From c55cd81b7d2052a01eeca1c35adc24960f904213 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Sun, 29 Dec 2024 15:11:17 +0000 Subject: [PATCH 01/35] Update version to 2.0.2 --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index 60453e69..b02d37b0 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -v1.0.0 \ No newline at end of file +v2.0.2 \ No newline at end of file From 46aecd46deee696317ad04344384d77c5d24be04 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Sun, 29 Dec 2024 15:17:24 +0000 Subject: [PATCH 02/35] Reference package from mrfelton repo --- .github/workflows/main.yml | 2 +- action.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fce5977b..f5c31814 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -103,7 +103,7 @@ jobs: # Backup original file cp action.yml action.yml.bak # Replace image path for local testing - sed -i 's|docker://ghcr.io/ln-zap/find-code-references-in-pull-request:latest|docker://localhost:5001/actions/find-code-references-in-pull-request:latest|' action.yml + sed -i 's|docker://ghcr.io/mrfelton/find-code-references-in-pull-request:latest|docker://localhost:5001/actions/find-code-references-in-pull-request:latest|' action.yml - name: Find LaunchDarkly feature flags in diff uses: ./ # Uses an action in the root directory id: find-flags diff --git a/action.yml b/action.yml index 1691e67e..c1198e8c 100644 --- a/action.yml +++ b/action.yml @@ -3,7 +3,7 @@ name: 'LaunchDarkly Code References in Pull Request' description: 'Find references to feature flags in your pull request' runs: using: 'docker' - image: 'docker://ghcr.io/ln-zap/find-code-references-in-pull-request:latest' + image: 'docker://ghcr.io/mrfelton/find-code-references-in-pull-request:latest' env: LD_PROJ_KEY: ${{ inputs.project-key }} LD_ACCESS_TOKEN: ${{ inputs.access-token }} From d218703dc64cf9779eb410949900b2ed52951727 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:38:25 -0800 Subject: [PATCH 03/35] chore(deps): bump golang.org/x/oauth2 from 0.24.0 to 0.25.0 (#141) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.24.0 to 0.25.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.24.0&new-version=0.25.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- vendor/golang.org/x/oauth2/oauth2.go | 2 +- vendor/modules.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 8d50c95d..42c7f07a 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 - golang.org/x/oauth2 v0.24.0 + golang.org/x/oauth2 v0.25.0 ) require ( diff --git a/go.sum b/go.sum index dae53e77..0624e2f5 100644 --- a/go.sum +++ b/go.sum @@ -316,8 +316,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 09f6a49b..74f052aa 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -56,7 +56,7 @@ type Config struct { // the OAuth flow, after the resource owner's URLs. RedirectURL string - // Scope specifies optional requested permissions. + // Scopes specifies optional requested permissions. Scopes []string // authStyleCache caches which auth style to use when Endpoint.AuthStyle is diff --git a/vendor/modules.txt b/vendor/modules.txt index d185a383..ac6ea55d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -210,7 +210,7 @@ golang.org/x/exp/slices golang.org/x/exp/slog golang.org/x/exp/slog/internal golang.org/x/exp/slog/internal/buffer -# golang.org/x/oauth2 v0.24.0 +# golang.org/x/oauth2 v0.25.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/internal From 545911ab4a664bbc4f9da4b8eda9ba6d599bd0b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 15 Jan 2025 14:47:05 +0100 Subject: [PATCH 04/35] bump go-github to current v68 (#145) --- .pre-commit-config.yaml | 9 +- .secrets.example.env | 1 + CHANGELOG.md | 6 + DEVELOPMENT.md | 3 +- comments/comments.go | 3 +- config/config.go | 3 +- go.mod | 9 +- go.sum | 6 +- internal/ldclient/flag_links.go | 3 +- internal/version/version.go | 2 +- main.go | 2 +- testdata/act/pull-request.json | 2 +- utils.go | 2 +- vendor/github.com/google/go-github/AUTHORS | 174 - .../google/go-github/github/activity.go | 69 - .../go-github/github/activity_events.go | 328 - .../google/go-github/github/apps.go | 223 - .../go-github/github/apps_installation.go | 101 - .../go-github/github/apps_marketplace.go | 168 - .../google/go-github/github/event_types.go | 786 - .../google/go-github/github/git_refs.go | 218 - .../go-github/github/github-accessors.go | 11861 ------- .../google/go-github/github/github.go | 994 - .../google/go-github/github/messages.go | 247 - .../google/go-github/github/misc.go | 257 - .../google/go-github/github/orgs.go | 197 - .../google/go-github/github/orgs_projects.go | 60 - .../google/go-github/github/projects.go | 448 - .../google/go-github/github/pulls.go | 383 - .../google/go-github/github/reactions.go | 274 - .../google/go-github/github/repos.go | 1082 - .../google/go-github/github/repos_contents.go | 266 - .../google/go-github/github/repos_hooks.go | 200 - .../google/go-github/github/repos_merging.go | 38 - .../google/go-github/github/repos_pages.go | 143 - .../google/go-github/github/repos_projects.go | 69 - .../google/go-github/github/teams.go | 357 - .../github/teams_discussion_comments.go | 154 - .../go-github/github/teams_discussions.go | 159 - .../google/go-github/github/teams_members.go | 174 - .../google/go-github/github/users_emails.go | 71 - .../github.com/google/go-github/v68/AUTHORS | 548 + .../google/go-github/{ => v68}/LICENSE | 0 .../google/go-github/v68/github/actions.go | 12 + .../go-github/v68/github/actions_artifacts.go | 177 + .../go-github/v68/github/actions_cache.go | 249 + .../go-github/v68/github/actions_oidc.go | 81 + .../github/actions_permissions_enterprise.go | 258 + .../v68/github/actions_permissions_orgs.go | 271 + .../v68/github/actions_required_workflows.go | 267 + .../v68/github/actions_runner_groups.go | 337 + .../go-github/v68/github/actions_runners.go | 377 + .../go-github/v68/github/actions_secrets.go | 407 + .../go-github/v68/github/actions_variables.go | 341 + .../v68/github/actions_workflow_jobs.go | 165 + .../v68/github/actions_workflow_runs.go | 475 + .../go-github/v68/github/actions_workflows.go | 237 + .../google/go-github/v68/github/activity.go | 77 + .../go-github/v68/github/activity_events.go | 235 + .../github/activity_notifications.go | 75 +- .../{ => v68}/github/activity_star.go | 39 +- .../{ => v68}/github/activity_watching.go | 30 +- .../go-github/{ => v68}/github/admin.go | 28 +- .../google/go-github/v68/github/admin_orgs.go | 95 + .../go-github/{ => v68}/github/admin_stats.go | 11 +- .../go-github/v68/github/admin_users.go | 137 + .../google/go-github/v68/github/apps.go | 495 + .../google/go-github/v68/github/apps_hooks.go | 52 + .../v68/github/apps_hooks_deliveries.go | 78 + .../go-github/v68/github/apps_installation.go | 138 + .../go-github/v68/github/apps_manifest.go | 51 + .../go-github/v68/github/apps_marketplace.go | 207 + .../go-github/v68/github/attestations.go | 27 + .../{ => v68}/github/authorizations.go | 254 +- .../google/go-github/v68/github/billing.go | 218 + .../go-github/{ => v68}/github/checks.go | 194 +- .../go-github/v68/github/code_scanning.go | 664 + .../go-github/v68/github/codesofconduct.go | 87 + .../google/go-github/v68/github/codespaces.go | 266 + .../v68/github/codespaces_secrets.go | 451 + .../google/go-github/v68/github/copilot.go | 570 + .../google/go-github/v68/github/dependabot.go | 12 + .../go-github/v68/github/dependabot_alerts.go | 176 + .../v68/github/dependabot_secrets.go | 289 + .../go-github/v68/github/dependency_graph.go | 82 + .../v68/github/dependency_graph_snapshots.go | 113 + .../google/go-github/{ => v68}/github/doc.go | 81 +- .../google/go-github/v68/github/emojis.go | 40 + .../google/go-github/v68/github/enterprise.go | 12 + .../enterprise_actions_runner_groups.go | 336 + .../v68/github/enterprise_actions_runners.go | 139 + .../v68/github/enterprise_audit_log.go | 37 + .../enterprise_code_security_and_analysis.go | 85 + .../v68/github/enterprise_properties.go | 121 + .../google/go-github/v68/github/event.go | 54 + .../go-github/v68/github/event_types.go | 1928 ++ .../go-github/{ => v68}/github/gists.go | 91 +- .../{ => v68}/github/gists_comments.go | 27 +- .../google/go-github/{ => v68}/github/git.go | 2 +- .../go-github/{ => v68}/github/git_blobs.go | 31 +- .../go-github/{ => v68}/github/git_commits.go | 114 +- .../google/go-github/v68/github/git_refs.go | 185 + .../go-github/{ => v68}/github/git_tags.go | 25 +- .../go-github/{ => v68}/github/git_trees.go | 83 +- .../go-github/v68/github/github-accessors.go | 26951 ++++++++++++++++ .../google/go-github/v68/github/github.go | 1618 + .../go-github/{ => v68}/github/gitignore.go | 14 +- .../go-github/v68/github/interactions.go | 28 + .../go-github/v68/github/interactions_orgs.go | 86 + .../v68/github/interactions_repos.go | 86 + .../go-github/v68/github/issue_import.go | 154 + .../go-github/{ => v68}/github/issues.go | 192 +- .../{ => v68}/github/issues_assignees.go | 34 +- .../{ => v68}/github/issues_comments.go | 37 +- .../{ => v68}/github/issues_events.go | 65 +- .../{ => v68}/github/issues_labels.go | 88 +- .../{ => v68}/github/issues_milestones.go | 33 +- .../{ => v68}/github/issues_timeline.go | 69 +- .../go-github/{ => v68}/github/licenses.go | 10 +- .../google/go-github/v68/github/markdown.go | 69 + .../google/go-github/v68/github/messages.go | 356 + .../google/go-github/v68/github/meta.go | 184 + .../go-github/{ => v68}/github/migrations.go | 40 +- .../github/migrations_source_import.go | 64 +- .../{ => v68}/github/migrations_user.go | 40 +- .../google/go-github/v68/github/orgs.go | 318 + .../v68/github/orgs_actions_allowed.go | 34 + .../v68/github/orgs_actions_permissions.go | 34 + .../go-github/v68/github/orgs_attestations.go | 40 + .../go-github/v68/github/orgs_audit_log.go | 142 + .../orgs_codesecurity_configurations.go | 284 + .../github/orgs_credential_authorizations.go | 109 + .../github/orgs_custom_repository_roles.go | 154 + .../go-github/{ => v68}/github/orgs_hooks.go | 59 +- .../v68/github/orgs_hooks_configuration.go | 53 + .../v68/github/orgs_hooks_deliveries.go | 79 + .../{ => v68}/github/orgs_members.go | 136 +- .../v68/github/orgs_organization_roles.go | 295 + .../github/orgs_outside_collaborators.go | 16 +- .../go-github/v68/github/orgs_packages.go | 180 + .../v68/github/orgs_personal_access_tokens.go | 167 + .../go-github/v68/github/orgs_properties.go | 243 + .../google/go-github/v68/github/orgs_rules.go | 115 + .../v68/github/orgs_security_managers.go | 63 + .../{ => v68}/github/orgs_users_blocking.go | 20 +- .../google/go-github/v68/github/packages.go | 143 + .../google/go-github/v68/github/pulls.go | 516 + .../{ => v68}/github/pulls_comments.go | 63 +- .../{ => v68}/github/pulls_reviewers.go | 39 +- .../{ => v68}/github/pulls_reviews.go | 161 +- .../go-github/v68/github/pulls_threads.go | 17 + .../google/go-github/v68/github/rate_limit.go | 125 + .../google/go-github/v68/github/reactions.go | 570 + .../google/go-github/v68/github/repos.go | 2428 ++ .../v68/github/repos_actions_access.go | 59 + .../v68/github/repos_actions_allowed.go | 53 + .../v68/github/repos_actions_permissions.go | 118 + .../v68/github/repos_attestations.go | 39 + .../go-github/v68/github/repos_autolinks.go | 112 + .../go-github/v68/github/repos_codeowners.go | 61 + .../{ => v68}/github/repos_collaborators.go | 68 +- .../{ => v68}/github/repos_comments.go | 38 +- .../{ => v68}/github/repos_commits.go | 172 +- .../github/repos_community_health.go | 20 +- .../go-github/v68/github/repos_contents.go | 367 + .../repos_deployment_branch_policies.go | 135 + .../repos_deployment_protection_rules.go | 148 + .../{ => v68}/github/repos_deployments.go | 110 +- .../v68/github/repos_environments.go | 252 + .../go-github/{ => v68}/github/repos_forks.go | 36 +- .../go-github/v68/github/repos_hooks.go | 271 + .../v68/github/repos_hooks_configuration.go | 68 + .../v68/github/repos_hooks_deliveries.go | 142 + .../{ => v68}/github/repos_invitations.go | 26 +- .../go-github/{ => v68}/github/repos_keys.go | 40 +- .../google/go-github/v68/github/repos_lfs.go | 53 + .../go-github/v68/github/repos_merging.go | 76 + .../go-github/v68/github/repos_pages.go | 324 + .../github/repos_prereceive_hooks.go | 20 +- .../go-github/v68/github/repos_properties.go | 60 + .../{ => v68}/github/repos_releases.go | 229 +- .../go-github/v68/github/repos_rules.go | 995 + .../go-github/{ => v68}/github/repos_stats.go | 46 +- .../{ => v68}/github/repos_statuses.go | 47 +- .../google/go-github/v68/github/repos_tags.go | 85 + .../{ => v68}/github/repos_traffic.go | 24 +- .../google/go-github/v68/github/scim.go | 219 + .../go-github/{ => v68}/github/search.go | 226 +- .../go-github/v68/github/secret_scanning.go | 261 + .../v68/github/security_advisories.go | 279 + .../go-github/{ => v68}/github/strings.go | 27 +- .../google/go-github/v68/github/teams.go | 1100 + .../v68/github/teams_discussion_comments.go | 262 + .../go-github/v68/github/teams_discussions.go | 267 + .../go-github/v68/github/teams_members.go | 263 + .../go-github/{ => v68}/github/timestamp.go | 13 +- .../go-github/{ => v68}/github/users.go | 140 +- .../{ => v68}/github/users_administration.go | 25 +- .../v68/github/users_attestations.go | 40 + .../{ => v68}/github/users_blocking.go | 20 +- .../go-github/v68/github/users_emails.go | 105 + .../{ => v68}/github/users_followers.go | 34 +- .../{ => v68}/github/users_gpg_keys.go | 62 +- .../go-github/{ => v68}/github/users_keys.go | 36 +- .../go-github/v68/github/users_packages.go | 235 + .../v68/github/users_ssh_signing_keys.go | 117 + .../{ => v68}/github/with_appengine.go | 2 +- .../{ => v68}/github/without_appengine.go | 2 +- .../google/go-querystring/query/encode.go | 97 +- vendor/modules.txt | 10 +- 210 files changed, 56441 insertions(+), 20812 deletions(-) delete mode 100644 vendor/github.com/google/go-github/AUTHORS delete mode 100644 vendor/github.com/google/go-github/github/activity.go delete mode 100644 vendor/github.com/google/go-github/github/activity_events.go delete mode 100644 vendor/github.com/google/go-github/github/apps.go delete mode 100644 vendor/github.com/google/go-github/github/apps_installation.go delete mode 100644 vendor/github.com/google/go-github/github/apps_marketplace.go delete mode 100644 vendor/github.com/google/go-github/github/event_types.go delete mode 100644 vendor/github.com/google/go-github/github/git_refs.go delete mode 100644 vendor/github.com/google/go-github/github/github-accessors.go delete mode 100644 vendor/github.com/google/go-github/github/github.go delete mode 100644 vendor/github.com/google/go-github/github/messages.go delete mode 100644 vendor/github.com/google/go-github/github/misc.go delete mode 100644 vendor/github.com/google/go-github/github/orgs.go delete mode 100644 vendor/github.com/google/go-github/github/orgs_projects.go delete mode 100644 vendor/github.com/google/go-github/github/projects.go delete mode 100644 vendor/github.com/google/go-github/github/pulls.go delete mode 100644 vendor/github.com/google/go-github/github/reactions.go delete mode 100644 vendor/github.com/google/go-github/github/repos.go delete mode 100644 vendor/github.com/google/go-github/github/repos_contents.go delete mode 100644 vendor/github.com/google/go-github/github/repos_hooks.go delete mode 100644 vendor/github.com/google/go-github/github/repos_merging.go delete mode 100644 vendor/github.com/google/go-github/github/repos_pages.go delete mode 100644 vendor/github.com/google/go-github/github/repos_projects.go delete mode 100644 vendor/github.com/google/go-github/github/teams.go delete mode 100644 vendor/github.com/google/go-github/github/teams_discussion_comments.go delete mode 100644 vendor/github.com/google/go-github/github/teams_discussions.go delete mode 100644 vendor/github.com/google/go-github/github/teams_members.go delete mode 100644 vendor/github.com/google/go-github/github/users_emails.go create mode 100644 vendor/github.com/google/go-github/v68/AUTHORS rename vendor/github.com/google/go-github/{ => v68}/LICENSE (100%) create mode 100644 vendor/github.com/google/go-github/v68/github/actions.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_artifacts.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_cache.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_oidc.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_required_workflows.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_runner_groups.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_runners.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_variables.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go create mode 100644 vendor/github.com/google/go-github/v68/github/actions_workflows.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity.go create mode 100644 vendor/github.com/google/go-github/v68/github/activity_events.go rename vendor/github.com/google/go-github/{ => v68}/github/activity_notifications.go (66%) rename vendor/github.com/google/go-github/{ => v68}/github/activity_star.go (70%) rename vendor/github.com/google/go-github/{ => v68}/github/activity_watching.go (77%) rename vendor/github.com/google/go-github/{ => v68}/github/admin.go (74%) create mode 100644 vendor/github.com/google/go-github/v68/github/admin_orgs.go rename vendor/github.com/google/go-github/{ => v68}/github/admin_stats.go (93%) create mode 100644 vendor/github.com/google/go-github/v68/github/admin_users.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_installation.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_manifest.go create mode 100644 vendor/github.com/google/go-github/v68/github/apps_marketplace.go create mode 100644 vendor/github.com/google/go-github/v68/github/attestations.go rename vendor/github.com/google/go-github/{ => v68}/github/authorizations.go (53%) create mode 100644 vendor/github.com/google/go-github/v68/github/billing.go rename vendor/github.com/google/go-github/{ => v68}/github/checks.go (56%) create mode 100644 vendor/github.com/google/go-github/v68/github/code_scanning.go create mode 100644 vendor/github.com/google/go-github/v68/github/codesofconduct.go create mode 100644 vendor/github.com/google/go-github/v68/github/codespaces.go create mode 100644 vendor/github.com/google/go-github/v68/github/codespaces_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/copilot.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot_alerts.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependabot_secrets.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependency_graph.go create mode 100644 vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go rename vendor/github.com/google/go-github/{ => v68}/github/doc.go (76%) create mode 100644 vendor/github.com/google/go-github/v68/github/emojis.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go create mode 100644 vendor/github.com/google/go-github/v68/github/enterprise_properties.go create mode 100644 vendor/github.com/google/go-github/v68/github/event.go create mode 100644 vendor/github.com/google/go-github/v68/github/event_types.go rename vendor/github.com/google/go-github/{ => v68}/github/gists.go (74%) rename vendor/github.com/google/go-github/{ => v68}/github/gists_comments.go (75%) rename vendor/github.com/google/go-github/{ => v68}/github/git.go (84%) rename vendor/github.com/google/go-github/{ => v68}/github/git_blobs.go (74%) rename vendor/github.com/google/go-github/{ => v68}/github/git_commits.go (52%) create mode 100644 vendor/github.com/google/go-github/v68/github/git_refs.go rename vendor/github.com/google/go-github/{ => v68}/github/git_tags.go (83%) rename vendor/github.com/google/go-github/{ => v68}/github/git_trees.go (50%) create mode 100644 vendor/github.com/google/go-github/v68/github/github-accessors.go create mode 100644 vendor/github.com/google/go-github/v68/github/github.go rename vendor/github.com/google/go-github/{ => v68}/github/gitignore.go (70%) create mode 100644 vendor/github.com/google/go-github/v68/github/interactions.go create mode 100644 vendor/github.com/google/go-github/v68/github/interactions_orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/interactions_repos.go create mode 100644 vendor/github.com/google/go-github/v68/github/issue_import.go rename vendor/github.com/google/go-github/{ => v68}/github/issues.go (58%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_assignees.go (72%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_comments.go (75%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_events.go (59%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_labels.go (66%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_milestones.go (77%) rename vendor/github.com/google/go-github/{ => v68}/github/issues_timeline.go (64%) rename vendor/github.com/google/go-github/{ => v68}/github/licenses.go (89%) create mode 100644 vendor/github.com/google/go-github/v68/github/markdown.go create mode 100644 vendor/github.com/google/go-github/v68/github/messages.go create mode 100644 vendor/github.com/google/go-github/v68/github/meta.go rename vendor/github.com/google/go-github/{ => v68}/github/migrations.go (82%) rename vendor/github.com/google/go-github/{ => v68}/github/migrations_source_import.go (84%) rename vendor/github.com/google/go-github/{ => v68}/github/migrations_user.go (82%) create mode 100644 vendor/github.com/google/go-github/v68/github/orgs.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_audit_log.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go rename vendor/github.com/google/go-github/{ => v68}/github/orgs_hooks.go (63%) create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go rename vendor/github.com/google/go-github/{ => v68}/github/orgs_members.go (69%) create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go rename vendor/github.com/google/go-github/{ => v68}/github/orgs_outside_collaborators.go (77%) create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_properties.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_rules.go create mode 100644 vendor/github.com/google/go-github/v68/github/orgs_security_managers.go rename vendor/github.com/google/go-github/{ => v68}/github/orgs_users_blocking.go (76%) create mode 100644 vendor/github.com/google/go-github/v68/github/packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/pulls.go rename vendor/github.com/google/go-github/{ => v68}/github/pulls_comments.go (62%) rename vendor/github.com/google/go-github/{ => v68}/github/pulls_reviewers.go (56%) rename vendor/github.com/google/go-github/{ => v68}/github/pulls_reviews.go (51%) create mode 100644 vendor/github.com/google/go-github/v68/github/pulls_threads.go create mode 100644 vendor/github.com/google/go-github/v68/github/rate_limit.go create mode 100644 vendor/github.com/google/go-github/v68/github/reactions.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_access.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_attestations.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_autolinks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_codeowners.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_collaborators.go (62%) rename vendor/github.com/google/go-github/{ => v68}/github/repos_comments.go (75%) rename vendor/github.com/google/go-github/{ => v68}/github/repos_commits.go (51%) rename vendor/github.com/google/go-github/{ => v68}/github/repos_community_health.go (69%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_contents.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_deployments.go (56%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_environments.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_forks.go (69%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_invitations.go (75%) rename vendor/github.com/google/go-github/{ => v68}/github/repos_keys.go (68%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_lfs.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_merging.go create mode 100644 vendor/github.com/google/go-github/v68/github/repos_pages.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_prereceive_hooks.go (73%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_properties.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_releases.go (50%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_rules.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_stats.go (85%) rename vendor/github.com/google/go-github/{ => v68}/github/repos_statuses.go (69%) create mode 100644 vendor/github.com/google/go-github/v68/github/repos_tags.go rename vendor/github.com/google/go-github/{ => v68}/github/repos_traffic.go (82%) create mode 100644 vendor/github.com/google/go-github/v68/github/scim.go rename vendor/github.com/google/go-github/{ => v68}/github/search.go (50%) create mode 100644 vendor/github.com/google/go-github/v68/github/secret_scanning.go create mode 100644 vendor/github.com/google/go-github/v68/github/security_advisories.go rename vendor/github.com/google/go-github/{ => v68}/github/strings.go (80%) create mode 100644 vendor/github.com/google/go-github/v68/github/teams.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_discussions.go create mode 100644 vendor/github.com/google/go-github/v68/github/teams_members.go rename vendor/github.com/google/go-github/{ => v68}/github/timestamp.go (80%) rename vendor/github.com/google/go-github/{ => v68}/github/users.go (54%) rename vendor/github.com/google/go-github/{ => v68}/github/users_administration.go (58%) create mode 100644 vendor/github.com/google/go-github/v68/github/users_attestations.go rename vendor/github.com/google/go-github/{ => v68}/github/users_blocking.go (77%) create mode 100644 vendor/github.com/google/go-github/v68/github/users_emails.go rename vendor/github.com/google/go-github/{ => v68}/github/users_followers.go (66%) rename vendor/github.com/google/go-github/{ => v68}/github/users_gpg_keys.go (61%) rename vendor/github.com/google/go-github/{ => v68}/github/users_keys.go (61%) create mode 100644 vendor/github.com/google/go-github/v68/github/users_packages.go create mode 100644 vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go rename vendor/github.com/google/go-github/{ => v68}/github/with_appengine.go (95%) rename vendor/github.com/google/go-github/{ => v68}/github/without_appengine.go (94%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bb835676..0b0e592a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,10 +10,11 @@ repos: language: golang pass_filenames: false -- repo: https://github.com/dnephin/pre-commit-golang - rev: v0.3.3 - hooks: - - id: go-unit-tests +# Run as part of GHA workflow +# - repo: https://github.com/dnephin/pre-commit-golang +# rev: v0.3.3 +# hooks: +# - id: go-unit-tests - repo: local hooks: diff --git a/.secrets.example.env b/.secrets.example.env index 92f176fc..091d8ea1 100644 --- a/.secrets.example.env +++ b/.secrets.example.env @@ -1,4 +1,5 @@ # Save as .secrets for testing with nektos/act LD_ACCESS_TOKEN= # LaunchDarkly access token +LD_ACCESS_TOKEN_WRITER= # LaunchDarkly access token (both are used for local runs with act) GITHUB_TOKEN= # GitHub PAT with repo access diff --git a/CHANGELOG.md b/CHANGELOG.md index 63e475e9..1de9b011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ### Fixed +## 2.0.2 + +### Changed + +- Update golang version + ## 2.0.1 ### Changed diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 1d2fc8ff..b3cd4a1a 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -9,9 +9,10 @@ ## Testing locally Use [nektos/act](https://github.com/nektos/act) to run actions locally. +NB: You'll want to use the `large` runner in order to have access to all commands needed for testing. ``` -act +act -e testdata/act/pull-request.json ``` _Read more: [Example commands](https://github.com/nektos/act#example-commands)_ diff --git a/comments/comments.go b/comments/comments.go index 78abb028..015d8276 100644 --- a/comments/comments.go +++ b/comments/comments.go @@ -14,7 +14,8 @@ import ( sprig "github.com/Masterminds/sprig/v3" - "github.com/google/go-github/github" + "github.com/google/go-github/v68/github" + ldapi "github.com/launchdarkly/api-client-go/v15" lcr "github.com/launchdarkly/find-code-references-in-pull-request/config" gha "github.com/launchdarkly/find-code-references-in-pull-request/internal/github_actions" diff --git a/config/config.go b/config/config.go index ceeeaf11..20c554a0 100644 --- a/config/config.go +++ b/config/config.go @@ -7,7 +7,8 @@ import ( "strconv" "strings" - "github.com/google/go-github/github" + "github.com/google/go-github/v68/github" + "golang.org/x/oauth2" gha "github.com/launchdarkly/find-code-references-in-pull-request/internal/github_actions" diff --git a/go.mod b/go.mod index 42c7f07a..07c41dfb 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/launchdarkly/find-code-references-in-pull-request -go 1.22 -toolchain go1.22.5 +go 1.22.0 + +toolchain go1.22.7 require ( github.com/Masterminds/sprig/v3 v3.3.0 - github.com/google/go-github v17.0.0+incompatible - github.com/google/go-querystring v1.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.19.0 @@ -15,6 +15,7 @@ require ( ) require ( + github.com/google/go-github/v68 v68.0.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/kyoh86/richgo v0.3.12 github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0 diff --git a/go.sum b/go.sum index 0624e2f5..f0123cff 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,10 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= +github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= diff --git a/internal/ldclient/flag_links.go b/internal/ldclient/flag_links.go index db3be444..8c9fc584 100644 --- a/internal/ldclient/flag_links.go +++ b/internal/ldclient/flag_links.go @@ -9,7 +9,8 @@ import ( "strconv" "strings" - "github.com/google/go-github/github" + "github.com/google/go-github/v68/github" + ldapi "github.com/launchdarkly/api-client-go/v15" lcr "github.com/launchdarkly/find-code-references-in-pull-request/config" gha "github.com/launchdarkly/find-code-references-in-pull-request/internal/github_actions" diff --git a/internal/version/version.go b/internal/version/version.go index 6577dd9b..eacf5007 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.0.1" +const Version = "2.0.2" diff --git a/main.go b/main.go index 3001092d..077eddf7 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( "github.com/pkg/errors" - "github.com/google/go-github/github" + "github.com/google/go-github/v68/github" ghc "github.com/launchdarkly/find-code-references-in-pull-request/comments" lcr "github.com/launchdarkly/find-code-references-in-pull-request/config" ldiff "github.com/launchdarkly/find-code-references-in-pull-request/diff" diff --git a/testdata/act/pull-request.json b/testdata/act/pull-request.json index 3dce926e..9485309d 100644 --- a/testdata/act/pull-request.json +++ b/testdata/act/pull-request.json @@ -1,6 +1,6 @@ { "pull_request": { - "number": 20, + "number": 23, "head": { "ref": "sample-head-ref" }, diff --git a/utils.go b/utils.go index 827ef6f3..016d16ca 100644 --- a/utils.go +++ b/utils.go @@ -5,7 +5,7 @@ import ( "io" "os" - "github.com/google/go-github/github" + "github.com/google/go-github/v68/github" ) // pulled from ld-find-code-refs github action diff --git a/vendor/github.com/google/go-github/AUTHORS b/vendor/github.com/google/go-github/AUTHORS deleted file mode 100644 index 56622a4c..00000000 --- a/vendor/github.com/google/go-github/AUTHORS +++ /dev/null @@ -1,174 +0,0 @@ -# This is the official list of go-github authors for copyright purposes. -# -# This does not necessarily list everyone who has contributed code, since in -# some cases, their employer may be the copyright holder. To see the full list -# of contributors, see the revision history in source control or -# https://github.com/google/go-github/graphs/contributors. -# -# Authors who wish to be recognized in this file should add themselves (or -# their employer, as appropriate). - -178inaba -Abhinav Gupta -Ahmed Hagy -Ainsley Chong -Akeda Bagus -Alec Thomas -Aleks Clark -Alex Bramley -Alexander Harkness -Allen Sun -Amey Sakhadeo -Andreas Garnæs -Andrew Ryabchun -Andy Hume -Andy Lindeman -Anshuman Bhartiya -Antoine Pelisse -Anubha Kushwaha -Aravind -Arıl Bozoluk -Austin Dizzy -Beshr Kayali -Beyang Liu -Billy Lynch -Björn Häuser -Brad Harris -Bradley Falzon -Brian Egizi -Bryan Boreham -Cami Diez -Carlos Alexandro Becker -chandresh-pancholi -Charles Fenwick Elliott -Charlie Yan -Chris King -Chris Roche -Chris Schaefer -Christoph Sassenberg -Colin Misare -Craig Peterson -Cristian Maglie -Daehyeok Mun -Daniel Leavitt -Dave Du Cros -Dave Henderson -David Deng -Dennis Webb -Diego Lapiduz -Dmitri Shuralyov -dmnlk -Don Petersen -Doug Turner -Drew Fradette -Eli Uriegas -Elliott Beach -erwinvaneyk -Fabrice -Filippo Valsorda -Florian Forster -Francesc Gil -Francis -Fredrik Jönsson -Garrett Squire -Georgy Buranov -Gnahz -Google Inc. -griffin_stewie -Guz Alexander -Hanno Hecker -Hari haran -haya14busa -Huy Tr -huydx -i2bskn -Isao Jonas -isqua -Jameel Haffejee -Jan Kosecki -Jeremy Morris -Jihoon Chung -Jimmi Dyson -Joe Tsai -John Barton -John Engelman -jpbelanger-mtl -Juan Basso -Julien Rostand -Justin Abrahms -jzhoucliqr -Katrina Owen -Keita Urashima -Kevin Burke -Konrad Malawski -Kookheon Kwon -Krzysztof Kowalczyk -Kshitij Saraogi -kyokomi -Lucas Alcantara -Luke Evers -Luke Kysow -Luke Roberts -Luke Young -Maksim Zhylinski -Martin-Louis Bright -Mat Geist -Matt Brender -Matt Landis -Maxime Bury -Michael Tiller -Michał Glapa -Nathan VanBenschoten -Neil O'Toole -Nick Miyake -Nick Spragg -Nikhita Raghunath -Noah Zoschke -ns-cweber -Ondřej Kupka -Panagiotis Moustafellos -Parker Moore -Pavel Shtanko -Petr Shevtsov -Pierre Carrier -Piotr Zurek -Quinn Slack -Rackspace US, Inc. -Rajendra arora -RaviTeja Pothana -rc1140 -Red Hat, Inc. -Rob Figueiredo -Ronak Jain -Ruben Vereecken -Ryan Lower -Sahil Dua -saisi -Sam Minnée -Sander van Harmelen -Sanket Payghan -Sarasa Kisaragi -Sean Wang -Sebastian Mandrean -Sebastian Mæland Pedersen -Sevki -Shawn Catanzarite -Shawn Smith -sona-tar -SoundCloud, Ltd. -Stian Eikeland -Thomas Bruyelle -Timothée Peignier -Trey Tacon -ttacon -Varadarajan Aravamudhan -Victor Castell -Victor Vrantchan -Vlad Ungureanu -Will Maier -William Bailey -Yann Malet -Yannick Utard -Yicheng Qin -Yumikiyo Osanai -Zach Latta diff --git a/vendor/github.com/google/go-github/github/activity.go b/vendor/github.com/google/go-github/github/activity.go deleted file mode 100644 index d6c992c7..00000000 --- a/vendor/github.com/google/go-github/github/activity.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import "context" - -// ActivityService handles communication with the activity related -// methods of the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/activity/ -type ActivityService service - -// FeedLink represents a link to a related resource. -type FeedLink struct { - HRef *string `json:"href,omitempty"` - Type *string `json:"type,omitempty"` -} - -// Feeds represents timeline resources in Atom format. -type Feeds struct { - TimelineURL *string `json:"timeline_url,omitempty"` - UserURL *string `json:"user_url,omitempty"` - CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` - CurrentUserURL *string `json:"current_user_url,omitempty"` - CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` - CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` - CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` - Links *struct { - Timeline *FeedLink `json:"timeline,omitempty"` - User *FeedLink `json:"user,omitempty"` - CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` - CurrentUser *FeedLink `json:"current_user,omitempty"` - CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` - CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` - CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` - } `json:"_links,omitempty"` -} - -// ListFeeds lists all the feeds available to the authenticated user. -// -// GitHub provides several timeline resources in Atom format: -// Timeline: The GitHub global public timeline -// User: The public timeline for any user, using URI template -// Current user public: The public timeline for the authenticated user -// Current user: The private timeline for the authenticated user -// Current user actor: The private timeline for activity created by the -// authenticated user -// Current user organizations: The private timeline for the organizations -// the authenticated user is a member of. -// -// Note: Private feeds are only returned when authenticating via Basic Auth -// since current feed URIs use the older, non revocable auth tokens. -func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { - req, err := s.client.NewRequest("GET", "feeds", nil) - if err != nil { - return nil, nil, err - } - - f := &Feeds{} - resp, err := s.client.Do(ctx, req, f) - if err != nil { - return nil, resp, err - } - - return f, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/activity_events.go b/vendor/github.com/google/go-github/github/activity_events.go deleted file mode 100644 index a919b11c..00000000 --- a/vendor/github.com/google/go-github/github/activity_events.go +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "encoding/json" - "fmt" - "time" -) - -// Event represents a GitHub event. -type Event struct { - Type *string `json:"type,omitempty"` - Public *bool `json:"public,omitempty"` - RawPayload *json.RawMessage `json:"payload,omitempty"` - Repo *Repository `json:"repo,omitempty"` - Actor *User `json:"actor,omitempty"` - Org *Organization `json:"org,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - ID *string `json:"id,omitempty"` -} - -func (e Event) String() string { - return Stringify(e) -} - -// ParsePayload parses the event payload. For recognized event types, -// a value of the corresponding struct type will be returned. -func (e *Event) ParsePayload() (payload interface{}, err error) { - switch *e.Type { - case "CheckRunEvent": - payload = &CheckRunEvent{} - case "CheckSuiteEvent": - payload = &CheckSuiteEvent{} - case "CommitCommentEvent": - payload = &CommitCommentEvent{} - case "CreateEvent": - payload = &CreateEvent{} - case "DeleteEvent": - payload = &DeleteEvent{} - case "DeploymentEvent": - payload = &DeploymentEvent{} - case "DeploymentStatusEvent": - payload = &DeploymentStatusEvent{} - case "ForkEvent": - payload = &ForkEvent{} - case "GollumEvent": - payload = &GollumEvent{} - case "InstallationEvent": - payload = &InstallationEvent{} - case "InstallationRepositoriesEvent": - payload = &InstallationRepositoriesEvent{} - case "IssueCommentEvent": - payload = &IssueCommentEvent{} - case "IssuesEvent": - payload = &IssuesEvent{} - case "LabelEvent": - payload = &LabelEvent{} - case "MarketplacePurchaseEvent": - payload = &MarketplacePurchaseEvent{} - case "MemberEvent": - payload = &MemberEvent{} - case "MembershipEvent": - payload = &MembershipEvent{} - case "MilestoneEvent": - payload = &MilestoneEvent{} - case "OrganizationEvent": - payload = &OrganizationEvent{} - case "OrgBlockEvent": - payload = &OrgBlockEvent{} - case "PageBuildEvent": - payload = &PageBuildEvent{} - case "PingEvent": - payload = &PingEvent{} - case "ProjectEvent": - payload = &ProjectEvent{} - case "ProjectCardEvent": - payload = &ProjectCardEvent{} - case "ProjectColumnEvent": - payload = &ProjectColumnEvent{} - case "PublicEvent": - payload = &PublicEvent{} - case "PullRequestEvent": - payload = &PullRequestEvent{} - case "PullRequestReviewEvent": - payload = &PullRequestReviewEvent{} - case "PullRequestReviewCommentEvent": - payload = &PullRequestReviewCommentEvent{} - case "PushEvent": - payload = &PushEvent{} - case "ReleaseEvent": - payload = &ReleaseEvent{} - case "RepositoryEvent": - payload = &RepositoryEvent{} - case "StatusEvent": - payload = &StatusEvent{} - case "TeamEvent": - payload = &TeamEvent{} - case "TeamAddEvent": - payload = &TeamAddEvent{} - case "WatchEvent": - payload = &WatchEvent{} - } - err = json.Unmarshal(*e.RawPayload, &payload) - return payload, err -} - -// Payload returns the parsed event payload. For recognized event types, -// a value of the corresponding struct type will be returned. -// -// Deprecated: Use ParsePayload instead, which returns an error -// rather than panics if JSON unmarshaling raw payload fails. -func (e *Event) Payload() (payload interface{}) { - var err error - payload, err = e.ParsePayload() - if err != nil { - panic(err) - } - return payload -} - -// ListEvents drinks from the firehose of all public events across GitHub. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events -func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*Event, *Response, error) { - u, err := addOptions("events", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListRepositoryEvents lists events for a repository. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events -func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/events", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListIssueEventsForRepository lists issue events for a repository. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository -func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*IssueEvent - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListEventsForRepoNetwork lists public events for a network of repositories. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories -func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { - u := fmt.Sprintf("networks/%v/%v/events", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListEventsForOrganization lists public events for an organization. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization -func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opt *ListOptions) ([]*Event, *Response, error) { - u := fmt.Sprintf("orgs/%v/events", org) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is -// true, only public events will be returned. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user -func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { - var u string - if publicOnly { - u = fmt.Sprintf("users/%v/events/public", user) - } else { - u = fmt.Sprintf("users/%v/events", user) - } - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListEventsReceivedByUser lists the events received by a user. If publicOnly is -// true, only public events will be returned. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received -func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { - var u string - if publicOnly { - u = fmt.Sprintf("users/%v/received_events/public", user) - } else { - u = fmt.Sprintf("users/%v/received_events", user) - } - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} - -// ListUserEventsForOrganization provides the user’s organization dashboard. You -// must be authenticated as the user to view this. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization -func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opt *ListOptions) ([]*Event, *Response, error) { - u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var events []*Event - resp, err := s.client.Do(ctx, req, &events) - if err != nil { - return nil, resp, err - } - - return events, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/apps.go b/vendor/github.com/google/go-github/github/apps.go deleted file mode 100644 index e25de2c5..00000000 --- a/vendor/github.com/google/go-github/github/apps.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" - "time" -) - -// AppsService provides access to the installation related functions -// in the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/apps/ -type AppsService service - -// App represents a GitHub App. -type App struct { - ID *int64 `json:"id,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Owner *User `json:"owner,omitempty"` - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - ExternalURL *string `json:"external_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` -} - -// InstallationToken represents an installation token. -type InstallationToken struct { - Token *string `json:"token,omitempty"` - ExpiresAt *time.Time `json:"expires_at,omitempty"` -} - -// InstallationPermissions lists the permissions for metadata, contents, issues and single file for an installation. -type InstallationPermissions struct { - Metadata *string `json:"metadata,omitempty"` - Contents *string `json:"contents,omitempty"` - Issues *string `json:"issues,omitempty"` - SingleFile *string `json:"single_file,omitempty"` -} - -// Installation represents a GitHub Apps installation. -type Installation struct { - ID *int64 `json:"id,omitempty"` - AppID *int64 `json:"app_id,omitempty"` - TargetID *int64 `json:"target_id,omitempty"` - Account *User `json:"account,omitempty"` - AccessTokensURL *string `json:"access_tokens_url,omitempty"` - RepositoriesURL *string `json:"repositories_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - TargetType *string `json:"target_type,omitempty"` - SingleFileName *string `json:"single_file_name,omitempty"` - RepositorySelection *string `json:"repository_selection,omitempty"` - Events []string `json:"events,omitempty"` - Permissions *InstallationPermissions `json:"permissions,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` -} - -func (i Installation) String() string { - return Stringify(i) -} - -// Get a single GitHub App. Passing the empty string will get -// the authenticated GitHub App. -// -// Note: appSlug is just the URL-friendly name of your GitHub App. -// You can find this on the settings page for your GitHub App -// (e.g., https://github.com/settings/apps/:app_slug). -// -// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app -func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { - var u string - if appSlug != "" { - u = fmt.Sprintf("apps/%v", appSlug) - } else { - u = "app" - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - app := new(App) - resp, err := s.client.Do(ctx, req, app) - if err != nil { - return nil, resp, err - } - - return app, resp, nil -} - -// ListInstallations lists the installations that the current GitHub App has. -// -// GitHub API docs: https://developer.github.com/v3/apps/#find-installations -func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { - u, err := addOptions("app/installations", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - var i []*Installation - resp, err := s.client.Do(ctx, req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil -} - -// GetInstallation returns the specified installation. -// -// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation -func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { - return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id)) -} - -// ListUserInstallations lists installations that are accessible to the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user -func (s *AppsService) ListUserInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { - u, err := addOptions("user/installations", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - var i struct { - Installations []*Installation `json:"installations"` - } - resp, err := s.client.Do(ctx, req, &i) - if err != nil { - return nil, resp, err - } - - return i.Installations, resp, nil -} - -// CreateInstallationToken creates a new installation token. -// -// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token -func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*InstallationToken, *Response, error) { - u := fmt.Sprintf("installations/%v/access_tokens", id) - - req, err := s.client.NewRequest("POST", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - t := new(InstallationToken) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// FindOrganizationInstallation finds the organization's installation information. -// -// GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation -func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) { - return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org)) -} - -// FindRepositoryInstallation finds the repository's installation information. -// -// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation -func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) { - return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo)) -} - -// FindUserInstallation finds the user's installation information. -// -// GitHub API docs: https://developer.github.com/v3/apps/#find-repository-installation -func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) { - return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user)) -} - -func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) { - req, err := s.client.NewRequest("GET", url, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - i := new(Installation) - resp, err := s.client.Do(ctx, req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/apps_installation.go b/vendor/github.com/google/go-github/github/apps_installation.go deleted file mode 100644 index ccfecb8d..00000000 --- a/vendor/github.com/google/go-github/github/apps_installation.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// ListRepos lists the repositories that are accessible to the authenticated installation. -// -// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories -func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repository, *Response, error) { - u, err := addOptions("installation/repositories", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - var r struct { - Repositories []*Repository `json:"repositories"` - } - resp, err := s.client.Do(ctx, req, &r) - if err != nil { - return nil, resp, err - } - - return r.Repositories, resp, nil -} - -// ListUserRepos lists repositories that are accessible -// to the authenticated user for an installation. -// -// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation -func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOptions) ([]*Repository, *Response, error) { - u := fmt.Sprintf("user/installations/%v/repositories", id) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeIntegrationPreview) - - var r struct { - Repositories []*Repository `json:"repositories"` - } - resp, err := s.client.Do(ctx, req, &r) - if err != nil { - return nil, resp, err - } - - return r.Repositories, resp, nil -} - -// AddRepository adds a single repository to an installation. -// -// GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation -func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { - u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID) - req, err := s.client.NewRequest("PUT", u, nil) - if err != nil { - return nil, nil, err - } - - r := new(Repository) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// RemoveRepository removes a single repository from an installation. -// -// GitHub docs: https://developer.github.com/v3/apps/installations/#remove-repository-from-installation -func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { - u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/apps_marketplace.go b/vendor/github.com/google/go-github/github/apps_marketplace.go deleted file mode 100644 index 3f35b915..00000000 --- a/vendor/github.com/google/go-github/github/apps_marketplace.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2017 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// MarketplaceService handles communication with the marketplace related -// methods of the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/ -type MarketplaceService struct { - client *Client - // Stubbed controls whether endpoints that return stubbed data are used - // instead of production endpoints. Stubbed data is fake data that's useful - // for testing your GitHub Apps. Stubbed data is hard-coded and will not - // change based on actual subscriptions. - // - // GitHub API docs: https://developer.github.com/v3/apps/marketplace/ - Stubbed bool -} - -// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. -type MarketplacePlan struct { - URL *string `json:"url,omitempty"` - AccountsURL *string `json:"accounts_url,omitempty"` - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` - YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` - PriceModel *string `json:"price_model,omitempty"` - UnitName *string `json:"unit_name,omitempty"` - Bullets *[]string `json:"bullets,omitempty"` -} - -// MarketplacePurchase represents a GitHub Apps Marketplace Purchase. -type MarketplacePurchase struct { - BillingCycle *string `json:"billing_cycle,omitempty"` - NextBillingDate *string `json:"next_billing_date,omitempty"` - UnitCount *int `json:"unit_count,omitempty"` - Plan *MarketplacePlan `json:"plan,omitempty"` - Account *MarketplacePlanAccount `json:"account,omitempty"` -} - -// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. -type MarketplacePlanAccount struct { - URL *string `json:"url,omitempty"` - Type *string `json:"type,omitempty"` - ID *int64 `json:"id,omitempty"` - Login *string `json:"login,omitempty"` - Email *string `json:"email,omitempty"` - OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` - MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` -} - -// ListPlans lists all plans for your Marketplace listing. -// -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing -func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([]*MarketplacePlan, *Response, error) { - uri := s.marketplaceURI("plans") - u, err := addOptions(uri, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var plans []*MarketplacePlan - resp, err := s.client.Do(ctx, req, &plans) - if err != nil { - return nil, resp, err - } - - return plans, resp, nil -} - -// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. -// -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan -func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { - uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) - u, err := addOptions(uri, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var accounts []*MarketplacePlanAccount - resp, err := s.client.Do(ctx, req, &accounts) - if err != nil { - return nil, resp, err - } - - return accounts, resp, nil -} - -// ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account. -// -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing -func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { - uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) - u, err := addOptions(uri, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var accounts []*MarketplacePlanAccount - resp, err := s.client.Do(ctx, req, &accounts) - if err != nil { - return nil, resp, err - } - - return accounts, resp, nil -} - -// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. -// -// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases -func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opt *ListOptions) ([]*MarketplacePurchase, *Response, error) { - uri := "user/marketplace_purchases" - if s.Stubbed { - uri = "user/marketplace_purchases/stubbed" - } - - u, err := addOptions(uri, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var purchases []*MarketplacePurchase - resp, err := s.client.Do(ctx, req, &purchases) - if err != nil { - return nil, resp, err - } - - return purchases, resp, nil -} - -func (s *MarketplaceService) marketplaceURI(endpoint string) string { - url := "marketplace_listing" - if s.Stubbed { - url = "marketplace_listing/stubbed" - } - return url + "/" + endpoint -} diff --git a/vendor/github.com/google/go-github/github/event_types.go b/vendor/github.com/google/go-github/github/event_types.go deleted file mode 100644 index 0b635ef8..00000000 --- a/vendor/github.com/google/go-github/github/event_types.go +++ /dev/null @@ -1,786 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// These event types are shared between the Events API and used as Webhook payloads. - -package github - -// CheckRunEvent is triggered when a check run is "created", "updated", or "re-requested". -// The Webhook event name is "check_run". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent -type CheckRunEvent struct { - CheckRun *CheckRun `json:"check_run,omitempty"` - // The action performed. Can be "created", "updated" or "re-requested". - Action *string `json:"action,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "re-requested". -// The Webhook event name is "check_suite". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent -type CheckSuiteEvent struct { - CheckSuite *CheckSuite `json:"check_suite,omitempty"` - // The action performed. Can be "completed", "requested" or "re-requested". - Action *string `json:"action,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// CommitCommentEvent is triggered when a commit comment is created. -// The Webhook event name is "commit_comment". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#commitcommentevent -type CommitCommentEvent struct { - Comment *RepositoryComment `json:"comment,omitempty"` - - // The following fields are only populated by Webhook events. - Action *string `json:"action,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// CreateEvent represents a created repository, branch, or tag. -// The Webhook event name is "create". -// -// Note: webhooks will not receive this event for created repositories. -// Additionally, webhooks will not receive this event for tags if more -// than three tags are pushed at once. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#createevent -type CreateEvent struct { - Ref *string `json:"ref,omitempty"` - // RefType is the object that was created. Possible values are: "repository", "branch", "tag". - RefType *string `json:"ref_type,omitempty"` - MasterBranch *string `json:"master_branch,omitempty"` - Description *string `json:"description,omitempty"` - - // The following fields are only populated by Webhook events. - PusherType *string `json:"pusher_type,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// DeleteEvent represents a deleted branch or tag. -// The Webhook event name is "delete". -// -// Note: webhooks will not receive this event for tags if more than three tags -// are deleted at once. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deleteevent -type DeleteEvent struct { - Ref *string `json:"ref,omitempty"` - // RefType is the object that was deleted. Possible values are: "branch", "tag". - RefType *string `json:"ref_type,omitempty"` - - // The following fields are only populated by Webhook events. - PusherType *string `json:"pusher_type,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// DeploymentEvent represents a deployment. -// The Webhook event name is "deployment". -// -// Events of this type are not visible in timelines, they are only used to trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentevent -type DeploymentEvent struct { - Deployment *Deployment `json:"deployment,omitempty"` - Repo *Repository `json:"repository,omitempty"` - - // The following fields are only populated by Webhook events. - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// DeploymentStatusEvent represents a deployment status. -// The Webhook event name is "deployment_status". -// -// Events of this type are not visible in timelines, they are only used to trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentstatusevent -type DeploymentStatusEvent struct { - Deployment *Deployment `json:"deployment,omitempty"` - DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` - Repo *Repository `json:"repository,omitempty"` - - // The following fields are only populated by Webhook events. - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// ForkEvent is triggered when a user forks a repository. -// The Webhook event name is "fork". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#forkevent -type ForkEvent struct { - // Forkee is the created repository. - Forkee *Repository `json:"forkee,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// Page represents a single Wiki page. -type Page struct { - PageName *string `json:"page_name,omitempty"` - Title *string `json:"title,omitempty"` - Summary *string `json:"summary,omitempty"` - Action *string `json:"action,omitempty"` - SHA *string `json:"sha,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` -} - -// GollumEvent is triggered when a Wiki page is created or updated. -// The Webhook event name is "gollum". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#gollumevent -type GollumEvent struct { - Pages []*Page `json:"pages,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// EditChange represents the changes when an issue, pull request, or comment has -// been edited. -type EditChange struct { - Title *struct { - From *string `json:"from,omitempty"` - } `json:"title,omitempty"` - Body *struct { - From *string `json:"from,omitempty"` - } `json:"body,omitempty"` -} - -// ProjectChange represents the changes when a project has been edited. -type ProjectChange struct { - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` - Body *struct { - From *string `json:"from,omitempty"` - } `json:"body,omitempty"` -} - -// ProjectCardChange represents the changes when a project card has been edited. -type ProjectCardChange struct { - Note *struct { - From *string `json:"from,omitempty"` - } `json:"note,omitempty"` -} - -// ProjectColumnChange represents the changes when a project column has been edited. -type ProjectColumnChange struct { - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` -} - -// TeamChange represents the changes when a team has been edited. -type TeamChange struct { - Description *struct { - From *string `json:"from,omitempty"` - } `json:"description,omitempty"` - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` - Privacy *struct { - From *string `json:"from,omitempty"` - } `json:"privacy,omitempty"` - Repository *struct { - Permissions *struct { - From *struct { - Admin *bool `json:"admin,omitempty"` - Pull *bool `json:"pull,omitempty"` - Push *bool `json:"push,omitempty"` - } `json:"from,omitempty"` - } `json:"permissions,omitempty"` - } `json:"repository,omitempty"` -} - -// InstallationEvent is triggered when a GitHub App has been installed or uninstalled. -// The Webhook event name is "installation". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationevent -type InstallationEvent struct { - // The action that was performed. Can be either "created" or "deleted". - Action *string `json:"action,omitempty"` - Repositories []*Repository `json:"repositories,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// InstallationRepositoriesEvent is triggered when a repository is added or -// removed from an installation. The Webhook event name is "installation_repositories". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationrepositoriesevent -type InstallationRepositoriesEvent struct { - // The action that was performed. Can be either "added" or "removed". - Action *string `json:"action,omitempty"` - RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` - RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` - RepositorySelection *string `json:"repository_selection,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// IssueCommentEvent is triggered when an issue comment is created on an issue -// or pull request. -// The Webhook event name is "issue_comment". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuecommentevent -type IssueCommentEvent struct { - // Action is the action that was performed on the comment. - // Possible values are: "created", "edited", "deleted". - Action *string `json:"action,omitempty"` - Issue *Issue `json:"issue,omitempty"` - Comment *IssueComment `json:"comment,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// IssuesEvent is triggered when an issue is assigned, unassigned, labeled, -// unlabeled, opened, closed, or reopened. -// The Webhook event name is "issues". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent -type IssuesEvent struct { - // Action is the action that was performed. Possible values are: "assigned", - // "unassigned", "labeled", "unlabeled", "opened", "closed", "reopened", "edited". - Action *string `json:"action,omitempty"` - Issue *Issue `json:"issue,omitempty"` - Assignee *User `json:"assignee,omitempty"` - Label *Label `json:"label,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// LabelEvent is triggered when a repository's label is created, edited, or deleted. -// The Webhook event name is "label" -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#labelevent -type LabelEvent struct { - // Action is the action that was performed. Possible values are: - // "created", "edited", "deleted" - Action *string `json:"action,omitempty"` - Label *Label `json:"label,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes -// their GitHub Marketplace plan. -// Webhook event name "marketplace_purchase". -// -// Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent -type MarketplacePurchaseEvent struct { - // Action is the action that was performed. Possible values are: - // "purchased", "cancelled", "changed". - Action *string `json:"action,omitempty"` - - // The following fields are only populated by Webhook events. - EffectiveDate *Timestamp `json:"effective_date,omitempty"` - MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` - PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// MemberEvent is triggered when a user is added as a collaborator to a repository. -// The Webhook event name is "member". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#memberevent -type MemberEvent struct { - // Action is the action that was performed. Possible value is: "added". - Action *string `json:"action,omitempty"` - Member *User `json:"member,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// MembershipEvent is triggered when a user is added or removed from a team. -// The Webhook event name is "membership". -// -// Events of this type are not visible in timelines, they are only used to -// trigger organization webhooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#membershipevent -type MembershipEvent struct { - // Action is the action that was performed. Possible values are: "added", "removed". - Action *string `json:"action,omitempty"` - // Scope is the scope of the membership. Possible value is: "team". - Scope *string `json:"scope,omitempty"` - Member *User `json:"member,omitempty"` - Team *Team `json:"team,omitempty"` - - // The following fields are only populated by Webhook events. - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. -// The Webhook event name is "milestone". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#milestoneevent -type MilestoneEvent struct { - // Action is the action that was performed. Possible values are: - // "created", "closed", "opened", "edited", "deleted" - Action *string `json:"action,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Org *Organization `json:"organization,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// OrganizationEvent is triggered when a user is added, removed, or invited to an organization. -// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. -// Webhook event name is "organization". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent -type OrganizationEvent struct { - // Action is the action that was performed. - // Can be one of "member_added", "member_removed", or "member_invited". - Action *string `json:"action,omitempty"` - - // Invitaion is the invitation for the user or email if the action is "member_invited". - Invitation *Invitation `json:"invitation,omitempty"` - - // Membership is the membership between the user and the organization. - // Not present when the action is "member_invited". - Membership *Membership `json:"membership,omitempty"` - - Organization *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// OrgBlockEvent is triggered when an organization blocks or unblocks a user. -// The Webhook event name is "org_block". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#orgblockevent -type OrgBlockEvent struct { - // Action is the action that was performed. - // Can be "blocked" or "unblocked". - Action *string `json:"action,omitempty"` - BlockedUser *User `json:"blocked_user,omitempty"` - Organization *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - - // The following fields are only populated by Webhook events. - Installation *Installation `json:"installation,omitempty"` -} - -// PageBuildEvent represents an attempted build of a GitHub Pages site, whether -// successful or not. -// The Webhook event name is "page_build". -// -// This event is triggered on push to a GitHub Pages enabled branch (gh-pages -// for project pages, master for user and organization pages). -// -// Events of this type are not visible in timelines, they are only used to trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pagebuildevent -type PageBuildEvent struct { - Build *PagesBuild `json:"build,omitempty"` - - // The following fields are only populated by Webhook events. - ID *int64 `json:"id,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// PingEvent is triggered when a Webhook is added to GitHub. -// -// GitHub API docs: https://developer.github.com/webhooks/#ping-event -type PingEvent struct { - // Random string of GitHub zen. - Zen *string `json:"zen,omitempty"` - // The ID of the webhook that triggered the ping. - HookID *int64 `json:"hook_id,omitempty"` - // The webhook configuration. - Hook *Hook `json:"hook,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// ProjectEvent is triggered when project is created, modified or deleted. -// The webhook event name is "project". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectevent -type ProjectEvent struct { - Action *string `json:"action,omitempty"` - Changes *ProjectChange `json:"changes,omitempty"` - Project *Project `json:"project,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted. -// The webhook event name is "project_card". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcardevent -type ProjectCardEvent struct { - Action *string `json:"action,omitempty"` - Changes *ProjectCardChange `json:"changes,omitempty"` - AfterID *int64 `json:"after_id,omitempty"` - ProjectCard *ProjectCard `json:"project_card,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted. -// The webhook event name is "project_column". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcolumnevent -type ProjectColumnEvent struct { - Action *string `json:"action,omitempty"` - Changes *ProjectColumnChange `json:"changes,omitempty"` - AfterID *int64 `json:"after_id,omitempty"` - ProjectColumn *ProjectColumn `json:"project_column,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// PublicEvent is triggered when a private repository is open sourced. -// According to GitHub: "Without a doubt: the best GitHub event." -// The Webhook event name is "public". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#publicevent -type PublicEvent struct { - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// PullRequestEvent is triggered when a pull request is assigned, unassigned, -// labeled, unlabeled, opened, closed, reopened, or synchronized. -// The Webhook event name is "pull_request". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent -type PullRequestEvent struct { - // Action is the action that was performed. Possible values are: - // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", - // "opened", "closed", "reopened", "synchronize", "edited". - // If the action is "closed" and the merged key is false, - // the pull request was closed with unmerged commits. If the action is "closed" - // and the merged key is true, the pull request was merged. - Action *string `json:"action,omitempty"` - Number *int `json:"number,omitempty"` - PullRequest *PullRequest `json:"pull_request,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. - // A request affecting multiple reviewers at once is split into multiple - // such event deliveries, each with a single, different RequestedReviewer. - RequestedReviewer *User `json:"requested_reviewer,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` - Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. -} - -// PullRequestReviewEvent is triggered when a review is submitted on a pull -// request. -// The Webhook event name is "pull_request_review". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent -type PullRequestReviewEvent struct { - // Action is always "submitted". - Action *string `json:"action,omitempty"` - Review *PullRequestReview `json:"review,omitempty"` - PullRequest *PullRequest `json:"pull_request,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` - - // The following field is only present when the webhook is triggered on - // a repository belonging to an organization. - Organization *Organization `json:"organization,omitempty"` -} - -// PullRequestReviewCommentEvent is triggered when a comment is created on a -// portion of the unified diff of a pull request. -// The Webhook event name is "pull_request_review_comment". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent -type PullRequestReviewCommentEvent struct { - // Action is the action that was performed on the comment. - // Possible values are: "created", "edited", "deleted". - Action *string `json:"action,omitempty"` - PullRequest *PullRequest `json:"pull_request,omitempty"` - Comment *PullRequestComment `json:"comment,omitempty"` - - // The following fields are only populated by Webhook events. - Changes *EditChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// PushEvent represents a git push to a GitHub repository. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent -type PushEvent struct { - PushID *int64 `json:"push_id,omitempty"` - Head *string `json:"head,omitempty"` - Ref *string `json:"ref,omitempty"` - Size *int `json:"size,omitempty"` - Commits []PushEventCommit `json:"commits,omitempty"` - Before *string `json:"before,omitempty"` - DistinctSize *int `json:"distinct_size,omitempty"` - - // The following fields are only populated by Webhook events. - After *string `json:"after,omitempty"` - Created *bool `json:"created,omitempty"` - Deleted *bool `json:"deleted,omitempty"` - Forced *bool `json:"forced,omitempty"` - BaseRef *string `json:"base_ref,omitempty"` - Compare *string `json:"compare,omitempty"` - Repo *PushEventRepository `json:"repository,omitempty"` - HeadCommit *PushEventCommit `json:"head_commit,omitempty"` - Pusher *User `json:"pusher,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -func (p PushEvent) String() string { - return Stringify(p) -} - -// PushEventCommit represents a git commit in a GitHub PushEvent. -type PushEventCommit struct { - Message *string `json:"message,omitempty"` - Author *CommitAuthor `json:"author,omitempty"` - URL *string `json:"url,omitempty"` - Distinct *bool `json:"distinct,omitempty"` - - // The following fields are only populated by Events API. - SHA *string `json:"sha,omitempty"` - - // The following fields are only populated by Webhook events. - ID *string `json:"id,omitempty"` - TreeID *string `json:"tree_id,omitempty"` - Timestamp *Timestamp `json:"timestamp,omitempty"` - Committer *CommitAuthor `json:"committer,omitempty"` - Added []string `json:"added,omitempty"` - Removed []string `json:"removed,omitempty"` - Modified []string `json:"modified,omitempty"` -} - -func (p PushEventCommit) String() string { - return Stringify(p) -} - -// PushEventRepository represents the repo object in a PushEvent payload. -type PushEventRepository struct { - ID *int64 `json:"id,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Name *string `json:"name,omitempty"` - FullName *string `json:"full_name,omitempty"` - Owner *PushEventRepoOwner `json:"owner,omitempty"` - Private *bool `json:"private,omitempty"` - Description *string `json:"description,omitempty"` - Fork *bool `json:"fork,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - PushedAt *Timestamp `json:"pushed_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - Homepage *string `json:"homepage,omitempty"` - Size *int `json:"size,omitempty"` - StargazersCount *int `json:"stargazers_count,omitempty"` - WatchersCount *int `json:"watchers_count,omitempty"` - Language *string `json:"language,omitempty"` - HasIssues *bool `json:"has_issues,omitempty"` - HasDownloads *bool `json:"has_downloads,omitempty"` - HasWiki *bool `json:"has_wiki,omitempty"` - HasPages *bool `json:"has_pages,omitempty"` - ForksCount *int `json:"forks_count,omitempty"` - OpenIssuesCount *int `json:"open_issues_count,omitempty"` - DefaultBranch *string `json:"default_branch,omitempty"` - MasterBranch *string `json:"master_branch,omitempty"` - Organization *string `json:"organization,omitempty"` - URL *string `json:"url,omitempty"` - ArchiveURL *string `json:"archive_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - StatusesURL *string `json:"statuses_url,omitempty"` - GitURL *string `json:"git_url,omitempty"` - SSHURL *string `json:"ssh_url,omitempty"` - CloneURL *string `json:"clone_url,omitempty"` - SVNURL *string `json:"svn_url,omitempty"` -} - -// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. -type PushEventRepoOwner struct { - Name *string `json:"name,omitempty"` - Email *string `json:"email,omitempty"` -} - -// ReleaseEvent is triggered when a release is published. -// The Webhook event name is "release". -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent -type ReleaseEvent struct { - // Action is the action that was performed. Possible value is: "published". - Action *string `json:"action,omitempty"` - Release *RepositoryRelease `json:"release,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// RepositoryEvent is triggered when a repository is created. -// The Webhook event name is "repository". -// -// Events of this type are not visible in timelines, they are only used to -// trigger organization webhooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent -type RepositoryEvent struct { - // Action is the action that was performed. Possible values are: "created", "deleted", - // "publicized", "privatized". - Action *string `json:"action,omitempty"` - Repo *Repository `json:"repository,omitempty"` - - // The following fields are only populated by Webhook events. - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// StatusEvent is triggered when the status of a Git commit changes. -// The Webhook event name is "status". -// -// Events of this type are not visible in timelines, they are only used to -// trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#statusevent -type StatusEvent struct { - SHA *string `json:"sha,omitempty"` - // State is the new state. Possible values are: "pending", "success", "failure", "error". - State *string `json:"state,omitempty"` - Description *string `json:"description,omitempty"` - TargetURL *string `json:"target_url,omitempty"` - Branches []*Branch `json:"branches,omitempty"` - - // The following fields are only populated by Webhook events. - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Context *string `json:"context,omitempty"` - Commit *RepositoryCommit `json:"commit,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// TeamEvent is triggered when an organization's team is created, modified or deleted. -// The Webhook event name is "team". -// -// Events of this type are not visible in timelines. These events are only used -// to trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamevent -type TeamEvent struct { - Action *string `json:"action,omitempty"` - Team *Team `json:"team,omitempty"` - Changes *TeamChange `json:"changes,omitempty"` - Repo *Repository `json:"repository,omitempty"` - - // The following fields are only populated by Webhook events. - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// TeamAddEvent is triggered when a repository is added to a team. -// The Webhook event name is "team_add". -// -// Events of this type are not visible in timelines. These events are only used -// to trigger hooks. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamaddevent -type TeamAddEvent struct { - Team *Team `json:"team,omitempty"` - Repo *Repository `json:"repository,omitempty"` - - // The following fields are only populated by Webhook events. - Org *Organization `json:"organization,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} - -// WatchEvent is related to starring a repository, not watching. See this API -// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ -// -// The event’s actor is the user who starred a repository, and the event’s -// repository is the repository that was starred. -// -// GitHub API docs: https://developer.github.com/v3/activity/events/types/#watchevent -type WatchEvent struct { - // Action is the action that was performed. Possible value is: "started". - Action *string `json:"action,omitempty"` - - // The following fields are only populated by Webhook events. - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` - Installation *Installation `json:"installation,omitempty"` -} diff --git a/vendor/github.com/google/go-github/github/git_refs.go b/vendor/github.com/google/go-github/github/git_refs.go deleted file mode 100644 index 3b2ced23..00000000 --- a/vendor/github.com/google/go-github/github/git_refs.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "strings" -) - -// Reference represents a GitHub reference. -type Reference struct { - Ref *string `json:"ref"` - URL *string `json:"url"` - Object *GitObject `json:"object"` - NodeID *string `json:"node_id,omitempty"` -} - -func (r Reference) String() string { - return Stringify(r) -} - -// GitObject represents a Git object. -type GitObject struct { - Type *string `json:"type"` - SHA *string `json:"sha"` - URL *string `json:"url"` -} - -func (o GitObject) String() string { - return Stringify(o) -} - -// createRefRequest represents the payload for creating a reference. -type createRefRequest struct { - Ref *string `json:"ref"` - SHA *string `json:"sha"` -} - -// updateRefRequest represents the payload for updating a reference. -type updateRefRequest struct { - SHA *string `json:"sha"` - Force *bool `json:"force"` -} - -// GetRef fetches a single Reference object for a given Git ref. -// If there is no exact match, GetRef will return an error. -// -// Note: The GitHub API can return multiple matches. -// If you wish to use this functionality please use the GetRefs() method. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference -func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { - ref = strings.TrimPrefix(ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - r := new(Reference) - resp, err := s.client.Do(ctx, req, r) - if _, ok := err.(*json.UnmarshalTypeError); ok { - // Multiple refs, means there wasn't an exact match. - return nil, resp, errors.New("no exact match found for this ref") - } else if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// GetRefs fetches a slice of Reference objects for a given Git ref. -// If there is an exact match, only that ref is returned. -// If there is no exact match, GitHub returns all refs that start with ref. -// If returned error is nil, there will be at least 1 ref returned. -// For example: -// -// "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned. -// "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref. -// "heads/notexist" -> [] // Returns an error. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference -func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) { - ref = strings.TrimPrefix(ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var rawJSON json.RawMessage - resp, err := s.client.Do(ctx, req, &rawJSON) - if err != nil { - return nil, resp, err - } - - // Prioritize the most common case: a single returned ref. - r := new(Reference) - singleUnmarshalError := json.Unmarshal(rawJSON, r) - if singleUnmarshalError == nil { - return []*Reference{r}, resp, nil - } - - // Attempt to unmarshal multiple refs. - var rs []*Reference - multipleUnmarshalError := json.Unmarshal(rawJSON, &rs) - if multipleUnmarshalError == nil { - if len(rs) == 0 { - return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0") - } - return rs, resp, nil - } - - return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError) -} - -// ReferenceListOptions specifies optional parameters to the -// GitService.ListRefs method. -type ReferenceListOptions struct { - Type string `url:"-"` - - ListOptions -} - -// ListRefs lists all refs in a repository. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references -func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opt *ReferenceListOptions) ([]*Reference, *Response, error) { - var u string - if opt != nil && opt.Type != "" { - u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opt.Type) - } else { - u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) - } - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var rs []*Reference - resp, err := s.client.Do(ctx, req, &rs) - if err != nil { - return nil, resp, err - } - - return rs, resp, nil -} - -// CreateRef creates a new ref in a repository. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#create-a-reference -func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) - req, err := s.client.NewRequest("POST", u, &createRefRequest{ - // back-compat with previous behavior that didn't require 'refs/' prefix - Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), - SHA: ref.Object.SHA, - }) - if err != nil { - return nil, nil, err - } - - r := new(Reference) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// UpdateRef updates an existing ref in a repository. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#update-a-reference -func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { - refPath := strings.TrimPrefix(*ref.Ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath) - req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ - SHA: ref.Object.SHA, - Force: &force, - }) - if err != nil { - return nil, nil, err - } - - r := new(Reference) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// DeleteRef deletes a ref from a repository. -// -// GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference -func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { - ref = strings.TrimPrefix(ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/github-accessors.go b/vendor/github.com/google/go-github/github/github-accessors.go deleted file mode 100644 index 5094ca66..00000000 --- a/vendor/github.com/google/go-github/github/github-accessors.go +++ /dev/null @@ -1,11861 +0,0 @@ -// Copyright 2017 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by gen-accessors; DO NOT EDIT. - -package github - -import ( - "encoding/json" - "time" -) - -// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. -func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { - if a == nil || a.RetryAfter == nil { - return 0 - } - return *a.RetryAfter -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (a *AdminEnforcement) GetURL() string { - if a == nil || a.URL == nil { - return "" - } - return *a.URL -} - -// GetComments returns the Comments field. -func (a *AdminStats) GetComments() *CommentStats { - if a == nil { - return nil - } - return a.Comments -} - -// GetGists returns the Gists field. -func (a *AdminStats) GetGists() *GistStats { - if a == nil { - return nil - } - return a.Gists -} - -// GetHooks returns the Hooks field. -func (a *AdminStats) GetHooks() *HookStats { - if a == nil { - return nil - } - return a.Hooks -} - -// GetIssues returns the Issues field. -func (a *AdminStats) GetIssues() *IssueStats { - if a == nil { - return nil - } - return a.Issues -} - -// GetMilestones returns the Milestones field. -func (a *AdminStats) GetMilestones() *MilestoneStats { - if a == nil { - return nil - } - return a.Milestones -} - -// GetOrgs returns the Orgs field. -func (a *AdminStats) GetOrgs() *OrgStats { - if a == nil { - return nil - } - return a.Orgs -} - -// GetPages returns the Pages field. -func (a *AdminStats) GetPages() *PageStats { - if a == nil { - return nil - } - return a.Pages -} - -// GetPulls returns the Pulls field. -func (a *AdminStats) GetPulls() *PullStats { - if a == nil { - return nil - } - return a.Pulls -} - -// GetRepos returns the Repos field. -func (a *AdminStats) GetRepos() *RepoStats { - if a == nil { - return nil - } - return a.Repos -} - -// GetUsers returns the Users field. -func (a *AdminStats) GetUsers() *UserStats { - if a == nil { - return nil - } - return a.Users -} - -// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. -func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { - if a == nil || a.VerifiablePasswordAuthentication == nil { - return false - } - return *a.VerifiablePasswordAuthentication -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (a *App) GetCreatedAt() time.Time { - if a == nil || a.CreatedAt == nil { - return time.Time{} - } - return *a.CreatedAt -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (a *App) GetDescription() string { - if a == nil || a.Description == nil { - return "" - } - return *a.Description -} - -// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. -func (a *App) GetExternalURL() string { - if a == nil || a.ExternalURL == nil { - return "" - } - return *a.ExternalURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (a *App) GetHTMLURL() string { - if a == nil || a.HTMLURL == nil { - return "" - } - return *a.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (a *App) GetID() int64 { - if a == nil || a.ID == nil { - return 0 - } - return *a.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (a *App) GetName() string { - if a == nil || a.Name == nil { - return "" - } - return *a.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (a *App) GetNodeID() string { - if a == nil || a.NodeID == nil { - return "" - } - return *a.NodeID -} - -// GetOwner returns the Owner field. -func (a *App) GetOwner() *User { - if a == nil { - return nil - } - return a.Owner -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (a *App) GetUpdatedAt() time.Time { - if a == nil || a.UpdatedAt == nil { - return time.Time{} - } - return *a.UpdatedAt -} - -// GetApp returns the App field. -func (a *Authorization) GetApp() *AuthorizationApp { - if a == nil { - return nil - } - return a.App -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (a *Authorization) GetCreatedAt() Timestamp { - if a == nil || a.CreatedAt == nil { - return Timestamp{} - } - return *a.CreatedAt -} - -// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. -func (a *Authorization) GetFingerprint() string { - if a == nil || a.Fingerprint == nil { - return "" - } - return *a.Fingerprint -} - -// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. -func (a *Authorization) GetHashedToken() string { - if a == nil || a.HashedToken == nil { - return "" - } - return *a.HashedToken -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (a *Authorization) GetID() int64 { - if a == nil || a.ID == nil { - return 0 - } - return *a.ID -} - -// GetNote returns the Note field if it's non-nil, zero value otherwise. -func (a *Authorization) GetNote() string { - if a == nil || a.Note == nil { - return "" - } - return *a.Note -} - -// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. -func (a *Authorization) GetNoteURL() string { - if a == nil || a.NoteURL == nil { - return "" - } - return *a.NoteURL -} - -// GetToken returns the Token field if it's non-nil, zero value otherwise. -func (a *Authorization) GetToken() string { - if a == nil || a.Token == nil { - return "" - } - return *a.Token -} - -// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. -func (a *Authorization) GetTokenLastEight() string { - if a == nil || a.TokenLastEight == nil { - return "" - } - return *a.TokenLastEight -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (a *Authorization) GetUpdatedAt() Timestamp { - if a == nil || a.UpdatedAt == nil { - return Timestamp{} - } - return *a.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (a *Authorization) GetURL() string { - if a == nil || a.URL == nil { - return "" - } - return *a.URL -} - -// GetUser returns the User field. -func (a *Authorization) GetUser() *User { - if a == nil { - return nil - } - return a.User -} - -// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. -func (a *AuthorizationApp) GetClientID() string { - if a == nil || a.ClientID == nil { - return "" - } - return *a.ClientID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (a *AuthorizationApp) GetName() string { - if a == nil || a.Name == nil { - return "" - } - return *a.Name -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (a *AuthorizationApp) GetURL() string { - if a == nil || a.URL == nil { - return "" - } - return *a.URL -} - -// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. -func (a *AuthorizationRequest) GetClientID() string { - if a == nil || a.ClientID == nil { - return "" - } - return *a.ClientID -} - -// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. -func (a *AuthorizationRequest) GetClientSecret() string { - if a == nil || a.ClientSecret == nil { - return "" - } - return *a.ClientSecret -} - -// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. -func (a *AuthorizationRequest) GetFingerprint() string { - if a == nil || a.Fingerprint == nil { - return "" - } - return *a.Fingerprint -} - -// GetNote returns the Note field if it's non-nil, zero value otherwise. -func (a *AuthorizationRequest) GetNote() string { - if a == nil || a.Note == nil { - return "" - } - return *a.Note -} - -// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. -func (a *AuthorizationRequest) GetNoteURL() string { - if a == nil || a.NoteURL == nil { - return "" - } - return *a.NoteURL -} - -// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. -func (a *AuthorizationUpdateRequest) GetFingerprint() string { - if a == nil || a.Fingerprint == nil { - return "" - } - return *a.Fingerprint -} - -// GetNote returns the Note field if it's non-nil, zero value otherwise. -func (a *AuthorizationUpdateRequest) GetNote() string { - if a == nil || a.Note == nil { - return "" - } - return *a.Note -} - -// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. -func (a *AuthorizationUpdateRequest) GetNoteURL() string { - if a == nil || a.NoteURL == nil { - return "" - } - return *a.NoteURL -} - -// GetAppID returns the AppID field if it's non-nil, zero value otherwise. -func (a *AutoTriggerCheck) GetAppID() int64 { - if a == nil || a.AppID == nil { - return 0 - } - return *a.AppID -} - -// GetSetting returns the Setting field if it's non-nil, zero value otherwise. -func (a *AutoTriggerCheck) GetSetting() bool { - if a == nil || a.Setting == nil { - return false - } - return *a.Setting -} - -// GetContent returns the Content field if it's non-nil, zero value otherwise. -func (b *Blob) GetContent() string { - if b == nil || b.Content == nil { - return "" - } - return *b.Content -} - -// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. -func (b *Blob) GetEncoding() string { - if b == nil || b.Encoding == nil { - return "" - } - return *b.Encoding -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (b *Blob) GetNodeID() string { - if b == nil || b.NodeID == nil { - return "" - } - return *b.NodeID -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (b *Blob) GetSHA() string { - if b == nil || b.SHA == nil { - return "" - } - return *b.SHA -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (b *Blob) GetSize() int { - if b == nil || b.Size == nil { - return 0 - } - return *b.Size -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (b *Blob) GetURL() string { - if b == nil || b.URL == nil { - return "" - } - return *b.URL -} - -// GetCommit returns the Commit field. -func (b *Branch) GetCommit() *RepositoryCommit { - if b == nil { - return nil - } - return b.Commit -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (b *Branch) GetName() string { - if b == nil || b.Name == nil { - return "" - } - return *b.Name -} - -// GetProtected returns the Protected field if it's non-nil, zero value otherwise. -func (b *Branch) GetProtected() bool { - if b == nil || b.Protected == nil { - return false - } - return *b.Protected -} - -// GetApp returns the App field. -func (c *CheckRun) GetApp() *App { - if c == nil { - return nil - } - return c.App -} - -// GetCheckSuite returns the CheckSuite field. -func (c *CheckRun) GetCheckSuite() *CheckSuite { - if c == nil { - return nil - } - return c.CheckSuite -} - -// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetCompletedAt() Timestamp { - if c == nil || c.CompletedAt == nil { - return Timestamp{} - } - return *c.CompletedAt -} - -// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetConclusion() string { - if c == nil || c.Conclusion == nil { - return "" - } - return *c.Conclusion -} - -// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetExternalID() string { - if c == nil || c.ExternalID == nil { - return "" - } - return *c.ExternalID -} - -// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetHeadSHA() string { - if c == nil || c.HeadSHA == nil { - return "" - } - return *c.HeadSHA -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetID() int64 { - if c == nil || c.ID == nil { - return 0 - } - return *c.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetName() string { - if c == nil || c.Name == nil { - return "" - } - return *c.Name -} - -// GetOutput returns the Output field. -func (c *CheckRun) GetOutput() *CheckRunOutput { - if c == nil { - return nil - } - return c.Output -} - -// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetStartedAt() Timestamp { - if c == nil || c.StartedAt == nil { - return Timestamp{} - } - return *c.StartedAt -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetStatus() string { - if c == nil || c.Status == nil { - return "" - } - return *c.Status -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *CheckRun) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetBlobHRef returns the BlobHRef field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetBlobHRef() string { - if c == nil || c.BlobHRef == nil { - return "" - } - return *c.BlobHRef -} - -// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetEndLine() int { - if c == nil || c.EndLine == nil { - return 0 - } - return *c.EndLine -} - -// GetFileName returns the FileName field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetFileName() string { - if c == nil || c.FileName == nil { - return "" - } - return *c.FileName -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetMessage() string { - if c == nil || c.Message == nil { - return "" - } - return *c.Message -} - -// GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetRawDetails() string { - if c == nil || c.RawDetails == nil { - return "" - } - return *c.RawDetails -} - -// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetStartLine() int { - if c == nil || c.StartLine == nil { - return 0 - } - return *c.StartLine -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetTitle() string { - if c == nil || c.Title == nil { - return "" - } - return *c.Title -} - -// GetWarningLevel returns the WarningLevel field if it's non-nil, zero value otherwise. -func (c *CheckRunAnnotation) GetWarningLevel() string { - if c == nil || c.WarningLevel == nil { - return "" - } - return *c.WarningLevel -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (c *CheckRunEvent) GetAction() string { - if c == nil || c.Action == nil { - return "" - } - return *c.Action -} - -// GetCheckRun returns the CheckRun field. -func (c *CheckRunEvent) GetCheckRun() *CheckRun { - if c == nil { - return nil - } - return c.CheckRun -} - -// GetInstallation returns the Installation field. -func (c *CheckRunEvent) GetInstallation() *Installation { - if c == nil { - return nil - } - return c.Installation -} - -// GetOrg returns the Org field. -func (c *CheckRunEvent) GetOrg() *Organization { - if c == nil { - return nil - } - return c.Org -} - -// GetRepo returns the Repo field. -func (c *CheckRunEvent) GetRepo() *Repository { - if c == nil { - return nil - } - return c.Repo -} - -// GetSender returns the Sender field. -func (c *CheckRunEvent) GetSender() *User { - if c == nil { - return nil - } - return c.Sender -} - -// GetAlt returns the Alt field if it's non-nil, zero value otherwise. -func (c *CheckRunImage) GetAlt() string { - if c == nil || c.Alt == nil { - return "" - } - return *c.Alt -} - -// GetCaption returns the Caption field if it's non-nil, zero value otherwise. -func (c *CheckRunImage) GetCaption() string { - if c == nil || c.Caption == nil { - return "" - } - return *c.Caption -} - -// GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise. -func (c *CheckRunImage) GetImageURL() string { - if c == nil || c.ImageURL == nil { - return "" - } - return *c.ImageURL -} - -// GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise. -func (c *CheckRunOutput) GetAnnotationsCount() int { - if c == nil || c.AnnotationsCount == nil { - return 0 - } - return *c.AnnotationsCount -} - -// GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise. -func (c *CheckRunOutput) GetAnnotationsURL() string { - if c == nil || c.AnnotationsURL == nil { - return "" - } - return *c.AnnotationsURL -} - -// GetSummary returns the Summary field if it's non-nil, zero value otherwise. -func (c *CheckRunOutput) GetSummary() string { - if c == nil || c.Summary == nil { - return "" - } - return *c.Summary -} - -// GetText returns the Text field if it's non-nil, zero value otherwise. -func (c *CheckRunOutput) GetText() string { - if c == nil || c.Text == nil { - return "" - } - return *c.Text -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (c *CheckRunOutput) GetTitle() string { - if c == nil || c.Title == nil { - return "" - } - return *c.Title -} - -// GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetAfterSHA() string { - if c == nil || c.AfterSHA == nil { - return "" - } - return *c.AfterSHA -} - -// GetApp returns the App field. -func (c *CheckSuite) GetApp() *App { - if c == nil { - return nil - } - return c.App -} - -// GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetBeforeSHA() string { - if c == nil || c.BeforeSHA == nil { - return "" - } - return *c.BeforeSHA -} - -// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetConclusion() string { - if c == nil || c.Conclusion == nil { - return "" - } - return *c.Conclusion -} - -// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetHeadBranch() string { - if c == nil || c.HeadBranch == nil { - return "" - } - return *c.HeadBranch -} - -// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetHeadSHA() string { - if c == nil || c.HeadSHA == nil { - return "" - } - return *c.HeadSHA -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetID() int64 { - if c == nil || c.ID == nil { - return 0 - } - return *c.ID -} - -// GetRepository returns the Repository field. -func (c *CheckSuite) GetRepository() *Repository { - if c == nil { - return nil - } - return c.Repository -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetStatus() string { - if c == nil || c.Status == nil { - return "" - } - return *c.Status -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (c *CheckSuiteEvent) GetAction() string { - if c == nil || c.Action == nil { - return "" - } - return *c.Action -} - -// GetCheckSuite returns the CheckSuite field. -func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite { - if c == nil { - return nil - } - return c.CheckSuite -} - -// GetInstallation returns the Installation field. -func (c *CheckSuiteEvent) GetInstallation() *Installation { - if c == nil { - return nil - } - return c.Installation -} - -// GetOrg returns the Org field. -func (c *CheckSuiteEvent) GetOrg() *Organization { - if c == nil { - return nil - } - return c.Org -} - -// GetRepo returns the Repo field. -func (c *CheckSuiteEvent) GetRepo() *Repository { - if c == nil { - return nil - } - return c.Repo -} - -// GetSender returns the Sender field. -func (c *CheckSuiteEvent) GetSender() *User { - if c == nil { - return nil - } - return c.Sender -} - -// GetPreferenceList returns the PreferenceList field. -func (c *CheckSuitePreferenceOptions) GetPreferenceList() *PreferenceList { - if c == nil { - return nil - } - return c.PreferenceList -} - -// GetPreferences returns the Preferences field. -func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList { - if c == nil { - return nil - } - return c.Preferences -} - -// GetRepository returns the Repository field. -func (c *CheckSuitePreferenceResults) GetRepository() *Repository { - if c == nil { - return nil - } - return c.Repository -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (c *CodeOfConduct) GetBody() string { - if c == nil || c.Body == nil { - return "" - } - return *c.Body -} - -// GetKey returns the Key field if it's non-nil, zero value otherwise. -func (c *CodeOfConduct) GetKey() string { - if c == nil || c.Key == nil { - return "" - } - return *c.Key -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *CodeOfConduct) GetName() string { - if c == nil || c.Name == nil { - return "" - } - return *c.Name -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *CodeOfConduct) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *CodeResult) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *CodeResult) GetName() string { - if c == nil || c.Name == nil { - return "" - } - return *c.Name -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (c *CodeResult) GetPath() string { - if c == nil || c.Path == nil { - return "" - } - return *c.Path -} - -// GetRepository returns the Repository field. -func (c *CodeResult) GetRepository() *Repository { - if c == nil { - return nil - } - return c.Repository -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (c *CodeResult) GetSHA() string { - if c == nil || c.SHA == nil { - return "" - } - return *c.SHA -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (c *CodeSearchResult) GetIncompleteResults() bool { - if c == nil || c.IncompleteResults == nil { - return false - } - return *c.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (c *CodeSearchResult) GetTotal() int { - if c == nil || c.Total == nil { - return 0 - } - return *c.Total -} - -// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetCommitURL() string { - if c == nil || c.CommitURL == nil { - return "" - } - return *c.CommitURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetName() string { - if c == nil || c.Name == nil { - return "" - } - return *c.Name -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetRepositoryURL() string { - if c == nil || c.RepositoryURL == nil { - return "" - } - return *c.RepositoryURL -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetSHA() string { - if c == nil || c.SHA == nil { - return "" - } - return *c.SHA -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetState() string { - if c == nil || c.State == nil { - return "" - } - return *c.State -} - -// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. -func (c *CombinedStatus) GetTotalCount() int { - if c == nil || c.TotalCount == nil { - return 0 - } - return *c.TotalCount -} - -// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. -func (c *CommentStats) GetTotalCommitComments() int { - if c == nil || c.TotalCommitComments == nil { - return 0 - } - return *c.TotalCommitComments -} - -// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. -func (c *CommentStats) GetTotalGistComments() int { - if c == nil || c.TotalGistComments == nil { - return 0 - } - return *c.TotalGistComments -} - -// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. -func (c *CommentStats) GetTotalIssueComments() int { - if c == nil || c.TotalIssueComments == nil { - return 0 - } - return *c.TotalIssueComments -} - -// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. -func (c *CommentStats) GetTotalPullRequestComments() int { - if c == nil || c.TotalPullRequestComments == nil { - return 0 - } - return *c.TotalPullRequestComments -} - -// GetAuthor returns the Author field. -func (c *Commit) GetAuthor() *CommitAuthor { - if c == nil { - return nil - } - return c.Author -} - -// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. -func (c *Commit) GetCommentCount() int { - if c == nil || c.CommentCount == nil { - return 0 - } - return *c.CommentCount -} - -// GetCommitter returns the Committer field. -func (c *Commit) GetCommitter() *CommitAuthor { - if c == nil { - return nil - } - return c.Committer -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *Commit) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (c *Commit) GetMessage() string { - if c == nil || c.Message == nil { - return "" - } - return *c.Message -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (c *Commit) GetNodeID() string { - if c == nil || c.NodeID == nil { - return "" - } - return *c.NodeID -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (c *Commit) GetSHA() string { - if c == nil || c.SHA == nil { - return "" - } - return *c.SHA -} - -// GetStats returns the Stats field. -func (c *Commit) GetStats() *CommitStats { - if c == nil { - return nil - } - return c.Stats -} - -// GetTree returns the Tree field. -func (c *Commit) GetTree() *Tree { - if c == nil { - return nil - } - return c.Tree -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *Commit) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetVerification returns the Verification field. -func (c *Commit) GetVerification() *SignatureVerification { - if c == nil { - return nil - } - return c.Verification -} - -// GetDate returns the Date field if it's non-nil, zero value otherwise. -func (c *CommitAuthor) GetDate() time.Time { - if c == nil || c.Date == nil { - return time.Time{} - } - return *c.Date -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (c *CommitAuthor) GetEmail() string { - if c == nil || c.Email == nil { - return "" - } - return *c.Email -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (c *CommitAuthor) GetLogin() string { - if c == nil || c.Login == nil { - return "" - } - return *c.Login -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *CommitAuthor) GetName() string { - if c == nil || c.Name == nil { - return "" - } - return *c.Name -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (c *CommitCommentEvent) GetAction() string { - if c == nil || c.Action == nil { - return "" - } - return *c.Action -} - -// GetComment returns the Comment field. -func (c *CommitCommentEvent) GetComment() *RepositoryComment { - if c == nil { - return nil - } - return c.Comment -} - -// GetInstallation returns the Installation field. -func (c *CommitCommentEvent) GetInstallation() *Installation { - if c == nil { - return nil - } - return c.Installation -} - -// GetRepo returns the Repo field. -func (c *CommitCommentEvent) GetRepo() *Repository { - if c == nil { - return nil - } - return c.Repo -} - -// GetSender returns the Sender field. -func (c *CommitCommentEvent) GetSender() *User { - if c == nil { - return nil - } - return c.Sender -} - -// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetAdditions() int { - if c == nil || c.Additions == nil { - return 0 - } - return *c.Additions -} - -// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetBlobURL() string { - if c == nil || c.BlobURL == nil { - return "" - } - return *c.BlobURL -} - -// GetChanges returns the Changes field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetChanges() int { - if c == nil || c.Changes == nil { - return 0 - } - return *c.Changes -} - -// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetContentsURL() string { - if c == nil || c.ContentsURL == nil { - return "" - } - return *c.ContentsURL -} - -// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetDeletions() int { - if c == nil || c.Deletions == nil { - return 0 - } - return *c.Deletions -} - -// GetFilename returns the Filename field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetFilename() string { - if c == nil || c.Filename == nil { - return "" - } - return *c.Filename -} - -// GetPatch returns the Patch field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetPatch() string { - if c == nil || c.Patch == nil { - return "" - } - return *c.Patch -} - -// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetRawURL() string { - if c == nil || c.RawURL == nil { - return "" - } - return *c.RawURL -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetSHA() string { - if c == nil || c.SHA == nil { - return "" - } - return *c.SHA -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (c *CommitFile) GetStatus() string { - if c == nil || c.Status == nil { - return "" - } - return *c.Status -} - -// GetAuthor returns the Author field. -func (c *CommitResult) GetAuthor() *User { - if c == nil { - return nil - } - return c.Author -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (c *CommitResult) GetCommentsURL() string { - if c == nil || c.CommentsURL == nil { - return "" - } - return *c.CommentsURL -} - -// GetCommit returns the Commit field. -func (c *CommitResult) GetCommit() *Commit { - if c == nil { - return nil - } - return c.Commit -} - -// GetCommitter returns the Committer field. -func (c *CommitResult) GetCommitter() *User { - if c == nil { - return nil - } - return c.Committer -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *CommitResult) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetRepository returns the Repository field. -func (c *CommitResult) GetRepository() *Repository { - if c == nil { - return nil - } - return c.Repository -} - -// GetScore returns the Score field. -func (c *CommitResult) GetScore() *float64 { - if c == nil { - return nil - } - return c.Score -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (c *CommitResult) GetSHA() string { - if c == nil || c.SHA == nil { - return "" - } - return *c.SHA -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *CommitResult) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetAheadBy() int { - if c == nil || c.AheadBy == nil { - return 0 - } - return *c.AheadBy -} - -// GetBaseCommit returns the BaseCommit field. -func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { - if c == nil { - return nil - } - return c.BaseCommit -} - -// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetBehindBy() int { - if c == nil || c.BehindBy == nil { - return 0 - } - return *c.BehindBy -} - -// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetDiffURL() string { - if c == nil || c.DiffURL == nil { - return "" - } - return *c.DiffURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetMergeBaseCommit returns the MergeBaseCommit field. -func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { - if c == nil { - return nil - } - return c.MergeBaseCommit -} - -// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetPatchURL() string { - if c == nil || c.PatchURL == nil { - return "" - } - return *c.PatchURL -} - -// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetPermalinkURL() string { - if c == nil || c.PermalinkURL == nil { - return "" - } - return *c.PermalinkURL -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetStatus() string { - if c == nil || c.Status == nil { - return "" - } - return *c.Status -} - -// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetTotalCommits() int { - if c == nil || c.TotalCommits == nil { - return 0 - } - return *c.TotalCommits -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *CommitsComparison) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (c *CommitsSearchResult) GetIncompleteResults() bool { - if c == nil || c.IncompleteResults == nil { - return false - } - return *c.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (c *CommitsSearchResult) GetTotal() int { - if c == nil || c.Total == nil { - return 0 - } - return *c.Total -} - -// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. -func (c *CommitStats) GetAdditions() int { - if c == nil || c.Additions == nil { - return 0 - } - return *c.Additions -} - -// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. -func (c *CommitStats) GetDeletions() int { - if c == nil || c.Deletions == nil { - return 0 - } - return *c.Deletions -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (c *CommitStats) GetTotal() int { - if c == nil || c.Total == nil { - return 0 - } - return *c.Total -} - -// GetCodeOfConduct returns the CodeOfConduct field. -func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { - if c == nil { - return nil - } - return c.CodeOfConduct -} - -// GetContributing returns the Contributing field. -func (c *CommunityHealthFiles) GetContributing() *Metric { - if c == nil { - return nil - } - return c.Contributing -} - -// GetIssueTemplate returns the IssueTemplate field. -func (c *CommunityHealthFiles) GetIssueTemplate() *Metric { - if c == nil { - return nil - } - return c.IssueTemplate -} - -// GetLicense returns the License field. -func (c *CommunityHealthFiles) GetLicense() *Metric { - if c == nil { - return nil - } - return c.License -} - -// GetPullRequestTemplate returns the PullRequestTemplate field. -func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric { - if c == nil { - return nil - } - return c.PullRequestTemplate -} - -// GetReadme returns the Readme field. -func (c *CommunityHealthFiles) GetReadme() *Metric { - if c == nil { - return nil - } - return c.Readme -} - -// GetFiles returns the Files field. -func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { - if c == nil { - return nil - } - return c.Files -} - -// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. -func (c *CommunityHealthMetrics) GetHealthPercentage() int { - if c == nil || c.HealthPercentage == nil { - return 0 - } - return *c.HealthPercentage -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (c *CommunityHealthMetrics) GetUpdatedAt() time.Time { - if c == nil || c.UpdatedAt == nil { - return time.Time{} - } - return *c.UpdatedAt -} - -// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetAvatarURL() string { - if c == nil || c.AvatarURL == nil { - return "" - } - return *c.AvatarURL -} - -// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. -func (c *Contributor) GetContributions() int { - if c == nil || c.Contributions == nil { - return 0 - } - return *c.Contributions -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetEventsURL() string { - if c == nil || c.EventsURL == nil { - return "" - } - return *c.EventsURL -} - -// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetFollowersURL() string { - if c == nil || c.FollowersURL == nil { - return "" - } - return *c.FollowersURL -} - -// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetFollowingURL() string { - if c == nil || c.FollowingURL == nil { - return "" - } - return *c.FollowingURL -} - -// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetGistsURL() string { - if c == nil || c.GistsURL == nil { - return "" - } - return *c.GistsURL -} - -// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. -func (c *Contributor) GetGravatarID() string { - if c == nil || c.GravatarID == nil { - return "" - } - return *c.GravatarID -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" - } - return *c.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (c *Contributor) GetID() int64 { - if c == nil || c.ID == nil { - return 0 - } - return *c.ID -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (c *Contributor) GetLogin() string { - if c == nil || c.Login == nil { - return "" - } - return *c.Login -} - -// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetOrganizationsURL() string { - if c == nil || c.OrganizationsURL == nil { - return "" - } - return *c.OrganizationsURL -} - -// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetReceivedEventsURL() string { - if c == nil || c.ReceivedEventsURL == nil { - return "" - } - return *c.ReceivedEventsURL -} - -// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetReposURL() string { - if c == nil || c.ReposURL == nil { - return "" - } - return *c.ReposURL -} - -// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. -func (c *Contributor) GetSiteAdmin() bool { - if c == nil || c.SiteAdmin == nil { - return false - } - return *c.SiteAdmin -} - -// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetStarredURL() string { - if c == nil || c.StarredURL == nil { - return "" - } - return *c.StarredURL -} - -// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetSubscriptionsURL() string { - if c == nil || c.SubscriptionsURL == nil { - return "" - } - return *c.SubscriptionsURL -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (c *Contributor) GetType() string { - if c == nil || c.Type == nil { - return "" - } - return *c.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetURL() string { - if c == nil || c.URL == nil { - return "" - } - return *c.URL -} - -// GetAuthor returns the Author field. -func (c *ContributorStats) GetAuthor() *Contributor { - if c == nil { - return nil - } - return c.Author -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (c *ContributorStats) GetTotal() int { - if c == nil || c.Total == nil { - return 0 - } - return *c.Total -} - -// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp { - if c == nil || c.CompletedAt == nil { - return Timestamp{} - } - return *c.CompletedAt -} - -// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetConclusion() string { - if c == nil || c.Conclusion == nil { - return "" - } - return *c.Conclusion -} - -// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetDetailsURL() string { - if c == nil || c.DetailsURL == nil { - return "" - } - return *c.DetailsURL -} - -// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetExternalID() string { - if c == nil || c.ExternalID == nil { - return "" - } - return *c.ExternalID -} - -// GetOutput returns the Output field. -func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput { - if c == nil { - return nil - } - return c.Output -} - -// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetStartedAt() Timestamp { - if c == nil || c.StartedAt == nil { - return Timestamp{} - } - return *c.StartedAt -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (c *CreateCheckRunOptions) GetStatus() string { - if c == nil || c.Status == nil { - return "" - } - return *c.Status -} - -// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. -func (c *CreateCheckSuiteOptions) GetHeadBranch() string { - if c == nil || c.HeadBranch == nil { - return "" - } - return *c.HeadBranch -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (c *CreateEvent) GetDescription() string { - if c == nil || c.Description == nil { - return "" - } - return *c.Description -} - -// GetInstallation returns the Installation field. -func (c *CreateEvent) GetInstallation() *Installation { - if c == nil { - return nil - } - return c.Installation -} - -// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. -func (c *CreateEvent) GetMasterBranch() string { - if c == nil || c.MasterBranch == nil { - return "" - } - return *c.MasterBranch -} - -// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. -func (c *CreateEvent) GetPusherType() string { - if c == nil || c.PusherType == nil { - return "" - } - return *c.PusherType -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (c *CreateEvent) GetRef() string { - if c == nil || c.Ref == nil { - return "" - } - return *c.Ref -} - -// GetRefType returns the RefType field if it's non-nil, zero value otherwise. -func (c *CreateEvent) GetRefType() string { - if c == nil || c.RefType == nil { - return "" - } - return *c.RefType -} - -// GetRepo returns the Repo field. -func (c *CreateEvent) GetRepo() *Repository { - if c == nil { - return nil - } - return c.Repo -} - -// GetSender returns the Sender field. -func (c *CreateEvent) GetSender() *User { - if c == nil { - return nil - } - return c.Sender -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (c *CreateOrgInvitationOptions) GetEmail() string { - if c == nil || c.Email == nil { - return "" - } - return *c.Email -} - -// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. -func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { - if c == nil || c.InviteeID == nil { - return 0 - } - return *c.InviteeID -} - -// GetRole returns the Role field if it's non-nil, zero value otherwise. -func (c *CreateOrgInvitationOptions) GetRole() string { - if c == nil || c.Role == nil { - return "" - } - return *c.Role -} - -// GetInstallation returns the Installation field. -func (d *DeleteEvent) GetInstallation() *Installation { - if d == nil { - return nil - } - return d.Installation -} - -// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. -func (d *DeleteEvent) GetPusherType() string { - if d == nil || d.PusherType == nil { - return "" - } - return *d.PusherType -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (d *DeleteEvent) GetRef() string { - if d == nil || d.Ref == nil { - return "" - } - return *d.Ref -} - -// GetRefType returns the RefType field if it's non-nil, zero value otherwise. -func (d *DeleteEvent) GetRefType() string { - if d == nil || d.RefType == nil { - return "" - } - return *d.RefType -} - -// GetRepo returns the Repo field. -func (d *DeleteEvent) GetRepo() *Repository { - if d == nil { - return nil - } - return d.Repo -} - -// GetSender returns the Sender field. -func (d *DeleteEvent) GetSender() *User { - if d == nil { - return nil - } - return d.Sender -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (d *Deployment) GetCreatedAt() Timestamp { - if d == nil || d.CreatedAt == nil { - return Timestamp{} - } - return *d.CreatedAt -} - -// GetCreator returns the Creator field. -func (d *Deployment) GetCreator() *User { - if d == nil { - return nil - } - return d.Creator -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (d *Deployment) GetDescription() string { - if d == nil || d.Description == nil { - return "" - } - return *d.Description -} - -// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. -func (d *Deployment) GetEnvironment() string { - if d == nil || d.Environment == nil { - return "" - } - return *d.Environment -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (d *Deployment) GetID() int64 { - if d == nil || d.ID == nil { - return 0 - } - return *d.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (d *Deployment) GetNodeID() string { - if d == nil || d.NodeID == nil { - return "" - } - return *d.NodeID -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (d *Deployment) GetRef() string { - if d == nil || d.Ref == nil { - return "" - } - return *d.Ref -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (d *Deployment) GetRepositoryURL() string { - if d == nil || d.RepositoryURL == nil { - return "" - } - return *d.RepositoryURL -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (d *Deployment) GetSHA() string { - if d == nil || d.SHA == nil { - return "" - } - return *d.SHA -} - -// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. -func (d *Deployment) GetStatusesURL() string { - if d == nil || d.StatusesURL == nil { - return "" - } - return *d.StatusesURL -} - -// GetTask returns the Task field if it's non-nil, zero value otherwise. -func (d *Deployment) GetTask() string { - if d == nil || d.Task == nil { - return "" - } - return *d.Task -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (d *Deployment) GetUpdatedAt() Timestamp { - if d == nil || d.UpdatedAt == nil { - return Timestamp{} - } - return *d.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (d *Deployment) GetURL() string { - if d == nil || d.URL == nil { - return "" - } - return *d.URL -} - -// GetDeployment returns the Deployment field. -func (d *DeploymentEvent) GetDeployment() *Deployment { - if d == nil { - return nil - } - return d.Deployment -} - -// GetInstallation returns the Installation field. -func (d *DeploymentEvent) GetInstallation() *Installation { - if d == nil { - return nil - } - return d.Installation -} - -// GetRepo returns the Repo field. -func (d *DeploymentEvent) GetRepo() *Repository { - if d == nil { - return nil - } - return d.Repo -} - -// GetSender returns the Sender field. -func (d *DeploymentEvent) GetSender() *User { - if d == nil { - return nil - } - return d.Sender -} - -// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetAutoMerge() bool { - if d == nil || d.AutoMerge == nil { - return false - } - return *d.AutoMerge -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetDescription() string { - if d == nil || d.Description == nil { - return "" - } - return *d.Description -} - -// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetEnvironment() string { - if d == nil || d.Environment == nil { - return "" - } - return *d.Environment -} - -// GetPayload returns the Payload field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetPayload() string { - if d == nil || d.Payload == nil { - return "" - } - return *d.Payload -} - -// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetProductionEnvironment() bool { - if d == nil || d.ProductionEnvironment == nil { - return false - } - return *d.ProductionEnvironment -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetRef() string { - if d == nil || d.Ref == nil { - return "" - } - return *d.Ref -} - -// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetRequiredContexts() []string { - if d == nil || d.RequiredContexts == nil { - return nil - } - return *d.RequiredContexts -} - -// GetTask returns the Task field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetTask() string { - if d == nil || d.Task == nil { - return "" - } - return *d.Task -} - -// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. -func (d *DeploymentRequest) GetTransientEnvironment() bool { - if d == nil || d.TransientEnvironment == nil { - return false - } - return *d.TransientEnvironment -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetCreatedAt() Timestamp { - if d == nil || d.CreatedAt == nil { - return Timestamp{} - } - return *d.CreatedAt -} - -// GetCreator returns the Creator field. -func (d *DeploymentStatus) GetCreator() *User { - if d == nil { - return nil - } - return d.Creator -} - -// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetDeploymentURL() string { - if d == nil || d.DeploymentURL == nil { - return "" - } - return *d.DeploymentURL -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetDescription() string { - if d == nil || d.Description == nil { - return "" - } - return *d.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetID() int64 { - if d == nil || d.ID == nil { - return 0 - } - return *d.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetNodeID() string { - if d == nil || d.NodeID == nil { - return "" - } - return *d.NodeID -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetRepositoryURL() string { - if d == nil || d.RepositoryURL == nil { - return "" - } - return *d.RepositoryURL -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetState() string { - if d == nil || d.State == nil { - return "" - } - return *d.State -} - -// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetTargetURL() string { - if d == nil || d.TargetURL == nil { - return "" - } - return *d.TargetURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (d *DeploymentStatus) GetUpdatedAt() Timestamp { - if d == nil || d.UpdatedAt == nil { - return Timestamp{} - } - return *d.UpdatedAt -} - -// GetDeployment returns the Deployment field. -func (d *DeploymentStatusEvent) GetDeployment() *Deployment { - if d == nil { - return nil - } - return d.Deployment -} - -// GetDeploymentStatus returns the DeploymentStatus field. -func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { - if d == nil { - return nil - } - return d.DeploymentStatus -} - -// GetInstallation returns the Installation field. -func (d *DeploymentStatusEvent) GetInstallation() *Installation { - if d == nil { - return nil - } - return d.Installation -} - -// GetRepo returns the Repo field. -func (d *DeploymentStatusEvent) GetRepo() *Repository { - if d == nil { - return nil - } - return d.Repo -} - -// GetSender returns the Sender field. -func (d *DeploymentStatusEvent) GetSender() *User { - if d == nil { - return nil - } - return d.Sender -} - -// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. -func (d *DeploymentStatusRequest) GetAutoInactive() bool { - if d == nil || d.AutoInactive == nil { - return false - } - return *d.AutoInactive -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (d *DeploymentStatusRequest) GetDescription() string { - if d == nil || d.Description == nil { - return "" - } - return *d.Description -} - -// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. -func (d *DeploymentStatusRequest) GetEnvironmentURL() string { - if d == nil || d.EnvironmentURL == nil { - return "" - } - return *d.EnvironmentURL -} - -// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. -func (d *DeploymentStatusRequest) GetLogURL() string { - if d == nil || d.LogURL == nil { - return "" - } - return *d.LogURL -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (d *DeploymentStatusRequest) GetState() string { - if d == nil || d.State == nil { - return "" - } - return *d.State -} - -// GetAuthor returns the Author field. -func (d *DiscussionComment) GetAuthor() *User { - if d == nil { - return nil - } - return d.Author -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetBody() string { - if d == nil || d.Body == nil { - return "" - } - return *d.Body -} - -// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetBodyHTML() string { - if d == nil || d.BodyHTML == nil { - return "" - } - return *d.BodyHTML -} - -// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetBodyVersion() string { - if d == nil || d.BodyVersion == nil { - return "" - } - return *d.BodyVersion -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetCreatedAt() Timestamp { - if d == nil || d.CreatedAt == nil { - return Timestamp{} - } - return *d.CreatedAt -} - -// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetDiscussionURL() string { - if d == nil || d.DiscussionURL == nil { - return "" - } - return *d.DiscussionURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetHTMLURL() string { - if d == nil || d.HTMLURL == nil { - return "" - } - return *d.HTMLURL -} - -// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetLastEditedAt() Timestamp { - if d == nil || d.LastEditedAt == nil { - return Timestamp{} - } - return *d.LastEditedAt -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetNodeID() string { - if d == nil || d.NodeID == nil { - return "" - } - return *d.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetNumber() int { - if d == nil || d.Number == nil { - return 0 - } - return *d.Number -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetUpdatedAt() Timestamp { - if d == nil || d.UpdatedAt == nil { - return Timestamp{} - } - return *d.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (d *DiscussionComment) GetURL() string { - if d == nil || d.URL == nil { - return "" - } - return *d.URL -} - -// GetTeams returns the Teams field if it's non-nil, zero value otherwise. -func (d *DismissalRestrictionsRequest) GetTeams() []string { - if d == nil || d.Teams == nil { - return nil - } - return *d.Teams -} - -// GetUsers returns the Users field if it's non-nil, zero value otherwise. -func (d *DismissalRestrictionsRequest) GetUsers() []string { - if d == nil || d.Users == nil { - return nil - } - return *d.Users -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (d *DraftReviewComment) GetBody() string { - if d == nil || d.Body == nil { - return "" - } - return *d.Body -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (d *DraftReviewComment) GetPath() string { - if d == nil || d.Path == nil { - return "" - } - return *d.Path -} - -// GetPosition returns the Position field if it's non-nil, zero value otherwise. -func (d *DraftReviewComment) GetPosition() int { - if d == nil || d.Position == nil { - return 0 - } - return *d.Position -} - -// GetActor returns the Actor field. -func (e *Event) GetActor() *User { - if e == nil { - return nil - } - return e.Actor -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (e *Event) GetCreatedAt() time.Time { - if e == nil || e.CreatedAt == nil { - return time.Time{} - } - return *e.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (e *Event) GetID() string { - if e == nil || e.ID == nil { - return "" - } - return *e.ID -} - -// GetOrg returns the Org field. -func (e *Event) GetOrg() *Organization { - if e == nil { - return nil - } - return e.Org -} - -// GetPublic returns the Public field if it's non-nil, zero value otherwise. -func (e *Event) GetPublic() bool { - if e == nil || e.Public == nil { - return false - } - return *e.Public -} - -// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. -func (e *Event) GetRawPayload() json.RawMessage { - if e == nil || e.RawPayload == nil { - return json.RawMessage{} - } - return *e.RawPayload -} - -// GetRepo returns the Repo field. -func (e *Event) GetRepo() *Repository { - if e == nil { - return nil - } - return e.Repo -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (e *Event) GetType() string { - if e == nil || e.Type == nil { - return "" - } - return *e.Type -} - -// GetHRef returns the HRef field if it's non-nil, zero value otherwise. -func (f *FeedLink) GetHRef() string { - if f == nil || f.HRef == nil { - return "" - } - return *f.HRef -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (f *FeedLink) GetType() string { - if f == nil || f.Type == nil { - return "" - } - return *f.Type -} - -// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetCurrentUserActorURL() string { - if f == nil || f.CurrentUserActorURL == nil { - return "" - } - return *f.CurrentUserActorURL -} - -// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetCurrentUserOrganizationURL() string { - if f == nil || f.CurrentUserOrganizationURL == nil { - return "" - } - return *f.CurrentUserOrganizationURL -} - -// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetCurrentUserPublicURL() string { - if f == nil || f.CurrentUserPublicURL == nil { - return "" - } - return *f.CurrentUserPublicURL -} - -// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetCurrentUserURL() string { - if f == nil || f.CurrentUserURL == nil { - return "" - } - return *f.CurrentUserURL -} - -// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetTimelineURL() string { - if f == nil || f.TimelineURL == nil { - return "" - } - return *f.TimelineURL -} - -// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. -func (f *Feeds) GetUserURL() string { - if f == nil || f.UserURL == nil { - return "" - } - return *f.UserURL -} - -// GetForkee returns the Forkee field. -func (f *ForkEvent) GetForkee() *Repository { - if f == nil { - return nil - } - return f.Forkee -} - -// GetInstallation returns the Installation field. -func (f *ForkEvent) GetInstallation() *Installation { - if f == nil { - return nil - } - return f.Installation -} - -// GetRepo returns the Repo field. -func (f *ForkEvent) GetRepo() *Repository { - if f == nil { - return nil - } - return f.Repo -} - -// GetSender returns the Sender field. -func (f *ForkEvent) GetSender() *User { - if f == nil { - return nil - } - return f.Sender -} - -// GetComments returns the Comments field if it's non-nil, zero value otherwise. -func (g *Gist) GetComments() int { - if g == nil || g.Comments == nil { - return 0 - } - return *g.Comments -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (g *Gist) GetCreatedAt() time.Time { - if g == nil || g.CreatedAt == nil { - return time.Time{} - } - return *g.CreatedAt -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (g *Gist) GetDescription() string { - if g == nil || g.Description == nil { - return "" - } - return *g.Description -} - -// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. -func (g *Gist) GetGitPullURL() string { - if g == nil || g.GitPullURL == nil { - return "" - } - return *g.GitPullURL -} - -// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. -func (g *Gist) GetGitPushURL() string { - if g == nil || g.GitPushURL == nil { - return "" - } - return *g.GitPushURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (g *Gist) GetHTMLURL() string { - if g == nil || g.HTMLURL == nil { - return "" - } - return *g.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (g *Gist) GetID() string { - if g == nil || g.ID == nil { - return "" - } - return *g.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (g *Gist) GetNodeID() string { - if g == nil || g.NodeID == nil { - return "" - } - return *g.NodeID -} - -// GetOwner returns the Owner field. -func (g *Gist) GetOwner() *User { - if g == nil { - return nil - } - return g.Owner -} - -// GetPublic returns the Public field if it's non-nil, zero value otherwise. -func (g *Gist) GetPublic() bool { - if g == nil || g.Public == nil { - return false - } - return *g.Public -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (g *Gist) GetUpdatedAt() time.Time { - if g == nil || g.UpdatedAt == nil { - return time.Time{} - } - return *g.UpdatedAt -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (g *GistComment) GetBody() string { - if g == nil || g.Body == nil { - return "" - } - return *g.Body -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (g *GistComment) GetCreatedAt() time.Time { - if g == nil || g.CreatedAt == nil { - return time.Time{} - } - return *g.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (g *GistComment) GetID() int64 { - if g == nil || g.ID == nil { - return 0 - } - return *g.ID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (g *GistComment) GetURL() string { - if g == nil || g.URL == nil { - return "" - } - return *g.URL -} - -// GetUser returns the User field. -func (g *GistComment) GetUser() *User { - if g == nil { - return nil - } - return g.User -} - -// GetChangeStatus returns the ChangeStatus field. -func (g *GistCommit) GetChangeStatus() *CommitStats { - if g == nil { - return nil - } - return g.ChangeStatus -} - -// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. -func (g *GistCommit) GetCommittedAt() Timestamp { - if g == nil || g.CommittedAt == nil { - return Timestamp{} - } - return *g.CommittedAt -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (g *GistCommit) GetNodeID() string { - if g == nil || g.NodeID == nil { - return "" - } - return *g.NodeID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (g *GistCommit) GetURL() string { - if g == nil || g.URL == nil { - return "" - } - return *g.URL -} - -// GetUser returns the User field. -func (g *GistCommit) GetUser() *User { - if g == nil { - return nil - } - return g.User -} - -// GetVersion returns the Version field if it's non-nil, zero value otherwise. -func (g *GistCommit) GetVersion() string { - if g == nil || g.Version == nil { - return "" - } - return *g.Version -} - -// GetContent returns the Content field if it's non-nil, zero value otherwise. -func (g *GistFile) GetContent() string { - if g == nil || g.Content == nil { - return "" - } - return *g.Content -} - -// GetFilename returns the Filename field if it's non-nil, zero value otherwise. -func (g *GistFile) GetFilename() string { - if g == nil || g.Filename == nil { - return "" - } - return *g.Filename -} - -// GetLanguage returns the Language field if it's non-nil, zero value otherwise. -func (g *GistFile) GetLanguage() string { - if g == nil || g.Language == nil { - return "" - } - return *g.Language -} - -// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. -func (g *GistFile) GetRawURL() string { - if g == nil || g.RawURL == nil { - return "" - } - return *g.RawURL -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (g *GistFile) GetSize() int { - if g == nil || g.Size == nil { - return 0 - } - return *g.Size -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (g *GistFile) GetType() string { - if g == nil || g.Type == nil { - return "" - } - return *g.Type -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (g *GistFork) GetCreatedAt() Timestamp { - if g == nil || g.CreatedAt == nil { - return Timestamp{} - } - return *g.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (g *GistFork) GetID() string { - if g == nil || g.ID == nil { - return "" - } - return *g.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (g *GistFork) GetNodeID() string { - if g == nil || g.NodeID == nil { - return "" - } - return *g.NodeID -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (g *GistFork) GetUpdatedAt() Timestamp { - if g == nil || g.UpdatedAt == nil { - return Timestamp{} - } - return *g.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (g *GistFork) GetURL() string { - if g == nil || g.URL == nil { - return "" - } - return *g.URL -} - -// GetUser returns the User field. -func (g *GistFork) GetUser() *User { - if g == nil { - return nil - } - return g.User -} - -// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. -func (g *GistStats) GetPrivateGists() int { - if g == nil || g.PrivateGists == nil { - return 0 - } - return *g.PrivateGists -} - -// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. -func (g *GistStats) GetPublicGists() int { - if g == nil || g.PublicGists == nil { - return 0 - } - return *g.PublicGists -} - -// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. -func (g *GistStats) GetTotalGists() int { - if g == nil || g.TotalGists == nil { - return 0 - } - return *g.TotalGists -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (g *Gitignore) GetName() string { - if g == nil || g.Name == nil { - return "" - } - return *g.Name -} - -// GetSource returns the Source field if it's non-nil, zero value otherwise. -func (g *Gitignore) GetSource() string { - if g == nil || g.Source == nil { - return "" - } - return *g.Source -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (g *GitObject) GetSHA() string { - if g == nil || g.SHA == nil { - return "" - } - return *g.SHA -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (g *GitObject) GetType() string { - if g == nil || g.Type == nil { - return "" - } - return *g.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (g *GitObject) GetURL() string { - if g == nil || g.URL == nil { - return "" - } - return *g.URL -} - -// GetInstallation returns the Installation field. -func (g *GollumEvent) GetInstallation() *Installation { - if g == nil { - return nil - } - return g.Installation -} - -// GetRepo returns the Repo field. -func (g *GollumEvent) GetRepo() *Repository { - if g == nil { - return nil - } - return g.Repo -} - -// GetSender returns the Sender field. -func (g *GollumEvent) GetSender() *User { - if g == nil { - return nil - } - return g.Sender -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (g *GPGEmail) GetEmail() string { - if g == nil || g.Email == nil { - return "" - } - return *g.Email -} - -// GetVerified returns the Verified field if it's non-nil, zero value otherwise. -func (g *GPGEmail) GetVerified() bool { - if g == nil || g.Verified == nil { - return false - } - return *g.Verified -} - -// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetCanCertify() bool { - if g == nil || g.CanCertify == nil { - return false - } - return *g.CanCertify -} - -// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetCanEncryptComms() bool { - if g == nil || g.CanEncryptComms == nil { - return false - } - return *g.CanEncryptComms -} - -// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetCanEncryptStorage() bool { - if g == nil || g.CanEncryptStorage == nil { - return false - } - return *g.CanEncryptStorage -} - -// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetCanSign() bool { - if g == nil || g.CanSign == nil { - return false - } - return *g.CanSign -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetCreatedAt() time.Time { - if g == nil || g.CreatedAt == nil { - return time.Time{} - } - return *g.CreatedAt -} - -// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetExpiresAt() time.Time { - if g == nil || g.ExpiresAt == nil { - return time.Time{} - } - return *g.ExpiresAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetID() int64 { - if g == nil || g.ID == nil { - return 0 - } - return *g.ID -} - -// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetKeyID() string { - if g == nil || g.KeyID == nil { - return "" - } - return *g.KeyID -} - -// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetPrimaryKeyID() int64 { - if g == nil || g.PrimaryKeyID == nil { - return 0 - } - return *g.PrimaryKeyID -} - -// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. -func (g *GPGKey) GetPublicKey() string { - if g == nil || g.PublicKey == nil { - return "" - } - return *g.PublicKey -} - -// GetApp returns the App field. -func (g *Grant) GetApp() *AuthorizationApp { - if g == nil { - return nil - } - return g.App -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (g *Grant) GetCreatedAt() Timestamp { - if g == nil || g.CreatedAt == nil { - return Timestamp{} - } - return *g.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (g *Grant) GetID() int64 { - if g == nil || g.ID == nil { - return 0 - } - return *g.ID -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (g *Grant) GetUpdatedAt() Timestamp { - if g == nil || g.UpdatedAt == nil { - return Timestamp{} - } - return *g.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (g *Grant) GetURL() string { - if g == nil || g.URL == nil { - return "" - } - return *g.URL -} - -// GetActive returns the Active field if it's non-nil, zero value otherwise. -func (h *Hook) GetActive() bool { - if h == nil || h.Active == nil { - return false - } - return *h.Active -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (h *Hook) GetCreatedAt() time.Time { - if h == nil || h.CreatedAt == nil { - return time.Time{} - } - return *h.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (h *Hook) GetID() int64 { - if h == nil || h.ID == nil { - return 0 - } - return *h.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (h *Hook) GetName() string { - if h == nil || h.Name == nil { - return "" - } - return *h.Name -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (h *Hook) GetUpdatedAt() time.Time { - if h == nil || h.UpdatedAt == nil { - return time.Time{} - } - return *h.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (h *Hook) GetURL() string { - if h == nil || h.URL == nil { - return "" - } - return *h.URL -} - -// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. -func (h *HookStats) GetActiveHooks() int { - if h == nil || h.ActiveHooks == nil { - return 0 - } - return *h.ActiveHooks -} - -// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. -func (h *HookStats) GetInactiveHooks() int { - if h == nil || h.InactiveHooks == nil { - return 0 - } - return *h.InactiveHooks -} - -// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. -func (h *HookStats) GetTotalHooks() int { - if h == nil || h.TotalHooks == nil { - return 0 - } - return *h.TotalHooks -} - -// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. -func (i *Import) GetAuthorsCount() int { - if i == nil || i.AuthorsCount == nil { - return 0 - } - return *i.AuthorsCount -} - -// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. -func (i *Import) GetAuthorsURL() string { - if i == nil || i.AuthorsURL == nil { - return "" - } - return *i.AuthorsURL -} - -// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. -func (i *Import) GetCommitCount() int { - if i == nil || i.CommitCount == nil { - return 0 - } - return *i.CommitCount -} - -// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. -func (i *Import) GetFailedStep() string { - if i == nil || i.FailedStep == nil { - return "" - } - return *i.FailedStep -} - -// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. -func (i *Import) GetHasLargeFiles() bool { - if i == nil || i.HasLargeFiles == nil { - return false - } - return *i.HasLargeFiles -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (i *Import) GetHTMLURL() string { - if i == nil || i.HTMLURL == nil { - return "" - } - return *i.HTMLURL -} - -// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. -func (i *Import) GetHumanName() string { - if i == nil || i.HumanName == nil { - return "" - } - return *i.HumanName -} - -// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. -func (i *Import) GetLargeFilesCount() int { - if i == nil || i.LargeFilesCount == nil { - return 0 - } - return *i.LargeFilesCount -} - -// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. -func (i *Import) GetLargeFilesSize() int { - if i == nil || i.LargeFilesSize == nil { - return 0 - } - return *i.LargeFilesSize -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (i *Import) GetMessage() string { - if i == nil || i.Message == nil { - return "" - } - return *i.Message -} - -// GetPercent returns the Percent field if it's non-nil, zero value otherwise. -func (i *Import) GetPercent() int { - if i == nil || i.Percent == nil { - return 0 - } - return *i.Percent -} - -// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. -func (i *Import) GetPushPercent() int { - if i == nil || i.PushPercent == nil { - return 0 - } - return *i.PushPercent -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (i *Import) GetRepositoryURL() string { - if i == nil || i.RepositoryURL == nil { - return "" - } - return *i.RepositoryURL -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (i *Import) GetStatus() string { - if i == nil || i.Status == nil { - return "" - } - return *i.Status -} - -// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. -func (i *Import) GetStatusText() string { - if i == nil || i.StatusText == nil { - return "" - } - return *i.StatusText -} - -// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. -func (i *Import) GetTFVCProject() string { - if i == nil || i.TFVCProject == nil { - return "" - } - return *i.TFVCProject -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (i *Import) GetURL() string { - if i == nil || i.URL == nil { - return "" - } - return *i.URL -} - -// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. -func (i *Import) GetUseLFS() string { - if i == nil || i.UseLFS == nil { - return "" - } - return *i.UseLFS -} - -// GetVCS returns the VCS field if it's non-nil, zero value otherwise. -func (i *Import) GetVCS() string { - if i == nil || i.VCS == nil { - return "" - } - return *i.VCS -} - -// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. -func (i *Import) GetVCSPassword() string { - if i == nil || i.VCSPassword == nil { - return "" - } - return *i.VCSPassword -} - -// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. -func (i *Import) GetVCSURL() string { - if i == nil || i.VCSURL == nil { - return "" - } - return *i.VCSURL -} - -// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. -func (i *Import) GetVCSUsername() string { - if i == nil || i.VCSUsername == nil { - return "" - } - return *i.VCSUsername -} - -// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. -func (i *Installation) GetAccessTokensURL() string { - if i == nil || i.AccessTokensURL == nil { - return "" - } - return *i.AccessTokensURL -} - -// GetAccount returns the Account field. -func (i *Installation) GetAccount() *User { - if i == nil { - return nil - } - return i.Account -} - -// GetAppID returns the AppID field if it's non-nil, zero value otherwise. -func (i *Installation) GetAppID() int64 { - if i == nil || i.AppID == nil { - return 0 - } - return *i.AppID -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (i *Installation) GetCreatedAt() Timestamp { - if i == nil || i.CreatedAt == nil { - return Timestamp{} - } - return *i.CreatedAt -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (i *Installation) GetHTMLURL() string { - if i == nil || i.HTMLURL == nil { - return "" - } - return *i.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (i *Installation) GetID() int64 { - if i == nil || i.ID == nil { - return 0 - } - return *i.ID -} - -// GetPermissions returns the Permissions field. -func (i *Installation) GetPermissions() *InstallationPermissions { - if i == nil { - return nil - } - return i.Permissions -} - -// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. -func (i *Installation) GetRepositoriesURL() string { - if i == nil || i.RepositoriesURL == nil { - return "" - } - return *i.RepositoriesURL -} - -// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. -func (i *Installation) GetRepositorySelection() string { - if i == nil || i.RepositorySelection == nil { - return "" - } - return *i.RepositorySelection -} - -// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. -func (i *Installation) GetSingleFileName() string { - if i == nil || i.SingleFileName == nil { - return "" - } - return *i.SingleFileName -} - -// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. -func (i *Installation) GetTargetID() int64 { - if i == nil || i.TargetID == nil { - return 0 - } - return *i.TargetID -} - -// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. -func (i *Installation) GetTargetType() string { - if i == nil || i.TargetType == nil { - return "" - } - return *i.TargetType -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (i *Installation) GetUpdatedAt() Timestamp { - if i == nil || i.UpdatedAt == nil { - return Timestamp{} - } - return *i.UpdatedAt -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (i *InstallationEvent) GetAction() string { - if i == nil || i.Action == nil { - return "" - } - return *i.Action -} - -// GetInstallation returns the Installation field. -func (i *InstallationEvent) GetInstallation() *Installation { - if i == nil { - return nil - } - return i.Installation -} - -// GetSender returns the Sender field. -func (i *InstallationEvent) GetSender() *User { - if i == nil { - return nil - } - return i.Sender -} - -// GetContents returns the Contents field if it's non-nil, zero value otherwise. -func (i *InstallationPermissions) GetContents() string { - if i == nil || i.Contents == nil { - return "" - } - return *i.Contents -} - -// GetIssues returns the Issues field if it's non-nil, zero value otherwise. -func (i *InstallationPermissions) GetIssues() string { - if i == nil || i.Issues == nil { - return "" - } - return *i.Issues -} - -// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. -func (i *InstallationPermissions) GetMetadata() string { - if i == nil || i.Metadata == nil { - return "" - } - return *i.Metadata -} - -// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. -func (i *InstallationPermissions) GetSingleFile() string { - if i == nil || i.SingleFile == nil { - return "" - } - return *i.SingleFile -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (i *InstallationRepositoriesEvent) GetAction() string { - if i == nil || i.Action == nil { - return "" - } - return *i.Action -} - -// GetInstallation returns the Installation field. -func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { - if i == nil { - return nil - } - return i.Installation -} - -// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. -func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { - if i == nil || i.RepositorySelection == nil { - return "" - } - return *i.RepositorySelection -} - -// GetSender returns the Sender field. -func (i *InstallationRepositoriesEvent) GetSender() *User { - if i == nil { - return nil - } - return i.Sender -} - -// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. -func (i *InstallationToken) GetExpiresAt() time.Time { - if i == nil || i.ExpiresAt == nil { - return time.Time{} - } - return *i.ExpiresAt -} - -// GetToken returns the Token field if it's non-nil, zero value otherwise. -func (i *InstallationToken) GetToken() string { - if i == nil || i.Token == nil { - return "" - } - return *i.Token -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (i *Invitation) GetCreatedAt() time.Time { - if i == nil || i.CreatedAt == nil { - return time.Time{} - } - return *i.CreatedAt -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (i *Invitation) GetEmail() string { - if i == nil || i.Email == nil { - return "" - } - return *i.Email -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (i *Invitation) GetID() int64 { - if i == nil || i.ID == nil { - return 0 - } - return *i.ID -} - -// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. -func (i *Invitation) GetInvitationTeamURL() string { - if i == nil || i.InvitationTeamURL == nil { - return "" - } - return *i.InvitationTeamURL -} - -// GetInviter returns the Inviter field. -func (i *Invitation) GetInviter() *User { - if i == nil { - return nil - } - return i.Inviter -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (i *Invitation) GetLogin() string { - if i == nil || i.Login == nil { - return "" - } - return *i.Login -} - -// GetRole returns the Role field if it's non-nil, zero value otherwise. -func (i *Invitation) GetRole() string { - if i == nil || i.Role == nil { - return "" - } - return *i.Role -} - -// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. -func (i *Invitation) GetTeamCount() int { - if i == nil || i.TeamCount == nil { - return 0 - } - return *i.TeamCount -} - -// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. -func (i *Issue) GetActiveLockReason() string { - if i == nil || i.ActiveLockReason == nil { - return "" - } - return *i.ActiveLockReason -} - -// GetAssignee returns the Assignee field. -func (i *Issue) GetAssignee() *User { - if i == nil { - return nil - } - return i.Assignee -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (i *Issue) GetBody() string { - if i == nil || i.Body == nil { - return "" - } - return *i.Body -} - -// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. -func (i *Issue) GetClosedAt() time.Time { - if i == nil || i.ClosedAt == nil { - return time.Time{} - } - return *i.ClosedAt -} - -// GetClosedBy returns the ClosedBy field. -func (i *Issue) GetClosedBy() *User { - if i == nil { - return nil - } - return i.ClosedBy -} - -// GetComments returns the Comments field if it's non-nil, zero value otherwise. -func (i *Issue) GetComments() int { - if i == nil || i.Comments == nil { - return 0 - } - return *i.Comments -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (i *Issue) GetCommentsURL() string { - if i == nil || i.CommentsURL == nil { - return "" - } - return *i.CommentsURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (i *Issue) GetCreatedAt() time.Time { - if i == nil || i.CreatedAt == nil { - return time.Time{} - } - return *i.CreatedAt -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (i *Issue) GetEventsURL() string { - if i == nil || i.EventsURL == nil { - return "" - } - return *i.EventsURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (i *Issue) GetHTMLURL() string { - if i == nil || i.HTMLURL == nil { - return "" - } - return *i.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (i *Issue) GetID() int64 { - if i == nil || i.ID == nil { - return 0 - } - return *i.ID -} - -// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. -func (i *Issue) GetLabelsURL() string { - if i == nil || i.LabelsURL == nil { - return "" - } - return *i.LabelsURL -} - -// GetLocked returns the Locked field if it's non-nil, zero value otherwise. -func (i *Issue) GetLocked() bool { - if i == nil || i.Locked == nil { - return false - } - return *i.Locked -} - -// GetMilestone returns the Milestone field. -func (i *Issue) GetMilestone() *Milestone { - if i == nil { - return nil - } - return i.Milestone -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (i *Issue) GetNodeID() string { - if i == nil || i.NodeID == nil { - return "" - } - return *i.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (i *Issue) GetNumber() int { - if i == nil || i.Number == nil { - return 0 - } - return *i.Number -} - -// GetPullRequestLinks returns the PullRequestLinks field. -func (i *Issue) GetPullRequestLinks() *PullRequestLinks { - if i == nil { - return nil - } - return i.PullRequestLinks -} - -// GetReactions returns the Reactions field. -func (i *Issue) GetReactions() *Reactions { - if i == nil { - return nil - } - return i.Reactions -} - -// GetRepository returns the Repository field. -func (i *Issue) GetRepository() *Repository { - if i == nil { - return nil - } - return i.Repository -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (i *Issue) GetRepositoryURL() string { - if i == nil || i.RepositoryURL == nil { - return "" - } - return *i.RepositoryURL -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (i *Issue) GetState() string { - if i == nil || i.State == nil { - return "" - } - return *i.State -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (i *Issue) GetTitle() string { - if i == nil || i.Title == nil { - return "" - } - return *i.Title -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (i *Issue) GetUpdatedAt() time.Time { - if i == nil || i.UpdatedAt == nil { - return time.Time{} - } - return *i.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (i *Issue) GetURL() string { - if i == nil || i.URL == nil { - return "" - } - return *i.URL -} - -// GetUser returns the User field. -func (i *Issue) GetUser() *User { - if i == nil { - return nil - } - return i.User -} - -// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetAuthorAssociation() string { - if i == nil || i.AuthorAssociation == nil { - return "" - } - return *i.AuthorAssociation -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetBody() string { - if i == nil || i.Body == nil { - return "" - } - return *i.Body -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetCreatedAt() time.Time { - if i == nil || i.CreatedAt == nil { - return time.Time{} - } - return *i.CreatedAt -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetHTMLURL() string { - if i == nil || i.HTMLURL == nil { - return "" - } - return *i.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetID() int64 { - if i == nil || i.ID == nil { - return 0 - } - return *i.ID -} - -// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetIssueURL() string { - if i == nil || i.IssueURL == nil { - return "" - } - return *i.IssueURL -} - -// GetReactions returns the Reactions field. -func (i *IssueComment) GetReactions() *Reactions { - if i == nil { - return nil - } - return i.Reactions -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetUpdatedAt() time.Time { - if i == nil || i.UpdatedAt == nil { - return time.Time{} - } - return *i.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (i *IssueComment) GetURL() string { - if i == nil || i.URL == nil { - return "" - } - return *i.URL -} - -// GetUser returns the User field. -func (i *IssueComment) GetUser() *User { - if i == nil { - return nil - } - return i.User -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (i *IssueCommentEvent) GetAction() string { - if i == nil || i.Action == nil { - return "" - } - return *i.Action -} - -// GetChanges returns the Changes field. -func (i *IssueCommentEvent) GetChanges() *EditChange { - if i == nil { - return nil - } - return i.Changes -} - -// GetComment returns the Comment field. -func (i *IssueCommentEvent) GetComment() *IssueComment { - if i == nil { - return nil - } - return i.Comment -} - -// GetInstallation returns the Installation field. -func (i *IssueCommentEvent) GetInstallation() *Installation { - if i == nil { - return nil - } - return i.Installation -} - -// GetIssue returns the Issue field. -func (i *IssueCommentEvent) GetIssue() *Issue { - if i == nil { - return nil - } - return i.Issue -} - -// GetRepo returns the Repo field. -func (i *IssueCommentEvent) GetRepo() *Repository { - if i == nil { - return nil - } - return i.Repo -} - -// GetSender returns the Sender field. -func (i *IssueCommentEvent) GetSender() *User { - if i == nil { - return nil - } - return i.Sender -} - -// GetActor returns the Actor field. -func (i *IssueEvent) GetActor() *User { - if i == nil { - return nil - } - return i.Actor -} - -// GetAssignee returns the Assignee field. -func (i *IssueEvent) GetAssignee() *User { - if i == nil { - return nil - } - return i.Assignee -} - -// GetAssigner returns the Assigner field. -func (i *IssueEvent) GetAssigner() *User { - if i == nil { - return nil - } - return i.Assigner -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetCommitID() string { - if i == nil || i.CommitID == nil { - return "" - } - return *i.CommitID -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetCreatedAt() time.Time { - if i == nil || i.CreatedAt == nil { - return time.Time{} - } - return *i.CreatedAt -} - -// GetEvent returns the Event field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetEvent() string { - if i == nil || i.Event == nil { - return "" - } - return *i.Event -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetID() int64 { - if i == nil || i.ID == nil { - return 0 - } - return *i.ID -} - -// GetIssue returns the Issue field. -func (i *IssueEvent) GetIssue() *Issue { - if i == nil { - return nil - } - return i.Issue -} - -// GetLabel returns the Label field. -func (i *IssueEvent) GetLabel() *Label { - if i == nil { - return nil - } - return i.Label -} - -// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetLockReason() string { - if i == nil || i.LockReason == nil { - return "" - } - return *i.LockReason -} - -// GetMilestone returns the Milestone field. -func (i *IssueEvent) GetMilestone() *Milestone { - if i == nil { - return nil - } - return i.Milestone -} - -// GetRename returns the Rename field. -func (i *IssueEvent) GetRename() *Rename { - if i == nil { - return nil - } - return i.Rename -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (i *IssueEvent) GetURL() string { - if i == nil || i.URL == nil { - return "" - } - return *i.URL -} - -// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetAssignee() string { - if i == nil || i.Assignee == nil { - return "" - } - return *i.Assignee -} - -// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetAssignees() []string { - if i == nil || i.Assignees == nil { - return nil - } - return *i.Assignees -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetBody() string { - if i == nil || i.Body == nil { - return "" - } - return *i.Body -} - -// GetLabels returns the Labels field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetLabels() []string { - if i == nil || i.Labels == nil { - return nil - } - return *i.Labels -} - -// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetMilestone() int { - if i == nil || i.Milestone == nil { - return 0 - } - return *i.Milestone -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetState() string { - if i == nil || i.State == nil { - return "" - } - return *i.State -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (i *IssueRequest) GetTitle() string { - if i == nil || i.Title == nil { - return "" - } - return *i.Title -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (i *IssuesEvent) GetAction() string { - if i == nil || i.Action == nil { - return "" - } - return *i.Action -} - -// GetAssignee returns the Assignee field. -func (i *IssuesEvent) GetAssignee() *User { - if i == nil { - return nil - } - return i.Assignee -} - -// GetChanges returns the Changes field. -func (i *IssuesEvent) GetChanges() *EditChange { - if i == nil { - return nil - } - return i.Changes -} - -// GetInstallation returns the Installation field. -func (i *IssuesEvent) GetInstallation() *Installation { - if i == nil { - return nil - } - return i.Installation -} - -// GetIssue returns the Issue field. -func (i *IssuesEvent) GetIssue() *Issue { - if i == nil { - return nil - } - return i.Issue -} - -// GetLabel returns the Label field. -func (i *IssuesEvent) GetLabel() *Label { - if i == nil { - return nil - } - return i.Label -} - -// GetRepo returns the Repo field. -func (i *IssuesEvent) GetRepo() *Repository { - if i == nil { - return nil - } - return i.Repo -} - -// GetSender returns the Sender field. -func (i *IssuesEvent) GetSender() *User { - if i == nil { - return nil - } - return i.Sender -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (i *IssuesSearchResult) GetIncompleteResults() bool { - if i == nil || i.IncompleteResults == nil { - return false - } - return *i.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (i *IssuesSearchResult) GetTotal() int { - if i == nil || i.Total == nil { - return 0 - } - return *i.Total -} - -// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetClosedIssues() int { - if i == nil || i.ClosedIssues == nil { - return 0 - } - return *i.ClosedIssues -} - -// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetOpenIssues() int { - if i == nil || i.OpenIssues == nil { - return 0 - } - return *i.OpenIssues -} - -// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetTotalIssues() int { - if i == nil || i.TotalIssues == nil { - return 0 - } - return *i.TotalIssues -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (k *Key) GetID() int64 { - if k == nil || k.ID == nil { - return 0 - } - return *k.ID -} - -// GetKey returns the Key field if it's non-nil, zero value otherwise. -func (k *Key) GetKey() string { - if k == nil || k.Key == nil { - return "" - } - return *k.Key -} - -// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. -func (k *Key) GetReadOnly() bool { - if k == nil || k.ReadOnly == nil { - return false - } - return *k.ReadOnly -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (k *Key) GetTitle() string { - if k == nil || k.Title == nil { - return "" - } - return *k.Title -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (k *Key) GetURL() string { - if k == nil || k.URL == nil { - return "" - } - return *k.URL -} - -// GetColor returns the Color field if it's non-nil, zero value otherwise. -func (l *Label) GetColor() string { - if l == nil || l.Color == nil { - return "" - } - return *l.Color -} - -// GetDefault returns the Default field if it's non-nil, zero value otherwise. -func (l *Label) GetDefault() bool { - if l == nil || l.Default == nil { - return false - } - return *l.Default -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (l *Label) GetDescription() string { - if l == nil || l.Description == nil { - return "" - } - return *l.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (l *Label) GetID() int64 { - if l == nil || l.ID == nil { - return 0 - } - return *l.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (l *Label) GetName() string { - if l == nil || l.Name == nil { - return "" - } - return *l.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (l *Label) GetNodeID() string { - if l == nil || l.NodeID == nil { - return "" - } - return *l.NodeID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (l *Label) GetURL() string { - if l == nil || l.URL == nil { - return "" - } - return *l.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (l *LabelEvent) GetAction() string { - if l == nil || l.Action == nil { - return "" - } - return *l.Action -} - -// GetChanges returns the Changes field. -func (l *LabelEvent) GetChanges() *EditChange { - if l == nil { - return nil - } - return l.Changes -} - -// GetInstallation returns the Installation field. -func (l *LabelEvent) GetInstallation() *Installation { - if l == nil { - return nil - } - return l.Installation -} - -// GetLabel returns the Label field. -func (l *LabelEvent) GetLabel() *Label { - if l == nil { - return nil - } - return l.Label -} - -// GetOrg returns the Org field. -func (l *LabelEvent) GetOrg() *Organization { - if l == nil { - return nil - } - return l.Org -} - -// GetRepo returns the Repo field. -func (l *LabelEvent) GetRepo() *Repository { - if l == nil { - return nil - } - return l.Repo -} - -// GetColor returns the Color field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetColor() string { - if l == nil || l.Color == nil { - return "" - } - return *l.Color -} - -// GetDefault returns the Default field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetDefault() bool { - if l == nil || l.Default == nil { - return false - } - return *l.Default -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetDescription() string { - if l == nil || l.Description == nil { - return "" - } - return *l.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetID() int64 { - if l == nil || l.ID == nil { - return 0 - } - return *l.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetName() string { - if l == nil || l.Name == nil { - return "" - } - return *l.Name -} - -// GetScore returns the Score field. -func (l *LabelResult) GetScore() *float64 { - if l == nil { - return nil - } - return l.Score -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (l *LabelResult) GetURL() string { - if l == nil || l.URL == nil { - return "" - } - return *l.URL -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (l *LabelsSearchResult) GetIncompleteResults() bool { - if l == nil || l.IncompleteResults == nil { - return false - } - return *l.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (l *LabelsSearchResult) GetTotal() int { - if l == nil || l.Total == nil { - return 0 - } - return *l.Total -} - -// GetOID returns the OID field if it's non-nil, zero value otherwise. -func (l *LargeFile) GetOID() string { - if l == nil || l.OID == nil { - return "" - } - return *l.OID -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (l *LargeFile) GetPath() string { - if l == nil || l.Path == nil { - return "" - } - return *l.Path -} - -// GetRefName returns the RefName field if it's non-nil, zero value otherwise. -func (l *LargeFile) GetRefName() string { - if l == nil || l.RefName == nil { - return "" - } - return *l.RefName -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (l *LargeFile) GetSize() int { - if l == nil || l.Size == nil { - return 0 - } - return *l.Size -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (l *License) GetBody() string { - if l == nil || l.Body == nil { - return "" - } - return *l.Body -} - -// GetConditions returns the Conditions field if it's non-nil, zero value otherwise. -func (l *License) GetConditions() []string { - if l == nil || l.Conditions == nil { - return nil - } - return *l.Conditions -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (l *License) GetDescription() string { - if l == nil || l.Description == nil { - return "" - } - return *l.Description -} - -// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. -func (l *License) GetFeatured() bool { - if l == nil || l.Featured == nil { - return false - } - return *l.Featured -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (l *License) GetHTMLURL() string { - if l == nil || l.HTMLURL == nil { - return "" - } - return *l.HTMLURL -} - -// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. -func (l *License) GetImplementation() string { - if l == nil || l.Implementation == nil { - return "" - } - return *l.Implementation -} - -// GetKey returns the Key field if it's non-nil, zero value otherwise. -func (l *License) GetKey() string { - if l == nil || l.Key == nil { - return "" - } - return *l.Key -} - -// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. -func (l *License) GetLimitations() []string { - if l == nil || l.Limitations == nil { - return nil - } - return *l.Limitations -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (l *License) GetName() string { - if l == nil || l.Name == nil { - return "" - } - return *l.Name -} - -// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. -func (l *License) GetPermissions() []string { - if l == nil || l.Permissions == nil { - return nil - } - return *l.Permissions -} - -// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. -func (l *License) GetSPDXID() string { - if l == nil || l.SPDXID == nil { - return "" - } - return *l.SPDXID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (l *License) GetURL() string { - if l == nil || l.URL == nil { - return "" - } - return *l.URL -} - -// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. -func (l *ListCheckRunsOptions) GetCheckName() string { - if l == nil || l.CheckName == nil { - return "" - } - return *l.CheckName -} - -// GetFilter returns the Filter field if it's non-nil, zero value otherwise. -func (l *ListCheckRunsOptions) GetFilter() string { - if l == nil || l.Filter == nil { - return "" - } - return *l.Filter -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (l *ListCheckRunsOptions) GetStatus() string { - if l == nil || l.Status == nil { - return "" - } - return *l.Status -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (l *ListCheckRunsResults) GetTotal() int { - if l == nil || l.Total == nil { - return 0 - } - return *l.Total -} - -// GetAppID returns the AppID field if it's non-nil, zero value otherwise. -func (l *ListCheckSuiteOptions) GetAppID() int { - if l == nil || l.AppID == nil { - return 0 - } - return *l.AppID -} - -// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. -func (l *ListCheckSuiteOptions) GetCheckName() string { - if l == nil || l.CheckName == nil { - return "" - } - return *l.CheckName -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (l *ListCheckSuiteResults) GetTotal() int { - if l == nil || l.Total == nil { - return 0 - } - return *l.Total -} - -// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetAccountsURL() string { - if m == nil || m.AccountsURL == nil { - return "" - } - return *m.AccountsURL -} - -// GetBullets returns the Bullets field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetBullets() []string { - if m == nil || m.Bullets == nil { - return nil - } - return *m.Bullets -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetDescription() string { - if m == nil || m.Description == nil { - return "" - } - return *m.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetID() int64 { - if m == nil || m.ID == nil { - return 0 - } - return *m.ID -} - -// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetMonthlyPriceInCents() int { - if m == nil || m.MonthlyPriceInCents == nil { - return 0 - } - return *m.MonthlyPriceInCents -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetName() string { - if m == nil || m.Name == nil { - return "" - } - return *m.Name -} - -// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetPriceModel() string { - if m == nil || m.PriceModel == nil { - return "" - } - return *m.PriceModel -} - -// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetUnitName() string { - if m == nil || m.UnitName == nil { - return "" - } - return *m.UnitName -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. -func (m *MarketplacePlan) GetYearlyPriceInCents() int { - if m == nil || m.YearlyPriceInCents == nil { - return 0 - } - return *m.YearlyPriceInCents -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetEmail() string { - if m == nil || m.Email == nil { - return "" - } - return *m.Email -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetID() int64 { - if m == nil || m.ID == nil { - return 0 - } - return *m.ID -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetLogin() string { - if m == nil || m.Login == nil { - return "" - } - return *m.Login -} - -// GetMarketplacePurchase returns the MarketplacePurchase field. -func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { - if m == nil { - return nil - } - return m.MarketplacePurchase -} - -// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { - if m == nil || m.OrganizationBillingEmail == nil { - return "" - } - return *m.OrganizationBillingEmail -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetType() string { - if m == nil || m.Type == nil { - return "" - } - return *m.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *MarketplacePlanAccount) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetAccount returns the Account field. -func (m *MarketplacePurchase) GetAccount() *MarketplacePlanAccount { - if m == nil { - return nil - } - return m.Account -} - -// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. -func (m *MarketplacePurchase) GetBillingCycle() string { - if m == nil || m.BillingCycle == nil { - return "" - } - return *m.BillingCycle -} - -// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. -func (m *MarketplacePurchase) GetNextBillingDate() string { - if m == nil || m.NextBillingDate == nil { - return "" - } - return *m.NextBillingDate -} - -// GetPlan returns the Plan field. -func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { - if m == nil { - return nil - } - return m.Plan -} - -// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. -func (m *MarketplacePurchase) GetUnitCount() int { - if m == nil || m.UnitCount == nil { - return 0 - } - return *m.UnitCount -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (m *MarketplacePurchaseEvent) GetAction() string { - if m == nil || m.Action == nil { - return "" - } - return *m.Action -} - -// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. -func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { - if m == nil || m.EffectiveDate == nil { - return Timestamp{} - } - return *m.EffectiveDate -} - -// GetInstallation returns the Installation field. -func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { - if m == nil { - return nil - } - return m.Installation -} - -// GetMarketplacePurchase returns the MarketplacePurchase field. -func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { - if m == nil { - return nil - } - return m.MarketplacePurchase -} - -// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. -func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { - if m == nil { - return nil - } - return m.PreviousMarketplacePurchase -} - -// GetSender returns the Sender field. -func (m *MarketplacePurchaseEvent) GetSender() *User { - if m == nil { - return nil - } - return m.Sender -} - -// GetText returns the Text field if it's non-nil, zero value otherwise. -func (m *Match) GetText() string { - if m == nil || m.Text == nil { - return "" - } - return *m.Text -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (m *MemberEvent) GetAction() string { - if m == nil || m.Action == nil { - return "" - } - return *m.Action -} - -// GetInstallation returns the Installation field. -func (m *MemberEvent) GetInstallation() *Installation { - if m == nil { - return nil - } - return m.Installation -} - -// GetMember returns the Member field. -func (m *MemberEvent) GetMember() *User { - if m == nil { - return nil - } - return m.Member -} - -// GetRepo returns the Repo field. -func (m *MemberEvent) GetRepo() *Repository { - if m == nil { - return nil - } - return m.Repo -} - -// GetSender returns the Sender field. -func (m *MemberEvent) GetSender() *User { - if m == nil { - return nil - } - return m.Sender -} - -// GetOrganization returns the Organization field. -func (m *Membership) GetOrganization() *Organization { - if m == nil { - return nil - } - return m.Organization -} - -// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. -func (m *Membership) GetOrganizationURL() string { - if m == nil || m.OrganizationURL == nil { - return "" - } - return *m.OrganizationURL -} - -// GetRole returns the Role field if it's non-nil, zero value otherwise. -func (m *Membership) GetRole() string { - if m == nil || m.Role == nil { - return "" - } - return *m.Role -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (m *Membership) GetState() string { - if m == nil || m.State == nil { - return "" - } - return *m.State -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *Membership) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetUser returns the User field. -func (m *Membership) GetUser() *User { - if m == nil { - return nil - } - return m.User -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (m *MembershipEvent) GetAction() string { - if m == nil || m.Action == nil { - return "" - } - return *m.Action -} - -// GetInstallation returns the Installation field. -func (m *MembershipEvent) GetInstallation() *Installation { - if m == nil { - return nil - } - return m.Installation -} - -// GetMember returns the Member field. -func (m *MembershipEvent) GetMember() *User { - if m == nil { - return nil - } - return m.Member -} - -// GetOrg returns the Org field. -func (m *MembershipEvent) GetOrg() *Organization { - if m == nil { - return nil - } - return m.Org -} - -// GetScope returns the Scope field if it's non-nil, zero value otherwise. -func (m *MembershipEvent) GetScope() string { - if m == nil || m.Scope == nil { - return "" - } - return *m.Scope -} - -// GetSender returns the Sender field. -func (m *MembershipEvent) GetSender() *User { - if m == nil { - return nil - } - return m.Sender -} - -// GetTeam returns the Team field. -func (m *MembershipEvent) GetTeam() *Team { - if m == nil { - return nil - } - return m.Team -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (m *Metric) GetHTMLURL() string { - if m == nil || m.HTMLURL == nil { - return "" - } - return *m.HTMLURL -} - -// GetKey returns the Key field if it's non-nil, zero value otherwise. -func (m *Metric) GetKey() string { - if m == nil || m.Key == nil { - return "" - } - return *m.Key -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (m *Metric) GetName() string { - if m == nil || m.Name == nil { - return "" - } - return *m.Name -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *Metric) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (m *Migration) GetCreatedAt() string { - if m == nil || m.CreatedAt == nil { - return "" - } - return *m.CreatedAt -} - -// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. -func (m *Migration) GetExcludeAttachments() bool { - if m == nil || m.ExcludeAttachments == nil { - return false - } - return *m.ExcludeAttachments -} - -// GetGUID returns the GUID field if it's non-nil, zero value otherwise. -func (m *Migration) GetGUID() string { - if m == nil || m.GUID == nil { - return "" - } - return *m.GUID -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (m *Migration) GetID() int64 { - if m == nil || m.ID == nil { - return 0 - } - return *m.ID -} - -// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. -func (m *Migration) GetLockRepositories() bool { - if m == nil || m.LockRepositories == nil { - return false - } - return *m.LockRepositories -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (m *Migration) GetState() string { - if m == nil || m.State == nil { - return "" - } - return *m.State -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (m *Migration) GetUpdatedAt() string { - if m == nil || m.UpdatedAt == nil { - return "" - } - return *m.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *Migration) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. -func (m *Milestone) GetClosedAt() time.Time { - if m == nil || m.ClosedAt == nil { - return time.Time{} - } - return *m.ClosedAt -} - -// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. -func (m *Milestone) GetClosedIssues() int { - if m == nil || m.ClosedIssues == nil { - return 0 - } - return *m.ClosedIssues -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (m *Milestone) GetCreatedAt() time.Time { - if m == nil || m.CreatedAt == nil { - return time.Time{} - } - return *m.CreatedAt -} - -// GetCreator returns the Creator field. -func (m *Milestone) GetCreator() *User { - if m == nil { - return nil - } - return m.Creator -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (m *Milestone) GetDescription() string { - if m == nil || m.Description == nil { - return "" - } - return *m.Description -} - -// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. -func (m *Milestone) GetDueOn() time.Time { - if m == nil || m.DueOn == nil { - return time.Time{} - } - return *m.DueOn -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (m *Milestone) GetHTMLURL() string { - if m == nil || m.HTMLURL == nil { - return "" - } - return *m.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (m *Milestone) GetID() int64 { - if m == nil || m.ID == nil { - return 0 - } - return *m.ID -} - -// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. -func (m *Milestone) GetLabelsURL() string { - if m == nil || m.LabelsURL == nil { - return "" - } - return *m.LabelsURL -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (m *Milestone) GetNodeID() string { - if m == nil || m.NodeID == nil { - return "" - } - return *m.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (m *Milestone) GetNumber() int { - if m == nil || m.Number == nil { - return 0 - } - return *m.Number -} - -// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. -func (m *Milestone) GetOpenIssues() int { - if m == nil || m.OpenIssues == nil { - return 0 - } - return *m.OpenIssues -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (m *Milestone) GetState() string { - if m == nil || m.State == nil { - return "" - } - return *m.State -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (m *Milestone) GetTitle() string { - if m == nil || m.Title == nil { - return "" - } - return *m.Title -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (m *Milestone) GetUpdatedAt() time.Time { - if m == nil || m.UpdatedAt == nil { - return time.Time{} - } - return *m.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (m *Milestone) GetURL() string { - if m == nil || m.URL == nil { - return "" - } - return *m.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (m *MilestoneEvent) GetAction() string { - if m == nil || m.Action == nil { - return "" - } - return *m.Action -} - -// GetChanges returns the Changes field. -func (m *MilestoneEvent) GetChanges() *EditChange { - if m == nil { - return nil - } - return m.Changes -} - -// GetInstallation returns the Installation field. -func (m *MilestoneEvent) GetInstallation() *Installation { - if m == nil { - return nil - } - return m.Installation -} - -// GetMilestone returns the Milestone field. -func (m *MilestoneEvent) GetMilestone() *Milestone { - if m == nil { - return nil - } - return m.Milestone -} - -// GetOrg returns the Org field. -func (m *MilestoneEvent) GetOrg() *Organization { - if m == nil { - return nil - } - return m.Org -} - -// GetRepo returns the Repo field. -func (m *MilestoneEvent) GetRepo() *Repository { - if m == nil { - return nil - } - return m.Repo -} - -// GetSender returns the Sender field. -func (m *MilestoneEvent) GetSender() *User { - if m == nil { - return nil - } - return m.Sender -} - -// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. -func (m *MilestoneStats) GetClosedMilestones() int { - if m == nil || m.ClosedMilestones == nil { - return 0 - } - return *m.ClosedMilestones -} - -// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. -func (m *MilestoneStats) GetOpenMilestones() int { - if m == nil || m.OpenMilestones == nil { - return 0 - } - return *m.OpenMilestones -} - -// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. -func (m *MilestoneStats) GetTotalMilestones() int { - if m == nil || m.TotalMilestones == nil { - return 0 - } - return *m.TotalMilestones -} - -// GetBase returns the Base field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetBase() string { - if n == nil || n.Base == nil { - return "" - } - return *n.Base -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetBody() string { - if n == nil || n.Body == nil { - return "" - } - return *n.Body -} - -// GetHead returns the Head field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetHead() string { - if n == nil || n.Head == nil { - return "" - } - return *n.Head -} - -// GetIssue returns the Issue field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetIssue() int { - if n == nil || n.Issue == nil { - return 0 - } - return *n.Issue -} - -// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetMaintainerCanModify() bool { - if n == nil || n.MaintainerCanModify == nil { - return false - } - return *n.MaintainerCanModify -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (n *NewPullRequest) GetTitle() string { - if n == nil || n.Title == nil { - return "" - } - return *n.Title -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetDescription() string { - if n == nil || n.Description == nil { - return "" - } - return *n.Description -} - -// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetLDAPDN() string { - if n == nil || n.LDAPDN == nil { - return "" - } - return *n.LDAPDN -} - -// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetParentTeamID() int64 { - if n == nil || n.ParentTeamID == nil { - return 0 - } - return *n.ParentTeamID -} - -// GetPermission returns the Permission field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetPermission() string { - if n == nil || n.Permission == nil { - return "" - } - return *n.Permission -} - -// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetPrivacy() string { - if n == nil || n.Privacy == nil { - return "" - } - return *n.Privacy -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (n *Notification) GetID() string { - if n == nil || n.ID == nil { - return "" - } - return *n.ID -} - -// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. -func (n *Notification) GetLastReadAt() time.Time { - if n == nil || n.LastReadAt == nil { - return time.Time{} - } - return *n.LastReadAt -} - -// GetReason returns the Reason field if it's non-nil, zero value otherwise. -func (n *Notification) GetReason() string { - if n == nil || n.Reason == nil { - return "" - } - return *n.Reason -} - -// GetRepository returns the Repository field. -func (n *Notification) GetRepository() *Repository { - if n == nil { - return nil - } - return n.Repository -} - -// GetSubject returns the Subject field. -func (n *Notification) GetSubject() *NotificationSubject { - if n == nil { - return nil - } - return n.Subject -} - -// GetUnread returns the Unread field if it's non-nil, zero value otherwise. -func (n *Notification) GetUnread() bool { - if n == nil || n.Unread == nil { - return false - } - return *n.Unread -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (n *Notification) GetUpdatedAt() time.Time { - if n == nil || n.UpdatedAt == nil { - return time.Time{} - } - return *n.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (n *Notification) GetURL() string { - if n == nil || n.URL == nil { - return "" - } - return *n.URL -} - -// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. -func (n *NotificationSubject) GetLatestCommentURL() string { - if n == nil || n.LatestCommentURL == nil { - return "" - } - return *n.LatestCommentURL -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (n *NotificationSubject) GetTitle() string { - if n == nil || n.Title == nil { - return "" - } - return *n.Title -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (n *NotificationSubject) GetType() string { - if n == nil || n.Type == nil { - return "" - } - return *n.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (n *NotificationSubject) GetURL() string { - if n == nil || n.URL == nil { - return "" - } - return *n.URL -} - -// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetAvatarURL() string { - if o == nil || o.AvatarURL == nil { - return "" - } - return *o.AvatarURL -} - -// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. -func (o *Organization) GetBillingEmail() string { - if o == nil || o.BillingEmail == nil { - return "" - } - return *o.BillingEmail -} - -// GetBlog returns the Blog field if it's non-nil, zero value otherwise. -func (o *Organization) GetBlog() string { - if o == nil || o.Blog == nil { - return "" - } - return *o.Blog -} - -// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. -func (o *Organization) GetCollaborators() int { - if o == nil || o.Collaborators == nil { - return 0 - } - return *o.Collaborators -} - -// GetCompany returns the Company field if it's non-nil, zero value otherwise. -func (o *Organization) GetCompany() string { - if o == nil || o.Company == nil { - return "" - } - return *o.Company -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (o *Organization) GetCreatedAt() time.Time { - if o == nil || o.CreatedAt == nil { - return time.Time{} - } - return *o.CreatedAt -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (o *Organization) GetDescription() string { - if o == nil || o.Description == nil { - return "" - } - return *o.Description -} - -// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. -func (o *Organization) GetDiskUsage() int { - if o == nil || o.DiskUsage == nil { - return 0 - } - return *o.DiskUsage -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (o *Organization) GetEmail() string { - if o == nil || o.Email == nil { - return "" - } - return *o.Email -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetEventsURL() string { - if o == nil || o.EventsURL == nil { - return "" - } - return *o.EventsURL -} - -// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. -func (o *Organization) GetFollowers() int { - if o == nil || o.Followers == nil { - return 0 - } - return *o.Followers -} - -// GetFollowing returns the Following field if it's non-nil, zero value otherwise. -func (o *Organization) GetFollowing() int { - if o == nil || o.Following == nil { - return 0 - } - return *o.Following -} - -// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetHooksURL() string { - if o == nil || o.HooksURL == nil { - return "" - } - return *o.HooksURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetHTMLURL() string { - if o == nil || o.HTMLURL == nil { - return "" - } - return *o.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (o *Organization) GetID() int64 { - if o == nil || o.ID == nil { - return 0 - } - return *o.ID -} - -// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetIssuesURL() string { - if o == nil || o.IssuesURL == nil { - return "" - } - return *o.IssuesURL -} - -// GetLocation returns the Location field if it's non-nil, zero value otherwise. -func (o *Organization) GetLocation() string { - if o == nil || o.Location == nil { - return "" - } - return *o.Location -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (o *Organization) GetLogin() string { - if o == nil || o.Login == nil { - return "" - } - return *o.Login -} - -// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetMembersURL() string { - if o == nil || o.MembersURL == nil { - return "" - } - return *o.MembersURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (o *Organization) GetName() string { - if o == nil || o.Name == nil { - return "" - } - return *o.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (o *Organization) GetNodeID() string { - if o == nil || o.NodeID == nil { - return "" - } - return *o.NodeID -} - -// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. -func (o *Organization) GetOwnedPrivateRepos() int { - if o == nil || o.OwnedPrivateRepos == nil { - return 0 - } - return *o.OwnedPrivateRepos -} - -// GetPlan returns the Plan field. -func (o *Organization) GetPlan() *Plan { - if o == nil { - return nil - } - return o.Plan -} - -// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. -func (o *Organization) GetPrivateGists() int { - if o == nil || o.PrivateGists == nil { - return 0 - } - return *o.PrivateGists -} - -// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. -func (o *Organization) GetPublicGists() int { - if o == nil || o.PublicGists == nil { - return 0 - } - return *o.PublicGists -} - -// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetPublicMembersURL() string { - if o == nil || o.PublicMembersURL == nil { - return "" - } - return *o.PublicMembersURL -} - -// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. -func (o *Organization) GetPublicRepos() int { - if o == nil || o.PublicRepos == nil { - return 0 - } - return *o.PublicRepos -} - -// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. -func (o *Organization) GetReposURL() string { - if o == nil || o.ReposURL == nil { - return "" - } - return *o.ReposURL -} - -// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. -func (o *Organization) GetTotalPrivateRepos() int { - if o == nil || o.TotalPrivateRepos == nil { - return 0 - } - return *o.TotalPrivateRepos -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (o *Organization) GetType() string { - if o == nil || o.Type == nil { - return "" - } - return *o.Type -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (o *Organization) GetUpdatedAt() time.Time { - if o == nil || o.UpdatedAt == nil { - return time.Time{} - } - return *o.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (o *Organization) GetURL() string { - if o == nil || o.URL == nil { - return "" - } - return *o.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (o *OrganizationEvent) GetAction() string { - if o == nil || o.Action == nil { - return "" - } - return *o.Action -} - -// GetInstallation returns the Installation field. -func (o *OrganizationEvent) GetInstallation() *Installation { - if o == nil { - return nil - } - return o.Installation -} - -// GetInvitation returns the Invitation field. -func (o *OrganizationEvent) GetInvitation() *Invitation { - if o == nil { - return nil - } - return o.Invitation -} - -// GetMembership returns the Membership field. -func (o *OrganizationEvent) GetMembership() *Membership { - if o == nil { - return nil - } - return o.Membership -} - -// GetOrganization returns the Organization field. -func (o *OrganizationEvent) GetOrganization() *Organization { - if o == nil { - return nil - } - return o.Organization -} - -// GetSender returns the Sender field. -func (o *OrganizationEvent) GetSender() *User { - if o == nil { - return nil - } - return o.Sender -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (o *OrgBlockEvent) GetAction() string { - if o == nil || o.Action == nil { - return "" - } - return *o.Action -} - -// GetBlockedUser returns the BlockedUser field. -func (o *OrgBlockEvent) GetBlockedUser() *User { - if o == nil { - return nil - } - return o.BlockedUser -} - -// GetInstallation returns the Installation field. -func (o *OrgBlockEvent) GetInstallation() *Installation { - if o == nil { - return nil - } - return o.Installation -} - -// GetOrganization returns the Organization field. -func (o *OrgBlockEvent) GetOrganization() *Organization { - if o == nil { - return nil - } - return o.Organization -} - -// GetSender returns the Sender field. -func (o *OrgBlockEvent) GetSender() *User { - if o == nil { - return nil - } - return o.Sender -} - -// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. -func (o *OrgStats) GetDisabledOrgs() int { - if o == nil || o.DisabledOrgs == nil { - return 0 - } - return *o.DisabledOrgs -} - -// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. -func (o *OrgStats) GetTotalOrgs() int { - if o == nil || o.TotalOrgs == nil { - return 0 - } - return *o.TotalOrgs -} - -// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. -func (o *OrgStats) GetTotalTeamMembers() int { - if o == nil || o.TotalTeamMembers == nil { - return 0 - } - return *o.TotalTeamMembers -} - -// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. -func (o *OrgStats) GetTotalTeams() int { - if o == nil || o.TotalTeams == nil { - return 0 - } - return *o.TotalTeams -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *Page) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *Page) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetPageName returns the PageName field if it's non-nil, zero value otherwise. -func (p *Page) GetPageName() string { - if p == nil || p.PageName == nil { - return "" - } - return *p.PageName -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (p *Page) GetSHA() string { - if p == nil || p.SHA == nil { - return "" - } - return *p.SHA -} - -// GetSummary returns the Summary field if it's non-nil, zero value otherwise. -func (p *Page) GetSummary() string { - if p == nil || p.Summary == nil { - return "" - } - return *p.Summary -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (p *Page) GetTitle() string { - if p == nil || p.Title == nil { - return "" - } - return *p.Title -} - -// GetBuild returns the Build field. -func (p *PageBuildEvent) GetBuild() *PagesBuild { - if p == nil { - return nil - } - return p.Build -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PageBuildEvent) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetInstallation returns the Installation field. -func (p *PageBuildEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetRepo returns the Repo field. -func (p *PageBuildEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *PageBuildEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. -func (p *Pages) GetCNAME() string { - if p == nil || p.CNAME == nil { - return "" - } - return *p.CNAME -} - -// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. -func (p *Pages) GetCustom404() bool { - if p == nil || p.Custom404 == nil { - return false - } - return *p.Custom404 -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *Pages) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (p *Pages) GetStatus() string { - if p == nil || p.Status == nil { - return "" - } - return *p.Status -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *Pages) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetCommit returns the Commit field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetCommit() string { - if p == nil || p.Commit == nil { - return "" - } - return *p.Commit -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetDuration returns the Duration field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetDuration() int { - if p == nil || p.Duration == nil { - return 0 - } - return *p.Duration -} - -// GetError returns the Error field. -func (p *PagesBuild) GetError() *PagesError { - if p == nil { - return nil - } - return p.Error -} - -// GetPusher returns the Pusher field. -func (p *PagesBuild) GetPusher() *User { - if p == nil { - return nil - } - return p.Pusher -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetStatus() string { - if p == nil || p.Status == nil { - return "" - } - return *p.Status -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PagesBuild) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (p *PagesError) GetMessage() string { - if p == nil || p.Message == nil { - return "" - } - return *p.Message -} - -// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. -func (p *PageStats) GetTotalPages() int { - if p == nil || p.TotalPages == nil { - return 0 - } - return *p.TotalPages -} - -// GetHook returns the Hook field. -func (p *PingEvent) GetHook() *Hook { - if p == nil { - return nil - } - return p.Hook -} - -// GetHookID returns the HookID field if it's non-nil, zero value otherwise. -func (p *PingEvent) GetHookID() int64 { - if p == nil || p.HookID == nil { - return 0 - } - return *p.HookID -} - -// GetInstallation returns the Installation field. -func (p *PingEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetZen returns the Zen field if it's non-nil, zero value otherwise. -func (p *PingEvent) GetZen() string { - if p == nil || p.Zen == nil { - return "" - } - return *p.Zen -} - -// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. -func (p *Plan) GetCollaborators() int { - if p == nil || p.Collaborators == nil { - return 0 - } - return *p.Collaborators -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *Plan) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. -func (p *Plan) GetPrivateRepos() int { - if p == nil || p.PrivateRepos == nil { - return 0 - } - return *p.PrivateRepos -} - -// GetSpace returns the Space field if it's non-nil, zero value otherwise. -func (p *Plan) GetSpace() int { - if p == nil || p.Space == nil { - return 0 - } - return *p.Space -} - -// GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise. -func (p *PreReceiveHook) GetConfigURL() string { - if p == nil || p.ConfigURL == nil { - return "" - } - return *p.ConfigURL -} - -// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. -func (p *PreReceiveHook) GetEnforcement() string { - if p == nil || p.Enforcement == nil { - return "" - } - return *p.Enforcement -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PreReceiveHook) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *PreReceiveHook) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *Project) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *Project) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetCreator returns the Creator field. -func (p *Project) GetCreator() *User { - if p == nil { - return nil - } - return p.Creator -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *Project) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *Project) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (p *Project) GetNodeID() string { - if p == nil || p.NodeID == nil { - return "" - } - return *p.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (p *Project) GetNumber() int { - if p == nil || p.Number == nil { - return 0 - } - return *p.Number -} - -// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. -func (p *Project) GetOwnerURL() string { - if p == nil || p.OwnerURL == nil { - return "" - } - return *p.OwnerURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *Project) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *Project) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetArchived returns the Archived field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetArchived() bool { - if p == nil || p.Archived == nil { - return false - } - return *p.Archived -} - -// GetColumnID returns the ColumnID field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetColumnID() int64 { - if p == nil || p.ColumnID == nil { - return 0 - } - return *p.ColumnID -} - -// GetColumnURL returns the ColumnURL field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetColumnURL() string { - if p == nil || p.ColumnURL == nil { - return "" - } - return *p.ColumnURL -} - -// GetContentURL returns the ContentURL field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetContentURL() string { - if p == nil || p.ContentURL == nil { - return "" - } - return *p.ContentURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetCreator returns the Creator field. -func (p *ProjectCard) GetCreator() *User { - if p == nil { - return nil - } - return p.Creator -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetNodeID() string { - if p == nil || p.NodeID == nil { - return "" - } - return *p.NodeID -} - -// GetNote returns the Note field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetNote() string { - if p == nil || p.Note == nil { - return "" - } - return *p.Note -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *ProjectCard) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *ProjectCardEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. -func (p *ProjectCardEvent) GetAfterID() int64 { - if p == nil || p.AfterID == nil { - return 0 - } - return *p.AfterID -} - -// GetChanges returns the Changes field. -func (p *ProjectCardEvent) GetChanges() *ProjectCardChange { - if p == nil { - return nil - } - return p.Changes -} - -// GetInstallation returns the Installation field. -func (p *ProjectCardEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetOrg returns the Org field. -func (p *ProjectCardEvent) GetOrg() *Organization { - if p == nil { - return nil - } - return p.Org -} - -// GetProjectCard returns the ProjectCard field. -func (p *ProjectCardEvent) GetProjectCard() *ProjectCard { - if p == nil { - return nil - } - return p.ProjectCard -} - -// GetRepo returns the Repo field. -func (p *ProjectCardEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *ProjectCardEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetArchivedState returns the ArchivedState field if it's non-nil, zero value otherwise. -func (p *ProjectCardListOptions) GetArchivedState() string { - if p == nil || p.ArchivedState == nil { - return "" - } - return *p.ArchivedState -} - -// GetArchived returns the Archived field if it's non-nil, zero value otherwise. -func (p *ProjectCardOptions) GetArchived() bool { - if p == nil || p.Archived == nil { - return false - } - return *p.Archived -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetNodeID() string { - if p == nil || p.NodeID == nil { - return "" - } - return *p.NodeID -} - -// GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetProjectURL() string { - if p == nil || p.ProjectURL == nil { - return "" - } - return *p.ProjectURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectColumn) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} - } - return *p.UpdatedAt -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *ProjectColumnEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. -func (p *ProjectColumnEvent) GetAfterID() int64 { - if p == nil || p.AfterID == nil { - return 0 - } - return *p.AfterID -} - -// GetChanges returns the Changes field. -func (p *ProjectColumnEvent) GetChanges() *ProjectColumnChange { - if p == nil { - return nil - } - return p.Changes -} - -// GetInstallation returns the Installation field. -func (p *ProjectColumnEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetOrg returns the Org field. -func (p *ProjectColumnEvent) GetOrg() *Organization { - if p == nil { - return nil - } - return p.Org -} - -// GetProjectColumn returns the ProjectColumn field. -func (p *ProjectColumnEvent) GetProjectColumn() *ProjectColumn { - if p == nil { - return nil - } - return p.ProjectColumn -} - -// GetRepo returns the Repo field. -func (p *ProjectColumnEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *ProjectColumnEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *ProjectEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetChanges returns the Changes field. -func (p *ProjectEvent) GetChanges() *ProjectChange { - if p == nil { - return nil - } - return p.Changes -} - -// GetInstallation returns the Installation field. -func (p *ProjectEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetOrg returns the Org field. -func (p *ProjectEvent) GetOrg() *Organization { - if p == nil { - return nil - } - return p.Org -} - -// GetProject returns the Project field. -func (p *ProjectEvent) GetProject() *Project { - if p == nil { - return nil - } - return p.Project -} - -// GetRepo returns the Repo field. -func (p *ProjectEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *ProjectEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetEnforceAdmins returns the EnforceAdmins field. -func (p *Protection) GetEnforceAdmins() *AdminEnforcement { - if p == nil { - return nil - } - return p.EnforceAdmins -} - -// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. -func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { - if p == nil { - return nil - } - return p.RequiredPullRequestReviews -} - -// GetRequiredStatusChecks returns the RequiredStatusChecks field. -func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { - if p == nil { - return nil - } - return p.RequiredStatusChecks -} - -// GetRestrictions returns the Restrictions field. -func (p *Protection) GetRestrictions() *BranchRestrictions { - if p == nil { - return nil - } - return p.Restrictions -} - -// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. -func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { - if p == nil { - return nil - } - return p.RequiredPullRequestReviews -} - -// GetRequiredStatusChecks returns the RequiredStatusChecks field. -func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { - if p == nil { - return nil - } - return p.RequiredStatusChecks -} - -// GetRestrictions returns the Restrictions field. -func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { - if p == nil { - return nil - } - return p.Restrictions -} - -// GetInstallation returns the Installation field. -func (p *PublicEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetRepo returns the Repo field. -func (p *PublicEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *PublicEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetActiveLockReason() string { - if p == nil || p.ActiveLockReason == nil { - return "" - } - return *p.ActiveLockReason -} - -// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetAdditions() int { - if p == nil || p.Additions == nil { - return 0 - } - return *p.Additions -} - -// GetAssignee returns the Assignee field. -func (p *PullRequest) GetAssignee() *User { - if p == nil { - return nil - } - return p.Assignee -} - -// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetAuthorAssociation() string { - if p == nil || p.AuthorAssociation == nil { - return "" - } - return *p.AuthorAssociation -} - -// GetBase returns the Base field. -func (p *PullRequest) GetBase() *PullRequestBranch { - if p == nil { - return nil - } - return p.Base -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - -// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetChangedFiles() int { - if p == nil || p.ChangedFiles == nil { - return 0 - } - return *p.ChangedFiles -} - -// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetClosedAt() time.Time { - if p == nil || p.ClosedAt == nil { - return time.Time{} - } - return *p.ClosedAt -} - -// GetComments returns the Comments field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetComments() int { - if p == nil || p.Comments == nil { - return 0 - } - return *p.Comments -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetCommentsURL() string { - if p == nil || p.CommentsURL == nil { - return "" - } - return *p.CommentsURL -} - -// GetCommits returns the Commits field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetCommits() int { - if p == nil || p.Commits == nil { - return 0 - } - return *p.Commits -} - -// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetCommitsURL() string { - if p == nil || p.CommitsURL == nil { - return "" - } - return *p.CommitsURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetCreatedAt() time.Time { - if p == nil || p.CreatedAt == nil { - return time.Time{} - } - return *p.CreatedAt -} - -// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetDeletions() int { - if p == nil || p.Deletions == nil { - return 0 - } - return *p.Deletions -} - -// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetDiffURL() string { - if p == nil || p.DiffURL == nil { - return "" - } - return *p.DiffURL -} - -// GetHead returns the Head field. -func (p *PullRequest) GetHead() *PullRequestBranch { - if p == nil { - return nil - } - return p.Head -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetIssueURL() string { - if p == nil || p.IssueURL == nil { - return "" - } - return *p.IssueURL -} - -// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMaintainerCanModify() bool { - if p == nil || p.MaintainerCanModify == nil { - return false - } - return *p.MaintainerCanModify -} - -// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMergeable() bool { - if p == nil || p.Mergeable == nil { - return false - } - return *p.Mergeable -} - -// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMergeableState() string { - if p == nil || p.MergeableState == nil { - return "" - } - return *p.MergeableState -} - -// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMergeCommitSHA() string { - if p == nil || p.MergeCommitSHA == nil { - return "" - } - return *p.MergeCommitSHA -} - -// GetMerged returns the Merged field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMerged() bool { - if p == nil || p.Merged == nil { - return false - } - return *p.Merged -} - -// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetMergedAt() time.Time { - if p == nil || p.MergedAt == nil { - return time.Time{} - } - return *p.MergedAt -} - -// GetMergedBy returns the MergedBy field. -func (p *PullRequest) GetMergedBy() *User { - if p == nil { - return nil - } - return p.MergedBy -} - -// GetMilestone returns the Milestone field. -func (p *PullRequest) GetMilestone() *Milestone { - if p == nil { - return nil - } - return p.Milestone -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetNodeID() string { - if p == nil || p.NodeID == nil { - return "" - } - return *p.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetNumber() int { - if p == nil || p.Number == nil { - return 0 - } - return *p.Number -} - -// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetPatchURL() string { - if p == nil || p.PatchURL == nil { - return "" - } - return *p.PatchURL -} - -// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetReviewCommentsURL() string { - if p == nil || p.ReviewCommentsURL == nil { - return "" - } - return *p.ReviewCommentsURL -} - -// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetReviewCommentURL() string { - if p == nil || p.ReviewCommentURL == nil { - return "" - } - return *p.ReviewCommentURL -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetState() string { - if p == nil || p.State == nil { - return "" - } - return *p.State -} - -// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetStatusesURL() string { - if p == nil || p.StatusesURL == nil { - return "" - } - return *p.StatusesURL -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetTitle() string { - if p == nil || p.Title == nil { - return "" - } - return *p.Title -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetUpdatedAt() time.Time { - if p == nil || p.UpdatedAt == nil { - return time.Time{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PullRequest) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetUser returns the User field. -func (p *PullRequest) GetUser() *User { - if p == nil { - return nil - } - return p.User -} - -// GetLabel returns the Label field if it's non-nil, zero value otherwise. -func (p *PullRequestBranch) GetLabel() string { - if p == nil || p.Label == nil { - return "" - } - return *p.Label -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (p *PullRequestBranch) GetRef() string { - if p == nil || p.Ref == nil { - return "" - } - return *p.Ref -} - -// GetRepo returns the Repo field. -func (p *PullRequestBranch) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (p *PullRequestBranch) GetSHA() string { - if p == nil || p.SHA == nil { - return "" - } - return *p.SHA -} - -// GetUser returns the User field. -func (p *PullRequestBranch) GetUser() *User { - if p == nil { - return nil - } - return p.User -} - -// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetAuthorAssociation() string { - if p == nil || p.AuthorAssociation == nil { - return "" - } - return *p.AuthorAssociation -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetCommitID() string { - if p == nil || p.CommitID == nil { - return "" - } - return *p.CommitID -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetCreatedAt() time.Time { - if p == nil || p.CreatedAt == nil { - return time.Time{} - } - return *p.CreatedAt -} - -// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetDiffHunk() string { - if p == nil || p.DiffHunk == nil { - return "" - } - return *p.DiffHunk -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetInReplyTo() int64 { - if p == nil || p.InReplyTo == nil { - return 0 - } - return *p.InReplyTo -} - -// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetOriginalCommitID() string { - if p == nil || p.OriginalCommitID == nil { - return "" - } - return *p.OriginalCommitID -} - -// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetOriginalPosition() int { - if p == nil || p.OriginalPosition == nil { - return 0 - } - return *p.OriginalPosition -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetPath() string { - if p == nil || p.Path == nil { - return "" - } - return *p.Path -} - -// GetPosition returns the Position field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetPosition() int { - if p == nil || p.Position == nil { - return 0 - } - return *p.Position -} - -// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetPullRequestReviewID() int64 { - if p == nil || p.PullRequestReviewID == nil { - return 0 - } - return *p.PullRequestReviewID -} - -// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetPullRequestURL() string { - if p == nil || p.PullRequestURL == nil { - return "" - } - return *p.PullRequestURL -} - -// GetReactions returns the Reactions field. -func (p *PullRequestComment) GetReactions() *Reactions { - if p == nil { - return nil - } - return p.Reactions -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetUpdatedAt() time.Time { - if p == nil || p.UpdatedAt == nil { - return time.Time{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PullRequestComment) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetUser returns the User field. -func (p *PullRequestComment) GetUser() *User { - if p == nil { - return nil - } - return p.User -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *PullRequestEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetChanges returns the Changes field. -func (p *PullRequestEvent) GetChanges() *EditChange { - if p == nil { - return nil - } - return p.Changes -} - -// GetInstallation returns the Installation field. -func (p *PullRequestEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetLabel returns the Label field. -func (p *PullRequestEvent) GetLabel() *Label { - if p == nil { - return nil - } - return p.Label -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (p *PullRequestEvent) GetNumber() int { - if p == nil || p.Number == nil { - return 0 - } - return *p.Number -} - -// GetPullRequest returns the PullRequest field. -func (p *PullRequestEvent) GetPullRequest() *PullRequest { - if p == nil { - return nil - } - return p.PullRequest -} - -// GetRepo returns the Repo field. -func (p *PullRequestEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetRequestedReviewer returns the RequestedReviewer field. -func (p *PullRequestEvent) GetRequestedReviewer() *User { - if p == nil { - return nil - } - return p.RequestedReviewer -} - -// GetSender returns the Sender field. -func (p *PullRequestEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. -func (p *PullRequestLinks) GetDiffURL() string { - if p == nil || p.DiffURL == nil { - return "" - } - return *p.DiffURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *PullRequestLinks) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. -func (p *PullRequestLinks) GetPatchURL() string { - if p == nil || p.PatchURL == nil { - return "" - } - return *p.PatchURL -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PullRequestLinks) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetMerged returns the Merged field if it's non-nil, zero value otherwise. -func (p *PullRequestMergeResult) GetMerged() bool { - if p == nil || p.Merged == nil { - return false - } - return *p.Merged -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (p *PullRequestMergeResult) GetMessage() string { - if p == nil || p.Message == nil { - return "" - } - return *p.Message -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (p *PullRequestMergeResult) GetSHA() string { - if p == nil || p.SHA == nil { - return "" - } - return *p.SHA -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetCommitID() string { - if p == nil || p.CommitID == nil { - return "" - } - return *p.CommitID -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetPullRequestURL() string { - if p == nil || p.PullRequestURL == nil { - return "" - } - return *p.PullRequestURL -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetState() string { - if p == nil || p.State == nil { - return "" - } - return *p.State -} - -// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. -func (p *PullRequestReview) GetSubmittedAt() time.Time { - if p == nil || p.SubmittedAt == nil { - return time.Time{} - } - return *p.SubmittedAt -} - -// GetUser returns the User field. -func (p *PullRequestReview) GetUser() *User { - if p == nil { - return nil - } - return p.User -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewCommentEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetChanges returns the Changes field. -func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { - if p == nil { - return nil - } - return p.Changes -} - -// GetComment returns the Comment field. -func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { - if p == nil { - return nil - } - return p.Comment -} - -// GetInstallation returns the Installation field. -func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetPullRequest returns the PullRequest field. -func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { - if p == nil { - return nil - } - return p.PullRequest -} - -// GetRepo returns the Repo field. -func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *PullRequestReviewCommentEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewDismissalRequest) GetMessage() string { - if p == nil || p.Message == nil { - return "" - } - return *p.Message -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewEvent) GetAction() string { - if p == nil || p.Action == nil { - return "" - } - return *p.Action -} - -// GetInstallation returns the Installation field. -func (p *PullRequestReviewEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetOrganization returns the Organization field. -func (p *PullRequestReviewEvent) GetOrganization() *Organization { - if p == nil { - return nil - } - return p.Organization -} - -// GetPullRequest returns the PullRequest field. -func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { - if p == nil { - return nil - } - return p.PullRequest -} - -// GetRepo returns the Repo field. -func (p *PullRequestReviewEvent) GetRepo() *Repository { - if p == nil { - return nil - } - return p.Repo -} - -// GetReview returns the Review field. -func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { - if p == nil { - return nil - } - return p.Review -} - -// GetSender returns the Sender field. -func (p *PullRequestReviewEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewRequest) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewRequest) GetCommitID() string { - if p == nil || p.CommitID == nil { - return "" - } - return *p.CommitID -} - -// GetEvent returns the Event field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewRequest) GetEvent() string { - if p == nil || p.Event == nil { - return "" - } - return *p.Event -} - -// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. -func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { - if p == nil { - return nil - } - return p.DismissalRestrictionsRequest -} - -// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. -func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { - if p == nil { - return nil - } - return p.DismissalRestrictionsRequest -} - -// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. -func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { - if p == nil || p.DismissStaleReviews == nil { - return false - } - return *p.DismissStaleReviews -} - -// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetMergablePulls() int { - if p == nil || p.MergablePulls == nil { - return 0 - } - return *p.MergablePulls -} - -// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetMergedPulls() int { - if p == nil || p.MergedPulls == nil { - return 0 - } - return *p.MergedPulls -} - -// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetTotalPulls() int { - if p == nil || p.TotalPulls == nil { - return 0 - } - return *p.TotalPulls -} - -// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetUnmergablePulls() int { - if p == nil || p.UnmergablePulls == nil { - return 0 - } - return *p.UnmergablePulls -} - -// GetCommits returns the Commits field if it's non-nil, zero value otherwise. -func (p *PunchCard) GetCommits() int { - if p == nil || p.Commits == nil { - return 0 - } - return *p.Commits -} - -// GetDay returns the Day field if it's non-nil, zero value otherwise. -func (p *PunchCard) GetDay() int { - if p == nil || p.Day == nil { - return 0 - } - return *p.Day -} - -// GetHour returns the Hour field if it's non-nil, zero value otherwise. -func (p *PunchCard) GetHour() int { - if p == nil || p.Hour == nil { - return 0 - } - return *p.Hour -} - -// GetAfter returns the After field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetAfter() string { - if p == nil || p.After == nil { - return "" - } - return *p.After -} - -// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetBaseRef() string { - if p == nil || p.BaseRef == nil { - return "" - } - return *p.BaseRef -} - -// GetBefore returns the Before field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetBefore() string { - if p == nil || p.Before == nil { - return "" - } - return *p.Before -} - -// GetCompare returns the Compare field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetCompare() string { - if p == nil || p.Compare == nil { - return "" - } - return *p.Compare -} - -// GetCreated returns the Created field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetCreated() bool { - if p == nil || p.Created == nil { - return false - } - return *p.Created -} - -// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetDeleted() bool { - if p == nil || p.Deleted == nil { - return false - } - return *p.Deleted -} - -// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetDistinctSize() int { - if p == nil || p.DistinctSize == nil { - return 0 - } - return *p.DistinctSize -} - -// GetForced returns the Forced field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetForced() bool { - if p == nil || p.Forced == nil { - return false - } - return *p.Forced -} - -// GetHead returns the Head field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetHead() string { - if p == nil || p.Head == nil { - return "" - } - return *p.Head -} - -// GetHeadCommit returns the HeadCommit field. -func (p *PushEvent) GetHeadCommit() *PushEventCommit { - if p == nil { - return nil - } - return p.HeadCommit -} - -// GetInstallation returns the Installation field. -func (p *PushEvent) GetInstallation() *Installation { - if p == nil { - return nil - } - return p.Installation -} - -// GetPusher returns the Pusher field. -func (p *PushEvent) GetPusher() *User { - if p == nil { - return nil - } - return p.Pusher -} - -// GetPushID returns the PushID field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetPushID() int64 { - if p == nil || p.PushID == nil { - return 0 - } - return *p.PushID -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetRef() string { - if p == nil || p.Ref == nil { - return "" - } - return *p.Ref -} - -// GetRepo returns the Repo field. -func (p *PushEvent) GetRepo() *PushEventRepository { - if p == nil { - return nil - } - return p.Repo -} - -// GetSender returns the Sender field. -func (p *PushEvent) GetSender() *User { - if p == nil { - return nil - } - return p.Sender -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (p *PushEvent) GetSize() int { - if p == nil || p.Size == nil { - return 0 - } - return *p.Size -} - -// GetAuthor returns the Author field. -func (p *PushEventCommit) GetAuthor() *CommitAuthor { - if p == nil { - return nil - } - return p.Author -} - -// GetCommitter returns the Committer field. -func (p *PushEventCommit) GetCommitter() *CommitAuthor { - if p == nil { - return nil - } - return p.Committer -} - -// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetDistinct() bool { - if p == nil || p.Distinct == nil { - return false - } - return *p.Distinct -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetID() string { - if p == nil || p.ID == nil { - return "" - } - return *p.ID -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetMessage() string { - if p == nil || p.Message == nil { - return "" - } - return *p.Message -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetSHA() string { - if p == nil || p.SHA == nil { - return "" - } - return *p.SHA -} - -// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetTimestamp() Timestamp { - if p == nil || p.Timestamp == nil { - return Timestamp{} - } - return *p.Timestamp -} - -// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetTreeID() string { - if p == nil || p.TreeID == nil { - return "" - } - return *p.TreeID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PushEventCommit) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (p *PushEventRepoOwner) GetEmail() string { - if p == nil || p.Email == nil { - return "" - } - return *p.Email -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *PushEventRepoOwner) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetArchiveURL() string { - if p == nil || p.ArchiveURL == nil { - return "" - } - return *p.ArchiveURL -} - -// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetCloneURL() string { - if p == nil || p.CloneURL == nil { - return "" - } - return *p.CloneURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetDefaultBranch() string { - if p == nil || p.DefaultBranch == nil { - return "" - } - return *p.DefaultBranch -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetDescription() string { - if p == nil || p.Description == nil { - return "" - } - return *p.Description -} - -// GetFork returns the Fork field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetFork() bool { - if p == nil || p.Fork == nil { - return false - } - return *p.Fork -} - -// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetForksCount() int { - if p == nil || p.ForksCount == nil { - return 0 - } - return *p.ForksCount -} - -// GetFullName returns the FullName field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetFullName() string { - if p == nil || p.FullName == nil { - return "" - } - return *p.FullName -} - -// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetGitURL() string { - if p == nil || p.GitURL == nil { - return "" - } - return *p.GitURL -} - -// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHasDownloads() bool { - if p == nil || p.HasDownloads == nil { - return false - } - return *p.HasDownloads -} - -// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHasIssues() bool { - if p == nil || p.HasIssues == nil { - return false - } - return *p.HasIssues -} - -// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHasPages() bool { - if p == nil || p.HasPages == nil { - return false - } - return *p.HasPages -} - -// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHasWiki() bool { - if p == nil || p.HasWiki == nil { - return false - } - return *p.HasWiki -} - -// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHomepage() string { - if p == nil || p.Homepage == nil { - return "" - } - return *p.Homepage -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetHTMLURL() string { - if p == nil || p.HTMLURL == nil { - return "" - } - return *p.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetID() int64 { - if p == nil || p.ID == nil { - return 0 - } - return *p.ID -} - -// GetLanguage returns the Language field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetLanguage() string { - if p == nil || p.Language == nil { - return "" - } - return *p.Language -} - -// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetMasterBranch() string { - if p == nil || p.MasterBranch == nil { - return "" - } - return *p.MasterBranch -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetName() string { - if p == nil || p.Name == nil { - return "" - } - return *p.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetNodeID() string { - if p == nil || p.NodeID == nil { - return "" - } - return *p.NodeID -} - -// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetOpenIssuesCount() int { - if p == nil || p.OpenIssuesCount == nil { - return 0 - } - return *p.OpenIssuesCount -} - -// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetOrganization() string { - if p == nil || p.Organization == nil { - return "" - } - return *p.Organization -} - -// GetOwner returns the Owner field. -func (p *PushEventRepository) GetOwner() *PushEventRepoOwner { - if p == nil { - return nil - } - return p.Owner -} - -// GetPrivate returns the Private field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetPrivate() bool { - if p == nil || p.Private == nil { - return false - } - return *p.Private -} - -// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetPushedAt() Timestamp { - if p == nil || p.PushedAt == nil { - return Timestamp{} - } - return *p.PushedAt -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetSize() int { - if p == nil || p.Size == nil { - return 0 - } - return *p.Size -} - -// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetSSHURL() string { - if p == nil || p.SSHURL == nil { - return "" - } - return *p.SSHURL -} - -// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetStargazersCount() int { - if p == nil || p.StargazersCount == nil { - return 0 - } - return *p.StargazersCount -} - -// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetStatusesURL() string { - if p == nil || p.StatusesURL == nil { - return "" - } - return *p.StatusesURL -} - -// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetSVNURL() string { - if p == nil || p.SVNURL == nil { - return "" - } - return *p.SVNURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} - } - return *p.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetURL() string { - if p == nil || p.URL == nil { - return "" - } - return *p.URL -} - -// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. -func (p *PushEventRepository) GetWatchersCount() int { - if p == nil || p.WatchersCount == nil { - return 0 - } - return *p.WatchersCount -} - -// GetCore returns the Core field. -func (r *RateLimits) GetCore() *Rate { - if r == nil { - return nil - } - return r.Core -} - -// GetSearch returns the Search field. -func (r *RateLimits) GetSearch() *Rate { - if r == nil { - return nil - } - return r.Search -} - -// GetContent returns the Content field if it's non-nil, zero value otherwise. -func (r *Reaction) GetContent() string { - if r == nil || r.Content == nil { - return "" - } - return *r.Content -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *Reaction) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *Reaction) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetUser returns the User field. -func (r *Reaction) GetUser() *User { - if r == nil { - return nil - } - return r.User -} - -// GetConfused returns the Confused field if it's non-nil, zero value otherwise. -func (r *Reactions) GetConfused() int { - if r == nil || r.Confused == nil { - return 0 - } - return *r.Confused -} - -// GetHeart returns the Heart field if it's non-nil, zero value otherwise. -func (r *Reactions) GetHeart() int { - if r == nil || r.Heart == nil { - return 0 - } - return *r.Heart -} - -// GetHooray returns the Hooray field if it's non-nil, zero value otherwise. -func (r *Reactions) GetHooray() int { - if r == nil || r.Hooray == nil { - return 0 - } - return *r.Hooray -} - -// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. -func (r *Reactions) GetLaugh() int { - if r == nil || r.Laugh == nil { - return 0 - } - return *r.Laugh -} - -// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. -func (r *Reactions) GetMinusOne() int { - if r == nil || r.MinusOne == nil { - return 0 - } - return *r.MinusOne -} - -// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. -func (r *Reactions) GetPlusOne() int { - if r == nil || r.PlusOne == nil { - return 0 - } - return *r.PlusOne -} - -// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. -func (r *Reactions) GetTotalCount() int { - if r == nil || r.TotalCount == nil { - return 0 - } - return *r.TotalCount -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *Reactions) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *Reference) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetObject returns the Object field. -func (r *Reference) GetObject() *GitObject { - if r == nil { - return nil - } - return r.Object -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (r *Reference) GetRef() string { - if r == nil || r.Ref == nil { - return "" - } - return *r.Ref -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *Reference) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetBrowserDownloadURL() string { - if r == nil || r.BrowserDownloadURL == nil { - return "" - } - return *r.BrowserDownloadURL -} - -// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetContentType() string { - if r == nil || r.ContentType == nil { - return "" - } - return *r.ContentType -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetCreatedAt() Timestamp { - if r == nil || r.CreatedAt == nil { - return Timestamp{} - } - return *r.CreatedAt -} - -// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetDownloadCount() int { - if r == nil || r.DownloadCount == nil { - return 0 - } - return *r.DownloadCount -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetLabel returns the Label field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetLabel() string { - if r == nil || r.Label == nil { - return "" - } - return *r.Label -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetSize() int { - if r == nil || r.Size == nil { - return 0 - } - return *r.Size -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetState() string { - if r == nil || r.State == nil { - return "" - } - return *r.State -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetUpdatedAt() Timestamp { - if r == nil || r.UpdatedAt == nil { - return Timestamp{} - } - return *r.UpdatedAt -} - -// GetUploader returns the Uploader field. -func (r *ReleaseAsset) GetUploader() *User { - if r == nil { - return nil - } - return r.Uploader -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *ReleaseAsset) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (r *ReleaseEvent) GetAction() string { - if r == nil || r.Action == nil { - return "" - } - return *r.Action -} - -// GetInstallation returns the Installation field. -func (r *ReleaseEvent) GetInstallation() *Installation { - if r == nil { - return nil - } - return r.Installation -} - -// GetRelease returns the Release field. -func (r *ReleaseEvent) GetRelease() *RepositoryRelease { - if r == nil { - return nil - } - return r.Release -} - -// GetRepo returns the Repo field. -func (r *ReleaseEvent) GetRepo() *Repository { - if r == nil { - return nil - } - return r.Repo -} - -// GetSender returns the Sender field. -func (r *ReleaseEvent) GetSender() *User { - if r == nil { - return nil - } - return r.Sender -} - -// GetFrom returns the From field if it's non-nil, zero value otherwise. -func (r *Rename) GetFrom() string { - if r == nil || r.From == nil { - return "" - } - return *r.From -} - -// GetTo returns the To field if it's non-nil, zero value otherwise. -func (r *Rename) GetTo() string { - if r == nil || r.To == nil { - return "" - } - return *r.To -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (r *RepositoriesSearchResult) GetIncompleteResults() bool { - if r == nil || r.IncompleteResults == nil { - return false - } - return *r.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (r *RepositoriesSearchResult) GetTotal() int { - if r == nil || r.Total == nil { - return 0 - } - return *r.Total -} - -// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. -func (r *Repository) GetAllowMergeCommit() bool { - if r == nil || r.AllowMergeCommit == nil { - return false - } - return *r.AllowMergeCommit -} - -// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. -func (r *Repository) GetAllowRebaseMerge() bool { - if r == nil || r.AllowRebaseMerge == nil { - return false - } - return *r.AllowRebaseMerge -} - -// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. -func (r *Repository) GetAllowSquashMerge() bool { - if r == nil || r.AllowSquashMerge == nil { - return false - } - return *r.AllowSquashMerge -} - -// GetArchived returns the Archived field if it's non-nil, zero value otherwise. -func (r *Repository) GetArchived() bool { - if r == nil || r.Archived == nil { - return false - } - return *r.Archived -} - -// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetArchiveURL() string { - if r == nil || r.ArchiveURL == nil { - return "" - } - return *r.ArchiveURL -} - -// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetAssigneesURL() string { - if r == nil || r.AssigneesURL == nil { - return "" - } - return *r.AssigneesURL -} - -// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. -func (r *Repository) GetAutoInit() bool { - if r == nil || r.AutoInit == nil { - return false - } - return *r.AutoInit -} - -// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetBlobsURL() string { - if r == nil || r.BlobsURL == nil { - return "" - } - return *r.BlobsURL -} - -// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetBranchesURL() string { - if r == nil || r.BranchesURL == nil { - return "" - } - return *r.BranchesURL -} - -// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetCloneURL() string { - if r == nil || r.CloneURL == nil { - return "" - } - return *r.CloneURL -} - -// GetCodeOfConduct returns the CodeOfConduct field. -func (r *Repository) GetCodeOfConduct() *CodeOfConduct { - if r == nil { - return nil - } - return r.CodeOfConduct -} - -// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetCollaboratorsURL() string { - if r == nil || r.CollaboratorsURL == nil { - return "" - } - return *r.CollaboratorsURL -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetCommentsURL() string { - if r == nil || r.CommentsURL == nil { - return "" - } - return *r.CommentsURL -} - -// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetCommitsURL() string { - if r == nil || r.CommitsURL == nil { - return "" - } - return *r.CommitsURL -} - -// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetCompareURL() string { - if r == nil || r.CompareURL == nil { - return "" - } - return *r.CompareURL -} - -// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetContentsURL() string { - if r == nil || r.ContentsURL == nil { - return "" - } - return *r.ContentsURL -} - -// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetContributorsURL() string { - if r == nil || r.ContributorsURL == nil { - return "" - } - return *r.ContributorsURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *Repository) GetCreatedAt() Timestamp { - if r == nil || r.CreatedAt == nil { - return Timestamp{} - } - return *r.CreatedAt -} - -// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. -func (r *Repository) GetDefaultBranch() string { - if r == nil || r.DefaultBranch == nil { - return "" - } - return *r.DefaultBranch -} - -// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetDeploymentsURL() string { - if r == nil || r.DeploymentsURL == nil { - return "" - } - return *r.DeploymentsURL -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (r *Repository) GetDescription() string { - if r == nil || r.Description == nil { - return "" - } - return *r.Description -} - -// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetDownloadsURL() string { - if r == nil || r.DownloadsURL == nil { - return "" - } - return *r.DownloadsURL -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetEventsURL() string { - if r == nil || r.EventsURL == nil { - return "" - } - return *r.EventsURL -} - -// GetFork returns the Fork field if it's non-nil, zero value otherwise. -func (r *Repository) GetFork() bool { - if r == nil || r.Fork == nil { - return false - } - return *r.Fork -} - -// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetForksCount() int { - if r == nil || r.ForksCount == nil { - return 0 - } - return *r.ForksCount -} - -// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetForksURL() string { - if r == nil || r.ForksURL == nil { - return "" - } - return *r.ForksURL -} - -// GetFullName returns the FullName field if it's non-nil, zero value otherwise. -func (r *Repository) GetFullName() string { - if r == nil || r.FullName == nil { - return "" - } - return *r.FullName -} - -// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetGitCommitsURL() string { - if r == nil || r.GitCommitsURL == nil { - return "" - } - return *r.GitCommitsURL -} - -// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. -func (r *Repository) GetGitignoreTemplate() string { - if r == nil || r.GitignoreTemplate == nil { - return "" - } - return *r.GitignoreTemplate -} - -// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetGitRefsURL() string { - if r == nil || r.GitRefsURL == nil { - return "" - } - return *r.GitRefsURL -} - -// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetGitTagsURL() string { - if r == nil || r.GitTagsURL == nil { - return "" - } - return *r.GitTagsURL -} - -// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetGitURL() string { - if r == nil || r.GitURL == nil { - return "" - } - return *r.GitURL -} - -// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. -func (r *Repository) GetHasDownloads() bool { - if r == nil || r.HasDownloads == nil { - return false - } - return *r.HasDownloads -} - -// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. -func (r *Repository) GetHasIssues() bool { - if r == nil || r.HasIssues == nil { - return false - } - return *r.HasIssues -} - -// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. -func (r *Repository) GetHasPages() bool { - if r == nil || r.HasPages == nil { - return false - } - return *r.HasPages -} - -// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. -func (r *Repository) GetHasProjects() bool { - if r == nil || r.HasProjects == nil { - return false - } - return *r.HasProjects -} - -// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. -func (r *Repository) GetHasWiki() bool { - if r == nil || r.HasWiki == nil { - return false - } - return *r.HasWiki -} - -// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. -func (r *Repository) GetHomepage() string { - if r == nil || r.Homepage == nil { - return "" - } - return *r.Homepage -} - -// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetHooksURL() string { - if r == nil || r.HooksURL == nil { - return "" - } - return *r.HooksURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *Repository) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetIssueCommentURL() string { - if r == nil || r.IssueCommentURL == nil { - return "" - } - return *r.IssueCommentURL -} - -// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetIssueEventsURL() string { - if r == nil || r.IssueEventsURL == nil { - return "" - } - return *r.IssueEventsURL -} - -// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetIssuesURL() string { - if r == nil || r.IssuesURL == nil { - return "" - } - return *r.IssuesURL -} - -// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetKeysURL() string { - if r == nil || r.KeysURL == nil { - return "" - } - return *r.KeysURL -} - -// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetLabelsURL() string { - if r == nil || r.LabelsURL == nil { - return "" - } - return *r.LabelsURL -} - -// GetLanguage returns the Language field if it's non-nil, zero value otherwise. -func (r *Repository) GetLanguage() string { - if r == nil || r.Language == nil { - return "" - } - return *r.Language -} - -// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetLanguagesURL() string { - if r == nil || r.LanguagesURL == nil { - return "" - } - return *r.LanguagesURL -} - -// GetLicense returns the License field. -func (r *Repository) GetLicense() *License { - if r == nil { - return nil - } - return r.License -} - -// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. -func (r *Repository) GetLicenseTemplate() string { - if r == nil || r.LicenseTemplate == nil { - return "" - } - return *r.LicenseTemplate -} - -// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. -func (r *Repository) GetMasterBranch() string { - if r == nil || r.MasterBranch == nil { - return "" - } - return *r.MasterBranch -} - -// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetMergesURL() string { - if r == nil || r.MergesURL == nil { - return "" - } - return *r.MergesURL -} - -// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetMilestonesURL() string { - if r == nil || r.MilestonesURL == nil { - return "" - } - return *r.MilestonesURL -} - -// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetMirrorURL() string { - if r == nil || r.MirrorURL == nil { - return "" - } - return *r.MirrorURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *Repository) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetNetworkCount() int { - if r == nil || r.NetworkCount == nil { - return 0 - } - return *r.NetworkCount -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *Repository) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetNotificationsURL() string { - if r == nil || r.NotificationsURL == nil { - return "" - } - return *r.NotificationsURL -} - -// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetOpenIssuesCount() int { - if r == nil || r.OpenIssuesCount == nil { - return 0 - } - return *r.OpenIssuesCount -} - -// GetOrganization returns the Organization field. -func (r *Repository) GetOrganization() *Organization { - if r == nil { - return nil - } - return r.Organization -} - -// GetOwner returns the Owner field. -func (r *Repository) GetOwner() *User { - if r == nil { - return nil - } - return r.Owner -} - -// GetParent returns the Parent field. -func (r *Repository) GetParent() *Repository { - if r == nil { - return nil - } - return r.Parent -} - -// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. -func (r *Repository) GetPermissions() map[string]bool { - if r == nil || r.Permissions == nil { - return map[string]bool{} - } - return *r.Permissions -} - -// GetPrivate returns the Private field if it's non-nil, zero value otherwise. -func (r *Repository) GetPrivate() bool { - if r == nil || r.Private == nil { - return false - } - return *r.Private -} - -// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetPullsURL() string { - if r == nil || r.PullsURL == nil { - return "" - } - return *r.PullsURL -} - -// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. -func (r *Repository) GetPushedAt() Timestamp { - if r == nil || r.PushedAt == nil { - return Timestamp{} - } - return *r.PushedAt -} - -// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetReleasesURL() string { - if r == nil || r.ReleasesURL == nil { - return "" - } - return *r.ReleasesURL -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (r *Repository) GetSize() int { - if r == nil || r.Size == nil { - return 0 - } - return *r.Size -} - -// GetSource returns the Source field. -func (r *Repository) GetSource() *Repository { - if r == nil { - return nil - } - return r.Source -} - -// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetSSHURL() string { - if r == nil || r.SSHURL == nil { - return "" - } - return *r.SSHURL -} - -// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetStargazersCount() int { - if r == nil || r.StargazersCount == nil { - return 0 - } - return *r.StargazersCount -} - -// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetStargazersURL() string { - if r == nil || r.StargazersURL == nil { - return "" - } - return *r.StargazersURL -} - -// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetStatusesURL() string { - if r == nil || r.StatusesURL == nil { - return "" - } - return *r.StatusesURL -} - -// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetSubscribersCount() int { - if r == nil || r.SubscribersCount == nil { - return 0 - } - return *r.SubscribersCount -} - -// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetSubscribersURL() string { - if r == nil || r.SubscribersURL == nil { - return "" - } - return *r.SubscribersURL -} - -// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetSubscriptionURL() string { - if r == nil || r.SubscriptionURL == nil { - return "" - } - return *r.SubscriptionURL -} - -// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetSVNURL() string { - if r == nil || r.SVNURL == nil { - return "" - } - return *r.SVNURL -} - -// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetTagsURL() string { - if r == nil || r.TagsURL == nil { - return "" - } - return *r.TagsURL -} - -// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. -func (r *Repository) GetTeamID() int64 { - if r == nil || r.TeamID == nil { - return 0 - } - return *r.TeamID -} - -// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetTeamsURL() string { - if r == nil || r.TeamsURL == nil { - return "" - } - return *r.TeamsURL -} - -// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. -func (r *Repository) GetTreesURL() string { - if r == nil || r.TreesURL == nil { - return "" - } - return *r.TreesURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (r *Repository) GetUpdatedAt() Timestamp { - if r == nil || r.UpdatedAt == nil { - return Timestamp{} - } - return *r.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *Repository) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. -func (r *Repository) GetWatchersCount() int { - if r == nil || r.WatchersCount == nil { - return 0 - } - return *r.WatchersCount -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetBody() string { - if r == nil || r.Body == nil { - return "" - } - return *r.Body -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetCommitID() string { - if r == nil || r.CommitID == nil { - return "" - } - return *r.CommitID -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetCreatedAt() time.Time { - if r == nil || r.CreatedAt == nil { - return time.Time{} - } - return *r.CreatedAt -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetPath() string { - if r == nil || r.Path == nil { - return "" - } - return *r.Path -} - -// GetPosition returns the Position field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetPosition() int { - if r == nil || r.Position == nil { - return 0 - } - return *r.Position -} - -// GetReactions returns the Reactions field. -func (r *RepositoryComment) GetReactions() *Reactions { - if r == nil { - return nil - } - return r.Reactions -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetUpdatedAt() time.Time { - if r == nil || r.UpdatedAt == nil { - return time.Time{} - } - return *r.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryComment) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetUser returns the User field. -func (r *RepositoryComment) GetUser() *User { - if r == nil { - return nil - } - return r.User -} - -// GetAuthor returns the Author field. -func (r *RepositoryCommit) GetAuthor() *User { - if r == nil { - return nil - } - return r.Author -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (r *RepositoryCommit) GetCommentsURL() string { - if r == nil || r.CommentsURL == nil { - return "" - } - return *r.CommentsURL -} - -// GetCommit returns the Commit field. -func (r *RepositoryCommit) GetCommit() *Commit { - if r == nil { - return nil - } - return r.Commit -} - -// GetCommitter returns the Committer field. -func (r *RepositoryCommit) GetCommitter() *User { - if r == nil { - return nil - } - return r.Committer -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryCommit) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (r *RepositoryCommit) GetSHA() string { - if r == nil || r.SHA == nil { - return "" - } - return *r.SHA -} - -// GetStats returns the Stats field. -func (r *RepositoryCommit) GetStats() *CommitStats { - if r == nil { - return nil - } - return r.Stats -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryCommit) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetDownloadURL() string { - if r == nil || r.DownloadURL == nil { - return "" - } - return *r.DownloadURL -} - -// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetEncoding() string { - if r == nil || r.Encoding == nil { - return "" - } - return *r.Encoding -} - -// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetGitURL() string { - if r == nil || r.GitURL == nil { - return "" - } - return *r.GitURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetPath() string { - if r == nil || r.Path == nil { - return "" - } - return *r.Path -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetSHA() string { - if r == nil || r.SHA == nil { - return "" - } - return *r.SHA -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetSize() int { - if r == nil || r.Size == nil { - return 0 - } - return *r.Size -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetType() string { - if r == nil || r.Type == nil { - return "" - } - return *r.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryContent) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetAuthor returns the Author field. -func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { - if r == nil { - return nil - } - return r.Author -} - -// GetBranch returns the Branch field if it's non-nil, zero value otherwise. -func (r *RepositoryContentFileOptions) GetBranch() string { - if r == nil || r.Branch == nil { - return "" - } - return *r.Branch -} - -// GetCommitter returns the Committer field. -func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { - if r == nil { - return nil - } - return r.Committer -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (r *RepositoryContentFileOptions) GetMessage() string { - if r == nil || r.Message == nil { - return "" - } - return *r.Message -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (r *RepositoryContentFileOptions) GetSHA() string { - if r == nil || r.SHA == nil { - return "" - } - return *r.SHA -} - -// GetContent returns the Content field. -func (r *RepositoryContentResponse) GetContent() *RepositoryContent { - if r == nil { - return nil - } - return r.Content -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (r *RepositoryEvent) GetAction() string { - if r == nil || r.Action == nil { - return "" - } - return *r.Action -} - -// GetInstallation returns the Installation field. -func (r *RepositoryEvent) GetInstallation() *Installation { - if r == nil { - return nil - } - return r.Installation -} - -// GetOrg returns the Org field. -func (r *RepositoryEvent) GetOrg() *Organization { - if r == nil { - return nil - } - return r.Org -} - -// GetRepo returns the Repo field. -func (r *RepositoryEvent) GetRepo() *Repository { - if r == nil { - return nil - } - return r.Repo -} - -// GetSender returns the Sender field. -func (r *RepositoryEvent) GetSender() *User { - if r == nil { - return nil - } - return r.Sender -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *RepositoryInvitation) GetCreatedAt() Timestamp { - if r == nil || r.CreatedAt == nil { - return Timestamp{} - } - return *r.CreatedAt -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryInvitation) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *RepositoryInvitation) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetInvitee returns the Invitee field. -func (r *RepositoryInvitation) GetInvitee() *User { - if r == nil { - return nil - } - return r.Invitee -} - -// GetInviter returns the Inviter field. -func (r *RepositoryInvitation) GetInviter() *User { - if r == nil { - return nil - } - return r.Inviter -} - -// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. -func (r *RepositoryInvitation) GetPermissions() string { - if r == nil || r.Permissions == nil { - return "" - } - return *r.Permissions -} - -// GetRepo returns the Repo field. -func (r *RepositoryInvitation) GetRepo() *Repository { - if r == nil { - return nil - } - return r.Repo -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryInvitation) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetContent returns the Content field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetContent() string { - if r == nil || r.Content == nil { - return "" - } - return *r.Content -} - -// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetDownloadURL() string { - if r == nil || r.DownloadURL == nil { - return "" - } - return *r.DownloadURL -} - -// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetEncoding() string { - if r == nil || r.Encoding == nil { - return "" - } - return *r.Encoding -} - -// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetGitURL() string { - if r == nil || r.GitURL == nil { - return "" - } - return *r.GitURL -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetLicense returns the License field. -func (r *RepositoryLicense) GetLicense() *License { - if r == nil { - return nil - } - return r.License -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetPath() string { - if r == nil || r.Path == nil { - return "" - } - return *r.Path -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetSHA() string { - if r == nil || r.SHA == nil { - return "" - } - return *r.SHA -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetSize() int { - if r == nil || r.Size == nil { - return 0 - } - return *r.Size -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetType() string { - if r == nil || r.Type == nil { - return "" - } - return *r.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryLicense) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetBase returns the Base field if it's non-nil, zero value otherwise. -func (r *RepositoryMergeRequest) GetBase() string { - if r == nil || r.Base == nil { - return "" - } - return *r.Base -} - -// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. -func (r *RepositoryMergeRequest) GetCommitMessage() string { - if r == nil || r.CommitMessage == nil { - return "" - } - return *r.CommitMessage -} - -// GetHead returns the Head field if it's non-nil, zero value otherwise. -func (r *RepositoryMergeRequest) GetHead() string { - if r == nil || r.Head == nil { - return "" - } - return *r.Head -} - -// GetPermission returns the Permission field if it's non-nil, zero value otherwise. -func (r *RepositoryPermissionLevel) GetPermission() string { - if r == nil || r.Permission == nil { - return "" - } - return *r.Permission -} - -// GetUser returns the User field. -func (r *RepositoryPermissionLevel) GetUser() *User { - if r == nil { - return nil - } - return r.User -} - -// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetAssetsURL() string { - if r == nil || r.AssetsURL == nil { - return "" - } - return *r.AssetsURL -} - -// GetAuthor returns the Author field. -func (r *RepositoryRelease) GetAuthor() *User { - if r == nil { - return nil - } - return r.Author -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetBody() string { - if r == nil || r.Body == nil { - return "" - } - return *r.Body -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetCreatedAt() Timestamp { - if r == nil || r.CreatedAt == nil { - return Timestamp{} - } - return *r.CreatedAt -} - -// GetDraft returns the Draft field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetDraft() bool { - if r == nil || r.Draft == nil { - return false - } - return *r.Draft -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetHTMLURL() string { - if r == nil || r.HTMLURL == nil { - return "" - } - return *r.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetPrerelease() bool { - if r == nil || r.Prerelease == nil { - return false - } - return *r.Prerelease -} - -// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetPublishedAt() Timestamp { - if r == nil || r.PublishedAt == nil { - return Timestamp{} - } - return *r.PublishedAt -} - -// GetTagName returns the TagName field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetTagName() string { - if r == nil || r.TagName == nil { - return "" - } - return *r.TagName -} - -// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetTarballURL() string { - if r == nil || r.TarballURL == nil { - return "" - } - return *r.TarballURL -} - -// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetTargetCommitish() string { - if r == nil || r.TargetCommitish == nil { - return "" - } - return *r.TargetCommitish -} - -// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetUploadURL() string { - if r == nil || r.UploadURL == nil { - return "" - } - return *r.UploadURL -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. -func (r *RepositoryRelease) GetZipballURL() string { - if r == nil || r.ZipballURL == nil { - return "" - } - return *r.ZipballURL -} - -// GetCommit returns the Commit field. -func (r *RepositoryTag) GetCommit() *Commit { - if r == nil { - return nil - } - return r.Commit -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RepositoryTag) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. -func (r *RepositoryTag) GetTarballURL() string { - if r == nil || r.TarballURL == nil { - return "" - } - return *r.TarballURL -} - -// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. -func (r *RepositoryTag) GetZipballURL() string { - if r == nil || r.ZipballURL == nil { - return "" - } - return *r.ZipballURL -} - -// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetForkRepos() int { - if r == nil || r.ForkRepos == nil { - return 0 - } - return *r.ForkRepos -} - -// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetOrgRepos() int { - if r == nil || r.OrgRepos == nil { - return 0 - } - return *r.OrgRepos -} - -// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetRootRepos() int { - if r == nil || r.RootRepos == nil { - return 0 - } - return *r.RootRepos -} - -// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetTotalPushes() int { - if r == nil || r.TotalPushes == nil { - return 0 - } - return *r.TotalPushes -} - -// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetTotalRepos() int { - if r == nil || r.TotalRepos == nil { - return 0 - } - return *r.TotalRepos -} - -// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. -func (r *RepoStats) GetTotalWikis() int { - if r == nil || r.TotalWikis == nil { - return 0 - } - return *r.TotalWikis -} - -// GetContext returns the Context field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetContext() string { - if r == nil || r.Context == nil { - return "" - } - return *r.Context -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetCreatedAt() time.Time { - if r == nil || r.CreatedAt == nil { - return time.Time{} - } - return *r.CreatedAt -} - -// GetCreator returns the Creator field. -func (r *RepoStatus) GetCreator() *User { - if r == nil { - return nil - } - return r.Creator -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetDescription() string { - if r == nil || r.Description == nil { - return "" - } - return *r.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetState() string { - if r == nil || r.State == nil { - return "" - } - return *r.State -} - -// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetTargetURL() string { - if r == nil || r.TargetURL == nil { - return "" - } - return *r.TargetURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetUpdatedAt() time.Time { - if r == nil || r.UpdatedAt == nil { - return time.Time{} - } - return *r.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (r *RepoStatus) GetURL() string { - if r == nil || r.URL == nil { - return "" - } - return *r.URL -} - -// GetStrict returns the Strict field if it's non-nil, zero value otherwise. -func (r *RequiredStatusChecksRequest) GetStrict() bool { - if r == nil || r.Strict == nil { - return false - } - return *r.Strict -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (s *ServiceHook) GetName() string { - if s == nil || s.Name == nil { - return "" - } - return *s.Name -} - -// GetPayload returns the Payload field if it's non-nil, zero value otherwise. -func (s *SignatureVerification) GetPayload() string { - if s == nil || s.Payload == nil { - return "" - } - return *s.Payload -} - -// GetReason returns the Reason field if it's non-nil, zero value otherwise. -func (s *SignatureVerification) GetReason() string { - if s == nil || s.Reason == nil { - return "" - } - return *s.Reason -} - -// GetSignature returns the Signature field if it's non-nil, zero value otherwise. -func (s *SignatureVerification) GetSignature() string { - if s == nil || s.Signature == nil { - return "" - } - return *s.Signature -} - -// GetVerified returns the Verified field if it's non-nil, zero value otherwise. -func (s *SignatureVerification) GetVerified() bool { - if s == nil || s.Verified == nil { - return false - } - return *s.Verified -} - -// GetActor returns the Actor field. -func (s *Source) GetActor() *User { - if s == nil { - return nil - } - return s.Actor -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (s *Source) GetID() int64 { - if s == nil || s.ID == nil { - return 0 - } - return *s.ID -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (s *Source) GetURL() string { - if s == nil || s.URL == nil { - return "" - } - return *s.URL -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetEmail() string { - if s == nil || s.Email == nil { - return "" - } - return *s.Email -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetID() int64 { - if s == nil || s.ID == nil { - return 0 - } - return *s.ID -} - -// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetImportURL() string { - if s == nil || s.ImportURL == nil { - return "" - } - return *s.ImportURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetName() string { - if s == nil || s.Name == nil { - return "" - } - return *s.Name -} - -// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetRemoteID() string { - if s == nil || s.RemoteID == nil { - return "" - } - return *s.RemoteID -} - -// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetRemoteName() string { - if s == nil || s.RemoteName == nil { - return "" - } - return *s.RemoteName -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (s *SourceImportAuthor) GetURL() string { - if s == nil || s.URL == nil { - return "" - } - return *s.URL -} - -// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. -func (s *Stargazer) GetStarredAt() Timestamp { - if s == nil || s.StarredAt == nil { - return Timestamp{} - } - return *s.StarredAt -} - -// GetUser returns the User field. -func (s *Stargazer) GetUser() *User { - if s == nil { - return nil - } - return s.User -} - -// GetRepository returns the Repository field. -func (s *StarredRepository) GetRepository() *Repository { - if s == nil { - return nil - } - return s.Repository -} - -// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. -func (s *StarredRepository) GetStarredAt() Timestamp { - if s == nil || s.StarredAt == nil { - return Timestamp{} - } - return *s.StarredAt -} - -// GetCommit returns the Commit field. -func (s *StatusEvent) GetCommit() *RepositoryCommit { - if s == nil { - return nil - } - return s.Commit -} - -// GetContext returns the Context field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetContext() string { - if s == nil || s.Context == nil { - return "" - } - return *s.Context -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetCreatedAt() Timestamp { - if s == nil || s.CreatedAt == nil { - return Timestamp{} - } - return *s.CreatedAt -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetDescription() string { - if s == nil || s.Description == nil { - return "" - } - return *s.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetID() int64 { - if s == nil || s.ID == nil { - return 0 - } - return *s.ID -} - -// GetInstallation returns the Installation field. -func (s *StatusEvent) GetInstallation() *Installation { - if s == nil { - return nil - } - return s.Installation -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetName() string { - if s == nil || s.Name == nil { - return "" - } - return *s.Name -} - -// GetRepo returns the Repo field. -func (s *StatusEvent) GetRepo() *Repository { - if s == nil { - return nil - } - return s.Repo -} - -// GetSender returns the Sender field. -func (s *StatusEvent) GetSender() *User { - if s == nil { - return nil - } - return s.Sender -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetSHA() string { - if s == nil || s.SHA == nil { - return "" - } - return *s.SHA -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetState() string { - if s == nil || s.State == nil { - return "" - } - return *s.State -} - -// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetTargetURL() string { - if s == nil || s.TargetURL == nil { - return "" - } - return *s.TargetURL -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (s *StatusEvent) GetUpdatedAt() Timestamp { - if s == nil || s.UpdatedAt == nil { - return Timestamp{} - } - return *s.UpdatedAt -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (s *Subscription) GetCreatedAt() Timestamp { - if s == nil || s.CreatedAt == nil { - return Timestamp{} - } - return *s.CreatedAt -} - -// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. -func (s *Subscription) GetIgnored() bool { - if s == nil || s.Ignored == nil { - return false - } - return *s.Ignored -} - -// GetReason returns the Reason field if it's non-nil, zero value otherwise. -func (s *Subscription) GetReason() string { - if s == nil || s.Reason == nil { - return "" - } - return *s.Reason -} - -// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. -func (s *Subscription) GetRepositoryURL() string { - if s == nil || s.RepositoryURL == nil { - return "" - } - return *s.RepositoryURL -} - -// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. -func (s *Subscription) GetSubscribed() bool { - if s == nil || s.Subscribed == nil { - return false - } - return *s.Subscribed -} - -// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. -func (s *Subscription) GetThreadURL() string { - if s == nil || s.ThreadURL == nil { - return "" - } - return *s.ThreadURL -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (s *Subscription) GetURL() string { - if s == nil || s.URL == nil { - return "" - } - return *s.URL -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (t *Tag) GetMessage() string { - if t == nil || t.Message == nil { - return "" - } - return *t.Message -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (t *Tag) GetNodeID() string { - if t == nil || t.NodeID == nil { - return "" - } - return *t.NodeID -} - -// GetObject returns the Object field. -func (t *Tag) GetObject() *GitObject { - if t == nil { - return nil - } - return t.Object -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (t *Tag) GetSHA() string { - if t == nil || t.SHA == nil { - return "" - } - return *t.SHA -} - -// GetTag returns the Tag field if it's non-nil, zero value otherwise. -func (t *Tag) GetTag() string { - if t == nil || t.Tag == nil { - return "" - } - return *t.Tag -} - -// GetTagger returns the Tagger field. -func (t *Tag) GetTagger() *CommitAuthor { - if t == nil { - return nil - } - return t.Tagger -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *Tag) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetVerification returns the Verification field. -func (t *Tag) GetVerification() *SignatureVerification { - if t == nil { - return nil - } - return t.Verification -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (t *Team) GetDescription() string { - if t == nil || t.Description == nil { - return "" - } - return *t.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (t *Team) GetID() int64 { - if t == nil || t.ID == nil { - return 0 - } - return *t.ID -} - -// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. -func (t *Team) GetLDAPDN() string { - if t == nil || t.LDAPDN == nil { - return "" - } - return *t.LDAPDN -} - -// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. -func (t *Team) GetMembersCount() int { - if t == nil || t.MembersCount == nil { - return 0 - } - return *t.MembersCount -} - -// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. -func (t *Team) GetMembersURL() string { - if t == nil || t.MembersURL == nil { - return "" - } - return *t.MembersURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (t *Team) GetName() string { - if t == nil || t.Name == nil { - return "" - } - return *t.Name -} - -// GetOrganization returns the Organization field. -func (t *Team) GetOrganization() *Organization { - if t == nil { - return nil - } - return t.Organization -} - -// GetParent returns the Parent field. -func (t *Team) GetParent() *Team { - if t == nil { - return nil - } - return t.Parent -} - -// GetPermission returns the Permission field if it's non-nil, zero value otherwise. -func (t *Team) GetPermission() string { - if t == nil || t.Permission == nil { - return "" - } - return *t.Permission -} - -// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. -func (t *Team) GetPrivacy() string { - if t == nil || t.Privacy == nil { - return "" - } - return *t.Privacy -} - -// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. -func (t *Team) GetReposCount() int { - if t == nil || t.ReposCount == nil { - return 0 - } - return *t.ReposCount -} - -// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. -func (t *Team) GetRepositoriesURL() string { - if t == nil || t.RepositoriesURL == nil { - return "" - } - return *t.RepositoriesURL -} - -// GetSlug returns the Slug field if it's non-nil, zero value otherwise. -func (t *Team) GetSlug() string { - if t == nil || t.Slug == nil { - return "" - } - return *t.Slug -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *Team) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetInstallation returns the Installation field. -func (t *TeamAddEvent) GetInstallation() *Installation { - if t == nil { - return nil - } - return t.Installation -} - -// GetOrg returns the Org field. -func (t *TeamAddEvent) GetOrg() *Organization { - if t == nil { - return nil - } - return t.Org -} - -// GetRepo returns the Repo field. -func (t *TeamAddEvent) GetRepo() *Repository { - if t == nil { - return nil - } - return t.Repo -} - -// GetSender returns the Sender field. -func (t *TeamAddEvent) GetSender() *User { - if t == nil { - return nil - } - return t.Sender -} - -// GetTeam returns the Team field. -func (t *TeamAddEvent) GetTeam() *Team { - if t == nil { - return nil - } - return t.Team -} - -// GetAuthor returns the Author field. -func (t *TeamDiscussion) GetAuthor() *User { - if t == nil { - return nil - } - return t.Author -} - -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetBody() string { - if t == nil || t.Body == nil { - return "" - } - return *t.Body -} - -// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetBodyHTML() string { - if t == nil || t.BodyHTML == nil { - return "" - } - return *t.BodyHTML -} - -// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetBodyVersion() string { - if t == nil || t.BodyVersion == nil { - return "" - } - return *t.BodyVersion -} - -// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetCommentsCount() int { - if t == nil || t.CommentsCount == nil { - return 0 - } - return *t.CommentsCount -} - -// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetCommentsURL() string { - if t == nil || t.CommentsURL == nil { - return "" - } - return *t.CommentsURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetCreatedAt() Timestamp { - if t == nil || t.CreatedAt == nil { - return Timestamp{} - } - return *t.CreatedAt -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetHTMLURL() string { - if t == nil || t.HTMLURL == nil { - return "" - } - return *t.HTMLURL -} - -// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetLastEditedAt() Timestamp { - if t == nil || t.LastEditedAt == nil { - return Timestamp{} - } - return *t.LastEditedAt -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetNodeID() string { - if t == nil || t.NodeID == nil { - return "" - } - return *t.NodeID -} - -// GetNumber returns the Number field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetNumber() int { - if t == nil || t.Number == nil { - return 0 - } - return *t.Number -} - -// GetPinned returns the Pinned field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetPinned() bool { - if t == nil || t.Pinned == nil { - return false - } - return *t.Pinned -} - -// GetPrivate returns the Private field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetPrivate() bool { - if t == nil || t.Private == nil { - return false - } - return *t.Private -} - -// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetTeamURL() string { - if t == nil || t.TeamURL == nil { - return "" - } - return *t.TeamURL -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetTitle() string { - if t == nil || t.Title == nil { - return "" - } - return *t.Title -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetUpdatedAt() Timestamp { - if t == nil || t.UpdatedAt == nil { - return Timestamp{} - } - return *t.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *TeamDiscussion) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (t *TeamEvent) GetAction() string { - if t == nil || t.Action == nil { - return "" - } - return *t.Action -} - -// GetChanges returns the Changes field. -func (t *TeamEvent) GetChanges() *TeamChange { - if t == nil { - return nil - } - return t.Changes -} - -// GetInstallation returns the Installation field. -func (t *TeamEvent) GetInstallation() *Installation { - if t == nil { - return nil - } - return t.Installation -} - -// GetOrg returns the Org field. -func (t *TeamEvent) GetOrg() *Organization { - if t == nil { - return nil - } - return t.Org -} - -// GetRepo returns the Repo field. -func (t *TeamEvent) GetRepo() *Repository { - if t == nil { - return nil - } - return t.Repo -} - -// GetSender returns the Sender field. -func (t *TeamEvent) GetSender() *User { - if t == nil { - return nil - } - return t.Sender -} - -// GetTeam returns the Team field. -func (t *TeamEvent) GetTeam() *Team { - if t == nil { - return nil - } - return t.Team -} - -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetDescription() string { - if t == nil || t.Description == nil { - return "" - } - return *t.Description -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetID() int64 { - if t == nil || t.ID == nil { - return 0 - } - return *t.ID -} - -// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetLDAPDN() string { - if t == nil || t.LDAPDN == nil { - return "" - } - return *t.LDAPDN -} - -// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetMembersURL() string { - if t == nil || t.MembersURL == nil { - return "" - } - return *t.MembersURL -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetName() string { - if t == nil || t.Name == nil { - return "" - } - return *t.Name -} - -// GetPermission returns the Permission field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetPermission() string { - if t == nil || t.Permission == nil { - return "" - } - return *t.Permission -} - -// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetPrivacy() string { - if t == nil || t.Privacy == nil { - return "" - } - return *t.Privacy -} - -// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetRepositoriesURL() string { - if t == nil || t.RepositoriesURL == nil { - return "" - } - return *t.RepositoriesURL -} - -// GetSlug returns the Slug field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetSlug() string { - if t == nil || t.Slug == nil { - return "" - } - return *t.Slug -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *TeamLDAPMapping) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetFragment returns the Fragment field if it's non-nil, zero value otherwise. -func (t *TextMatch) GetFragment() string { - if t == nil || t.Fragment == nil { - return "" - } - return *t.Fragment -} - -// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. -func (t *TextMatch) GetObjectType() string { - if t == nil || t.ObjectType == nil { - return "" - } - return *t.ObjectType -} - -// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. -func (t *TextMatch) GetObjectURL() string { - if t == nil || t.ObjectURL == nil { - return "" - } - return *t.ObjectURL -} - -// GetProperty returns the Property field if it's non-nil, zero value otherwise. -func (t *TextMatch) GetProperty() string { - if t == nil || t.Property == nil { - return "" - } - return *t.Property -} - -// GetActor returns the Actor field. -func (t *Timeline) GetActor() *User { - if t == nil { - return nil - } - return t.Actor -} - -// GetAssignee returns the Assignee field. -func (t *Timeline) GetAssignee() *User { - if t == nil { - return nil - } - return t.Assignee -} - -// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. -func (t *Timeline) GetCommitID() string { - if t == nil || t.CommitID == nil { - return "" - } - return *t.CommitID -} - -// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. -func (t *Timeline) GetCommitURL() string { - if t == nil || t.CommitURL == nil { - return "" - } - return *t.CommitURL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (t *Timeline) GetCreatedAt() time.Time { - if t == nil || t.CreatedAt == nil { - return time.Time{} - } - return *t.CreatedAt -} - -// GetEvent returns the Event field if it's non-nil, zero value otherwise. -func (t *Timeline) GetEvent() string { - if t == nil || t.Event == nil { - return "" - } - return *t.Event -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (t *Timeline) GetID() int64 { - if t == nil || t.ID == nil { - return 0 - } - return *t.ID -} - -// GetLabel returns the Label field. -func (t *Timeline) GetLabel() *Label { - if t == nil { - return nil - } - return t.Label -} - -// GetMilestone returns the Milestone field. -func (t *Timeline) GetMilestone() *Milestone { - if t == nil { - return nil - } - return t.Milestone -} - -// GetRename returns the Rename field. -func (t *Timeline) GetRename() *Rename { - if t == nil { - return nil - } - return t.Rename -} - -// GetSource returns the Source field. -func (t *Timeline) GetSource() *Source { - if t == nil { - return nil - } - return t.Source -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *Timeline) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetCount returns the Count field if it's non-nil, zero value otherwise. -func (t *TrafficClones) GetCount() int { - if t == nil || t.Count == nil { - return 0 - } - return *t.Count -} - -// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. -func (t *TrafficClones) GetUniques() int { - if t == nil || t.Uniques == nil { - return 0 - } - return *t.Uniques -} - -// GetCount returns the Count field if it's non-nil, zero value otherwise. -func (t *TrafficData) GetCount() int { - if t == nil || t.Count == nil { - return 0 - } - return *t.Count -} - -// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. -func (t *TrafficData) GetTimestamp() Timestamp { - if t == nil || t.Timestamp == nil { - return Timestamp{} - } - return *t.Timestamp -} - -// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. -func (t *TrafficData) GetUniques() int { - if t == nil || t.Uniques == nil { - return 0 - } - return *t.Uniques -} - -// GetCount returns the Count field if it's non-nil, zero value otherwise. -func (t *TrafficPath) GetCount() int { - if t == nil || t.Count == nil { - return 0 - } - return *t.Count -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (t *TrafficPath) GetPath() string { - if t == nil || t.Path == nil { - return "" - } - return *t.Path -} - -// GetTitle returns the Title field if it's non-nil, zero value otherwise. -func (t *TrafficPath) GetTitle() string { - if t == nil || t.Title == nil { - return "" - } - return *t.Title -} - -// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. -func (t *TrafficPath) GetUniques() int { - if t == nil || t.Uniques == nil { - return 0 - } - return *t.Uniques -} - -// GetCount returns the Count field if it's non-nil, zero value otherwise. -func (t *TrafficReferrer) GetCount() int { - if t == nil || t.Count == nil { - return 0 - } - return *t.Count -} - -// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. -func (t *TrafficReferrer) GetReferrer() string { - if t == nil || t.Referrer == nil { - return "" - } - return *t.Referrer -} - -// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. -func (t *TrafficReferrer) GetUniques() int { - if t == nil || t.Uniques == nil { - return 0 - } - return *t.Uniques -} - -// GetCount returns the Count field if it's non-nil, zero value otherwise. -func (t *TrafficViews) GetCount() int { - if t == nil || t.Count == nil { - return 0 - } - return *t.Count -} - -// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. -func (t *TrafficViews) GetUniques() int { - if t == nil || t.Uniques == nil { - return 0 - } - return *t.Uniques -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (t *Tree) GetSHA() string { - if t == nil || t.SHA == nil { - return "" - } - return *t.SHA -} - -// GetTruncated returns the Truncated field if it's non-nil, zero value otherwise. -func (t *Tree) GetTruncated() bool { - if t == nil || t.Truncated == nil { - return false - } - return *t.Truncated -} - -// GetContent returns the Content field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetContent() string { - if t == nil || t.Content == nil { - return "" - } - return *t.Content -} - -// GetMode returns the Mode field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetMode() string { - if t == nil || t.Mode == nil { - return "" - } - return *t.Mode -} - -// GetPath returns the Path field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetPath() string { - if t == nil || t.Path == nil { - return "" - } - return *t.Path -} - -// GetSHA returns the SHA field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetSHA() string { - if t == nil || t.SHA == nil { - return "" - } - return *t.SHA -} - -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetSize() int { - if t == nil || t.Size == nil { - return 0 - } - return *t.Size -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetType() string { - if t == nil || t.Type == nil { - return "" - } - return *t.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (t *TreeEntry) GetURL() string { - if t == nil || t.URL == nil { - return "" - } - return *t.URL -} - -// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp { - if u == nil || u.CompletedAt == nil { - return Timestamp{} - } - return *u.CompletedAt -} - -// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetConclusion() string { - if u == nil || u.Conclusion == nil { - return "" - } - return *u.Conclusion -} - -// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetDetailsURL() string { - if u == nil || u.DetailsURL == nil { - return "" - } - return *u.DetailsURL -} - -// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetExternalID() string { - if u == nil || u.ExternalID == nil { - return "" - } - return *u.ExternalID -} - -// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetHeadBranch() string { - if u == nil || u.HeadBranch == nil { - return "" - } - return *u.HeadBranch -} - -// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetHeadSHA() string { - if u == nil || u.HeadSHA == nil { - return "" - } - return *u.HeadSHA -} - -// GetOutput returns the Output field. -func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput { - if u == nil { - return nil - } - return u.Output -} - -// GetStatus returns the Status field if it's non-nil, zero value otherwise. -func (u *UpdateCheckRunOptions) GetStatus() string { - if u == nil || u.Status == nil { - return "" - } - return *u.Status -} - -// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. -func (u *User) GetAvatarURL() string { - if u == nil || u.AvatarURL == nil { - return "" - } - return *u.AvatarURL -} - -// GetBio returns the Bio field if it's non-nil, zero value otherwise. -func (u *User) GetBio() string { - if u == nil || u.Bio == nil { - return "" - } - return *u.Bio -} - -// GetBlog returns the Blog field if it's non-nil, zero value otherwise. -func (u *User) GetBlog() string { - if u == nil || u.Blog == nil { - return "" - } - return *u.Blog -} - -// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. -func (u *User) GetCollaborators() int { - if u == nil || u.Collaborators == nil { - return 0 - } - return *u.Collaborators -} - -// GetCompany returns the Company field if it's non-nil, zero value otherwise. -func (u *User) GetCompany() string { - if u == nil || u.Company == nil { - return "" - } - return *u.Company -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (u *User) GetCreatedAt() Timestamp { - if u == nil || u.CreatedAt == nil { - return Timestamp{} - } - return *u.CreatedAt -} - -// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. -func (u *User) GetDiskUsage() int { - if u == nil || u.DiskUsage == nil { - return 0 - } - return *u.DiskUsage -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (u *User) GetEmail() string { - if u == nil || u.Email == nil { - return "" - } - return *u.Email -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (u *User) GetEventsURL() string { - if u == nil || u.EventsURL == nil { - return "" - } - return *u.EventsURL -} - -// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. -func (u *User) GetFollowers() int { - if u == nil || u.Followers == nil { - return 0 - } - return *u.Followers -} - -// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. -func (u *User) GetFollowersURL() string { - if u == nil || u.FollowersURL == nil { - return "" - } - return *u.FollowersURL -} - -// GetFollowing returns the Following field if it's non-nil, zero value otherwise. -func (u *User) GetFollowing() int { - if u == nil || u.Following == nil { - return 0 - } - return *u.Following -} - -// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. -func (u *User) GetFollowingURL() string { - if u == nil || u.FollowingURL == nil { - return "" - } - return *u.FollowingURL -} - -// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. -func (u *User) GetGistsURL() string { - if u == nil || u.GistsURL == nil { - return "" - } - return *u.GistsURL -} - -// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. -func (u *User) GetGravatarID() string { - if u == nil || u.GravatarID == nil { - return "" - } - return *u.GravatarID -} - -// GetHireable returns the Hireable field if it's non-nil, zero value otherwise. -func (u *User) GetHireable() bool { - if u == nil || u.Hireable == nil { - return false - } - return *u.Hireable -} - -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (u *User) GetHTMLURL() string { - if u == nil || u.HTMLURL == nil { - return "" - } - return *u.HTMLURL -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (u *User) GetID() int64 { - if u == nil || u.ID == nil { - return 0 - } - return *u.ID -} - -// GetLocation returns the Location field if it's non-nil, zero value otherwise. -func (u *User) GetLocation() string { - if u == nil || u.Location == nil { - return "" - } - return *u.Location -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (u *User) GetLogin() string { - if u == nil || u.Login == nil { - return "" - } - return *u.Login -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (u *User) GetName() string { - if u == nil || u.Name == nil { - return "" - } - return *u.Name -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (u *User) GetNodeID() string { - if u == nil || u.NodeID == nil { - return "" - } - return *u.NodeID -} - -// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. -func (u *User) GetOrganizationsURL() string { - if u == nil || u.OrganizationsURL == nil { - return "" - } - return *u.OrganizationsURL -} - -// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. -func (u *User) GetOwnedPrivateRepos() int { - if u == nil || u.OwnedPrivateRepos == nil { - return 0 - } - return *u.OwnedPrivateRepos -} - -// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. -func (u *User) GetPermissions() map[string]bool { - if u == nil || u.Permissions == nil { - return map[string]bool{} - } - return *u.Permissions -} - -// GetPlan returns the Plan field. -func (u *User) GetPlan() *Plan { - if u == nil { - return nil - } - return u.Plan -} - -// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. -func (u *User) GetPrivateGists() int { - if u == nil || u.PrivateGists == nil { - return 0 - } - return *u.PrivateGists -} - -// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. -func (u *User) GetPublicGists() int { - if u == nil || u.PublicGists == nil { - return 0 - } - return *u.PublicGists -} - -// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. -func (u *User) GetPublicRepos() int { - if u == nil || u.PublicRepos == nil { - return 0 - } - return *u.PublicRepos -} - -// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. -func (u *User) GetReceivedEventsURL() string { - if u == nil || u.ReceivedEventsURL == nil { - return "" - } - return *u.ReceivedEventsURL -} - -// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. -func (u *User) GetReposURL() string { - if u == nil || u.ReposURL == nil { - return "" - } - return *u.ReposURL -} - -// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. -func (u *User) GetSiteAdmin() bool { - if u == nil || u.SiteAdmin == nil { - return false - } - return *u.SiteAdmin -} - -// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. -func (u *User) GetStarredURL() string { - if u == nil || u.StarredURL == nil { - return "" - } - return *u.StarredURL -} - -// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. -func (u *User) GetSubscriptionsURL() string { - if u == nil || u.SubscriptionsURL == nil { - return "" - } - return *u.SubscriptionsURL -} - -// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. -func (u *User) GetSuspendedAt() Timestamp { - if u == nil || u.SuspendedAt == nil { - return Timestamp{} - } - return *u.SuspendedAt -} - -// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. -func (u *User) GetTotalPrivateRepos() int { - if u == nil || u.TotalPrivateRepos == nil { - return 0 - } - return *u.TotalPrivateRepos -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (u *User) GetType() string { - if u == nil || u.Type == nil { - return "" - } - return *u.Type -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (u *User) GetUpdatedAt() Timestamp { - if u == nil || u.UpdatedAt == nil { - return Timestamp{} - } - return *u.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (u *User) GetURL() string { - if u == nil || u.URL == nil { - return "" - } - return *u.URL -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (u *UserContext) GetMessage() string { - if u == nil || u.Message == nil { - return "" - } - return *u.Message -} - -// GetOcticon returns the Octicon field if it's non-nil, zero value otherwise. -func (u *UserContext) GetOcticon() string { - if u == nil || u.Octicon == nil { - return "" - } - return *u.Octicon -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (u *UserEmail) GetEmail() string { - if u == nil || u.Email == nil { - return "" - } - return *u.Email -} - -// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. -func (u *UserEmail) GetPrimary() bool { - if u == nil || u.Primary == nil { - return false - } - return *u.Primary -} - -// GetVerified returns the Verified field if it's non-nil, zero value otherwise. -func (u *UserEmail) GetVerified() bool { - if u == nil || u.Verified == nil { - return false - } - return *u.Verified -} - -// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetAvatarURL() string { - if u == nil || u.AvatarURL == nil { - return "" - } - return *u.AvatarURL -} - -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetEventsURL() string { - if u == nil || u.EventsURL == nil { - return "" - } - return *u.EventsURL -} - -// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetFollowersURL() string { - if u == nil || u.FollowersURL == nil { - return "" - } - return *u.FollowersURL -} - -// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetFollowingURL() string { - if u == nil || u.FollowingURL == nil { - return "" - } - return *u.FollowingURL -} - -// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetGistsURL() string { - if u == nil || u.GistsURL == nil { - return "" - } - return *u.GistsURL -} - -// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetGravatarID() string { - if u == nil || u.GravatarID == nil { - return "" - } - return *u.GravatarID -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetID() int64 { - if u == nil || u.ID == nil { - return 0 - } - return *u.ID -} - -// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetLDAPDN() string { - if u == nil || u.LDAPDN == nil { - return "" - } - return *u.LDAPDN -} - -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetLogin() string { - if u == nil || u.Login == nil { - return "" - } - return *u.Login -} - -// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetOrganizationsURL() string { - if u == nil || u.OrganizationsURL == nil { - return "" - } - return *u.OrganizationsURL -} - -// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetReceivedEventsURL() string { - if u == nil || u.ReceivedEventsURL == nil { - return "" - } - return *u.ReceivedEventsURL -} - -// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetReposURL() string { - if u == nil || u.ReposURL == nil { - return "" - } - return *u.ReposURL -} - -// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetSiteAdmin() bool { - if u == nil || u.SiteAdmin == nil { - return false - } - return *u.SiteAdmin -} - -// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetStarredURL() string { - if u == nil || u.StarredURL == nil { - return "" - } - return *u.StarredURL -} - -// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetSubscriptionsURL() string { - if u == nil || u.SubscriptionsURL == nil { - return "" - } - return *u.SubscriptionsURL -} - -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetType() string { - if u == nil || u.Type == nil { - return "" - } - return *u.Type -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (u *UserLDAPMapping) GetURL() string { - if u == nil || u.URL == nil { - return "" - } - return *u.URL -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetCreatedAt() string { - if u == nil || u.CreatedAt == nil { - return "" - } - return *u.CreatedAt -} - -// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetExcludeAttachments() bool { - if u == nil || u.ExcludeAttachments == nil { - return false - } - return *u.ExcludeAttachments -} - -// GetGUID returns the GUID field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetGUID() string { - if u == nil || u.GUID == nil { - return "" - } - return *u.GUID -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetID() int64 { - if u == nil || u.ID == nil { - return 0 - } - return *u.ID -} - -// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetLockRepositories() bool { - if u == nil || u.LockRepositories == nil { - return false - } - return *u.LockRepositories -} - -// GetState returns the State field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetState() string { - if u == nil || u.State == nil { - return "" - } - return *u.State -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetUpdatedAt() string { - if u == nil || u.UpdatedAt == nil { - return "" - } - return *u.UpdatedAt -} - -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (u *UserMigration) GetURL() string { - if u == nil || u.URL == nil { - return "" - } - return *u.URL -} - -// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. -func (u *UsersSearchResult) GetIncompleteResults() bool { - if u == nil || u.IncompleteResults == nil { - return false - } - return *u.IncompleteResults -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (u *UsersSearchResult) GetTotal() int { - if u == nil || u.Total == nil { - return 0 - } - return *u.Total -} - -// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. -func (u *UserStats) GetAdminUsers() int { - if u == nil || u.AdminUsers == nil { - return 0 - } - return *u.AdminUsers -} - -// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. -func (u *UserStats) GetSuspendedUsers() int { - if u == nil || u.SuspendedUsers == nil { - return 0 - } - return *u.SuspendedUsers -} - -// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. -func (u *UserStats) GetTotalUsers() int { - if u == nil || u.TotalUsers == nil { - return 0 - } - return *u.TotalUsers -} - -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (w *WatchEvent) GetAction() string { - if w == nil || w.Action == nil { - return "" - } - return *w.Action -} - -// GetInstallation returns the Installation field. -func (w *WatchEvent) GetInstallation() *Installation { - if w == nil { - return nil - } - return w.Installation -} - -// GetRepo returns the Repo field. -func (w *WatchEvent) GetRepo() *Repository { - if w == nil { - return nil - } - return w.Repo -} - -// GetSender returns the Sender field. -func (w *WatchEvent) GetSender() *User { - if w == nil { - return nil - } - return w.Sender -} - -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (w *WebHookAuthor) GetEmail() string { - if w == nil || w.Email == nil { - return "" - } - return *w.Email -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (w *WebHookAuthor) GetName() string { - if w == nil || w.Name == nil { - return "" - } - return *w.Name -} - -// GetUsername returns the Username field if it's non-nil, zero value otherwise. -func (w *WebHookAuthor) GetUsername() string { - if w == nil || w.Username == nil { - return "" - } - return *w.Username -} - -// GetAuthor returns the Author field. -func (w *WebHookCommit) GetAuthor() *WebHookAuthor { - if w == nil { - return nil - } - return w.Author -} - -// GetCommitter returns the Committer field. -func (w *WebHookCommit) GetCommitter() *WebHookAuthor { - if w == nil { - return nil - } - return w.Committer -} - -// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. -func (w *WebHookCommit) GetDistinct() bool { - if w == nil || w.Distinct == nil { - return false - } - return *w.Distinct -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (w *WebHookCommit) GetID() string { - if w == nil || w.ID == nil { - return "" - } - return *w.ID -} - -// GetMessage returns the Message field if it's non-nil, zero value otherwise. -func (w *WebHookCommit) GetMessage() string { - if w == nil || w.Message == nil { - return "" - } - return *w.Message -} - -// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. -func (w *WebHookCommit) GetTimestamp() time.Time { - if w == nil || w.Timestamp == nil { - return time.Time{} - } - return *w.Timestamp -} - -// GetAfter returns the After field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetAfter() string { - if w == nil || w.After == nil { - return "" - } - return *w.After -} - -// GetBefore returns the Before field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetBefore() string { - if w == nil || w.Before == nil { - return "" - } - return *w.Before -} - -// GetCompare returns the Compare field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetCompare() string { - if w == nil || w.Compare == nil { - return "" - } - return *w.Compare -} - -// GetCreated returns the Created field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetCreated() bool { - if w == nil || w.Created == nil { - return false - } - return *w.Created -} - -// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetDeleted() bool { - if w == nil || w.Deleted == nil { - return false - } - return *w.Deleted -} - -// GetForced returns the Forced field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetForced() bool { - if w == nil || w.Forced == nil { - return false - } - return *w.Forced -} - -// GetHeadCommit returns the HeadCommit field. -func (w *WebHookPayload) GetHeadCommit() *WebHookCommit { - if w == nil { - return nil - } - return w.HeadCommit -} - -// GetPusher returns the Pusher field. -func (w *WebHookPayload) GetPusher() *User { - if w == nil { - return nil - } - return w.Pusher -} - -// GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (w *WebHookPayload) GetRef() string { - if w == nil || w.Ref == nil { - return "" - } - return *w.Ref -} - -// GetRepo returns the Repo field. -func (w *WebHookPayload) GetRepo() *Repository { - if w == nil { - return nil - } - return w.Repo -} - -// GetSender returns the Sender field. -func (w *WebHookPayload) GetSender() *User { - if w == nil { - return nil - } - return w.Sender -} - -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (w *WeeklyCommitActivity) GetTotal() int { - if w == nil || w.Total == nil { - return 0 - } - return *w.Total -} - -// GetWeek returns the Week field if it's non-nil, zero value otherwise. -func (w *WeeklyCommitActivity) GetWeek() Timestamp { - if w == nil || w.Week == nil { - return Timestamp{} - } - return *w.Week -} - -// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. -func (w *WeeklyStats) GetAdditions() int { - if w == nil || w.Additions == nil { - return 0 - } - return *w.Additions -} - -// GetCommits returns the Commits field if it's non-nil, zero value otherwise. -func (w *WeeklyStats) GetCommits() int { - if w == nil || w.Commits == nil { - return 0 - } - return *w.Commits -} - -// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. -func (w *WeeklyStats) GetDeletions() int { - if w == nil || w.Deletions == nil { - return 0 - } - return *w.Deletions -} - -// GetWeek returns the Week field if it's non-nil, zero value otherwise. -func (w *WeeklyStats) GetWeek() Timestamp { - if w == nil || w.Week == nil { - return Timestamp{} - } - return *w.Week -} diff --git a/vendor/github.com/google/go-github/github/github.go b/vendor/github.com/google/go-github/github/github.go deleted file mode 100644 index 0685852d..00000000 --- a/vendor/github.com/google/go-github/github/github.go +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen-accessors.go - -package github - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" - "sync" - "time" - - "github.com/google/go-querystring/query" -) - -const ( - defaultBaseURL = "https://api.github.com/" - uploadBaseURL = "https://uploads.github.com/" - userAgent = "go-github" - - headerRateLimit = "X-RateLimit-Limit" - headerRateRemaining = "X-RateLimit-Remaining" - headerRateReset = "X-RateLimit-Reset" - headerOTP = "X-GitHub-OTP" - - mediaTypeV3 = "application/vnd.github.v3+json" - defaultMediaType = "application/octet-stream" - mediaTypeV3SHA = "application/vnd.github.v3.sha" - mediaTypeV3Diff = "application/vnd.github.v3.diff" - mediaTypeV3Patch = "application/vnd.github.v3.patch" - mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" - - // Media Type values to access preview APIs - - // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ - mediaTypeStarringPreview = "application/vnd.github.v3.star+json" - - // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/ - mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" - - // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ - mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" - - // https://developer.github.com/changes/2016-02-19-source-import-preview-api/ - mediaTypeImportPreview = "application/vnd.github.barred-rock-preview" - - // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ - mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" - - // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ - mediaTypeGitSigningPreview = "application/vnd.github.cryptographer-preview+json" - - // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ - mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" - - // https://developer.github.com/changes/2016-06-14-repository-invitations/ - mediaTypeRepositoryInvitationsPreview = "application/vnd.github.swamp-thing-preview+json" - - // https://developer.github.com/changes/2016-07-06-github-pages-preiew-api/ - mediaTypePagesPreview = "application/vnd.github.mister-fantastic-preview+json" - - // https://developer.github.com/changes/2016-09-14-projects-api/ - mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" - - // https://developer.github.com/changes/2016-09-14-Integrations-Early-Access/ - mediaTypeIntegrationPreview = "application/vnd.github.machine-man-preview+json" - - // https://developer.github.com/changes/2017-01-05-commit-search-api/ - mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" - - // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ - mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" - - // https://developer.github.com/changes/2017-02-09-community-health/ - mediaTypeRepositoryCommunityHealthMetricsPreview = "application/vnd.github.black-panther-preview+json" - - // https://developer.github.com/changes/2017-05-23-coc-api/ - mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" - - // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ - mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" - - // https://developer.github.com/changes/2017-08-30-preview-nested-teams/ - mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json" - - // https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/ - mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json" - - // https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/ - mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json" - - // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ - mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" - - // https://developer.github.com/changes/2018-02-22-label-description-search-preview/ - mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json" - - // https://developer.github.com/changes/2018-02-07-team-discussions-api/ - mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json" - - // https://developer.github.com/changes/2018-03-21-hovercard-api-preview/ - mediaTypeHovercardPreview = "application/vnd.github.hagar-preview+json" - - // https://developer.github.com/changes/2018-01-10-lock-reason-api-preview/ - mediaTypeLockReasonPreview = "application/vnd.github.sailor-v-preview+json" - - // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/ - mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json" - - // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/ - mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview" -) - -// A Client manages communication with the GitHub API. -type Client struct { - clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. - client *http.Client // HTTP client used to communicate with the API. - - // Base URL for API requests. Defaults to the public GitHub API, but can be - // set to a domain endpoint to use with GitHub Enterprise. BaseURL should - // always be specified with a trailing slash. - BaseURL *url.URL - - // Base URL for uploading files. - UploadURL *url.URL - - // User agent used when communicating with the GitHub API. - UserAgent string - - rateMu sync.Mutex - rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls. - - common service // Reuse a single struct instead of allocating one for each service on the heap. - - // Services used for talking to different parts of the GitHub API. - Activity *ActivityService - Admin *AdminService - Apps *AppsService - Authorizations *AuthorizationsService - Checks *ChecksService - Gists *GistsService - Git *GitService - Gitignores *GitignoresService - Issues *IssuesService - Licenses *LicensesService - Marketplace *MarketplaceService - Migrations *MigrationService - Organizations *OrganizationsService - Projects *ProjectsService - PullRequests *PullRequestsService - Reactions *ReactionsService - Repositories *RepositoriesService - Search *SearchService - Teams *TeamsService - Users *UsersService -} - -type service struct { - client *Client -} - -// ListOptions specifies the optional parameters to various List methods that -// support pagination. -type ListOptions struct { - // For paginated result sets, page of results to retrieve. - Page int `url:"page,omitempty"` - - // For paginated result sets, the number of results to include per page. - PerPage int `url:"per_page,omitempty"` -} - -// UploadOptions specifies the parameters to methods that support uploads. -type UploadOptions struct { - Name string `url:"name,omitempty"` -} - -// RawType represents type of raw format of a request instead of JSON. -type RawType uint8 - -const ( - // Diff format. - Diff RawType = 1 + iota - // Patch format. - Patch -) - -// RawOptions specifies parameters when user wants to get raw format of -// a response instead of JSON. -type RawOptions struct { - Type RawType -} - -// addOptions adds the parameters in opt as URL query parameters to s. opt -// must be a struct whose fields may contain "url" tags. -func addOptions(s string, opt interface{}) (string, error) { - v := reflect.ValueOf(opt) - if v.Kind() == reflect.Ptr && v.IsNil() { - return s, nil - } - - u, err := url.Parse(s) - if err != nil { - return s, err - } - - qs, err := query.Values(opt) - if err != nil { - return s, err - } - - u.RawQuery = qs.Encode() - return u.String(), nil -} - -// NewClient returns a new GitHub API client. If a nil httpClient is -// provided, http.DefaultClient will be used. To use API methods which require -// authentication, provide an http.Client that will perform the authentication -// for you (such as that provided by the golang.org/x/oauth2 library). -func NewClient(httpClient *http.Client) *Client { - if httpClient == nil { - httpClient = http.DefaultClient - } - baseURL, _ := url.Parse(defaultBaseURL) - uploadURL, _ := url.Parse(uploadBaseURL) - - c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL} - c.common.client = c - c.Activity = (*ActivityService)(&c.common) - c.Admin = (*AdminService)(&c.common) - c.Apps = (*AppsService)(&c.common) - c.Authorizations = (*AuthorizationsService)(&c.common) - c.Checks = (*ChecksService)(&c.common) - c.Gists = (*GistsService)(&c.common) - c.Git = (*GitService)(&c.common) - c.Gitignores = (*GitignoresService)(&c.common) - c.Issues = (*IssuesService)(&c.common) - c.Licenses = (*LicensesService)(&c.common) - c.Marketplace = &MarketplaceService{client: c} - c.Migrations = (*MigrationService)(&c.common) - c.Organizations = (*OrganizationsService)(&c.common) - c.Projects = (*ProjectsService)(&c.common) - c.PullRequests = (*PullRequestsService)(&c.common) - c.Reactions = (*ReactionsService)(&c.common) - c.Repositories = (*RepositoriesService)(&c.common) - c.Search = (*SearchService)(&c.common) - c.Teams = (*TeamsService)(&c.common) - c.Users = (*UsersService)(&c.common) - return c -} - -// NewEnterpriseClient returns a new GitHub API client with provided -// base URL and upload URL (often the same URL). -// If either URL does not have a trailing slash, one is added automatically. -// If a nil httpClient is provided, http.DefaultClient will be used. -// -// Note that NewEnterpriseClient is a convenience helper only; -// its behavior is equivalent to using NewClient, followed by setting -// the BaseURL and UploadURL fields. -func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { - baseEndpoint, err := url.Parse(baseURL) - if err != nil { - return nil, err - } - if !strings.HasSuffix(baseEndpoint.Path, "/") { - baseEndpoint.Path += "/" - } - - uploadEndpoint, err := url.Parse(uploadURL) - if err != nil { - return nil, err - } - if !strings.HasSuffix(uploadEndpoint.Path, "/") { - uploadEndpoint.Path += "/" - } - - c := NewClient(httpClient) - c.BaseURL = baseEndpoint - c.UploadURL = uploadEndpoint - return c, nil -} - -// NewRequest creates an API request. A relative URL can be provided in urlStr, -// in which case it is resolved relative to the BaseURL of the Client. -// Relative URLs should always be specified without a preceding slash. If -// specified, the value pointed to by body is JSON encoded and included as the -// request body. -func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { - if !strings.HasSuffix(c.BaseURL.Path, "/") { - return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) - } - u, err := c.BaseURL.Parse(urlStr) - if err != nil { - return nil, err - } - - var buf io.ReadWriter - if body != nil { - buf = new(bytes.Buffer) - enc := json.NewEncoder(buf) - enc.SetEscapeHTML(false) - err := enc.Encode(body) - if err != nil { - return nil, err - } - } - - req, err := http.NewRequest(method, u.String(), buf) - if err != nil { - return nil, err - } - - if body != nil { - req.Header.Set("Content-Type", "application/json") - } - req.Header.Set("Accept", mediaTypeV3) - if c.UserAgent != "" { - req.Header.Set("User-Agent", c.UserAgent) - } - return req, nil -} - -// NewUploadRequest creates an upload request. A relative URL can be provided in -// urlStr, in which case it is resolved relative to the UploadURL of the Client. -// Relative URLs should always be specified without a preceding slash. -func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error) { - if !strings.HasSuffix(c.UploadURL.Path, "/") { - return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) - } - u, err := c.UploadURL.Parse(urlStr) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", u.String(), reader) - if err != nil { - return nil, err - } - req.ContentLength = size - - if mediaType == "" { - mediaType = defaultMediaType - } - req.Header.Set("Content-Type", mediaType) - req.Header.Set("Accept", mediaTypeV3) - req.Header.Set("User-Agent", c.UserAgent) - return req, nil -} - -// Response is a GitHub API response. This wraps the standard http.Response -// returned from GitHub and provides convenient access to things like -// pagination links. -type Response struct { - *http.Response - - // These fields provide the page values for paginating through a set of - // results. Any or all of these may be set to the zero value for - // responses that are not part of a paginated set, or for which there - // are no additional pages. - - NextPage int - PrevPage int - FirstPage int - LastPage int - - Rate -} - -// newResponse creates a new Response for the provided http.Response. -// r must not be nil. -func newResponse(r *http.Response) *Response { - response := &Response{Response: r} - response.populatePageValues() - response.Rate = parseRate(r) - return response -} - -// populatePageValues parses the HTTP Link response headers and populates the -// various pagination link values in the Response. -func (r *Response) populatePageValues() { - if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { - for _, link := range strings.Split(links[0], ",") { - segments := strings.Split(strings.TrimSpace(link), ";") - - // link must at least have href and rel - if len(segments) < 2 { - continue - } - - // ensure href is properly formatted - if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { - continue - } - - // try to pull out page parameter - url, err := url.Parse(segments[0][1 : len(segments[0])-1]) - if err != nil { - continue - } - page := url.Query().Get("page") - if page == "" { - continue - } - - for _, segment := range segments[1:] { - switch strings.TrimSpace(segment) { - case `rel="next"`: - r.NextPage, _ = strconv.Atoi(page) - case `rel="prev"`: - r.PrevPage, _ = strconv.Atoi(page) - case `rel="first"`: - r.FirstPage, _ = strconv.Atoi(page) - case `rel="last"`: - r.LastPage, _ = strconv.Atoi(page) - } - - } - } - } -} - -// parseRate parses the rate related headers. -func parseRate(r *http.Response) Rate { - var rate Rate - if limit := r.Header.Get(headerRateLimit); limit != "" { - rate.Limit, _ = strconv.Atoi(limit) - } - if remaining := r.Header.Get(headerRateRemaining); remaining != "" { - rate.Remaining, _ = strconv.Atoi(remaining) - } - if reset := r.Header.Get(headerRateReset); reset != "" { - if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { - rate.Reset = Timestamp{time.Unix(v, 0)} - } - } - return rate -} - -// Do sends an API request and returns the API response. The API response is -// JSON decoded and stored in the value pointed to by v, or returned as an -// error if an API error has occurred. If v implements the io.Writer -// interface, the raw response body will be written to v, without attempting to -// first decode it. If rate limit is exceeded and reset time is in the future, -// Do returns *RateLimitError immediately without making a network API call. -// -// The provided ctx must be non-nil. If it is canceled or times out, -// ctx.Err() will be returned. -func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { - req = withContext(ctx, req) - - rateLimitCategory := category(req.URL.Path) - - // If we've hit rate limit, don't make further requests before Reset time. - if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { - return &Response{ - Response: err.Response, - Rate: err.Rate, - }, err - } - - resp, err := c.client.Do(req) - if err != nil { - // If we got an error, and the context has been canceled, - // the context's error is probably more useful. - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - - // If the error type is *url.Error, sanitize its URL before returning. - if e, ok := err.(*url.Error); ok { - if url, err := url.Parse(e.URL); err == nil { - e.URL = sanitizeURL(url).String() - return nil, e - } - } - - return nil, err - } - defer resp.Body.Close() - - response := newResponse(resp) - - c.rateMu.Lock() - c.rateLimits[rateLimitCategory] = response.Rate - c.rateMu.Unlock() - - err = CheckResponse(resp) - if err != nil { - // Even though there was an error, we still return the response - // in case the caller wants to inspect it further. - // However, if the error is AcceptedError, decode it below before - // returning from this function and closing the response body. - if _, ok := err.(*AcceptedError); !ok { - return response, err - } - } - - if v != nil { - if w, ok := v.(io.Writer); ok { - io.Copy(w, resp.Body) - } else { - decErr := json.NewDecoder(resp.Body).Decode(v) - if decErr == io.EOF { - decErr = nil // ignore EOF errors caused by empty response body - } - if decErr != nil { - err = decErr - } - } - } - - return response, err -} - -// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from -// current client state in order to quickly check if *RateLimitError can be immediately returned -// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. -// Otherwise it returns nil, and Client.Do should proceed normally. -func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rateLimitCategory) *RateLimitError { - c.rateMu.Lock() - rate := c.rateLimits[rateLimitCategory] - c.rateMu.Unlock() - if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { - // Create a fake response. - resp := &http.Response{ - Status: http.StatusText(http.StatusForbidden), - StatusCode: http.StatusForbidden, - Request: req, - Header: make(http.Header), - Body: ioutil.NopCloser(strings.NewReader("")), - } - return &RateLimitError{ - Rate: rate, - Response: resp, - Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), - } - } - - return nil -} - -/* -An ErrorResponse reports one or more errors caused by an API request. - -GitHub API docs: https://developer.github.com/v3/#client-errors -*/ -type ErrorResponse struct { - Response *http.Response // HTTP response that caused this error - Message string `json:"message"` // error message - Errors []Error `json:"errors"` // more detail on individual errors - // Block is only populated on certain types of errors such as code 451. - // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ - // for more information. - Block *struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - } `json:"block,omitempty"` - // Most errors will also include a documentation_url field pointing - // to some content that might help you resolve the error, see - // https://developer.github.com/v3/#client-errors - DocumentationURL string `json:"documentation_url,omitempty"` -} - -func (r *ErrorResponse) Error() string { - return fmt.Sprintf("%v %v: %d %v %+v", - r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), - r.Response.StatusCode, r.Message, r.Errors) -} - -// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user -// that has two-factor authentication enabled. The request can be reattempted -// by providing a one-time password in the request. -type TwoFactorAuthError ErrorResponse - -func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } - -// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit -// remaining value of 0, and error message starts with "API rate limit exceeded for ". -type RateLimitError struct { - Rate Rate // Rate specifies last known rate limit for the client - Response *http.Response // HTTP response that caused this error - Message string `json:"message"` // error message -} - -func (r *RateLimitError) Error() string { - return fmt.Sprintf("%v %v: %d %v %v", - r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), - r.Response.StatusCode, r.Message, formatRateReset(r.Rate.Reset.Time.Sub(time.Now()))) -} - -// AcceptedError occurs when GitHub returns 202 Accepted response with an -// empty body, which means a job was scheduled on the GitHub side to process -// the information needed and cache it. -// Technically, 202 Accepted is not a real error, it's just used to -// indicate that results are not ready yet, but should be available soon. -// The request can be repeated after some time. -type AcceptedError struct{} - -func (*AcceptedError) Error() string { - return "job scheduled on GitHub side; try again later" -} - -// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the -// "documentation_url" field value equal to "https://developer.github.com/v3/#abuse-rate-limits". -type AbuseRateLimitError struct { - Response *http.Response // HTTP response that caused this error - Message string `json:"message"` // error message - - // RetryAfter is provided with some abuse rate limit errors. If present, - // it is the amount of time that the client should wait before retrying. - // Otherwise, the client should try again later (after an unspecified amount of time). - RetryAfter *time.Duration -} - -func (r *AbuseRateLimitError) Error() string { - return fmt.Sprintf("%v %v: %d %v", - r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), - r.Response.StatusCode, r.Message) -} - -// sanitizeURL redacts the client_secret parameter from the URL which may be -// exposed to the user. -func sanitizeURL(uri *url.URL) *url.URL { - if uri == nil { - return nil - } - params := uri.Query() - if len(params.Get("client_secret")) > 0 { - params.Set("client_secret", "REDACTED") - uri.RawQuery = params.Encode() - } - return uri -} - -/* -An Error reports more details on an individual error in an ErrorResponse. -These are the possible validation error codes: - - missing: - resource does not exist - missing_field: - a required field on a resource has not been set - invalid: - the formatting of a field is invalid - already_exists: - another resource has the same valid as this field - custom: - some resources return this (e.g. github.User.CreateKey()), additional - information is set in the Message field of the Error - -GitHub API docs: https://developer.github.com/v3/#client-errors -*/ -type Error struct { - Resource string `json:"resource"` // resource on which the error occurred - Field string `json:"field"` // field on which the error occurred - Code string `json:"code"` // validation error code - Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. -} - -func (e *Error) Error() string { - return fmt.Sprintf("%v error caused by %v field on %v resource", - e.Code, e.Field, e.Resource) -} - -// CheckResponse checks the API response for errors, and returns them if -// present. A response is considered an error if it has a status code outside -// the 200 range or equal to 202 Accepted. -// API error responses are expected to have either no response -// body, or a JSON response body that maps to ErrorResponse. Any other -// response body will be silently ignored. -// -// The error type will be *RateLimitError for rate limit exceeded errors, -// *AcceptedError for 202 Accepted status codes, -// and *TwoFactorAuthError for two-factor authentication errors. -func CheckResponse(r *http.Response) error { - if r.StatusCode == http.StatusAccepted { - return &AcceptedError{} - } - if c := r.StatusCode; 200 <= c && c <= 299 { - return nil - } - errorResponse := &ErrorResponse{Response: r} - data, err := ioutil.ReadAll(r.Body) - if err == nil && data != nil { - json.Unmarshal(data, errorResponse) - } - switch { - case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): - return (*TwoFactorAuthError)(errorResponse) - case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0" && strings.HasPrefix(errorResponse.Message, "API rate limit exceeded for "): - return &RateLimitError{ - Rate: parseRate(r), - Response: errorResponse.Response, - Message: errorResponse.Message, - } - case r.StatusCode == http.StatusForbidden && strings.HasSuffix(errorResponse.DocumentationURL, "/v3/#abuse-rate-limits"): - abuseRateLimitError := &AbuseRateLimitError{ - Response: errorResponse.Response, - Message: errorResponse.Message, - } - if v := r.Header["Retry-After"]; len(v) > 0 { - // According to GitHub support, the "Retry-After" header value will be - // an integer which represents the number of seconds that one should - // wait before resuming making requests. - retryAfterSeconds, _ := strconv.ParseInt(v[0], 10, 64) // Error handling is noop. - retryAfter := time.Duration(retryAfterSeconds) * time.Second - abuseRateLimitError.RetryAfter = &retryAfter - } - return abuseRateLimitError - default: - return errorResponse - } -} - -// parseBoolResponse determines the boolean result from a GitHub API response. -// Several GitHub API methods return boolean responses indicated by the HTTP -// status code in the response (true indicated by a 204, false indicated by a -// 404). This helper function will determine that result and hide the 404 -// error if present. Any other error will be returned through as-is. -func parseBoolResponse(err error) (bool, error) { - if err == nil { - return true, nil - } - - if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { - // Simply false. In this one case, we do not pass the error through. - return false, nil - } - - // some other real error occurred - return false, err -} - -// Rate represents the rate limit for the current client. -type Rate struct { - // The number of requests per hour the client is currently limited to. - Limit int `json:"limit"` - - // The number of remaining requests the client can make this hour. - Remaining int `json:"remaining"` - - // The time at which the current rate limit will reset. - Reset Timestamp `json:"reset"` -} - -func (r Rate) String() string { - return Stringify(r) -} - -// RateLimits represents the rate limits for the current client. -type RateLimits struct { - // The rate limit for non-search API requests. Unauthenticated - // requests are limited to 60 per hour. Authenticated requests are - // limited to 5,000 per hour. - // - // GitHub API docs: https://developer.github.com/v3/#rate-limiting - Core *Rate `json:"core"` - - // The rate limit for search API requests. Unauthenticated requests - // are limited to 10 requests per minutes. Authenticated requests are - // limited to 30 per minute. - // - // GitHub API docs: https://developer.github.com/v3/search/#rate-limit - Search *Rate `json:"search"` -} - -func (r RateLimits) String() string { - return Stringify(r) -} - -type rateLimitCategory uint8 - -const ( - coreCategory rateLimitCategory = iota - searchCategory - - categories // An array of this length will be able to contain all rate limit categories. -) - -// category returns the rate limit category of the endpoint, determined by Request.URL.Path. -func category(path string) rateLimitCategory { - switch { - default: - return coreCategory - case strings.HasPrefix(path, "/search/"): - return searchCategory - } -} - -// RateLimits returns the rate limits for the current client. -func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { - req, err := c.NewRequest("GET", "rate_limit", nil) - if err != nil { - return nil, nil, err - } - - response := new(struct { - Resources *RateLimits `json:"resources"` - }) - resp, err := c.Do(ctx, req, response) - if err != nil { - return nil, nil, err - } - - if response.Resources != nil { - c.rateMu.Lock() - if response.Resources.Core != nil { - c.rateLimits[coreCategory] = *response.Resources.Core - } - if response.Resources.Search != nil { - c.rateLimits[searchCategory] = *response.Resources.Search - } - c.rateMu.Unlock() - } - - return response.Resources, resp, nil -} - -/* -UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls -that need to use a higher rate limit associated with your OAuth application. - - t := &github.UnauthenticatedRateLimitedTransport{ - ClientID: "your app's client ID", - ClientSecret: "your app's client secret", - } - client := github.NewClient(t.Client()) - -This will append the querystring params client_id=xxx&client_secret=yyy to all -requests. - -See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for -more information. -*/ -type UnauthenticatedRateLimitedTransport struct { - // ClientID is the GitHub OAuth client ID of the current application, which - // can be found by selecting its entry in the list at - // https://github.com/settings/applications. - ClientID string - - // ClientSecret is the GitHub OAuth client secret of the current - // application. - ClientSecret string - - // Transport is the underlying HTTP transport to use when making requests. - // It will default to http.DefaultTransport if nil. - Transport http.RoundTripper -} - -// RoundTrip implements the RoundTripper interface. -func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { - if t.ClientID == "" { - return nil, errors.New("t.ClientID is empty") - } - if t.ClientSecret == "" { - return nil, errors.New("t.ClientSecret is empty") - } - - // To set extra querystring params, we must make a copy of the Request so - // that we don't modify the Request we were given. This is required by the - // specification of http.RoundTripper. - // - // Since we are going to modify only req.URL here, we only need a deep copy - // of req.URL. - req2 := new(http.Request) - *req2 = *req - req2.URL = new(url.URL) - *req2.URL = *req.URL - - q := req2.URL.Query() - q.Set("client_id", t.ClientID) - q.Set("client_secret", t.ClientSecret) - req2.URL.RawQuery = q.Encode() - - // Make the HTTP request. - return t.transport().RoundTrip(req2) -} - -// Client returns an *http.Client that makes requests which are subject to the -// rate limit of your OAuth application. -func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { - return &http.Client{Transport: t} -} - -func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { - if t.Transport != nil { - return t.Transport - } - return http.DefaultTransport -} - -// BasicAuthTransport is an http.RoundTripper that authenticates all requests -// using HTTP Basic Authentication with the provided username and password. It -// additionally supports users who have two-factor authentication enabled on -// their GitHub account. -type BasicAuthTransport struct { - Username string // GitHub username - Password string // GitHub password - OTP string // one-time password for users with two-factor auth enabled - - // Transport is the underlying HTTP transport to use when making requests. - // It will default to http.DefaultTransport if nil. - Transport http.RoundTripper -} - -// RoundTrip implements the RoundTripper interface. -func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { - // To set extra headers, we must make a copy of the Request so - // that we don't modify the Request we were given. This is required by the - // specification of http.RoundTripper. - // - // Since we are going to modify only req.Header here, we only need a deep copy - // of req.Header. - req2 := new(http.Request) - *req2 = *req - req2.Header = make(http.Header, len(req.Header)) - for k, s := range req.Header { - req2.Header[k] = append([]string(nil), s...) - } - - req2.SetBasicAuth(t.Username, t.Password) - if t.OTP != "" { - req2.Header.Set(headerOTP, t.OTP) - } - return t.transport().RoundTrip(req2) -} - -// Client returns an *http.Client that makes requests that are authenticated -// using HTTP Basic Authentication. -func (t *BasicAuthTransport) Client() *http.Client { - return &http.Client{Transport: t} -} - -func (t *BasicAuthTransport) transport() http.RoundTripper { - if t.Transport != nil { - return t.Transport - } - return http.DefaultTransport -} - -// formatRateReset formats d to look like "[rate reset in 2s]" or -// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" -// for the negative cases. -func formatRateReset(d time.Duration) string { - isNegative := d < 0 - if isNegative { - d *= -1 - } - secondsTotal := int(0.5 + d.Seconds()) - minutes := secondsTotal / 60 - seconds := secondsTotal - minutes*60 - - var timeString string - if minutes > 0 { - timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) - } else { - timeString = fmt.Sprintf("%ds", seconds) - } - - if isNegative { - return fmt.Sprintf("[rate limit was reset %v ago]", timeString) - } - return fmt.Sprintf("[rate reset in %v]", timeString) -} - -// Bool is a helper routine that allocates a new bool value -// to store v and returns a pointer to it. -func Bool(v bool) *bool { return &v } - -// Int is a helper routine that allocates a new int value -// to store v and returns a pointer to it. -func Int(v int) *int { return &v } - -// Int64 is a helper routine that allocates a new int64 value -// to store v and returns a pointer to it. -func Int64(v int64) *int64 { return &v } - -// String is a helper routine that allocates a new string value -// to store v and returns a pointer to it. -func String(v string) *string { return &v } diff --git a/vendor/github.com/google/go-github/github/messages.go b/vendor/github.com/google/go-github/github/messages.go deleted file mode 100644 index b8d3380e..00000000 --- a/vendor/github.com/google/go-github/github/messages.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file provides functions for validating payloads from GitHub Webhooks. -// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github - -package github - -import ( - "crypto/hmac" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "hash" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -const ( - // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. - sha1Prefix = "sha1" - // sha256Prefix and sha512Prefix are provided for future compatibility. - sha256Prefix = "sha256" - sha512Prefix = "sha512" - // signatureHeader is the GitHub header key used to pass the HMAC hexdigest. - signatureHeader = "X-Hub-Signature" - // eventTypeHeader is the GitHub header key used to pass the event type. - eventTypeHeader = "X-Github-Event" - // deliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. - deliveryIDHeader = "X-Github-Delivery" -) - -var ( - // eventTypeMapping maps webhooks types to their corresponding go-github struct types. - eventTypeMapping = map[string]string{ - "check_run": "CheckRunEvent", - "check_suite": "CheckSuiteEvent", - "commit_comment": "CommitCommentEvent", - "create": "CreateEvent", - "delete": "DeleteEvent", - "deployment": "DeploymentEvent", - "deployment_status": "DeploymentStatusEvent", - "fork": "ForkEvent", - "gollum": "GollumEvent", - "installation": "InstallationEvent", - "installation_repositories": "InstallationRepositoriesEvent", - "issue_comment": "IssueCommentEvent", - "issues": "IssuesEvent", - "label": "LabelEvent", - "marketplace_purchase": "MarketplacePurchaseEvent", - "member": "MemberEvent", - "membership": "MembershipEvent", - "milestone": "MilestoneEvent", - "organization": "OrganizationEvent", - "org_block": "OrgBlockEvent", - "page_build": "PageBuildEvent", - "ping": "PingEvent", - "project": "ProjectEvent", - "project_card": "ProjectCardEvent", - "project_column": "ProjectColumnEvent", - "public": "PublicEvent", - "pull_request_review": "PullRequestReviewEvent", - "pull_request_review_comment": "PullRequestReviewCommentEvent", - "pull_request": "PullRequestEvent", - "push": "PushEvent", - "repository": "RepositoryEvent", - "release": "ReleaseEvent", - "status": "StatusEvent", - "team": "TeamEvent", - "team_add": "TeamAddEvent", - "watch": "WatchEvent", - } -) - -// genMAC generates the HMAC signature for a message provided the secret key -// and hashFunc. -func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { - mac := hmac.New(hashFunc, key) - mac.Write(message) - return mac.Sum(nil) -} - -// checkMAC reports whether messageMAC is a valid HMAC tag for message. -func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { - expectedMAC := genMAC(message, key, hashFunc) - return hmac.Equal(messageMAC, expectedMAC) -} - -// messageMAC returns the hex-decoded HMAC tag from the signature and its -// corresponding hash function. -func messageMAC(signature string) ([]byte, func() hash.Hash, error) { - if signature == "" { - return nil, nil, errors.New("missing signature") - } - sigParts := strings.SplitN(signature, "=", 2) - if len(sigParts) != 2 { - return nil, nil, fmt.Errorf("error parsing signature %q", signature) - } - - var hashFunc func() hash.Hash - switch sigParts[0] { - case sha1Prefix: - hashFunc = sha1.New - case sha256Prefix: - hashFunc = sha256.New - case sha512Prefix: - hashFunc = sha512.New - default: - return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) - } - - buf, err := hex.DecodeString(sigParts[1]) - if err != nil { - return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) - } - return buf, hashFunc, nil -} - -// ValidatePayload validates an incoming GitHub Webhook event request -// and returns the (JSON) payload. -// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". -// If the Content-Type is neither then an error is returned. -// secretKey is the GitHub Webhook secret message. -// -// Example usage: -// -// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { -// payload, err := github.ValidatePayload(r, s.webhookSecretKey) -// if err != nil { ... } -// // Process payload... -// } -// -func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) { - var body []byte // Raw body that GitHub uses to calculate the signature. - - switch ct := r.Header.Get("Content-Type"); ct { - case "application/json": - var err error - if body, err = ioutil.ReadAll(r.Body); err != nil { - return nil, err - } - - // If the content type is application/json, - // the JSON payload is just the original body. - payload = body - - case "application/x-www-form-urlencoded": - // payloadFormParam is the name of the form parameter that the JSON payload - // will be in if a webhook has its content type set to application/x-www-form-urlencoded. - const payloadFormParam = "payload" - - var err error - if body, err = ioutil.ReadAll(r.Body); err != nil { - return nil, err - } - - // If the content type is application/x-www-form-urlencoded, - // the JSON payload will be under the "payload" form param. - form, err := url.ParseQuery(string(body)) - if err != nil { - return nil, err - } - payload = []byte(form.Get(payloadFormParam)) - - default: - return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct) - } - - sig := r.Header.Get(signatureHeader) - if err := validateSignature(sig, body, secretKey); err != nil { - return nil, err - } - return payload, nil -} - -// validateSignature validates the signature for the given payload. -// signature is the GitHub hash signature delivered in the X-Hub-Signature header. -// payload is the JSON payload sent by GitHub Webhooks. -// secretKey is the GitHub Webhook secret message. -// -// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github -func validateSignature(signature string, payload, secretKey []byte) error { - messageMAC, hashFunc, err := messageMAC(signature) - if err != nil { - return err - } - if !checkMAC(payload, messageMAC, secretKey, hashFunc) { - return errors.New("payload signature check failed") - } - return nil -} - -// WebHookType returns the event type of webhook request r. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers -func WebHookType(r *http.Request) string { - return r.Header.Get(eventTypeHeader) -} - -// DeliveryID returns the unique delivery ID of webhook request r. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers -func DeliveryID(r *http.Request) string { - return r.Header.Get(deliveryIDHeader) -} - -// ParseWebHook parses the event payload. For recognized event types, a -// value of the corresponding struct type will be returned (as returned -// by Event.ParsePayload()). An error will be returned for unrecognized event -// types. -// -// Example usage: -// -// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { -// payload, err := github.ValidatePayload(r, s.webhookSecretKey) -// if err != nil { ... } -// event, err := github.ParseWebHook(github.WebHookType(r), payload) -// if err != nil { ... } -// switch event := event.(type) { -// case *github.CommitCommentEvent: -// processCommitCommentEvent(event) -// case *github.CreateEvent: -// processCreateEvent(event) -// ... -// } -// } -// -func ParseWebHook(messageType string, payload []byte) (interface{}, error) { - eventType, ok := eventTypeMapping[messageType] - if !ok { - return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) - } - - event := Event{ - Type: &eventType, - RawPayload: (*json.RawMessage)(&payload), - } - return event.ParsePayload() -} diff --git a/vendor/github.com/google/go-github/github/misc.go b/vendor/github.com/google/go-github/github/misc.go deleted file mode 100644 index e9b0ea22..00000000 --- a/vendor/github.com/google/go-github/github/misc.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2014 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "bytes" - "context" - "fmt" - "net/url" -) - -// MarkdownOptions specifies optional parameters to the Markdown method. -type MarkdownOptions struct { - // Mode identifies the rendering mode. Possible values are: - // markdown - render a document as plain Markdown, just like - // README files are rendered. - // - // gfm - to render a document as user-content, e.g. like user - // comments or issues are rendered. In GFM mode, hard line breaks are - // always taken into account, and issue and user mentions are linked - // accordingly. - // - // Default is "markdown". - Mode string - - // Context identifies the repository context. Only taken into account - // when rendering as "gfm". - Context string -} - -type markdownRequest struct { - Text *string `json:"text,omitempty"` - Mode *string `json:"mode,omitempty"` - Context *string `json:"context,omitempty"` -} - -// Markdown renders an arbitrary Markdown document. -// -// GitHub API docs: https://developer.github.com/v3/markdown/ -func (c *Client) Markdown(ctx context.Context, text string, opt *MarkdownOptions) (string, *Response, error) { - request := &markdownRequest{Text: String(text)} - if opt != nil { - if opt.Mode != "" { - request.Mode = String(opt.Mode) - } - if opt.Context != "" { - request.Context = String(opt.Context) - } - } - - req, err := c.NewRequest("POST", "markdown", request) - if err != nil { - return "", nil, err - } - - buf := new(bytes.Buffer) - resp, err := c.Do(ctx, req, buf) - if err != nil { - return "", resp, err - } - - return buf.String(), resp, nil -} - -// ListEmojis returns the emojis available to use on GitHub. -// -// GitHub API docs: https://developer.github.com/v3/emojis/ -func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { - req, err := c.NewRequest("GET", "emojis", nil) - if err != nil { - return nil, nil, err - } - - var emoji map[string]string - resp, err := c.Do(ctx, req, &emoji) - if err != nil { - return nil, resp, err - } - - return emoji, resp, nil -} - -// CodeOfConduct represents a code of conduct. -type CodeOfConduct struct { - Name *string `json:"name,omitempty"` - Key *string `json:"key,omitempty"` - URL *string `json:"url,omitempty"` - Body *string `json:"body,omitempty"` -} - -func (c *CodeOfConduct) String() string { - return Stringify(c) -} - -// ListCodesOfConduct returns all codes of conduct. -// -// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#list-all-codes-of-conduct -func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { - req, err := c.NewRequest("GET", "codes_of_conduct", nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeCodesOfConductPreview) - - var cs []*CodeOfConduct - resp, err := c.Do(ctx, req, &cs) - if err != nil { - return nil, resp, err - } - - return cs, resp, nil -} - -// GetCodeOfConduct returns an individual code of conduct. -// -// https://developer.github.com/v3/codes_of_conduct/#get-an-individual-code-of-conduct -func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { - u := fmt.Sprintf("codes_of_conduct/%s", key) - req, err := c.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeCodesOfConductPreview) - - coc := new(CodeOfConduct) - resp, err := c.Do(ctx, req, coc) - if err != nil { - return nil, resp, err - } - - return coc, resp, nil -} - -// APIMeta represents metadata about the GitHub API. -type APIMeta struct { - // An Array of IP addresses in CIDR format specifying the addresses - // that incoming service hooks will originate from on GitHub.com. - Hooks []string `json:"hooks,omitempty"` - - // An Array of IP addresses in CIDR format specifying the Git servers - // for GitHub.com. - Git []string `json:"git,omitempty"` - - // Whether authentication with username and password is supported. - // (GitHub Enterprise instances using CAS or OAuth for authentication - // will return false. Features like Basic Authentication with a - // username and password, sudo mode, and two-factor authentication are - // not supported on these servers.) - VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` - - // An array of IP addresses in CIDR format specifying the addresses - // which serve GitHub Pages websites. - Pages []string `json:"pages,omitempty"` - - // An Array of IP addresses specifying the addresses that source imports - // will originate from on GitHub.com. - Importer []string `json:"importer,omitempty"` -} - -// APIMeta returns information about GitHub.com, the service. Or, if you access -// this endpoint on your organization’s GitHub Enterprise installation, this -// endpoint provides information about that installation. -// -// GitHub API docs: https://developer.github.com/v3/meta/ -func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { - req, err := c.NewRequest("GET", "meta", nil) - if err != nil { - return nil, nil, err - } - - meta := new(APIMeta) - resp, err := c.Do(ctx, req, meta) - if err != nil { - return nil, resp, err - } - - return meta, resp, nil -} - -// Octocat returns an ASCII art octocat with the specified message in a speech -// bubble. If message is empty, a random zen phrase is used. -func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { - u := "octocat" - if message != "" { - u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) - } - - req, err := c.NewRequest("GET", u, nil) - if err != nil { - return "", nil, err - } - - buf := new(bytes.Buffer) - resp, err := c.Do(ctx, req, buf) - if err != nil { - return "", resp, err - } - - return buf.String(), resp, nil -} - -// Zen returns a random line from The Zen of GitHub. -// -// see also: http://warpspire.com/posts/taste/ -func (c *Client) Zen(ctx context.Context) (string, *Response, error) { - req, err := c.NewRequest("GET", "zen", nil) - if err != nil { - return "", nil, err - } - - buf := new(bytes.Buffer) - resp, err := c.Do(ctx, req, buf) - if err != nil { - return "", resp, err - } - - return buf.String(), resp, nil -} - -// ServiceHook represents a hook that has configuration settings, a list of -// available events, and default events. -type ServiceHook struct { - Name *string `json:"name,omitempty"` - Events []string `json:"events,omitempty"` - SupportedEvents []string `json:"supported_events,omitempty"` - Schema [][]string `json:"schema,omitempty"` -} - -func (s *ServiceHook) String() string { - return Stringify(s) -} - -// ListServiceHooks lists all of the available service hooks. -// -// GitHub API docs: https://developer.github.com/webhooks/#services -func (c *Client) ListServiceHooks(ctx context.Context) ([]*ServiceHook, *Response, error) { - u := "hooks" - req, err := c.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var hooks []*ServiceHook - resp, err := c.Do(ctx, req, &hooks) - if err != nil { - return nil, resp, err - } - - return hooks, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/orgs.go b/vendor/github.com/google/go-github/github/orgs.go deleted file mode 100644 index 044dff57..00000000 --- a/vendor/github.com/google/go-github/github/orgs.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" - "time" -) - -// OrganizationsService provides access to the organization related functions -// in the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/orgs/ -type OrganizationsService service - -// Organization represents a GitHub organization account. -type Organization struct { - Login *string `json:"login,omitempty"` - ID *int64 `json:"id,omitempty"` - NodeID *string `json:"node_id,omitempty"` - AvatarURL *string `json:"avatar_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - Name *string `json:"name,omitempty"` - Company *string `json:"company,omitempty"` - Blog *string `json:"blog,omitempty"` - Location *string `json:"location,omitempty"` - Email *string `json:"email,omitempty"` - Description *string `json:"description,omitempty"` - PublicRepos *int `json:"public_repos,omitempty"` - PublicGists *int `json:"public_gists,omitempty"` - Followers *int `json:"followers,omitempty"` - Following *int `json:"following,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - TotalPrivateRepos *int `json:"total_private_repos,omitempty"` - OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` - PrivateGists *int `json:"private_gists,omitempty"` - DiskUsage *int `json:"disk_usage,omitempty"` - Collaborators *int `json:"collaborators,omitempty"` - BillingEmail *string `json:"billing_email,omitempty"` - Type *string `json:"type,omitempty"` - Plan *Plan `json:"plan,omitempty"` - - // API URLs - URL *string `json:"url,omitempty"` - EventsURL *string `json:"events_url,omitempty"` - HooksURL *string `json:"hooks_url,omitempty"` - IssuesURL *string `json:"issues_url,omitempty"` - MembersURL *string `json:"members_url,omitempty"` - PublicMembersURL *string `json:"public_members_url,omitempty"` - ReposURL *string `json:"repos_url,omitempty"` -} - -func (o Organization) String() string { - return Stringify(o) -} - -// Plan represents the payment plan for an account. See plans at https://github.com/plans. -type Plan struct { - Name *string `json:"name,omitempty"` - Space *int `json:"space,omitempty"` - Collaborators *int `json:"collaborators,omitempty"` - PrivateRepos *int `json:"private_repos,omitempty"` -} - -func (p Plan) String() string { - return Stringify(p) -} - -// OrganizationsListOptions specifies the optional parameters to the -// OrganizationsService.ListAll method. -type OrganizationsListOptions struct { - // Since filters Organizations by ID. - Since int64 `url:"since,omitempty"` - - // Note: Pagination is powered exclusively by the Since parameter, - // ListOptions.Page has no effect. - // ListOptions.PerPage controls an undocumented GitHub API parameter. - ListOptions -} - -// ListAll lists all organizations, in the order that they were created on GitHub. -// -// Note: Pagination is powered exclusively by the since parameter. To continue -// listing the next set of organizations, use the ID of the last-returned organization -// as the opts.Since parameter for the next call. -// -// GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations -func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsListOptions) ([]*Organization, *Response, error) { - u, err := addOptions("organizations", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - orgs := []*Organization{} - resp, err := s.client.Do(ctx, req, &orgs) - if err != nil { - return nil, resp, err - } - return orgs, resp, nil -} - -// List the organizations for a user. Passing the empty string will list -// organizations for the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations -func (s *OrganizationsService) List(ctx context.Context, user string, opt *ListOptions) ([]*Organization, *Response, error) { - var u string - if user != "" { - u = fmt.Sprintf("users/%v/orgs", user) - } else { - u = "user/orgs" - } - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var orgs []*Organization - resp, err := s.client.Do(ctx, req, &orgs) - if err != nil { - return nil, resp, err - } - - return orgs, resp, nil -} - -// Get fetches an organization by name. -// -// GitHub API docs: https://developer.github.com/v3/orgs/#get-an-organization -func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { - u := fmt.Sprintf("orgs/%v", org) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - organization := new(Organization) - resp, err := s.client.Do(ctx, req, organization) - if err != nil { - return nil, resp, err - } - - return organization, resp, nil -} - -// GetByID fetches an organization. -// -// Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id. -func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { - u := fmt.Sprintf("organizations/%d", id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - organization := new(Organization) - resp, err := s.client.Do(ctx, req, organization) - if err != nil { - return nil, resp, err - } - - return organization, resp, nil -} - -// Edit an organization. -// -// GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization -func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { - u := fmt.Sprintf("orgs/%v", name) - req, err := s.client.NewRequest("PATCH", u, org) - if err != nil { - return nil, nil, err - } - - o := new(Organization) - resp, err := s.client.Do(ctx, req, o) - if err != nil { - return nil, resp, err - } - - return o, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/orgs_projects.go b/vendor/github.com/google/go-github/github/orgs_projects.go deleted file mode 100644 index e57cba97..00000000 --- a/vendor/github.com/google/go-github/github/orgs_projects.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// ListProjects lists the projects for an organization. -// -// GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects -func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt *ProjectListOptions) ([]*Project, *Response, error) { - u := fmt.Sprintf("orgs/%v/projects", org) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - var projects []*Project - resp, err := s.client.Do(ctx, req, &projects) - if err != nil { - return nil, resp, err - } - - return projects, resp, nil -} - -// CreateProject creates a GitHub Project for the specified organization. -// -// GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project -func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opt *ProjectOptions) (*Project, *Response, error) { - u := fmt.Sprintf("orgs/%v/projects", org) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - project := &Project{} - resp, err := s.client.Do(ctx, req, project) - if err != nil { - return nil, resp, err - } - - return project, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/projects.go b/vendor/github.com/google/go-github/github/projects.go deleted file mode 100644 index 614870f5..00000000 --- a/vendor/github.com/google/go-github/github/projects.go +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// ProjectsService provides access to the projects functions in the -// GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/projects/ -type ProjectsService service - -// Project represents a GitHub Project. -type Project struct { - ID *int64 `json:"id,omitempty"` - URL *string `json:"url,omitempty"` - OwnerURL *string `json:"owner_url,omitempty"` - Name *string `json:"name,omitempty"` - Body *string `json:"body,omitempty"` - Number *int `json:"number,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - NodeID *string `json:"node_id,omitempty"` - - // The User object that generated the project. - Creator *User `json:"creator,omitempty"` -} - -func (p Project) String() string { - return Stringify(p) -} - -// GetProject gets a GitHub Project for a repo. -// -// GitHub API docs: https://developer.github.com/v3/projects/#get-a-project -func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) { - u := fmt.Sprintf("projects/%v", id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - project := &Project{} - resp, err := s.client.Do(ctx, req, project) - if err != nil { - return nil, resp, err - } - - return project, resp, nil -} - -// ProjectOptions specifies the parameters to the -// RepositoriesService.CreateProject and -// ProjectsService.UpdateProject methods. -type ProjectOptions struct { - // The name of the project. (Required for creation; optional for update.) - Name string `json:"name,omitempty"` - // The body of the project. (Optional.) - Body string `json:"body,omitempty"` - - // The following field(s) are only applicable for update. - // They should be left with zero values for creation. - - // State of the project. Either "open" or "closed". (Optional.) - State string `json:"state,omitempty"` -} - -// UpdateProject updates a repository project. -// -// GitHub API docs: https://developer.github.com/v3/projects/#update-a-project -func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opt *ProjectOptions) (*Project, *Response, error) { - u := fmt.Sprintf("projects/%v", id) - req, err := s.client.NewRequest("PATCH", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - project := &Project{} - resp, err := s.client.Do(ctx, req, project) - if err != nil { - return nil, resp, err - } - - return project, resp, nil -} - -// DeleteProject deletes a GitHub Project from a repository. -// -// GitHub API docs: https://developer.github.com/v3/projects/#delete-a-project -func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) { - u := fmt.Sprintf("projects/%v", id) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - return s.client.Do(ctx, req, nil) -} - -// ProjectColumn represents a column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/repos/projects/ -type ProjectColumn struct { - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - ProjectURL *string `json:"project_url,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - NodeID *string `json:"node_id,omitempty"` -} - -// ListProjectColumns lists the columns of a GitHub Project for a repo. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns -func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opt *ListOptions) ([]*ProjectColumn, *Response, error) { - u := fmt.Sprintf("projects/%v/columns", projectID) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - columns := []*ProjectColumn{} - resp, err := s.client.Do(ctx, req, &columns) - if err != nil { - return nil, resp, err - } - - return columns, resp, nil -} - -// GetProjectColumn gets a column of a GitHub Project for a repo. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#get-a-project-column -func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) { - u := fmt.Sprintf("projects/columns/%v", id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - column := &ProjectColumn{} - resp, err := s.client.Do(ctx, req, column) - if err != nil { - return nil, resp, err - } - - return column, resp, nil -} - -// ProjectColumnOptions specifies the parameters to the -// ProjectsService.CreateProjectColumn and -// ProjectsService.UpdateProjectColumn methods. -type ProjectColumnOptions struct { - // The name of the project column. (Required for creation and update.) - Name string `json:"name"` -} - -// CreateProjectColumn creates a column for the specified (by number) project. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column -func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { - u := fmt.Sprintf("projects/%v/columns", projectID) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - column := &ProjectColumn{} - resp, err := s.client.Do(ctx, req, column) - if err != nil { - return nil, resp, err - } - - return column, resp, nil -} - -// UpdateProjectColumn updates a column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column -func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { - u := fmt.Sprintf("projects/columns/%v", columnID) - req, err := s.client.NewRequest("PATCH", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - column := &ProjectColumn{} - resp, err := s.client.Do(ctx, req, column) - if err != nil { - return nil, resp, err - } - - return column, resp, nil -} - -// DeleteProjectColumn deletes a column from a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#delete-a-project-column -func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) { - u := fmt.Sprintf("projects/columns/%v", columnID) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - return s.client.Do(ctx, req, nil) -} - -// ProjectColumnMoveOptions specifies the parameters to the -// ProjectsService.MoveProjectColumn method. -type ProjectColumnMoveOptions struct { - // Position can be one of "first", "last", or "after:", where - // is the ID of a column in the same project. (Required.) - Position string `json:"position"` -} - -// MoveProjectColumn moves a column within a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column -func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnMoveOptions) (*Response, error) { - u := fmt.Sprintf("projects/columns/%v/moves", columnID) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - return s.client.Do(ctx, req, nil) -} - -// ProjectCard represents a card in a column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card -type ProjectCard struct { - URL *string `json:"url,omitempty"` - ColumnURL *string `json:"column_url,omitempty"` - ContentURL *string `json:"content_url,omitempty"` - ID *int64 `json:"id,omitempty"` - Note *string `json:"note,omitempty"` - Creator *User `json:"creator,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Archived *bool `json:"archived,omitempty"` - - // The following fields are only populated by Webhook events. - ColumnID *int64 `json:"column_id,omitempty"` -} - -// ProjectCardListOptions specifies the optional parameters to the -// ProjectsService.ListProjectCards method. -type ProjectCardListOptions struct { - // ArchivedState is used to list all, archived, or not_archived project cards. - // Defaults to not_archived when you omit this parameter. - ArchivedState *string `url:"archived_state,omitempty"` - - ListOptions -} - -// ListProjectCards lists the cards in a column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards -func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opt *ProjectCardListOptions) ([]*ProjectCard, *Response, error) { - u := fmt.Sprintf("projects/columns/%v/cards", columnID) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - cards := []*ProjectCard{} - resp, err := s.client.Do(ctx, req, &cards) - if err != nil { - return nil, resp, err - } - - return cards, resp, nil -} - -// GetProjectCard gets a card in a column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card -func (s *ProjectsService) GetProjectCard(ctx context.Context, columnID int64) (*ProjectCard, *Response, error) { - u := fmt.Sprintf("projects/columns/cards/%v", columnID) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - card := &ProjectCard{} - resp, err := s.client.Do(ctx, req, card) - if err != nil { - return nil, resp, err - } - - return card, resp, nil -} - -// ProjectCardOptions specifies the parameters to the -// ProjectsService.CreateProjectCard and -// ProjectsService.UpdateProjectCard methods. -type ProjectCardOptions struct { - // The note of the card. Note and ContentID are mutually exclusive. - Note string `json:"note,omitempty"` - // The ID (not Number) of the Issue to associate with this card. - // Note and ContentID are mutually exclusive. - ContentID int64 `json:"content_id,omitempty"` - // The type of content to associate with this card. Possible values are: "Issue". - ContentType string `json:"content_type,omitempty"` - // Use true to archive a project card. - // Specify false if you need to restore a previously archived project card. - Archived *bool `json:"archived,omitempty"` -} - -// CreateProjectCard creates a card in the specified column of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card -func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { - u := fmt.Sprintf("projects/columns/%v/cards", columnID) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - card := &ProjectCard{} - resp, err := s.client.Do(ctx, req, card) - if err != nil { - return nil, resp, err - } - - return card, resp, nil -} - -// UpdateProjectCard updates a card of a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card -func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { - u := fmt.Sprintf("projects/columns/cards/%v", cardID) - req, err := s.client.NewRequest("PATCH", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - card := &ProjectCard{} - resp, err := s.client.Do(ctx, req, card) - if err != nil { - return nil, resp, err - } - - return card, resp, nil -} - -// DeleteProjectCard deletes a card from a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#delete-a-project-card -func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) { - u := fmt.Sprintf("projects/columns/cards/%v", cardID) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - return s.client.Do(ctx, req, nil) -} - -// ProjectCardMoveOptions specifies the parameters to the -// ProjectsService.MoveProjectCard method. -type ProjectCardMoveOptions struct { - // Position can be one of "top", "bottom", or "after:", where - // is the ID of a card in the same project. - Position string `json:"position"` - // ColumnID is the ID of a column in the same project. Note that ColumnID - // is required when using Position "after:" when that card is in - // another column; otherwise it is optional. - ColumnID int64 `json:"column_id,omitempty"` -} - -// MoveProjectCard moves a card within a GitHub Project. -// -// GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card -func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opt *ProjectCardMoveOptions) (*Response, error) { - u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/pulls.go b/vendor/github.com/google/go-github/github/pulls.go deleted file mode 100644 index a123ec56..00000000 --- a/vendor/github.com/google/go-github/github/pulls.go +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "bytes" - "context" - "fmt" - "strings" - "time" -) - -// PullRequestsService handles communication with the pull request related -// methods of the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/pulls/ -type PullRequestsService service - -// PullRequest represents a GitHub pull request on a repository. -type PullRequest struct { - ID *int64 `json:"id,omitempty"` - Number *int `json:"number,omitempty"` - State *string `json:"state,omitempty"` - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - ClosedAt *time.Time `json:"closed_at,omitempty"` - MergedAt *time.Time `json:"merged_at,omitempty"` - Labels []*Label `json:"labels,omitempty"` - User *User `json:"user,omitempty"` - Merged *bool `json:"merged,omitempty"` - Mergeable *bool `json:"mergeable,omitempty"` - MergeableState *string `json:"mergeable_state,omitempty"` - MergedBy *User `json:"merged_by,omitempty"` - MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` - Comments *int `json:"comments,omitempty"` - Commits *int `json:"commits,omitempty"` - Additions *int `json:"additions,omitempty"` - Deletions *int `json:"deletions,omitempty"` - ChangedFiles *int `json:"changed_files,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - IssueURL *string `json:"issue_url,omitempty"` - StatusesURL *string `json:"statuses_url,omitempty"` - DiffURL *string `json:"diff_url,omitempty"` - PatchURL *string `json:"patch_url,omitempty"` - CommitsURL *string `json:"commits_url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - ReviewCommentsURL *string `json:"review_comments_url,omitempty"` - ReviewCommentURL *string `json:"review_comment_url,omitempty"` - Assignee *User `json:"assignee,omitempty"` - Assignees []*User `json:"assignees,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` - AuthorAssociation *string `json:"author_association,omitempty"` - NodeID *string `json:"node_id,omitempty"` - RequestedReviewers []*User `json:"requested_reviewers,omitempty"` - - Head *PullRequestBranch `json:"head,omitempty"` - Base *PullRequestBranch `json:"base,omitempty"` - - // ActiveLockReason is populated only when LockReason is provided while locking the pull request. - // Possible values are: "off-topic", "too heated", "resolved", and "spam". - ActiveLockReason *string `json:"active_lock_reason,omitempty"` -} - -func (p PullRequest) String() string { - return Stringify(p) -} - -// PullRequestBranch represents a base or head branch in a GitHub pull request. -type PullRequestBranch struct { - Label *string `json:"label,omitempty"` - Ref *string `json:"ref,omitempty"` - SHA *string `json:"sha,omitempty"` - Repo *Repository `json:"repo,omitempty"` - User *User `json:"user,omitempty"` -} - -// PullRequestListOptions specifies the optional parameters to the -// PullRequestsService.List method. -type PullRequestListOptions struct { - // State filters pull requests based on their state. Possible values are: - // open, closed. Default is "open". - State string `url:"state,omitempty"` - - // Head filters pull requests by head user and branch name in the format of: - // "user:ref-name". - Head string `url:"head,omitempty"` - - // Base filters pull requests by base branch name. - Base string `url:"base,omitempty"` - - // Sort specifies how to sort pull requests. Possible values are: created, - // updated, popularity, long-running. Default is "created". - Sort string `url:"sort,omitempty"` - - // Direction in which to sort pull requests. Possible values are: asc, desc. - // If Sort is "created" or not specified, Default is "desc", otherwise Default - // is "asc" - Direction string `url:"direction,omitempty"` - - ListOptions -} - -// List the pull requests for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests -func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - var pulls []*PullRequest - resp, err := s.client.Do(ctx, req, &pulls) - if err != nil { - return nil, resp, err - } - - return pulls, resp, nil -} - -// Get a single pull request. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request -func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - pull := new(PullRequest) - resp, err := s.client.Do(ctx, req, pull) - if err != nil { - return nil, resp, err - } - - return pull, resp, nil -} - -// GetRaw gets a single pull request in raw (diff or patch) format. -func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opt RawOptions) (string, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return "", nil, err - } - - switch opt.Type { - case Diff: - req.Header.Set("Accept", mediaTypeV3Diff) - case Patch: - req.Header.Set("Accept", mediaTypeV3Patch) - default: - return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) - } - - var buf bytes.Buffer - resp, err := s.client.Do(ctx, req, &buf) - if err != nil { - return "", resp, err - } - - return buf.String(), resp, nil -} - -// NewPullRequest represents a new pull request to be created. -type NewPullRequest struct { - Title *string `json:"title,omitempty"` - Head *string `json:"head,omitempty"` - Base *string `json:"base,omitempty"` - Body *string `json:"body,omitempty"` - Issue *int `json:"issue,omitempty"` - MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` -} - -// Create a new pull request on the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#create-a-pull-request -func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) - req, err := s.client.NewRequest("POST", u, pull) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - - p := new(PullRequest) - resp, err := s.client.Do(ctx, req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil -} - -type pullRequestUpdate struct { - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - State *string `json:"state,omitempty"` - Base *string `json:"base,omitempty"` - MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` -} - -// Edit a pull request. -// pull must not be nil. -// -// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. -// Base.Ref updates the base branch of the pull request. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request -func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { - if pull == nil { - return nil, nil, fmt.Errorf("pull must be provided") - } - - u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) - - update := &pullRequestUpdate{ - Title: pull.Title, - Body: pull.Body, - State: pull.State, - MaintainerCanModify: pull.MaintainerCanModify, - } - if pull.Base != nil { - update.Base = pull.Base.Ref - } - - req, err := s.client.NewRequest("PATCH", u, update) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - p := new(PullRequest) - resp, err := s.client.Do(ctx, req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil -} - -// ListCommits lists the commits in a pull request. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request -func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*RepositoryCommit, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - - var commits []*RepositoryCommit - resp, err := s.client.Do(ctx, req, &commits) - if err != nil { - return nil, resp, err - } - - return commits, resp, nil -} - -// ListFiles lists the files in a pull request. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files -func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*CommitFile, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var commitFiles []*CommitFile - resp, err := s.client.Do(ctx, req, &commitFiles) - if err != nil { - return nil, resp, err - } - - return commitFiles, resp, nil -} - -// IsMerged checks if a pull request has been merged. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged -func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return false, nil, err - } - - resp, err := s.client.Do(ctx, req, nil) - merged, err := parseBoolResponse(err) - return merged, resp, err -} - -// PullRequestMergeResult represents the result of merging a pull request. -type PullRequestMergeResult struct { - SHA *string `json:"sha,omitempty"` - Merged *bool `json:"merged,omitempty"` - Message *string `json:"message,omitempty"` -} - -// PullRequestOptions lets you define how a pull request will be merged. -type PullRequestOptions struct { - CommitTitle string // Extra detail to append to automatic commit message. (Optional.) - SHA string // SHA that pull request head must match to allow merge. (Optional.) - - // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) - MergeMethod string -} - -type pullRequestMergeRequest struct { - CommitMessage string `json:"commit_message"` - CommitTitle string `json:"commit_title,omitempty"` - MergeMethod string `json:"merge_method,omitempty"` - SHA string `json:"sha,omitempty"` -} - -// Merge a pull request (Merge Button™). -// commitMessage is the title for the automatic commit message. -// -// GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-buttontrade -func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) - - pullRequestBody := &pullRequestMergeRequest{CommitMessage: commitMessage} - if options != nil { - pullRequestBody.CommitTitle = options.CommitTitle - pullRequestBody.MergeMethod = options.MergeMethod - pullRequestBody.SHA = options.SHA - } - req, err := s.client.NewRequest("PUT", u, pullRequestBody) - if err != nil { - return nil, nil, err - } - - mergeResult := new(PullRequestMergeResult) - resp, err := s.client.Do(ctx, req, mergeResult) - if err != nil { - return nil, resp, err - } - - return mergeResult, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/reactions.go b/vendor/github.com/google/go-github/github/reactions.go deleted file mode 100644 index 97b2818c..00000000 --- a/vendor/github.com/google/go-github/github/reactions.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2016 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// ReactionsService provides access to the reactions-related functions in the -// GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/reactions/ -type ReactionsService service - -// Reaction represents a GitHub reaction. -type Reaction struct { - // ID is the Reaction ID. - ID *int64 `json:"id,omitempty"` - User *User `json:"user,omitempty"` - NodeID *string `json:"node_id,omitempty"` - // Content is the type of reaction. - // Possible values are: - // "+1", "-1", "laugh", "confused", "heart", "hooray". - Content *string `json:"content,omitempty"` -} - -// Reactions represents a summary of GitHub reactions. -type Reactions struct { - TotalCount *int `json:"total_count,omitempty"` - PlusOne *int `json:"+1,omitempty"` - MinusOne *int `json:"-1,omitempty"` - Laugh *int `json:"laugh,omitempty"` - Confused *int `json:"confused,omitempty"` - Heart *int `json:"heart,omitempty"` - Hooray *int `json:"hooray,omitempty"` - URL *string `json:"url,omitempty"` -} - -func (r Reaction) String() string { - return Stringify(r) -} - -// ListCommentReactions lists the reactions for a commit comment. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment -func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - var m []*Reaction - resp, err := s.client.Do(ctx, req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// CreateCommentReaction creates a reaction for a commit comment. -// Note that if you have already created a reaction of type content, the -// previously created reaction will be returned with Status: 200 OK. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment -func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) - - body := &Reaction{Content: String(content)} - req, err := s.client.NewRequest("POST", u, body) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - m := &Reaction{} - resp, err := s.client.Do(ctx, req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// ListIssueReactions lists the reactions for an issue. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue -func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - var m []*Reaction - resp, err := s.client.Do(ctx, req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// CreateIssueReaction creates a reaction for an issue. -// Note that if you have already created a reaction of type content, the -// previously created reaction will be returned with Status: 200 OK. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue -func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) - - body := &Reaction{Content: String(content)} - req, err := s.client.NewRequest("POST", u, body) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - m := &Reaction{} - resp, err := s.client.Do(ctx, req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// ListIssueCommentReactions lists the reactions for an issue comment. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment -func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - var m []*Reaction - resp, err := s.client.Do(ctx, req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// CreateIssueCommentReaction creates a reaction for an issue comment. -// Note that if you have already created a reaction of type content, the -// previously created reaction will be returned with Status: 200 OK. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment -func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) - - body := &Reaction{Content: String(content)} - req, err := s.client.NewRequest("POST", u, body) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - m := &Reaction{} - resp, err := s.client.Do(ctx, req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// ListPullRequestCommentReactions lists the reactions for a pull request review comment. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment -func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - var m []*Reaction - resp, err := s.client.Do(ctx, req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. -// Note that if you have already created a reaction of type content, the -// previously created reaction will be returned with Status: 200 OK. -// -// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment -func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) - - body := &Reaction{Content: String(content)} - req, err := s.client.NewRequest("POST", u, body) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - m := &Reaction{} - resp, err := s.client.Do(ctx, req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil -} - -// DeleteReaction deletes a reaction. -// -// GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive -func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) { - u := fmt.Sprintf("reactions/%v", id) - - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeReactionsPreview) - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/repos.go b/vendor/github.com/google/go-github/github/repos.go deleted file mode 100644 index fe05272a..00000000 --- a/vendor/github.com/google/go-github/github/repos.go +++ /dev/null @@ -1,1082 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" - "strings" -) - -// RepositoriesService handles communication with the repository related -// methods of the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/repos/ -type RepositoriesService service - -// Repository represents a GitHub repository. -type Repository struct { - ID *int64 `json:"id,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Owner *User `json:"owner,omitempty"` - Name *string `json:"name,omitempty"` - FullName *string `json:"full_name,omitempty"` - Description *string `json:"description,omitempty"` - Homepage *string `json:"homepage,omitempty"` - CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` - DefaultBranch *string `json:"default_branch,omitempty"` - MasterBranch *string `json:"master_branch,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - PushedAt *Timestamp `json:"pushed_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - CloneURL *string `json:"clone_url,omitempty"` - GitURL *string `json:"git_url,omitempty"` - MirrorURL *string `json:"mirror_url,omitempty"` - SSHURL *string `json:"ssh_url,omitempty"` - SVNURL *string `json:"svn_url,omitempty"` - Language *string `json:"language,omitempty"` - Fork *bool `json:"fork,omitempty"` - ForksCount *int `json:"forks_count,omitempty"` - NetworkCount *int `json:"network_count,omitempty"` - OpenIssuesCount *int `json:"open_issues_count,omitempty"` - StargazersCount *int `json:"stargazers_count,omitempty"` - SubscribersCount *int `json:"subscribers_count,omitempty"` - WatchersCount *int `json:"watchers_count,omitempty"` - Size *int `json:"size,omitempty"` - AutoInit *bool `json:"auto_init,omitempty"` - Parent *Repository `json:"parent,omitempty"` - Source *Repository `json:"source,omitempty"` - Organization *Organization `json:"organization,omitempty"` - Permissions *map[string]bool `json:"permissions,omitempty"` - AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` - AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` - AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` - Topics []string `json:"topics,omitempty"` - - // Only provided when using RepositoriesService.Get while in preview - License *License `json:"license,omitempty"` - - // Additional mutable fields when creating and editing a repository - Private *bool `json:"private,omitempty"` - HasIssues *bool `json:"has_issues,omitempty"` - HasWiki *bool `json:"has_wiki,omitempty"` - HasPages *bool `json:"has_pages,omitempty"` - HasProjects *bool `json:"has_projects,omitempty"` - HasDownloads *bool `json:"has_downloads,omitempty"` - LicenseTemplate *string `json:"license_template,omitempty"` - GitignoreTemplate *string `json:"gitignore_template,omitempty"` - Archived *bool `json:"archived,omitempty"` - - // Creating an organization repository. Required for non-owners. - TeamID *int64 `json:"team_id,omitempty"` - - // API URLs - URL *string `json:"url,omitempty"` - ArchiveURL *string `json:"archive_url,omitempty"` - AssigneesURL *string `json:"assignees_url,omitempty"` - BlobsURL *string `json:"blobs_url,omitempty"` - BranchesURL *string `json:"branches_url,omitempty"` - CollaboratorsURL *string `json:"collaborators_url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - CommitsURL *string `json:"commits_url,omitempty"` - CompareURL *string `json:"compare_url,omitempty"` - ContentsURL *string `json:"contents_url,omitempty"` - ContributorsURL *string `json:"contributors_url,omitempty"` - DeploymentsURL *string `json:"deployments_url,omitempty"` - DownloadsURL *string `json:"downloads_url,omitempty"` - EventsURL *string `json:"events_url,omitempty"` - ForksURL *string `json:"forks_url,omitempty"` - GitCommitsURL *string `json:"git_commits_url,omitempty"` - GitRefsURL *string `json:"git_refs_url,omitempty"` - GitTagsURL *string `json:"git_tags_url,omitempty"` - HooksURL *string `json:"hooks_url,omitempty"` - IssueCommentURL *string `json:"issue_comment_url,omitempty"` - IssueEventsURL *string `json:"issue_events_url,omitempty"` - IssuesURL *string `json:"issues_url,omitempty"` - KeysURL *string `json:"keys_url,omitempty"` - LabelsURL *string `json:"labels_url,omitempty"` - LanguagesURL *string `json:"languages_url,omitempty"` - MergesURL *string `json:"merges_url,omitempty"` - MilestonesURL *string `json:"milestones_url,omitempty"` - NotificationsURL *string `json:"notifications_url,omitempty"` - PullsURL *string `json:"pulls_url,omitempty"` - ReleasesURL *string `json:"releases_url,omitempty"` - StargazersURL *string `json:"stargazers_url,omitempty"` - StatusesURL *string `json:"statuses_url,omitempty"` - SubscribersURL *string `json:"subscribers_url,omitempty"` - SubscriptionURL *string `json:"subscription_url,omitempty"` - TagsURL *string `json:"tags_url,omitempty"` - TreesURL *string `json:"trees_url,omitempty"` - TeamsURL *string `json:"teams_url,omitempty"` - - // TextMatches is only populated from search results that request text matches - // See: search.go and https://developer.github.com/v3/search/#text-match-metadata - TextMatches []TextMatch `json:"text_matches,omitempty"` -} - -func (r Repository) String() string { - return Stringify(r) -} - -// RepositoryListOptions specifies the optional parameters to the -// RepositoriesService.List method. -type RepositoryListOptions struct { - // Visibility of repositories to list. Can be one of all, public, or private. - // Default: all - Visibility string `url:"visibility,omitempty"` - - // List repos of given affiliation[s]. - // Comma-separated list of values. Can include: - // * owner: Repositories that are owned by the authenticated user. - // * collaborator: Repositories that the user has been added to as a - // collaborator. - // * organization_member: Repositories that the user has access to through - // being a member of an organization. This includes every repository on - // every team that the user is on. - // Default: owner,collaborator,organization_member - Affiliation string `url:"affiliation,omitempty"` - - // Type of repositories to list. - // Can be one of all, owner, public, private, member. Default: all - // Will cause a 422 error if used in the same request as visibility or - // affiliation. - Type string `url:"type,omitempty"` - - // How to sort the repository list. Can be one of created, updated, pushed, - // full_name. Default: full_name - Sort string `url:"sort,omitempty"` - - // Direction in which to sort repositories. Can be one of asc or desc. - // Default: when using full_name: asc; otherwise desc - Direction string `url:"direction,omitempty"` - - ListOptions -} - -// List the repositories for a user. Passing the empty string will list -// repositories for the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-user-repositories -func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) { - var u string - if user != "" { - u = fmt.Sprintf("users/%v/repos", user) - } else { - u = "user/repos" - } - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - var repos []*Repository - resp, err := s.client.Do(ctx, req, &repos) - if err != nil { - return nil, resp, err - } - - return repos, resp, nil -} - -// RepositoryListByOrgOptions specifies the optional parameters to the -// RepositoriesService.ListByOrg method. -type RepositoryListByOrgOptions struct { - // Type of repositories to list. Possible values are: all, public, private, - // forks, sources, member. Default is "all". - Type string `url:"type,omitempty"` - - ListOptions -} - -// ListByOrg lists the repositories for an organization. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories -func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { - u := fmt.Sprintf("orgs/%v/repos", org) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - var repos []*Repository - resp, err := s.client.Do(ctx, req, &repos) - if err != nil { - return nil, resp, err - } - - return repos, resp, nil -} - -// RepositoryListAllOptions specifies the optional parameters to the -// RepositoriesService.ListAll method. -type RepositoryListAllOptions struct { - // ID of the last repository seen - Since int64 `url:"since,omitempty"` -} - -// ListAll lists all GitHub repositories in the order that they were created. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-all-public-repositories -func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) { - u, err := addOptions("repositories", opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var repos []*Repository - resp, err := s.client.Do(ctx, req, &repos) - if err != nil { - return nil, resp, err - } - - return repos, resp, nil -} - -// Create a new repository. If an organization is specified, the new -// repository will be created under that org. If the empty string is -// specified, it will be created for the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/repos/#create -func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { - var u string - if org != "" { - u = fmt.Sprintf("orgs/%v/repos", org) - } else { - u = "user/repos" - } - - req, err := s.client.NewRequest("POST", u, repo) - if err != nil { - return nil, nil, err - } - - r := new(Repository) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// Get fetches a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#get -func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { - u := fmt.Sprintf("repos/%v/%v", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when the license support fully launches - // https://developer.github.com/v3/licenses/#get-a-repositorys-license - acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) - - repository := new(Repository) - resp, err := s.client.Do(ctx, req, repository) - if err != nil { - return nil, resp, err - } - - return repository, resp, nil -} - -// GetCodeOfConduct gets the contents of a repository's code of conduct. -// -// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct -func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeCodesOfConductPreview) - - coc := new(CodeOfConduct) - resp, err := s.client.Do(ctx, req, coc) - if err != nil { - return nil, resp, err - } - - return coc, resp, nil -} - -// GetByID fetches a repository. -// -// Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. -func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { - u := fmt.Sprintf("repositories/%d", id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - repository := new(Repository) - resp, err := s.client.Do(ctx, req, repository) - if err != nil { - return nil, resp, err - } - - return repository, resp, nil -} - -// Edit updates a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#edit -func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { - u := fmt.Sprintf("repos/%v/%v", owner, repo) - req, err := s.client.NewRequest("PATCH", u, repository) - if err != nil { - return nil, nil, err - } - - r := new(Repository) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// Delete a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#delete-a-repository -func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v", owner, repo) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - -// Contributor represents a repository contributor -type Contributor struct { - Login *string `json:"login,omitempty"` - ID *int64 `json:"id,omitempty"` - AvatarURL *string `json:"avatar_url,omitempty"` - GravatarID *string `json:"gravatar_id,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - FollowersURL *string `json:"followers_url,omitempty"` - FollowingURL *string `json:"following_url,omitempty"` - GistsURL *string `json:"gists_url,omitempty"` - StarredURL *string `json:"starred_url,omitempty"` - SubscriptionsURL *string `json:"subscriptions_url,omitempty"` - OrganizationsURL *string `json:"organizations_url,omitempty"` - ReposURL *string `json:"repos_url,omitempty"` - EventsURL *string `json:"events_url,omitempty"` - ReceivedEventsURL *string `json:"received_events_url,omitempty"` - Type *string `json:"type,omitempty"` - SiteAdmin *bool `json:"site_admin,omitempty"` - Contributions *int `json:"contributions,omitempty"` -} - -// ListContributorsOptions specifies the optional parameters to the -// RepositoriesService.ListContributors method. -type ListContributorsOptions struct { - // Include anonymous contributors in results or not - Anon string `url:"anon,omitempty"` - - ListOptions -} - -// ListContributors lists contributors for a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-contributors -func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var contributor []*Contributor - resp, err := s.client.Do(ctx, req, &contributor) - if err != nil { - return nil, nil, err - } - - return contributor, resp, nil -} - -// ListLanguages lists languages for the specified repository. The returned map -// specifies the languages and the number of bytes of code written in that -// language. For example: -// -// { -// "C": 78769, -// "Python": 7769 -// } -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-languages -func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - languages := make(map[string]int) - resp, err := s.client.Do(ctx, req, &languages) - if err != nil { - return nil, resp, err - } - - return languages, resp, nil -} - -// ListTeams lists the teams for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-teams -func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - var teams []*Team - resp, err := s.client.Do(ctx, req, &teams) - if err != nil { - return nil, resp, err - } - - return teams, resp, nil -} - -// RepositoryTag represents a repository tag. -type RepositoryTag struct { - Name *string `json:"name,omitempty"` - Commit *Commit `json:"commit,omitempty"` - ZipballURL *string `json:"zipball_url,omitempty"` - TarballURL *string `json:"tarball_url,omitempty"` -} - -// ListTags lists tags for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-tags -func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var tags []*RepositoryTag - resp, err := s.client.Do(ctx, req, &tags) - if err != nil { - return nil, resp, err - } - - return tags, resp, nil -} - -// Branch represents a repository branch -type Branch struct { - Name *string `json:"name,omitempty"` - Commit *RepositoryCommit `json:"commit,omitempty"` - Protected *bool `json:"protected,omitempty"` -} - -// Protection represents a repository branch's protection. -type Protection struct { - RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` - RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` - EnforceAdmins *AdminEnforcement `json:"enforce_admins"` - Restrictions *BranchRestrictions `json:"restrictions"` -} - -// ProtectionRequest represents a request to create/edit a branch's protection. -type ProtectionRequest struct { - RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` - RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` - EnforceAdmins bool `json:"enforce_admins"` - Restrictions *BranchRestrictionsRequest `json:"restrictions"` -} - -// RequiredStatusChecks represents the protection status of a individual branch. -type RequiredStatusChecks struct { - // Require branches to be up to date before merging. (Required.) - Strict bool `json:"strict"` - // The list of status checks to require in order to merge into this - // branch. (Required; use []string{} instead of nil for empty list.) - Contexts []string `json:"contexts"` -} - -// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. -type RequiredStatusChecksRequest struct { - Strict *bool `json:"strict,omitempty"` - Contexts []string `json:"contexts,omitempty"` -} - -// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. -type PullRequestReviewsEnforcement struct { - // Specifies which users and teams can dismiss pull request reviews. - DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"` - // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. - DismissStaleReviews bool `json:"dismiss_stale_reviews"` - // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. - RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` - // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. - // Valid values are 1-6. - RequiredApprovingReviewCount int `json:"required_approving_review_count"` -} - -// PullRequestReviewsEnforcementRequest represents request to set the pull request review -// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above -// because the request structure is different from the response structure. -type PullRequestReviewsEnforcementRequest struct { - // Specifies which users and teams should be allowed to dismiss pull request reviews. - // User and team dismissal restrictions are only available for - // organization-owned repositories. Must be nil for personal repositories. - DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` - // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) - DismissStaleReviews bool `json:"dismiss_stale_reviews"` - // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. - RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` - // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. - // Valid values are 1-6. - RequiredApprovingReviewCount int `json:"required_approving_review_count"` -} - -// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review -// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above -// because the patch request does not require all fields to be initialized. -type PullRequestReviewsEnforcementUpdate struct { - // Specifies which users and teams can dismiss pull request reviews. Can be omitted. - DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` - // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. - DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` - // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. - RequireCodeOwnerReviews bool `json:"require_code_owner_reviews,omitempty"` - // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. - // Valid values are 1 - 6. - RequiredApprovingReviewCount int `json:"required_approving_review_count"` -} - -// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. -type AdminEnforcement struct { - URL *string `json:"url,omitempty"` - Enabled bool `json:"enabled"` -} - -// BranchRestrictions represents the restriction that only certain users or -// teams may push to a branch. -type BranchRestrictions struct { - // The list of user logins with push access. - Users []*User `json:"users"` - // The list of team slugs with push access. - Teams []*Team `json:"teams"` -} - -// BranchRestrictionsRequest represents the request to create/edit the -// restriction that only certain users or teams may push to a branch. It is -// separate from BranchRestrictions above because the request structure is -// different from the response structure. -type BranchRestrictionsRequest struct { - // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) - Users []string `json:"users"` - // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) - Teams []string `json:"teams"` -} - -// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. -type DismissalRestrictions struct { - // The list of users who can dimiss pull request reviews. - Users []*User `json:"users"` - // The list of teams which can dismiss pull request reviews. - Teams []*Team `json:"teams"` -} - -// DismissalRestrictionsRequest represents the request to create/edit the -// restriction to allows only specific users or teams to dimiss pull request reviews. It is -// separate from DismissalRestrictions above because the request structure is -// different from the response structure. -// Note: Both Users and Teams must be nil, or both must be non-nil. -type DismissalRestrictionsRequest struct { - // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) - Users *[]string `json:"users,omitempty"` - // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) - Teams *[]string `json:"teams,omitempty"` -} - -// ListBranches lists branches for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-branches -func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - var branches []*Branch - resp, err := s.client.Do(ctx, req, &branches) - if err != nil { - return nil, resp, err - } - - return branches, resp, nil -} - -// GetBranch gets the specified branch for a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#get-branch -func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - b := new(Branch) - resp, err := s.client.Do(ctx, req, b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil -} - -// GetBranchProtection gets the protection of a given branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-branch-protection -func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - p := new(Protection) - resp, err := s.client.Do(ctx, req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil -} - -// GetRequiredStatusChecks gets the required status checks for a given protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch -func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - p := new(RequiredStatusChecks) - resp, err := s.client.Do(ctx, req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil -} - -// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch -func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - resp, err = s.client.Do(ctx, req, &contexts) - if err != nil { - return nil, resp, err - } - - return contexts, resp, nil -} - -// UpdateBranchProtection updates the protection of a given branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-branch-protection -func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) - req, err := s.client.NewRequest("PUT", u, preq) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - p := new(Protection) - resp, err := s.client.Do(ctx, req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil -} - -// RemoveBranchProtection removes the protection of a given branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection -func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - return s.client.Do(ctx, req, nil) -} - -// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch -func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) - req, err := s.client.NewRequest("PATCH", u, sreq) - if err != nil { - return nil, nil, err - } - - sc := new(RequiredStatusChecks) - resp, err := s.client.Do(ctx, req, sc) - if err != nil { - return nil, resp, err - } - - return sc, resp, nil -} - -// License gets the contents of a repository's license if one is detected. -// -// GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license -func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/license", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - r := &RepositoryLicense{} - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch -func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - r := new(PullRequestReviewsEnforcement) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. -// It requires admin access and branch protection to be enabled. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch -func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) - req, err := s.client.NewRequest("PATCH", u, patch) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - r := new(PullRequestReviewsEnforcement) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, err -} - -// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. -// It requires admin access and branch protection to be enabled. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch -func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) - - data := struct { - R []interface{} `json:"dismissal_restrictions"` - }{[]interface{}{}} - - req, err := s.client.NewRequest("PATCH", u, data) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - r := new(PullRequestReviewsEnforcement) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, err -} - -// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch -func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - return s.client.Do(ctx, req, nil) -} - -// GetAdminEnforcement gets admin enforcement information of a protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch -func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - r := new(AdminEnforcement) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// AddAdminEnforcement adds admin enforcement to a protected branch. -// It requires admin access and branch protection to be enabled. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch -func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) - req, err := s.client.NewRequest("POST", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - r := new(AdminEnforcement) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, err -} - -// RemoveAdminEnforcement removes admin enforcement from a protected branch. -// -// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch -func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) - - return s.client.Do(ctx, req, nil) -} - -// repositoryTopics represents a collection of repository topics. -type repositoryTopics struct { - Names []string `json:"names"` -} - -// ListAllTopics lists topics for a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository -func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTopicsPreview) - - topics := new(repositoryTopics) - resp, err := s.client.Do(ctx, req, topics) - if err != nil { - return nil, resp, err - } - - return topics.Names, resp, nil -} - -// ReplaceAllTopics replaces topics for a repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository -func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) - t := &repositoryTopics{ - Names: topics, - } - if t.Names == nil { - t.Names = []string{} - } - req, err := s.client.NewRequest("PUT", u, t) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTopicsPreview) - - t = new(repositoryTopics) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t.Names, resp, nil -} - -// TransferRequest represents a request to transfer a repository. -type TransferRequest struct { - NewOwner string `json:"new_owner"` - TeamID []int64 `json:"team_ids,omitempty"` -} - -// Transfer transfers a repository from one account or organization to another. -// -// This method might return an *AcceptedError and a status code of -// 202. This is because this is the status that GitHub returns to signify that -// it has now scheduled the transfer of the repository in a background task. -// A follow up request, after a delay of a second or so, should result -// in a successful request. -// -// GitHub API docs: https://developer.github.com/v3/repos/#transfer-a-repository -func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) - - req, err := s.client.NewRequest("POST", u, &transfer) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryTransferPreview) - - r := new(Repository) - resp, err := s.client.Do(ctx, req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/repos_contents.go b/vendor/github.com/google/go-github/github/repos_contents.go deleted file mode 100644 index ffb56b90..00000000 --- a/vendor/github.com/google/go-github/github/repos_contents.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Repository contents API methods. -// GitHub API docs: https://developer.github.com/v3/repos/contents/ - -package github - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "path" -) - -// RepositoryContent represents a file or directory in a github repository. -type RepositoryContent struct { - Type *string `json:"type,omitempty"` - Encoding *string `json:"encoding,omitempty"` - Size *int `json:"size,omitempty"` - Name *string `json:"name,omitempty"` - Path *string `json:"path,omitempty"` - // Content contains the actual file content, which may be encoded. - // Callers should call GetContent which will decode the content if - // necessary. - Content *string `json:"content,omitempty"` - SHA *string `json:"sha,omitempty"` - URL *string `json:"url,omitempty"` - GitURL *string `json:"git_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - DownloadURL *string `json:"download_url,omitempty"` -} - -// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. -type RepositoryContentResponse struct { - Content *RepositoryContent `json:"content,omitempty"` - Commit `json:"commit,omitempty"` -} - -// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. -type RepositoryContentFileOptions struct { - Message *string `json:"message,omitempty"` - Content []byte `json:"content,omitempty"` // unencoded - SHA *string `json:"sha,omitempty"` - Branch *string `json:"branch,omitempty"` - Author *CommitAuthor `json:"author,omitempty"` - Committer *CommitAuthor `json:"committer,omitempty"` -} - -// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, -// branch, or tag -type RepositoryContentGetOptions struct { - Ref string `url:"ref,omitempty"` -} - -// String converts RepositoryContent to a string. It's primarily for testing. -func (r RepositoryContent) String() string { - return Stringify(r) -} - -// GetContent returns the content of r, decoding it if necessary. -func (r *RepositoryContent) GetContent() (string, error) { - var encoding string - if r.Encoding != nil { - encoding = *r.Encoding - } - - switch encoding { - case "base64": - c, err := base64.StdEncoding.DecodeString(*r.Content) - return string(c), err - case "": - if r.Content == nil { - return "", nil - } - return *r.Content, nil - default: - return "", fmt.Errorf("unsupported content encoding: %v", encoding) - } -} - -// GetReadme gets the Readme file for the repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme -func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - readme := new(RepositoryContent) - resp, err := s.client.Do(ctx, req, readme) - if err != nil { - return nil, resp, err - } - return readme, resp, nil -} - -// DownloadContents returns an io.ReadCloser that reads the contents of the -// specified file. This function will work with files of any size, as opposed -// to GetContents which is limited to 1 Mb files. It is the caller's -// responsibility to close the ReadCloser. -func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) { - dir := path.Dir(filepath) - filename := path.Base(filepath) - _, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opt) - if err != nil { - return nil, err - } - for _, contents := range dirContents { - if *contents.Name == filename { - if contents.DownloadURL == nil || *contents.DownloadURL == "" { - return nil, fmt.Errorf("No download link found for %s", filepath) - } - resp, err := s.client.client.Get(*contents.DownloadURL) - if err != nil { - return nil, err - } - return resp.Body, nil - } - } - return nil, fmt.Errorf("No file named %s found in %s", filename, dir) -} - -// GetContents can return either the metadata and content of a single file -// (when path references a file) or the metadata of all the files and/or -// subdirectories of a directory (when path references a directory). To make it -// easy to distinguish between both result types and to mimic the API as much -// as possible, both result types will be returned but only one will contain a -// value and the other will be nil. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents -func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { - escapedPath := (&url.URL{Path: path}).String() - u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) - u, err = addOptions(u, opt) - if err != nil { - return nil, nil, nil, err - } - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, nil, err - } - var rawJSON json.RawMessage - resp, err = s.client.Do(ctx, req, &rawJSON) - if err != nil { - return nil, nil, resp, err - } - fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) - if fileUnmarshalError == nil { - return fileContent, nil, resp, nil - } - directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) - if directoryUnmarshalError == nil { - return nil, directoryContent, resp, nil - } - return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) -} - -// CreateFile creates a new file in a repository at the given path and returns -// the commit and file metadata. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#create-a-file -func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { - u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) - req, err := s.client.NewRequest("PUT", u, opt) - if err != nil { - return nil, nil, err - } - createResponse := new(RepositoryContentResponse) - resp, err := s.client.Do(ctx, req, createResponse) - if err != nil { - return nil, resp, err - } - return createResponse, resp, nil -} - -// UpdateFile updates a file in a repository at the given path and returns the -// commit and file metadata. Requires the blob SHA of the file being updated. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#update-a-file -func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { - u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) - req, err := s.client.NewRequest("PUT", u, opt) - if err != nil { - return nil, nil, err - } - updateResponse := new(RepositoryContentResponse) - resp, err := s.client.Do(ctx, req, updateResponse) - if err != nil { - return nil, resp, err - } - return updateResponse, resp, nil -} - -// DeleteFile deletes a file from a repository and returns the commit. -// Requires the blob SHA of the file to be deleted. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file -func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { - u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) - req, err := s.client.NewRequest("DELETE", u, opt) - if err != nil { - return nil, nil, err - } - deleteResponse := new(RepositoryContentResponse) - resp, err := s.client.Do(ctx, req, deleteResponse) - if err != nil { - return nil, resp, err - } - return deleteResponse, resp, nil -} - -// archiveFormat is used to define the archive type when calling GetArchiveLink. -type archiveFormat string - -const ( - // Tarball specifies an archive in gzipped tar format. - Tarball archiveFormat = "tarball" - - // Zipball specifies an archive in zip format. - Zipball archiveFormat = "zipball" -) - -// GetArchiveLink returns an URL to download a tarball or zipball archive for a -// repository. The archiveFormat can be specified by either the github.Tarball -// or github.Zipball constant. -// -// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link -func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) { - u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) - if opt != nil && opt.Ref != "" { - u += fmt.Sprintf("/%s", opt.Ref) - } - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - var resp *http.Response - // Use http.DefaultTransport if no custom Transport is configured - req = withContext(ctx, req) - if s.client.client.Transport == nil { - resp, err = http.DefaultTransport.RoundTrip(req) - } else { - resp, err = s.client.client.Transport.RoundTrip(req) - } - if err != nil { - return nil, nil, err - } - resp.Body.Close() - if resp.StatusCode != http.StatusFound { - return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) - } - parsedURL, err := url.Parse(resp.Header.Get("Location")) - return parsedURL, newResponse(resp), err -} diff --git a/vendor/github.com/google/go-github/github/repos_hooks.go b/vendor/github.com/google/go-github/github/repos_hooks.go deleted file mode 100644 index 1e9e8848..00000000 --- a/vendor/github.com/google/go-github/github/repos_hooks.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" - "time" -) - -// WebHookPayload represents the data that is received from GitHub when a push -// event hook is triggered. The format of these payloads pre-date most of the -// GitHub v3 API, so there are lots of minor incompatibilities with the types -// defined in the rest of the API. Therefore, several types are duplicated -// here to account for these differences. -// -// GitHub API docs: https://help.github.com/articles/post-receive-hooks -type WebHookPayload struct { - After *string `json:"after,omitempty"` - Before *string `json:"before,omitempty"` - Commits []WebHookCommit `json:"commits,omitempty"` - Compare *string `json:"compare,omitempty"` - Created *bool `json:"created,omitempty"` - Deleted *bool `json:"deleted,omitempty"` - Forced *bool `json:"forced,omitempty"` - HeadCommit *WebHookCommit `json:"head_commit,omitempty"` - Pusher *User `json:"pusher,omitempty"` - Ref *string `json:"ref,omitempty"` - Repo *Repository `json:"repository,omitempty"` - Sender *User `json:"sender,omitempty"` -} - -func (w WebHookPayload) String() string { - return Stringify(w) -} - -// WebHookCommit represents the commit variant we receive from GitHub in a -// WebHookPayload. -type WebHookCommit struct { - Added []string `json:"added,omitempty"` - Author *WebHookAuthor `json:"author,omitempty"` - Committer *WebHookAuthor `json:"committer,omitempty"` - Distinct *bool `json:"distinct,omitempty"` - ID *string `json:"id,omitempty"` - Message *string `json:"message,omitempty"` - Modified []string `json:"modified,omitempty"` - Removed []string `json:"removed,omitempty"` - Timestamp *time.Time `json:"timestamp,omitempty"` -} - -func (w WebHookCommit) String() string { - return Stringify(w) -} - -// WebHookAuthor represents the author or committer of a commit, as specified -// in a WebHookCommit. The commit author may not correspond to a GitHub User. -type WebHookAuthor struct { - Email *string `json:"email,omitempty"` - Name *string `json:"name,omitempty"` - Username *string `json:"username,omitempty"` -} - -func (w WebHookAuthor) String() string { - return Stringify(w) -} - -// Hook represents a GitHub (web and service) hook for a repository. -type Hook struct { - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - Name *string `json:"name,omitempty"` - URL *string `json:"url,omitempty"` - Events []string `json:"events,omitempty"` - Active *bool `json:"active,omitempty"` - Config map[string]interface{} `json:"config,omitempty"` - ID *int64 `json:"id,omitempty"` -} - -func (h Hook) String() string { - return Stringify(h) -} - -// CreateHook creates a Hook for the specified repository. -// Name and Config are required fields. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook -func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) - req, err := s.client.NewRequest("POST", u, hook) - if err != nil { - return nil, nil, err - } - - h := new(Hook) - resp, err := s.client.Do(ctx, req, h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil -} - -// ListHooks lists all Hooks for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#list -func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Hook, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var hooks []*Hook - resp, err := s.client.Do(ctx, req, &hooks) - if err != nil { - return nil, resp, err - } - - return hooks, resp, nil -} - -// GetHook returns a single specified Hook. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook -func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - h := new(Hook) - resp, err := s.client.Do(ctx, req, h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil -} - -// EditHook updates a specified Hook. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook -func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) - req, err := s.client.NewRequest("PATCH", u, hook) - if err != nil { - return nil, nil, err - } - h := new(Hook) - resp, err := s.client.Do(ctx, req, h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil -} - -// DeleteHook deletes a specified Hook. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook -func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - return s.client.Do(ctx, req, nil) -} - -// PingHook triggers a 'ping' event to be sent to the Hook. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook -func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) - req, err := s.client.NewRequest("POST", u, nil) - if err != nil { - return nil, err - } - return s.client.Do(ctx, req, nil) -} - -// TestHook triggers a test Hook by github. -// -// GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook -func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) - req, err := s.client.NewRequest("POST", u, nil) - if err != nil { - return nil, err - } - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/repos_merging.go b/vendor/github.com/google/go-github/github/repos_merging.go deleted file mode 100644 index 04383c1a..00000000 --- a/vendor/github.com/google/go-github/github/repos_merging.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// RepositoryMergeRequest represents a request to merge a branch in a -// repository. -type RepositoryMergeRequest struct { - Base *string `json:"base,omitempty"` - Head *string `json:"head,omitempty"` - CommitMessage *string `json:"commit_message,omitempty"` -} - -// Merge a branch in the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge -func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) - req, err := s.client.NewRequest("POST", u, request) - if err != nil { - return nil, nil, err - } - - commit := new(RepositoryCommit) - resp, err := s.client.Do(ctx, req, commit) - if err != nil { - return nil, resp, err - } - - return commit, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/repos_pages.go b/vendor/github.com/google/go-github/github/repos_pages.go deleted file mode 100644 index 94a95f2b..00000000 --- a/vendor/github.com/google/go-github/github/repos_pages.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// Pages represents a GitHub Pages site configuration. -type Pages struct { - URL *string `json:"url,omitempty"` - Status *string `json:"status,omitempty"` - CNAME *string `json:"cname,omitempty"` - Custom404 *bool `json:"custom_404,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` -} - -// PagesError represents a build error for a GitHub Pages site. -type PagesError struct { - Message *string `json:"message,omitempty"` -} - -// PagesBuild represents the build information for a GitHub Pages site. -type PagesBuild struct { - URL *string `json:"url,omitempty"` - Status *string `json:"status,omitempty"` - Error *PagesError `json:"error,omitempty"` - Pusher *User `json:"pusher,omitempty"` - Commit *string `json:"commit,omitempty"` - Duration *int `json:"duration,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` -} - -// GetPagesInfo fetches information about a GitHub Pages site. -// -// GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site -func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypePagesPreview) - - site := new(Pages) - resp, err := s.client.Do(ctx, req, site) - if err != nil { - return nil, resp, err - } - - return site, resp, nil -} - -// ListPagesBuilds lists the builds for a GitHub Pages site. -// -// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds -func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PagesBuild, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var pages []*PagesBuild - resp, err := s.client.Do(ctx, req, &pages) - if err != nil { - return nil, resp, err - } - - return pages, resp, nil -} - -// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. -// -// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build -func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - build := new(PagesBuild) - resp, err := s.client.Do(ctx, req, build) - if err != nil { - return nil, resp, err - } - - return build, resp, nil -} - -// GetPageBuild fetches the specific build information for a GitHub pages site. -// -// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build -func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - build := new(PagesBuild) - resp, err := s.client.Do(ctx, req, build) - if err != nil { - return nil, resp, err - } - - return build, resp, nil -} - -// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. -// -// GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build -func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) - req, err := s.client.NewRequest("POST", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypePagesPreview) - - build := new(PagesBuild) - resp, err := s.client.Do(ctx, req, build) - if err != nil { - return nil, resp, err - } - - return build, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/repos_projects.go b/vendor/github.com/google/go-github/github/repos_projects.go deleted file mode 100644 index d6486d29..00000000 --- a/vendor/github.com/google/go-github/github/repos_projects.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2017 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// ProjectListOptions specifies the optional parameters to the -// OrganizationsService.ListProjects and RepositoriesService.ListProjects methods. -type ProjectListOptions struct { - // Indicates the state of the projects to return. Can be either open, closed, or all. Default: open - State string `url:"state,omitempty"` - - ListOptions -} - -// ListProjects lists the projects for a repo. -// -// GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects -func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opt *ProjectListOptions) ([]*Project, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - var projects []*Project - resp, err := s.client.Do(ctx, req, &projects) - if err != nil { - return nil, resp, err - } - - return projects, resp, nil -} - -// CreateProject creates a GitHub Project for the specified repository. -// -// GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project -func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opt *ProjectOptions) (*Project, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) - req, err := s.client.NewRequest("POST", u, opt) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeProjectsPreview) - - project := &Project{} - resp, err := s.client.Do(ctx, req, project) - if err != nil { - return nil, resp, err - } - - return project, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/teams.go b/vendor/github.com/google/go-github/github/teams.go deleted file mode 100644 index c3773e00..00000000 --- a/vendor/github.com/google/go-github/github/teams.go +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2018 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" - "strings" - "time" -) - -// TeamsService provides access to the team-related functions -// in the GitHub API. -// -// GitHub API docs: https://developer.github.com/v3/teams/ -type TeamsService service - -// Team represents a team within a GitHub organization. Teams are used to -// manage access to an organization's repositories. -type Team struct { - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - URL *string `json:"url,omitempty"` - Slug *string `json:"slug,omitempty"` - - // Permission specifies the default permission for repositories owned by the team. - Permission *string `json:"permission,omitempty"` - - // Privacy identifies the level of privacy this team should have. - // Possible values are: - // secret - only visible to organization owners and members of this team - // closed - visible to all members of this organization - // Default is "secret". - Privacy *string `json:"privacy,omitempty"` - - MembersCount *int `json:"members_count,omitempty"` - ReposCount *int `json:"repos_count,omitempty"` - Organization *Organization `json:"organization,omitempty"` - MembersURL *string `json:"members_url,omitempty"` - RepositoriesURL *string `json:"repositories_url,omitempty"` - Parent *Team `json:"parent,omitempty"` - - // LDAPDN is only available in GitHub Enterprise and when the team - // membership is synchronized with LDAP. - LDAPDN *string `json:"ldap_dn,omitempty"` -} - -func (t Team) String() string { - return Stringify(t) -} - -// Invitation represents a team member's invitation status. -type Invitation struct { - ID *int64 `json:"id,omitempty"` - Login *string `json:"login,omitempty"` - Email *string `json:"email,omitempty"` - // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. - Role *string `json:"role,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - Inviter *User `json:"inviter,omitempty"` - TeamCount *int `json:"team_count,omitempty"` - InvitationTeamURL *string `json:"invitation_team_url,omitempty"` -} - -func (i Invitation) String() string { - return Stringify(i) -} - -// ListTeams lists all of the teams for an organization. -// -// GitHub API docs: https://developer.github.com/v3/teams/#list-teams -func (s *TeamsService) ListTeams(ctx context.Context, org string, opt *ListOptions) ([]*Team, *Response, error) { - u := fmt.Sprintf("orgs/%v/teams", org) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - var teams []*Team - resp, err := s.client.Do(ctx, req, &teams) - if err != nil { - return nil, resp, err - } - - return teams, resp, nil -} - -// GetTeam fetches a team by ID. -// -// GitHub API docs: https://developer.github.com/v3/teams/#get-team -func (s *TeamsService) GetTeam(ctx context.Context, team int64) (*Team, *Response, error) { - u := fmt.Sprintf("teams/%v", team) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - t := new(Team) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// NewTeam represents a team to be created or modified. -type NewTeam struct { - Name string `json:"name"` // Name of the team. (Required.) - Description *string `json:"description,omitempty"` - Maintainers []string `json:"maintainers,omitempty"` - RepoNames []string `json:"repo_names,omitempty"` - ParentTeamID *int64 `json:"parent_team_id,omitempty"` - - // Deprecated: Permission is deprecated when creating or editing a team in an org - // using the new GitHub permission model. It no longer identifies the - // permission a team has on its repos, but only specifies the default - // permission a repo is initially added with. Avoid confusion by - // specifying a permission value when calling AddTeamRepo. - Permission *string `json:"permission,omitempty"` - - // Privacy identifies the level of privacy this team should have. - // Possible values are: - // secret - only visible to organization owners and members of this team - // closed - visible to all members of this organization - // Default is "secret". - Privacy *string `json:"privacy,omitempty"` - - // LDAPDN may be used in GitHub Enterprise when the team membership - // is synchronized with LDAP. - LDAPDN *string `json:"ldap_dn,omitempty"` -} - -func (s NewTeam) String() string { - return Stringify(s) -} - -// CreateTeam creates a new team within an organization. -// -// GitHub API docs: https://developer.github.com/v3/teams/#create-team -func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { - u := fmt.Sprintf("orgs/%v/teams", org) - req, err := s.client.NewRequest("POST", u, team) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - t := new(Team) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// EditTeam edits a team. -// -// GitHub API docs: https://developer.github.com/v3/teams/#edit-team -func (s *TeamsService) EditTeam(ctx context.Context, id int64, team NewTeam) (*Team, *Response, error) { - u := fmt.Sprintf("teams/%v", id) - req, err := s.client.NewRequest("PATCH", u, team) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - t := new(Team) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// DeleteTeam deletes a team. -// -// GitHub API docs: https://developer.github.com/v3/teams/#delete-team -func (s *TeamsService) DeleteTeam(ctx context.Context, team int64) (*Response, error) { - u := fmt.Sprintf("teams/%v", team) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - return s.client.Do(ctx, req, nil) -} - -// ListChildTeams lists child teams for a team. -// -// GitHub API docs: https://developer.github.com/v3/teams/#list-child-teams -func (s *TeamsService) ListChildTeams(ctx context.Context, teamID int64, opt *ListOptions) ([]*Team, *Response, error) { - u := fmt.Sprintf("teams/%v/teams", teamID) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - var teams []*Team - resp, err := s.client.Do(ctx, req, &teams) - if err != nil { - return nil, resp, err - } - - return teams, resp, nil -} - -// ListTeamRepos lists the repositories that the specified team has access to. -// -// GitHub API docs: https://developer.github.com/v3/teams/#list-team-repos -func (s *TeamsService) ListTeamRepos(ctx context.Context, team int64, opt *ListOptions) ([]*Repository, *Response, error) { - u := fmt.Sprintf("teams/%v/repos", team) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when topics API fully launches. - headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview} - req.Header.Set("Accept", strings.Join(headers, ", ")) - - var repos []*Repository - resp, err := s.client.Do(ctx, req, &repos) - if err != nil { - return nil, resp, err - } - - return repos, resp, nil -} - -// IsTeamRepo checks if a team manages the specified repository. If the -// repository is managed by team, a Repository is returned which includes the -// permissions team has for that repo. -// -// GitHub API docs: https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository -func (s *TeamsService) IsTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Repository, *Response, error) { - u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview} - req.Header.Set("Accept", strings.Join(headers, ", ")) - - repository := new(Repository) - resp, err := s.client.Do(ctx, req, repository) - if err != nil { - return nil, resp, err - } - - return repository, resp, nil -} - -// TeamAddTeamRepoOptions specifies the optional parameters to the -// TeamsService.AddTeamRepo method. -type TeamAddTeamRepoOptions struct { - // Permission specifies the permission to grant the team on this repository. - // Possible values are: - // pull - team members can pull, but not push to or administer this repository - // push - team members can pull and push, but not administer this repository - // admin - team members can pull, push and administer this repository - // - // If not specified, the team's permission attribute will be used. - Permission string `json:"permission,omitempty"` -} - -// AddTeamRepo adds a repository to be managed by the specified team. The -// specified repository must be owned by the organization to which the team -// belongs, or a direct fork of a repository owned by the organization. -// -// GitHub API docs: https://developer.github.com/v3/teams/#add-team-repo -func (s *TeamsService) AddTeamRepo(ctx context.Context, team int64, owner string, repo string, opt *TeamAddTeamRepoOptions) (*Response, error) { - u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) - req, err := s.client.NewRequest("PUT", u, opt) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - -// RemoveTeamRepo removes a repository from being managed by the specified -// team. Note that this does not delete the repository, it just removes it -// from the team. -// -// GitHub API docs: https://developer.github.com/v3/teams/#remove-team-repo -func (s *TeamsService) RemoveTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Response, error) { - u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - -// ListUserTeams lists a user's teams -// GitHub API docs: https://developer.github.com/v3/teams/#list-user-teams -func (s *TeamsService) ListUserTeams(ctx context.Context, opt *ListOptions) ([]*Team, *Response, error) { - u := "user/teams" - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - var teams []*Team - resp, err := s.client.Do(ctx, req, &teams) - if err != nil { - return nil, resp, err - } - - return teams, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/github/teams_discussion_comments.go deleted file mode 100644 index 383d559e..00000000 --- a/vendor/github.com/google/go-github/github/teams_discussion_comments.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2018 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// DiscussionComment represents a GitHub dicussion in a team. -type DiscussionComment struct { - Author *User `json:"author,omitempty"` - Body *string `json:"body,omitempty"` - BodyHTML *string `json:"body_html,omitempty"` - BodyVersion *string `json:"body_version,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` - DiscussionURL *string `json:"discussion_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Number *int `json:"number,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - URL *string `json:"url,omitempty"` -} - -func (c DiscussionComment) String() string { - return Stringify(c) -} - -// DiscussionCommentListOptions specifies optional parameters to the -// TeamServices.ListComments method. -type DiscussionCommentListOptions struct { - // Sorts the discussion comments by the date they were created. - // Accepted values are asc and desc. Default is desc. - Direction string `url:"direction,omitempty"` -} - -// ListComments lists all comments on a team discussion. -// Authenticated user must grant read:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-comments -func (s *TeamsService) ListComments(ctx context.Context, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discussionNumber) - u, err := addOptions(u, options) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - var comments []*DiscussionComment - resp, err := s.client.Do(ctx, req, &comments) - if err != nil { - return nil, resp, err - } - - return comments, resp, nil -} - -// GetComment gets a specific comment on a team discussion. -// Authenticated user must grant read:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-single-comment -func (s *TeamsService) GetComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - discussionComment := &DiscussionComment{} - resp, err := s.client.Do(ctx, req, discussionComment) - if err != nil { - return nil, resp, err - } - - return discussionComment, resp, nil -} - -// CreateComment creates a new discussion post on a team discussion. -// Authenticated user must grant write:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-comment -func (s *TeamsService) CreateComment(ctx context.Context, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discsusionNumber) - req, err := s.client.NewRequest("POST", u, comment) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - discussionComment := &DiscussionComment{} - resp, err := s.client.Do(ctx, req, discussionComment) - if err != nil { - return nil, resp, err - } - - return discussionComment, resp, nil -} - -// EditComment edits the body text of a discussion comment. -// Authenticated user must grant write:discussion scope. -// User is allowed to edit body of a comment only. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#edit-a-comment -func (s *TeamsService) EditComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) - req, err := s.client.NewRequest("PATCH", u, comment) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - discussionComment := &DiscussionComment{} - resp, err := s.client.Do(ctx, req, discussionComment) - if err != nil { - return nil, resp, err - } - - return discussionComment, resp, nil -} - -// DeleteComment deletes a comment on a team discussion. -// Authenticated user must grant write:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-comment -func (s *TeamsService) DeleteComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/teams_discussions.go b/vendor/github.com/google/go-github/github/teams_discussions.go deleted file mode 100644 index 5db06d10..00000000 --- a/vendor/github.com/google/go-github/github/teams_discussions.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2018 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// TeamDiscussion represents a GitHub dicussion in a team. -type TeamDiscussion struct { - Author *User `json:"author,omitempty"` - Body *string `json:"body,omitempty"` - BodyHTML *string `json:"body_html,omitempty"` - BodyVersion *string `json:"body_version,omitempty"` - CommentsCount *int `json:"comments_count,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Number *int `json:"number,omitempty"` - Pinned *bool `json:"pinned,omitempty"` - Private *bool `json:"private,omitempty"` - TeamURL *string `json:"team_url,omitempty"` - Title *string `json:"title,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - URL *string `json:"url,omitempty"` -} - -func (d TeamDiscussion) String() string { - return Stringify(d) -} - -// DiscussionListOptions specifies optional parameters to the -// TeamServices.ListDiscussions method. -type DiscussionListOptions struct { - // Sorts the discussion by the date they were created. - // Accepted values are asc and desc. Default is desc. - Direction string `url:"direction,omitempty"` -} - -// ListDiscussions lists all discussions on team's page. -// Authenticated user must grant read:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussions/#list-discussions -func (s *TeamsService) ListDiscussions(ctx context.Context, teamID int64, options *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions", teamID) - u, err := addOptions(u, options) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - var teamDiscussions []*TeamDiscussion - resp, err := s.client.Do(ctx, req, &teamDiscussions) - if err != nil { - return nil, resp, err - } - - return teamDiscussions, resp, nil -} - -// GetDiscussion gets a specific discussion on a team's page. -// Authenticated user must grant read:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussions/#get-a-single-discussion -func (s *TeamsService) GetDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - teamDiscussion := &TeamDiscussion{} - resp, err := s.client.Do(ctx, req, teamDiscussion) - if err != nil { - return nil, resp, err - } - - return teamDiscussion, resp, nil -} - -// CreateDiscussion creates a new discussion post on a team's page. -// Authenticated user must grant write:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussions/#create-a-discussion -func (s *TeamsService) CreateDiscussion(ctx context.Context, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions", teamID) - req, err := s.client.NewRequest("POST", u, discussion) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - teamDiscussion := &TeamDiscussion{} - resp, err := s.client.Do(ctx, req, teamDiscussion) - if err != nil { - return nil, resp, err - } - - return teamDiscussion, resp, nil -} - -// EditDiscussion edits the title and body text of a discussion post. -// Authenticated user must grant write:discussion scope. -// User is allowed to change Title and Body of a discussion only. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussions/#edit-a-discussion -func (s *TeamsService) EditDiscussion(ctx context.Context, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) - req, err := s.client.NewRequest("PATCH", u, discussion) - if err != nil { - return nil, nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - teamDiscussion := &TeamDiscussion{} - resp, err := s.client.Do(ctx, req, teamDiscussion) - if err != nil { - return nil, resp, err - } - - return teamDiscussion, resp, nil -} - -// DeleteDiscussion deletes a discussion from team's page. -// Authenticated user must grant write:discussion scope. -// -// GitHub API docs: https://developer.github.com/v3/teams/discussions/#delete-a-discussion -func (s *TeamsService) DeleteDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*Response, error) { - u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/github/teams_members.go b/vendor/github.com/google/go-github/github/teams_members.go deleted file mode 100644 index d5cfa0dc..00000000 --- a/vendor/github.com/google/go-github/github/teams_members.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2018 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// TeamListTeamMembersOptions specifies the optional parameters to the -// TeamsService.ListTeamMembers method. -type TeamListTeamMembersOptions struct { - // Role filters members returned by their role in the team. Possible - // values are "all", "member", "maintainer". Default is "all". - Role string `url:"role,omitempty"` - - ListOptions -} - -// ListTeamMembers lists all of the users who are members of the specified -// team. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#list-team-members -func (s *TeamsService) ListTeamMembers(ctx context.Context, team int64, opt *TeamListTeamMembersOptions) ([]*User, *Response, error) { - u := fmt.Sprintf("teams/%v/members", team) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - var members []*User - resp, err := s.client.Do(ctx, req, &members) - if err != nil { - return nil, resp, err - } - - return members, resp, nil -} - -// IsTeamMember checks if a user is a member of the specified team. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-member -// -// Deprecated: This API has been marked as deprecated in the Github API docs, -// TeamsService.GetTeamMembership method should be used instead. -func (s *TeamsService) IsTeamMember(ctx context.Context, team int64, user string) (bool, *Response, error) { - u := fmt.Sprintf("teams/%v/members/%v", team, user) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return false, nil, err - } - - resp, err := s.client.Do(ctx, req, nil) - member, err := parseBoolResponse(err) - return member, resp, err -} - -// GetTeamMembership returns the membership status for a user in a team. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#get-team-membership -func (s *TeamsService) GetTeamMembership(ctx context.Context, team int64, user string) (*Membership, *Response, error) { - u := fmt.Sprintf("teams/%v/memberships/%v", team, user) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - - t := new(Membership) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// TeamAddTeamMembershipOptions specifies the optional -// parameters to the TeamsService.AddTeamMembership method. -type TeamAddTeamMembershipOptions struct { - // Role specifies the role the user should have in the team. Possible - // values are: - // member - a normal member of the team - // maintainer - a team maintainer. Able to add/remove other team - // members, promote other team members to team - // maintainer, and edit the team’s name and description - // - // Default value is "member". - Role string `json:"role,omitempty"` -} - -// AddTeamMembership adds or invites a user to a team. -// -// In order to add a membership between a user and a team, the authenticated -// user must have 'admin' permissions to the team or be an owner of the -// organization that the team is associated with. -// -// If the user is already a part of the team's organization (meaning they're on -// at least one other team in the organization), this endpoint will add the -// user to the team. -// -// If the user is completely unaffiliated with the team's organization (meaning -// they're on none of the organization's teams), this endpoint will send an -// invitation to the user via email. This newly-created membership will be in -// the "pending" state until the user accepts the invitation, at which point -// the membership will transition to the "active" state and the user will be -// added as a member of the team. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#add-or-update-team-membership -func (s *TeamsService) AddTeamMembership(ctx context.Context, team int64, user string, opt *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { - u := fmt.Sprintf("teams/%v/memberships/%v", team, user) - req, err := s.client.NewRequest("PUT", u, opt) - if err != nil { - return nil, nil, err - } - - t := new(Membership) - resp, err := s.client.Do(ctx, req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil -} - -// RemoveTeamMembership removes a user from a team. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#remove-team-membership -func (s *TeamsService) RemoveTeamMembership(ctx context.Context, team int64, user string) (*Response, error) { - u := fmt.Sprintf("teams/%v/memberships/%v", team, user) - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - -// ListPendingTeamInvitations get pending invitaion list in team. -// Warning: The API may change without advance notice during the preview period. -// Preview features are not supported for production use. -// -// GitHub API docs: https://developer.github.com/v3/teams/members/#list-pending-team-invitations -func (s *TeamsService) ListPendingTeamInvitations(ctx context.Context, team int64, opt *ListOptions) ([]*Invitation, *Response, error) { - u := fmt.Sprintf("teams/%v/invitations", team) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var pendingInvitations []*Invitation - resp, err := s.client.Do(ctx, req, &pendingInvitations) - if err != nil { - return nil, resp, err - } - - return pendingInvitations, resp, nil -} diff --git a/vendor/github.com/google/go-github/github/users_emails.go b/vendor/github.com/google/go-github/github/users_emails.go deleted file mode 100644 index 0bbd4627..00000000 --- a/vendor/github.com/google/go-github/github/users_emails.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2013 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import "context" - -// UserEmail represents user's email address -type UserEmail struct { - Email *string `json:"email,omitempty"` - Primary *bool `json:"primary,omitempty"` - Verified *bool `json:"verified,omitempty"` -} - -// ListEmails lists all email addresses for the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user -func (s *UsersService) ListEmails(ctx context.Context, opt *ListOptions) ([]*UserEmail, *Response, error) { - u := "user/emails" - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var emails []*UserEmail - resp, err := s.client.Do(ctx, req, &emails) - if err != nil { - return nil, resp, err - } - - return emails, resp, nil -} - -// AddEmails adds email addresses of the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/users/emails/#add-email-addresses -func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { - u := "user/emails" - req, err := s.client.NewRequest("POST", u, emails) - if err != nil { - return nil, nil, err - } - - var e []*UserEmail - resp, err := s.client.Do(ctx, req, &e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil -} - -// DeleteEmails deletes email addresses from authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/users/emails/#delete-email-addresses -func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { - u := "user/emails" - req, err := s.client.NewRequest("DELETE", u, emails) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/v68/AUTHORS b/vendor/github.com/google/go-github/v68/AUTHORS new file mode 100644 index 00000000..a6104ffa --- /dev/null +++ b/vendor/github.com/google/go-github/v68/AUTHORS @@ -0,0 +1,548 @@ +# This is the official list of go-github authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control or +# https://github.com/google/go-github/graphs/contributors. +# +# Authors who wish to be recognized in this file should add themselves (or +# their employer, as appropriate). + +178inaba +2BFL +413x +6543 <6543@obermui.de> +Abed Kibbe +Abhijit Hota +Abhinav Gupta +abhishek +Abhishek Sharma +Abhishek Veeramalla +aboy +Adam Kohring +Aditya Mahendrakar +adrienzieba +afdesk +Ahmad Nurus S +Ahmed Hagy +Aidan +Aidan Steele +Ainsley Chong +ajz01 +Akeda Bagus +Akhil Mohan +Alec Thomas +Aleks Clark +Alex Bramley +Alex Ellis +Alex Orr +Alex Su +Alex Unger +Alexander Harkness +Alexey Alekhin +Alexis Couvreur +Alexis Gauthiez +Ali Farooq +Alin Balutoiu +Allan Guwatudde +Allen Sun +Amey Sakhadeo +Anders Janmyr +Andreas Deininger +Andreas Garnæs +Andrew Gillis +Andrew Ryabchun +Andrew Svoboda +Andriyun +Andy Grunwald +Andy Hume +Andy Lindeman +angie pinilla +Anish Rajan +anjanashenoy +Anshuman Bhartiya +Antoine +Antoine Pelisse +Anton Nguyen +Anubha Kushwaha +appilon +aprp +apurwaj2 +Aravind +Arda Kuyumcu +Ary +Arıl Bozoluk +Asier Marruedo +Austin Burdine +Austin Dizzy +Azuka Okuleye +Ben Batha +Benjamen Keroack +Benjamin Nater +Berkay Tacyildiz +Beshr Kayali +Beyang Liu +billnapier +Billy Keyes +Billy Lynch +Bingtan Lu +Bjorn Neergaard +Björn Häuser +Bo Huang +boljen +Bracken +Brad Harris +Brad Moylan +Bradley Falzon +Bradley McAllister +Brandon Butler +Brandon Cook +Brandon Stubbs +Brett Kuhlman +Brett Logan +Brian Egizi +Bryan Boreham +Bryan Peterson +Cami Diez +Carl Johnson +Carlos Alexandro Becker +Carlos Tadeu Panato Junior +Casey +ChandanChainani +chandresh-pancholi +Charles Fenwick Elliott +Charlie Yan +Chmouel Boudjnah +Chris Allen Lane +Chris King +Chris Mc +Chris Raborg +Chris Roche +Chris Schaefer +chrisforrette +Christian Bargmann +Christian Muehlhaeuser +Christoph Jerolimov +Christoph Sassenberg +CI Monk +Clemens W +Colin Misare +Craig Gumbley +Craig Peterson +Cristian Maglie +Cyb3r Jak3 +Daehyeok Mun +Dalton Hubble +Daniel Lanner +Daniel Leavitt +Daniel Nilsson +Daoq +Dave Du Cros +Dave Henderson +Dave Perrett +Dave Protasowski +David Deng +David Gamba +David J. M. Karlsen +David Jannotta +David Ji +David Lopez Reyes +Davide Zipeto +Dennis Webb +Derek Jobst +DeviousLab +Dhi Aurrahman +Diego Lapiduz +Diogo Vilela +Dion Gionet Mallet +Dmitri Shuralyov +dmnlk +Don Petersen +Doug Turner +Drew Fradette +Dustin Deus +Dustin Lish +Eivind +Eli Uriegas +Elliott Beach +Emerson Wood +Emil V +Emma Sax +Eng Zer Jun +Enrico Candino +eperm +Erick Fejta +Erik Elkins +Erik Nobel +Erwan Finot +erwinvaneyk +Evan Anderson +Evan Elias +Fabian Holler +Fabrice +Fatema-Moaiyadi +Federico Di Pierro +Felix Geisendörfer +Filippo Valsorda +Florian Forster +Florian Maier +Florian Wagner +Francesc Gil +Francis +Francisco Guimarães +François de Metz +Fredrik Jönsson +Gabriel +Gal Ofri +Garrett Squire +George Kontridze +Georgy Buranov +Glen Mailer +Gnahz +Google Inc. +Grachev Mikhail +Gregory Oschwald +griffin_stewie +guangwu +Guillaume Jacquet +Guz Alexander +Guðmundur Bjarni Ólafsson +Hanno Hecker +Hari haran +Harikesh00 +haya14busa +haya14busa +Henrik Lundström +Hiroki Ito +Hubot Jr +Huy Tr +huydx +i2bskn +Iain Steers +Ikko Ashimine +Ilia Choly +Ioannis Georgoulas +Isao Jonas +ishan upadhyay +isqua +Ivan Martos +Jacob Valdemar +Jake Krammer +Jake Scaltreto +Jake White +Jameel Haffejee +James Bowes +James Cockbain +James Loh +James Maguire +James Turley +Jamie West +Jan Guth +Jan Kosecki +Jan Švábík +Jason Field +Javier Campanini +Jef LeCompte +Jeff Wenzbauer +Jens Rantil +Jeremy Morris +Jesse Haka +Jesse Newland +Jihoon Chung +Jille Timmermans +Jimmi Dyson +Joan Saum +JoannaaKL +Joe Tsai +John Barton +John Engelman +John Jones +John Liu +Jordan Brockopp +Jordan Burandt +Jordan Sussman +Jorge Ferrero +Jorge Gómez Reus +Joshua Bezaleel Abednego +João Cerqueira +JP Phillips +jpbelanger-mtl +Juan +Juan Basso +Julien Garcia Gonzalez +Julien Midedji +Julien Rostand +Junya Kono +Justin Abrahms +Justin Toh +Jusung Lee +jzhoucliqr +k0ral +k1rnt +kadern0 +Karthik Sundari +Katrina Owen +Kautilya Tripathi +Keita Urashima +Kevin Burke +Kevin Wang +Kevin Zhao +kgalli +Khanh Ngo +Kirill +Konrad Malawski +Kookheon Kwon +Krishna Indani +Krzysztof Kowalczyk +Kshitij Saraogi +Kumar Saurabh +Kyle Kurz +kyokomi +Lachlan Cooper +Lars Lehtonen +Laurent Verdoïa +leopoldwang +Liam Galvin +Liam Stanley +Lluis Campos +Lovro Mažgon +Loïs Postula +Luca Campese +Lucas Alcantara +Lucas Martin-King +Luis Davim +Luke Evers +Luke Hinds +Luke Kysow +Luke Roberts +Luke Young +lynn [they] +Léo Salé +M. Ryan Rigdon +Magnus Kulke +Maksim Zhylinski +Marc Binder +Marcelo Carlos +Mark Tareshawty +Martin Holman +Martin-Louis Bright +Martins Sipenko +Marwan Sulaiman +Masayuki Izumi +Mat Geist +Matheus Santos Araújo +Matija Horvat +Matin Rahmanian +Matt +Matt Brender +Matt Dainty +Matt Gaunt +Matt Landis +Matt Mencel +Matt Moore +Matt Simons +Matthew Reidy +Maxime Bury +Michael Meng +Michael Spiegel +Michael Tiller +Michał Glapa +Michelangelo Morrillo +Miguel Elias dos Santos +Mike Chen +Miles Crabill +Mishin Nikolai +mohammad ali <2018cs92@student.uet.edu.pk> +Mohammed AlDujaili +Mohammed Nafees +Mudit +Mukundan Senthil +Munia Balayil +Mustafa Abban +Nadav Kaner +Naoki Kanatani +Nathan VanBenschoten +Navaneeth Suresh +Nayeem Hasan +Neal Caffery +Neil O'Toole +Nicholas Herring +Nick Miyake +Nick Platt +Nick Spragg +Nicolas Chapurlat +Nikhita Raghunath +Nikita Pivkin +Nilesh Singh +Noah Hanjun Lee +Noah Zoschke +Noble Varghese +ns-cweber +nxya +Ole Orhagen +Oleg Kovalov +Oleksandr Redko +Ondřej Kupka +Ori Talmor +Osama Faqhruldin +oslowalk +Pablo Pérez Schröder +Palash Nigam +Panagiotis Moustafellos +Parham Alvani +pari-27 +Parker Moore +parkhyukjun89 +Pat Alwell +Patrick DeVivo +Patrick Marabeas +Patrik Nordlén +Pavel Dvoinos +Pavel Shtanko +Pete Wagner +Petr Shevtsov +Pierce McEntagart +Pierre Carrier +Piotr Zurek +Piyush Chugh +Pj Meyer +Pratik Mallya +Qais Patankar +Quang Le Hong +Quentin Leffray +Quinn Slack +Rackspace US, Inc. +Radek Simko +Radliński Ignacy +Rafael Aramizu Gomes +Rajat Jindal +Rajendra arora +Rajkumar +Ramesh Gaikwad +Ranbir Singh +Ravi Shekhar Jethani +RaviTeja Pothana +rc1140 +Red Hat, Inc. +Reetuparna Mukherjee +reeves122 +Reinier Timmer +Renjith R +Rez Moss +Riaje +Ricco Førgaard +Richard de Vries +Rob Figueiredo +Rohit Upadhyay +Rojan Dinc +Roming22 +Ronak Jain +Ronan Pelliard +Ross Gustafson +Ruben Vereecken +Rufina Talalaeva +Russell Boley +Ryan Leung +Ryan Lower +Ryan Skidmore +Ryo Nakao +Saaarah +Safwan Olaimat +Sahil Dua +Sai Ravi Teja Chintakrindi +saisi +Sam Minnée +Sandeep Sukhani +Sander Knape +Sander van Harmelen +Sanket Payghan +Sarah Funkhouser +Sarasa Kisaragi +Sasha Melentyev +Sean Wang +Sebastian Mandrean +Sebastian Mæland Pedersen +Sergei Popinevskii +Sergey Romanov +Sergio Garcia +Seth Vargo +Sevki +Shagun Khemka +shakeelrao +Shawn Catanzarite +Shawn Smith +Shibasis Patel +Sho Okada +Shrikrishna Singh +Simon Davis +sona-tar +soniachikh +SoundCloud, Ltd. +Sridhar Mocherla +SriVignessh Pss +Stefan Sedich +Steve Hipwell +Steve Teuber +Stian Eikeland +Suhaib Mujahid +sushmita wable +Sven Palberg +Szymon Kodrebski +Søren Hansen +T.J. Corrigan +Takashi Yoneuchi +Takayuki Watanabe +Taketoshi Fujiwara +Taketoshi Fujiwara +Takuma Kajikawa +Tasya Aditya Rukmana +Theo Henson +Theofilos Petsios +Thomas Aidan Curran +Thomas Bruyelle +Tim Rogers +Timothy O'Brien +Timothée Peignier +Tingluo Huang +tkhandel +Tobias Gesellchen +Tom Payne +Tomasz Adam Skrzypczak +tomfeigin +Travis Tomsu +Trey Tacon +tsbkw +ttacon +Vaibhav Singh +Varadarajan Aravamudhan +Victor Castell +Victor Vrantchan +Victory Osikwemhe +vikkyomkar +Vivek +Vlad Ungureanu +Wasim Thabraze +Weslei Juan Moser Pereira +Wheeler Law +Will Maier +Will Norris +Willem D'Haeseleer +William Bailey +William Cooke +Xabi +xibz +Yann Malet +Yannick Utard +Yarden Shoham +Yicheng Qin +Yosuke Akatsuka +Yumikiyo Osanai +Yurii Soldak +Yusef Mohamadi +Yusuke Kuoka +Zach Latta +Ze Peng +zhouhaibing089 +六开箱 +缘生 +蒋航 diff --git a/vendor/github.com/google/go-github/LICENSE b/vendor/github.com/google/go-github/v68/LICENSE similarity index 100% rename from vendor/github.com/google/go-github/LICENSE rename to vendor/github.com/google/go-github/v68/LICENSE diff --git a/vendor/github.com/google/go-github/v68/github/actions.go b/vendor/github.com/google/go-github/v68/github/actions.go new file mode 100644 index 00000000..4b88a1e1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// ActionsService handles communication with the actions related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/actions/ +type ActionsService service diff --git a/vendor/github.com/google/go-github/v68/github/actions_artifacts.go b/vendor/github.com/google/go-github/v68/github/actions_artifacts.go new file mode 100644 index 00000000..e05a9a84 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_artifacts.go @@ -0,0 +1,177 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// ArtifactWorkflowRun represents a GitHub artifact's workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts +type ArtifactWorkflowRun struct { + ID *int64 `json:"id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + HeadRepositoryID *int64 `json:"head_repository_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` +} + +// Artifact represents a GitHub artifact. Artifacts allow sharing +// data between jobs in a workflow and provide storage for data +// once a workflow is complete. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts +type Artifact struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + SizeInBytes *int64 `json:"size_in_bytes,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveDownloadURL *string `json:"archive_download_url,omitempty"` + Expired *bool `json:"expired,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` + WorkflowRun *ArtifactWorkflowRun `json:"workflow_run,omitempty"` +} + +// ArtifactList represents a list of GitHub artifacts. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#artifacts +type ArtifactList struct { + TotalCount *int64 `json:"total_count,omitempty"` + Artifacts []*Artifact `json:"artifacts,omitempty"` +} + +// ListArtifactsOptions specifies the optional parameters to the +// ActionsService.ListArtifacts method. +type ListArtifactsOptions struct { + // Name represents the name field of an artifact. + // When specified, only artifacts with this name will be returned. + Name *string `url:"name,omitempty"` + + ListOptions +} + +// ListArtifacts lists all artifacts that belong to a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-artifacts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts +func (s *ActionsService) ListArtifacts(ctx context.Context, owner, repo string, opts *ListArtifactsOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// ListWorkflowRunArtifacts lists all artifacts that belong to a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-workflow-run-artifacts +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts +func (s *ActionsService) ListWorkflowRunArtifacts(ctx context.Context, owner, repo string, runID int64, opts *ListOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/artifacts", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// GetArtifact gets a specific artifact for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#get-an-artifact +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id} +func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Artifact, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifact := new(Artifact) + resp, err := s.client.Do(ctx, req, artifact) + if err != nil { + return nil, resp, err + } + + return artifact, resp, nil +} + +// DownloadArtifact gets a redirect URL to download an archive for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#download-an-artifact +// +//meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format} +func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + if err != nil { + return nil, newResponse(resp), err + } + + return parsedURL, newResponse(resp), nil +} + +// DeleteArtifact deletes a workflow run artifact. +// +// GitHub API docs: https://docs.github.com/rest/actions/artifacts#delete-an-artifact +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id} +func (s *ActionsService) DeleteArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_cache.go b/vendor/github.com/google/go-github/v68/github/actions_cache.go new file mode 100644 index 00000000..852e9860 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_cache.go @@ -0,0 +1,249 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsCache represents a GitHub action cache. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#about-the-cache-api +type ActionsCache struct { + ID *int64 `json:"id,omitempty" url:"-"` + Ref *string `json:"ref,omitempty" url:"ref"` + Key *string `json:"key,omitempty" url:"key"` + Version *string `json:"version,omitempty" url:"-"` + LastAccessedAt *Timestamp `json:"last_accessed_at,omitempty" url:"-"` + CreatedAt *Timestamp `json:"created_at,omitempty" url:"-"` + SizeInBytes *int64 `json:"size_in_bytes,omitempty" url:"-"` +} + +// ActionsCacheList represents a list of GitHub actions Cache. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +type ActionsCacheList struct { + TotalCount int `json:"total_count"` + ActionsCaches []*ActionsCache `json:"actions_caches,omitempty"` +} + +// ActionsCacheUsage represents a GitHub Actions Cache Usage object. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +type ActionsCacheUsage struct { + FullName string `json:"full_name"` + ActiveCachesSizeInBytes int64 `json:"active_caches_size_in_bytes"` + ActiveCachesCount int `json:"active_caches_count"` +} + +// ActionsCacheUsageList represents a list of repositories with GitHub Actions cache usage for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +type ActionsCacheUsageList struct { + TotalCount int `json:"total_count"` + RepoCacheUsage []*ActionsCacheUsage `json:"repository_cache_usages,omitempty"` +} + +// TotalCacheUsage represents total GitHub actions cache usage of an organization or enterprise. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-an-enterprise +type TotalCacheUsage struct { + TotalActiveCachesUsageSizeInBytes int64 `json:"total_active_caches_size_in_bytes"` + TotalActiveCachesCount int `json:"total_active_caches_count"` +} + +// ActionsCacheListOptions represents a list of all possible optional Query parameters for ListCaches method. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +type ActionsCacheListOptions struct { + ListOptions + // The Git reference for the results you want to list. + // The ref for a branch can be formatted either as refs/heads/ + // or simply . To reference a pull request use refs/pull//merge + Ref *string `url:"ref,omitempty"` + Key *string `url:"key,omitempty"` + // Can be one of: "created_at", "last_accessed_at", "size_in_bytes". Default: "last_accessed_at" + Sort *string `url:"sort,omitempty"` + // Can be one of: "asc", "desc" Default: desc + Direction *string `url:"direction,omitempty"` +} + +// ListCaches lists the GitHub Actions caches for a repository. +// You must authenticate using an access token with the repo scope to use this endpoint. +// +// Permissions: must have the actions:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-github-actions-caches-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/caches +func (s *ActionsService) ListCaches(ctx context.Context, owner, repo string, opts *ActionsCacheListOptions) (*ActionsCacheList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionCacheList := new(ActionsCacheList) + resp, err := s.client.Do(ctx, req, actionCacheList) + if err != nil { + return nil, resp, err + } + + return actionCacheList, resp, nil +} + +// DeleteCachesByKey deletes one or more GitHub Actions caches for a repository, using a complete cache key. +// By default, all caches that match the provided key are deleted, but you can optionally provide +// a Git ref to restrict deletions to caches that match both the provided key and the Git ref. +// The ref for a branch can be formatted either as "refs/heads/" or simply "". +// To reference a pull request use "refs/pull//merge". If you don't want to use ref just pass nil in parameter. +// +// Permissions: You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have the actions:write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#delete-github-actions-caches-for-a-repository-using-a-cache-key +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/caches +func (s *ActionsService) DeleteCachesByKey(ctx context.Context, owner, repo, key string, ref *string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches", owner, repo) + u, err := addOptions(u, ActionsCache{Key: &key, Ref: ref}) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteCachesByID deletes a GitHub Actions cache for a repository, using a cache ID. +// +// Permissions: You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have the actions:write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#delete-a-github-actions-cache-for-a-repository-using-a-cache-id +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/caches/{cache_id} +func (s *ActionsService) DeleteCachesByID(ctx context.Context, owner, repo string, cacheID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/caches/%v", owner, repo, cacheID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetCacheUsageForRepo gets GitHub Actions cache usage for a repository. The data fetched using this API is refreshed approximately every 5 minutes, +// so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: Anyone with read access to the repository can use this endpoint. If the repository is private, you must use an +// access token with the repo scope. GitHub Apps must have the actions:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/cache/usage +func (s *ActionsService) GetCacheUsageForRepo(ctx context.Context, owner, repo string) (*ActionsCacheUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/cache/usage", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(ActionsCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// ListCacheUsageByRepoForOrg lists repositories and their GitHub Actions cache usage for an organization. The data fetched using this API is +// refreshed approximately every 5 minutes, so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the read:org scope to use this endpoint. +// GitHub Apps must have the organization_administration:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#list-repositories-with-github-actions-cache-usage-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/cache/usage-by-repository +func (s *ActionsService) ListCacheUsageByRepoForOrg(ctx context.Context, org string, opts *ListOptions) (*ActionsCacheUsageList, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/cache/usage-by-repository", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(ActionsCacheUsageList) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// GetTotalCacheUsageForOrg gets the total GitHub Actions cache usage for an organization. The data fetched using this API is refreshed approximately every +// 5 minutes, so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the read:org scope to use this endpoint. +// GitHub Apps must have the organization_administration:read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/actions/cache#get-github-actions-cache-usage-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/cache/usage +func (s *ActionsService) GetTotalCacheUsageForOrg(ctx context.Context, org string) (*TotalCacheUsage, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/cache/usage", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(TotalCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} + +// GetTotalCacheUsageForEnterprise gets the total GitHub Actions cache usage for an enterprise. The data fetched using this API is refreshed approximately every 5 minutes, +// so values returned from this endpoint may take at least 5 minutes to get updated. +// +// Permissions: You must authenticate using an access token with the "admin:enterprise" scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/cache#get-github-actions-cache-usage-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/cache/usage +func (s *ActionsService) GetTotalCacheUsageForEnterprise(ctx context.Context, enterprise string) (*TotalCacheUsage, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/cache/usage", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cacheUsage := new(TotalCacheUsage) + res, err := s.client.Do(ctx, req, cacheUsage) + if err != nil { + return nil, res, err + } + + return cacheUsage, res, err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_oidc.go b/vendor/github.com/google/go-github/v68/github/actions_oidc.go new file mode 100644 index 00000000..596aa9d9 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_oidc.go @@ -0,0 +1,81 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OIDCSubjectClaimCustomTemplate represents an OIDC subject claim customization template. +type OIDCSubjectClaimCustomTemplate struct { + UseDefault *bool `json:"use_default,omitempty"` + IncludeClaimKeys []string `json:"include_claim_keys,omitempty"` +} + +// GetOrgOIDCSubjectClaimCustomTemplate gets the subject claim customization template for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#get-the-customization-template-for-an-oidc-subject-claim-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/oidc/customization/sub +func (s *ActionsService) GetOrgOIDCSubjectClaimCustomTemplate(ctx context.Context, org string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/oidc/customization/sub", org) + return s.getOIDCSubjectClaimCustomTemplate(ctx, u) +} + +// GetRepoOIDCSubjectClaimCustomTemplate gets the subject claim customization template for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#get-the-customization-template-for-an-oidc-subject-claim-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/oidc/customization/sub +func (s *ActionsService) GetRepoOIDCSubjectClaimCustomTemplate(ctx context.Context, owner, repo string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/oidc/customization/sub", owner, repo) + return s.getOIDCSubjectClaimCustomTemplate(ctx, u) +} + +func (s *ActionsService) getOIDCSubjectClaimCustomTemplate(ctx context.Context, url string) (*OIDCSubjectClaimCustomTemplate, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + tmpl := new(OIDCSubjectClaimCustomTemplate) + resp, err := s.client.Do(ctx, req, tmpl) + if err != nil { + return nil, resp, err + } + + return tmpl, resp, nil +} + +// SetOrgOIDCSubjectClaimCustomTemplate sets the subject claim customization for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#set-the-customization-template-for-an-oidc-subject-claim-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/oidc/customization/sub +func (s *ActionsService) SetOrgOIDCSubjectClaimCustomTemplate(ctx context.Context, org string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/oidc/customization/sub", org) + return s.setOIDCSubjectClaimCustomTemplate(ctx, u, template) +} + +// SetRepoOIDCSubjectClaimCustomTemplate sets the subject claim customization for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/oidc#set-the-customization-template-for-an-oidc-subject-claim-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/oidc/customization/sub +func (s *ActionsService) SetRepoOIDCSubjectClaimCustomTemplate(ctx context.Context, owner, repo string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/oidc/customization/sub", owner, repo) + return s.setOIDCSubjectClaimCustomTemplate(ctx, u, template) +} + +func (s *ActionsService) setOIDCSubjectClaimCustomTemplate(ctx context.Context, url string, template *OIDCSubjectClaimCustomTemplate) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, template) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go b/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go new file mode 100644 index 00000000..a6a85aa3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go @@ -0,0 +1,258 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsEnabledOnEnterpriseRepos represents all the repositories in an enterprise for which Actions is enabled. +type ActionsEnabledOnEnterpriseRepos struct { + TotalCount int `json:"total_count"` + Organizations []*Organization `json:"organizations"` +} + +// ActionsPermissionsEnterprise represents a policy for allowed actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions +type ActionsPermissionsEnterprise struct { + EnabledOrganizations *string `json:"enabled_organizations,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissionsEnterprise) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionEnterprise represents the default permissions for GitHub Actions workflows for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions +type DefaultWorkflowPermissionEnterprise struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissionsInEnterprise gets the GitHub Actions permissions policy for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-github-actions-permissions-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions +func (s *ActionsService) GetActionsPermissionsInEnterprise(ctx context.Context, enterprise string) (*ActionsPermissionsEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsEnterprise) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissionsInEnterprise sets the permissions policy in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-github-actions-permissions-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions +func (s *ActionsService) EditActionsPermissionsInEnterprise(ctx context.Context, enterprise string, actionsPermissionsEnterprise ActionsPermissionsEnterprise) (*ActionsPermissionsEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions", enterprise) + req, err := s.client.NewRequest("PUT", u, actionsPermissionsEnterprise) + if err != nil { + return nil, nil, err + } + + p := new(ActionsPermissionsEnterprise) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListEnabledOrgsInEnterprise lists the selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#list-selected-organizations-enabled-for-github-actions-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/organizations +func (s *ActionsService) ListEnabledOrgsInEnterprise(ctx context.Context, owner string, opts *ListOptions) (*ActionsEnabledOnEnterpriseRepos, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := &ActionsEnabledOnEnterpriseRepos{} + resp, err := s.client.Do(ctx, req, orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// SetEnabledOrgsInEnterprise replaces the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-selected-organizations-enabled-for-github-actions-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/organizations +func (s *ActionsService) SetEnabledOrgsInEnterprise(ctx context.Context, owner string, organizationIDs []int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations", owner) + + req, err := s.client.NewRequest("PUT", u, struct { + IDs []int64 `json:"selected_organization_ids"` + }{IDs: organizationIDs}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddEnabledOrgInEnterprise adds an organization to the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#enable-a-selected-organization-for-github-actions-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/organizations/{org_id} +func (s *ActionsService) AddEnabledOrgInEnterprise(ctx context.Context, owner string, organizationID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations/%v", owner, organizationID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveEnabledOrgInEnterprise removes an organization from the list of selected organizations that are enabled for GitHub Actions in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#disable-a-selected-organization-for-github-actions-in-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/permissions/organizations/{org_id} +func (s *ActionsService) RemoveEnabledOrgInEnterprise(ctx context.Context, owner string, organizationID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/organizations/%v", owner, organizationID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetActionsAllowedInEnterprise gets the actions that are allowed in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/selected-actions +func (s *ActionsService) GetActionsAllowedInEnterprise(ctx context.Context, enterprise string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/selected-actions", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowedInEnterprise sets the actions that are allowed in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/selected-actions +func (s *ActionsService) EditActionsAllowedInEnterprise(ctx context.Context, enterprise string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/selected-actions", enterprise) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// GetDefaultWorkflowPermissionsInEnterprise gets the GitHub Actions default workflow permissions for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#get-default-workflow-permissions-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/permissions/workflow +func (s *ActionsService) GetDefaultWorkflowPermissionsInEnterprise(ctx context.Context, enterprise string) (*DefaultWorkflowPermissionEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/workflow", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionEnterprise) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissionsInEnterprise sets the GitHub Actions default workflow permissions for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/permissions#set-default-workflow-permissions-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/permissions/workflow +func (s *ActionsService) EditDefaultWorkflowPermissionsInEnterprise(ctx context.Context, enterprise string, permissions DefaultWorkflowPermissionEnterprise) (*DefaultWorkflowPermissionEnterprise, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/permissions/workflow", enterprise) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionEnterprise) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go b/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go new file mode 100644 index 00000000..2f555f24 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go @@ -0,0 +1,271 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissions represents a policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsPermissions struct { + EnabledRepositories *string `json:"enabled_repositories,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissions) String() string { + return Stringify(a) +} + +// ActionsEnabledOnOrgRepos represents all the repositories in an organization for which Actions is enabled. +type ActionsEnabledOnOrgRepos struct { + TotalCount int `json:"total_count"` + Repositories []*Repository `json:"repositories"` +} + +// ActionsAllowed represents selected actions that are allowed. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsAllowed struct { + GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` + VerifiedAllowed *bool `json:"verified_allowed,omitempty"` + PatternsAllowed []string `json:"patterns_allowed,omitempty"` +} + +func (a ActionsAllowed) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionOrganization represents the default permissions for GitHub Actions workflows for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type DefaultWorkflowPermissionOrganization struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions +func (s *ActionsService) GetActionsPermissions(ctx context.Context, org string) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions +func (s *ActionsService) EditActionsPermissions(ctx context.Context, org string, actionsPermissions ActionsPermissions) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + req, err := s.client.NewRequest("PUT", u, actionsPermissions) + if err != nil { + return nil, nil, err + } + + p := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListEnabledReposInOrg lists the selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/repositories +func (s *ActionsService) ListEnabledReposInOrg(ctx context.Context, owner string, opts *ListOptions) (*ActionsEnabledOnOrgRepos, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ActionsEnabledOnOrgRepos{} + resp, err := s.client.Do(ctx, req, repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetEnabledReposInOrg replaces the list of selected repositories that are enabled for GitHub Actions in an organization.. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-selected-repositories-enabled-for-github-actions-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/repositories +func (s *ActionsService) SetEnabledReposInOrg(ctx context.Context, owner string, repositoryIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + + req, err := s.client.NewRequest("PUT", u, struct { + IDs []int64 `json:"selected_repository_ids"` + }{IDs: repositoryIDs}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddEnabledReposInOrg adds a repository to the list of selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#enable-a-selected-repository-for-github-actions-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/repositories/{repository_id} +func (s *ActionsService) AddEnabledReposInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveEnabledReposInOrg removes a single repository from the list of enabled repos for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#disable-a-selected-repository-for-github-actions-in-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/permissions/repositories/{repository_id} +func (s *ActionsService) RemoveEnabledReposInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetActionsAllowed gets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/selected-actions +func (s *ActionsService) GetActionsAllowed(ctx context.Context, org string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/selected-actions +func (s *ActionsService) EditActionsAllowed(ctx context.Context, org string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// GetDefaultWorkflowPermissionsInOrganization gets the GitHub Actions default workflow permissions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-default-workflow-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/workflow +func (s *ActionsService) GetDefaultWorkflowPermissionsInOrganization(ctx context.Context, org string) (*DefaultWorkflowPermissionOrganization, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/workflow", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionOrganization) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissionsInOrganization sets the GitHub Actions default workflow permissions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-default-workflow-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/workflow +func (s *ActionsService) EditDefaultWorkflowPermissionsInOrganization(ctx context.Context, org string, permissions DefaultWorkflowPermissionOrganization) (*DefaultWorkflowPermissionOrganization, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/workflow", org) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionOrganization) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go b/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go new file mode 100644 index 00000000..b89741a8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go @@ -0,0 +1,267 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrgRequiredWorkflow represents a required workflow object at the org level. +type OrgRequiredWorkflow struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + Scope *string `json:"scope,omitempty"` + Ref *string `json:"ref,omitempty"` + State *string `json:"state,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +// OrgRequiredWorkflows represents the required workflows for the org. +type OrgRequiredWorkflows struct { + TotalCount *int `json:"total_count,omitempty"` + RequiredWorkflows []*OrgRequiredWorkflow `json:"required_workflows,omitempty"` +} + +// CreateUpdateRequiredWorkflowOptions represents the input object used to create or update required workflows. +type CreateUpdateRequiredWorkflowOptions struct { + WorkflowFilePath *string `json:"workflow_file_path,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Scope *string `json:"scope,omitempty"` + SelectedRepositoryIDs *SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +// RequiredWorkflowSelectedRepos represents the repos that a required workflow is applied to. +type RequiredWorkflowSelectedRepos struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +// RepoRequiredWorkflow represents a required workflow object at the repo level. +type RepoRequiredWorkflow struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + State *string `json:"state,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BadgeURL *string `json:"badge_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SourceRepository *Repository `json:"source_repository,omitempty"` +} + +// RepoRequiredWorkflows represents the required workflows for a repo. +type RepoRequiredWorkflows struct { + TotalCount *int `json:"total_count,omitempty"` + RequiredWorkflows []*RepoRequiredWorkflow `json:"required_workflows,omitempty"` +} + +// ListOrgRequiredWorkflows lists the RequiredWorkflows for an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows +func (s *ActionsService) ListOrgRequiredWorkflows(ctx context.Context, org string, opts *ListOptions) (*OrgRequiredWorkflows, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows", org) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflows := new(OrgRequiredWorkflows) + resp, err := s.client.Do(ctx, req, &requiredWorkflows) + if err != nil { + return nil, resp, err + } + + return requiredWorkflows, resp, nil +} + +// CreateRequiredWorkflow creates the required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation POST /orgs/{org}/actions/required_workflows +func (s *ActionsService) CreateRequiredWorkflow(ctx context.Context, org string, createRequiredWorkflowOptions *CreateUpdateRequiredWorkflowOptions) (*OrgRequiredWorkflow, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows", org) + req, err := s.client.NewRequest("POST", url, createRequiredWorkflowOptions) + if err != nil { + return nil, nil, err + } + + orgRequiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, orgRequiredWorkflow) + if err != nil { + return nil, resp, err + } + + return orgRequiredWorkflow, resp, nil +} + +// GetRequiredWorkflowByID get the RequiredWorkflows for an org by its ID. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) GetRequiredWorkflowByID(ctx context.Context, owner string, requiredWorkflowID int64) (*OrgRequiredWorkflow, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", owner, requiredWorkflowID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, &requiredWorkflow) + if err != nil { + return nil, resp, err + } + + return requiredWorkflow, resp, nil +} + +// UpdateRequiredWorkflow updates a required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PATCH /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) UpdateRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID int64, updateRequiredWorkflowOptions *CreateUpdateRequiredWorkflowOptions) (*OrgRequiredWorkflow, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", org, requiredWorkflowID) + req, err := s.client.NewRequest("PATCH", url, updateRequiredWorkflowOptions) + if err != nil { + return nil, nil, err + } + + orgRequiredWorkflow := new(OrgRequiredWorkflow) + resp, err := s.client.Do(ctx, req, orgRequiredWorkflow) + if err != nil { + return nil, resp, err + } + + return orgRequiredWorkflow, resp, nil +} + +// DeleteRequiredWorkflow deletes a required workflow in an org. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation DELETE /orgs/{org}/actions/required_workflows/{workflow_id} +func (s *ActionsService) DeleteRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v", org, requiredWorkflowID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListRequiredWorkflowSelectedRepos lists the Repositories selected for a workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /orgs/{org}/actions/required_workflows/{workflow_id}/repositories +func (s *ActionsService) ListRequiredWorkflowSelectedRepos(ctx context.Context, org string, requiredWorkflowID int64, opts *ListOptions) (*RequiredWorkflowSelectedRepos, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories", org, requiredWorkflowID) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflowRepos := new(RequiredWorkflowSelectedRepos) + resp, err := s.client.Do(ctx, req, &requiredWorkflowRepos) + if err != nil { + return nil, resp, err + } + + return requiredWorkflowRepos, resp, nil +} + +// SetRequiredWorkflowSelectedRepos sets the Repositories selected for a workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PUT /orgs/{org}/actions/required_workflows/{workflow_id}/repositories +func (s *ActionsService) SetRequiredWorkflowSelectedRepos(ctx context.Context, org string, requiredWorkflowID int64, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories", org, requiredWorkflowID) + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRepoToRequiredWorkflow adds the Repository to a required workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation PUT /orgs/{org}/actions/required_workflows/{workflow_id}/repositories/{repository_id} +func (s *ActionsService) AddRepoToRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID, repoID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories/%v", org, requiredWorkflowID, repoID) + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// RemoveRepoFromRequiredWorkflow removes the Repository from a required workflow. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation DELETE /orgs/{org}/actions/required_workflows/{workflow_id}/repositories/{repository_id} +func (s *ActionsService) RemoveRepoFromRequiredWorkflow(ctx context.Context, org string, requiredWorkflowID, repoID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/required_workflows/%v/repositories/%v", org, requiredWorkflowID, repoID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListRepoRequiredWorkflows lists the RequiredWorkflows for a repo. +// +// GitHub API docs: https://docs.github.com/actions/using-workflows/required-workflows +// +//meta:operation GET /repos/{owner}/{repo}/actions/required_workflows +func (s *ActionsService) ListRepoRequiredWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*RepoRequiredWorkflows, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/required_workflows", owner, repo) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + requiredWorkflows := new(RepoRequiredWorkflows) + resp, err := s.client.Do(ctx, req, &requiredWorkflows) + if err != nil { + return nil, resp, err + } + + return requiredWorkflows, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go b/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go new file mode 100644 index 00000000..b2ee32f6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go @@ -0,0 +1,337 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerGroup represents a self-hosted runner group configured in an organization. +type RunnerGroup struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Default *bool `json:"default,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + RunnersURL *string `json:"runners_url,omitempty"` + Inherited *bool `json:"inherited,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` + WorkflowRestrictionsReadOnly *bool `json:"workflow_restrictions_read_only,omitempty"` +} + +// RunnerGroups represents a collection of self-hosted runner groups configured for an organization. +type RunnerGroups struct { + TotalCount int `json:"total_count"` + RunnerGroups []*RunnerGroup `json:"runner_groups"` +} + +// CreateRunnerGroupRequest represents a request to create a Runner group for an organization. +type CreateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // List of repository IDs that can access the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"` + // Runners represent a list of runner IDs to add to the runner group. + Runners []int64 `json:"runners,omitempty"` + // If set to True, public repos can use this runner group + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + // If true, the runner group will be restricted to running only the workflows specified in the SelectedWorkflows slice. + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + // List of workflows the runner group should be allowed to run. This setting will be ignored unless RestrictedToWorkflows is set to true. + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// UpdateRunnerGroupRequest represents a request to update a Runner group for an organization. +type UpdateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// SetRepoAccessRunnerGroupRequest represents a request to replace the list of repositories +// that can access a self-hosted runner group configured in an organization. +type SetRepoAccessRunnerGroupRequest struct { + // Updated list of repository IDs that should be given access to the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids"` +} + +// SetRunnerGroupRunnersRequest represents a request to replace the list of +// self-hosted runners that are part of an organization runner group. +type SetRunnerGroupRunnersRequest struct { + // Updated list of runner IDs that should be given access to the runner group. + Runners []int64 `json:"runners"` +} + +// ListOrgRunnerGroupOptions extend ListOptions to have the optional parameters VisibleToRepository. +type ListOrgRunnerGroupOptions struct { + ListOptions + + // Only return runner groups that are allowed to be used by this repository. + VisibleToRepository string `url:"visible_to_repository,omitempty"` +} + +// ListOrganizationRunnerGroups lists all self-hosted runner groups configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-self-hosted-runner-groups-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups +func (s *ActionsService) ListOrganizationRunnerGroups(ctx context.Context, org string, opts *ListOrgRunnerGroupOptions) (*RunnerGroups, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := &RunnerGroups{} + resp, err := s.client.Do(ctx, req, &groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// GetOrganizationRunnerGroup gets a specific self-hosted runner group for an organization using its RunnerGroup ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#get-a-self-hosted-runner-group-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) GetOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// DeleteOrganizationRunnerGroup deletes a self-hosted runner group from an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#delete-a-self-hosted-runner-group-from-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) DeleteOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrganizationRunnerGroup creates a new self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#create-a-self-hosted-runner-group-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runner-groups +func (s *ActionsService) CreateOrganizationRunnerGroup(ctx context.Context, org string, createReq CreateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// UpdateOrganizationRunnerGroup updates a self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-organization +// +//meta:operation PATCH /orgs/{org}/actions/runner-groups/{runner_group_id} +func (s *ActionsService) UpdateOrganizationRunnerGroup(ctx context.Context, org string, groupID int64, updateReq UpdateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// ListRepositoryAccessRunnerGroup lists the repositories with access to a self-hosted runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories +func (s *ActionsService) ListRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ListRepositories{} + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetRepositoryAccessRunnerGroup replaces the list of repositories that have access to a self-hosted runner group configured in an organization +// with a new List of repositories. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#set-repository-access-for-a-self-hosted-runner-group-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories +func (s *ActionsService) SetRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, ids SetRepoAccessRunnerGroupRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRepositoryAccessRunnerGroup adds a repository to the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#add-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id} +func (s *ActionsService) AddRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRepositoryAccessRunnerGroup removes a repository from the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#remove-repository-access-to-a-self-hosted-runner-group-in-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories/{repository_id} +func (s *ActionsService) RemoveRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListRunnerGroupRunners lists self-hosted runners that are in a specific organization group. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#list-self-hosted-runners-in-a-group-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners +func (s *ActionsService) ListRunnerGroupRunners(ctx context.Context, org string, groupID int64, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an organization runner group +// with a new list of runners. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#set-self-hosted-runners-in-a-group-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/runners +func (s *ActionsService) SetRunnerGroupRunners(ctx context.Context, org string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#add-a-self-hosted-runner-to-a-group-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *ActionsService) AddRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an organization. +// The runner is then returned to the default group. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runner-groups#remove-a-self-hosted-runner-from-a-group-for-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *ActionsService) RemoveRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_runners.go b/vendor/github.com/google/go-github/v68/github/actions_runners.go new file mode 100644 index 00000000..c4ae4823 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_runners.go @@ -0,0 +1,377 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerApplicationDownload represents a binary for the self-hosted runner application that can be downloaded. +type RunnerApplicationDownload struct { + OS *string `json:"os,omitempty"` + Architecture *string `json:"architecture,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Filename *string `json:"filename,omitempty"` + TempDownloadToken *string `json:"temp_download_token,omitempty"` + SHA256Checksum *string `json:"sha256_checksum,omitempty"` +} + +// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-runner-applications-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners/downloads +func (s *ActionsService) ListRunnerApplicationDownloads(ctx context.Context, owner, repo string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/downloads", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// GenerateJITConfigRequest specifies body parameters to GenerateRepoJITConfig. +type GenerateJITConfigRequest struct { + Name string `json:"name"` + RunnerGroupID int64 `json:"runner_group_id"` + WorkFolder *string `json:"work_folder,omitempty"` + + // Labels represents the names of the custom labels to add to the runner. + // Minimum items: 1. Maximum items: 100. + Labels []string `json:"labels"` +} + +// JITRunnerConfig represents encoded JIT configuration that can be used to bootstrap a self-hosted runner. +type JITRunnerConfig struct { + Runner *Runner `json:"runner,omitempty"` + EncodedJITConfig *string `json:"encoded_jit_config,omitempty"` +} + +// GenerateOrgJITConfig generate a just-in-time configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/generate-jitconfig +func (s *ActionsService) GenerateOrgJITConfig(ctx context.Context, org string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/generate-jitconfig", org) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// GenerateRepoJITConfig generates a just-in-time configuration for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig +func (s *ActionsService) GenerateRepoJITConfig(ctx context.Context, owner, repo string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/generate-jitconfig", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// RegistrationToken represents a token that can be used to add a self-hosted runner to a repository. +type RegistrationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-registration-token-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/registration-token +func (s *ActionsService) CreateRegistrationToken(ctx context.Context, owner, repo string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/registration-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// Runner represents a self-hosted runner registered with a repository. +type Runner struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + OS *string `json:"os,omitempty"` + Status *string `json:"status,omitempty"` + Busy *bool `json:"busy,omitempty"` + Labels []*RunnerLabels `json:"labels,omitempty"` +} + +// RunnerLabels represents a collection of labels attached to each runner. +type RunnerLabels struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Runners represents a collection of self-hosted runners for a repository. +type Runners struct { + TotalCount int `json:"total_count"` + Runners []*Runner `json:"runners"` +} + +// ListRunnersOptions specifies the optional parameters to the ListRunners and ListOrganizationRunners methods. +type ListRunnersOptions struct { + Name *string `url:"name,omitempty"` + ListOptions +} + +// ListRunners lists all the self-hosted runners for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-self-hosted-runners-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners +func (s *ActionsService) ListRunners(ctx context.Context, owner, repo string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetRunner gets a specific self-hosted runner for a repository using its runner ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runners/{runner_id} +func (s *ActionsService) GetRunner(ctx context.Context, owner, repo string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// RemoveToken represents a token that can be used to remove a self-hosted runner from a repository. +type RemoveToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRemoveToken creates a token that can be used to remove a self-hosted runner from a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-remove-token-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/actions/runners/remove-token +func (s *ActionsService) CreateRemoveToken(ctx context.Context, owner, repo string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/remove-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner in a repository using the runner id. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runners/{runner_id} +func (s *ActionsService) RemoveRunner(ctx context.Context, owner, repo string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrganizationRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-runner-applications-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners/downloads +func (s *ActionsService) ListOrganizationRunnerApplicationDownloads(ctx context.Context, org string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/downloads", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// CreateOrganizationRegistrationToken creates a token that can be used to add a self-hosted runner to an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-registration-token-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/registration-token +func (s *ActionsService) CreateOrganizationRegistrationToken(ctx context.Context, org string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/registration-token", org) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListOrganizationRunners lists all the self-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners +func (s *ActionsService) ListOrganizationRunners(ctx context.Context, org string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetOrganizationRunner gets a specific self-hosted runner for an organization using its runner ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/runners/{runner_id} +func (s *ActionsService) GetOrganizationRunner(ctx context.Context, org string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", org, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// CreateOrganizationRemoveToken creates a token that can be used to remove a self-hosted runner from an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#create-a-remove-token-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/runners/remove-token +func (s *ActionsService) CreateOrganizationRemoveToken(ctx context.Context, org string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/remove-token", org) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveOrganizationRunner forces the removal of a self-hosted runner from an organization using the runner id. +// +// GitHub API docs: https://docs.github.com/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/runners/{runner_id} +func (s *ActionsService) RemoveOrganizationRunner(ctx context.Context, org string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", org, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_secrets.go b/vendor/github.com/google/go-github/v68/github/actions_secrets.go new file mode 100644 index 00000000..cba85c10 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_secrets.go @@ -0,0 +1,407 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strconv" +) + +// PublicKey represents the public key that should be used to encrypt secrets. +type PublicKey struct { + KeyID *string `json:"key_id"` + Key *string `json:"key"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This ensures GitHub Enterprise versions which return a numeric key id +// do not error out when unmarshaling. +func (p *PublicKey) UnmarshalJSON(data []byte) error { + var pk struct { + KeyID interface{} `json:"key_id"` + Key *string `json:"key"` + } + + if err := json.Unmarshal(data, &pk); err != nil { + return err + } + + p.Key = pk.Key + + switch v := pk.KeyID.(type) { + case nil: + return nil + case string: + p.KeyID = &v + case float64: + p.KeyID = Ptr(strconv.FormatFloat(v, 'f', -1, 64)) + default: + return fmt.Errorf("unable to unmarshal %T as a string", v) + } + + return nil +} + +func (s *ActionsService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets/public-key +func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/actions/secrets/public-key +func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +// GetEnvPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#get-an-environment-public-key +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key +func (s *ActionsService) GetEnvPublicKey(ctx context.Context, repoID int, env string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/public-key", repoID, env) + return s.getPublicKey(ctx, url) +} + +// Secret represents a repository action secret. +type Secret struct { + Name string `json:"name"` + CreatedAt Timestamp `json:"created_at"` + UpdatedAt Timestamp `json:"updated_at"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` +} + +// Secrets represents one item from the ListSecrets response. +type Secrets struct { + TotalCount int `json:"total_count"` + Secrets []*Secret `json:"secrets"` +} + +func (s *ActionsService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets +func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListRepoOrgSecrets lists all organization secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-organization-secrets +// +//meta:operation GET /repos/{owner}/{repo}/actions/organization-secrets +func (s *ActionsService) ListRepoOrgSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/organization-secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/actions/secrets +func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +// ListEnvSecrets lists all secrets available in an environment. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#list-environment-secrets +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets +func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) + return s.listSecrets(ctx, url, opts) +} + +func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +// GetEnvSecret gets a single environment secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#get-an-environment-secret +// +//meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.getSecret(ctx, url) +} + +// SelectedRepoIDs are the repository IDs that have access to the actions secrets. +type SelectedRepoIDs []int64 + +// EncryptedSecret represents a secret that is encrypted using a public key. +// +// The value of EncryptedValue must be your secret, encrypted with +// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) +// using the public key retrieved using the GetPublicKey method. +type EncryptedSecret struct { + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#create-or-update-an-environment-secret +// +//meta:operation PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name} +func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name} +func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// DeleteEnvSecret deletes a secret in an environment using the secret name. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#delete-an-environment-secret +// +//meta:operation DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} +func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.deleteSecret(ctx, url) +} + +// SelectedReposList represents the list of repositories selected for an organization secret. +type SelectedReposList struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/actions/secrets/{secret_name}/repositories +func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.listSelectedReposForSecret(ctx, url, opts) +} + +func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetSelectedReposForOrgSecret sets the repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories +func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.setSelectedReposForSecret(ctx, url, ids) +} + +func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} +func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, url) +} + +func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. +// +// GitHub API docs: https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} +func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, url) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_variables.go b/vendor/github.com/google/go-github/v68/github/actions_variables.go new file mode 100644 index 00000000..bca46b6d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_variables.go @@ -0,0 +1,341 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsVariable represents a repository action variable. +type ActionsVariable struct { + Name string `json:"name"` + Value string `json:"value"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // Used by ListOrgVariables and GetOrgVariables + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + // Used by UpdateOrgVariable and CreateOrgVariable + SelectedRepositoryIDs *SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +// ActionsVariables represents one item from the ListVariables response. +type ActionsVariables struct { + TotalCount int `json:"total_count"` + Variables []*ActionsVariable `json:"variables"` +} + +func (s *ActionsService) listVariables(ctx context.Context, url string, opts *ListOptions) (*ActionsVariables, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + variables := new(ActionsVariables) + resp, err := s.client.Do(ctx, req, &variables) + if err != nil { + return nil, resp, err + } + + return variables, resp, nil +} + +// ListRepoVariables lists all variables available in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-repository-variables +// +//meta:operation GET /repos/{owner}/{repo}/actions/variables +func (s *ActionsService) ListRepoVariables(ctx context.Context, owner, repo string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables", owner, repo) + return s.listVariables(ctx, url, opts) +} + +// ListRepoOrgVariables lists all organization variables available in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-repository-organization-variables +// +//meta:operation GET /repos/{owner}/{repo}/actions/organization-variables +func (s *ActionsService) ListRepoOrgVariables(ctx context.Context, owner, repo string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/organization-variables", owner, repo) + return s.listVariables(ctx, url, opts) +} + +// ListOrgVariables lists all variables available in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-organization-variables +// +//meta:operation GET /orgs/{org}/actions/variables +func (s *ActionsService) ListOrgVariables(ctx context.Context, org string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables", org) + return s.listVariables(ctx, url, opts) +} + +// ListEnvVariables lists all variables available in an environment. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-environment-variables +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/variables +func (s *ActionsService) ListEnvVariables(ctx context.Context, owner, repo, env string, opts *ListOptions) (*ActionsVariables, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables", owner, repo, env) + return s.listVariables(ctx, url, opts) +} + +func (s *ActionsService) getVariable(ctx context.Context, url string) (*ActionsVariable, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + variable := new(ActionsVariable) + resp, err := s.client.Do(ctx, req, variable) + if err != nil { + return nil, resp, err + } + + return variable, resp, nil +} + +// GetRepoVariable gets a single repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-a-repository-variable +// +//meta:operation GET /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) GetRepoVariable(ctx context.Context, owner, repo, name string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, name) + return s.getVariable(ctx, url) +} + +// GetOrgVariable gets a single organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-an-organization-variable +// +//meta:operation GET /orgs/{org}/actions/variables/{name} +func (s *ActionsService) GetOrgVariable(ctx context.Context, org, name string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, name) + return s.getVariable(ctx, url) +} + +// GetEnvVariable gets a single environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#get-an-environment-variable +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) GetEnvVariable(ctx context.Context, owner, repo, env, variableName string) (*ActionsVariable, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variableName) + return s.getVariable(ctx, url) +} + +func (s *ActionsService) postVariable(ctx context.Context, url string, variable *ActionsVariable) (*Response, error) { + req, err := s.client.NewRequest("POST", url, variable) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// CreateRepoVariable creates a repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-a-repository-variable +// +//meta:operation POST /repos/{owner}/{repo}/actions/variables +func (s *ActionsService) CreateRepoVariable(ctx context.Context, owner, repo string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables", owner, repo) + return s.postVariable(ctx, url, variable) +} + +// CreateOrgVariable creates an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-an-organization-variable +// +//meta:operation POST /orgs/{org}/actions/variables +func (s *ActionsService) CreateOrgVariable(ctx context.Context, org string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables", org) + return s.postVariable(ctx, url, variable) +} + +// CreateEnvVariable creates an environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#create-an-environment-variable +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/variables +func (s *ActionsService) CreateEnvVariable(ctx context.Context, owner, repo, env string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables", owner, repo, env) + return s.postVariable(ctx, url, variable) +} + +func (s *ActionsService) patchVariable(ctx context.Context, url string, variable *ActionsVariable) (*Response, error) { + req, err := s.client.NewRequest("PATCH", url, variable) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UpdateRepoVariable updates a repository variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-a-repository-variable +// +//meta:operation PATCH /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) UpdateRepoVariable(ctx context.Context, owner, repo string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +// UpdateOrgVariable updates an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-an-organization-variable +// +//meta:operation PATCH /orgs/{org}/actions/variables/{name} +func (s *ActionsService) UpdateOrgVariable(ctx context.Context, org string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +// UpdateEnvVariable updates an environment variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#update-an-environment-variable +// +//meta:operation PATCH /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) UpdateEnvVariable(ctx context.Context, owner, repo, env string, variable *ActionsVariable) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variable.Name) + return s.patchVariable(ctx, url, variable) +} + +func (s *ActionsService) deleteVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoVariable deletes a variable in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-a-repository-variable +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/variables/{name} +func (s *ActionsService) DeleteRepoVariable(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/variables/%v", owner, repo, name) + return s.deleteVariable(ctx, url) +} + +// DeleteOrgVariable deletes a variable in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-an-organization-variable +// +//meta:operation DELETE /orgs/{org}/actions/variables/{name} +func (s *ActionsService) DeleteOrgVariable(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v", org, name) + return s.deleteVariable(ctx, url) +} + +// DeleteEnvVariable deletes a variable in an environment. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#delete-an-environment-variable +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/variables/{name} +func (s *ActionsService) DeleteEnvVariable(ctx context.Context, owner, repo, env, variableName string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/environments/%v/variables/%v", owner, repo, env, variableName) + return s.deleteVariable(ctx, url) +} + +func (s *ActionsService) listSelectedReposForVariable(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// ListSelectedReposForOrgVariable lists all repositories that have access to a variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#list-selected-repositories-for-an-organization-variable +// +//meta:operation GET /orgs/{org}/actions/variables/{name}/repositories +func (s *ActionsService) ListSelectedReposForOrgVariable(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories", org, name) + return s.listSelectedReposForVariable(ctx, url, opts) +} + +func (s *ActionsService) setSelectedReposForVariable(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetSelectedReposForOrgVariable sets the repositories that have access to a variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#set-selected-repositories-for-an-organization-variable +// +//meta:operation PUT /orgs/{org}/actions/variables/{name}/repositories +func (s *ActionsService) SetSelectedReposForOrgVariable(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories", org, name) + return s.setSelectedReposForVariable(ctx, url, ids) +} + +func (s *ActionsService) addSelectedRepoToVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgVariable adds a repository to an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#add-selected-repository-to-an-organization-variable +// +//meta:operation PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id} +func (s *ActionsService) AddSelectedRepoToOrgVariable(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToVariable(ctx, url) +} + +func (s *ActionsService) removeSelectedRepoFromVariable(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgVariable removes a repository from an organization variable. +// +// GitHub API docs: https://docs.github.com/rest/actions/variables#remove-selected-repository-from-an-organization-variable +// +//meta:operation DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id} +func (s *ActionsService) RemoveSelectedRepoFromOrgVariable(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/variables/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromVariable(ctx, url) +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go b/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go new file mode 100644 index 00000000..84bbe5aa --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go @@ -0,0 +1,165 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// TaskStep represents a single task step from a sequence of tasks of a job. +type TaskStep struct { + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + Number *int64 `json:"number,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` +} + +// WorkflowJob represents a repository action workflow job. +type WorkflowJob struct { + ID *int64 `json:"id,omitempty"` + RunID *int64 `json:"run_id,omitempty"` + RunURL *string `json:"run_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Name *string `json:"name,omitempty"` + Steps []*TaskStep `json:"steps,omitempty"` + CheckRunURL *string `json:"check_run_url,omitempty"` + // Labels represents runner labels from the `runs-on:` key from a GitHub Actions workflow. + Labels []string `json:"labels,omitempty"` + RunnerID *int64 `json:"runner_id,omitempty"` + RunnerName *string `json:"runner_name,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + RunnerGroupName *string `json:"runner_group_name,omitempty"` + RunAttempt *int64 `json:"run_attempt,omitempty"` + WorkflowName *string `json:"workflow_name,omitempty"` +} + +// Jobs represents a slice of repository action workflow job. +type Jobs struct { + TotalCount *int `json:"total_count,omitempty"` + Jobs []*WorkflowJob `json:"jobs,omitempty"` +} + +// ListWorkflowJobsOptions specifies optional parameters to ListWorkflowJobs. +type ListWorkflowJobsOptions struct { + // Filter specifies how jobs should be filtered by their completed_at timestamp. + // Possible values are: + // latest - Returns jobs from the most recent execution of the workflow run + // all - Returns all jobs for a workflow run, including from old executions of the workflow run + // + // Default value is "latest". + Filter string `url:"filter,omitempty"` + ListOptions +} + +// ListWorkflowJobs lists all jobs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs +func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo string, runID int64, opts *ListWorkflowJobsOptions) (*Jobs, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/jobs", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + jobs := new(Jobs) + resp, err := s.client.Do(ctx, req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, nil +} + +// ListWorkflowJobsAttempt lists jobs for a workflow run Attempt. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run-attempt +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs +func (s *ActionsService) ListWorkflowJobsAttempt(ctx context.Context, owner, repo string, runID, attemptNumber int64, opts *ListOptions) (*Jobs, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/attempts/%v/jobs", owner, repo, runID, attemptNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + jobs := new(Jobs) + resp, err := s.client.Do(ctx, req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, nil +} + +// GetWorkflowJobByID gets a specific job in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/jobs/{job_id} +func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo string, jobID int64) (*WorkflowJob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v", owner, repo, jobID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + job := new(WorkflowJob) + resp, err := s.client.Do(ctx, req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, nil +} + +// GetWorkflowJobLogs gets a redirect URL to download a plain text file of logs for a workflow job. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-jobs#download-job-logs-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs +func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go b/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go new file mode 100644 index 00000000..122ea1d0 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go @@ -0,0 +1,475 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// WorkflowRun represents a repository action workflow run. +type WorkflowRun struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + Path *string `json:"path,omitempty"` + RunNumber *int `json:"run_number,omitempty"` + RunAttempt *int `json:"run_attempt,omitempty"` + Event *string `json:"event,omitempty"` + DisplayTitle *string `json:"display_title,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + WorkflowID *int64 `json:"workflow_id,omitempty"` + CheckSuiteID *int64 `json:"check_suite_id,omitempty"` + CheckSuiteNodeID *string `json:"check_suite_node_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + RunStartedAt *Timestamp `json:"run_started_at,omitempty"` + JobsURL *string `json:"jobs_url,omitempty"` + LogsURL *string `json:"logs_url,omitempty"` + CheckSuiteURL *string `json:"check_suite_url,omitempty"` + ArtifactsURL *string `json:"artifacts_url,omitempty"` + CancelURL *string `json:"cancel_url,omitempty"` + RerunURL *string `json:"rerun_url,omitempty"` + PreviousAttemptURL *string `json:"previous_attempt_url,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + WorkflowURL *string `json:"workflow_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + HeadRepository *Repository `json:"head_repository,omitempty"` + Actor *User `json:"actor,omitempty"` + TriggeringActor *User `json:"triggering_actor,omitempty"` + ReferencedWorkflows []*ReferencedWorkflow `json:"referenced_workflows,omitempty"` +} + +// WorkflowRuns represents a slice of repository action workflow run. +type WorkflowRuns struct { + TotalCount *int `json:"total_count,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflow_runs,omitempty"` +} + +// ListWorkflowRunsOptions specifies optional parameters to ListWorkflowRuns. +type ListWorkflowRunsOptions struct { + Actor string `url:"actor,omitempty"` + Branch string `url:"branch,omitempty"` + Event string `url:"event,omitempty"` + Status string `url:"status,omitempty"` + Created string `url:"created,omitempty"` + HeadSHA string `url:"head_sha,omitempty"` + ExcludePullRequests bool `url:"exclude_pull_requests,omitempty"` + CheckSuiteID int64 `url:"check_suite_id,omitempty"` + ListOptions +} + +// WorkflowRunUsage represents a usage of a specific workflow run. +type WorkflowRunUsage struct { + Billable *WorkflowRunBillMap `json:"billable,omitempty"` + RunDurationMS *int64 `json:"run_duration_ms,omitempty"` +} + +// WorkflowRunBillMap represents different runner environments available for a workflow run. +// Its key is the name of its environment, e.g. "UBUNTU", "MACOS", "WINDOWS", etc. +type WorkflowRunBillMap map[string]*WorkflowRunBill + +// WorkflowRunBill specifies billable time for a specific environment in a workflow run. +type WorkflowRunBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` + Jobs *int `json:"jobs,omitempty"` + JobRuns []*WorkflowRunJobRun `json:"job_runs,omitempty"` +} + +// WorkflowRunJobRun represents a usage of individual jobs of a specific workflow run. +type WorkflowRunJobRun struct { + JobID *int `json:"job_id,omitempty"` + DurationMS *int64 `json:"duration_ms,omitempty"` +} + +// WorkflowRunAttemptOptions specifies optional parameters to GetWorkflowRunAttempt. +type WorkflowRunAttemptOptions struct { + ExcludePullRequests *bool `url:"exclude_pull_requests,omitempty"` +} + +// PendingDeploymentsRequest specifies body parameters to PendingDeployments. +type PendingDeploymentsRequest struct { + EnvironmentIDs []int64 `json:"environment_ids"` + // State can be one of: "approved", "rejected". + State string `json:"state"` + Comment string `json:"comment"` +} + +type ReferencedWorkflow struct { + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` +} + +// PendingDeployment represents the pending_deployments response. +type PendingDeployment struct { + Environment *PendingDeploymentEnvironment `json:"environment,omitempty"` + WaitTimer *int64 `json:"wait_timer,omitempty"` + WaitTimerStartedAt *Timestamp `json:"wait_timer_started_at,omitempty"` + CurrentUserCanApprove *bool `json:"current_user_can_approve,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` +} + +// PendingDeploymentEnvironment represents pending deployment environment properties. +type PendingDeploymentEnvironment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ReviewCustomDeploymentProtectionRuleRequest specifies the parameters to ReviewCustomDeploymentProtectionRule. +type ReviewCustomDeploymentProtectionRuleRequest struct { + EnvironmentName string `json:"environment_name"` + State string `json:"state"` + Comment string `json:"comment"` +} + +func (s *ActionsService) listWorkflowRuns(ctx context.Context, endpoint string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u, err := addOptions(endpoint, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// ListWorkflowRunsByID lists all workflow runs by workflow ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs +func (s *ActionsService) ListWorkflowRunsByID(ctx context.Context, owner, repo string, workflowID int64, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowID) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListWorkflowRunsByFileName lists all workflow runs by workflow file name. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs +func (s *ActionsService) ListWorkflowRunsByFileName(ctx context.Context, owner, repo, workflowFileName string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowFileName) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListRepositoryWorkflowRuns lists all workflow runs for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs +func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner, repo string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// GetWorkflowRunByID gets a specific workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id} +func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// GetWorkflowRunAttempt gets a specific workflow run attempt. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run-attempt +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number} +func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo string, runID int64, attemptNumber int, opts *WorkflowRunAttemptOptions) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v", owner, repo, runID, attemptNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// GetWorkflowRunAttemptLogs gets a redirect URL to download a plain text file of logs for a workflow run for attempt number. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-attempt-logs +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs +func (s *ActionsService) GetWorkflowRunAttemptLogs(ctx context.Context, owner, repo string, runID int64, attemptNumber int, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v/logs", owner, repo, runID, attemptNumber) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} + +// RerunWorkflowByID re-runs a workflow by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun +func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunFailedJobsByID re-runs all of the failed jobs and their dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-failed-jobs-from-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs +func (s *ActionsService) RerunFailedJobsByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun-failed-jobs", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunJobByID re-runs a job and its dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-job-from-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun +func (s *ActionsService) RerunJobByID(ctx context.Context, owner, repo string, jobID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/rerun", owner, repo, jobID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CancelWorkflowRunByID cancels a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel +func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/cancel", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-logs +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs +func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} + +// DeleteWorkflowRun deletes a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-a-workflow-run +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runs/{run_id} +func (s *ActionsService) DeleteWorkflowRun(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteWorkflowRunLogs deletes all logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-workflow-run-logs +// +//meta:operation DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs +func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-workflow-run-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing +func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRunUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/timing", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflowRunUsage := new(WorkflowRunUsage) + resp, err := s.client.Do(ctx, req, workflowRunUsage) + if err != nil { + return nil, resp, err + } + + return workflowRunUsage, resp, nil +} + +// GetPendingDeployments get all deployment environments for a workflow run that are waiting for protection rules to pass. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-pending-deployments-for-a-workflow-run +// +//meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments +func (s *ActionsService) GetPendingDeployments(ctx context.Context, owner, repo string, runID int64) ([]*PendingDeployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/pending_deployments", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var deployments []*PendingDeployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// PendingDeployments approve or reject pending deployments that are waiting on approval by a required reviewer. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-pending-deployments-for-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments +func (s *ActionsService) PendingDeployments(ctx context.Context, owner, repo string, runID int64, request *PendingDeploymentsRequest) ([]*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/pending_deployments", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var deployments []*Deployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// ReviewCustomDeploymentProtectionRule approves or rejects custom deployment protection rules provided by a GitHub App for a workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-custom-deployment-protection-rules-for-a-workflow-run +// +//meta:operation POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule +func (s *ActionsService) ReviewCustomDeploymentProtectionRule(ctx context.Context, owner, repo string, runID int64, request *ReviewCustomDeploymentProtectionRuleRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/deployment_protection_rule", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + return resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflows.go b/vendor/github.com/google/go-github/v68/github/actions_workflows.go new file mode 100644 index 00000000..0214e6ab --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/actions_workflows.go @@ -0,0 +1,237 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Workflow represents a repository action workflow. +type Workflow struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BadgeURL *string `json:"badge_url,omitempty"` +} + +// Workflows represents a slice of repository action workflows. +type Workflows struct { + TotalCount *int `json:"total_count,omitempty"` + Workflows []*Workflow `json:"workflows,omitempty"` +} + +// WorkflowUsage represents a usage of a specific workflow. +type WorkflowUsage struct { + Billable *WorkflowBillMap `json:"billable,omitempty"` +} + +// WorkflowBillMap represents different runner environments available for a workflow. +// Its key is the name of its environment, e.g. "UBUNTU", "MACOS", "WINDOWS", etc. +type WorkflowBillMap map[string]*WorkflowBill + +// WorkflowBill specifies billable time for a specific environment in a workflow. +type WorkflowBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` +} + +// CreateWorkflowDispatchEventRequest represents a request to create a workflow dispatch event. +type CreateWorkflowDispatchEventRequest struct { + // Ref represents the reference of the workflow run. + // The reference can be a branch or a tag. + // Ref is required when creating a workflow dispatch event. + Ref string `json:"ref"` + // Inputs represents input keys and values configured in the workflow file. + // The maximum number of properties is 10. + // Default: Any default properties configured in the workflow file will be used when `inputs` are omitted. + Inputs map[string]interface{} `json:"inputs,omitempty"` +} + +// ListWorkflows lists all workflows in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#list-repository-workflows +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows +func (s *ActionsService) ListWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*Workflows, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflows := new(Workflows) + resp, err := s.client.Do(ctx, req, &workflows) + if err != nil { + return nil, resp, err + } + + return workflows, resp, nil +} + +// GetWorkflowByID gets a specific workflow by ID. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id} +func (s *ActionsService) GetWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowID) + + return s.getWorkflow(ctx, u) +} + +// GetWorkflowByFileName gets a specific workflow by file name. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-a-workflow +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id} +func (s *ActionsService) GetWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowFileName) + + return s.getWorkflow(ctx, u) +} + +func (s *ActionsService) getWorkflow(ctx context.Context, url string) (*Workflow, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflow := new(Workflow) + resp, err := s.client.Do(ctx, req, workflow) + if err != nil { + return nil, resp, err + } + + return workflow, resp, nil +} + +// GetWorkflowUsageByID gets a specific workflow usage by ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-workflow-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing +func (s *ActionsService) GetWorkflowUsageByID(ctx context.Context, owner, repo string, workflowID int64) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowID) + + return s.getWorkflowUsage(ctx, u) +} + +// GetWorkflowUsageByFileName gets a specific workflow usage by file name in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#get-workflow-usage +// +//meta:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing +func (s *ActionsService) GetWorkflowUsageByFileName(ctx context.Context, owner, repo, workflowFileName string) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowFileName) + + return s.getWorkflowUsage(ctx, u) +} + +func (s *ActionsService) getWorkflowUsage(ctx context.Context, url string) (*WorkflowUsage, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflowUsage := new(WorkflowUsage) + resp, err := s.client.Do(ctx, req, workflowUsage) + if err != nil { + return nil, resp, err + } + + return workflowUsage, resp, nil +} + +// CreateWorkflowDispatchEventByID manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#create-a-workflow-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches +func (s *ActionsService) CreateWorkflowDispatchEventByID(ctx context.Context, owner, repo string, workflowID int64, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowID) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +// CreateWorkflowDispatchEventByFileName manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#create-a-workflow-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches +func (s *ActionsService) CreateWorkflowDispatchEventByFileName(ctx context.Context, owner, repo, workflowFileName string, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowFileName) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +func (s *ActionsService) createWorkflowDispatchEvent(ctx context.Context, url string, event *CreateWorkflowDispatchEventRequest) (*Response, error) { + req, err := s.client.NewRequest("POST", url, event) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// EnableWorkflowByID enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#enable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable +func (s *ActionsService) EnableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// EnableWorkflowByFileName enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#enable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable +func (s *ActionsService) EnableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByID disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#disable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable +func (s *ActionsService) DisableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByFileName disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/rest/actions/workflows#disable-a-workflow +// +//meta:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable +func (s *ActionsService) DisableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +func (s *ActionsService) doNewPutRequest(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/activity.go b/vendor/github.com/google/go-github/v68/github/activity.go new file mode 100644 index 00000000..edf8cc43 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity.go @@ -0,0 +1,77 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// ActivityService handles communication with the activity related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/activity/ +type ActivityService service + +// FeedLink represents a link to a related resource. +type FeedLink struct { + HRef *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Feeds represents timeline resources in Atom format. +type Feeds struct { + TimelineURL *string `json:"timeline_url,omitempty"` + UserURL *string `json:"user_url,omitempty"` + CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` + CurrentUserURL *string `json:"current_user_url,omitempty"` + CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` + CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` + CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` + Links *FeedLinks `json:"_links,omitempty"` +} + +// FeedLinks represents the links in a Feed. +type FeedLinks struct { + Timeline *FeedLink `json:"timeline,omitempty"` + User *FeedLink `json:"user,omitempty"` + CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` + CurrentUser *FeedLink `json:"current_user,omitempty"` + CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` + CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` + CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` +} + +// ListFeeds lists all the feeds available to the authenticated user. +// +// GitHub provides several timeline resources in Atom format: +// +// Timeline: The GitHub global public timeline +// User: The public timeline for any user, using URI template +// Current user public: The public timeline for the authenticated user +// Current user: The private timeline for the authenticated user +// Current user actor: The private timeline for activity created by the +// authenticated user +// Current user organizations: The private timeline for the organizations +// the authenticated user is a member of. +// +// Note: Private feeds are only returned when authenticating via Basic Auth +// since current feed URIs use the older, non revocable auth tokens. +// +// GitHub API docs: https://docs.github.com/rest/activity/feeds#get-feeds +// +//meta:operation GET /feeds +func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { + req, err := s.client.NewRequest("GET", "feeds", nil) + if err != nil { + return nil, nil, err + } + + f := &Feeds{} + resp, err := s.client.Do(ctx, req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/activity_events.go b/vendor/github.com/google/go-github/v68/github/activity_events.go new file mode 100644 index 00000000..b12baa99 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/activity_events.go @@ -0,0 +1,235 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events +// +//meta:operation GET /events +func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-repository-events +// +//meta:operation GET /repos/{owner}/{repo}/events +func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListIssueEventsForRepository lists issue events for a repository. +// +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/events +func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForRepoNetwork lists public events for a network of repositories. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-for-a-network-of-repositories +// +//meta:operation GET /networks/{owner}/{repo}/events +func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("networks/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists public events for an organization. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-organization-events +// +//meta:operation GET /orgs/{org}/events +func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-events-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-for-a-user +// +//meta:operation GET /users/{username}/events +//meta:operation GET /users/{username}/events/public +func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-events-received-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/activity/events#list-public-events-received-by-a-user +// +//meta:operation GET /users/{username}/received_events +//meta:operation GET /users/{username}/received_events/public +func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// GitHub API docs: https://docs.github.com/rest/activity/events#list-organization-events-for-the-authenticated-user +// +//meta:operation GET /users/{username}/events/orgs/{org} +func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/activity_notifications.go b/vendor/github.com/google/go-github/v68/github/activity_notifications.go similarity index 66% rename from vendor/github.com/google/go-github/github/activity_notifications.go rename to vendor/github.com/google/go-github/v68/github/activity_notifications.go index 45c8b2ae..e712323e 100644 --- a/vendor/github.com/google/go-github/github/activity_notifications.go +++ b/vendor/github.com/google/go-github/v68/github/activity_notifications.go @@ -19,12 +19,12 @@ type Notification struct { // Reason identifies the event that triggered the notification. // - // GitHub API docs: https://developer.github.com/v3/activity/notifications/#notification-reasons + // GitHub API docs: https://docs.github.com/rest/activity#notification-reasons Reason *string `json:"reason,omitempty"` Unread *bool `json:"unread,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - LastReadAt *time.Time `json:"last_read_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + LastReadAt *Timestamp `json:"last_read_at,omitempty"` URL *string `json:"url,omitempty"` } @@ -49,10 +49,12 @@ type NotificationListOptions struct { // ListNotifications lists all notifications for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications -func (s *ActivityService) ListNotifications(ctx context.Context, opt *NotificationListOptions) ([]*Notification, *Response, error) { - u := fmt.Sprintf("notifications") - u, err := addOptions(u, opt) +// GitHub API docs: https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user +// +//meta:operation GET /notifications +func (s *ActivityService) ListNotifications(ctx context.Context, opts *NotificationListOptions) ([]*Notification, *Response, error) { + u := "notifications" + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -74,10 +76,12 @@ func (s *ActivityService) ListNotifications(ctx context.Context, opt *Notificati // ListRepositoryNotifications lists all notifications in a given repository // for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository -func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opt *NotificationListOptions) ([]*Notification, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/notifications#list-repository-notifications-for-the-authenticated-user +// +//meta:operation GET /repos/{owner}/{repo}/notifications +func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opts *NotificationListOptions) ([]*Notification, *Response, error) { u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -97,13 +101,15 @@ func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner } type markReadOptions struct { - LastReadAt time.Time `json:"last_read_at,omitempty"` + LastReadAt Timestamp `json:"last_read_at,omitempty"` } // MarkNotificationsRead marks all notifications up to lastRead as read. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read -func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-notifications-as-read +// +//meta:operation PUT /notifications +func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead Timestamp) (*Response, error) { opts := &markReadOptions{ LastReadAt: lastRead, } @@ -118,8 +124,10 @@ func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead ti // MarkRepositoryNotificationsRead marks all notifications up to lastRead in // the specified repository as read. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository -func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-repository-notifications-as-read +// +//meta:operation PUT /repos/{owner}/{repo}/notifications +func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead Timestamp) (*Response, error) { opts := &markReadOptions{ LastReadAt: lastRead, } @@ -134,7 +142,9 @@ func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, o // GetThread gets the specified notification thread. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread +// GitHub API docs: https://docs.github.com/rest/activity/notifications#get-a-thread +// +//meta:operation GET /notifications/threads/{thread_id} func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { u := fmt.Sprintf("notifications/threads/%v", id) @@ -154,7 +164,9 @@ func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notificati // MarkThreadRead marks the specified thread as read. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-a-thread-as-read +// +//meta:operation PATCH /notifications/threads/{thread_id} func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("notifications/threads/%v", id) @@ -166,10 +178,29 @@ func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Respo return s.client.Do(ctx, req, nil) } +// MarkThreadDone marks the specified thread as done. +// Marking a thread as "done" is equivalent to marking a notification in your notification inbox on GitHub as done. +// +// GitHub API docs: https://docs.github.com/rest/activity/notifications#mark-a-thread-as-done +// +//meta:operation DELETE /notifications/threads/{thread_id} +func (s *ActivityService) MarkThreadDone(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + // GetThreadSubscription checks to see if the authenticated user is subscribed // to a thread. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription +// GitHub API docs: https://docs.github.com/rest/activity/notifications#get-a-thread-subscription-for-the-authenticated-user +// +//meta:operation GET /notifications/threads/{thread_id}/subscription func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) @@ -190,7 +221,9 @@ func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) // SetThreadSubscription sets the subscription for the specified thread for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription +// GitHub API docs: https://docs.github.com/rest/activity/notifications#set-a-thread-subscription +// +//meta:operation PUT /notifications/threads/{thread_id}/subscription func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) @@ -211,7 +244,9 @@ func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, // DeleteThreadSubscription deletes the subscription for the specified thread // for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription +// GitHub API docs: https://docs.github.com/rest/activity/notifications#delete-a-thread-subscription +// +//meta:operation DELETE /notifications/threads/{thread_id}/subscription func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("notifications/threads/%v/subscription", id) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/activity_star.go b/vendor/github.com/google/go-github/v68/github/activity_star.go similarity index 70% rename from vendor/github.com/google/go-github/github/activity_star.go rename to vendor/github.com/google/go-github/v68/github/activity_star.go index d5b06712..cebdacf7 100644 --- a/vendor/github.com/google/go-github/github/activity_star.go +++ b/vendor/github.com/google/go-github/v68/github/activity_star.go @@ -8,6 +8,7 @@ package github import ( "context" "fmt" + "strings" ) // StarredRepository is returned by ListStarred. @@ -24,10 +25,12 @@ type Stargazer struct { // ListStargazers lists people who have starred the specified repo. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers -func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-stargazers +// +//meta:operation GET /repos/{owner}/{repo}/stargazers +func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Stargazer, *Response, error) { u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -66,15 +69,19 @@ type ActivityListStarredOptions struct { // ListStarred lists all the repos starred by a user. Passing the empty string // will list the starred repositories for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-being-starred -func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-repositories-starred-by-a-user +// GitHub API docs: https://docs.github.com/rest/activity/starring#list-repositories-starred-by-the-authenticated-user +// +//meta:operation GET /user/starred +//meta:operation GET /users/{username}/starred +func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/starred", user) } else { u = "user/starred" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -84,8 +91,9 @@ func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *Act return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeStarringPreview) + // TODO: remove custom Accept header when APIs fully launch + acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var repos []*StarredRepository resp, err := s.client.Do(ctx, req, &repos) @@ -98,13 +106,16 @@ func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *Act // IsStarred checks if a repository is starred by authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository +// GitHub API docs: https://docs.github.com/rest/activity/starring#check-if-a-repository-is-starred-by-the-authenticated-user +// +//meta:operation GET /user/starred/{owner}/{repo} func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } + resp, err := s.client.Do(ctx, req, nil) starred, err := parseBoolResponse(err) return starred, resp, err @@ -112,24 +123,30 @@ func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bo // Star a repository as the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository +// GitHub API docs: https://docs.github.com/rest/activity/starring#star-a-repository-for-the-authenticated-user +// +//meta:operation PUT /user/starred/{owner}/{repo} func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } // Unstar a repository as the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository +// GitHub API docs: https://docs.github.com/rest/activity/starring#unstar-a-repository-for-the-authenticated-user +// +//meta:operation DELETE /user/starred/{owner}/{repo} func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("user/starred/%v/%v", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/github/activity_watching.go b/vendor/github.com/google/go-github/v68/github/activity_watching.go similarity index 77% rename from vendor/github.com/google/go-github/github/activity_watching.go rename to vendor/github.com/google/go-github/v68/github/activity_watching.go index c749ca86..34859005 100644 --- a/vendor/github.com/google/go-github/github/activity_watching.go +++ b/vendor/github.com/google/go-github/v68/github/activity_watching.go @@ -27,10 +27,12 @@ type Subscription struct { // ListWatchers lists watchers of a particular repo. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers -func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-watchers +// +//meta:operation GET /repos/{owner}/{repo}/subscribers +func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -52,15 +54,19 @@ func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, // ListWatched lists the repositories the specified user is watching. Passing // the empty string will fetch watched repos for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched -func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-repositories-watched-by-a-user +// GitHub API docs: https://docs.github.com/rest/activity/watching#list-repositories-watched-by-the-authenticated-user +// +//meta:operation GET /user/subscriptions +//meta:operation GET /users/{username}/subscriptions +func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/subscriptions", user) } else { u = "user/subscriptions" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -83,7 +89,9 @@ func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *Lis // repository for the authenticated user. If the authenticated user is not // watching the repository, a nil Subscription is returned. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription +// GitHub API docs: https://docs.github.com/rest/activity/watching#get-a-repository-subscription +// +//meta:operation GET /repos/{owner}/{repo}/subscription func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) @@ -110,7 +118,9 @@ func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, // To ignore notifications made within a repository, set subscription.Ignored to true. // To stop watching a repository, use DeleteRepositorySubscription. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription +// GitHub API docs: https://docs.github.com/rest/activity/watching#set-a-repository-subscription +// +//meta:operation PUT /repos/{owner}/{repo}/subscription func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) @@ -134,7 +144,9 @@ func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, // This is used to stop watching a repository. To control whether or not to // receive notifications from a repository, use SetRepositorySubscription. // -// GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription +// GitHub API docs: https://docs.github.com/rest/activity/watching#delete-a-repository-subscription +// +//meta:operation DELETE /repos/{owner}/{repo}/subscription func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/admin.go b/vendor/github.com/google/go-github/v68/github/admin.go similarity index 74% rename from vendor/github.com/google/go-github/github/admin.go rename to vendor/github.com/google/go-github/v68/github/admin.go index 2d96733a..adf55d64 100644 --- a/vendor/github.com/google/go-github/github/admin.go +++ b/vendor/github.com/google/go-github/v68/github/admin.go @@ -14,7 +14,7 @@ import ( // GitHub API. These API routes are normally only accessible for GitHub // Enterprise installations. // -// GitHub API docs: https://developer.github.com/v3/enterprise/ +// GitHub API docs: https://docs.github.com/rest/enterprise-admin type AdminService service // TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group. @@ -62,9 +62,29 @@ func (m UserLDAPMapping) String() string { return Stringify(m) } +// Enterprise represents the GitHub enterprise profile. +type Enterprise struct { + ID *int `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + Description *string `json:"description,omitempty"` + WebsiteURL *string `json:"website_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (m Enterprise) String() string { + return Stringify(m) +} + // UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. // -// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/ldap#update-ldap-mapping-for-a-user +// +//meta:operation PATCH /admin/ldap/users/{username}/mapping func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) { u := fmt.Sprintf("admin/ldap/users/%v/mapping", user) req, err := s.client.NewRequest("PATCH", u, mapping) @@ -83,7 +103,9 @@ func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, m // UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group. // -// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-team +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/ldap#update-ldap-mapping-for-a-team +// +//meta:operation PATCH /admin/ldap/teams/{team_id}/mapping func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) { u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team) req, err := s.client.NewRequest("PATCH", u, mapping) diff --git a/vendor/github.com/google/go-github/v68/github/admin_orgs.go b/vendor/github.com/google/go-github/v68/github/admin_orgs.go new file mode 100644 index 00000000..8b50756b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin_orgs.go @@ -0,0 +1,95 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// createOrgRequest is a subset of Organization and is used internally +// by CreateOrg to pass only the known fields for the endpoint. +type createOrgRequest struct { + Login *string `json:"login,omitempty"` + Admin *string `json:"admin,omitempty"` +} + +// CreateOrg creates a new organization in GitHub Enterprise. +// +// Note that only a subset of the org fields are used and org must +// not be nil. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#create-an-organization +// +//meta:operation POST /admin/organizations +func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) { + u := "admin/organizations" + + orgReq := &createOrgRequest{ + Login: org.Login, + Admin: &admin, + } + + req, err := s.client.NewRequest("POST", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// renameOrgRequest is a subset of Organization and is used internally +// by RenameOrg and RenameOrgByName to pass only the known fields for the endpoint. +type renameOrgRequest struct { + Login *string `json:"login,omitempty"` +} + +// RenameOrgResponse is the response given when renaming an Organization. +type RenameOrgResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// RenameOrg renames an organization in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#update-an-organization-name +// +//meta:operation PATCH /admin/organizations/{org} +func (s *AdminService) RenameOrg(ctx context.Context, org *Organization, newName string) (*RenameOrgResponse, *Response, error) { + return s.RenameOrgByName(ctx, *org.Login, newName) +} + +// RenameOrgByName renames an organization in GitHub Enterprise using its current name. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/orgs#update-an-organization-name +// +//meta:operation PATCH /admin/organizations/{org} +func (s *AdminService) RenameOrgByName(ctx context.Context, org, newName string) (*RenameOrgResponse, *Response, error) { + u := fmt.Sprintf("admin/organizations/%v", org) + + orgReq := &renameOrgRequest{ + Login: &newName, + } + + req, err := s.client.NewRequest("PATCH", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(RenameOrgResponse) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/admin_stats.go b/vendor/github.com/google/go-github/v68/github/admin_stats.go similarity index 93% rename from vendor/github.com/google/go-github/github/admin_stats.go rename to vendor/github.com/google/go-github/v68/github/admin_stats.go index b5645f8c..f012d798 100644 --- a/vendor/github.com/google/go-github/github/admin_stats.go +++ b/vendor/github.com/google/go-github/v68/github/admin_stats.go @@ -7,10 +7,9 @@ package github import ( "context" - "fmt" ) -// AdminStats represents a variety of stats of a Github Enterprise +// AdminStats represents a variety of stats of a GitHub Enterprise // installation. type AdminStats struct { Issues *IssueStats `json:"issues,omitempty"` @@ -147,15 +146,17 @@ func (s RepoStats) String() string { return Stringify(s) } -// GetAdminStats returns a variety of metrics about a Github Enterprise +// GetAdminStats returns a variety of metrics about a GitHub Enterprise // installation. // // Please note that this is only available to site administrators, // otherwise it will error with a 404 not found (instead of 401 or 403). // -// GitHub API docs: https://developer.github.com/v3/enterprise-admin/admin_stats/ +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/admin-stats#get-all-statistics +// +//meta:operation GET /enterprise/stats/all func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) { - u := fmt.Sprintf("enterprise/stats/all") + u := "enterprise/stats/all" req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err diff --git a/vendor/github.com/google/go-github/v68/github/admin_users.go b/vendor/github.com/google/go-github/v68/github/admin_users.go new file mode 100644 index 00000000..6877cef4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/admin_users.go @@ -0,0 +1,137 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CreateUserRequest represents the fields sent to the `CreateUser` endpoint. +// Note that `Login` is a required field. +type CreateUserRequest struct { + Login string `json:"login"` + Email *string `json:"email,omitempty"` + Suspended *bool `json:"suspended,omitempty"` +} + +// CreateUser creates a new user in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-a-user +// +//meta:operation POST /admin/users +func (s *AdminService) CreateUser(ctx context.Context, userReq CreateUserRequest) (*User, *Response, error) { + u := "admin/users" + + req, err := s.client.NewRequest("POST", u, userReq) + if err != nil { + return nil, nil, err + } + + var user User + resp, err := s.client.Do(ctx, req, &user) + if err != nil { + return nil, resp, err + } + + return &user, resp, nil +} + +// DeleteUser deletes a user in GitHub Enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-a-user +// +//meta:operation DELETE /admin/users/{username} +func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) { + u := "admin/users/" + username + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ImpersonateUserOptions represents the scoping for the OAuth token. +type ImpersonateUserOptions struct { + Scopes []string `json:"scopes,omitempty"` +} + +// OAuthAPP represents the GitHub Site Administrator OAuth app. +type OAuthAPP struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (s OAuthAPP) String() string { + return Stringify(s) +} + +// UserAuthorization represents the impersonation response. +type UserAuthorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []string `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *OAuthAPP `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +// CreateUserImpersonation creates an impersonation OAuth token. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-an-impersonation-oauth-token +// +//meta:operation POST /admin/users/{username}/authorizations +func (s *AdminService) CreateUserImpersonation(ctx context.Context, username string, opts *ImpersonateUserOptions) (*UserAuthorization, *Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + a := new(UserAuthorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// DeleteUserImpersonation deletes an impersonation OAuth token. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-an-impersonation-oauth-token +// +//meta:operation DELETE /admin/users/{username}/authorizations +func (s *AdminService) DeleteUserImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps.go b/vendor/github.com/google/go-github/v68/github/apps.go new file mode 100644 index 00000000..3dd392d0 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps.go @@ -0,0 +1,495 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AppsService provides access to the installation related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/apps/ +type AppsService service + +// App represents a GitHub App. +type App struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Events []string `json:"events,omitempty"` + InstallationsCount *int `json:"installations_count,omitempty"` +} + +// InstallationToken represents an installation token. +type InstallationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +// InstallationTokenOptions allow restricting a token's access to specific repositories. +type InstallationTokenOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids,omitempty"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +type InstallationTokenListRepoOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +// InstallationPermissions lists the repository and organization permissions for an installation. +// +// Permission names taken from: +// +// https://docs.github.com/enterprise-server@3.0/rest/apps#create-an-installation-access-token-for-an-app +// https://docs.github.com/rest/apps#create-an-installation-access-token-for-an-app +type InstallationPermissions struct { + Actions *string `json:"actions,omitempty"` + ActionsVariables *string `json:"actions_variables,omitempty"` + Administration *string `json:"administration,omitempty"` + Attestations *string `json:"attestations,omitempty"` + Blocking *string `json:"blocking,omitempty"` + Checks *string `json:"checks,omitempty"` + Codespaces *string `json:"codespaces,omitempty"` + CodespacesLifecycleAdmin *string `json:"codespaces_lifecycle_admin,omitempty"` + CodespacesMetadata *string `json:"codespaces_metadata,omitempty"` + CodespacesSecrets *string `json:"codespaces_secrets,omitempty"` + CodespacesUserSecrets *string `json:"codespaces_user_secrets,omitempty"` + Contents *string `json:"contents,omitempty"` + ContentReferences *string `json:"content_references,omitempty"` + CopilotMessages *string `json:"copilot_messages,omitempty"` + DependabotSecrets *string `json:"dependabot_secrets,omitempty"` + Deployments *string `json:"deployments,omitempty"` + Discussions *string `json:"discussions,omitempty"` + Emails *string `json:"emails,omitempty"` + Environments *string `json:"environments,omitempty"` + Followers *string `json:"followers,omitempty"` + Gists *string `json:"gists,omitempty"` + GitSigningSSHPublicKeys *string `json:"git_signing_ssh_public_keys,omitempty"` + GPGKeys *string `json:"gpg_keys,omitempty"` + InteractionLimits *string `json:"interaction_limits,omitempty"` + Issues *string `json:"issues,omitempty"` + Keys *string `json:"keys,omitempty"` + Metadata *string `json:"metadata,omitempty"` + Members *string `json:"members,omitempty"` + MergeQueues *string `json:"merge_queues,omitempty"` + OrganizationActionsVariables *string `json:"organization_actions_variables,omitempty"` + OrganizationAdministration *string `json:"organization_administration,omitempty"` + OrganizationAnnouncementBanners *string `json:"organization_announcement_banners,omitempty"` + OrganizationAPIInsights *string `json:"organization_api_insights,omitempty"` + OrganizationCodespaces *string `json:"organization_codespaces,omitempty"` + OrganizationCodespacesSecrets *string `json:"organization_codespaces_secrets,omitempty"` + OrganizationCodespacesSettings *string `json:"organization_codespaces_settings,omitempty"` + OrganizationCopilotSeatManagement *string `json:"organization_copilot_seat_management,omitempty"` + OrganizationCustomProperties *string `json:"organization_custom_properties,omitempty"` + OrganizationCustomRoles *string `json:"organization_custom_roles,omitempty"` + OrganizationCustomOrgRoles *string `json:"organization_custom_org_roles,omitempty"` + OrganizationDependabotSecrets *string `json:"organization_dependabot_secrets,omitempty"` + OrganizationEvents *string `json:"organization_events,omitempty"` + OrganizationHooks *string `json:"organization_hooks,omitempty"` + OrganizationKnowledgeBases *string `json:"organization_knowledge_bases,omitempty"` + OrganizationPackages *string `json:"organization_packages,omitempty"` + OrganizationPersonalAccessTokens *string `json:"organization_personal_access_tokens,omitempty"` + OrganizationPersonalAccessTokenRequests *string `json:"organization_personal_access_token_requests,omitempty"` + OrganizationPlan *string `json:"organization_plan,omitempty"` + OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"` + OrganizationProjects *string `json:"organization_projects,omitempty"` + OrganizationSecrets *string `json:"organization_secrets,omitempty"` + OrganizationSelfHostedRunners *string `json:"organization_self_hosted_runners,omitempty"` + OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"` + Packages *string `json:"packages,omitempty"` + Pages *string `json:"pages,omitempty"` + Plan *string `json:"plan,omitempty"` + Profile *string `json:"profile,omitempty"` + PullRequests *string `json:"pull_requests,omitempty"` + RepositoryAdvisories *string `json:"repository_advisories,omitempty"` + RepositoryCustomProperties *string `json:"repository_custom_properties,omitempty"` + RepositoryHooks *string `json:"repository_hooks,omitempty"` + RepositoryProjects *string `json:"repository_projects,omitempty"` + RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"` + Secrets *string `json:"secrets,omitempty"` + SecretScanningAlerts *string `json:"secret_scanning_alerts,omitempty"` + SecurityEvents *string `json:"security_events,omitempty"` + SingleFile *string `json:"single_file,omitempty"` + Starring *string `json:"starring,omitempty"` + Statuses *string `json:"statuses,omitempty"` + TeamDiscussions *string `json:"team_discussions,omitempty"` + UserEvents *string `json:"user_events,omitempty"` + VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"` + Watching *string `json:"watching,omitempty"` + Workflows *string `json:"workflows,omitempty"` +} + +// InstallationRequest represents a pending GitHub App installation request. +type InstallationRequest struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Account *User `json:"account,omitempty"` + Requester *User `json:"requester,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// Installation represents a GitHub Apps installation. +type Installation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AppID *int64 `json:"app_id,omitempty"` + AppSlug *string `json:"app_slug,omitempty"` + TargetID *int64 `json:"target_id,omitempty"` + Account *User `json:"account,omitempty"` + AccessTokensURL *string `json:"access_tokens_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TargetType *string `json:"target_type,omitempty"` + SingleFileName *string `json:"single_file_name,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Events []string `json:"events,omitempty"` + SingleFilePaths []string `json:"single_file_paths,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HasMultipleSingleFiles *bool `json:"has_multiple_single_files,omitempty"` + SuspendedBy *User `json:"suspended_by,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` +} + +// Attachment represents a GitHub Apps attachment. +type Attachment struct { + ID *int64 `json:"id,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` +} + +// ContentReference represents a reference to a URL in an issue or pull request. +type ContentReference struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Reference *string `json:"reference,omitempty"` +} + +func (i Installation) String() string { + return Stringify(i) +} + +// Get a single GitHub App. Passing the empty string will get +// the authenticated GitHub App. +// +// Note: appSlug is just the URL-friendly name of your GitHub App. +// You can find this on the settings page for your GitHub App +// (e.g., https://github.com/settings/apps/:app_slug). +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-app +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-the-authenticated-app +// +//meta:operation GET /app +//meta:operation GET /apps/{app_slug} +func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { + var u string + if appSlug != "" { + u = fmt.Sprintf("apps/%v", appSlug) + } else { + u = "app" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + app := new(App) + resp, err := s.client.Do(ctx, req, app) + if err != nil { + return nil, resp, err + } + + return app, resp, nil +} + +// ListInstallationRequests lists the pending installation requests that the current GitHub App has. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#list-installation-requests-for-the-authenticated-app +// +//meta:operation GET /app/installation-requests +func (s *AppsService) ListInstallationRequests(ctx context.Context, opts *ListOptions) ([]*InstallationRequest, *Response, error) { + u, err := addOptions("app/installation-requests", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i []*InstallationRequest + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// ListInstallations lists the installations that the current GitHub App has. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#list-installations-for-the-authenticated-app +// +//meta:operation GET /app/installations +func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("app/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i []*Installation + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// GetInstallation returns the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-installation-for-the-authenticated-app +// +//meta:operation GET /app/installations/{installation_id} +func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id)) +} + +// ListUserInstallations lists installations that are accessible to the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-app-installations-accessible-to-the-user-access-token +// +//meta:operation GET /user/installations +func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("user/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i struct { + Installations []*Installation `json:"installations"` + } + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i.Installations, resp, nil +} + +// SuspendInstallation suspends the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#suspend-an-app-installation +// +//meta:operation PUT /app/installations/{installation_id}/suspended +func (s *AppsService) SuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UnsuspendInstallation unsuspends the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#unsuspend-an-app-installation +// +//meta:operation DELETE /app/installations/{installation_id}/suspended +func (s *AppsService) UnsuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteInstallation deletes the specified installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#delete-an-installation-for-the-authenticated-app +// +//meta:operation DELETE /app/installations/{installation_id} +func (s *AppsService) DeleteInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateInstallationToken creates a new installation token. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-an-installation-access-token-for-an-app +// +//meta:operation POST /app/installations/{installation_id}/access_tokens +func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("app/installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// CreateInstallationTokenListRepos creates a new installation token with a list of all repositories in an installation which is not possible with CreateInstallationToken. +// +// It differs from CreateInstallationToken by taking InstallationTokenListRepoOptions as a parameter which does not omit RepositoryIDs if that field is nil or an empty array. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-an-installation-access-token-for-an-app +// +//meta:operation POST /app/installations/{installation_id}/access_tokens +func (s *AppsService) CreateInstallationTokenListRepos(ctx context.Context, id int64, opts *InstallationTokenListRepoOptions) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("app/installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// CreateAttachment creates a new attachment on user comment containing a url. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.3/rest/reference/apps#create-a-content-attachment +// +//meta:operation POST /repos/{owner}/{repo}/content_references/{content_reference_id}/attachments +func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) { + u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID) + payload := &Attachment{Title: Ptr(title), Body: Ptr(body)} + req, err := s.client.NewRequest("POST", u, payload) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeContentAttachmentsPreview) + + m := &Attachment{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// FindOrganizationInstallation finds the organization's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-an-organization-installation-for-the-authenticated-app +// +//meta:operation GET /orgs/{org}/installation +func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org)) +} + +// FindRepositoryInstallation finds the repository's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-a-repository-installation-for-the-authenticated-app +// +//meta:operation GET /repos/{owner}/{repo}/installation +func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo)) +} + +// FindRepositoryInstallationByID finds the repository's installation information. +// +// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint "GET /repositories/{repository_id}/installation". +// +//meta:operation GET /repositories/{repository_id}/installation +func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id)) +} + +// FindUserInstallation finds the user's installation information. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#get-a-user-installation-for-the-authenticated-app +// +//meta:operation GET /users/{username}/installation +func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user)) +} + +func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + i := new(Installation) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks.go b/vendor/github.com/google/go-github/v68/github/apps_hooks.go new file mode 100644 index 00000000..6046827e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_hooks.go @@ -0,0 +1,52 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetHookConfig returns the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#get-a-webhook-configuration-for-an-app +// +//meta:operation GET /app/hook/config +func (s *AppsService) GetHookConfig(ctx context.Context) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("GET", "app/hook/config", nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, &config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// UpdateHookConfig updates the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#update-a-webhook-configuration-for-an-app +// +//meta:operation PATCH /app/hook/config +func (s *AppsService) UpdateHookConfig(ctx context.Context, config *HookConfig) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("PATCH", "app/hook/config", config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go new file mode 100644 index 00000000..59800a0a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go @@ -0,0 +1,78 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists deliveries of an App webhook. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#list-deliveries-for-an-app-webhook +// +//meta:operation GET /app/hook/deliveries +func (s *AppsService) ListHookDeliveries(ctx context.Context, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u, err := addOptions("app/hook/deliveries", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns the App webhook delivery with the specified ID. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#get-a-delivery-for-an-app-webhook +// +//meta:operation GET /app/hook/deliveries/{delivery_id} +func (s *AppsService) GetHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v", deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for an App webhook. +// +// GitHub API docs: https://docs.github.com/rest/apps/webhooks#redeliver-a-delivery-for-an-app-webhook +// +//meta:operation POST /app/hook/deliveries/{delivery_id}/attempts +func (s *AppsService) RedeliverHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v/attempts", deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_installation.go b/vendor/github.com/google/go-github/v68/github/apps_installation.go new file mode 100644 index 00000000..d430511d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_installation.go @@ -0,0 +1,138 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ListRepositories represents the response from the list repos endpoints. +type ListRepositories struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories"` +} + +// ListRepos lists the repositories that are accessible to the authenticated installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-repositories-accessible-to-the-app-installation +// +//meta:operation GET /installation/repositories +func (s *AppsService) ListRepos(ctx context.Context, opts *ListOptions) (*ListRepositories, *Response, error) { + u, err := addOptions("installation/repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListUserRepos lists repositories that are accessible +// to the authenticated user for an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#list-repositories-accessible-to-the-user-access-token +// +//meta:operation GET /user/installations/{installation_id}/repositories +func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddRepository adds a single repository to an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#add-a-repository-to-an-app-installation +// +//meta:operation PUT /user/installations/{installation_id}/repositories/{repository_id} +func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveRepository removes a single repository from an installation. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#remove-a-repository-from-an-app-installation +// +//meta:operation DELETE /user/installations/{installation_id}/repositories/{repository_id} +func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RevokeInstallationToken revokes an installation token. +// +// GitHub API docs: https://docs.github.com/rest/apps/installations#revoke-an-installation-access-token +// +//meta:operation DELETE /installation/token +func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) { + u := "installation/token" + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_manifest.go b/vendor/github.com/google/go-github/v68/github/apps_manifest.go new file mode 100644 index 00000000..5b6ff9af --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_manifest.go @@ -0,0 +1,51 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AppConfig describes the configuration of a GitHub App. +type AppConfig struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + WebhookSecret *string `json:"webhook_secret,omitempty"` + PEM *string `json:"pem,omitempty"` +} + +// CompleteAppManifest completes the App manifest handshake flow for the given +// code. +// +// GitHub API docs: https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest +// +//meta:operation POST /app-manifests/{code}/conversions +func (s *AppsService) CompleteAppManifest(ctx context.Context, code string) (*AppConfig, *Response, error) { + u := fmt.Sprintf("app-manifests/%s/conversions", code) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + cfg := new(AppConfig) + resp, err := s.client.Do(ctx, req, cfg) + if err != nil { + return nil, resp, err + } + + return cfg, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/apps_marketplace.go b/vendor/github.com/google/go-github/v68/github/apps_marketplace.go new file mode 100644 index 00000000..976775a7 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/apps_marketplace.go @@ -0,0 +1,207 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// MarketplaceService handles communication with the marketplace related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/apps#marketplace +type MarketplaceService struct { + client *Client + // Stubbed controls whether endpoints that return stubbed data are used + // instead of production endpoints. Stubbed data is fake data that's useful + // for testing your GitHub Apps. Stubbed data is hard-coded and will not + // change based on actual subscriptions. + // + // GitHub API docs: https://docs.github.com/rest/apps#testing-with-stubbed-endpoints + Stubbed bool +} + +// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. +type MarketplacePlan struct { + URL *string `json:"url,omitempty"` + AccountsURL *string `json:"accounts_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` + YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` + // The pricing model for this listing. Can be one of "flat-rate", "per-unit", or "free". + PriceModel *string `json:"price_model,omitempty"` + UnitName *string `json:"unit_name,omitempty"` + Bullets *[]string `json:"bullets,omitempty"` + // State can be one of the values "draft" or "published". + State *string `json:"state,omitempty"` + HasFreeTrial *bool `json:"has_free_trial,omitempty"` +} + +// MarketplacePurchase represents a GitHub Apps Marketplace Purchase. +type MarketplacePurchase struct { + Account *MarketplacePurchaseAccount `json:"account,omitempty"` + // BillingCycle can be one of the values "yearly", "monthly" or nil. + BillingCycle *string `json:"billing_cycle,omitempty"` + NextBillingDate *Timestamp `json:"next_billing_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` + OnFreeTrial *bool `json:"on_free_trial,omitempty"` + FreeTrialEndsOn *Timestamp `json:"free_trial_ends_on,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan. +type MarketplacePendingChange struct { + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + ID *int64 `json:"id,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` +} + +// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. +type MarketplacePlanAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"` +} + +// MarketplacePurchaseAccount represents a GitHub Account (user or organization) for a Purchase. +type MarketplacePurchaseAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + Email *string `json:"email,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// ListPlans lists all plans for your Marketplace listing. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-plans +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-plans-stubbed +// +//meta:operation GET /marketplace_listing/plans +//meta:operation GET /marketplace_listing/stubbed/plans +func (s *MarketplaceService) ListPlans(ctx context.Context, opts *ListOptions) ([]*MarketplacePlan, *Response, error) { + uri := s.marketplaceURI("plans") + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var plans []*MarketplacePlan + resp, err := s.client.Do(ctx, req, &plans) + if err != nil { + return nil, resp, err + } + + return plans, resp, nil +} + +// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-accounts-for-a-plan +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-accounts-for-a-plan-stubbed +// +//meta:operation GET /marketplace_listing/plans/{plan_id}/accounts +//meta:operation GET /marketplace_listing/stubbed/plans/{plan_id}/accounts +func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var accounts []*MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &accounts) + if err != nil { + return nil, resp, err + } + + return accounts, resp, nil +} + +// GetPlanAccountForAccount get GitHub account (user or organization) associated with an account. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#get-a-subscription-plan-for-an-account +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#get-a-subscription-plan-for-an-account-stubbed +// +//meta:operation GET /marketplace_listing/accounts/{account_id} +//meta:operation GET /marketplace_listing/stubbed/accounts/{account_id} +func (s *MarketplaceService) GetPlanAccountForAccount(ctx context.Context, accountID int64) (*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) + + req, err := s.client.NewRequest("GET", uri, nil) + if err != nil { + return nil, nil, err + } + + var account *MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &account) + if err != nil { + return nil, resp, err + } + + return account, resp, nil +} + +// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. +// +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user-stubbed +// +//meta:operation GET /user/marketplace_purchases +//meta:operation GET /user/marketplace_purchases/stubbed +func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) { + uri := "user/marketplace_purchases" + if s.Stubbed { + uri = "user/marketplace_purchases/stubbed" + } + + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var purchases []*MarketplacePurchase + resp, err := s.client.Do(ctx, req, &purchases) + if err != nil { + return nil, resp, err + } + return purchases, resp, nil +} + +func (s *MarketplaceService) marketplaceURI(endpoint string) string { + url := "marketplace_listing" + if s.Stubbed { + url = "marketplace_listing/stubbed" + } + return url + "/" + endpoint +} diff --git a/vendor/github.com/google/go-github/v68/github/attestations.go b/vendor/github.com/google/go-github/v68/github/attestations.go new file mode 100644 index 00000000..618d5d73 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/attestations.go @@ -0,0 +1,27 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" +) + +// Attestation represents an artifact attestation associated with a repository. +// The provided bundle can be used to verify the provenance of artifacts. +// +// https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds +type Attestation struct { + // The attestation's Sigstore Bundle. + // Refer to the sigstore bundle specification for more info: + // https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto + Bundle json.RawMessage `json:"bundle"` + RepositoryID int64 `json:"repository_id"` +} + +// AttestationsResponse represents a collection of artifact attestations. +type AttestationsResponse struct { + Attestations []*Attestation `json:"attestations"` +} diff --git a/vendor/github.com/google/go-github/github/authorizations.go b/vendor/github.com/google/go-github/v68/github/authorizations.go similarity index 53% rename from vendor/github.com/google/go-github/github/authorizations.go rename to vendor/github.com/google/go-github/v68/github/authorizations.go index 190205b0..8b8a67d5 100644 --- a/vendor/github.com/google/go-github/github/authorizations.go +++ b/vendor/github.com/google/go-github/v68/github/authorizations.go @@ -12,10 +12,10 @@ import ( // Scope models a GitHub authorization scope. // -// GitHub API docs: https://developer.github.com/v3/oauth/#scopes +// GitHub API docs: https://docs.github.com/rest/oauth/#scopes type Scope string -// This is the set of scopes for GitHub API V3 +// This is the set of scopes for GitHub API V3. const ( ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact? ScopeUser Scope = "user" @@ -41,6 +41,7 @@ const ( ScopeReadGPGKey Scope = "read:gpg_key" ScopeWriteGPGKey Scope = "write:gpg_key" ScopeAdminGPGKey Scope = "admin:gpg_key" + ScopeSecurityEvents Scope = "security_events" ) // AuthorizationsService handles communication with the authorization related @@ -49,7 +50,7 @@ const ( // This service requires HTTP Basic Authentication; it cannot be accessed using // an OAuth token. // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/ +// GitHub API docs: https://docs.github.com/rest/oauth-authorizations type AuthorizationsService service // Authorization represents an individual GitHub authorization. @@ -120,7 +121,7 @@ func (a AuthorizationRequest) String() string { // fields. That is, you may provide only one of "Scopes", or "AddScopes", or // "RemoveScopes". // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization +// GitHub API docs: https://docs.github.com/rest/oauth-authorizations#update-an-existing-authorization type AuthorizationUpdateRequest struct { Scopes []string `json:"scopes,omitempty"` AddScopes []string `json:"add_scopes,omitempty"` @@ -134,137 +135,6 @@ func (a AuthorizationUpdateRequest) String() string { return Stringify(a) } -// List the authorizations for the authenticated user. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations -func (s *AuthorizationsService) List(ctx context.Context, opt *ListOptions) ([]*Authorization, *Response, error) { - u := "authorizations" - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var auths []*Authorization - resp, err := s.client.Do(ctx, req, &auths) - if err != nil { - return nil, resp, err - } - return auths, resp, nil -} - -// Get a single authorization. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization -func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) { - u := fmt.Sprintf("authorizations/%d", id) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - a := new(Authorization) - resp, err := s.client.Do(ctx, req, a) - if err != nil { - return nil, resp, err - } - return a, resp, nil -} - -// Create a new authorization for the specified OAuth application. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization -func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) { - u := "authorizations" - - req, err := s.client.NewRequest("POST", u, auth) - if err != nil { - return nil, nil, err - } - - a := new(Authorization) - resp, err := s.client.Do(ctx, req, a) - if err != nil { - return nil, resp, err - } - return a, resp, nil -} - -// GetOrCreateForApp creates a new authorization for the specified OAuth -// application, only if an authorization for that application doesn’t already -// exist for the user. -// -// If a new token is created, the HTTP status code will be "201 Created", and -// the returned Authorization.Token field will be populated. If an existing -// token is returned, the status code will be "200 OK" and the -// Authorization.Token field will be empty. -// -// clientID is the OAuth Client ID with which to create the token. -// -// GitHub API docs: -// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app -// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint -func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) { - var u string - if auth.Fingerprint == nil || *auth.Fingerprint == "" { - u = fmt.Sprintf("authorizations/clients/%v", clientID) - } else { - u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint) - } - - req, err := s.client.NewRequest("PUT", u, auth) - if err != nil { - return nil, nil, err - } - - a := new(Authorization) - resp, err := s.client.Do(ctx, req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil -} - -// Edit a single authorization. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization -func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) { - u := fmt.Sprintf("authorizations/%d", id) - - req, err := s.client.NewRequest("PATCH", u, auth) - if err != nil { - return nil, nil, err - } - - a := new(Authorization) - resp, err := s.client.Do(ctx, req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil -} - -// Delete a single authorization. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization -func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) { - u := fmt.Sprintf("authorizations/%d", id) - - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - // Check if an OAuth token is valid for a specific app. // // Note that this operation requires the use of BasicAuth, but where the @@ -273,14 +143,21 @@ func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response // // The returned Authorization.User field will be populated. // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization -func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { - u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#check-a-token +// +//meta:operation POST /applications/{client_id}/token +func (s *AuthorizationsService) Check(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) - req, err := s.client.NewRequest("GET", u, nil) + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("POST", u, reqBody) if err != nil { return nil, nil, err } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) a := new(Authorization) resp, err := s.client.Do(ctx, req, a) @@ -301,14 +178,21 @@ func (s *AuthorizationsService) Check(ctx context.Context, clientID string, toke // // The returned Authorization.User field will be populated. // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization -func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { - u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#reset-a-token +// +//meta:operation PATCH /applications/{client_id}/token +func (s *AuthorizationsService) Reset(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) - req, err := s.client.NewRequest("POST", u, nil) + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("PATCH", u, reqBody) if err != nil { return nil, nil, err } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) a := new(Authorization) resp, err := s.client.Do(ctx, req, a) @@ -325,74 +209,44 @@ func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, toke // username is the OAuth application clientID, and the password is its // clientSecret. Invalid tokens will return a 404 Not Found. // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application -func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) { - u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) - - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} - -// ListGrants lists the set of OAuth applications that have been granted -// access to a user's account. This will return one entry for each application -// that has been granted access to the account, regardless of the number of -// tokens an application has generated for the user. +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#delete-an-app-token // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants -func (s *AuthorizationsService) ListGrants(ctx context.Context, opt *ListOptions) ([]*Grant, *Response, error) { - u, err := addOptions("applications/grants", opt) - if err != nil { - return nil, nil, err - } +//meta:operation DELETE /applications/{client_id}/token +func (s *AuthorizationsService) Revoke(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} - grants := []*Grant{} - resp, err := s.client.Do(ctx, req, &grants) + req, err := s.client.NewRequest("DELETE", u, reqBody) if err != nil { - return nil, resp, err - } - - return grants, resp, nil -} - -// GetGrant gets a single OAuth application grant. -// -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant -func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) { - u := fmt.Sprintf("applications/grants/%d", id) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - grant := new(Grant) - resp, err := s.client.Do(ctx, req, grant) - if err != nil { - return nil, resp, err + return nil, err } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) - return grant, resp, nil + return s.client.Do(ctx, req, nil) } // DeleteGrant deletes an OAuth application grant. Deleting an application's // grant will also delete all OAuth tokens associated with the application for // the user. // -// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant -func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) { - u := fmt.Sprintf("applications/grants/%d", id) - req, err := s.client.NewRequest("DELETE", u, nil) +// GitHub API docs: https://docs.github.com/rest/apps/oauth-applications#delete-an-app-authorization +// +//meta:operation DELETE /applications/{client_id}/grant +func (s *AuthorizationsService) DeleteGrant(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/grant", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("DELETE", u, reqBody) if err != nil { return nil, err } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) return s.client.Do(ctx, req, nil) } @@ -403,7 +257,9 @@ func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Res // you can e.g. create or delete a user's public SSH key. NOTE: creating a // new token automatically revokes an existing one. // -// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#create-an-impersonation-oauth-token +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#create-an-impersonation-oauth-token +// +//meta:operation POST /admin/users/{username}/authorizations func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) { u := fmt.Sprintf("admin/users/%v/authorizations", username) req, err := s.client.NewRequest("POST", u, authReq) @@ -423,7 +279,9 @@ func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, usernam // // NOTE: there can be only one at a time. // -// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#delete-an-impersonation-oauth-token +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#delete-an-impersonation-oauth-token +// +//meta:operation DELETE /admin/users/{username}/authorizations func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) { u := fmt.Sprintf("admin/users/%v/authorizations", username) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/v68/github/billing.go b/vendor/github.com/google/go-github/v68/github/billing.go new file mode 100644 index 00000000..09b1a5d0 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/billing.go @@ -0,0 +1,218 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// BillingService provides access to the billing related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/billing +type BillingService service + +// ActionBilling represents a GitHub Action billing. +type ActionBilling struct { + TotalMinutesUsed float64 `json:"total_minutes_used"` + TotalPaidMinutesUsed float64 `json:"total_paid_minutes_used"` + IncludedMinutes float64 `json:"included_minutes"` + MinutesUsedBreakdown MinutesUsedBreakdown `json:"minutes_used_breakdown"` +} + +// MinutesUsedBreakdown counts the actions minutes used by machine type (e.g. UBUNTU, WINDOWS, MACOS). +type MinutesUsedBreakdown = map[string]int + +// PackageBilling represents a GitHub Package billing. +type PackageBilling struct { + TotalGigabytesBandwidthUsed int `json:"total_gigabytes_bandwidth_used"` + TotalPaidGigabytesBandwidthUsed int `json:"total_paid_gigabytes_bandwidth_used"` + IncludedGigabytesBandwidth float64 `json:"included_gigabytes_bandwidth"` +} + +// StorageBilling represents a GitHub Storage billing. +type StorageBilling struct { + DaysLeftInBillingCycle int `json:"days_left_in_billing_cycle"` + EstimatedPaidStorageForMonth float64 `json:"estimated_paid_storage_for_month"` + EstimatedStorageForMonth float64 `json:"estimated_storage_for_month"` +} + +// ActiveCommitters represents the total active committers across all repositories in an Organization. +type ActiveCommitters struct { + TotalAdvancedSecurityCommitters int `json:"total_advanced_security_committers"` + TotalCount int `json:"total_count"` + MaximumAdvancedSecurityCommitters int `json:"maximum_advanced_security_committers"` + PurchasedAdvancedSecurityCommitters int `json:"purchased_advanced_security_committers"` + Repositories []*RepositoryActiveCommitters `json:"repositories,omitempty"` +} + +// RepositoryActiveCommitters represents active committers on each repository. +type RepositoryActiveCommitters struct { + Name *string `json:"name,omitempty"` + AdvancedSecurityCommitters *int `json:"advanced_security_committers,omitempty"` + AdvancedSecurityCommittersBreakdown []*AdvancedSecurityCommittersBreakdown `json:"advanced_security_committers_breakdown,omitempty"` +} + +// AdvancedSecurityCommittersBreakdown represents the user activity breakdown for ActiveCommitters. +type AdvancedSecurityCommittersBreakdown struct { + UserLogin *string `json:"user_login,omitempty"` + LastPushedDate *string `json:"last_pushed_date,omitempty"` +} + +// GetActionsBillingOrg returns the summary of the free and paid GitHub Actions minutes used for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-actions-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/actions +func (s *BillingService) GetActionsBillingOrg(ctx context.Context, org string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/actions", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsOrgBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsOrgBilling) + if err != nil { + return nil, resp, err + } + + return actionsOrgBilling, resp, nil +} + +// GetPackagesBillingOrg returns the free and paid storage used for GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-packages-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/packages +func (s *BillingService) GetPackagesBillingOrg(ctx context.Context, org string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/packages", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesOrgBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesOrgBilling) + if err != nil { + return nil, resp, err + } + + return packagesOrgBilling, resp, nil +} + +// GetStorageBillingOrg returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-shared-storage-billing-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/shared-storage +func (s *BillingService) GetStorageBillingOrg(ctx context.Context, org string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/shared-storage", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageOrgBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageOrgBilling) + if err != nil { + return nil, resp, err + } + + return storageOrgBilling, resp, nil +} + +// GetAdvancedSecurityActiveCommittersOrg returns the GitHub Advanced Security active committers for an organization per repository. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/billing/billing#get-github-advanced-security-active-committers-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/billing/advanced-security +func (s *BillingService) GetAdvancedSecurityActiveCommittersOrg(ctx context.Context, org string, opts *ListOptions) (*ActiveCommitters, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/advanced-security", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + activeOrgCommitters := new(ActiveCommitters) + resp, err := s.client.Do(ctx, req, activeOrgCommitters) + if err != nil { + return nil, resp, err + } + + return activeOrgCommitters, resp, nil +} + +// GetActionsBillingUser returns the summary of the free and paid GitHub Actions minutes used for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-actions-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/actions +func (s *BillingService) GetActionsBillingUser(ctx context.Context, user string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/actions", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsUserBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsUserBilling) + if err != nil { + return nil, resp, err + } + + return actionsUserBilling, resp, nil +} + +// GetPackagesBillingUser returns the free and paid storage used for GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-packages-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/packages +func (s *BillingService) GetPackagesBillingUser(ctx context.Context, user string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/packages", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesUserBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesUserBilling) + if err != nil { + return nil, resp, err + } + + return packagesUserBilling, resp, nil +} + +// GetStorageBillingUser returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/rest/billing/billing#get-shared-storage-billing-for-a-user +// +//meta:operation GET /users/{username}/settings/billing/shared-storage +func (s *BillingService) GetStorageBillingUser(ctx context.Context, user string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/shared-storage", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageUserBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageUserBilling) + if err != nil { + return nil, resp, err + } + + return storageUserBilling, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/checks.go b/vendor/github.com/google/go-github/v68/github/checks.go similarity index 56% rename from vendor/github.com/google/go-github/github/checks.go rename to vendor/github.com/google/go-github/v68/github/checks.go index 35490899..711be207 100644 --- a/vendor/github.com/google/go-github/github/checks.go +++ b/vendor/github.com/google/go-github/v68/github/checks.go @@ -13,16 +13,18 @@ import ( // ChecksService provides access to the Checks API in the // GitHub API. // -// GitHub API docs: https://developer.github.com/v3/checks/ +// GitHub API docs: https://docs.github.com/rest/checks/ type ChecksService service // CheckRun represents a GitHub check run on a repository associated with a GitHub app. type CheckRun struct { ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` HeadSHA *string `json:"head_sha,omitempty"` ExternalID *string `json:"external_id,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` + DetailsURL *string `json:"details_url,omitempty"` Status *string `json:"status,omitempty"` Conclusion *string `json:"conclusion,omitempty"` StartedAt *Timestamp `json:"started_at,omitempty"` @@ -47,14 +49,15 @@ type CheckRunOutput struct { // CheckRunAnnotation represents an annotation object for a CheckRun output. type CheckRunAnnotation struct { - FileName *string `json:"filename,omitempty"` - BlobHRef *string `json:"blob_href,omitempty"` - StartLine *int `json:"start_line,omitempty"` - EndLine *int `json:"end_line,omitempty"` - WarningLevel *string `json:"warning_level,omitempty"` - Message *string `json:"message,omitempty"` - Title *string `json:"title,omitempty"` - RawDetails *string `json:"raw_details,omitempty"` + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + AnnotationLevel *string `json:"annotation_level,omitempty"` + Message *string `json:"message,omitempty"` + Title *string `json:"title,omitempty"` + RawDetails *string `json:"raw_details,omitempty"` } // CheckRunImage represents an image object for a CheckRun output. @@ -67,6 +70,7 @@ type CheckRunImage struct { // CheckSuite represents a suite of check runs. type CheckSuite struct { ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` HeadBranch *string `json:"head_branch,omitempty"` HeadSHA *string `json:"head_sha,omitempty"` URL *string `json:"url,omitempty"` @@ -74,9 +78,17 @@ type CheckSuite struct { AfterSHA *string `json:"after,omitempty"` Status *string `json:"status,omitempty"` Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` App *App `json:"app,omitempty"` Repository *Repository `json:"repository,omitempty"` PullRequests []*PullRequest `json:"pull_requests,omitempty"` + + // The following fields are only populated by Webhook events. + HeadCommit *Commit `json:"head_commit,omitempty"` + LatestCheckRunsCount *int64 `json:"latest_check_runs_count,omitempty"` + Rerequstable *bool `json:"rerequestable,omitempty"` + RunsRerequstable *bool `json:"runs_rerequestable,omitempty"` } func (c CheckRun) String() string { @@ -89,7 +101,9 @@ func (c CheckSuite) String() string { // GetCheckRun gets a check-run for a repository. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-single-check-run +// GitHub API docs: https://docs.github.com/rest/checks/runs#get-a-check-run +// +//meta:operation GET /repos/{owner}/{repo}/check-runs/{check_run_id} func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) req, err := s.client.NewRequest("GET", u, nil) @@ -110,7 +124,9 @@ func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, che // GetCheckSuite gets a single check suite. // -// GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-single-check-suite +// GitHub API docs: https://docs.github.com/rest/checks/suites#get-a-check-suite +// +//meta:operation GET /repos/{owner}/{repo}/check-suites/{check_suite_id} func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID) req, err := s.client.NewRequest("GET", u, nil) @@ -131,24 +147,33 @@ func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, c // CreateCheckRunOptions sets up parameters needed to create a CheckRun. type CreateCheckRunOptions struct { - Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) - HeadBranch string `json:"head_branch"` // The name of the branch to perform a check against. (Required.) - HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) - DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) - ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) - Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) - Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) - StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) - CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) - Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) +} + +// CheckRunAction exposes further actions the integrator can perform, which a user may trigger. +type CheckRunAction struct { + Label string `json:"label"` // The text to be displayed on a button in the web UI. The maximum size is 20 characters. (Required.) + Description string `json:"description"` // A short explanation of what this action would do. The maximum size is 40 characters. (Required.) + Identifier string `json:"identifier"` // A reference for the action on the integrator's system. The maximum size is 20 characters. (Required.) } // CreateCheckRun creates a check run for repository. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run -func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opt CreateCheckRunOptions) (*CheckRun, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/runs#create-a-check-run +// +//meta:operation POST /repos/{owner}/{repo}/check-runs +func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opts CreateCheckRunOptions) (*CheckRun, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo) - req, err := s.client.NewRequest("POST", u, opt) + req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err } @@ -166,23 +191,24 @@ func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, // UpdateCheckRunOptions sets up parameters needed to update a CheckRun. type UpdateCheckRunOptions struct { - Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) - HeadBranch *string `json:"head_branch,omitempty"` // The name of the branch to perform a check against. (Optional.) - HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.) - DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) - ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) - Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) - Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) - CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) - Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) } // UpdateCheckRun updates a check run for a specific commit in a repository. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run -func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opt UpdateCheckRunOptions) (*CheckRun, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/runs#update-a-check-run +// +//meta:operation PATCH /repos/{owner}/{repo}/check-runs/{check_run_id} +func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opts UpdateCheckRunOptions) (*CheckRun, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) - req, err := s.client.NewRequest("PATCH", u, opt) + req, err := s.client.NewRequest("PATCH", u, opts) if err != nil { return nil, nil, err } @@ -200,10 +226,12 @@ func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, // ListCheckRunAnnotations lists the annotations for a check run. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run -func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opt *ListOptions) ([]*CheckRunAnnotation, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-run-annotations +// +//meta:operation GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations +func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -229,6 +257,7 @@ type ListCheckRunsOptions struct { CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name. Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed". Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest" + AppID *int64 `url:"app_id,omitempty"` // Filters check runs by GitHub App ID. ListOptions } @@ -241,10 +270,12 @@ type ListCheckRunsResults struct { // ListCheckRunsForRef lists check runs for a specific ref. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref -func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, ref) - u, err := addOptions(u, opt) +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-runs-for-a-git-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/check-runs +func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -267,10 +298,12 @@ func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, re // ListCheckRunsCheckSuite lists check runs for a check suite. // -// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite -func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opt *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/runs#list-check-runs-in-a-check-suite +// +//meta:operation GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs +func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -291,6 +324,24 @@ func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo return checkRunResults, resp, nil } +// ReRequestCheckRun triggers GitHub to rerequest an existing check run. +// +// GitHub API docs: https://docs.github.com/rest/checks/runs#rerequest-a-check-run +// +//meta:operation POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest +func (s *ChecksService) ReRequestCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v/rerequest", owner, repo, checkRunID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + return s.client.Do(ctx, req, nil) +} + // ListCheckSuiteOptions represents parameters to list check suites. type ListCheckSuiteOptions struct { CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run. @@ -307,10 +358,12 @@ type ListCheckSuiteResults struct { // ListCheckSuitesForRef lists check suite for a specific ref. // -// GitHub API docs: https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-specific-ref -func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opt *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, ref) - u, err := addOptions(u, opt) +// GitHub API docs: https://docs.github.com/rest/checks/suites#list-check-suites-for-a-git-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/check-suites +func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -339,7 +392,7 @@ type AutoTriggerCheck struct { // CheckSuitePreferenceOptions set options for check suite preferences for a repository. type CheckSuitePreferenceOptions struct { - PreferenceList *PreferenceList `json:"auto_trigger_checks,omitempty"` // A list of auto trigger checks that can be set for a check suite in a repository. + AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. } // CheckSuitePreferenceResults represents the results of the preference set operation. @@ -348,17 +401,19 @@ type CheckSuitePreferenceResults struct { Repository *Repository `json:"repository,omitempty"` } -// PreferenceList represents a list of auto trigger checks for repository +// PreferenceList represents a list of auto trigger checks for repository. type PreferenceList struct { AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. } // SetCheckSuitePreferences changes the default automatic flow when creating check suites. // -// GitHub API docs: https://developer.github.com/v3/checks/suites/#set-preferences-for-check-suites-on-a-repository -func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opt CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/suites#update-repository-preferences-for-check-suites +// +//meta:operation PATCH /repos/{owner}/{repo}/check-suites/preferences +func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) - req, err := s.client.NewRequest("PATCH", u, opt) + req, err := s.client.NewRequest("PATCH", u, opts) if err != nil { return nil, nil, err } @@ -374,7 +429,7 @@ func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, rep return checkSuitePrefResults, resp, nil } -// CreateCheckSuiteOptions sets up parameters to manually create a check suites +// CreateCheckSuiteOptions sets up parameters to manually create a check suites. type CreateCheckSuiteOptions struct { HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.) HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented. @@ -382,10 +437,12 @@ type CreateCheckSuiteOptions struct { // CreateCheckSuite manually creates a check suite for a repository. // -// GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite -func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opt CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/checks/suites#create-a-check-suite +// +//meta:operation POST /repos/{owner}/{repo}/check-suites +func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opts CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo) - req, err := s.client.NewRequest("POST", u, opt) + req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err } @@ -401,20 +458,13 @@ func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string return checkSuite, resp, nil } -// RequestCheckSuiteOptions sets up the parameters for a request check suite endpoint. -type RequestCheckSuiteOptions struct { - HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.) -} - -// RequestCheckSuite triggers GitHub to create a new check suite, without pushing new code to a repository. +// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository. // -// GitHub API docs: https://developer.github.com/v3/checks/suites/#request-check-suites -func (s *ChecksService) RequestCheckSuite(ctx context.Context, owner, repo string, opt RequestCheckSuiteOptions) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/check-suite-requests", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, err - } +// GitHub API docs: https://docs.github.com/rest/checks/suites#rerequest-a-check-suite +// +//meta:operation POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest +func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID) req, err := s.client.NewRequest("POST", u, nil) if err != nil { diff --git a/vendor/github.com/google/go-github/v68/github/code_scanning.go b/vendor/github.com/google/go-github/v68/github/code_scanning.go new file mode 100644 index 00000000..a8fca98a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/code_scanning.go @@ -0,0 +1,664 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" +) + +// CodeScanningService handles communication with the code scanning related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeScanningService service + +// Rule represents the complete details of GitHub Code Scanning alert type. +type Rule struct { + ID *string `json:"id,omitempty"` + Severity *string `json:"severity,omitempty"` + Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + SecuritySeverityLevel *string `json:"security_severity_level,omitempty"` + FullDescription *string `json:"full_description,omitempty"` + Tags []string `json:"tags,omitempty"` + Help *string `json:"help,omitempty"` +} + +// Location represents the exact location of the GitHub Code Scanning Alert in the scanned project. +type Location struct { + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` +} + +// Message is a part of MostRecentInstance struct which provides the appropriate message when any action is performed on the analysis object. +type Message struct { + Text *string `json:"text,omitempty"` +} + +// MostRecentInstance provides details of the most recent instance of this alert for the default branch or for the specified Git reference. +type MostRecentInstance struct { + Ref *string `json:"ref,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Category *string `json:"category,omitempty"` + Environment *string `json:"environment,omitempty"` + State *string `json:"state,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + Message *Message `json:"message,omitempty"` + Location *Location `json:"location,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Classifications []string `json:"classifications,omitempty"` +} + +// Tool represents the tool used to generate a GitHub Code Scanning Alert. +type Tool struct { + Name *string `json:"name,omitempty"` + GUID *string `json:"guid,omitempty"` + Version *string `json:"version,omitempty"` +} + +// Alert represents an individual GitHub Code Scanning Alert on a single repository. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type Alert struct { + Number *int `json:"number,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RuleID *string `json:"rule_id,omitempty"` + RuleSeverity *string `json:"rule_severity,omitempty"` + RuleDescription *string `json:"rule_description,omitempty"` + Rule *Rule `json:"rule,omitempty"` + Tool *Tool `json:"tool,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + FixedAt *Timestamp `json:"fixed_at,omitempty"` + State *string `json:"state,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MostRecentInstance *MostRecentInstance `json:"most_recent_instance,omitempty"` + Instances []*MostRecentInstance `json:"instances,omitempty"` + DismissedBy *User `json:"dismissed_by,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` + DismissedReason *string `json:"dismissed_reason,omitempty"` + DismissedComment *string `json:"dismissed_comment,omitempty"` + InstancesURL *string `json:"instances_url,omitempty"` +} + +// ID returns the ID associated with an alert. It is the number at the end of the security alert's URL. +func (a *Alert) ID() int64 { + if a == nil { + return 0 + } + + s := a.GetHTMLURL() + + // Check for an ID to parse at the end of the url + if i := strings.LastIndex(s, "/"); i >= 0 { + s = s[i+1:] + } + + // Return the alert ID as a 64-bit integer. Unable to convert or out of range returns 0. + id, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0 + } + + return id +} + +// AlertInstancesListOptions specifies optional parameters to the CodeScanningService.ListAlertInstances method. +type AlertInstancesListOptions struct { + // Return code scanning alert instances for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref string `url:"ref,omitempty"` + + ListOptions +} + +// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts method. +type AlertListOptions struct { + // State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open + State string `url:"state,omitempty"` + + // Return code scanning alerts for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref string `url:"ref,omitempty"` + + // If specified, only code scanning alerts with this severity will be returned. Possible values are: critical, high, medium, low, warning, note, error. + Severity string `url:"severity,omitempty"` + + // The name of a code scanning tool. Only results by this tool will be listed. + ToolName string `url:"tool_name,omitempty"` + + ListCursorOptions + + // Add ListOptions so offset pagination with integer type "page" query parameter is accepted + // since ListCursorOptions accepts "page" as string only. + ListOptions +} + +// AnalysesListOptions specifies optional parameters to the CodeScanningService.ListAnalysesForRepo method. +type AnalysesListOptions struct { + // Return code scanning analyses belonging to the same SARIF upload. + SarifID *string `url:"sarif_id,omitempty"` + + // Return code scanning analyses for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref *string `url:"ref,omitempty"` + + ListOptions +} + +// CodeQLDatabase represents a metadata about the CodeQL database. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeQLDatabase struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Language *string `json:"language,omitempty"` + Uploader *User `json:"uploader,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +// ScanningAnalysis represents an individual GitHub Code Scanning ScanningAnalysis on a single repository. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type ScanningAnalysis struct { + ID *int64 `json:"id,omitempty"` + Ref *string `json:"ref,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Environment *string `json:"environment,omitempty"` + Error *string `json:"error,omitempty"` + Category *string `json:"category,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ResultsCount *int `json:"results_count,omitempty"` + RulesCount *int `json:"rules_count,omitempty"` + URL *string `json:"url,omitempty"` + SarifID *string `json:"sarif_id,omitempty"` + Tool *Tool `json:"tool,omitempty"` + Deletable *bool `json:"deletable,omitempty"` + Warning *string `json:"warning,omitempty"` +} + +// SarifAnalysis specifies the results of a code scanning job. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type SarifAnalysis struct { + CommitSHA *string `json:"commit_sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Sarif *string `json:"sarif,omitempty"` + CheckoutURI *string `json:"checkout_uri,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + ToolName *string `json:"tool_name,omitempty"` +} + +// CodeScanningAlertState specifies the state of a code scanning alert. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type CodeScanningAlertState struct { + // State sets the state of the code scanning alert and is a required field. + // You must also provide DismissedReason when you set the state to "dismissed". + // State can be one of: "open", "dismissed". + State string `json:"state"` + // DismissedReason represents the reason for dismissing or closing the alert. + // It is required when the state is "dismissed". + // It can be one of: "false positive", "won't fix", "used in tests". + DismissedReason *string `json:"dismissed_reason,omitempty"` + // DismissedComment is associated with the dismissal of the alert. + DismissedComment *string `json:"dismissed_comment,omitempty"` +} + +// SarifID identifies a sarif analysis upload. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning +type SarifID struct { + ID *string `json:"id,omitempty"` + URL *string `json:"url,omitempty"` +} + +// ListAlertsForOrg lists code scanning alerts for an org. +// +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/code-scanning/alerts +func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForRepo lists code scanning alerts for a repository. +// +// Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts +func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// GetAlert gets a single code scanning alert for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security alert_id is the number at the end of the security alert's URL. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number} +func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Alert) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// UpdateAlert updates the state of a single code scanning alert for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security alert_id is the number at the end of the security alert's URL. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number} +func (s *CodeScanningService) UpdateAlert(ctx context.Context, owner, repo string, id int64, stateInfo *CodeScanningAlertState) (*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, stateInfo) + if err != nil { + return nil, nil, err + } + + a := new(Alert) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// ListAlertInstances lists instances of a code scanning alert. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-instances-of-a-code-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances +func (s *CodeScanningService) ListAlertInstances(ctx context.Context, owner, repo string, id int64, opts *AlertInstancesListOptions) ([]*MostRecentInstance, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v/instances", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alertInstances []*MostRecentInstance + resp, err := s.client.Do(ctx, req, &alertInstances) + if err != nil { + return nil, resp, err + } + + return alertInstances, resp, nil +} + +// UploadSarif uploads the result of code scanning job to GitHub. +// +// For the parameter sarif, you must first compress your SARIF file using gzip and then translate the contents of the file into a Base64 encoding string. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#upload-an-analysis-as-sarif-data +// +//meta:operation POST /repos/{owner}/{repo}/code-scanning/sarifs +func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo string, sarif *SarifAnalysis) (*SarifID, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs", owner, repo) + + req, err := s.client.NewRequest("POST", u, sarif) + if err != nil { + return nil, nil, err + } + + // This will always return an error without unmarshalling the data + resp, err := s.client.Do(ctx, req, nil) + // Even though there was an error, we still return the response + // in case the caller wants to inspect it further. + // However, if the error is AcceptedError, decode it below before + // returning from this function and closing the response body. + var acceptedError *AcceptedError + if !errors.As(err, &acceptedError) { + return nil, resp, err + } + sarifID := new(SarifID) + decErr := json.Unmarshal(acceptedError.Raw, sarifID) + if decErr != nil { + return nil, resp, decErr + } + + return sarifID, resp, nil +} + +// SARIFUpload represents information about a SARIF upload. +type SARIFUpload struct { + // `pending` files have not yet been processed, while `complete` means results from the SARIF have been stored. + // `failed` files have either not been processed at all, or could only be partially processed. + ProcessingStatus *string `json:"processing_status,omitempty"` + // The REST API URL for getting the analyses associated with the upload. + AnalysesURL *string `json:"analyses_url,omitempty"` +} + +// GetSARIF gets information about a SARIF upload. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-information-about-a-sarif-upload +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id} +func (s *CodeScanningService) GetSARIF(ctx context.Context, owner, repo, sarifID string) (*SARIFUpload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs/%v", owner, repo, sarifID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sarifUpload := new(SARIFUpload) + resp, err := s.client.Do(ctx, req, sarifUpload) + if err != nil { + return nil, resp, err + } + + return sarifUpload, resp, nil +} + +// ListAnalysesForRepo lists code scanning analyses for a repository. +// +// Lists the details of all code scanning analyses for a repository, starting with the most recent. +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-code-scanning-analyses-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/analyses +func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, repo string, opts *AnalysesListOptions) ([]*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var analyses []*ScanningAnalysis + resp, err := s.client.Do(ctx, req, &analyses) + if err != nil { + return nil, resp, err + } + + return analyses, resp, nil +} + +// GetAnalysis gets a single code scanning analysis for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-analysis-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id} +func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo string, id int64) (*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + analysis := new(ScanningAnalysis) + resp, err := s.client.Do(ctx, req, analysis) + if err != nil { + return nil, resp, err + } + + return analysis, resp, nil +} + +// DeleteAnalysis represents a successful deletion of a code scanning analysis. +type DeleteAnalysis struct { + // Next deletable analysis in chain, without last analysis deletion confirmation + NextAnalysisURL *string `json:"next_analysis_url,omitempty"` + // Next deletable analysis in chain, with last analysis deletion confirmation + ConfirmDeleteURL *string `json:"confirm_delete_url,omitempty"` +} + +// DeleteAnalysis deletes a single code scanning analysis from a repository. +// +// You must use an access token with the repo scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#delete-a-code-scanning-analysis-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id} +func (s *CodeScanningService) DeleteAnalysis(ctx context.Context, owner, repo string, id int64) (*DeleteAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + deleteAnalysis := new(DeleteAnalysis) + resp, err := s.client.Do(ctx, req, deleteAnalysis) + if err != nil { + return nil, resp, err + } + + return deleteAnalysis, resp, nil +} + +// ListCodeQLDatabases lists the CodeQL databases that are available in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#list-codeql-databases-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/codeql/databases +func (s *CodeScanningService) ListCodeQLDatabases(ctx context.Context, owner, repo string) ([]*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codeqlDatabases []*CodeQLDatabase + resp, err := s.client.Do(ctx, req, &codeqlDatabases) + if err != nil { + return nil, resp, err + } + + return codeqlDatabases, resp, nil +} + +// GetCodeQLDatabase gets a CodeQL database for a language in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-codeql-database-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language} +func (s *CodeScanningService) GetCodeQLDatabase(ctx context.Context, owner, repo, language string) (*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases/%v", owner, repo, language) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + codeqlDatabase := new(CodeQLDatabase) + resp, err := s.client.Do(ctx, req, codeqlDatabase) + if err != nil { + return nil, resp, err + } + + return codeqlDatabase, resp, nil +} + +// DefaultSetupConfiguration represents a code scanning default setup configuration. +type DefaultSetupConfiguration struct { + State *string `json:"state,omitempty"` + Languages []string `json:"languages,omitempty"` + QuerySuite *string `json:"query_suite,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// GetDefaultSetupConfiguration gets a code scanning default setup configuration. +// +// You must use an access token with the repo scope to use this +// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write +// permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#get-a-code-scanning-default-setup-configuration +// +//meta:operation GET /repos/{owner}/{repo}/code-scanning/default-setup +func (s *CodeScanningService) GetDefaultSetupConfiguration(ctx context.Context, owner, repo string) (*DefaultSetupConfiguration, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + cfg := new(DefaultSetupConfiguration) + resp, err := s.client.Do(ctx, req, cfg) + if err != nil { + return nil, resp, err + } + + return cfg, resp, nil +} + +// UpdateDefaultSetupConfigurationOptions specifies parameters to the CodeScanningService.UpdateDefaultSetupConfiguration +// method. +type UpdateDefaultSetupConfigurationOptions struct { + State string `json:"state"` + QuerySuite *string `json:"query_suite,omitempty"` + Languages []string `json:"languages,omitempty"` +} + +// UpdateDefaultSetupConfigurationResponse represents a response from updating a code scanning default setup configuration. +type UpdateDefaultSetupConfigurationResponse struct { + RunID *int64 `json:"run_id,omitempty"` + RunURL *string `json:"run_url,omitempty"` +} + +// UpdateDefaultSetupConfiguration updates a code scanning default setup configuration. +// +// You must use an access token with the repo scope to use this +// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write +// permission to use this endpoint. +// +// This method might return an AcceptedError and a status code of 202. This is because this is the status that GitHub +// returns to signify that it has now scheduled the update of the pull request branch in a background task. +// +// GitHub API docs: https://docs.github.com/rest/code-scanning/code-scanning#update-a-code-scanning-default-setup-configuration +// +//meta:operation PATCH /repos/{owner}/{repo}/code-scanning/default-setup +func (s *CodeScanningService) UpdateDefaultSetupConfiguration(ctx context.Context, owner, repo string, options *UpdateDefaultSetupConfigurationOptions) (*UpdateDefaultSetupConfigurationResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) + + req, err := s.client.NewRequest("PATCH", u, options) + if err != nil { + return nil, nil, err + } + + a := new(UpdateDefaultSetupConfigurationResponse) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/codesofconduct.go b/vendor/github.com/google/go-github/v68/github/codesofconduct.go new file mode 100644 index 00000000..aba05741 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codesofconduct.go @@ -0,0 +1,87 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CodesOfConductService provides access to code-of-conduct-related functions in the GitHub API. +type CodesOfConductService service + +// CodeOfConduct represents a code of conduct. +type CodeOfConduct struct { + Name *string `json:"name,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (c *CodeOfConduct) String() string { + return Stringify(c) +} + +// List returns all codes of conduct. +// +// GitHub API docs: https://docs.github.com/rest/codes-of-conduct/codes-of-conduct#get-all-codes-of-conduct +// +//meta:operation GET /codes_of_conduct +func (s *CodesOfConductService) List(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + req, err := s.client.NewRequest("GET", "codes_of_conduct", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + var cs []*CodeOfConduct + resp, err := s.client.Do(ctx, req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, nil +} + +// ListCodesOfConduct returns all codes of conduct. +// +// Deprecated: Use CodesOfConductService.List instead. +func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + return c.CodesOfConduct.List(ctx) +} + +// Get returns an individual code of conduct. +// +// GitHub API docs: https://docs.github.com/rest/codes-of-conduct/codes-of-conduct#get-a-code-of-conduct +// +//meta:operation GET /codes_of_conduct/{key} +func (s *CodesOfConductService) Get(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("codes_of_conduct/%s", key) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + coc := new(CodeOfConduct) + resp, err := s.client.Do(ctx, req, coc) + if err != nil { + return nil, resp, err + } + + return coc, resp, nil +} + +// GetCodeOfConduct returns an individual code of conduct. +// +// Deprecated: Use CodesOfConductService.Get instead. +func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + return c.CodesOfConduct.Get(ctx, key) +} diff --git a/vendor/github.com/google/go-github/v68/github/codespaces.go b/vendor/github.com/google/go-github/v68/github/codespaces.go new file mode 100644 index 00000000..60837050 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codespaces.go @@ -0,0 +1,266 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CodespacesService handles communication with the Codespaces related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/ +type CodespacesService service + +// Codespace represents a codespace. +// +// GitHub API docs: https://docs.github.com/rest/codespaces +type Codespace struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + EnvironmentID *string `json:"environment_id,omitempty"` + Owner *User `json:"owner,omitempty"` + BillableOwner *User `json:"billable_owner,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Machine *CodespacesMachine `json:"machine,omitempty"` + DevcontainerPath *string `json:"devcontainer_path,omitempty"` + Prebuild *bool `json:"prebuild,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + LastUsedAt *Timestamp `json:"last_used_at,omitempty"` + State *string `json:"state,omitempty"` + URL *string `json:"url,omitempty"` + GitStatus *CodespacesGitStatus `json:"git_status,omitempty"` + Location *string `json:"location,omitempty"` + IdleTimeoutMinutes *int `json:"idle_timeout_minutes,omitempty"` + WebURL *string `json:"web_url,omitempty"` + MachinesURL *string `json:"machines_url,omitempty"` + StartURL *string `json:"start_url,omitempty"` + StopURL *string `json:"stop_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + RecentFolders []string `json:"recent_folders,omitempty"` + RuntimeConstraints *CodespacesRuntimeConstraints `json:"runtime_constraints,omitempty"` + PendingOperation *bool `json:"pending_operation,omitempty"` + PendingOperationDisabledReason *string `json:"pending_operation_disabled_reason,omitempty"` + IdleTimeoutNotice *string `json:"idle_timeout_notice,omitempty"` + RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"` + RetentionExpiresAt *Timestamp `json:"retention_expires_at,omitempty"` + LastKnownStopNotice *string `json:"last_known_stop_notice,omitempty"` +} + +// CodespacesGitStatus represents the git status of a codespace. +type CodespacesGitStatus struct { + Ahead *int `json:"ahead,omitempty"` + Behind *int `json:"behind,omitempty"` + HasUnpushedChanges *bool `json:"has_unpushed_changes,omitempty"` + HasUncommittedChanges *bool `json:"has_uncommitted_changes,omitempty"` + Ref *string `json:"ref,omitempty"` +} + +// CodespacesMachine represents the machine type of a codespace. +type CodespacesMachine struct { + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + OperatingSystem *string `json:"operating_system,omitempty"` + StorageInBytes *int64 `json:"storage_in_bytes,omitempty"` + MemoryInBytes *int64 `json:"memory_in_bytes,omitempty"` + CPUs *int `json:"cpus,omitempty"` + PrebuildAvailability *string `json:"prebuild_availability,omitempty"` +} + +// CodespacesRuntimeConstraints represents the runtime constraints of a codespace. +type CodespacesRuntimeConstraints struct { + AllowedPortPrivacySettings []string `json:"allowed_port_privacy_settings,omitempty"` +} + +// ListCodespaces represents the response from the list codespaces endpoints. +type ListCodespaces struct { + TotalCount *int `json:"total_count,omitempty"` + Codespaces []*Codespace `json:"codespaces"` +} + +// ListInRepo lists codespaces for a user in a repository. +// +// Lists the codespaces associated with a specified repository and the authenticated user. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have read access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#list-codespaces-in-a-repository-for-the-authenticated-user +// +//meta:operation GET /repos/{owner}/{repo}/codespaces +func (s *CodespacesService) ListInRepo(ctx context.Context, owner, repo string, opts *ListOptions) (*ListCodespaces, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codespaces *ListCodespaces + resp, err := s.client.Do(ctx, req, &codespaces) + if err != nil { + return nil, resp, err + } + + return codespaces, resp, nil +} + +// ListCodespacesOptions represents the options for listing codespaces for a user. +type ListCodespacesOptions struct { + ListOptions + RepositoryID int64 `url:"repository_id,omitempty"` +} + +// List lists codespaces for an authenticated user. +// +// Lists the authenticated user's codespaces. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have read access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#list-codespaces-for-the-authenticated-user +// +//meta:operation GET /user/codespaces +func (s *CodespacesService) List(ctx context.Context, opts *ListCodespacesOptions) (*ListCodespaces, *Response, error) { + u := "user/codespaces" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codespaces *ListCodespaces + resp, err := s.client.Do(ctx, req, &codespaces) + if err != nil { + return nil, resp, err + } + + return codespaces, resp, nil +} + +// CreateCodespaceOptions represents options for the creation of a codespace in a repository. +type CreateCodespaceOptions struct { + Ref *string `json:"ref,omitempty"` + // Geo represents the geographic area for this codespace. + // If not specified, the value is assigned by IP. + // This property replaces location, which is being deprecated. + // Geo can be one of: `EuropeWest`, `SoutheastAsia`, `UsEast`, `UsWest`. + Geo *string `json:"geo,omitempty"` + ClientIP *string `json:"client_ip,omitempty"` + Machine *string `json:"machine,omitempty"` + DevcontainerPath *string `json:"devcontainer_path,omitempty"` + MultiRepoPermissionsOptOut *bool `json:"multi_repo_permissions_opt_out,omitempty"` + WorkingDirectory *string `json:"working_directory,omitempty"` + IdleTimeoutMinutes *int `json:"idle_timeout_minutes,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + // RetentionPeriodMinutes represents the duration in minutes after codespace has gone idle in which it will be deleted. + // Must be integer minutes between 0 and 43200 (30 days). + RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"` +} + +// CreateInRepo creates a codespace in a repository. +// +// Creates a codespace owned by the authenticated user in the specified repository. +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#create-a-codespace-in-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/codespaces +func (s *CodespacesService) CreateInRepo(ctx context.Context, owner, repo string, request *CreateCodespaceOptions) (*Codespace, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Start starts a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#start-a-codespace-for-the-authenticated-user +// +//meta:operation POST /user/codespaces/{codespace_name}/start +func (s *CodespacesService) Start(ctx context.Context, codespaceName string) (*Codespace, *Response, error) { + u := fmt.Sprintf("user/codespaces/%v/start", codespaceName) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Stop stops a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#stop-a-codespace-for-the-authenticated-user +// +//meta:operation POST /user/codespaces/{codespace_name}/stop +func (s *CodespacesService) Stop(ctx context.Context, codespaceName string) (*Codespace, *Response, error) { + u := fmt.Sprintf("user/codespaces/%v/stop", codespaceName) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + var codespace *Codespace + resp, err := s.client.Do(ctx, req, &codespace) + if err != nil { + return nil, resp, err + } + + return codespace, resp, nil +} + +// Delete deletes a codespace. +// +// You must authenticate using an access token with the codespace scope to use this endpoint. +// GitHub Apps must have write access to the codespaces repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/codespaces#delete-a-codespace-for-the-authenticated-user +// +//meta:operation DELETE /user/codespaces/{codespace_name} +func (s *CodespacesService) Delete(ctx context.Context, codespaceName string) (*Response, error) { + u := fmt.Sprintf("user/codespaces/%v", codespaceName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go b/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go new file mode 100644 index 00000000..438c27f8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go @@ -0,0 +1,451 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListUserSecrets list all secrets available for a users codespace +// +// Lists all secrets available for a user's Codespaces without revealing their encrypted values +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#list-secrets-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets +func (s *CodespacesService) ListUserSecrets(ctx context.Context, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions("user/codespaces/secrets", opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +// ListOrgSecrets list all secrets available to an org +// +// Lists all Codespaces secrets available at the organization-level without revealing their encrypted values. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/codespaces/secrets +func (s *CodespacesService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +// ListRepoSecrets list all secrets available to a repo +// +// Lists all secrets available in a repository without revealing their encrypted values. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets +func (s *CodespacesService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + return s.listSecrets(ctx, u) +} + +func (s *CodespacesService) listSecrets(ctx context.Context, url string) (*Secrets, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var secrets *Secrets + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// GetUserPublicKey gets the users public key for encrypting codespace secrets +// +// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#get-public-key-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets/public-key +func (s *CodespacesService) GetUserPublicKey(ctx context.Context) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, "user/codespaces/secrets/public-key") +} + +// GetOrgPublicKey gets the org public key for encrypting codespace secrets +// +// Gets a public key for an organization, which is required in order to encrypt secrets. You need to encrypt the value of a secret before you can create or update secrets. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/codespaces/secrets/public-key +func (s *CodespacesService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, fmt.Sprintf("orgs/%v/codespaces/secrets/public-key", org)) +} + +// GetRepoPublicKey gets the repo public key for encrypting codespace secrets +// +// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. Anyone with read access to the repository can use this endpoint. If the repository is private you must use an access token with the repo scope. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets/public-key +func (s *CodespacesService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + return s.getPublicKey(ctx, fmt.Sprintf("repos/%v/%v/codespaces/secrets/public-key", owner, repo)) +} + +func (s *CodespacesService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var publicKey *PublicKey + resp, err := s.client.Do(ctx, req, &publicKey) + if err != nil { + return nil, resp, err + } + + return publicKey, resp, nil +} + +// GetUserSecret gets a users codespace secret +// +// Gets a secret available to a user's codespaces without revealing its encrypted value. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#get-a-secret-for-the-authenticated-user +// +//meta:operation GET /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetUserSecret(ctx context.Context, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", name) + return s.getSecret(ctx, u) +} + +// GetOrgSecret gets an org codespace secret +// +// Gets an organization secret without revealing its encrypted value. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name) + return s.getSecret(ctx, u) +} + +// GetRepoSecret gets a repo codespace secret +// +// Gets a single repository secret without revealing its encrypted value. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name) + return s.getSecret(ctx, u) +} + +func (s *CodespacesService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var secret *Secret + resp, err := s.client.Do(ctx, req, &secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// CreateOrUpdateUserSecret creates or updates a users codespace secret +// +// Creates or updates a secret for a user's codespace with an encrypted value. Encrypt your secret using LibSodium. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must also have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission and codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#create-or-update-a-secret-for-the-authenticated-user +// +//meta:operation PUT /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateUserSecret(ctx context.Context, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an orgs codespace secret +// +// Creates or updates an organization secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +// CreateOrUpdateRepoSecret creates or updates a repos codespace secret +// +// Creates or updates a repository secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, eSecret.Name) + return s.createOrUpdateSecret(ctx, u, eSecret) +} + +func (s *CodespacesService) createOrUpdateSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DeleteUserSecret deletes a users codespace secret +// +// Deletes a secret from a user's codespaces using the secret name. Deleting the secret will remove access from all codespaces that were allowed to access the secret. +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#delete-a-secret-for-the-authenticated-user +// +//meta:operation DELETE /user/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteUserSecret(ctx context.Context, name string) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v", name) + return s.deleteSecret(ctx, u) +} + +// DeleteOrgSecret deletes an orgs codespace secret +// +// Deletes an organization secret using the secret name. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name) + return s.deleteSecret(ctx, u) +} + +// DeleteRepoSecret deletes a repos codespace secret +// +// Deletes a secret in a repository using the secret name. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/repository-secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name} +func (s *CodespacesService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, u) +} + +func (s *CodespacesService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ListSelectedReposForUserSecret lists the repositories that have been granted the ability to use a user's codespace secret. +// +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have read access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#list-selected-repositories-for-a-user-secret +// +//meta:operation GET /user/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) ListSelectedReposForUserSecret(ctx context.Context, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + return s.listSelectedReposForSecret(ctx, u) +} + +// ListSelectedReposForOrgSecret lists the repositories that have been granted the ability to use an organization's codespace secret. +// +// Lists all repositories that have been selected when the visibility for repository access to a secret is set to selected. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + return s.listSelectedReposForSecret(ctx, u) +} + +func (s *CodespacesService) listSelectedReposForSecret(ctx context.Context, url string) (*SelectedReposList, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var repositories *SelectedReposList + resp, err := s.client.Do(ctx, req, &repositories) + if err != nil { + return nil, resp, err + } + + return repositories, resp, nil +} + +// SetSelectedReposForUserSecret sets the repositories that have been granted the ability to use a user's codespace secret. +// +// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. +// GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#set-selected-repositories-for-a-user-secret +// +//meta:operation PUT /user/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) SetSelectedReposForUserSecret(ctx context.Context, name string, ids SelectedRepoIDs) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name) + return s.setSelectedRepoForSecret(ctx, u, ids) +} + +// SetSelectedReposForOrgSecret sets the repositories that have been granted the ability to use a user's codespace secret. +// +// Replaces all repositories for an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories +func (s *CodespacesService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name) + return s.setSelectedRepoForSecret(ctx, u, ids) +} + +func (s *CodespacesService) setSelectedRepoForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddSelectedRepoToUserSecret adds a repository to the list of repositories that have been granted the ability to use a user's codespace secret. +// +// Adds a repository to the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on the referenced repository to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#add-a-selected-repository-to-a-user-secret +// +//meta:operation PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) AddSelectedRepoToUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, u) +} + +// AddSelectedRepoToOrgSecret adds a repository to the list of repositories that have been granted the ability to use an organization's codespace secret. +// +// Adds a repository to an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, u) +} + +func (s *CodespacesService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveSelectedRepoFromUserSecret removes a repository from the list of repositories that have been granted the ability to use a user's codespace secret. +// +// Removes a repository from the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/secrets#remove-a-selected-repository-from-a-user-secret +// +//meta:operation DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) RemoveSelectedRepoFromUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, u) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from the list of repositories that have been granted the ability to use an organization's codespace secret. +// +// Removes a repository from an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint. +// +// GitHub API docs: https://docs.github.com/rest/codespaces/organization-secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id} +func (s *CodespacesService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, u) +} + +func (s *CodespacesService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/copilot.go b/vendor/github.com/google/go-github/v68/github/copilot.go new file mode 100644 index 00000000..a2b2aa09 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/copilot.go @@ -0,0 +1,570 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "time" +) + +// CopilotService provides access to the Copilot-related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/copilot/ +type CopilotService service + +// CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription. +type CopilotOrganizationDetails struct { + SeatBreakdown *CopilotSeatBreakdown `json:"seat_breakdown"` + PublicCodeSuggestions string `json:"public_code_suggestions"` + CopilotChat string `json:"copilot_chat"` + SeatManagementSetting string `json:"seat_management_setting"` +} + +// CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization. +type CopilotSeatBreakdown struct { + Total int `json:"total"` + AddedThisCycle int `json:"added_this_cycle"` + PendingCancellation int `json:"pending_cancellation"` + PendingInvitation int `json:"pending_invitation"` + ActiveThisCycle int `json:"active_this_cycle"` + InactiveThisCycle int `json:"inactive_this_cycle"` +} + +// ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization. +type ListCopilotSeatsResponse struct { + TotalSeats int64 `json:"total_seats"` + Seats []*CopilotSeatDetails `json:"seats"` +} + +// CopilotSeatDetails represents the details of a Copilot for Business seat. +type CopilotSeatDetails struct { + // Assignee can either be a User, Team, or Organization. + Assignee interface{} `json:"assignee"` + AssigningTeam *Team `json:"assigning_team,omitempty"` + PendingCancellationDate *string `json:"pending_cancellation_date,omitempty"` + LastActivityAt *Timestamp `json:"last_activity_at,omitempty"` + LastActivityEditor *string `json:"last_activity_editor,omitempty"` + CreatedAt *Timestamp `json:"created_at"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PlanType *string `json:"plan_type,omitempty"` +} + +// SeatAssignments represents the number of seats assigned. +type SeatAssignments struct { + SeatsCreated int `json:"seats_created"` +} + +// SeatCancellations represents the number of seats cancelled. +type SeatCancellations struct { + SeatsCancelled int `json:"seats_cancelled"` +} + +// CopilotMetricsListOptions represents the optional parameters to the CopilotService get metrics methods. +type CopilotMetricsListOptions struct { + Since *time.Time `url:"since,omitempty"` + Until *time.Time `url:"until,omitempty"` + + ListOptions +} + +// CopilotIDECodeCompletionsLanguage represents Copilot usage metrics for completions in the IDE for a language. +type CopilotIDECodeCompletionsLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotIDECodeCompletionsModelLanguage represents Copilot usage metrics for completions in the IDE for a model and language. +type CopilotIDECodeCompletionsModelLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalCodeSuggestions int `json:"total_code_suggestions"` + TotalCodeAcceptances int `json:"total_code_acceptances"` + TotalCodeLinesSuggested int `json:"total_code_lines_suggested"` + TotalCodeLinesAccepted int `json:"total_code_lines_accepted"` +} + +// CopilotIDECodeCompletionsModel represents Copilot usage metrics for completions in the IDE for a model. +type CopilotIDECodeCompletionsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsModelLanguage `json:"languages"` +} + +// CopilotIDECodeCompletionsEditor represents Copilot usage metrics for completions in the IDE for an editor. +type CopilotIDECodeCompletionsEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDECodeCompletionsModel `json:"models"` +} + +// CopilotIDECodeCompletions represents Copilot usage metrics for Copilot code completions in the IDE, categorized by editor, model and language. +type CopilotIDECodeCompletions struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsLanguage `json:"languages"` + Editors []*CopilotIDECodeCompletionsEditor `json:"editors"` +} + +// CopilotIDEChatModel represents Copilot usage metrics for chatting with a model in the IDE. +type CopilotIDEChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` + TotalChatInsertionEvents int `json:"total_chat_insertion_events"` + TotalChatCopyEvents int `json:"total_chat_copy_events"` +} + +// CopilotIDEChatEditor represents Copilot usage metrics for chatting with a model in the IDE, categorized by editor and model. +type CopilotIDEChatEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDEChatModel `json:"models"` +} + +// CopilotIDEChat represents Copilot usage metrics for Copilot Chat in the IDE, categorized by editor and model. +type CopilotIDEChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Editors []*CopilotIDEChatEditor `json:"editors"` +} + +// CopilotDotcomChatModel represents Copilot usage metrics for chatting with a model in the webbrowser. +type CopilotDotcomChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` +} + +// CopilotDotcomChat represents Copilot usage metrics for Copilot Chat in the webbrowser, categorized by model. +type CopilotDotcomChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomChatModel `json:"models"` +} + +// CopilotDotcomPullRequestsModel represents Copilot usage metrics for pull requests in the webbrowser, categorized by model. +type CopilotDotcomPullRequestsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalPRSummariesCreated int `json:"total_pr_summaries_created"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotDotcomPullRequestsRepository represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository. +type CopilotDotcomPullRequestsRepository struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomPullRequestsModel `json:"models"` +} + +// CopilotDotcomPullRequests represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository and model. +type CopilotDotcomPullRequests struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Repositories []*CopilotDotcomPullRequestsRepository `json:"repositories"` +} + +// CopilotMetrics represents Copilot usage metrics for a given day. +type CopilotMetrics struct { + Date string `json:"date"` + TotalActiveUsers *int `json:"total_active_users,omitempty"` + TotalEngagedUsers *int `json:"total_engaged_users,omitempty"` + CopilotIDECodeCompletions *CopilotIDECodeCompletions `json:"copilot_ide_code_completions,omitempty"` + CopilotIDEChat *CopilotIDEChat `json:"copilot_ide_chat,omitempty"` + CopilotDotcomChat *CopilotDotcomChat `json:"copilot_dotcom_chat,omitempty"` + CopilotDotcomPullRequests *CopilotDotcomPullRequests `json:"copilot_dotcom_pull_requests,omitempty"` +} + +func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error { + // Using an alias to avoid infinite recursion when calling json.Unmarshal + type alias CopilotSeatDetails + var seatDetail alias + + if err := json.Unmarshal(data, &seatDetail); err != nil { + return err + } + + cp.AssigningTeam = seatDetail.AssigningTeam + cp.PendingCancellationDate = seatDetail.PendingCancellationDate + cp.LastActivityAt = seatDetail.LastActivityAt + cp.LastActivityEditor = seatDetail.LastActivityEditor + cp.CreatedAt = seatDetail.CreatedAt + cp.UpdatedAt = seatDetail.UpdatedAt + cp.PlanType = seatDetail.PlanType + + switch v := seatDetail.Assignee.(type) { + case map[string]interface{}: + jsonData, err := json.Marshal(seatDetail.Assignee) + if err != nil { + return err + } + + if v["type"] == nil { + return errors.New("assignee type field is not set") + } + + if t, ok := v["type"].(string); ok && t == "User" { + user := &User{} + if err := json.Unmarshal(jsonData, user); err != nil { + return err + } + cp.Assignee = user + } else if t, ok := v["type"].(string); ok && t == "Team" { + team := &Team{} + if err := json.Unmarshal(jsonData, team); err != nil { + return err + } + cp.Assignee = team + } else if t, ok := v["type"].(string); ok && t == "Organization" { + organization := &Organization{} + if err := json.Unmarshal(jsonData, organization); err != nil { + return err + } + cp.Assignee = organization + } else { + return fmt.Errorf("unsupported assignee type %v", v["type"]) + } + default: + return fmt.Errorf("unsupported assignee type %T", v) + } + + return nil +} + +// GetUser gets the User from the CopilotSeatDetails if the assignee is a user. +func (cp *CopilotSeatDetails) GetUser() (*User, bool) { u, ok := cp.Assignee.(*User); return u, ok } + +// GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team. +func (cp *CopilotSeatDetails) GetTeam() (*Team, bool) { t, ok := cp.Assignee.(*Team); return t, ok } + +// GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization. +func (cp *CopilotSeatDetails) GetOrganization() (*Organization, bool) { + o, ok := cp.Assignee.(*Organization) + return o, ok +} + +// GetCopilotBilling gets Copilot for Business billing information and settings for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-information-and-settings-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/billing +func (s *CopilotService) GetCopilotBilling(ctx context.Context, org string) (*CopilotOrganizationDetails, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotDetails *CopilotOrganizationDetails + resp, err := s.client.Do(ctx, req, &copilotDetails) + if err != nil { + return nil, resp, err + } + + return copilotDetails, resp, nil +} + +// ListCopilotSeats lists Copilot for Business seat assignments for an organization. +// +// To paginate through all seats, populate 'Page' with the number of the last page. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/billing/seats +func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/seats", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotSeats *ListCopilotSeatsResponse + resp, err := s.client.Do(ctx, req, &copilotSeats) + if err != nil { + return nil, resp, err + } + + return copilotSeats, resp, nil +} + +// ListCopilotEnterpriseSeats lists Copilot for Business seat assignments for an enterprise. +// +// To paginate through all seats, populate 'Page' with the number of the last page. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/copilot/billing/seats +func (s *CopilotService) ListCopilotEnterpriseSeats(ctx context.Context, enterprise string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { + u := fmt.Sprintf("enterprises/%v/copilot/billing/seats", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var copilotSeats *ListCopilotSeatsResponse + resp, err := s.client.Do(ctx, req, &copilotSeats) + if err != nil { + return nil, resp, err + } + + return copilotSeats, resp, nil +} + +// AddCopilotTeams adds teams to the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-teams-to-the-copilot-subscription-for-an-organization +// +//meta:operation POST /orgs/{org}/copilot/billing/selected_teams +func (s *CopilotService) AddCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatAssignments, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) + + body := struct { + SelectedTeams []string `json:"selected_teams"` + }{ + SelectedTeams: teamNames, + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + var seatAssignments *SeatAssignments + resp, err := s.client.Do(ctx, req, &seatAssignments) + if err != nil { + return nil, resp, err + } + + return seatAssignments, resp, nil +} + +// RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-teams-from-the-copilot-subscription-for-an-organization +// +//meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams +func (s *CopilotService) RemoveCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatCancellations, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) + + body := struct { + SelectedTeams []string `json:"selected_teams"` + }{ + SelectedTeams: teamNames, + } + + req, err := s.client.NewRequest("DELETE", u, body) + if err != nil { + return nil, nil, err + } + + var seatCancellations *SeatCancellations + resp, err := s.client.Do(ctx, req, &seatCancellations) + if err != nil { + return nil, resp, err + } + + return seatCancellations, resp, nil +} + +// AddCopilotUsers adds users to the Copilot for Business subscription for an organization +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-users-to-the-copilot-subscription-for-an-organization +// +//meta:operation POST /orgs/{org}/copilot/billing/selected_users +func (s *CopilotService) AddCopilotUsers(ctx context.Context, org string, users []string) (*SeatAssignments, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) + + body := struct { + SelectedUsernames []string `json:"selected_usernames"` + }{ + SelectedUsernames: users, + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + var seatAssignments *SeatAssignments + resp, err := s.client.Do(ctx, req, &seatAssignments) + if err != nil { + return nil, resp, err + } + + return seatAssignments, resp, nil +} + +// RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-users-from-the-copilot-subscription-for-an-organization +// +//meta:operation DELETE /orgs/{org}/copilot/billing/selected_users +func (s *CopilotService) RemoveCopilotUsers(ctx context.Context, org string, users []string) (*SeatCancellations, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) + + body := struct { + SelectedUsernames []string `json:"selected_usernames"` + }{ + SelectedUsernames: users, + } + + req, err := s.client.NewRequest("DELETE", u, body) + if err != nil { + return nil, nil, err + } + + var seatCancellations *SeatCancellations + resp, err := s.client.Do(ctx, req, &seatCancellations) + if err != nil { + return nil, resp, err + } + + return seatCancellations, resp, nil +} + +// GetSeatDetails gets Copilot for Business seat assignment details for a user. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-assignment-details-for-a-user +// +//meta:operation GET /orgs/{org}/members/{username}/copilot +func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (*CopilotSeatDetails, *Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v/copilot", org, user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var seatDetails *CopilotSeatDetails + resp, err := s.client.Do(ctx, req, &seatDetails) + if err != nil { + return nil, resp, err + } + + return seatDetails, resp, nil +} + +// GetEnterpriseMetrics gets Copilot usage metrics for an enterprise. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/copilot/metrics +func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/copilot/metrics", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetEnterpriseTeamMetrics gets Copilot usage metrics for an enterprise team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team +// +//meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetEnterpriseTeamMetrics(ctx context.Context, enterprise, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/team/%v/copilot/metrics", enterprise, team) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationMetrics gets Copilot usage metrics for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/metrics +func (s *CopilotService) GetOrganizationMetrics(ctx context.Context, org string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/metrics", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationTeamMetrics gets Copilot usage metrics for an organization team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-a-team +// +//meta:operation GET /orgs/{org}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetOrganizationTeamMetrics(ctx context.Context, org, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/team/%v/copilot/metrics", org, team) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependabot.go b/vendor/github.com/google/go-github/v68/github/dependabot.go new file mode 100644 index 00000000..2a11a9c9 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot.go @@ -0,0 +1,12 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// DependabotService handles communication with the Dependabot related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/ +type DependabotService service diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go b/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go new file mode 100644 index 00000000..c274f07b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go @@ -0,0 +1,176 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Dependency represents the vulnerable dependency. +type Dependency struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + ManifestPath *string `json:"manifest_path,omitempty"` + Scope *string `json:"scope,omitempty"` +} + +// AdvisoryCVSS represents the advisory pertaining to the Common Vulnerability Scoring System. +type AdvisoryCVSS struct { + Score *float64 `json:"score,omitempty"` + VectorString *string `json:"vector_string,omitempty"` +} + +// AdvisoryCWEs represent the advisory pertaining to Common Weakness Enumeration. +type AdvisoryCWEs struct { + CWEID *string `json:"cwe_id,omitempty"` + Name *string `json:"name,omitempty"` +} + +// DependabotSecurityAdvisory represents the GitHub Security Advisory. +type DependabotSecurityAdvisory struct { + GHSAID *string `json:"ghsa_id,omitempty"` + CVEID *string `json:"cve_id,omitempty"` + Summary *string `json:"summary,omitempty"` + Description *string `json:"description,omitempty"` + Vulnerabilities []*AdvisoryVulnerability `json:"vulnerabilities,omitempty"` + Severity *string `json:"severity,omitempty"` + CVSS *AdvisoryCVSS `json:"cvss,omitempty"` + CWEs []*AdvisoryCWEs `json:"cwes,omitempty"` + Identifiers []*AdvisoryIdentifier `json:"identifiers,omitempty"` + References []*AdvisoryReference `json:"references,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + WithdrawnAt *Timestamp `json:"withdrawn_at,omitempty"` +} + +// DependabotAlert represents a Dependabot alert. +type DependabotAlert struct { + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Dependency *Dependency `json:"dependency,omitempty"` + SecurityAdvisory *DependabotSecurityAdvisory `json:"security_advisory,omitempty"` + SecurityVulnerability *AdvisoryVulnerability `json:"security_vulnerability,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` + DismissedBy *User `json:"dismissed_by,omitempty"` + DismissedReason *string `json:"dismissed_reason,omitempty"` + DismissedComment *string `json:"dismissed_comment,omitempty"` + FixedAt *Timestamp `json:"fixed_at,omitempty"` + AutoDismissedAt *Timestamp `json:"auto_dismissed_at,omitempty"` + // The repository is always empty for events + Repository *Repository `json:"repository,omitempty"` +} + +// DependabotAlertState represents the state of a Dependabot alert to update. +type DependabotAlertState struct { + // The state of the Dependabot alert. A dismissed_reason must be provided when setting the state to dismissed. + State string `json:"state"` + // Required when state is dismissed. A reason for dismissing the alert. + // Can be one of: fix_started, inaccurate, no_bandwidth, not_used, tolerable_risk + DismissedReason *string `json:"dismissed_reason,omitempty"` + // An optional comment associated with dismissing the alert. + DismissedComment *string `json:"dismissed_comment,omitempty"` +} + +// ListAlertsOptions specifies the optional parameters to the DependabotService.ListRepoAlerts +// and DependabotService.ListOrgAlerts methods. +type ListAlertsOptions struct { + State *string `url:"state,omitempty"` + Severity *string `url:"severity,omitempty"` + Ecosystem *string `url:"ecosystem,omitempty"` + Package *string `url:"package,omitempty"` + Scope *string `url:"scope,omitempty"` + Sort *string `url:"sort,omitempty"` + Direction *string `url:"direction,omitempty"` + + ListOptions + ListCursorOptions +} + +func (s *DependabotService) listAlerts(ctx context.Context, url string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*DependabotAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListRepoAlerts lists all Dependabot alerts of a repository. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#list-dependabot-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/alerts +func (s *DependabotService) ListRepoAlerts(ctx context.Context, owner, repo string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts", owner, repo) + return s.listAlerts(ctx, url, opts) +} + +// ListOrgAlerts lists all Dependabot alerts of an organization. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#list-dependabot-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/dependabot/alerts +func (s *DependabotService) ListOrgAlerts(ctx context.Context, org string, opts *ListAlertsOptions) ([]*DependabotAlert, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/alerts", org) + return s.listAlerts(ctx, url, opts) +} + +// GetRepoAlert gets a single repository Dependabot alert. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#get-a-dependabot-alert +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number} +func (s *DependabotService) GetRepoAlert(ctx context.Context, owner, repo string, number int) (*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts/%v", owner, repo, number) + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + alert := new(DependabotAlert) + resp, err := s.client.Do(ctx, req, alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// UpdateAlert updates a Dependabot alert. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/alerts#update-a-dependabot-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number} +func (s *DependabotService) UpdateAlert(ctx context.Context, owner, repo string, number int, stateInfo *DependabotAlertState) (*DependabotAlert, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/alerts/%v", owner, repo, number) + req, err := s.client.NewRequest("PATCH", url, stateInfo) + if err != nil { + return nil, nil, err + } + + alert := new(DependabotAlert) + resp, err := s.client.Do(ctx, req, alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go b/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go new file mode 100644 index 00000000..e85c805a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go @@ -0,0 +1,289 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +func (s *DependabotService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-a-repository-public-key +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets/public-key +func (s *DependabotService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-an-organization-public-key +// +//meta:operation GET /orgs/{org}/dependabot/secrets/public-key +func (s *DependabotService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +func (s *DependabotService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all Dependabot secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-repository-secrets +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets +func (s *DependabotService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all Dependabot secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-organization-secrets +// +//meta:operation GET /orgs/{org}/dependabot/secrets +func (s *DependabotService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +func (s *DependabotService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-a-repository-secret +// +//meta:operation GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#get-an-organization-secret +// +//meta:operation GET /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +// DependabotEncryptedSecret represents a secret that is encrypted using a public key for Dependabot. +// +// The value of EncryptedValue must be your secret, encrypted with +// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) +// using the public key retrieved using the GetPublicKey method. +type DependabotEncryptedSecret struct { + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoryIDs DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +func (s *DependabotService) putSecret(ctx context.Context, url string, eSecret *DependabotEncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#create-or-update-a-repository-secret +// +//meta:operation PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *DependabotEncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#create-or-update-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *DependabotEncryptedSecret) (*Response, error) { + repoIDs := make([]string, len(eSecret.SelectedRepositoryIDs)) + for i, secret := range eSecret.SelectedRepositoryIDs { + repoIDs[i] = fmt.Sprintf("%v", secret) + } + params := struct { + *DependabotEncryptedSecret + SelectedRepositoryIDs []string `json:"selected_repository_ids,omitempty"` + }{ + DependabotEncryptedSecret: eSecret, + SelectedRepositoryIDs: repoIDs, + } + + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, eSecret.Name) + req, err := s.client.NewRequest("PUT", url, params) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +func (s *DependabotService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a Dependabot secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#delete-a-repository-secret +// +//meta:operation DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name} +func (s *DependabotService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a Dependabot secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#delete-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/dependabot/secrets/{secret_name} +func (s *DependabotService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#list-selected-repositories-for-an-organization-secret +// +//meta:operation GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories +func (s *DependabotService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// DependabotSecretsSelectedRepoIDs are the repository IDs that have access to the dependabot secrets. +type DependabotSecretsSelectedRepoIDs []int64 + +// SetSelectedReposForOrgSecret sets the repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#set-selected-repositories-for-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories +func (s *DependabotService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids DependabotSecretsSelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + type repoIDs struct { + SelectedIDs DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#add-selected-repository-to-an-organization-secret +// +//meta:operation PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id} +func (s *DependabotService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/rest/dependabot/secrets#remove-selected-repository-from-an-organization-secret +// +//meta:operation DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id} +func (s *DependabotService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph.go b/vendor/github.com/google/go-github/v68/github/dependency_graph.go new file mode 100644 index 00000000..86a1fe48 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependency_graph.go @@ -0,0 +1,82 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +type DependencyGraphService service + +// SBOM represents a software bill of materials, which describes the +// packages/libraries that a repository depends on. +type SBOM struct { + SBOM *SBOMInfo `json:"sbom,omitempty"` +} + +// CreationInfo represents when the SBOM was created and who created it. +type CreationInfo struct { + Created *Timestamp `json:"created,omitempty"` + Creators []string `json:"creators,omitempty"` +} + +// RepoDependencies represents the dependencies of a repo. +type RepoDependencies struct { + SPDXID *string `json:"SPDXID,omitempty"` + // Package name + Name *string `json:"name,omitempty"` + VersionInfo *string `json:"versionInfo,omitempty"` + DownloadLocation *string `json:"downloadLocation,omitempty"` + FilesAnalyzed *bool `json:"filesAnalyzed,omitempty"` + LicenseConcluded *string `json:"licenseConcluded,omitempty"` + LicenseDeclared *string `json:"licenseDeclared,omitempty"` +} + +// SBOMInfo represents a software bill of materials (SBOM) using SPDX. +// SPDX is an open standard for SBOMs that +// identifies and catalogs components, licenses, copyrights, security +// references, and other metadata relating to software. +type SBOMInfo struct { + SPDXID *string `json:"SPDXID,omitempty"` + SPDXVersion *string `json:"spdxVersion,omitempty"` + CreationInfo *CreationInfo `json:"creationInfo,omitempty"` + + // Repo name + Name *string `json:"name,omitempty"` + DataLicense *string `json:"dataLicense,omitempty"` + DocumentDescribes []string `json:"documentDescribes,omitempty"` + DocumentNamespace *string `json:"documentNamespace,omitempty"` + + // List of packages dependencies + Packages []*RepoDependencies `json:"packages,omitempty"` +} + +func (s SBOM) String() string { + return Stringify(s) +} + +// GetSBOM fetches the software bill of materials for a repository. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/sboms#export-a-software-bill-of-materials-sbom-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/dependency-graph/sbom +func (s *DependencyGraphService) GetSBOM(ctx context.Context, owner, repo string) (*SBOM, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/dependency-graph/sbom", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var sbom *SBOM + resp, err := s.client.Do(ctx, req, &sbom) + if err != nil { + return nil, resp, err + } + + return sbom, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go b/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go new file mode 100644 index 00000000..0606b981 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go @@ -0,0 +1,113 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DependencyGraphSnapshotResolvedDependency represents a resolved dependency in a dependency graph snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotResolvedDependency struct { + PackageURL *string `json:"package_url,omitempty"` + // Represents whether the dependency is requested directly by the manifest or is a dependency of another dependency. + // Can have the following values: + // - "direct": indicates that the dependency is requested directly by the manifest. + // - "indirect": indicates that the dependency is a dependency of another dependency. + Relationship *string `json:"relationship,omitempty"` + // Represents whether the dependency is required for the primary build artifact or is only used for development. + // Can have the following values: + // - "runtime": indicates that the dependency is required for the primary build artifact. + // - "development": indicates that the dependency is only used for development. + Scope *string `json:"scope,omitempty"` + Dependencies []string `json:"dependencies,omitempty"` +} + +// DependencyGraphSnapshotJob represents the job that created the snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotJob struct { + Correlator *string `json:"correlator,omitempty"` + ID *string `json:"id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// DependencyGraphSnapshotDetector represents a description of the detector used. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotDetector struct { + Name *string `json:"name,omitempty"` + Version *string `json:"version,omitempty"` + URL *string `json:"url,omitempty"` +} + +// DependencyGraphSnapshotManifestFile represents the file declaring the repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifestFile struct { + SourceLocation *string `json:"source_location,omitempty"` +} + +// DependencyGraphSnapshotManifest represents a collection of related dependencies declared in a file or representing a logical group of dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifest struct { + Name *string `json:"name,omitempty"` + File *DependencyGraphSnapshotManifestFile `json:"file,omitempty"` + Resolved map[string]*DependencyGraphSnapshotResolvedDependency `json:"resolved,omitempty"` +} + +// DependencyGraphSnapshot represent a snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshot struct { + Version int `json:"version"` + Sha *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Job *DependencyGraphSnapshotJob `json:"job,omitempty"` + Detector *DependencyGraphSnapshotDetector `json:"detector,omitempty"` + Scanned *Timestamp `json:"scanned,omitempty"` + Manifests map[string]*DependencyGraphSnapshotManifest `json:"manifests,omitempty"` +} + +// DependencyGraphSnapshotCreationData represents the dependency snapshot's creation result. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotCreationData struct { + ID int64 `json:"id"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Message *string `json:"message,omitempty"` + // Represents the snapshot creation result. + // Can have the following values: + // - "SUCCESS": indicates that the snapshot was successfully created and the repository's dependencies were updated. + // - "ACCEPTED": indicates that the snapshot was successfully created, but the repository's dependencies were not updated. + // - "INVALID": indicates that the snapshot was malformed. + Result *string `json:"result,omitempty"` +} + +// CreateSnapshot creates a new snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/dependency-graph/snapshots +func (s *DependencyGraphService) CreateSnapshot(ctx context.Context, owner, repo string, dependencyGraphSnapshot *DependencyGraphSnapshot) (*DependencyGraphSnapshotCreationData, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependency-graph/snapshots", owner, repo) + + req, err := s.client.NewRequest("POST", url, dependencyGraphSnapshot) + if err != nil { + return nil, nil, err + } + + var snapshotCreationData *DependencyGraphSnapshotCreationData + resp, err := s.client.Do(ctx, req, &snapshotCreationData) + if err != nil { + return nil, resp, err + } + + return snapshotCreationData, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/doc.go b/vendor/github.com/google/go-github/v68/github/doc.go similarity index 76% rename from vendor/github.com/google/go-github/github/doc.go rename to vendor/github.com/google/go-github/v68/github/doc.go index 96445d26..4a0f163a 100644 --- a/vendor/github.com/google/go-github/github/doc.go +++ b/vendor/github.com/google/go-github/v68/github/doc.go @@ -8,7 +8,8 @@ Package github provides a client for using the GitHub API. Usage: - import "github.com/google/go-github/github" + import "github.com/google/go-github/v68/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) + import "github.com/google/go-github/github" // with go modules disabled Construct a new GitHub client, then use the various services on the client to access different parts of the GitHub API. For example: @@ -28,50 +29,36 @@ Some API methods have optional parameters that can be passed. For example: The services of a client divide the API into logical chunks and correspond to the structure of the GitHub API documentation at -https://developer.github.com/v3/. +https://docs.github.com/rest . -NOTE: Using the https://godoc.org/context package, one can easily +NOTE: Using the https://pkg.go.dev/context package, one can easily pass cancelation signals and deadlines to various services of the client for handling a request. In case there is no context available, then context.Background() can be used as a starting point. For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory. -Authentication +# Authentication -The go-github library does not directly handle authentication. Instead, when -creating a new client, pass an http.Client that can handle authentication for -you. The easiest and recommended way to do this is using the golang.org/x/oauth2 -library, but you can always use any other library that provides an http.Client. -If you have an OAuth2 access token (for example, a personal API token), you can -use it with the oauth2 library using: +Use Client.WithAuthToken to configure your client to authenticate using an Oauth token +(for example, a personal access token). This is what is needed for a majority of use cases +aside from GitHub Apps. - import "golang.org/x/oauth2" - - func main() { - ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: "... your access token ..."}, - ) - tc := oauth2.NewClient(ctx, ts) - - client := github.NewClient(tc) - - // list all repositories for the authenticated user - repos, _, err := client.Repositories.List(ctx, "", nil) - } + client := github.NewClient(nil).WithAuthToken("... your access token ...") Note that when using an authenticated Client, all calls made by the client will include the specified OAuth token. Therefore, authenticated clients should almost never be shared between different users. -See the oauth2 docs for complete instructions on using that library. - For API methods that require HTTP Basic Authentication, use the BasicAuthTransport. GitHub Apps authentication can be provided by the https://github.com/bradleyfalzon/ghinstallation package. +It supports both authentication as an installation, using an installation access token, +and as an app, using a JWT. + +To authenticate as an installation: import "github.com/bradleyfalzon/ghinstallation" @@ -88,7 +75,24 @@ https://github.com/bradleyfalzon/ghinstallation package. // Use client... } -Rate Limiting +To authenticate as an app, using a JWT: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the application ID 1. + atr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use app transport with client + client := github.NewClient(&http.Client{Transport: atr}) + + // Use client... + } + +# Rate Limiting GitHub imposes a rate limit on all API clients. Unauthenticated clients are limited to 60 requests per hour, while authenticated clients can make up to @@ -103,17 +107,21 @@ from the most recent API call. If a recent enough response isn't available, you can use RateLimits to fetch the most up-to-date rate limit data for the client. -To detect an API rate limit error, you can check if its type is *github.RateLimitError: +To detect an API rate limit error, you can check if its type is *github.RateLimitError. +For secondary rate limits, you can check if its type is *github.AbuseRateLimitError: repos, _, err := client.Repositories.List(ctx, "", nil) if _, ok := err.(*github.RateLimitError); ok { log.Println("hit rate limit") } + if _, ok := err.(*github.AbuseRateLimitError); ok { + log.Println("hit secondary rate limit") + } Learn more about GitHub rate limiting at -https://developer.github.com/v3/#rate-limiting. +https://docs.github.com/rest/rate-limit . -Accepted Status +# Accepted Status Some endpoints may return a 202 Accepted status code, meaning that the information required is not yet ready and was scheduled to be gathered on @@ -128,7 +136,7 @@ To detect this condition of error, you can check if its type is log.Println("scheduled on GitHub side") } -Conditional Requests +# Conditional Requests The GitHub API has good support for conditional requests which will help prevent you from burning through your rate limit, as well as help speed up your @@ -137,9 +145,9 @@ instead designed to work with a caching http.Transport. We recommend using https://github.com/gregjones/httpcache for that. Learn more about GitHub conditional requests at -https://developer.github.com/v3/#conditional-requests. +https://docs.github.com/rest/overview/resources-in-the-rest-api#conditional-requests. -Creating and Updating Resources +# Creating and Updating Resources All structs for GitHub resources use pointer values for all non-repeated fields. This allows distinguishing between unset fields and those set to a zero-value. @@ -148,14 +156,14 @@ bool, and int values. For example: // create a new private repository named "foo" repo := &github.Repository{ - Name: github.String("foo"), - Private: github.Bool(true), + Name: github.Ptr("foo"), + Private: github.Ptr(true), } client.Repositories.Create(ctx, "", repo) Users who have worked with protocol buffers should find this pattern familiar. -Pagination +# Pagination All requests for resource collections (repos, pull requests, issues, etc.) support pagination. Pagination options are described in the @@ -182,6 +190,5 @@ github.Response struct. } opt.Page = resp.NextPage } - */ package github diff --git a/vendor/github.com/google/go-github/v68/github/emojis.go b/vendor/github.com/google/go-github/v68/github/emojis.go new file mode 100644 index 00000000..b7a03dd9 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/emojis.go @@ -0,0 +1,40 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// EmojisService provides access to emoji-related functions in the GitHub API. +type EmojisService service + +// List returns the emojis available to use on GitHub. +// +// GitHub API docs: https://docs.github.com/rest/emojis/emojis#get-emojis +// +//meta:operation GET /emojis +func (s *EmojisService) List(ctx context.Context) (map[string]string, *Response, error) { + req, err := s.client.NewRequest("GET", "emojis", nil) + if err != nil { + return nil, nil, err + } + + var emoji map[string]string + resp, err := s.client.Do(ctx, req, &emoji) + if err != nil { + return nil, resp, err + } + + return emoji, resp, nil +} + +// ListEmojis returns the emojis available to use on GitHub. +// +// Deprecated: Use EmojisService.List instead. +func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { + return c.Emojis.List(ctx) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise.go b/vendor/github.com/google/go-github/v68/github/enterprise.go new file mode 100644 index 00000000..2036f8bc --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// EnterpriseService provides access to the enterprise related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/enterprise-admin/ +type EnterpriseService service diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go new file mode 100644 index 00000000..f171df75 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go @@ -0,0 +1,336 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListOrganizations represents the response from the list orgs endpoints. +type ListOrganizations struct { + TotalCount *int `json:"total_count,omitempty"` + Organizations []*Organization `json:"organizations"` +} + +// EnterpriseRunnerGroup represents a self-hosted runner group configured in an enterprise. +type EnterpriseRunnerGroup struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Default *bool `json:"default,omitempty"` + SelectedOrganizationsURL *string `json:"selected_organizations_url,omitempty"` + RunnersURL *string `json:"runners_url,omitempty"` + Inherited *bool `json:"inherited,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` + WorkflowRestrictionsReadOnly *bool `json:"workflow_restrictions_read_only,omitempty"` +} + +// EnterpriseRunnerGroups represents a collection of self-hosted runner groups configured for an enterprise. +type EnterpriseRunnerGroups struct { + TotalCount *int `json:"total_count,omitempty"` + RunnerGroups []*EnterpriseRunnerGroup `json:"runner_groups"` +} + +// CreateEnterpriseRunnerGroupRequest represents a request to create a Runner group for an enterprise. +type CreateEnterpriseRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // List of organization IDs that can access the runner group. + SelectedOrganizationIDs []int64 `json:"selected_organization_ids,omitempty"` + // Runners represent a list of runner IDs to add to the runner group. + Runners []int64 `json:"runners,omitempty"` + // If set to True, public repos can use this runner group + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + // If true, the runner group will be restricted to running only the workflows specified in the SelectedWorkflows slice. + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + // List of workflows the runner group should be allowed to run. This setting will be ignored unless RestrictedToWorkflows is set to true. + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// UpdateEnterpriseRunnerGroupRequest represents a request to update a Runner group for an enterprise. +type UpdateEnterpriseRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` + RestrictedToWorkflows *bool `json:"restricted_to_workflows,omitempty"` + SelectedWorkflows []string `json:"selected_workflows,omitempty"` +} + +// SetOrgAccessRunnerGroupRequest represents a request to replace the list of organizations +// that can access a self-hosted runner group configured in an enterprise. +type SetOrgAccessRunnerGroupRequest struct { + // Updated list of organization IDs that should be given access to the runner group. + SelectedOrganizationIDs []int64 `json:"selected_organization_ids"` +} + +// ListEnterpriseRunnerGroupOptions extend ListOptions to have the optional parameters VisibleToOrganization. +type ListEnterpriseRunnerGroupOptions struct { + ListOptions + + // Only return runner groups that are allowed to be used by this organization. + VisibleToOrganization string `url:"visible_to_organization,omitempty"` +} + +// ListRunnerGroups lists all self-hosted runner groups configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-self-hosted-runner-groups-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups +func (s *EnterpriseService) ListRunnerGroups(ctx context.Context, enterprise string, opts *ListEnterpriseRunnerGroupOptions) (*EnterpriseRunnerGroups, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := &EnterpriseRunnerGroups{} + resp, err := s.client.Do(ctx, req, &groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// GetEnterpriseRunnerGroup gets a specific self-hosted runner group for an enterprise using its RunnerGroup ID. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#get-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) GetEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// DeleteEnterpriseRunnerGroup deletes a self-hosted runner group from an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#delete-a-self-hosted-runner-group-from-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) DeleteEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateEnterpriseRunnerGroup creates a new self-hosted runner group for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#create-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runner-groups +func (s *EnterpriseService) CreateEnterpriseRunnerGroup(ctx context.Context, enterprise string, createReq CreateEnterpriseRunnerGroupRequest) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups", enterprise) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// UpdateEnterpriseRunnerGroup updates a self-hosted runner group for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/actions/runner-groups/{runner_group_id} +func (s *EnterpriseService) UpdateEnterpriseRunnerGroup(ctx context.Context, enterprise string, groupID int64, updateReq UpdateEnterpriseRunnerGroupRequest) (*EnterpriseRunnerGroup, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v", enterprise, groupID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(EnterpriseRunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// ListOrganizationAccessRunnerGroup lists the organizations with access to a self-hosted runner group configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations +func (s *EnterpriseService) ListOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID int64, opts *ListOptions) (*ListOrganizations, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations", enterprise, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := &ListOrganizations{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// SetOrganizationAccessRunnerGroup replaces the list of organizations that have access to a self-hosted runner group configured in an enterprise +// with a new List of organizations. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#set-organization-access-for-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations +func (s *EnterpriseService) SetOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID int64, ids SetOrgAccessRunnerGroupRequest) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations", enterprise, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddOrganizationAccessRunnerGroup adds an organization to the list of selected organizations that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#add-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations/{org_id} +func (s *EnterpriseService) AddOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID, orgID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations/%v", enterprise, groupID, orgID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveOrganizationAccessRunnerGroup removes an organization from the list of selected organizations that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#remove-organization-access-to-a-self-hosted-runner-group-in-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations/{org_id} +func (s *EnterpriseService) RemoveOrganizationAccessRunnerGroup(ctx context.Context, enterprise string, groupID, orgID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/organizations/%v", enterprise, groupID, orgID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListRunnerGroupRunners lists self-hosted runners that are in a specific enterprise group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#list-self-hosted-runners-in-a-group-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners +func (s *EnterpriseService) ListRunnerGroupRunners(ctx context.Context, enterprise string, groupID int64, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners", enterprise, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an enterprise runner group +// with a new list of runners. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#set-self-hosted-runners-in-a-group-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners +func (s *EnterpriseService) SetRunnerGroupRunners(ctx context.Context, enterprise string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners", enterprise, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#add-a-self-hosted-runner-to-a-group-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *EnterpriseService) AddRunnerGroupRunners(ctx context.Context, enterprise string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners/%v", enterprise, groupID, runnerID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an enterprise. +// The runner is then returned to the default group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runner-groups#remove-a-self-hosted-runner-from-a-group-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners/{runner_id} +func (s *EnterpriseService) RemoveRunnerGroupRunners(ctx context.Context, enterprise string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runner-groups/%v/runners/%v", enterprise, groupID, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go new file mode 100644 index 00000000..fa345aea --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go @@ -0,0 +1,139 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#list-runner-applications-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners/downloads +func (s *EnterpriseService) ListRunnerApplicationDownloads(ctx context.Context, enterprise string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/downloads", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// GenerateEnterpriseJITConfig generates a just-in-time configuration for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#create-configuration-for-a-just-in-time-runner-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runners/generate-jitconfig +func (s *EnterpriseService) GenerateEnterpriseJITConfig(ctx context.Context, enterprise string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/generate-jitconfig", enterprise) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + jitConfig := new(JITRunnerConfig) + resp, err := s.client.Do(ctx, req, jitConfig) + if err != nil { + return nil, resp, err + } + + return jitConfig, resp, nil +} + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#create-a-registration-token-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/runners/registration-token +func (s *EnterpriseService) CreateRegistrationToken(ctx context.Context, enterprise string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/registration-token", enterprise) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListRunners lists all the self-hosted runners for a enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners +func (s *EnterpriseService) ListRunners(ctx context.Context, enterprise string, opts *ListRunnersOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetRunner gets a specific self-hosted runner configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/runners/{runner_id} +func (s *EnterpriseService) GetRunner(ctx context.Context, enterprise string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner from an enterprise using the runner id. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/runners/{runner_id} +func (s *EnterpriseService) RemoveRunner(ctx context.Context, enterprise string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go b/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go new file mode 100644 index 00000000..058a7d17 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go @@ -0,0 +1,37 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/audit-log#get-the-audit-log-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/audit-log +func (s *EnterpriseService) GetAuditLog(ctx context.Context, enterprise string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("enterprises/%v/audit-log", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go b/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go new file mode 100644 index 00000000..159aeae4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go @@ -0,0 +1,85 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// EnterpriseSecurityAnalysisSettings represents security analysis settings for an enterprise. +type EnterpriseSecurityAnalysisSettings struct { + AdvancedSecurityEnabledForNewRepositories *bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` + SecretScanningEnabledForNewRepositories *bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` + SecretScanningPushProtectionEnabledForNewRepositories *bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` + SecretScanningPushProtectionCustomLink *string `json:"secret_scanning_push_protection_custom_link,omitempty"` + SecretScanningValidityChecksEnabled *bool `json:"secret_scanning_validity_checks_enabled,omitempty"` +} + +// GetCodeSecurityAndAnalysis gets code security and analysis features for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#get-code-security-and-analysis-features-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/code_security_and_analysis +func (s *EnterpriseService) GetCodeSecurityAndAnalysis(ctx context.Context, enterprise string) (*EnterpriseSecurityAnalysisSettings, *Response, error) { + u := fmt.Sprintf("enterprises/%v/code_security_and_analysis", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + settings := new(EnterpriseSecurityAnalysisSettings) + resp, err := s.client.Do(ctx, req, settings) + if err != nil { + return nil, resp, err + } + + return settings, resp, nil +} + +// UpdateCodeSecurityAndAnalysis updates code security and analysis features for new repositories in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#update-code-security-and-analysis-features-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/code_security_and_analysis +func (s *EnterpriseService) UpdateCodeSecurityAndAnalysis(ctx context.Context, enterprise string, settings *EnterpriseSecurityAnalysisSettings) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/code_security_and_analysis", enterprise) + req, err := s.client.NewRequest("PATCH", u, settings) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// EnableDisableSecurityFeature enables or disables a security feature for all repositories in an enterprise. +// +// Valid values for securityProduct: "advanced_security", "secret_scanning", "secret_scanning_push_protection". +// Valid values for enablement: "enable_all", "disable_all". +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/code-security-and-analysis#enable-or-disable-a-security-feature +// +//meta:operation POST /enterprises/{enterprise}/{security_product}/{enablement} +func (s *EnterpriseService) EnableDisableSecurityFeature(ctx context.Context, enterprise, securityProduct, enablement string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/%v/%v", enterprise, securityProduct, enablement) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_properties.go b/vendor/github.com/google/go-github/v68/github/enterprise_properties.go new file mode 100644 index 00000000..bc5ab55a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/enterprise_properties.go @@ -0,0 +1,121 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllCustomProperties gets all custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-custom-properties-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) GetAllCustomProperties(ctx context.Context, enterprise string) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-custom-properties-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) CreateOrUpdateCustomProperties(ctx context.Context, enterprise string, properties []*CustomProperty) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + params := struct { + Properties []*CustomProperty `json:"properties"` + }{ + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// GetCustomProperty gets a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-a-custom-property-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) GetCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// CreateOrUpdateCustomProperty creates a new or updates an existing custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-a-custom-property-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) CreateOrUpdateCustomProperty(ctx context.Context, enterprise, customPropertyName string, property *CustomProperty) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("PUT", u, property) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// RemoveCustomProperty removes a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#remove-a-custom-property-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) RemoveCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/event.go b/vendor/github.com/google/go-github/v68/github/event.go new file mode 100644 index 00000000..e98606bc --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/event.go @@ -0,0 +1,54 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" +) + +// Event represents a GitHub event. +type Event struct { + Type *string `json:"type,omitempty"` + Public *bool `json:"public,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` + Repo *Repository `json:"repo,omitempty"` + Actor *User `json:"actor,omitempty"` + Org *Organization `json:"org,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ID *string `json:"id,omitempty"` +} + +func (e Event) String() string { + return Stringify(e) +} + +// ParsePayload parses the event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (e *Event) ParsePayload() (interface{}, error) { + // It would be nice if e.Type were the snake_case name of the event, + // but the existing interface uses the struct name instead. + payload := EventForType(typeToMessageMapping[e.GetType()]) + + if err := json.Unmarshal(e.GetRawPayload(), &payload); err != nil { + return nil, err + } + + return payload, nil +} + +// Payload returns the parsed event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +// +// Deprecated: Use ParsePayload instead, which returns an error +// rather than panics if JSON unmarshaling raw payload fails. +func (e *Event) Payload() (payload interface{}) { + var err error + payload, err = e.ParsePayload() + if err != nil { + panic(err) + } + return payload +} diff --git a/vendor/github.com/google/go-github/v68/github/event_types.go b/vendor/github.com/google/go-github/v68/github/event_types.go new file mode 100644 index 00000000..37e62c2f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/event_types.go @@ -0,0 +1,1928 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// These event types are shared between the Events API and used as Webhook payloads. + +package github + +import "encoding/json" + +// RequestedAction is included in a CheckRunEvent when a user has invoked an action, +// i.e. when the CheckRunEvent's Action field is "requested_action". +type RequestedAction struct { + Identifier string `json:"identifier"` // The integrator reference of the action requested by the user. +} + +// BranchProtectionRuleEvent triggered when a check suite is "created", "edited", or "deleted". +// The Webhook event name is "branch_protection_rule". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_rule +type BranchProtectionRuleEvent struct { + Action *string `json:"action,omitempty"` + Rule *BranchProtectionRule `json:"rule,omitempty"` + Changes *ProtectionChanges `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// BranchProtectionConfigurationEvent is triggered when there is a change to branch protection configurations for a repository. +// The Webhook event name is "branch_protection_configuration". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_configuration +type BranchProtectionConfigurationEvent struct { + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CheckRunEvent is triggered when a check run is "created", "completed", or "rerequested". +// The Webhook event name is "check_run". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#check_run +type CheckRunEvent struct { + CheckRun *CheckRun `json:"check_run,omitempty"` + // The action performed. Possible values are: "created", "completed", "rerequested" or "requested_action". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The action requested by the user. Populated when the Action is "requested_action". + RequestedAction *RequestedAction `json:"requested_action,omitempty"` // +} + +// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested". +// The Webhook event name is "check_suite". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#check_suite +type CheckSuiteEvent struct { + CheckSuite *CheckSuite `json:"check_suite,omitempty"` + // The action performed. Possible values are: "completed", "requested" or "rerequested". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CommitCommentEvent is triggered when a commit comment is created. +// The Webhook event name is "commit_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#commit_comment +type CommitCommentEvent struct { + Comment *RepositoryComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// ContentReferenceEvent is triggered when the body or comment of an issue or +// pull request includes a URL that matches a configured content reference +// domain. +// The Webhook event name is "content_reference". +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#content_reference +type ContentReferenceEvent struct { + Action *string `json:"action,omitempty"` + ContentReference *ContentReference `json:"content_reference,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CreateEvent represents a created repository, branch, or tag. +// The Webhook event name is "create". +// +// Note: webhooks will not receive this event for created repositories. +// Additionally, webhooks will not receive this event for tags if more +// than three tags are pushed at once. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#createevent +type CreateEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was created. Possible values are: "repository", "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Description *string `json:"description,omitempty"` + PusherType *string `json:"pusher_type,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CustomPropertyEvent represents a created, deleted or updated custom property. +// The Webhook event name is "custom_property". +// +// Note: this is related to custom property configuration at the enterprise or organization level. +// See CustomPropertyValuesEvent for activity related to custom property values for a repository. +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#custom_property +type CustomPropertyEvent struct { + // Action possible values are: "created", "deleted", "updated". + Action *string `json:"action,omitempty"` + Definition *CustomProperty `json:"definition,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// CustomPropertyValuesEvent represents an update to a custom property. +// The Webhook event name is "custom_property_values". +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#custom_property_values +type CustomPropertyValuesEvent struct { + // Action possible values are: "updated". + Action *string `json:"action,omitempty"` + NewPropertyValues []*CustomPropertyValue `json:"new_property_values,omitempty"` + OldPropertyValues []*CustomPropertyValue `json:"old_property_values,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// DeleteEvent represents a deleted branch or tag. +// The Webhook event name is "delete". +// +// Note: webhooks will not receive this event for tags if more than three tags +// are deleted at once. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#deleteevent +type DeleteEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was deleted. Possible values are: "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DependabotAlertEvent is triggered when there is activity relating to Dependabot alerts. +// The Webhook event name is "dependabot_alert". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#dependabot_alert +type DependabotAlertEvent struct { + Action *string `json:"action,omitempty"` + Alert *DependabotAlert `json:"alert,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// DeployKeyEvent is triggered when a deploy key is added or removed from a repository. +// The Webhook event name is "deploy_key". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deploy_key +type DeployKeyEvent struct { + // Action is the action that was performed. Possible values are: + // "created" or "deleted". + Action *string `json:"action,omitempty"` + + // The deploy key resource. + Key *Key `json:"key,omitempty"` + + // The Repository where the event occurred + Repo *Repository `json:"repository,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentEvent represents a deployment. +// The Webhook event name is "deployment". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deployment +type DeploymentEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DeploymentProtectionRuleEvent represents a deployment protection rule event. +// The Webhook event name is "deployment_protection_rule". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#deployment_protection_rule +type DeploymentProtectionRuleEvent struct { + Action *string `json:"action,omitempty"` + Environment *string `json:"environment,omitempty"` + Event *string `json:"event,omitempty"` + + // The URL Github provides for a third-party to use in order to pass/fail a deployment gate + DeploymentCallbackURL *string `json:"deployment_callback_url,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentReviewEvent represents a deployment review event. +// The Webhook event name is "deployment_review". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads?#deployment_review +type DeploymentReviewEvent struct { + // The action performed. Possible values are: "requested", "approved", or "rejected". + Action *string `json:"action,omitempty"` + + // The following will be populated only if requested. + Requester *User `json:"requester,omitempty"` + Environment *string `json:"environment,omitempty"` + + // The following will be populated only if approved or rejected. + Approver *User `json:"approver,omitempty"` + Comment *string `json:"comment,omitempty"` + WorkflowJobRuns []*WorkflowJobRun `json:"workflow_job_runs,omitempty"` + + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` + Sender *User `json:"sender,omitempty"` + Since *string `json:"since,omitempty"` + WorkflowJobRun *WorkflowJobRun `json:"workflow_job_run,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` +} + +// WorkflowJobRun represents a workflow_job_run in a GitHub DeploymentReviewEvent. +type WorkflowJobRun struct { + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Environment *string `json:"environment,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// DeploymentStatusEvent represents a deployment status. +// The Webhook event name is "deployment_status". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#deployment_status +type DeploymentStatusEvent struct { + Action *string `json:"action,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` + DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// DiscussionCommentEvent represents a webhook event for a comment on discussion. +// The Webhook event name is "discussion_comment". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#discussion_comment +type DiscussionCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". ** check what all can be added + Action *string `json:"action,omitempty"` + Discussion *Discussion `json:"discussion,omitempty"` + Comment *CommentDiscussion `json:"comment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CommentDiscussion represents a comment in a GitHub DiscussionCommentEvent. +type CommentDiscussion struct { + AuthorAssociation *string `json:"author_association,omitempty"` + Body *string `json:"body,omitempty"` + ChildCommentCount *int `json:"child_comment_count,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + DiscussionID *int64 `json:"discussion_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + ParentID *int64 `json:"parent_id,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + User *User `json:"user,omitempty"` +} + +// DiscussionEvent represents a webhook event for a discussion. +// The Webhook event name is "discussion". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#discussion +type DiscussionEvent struct { + // Action is the action that was performed. Possible values are: + // created, edited, deleted, pinned, unpinned, locked, unlocked, + // transferred, category_changed, answered, or unanswered. + Action *string `json:"action,omitempty"` + Discussion *Discussion `json:"discussion,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Discussion represents a discussion in a GitHub DiscussionEvent. +type Discussion struct { + RepositoryURL *string `json:"repository_url,omitempty"` + DiscussionCategory *DiscussionCategory `json:"category,omitempty"` + AnswerHTMLURL *string `json:"answer_html_url,omitempty"` + AnswerChosenAt *Timestamp `json:"answer_chosen_at,omitempty"` + AnswerChosenBy *string `json:"answer_chosen_by,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Title *string `json:"title,omitempty"` + User *User `json:"user,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Comments *int `json:"comments,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + ActiveLockReason *string `json:"active_lock_reason,omitempty"` + Body *string `json:"body,omitempty"` +} + +// DiscussionCategory represents a discussion category in a GitHub DiscussionEvent. +type DiscussionCategory struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Emoji *string `json:"emoji,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Slug *string `json:"slug,omitempty"` + IsAnswerable *bool `json:"is_answerable,omitempty"` +} + +// ForkEvent is triggered when a user forks a repository. +// The Webhook event name is "fork". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#fork +type ForkEvent struct { + // Forkee is the created repository. + Forkee *Repository `json:"forkee,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// GitHubAppAuthorizationEvent is triggered when a user's authorization for a +// GitHub Application is revoked. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#github_app_authorization +type GitHubAppAuthorizationEvent struct { + // The action performed. Possible value is: "revoked". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Page represents a single Wiki page. +type Page struct { + PageName *string `json:"page_name,omitempty"` + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Action *string `json:"action,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// GollumEvent is triggered when a Wiki page is created or updated. +// The Webhook event name is "gollum". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#gollum +type GollumEvent struct { + Pages []*Page `json:"pages,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// EditChange represents the changes when an issue, pull request, comment, +// or repository has been edited. +type EditChange struct { + Title *EditTitle `json:"title,omitempty"` + Body *EditBody `json:"body,omitempty"` + Base *EditBase `json:"base,omitempty"` + Repo *EditRepo `json:"repository,omitempty"` + Owner *EditOwner `json:"owner,omitempty"` + DefaultBranch *EditDefaultBranch `json:"default_branch,omitempty"` + Topics *EditTopics `json:"topics,omitempty"` +} + +// EditTitle represents a pull-request title change. +type EditTitle struct { + From *string `json:"from,omitempty"` +} + +// EditBody represents a change of pull-request body. +type EditBody struct { + From *string `json:"from,omitempty"` +} + +// EditBase represents the change of a pull-request base branch. +type EditBase struct { + Ref *EditRef `json:"ref,omitempty"` + SHA *EditSHA `json:"sha,omitempty"` +} + +// EditRef represents a ref change of a pull-request. +type EditRef struct { + From *string `json:"from,omitempty"` +} + +// EditRepo represents a change of repository name. +type EditRepo struct { + Name *RepoName `json:"name,omitempty"` +} + +// EditOwner represents a change of repository ownership. +type EditOwner struct { + OwnerInfo *OwnerInfo `json:"from,omitempty"` +} + +// OwnerInfo represents the account info of the owner of the repo (could be User or Organization but both are User structs). +type OwnerInfo struct { + User *User `json:"user,omitempty"` + Org *User `json:"organization,omitempty"` +} + +// RepoName represents a change of repository name. +type RepoName struct { + From *string `json:"from,omitempty"` +} + +// EditTopics represents a change of repository topics. +type EditTopics struct { + From []string `json:"from,omitempty"` +} + +// EditSHA represents a sha change of a pull-request. +type EditSHA struct { + From *string `json:"from,omitempty"` +} + +// EditDefaultBranch represents a change of repository's default branch name. +type EditDefaultBranch struct { + From *string `json:"from,omitempty"` +} + +// ProjectChange represents the changes when a project has been edited. +type ProjectChange struct { + Name *ProjectName `json:"name,omitempty"` + Body *ProjectBody `json:"body,omitempty"` +} + +// ProjectName represents a project name change. +type ProjectName struct { + From *string `json:"from,omitempty"` +} + +// ProjectBody represents a project body change. +type ProjectBody struct { + From *string `json:"from,omitempty"` +} + +// ProjectCardChange represents the changes when a project card has been edited. +type ProjectCardChange struct { + Note *ProjectCardNote `json:"note,omitempty"` +} + +// ProjectCardNote represents a change of a note of a project card. +type ProjectCardNote struct { + From *string `json:"from,omitempty"` +} + +// ProjectColumnChange represents the changes when a project column has been edited. +type ProjectColumnChange struct { + Name *ProjectColumnName `json:"name,omitempty"` +} + +// ProjectColumnName represents a project column name change. +type ProjectColumnName struct { + From *string `json:"from,omitempty"` +} + +// TeamChange represents the changes when a team has been edited. +type TeamChange struct { + Description *TeamDescription `json:"description,omitempty"` + Name *TeamName `json:"name,omitempty"` + Privacy *TeamPrivacy `json:"privacy,omitempty"` + Repository *TeamRepository `json:"repository,omitempty"` +} + +// TeamDescription represents a team description change. +type TeamDescription struct { + From *string `json:"from,omitempty"` +} + +// TeamName represents a team name change. +type TeamName struct { + From *string `json:"from,omitempty"` +} + +// TeamPrivacy represents a team privacy change. +type TeamPrivacy struct { + From *string `json:"from,omitempty"` +} + +// TeamRepository represents a team repository permission change. +type TeamRepository struct { + Permissions *TeamPermissions `json:"permissions,omitempty"` +} + +// TeamPermissions represents a team permission change. +type TeamPermissions struct { + From *TeamPermissionsFrom `json:"from,omitempty"` +} + +// TeamPermissionsFrom represents a team permission change. +type TeamPermissionsFrom struct { + Admin *bool `json:"admin,omitempty"` + Pull *bool `json:"pull,omitempty"` + Push *bool `json:"push,omitempty"` +} + +// InstallationEvent is triggered when a GitHub App has been installed, uninstalled, suspend, unsuspended +// or new permissions have been accepted. +// The Webhook event name is "installation". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#installation +type InstallationEvent struct { + // The action that was performed. Can be either "created", "deleted", "suspend", "unsuspend" or "new_permissions_accepted". + Action *string `json:"action,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Requester *User `json:"requester,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// InstallationRepositoriesEvent is triggered when a repository is added or +// removed from an installation. The Webhook event name is "installation_repositories". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#installation_repositories +type InstallationRepositoriesEvent struct { + // The action that was performed. Can be either "added" or "removed". + Action *string `json:"action,omitempty"` + RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` + RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// InstallationLoginChange represents a change in login on an installation. +type InstallationLoginChange struct { + From *string `json:"from,omitempty"` +} + +// InstallationSlugChange represents a change in slug on an installation. +type InstallationSlugChange struct { + From *string `json:"from,omitempty"` +} + +// InstallationChanges represents a change in slug or login on an installation. +type InstallationChanges struct { + Login *InstallationLoginChange `json:"login,omitempty"` + Slug *InstallationSlugChange `json:"slug,omitempty"` +} + +// InstallationTargetEvent is triggered when there is activity on an installation from a user or organization account. +// The Webhook event name is "installation_target". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#installation_target +type InstallationTargetEvent struct { + Account *User `json:"account,omitempty"` + Action *string `json:"action,omitempty"` + Changes *InstallationChanges `json:"changes,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + TargetType *string `json:"target_type,omitempty"` +} + +// IssueCommentEvent is triggered when an issue comment is created on an issue +// or pull request. +// The Webhook event name is "issue_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment +type IssueCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Comment *IssueComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// IssuesEvent is triggered when an issue is opened, edited, deleted, transferred, +// pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, +// locked, unlocked, milestoned, or demilestoned. +// The Webhook event name is "issues". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#issues +type IssuesEvent struct { + // Action is the action that was performed. Possible values are: "opened", + // "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", + // "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", + // "milestoned", or "demilestoned". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// LabelEvent is triggered when a repository's label is created, edited, or deleted. +// The Webhook event name is "label" +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#label +type LabelEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "edited", "deleted" + Action *string `json:"action,omitempty"` + Label *Label `json:"label,omitempty"` + Changes *EditChange `json:"changes,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes +// their GitHub Marketplace plan. +// Webhook event name "marketplace_purchase". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#marketplace_purchase +type MarketplacePurchaseEvent struct { + // Action is the action that was performed. Possible values are: + // "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// MemberChangesPermission represents changes to a repository collaborator's permissions. +type MemberChangesPermission struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +// MemberChangesRoleName represents changes to a repository collaborator's role. +type MemberChangesRoleName struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +// MemberChanges represents changes to a repository collaborator's role or permission. +type MemberChanges struct { + Permission *MemberChangesPermission `json:"permission,omitempty"` + RoleName *MemberChangesRoleName `json:"role_name,omitempty"` +} + +// MemberEvent is triggered when a user's membership as a collaborator to a repository changes. +// The Webhook event name is "member". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#member +type MemberEvent struct { + // Action is the action that was performed. Possible values are: "added", "edited", "removed". + Action *string `json:"action,omitempty"` + Member *User `json:"member,omitempty"` + Changes *MemberChanges `json:"changes,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// MembershipEvent is triggered when a user is added or removed from a team. +// The Webhook event name is "membership". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#membership +type MembershipEvent struct { + // Action is the action that was performed. Possible values are: "added", "removed". + Action *string `json:"action,omitempty"` + // Scope is the scope of the membership. Possible value is: "team". + Scope *string `json:"scope,omitempty"` + Member *User `json:"member,omitempty"` + Team *Team `json:"team,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MergeGroup represents the merge group in a merge queue. +type MergeGroup struct { + // The SHA of the merge group. + HeadSHA *string `json:"head_sha,omitempty"` + // The full ref of the merge group. + HeadRef *string `json:"head_ref,omitempty"` + // The SHA of the merge group's parent commit. + BaseSHA *string `json:"base_sha,omitempty"` + // The full ref of the branch the merge group will be merged into. + BaseRef *string `json:"base_ref,omitempty"` + // An expanded representation of the head_sha commit. + HeadCommit *Commit `json:"head_commit,omitempty"` +} + +// MergeGroupEvent represents activity related to merge groups in a merge queue. The type of activity is specified +// in the action property of the payload object. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#merge_group +type MergeGroupEvent struct { + // The action that was performed. Currently, can only be checks_requested. + Action *string `json:"action,omitempty"` + // The merge group. + MergeGroup *MergeGroup `json:"merge_group,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// MetaEvent is triggered when the webhook that this event is configured on is deleted. +// This event will only listen for changes to the particular hook the event is installed on. +// Therefore, it must be selected for each hook that you'd like to receive meta events for. +// The Webhook event name is "meta". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#meta +type MetaEvent struct { + // Action is the action that was performed. Possible value is: "deleted". + Action *string `json:"action,omitempty"` + // The ID of the modified webhook. + HookID *int64 `json:"hook_id,omitempty"` + // The modified webhook. + // This will contain different keys based on the type of webhook it is: repository, + // organization, business, app, or GitHub Marketplace. + Hook *Hook `json:"hook,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. +// The Webhook event name is "milestone". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#milestone +type MilestoneEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "closed", "opened", "edited", "deleted" + Action *string `json:"action,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added, +// removed, or invited to an organization. +// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. +// Webhook event name is "organization". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#organization +type OrganizationEvent struct { + // Action is the action that was performed. + // Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited". + Action *string `json:"action,omitempty"` + + // Invitation is the invitation for the user or email if the action is "member_invited". + Invitation *Invitation `json:"invitation,omitempty"` + + // Membership is the membership between the user and the organization. + // Not present when the action is "member_invited". + Membership *Membership `json:"membership,omitempty"` + + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrgBlockEvent is triggered when an organization blocks or unblocks a user. +// The Webhook event name is "org_block". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#org_block +type OrgBlockEvent struct { + // Action is the action that was performed. + // Can be "blocked" or "unblocked". + Action *string `json:"action,omitempty"` + BlockedUser *User `json:"blocked_user,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PackageEvent represents activity related to GitHub Packages. +// The Webhook event name is "package". +// +// This event is triggered when a GitHub Package is published or updated. +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#package +type PackageEvent struct { + // Action is the action that was performed. + // Can be "published" or "updated". + Action *string `json:"action,omitempty"` + Package *Package `json:"package,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PageBuildEvent represents an attempted build of a GitHub Pages site, whether +// successful or not. +// The Webhook event name is "page_build". +// +// This event is triggered on push to a GitHub Pages enabled branch (gh-pages +// for project pages, master for user and organization pages). +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#page_build +type PageBuildEvent struct { + Build *PagesBuild `json:"build,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PersonalAccessTokenRequestEvent occurs when there is activity relating to a +// request for a fine-grained personal access token to access resources that +// belong to a resource owner that requires approval for token access. +// The webhook event name is "personal_access_token_request". +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#personal_access_token_request +type PersonalAccessTokenRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "approved", "cancelled", "created" or "denied" + Action *string `json:"action,omitempty"` + PersonalAccessTokenRequest *PersonalAccessTokenRequest `json:"personal_access_token_request,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PersonalAccessTokenRequest contains the details of a PersonalAccessTokenRequestEvent. +type PersonalAccessTokenRequest struct { + // Unique identifier of the request for access via fine-grained personal + // access token. Used as the pat_request_id parameter in the list and review + // API calls. + ID *int64 `json:"id,omitempty"` + Owner *User `json:"owner,omitempty"` + + // New requested permissions, categorized by type of permission. + PermissionsAdded *PersonalAccessTokenPermissions `json:"permissions_added,omitempty"` + + // Requested permissions that elevate access for a previously approved + // request for access, categorized by type of permission. + PermissionsUpgraded *PersonalAccessTokenPermissions `json:"permissions_upgraded,omitempty"` + + // Permissions requested, categorized by type of permission. + // This field incorporates permissions_added and permissions_upgraded. + PermissionsResult *PersonalAccessTokenPermissions `json:"permissions_result,omitempty"` + + // Type of repository selection requested. Possible values are: + // "none", "all" or "subset" + RepositorySelection *string `json:"repository_selection,omitempty"` + + // The number of repositories the token is requesting access to. + // This field is only populated when repository_selection is subset. + RepositoryCount *int64 `json:"repository_count,omitempty"` + + // An array of repository objects the token is requesting access to. + // This field is only populated when repository_selection is subset. + Repositories []*Repository `json:"repositories,omitempty"` + + // Date and time when the request for access was created. + CreatedAt *Timestamp `json:"created_at,omitempty"` + + // Whether the associated fine-grained personal access token has expired. + TokenExpired *bool `json:"token_expired,omitempty"` + + // Date and time when the associated fine-grained personal access token expires. + TokenExpiresAt *Timestamp `json:"token_expires_at,omitempty"` + + // Date and time when the associated fine-grained personal access token was last used for authentication. + TokenLastUsedAt *Timestamp `json:"token_last_used_at,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PersonalAccessTokenPermissions represents the original or newly requested +// scope of permissions for a fine-grained personal access token within a PersonalAccessTokenRequest. +type PersonalAccessTokenPermissions struct { + Org map[string]string `json:"organization,omitempty"` + Repo map[string]string `json:"repository,omitempty"` + Other map[string]string `json:"other,omitempty"` +} + +// PingEvent is triggered when a Webhook is added to GitHub. +// +// GitHub API docs: https://developer.github.com/webhooks/#ping-event +type PingEvent struct { + // Random string of GitHub zen. + Zen *string `json:"zen,omitempty"` + // The ID of the webhook that triggered the ping. + HookID *int64 `json:"hook_id,omitempty"` + // The webhook configuration. + Hook *Hook `json:"hook,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectV2Event is triggered when there is activity relating to an organization-level project. +// The Webhook event name is "projects_v2". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2 +type ProjectV2Event struct { + Action *string `json:"action,omitempty"` + ProjectsV2 *ProjectV2 `json:"projects_v2,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// ProjectV2 represents a v2 project. +type ProjectV2 struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Creator *User `json:"creator,omitempty"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + Public *bool `json:"public,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + DeletedAt *Timestamp `json:"deleted_at,omitempty"` + Number *int `json:"number,omitempty"` + ShortDescription *string `json:"short_description,omitempty"` + DeletedBy *User `json:"deleted_by,omitempty"` + + // Fields migrated from the Project (classic) struct: + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ColumnsURL *string `json:"columns_url,omitempty"` + OwnerURL *string `json:"owner_url,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + OrganizationPermission *string `json:"organization_permission,omitempty"` + Private *bool `json:"private,omitempty"` +} + +// ProjectV2ItemEvent is triggered when there is activity relating to an item on an organization-level project. +// The Webhook event name is "projects_v2_item". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2_item +type ProjectV2ItemEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectV2ItemChange `json:"changes,omitempty"` + ProjectV2Item *ProjectV2Item `json:"projects_v2_item,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// ProjectV2ItemChange represents a project v2 item change. +type ProjectV2ItemChange struct { + ArchivedAt *ArchivedAt `json:"archived_at,omitempty"` +} + +// ArchivedAt represents an archiving date change. +type ArchivedAt struct { + From *Timestamp `json:"from,omitempty"` + To *Timestamp `json:"to,omitempty"` +} + +// ProjectV2Item represents an item belonging to a project. +type ProjectV2Item struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + ProjectNodeID *string `json:"project_node_id,omitempty"` + ContentNodeID *string `json:"content_node_id,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ArchivedAt *Timestamp `json:"archived_at,omitempty"` +} + +// PublicEvent is triggered when a private repository is open sourced. +// According to GitHub: "Without a doubt: the best GitHub event." +// The Webhook event name is "public". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#public +type PublicEvent struct { + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/github-event-types#pullrequestevent +type PullRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", + // "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` + + // The following will be populated if the event was performed by an App + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// PullRequestReviewEvent is triggered when a review is submitted on a pull +// request. +// The Webhook event name is "pull_request_review". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review +type PullRequestReviewEvent struct { + // Action is always "submitted". + Action *string `json:"action,omitempty"` + Review *PullRequestReview `json:"review,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewCommentEvent is triggered when a comment is created on a +// portion of the unified diff of a pull request. +// The Webhook event name is "pull_request_review_comment". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_comment +type PullRequestReviewCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + Comment *PullRequestComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewThreadEvent is triggered when a comment made as part of a +// review of a pull request is marked resolved or unresolved. +// The Webhook event name is "pull_request_review_thread". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_thread +type PullRequestReviewThreadEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "resolved", "unresolved". + Action *string `json:"action,omitempty"` + Thread *PullRequestThread `json:"thread,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// PullRequestTargetEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request_target". +// +// GitHub API docs: https://docs.github.com/actions/events-that-trigger-workflows#pull_request_target +type PullRequestTargetEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "labeled", "unlabeled", "opened", "edited", "closed", "reopened", + // "ready_for_review", "locked", "unlocked", "review_requested" or "review_request_removed". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` + + // The following will be populated if the event was performed by an App + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// PushEvent represents a git push to a GitHub repository. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#push +type PushEvent struct { + PushID *int64 `json:"push_id,omitempty"` + Head *string `json:"head,omitempty"` + Ref *string `json:"ref,omitempty"` + Size *int `json:"size,omitempty"` + Commits []*HeadCommit `json:"commits,omitempty"` + Before *string `json:"before,omitempty"` + DistinctSize *int `json:"distinct_size,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + After *string `json:"after,omitempty"` + Created *bool `json:"created,omitempty"` + Deleted *bool `json:"deleted,omitempty"` + Forced *bool `json:"forced,omitempty"` + BaseRef *string `json:"base_ref,omitempty"` + Compare *string `json:"compare,omitempty"` + Repo *PushEventRepository `json:"repository,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + Pusher *CommitAuthor `json:"pusher,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +func (p PushEvent) String() string { + return Stringify(p) +} + +// HeadCommit represents a git commit in a GitHub PushEvent. +type HeadCommit struct { + Message *string `json:"message,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + URL *string `json:"url,omitempty"` + Distinct *bool `json:"distinct,omitempty"` + + // The following fields are only populated by Events API. + SHA *string `json:"sha,omitempty"` + + // The following fields are only populated by Webhook events. + ID *string `json:"id,omitempty"` + TreeID *string `json:"tree_id,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Added []string `json:"added,omitempty"` + Removed []string `json:"removed,omitempty"` + Modified []string `json:"modified,omitempty"` +} + +func (h HeadCommit) String() string { + return Stringify(h) +} + +// PushEventRepository represents the repo object in a PushEvent payload. +type PushEventRepository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Owner *User `json:"owner,omitempty"` + Private *bool `json:"private,omitempty"` + Description *string `json:"description,omitempty"` + Fork *bool `json:"fork,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Homepage *string `json:"homepage,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + Size *int `json:"size,omitempty"` + StargazersCount *int `json:"stargazers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` + Language *string `json:"language,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Organization *string `json:"organization,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Topics []string `json:"topics,omitempty"` + CustomProperties map[string]interface{} `json:"custom_properties,omitempty"` +} + +// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. +type PushEventRepoOwner struct { + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ReleaseEvent is triggered when a release is published, unpublished, created, +// edited, deleted, or prereleased. +// The Webhook event name is "release". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#release +type ReleaseEvent struct { + // Action is the action that was performed. Possible values are: "published", "unpublished", + // "created", "edited", "deleted", or "prereleased". + Action *string `json:"action,omitempty"` + Release *RepositoryRelease `json:"release,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// RepositoryEvent is triggered when a repository is created, archived, unarchived, +// renamed, edited, transferred, made public, or made private. Organization hooks are +// also triggered when a repository is deleted. +// The Webhook event name is "repository". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository +type RepositoryEvent struct { + // Action is the action that was performed. Possible values are: "created", + // "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed", + // "transferred", "publicized", or "privatized". + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryDispatchEvent is triggered when a client sends a POST request to the repository dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository_dispatch +type RepositoryDispatchEvent struct { + // Action is the event_type that submitted with the repository dispatch payload. Value can be any string. + Action *string `json:"action,omitempty"` + Branch *string `json:"branch,omitempty"` + ClientPayload json.RawMessage `json:"client_payload,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryImportEvent represents the activity related to a repository being imported to GitHub. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#repository_import +type RepositoryImportEvent struct { + // Status represents the final state of the import. This can be one of "success", "cancelled", or "failure". + Status *string `json:"status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// RepositoryRulesetEvent triggers whenever there is a change to the repository's ruleset configuration. +// +// This can include updates to protection rules, required status checks, code owners, or other related configurations. +// +// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#repository_ruleset +type RepositoryRulesetEvent struct { + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RepositoryRuleset *RepositoryRuleset `json:"repository_ruleset"` + Changes *RepositoryRulesetEditedChanges `json:"changes,omitempty"` + Sender *User `json:"sender"` +} + +// RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#repository_vulnerability_alert +type RepositoryVulnerabilityAlertEvent struct { + // Action is the action that was performed. Possible values are: "create", "dismiss", "resolve". + Action *string `json:"action,omitempty"` + + // The security alert of the vulnerable dependency. + Alert *RepositoryVulnerabilityAlert `json:"alert,omitempty"` + + // The repository of the vulnerable dependency. + Repository *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + + // The user that triggered the event. + Sender *User `json:"sender,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// RepositoryVulnerabilityAlert represents a repository security alert. +type RepositoryVulnerabilityAlert struct { + ID *int64 `json:"id,omitempty"` + AffectedRange *string `json:"affected_range,omitempty"` + AffectedPackageName *string `json:"affected_package_name,omitempty"` + ExternalReference *string `json:"external_reference,omitempty"` + ExternalIdentifier *string `json:"external_identifier,omitempty"` + GitHubSecurityAdvisoryID *string `json:"ghsa_id,omitempty"` + Severity *string `json:"severity,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + FixedIn *string `json:"fixed_in,omitempty"` + Dismisser *User `json:"dismisser,omitempty"` + DismissReason *string `json:"dismiss_reason,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` +} + +// SecretScanningAlertEvent is triggered when a secret scanning alert occurs in a repository. +// The Webhook name is secret_scanning_alert. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert +type SecretScanningAlertEvent struct { + // Action is the action that was performed. Possible values are: "created", "resolved", or "reopened". + Action *string `json:"action,omitempty"` + + // Alert is the secret scanning alert involved in the event. + Alert *SecretScanningAlert `json:"alert,omitempty"` + + // Only populated by the "resolved" and "reopen" actions + Sender *User `json:"sender,omitempty"` + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SecretScanningAlertLocationEvent is triggered when there is activity relating to the locations of a secret in a secret scanning alert. +// The Webhook event name is "secret_scanning_alert_location". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert_location +type SecretScanningAlertLocationEvent struct { + Action *string `json:"action,omitempty"` + Alert *SecretScanningAlert `json:"alert,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Location *SecretScanningAlertLocation `json:"location,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// SecurityAndAnalysisEvent is triggered when code security and analysis features +// are enabled or disabled for a repository. +// +// GitHub API docs: https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#security_and_analysis +type SecurityAndAnalysisEvent struct { + Changes *SecurityAndAnalysisChange `json:"changes,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// SecurityAndAnalysisChange represents the changes when security and analysis +// features are enabled or disabled for a repository. +type SecurityAndAnalysisChange struct { + From *SecurityAndAnalysisChangeFrom `json:"from,omitempty"` +} + +// SecurityAndAnalysisChangeFrom represents which change was made when security +// and analysis features are enabled or disabled for a repository. +type SecurityAndAnalysisChangeFrom struct { + SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` +} + +// StarEvent is triggered when a star is added or removed from a repository. +// The Webhook event name is "star". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#star +type StarEvent struct { + // Action is the action that was performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + + // StarredAt is the time the star was created. It will be null for the "deleted" action. + StarredAt *Timestamp `json:"starred_at,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// StatusEvent is triggered when the status of a Git commit changes. +// The Webhook event name is "status". +// +// Events of this type are not visible in timelines, they are only used to +// trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#status +type StatusEvent struct { + SHA *string `json:"sha,omitempty"` + // State is the new state. Possible values are: "pending", "success", "failure", "error". + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + Branches []*Branch `json:"branches,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Context *string `json:"context,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// TeamEvent is triggered when an organization's team is created, modified or deleted. +// The Webhook event name is "team". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#team +type TeamEvent struct { + Action *string `json:"action,omitempty"` + Team *Team `json:"team,omitempty"` + Changes *TeamChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamAddEvent is triggered when a repository is added to a team. +// The Webhook event name is "team_add". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#team_add +type TeamAddEvent struct { + Team *Team `json:"team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// UserEvent is triggered when a user is created or deleted. +// The Webhook event name is "user". +// +// Only global webhooks can subscribe to this event type. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/activity/events/types/#userevent-enterprise +type UserEvent struct { + User *User `json:"user,omitempty"` + // The action performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// WatchEvent is related to starring a repository, not watching. See this API +// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ +// +// The event’s actor is the user who starred a repository, and the event’s +// repository is the repository that was starred. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#watch +type WatchEvent struct { + // Action is the action that was performed. Possible value is: "started". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Org *Organization `json:"organization,omitempty"` +} + +// WorkflowDispatchEvent is triggered when someone triggers a workflow run on GitHub or +// sends a POST request to the create a workflow dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#workflow_dispatch +type WorkflowDispatchEvent struct { + Inputs json.RawMessage `json:"inputs,omitempty"` + Ref *string `json:"ref,omitempty"` + Workflow *string `json:"workflow,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WorkflowJobEvent is triggered when a job is queued, started or completed. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job +type WorkflowJobEvent struct { + WorkflowJob *WorkflowJob `json:"workflow_job,omitempty"` + + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + + // Org is not nil when the webhook is configured for an organization or the event + // occurs from activity in a repository owned by an organization. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` +} + +// WorkflowRunEvent is triggered when a GitHub Actions workflow run is requested or completed. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#workflow_run +type WorkflowRunEvent struct { + Action *string `json:"action,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SecurityAdvisory represents the advisory object in SecurityAdvisoryEvent payload. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisory struct { + CVSS *AdvisoryCVSS `json:"cvss,omitempty"` + CWEs []*AdvisoryCWEs `json:"cwes,omitempty"` + GHSAID *string `json:"ghsa_id,omitempty"` + Summary *string `json:"summary,omitempty"` + Description *string `json:"description,omitempty"` + Severity *string `json:"severity,omitempty"` + Identifiers []*AdvisoryIdentifier `json:"identifiers,omitempty"` + References []*AdvisoryReference `json:"references,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + WithdrawnAt *Timestamp `json:"withdrawn_at,omitempty"` + Vulnerabilities []*AdvisoryVulnerability `json:"vulnerabilities,omitempty"` + CVEID *string `json:"cve_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Author *User `json:"author,omitempty"` + Publisher *User `json:"publisher,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + Submission *SecurityAdvisorySubmission `json:"submission,omitempty"` + CWEIDs []string `json:"cwe_ids,omitempty"` + Credits []*RepoAdvisoryCredit `json:"credits,omitempty"` + CreditsDetailed []*RepoAdvisoryCreditDetailed `json:"credits_detailed,omitempty"` + CollaboratingUsers []*User `json:"collaborating_users,omitempty"` + CollaboratingTeams []*Team `json:"collaborating_teams,omitempty"` + PrivateFork *Repository `json:"private_fork,omitempty"` +} + +// AdvisoryIdentifier represents the identifier for a Security Advisory. +type AdvisoryIdentifier struct { + Value *string `json:"value,omitempty"` + Type *string `json:"type,omitempty"` +} + +// AdvisoryReference represents the reference url for the security advisory. +type AdvisoryReference struct { + URL *string `json:"url,omitempty"` +} + +// AdvisoryVulnerability represents the vulnerability object for a Security Advisory. +type AdvisoryVulnerability struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + Severity *string `json:"severity,omitempty"` + VulnerableVersionRange *string `json:"vulnerable_version_range,omitempty"` + FirstPatchedVersion *FirstPatchedVersion `json:"first_patched_version,omitempty"` + + // PatchedVersions and VulnerableFunctions are used in the following APIs: + // - https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories-for-an-organization + // - https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories + PatchedVersions *string `json:"patched_versions,omitempty"` + VulnerableFunctions []string `json:"vulnerable_functions,omitempty"` +} + +// VulnerabilityPackage represents the package object for an Advisory Vulnerability. +type VulnerabilityPackage struct { + Ecosystem *string `json:"ecosystem,omitempty"` + Name *string `json:"name,omitempty"` +} + +// FirstPatchedVersion represents the identifier for the first patched version of that vulnerability. +type FirstPatchedVersion struct { + Identifier *string `json:"identifier,omitempty"` +} + +// SecurityAdvisoryEvent is triggered when a security-related vulnerability is found in software on GitHub. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisoryEvent struct { + Action *string `json:"action,omitempty"` + SecurityAdvisory *SecurityAdvisory `json:"security_advisory,omitempty"` + + // The following fields are only populated by Webhook events. + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// CodeScanningAlertEvent is triggered when a code scanning finds a potential vulnerability or error in your code. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#code_scanning_alert +type CodeScanningAlertEvent struct { + Action *string `json:"action,omitempty"` + Alert *Alert `json:"alert,omitempty"` + Ref *string `json:"ref,omitempty"` + // CommitOID is the commit SHA of the code scanning alert + CommitOID *string `json:"commit_oid,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + Installation *Installation `json:"installation,omitempty"` +} + +// SponsorshipEvent represents a sponsorship event in GitHub. +// +// GitHub API docs: https://docs.github.com/en/rest/overview/github-event-types?apiVersion=2022-11-28#sponsorshipevent +type SponsorshipEvent struct { + Action *string `json:"action,omitempty"` + EffectiveDate *string `json:"effective_date,omitempty"` + Changes *SponsorshipChanges `json:"changes,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SponsorshipChanges represents changes made to the sponsorship. +type SponsorshipChanges struct { + Tier *SponsorshipTier `json:"tier,omitempty"` + PrivacyLevel *string `json:"privacy_level,omitempty"` +} + +// SponsorshipTier represents the tier information of a sponsorship. +type SponsorshipTier struct { + From *string `json:"from,omitempty"` +} diff --git a/vendor/github.com/google/go-github/github/gists.go b/vendor/github.com/google/go-github/v68/github/gists.go similarity index 74% rename from vendor/github.com/google/go-github/github/gists.go rename to vendor/github.com/google/go-github/v68/github/gists.go index 15e0bc2c..08180c6d 100644 --- a/vendor/github.com/google/go-github/github/gists.go +++ b/vendor/github.com/google/go-github/v68/github/gists.go @@ -14,7 +14,7 @@ import ( // GistsService handles communication with the Gist related // methods of the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/gists/ +// GitHub API docs: https://docs.github.com/rest/gists type GistsService service // Gist represents a GitHub's gist. @@ -28,8 +28,8 @@ type Gist struct { HTMLURL *string `json:"html_url,omitempty"` GitPullURL *string `json:"git_pull_url,omitempty"` GitPushURL *string `json:"git_push_url,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` NodeID *string `json:"node_id,omitempty"` } @@ -96,15 +96,19 @@ type GistListOptions struct { // is authenticated, it will returns all gists for the authenticated // user. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists -func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptions) ([]*Gist, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gists-for-a-user +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gists-for-the-authenticated-user +// +//meta:operation GET /gists +//meta:operation GET /users/{username}/gists +func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/gists", user) } else { u = "gists" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -125,9 +129,11 @@ func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptio // ListAll lists all public gists. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists -func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { - u, err := addOptions("gists/public", opt) +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-public-gists +// +//meta:operation GET /gists/public +func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/public", opts) if err != nil { return nil, nil, err } @@ -148,9 +154,11 @@ func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gi // ListStarred lists starred gists of authenticated user. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gists -func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { - u, err := addOptions("gists/starred", opt) +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-starred-gists +// +//meta:operation GET /gists/starred +func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/starred", opts) if err != nil { return nil, nil, err } @@ -171,7 +179,9 @@ func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([ // Get a single gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#get-a-gist +// +//meta:operation GET /gists/{gist_id} func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("GET", u, nil) @@ -190,7 +200,9 @@ func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, er // GetRevision gets a specific revision of a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#get-a-gist-revision +// +//meta:operation GET /gists/{gist_id}/{sha} func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v/%v", id, sha) req, err := s.client.NewRequest("GET", u, nil) @@ -209,7 +221,9 @@ func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, // Create a gist for authenticated user. // -// GitHub API docs: https://developer.github.com/v3/gists/#create-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#create-a-gist +// +//meta:operation POST /gists func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) { u := "gists" req, err := s.client.NewRequest("POST", u, gist) @@ -228,7 +242,9 @@ func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response // Edit a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#edit-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#update-a-gist +// +//meta:operation PATCH /gists/{gist_id} func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("PATCH", u, gist) @@ -247,10 +263,12 @@ func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, // ListCommits lists commits of a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits -func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOptions) ([]*GistCommit, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gist-commits +// +//meta:operation GET /gists/{gist_id}/commits +func (s *GistsService) ListCommits(ctx context.Context, id string, opts *ListOptions) ([]*GistCommit, *Response, error) { u := fmt.Sprintf("gists/%v/commits", id) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -271,49 +289,61 @@ func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOpti // Delete a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#delete-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#delete-a-gist +// +//meta:operation DELETE /gists/{gist_id} func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } // Star a gist on behalf of authenticated user. // -// GitHub API docs: https://developer.github.com/v3/gists/#star-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#star-a-gist +// +//meta:operation PUT /gists/{gist_id}/star func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("PUT", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } // Unstar a gist on a behalf of authenticated user. // -// GitHub API docs: https://developer.github.com/v3/gists/#unstar-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#unstar-a-gist +// +//meta:operation DELETE /gists/{gist_id}/star func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } // IsStarred checks if a gist is starred by authenticated user. // -// GitHub API docs: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred +// GitHub API docs: https://docs.github.com/rest/gists/gists#check-if-a-gist-is-starred +// +//meta:operation GET /gists/{gist_id}/star func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) { u := fmt.Sprintf("gists/%v/star", id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } + resp, err := s.client.Do(ctx, req, nil) starred, err := parseBoolResponse(err) return starred, resp, err @@ -321,7 +351,9 @@ func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Respons // Fork a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#fork-a-gist +// GitHub API docs: https://docs.github.com/rest/gists/gists#fork-a-gist +// +//meta:operation POST /gists/{gist_id}/forks func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) { u := fmt.Sprintf("gists/%v/forks", id) req, err := s.client.NewRequest("POST", u, nil) @@ -340,9 +372,16 @@ func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, e // ListForks lists forks of a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks -func (s *GistsService) ListForks(ctx context.Context, id string) ([]*GistFork, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gist-forks +// +//meta:operation GET /gists/{gist_id}/forks +func (s *GistsService) ListForks(ctx context.Context, id string, opts *ListOptions) ([]*GistFork, *Response, error) { u := fmt.Sprintf("gists/%v/forks", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err diff --git a/vendor/github.com/google/go-github/github/gists_comments.go b/vendor/github.com/google/go-github/v68/github/gists_comments.go similarity index 75% rename from vendor/github.com/google/go-github/github/gists_comments.go rename to vendor/github.com/google/go-github/v68/github/gists_comments.go index d5322e3d..5e061423 100644 --- a/vendor/github.com/google/go-github/github/gists_comments.go +++ b/vendor/github.com/google/go-github/v68/github/gists_comments.go @@ -8,7 +8,6 @@ package github import ( "context" "fmt" - "time" ) // GistComment represents a Gist comment. @@ -17,7 +16,7 @@ type GistComment struct { URL *string `json:"url,omitempty"` Body *string `json:"body,omitempty"` User *User `json:"user,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` } func (g GistComment) String() string { @@ -26,10 +25,12 @@ func (g GistComment) String() string { // ListComments lists all comments for a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist -func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *ListOptions) ([]*GistComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gists/comments#list-gist-comments +// +//meta:operation GET /gists/{gist_id}/comments +func (s *GistsService) ListComments(ctx context.Context, gistID string, opts *ListOptions) ([]*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments", gistID) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -50,7 +51,9 @@ func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *Lis // GetComment retrieves a single comment from a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment +// GitHub API docs: https://docs.github.com/rest/gists/comments#get-a-gist-comment +// +//meta:operation GET /gists/{gist_id}/comments/{comment_id} func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("GET", u, nil) @@ -69,7 +72,9 @@ func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID // CreateComment creates a comment for a gist. // -// GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment +// GitHub API docs: https://docs.github.com/rest/gists/comments#create-a-gist-comment +// +//meta:operation POST /gists/{gist_id}/comments func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments", gistID) req, err := s.client.NewRequest("POST", u, comment) @@ -88,7 +93,9 @@ func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment // EditComment edits an existing gist comment. // -// GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment +// GitHub API docs: https://docs.github.com/rest/gists/comments#update-a-gist-comment +// +//meta:operation PATCH /gists/{gist_id}/comments/{comment_id} func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("PATCH", u, comment) @@ -107,7 +114,9 @@ func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID // DeleteComment deletes a gist comment. // -// GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment +// GitHub API docs: https://docs.github.com/rest/gists/comments#delete-a-gist-comment +// +//meta:operation DELETE /gists/{gist_id}/comments/{comment_id} func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/git.go b/vendor/github.com/google/go-github/v68/github/git.go similarity index 84% rename from vendor/github.com/google/go-github/github/git.go rename to vendor/github.com/google/go-github/v68/github/git.go index 1ce47437..2ca835e1 100644 --- a/vendor/github.com/google/go-github/github/git.go +++ b/vendor/github.com/google/go-github/v68/github/git.go @@ -8,5 +8,5 @@ package github // GitService handles communication with the git data related // methods of the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/git/ +// GitHub API docs: https://docs.github.com/rest/git/ type GitService service diff --git a/vendor/github.com/google/go-github/github/git_blobs.go b/vendor/github.com/google/go-github/v68/github/git_blobs.go similarity index 74% rename from vendor/github.com/google/go-github/github/git_blobs.go rename to vendor/github.com/google/go-github/v68/github/git_blobs.go index 70aee14a..d8904288 100644 --- a/vendor/github.com/google/go-github/github/git_blobs.go +++ b/vendor/github.com/google/go-github/v68/github/git_blobs.go @@ -23,7 +23,9 @@ type Blob struct { // GetBlob fetches a blob from a repo given a SHA. // -// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob +// GitHub API docs: https://docs.github.com/rest/git/blobs#get-a-blob +// +//meta:operation GET /repos/{owner}/{repo}/git/blobs/{file_sha} func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) @@ -33,29 +35,42 @@ func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha blob := new(Blob) resp, err := s.client.Do(ctx, req, blob) - return blob, resp, err + if err != nil { + return nil, resp, err + } + + return blob, resp, nil } // GetBlobRaw fetches a blob's contents from a repo. // Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data. // -// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob +// GitHub API docs: https://docs.github.com/rest/git/blobs#get-a-blob +// +//meta:operation GET /repos/{owner}/{repo}/git/blobs/{file_sha} func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } + req.Header.Set("Accept", "application/vnd.github.v3.raw") var buf bytes.Buffer resp, err := s.client.Do(ctx, req, &buf) - return buf.Bytes(), resp, err + if err != nil { + return nil, resp, err + } + + return buf.Bytes(), resp, nil } // CreateBlob creates a blob object. // -// GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob +// GitHub API docs: https://docs.github.com/rest/git/blobs#create-a-blob +// +//meta:operation POST /repos/{owner}/{repo}/git/blobs func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) req, err := s.client.NewRequest("POST", u, blob) @@ -65,5 +80,9 @@ func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, t := new(Blob) resp, err := s.client.Do(ctx, req, t) - return t, resp, err + if err != nil { + return nil, resp, err + } + + return t, resp, nil } diff --git a/vendor/github.com/google/go-github/github/git_commits.go b/vendor/github.com/google/go-github/v68/github/git_commits.go similarity index 52% rename from vendor/github.com/google/go-github/github/git_commits.go rename to vendor/github.com/google/go-github/v68/github/git_commits.go index 1eb48a8e..d7ed3ecb 100644 --- a/vendor/github.com/google/go-github/github/git_commits.go +++ b/vendor/github.com/google/go-github/v68/github/git_commits.go @@ -6,9 +6,12 @@ package github import ( + "bytes" "context" + "errors" "fmt" - "time" + "io" + "strings" ) // SignatureVerification represents GPG signature verification. @@ -19,6 +22,25 @@ type SignatureVerification struct { Payload *string `json:"payload,omitempty"` } +// MessageSigner is used by GitService.CreateCommit to sign a commit. +// +// To create a MessageSigner that signs a commit with a [golang.org/x/crypto/openpgp.Entity], +// or [github.com/ProtonMail/go-crypto/openpgp.Entity], use: +// +// commit.Signer = github.MessageSignerFunc(func(w io.Writer, r io.Reader) error { +// return openpgp.ArmoredDetachSign(w, openpgpEntity, r, nil) +// }) +type MessageSigner interface { + Sign(w io.Writer, r io.Reader) error +} + +// MessageSignerFunc is a single function implementation of MessageSigner. +type MessageSignerFunc func(w io.Writer, r io.Reader) error + +func (f MessageSignerFunc) Sign(w io.Writer, r io.Reader) error { + return f(w, r) +} + // Commit represents a GitHub commit. type Commit struct { SHA *string `json:"sha,omitempty"` @@ -26,8 +48,7 @@ type Commit struct { Committer *CommitAuthor `json:"committer,omitempty"` Message *string `json:"message,omitempty"` Tree *Tree `json:"tree,omitempty"` - Parents []Commit `json:"parents,omitempty"` - Stats *CommitStats `json:"stats,omitempty"` + Parents []*Commit `json:"parents,omitempty"` HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` Verification *SignatureVerification `json:"verification,omitempty"` @@ -46,7 +67,7 @@ func (c Commit) String() string { // CommitAuthor represents the author or committer of a commit. The commit // author may not correspond to a GitHub User. type CommitAuthor struct { - Date *time.Time `json:"date,omitempty"` + Date *Timestamp `json:"date,omitempty"` Name *string `json:"name,omitempty"` Email *string `json:"email,omitempty"` @@ -58,9 +79,11 @@ func (c CommitAuthor) String() string { return Stringify(c) } -// GetCommit fetchs the Commit object for a given SHA. +// GetCommit fetches the Commit object for a given SHA. +// +// GitHub API docs: https://docs.github.com/rest/git/commits#get-a-commit-object // -// GitHub API docs: https://developer.github.com/v3/git/commits/#get-a-commit +//meta:operation GET /repos/{owner}/{repo}/git/commits/{commit_sha} func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) @@ -68,9 +91,6 @@ func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, s return nil, nil, err } - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - c := new(Commit) resp, err := s.client.Do(ctx, req, c) if err != nil { @@ -87,6 +107,13 @@ type createCommit struct { Message *string `json:"message,omitempty"` Tree *string `json:"tree,omitempty"` Parents []string `json:"parents,omitempty"` + Signature *string `json:"signature,omitempty"` +} + +type CreateCommitOptions struct { + // CreateCommit will sign the commit with this signer. See MessageSigner doc for more details. + // Ignored on commits where Verification.Signature is defined. + Signer MessageSigner } // CreateCommit creates a new commit in a repository. @@ -96,10 +123,15 @@ type createCommit struct { // data if omitted. If the commit.Author is omitted, it will be filled in with // the authenticated user’s information and the current date. // -// GitHub API docs: https://developer.github.com/v3/git/commits/#create-a-commit -func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/git/commits#create-a-commit +// +//meta:operation POST /repos/{owner}/{repo}/git/commits +func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit, opts *CreateCommitOptions) (*Commit, *Response, error) { if commit == nil { - return nil, nil, fmt.Errorf("commit must be provided") + return nil, nil, errors.New("commit must be provided") + } + if opts == nil { + opts = &CreateCommitOptions{} } u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) @@ -118,6 +150,16 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string if commit.Tree != nil { body.Tree = commit.Tree.SHA } + switch { + case commit.Verification != nil: + body.Signature = commit.Verification.Signature + case opts.Signer != nil: + signature, err := createSignature(opts.Signer, body) + if err != nil { + return nil, nil, err + } + body.Signature = &signature + } req, err := s.client.NewRequest("POST", u, body) if err != nil { @@ -132,3 +174,51 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string return c, resp, nil } + +func createSignature(signer MessageSigner, commit *createCommit) (string, error) { + if signer == nil { + return "", errors.New("createSignature: invalid parameters") + } + + message, err := createSignatureMessage(commit) + if err != nil { + return "", err + } + + var writer bytes.Buffer + err = signer.Sign(&writer, strings.NewReader(message)) + if err != nil { + return "", err + } + + return writer.String(), nil +} + +func createSignatureMessage(commit *createCommit) (string, error) { + if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil { + return "", errors.New("createSignatureMessage: invalid parameters") + } + + var message []string + + if commit.Tree != nil { + message = append(message, fmt.Sprintf("tree %s", *commit.Tree)) + } + + for _, parent := range commit.Parents { + message = append(message, fmt.Sprintf("parent %s", parent)) + } + + message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700"))) + + committer := commit.Committer + if committer == nil { + committer = commit.Author + } + + // There needs to be a double newline after committer + message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700"))) + message = append(message, *commit.Message) + + return strings.Join(message, "\n"), nil +} diff --git a/vendor/github.com/google/go-github/v68/github/git_refs.go b/vendor/github.com/google/go-github/v68/github/git_refs.go new file mode 100644 index 00000000..91eb6dd4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/git_refs.go @@ -0,0 +1,185 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/url" + "strings" +) + +// Reference represents a GitHub reference. +type Reference struct { + Ref *string `json:"ref"` + URL *string `json:"url"` + Object *GitObject `json:"object"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r Reference) String() string { + return Stringify(r) +} + +// GitObject represents a Git object. +type GitObject struct { + Type *string `json:"type"` + SHA *string `json:"sha"` + URL *string `json:"url"` +} + +func (o GitObject) String() string { + return Stringify(o) +} + +// createRefRequest represents the payload for creating a reference. +type createRefRequest struct { + Ref *string `json:"ref"` + SHA *string `json:"sha"` +} + +// updateRefRequest represents the payload for updating a reference. +type updateRefRequest struct { + SHA *string `json:"sha"` + Force *bool `json:"force"` +} + +// GetRef fetches a single reference in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#get-a-reference +// +//meta:operation GET /repos/{owner}/{repo}/git/ref/{ref} +func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// refURLEscape escapes every path segment of the given ref. Those must +// not contain escaped "/" - as "%2F" - or github will not recognize it. +func refURLEscape(ref string) string { + parts := strings.Split(ref, "/") + for i, s := range parts { + parts[i] = url.PathEscape(s) + } + return strings.Join(parts, "/") +} + +// ReferenceListOptions specifies optional parameters to the +// GitService.ListMatchingRefs method. +type ReferenceListOptions struct { + Ref string `url:"-"` + + ListOptions +} + +// ListMatchingRefs lists references in a repository that match a supplied ref. +// Use an empty ref to list all references. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#list-matching-references +// +//meta:operation GET /repos/{owner}/{repo}/git/matching-refs/{ref} +func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) { + var ref string + if opts != nil { + ref = strings.TrimPrefix(opts.Ref, "refs/") + } + u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rs []*Reference + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// CreateRef creates a new ref in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#create-a-reference +// +//meta:operation POST /repos/{owner}/{repo}/git/refs +func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) + req, err := s.client.NewRequest("POST", u, &createRefRequest{ + // back-compat with previous behavior that didn't require 'refs/' prefix + Ref: Ptr("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), + SHA: ref.Object.SHA, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateRef updates an existing ref in a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#update-a-reference +// +//meta:operation PATCH /repos/{owner}/{repo}/git/refs/{ref} +func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { + refPath := strings.TrimPrefix(*ref.Ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(refPath)) + req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ + SHA: ref.Object.SHA, + Force: &force, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DeleteRef deletes a ref from a repository. +// +// GitHub API docs: https://docs.github.com/rest/git/refs#delete-a-reference +// +//meta:operation DELETE /repos/{owner}/{repo}/git/refs/{ref} +func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/git_tags.go b/vendor/github.com/google/go-github/v68/github/git_tags.go similarity index 83% rename from vendor/github.com/google/go-github/github/git_tags.go rename to vendor/github.com/google/go-github/v68/github/git_tags.go index 90398b38..67321566 100644 --- a/vendor/github.com/google/go-github/github/git_tags.go +++ b/vendor/github.com/google/go-github/v68/github/git_tags.go @@ -33,9 +33,11 @@ type createTagRequest struct { Tagger *CommitAuthor `json:"tagger,omitempty"` } -// GetTag fetchs a tag from a repo given a SHA. +// GetTag fetches a tag from a repo given a SHA. // -// GitHub API docs: https://developer.github.com/v3/git/tags/#get-a-tag +// GitHub API docs: https://docs.github.com/rest/git/tags#get-a-tag +// +//meta:operation GET /repos/{owner}/{repo}/git/tags/{tag_sha} func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) @@ -43,17 +45,20 @@ func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha return nil, nil, err } - // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - tag := new(Tag) resp, err := s.client.Do(ctx, req, tag) - return tag, resp, err + if err != nil { + return nil, resp, err + } + + return tag, resp, nil } // CreateTag creates a tag object. // -// GitHub API docs: https://developer.github.com/v3/git/tags/#create-a-tag-object +// GitHub API docs: https://docs.github.com/rest/git/tags#create-a-tag-object +// +//meta:operation POST /repos/{owner}/{repo}/git/tags func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) @@ -75,5 +80,9 @@ func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, t t := new(Tag) resp, err := s.client.Do(ctx, req, t) - return t, resp, err + if err != nil { + return nil, resp, err + } + + return t, resp, nil } diff --git a/vendor/github.com/google/go-github/github/git_trees.go b/vendor/github.com/google/go-github/v68/github/git_trees.go similarity index 50% rename from vendor/github.com/google/go-github/github/git_trees.go rename to vendor/github.com/google/go-github/v68/github/git_trees.go index 4bc29135..b8eed58e 100644 --- a/vendor/github.com/google/go-github/github/git_trees.go +++ b/vendor/github.com/google/go-github/v68/github/git_trees.go @@ -7,13 +7,14 @@ package github import ( "context" + "encoding/json" "fmt" ) // Tree represents a GitHub tree. type Tree struct { - SHA *string `json:"sha,omitempty"` - Entries []TreeEntry `json:"tree,omitempty"` + SHA *string `json:"sha,omitempty"` + Entries []*TreeEntry `json:"tree,omitempty"` // Truncated is true if the number of items in the tree // exceeded GitHub's maximum limit and the Entries were truncated @@ -43,9 +44,58 @@ func (t TreeEntry) String() string { return Stringify(t) } +// treeEntryWithFileDelete is used internally to delete a file whose +// Content and SHA fields are empty. It does this by removing the "omitempty" +// tag modifier on the SHA field which causes the GitHub API to receive +// {"sha":null} and thereby delete the file. +type treeEntryWithFileDelete struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t *TreeEntry) MarshalJSON() ([]byte, error) { + if t.SHA == nil && t.Content == nil { + return json.Marshal(struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + }{ + nil, + t.Path, + t.Mode, + t.Type, + }) + } + return json.Marshal(struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` + }{ + SHA: t.SHA, + Path: t.Path, + Mode: t.Mode, + Type: t.Type, + Size: t.Size, + Content: t.Content, + URL: t.URL, + }) +} + // GetTree fetches the Tree object for a given sha hash from a repository. // -// GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree +// GitHub API docs: https://docs.github.com/rest/git/trees#get-a-tree +// +//meta:operation GET /repos/{owner}/{repo}/git/trees/{tree_sha} func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) if recursive { @@ -68,21 +118,38 @@ func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha // createTree represents the body of a CreateTree request. type createTree struct { - BaseTree string `json:"base_tree,omitempty"` - Entries []TreeEntry `json:"tree"` + BaseTree string `json:"base_tree,omitempty"` + Entries []interface{} `json:"tree"` } // CreateTree creates a new tree in a repository. If both a tree and a nested // path modifying that tree are specified, it will overwrite the contents of // that tree with the new path contents and write a new tree out. // -// GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree -func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/git/trees#create-a-tree +// +//meta:operation POST /repos/{owner}/{repo}/git/trees +func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []*TreeEntry) (*Tree, *Response, error) { u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) + newEntries := make([]interface{}, 0, len(entries)) + for _, entry := range entries { + if entry.Content == nil && entry.SHA == nil { + newEntries = append(newEntries, treeEntryWithFileDelete{ + Path: entry.Path, + Mode: entry.Mode, + Type: entry.Type, + Size: entry.Size, + URL: entry.URL, + }) + continue + } + newEntries = append(newEntries, entry) + } + body := &createTree{ BaseTree: baseTree, - Entries: entries, + Entries: newEntries, } req, err := s.client.NewRequest("POST", u, body) if err != nil { diff --git a/vendor/github.com/google/go-github/v68/github/github-accessors.go b/vendor/github.com/google/go-github/v68/github/github-accessors.go new file mode 100644 index 00000000..0800c02c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/github-accessors.go @@ -0,0 +1,26951 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by gen-accessors; DO NOT EDIT. +// Instead, please run "go generate ./..." as described here: +// https://github.com/google/go-github/blob/master/CONTRIBUTING.md#submitting-a-patch + +package github + +import ( + "encoding/json" + "time" +) + +// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. +func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { + if a == nil || a.RetryAfter == nil { + return 0 + } + return *a.RetryAfter +} + +// GetGithubOwnedAllowed returns the GithubOwnedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetGithubOwnedAllowed() bool { + if a == nil || a.GithubOwnedAllowed == nil { + return false + } + return *a.GithubOwnedAllowed +} + +// GetVerifiedAllowed returns the VerifiedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetVerifiedAllowed() bool { + if a == nil || a.VerifiedAllowed == nil { + return false + } + return *a.VerifiedAllowed +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetKey() string { + if a == nil || a.Key == nil { + return "" + } + return *a.Key +} + +// GetLastAccessedAt returns the LastAccessedAt field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetLastAccessedAt() Timestamp { + if a == nil || a.LastAccessedAt == nil { + return Timestamp{} + } + return *a.LastAccessedAt +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSizeInBytes returns the SizeInBytes field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetSizeInBytes() int64 { + if a == nil || a.SizeInBytes == nil { + return 0 + } + return *a.SizeInBytes +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (a *ActionsCache) GetVersion() string { + if a == nil || a.Version == nil { + return "" + } + return *a.Version +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetDirection() string { + if a == nil || a.Direction == nil { + return "" + } + return *a.Direction +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetKey() string { + if a == nil || a.Key == nil { + return "" + } + return *a.Key +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (a *ActionsCacheListOptions) GetSort() string { + if a == nil || a.Sort == nil { + return "" + } + return *a.Sort +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabledRepositories returns the EnabledRepositories field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetEnabledRepositories() string { + if a == nil || a.EnabledRepositories == nil { + return "" + } + return *a.EnabledRepositories +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabledOrganizations returns the EnabledOrganizations field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetEnabledOrganizations() string { + if a == nil || a.EnabledOrganizations == nil { + return "" + } + return *a.EnabledOrganizations +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsEnterprise) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetSelectedRepositoriesURL() string { + if a == nil || a.SelectedRepositoriesURL == nil { + return "" + } + return *a.SelectedRepositoriesURL +} + +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (a *ActionsVariable) GetSelectedRepositoryIDs() *SelectedRepoIDs { + if a == nil { + return nil + } + return a.SelectedRepositoryIDs +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (a *ActionsVariable) GetVisibility() string { + if a == nil || a.Visibility == nil { + return "" + } + return *a.Visibility +} + +// GetCountryCode returns the CountryCode field if it's non-nil, zero value otherwise. +func (a *ActorLocation) GetCountryCode() string { + if a == nil || a.CountryCode == nil { + return "" + } + return *a.CountryCode +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AdminEnforcedChanges) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdminEnforcement) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetComments returns the Comments field. +func (a *AdminStats) GetComments() *CommentStats { + if a == nil { + return nil + } + return a.Comments +} + +// GetGists returns the Gists field. +func (a *AdminStats) GetGists() *GistStats { + if a == nil { + return nil + } + return a.Gists +} + +// GetHooks returns the Hooks field. +func (a *AdminStats) GetHooks() *HookStats { + if a == nil { + return nil + } + return a.Hooks +} + +// GetIssues returns the Issues field. +func (a *AdminStats) GetIssues() *IssueStats { + if a == nil { + return nil + } + return a.Issues +} + +// GetMilestones returns the Milestones field. +func (a *AdminStats) GetMilestones() *MilestoneStats { + if a == nil { + return nil + } + return a.Milestones +} + +// GetOrgs returns the Orgs field. +func (a *AdminStats) GetOrgs() *OrgStats { + if a == nil { + return nil + } + return a.Orgs +} + +// GetPages returns the Pages field. +func (a *AdminStats) GetPages() *PageStats { + if a == nil { + return nil + } + return a.Pages +} + +// GetPulls returns the Pulls field. +func (a *AdminStats) GetPulls() *PullStats { + if a == nil { + return nil + } + return a.Pulls +} + +// GetRepos returns the Repos field. +func (a *AdminStats) GetRepos() *RepoStats { + if a == nil { + return nil + } + return a.Repos +} + +// GetUsers returns the Users field. +func (a *AdminStats) GetUsers() *UserStats { + if a == nil { + return nil + } + return a.Users +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurity) GetStatus() string { + if a == nil || a.Status == nil { + return "" + } + return *a.Status +} + +// GetLastPushedDate returns the LastPushedDate field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetLastPushedDate() string { + if a == nil || a.LastPushedDate == nil { + return "" + } + return *a.LastPushedDate +} + +// GetUserLogin returns the UserLogin field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetUserLogin() string { + if a == nil || a.UserLogin == nil { + return "" + } + return *a.UserLogin +} + +// GetScore returns the Score field. +func (a *AdvisoryCVSS) GetScore() *float64 { + if a == nil { + return nil + } + return a.Score +} + +// GetVectorString returns the VectorString field if it's non-nil, zero value otherwise. +func (a *AdvisoryCVSS) GetVectorString() string { + if a == nil || a.VectorString == nil { + return "" + } + return *a.VectorString +} + +// GetCWEID returns the CWEID field if it's non-nil, zero value otherwise. +func (a *AdvisoryCWEs) GetCWEID() string { + if a == nil || a.CWEID == nil { + return "" + } + return *a.CWEID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AdvisoryCWEs) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetValue() string { + if a == nil || a.Value == nil { + return "" + } + return *a.Value +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdvisoryReference) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetFirstPatchedVersion returns the FirstPatchedVersion field. +func (a *AdvisoryVulnerability) GetFirstPatchedVersion() *FirstPatchedVersion { + if a == nil { + return nil + } + return a.FirstPatchedVersion +} + +// GetPackage returns the Package field. +func (a *AdvisoryVulnerability) GetPackage() *VulnerabilityPackage { + if a == nil { + return nil + } + return a.Package +} + +// GetPatchedVersions returns the PatchedVersions field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetPatchedVersions() string { + if a == nil || a.PatchedVersions == nil { + return "" + } + return *a.PatchedVersions +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetSeverity() string { + if a == nil || a.Severity == nil { + return "" + } + return *a.Severity +} + +// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetVulnerableVersionRange() string { + if a == nil || a.VulnerableVersionRange == nil { + return "" + } + return *a.VulnerableVersionRange +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetClosedAt() Timestamp { + if a == nil || a.ClosedAt == nil { + return Timestamp{} + } + return *a.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (a *Alert) GetClosedBy() *User { + if a == nil { + return nil + } + return a.ClosedBy +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedAt() Timestamp { + if a == nil || a.DismissedAt == nil { + return Timestamp{} + } + return *a.DismissedAt +} + +// GetDismissedBy returns the DismissedBy field. +func (a *Alert) GetDismissedBy() *User { + if a == nil { + return nil + } + return a.DismissedBy +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedComment() string { + if a == nil || a.DismissedComment == nil { + return "" + } + return *a.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedReason() string { + if a == nil || a.DismissedReason == nil { + return "" + } + return *a.DismissedReason +} + +// GetFixedAt returns the FixedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetFixedAt() Timestamp { + if a == nil || a.FixedAt == nil { + return Timestamp{} + } + return *a.FixedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetInstancesURL returns the InstancesURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetInstancesURL() string { + if a == nil || a.InstancesURL == nil { + return "" + } + return *a.InstancesURL +} + +// GetMostRecentInstance returns the MostRecentInstance field. +func (a *Alert) GetMostRecentInstance() *MostRecentInstance { + if a == nil { + return nil + } + return a.MostRecentInstance +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (a *Alert) GetNumber() int { + if a == nil || a.Number == nil { + return 0 + } + return *a.Number +} + +// GetRepository returns the Repository field. +func (a *Alert) GetRepository() *Repository { + if a == nil { + return nil + } + return a.Repository +} + +// GetRule returns the Rule field. +func (a *Alert) GetRule() *Rule { + if a == nil { + return nil + } + return a.Rule +} + +// GetRuleDescription returns the RuleDescription field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleDescription() string { + if a == nil || a.RuleDescription == nil { + return "" + } + return *a.RuleDescription +} + +// GetRuleID returns the RuleID field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleID() string { + if a == nil || a.RuleID == nil { + return "" + } + return *a.RuleID +} + +// GetRuleSeverity returns the RuleSeverity field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleSeverity() string { + if a == nil || a.RuleSeverity == nil { + return "" + } + return *a.RuleSeverity +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (a *Alert) GetState() string { + if a == nil || a.State == nil { + return "" + } + return *a.State +} + +// GetTool returns the Tool field. +func (a *Alert) GetTool() *Tool { + if a == nil { + return nil + } + return a.Tool +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Alert) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AllowDeletionsEnforcementLevelChanges) GetFrom() string { + if a == nil || a.From == nil { + return "" + } + return *a.From +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *AllowForkSyncing) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetSarifID() string { + if a == nil || a.SarifID == nil { + return "" + } + return *a.SarifID +} + +// GetDomains returns the Domains field. +func (a *APIMeta) GetDomains() *APIMetaDomains { + if a == nil { + return nil + } + return a.Domains +} + +// GetSSHKeyFingerprints returns the SSHKeyFingerprints map if it's non-nil, an empty map otherwise. +func (a *APIMeta) GetSSHKeyFingerprints() map[string]string { + if a == nil || a.SSHKeyFingerprints == nil { + return map[string]string{} + } + return a.SSHKeyFingerprints +} + +// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. +func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { + if a == nil || a.VerifiablePasswordAuthentication == nil { + return false + } + return *a.VerifiablePasswordAuthentication +} + +// GetArtifactAttestations returns the ArtifactAttestations field. +func (a *APIMetaDomains) GetArtifactAttestations() *APIMetaArtifactAttestations { + if a == nil { + return nil + } + return a.ArtifactAttestations +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *App) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *App) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *App) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *App) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetInstallationsCount returns the InstallationsCount field if it's non-nil, zero value otherwise. +func (a *App) GetInstallationsCount() int { + if a == nil || a.InstallationsCount == nil { + return 0 + } + return *a.InstallationsCount +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *App) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *App) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *App) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPermissions returns the Permissions field. +func (a *App) GetPermissions() *InstallationPermissions { + if a == nil { + return nil + } + return a.Permissions +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *App) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *AppConfig) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPEM returns the PEM field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetPEM() string { + if a == nil || a.PEM == nil { + return "" + } + return *a.PEM +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetWebhookSecret returns the WebhookSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetWebhookSecret() string { + if a == nil || a.WebhookSecret == nil { + return "" + } + return *a.WebhookSecret +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *ArchivedAt) GetFrom() Timestamp { + if a == nil || a.From == nil { + return Timestamp{} + } + return *a.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (a *ArchivedAt) GetTo() Timestamp { + if a == nil || a.To == nil { + return Timestamp{} + } + return *a.To +} + +// GetArchiveDownloadURL returns the ArchiveDownloadURL field if it's non-nil, zero value otherwise. +func (a *Artifact) GetArchiveDownloadURL() string { + if a == nil || a.ArchiveDownloadURL == nil { + return "" + } + return *a.ArchiveDownloadURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetExpired returns the Expired field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpired() bool { + if a == nil || a.Expired == nil { + return false + } + return *a.Expired +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpiresAt() Timestamp { + if a == nil || a.ExpiresAt == nil { + return Timestamp{} + } + return *a.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *Artifact) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetSizeInBytes returns the SizeInBytes field if it's non-nil, zero value otherwise. +func (a *Artifact) GetSizeInBytes() int64 { + if a == nil || a.SizeInBytes == nil { + return 0 + } + return *a.SizeInBytes +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Artifact) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetWorkflowRun returns the WorkflowRun field. +func (a *Artifact) GetWorkflowRun() *ArtifactWorkflowRun { + if a == nil { + return nil + } + return a.WorkflowRun +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (a *ArtifactList) GetTotalCount() int64 { + if a == nil || a.TotalCount == nil { + return 0 + } + return *a.TotalCount +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadBranch() string { + if a == nil || a.HeadBranch == nil { + return "" + } + return *a.HeadBranch +} + +// GetHeadRepositoryID returns the HeadRepositoryID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadRepositoryID() int64 { + if a == nil || a.HeadRepositoryID == nil { + return 0 + } + return *a.HeadRepositoryID +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetHeadSHA() string { + if a == nil || a.HeadSHA == nil { + return "" + } + return *a.HeadSHA +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (a *ArtifactWorkflowRun) GetRepositoryID() int64 { + if a == nil || a.RepositoryID == nil { + return 0 + } + return *a.RepositoryID +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (a *Attachment) GetBody() string { + if a == nil || a.Body == nil { + return "" + } + return *a.Body +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Attachment) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (a *Attachment) GetTitle() string { + if a == nil || a.Title == nil { + return "" + } + return *a.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetAction() string { + if a == nil || a.Action == nil { + return "" + } + return *a.Action +} + +// GetActor returns the Actor field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActor() string { + if a == nil || a.Actor == nil { + return "" + } + return *a.Actor +} + +// GetActorID returns the ActorID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActorID() int64 { + if a == nil || a.ActorID == nil { + return 0 + } + return *a.ActorID +} + +// GetActorLocation returns the ActorLocation field. +func (a *AuditEntry) GetActorLocation() *ActorLocation { + if a == nil { + return nil + } + return a.ActorLocation +} + +// GetBusiness returns the Business field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBusiness() string { + if a == nil || a.Business == nil { + return "" + } + return *a.Business +} + +// GetBusinessID returns the BusinessID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBusinessID() int64 { + if a == nil || a.BusinessID == nil { + return 0 + } + return *a.BusinessID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDocumentID returns the DocumentID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetDocumentID() string { + if a == nil || a.DocumentID == nil { + return "" + } + return *a.DocumentID +} + +// GetExternalIdentityNameID returns the ExternalIdentityNameID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetExternalIdentityNameID() string { + if a == nil || a.ExternalIdentityNameID == nil { + return "" + } + return *a.ExternalIdentityNameID +} + +// GetExternalIdentityUsername returns the ExternalIdentityUsername field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetExternalIdentityUsername() string { + if a == nil || a.ExternalIdentityUsername == nil { + return "" + } + return *a.ExternalIdentityUsername +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetOrg returns the Org field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOrg() string { + if a == nil || a.Org == nil { + return "" + } + return *a.Org +} + +// GetOrgID returns the OrgID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOrgID() int64 { + if a == nil || a.OrgID == nil { + return 0 + } + return *a.OrgID +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTimestamp() Timestamp { + if a == nil || a.Timestamp == nil { + return Timestamp{} + } + return *a.Timestamp +} + +// GetTokenID returns the TokenID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTokenID() int64 { + if a == nil || a.TokenID == nil { + return 0 + } + return *a.TokenID +} + +// GetTokenScopes returns the TokenScopes field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTokenScopes() string { + if a == nil || a.TokenScopes == nil { + return "" + } + return *a.TokenScopes +} + +// GetUser returns the User field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetUser() string { + if a == nil || a.User == nil { + return "" + } + return *a.User +} + +// GetUserID returns the UserID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetUserID() int64 { + if a == nil || a.UserID == nil { + return 0 + } + return *a.UserID +} + +// GetApp returns the App field. +func (a *Authorization) GetApp() *AuthorizationApp { + if a == nil { + return nil + } + return a.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *Authorization) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *Authorization) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Authorization) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (a *Authorization) GetToken() string { + if a == nil || a.Token == nil { + return "" + } + return *a.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (a *Authorization) GetTokenLastEight() string { + if a == nil || a.TokenLastEight == nil { + return "" + } + return *a.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetUser returns the User field. +func (a *Authorization) GetUser() *User { + if a == nil { + return nil + } + return a.User +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AuthorizedActorsOnly) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AuthorizedDismissalActorsOnlyChanges) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Autolink) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *Autolink) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *Autolink) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *Autolink) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *AutomatedSecurityFixes) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetPaused returns the Paused field if it's non-nil, zero value otherwise. +func (a *AutomatedSecurityFixes) GetPaused() bool { + if a == nil || a.Paused == nil { + return false + } + return *a.Paused +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetAppID() int64 { + if a == nil || a.AppID == nil { + return 0 + } + return *a.AppID +} + +// GetSetting returns the Setting field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetSetting() bool { + if a == nil || a.Setting == nil { + return false + } + return *a.Setting +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (b *Blob) GetContent() string { + if b == nil || b.Content == nil { + return "" + } + return *b.Content +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (b *Blob) GetEncoding() string { + if b == nil || b.Encoding == nil { + return "" + } + return *b.Encoding +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (b *Blob) GetNodeID() string { + if b == nil || b.NodeID == nil { + return "" + } + return *b.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (b *Blob) GetSHA() string { + if b == nil || b.SHA == nil { + return "" + } + return *b.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (b *Blob) GetSize() int { + if b == nil || b.Size == nil { + return 0 + } + return *b.Size +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (b *Blob) GetURL() string { + if b == nil || b.URL == nil { + return "" + } + return *b.URL +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (b *BlockCreations) GetEnabled() bool { + if b == nil || b.Enabled == nil { + return false + } + return *b.Enabled +} + +// GetCommit returns the Commit field. +func (b *Branch) GetCommit() *RepositoryCommit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *Branch) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *Branch) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetProtection returns the Protection field. +func (b *Branch) GetProtection() *Protection { + if b == nil { + return nil + } + return b.Protection +} + +// GetCommit returns the Commit field. +func (b *BranchCommit) GetCommit() *Commit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchListOptions) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetCustomBranchPolicies returns the CustomBranchPolicies field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetCustomBranchPolicies() bool { + if b == nil || b.CustomBranchPolicies == nil { + return false + } + return *b.CustomBranchPolicies +} + +// GetProtectedBranches returns the ProtectedBranches field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetProtectedBranches() bool { + if b == nil || b.ProtectedBranches == nil { + return false + } + return *b.ProtectedBranches +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionConfigurationEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetEnterprise returns the Enterprise field. +func (b *BranchProtectionConfigurationEvent) GetEnterprise() *Enterprise { + if b == nil { + return nil + } + return b.Enterprise +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionConfigurationEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionConfigurationEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionConfigurationEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetSender returns the Sender field. +func (b *BranchProtectionConfigurationEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + +// GetAdminEnforced returns the AdminEnforced field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAdminEnforced() bool { + if b == nil || b.AdminEnforced == nil { + return false + } + return *b.AdminEnforced +} + +// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowDeletionsEnforcementLevel() string { + if b == nil || b.AllowDeletionsEnforcementLevel == nil { + return "" + } + return *b.AllowDeletionsEnforcementLevel +} + +// GetAllowForcePushesEnforcementLevel returns the AllowForcePushesEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowForcePushesEnforcementLevel() string { + if b == nil || b.AllowForcePushesEnforcementLevel == nil { + return "" + } + return *b.AllowForcePushesEnforcementLevel +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedActorsOnly() bool { + if b == nil || b.AuthorizedActorsOnly == nil { + return false + } + return *b.AuthorizedActorsOnly +} + +// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedDismissalActorsOnly() bool { + if b == nil || b.AuthorizedDismissalActorsOnly == nil { + return false + } + return *b.AuthorizedDismissalActorsOnly +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetCreatedAt() Timestamp { + if b == nil || b.CreatedAt == nil { + return Timestamp{} + } + return *b.CreatedAt +} + +// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetDismissStaleReviewsOnPush() bool { + if b == nil || b.DismissStaleReviewsOnPush == nil { + return false + } + return *b.DismissStaleReviewsOnPush +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetID() int64 { + if b == nil || b.ID == nil { + return 0 + } + return *b.ID +} + +// GetIgnoreApprovalsFromContributors returns the IgnoreApprovalsFromContributors field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetIgnoreApprovalsFromContributors() bool { + if b == nil || b.IgnoreApprovalsFromContributors == nil { + return false + } + return *b.IgnoreApprovalsFromContributors +} + +// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetLinearHistoryRequirementEnforcementLevel() string { + if b == nil || b.LinearHistoryRequirementEnforcementLevel == nil { + return "" + } + return *b.LinearHistoryRequirementEnforcementLevel +} + +// GetMergeQueueEnforcementLevel returns the MergeQueueEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetMergeQueueEnforcementLevel() string { + if b == nil || b.MergeQueueEnforcementLevel == nil { + return "" + } + return *b.MergeQueueEnforcementLevel +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetPullRequestReviewsEnforcementLevel() string { + if b == nil || b.PullRequestReviewsEnforcementLevel == nil { + return "" + } + return *b.PullRequestReviewsEnforcementLevel +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRepositoryID() int64 { + if b == nil || b.RepositoryID == nil { + return 0 + } + return *b.RepositoryID +} + +// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequireCodeOwnerReview() bool { + if b == nil || b.RequireCodeOwnerReview == nil { + return false + } + return *b.RequireCodeOwnerReview +} + +// GetRequiredApprovingReviewCount returns the RequiredApprovingReviewCount field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredApprovingReviewCount() int { + if b == nil || b.RequiredApprovingReviewCount == nil { + return 0 + } + return *b.RequiredApprovingReviewCount +} + +// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredConversationResolutionLevel() string { + if b == nil || b.RequiredConversationResolutionLevel == nil { + return "" + } + return *b.RequiredConversationResolutionLevel +} + +// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredDeploymentsEnforcementLevel() string { + if b == nil || b.RequiredDeploymentsEnforcementLevel == nil { + return "" + } + return *b.RequiredDeploymentsEnforcementLevel +} + +// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredStatusChecksEnforcementLevel() string { + if b == nil || b.RequiredStatusChecksEnforcementLevel == nil { + return "" + } + return *b.RequiredStatusChecksEnforcementLevel +} + +// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetSignatureRequirementEnforcementLevel() string { + if b == nil || b.SignatureRequirementEnforcementLevel == nil { + return "" + } + return *b.SignatureRequirementEnforcementLevel +} + +// GetStrictRequiredStatusChecksPolicy returns the StrictRequiredStatusChecksPolicy field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetStrictRequiredStatusChecksPolicy() bool { + if b == nil || b.StrictRequiredStatusChecksPolicy == nil { + return false + } + return *b.StrictRequiredStatusChecksPolicy +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetUpdatedAt() Timestamp { + if b == nil || b.UpdatedAt == nil { + return Timestamp{} + } + return *b.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRuleEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetChanges returns the Changes field. +func (b *BranchProtectionRuleEvent) GetChanges() *ProtectionChanges { + if b == nil { + return nil + } + return b.Changes +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionRuleEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionRuleEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionRuleEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetRule returns the Rule field. +func (b *BranchProtectionRuleEvent) GetRule() *BranchProtectionRule { + if b == nil { + return nil + } + return b.Rule +} + +// GetSender returns the Sender field. +func (b *BranchProtectionRuleEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + +// GetActorID returns the ActorID field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetActorID() int64 { + if b == nil || b.ActorID == nil { + return 0 + } + return *b.ActorID +} + +// GetActorType returns the ActorType field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetActorType() string { + if b == nil || b.ActorType == nil { + return "" + } + return *b.ActorType +} + +// GetBypassMode returns the BypassMode field if it's non-nil, zero value otherwise. +func (b *BypassActor) GetBypassMode() string { + if b == nil || b.BypassMode == nil { + return "" + } + return *b.BypassMode +} + +// GetApp returns the App field. +func (c *CheckRun) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckRun) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOutput returns the Output field. +func (c *CheckRun) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAnnotationLevel returns the AnnotationLevel field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetAnnotationLevel() string { + if c == nil || c.AnnotationLevel == nil { + return "" + } + return *c.AnnotationLevel +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndColumn() int { + if c == nil || c.EndColumn == nil { + return 0 + } + return *c.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndLine() int { + if c == nil || c.EndLine == nil { + return 0 + } + return *c.EndLine +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetRawDetails() string { + if c == nil || c.RawDetails == nil { + return "" + } + return *c.RawDetails +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartColumn() int { + if c == nil || c.StartColumn == nil { + return 0 + } + return *c.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartLine() int { + if c == nil || c.StartLine == nil { + return 0 + } + return *c.StartLine +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckRunEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckRun returns the CheckRun field. +func (c *CheckRunEvent) GetCheckRun() *CheckRun { + if c == nil { + return nil + } + return c.CheckRun +} + +// GetInstallation returns the Installation field. +func (c *CheckRunEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckRunEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckRunEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetRequestedAction returns the RequestedAction field. +func (c *CheckRunEvent) GetRequestedAction() *RequestedAction { + if c == nil { + return nil + } + return c.RequestedAction +} + +// GetSender returns the Sender field. +func (c *CheckRunEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAlt returns the Alt field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetAlt() string { + if c == nil || c.Alt == nil { + return "" + } + return *c.Alt +} + +// GetCaption returns the Caption field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetCaption() string { + if c == nil || c.Caption == nil { + return "" + } + return *c.Caption +} + +// GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetImageURL() string { + if c == nil || c.ImageURL == nil { + return "" + } + return *c.ImageURL +} + +// GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsCount() int { + if c == nil || c.AnnotationsCount == nil { + return 0 + } + return *c.AnnotationsCount +} + +// GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsURL() string { + if c == nil || c.AnnotationsURL == nil { + return "" + } + return *c.AnnotationsURL +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetSummary() string { + if c == nil || c.Summary == nil { + return "" + } + return *c.Summary +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetText() string { + if c == nil || c.Text == nil { + return "" + } + return *c.Text +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetAfterSHA() string { + if c == nil || c.AfterSHA == nil { + return "" + } + return *c.AfterSHA +} + +// GetApp returns the App field. +func (c *CheckSuite) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetBeforeSHA() string { + if c == nil || c.BeforeSHA == nil { + return "" + } + return *c.BeforeSHA +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (c *CheckSuite) GetHeadCommit() *Commit { + if c == nil { + return nil + } + return c.HeadCommit +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLatestCheckRunsCount returns the LatestCheckRunsCount field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetLatestCheckRunsCount() int64 { + if c == nil || c.LatestCheckRunsCount == nil { + return 0 + } + return *c.LatestCheckRunsCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetRepository returns the Repository field. +func (c *CheckSuite) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetRerequstable returns the Rerequstable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRerequstable() bool { + if c == nil || c.Rerequstable == nil { + return false + } + return *c.Rerequstable +} + +// GetRunsRerequstable returns the RunsRerequstable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRunsRerequstable() bool { + if c == nil || c.RunsRerequstable == nil { + return false + } + return *c.RunsRerequstable +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckSuiteEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetInstallation returns the Installation field. +func (c *CheckSuiteEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckSuiteEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckSuiteEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CheckSuiteEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetPreferences returns the Preferences field. +func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList { + if c == nil { + return nil + } + return c.Preferences +} + +// GetRepository returns the Repository field. +func (c *CheckSuitePreferenceResults) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetSuggestion returns the Suggestion field if it's non-nil, zero value otherwise. +func (c *CodeownersError) GetSuggestion() string { + if c == nil || c.Suggestion == nil { + return "" + } + return *c.Suggestion +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetContentType() string { + if c == nil || c.ContentType == nil { + return "" + } + return *c.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetLanguage() string { + if c == nil || c.Language == nil { + return "" + } + return *c.Language +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetSize() int64 { + if c == nil || c.Size == nil { + return 0 + } + return *c.Size +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (c *CodeQLDatabase) GetUploader() *User { + if c == nil { + return nil + } + return c.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRepository returns the Repository field. +func (c *CodeResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetAlert returns the Alert field. +func (c *CodeScanningAlertEvent) GetAlert() *Alert { + if c == nil { + return nil + } + return c.Alert +} + +// GetCommitOID returns the CommitOID field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetCommitOID() string { + if c == nil || c.CommitOID == nil { + return "" + } + return *c.CommitOID +} + +// GetInstallation returns the Installation field. +func (c *CodeScanningAlertEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CodeScanningAlertEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRepo returns the Repo field. +func (c *CodeScanningAlertEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CodeScanningAlertEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertState) GetDismissedComment() string { + if c == nil || c.DismissedComment == nil { + return "" + } + return *c.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertState) GetDismissedReason() string { + if c == nil || c.DismissedReason == nil { + return "" + } + return *c.DismissedReason +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdvancedSecurity returns the AdvancedSecurity field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetAdvancedSecurity() string { + if c == nil || c.AdvancedSecurity == nil { + return "" + } + return *c.AdvancedSecurity +} + +// GetCodeScanningDefaultSetup returns the CodeScanningDefaultSetup field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetCodeScanningDefaultSetup() string { + if c == nil || c.CodeScanningDefaultSetup == nil { + return "" + } + return *c.CodeScanningDefaultSetup +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDependabotAlerts returns the DependabotAlerts field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependabotAlerts() string { + if c == nil || c.DependabotAlerts == nil { + return "" + } + return *c.DependabotAlerts +} + +// GetDependabotSecurityUpdates returns the DependabotSecurityUpdates field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependabotSecurityUpdates() string { + if c == nil || c.DependabotSecurityUpdates == nil { + return "" + } + return *c.DependabotSecurityUpdates +} + +// GetDependencyGraph returns the DependencyGraph field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependencyGraph() string { + if c == nil || c.DependencyGraph == nil { + return "" + } + return *c.DependencyGraph +} + +// GetDependencyGraphAutosubmitAction returns the DependencyGraphAutosubmitAction field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDependencyGraphAutosubmitAction() string { + if c == nil || c.DependencyGraphAutosubmitAction == nil { + return "" + } + return *c.DependencyGraphAutosubmitAction +} + +// GetDependencyGraphAutosubmitActionOptions returns the DependencyGraphAutosubmitActionOptions field. +func (c *CodeSecurityConfiguration) GetDependencyGraphAutosubmitActionOptions() *DependencyGraphAutosubmitActionOptions { + if c == nil { + return nil + } + return c.DependencyGraphAutosubmitActionOptions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetEnforcement() string { + if c == nil || c.Enforcement == nil { + return "" + } + return *c.Enforcement +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPrivateVulnerabilityReporting returns the PrivateVulnerabilityReporting field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetPrivateVulnerabilityReporting() string { + if c == nil || c.PrivateVulnerabilityReporting == nil { + return "" + } + return *c.PrivateVulnerabilityReporting +} + +// GetSecretScanning returns the SecretScanning field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanning() string { + if c == nil || c.SecretScanning == nil { + return "" + } + return *c.SecretScanning +} + +// GetSecretScanningNonProviderPatterns returns the SecretScanningNonProviderPatterns field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningNonProviderPatterns() string { + if c == nil || c.SecretScanningNonProviderPatterns == nil { + return "" + } + return *c.SecretScanningNonProviderPatterns +} + +// GetSecretScanningPushProtection returns the SecretScanningPushProtection field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningPushProtection() string { + if c == nil || c.SecretScanningPushProtection == nil { + return "" + } + return *c.SecretScanningPushProtection +} + +// GetSecretScanningValidityChecks returns the SecretScanningValidityChecks field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetSecretScanningValidityChecks() string { + if c == nil || c.SecretScanningValidityChecks == nil { + return "" + } + return *c.SecretScanningValidityChecks +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetTargetType() string { + if c == nil || c.TargetType == nil { + return "" + } + return *c.TargetType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfiguration) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetConfiguration returns the Configuration field. +func (c *CodeSecurityConfigurationWithDefaultForNewRepos) GetConfiguration() *CodeSecurityConfiguration { + if c == nil { + return nil + } + return c.Configuration +} + +// GetDefaultForNewRepos returns the DefaultForNewRepos field if it's non-nil, zero value otherwise. +func (c *CodeSecurityConfigurationWithDefaultForNewRepos) GetDefaultForNewRepos() string { + if c == nil || c.DefaultForNewRepos == nil { + return "" + } + return *c.DefaultForNewRepos +} + +// GetBillableOwner returns the BillableOwner field. +func (c *Codespace) GetBillableOwner() *User { + if c == nil { + return nil + } + return c.BillableOwner +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise. +func (c *Codespace) GetDevcontainerPath() string { + if c == nil || c.DevcontainerPath == nil { + return "" + } + return *c.DevcontainerPath +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *Codespace) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetEnvironmentID returns the EnvironmentID field if it's non-nil, zero value otherwise. +func (c *Codespace) GetEnvironmentID() string { + if c == nil || c.EnvironmentID == nil { + return "" + } + return *c.EnvironmentID +} + +// GetGitStatus returns the GitStatus field. +func (c *Codespace) GetGitStatus() *CodespacesGitStatus { + if c == nil { + return nil + } + return c.GitStatus +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Codespace) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise. +func (c *Codespace) GetIdleTimeoutMinutes() int { + if c == nil || c.IdleTimeoutMinutes == nil { + return 0 + } + return *c.IdleTimeoutMinutes +} + +// GetIdleTimeoutNotice returns the IdleTimeoutNotice field if it's non-nil, zero value otherwise. +func (c *Codespace) GetIdleTimeoutNotice() string { + if c == nil || c.IdleTimeoutNotice == nil { + return "" + } + return *c.IdleTimeoutNotice +} + +// GetLastKnownStopNotice returns the LastKnownStopNotice field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLastKnownStopNotice() string { + if c == nil || c.LastKnownStopNotice == nil { + return "" + } + return *c.LastKnownStopNotice +} + +// GetLastUsedAt returns the LastUsedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLastUsedAt() Timestamp { + if c == nil || c.LastUsedAt == nil { + return Timestamp{} + } + return *c.LastUsedAt +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (c *Codespace) GetLocation() string { + if c == nil || c.Location == nil { + return "" + } + return *c.Location +} + +// GetMachine returns the Machine field. +func (c *Codespace) GetMachine() *CodespacesMachine { + if c == nil { + return nil + } + return c.Machine +} + +// GetMachinesURL returns the MachinesURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetMachinesURL() string { + if c == nil || c.MachinesURL == nil { + return "" + } + return *c.MachinesURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Codespace) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOwner returns the Owner field. +func (c *Codespace) GetOwner() *User { + if c == nil { + return nil + } + return c.Owner +} + +// GetPendingOperation returns the PendingOperation field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPendingOperation() bool { + if c == nil || c.PendingOperation == nil { + return false + } + return *c.PendingOperation +} + +// GetPendingOperationDisabledReason returns the PendingOperationDisabledReason field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPendingOperationDisabledReason() string { + if c == nil || c.PendingOperationDisabledReason == nil { + return "" + } + return *c.PendingOperationDisabledReason +} + +// GetPrebuild returns the Prebuild field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPrebuild() bool { + if c == nil || c.Prebuild == nil { + return false + } + return *c.Prebuild +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetPullsURL() string { + if c == nil || c.PullsURL == nil { + return "" + } + return *c.PullsURL +} + +// GetRepository returns the Repository field. +func (c *Codespace) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetRetentionExpiresAt returns the RetentionExpiresAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetRetentionExpiresAt() Timestamp { + if c == nil || c.RetentionExpiresAt == nil { + return Timestamp{} + } + return *c.RetentionExpiresAt +} + +// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise. +func (c *Codespace) GetRetentionPeriodMinutes() int { + if c == nil || c.RetentionPeriodMinutes == nil { + return 0 + } + return *c.RetentionPeriodMinutes +} + +// GetRuntimeConstraints returns the RuntimeConstraints field. +func (c *Codespace) GetRuntimeConstraints() *CodespacesRuntimeConstraints { + if c == nil { + return nil + } + return c.RuntimeConstraints +} + +// GetStartURL returns the StartURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetStartURL() string { + if c == nil || c.StartURL == nil { + return "" + } + return *c.StartURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *Codespace) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetStopURL returns the StopURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetStopURL() string { + if c == nil || c.StopURL == nil { + return "" + } + return *c.StopURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *Codespace) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetWebURL returns the WebURL field if it's non-nil, zero value otherwise. +func (c *Codespace) GetWebURL() string { + if c == nil || c.WebURL == nil { + return "" + } + return *c.WebURL +} + +// GetAhead returns the Ahead field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetAhead() int { + if c == nil || c.Ahead == nil { + return 0 + } + return *c.Ahead +} + +// GetBehind returns the Behind field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetBehind() int { + if c == nil || c.Behind == nil { + return 0 + } + return *c.Behind +} + +// GetHasUncommittedChanges returns the HasUncommittedChanges field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetHasUncommittedChanges() bool { + if c == nil || c.HasUncommittedChanges == nil { + return false + } + return *c.HasUncommittedChanges +} + +// GetHasUnpushedChanges returns the HasUnpushedChanges field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetHasUnpushedChanges() bool { + if c == nil || c.HasUnpushedChanges == nil { + return false + } + return *c.HasUnpushedChanges +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CodespacesGitStatus) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetCPUs returns the CPUs field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetCPUs() int { + if c == nil || c.CPUs == nil { + return 0 + } + return *c.CPUs +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetMemoryInBytes returns the MemoryInBytes field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetMemoryInBytes() int64 { + if c == nil || c.MemoryInBytes == nil { + return 0 + } + return *c.MemoryInBytes +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOperatingSystem returns the OperatingSystem field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetOperatingSystem() string { + if c == nil || c.OperatingSystem == nil { + return "" + } + return *c.OperatingSystem +} + +// GetPrebuildAvailability returns the PrebuildAvailability field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetPrebuildAvailability() string { + if c == nil || c.PrebuildAvailability == nil { + return "" + } + return *c.PrebuildAvailability +} + +// GetStorageInBytes returns the StorageInBytes field if it's non-nil, zero value otherwise. +func (c *CodespacesMachine) GetStorageInBytes() int64 { + if c == nil || c.StorageInBytes == nil { + return 0 + } + return *c.StorageInBytes +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetInvitee returns the Invitee field. +func (c *CollaboratorInvitation) GetInvitee() *User { + if c == nil { + return nil + } + return c.Invitee +} + +// GetInviter returns the Inviter field. +func (c *CollaboratorInvitation) GetInviter() *User { + if c == nil { + return nil + } + return c.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetPermissions() string { + if c == nil || c.Permissions == nil { + return "" + } + return *c.Permissions +} + +// GetRepo returns the Repo field. +func (c *CollaboratorInvitation) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetCommitURL() string { + if c == nil || c.CommitURL == nil { + return "" + } + return *c.CommitURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetTotalCount() int { + if c == nil || c.TotalCount == nil { + return 0 + } + return *c.TotalCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *Comment) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetAuthorAssociation() string { + if c == nil || c.AuthorAssociation == nil { + return "" + } + return *c.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetChildCommentCount returns the ChildCommentCount field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetChildCommentCount() int { + if c == nil || c.ChildCommentCount == nil { + return 0 + } + return *c.ChildCommentCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDiscussionID returns the DiscussionID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetDiscussionID() int64 { + if c == nil || c.DiscussionID == nil { + return 0 + } + return *c.DiscussionID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetParentID returns the ParentID field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetParentID() int64 { + if c == nil || c.ParentID == nil { + return 0 + } + return *c.ParentID +} + +// GetReactions returns the Reactions field. +func (c *CommentDiscussion) GetReactions() *Reactions { + if c == nil { + return nil + } + return c.Reactions +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommentDiscussion) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetUser returns the User field. +func (c *CommentDiscussion) GetUser() *User { + if c == nil { + return nil + } + return c.User +} + +// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalCommitComments() int { + if c == nil || c.TotalCommitComments == nil { + return 0 + } + return *c.TotalCommitComments +} + +// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalGistComments() int { + if c == nil || c.TotalGistComments == nil { + return 0 + } + return *c.TotalGistComments +} + +// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalIssueComments() int { + if c == nil || c.TotalIssueComments == nil { + return 0 + } + return *c.TotalIssueComments +} + +// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalPullRequestComments() int { + if c == nil || c.TotalPullRequestComments == nil { + return 0 + } + return *c.TotalPullRequestComments +} + +// GetAuthor returns the Author field. +func (c *Commit) GetAuthor() *CommitAuthor { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. +func (c *Commit) GetCommentCount() int { + if c == nil || c.CommentCount == nil { + return 0 + } + return *c.CommentCount +} + +// GetCommitter returns the Committer field. +func (c *Commit) GetCommitter() *CommitAuthor { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Commit) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *Commit) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Commit) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *Commit) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetTree returns the Tree field. +func (c *Commit) GetTree() *Tree { + if c == nil { + return nil + } + return c.Tree +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Commit) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetVerification returns the Verification field. +func (c *Commit) GetVerification() *SignatureVerification { + if c == nil { + return nil + } + return c.Verification +} + +// GetDate returns the Date field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetDate() Timestamp { + if c == nil || c.Date == nil { + return Timestamp{} + } + return *c.Date +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CommitCommentEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetComment returns the Comment field. +func (c *CommitCommentEvent) GetComment() *RepositoryComment { + if c == nil { + return nil + } + return c.Comment +} + +// GetInstallation returns the Installation field. +func (c *CommitCommentEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CommitCommentEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CommitCommentEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CommitCommentEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetBlobURL() string { + if c == nil || c.BlobURL == nil { + return "" + } + return *c.BlobURL +} + +// GetChanges returns the Changes field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetChanges() int { + if c == nil || c.Changes == nil { + return 0 + } + return *c.Changes +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetContentsURL() string { + if c == nil || c.ContentsURL == nil { + return "" + } + return *c.ContentsURL +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetFilename() string { + if c == nil || c.Filename == nil { + return "" + } + return *c.Filename +} + +// GetPatch returns the Patch field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPatch() string { + if c == nil || c.Patch == nil { + return "" + } + return *c.Patch +} + +// GetPreviousFilename returns the PreviousFilename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPreviousFilename() string { + if c == nil || c.PreviousFilename == nil { + return "" + } + return *c.PreviousFilename +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetRawURL() string { + if c == nil || c.RawURL == nil { + return "" + } + return *c.RawURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetAuthor returns the Author field. +func (c *CommitResult) GetAuthor() *User { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetCommentsURL() string { + if c == nil || c.CommentsURL == nil { + return "" + } + return *c.CommentsURL +} + +// GetCommit returns the Commit field. +func (c *CommitResult) GetCommit() *Commit { + if c == nil { + return nil + } + return c.Commit +} + +// GetCommitter returns the Committer field. +func (c *CommitResult) GetCommitter() *User { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetRepository returns the Repository field. +func (c *CommitResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetScore returns the Score field. +func (c *CommitResult) GetScore() *float64 { + if c == nil { + return nil + } + return c.Score +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetAheadBy() int { + if c == nil || c.AheadBy == nil { + return 0 + } + return *c.AheadBy +} + +// GetBaseCommit returns the BaseCommit field. +func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.BaseCommit +} + +// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetBehindBy() int { + if c == nil || c.BehindBy == nil { + return 0 + } + return *c.BehindBy +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetDiffURL() string { + if c == nil || c.DiffURL == nil { + return "" + } + return *c.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMergeBaseCommit returns the MergeBaseCommit field. +func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.MergeBaseCommit +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPatchURL() string { + if c == nil || c.PatchURL == nil { + return "" + } + return *c.PatchURL +} + +// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPermalinkURL() string { + if c == nil || c.PermalinkURL == nil { + return "" + } + return *c.PermalinkURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetTotalCommits() int { + if c == nil || c.TotalCommits == nil { + return 0 + } + return *c.TotalCommits +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { + if c == nil { + return nil + } + return c.CodeOfConduct +} + +// GetCodeOfConductFile returns the CodeOfConductFile field. +func (c *CommunityHealthFiles) GetCodeOfConductFile() *Metric { + if c == nil { + return nil + } + return c.CodeOfConductFile +} + +// GetContributing returns the Contributing field. +func (c *CommunityHealthFiles) GetContributing() *Metric { + if c == nil { + return nil + } + return c.Contributing +} + +// GetIssueTemplate returns the IssueTemplate field. +func (c *CommunityHealthFiles) GetIssueTemplate() *Metric { + if c == nil { + return nil + } + return c.IssueTemplate +} + +// GetLicense returns the License field. +func (c *CommunityHealthFiles) GetLicense() *Metric { + if c == nil { + return nil + } + return c.License +} + +// GetPullRequestTemplate returns the PullRequestTemplate field. +func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric { + if c == nil { + return nil + } + return c.PullRequestTemplate +} + +// GetReadme returns the Readme field. +func (c *CommunityHealthFiles) GetReadme() *Metric { + if c == nil { + return nil + } + return c.Readme +} + +// GetContentReportsEnabled returns the ContentReportsEnabled field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetContentReportsEnabled() bool { + if c == nil || c.ContentReportsEnabled == nil { + return false + } + return *c.ContentReportsEnabled +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetDocumentation returns the Documentation field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDocumentation() string { + if c == nil || c.Documentation == nil { + return "" + } + return *c.Documentation +} + +// GetFiles returns the Files field. +func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { + if c == nil { + return nil + } + return c.Files +} + +// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetHealthPercentage() int { + if c == nil || c.HealthPercentage == nil { + return 0 + } + return *c.HealthPercentage +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetReference returns the Reference field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetReference() string { + if c == nil || c.Reference == nil { + return "" + } + return *c.Reference +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *ContentReferenceEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetContentReference returns the ContentReference field. +func (c *ContentReferenceEvent) GetContentReference() *ContentReference { + if c == nil { + return nil + } + return c.ContentReference +} + +// GetInstallation returns the Installation field. +func (c *ContentReferenceEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *ContentReferenceEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *ContentReferenceEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetAvatarURL() string { + if c == nil || c.AvatarURL == nil { + return "" + } + return *c.AvatarURL +} + +// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. +func (c *Contributor) GetContributions() int { + if c == nil || c.Contributions == nil { + return 0 + } + return *c.Contributions +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEventsURL() string { + if c == nil || c.EventsURL == nil { + return "" + } + return *c.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowersURL() string { + if c == nil || c.FollowersURL == nil { + return "" + } + return *c.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowingURL() string { + if c == nil || c.FollowingURL == nil { + return "" + } + return *c.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGistsURL() string { + if c == nil || c.GistsURL == nil { + return "" + } + return *c.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGravatarID() string { + if c == nil || c.GravatarID == nil { + return "" + } + return *c.GravatarID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *Contributor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Contributor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetOrganizationsURL() string { + if c == nil || c.OrganizationsURL == nil { + return "" + } + return *c.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReceivedEventsURL() string { + if c == nil || c.ReceivedEventsURL == nil { + return "" + } + return *c.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReposURL() string { + if c == nil || c.ReposURL == nil { + return "" + } + return *c.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSiteAdmin() bool { + if c == nil || c.SiteAdmin == nil { + return false + } + return *c.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetStarredURL() string { + if c == nil || c.StarredURL == nil { + return "" + } + return *c.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSubscriptionsURL() string { + if c == nil || c.SubscriptionsURL == nil { + return "" + } + return *c.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Contributor) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAuthor returns the Author field. +func (c *ContributorStats) GetAuthor() *Contributor { + if c == nil { + return nil + } + return c.Author +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *ContributorStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomPullRequestsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDEChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDECodeCompletionsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCopilotDotcomChat returns the CopilotDotcomChat field. +func (c *CopilotMetrics) GetCopilotDotcomChat() *CopilotDotcomChat { + if c == nil { + return nil + } + return c.CopilotDotcomChat +} + +// GetCopilotDotcomPullRequests returns the CopilotDotcomPullRequests field. +func (c *CopilotMetrics) GetCopilotDotcomPullRequests() *CopilotDotcomPullRequests { + if c == nil { + return nil + } + return c.CopilotDotcomPullRequests +} + +// GetCopilotIDEChat returns the CopilotIDEChat field. +func (c *CopilotMetrics) GetCopilotIDEChat() *CopilotIDEChat { + if c == nil { + return nil + } + return c.CopilotIDEChat +} + +// GetCopilotIDECodeCompletions returns the CopilotIDECodeCompletions field. +func (c *CopilotMetrics) GetCopilotIDECodeCompletions() *CopilotIDECodeCompletions { + if c == nil { + return nil + } + return c.CopilotIDECodeCompletions +} + +// GetTotalActiveUsers returns the TotalActiveUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalActiveUsers() int { + if c == nil || c.TotalActiveUsers == nil { + return 0 + } + return *c.TotalActiveUsers +} + +// GetTotalEngagedUsers returns the TotalEngagedUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalEngagedUsers() int { + if c == nil || c.TotalEngagedUsers == nil { + return 0 + } + return *c.TotalEngagedUsers +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetSince() time.Time { + if c == nil || c.Since == nil { + return time.Time{} + } + return *c.Since +} + +// GetUntil returns the Until field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetUntil() time.Time { + if c == nil || c.Until == nil { + return time.Time{} + } + return *c.Until +} + +// GetSeatBreakdown returns the SeatBreakdown field. +func (c *CopilotOrganizationDetails) GetSeatBreakdown() *CopilotSeatBreakdown { + if c == nil { + return nil + } + return c.SeatBreakdown +} + +// GetAssigningTeam returns the AssigningTeam field. +func (c *CopilotSeatDetails) GetAssigningTeam() *Team { + if c == nil { + return nil + } + return c.AssigningTeam +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetLastActivityAt returns the LastActivityAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetLastActivityAt() Timestamp { + if c == nil || c.LastActivityAt == nil { + return Timestamp{} + } + return *c.LastActivityAt +} + +// GetLastActivityEditor returns the LastActivityEditor field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetLastActivityEditor() string { + if c == nil || c.LastActivityEditor == nil { + return "" + } + return *c.LastActivityEditor +} + +// GetPendingCancellationDate returns the PendingCancellationDate field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetPendingCancellationDate() string { + if c == nil || c.PendingCancellationDate == nil { + return "" + } + return *c.PendingCancellationDate +} + +// GetPlanType returns the PlanType field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetPlanType() string { + if c == nil || c.PlanType == nil { + return "" + } + return *c.PlanType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CopilotSeatDetails) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetOutput returns the Output field. +func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CreateCheckSuiteOptions) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetClientIP returns the ClientIP field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetClientIP() string { + if c == nil || c.ClientIP == nil { + return "" + } + return *c.ClientIP +} + +// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetDevcontainerPath() string { + if c == nil || c.DevcontainerPath == nil { + return "" + } + return *c.DevcontainerPath +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetDisplayName() string { + if c == nil || c.DisplayName == nil { + return "" + } + return *c.DisplayName +} + +// GetGeo returns the Geo field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetGeo() string { + if c == nil || c.Geo == nil { + return "" + } + return *c.Geo +} + +// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetIdleTimeoutMinutes() int { + if c == nil || c.IdleTimeoutMinutes == nil { + return 0 + } + return *c.IdleTimeoutMinutes +} + +// GetMachine returns the Machine field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetMachine() string { + if c == nil || c.Machine == nil { + return "" + } + return *c.Machine +} + +// GetMultiRepoPermissionsOptOut returns the MultiRepoPermissionsOptOut field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetMultiRepoPermissionsOptOut() bool { + if c == nil || c.MultiRepoPermissionsOptOut == nil { + return false + } + return *c.MultiRepoPermissionsOptOut +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetRetentionPeriodMinutes() int { + if c == nil || c.RetentionPeriodMinutes == nil { + return 0 + } + return *c.RetentionPeriodMinutes +} + +// GetWorkingDirectory returns the WorkingDirectory field if it's non-nil, zero value otherwise. +func (c *CreateCodespaceOptions) GetWorkingDirectory() string { + if c == nil || c.WorkingDirectory == nil { + return "" + } + return *c.WorkingDirectory +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if c == nil || c.AllowsPublicRepositories == nil { + return false + } + return *c.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if c == nil || c.RestrictedToWorkflows == nil { + return false + } + return *c.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (c *CreateEnterpriseRunnerGroupRequest) GetVisibility() string { + if c == nil || c.Visibility == nil { + return "" + } + return *c.Visibility +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetInstallation returns the Installation field. +func (c *CreateEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetMasterBranch() string { + if c == nil || c.MasterBranch == nil { + return "" + } + return *c.MasterBranch +} + +// GetOrg returns the Org field. +func (c *CreateEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetPusherType() string { + if c == nil || c.PusherType == nil { + return "" + } + return *c.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRefType() string { + if c == nil || c.RefType == nil { + return "" + } + return *c.RefType +} + +// GetRepo returns the Repo field. +func (c *CreateEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CreateEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { + if c == nil || c.InviteeID == nil { + return 0 + } + return *c.InviteeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetRole() string { + if c == nil || c.Role == nil { + return "" + } + return *c.Role +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateCustomRepoRoleOptions) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateOrUpdateOrgRoleOptions) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (c *CreateProtectedChanges) GetFrom() bool { + if c == nil || c.From == nil { + return false + } + return *c.From +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if c == nil || c.AllowsPublicRepositories == nil { + return false + } + return *c.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if c == nil || c.RestrictedToWorkflows == nil { + return false + } + return *c.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetVisibility() string { + if c == nil || c.Visibility == nil { + return "" + } + return *c.Visibility +} + +// GetCanAdminsBypass returns the CanAdminsBypass field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetCanAdminsBypass() bool { + if c == nil || c.CanAdminsBypass == nil { + return false + } + return *c.CanAdminsBypass +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (c *CreateUpdateEnvironment) GetDeploymentBranchPolicy() *BranchPolicy { + if c == nil { + return nil + } + return c.DeploymentBranchPolicy +} + +// GetPreventSelfReview returns the PreventSelfReview field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetPreventSelfReview() bool { + if c == nil || c.PreventSelfReview == nil { + return false + } + return *c.PreventSelfReview +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetWaitTimer() int { + if c == nil || c.WaitTimer == nil { + return 0 + } + return *c.WaitTimer +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetRepositoryID() int64 { + if c == nil || c.RepositoryID == nil { + return 0 + } + return *c.RepositoryID +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetScope() string { + if c == nil || c.Scope == nil { + return "" + } + return *c.Scope +} + +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (c *CreateUpdateRequiredWorkflowOptions) GetSelectedRepositoryIDs() *SelectedRepoIDs { + if c == nil { + return nil + } + return c.SelectedRepositoryIDs +} + +// GetWorkflowFilePath returns the WorkflowFilePath field if it's non-nil, zero value otherwise. +func (c *CreateUpdateRequiredWorkflowOptions) GetWorkflowFilePath() string { + if c == nil || c.WorkflowFilePath == nil { + return "" + } + return *c.WorkflowFilePath +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateUserRequest) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetSuspended returns the Suspended field if it's non-nil, zero value otherwise. +func (c *CreateUserRequest) GetSuspended() bool { + if c == nil || c.Suspended == nil { + return false + } + return *c.Suspended +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (c *CreationInfo) GetCreated() Timestamp { + if c == nil || c.Created == nil { + return Timestamp{} + } + return *c.Created +} + +// GetAuthorizedCredentialExpiresAt returns the AuthorizedCredentialExpiresAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialExpiresAt() Timestamp { + if c == nil || c.AuthorizedCredentialExpiresAt == nil { + return Timestamp{} + } + return *c.AuthorizedCredentialExpiresAt +} + +// GetAuthorizedCredentialID returns the AuthorizedCredentialID field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialID() int64 { + if c == nil || c.AuthorizedCredentialID == nil { + return 0 + } + return *c.AuthorizedCredentialID +} + +// GetAuthorizedCredentialNote returns the AuthorizedCredentialNote field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialNote() string { + if c == nil || c.AuthorizedCredentialNote == nil { + return "" + } + return *c.AuthorizedCredentialNote +} + +// GetAuthorizedCredentialTitle returns the AuthorizedCredentialTitle field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetAuthorizedCredentialTitle() string { + if c == nil || c.AuthorizedCredentialTitle == nil { + return "" + } + return *c.AuthorizedCredentialTitle +} + +// GetCredentialAccessedAt returns the CredentialAccessedAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialAccessedAt() Timestamp { + if c == nil || c.CredentialAccessedAt == nil { + return Timestamp{} + } + return *c.CredentialAccessedAt +} + +// GetCredentialAuthorizedAt returns the CredentialAuthorizedAt field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialAuthorizedAt() Timestamp { + if c == nil || c.CredentialAuthorizedAt == nil { + return Timestamp{} + } + return *c.CredentialAuthorizedAt +} + +// GetCredentialID returns the CredentialID field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialID() int64 { + if c == nil || c.CredentialID == nil { + return 0 + } + return *c.CredentialID +} + +// GetCredentialType returns the CredentialType field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetCredentialType() string { + if c == nil || c.CredentialType == nil { + return "" + } + return *c.CredentialType +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetFingerprint() string { + if c == nil || c.Fingerprint == nil { + return "" + } + return *c.Fingerprint +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (c *CredentialAuthorization) GetTokenLastEight() string { + if c == nil || c.TokenLastEight == nil { + return "" + } + return *c.TokenLastEight +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Credit) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetUser returns the User field. +func (c *Credit) GetUser() *User { + if c == nil { + return nil + } + return c.User +} + +// GetApp returns the App field. +func (c *CustomDeploymentProtectionRule) GetApp() *CustomDeploymentProtectionRuleApp { + if c == nil { + return nil + } + return c.App +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRule) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetIntegrationURL returns the IntegrationURL field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetIntegrationURL() string { + if c == nil || c.IntegrationURL == nil { + return "" + } + return *c.IntegrationURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleApp) GetSlug() string { + if c == nil || c.Slug == nil { + return "" + } + return *c.Slug +} + +// GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise. +func (c *CustomDeploymentProtectionRuleRequest) GetIntegrationID() int64 { + if c == nil || c.IntegrationID == nil { + return 0 + } + return *c.IntegrationID +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOrg returns the Org field. +func (c *CustomOrgRoles) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetSource() string { + if c == nil || c.Source == nil { + return "" + } + return *c.Source +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CustomOrgRoles) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetDefaultValue returns the DefaultValue field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetDefaultValue() string { + if c == nil || c.DefaultValue == nil { + return "" + } + return *c.DefaultValue +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetPropertyName returns the PropertyName field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetPropertyName() string { + if c == nil || c.PropertyName == nil { + return "" + } + return *c.PropertyName +} + +// GetRequired returns the Required field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetRequired() bool { + if c == nil || c.Required == nil { + return false + } + return *c.Required +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetSourceType() string { + if c == nil || c.SourceType == nil { + return "" + } + return *c.SourceType +} + +// GetValuesEditableBy returns the ValuesEditableBy field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetValuesEditableBy() string { + if c == nil || c.ValuesEditableBy == nil { + return "" + } + return *c.ValuesEditableBy +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CustomPropertyEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetDefinition returns the Definition field. +func (c *CustomPropertyEvent) GetDefinition() *CustomProperty { + if c == nil { + return nil + } + return c.Definition +} + +// GetEnterprise returns the Enterprise field. +func (c *CustomPropertyEvent) GetEnterprise() *Enterprise { + if c == nil { + return nil + } + return c.Enterprise +} + +// GetInstallation returns the Installation field. +func (c *CustomPropertyEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CustomPropertyEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetSender returns the Sender field. +func (c *CustomPropertyEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CustomPropertyValuesEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetEnterprise returns the Enterprise field. +func (c *CustomPropertyValuesEvent) GetEnterprise() *Enterprise { + if c == nil { + return nil + } + return c.Enterprise +} + +// GetInstallation returns the Installation field. +func (c *CustomPropertyValuesEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CustomPropertyValuesEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CustomPropertyValuesEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CustomPropertyValuesEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetBaseRole returns the BaseRole field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetBaseRole() string { + if c == nil || c.BaseRole == nil { + return "" + } + return *c.BaseRole +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetOrg returns the Org field. +func (c *CustomRepoRoles) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetQuerySuite() string { + if d == nil || d.QuerySuite == nil { + return "" + } + return *d.QuerySuite +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DefaultSetupConfiguration) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionEnterprise) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionEnterprise) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionOrganization) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionOrganization) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetCanApprovePullRequestReviews returns the CanApprovePullRequestReviews field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionRepository) GetCanApprovePullRequestReviews() bool { + if d == nil || d.CanApprovePullRequestReviews == nil { + return false + } + return *d.CanApprovePullRequestReviews +} + +// GetDefaultWorkflowPermissions returns the DefaultWorkflowPermissions field if it's non-nil, zero value otherwise. +func (d *DefaultWorkflowPermissionRepository) GetDefaultWorkflowPermissions() string { + if d == nil || d.DefaultWorkflowPermissions == nil { + return "" + } + return *d.DefaultWorkflowPermissions +} + +// GetConfirmDeleteURL returns the ConfirmDeleteURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetConfirmDeleteURL() string { + if d == nil || d.ConfirmDeleteURL == nil { + return "" + } + return *d.ConfirmDeleteURL +} + +// GetNextAnalysisURL returns the NextAnalysisURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetNextAnalysisURL() string { + if d == nil || d.NextAnalysisURL == nil { + return "" + } + return *d.NextAnalysisURL +} + +// GetInstallation returns the Installation field. +func (d *DeleteEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeleteEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetPusherType() string { + if d == nil || d.PusherType == nil { + return "" + } + return *d.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRefType() string { + if d == nil || d.RefType == nil { + return "" + } + return *d.RefType +} + +// GetRepo returns the Repo field. +func (d *DeleteEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeleteEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoDismissedAt returns the AutoDismissedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetAutoDismissedAt() Timestamp { + if d == nil || d.AutoDismissedAt == nil { + return Timestamp{} + } + return *d.AutoDismissedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDependency returns the Dependency field. +func (d *DependabotAlert) GetDependency() *Dependency { + if d == nil { + return nil + } + return d.Dependency +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedAt() Timestamp { + if d == nil || d.DismissedAt == nil { + return Timestamp{} + } + return *d.DismissedAt +} + +// GetDismissedBy returns the DismissedBy field. +func (d *DependabotAlert) GetDismissedBy() *User { + if d == nil { + return nil + } + return d.DismissedBy +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedComment() string { + if d == nil || d.DismissedComment == nil { + return "" + } + return *d.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetDismissedReason() string { + if d == nil || d.DismissedReason == nil { + return "" + } + return *d.DismissedReason +} + +// GetFixedAt returns the FixedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetFixedAt() Timestamp { + if d == nil || d.FixedAt == nil { + return Timestamp{} + } + return *d.FixedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetRepository returns the Repository field. +func (d *DependabotAlert) GetRepository() *Repository { + if d == nil { + return nil + } + return d.Repository +} + +// GetSecurityAdvisory returns the SecurityAdvisory field. +func (d *DependabotAlert) GetSecurityAdvisory() *DependabotSecurityAdvisory { + if d == nil { + return nil + } + return d.SecurityAdvisory +} + +// GetSecurityVulnerability returns the SecurityVulnerability field. +func (d *DependabotAlert) GetSecurityVulnerability() *AdvisoryVulnerability { + if d == nil { + return nil + } + return d.SecurityVulnerability +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DependabotAlert) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DependabotAlertEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetAlert returns the Alert field. +func (d *DependabotAlertEvent) GetAlert() *DependabotAlert { + if d == nil { + return nil + } + return d.Alert +} + +// GetEnterprise returns the Enterprise field. +func (d *DependabotAlertEvent) GetEnterprise() *Enterprise { + if d == nil { + return nil + } + return d.Enterprise +} + +// GetInstallation returns the Installation field. +func (d *DependabotAlertEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DependabotAlertEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DependabotAlertEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DependabotAlertEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetDismissedComment returns the DismissedComment field if it's non-nil, zero value otherwise. +func (d *DependabotAlertState) GetDismissedComment() string { + if d == nil || d.DismissedComment == nil { + return "" + } + return *d.DismissedComment +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (d *DependabotAlertState) GetDismissedReason() string { + if d == nil || d.DismissedReason == nil { + return "" + } + return *d.DismissedReason +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetCVEID() string { + if d == nil || d.CVEID == nil { + return "" + } + return *d.CVEID +} + +// GetCVSS returns the CVSS field. +func (d *DependabotSecurityAdvisory) GetCVSS() *AdvisoryCVSS { + if d == nil { + return nil + } + return d.CVSS +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetGHSAID() string { + if d == nil || d.GHSAID == nil { + return "" + } + return *d.GHSAID +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetPublishedAt() Timestamp { + if d == nil || d.PublishedAt == nil { + return Timestamp{} + } + return *d.PublishedAt +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetSeverity() string { + if d == nil || d.Severity == nil { + return "" + } + return *d.Severity +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetSummary() string { + if d == nil || d.Summary == nil { + return "" + } + return *d.Summary +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetWithdrawnAt returns the WithdrawnAt field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityAdvisory) GetWithdrawnAt() Timestamp { + if d == nil || d.WithdrawnAt == nil { + return Timestamp{} + } + return *d.WithdrawnAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (d *DependabotSecurityUpdates) GetStatus() string { + if d == nil || d.Status == nil { + return "" + } + return *d.Status +} + +// GetManifestPath returns the ManifestPath field if it's non-nil, zero value otherwise. +func (d *Dependency) GetManifestPath() string { + if d == nil || d.ManifestPath == nil { + return "" + } + return *d.ManifestPath +} + +// GetPackage returns the Package field. +func (d *Dependency) GetPackage() *VulnerabilityPackage { + if d == nil { + return nil + } + return d.Package +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (d *Dependency) GetScope() string { + if d == nil || d.Scope == nil { + return "" + } + return *d.Scope +} + +// GetLabeledRunners returns the LabeledRunners field if it's non-nil, zero value otherwise. +func (d *DependencyGraphAutosubmitActionOptions) GetLabeledRunners() bool { + if d == nil || d.LabeledRunners == nil { + return false + } + return *d.LabeledRunners +} + +// GetDetector returns the Detector field. +func (d *DependencyGraphSnapshot) GetDetector() *DependencyGraphSnapshotDetector { + if d == nil { + return nil + } + return d.Detector +} + +// GetJob returns the Job field. +func (d *DependencyGraphSnapshot) GetJob() *DependencyGraphSnapshotJob { + if d == nil { + return nil + } + return d.Job +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetScanned returns the Scanned field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetScanned() Timestamp { + if d == nil || d.Scanned == nil { + return Timestamp{} + } + return *d.Scanned +} + +// GetSha returns the Sha field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetSha() string { + if d == nil || d.Sha == nil { + return "" + } + return *d.Sha +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetMessage() string { + if d == nil || d.Message == nil { + return "" + } + return *d.Message +} + +// GetResult returns the Result field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetResult() string { + if d == nil || d.Result == nil { + return "" + } + return *d.Result +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetVersion() string { + if d == nil || d.Version == nil { + return "" + } + return *d.Version +} + +// GetCorrelator returns the Correlator field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetCorrelator() string { + if d == nil || d.Correlator == nil { + return "" + } + return *d.Correlator +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetID() string { + if d == nil || d.ID == nil { + return "" + } + return *d.ID +} + +// GetFile returns the File field. +func (d *DependencyGraphSnapshotManifest) GetFile() *DependencyGraphSnapshotManifestFile { + if d == nil { + return nil + } + return d.File +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifest) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetSourceLocation returns the SourceLocation field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifestFile) GetSourceLocation() string { + if d == nil || d.SourceLocation == nil { + return "" + } + return *d.SourceLocation +} + +// GetPackageURL returns the PackageURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetPackageURL() string { + if d == nil || d.PackageURL == nil { + return "" + } + return *d.PackageURL +} + +// GetRelationship returns the Relationship field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetRelationship() string { + if d == nil || d.Relationship == nil { + return "" + } + return *d.Relationship +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetScope() string { + if d == nil || d.Scope == nil { + return "" + } + return *d.Scope +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeployKeyEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetInstallation returns the Installation field. +func (d *DeployKeyEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetKey returns the Key field. +func (d *DeployKeyEvent) GetKey() *Key { + if d == nil { + return nil + } + return d.Key +} + +// GetOrganization returns the Organization field. +func (d *DeployKeyEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeployKeyEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeployKeyEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *Deployment) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *Deployment) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *Deployment) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (d *Deployment) GetSHA() string { + if d == nil || d.SHA == nil { + return "" + } + return *d.SHA +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetStatusesURL() string { + if d == nil || d.StatusesURL == nil { + return "" + } + return *d.StatusesURL +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *Deployment) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicy) GetType() string { + if d == nil || d.Type == nil { + return "" + } + return *d.Type +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyRequest) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyRequest) GetType() string { + if d == nil || d.Type == nil { + return "" + } + return *d.Type +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (d *DeploymentBranchPolicyResponse) GetTotalCount() int { + if d == nil || d.TotalCount == nil { + return 0 + } + return *d.TotalCount +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeploymentEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DeploymentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetWorkflow returns the Workflow field. +func (d *DeploymentEvent) GetWorkflow() *Workflow { + if d == nil { + return nil + } + return d.Workflow +} + +// GetWorkflowRun returns the WorkflowRun field. +func (d *DeploymentEvent) GetWorkflowRun() *WorkflowRun { + if d == nil { + return nil + } + return d.WorkflowRun +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentProtectionRuleEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentCallbackURL returns the DeploymentCallbackURL field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetDeploymentCallbackURL() string { + if d == nil || d.DeploymentCallbackURL == nil { + return "" + } + return *d.DeploymentCallbackURL +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (d *DeploymentProtectionRuleEvent) GetEvent() string { + if d == nil || d.Event == nil { + return "" + } + return *d.Event +} + +// GetInstallation returns the Installation field. +func (d *DeploymentProtectionRuleEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DeploymentProtectionRuleEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeploymentProtectionRuleEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentProtectionRuleEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetAutoMerge() bool { + if d == nil || d.AutoMerge == nil { + return false + } + return *d.AutoMerge +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetProductionEnvironment() bool { + if d == nil || d.ProductionEnvironment == nil { + return false + } + return *d.ProductionEnvironment +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRequiredContexts() []string { + if d == nil || d.RequiredContexts == nil { + return nil + } + return *d.RequiredContexts +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTransientEnvironment() bool { + if d == nil || d.TransientEnvironment == nil { + return false + } + return *d.TransientEnvironment +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetApprover returns the Approver field. +func (d *DeploymentReviewEvent) GetApprover() *User { + if d == nil { + return nil + } + return d.Approver +} + +// GetComment returns the Comment field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetComment() string { + if d == nil || d.Comment == nil { + return "" + } + return *d.Comment +} + +// GetEnterprise returns the Enterprise field. +func (d *DeploymentReviewEvent) GetEnterprise() *Enterprise { + if d == nil { + return nil + } + return d.Enterprise +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentReviewEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrganization returns the Organization field. +func (d *DeploymentReviewEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeploymentReviewEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetRequester returns the Requester field. +func (d *DeploymentReviewEvent) GetRequester() *User { + if d == nil { + return nil + } + return d.Requester +} + +// GetSender returns the Sender field. +func (d *DeploymentReviewEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (d *DeploymentReviewEvent) GetSince() string { + if d == nil || d.Since == nil { + return "" + } + return *d.Since +} + +// GetWorkflowJobRun returns the WorkflowJobRun field. +func (d *DeploymentReviewEvent) GetWorkflowJobRun() *WorkflowJobRun { + if d == nil { + return nil + } + return d.WorkflowJobRun +} + +// GetWorkflowRun returns the WorkflowRun field. +func (d *DeploymentReviewEvent) GetWorkflowRun() *WorkflowRun { + if d == nil { + return nil + } + return d.WorkflowRun +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *DeploymentStatus) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDeploymentURL() string { + if d == nil || d.DeploymentURL == nil { + return "" + } + return *d.DeploymentURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetTargetURL() string { + if d == nil || d.TargetURL == nil { + return "" + } + return *d.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentStatusEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentStatus returns the DeploymentStatus field. +func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { + if d == nil { + return nil + } + return d.DeploymentStatus +} + +// GetInstallation returns the Installation field. +func (d *DeploymentStatusEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DeploymentStatusEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DeploymentStatusEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentStatusEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetAutoInactive() bool { + if d == nil || d.AutoInactive == nil { + return false + } + return *d.AutoInactive +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (d *Discussion) GetActiveLockReason() string { + if d == nil || d.ActiveLockReason == nil { + return "" + } + return *d.ActiveLockReason +} + +// GetAnswerChosenAt returns the AnswerChosenAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenAt() Timestamp { + if d == nil || d.AnswerChosenAt == nil { + return Timestamp{} + } + return *d.AnswerChosenAt +} + +// GetAnswerChosenBy returns the AnswerChosenBy field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenBy() string { + if d == nil || d.AnswerChosenBy == nil { + return "" + } + return *d.AnswerChosenBy +} + +// GetAnswerHTMLURL returns the AnswerHTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerHTMLURL() string { + if d == nil || d.AnswerHTMLURL == nil { + return "" + } + return *d.AnswerHTMLURL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAuthorAssociation() string { + if d == nil || d.AuthorAssociation == nil { + return "" + } + return *d.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *Discussion) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (d *Discussion) GetComments() int { + if d == nil || d.Comments == nil { + return 0 + } + return *d.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionCategory returns the DiscussionCategory field. +func (d *Discussion) GetDiscussionCategory() *DiscussionCategory { + if d == nil { + return nil + } + return d.DiscussionCategory +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (d *Discussion) GetLocked() bool { + if d == nil || d.Locked == nil { + return false + } + return *d.Locked +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *Discussion) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (d *Discussion) GetTitle() string { + if d == nil || d.Title == nil { + return "" + } + return *d.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetUser returns the User field. +func (d *Discussion) GetUser() *User { + if d == nil { + return nil + } + return d.User +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEmoji returns the Emoji field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetEmoji() string { + if d == nil || d.Emoji == nil { + return "" + } + return *d.Emoji +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetIsAnswerable returns the IsAnswerable field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetIsAnswerable() bool { + if d == nil || d.IsAnswerable == nil { + return false + } + return *d.IsAnswerable +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetRepositoryID() int64 { + if d == nil || d.RepositoryID == nil { + return 0 + } + return *d.RepositoryID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetSlug() string { + if d == nil || d.Slug == nil { + return "" + } + return *d.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetAuthor returns the Author field. +func (d *DiscussionComment) GetAuthor() *User { + if d == nil { + return nil + } + return d.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyHTML() string { + if d == nil || d.BodyHTML == nil { + return "" + } + return *d.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyVersion() string { + if d == nil || d.BodyVersion == nil { + return "" + } + return *d.BodyVersion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetDiscussionURL() string { + if d == nil || d.DiscussionURL == nil { + return "" + } + return *d.DiscussionURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetLastEditedAt() Timestamp { + if d == nil || d.LastEditedAt == nil { + return Timestamp{} + } + return *d.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetReactions returns the Reactions field. +func (d *DiscussionComment) GetReactions() *Reactions { + if d == nil { + return nil + } + return d.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DiscussionCommentEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetComment returns the Comment field. +func (d *DiscussionCommentEvent) GetComment() *CommentDiscussion { + if d == nil { + return nil + } + return d.Comment +} + +// GetDiscussion returns the Discussion field. +func (d *DiscussionCommentEvent) GetDiscussion() *Discussion { + if d == nil { + return nil + } + return d.Discussion +} + +// GetInstallation returns the Installation field. +func (d *DiscussionCommentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DiscussionCommentEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DiscussionCommentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DiscussionCommentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DiscussionEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDiscussion returns the Discussion field. +func (d *DiscussionEvent) GetDiscussion() *Discussion { + if d == nil { + return nil + } + return d.Discussion +} + +// GetInstallation returns the Installation field. +func (d *DiscussionEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DiscussionEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DiscussionEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DiscussionEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetApps returns the Apps field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetApps() []string { + if d == nil || d.Apps == nil { + return nil + } + return *d.Apps +} + +// GetTeams returns the Teams field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetTeams() []string { + if d == nil || d.Teams == nil { + return nil + } + return *d.Teams +} + +// GetUsers returns the Users field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetUsers() []string { + if d == nil || d.Users == nil { + return nil + } + return *d.Users +} + +// GetDismissalCommitID returns the DismissalCommitID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalCommitID() string { + if d == nil || d.DismissalCommitID == nil { + return "" + } + return *d.DismissalCommitID +} + +// GetDismissalMessage returns the DismissalMessage field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalMessage() string { + if d == nil || d.DismissalMessage == nil { + return "" + } + return *d.DismissalMessage +} + +// GetReviewID returns the ReviewID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetReviewID() int64 { + if d == nil || d.ReviewID == nil { + return 0 + } + return *d.ReviewID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (d *DismissStaleReviewsOnPushChanges) GetFrom() bool { + if d == nil || d.From == nil { + return false + } + return *d.From +} + +// GetClientPayload returns the ClientPayload field if it's non-nil, zero value otherwise. +func (d *DispatchRequestOptions) GetClientPayload() json.RawMessage { + if d == nil || d.ClientPayload == nil { + return json.RawMessage{} + } + return *d.ClientPayload +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetLine() int { + if d == nil || d.Line == nil { + return 0 + } + return *d.Line +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPath() string { + if d == nil || d.Path == nil { + return "" + } + return *d.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPosition() int { + if d == nil || d.Position == nil { + return 0 + } + return *d.Position +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetSide() string { + if d == nil || d.Side == nil { + return "" + } + return *d.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartLine() int { + if d == nil || d.StartLine == nil { + return 0 + } + return *d.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartSide() string { + if d == nil || d.StartSide == nil { + return "" + } + return *d.StartSide +} + +// GetRef returns the Ref field. +func (e *EditBase) GetRef() *EditRef { + if e == nil { + return nil + } + return e.Ref +} + +// GetSHA returns the SHA field. +func (e *EditBase) GetSHA() *EditSHA { + if e == nil { + return nil + } + return e.SHA +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditBody) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetBase returns the Base field. +func (e *EditChange) GetBase() *EditBase { + if e == nil { + return nil + } + return e.Base +} + +// GetBody returns the Body field. +func (e *EditChange) GetBody() *EditBody { + if e == nil { + return nil + } + return e.Body +} + +// GetDefaultBranch returns the DefaultBranch field. +func (e *EditChange) GetDefaultBranch() *EditDefaultBranch { + if e == nil { + return nil + } + return e.DefaultBranch +} + +// GetOwner returns the Owner field. +func (e *EditChange) GetOwner() *EditOwner { + if e == nil { + return nil + } + return e.Owner +} + +// GetRepo returns the Repo field. +func (e *EditChange) GetRepo() *EditRepo { + if e == nil { + return nil + } + return e.Repo +} + +// GetTitle returns the Title field. +func (e *EditChange) GetTitle() *EditTitle { + if e == nil { + return nil + } + return e.Title +} + +// GetTopics returns the Topics field. +func (e *EditChange) GetTopics() *EditTopics { + if e == nil { + return nil + } + return e.Topics +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditDefaultBranch) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetOwnerInfo returns the OwnerInfo field. +func (e *EditOwner) GetOwnerInfo() *OwnerInfo { + if e == nil { + return nil + } + return e.OwnerInfo +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditRef) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetName returns the Name field. +func (e *EditRepo) GetName() *RepoName { + if e == nil { + return nil + } + return e.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditSHA) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditTitle) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetAvatarURL() string { + if e == nil || e.AvatarURL == nil { + return "" + } + return *e.AvatarURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetDescription() string { + if e == nil || e.Description == nil { + return "" + } + return *e.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetID() int { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetSlug() string { + if e == nil || e.Slug == nil { + return "" + } + return *e.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetWebsiteURL returns the WebsiteURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetWebsiteURL() string { + if e == nil || e.WebsiteURL == nil { + return "" + } + return *e.WebsiteURL +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetAllowsPublicRepositories() bool { + if e == nil || e.AllowsPublicRepositories == nil { + return false + } + return *e.AllowsPublicRepositories +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetDefault() bool { + if e == nil || e.Default == nil { + return false + } + return *e.Default +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetInherited returns the Inherited field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetInherited() bool { + if e == nil || e.Inherited == nil { + return false + } + return *e.Inherited +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetRestrictedToWorkflows() bool { + if e == nil || e.RestrictedToWorkflows == nil { + return false + } + return *e.RestrictedToWorkflows +} + +// GetRunnersURL returns the RunnersURL field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetRunnersURL() string { + if e == nil || e.RunnersURL == nil { + return "" + } + return *e.RunnersURL +} + +// GetSelectedOrganizationsURL returns the SelectedOrganizationsURL field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetSelectedOrganizationsURL() string { + if e == nil || e.SelectedOrganizationsURL == nil { + return "" + } + return *e.SelectedOrganizationsURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetVisibility() string { + if e == nil || e.Visibility == nil { + return "" + } + return *e.Visibility +} + +// GetWorkflowRestrictionsReadOnly returns the WorkflowRestrictionsReadOnly field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroup) GetWorkflowRestrictionsReadOnly() bool { + if e == nil || e.WorkflowRestrictionsReadOnly == nil { + return false + } + return *e.WorkflowRestrictionsReadOnly +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (e *EnterpriseRunnerGroups) GetTotalCount() int { + if e == nil || e.TotalCount == nil { + return 0 + } + return *e.TotalCount +} + +// GetAdvancedSecurityEnabledForNewRepositories returns the AdvancedSecurityEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetAdvancedSecurityEnabledForNewRepositories() bool { + if e == nil || e.AdvancedSecurityEnabledForNewRepositories == nil { + return false + } + return *e.AdvancedSecurityEnabledForNewRepositories +} + +// GetSecretScanningEnabledForNewRepositories returns the SecretScanningEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningEnabledForNewRepositories() bool { + if e == nil || e.SecretScanningEnabledForNewRepositories == nil { + return false + } + return *e.SecretScanningEnabledForNewRepositories +} + +// GetSecretScanningPushProtectionCustomLink returns the SecretScanningPushProtectionCustomLink field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningPushProtectionCustomLink() string { + if e == nil || e.SecretScanningPushProtectionCustomLink == nil { + return "" + } + return *e.SecretScanningPushProtectionCustomLink +} + +// GetSecretScanningPushProtectionEnabledForNewRepositories returns the SecretScanningPushProtectionEnabledForNewRepositories field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningPushProtectionEnabledForNewRepositories() bool { + if e == nil || e.SecretScanningPushProtectionEnabledForNewRepositories == nil { + return false + } + return *e.SecretScanningPushProtectionEnabledForNewRepositories +} + +// GetSecretScanningValidityChecksEnabled returns the SecretScanningValidityChecksEnabled field if it's non-nil, zero value otherwise. +func (e *EnterpriseSecurityAnalysisSettings) GetSecretScanningValidityChecksEnabled() bool { + if e == nil || e.SecretScanningValidityChecksEnabled == nil { + return false + } + return *e.SecretScanningValidityChecksEnabled +} + +// GetCanAdminsBypass returns the CanAdminsBypass field if it's non-nil, zero value otherwise. +func (e *Environment) GetCanAdminsBypass() bool { + if e == nil || e.CanAdminsBypass == nil { + return false + } + return *e.CanAdminsBypass +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (e *Environment) GetDeploymentBranchPolicy() *BranchPolicy { + if e == nil { + return nil + } + return e.DeploymentBranchPolicy +} + +// GetEnvironmentName returns the EnvironmentName field if it's non-nil, zero value otherwise. +func (e *Environment) GetEnvironmentName() string { + if e == nil || e.EnvironmentName == nil { + return "" + } + return *e.EnvironmentName +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Environment) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Environment) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Environment) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Environment) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (e *Environment) GetOwner() string { + if e == nil || e.Owner == nil { + return "" + } + return *e.Owner +} + +// GetRepo returns the Repo field if it's non-nil, zero value otherwise. +func (e *Environment) GetRepo() string { + if e == nil || e.Repo == nil { + return "" + } + return *e.Repo +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (e *Environment) GetURL() string { + if e == nil || e.URL == nil { + return "" + } + return *e.URL +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (e *Environment) GetWaitTimer() int { + if e == nil || e.WaitTimer == nil { + return 0 + } + return *e.WaitTimer +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (e *EnvResponse) GetTotalCount() int { + if e == nil || e.TotalCount == nil { + return 0 + } + return *e.TotalCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *ErrorBlock) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetBlock returns the Block field. +func (e *ErrorResponse) GetBlock() *ErrorBlock { + if e == nil { + return nil + } + return e.Block +} + +// GetActor returns the Actor field. +func (e *Event) GetActor() *User { + if e == nil { + return nil + } + return e.Actor +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Event) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Event) GetID() string { + if e == nil || e.ID == nil { + return "" + } + return *e.ID +} + +// GetOrg returns the Org field. +func (e *Event) GetOrg() *Organization { + if e == nil { + return nil + } + return e.Org +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (e *Event) GetPublic() bool { + if e == nil || e.Public == nil { + return false + } + return *e.Public +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (e *Event) GetRawPayload() json.RawMessage { + if e == nil || e.RawPayload == nil { + return json.RawMessage{} + } + return *e.RawPayload +} + +// GetRepo returns the Repo field. +func (e *Event) GetRepo() *Repository { + if e == nil { + return nil + } + return e.Repo +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *Event) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupID() int64 { + if e == nil || e.GroupID == nil { + return 0 + } + return *e.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupName() string { + if e == nil || e.GroupName == nil { + return "" + } + return *e.GroupName +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetMemberEmail returns the MemberEmail field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberEmail() string { + if e == nil || e.MemberEmail == nil { + return "" + } + return *e.MemberEmail +} + +// GetMemberID returns the MemberID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberID() int64 { + if e == nil || e.MemberID == nil { + return 0 + } + return *e.MemberID +} + +// GetMemberLogin returns the MemberLogin field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberLogin() string { + if e == nil || e.MemberLogin == nil { + return "" + } + return *e.MemberLogin +} + +// GetMemberName returns the MemberName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberName() string { + if e == nil || e.MemberName == nil { + return "" + } + return *e.MemberName +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamID() int64 { + if e == nil || e.TeamID == nil { + return 0 + } + return *e.TeamID +} + +// GetTeamName returns the TeamName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamName() string { + if e == nil || e.TeamName == nil { + return "" + } + return *e.TeamName +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetHRef() string { + if f == nil || f.HRef == nil { + return "" + } + return *f.HRef +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetType() string { + if f == nil || f.Type == nil { + return "" + } + return *f.Type +} + +// GetCurrentUser returns the CurrentUser field. +func (f *FeedLinks) GetCurrentUser() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUser +} + +// GetCurrentUserActor returns the CurrentUserActor field. +func (f *FeedLinks) GetCurrentUserActor() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserActor +} + +// GetCurrentUserOrganization returns the CurrentUserOrganization field. +func (f *FeedLinks) GetCurrentUserOrganization() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserOrganization +} + +// GetCurrentUserPublic returns the CurrentUserPublic field. +func (f *FeedLinks) GetCurrentUserPublic() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserPublic +} + +// GetTimeline returns the Timeline field. +func (f *FeedLinks) GetTimeline() *FeedLink { + if f == nil { + return nil + } + return f.Timeline +} + +// GetUser returns the User field. +func (f *FeedLinks) GetUser() *FeedLink { + if f == nil { + return nil + } + return f.User +} + +// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserActorURL() string { + if f == nil || f.CurrentUserActorURL == nil { + return "" + } + return *f.CurrentUserActorURL +} + +// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserOrganizationURL() string { + if f == nil || f.CurrentUserOrganizationURL == nil { + return "" + } + return *f.CurrentUserOrganizationURL +} + +// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserPublicURL() string { + if f == nil || f.CurrentUserPublicURL == nil { + return "" + } + return *f.CurrentUserPublicURL +} + +// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserURL() string { + if f == nil || f.CurrentUserURL == nil { + return "" + } + return *f.CurrentUserURL +} + +// GetLinks returns the Links field. +func (f *Feeds) GetLinks() *FeedLinks { + if f == nil { + return nil + } + return f.Links +} + +// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetTimelineURL() string { + if f == nil || f.TimelineURL == nil { + return "" + } + return *f.TimelineURL +} + +// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetUserURL() string { + if f == nil || f.UserURL == nil { + return "" + } + return *f.UserURL +} + +// GetIdentifier returns the Identifier field if it's non-nil, zero value otherwise. +func (f *FirstPatchedVersion) GetIdentifier() string { + if f == nil || f.Identifier == nil { + return "" + } + return *f.Identifier +} + +// GetForkee returns the Forkee field. +func (f *ForkEvent) GetForkee() *Repository { + if f == nil { + return nil + } + return f.Forkee +} + +// GetInstallation returns the Installation field. +func (f *ForkEvent) GetInstallation() *Installation { + if f == nil { + return nil + } + return f.Installation +} + +// GetRepo returns the Repo field. +func (f *ForkEvent) GetRepo() *Repository { + if f == nil { + return nil + } + return f.Repo +} + +// GetSender returns the Sender field. +func (f *ForkEvent) GetSender() *User { + if f == nil { + return nil + } + return f.Sender +} + +// GetWorkFolder returns the WorkFolder field if it's non-nil, zero value otherwise. +func (g *GenerateJITConfigRequest) GetWorkFolder() string { + if g == nil || g.WorkFolder == nil { + return "" + } + return *g.WorkFolder +} + +// GetPreviousTagName returns the PreviousTagName field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetPreviousTagName() string { + if g == nil || g.PreviousTagName == nil { + return "" + } + return *g.PreviousTagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetTargetCommitish() string { + if g == nil || g.TargetCommitish == nil { + return "" + } + return *g.TargetCommitish +} + +// GetInclude returns the Include field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetInclude() string { + if g == nil || g.Include == nil { + return "" + } + return *g.Include +} + +// GetOrder returns the Order field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetOrder() string { + if g == nil || g.Order == nil { + return "" + } + return *g.Order +} + +// GetPhrase returns the Phrase field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetPhrase() string { + if g == nil || g.Phrase == nil { + return "" + } + return *g.Phrase +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (g *Gist) GetComments() int { + if g == nil || g.Comments == nil { + return 0 + } + return *g.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (g *Gist) GetDescription() string { + if g == nil || g.Description == nil { + return "" + } + return *g.Description +} + +// GetFiles returns the Files map if it's non-nil, an empty map otherwise. +func (g *Gist) GetFiles() map[GistFilename]GistFile { + if g == nil || g.Files == nil { + return map[GistFilename]GistFile{} + } + return g.Files +} + +// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPullURL() string { + if g == nil || g.GitPullURL == nil { + return "" + } + return *g.GitPullURL +} + +// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPushURL() string { + if g == nil || g.GitPushURL == nil { + return "" + } + return *g.GitPushURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetHTMLURL() string { + if g == nil || g.HTMLURL == nil { + return "" + } + return *g.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Gist) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *Gist) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetOwner returns the Owner field. +func (g *Gist) GetOwner() *User { + if g == nil { + return nil + } + return g.Owner +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (g *Gist) GetPublic() bool { + if g == nil || g.Public == nil { + return false + } + return *g.Public +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (g *GistComment) GetBody() string { + if g == nil || g.Body == nil { + return "" + } + return *g.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistComment) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistComment) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistComment) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistComment) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetChangeStatus returns the ChangeStatus field. +func (g *GistCommit) GetChangeStatus() *CommitStats { + if g == nil { + return nil + } + return g.ChangeStatus +} + +// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetCommittedAt() Timestamp { + if g == nil || g.CommittedAt == nil { + return Timestamp{} + } + return *g.CommittedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistCommit) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetVersion() string { + if g == nil || g.Version == nil { + return "" + } + return *g.Version +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (g *GistFile) GetContent() string { + if g == nil || g.Content == nil { + return "" + } + return *g.Content +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (g *GistFile) GetFilename() string { + if g == nil || g.Filename == nil { + return "" + } + return *g.Filename +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (g *GistFile) GetLanguage() string { + if g == nil || g.Language == nil { + return "" + } + return *g.Language +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (g *GistFile) GetRawURL() string { + if g == nil || g.RawURL == nil { + return "" + } + return *g.RawURL +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (g *GistFile) GetSize() int { + if g == nil || g.Size == nil { + return 0 + } + return *g.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GistFile) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistFork) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistFork) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPrivateGists() int { + if g == nil || g.PrivateGists == nil { + return 0 + } + return *g.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPublicGists() int { + if g == nil || g.PublicGists == nil { + return 0 + } + return *g.PublicGists +} + +// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetTotalGists() int { + if g == nil || g.TotalGists == nil { + return 0 + } + return *g.TotalGists +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (g *GitHubAppAuthorizationEvent) GetAction() string { + if g == nil || g.Action == nil { + return "" + } + return *g.Action +} + +// GetInstallation returns the Installation field. +func (g *GitHubAppAuthorizationEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetSender returns the Sender field. +func (g *GitHubAppAuthorizationEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetName() string { + if g == nil || g.Name == nil { + return "" + } + return *g.Name +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetSource() string { + if g == nil || g.Source == nil { + return "" + } + return *g.Source +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (g *GitObject) GetSHA() string { + if g == nil || g.SHA == nil { + return "" + } + return *g.SHA +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GitObject) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GitObject) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetGithubReviewedAt returns the GithubReviewedAt field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetGithubReviewedAt() Timestamp { + if g == nil || g.GithubReviewedAt == nil { + return Timestamp{} + } + return *g.GithubReviewedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetNVDPublishedAt returns the NVDPublishedAt field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetNVDPublishedAt() Timestamp { + if g == nil || g.NVDPublishedAt == nil { + return Timestamp{} + } + return *g.NVDPublishedAt +} + +// GetRepositoryAdvisoryURL returns the RepositoryAdvisoryURL field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetRepositoryAdvisoryURL() string { + if g == nil || g.RepositoryAdvisoryURL == nil { + return "" + } + return *g.RepositoryAdvisoryURL +} + +// GetSourceCodeLocation returns the SourceCodeLocation field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetSourceCodeLocation() string { + if g == nil || g.SourceCodeLocation == nil { + return "" + } + return *g.SourceCodeLocation +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityAdvisory) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetFirstPatchedVersion returns the FirstPatchedVersion field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityVulnerability) GetFirstPatchedVersion() string { + if g == nil || g.FirstPatchedVersion == nil { + return "" + } + return *g.FirstPatchedVersion +} + +// GetPackage returns the Package field. +func (g *GlobalSecurityVulnerability) GetPackage() *VulnerabilityPackage { + if g == nil { + return nil + } + return g.Package +} + +// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise. +func (g *GlobalSecurityVulnerability) GetVulnerableVersionRange() string { + if g == nil || g.VulnerableVersionRange == nil { + return "" + } + return *g.VulnerableVersionRange +} + +// GetInstallation returns the Installation field. +func (g *GollumEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetOrg returns the Org field. +func (g *GollumEvent) GetOrg() *Organization { + if g == nil { + return nil + } + return g.Org +} + +// GetRepo returns the Repo field. +func (g *GollumEvent) GetRepo() *Repository { + if g == nil { + return nil + } + return g.Repo +} + +// GetSender returns the Sender field. +func (g *GollumEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetEmail() string { + if g == nil || g.Email == nil { + return "" + } + return *g.Email +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetVerified() bool { + if g == nil || g.Verified == nil { + return false + } + return *g.Verified +} + +// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanCertify() bool { + if g == nil || g.CanCertify == nil { + return false + } + return *g.CanCertify +} + +// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptComms() bool { + if g == nil || g.CanEncryptComms == nil { + return false + } + return *g.CanEncryptComms +} + +// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptStorage() bool { + if g == nil || g.CanEncryptStorage == nil { + return false + } + return *g.CanEncryptStorage +} + +// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanSign() bool { + if g == nil || g.CanSign == nil { + return false + } + return *g.CanSign +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetExpiresAt() Timestamp { + if g == nil || g.ExpiresAt == nil { + return Timestamp{} + } + return *g.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetKeyID() string { + if g == nil || g.KeyID == nil { + return "" + } + return *g.KeyID +} + +// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPrimaryKeyID() int64 { + if g == nil || g.PrimaryKeyID == nil { + return 0 + } + return *g.PrimaryKeyID +} + +// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPublicKey() string { + if g == nil || g.PublicKey == nil { + return "" + } + return *g.PublicKey +} + +// GetRawKey returns the RawKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetRawKey() string { + if g == nil || g.RawKey == nil { + return "" + } + return *g.RawKey +} + +// GetApp returns the App field. +func (g *Grant) GetApp() *AuthorizationApp { + if g == nil { + return nil + } + return g.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Grant) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *Grant) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetAuthor returns the Author field. +func (h *HeadCommit) GetAuthor() *CommitAuthor { + if h == nil { + return nil + } + return h.Author +} + +// GetCommitter returns the Committer field. +func (h *HeadCommit) GetCommitter() *CommitAuthor { + if h == nil { + return nil + } + return h.Committer +} + +// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetDistinct() bool { + if h == nil || h.Distinct == nil { + return false + } + return *h.Distinct +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetID() string { + if h == nil || h.ID == nil { + return "" + } + return *h.ID +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetMessage() string { + if h == nil || h.Message == nil { + return "" + } + return *h.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetSHA() string { + if h == nil || h.SHA == nil { + return "" + } + return *h.SHA +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTimestamp() Timestamp { + if h == nil || h.Timestamp == nil { + return Timestamp{} + } + return *h.Timestamp +} + +// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTreeID() string { + if h == nil || h.TreeID == nil { + return "" + } + return *h.TreeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (h *Hook) GetActive() bool { + if h == nil || h.Active == nil { + return false + } + return *h.Active +} + +// GetConfig returns the Config field. +func (h *Hook) GetConfig() *HookConfig { + if h == nil { + return nil + } + return h.Config +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetCreatedAt() Timestamp { + if h == nil || h.CreatedAt == nil { + return Timestamp{} + } + return *h.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *Hook) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *Hook) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetPingURL returns the PingURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetPingURL() string { + if h == nil || h.PingURL == nil { + return "" + } + return *h.PingURL +} + +// GetTestURL returns the TestURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetTestURL() string { + if h == nil || h.TestURL == nil { + return "" + } + return *h.TestURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (h *Hook) GetType() string { + if h == nil || h.Type == nil { + return "" + } + return *h.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetUpdatedAt() Timestamp { + if h == nil || h.UpdatedAt == nil { + return Timestamp{} + } + return *h.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *Hook) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetContentType() string { + if h == nil || h.ContentType == nil { + return "" + } + return *h.ContentType +} + +// GetInsecureSSL returns the InsecureSSL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetInsecureSSL() string { + if h == nil || h.InsecureSSL == nil { + return "" + } + return *h.InsecureSSL +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetSecret() string { + if h == nil || h.Secret == nil { + return "" + } + return *h.Secret +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetAction() string { + if h == nil || h.Action == nil { + return "" + } + return *h.Action +} + +// GetDeliveredAt returns the DeliveredAt field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetDeliveredAt() Timestamp { + if h == nil || h.DeliveredAt == nil { + return Timestamp{} + } + return *h.DeliveredAt +} + +// GetDuration returns the Duration field. +func (h *HookDelivery) GetDuration() *float64 { + if h == nil { + return nil + } + return h.Duration +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetEvent() string { + if h == nil || h.Event == nil { + return "" + } + return *h.Event +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetGUID() string { + if h == nil || h.GUID == nil { + return "" + } + return *h.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetInstallationID returns the InstallationID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetInstallationID() int64 { + if h == nil || h.InstallationID == nil { + return 0 + } + return *h.InstallationID +} + +// GetRedelivery returns the Redelivery field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRedelivery() bool { + if h == nil || h.Redelivery == nil { + return false + } + return *h.Redelivery +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRepositoryID() int64 { + if h == nil || h.RepositoryID == nil { + return 0 + } + return *h.RepositoryID +} + +// GetRequest returns the Request field. +func (h *HookDelivery) GetRequest() *HookRequest { + if h == nil { + return nil + } + return h.Request +} + +// GetResponse returns the Response field. +func (h *HookDelivery) GetResponse() *HookResponse { + if h == nil { + return nil + } + return h.Response +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatus() string { + if h == nil || h.Status == nil { + return "" + } + return *h.Status +} + +// GetStatusCode returns the StatusCode field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatusCode() int { + if h == nil || h.StatusCode == nil { + return 0 + } + return *h.StatusCode +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookRequest) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookRequest) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookResponse) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookResponse) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetActiveHooks() int { + if h == nil || h.ActiveHooks == nil { + return 0 + } + return *h.ActiveHooks +} + +// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetInactiveHooks() int { + if h == nil || h.InactiveHooks == nil { + return 0 + } + return *h.InactiveHooks +} + +// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetTotalHooks() int { + if h == nil || h.TotalHooks == nil { + return 0 + } + return *h.TotalHooks +} + +// GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupDescription() string { + if i == nil || i.GroupDescription == nil { + return "" + } + return *i.GroupDescription +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupID() string { + if i == nil || i.GroupID == nil { + return "" + } + return *i.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupName() string { + if i == nil || i.GroupName == nil { + return "" + } + return *i.GroupName +} + +// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsCount() int { + if i == nil || i.AuthorsCount == nil { + return 0 + } + return *i.AuthorsCount +} + +// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsURL() string { + if i == nil || i.AuthorsURL == nil { + return "" + } + return *i.AuthorsURL +} + +// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. +func (i *Import) GetCommitCount() int { + if i == nil || i.CommitCount == nil { + return 0 + } + return *i.CommitCount +} + +// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. +func (i *Import) GetFailedStep() string { + if i == nil || i.FailedStep == nil { + return "" + } + return *i.FailedStep +} + +// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. +func (i *Import) GetHasLargeFiles() bool { + if i == nil || i.HasLargeFiles == nil { + return false + } + return *i.HasLargeFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Import) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. +func (i *Import) GetHumanName() string { + if i == nil || i.HumanName == nil { + return "" + } + return *i.HumanName +} + +// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesCount() int { + if i == nil || i.LargeFilesCount == nil { + return 0 + } + return *i.LargeFilesCount +} + +// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesSize() int { + if i == nil || i.LargeFilesSize == nil { + return 0 + } + return *i.LargeFilesSize +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *Import) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetPercent returns the Percent field if it's non-nil, zero value otherwise. +func (i *Import) GetPercent() int { + if i == nil || i.Percent == nil { + return 0 + } + return *i.Percent +} + +// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. +func (i *Import) GetPushPercent() int { + if i == nil || i.PushPercent == nil { + return 0 + } + return *i.PushPercent +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Import) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *Import) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. +func (i *Import) GetStatusText() string { + if i == nil || i.StatusText == nil { + return "" + } + return *i.StatusText +} + +// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. +func (i *Import) GetTFVCProject() string { + if i == nil || i.TFVCProject == nil { + return "" + } + return *i.TFVCProject +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Import) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. +func (i *Import) GetUseLFS() string { + if i == nil || i.UseLFS == nil { + return "" + } + return *i.UseLFS +} + +// GetVCS returns the VCS field if it's non-nil, zero value otherwise. +func (i *Import) GetVCS() string { + if i == nil || i.VCS == nil { + return "" + } + return *i.VCS +} + +// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSPassword() string { + if i == nil || i.VCSPassword == nil { + return "" + } + return *i.VCSPassword +} + +// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSURL() string { + if i == nil || i.VCSURL == nil { + return "" + } + return *i.VCSURL +} + +// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSUsername() string { + if i == nil || i.VCSUsername == nil { + return "" + } + return *i.VCSUsername +} + +// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetAccessTokensURL() string { + if i == nil || i.AccessTokensURL == nil { + return "" + } + return *i.AccessTokensURL +} + +// GetAccount returns the Account field. +func (i *Installation) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppID() int64 { + if i == nil || i.AppID == nil { + return 0 + } + return *i.AppID +} + +// GetAppSlug returns the AppSlug field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppSlug() string { + if i == nil || i.AppSlug == nil { + return "" + } + return *i.AppSlug +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetHasMultipleSingleFiles returns the HasMultipleSingleFiles field if it's non-nil, zero value otherwise. +func (i *Installation) GetHasMultipleSingleFiles() bool { + if i == nil || i.HasMultipleSingleFiles == nil { + return false + } + return *i.HasMultipleSingleFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Installation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Installation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetPermissions returns the Permissions field. +func (i *Installation) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositoriesURL() string { + if i == nil || i.RepositoriesURL == nil { + return "" + } + return *i.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. +func (i *Installation) GetSingleFileName() string { + if i == nil || i.SingleFileName == nil { + return "" + } + return *i.SingleFileName +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetSuspendedAt() Timestamp { + if i == nil || i.SuspendedAt == nil { + return Timestamp{} + } + return *i.SuspendedAt +} + +// GetSuspendedBy returns the SuspendedBy field. +func (i *Installation) GetSuspendedBy() *User { + if i == nil { + return nil + } + return i.SuspendedBy +} + +// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetID() int64 { + if i == nil || i.TargetID == nil { + return 0 + } + return *i.TargetID +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetLogin returns the Login field. +func (i *InstallationChanges) GetLogin() *InstallationLoginChange { + if i == nil { + return nil + } + return i.Login +} + +// GetSlug returns the Slug field. +func (i *InstallationChanges) GetSlug() *InstallationSlugChange { + if i == nil { + return nil + } + return i.Slug +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrg returns the Org field. +func (i *InstallationEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRequester returns the Requester field. +func (i *InstallationEvent) GetRequester() *User { + if i == nil { + return nil + } + return i.Requester +} + +// GetSender returns the Sender field. +func (i *InstallationEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (i *InstallationLoginChange) GetFrom() string { + if i == nil || i.From == nil { + return "" + } + return *i.From +} + +// GetActions returns the Actions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetActions() string { + if i == nil || i.Actions == nil { + return "" + } + return *i.Actions +} + +// GetActionsVariables returns the ActionsVariables field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetActionsVariables() string { + if i == nil || i.ActionsVariables == nil { + return "" + } + return *i.ActionsVariables +} + +// GetAdministration returns the Administration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetAdministration() string { + if i == nil || i.Administration == nil { + return "" + } + return *i.Administration +} + +// GetAttestations returns the Attestations field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetAttestations() string { + if i == nil || i.Attestations == nil { + return "" + } + return *i.Attestations +} + +// GetBlocking returns the Blocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetBlocking() string { + if i == nil || i.Blocking == nil { + return "" + } + return *i.Blocking +} + +// GetChecks returns the Checks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetChecks() string { + if i == nil || i.Checks == nil { + return "" + } + return *i.Checks +} + +// GetCodespaces returns the Codespaces field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespaces() string { + if i == nil || i.Codespaces == nil { + return "" + } + return *i.Codespaces +} + +// GetCodespacesLifecycleAdmin returns the CodespacesLifecycleAdmin field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesLifecycleAdmin() string { + if i == nil || i.CodespacesLifecycleAdmin == nil { + return "" + } + return *i.CodespacesLifecycleAdmin +} + +// GetCodespacesMetadata returns the CodespacesMetadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesMetadata() string { + if i == nil || i.CodespacesMetadata == nil { + return "" + } + return *i.CodespacesMetadata +} + +// GetCodespacesSecrets returns the CodespacesSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesSecrets() string { + if i == nil || i.CodespacesSecrets == nil { + return "" + } + return *i.CodespacesSecrets +} + +// GetCodespacesUserSecrets returns the CodespacesUserSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCodespacesUserSecrets() string { + if i == nil || i.CodespacesUserSecrets == nil { + return "" + } + return *i.CodespacesUserSecrets +} + +// GetContentReferences returns the ContentReferences field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContentReferences() string { + if i == nil || i.ContentReferences == nil { + return "" + } + return *i.ContentReferences +} + +// GetContents returns the Contents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContents() string { + if i == nil || i.Contents == nil { + return "" + } + return *i.Contents +} + +// GetCopilotMessages returns the CopilotMessages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetCopilotMessages() string { + if i == nil || i.CopilotMessages == nil { + return "" + } + return *i.CopilotMessages +} + +// GetDependabotSecrets returns the DependabotSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDependabotSecrets() string { + if i == nil || i.DependabotSecrets == nil { + return "" + } + return *i.DependabotSecrets +} + +// GetDeployments returns the Deployments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDeployments() string { + if i == nil || i.Deployments == nil { + return "" + } + return *i.Deployments +} + +// GetDiscussions returns the Discussions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDiscussions() string { + if i == nil || i.Discussions == nil { + return "" + } + return *i.Discussions +} + +// GetEmails returns the Emails field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEmails() string { + if i == nil || i.Emails == nil { + return "" + } + return *i.Emails +} + +// GetEnvironments returns the Environments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEnvironments() string { + if i == nil || i.Environments == nil { + return "" + } + return *i.Environments +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetFollowers() string { + if i == nil || i.Followers == nil { + return "" + } + return *i.Followers +} + +// GetGists returns the Gists field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGists() string { + if i == nil || i.Gists == nil { + return "" + } + return *i.Gists +} + +// GetGitSigningSSHPublicKeys returns the GitSigningSSHPublicKeys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGitSigningSSHPublicKeys() string { + if i == nil || i.GitSigningSSHPublicKeys == nil { + return "" + } + return *i.GitSigningSSHPublicKeys +} + +// GetGPGKeys returns the GPGKeys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetGPGKeys() string { + if i == nil || i.GPGKeys == nil { + return "" + } + return *i.GPGKeys +} + +// GetInteractionLimits returns the InteractionLimits field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetInteractionLimits() string { + if i == nil || i.InteractionLimits == nil { + return "" + } + return *i.InteractionLimits +} + +// GetIssues returns the Issues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetIssues() string { + if i == nil || i.Issues == nil { + return "" + } + return *i.Issues +} + +// GetKeys returns the Keys field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetKeys() string { + if i == nil || i.Keys == nil { + return "" + } + return *i.Keys +} + +// GetMembers returns the Members field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMembers() string { + if i == nil || i.Members == nil { + return "" + } + return *i.Members +} + +// GetMergeQueues returns the MergeQueues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMergeQueues() string { + if i == nil || i.MergeQueues == nil { + return "" + } + return *i.MergeQueues +} + +// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMetadata() string { + if i == nil || i.Metadata == nil { + return "" + } + return *i.Metadata +} + +// GetOrganizationActionsVariables returns the OrganizationActionsVariables field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationActionsVariables() string { + if i == nil || i.OrganizationActionsVariables == nil { + return "" + } + return *i.OrganizationActionsVariables +} + +// GetOrganizationAdministration returns the OrganizationAdministration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAdministration() string { + if i == nil || i.OrganizationAdministration == nil { + return "" + } + return *i.OrganizationAdministration +} + +// GetOrganizationAnnouncementBanners returns the OrganizationAnnouncementBanners field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAnnouncementBanners() string { + if i == nil || i.OrganizationAnnouncementBanners == nil { + return "" + } + return *i.OrganizationAnnouncementBanners +} + +// GetOrganizationAPIInsights returns the OrganizationAPIInsights field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAPIInsights() string { + if i == nil || i.OrganizationAPIInsights == nil { + return "" + } + return *i.OrganizationAPIInsights +} + +// GetOrganizationCodespaces returns the OrganizationCodespaces field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespaces() string { + if i == nil || i.OrganizationCodespaces == nil { + return "" + } + return *i.OrganizationCodespaces +} + +// GetOrganizationCodespacesSecrets returns the OrganizationCodespacesSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespacesSecrets() string { + if i == nil || i.OrganizationCodespacesSecrets == nil { + return "" + } + return *i.OrganizationCodespacesSecrets +} + +// GetOrganizationCodespacesSettings returns the OrganizationCodespacesSettings field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCodespacesSettings() string { + if i == nil || i.OrganizationCodespacesSettings == nil { + return "" + } + return *i.OrganizationCodespacesSettings +} + +// GetOrganizationCopilotSeatManagement returns the OrganizationCopilotSeatManagement field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCopilotSeatManagement() string { + if i == nil || i.OrganizationCopilotSeatManagement == nil { + return "" + } + return *i.OrganizationCopilotSeatManagement +} + +// GetOrganizationCustomOrgRoles returns the OrganizationCustomOrgRoles field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomOrgRoles() string { + if i == nil || i.OrganizationCustomOrgRoles == nil { + return "" + } + return *i.OrganizationCustomOrgRoles +} + +// GetOrganizationCustomProperties returns the OrganizationCustomProperties field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomProperties() string { + if i == nil || i.OrganizationCustomProperties == nil { + return "" + } + return *i.OrganizationCustomProperties +} + +// GetOrganizationCustomRoles returns the OrganizationCustomRoles field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomRoles() string { + if i == nil || i.OrganizationCustomRoles == nil { + return "" + } + return *i.OrganizationCustomRoles +} + +// GetOrganizationDependabotSecrets returns the OrganizationDependabotSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationDependabotSecrets() string { + if i == nil || i.OrganizationDependabotSecrets == nil { + return "" + } + return *i.OrganizationDependabotSecrets +} + +// GetOrganizationEvents returns the OrganizationEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationEvents() string { + if i == nil || i.OrganizationEvents == nil { + return "" + } + return *i.OrganizationEvents +} + +// GetOrganizationHooks returns the OrganizationHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationHooks() string { + if i == nil || i.OrganizationHooks == nil { + return "" + } + return *i.OrganizationHooks +} + +// GetOrganizationKnowledgeBases returns the OrganizationKnowledgeBases field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationKnowledgeBases() string { + if i == nil || i.OrganizationKnowledgeBases == nil { + return "" + } + return *i.OrganizationKnowledgeBases +} + +// GetOrganizationPackages returns the OrganizationPackages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPackages() string { + if i == nil || i.OrganizationPackages == nil { + return "" + } + return *i.OrganizationPackages +} + +// GetOrganizationPersonalAccessTokenRequests returns the OrganizationPersonalAccessTokenRequests field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPersonalAccessTokenRequests() string { + if i == nil || i.OrganizationPersonalAccessTokenRequests == nil { + return "" + } + return *i.OrganizationPersonalAccessTokenRequests +} + +// GetOrganizationPersonalAccessTokens returns the OrganizationPersonalAccessTokens field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPersonalAccessTokens() string { + if i == nil || i.OrganizationPersonalAccessTokens == nil { + return "" + } + return *i.OrganizationPersonalAccessTokens +} + +// GetOrganizationPlan returns the OrganizationPlan field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPlan() string { + if i == nil || i.OrganizationPlan == nil { + return "" + } + return *i.OrganizationPlan +} + +// GetOrganizationPreReceiveHooks returns the OrganizationPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPreReceiveHooks() string { + if i == nil || i.OrganizationPreReceiveHooks == nil { + return "" + } + return *i.OrganizationPreReceiveHooks +} + +// GetOrganizationProjects returns the OrganizationProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationProjects() string { + if i == nil || i.OrganizationProjects == nil { + return "" + } + return *i.OrganizationProjects +} + +// GetOrganizationSecrets returns the OrganizationSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSecrets() string { + if i == nil || i.OrganizationSecrets == nil { + return "" + } + return *i.OrganizationSecrets +} + +// GetOrganizationSelfHostedRunners returns the OrganizationSelfHostedRunners field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSelfHostedRunners() string { + if i == nil || i.OrganizationSelfHostedRunners == nil { + return "" + } + return *i.OrganizationSelfHostedRunners +} + +// GetOrganizationUserBlocking returns the OrganizationUserBlocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationUserBlocking() string { + if i == nil || i.OrganizationUserBlocking == nil { + return "" + } + return *i.OrganizationUserBlocking +} + +// GetPackages returns the Packages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPackages() string { + if i == nil || i.Packages == nil { + return "" + } + return *i.Packages +} + +// GetPages returns the Pages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPages() string { + if i == nil || i.Pages == nil { + return "" + } + return *i.Pages +} + +// GetPlan returns the Plan field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPlan() string { + if i == nil || i.Plan == nil { + return "" + } + return *i.Plan +} + +// GetProfile returns the Profile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetProfile() string { + if i == nil || i.Profile == nil { + return "" + } + return *i.Profile +} + +// GetPullRequests returns the PullRequests field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPullRequests() string { + if i == nil || i.PullRequests == nil { + return "" + } + return *i.PullRequests +} + +// GetRepositoryAdvisories returns the RepositoryAdvisories field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryAdvisories() string { + if i == nil || i.RepositoryAdvisories == nil { + return "" + } + return *i.RepositoryAdvisories +} + +// GetRepositoryCustomProperties returns the RepositoryCustomProperties field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryCustomProperties() string { + if i == nil || i.RepositoryCustomProperties == nil { + return "" + } + return *i.RepositoryCustomProperties +} + +// GetRepositoryHooks returns the RepositoryHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryHooks() string { + if i == nil || i.RepositoryHooks == nil { + return "" + } + return *i.RepositoryHooks +} + +// GetRepositoryPreReceiveHooks returns the RepositoryPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryPreReceiveHooks() string { + if i == nil || i.RepositoryPreReceiveHooks == nil { + return "" + } + return *i.RepositoryPreReceiveHooks +} + +// GetRepositoryProjects returns the RepositoryProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryProjects() string { + if i == nil || i.RepositoryProjects == nil { + return "" + } + return *i.RepositoryProjects +} + +// GetSecrets returns the Secrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecrets() string { + if i == nil || i.Secrets == nil { + return "" + } + return *i.Secrets +} + +// GetSecretScanningAlerts returns the SecretScanningAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecretScanningAlerts() string { + if i == nil || i.SecretScanningAlerts == nil { + return "" + } + return *i.SecretScanningAlerts +} + +// GetSecurityEvents returns the SecurityEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecurityEvents() string { + if i == nil || i.SecurityEvents == nil { + return "" + } + return *i.SecurityEvents +} + +// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSingleFile() string { + if i == nil || i.SingleFile == nil { + return "" + } + return *i.SingleFile +} + +// GetStarring returns the Starring field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetStarring() string { + if i == nil || i.Starring == nil { + return "" + } + return *i.Starring +} + +// GetStatuses returns the Statuses field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetStatuses() string { + if i == nil || i.Statuses == nil { + return "" + } + return *i.Statuses +} + +// GetTeamDiscussions returns the TeamDiscussions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetTeamDiscussions() string { + if i == nil || i.TeamDiscussions == nil { + return "" + } + return *i.TeamDiscussions +} + +// GetUserEvents returns the UserEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetUserEvents() string { + if i == nil || i.UserEvents == nil { + return "" + } + return *i.UserEvents +} + +// GetVulnerabilityAlerts returns the VulnerabilityAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetVulnerabilityAlerts() string { + if i == nil || i.VulnerabilityAlerts == nil { + return "" + } + return *i.VulnerabilityAlerts +} + +// GetWatching returns the Watching field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetWatching() string { + if i == nil || i.Watching == nil { + return "" + } + return *i.Watching +} + +// GetWorkflows returns the Workflows field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetWorkflows() string { + if i == nil || i.Workflows == nil { + return "" + } + return *i.Workflows +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrg returns the Org field. +func (i *InstallationRepositoriesEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSender returns the Sender field. +func (i *InstallationRepositoriesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetAccount returns the Account field. +func (i *InstallationRequest) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *InstallationRequest) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetRequester returns the Requester field. +func (i *InstallationRequest) GetRequester() *User { + if i == nil { + return nil + } + return i.Requester +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (i *InstallationSlugChange) GetFrom() string { + if i == nil || i.From == nil { + return "" + } + return *i.From +} + +// GetAccount returns the Account field. +func (i *InstallationTargetEvent) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationTargetEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *InstallationTargetEvent) GetChanges() *InstallationChanges { + if i == nil { + return nil + } + return i.Changes +} + +// GetEnterprise returns the Enterprise field. +func (i *InstallationTargetEvent) GetEnterprise() *Enterprise { + if i == nil { + return nil + } + return i.Enterprise +} + +// GetInstallation returns the Installation field. +func (i *InstallationTargetEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetOrganization returns the Organization field. +func (i *InstallationTargetEvent) GetOrganization() *Organization { + if i == nil { + return nil + } + return i.Organization +} + +// GetRepository returns the Repository field. +func (i *InstallationTargetEvent) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetSender returns the Sender field. +func (i *InstallationTargetEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *InstallationTargetEvent) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetExpiresAt() Timestamp { + if i == nil || i.ExpiresAt == nil { + return Timestamp{} + } + return *i.ExpiresAt +} + +// GetPermissions returns the Permissions field. +func (i *InstallationToken) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetToken() string { + if i == nil || i.Token == nil { + return "" + } + return *i.Token +} + +// GetPermissions returns the Permissions field. +func (i *InstallationTokenListRepoOptions) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetPermissions returns the Permissions field. +func (i *InstallationTokenOptions) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetExpiresAt() Timestamp { + if i == nil || i.ExpiresAt == nil { + return Timestamp{} + } + return *i.ExpiresAt +} + +// GetLimit returns the Limit field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetLimit() string { + if i == nil || i.Limit == nil { + return "" + } + return *i.Limit +} + +// GetOrigin returns the Origin field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetOrigin() string { + if i == nil || i.Origin == nil { + return "" + } + return *i.Origin +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (i *Invitation) GetEmail() string { + if i == nil || i.Email == nil { + return "" + } + return *i.Email +} + +// GetFailedAt returns the FailedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedAt() Timestamp { + if i == nil || i.FailedAt == nil { + return Timestamp{} + } + return *i.FailedAt +} + +// GetFailedReason returns the FailedReason field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedReason() string { + if i == nil || i.FailedReason == nil { + return "" + } + return *i.FailedReason +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. +func (i *Invitation) GetInvitationTeamURL() string { + if i == nil || i.InvitationTeamURL == nil { + return "" + } + return *i.InvitationTeamURL +} + +// GetInviter returns the Inviter field. +func (i *Invitation) GetInviter() *User { + if i == nil { + return nil + } + return i.Inviter +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (i *Invitation) GetLogin() string { + if i == nil || i.Login == nil { + return "" + } + return *i.Login +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (i *Invitation) GetRole() string { + if i == nil || i.Role == nil { + return "" + } + return *i.Role +} + +// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. +func (i *Invitation) GetTeamCount() int { + if i == nil || i.TeamCount == nil { + return 0 + } + return *i.TeamCount +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (i *Issue) GetActiveLockReason() string { + if i == nil || i.ActiveLockReason == nil { + return "" + } + return *i.ActiveLockReason +} + +// GetAssignee returns the Assignee field. +func (i *Issue) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *Issue) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *Issue) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetClosedAt() Timestamp { + if i == nil || i.ClosedAt == nil { + return Timestamp{} + } + return *i.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (i *Issue) GetClosedBy() *User { + if i == nil { + return nil + } + return i.ClosedBy +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (i *Issue) GetComments() int { + if i == nil || i.Comments == nil { + return 0 + } + return *i.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetCommentsURL() string { + if i == nil || i.CommentsURL == nil { + return "" + } + return *i.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (i *Issue) GetDraft() bool { + if i == nil || i.Draft == nil { + return false + } + return *i.Draft +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetEventsURL() string { + if i == nil || i.EventsURL == nil { + return "" + } + return *i.EventsURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Issue) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetLabelsURL() string { + if i == nil || i.LabelsURL == nil { + return "" + } + return *i.LabelsURL +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (i *Issue) GetLocked() bool { + if i == nil || i.Locked == nil { + return false + } + return *i.Locked +} + +// GetMilestone returns the Milestone field. +func (i *Issue) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Issue) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (i *Issue) GetNumber() int { + if i == nil || i.Number == nil { + return 0 + } + return *i.Number +} + +// GetPullRequestLinks returns the PullRequestLinks field. +func (i *Issue) GetPullRequestLinks() *PullRequestLinks { + if i == nil { + return nil + } + return i.PullRequestLinks +} + +// GetReactions returns the Reactions field. +func (i *Issue) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetRepository returns the Repository field. +func (i *Issue) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *Issue) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetStateReason returns the StateReason field if it's non-nil, zero value otherwise. +func (i *Issue) GetStateReason() string { + if i == nil || i.StateReason == nil { + return "" + } + return *i.StateReason +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *Issue) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Issue) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *Issue) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetIssueURL() string { + if i == nil || i.IssueURL == nil { + return "" + } + return *i.IssueURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetReactions returns the Reactions field. +func (i *IssueComment) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *IssueComment) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssueCommentEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *IssueCommentEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetComment returns the Comment field. +func (i *IssueCommentEvent) GetComment() *IssueComment { + if i == nil { + return nil + } + return i.Comment +} + +// GetInstallation returns the Installation field. +func (i *IssueCommentEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssueCommentEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetOrganization returns the Organization field. +func (i *IssueCommentEvent) GetOrganization() *Organization { + if i == nil { + return nil + } + return i.Organization +} + +// GetRepo returns the Repo field. +func (i *IssueCommentEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssueCommentEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetActor returns the Actor field. +func (i *IssueEvent) GetActor() *User { + if i == nil { + return nil + } + return i.Actor +} + +// GetAssignee returns the Assignee field. +func (i *IssueEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAssigner returns the Assigner field. +func (i *IssueEvent) GetAssigner() *User { + if i == nil { + return nil + } + return i.Assigner +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCommitID() string { + if i == nil || i.CommitID == nil { + return "" + } + return *i.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDismissedReview returns the DismissedReview field. +func (i *IssueEvent) GetDismissedReview() *DismissedReview { + if i == nil { + return nil + } + return i.DismissedReview +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetEvent() string { + if i == nil || i.Event == nil { + return "" + } + return *i.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssue returns the Issue field. +func (i *IssueEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssueEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetLockReason() string { + if i == nil || i.LockReason == nil { + return "" + } + return *i.LockReason +} + +// GetMilestone returns the Milestone field. +func (i *IssueEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (i *IssueEvent) GetPerformedViaGithubApp() *App { + if i == nil { + return nil + } + return i.PerformedViaGithubApp +} + +// GetRename returns the Rename field. +func (i *IssueEvent) GetRename() *Rename { + if i == nil { + return nil + } + return i.Rename +} + +// GetRepository returns the Repository field. +func (i *IssueEvent) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (i *IssueEvent) GetRequestedReviewer() *User { + if i == nil { + return nil + } + return i.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (i *IssueEvent) GetRequestedTeam() *Team { + if i == nil { + return nil + } + return i.RequestedTeam +} + +// GetReviewRequester returns the ReviewRequester field. +func (i *IssueEvent) GetReviewRequester() *User { + if i == nil { + return nil + } + return i.ReviewRequester +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetClosed returns the Closed field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosed() bool { + if i == nil || i.Closed == nil { + return false + } + return *i.Closed +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosedAt() Timestamp { + if i == nil || i.ClosedAt == nil { + return Timestamp{} + } + return *i.ClosedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetCode returns the Code field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetCode() string { + if i == nil || i.Code == nil { + return "" + } + return *i.Code +} + +// GetField returns the Field field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetField() string { + if i == nil || i.Field == nil { + return "" + } + return *i.Field +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetLocation() string { + if i == nil || i.Location == nil { + return "" + } + return *i.Location +} + +// GetResource returns the Resource field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetResource() string { + if i == nil || i.Resource == nil { + return "" + } + return *i.Resource +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetValue() string { + if i == nil || i.Value == nil { + return "" + } + return *i.Value +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDocumentationURL returns the DocumentationURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetDocumentationURL() string { + if i == nil || i.DocumentationURL == nil { + return "" + } + return *i.DocumentationURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetID() int { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetImportIssuesURL returns the ImportIssuesURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetImportIssuesURL() string { + if i == nil || i.ImportIssuesURL == nil { + return "" + } + return *i.ImportIssuesURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetDirection() string { + if i == nil || i.Direction == nil { + return "" + } + return *i.Direction +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSince() time.Time { + if i == nil || i.Since == nil { + return time.Time{} + } + return *i.Since +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSort() string { + if i == nil || i.Sort == nil { + return "" + } + return *i.Sort +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignees() []string { + if i == nil || i.Assignees == nil { + return nil + } + return *i.Assignees +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetLabels returns the Labels field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetLabels() []string { + if i == nil || i.Labels == nil { + return nil + } + return *i.Labels +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetStateReason returns the StateReason field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetStateReason() string { + if i == nil || i.StateReason == nil { + return "" + } + return *i.StateReason +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssuesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetAssignee returns the Assignee field. +func (i *IssuesEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetChanges returns the Changes field. +func (i *IssuesEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetInstallation returns the Installation field. +func (i *IssuesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssuesEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssuesEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetMilestone returns the Milestone field. +func (i *IssuesEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetOrg returns the Org field. +func (i *IssuesEvent) GetOrg() *Organization { + if i == nil { + return nil + } + return i.Org +} + +// GetRepo returns the Repo field. +func (i *IssuesEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssuesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetIncompleteResults() bool { + if i == nil || i.IncompleteResults == nil { + return false + } + return *i.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetTotal() int { + if i == nil || i.Total == nil { + return 0 + } + return *i.Total +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetClosedIssues() int { + if i == nil || i.ClosedIssues == nil { + return 0 + } + return *i.ClosedIssues +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetOpenIssues() int { + if i == nil || i.OpenIssues == nil { + return 0 + } + return *i.OpenIssues +} + +// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetTotalIssues() int { + if i == nil || i.TotalIssues == nil { + return 0 + } + return *i.TotalIssues +} + +// GetEncodedJITConfig returns the EncodedJITConfig field if it's non-nil, zero value otherwise. +func (j *JITRunnerConfig) GetEncodedJITConfig() string { + if j == nil || j.EncodedJITConfig == nil { + return "" + } + return *j.EncodedJITConfig +} + +// GetRunner returns the Runner field. +func (j *JITRunnerConfig) GetRunner() *Runner { + if j == nil { + return nil + } + return j.Runner +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (j *Jobs) GetTotalCount() int { + if j == nil || j.TotalCount == nil { + return 0 + } + return *j.TotalCount +} + +// GetAddedBy returns the AddedBy field if it's non-nil, zero value otherwise. +func (k *Key) GetAddedBy() string { + if k == nil || k.AddedBy == nil { + return "" + } + return *k.AddedBy +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (k *Key) GetCreatedAt() Timestamp { + if k == nil || k.CreatedAt == nil { + return Timestamp{} + } + return *k.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (k *Key) GetID() int64 { + if k == nil || k.ID == nil { + return 0 + } + return *k.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (k *Key) GetKey() string { + if k == nil || k.Key == nil { + return "" + } + return *k.Key +} + +// GetLastUsed returns the LastUsed field if it's non-nil, zero value otherwise. +func (k *Key) GetLastUsed() Timestamp { + if k == nil || k.LastUsed == nil { + return Timestamp{} + } + return *k.LastUsed +} + +// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. +func (k *Key) GetReadOnly() bool { + if k == nil || k.ReadOnly == nil { + return false + } + return *k.ReadOnly +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (k *Key) GetTitle() string { + if k == nil || k.Title == nil { + return "" + } + return *k.Title +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (k *Key) GetURL() string { + if k == nil || k.URL == nil { + return "" + } + return *k.URL +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (k *Key) GetVerified() bool { + if k == nil || k.Verified == nil { + return false + } + return *k.Verified +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *Label) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *Label) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *Label) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *Label) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *Label) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (l *Label) GetNodeID() string { + if l == nil || l.NodeID == nil { + return "" + } + return *l.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *Label) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (l *LabelEvent) GetAction() string { + if l == nil || l.Action == nil { + return "" + } + return *l.Action +} + +// GetChanges returns the Changes field. +func (l *LabelEvent) GetChanges() *EditChange { + if l == nil { + return nil + } + return l.Changes +} + +// GetInstallation returns the Installation field. +func (l *LabelEvent) GetInstallation() *Installation { + if l == nil { + return nil + } + return l.Installation +} + +// GetLabel returns the Label field. +func (l *LabelEvent) GetLabel() *Label { + if l == nil { + return nil + } + return l.Label +} + +// GetOrg returns the Org field. +func (l *LabelEvent) GetOrg() *Organization { + if l == nil { + return nil + } + return l.Org +} + +// GetRepo returns the Repo field. +func (l *LabelEvent) GetRepo() *Repository { + if l == nil { + return nil + } + return l.Repo +} + +// GetSender returns the Sender field. +func (l *LabelEvent) GetSender() *User { + if l == nil { + return nil + } + return l.Sender +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetScore returns the Score field. +func (l *LabelResult) GetScore() *float64 { + if l == nil { + return nil + } + return l.Score +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetIncompleteResults() bool { + if l == nil || l.IncompleteResults == nil { + return false + } + return *l.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetOID returns the OID field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetOID() string { + if l == nil || l.OID == nil { + return "" + } + return *l.OID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetRefName returns the RefName field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetRefName() string { + if l == nil || l.RefName == nil { + return "" + } + return *l.RefName +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetSize() int { + if l == nil || l.Size == nil { + return 0 + } + return *l.Size +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (l *License) GetBody() string { + if l == nil || l.Body == nil { + return "" + } + return *l.Body +} + +// GetConditions returns the Conditions field if it's non-nil, zero value otherwise. +func (l *License) GetConditions() []string { + if l == nil || l.Conditions == nil { + return nil + } + return *l.Conditions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *License) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (l *License) GetFeatured() bool { + if l == nil || l.Featured == nil { + return false + } + return *l.Featured +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (l *License) GetHTMLURL() string { + if l == nil || l.HTMLURL == nil { + return "" + } + return *l.HTMLURL +} + +// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. +func (l *License) GetImplementation() string { + if l == nil || l.Implementation == nil { + return "" + } + return *l.Implementation +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (l *License) GetKey() string { + if l == nil || l.Key == nil { + return "" + } + return *l.Key +} + +// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. +func (l *License) GetLimitations() []string { + if l == nil || l.Limitations == nil { + return nil + } + return *l.Limitations +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *License) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (l *License) GetPermissions() []string { + if l == nil || l.Permissions == nil { + return nil + } + return *l.Permissions +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (l *License) GetSPDXID() string { + if l == nil || l.SPDXID == nil { + return "" + } + return *l.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *License) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (l *LinearHistoryRequirementEnforcementLevelChanges) GetFrom() string { + if l == nil || l.From == nil { + return "" + } + return *l.From +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetDirection() string { + if l == nil || l.Direction == nil { + return "" + } + return *l.Direction +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetEcosystem() string { + if l == nil || l.Ecosystem == nil { + return "" + } + return *l.Ecosystem +} + +// GetPackage returns the Package field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetPackage() string { + if l == nil || l.Package == nil { + return "" + } + return *l.Package +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetScope() string { + if l == nil || l.Scope == nil { + return "" + } + return *l.Scope +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetSeverity() string { + if l == nil || l.Severity == nil { + return "" + } + return *l.Severity +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetSort() string { + if l == nil || l.Sort == nil { + return "" + } + return *l.Sort +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (l *ListAlertsOptions) GetState() string { + if l == nil || l.State == nil { + return "" + } + return *l.State +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *ListArtifactsOptions) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetAppID() int64 { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetStatus() string { + if l == nil || l.Status == nil { + return "" + } + return *l.Status +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetAppID() int { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListCodespaces) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListCustomDeploymentRuleIntegrationsResponse) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListDeploymentProtectionRuleResponse) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (l *ListExternalGroupsOptions) GetDisplayName() string { + if l == nil || l.DisplayName == nil { + return "" + } + return *l.DisplayName +} + +// GetAffects returns the Affects field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetAffects() string { + if l == nil || l.Affects == nil { + return "" + } + return *l.Affects +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetCVEID() string { + if l == nil || l.CVEID == nil { + return "" + } + return *l.CVEID +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetEcosystem() string { + if l == nil || l.Ecosystem == nil { + return "" + } + return *l.Ecosystem +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetGHSAID() string { + if l == nil || l.GHSAID == nil { + return "" + } + return *l.GHSAID +} + +// GetIsWithdrawn returns the IsWithdrawn field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetIsWithdrawn() bool { + if l == nil || l.IsWithdrawn == nil { + return false + } + return *l.IsWithdrawn +} + +// GetModified returns the Modified field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetModified() string { + if l == nil || l.Modified == nil { + return "" + } + return *l.Modified +} + +// GetPublished returns the Published field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetPublished() string { + if l == nil || l.Published == nil { + return "" + } + return *l.Published +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetSeverity() string { + if l == nil || l.Severity == nil { + return "" + } + return *l.Severity +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetType() string { + if l == nil || l.Type == nil { + return "" + } + return *l.Type +} + +// GetUpdated returns the Updated field if it's non-nil, zero value otherwise. +func (l *ListGlobalSecurityAdvisoriesOptions) GetUpdated() string { + if l == nil || l.Updated == nil { + return "" + } + return *l.Updated +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListOrganizations) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListRepositories) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *ListRunnersOptions) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetCount() int { + if l == nil || l.Count == nil { + return 0 + } + return *l.Count +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetStartIndex() int { + if l == nil || l.StartIndex == nil { + return 0 + } + return *l.StartIndex +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetEndColumn() int { + if l == nil || l.EndColumn == nil { + return 0 + } + return *l.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (l *Location) GetEndLine() int { + if l == nil || l.EndLine == nil { + return 0 + } + return *l.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *Location) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetStartColumn() int { + if l == nil || l.StartColumn == nil { + return 0 + } + return *l.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (l *Location) GetStartLine() int { + if l == nil || l.StartLine == nil { + return 0 + } + return *l.StartLine +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (l *LockBranch) GetEnabled() bool { + if l == nil || l.Enabled == nil { + return false + } + return *l.Enabled +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetPlan returns the Plan field. +func (m *MarketplacePendingChange) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetAccountsURL() string { + if m == nil || m.AccountsURL == nil { + return "" + } + return *m.AccountsURL +} + +// GetBullets returns the Bullets field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetBullets() []string { + if m == nil || m.Bullets == nil { + return nil + } + return *m.Bullets +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetHasFreeTrial returns the HasFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetHasFreeTrial() bool { + if m == nil || m.HasFreeTrial == nil { + return false + } + return *m.HasFreeTrial +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetMonthlyPriceInCents() int { + if m == nil || m.MonthlyPriceInCents == nil { + return 0 + } + return *m.MonthlyPriceInCents +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetPriceModel() string { + if m == nil || m.PriceModel == nil { + return "" + } + return *m.PriceModel +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetUnitName() string { + if m == nil || m.UnitName == nil { + return "" + } + return *m.UnitName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetYearlyPriceInCents() int { + if m == nil || m.YearlyPriceInCents == nil { + return 0 + } + return *m.YearlyPriceInCents +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetMarketplacePendingChange returns the MarketplacePendingChange field. +func (m *MarketplacePlanAccount) GetMarketplacePendingChange() *MarketplacePendingChange { + if m == nil { + return nil + } + return m.MarketplacePendingChange +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAccount returns the Account field. +func (m *MarketplacePurchase) GetAccount() *MarketplacePurchaseAccount { + if m == nil { + return nil + } + return m.Account +} + +// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetBillingCycle() string { + if m == nil || m.BillingCycle == nil { + return "" + } + return *m.BillingCycle +} + +// GetFreeTrialEndsOn returns the FreeTrialEndsOn field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetFreeTrialEndsOn() Timestamp { + if m == nil || m.FreeTrialEndsOn == nil { + return Timestamp{} + } + return *m.FreeTrialEndsOn +} + +// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetNextBillingDate() Timestamp { + if m == nil || m.NextBillingDate == nil { + return Timestamp{} + } + return *m.NextBillingDate +} + +// GetOnFreeTrial returns the OnFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetOnFreeTrial() bool { + if m == nil || m.OnFreeTrial == nil { + return false + } + return *m.OnFreeTrial +} + +// GetPlan returns the Plan field. +func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUpdatedAt() Timestamp { + if m == nil || m.UpdatedAt == nil { + return Timestamp{} + } + return *m.UpdatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetEmail() string { + if m == nil || m.Email == nil { + return "" + } + return *m.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrg returns the Org field. +func (m *MarketplacePurchaseEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.PreviousMarketplacePurchase +} + +// GetSender returns the Sender field. +func (m *MarketplacePurchaseEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Match) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetPermission returns the Permission field. +func (m *MemberChanges) GetPermission() *MemberChangesPermission { + if m == nil { + return nil + } + return m.Permission +} + +// GetRoleName returns the RoleName field. +func (m *MemberChanges) GetRoleName() *MemberChangesRoleName { + if m == nil { + return nil + } + return m.RoleName +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (m *MemberChangesPermission) GetFrom() string { + if m == nil || m.From == nil { + return "" + } + return *m.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (m *MemberChangesPermission) GetTo() string { + if m == nil || m.To == nil { + return "" + } + return *m.To +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (m *MemberChangesRoleName) GetFrom() string { + if m == nil || m.From == nil { + return "" + } + return *m.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (m *MemberChangesRoleName) GetTo() string { + if m == nil || m.To == nil { + return "" + } + return *m.To +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MemberEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MemberEvent) GetChanges() *MemberChanges { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MemberEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MemberEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MemberEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MemberEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MemberEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetOrganization returns the Organization field. +func (m *Membership) GetOrganization() *Organization { + if m == nil { + return nil + } + return m.Organization +} + +// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. +func (m *Membership) GetOrganizationURL() string { + if m == nil || m.OrganizationURL == nil { + return "" + } + return *m.OrganizationURL +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (m *Membership) GetRole() string { + if m == nil || m.Role == nil { + return "" + } + return *m.Role +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Membership) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Membership) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetUser returns the User field. +func (m *Membership) GetUser() *User { + if m == nil { + return nil + } + return m.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MembershipEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MembershipEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MembershipEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetScope() string { + if m == nil || m.Scope == nil { + return "" + } + return *m.Scope +} + +// GetSender returns the Sender field. +func (m *MembershipEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetTeam returns the Team field. +func (m *MembershipEvent) GetTeam() *Team { + if m == nil { + return nil + } + return m.Team +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetBaseRef() string { + if m == nil || m.BaseRef == nil { + return "" + } + return *m.BaseRef +} + +// GetBaseSHA returns the BaseSHA field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetBaseSHA() string { + if m == nil || m.BaseSHA == nil { + return "" + } + return *m.BaseSHA +} + +// GetHeadCommit returns the HeadCommit field. +func (m *MergeGroup) GetHeadCommit() *Commit { + if m == nil { + return nil + } + return m.HeadCommit +} + +// GetHeadRef returns the HeadRef field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetHeadRef() string { + if m == nil || m.HeadRef == nil { + return "" + } + return *m.HeadRef +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (m *MergeGroup) GetHeadSHA() string { + if m == nil || m.HeadSHA == nil { + return "" + } + return *m.HeadSHA +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MergeGroupEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MergeGroupEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMergeGroup returns the MergeGroup field. +func (m *MergeGroupEvent) GetMergeGroup() *MergeGroup { + if m == nil { + return nil + } + return m.MergeGroup +} + +// GetOrg returns the Org field. +func (m *MergeGroupEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MergeGroupEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MergeGroupEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Message) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetHook returns the Hook field. +func (m *MetaEvent) GetHook() *Hook { + if m == nil { + return nil + } + return m.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetHookID() int64 { + if m == nil || m.HookID == nil { + return 0 + } + return *m.HookID +} + +// GetInstallation returns the Installation field. +func (m *MetaEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetOrg returns the Org field. +func (m *MetaEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MetaEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MetaEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Metric) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (m *Metric) GetKey() string { + if m == nil || m.Key == nil { + return "" + } + return *m.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *Metric) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Metric) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (m *Metric) GetSPDXID() string { + if m == nil || m.SPDXID == nil { + return "" + } + return *m.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Metric) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetCreatedAt() string { + if m == nil || m.CreatedAt == nil { + return "" + } + return *m.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (m *Migration) GetExcludeAttachments() bool { + if m == nil || m.ExcludeAttachments == nil { + return false + } + return *m.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (m *Migration) GetGUID() string { + if m == nil || m.GUID == nil { + return "" + } + return *m.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Migration) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (m *Migration) GetLockRepositories() bool { + if m == nil || m.LockRepositories == nil { + return false + } + return *m.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Migration) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetUpdatedAt() string { + if m == nil || m.UpdatedAt == nil { + return "" + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Migration) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedAt() Timestamp { + if m == nil || m.ClosedAt == nil { + return Timestamp{} + } + return *m.ClosedAt +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedIssues() int { + if m == nil || m.ClosedIssues == nil { + return 0 + } + return *m.ClosedIssues +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetCreatedAt() Timestamp { + if m == nil || m.CreatedAt == nil { + return Timestamp{} + } + return *m.CreatedAt +} + +// GetCreator returns the Creator field. +func (m *Milestone) GetCreator() *User { + if m == nil { + return nil + } + return m.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDueOn() Timestamp { + if m == nil || m.DueOn == nil { + return Timestamp{} + } + return *m.DueOn +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetLabelsURL() string { + if m == nil || m.LabelsURL == nil { + return "" + } + return *m.LabelsURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetOpenIssues() int { + if m == nil || m.OpenIssues == nil { + return 0 + } + return *m.OpenIssues +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Milestone) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (m *Milestone) GetTitle() string { + if m == nil || m.Title == nil { + return "" + } + return *m.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetUpdatedAt() Timestamp { + if m == nil || m.UpdatedAt == nil { + return Timestamp{} + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MilestoneEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MilestoneEvent) GetChanges() *EditChange { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MilestoneEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMilestone returns the Milestone field. +func (m *MilestoneEvent) GetMilestone() *Milestone { + if m == nil { + return nil + } + return m.Milestone +} + +// GetOrg returns the Org field. +func (m *MilestoneEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MilestoneEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MilestoneEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetClosedMilestones() int { + if m == nil || m.ClosedMilestones == nil { + return 0 + } + return *m.ClosedMilestones +} + +// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetOpenMilestones() int { + if m == nil || m.OpenMilestones == nil { + return 0 + } + return *m.OpenMilestones +} + +// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetTotalMilestones() int { + if m == nil || m.TotalMilestones == nil { + return 0 + } + return *m.TotalMilestones +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetAnalysisKey() string { + if m == nil || m.AnalysisKey == nil { + return "" + } + return *m.AnalysisKey +} + +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCategory() string { + if m == nil || m.Category == nil { + return "" + } + return *m.Category +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCommitSHA() string { + if m == nil || m.CommitSHA == nil { + return "" + } + return *m.CommitSHA +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetEnvironment() string { + if m == nil || m.Environment == nil { + return "" + } + return *m.Environment +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetLocation returns the Location field. +func (m *MostRecentInstance) GetLocation() *Location { + if m == nil { + return nil + } + return m.Location +} + +// GetMessage returns the Message field. +func (m *MostRecentInstance) GetMessage() *Message { + if m == nil { + return nil + } + return m.Message +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetRef() string { + if m == nil || m.Ref == nil { + return "" + } + return *m.Ref +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBase() string { + if n == nil || n.Base == nil { + return "" + } + return *n.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBody() string { + if n == nil || n.Body == nil { + return "" + } + return *n.Body +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetDraft() bool { + if n == nil || n.Draft == nil { + return false + } + return *n.Draft +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHead() string { + if n == nil || n.Head == nil { + return "" + } + return *n.Head +} + +// GetHeadRepo returns the HeadRepo field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHeadRepo() string { + if n == nil || n.HeadRepo == nil { + return "" + } + return *n.HeadRepo +} + +// GetIssue returns the Issue field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetIssue() int { + if n == nil || n.Issue == nil { + return 0 + } + return *n.Issue +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetMaintainerCanModify() bool { + if n == nil || n.MaintainerCanModify == nil { + return false + } + return *n.MaintainerCanModify +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetDescription() string { + if n == nil || n.Description == nil { + return "" + } + return *n.Description +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetLDAPDN() string { + if n == nil || n.LDAPDN == nil { + return "" + } + return *n.LDAPDN +} + +// GetNotificationSetting returns the NotificationSetting field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetNotificationSetting() string { + if n == nil || n.NotificationSetting == nil { + return "" + } + return *n.NotificationSetting +} + +// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetParentTeamID() int64 { + if n == nil || n.ParentTeamID == nil { + return 0 + } + return *n.ParentTeamID +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPermission() string { + if n == nil || n.Permission == nil { + return "" + } + return *n.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPrivacy() string { + if n == nil || n.Privacy == nil { + return "" + } + return *n.Privacy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *Notification) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetLastReadAt() Timestamp { + if n == nil || n.LastReadAt == nil { + return Timestamp{} + } + return *n.LastReadAt +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (n *Notification) GetReason() string { + if n == nil || n.Reason == nil { + return "" + } + return *n.Reason +} + +// GetRepository returns the Repository field. +func (n *Notification) GetRepository() *Repository { + if n == nil { + return nil + } + return n.Repository +} + +// GetSubject returns the Subject field. +func (n *Notification) GetSubject() *NotificationSubject { + if n == nil { + return nil + } + return n.Subject +} + +// GetUnread returns the Unread field if it's non-nil, zero value otherwise. +func (n *Notification) GetUnread() bool { + if n == nil || n.Unread == nil { + return false + } + return *n.Unread +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetUpdatedAt() Timestamp { + if n == nil || n.UpdatedAt == nil { + return Timestamp{} + } + return *n.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *Notification) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetLatestCommentURL() string { + if n == nil || n.LatestCommentURL == nil { + return "" + } + return *n.LatestCommentURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetType() string { + if n == nil || n.Type == nil { + return "" + } + return *n.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetClientID() string { + if o == nil || o.ClientID == nil { + return "" + } + return *o.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetUseDefault returns the UseDefault field if it's non-nil, zero value otherwise. +func (o *OIDCSubjectClaimCustomTemplate) GetUseDefault() bool { + if o == nil || o.UseDefault == nil { + return false + } + return *o.UseDefault +} + +// GetAdvancedSecurityEnabledForNewRepos returns the AdvancedSecurityEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetAdvancedSecurityEnabledForNewRepos() bool { + if o == nil || o.AdvancedSecurityEnabledForNewRepos == nil { + return false + } + return *o.AdvancedSecurityEnabledForNewRepos +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetAvatarURL() string { + if o == nil || o.AvatarURL == nil { + return "" + } + return *o.AvatarURL +} + +// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. +func (o *Organization) GetBillingEmail() string { + if o == nil || o.BillingEmail == nil { + return "" + } + return *o.BillingEmail +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (o *Organization) GetBlog() string { + if o == nil || o.Blog == nil { + return "" + } + return *o.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (o *Organization) GetCollaborators() int { + if o == nil || o.Collaborators == nil { + return 0 + } + return *o.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (o *Organization) GetCompany() string { + if o == nil || o.Company == nil { + return "" + } + return *o.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetCreatedAt() Timestamp { + if o == nil || o.CreatedAt == nil { + return Timestamp{} + } + return *o.CreatedAt +} + +// GetDefaultRepoPermission returns the DefaultRepoPermission field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoPermission() string { + if o == nil || o.DefaultRepoPermission == nil { + return "" + } + return *o.DefaultRepoPermission +} + +// GetDefaultRepoSettings returns the DefaultRepoSettings field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoSettings() string { + if o == nil || o.DefaultRepoSettings == nil { + return "" + } + return *o.DefaultRepoSettings +} + +// GetDependabotAlertsEnabledForNewRepos returns the DependabotAlertsEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotAlertsEnabledForNewRepos() bool { + if o == nil || o.DependabotAlertsEnabledForNewRepos == nil { + return false + } + return *o.DependabotAlertsEnabledForNewRepos +} + +// GetDependabotSecurityUpdatesEnabledForNewRepos returns the DependabotSecurityUpdatesEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotSecurityUpdatesEnabledForNewRepos() bool { + if o == nil || o.DependabotSecurityUpdatesEnabledForNewRepos == nil { + return false + } + return *o.DependabotSecurityUpdatesEnabledForNewRepos +} + +// GetDependencyGraphEnabledForNewRepos returns the DependencyGraphEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependencyGraphEnabledForNewRepos() bool { + if o == nil || o.DependencyGraphEnabledForNewRepos == nil { + return false + } + return *o.DependencyGraphEnabledForNewRepos +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (o *Organization) GetDescription() string { + if o == nil || o.Description == nil { + return "" + } + return *o.Description +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (o *Organization) GetDiskUsage() int { + if o == nil || o.DiskUsage == nil { + return 0 + } + return *o.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (o *Organization) GetEmail() string { + if o == nil || o.Email == nil { + return "" + } + return *o.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetEventsURL() string { + if o == nil || o.EventsURL == nil { + return "" + } + return *o.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowers() int { + if o == nil || o.Followers == nil { + return 0 + } + return *o.Followers +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowing() int { + if o == nil || o.Following == nil { + return 0 + } + return *o.Following +} + +// GetHasOrganizationProjects returns the HasOrganizationProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasOrganizationProjects() bool { + if o == nil || o.HasOrganizationProjects == nil { + return false + } + return *o.HasOrganizationProjects +} + +// GetHasRepositoryProjects returns the HasRepositoryProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasRepositoryProjects() bool { + if o == nil || o.HasRepositoryProjects == nil { + return false + } + return *o.HasRepositoryProjects +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHooksURL() string { + if o == nil || o.HooksURL == nil { + return "" + } + return *o.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHTMLURL() string { + if o == nil || o.HTMLURL == nil { + return "" + } + return *o.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *Organization) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetIssuesURL() string { + if o == nil || o.IssuesURL == nil { + return "" + } + return *o.IssuesURL +} + +// GetIsVerified returns the IsVerified field if it's non-nil, zero value otherwise. +func (o *Organization) GetIsVerified() bool { + if o == nil || o.IsVerified == nil { + return false + } + return *o.IsVerified +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (o *Organization) GetLocation() string { + if o == nil || o.Location == nil { + return "" + } + return *o.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (o *Organization) GetLogin() string { + if o == nil || o.Login == nil { + return "" + } + return *o.Login +} + +// GetMembersAllowedRepositoryCreationType returns the MembersAllowedRepositoryCreationType field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersAllowedRepositoryCreationType() string { + if o == nil || o.MembersAllowedRepositoryCreationType == nil { + return "" + } + return *o.MembersAllowedRepositoryCreationType +} + +// GetMembersCanCreateInternalRepos returns the MembersCanCreateInternalRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateInternalRepos() bool { + if o == nil || o.MembersCanCreateInternalRepos == nil { + return false + } + return *o.MembersCanCreateInternalRepos +} + +// GetMembersCanCreatePages returns the MembersCanCreatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePages() bool { + if o == nil || o.MembersCanCreatePages == nil { + return false + } + return *o.MembersCanCreatePages +} + +// GetMembersCanCreatePrivatePages returns the MembersCanCreatePrivatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivatePages() bool { + if o == nil || o.MembersCanCreatePrivatePages == nil { + return false + } + return *o.MembersCanCreatePrivatePages +} + +// GetMembersCanCreatePrivateRepos returns the MembersCanCreatePrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivateRepos() bool { + if o == nil || o.MembersCanCreatePrivateRepos == nil { + return false + } + return *o.MembersCanCreatePrivateRepos +} + +// GetMembersCanCreatePublicPages returns the MembersCanCreatePublicPages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicPages() bool { + if o == nil || o.MembersCanCreatePublicPages == nil { + return false + } + return *o.MembersCanCreatePublicPages +} + +// GetMembersCanCreatePublicRepos returns the MembersCanCreatePublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicRepos() bool { + if o == nil || o.MembersCanCreatePublicRepos == nil { + return false + } + return *o.MembersCanCreatePublicRepos +} + +// GetMembersCanCreateRepos returns the MembersCanCreateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateRepos() bool { + if o == nil || o.MembersCanCreateRepos == nil { + return false + } + return *o.MembersCanCreateRepos +} + +// GetMembersCanForkPrivateRepos returns the MembersCanForkPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanForkPrivateRepos() bool { + if o == nil || o.MembersCanForkPrivateRepos == nil { + return false + } + return *o.MembersCanForkPrivateRepos +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersURL() string { + if o == nil || o.MembersURL == nil { + return "" + } + return *o.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *Organization) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (o *Organization) GetNodeID() string { + if o == nil || o.NodeID == nil { + return "" + } + return *o.NodeID +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetOwnedPrivateRepos() int64 { + if o == nil || o.OwnedPrivateRepos == nil { + return 0 + } + return *o.OwnedPrivateRepos +} + +// GetPlan returns the Plan field. +func (o *Organization) GetPlan() *Plan { + if o == nil { + return nil + } + return o.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPrivateGists() int { + if o == nil || o.PrivateGists == nil { + return 0 + } + return *o.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicGists() int { + if o == nil || o.PublicGists == nil { + return 0 + } + return *o.PublicGists +} + +// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicMembersURL() string { + if o == nil || o.PublicMembersURL == nil { + return "" + } + return *o.PublicMembersURL +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicRepos() int { + if o == nil || o.PublicRepos == nil { + return 0 + } + return *o.PublicRepos +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetReposURL() string { + if o == nil || o.ReposURL == nil { + return "" + } + return *o.ReposURL +} + +// GetSecretScanningEnabledForNewRepos returns the SecretScanningEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningEnabledForNewRepos() bool { + if o == nil || o.SecretScanningEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningEnabledForNewRepos +} + +// GetSecretScanningPushProtectionEnabledForNewRepos returns the SecretScanningPushProtectionEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningPushProtectionEnabledForNewRepos() bool { + if o == nil || o.SecretScanningPushProtectionEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningPushProtectionEnabledForNewRepos +} + +// GetSecretScanningValidityChecksEnabled returns the SecretScanningValidityChecksEnabled field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningValidityChecksEnabled() bool { + if o == nil || o.SecretScanningValidityChecksEnabled == nil { + return false + } + return *o.SecretScanningValidityChecksEnabled +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetTotalPrivateRepos() int64 { + if o == nil || o.TotalPrivateRepos == nil { + return 0 + } + return *o.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwitterUsername() string { + if o == nil || o.TwitterUsername == nil { + return "" + } + return *o.TwitterUsername +} + +// GetTwoFactorRequirementEnabled returns the TwoFactorRequirementEnabled field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwoFactorRequirementEnabled() bool { + if o == nil || o.TwoFactorRequirementEnabled == nil { + return false + } + return *o.TwoFactorRequirementEnabled +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (o *Organization) GetType() string { + if o == nil || o.Type == nil { + return "" + } + return *o.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetUpdatedAt() Timestamp { + if o == nil || o.UpdatedAt == nil { + return Timestamp{} + } + return *o.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *Organization) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise. +func (o *Organization) GetWebCommitSignoffRequired() bool { + if o == nil || o.WebCommitSignoffRequired == nil { + return false + } + return *o.WebCommitSignoffRequired +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationCustomRepoRoles) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationCustomRoles) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrganizationEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetInstallation returns the Installation field. +func (o *OrganizationEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetInvitation returns the Invitation field. +func (o *OrganizationEvent) GetInvitation() *Invitation { + if o == nil { + return nil + } + return o.Invitation +} + +// GetMembership returns the Membership field. +func (o *OrganizationEvent) GetMembership() *Membership { + if o == nil { + return nil + } + return o.Membership +} + +// GetOrganization returns the Organization field. +func (o *OrganizationEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrganizationEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationInstallations) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrgBlockEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetBlockedUser returns the BlockedUser field. +func (o *OrgBlockEvent) GetBlockedUser() *User { + if o == nil { + return nil + } + return o.BlockedUser +} + +// GetInstallation returns the Installation field. +func (o *OrgBlockEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetOrganization returns the Organization field. +func (o *OrgBlockEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrgBlockEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetCreatedAt() Timestamp { + if o == nil || o.CreatedAt == nil { + return Timestamp{} + } + return *o.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetPath() string { + if o == nil || o.Path == nil { + return "" + } + return *o.Path +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetRef() string { + if o == nil || o.Ref == nil { + return "" + } + return *o.Ref +} + +// GetRepository returns the Repository field. +func (o *OrgRequiredWorkflow) GetRepository() *Repository { + if o == nil { + return nil + } + return o.Repository +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetScope() string { + if o == nil || o.Scope == nil { + return "" + } + return *o.Scope +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetSelectedRepositoriesURL() string { + if o == nil || o.SelectedRepositoriesURL == nil { + return "" + } + return *o.SelectedRepositoriesURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetState() string { + if o == nil || o.State == nil { + return "" + } + return *o.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflow) GetUpdatedAt() Timestamp { + if o == nil || o.UpdatedAt == nil { + return Timestamp{} + } + return *o.UpdatedAt +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrgRequiredWorkflows) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetDisabledOrgs() int { + if o == nil || o.DisabledOrgs == nil { + return 0 + } + return *o.DisabledOrgs +} + +// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalOrgs() int { + if o == nil || o.TotalOrgs == nil { + return 0 + } + return *o.TotalOrgs +} + +// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeamMembers() int { + if o == nil || o.TotalTeamMembers == nil { + return 0 + } + return *o.TotalTeamMembers +} + +// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeams() int { + if o == nil || o.TotalTeams == nil { + return 0 + } + return *o.TotalTeams +} + +// GetOrg returns the Org field. +func (o *OwnerInfo) GetOrg() *User { + if o == nil { + return nil + } + return o.Org +} + +// GetUser returns the User field. +func (o *OwnerInfo) GetUser() *User { + if o == nil { + return nil + } + return o.User +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Package) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *Package) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Package) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetOwner returns the Owner field. +func (p *Package) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *Package) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetPackageVersion returns the PackageVersion field. +func (p *Package) GetPackageVersion() *PackageVersion { + if p == nil { + return nil + } + return p.PackageVersion +} + +// GetRegistry returns the Registry field. +func (p *Package) GetRegistry() *PackageRegistry { + if p == nil { + return nil + } + return p.Registry +} + +// GetRepository returns the Repository field. +func (p *Package) GetRepository() *Repository { + if p == nil { + return nil + } + return p.Repository +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Package) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersionCount returns the VersionCount field if it's non-nil, zero value otherwise. +func (p *Package) GetVersionCount() int64 { + if p == nil || p.VersionCount == nil { + return 0 + } + return *p.VersionCount +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *Package) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PackageEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PackageEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PackageEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPackage returns the Package field. +func (p *PackageEvent) GetPackage() *Package { + if p == nil { + return nil + } + return p.Package +} + +// GetRepo returns the Repo field. +func (p *PackageEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PackageEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAuthor returns the Author field. +func (p *PackageFile) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetDownloadURL() string { + if p == nil || p.DownloadURL == nil { + return "" + } + return *p.DownloadURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetMD5 returns the MD5 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetMD5() string { + if p == nil || p.MD5 == nil { + return "" + } + return *p.MD5 +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetSHA1 returns the SHA1 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA1() string { + if p == nil || p.SHA1 == nil { + return "" + } + return *p.SHA1 +} + +// GetSHA256 returns the SHA256 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA256() string { + if p == nil || p.SHA256 == nil { + return "" + } + return *p.SHA256 +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSize() int64 { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetContainer returns the Container field. +func (p *PackageMetadata) GetContainer() *PackageContainerMetadata { + if p == nil { + return nil + } + return p.Container +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageMetadata) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetAboutURL returns the AboutURL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetAboutURL() string { + if p == nil || p.AboutURL == nil { + return "" + } + return *p.AboutURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVendor returns the Vendor field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetVendor() string { + if p == nil || p.Vendor == nil { + return "" + } + return *p.Vendor +} + +// GetAuthor returns the Author field. +func (p *PackageRelease) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPublishedAt() Timestamp { + if p == nil || p.PublishedAt == nil { + return Timestamp{} + } + return *p.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthor returns the Author field. +func (p *PackageVersion) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBodyHTML() string { + if p == nil || p.BodyHTML == nil { + return "" + } + return *p.BodyHTML +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallationCommand returns the InstallationCommand field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetInstallationCommand() string { + if p == nil || p.InstallationCommand == nil { + return "" + } + return *p.InstallationCommand +} + +// GetManifest returns the Manifest field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetManifest() string { + if p == nil || p.Manifest == nil { + return "" + } + return *p.Manifest +} + +// GetMetadata returns the Metadata field. +func (p *PackageVersion) GetMetadata() *PackageMetadata { + if p == nil { + return nil + } + return p.Metadata +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPackageHTMLURL returns the PackageHTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPackageHTMLURL() string { + if p == nil || p.PackageHTMLURL == nil { + return "" + } + return *p.PackageHTMLURL +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetRelease returns the Release field. +func (p *PackageVersion) GetRelease() *PackageRelease { + if p == nil { + return nil + } + return p.Release +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetTargetOID returns the TargetOID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetOID() string { + if p == nil || p.TargetOID == nil { + return "" + } + return *p.TargetOID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetVersion() string { + if p == nil || p.Version == nil { + return "" + } + return *p.Version +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *Page) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Page) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPageName returns the PageName field if it's non-nil, zero value otherwise. +func (p *Page) GetPageName() string { + if p == nil || p.PageName == nil { + return "" + } + return *p.PageName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *Page) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *Page) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *Page) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetBuild returns the Build field. +func (p *PageBuildEvent) GetBuild() *PagesBuild { + if p == nil { + return nil + } + return p.Build +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PageBuildEvent) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallation returns the Installation field. +func (p *PageBuildEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PageBuildEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PageBuildEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PageBuildEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBuildType returns the BuildType field if it's non-nil, zero value otherwise. +func (p *Pages) GetBuildType() string { + if p == nil || p.BuildType == nil { + return "" + } + return *p.BuildType +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *Pages) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. +func (p *Pages) GetCustom404() bool { + if p == nil || p.Custom404 == nil { + return false + } + return *p.Custom404 +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetHTTPSCertificate returns the HTTPSCertificate field. +func (p *Pages) GetHTTPSCertificate() *PagesHTTPSCertificate { + if p == nil { + return nil + } + return p.HTTPSCertificate +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *Pages) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *Pages) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *Pages) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Pages) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCommit returns the Commit field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCommit() string { + if p == nil || p.Commit == nil { + return "" + } + return *p.Commit +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDuration returns the Duration field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetDuration() int { + if p == nil || p.Duration == nil { + return 0 + } + return *p.Duration +} + +// GetError returns the Error field. +func (p *PagesBuild) GetError() *PagesError { + if p == nil { + return nil + } + return p.Error +} + +// GetPusher returns the Pusher field. +func (p *PagesBuild) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCAAError returns the CAAError field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetCAAError() string { + if p == nil || p.CAAError == nil { + return "" + } + return *p.CAAError +} + +// GetDNSResolves returns the DNSResolves field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetDNSResolves() bool { + if p == nil || p.DNSResolves == nil { + return false + } + return *p.DNSResolves +} + +// GetEnforcesHTTPS returns the EnforcesHTTPS field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetEnforcesHTTPS() bool { + if p == nil || p.EnforcesHTTPS == nil { + return false + } + return *p.EnforcesHTTPS +} + +// GetHasCNAMERecord returns the HasCNAMERecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHasCNAMERecord() bool { + if p == nil || p.HasCNAMERecord == nil { + return false + } + return *p.HasCNAMERecord +} + +// GetHasMXRecordsPresent returns the HasMXRecordsPresent field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHasMXRecordsPresent() bool { + if p == nil || p.HasMXRecordsPresent == nil { + return false + } + return *p.HasMXRecordsPresent +} + +// GetHost returns the Host field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHost() string { + if p == nil || p.Host == nil { + return "" + } + return *p.Host +} + +// GetHTTPSError returns the HTTPSError field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetHTTPSError() string { + if p == nil || p.HTTPSError == nil { + return "" + } + return *p.HTTPSError +} + +// GetIsApexDomain returns the IsApexDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsApexDomain() bool { + if p == nil || p.IsApexDomain == nil { + return false + } + return *p.IsApexDomain +} + +// GetIsARecord returns the IsARecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsARecord() bool { + if p == nil || p.IsARecord == nil { + return false + } + return *p.IsARecord +} + +// GetIsCloudflareIP returns the IsCloudflareIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCloudflareIP() bool { + if p == nil || p.IsCloudflareIP == nil { + return false + } + return *p.IsCloudflareIP +} + +// GetIsCNAMEToFastly returns the IsCNAMEToFastly field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToFastly() bool { + if p == nil || p.IsCNAMEToFastly == nil { + return false + } + return *p.IsCNAMEToFastly +} + +// GetIsCNAMEToGithubUserDomain returns the IsCNAMEToGithubUserDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToGithubUserDomain() bool { + if p == nil || p.IsCNAMEToGithubUserDomain == nil { + return false + } + return *p.IsCNAMEToGithubUserDomain +} + +// GetIsCNAMEToPagesDotGithubDotCom returns the IsCNAMEToPagesDotGithubDotCom field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsCNAMEToPagesDotGithubDotCom() bool { + if p == nil || p.IsCNAMEToPagesDotGithubDotCom == nil { + return false + } + return *p.IsCNAMEToPagesDotGithubDotCom +} + +// GetIsFastlyIP returns the IsFastlyIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsFastlyIP() bool { + if p == nil || p.IsFastlyIP == nil { + return false + } + return *p.IsFastlyIP +} + +// GetIsHTTPSEligible returns the IsHTTPSEligible field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsHTTPSEligible() bool { + if p == nil || p.IsHTTPSEligible == nil { + return false + } + return *p.IsHTTPSEligible +} + +// GetIsNonGithubPagesIPPresent returns the IsNonGithubPagesIPPresent field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsNonGithubPagesIPPresent() bool { + if p == nil || p.IsNonGithubPagesIPPresent == nil { + return false + } + return *p.IsNonGithubPagesIPPresent +} + +// GetIsOldIPAddress returns the IsOldIPAddress field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsOldIPAddress() bool { + if p == nil || p.IsOldIPAddress == nil { + return false + } + return *p.IsOldIPAddress +} + +// GetIsPagesDomain returns the IsPagesDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsPagesDomain() bool { + if p == nil || p.IsPagesDomain == nil { + return false + } + return *p.IsPagesDomain +} + +// GetIsPointedToGithubPagesIP returns the IsPointedToGithubPagesIP field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsPointedToGithubPagesIP() bool { + if p == nil || p.IsPointedToGithubPagesIP == nil { + return false + } + return *p.IsPointedToGithubPagesIP +} + +// GetIsProxied returns the IsProxied field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsProxied() bool { + if p == nil || p.IsProxied == nil { + return false + } + return *p.IsProxied +} + +// GetIsServedByPages returns the IsServedByPages field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsServedByPages() bool { + if p == nil || p.IsServedByPages == nil { + return false + } + return *p.IsServedByPages +} + +// GetIsValid returns the IsValid field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsValid() bool { + if p == nil || p.IsValid == nil { + return false + } + return *p.IsValid +} + +// GetIsValidDomain returns the IsValidDomain field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetIsValidDomain() bool { + if p == nil || p.IsValidDomain == nil { + return false + } + return *p.IsValidDomain +} + +// GetNameservers returns the Nameservers field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetNameservers() string { + if p == nil || p.Nameservers == nil { + return "" + } + return *p.Nameservers +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetReason() string { + if p == nil || p.Reason == nil { + return "" + } + return *p.Reason +} + +// GetRespondsToHTTPS returns the RespondsToHTTPS field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetRespondsToHTTPS() bool { + if p == nil || p.RespondsToHTTPS == nil { + return false + } + return *p.RespondsToHTTPS +} + +// GetShouldBeARecord returns the ShouldBeARecord field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetShouldBeARecord() bool { + if p == nil || p.ShouldBeARecord == nil { + return false + } + return *p.ShouldBeARecord +} + +// GetURI returns the URI field if it's non-nil, zero value otherwise. +func (p *PagesDomain) GetURI() string { + if p == nil || p.URI == nil { + return "" + } + return *p.URI +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PagesError) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAltDomain returns the AltDomain field. +func (p *PagesHealthCheckResponse) GetAltDomain() *PagesDomain { + if p == nil { + return nil + } + return p.AltDomain +} + +// GetDomain returns the Domain field. +func (p *PagesHealthCheckResponse) GetDomain() *PagesDomain { + if p == nil { + return nil + } + return p.Domain +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetExpiresAt() string { + if p == nil || p.ExpiresAt == nil { + return "" + } + return *p.ExpiresAt +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetBranch() string { + if p == nil || p.Branch == nil { + return "" + } + return *p.Branch +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. +func (p *PageStats) GetTotalPages() int { + if p == nil || p.TotalPages == nil { + return 0 + } + return *p.TotalPages +} + +// GetBuildType returns the BuildType field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetBuildType() string { + if p == nil || p.BuildType == nil { + return "" + } + return *p.BuildType +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *PagesUpdate) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetCurrentUserCanApprove returns the CurrentUserCanApprove field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetCurrentUserCanApprove() bool { + if p == nil || p.CurrentUserCanApprove == nil { + return false + } + return *p.CurrentUserCanApprove +} + +// GetEnvironment returns the Environment field. +func (p *PendingDeployment) GetEnvironment() *PendingDeploymentEnvironment { + if p == nil { + return nil + } + return p.Environment +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetWaitTimer() int64 { + if p == nil || p.WaitTimer == nil { + return 0 + } + return *p.WaitTimer +} + +// GetWaitTimerStartedAt returns the WaitTimerStartedAt field if it's non-nil, zero value otherwise. +func (p *PendingDeployment) GetWaitTimerStartedAt() Timestamp { + if p == nil || p.WaitTimerStartedAt == nil { + return Timestamp{} + } + return *p.WaitTimerStartedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PendingDeploymentEnvironment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAccessGrantedAt returns the AccessGrantedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetAccessGrantedAt() Timestamp { + if p == nil || p.AccessGrantedAt == nil { + return Timestamp{} + } + return *p.AccessGrantedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetOwner returns the Owner field. +func (p *PersonalAccessToken) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPermissions returns the Permissions field. +func (p *PersonalAccessToken) GetPermissions() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetRepositoriesURL() string { + if p == nil || p.RepositoriesURL == nil { + return "" + } + return *p.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetRepositorySelection() string { + if p == nil || p.RepositorySelection == nil { + return "" + } + return *p.RepositorySelection +} + +// GetTokenExpired returns the TokenExpired field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenExpired() bool { + if p == nil || p.TokenExpired == nil { + return false + } + return *p.TokenExpired +} + +// GetTokenExpiresAt returns the TokenExpiresAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenExpiresAt() Timestamp { + if p == nil || p.TokenExpiresAt == nil { + return Timestamp{} + } + return *p.TokenExpiresAt +} + +// GetTokenLastUsedAt returns the TokenLastUsedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenLastUsedAt() Timestamp { + if p == nil || p.TokenLastUsedAt == nil { + return Timestamp{} + } + return *p.TokenLastUsedAt +} + +// GetOrg returns the Org map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetOrg() map[string]string { + if p == nil || p.Org == nil { + return map[string]string{} + } + return p.Org +} + +// GetOther returns the Other map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetOther() map[string]string { + if p == nil || p.Other == nil { + return map[string]string{} + } + return p.Other +} + +// GetRepo returns the Repo map if it's non-nil, an empty map otherwise. +func (p *PersonalAccessTokenPermissions) GetRepo() map[string]string { + if p == nil || p.Repo == nil { + return map[string]string{} + } + return p.Repo +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetOrg returns the Org field. +func (p *PersonalAccessTokenRequest) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetOwner returns the Owner field. +func (p *PersonalAccessTokenRequest) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPermissionsAdded returns the PermissionsAdded field. +func (p *PersonalAccessTokenRequest) GetPermissionsAdded() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsAdded +} + +// GetPermissionsResult returns the PermissionsResult field. +func (p *PersonalAccessTokenRequest) GetPermissionsResult() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsResult +} + +// GetPermissionsUpgraded returns the PermissionsUpgraded field. +func (p *PersonalAccessTokenRequest) GetPermissionsUpgraded() *PersonalAccessTokenPermissions { + if p == nil { + return nil + } + return p.PermissionsUpgraded +} + +// GetRepositoryCount returns the RepositoryCount field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetRepositoryCount() int64 { + if p == nil || p.RepositoryCount == nil { + return 0 + } + return *p.RepositoryCount +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetRepositorySelection() string { + if p == nil || p.RepositorySelection == nil { + return "" + } + return *p.RepositorySelection +} + +// GetTokenExpired returns the TokenExpired field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenExpired() bool { + if p == nil || p.TokenExpired == nil { + return false + } + return *p.TokenExpired +} + +// GetTokenExpiresAt returns the TokenExpiresAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenExpiresAt() Timestamp { + if p == nil || p.TokenExpiresAt == nil { + return Timestamp{} + } + return *p.TokenExpiresAt +} + +// GetTokenLastUsedAt returns the TokenLastUsedAt field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequest) GetTokenLastUsedAt() Timestamp { + if p == nil || p.TokenLastUsedAt == nil { + return Timestamp{} + } + return *p.TokenLastUsedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PersonalAccessTokenRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PersonalAccessTokenRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PersonalAccessTokenRequestEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPersonalAccessTokenRequest returns the PersonalAccessTokenRequest field. +func (p *PersonalAccessTokenRequestEvent) GetPersonalAccessTokenRequest() *PersonalAccessTokenRequest { + if p == nil { + return nil + } + return p.PersonalAccessTokenRequest +} + +// GetSender returns the Sender field. +func (p *PersonalAccessTokenRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetHook returns the Hook field. +func (p *PingEvent) GetHook() *Hook { + if p == nil { + return nil + } + return p.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetHookID() int64 { + if p == nil || p.HookID == nil { + return 0 + } + return *p.HookID +} + +// GetInstallation returns the Installation field. +func (p *PingEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PingEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PingEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PingEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetZen returns the Zen field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetZen() string { + if p == nil || p.Zen == nil { + return "" + } + return *p.Zen +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (p *Plan) GetCollaborators() int { + if p == nil || p.Collaborators == nil { + return 0 + } + return *p.Collaborators +} + +// GetFilledSeats returns the FilledSeats field if it's non-nil, zero value otherwise. +func (p *Plan) GetFilledSeats() int { + if p == nil || p.FilledSeats == nil { + return 0 + } + return *p.FilledSeats +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Plan) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. +func (p *Plan) GetPrivateRepos() int64 { + if p == nil || p.PrivateRepos == nil { + return 0 + } + return *p.PrivateRepos +} + +// GetSeats returns the Seats field if it's non-nil, zero value otherwise. +func (p *Plan) GetSeats() int { + if p == nil || p.Seats == nil { + return 0 + } + return *p.Seats +} + +// GetSpace returns the Space field if it's non-nil, zero value otherwise. +func (p *Plan) GetSpace() int { + if p == nil || p.Space == nil { + return 0 + } + return *p.Space +} + +// GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetConfigURL() string { + if p == nil || p.ConfigURL == nil { + return "" + } + return *p.ConfigURL +} + +// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetEnforcement() string { + if p == nil || p.Enforcement == nil { + return "" + } + return *p.Enforcement +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (p *PRLink) GetHRef() string { + if p == nil || p.HRef == nil { + return "" + } + return *p.HRef +} + +// GetComments returns the Comments field. +func (p *PRLinks) GetComments() *PRLink { + if p == nil { + return nil + } + return p.Comments +} + +// GetCommits returns the Commits field. +func (p *PRLinks) GetCommits() *PRLink { + if p == nil { + return nil + } + return p.Commits +} + +// GetHTML returns the HTML field. +func (p *PRLinks) GetHTML() *PRLink { + if p == nil { + return nil + } + return p.HTML +} + +// GetIssue returns the Issue field. +func (p *PRLinks) GetIssue() *PRLink { + if p == nil { + return nil + } + return p.Issue +} + +// GetReviewComment returns the ReviewComment field. +func (p *PRLinks) GetReviewComment() *PRLink { + if p == nil { + return nil + } + return p.ReviewComment +} + +// GetReviewComments returns the ReviewComments field. +func (p *PRLinks) GetReviewComments() *PRLink { + if p == nil { + return nil + } + return p.ReviewComments +} + +// GetSelf returns the Self field. +func (p *PRLinks) GetSelf() *PRLink { + if p == nil { + return nil + } + return p.Self +} + +// GetStatuses returns the Statuses field. +func (p *PRLinks) GetStatuses() *PRLink { + if p == nil { + return nil + } + return p.Statuses +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectBody) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetNote returns the Note field. +func (p *ProjectCardChange) GetNote() *ProjectCardNote { + if p == nil { + return nil + } + return p.Note +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectCardNote) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBody returns the Body field. +func (p *ProjectChange) GetBody() *ProjectBody { + if p == nil { + return nil + } + return p.Body +} + +// GetName returns the Name field. +func (p *ProjectChange) GetName() *ProjectName { + if p == nil { + return nil + } + return p.Name +} + +// GetName returns the Name field. +func (p *ProjectColumnChange) GetName() *ProjectColumnName { + if p == nil { + return nil + } + return p.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectColumnName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetClosedAt() Timestamp { + if p == nil || p.ClosedAt == nil { + return Timestamp{} + } + return *p.ClosedAt +} + +// GetColumnsURL returns the ColumnsURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetColumnsURL() string { + if p == nil || p.ColumnsURL == nil { + return "" + } + return *p.ColumnsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectV2) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetDeletedAt returns the DeletedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetDeletedAt() Timestamp { + if p == nil || p.DeletedAt == nil { + return Timestamp{} + } + return *p.DeletedAt +} + +// GetDeletedBy returns the DeletedBy field. +func (p *ProjectV2) GetDeletedBy() *User { + if p == nil { + return nil + } + return p.DeletedBy +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetOrganizationPermission() string { + if p == nil || p.OrganizationPermission == nil { + return "" + } + return *p.OrganizationPermission +} + +// GetOwner returns the Owner field. +func (p *ProjectV2) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetOwnerURL() string { + if p == nil || p.OwnerURL == nil { + return "" + } + return *p.OwnerURL +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetShortDescription() string { + if p == nil || p.ShortDescription == nil { + return "" + } + return *p.ShortDescription +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectV2) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectV2Event) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *ProjectV2Event) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectV2Event) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectsV2 returns the ProjectsV2 field. +func (p *ProjectV2Event) GetProjectsV2() *ProjectV2 { + if p == nil { + return nil + } + return p.ProjectsV2 +} + +// GetSender returns the Sender field. +func (p *ProjectV2Event) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetArchivedAt returns the ArchivedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetArchivedAt() Timestamp { + if p == nil || p.ArchivedAt == nil { + return Timestamp{} + } + return *p.ArchivedAt +} + +// GetContentNodeID returns the ContentNodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetContentNodeID() string { + if p == nil || p.ContentNodeID == nil { + return "" + } + return *p.ContentNodeID +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectV2Item) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetProjectNodeID returns the ProjectNodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetProjectNodeID() string { + if p == nil || p.ProjectNodeID == nil { + return "" + } + return *p.ProjectNodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectV2Item) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetArchivedAt returns the ArchivedAt field. +func (p *ProjectV2ItemChange) GetArchivedAt() *ArchivedAt { + if p == nil { + return nil + } + return p.ArchivedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectV2ItemEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *ProjectV2ItemEvent) GetChanges() *ProjectV2ItemChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectV2ItemEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectV2ItemEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectV2Item returns the ProjectV2Item field. +func (p *ProjectV2ItemEvent) GetProjectV2Item() *ProjectV2Item { + if p == nil { + return nil + } + return p.ProjectV2Item +} + +// GetSender returns the Sender field. +func (p *ProjectV2ItemEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAllowDeletions returns the AllowDeletions field. +func (p *Protection) GetAllowDeletions() *AllowDeletions { + if p == nil { + return nil + } + return p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field. +func (p *Protection) GetAllowForcePushes() *AllowForcePushes { + if p == nil { + return nil + } + return p.AllowForcePushes +} + +// GetAllowForkSyncing returns the AllowForkSyncing field. +func (p *Protection) GetAllowForkSyncing() *AllowForkSyncing { + if p == nil { + return nil + } + return p.AllowForkSyncing +} + +// GetBlockCreations returns the BlockCreations field. +func (p *Protection) GetBlockCreations() *BlockCreations { + if p == nil { + return nil + } + return p.BlockCreations +} + +// GetEnforceAdmins returns the EnforceAdmins field. +func (p *Protection) GetEnforceAdmins() *AdminEnforcement { + if p == nil { + return nil + } + return p.EnforceAdmins +} + +// GetLockBranch returns the LockBranch field. +func (p *Protection) GetLockBranch() *LockBranch { + if p == nil { + return nil + } + return p.LockBranch +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field. +func (p *Protection) GetRequiredConversationResolution() *RequiredConversationResolution { + if p == nil { + return nil + } + return p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredSignatures returns the RequiredSignatures field. +func (p *Protection) GetRequiredSignatures() *SignaturesProtectedBranch { + if p == nil { + return nil + } + return p.RequiredSignatures +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field. +func (p *Protection) GetRequireLinearHistory() *RequireLinearHistory { + if p == nil { + return nil + } + return p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *Protection) GetRestrictions() *BranchRestrictions { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Protection) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAdminEnforced returns the AdminEnforced field. +func (p *ProtectionChanges) GetAdminEnforced() *AdminEnforcedChanges { + if p == nil { + return nil + } + return p.AdminEnforced +} + +// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field. +func (p *ProtectionChanges) GetAllowDeletionsEnforcementLevel() *AllowDeletionsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.AllowDeletionsEnforcementLevel +} + +// GetAuthorizedActorNames returns the AuthorizedActorNames field. +func (p *ProtectionChanges) GetAuthorizedActorNames() *AuthorizedActorNames { + if p == nil { + return nil + } + return p.AuthorizedActorNames +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field. +func (p *ProtectionChanges) GetAuthorizedActorsOnly() *AuthorizedActorsOnly { + if p == nil { + return nil + } + return p.AuthorizedActorsOnly +} + +// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field. +func (p *ProtectionChanges) GetAuthorizedDismissalActorsOnly() *AuthorizedDismissalActorsOnlyChanges { + if p == nil { + return nil + } + return p.AuthorizedDismissalActorsOnly +} + +// GetCreateProtected returns the CreateProtected field. +func (p *ProtectionChanges) GetCreateProtected() *CreateProtectedChanges { + if p == nil { + return nil + } + return p.CreateProtected +} + +// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field. +func (p *ProtectionChanges) GetDismissStaleReviewsOnPush() *DismissStaleReviewsOnPushChanges { + if p == nil { + return nil + } + return p.DismissStaleReviewsOnPush +} + +// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field. +func (p *ProtectionChanges) GetLinearHistoryRequirementEnforcementLevel() *LinearHistoryRequirementEnforcementLevelChanges { + if p == nil { + return nil + } + return p.LinearHistoryRequirementEnforcementLevel +} + +// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field. +func (p *ProtectionChanges) GetPullRequestReviewsEnforcementLevel() *PullRequestReviewsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.PullRequestReviewsEnforcementLevel +} + +// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field. +func (p *ProtectionChanges) GetRequireCodeOwnerReview() *RequireCodeOwnerReviewChanges { + if p == nil { + return nil + } + return p.RequireCodeOwnerReview +} + +// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field. +func (p *ProtectionChanges) GetRequiredConversationResolutionLevel() *RequiredConversationResolutionLevelChanges { + if p == nil { + return nil + } + return p.RequiredConversationResolutionLevel +} + +// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field. +func (p *ProtectionChanges) GetRequiredDeploymentsEnforcementLevel() *RequiredDeploymentsEnforcementLevelChanges { + if p == nil { + return nil + } + return p.RequiredDeploymentsEnforcementLevel +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionChanges) GetRequiredStatusChecks() *RequiredStatusChecksChanges { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field. +func (p *ProtectionChanges) GetRequiredStatusChecksEnforcementLevel() *RequiredStatusChecksEnforcementLevelChanges { + if p == nil { + return nil + } + return p.RequiredStatusChecksEnforcementLevel +} + +// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field. +func (p *ProtectionChanges) GetSignatureRequirementEnforcementLevel() *SignatureRequirementEnforcementLevelChanges { + if p == nil { + return nil + } + return p.SignatureRequirementEnforcementLevel +} + +// GetAllowDeletions returns the AllowDeletions field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowDeletions() bool { + if p == nil || p.AllowDeletions == nil { + return false + } + return *p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowForcePushes() bool { + if p == nil || p.AllowForcePushes == nil { + return false + } + return *p.AllowForcePushes +} + +// GetAllowForkSyncing returns the AllowForkSyncing field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowForkSyncing() bool { + if p == nil || p.AllowForkSyncing == nil { + return false + } + return *p.AllowForkSyncing +} + +// GetBlockCreations returns the BlockCreations field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetBlockCreations() bool { + if p == nil || p.BlockCreations == nil { + return false + } + return *p.BlockCreations +} + +// GetLockBranch returns the LockBranch field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetLockBranch() bool { + if p == nil || p.LockBranch == nil { + return false + } + return *p.LockBranch +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequiredConversationResolution() bool { + if p == nil || p.RequiredConversationResolution == nil { + return false + } + return *p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequireLinearHistory() bool { + if p == nil || p.RequireLinearHistory == nil { + return false + } + return *p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetPreventSelfReview returns the PreventSelfReview field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetPreventSelfReview() bool { + if p == nil || p.PreventSelfReview == nil { + return false + } + return *p.PreventSelfReview +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetWaitTimer() int { + if p == nil || p.WaitTimer == nil { + return 0 + } + return *p.WaitTimer +} + +// GetInstallation returns the Installation field. +func (p *PublicEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PublicEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetRepo returns the Repo field. +func (p *PublicEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PublicEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKey() string { + if p == nil || p.Key == nil { + return "" + } + return *p.Key +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKeyID() string { + if p == nil || p.KeyID == nil { + return "" + } + return *p.KeyID +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetActiveLockReason() string { + if p == nil || p.ActiveLockReason == nil { + return "" + } + return *p.ActiveLockReason +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAdditions() int { + if p == nil || p.Additions == nil { + return 0 + } + return *p.Additions +} + +// GetAssignee returns the Assignee field. +func (p *PullRequest) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetAutoMerge returns the AutoMerge field. +func (p *PullRequest) GetAutoMerge() *PullRequestAutoMerge { + if p == nil { + return nil + } + return p.AutoMerge +} + +// GetBase returns the Base field. +func (p *PullRequest) GetBase() *PullRequestBranch { + if p == nil { + return nil + } + return p.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetChangedFiles() int { + if p == nil || p.ChangedFiles == nil { + return 0 + } + return *p.ChangedFiles +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetClosedAt() Timestamp { + if p == nil || p.ClosedAt == nil { + return Timestamp{} + } + return *p.ClosedAt +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetComments() int { + if p == nil || p.Comments == nil { + return 0 + } + return *p.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommentsURL() string { + if p == nil || p.CommentsURL == nil { + return "" + } + return *p.CommentsURL +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommitsURL() string { + if p == nil || p.CommitsURL == nil { + return "" + } + return *p.CommitsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDeletions() int { + if p == nil || p.Deletions == nil { + return 0 + } + return *p.Deletions +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHead returns the Head field. +func (p *PullRequest) GetHead() *PullRequestBranch { + if p == nil { + return nil + } + return p.Head +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetIssueURL() string { + if p == nil || p.IssueURL == nil { + return "" + } + return *p.IssueURL +} + +// GetLinks returns the Links field. +func (p *PullRequest) GetLinks() *PRLinks { + if p == nil { + return nil + } + return p.Links +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetLocked() bool { + if p == nil || p.Locked == nil { + return false + } + return *p.Locked +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMaintainerCanModify() bool { + if p == nil || p.MaintainerCanModify == nil { + return false + } + return *p.MaintainerCanModify +} + +// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeable() bool { + if p == nil || p.Mergeable == nil { + return false + } + return *p.Mergeable +} + +// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeableState() string { + if p == nil || p.MergeableState == nil { + return "" + } + return *p.MergeableState +} + +// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeCommitSHA() string { + if p == nil || p.MergeCommitSHA == nil { + return "" + } + return *p.MergeCommitSHA +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergedAt() Timestamp { + if p == nil || p.MergedAt == nil { + return Timestamp{} + } + return *p.MergedAt +} + +// GetMergedBy returns the MergedBy field. +func (p *PullRequest) GetMergedBy() *User { + if p == nil { + return nil + } + return p.MergedBy +} + +// GetMilestone returns the Milestone field. +func (p *PullRequest) GetMilestone() *Milestone { + if p == nil { + return nil + } + return p.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetRebaseable returns the Rebaseable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetRebaseable() bool { + if p == nil || p.Rebaseable == nil { + return false + } + return *p.Rebaseable +} + +// GetReviewComments returns the ReviewComments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewComments() int { + if p == nil || p.ReviewComments == nil { + return 0 + } + return *p.ReviewComments +} + +// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentsURL() string { + if p == nil || p.ReviewCommentsURL == nil { + return "" + } + return *p.ReviewCommentsURL +} + +// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentURL() string { + if p == nil || p.ReviewCommentURL == nil { + return "" + } + return *p.ReviewCommentURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequest) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitMessage() string { + if p == nil || p.CommitMessage == nil { + return "" + } + return *p.CommitMessage +} + +// GetCommitTitle returns the CommitTitle field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitTitle() string { + if p == nil || p.CommitTitle == nil { + return "" + } + return *p.CommitTitle +} + +// GetEnabledBy returns the EnabledBy field. +func (p *PullRequestAutoMerge) GetEnabledBy() *User { + if p == nil { + return nil + } + return p.EnabledBy +} + +// GetMergeMethod returns the MergeMethod field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetMergeMethod() string { + if p == nil || p.MergeMethod == nil { + return "" + } + return *p.MergeMethod +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetLabel() string { + if p == nil || p.Label == nil { + return "" + } + return *p.Label +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PullRequestBranch) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetUser returns the User field. +func (p *PullRequestBranch) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetExpectedHeadSHA returns the ExpectedHeadSHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateOptions) GetExpectedHeadSHA() string { + if p == nil || p.ExpectedHeadSHA == nil { + return "" + } + return *p.ExpectedHeadSHA +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetDiffHunk() string { + if p == nil || p.DiffHunk == nil { + return "" + } + return *p.DiffHunk +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetInReplyTo() int64 { + if p == nil || p.InReplyTo == nil { + return 0 + } + return *p.InReplyTo +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetLine() int { + if p == nil || p.Line == nil { + return 0 + } + return *p.Line +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalCommitID() string { + if p == nil || p.OriginalCommitID == nil { + return "" + } + return *p.OriginalCommitID +} + +// GetOriginalLine returns the OriginalLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalLine() int { + if p == nil || p.OriginalLine == nil { + return 0 + } + return *p.OriginalLine +} + +// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalPosition() int { + if p == nil || p.OriginalPosition == nil { + return 0 + } + return *p.OriginalPosition +} + +// GetOriginalStartLine returns the OriginalStartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalStartLine() int { + if p == nil || p.OriginalStartLine == nil { + return 0 + } + return *p.OriginalStartLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPosition() int { + if p == nil || p.Position == nil { + return 0 + } + return *p.Position +} + +// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestReviewID() int64 { + if p == nil || p.PullRequestReviewID == nil { + return 0 + } + return *p.PullRequestReviewID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetReactions returns the Reactions field. +func (p *PullRequestComment) GetReactions() *Reactions { + if p == nil { + return nil + } + return p.Reactions +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetSide() string { + if p == nil || p.Side == nil { + return "" + } + return *p.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartLine() int { + if p == nil || p.StartLine == nil { + return 0 + } + return *p.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartSide() string { + if p == nil || p.StartSide == nil { + return "" + } + return *p.StartSide +} + +// GetSubjectType returns the SubjectType field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetSubjectType() string { + if p == nil || p.SubjectType == nil { + return "" + } + return *p.SubjectType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequestComment) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (p *PullRequestEvent) GetPerformedViaGithubApp() *App { + if p == nil { + return nil + } + return p.PerformedViaGithubApp +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetMergedAt() Timestamp { + if p == nil || p.MergedAt == nil { + return Timestamp{} + } + return *p.MergedAt +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetSubmittedAt() Timestamp { + if p == nil || p.SubmittedAt == nil { + return Timestamp{} + } + return *p.SubmittedAt +} + +// GetUser returns the User field. +func (p *PullRequestReview) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewCommentEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetComment returns the Comment field. +func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { + if p == nil { + return nil + } + return p.Comment +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PullRequestReviewCommentEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewCommentEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewDismissalRequest) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PullRequestReviewEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetReview returns the Review field. +func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { + if p == nil { + return nil + } + return p.Review +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetEvent() string { + if p == nil || p.Event == nil { + return "" + } + return *p.Event +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetBypassPullRequestAllowances returns the BypassPullRequestAllowances field. +func (p *PullRequestReviewsEnforcement) GetBypassPullRequestAllowances() *BypassPullRequestAllowances { + if p == nil { + return nil + } + return p.BypassPullRequestAllowances +} + +// GetDismissalRestrictions returns the DismissalRestrictions field. +func (p *PullRequestReviewsEnforcement) GetDismissalRestrictions() *DismissalRestrictions { + if p == nil { + return nil + } + return p.DismissalRestrictions +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementLevelChanges) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBypassPullRequestAllowancesRequest returns the BypassPullRequestAllowancesRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetBypassPullRequestAllowancesRequest() *BypassPullRequestAllowancesRequest { + if p == nil { + return nil + } + return p.BypassPullRequestAllowancesRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetRequireLastPushApproval returns the RequireLastPushApproval field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementRequest) GetRequireLastPushApproval() bool { + if p == nil || p.RequireLastPushApproval == nil { + return false + } + return *p.RequireLastPushApproval +} + +// GetBypassPullRequestAllowancesRequest returns the BypassPullRequestAllowancesRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetBypassPullRequestAllowancesRequest() *BypassPullRequestAllowancesRequest { + if p == nil { + return nil + } + return p.BypassPullRequestAllowancesRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { + if p == nil || p.DismissStaleReviews == nil { + return false + } + return *p.DismissStaleReviews +} + +// GetRequireCodeOwnerReviews returns the RequireCodeOwnerReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetRequireCodeOwnerReviews() bool { + if p == nil || p.RequireCodeOwnerReviews == nil { + return false + } + return *p.RequireCodeOwnerReviews +} + +// GetRequireLastPushApproval returns the RequireLastPushApproval field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetRequireLastPushApproval() bool { + if p == nil || p.RequireLastPushApproval == nil { + return false + } + return *p.RequireLastPushApproval +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewThreadEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewThreadEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PullRequestReviewThreadEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewThreadEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewThreadEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewThreadEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetThread returns the Thread field. +func (p *PullRequestReviewThreadEvent) GetThread() *PullRequestThread { + if p == nil { + return nil + } + return p.Thread +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestTargetEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestTargetEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestTargetEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestTargetEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestTargetEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (p *PullRequestTargetEvent) GetPerformedViaGithubApp() *App { + if p == nil { + return nil + } + return p.PerformedViaGithubApp +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestTargetEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestTargetEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestTargetEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestTargetEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestTargetEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergablePulls() int { + if p == nil || p.MergablePulls == nil { + return 0 + } + return *p.MergablePulls +} + +// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergedPulls() int { + if p == nil || p.MergedPulls == nil { + return 0 + } + return *p.MergedPulls +} + +// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetTotalPulls() int { + if p == nil || p.TotalPulls == nil { + return 0 + } + return *p.TotalPulls +} + +// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetUnmergablePulls() int { + if p == nil || p.UnmergablePulls == nil { + return 0 + } + return *p.UnmergablePulls +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetDay returns the Day field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetDay() int { + if p == nil || p.Day == nil { + return 0 + } + return *p.Day +} + +// GetHour returns the Hour field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetHour() int { + if p == nil || p.Hour == nil { + return 0 + } + return *p.Hour +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBaseRef() string { + if p == nil || p.BaseRef == nil { + return "" + } + return *p.BaseRef +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetCommits returns the Commits slice if it's non-nil, nil otherwise. +func (p *PushEvent) GetCommits() []*HeadCommit { + if p == nil || p.Commits == nil { + return nil + } + return p.Commits +} + +// GetCompare returns the Compare field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCompare() string { + if p == nil || p.Compare == nil { + return "" + } + return *p.Compare +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCreated() bool { + if p == nil || p.Created == nil { + return false + } + return *p.Created +} + +// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDeleted() bool { + if p == nil || p.Deleted == nil { + return false + } + return *p.Deleted +} + +// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDistinctSize() int { + if p == nil || p.DistinctSize == nil { + return 0 + } + return *p.DistinctSize +} + +// GetForced returns the Forced field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetForced() bool { + if p == nil || p.Forced == nil { + return false + } + return *p.Forced +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetHead() string { + if p == nil || p.Head == nil { + return "" + } + return *p.Head +} + +// GetHeadCommit returns the HeadCommit field. +func (p *PushEvent) GetHeadCommit() *HeadCommit { + if p == nil { + return nil + } + return p.HeadCommit +} + +// GetInstallation returns the Installation field. +func (p *PushEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PushEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPusher returns the Pusher field. +func (p *PushEvent) GetPusher() *CommitAuthor { + if p == nil { + return nil + } + return p.Pusher +} + +// GetPushID returns the PushID field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetPushID() int64 { + if p == nil || p.PushID == nil { + return 0 + } + return *p.PushID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PushEvent) GetRepo() *PushEventRepository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PushEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetEmail() string { + if p == nil || p.Email == nil { + return "" + } + return *p.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchived() bool { + if p == nil || p.Archived == nil { + return false + } + return *p.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchiveURL() string { + if p == nil || p.ArchiveURL == nil { + return "" + } + return *p.ArchiveURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCloneURL() string { + if p == nil || p.CloneURL == nil { + return "" + } + return *p.CloneURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDefaultBranch() string { + if p == nil || p.DefaultBranch == nil { + return "" + } + return *p.DefaultBranch +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDisabled() bool { + if p == nil || p.Disabled == nil { + return false + } + return *p.Disabled +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFork() bool { + if p == nil || p.Fork == nil { + return false + } + return *p.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetForksCount() int { + if p == nil || p.ForksCount == nil { + return 0 + } + return *p.ForksCount +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFullName() string { + if p == nil || p.FullName == nil { + return "" + } + return *p.FullName +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetGitURL() string { + if p == nil || p.GitURL == nil { + return "" + } + return *p.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasDownloads() bool { + if p == nil || p.HasDownloads == nil { + return false + } + return *p.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasIssues() bool { + if p == nil || p.HasIssues == nil { + return false + } + return *p.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasPages() bool { + if p == nil || p.HasPages == nil { + return false + } + return *p.HasPages +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasWiki() bool { + if p == nil || p.HasWiki == nil { + return false + } + return *p.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHomepage() string { + if p == nil || p.Homepage == nil { + return "" + } + return *p.Homepage +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetLanguage() string { + if p == nil || p.Language == nil { + return "" + } + return *p.Language +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetMasterBranch() string { + if p == nil || p.MasterBranch == nil { + return "" + } + return *p.MasterBranch +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOpenIssuesCount() int { + if p == nil || p.OpenIssuesCount == nil { + return 0 + } + return *p.OpenIssuesCount +} + +// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOrganization() string { + if p == nil || p.Organization == nil { + return "" + } + return *p.Organization +} + +// GetOwner returns the Owner field. +func (p *PushEventRepository) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPullsURL() string { + if p == nil || p.PullsURL == nil { + return "" + } + return *p.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPushedAt() Timestamp { + if p == nil || p.PushedAt == nil { + return Timestamp{} + } + return *p.PushedAt +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSSHURL() string { + if p == nil || p.SSHURL == nil { + return "" + } + return *p.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStargazersCount() int { + if p == nil || p.StargazersCount == nil { + return 0 + } + return *p.StargazersCount +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSVNURL() string { + if p == nil || p.SVNURL == nil { + return "" + } + return *p.SVNURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetWatchersCount() int { + if p == nil || p.WatchersCount == nil { + return 0 + } + return *p.WatchersCount +} + +// GetActionsRunnerRegistration returns the ActionsRunnerRegistration field. +func (r *RateLimits) GetActionsRunnerRegistration() *Rate { + if r == nil { + return nil + } + return r.ActionsRunnerRegistration +} + +// GetAuditLog returns the AuditLog field. +func (r *RateLimits) GetAuditLog() *Rate { + if r == nil { + return nil + } + return r.AuditLog +} + +// GetCodeScanningUpload returns the CodeScanningUpload field. +func (r *RateLimits) GetCodeScanningUpload() *Rate { + if r == nil { + return nil + } + return r.CodeScanningUpload +} + +// GetCodeSearch returns the CodeSearch field. +func (r *RateLimits) GetCodeSearch() *Rate { + if r == nil { + return nil + } + return r.CodeSearch +} + +// GetCore returns the Core field. +func (r *RateLimits) GetCore() *Rate { + if r == nil { + return nil + } + return r.Core +} + +// GetDependencySnapshots returns the DependencySnapshots field. +func (r *RateLimits) GetDependencySnapshots() *Rate { + if r == nil { + return nil + } + return r.DependencySnapshots +} + +// GetGraphQL returns the GraphQL field. +func (r *RateLimits) GetGraphQL() *Rate { + if r == nil { + return nil + } + return r.GraphQL +} + +// GetIntegrationManifest returns the IntegrationManifest field. +func (r *RateLimits) GetIntegrationManifest() *Rate { + if r == nil { + return nil + } + return r.IntegrationManifest +} + +// GetSCIM returns the SCIM field. +func (r *RateLimits) GetSCIM() *Rate { + if r == nil { + return nil + } + return r.SCIM +} + +// GetSearch returns the Search field. +func (r *RateLimits) GetSearch() *Rate { + if r == nil { + return nil + } + return r.Search +} + +// GetSourceImport returns the SourceImport field. +func (r *RateLimits) GetSourceImport() *Rate { + if r == nil { + return nil + } + return r.SourceImport +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *Reaction) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetUser returns the User field. +func (r *Reaction) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetConfused returns the Confused field if it's non-nil, zero value otherwise. +func (r *Reactions) GetConfused() int { + if r == nil || r.Confused == nil { + return 0 + } + return *r.Confused +} + +// GetEyes returns the Eyes field if it's non-nil, zero value otherwise. +func (r *Reactions) GetEyes() int { + if r == nil || r.Eyes == nil { + return 0 + } + return *r.Eyes +} + +// GetHeart returns the Heart field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHeart() int { + if r == nil || r.Heart == nil { + return 0 + } + return *r.Heart +} + +// GetHooray returns the Hooray field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHooray() int { + if r == nil || r.Hooray == nil { + return 0 + } + return *r.Hooray +} + +// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. +func (r *Reactions) GetLaugh() int { + if r == nil || r.Laugh == nil { + return 0 + } + return *r.Laugh +} + +// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetMinusOne() int { + if r == nil || r.MinusOne == nil { + return 0 + } + return *r.MinusOne +} + +// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetPlusOne() int { + if r == nil || r.PlusOne == nil { + return 0 + } + return *r.PlusOne +} + +// GetRocket returns the Rocket field if it's non-nil, zero value otherwise. +func (r *Reactions) GetRocket() int { + if r == nil || r.Rocket == nil { + return 0 + } + return *r.Rocket +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *Reactions) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reactions) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reference) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetObject returns the Object field. +func (r *Reference) GetObject() *GitObject { + if r == nil { + return nil + } + return r.Object +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *Reference) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reference) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *ReferencedWorkflow) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetBrowserDownloadURL() string { + if r == nil || r.BrowserDownloadURL == nil { + return "" + } + return *r.BrowserDownloadURL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetContentType() string { + if r == nil || r.ContentType == nil { + return "" + } + return *r.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetDownloadCount() int { + if r == nil || r.DownloadCount == nil { + return 0 + } + return *r.DownloadCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetLabel() string { + if r == nil || r.Label == nil { + return "" + } + return *r.Label +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (r *ReleaseAsset) GetUploader() *User { + if r == nil { + return nil + } + return r.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *ReleaseEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetInstallation returns the Installation field. +func (r *ReleaseEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *ReleaseEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRelease returns the Release field. +func (r *ReleaseEvent) GetRelease() *RepositoryRelease { + if r == nil { + return nil + } + return r.Release +} + +// GetRepo returns the Repo field. +func (r *ReleaseEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *ReleaseEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *Rename) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (r *Rename) GetTo() string { + if r == nil || r.To == nil { + return "" + } + return *r.To +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCredit) GetLogin() string { + if r == nil || r.Login == nil { + return "" + } + return *r.Login +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCredit) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCreditDetailed) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepoAdvisoryCreditDetailed) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetUser returns the User field. +func (r *RepoAdvisoryCreditDetailed) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetDownloadLocation returns the DownloadLocation field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetDownloadLocation() string { + if r == nil || r.DownloadLocation == nil { + return "" + } + return *r.DownloadLocation +} + +// GetFilesAnalyzed returns the FilesAnalyzed field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetFilesAnalyzed() bool { + if r == nil || r.FilesAnalyzed == nil { + return false + } + return *r.FilesAnalyzed +} + +// GetLicenseConcluded returns the LicenseConcluded field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetLicenseConcluded() string { + if r == nil || r.LicenseConcluded == nil { + return "" + } + return *r.LicenseConcluded +} + +// GetLicenseDeclared returns the LicenseDeclared field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetLicenseDeclared() string { + if r == nil || r.LicenseDeclared == nil { + return "" + } + return *r.LicenseDeclared +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetSPDXID() string { + if r == nil || r.SPDXID == nil { + return "" + } + return *r.SPDXID +} + +// GetVersionInfo returns the VersionInfo field if it's non-nil, zero value otherwise. +func (r *RepoDependencies) GetVersionInfo() string { + if r == nil || r.VersionInfo == nil { + return "" + } + return *r.VersionInfo +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamRequest) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetBaseBranch returns the BaseBranch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetBaseBranch() string { + if r == nil || r.BaseBranch == nil { + return "" + } + return *r.BaseBranch +} + +// GetMergeType returns the MergeType field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMergeType() string { + if r == nil || r.MergeType == nil { + return "" + } + return *r.MergeType +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepoName) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetBadgeURL returns the BadgeURL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetBadgeURL() string { + if r == nil || r.BadgeURL == nil { + return "" + } + return *r.BadgeURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSourceRepository returns the SourceRepository field. +func (r *RepoRequiredWorkflow) GetSourceRepository() *Repository { + if r == nil { + return nil + } + return r.SourceRepository +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflow) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *RepoRequiredWorkflows) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetIncompleteResults() bool { + if r == nil || r.IncompleteResults == nil { + return false + } + return *r.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetTotal() int { + if r == nil || r.Total == nil { + return 0 + } + return *r.Total +} + +// GetAllowAutoMerge returns the AllowAutoMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowAutoMerge() bool { + if r == nil || r.AllowAutoMerge == nil { + return false + } + return *r.AllowAutoMerge +} + +// GetAllowForking returns the AllowForking field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowForking() bool { + if r == nil || r.AllowForking == nil { + return false + } + return *r.AllowForking +} + +// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowMergeCommit() bool { + if r == nil || r.AllowMergeCommit == nil { + return false + } + return *r.AllowMergeCommit +} + +// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowRebaseMerge() bool { + if r == nil || r.AllowRebaseMerge == nil { + return false + } + return *r.AllowRebaseMerge +} + +// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowSquashMerge() bool { + if r == nil || r.AllowSquashMerge == nil { + return false + } + return *r.AllowSquashMerge +} + +// GetAllowUpdateBranch returns the AllowUpdateBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowUpdateBranch() bool { + if r == nil || r.AllowUpdateBranch == nil { + return false + } + return *r.AllowUpdateBranch +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchived() bool { + if r == nil || r.Archived == nil { + return false + } + return *r.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchiveURL() string { + if r == nil || r.ArchiveURL == nil { + return "" + } + return *r.ArchiveURL +} + +// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetAssigneesURL() string { + if r == nil || r.AssigneesURL == nil { + return "" + } + return *r.AssigneesURL +} + +// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAutoInit() bool { + if r == nil || r.AutoInit == nil { + return false + } + return *r.AutoInit +} + +// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBlobsURL() string { + if r == nil || r.BlobsURL == nil { + return "" + } + return *r.BlobsURL +} + +// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBranchesURL() string { + if r == nil || r.BranchesURL == nil { + return "" + } + return *r.BranchesURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCloneURL() string { + if r == nil || r.CloneURL == nil { + return "" + } + return *r.CloneURL +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (r *Repository) GetCodeOfConduct() *CodeOfConduct { + if r == nil { + return nil + } + return r.CodeOfConduct +} + +// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCollaboratorsURL() string { + if r == nil || r.CollaboratorsURL == nil { + return "" + } + return *r.CollaboratorsURL +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommitsURL() string { + if r == nil || r.CommitsURL == nil { + return "" + } + return *r.CommitsURL +} + +// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCompareURL() string { + if r == nil || r.CompareURL == nil { + return "" + } + return *r.CompareURL +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContentsURL() string { + if r == nil || r.ContentsURL == nil { + return "" + } + return *r.ContentsURL +} + +// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContributorsURL() string { + if r == nil || r.ContributorsURL == nil { + return "" + } + return *r.ContributorsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetDefaultBranch() string { + if r == nil || r.DefaultBranch == nil { + return "" + } + return *r.DefaultBranch +} + +// GetDeleteBranchOnMerge returns the DeleteBranchOnMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeleteBranchOnMerge() bool { + if r == nil || r.DeleteBranchOnMerge == nil { + return false + } + return *r.DeleteBranchOnMerge +} + +// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeploymentsURL() string { + if r == nil || r.DeploymentsURL == nil { + return "" + } + return *r.DeploymentsURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Repository) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (r *Repository) GetDisabled() bool { + if r == nil || r.Disabled == nil { + return false + } + return *r.Disabled +} + +// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDownloadsURL() string { + if r == nil || r.DownloadsURL == nil { + return "" + } + return *r.DownloadsURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetEventsURL() string { + if r == nil || r.EventsURL == nil { + return "" + } + return *r.EventsURL +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (r *Repository) GetFork() bool { + if r == nil || r.Fork == nil { + return false + } + return *r.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksCount() int { + if r == nil || r.ForksCount == nil { + return 0 + } + return *r.ForksCount +} + +// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksURL() string { + if r == nil || r.ForksURL == nil { + return "" + } + return *r.ForksURL +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (r *Repository) GetFullName() string { + if r == nil || r.FullName == nil { + return "" + } + return *r.FullName +} + +// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitCommitsURL() string { + if r == nil || r.GitCommitsURL == nil { + return "" + } + return *r.GitCommitsURL +} + +// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitignoreTemplate() string { + if r == nil || r.GitignoreTemplate == nil { + return "" + } + return *r.GitignoreTemplate +} + +// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitRefsURL() string { + if r == nil || r.GitRefsURL == nil { + return "" + } + return *r.GitRefsURL +} + +// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitTagsURL() string { + if r == nil || r.GitTagsURL == nil { + return "" + } + return *r.GitTagsURL +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHasDiscussions returns the HasDiscussions field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDiscussions() bool { + if r == nil || r.HasDiscussions == nil { + return false + } + return *r.HasDiscussions +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDownloads() bool { + if r == nil || r.HasDownloads == nil { + return false + } + return *r.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasIssues() bool { + if r == nil || r.HasIssues == nil { + return false + } + return *r.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasPages() bool { + if r == nil || r.HasPages == nil { + return false + } + return *r.HasPages +} + +// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasProjects() bool { + if r == nil || r.HasProjects == nil { + return false + } + return *r.HasProjects +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasWiki() bool { + if r == nil || r.HasWiki == nil { + return false + } + return *r.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (r *Repository) GetHomepage() string { + if r == nil || r.Homepage == nil { + return "" + } + return *r.Homepage +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHooksURL() string { + if r == nil || r.HooksURL == nil { + return "" + } + return *r.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Repository) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueCommentURL() string { + if r == nil || r.IssueCommentURL == nil { + return "" + } + return *r.IssueCommentURL +} + +// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueEventsURL() string { + if r == nil || r.IssueEventsURL == nil { + return "" + } + return *r.IssueEventsURL +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssuesURL() string { + if r == nil || r.IssuesURL == nil { + return "" + } + return *r.IssuesURL +} + +// GetIsTemplate returns the IsTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetIsTemplate() bool { + if r == nil || r.IsTemplate == nil { + return false + } + return *r.IsTemplate +} + +// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetKeysURL() string { + if r == nil || r.KeysURL == nil { + return "" + } + return *r.KeysURL +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLabelsURL() string { + if r == nil || r.LabelsURL == nil { + return "" + } + return *r.LabelsURL +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguage() string { + if r == nil || r.Language == nil { + return "" + } + return *r.Language +} + +// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguagesURL() string { + if r == nil || r.LanguagesURL == nil { + return "" + } + return *r.LanguagesURL +} + +// GetLicense returns the License field. +func (r *Repository) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetLicenseTemplate() string { + if r == nil || r.LicenseTemplate == nil { + return "" + } + return *r.LicenseTemplate +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetMasterBranch() string { + if r == nil || r.MasterBranch == nil { + return "" + } + return *r.MasterBranch +} + +// GetMergeCommitMessage returns the MergeCommitMessage field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergeCommitMessage() string { + if r == nil || r.MergeCommitMessage == nil { + return "" + } + return *r.MergeCommitMessage +} + +// GetMergeCommitTitle returns the MergeCommitTitle field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergeCommitTitle() string { + if r == nil || r.MergeCommitTitle == nil { + return "" + } + return *r.MergeCommitTitle +} + +// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergesURL() string { + if r == nil || r.MergesURL == nil { + return "" + } + return *r.MergesURL +} + +// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMilestonesURL() string { + if r == nil || r.MilestonesURL == nil { + return "" + } + return *r.MilestonesURL +} + +// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMirrorURL() string { + if r == nil || r.MirrorURL == nil { + return "" + } + return *r.MirrorURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Repository) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetNetworkCount() int { + if r == nil || r.NetworkCount == nil { + return 0 + } + return *r.NetworkCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Repository) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetNotificationsURL() string { + if r == nil || r.NotificationsURL == nil { + return "" + } + return *r.NotificationsURL +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssues() int { + if r == nil || r.OpenIssues == nil { + return 0 + } + return *r.OpenIssues +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssuesCount() int { + if r == nil || r.OpenIssuesCount == nil { + return 0 + } + return *r.OpenIssuesCount +} + +// GetOrganization returns the Organization field. +func (r *Repository) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetOwner returns the Owner field. +func (r *Repository) GetOwner() *User { + if r == nil { + return nil + } + return r.Owner +} + +// GetParent returns the Parent field. +func (r *Repository) GetParent() *Repository { + if r == nil { + return nil + } + return r.Parent +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (r *Repository) GetPermissions() map[string]bool { + if r == nil || r.Permissions == nil { + return map[string]bool{} + } + return r.Permissions +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (r *Repository) GetPrivate() bool { + if r == nil || r.Private == nil { + return false + } + return *r.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetPullsURL() string { + if r == nil || r.PullsURL == nil { + return "" + } + return *r.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetPushedAt() Timestamp { + if r == nil || r.PushedAt == nil { + return Timestamp{} + } + return *r.PushedAt +} + +// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetReleasesURL() string { + if r == nil || r.ReleasesURL == nil { + return "" + } + return *r.ReleasesURL +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (r *Repository) GetRoleName() string { + if r == nil || r.RoleName == nil { + return "" + } + return *r.RoleName +} + +// GetSecurityAndAnalysis returns the SecurityAndAnalysis field. +func (r *Repository) GetSecurityAndAnalysis() *SecurityAndAnalysis { + if r == nil { + return nil + } + return r.SecurityAndAnalysis +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *Repository) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSource returns the Source field. +func (r *Repository) GetSource() *Repository { + if r == nil { + return nil + } + return r.Source +} + +// GetSquashMergeCommitMessage returns the SquashMergeCommitMessage field if it's non-nil, zero value otherwise. +func (r *Repository) GetSquashMergeCommitMessage() string { + if r == nil || r.SquashMergeCommitMessage == nil { + return "" + } + return *r.SquashMergeCommitMessage +} + +// GetSquashMergeCommitTitle returns the SquashMergeCommitTitle field if it's non-nil, zero value otherwise. +func (r *Repository) GetSquashMergeCommitTitle() string { + if r == nil || r.SquashMergeCommitTitle == nil { + return "" + } + return *r.SquashMergeCommitTitle +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSSHURL() string { + if r == nil || r.SSHURL == nil { + return "" + } + return *r.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersCount() int { + if r == nil || r.StargazersCount == nil { + return 0 + } + return *r.StargazersCount +} + +// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersURL() string { + if r == nil || r.StargazersURL == nil { + return "" + } + return *r.StargazersURL +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStatusesURL() string { + if r == nil || r.StatusesURL == nil { + return "" + } + return *r.StatusesURL +} + +// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersCount() int { + if r == nil || r.SubscribersCount == nil { + return 0 + } + return *r.SubscribersCount +} + +// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersURL() string { + if r == nil || r.SubscribersURL == nil { + return "" + } + return *r.SubscribersURL +} + +// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscriptionURL() string { + if r == nil || r.SubscriptionURL == nil { + return "" + } + return *r.SubscriptionURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSVNURL() string { + if r == nil || r.SVNURL == nil { + return "" + } + return *r.SVNURL +} + +// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTagsURL() string { + if r == nil || r.TagsURL == nil { + return "" + } + return *r.TagsURL +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamID() int64 { + if r == nil || r.TeamID == nil { + return 0 + } + return *r.TeamID +} + +// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamsURL() string { + if r == nil || r.TeamsURL == nil { + return "" + } + return *r.TeamsURL +} + +// GetTemplateRepository returns the TemplateRepository field. +func (r *Repository) GetTemplateRepository() *Repository { + if r == nil { + return nil + } + return r.TemplateRepository +} + +// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTreesURL() string { + if r == nil || r.TreesURL == nil { + return "" + } + return *r.TreesURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Repository) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUseSquashPRTitleAsDefault returns the UseSquashPRTitleAsDefault field if it's non-nil, zero value otherwise. +func (r *Repository) GetUseSquashPRTitleAsDefault() bool { + if r == nil || r.UseSquashPRTitleAsDefault == nil { + return false + } + return *r.UseSquashPRTitleAsDefault +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *Repository) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetWatchers returns the Watchers field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchers() int { + if r == nil || r.Watchers == nil { + return 0 + } + return *r.Watchers +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchersCount() int { + if r == nil || r.WatchersCount == nil { + return 0 + } + return *r.WatchersCount +} + +// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise. +func (r *Repository) GetWebCommitSignoffRequired() bool { + if r == nil || r.WebCommitSignoffRequired == nil { + return false + } + return *r.WebCommitSignoffRequired +} + +// GetAccessLevel returns the AccessLevel field if it's non-nil, zero value otherwise. +func (r *RepositoryActionsAccessLevel) GetAccessLevel() string { + if r == nil || r.AccessLevel == nil { + return "" + } + return *r.AccessLevel +} + +// GetAdvancedSecurityCommitters returns the AdvancedSecurityCommitters field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetAdvancedSecurityCommitters() int { + if r == nil || r.AdvancedSecurityCommitters == nil { + return 0 + } + return *r.AdvancedSecurityCommitters +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetConfiguration returns the Configuration field. +func (r *RepositoryCodeSecurityConfiguration) GetConfiguration() *CodeSecurityConfiguration { + if r == nil { + return nil + } + return r.Configuration +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepositoryCodeSecurityConfiguration) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCommitID() string { + if r == nil || r.CommitID == nil { + return "" + } + return *r.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPosition() int { + if r == nil || r.Position == nil { + return 0 + } + return *r.Position +} + +// GetReactions returns the Reactions field. +func (r *RepositoryComment) GetReactions() *Reactions { + if r == nil { + return nil + } + return r.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUser returns the User field. +func (r *RepositoryComment) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAuthor returns the Author field. +func (r *RepositoryCommit) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryCommit) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetCommitter returns the Committer field. +func (r *RepositoryCommit) GetCommitter() *User { + if r == nil { + return nil + } + return r.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetStats returns the Stats field. +func (r *RepositoryCommit) GetStats() *CommitStats { + if r == nil { + return nil + } + return r.Stats +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSubmoduleGitURL returns the SubmoduleGitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSubmoduleGitURL() string { + if r == nil || r.SubmoduleGitURL == nil { + return "" + } + return *r.SubmoduleGitURL +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAuthor returns the Author field. +func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { + if r == nil { + return nil + } + return r.Author +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetCommitter returns the Committer field. +func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { + if r == nil { + return nil + } + return r.Committer +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetContent returns the Content field. +func (r *RepositoryContentResponse) GetContent() *RepositoryContent { + if r == nil { + return nil + } + return r.Content +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetInstallation returns the Installation field. +func (r *RepositoryDispatchEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryDispatchEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryDispatchEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryDispatchEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetChanges returns the Changes field. +func (r *RepositoryEvent) GetChanges() *EditChange { + if r == nil { + return nil + } + return r.Changes +} + +// GetInstallation returns the Installation field. +func (r *RepositoryEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetOrg returns the Org field. +func (r *RepositoryImportEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryImportEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryImportEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *RepositoryImportEvent) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetExpired returns the Expired field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetExpired() bool { + if r == nil || r.Expired == nil { + return false + } + return *r.Expired +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInvitee returns the Invitee field. +func (r *RepositoryInvitation) GetInvitee() *User { + if r == nil { + return nil + } + return r.Invitee +} + +// GetInviter returns the Inviter field. +func (r *RepositoryInvitation) GetInviter() *User { + if r == nil { + return nil + } + return r.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetPermissions() string { + if r == nil || r.Permissions == nil { + return "" + } + return *r.Permissions +} + +// GetRepo returns the Repo field. +func (r *RepositoryInvitation) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetLicense returns the License field. +func (r *RepositoryLicense) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetBase() string { + if r == nil || r.Base == nil { + return "" + } + return *r.Base +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetCommitMessage() string { + if r == nil || r.CommitMessage == nil { + return "" + } + return *r.CommitMessage +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetHead() string { + if r == nil || r.Head == nil { + return "" + } + return *r.Head +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetPermission() string { + if r == nil || r.Permission == nil { + return "" + } + return *r.Permission +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetRoleName() string { + if r == nil || r.RoleName == nil { + return "" + } + return *r.RoleName +} + +// GetUser returns the User field. +func (r *RepositoryPermissionLevel) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetAssetsURL() string { + if r == nil || r.AssetsURL == nil { + return "" + } + return *r.AssetsURL +} + +// GetAuthor returns the Author field. +func (r *RepositoryRelease) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDiscussionCategoryName returns the DiscussionCategoryName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDiscussionCategoryName() string { + if r == nil || r.DiscussionCategoryName == nil { + return "" + } + return *r.DiscussionCategoryName +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDraft() bool { + if r == nil || r.Draft == nil { + return false + } + return *r.Draft +} + +// GetGenerateReleaseNotes returns the GenerateReleaseNotes field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetGenerateReleaseNotes() bool { + if r == nil || r.GenerateReleaseNotes == nil { + return false + } + return *r.GenerateReleaseNotes +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetMakeLatest returns the MakeLatest field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetMakeLatest() string { + if r == nil || r.MakeLatest == nil { + return "" + } + return *r.MakeLatest +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPrerelease() bool { + if r == nil || r.Prerelease == nil { + return false + } + return *r.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPublishedAt() Timestamp { + if r == nil || r.PublishedAt == nil { + return Timestamp{} + } + return *r.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTagName() string { + if r == nil || r.TagName == nil { + return "" + } + return *r.TagName +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTargetCommitish() string { + if r == nil || r.TargetCommitish == nil { + return "" + } + return *r.TargetCommitish +} + +// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetUploadURL() string { + if r == nil || r.UploadURL == nil { + return "" + } + return *r.UploadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetParameters returns the Parameters field if it's non-nil, zero value otherwise. +func (r *RepositoryRule) GetParameters() json.RawMessage { + if r == nil || r.Parameters == nil { + return json.RawMessage{} + } + return *r.Parameters +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetCurrentUserCanBypass returns the CurrentUserCanBypass field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetCurrentUserCanBypass() string { + if r == nil || r.CurrentUserCanBypass == nil { + return "" + } + return *r.CurrentUserCanBypass +} + +// GetLinks returns the Links field. +func (r *RepositoryRuleset) GetLinks() *RepositoryRulesetLink { + if r == nil { + return nil + } + return r.Links +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetSourceType() string { + if r == nil || r.SourceType == nil { + return "" + } + return *r.SourceType +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetCodeScanningRule) GetParameters() *RuleCodeScanningParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetConditions returns the Conditions field. +func (r *RepositoryRulesetEditedChanges) GetConditions() *RepositoryRulesetEditedConditions { + if r == nil { + return nil + } + return r.Conditions +} + +// GetEnforcement returns the Enforcement field. +func (r *RepositoryRulesetEditedChanges) GetEnforcement() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Enforcement +} + +// GetName returns the Name field. +func (r *RepositoryRulesetEditedChanges) GetName() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Name +} + +// GetRules returns the Rules field. +func (r *RepositoryRulesetEditedChanges) GetRules() *RepositoryRulesetEditedRules { + if r == nil { + return nil + } + return r.Rules +} + +// GetConfiguration returns the Configuration field. +func (r *RepositoryRulesetEditedRuleChanges) GetConfiguration() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Configuration +} + +// GetPattern returns the Pattern field. +func (r *RepositoryRulesetEditedRuleChanges) GetPattern() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Pattern +} + +// GetRuleType returns the RuleType field. +func (r *RepositoryRulesetEditedRuleChanges) GetRuleType() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.RuleType +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetEditedSource) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetEditedUpdatedConditions) GetChanges() *RepositoryRulesetUpdatedConditionsEdited { + if r == nil { + return nil + } + return r.Changes +} + +// GetCondition returns the Condition field. +func (r *RepositoryRulesetEditedUpdatedConditions) GetCondition() *RepositoryRulesetRefCondition { + if r == nil { + return nil + } + return r.Condition +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetEvent) GetChanges() *RepositoryRulesetEditedChanges { + if r == nil { + return nil + } + return r.Changes +} + +// GetEnterprise returns the Enterprise field. +func (r *RepositoryRulesetEvent) GetEnterprise() *Enterprise { + if r == nil { + return nil + } + return r.Enterprise +} + +// GetInstallation returns the Installation field. +func (r *RepositoryRulesetEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrganization returns the Organization field. +func (r *RepositoryRulesetEvent) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetRepository returns the Repository field. +func (r *RepositoryRulesetEvent) GetRepository() *Repository { + if r == nil { + return nil + } + return r.Repository +} + +// GetRepositoryRuleset returns the RepositoryRuleset field. +func (r *RepositoryRulesetEvent) GetRepositoryRuleset() *RepositoryRuleset { + if r == nil { + return nil + } + return r.RepositoryRuleset +} + +// GetSender returns the Sender field. +func (r *RepositoryRulesetEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetFileExtensionRestrictionRule) GetParameters() *RuleFileExtensionRestrictionParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetFilePathRestrictionRule) GetParameters() *RuleFileParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetHTML returns the HTML field. +func (r *RepositoryRulesetLink) GetHTML() *RulesetLink { + if r == nil { + return nil + } + return r.HTML +} + +// GetSelf returns the Self field. +func (r *RepositoryRulesetLink) GetSelf() *RulesetLink { + if r == nil { + return nil + } + return r.Self +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMaxFilePathLengthRule) GetParameters() *RuleMaxFilePathLengthParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMaxFileSizeRule) GetParameters() *RuleMaxFileSizeParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetMergeQueueRule) GetParameters() *MergeQueueRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetPatternRule) GetParameters() *RulePatternParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetPullRequestRule) GetParameters() *PullRequestRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetRefName returns the RefName field. +func (r *RepositoryRulesetRefCondition) GetRefName() *RulesetRefConditionParameters { + if r == nil { + return nil + } + return r.RefName +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetRequiredDeploymentsRule) GetParameters() *RequiredDeploymentEnvironmentsRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetRequiredStatusChecksRule) GetParameters() *RequiredStatusChecksRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetBranchNamePattern returns the BranchNamePattern field. +func (r *RepositoryRulesetRule) GetBranchNamePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.BranchNamePattern +} + +// GetCodeScanning returns the CodeScanning field. +func (r *RepositoryRulesetRule) GetCodeScanning() *RepositoryRulesetCodeScanningRule { + if r == nil { + return nil + } + return r.CodeScanning +} + +// GetCommitAuthorEmailPattern returns the CommitAuthorEmailPattern field. +func (r *RepositoryRulesetRule) GetCommitAuthorEmailPattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitAuthorEmailPattern +} + +// GetCommitMessagePattern returns the CommitMessagePattern field. +func (r *RepositoryRulesetRule) GetCommitMessagePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitMessagePattern +} + +// GetCommitterEmailPattern returns the CommitterEmailPattern field. +func (r *RepositoryRulesetRule) GetCommitterEmailPattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.CommitterEmailPattern +} + +// GetCreation returns the Creation field. +func (r *RepositoryRulesetRule) GetCreation() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.Creation +} + +// GetDeletion returns the Deletion field. +func (r *RepositoryRulesetRule) GetDeletion() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.Deletion +} + +// GetFileExtensionRestriction returns the FileExtensionRestriction field. +func (r *RepositoryRulesetRule) GetFileExtensionRestriction() *RepositoryRulesetFileExtensionRestrictionRule { + if r == nil { + return nil + } + return r.FileExtensionRestriction +} + +// GetFilePathRestriction returns the FilePathRestriction field. +func (r *RepositoryRulesetRule) GetFilePathRestriction() *RepositoryRulesetFilePathRestrictionRule { + if r == nil { + return nil + } + return r.FilePathRestriction +} + +// GetMaxFilePathLength returns the MaxFilePathLength field. +func (r *RepositoryRulesetRule) GetMaxFilePathLength() *RepositoryRulesetMaxFilePathLengthRule { + if r == nil { + return nil + } + return r.MaxFilePathLength +} + +// GetMaxFileSize returns the MaxFileSize field. +func (r *RepositoryRulesetRule) GetMaxFileSize() *RepositoryRulesetMaxFileSizeRule { + if r == nil { + return nil + } + return r.MaxFileSize +} + +// GetMergeQueue returns the MergeQueue field. +func (r *RepositoryRulesetRule) GetMergeQueue() *RepositoryRulesetMergeQueueRule { + if r == nil { + return nil + } + return r.MergeQueue +} + +// GetNonFastForward returns the NonFastForward field. +func (r *RepositoryRulesetRule) GetNonFastForward() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.NonFastForward +} + +// GetPullRequest returns the PullRequest field. +func (r *RepositoryRulesetRule) GetPullRequest() *RepositoryRulesetPullRequestRule { + if r == nil { + return nil + } + return r.PullRequest +} + +// GetRequiredDeployments returns the RequiredDeployments field. +func (r *RepositoryRulesetRule) GetRequiredDeployments() *RepositoryRulesetRequiredDeploymentsRule { + if r == nil { + return nil + } + return r.RequiredDeployments +} + +// GetRequiredLinearHistory returns the RequiredLinearHistory field. +func (r *RepositoryRulesetRule) GetRequiredLinearHistory() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.RequiredLinearHistory +} + +// GetRequiredSignatures returns the RequiredSignatures field. +func (r *RepositoryRulesetRule) GetRequiredSignatures() *RepositoryRulesetRuleType { + if r == nil { + return nil + } + return r.RequiredSignatures +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (r *RepositoryRulesetRule) GetRequiredStatusChecks() *RepositoryRulesetRequiredStatusChecksRule { + if r == nil { + return nil + } + return r.RequiredStatusChecks +} + +// GetTagNamePattern returns the TagNamePattern field. +func (r *RepositoryRulesetRule) GetTagNamePattern() *RepositoryRulesetPatternRule { + if r == nil { + return nil + } + return r.TagNamePattern +} + +// GetUpdate returns the Update field. +func (r *RepositoryRulesetRule) GetUpdate() *RepositoryRulesetUpdateRule { + if r == nil { + return nil + } + return r.Update +} + +// GetWorkflows returns the Workflows field. +func (r *RepositoryRulesetRule) GetWorkflows() *RepositoryRulesetWorkflowsRule { + if r == nil { + return nil + } + return r.Workflows +} + +// GetConditionType returns the ConditionType field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetConditionType() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.ConditionType +} + +// GetExclude returns the Exclude field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetExclude() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Exclude +} + +// GetInclude returns the Include field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetInclude() *RepositoryRulesetEditedSources { + if r == nil { + return nil + } + return r.Include +} + +// GetTarget returns the Target field. +func (r *RepositoryRulesetUpdatedConditionsEdited) GetTarget() *RepositoryRulesetEditedSource { + if r == nil { + return nil + } + return r.Target +} + +// GetChanges returns the Changes field. +func (r *RepositoryRulesetUpdatedRules) GetChanges() *RepositoryRulesetEditedRuleChanges { + if r == nil { + return nil + } + return r.Changes +} + +// GetRule returns the Rule field. +func (r *RepositoryRulesetUpdatedRules) GetRule() *RepositoryRulesetRule { + if r == nil { + return nil + } + return r.Rule +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetUpdateRule) GetParameters() *UpdateAllowsFetchAndMergeRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetParameters returns the Parameters field. +func (r *RepositoryRulesetWorkflowsRule) GetParameters() *RequiredWorkflowsRuleParameters { + if r == nil { + return nil + } + return r.Parameters +} + +// GetCommit returns the Commit field. +func (r *RepositoryTag) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetAffectedPackageName returns the AffectedPackageName field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedPackageName() string { + if r == nil || r.AffectedPackageName == nil { + return "" + } + return *r.AffectedPackageName +} + +// GetAffectedRange returns the AffectedRange field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedRange() string { + if r == nil || r.AffectedRange == nil { + return "" + } + return *r.AffectedRange +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissedAt() Timestamp { + if r == nil || r.DismissedAt == nil { + return Timestamp{} + } + return *r.DismissedAt +} + +// GetDismisser returns the Dismisser field. +func (r *RepositoryVulnerabilityAlert) GetDismisser() *User { + if r == nil { + return nil + } + return r.Dismisser +} + +// GetDismissReason returns the DismissReason field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissReason() string { + if r == nil || r.DismissReason == nil { + return "" + } + return *r.DismissReason +} + +// GetExternalIdentifier returns the ExternalIdentifier field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalIdentifier() string { + if r == nil || r.ExternalIdentifier == nil { + return "" + } + return *r.ExternalIdentifier +} + +// GetExternalReference returns the ExternalReference field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalReference() string { + if r == nil || r.ExternalReference == nil { + return "" + } + return *r.ExternalReference +} + +// GetFixedIn returns the FixedIn field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetFixedIn() string { + if r == nil || r.FixedIn == nil { + return "" + } + return *r.FixedIn +} + +// GetGitHubSecurityAdvisoryID returns the GitHubSecurityAdvisoryID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetGitHubSecurityAdvisoryID() string { + if r == nil || r.GitHubSecurityAdvisoryID == nil { + return "" + } + return *r.GitHubSecurityAdvisoryID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetAlert returns the Alert field. +func (r *RepositoryVulnerabilityAlertEvent) GetAlert() *RepositoryVulnerabilityAlert { + if r == nil { + return nil + } + return r.Alert +} + +// GetInstallation returns the Installation field. +func (r *RepositoryVulnerabilityAlertEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryVulnerabilityAlertEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepository returns the Repository field. +func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository { + if r == nil { + return nil + } + return r.Repository +} + +// GetSender returns the Sender field. +func (r *RepositoryVulnerabilityAlertEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetForkRepos() int { + if r == nil || r.ForkRepos == nil { + return 0 + } + return *r.ForkRepos +} + +// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetOrgRepos() int { + if r == nil || r.OrgRepos == nil { + return 0 + } + return *r.OrgRepos +} + +// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetRootRepos() int { + if r == nil || r.RootRepos == nil { + return 0 + } + return *r.RootRepos +} + +// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalPushes() int { + if r == nil || r.TotalPushes == nil { + return 0 + } + return *r.TotalPushes +} + +// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalRepos() int { + if r == nil || r.TotalRepos == nil { + return 0 + } + return *r.TotalRepos +} + +// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalWikis() int { + if r == nil || r.TotalWikis == nil { + return 0 + } + return *r.TotalWikis +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetAvatarURL() string { + if r == nil || r.AvatarURL == nil { + return "" + } + return *r.AvatarURL +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetContext() string { + if r == nil || r.Context == nil { + return "" + } + return *r.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetCreator returns the Creator field. +func (r *RepoStatus) GetCreator() *User { + if r == nil { + return nil + } + return r.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetTargetURL() string { + if r == nil || r.TargetURL == nil { + return "" + } + return *r.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequireCodeOwnerReviewChanges) GetFrom() bool { + if r == nil || r.From == nil { + return false + } + return *r.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredConversationResolutionLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredDeploymentsEnforcementLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RequiredReviewer) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (r *RequiredStatusCheck) GetAppID() int64 { + if r == nil || r.AppID == nil { + return 0 + } + return *r.AppID +} + +// GetChecks returns the Checks field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetChecks() []*RequiredStatusCheck { + if r == nil || r.Checks == nil { + return nil + } + return *r.Checks +} + +// GetContexts returns the Contexts field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetContexts() []string { + if r == nil || r.Contexts == nil { + return nil + } + return *r.Contexts +} + +// GetContextsURL returns the ContextsURL field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetContextsURL() string { + if r == nil || r.ContextsURL == nil { + return "" + } + return *r.ContextsURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecks) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksEnforcementLevelChanges) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetStrict returns the Strict field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksRequest) GetStrict() bool { + if r == nil || r.Strict == nil { + return false + } + return *r.Strict +} + +// GetDoNotEnforceOnCreate returns the DoNotEnforceOnCreate field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksRuleParameters) GetDoNotEnforceOnCreate() bool { + if r == nil || r.DoNotEnforceOnCreate == nil { + return false + } + return *r.DoNotEnforceOnCreate +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *RequiredWorkflowSelectedRepos) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReviewersRequest) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (r *ReviewPersonalAccessTokenRequestOptions) GetReason() string { + if r == nil || r.Reason == nil { + return "" + } + return *r.Reason +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Rule) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetFullDescription returns the FullDescription field if it's non-nil, zero value otherwise. +func (r *Rule) GetFullDescription() string { + if r == nil || r.FullDescription == nil { + return "" + } + return *r.FullDescription +} + +// GetHelp returns the Help field if it's non-nil, zero value otherwise. +func (r *Rule) GetHelp() string { + if r == nil || r.Help == nil { + return "" + } + return *r.Help +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Rule) GetID() string { + if r == nil || r.ID == nil { + return "" + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Rule) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetSecuritySeverityLevel returns the SecuritySeverityLevel field if it's non-nil, zero value otherwise. +func (r *Rule) GetSecuritySeverityLevel() string { + if r == nil || r.SecuritySeverityLevel == nil { + return "" + } + return *r.SecuritySeverityLevel +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *Rule) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetRestrictedFilePaths returns the RestrictedFilePaths field if it's non-nil, zero value otherwise. +func (r *RuleFileParameters) GetRestrictedFilePaths() []string { + if r == nil || r.RestrictedFilePaths == nil { + return nil + } + return *r.RestrictedFilePaths +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RulePatternParameters) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNegate returns the Negate field if it's non-nil, zero value otherwise. +func (r *RulePatternParameters) GetNegate() bool { + if r == nil || r.Negate == nil { + return false + } + return *r.Negate +} + +// GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise. +func (r *RuleRequiredStatusChecks) GetIntegrationID() int64 { + if r == nil || r.IntegrationID == nil { + return 0 + } + return *r.IntegrationID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetRepositoryID() int64 { + if r == nil || r.RepositoryID == nil { + return 0 + } + return *r.RepositoryID +} + +// GetSha returns the Sha field if it's non-nil, zero value otherwise. +func (r *RuleRequiredWorkflow) GetSha() string { + if r == nil || r.Sha == nil { + return "" + } + return *r.Sha +} + +// GetConditions returns the Conditions field. +func (r *Ruleset) GetConditions() *RulesetConditions { + if r == nil { + return nil + } + return r.Conditions +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLinks returns the Links field. +func (r *Ruleset) GetLinks() *RulesetLinks { + if r == nil { + return nil + } + return r.Links +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetSourceType() string { + if r == nil || r.SourceType == nil { + return "" + } + return *r.SourceType +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Ruleset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetRefName returns the RefName field. +func (r *RulesetConditions) GetRefName() *RulesetRefConditionParameters { + if r == nil { + return nil + } + return r.RefName +} + +// GetRepositoryID returns the RepositoryID field. +func (r *RulesetConditions) GetRepositoryID() *RulesetRepositoryIDsConditionParameters { + if r == nil { + return nil + } + return r.RepositoryID +} + +// GetRepositoryName returns the RepositoryName field. +func (r *RulesetConditions) GetRepositoryName() *RulesetRepositoryNamesConditionParameters { + if r == nil { + return nil + } + return r.RepositoryName +} + +// GetRepositoryProperty returns the RepositoryProperty field. +func (r *RulesetConditions) GetRepositoryProperty() *RulesetRepositoryPropertyConditionParameters { + if r == nil { + return nil + } + return r.RepositoryProperty +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (r *RulesetLink) GetHRef() string { + if r == nil || r.HRef == nil { + return "" + } + return *r.HRef +} + +// GetSelf returns the Self field. +func (r *RulesetLinks) GetSelf() *RulesetLink { + if r == nil { + return nil + } + return r.Self +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (r *RulesetRepositoryNamesConditionParameters) GetProtected() bool { + if r == nil || r.Protected == nil { + return false + } + return *r.Protected +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (r *RulesetRepositoryPropertyTargetParameters) GetSource() string { + if r == nil || r.Source == nil { + return "" + } + return *r.Source +} + +// GetBusy returns the Busy field if it's non-nil, zero value otherwise. +func (r *Runner) GetBusy() bool { + if r == nil || r.Busy == nil { + return false + } + return *r.Busy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Runner) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Runner) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *Runner) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *Runner) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetArchitecture returns the Architecture field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetArchitecture() string { + if r == nil || r.Architecture == nil { + return "" + } + return *r.Architecture +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetFilename() string { + if r == nil || r.Filename == nil { + return "" + } + return *r.Filename +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetSHA256Checksum returns the SHA256Checksum field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetSHA256Checksum() string { + if r == nil || r.SHA256Checksum == nil { + return "" + } + return *r.SHA256Checksum +} + +// GetTempDownloadToken returns the TempDownloadToken field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetTempDownloadToken() string { + if r == nil || r.TempDownloadToken == nil { + return "" + } + return *r.TempDownloadToken +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetAllowsPublicRepositories() bool { + if r == nil || r.AllowsPublicRepositories == nil { + return false + } + return *r.AllowsPublicRepositories +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetDefault() bool { + if r == nil || r.Default == nil { + return false + } + return *r.Default +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInherited returns the Inherited field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetInherited() bool { + if r == nil || r.Inherited == nil { + return false + } + return *r.Inherited +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetRestrictedToWorkflows() bool { + if r == nil || r.RestrictedToWorkflows == nil { + return false + } + return *r.RestrictedToWorkflows +} + +// GetRunnersURL returns the RunnersURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetRunnersURL() string { + if r == nil || r.RunnersURL == nil { + return "" + } + return *r.RunnersURL +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetSelectedRepositoriesURL() string { + if r == nil || r.SelectedRepositoriesURL == nil { + return "" + } + return *r.SelectedRepositoriesURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetWorkflowRestrictionsReadOnly returns the WorkflowRestrictionsReadOnly field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetWorkflowRestrictionsReadOnly() bool { + if r == nil || r.WorkflowRestrictionsReadOnly == nil { + return false + } + return *r.WorkflowRestrictionsReadOnly +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetCheckoutURI returns the CheckoutURI field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCheckoutURI() string { + if s == nil || s.CheckoutURI == nil { + return "" + } + return *s.CheckoutURI +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetSarif returns the Sarif field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetSarif() string { + if s == nil || s.Sarif == nil { + return "" + } + return *s.Sarif +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetStartedAt() Timestamp { + if s == nil || s.StartedAt == nil { + return Timestamp{} + } + return *s.StartedAt +} + +// GetToolName returns the ToolName field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetToolName() string { + if s == nil || s.ToolName == nil { + return "" + } + return *s.ToolName +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SarifID) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SarifID) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAnalysesURL returns the AnalysesURL field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetAnalysesURL() string { + if s == nil || s.AnalysesURL == nil { + return "" + } + return *s.AnalysesURL +} + +// GetProcessingStatus returns the ProcessingStatus field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetProcessingStatus() string { + if s == nil || s.ProcessingStatus == nil { + return "" + } + return *s.ProcessingStatus +} + +// GetSBOM returns the SBOM field. +func (s *SBOM) GetSBOM() *SBOMInfo { + if s == nil { + return nil + } + return s.SBOM +} + +// GetCreationInfo returns the CreationInfo field. +func (s *SBOMInfo) GetCreationInfo() *CreationInfo { + if s == nil { + return nil + } + return s.CreationInfo +} + +// GetDataLicense returns the DataLicense field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetDataLicense() string { + if s == nil || s.DataLicense == nil { + return "" + } + return *s.DataLicense +} + +// GetDocumentNamespace returns the DocumentNamespace field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetDocumentNamespace() string { + if s == nil || s.DocumentNamespace == nil { + return "" + } + return *s.DocumentNamespace +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetSPDXID() string { + if s == nil || s.SPDXID == nil { + return "" + } + return *s.SPDXID +} + +// GetSPDXVersion returns the SPDXVersion field if it's non-nil, zero value otherwise. +func (s *SBOMInfo) GetSPDXVersion() string { + if s == nil || s.SPDXVersion == nil { + return "" + } + return *s.SPDXVersion +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetAnalysisKey() string { + if s == nil || s.AnalysisKey == nil { + return "" + } + return *s.AnalysisKey +} + +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCategory() string { + if s == nil || s.Category == nil { + return "" + } + return *s.Category +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDeletable returns the Deletable field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetDeletable() bool { + if s == nil || s.Deletable == nil { + return false + } + return *s.Deletable +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetEnvironment() string { + if s == nil || s.Environment == nil { + return "" + } + return *s.Environment +} + +// GetError returns the Error field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetError() string { + if s == nil || s.Error == nil { + return "" + } + return *s.Error +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetResultsCount returns the ResultsCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetResultsCount() int { + if s == nil || s.ResultsCount == nil { + return 0 + } + return *s.ResultsCount +} + +// GetRulesCount returns the RulesCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRulesCount() int { + if s == nil || s.RulesCount == nil { + return 0 + } + return *s.RulesCount +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetSarifID() string { + if s == nil || s.SarifID == nil { + return "" + } + return *s.SarifID +} + +// GetTool returns the Tool field. +func (s *ScanningAnalysis) GetTool() *Tool { + if s == nil { + return nil + } + return s.Tool +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetWarning returns the Warning field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetWarning() string { + if s == nil || s.Warning == nil { + return "" + } + return *s.Warning +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetCreated() Timestamp { + if s == nil || s.Created == nil { + return Timestamp{} + } + return *s.Created +} + +// GetLastModified returns the LastModified field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetLastModified() Timestamp { + if s == nil || s.LastModified == nil { + return Timestamp{} + } + return *s.LastModified +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetLocation() string { + if s == nil || s.Location == nil { + return "" + } + return *s.Location +} + +// GetResourceType returns the ResourceType field if it's non-nil, zero value otherwise. +func (s *SCIMMeta) GetResourceType() string { + if s == nil || s.ResourceType == nil { + return "" + } + return *s.ResourceType +} + +// GetItemsPerPage returns the ItemsPerPage field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetItemsPerPage() int { + if s == nil || s.ItemsPerPage == nil { + return 0 + } + return *s.ItemsPerPage +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetStartIndex() int { + if s == nil || s.StartIndex == nil { + return 0 + } + return *s.StartIndex +} + +// GetTotalResults returns the TotalResults field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedIdentities) GetTotalResults() int { + if s == nil || s.TotalResults == nil { + return 0 + } + return *s.TotalResults +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetActive() bool { + if s == nil || s.Active == nil { + return false + } + return *s.Active +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetDisplayName() string { + if s == nil || s.DisplayName == nil { + return "" + } + return *s.DisplayName +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetExternalID() string { + if s == nil || s.ExternalID == nil { + return "" + } + return *s.ExternalID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetMeta returns the Meta field. +func (s *SCIMUserAttributes) GetMeta() *SCIMMeta { + if s == nil { + return nil + } + return s.Meta +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetPrimary() bool { + if s == nil || s.Primary == nil { + return false + } + return *s.Primary +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetFormatted returns the Formatted field if it's non-nil, zero value otherwise. +func (s *SCIMUserName) GetFormatted() string { + if s == nil || s.Formatted == nil { + return "" + } + return *s.Formatted +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanning) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetHTMLURL() string { + if s == nil || s.HTMLURL == nil { + return "" + } + return *s.HTMLURL +} + +// GetLocationsURL returns the LocationsURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetLocationsURL() string { + if s == nil || s.LocationsURL == nil { + return "" + } + return *s.LocationsURL +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetNumber() int { + if s == nil || s.Number == nil { + return 0 + } + return *s.Number +} + +// GetPushProtectionBypassed returns the PushProtectionBypassed field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetPushProtectionBypassed() bool { + if s == nil || s.PushProtectionBypassed == nil { + return false + } + return *s.PushProtectionBypassed +} + +// GetPushProtectionBypassedAt returns the PushProtectionBypassedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetPushProtectionBypassedAt() Timestamp { + if s == nil || s.PushProtectionBypassedAt == nil { + return Timestamp{} + } + return *s.PushProtectionBypassedAt +} + +// GetPushProtectionBypassedBy returns the PushProtectionBypassedBy field. +func (s *SecretScanningAlert) GetPushProtectionBypassedBy() *User { + if s == nil { + return nil + } + return s.PushProtectionBypassedBy +} + +// GetRepository returns the Repository field. +func (s *SecretScanningAlert) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetResolutionComment returns the ResolutionComment field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolutionComment() string { + if s == nil || s.ResolutionComment == nil { + return "" + } + return *s.ResolutionComment +} + +// GetResolvedAt returns the ResolvedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolvedAt() Timestamp { + if s == nil || s.ResolvedAt == nil { + return Timestamp{} + } + return *s.ResolvedAt +} + +// GetResolvedBy returns the ResolvedBy field. +func (s *SecretScanningAlert) GetResolvedBy() *User { + if s == nil { + return nil + } + return s.ResolvedBy +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecret() string { + if s == nil || s.Secret == nil { + return "" + } + return *s.Secret +} + +// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecretType() string { + if s == nil || s.SecretType == nil { + return "" + } + return *s.SecretType +} + +// GetSecretTypeDisplayName returns the SecretTypeDisplayName field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecretTypeDisplayName() string { + if s == nil || s.SecretTypeDisplayName == nil { + return "" + } + return *s.SecretTypeDisplayName +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetEnterprise returns the Enterprise field. +func (s *SecretScanningAlertEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetDetails returns the Details field. +func (s *SecretScanningAlertLocation) GetDetails() *SecretScanningAlertLocationDetails { + if s == nil { + return nil + } + return s.Details +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocation) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetBlobSHA returns the BlobSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobSHA() string { + if s == nil || s.BlobSHA == nil { + return "" + } + return *s.BlobSHA +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobURL() string { + if s == nil || s.BlobURL == nil { + return "" + } + return *s.BlobURL +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitURL() string { + if s == nil || s.CommitURL == nil { + return "" + } + return *s.CommitURL +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndColumn() int { + if s == nil || s.EndColumn == nil { + return 0 + } + return *s.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndLine() int { + if s == nil || s.EndLine == nil { + return 0 + } + return *s.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetPath() string { + if s == nil || s.Path == nil { + return "" + } + return *s.Path +} + +// GetPullRequestCommentURL returns the PullRequestCommentURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetPullRequestCommentURL() string { + if s == nil || s.PullRequestCommentURL == nil { + return "" + } + return *s.PullRequestCommentURL +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartColumn() int { + if s == nil || s.StartColumn == nil { + return 0 + } + return *s.StartColumn +} + +// GetStartline returns the Startline field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartline() int { + if s == nil || s.Startline == nil { + return 0 + } + return *s.Startline +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertLocationEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertLocationEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetLocation returns the Location field. +func (s *SecretScanningAlertLocationEvent) GetLocation() *SecretScanningAlertLocation { + if s == nil { + return nil + } + return s.Location +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertLocationEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertLocationEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertLocationEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetResolutionComment returns the ResolutionComment field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetResolutionComment() string { + if s == nil || s.ResolutionComment == nil { + return "" + } + return *s.ResolutionComment +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanningPushProtection) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanningValidityChecks) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetAuthor returns the Author field. +func (s *SecurityAdvisory) GetAuthor() *User { + if s == nil { + return nil + } + return s.Author +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetClosedAt() Timestamp { + if s == nil || s.ClosedAt == nil { + return Timestamp{} + } + return *s.ClosedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetCVEID() string { + if s == nil || s.CVEID == nil { + return "" + } + return *s.CVEID +} + +// GetCVSS returns the CVSS field. +func (s *SecurityAdvisory) GetCVSS() *AdvisoryCVSS { + if s == nil { + return nil + } + return s.CVSS +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetGHSAID() string { + if s == nil || s.GHSAID == nil { + return "" + } + return *s.GHSAID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetHTMLURL() string { + if s == nil || s.HTMLURL == nil { + return "" + } + return *s.HTMLURL +} + +// GetPrivateFork returns the PrivateFork field. +func (s *SecurityAdvisory) GetPrivateFork() *Repository { + if s == nil { + return nil + } + return s.PrivateFork +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetPublishedAt() Timestamp { + if s == nil || s.PublishedAt == nil { + return Timestamp{} + } + return *s.PublishedAt +} + +// GetPublisher returns the Publisher field. +func (s *SecurityAdvisory) GetPublisher() *User { + if s == nil { + return nil + } + return s.Publisher +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSeverity() string { + if s == nil || s.Severity == nil { + return "" + } + return *s.Severity +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetSubmission returns the Submission field. +func (s *SecurityAdvisory) GetSubmission() *SecurityAdvisorySubmission { + if s == nil { + return nil + } + return s.Submission +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSummary() string { + if s == nil || s.Summary == nil { + return "" + } + return *s.Summary +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetWithdrawnAt returns the WithdrawnAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetWithdrawnAt() Timestamp { + if s == nil || s.WithdrawnAt == nil { + return Timestamp{} + } + return *s.WithdrawnAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisoryEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetEnterprise returns the Enterprise field. +func (s *SecurityAdvisoryEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecurityAdvisoryEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecurityAdvisoryEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SecurityAdvisoryEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSecurityAdvisory returns the SecurityAdvisory field. +func (s *SecurityAdvisoryEvent) GetSecurityAdvisory() *SecurityAdvisory { + if s == nil { + return nil + } + return s.SecurityAdvisory +} + +// GetSender returns the Sender field. +func (s *SecurityAdvisoryEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetAccepted returns the Accepted field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisorySubmission) GetAccepted() bool { + if s == nil || s.Accepted == nil { + return false + } + return *s.Accepted +} + +// GetAdvancedSecurity returns the AdvancedSecurity field. +func (s *SecurityAndAnalysis) GetAdvancedSecurity() *AdvancedSecurity { + if s == nil { + return nil + } + return s.AdvancedSecurity +} + +// GetDependabotSecurityUpdates returns the DependabotSecurityUpdates field. +func (s *SecurityAndAnalysis) GetDependabotSecurityUpdates() *DependabotSecurityUpdates { + if s == nil { + return nil + } + return s.DependabotSecurityUpdates +} + +// GetSecretScanning returns the SecretScanning field. +func (s *SecurityAndAnalysis) GetSecretScanning() *SecretScanning { + if s == nil { + return nil + } + return s.SecretScanning +} + +// GetSecretScanningPushProtection returns the SecretScanningPushProtection field. +func (s *SecurityAndAnalysis) GetSecretScanningPushProtection() *SecretScanningPushProtection { + if s == nil { + return nil + } + return s.SecretScanningPushProtection +} + +// GetSecretScanningValidityChecks returns the SecretScanningValidityChecks field. +func (s *SecurityAndAnalysis) GetSecretScanningValidityChecks() *SecretScanningValidityChecks { + if s == nil { + return nil + } + return s.SecretScanningValidityChecks +} + +// GetFrom returns the From field. +func (s *SecurityAndAnalysisChange) GetFrom() *SecurityAndAnalysisChangeFrom { + if s == nil { + return nil + } + return s.From +} + +// GetSecurityAndAnalysis returns the SecurityAndAnalysis field. +func (s *SecurityAndAnalysisChangeFrom) GetSecurityAndAnalysis() *SecurityAndAnalysis { + if s == nil { + return nil + } + return s.SecurityAndAnalysis +} + +// GetChanges returns the Changes field. +func (s *SecurityAndAnalysisEvent) GetChanges() *SecurityAndAnalysisChange { + if s == nil { + return nil + } + return s.Changes +} + +// GetEnterprise returns the Enterprise field. +func (s *SecurityAndAnalysisEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecurityAndAnalysisEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecurityAndAnalysisEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SecurityAndAnalysisEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSender returns the Sender field. +func (s *SecurityAndAnalysisEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (s *SelectedReposList) GetTotalCount() int { + if s == nil || s.TotalCount == nil { + return 0 + } + return *s.TotalCount +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (s *SignatureRequirementEnforcementLevelChanges) GetFrom() string { + if s == nil || s.From == nil { + return "" + } + return *s.From +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetEnabled() bool { + if s == nil || s.Enabled == nil { + return false + } + return *s.Enabled +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetPayload returns the Payload field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetPayload() string { + if s == nil || s.Payload == nil { + return "" + } + return *s.Payload +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetSignature returns the Signature field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetSignature() string { + if s == nil || s.Signature == nil { + return "" + } + return *s.Signature +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetVerified() bool { + if s == nil || s.Verified == nil { + return false + } + return *s.Verified +} + +// GetActor returns the Actor field. +func (s *Source) GetActor() *User { + if s == nil { + return nil + } + return s.Actor +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *Source) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetIssue returns the Issue field. +func (s *Source) GetIssue() *Issue { + if s == nil { + return nil + } + return s.Issue +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *Source) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Source) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetEmail() string { + if s == nil || s.Email == nil { + return "" + } + return *s.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetImportURL() string { + if s == nil || s.ImportURL == nil { + return "" + } + return *s.ImportURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteID() string { + if s == nil || s.RemoteID == nil { + return "" + } + return *s.RemoteID +} + +// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteName() string { + if s == nil || s.RemoteName == nil { + return "" + } + return *s.RemoteName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetPrivacyLevel returns the PrivacyLevel field if it's non-nil, zero value otherwise. +func (s *SponsorshipChanges) GetPrivacyLevel() string { + if s == nil || s.PrivacyLevel == nil { + return "" + } + return *s.PrivacyLevel +} + +// GetTier returns the Tier field. +func (s *SponsorshipChanges) GetTier() *SponsorshipTier { + if s == nil { + return nil + } + return s.Tier +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SponsorshipEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetChanges returns the Changes field. +func (s *SponsorshipEvent) GetChanges() *SponsorshipChanges { + if s == nil { + return nil + } + return s.Changes +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (s *SponsorshipEvent) GetEffectiveDate() string { + if s == nil || s.EffectiveDate == nil { + return "" + } + return *s.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (s *SponsorshipEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SponsorshipEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepository returns the Repository field. +func (s *SponsorshipEvent) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetSender returns the Sender field. +func (s *SponsorshipEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (s *SponsorshipTier) GetFrom() string { + if s == nil || s.From == nil { + return "" + } + return *s.From +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetKey() string { + if s == nil || s.Key == nil { + return "" + } + return *s.Key +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (s *SSHSigningKey) GetTitle() string { + if s == nil || s.Title == nil { + return "" + } + return *s.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetInstallation returns the Installation field. +func (s *StarEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrg returns the Org field. +func (s *StarEvent) GetOrg() *Organization { + if s == nil { + return nil + } + return s.Org +} + +// GetRepo returns the Repo field. +func (s *StarEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StarEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *Stargazer) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetUser returns the User field. +func (s *Stargazer) GetUser() *User { + if s == nil { + return nil + } + return s.User +} + +// GetRepository returns the Repository field. +func (s *StarredRepository) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarredRepository) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetCommit returns the Commit field. +func (s *StatusEvent) GetCommit() *RepositoryCommit { + if s == nil { + return nil + } + return s.Commit +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetContext() string { + if s == nil || s.Context == nil { + return "" + } + return *s.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetInstallation returns the Installation field. +func (s *StatusEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetOrg returns the Org field. +func (s *StatusEvent) GetOrg() *Organization { + if s == nil { + return nil + } + return s.Org +} + +// GetRepo returns the Repo field. +func (s *StatusEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StatusEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetSHA() string { + if s == nil || s.SHA == nil { + return "" + } + return *s.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetTargetURL() string { + if s == nil || s.TargetURL == nil { + return "" + } + return *s.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *Subscription) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. +func (s *Subscription) GetIgnored() bool { + if s == nil || s.Ignored == nil { + return false + } + return *s.Ignored +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *Subscription) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetRepositoryURL() string { + if s == nil || s.RepositoryURL == nil { + return "" + } + return *s.RepositoryURL +} + +// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. +func (s *Subscription) GetSubscribed() bool { + if s == nil || s.Subscribed == nil { + return false + } + return *s.Subscribed +} + +// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetThreadURL() string { + if s == nil || s.ThreadURL == nil { + return "" + } + return *s.ThreadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Tag) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Tag) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetObject returns the Object field. +func (t *Tag) GetObject() *GitObject { + if t == nil { + return nil + } + return t.Object +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tag) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTag returns the Tag field if it's non-nil, zero value otherwise. +func (t *Tag) GetTag() string { + if t == nil || t.Tag == nil { + return "" + } + return *t.Tag +} + +// GetTagger returns the Tagger field. +func (t *Tag) GetTagger() *CommitAuthor { + if t == nil { + return nil + } + return t.Tagger +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Tag) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetVerification returns the Verification field. +func (t *Tag) GetVerification() *SignatureVerification { + if t == nil { + return nil + } + return t.Verification +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TagProtection) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetPattern returns the Pattern field if it's non-nil, zero value otherwise. +func (t *TagProtection) GetPattern() string { + if t == nil || t.Pattern == nil { + return "" + } + return *t.Pattern +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetCompletedAt() Timestamp { + if t == nil || t.CompletedAt == nil { + return Timestamp{} + } + return *t.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetConclusion() string { + if t == nil || t.Conclusion == nil { + return "" + } + return *t.Conclusion +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetNumber() int64 { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStartedAt() Timestamp { + if t == nil || t.StartedAt == nil { + return Timestamp{} + } + return *t.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStatus() string { + if t == nil || t.Status == nil { + return "" + } + return *t.Status +} + +// GetAssignment returns the Assignment field if it's non-nil, zero value otherwise. +func (t *Team) GetAssignment() string { + if t == nil || t.Assignment == nil { + return "" + } + return *t.Assignment +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *Team) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *Team) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Team) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *Team) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersCount() int { + if t == nil || t.MembersCount == nil { + return 0 + } + return *t.MembersCount +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Team) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Team) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetOrganization returns the Organization field. +func (t *Team) GetOrganization() *Organization { + if t == nil { + return nil + } + return t.Organization +} + +// GetParent returns the Parent field. +func (t *Team) GetParent() *Team { + if t == nil { + return nil + } + return t.Parent +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *Team) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (t *Team) GetPermissions() map[string]bool { + if t == nil || t.Permissions == nil { + return map[string]bool{} + } + return t.Permissions +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *Team) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. +func (t *Team) GetReposCount() int { + if t == nil || t.ReposCount == nil { + return 0 + } + return *t.ReposCount +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *Team) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *Team) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Team) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetInstallation returns the Installation field. +func (t *TeamAddEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamAddEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamAddEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamAddEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamAddEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field. +func (t *TeamChange) GetDescription() *TeamDescription { + if t == nil { + return nil + } + return t.Description +} + +// GetName returns the Name field. +func (t *TeamChange) GetName() *TeamName { + if t == nil { + return nil + } + return t.Name +} + +// GetPrivacy returns the Privacy field. +func (t *TeamChange) GetPrivacy() *TeamPrivacy { + if t == nil { + return nil + } + return t.Privacy +} + +// GetRepository returns the Repository field. +func (t *TeamChange) GetRepository() *TeamRepository { + if t == nil { + return nil + } + return t.Repository +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamDescription) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetAuthor returns the Author field. +func (t *TeamDiscussion) GetAuthor() *User { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyHTML() string { + if t == nil || t.BodyHTML == nil { + return "" + } + return *t.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyVersion() string { + if t == nil || t.BodyVersion == nil { + return "" + } + return *t.BodyVersion +} + +// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsCount() int { + if t == nil || t.CommentsCount == nil { + return 0 + } + return *t.CommentsCount +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsURL() string { + if t == nil || t.CommentsURL == nil { + return "" + } + return *t.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetLastEditedAt() Timestamp { + if t == nil || t.LastEditedAt == nil { + return Timestamp{} + } + return *t.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNumber() int { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetPinned returns the Pinned field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPinned() bool { + if t == nil || t.Pinned == nil { + return false + } + return *t.Pinned +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetReactions returns the Reactions field. +func (t *TeamDiscussion) GetReactions() *Reactions { + if t == nil { + return nil + } + return t.Reactions +} + +// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTeamURL() string { + if t == nil || t.TeamURL == nil { + return "" + } + return *t.TeamURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetUpdatedAt() Timestamp { + if t == nil || t.UpdatedAt == nil { + return Timestamp{} + } + return *t.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (t *TeamEvent) GetAction() string { + if t == nil || t.Action == nil { + return "" + } + return *t.Action +} + +// GetChanges returns the Changes field. +func (t *TeamEvent) GetChanges() *TeamChange { + if t == nil { + return nil + } + return t.Changes +} + +// GetInstallation returns the Installation field. +func (t *TeamEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamName) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetFrom returns the From field. +func (t *TeamPermissions) GetFrom() *TeamPermissionsFrom { + if t == nil { + return nil + } + return t.From +} + +// GetAdmin returns the Admin field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetAdmin() bool { + if t == nil || t.Admin == nil { + return false + } + return *t.Admin +} + +// GetPull returns the Pull field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPull() bool { + if t == nil || t.Pull == nil { + return false + } + return *t.Pull +} + +// GetPush returns the Push field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPush() bool { + if t == nil || t.Push == nil { + return false + } + return *t.Push +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamPrivacy) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamProjectOptions) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions field. +func (t *TeamRepository) GetPermissions() *TeamPermissions { + if t == nil { + return nil + } + return t.Permissions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetIncludeAllBranches returns the IncludeAllBranches field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetIncludeAllBranches() bool { + if t == nil || t.IncludeAllBranches == nil { + return false + } + return *t.IncludeAllBranches +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetOwner() string { + if t == nil || t.Owner == nil { + return "" + } + return *t.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetFragment returns the Fragment field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetFragment() string { + if t == nil || t.Fragment == nil { + return "" + } + return *t.Fragment +} + +// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectType() string { + if t == nil || t.ObjectType == nil { + return "" + } + return *t.ObjectType +} + +// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectURL() string { + if t == nil || t.ObjectURL == nil { + return "" + } + return *t.ObjectURL +} + +// GetProperty returns the Property field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetProperty() string { + if t == nil || t.Property == nil { + return "" + } + return *t.Property +} + +// GetActor returns the Actor field. +func (t *Timeline) GetActor() *User { + if t == nil { + return nil + } + return t.Actor +} + +// GetAssignee returns the Assignee field. +func (t *Timeline) GetAssignee() *User { + if t == nil { + return nil + } + return t.Assignee +} + +// GetAssigner returns the Assigner field. +func (t *Timeline) GetAssigner() *User { + if t == nil { + return nil + } + return t.Assigner +} + +// GetAuthor returns the Author field. +func (t *Timeline) GetAuthor() *CommitAuthor { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *Timeline) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitID() string { + if t == nil || t.CommitID == nil { + return "" + } + return *t.CommitID +} + +// GetCommitter returns the Committer field. +func (t *Timeline) GetCommitter() *CommitAuthor { + if t == nil { + return nil + } + return t.Committer +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitURL() string { + if t == nil || t.CommitURL == nil { + return "" + } + return *t.CommitURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (t *Timeline) GetEvent() string { + if t == nil || t.Event == nil { + return "" + } + return *t.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLabel returns the Label field. +func (t *Timeline) GetLabel() *Label { + if t == nil { + return nil + } + return t.Label +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Timeline) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetMilestone returns the Milestone field. +func (t *Timeline) GetMilestone() *Milestone { + if t == nil { + return nil + } + return t.Milestone +} + +// GetPerformedViaGithubApp returns the PerformedViaGithubApp field. +func (t *Timeline) GetPerformedViaGithubApp() *App { + if t == nil { + return nil + } + return t.PerformedViaGithubApp +} + +// GetRename returns the Rename field. +func (t *Timeline) GetRename() *Rename { + if t == nil { + return nil + } + return t.Rename +} + +// GetRequestedTeam returns the RequestedTeam field. +func (t *Timeline) GetRequestedTeam() *Team { + if t == nil { + return nil + } + return t.RequestedTeam +} + +// GetRequester returns the Requester field. +func (t *Timeline) GetRequester() *User { + if t == nil { + return nil + } + return t.Requester +} + +// GetReviewer returns the Reviewer field. +func (t *Timeline) GetReviewer() *User { + if t == nil { + return nil + } + return t.Reviewer +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSource returns the Source field. +func (t *Timeline) GetSource() *Source { + if t == nil { + return nil + } + return t.Source +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (t *Timeline) GetState() string { + if t == nil || t.State == nil { + return "" + } + return *t.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSubmittedAt() Timestamp { + if t == nil || t.SubmittedAt == nil { + return Timestamp{} + } + return *t.SubmittedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetUser returns the User field. +func (t *Timeline) GetUser() *User { + if t == nil { + return nil + } + return t.User +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (t *Tool) GetGUID() string { + if t == nil || t.GUID == nil { + return "" + } + return *t.GUID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Tool) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (t *Tool) GetVersion() string { + if t == nil || t.Version == nil { + return "" + } + return *t.Version +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetCreatedBy returns the CreatedBy field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedBy() string { + if t == nil || t.CreatedBy == nil { + return "" + } + return *t.CreatedBy +} + +// GetCurated returns the Curated field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCurated() bool { + if t == nil || t.Curated == nil { + return false + } + return *t.Curated +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDisplayName() string { + if t == nil || t.DisplayName == nil { + return "" + } + return *t.DisplayName +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetFeatured() bool { + if t == nil || t.Featured == nil { + return false + } + return *t.Featured +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetScore returns the Score field. +func (t *TopicResult) GetScore() *float64 { + if t == nil { + return nil + } + return t.Score +} + +// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetShortDescription() string { + if t == nil || t.ShortDescription == nil { + return "" + } + return *t.ShortDescription +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetUpdatedAt() string { + if t == nil || t.UpdatedAt == nil { + return "" + } + return *t.UpdatedAt +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetIncompleteResults() bool { + if t == nil || t.IncompleteResults == nil { + return false + } + return *t.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetTotal() int { + if t == nil || t.Total == nil { + return 0 + } + return *t.Total +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetTimestamp() Timestamp { + if t == nil || t.Timestamp == nil { + return Timestamp{} + } + return *t.Timestamp +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetReferrer() string { + if t == nil || t.Referrer == nil { + return "" + } + return *t.Referrer +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetNewName returns the NewName field if it's non-nil, zero value otherwise. +func (t *TransferRequest) GetNewName() string { + if t == nil || t.NewName == nil { + return "" + } + return *t.NewName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tree) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTruncated returns the Truncated field if it's non-nil, zero value otherwise. +func (t *Tree) GetTruncated() bool { + if t == nil || t.Truncated == nil { + return false + } + return *t.Truncated +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetContent() string { + if t == nil || t.Content == nil { + return "" + } + return *t.Content +} + +// GetMode returns the Mode field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetMode() string { + if t == nil || t.Mode == nil { + return "" + } + return *t.Mode +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSize() int { + if t == nil || t.Size == nil { + return 0 + } + return *t.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetType() string { + if t == nil || t.Type == nil { + return "" + } + return *t.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (u *UpdateAttributeForSCIMUserOperations) GetPath() string { + if u == nil || u.Path == nil { + return "" + } + return *u.Path +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp { + if u == nil || u.CompletedAt == nil { + return Timestamp{} + } + return *u.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetConclusion() string { + if u == nil || u.Conclusion == nil { + return "" + } + return *u.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetDetailsURL() string { + if u == nil || u.DetailsURL == nil { + return "" + } + return *u.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetExternalID() string { + if u == nil || u.ExternalID == nil { + return "" + } + return *u.ExternalID +} + +// GetOutput returns the Output field. +func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput { + if u == nil { + return nil + } + return u.Output +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetStatus() string { + if u == nil || u.Status == nil { + return "" + } + return *u.Status +} + +// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationOptions) GetQuerySuite() string { + if u == nil || u.QuerySuite == nil { + return "" + } + return *u.QuerySuite +} + +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationResponse) GetRunID() int64 { + if u == nil || u.RunID == nil { + return 0 + } + return *u.RunID +} + +// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise. +func (u *UpdateDefaultSetupConfigurationResponse) GetRunURL() string { + if u == nil || u.RunURL == nil { + return "" + } + return *u.RunURL +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if u == nil || u.AllowsPublicRepositories == nil { + return false + } + return *u.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if u == nil || u.RestrictedToWorkflows == nil { + return false + } + return *u.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UpdateEnterpriseRunnerGroupRequest) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if u == nil || u.AllowsPublicRepositories == nil { + return false + } + return *u.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetRestrictedToWorkflows returns the RestrictedToWorkflows field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetRestrictedToWorkflows() bool { + if u == nil || u.RestrictedToWorkflows == nil { + return false + } + return *u.RestrictedToWorkflows +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAssignment returns the Assignment field if it's non-nil, zero value otherwise. +func (u *User) GetAssignment() string { + if u == nil || u.Assignment == nil { + return "" + } + return *u.Assignment +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *User) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetBio returns the Bio field if it's non-nil, zero value otherwise. +func (u *User) GetBio() string { + if u == nil || u.Bio == nil { + return "" + } + return *u.Bio +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (u *User) GetBlog() string { + if u == nil || u.Blog == nil { + return "" + } + return *u.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (u *User) GetCollaborators() int { + if u == nil || u.Collaborators == nil { + return 0 + } + return *u.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (u *User) GetCompany() string { + if u == nil || u.Company == nil { + return "" + } + return *u.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (u *User) GetDiskUsage() int { + if u == nil || u.DiskUsage == nil { + return 0 + } + return *u.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *User) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (u *User) GetFollowers() int { + if u == nil || u.Followers == nil { + return 0 + } + return *u.Followers +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (u *User) GetFollowing() int { + if u == nil || u.Following == nil { + return 0 + } + return *u.Following +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *User) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *User) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetHireable returns the Hireable field if it's non-nil, zero value otherwise. +func (u *User) GetHireable() bool { + if u == nil || u.Hireable == nil { + return false + } + return *u.Hireable +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (u *User) GetHTMLURL() string { + if u == nil || u.HTMLURL == nil { + return "" + } + return *u.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *User) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetInheritedFrom returns the InheritedFrom field. +func (u *User) GetInheritedFrom() *Team { + if u == nil { + return nil + } + return u.InheritedFrom +} + +// GetLdapDn returns the LdapDn field if it's non-nil, zero value otherwise. +func (u *User) GetLdapDn() string { + if u == nil || u.LdapDn == nil { + return "" + } + return *u.LdapDn +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (u *User) GetLocation() string { + if u == nil || u.Location == nil { + return "" + } + return *u.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *User) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *User) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (u *User) GetNodeID() string { + if u == nil || u.NodeID == nil { + return "" + } + return *u.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *User) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetOwnedPrivateRepos() int64 { + if u == nil || u.OwnedPrivateRepos == nil { + return 0 + } + return *u.OwnedPrivateRepos +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (u *User) GetPermissions() map[string]bool { + if u == nil || u.Permissions == nil { + return map[string]bool{} + } + return u.Permissions +} + +// GetPlan returns the Plan field. +func (u *User) GetPlan() *Plan { + if u == nil { + return nil + } + return u.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (u *User) GetPrivateGists() int { + if u == nil || u.PrivateGists == nil { + return 0 + } + return *u.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (u *User) GetPublicGists() int { + if u == nil || u.PublicGists == nil { + return 0 + } + return *u.PublicGists +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (u *User) GetPublicRepos() int { + if u == nil || u.PublicRepos == nil { + return 0 + } + return *u.PublicRepos +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *User) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise. +func (u *User) GetRoleName() string { + if u == nil || u.RoleName == nil { + return "" + } + return *u.RoleName +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *User) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *User) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *User) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (u *User) GetSuspendedAt() Timestamp { + if u == nil || u.SuspendedAt == nil { + return Timestamp{} + } + return *u.SuspendedAt +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetTotalPrivateRepos() int64 { + if u == nil || u.TotalPrivateRepos == nil { + return 0 + } + return *u.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (u *User) GetTwitterUsername() string { + if u == nil || u.TwitterUsername == nil { + return "" + } + return *u.TwitterUsername +} + +// GetTwoFactorAuthentication returns the TwoFactorAuthentication field if it's non-nil, zero value otherwise. +func (u *User) GetTwoFactorAuthentication() bool { + if u == nil || u.TwoFactorAuthentication == nil { + return false + } + return *u.TwoFactorAuthentication +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *User) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *User) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetApp returns the App field. +func (u *UserAuthorization) GetApp() *OAuthAPP { + if u == nil { + return nil + } + return u.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetFingerprint() string { + if u == nil || u.Fingerprint == nil { + return "" + } + return *u.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetHashedToken() string { + if u == nil || u.HashedToken == nil { + return "" + } + return *u.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNote() string { + if u == nil || u.Note == nil { + return "" + } + return *u.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNoteURL() string { + if u == nil || u.NoteURL == nil { + return "" + } + return *u.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetToken() string { + if u == nil || u.Token == nil { + return "" + } + return *u.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetTokenLastEight() string { + if u == nil || u.TokenLastEight == nil { + return "" + } + return *u.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (u *UserContext) GetMessage() string { + if u == nil || u.Message == nil { + return "" + } + return *u.Message +} + +// GetOcticon returns the Octicon field if it's non-nil, zero value otherwise. +func (u *UserContext) GetOcticon() string { + if u == nil || u.Octicon == nil { + return "" + } + return *u.Octicon +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetPrimary() bool { + if u == nil || u.Primary == nil { + return false + } + return *u.Primary +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVerified() bool { + if u == nil || u.Verified == nil { + return false + } + return *u.Verified +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (u *UserEvent) GetAction() string { + if u == nil || u.Action == nil { + return "" + } + return *u.Action +} + +// GetEnterprise returns the Enterprise field. +func (u *UserEvent) GetEnterprise() *Enterprise { + if u == nil { + return nil + } + return u.Enterprise +} + +// GetInstallation returns the Installation field. +func (u *UserEvent) GetInstallation() *Installation { + if u == nil { + return nil + } + return u.Installation +} + +// GetSender returns the Sender field. +func (u *UserEvent) GetSender() *User { + if u == nil { + return nil + } + return u.Sender +} + +// GetUser returns the User field. +func (u *UserEvent) GetUser() *User { + if u == nil { + return nil + } + return u.User +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLDAPDN() string { + if u == nil || u.LDAPDN == nil { + return "" + } + return *u.LDAPDN +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetCreatedAt() string { + if u == nil || u.CreatedAt == nil { + return "" + } + return *u.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetExcludeAttachments() bool { + if u == nil || u.ExcludeAttachments == nil { + return false + } + return *u.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetGUID() string { + if u == nil || u.GUID == nil { + return "" + } + return *u.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetLockRepositories() bool { + if u == nil || u.LockRepositories == nil { + return false + } + return *u.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetState() string { + if u == nil || u.State == nil { + return "" + } + return *u.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetUpdatedAt() string { + if u == nil || u.UpdatedAt == nil { + return "" + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetIncompleteResults() bool { + if u == nil || u.IncompleteResults == nil { + return false + } + return *u.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetTotal() int { + if u == nil || u.Total == nil { + return 0 + } + return *u.Total +} + +// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetAdminUsers() int { + if u == nil || u.AdminUsers == nil { + return 0 + } + return *u.AdminUsers +} + +// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetSuspendedUsers() int { + if u == nil || u.SuspendedUsers == nil { + return 0 + } + return *u.SuspendedUsers +} + +// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetTotalUsers() int { + if u == nil || u.TotalUsers == nil { + return 0 + } + return *u.TotalUsers +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (u *UserSuspendOptions) GetReason() string { + if u == nil || u.Reason == nil { + return "" + } + return *u.Reason +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetEcosystem() string { + if v == nil || v.Ecosystem == nil { + return "" + } + return *v.Ecosystem +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetName() string { + if v == nil || v.Name == nil { + return "" + } + return *v.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WatchEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WatchEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetTotal() int { + if w == nil || w.Total == nil { + return 0 + } + return *w.Total +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetAdditions() int { + if w == nil || w.Additions == nil { + return 0 + } + return *w.Additions +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetCommits() int { + if w == nil || w.Commits == nil { + return 0 + } + return *w.Commits +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetDeletions() int { + if w == nil || w.Deletions == nil { + return 0 + } + return *w.Deletions +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetBadgeURL returns the BadgeURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetBadgeURL() string { + if w == nil || w.BadgeURL == nil { + return "" + } + return *w.BadgeURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *Workflow) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (w *Workflow) GetPath() string { + if w == nil || w.Path == nil { + return "" + } + return *w.Path +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (w *Workflow) GetState() string { + if w == nil || w.State == nil { + return "" + } + return *w.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetInstallation returns the Installation field. +func (w *WorkflowDispatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowDispatchEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetRef() string { + if w == nil || w.Ref == nil { + return "" + } + return *w.Ref +} + +// GetRepo returns the Repo field. +func (w *WorkflowDispatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowDispatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetWorkflow() string { + if w == nil || w.Workflow == nil { + return "" + } + return *w.Workflow +} + +// GetCheckRunURL returns the CheckRunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCheckRunURL() string { + if w == nil || w.CheckRunURL == nil { + return "" + } + return *w.CheckRunURL +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCompletedAt() Timestamp { + if w == nil || w.CompletedAt == nil { + return Timestamp{} + } + return *w.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHeadBranch() string { + if w == nil || w.HeadBranch == nil { + return "" + } + return *w.HeadBranch +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetRunAttempt returns the RunAttempt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunAttempt() int64 { + if w == nil || w.RunAttempt == nil { + return 0 + } + return *w.RunAttempt +} + +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunID() int64 { + if w == nil || w.RunID == nil { + return 0 + } + return *w.RunID +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupID() int64 { + if w == nil || w.RunnerGroupID == nil { + return 0 + } + return *w.RunnerGroupID +} + +// GetRunnerGroupName returns the RunnerGroupName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupName() string { + if w == nil || w.RunnerGroupName == nil { + return "" + } + return *w.RunnerGroupName +} + +// GetRunnerID returns the RunnerID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerID() int64 { + if w == nil || w.RunnerID == nil { + return 0 + } + return *w.RunnerID +} + +// GetRunnerName returns the RunnerName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerName() string { + if w == nil || w.RunnerName == nil { + return "" + } + return *w.RunnerName +} + +// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunURL() string { + if w == nil || w.RunURL == nil { + return "" + } + return *w.RunURL +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStartedAt() Timestamp { + if w == nil || w.StartedAt == nil { + return Timestamp{} + } + return *w.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetWorkflowName returns the WorkflowName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetWorkflowName() string { + if w == nil || w.WorkflowName == nil { + return "" + } + return *w.WorkflowName +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowJobEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetDeployment returns the Deployment field. +func (w *WorkflowJobEvent) GetDeployment() *Deployment { + if w == nil { + return nil + } + return w.Deployment +} + +// GetInstallation returns the Installation field. +func (w *WorkflowJobEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowJobEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowJobEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowJobEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflowJob returns the WorkflowJob field. +func (w *WorkflowJobEvent) GetWorkflowJob() *WorkflowJob { + if w == nil { + return nil + } + return w.WorkflowJob +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetEnvironment() string { + if w == nil || w.Environment == nil { + return "" + } + return *w.Environment +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJobRun) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetActor returns the Actor field. +func (w *WorkflowRun) GetActor() *User { + if w == nil { + return nil + } + return w.Actor +} + +// GetArtifactsURL returns the ArtifactsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetArtifactsURL() string { + if w == nil || w.ArtifactsURL == nil { + return "" + } + return *w.ArtifactsURL +} + +// GetCancelURL returns the CancelURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCancelURL() string { + if w == nil || w.CancelURL == nil { + return "" + } + return *w.CancelURL +} + +// GetCheckSuiteID returns the CheckSuiteID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteID() int64 { + if w == nil || w.CheckSuiteID == nil { + return 0 + } + return *w.CheckSuiteID +} + +// GetCheckSuiteNodeID returns the CheckSuiteNodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteNodeID() string { + if w == nil || w.CheckSuiteNodeID == nil { + return "" + } + return *w.CheckSuiteNodeID +} + +// GetCheckSuiteURL returns the CheckSuiteURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteURL() string { + if w == nil || w.CheckSuiteURL == nil { + return "" + } + return *w.CheckSuiteURL +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetDisplayTitle returns the DisplayTitle field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetDisplayTitle() string { + if w == nil || w.DisplayTitle == nil { + return "" + } + return *w.DisplayTitle +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetEvent() string { + if w == nil || w.Event == nil { + return "" + } + return *w.Event +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadBranch() string { + if w == nil || w.HeadBranch == nil { + return "" + } + return *w.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (w *WorkflowRun) GetHeadCommit() *HeadCommit { + if w == nil { + return nil + } + return w.HeadCommit +} + +// GetHeadRepository returns the HeadRepository field. +func (w *WorkflowRun) GetHeadRepository() *Repository { + if w == nil { + return nil + } + return w.HeadRepository +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetJobsURL returns the JobsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetJobsURL() string { + if w == nil || w.JobsURL == nil { + return "" + } + return *w.JobsURL +} + +// GetLogsURL returns the LogsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetLogsURL() string { + if w == nil || w.LogsURL == nil { + return "" + } + return *w.LogsURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetPath() string { + if w == nil || w.Path == nil { + return "" + } + return *w.Path +} + +// GetPreviousAttemptURL returns the PreviousAttemptURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetPreviousAttemptURL() string { + if w == nil || w.PreviousAttemptURL == nil { + return "" + } + return *w.PreviousAttemptURL +} + +// GetRepository returns the Repository field. +func (w *WorkflowRun) GetRepository() *Repository { + if w == nil { + return nil + } + return w.Repository +} + +// GetRerunURL returns the RerunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRerunURL() string { + if w == nil || w.RerunURL == nil { + return "" + } + return *w.RerunURL +} + +// GetRunAttempt returns the RunAttempt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunAttempt() int { + if w == nil || w.RunAttempt == nil { + return 0 + } + return *w.RunAttempt +} + +// GetRunNumber returns the RunNumber field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunNumber() int { + if w == nil || w.RunNumber == nil { + return 0 + } + return *w.RunNumber +} + +// GetRunStartedAt returns the RunStartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunStartedAt() Timestamp { + if w == nil || w.RunStartedAt == nil { + return Timestamp{} + } + return *w.RunStartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetTriggeringActor returns the TriggeringActor field. +func (w *WorkflowRun) GetTriggeringActor() *User { + if w == nil { + return nil + } + return w.TriggeringActor +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetWorkflowID returns the WorkflowID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowID() int64 { + if w == nil || w.WorkflowID == nil { + return 0 + } + return *w.WorkflowID +} + +// GetWorkflowURL returns the WorkflowURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowURL() string { + if w == nil || w.WorkflowURL == nil { + return "" + } + return *w.WorkflowURL +} + +// GetExcludePullRequests returns the ExcludePullRequests field if it's non-nil, zero value otherwise. +func (w *WorkflowRunAttemptOptions) GetExcludePullRequests() bool { + if w == nil || w.ExcludePullRequests == nil { + return false + } + return *w.ExcludePullRequests +} + +// GetJobs returns the Jobs field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetJobs() int { + if w == nil || w.Jobs == nil { + return 0 + } + return *w.Jobs +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowRunEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WorkflowRunEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowRunEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowRunEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowRunEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field. +func (w *WorkflowRunEvent) GetWorkflow() *Workflow { + if w == nil { + return nil + } + return w.Workflow +} + +// GetWorkflowRun returns the WorkflowRun field. +func (w *WorkflowRunEvent) GetWorkflowRun() *WorkflowRun { + if w == nil { + return nil + } + return w.WorkflowRun +} + +// GetDurationMS returns the DurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetDurationMS() int64 { + if w == nil || w.DurationMS == nil { + return 0 + } + return *w.DurationMS +} + +// GetJobID returns the JobID field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetJobID() int { + if w == nil || w.JobID == nil { + return 0 + } + return *w.JobID +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *WorkflowRuns) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowRunUsage) GetBillable() *WorkflowRunBillMap { + if w == nil { + return nil + } + return w.Billable +} + +// GetRunDurationMS returns the RunDurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunUsage) GetRunDurationMS() int64 { + if w == nil || w.RunDurationMS == nil { + return 0 + } + return *w.RunDurationMS +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *Workflows) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowUsage) GetBillable() *WorkflowBillMap { + if w == nil { + return nil + } + return w.Billable +} diff --git a/vendor/github.com/google/go-github/v68/github/github.go b/vendor/github.com/google/go-github/v68/github/github.go new file mode 100644 index 00000000..4e5a33c6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/github.go @@ -0,0 +1,1618 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen-accessors.go +//go:generate go run gen-stringify-test.go +//go:generate ../script/metadata.sh update-go + +package github + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/google/go-querystring/query" +) + +const ( + Version = "v68.0.0" + + defaultAPIVersion = "2022-11-28" + defaultBaseURL = "https://api.github.com/" + defaultUserAgent = "go-github" + "/" + Version + uploadBaseURL = "https://uploads.github.com/" + + headerAPIVersion = "X-Github-Api-Version" + headerRateLimit = "X-Ratelimit-Limit" + headerRateRemaining = "X-Ratelimit-Remaining" + headerRateReset = "X-Ratelimit-Reset" + headerOTP = "X-Github-Otp" + headerRetryAfter = "Retry-After" + + headerTokenExpiration = "Github-Authentication-Token-Expiration" + + mediaTypeV3 = "application/vnd.github.v3+json" + defaultMediaType = "application/octet-stream" + mediaTypeV3SHA = "application/vnd.github.v3.sha" + mediaTypeV3Diff = "application/vnd.github.v3.diff" + mediaTypeV3Patch = "application/vnd.github.v3.patch" + mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" + mediaTypeIssueImportAPI = "application/vnd.github.golden-comet-preview+json" + + // Media Type values to access preview APIs + // These media types will be added to the API request as headers + // and used to enable particular features on GitHub API that are still in preview. + // After some time, specific media types will be promoted (to a "stable" state). + // From then on, the preview headers are not required anymore to activate the additional + // feature on GitHub.com's API. However, this API header might still be needed for users + // to run a GitHub Enterprise Server on-premise. + // It's not uncommon for GitHub Enterprise Server customers to run older versions which + // would probably rely on the preview headers for some time. + // While the header promotion is going out for GitHub.com, it may be some time before it + // even arrives in GitHub Enterprise Server. + // We keep those preview headers around to avoid breaking older GitHub Enterprise Server + // versions. Additionally, non-functional (preview) headers don't create any side effects + // on GitHub Cloud version. + // + // See https://github.com/google/go-github/pull/2125 for full context. + + // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ + mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/ + mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" + + // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ + mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" + + // https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/ + mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json" + + // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ + mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" + + // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ + mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" + + // https://developer.github.com/changes/2016-09-14-projects-api/ + mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" + + // https://developer.github.com/changes/2017-01-05-commit-search-api/ + mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" + + // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ + mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" + + // https://developer.github.com/changes/2017-05-23-coc-api/ + mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" + + // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ + mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" + + // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ + mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" + + // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/ + mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json" + + // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/ + mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview" + + // https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/ + mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json" + + // https://developer.github.com/changes/2018-09-05-project-card-events/ + mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json" + + // https://developer.github.com/changes/2018-12-18-interactions-preview/ + mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json" + + // https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/ + mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json" + + // https://developer.github.com/changes/2019-04-24-vulnerability-alerts/ + mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json" + + // https://developer.github.com/changes/2019-05-29-update-branch-api/ + mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json" + + // https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/ + mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json" + + // https://docs.github.com/rest/previews/#repository-creation-permissions + mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json" + + // https://docs.github.com/rest/previews/#create-and-use-repository-templates + mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json" + + // https://developer.github.com/changes/2019-10-03-multi-line-comments/ + mediaTypeMultiLineCommentsPreview = "application/vnd.github.comfort-fade-preview+json" + + // https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/ + mediaTypeOAuthAppPreview = "application/vnd.github.doctor-strange-preview+json" + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/ + mediaTypeRepositoryVisibilityPreview = "application/vnd.github.nebula-preview+json" + + // https://developer.github.com/changes/2018-12-10-content-attachments-api/ + mediaTypeContentAttachmentsPreview = "application/vnd.github.corsair-preview+json" +) + +var errNonNilContext = errors.New("context must be non-nil") + +// A Client manages communication with the GitHub API. +type Client struct { + clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. + client *http.Client // HTTP client used to communicate with the API. + + // Base URL for API requests. Defaults to the public GitHub API, but can be + // set to a domain endpoint to use with GitHub Enterprise. BaseURL should + // always be specified with a trailing slash. + BaseURL *url.URL + + // Base URL for uploading files. + UploadURL *url.URL + + // User agent used when communicating with the GitHub API. + UserAgent string + + rateMu sync.Mutex + rateLimits [Categories]Rate // Rate limits for the client as determined by the most recent API calls. + secondaryRateLimitReset time.Time // Secondary rate limit reset for the client as determined by the most recent API calls. + + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // Services used for talking to different parts of the GitHub API. + Actions *ActionsService + Activity *ActivityService + Admin *AdminService + Apps *AppsService + Authorizations *AuthorizationsService + Billing *BillingService + Checks *ChecksService + CodeScanning *CodeScanningService + CodesOfConduct *CodesOfConductService + Codespaces *CodespacesService + Copilot *CopilotService + Dependabot *DependabotService + DependencyGraph *DependencyGraphService + Emojis *EmojisService + Enterprise *EnterpriseService + Gists *GistsService + Git *GitService + Gitignores *GitignoresService + Interactions *InteractionsService + IssueImport *IssueImportService + Issues *IssuesService + Licenses *LicensesService + Markdown *MarkdownService + Marketplace *MarketplaceService + Meta *MetaService + Migrations *MigrationService + Organizations *OrganizationsService + PullRequests *PullRequestsService + RateLimit *RateLimitService + Reactions *ReactionsService + Repositories *RepositoriesService + SCIM *SCIMService + Search *SearchService + SecretScanning *SecretScanningService + SecurityAdvisories *SecurityAdvisoriesService + Teams *TeamsService + Users *UsersService +} + +type service struct { + client *Client +} + +// Client returns the http.Client used by this GitHub client. +// This should only be used for requests to the GitHub API because +// request headers will contain an authorization token. +func (c *Client) Client() *http.Client { + c.clientMu.Lock() + defer c.clientMu.Unlock() + clientCopy := *c.client + return &clientCopy +} + +// ListOptions specifies the optional parameters to various List methods that +// support offset pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` +} + +// ListCursorOptions specifies the optional parameters to various List methods that +// support cursor pagination. +type ListCursorOptions struct { + // For paginated result sets, page of results to retrieve. + Page string `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` + + // For paginated result sets, the number of results per page (max 100), starting from the first matching result. + // This parameter must not be used in combination with last. + First int `url:"first,omitempty"` + + // For paginated result sets, the number of results per page (max 100), starting from the last matching result. + // This parameter must not be used in combination with first. + Last int `url:"last,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events after this cursor. + After string `url:"after,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events before this cursor. + Before string `url:"before,omitempty"` + + // A cursor, as given in the Link header. If specified, the query continues the search using this cursor. + Cursor string `url:"cursor,omitempty"` +} + +// UploadOptions specifies the parameters to methods that support uploads. +type UploadOptions struct { + Name string `url:"name,omitempty"` + Label string `url:"label,omitempty"` + MediaType string `url:"-"` +} + +// RawType represents type of raw format of a request instead of JSON. +type RawType uint8 + +const ( + // Diff format. + Diff RawType = 1 + iota + // Patch format. + Patch +) + +// RawOptions specifies parameters when user wants to get raw format of +// a response instead of JSON. +type RawOptions struct { + Type RawType +} + +// addOptions adds the parameters in opts as URL query parameters to s. opts +// must be a struct whose fields may contain "url" tags. +func addOptions(s string, opts interface{}) (string, error) { + v := reflect.ValueOf(opts) + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + u, err := url.Parse(s) + if err != nil { + return s, err + } + + qs, err := query.Values(opts) + if err != nil { + return s, err + } + + u.RawQuery = qs.Encode() + return u.String(), nil +} + +// NewClient returns a new GitHub API client. If a nil httpClient is +// provided, a new http.Client will be used. To use API methods which require +// authentication, either use Client.WithAuthToken or provide NewClient with +// an http.Client that will perform the authentication for you (such as that +// provided by the golang.org/x/oauth2 library). +func NewClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = &http.Client{} + } + httpClient2 := *httpClient + c := &Client{client: &httpClient2} + c.initialize() + return c +} + +// WithAuthToken returns a copy of the client configured to use the provided token for the Authorization header. +func (c *Client) WithAuthToken(token string) *Client { + c2 := c.copy() + defer c2.initialize() + transport := c2.client.Transport + if transport == nil { + transport = http.DefaultTransport + } + c2.client.Transport = roundTripperFunc( + func(req *http.Request) (*http.Response, error) { + req = req.Clone(req.Context()) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + return transport.RoundTrip(req) + }, + ) + return c2 +} + +// WithEnterpriseURLs returns a copy of the client configured to use the provided base and +// upload URLs. If the base URL does not have the suffix "/api/v3/", it will be added +// automatically. If the upload URL does not have the suffix "/api/uploads", it will be +// added automatically. +// +// Note that WithEnterpriseURLs is a convenience helper only; +// its behavior is equivalent to setting the BaseURL and UploadURL fields. +// +// Another important thing is that by default, the GitHub Enterprise URL format +// should be http(s)://[hostname]/api/v3/ or you will always receive the 406 status code. +// The upload URL format should be http(s)://[hostname]/api/uploads/. +func (c *Client) WithEnterpriseURLs(baseURL, uploadURL string) (*Client, error) { + c2 := c.copy() + defer c2.initialize() + var err error + c2.BaseURL, err = url.Parse(baseURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(c2.BaseURL.Path, "/") { + c2.BaseURL.Path += "/" + } + if !strings.HasSuffix(c2.BaseURL.Path, "/api/v3/") && + !strings.HasPrefix(c2.BaseURL.Host, "api.") && + !strings.Contains(c2.BaseURL.Host, ".api.") { + c2.BaseURL.Path += "api/v3/" + } + + c2.UploadURL, err = url.Parse(uploadURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(c2.UploadURL.Path, "/") { + c2.UploadURL.Path += "/" + } + if !strings.HasSuffix(c2.UploadURL.Path, "/api/uploads/") && + !strings.HasPrefix(c2.UploadURL.Host, "api.") && + !strings.Contains(c2.UploadURL.Host, ".api.") { + c2.UploadURL.Path += "api/uploads/" + } + return c2, nil +} + +// initialize sets default values and initializes services. +func (c *Client) initialize() { + if c.client == nil { + c.client = &http.Client{} + } + if c.BaseURL == nil { + c.BaseURL, _ = url.Parse(defaultBaseURL) + } + if c.UploadURL == nil { + c.UploadURL, _ = url.Parse(uploadBaseURL) + } + if c.UserAgent == "" { + c.UserAgent = defaultUserAgent + } + c.common.client = c + c.Actions = (*ActionsService)(&c.common) + c.Activity = (*ActivityService)(&c.common) + c.Admin = (*AdminService)(&c.common) + c.Apps = (*AppsService)(&c.common) + c.Authorizations = (*AuthorizationsService)(&c.common) + c.Billing = (*BillingService)(&c.common) + c.Checks = (*ChecksService)(&c.common) + c.CodeScanning = (*CodeScanningService)(&c.common) + c.Codespaces = (*CodespacesService)(&c.common) + c.CodesOfConduct = (*CodesOfConductService)(&c.common) + c.Copilot = (*CopilotService)(&c.common) + c.Dependabot = (*DependabotService)(&c.common) + c.DependencyGraph = (*DependencyGraphService)(&c.common) + c.Emojis = (*EmojisService)(&c.common) + c.Enterprise = (*EnterpriseService)(&c.common) + c.Gists = (*GistsService)(&c.common) + c.Git = (*GitService)(&c.common) + c.Gitignores = (*GitignoresService)(&c.common) + c.Interactions = (*InteractionsService)(&c.common) + c.IssueImport = (*IssueImportService)(&c.common) + c.Issues = (*IssuesService)(&c.common) + c.Licenses = (*LicensesService)(&c.common) + c.Markdown = (*MarkdownService)(&c.common) + c.Marketplace = &MarketplaceService{client: c} + c.Meta = (*MetaService)(&c.common) + c.Migrations = (*MigrationService)(&c.common) + c.Organizations = (*OrganizationsService)(&c.common) + c.PullRequests = (*PullRequestsService)(&c.common) + c.RateLimit = (*RateLimitService)(&c.common) + c.Reactions = (*ReactionsService)(&c.common) + c.Repositories = (*RepositoriesService)(&c.common) + c.SCIM = (*SCIMService)(&c.common) + c.Search = (*SearchService)(&c.common) + c.SecretScanning = (*SecretScanningService)(&c.common) + c.SecurityAdvisories = (*SecurityAdvisoriesService)(&c.common) + c.Teams = (*TeamsService)(&c.common) + c.Users = (*UsersService)(&c.common) +} + +// copy returns a copy of the current client. It must be initialized before use. +func (c *Client) copy() *Client { + c.clientMu.Lock() + // can't use *c here because that would copy mutexes by value. + clone := Client{ + client: &http.Client{}, + UserAgent: c.UserAgent, + BaseURL: c.BaseURL, + UploadURL: c.UploadURL, + secondaryRateLimitReset: c.secondaryRateLimitReset, + } + c.clientMu.Unlock() + if c.client != nil { + clone.client.Transport = c.client.Transport + clone.client.CheckRedirect = c.client.CheckRedirect + clone.client.Jar = c.client.Jar + clone.client.Timeout = c.client.Timeout + } + c.rateMu.Lock() + copy(clone.rateLimits[:], c.rateLimits[:]) + c.rateMu.Unlock() + return &clone +} + +// NewClientWithEnvProxy enhances NewClient with the HttpProxy env. +func NewClientWithEnvProxy() *Client { + return NewClient(&http.Client{Transport: &http.Transport{Proxy: http.ProxyFromEnvironment}}) +} + +// NewTokenClient returns a new GitHub API client authenticated with the provided token. +// Deprecated: Use NewClient(nil).WithAuthToken(token) instead. +func NewTokenClient(_ context.Context, token string) *Client { + // This always returns a nil error. + return NewClient(nil).WithAuthToken(token) +} + +// NewEnterpriseClient returns a new GitHub API client with provided +// base URL and upload URL (often is your GitHub Enterprise hostname). +// +// Deprecated: Use NewClient(httpClient).WithEnterpriseURLs(baseURL, uploadURL) instead. +func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { + return NewClient(httpClient).WithEnterpriseURLs(baseURL, uploadURL) +} + +// RequestOption represents an option that can modify an http.Request. +type RequestOption func(req *http.Request) + +// WithVersion overrides the GitHub v3 API version for this individual request. +// For more information, see: +// https://github.blog/2022-11-28-to-infinity-and-beyond-enabling-the-future-of-githubs-rest-api-with-api-versioning/ +func WithVersion(version string) RequestOption { + return func(req *http.Request) { + req.Header.Set(headerAPIVersion, version) + } +} + +// NewRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. If +// specified, the value pointed to by body is JSON encoded and included as the +// request body. +func (c *Client) NewRequest(method, urlStr string, body interface{}, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + var buf io.ReadWriter + if body != nil { + buf = &bytes.Buffer{} + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(body) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, u.String(), buf) + if err != nil { + return nil, err + } + + if body != nil { + req.Header.Set("Content-Type", "application/json") + } + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// NewFormRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. +// Body is sent with Content-Type: application/x-www-form-urlencoded. +func (c *Client) NewFormRequest(urlStr string, body io.Reader, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodPost, u.String(), body) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// NewUploadRequest creates an upload request. A relative URL can be provided in +// urlStr, in which case it is resolved relative to the UploadURL of the Client. +// Relative URLs should always be specified without a preceding slash. +func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string, opts ...RequestOption) (*http.Request, error) { + if !strings.HasSuffix(c.UploadURL.Path, "/") { + return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) + } + u, err := c.UploadURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", u.String(), reader) + if err != nil { + return nil, err + } + + req.ContentLength = size + + if mediaType == "" { + mediaType = defaultMediaType + } + req.Header.Set("Content-Type", mediaType) + req.Header.Set("Accept", mediaTypeV3) + req.Header.Set("User-Agent", c.UserAgent) + req.Header.Set(headerAPIVersion, defaultAPIVersion) + + for _, opt := range opts { + opt(req) + } + + return req, nil +} + +// Response is a GitHub API response. This wraps the standard http.Response +// returned from GitHub and provides convenient access to things like +// pagination links. +type Response struct { + *http.Response + + // These fields provide the page values for paginating through a set of + // results. Any or all of these may be set to the zero value for + // responses that are not part of a paginated set, or for which there + // are no additional pages. + // + // These fields support what is called "offset pagination" and should + // be used with the ListOptions struct. + NextPage int + PrevPage int + FirstPage int + LastPage int + + // Additionally, some APIs support "cursor pagination" instead of offset. + // This means that a token points directly to the next record which + // can lead to O(1) performance compared to O(n) performance provided + // by offset pagination. + // + // For APIs that support cursor pagination (such as + // TeamsService.ListIDPGroupsInOrganization), the following field + // will be populated to point to the next page. + // + // To use this token, set ListCursorOptions.Page to this value before + // calling the endpoint again. + NextPageToken string + + // For APIs that support cursor pagination, such as RepositoriesService.ListHookDeliveries, + // the following field will be populated to point to the next page. + // Set ListCursorOptions.Cursor to this value when calling the endpoint again. + Cursor string + + // For APIs that support before/after pagination, such as OrganizationsService.AuditLog. + Before string + After string + + // Explicitly specify the Rate type so Rate's String() receiver doesn't + // propagate to Response. + Rate Rate + + // token's expiration date. Timestamp is 0001-01-01 when token doesn't expire. + // So it is valid for TokenExpiration.Equal(Timestamp{}) or TokenExpiration.Time.After(time.Now()) + TokenExpiration Timestamp +} + +// newResponse creates a new Response for the provided http.Response. +// r must not be nil. +func newResponse(r *http.Response) *Response { + response := &Response{Response: r} + response.populatePageValues() + response.Rate = parseRate(r) + response.TokenExpiration = parseTokenExpiration(r) + return response +} + +// populatePageValues parses the HTTP Link response headers and populates the +// various pagination link values in the Response. +func (r *Response) populatePageValues() { + if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { + for _, link := range strings.Split(links[0], ",") { + segments := strings.Split(strings.TrimSpace(link), ";") + + // link must at least have href and rel + if len(segments) < 2 { + continue + } + + // ensure href is properly formatted + if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { + continue + } + + // try to pull out page parameter + url, err := url.Parse(segments[0][1 : len(segments[0])-1]) + if err != nil { + continue + } + + q := url.Query() + + if cursor := q.Get("cursor"); cursor != "" { + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + r.Cursor = cursor + } + } + + continue + } + + page := q.Get("page") + since := q.Get("since") + before := q.Get("before") + after := q.Get("after") + + if page == "" && before == "" && after == "" && since == "" { + continue + } + + if since != "" && page == "" { + page = since + } + + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + if r.NextPage, err = strconv.Atoi(page); err != nil { + r.NextPageToken = page + } + r.After = after + case `rel="prev"`: + r.PrevPage, _ = strconv.Atoi(page) + r.Before = before + case `rel="first"`: + r.FirstPage, _ = strconv.Atoi(page) + case `rel="last"`: + r.LastPage, _ = strconv.Atoi(page) + } + } + } + } +} + +// parseRate parses the rate related headers. +func parseRate(r *http.Response) Rate { + var rate Rate + if limit := r.Header.Get(headerRateLimit); limit != "" { + rate.Limit, _ = strconv.Atoi(limit) + } + if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + rate.Remaining, _ = strconv.Atoi(remaining) + } + if reset := r.Header.Get(headerRateReset); reset != "" { + if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { + rate.Reset = Timestamp{time.Unix(v, 0)} + } + } + return rate +} + +// parseSecondaryRate parses the secondary rate related headers, +// and returns the time to retry after. +func parseSecondaryRate(r *http.Response) *time.Duration { + // According to GitHub support, the "Retry-After" header value will be + // an integer which represents the number of seconds that one should + // wait before resuming making requests. + if v := r.Header.Get(headerRetryAfter); v != "" { + retryAfterSeconds, _ := strconv.ParseInt(v, 10, 64) // Error handling is noop. + retryAfter := time.Duration(retryAfterSeconds) * time.Second + return &retryAfter + } + + // According to GitHub support, endpoints might return x-ratelimit-reset instead, + // as an integer which represents the number of seconds since epoch UTC, + // representing the time to resume making requests. + if v := r.Header.Get(headerRateReset); v != "" { + secondsSinceEpoch, _ := strconv.ParseInt(v, 10, 64) // Error handling is noop. + retryAfter := time.Until(time.Unix(secondsSinceEpoch, 0)) + return &retryAfter + } + + return nil +} + +// parseTokenExpiration parses the TokenExpiration related headers. +// Returns 0001-01-01 if the header is not defined or could not be parsed. +func parseTokenExpiration(r *http.Response) Timestamp { + if v := r.Header.Get(headerTokenExpiration); v != "" { + if t, err := time.Parse("2006-01-02 15:04:05 MST", v); err == nil { + return Timestamp{t.Local()} + } + // Some tokens include the timezone offset instead of the timezone. + // https://github.com/google/go-github/issues/2649 + if t, err := time.Parse("2006-01-02 15:04:05 -0700", v); err == nil { + return Timestamp{t.Local()} + } + } + return Timestamp{} // 0001-01-01 00:00:00 +} + +type requestContext uint8 + +const ( + bypassRateLimitCheck requestContext = iota + SleepUntilPrimaryRateLimitResetWhenRateLimited +) + +// BareDo sends an API request and lets you handle the api response. If an error +// or API Error occurs, the error will contain more information. Otherwise you +// are supposed to read and close the response's Body. If rate limit is exceeded +// and reset time is in the future, BareDo returns *RateLimitError immediately +// without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error) { + if ctx == nil { + return nil, errNonNilContext + } + + req = withContext(ctx, req) + + rateLimitCategory := GetRateLimitCategory(req.Method, req.URL.Path) + + if bypass := ctx.Value(bypassRateLimitCheck); bypass == nil { + // If we've hit rate limit, don't make further requests before Reset time. + if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { + return &Response{ + Response: err.Response, + Rate: err.Rate, + }, err + } + // If we've hit a secondary rate limit, don't make further requests before Retry After. + if err := c.checkSecondaryRateLimitBeforeDo(req); err != nil { + return &Response{ + Response: err.Response, + }, err + } + } + + resp, err := c.client.Do(req) + var response *Response + if resp != nil { + response = newResponse(resp) + } + + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return response, ctx.Err() + default: + } + + // If the error type is *url.Error, sanitize its URL before returning. + if e, ok := err.(*url.Error); ok { + if url, err := url.Parse(e.URL); err == nil { + e.URL = sanitizeURL(url).String() + return response, e + } + } + + return response, err + } + + // Don't update the rate limits if this was a cached response. + // X-From-Cache is set by https://github.com/gregjones/httpcache + if response.Header.Get("X-From-Cache") == "" { + c.rateMu.Lock() + c.rateLimits[rateLimitCategory] = response.Rate + c.rateMu.Unlock() + } + + err = CheckResponse(resp) + if err != nil { + defer resp.Body.Close() + // Special case for AcceptedErrors. If an AcceptedError + // has been encountered, the response's payload will be + // added to the AcceptedError and returned. + // + // Issue #1022 + aerr, ok := err.(*AcceptedError) + if ok { + b, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return response, readErr + } + + aerr.Raw = b + err = aerr + } + + rateLimitError, ok := err.(*RateLimitError) + if ok && req.Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil { + if err := sleepUntilResetWithBuffer(req.Context(), rateLimitError.Rate.Reset.Time); err != nil { + return response, err + } + // retry the request once when the rate limit has reset + return c.BareDo(context.WithValue(req.Context(), SleepUntilPrimaryRateLimitResetWhenRateLimited, nil), req) + } + + // Update the secondary rate limit if we hit it. + rerr, ok := err.(*AbuseRateLimitError) + if ok && rerr.RetryAfter != nil { + c.rateMu.Lock() + c.secondaryRateLimitReset = time.Now().Add(*rerr.RetryAfter) + c.rateMu.Unlock() + } + } + return response, err +} + +// Do sends an API request and returns the API response. The API response is +// JSON decoded and stored in the value pointed to by v, or returned as an +// error if an API error has occurred. If v implements the io.Writer interface, +// the raw response body will be written to v, without attempting to first +// decode it. If v is nil, and no error happens, the response is returned as is. +// If rate limit is exceeded and reset time is in the future, Do returns +// *RateLimitError immediately without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it +// is canceled or times out, ctx.Err() will be returned. +func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { + resp, err := c.BareDo(ctx, req) + if err != nil { + return resp, err + } + defer resp.Body.Close() + + switch v := v.(type) { + case nil: + case io.Writer: + _, err = io.Copy(v, resp.Body) + default: + decErr := json.NewDecoder(resp.Body).Decode(v) + if decErr == io.EOF { + decErr = nil // ignore EOF errors caused by empty response body + } + if decErr != nil { + err = decErr + } + } + return resp, err +} + +// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *RateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory RateLimitCategory) *RateLimitError { + c.rateMu.Lock() + rate := c.rateLimits[rateLimitCategory] + c.rateMu.Unlock() + if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("")), + } + + if req.Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil { + if err := sleepUntilResetWithBuffer(req.Context(), rate.Reset.Time); err == nil { + return nil + } + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("Context cancelled while waiting for rate limit to reset until %v, not making remote request.", rate.Reset.Time), + } + } + + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), + } + } + + return nil +} + +// checkSecondaryRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *AbuseRateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkSecondaryRateLimitBeforeDo(req *http.Request) *AbuseRateLimitError { + c.rateMu.Lock() + secondary := c.secondaryRateLimitReset + c.rateMu.Unlock() + if !secondary.IsZero() && time.Now().Before(secondary) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("")), + } + + retryAfter := time.Until(secondary) + return &AbuseRateLimitError{ + Response: resp, + Message: fmt.Sprintf("API secondary rate limit exceeded until %v, not making remote request.", secondary), + RetryAfter: &retryAfter, + } + } + + return nil +} + +// compareHTTPResponse returns whether two http.Response objects are equal or not. +// Currently, only StatusCode is checked. This function is used when implementing the +// Is(error) bool interface for the custom error types in this package. +func compareHTTPResponse(r1, r2 *http.Response) bool { + if r1 == nil && r2 == nil { + return true + } + + if r1 != nil && r2 != nil { + return r1.StatusCode == r2.StatusCode + } + return false +} + +/* +An ErrorResponse reports one or more errors caused by an API request. + +GitHub API docs: https://docs.github.com/rest/#client-errors +*/ +type ErrorResponse struct { + Response *http.Response `json:"-"` // HTTP response that caused this error + Message string `json:"message"` // error message + Errors []Error `json:"errors"` // more detail on individual errors + // Block is only populated on certain types of errors such as code 451. + Block *ErrorBlock `json:"block,omitempty"` + // Most errors will also include a documentation_url field pointing + // to some content that might help you resolve the error, see + // https://docs.github.com/rest/#client-errors + DocumentationURL string `json:"documentation_url,omitempty"` +} + +// ErrorBlock contains a further explanation for the reason of an error. +// See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ +// for more information. +type ErrorBlock struct { + Reason string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (r *ErrorResponse) Error() string { + if r.Response != nil && r.Response.Request != nil { + return fmt.Sprintf("%v %v: %d %v %+v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, r.Errors) + } + + if r.Response != nil { + return fmt.Sprintf("%d %v %+v", r.Response.StatusCode, r.Message, r.Errors) + } + + return fmt.Sprintf("%v %+v", r.Message, r.Errors) +} + +// Is returns whether the provided error equals this error. +func (r *ErrorResponse) Is(target error) bool { + v, ok := target.(*ErrorResponse) + if !ok { + return false + } + + if r.Message != v.Message || (r.DocumentationURL != v.DocumentationURL) || + !compareHTTPResponse(r.Response, v.Response) { + return false + } + + // Compare Errors. + if len(r.Errors) != len(v.Errors) { + return false + } + for idx := range r.Errors { + if r.Errors[idx] != v.Errors[idx] { + return false + } + } + + // Compare Block. + if (r.Block != nil && v.Block == nil) || (r.Block == nil && v.Block != nil) { + return false + } + if r.Block != nil && v.Block != nil { + if r.Block.Reason != v.Block.Reason { + return false + } + if (r.Block.CreatedAt != nil && v.Block.CreatedAt == nil) || (r.Block.CreatedAt == + nil && v.Block.CreatedAt != nil) { + return false + } + if r.Block.CreatedAt != nil && v.Block.CreatedAt != nil { + if *(r.Block.CreatedAt) != *(v.Block.CreatedAt) { + return false + } + } + } + + return true +} + +// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user +// that has two-factor authentication enabled. The request can be reattempted +// by providing a one-time password in the request. +type TwoFactorAuthError ErrorResponse + +func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } + +// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit +// remaining value of 0. +type RateLimitError struct { + Rate Rate // Rate specifies last known rate limit for the client + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message +} + +func (r *RateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, formatRateReset(time.Until(r.Rate.Reset.Time))) +} + +// Is returns whether the provided error equals this error. +func (r *RateLimitError) Is(target error) bool { + v, ok := target.(*RateLimitError) + if !ok { + return false + } + + return r.Rate == v.Rate && + r.Message == v.Message && + compareHTTPResponse(r.Response, v.Response) +} + +// AcceptedError occurs when GitHub returns 202 Accepted response with an +// empty body, which means a job was scheduled on the GitHub side to process +// the information needed and cache it. +// Technically, 202 Accepted is not a real error, it's just used to +// indicate that results are not ready yet, but should be available soon. +// The request can be repeated after some time. +type AcceptedError struct { + // Raw contains the response body. + Raw []byte +} + +func (*AcceptedError) Error() string { + return "job scheduled on GitHub side; try again later" +} + +// Is returns whether the provided error equals this error. +func (ae *AcceptedError) Is(target error) bool { + v, ok := target.(*AcceptedError) + if !ok { + return false + } + return bytes.Equal(ae.Raw, v.Raw) +} + +// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the +// "documentation_url" field value equal to "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits". +type AbuseRateLimitError struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + + // RetryAfter is provided with some abuse rate limit errors. If present, + // it is the amount of time that the client should wait before retrying. + // Otherwise, the client should try again later (after an unspecified amount of time). + RetryAfter *time.Duration +} + +func (r *AbuseRateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message) +} + +// Is returns whether the provided error equals this error. +func (r *AbuseRateLimitError) Is(target error) bool { + v, ok := target.(*AbuseRateLimitError) + if !ok { + return false + } + + return r.Message == v.Message && + r.RetryAfter == v.RetryAfter && + compareHTTPResponse(r.Response, v.Response) +} + +// sanitizeURL redacts the client_secret parameter from the URL which may be +// exposed to the user. +func sanitizeURL(uri *url.URL) *url.URL { + if uri == nil { + return nil + } + params := uri.Query() + if len(params.Get("client_secret")) > 0 { + params.Set("client_secret", "REDACTED") + uri.RawQuery = params.Encode() + } + return uri +} + +/* +An Error reports more details on an individual error in an ErrorResponse. +These are the possible validation error codes: + + missing: + resource does not exist + missing_field: + a required field on a resource has not been set + invalid: + the formatting of a field is invalid + already_exists: + another resource has the same valid as this field + custom: + some resources return this (e.g. github.User.CreateKey()), additional + information is set in the Message field of the Error + +GitHub error responses structure are often undocumented and inconsistent. +Sometimes error is just a simple string (Issue #540). +In such cases, Message represents an error message as a workaround. + +GitHub API docs: https://docs.github.com/rest/#client-errors +*/ +type Error struct { + Resource string `json:"resource"` // resource on which the error occurred + Field string `json:"field"` // field on which the error occurred + Code string `json:"code"` // validation error code + Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. +} + +func (e *Error) Error() string { + return fmt.Sprintf("%v error caused by %v field on %v resource", + e.Code, e.Field, e.Resource) +} + +func (e *Error) UnmarshalJSON(data []byte) error { + type aliasError Error // avoid infinite recursion by using type alias. + if err := json.Unmarshal(data, (*aliasError)(e)); err != nil { + return json.Unmarshal(data, &e.Message) // data can be json string. + } + return nil +} + +// CheckResponse checks the API response for errors, and returns them if +// present. A response is considered an error if it has a status code outside +// the 200 range or equal to 202 Accepted. +// API error responses are expected to have response +// body, and a JSON response body that maps to ErrorResponse. +// +// The error type will be *RateLimitError for rate limit exceeded errors, +// *AcceptedError for 202 Accepted status codes, +// and *TwoFactorAuthError for two-factor authentication errors. +func CheckResponse(r *http.Response) error { + if r.StatusCode == http.StatusAccepted { + return &AcceptedError{} + } + if c := r.StatusCode; 200 <= c && c <= 299 { + return nil + } + + errorResponse := &ErrorResponse{Response: r} + data, err := io.ReadAll(r.Body) + if err == nil && data != nil { + err = json.Unmarshal(data, errorResponse) + if err != nil { + // reset the response as if this never happened + errorResponse = &ErrorResponse{Response: r} + } + } + // Re-populate error response body because GitHub error responses are often + // undocumented and inconsistent. + // Issue #1136, #540. + r.Body = io.NopCloser(bytes.NewBuffer(data)) + switch { + case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): + return (*TwoFactorAuthError)(errorResponse) + case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0": + return &RateLimitError{ + Rate: parseRate(r), + Response: errorResponse.Response, + Message: errorResponse.Message, + } + case r.StatusCode == http.StatusForbidden && + (strings.HasSuffix(errorResponse.DocumentationURL, "#abuse-rate-limits") || + strings.HasSuffix(errorResponse.DocumentationURL, "secondary-rate-limits")): + abuseRateLimitError := &AbuseRateLimitError{ + Response: errorResponse.Response, + Message: errorResponse.Message, + } + if retryAfter := parseSecondaryRate(r); retryAfter != nil { + abuseRateLimitError.RetryAfter = retryAfter + } + return abuseRateLimitError + default: + return errorResponse + } +} + +// parseBoolResponse determines the boolean result from a GitHub API response. +// Several GitHub API methods return boolean responses indicated by the HTTP +// status code in the response (true indicated by a 204, false indicated by a +// 404). This helper function will determine that result and hide the 404 +// error if present. Any other error will be returned through as-is. +func parseBoolResponse(err error) (bool, error) { + if err == nil { + return true, nil + } + + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // Simply false. In this one case, we do not pass the error through. + return false, nil + } + + // some other real error occurred + return false, err +} + +type RateLimitCategory uint8 + +const ( + CoreCategory RateLimitCategory = iota + SearchCategory + GraphqlCategory + IntegrationManifestCategory + SourceImportCategory + CodeScanningUploadCategory + ActionsRunnerRegistrationCategory + ScimCategory + DependencySnapshotsCategory + CodeSearchCategory + AuditLogCategory + + Categories // An array of this length will be able to contain all rate limit categories. +) + +// GetRateLimitCategory returns the rate limit RateLimitCategory of the endpoint, determined by HTTP method and Request.URL.Path. +func GetRateLimitCategory(method, path string) RateLimitCategory { + switch { + // https://docs.github.com/rest/rate-limit#about-rate-limits + default: + // NOTE: coreCategory is returned for actionsRunnerRegistrationCategory too, + // because no API found for this category. + return CoreCategory + + // https://docs.github.com/en/rest/search/search#search-code + case strings.HasPrefix(path, "/search/code") && + method == http.MethodGet: + return CodeSearchCategory + + case strings.HasPrefix(path, "/search/"): + return SearchCategory + case path == "/graphql": + return GraphqlCategory + case strings.HasPrefix(path, "/app-manifests/") && + strings.HasSuffix(path, "/conversions") && + method == http.MethodPost: + return IntegrationManifestCategory + + // https://docs.github.com/rest/migrations/source-imports#start-an-import + case strings.HasPrefix(path, "/repos/") && + strings.HasSuffix(path, "/import") && + method == http.MethodPut: + return SourceImportCategory + + // https://docs.github.com/rest/code-scanning#upload-an-analysis-as-sarif-data + case strings.HasSuffix(path, "/code-scanning/sarifs"): + return CodeScanningUploadCategory + + // https://docs.github.com/enterprise-cloud@latest/rest/scim + case strings.HasPrefix(path, "/scim/"): + return ScimCategory + + // https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository + case strings.HasPrefix(path, "/repos/") && + strings.HasSuffix(path, "/dependency-graph/snapshots") && + method == http.MethodPost: + return DependencySnapshotsCategory + + // https://docs.github.com/en/enterprise-cloud@latest/rest/orgs/orgs?apiVersion=2022-11-28#get-the-audit-log-for-an-organization + case strings.HasSuffix(path, "/audit-log"): + return AuditLogCategory + } +} + +// RateLimits returns the rate limits for the current client. +// +// Deprecated: Use RateLimitService.Get instead. +func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { + return c.RateLimit.Get(ctx) +} + +func setCredentialsAsHeaders(req *http.Request, id, secret string) *http.Request { + // To set extra headers, we must make a copy of the Request so + // that we don't modify the Request we were given. This is required by the + // specification of http.RoundTripper. + // + // Since we are going to modify only req.Header here, we only need a deep copy + // of req.Header. + convertedRequest := new(http.Request) + *convertedRequest = *req + convertedRequest.Header = make(http.Header, len(req.Header)) + + for k, s := range req.Header { + convertedRequest.Header[k] = append([]string(nil), s...) + } + convertedRequest.SetBasicAuth(id, secret) + return convertedRequest +} + +/* +UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls +that need to use a higher rate limit associated with your OAuth application. + + t := &github.UnauthenticatedRateLimitedTransport{ + ClientID: "your app's client ID", + ClientSecret: "your app's client secret", + } + client := github.NewClient(t.Client()) + +This will add the client id and secret as a base64-encoded string in the format +ClientID:ClientSecret and apply it as an "Authorization": "Basic" header. + +See https://docs.github.com/rest/#unauthenticated-rate-limited-requests for +more information. +*/ +type UnauthenticatedRateLimitedTransport struct { + // ClientID is the GitHub OAuth client ID of the current application, which + // can be found by selecting its entry in the list at + // https://github.com/settings/applications. + ClientID string + + // ClientSecret is the GitHub OAuth client secret of the current + // application. + ClientSecret string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.ClientID == "" { + return nil, errors.New("t.ClientID is empty") + } + if t.ClientSecret == "" { + return nil, errors.New("t.ClientSecret is empty") + } + + req2 := setCredentialsAsHeaders(req, t.ClientID, t.ClientSecret) + // Make the HTTP request. + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests which are subject to the +// rate limit of your OAuth application. +func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// BasicAuthTransport is an http.RoundTripper that authenticates all requests +// using HTTP Basic Authentication with the provided username and password. It +// additionally supports users who have two-factor authentication enabled on +// their GitHub account. +type BasicAuthTransport struct { + Username string // GitHub username + Password string // GitHub password + OTP string // one-time password for users with two-factor auth enabled + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := setCredentialsAsHeaders(req, t.Username, t.Password) + if t.OTP != "" { + req2.Header.Set(headerOTP, t.OTP) + } + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. +func (t *BasicAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BasicAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// formatRateReset formats d to look like "[rate reset in 2s]" or +// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" +// for the negative cases. +func formatRateReset(d time.Duration) string { + isNegative := d < 0 + if isNegative { + d *= -1 + } + secondsTotal := int(0.5 + d.Seconds()) + minutes := secondsTotal / 60 + seconds := secondsTotal - minutes*60 + + var timeString string + if minutes > 0 { + timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) + } else { + timeString = fmt.Sprintf("%ds", seconds) + } + + if isNegative { + return fmt.Sprintf("[rate limit was reset %v ago]", timeString) + } + return fmt.Sprintf("[rate reset in %v]", timeString) +} + +func sleepUntilResetWithBuffer(ctx context.Context, reset time.Time) error { + buffer := time.Second + timer := time.NewTimer(time.Until(reset) + buffer) + select { + case <-ctx.Done(): + if !timer.Stop() { + <-timer.C + } + return ctx.Err() + case <-timer.C: + } + return nil +} + +// When using roundTripWithOptionalFollowRedirect, note that it +// is the responsibility of the caller to close the response body. +func (c *Client) roundTripWithOptionalFollowRedirect(ctx context.Context, u string, maxRedirects int, opts ...RequestOption) (*http.Response, error) { + req, err := c.NewRequest("GET", u, nil, opts...) + if err != nil { + return nil, err + } + + var resp *http.Response + // Use http.DefaultTransport if no custom Transport is configured + req = withContext(ctx, req) + if c.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = c.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, err + } + + // If redirect response is returned, follow it + if maxRedirects > 0 && resp.StatusCode == http.StatusMovedPermanently { + _ = resp.Body.Close() + u = resp.Header.Get("Location") + resp, err = c.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects-1, opts...) + } + return resp, err +} + +// Ptr is a helper routine that allocates a new T value +// to store v and returns a pointer to it. +func Ptr[T any](v T) *T { + return &v +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Bool(v bool) *bool { return &v } + +// Int is a helper routine that allocates a new int value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Int(v int) *int { return &v } + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func Int64(v int64) *int64 { return &v } + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +// +// Deprecated: use Ptr instead. +func String(v string) *string { return &v } + +// roundTripperFunc creates a RoundTripper (transport). +type roundTripperFunc func(*http.Request) (*http.Response, error) + +func (fn roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { + return fn(r) +} diff --git a/vendor/github.com/google/go-github/github/gitignore.go b/vendor/github.com/google/go-github/v68/github/gitignore.go similarity index 70% rename from vendor/github.com/google/go-github/github/gitignore.go rename to vendor/github.com/google/go-github/v68/github/gitignore.go index 2f691bc3..34cf285e 100644 --- a/vendor/github.com/google/go-github/github/gitignore.go +++ b/vendor/github.com/google/go-github/v68/github/gitignore.go @@ -13,7 +13,7 @@ import ( // GitignoresService provides access to the gitignore related functions in the // GitHub API. // -// GitHub API docs: https://developer.github.com/v3/gitignore/ +// GitHub API docs: https://docs.github.com/rest/gitignore/ type GitignoresService service // Gitignore represents a .gitignore file as returned by the GitHub API. @@ -28,8 +28,10 @@ func (g Gitignore) String() string { // List all available Gitignore templates. // -// GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates -func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gitignore/gitignore#get-all-gitignore-templates +// +//meta:operation GET /gitignore/templates +func (s *GitignoresService) List(ctx context.Context) ([]string, *Response, error) { req, err := s.client.NewRequest("GET", "gitignore/templates", nil) if err != nil { return nil, nil, err @@ -46,8 +48,10 @@ func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error // Get a Gitignore by name. // -// GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-template -func (s GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/gitignore/gitignore#get-a-gitignore-template +// +//meta:operation GET /gitignore/templates/{name} +func (s *GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { u := fmt.Sprintf("gitignore/templates/%v", name) req, err := s.client.NewRequest("GET", u, nil) if err != nil { diff --git a/vendor/github.com/google/go-github/v68/github/interactions.go b/vendor/github.com/google/go-github/v68/github/interactions.go new file mode 100644 index 00000000..2268273d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions.go @@ -0,0 +1,28 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// InteractionsService handles communication with the repository and organization related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/interactions/ +type InteractionsService service + +// InteractionRestriction represents the interaction restrictions for repository and organization. +type InteractionRestriction struct { + // Specifies the group of GitHub users who can + // comment, open issues, or create pull requests for the given repository. + // Possible values are: "existing_users", "contributors_only" and "collaborators_only". + Limit *string `json:"limit,omitempty"` + + // Origin specifies the type of the resource to interact with. + // Possible values are: "repository" and "organization". + Origin *string `json:"origin,omitempty"` + + // ExpiresAt specifies the time after which the interaction restrictions expire. + // The default expiry time is 24 hours from the time restriction is created. + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} diff --git a/vendor/github.com/google/go-github/v68/github/interactions_orgs.go b/vendor/github.com/google/go-github/v68/github/interactions_orgs.go new file mode 100644 index 00000000..47998c4e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions_orgs.go @@ -0,0 +1,86 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForOrg fetches the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#get-interaction-restrictions-for-an-organization +// +//meta:operation GET /orgs/{org}/interaction-limits +func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organization string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// UpdateRestrictionsForOrg adds or updates the interaction restrictions for an organization. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// in public repositories for the given organization. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#set-interaction-restrictions-for-an-organization +// +//meta:operation PUT /orgs/{org}/interaction-limits +func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + + interaction := &InteractionRestriction{Limit: Ptr(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// RemoveRestrictionsFromOrg removes the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/rest/interactions/orgs#remove-interaction-restrictions-for-an-organization +// +//meta:operation DELETE /orgs/{org}/interaction-limits +func (s *InteractionsService) RemoveRestrictionsFromOrg(ctx context.Context, organization string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/interactions_repos.go b/vendor/github.com/google/go-github/v68/github/interactions_repos.go new file mode 100644 index 00000000..58fd4f04 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/interactions_repos.go @@ -0,0 +1,86 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForRepo fetches the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#get-interaction-restrictions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner, repo string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// UpdateRestrictionsForRepo adds or updates the interaction restrictions for a repository. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// for the given repository. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#set-interaction-restrictions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + + interaction := &InteractionRestriction{Limit: Ptr(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// RemoveRestrictionsFromRepo removes the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/rest/interactions/repos#remove-interaction-restrictions-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/interaction-limits +func (s *InteractionsService) RemoveRestrictionsFromRepo(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/issue_import.go b/vendor/github.com/google/go-github/v68/github/issue_import.go new file mode 100644 index 00000000..4f063710 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/issue_import.go @@ -0,0 +1,154 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "encoding/json" + "fmt" +) + +// IssueImportService handles communication with the issue import related +// methods of the Issue Import GitHub API. +type IssueImportService service + +// IssueImportRequest represents a request to create an issue. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#supported-issue-and-comment-fields +type IssueImportRequest struct { + IssueImport IssueImport `json:"issue"` + Comments []*Comment `json:"comments,omitempty"` +} + +// IssueImport represents body of issue to import. +type IssueImport struct { + Title string `json:"title"` + Body string `json:"body"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Assignee *string `json:"assignee,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Closed *bool `json:"closed,omitempty"` + Labels []string `json:"labels,omitempty"` +} + +// Comment represents comments of issue to import. +type Comment struct { + CreatedAt *Timestamp `json:"created_at,omitempty"` + Body string `json:"body"` +} + +// IssueImportResponse represents the response of an issue import create request. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#import-issue-response +type IssueImportResponse struct { + ID *int `json:"id,omitempty"` + Status *string `json:"status,omitempty"` + URL *string `json:"url,omitempty"` + ImportIssuesURL *string `json:"import_issues_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Message *string `json:"message,omitempty"` + DocumentationURL *string `json:"documentation_url,omitempty"` + Errors []*IssueImportError `json:"errors,omitempty"` +} + +// IssueImportError represents errors of an issue import create request. +type IssueImportError struct { + Location *string `json:"location,omitempty"` + Resource *string `json:"resource,omitempty"` + Field *string `json:"field,omitempty"` + Value *string `json:"value,omitempty"` + Code *string `json:"code,omitempty"` +} + +// Create a new imported issue on the specified repository. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#start-an-issue-import +// +//meta:operation POST /repos/{owner}/{repo}/import/issues +func (s *IssueImportService) Create(ctx context.Context, owner, repo string, issue *IssueImportRequest) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + aerr, ok := err.(*AcceptedError) + if ok { + if err := json.Unmarshal(aerr.Raw, i); err != nil { + return i, resp, err + } + return i, resp, err + } + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatus checks the status of an imported issue. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#import-status-request +// +//meta:operation GET /repos/{owner}/{repo}/import/issues/{issue_number} +func (s *IssueImportService) CheckStatus(ctx context.Context, owner, repo string, issueID int64) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues/%v", owner, repo, issueID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatusSince checks the status of multiple imported issues since a given date. +// +// GitHub API docs: https://gist.github.com/jonmagic/5282384165e0f86ef105#check-status-of-multiple-issues +// +//meta:operation GET /repos/{owner}/{repo}/import/issues +func (s *IssueImportService) CheckStatusSince(ctx context.Context, owner, repo string, since Timestamp) ([]*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues?since=%v", owner, repo, since.Format("2006-01-02")) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + var b bytes.Buffer + resp, err := s.client.Do(ctx, req, &b) + if err != nil { + return nil, resp, err + } + + var i []*IssueImportResponse + err = json.Unmarshal(b.Bytes(), &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/issues.go b/vendor/github.com/google/go-github/v68/github/issues.go similarity index 58% rename from vendor/github.com/google/go-github/github/issues.go rename to vendor/github.com/google/go-github/v68/github/issues.go index 47537544..a2652b34 100644 --- a/vendor/github.com/google/go-github/github/issues.go +++ b/vendor/github.com/google/go-github/v68/github/issues.go @@ -8,14 +8,13 @@ package github import ( "context" "fmt" - "strings" "time" ) // IssuesService handles communication with the issue related // methods of the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/issues/ +// GitHub API docs: https://docs.github.com/rest/issues/ type IssuesService service // Issue represents a GitHub issue on a repository. @@ -26,36 +25,40 @@ type IssuesService service // this is an issue, and if PullRequestLinks is not nil, this is a pull request. // The IsPullRequest helper method can be used to check that. type Issue struct { - ID *int64 `json:"id,omitempty"` - Number *int `json:"number,omitempty"` - State *string `json:"state,omitempty"` - Locked *bool `json:"locked,omitempty"` - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - User *User `json:"user,omitempty"` - Labels []Label `json:"labels,omitempty"` - Assignee *User `json:"assignee,omitempty"` - Comments *int `json:"comments,omitempty"` - ClosedAt *time.Time `json:"closed_at,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - ClosedBy *User `json:"closed_by,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - EventsURL *string `json:"events_url,omitempty"` - LabelsURL *string `json:"labels_url,omitempty"` - RepositoryURL *string `json:"repository_url,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` - Repository *Repository `json:"repository,omitempty"` - Reactions *Reactions `json:"reactions,omitempty"` - Assignees []*User `json:"assignees,omitempty"` - NodeID *string `json:"node_id,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + // StateReason can be one of: "completed", "not_planned", "reopened". + StateReason *string `json:"state_reason,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + User *User `json:"user,omitempty"` + Labels []*Label `json:"labels,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Comments *int `json:"comments,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Draft *bool `json:"draft,omitempty"` // TextMatches is only populated from search results that request text matches - // See: search.go and https://developer.github.com/v3/search/#text-match-metadata - TextMatches []TextMatch `json:"text_matches,omitempty"` + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` // ActiveLockReason is populated only when LockReason is provided while locking the issue. // Possible values are: "off-topic", "too heated", "resolved", and "spam". @@ -77,13 +80,15 @@ func (i Issue) IsPullRequest() bool { // It is separate from Issue above because otherwise Labels // and Assignee fail to serialize to the correct JSON. type IssueRequest struct { - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - Labels *[]string `json:"labels,omitempty"` - Assignee *string `json:"assignee,omitempty"` - State *string `json:"state,omitempty"` - Milestone *int `json:"milestone,omitempty"` - Assignees *[]string `json:"assignees,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + Labels *[]string `json:"labels,omitempty"` + Assignee *string `json:"assignee,omitempty"` + State *string `json:"state,omitempty"` + // StateReason can be 'completed' or 'not_planned'. + StateReason *string `json:"state_reason,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Assignees *[]string `json:"assignees,omitempty"` } // IssueListOptions specifies the optional parameters to the IssuesService.List @@ -117,10 +122,11 @@ type IssueListOptions struct { // PullRequestLinks object is added to the Issue object when it's an issue included // in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR. type PullRequestLinks struct { - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - DiffURL *string `json:"diff_url,omitempty"` - PatchURL *string `json:"patch_url,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + MergedAt *Timestamp `json:"merged_at,omitempty"` } // List the issues for the authenticated user. If all is true, list issues @@ -128,28 +134,34 @@ type PullRequestLinks struct { // organization repositories; if false, list only owned and member // repositories. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-issues -func (s *IssuesService) List(ctx context.Context, all bool, opt *IssueListOptions) ([]*Issue, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-issues-assigned-to-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-user-account-issues-assigned-to-the-authenticated-user +// +//meta:operation GET /issues +//meta:operation GET /user/issues +func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) { var u string if all { u = "issues" } else { u = "user/issues" } - return s.listIssues(ctx, u, opt) + return s.listIssues(ctx, u, opts) } // ListByOrg fetches the issues in the specified organization for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-issues -func (s *IssuesService) ListByOrg(ctx context.Context, org string, opt *IssueListOptions) ([]*Issue, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-organization-issues-assigned-to-the-authenticated-user +// +//meta:operation GET /orgs/{org}/issues +func (s *IssuesService) ListByOrg(ctx context.Context, org string, opts *IssueListOptions) ([]*Issue, *Response, error) { u := fmt.Sprintf("orgs/%v/issues", org) - return s.listIssues(ctx, u, opt) + return s.listIssues(ctx, u, opts) } -func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueListOptions) ([]*Issue, *Response, error) { - u, err := addOptions(u, opt) +func (s *IssuesService) listIssues(ctx context.Context, u string, opts *IssueListOptions) ([]*Issue, *Response, error) { + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -159,9 +171,8 @@ func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueList return nil, nil, err } - // TODO: remove custom Accept headers when APIs fully launch. - acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) var issues []*Issue resp, err := s.client.Do(ctx, req, &issues) @@ -214,10 +225,12 @@ type IssueListByRepoOptions struct { // ListByRepo lists the issues for the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository -func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opt *IssueListByRepoOptions) ([]*Issue, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/issues#list-repository-issues +// +//meta:operation GET /repos/{owner}/{repo}/issues +func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opts *IssueListByRepoOptions) ([]*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -227,9 +240,8 @@ func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo strin return nil, nil, err } - // TODO: remove custom Accept headers when APIs fully launch. - acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) var issues []*Issue resp, err := s.client.Do(ctx, req, &issues) @@ -242,7 +254,9 @@ func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo strin // Get a single issue. // -// GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-issue +// GitHub API docs: https://docs.github.com/rest/issues/issues#get-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number} func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) @@ -250,9 +264,8 @@ func (s *IssuesService) Get(ctx context.Context, owner string, repo string, numb return nil, nil, err } - // TODO: remove custom Accept headers when APIs fully launch. - acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview} - req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) issue := new(Issue) resp, err := s.client.Do(ctx, req, issue) @@ -265,7 +278,9 @@ func (s *IssuesService) Get(ctx context.Context, owner string, repo string, numb // Create a new issue on the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/#create-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/issues#create-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) req, err := s.client.NewRequest("POST", u, issue) @@ -273,9 +288,6 @@ func (s *IssuesService) Create(ctx context.Context, owner string, repo string, i return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - i := new(Issue) resp, err := s.client.Do(ctx, req, i) if err != nil { @@ -285,9 +297,11 @@ func (s *IssuesService) Create(ctx context.Context, owner string, repo string, i return i, resp, nil } -// Edit an issue. +// Edit (update) an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/#edit-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/issues#update-an-issue +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/{issue_number} func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) req, err := s.client.NewRequest("PATCH", u, issue) @@ -295,8 +309,30 @@ func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, num return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// RemoveMilestone removes a milestone from an issue. +// +// This is a helper method to explicitly update an issue with a `null` milestone, thereby removing it. +// +// GitHub API docs: https://docs.github.com/rest/issues/issues#update-an-issue +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/{issue_number} +func (s *IssuesService) RemoveMilestone(ctx context.Context, owner, repo string, issueNumber int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v", owner, repo, issueNumber) + req, err := s.client.NewRequest("PATCH", u, &struct { + Milestone *Milestone `json:"milestone"` + }{}) + if err != nil { + return nil, nil, err + } i := new(Issue) resp, err := s.client.Do(ctx, req, i) @@ -318,24 +354,24 @@ type LockIssueOptions struct { // Lock an issue's conversation. // -// GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue -func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opt *LockIssueOptions) (*Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/issues#lock-an-issue +// +//meta:operation PUT /repos/{owner}/{repo}/issues/{issue_number}/lock +func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opts *LockIssueOptions) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) - req, err := s.client.NewRequest("PUT", u, opt) + req, err := s.client.NewRequest("PUT", u, opts) if err != nil { return nil, err } - if opt != nil { - req.Header.Set("Accept", mediaTypeLockReasonPreview) - } - return s.client.Do(ctx, req, nil) } // Unlock an issue's conversation. // -// GitHub API docs: https://developer.github.com/v3/issues/#unlock-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/issues#unlock-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/issues_assignees.go b/vendor/github.com/google/go-github/v68/github/issues_assignees.go similarity index 72% rename from vendor/github.com/google/go-github/github/issues_assignees.go rename to vendor/github.com/google/go-github/v68/github/issues_assignees.go index 9cb366f5..fd065771 100644 --- a/vendor/github.com/google/go-github/github/issues_assignees.go +++ b/vendor/github.com/google/go-github/v68/github/issues_assignees.go @@ -13,10 +13,12 @@ import ( // ListAssignees fetches all available assignees (owners and collaborators) to // which issues may be assigned. // -// GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees -func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/assignees#list-assignees +// +//meta:operation GET /repos/{owner}/{repo}/assignees +func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -25,6 +27,7 @@ func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, o if err != nil { return nil, nil, err } + var assignees []*User resp, err := s.client.Do(ctx, req, &assignees) if err != nil { @@ -36,13 +39,16 @@ func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, o // IsAssignee checks if a user is an assignee for the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee +// GitHub API docs: https://docs.github.com/rest/issues/assignees#check-if-a-user-can-be-assigned +// +//meta:operation GET /repos/{owner}/{repo}/assignees/{assignee} func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return false, nil, err } + resp, err := s.client.Do(ctx, req, nil) assignee, err := parseBoolResponse(err) return assignee, resp, err @@ -50,7 +56,9 @@ func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string // AddAssignees adds the provided GitHub users as assignees to the issue. // -// GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/assignees#add-assignees-to-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/assignees func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { users := &struct { Assignees []string `json:"assignees,omitempty"` @@ -63,12 +71,18 @@ func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, nu issue := &Issue{} resp, err := s.client.Do(ctx, req, issue) - return issue, resp, err + if err != nil { + return nil, resp, err + } + + return issue, resp, nil } // RemoveAssignees removes the provided GitHub users as assignees from the issue. // -// GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/assignees#remove-assignees-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { users := &struct { Assignees []string `json:"assignees,omitempty"` @@ -81,5 +95,9 @@ func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, issue := &Issue{} resp, err := s.client.Do(ctx, req, issue) - return issue, resp, err + if err != nil { + return nil, resp, err + } + + return issue, resp, nil } diff --git a/vendor/github.com/google/go-github/github/issues_comments.go b/vendor/github.com/google/go-github/v68/github/issues_comments.go similarity index 75% rename from vendor/github.com/google/go-github/github/issues_comments.go rename to vendor/github.com/google/go-github/v68/github/issues_comments.go index e6f6f219..74a4e60f 100644 --- a/vendor/github.com/google/go-github/github/issues_comments.go +++ b/vendor/github.com/google/go-github/v68/github/issues_comments.go @@ -14,11 +14,12 @@ import ( // IssueComment represents a comment left on an issue. type IssueComment struct { ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` Body *string `json:"body,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` // AuthorAssociation is the comment author's relationship to the issue's repository. // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". AuthorAssociation *string `json:"author_association,omitempty"` @@ -35,13 +36,13 @@ func (i IssueComment) String() string { // IssuesService.ListComments method. type IssueListCommentsOptions struct { // Sort specifies how to sort comments. Possible values are: created, updated. - Sort string `url:"sort,omitempty"` + Sort *string `url:"sort,omitempty"` // Direction in which to sort comments. Possible values are: asc, desc. - Direction string `url:"direction,omitempty"` + Direction *string `url:"direction,omitempty"` // Since filters comments by time. - Since time.Time `url:"since,omitempty"` + Since *time.Time `url:"since,omitempty"` ListOptions } @@ -49,15 +50,19 @@ type IssueListCommentsOptions struct { // ListComments lists all comments on the specified issue. Specifying an issue // number of 0 will return all comments on all issues for the repository. // -// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue -func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opt *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/comments#list-issue-comments +// GitHub API docs: https://docs.github.com/rest/issues/comments#list-issue-comments-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/comments +func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { var u string if number == 0 { u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) } else { u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -81,7 +86,9 @@ func (s *IssuesService) ListComments(ctx context.Context, owner string, repo str // GetComment fetches the specified issue comment. // -// GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment +// GitHub API docs: https://docs.github.com/rest/issues/comments#get-an-issue-comment +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments/{comment_id} func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) @@ -104,7 +111,9 @@ func (s *IssuesService) GetComment(ctx context.Context, owner string, repo strin // CreateComment creates a new comment on the specified issue. // -// GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment +// GitHub API docs: https://docs.github.com/rest/issues/comments#create-an-issue-comment +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/comments func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) @@ -123,7 +132,9 @@ func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo st // EditComment updates an issue comment. // A non-nil comment.Body must be provided. Other comment fields should be left nil. // -// GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment +// GitHub API docs: https://docs.github.com/rest/issues/comments#update-an-issue-comment +// +//meta:operation PATCH /repos/{owner}/{repo}/issues/comments/{comment_id} func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("PATCH", u, comment) @@ -141,7 +152,9 @@ func (s *IssuesService) EditComment(ctx context.Context, owner string, repo stri // DeleteComment deletes an issue comment. // -// GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment +// GitHub API docs: https://docs.github.com/rest/issues/comments#delete-an-issue-comment +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id} func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/issues_events.go b/vendor/github.com/google/go-github/v68/github/issues_events.go similarity index 59% rename from vendor/github.com/google/go-github/github/issues_events.go rename to vendor/github.com/google/go-github/v68/github/issues_events.go index f71e4636..8e234d7e 100644 --- a/vendor/github.com/google/go-github/github/issues_events.go +++ b/vendor/github.com/google/go-github/v68/github/issues_events.go @@ -8,7 +8,6 @@ package github import ( "context" "fmt" - "time" ) // IssueEvent represents an event that occurred around an Issue or Pull Request. @@ -19,6 +18,9 @@ type IssueEvent struct { // The User that generated this event. Actor *User `json:"actor,omitempty"` + // The action corresponding to the event. + Action string `json:"action,omitempty"` + // Event identifies the actual type of Event that occurred. Possible // values are: // @@ -62,27 +64,52 @@ type IssueEvent struct { // head_ref_deleted, head_ref_restored // The pull request’s branch was deleted or restored. // + // review_dismissed + // The review was dismissed and `DismissedReview` will be populated below. + // + // review_requested, review_request_removed + // The Actor requested or removed the request for a review. + // RequestedReviewer or RequestedTeam, and ReviewRequester will be populated below. + // Event *string `json:"event,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` Issue *Issue `json:"issue,omitempty"` // Only present on certain events; see above. - Assignee *User `json:"assignee,omitempty"` - Assigner *User `json:"assigner,omitempty"` - CommitID *string `json:"commit_id,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - Label *Label `json:"label,omitempty"` - Rename *Rename `json:"rename,omitempty"` - LockReason *string `json:"lock_reason,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + Label *Label `json:"label,omitempty"` + Rename *Rename `json:"rename,omitempty"` + LockReason *string `json:"lock_reason,omitempty"` + DismissedReview *DismissedReview `json:"dismissed_review,omitempty"` + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + RequestedTeam *Team `json:"requested_team,omitempty"` + ReviewRequester *User `json:"review_requester,omitempty"` + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` +} + +// DismissedReview represents details for 'dismissed_review' events. +type DismissedReview struct { + // State represents the state of the dismissed review. + // Possible values are: "commented", "approved", and "changes_requested". + State *string `json:"state,omitempty"` + ReviewID *int64 `json:"review_id,omitempty"` + DismissalMessage *string `json:"dismissal_message,omitempty"` + DismissalCommitID *string `json:"dismissal_commit_id,omitempty"` } // ListIssueEvents lists events for the specified issue. // -// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue -func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*IssueEvent, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/events +func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -92,7 +119,7 @@ func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, return nil, nil, err } - req.Header.Set("Accept", mediaTypeLockReasonPreview) + req.Header.Set("Accept", mediaTypeProjectCardDetailsPreview) var events []*IssueEvent resp, err := s.client.Do(ctx, req, &events) @@ -105,10 +132,12 @@ func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, // ListRepositoryEvents lists events for the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository -func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/events#list-issue-events-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/issues/events +func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -129,7 +158,9 @@ func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo st // GetEvent returns the specified issue event. // -// GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event +// GitHub API docs: https://docs.github.com/rest/issues/events#get-an-issue-event +// +//meta:operation GET /repos/{owner}/{repo}/issues/events/{event_id} func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) diff --git a/vendor/github.com/google/go-github/github/issues_labels.go b/vendor/github.com/google/go-github/v68/github/issues_labels.go similarity index 66% rename from vendor/github.com/google/go-github/github/issues_labels.go rename to vendor/github.com/google/go-github/v68/github/issues_labels.go index adcbe068..b97b00f3 100644 --- a/vendor/github.com/google/go-github/github/issues_labels.go +++ b/vendor/github.com/google/go-github/v68/github/issues_labels.go @@ -10,7 +10,7 @@ import ( "fmt" ) -// Label represents a GitHub label on an Issue +// Label represents a GitHub label on an Issue. type Label struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` @@ -27,10 +27,12 @@ func (l Label) String() string { // ListLabels lists all labels for a repository. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository -func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Label, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/labels +func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -40,9 +42,6 @@ func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo strin return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { @@ -54,7 +53,9 @@ func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo strin // GetLabel gets a single label. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label +// GitHub API docs: https://docs.github.com/rest/issues/labels#get-a-label +// +//meta:operation GET /repos/{owner}/{repo}/labels/{name} func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("GET", u, nil) @@ -62,9 +63,6 @@ func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - label := new(Label) resp, err := s.client.Do(ctx, req, label) if err != nil { @@ -76,7 +74,9 @@ func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, // CreateLabel creates a new label on the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#create-a-label +// GitHub API docs: https://docs.github.com/rest/issues/labels#create-a-label +// +//meta:operation POST /repos/{owner}/{repo}/labels func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) req, err := s.client.NewRequest("POST", u, label) @@ -84,9 +84,6 @@ func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo stri return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - l := new(Label) resp, err := s.client.Do(ctx, req, l) if err != nil { @@ -98,7 +95,9 @@ func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo stri // EditLabel edits a label. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#update-a-label +// GitHub API docs: https://docs.github.com/rest/issues/labels#update-a-label +// +//meta:operation PATCH /repos/{owner}/{repo}/labels/{name} func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("PATCH", u, label) @@ -106,9 +105,6 @@ func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - l := new(Label) resp, err := s.client.Do(ctx, req, l) if err != nil { @@ -120,7 +116,9 @@ func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string // DeleteLabel deletes a label. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#delete-a-label +// GitHub API docs: https://docs.github.com/rest/issues/labels#delete-a-label +// +//meta:operation DELETE /repos/{owner}/{repo}/labels/{name} func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) req, err := s.client.NewRequest("DELETE", u, nil) @@ -132,10 +130,12 @@ func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo stri // ListLabelsByIssue lists all labels for an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue -func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/labels +func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -145,9 +145,6 @@ func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, rep return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { @@ -159,7 +156,9 @@ func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, rep // AddLabelsToIssue adds labels to an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/labels#add-labels-to-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/labels func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("POST", u, labels) @@ -167,9 +166,6 @@ func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - var l []*Label resp, err := s.client.Do(ctx, req, &l) if err != nil { @@ -181,7 +177,9 @@ func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo // RemoveLabelForIssue removes a label for an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/labels#remove-a-label-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name} func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label) req, err := s.client.NewRequest("DELETE", u, nil) @@ -189,15 +187,14 @@ func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, r return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - return s.client.Do(ctx, req, nil) } // ReplaceLabelsForIssue replaces all labels for an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/labels#set-labels-for-an-issue +// +//meta:operation PUT /repos/{owner}/{repo}/issues/{issue_number}/labels func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("PUT", u, labels) @@ -205,9 +202,6 @@ func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - var l []*Label resp, err := s.client.Do(ctx, req, &l) if err != nil { @@ -219,7 +213,9 @@ func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, // RemoveLabelsForIssue removes all labels for an issue. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue +// GitHub API docs: https://docs.github.com/rest/issues/labels#remove-all-labels-from-an-issue +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) @@ -227,18 +223,17 @@ func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - return s.client.Do(ctx, req, nil) } // ListLabelsForMilestone lists labels for every issue in a milestone. // -// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone -func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/labels#list-labels-for-issues-in-a-milestone +// +//meta:operation GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels +func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -248,9 +243,6 @@ func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - var labels []*Label resp, err := s.client.Do(ctx, req, &labels) if err != nil { diff --git a/vendor/github.com/google/go-github/github/issues_milestones.go b/vendor/github.com/google/go-github/v68/github/issues_milestones.go similarity index 77% rename from vendor/github.com/google/go-github/github/issues_milestones.go rename to vendor/github.com/google/go-github/v68/github/issues_milestones.go index ffe9aae1..6c31bcd0 100644 --- a/vendor/github.com/google/go-github/github/issues_milestones.go +++ b/vendor/github.com/google/go-github/v68/github/issues_milestones.go @@ -8,7 +8,6 @@ package github import ( "context" "fmt" - "time" ) // Milestone represents a GitHub repository milestone. @@ -24,10 +23,10 @@ type Milestone struct { Creator *User `json:"creator,omitempty"` OpenIssues *int `json:"open_issues,omitempty"` ClosedIssues *int `json:"closed_issues,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - ClosedAt *time.Time `json:"closed_at,omitempty"` - DueOn *time.Time `json:"due_on,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + DueOn *Timestamp `json:"due_on,omitempty"` NodeID *string `json:"node_id,omitempty"` } @@ -55,10 +54,12 @@ type MilestoneListOptions struct { // ListMilestones lists all milestones for a repository. // -// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository -func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opt *MilestoneListOptions) ([]*Milestone, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/milestones#list-milestones +// +//meta:operation GET /repos/{owner}/{repo}/milestones +func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opts *MilestoneListOptions) ([]*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -79,7 +80,9 @@ func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo s // GetMilestone gets a single milestone. // -// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone +// GitHub API docs: https://docs.github.com/rest/issues/milestones#get-a-milestone +// +//meta:operation GET /repos/{owner}/{repo}/milestones/{milestone_number} func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("GET", u, nil) @@ -98,7 +101,9 @@ func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo str // CreateMilestone creates a new milestone on the specified repository. // -// GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone +// GitHub API docs: https://docs.github.com/rest/issues/milestones#create-a-milestone +// +//meta:operation POST /repos/{owner}/{repo}/milestones func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) req, err := s.client.NewRequest("POST", u, milestone) @@ -117,7 +122,9 @@ func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo // EditMilestone edits a milestone. // -// GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone +// GitHub API docs: https://docs.github.com/rest/issues/milestones#update-a-milestone +// +//meta:operation PATCH /repos/{owner}/{repo}/milestones/{milestone_number} func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("PATCH", u, milestone) @@ -136,7 +143,9 @@ func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo st // DeleteMilestone deletes a milestone. // -// GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone +// GitHub API docs: https://docs.github.com/rest/issues/milestones#delete-a-milestone +// +//meta:operation DELETE /repos/{owner}/{repo}/milestones/{milestone_number} func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/issues_timeline.go b/vendor/github.com/google/go-github/v68/github/issues_timeline.go similarity index 64% rename from vendor/github.com/google/go-github/github/issues_timeline.go rename to vendor/github.com/google/go-github/v68/github/issues_timeline.go index 9cfda832..903f5b89 100644 --- a/vendor/github.com/google/go-github/github/issues_timeline.go +++ b/vendor/github.com/google/go-github/v68/github/issues_timeline.go @@ -8,13 +8,13 @@ package github import ( "context" "fmt" - "time" + "strings" ) // Timeline represents an event that occurred around an Issue or Pull Request. // // It is similar to an IssueEvent but may contain more information. -// GitHub API docs: https://developer.github.com/v3/issues/timeline/ +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/issue-event-types type Timeline struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` @@ -23,6 +23,20 @@ type Timeline struct { // The User object that generated the event. Actor *User `json:"actor,omitempty"` + // The person who commented on the issue. + User *User `json:"user,omitempty"` + + // The person who authored the commit. + Author *CommitAuthor `json:"author,omitempty"` + // The person who committed the commit on behalf of the author. + Committer *CommitAuthor `json:"committer,omitempty"` + // The SHA of the commit in the pull request. + SHA *string `json:"sha,omitempty"` + // The commit message. + Message *string `json:"message,omitempty"` + // A list of parent commits. + Parents []*Commit `json:"parents,omitempty"` + // Event identifies the actual type of Event that occurred. Possible values // are: // @@ -80,6 +94,17 @@ type Timeline struct { // reopened // The issue was reopened by the actor. // + // reviewed + // The pull request was reviewed. + // + // review_requested + // The actor requested a review from a user or team. + // Reviewer and Requester/RequestedTeam will be populated. + // + // review_request_removed + // The actor removed a review request from a user or team. + // Reviewer and Requester/RequestedTeam will be populated. + // // subscribed // The actor subscribed to receive notifications for an issue. // @@ -100,13 +125,15 @@ type Timeline struct { // The string SHA of a commit that referenced this Issue or Pull Request. CommitID *string `json:"commit_id,omitempty"` // The timestamp indicating when the event occurred. - CreatedAt *time.Time `json:"created_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` // The Label object including `name` and `color` attributes. Only provided for // 'labeled' and 'unlabeled' events. Label *Label `json:"label,omitempty"` // The User object which was assigned to (or unassigned from) this Issue or // Pull Request. Only provided for 'assigned' and 'unassigned' events. Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + // The Milestone object including a 'title' attribute. // Only provided for 'milestoned' and 'demilestoned' events. Milestone *Milestone `json:"milestone,omitempty"` @@ -116,6 +143,23 @@ type Timeline struct { // An object containing rename details including 'from' and 'to' attributes. // Only provided for 'renamed' events. Rename *Rename `json:"rename,omitempty"` + // The state of a submitted review. Can be one of: 'commented', + // 'changes_requested' or 'approved'. + // Only provided for 'reviewed' events. + State *string `json:"state,omitempty"` + + // The person requested to review the pull request. + Reviewer *User `json:"requested_reviewer,omitempty"` + // RequestedTeam contains the team requested to review the pull request. + RequestedTeam *Team `json:"requested_team,omitempty"` + // The person who requested a review. + Requester *User `json:"review_requester,omitempty"` + + // The review summary text. + Body *string `json:"body,omitempty"` + SubmittedAt *Timestamp `json:"submitted_at,omitempty"` + + PerformedViaGithubApp *App `json:"performed_via_github_app,omitempty"` } // Source represents a reference's source. @@ -123,14 +167,18 @@ type Source struct { ID *int64 `json:"id,omitempty"` URL *string `json:"url,omitempty"` Actor *User `json:"actor,omitempty"` + Type *string `json:"type,omitempty"` + Issue *Issue `json:"issue,omitempty"` } // ListIssueTimeline lists events for the specified issue. // -// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue -func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/issues/timeline#list-timeline-events-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/timeline +func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Timeline, *Response, error) { u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -141,9 +189,14 @@ func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo strin } // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTimelinePreview) + acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var events []*Timeline resp, err := s.client.Do(ctx, req, &events) - return events, resp, err + if err != nil { + return nil, resp, err + } + + return events, resp, nil } diff --git a/vendor/github.com/google/go-github/github/licenses.go b/vendor/github.com/google/go-github/v68/github/licenses.go similarity index 89% rename from vendor/github.com/google/go-github/github/licenses.go rename to vendor/github.com/google/go-github/v68/github/licenses.go index 1176d3a8..34b8a3d8 100644 --- a/vendor/github.com/google/go-github/github/licenses.go +++ b/vendor/github.com/google/go-github/v68/github/licenses.go @@ -13,7 +13,7 @@ import ( // LicensesService handles communication with the license related // methods of the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/licenses/ +// GitHub API docs: https://docs.github.com/rest/licenses/ type LicensesService service // RepositoryLicense represents the license for a repository. @@ -60,7 +60,9 @@ func (l License) String() string { // List popular open source licenses. // -// GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-all-commonly-used-licenses +// +//meta:operation GET /licenses func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) { req, err := s.client.NewRequest("GET", "licenses", nil) if err != nil { @@ -78,7 +80,9 @@ func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, erro // Get extended metadata for one license. // -// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-a-license +// +//meta:operation GET /licenses/{license} func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { u := fmt.Sprintf("licenses/%s", licenseName) diff --git a/vendor/github.com/google/go-github/v68/github/markdown.go b/vendor/github.com/google/go-github/v68/github/markdown.go new file mode 100644 index 00000000..0fd896c6 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/markdown.go @@ -0,0 +1,69 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" +) + +// MarkdownService provides access to markdown-related functions in the GitHub API. +type MarkdownService service + +// MarkdownOptions specifies optional parameters to the Render method. +type MarkdownOptions struct { + // Mode identifies the rendering mode. Possible values are: + // markdown - render a document as plain Render, just like + // README files are rendered. + // + // gfm - to render a document as user-content, e.g. like user + // comments or issues are rendered. In GFM mode, hard line breaks are + // always taken into account, and issue and user mentions are linked + // accordingly. + // + // Default is "markdown". + Mode string + + // Context identifies the repository context. Only taken into account + // when rendering as "gfm". + Context string +} + +type markdownRenderRequest struct { + Text *string `json:"text,omitempty"` + Mode *string `json:"mode,omitempty"` + Context *string `json:"context,omitempty"` +} + +// Render renders an arbitrary Render document. +// +// GitHub API docs: https://docs.github.com/rest/markdown/markdown#render-a-markdown-document +// +//meta:operation POST /markdown +func (s *MarkdownService) Render(ctx context.Context, text string, opts *MarkdownOptions) (string, *Response, error) { + request := &markdownRenderRequest{Text: Ptr(text)} + if opts != nil { + if opts.Mode != "" { + request.Mode = Ptr(opts.Mode) + } + if opts.Context != "" { + request.Context = Ptr(opts.Context) + } + } + + req, err := s.client.NewRequest("POST", "markdown", request) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/messages.go b/vendor/github.com/google/go-github/v68/github/messages.go new file mode 100644 index 00000000..59b214b3 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/messages.go @@ -0,0 +1,356 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides functions for validating payloads from GitHub Webhooks. +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github + +package github + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "hash" + "io" + "mime" + "net/http" + "net/url" + "reflect" + "sort" + "strings" +) + +const ( + // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. + sha1Prefix = "sha1" + // sha256Prefix and sha512Prefix are provided for future compatibility. + sha256Prefix = "sha256" + sha512Prefix = "sha512" + // SHA1SignatureHeader is the GitHub header key used to pass the HMAC-SHA1 hexdigest. + SHA1SignatureHeader = "X-Hub-Signature" + // SHA256SignatureHeader is the GitHub header key used to pass the HMAC-SHA256 hexdigest. + SHA256SignatureHeader = "X-Hub-Signature-256" + // EventTypeHeader is the GitHub header key used to pass the event type. + EventTypeHeader = "X-Github-Event" + // DeliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. + DeliveryIDHeader = "X-Github-Delivery" +) + +var ( + // eventTypeMapping maps webhooks types to their corresponding go-github struct types. + eventTypeMapping = map[string]interface{}{ + "branch_protection_configuration": &BranchProtectionConfigurationEvent{}, + "branch_protection_rule": &BranchProtectionRuleEvent{}, + "check_run": &CheckRunEvent{}, + "check_suite": &CheckSuiteEvent{}, + "code_scanning_alert": &CodeScanningAlertEvent{}, + "commit_comment": &CommitCommentEvent{}, + "content_reference": &ContentReferenceEvent{}, + "create": &CreateEvent{}, + "custom_property": &CustomPropertyEvent{}, + "custom_property_values": &CustomPropertyValuesEvent{}, + "delete": &DeleteEvent{}, + "dependabot_alert": &DependabotAlertEvent{}, + "deploy_key": &DeployKeyEvent{}, + "deployment": &DeploymentEvent{}, + "deployment_review": &DeploymentReviewEvent{}, + "deployment_status": &DeploymentStatusEvent{}, + "deployment_protection_rule": &DeploymentProtectionRuleEvent{}, + "discussion": &DiscussionEvent{}, + "discussion_comment": &DiscussionCommentEvent{}, + "fork": &ForkEvent{}, + "github_app_authorization": &GitHubAppAuthorizationEvent{}, + "gollum": &GollumEvent{}, + "installation": &InstallationEvent{}, + "installation_repositories": &InstallationRepositoriesEvent{}, + "installation_target": &InstallationTargetEvent{}, + "issue_comment": &IssueCommentEvent{}, + "issues": &IssuesEvent{}, + "label": &LabelEvent{}, + "marketplace_purchase": &MarketplacePurchaseEvent{}, + "member": &MemberEvent{}, + "membership": &MembershipEvent{}, + "merge_group": &MergeGroupEvent{}, + "meta": &MetaEvent{}, + "milestone": &MilestoneEvent{}, + "organization": &OrganizationEvent{}, + "org_block": &OrgBlockEvent{}, + "package": &PackageEvent{}, + "page_build": &PageBuildEvent{}, + "personal_access_token_request": &PersonalAccessTokenRequestEvent{}, + "ping": &PingEvent{}, + "projects_v2": &ProjectV2Event{}, + "projects_v2_item": &ProjectV2ItemEvent{}, + "public": &PublicEvent{}, + "pull_request": &PullRequestEvent{}, + "pull_request_review": &PullRequestReviewEvent{}, + "pull_request_review_comment": &PullRequestReviewCommentEvent{}, + "pull_request_review_thread": &PullRequestReviewThreadEvent{}, + "pull_request_target": &PullRequestTargetEvent{}, + "push": &PushEvent{}, + "repository": &RepositoryEvent{}, + "repository_dispatch": &RepositoryDispatchEvent{}, + "repository_import": &RepositoryImportEvent{}, + "repository_ruleset": &RepositoryRulesetEvent{}, + "repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{}, + "release": &ReleaseEvent{}, + "secret_scanning_alert": &SecretScanningAlertEvent{}, + "secret_scanning_alert_location": &SecretScanningAlertLocationEvent{}, + "security_advisory": &SecurityAdvisoryEvent{}, + "security_and_analysis": &SecurityAndAnalysisEvent{}, + "sponsorship": &SponsorshipEvent{}, + "star": &StarEvent{}, + "status": &StatusEvent{}, + "team": &TeamEvent{}, + "team_add": &TeamAddEvent{}, + "user": &UserEvent{}, + "watch": &WatchEvent{}, + "workflow_dispatch": &WorkflowDispatchEvent{}, + "workflow_job": &WorkflowJobEvent{}, + "workflow_run": &WorkflowRunEvent{}, + } + // Forward mapping of event types to the string names of the structs. + messageToTypeName = make(map[string]string, len(eventTypeMapping)) + // Inverse map of the above. + typeToMessageMapping = make(map[string]string, len(eventTypeMapping)) +) + +func init() { + for k, v := range eventTypeMapping { + typename := reflect.TypeOf(v).Elem().Name() + messageToTypeName[k] = typename + typeToMessageMapping[typename] = k + } +} + +// genMAC generates the HMAC signature for a message provided the secret key +// and hashFunc. +func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { + mac := hmac.New(hashFunc, key) + mac.Write(message) + return mac.Sum(nil) +} + +// checkMAC reports whether messageMAC is a valid HMAC tag for message. +func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { + expectedMAC := genMAC(message, key, hashFunc) + return hmac.Equal(messageMAC, expectedMAC) +} + +// messageMAC returns the hex-decoded HMAC tag from the signature and its +// corresponding hash function. +func messageMAC(signature string) ([]byte, func() hash.Hash, error) { + if signature == "" { + return nil, nil, errors.New("missing signature") + } + sigParts := strings.SplitN(signature, "=", 2) + if len(sigParts) != 2 { + return nil, nil, fmt.Errorf("error parsing signature %q", signature) + } + + var hashFunc func() hash.Hash + switch sigParts[0] { + case sha1Prefix: + hashFunc = sha1.New + case sha256Prefix: + hashFunc = sha256.New + case sha512Prefix: + hashFunc = sha512.New + default: + return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) + } + + buf, err := hex.DecodeString(sigParts[1]) + if err != nil { + return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) + } + return buf, hashFunc, nil +} + +// ValidatePayloadFromBody validates an incoming GitHub Webhook event request body +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass an empty secretToken. +// Webhooks without a secret token are not secure and should be avoided. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// // read signature from request +// signature := "" +// payload, err := github.ValidatePayloadFromBody(r.Header.Get("Content-Type"), r.Body, signature, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +func ValidatePayloadFromBody(contentType string, readable io.Reader, signature string, secretToken []byte) (payload []byte, err error) { + var body []byte // Raw body that GitHub uses to calculate the signature. + + switch contentType { + case "application/json": + var err error + if body, err = io.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/json, + // the JSON payload is just the original body. + payload = body + + case "application/x-www-form-urlencoded": + // payloadFormParam is the name of the form parameter that the JSON payload + // will be in if a webhook has its content type set to application/x-www-form-urlencoded. + const payloadFormParam = "payload" + + var err error + if body, err = io.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/x-www-form-urlencoded, + // the JSON payload will be under the "payload" form param. + form, err := url.ParseQuery(string(body)) + if err != nil { + return nil, err + } + payload = []byte(form.Get(payloadFormParam)) + + default: + return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", contentType) + } + + // Validate the signature if present or if one is expected (secretToken is non-empty). + if len(secretToken) > 0 || len(signature) > 0 { + if err := ValidateSignature(signature, body, secretToken); err != nil { + return nil, err + } + } + + return payload, nil +} + +// ValidatePayload validates an incoming GitHub Webhook event request +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass nil or an empty slice. +// This is intended for local development purposes only and all webhooks should ideally set up a secret token. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) { + signature := r.Header.Get(SHA256SignatureHeader) + if signature == "" { + signature = r.Header.Get(SHA1SignatureHeader) + } + + contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return nil, err + } + + return ValidatePayloadFromBody(contentType, r.Body, signature, secretToken) +} + +// ValidateSignature validates the signature for the given payload. +// signature is the GitHub hash signature delivered in the X-Hub-Signature header. +// payload is the JSON payload sent by GitHub Webhooks. +// secretToken is the GitHub Webhook secret token. +// +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github +func ValidateSignature(signature string, payload, secretToken []byte) error { + messageMAC, hashFunc, err := messageMAC(signature) + if err != nil { + return err + } + if !checkMAC(payload, messageMAC, secretToken, hashFunc) { + return errors.New("payload signature check failed") + } + return nil +} + +// WebHookType returns the event type of webhook request r. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/github-event-types +func WebHookType(r *http.Request) string { + return r.Header.Get(EventTypeHeader) +} + +// DeliveryID returns the unique delivery ID of webhook request r. +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/events/github-event-types +func DeliveryID(r *http.Request) string { + return r.Header.Get(DeliveryIDHeader) +} + +// ParseWebHook parses the event payload. For recognized event types, a +// value of the corresponding struct type will be returned (as returned +// by Event.ParsePayload()). An error will be returned for unrecognized event +// types. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// event, err := github.ParseWebHook(github.WebHookType(r), payload) +// if err != nil { ... } +// switch event := event.(type) { +// case *github.CommitCommentEvent: +// processCommitCommentEvent(event) +// case *github.CreateEvent: +// processCreateEvent(event) +// ... +// } +// } +func ParseWebHook(messageType string, payload []byte) (interface{}, error) { + eventType, ok := messageToTypeName[messageType] + if !ok { + return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) + } + + event := Event{ + Type: &eventType, + RawPayload: (*json.RawMessage)(&payload), + } + return event.ParsePayload() +} + +// MessageTypes returns a sorted list of all the known GitHub event type strings +// supported by go-github. +func MessageTypes() []string { + types := make([]string, 0, len(eventTypeMapping)) + for t := range eventTypeMapping { + types = append(types, t) + } + sort.Strings(types) + return types +} + +// EventForType returns an empty struct matching the specified GitHub event type. +// If messageType does not match any known event types, it returns nil. +func EventForType(messageType string) interface{} { + prototype := eventTypeMapping[messageType] + if prototype == nil { + return nil + } + // return a _copy_ of the pointed-to-object. Unfortunately, for this we + // need to use reflection. If we store the actual objects in the map, + // we still need to use reflection to convert from `any` to the actual + // type, so this was deemed the lesser of two evils. (#2865) + return reflect.New(reflect.TypeOf(prototype).Elem()).Interface() +} diff --git a/vendor/github.com/google/go-github/v68/github/meta.go b/vendor/github.com/google/go-github/v68/github/meta.go new file mode 100644 index 00000000..cc90b618 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/meta.go @@ -0,0 +1,184 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" +) + +// MetaService provides access to functions in the GitHub API that GitHub categorizes as "meta". +type MetaService service + +// APIMeta represents metadata about the GitHub API. +type APIMeta struct { + // An array of IP addresses in CIDR format specifying the addresses + // that incoming service hooks will originate from on GitHub.com. + Hooks []string `json:"hooks,omitempty"` + + // An array of IP addresses in CIDR format specifying the Git servers + // for GitHub.com. + Git []string `json:"git,omitempty"` + + // Whether authentication with username and password is supported. + // (GitHub Enterprise instances using CAS or OAuth for authentication + // will return false. Features like Basic Authentication with a + // username and password, sudo mode, and two-factor authentication are + // not supported on these servers.) + VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Packages. + Packages []string `json:"packages,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Pages websites. + Pages []string `json:"pages,omitempty"` + + // An array of IP addresses specifying the addresses that source imports + // will originate from on GitHub.com. + Importer []string `json:"importer,omitempty"` + + // An array of IP addresses specifying the addresses that source imports + // will originate from on GitHub Enterprise Cloud. + GithubEnterpriseImporter []string `json:"github_enterprise_importer,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // GitHub Actions will originate from. + Actions []string `json:"actions,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // Dependabot will originate from. + Dependabot []string `json:"dependabot,omitempty"` + + // A map of algorithms to SSH key fingerprints. + SSHKeyFingerprints map[string]string `json:"ssh_key_fingerprints,omitempty"` + + // An array of SSH keys. + SSHKeys []string `json:"ssh_keys,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub websites. + Web []string `json:"web,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub APIs. + API []string `json:"api,omitempty"` + + // GitHub services and their associated domains. Note that many of these domains + // are represented as wildcards (e.g. "*.github.com"). + Domains *APIMetaDomains `json:"domains,omitempty"` +} + +// APIMetaDomains represents the domains associated with GitHub services. +type APIMetaDomains struct { + Website []string `json:"website,omitempty"` + Codespaces []string `json:"codespaces,omitempty"` + Copilot []string `json:"copilot,omitempty"` + Packages []string `json:"packages,omitempty"` + Actions []string `json:"actions,omitempty"` + ArtifactAttestations *APIMetaArtifactAttestations `json:"artifact_attestations,omitempty"` +} + +// APIMetaArtifactAttestations represents the artifact attestation services domains. +type APIMetaArtifactAttestations struct { + TrustDomain string `json:"trust_domain,omitempty"` + Services []string `json:"services,omitempty"` +} + +// Get returns information about GitHub.com, the service. Or, if you access +// this endpoint on your organization’s GitHub Enterprise installation, this +// endpoint provides information about that installation. +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-github-meta-information +// +//meta:operation GET /meta +func (s *MetaService) Get(ctx context.Context) (*APIMeta, *Response, error) { + req, err := s.client.NewRequest("GET", "meta", nil) + if err != nil { + return nil, nil, err + } + + meta := new(APIMeta) + resp, err := s.client.Do(ctx, req, meta) + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// APIMeta returns information about GitHub.com. +// +// Deprecated: Use MetaService.Get instead. +func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { + return c.Meta.Get(ctx) +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-octocat +// +//meta:operation GET /octocat +func (s *MetaService) Octocat(ctx context.Context, message string) (string, *Response, error) { + u := "octocat" + if message != "" { + u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +// +// Deprecated: Use MetaService.Octocat instead. +func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { + return c.Meta.Octocat(ctx, message) +} + +// Zen returns a random line from The Zen of GitHub. +// +// See also: http://warpspire.com/posts/taste/ +// +// GitHub API docs: https://docs.github.com/rest/meta/meta#get-the-zen-of-github +// +//meta:operation GET /zen +func (s *MetaService) Zen(ctx context.Context) (string, *Response, error) { + req, err := s.client.NewRequest("GET", "zen", nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := s.client.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Zen returns a random line from The Zen of GitHub. +// +// Deprecated: Use MetaService.Zen instead. +func (c *Client) Zen(ctx context.Context) (string, *Response, error) { + return c.Meta.Zen(ctx) +} diff --git a/vendor/github.com/google/go-github/github/migrations.go b/vendor/github.com/google/go-github/v68/github/migrations.go similarity index 82% rename from vendor/github.com/google/go-github/github/migrations.go rename to vendor/github.com/google/go-github/v68/github/migrations.go index 90cc1fae..766c4c38 100644 --- a/vendor/github.com/google/go-github/github/migrations.go +++ b/vendor/github.com/google/go-github/v68/github/migrations.go @@ -16,7 +16,7 @@ import ( // MigrationService provides access to the migration related functions // in the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/migration/ +// GitHub API docs: https://docs.github.com/rest/migration/ type MigrationService service // Migration represents a GitHub migration (archival). @@ -74,14 +74,16 @@ type startMigration struct { // StartMigration starts the generation of a migration archive. // repos is a slice of repository names to migrate. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#start-a-migration -func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opt *MigrationOptions) (*Migration, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#start-an-organization-migration +// +//meta:operation POST /orgs/{org}/migrations +func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) body := &startMigration{Repositories: repos} - if opt != nil { - body.LockRepositories = Bool(opt.LockRepositories) - body.ExcludeAttachments = Bool(opt.ExcludeAttachments) + if opts != nil { + body.LockRepositories = Ptr(opts.LockRepositories) + body.ExcludeAttachments = Ptr(opts.ExcludeAttachments) } req, err := s.client.NewRequest("POST", u, body) @@ -103,9 +105,15 @@ func (s *MigrationService) StartMigration(ctx context.Context, org string, repos // ListMigrations lists the most recent migrations. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations -func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*Migration, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#list-organization-migrations +// +//meta:operation GET /orgs/{org}/migrations +func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -127,7 +135,9 @@ func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*M // MigrationStatus gets the status of a specific migration archive. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-the-status-of-a-migration +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#get-an-organization-migration-status +// +//meta:operation GET /orgs/{org}/migrations/{migration_id} func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) @@ -151,7 +161,9 @@ func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id i // MigrationArchiveURL fetches a migration archive URL. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#download-a-migration-archive +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#download-an-organization-migration-archive +// +//meta:operation GET /orgs/{org}/migrations/{migration_id}/archive func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) @@ -188,7 +200,9 @@ func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, // DeleteMigration deletes a previous migration archive. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#delete-a-migration-archive +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#delete-an-organization-migration-archive +// +//meta:operation DELETE /orgs/{org}/migrations/{migration_id}/archive func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) @@ -208,7 +222,9 @@ func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id i // You should unlock each migrated repository and delete them when the migration // is complete and you no longer need the source data. // -// GitHub API docs: https://developer.github.com/v3/migration/migrations/#unlock-a-repository +// GitHub API docs: https://docs.github.com/rest/migrations/orgs#unlock-an-organization-repository +// +//meta:operation DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) diff --git a/vendor/github.com/google/go-github/github/migrations_source_import.go b/vendor/github.com/google/go-github/v68/github/migrations_source_import.go similarity index 84% rename from vendor/github.com/google/go-github/github/migrations_source_import.go rename to vendor/github.com/google/go-github/v68/github/migrations_source_import.go index fd45e780..f484b77d 100644 --- a/vendor/github.com/google/go-github/github/migrations_source_import.go +++ b/vendor/github.com/google/go-github/v68/github/migrations_source_import.go @@ -76,7 +76,7 @@ type Import struct { // Contact GitHub support for more information. // detection_needs_auth - the importer requires authentication for // the originating repository to continue detection. Make an - // UpdatImport request, and include VCSUsername and + // UpdateImport request, and include VCSUsername and // VCSPassword. // detection_found_nothing - the importer didn't recognize any // source control at the URL. @@ -106,7 +106,7 @@ type Import struct { // When the importer finds several projects or repositories at the // provided URLs, this will identify the available choices. Call // UpdateImport with the selected Import value. - ProjectChoices []Import `json:"project_choices,omitempty"` + ProjectChoices []*Import `json:"project_choices,omitempty"` } func (i Import) String() string { @@ -115,7 +115,7 @@ func (i Import) String() string { // SourceImportAuthor identifies an author imported from a source repository. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors +// GitHub API docs: https://docs.github.com/rest/migration/source_imports/#get-commit-authors type SourceImportAuthor struct { ID *int64 `json:"id,omitempty"` RemoteID *string `json:"remote_id,omitempty"` @@ -132,7 +132,7 @@ func (a SourceImportAuthor) String() string { // LargeFile identifies a file larger than 100MB found during a repository import. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files +// GitHub API docs: https://docs.github.com/rest/migration/source_imports/#get-large-files type LargeFile struct { RefName *string `json:"ref_name,omitempty"` Path *string `json:"path,omitempty"` @@ -146,7 +146,9 @@ func (f LargeFile) String() string { // StartImport initiates a repository import. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#start-an-import +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#start-an-import +// +//meta:operation PUT /repos/{owner}/{repo}/import func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("PUT", u, in) @@ -154,9 +156,6 @@ func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { @@ -168,7 +167,9 @@ func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, // ImportProgress queries for the status and progress of an ongoing repository import. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-import-progress +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-an-import-status +// +//meta:operation GET /repos/{owner}/{repo}/import func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -176,9 +177,6 @@ func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo strin return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { @@ -190,7 +188,9 @@ func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo strin // UpdateImport initiates a repository import. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#update-existing-import +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#update-an-import +// +//meta:operation PATCH /repos/{owner}/{repo}/import func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("PATCH", u, in) @@ -198,9 +198,6 @@ func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { @@ -222,7 +219,9 @@ func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, // This method and MapCommitAuthor allow you to provide correct Git author // information. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-commit-authors +// +//meta:operation GET /repos/{owner}/{repo}/import/authors func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -230,9 +229,6 @@ func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - var authors []*SourceImportAuthor resp, err := s.client.Do(ctx, req, &authors) if err != nil { @@ -246,7 +242,9 @@ func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string // application can continue updating authors any time before you push new // commits to the repository. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#map-a-commit-author +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#map-a-commit-author +// +//meta:operation PATCH /repos/{owner}/{repo}/import/authors/{author_id} func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, author) @@ -254,9 +252,6 @@ func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo stri return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - out := new(SourceImportAuthor) resp, err := s.client.Do(ctx, req, out) if err != nil { @@ -270,7 +265,9 @@ func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo stri // files larger than 100MB. Only the UseLFS field on the provided Import is // used. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#update-git-lfs-preference +// +//meta:operation PATCH /repos/{owner}/{repo}/import/lfs func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo) req, err := s.client.NewRequest("PATCH", u, in) @@ -278,9 +275,6 @@ func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo str return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - out := new(Import) resp, err := s.client.Do(ctx, req, out) if err != nil { @@ -292,7 +286,9 @@ func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo str // LargeFiles lists files larger than 100MB found during the import. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#get-large-files +// +//meta:operation GET /repos/{owner}/{repo}/import/large_files func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) { u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -300,9 +296,6 @@ func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ( return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - var files []*LargeFile resp, err := s.client.Do(ctx, req, &files) if err != nil { @@ -314,7 +307,9 @@ func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ( // CancelImport stops an import for a repository. // -// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#cancel-an-import +// GitHub API docs: https://docs.github.com/rest/migrations/source-imports#cancel-an-import +// +//meta:operation DELETE /repos/{owner}/{repo}/import func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/import", owner, repo) req, err := s.client.NewRequest("DELETE", u, nil) @@ -322,8 +317,5 @@ func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) return nil, err } - // TODO: remove custom Accept header when this API fully launches - req.Header.Set("Accept", mediaTypeImportPreview) - return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/github/migrations_user.go b/vendor/github.com/google/go-github/v68/github/migrations_user.go similarity index 82% rename from vendor/github.com/google/go-github/github/migrations_user.go rename to vendor/github.com/google/go-github/v68/github/migrations_user.go index ae53e687..a7bd7949 100644 --- a/vendor/github.com/google/go-github/github/migrations_user.go +++ b/vendor/github.com/google/go-github/v68/github/migrations_user.go @@ -67,14 +67,16 @@ type startUserMigration struct { // StartUserMigration starts the generation of a migration archive. // repos is a slice of repository names to migrate. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration -func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opt *UserMigrationOptions) (*UserMigration, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/migrations/users#start-a-user-migration +// +//meta:operation POST /user/migrations +func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opts *UserMigrationOptions) (*UserMigration, *Response, error) { u := "user/migrations" body := &startUserMigration{Repositories: repos} - if opt != nil { - body.LockRepositories = Bool(opt.LockRepositories) - body.ExcludeAttachments = Bool(opt.ExcludeAttachments) + if opts != nil { + body.LockRepositories = Ptr(opts.LockRepositories) + body.ExcludeAttachments = Ptr(opts.ExcludeAttachments) } req, err := s.client.NewRequest("POST", u, body) @@ -96,9 +98,15 @@ func (s *MigrationService) StartUserMigration(ctx context.Context, repos []strin // ListUserMigrations lists the most recent migrations. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-list-of-user-migrations -func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/migrations/users#list-user-migrations +// +//meta:operation GET /user/migrations +func (s *MigrationService) ListUserMigrations(ctx context.Context, opts *ListOptions) ([]*UserMigration, *Response, error) { u := "user/migrations" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -120,7 +128,9 @@ func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigra // UserMigrationStatus gets the status of a specific migration archive. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-the-status-of-a-user-migration +// GitHub API docs: https://docs.github.com/rest/migrations/users#get-a-user-migration-status +// +//meta:operation GET /user/migrations/{migration_id} func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) { u := fmt.Sprintf("user/migrations/%v", id) @@ -144,7 +154,9 @@ func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (* // UserMigrationArchiveURL gets the URL for a specific migration archive. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#download-a-user-migration-archive +// GitHub API docs: https://docs.github.com/rest/migrations/users#download-a-user-migration-archive +// +//meta:operation GET /user/migrations/{migration_id}/archive func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) { url := fmt.Sprintf("user/migrations/%v/archive", id) @@ -178,7 +190,9 @@ func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64 // DeleteUserMigration will delete a previous migration archive. // id is the migration ID. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#delete-a-user-migration-archive +// GitHub API docs: https://docs.github.com/rest/migrations/users#delete-a-user-migration-archive +// +//meta:operation DELETE /user/migrations/{migration_id}/archive func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) { url := fmt.Sprintf("user/migrations/%v/archive", id) @@ -193,12 +207,14 @@ func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (* return s.client.Do(ctx, req, nil) } -// UnlockUserRepository will unlock a repo that was locked for migration. +// UnlockUserRepo will unlock a repo that was locked for migration. // id is migration ID. // You should unlock each migrated repository and delete them when the migration // is complete and you no longer need the source data. // -// GitHub API docs: https://developer.github.com/v3/migrations/users/#unlock-a-user-repository +// GitHub API docs: https://docs.github.com/rest/migrations/users#unlock-a-user-repository +// +//meta:operation DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) { url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo) diff --git a/vendor/github.com/google/go-github/v68/github/orgs.go b/vendor/github.com/google/go-github/v68/github/orgs.go new file mode 100644 index 00000000..27c0f102 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs.go @@ -0,0 +1,318 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationsService provides access to the organization related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/orgs/ +type OrganizationsService service + +// Organization represents a GitHub organization account. +type Organization struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + Description *string `json:"description,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + TotalPrivateRepos *int64 `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int64 `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + BillingEmail *string `json:"billing_email,omitempty"` + Type *string `json:"type,omitempty"` + Plan *Plan `json:"plan,omitempty"` + TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"` + IsVerified *bool `json:"is_verified,omitempty"` + HasOrganizationProjects *bool `json:"has_organization_projects,omitempty"` + HasRepositoryProjects *bool `json:"has_repository_projects,omitempty"` + + // DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Edit. + DefaultRepoPermission *string `json:"default_repository_permission,omitempty"` + // DefaultRepoSettings can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Get. + DefaultRepoSettings *string `json:"default_repository_settings,omitempty"` + + // MembersCanCreateRepos default value is true and is only used in Organizations.Edit. + MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"` + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/#rest-v3-api + MembersCanCreatePublicRepos *bool `json:"members_can_create_public_repositories,omitempty"` + MembersCanCreatePrivateRepos *bool `json:"members_can_create_private_repositories,omitempty"` + MembersCanCreateInternalRepos *bool `json:"members_can_create_internal_repositories,omitempty"` + + // MembersCanForkPrivateRepos toggles whether organization members can fork private organization repositories. + MembersCanForkPrivateRepos *bool `json:"members_can_fork_private_repositories,omitempty"` + + // MembersAllowedRepositoryCreationType denotes if organization members can create repositories + // and the type of repositories they can create. Possible values are: "all", "private", or "none". + // + // Deprecated: Use MembersCanCreatePublicRepos, MembersCanCreatePrivateRepos, MembersCanCreateInternalRepos + // instead. The new fields overrides the existing MembersAllowedRepositoryCreationType during 'edit' + // operation and does not consider 'internal' repositories during 'get' operation + MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"` + + // MembersCanCreatePages toggles whether organization members can create GitHub Pages sites. + MembersCanCreatePages *bool `json:"members_can_create_pages,omitempty"` + // MembersCanCreatePublicPages toggles whether organization members can create public GitHub Pages sites. + MembersCanCreatePublicPages *bool `json:"members_can_create_public_pages,omitempty"` + // MembersCanCreatePrivatePages toggles whether organization members can create private GitHub Pages sites. + MembersCanCreatePrivatePages *bool `json:"members_can_create_private_pages,omitempty"` + // WebCommitSignoffRequire toggles + WebCommitSignoffRequired *bool `json:"web_commit_signoff_required,omitempty"` + // AdvancedSecurityAuditLogEnabled toggles whether the advanced security audit log is enabled. + AdvancedSecurityEnabledForNewRepos *bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` + // DependabotAlertsEnabled toggles whether dependabot alerts are enabled. + DependabotAlertsEnabledForNewRepos *bool `json:"dependabot_alerts_enabled_for_new_repositories,omitempty"` + // DependabotSecurityUpdatesEnabled toggles whether dependabot security updates are enabled. + DependabotSecurityUpdatesEnabledForNewRepos *bool `json:"dependabot_security_updates_enabled_for_new_repositories,omitempty"` + // DependabotGraphEnabledForNewRepos toggles whether dependabot graph is enabled on new repositories. + DependencyGraphEnabledForNewRepos *bool `json:"dependency_graph_enabled_for_new_repositories,omitempty"` + // SecretScanningEnabled toggles whether secret scanning is enabled on new repositories. + SecretScanningEnabledForNewRepos *bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` + // SecretScanningPushProtectionEnabledForNewRepos toggles whether secret scanning push protection is enabled on new repositories. + SecretScanningPushProtectionEnabledForNewRepos *bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` + // SecretScanningValidityChecksEnabled toggles whether secret scanning validity check is enabled. + SecretScanningValidityChecksEnabled *bool `json:"secret_scanning_validity_checks_enabled,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + PublicMembersURL *string `json:"public_members_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` +} + +// OrganizationInstallations represents GitHub app installations for an organization. +type OrganizationInstallations struct { + TotalCount *int `json:"total_count,omitempty"` + Installations []*Installation `json:"installations,omitempty"` +} + +func (o Organization) String() string { + return Stringify(o) +} + +// Plan represents the payment plan for an account. See plans at https://github.com/plans. +type Plan struct { + Name *string `json:"name,omitempty"` + Space *int `json:"space,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + PrivateRepos *int64 `json:"private_repos,omitempty"` + FilledSeats *int `json:"filled_seats,omitempty"` + Seats *int `json:"seats,omitempty"` +} + +func (p Plan) String() string { + return Stringify(p) +} + +// OrganizationsListOptions specifies the optional parameters to the +// OrganizationsService.ListAll method. +type OrganizationsListOptions struct { + // Since filters Organizations by ID. + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all organizations, in the order that they were created on GitHub. +// +// Note: Pagination is powered exclusively by the since parameter. To continue +// listing the next set of organizations, use the ID of the last-returned organization +// as the opts.Since parameter for the next call. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations +// +//meta:operation GET /organizations +func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsListOptions) ([]*Organization, *Response, error) { + u, err := addOptions("organizations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := []*Organization{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + return orgs, resp, nil +} + +// List the organizations for a user. Passing the empty string will list +// organizations for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations-for-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user +// +//meta:operation GET /user/orgs +//meta:operation GET /users/{username}/orgs +func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/orgs", user) + } else { + u = "user/orgs" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var orgs []*Organization + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// Get fetches an organization by name. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#get-an-organization +// +//meta:operation GET /orgs/{org} +func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// GetByID fetches an organization. +// +// Note: GetByID uses the undocumented GitHub API endpoint "GET /organizations/{organization_id}". +// +//meta:operation GET /organizations/{organization_id} +func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { + u := fmt.Sprintf("organizations/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// Edit an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#update-an-organization +// +//meta:operation PATCH /orgs/{org} +func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", name) + req, err := s.client.NewRequest("PATCH", u, org) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// Delete an organization by name. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#delete-an-organization +// +//meta:operation DELETE /orgs/{org} +func (s *OrganizationsService) Delete(ctx context.Context, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListInstallations lists installations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-app-installations-for-an-organization +// +//meta:operation GET /orgs/{org}/installations +func (s *OrganizationsService) ListInstallations(ctx context.Context, org string, opts *ListOptions) (*OrganizationInstallations, *Response, error) { + u := fmt.Sprintf("orgs/%v/installations", org) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(OrganizationInstallations) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go b/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go new file mode 100644 index 00000000..b115e094 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go @@ -0,0 +1,34 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetActionsAllowed gets the actions that are allowed in an organization. +// +// Deprecated: please use `client.Actions.GetActionsAllowed` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions/selected-actions +func (s *OrganizationsService) GetActionsAllowed(ctx context.Context, org string) (*ActionsAllowed, *Response, error) { + s2 := (*ActionsService)(s) + return s2.GetActionsAllowed(ctx, org) +} + +// EditActionsAllowed sets the actions that are allowed in an organization. +// +// Deprecated: please use `client.Actions.EditActionsAllowed` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions/selected-actions +func (s *OrganizationsService) EditActionsAllowed(ctx context.Context, org string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + s2 := (*ActionsService)(s) + return s2.EditActionsAllowed(ctx, org, actionsAllowed) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go b/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go new file mode 100644 index 00000000..97df1c96 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go @@ -0,0 +1,34 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in an organization. +// +// Deprecated: please use `client.Actions.GetActionsPermissions` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/permissions +func (s *OrganizationsService) GetActionsPermissions(ctx context.Context, org string) (*ActionsPermissions, *Response, error) { + s2 := (*ActionsService)(s) + return s2.GetActionsPermissions(ctx, org) +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in an organization. +// +// Deprecated: please use `client.Actions.EditActionsPermissions` instead. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-an-organization +// +//meta:operation PUT /orgs/{org}/actions/permissions +func (s *OrganizationsService) EditActionsPermissions(ctx context.Context, org string, actionsPermissions ActionsPermissions) (*ActionsPermissions, *Response, error) { + s2 := (*ActionsService)(s) + return s2.EditActionsPermissions(ctx, org, actionsPermissions) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_attestations.go b/vendor/github.com/google/go-github/v68/github/orgs_attestations.go new file mode 100644 index 00000000..3d5793c1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_attestations.go @@ -0,0 +1,40 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with repositories +// owned by an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/orgs#list-attestations +// +//meta:operation GET /orgs/{org}/attestations/{subject_digest} +func (s *OrganizationsService) ListAttestations(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("orgs/%v/attestations/%v", org, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + resp, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, resp, err + } + + return attestations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go b/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go new file mode 100644 index 00000000..025c5d02 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go @@ -0,0 +1,142 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// GetAuditLogOptions sets up optional parameters to query audit-log endpoint. +type GetAuditLogOptions struct { + Phrase *string `url:"phrase,omitempty"` // A search phrase. (Optional.) + Include *string `url:"include,omitempty"` // Event type includes. Can be one of "web", "git", "all". Default: "web". (Optional.) + Order *string `url:"order,omitempty"` // The order of audit log events. Can be one of "asc" or "desc". Default: "desc". (Optional.) + + ListCursorOptions +} + +// ActorLocation contains information about reported location for an actor. +type ActorLocation struct { + CountryCode *string `json:"country_code,omitempty"` +} + +// AuditEntry describes the fields that may be represented by various audit-log "action" entries. +// There are many other fields that may be present depending on the action. You can access those +// in AdditionalFields. +// For a list of actions see - https://docs.github.com/github/setting-up-and-managing-organizations-and-teams/reviewing-the-audit-log-for-your-organization#audit-log-actions +type AuditEntry struct { + Action *string `json:"action,omitempty"` // The name of the action that was performed, for example `user.login` or `repo.create`. + Actor *string `json:"actor,omitempty"` // The actor who performed the action. + ActorID *int64 `json:"actor_id,omitempty"` + ActorLocation *ActorLocation `json:"actor_location,omitempty"` + Business *string `json:"business,omitempty"` + BusinessID *int64 `json:"business_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + DocumentID *string `json:"_document_id,omitempty"` + ExternalIdentityNameID *string `json:"external_identity_nameid,omitempty"` + ExternalIdentityUsername *string `json:"external_identity_username,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + Org *string `json:"org,omitempty"` + OrgID *int64 `json:"org_id,omitempty"` + Timestamp *Timestamp `json:"@timestamp,omitempty"` // The time the audit log event occurred, given as a [Unix timestamp](http://en.wikipedia.org/wiki/Unix_time). + TokenID *int64 `json:"token_id,omitempty"` + TokenScopes *string `json:"token_scopes,omitempty"` + User *string `json:"user,omitempty"` // The user that was affected by the action performed (if available). + UserID *int64 `json:"user_id,omitempty"` + + // Some events types have a data field that contains additional information about the event. + Data map[string]interface{} `json:"data,omitempty"` + + // All fields that are not explicitly defined in the struct are captured here. + AdditionalFields map[string]interface{} `json:"-"` +} + +func (a *AuditEntry) UnmarshalJSON(data []byte) error { + type entryAlias AuditEntry + var v entryAlias + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + rawDefinedFields, err := json.Marshal(v) + if err != nil { + return err + } + definedFields := map[string]interface{}{} + if err := json.Unmarshal(rawDefinedFields, &definedFields); err != nil { + return err + } + + if err := json.Unmarshal(data, &v.AdditionalFields); err != nil { + return err + } + + for key, val := range v.AdditionalFields { + if _, ok := definedFields[key]; ok || val == nil { + delete(v.AdditionalFields, key) + } + } + + *a = AuditEntry(v) + if len(v.AdditionalFields) == 0 { + a.AdditionalFields = nil + } + return nil +} + +func (a *AuditEntry) MarshalJSON() ([]byte, error) { + type entryAlias AuditEntry + v := entryAlias(*a) + defBytes, err := json.Marshal(v) + if err != nil { + return nil, err + } + if len(a.AdditionalFields) == 0 { + return defBytes, err + } + resMap := map[string]interface{}{} + if err := json.Unmarshal(defBytes, &resMap); err != nil { + return nil, err + } + for key, val := range a.AdditionalFields { + if val == nil { + continue + } + if _, ok := resMap[key]; ok { + return nil, fmt.Errorf("unexpected field in AdditionalFields: %v", key) + } + resMap[key] = val + } + return json.Marshal(resMap) +} + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#get-the-audit-log-for-an-organization +// +//meta:operation GET /orgs/{org}/audit-log +func (s *OrganizationsService) GetAuditLog(ctx context.Context, org string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("orgs/%v/audit-log", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go b/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go new file mode 100644 index 00000000..b25845a4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go @@ -0,0 +1,284 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// DependencyGraphAutosubmitActionOptions represents the options for the DependencyGraphAutosubmitAction. +type DependencyGraphAutosubmitActionOptions struct { + LabeledRunners *bool `json:"labeled_runners,omitempty"` +} + +// CodeSecurityConfiguration represents a code security configuration. +type CodeSecurityConfiguration struct { + ID *int64 `json:"id,omitempty"` + TargetType *string `json:"target_type,omitempty"` + Name *string `json:"name"` + Description *string `json:"description,omitempty"` + AdvancedSecurity *string `json:"advanced_security,omitempty"` + DependencyGraph *string `json:"dependency_graph,omitempty"` + DependencyGraphAutosubmitAction *string `json:"dependency_graph_autosubmit_action,omitempty"` + DependencyGraphAutosubmitActionOptions *DependencyGraphAutosubmitActionOptions `json:"dependency_graph_autosubmit_action_options,omitempty"` + DependabotAlerts *string `json:"dependabot_alerts,omitempty"` + DependabotSecurityUpdates *string `json:"dependabot_security_updates,omitempty"` + CodeScanningDefaultSetup *string `json:"code_scanning_default_setup,omitempty"` + SecretScanning *string `json:"secret_scanning,omitempty"` + SecretScanningPushProtection *string `json:"secret_scanning_push_protection,omitempty"` + SecretScanningValidityChecks *string `json:"secret_scanning_validity_checks,omitempty"` + SecretScanningNonProviderPatterns *string `json:"secret_scanning_non_provider_patterns,omitempty"` + PrivateVulnerabilityReporting *string `json:"private_vulnerability_reporting,omitempty"` + Enforcement *string `json:"enforcement,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// CodeSecurityConfigurationWithDefaultForNewRepos represents a code security configuration with default for new repos param. +type CodeSecurityConfigurationWithDefaultForNewRepos struct { + Configuration *CodeSecurityConfiguration `json:"configuration"` + DefaultForNewRepos *string `json:"default_for_new_repos"` +} + +// RepositoryCodeSecurityConfiguration represents a code security configuration for a repository. +type RepositoryCodeSecurityConfiguration struct { + State *string `json:"state,omitempty"` + Configuration *CodeSecurityConfiguration `json:"configuration,omitempty"` +} + +// GetCodeSecurityConfigurations gets code security configurations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-code-security-configurations-for-an-organization +// +//meta:operation GET /orgs/{org}/code-security/configurations +func (s *OrganizationsService) GetCodeSecurityConfigurations(ctx context.Context, org string) ([]*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configurations []*CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configurations) + if err != nil { + return nil, resp, err + } + return configurations, resp, nil +} + +// CreateCodeSecurityConfiguration creates a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#create-a-code-security-configuration +// +//meta:operation POST /orgs/{org}/code-security/configurations +func (s *OrganizationsService) CreateCodeSecurityConfiguration(ctx context.Context, org string, c *CodeSecurityConfiguration) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations", org) + + req, err := s.client.NewRequest("POST", u, c) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// GetDefaultCodeSecurityConfigurations gets default code security configurations for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-default-code-security-configurations +// +//meta:operation GET /orgs/{org}/code-security/configurations/defaults +func (s *OrganizationsService) GetDefaultCodeSecurityConfigurations(ctx context.Context, org string) ([]*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/defaults", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configurations []*CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configurations) + if err != nil { + return nil, resp, err + } + return configurations, resp, nil +} + +// DetachCodeSecurityConfigurationsFromRepositories detaches code security configuration from an organization's repositories. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#detach-configurations-from-repositories +// +//meta:operation DELETE /orgs/{org}/code-security/configurations/detach +func (s *OrganizationsService) DetachCodeSecurityConfigurationsFromRepositories(ctx context.Context, org string, repoIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/detach", org) + type selectedRepoIDs struct { + SelectedIDs []int64 `json:"selected_repository_ids"` + } + req, err := s.client.NewRequest("DELETE", u, selectedRepoIDs{SelectedIDs: repoIDs}) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// GetCodeSecurityConfiguration gets a code security configuration available in an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-a-code-security-configuration +// +//meta:operation GET /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) GetCodeSecurityConfiguration(ctx context.Context, org string, id int64) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// UpdateCodeSecurityConfiguration updates a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#update-a-code-security-configuration +// +//meta:operation PATCH /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) UpdateCodeSecurityConfiguration(ctx context.Context, org string, id int64, c *CodeSecurityConfiguration) (*CodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("PATCH", u, c) + if err != nil { + return nil, nil, err + } + + var configuration *CodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// DeleteCodeSecurityConfiguration deletes a code security configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#delete-a-code-security-configuration +// +//meta:operation DELETE /orgs/{org}/code-security/configurations/{configuration_id} +func (s *OrganizationsService) DeleteCodeSecurityConfiguration(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v", org, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// AttachCodeSecurityConfigurationsToRepositories attaches code security configurations to repositories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#attach-a-configuration-to-repositories +// +//meta:operation POST /orgs/{org}/code-security/configurations/{configuration_id}/attach +func (s *OrganizationsService) AttachCodeSecurityConfigurationsToRepositories(ctx context.Context, org string, id int64, scope string, repoIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/attach", org, id) + type selectedRepoIDs struct { + Scope string `json:"scope"` + SelectedIDs []int64 `json:"selected_repository_ids,omitempty"` + } + req, err := s.client.NewRequest("POST", u, selectedRepoIDs{Scope: scope, SelectedIDs: repoIDs}) + if err != nil { + return nil, err + } + resp, err := s.client.Do(ctx, req, nil) + if err != nil && resp.StatusCode != http.StatusAccepted { // StatusAccepted(202) is the expected status code as job is queued for processing + return resp, err + } + return resp, nil +} + +// SetDefaultCodeSecurityConfiguration sets a code security configuration as the default for an organization. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#set-a-code-security-configuration-as-a-default-for-an-organization +// +//meta:operation PUT /orgs/{org}/code-security/configurations/{configuration_id}/defaults +func (s *OrganizationsService) SetDefaultCodeSecurityConfiguration(ctx context.Context, org string, id int64, newReposParam string) (*CodeSecurityConfigurationWithDefaultForNewRepos, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/defaults", org, id) + type configParam struct { + DefaultForNewRepos string `json:"default_for_new_repos"` + } + req, err := s.client.NewRequest("PUT", u, configParam{DefaultForNewRepos: newReposParam}) + if err != nil { + return nil, nil, err + } + var c *CodeSecurityConfigurationWithDefaultForNewRepos + resp, err := s.client.Do(ctx, req, &c) + if err != nil { + return nil, resp, err + } + return c, resp, nil +} + +// GetRepositoriesForCodeSecurityConfiguration gets repositories associated with a code security configuration. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-repositories-associated-with-a-code-security-configuration +// +//meta:operation GET /orgs/{org}/code-security/configurations/{configuration_id}/repositories +func (s *OrganizationsService) GetRepositoriesForCodeSecurityConfiguration(ctx context.Context, org string, id int64) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-security/configurations/%v/repositories", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repositories []*Repository + resp, err := s.client.Do(ctx, req, &repositories) + if err != nil { + return nil, resp, err + } + return repositories, resp, nil +} + +// GetCodeSecurityConfigurationForRepository gets code security configuration that manages a repository's code security settings. +// +// GitHub API docs: https://docs.github.com/rest/code-security/configurations#get-the-code-security-configuration-associated-with-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/code-security-configuration +func (s *OrganizationsService) GetCodeSecurityConfigurationForRepository(ctx context.Context, org, repo string) (*RepositoryCodeSecurityConfiguration, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-security-configuration", org, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + var repoConfig *RepositoryCodeSecurityConfiguration + resp, err := s.client.Do(ctx, req, &repoConfig) + if err != nil { + return nil, resp, err + } + return repoConfig, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go b/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go new file mode 100644 index 00000000..dca42433 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go @@ -0,0 +1,109 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// CredentialAuthorization represents a credential authorized through SAML SSO. +type CredentialAuthorization struct { + // User login that owns the underlying credential. + Login *string `json:"login,omitempty"` + + // Unique identifier for the credential. + CredentialID *int64 `json:"credential_id,omitempty"` + + // Human-readable description of the credential type. + CredentialType *string `json:"credential_type,omitempty"` + + // Last eight characters of the credential. + // Only included in responses with credential_type of personal access token. + TokenLastEight *string `json:"token_last_eight,omitempty"` + + // Date when the credential was authorized for use. + CredentialAuthorizedAt *Timestamp `json:"credential_authorized_at,omitempty"` + + // Date when the credential was last accessed. + // May be null if it was never accessed. + CredentialAccessedAt *Timestamp `json:"credential_accessed_at,omitempty"` + + // List of oauth scopes the token has been granted. + Scopes []string `json:"scopes,omitempty"` + + // Unique string to distinguish the credential. + // Only included in responses with credential_type of SSH Key. + Fingerprint *string `json:"fingerprint,omitempty"` + + AuthorizedCredentialID *int64 `json:"authorized_credential_id,omitempty"` + + // The title given to the ssh key. + // This will only be present when the credential is an ssh key. + AuthorizedCredentialTitle *string `json:"authorized_credential_title,omitempty"` + + // The note given to the token. + // This will only be present when the credential is a token. + AuthorizedCredentialNote *string `json:"authorized_credential_note,omitempty"` + + // The expiry for the token. + // This will only be present when the credential is a token. + AuthorizedCredentialExpiresAt *Timestamp `json:"authorized_credential_expires_at,omitempty"` +} + +// CredentialAuthorizationsListOptions adds the Login option as supported by the +// list SAML SSO authorizations for organizations endpoint alongside paging options +// such as Page and PerPage. +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#list-saml-sso-authorizations-for-an-organization +type CredentialAuthorizationsListOptions struct { + ListOptions + // For credentials authorizations for an organization, limit the list of authorizations to a specific login (aka github username) + Login string `url:"login,omitempty"` +} + +// ListCredentialAuthorizations lists credentials authorized through SAML SSO +// for a given organization. Only available with GitHub Enterprise Cloud. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#list-saml-sso-authorizations-for-an-organization +// +//meta:operation GET /orgs/{org}/credential-authorizations +func (s *OrganizationsService) ListCredentialAuthorizations(ctx context.Context, org string, opts *CredentialAuthorizationsListOptions) ([]*CredentialAuthorization, *Response, error) { + u := fmt.Sprintf("orgs/%v/credential-authorizations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, u, nil) + if err != nil { + return nil, nil, err + } + + var creds []*CredentialAuthorization + resp, err := s.client.Do(ctx, req, &creds) + if err != nil { + return nil, resp, err + } + + return creds, resp, nil +} + +// RemoveCredentialAuthorization revokes the SAML SSO authorization for a given +// credential within an organization. Only available with GitHub Enterprise Cloud. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/orgs#remove-a-saml-sso-authorization-for-an-organization +// +//meta:operation DELETE /orgs/{org}/credential-authorizations/{credential_id} +func (s *OrganizationsService) RemoveCredentialAuthorization(ctx context.Context, org string, credentialID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/credential-authorizations/%v", org, credentialID) + req, err := s.client.NewRequest(http.MethodDelete, u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go b/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go new file mode 100644 index 00000000..44408db1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go @@ -0,0 +1,154 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationCustomRepoRoles represents custom repository roles available in specified organization. +type OrganizationCustomRepoRoles struct { + TotalCount *int `json:"total_count,omitempty"` + CustomRepoRoles []*CustomRepoRoles `json:"custom_roles,omitempty"` +} + +// CustomRepoRoles represents custom repository roles for an organization. +// See https://docs.github.com/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization +// for more information. +type CustomRepoRoles struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions []string `json:"permissions,omitempty"` + Org *Organization `json:"organization,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// CreateOrUpdateCustomRepoRoleOptions represents options required to create or update a custom repository role. +type CreateOrUpdateCustomRepoRoleOptions struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + BaseRole *string `json:"base_role,omitempty"` + Permissions []string `json:"permissions"` +} + +// ListCustomRepoRoles lists the custom repository roles available in this organization. +// In order to see custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#list-custom-repository-roles-in-an-organization +// +//meta:operation GET /orgs/{org}/custom-repository-roles +func (s *OrganizationsService) ListCustomRepoRoles(ctx context.Context, org string) (*OrganizationCustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + customRepoRoles := new(OrganizationCustomRepoRoles) + resp, err := s.client.Do(ctx, req, customRepoRoles) + if err != nil { + return nil, resp, err + } + + return customRepoRoles, resp, nil +} + +// GetCustomRepoRole gets a custom repository roles available in this organization. +// In order to see custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#get-a-custom-repository-role +// +//meta:operation GET /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) GetCustomRepoRole(ctx context.Context, org string, roleID int64) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, nil +} + +// CreateCustomRepoRole creates a custom repository role in this organization. +// In order to create custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#create-a-custom-repository-role +// +//meta:operation POST /orgs/{org}/custom-repository-roles +func (s *OrganizationsService) CreateCustomRepoRole(ctx context.Context, org string, opts *CreateOrUpdateCustomRepoRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// UpdateCustomRepoRole updates a custom repository role in this organization. +// In order to update custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#update-a-custom-repository-role +// +//meta:operation PATCH /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) UpdateCustomRepoRole(ctx context.Context, org string, roleID int64, opts *CreateOrUpdateCustomRepoRoleOptions) (*CustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// DeleteCustomRepoRole deletes an existing custom repository role in this organization. +// In order to delete custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#delete-a-custom-repository-role +// +//meta:operation DELETE /orgs/{org}/custom-repository-roles/{role_id} +func (s *OrganizationsService) DeleteCustomRepoRole(ctx context.Context, org string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/custom-repository-roles/%v", org, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resultingRole := new(CustomRepoRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_hooks.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks.go similarity index 63% rename from vendor/github.com/google/go-github/github/orgs_hooks.go rename to vendor/github.com/google/go-github/v68/github/orgs_hooks.go index ab1d02da..c2eef77c 100644 --- a/vendor/github.com/google/go-github/github/orgs_hooks.go +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks.go @@ -12,10 +12,12 @@ import ( // ListHooks lists all Hooks for the specified organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks -func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *ListOptions) ([]*Hook, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#list-organization-webhooks +// +//meta:operation GET /orgs/{org}/hooks +func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opts *ListOptions) ([]*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks", org) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -36,25 +38,45 @@ func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *L // GetHook returns a single specified Hook. // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id} func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } + hook := new(Hook) resp, err := s.client.Do(ctx, req, hook) - return hook, resp, err + if err != nil { + return nil, resp, err + } + + return hook, resp, nil } // CreateHook creates a Hook for the specified org. -// Name and Config are required fields. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#create-an-organization-webhook // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook +//meta:operation POST /orgs/{org}/hooks func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks", org) - req, err := s.client.NewRequest("POST", u, hook) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) if err != nil { return nil, nil, err } @@ -70,38 +92,51 @@ func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook // EditHook updates a specified Hook. // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#update-an-organization-webhook +// +//meta:operation PATCH /orgs/{org}/hooks/{hook_id} func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("PATCH", u, hook) if err != nil { return nil, nil, err } + h := new(Hook) resp, err := s.client.Do(ctx, req, h) - return h, resp, err + if err != nil { + return nil, resp, err + } + + return h, resp, nil } // PingHook triggers a 'ping' event to be sent to the Hook. // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#ping-an-organization-webhook +// +//meta:operation POST /orgs/{org}/hooks/{hook_id}/pings func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } // DeleteHook deletes a specified Hook. // -// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#delete-an-organization-webhook +// +//meta:operation DELETE /orgs/{org}/hooks/{hook_id} func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go new file mode 100644 index 00000000..aeb616fc --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go @@ -0,0 +1,53 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetHookConfiguration returns the configuration for the specified organization webhook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-a-webhook-configuration-for-an-organization +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/config +func (s *OrganizationsService) GetHookConfiguration(ctx context.Context, org string, id int64) (*HookConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/config", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// EditHookConfiguration updates the configuration for the specified organization webhook. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#update-a-webhook-configuration-for-an-organization +// +//meta:operation PATCH /orgs/{org}/hooks/{hook_id}/config +func (s *OrganizationsService) EditHookConfiguration(ctx context.Context, org string, id int64, config *HookConfig) (*HookConfig, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/config", org, id) + req, err := s.client.NewRequest("PATCH", u, config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go new file mode 100644 index 00000000..c1c30124 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go @@ -0,0 +1,79 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists webhook deliveries for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#list-deliveries-for-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/deliveries +func (s *OrganizationsService) ListHookDeliveries(ctx context.Context, org string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries", org, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#get-a-webhook-delivery-for-an-organization-webhook +// +//meta:operation GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id} +func (s *OrganizationsService) GetHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v", owner, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/webhooks#redeliver-a-delivery-for-an-organization-webhook +// +//meta:operation POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts +func (s *OrganizationsService) RedeliverHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v/attempts", owner, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_members.go b/vendor/github.com/google/go-github/v68/github/orgs_members.go similarity index 69% rename from vendor/github.com/google/go-github/github/orgs_members.go rename to vendor/github.com/google/go-github/v68/github/orgs_members.go index d1843599..d818d7f9 100644 --- a/vendor/github.com/google/go-github/github/orgs_members.go +++ b/vendor/github.com/google/go-github/v68/github/orgs_members.go @@ -71,15 +71,19 @@ type ListMembersOptions struct { // user is an owner of the organization, this will return both concealed and // public members, otherwise it will only return public members. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list -func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt *ListMembersOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-members +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-public-organization-members +// +//meta:operation GET /orgs/{org}/members +//meta:operation GET /orgs/{org}/public_members +func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { var u string - if opt != nil && opt.PublicOnly { + if opts != nil && opts.PublicOnly { u = fmt.Sprintf("orgs/%v/public_members", org) } else { u = fmt.Sprintf("orgs/%v/members", org) } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -100,7 +104,9 @@ func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt // IsMember checks if a user is a member of an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#check-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/members/{username} func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("GET", u, nil) @@ -115,7 +121,9 @@ func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) ( // IsPublicMember checks if a user is a public member of an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#check-public-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/public_members/{username} func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("GET", u, nil) @@ -130,7 +138,9 @@ func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user str // RemoveMember removes a user from all teams of an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-an-organization-member +// +//meta:operation DELETE /orgs/{org}/members/{username} func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) @@ -141,10 +151,26 @@ func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user strin return s.client.Do(ctx, req, nil) } +// CancelInvite cancels an organization invitation. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#cancel-an-organization-invitation +// +//meta:operation DELETE /orgs/{org}/invitations/{invitation_id} +func (s *OrganizationsService) CancelInvite(ctx context.Context, org string, invitationID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/invitations/%v", org, invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + // PublicizeMembership publicizes a user's membership in an organization. (A // user cannot publicize the membership for another user.) // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#set-public-organization-membership-for-the-authenticated-user +// +//meta:operation PUT /orgs/{org}/public_members/{username} func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("PUT", u, nil) @@ -157,7 +183,9 @@ func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, use // ConcealMembership conceals a user's membership in an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-public-organization-membership-for-the-authenticated-user +// +//meta:operation DELETE /orgs/{org}/public_members/{username} func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) @@ -180,10 +208,12 @@ type ListOrgMembershipsOptions struct { // ListOrgMemberships lists the organization memberships for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships -func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-memberships-for-the-authenticated-user +// +//meta:operation GET /user/memberships/orgs +func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { u := "user/memberships/orgs" - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -206,9 +236,11 @@ func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *List // Passing an empty string for user will get the membership for the // authenticated user. // -// GitHub API docs: -// https://developer.github.com/v3/orgs/members/#get-organization-membership -// https://developer.github.com/v3/orgs/members/#get-your-organization-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#get-an-organization-membership-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/orgs/members#get-organization-membership-for-a-user +// +//meta:operation GET /orgs/{org}/memberships/{username} +//meta:operation GET /user/memberships/orgs/{org} func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { var u string if user != "" { @@ -235,8 +267,11 @@ func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org s // Passing an empty string for user will edit the membership for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership -// GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#set-organization-membership-for-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/members#update-an-organization-membership-for-the-authenticated-user +// +//meta:operation PUT /orgs/{org}/memberships/{username} +//meta:operation PATCH /user/memberships/orgs/{org} func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { var u, method string if user != "" { @@ -264,7 +299,9 @@ func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org // RemoveOrgMembership removes user from the specified organization. If the // user has been invited to the organization, this will cancel their invitation. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership +// GitHub API docs: https://docs.github.com/rest/orgs/members#remove-organization-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/memberships/{username} func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) @@ -277,10 +314,12 @@ func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, or // ListPendingOrgInvitations returns a list of pending invitations. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations -func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opt *ListOptions) ([]*Invitation, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-pending-organization-invitations +// +//meta:operation GET /orgs/{org}/invitations +func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations", org) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -295,6 +334,7 @@ func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, or if err != nil { return nil, resp, err } + return pendingInvitations, resp, nil } @@ -314,41 +354,43 @@ type CreateOrgInvitationOptions struct { // * billing_manager - Non-owner organization members with ability to // manage the billing settings of your organization. // Default is "direct_member". - Role *string `json:"role"` - TeamID []int64 `json:"team_ids"` + Role *string `json:"role,omitempty"` + TeamID []int64 `json:"team_ids,omitempty"` } // CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address. // In order to create invitations in an organization, // the authenticated user must be an organization owner. // -// https://developer.github.com/v3/orgs/members/#create-organization-invitation -func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/members#create-an-organization-invitation +// +//meta:operation POST /orgs/{org}/invitations +func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations", org) - req, err := s.client.NewRequest("POST", u, opt) + req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) - var invitation *Invitation resp, err := s.client.Do(ctx, req, &invitation) if err != nil { return nil, resp, err } + return invitation, resp, nil } // ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization, // the authenticated user must be an organization owner. // -// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams -func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opt *ListOptions) ([]*Team, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-organization-invitation-teams +// +//meta:operation GET /orgs/{org}/invitations/{invitation_id}/teams +func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opts *ListOptions) ([]*Team, *Response, error) { u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -358,13 +400,37 @@ func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) - var orgInvitationTeams []*Team resp, err := s.client.Do(ctx, req, &orgInvitationTeams) if err != nil { return nil, resp, err } + return orgInvitationTeams, resp, nil } + +// ListFailedOrgInvitations returns a list of failed invitations. +// +// GitHub API docs: https://docs.github.com/rest/orgs/members#list-failed-organization-invitations +// +//meta:operation GET /orgs/{org}/failed_invitations +func (s *OrganizationsService) ListFailedOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/failed_invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var failedInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &failedInvitations) + if err != nil { + return nil, resp, err + } + + return failedInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go b/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go new file mode 100644 index 00000000..0954b92d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go @@ -0,0 +1,295 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationCustomRoles represents custom organization roles available in specified organization. +type OrganizationCustomRoles struct { + TotalCount *int `json:"total_count,omitempty"` + CustomRepoRoles []*CustomOrgRoles `json:"roles,omitempty"` +} + +// CustomOrgRoles represents custom organization role available in specified organization. +type CustomOrgRoles struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Permissions []string `json:"permissions,omitempty"` + Org *Organization `json:"organization,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Source *string `json:"source,omitempty"` + BaseRole *string `json:"base_role,omitempty"` +} + +// CreateOrUpdateOrgRoleOptions represents options required to create or update a custom organization role. +type CreateOrUpdateOrgRoleOptions struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Permissions []string `json:"permissions"` + BaseRole *string `json:"base_role,omitempty"` +} + +// ListRoles lists the custom roles available in this organization. +// In order to see custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-all-organization-roles-for-an-organization +// +//meta:operation GET /orgs/{org}/organization-roles +func (s *OrganizationsService) ListRoles(ctx context.Context, org string) (*OrganizationCustomRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + customRepoRoles := new(OrganizationCustomRoles) + resp, err := s.client.Do(ctx, req, customRepoRoles) + if err != nil { + return nil, resp, err + } + + return customRepoRoles, resp, nil +} + +// GetOrgRole gets an organization role in this organization. +// In order to get organization roles in an organization, the authenticated user must be an organization owner, or have access via an organization role. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#get-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) GetOrgRole(ctx context.Context, org string, roleID int64) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// CreateCustomOrgRole creates a custom role in this organization. +// In order to create custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#create-a-custom-organization-role +// +//meta:operation POST /orgs/{org}/organization-roles +func (s *OrganizationsService) CreateCustomOrgRole(ctx context.Context, org string, opts *CreateOrUpdateOrgRoleOptions) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// UpdateCustomOrgRole updates a custom role in this organization. +// In order to update custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#update-a-custom-organization-role +// +//meta:operation PATCH /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) UpdateCustomOrgRole(ctx context.Context, org string, roleID int64, opts *CreateOrUpdateOrgRoleOptions) (*CustomOrgRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return nil, resp, err + } + + return resultingRole, resp, err +} + +// DeleteCustomOrgRole deletes an existing custom role in this organization. +// In order to delete custom roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/organization-roles#delete-a-custom-organization-role +// +//meta:operation DELETE /orgs/{org}/organization-roles/{role_id} +func (s *OrganizationsService) DeleteCustomOrgRole(ctx context.Context, org string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v", org, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resultingRole := new(CustomOrgRoles) + resp, err := s.client.Do(ctx, req, resultingRole) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AssignOrgRoleToTeam assigns an existing organization role to a team in this organization. +// In order to assign organization roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-team +// +//meta:operation PUT /orgs/{org}/organization-roles/teams/{team_slug}/{role_id} +func (s *OrganizationsService) AssignOrgRoleToTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveOrgRoleFromTeam removes an existing organization role assignment from a team in this organization. +// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-team +// +//meta:operation DELETE /orgs/{org}/organization-roles/teams/{team_slug}/{role_id} +func (s *OrganizationsService) RemoveOrgRoleFromTeam(ctx context.Context, org, teamSlug string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/teams/%v/%v", org, teamSlug, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AssignOrgRoleToUser assigns an existing organization role to a user in this organization. +// In order to assign organization roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#assign-an-organization-role-to-a-user +// +//meta:operation PUT /orgs/{org}/organization-roles/users/{username}/{role_id} +func (s *OrganizationsService) AssignOrgRoleToUser(ctx context.Context, org, username string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveOrgRoleFromUser removes an existing organization role assignment from a user in this organization. +// In order to remove organization role assignments in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#remove-an-organization-role-from-a-user +// +//meta:operation DELETE /orgs/{org}/organization-roles/users/{username}/{role_id} +func (s *OrganizationsService) RemoveOrgRoleFromUser(ctx context.Context, org, username string, roleID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/users/%v/%v", org, username, roleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ListTeamsAssignedToOrgRole returns all teams assigned to a specific organization role. +// In order to list teams assigned to an organization role, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#list-teams-that-are-assigned-to-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id}/teams +func (s *OrganizationsService) ListTeamsAssignedToOrgRole(ctx context.Context, org string, roleID int64, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v/teams", org, roleID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListUsersAssignedToOrgRole returns all users assigned to a specific organization role. +// In order to list users assigned to an organization role, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/rest/orgs/organization-roles#list-users-that-are-assigned-to-an-organization-role +// +//meta:operation GET /orgs/{org}/organization-roles/{role_id}/users +func (s *OrganizationsService) ListUsersAssignedToOrgRole(ctx context.Context, org string, roleID int64, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/organization-roles/%v/users", org, roleID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go similarity index 77% rename from vendor/github.com/google/go-github/github/orgs_outside_collaborators.go rename to vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go index 85ffd05f..56034d72 100644 --- a/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go +++ b/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go @@ -27,10 +27,12 @@ type ListOutsideCollaboratorsOptions struct { // Warning: The API may change without advance notice during the preview period. // Preview features are not supported for production use. // -// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators -func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opt *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#list-outside-collaborators-for-an-organization +// +//meta:operation GET /orgs/{org}/outside_collaborators +func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opts *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators", org) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -52,7 +54,9 @@ func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org // RemoveOutsideCollaborator removes a user from the list of outside collaborators; // consequently, removing them from all the organization's repositories. // -// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#remove-outside-collaborator-from-an-organization +// +//meta:operation DELETE /orgs/{org}/outside_collaborators/{username} func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) req, err := s.client.NewRequest("DELETE", u, nil) @@ -69,7 +73,9 @@ func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, or // Responses for converting a non-member or the last owner to an outside collaborator // are listed in GitHub API docs. // -// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator +// GitHub API docs: https://docs.github.com/rest/orgs/outside-collaborators#convert-an-organization-member-to-outside-collaborator +// +//meta:operation PUT /orgs/{org}/outside_collaborators/{username} func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) req, err := s.client.NewRequest("PUT", u, nil) diff --git a/vendor/github.com/google/go-github/v68/github/orgs_packages.go b/vendor/github.com/google/go-github/v68/github/orgs_packages.go new file mode 100644 index 00000000..edd8e508 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_packages.go @@ -0,0 +1,180 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/url" +) + +// ListPackages lists the packages for an organization. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-an-organization +// +//meta:operation GET /orgs/{org}/packages +func (s *OrganizationsService) ListPackages(ctx context.Context, org string, opts *PackageListOptions) ([]*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// GetPackage gets a package by name from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name} +func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, packageName string) (*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// DeletePackage deletes a package from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-an-organization +// +//meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name} +func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RestorePackage restores a package to an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-an-organization +// +//meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/restore +func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, url.PathEscape(packageName)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageGetAllVersions gets all versions of a package in an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions +func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, url.PathEscape(packageName)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// PackageGetVersion gets a specific version of a package in an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-an-organization +// +//meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// PackageDeleteVersion deletes a package version from an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-package-version-for-an-organization +// +//meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageRestoreVersion restores a package version to an organization. +// +// Note that packageName is escaped for the URL path so that you don't need to. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-package-version-for-an-organization +// +//meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +func (s *OrganizationsService) PackageRestoreVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, url.PathEscape(packageName), packageVersionID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go b/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go new file mode 100644 index 00000000..af083744 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go @@ -0,0 +1,167 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// PersonalAccessToken represents the minimal representation of an organization programmatic access grant. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/personal-access-tokens?apiVersion=2022-11-28 +type PersonalAccessToken struct { + // "Unique identifier of the fine-grained personal access token. + // The `pat_id` used to get details about an approved fine-grained personal access token. + ID *int64 `json:"id"` + + // Owner is the GitHub user associated with the token. + Owner *User `json:"owner"` + + // RepositorySelection is the type of repository selection requested. + // Possible values are: "none", "all", "subset". + RepositorySelection *string `json:"repository_selection"` + + // URL to the list of repositories the fine-grained personal access token can access. + // Only follow when `repository_selection` is `subset`. + RepositoriesURL *string `json:"repositories_url"` + + // Permissions are the permissions requested, categorized by type. + Permissions *PersonalAccessTokenPermissions `json:"permissions"` + + // Date and time when the fine-grained personal access token was approved to access the organization. + AccessGrantedAt *Timestamp `json:"access_granted_at"` + + // Whether the associated fine-grained personal access token has expired. + TokenExpired *bool `json:"token_expired"` + + // Date and time when the associated fine-grained personal access token expires. + TokenExpiresAt *Timestamp `json:"token_expires_at"` + + // Date and time when the associated fine-grained personal access token was last used for authentication. + TokenLastUsedAt *Timestamp `json:"token_last_used_at"` +} + +// ListFineGrainedPATOptions specifies optional parameters to ListFineGrainedPersonalAccessTokens. +type ListFineGrainedPATOptions struct { + // The property by which to sort the results. + // Default: created_at + // Value: created_at + Sort string `url:"sort,omitempty"` + + // The direction to sort the results by. + // Default: desc + // Value: asc, desc + Direction string `url:"direction,omitempty"` + + // A list of owner usernames to use to filter the results. + Owner []string `url:"-"` + + // The name of the repository to use to filter the results. + Repository string `url:"repository,omitempty"` + + // The permission to use to filter the results. + Permission string `url:"permission,omitempty"` + + // Only show fine-grained personal access tokens used before the given time. + // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. + LastUsedBefore string `url:"last_used_before,omitempty"` + + // Only show fine-grained personal access tokens used after the given time. + // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. + LastUsedAfter string `url:"last_used_after,omitempty"` + + ListOptions +} + +// ListFineGrainedPersonalAccessTokens lists approved fine-grained personal access tokens owned by organization members that can access organization resources. +// Only GitHub Apps can call this API, using the `Personal access tokens` organization permissions (read). +// +// GitHub API docs: https://docs.github.com/rest/orgs/personal-access-tokens#list-fine-grained-personal-access-tokens-with-access-to-organization-resources +// +//meta:operation GET /orgs/{org}/personal-access-tokens +func (s *OrganizationsService) ListFineGrainedPersonalAccessTokens(ctx context.Context, org string, opts *ListFineGrainedPATOptions) ([]*PersonalAccessToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/personal-access-tokens", org) + // The `owner` parameter is a special case that uses the `owner[]=...` format and needs a custom function to format it correctly. + u, err := addListFineGrainedPATOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, u, opts) + if err != nil { + return nil, nil, err + } + + var pats []*PersonalAccessToken + + resp, err := s.client.Do(ctx, req, &pats) + if err != nil { + return nil, resp, err + } + + return pats, resp, nil +} + +// ReviewPersonalAccessTokenRequestOptions specifies the parameters to the ReviewPersonalAccessTokenRequest method. +type ReviewPersonalAccessTokenRequestOptions struct { + Action string `json:"action"` + Reason *string `json:"reason,omitempty"` +} + +// ReviewPersonalAccessTokenRequest approves or denies a pending request to access organization resources via a fine-grained personal access token. +// Only GitHub Apps can call this API, using the `organization_personal_access_token_requests: write` permission. +// `action` can be one of `approve` or `deny`. +// +// GitHub API docs: https://docs.github.com/rest/orgs/personal-access-tokens#review-a-request-to-access-organization-resources-with-a-fine-grained-personal-access-token +// +//meta:operation POST /orgs/{org}/personal-access-token-requests/{pat_request_id} +func (s *OrganizationsService) ReviewPersonalAccessTokenRequest(ctx context.Context, org string, requestID int64, opts ReviewPersonalAccessTokenRequestOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/personal-access-token-requests/%v", org, requestID) + + req, err := s.client.NewRequest(http.MethodPost, u, &opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// addListFineGrainedPATOptions adds the owner parameter to the URL query string with the correct format if it is set. +// +// GitHub API expects the owner parameter to be a list of strings in the `owner[]=...` format. +// For multiple owner values, the owner parameter is repeated in the query string. +// +// Example: +// owner[]=user1&owner[]=user2 +// This will filter the results to only include fine-grained personal access tokens owned by `user1` and `user2`. +// +// This function ensures the owner parameter is formatted correctly in the URL query string. +func addListFineGrainedPATOptions(s string, opts *ListFineGrainedPATOptions) (string, error) { + u, err := addOptions(s, opts) + if err != nil { + return s, err + } + + if len(opts.Owner) > 0 { + ownerVals := make([]string, len(opts.Owner)) + for i, owner := range opts.Owner { + ownerVals[i] = fmt.Sprintf("owner[]=%s", url.QueryEscape(owner)) + } + ownerQuery := strings.Join(ownerVals, "&") + + if strings.Contains(u, "?") { + u += "&" + ownerQuery + } else { + u += "?" + ownerQuery + } + } + + return u, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_properties.go b/vendor/github.com/google/go-github/v68/github/orgs_properties.go new file mode 100644 index 00000000..f59d9f46 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_properties.go @@ -0,0 +1,243 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" +) + +// CustomProperty represents an organization custom property object. +type CustomProperty struct { + // PropertyName is required for most endpoints except when calling CreateOrUpdateCustomProperty; + // where this is sent in the path and thus can be omitted. + PropertyName *string `json:"property_name,omitempty"` + // SourceType is the source type of the property where it has been created. Can be one of: organization, enterprise. + SourceType *string `json:"source_type,omitempty"` + // The type of the value for the property. Can be one of: string, single_select, multi_select, true_false. + ValueType string `json:"value_type"` + // Whether the property is required. + Required *bool `json:"required,omitempty"` + // Default value of the property. + DefaultValue *string `json:"default_value,omitempty"` + // Short description of the property. + Description *string `json:"description,omitempty"` + // An ordered list of the allowed values of the property. The property can have up to 200 + // allowed values. + AllowedValues []string `json:"allowed_values,omitempty"` + // Who can edit the values of the property. Can be one of: org_actors, org_and_repo_actors, nil (null). + ValuesEditableBy *string `json:"values_editable_by,omitempty"` +} + +// RepoCustomPropertyValue represents a repository custom property value. +type RepoCustomPropertyValue struct { + RepositoryID int64 `json:"repository_id"` + RepositoryName string `json:"repository_name"` + RepositoryFullName string `json:"repository_full_name"` + Properties []*CustomPropertyValue `json:"properties"` +} + +// CustomPropertyValue represents a custom property value. +type CustomPropertyValue struct { + PropertyName string `json:"property_name"` + Value interface{} `json:"value"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that Value can be either a string, []string, or nil. +func (cpv *CustomPropertyValue) UnmarshalJSON(data []byte) error { + type aliasCustomPropertyValue CustomPropertyValue + aux := &struct { + *aliasCustomPropertyValue + }{ + aliasCustomPropertyValue: (*aliasCustomPropertyValue)(cpv), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + switch v := aux.Value.(type) { + case nil: + cpv.Value = nil + case string: + cpv.Value = v + case []interface{}: + strSlice := make([]string, len(v)) + for i, item := range v { + str, ok := item.(string) + if !ok { + return errors.New("non-string value in string array") + } + strSlice[i] = str + } + cpv.Value = strSlice + default: + return fmt.Errorf("unexpected value type: %T", v) + } + return nil +} + +// GetAllCustomProperties gets all custom properties that are defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#get-all-custom-properties-for-an-organization +// +//meta:operation GET /orgs/{org}/properties/schema +func (s *OrganizationsService) GetAllCustomProperties(ctx context.Context, org string) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom properties that are defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-custom-properties-for-an-organization +// +//meta:operation PATCH /orgs/{org}/properties/schema +func (s *OrganizationsService) CreateOrUpdateCustomProperties(ctx context.Context, org string, properties []*CustomProperty) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema", org) + + params := struct { + Properties []*CustomProperty `json:"properties"` + }{ + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// GetCustomProperty gets a custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#get-a-custom-property-for-an-organization +// +//meta:operation GET /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) GetCustomProperty(ctx context.Context, org, name string) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, name) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// CreateOrUpdateCustomProperty creates a new or updates an existing custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-a-custom-property-for-an-organization +// +//meta:operation PUT /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) CreateOrUpdateCustomProperty(ctx context.Context, org, customPropertyName string, property *CustomProperty) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, customPropertyName) + + req, err := s.client.NewRequest("PUT", u, property) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// RemoveCustomProperty removes a custom property that is defined for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#remove-a-custom-property-for-an-organization +// +//meta:operation DELETE /orgs/{org}/properties/schema/{custom_property_name} +func (s *OrganizationsService) RemoveCustomProperty(ctx context.Context, org, customPropertyName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/properties/schema/%v", org, customPropertyName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListCustomPropertyValues lists all custom property values for repositories in the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#list-custom-property-values-for-organization-repositories +// +//meta:operation GET /orgs/{org}/properties/values +func (s *OrganizationsService) ListCustomPropertyValues(ctx context.Context, org string, opts *ListOptions) ([]*RepoCustomPropertyValue, *Response, error) { + u := fmt.Sprintf("orgs/%v/properties/values", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repoCustomPropertyValues []*RepoCustomPropertyValue + resp, err := s.client.Do(ctx, req, &repoCustomPropertyValues) + if err != nil { + return nil, resp, err + } + + return repoCustomPropertyValues, resp, nil +} + +// CreateOrUpdateRepoCustomPropertyValues creates new or updates existing custom property values across multiple repositories for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/custom-properties#create-or-update-custom-property-values-for-organization-repositories +// +//meta:operation PATCH /orgs/{org}/properties/values +func (s *OrganizationsService) CreateOrUpdateRepoCustomPropertyValues(ctx context.Context, org string, repoNames []string, properties []*CustomPropertyValue) (*Response, error) { + u := fmt.Sprintf("orgs/%v/properties/values", org) + + params := struct { + RepositoryNames []string `json:"repository_names"` + Properties []*CustomPropertyValue `json:"properties"` + }{ + RepositoryNames: repoNames, + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_rules.go b/vendor/github.com/google/go-github/v68/github/orgs_rules.go new file mode 100644 index 00000000..37c06a73 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_rules.go @@ -0,0 +1,115 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllOrganizationRulesets gets all the rulesets for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-all-organization-repository-rulesets +// +//meta:operation GET /orgs/{org}/rulesets +func (s *OrganizationsService) GetAllOrganizationRulesets(ctx context.Context, org string) ([]*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rulesets []*Ruleset + resp, err := s.client.Do(ctx, req, &rulesets) + if err != nil { + return nil, resp, err + } + + return rulesets, resp, nil +} + +// CreateOrganizationRuleset creates a ruleset for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#create-an-organization-repository-ruleset +// +//meta:operation POST /orgs/{org}/rulesets +func (s *OrganizationsService) CreateOrganizationRuleset(ctx context.Context, org string, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("POST", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// GetOrganizationRuleset gets a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-an-organization-repository-ruleset +// +//meta:operation GET /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) GetOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateOrganizationRuleset updates a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#update-an-organization-repository-ruleset +// +//meta:operation PUT /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) UpdateOrganizationRuleset(ctx context.Context, org string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("PUT", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// DeleteOrganizationRuleset deletes a ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#delete-an-organization-repository-ruleset +// +//meta:operation DELETE /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) DeleteOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go b/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go new file mode 100644 index 00000000..08037727 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go @@ -0,0 +1,63 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListSecurityManagerTeams lists all security manager teams for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams +// +//meta:operation GET /orgs/{org}/security-managers +func (s *OrganizationsService) ListSecurityManagerTeams(ctx context.Context, org string) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// AddSecurityManagerTeam adds a team to the list of security managers for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team +// +//meta:operation PUT /orgs/{org}/security-managers/teams/{team_slug} +func (s *OrganizationsService) AddSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSecurityManagerTeam removes a team from the list of security managers for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team +// +//meta:operation DELETE /orgs/{org}/security-managers/teams/{team_slug} +func (s *OrganizationsService) RemoveSecurityManagerTeam(ctx context.Context, org, team string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/security-managers/teams/%v", org, team) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go similarity index 76% rename from vendor/github.com/google/go-github/github/orgs_users_blocking.go rename to vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go index b1aecf44..62bd9116 100644 --- a/vendor/github.com/google/go-github/github/orgs_users_blocking.go +++ b/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go @@ -12,10 +12,12 @@ import ( // ListBlockedUsers lists all the users blocked by an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users -func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#list-users-blocked-by-an-organization +// +//meta:operation GET /orgs/{org}/blocks +func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opts *ListOptions) ([]*User, *Response, error) { u := fmt.Sprintf("orgs/%v/blocks", org) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -39,7 +41,9 @@ func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, // IsBlocked reports whether specified user is blocked from an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#check-if-a-user-is-blocked-by-an-organization +// +//meta:operation GET /orgs/{org}/blocks/{username} func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) @@ -58,7 +62,9 @@ func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user s // BlockUser blocks specified user from an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#block-a-user-from-an-organization +// +//meta:operation PUT /orgs/{org}/blocks/{username} func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) @@ -75,7 +81,9 @@ func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user s // UnblockUser unblocks specified user from an organization. // -// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user +// GitHub API docs: https://docs.github.com/rest/orgs/blocking#unblock-a-user-from-an-organization +// +//meta:operation DELETE /orgs/{org}/blocks/{username} func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) diff --git a/vendor/github.com/google/go-github/v68/github/packages.go b/vendor/github.com/google/go-github/v68/github/packages.go new file mode 100644 index 00000000..ef7df074 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/packages.go @@ -0,0 +1,143 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// Package represents a GitHub package. +type Package struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + PackageType *string `json:"package_type,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Owner *User `json:"owner,omitempty"` + PackageVersion *PackageVersion `json:"package_version,omitempty"` + Registry *PackageRegistry `json:"registry,omitempty"` + URL *string `json:"url,omitempty"` + VersionCount *int64 `json:"version_count,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +func (p Package) String() string { + return Stringify(p) +} + +// PackageVersion represents a GitHub package version. +type PackageVersion struct { + ID *int64 `json:"id,omitempty"` + Version *string `json:"version,omitempty"` + Summary *string `json:"summary,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + Release *PackageRelease `json:"release,omitempty"` + Manifest *string `json:"manifest,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + TargetOID *string `json:"target_oid,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PackageFiles []*PackageFile `json:"package_files,omitempty"` + Author *User `json:"author,omitempty"` + InstallationCommand *string `json:"installation_command,omitempty"` + Metadata *PackageMetadata `json:"metadata,omitempty"` + PackageHTMLURL *string `json:"package_html_url,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (pv PackageVersion) String() string { + return Stringify(pv) +} + +// PackageRelease represents a GitHub package version release. +type PackageRelease struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Draft *bool `json:"draft,omitempty"` + Author *User `json:"author,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` +} + +func (r PackageRelease) String() string { + return Stringify(r) +} + +// PackageFile represents a GitHub package version release file. +type PackageFile struct { + DownloadURL *string `json:"download_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + SHA256 *string `json:"sha256,omitempty"` + SHA1 *string `json:"sha1,omitempty"` + MD5 *string `json:"md5,omitempty"` + ContentType *string `json:"content_type,omitempty"` + State *string `json:"state,omitempty"` + Author *User `json:"author,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (pf PackageFile) String() string { + return Stringify(pf) +} + +// PackageRegistry represents a GitHub package registry. +type PackageRegistry struct { + AboutURL *string `json:"about_url,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + URL *string `json:"url,omitempty"` + Vendor *string `json:"vendor,omitempty"` +} + +func (r PackageRegistry) String() string { + return Stringify(r) +} + +// PackageListOptions represents the optional list options for a package. +type PackageListOptions struct { + // Visibility of packages "public", "internal" or "private". + Visibility *string `url:"visibility,omitempty"` + + // PackageType represents the type of package. + // It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container". + PackageType *string `url:"package_type,omitempty"` + + // State of package either "active" or "deleted". + State *string `url:"state,omitempty"` + + ListOptions +} + +// PackageMetadata represents metadata from a package. +type PackageMetadata struct { + PackageType *string `json:"package_type,omitempty"` + Container *PackageContainerMetadata `json:"container,omitempty"` +} + +func (r PackageMetadata) String() string { + return Stringify(r) +} + +// PackageContainerMetadata represents container metadata for docker container packages. +type PackageContainerMetadata struct { + Tags []string `json:"tags,omitempty"` +} + +func (r PackageContainerMetadata) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls.go b/vendor/github.com/google/go-github/v68/github/pulls.go new file mode 100644 index 00000000..35ceda44 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls.go @@ -0,0 +1,516 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "errors" + "fmt" +) + +// PullRequestsService handles communication with the pull request related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/pulls/ +type PullRequestsService service + +// PullRequestAutoMerge represents the "auto_merge" response for a PullRequest. +type PullRequestAutoMerge struct { + EnabledBy *User `json:"enabled_by,omitempty"` + MergeMethod *string `json:"merge_method,omitempty"` + CommitTitle *string `json:"commit_title,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// PullRequest represents a GitHub pull request on a repository. +type PullRequest struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + MergedAt *Timestamp `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Draft *bool `json:"draft,omitempty"` + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Rebaseable *bool `json:"rebaseable,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + ReviewComments *int `json:"review_comments,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` + + // RequestedTeams is populated as part of the PullRequestEvent. + // See, https://docs.github.com/developers/webhooks-and-events/github-event-types#pullrequestevent for an example. + RequestedTeams []*Team `json:"requested_teams,omitempty"` + + Links *PRLinks `json:"_links,omitempty"` + Head *PullRequestBranch `json:"head,omitempty"` + Base *PullRequestBranch `json:"base,omitempty"` + + // ActiveLockReason is populated only when LockReason is provided while locking the pull request. + // Possible values are: "off-topic", "too heated", "resolved", and "spam". + ActiveLockReason *string `json:"active_lock_reason,omitempty"` +} + +func (p PullRequest) String() string { + return Stringify(p) +} + +// PRLink represents a single link object from GitHub pull request _links. +type PRLink struct { + HRef *string `json:"href,omitempty"` +} + +// PRLinks represents the "_links" object in a GitHub pull request. +type PRLinks struct { + Self *PRLink `json:"self,omitempty"` + HTML *PRLink `json:"html,omitempty"` + Issue *PRLink `json:"issue,omitempty"` + Comments *PRLink `json:"comments,omitempty"` + ReviewComments *PRLink `json:"review_comments,omitempty"` + ReviewComment *PRLink `json:"review_comment,omitempty"` + Commits *PRLink `json:"commits,omitempty"` + Statuses *PRLink `json:"statuses,omitempty"` +} + +// PullRequestBranch represents a base or head branch in a GitHub pull request. +type PullRequestBranch struct { + Label *string `json:"label,omitempty"` + Ref *string `json:"ref,omitempty"` + SHA *string `json:"sha,omitempty"` + Repo *Repository `json:"repo,omitempty"` + User *User `json:"user,omitempty"` +} + +// PullRequestListOptions specifies the optional parameters to the +// PullRequestsService.List method. +type PullRequestListOptions struct { + // State filters pull requests based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Head filters pull requests by head user and branch name in the format of: + // "user:ref-name". + Head string `url:"head,omitempty"` + + // Base filters pull requests by base branch name. + Base string `url:"base,omitempty"` + + // Sort specifies how to sort pull requests. Possible values are: created, + // updated, popularity, long-running. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort pull requests. Possible values are: asc, desc. + // If Sort is "created" or not specified, Default is "desc", otherwise Default + // is "asc" + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// List the pull requests for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-pull-requests +// +//meta:operation GET /repos/{owner}/{repo}/pulls +func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// ListPullRequestsWithCommit returns pull requests associated with a commit SHA. +// +// The results may include open and closed pull requests. +// By default, the PullRequestListOptions State filters for "open". +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-pull-requests-associated-with-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls +func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// Get a single pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#get-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + pull := new(PullRequest) + resp, err := s.client.Do(ctx, req, pull) + if err != nil { + return nil, resp, err + } + + return pull, resp, nil +} + +// GetRaw gets a single pull request in raw (diff or patch) format. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#get-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opts RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// NewPullRequest represents a new pull request to be created. +type NewPullRequest struct { + Title *string `json:"title,omitempty"` + // The name of the branch where your changes are implemented. For + // cross-repository pull requests in the same network, namespace head with + // a user like this: username:branch. + Head *string `json:"head,omitempty"` + HeadRepo *string `json:"head_repo,omitempty"` + // The name of the branch you want the changes pulled into. This should be + // an existing branch on the current repository. You cannot submit a pull + // request to one repository that requests a merge to a base of another + // repository. + Base *string `json:"base,omitempty"` + Body *string `json:"body,omitempty"` + Issue *int `json:"issue,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + Draft *bool `json:"draft,omitempty"` +} + +// Create a new pull request on the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#create-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls +func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + req, err := s.client.NewRequest("POST", u, pull) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// PullRequestBranchUpdateOptions specifies the optional parameters to the +// PullRequestsService.UpdateBranch method. +type PullRequestBranchUpdateOptions struct { + // ExpectedHeadSHA specifies the most recent commit on the pull request's branch. + // Default value is the SHA of the pull request's current HEAD ref. + ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"` +} + +// PullRequestBranchUpdateResponse specifies the response of pull request branch update. +type PullRequestBranchUpdateResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// UpdateBranch updates the pull request branch with latest upstream changes. +// +// This method might return an AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the update of the pull request branch in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#update-a-pull-request-branch +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch +func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullRequestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview) + + p := new(PullRequestBranchUpdateResponse) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +type pullRequestUpdate struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + Base *string `json:"base,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` +} + +// Edit a pull request. +// pull must not be nil. +// +// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. +// Base.Ref updates the base branch of the pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#update-a-pull-request +// +//meta:operation PATCH /repos/{owner}/{repo}/pulls/{pull_number} +func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { + if pull == nil { + return nil, nil, errors.New("pull must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + + update := &pullRequestUpdate{ + Title: pull.Title, + Body: pull.Body, + State: pull.State, + MaintainerCanModify: pull.MaintainerCanModify, + } + // avoid updating the base branch when closing the Pull Request + // - otherwise the GitHub API server returns a "Validation Failed" error: + // "Cannot change base branch of closed pull request". + if pull.Base != nil && pull.GetState() != "closed" { + update.Base = pull.Base.Ref + } + + req, err := s.client.NewRequest("PATCH", u, update) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListCommits lists the commits in a pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-commits-on-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/commits +func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// ListFiles lists the files in a pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#list-pull-requests-files +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/files +func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*CommitFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commitFiles []*CommitFile + resp, err := s.client.Do(ctx, req, &commitFiles) + if err != nil { + return nil, resp, err + } + + return commitFiles, resp, nil +} + +// IsMerged checks if a pull request has been merged. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#check-if-a-pull-request-has-been-merged +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/merge +func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + merged, err := parseBoolResponse(err) + return merged, resp, err +} + +// PullRequestMergeResult represents the result of merging a pull request. +type PullRequestMergeResult struct { + SHA *string `json:"sha,omitempty"` + Merged *bool `json:"merged,omitempty"` + Message *string `json:"message,omitempty"` +} + +// PullRequestOptions lets you define how a pull request will be merged. +type PullRequestOptions struct { + CommitTitle string // Title for the automatic commit message. (Optional.) + SHA string // SHA that pull request head must match to allow merge. (Optional.) + + // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) + MergeMethod string + + // If false, an empty string commit message will use the default commit message. If true, an empty string commit message will be used. + DontDefaultIfBlank bool +} + +type pullRequestMergeRequest struct { + CommitMessage *string `json:"commit_message,omitempty"` + CommitTitle string `json:"commit_title,omitempty"` + MergeMethod string `json:"merge_method,omitempty"` + SHA string `json:"sha,omitempty"` +} + +// Merge a pull request. +// commitMessage is an extra detail to append to automatic commit message. +// +// GitHub API docs: https://docs.github.com/rest/pulls/pulls#merge-a-pull-request +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge +func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + + pullRequestBody := &pullRequestMergeRequest{} + if commitMessage != "" { + pullRequestBody.CommitMessage = &commitMessage + } + if options != nil { + pullRequestBody.CommitTitle = options.CommitTitle + pullRequestBody.MergeMethod = options.MergeMethod + pullRequestBody.SHA = options.SHA + if options.DontDefaultIfBlank && commitMessage == "" { + pullRequestBody.CommitMessage = &commitMessage + } + } + req, err := s.client.NewRequest("PUT", u, pullRequestBody) + if err != nil { + return nil, nil, err + } + + mergeResult := new(PullRequestMergeResult) + resp, err := s.client.Do(ctx, req, mergeResult) + if err != nil { + return nil, resp, err + } + + return mergeResult, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/pulls_comments.go b/vendor/github.com/google/go-github/v68/github/pulls_comments.go similarity index 62% rename from vendor/github.com/google/go-github/github/pulls_comments.go rename to vendor/github.com/google/go-github/v68/github/pulls_comments.go index f3067762..a9ffe8d7 100644 --- a/vendor/github.com/google/go-github/github/pulls_comments.go +++ b/vendor/github.com/google/go-github/v68/github/pulls_comments.go @@ -8,12 +8,14 @@ package github import ( "context" "fmt" + "strings" "time" ) // PullRequestComment represents a comment left on a pull request. type PullRequestComment struct { ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` InReplyTo *int64 `json:"in_reply_to_id,omitempty"` Body *string `json:"body,omitempty"` Path *string `json:"path,omitempty"` @@ -21,18 +23,26 @@ type PullRequestComment struct { PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` Position *int `json:"position,omitempty"` OriginalPosition *int `json:"original_position,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` + OriginalLine *int `json:"original_line,omitempty"` + OriginalStartLine *int `json:"original_start_line,omitempty"` + Side *string `json:"side,omitempty"` + StartSide *string `json:"start_side,omitempty"` CommitID *string `json:"commit_id,omitempty"` OriginalCommitID *string `json:"original_commit_id,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` // AuthorAssociation is the comment author's relationship to the pull request's repository. // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". AuthorAssociation *string `json:"author_association,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PullRequestURL *string `json:"pull_request_url,omitempty"` + // Can be one of: LINE, FILE from https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request + SubjectType *string `json:"subject_type,omitempty"` } func (p PullRequestComment) String() string { @@ -58,15 +68,19 @@ type PullRequestListCommentsOptions struct { // pull request number of 0 will return all comments on all pull requests for // the repository. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request -func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opt *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#list-review-comments-in-a-repository +// GitHub API docs: https://docs.github.com/rest/pulls/comments#list-review-comments-on-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) ListComments(ctx context.Context, owner, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { var u string if number == 0 { u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) } else { u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -77,7 +91,8 @@ func (s *PullRequestsService) ListComments(ctx context.Context, owner string, re } // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeReactionsPreview) + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) var comments []*PullRequestComment resp, err := s.client.Do(ctx, req, &comments) @@ -90,8 +105,10 @@ func (s *PullRequestsService) ListComments(ctx context.Context, owner string, re // GetComment fetches the specified pull request comment. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment -func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#get-a-review-comment-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) GetComment(ctx context.Context, owner, repo string, commentID int64) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -99,7 +116,8 @@ func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo } // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeReactionsPreview) + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) comment := new(PullRequestComment) resp, err := s.client.Do(ctx, req, comment) @@ -112,13 +130,18 @@ func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo // CreateComment creates a new comment on the specified pull request. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment -func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) CreateComment(ctx context.Context, owner, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err } + // TODO: remove custom Accept headers when their respective API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) c := new(PullRequestComment) resp, err := s.client.Do(ctx, req, c) @@ -131,8 +154,10 @@ func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, r // CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#alternative-input -func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#create-a-review-comment-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/comments +func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { comment := &struct { Body string `json:"body,omitempty"` InReplyTo int64 `json:"in_reply_to,omitempty"` @@ -158,8 +183,10 @@ func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner // EditComment updates a pull request comment. // A non-nil comment.Body must be provided. Other comment fields should be left nil. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment -func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#update-a-review-comment-for-a-pull-request +// +//meta:operation PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) EditComment(ctx context.Context, owner, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("PATCH", u, comment) if err != nil { @@ -177,8 +204,10 @@ func (s *PullRequestsService) EditComment(ctx context.Context, owner string, rep // DeleteComment deletes a pull request comment. // -// GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment -func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/comments#delete-a-review-comment-for-a-pull-request +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id} +func (s *PullRequestsService) DeleteComment(ctx context.Context, owner, repo string, commentID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { diff --git a/vendor/github.com/google/go-github/github/pulls_reviewers.go b/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go similarity index 56% rename from vendor/github.com/google/go-github/github/pulls_reviewers.go rename to vendor/github.com/google/go-github/v68/github/pulls_reviewers.go index a1d78531..9dd60ae6 100644 --- a/vendor/github.com/google/go-github/github/pulls_reviewers.go +++ b/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go @@ -12,6 +12,7 @@ import ( // ReviewersRequest specifies users and teams for a pull request review request. type ReviewersRequest struct { + NodeID *string `json:"node_id,omitempty"` Reviewers []string `json:"reviewers,omitempty"` TeamReviewers []string `json:"team_reviewers,omitempty"` } @@ -22,9 +23,18 @@ type Reviewers struct { Teams []*Team `json:"teams,omitempty"` } +type removeReviewersRequest struct { + NodeID *string `json:"node_id,omitempty"` + // Note the lack of omitempty! See comment in RemoveReviewers. + Reviewers []string `json:"reviewers"` + TeamReviewers []string `json:"team_reviewers,omitempty"` +} + // RequestReviewers creates a review request for the provided reviewers for the specified pull request. // -// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#request-reviewers-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) req, err := s.client.NewRequest("POST", u, &reviewers) @@ -43,10 +53,12 @@ func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo // ListReviewers lists reviewers whose reviews have been requested on the specified pull request. // -// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests -func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opt *ListOptions) (*Reviewers, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#get-all-requested-reviewers-for-a-pull-request +// +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers +func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opts *ListOptions) (*Reviewers, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -67,10 +79,25 @@ func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo str // RemoveReviewers removes the review request for the provided reviewers for the specified pull request. // -// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request +// GitHub API docs: https://docs.github.com/rest/pulls/review-requests#remove-requested-reviewers-from-a-pull-request +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { + // reviewers.Reviewers may be empty if the caller wants to remove teams, but not users. Unlike AddReviewers, + // "reviewers" is a required param here. Reference: https://github.com/google/go-github/issues/3336 + removeRequest := removeReviewersRequest{ + NodeID: reviewers.NodeID, + Reviewers: reviewers.Reviewers, + TeamReviewers: reviewers.TeamReviewers, + } + + if removeRequest.Reviewers == nil { + // GitHub accepts the empty list, but rejects null. Removing `omitempty` is not enough - we also have to promote nil to []. + removeRequest.Reviewers = []string{} + } + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) - req, err := s.client.NewRequest("DELETE", u, &reviewers) + req, err := s.client.NewRequest("DELETE", u, &removeRequest) if err != nil { return nil, err } diff --git a/vendor/github.com/google/go-github/github/pulls_reviews.go b/vendor/github.com/google/go-github/v68/github/pulls_reviews.go similarity index 51% rename from vendor/github.com/google/go-github/github/pulls_reviews.go rename to vendor/github.com/google/go-github/v68/github/pulls_reviews.go index 57d3c635..27b8dc37 100644 --- a/vendor/github.com/google/go-github/github/pulls_reviews.go +++ b/vendor/github.com/google/go-github/v68/github/pulls_reviews.go @@ -7,20 +7,26 @@ package github import ( "context" + "errors" "fmt" - "time" ) +var ErrMixedCommentStyles = errors.New("cannot use both position and side/line form comments") + // PullRequestReview represents a review of a pull request. type PullRequestReview struct { ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` User *User `json:"user,omitempty"` Body *string `json:"body,omitempty"` - SubmittedAt *time.Time `json:"submitted_at,omitempty"` + SubmittedAt *Timestamp `json:"submitted_at,omitempty"` CommitID *string `json:"commit_id,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PullRequestURL *string `json:"pull_request_url,omitempty"` State *string `json:"state,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` } func (p PullRequestReview) String() string { @@ -32,6 +38,12 @@ type DraftReviewComment struct { Path *string `json:"path,omitempty"` Position *int `json:"position,omitempty"` Body *string `json:"body,omitempty"` + + // The new comfort-fade-preview fields + StartSide *string `json:"start_side,omitempty"` + Side *string `json:"side,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` } func (c DraftReviewComment) String() string { @@ -40,6 +52,7 @@ func (c DraftReviewComment) String() string { // PullRequestReviewRequest represents a request to create a review. type PullRequestReviewRequest struct { + NodeID *string `json:"node_id,omitempty"` CommitID *string `json:"commit_id,omitempty"` Body *string `json:"body,omitempty"` Event *string `json:"event,omitempty"` @@ -50,6 +63,32 @@ func (r PullRequestReviewRequest) String() string { return Stringify(r) } +func (r *PullRequestReviewRequest) isComfortFadePreview() (bool, error) { + var isCF *bool + for _, comment := range r.Comments { + if comment == nil { + continue + } + hasPos := comment.Position != nil + hasComfortFade := (comment.StartSide != nil) || (comment.Side != nil) || + (comment.StartLine != nil) || (comment.Line != nil) + + switch { + case hasPos && hasComfortFade: + return false, ErrMixedCommentStyles + case hasPos && isCF != nil && *isCF: + return false, ErrMixedCommentStyles + case hasComfortFade && isCF != nil && !*isCF: + return false, ErrMixedCommentStyles + } + isCF = &hasComfortFade + } + if isCF != nil { + return *isCF, nil + } + return false, nil +} + // PullRequestReviewDismissalRequest represents a request to dismiss a review. type PullRequestReviewDismissalRequest struct { Message *string `json:"message,omitempty"` @@ -61,14 +100,12 @@ func (r PullRequestReviewDismissalRequest) String() string { // ListReviews lists all reviews on the specified pull request. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#list-reviews-for-a-pull-request // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request -func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) { +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews +func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -89,11 +126,9 @@ func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo strin // GetReview fetches the specified pull request review. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#get-a-review-for-a-pull-request // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) @@ -113,11 +148,9 @@ func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, // DeletePendingReview deletes the specified pull request pending review. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#delete-a-pending-review-for-a-pull-request // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review +//meta:operation DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) @@ -137,14 +170,12 @@ func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, re // ListReviewComments lists all the comments for the specified review. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#list-comments-for-a-pull-request-review // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review -func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) { +//meta:operation GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments +func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -165,11 +196,43 @@ func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, rep // CreateReview creates a new review on the specified pull request. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// In order to use multi-line comments, you must use the "comfort fade" preview. +// This replaces the use of the "Position" field in comments with 4 new fields: +// +// [Start]Side, and [Start]Line. +// +// These new fields must be used for ALL comments (including single-line), +// with the following restrictions (empirically observed, so subject to change). +// +// For single-line "comfort fade" comments, you must use: // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review +// Path: &path, // as before +// Body: &body, // as before +// Side: &"RIGHT" (or "LEFT") +// Line: &123, // NOT THE SAME AS POSITION, this is an actual line number. +// +// If StartSide or StartLine is used with single-line comments, a 422 is returned. +// +// For multi-line "comfort fade" comments, you must use: +// +// Path: &path, // as before +// Body: &body, // as before +// StartSide: &"RIGHT" (or "LEFT") +// Side: &"RIGHT" (or "LEFT") +// StartLine: &120, +// Line: &125, +// +// Suggested edits are made by commenting on the lines to replace, and including the +// suggested edit in a block like this (it may be surrounded in non-suggestion markdown): +// +// ```suggestion +// Use this instead. +// It is waaaaaay better. +// ``` +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#create-a-review-for-a-pull-request +// +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) @@ -178,6 +241,15 @@ func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo stri return nil, nil, err } + // Detect which style of review comment is being used. + if isCF, err := review.isComfortFadePreview(); err != nil { + return nil, nil, err + } else if isCF { + // If the review comments are using the comfort fade preview fields, + // then pass the comfort fade header. + req.Header.Set("Accept", mediaTypeMultiLineCommentsPreview) + } + r := new(PullRequestReview) resp, err := s.client.Do(ctx, req, r) if err != nil { @@ -187,13 +259,36 @@ func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo stri return r, resp, nil } +// UpdateReview updates the review summary on the specified pull request. +// +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#update-a-review-for-a-pull-request +// +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id} +func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) { + opts := &struct { + Body string `json:"body"` + }{Body: body} + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + review := &PullRequestReview{} + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + // SubmitReview submits a specified review on the specified pull request. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#submit-a-review-for-a-pull-request // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review +//meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) @@ -213,11 +308,9 @@ func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo stri // DismissReview dismisses a specified review on the specified pull request. // -// TODO: Follow up with GitHub support about an issue with this method's -// returned error format and remove this comment once it's fixed. -// Read more about it here - https://github.com/google/go-github/issues/540 +// GitHub API docs: https://docs.github.com/rest/pulls/reviews#dismiss-a-review-for-a-pull-request // -// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review +//meta:operation PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) diff --git a/vendor/github.com/google/go-github/v68/github/pulls_threads.go b/vendor/github.com/google/go-github/v68/github/pulls_threads.go new file mode 100644 index 00000000..23e924d8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/pulls_threads.go @@ -0,0 +1,17 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// PullRequestThread represents a thread of comments on a pull request. +type PullRequestThread struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Comments []*PullRequestComment `json:"comments,omitempty"` +} + +func (p PullRequestThread) String() string { + return Stringify(p) +} diff --git a/vendor/github.com/google/go-github/v68/github/rate_limit.go b/vendor/github.com/google/go-github/v68/github/rate_limit.go new file mode 100644 index 00000000..5b01b573 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/rate_limit.go @@ -0,0 +1,125 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// RateLimitService provides access to rate limit functions in the GitHub API. +type RateLimitService service + +// Rate represents the rate limit for the current client. +type Rate struct { + // The number of requests per hour the client is currently limited to. + Limit int `json:"limit"` + + // The number of remaining requests the client can make this hour. + Remaining int `json:"remaining"` + + // The time at which the current rate limit will reset. + Reset Timestamp `json:"reset"` +} + +func (r Rate) String() string { + return Stringify(r) +} + +// RateLimits represents the rate limits for the current client. +type RateLimits struct { + // The rate limit for non-search API requests. Unauthenticated + // requests are limited to 60 per hour. Authenticated requests are + // limited to 5,000 per hour. + // + // GitHub API docs: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting + Core *Rate `json:"core"` + + // The rate limit for search API requests. Unauthenticated requests + // are limited to 10 requests per minutes. Authenticated requests are + // limited to 30 per minute. + // + // GitHub API docs: https://docs.github.com/en/rest/search#rate-limit + Search *Rate `json:"search"` + + // GitHub API docs: https://docs.github.com/en/graphql/overview/resource-limitations#rate-limit + GraphQL *Rate `json:"graphql"` + + // GitHub API dos: https://docs.github.com/en/rest/rate-limit + IntegrationManifest *Rate `json:"integration_manifest"` + + SourceImport *Rate `json:"source_import"` + CodeScanningUpload *Rate `json:"code_scanning_upload"` + ActionsRunnerRegistration *Rate `json:"actions_runner_registration"` + SCIM *Rate `json:"scim"` + DependencySnapshots *Rate `json:"dependency_snapshots"` + CodeSearch *Rate `json:"code_search"` + AuditLog *Rate `json:"audit_log"` +} + +func (r RateLimits) String() string { + return Stringify(r) +} + +// Get returns the rate limits for the current client. +// +// GitHub API docs: https://docs.github.com/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user +// +//meta:operation GET /rate_limit +func (s *RateLimitService) Get(ctx context.Context) (*RateLimits, *Response, error) { + req, err := s.client.NewRequest("GET", "rate_limit", nil) + if err != nil { + return nil, nil, err + } + + response := new(struct { + Resources *RateLimits `json:"resources"` + }) + + // This resource is not subject to rate limits. + ctx = context.WithValue(ctx, bypassRateLimitCheck, true) + resp, err := s.client.Do(ctx, req, response) + if err != nil { + return nil, resp, err + } + + if response.Resources != nil { + s.client.rateMu.Lock() + if response.Resources.Core != nil { + s.client.rateLimits[CoreCategory] = *response.Resources.Core + } + if response.Resources.Search != nil { + s.client.rateLimits[SearchCategory] = *response.Resources.Search + } + if response.Resources.GraphQL != nil { + s.client.rateLimits[GraphqlCategory] = *response.Resources.GraphQL + } + if response.Resources.IntegrationManifest != nil { + s.client.rateLimits[IntegrationManifestCategory] = *response.Resources.IntegrationManifest + } + if response.Resources.SourceImport != nil { + s.client.rateLimits[SourceImportCategory] = *response.Resources.SourceImport + } + if response.Resources.CodeScanningUpload != nil { + s.client.rateLimits[CodeScanningUploadCategory] = *response.Resources.CodeScanningUpload + } + if response.Resources.ActionsRunnerRegistration != nil { + s.client.rateLimits[ActionsRunnerRegistrationCategory] = *response.Resources.ActionsRunnerRegistration + } + if response.Resources.SCIM != nil { + s.client.rateLimits[ScimCategory] = *response.Resources.SCIM + } + if response.Resources.DependencySnapshots != nil { + s.client.rateLimits[DependencySnapshotsCategory] = *response.Resources.DependencySnapshots + } + if response.Resources.CodeSearch != nil { + s.client.rateLimits[CodeSearchCategory] = *response.Resources.CodeSearch + } + if response.Resources.AuditLog != nil { + s.client.rateLimits[AuditLogCategory] = *response.Resources.AuditLog + } + s.client.rateMu.Unlock() + } + + return response.Resources, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/reactions.go b/vendor/github.com/google/go-github/v68/github/reactions.go new file mode 100644 index 00000000..9f9f72fa --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/reactions.go @@ -0,0 +1,570 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/reactions +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 `json:"id,omitempty"` + User *User `json:"user,omitempty"` + NodeID *string `json:"node_id,omitempty"` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content *string `json:"content,omitempty"` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int `json:"total_count,omitempty"` + PlusOne *int `json:"+1,omitempty"` + MinusOne *int `json:"-1,omitempty"` + Laugh *int `json:"laugh,omitempty"` + Confused *int `json:"confused,omitempty"` + Heart *int `json:"heart,omitempty"` + Hooray *int `json:"hooray,omitempty"` + Rocket *int `json:"rocket,omitempty"` + Eyes *int `json:"eyes,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (r Reaction) String() string { + return Stringify(r) +} + +// ListCommentReactionOptions specifies the optional parameters to the +// ReactionsService.ListCommentReactions method. +type ListCommentReactionOptions struct { + // Content restricts the returned comment reactions to only those with the given type. + // Omit this parameter to list all reactions to a commit comment. + // Possible values are: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content string `url:"content,omitempty"` + + ListOptions +} + +// ListCommentReactions lists the reactions for a commit comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-commit-comment +// +//meta:operation GET /repos/{owner}/{repo}/comments/{comment_id}/reactions +func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-commit-comment +// +//meta:operation POST /repos/{owner}/{repo}/comments/{comment_id}/reactions +func (s *ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteCommentReaction deletes the reaction for a commit comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-commit-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// DeleteCommentReactionByID deletes the reaction for a commit comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-commit-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repositories/%v/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// ListIssueReactions lists the reactions for an issue. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-an-issue +// +//meta:operation GET /repos/{owner}/{repo}/issues/{issue_number}/reactions +func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-an-issue +// +//meta:operation POST /repos/{owner}/{repo}/issues/{issue_number}/reactions +func (s *ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueReaction deletes the reaction to an issue. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueReaction(ctx context.Context, owner, repo string, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/%v/reactions/%v", owner, repo, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueReactionByID deletes the reaction to an issue by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueReactionByID(ctx context.Context, repoID, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/%v/reactions/%v", repoID, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListIssueCommentReactions lists the reactions for an issue comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-an-issue-comment +// +//meta:operation GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions +func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-an-issue-comment +// +//meta:operation POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions +func (s *ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueCommentReaction deletes the reaction to an issue comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueCommentReactionByID deletes the reaction to an issue comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-an-issue-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeleteIssueCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListPullRequestCommentReactions lists the reactions for a pull request review comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-pull-request-review-comment +// +//meta:operation GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions +func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-pull-request-review-comment +// +//meta:operation POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions +func (s *ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeletePullRequestCommentReaction deletes the reaction to a pull request review comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-pull-request-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeletePullRequestCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeletePullRequestCommentReactionByID deletes the reaction to a pull request review comment by repository ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-a-pull-request-comment-reaction +// +//meta:operation DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id} +func (s *ReactionsService) DeletePullRequestCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/pulls/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionReactions lists the reactions for a team discussion. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-team-discussion-legacy +// +//meta:operation GET /teams/{team_id}/discussions/{discussion_number}/reactions +func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateTeamDiscussionReaction creates a reaction for a team discussion. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-legacy +// +//meta:operation POST /teams/{team_id}/discussions/{discussion_number}/reactions +func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionReaction deletes the reaction to a team discussion. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-team-discussion-reaction +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteTeamDiscussionReaction(ctx context.Context, org, teamSlug string, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/reactions/%v", org, teamSlug, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionReactionByOrgIDAndTeamID deletes the reaction to a team discussion by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions +func (s *ReactionsService) DeleteTeamDiscussionReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/reactions/%v", orgID, teamID, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#list-reactions-for-a-team-discussion-comment-legacy +// +//meta:operation GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + return m, resp, nil +} + +// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-comment-legacy +// +//meta:operation POST /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#delete-team-discussion-comment-reaction +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id} +func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID deletes the reaction to a team discussion comment by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-team-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions +func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v", orgID, teamID, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} + +// CreateReleaseReaction creates a reaction to a release. +// Note that a response with a Status: 200 OK means that you already +// added the reaction type to this release. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/rest/reactions/reactions#create-reaction-for-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases/{release_id}/reactions +func (s *ReactionsService) CreateReleaseReaction(ctx context.Context, owner, repo string, releaseID int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/releases/%v/reactions", owner, repo, releaseID) + + body := &Reaction{Content: Ptr(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos.go b/vendor/github.com/google/go-github/v68/github/repos.go new file mode 100644 index 00000000..9faed401 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos.go @@ -0,0 +1,2428 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strings" +) + +const githubBranchNotProtected string = "Branch not protected" + +var ErrBranchNotProtected = errors.New("branch is not protected") + +// RepositoriesService handles communication with the repository related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/repos/ +type RepositoriesService service + +// Repository represents a GitHub repository. +type Repository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + MirrorURL *string `json:"mirror_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Language *string `json:"language,omitempty"` + Fork *bool `json:"fork,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + NetworkCount *int `json:"network_count,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated. + StargazersCount *int `json:"stargazers_count,omitempty"` + SubscribersCount *int `json:"subscribers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated. + Watchers *int `json:"watchers,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated. + Size *int `json:"size,omitempty"` + AutoInit *bool `json:"auto_init,omitempty"` + Parent *Repository `json:"parent,omitempty"` + Source *Repository `json:"source,omitempty"` + TemplateRepository *Repository `json:"template_repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Permissions map[string]bool `json:"permissions,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + WebCommitSignoffRequired *bool `json:"web_commit_signoff_required,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` + UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` + SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "COMMIT_OR_PR_TITLE" + SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "COMMIT_MESSAGES", "BLANK" + MergeCommitTitle *string `json:"merge_commit_title,omitempty"` // Can be one of: "PR_TITLE", "MERGE_MESSAGE" + MergeCommitMessage *string `json:"merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "PR_TITLE", "BLANK" + Topics []string `json:"topics,omitempty"` + CustomProperties map[string]interface{} `json:"custom_properties,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + + // Only provided when using RepositoriesService.Get while in preview + License *License `json:"license,omitempty"` + + // Additional mutable fields when creating and editing a repository + Private *bool `json:"private,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasDiscussions *bool `json:"has_discussions,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + + // Options for configuring Advanced Security and Secret Scanning + SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + AssigneesURL *string `json:"assignees_url,omitempty"` + BlobsURL *string `json:"blobs_url,omitempty"` + BranchesURL *string `json:"branches_url,omitempty"` + CollaboratorsURL *string `json:"collaborators_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CompareURL *string `json:"compare_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + ContributorsURL *string `json:"contributors_url,omitempty"` + DeploymentsURL *string `json:"deployments_url,omitempty"` + DownloadsURL *string `json:"downloads_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ForksURL *string `json:"forks_url,omitempty"` + GitCommitsURL *string `json:"git_commits_url,omitempty"` + GitRefsURL *string `json:"git_refs_url,omitempty"` + GitTagsURL *string `json:"git_tags_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssueCommentURL *string `json:"issue_comment_url,omitempty"` + IssueEventsURL *string `json:"issue_events_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + KeysURL *string `json:"keys_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + LanguagesURL *string `json:"languages_url,omitempty"` + MergesURL *string `json:"merges_url,omitempty"` + MilestonesURL *string `json:"milestones_url,omitempty"` + NotificationsURL *string `json:"notifications_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + ReleasesURL *string `json:"releases_url,omitempty"` + StargazersURL *string `json:"stargazers_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + SubscribersURL *string `json:"subscribers_url,omitempty"` + SubscriptionURL *string `json:"subscription_url,omitempty"` + TagsURL *string `json:"tags_url,omitempty"` + TreesURL *string `json:"trees_url,omitempty"` + TeamsURL *string `json:"teams_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Visibility is only used for Create and Edit endpoints. The visibility field + // overrides the field parameter when both are used. + // Can be one of public, private or internal. + Visibility *string `json:"visibility,omitempty"` + + // RoleName is only returned by the API 'check team permissions for a repository'. + // See: teams.go (IsTeamRepoByID) https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository + RoleName *string `json:"role_name,omitempty"` +} + +func (r Repository) String() string { + return Stringify(r) +} + +// BranchListOptions specifies the optional parameters to the +// RepositoriesService.ListBranches method. +type BranchListOptions struct { + // Setting to true returns only protected branches. + // When set to false, only unprotected branches are returned. + // Omitting this parameter returns all branches. + // Default: nil + Protected *bool `url:"protected,omitempty"` + + ListOptions +} + +// RepositoryListOptions specifies the optional parameters to the +// RepositoriesService.List method. +type RepositoryListOptions struct { + // See RepositoryListByAuthenticatedUserOptions.Visibility + Visibility string `url:"visibility,omitempty"` + + // See RepositoryListByAuthenticatedUserOptions.Affiliation + Affiliation string `url:"affiliation,omitempty"` + + // See RepositoryListByUserOptions.Type or RepositoryListByAuthenticatedUserOptions.Type + Type string `url:"type,omitempty"` + + // See RepositoryListByUserOptions.Sort or RepositoryListByAuthenticatedUserOptions.Sort + Sort string `url:"sort,omitempty"` + + // See RepositoryListByUserOptions.Direction or RepositoryListByAuthenticatedUserOptions.Direction + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// SecurityAndAnalysis specifies the optional advanced security features +// that are enabled on a given repository. +type SecurityAndAnalysis struct { + AdvancedSecurity *AdvancedSecurity `json:"advanced_security,omitempty"` + SecretScanning *SecretScanning `json:"secret_scanning,omitempty"` + SecretScanningPushProtection *SecretScanningPushProtection `json:"secret_scanning_push_protection,omitempty"` + DependabotSecurityUpdates *DependabotSecurityUpdates `json:"dependabot_security_updates,omitempty"` + SecretScanningValidityChecks *SecretScanningValidityChecks `json:"secret_scanning_validity_checks,omitempty"` +} + +func (s SecurityAndAnalysis) String() string { + return Stringify(s) +} + +// AdvancedSecurity specifies the state of advanced security on a repository. +// +// GitHub API docs: https://docs.github.com/github/getting-started-with-github/learning-about-github/about-github-advanced-security +type AdvancedSecurity struct { + Status *string `json:"status,omitempty"` +} + +func (a AdvancedSecurity) String() string { + return Stringify(a) +} + +// SecretScanning specifies the state of secret scanning on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/secret-security/about-secret-scanning +type SecretScanning struct { + Status *string `json:"status,omitempty"` +} + +func (s SecretScanning) String() string { + return Stringify(s) +} + +// SecretScanningPushProtection specifies the state of secret scanning push protection on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/secret-scanning/about-secret-scanning#about-secret-scanning-for-partner-patterns +type SecretScanningPushProtection struct { + Status *string `json:"status,omitempty"` +} + +func (s SecretScanningPushProtection) String() string { + return Stringify(s) +} + +// DependabotSecurityUpdates specifies the state of Dependabot security updates on a repository. +// +// GitHub API docs: https://docs.github.com/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates +type DependabotSecurityUpdates struct { + Status *string `json:"status,omitempty"` +} + +func (d DependabotSecurityUpdates) String() string { + return Stringify(d) +} + +// SecretScanningValidityChecks represents the state of secret scanning validity checks on a repository. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-security-and-analysis-settings-for-your-repository#allowing-validity-checks-for-partner-patterns-in-a-repository +type SecretScanningValidityChecks struct { + Status *string `json:"status,omitempty"` +} + +// List calls either RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser +// depending on whether user is empty. +// +// Deprecated: Use RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser instead. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-a-user +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user +// +//meta:operation GET /user/repos +//meta:operation GET /users/{username}/repos +func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { + if opts == nil { + opts = &RepositoryListOptions{} + } + if user != "" { + return s.ListByUser(ctx, user, &RepositoryListByUserOptions{ + Type: opts.Type, + Sort: opts.Sort, + Direction: opts.Direction, + ListOptions: opts.ListOptions, + }) + } + return s.ListByAuthenticatedUser(ctx, &RepositoryListByAuthenticatedUserOptions{ + Visibility: opts.Visibility, + Affiliation: opts.Affiliation, + Type: opts.Type, + Sort: opts.Sort, + Direction: opts.Direction, + ListOptions: opts.ListOptions, + }) +} + +// RepositoryListByUserOptions specifies the optional parameters to the +// RepositoriesService.ListByUser method. +type RepositoryListByUserOptions struct { + // Limit results to repositories of the specified type. + // Default: owner + // Can be one of: all, owner, member + Type string `url:"type,omitempty"` + + // The property to sort the results by. + // Default: full_name + // Can be one of: created, updated, pushed, full_name + Sort string `url:"sort,omitempty"` + + // The order to sort by. + // Default: asc when using full_name, otherwise desc. + // Can be one of: asc, desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByUser lists public repositories for the specified user. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-a-user +// +//meta:operation GET /users/{username}/repos +func (s *RepositoriesService) ListByUser(ctx context.Context, user string, opts *RepositoryListByUserOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("users/%v/repos", user) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByAuthenticatedUserOptions specifies the optional parameters to the +// RepositoriesService.ListByAuthenticatedUser method. +type RepositoryListByAuthenticatedUserOptions struct { + // Limit results to repositories with the specified visibility. + // Default: all + // Can be one of: all, public, private + Visibility string `url:"visibility,omitempty"` + + // List repos of given affiliation[s]. + // Comma-separated list of values. Can include: + // * owner: Repositories that are owned by the authenticated user. + // * collaborator: Repositories that the user has been added to as a + // collaborator. + // * organization_member: Repositories that the user has access to through + // being a member of an organization. This includes every repository on + // every team that the user is on. + // Default: owner,collaborator,organization_member + Affiliation string `url:"affiliation,omitempty"` + + // Limit results to repositories of the specified type. Will cause a 422 error if + // used in the same request as visibility or affiliation. + // Default: all + // Can be one of: all, owner, public, private, member + Type string `url:"type,omitempty"` + + // The property to sort the results by. + // Default: full_name + // Can be one of: created, updated, pushed, full_name + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default: when using full_name: asc; otherwise desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByAuthenticatedUser lists repositories for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user +// +//meta:operation GET /user/repos +func (s *RepositoriesService) ListByAuthenticatedUser(ctx context.Context, opts *RepositoryListByAuthenticatedUserOptions) ([]*Repository, *Response, error) { + u := "user/repos" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByOrgOptions specifies the optional parameters to the +// RepositoriesService.ListByOrg method. +type RepositoryListByOrgOptions struct { + // Type of repositories to list. Possible values are: all, public, private, + // forks, sources, member. Default is "all". + Type string `url:"type,omitempty"` + + // How to sort the repository list. Can be one of created, updated, pushed, + // full_name. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default when using full_name: asc; otherwise desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByOrg lists the repositories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-organization-repositories +// +//meta:operation GET /orgs/{org}/repos +func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/repos", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListAllOptions specifies the optional parameters to the +// RepositoriesService.ListAll method. +type RepositoryListAllOptions struct { + // ID of the last repository seen + Since int64 `url:"since,omitempty"` +} + +// ListAll lists all GitHub repositories in the order that they were created. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-public-repositories +// +//meta:operation GET /repositories +func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) { + u, err := addOptions("repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// createRepoRequest is a subset of Repository and is used internally +// by Create to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1014 for more +// information. +type createRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + + Private *bool `json:"private,omitempty"` + Visibility *string `json:"visibility,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasDiscussions *bool `json:"has_discussions,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + AutoInit *bool `json:"auto_init,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` + UseSquashPRTitleAsDefault *bool `json:"use_squash_pr_title_as_default,omitempty"` + SquashMergeCommitTitle *string `json:"squash_merge_commit_title,omitempty"` + SquashMergeCommitMessage *string `json:"squash_merge_commit_message,omitempty"` + MergeCommitTitle *string `json:"merge_commit_title,omitempty"` + MergeCommitMessage *string `json:"merge_commit_message,omitempty"` +} + +// Create a new repository. If an organization is specified, the new +// repository will be created under that org. If the empty string is +// specified, it will be created for the authenticated user. +// +// Note that only a subset of the repo fields are used and repo must +// not be nil. +// +// Also note that this method will return the response without actually +// waiting for GitHub to finish creating the repository and letting the +// changes propagate throughout its servers. You may set up a loop with +// exponential back-off to verify repository's creation. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-an-organization-repository +// +//meta:operation POST /orgs/{org}/repos +//meta:operation POST /user/repos +func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { + var u string + if org != "" { + u = fmt.Sprintf("orgs/%v/repos", org) + } else { + u = "user/repos" + } + + repoReq := &createRepoRequest{ + Name: repo.Name, + Description: repo.Description, + Homepage: repo.Homepage, + Private: repo.Private, + Visibility: repo.Visibility, + HasIssues: repo.HasIssues, + HasProjects: repo.HasProjects, + HasWiki: repo.HasWiki, + HasDiscussions: repo.HasDiscussions, + IsTemplate: repo.IsTemplate, + TeamID: repo.TeamID, + AutoInit: repo.AutoInit, + GitignoreTemplate: repo.GitignoreTemplate, + LicenseTemplate: repo.LicenseTemplate, + AllowSquashMerge: repo.AllowSquashMerge, + AllowMergeCommit: repo.AllowMergeCommit, + AllowRebaseMerge: repo.AllowRebaseMerge, + AllowUpdateBranch: repo.AllowUpdateBranch, + AllowAutoMerge: repo.AllowAutoMerge, + AllowForking: repo.AllowForking, + DeleteBranchOnMerge: repo.DeleteBranchOnMerge, + UseSquashPRTitleAsDefault: repo.UseSquashPRTitleAsDefault, + SquashMergeCommitTitle: repo.SquashMergeCommitTitle, + SquashMergeCommitMessage: repo.SquashMergeCommitMessage, + MergeCommitTitle: repo.MergeCommitTitle, + MergeCommitMessage: repo.MergeCommitMessage, + } + + req, err := s.client.NewRequest("POST", u, repoReq) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// TemplateRepoRequest represents a request to create a repository from a template. +type TemplateRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Owner *string `json:"owner,omitempty"` + Description *string `json:"description,omitempty"` + + IncludeAllBranches *bool `json:"include_all_branches,omitempty"` + Private *bool `json:"private,omitempty"` +} + +// CreateFromTemplate generates a repository from a template. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-using-a-template +// +//meta:operation POST /repos/{template_owner}/{template_repo}/generate +func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo) + + req, err := s.client.NewRequest("POST", u, templateRepoReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Get fetches a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-a-repository +// +//meta:operation GET /repos/{owner}/{repo} +func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when the license support fully launches + // https://docs.github.com/rest/licenses/#get-a-repositorys-license + acceptHeaders := []string{ + mediaTypeCodesOfConductPreview, + mediaTypeTopicsPreview, + mediaTypeRepositoryTemplatePreview, + mediaTypeRepositoryVisibilityPreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// GetCodeOfConduct gets the contents of a repository's code of conduct. +// Note that https://docs.github.com/rest/codes-of-conduct#about-the-codes-of-conduct-api +// says to use the GET /repos/{owner}/{repo} endpoint. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-a-repository +// +//meta:operation GET /repos/{owner}/{repo} +func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r.GetCodeOfConduct(), resp, nil +} + +// GetByID fetches a repository. +// +// Note: GetByID uses the undocumented GitHub API endpoint "GET /repositories/{repository_id}". +// +//meta:operation GET /repositories/{repository_id} +func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { + u := fmt.Sprintf("repositories/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// Edit updates a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#update-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo} +func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("PATCH", u, repository) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Delete a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#delete-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo} +func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Contributor represents a repository contributor. +type Contributor struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + Contributions *int `json:"contributions,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ListContributorsOptions specifies the optional parameters to the +// RepositoriesService.ListContributors method. +type ListContributorsOptions struct { + // Include anonymous contributors in results or not + Anon string `url:"anon,omitempty"` + + ListOptions +} + +// GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + resp, err := s.client.Do(ctx, req, nil) + vulnerabilityAlertsEnabled, err := parseBoolResponse(err) + return vulnerabilityAlertsEnabled, resp, err +} + +// EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-vulnerability-alerts +// +//meta:operation PUT /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-vulnerability-alerts +// +//meta:operation DELETE /repos/{owner}/{repo}/vulnerability-alerts +func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetAutomatedSecurityFixes checks if the automated security fixes for a repository are enabled. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-automated-security-fixes-are-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) GetAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*AutomatedSecurityFixes, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + p := new(AutomatedSecurityFixes) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + return p, resp, nil +} + +// EnableAutomatedSecurityFixes enables the automated security fixes for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-automated-security-fixes +// +//meta:operation PUT /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-automated-security-fixes +// +//meta:operation DELETE /repos/{owner}/{repo}/automated-security-fixes +func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListContributors lists contributors for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-contributors +// +//meta:operation GET /repos/{owner}/{repo}/contributors +func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributor []*Contributor + resp, err := s.client.Do(ctx, req, &contributor) + if err != nil { + return nil, resp, err + } + + return contributor, resp, nil +} + +// ListLanguages lists languages for the specified repository. The returned map +// specifies the languages and the number of bytes of code written in that +// language. For example: +// +// { +// "C": 78769, +// "Python": 7769 +// } +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-languages +// +//meta:operation GET /repos/{owner}/{repo}/languages +func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + languages := make(map[string]int) + resp, err := s.client.Do(ctx, req, &languages) + if err != nil { + return nil, resp, err + } + + return languages, resp, nil +} + +// ListTeams lists the teams for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-teams +// +//meta:operation GET /repos/{owner}/{repo}/teams +func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// RepositoryTag represents a repository tag. +type RepositoryTag struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` +} + +// ListTags lists tags for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-repository-tags +// +//meta:operation GET /repos/{owner}/{repo}/tags +func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tags []*RepositoryTag + resp, err := s.client.Do(ctx, req, &tags) + if err != nil { + return nil, resp, err + } + + return tags, resp, nil +} + +// Branch represents a repository branch. +type Branch struct { + Name *string `json:"name,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` + + // Protection will always be included in APIs which return the + // 'Branch With Protection' schema such as 'Get a branch', but may + // not be included in APIs that return the `Short Branch` schema + // such as 'List branches'. In such cases, if branch protection is + // enabled, Protected will be `true` but this will be nil, and + // additional protection details can be obtained by calling GetBranch(). + Protection *Protection `json:"protection,omitempty"` +} + +// Protection represents a repository branch's protection. +type Protection struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` + EnforceAdmins *AdminEnforcement `json:"enforce_admins"` + Restrictions *BranchRestrictions `json:"restrictions"` + RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` + AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` + AllowDeletions *AllowDeletions `json:"allow_deletions"` + RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"` + BlockCreations *BlockCreations `json:"block_creations,omitempty"` + LockBranch *LockBranch `json:"lock_branch,omitempty"` + AllowForkSyncing *AllowForkSyncing `json:"allow_fork_syncing,omitempty"` + RequiredSignatures *SignaturesProtectedBranch `json:"required_signatures,omitempty"` + URL *string `json:"url,omitempty"` +} + +// BlockCreations represents whether users can push changes that create branches. If this is true, this +// setting blocks pushes that create new branches, unless the push is initiated by a user, team, or app +// which has the ability to push. +type BlockCreations struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// LockBranch represents if the branch is marked as read-only. If this is true, users will not be able to push to the branch. +type LockBranch struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// AllowForkSyncing represents whether users can pull changes from upstream when the branch is locked. +type AllowForkSyncing struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// BranchProtectionRule represents the rule applied to a repositories branch. +type BranchProtectionRule struct { + ID *int64 `json:"id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Name *string `json:"name,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PullRequestReviewsEnforcementLevel *string `json:"pull_request_reviews_enforcement_level,omitempty"` + RequiredApprovingReviewCount *int `json:"required_approving_review_count,omitempty"` + DismissStaleReviewsOnPush *bool `json:"dismiss_stale_reviews_on_push,omitempty"` + AuthorizedDismissalActorsOnly *bool `json:"authorized_dismissal_actors_only,omitempty"` + IgnoreApprovalsFromContributors *bool `json:"ignore_approvals_from_contributors,omitempty"` + RequireCodeOwnerReview *bool `json:"require_code_owner_review,omitempty"` + RequiredStatusChecks []string `json:"required_status_checks,omitempty"` + RequiredStatusChecksEnforcementLevel *string `json:"required_status_checks_enforcement_level,omitempty"` + StrictRequiredStatusChecksPolicy *bool `json:"strict_required_status_checks_policy,omitempty"` + SignatureRequirementEnforcementLevel *string `json:"signature_requirement_enforcement_level,omitempty"` + LinearHistoryRequirementEnforcementLevel *string `json:"linear_history_requirement_enforcement_level,omitempty"` + AdminEnforced *bool `json:"admin_enforced,omitempty"` + AllowForcePushesEnforcementLevel *string `json:"allow_force_pushes_enforcement_level,omitempty"` + AllowDeletionsEnforcementLevel *string `json:"allow_deletions_enforcement_level,omitempty"` + MergeQueueEnforcementLevel *string `json:"merge_queue_enforcement_level,omitempty"` + RequiredDeploymentsEnforcementLevel *string `json:"required_deployments_enforcement_level,omitempty"` + RequiredConversationResolutionLevel *string `json:"required_conversation_resolution_level,omitempty"` + AuthorizedActorsOnly *bool `json:"authorized_actors_only,omitempty"` + AuthorizedActorNames []string `json:"authorized_actor_names,omitempty"` +} + +// ProtectionChanges represents the changes to the rule if the BranchProtection was edited. +type ProtectionChanges struct { + AdminEnforced *AdminEnforcedChanges `json:"admin_enforced,omitempty"` + AllowDeletionsEnforcementLevel *AllowDeletionsEnforcementLevelChanges `json:"allow_deletions_enforcement_level,omitempty"` + AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"` + AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"` + AuthorizedDismissalActorsOnly *AuthorizedDismissalActorsOnlyChanges `json:"authorized_dismissal_actors_only,omitempty"` + CreateProtected *CreateProtectedChanges `json:"create_protected,omitempty"` + DismissStaleReviewsOnPush *DismissStaleReviewsOnPushChanges `json:"dismiss_stale_reviews_on_push,omitempty"` + LinearHistoryRequirementEnforcementLevel *LinearHistoryRequirementEnforcementLevelChanges `json:"linear_history_requirement_enforcement_level,omitempty"` + PullRequestReviewsEnforcementLevel *PullRequestReviewsEnforcementLevelChanges `json:"pull_request_reviews_enforcement_level,omitempty"` + RequireCodeOwnerReview *RequireCodeOwnerReviewChanges `json:"require_code_owner_review,omitempty"` + RequiredConversationResolutionLevel *RequiredConversationResolutionLevelChanges `json:"required_conversation_resolution_level,omitempty"` + RequiredDeploymentsEnforcementLevel *RequiredDeploymentsEnforcementLevelChanges `json:"required_deployments_enforcement_level,omitempty"` + RequiredStatusChecks *RequiredStatusChecksChanges `json:"required_status_checks,omitempty"` + RequiredStatusChecksEnforcementLevel *RequiredStatusChecksEnforcementLevelChanges `json:"required_status_checks_enforcement_level,omitempty"` + SignatureRequirementEnforcementLevel *SignatureRequirementEnforcementLevelChanges `json:"signature_requirement_enforcement_level,omitempty"` +} + +// AdminEnforcedChanges represents the changes made to the AdminEnforced policy. +type AdminEnforcedChanges struct { + From *bool `json:"from,omitempty"` +} + +// AllowDeletionsEnforcementLevelChanges represents the changes made to the AllowDeletionsEnforcementLevel policy. +type AllowDeletionsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// AuthorizedActorNames represents who are authorized to edit the branch protection rules. +type AuthorizedActorNames struct { + From []string `json:"from,omitempty"` +} + +// AuthorizedActorsOnly represents if the branch rule can be edited by authorized actors only. +type AuthorizedActorsOnly struct { + From *bool `json:"from,omitempty"` +} + +// AuthorizedDismissalActorsOnlyChanges represents the changes made to the AuthorizedDismissalActorsOnly policy. +type AuthorizedDismissalActorsOnlyChanges struct { + From *bool `json:"from,omitempty"` +} + +// CreateProtectedChanges represents the changes made to the CreateProtected policy. +type CreateProtectedChanges struct { + From *bool `json:"from,omitempty"` +} + +// DismissStaleReviewsOnPushChanges represents the changes made to the DismissStaleReviewsOnPushChanges policy. +type DismissStaleReviewsOnPushChanges struct { + From *bool `json:"from,omitempty"` +} + +// LinearHistoryRequirementEnforcementLevelChanges represents the changes made to the LinearHistoryRequirementEnforcementLevel policy. +type LinearHistoryRequirementEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// PullRequestReviewsEnforcementLevelChanges represents the changes made to the PullRequestReviewsEnforcementLevel policy. +type PullRequestReviewsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequireCodeOwnerReviewChanges represents the changes made to the RequireCodeOwnerReview policy. +type RequireCodeOwnerReviewChanges struct { + From *bool `json:"from,omitempty"` +} + +// RequiredConversationResolutionLevelChanges represents the changes made to the RequiredConversationResolutionLevel policy. +type RequiredConversationResolutionLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequiredDeploymentsEnforcementLevelChanges represents the changes made to the RequiredDeploymentsEnforcementLevel policy. +type RequiredDeploymentsEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// RequiredStatusChecksChanges represents the changes made to the RequiredStatusChecks policy. +type RequiredStatusChecksChanges struct { + From []string `json:"from,omitempty"` +} + +// RequiredStatusChecksEnforcementLevelChanges represents the changes made to the RequiredStatusChecksEnforcementLevel policy. +type RequiredStatusChecksEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// SignatureRequirementEnforcementLevelChanges represents the changes made to the SignatureRequirementEnforcementLevel policy. +type SignatureRequirementEnforcementLevelChanges struct { + From *string `json:"from,omitempty"` +} + +// ProtectionRequest represents a request to create/edit a branch's protection. +type ProtectionRequest struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` + EnforceAdmins bool `json:"enforce_admins"` + Restrictions *BranchRestrictionsRequest `json:"restrictions"` + // Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch. + RequireLinearHistory *bool `json:"required_linear_history,omitempty"` + // Permits force pushes to the protected branch by anyone with write access to the repository. + AllowForcePushes *bool `json:"allow_force_pushes,omitempty"` + // Allows deletion of the protected branch by anyone with write access to the repository. + AllowDeletions *bool `json:"allow_deletions,omitempty"` + // RequiredConversationResolution, if set to true, requires all comments + // on the pull request to be resolved before it can be merged to a protected branch. + RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"` + // BlockCreations, if set to true, will cause the restrictions setting to also block pushes + // which create new branches, unless initiated by a user, team, app with the ability to push. + BlockCreations *bool `json:"block_creations,omitempty"` + // LockBranch, if set to true, will prevent users from pushing to the branch. + LockBranch *bool `json:"lock_branch,omitempty"` + // AllowForkSyncing, if set to true, will allow users to pull changes from upstream + // when the branch is locked. + AllowForkSyncing *bool `json:"allow_fork_syncing,omitempty"` +} + +// RequiredStatusChecks represents the protection status of a individual branch. +type RequiredStatusChecks struct { + // Require branches to be up to date before merging. (Required.) + Strict bool `json:"strict"` + // The list of status checks to require in order to merge into this + // branch. An empty slice is valid. (Deprecated. Note: only one of + // Contexts/Checks can be populated, but at least one must be populated). + Contexts *[]string `json:"contexts,omitempty"` + // The list of status checks to require in order to merge into this + // branch. An empty slice is valid. + Checks *[]*RequiredStatusCheck `json:"checks,omitempty"` + ContextsURL *string `json:"contexts_url,omitempty"` + URL *string `json:"url,omitempty"` +} + +// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. +type RequiredStatusChecksRequest struct { + Strict *bool `json:"strict,omitempty"` + // Deprecated. Note: if both Contexts and Checks are populated, + // the GitHub API will only use Checks. + Contexts []string `json:"contexts,omitempty"` + Checks []*RequiredStatusCheck `json:"checks,omitempty"` +} + +// RequiredStatusCheck represents a status check of a protected branch. +type RequiredStatusCheck struct { + // The name of the required check. + Context string `json:"context"` + // The ID of the GitHub App that must provide this check. + // Omit this field to automatically select the GitHub App + // that has recently provided this check, + // or any app if it was not set by a GitHub App. + // Pass -1 to explicitly allow any app to set the status. + AppID *int64 `json:"app_id,omitempty"` +} + +// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. +type PullRequestReviewsEnforcement struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowances *BypassPullRequestAllowances `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps can dismiss pull request reviews. + DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval bool `json:"require_last_push_approval"` +} + +// PullRequestReviewsEnforcementRequest represents request to set the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above +// because the request structure is different from the response structure. +type PullRequestReviewsEnforcementRequest struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps should be allowed to dismiss pull request reviews. + // User, team and app dismissal restrictions are only available for + // organization-owned repositories. Must be nil for personal repositories. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval *bool `json:"require_last_push_approval,omitempty"` +} + +// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above +// because the patch request does not require all fields to be initialized. +type PullRequestReviewsEnforcementUpdate struct { + // Allow specific users, teams, or apps to bypass pull request requirements. + BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"` + // Specifies which users, teams and apps can dismiss pull request reviews. Can be omitted. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. + DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` + // RequireCodeOwnerReviews specifies if merging pull requests is blocked until code owners have reviewed. + RequireCodeOwnerReviews *bool `json:"require_code_owner_reviews,omitempty"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1 - 6 or 0 to not require reviewers. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + // RequireLastPushApproval specifies whether the last pusher to a pull request branch can approve it. + RequireLastPushApproval *bool `json:"require_last_push_approval,omitempty"` +} + +// RequireLinearHistory represents the configuration to enforce branches with no merge commit. +type RequireLinearHistory struct { + Enabled bool `json:"enabled"` +} + +// AllowDeletions represents the configuration to accept deletion of protected branches. +type AllowDeletions struct { + Enabled bool `json:"enabled"` +} + +// AllowForcePushes represents the configuration to accept forced pushes on protected branches. +type AllowForcePushes struct { + Enabled bool `json:"enabled"` +} + +// RequiredConversationResolution requires all comments on the pull request to be resolved before it can be +// merged to a protected branch when enabled. +type RequiredConversationResolution struct { + Enabled bool `json:"enabled"` +} + +// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. +type AdminEnforcement struct { + URL *string `json:"url,omitempty"` + Enabled bool `json:"enabled"` +} + +// BranchRestrictions represents the restriction that only certain users or +// teams may push to a branch. +type BranchRestrictions struct { + // The list of user logins with push access. + Users []*User `json:"users"` + // The list of team slugs with push access. + Teams []*Team `json:"teams"` + // The list of app slugs with push access. + Apps []*App `json:"apps"` +} + +// BranchRestrictionsRequest represents the request to create/edit the +// restriction that only certain users or teams may push to a branch. It is +// separate from BranchRestrictions above because the request structure is +// different from the response structure. +type BranchRestrictionsRequest struct { + // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) + Users []string `json:"users"` + // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) + Teams []string `json:"teams"` + // The list of app slugs with push access. + Apps []string `json:"apps"` +} + +// BypassPullRequestAllowances represents the people, teams, or apps who are allowed to bypass required pull requests. +type BypassPullRequestAllowances struct { + // The list of users allowed to bypass pull request requirements. + Users []*User `json:"users"` + // The list of teams allowed to bypass pull request requirements. + Teams []*Team `json:"teams"` + // The list of apps allowed to bypass pull request requirements. + Apps []*App `json:"apps"` +} + +// BypassPullRequestAllowancesRequest represents the people, teams, or apps who are +// allowed to bypass required pull requests. +// It is separate from BypassPullRequestAllowances above because the request structure is +// different from the response structure. +type BypassPullRequestAllowancesRequest struct { + // The list of user logins allowed to bypass pull request requirements. + Users []string `json:"users"` + // The list of team slugs allowed to bypass pull request requirements. + Teams []string `json:"teams"` + // The list of app slugs allowed to bypass pull request requirements. + Apps []string `json:"apps"` +} + +// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. +type DismissalRestrictions struct { + // The list of users who can dismiss pull request reviews. + Users []*User `json:"users"` + // The list of teams which can dismiss pull request reviews. + Teams []*Team `json:"teams"` + // The list of apps which can dismiss pull request reviews. + Apps []*App `json:"apps"` +} + +// DismissalRestrictionsRequest represents the request to create/edit the +// restriction to allows only specific users, teams or apps to dismiss pull request reviews. It is +// separate from DismissalRestrictions above because the request structure is +// different from the response structure. +// Note: Both Users and Teams must be nil, or both must be non-nil. +type DismissalRestrictionsRequest struct { + // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Users *[]string `json:"users,omitempty"` + // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Teams *[]string `json:"teams,omitempty"` + // The list of app slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Apps *[]string `json:"apps,omitempty"` +} + +// SignaturesProtectedBranch represents the protection status of an individual branch. +type SignaturesProtectedBranch struct { + URL *string `json:"url,omitempty"` + // Commits pushed to matching branches must have verified signatures. + Enabled *bool `json:"enabled,omitempty"` +} + +// AutomatedSecurityFixes represents their status. +type AutomatedSecurityFixes struct { + Enabled *bool `json:"enabled"` + Paused *bool `json:"paused"` +} + +// ListBranches lists branches for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#list-branches +// +//meta:operation GET /repos/{owner}/{repo}/branches +func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var branches []*Branch + resp, err := s.client.Do(ctx, req, &branches) + if err != nil { + return nil, resp, err + } + + return branches, resp, nil +} + +// GetBranch gets the specified branch for a repository. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#get-a-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch} +func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, maxRedirects int) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, url.PathEscape(branch)) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + b := new(Branch) + err = json.NewDecoder(resp.Body).Decode(b) + return b, newResponse(resp), err +} + +// renameBranchRequest represents a request to rename a branch. +type renameBranchRequest struct { + NewName string `json:"new_name"` +} + +// RenameBranch renames a branch in a repository. +// +// To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission. +// To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#rename-a-branch +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/rename +func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, url.PathEscape(branch)) + r := &renameBranchRequest{NewName: newName} + req, err := s.client.NewRequest("POST", u, r) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(ctx, req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, nil +} + +// GetBranchProtection gets the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-branch-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// GetRequiredStatusChecks gets the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-status-checks-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + p := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-all-status-check-contexts +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts +func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resp, err = s.client.Do(ctx, req, &contexts) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return contexts, resp, nil +} + +// UpdateBranchProtection updates the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-branch-protection +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, preq) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RemoveBranchProtection removes the protection of a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-branch-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection +func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetSignaturesProtectedBranch gets required signatures of protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-commit-signature-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + p := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#create-commit-signature-protection +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + r := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-commit-signature-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures +func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + return s.client.Do(ctx, req, nil) +} + +// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-status-check-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PATCH", u, sreq) + if err != nil { + return nil, nil, err + } + + sc := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, sc) + if err != nil { + return nil, resp, err + } + + return sc, resp, nil +} + +// RemoveRequiredStatusChecks removes the required status checks for a given protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-status-check-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks +func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// License gets the contents of a repository's license if one is detected. +// +// GitHub API docs: https://docs.github.com/rest/licenses/licenses#get-the-license-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/license +func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/license", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := &RepositoryLicense{} + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-pull-request-review-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-pull-request-review-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PATCH", u, patch) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#update-pull-request-review-protection +// +//meta:operation PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + + data := new(struct { + DismissalRestrictionsRequest `json:"dismissal_restrictions"` + }) + + req, err := s.client.NewRequest("PATCH", u, data) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-pull-request-review-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews +func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetAdminEnforcement gets admin enforcement information of a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-admin-branch-protection +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddAdminEnforcement adds admin enforcement to a protected branch. +// It requires admin access and branch protection to be enabled. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-admin-branch-protection +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveAdminEnforcement removes admin enforcement from a protected branch. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#delete-admin-branch-protection +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins +func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// repositoryTopics represents a collection of repository topics. +type repositoryTopics struct { + Names []string `json:"names"` +} + +// ListAllTopics lists topics for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#get-all-repository-topics +// +//meta:operation GET /repos/{owner}/{repo}/topics +func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + topics := new(repositoryTopics) + resp, err := s.client.Do(ctx, req, topics) + if err != nil { + return nil, resp, err + } + + return topics.Names, resp, nil +} + +// ReplaceAllTopics replaces all repository topics. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#replace-all-repository-topics +// +//meta:operation PUT /repos/{owner}/{repo}/topics +func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + t := &repositoryTopics{ + Names: topics, + } + if t.Names == nil { + t.Names = []string{} + } + req, err := s.client.NewRequest("PUT", u, t) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + t = new(repositoryTopics) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t.Names, resp, nil +} + +// ListApps lists the GitHub apps that have push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// Deprecated: Please use ListAppRestrictions instead. +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// ListAppRestrictions lists the GitHub apps that have push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: This is a wrapper around ListApps so a naming convention with ListUserRestrictions and ListTeamRestrictions is preserved. +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ListAppRestrictions(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { + return s.ListApps(ctx, owner, repo, branch) +} + +// ReplaceAppRestrictions replaces the apps that have push access to a given protected branch. +// It removes all apps that previously had push access and grants push access to the new list of apps. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-app-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// AddAppRestrictions grants the specified apps push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-app-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// RemoveAppRestrictions removes the restrictions of an app from pushing to this branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-app-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps +func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, apps) + if err != nil { + return nil, nil, err + } + + var newApps []*App + resp, err := s.client.Do(ctx, req, &newApps) + if err != nil { + return nil, resp, err + } + + return newApps, resp, nil +} + +// ListTeamRestrictions lists the GitHub teams that have push access to a given protected branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-teams-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) ListTeamRestrictions(ctx context.Context, owner, repo, branch string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ReplaceTeamRestrictions replaces the team that have push access to a given protected branch. +// This removes all teams that previously had push access and grants push access to the new list of teams. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-team-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) ReplaceTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// AddTeamRestrictions grants the specified teams push access to a given protected branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-team-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) AddTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// RemoveTeamRestrictions removes the restrictions of a team from pushing to this branch. +// It requires the GitHub teams to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-team-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams +func (s *RepositoriesService) RemoveTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, teams) + if err != nil { + return nil, nil, err + } + + var newTeams []*Team + resp, err := s.client.Do(ctx, req, &newTeams) + if err != nil { + return nil, resp, err + } + + return newTeams, resp, nil +} + +// ListUserRestrictions lists the GitHub users that have push access to a given protected branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#get-users-with-access-to-the-protected-branch +// +//meta:operation GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) ListUserRestrictions(ctx context.Context, owner, repo, branch string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ReplaceUserRestrictions replaces the user that have push access to a given protected branch. +// It removes all users that previously had push access and grants push access to the new list of users. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#set-user-access-restrictions +// +//meta:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) ReplaceUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("PUT", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// AddUserRestrictions grants the specified users push access to a given protected branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#add-user-access-restrictions +// +//meta:operation POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) AddUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("POST", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// RemoveUserRestrictions removes the restrictions of a user from pushing to this branch. +// It requires the GitHub users to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// +// GitHub API docs: https://docs.github.com/rest/branches/branch-protection#remove-user-access-restrictions +// +//meta:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users +func (s *RepositoriesService) RemoveUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch)) + req, err := s.client.NewRequest("DELETE", u, users) + if err != nil { + return nil, nil, err + } + + var newUsers []*User + resp, err := s.client.Do(ctx, req, &newUsers) + if err != nil { + return nil, resp, err + } + + return newUsers, resp, nil +} + +// TransferRequest represents a request to transfer a repository. +type TransferRequest struct { + NewOwner string `json:"new_owner"` + NewName *string `json:"new_name,omitempty"` + TeamID []int64 `json:"team_ids,omitempty"` +} + +// Transfer transfers a repository from one account or organization to another. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the transfer of the repository in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#transfer-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/transfer +func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) + + req, err := s.client.NewRequest("POST", u, &transfer) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DispatchRequestOptions represents a request to trigger a repository_dispatch event. +type DispatchRequestOptions struct { + // EventType is a custom webhook event name. (Required.) + EventType string `json:"event_type"` + // ClientPayload is a custom JSON payload with extra information about the webhook event. + // Defaults to an empty JSON object. + ClientPayload *json.RawMessage `json:"client_payload,omitempty"` +} + +// Dispatch triggers a repository_dispatch event in a GitHub Actions workflow. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#create-a-repository-dispatch-event +// +//meta:operation POST /repos/{owner}/{repo}/dispatches +func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo) + + req, err := s.client.NewRequest("POST", u, &opts) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// isBranchNotProtected determines whether a branch is not protected +// based on the error message returned by GitHub API. +func isBranchNotProtected(err error) bool { + errorResponse, ok := err.(*ErrorResponse) + return ok && errorResponse.Message == githubBranchNotProtected +} + +// EnablePrivateReporting enables private reporting of vulnerabilities for a +// repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-private-vulnerability-reporting-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) EnablePrivateReporting(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisablePrivateReporting disables private reporting of vulnerabilities for a +// repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-private-vulnerability-reporting-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) DisablePrivateReporting(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// checkPrivateReporting represents whether private vulnerability reporting is enabled. +type checkPrivateReporting struct { + Enabled bool `json:"enabled,omitempty"` +} + +// IsPrivateReportingEnabled checks if private vulnerability reporting is enabled +// for the repository and returns a boolean indicating the status. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-private-vulnerability-reporting-is-enabled-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/private-vulnerability-reporting +func (s *RepositoriesService) IsPrivateReportingEnabled(ctx context.Context, owner, repo string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/private-vulnerability-reporting", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + privateReporting := new(checkPrivateReporting) + resp, err := s.client.Do(ctx, req, privateReporting) + return privateReporting.Enabled, resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_access.go b/vendor/github.com/google/go-github/v68/github/repos_actions_access.go new file mode 100644 index 00000000..2da1f01c --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_access.go @@ -0,0 +1,59 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryActionsAccessLevel represents the repository actions access level. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-the-level-of-access-for-workflows-outside-of-the-repository +type RepositoryActionsAccessLevel struct { + // AccessLevel specifies the level of access that workflows outside of the repository have + // to actions and reusable workflows within the repository. + // Possible values are: "none", "organization" "enterprise". + AccessLevel *string `json:"access_level,omitempty"` +} + +// GetActionsAccessLevel gets the level of access that workflows outside of the repository have +// to actions and reusable workflows in the repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-the-level-of-access-for-workflows-outside-of-the-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/access +func (s *RepositoriesService) GetActionsAccessLevel(ctx context.Context, owner, repo string) (*RepositoryActionsAccessLevel, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/access", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + raal := new(RepositoryActionsAccessLevel) + resp, err := s.client.Do(ctx, req, raal) + if err != nil { + return nil, resp, err + } + + return raal, resp, nil +} + +// EditActionsAccessLevel sets the level of access that workflows outside of the repository have +// to actions and reusable workflows in the repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-the-level-of-access-for-workflows-outside-of-the-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/access +func (s *RepositoriesService) EditActionsAccessLevel(ctx context.Context, owner, repo string, repositoryActionsAccessLevel RepositoryActionsAccessLevel) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/access", owner, repo) + req, err := s.client.NewRequest("PUT", u, repositoryActionsAccessLevel) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go b/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go new file mode 100644 index 00000000..e9ebff1d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go @@ -0,0 +1,53 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetActionsAllowed gets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/selected-actions +func (s *RepositoriesService) GetActionsAllowed(ctx context.Context, org, repo string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/selected-actions +func (s *RepositoriesService) EditActionsAllowed(ctx context.Context, org, repo string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go b/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go new file mode 100644 index 00000000..9abd32a7 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go @@ -0,0 +1,118 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissionsRepository represents a policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type ActionsPermissionsRepository struct { + Enabled *bool `json:"enabled,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissionsRepository) String() string { + return Stringify(a) +} + +// DefaultWorkflowPermissionRepository represents the default permissions for GitHub Actions workflows for a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions +type DefaultWorkflowPermissionRepository struct { + DefaultWorkflowPermissions *string `json:"default_workflow_permissions,omitempty"` + CanApprovePullRequestReviews *bool `json:"can_approve_pull_request_reviews,omitempty"` +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-github-actions-permissions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions +func (s *RepositoriesService) GetActionsPermissions(ctx context.Context, owner, repo string) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-github-actions-permissions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions +func (s *RepositoriesService) EditActionsPermissions(ctx context.Context, owner, repo string, actionsPermissionsRepository ActionsPermissionsRepository) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + req, err := s.client.NewRequest("PUT", u, actionsPermissionsRepository) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// GetDefaultWorkflowPermissions gets the GitHub Actions default workflow permissions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#get-default-workflow-permissions-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/actions/permissions/workflow +func (s *RepositoriesService) GetDefaultWorkflowPermissions(ctx context.Context, owner, repo string) (*DefaultWorkflowPermissionRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/workflow", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(DefaultWorkflowPermissionRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditDefaultWorkflowPermissions sets the GitHub Actions default workflow permissions in a repository. +// +// GitHub API docs: https://docs.github.com/rest/actions/permissions#set-default-workflow-permissions-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/actions/permissions/workflow +func (s *RepositoriesService) EditDefaultWorkflowPermissions(ctx context.Context, owner, repo string, permissions DefaultWorkflowPermissionRepository) (*DefaultWorkflowPermissionRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/workflow", owner, repo) + req, err := s.client.NewRequest("PUT", u, permissions) + if err != nil { + return nil, nil, err + } + + p := new(DefaultWorkflowPermissionRepository) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_attestations.go b/vendor/github.com/google/go-github/v68/github/repos_attestations.go new file mode 100644 index 00000000..2e542550 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_attestations.go @@ -0,0 +1,39 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-attestations +// +//meta:operation GET /repos/{owner}/{repo}/attestations/{subject_digest} +func (s *RepositoriesService) ListAttestations(ctx context.Context, owner, repo, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("repos/%v/%v/attestations/%v", owner, repo, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + resp, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, resp, err + } + + return attestations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_autolinks.go b/vendor/github.com/google/go-github/v68/github/repos_autolinks.go new file mode 100644 index 00000000..6c209b2d --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_autolinks.go @@ -0,0 +1,112 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AutolinkOptions specifies parameters for RepositoriesService.AddAutolink method. +type AutolinkOptions struct { + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` +} + +// Autolink represents autolinks to external resources like JIRA issues and Zendesk tickets. +type Autolink struct { + ID *int64 `json:"id,omitempty"` + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` +} + +// ListAutolinks returns a list of autolinks configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#get-all-autolinks-of-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/autolinks +func (s *RepositoriesService) ListAutolinks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolinks []*Autolink + resp, err := s.client.Do(ctx, req, &autolinks) + if err != nil { + return nil, resp, err + } + + return autolinks, resp, nil +} + +// AddAutolink creates an autolink reference for a repository. +// Users with admin access to the repository can create an autolink. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#create-an-autolink-reference-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/autolinks +func (s *RepositoriesService) AddAutolink(ctx context.Context, owner, repo string, opts *AutolinkOptions) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + al := new(Autolink) + resp, err := s.client.Do(ctx, req, al) + if err != nil { + return nil, resp, err + } + return al, resp, nil +} + +// GetAutolink returns a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/autolinks/{autolink_id} +func (s *RepositoriesService) GetAutolink(ctx context.Context, owner, repo string, id int64) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolink *Autolink + resp, err := s.client.Do(ctx, req, &autolink) + if err != nil { + return nil, resp, err + } + + return autolink, resp, nil +} + +// DeleteAutolink deletes a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/rest/repos/autolinks#delete-an-autolink-reference-from-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/autolinks/{autolink_id} +func (s *RepositoriesService) DeleteAutolink(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_codeowners.go b/vendor/github.com/google/go-github/v68/github/repos_codeowners.go new file mode 100644 index 00000000..93eeae09 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_codeowners.go @@ -0,0 +1,61 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetCodeownersErrorsOptions specifies the optional parameters to the +// RepositoriesService.GetCodeownersErrors method. +type GetCodeownersErrorsOptions struct { + // A branch, tag or commit name used to determine which version of the CODEOWNERS file to use. + // Default: the repository's default branch (e.g. main). + Ref string `url:"ref,omitempty"` +} + +// CodeownersErrors represents a list of syntax errors detected in the CODEOWNERS file. +type CodeownersErrors struct { + Errors []*CodeownersError `json:"errors"` +} + +// CodeownersError represents a syntax error detected in the CODEOWNERS file. +type CodeownersError struct { + Line int `json:"line"` + Column int `json:"column"` + Kind string `json:"kind"` + Source string `json:"source"` + Suggestion *string `json:"suggestion,omitempty"` + Message string `json:"message"` + Path string `json:"path"` +} + +// GetCodeownersErrors lists any syntax errors that are detected in the CODEOWNERS file. +// +// GitHub API docs: https://docs.github.com/rest/repos/repos#list-codeowners-errors +// +//meta:operation GET /repos/{owner}/{repo}/codeowners/errors +func (s *RepositoriesService) GetCodeownersErrors(ctx context.Context, owner, repo string, opts *GetCodeownersErrorsOptions) (*CodeownersErrors, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/codeowners/errors", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + codeownersErrors := &CodeownersErrors{} + resp, err := s.client.Do(ctx, req, codeownersErrors) + if err != nil { + return nil, resp, err + } + + return codeownersErrors, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_collaborators.go b/vendor/github.com/google/go-github/v68/github/repos_collaborators.go similarity index 62% rename from vendor/github.com/google/go-github/github/repos_collaborators.go rename to vendor/github.com/google/go-github/v68/github/repos_collaborators.go index 61ee9d39..d6c98535 100644 --- a/vendor/github.com/google/go-github/github/repos_collaborators.go +++ b/vendor/github.com/google/go-github/v68/github/repos_collaborators.go @@ -23,15 +23,37 @@ type ListCollaboratorsOptions struct { // Default value is "all". Affiliation string `url:"affiliation,omitempty"` + // Permission specifies how collaborators should be filtered by the permissions they have on the repository. + // Possible values are: + // "pull", "triage", "push", "maintain", "admin" + // + // If not specified, all collaborators will be returned. + Permission string `url:"permission,omitempty"` + ListOptions } +// CollaboratorInvitation represents an invitation created when adding a collaborator. +// GitHub API docs: https://docs.github.com/rest/repos/collaborators/#response-when-a-new-invitation-is-created +type CollaboratorInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + // ListCollaborators lists the GitHub users that have access to the repository. // -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators -func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opt *ListCollaboratorsOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#list-repository-collaborators +// +//meta:operation GET /repos/{owner}/{repo}/collaborators +func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opts *ListCollaboratorsOptions) ([]*User, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -41,8 +63,6 @@ func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo return nil, nil, err } - req.Header.Set("Accept", mediaTypeNestedTeamsPreview) - var users []*User resp, err := s.client.Do(ctx, req, &users) if err != nil { @@ -57,7 +77,9 @@ func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo // Note: This will return false if the user is not a collaborator OR the user // is not a GitHub user. // -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#check-if-a-user-is-a-repository-collaborator +// +//meta:operation GET /repos/{owner}/{repo}/collaborators/{username} func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) req, err := s.client.NewRequest("GET", u, nil) @@ -77,10 +99,15 @@ type RepositoryPermissionLevel struct { Permission *string `json:"permission,omitempty"` User *User `json:"user,omitempty"` + + RoleName *string `json:"role_name,omitempty"` } // GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level +// +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#get-repository-permissions-for-a-user +// +//meta:operation GET /repos/{owner}/{repo}/collaborators/{username}/permission func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) req, err := s.client.NewRequest("GET", u, nil) @@ -93,6 +120,7 @@ func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, rep if err != nil { return nil, resp, err } + return rpl, resp, nil } @@ -104,6 +132,8 @@ type RepositoryAddCollaboratorOptions struct { // pull - team members can pull, but not push to or administer this repository // push - team members can pull and push, but not administer this repository // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. // // Default value is "push". This option is only valid for organization-owned repositories. Permission string `json:"permission,omitempty"` @@ -112,29 +142,37 @@ type RepositoryAddCollaboratorOptions struct { // AddCollaborator sends an invitation to the specified GitHub user // to become a collaborator to the given repo. // -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator -func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#add-a-repository-collaborator +// +//meta:operation PUT /repos/{owner}/{repo}/collaborators/{username} +func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opts *RepositoryAddCollaboratorOptions) (*CollaboratorInvitation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) - req, err := s.client.NewRequest("PUT", u, opt) + req, err := s.client.NewRequest("PUT", u, opts) if err != nil { - return nil, err + return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + acr := new(CollaboratorInvitation) + resp, err := s.client.Do(ctx, req, acr) + if err != nil { + return nil, resp, err + } - return s.client.Do(ctx, req, nil) + return acr, resp, nil } // RemoveCollaborator removes the specified GitHub user as collaborator from the given repo. // Note: Does not return error if a valid user that is not a collaborator is removed. // -// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator +// GitHub API docs: https://docs.github.com/rest/collaborators/collaborators#remove-a-repository-collaborator +// +//meta:operation DELETE /repos/{owner}/{repo}/collaborators/{username} func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err } + return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/github/repos_comments.go b/vendor/github.com/google/go-github/v68/github/repos_comments.go similarity index 75% rename from vendor/github.com/google/go-github/github/repos_comments.go rename to vendor/github.com/google/go-github/v68/github/repos_comments.go index fa2377d4..766a614c 100644 --- a/vendor/github.com/google/go-github/github/repos_comments.go +++ b/vendor/github.com/google/go-github/v68/github/repos_comments.go @@ -8,7 +8,6 @@ package github import ( "context" "fmt" - "time" ) // RepositoryComment represents a comment for a commit, file, or line in a repository. @@ -16,11 +15,12 @@ type RepositoryComment struct { HTMLURL *string `json:"html_url,omitempty"` URL *string `json:"url,omitempty"` ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` CommitID *string `json:"commit_id,omitempty"` User *User `json:"user,omitempty"` Reactions *Reactions `json:"reactions,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` // User-mutable fields Body *string `json:"body"` @@ -35,10 +35,12 @@ func (r RepositoryComment) String() string { // ListComments lists all the comments for the repository. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository -func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/commits/comments#list-commit-comments-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/comments +func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -62,10 +64,12 @@ func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo stri // ListCommitComments lists all the comments for a given commit SHA. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit -func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/commits/comments#list-commit-comments +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/comments +func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -90,7 +94,9 @@ func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, rep // CreateComment creates a comment for the given commit. // Note: GitHub allows for comments to be created for non-existing files and positions. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#create-a-commit-comment +// GitHub API docs: https://docs.github.com/rest/commits/comments#create-a-commit-comment +// +//meta:operation POST /repos/{owner}/{repo}/commits/{commit_sha}/comments func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) req, err := s.client.NewRequest("POST", u, comment) @@ -109,7 +115,9 @@ func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sh // GetComment gets a single comment from a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment +// GitHub API docs: https://docs.github.com/rest/commits/comments#get-a-commit-comment +// +//meta:operation GET /repos/{owner}/{repo}/comments/{comment_id} func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) @@ -131,7 +139,9 @@ func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string // UpdateComment updates the body of a single comment. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#update-a-commit-comment +// GitHub API docs: https://docs.github.com/rest/commits/comments#update-a-commit-comment +// +//meta:operation PATCH /repos/{owner}/{repo}/comments/{comment_id} func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, comment) @@ -150,7 +160,9 @@ func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo str // DeleteComment deletes a single comment from a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/comments/#delete-a-commit-comment +// GitHub API docs: https://docs.github.com/rest/commits/comments#delete-a-commit-comment +// +//meta:operation DELETE /repos/{owner}/{repo}/comments/{comment_id} func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/repos_commits.go b/vendor/github.com/google/go-github/v68/github/repos_commits.go similarity index 51% rename from vendor/github.com/google/go-github/github/repos_commits.go rename to vendor/github.com/google/go-github/v68/github/repos_commits.go index 04faa3ea..cca7430c 100644 --- a/vendor/github.com/google/go-github/github/repos_commits.go +++ b/vendor/github.com/google/go-github/v68/github/repos_commits.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "fmt" + "net/url" "time" ) @@ -16,19 +17,20 @@ import ( // Note that it's wrapping a Commit, so author/committer information is in two places, // but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". type RepositoryCommit struct { - SHA *string `json:"sha,omitempty"` - Commit *Commit `json:"commit,omitempty"` - Author *User `json:"author,omitempty"` - Committer *User `json:"committer,omitempty"` - Parents []Commit `json:"parents,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - URL *string `json:"url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` // Details about how many changes were made in this commit. Only filled in during GetCommit! Stats *CommitStats `json:"stats,omitempty"` // Details about which files, and how this commit touched. Only filled in during GetCommit! - Files []CommitFile `json:"files,omitempty"` + Files []*CommitFile `json:"files,omitempty"` } func (r RepositoryCommit) String() string { @@ -48,16 +50,17 @@ func (c CommitStats) String() string { // CommitFile represents a file modified in a commit. type CommitFile struct { - SHA *string `json:"sha,omitempty"` - Filename *string `json:"filename,omitempty"` - Additions *int `json:"additions,omitempty"` - Deletions *int `json:"deletions,omitempty"` - Changes *int `json:"changes,omitempty"` - Status *string `json:"status,omitempty"` - Patch *string `json:"patch,omitempty"` - BlobURL *string `json:"blob_url,omitempty"` - RawURL *string `json:"raw_url,omitempty"` - ContentsURL *string `json:"contents_url,omitempty"` + SHA *string `json:"sha,omitempty"` + Filename *string `json:"filename,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Changes *int `json:"changes,omitempty"` + Status *string `json:"status,omitempty"` + Patch *string `json:"patch,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + PreviousFilename *string `json:"previous_filename,omitempty"` } func (c CommitFile) String() string { @@ -76,9 +79,9 @@ type CommitsComparison struct { BehindBy *int `json:"behind_by,omitempty"` TotalCommits *int `json:"total_commits,omitempty"` - Commits []RepositoryCommit `json:"commits,omitempty"` + Commits []*RepositoryCommit `json:"commits,omitempty"` - Files []CommitFile `json:"files,omitempty"` + Files []*CommitFile `json:"files,omitempty"` HTMLURL *string `json:"html_url,omitempty"` PermalinkURL *string `json:"permalink_url,omitempty"` @@ -112,12 +115,21 @@ type CommitsListOptions struct { ListOptions } +// BranchCommit is the result of listing branches with commit SHA. +type BranchCommit struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` +} + // ListCommits lists the commits of a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/commits/#list -func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opt *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-commits +// +//meta:operation GET /repos/{owner}/{repo}/commits +func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -127,9 +139,6 @@ func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo strin return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - var commits []*RepositoryCommit resp, err := s.client.Do(ctx, req, &commits) if err != nil { @@ -141,19 +150,21 @@ func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo strin // GetCommit fetches the specified commit, including all details about it. // -// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit -// See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality -func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} +func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) (*RepositoryCommit, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - commit := new(RepositoryCommit) resp, err := s.client.Do(ctx, req, commit) if err != nil { @@ -164,20 +175,24 @@ func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha st } // GetCommitRaw fetches the specified commit in raw (diff or patch) format. -func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opt RawOptions) (string, *Response, error) { +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} +func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) { u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return "", nil, err } - switch opt.Type { + switch opts.Type { case Diff: req.Header.Set("Accept", mediaTypeV3Diff) case Patch: req.Header.Set("Accept", mediaTypeV3Patch) default: - return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) } var buf bytes.Buffer @@ -192,9 +207,11 @@ func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, re // GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is // supplied and no new commits have occurred, a 304 Unmodified response is returned. // -// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference +// GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref} func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, ref) + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, refURLEscape(ref)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -216,11 +233,19 @@ func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, re } // CompareCommits compares a range of commits with each other. -// todo: support media formats - https://github.com/google/go-github/issues/6 // -// GitHub API docs: https://developer.github.com/v3/repos/commits/#compare-two-commits -func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string) (*CommitsComparison, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head) +// GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits +// +//meta:operation GET /repos/{owner}/{repo}/compare/{basehead} +func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string, opts *ListOptions) (*CommitsComparison, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -235,3 +260,66 @@ func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo st return comp, resp, nil } + +// CompareCommitsRaw compares a range of commits with each other in raw (diff or patch) format. +// +// Both "base" and "head" must be branch names in "repo". +// To compare branches across other repositories in the same network as "repo", +// use the format ":branch". +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits +// +//meta:operation GET /repos/{owner}/{repo}/compare/{basehead} +func (s *RepositoriesService) CompareCommitsRaw(ctx context.Context, owner, repo, base, head string, opts RawOptions) (string, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD, +// or latest commit for the branch. +// +// GitHub API docs: https://docs.github.com/rest/commits/commits#list-branches-for-head-commit +// +//meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head +func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var branchCommits []*BranchCommit + resp, err := s.client.Do(ctx, req, &branchCommits) + if err != nil { + return nil, resp, err + } + + return branchCommits, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_community_health.go b/vendor/github.com/google/go-github/v68/github/repos_community_health.go similarity index 69% rename from vendor/github.com/google/go-github/github/repos_community_health.go rename to vendor/github.com/google/go-github/v68/github/repos_community_health.go index 73d1d573..54d1b414 100644 --- a/vendor/github.com/google/go-github/github/repos_community_health.go +++ b/vendor/github.com/google/go-github/v68/github/repos_community_health.go @@ -8,20 +8,22 @@ package github import ( "context" "fmt" - "time" ) // Metric represents the different fields for one file in community health files. type Metric struct { Name *string `json:"name"` Key *string `json:"key"` + SPDXID *string `json:"spdx_id"` URL *string `json:"url"` HTMLURL *string `json:"html_url"` + NodeID *string `json:"node_id"` } // CommunityHealthFiles represents the different files in the community health metrics response. type CommunityHealthFiles struct { CodeOfConduct *Metric `json:"code_of_conduct"` + CodeOfConductFile *Metric `json:"code_of_conduct_file"` Contributing *Metric `json:"contributing"` IssueTemplate *Metric `json:"issue_template"` PullRequestTemplate *Metric `json:"pull_request_template"` @@ -31,14 +33,19 @@ type CommunityHealthFiles struct { // CommunityHealthMetrics represents a response containing the community metrics of a repository. type CommunityHealthMetrics struct { - HealthPercentage *int `json:"health_percentage"` - Files *CommunityHealthFiles `json:"files"` - UpdatedAt *time.Time `json:"updated_at"` + HealthPercentage *int `json:"health_percentage"` + Description *string `json:"description"` + Documentation *string `json:"documentation"` + Files *CommunityHealthFiles `json:"files"` + UpdatedAt *Timestamp `json:"updated_at"` + ContentReportsEnabled *bool `json:"content_reports_enabled"` } // GetCommunityHealthMetrics retrieves all the community health metrics for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-metrics +// GitHub API docs: https://docs.github.com/rest/metrics/community#get-community-profile-metrics +// +//meta:operation GET /repos/{owner}/{repo}/community/profile func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -46,9 +53,6 @@ func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, own return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryCommunityHealthMetricsPreview) - metrics := &CommunityHealthMetrics{} resp, err := s.client.Do(ctx, req, metrics) if err != nil { diff --git a/vendor/github.com/google/go-github/v68/github/repos_contents.go b/vendor/github.com/google/go-github/v68/github/repos_contents.go new file mode 100644 index 00000000..3a0c266b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_contents.go @@ -0,0 +1,367 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Repository contents API methods. +// GitHub API docs: https://docs.github.com/rest/repos/contents/ + +package github + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" +) + +var ErrPathForbidden = errors.New("path must not contain '..' due to auth vulnerability issue") + +// RepositoryContent represents a file or directory in a github repository. +type RepositoryContent struct { + Type *string `json:"type,omitempty"` + // Target is only set if the type is "symlink" and the target is not a normal file. + // If Target is set, Path will be the symlink path. + Target *string `json:"target,omitempty"` + Encoding *string `json:"encoding,omitempty"` + Size *int `json:"size,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + // Content contains the actual file content, which may be encoded. + // Callers should call GetContent which will decode the content if + // necessary. + Content *string `json:"content,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + SubmoduleGitURL *string `json:"submodule_git_url,omitempty"` +} + +// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentResponse struct { + Content *RepositoryContent `json:"content,omitempty"` + Commit `json:"commit,omitempty"` +} + +// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentFileOptions struct { + Message *string `json:"message,omitempty"` + Content []byte `json:"content"` // unencoded + SHA *string `json:"sha,omitempty"` + Branch *string `json:"branch,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` +} + +// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, +// branch, or tag. +type RepositoryContentGetOptions struct { + Ref string `url:"ref,omitempty"` +} + +// String converts RepositoryContent to a string. It's primarily for testing. +func (r RepositoryContent) String() string { + return Stringify(r) +} + +// GetContent returns the content of r, decoding it if necessary. +func (r *RepositoryContent) GetContent() (string, error) { + var encoding string + if r.Encoding != nil { + encoding = *r.Encoding + } + + switch encoding { + case "base64": + if r.Content == nil { + return "", errors.New("malformed response: base64 encoding of null content") + } + c, err := base64.StdEncoding.DecodeString(*r.Content) + return string(c), err + case "": + if r.Content == nil { + return "", nil + } + return *r.Content, nil + case "none": + return "", errors.New("unsupported content encoding: none, this may occur when file size > 1 MB, if that is the case consider using DownloadContents") + default: + return "", fmt.Errorf("unsupported content encoding: %v", encoding) + } +} + +// GetReadme gets the Readme file for the repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-a-repository-readme +// +//meta:operation GET /repos/{owner}/{repo}/readme +func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opts *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + readme := new(RepositoryContent) + resp, err := s.client.Do(ctx, req, readme) + if err != nil { + return nil, resp, err + } + + return readme, resp, nil +} + +// DownloadContents returns an io.ReadCloser that reads the contents of the +// specified file. This function will work with files of any size, as opposed +// to GetContents which is limited to 1 Mb files. It is the caller's +// responsibility to close the ReadCloser. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil) + if err != nil { + return nil, resp, err + } + dlResp, err := s.client.client.Do(dlReq) + if err != nil { + return nil, &Response{Response: dlResp}, err + } + + return dlResp.Body, &Response{Response: dlResp}, nil + } + } + + return nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// DownloadContentsWithMeta is identical to DownloadContents but additionally +// returns the RepositoryContent of the requested file. This additional data +// is useful for future operations involving the requested file. For merely +// reading the content of a file, DownloadContents is perfectly adequate. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *RepositoryContent, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil) + if err != nil { + return nil, contents, resp, err + } + dlResp, err := s.client.client.Do(dlReq) + if err != nil { + return nil, contents, &Response{Response: dlResp}, err + } + + return dlResp.Body, contents, &Response{Response: dlResp}, nil + } + } + + return nil, nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// GetContents can return either the metadata and content of a single file +// (when path references a file) or the metadata of all the files and/or +// subdirectories of a directory (when path references a directory). To make it +// easy to distinguish between both result types and to mimic the API as much +// as possible, both result types will be returned but only one will contain a +// value and the other will be nil. +// +// Due to an auth vulnerability issue in the GitHub v3 API, ".." is not allowed +// to appear anywhere in the "path" or this method will return an error. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content +// +//meta:operation GET /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { + if strings.Contains(path, "..") { + return nil, nil, nil, ErrPathForbidden + } + + escapedPath := (&url.URL{Path: strings.TrimSuffix(path, "/")}).String() + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) + u, err = addOptions(u, opts) + if err != nil { + return nil, nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, nil, err + } + + var rawJSON json.RawMessage + resp, err = s.client.Do(ctx, req, &rawJSON) + if err != nil { + return nil, nil, resp, err + } + + fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) + if fileUnmarshalError == nil { + return fileContent, nil, resp, nil + } + + directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) + if directoryUnmarshalError == nil { + return nil, directoryContent, resp, nil + } + + return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) +} + +// CreateFile creates a new file in a repository at the given path and returns +// the commit and file metadata. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents +// +//meta:operation PUT /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + createResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, createResponse) + if err != nil { + return nil, resp, err + } + + return createResponse, resp, nil +} + +// UpdateFile updates a file in a repository at the given path and returns the +// commit and file metadata. Requires the blob SHA of the file being updated. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents +// +//meta:operation PUT /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + updateResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, updateResponse) + if err != nil { + return nil, resp, err + } + + return updateResponse, resp, nil +} + +// DeleteFile deletes a file from a repository and returns the commit. +// Requires the blob SHA of the file to be deleted. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#delete-a-file +// +//meta:operation DELETE /repos/{owner}/{repo}/contents/{path} +func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("DELETE", u, opts) + if err != nil { + return nil, nil, err + } + + deleteResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, deleteResponse) + if err != nil { + return nil, resp, err + } + + return deleteResponse, resp, nil +} + +// ArchiveFormat is used to define the archive type when calling GetArchiveLink. +type ArchiveFormat string + +const ( + // Tarball specifies an archive in gzipped tar format. + Tarball ArchiveFormat = "tarball" + + // Zipball specifies an archive in zip format. + Zipball ArchiveFormat = "zipball" +) + +// GetArchiveLink returns an URL to download a tarball or zipball archive for a +// repository. The archiveFormat can be specified by either the github.Tarball +// or github.Zipball constant. +// +// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-tar +// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-zip +// +//meta:operation GET /repos/{owner}/{repo}/tarball/{ref} +//meta:operation GET /repos/{owner}/{repo}/zipball/{ref} +func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat ArchiveFormat, opts *RepositoryContentGetOptions, maxRedirects int) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) + if opts != nil && opts.Ref != "" { + u += fmt.Sprintf("/%s", opts.Ref) + } + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + if err != nil { + return nil, newResponse(resp), err + } + + return parsedURL, newResponse(resp), nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go b/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go new file mode 100644 index 00000000..77ac73e4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go @@ -0,0 +1,135 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DeploymentBranchPolicy represents a single deployment branch policy for an environment. +type DeploymentBranchPolicy struct { + Name *string `json:"name,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Type *string `json:"type,omitempty"` +} + +// DeploymentBranchPolicyResponse represents the slightly different format of response that comes back when you list deployment branch policies. +type DeploymentBranchPolicyResponse struct { + TotalCount *int `json:"total_count,omitempty"` + BranchPolicies []*DeploymentBranchPolicy `json:"branch_policies,omitempty"` +} + +// DeploymentBranchPolicyRequest represents a deployment branch policy request. +type DeploymentBranchPolicyRequest struct { + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// ListDeploymentBranchPolicies lists the deployment branch policies for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#list-deployment-branch-policies +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies +func (s *RepositoriesService) ListDeploymentBranchPolicies(ctx context.Context, owner, repo, environment string) (*DeploymentBranchPolicyResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *DeploymentBranchPolicyResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// GetDeploymentBranchPolicy gets a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#get-a-deployment-branch-policy +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) GetDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// CreateDeploymentBranchPolicy creates a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#create-a-deployment-branch-policy +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies +func (s *RepositoriesService) CreateDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, request *DeploymentBranchPolicyRequest) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies", owner, repo, environment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// UpdateDeploymentBranchPolicy updates a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#update-a-deployment-branch-policy +// +//meta:operation PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) UpdateDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64, request *DeploymentBranchPolicyRequest) (*DeploymentBranchPolicy, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("PUT", u, request) + if err != nil { + return nil, nil, err + } + + var policy *DeploymentBranchPolicy + resp, err := s.client.Do(ctx, req, &policy) + if err != nil { + return nil, resp, err + } + + return policy, resp, nil +} + +// DeleteDeploymentBranchPolicy deletes a deployment branch policy for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/branch-policies#delete-a-deployment-branch-policy +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id} +func (s *RepositoriesService) DeleteDeploymentBranchPolicy(ctx context.Context, owner, repo, environment string, branchPolicyID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment-branch-policies/%v", owner, repo, environment, branchPolicyID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go b/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go new file mode 100644 index 00000000..29d49032 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go @@ -0,0 +1,148 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CustomDeploymentProtectionRuleApp represents a single deployment protection rule app for an environment. +type CustomDeploymentProtectionRuleApp struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + IntegrationURL *string `json:"integration_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// CustomDeploymentProtectionRule represents a single deployment protection rule for an environment. +type CustomDeploymentProtectionRule struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + App *CustomDeploymentProtectionRuleApp `json:"app,omitempty"` +} + +// ListDeploymentProtectionRuleResponse represents the response that comes back when you list deployment protection rules. +type ListDeploymentProtectionRuleResponse struct { + TotalCount *int `json:"total_count,omitempty"` + ProtectionRules []*CustomDeploymentProtectionRule `json:"custom_deployment_protection_rules,omitempty"` +} + +// ListCustomDeploymentRuleIntegrationsResponse represents the slightly different response that comes back when you list custom deployment rule integrations. +type ListCustomDeploymentRuleIntegrationsResponse struct { + TotalCount *int `json:"total_count,omitempty"` + AvailableIntegrations []*CustomDeploymentProtectionRuleApp `json:"available_custom_deployment_protection_rule_integrations,omitempty"` +} + +// CustomDeploymentProtectionRuleRequest represents a deployment protection rule request. +type CustomDeploymentProtectionRuleRequest struct { + IntegrationID *int64 `json:"integration_id,omitempty"` +} + +// GetAllDeploymentProtectionRules gets all the deployment protection rules for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#get-all-deployment-protection-rules-for-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules +func (s *RepositoriesService) GetAllDeploymentProtectionRules(ctx context.Context, owner, repo, environment string) (*ListDeploymentProtectionRuleResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *ListDeploymentProtectionRuleResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// CreateCustomDeploymentProtectionRule creates a custom deployment protection rule on an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#create-a-custom-deployment-protection-rule-on-an-environment +// +//meta:operation POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules +func (s *RepositoriesService) CreateCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, request *CustomDeploymentProtectionRuleRequest) (*CustomDeploymentProtectionRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules", owner, repo, environment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + protectionRule := new(CustomDeploymentProtectionRule) + resp, err := s.client.Do(ctx, req, protectionRule) + if err != nil { + return nil, resp, err + } + + return protectionRule, resp, nil +} + +// ListCustomDeploymentRuleIntegrations lists the custom deployment rule integrations for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#list-custom-deployment-rule-integrations-available-for-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps +func (s *RepositoriesService) ListCustomDeploymentRuleIntegrations(ctx context.Context, owner, repo, environment string) (*ListCustomDeploymentRuleIntegrationsResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/apps", owner, repo, environment) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *ListCustomDeploymentRuleIntegrationsResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + + return list, resp, nil +} + +// GetCustomDeploymentProtectionRule gets a custom deployment protection rule for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#get-a-custom-deployment-protection-rule +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id} +func (s *RepositoriesService) GetCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, protectionRuleID int64) (*CustomDeploymentProtectionRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/%v", owner, repo, environment, protectionRuleID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var protectionRule *CustomDeploymentProtectionRule + resp, err := s.client.Do(ctx, req, &protectionRule) + if err != nil { + return nil, resp, err + } + + return protectionRule, resp, nil +} + +// DisableCustomDeploymentProtectionRule disables a custom deployment protection rule for an environment. +// +// GitHub API docs: https://docs.github.com/rest/deployments/protection-rules#disable-a-custom-protection-rule-for-an-environment +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id} +func (s *RepositoriesService) DisableCustomDeploymentProtectionRule(ctx context.Context, owner, repo, environment string, protectionRuleID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/environments/%v/deployment_protection_rules/%v", owner, repo, environment, protectionRuleID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_deployments.go b/vendor/github.com/google/go-github/v68/github/repos_deployments.go similarity index 56% rename from vendor/github.com/google/go-github/github/repos_deployments.go rename to vendor/github.com/google/go-github/v68/github/repos_deployments.go index 794c3232..6277ac21 100644 --- a/vendor/github.com/google/go-github/github/repos_deployments.go +++ b/vendor/github.com/google/go-github/v68/github/repos_deployments.go @@ -9,9 +9,10 @@ import ( "context" "encoding/json" "fmt" + "strings" ) -// Deployment represents a deployment in a repo +// Deployment represents a deployment in a repo. type Deployment struct { URL *string `json:"url,omitempty"` ID *int64 `json:"id,omitempty"` @@ -29,17 +30,17 @@ type Deployment struct { NodeID *string `json:"node_id,omitempty"` } -// DeploymentRequest represents a deployment request +// DeploymentRequest represents a deployment request. type DeploymentRequest struct { - Ref *string `json:"ref,omitempty"` - Task *string `json:"task,omitempty"` - AutoMerge *bool `json:"auto_merge,omitempty"` - RequiredContexts *[]string `json:"required_contexts,omitempty"` - Payload *string `json:"payload,omitempty"` - Environment *string `json:"environment,omitempty"` - Description *string `json:"description,omitempty"` - TransientEnvironment *bool `json:"transient_environment,omitempty"` - ProductionEnvironment *bool `json:"production_environment,omitempty"` + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + AutoMerge *bool `json:"auto_merge,omitempty"` + RequiredContexts *[]string `json:"required_contexts,omitempty"` + Payload interface{} `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + TransientEnvironment *bool `json:"transient_environment,omitempty"` + ProductionEnvironment *bool `json:"production_environment,omitempty"` } // DeploymentsListOptions specifies the optional parameters to the @@ -62,10 +63,12 @@ type DeploymentsListOptions struct { // ListDeployments lists the deployments of a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments -func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#list-deployments +// +//meta:operation GET /repos/{owner}/{repo}/deployments +func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opts *DeploymentsListOptions) ([]*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -86,7 +89,9 @@ func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo s // GetDeployment returns a single deployment of a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#get-a-deployment +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id} func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) @@ -106,7 +111,9 @@ func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo str // CreateDeployment creates a new deployment for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#create-a-deployment +// +//meta:operation POST /repos/{owner}/{repo}/deployments func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) @@ -116,7 +123,8 @@ func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo } // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeDeploymentStatusPreview) + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(Deployment) resp, err := s.client.Do(ctx, req, d) @@ -127,38 +135,60 @@ func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo return d, resp, nil } +// DeleteDeployment deletes an existing deployment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/deployments#delete-a-deployment +// +//meta:operation DELETE /repos/{owner}/{repo}/deployments/{deployment_id} +func (s *RepositoriesService) DeleteDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + // DeploymentStatus represents the status of a // particular deployment. type DeploymentStatus struct { ID *int64 `json:"id,omitempty"` // State is the deployment state. - // Possible values are: "pending", "success", "failure", "error", "inactive". - State *string `json:"state,omitempty"` - Creator *User `json:"creator,omitempty"` - Description *string `json:"description,omitempty"` - TargetURL *string `json:"target_url,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - DeploymentURL *string `json:"deployment_url,omitempty"` - RepositoryURL *string `json:"repository_url,omitempty"` - NodeID *string `json:"node_id,omitempty"` + // Possible values are: "pending", "success", "failure", "error", + // "inactive", "in_progress", "queued". + State *string `json:"state,omitempty"` + Creator *User `json:"creator,omitempty"` + Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` + NodeID *string `json:"node_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + DeploymentURL *string `json:"deployment_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + LogURL *string `json:"log_url,omitempty"` + URL *string `json:"url,omitempty"` } -// DeploymentStatusRequest represents a deployment request +// DeploymentStatusRequest represents a deployment request. type DeploymentStatusRequest struct { State *string `json:"state,omitempty"` LogURL *string `json:"log_url,omitempty"` Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` EnvironmentURL *string `json:"environment_url,omitempty"` AutoInactive *bool `json:"auto_inactive,omitempty"` } // ListDeploymentStatuses lists the statuses of a given deployment of a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses -func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#list-deployment-statuses +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses +func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opts *ListOptions) ([]*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -168,6 +198,10 @@ func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, return nil, nil, err } + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + var statuses []*DeploymentStatus resp, err := s.client.Do(ctx, req, &statuses) if err != nil { @@ -179,7 +213,9 @@ func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, // GetDeploymentStatus returns a single deployment status of a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#get-a-deployment-status +// +//meta:operation GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id} func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) @@ -189,7 +225,8 @@ func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, re } // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeDeploymentStatusPreview) + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(DeploymentStatus) resp, err := s.client.Do(ctx, req, d) @@ -202,7 +239,9 @@ func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, re // CreateDeploymentStatus creates a new status for a deployment. // -// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status +// GitHub API docs: https://docs.github.com/rest/deployments/statuses#create-a-deployment-status +// +//meta:operation POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) { u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) @@ -212,7 +251,8 @@ func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, } // TODO: remove custom Accept headers when APIs fully launch. - req.Header.Set("Accept", mediaTypeDeploymentStatusPreview) + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) d := new(DeploymentStatus) resp, err := s.client.Do(ctx, req, d) diff --git a/vendor/github.com/google/go-github/v68/github/repos_environments.go b/vendor/github.com/google/go-github/v68/github/repos_environments.go new file mode 100644 index 00000000..d3e34fa8 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_environments.go @@ -0,0 +1,252 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +// Environment represents a single environment in a repository. +type Environment struct { + Owner *string `json:"owner,omitempty"` + Repo *string `json:"repo,omitempty"` + EnvironmentName *string `json:"environment_name,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*EnvReviewers `json:"reviewers,omitempty"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy,omitempty"` + // Return/response only values + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CanAdminsBypass *bool `json:"can_admins_bypass,omitempty"` + ProtectionRules []*ProtectionRule `json:"protection_rules,omitempty"` +} + +// EnvReviewers represents a single environment reviewer entry. +type EnvReviewers struct { + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` +} + +// BranchPolicy represents the options for whether a branch deployment policy is applied to this environment. +type BranchPolicy struct { + ProtectedBranches *bool `json:"protected_branches,omitempty"` + CustomBranchPolicies *bool `json:"custom_branch_policies,omitempty"` +} + +// EnvResponse represents the slightly different format of response that comes back when you list an environment. +type EnvResponse struct { + TotalCount *int `json:"total_count,omitempty"` + Environments []*Environment `json:"environments,omitempty"` +} + +// ProtectionRule represents a single protection rule applied to the environment. +type ProtectionRule struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + PreventSelfReview *bool `json:"prevent_self_review,omitempty"` + Type *string `json:"type,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` +} + +// RequiredReviewer represents a required reviewer. +type RequiredReviewer struct { + Type *string `json:"type,omitempty"` + Reviewer interface{} `json:"reviewer,omitempty"` +} + +// EnvironmentListOptions specifies the optional parameters to the +// RepositoriesService.ListEnvironments method. +type EnvironmentListOptions struct { + ListOptions +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that RequiredReviewer can have either a User or Team type reviewer field. +func (r *RequiredReviewer) UnmarshalJSON(data []byte) error { + type aliasReviewer RequiredReviewer + var reviewer aliasReviewer + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + + r.Type = reviewer.Type + + switch *reviewer.Type { + case "User": + reviewer.Reviewer = &User{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + case "Team": + reviewer.Reviewer = &Team{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + default: + r.Type = nil + r.Reviewer = nil + return fmt.Errorf("reviewer.Type is %T, not a string of 'User' or 'Team', unable to unmarshal", reviewer.Type) + } + + return nil +} + +// ListEnvironments lists all environments for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#list-environments +// +//meta:operation GET /repos/{owner}/{repo}/environments +func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *EnvironmentListOptions) (*EnvResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *EnvResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + return list, resp, nil +} + +// GetEnvironment get a single environment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#get-an-environment +// +//meta:operation GET /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) GetEnvironment(ctx context.Context, owner, repo, name string) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var env *Environment + resp, err := s.client.Do(ctx, req, &env) + if err != nil { + return nil, resp, err + } + return env, resp, nil +} + +// MarshalJSON implements the json.Marshaler interface. +// As the only way to clear a WaitTimer is to set it to 0, a missing WaitTimer object should default to 0, not null. +// As the default value for CanAdminsBypass is true, a nil value here marshals to true. +func (c *CreateUpdateEnvironment) MarshalJSON() ([]byte, error) { + type Alias CreateUpdateEnvironment + if c.WaitTimer == nil { + c.WaitTimer = Ptr(0) + } + if c.CanAdminsBypass == nil { + c.CanAdminsBypass = Ptr(true) + } + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(c), + }) +} + +// CreateUpdateEnvironment represents the fields required for the create/update operation +// following the Create/Update release example. +// See https://github.com/google/go-github/issues/992 for more information. +// Removed omitempty here as the API expects null values for reviewers and deployment_branch_policy to clear them. +type CreateUpdateEnvironment struct { + WaitTimer *int `json:"wait_timer"` + Reviewers []*EnvReviewers `json:"reviewers"` + CanAdminsBypass *bool `json:"can_admins_bypass"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"` + PreventSelfReview *bool `json:"prevent_self_review,omitempty"` +} + +// createUpdateEnvironmentNoEnterprise represents the fields accepted for Pro/Teams private repos. +// Ref: https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment +// See https://github.com/google/go-github/issues/2602 for more information. +type createUpdateEnvironmentNoEnterprise struct { + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"` +} + +// CreateUpdateEnvironment create or update a new environment for a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#create-or-update-an-environment +// +//meta:operation PUT /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) CreateUpdateEnvironment(ctx context.Context, owner, repo, name string, environment *CreateUpdateEnvironment) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("PUT", u, environment) + if err != nil { + return nil, nil, err + } + + e := new(Environment) + resp, err := s.client.Do(ctx, req, e) + if err != nil { + // The API returns 422 when the pricing plan doesn't support all the fields sent. + // This path will be executed for Pro/Teams private repos. + // For public repos, regardless of the pricing plan, all fields supported. + // For Free plan private repos the returned error code is 404. + // We are checking that the user didn't try to send a value for unsupported fields, + // and return an error if they did. + if resp != nil && resp.StatusCode == http.StatusUnprocessableEntity && environment != nil && len(environment.Reviewers) == 0 && environment.GetWaitTimer() == 0 { + return s.createNewEnvNoEnterprise(ctx, u, environment) + } + return nil, resp, err + } + return e, resp, nil +} + +// createNewEnvNoEnterprise is an internal function for cases where the original call returned 422. +// Currently only the `deployment_branch_policy` parameter is supported for Pro/Team private repos. +func (s *RepositoriesService) createNewEnvNoEnterprise(ctx context.Context, u string, environment *CreateUpdateEnvironment) (*Environment, *Response, error) { + req, err := s.client.NewRequest("PUT", u, &createUpdateEnvironmentNoEnterprise{ + DeploymentBranchPolicy: environment.DeploymentBranchPolicy, + }) + if err != nil { + return nil, nil, err + } + + e := new(Environment) + resp, err := s.client.Do(ctx, req, e) + if err != nil { + return nil, resp, err + } + return e, resp, nil +} + +// DeleteEnvironment delete an environment from a repository. +// +// GitHub API docs: https://docs.github.com/rest/deployments/environments#delete-an-environment +// +//meta:operation DELETE /repos/{owner}/{repo}/environments/{environment_name} +func (s *RepositoriesService) DeleteEnvironment(ctx context.Context, owner, repo, name string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_forks.go b/vendor/github.com/google/go-github/v68/github/repos_forks.go similarity index 69% rename from vendor/github.com/google/go-github/github/repos_forks.go rename to vendor/github.com/google/go-github/v68/github/repos_forks.go index d0bff544..60fb49da 100644 --- a/vendor/github.com/google/go-github/github/repos_forks.go +++ b/vendor/github.com/google/go-github/v68/github/repos_forks.go @@ -7,6 +7,7 @@ package github import ( "context" + "encoding/json" "fmt" ) @@ -22,10 +23,12 @@ type RepositoryListForksOptions struct { // ListForks lists the forks of the specified repository. // -// GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks -func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/repos/forks#list-forks +// +//meta:operation GET /repos/{owner}/{repo}/forks +func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opts *RepositoryListForksOptions) ([]*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -51,7 +54,9 @@ func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, // RepositoriesService.CreateFork method. type RepositoryCreateForkOptions struct { // The organization to fork the repository into. - Organization string `url:"organization,omitempty"` + Organization string `json:"organization,omitempty"` + Name string `json:"name,omitempty"` + DefaultBranchOnly bool `json:"default_branch_only,omitempty"` } // CreateFork creates a fork of the specified repository. @@ -63,25 +68,28 @@ type RepositoryCreateForkOptions struct { // A follow up request, after a delay of a second or so, should result // in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork -func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/repos/forks#create-a-fork +// +//meta:operation POST /repos/{owner}/{repo}/forks +func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opts *RepositoryCreateForkOptions) (*Repository, *Response, error) { u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) - u, err := addOptions(u, opt) - if err != nil { - return nil, nil, err - } - req, err := s.client.NewRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, opts) if err != nil { return nil, nil, err } fork := new(Repository) resp, err := s.client.Do(ctx, req, fork) - if _, ok := err.(*AcceptedError); ok { - return fork, resp, err - } if err != nil { + // Persist AcceptedError's metadata to the Repository object. + if aerr, ok := err.(*AcceptedError); ok { + if err := json.Unmarshal(aerr.Raw, fork); err != nil { + return fork, resp, err + } + + return fork, resp, err + } return nil, resp, err } diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks.go b/vendor/github.com/google/go-github/v68/github/repos_hooks.go new file mode 100644 index 00000000..d221db21 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks.go @@ -0,0 +1,271 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" +) + +// WebHookPayload represents the data that is received from GitHub when a push +// event hook is triggered. The format of these payloads pre-date most of the +// GitHub v3 API, so there are lots of minor incompatibilities with the types +// defined in the rest of the API. Therefore, several types are duplicated +// here to account for these differences. +// +// GitHub API docs: https://help.github.com/articles/post-receive-hooks +// +// Deprecated: Please use PushEvent instead. +type WebHookPayload = PushEvent + +// WebHookCommit represents the commit variant we receive from GitHub in a +// WebHookPayload. +// +// Deprecated: Please use HeadCommit instead. +type WebHookCommit = HeadCommit + +// WebHookAuthor represents the author or committer of a commit, as specified +// in a WebHookCommit. The commit author may not correspond to a GitHub User. +// +// Deprecated: Please use CommitAuthor instead. +// NOTE Breaking API change: the `Username` field is now called `Login`. +type WebHookAuthor = CommitAuthor + +// Hook represents a GitHub (web and service) hook for a repository. +type Hook struct { + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + Type *string `json:"type,omitempty"` + Name *string `json:"name,omitempty"` + TestURL *string `json:"test_url,omitempty"` + PingURL *string `json:"ping_url,omitempty"` + LastResponse map[string]interface{} `json:"last_response,omitempty"` + + // Only the following fields are used when creating a hook. + // Config is required. + Config *HookConfig `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +func (h Hook) String() string { + return Stringify(h) +} + +// createHookRequest is a subset of Hook and is used internally +// by CreateHook to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1015 for more +// information. +type createHookRequest struct { + // Config is required. + Name string `json:"name"` + Config *HookConfig `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +// CreateHook creates a Hook for the specified repository. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#create-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks +func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ListHooks lists all Hooks for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#list-repository-webhooks +// +//meta:operation GET /repos/{owner}/{repo}/hooks +func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#update-a-repository-webhook +// +//meta:operation PATCH /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#delete-a-repository-webhook +// +//meta:operation DELETE /repos/{owner}/{repo}/hooks/{hook_id} +func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#ping-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/pings +func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// TestHook triggers a test Hook by github. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#test-the-push-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/tests +func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// Subscribe lets servers register to receive updates when a topic is updated. +// +// GitHub API docs: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub +// +//meta:operation POST /hub +func (s *RepositoriesService) Subscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { + req, err := s.createWebSubRequest("subscribe", owner, repo, event, callback, secret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unsubscribe lets servers unregister to no longer receive updates when a topic is updated. +// +// GitHub API docs: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub +// +//meta:operation POST /hub +func (s *RepositoriesService) Unsubscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { + req, err := s.createWebSubRequest("unsubscribe", owner, repo, event, callback, secret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// createWebSubRequest returns a subscribe/unsubscribe request that implements +// the WebSub (formerly PubSubHubbub) protocol. +// +// See: https://www.w3.org/TR/websub/#subscriber-sends-subscription-request +func (s *RepositoriesService) createWebSubRequest(hubMode, owner, repo, event, callback string, secret []byte) (*http.Request, error) { + topic := fmt.Sprintf( + "https://github.com/%s/%s/events/%s", + owner, + repo, + event, + ) + form := url.Values{} + form.Add("hub.mode", hubMode) + form.Add("hub.topic", topic) + form.Add("hub.callback", callback) + if secret != nil { + form.Add("hub.secret", string(secret)) + } + body := strings.NewReader(form.Encode()) + + req, err := s.client.NewFormRequest("hub", body) + if err != nil { + return nil, err + } + + return req, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go b/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go new file mode 100644 index 00000000..9560bd7a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go @@ -0,0 +1,68 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// HookConfig describes metadata about a webhook configuration. +type HookConfig struct { + // The media type used to serialize the payloads + // Possible values are `json` and `form`, the field is not specified the default is `form` + ContentType *string `json:"content_type,omitempty"` + // The possible values are 0 and 1. + // Setting it to 1 will allow skip certificate verification for the host, + // potentially exposing to MitM attacks: https://en.wikipedia.org/wiki/Man-in-the-middle_attack + InsecureSSL *string `json:"insecure_ssl,omitempty"` + URL *string `json:"url,omitempty"` + + // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests. + Secret *string `json:"secret,omitempty"` +} + +// GetHookConfiguration returns the configuration for the specified repository webhook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-webhook-configuration-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/config +func (s *RepositoriesService) GetHookConfiguration(ctx context.Context, owner, repo string, id int64) (*HookConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/config", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// EditHookConfiguration updates the configuration for the specified repository webhook. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#update-a-webhook-configuration-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config +func (s *RepositoriesService) EditHookConfiguration(ctx context.Context, owner, repo string, id int64, config *HookConfig) (*HookConfig, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/config", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go b/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go new file mode 100644 index 00000000..c8029f62 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go @@ -0,0 +1,142 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// HookDelivery represents the data that is received from GitHub's Webhook Delivery API +// +// GitHub API docs: +// - https://docs.github.com/rest/webhooks/repo-deliveries#list-deliveries-for-a-repository-webhook +// - https://docs.github.com/rest/webhooks/repo-deliveries#get-a-delivery-for-a-repository-webhook +type HookDelivery struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + DeliveredAt *Timestamp `json:"delivered_at,omitempty"` + Redelivery *bool `json:"redelivery,omitempty"` + Duration *float64 `json:"duration,omitempty"` + Status *string `json:"status,omitempty"` + StatusCode *int `json:"status_code,omitempty"` + Event *string `json:"event,omitempty"` + Action *string `json:"action,omitempty"` + InstallationID *int64 `json:"installation_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + + // Request is populated by GetHookDelivery. + Request *HookRequest `json:"request,omitempty"` + // Response is populated by GetHookDelivery. + Response *HookResponse `json:"response,omitempty"` +} + +func (d HookDelivery) String() string { + return Stringify(d) +} + +// HookRequest is a part of HookDelivery that contains +// the HTTP headers and the JSON payload of the webhook request. +type HookRequest struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookRequest) String() string { + return Stringify(r) +} + +// HookResponse is a part of HookDelivery that contains +// the HTTP headers and the response body served by the webhook endpoint. +type HookResponse struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookResponse) String() string { + return Stringify(r) +} + +// ListHookDeliveries lists webhook deliveries for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#list-deliveries-for-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries +func (s *RepositoriesService) ListHookDeliveries(ctx context.Context, owner, repo string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#get-a-delivery-for-a-repository-webhook +// +//meta:operation GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id} +func (s *RepositoriesService) GetHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/webhooks#redeliver-a-delivery-for-a-repository-webhook +// +//meta:operation POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts +func (s *RepositoriesService) RedeliverHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v/attempts", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ParseRequestPayload parses the request payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (d *HookDelivery) ParseRequestPayload() (interface{}, error) { + eType, ok := messageToTypeName[d.GetEvent()] + if !ok { + return nil, fmt.Errorf("unsupported event type %q", d.GetEvent()) + } + + e := &Event{Type: &eType, RawPayload: d.Request.RawPayload} + return e.ParsePayload() +} diff --git a/vendor/github.com/google/go-github/github/repos_invitations.go b/vendor/github.com/google/go-github/v68/github/repos_invitations.go similarity index 75% rename from vendor/github.com/google/go-github/github/repos_invitations.go rename to vendor/github.com/google/go-github/v68/github/repos_invitations.go index 34bf3830..98fe01d1 100644 --- a/vendor/github.com/google/go-github/github/repos_invitations.go +++ b/vendor/github.com/google/go-github/v68/github/repos_invitations.go @@ -23,14 +23,17 @@ type RepositoryInvitation struct { CreatedAt *Timestamp `json:"created_at,omitempty"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` + Expired *bool `json:"expired,omitempty"` } // ListInvitations lists all currently-open repository invitations. // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository -func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#list-repository-invitations +// +//meta:operation GET /repos/{owner}/{repo}/invitations +func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -40,9 +43,6 @@ func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo s return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - invites := []*RepositoryInvitation{} resp, err := s.client.Do(ctx, req, &invites) if err != nil { @@ -54,7 +54,9 @@ func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo s // DeleteInvitation deletes a repository invitation. // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#delete-a-repository-invitation +// +//meta:operation DELETE /repos/{owner}/{repo}/invitations/{invitation_id} func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) req, err := s.client.NewRequest("DELETE", u, nil) @@ -62,9 +64,6 @@ func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - return s.client.Do(ctx, req, nil) } @@ -74,7 +73,9 @@ func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo // permissions represents the permissions that the associated user will have // on the repository. Possible values are: "read", "write", "admin". // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#update-a-repository-invitation +// +//meta:operation PATCH /repos/{owner}/{repo}/invitations/{invitation_id} func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) { opts := &struct { Permissions string `json:"permissions"` @@ -85,9 +86,6 @@ func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - invite := &RepositoryInvitation{} resp, err := s.client.Do(ctx, req, invite) if err != nil { diff --git a/vendor/github.com/google/go-github/github/repos_keys.go b/vendor/github.com/google/go-github/v68/github/repos_keys.go similarity index 68% rename from vendor/github.com/google/go-github/github/repos_keys.go rename to vendor/github.com/google/go-github/v68/github/repos_keys.go index b484f844..cc86f8bb 100644 --- a/vendor/github.com/google/go-github/github/repos_keys.go +++ b/vendor/github.com/google/go-github/v68/github/repos_keys.go @@ -14,10 +14,12 @@ import ( // ListKeys lists the deploy keys for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/keys/#list -func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#list-deploy-keys +// +//meta:operation GET /repos/{owner}/{repo}/keys +func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Key, *Response, error) { u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -38,7 +40,9 @@ func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo s // GetKey fetches a single deploy key. // -// GitHub API docs: https://developer.github.com/v3/repos/keys/#get +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#get-a-deploy-key +// +//meta:operation GET /repos/{owner}/{repo}/keys/{key_id} func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) { u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) @@ -58,7 +62,9 @@ func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo str // CreateKey adds a deploy key for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/keys/#create +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#create-a-deploy-key +// +//meta:operation POST /repos/{owner}/{repo}/keys func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) { u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) @@ -76,29 +82,11 @@ func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo return k, resp, nil } -// EditKey edits a deploy key. -// -// GitHub API docs: https://developer.github.com/v3/repos/keys/#edit -func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo string, id int64, key *Key) (*Key, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) - - req, err := s.client.NewRequest("PATCH", u, key) - if err != nil { - return nil, nil, err - } - - k := new(Key) - resp, err := s.client.Do(ctx, req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil -} - // DeleteKey deletes a deploy key. // -// GitHub API docs: https://developer.github.com/v3/repos/keys/#delete +// GitHub API docs: https://docs.github.com/rest/deploy-keys/deploy-keys#delete-a-deploy-key +// +//meta:operation DELETE /repos/{owner}/{repo}/keys/{key_id} func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) diff --git a/vendor/github.com/google/go-github/v68/github/repos_lfs.go b/vendor/github.com/google/go-github/v68/github/repos_lfs.go new file mode 100644 index 00000000..f0153c08 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_lfs.go @@ -0,0 +1,53 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// EnableLFS turns the LFS (Large File Storage) feature ON for the selected repo. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/repos/lfs#enable-git-lfs-for-a-repository +// +//meta:operation PUT /repos/{owner}/{repo}/lfs +func (s *RepositoriesService) EnableLFS(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/lfs", owner, repo) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisableLFS turns the LFS (Large File Storage) feature OFF for the selected repo. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/repos/lfs#disable-git-lfs-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/lfs +func (s *RepositoriesService) DisableLFS(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/lfs", owner, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_merging.go b/vendor/github.com/google/go-github/v68/github/repos_merging.go new file mode 100644 index 00000000..b26e5da1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_merging.go @@ -0,0 +1,76 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryMergeRequest represents a request to merge a branch in a +// repository. +type RepositoryMergeRequest struct { + Base *string `json:"base,omitempty"` + Head *string `json:"head,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// RepoMergeUpstreamRequest represents a request to sync a branch of +// a forked repository to keep it up-to-date with the upstream repository. +type RepoMergeUpstreamRequest struct { + Branch *string `json:"branch,omitempty"` +} + +// RepoMergeUpstreamResult represents the result of syncing a branch of +// a forked repository with the upstream repository. +type RepoMergeUpstreamResult struct { + Message *string `json:"message,omitempty"` + MergeType *string `json:"merge_type,omitempty"` + BaseBranch *string `json:"base_branch,omitempty"` +} + +// Merge a branch in the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#merge-a-branch +// +//meta:operation POST /repos/{owner}/{repo}/merges +func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// MergeUpstream syncs a branch of a forked repository to keep it up-to-date +// with the upstream repository. +// +// GitHub API docs: https://docs.github.com/rest/branches/branches#sync-a-fork-branch-with-the-upstream-repository +// +//meta:operation POST /repos/{owner}/{repo}/merge-upstream +func (s *RepositoriesService) MergeUpstream(ctx context.Context, owner, repo string, request *RepoMergeUpstreamRequest) (*RepoMergeUpstreamResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merge-upstream", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + result := new(RepoMergeUpstreamResult) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_pages.go b/vendor/github.com/google/go-github/v68/github/repos_pages.go new file mode 100644 index 00000000..6b9ba76e --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_pages.go @@ -0,0 +1,324 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Pages represents a GitHub Pages site configuration. +type Pages struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + CNAME *string `json:"cname,omitempty"` + Custom404 *bool `json:"custom_404,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BuildType *string `json:"build_type,omitempty"` + Source *PagesSource `json:"source,omitempty"` + Public *bool `json:"public,omitempty"` + HTTPSCertificate *PagesHTTPSCertificate `json:"https_certificate,omitempty"` + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// PagesSource represents a GitHub page's source. +type PagesSource struct { + Branch *string `json:"branch,omitempty"` + Path *string `json:"path,omitempty"` +} + +// PagesError represents a build error for a GitHub Pages site. +type PagesError struct { + Message *string `json:"message,omitempty"` +} + +// PagesBuild represents the build information for a GitHub Pages site. +type PagesBuild struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + Error *PagesError `json:"error,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Commit *string `json:"commit,omitempty"` + Duration *int `json:"duration,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// PagesDomain represents a domain associated with a GitHub Pages site. +type PagesDomain struct { + Host *string `json:"host,omitempty"` + URI *string `json:"uri,omitempty"` + Nameservers *string `json:"nameservers,omitempty"` + DNSResolves *bool `json:"dns_resolves,omitempty"` + IsProxied *bool `json:"is_proxied,omitempty"` + IsCloudflareIP *bool `json:"is_cloudflare_ip,omitempty"` + IsFastlyIP *bool `json:"is_fastly_ip,omitempty"` + IsOldIPAddress *bool `json:"is_old_ip_address,omitempty"` + IsARecord *bool `json:"is_a_record,omitempty"` + HasCNAMERecord *bool `json:"has_cname_record,omitempty"` + HasMXRecordsPresent *bool `json:"has_mx_records_present,omitempty"` + IsValidDomain *bool `json:"is_valid_domain,omitempty"` + IsApexDomain *bool `json:"is_apex_domain,omitempty"` + ShouldBeARecord *bool `json:"should_be_a_record,omitempty"` + IsCNAMEToGithubUserDomain *bool `json:"is_cname_to_github_user_domain,omitempty"` + IsCNAMEToPagesDotGithubDotCom *bool `json:"is_cname_to_pages_dot_github_dot_com,omitempty"` + IsCNAMEToFastly *bool `json:"is_cname_to_fastly,omitempty"` + IsPointedToGithubPagesIP *bool `json:"is_pointed_to_github_pages_ip,omitempty"` + IsNonGithubPagesIPPresent *bool `json:"is_non_github_pages_ip_present,omitempty"` + IsPagesDomain *bool `json:"is_pages_domain,omitempty"` + IsServedByPages *bool `json:"is_served_by_pages,omitempty"` + IsValid *bool `json:"is_valid,omitempty"` + Reason *string `json:"reason,omitempty"` + RespondsToHTTPS *bool `json:"responds_to_https,omitempty"` + EnforcesHTTPS *bool `json:"enforces_https,omitempty"` + HTTPSError *string `json:"https_error,omitempty"` + IsHTTPSEligible *bool `json:"is_https_eligible,omitempty"` + CAAError *string `json:"caa_error,omitempty"` +} + +// PagesHealthCheckResponse represents the response given for the health check of a GitHub Pages site. +type PagesHealthCheckResponse struct { + Domain *PagesDomain `json:"domain,omitempty"` + AltDomain *PagesDomain `json:"alt_domain,omitempty"` +} + +// PagesHTTPSCertificate represents the HTTPS Certificate information for a GitHub Pages site. +type PagesHTTPSCertificate struct { + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + Domains []string `json:"domains,omitempty"` + // GitHub's API doesn't return a standard Timestamp, rather it returns a YYYY-MM-DD string. + ExpiresAt *string `json:"expires_at,omitempty"` +} + +// createPagesRequest is a subset of Pages and is used internally +// by EnablePages to pass only the known fields for the endpoint. +type createPagesRequest struct { + BuildType *string `json:"build_type,omitempty"` + Source *PagesSource `json:"source,omitempty"` +} + +// EnablePages enables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#create-a-github-pages-site +// +//meta:operation POST /repos/{owner}/{repo}/pages +func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string, pages *Pages) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + pagesReq := &createPagesRequest{ + BuildType: pages.BuildType, + Source: pages.Source, + } + + req, err := s.client.NewRequest("POST", u, pagesReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + enable := new(Pages) + resp, err := s.client.Do(ctx, req, enable) + if err != nil { + return nil, resp, err + } + + return enable, resp, nil +} + +// PagesUpdate sets up parameters needed to update a GitHub Pages site. +type PagesUpdate struct { + // CNAME represents a custom domain for the repository. + // Leaving CNAME empty will remove the custom domain. + CNAME *string `json:"cname"` + // BuildType is optional and can either be "legacy" or "workflow". + // "workflow" - You are using a github workflow to build your pages. + // "legacy" - You are deploying from a branch. + BuildType *string `json:"build_type,omitempty"` + // Source must include the branch name, and may optionally specify the subdirectory "/docs". + // Possible values for Source.Branch are usually "gh-pages", "main", and "master", + // or any other existing branch name. + // Possible values for Source.Path are: "/", and "/docs". + Source *PagesSource `json:"source,omitempty"` + // Public configures access controls for the site. + // If "true", the site will be accessible to anyone on the internet. If "false", + // the site will be accessible to anyone with read access to the repository that + // published the site. + Public *bool `json:"public,omitempty"` + // HTTPSEnforced specifies whether HTTPS should be enforced for the repository. + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// UpdatePages updates GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#update-information-about-a-github-pages-site +// +//meta:operation PUT /repos/{owner}/{repo}/pages +func (s *RepositoriesService) UpdatePages(ctx context.Context, owner, repo string, opts *PagesUpdate) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisablePages disables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#delete-a-github-pages-site +// +//meta:operation DELETE /repos/{owner}/{repo}/pages +func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetPagesInfo fetches information about a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-a-github-pages-site +// +//meta:operation GET /repos/{owner}/{repo}/pages +func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + site := new(Pages) + resp, err := s.client.Do(ctx, req, site) + if err != nil { + return nil, resp, err + } + + return site, resp, nil +} + +// ListPagesBuilds lists the builds for a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#list-github-pages-builds +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds +func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pages []*PagesBuild + resp, err := s.client.Do(ctx, req, &pages) + if err != nil { + return nil, resp, err + } + + return pages, resp, nil +} + +// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-latest-pages-build +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds/latest +func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageBuild fetches the specific build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-github-pages-build +// +//meta:operation GET /repos/{owner}/{repo}/pages/builds/{build_id} +func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#request-a-github-pages-build +// +//meta:operation POST /repos/{owner}/{repo}/pages/builds +func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageHealthCheck gets a DNS health check for the CNAME record configured for a repository's GitHub Pages. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#get-a-dns-health-check-for-github-pages +// +//meta:operation GET /repos/{owner}/{repo}/pages/health +func (s *RepositoriesService) GetPageHealthCheck(ctx context.Context, owner, repo string) (*PagesHealthCheckResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/health", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + healthCheckResponse := new(PagesHealthCheckResponse) + resp, err := s.client.Do(ctx, req, healthCheckResponse) + if err != nil { + return nil, resp, err + } + + return healthCheckResponse, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_prereceive_hooks.go b/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go similarity index 73% rename from vendor/github.com/google/go-github/github/repos_prereceive_hooks.go rename to vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go index cab09f74..e97075d0 100644 --- a/vendor/github.com/google/go-github/github/repos_prereceive_hooks.go +++ b/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go @@ -24,10 +24,12 @@ func (p PreReceiveHook) String() string { // ListPreReceiveHooks lists all pre-receive hooks for the specified repository. // -// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks -func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PreReceiveHook, *Response, error) { +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#list-pre-receive-hooks-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/pre-receive-hooks +func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -51,7 +53,9 @@ func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, re // GetPreReceiveHook returns a single specified pre-receive hook. // -// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#get-a-single-pre-receive-hook +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#get-a-pre-receive-hook-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) @@ -73,7 +77,9 @@ func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo // UpdatePreReceiveHook updates a specified pre-receive hook. // -// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#update-pre-receive-hook-enforcement +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#update-pre-receive-hook-enforcement-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("PATCH", u, hook) @@ -95,7 +101,9 @@ func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, r // DeletePreReceiveHook deletes a specified pre-receive hook. // -// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#remove-enforcement-overrides-for-a-pre-receive-hook +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/repo-pre-receive-hooks#remove-pre-receive-hook-enforcement-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/pre-receive-hooks/{pre_receive_hook_id} func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/v68/github/repos_properties.go b/vendor/github.com/google/go-github/v68/github/repos_properties.go new file mode 100644 index 00000000..5b12bc8b --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_properties.go @@ -0,0 +1,60 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllCustomPropertyValues gets all custom property values that are set for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/custom-properties#get-all-custom-property-values-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/properties/values +func (s *RepositoriesService) GetAllCustomPropertyValues(ctx context.Context, org, repo string) ([]*CustomPropertyValue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/properties/values", org, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customPropertyValues []*CustomPropertyValue + resp, err := s.client.Do(ctx, req, &customPropertyValues) + if err != nil { + return nil, resp, err + } + + return customPropertyValues, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom property values for a repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/custom-properties#create-or-update-custom-property-values-for-a-repository +// +//meta:operation PATCH /repos/{owner}/{repo}/properties/values +func (s *RepositoriesService) CreateOrUpdateCustomProperties(ctx context.Context, org, repo string, customPropertyValues []*CustomPropertyValue) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/properties/values", org, repo) + + params := struct { + Properties []*CustomPropertyValue `json:"properties"` + }{ + Properties: customPropertyValues, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_releases.go b/vendor/github.com/google/go-github/v68/github/repos_releases.go similarity index 50% rename from vendor/github.com/google/go-github/github/repos_releases.go rename to vendor/github.com/google/go-github/v68/github/repos_releases.go index c23601d1..6023f632 100644 --- a/vendor/github.com/google/go-github/github/repos_releases.go +++ b/vendor/github.com/google/go-github/v68/github/repos_releases.go @@ -19,30 +19,51 @@ import ( // RepositoryRelease represents a GitHub release in a repository. type RepositoryRelease struct { - ID *int64 `json:"id,omitempty"` - TagName *string `json:"tag_name,omitempty"` - TargetCommitish *string `json:"target_commitish,omitempty"` - Name *string `json:"name,omitempty"` - Body *string `json:"body,omitempty"` - Draft *bool `json:"draft,omitempty"` - Prerelease *bool `json:"prerelease,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - PublishedAt *Timestamp `json:"published_at,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - AssetsURL *string `json:"assets_url,omitempty"` - Assets []ReleaseAsset `json:"assets,omitempty"` - UploadURL *string `json:"upload_url,omitempty"` - ZipballURL *string `json:"zipball_url,omitempty"` - TarballURL *string `json:"tarball_url,omitempty"` - Author *User `json:"author,omitempty"` - NodeID *string `json:"node_id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + // MakeLatest can be one of: "true", "false", or "legacy". + MakeLatest *string `json:"make_latest,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` + + // The following fields are not used in EditRelease: + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + + // The following fields are not used in CreateRelease or EditRelease: + ID *int64 `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AssetsURL *string `json:"assets_url,omitempty"` + Assets []*ReleaseAsset `json:"assets,omitempty"` + UploadURL *string `json:"upload_url,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` + Author *User `json:"author,omitempty"` + NodeID *string `json:"node_id,omitempty"` } func (r RepositoryRelease) String() string { return Stringify(r) } +// RepositoryReleaseNotes represents a GitHub-generated release notes. +type RepositoryReleaseNotes struct { + Name string `json:"name"` + Body string `json:"body"` +} + +// GenerateNotesOptions represents the options to generate release notes. +type GenerateNotesOptions struct { + TagName string `json:"tag_name"` + PreviousTagName *string `json:"previous_tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` +} + // ReleaseAsset represents a GitHub release asset in a repository. type ReleaseAsset struct { ID *int64 `json:"id,omitempty"` @@ -66,10 +87,12 @@ func (r ReleaseAsset) String() string { // ListReleases lists the releases for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository -func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryRelease, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/releases/releases#list-releases +// +//meta:operation GET /repos/{owner}/{repo}/releases +func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -89,7 +112,9 @@ func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo stri // GetRelease fetches a single release. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-a-release +// +//meta:operation GET /repos/{owner}/{repo}/releases/{release_id} func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) return s.getSingleRelease(ctx, u) @@ -97,7 +122,9 @@ func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string // GetLatestRelease fetches the latest published release for the repository. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-the-latest-release +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-the-latest-release +// +//meta:operation GET /repos/{owner}/{repo}/releases/latest func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) return s.getSingleRelease(ctx, u) @@ -105,12 +132,35 @@ func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo // GetReleaseByTag fetches a release with the specified tag. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name +// GitHub API docs: https://docs.github.com/rest/releases/releases#get-a-release-by-tag-name +// +//meta:operation GET /repos/{owner}/{repo}/releases/tags/{tag} func (s *RepositoriesService) GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) return s.getSingleRelease(ctx, u) } +// GenerateReleaseNotes generates the release notes for the given tag. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#generate-release-notes-content-for-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases/generate-notes +func (s *RepositoriesService) GenerateReleaseNotes(ctx context.Context, owner, repo string, opts *GenerateNotesOptions) (*RepositoryReleaseNotes, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/generate-notes", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryReleaseNotes) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) { req, err := s.client.NewRequest("GET", url, nil) if err != nil { @@ -125,13 +175,48 @@ func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) return release, resp, nil } +// repositoryReleaseRequest is a subset of RepositoryRelease and +// is used internally by CreateRelease and EditRelease to pass +// only the known fields for these endpoints. +// +// See https://github.com/google/go-github/issues/992 for more +// information. +type repositoryReleaseRequest struct { + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + MakeLatest *string `json:"make_latest,omitempty"` + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` +} + // CreateRelease adds a new release for a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#create-a-release +// +//meta:operation POST /repos/{owner}/{repo}/releases func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) - req, err := s.client.NewRequest("POST", u, release) + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + MakeLatest: release.MakeLatest, + DiscussionCategoryName: release.DiscussionCategoryName, + GenerateReleaseNotes: release.GenerateReleaseNotes, + } + + req, err := s.client.NewRequest("POST", u, releaseReq) if err != nil { return nil, nil, err } @@ -146,11 +231,27 @@ func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo str // EditRelease edits a repository release. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/rest/releases/releases#update-a-release +// +//meta:operation PATCH /repos/{owner}/{repo}/releases/{release_id} func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) - req, err := s.client.NewRequest("PATCH", u, release) + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + MakeLatest: release.MakeLatest, + DiscussionCategoryName: release.DiscussionCategoryName, + } + + req, err := s.client.NewRequest("PATCH", u, releaseReq) if err != nil { return nil, nil, err } @@ -165,7 +266,9 @@ func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo strin // DeleteRelease delete a single release from a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release +// GitHub API docs: https://docs.github.com/rest/releases/releases#delete-a-release +// +//meta:operation DELETE /repos/{owner}/{repo}/releases/{release_id} func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) @@ -178,10 +281,12 @@ func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo str // ListReleaseAssets lists the release's assets. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release -func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*ReleaseAsset, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/releases/assets#list-release-assets +// +//meta:operation GET /repos/{owner}/{repo}/releases/{release_id}/assets +func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -201,7 +306,9 @@ func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo // GetReleaseAsset fetches a single release asset. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset +// GitHub API docs: https://docs.github.com/rest/releases/assets#get-a-release-asset +// +//meta:operation GET /repos/{owner}/{repo}/releases/assets/{asset_id} func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) @@ -225,8 +332,16 @@ func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo s // If a redirect is returned, the redirect URL will be returned as a string instead // of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset -func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64) (rc io.ReadCloser, redirectURL string, err error) { +// followRedirectsClient can be passed to download the asset from a redirected +// location. Specifying any http.Client is possible, but passing http.DefaultClient +// is recommended, except when the specified repository is private, in which case +// it's necessary to pass an http.Client that performs authenticated requests. +// If nil is passed the redirectURL will be returned instead. +// +// GitHub API docs: https://docs.github.com/rest/releases/assets#get-a-release-asset +// +//meta:operation GET /repos/{owner}/{repo}/releases/assets/{asset_id} +func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64, followRedirectsClient *http.Client) (rc io.ReadCloser, redirectURL string, err error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) req, err := s.client.NewRequest("GET", u, nil) @@ -252,20 +367,44 @@ func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, r if !strings.Contains(err.Error(), "disable redirect") { return nil, "", err } + if followRedirectsClient != nil { + rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, loc) + return rc, "", err + } return nil, loc, nil // Intentionally return no error with valid redirect URL. } if err := CheckResponse(resp); err != nil { - resp.Body.Close() + _ = resp.Body.Close() return nil, "", err } return resp.Body, "", nil } +func (s *RepositoriesService) downloadReleaseAssetFromURL(ctx context.Context, followRedirectsClient *http.Client, url string) (rc io.ReadCloser, err error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req = withContext(ctx, req) + req.Header.Set("Accept", defaultMediaType) + resp, err := followRedirectsClient.Do(req) + if err != nil { + return nil, err + } + if err := CheckResponse(resp); err != nil { + _ = resp.Body.Close() + return nil, err + } + return resp.Body, nil +} + // EditReleaseAsset edits a repository release asset. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release-asset +// GitHub API docs: https://docs.github.com/rest/releases/assets#update-a-release-asset +// +//meta:operation PATCH /repos/{owner}/{repo}/releases/assets/{asset_id} func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) @@ -284,7 +423,9 @@ func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo // DeleteReleaseAsset delete a single release asset from a repository. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release-asset +// GitHub API docs: https://docs.github.com/rest/releases/assets#delete-a-release-asset +// +//meta:operation DELETE /repos/{owner}/{repo}/releases/assets/{asset_id} func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) @@ -298,10 +439,12 @@ func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, rep // UploadReleaseAsset creates an asset by uploading a file into a release repository. // To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. // -// GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset -func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opt *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/releases/assets#upload-a-release-asset +// +//meta:operation POST /repos/{owner}/{repo}/releases/{release_id}/assets +func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opts *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -315,6 +458,10 @@ func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, rep } mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) + if opts.MediaType != "" { + mediaType = opts.MediaType + } + req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) if err != nil { return nil, nil, err diff --git a/vendor/github.com/google/go-github/v68/github/repos_rules.go b/vendor/github.com/google/go-github/v68/github/repos_rules.go new file mode 100644 index 00000000..b113553a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_rules.go @@ -0,0 +1,995 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// BypassActor represents the bypass actors from a ruleset. +type BypassActor struct { + ActorID *int64 `json:"actor_id,omitempty"` + // Possible values for ActorType are: RepositoryRole, Team, Integration, OrganizationAdmin + ActorType *string `json:"actor_type,omitempty"` + // Possible values for BypassMode are: always, pull_request + BypassMode *string `json:"bypass_mode,omitempty"` +} + +// RulesetLink represents a single link object from GitHub ruleset request _links. +type RulesetLink struct { + HRef *string `json:"href,omitempty"` +} + +// RulesetLinks represents the "_links" object in a Ruleset. +type RulesetLinks struct { + Self *RulesetLink `json:"self,omitempty"` +} + +// RulesetRefConditionParameters represents the conditions object for ref_names. +type RulesetRefConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` +} + +// RulesetRepositoryNamesConditionParameters represents the conditions object for repository_names. +type RulesetRepositoryNamesConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` + Protected *bool `json:"protected,omitempty"` +} + +// RulesetRepositoryIDsConditionParameters represents the conditions object for repository_ids. +type RulesetRepositoryIDsConditionParameters struct { + RepositoryIDs []int64 `json:"repository_ids,omitempty"` +} + +// RulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting. +type RulesetRepositoryPropertyTargetParameters struct { + Name string `json:"name"` + Values []string `json:"property_values"` + Source *string `json:"source,omitempty"` +} + +// RulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property. +type RulesetRepositoryPropertyConditionParameters struct { + Include []RulesetRepositoryPropertyTargetParameters `json:"include"` + Exclude []RulesetRepositoryPropertyTargetParameters `json:"exclude"` +} + +// RulesetConditions represents the conditions object in a ruleset. +// Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one. +type RulesetConditions struct { + RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` + RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"` + RepositoryID *RulesetRepositoryIDsConditionParameters `json:"repository_id,omitempty"` + RepositoryProperty *RulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"` +} + +// RulePatternParameters represents the rule pattern parameters. +type RulePatternParameters struct { + Name *string `json:"name,omitempty"` + // If Negate is true, the rule will fail if the pattern matches. + Negate *bool `json:"negate,omitempty"` + // Possible values for Operator are: starts_with, ends_with, contains, regex + Operator string `json:"operator"` + Pattern string `json:"pattern"` +} + +// RuleFileParameters represents a list of file paths. +type RuleFileParameters struct { + RestrictedFilePaths *[]string `json:"restricted_file_paths"` +} + +// RuleMaxFilePathLengthParameters represents the max_file_path_length rule parameters. +type RuleMaxFilePathLengthParameters struct { + MaxFilePathLength int `json:"max_file_path_length"` +} + +// RuleFileExtensionRestrictionParameters represents the file_extension_restriction rule parameters. +type RuleFileExtensionRestrictionParameters struct { + RestrictedFileExtensions []string `json:"restricted_file_extensions"` +} + +// RuleMaxFileSizeParameters represents the max_file_size rule parameters. +type RuleMaxFileSizeParameters struct { + MaxFileSize int64 `json:"max_file_size"` +} + +// UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters. +type UpdateAllowsFetchAndMergeRuleParameters struct { + UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"` +} + +// RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters. +type RequiredDeploymentEnvironmentsRuleParameters struct { + RequiredDeploymentEnvironments []string `json:"required_deployment_environments"` +} + +// PullRequestRuleParameters represents the pull_request rule parameters. +type PullRequestRuleParameters struct { + DismissStaleReviewsOnPush bool `json:"dismiss_stale_reviews_on_push"` + RequireCodeOwnerReview bool `json:"require_code_owner_review"` + RequireLastPushApproval bool `json:"require_last_push_approval"` + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"` +} + +// RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object. +type RuleRequiredStatusChecks struct { + Context string `json:"context"` + IntegrationID *int64 `json:"integration_id,omitempty"` +} + +// MergeQueueRuleParameters represents the merge_queue rule parameters. +type MergeQueueRuleParameters struct { + CheckResponseTimeoutMinutes int `json:"check_response_timeout_minutes"` + // Possible values for GroupingStrategy are: ALLGREEN, HEADGREEN + GroupingStrategy string `json:"grouping_strategy"` + MaxEntriesToBuild int `json:"max_entries_to_build"` + MaxEntriesToMerge int `json:"max_entries_to_merge"` + // Possible values for MergeMethod are: MERGE, SQUASH, REBASE + MergeMethod string `json:"merge_method"` + MinEntriesToMerge int `json:"min_entries_to_merge"` + MinEntriesToMergeWaitMinutes int `json:"min_entries_to_merge_wait_minutes"` +} + +// RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters. +type RequiredStatusChecksRuleParameters struct { + DoNotEnforceOnCreate *bool `json:"do_not_enforce_on_create,omitempty"` + RequiredStatusChecks []RuleRequiredStatusChecks `json:"required_status_checks"` + StrictRequiredStatusChecksPolicy bool `json:"strict_required_status_checks_policy"` +} + +// RuleRequiredWorkflow represents the Workflow for the RequireWorkflowsRuleParameters object. +type RuleRequiredWorkflow struct { + Path string `json:"path"` + Ref *string `json:"ref,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Sha *string `json:"sha,omitempty"` +} + +// RequiredWorkflowsRuleParameters represents the workflows rule parameters. +type RequiredWorkflowsRuleParameters struct { + DoNotEnforceOnCreate bool `json:"do_not_enforce_on_create,omitempty"` + RequiredWorkflows []*RuleRequiredWorkflow `json:"workflows"` +} + +// RuleRequiredCodeScanningTool represents a single required code-scanning tool for the RequiredCodeScanningParameters object. +type RuleRequiredCodeScanningTool struct { + AlertsThreshold string `json:"alerts_threshold"` + SecurityAlertsThreshold string `json:"security_alerts_threshold"` + Tool string `json:"tool"` +} + +// RequiredCodeScanningRuleParameters represents the code_scanning rule parameters. +type RequiredCodeScanningRuleParameters struct { + RequiredCodeScanningTools []*RuleRequiredCodeScanningTool `json:"code_scanning_tools"` +} + +// RepositoryRule represents a GitHub Rule. +type RepositoryRule struct { + Type string `json:"type"` + Parameters *json.RawMessage `json:"parameters,omitempty"` + RulesetSourceType string `json:"ruleset_source_type"` + RulesetSource string `json:"ruleset_source"` + RulesetID int64 `json:"ruleset_id"` +} + +// RepositoryRulesetEditedChanges represents the changes made to a repository ruleset. +type RepositoryRulesetEditedChanges struct { + Name *RepositoryRulesetEditedSource `json:"name,omitempty"` + Enforcement *RepositoryRulesetEditedSource `json:"enforcement,omitempty"` + Conditions *RepositoryRulesetEditedConditions `json:"conditions,omitempty"` + Rules *RepositoryRulesetEditedRules `json:"rules,omitempty"` +} + +// RepositoryRulesetEditedSource represents a source change for the ruleset. +type RepositoryRulesetEditedSource struct { + From *string `json:"from,omitempty"` +} + +// RepositoryRulesetEditedSources represents multiple source changes for the ruleset. +type RepositoryRulesetEditedSources struct { + From []string `json:"from,omitempty"` +} + +// RepositoryRulesetEditedConditions holds changes to conditions in a ruleset. +type RepositoryRulesetEditedConditions struct { + Added []*RepositoryRulesetRefCondition `json:"added,omitempty"` + Deleted []*RepositoryRulesetRefCondition `json:"deleted,omitempty"` + Updated []*RepositoryRulesetEditedUpdatedConditions `json:"updated,omitempty"` +} + +// RepositoryRulesetEditedRules holds changes to rules in a ruleset. +type RepositoryRulesetEditedRules struct { + Added []*RepositoryRulesetRule `json:"added,omitempty"` + Deleted []*RepositoryRulesetRule `json:"deleted,omitempty"` + Updated []*RepositoryRulesetUpdatedRules `json:"updated,omitempty"` +} + +// RepositoryRulesetRefCondition represents a reference condition for the ruleset. +type RepositoryRulesetRefCondition struct { + RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` +} + +// RepositoryRulesetEditedUpdatedConditions holds updates to conditions in a ruleset. +type RepositoryRulesetEditedUpdatedConditions struct { + Condition *RepositoryRulesetRefCondition `json:"condition,omitempty"` + Changes *RepositoryRulesetUpdatedConditionsEdited `json:"changes,omitempty"` +} + +// RepositoryRulesetUpdatedConditionsEdited holds the edited updates to conditions in a ruleset. +type RepositoryRulesetUpdatedConditionsEdited struct { + ConditionType *RepositoryRulesetEditedSource `json:"condition_type,omitempty"` + Target *RepositoryRulesetEditedSource `json:"target,omitempty"` + Include *RepositoryRulesetEditedSources `json:"include,omitempty"` + Exclude *RepositoryRulesetEditedSources `json:"exclude,omitempty"` +} + +// RepositoryRulesetUpdatedRules holds updates to rules in a ruleset. +type RepositoryRulesetUpdatedRules struct { + Rule *RepositoryRulesetRule `json:"rule,omitempty"` + Changes *RepositoryRulesetEditedRuleChanges `json:"changes,omitempty"` +} + +// RepositoryRulesetEditedRuleChanges holds changes made to a rule in a ruleset. +type RepositoryRulesetEditedRuleChanges struct { + Configuration *RepositoryRulesetEditedSources `json:"configuration,omitempty"` + RuleType *RepositoryRulesetEditedSources `json:"rule_type,omitempty"` + Pattern *RepositoryRulesetEditedSources `json:"pattern,omitempty"` +} + +// RepositoryRuleset represents the structure of a ruleset associated with a GitHub repository. +type RepositoryRuleset struct { + ID int64 `json:"id"` + Name string `json:"name"` + // Possible values for target: "branch", "tag", "push" + Target *string `json:"target,omitempty"` + // Possible values for source type: "Repository", "Organization" + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for enforcement: "disabled", "active", "evaluate" + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors,omitempty"` + // Possible values for current user can bypass: "always", "pull_requests_only", "never" + CurrentUserCanBypass *string `json:"current_user_can_bypass,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RepositoryRulesetLink `json:"_links,omitempty"` + Conditions json.RawMessage `json:"conditions,omitempty"` + Rules []*RepositoryRulesetRule `json:"rules,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// RepositoryRulesetRule represents individual rules which are present in a repository's ruleset. +type RepositoryRulesetRule struct { + Creation *RepositoryRulesetRuleType `json:"creation,omitempty"` + Update *RepositoryRulesetUpdateRule `json:"update,omitempty"` + Deletion *RepositoryRulesetRuleType `json:"deletion,omitempty"` + RequiredLinearHistory *RepositoryRulesetRuleType `json:"required_linear_history,omitempty"` + MergeQueue *RepositoryRulesetMergeQueueRule `json:"merge_queue,omitempty"` + RequiredDeployments *RepositoryRulesetRequiredDeploymentsRule `json:"required_deployments,omitempty"` + RequiredSignatures *RepositoryRulesetRuleType `json:"required_signatures,omitempty"` + PullRequest *RepositoryRulesetPullRequestRule `json:"pull_request,omitempty"` + RequiredStatusChecks *RepositoryRulesetRequiredStatusChecksRule `json:"required_status_checks,omitempty"` + NonFastForward *RepositoryRulesetRuleType `json:"non_fast_forward,omitempty"` + CommitMessagePattern *RepositoryRulesetPatternRule `json:"commit_message_pattern,omitempty"` + CommitAuthorEmailPattern *RepositoryRulesetPatternRule `json:"commit_author_email_pattern,omitempty"` + CommitterEmailPattern *RepositoryRulesetPatternRule `json:"committer_email_pattern,omitempty"` + BranchNamePattern *RepositoryRulesetPatternRule `json:"branch_name_pattern,omitempty"` + TagNamePattern *RepositoryRulesetPatternRule `json:"tag_name_pattern,omitempty"` + FilePathRestriction *RepositoryRulesetFilePathRestrictionRule `json:"file_path_restriction,omitempty"` + MaxFilePathLength *RepositoryRulesetMaxFilePathLengthRule `json:"max_file_path_length,omitempty"` + FileExtensionRestriction *RepositoryRulesetFileExtensionRestrictionRule `json:"file_extension_restriction,omitempty"` + MaxFileSize *RepositoryRulesetMaxFileSizeRule `json:"max_file_size,omitempty"` + Workflows *RepositoryRulesetWorkflowsRule `json:"workflows,omitempty"` + CodeScanning *RepositoryRulesetCodeScanningRule `json:"code_scanning,omitempty"` +} + +// RepositoryRulesetLink represents Links associated with a repository's rulesets. These links are used to provide more information about the ruleset. +type RepositoryRulesetLink struct { + Self *RulesetLink `json:"self,omitempty"` + HTML *RulesetLink `json:"html,omitempty"` +} + +// RepositoryRulesetRuleType represents the type of a ruleset rule. +type RepositoryRulesetRuleType struct { + Type string `json:"type"` +} + +// RepositoryRulesetUpdateRule defines an update rule for the repository. +type RepositoryRulesetUpdateRule struct { + // Type can be one of: "update". + Type string `json:"type"` + Parameters *UpdateAllowsFetchAndMergeRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMergeQueueRule defines a merge queue rule for the repository. +type RepositoryRulesetMergeQueueRule struct { + // Type can be one of: "merge_queue". + Type string `json:"type"` + Parameters *MergeQueueRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetRequiredDeploymentsRule defines a rule for required deployments. +type RepositoryRulesetRequiredDeploymentsRule struct { + // Type can be one of: "required_deployments". + Type string `json:"type"` + Parameters *RequiredDeploymentEnvironmentsRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetPullRequestRule defines a rule for pull requests. +type RepositoryRulesetPullRequestRule struct { + // Type can be one of: "pull_request". + + Type string `json:"type"` + Parameters *PullRequestRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetRequiredStatusChecksRule defines a rule for required status checks. +type RepositoryRulesetRequiredStatusChecksRule struct { + // Type can be one of: "required_status_checks". + + Type string `json:"type"` + Parameters *RequiredStatusChecksRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetPatternRule defines a pattern rule for the repository. +type RepositoryRulesetPatternRule struct { + Type string `json:"type"` + Parameters *RulePatternParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetFilePathRestrictionRule defines a file path restriction rule for the repository. +type RepositoryRulesetFilePathRestrictionRule struct { + // Type can be one of: "file_path_restriction". + Type string `json:"type"` + Parameters *RuleFileParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMaxFilePathLengthRule defines a maximum file path length rule for the repository. +type RepositoryRulesetMaxFilePathLengthRule struct { + // Type can be one of: "max_file_path_length". + + Type string `json:"type"` + Parameters *RuleMaxFilePathLengthParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetFileExtensionRestrictionRule defines a file extension restriction rule for the repository. +type RepositoryRulesetFileExtensionRestrictionRule struct { + // Type can be one of: "file_extension_restriction". + Type string `json:"type"` + Parameters *RuleFileExtensionRestrictionParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetMaxFileSizeRule defines a maximum file size rule for the repository. +type RepositoryRulesetMaxFileSizeRule struct { + // Type can be one of: "max_file_size". + Type string `json:"type"` + Parameters *RuleMaxFileSizeParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetWorkflowsRule defines a workflow rule for the repository. +type RepositoryRulesetWorkflowsRule struct { + // Type can be one of: "workflows". + Type string `json:"type"` + Parameters *RequiredWorkflowsRuleParameters `json:"parameters,omitempty"` +} + +// RepositoryRulesetCodeScanningRule defines a code scanning rule for the repository. +type RepositoryRulesetCodeScanningRule struct { + // Type can be one of: "code_scanning". + Type string `json:"type"` + Parameters *RuleCodeScanningParameters `json:"parameters,omitempty"` +} + +// RuleCodeScanningParameters defines parameters for code scanning rules. +type RuleCodeScanningParameters struct { + CodeScanningTools []*CodeScanningTool `json:"code_scanning_tools,omitempty"` +} + +// CodeScanningTool defines a specific tool used for code scanning. +type CodeScanningTool struct { + AlertsThreshold string `json:"alerts_threshold"` + SecurityAlertsThreshold string `json:"security_alerts_threshold"` + Tool string `json:"tool"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that RepositoryRule parameter field can be of numerous types. +func (r *RepositoryRule) UnmarshalJSON(data []byte) error { + type rule RepositoryRule + var repositoryRule rule + if err := json.Unmarshal(data, &repositoryRule); err != nil { + return err + } + + r.RulesetID = repositoryRule.RulesetID + r.RulesetSourceType = repositoryRule.RulesetSourceType + r.RulesetSource = repositoryRule.RulesetSource + r.Type = repositoryRule.Type + + switch repositoryRule.Type { + case "creation", "deletion", "non_fast_forward", "required_linear_history", "required_signatures": + r.Parameters = nil + case "update": + if repositoryRule.Parameters == nil { + r.Parameters = nil + return nil + } + params := UpdateAllowsFetchAndMergeRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "merge_queue": + if repositoryRule.Parameters == nil { + r.Parameters = nil + return nil + } + params := MergeQueueRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "required_deployments": + params := RequiredDeploymentEnvironmentsRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern": + params := RulePatternParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "pull_request": + params := PullRequestRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "required_status_checks": + params := RequiredStatusChecksRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "workflows": + params := RequiredWorkflowsRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "file_path_restriction": + params := RuleFileParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "code_scanning": + params := RequiredCodeScanningRuleParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "max_file_path_length": + params := RuleMaxFilePathLengthParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "file_extension_restriction": + params := RuleFileExtensionRestrictionParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + case "max_file_size": + params := RuleMaxFileSizeParameters{} + if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { + return err + } + bytes, _ := json.Marshal(params) + rawParams := json.RawMessage(bytes) + + r.Parameters = &rawParams + default: + r.Type = "" + r.Parameters = nil + return fmt.Errorf("RepositoryRule.Type %q is not yet implemented, unable to unmarshal (%#v)", repositoryRule.Type, repositoryRule) + } + + return nil +} + +// NewMergeQueueRule creates a rule to only allow merges via a merge queue. +func NewMergeQueueRule(params *MergeQueueRuleParameters) (rule *RepositoryRule) { + if params != nil { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "merge_queue", + Parameters: &rawParams, + } + } + return &RepositoryRule{ + Type: "merge_queue", + } +} + +// NewCreationRule creates a rule to only allow users with bypass permission to create matching refs. +func NewCreationRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "creation", + } +} + +// NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs. +func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) { + if params != nil { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "update", + Parameters: &rawParams, + } + } + return &RepositoryRule{ + Type: "update", + } +} + +// NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs. +func NewDeletionRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "deletion", + } +} + +// NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches. +func NewRequiredLinearHistoryRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "required_linear_history", + } +} + +// NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches. +func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "required_deployments", + Parameters: &rawParams, + } +} + +// NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures. +func NewRequiredSignaturesRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "required_signatures", + } +} + +// NewPullRequestRule creates a rule to require all commits be made to a non-target branch and submitted via a pull request before they can be merged. +func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "pull_request", + Parameters: &rawParams, + } +} + +// NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. +func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "required_status_checks", + Parameters: &rawParams, + } +} + +// NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches. +func NewNonFastForwardRule() (rule *RepositoryRule) { + return &RepositoryRule{ + Type: "non_fast_forward", + } +} + +// NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches. +func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "commit_message_pattern", + Parameters: &rawParams, + } +} + +// NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches. +func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "commit_author_email_pattern", + Parameters: &rawParams, + } +} + +// NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches. +func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "committer_email_pattern", + Parameters: &rawParams, + } +} + +// NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches. +func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "branch_name_pattern", + Parameters: &rawParams, + } +} + +// NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches. +func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "tag_name_pattern", + Parameters: &rawParams, + } +} + +// NewRequiredWorkflowsRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. +func NewRequiredWorkflowsRule(params *RequiredWorkflowsRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "workflows", + Parameters: &rawParams, + } +} + +// NewRequiredCodeScanningRule creates a rule to require which tools must provide code scanning results before the reference is updated. +func NewRequiredCodeScanningRule(params *RequiredCodeScanningRuleParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "code_scanning", + Parameters: &rawParams, + } +} + +// NewFilePathRestrictionRule creates a rule to restrict file paths from being pushed to. +func NewFilePathRestrictionRule(params *RuleFileParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "file_path_restriction", + Parameters: &rawParams, + } +} + +// NewMaxFilePathLengthRule creates a rule to restrict file paths longer than the limit from being pushed. +func NewMaxFilePathLengthRule(params *RuleMaxFilePathLengthParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "max_file_path_length", + Parameters: &rawParams, + } +} + +// NewFileExtensionRestrictionRule creates a rule to restrict file extensions from being pushed to a commit. +func NewFileExtensionRestrictionRule(params *RuleFileExtensionRestrictionParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "file_extension_restriction", + Parameters: &rawParams, + } +} + +// NewMaxFileSizeRule creates a rule to restrict file sizes from being pushed to a commit. +func NewMaxFileSizeRule(params *RuleMaxFileSizeParameters) (rule *RepositoryRule) { + bytes, _ := json.Marshal(params) + + rawParams := json.RawMessage(bytes) + + return &RepositoryRule{ + Type: "max_file_size", + Parameters: &rawParams, + } +} + +// Ruleset represents a GitHub ruleset object. +type Ruleset struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + // Possible values for Target are branch, tag, push + Target *string `json:"target,omitempty"` + // Possible values for SourceType are: Repository, Organization + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for Enforcement are: disabled, active, evaluate + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RulesetLinks `json:"_links,omitempty"` + Conditions *RulesetConditions `json:"conditions,omitempty"` + Rules []*RepositoryRule `json:"rules,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. +type rulesetNoOmitBypassActors struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + // Possible values for Target are branch, tag + Target *string `json:"target,omitempty"` + // Possible values for SourceType are: Repository, Organization + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for Enforcement are: disabled, active, evaluate + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors"` + NodeID *string `json:"node_id,omitempty"` + Links *RulesetLinks `json:"_links,omitempty"` + Conditions *RulesetConditions `json:"conditions,omitempty"` + Rules []*RepositoryRule `json:"rules,omitempty"` +} + +// GetRulesForBranch gets all the rules that apply to the specified branch. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch +// +//meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} +func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rules []*RepositoryRule + resp, err := s.client.Do(ctx, req, &rules) + if err != nil { + return nil, resp, err + } + + return rules, resp, nil +} + +// GetAllRulesets gets all the rules that apply to the specified repository. +// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets +// +//meta:operation GET /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset []*Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// CreateRuleset creates a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset +// +//meta:operation POST /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo) + + req, err := s.client.NewRequest("POST", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// GetRuleset gets a ruleset for the specified repository. +// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-a-repository-ruleset +// +//meta:operation GET /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRuleset updates a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("PUT", u, rs) + if err != nil { + return nil, nil, err + } + + var ruleset *Ruleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRulesetNoBypassActor updates a ruleset for the specified repository. +// +// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as nil or an empty array. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + rsNoBypassActor := &rulesetNoOmitBypassActors{} + + if rs != nil { + rsNoBypassActor = &rulesetNoOmitBypassActors{ + ID: rs.ID, + Name: rs.Name, + Target: rs.Target, + SourceType: rs.SourceType, + Source: rs.Source, + Enforcement: rs.Enforcement, + BypassActors: rs.BypassActors, + NodeID: rs.NodeID, + Links: rs.Links, + Conditions: rs.Conditions, + Rules: rs.Rules, + } + } + + req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) + if err != nil { + return nil, nil, err + } + + var ruleSet *Ruleset + resp, err := s.client.Do(ctx, req, &ruleSet) + if err != nil { + return nil, resp, err + } + + return ruleSet, resp, nil +} + +// DeleteRuleset deletes a ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset +// +//meta:operation DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_stats.go b/vendor/github.com/google/go-github/v68/github/repos_stats.go similarity index 85% rename from vendor/github.com/google/go-github/github/repos_stats.go rename to vendor/github.com/google/go-github/v68/github/repos_stats.go index bb355aea..a6ef9c0d 100644 --- a/vendor/github.com/google/go-github/github/repos_stats.go +++ b/vendor/github.com/google/go-github/v68/github/repos_stats.go @@ -14,9 +14,9 @@ import ( // ContributorStats represents a contributor to a repository and their // weekly contributions to a given repo. type ContributorStats struct { - Author *Contributor `json:"author,omitempty"` - Total *int `json:"total,omitempty"` - Weeks []WeeklyStats `json:"weeks,omitempty"` + Author *Contributor `json:"author,omitempty"` + Total *int `json:"total,omitempty"` + Weeks []*WeeklyStats `json:"weeks,omitempty"` } func (c ContributorStats) String() string { @@ -45,7 +45,9 @@ func (w WeeklyStats) String() string { // it is now computing the requested statistics. A follow up request, after a // delay of a second or so, should result in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#contributors +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-all-contributor-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/contributors func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -84,7 +86,9 @@ func (w WeeklyCommitActivity) String() string { // it is now computing the requested statistics. A follow up request, after a // delay of a second or so, should result in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#commit-activity +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-last-year-of-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/commit_activity func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -111,7 +115,9 @@ func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, rep // it is now computing the requested statistics. A follow up request, after a // delay of a second or so, should result in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#code-frequency +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-weekly-commit-activity +// +//meta:operation GET /repos/{owner}/{repo}/stats/code_frequency func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -121,6 +127,9 @@ func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo var weeks [][]int resp, err := s.client.Do(ctx, req, &weeks) + if err != nil { + return nil, resp, err + } // convert int slices into WeeklyStats var stats []*WeeklyStats @@ -130,13 +139,13 @@ func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo } stat := &WeeklyStats{ Week: &Timestamp{time.Unix(int64(week[0]), 0)}, - Additions: Int(week[1]), - Deletions: Int(week[2]), + Additions: Ptr(week[1]), + Deletions: Ptr(week[2]), } stats = append(stats, stat) } - return stats, resp, err + return stats, resp, nil } // RepositoryParticipation is the number of commits by everyone @@ -164,7 +173,9 @@ func (r RepositoryParticipation) String() string { // it is now computing the requested statistics. A follow up request, after a // delay of a second or so, should result in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#participation +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-weekly-commit-count +// +//meta:operation GET /repos/{owner}/{repo}/stats/participation func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -197,7 +208,9 @@ type PunchCard struct { // it is now computing the requested statistics. A follow up request, after a // delay of a second or so, should result in a successful request. // -// GitHub API docs: https://developer.github.com/v3/repos/statistics/#punch-card +// GitHub API docs: https://docs.github.com/rest/metrics/statistics#get-the-hourly-commit-count-for-each-day +// +//meta:operation GET /repos/{owner}/{repo}/stats/punch_card func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) req, err := s.client.NewRequest("GET", u, nil) @@ -207,6 +220,9 @@ func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo str var results [][]int resp, err := s.client.Do(ctx, req, &results) + if err != nil { + return nil, resp, err + } // convert int slices into Punchcards var cards []*PunchCard @@ -215,12 +231,12 @@ func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo str continue } card := &PunchCard{ - Day: Int(result[0]), - Hour: Int(result[1]), - Commits: Int(result[2]), + Day: Ptr(result[0]), + Hour: Ptr(result[1]), + Commits: Ptr(result[2]), } cards = append(cards, card) } - return cards, resp, err + return cards, resp, nil } diff --git a/vendor/github.com/google/go-github/github/repos_statuses.go b/vendor/github.com/google/go-github/v68/github/repos_statuses.go similarity index 69% rename from vendor/github.com/google/go-github/github/repos_statuses.go rename to vendor/github.com/google/go-github/v68/github/repos_statuses.go index f94fdc85..e7b03047 100644 --- a/vendor/github.com/google/go-github/github/repos_statuses.go +++ b/vendor/github.com/google/go-github/v68/github/repos_statuses.go @@ -8,13 +8,13 @@ package github import ( "context" "fmt" - "time" ) // RepoStatus represents the status of a repository at a particular reference. type RepoStatus struct { - ID *int64 `json:"id,omitempty"` - URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + URL *string `json:"url,omitempty"` // State is the current state of the repository. Possible values are: // pending, success, error, or failure. @@ -30,9 +30,12 @@ type RepoStatus struct { // A string label to differentiate this status from the statuses of other systems. Context *string `json:"context,omitempty"` + // AvatarURL is the URL of the avatar of this status. + AvatarURL *string `json:"avatar_url,omitempty"` + Creator *User `json:"creator,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` } func (r RepoStatus) String() string { @@ -42,10 +45,12 @@ func (r RepoStatus) String() string { // ListStatuses lists the statuses of a repository at the specified // reference. ref can be a SHA, a branch name, or a tag name. // -// GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref -func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, ref) - u, err := addOptions(u, opt) +// GitHub API docs: https://docs.github.com/rest/commits/statuses#list-commit-statuses-for-a-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/statuses +func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opts *ListOptions) ([]*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -67,9 +72,11 @@ func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref // CreateStatus creates a new status for a repository at the specified // reference. Ref can be a SHA, a branch name, or a tag name. // -// GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-status +// GitHub API docs: https://docs.github.com/rest/commits/statuses#create-a-commit-status +// +//meta:operation POST /repos/{owner}/{repo}/statuses/{sha} func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, ref) + u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, refURLEscape(ref)) req, err := s.client.NewRequest("POST", u, status) if err != nil { return nil, nil, err @@ -90,10 +97,10 @@ type CombinedStatus struct { // failure, pending, or success. State *string `json:"state,omitempty"` - Name *string `json:"name,omitempty"` - SHA *string `json:"sha,omitempty"` - TotalCount *int `json:"total_count,omitempty"` - Statuses []RepoStatus `json:"statuses,omitempty"` + Name *string `json:"name,omitempty"` + SHA *string `json:"sha,omitempty"` + TotalCount *int `json:"total_count,omitempty"` + Statuses []*RepoStatus `json:"statuses,omitempty"` CommitURL *string `json:"commit_url,omitempty"` RepositoryURL *string `json:"repository_url,omitempty"` @@ -106,10 +113,12 @@ func (s CombinedStatus) String() string { // GetCombinedStatus returns the combined status of a repository at the specified // reference. ref can be a SHA, a branch name, or a tag name. // -// GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref -func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, ref) - u, err := addOptions(u, opt) +// GitHub API docs: https://docs.github.com/rest/commits/statuses#get-the-combined-status-for-a-specific-reference +// +//meta:operation GET /repos/{owner}/{repo}/commits/{ref}/status +func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opts *ListOptions) (*CombinedStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/google/go-github/v68/github/repos_tags.go b/vendor/github.com/google/go-github/v68/github/repos_tags.go new file mode 100644 index 00000000..b6dc36e2 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/repos_tags.go @@ -0,0 +1,85 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TagProtection represents a repository tag protection. +type TagProtection struct { + ID *int64 `json:"id"` + Pattern *string `json:"pattern"` +} + +// tagProtectionRequest represents a request to create tag protection. +type tagProtectionRequest struct { + // An optional glob pattern to match against when enforcing tag protection. + Pattern string `json:"pattern"` +} + +// Deprecated: ListTagProtection lists tag protection of the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---list-tag-protection-states-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/tags/protection +func (s *RepositoriesService) ListTagProtection(ctx context.Context, owner, repo string) ([]*TagProtection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tagProtections []*TagProtection + resp, err := s.client.Do(ctx, req, &tagProtections) + if err != nil { + return nil, resp, err + } + + return tagProtections, resp, nil +} + +// Deprecated: CreateTagProtection creates the tag protection of the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---create-a-tag-protection-state-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/tags/protection +func (s *RepositoriesService) CreateTagProtection(ctx context.Context, owner, repo, pattern string) (*TagProtection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection", owner, repo) + r := &tagProtectionRequest{Pattern: pattern} + req, err := s.client.NewRequest("POST", u, r) + if err != nil { + return nil, nil, err + } + + tagProtection := new(TagProtection) + resp, err := s.client.Do(ctx, req, tagProtection) + if err != nil { + return nil, resp, err + } + + return tagProtection, resp, nil +} + +// Deprecated: DeleteTagProtection deletes a tag protection from the specified repository. +// Deprecation notice: This operation is deprecated and will be removed after August 30, 2024. Use the "Repository Rulesets" endpoint instead: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset +// +// GitHub API docs: https://docs.github.com/rest/repos/tags#closing-down---delete-a-tag-protection-state-for-a-repository +// +//meta:operation DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id} +func (s *RepositoriesService) DeleteTagProtection(ctx context.Context, owner, repo string, tagProtectionID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags/protection/%v", owner, repo, tagProtectionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_traffic.go b/vendor/github.com/google/go-github/v68/github/repos_traffic.go similarity index 82% rename from vendor/github.com/google/go-github/github/repos_traffic.go rename to vendor/github.com/google/go-github/v68/github/repos_traffic.go index fb1c9764..ae2f1a86 100644 --- a/vendor/github.com/google/go-github/github/repos_traffic.go +++ b/vendor/github.com/google/go-github/v68/github/repos_traffic.go @@ -54,7 +54,9 @@ type TrafficBreakdownOptions struct { // ListTrafficReferrers list the top 10 referrers over the last 14 days. // -// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-referrers +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-top-referral-sources +// +//meta:operation GET /repos/{owner}/{repo}/traffic/popular/referrers func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) @@ -74,7 +76,9 @@ func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, r // ListTrafficPaths list the top 10 popular content over the last 14 days. // -// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-paths +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-top-referral-paths +// +//meta:operation GET /repos/{owner}/{repo}/traffic/popular/paths func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) @@ -94,10 +98,12 @@ func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo // ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. // -// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views -func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-page-views +// +//meta:operation GET /repos/{owner}/{repo}/traffic/views +func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -118,10 +124,12 @@ func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo // ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days. // -// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views -func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/metrics/traffic#get-repository-clones +// +//meta:operation GET /repos/{owner}/{repo}/traffic/clones +func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/google/go-github/v68/github/scim.go b/vendor/github.com/google/go-github/v68/github/scim.go new file mode 100644 index 00000000..4b34c166 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/scim.go @@ -0,0 +1,219 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// SCIMService provides access to SCIM related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/scim +type SCIMService service + +// SCIMUserAttributes represents supported SCIM User attributes. +// +// GitHub API docs: https://docs.github.com/rest/scim#supported-scim-user-attributes +type SCIMUserAttributes struct { + UserName string `json:"userName"` // Configured by the admin. Could be an email, login, or username. (Required.) + Name SCIMUserName `json:"name"` // (Required.) + DisplayName *string `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.) + Emails []*SCIMUserEmail `json:"emails"` // User emails. (Required.) + Schemas []string `json:"schemas,omitempty"` // (Optional.) + ExternalID *string `json:"externalId,omitempty"` // (Optional.) + Groups []string `json:"groups,omitempty"` // (Optional.) + Active *bool `json:"active,omitempty"` // (Optional.) + // Only populated as a result of calling ListSCIMProvisionedIdentitiesOptions or GetSCIMProvisioningInfoForUser: + ID *string `json:"id,omitempty"` + Meta *SCIMMeta `json:"meta,omitempty"` +} + +// SCIMUserName represents SCIM user information. +type SCIMUserName struct { + GivenName string `json:"givenName"` // The first name of the user. (Required.) + FamilyName string `json:"familyName"` // The family name of the user. (Required.) + Formatted *string `json:"formatted,omitempty"` // (Optional.) +} + +// SCIMUserEmail represents SCIM user email. +type SCIMUserEmail struct { + Value string `json:"value"` // (Required.) + Primary *bool `json:"primary,omitempty"` // (Optional.) + Type *string `json:"type,omitempty"` // (Optional.) +} + +// SCIMMeta represents metadata about the SCIM resource. +type SCIMMeta struct { + ResourceType *string `json:"resourceType,omitempty"` + Created *Timestamp `json:"created,omitempty"` + LastModified *Timestamp `json:"lastModified,omitempty"` + Location *string `json:"location,omitempty"` +} + +// SCIMProvisionedIdentities represents the result of calling ListSCIMProvisionedIdentities. +type SCIMProvisionedIdentities struct { + Schemas []string `json:"schemas,omitempty"` + TotalResults *int `json:"totalResults,omitempty"` + ItemsPerPage *int `json:"itemsPerPage,omitempty"` + StartIndex *int `json:"startIndex,omitempty"` + Resources []*SCIMUserAttributes `json:"Resources,omitempty"` +} + +// ListSCIMProvisionedIdentitiesOptions represents options for ListSCIMProvisionedIdentities. +// +// GitHub API docs: https://docs.github.com/rest/scim#list-scim-provisioned-identities--parameters +type ListSCIMProvisionedIdentitiesOptions struct { + StartIndex *int `url:"startIndex,omitempty"` // Used for pagination: the index of the first result to return. (Optional.) + Count *int `url:"count,omitempty"` // Used for pagination: the number of results to return. (Optional.) + // Filter results using the equals query parameter operator (eq). + // You can filter results that are equal to id, userName, emails, and external_id. + // For example, to search for an identity with the userName Octocat, you would use this query: ?filter=userName%20eq%20\"Octocat\". + // To filter results for the identity with the email octocat@github.com, you would use this query: ?filter=emails%20eq%20\"octocat@github.com\". + // (Optional.) + Filter *string `url:"filter,omitempty"` +} + +// ListSCIMProvisionedIdentities lists SCIM provisioned identities. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#list-scim-provisioned-identities +// +//meta:operation GET /scim/v2/organizations/{org}/Users +func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*SCIMProvisionedIdentities, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + identities := new(SCIMProvisionedIdentities) + resp, err := s.client.Do(ctx, req, identities) + if err != nil { + return nil, resp, err + } + + return identities, resp, nil +} + +// ProvisionAndInviteSCIMUser provisions organization membership for a user, and sends an activation email to the email address. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#provision-and-invite-a-scim-user +// +//meta:operation POST /scim/v2/organizations/{org}/Users +func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, opts *SCIMUserAttributes) (*SCIMUserAttributes, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + user := new(SCIMUserAttributes) + resp, err := s.client.Do(ctx, req, user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#get-scim-provisioning-information-for-a-user +// +//meta:operation GET /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*SCIMUserAttributes, *Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + user := new(SCIMUserAttributes) + resp, err := s.client.Do(ctx, req, &user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// UpdateProvisionedOrgMembership updates a provisioned organization membership. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#update-a-provisioned-organization-membership +// +//meta:operation PUT /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, opts *SCIMUserAttributes) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UpdateAttributeForSCIMUserOptions represents options for UpdateAttributeForSCIMUser. +// +// GitHub API docs: https://docs.github.com/rest/scim#update-an-attribute-for-a-scim-user--parameters +type UpdateAttributeForSCIMUserOptions struct { + Schemas []string `json:"schemas,omitempty"` // (Optional.) + Operations UpdateAttributeForSCIMUserOperations `json:"operations"` // Set of operations to be performed. (Required.) +} + +// UpdateAttributeForSCIMUserOperations represents operations for UpdateAttributeForSCIMUser. +type UpdateAttributeForSCIMUserOperations struct { + Op string `json:"op"` // (Required.) + Path *string `json:"path,omitempty"` // (Optional.) + Value json.RawMessage `json:"value,omitempty"` // (Optional.) +} + +// UpdateAttributeForSCIMUser updates an attribute for an SCIM user. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#update-an-attribute-for-a-scim-user +// +//meta:operation PATCH /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, opts *UpdateAttributeForSCIMUserOptions) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteSCIMUserFromOrg deletes SCIM user from an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/scim/scim#delete-a-scim-user-from-an-organization +// +//meta:operation DELETE /scim/v2/organizations/{org}/Users/{scim_user_id} +func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID string) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/search.go b/vendor/github.com/google/go-github/v68/github/search.go similarity index 50% rename from vendor/github.com/google/go-github/github/search.go rename to vendor/github.com/google/go-github/v68/github/search.go index abaf5e1f..54bc6d5e 100644 --- a/vendor/github.com/google/go-github/github/search.go +++ b/vendor/github.com/google/go-github/v68/github/search.go @@ -8,7 +8,6 @@ package github import ( "context" "fmt" - "net/url" "strconv" "strings" @@ -21,12 +20,19 @@ import ( // Each method takes a query string defining the search keywords and any search qualifiers. // For example, when searching issues, the query "gopher is:issue language:go" will search // for issues containing the word "gopher" in Go repositories. The method call -// opts := &github.SearchOptions{Sort: "created", Order: "asc"} -// cl.Search.Issues(ctx, "gopher is:issue language:go", opts) +// +// opts := &github.SearchOptions{Sort: "created", Order: "asc"} +// cl.Search.Issues(ctx, "gopher is:issue language:go", opts) +// // will search for such issues, sorting by creation date in ascending order // (i.e., oldest first). // -// GitHub API docs: https://developer.github.com/v3/search/ +// If query includes multiple conditions, it MUST NOT include "+" as the condition separator. +// You have to use " " as the separator instead. +// For example, querying with "language:c++" and "leveldb", then query should be +// "language:c++ leveldb" but not "language:c+++leveldb". +// +// GitHub API docs: https://docs.github.com/rest/search/ type SearchService service // SearchOptions specifies optional parameters to the SearchService methods. @@ -59,18 +65,61 @@ type searchParameters struct { // RepositoriesSearchResult represents the result of a repositories search. type RepositoriesSearchResult struct { - Total *int `json:"total_count,omitempty"` - IncompleteResults *bool `json:"incomplete_results,omitempty"` - Repositories []Repository `json:"items,omitempty"` + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Repositories []*Repository `json:"items,omitempty"` } // Repositories searches repositories via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-repositories -func (s *SearchService) Repositories(ctx context.Context, query string, opt *SearchOptions) (*RepositoriesSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-repositories +// +//meta:operation GET /search/repositories +func (s *SearchService) Repositories(ctx context.Context, query string, opts *SearchOptions) (*RepositoriesSearchResult, *Response, error) { result := new(RepositoriesSearchResult) - resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// TopicsSearchResult represents the result of a topics search. +type TopicsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Topics []*TopicResult `json:"items,omitempty"` +} + +type TopicResult struct { + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + ShortDescription *string `json:"short_description,omitempty"` + Description *string `json:"description,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Featured *bool `json:"featured,omitempty"` + Curated *bool `json:"curated,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Topics finds topics via various criteria. Results are sorted by best match. +// Please see https://help.github.com/articles/searching-topics for more +// information about search qualifiers. +// +// GitHub API docs: https://docs.github.com/rest/search/search#search-topics +// +//meta:operation GET /search/topics +func (s *SearchService) Topics(ctx context.Context, query string, opts *SearchOptions) (*TopicsSearchResult, *Response, error) { + result := new(TopicsSearchResult) + resp, err := s.search(ctx, "topics", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // CommitsSearchResult represents the result of a commits search. @@ -97,43 +146,61 @@ type CommitResult struct { // Commits searches commits via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-commits -func (s *SearchService) Commits(ctx context.Context, query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-commits +// +//meta:operation GET /search/commits +func (s *SearchService) Commits(ctx context.Context, query string, opts *SearchOptions) (*CommitsSearchResult, *Response, error) { result := new(CommitsSearchResult) - resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // IssuesSearchResult represents the result of an issues search. type IssuesSearchResult struct { - Total *int `json:"total_count,omitempty"` - IncompleteResults *bool `json:"incomplete_results,omitempty"` - Issues []Issue `json:"items,omitempty"` + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Issues []*Issue `json:"items,omitempty"` } // Issues searches issues via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-issues -func (s *SearchService) Issues(ctx context.Context, query string, opt *SearchOptions) (*IssuesSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-issues-and-pull-requests +// +//meta:operation GET /search/issues +func (s *SearchService) Issues(ctx context.Context, query string, opts *SearchOptions) (*IssuesSearchResult, *Response, error) { result := new(IssuesSearchResult) - resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // UsersSearchResult represents the result of a users search. type UsersSearchResult struct { - Total *int `json:"total_count,omitempty"` - IncompleteResults *bool `json:"incomplete_results,omitempty"` - Users []User `json:"items,omitempty"` + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Users []*User `json:"items,omitempty"` } // Users searches users via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-users -func (s *SearchService) Users(ctx context.Context, query string, opt *SearchOptions) (*UsersSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-users +// +//meta:operation GET /search/users +func (s *SearchService) Users(ctx context.Context, query string, opts *SearchOptions) (*UsersSearchResult, *Response, error) { result := new(UsersSearchResult) - resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // Match represents a single text match. @@ -142,13 +209,13 @@ type Match struct { Indices []int `json:"indices,omitempty"` } -// TextMatch represents a text match for a SearchResult +// TextMatch represents a text match for a SearchResult. type TextMatch struct { - ObjectURL *string `json:"object_url,omitempty"` - ObjectType *string `json:"object_type,omitempty"` - Property *string `json:"property,omitempty"` - Fragment *string `json:"fragment,omitempty"` - Matches []Match `json:"matches,omitempty"` + ObjectURL *string `json:"object_url,omitempty"` + ObjectType *string `json:"object_type,omitempty"` + Property *string `json:"property,omitempty"` + Fragment *string `json:"fragment,omitempty"` + Matches []*Match `json:"matches,omitempty"` } func (tm TextMatch) String() string { @@ -157,19 +224,19 @@ func (tm TextMatch) String() string { // CodeSearchResult represents the result of a code search. type CodeSearchResult struct { - Total *int `json:"total_count,omitempty"` - IncompleteResults *bool `json:"incomplete_results,omitempty"` - CodeResults []CodeResult `json:"items,omitempty"` + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + CodeResults []*CodeResult `json:"items,omitempty"` } // CodeResult represents a single search result. type CodeResult struct { - Name *string `json:"name,omitempty"` - Path *string `json:"path,omitempty"` - SHA *string `json:"sha,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - Repository *Repository `json:"repository,omitempty"` - TextMatches []TextMatch `json:"text_matches,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TextMatches []*TextMatch `json:"text_matches,omitempty"` } func (c CodeResult) String() string { @@ -178,11 +245,17 @@ func (c CodeResult) String() string { // Code searches code via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-code -func (s *SearchService) Code(ctx context.Context, query string, opt *SearchOptions) (*CodeSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-code +// +//meta:operation GET /search/code +func (s *SearchService) Code(ctx context.Context, query string, opts *SearchOptions) (*CodeSearchResult, *Response, error) { result := new(CodeSearchResult) - resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // LabelsSearchResult represents the result of a code search. @@ -209,53 +282,66 @@ func (l LabelResult) String() string { // Labels searches labels in the repository with ID repoID via various criteria. // -// GitHub API docs: https://developer.github.com/v3/search/#search-labels -func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opt *SearchOptions) (*LabelsSearchResult, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/search/search#search-labels +// +//meta:operation GET /search/labels +func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opts *SearchOptions) (*LabelsSearchResult, *Response, error) { result := new(LabelsSearchResult) - resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opt, result) - return result, resp, err + resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil } // Helper function that executes search queries against different // GitHub search types (repositories, commits, code, issues, users, labels) -func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opt *SearchOptions, result interface{}) (*Response, error) { - params, err := qs.Values(opt) +// +// If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator. +// For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb". +func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opts *SearchOptions, result interface{}) (*Response, error) { + params, err := qs.Values(opts) if err != nil { return nil, err } - q := strings.Replace(parameters.Query, " ", "+", -1) + if parameters.RepositoryID != nil { params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10)) } - query := "q=" + url.PathEscape(q) - if v := params.Encode(); v != "" { - query = query + "&" + v - } - u := fmt.Sprintf("search/%s?%s", searchType, query) + params.Set("q", parameters.Query) + u := fmt.Sprintf("search/%s?%s", searchType, params.Encode()) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } - + var acceptHeaders []string switch { case searchType == "commits": // Accept header for search commits preview endpoint // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeCommitSearchPreview) + acceptHeaders = append(acceptHeaders, mediaTypeCommitSearchPreview) + case searchType == "topics": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview) case searchType == "repositories": // Accept header for search repositories based on topics preview endpoint // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeTopicsPreview) - case searchType == "labels": - // Accept header for search labels based on label description preview endpoint. + acceptHeaders = append(acceptHeaders, mediaTypeTopicsPreview) + case searchType == "issues": + // Accept header for search issues based on reactions preview endpoint // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) - case opt != nil && opt.TextMatch: - // Accept header defaults to "application/vnd.github.v3+json" - // We change it here to fetch back text-match metadata - req.Header.Set("Accept", "application/vnd.github.v3.text-match+json") + acceptHeaders = append(acceptHeaders, mediaTypeReactionsPreview) + } + // https://docs.github.com/rest/search#search-repositories + // Accept header defaults to "application/vnd.github.v3+json" + // We change it here to fetch back text-match metadata + if opts != nil && opts.TextMatch { + acceptHeaders = append(acceptHeaders, "application/vnd.github.v3.text-match+json") } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) return s.client.Do(ctx, req, result) } diff --git a/vendor/github.com/google/go-github/v68/github/secret_scanning.go b/vendor/github.com/google/go-github/v68/github/secret_scanning.go new file mode 100644 index 00000000..fc0fe0cd --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/secret_scanning.go @@ -0,0 +1,261 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// SecretScanningService handles communication with the secret scanning related +// methods of the GitHub API. +type SecretScanningService service + +// SecretScanningAlert represents a GitHub secret scanning alert. +type SecretScanningAlert struct { + Number *int `json:"number,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LocationsURL *string `json:"locations_url,omitempty"` + State *string `json:"state,omitempty"` + Resolution *string `json:"resolution,omitempty"` + ResolvedAt *Timestamp `json:"resolved_at,omitempty"` + ResolvedBy *User `json:"resolved_by,omitempty"` + SecretType *string `json:"secret_type,omitempty"` + SecretTypeDisplayName *string `json:"secret_type_display_name,omitempty"` + Secret *string `json:"secret,omitempty"` + Repository *Repository `json:"repository,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PushProtectionBypassed *bool `json:"push_protection_bypassed,omitempty"` + PushProtectionBypassedBy *User `json:"push_protection_bypassed_by,omitempty"` + PushProtectionBypassedAt *Timestamp `json:"push_protection_bypassed_at,omitempty"` + ResolutionComment *string `json:"resolution_comment,omitempty"` +} + +// SecretScanningAlertLocation represents the location for a secret scanning alert. +type SecretScanningAlertLocation struct { + Type *string `json:"type,omitempty"` + Details *SecretScanningAlertLocationDetails `json:"details,omitempty"` +} + +// SecretScanningAlertLocationDetails represents the location details for a secret scanning alert. +type SecretScanningAlertLocationDetails struct { + Path *string `json:"path,omitempty"` + Startline *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + BlobSHA *string `json:"blob_sha,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` + PullRequestCommentURL *string `json:"pull_request_comment_url,omitempty"` +} + +// SecretScanningAlertListOptions specifies optional parameters to the SecretScanningService.ListAlertsForEnterprise method. +type SecretScanningAlertListOptions struct { + // State of the secret scanning alerts to list. Set to open or resolved to only list secret scanning alerts in a specific state. + State string `url:"state,omitempty"` + + // A comma-separated list of secret types to return. By default all secret types are returned. + SecretType string `url:"secret_type,omitempty"` + + // A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. + // Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests. + Resolution string `url:"resolution,omitempty"` + + ListCursorOptions + + // List options can vary on the Enterprise type. + // On Enterprise Cloud, Secret Scan alerts support requesting by page number + // along with providing a cursor for an "after" param. + // See: https://docs.github.com/enterprise-cloud@latest/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + // Whereas on Enterprise Server, pagination is by index. + // See: https://docs.github.com/enterprise-server@3.6/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + ListOptions +} + +// SecretScanningAlertUpdateOptions specifies optional parameters to the SecretScanningService.UpdateAlert method. +type SecretScanningAlertUpdateOptions struct { + // State is required and sets the state of the secret scanning alert. + // Can be either "open" or "resolved". + // You must provide resolution when you set the state to "resolved". + State string `json:"state"` + + // Required when the state is "resolved" and represents the reason for resolving the alert. + // Can be one of: "false_positive", "wont_fix", "revoked", or "used_in_tests". + Resolution *string `json:"resolution,omitempty"` + + // An optional comment when closing an alert. + ResolutionComment *string `json:"resolution_comment,omitempty"` +} + +// ListAlertsForEnterprise lists secret scanning alerts for eligible repositories in an enterprise, from newest to oldest. +// +// To use this endpoint, you must be a member of the enterprise, and you must use an access token with the repo scope or +// security_events scope. Alerts are only returned for organizations in the enterprise for which you are an organization owner or a security manager. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForEnterprise(ctx context.Context, enterprise string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("enterprises/%v/secret-scanning/alerts", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForOrg lists secret scanning alerts for eligible repositories in an organization, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-an-organization +// +//meta:operation GET /orgs/{org}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("orgs/%v/secret-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForRepo lists secret scanning alerts for a private repository, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-secret-scanning-alerts-for-a-repository +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts +func (s *SecretScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// GetAlert gets a single secret scanning alert detected in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#get-a-secret-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} +func (s *SecretScanningService) GetAlert(ctx context.Context, owner, repo string, number int64) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// UpdateAlert updates the status of a secret scanning alert in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#update-a-secret-scanning-alert +// +//meta:operation PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} +func (s *SecretScanningService) UpdateAlert(ctx context.Context, owner, repo string, number int64, opts *SecretScanningAlertUpdateOptions) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// ListLocationsForAlert lists all locations for a given secret scanning alert for a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning#list-locations-for-a-secret-scanning-alert +// +//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations +func (s *SecretScanningService) ListLocationsForAlert(ctx context.Context, owner, repo string, number int64, opts *ListOptions) ([]*SecretScanningAlertLocation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v/locations", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var locations []*SecretScanningAlertLocation + resp, err := s.client.Do(ctx, req, &locations) + if err != nil { + return nil, resp, err + } + + return locations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/security_advisories.go b/vendor/github.com/google/go-github/v68/github/security_advisories.go new file mode 100644 index 00000000..b5a43f1a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/security_advisories.go @@ -0,0 +1,279 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +type SecurityAdvisoriesService service + +// SecurityAdvisorySubmission represents the Security Advisory Submission. +type SecurityAdvisorySubmission struct { + // Accepted represents whether a private vulnerability report was accepted by the repository's administrators. + Accepted *bool `json:"accepted,omitempty"` +} + +// RepoAdvisoryCredit represents the credit object for a repository Security Advisory. +type RepoAdvisoryCredit struct { + Login *string `json:"login,omitempty"` + Type *string `json:"type,omitempty"` +} + +// RepoAdvisoryCreditDetailed represents a credit given to a user for a repository Security Advisory. +type RepoAdvisoryCreditDetailed struct { + User *User `json:"user,omitempty"` + Type *string `json:"type,omitempty"` + State *string `json:"state,omitempty"` +} + +// ListRepositorySecurityAdvisoriesOptions specifies the optional parameters to list the repository security advisories. +type ListRepositorySecurityAdvisoriesOptions struct { + ListCursorOptions + + // Direction in which to sort advisories. Possible values are: asc, desc. + // Default is "asc". + Direction string `url:"direction,omitempty"` + + // Sort specifies how to sort advisories. Possible values are: created, updated, + // and published. Default value is "created". + Sort string `url:"sort,omitempty"` + + // State filters advisories based on their state. Possible values are: triage, draft, published, closed. + State string `url:"state,omitempty"` +} + +// ListGlobalSecurityAdvisoriesOptions specifies the optional parameters to list the global security advisories. +type ListGlobalSecurityAdvisoriesOptions struct { + ListCursorOptions + + // If specified, only advisories with this GHSA (GitHub Security Advisory) identifier will be returned. + GHSAID *string `url:"ghsa_id,omitempty"` + + // If specified, only advisories of this type will be returned. + // By default, a request with no other parameters defined will only return reviewed advisories that are not malware. + // Default: reviewed + // Can be one of: reviewed, malware, unreviewed + Type *string `url:"type,omitempty"` + + // If specified, only advisories with this CVE (Common Vulnerabilities and Exposures) identifier will be returned. + CVEID *string `url:"cve_id,omitempty"` + + // If specified, only advisories for these ecosystems will be returned. + // Can be one of: actions, composer, erlang, go, maven, npm, nuget, other, pip, pub, rubygems, rust + Ecosystem *string `url:"ecosystem,omitempty"` + + // If specified, only advisories with these severities will be returned. + // Can be one of: unknown, low, medium, high, critical + Severity *string `url:"severity,omitempty"` + + // If specified, only advisories with these Common Weakness Enumerations (CWEs) will be returned. + // Example: cwes=79,284,22 or cwes[]=79&cwes[]=284&cwes[]=22 + CWEs []string `url:"cwes,omitempty"` + + // Whether to only return advisories that have been withdrawn. + IsWithdrawn *bool `url:"is_withdrawn,omitempty"` + + // If specified, only return advisories that affect any of package or package@version. + // A maximum of 1000 packages can be specified. If the query parameter causes + // the URL to exceed the maximum URL length supported by your client, you must specify fewer packages. + // Example: affects=package1,package2@1.0.0,package3@^2.0.0 or affects[]=package1&affects[]=package2@1.0.0 + Affects *string `url:"affects,omitempty"` + + // If specified, only return advisories that were published on a date or date range. + Published *string `url:"published,omitempty"` + + // If specified, only return advisories that were updated on a date or date range. + Updated *string `url:"updated,omitempty"` + + // If specified, only show advisories that were updated or published on a date or date range. + Modified *string `url:"modified,omitempty"` +} + +// GlobalSecurityAdvisory represents the global security advisory object response. +type GlobalSecurityAdvisory struct { + SecurityAdvisory + ID *int64 `json:"id,omitempty"` + RepositoryAdvisoryURL *string `json:"repository_advisory_url,omitempty"` + Type *string `json:"type,omitempty"` + SourceCodeLocation *string `json:"source_code_location,omitempty"` + References []string `json:"references,omitempty"` + Vulnerabilities []*GlobalSecurityVulnerability `json:"vulnerabilities,omitempty"` + GithubReviewedAt *Timestamp `json:"github_reviewed_at,omitempty"` + NVDPublishedAt *Timestamp `json:"nvd_published_at,omitempty"` + Credits []*Credit `json:"credits,omitempty"` +} + +// GlobalSecurityVulnerability represents a vulnerability for a global security advisory. +type GlobalSecurityVulnerability struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + FirstPatchedVersion *string `json:"first_patched_version,omitempty"` + VulnerableVersionRange *string `json:"vulnerable_version_range,omitempty"` + VulnerableFunctions []string `json:"vulnerable_functions,omitempty"` +} + +// Credit represents the credit object for a global security advisory. +type Credit struct { + User *User `json:"user,omitempty"` + Type *string `json:"type,omitempty"` +} + +// RequestCVE requests a Common Vulnerabilities and Exposures (CVE) for a repository security advisory. +// The ghsaID is the GitHub Security Advisory identifier of the advisory. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#request-a-cve-for-a-repository-security-advisory +// +//meta:operation POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve +func (s *SecurityAdvisoriesService) RequestCVE(ctx context.Context, owner, repo, ghsaID string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/cve", owner, repo, ghsaID) + + req, err := s.client.NewRequest("POST", url, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + if _, ok := err.(*AcceptedError); ok { + return resp, nil + } + + return resp, err + } + + return resp, nil +} + +// CreateTemporaryPrivateFork creates a temporary private fork to collaborate on fixing a security vulnerability in your repository. +// The ghsaID is the GitHub Security Advisory identifier of the advisory. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#create-a-temporary-private-fork +// +//meta:operation POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/forks +func (s *SecurityAdvisoriesService) CreateTemporaryPrivateFork(ctx context.Context, owner, repo, ghsaID string) (*Repository, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/forks", owner, repo, ghsaID) + + req, err := s.client.NewRequest("POST", url, nil) + if err != nil { + return nil, nil, err + } + + fork := new(Repository) + resp, err := s.client.Do(ctx, req, fork) + if err != nil { + if aerr, ok := err.(*AcceptedError); ok { + if err := json.Unmarshal(aerr.Raw, fork); err != nil { + return fork, resp, err + } + + return fork, resp, err + } + return nil, resp, err + } + + return fork, resp, nil +} + +// ListRepositorySecurityAdvisoriesForOrg lists the repository security advisories for an organization. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories-for-an-organization +// +//meta:operation GET /orgs/{org}/security-advisories +func (s *SecurityAdvisoriesService) ListRepositorySecurityAdvisoriesForOrg(ctx context.Context, org string, opt *ListRepositorySecurityAdvisoriesOptions) ([]*SecurityAdvisory, *Response, error) { + url := fmt.Sprintf("orgs/%v/security-advisories", org) + url, err := addOptions(url, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*SecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// ListRepositorySecurityAdvisories lists the security advisories in a repository. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/repository-advisories#list-repository-security-advisories +// +//meta:operation GET /repos/{owner}/{repo}/security-advisories +func (s *SecurityAdvisoriesService) ListRepositorySecurityAdvisories(ctx context.Context, owner, repo string, opt *ListRepositorySecurityAdvisoriesOptions) ([]*SecurityAdvisory, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/security-advisories", owner, repo) + url, err := addOptions(url, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*SecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// ListGlobalSecurityAdvisories lists all global security advisories. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#list-global-security-advisories +// +//meta:operation GET /advisories +func (s *SecurityAdvisoriesService) ListGlobalSecurityAdvisories(ctx context.Context, opts *ListGlobalSecurityAdvisoriesOptions) ([]*GlobalSecurityAdvisory, *Response, error) { + url := "advisories" + url, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisories []*GlobalSecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisories) + if err != nil { + return nil, resp, err + } + + return advisories, resp, nil +} + +// GetGlobalSecurityAdvisories gets a global security advisory using its GitHub Security Advisory (GHSA) identifier. +// +// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#get-a-global-security-advisory +// +//meta:operation GET /advisories/{ghsa_id} +func (s *SecurityAdvisoriesService) GetGlobalSecurityAdvisories(ctx context.Context, ghsaID string) (*GlobalSecurityAdvisory, *Response, error) { + url := fmt.Sprintf("advisories/%s", ghsaID) + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + var advisory *GlobalSecurityAdvisory + resp, err := s.client.Do(ctx, req, &advisory) + if err != nil { + return nil, resp, err + } + + return advisory, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/strings.go b/vendor/github.com/google/go-github/v68/github/strings.go similarity index 80% rename from vendor/github.com/google/go-github/github/strings.go rename to vendor/github.com/google/go-github/v68/github/strings.go index 431e1cc6..f5e61aa3 100644 --- a/vendor/github.com/google/go-github/github/strings.go +++ b/vendor/github.com/google/go-github/v68/github/strings.go @@ -8,8 +8,6 @@ package github import ( "bytes" "fmt" - "io" - "reflect" ) @@ -27,9 +25,9 @@ func Stringify(message interface{}) string { // stringifyValue was heavily inspired by the goprotobuf library. -func stringifyValue(w io.Writer, val reflect.Value) { +func stringifyValue(w *bytes.Buffer, val reflect.Value) { if val.Kind() == reflect.Ptr && val.IsNil() { - w.Write([]byte("")) + w.WriteString("") return } @@ -39,20 +37,20 @@ func stringifyValue(w io.Writer, val reflect.Value) { case reflect.String: fmt.Fprintf(w, `"%s"`, v) case reflect.Slice: - w.Write([]byte{'['}) + w.WriteByte('[') for i := 0; i < v.Len(); i++ { if i > 0 { - w.Write([]byte{' '}) + w.WriteByte(' ') } stringifyValue(w, v.Index(i)) } - w.Write([]byte{']'}) + w.WriteByte(']') return case reflect.Struct: if v.Type().Name() != "" { - w.Write([]byte(v.Type().String())) + w.WriteString(v.Type().String()) } // special handling of Timestamp values @@ -61,7 +59,7 @@ func stringifyValue(w io.Writer, val reflect.Value) { return } - w.Write([]byte{'{'}) + w.WriteByte('{') var sep bool for i := 0; i < v.NumField(); i++ { @@ -72,19 +70,22 @@ func stringifyValue(w io.Writer, val reflect.Value) { if fv.Kind() == reflect.Slice && fv.IsNil() { continue } + if fv.Kind() == reflect.Map && fv.IsNil() { + continue + } if sep { - w.Write([]byte(", ")) + w.WriteString(", ") } else { sep = true } - w.Write([]byte(v.Type().Field(i).Name)) - w.Write([]byte{':'}) + w.WriteString(v.Type().Field(i).Name) + w.WriteByte(':') stringifyValue(w, fv) } - w.Write([]byte{'}'}) + w.WriteByte('}') default: if v.CanInterface() { fmt.Fprint(w, v.Interface()) diff --git a/vendor/github.com/google/go-github/v68/github/teams.go b/vendor/github.com/google/go-github/v68/github/teams.go new file mode 100644 index 00000000..579e5b82 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams.go @@ -0,0 +1,1100 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// TeamsService provides access to the team-related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/teams/ +type TeamsService service + +// Team represents a team within a GitHub organization. Teams are used to +// manage access to an organization's repositories. +type Team struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission specifies the default permission for repositories owned by the team. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + MembersCount *int `json:"members_count,omitempty"` + ReposCount *int `json:"repos_count,omitempty"` + Organization *Organization `json:"organization,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + Parent *Team `json:"parent,omitempty"` + + // LDAPDN is only available in GitHub Enterprise and when the team + // membership is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` + + // Permissions identifies the permissions that a team has on a given + // repository. This is only populated when calling Repositories.ListTeams. + Permissions map[string]bool `json:"permissions,omitempty"` + + // Assignment identifies how a team was assigned to an organization role. Its + // possible values are: "direct", "indirect", "mixed". This is only populated when + // calling the ListTeamsAssignedToOrgRole method. + Assignment *string `json:"assignment,omitempty"` +} + +func (t Team) String() string { + return Stringify(t) +} + +// Invitation represents a team member's invitation status. +type Invitation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` + // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. + Role *string `json:"role,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Inviter *User `json:"inviter,omitempty"` + TeamCount *int `json:"team_count,omitempty"` + InvitationTeamURL *string `json:"invitation_team_url,omitempty"` + FailedAt *Timestamp `json:"failed_at,omitempty"` + FailedReason *string `json:"failed_reason,omitempty"` +} + +func (i Invitation) String() string { + return Stringify(i) +} + +// ListTeams lists all of the teams for an organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams +// +//meta:operation GET /orgs/{org}/teams +func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// GetTeamByID fetches a team, given a specified organization ID, by ID. +// +// Deprecated: Use GetTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name +// +//meta:operation GET /orgs/{org}/teams/{team_slug} +func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamBySlug fetches a team, given a specified organization name, by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#get-a-team-by-name +// +//meta:operation GET /orgs/{org}/teams/{team_slug} +func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// NewTeam represents a team to be created or modified. +type NewTeam struct { + Name string `json:"name"` // Name of the team. (Required.) + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id,omitempty"` + + // NotificationSetting can be one of: "notifications_enabled", "notifications_disabled". + NotificationSetting *string `json:"notification_setting,omitempty"` + + // Deprecated: Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + // LDAPDN may be used in GitHub Enterprise when the team membership + // is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (s NewTeam) String() string { + return Stringify(s) +} + +// CreateTeam creates a new team within an organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#create-a-team +// +//meta:operation POST /orgs/{org}/teams +func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + req, err := s.client.NewRequest("POST", u, team) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// newTeamNoParent is the same as NewTeam but ensures that the +// "parent_team_id" field will be null. It is for internal use +// only and should not be exported. +type newTeamNoParent struct { + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id"` // This will be "null" + NotificationSetting *string `json:"notification_setting,omitempty"` + Privacy *string `json:"privacy,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +// copyNewTeamWithoutParent is used to set the "parent_team_id" +// field to "null" after copying the other fields from a NewTeam. +// It is for internal use only and should not be exported. +func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent { + return &newTeamNoParent{ + Name: team.Name, + Description: team.Description, + Maintainers: team.Maintainers, + RepoNames: team.RepoNames, + NotificationSetting: team.NotificationSetting, + Privacy: team.Privacy, + LDAPDN: team.LDAPDN, + } +} + +// EditTeamByID edits a team, given an organization ID, selected by ID. +// +// Deprecated: Use EditTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug} +func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// EditTeamBySlug edits a team, given an organization name, by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#update-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug} +func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// DeleteTeamByID deletes a team referenced by ID. +// +// Deprecated: Use DeleteTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug} +func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteTeamBySlug deletes a team reference by slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#delete-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug} +func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListChildTeamsByParentID lists child teams for a parent team given parent ID. +// +// Deprecated: Use ListChildTeamsByParentSlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/teams +func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListChildTeamsByParentSlug lists child teams for a parent team given parent slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-child-teams +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/teams +func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamReposByID lists the repositories given a team ID that the specified team has access to. +// +// Deprecated: Use ListTeamReposBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos +func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-repositories +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos +func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsTeamRepoByID checks if a team, given its ID, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// Deprecated: Use IsTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeOrgPermissionRepo) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// IsTeamRepoBySlug checks if a team, given its slug, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-repository +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeOrgPermissionRepo) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// TeamAddTeamRepoOptions specifies the optional parameters to the +// TeamsService.AddTeamRepoByID and TeamsService.AddTeamRepoBySlug methods. +type TeamAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. + // + // If not specified, the team's permission attribute will be used. + Permission string `json:"permission,omitempty"` +} + +// AddTeamRepoByID adds a repository to be managed by the specified team given the team ID. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// Deprecated: Use AddTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-repository-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoByID removes a repository from being managed by the specified +// team given the team ID. Note that this does not delete the repository, it +// just removes it from the team. +// +// Deprecated: Use RemoveTeamRepoBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoBySlug removes a repository from being managed by the specified +// team given the team slug. Note that this does not delete the repository, it +// just removes it from the team. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-repository-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo} +func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListUserTeams lists a user's teams +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-teams-for-the-authenticated-user +// +//meta:operation GET /user/teams +func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) { + u := "user/teams" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamProjectsByID lists the organization projects for a team given the team ID. +// +// Deprecated: Use ListTeamProjectsBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects +func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*ProjectV2, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*ProjectV2 + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ListTeamProjectsBySlug lists the organization projects for a team given the team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#list-team-projects +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects +func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*ProjectV2, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*ProjectV2 + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin +// permissions for an organization project. +// +// Deprecated: Use ReviewTeamProjectsBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*ProjectV2, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + projects := &ProjectV2{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin +// permissions for an organization project. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#check-team-permissions-for-a-project +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*ProjectV2, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + projects := &ProjectV2{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// TeamProjectOptions specifies the optional parameters to the +// TeamsService.AddTeamProject method. +type TeamProjectOptions struct { + // Permission specifies the permission to grant to the team for this project. + // Possible values are: + // "read" - team members can read, but not write to or administer this project. + // "write" - team members can read and write, but not administer this project. + // "admin" - team members can read, write and administer this project. + // + Permission *string `json:"permission,omitempty"` +} + +// AddTeamProjectByID adds an organization project to a team given the team ID. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// Deprecated: Use AddTeamProjectBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// AddTeamProjectBySlug adds an organization project to a team given the team slug. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#add-or-update-team-project-permissions +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectByID removes an organization project from a team given team ID. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// Deprecated: Use RemoveTeamProjectBySlug instead. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectBySlug removes an organization project from a team given team slug. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// GitHub API docs: https://docs.github.com/rest/teams/teams#remove-a-project-from-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id} +func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListIDPGroupsOptions specifies the optional parameters to the ListIDPGroupsInOrganization method. +type ListIDPGroupsOptions struct { + // Filters the results to return only those that begin with the value specified by this parameter. + Query string `url:"q,omitempty"` + + ListCursorOptions +} + +// IDPGroupList represents a list of external identity provider (IDP) groups. +type IDPGroupList struct { + Groups []*IDPGroup `json:"groups"` +} + +// IDPGroup represents an external identity provider (IDP) group. +type IDPGroup struct { + GroupID *string `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + GroupDescription *string `json:"group_description,omitempty"` +} + +// ListIDPGroupsInOrganization lists IDP groups available in an organization. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-an-organization +// +//meta:operation GET /orgs/{org}/team-sync/groups +func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListIDPGroupsOptions) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/team-sync/groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub +// given organization and team IDs. +// +// Deprecated: Use ListIDPGroupsForTeamBySlug instead. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub +// given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#list-idp-groups-for-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection +// between a team and an IDP group given organization and team IDs. +// +// Deprecated: Use CreateOrUpdateIDPGroupConnectionsBySlug instead. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection +// between a team and an IDP group given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/team-sync#create-or-update-idp-group-connections +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/team-sync/group-mappings +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ExternalGroupMember represents a member of an external group. +type ExternalGroupMember struct { + MemberID *int64 `json:"member_id,omitempty"` + MemberLogin *string `json:"member_login,omitempty"` + MemberName *string `json:"member_name,omitempty"` + MemberEmail *string `json:"member_email,omitempty"` +} + +// ExternalGroupTeam represents a team connected to an external group. +type ExternalGroupTeam struct { + TeamID *int64 `json:"team_id,omitempty"` + TeamName *string `json:"team_name,omitempty"` +} + +// ExternalGroup represents an external group. +type ExternalGroup struct { + GroupID *int64 `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Teams []*ExternalGroupTeam `json:"teams,omitempty"` + Members []*ExternalGroupMember `json:"members,omitempty"` +} + +// ExternalGroupList represents a list of external groups. +type ExternalGroupList struct { + Groups []*ExternalGroup `json:"groups"` +} + +// GetExternalGroup fetches an external group. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group +// +//meta:operation GET /orgs/{org}/external-group/{group_id} +func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// ListExternalGroupsOptions specifies the optional parameters to the +// TeamsService.ListExternalGroups method. +type ListExternalGroupsOptions struct { + DisplayName *string `url:"display_name,omitempty"` + + ListOptions +} + +// ListExternalGroups lists external groups in an organization on GitHub. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization +// +//meta:operation GET /orgs/{org}/external-groups +func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroups := new(ExternalGroupList) + resp, err := s.client.Do(ctx, req, externalGroups) + if err != nil { + return nil, resp, err + } + + return externalGroups, resp, nil +} + +// ListExternalGroupsForTeamBySlug lists external groups connected to a team on GitHub. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) ListExternalGroupsForTeamBySlug(ctx context.Context, org, slug string) (*ExternalGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroups := new(ExternalGroupList) + resp, err := s.client.Do(ctx, req, externalGroups) + if err != nil { + return nil, resp, err + } + + return externalGroups, resp, nil +} + +// UpdateConnectedExternalGroup updates the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#update-the-connection-between-an-external-group-and-a-team +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("PATCH", u, eg) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// RemoveConnectedExternalGroup removes the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/teams/external-groups#remove-the-connection-between-an-external-group-and-a-team +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/external-groups +func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go new file mode 100644 index 00000000..eba6fdf4 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go @@ -0,0 +1,262 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DiscussionComment represents a GitHub discussion in a team. +type DiscussionComment struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + DiscussionURL *string `json:"discussion_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (c DiscussionComment) String() string { + return Stringify(c) +} + +// DiscussionCommentListOptions specifies optional parameters to the +// TeamServices.ListComments method. +type DiscussionCommentListOptions struct { + // Sorts the discussion comments by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + ListOptions +} + +// ListCommentsByID lists all comments on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#list-discussion-comments +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) ListCommentsByID(ctx context.Context, orgID, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommentsBySlug lists all comments on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#list-discussion-comments +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) ListCommentsBySlug(ctx context.Context, org, slug string, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetCommentByID gets a specific comment on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#get-a-discussion-comment +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) GetCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// GetCommentBySlug gets a specific comment on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#get-a-discussion-comment +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) GetCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentByID creates a new comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#create-a-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) CreateCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentBySlug creates a new comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#create-a-discussion-comment +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments +func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discsusionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentByID edits the body text of a discussion comment by team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#update-a-discussion-comment +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) EditCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentBySlug edits the body text of a discussion comment by team slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#update-a-discussion-comment +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) EditCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// DeleteCommentByID deletes a comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#delete-a-discussion-comment +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) DeleteCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteCommentBySlug deletes a comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#delete-a-discussion-comment +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number} +func (s *TeamsService) DeleteCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussions.go b/vendor/github.com/google/go-github/v68/github/teams_discussions.go new file mode 100644 index 00000000..b056525f --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_discussions.go @@ -0,0 +1,267 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamDiscussion represents a GitHub discussion in a team. +type TeamDiscussion struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CommentsCount *int `json:"comments_count,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Pinned *bool `json:"pinned,omitempty"` + Private *bool `json:"private,omitempty"` + TeamURL *string `json:"team_url,omitempty"` + Title *string `json:"title,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (d TeamDiscussion) String() string { + return Stringify(d) +} + +// DiscussionListOptions specifies optional parameters to the +// TeamServices.ListDiscussions method. +type DiscussionListOptions struct { + // Sorts the discussion by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListDiscussionsByID lists all discussions on team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#list-discussions +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) ListDiscussionsByID(ctx context.Context, orgID, teamID int64, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// ListDiscussionsBySlug lists all discussions on team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#list-discussions +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) ListDiscussionsBySlug(ctx context.Context, org, slug string, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// GetDiscussionByID gets a specific discussion on a team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#get-a-discussion +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) GetDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// GetDiscussionBySlug gets a specific discussion on a team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#get-a-discussion +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) GetDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionByID creates a new discussion post on a team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#create-a-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) CreateDiscussionByID(ctx context.Context, orgID, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionBySlug creates a new discussion post on a team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#create-a-discussion +// +//meta:operation POST /orgs/{org}/teams/{team_slug}/discussions +func (s *TeamsService) CreateDiscussionBySlug(ctx context.Context, org, slug string, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionByID edits the title and body text of a discussion post given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#update-a-discussion +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) EditDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionBySlug edits the title and body text of a discussion post given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#update-a-discussion +// +//meta:operation PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) EditDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// DeleteDiscussionByID deletes a discussion from team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#delete-a-discussion +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) DeleteDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteDiscussionBySlug deletes a discussion from team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/rest/teams/discussions#delete-a-discussion +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number} +func (s *TeamsService) DeleteDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/teams_members.go b/vendor/github.com/google/go-github/v68/github/teams_members.go new file mode 100644 index 00000000..059d993a --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/teams_members.go @@ -0,0 +1,263 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamListTeamMembersOptions specifies the optional parameters to the +// TeamsService.ListTeamMembers method. +type TeamListTeamMembersOptions struct { + // Role filters members returned by their role in the team. Possible + // values are "all", "member", "maintainer". Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListTeamMembersByID lists all of the users who are members of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) ListTeamMembersByID(ctx context.Context, orgID, teamID int64, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/members", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// ListTeamMembersBySlug lists all of the users who are members of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) ListTeamMembersBySlug(ctx context.Context, org, slug string, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/members", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// GetTeamMembershipByID returns the membership status for a user in a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-team-members +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/members +func (s *TeamsService) GetTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamMembershipBySlug returns the membership status for a user in a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#get-team-membership-for-a-user +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) GetTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// TeamAddTeamMembershipOptions specifies the optional +// parameters to the TeamsService.AddTeamMembership method. +type TeamAddTeamMembershipOptions struct { + // Role specifies the role the user should have in the team. Possible + // values are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + // + // Default value is "member". + Role string `json:"role,omitempty"` +} + +// AddTeamMembershipByID adds or invites a user to a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#add-or-update-team-membership-for-a-user +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) AddTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// AddTeamMembershipBySlug adds or invites a user to a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#add-or-update-team-membership-for-a-user +// +//meta:operation PUT /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) AddTeamMembershipBySlug(ctx context.Context, org, slug, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// RemoveTeamMembershipByID removes a user from a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#remove-team-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) RemoveTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamMembershipBySlug removes a user from a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#remove-team-membership-for-a-user +// +//meta:operation DELETE /orgs/{org}/teams/{team_slug}/memberships/{username} +func (s *TeamsService) RemoveTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingTeamInvitationsByID gets pending invitation list of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-pending-team-invitations +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/invitations +func (s *TeamsService) ListPendingTeamInvitationsByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/invitations", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} + +// ListPendingTeamInvitationsBySlug get pending invitation list of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/rest/teams/members#list-pending-team-invitations +// +//meta:operation GET /orgs/{org}/teams/{team_slug}/invitations +func (s *TeamsService) ListPendingTeamInvitationsBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/invitations", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/timestamp.go b/vendor/github.com/google/go-github/v68/github/timestamp.go similarity index 80% rename from vendor/github.com/google/go-github/github/timestamp.go rename to vendor/github.com/google/go-github/v68/github/timestamp.go index 90929d57..dc1045cf 100644 --- a/vendor/github.com/google/go-github/github/timestamp.go +++ b/vendor/github.com/google/go-github/v68/github/timestamp.go @@ -22,6 +22,14 @@ func (t Timestamp) String() string { return t.Time.String() } +// GetTime returns std time.Time. +func (t *Timestamp) GetTime() *time.Time { + if t == nil { + return nil + } + return &t.Time +} + // UnmarshalJSON implements the json.Unmarshaler interface. // Time is expected in RFC3339 or Unix format. func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { @@ -29,13 +37,16 @@ func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { i, err := strconv.ParseInt(str, 10, 64) if err == nil { t.Time = time.Unix(i, 0) + if t.Time.Year() > 3000 { + t.Time = time.Unix(0, i*1e6) + } } else { t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) } return } -// Equal reports whether t and u are equal based on time.Equal +// Equal reports whether t and u are equal based on time.Equal. func (t Timestamp) Equal(u Timestamp) bool { return t.Time.Equal(u.Time) } diff --git a/vendor/github.com/google/go-github/github/users.go b/vendor/github.com/google/go-github/v68/github/users.go similarity index 54% rename from vendor/github.com/google/go-github/github/users.go rename to vendor/github.com/google/go-github/v68/github/users.go index f164d559..60f1e06a 100644 --- a/vendor/github.com/google/go-github/github/users.go +++ b/vendor/github.com/google/go-github/v68/github/users.go @@ -13,39 +13,42 @@ import ( // UsersService handles communication with the user related // methods of the GitHub API. // -// GitHub API docs: https://developer.github.com/v3/users/ +// GitHub API docs: https://docs.github.com/rest/users/ type UsersService service // User represents a GitHub user. type User struct { - Login *string `json:"login,omitempty"` - ID *int64 `json:"id,omitempty"` - NodeID *string `json:"node_id,omitempty"` - AvatarURL *string `json:"avatar_url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - GravatarID *string `json:"gravatar_id,omitempty"` - Name *string `json:"name,omitempty"` - Company *string `json:"company,omitempty"` - Blog *string `json:"blog,omitempty"` - Location *string `json:"location,omitempty"` - Email *string `json:"email,omitempty"` - Hireable *bool `json:"hireable,omitempty"` - Bio *string `json:"bio,omitempty"` - PublicRepos *int `json:"public_repos,omitempty"` - PublicGists *int `json:"public_gists,omitempty"` - Followers *int `json:"followers,omitempty"` - Following *int `json:"following,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - SuspendedAt *Timestamp `json:"suspended_at,omitempty"` - Type *string `json:"type,omitempty"` - SiteAdmin *bool `json:"site_admin,omitempty"` - TotalPrivateRepos *int `json:"total_private_repos,omitempty"` - OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` - PrivateGists *int `json:"private_gists,omitempty"` - DiskUsage *int `json:"disk_usage,omitempty"` - Collaborators *int `json:"collaborators,omitempty"` - Plan *Plan `json:"plan,omitempty"` + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + Hireable *bool `json:"hireable,omitempty"` + Bio *string `json:"bio,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + TotalPrivateRepos *int64 `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int64 `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + TwoFactorAuthentication *bool `json:"two_factor_authentication,omitempty"` + Plan *Plan `json:"plan,omitempty"` + LdapDn *string `json:"ldap_dn,omitempty"` // API URLs URL *string `json:"url,omitempty"` @@ -60,12 +63,21 @@ type User struct { SubscriptionsURL *string `json:"subscriptions_url,omitempty"` // TextMatches is only populated from search results that request text matches - // See: search.go and https://developer.github.com/v3/search/#text-match-metadata - TextMatches []TextMatch `json:"text_matches,omitempty"` - - // Permissions identifies the permissions that a user has on a given - // repository. This is only populated when calling Repositories.ListCollaborators. - Permissions *map[string]bool `json:"permissions,omitempty"` + // See: search.go and https://docs.github.com/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Permissions and RoleName identify the permissions and role that a user has on a given + // repository. These are only populated when calling Repositories.ListCollaborators. + Permissions map[string]bool `json:"permissions,omitempty"` + RoleName *string `json:"role_name,omitempty"` + + // Assignment identifies how a user was assigned to an organization role. Its + // possible values are: "direct", "indirect", "mixed". This is only populated when + // calling the ListUsersAssignedToOrgRole method. + Assignment *string `json:"assignment,omitempty"` + // InheritedFrom identifies the team that a user inherited their organization role + // from. This is only populated when calling the ListUsersAssignedToOrgRole method. + InheritedFrom *Team `json:"inherited_from,omitempty"` } func (u User) String() string { @@ -75,7 +87,11 @@ func (u User) String() string { // Get fetches a user. Passing the empty string will fetch the authenticated // user. // -// GitHub API docs: https://developer.github.com/v3/users/#get-a-single-user +// GitHub API docs: https://docs.github.com/rest/users/users#get-a-user +// GitHub API docs: https://docs.github.com/rest/users/users#get-the-authenticated-user +// +//meta:operation GET /user +//meta:operation GET /users/{username} func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { var u string if user != "" { @@ -99,7 +115,9 @@ func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, // GetByID fetches a user. // -// Note: GetByID uses the undocumented GitHub API endpoint /user/:id. +// GitHub API docs: https://docs.github.com/rest/users/users#get-a-user-using-their-id +// +//meta:operation GET /user/{account_id} func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) { u := fmt.Sprintf("user/%d", id) req, err := s.client.NewRequest("GET", u, nil) @@ -118,7 +136,9 @@ func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, // Edit the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/#update-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/users/users#update-the-authenticated-user +// +//meta:operation PATCH /user func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) { u := "user" req, err := s.client.NewRequest("PATCH", u, user) @@ -160,10 +180,12 @@ type UserContext struct { // GetHovercard fetches contextual information about user. It requires authentication // via Basic Auth or via OAuth with the repo scope. // -// GitHub API docs: https://developer.github.com/v3/users/#get-contextual-information-about-a-user -func (s *UsersService) GetHovercard(ctx context.Context, user string, opt *HovercardOptions) (*Hovercard, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/users#get-contextual-information-for-a-user +// +//meta:operation GET /users/{username}/hovercard +func (s *UsersService) GetHovercard(ctx context.Context, user string, opts *HovercardOptions) (*Hovercard, *Response, error) { u := fmt.Sprintf("users/%v/hovercard", user) - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -173,9 +195,6 @@ func (s *UsersService) GetHovercard(ctx context.Context, user string, opt *Hover return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeHovercardPreview) - hc := new(Hovercard) resp, err := s.client.Do(ctx, req, hc) if err != nil { @@ -201,9 +220,11 @@ type UserListOptions struct { // // To paginate through all users, populate 'Since' with the ID of the last user. // -// GitHub API docs: https://developer.github.com/v3/users/#get-all-users -func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) ([]*User, *Response, error) { - u, err := addOptions("users", opt) +// GitHub API docs: https://docs.github.com/rest/users/users#list-users +// +//meta:operation GET /users +func (s *UsersService) ListAll(ctx context.Context, opts *UserListOptions) ([]*User, *Response, error) { + u, err := addOptions("users", opts) if err != nil { return nil, nil, err } @@ -225,9 +246,11 @@ func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) ([]*Us // ListInvitations lists all currently-open repository invitations for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-a-users-repository-invitations -func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { - u, err := addOptions("user/repository_invitations", opt) +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#list-repository-invitations-for-the-authenticated-user +// +//meta:operation GET /user/repository_invitations +func (s *UsersService) ListInvitations(ctx context.Context, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u, err := addOptions("user/repository_invitations", opts) if err != nil { return nil, nil, err } @@ -237,9 +260,6 @@ func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([ return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - invites := []*RepositoryInvitation{} resp, err := s.client.Do(ctx, req, &invites) if err != nil { @@ -252,7 +272,9 @@ func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([ // AcceptInvitation accepts the currently-open repository invitation for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#accept-a-repository-invitation +// +//meta:operation PATCH /user/repository_invitations/{invitation_id} func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) { u := fmt.Sprintf("user/repository_invitations/%v", invitationID) req, err := s.client.NewRequest("PATCH", u, nil) @@ -260,16 +282,15 @@ func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - return s.client.Do(ctx, req, nil) } // DeclineInvitation declines the currently-open repository invitation for the // authenticated user. // -// GitHub API docs: https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation +// GitHub API docs: https://docs.github.com/rest/collaborators/invitations#decline-a-repository-invitation +// +//meta:operation DELETE /user/repository_invitations/{invitation_id} func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) { u := fmt.Sprintf("user/repository_invitations/%v", invitationID) req, err := s.client.NewRequest("DELETE", u, nil) @@ -277,8 +298,5 @@ func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64 return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) - return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/github/users_administration.go b/vendor/github.com/google/go-github/v68/github/users_administration.go similarity index 58% rename from vendor/github.com/google/go-github/github/users_administration.go rename to vendor/github.com/google/go-github/v68/github/users_administration.go index e042398d..c0aa3b64 100644 --- a/vendor/github.com/google/go-github/github/users_administration.go +++ b/vendor/github.com/google/go-github/v68/github/users_administration.go @@ -12,7 +12,9 @@ import ( // PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. // -// GitHub API docs: https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#promote-a-user-to-be-a-site-administrator +// +//meta:operation PUT /users/{username}/site_admin func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/site_admin", user) @@ -26,7 +28,9 @@ func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Resp // DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. // -// GitHub API docs: https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#demote-a-site-administrator +// +//meta:operation DELETE /users/{username}/site_admin func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/site_admin", user) @@ -38,13 +42,20 @@ func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Respo return s.client.Do(ctx, req, nil) } +// UserSuspendOptions represents the reason a user is being suspended. +type UserSuspendOptions struct { + Reason *string `json:"reason,omitempty"` +} + // Suspend a user on a GitHub Enterprise instance. // -// GitHub API docs: https://developer.github.com/v3/users/administration/#suspend-a-user -func (s *UsersService) Suspend(ctx context.Context, user string) (*Response, error) { +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#suspend-a-user +// +//meta:operation PUT /users/{username}/suspended +func (s *UsersService) Suspend(ctx context.Context, user string, opts *UserSuspendOptions) (*Response, error) { u := fmt.Sprintf("users/%v/suspended", user) - req, err := s.client.NewRequest("PUT", u, nil) + req, err := s.client.NewRequest("PUT", u, opts) if err != nil { return nil, err } @@ -54,7 +65,9 @@ func (s *UsersService) Suspend(ctx context.Context, user string) (*Response, err // Unsuspend a user on a GitHub Enterprise instance. // -// GitHub API docs: https://developer.github.com/v3/users/administration/#unsuspend-a-user +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/users#unsuspend-a-user +// +//meta:operation DELETE /users/{username}/suspended func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("users/%v/suspended", user) diff --git a/vendor/github.com/google/go-github/v68/github/users_attestations.go b/vendor/github.com/google/go-github/v68/github/users_attestations.go new file mode 100644 index 00000000..18f60298 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_attestations.go @@ -0,0 +1,40 @@ +// Copyright 2024 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAttestations returns a collection of artifact attestations +// with a given subject digest that are associated with repositories +// owned by a user. +// +// GitHub API docs: https://docs.github.com/rest/users/attestations#list-attestations +// +//meta:operation GET /users/{username}/attestations/{subject_digest} +func (s *UsersService) ListAttestations(ctx context.Context, user, subjectDigest string, opts *ListOptions) (*AttestationsResponse, *Response, error) { + var u = fmt.Sprintf("users/%v/attestations/%v", user, subjectDigest) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var attestations *AttestationsResponse + res, err := s.client.Do(ctx, req, &attestations) + if err != nil { + return nil, res, err + } + + return attestations, res, nil +} diff --git a/vendor/github.com/google/go-github/github/users_blocking.go b/vendor/github.com/google/go-github/v68/github/users_blocking.go similarity index 77% rename from vendor/github.com/google/go-github/github/users_blocking.go rename to vendor/github.com/google/go-github/v68/github/users_blocking.go index 39e45601..3f2af38f 100644 --- a/vendor/github.com/google/go-github/github/users_blocking.go +++ b/vendor/github.com/google/go-github/v68/github/users_blocking.go @@ -12,10 +12,12 @@ import ( // ListBlockedUsers lists all the blocked users by the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/blocking/#list-blocked-users -func (s *UsersService) ListBlockedUsers(ctx context.Context, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/blocking#list-users-blocked-by-the-authenticated-user +// +//meta:operation GET /user/blocks +func (s *UsersService) ListBlockedUsers(ctx context.Context, opts *ListOptions) ([]*User, *Response, error) { u := "user/blocks" - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -39,7 +41,9 @@ func (s *UsersService) ListBlockedUsers(ctx context.Context, opt *ListOptions) ( // IsBlocked reports whether specified user is blocked by the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/blocking/#check-whether-youve-blocked-a-user +// GitHub API docs: https://docs.github.com/rest/users/blocking#check-if-a-user-is-blocked-by-the-authenticated-user +// +//meta:operation GET /user/blocks/{username} func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) { u := fmt.Sprintf("user/blocks/%v", user) @@ -58,7 +62,9 @@ func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Respo // BlockUser blocks specified user for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/blocking/#block-a-user +// GitHub API docs: https://docs.github.com/rest/users/blocking#block-a-user +// +//meta:operation PUT /user/blocks/{username} func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/blocks/%v", user) @@ -75,7 +81,9 @@ func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, e // UnblockUser unblocks specified user for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/blocking/#unblock-a-user +// GitHub API docs: https://docs.github.com/rest/users/blocking#unblock-a-user +// +//meta:operation DELETE /user/blocks/{username} func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/blocks/%v", user) diff --git a/vendor/github.com/google/go-github/v68/github/users_emails.go b/vendor/github.com/google/go-github/v68/github/users_emails.go new file mode 100644 index 00000000..3d0e1bfa --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_emails.go @@ -0,0 +1,105 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// UserEmail represents user's email address. +type UserEmail struct { + Email *string `json:"email,omitempty"` + Primary *bool `json:"primary,omitempty"` + Verified *bool `json:"verified,omitempty"` + Visibility *string `json:"visibility,omitempty"` +} + +// ListEmails lists all email addresses for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#list-email-addresses-for-the-authenticated-user +// +//meta:operation GET /user/emails +func (s *UsersService) ListEmails(ctx context.Context, opts *ListOptions) ([]*UserEmail, *Response, error) { + u := "user/emails" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var emails []*UserEmail + resp, err := s.client.Do(ctx, req, &emails) + if err != nil { + return nil, resp, err + } + + return emails, resp, nil +} + +// AddEmails adds email addresses of the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#add-an-email-address-for-the-authenticated-user +// +//meta:operation POST /user/emails +func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("POST", u, emails) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} + +// DeleteEmails deletes email addresses from authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/emails#delete-an-email-address-for-the-authenticated-user +// +//meta:operation DELETE /user/emails +func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("DELETE", u, emails) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetEmailVisibility sets the visibility for the primary email address of the authenticated user. +// `visibility` can be "private" or "public". +// +// GitHub API docs: https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user +// +//meta:operation PATCH /user/email/visibility +func (s *UsersService) SetEmailVisibility(ctx context.Context, visibility string) ([]*UserEmail, *Response, error) { + u := "user/email/visibility" + + updateVisibilityReq := &UserEmail{ + Visibility: &visibility, + } + + req, err := s.client.NewRequest("PATCH", u, updateVisibilityReq) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/users_followers.go b/vendor/github.com/google/go-github/v68/github/users_followers.go similarity index 66% rename from vendor/github.com/google/go-github/github/users_followers.go rename to vendor/github.com/google/go-github/v68/github/users_followers.go index c2224096..ec6f531e 100644 --- a/vendor/github.com/google/go-github/github/users_followers.go +++ b/vendor/github.com/google/go-github/v68/github/users_followers.go @@ -13,15 +13,19 @@ import ( // ListFollowers lists the followers for a user. Passing the empty string will // fetch followers for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-a-user -func (s *UsersService) ListFollowers(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/followers#list-followers-of-a-user +// GitHub API docs: https://docs.github.com/rest/users/followers#list-followers-of-the-authenticated-user +// +//meta:operation GET /user/followers +//meta:operation GET /users/{username}/followers +func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/followers", user) } else { u = "user/followers" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -43,15 +47,19 @@ func (s *UsersService) ListFollowers(ctx context.Context, user string, opt *List // ListFollowing lists the people that a user is following. Passing the empty // string will list people the authenticated user is following. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user -func (s *UsersService) ListFollowing(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/followers#list-the-people-a-user-follows +// GitHub API docs: https://docs.github.com/rest/users/followers#list-the-people-the-authenticated-user-follows +// +//meta:operation GET /user/following +//meta:operation GET /users/{username}/following +func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/following", user) } else { u = "user/following" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -73,7 +81,11 @@ func (s *UsersService) ListFollowing(ctx context.Context, user string, opt *List // IsFollowing checks if "user" is following "target". Passing the empty // string for "user" will check if the authenticated user is following "target". // -// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user +// GitHub API docs: https://docs.github.com/rest/users/followers#check-if-a-person-is-followed-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/users/followers#check-if-a-user-follows-another-user +// +//meta:operation GET /user/following/{username} +//meta:operation GET /users/{username}/following/{target_user} func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { var u string if user != "" { @@ -94,7 +106,9 @@ func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bo // Follow will cause the authenticated user to follow the specified user. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#follow-a-user +// GitHub API docs: https://docs.github.com/rest/users/followers#follow-a-user +// +//meta:operation PUT /user/following/{username} func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/following/%v", user) req, err := s.client.NewRequest("PUT", u, nil) @@ -107,7 +121,9 @@ func (s *UsersService) Follow(ctx context.Context, user string) (*Response, erro // Unfollow will cause the authenticated user to unfollow the specified user. // -// GitHub API docs: https://developer.github.com/v3/users/followers/#unfollow-a-user +// GitHub API docs: https://docs.github.com/rest/users/followers#unfollow-a-user +// +//meta:operation DELETE /user/following/{username} func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) { u := fmt.Sprintf("user/following/%v", user) req, err := s.client.NewRequest("DELETE", u, nil) diff --git a/vendor/github.com/google/go-github/github/users_gpg_keys.go b/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go similarity index 61% rename from vendor/github.com/google/go-github/github/users_gpg_keys.go rename to vendor/github.com/google/go-github/v68/github/users_gpg_keys.go index d8bbc520..2f296a1e 100644 --- a/vendor/github.com/google/go-github/github/users_gpg_keys.go +++ b/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go @@ -8,25 +8,25 @@ package github import ( "context" "fmt" - "time" ) // GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. // // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ type GPGKey struct { - ID *int64 `json:"id,omitempty"` - PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` - KeyID *string `json:"key_id,omitempty"` - PublicKey *string `json:"public_key,omitempty"` - Emails []GPGEmail `json:"emails,omitempty"` - Subkeys []GPGKey `json:"subkeys,omitempty"` - CanSign *bool `json:"can_sign,omitempty"` - CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` - CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` - CanCertify *bool `json:"can_certify,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - ExpiresAt *time.Time `json:"expires_at,omitempty"` + ID *int64 `json:"id,omitempty"` + PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` + KeyID *string `json:"key_id,omitempty"` + RawKey *string `json:"raw_key,omitempty"` + PublicKey *string `json:"public_key,omitempty"` + Emails []*GPGEmail `json:"emails,omitempty"` + Subkeys []*GPGKey `json:"subkeys,omitempty"` + CanSign *bool `json:"can_sign,omitempty"` + CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` + CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` + CanCertify *bool `json:"can_certify,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` } // String stringifies a GPGKey. @@ -44,15 +44,19 @@ type GPGEmail struct { // string will fetch keys for the authenticated user. It requires authentication // via Basic Auth or via OAuth with at least read:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user -func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOptions) ([]*GPGKey, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#list-gpg-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#list-gpg-keys-for-the-authenticated-user +// +//meta:operation GET /user/gpg_keys +//meta:operation GET /users/{username}/gpg_keys +func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/gpg_keys", user) } else { u = "user/gpg_keys" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -62,9 +66,6 @@ func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOp return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - var keys []*GPGKey resp, err := s.client.Do(ctx, req, &keys) if err != nil { @@ -77,7 +78,9 @@ func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOp // GetGPGKey gets extended details for a single GPG key. It requires authentication // via Basic Auth or via OAuth with at least read:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#get-a-gpg-key-for-the-authenticated-user +// +//meta:operation GET /user/gpg_keys/{gpg_key_id} func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) { u := fmt.Sprintf("user/gpg_keys/%v", id) req, err := s.client.NewRequest("GET", u, nil) @@ -85,9 +88,6 @@ func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Respo return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - key := &GPGKey{} resp, err := s.client.Do(ctx, req, key) if err != nil { @@ -97,10 +97,12 @@ func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Respo return key, resp, nil } -// CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth +// CreateGPGKey creates a GPG key. It requires authentication via Basic Auth // or OAuth with at least write:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#create-a-gpg-key-for-the-authenticated-user +// +//meta:operation POST /user/gpg_keys func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) { gpgKey := &struct { ArmoredPublicKey string `json:"armored_public_key"` @@ -110,9 +112,6 @@ func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string return nil, nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - key := &GPGKey{} resp, err := s.client.Do(ctx, req, key) if err != nil { @@ -125,7 +124,9 @@ func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string // DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or // via OAuth with at least admin:gpg_key scope. // -// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key +// GitHub API docs: https://docs.github.com/rest/users/gpg-keys#delete-a-gpg-key-for-the-authenticated-user +// +//meta:operation DELETE /user/gpg_keys/{gpg_key_id} func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("user/gpg_keys/%v", id) req, err := s.client.NewRequest("DELETE", u, nil) @@ -133,8 +134,5 @@ func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, e return nil, err } - // TODO: remove custom Accept header when this API fully launches. - req.Header.Set("Accept", mediaTypeGitSigningPreview) - return s.client.Do(ctx, req, nil) } diff --git a/vendor/github.com/google/go-github/github/users_keys.go b/vendor/github.com/google/go-github/v68/github/users_keys.go similarity index 61% rename from vendor/github.com/google/go-github/github/users_keys.go rename to vendor/github.com/google/go-github/v68/github/users_keys.go index ddc832a1..4d42986e 100644 --- a/vendor/github.com/google/go-github/github/users_keys.go +++ b/vendor/github.com/google/go-github/v68/github/users_keys.go @@ -12,11 +12,15 @@ import ( // Key represents a public SSH key used to authenticate a user or deploy script. type Key struct { - ID *int64 `json:"id,omitempty"` - Key *string `json:"key,omitempty"` - URL *string `json:"url,omitempty"` - Title *string `json:"title,omitempty"` - ReadOnly *bool `json:"read_only,omitempty"` + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Title *string `json:"title,omitempty"` + ReadOnly *bool `json:"read_only,omitempty"` + Verified *bool `json:"verified,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + AddedBy *string `json:"added_by,omitempty"` + LastUsed *Timestamp `json:"last_used,omitempty"` } func (k Key) String() string { @@ -26,15 +30,19 @@ func (k Key) String() string { // ListKeys lists the verified public keys for a user. Passing the empty // string will fetch keys for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user -func (s *UsersService) ListKeys(ctx context.Context, user string, opt *ListOptions) ([]*Key, *Response, error) { +// GitHub API docs: https://docs.github.com/rest/users/keys#list-public-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/keys#list-public-ssh-keys-for-the-authenticated-user +// +//meta:operation GET /user/keys +//meta:operation GET /users/{username}/keys +func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { var u string if user != "" { u = fmt.Sprintf("users/%v/keys", user) } else { u = "user/keys" } - u, err := addOptions(u, opt) + u, err := addOptions(u, opts) if err != nil { return nil, nil, err } @@ -55,7 +63,9 @@ func (s *UsersService) ListKeys(ctx context.Context, user string, opt *ListOptio // GetKey fetches a single public key. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#get-a-single-public-key +// GitHub API docs: https://docs.github.com/rest/users/keys#get-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation GET /user/keys/{key_id} func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) { u := fmt.Sprintf("user/keys/%v", id) @@ -75,7 +85,9 @@ func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, e // CreateKey adds a public key for the authenticated user. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#create-a-public-key +// GitHub API docs: https://docs.github.com/rest/users/keys#create-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation POST /user/keys func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) { u := "user/keys" @@ -95,7 +107,9 @@ func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response // DeleteKey deletes a public key. // -// GitHub API docs: https://developer.github.com/v3/users/keys/#delete-a-public-key +// GitHub API docs: https://docs.github.com/rest/users/keys#delete-a-public-ssh-key-for-the-authenticated-user +// +//meta:operation DELETE /user/keys/{key_id} func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) { u := fmt.Sprintf("user/keys/%v", id) diff --git a/vendor/github.com/google/go-github/v68/github/users_packages.go b/vendor/github.com/google/go-github/v68/github/users_packages.go new file mode 100644 index 00000000..3ccf68a1 --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_packages.go @@ -0,0 +1,235 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListPackages lists the packages for a user. Passing the empty string for "user" will +// list packages for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-packages-for-the-authenticated-users-namespace +// +//meta:operation GET /user/packages +//meta:operation GET /users/{username}/packages +func (s *UsersService) ListPackages(ctx context.Context, user string, opts *PackageListOptions) ([]*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages", user) + } else { + u = "user/packages" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// GetPackage gets a package by name for a user. Passing the empty string for "user" will +// get the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name} +//meta:operation GET /users/{username}/packages/{package_type}/{package_name} +func (s *UsersService) GetPackage(ctx context.Context, user, packageType, packageName string) (*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// DeletePackage deletes a package from a user. Passing the empty string for "user" will +// delete the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-the-authenticated-user +// +//meta:operation DELETE /user/packages/{package_type}/{package_name} +//meta:operation DELETE /users/{username}/packages/{package_type}/{package_name} +func (s *UsersService) DeletePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RestorePackage restores a package to a user. Passing the empty string for "user" will +// restore the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-the-authenticated-user +// +//meta:operation POST /user/packages/{package_type}/{package_name}/restore +//meta:operation POST /users/{username}/packages/{package_type}/{package_name}/restore +func (s *UsersService) RestorePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/restore", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/restore", packageType, packageName) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageGetAllVersions gets all versions of a package for a user. Passing the empty string for "user" will +// get versions for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name}/versions +//meta:operation GET /users/{username}/packages/{package_type}/{package_name}/versions +func (s *UsersService) PackageGetAllVersions(ctx context.Context, user, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions", packageType, packageName) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// PackageGetVersion gets a specific version of a package for a user. Passing the empty string for "user" will +// get the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-a-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-the-authenticated-user +// +//meta:operation GET /user/packages/{package_type}/{package_name}/versions/{package_version_id} +//meta:operation GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *UsersService) PackageGetVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// PackageDeleteVersion deletes a package version for a user. Passing the empty string for "user" will +// delete the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#delete-package-version-for-a-user +// +//meta:operation DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id} +//meta:operation DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id} +func (s *UsersService) PackageDeleteVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PackageRestoreVersion restores a package version to a user. Passing the empty string for "user" will +// restore the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/rest/packages/packages#restore-package-version-for-a-user +// +//meta:operation POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +//meta:operation POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore +func (s *UsersService) PackageRestoreVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v/restore", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v/restore", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go b/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go new file mode 100644 index 00000000..fcc930be --- /dev/null +++ b/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go @@ -0,0 +1,117 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// SSHSigningKey represents a public SSH key used to sign git commits. +type SSHSigningKey struct { + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + Title *string `json:"title,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (k SSHSigningKey) String() string { + return Stringify(k) +} + +// ListSSHSigningKeys lists the SSH signing keys for a user. Passing an empty +// username string will fetch SSH signing keys for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#list-ssh-signing-keys-for-a-user +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#list-ssh-signing-keys-for-the-authenticated-user +// +//meta:operation GET /user/ssh_signing_keys +//meta:operation GET /users/{username}/ssh_signing_keys +func (s *UsersService) ListSSHSigningKeys(ctx context.Context, user string, opts *ListOptions) ([]*SSHSigningKey, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/ssh_signing_keys", user) + } else { + u = "user/ssh_signing_keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*SSHSigningKey + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetSSHSigningKey fetches a single SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#get-an-ssh-signing-key-for-the-authenticated-user +// +//meta:operation GET /user/ssh_signing_keys/{ssh_signing_key_id} +func (s *UsersService) GetSSHSigningKey(ctx context.Context, id int64) (*SSHSigningKey, *Response, error) { + u := fmt.Sprintf("user/ssh_signing_keys/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(SSHSigningKey) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateSSHSigningKey adds a SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#create-a-ssh-signing-key-for-the-authenticated-user +// +//meta:operation POST /user/ssh_signing_keys +func (s *UsersService) CreateSSHSigningKey(ctx context.Context, key *Key) (*SSHSigningKey, *Response, error) { + u := "user/ssh_signing_keys" + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(SSHSigningKey) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteSSHSigningKey deletes a SSH signing key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/users/ssh-signing-keys#delete-an-ssh-signing-key-for-the-authenticated-user +// +//meta:operation DELETE /user/ssh_signing_keys/{ssh_signing_key_id} +func (s *UsersService) DeleteSSHSigningKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/ssh_signing_keys/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/with_appengine.go b/vendor/github.com/google/go-github/v68/github/with_appengine.go similarity index 95% rename from vendor/github.com/google/go-github/github/with_appengine.go rename to vendor/github.com/google/go-github/v68/github/with_appengine.go index 59ce26b2..9bb95b8c 100644 --- a/vendor/github.com/google/go-github/github/with_appengine.go +++ b/vendor/github.com/google/go-github/v68/github/with_appengine.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build appengine +//go:build appengine // This file provides glue for making github work on App Engine. diff --git a/vendor/github.com/google/go-github/github/without_appengine.go b/vendor/github.com/google/go-github/v68/github/without_appengine.go similarity index 94% rename from vendor/github.com/google/go-github/github/without_appengine.go rename to vendor/github.com/google/go-github/v68/github/without_appengine.go index 6f8fdac5..bfdb18ec 100644 --- a/vendor/github.com/google/go-github/github/without_appengine.go +++ b/vendor/github.com/google/go-github/v68/github/without_appengine.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +//go:build !appengine // This file provides glue for making github work without App Engine. diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go index 37080b19..91198f81 100644 --- a/vendor/github.com/google/go-querystring/query/encode.go +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -51,8 +51,8 @@ type Encoder interface { // - the field is empty and its tag specifies the "omitempty" option // // The empty values are false, 0, any nil pointer or interface value, any array -// slice, map, or string of length zero, and any time.Time that returns true -// for IsZero(). +// slice, map, or string of length zero, and any type (such as time.Time) that +// returns true for IsZero(). // // The URL parameter name defaults to the struct field name but can be // specified in the struct field's tag value. The "url" key in the struct @@ -82,7 +82,14 @@ type Encoder interface { // // time.Time values default to encoding as RFC3339 timestamps. Including the // "unix" option signals that the field should be encoded as a Unix time (see -// time.Unix()) +// time.Unix()). The "unixmilli" and "unixnano" options will encode the number +// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see +// time.UnixNano()). Including the "layout" struct tag (separate from the +// "url" tag) will use the value of the "layout" tag as a layout passed to +// time.Format. For example: +// +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` // // Slice and Array values default to encoding as multiple URL values of the // same name. Including the "comma" option signals that the field should be @@ -92,7 +99,13 @@ type Encoder interface { // Including the "brackets" option signals that the multiple URL values should // have "[]" appended to the value name. "numbered" will append a number to // the end of each incidence of the value name, example: -// name0=value0&name1=value1, etc. +// name0=value0&name1=value1, etc. Including the "del" struct tag (separate +// from the "url" tag) will use the value of the "del" tag as the delimiter. +// For example: +// +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the standard Go @@ -151,11 +164,15 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } name, opts := parseTag(tag) + if name == "" { - if sf.Anonymous && sv.Kind() == reflect.Struct { - // save embedded struct for later processing - embedded = append(embedded, sv) - continue + if sf.Anonymous { + v := reflect.Indirect(sv) + if v.IsValid() && v.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, v) + continue + } } name = sf.Name @@ -170,7 +187,9 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if sv.Type().Implements(encoderType) { - if !reflect.Indirect(sv).IsValid() { + // if sv is a nil pointer and the custom encoder is defined on a non-pointer + // method receiver, set sv to the zero value of the underlying type + if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) { sv = reflect.New(sv.Type().Elem()) } @@ -181,28 +200,38 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } + // recursively dereference pointers. break on nil pointers + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { - var del byte + var del string if opts.Contains("comma") { - del = ',' + del = "," } else if opts.Contains("space") { - del = ' ' + del = " " } else if opts.Contains("semicolon") { - del = ';' + del = ";" } else if opts.Contains("brackets") { name = name + "[]" + } else { + del = sf.Tag.Get("del") } - if del != 0 { + if del != "" { s := new(bytes.Buffer) first := true for i := 0; i < sv.Len(); i++ { if first { first = false } else { - s.WriteByte(del) + s.WriteString(del) } - s.WriteString(valueString(sv.Index(i), opts)) + s.WriteString(valueString(sv.Index(i), opts, sf)) } values.Add(name, s.String()) } else { @@ -211,30 +240,25 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { if opts.Contains("numbered") { k = fmt.Sprintf("%s%d", name, i) } - values.Add(k, valueString(sv.Index(i), opts)) + values.Add(k, valueString(sv.Index(i), opts, sf)) } } continue } - for sv.Kind() == reflect.Ptr { - if sv.IsNil() { - break - } - sv = sv.Elem() - } - if sv.Type() == timeType { - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) continue } if sv.Kind() == reflect.Struct { - reflectValue(values, sv, name) + if err := reflectValue(values, sv, name); err != nil { + return err + } continue } - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) } for _, f := range embedded { @@ -247,7 +271,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } // valueString returns the string representation of a value. -func valueString(v reflect.Value, opts tagOptions) string { +func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string { for v.Kind() == reflect.Ptr { if v.IsNil() { return "" @@ -267,6 +291,15 @@ func valueString(v reflect.Value, opts tagOptions) string { if opts.Contains("unix") { return strconv.FormatInt(t.Unix(), 10) } + if opts.Contains("unixmilli") { + return strconv.FormatInt((t.UnixNano() / 1e6), 10) + } + if opts.Contains("unixnano") { + return strconv.FormatInt(t.UnixNano(), 10) + } + if layout := sf.Tag.Get("layout"); layout != "" { + return t.Format(layout) + } return t.Format(time.RFC3339) } @@ -291,8 +324,12 @@ func isEmptyValue(v reflect.Value) bool { return v.IsNil() } - if v.Type() == timeType { - return v.Interface().(time.Time).IsZero() + type zeroable interface { + IsZero() bool + } + + if z, ok := v.Interface().(zeroable); ok { + return z.IsZero() } return false diff --git a/vendor/modules.txt b/vendor/modules.txt index ac6ea55d..2b61075f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -23,11 +23,11 @@ github.com/fsnotify/fsnotify ## explicit; go 1.19 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash -# github.com/google/go-github v17.0.0+incompatible -## explicit -github.com/google/go-github/github -# github.com/google/go-querystring v1.0.0 -## explicit +# github.com/google/go-github/v68 v68.0.0 +## explicit; go 1.21 +github.com/google/go-github/v68/github +# github.com/google/go-querystring v1.1.0 +## explicit; go 1.10 github.com/google/go-querystring/query # github.com/google/uuid v1.6.0 ## explicit From c49a2f6e96eefbbbc434a416e68d7f0ad5daeac6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 15 Jan 2025 15:41:16 +0100 Subject: [PATCH 05/35] fix changelog text (#146) Just realised I messed up the changelog as I was about to publish the new version. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de9b011..6d1ea1e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ ### Changed -- Update golang version +- Update dependencies ## 2.0.1 From 587300ffc8ce465162f6e0b16c010c903f73294a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 16 Jan 2025 14:04:50 +0100 Subject: [PATCH 06/35] Ffeldberg/rel 4888/support enterprise instances (#147) Adding support for instantiating a github enterprise client if the PR we are checking isn't in a regular GH account. Also adds some safety for nil pointer references and a fallback value for required flag link values. --------- Co-authored-by: collinmurd --- CHANGELOG.md | 4 ++++ config/config.go | 19 ++++++++++++++++--- internal/ldclient/flag_links.go | 33 ++++++++++++++++++++------------- internal/utils/utils.go | 7 +++++++ internal/version/version.go | 2 +- testdata/test | 2 +- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d1ea1e1..1fbdfb6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,14 @@ ### Added +- Add support for enterprise hosted github instances [More info](https://github.com/launchdarkly/find-code-references-in-pull-request/issues/102) + ### Changed ### Fixed + - Potential null pointer error when creating flag links + ## 2.0.2 ### Changed diff --git a/config/config.go b/config/config.go index 20c554a0..07cc7669 100644 --- a/config/config.go +++ b/config/config.go @@ -98,14 +98,27 @@ func ValidateInputandParse(ctx context.Context) (*Config, error) { config.CreateFlagLinks = createFlagLinks } - config.GHClient = getGithubClient(ctx) + client, err := getGithubClient(ctx) + if err != nil { + return nil, err + } + config.GHClient = client + return &config, nil } -func getGithubClient(ctx context.Context) *github.Client { +func getGithubClient(ctx context.Context) (*github.Client, error) { ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}, ) tc := oauth2.NewClient(ctx, ts) - return github.NewClient(tc) + gc := github.NewClient(tc) + + host := os.Getenv("GITHUB_SERVER_URL") + if host != "https://github.com" && host != "" { + gha.Log("Using GitHub Enterprise host. baseUrl: %s, uploadUrl: %s", host+"/api/v3/", host+"/api/uploads/") + return gc.WithEnterpriseURLs(host+"/api/v3/", host+"/api/uploads/") + } + + return gc, nil } diff --git a/internal/ldclient/flag_links.go b/internal/ldclient/flag_links.go index 8c9fc584..6555f2b6 100644 --- a/internal/ldclient/flag_links.go +++ b/internal/ldclient/flag_links.go @@ -14,6 +14,7 @@ import ( ldapi "github.com/launchdarkly/api-client-go/v15" lcr "github.com/launchdarkly/find-code-references-in-pull-request/config" gha "github.com/launchdarkly/find-code-references-in-pull-request/internal/github_actions" + "github.com/launchdarkly/find-code-references-in-pull-request/internal/utils" "github.com/launchdarkly/find-code-references-in-pull-request/internal/version" flags "github.com/launchdarkly/find-code-references-in-pull-request/internal/references" @@ -101,23 +102,24 @@ func makeFlagLinkRep(event *github.PullRequestEvent, flagKey, message string) *l return nil } + authorLogin := utils.SafeString(pr.User.Login) metadata := map[string]string{ "message": message, "prNumber": strconv.Itoa(*pr.Number), - "prTitle": *pr.Title, - "prBody": *pr.Body, - "state": *pr.State, - "avatarUrl": *pr.User.AvatarURL, - "repoName": *event.Repo.FullName, - "repoUrl": *event.Repo.HTMLURL, + "prTitle": utils.SafeString(pr.Title), + "prBody": utils.SafeString(pr.Body), + "state": utils.SafeString(pr.State), + "avatarUrl": utils.SafeString(pr.User.AvatarURL), + "repoName": utils.SafeString(event.Repo.FullName), + "repoUrl": utils.SafeString(event.Repo.HTMLURL), } if pr.User.Name != nil { - metadata["authorName"] = *pr.User.Name - metadata["authorDisplayName"] = *pr.User.Name + metadata["authorName"] = utils.SafeString(pr.User.Name) + metadata["authorDisplayName"] = utils.SafeString(pr.User.Name) } else { - metadata["authorDisplayName"] = *pr.User.Login - metadata["authorLogin"] = *pr.User.Login + metadata["authorDisplayName"] = authorLogin + metadata["authorLogin"] = authorLogin } var timestamp *int64 @@ -131,25 +133,30 @@ func makeFlagLinkRep(event *github.PullRequestEvent, flagKey, message string) *l // key must be unique key := fmt.Sprintf("github-pr-%s-%s", id, flagKey) + description := utils.SafeString(pr.Body) + // Flag links require a description + if description == "" { + description = "Empty PR Body" + } return &ldapi.FlagLinkPost{ DeepLink: pr.HTMLURL, Key: &key, IntegrationKey: &integration, Timestamp: timestamp, Title: getLinkTitle(event), - Description: pr.Body, + Description: &description, Metadata: &metadata, } } func getLinkTitle(event *github.PullRequestEvent) *string { builder := new(strings.Builder) - builder.WriteString(fmt.Sprintf("[%s]", *event.Repo.FullName)) + builder.WriteString(fmt.Sprintf("[%s]", utils.SafeString(event.Repo.FullName))) pr := event.PullRequest if pr.Title != nil { builder.WriteString(" ") - builder.WriteString(*pr.Title) + builder.WriteString(utils.SafeString(pr.Title)) if pr.Number != nil { builder.WriteString(fmt.Sprintf(" (#%d)", *pr.Number)) } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 9c5375a8..a07ec9a0 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -14,3 +14,10 @@ func Dedupe(s []string) []string { } return ret } + +func SafeString(s *string) string { + if s != nil { + return *s + } + return "" +} diff --git a/internal/version/version.go b/internal/version/version.go index eacf5007..61697b03 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.0.2" +const Version = "2.0.3-alpha" diff --git a/testdata/test b/testdata/test index 613b7907..4de0a8af 100644 --- a/testdata/test +++ b/testdata/test @@ -5,4 +5,4 @@ show-widgets show_widgets mobile-app-promo-ios mobile-app-promo-ios -beta-ui +beta-ui \ No newline at end of file From 30f4c4ab2949bbf258b797ced2fbf6dea34df9ce Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 16 Jan 2025 15:23:24 +0100 Subject: [PATCH 07/35] prepare release (#148) Updating changelog and version number for pending release --- CHANGELOG.md | 8 ++++++++ internal/version/version.go | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fbdfb6d..2ea1edb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ### Added +### Changed + +### Fixed + +## 2.1.0 + +### Added + - Add support for enterprise hosted github instances [More info](https://github.com/launchdarkly/find-code-references-in-pull-request/issues/102) ### Changed diff --git a/internal/version/version.go b/internal/version/version.go index 61697b03..4b41c075 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.0.3-alpha" +const Version = "2.1.0" From a15eea5afe9dfa9d694abbaad49f9fb984b4fc92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 13:20:57 -0400 Subject: [PATCH 08/35] chore(deps): bump github.com/go-git/go-git/v5 from 5.12.0 to 5.13.0 (#144) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.12.0 to 5.13.0.
Release notes

Sourced from github.com/go-git/go-git/v5's releases.

v5.13.0

What's Changed

... (truncated)

Commits
  • 94bd4af Merge pull request #1261 from BeChris/issue680
  • 8b7f5ba Merge pull request #1262 from go-git/dependabot/go_modules/github.com/elazarl...
  • 41d80a0 build: bump github.com/elazarl/goproxy
  • 4998140 git: worktree_commit, sanitize author and commiter name and email before crea...
  • 9049625 Merge pull request #1260 from go-git/dependabot/github_actions/github/codeql-...
  • dae48b4 build: bump github/codeql-action from 3.27.9 to 3.28.0
  • 7d6fbc2 Merge pull request #1220 from BeChris/accept_uppercase_hexa_in_pktline_length
  • 62a77b7 plumbing: Fix invalid reference name error while cloning branches containing ...
  • 5e11196 plumbing: format/pktline, accept upercase hexadecimal value as pktline length...
  • 65f5e1a Merge pull request #1256 from go-git/dependabot/go_modules/golang-org-232a611e2d
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-git/go-git/v5&package-manager=go_modules&previous-version=5.12.0&new-version=5.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/launchdarkly/find-code-references-in-pull-request/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- go.mod | 4 +- go.sum | 8 ++-- .../go-git/go-git/v5/plumbing/reference.go | 4 +- vendor/golang.org/x/exp/LICENSE | 4 +- vendor/golang.org/x/exp/slices/slices.go | 44 +++++++++++++------ vendor/golang.org/x/exp/slices/sort.go | 4 +- vendor/golang.org/x/exp/slog/handler.go | 18 ++++++++ vendor/modules.txt | 6 +-- 8 files changed, 64 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 07c41dfb..41d36de0 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect ) require ( @@ -37,7 +37,7 @@ require ( github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-git/go-git/v5 v5.12.0 // indirect + github.com/go-git/go-git/v5 v5.13.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect diff --git a/go.sum b/go.sum index f0123cff..5ea859d6 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= -github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= +github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -264,8 +264,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/reference.go b/vendor/github.com/go-git/go-git/v5/plumbing/reference.go index ddba9302..4daa3416 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/reference.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/reference.go @@ -188,7 +188,7 @@ func (r ReferenceName) Validate() error { isBranch := r.IsBranch() isTag := r.IsTag() - for _, part := range parts { + for i, part := range parts { // rule 6 if len(part) == 0 { return ErrInvalidReferenceName @@ -205,7 +205,7 @@ func (r ReferenceName) Validate() error { return ErrInvalidReferenceName } - if (isBranch || isTag) && strings.HasPrefix(part, "-") { // branches & tags can't start with - + if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with - return ErrInvalidReferenceName } } diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE index 6a66aea5..2a7cf70d 100644 --- a/vendor/golang.org/x/exp/LICENSE +++ b/vendor/golang.org/x/exp/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/exp/slices/slices.go b/vendor/golang.org/x/exp/slices/slices.go index 5e8158bb..46ceac34 100644 --- a/vendor/golang.org/x/exp/slices/slices.go +++ b/vendor/golang.org/x/exp/slices/slices.go @@ -209,25 +209,37 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S { return s } +// clearSlice sets all elements up to the length of s to the zero value of E. +// We may use the builtin clear func instead, and remove clearSlice, when upgrading +// to Go 1.21+. +func clearSlice[S ~[]E, E any](s S) { + var zero E + for i := range s { + s[i] = zero + } +} + // Delete removes the elements s[i:j] from s, returning the modified slice. -// Delete panics if s[i:j] is not a valid slice of s. -// Delete is O(len(s)-j), so if many items must be deleted, it is better to +// Delete panics if j > len(s) or s[i:j] is not a valid slice of s. +// Delete is O(len(s)-i), so if many items must be deleted, it is better to // make a single call deleting them all together than to delete one at a time. -// Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those -// elements contain pointers you might consider zeroing those elements so that -// objects they reference can be garbage collected. +// Delete zeroes the elements s[len(s)-(j-i):len(s)]. func Delete[S ~[]E, E any](s S, i, j int) S { - _ = s[i:j] // bounds check + _ = s[i:j:len(s)] // bounds check - return append(s[:i], s[j:]...) + if i == j { + return s + } + + oldlen := len(s) + s = append(s[:i], s[j:]...) + clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC + return s } // DeleteFunc removes any elements from s for which del returns true, // returning the modified slice. -// When DeleteFunc removes m elements, it might not modify the elements -// s[len(s)-m:len(s)]. If those elements contain pointers you might consider -// zeroing those elements so that objects they reference can be garbage -// collected. +// DeleteFunc zeroes the elements between the new length and the original length. func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { i := IndexFunc(s, del) if i == -1 { @@ -240,11 +252,13 @@ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { i++ } } + clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC return s[:i] } // Replace replaces the elements s[i:j] by the given v, and returns the // modified slice. Replace panics if s[i:j] is not a valid slice of s. +// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length. func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { _ = s[i:j] // verify that i:j is a valid subslice @@ -272,6 +286,7 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { if i+len(v) != j { copy(r[i+len(v):], s[j:]) } + clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC return r } @@ -345,9 +360,7 @@ func Clone[S ~[]E, E any](s S) S { // This is like the uniq command found on Unix. // Compact modifies the contents of the slice s and returns the modified slice, // which may have a smaller length. -// When Compact discards m elements in total, it might not modify the elements -// s[len(s)-m:len(s)]. If those elements contain pointers you might consider -// zeroing those elements so that objects they reference can be garbage collected. +// Compact zeroes the elements between the new length and the original length. func Compact[S ~[]E, E comparable](s S) S { if len(s) < 2 { return s @@ -361,11 +374,13 @@ func Compact[S ~[]E, E comparable](s S) S { i++ } } + clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC return s[:i] } // CompactFunc is like [Compact] but uses an equality function to compare elements. // For runs of elements that compare equal, CompactFunc keeps the first one. +// CompactFunc zeroes the elements between the new length and the original length. func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { if len(s) < 2 { return s @@ -379,6 +394,7 @@ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { i++ } } + clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC return s[:i] } diff --git a/vendor/golang.org/x/exp/slices/sort.go b/vendor/golang.org/x/exp/slices/sort.go index b67897f7..f58bbc7b 100644 --- a/vendor/golang.org/x/exp/slices/sort.go +++ b/vendor/golang.org/x/exp/slices/sort.go @@ -22,10 +22,12 @@ func Sort[S ~[]E, E constraints.Ordered](x S) { // SortFunc sorts the slice x in ascending order as determined by the cmp // function. This sort is not guaranteed to be stable. // cmp(a, b) should return a negative number when a < b, a positive number when -// a > b and zero when a == b. +// a > b and zero when a == b or when a is not comparable to b in the sense +// of the formal definition of Strict Weak Ordering. // // SortFunc requires that cmp is a strict weak ordering. // See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. +// To indicate 'uncomparable', return 0 from the function. func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { n := len(x) pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp) diff --git a/vendor/golang.org/x/exp/slog/handler.go b/vendor/golang.org/x/exp/slog/handler.go index 74f88738..bd635cb8 100644 --- a/vendor/golang.org/x/exp/slog/handler.go +++ b/vendor/golang.org/x/exp/slog/handler.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "io" + "reflect" "strconv" "sync" "time" @@ -504,6 +505,23 @@ func (s *handleState) appendString(str string) { } func (s *handleState) appendValue(v Value) { + defer func() { + if r := recover(); r != nil { + // If it panics with a nil pointer, the most likely cases are + // an encoding.TextMarshaler or error fails to guard against nil, + // in which case "" seems to be the feasible choice. + // + // Adapted from the code in fmt/print.go. + if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { + s.appendString("") + return + } + + // Otherwise just print the original panic message. + s.appendString(fmt.Sprintf("!PANIC: %v", r)) + } + }() + var err error if s.h.json { err = appendJSONValue(s, v) diff --git a/vendor/modules.txt b/vendor/modules.txt index 2b61075f..fc0e05fb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -19,8 +19,8 @@ github.com/davecgh/go-spew/spew # github.com/fsnotify/fsnotify v1.7.0 ## explicit; go 1.17 github.com/fsnotify/fsnotify -# github.com/go-git/go-git/v5 v5.12.0 -## explicit; go 1.19 +# github.com/go-git/go-git/v5 v5.13.0 +## explicit; go 1.21 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash # github.com/google/go-github/v68 v68.0.0 @@ -203,7 +203,7 @@ golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/exp v0.0.0-20230905200255-921286631fa9 +# golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 ## explicit; go 1.20 golang.org/x/exp/constraints golang.org/x/exp/slices From 7fa7dbd65a9dd56b622f9c19e261a4c67994eec7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 13:53:40 -0400 Subject: [PATCH 09/35] chore(deps): bump actions/setup-node from 4.1.0 to 4.4.0 (#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.1.0 to 4.4.0.
Release notes

Sourced from actions/setup-node's releases.

v4.4.0

What's Changed

Bug fixes:

Enhancement:

Dependency update:

New Contributors

Full Changeloghttps://github.com/actions/setup-node/compare/v4...v4.4.0

v4.3.0

What's Changed

Dependency updates

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v4...v4.3.0

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v4...v4.2.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=4.1.0&new-version=4.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 39c11932..35d36468 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: Set up Node.js - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: node-version: '18.x' @@ -131,7 +131,7 @@ jobs: pip install pre-commit - name: Set up Node.js - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: node-version: '18.8.0' From 5aeec75066d7a047317f6bbbc19b351e0c4a3307 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 14:02:29 -0400 Subject: [PATCH 10/35] chore(deps): bump golang.org/x/oauth2 from 0.25.0 to 0.30.0 (#164) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.25.0 to 0.30.0.
Commits
  • cf14319 oauth2: fix expiration time window check
  • 32d34ef internal: include clientID in auth style cache key
  • 2d34e30 oauth2: replace a magic number with AuthStyleUnknown
  • 696f7b3 all: modernize with doc links and any
  • 471209b oauth2: drop dependency on go-cmp
  • 6968da2 oauth2: sync Token.ExpiresIn from internal Token
  • d2c4e0a oauth2: context instead of golang.org/x/net/context in doc
  • 883dc3c endpoints: add various endpoints from stale CLs
  • 1c06e87 all: make use of oauth.Token.ExpiresIn
  • 65c15a3 oauth2: remove extra period
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.25.0&new-version=0.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- go.mod | 6 +- go.sum | 6 +- vendor/golang.org/x/oauth2/internal/doc.go | 2 +- vendor/golang.org/x/oauth2/internal/oauth2.go | 2 +- vendor/golang.org/x/oauth2/internal/token.go | 50 ++++++++------- .../golang.org/x/oauth2/internal/transport.go | 4 +- vendor/golang.org/x/oauth2/oauth2.go | 63 ++++++++++--------- vendor/golang.org/x/oauth2/pkce.go | 15 ++--- vendor/golang.org/x/oauth2/token.go | 17 ++--- vendor/golang.org/x/oauth2/transport.go | 24 ++----- vendor/modules.txt | 4 +- 11 files changed, 92 insertions(+), 101 deletions(-) diff --git a/go.mod b/go.mod index 41d36de0..608f3949 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/launchdarkly/find-code-references-in-pull-request -go 1.22.0 - -toolchain go1.22.7 +go 1.23.0 require ( github.com/Masterminds/sprig/v3 v3.3.0 @@ -11,7 +9,7 @@ require ( github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 - golang.org/x/oauth2 v0.25.0 + golang.org/x/oauth2 v0.30.0 ) require ( diff --git a/go.sum b/go.sum index 5ea859d6..ccead806 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -318,8 +316,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go index 03265e88..8c7c475f 100644 --- a/vendor/golang.org/x/oauth2/internal/doc.go +++ b/vendor/golang.org/x/oauth2/internal/doc.go @@ -2,5 +2,5 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. +// Package internal contains support packages for [golang.org/x/oauth2]. package internal diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go index 14989bea..71ea6ad1 100644 --- a/vendor/golang.org/x/oauth2/internal/oauth2.go +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go @@ -13,7 +13,7 @@ import ( ) // ParseKey converts the binary contents of a private key file -// to an *rsa.PrivateKey. It detects whether the private key is in a +// to an [*rsa.PrivateKey]. It detects whether the private key is in a // PEM container or not. If so, it extracts the private key // from PEM container before conversion. It only supports PEM // containers with no passphrase. diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go index e83ddeef..8389f246 100644 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "mime" "net/http" @@ -26,9 +25,9 @@ import ( // the requests to access protected resources on the OAuth 2.0 // provider's backend. // -// This type is a mirror of oauth2.Token and exists to break +// This type is a mirror of [golang.org/x/oauth2.Token] and exists to break // an otherwise-circular dependency. Other internal packages -// should convert this Token into an oauth2.Token before use. +// should convert this Token into an [golang.org/x/oauth2.Token] before use. type Token struct { // AccessToken is the token that authorizes and authenticates // the requests. @@ -50,9 +49,16 @@ type Token struct { // mechanisms for that TokenSource will not be used. Expiry time.Time + // ExpiresIn is the OAuth2 wire format "expires_in" field, + // which specifies how many seconds later the token expires, + // relative to an unknown time base approximately around "now". + // It is the application's responsibility to populate + // `Expiry` from `ExpiresIn` when required. + ExpiresIn int64 `json:"expires_in,omitempty"` + // Raw optionally contains extra metadata from the server // when updating a token. - Raw interface{} + Raw any } // tokenJSON is the struct representing the HTTP response from OAuth2 @@ -99,14 +105,6 @@ func (e *expirationTime) UnmarshalJSON(b []byte) error { return nil } -// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. -// -// Deprecated: this function no longer does anything. Caller code that -// wants to avoid potential extra HTTP requests made during -// auto-probing of the provider's auth style should set -// Endpoint.AuthStyle. -func RegisterBrokenAuthHeaderProvider(tokenURL string) {} - // AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. type AuthStyle int @@ -143,6 +141,11 @@ func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { return c } +type authStyleCacheKey struct { + url string + clientID string +} + // AuthStyleCache is the set of tokenURLs we've successfully used via // RetrieveToken and which style auth we ended up using. // It's called a cache, but it doesn't (yet?) shrink. It's expected that @@ -150,26 +153,26 @@ func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { // small. type AuthStyleCache struct { mu sync.Mutex - m map[string]AuthStyle // keyed by tokenURL + m map[authStyleCacheKey]AuthStyle } // lookupAuthStyle reports which auth style we last used with tokenURL // when calling RetrieveToken and whether we have ever done so. -func (c *AuthStyleCache) lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) { +func (c *AuthStyleCache) lookupAuthStyle(tokenURL, clientID string) (style AuthStyle, ok bool) { c.mu.Lock() defer c.mu.Unlock() - style, ok = c.m[tokenURL] + style, ok = c.m[authStyleCacheKey{tokenURL, clientID}] return } // setAuthStyle adds an entry to authStyleCache, documented above. -func (c *AuthStyleCache) setAuthStyle(tokenURL string, v AuthStyle) { +func (c *AuthStyleCache) setAuthStyle(tokenURL, clientID string, v AuthStyle) { c.mu.Lock() defer c.mu.Unlock() if c.m == nil { - c.m = make(map[string]AuthStyle) + c.m = make(map[authStyleCacheKey]AuthStyle) } - c.m[tokenURL] = v + c.m[authStyleCacheKey{tokenURL, clientID}] = v } // newTokenRequest returns a new *http.Request to retrieve a new token @@ -210,9 +213,9 @@ func cloneURLValues(v url.Values) url.Values { } func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { - needsAuthStyleProbe := authStyle == 0 + needsAuthStyleProbe := authStyle == AuthStyleUnknown if needsAuthStyleProbe { - if style, ok := styleCache.lookupAuthStyle(tokenURL); ok { + if style, ok := styleCache.lookupAuthStyle(tokenURL, clientID); ok { authStyle = style needsAuthStyleProbe = false } else { @@ -242,7 +245,7 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, token, err = doTokenRoundTrip(ctx, req) } if needsAuthStyleProbe && err == nil { - styleCache.setAuthStyle(tokenURL, authStyle) + styleCache.setAuthStyle(tokenURL, clientID, authStyle) } // Don't overwrite `RefreshToken` with an empty value // if this was a token refreshing request. @@ -257,7 +260,7 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { if err != nil { return nil, err } - body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) + body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) r.Body.Close() if err != nil { return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) @@ -312,7 +315,8 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { TokenType: tj.TokenType, RefreshToken: tj.RefreshToken, Expiry: tj.expiry(), - Raw: make(map[string]interface{}), + ExpiresIn: int64(tj.ExpiresIn), + Raw: make(map[string]any), } json.Unmarshal(body, &token.Raw) // no error checks for optional fields } diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go index b9db01dd..afc0aeb2 100644 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -9,8 +9,8 @@ import ( "net/http" ) -// HTTPClient is the context key to use with golang.org/x/net/context's -// WithValue function to associate an *http.Client value with a context. +// HTTPClient is the context key to use with [context.WithValue] +// to associate an [*http.Client] value with a context. var HTTPClient ContextKey // ContextKey is just an empty struct. It exists so HTTPClient can be diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 74f052aa..de34feb8 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -22,9 +22,9 @@ import ( ) // NoContext is the default context you should supply if not using -// your own context.Context (see https://golang.org/x/net/context). +// your own [context.Context]. // -// Deprecated: Use context.Background() or context.TODO() instead. +// Deprecated: Use [context.Background] or [context.TODO] instead. var NoContext = context.TODO() // RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. @@ -37,8 +37,8 @@ func RegisterBrokenAuthHeaderProvider(tokenURL string) {} // Config describes a typical 3-legged OAuth2 flow, with both the // client application information and the server's endpoint URLs. -// For the client credentials 2-legged OAuth2 flow, see the clientcredentials -// package (https://golang.org/x/oauth2/clientcredentials). +// For the client credentials 2-legged OAuth2 flow, see the +// [golang.org/x/oauth2/clientcredentials] package. type Config struct { // ClientID is the application's ID. ClientID string @@ -46,7 +46,7 @@ type Config struct { // ClientSecret is the application's secret. ClientSecret string - // Endpoint contains the resource server's token endpoint + // Endpoint contains the authorization server's token endpoint // URLs. These are constants specific to each server and are // often available via site-specific packages, such as // google.Endpoint or github.Endpoint. @@ -135,7 +135,7 @@ type setParam struct{ k, v string } func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } -// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters +// SetAuthURLParam builds an [AuthCodeOption] which passes key/value parameters // to a provider's authorization endpoint. func SetAuthURLParam(key, value string) AuthCodeOption { return setParam{key, value} @@ -148,8 +148,8 @@ func SetAuthURLParam(key, value string) AuthCodeOption { // request and callback. The authorization server includes this value when // redirecting the user agent back to the client. // -// Opts may include AccessTypeOnline or AccessTypeOffline, as well -// as ApprovalForce. +// Opts may include [AccessTypeOnline] or [AccessTypeOffline], as well +// as [ApprovalForce]. // // To protect against CSRF attacks, opts should include a PKCE challenge // (S256ChallengeOption). Not all servers support PKCE. An alternative is to @@ -194,7 +194,7 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { // and when other authorization grant types are not available." // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. // -// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. +// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { v := url.Values{ "grant_type": {"password"}, @@ -212,10 +212,10 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor // It is used after a resource provider redirects the user back // to the Redirect URI (the URL obtained from AuthCodeURL). // -// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. +// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. // -// The code will be in the *http.Request.FormValue("code"). Before -// calling Exchange, be sure to validate FormValue("state") if you are +// The code will be in the [http.Request.FormValue]("code"). Before +// calling Exchange, be sure to validate [http.Request.FormValue]("state") if you are // using it to protect against CSRF attacks. // // If using PKCE to protect against CSRF attacks, opts should include a @@ -242,10 +242,10 @@ func (c *Config) Client(ctx context.Context, t *Token) *http.Client { return NewClient(ctx, c.TokenSource(ctx, t)) } -// TokenSource returns a TokenSource that returns t until t expires, +// TokenSource returns a [TokenSource] that returns t until t expires, // automatically refreshing it as necessary using the provided context. // -// Most users will use Config.Client instead. +// Most users will use [Config.Client] instead. func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { tkr := &tokenRefresher{ ctx: ctx, @@ -260,7 +260,7 @@ func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { } } -// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token" +// tokenRefresher is a TokenSource that makes "grant_type=refresh_token" // HTTP requests to renew a token using a RefreshToken. type tokenRefresher struct { ctx context.Context // used to get HTTP requests @@ -288,7 +288,7 @@ func (tf *tokenRefresher) Token() (*Token, error) { if tf.refreshToken != tk.RefreshToken { tf.refreshToken = tk.RefreshToken } - return tk, err + return tk, nil } // reuseTokenSource is a TokenSource that holds a single token in memory @@ -305,8 +305,7 @@ type reuseTokenSource struct { } // Token returns the current token if it's still valid, else will -// refresh the current token (using r.Context for HTTP client -// information) and return the new one. +// refresh the current token and return the new one. func (s *reuseTokenSource) Token() (*Token, error) { s.mu.Lock() defer s.mu.Unlock() @@ -322,7 +321,7 @@ func (s *reuseTokenSource) Token() (*Token, error) { return t, nil } -// StaticTokenSource returns a TokenSource that always returns the same token. +// StaticTokenSource returns a [TokenSource] that always returns the same token. // Because the provided token t is never refreshed, StaticTokenSource is only // useful for tokens that never expire. func StaticTokenSource(t *Token) TokenSource { @@ -338,16 +337,16 @@ func (s staticTokenSource) Token() (*Token, error) { return s.t, nil } -// HTTPClient is the context key to use with golang.org/x/net/context's -// WithValue function to associate an *http.Client value with a context. +// HTTPClient is the context key to use with [context.WithValue] +// to associate a [*http.Client] value with a context. var HTTPClient internal.ContextKey -// NewClient creates an *http.Client from a Context and TokenSource. +// NewClient creates an [*http.Client] from a [context.Context] and [TokenSource]. // The returned client is not valid beyond the lifetime of the context. // -// Note that if a custom *http.Client is provided via the Context it +// Note that if a custom [*http.Client] is provided via the [context.Context] it // is used only for token acquisition and is not used to configure the -// *http.Client returned from NewClient. +// [*http.Client] returned from NewClient. // // As a special case, if src is nil, a non-OAuth2 client is returned // using the provided context. This exists to support related OAuth2 @@ -356,15 +355,19 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client { if src == nil { return internal.ContextClient(ctx) } + cc := internal.ContextClient(ctx) return &http.Client{ Transport: &Transport{ - Base: internal.ContextClient(ctx).Transport, + Base: cc.Transport, Source: ReuseTokenSource(nil, src), }, + CheckRedirect: cc.CheckRedirect, + Jar: cc.Jar, + Timeout: cc.Timeout, } } -// ReuseTokenSource returns a TokenSource which repeatedly returns the +// ReuseTokenSource returns a [TokenSource] which repeatedly returns the // same token as long as it's valid, starting with t. // When its cached token is invalid, a new token is obtained from src. // @@ -372,10 +375,10 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client { // (such as a file on disk) between runs of a program, rather than // obtaining new tokens unnecessarily. // -// The initial token t may be nil, in which case the TokenSource is +// The initial token t may be nil, in which case the [TokenSource] is // wrapped in a caching version if it isn't one already. This also // means it's always safe to wrap ReuseTokenSource around any other -// TokenSource without adverse effects. +// [TokenSource] without adverse effects. func ReuseTokenSource(t *Token, src TokenSource) TokenSource { // Don't wrap a reuseTokenSource in itself. That would work, // but cause an unnecessary number of mutex operations. @@ -393,8 +396,8 @@ func ReuseTokenSource(t *Token, src TokenSource) TokenSource { } } -// ReuseTokenSourceWithExpiry returns a TokenSource that acts in the same manner as the -// TokenSource returned by ReuseTokenSource, except the expiry buffer is +// ReuseTokenSourceWithExpiry returns a [TokenSource] that acts in the same manner as the +// [TokenSource] returned by [ReuseTokenSource], except the expiry buffer is // configurable. The expiration time of a token is calculated as // t.Expiry.Add(-earlyExpiry). func ReuseTokenSourceWithExpiry(t *Token, src TokenSource, earlyExpiry time.Duration) TokenSource { diff --git a/vendor/golang.org/x/oauth2/pkce.go b/vendor/golang.org/x/oauth2/pkce.go index 50593b6d..cea8374d 100644 --- a/vendor/golang.org/x/oauth2/pkce.go +++ b/vendor/golang.org/x/oauth2/pkce.go @@ -1,6 +1,7 @@ // Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. + package oauth2 import ( @@ -20,9 +21,9 @@ const ( // This follows recommendations in RFC 7636. // // A fresh verifier should be generated for each authorization. -// S256ChallengeOption(verifier) should then be passed to Config.AuthCodeURL -// (or Config.DeviceAccess) and VerifierOption(verifier) to Config.Exchange -// (or Config.DeviceAccessToken). +// The resulting verifier should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] +// with [S256ChallengeOption], and to [Config.Exchange] or [Config.DeviceAccessToken] +// with [VerifierOption]. func GenerateVerifier() string { // "RECOMMENDED that the output of a suitable random number generator be // used to create a 32-octet sequence. The octet sequence is then @@ -36,22 +37,22 @@ func GenerateVerifier() string { return base64.RawURLEncoding.EncodeToString(data) } -// VerifierOption returns a PKCE code verifier AuthCodeOption. It should be -// passed to Config.Exchange or Config.DeviceAccessToken only. +// VerifierOption returns a PKCE code verifier [AuthCodeOption]. It should only be +// passed to [Config.Exchange] or [Config.DeviceAccessToken]. func VerifierOption(verifier string) AuthCodeOption { return setParam{k: codeVerifierKey, v: verifier} } // S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256. // -// Prefer to use S256ChallengeOption where possible. +// Prefer to use [S256ChallengeOption] where possible. func S256ChallengeFromVerifier(verifier string) string { sha := sha256.Sum256([]byte(verifier)) return base64.RawURLEncoding.EncodeToString(sha[:]) } // S256ChallengeOption derives a PKCE code challenge derived from verifier with -// method S256. It should be passed to Config.AuthCodeURL or Config.DeviceAccess +// method S256. It should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] // only. func S256ChallengeOption(verifier string) AuthCodeOption { return challengeOption{ diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 109997d7..239ec329 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -44,7 +44,7 @@ type Token struct { // Expiry is the optional expiration time of the access token. // - // If zero, TokenSource implementations will reuse the same + // If zero, [TokenSource] implementations will reuse the same // token forever and RefreshToken or equivalent // mechanisms for that TokenSource will not be used. Expiry time.Time `json:"expiry,omitempty"` @@ -58,7 +58,7 @@ type Token struct { // raw optionally contains extra metadata from the server // when updating a token. - raw interface{} + raw any // expiryDelta is used to calculate when a token is considered // expired, by subtracting from Expiry. If zero, defaultExpiryDelta @@ -86,16 +86,16 @@ func (t *Token) Type() string { // SetAuthHeader sets the Authorization header to r using the access // token in t. // -// This method is unnecessary when using Transport or an HTTP Client +// This method is unnecessary when using [Transport] or an HTTP Client // returned by this package. func (t *Token) SetAuthHeader(r *http.Request) { r.Header.Set("Authorization", t.Type()+" "+t.AccessToken) } -// WithExtra returns a new Token that's a clone of t, but using the +// WithExtra returns a new [Token] that's a clone of t, but using the // provided raw extra map. This is only intended for use by packages // implementing derivative OAuth2 flows. -func (t *Token) WithExtra(extra interface{}) *Token { +func (t *Token) WithExtra(extra any) *Token { t2 := new(Token) *t2 = *t t2.raw = extra @@ -105,8 +105,8 @@ func (t *Token) WithExtra(extra interface{}) *Token { // Extra returns an extra field. // Extra fields are key-value pairs returned by the server as a // part of the token retrieval response. -func (t *Token) Extra(key string) interface{} { - if raw, ok := t.raw.(map[string]interface{}); ok { +func (t *Token) Extra(key string) any { + if raw, ok := t.raw.(map[string]any); ok { return raw[key] } @@ -163,13 +163,14 @@ func tokenFromInternal(t *internal.Token) *Token { TokenType: t.TokenType, RefreshToken: t.RefreshToken, Expiry: t.Expiry, + ExpiresIn: t.ExpiresIn, raw: t.Raw, } } // retrieveToken takes a *Config and uses that to retrieve an *internal.Token. // This token is then mapped from *internal.Token into an *oauth2.Token which is returned along -// with an error.. +// with an error. func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get()) if err != nil { diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go index 90657915..8bbebbac 100644 --- a/vendor/golang.org/x/oauth2/transport.go +++ b/vendor/golang.org/x/oauth2/transport.go @@ -11,12 +11,12 @@ import ( "sync" ) -// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests, -// wrapping a base RoundTripper and adding an Authorization header -// with a token from the supplied Sources. +// Transport is an [http.RoundTripper] that makes OAuth 2.0 HTTP requests, +// wrapping a base [http.RoundTripper] and adding an Authorization header +// with a token from the supplied [TokenSource]. // // Transport is a low-level mechanism. Most code will use the -// higher-level Config.Client method instead. +// higher-level [Config.Client] method instead. type Transport struct { // Source supplies the token to add to outgoing requests' // Authorization headers. @@ -47,7 +47,7 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { return nil, err } - req2 := cloneRequest(req) // per RoundTripper contract + req2 := req.Clone(req.Context()) token.SetAuthHeader(req2) // req.Body is assumed to be closed by the base RoundTripper. @@ -73,17 +73,3 @@ func (t *Transport) base() http.RoundTripper { } return http.DefaultTransport } - -// cloneRequest returns a clone of the provided *http.Request. -// The clone is a shallow copy of the struct and its Header map. -func cloneRequest(r *http.Request) *http.Request { - // shallow copy of the struct - r2 := new(http.Request) - *r2 = *r - // deep copy of the Header - r2.Header = make(http.Header, len(r.Header)) - for k, s := range r.Header { - r2.Header[k] = append([]string(nil), s...) - } - return r2 -} diff --git a/vendor/modules.txt b/vendor/modules.txt index fc0e05fb..d98c8fe4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -210,8 +210,8 @@ golang.org/x/exp/slices golang.org/x/exp/slog golang.org/x/exp/slog/internal golang.org/x/exp/slog/internal/buffer -# golang.org/x/oauth2 v0.25.0 -## explicit; go 1.18 +# golang.org/x/oauth2 v0.30.0 +## explicit; go 1.23.0 golang.org/x/oauth2 golang.org/x/oauth2/internal # golang.org/x/sys v0.28.0 From 3f98ad976da57e6554d8138af270b73edda5383f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 14:06:40 -0400 Subject: [PATCH 11/35] chore(deps): bump actions/setup-python from 5.3.0 to 5.6.0 (#163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.3.0 to 5.6.0.
Release notes

Sourced from actions/setup-python's releases.

v5.6.0

What's Changed

Full Changelog: https://github.com/actions/setup-python/compare/v5...v5.6.0

v5.5.0

What's Changed

Enhancements:

Bug fixes:

Dependency updates:

New Contributors

Full Changelog: https://github.com/actions/setup-python/compare/v5...v5.5.0

v5.4.0

What's Changed

Enhancements:

Documentation changes:

Dependency updates:

New Contributors

... (truncated)

Commits
  • a26af69 Bump ts-jest from 29.1.2 to 29.3.2 (#1081)
  • 30eafe9 Bump prettier from 2.8.8 to 3.5.3 (#1046)
  • 5d95bc1 Bump semver and @​types/semver (#1091)
  • 6ed2c67 Fix for Candidate Not Iterable Error (#1082)
  • e348410 Remove Ubuntu 20.04 from workflows due to deprecation from 2025-04-15 (#1065)
  • 8d9ed9a Add e2e Testing for free threaded and Bump @​action/cache from 4.0.0 to 4.0.3 ...
  • 19e4675 Add support for .tool-versions file in setup-python (#1043)
  • 6fd11e1 Bump @​actions/glob from 0.4.0 to 0.5.0 (#1015)
  • 9e62be8 Support free threaded Python versions like '3.13t' (#973)
  • 6ca8e85 Bump @​vercel/ncc from 0.38.1 to 0.38.3 (#1016)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=5.3.0&new-version=5.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 35d36468..5b8dc284 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: run: npm install -g @datadog/datadog-ci - name: Set up Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with: python-version: '3.x' @@ -121,7 +121,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: Set up Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with: python-version: '3.x' From ef684707ca5ae05c19454f330179a4397bbdf817 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 14:14:31 -0400 Subject: [PATCH 12/35] chore(deps): bump golang.org/x/crypto from 0.31.0 to 0.35.0 (#162) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.31.0 to 0.35.0.
Commits
  • 7292932 ssh: limit the size of the internal packet queue while waiting for KEX
  • f66f74b acme/autocert: check host policy before probing the cache
  • b0784b7 x509roots/fallback: drop obsolete build constraint
  • 911360c all: bump golang.org/x/crypto dependencies of asm generators
  • 89ff08d all: upgrade go directive to at least 1.23.0 [generated]
  • e47973b all: update certs for go1.24
  • 9290511 go.mod: update golang.org/x dependencies
  • fa5273e x509roots/fallback: update bundle
  • a8ea4be ssh: add ServerConfig.PreAuthConnCallback, ServerPreAuthConn (banner) interface
  • 71d3a4c acme: support challenges that require the ACME client to send a non-empty JSO...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/crypto&package-manager=go_modules&previous-version=0.31.0&new-version=0.35.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/launchdarkly/find-code-references-in-pull-request/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- go.mod | 6 +- go.sum | 12 +- vendor/golang.org/x/sys/unix/auxv.go | 36 ++++++ .../golang.org/x/sys/unix/auxv_unsupported.go | 13 ++ .../x/sys/unix/syscall_dragonfly.go | 12 ++ .../golang.org/x/sys/unix/syscall_solaris.go | 87 +++++++++++++ vendor/golang.org/x/sys/unix/zerrors_linux.go | 20 ++- .../x/sys/unix/zerrors_linux_386.go | 3 + .../x/sys/unix/zerrors_linux_amd64.go | 3 + .../x/sys/unix/zerrors_linux_arm.go | 3 + .../x/sys/unix/zerrors_linux_arm64.go | 4 + .../x/sys/unix/zerrors_linux_loong64.go | 3 + .../x/sys/unix/zerrors_linux_mips.go | 3 + .../x/sys/unix/zerrors_linux_mips64.go | 3 + .../x/sys/unix/zerrors_linux_mips64le.go | 3 + .../x/sys/unix/zerrors_linux_mipsle.go | 3 + .../x/sys/unix/zerrors_linux_ppc.go | 3 + .../x/sys/unix/zerrors_linux_ppc64.go | 3 + .../x/sys/unix/zerrors_linux_ppc64le.go | 3 + .../x/sys/unix/zerrors_linux_riscv64.go | 3 + .../x/sys/unix/zerrors_linux_s390x.go | 3 + .../x/sys/unix/zerrors_linux_sparc64.go | 3 + .../x/sys/unix/zsyscall_solaris_amd64.go | 114 ++++++++++++++++++ .../x/sys/unix/zsysnum_linux_386.go | 4 + .../x/sys/unix/zsysnum_linux_amd64.go | 4 + .../x/sys/unix/zsysnum_linux_arm.go | 4 + .../x/sys/unix/zsysnum_linux_arm64.go | 4 + .../x/sys/unix/zsysnum_linux_loong64.go | 4 + .../x/sys/unix/zsysnum_linux_mips.go | 4 + .../x/sys/unix/zsysnum_linux_mips64.go | 4 + .../x/sys/unix/zsysnum_linux_mips64le.go | 4 + .../x/sys/unix/zsysnum_linux_mipsle.go | 4 + .../x/sys/unix/zsysnum_linux_ppc.go | 4 + .../x/sys/unix/zsysnum_linux_ppc64.go | 4 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 4 + .../x/sys/unix/zsysnum_linux_riscv64.go | 4 + .../x/sys/unix/zsysnum_linux_s390x.go | 4 + .../x/sys/unix/zsysnum_linux_sparc64.go | 4 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 6 +- .../golang.org/x/sys/windows/dll_windows.go | 11 +- vendor/modules.txt | 8 +- 41 files changed, 409 insertions(+), 22 deletions(-) create mode 100644 vendor/golang.org/x/sys/unix/auxv.go create mode 100644 vendor/golang.org/x/sys/unix/auxv_unsupported.go diff --git a/go.mod b/go.mod index 608f3949..0dc961cc 100644 --- a/go.mod +++ b/go.mod @@ -64,9 +64,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/wacul/ptr v1.0.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/crypto v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/tools v0.28.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index ccead806..6fb9b008 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -352,15 +352,15 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/vendor/golang.org/x/sys/unix/auxv.go b/vendor/golang.org/x/sys/unix/auxv.go new file mode 100644 index 00000000..37a82528 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv.go @@ -0,0 +1,36 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import ( + "syscall" + "unsafe" +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +// Auxv returns the ELF auxiliary vector as a sequence of key/value pairs. +// The returned slice is always a fresh copy, owned by the caller. +// It returns an error on non-ELF platforms, or if the auxiliary vector cannot be accessed, +// which happens in some locked-down environments and build modes. +func Auxv() ([][2]uintptr, error) { + vec := runtime_getAuxv() + vecLen := len(vec) + + if vecLen == 0 { + return nil, syscall.ENOENT + } + + if vecLen%2 != 0 { + return nil, syscall.EINVAL + } + + result := make([]uintptr, vecLen) + copy(result, vec) + return unsafe.Slice((*[2]uintptr)(unsafe.Pointer(&result[0])), vecLen/2), nil +} diff --git a/vendor/golang.org/x/sys/unix/auxv_unsupported.go b/vendor/golang.org/x/sys/unix/auxv_unsupported.go new file mode 100644 index 00000000..1200487f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv_unsupported.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import "syscall" + +func Auxv() ([][2]uintptr, error) { + return nil, syscall.ENOTSUP +} diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 97cb916f..be8c0020 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -246,6 +246,18 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e return sendfile(outfd, infd, offset, count) } +func Dup3(oldfd, newfd, flags int) error { + if oldfd == newfd || flags&^O_CLOEXEC != 0 { + return EINVAL + } + how := F_DUP2FD + if flags&O_CLOEXEC != 0 { + how = F_DUP2FD_CLOEXEC + } + _, err := fcntl(oldfd, how, newfd) + return err +} + /* * Exposed directly */ diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 21974af0..abc39554 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) { func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) { return ioctlPtrRet(fd, req, unsafe.Pointer(s)) } + +// Ucred Helpers +// See ucred(3c) and getpeerucred(3c) + +//sys getpeerucred(fd uintptr, ucred *uintptr) (err error) +//sys ucredFree(ucred uintptr) = ucred_free +//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get +//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid +//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid +//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid +//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid +//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid +//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid +//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid + +// Ucred is an opaque struct that holds user credentials. +type Ucred struct { + ucred uintptr +} + +// We need to ensure that ucredFree is called on the underlying ucred +// when the Ucred is garbage collected. +func ucredFinalizer(u *Ucred) { + ucredFree(u.ucred) +} + +func GetPeerUcred(fd uintptr) (*Ucred, error) { + var ucred uintptr + err := getpeerucred(fd, &ucred) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func UcredGet(pid int) (*Ucred, error) { + ucred, err := ucredGet(pid) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func (u *Ucred) Geteuid() int { + defer runtime.KeepAlive(u) + return ucredGeteuid(u.ucred) +} + +func (u *Ucred) Getruid() int { + defer runtime.KeepAlive(u) + return ucredGetruid(u.ucred) +} + +func (u *Ucred) Getsuid() int { + defer runtime.KeepAlive(u) + return ucredGetsuid(u.ucred) +} + +func (u *Ucred) Getegid() int { + defer runtime.KeepAlive(u) + return ucredGetegid(u.ucred) +} + +func (u *Ucred) Getrgid() int { + defer runtime.KeepAlive(u) + return ucredGetrgid(u.ucred) +} + +func (u *Ucred) Getsgid() int { + defer runtime.KeepAlive(u) + return ucredGetsgid(u.ucred) +} + +func (u *Ucred) Getpid() int { + defer runtime.KeepAlive(u) + return ucredGetpid(u.ucred) +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 6ebc48b3..4f432bfe 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1245,6 +1245,7 @@ const ( FAN_REPORT_DFID_NAME = 0xc00 FAN_REPORT_DFID_NAME_TARGET = 0x1e00 FAN_REPORT_DIR_FID = 0x400 + FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 @@ -1330,8 +1331,10 @@ const ( FUSE_SUPER_MAGIC = 0x65735546 FUTEXFS_SUPER_MAGIC = 0xbad1dea F_ADD_SEALS = 0x409 + F_CREATED_QUERY = 0x404 F_DUPFD = 0x0 F_DUPFD_CLOEXEC = 0x406 + F_DUPFD_QUERY = 0x403 F_EXLCK = 0x4 F_GETFD = 0x1 F_GETFL = 0x3 @@ -1551,6 +1554,7 @@ const ( IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e IPPROTO_SCTP = 0x84 + IPPROTO_SMC = 0x100 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 @@ -1623,6 +1627,8 @@ const ( IPV6_UNICAST_IF = 0x4c IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 IPV6_XFRM_POLICY = 0x23 IP_ADD_MEMBERSHIP = 0x23 IP_ADD_SOURCE_MEMBERSHIP = 0x27 @@ -1867,6 +1873,7 @@ const ( MADV_UNMERGEABLE = 0xd MADV_WILLNEED = 0x3 MADV_WIPEONFORK = 0x12 + MAP_DROPPABLE = 0x8 MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FIXED_NOREPLACE = 0x100000 @@ -1967,6 +1974,7 @@ const ( MSG_PEEK = 0x2 MSG_PROXY = 0x10 MSG_RST = 0x1000 + MSG_SOCK_DEVMEM = 0x2000000 MSG_SYN = 0x400 MSG_TRUNC = 0x20 MSG_TRYHARD = 0x4 @@ -2083,6 +2091,7 @@ const ( NFC_ATR_REQ_MAXSIZE = 0x40 NFC_ATR_RES_GB_MAXSIZE = 0x2f NFC_ATR_RES_MAXSIZE = 0x40 + NFC_ATS_MAXSIZE = 0x14 NFC_COMM_ACTIVE = 0x0 NFC_COMM_PASSIVE = 0x1 NFC_DEVICE_NAME_MAXSIZE = 0x8 @@ -2163,6 +2172,7 @@ const ( NFNL_SUBSYS_QUEUE = 0x3 NFNL_SUBSYS_ULOG = 0x4 NFS_SUPER_MAGIC = 0x6969 + NFT_BITWISE_BOOL = 0x0 NFT_CHAIN_FLAGS = 0x7 NFT_CHAIN_MAXNAMELEN = 0x100 NFT_CT_MAX = 0x17 @@ -2491,6 +2501,7 @@ const ( PR_GET_PDEATHSIG = 0x2 PR_GET_SECCOMP = 0x15 PR_GET_SECUREBITS = 0x1b + PR_GET_SHADOW_STACK_STATUS = 0x4a PR_GET_SPECULATION_CTRL = 0x34 PR_GET_TAGGED_ADDR_CTRL = 0x38 PR_GET_THP_DISABLE = 0x2a @@ -2499,6 +2510,7 @@ const ( PR_GET_TIMING = 0xd PR_GET_TSC = 0x19 PR_GET_UNALIGN = 0x5 + PR_LOCK_SHADOW_STACK_STATUS = 0x4c PR_MCE_KILL = 0x21 PR_MCE_KILL_CLEAR = 0x0 PR_MCE_KILL_DEFAULT = 0x2 @@ -2525,6 +2537,8 @@ const ( PR_PAC_GET_ENABLED_KEYS = 0x3d PR_PAC_RESET_KEYS = 0x36 PR_PAC_SET_ENABLED_KEYS = 0x3c + PR_PMLEN_MASK = 0x7f000000 + PR_PMLEN_SHIFT = 0x18 PR_PPC_DEXCR_CTRL_CLEAR = 0x4 PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10 PR_PPC_DEXCR_CTRL_EDITABLE = 0x1 @@ -2592,6 +2606,7 @@ const ( PR_SET_PTRACER = 0x59616d61 PR_SET_SECCOMP = 0x16 PR_SET_SECUREBITS = 0x1c + PR_SET_SHADOW_STACK_STATUS = 0x4b PR_SET_SPECULATION_CTRL = 0x35 PR_SET_SYSCALL_USER_DISPATCH = 0x3b PR_SET_TAGGED_ADDR_CTRL = 0x37 @@ -2602,6 +2617,9 @@ const ( PR_SET_UNALIGN = 0x6 PR_SET_VMA = 0x53564d41 PR_SET_VMA_ANON_NAME = 0x0 + PR_SHADOW_STACK_ENABLE = 0x1 + PR_SHADOW_STACK_PUSH = 0x4 + PR_SHADOW_STACK_WRITE = 0x2 PR_SME_GET_VL = 0x40 PR_SME_SET_VL = 0x3f PR_SME_SET_VL_ONEXEC = 0x40000 @@ -2911,7 +2929,6 @@ const ( RTM_NEWNEXTHOP = 0x68 RTM_NEWNEXTHOPBUCKET = 0x74 RTM_NEWNSID = 0x58 - RTM_NEWNVLAN = 0x70 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 RTM_NEWROUTE = 0x18 @@ -2920,6 +2937,7 @@ const ( RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c RTM_NEWTUNNEL = 0x78 + RTM_NEWVLAN = 0x70 RTM_NR_FAMILIES = 0x1b RTM_NR_MSGTYPES = 0x6c RTM_SETDCB = 0x4f diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index c0d45e32..75207613 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -304,6 +306,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c731d24f..c68acda5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -305,6 +307,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 680018a4..a8c607ab 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -310,6 +312,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index a63909f3..18563dd8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -109,6 +109,7 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + GCS_MAGIC = 0x47435300 HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 @@ -119,6 +120,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -302,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 9b0a2573..22912cda 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -297,6 +299,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 958e6e06..29344eb3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 50c7f25b..20d51fb9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ced21d66..321b6090 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 226c0441..9bacdf1e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 3122737c..c2242726 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -358,6 +360,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index eb5d3467..6270c8ee 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -362,6 +364,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index e921ebc6..9966c194 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -362,6 +364,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 38ba81c5..848e5fcc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -294,6 +296,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 71f04009..669b2adb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -366,6 +368,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index c44a3133..4834e575 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -119,6 +119,8 @@ const ( IN_CLOEXEC = 0x400000 IN_NONBLOCK = 0x4000 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -357,6 +359,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x38 SCM_TIMESTAMPING_PKTINFO = 0x3c SCM_TIMESTAMPNS = 0x21 + SCM_TS_OPT_ID = 0x5a SCM_TXTIME = 0x3f SCM_WIFI_STATUS = 0x25 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 829b87fe..c6545413 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -141,6 +141,16 @@ import ( //go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so" //go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" +//go:cgo_import_dynamic libc_getpeerucred getpeerucred "libc.so" +//go:cgo_import_dynamic libc_ucred_get ucred_get "libc.so" +//go:cgo_import_dynamic libc_ucred_geteuid ucred_geteuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getegid ucred_getegid "libc.so" +//go:cgo_import_dynamic libc_ucred_getruid ucred_getruid "libc.so" +//go:cgo_import_dynamic libc_ucred_getrgid ucred_getrgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsuid ucred_getsuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsgid ucred_getsgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getpid ucred_getpid "libc.so" +//go:cgo_import_dynamic libc_ucred_free ucred_free "libc.so" //go:cgo_import_dynamic libc_port_create port_create "libc.so" //go:cgo_import_dynamic libc_port_associate port_associate "libc.so" //go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" @@ -280,6 +290,16 @@ import ( //go:linkname procgetpeername libc_getpeername //go:linkname procsetsockopt libc_setsockopt //go:linkname procrecvfrom libc_recvfrom +//go:linkname procgetpeerucred libc_getpeerucred +//go:linkname procucred_get libc_ucred_get +//go:linkname procucred_geteuid libc_ucred_geteuid +//go:linkname procucred_getegid libc_ucred_getegid +//go:linkname procucred_getruid libc_ucred_getruid +//go:linkname procucred_getrgid libc_ucred_getrgid +//go:linkname procucred_getsuid libc_ucred_getsuid +//go:linkname procucred_getsgid libc_ucred_getsgid +//go:linkname procucred_getpid libc_ucred_getpid +//go:linkname procucred_free libc_ucred_free //go:linkname procport_create libc_port_create //go:linkname procport_associate libc_port_associate //go:linkname procport_dissociate libc_port_dissociate @@ -420,6 +440,16 @@ var ( procgetpeername, procsetsockopt, procrecvfrom, + procgetpeerucred, + procucred_get, + procucred_geteuid, + procucred_getegid, + procucred_getruid, + procucred_getrgid, + procucred_getsuid, + procucred_getsgid, + procucred_getpid, + procucred_free, procport_create, procport_associate, procport_dissociate, @@ -2029,6 +2059,90 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getpeerucred(fd uintptr, ucred *uintptr) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetpeerucred)), 2, uintptr(fd), uintptr(unsafe.Pointer(ucred)), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGet(pid int) (ucred uintptr, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procucred_get)), 1, uintptr(pid), 0, 0, 0, 0, 0) + ucred = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGeteuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_geteuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetegid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getegid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetruid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getruid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetrgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getrgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetpid(ucred uintptr) (pid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getpid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredFree(ucred uintptr) { + sysvicall6(uintptr(unsafe.Pointer(&procucred_free)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func port_create() (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_create)), 0, 0, 0, 0, 0, 0, 0) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 524b0820..c79aaff3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -458,4 +458,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index f485dbf4..5eb45069 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -381,4 +381,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 70b35bf3..05e50297 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -422,4 +422,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 1893e2fe..38c53ec5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -325,4 +325,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 16a4017d..31d2e71a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -321,4 +321,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 7e567f1e..f4184a33 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -442,4 +442,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 4460 SYS_LSM_LIST_MODULES = 4461 SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 38ae55e5..05b99622 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -372,4 +372,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 5460 SYS_LSM_LIST_MODULES = 5461 SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 55e92e60..43a256e9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -372,4 +372,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 5460 SYS_LSM_LIST_MODULES = 5461 SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 60658d6a..eea5ddfc 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -442,4 +442,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 4460 SYS_LSM_LIST_MODULES = 4461 SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index e203e8a7..0d777bfb 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -449,4 +449,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 5944b97d..b4463650 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -421,4 +421,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index c66d416d..0c7d21c1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -421,4 +421,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index a5459e76..84053916 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -326,4 +326,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 01d86825..fcf1b790 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -387,4 +387,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 7b703e77..52d15b5f 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -400,4 +400,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 5537148d..a46abe64 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -4747,7 +4747,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14c + NL80211_ATTR_MAX = 0x14d NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_MATCH_SETS = 0x85 @@ -5519,7 +5519,7 @@ const ( NL80211_MNTR_FLAG_CONTROL = 0x3 NL80211_MNTR_FLAG_COOK_FRAMES = 0x5 NL80211_MNTR_FLAG_FCSFAIL = 0x1 - NL80211_MNTR_FLAG_MAX = 0x6 + NL80211_MNTR_FLAG_MAX = 0x7 NL80211_MNTR_FLAG_OTHER_BSS = 0x4 NL80211_MNTR_FLAG_PLCPFAIL = 0x2 NL80211_MPATH_FLAG_ACTIVE = 0x1 @@ -6174,3 +6174,5 @@ type SockDiagReq struct { Family uint8 Protocol uint8 } + +const RTM_NEWNVLAN = 0x70 diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index 4e613cf6..3ca814f5 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -43,8 +43,8 @@ type DLL struct { // LoadDLL loads DLL file into memory. // // Warning: using LoadDLL without an absolute path name is subject to -// DLL preloading attacks. To safely load a system DLL, use LazyDLL -// with System set to true, or use LoadLibraryEx directly. +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL], +// or use [LoadLibraryEx] directly. func LoadDLL(name string) (dll *DLL, err error) { namep, err := UTF16PtrFromString(name) if err != nil { @@ -271,6 +271,9 @@ func (d *LazyDLL) NewProc(name string) *LazyProc { } // NewLazyDLL creates new LazyDLL associated with DLL file. +// +// Warning: using NewLazyDLL without an absolute path name is subject to +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL]. func NewLazyDLL(name string) *LazyDLL { return &LazyDLL{Name: name} } @@ -410,7 +413,3 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { } return &DLL{Name: name, Handle: h}, nil } - -type errString string - -func (s errString) Error() string { return string(s) } diff --git a/vendor/modules.txt b/vendor/modules.txt index d98c8fe4..8b858249 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -197,8 +197,8 @@ go.uber.org/atomic # go.uber.org/multierr v1.9.0 ## explicit; go 1.19 go.uber.org/multierr -# golang.org/x/crypto v0.31.0 -## explicit; go 1.20 +# golang.org/x/crypto v0.35.0 +## explicit; go 1.23.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 @@ -214,11 +214,11 @@ golang.org/x/exp/slog/internal/buffer ## explicit; go 1.23.0 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sys v0.28.0 +# golang.org/x/sys v0.30.0 ## explicit; go 1.18 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/text v0.21.0 +# golang.org/x/text v0.22.0 ## explicit; go 1.18 golang.org/x/text/encoding golang.org/x/text/encoding/internal From 962b0be1e4418bff1e311e694d1b68579dd05a11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 14:18:27 -0400 Subject: [PATCH 13/35] chore(deps): bump actions/setup-go from 5.2.0 to 5.5.0 (#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.2.0 to 5.5.0.
Release notes

Sourced from actions/setup-go's releases.

v5.5.0

What's Changed

Bug fixes:

Dependency updates:

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v5.5.0

v5.4.0

What's Changed

Dependency updates :

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v5.4.0

v5.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v5.3.0

Commits
  • d35c59a chore: update discussions url (#527)
  • 29694d7 Add manifest validation and improve error handling (#586)
  • 78535dd Bump eslint-plugin-jest from 27.9.0 to 28.11.0 (#537)
  • bb65d88 Bump ts-jest from 29.1.2 to 29.3.2 (#582)
  • 7f17e83 Bump @​actions/glob from 0.4.0 to 0.5.0 (#573)
  • dca8468 Update self-hosted environment validation and bump undici version (#556)
  • 691cc35 upgrade actions/cache to 4.0.3 (#574)
  • 0aaccfd Bump undici from 5.28.4 to 5.28.5 (#541)
  • c4c1141 upgrade actions/cache to 4.0.2 (#568)
  • 5a083d0 Bump eslint-config-prettier from 8.10.0 to 10.0.1 (#536)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=5.2.0&new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Blackburn --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b8dc284..03beab01 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: run: pre-commit run --all-files - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 with: go-version-file: go.mod From 6ac887a659688a78fa33b451c5240b9c2db92678 Mon Sep 17 00:00:00 2001 From: Chris Blackburn Date: Tue, 13 May 2025 15:26:47 -0400 Subject: [PATCH 14/35] bump go to 1.24 (#166) #159 is complaining about Go version used to build golangci-lint doesn't match target version. That PR updates the toolchain to use Go 1.24.1, but I believe golangci-lint is being built with one of the versions [here](https://github.com/actions/runner-images/blob/ubuntu24/20250427.1/images/ubuntu/Ubuntu2404-Readme.md#go) (likely `1.23.8`, based on the error message) which are included with the `ubuntu-latest` image we're [using](https://github.com/launchdarkly/find-code-references-in-pull-request/blob/main/.github/workflows/main.yml#L10). The `Set up Go` job pulls the Go version from our go.mod file, so I'm hoping moving that step above the pre-commit step will resolve this for us. Note: Also bumping to Go 1.24 here --- .github/workflows/main.yml | 10 +++++----- go.mod | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 03beab01..9e814a50 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,6 +25,11 @@ jobs: with: python-version: '3.x' + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + with: + go-version-file: go.mod + - name: Install pre-commit run: | python -m pip install --upgrade pip @@ -33,11 +38,6 @@ jobs: - name: Run pre-commit hooks run: pre-commit run --all-files - - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 - with: - go-version-file: go.mod - - name: Install dependencies run: go mod tidy diff --git a/go.mod b/go.mod index 0dc961cc..260656bc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/launchdarkly/find-code-references-in-pull-request -go 1.23.0 +go 1.24 require ( github.com/Masterminds/sprig/v3 v3.3.0 From 9e311450a5deec84c9bd819eee97dca36beb90e9 Mon Sep 17 00:00:00 2001 From: Chris Blackburn Date: Wed, 14 May 2025 14:52:27 -0400 Subject: [PATCH 15/35] update code owners (#170) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 46e1e5da..0da4a455 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,3 @@ # These owners will be the default owners for everything in the repo. -* @launchdarkly/team-automation +* @launchdarkly/team-enterprise From b9e609841b4b6195a68078f3c345633915b10bc5 Mon Sep 17 00:00:00 2001 From: Chris Blackburn Date: Wed, 14 May 2025 14:57:10 -0400 Subject: [PATCH 16/35] bump viper incrementally (#168) #159 attempts to bump `spf13/viper` from `1.19.0` to `1.20.1`, but there is a failing GHA because the `e2e-tests` job gets the diff of the PR from the GitHub API, and the diff is so huge that it exceeds the max number of lines that can be returned from the GET pull request endpoint (ripping out a bunch of unneeded code). So this PR bumps the version incrementally to `1.20.0-alpha.1` which accounts for roughly half the changes, and passes the `e2e-tests` job. We can then immediately upgrade from `1.20.0-alpha.1` to `1.20.1` and I believe that diff should be small enough as well. This means we'd be on an alpha version for a brief time, which is a bit dicey, but I think acceptable. In any event, I'm not sure how else we're going to get around this issue, unless we want to dig into what the test is doing and try to come up with an acceptable substitute, but that feels substantially riskier, actually. Thoughts? --- go.mod | 14 +- go.sum | 16 +- .../mapstructure/v2}/.editorconfig | 6 +- .../go-viper/mapstructure/v2/.envrc | 4 + .../go-viper/mapstructure/v2/.gitignore | 6 + .../go-viper/mapstructure/v2/.golangci.yaml | 23 + .../mapstructure/v2}/CHANGELOG.md | 8 + .../mapstructure/v2}/LICENSE | 0 .../go-viper/mapstructure/v2/README.md | 80 +++ .../go-viper/mapstructure/v2/decode_hooks.go | 577 ++++++++++++++++++ .../go-viper/mapstructure/v2/flake.lock | 472 ++++++++++++++ .../mapstructure/v2}/flake.nix | 36 +- .../mapstructure/v2/internal/errors/errors.go | 11 + .../mapstructure/v2/internal/errors/join.go | 9 + .../v2/internal/errors/join_go1_19.go | 61 ++ .../mapstructure/v2}/mapstructure.go | 232 ++++--- .../mapstructure/v2/reflect_go1_19.go | 44 ++ .../mapstructure/v2/reflect_go1_20.go | 10 + .../mitchellh/mapstructure/README.md | 46 -- .../mitchellh/mapstructure/decode_hooks.go | 279 --------- .../mitchellh/mapstructure/error.go | 50 -- .../github.com/sagikazarmark/locafero/.envrc | 4 +- .../sagikazarmark/locafero/finder.go | 6 +- .../sagikazarmark/locafero/flake.lock | 303 +++++++-- .../sagikazarmark/locafero/flake.nix | 4 +- .../github.com/sagikazarmark/locafero/glob.go | 5 + .../sagikazarmark/locafero/glob_windows.go | 8 + .../github.com/sagikazarmark/slog-shim/.envrc | 4 - .../sagikazarmark/slog-shim/.gitignore | 4 - .../sagikazarmark/slog-shim/LICENSE | 27 - .../sagikazarmark/slog-shim/README.md | 81 --- .../sagikazarmark/slog-shim/attr.go | 74 --- .../sagikazarmark/slog-shim/attr_120.go | 75 --- .../sagikazarmark/slog-shim/flake.lock | 273 --------- .../sagikazarmark/slog-shim/handler.go | 45 -- .../sagikazarmark/slog-shim/handler_120.go | 45 -- .../sagikazarmark/slog-shim/json_handler.go | 23 - .../slog-shim/json_handler_120.go | 24 - .../sagikazarmark/slog-shim/level.go | 61 -- .../sagikazarmark/slog-shim/level_120.go | 61 -- .../sagikazarmark/slog-shim/logger.go | 98 --- .../sagikazarmark/slog-shim/logger_120.go | 99 --- .../sagikazarmark/slog-shim/record.go | 31 - .../sagikazarmark/slog-shim/record_120.go | 32 - .../sagikazarmark/slog-shim/text_handler.go | 23 - .../slog-shim/text_handler_120.go | 24 - .../sagikazarmark/slog-shim/value.go | 109 ---- .../sagikazarmark/slog-shim/value_120.go | 110 ---- vendor/github.com/spf13/viper/.envrc | 4 +- vendor/github.com/spf13/viper/README.md | 18 +- vendor/github.com/spf13/viper/experimental.go | 8 + vendor/github.com/spf13/viper/file.go | 54 +- vendor/github.com/spf13/viper/file_finder.go | 38 -- vendor/github.com/spf13/viper/finder.go | 47 ++ vendor/github.com/spf13/viper/flake.lock | 303 +++++++-- .../spf13/viper/internal/features/finder.go | 5 + .../viper/internal/features/finder_default.go | 5 + vendor/github.com/spf13/viper/logger.go | 39 +- vendor/github.com/spf13/viper/remote.go | 255 ++++++++ vendor/github.com/spf13/viper/util.go | 2 +- vendor/github.com/spf13/viper/viper.go | 320 +++------- vendor/golang.org/x/exp/LICENSE | 27 - vendor/golang.org/x/exp/PATENTS | 22 - .../x/exp/constraints/constraints.go | 50 -- vendor/golang.org/x/exp/slices/cmp.go | 44 -- vendor/golang.org/x/exp/slices/slices.go | 515 ---------------- vendor/golang.org/x/exp/slices/sort.go | 197 ------ .../golang.org/x/exp/slices/zsortanyfunc.go | 479 --------------- .../golang.org/x/exp/slices/zsortordered.go | 481 --------------- vendor/golang.org/x/exp/slog/attr.go | 102 ---- vendor/golang.org/x/exp/slog/doc.go | 316 ---------- vendor/golang.org/x/exp/slog/handler.go | 577 ------------------ .../x/exp/slog/internal/buffer/buffer.go | 84 --- .../x/exp/slog/internal/ignorepc.go | 9 - vendor/golang.org/x/exp/slog/json_handler.go | 336 ---------- vendor/golang.org/x/exp/slog/level.go | 201 ------ vendor/golang.org/x/exp/slog/logger.go | 343 ----------- vendor/golang.org/x/exp/slog/noplog.bench | 36 -- vendor/golang.org/x/exp/slog/record.go | 207 ------- vendor/golang.org/x/exp/slog/text_handler.go | 161 ----- vendor/golang.org/x/exp/slog/value.go | 456 -------------- vendor/golang.org/x/exp/slog/value_119.go | 53 -- vendor/golang.org/x/exp/slog/value_120.go | 39 -- vendor/modules.txt | 23 +- 84 files changed, 2448 insertions(+), 7045 deletions(-) rename vendor/github.com/{sagikazarmark/slog-shim => go-viper/mapstructure/v2}/.editorconfig (86%) create mode 100644 vendor/github.com/go-viper/mapstructure/v2/.envrc create mode 100644 vendor/github.com/go-viper/mapstructure/v2/.gitignore create mode 100644 vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml rename vendor/github.com/{mitchellh/mapstructure => go-viper/mapstructure/v2}/CHANGELOG.md (92%) rename vendor/github.com/{mitchellh/mapstructure => go-viper/mapstructure/v2}/LICENSE (100%) create mode 100644 vendor/github.com/go-viper/mapstructure/v2/README.md create mode 100644 vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go create mode 100644 vendor/github.com/go-viper/mapstructure/v2/flake.lock rename vendor/github.com/{sagikazarmark/slog-shim => go-viper/mapstructure/v2}/flake.nix (54%) create mode 100644 vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go create mode 100644 vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go create mode 100644 vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go rename vendor/github.com/{mitchellh/mapstructure => go-viper/mapstructure/v2}/mapstructure.go (92%) create mode 100644 vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go create mode 100644 vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go delete mode 100644 vendor/github.com/mitchellh/mapstructure/README.md delete mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go delete mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/sagikazarmark/locafero/glob.go create mode 100644 vendor/github.com/sagikazarmark/locafero/glob_windows.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/.envrc delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/.gitignore delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/LICENSE delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/README.md delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/attr.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/attr_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/flake.lock delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/handler.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/handler_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/json_handler.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/level.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/level_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/logger.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/logger_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/record.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/record_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/text_handler.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/value.go delete mode 100644 vendor/github.com/sagikazarmark/slog-shim/value_120.go create mode 100644 vendor/github.com/spf13/viper/experimental.go delete mode 100644 vendor/github.com/spf13/viper/file_finder.go create mode 100644 vendor/github.com/spf13/viper/finder.go create mode 100644 vendor/github.com/spf13/viper/internal/features/finder.go create mode 100644 vendor/github.com/spf13/viper/internal/features/finder_default.go create mode 100644 vendor/github.com/spf13/viper/remote.go delete mode 100644 vendor/golang.org/x/exp/LICENSE delete mode 100644 vendor/golang.org/x/exp/PATENTS delete mode 100644 vendor/golang.org/x/exp/constraints/constraints.go delete mode 100644 vendor/golang.org/x/exp/slices/cmp.go delete mode 100644 vendor/golang.org/x/exp/slices/slices.go delete mode 100644 vendor/golang.org/x/exp/slices/sort.go delete mode 100644 vendor/golang.org/x/exp/slices/zsortanyfunc.go delete mode 100644 vendor/golang.org/x/exp/slices/zsortordered.go delete mode 100644 vendor/golang.org/x/exp/slog/attr.go delete mode 100644 vendor/golang.org/x/exp/slog/doc.go delete mode 100644 vendor/golang.org/x/exp/slog/handler.go delete mode 100644 vendor/golang.org/x/exp/slog/internal/buffer/buffer.go delete mode 100644 vendor/golang.org/x/exp/slog/internal/ignorepc.go delete mode 100644 vendor/golang.org/x/exp/slog/json_handler.go delete mode 100644 vendor/golang.org/x/exp/slog/level.go delete mode 100644 vendor/golang.org/x/exp/slog/logger.go delete mode 100644 vendor/golang.org/x/exp/slog/noplog.bench delete mode 100644 vendor/golang.org/x/exp/slog/record.go delete mode 100644 vendor/golang.org/x/exp/slog/text_handler.go delete mode 100644 vendor/golang.org/x/exp/slog/value.go delete mode 100644 vendor/golang.org/x/exp/slog/value_119.go delete mode 100644 vendor/golang.org/x/exp/slog/value_120.go diff --git a/go.mod b/go.mod index 260656bc..f9de4864 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/sourcegraph/go-diff v0.6.1 - github.com/spf13/viper v1.19.0 + github.com/spf13/viper v1.20.0-alpha.1 github.com/stretchr/testify v1.10.0 golang.org/x/oauth2 v0.30.0 ) @@ -21,12 +21,14 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect ) require ( @@ -39,17 +41,14 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/kyoh86/xdg v1.2.0 // indirect github.com/launchdarkly/api-client-go/v15 v15.1.0 github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f // indirect - github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -68,7 +67,6 @@ require ( golang.org/x/sys v0.30.0 // indirect golang.org/x/text v0.22.0 // indirect golang.org/x/tools v0.28.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6fb9b008..68be30a3 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,8 @@ github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkv github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= +github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -170,8 +172,6 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= @@ -197,10 +197,8 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= +github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -215,8 +213,8 @@ github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= -github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spf13/viper v1.20.0-alpha.1 h1:ScUDXU3yX4i/I1ovQQtaGe9kwl63fGzG3UsFr+pGtyY= +github.com/spf13/viper v1.20.0-alpha.1/go.mod h1:VJcuMrHwg6XArbUYF9KBRrFpavzx9NrQMFtdcRsZCLs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -262,8 +260,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig similarity index 86% rename from vendor/github.com/sagikazarmark/slog-shim/.editorconfig rename to vendor/github.com/go-viper/mapstructure/v2/.editorconfig index 1fb0e1be..1f664d13 100644 --- a/vendor/github.com/sagikazarmark/slog-shim/.editorconfig +++ b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig @@ -8,11 +8,11 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[*.nix] -indent_size = 2 +[*.go] +indent_style = tab [{Makefile,*.mk}] indent_style = tab -[Taskfile.yaml] +[*.nix] indent_size = 2 diff --git a/vendor/github.com/go-viper/mapstructure/v2/.envrc b/vendor/github.com/go-viper/mapstructure/v2/.envrc new file mode 100644 index 00000000..2e0f9f5f --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/.envrc @@ -0,0 +1,4 @@ +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" +fi +use flake . --impure diff --git a/vendor/github.com/go-viper/mapstructure/v2/.gitignore b/vendor/github.com/go-viper/mapstructure/v2/.gitignore new file mode 100644 index 00000000..470e7ca2 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/.gitignore @@ -0,0 +1,6 @@ +/.devenv/ +/.direnv/ +/.pre-commit-config.yaml +/bin/ +/build/ +/var/ diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml new file mode 100644 index 00000000..763143aa --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -0,0 +1,23 @@ +run: + timeout: 5m + +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/go-viper/mapstructure) + golint: + min-confidence: 0 + goimports: + local-prefixes: github.com/go-viper/maptstructure + +linters: + disable-all: true + enable: + - gci + - gofmt + - gofumpt + - goimports + - staticcheck + # - stylecheck diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md similarity index 92% rename from vendor/github.com/mitchellh/mapstructure/CHANGELOG.md rename to vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md index c7582349..afd44e5f 100644 --- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md +++ b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md @@ -1,3 +1,11 @@ +> [!WARNING] +> As of v2 of this library, change log can be found in GitHub releases. + +## 1.5.1 + +* Wrap errors so they're compatible with `errors.Is` and `errors.As` [GH-282] +* Fix map of slices not decoding properly in certain cases. [GH-266] + ## 1.5.0 * New option `IgnoreUntaggedFields` to ignore decoding to any fields diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/go-viper/mapstructure/v2/LICENSE similarity index 100% rename from vendor/github.com/mitchellh/mapstructure/LICENSE rename to vendor/github.com/go-viper/mapstructure/v2/LICENSE diff --git a/vendor/github.com/go-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md new file mode 100644 index 00000000..dd5ec69d --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -0,0 +1,80 @@ +# mapstructure + +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI) +[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +```shell +go get github.com/go-viper/mapstructure/v2 +``` + +## Migrating from `github.com/mitchellh/mapstructure` + +[@mitchehllh](https://github.com/mitchellh) announced his intent to archive some of his unmaintained projects (see [here](https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc) and [here](https://github.com/mitchellh/mapstructure/issues/349)). This is a repository achieved the "blessed fork" status. + +You can migrate to this package by changing your import paths in your Go files to `github.com/go-viper/mapstructure/v2`. +The API is the same, so you don't need to change anything else. + +Here is a script that can help you with the migration: + +```shell +sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +``` + +If you need more time to migrate your code, that is absolutely fine. + +Some of the latest fixes are backported to the v1 release branch of this package, so you can use the Go modules `replace` feature until you are ready to migrate: + +```shell +replace github.com/mitchellh/mapstructure => github.com/go-viper/mapstructure v1.6.0 +``` + +## Usage & Example + +For usage and examples see the [documentation](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. + +## Credits + +Mapstructure was originally created by [@mitchellh](https://github.com/mitchellh). +This is a maintained fork of the original library. + +Read more about the reasons for the fork [here](https://github.com/mitchellh/mapstructure/issues/349). + +## License + +The project is licensed under the [MIT License](LICENSE). diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go new file mode 100644 index 00000000..24d82f07 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -0,0 +1,577 @@ +package mapstructure + +import ( + "encoding" + "errors" + "fmt" + "net" + "net/netip" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + var f3 DecodeHookFuncValue + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2, f3} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Value, to reflect.Value, +) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from.Type(), to.Type(), from.Interface()) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), from.Interface()) + case DecodeHookFuncValue: + return f(from, to) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + var err error + data := f.Interface() + + newFrom := f + for _, f1 := range fs { + data, err = DecodeHookExec(f1, newFrom, t) + if err != nil { + return nil, err + } + newFrom = reflect.ValueOf(data) + } + + return data, nil + } +} + +// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. +// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. +func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { + return func(a, b reflect.Value) (interface{}, error) { + var allErrs string + var out interface{} + var err error + + for _, f := range ff { + out, err = DecodeHookExec(f, a, b) + if err != nil { + allErrs += err.Error() + "\n" + continue + } + + return out, nil + } + + return nil, errors.New(allErrs) + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.SliceOf(f) { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}, +) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} + +func RecursiveStructToMapHookFunc() DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + if f.Kind() != reflect.Struct { + return f.Interface(), nil + } + + var i interface{} = struct{}{} + if t.Type() != reflect.TypeOf(&i).Elem() { + return f.Interface(), nil + } + + m := make(map[string]interface{}) + t.Set(reflect.ValueOf(m)) + + return f.Interface(), nil + } +} + +// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies +// strings to the UnmarshalText function, when the target type +// implements the encoding.TextUnmarshaler interface +func TextUnmarshallerHookFunc() DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + result := reflect.New(t).Interface() + unmarshaller, ok := result.(encoding.TextUnmarshaler) + if !ok { + return data, nil + } + str, ok := data.(string) + if !ok { + str = reflect.Indirect(reflect.ValueOf(&data)).Elem().String() + } + if err := unmarshaller.UnmarshalText([]byte(str)); err != nil { + return nil, err + } + return result, nil + } +} + +// StringToNetIPAddrHookFunc returns a DecodeHookFunc that converts +// strings to netip.Addr. +func StringToNetIPAddrHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.Addr{}) { + return data, nil + } + + // Convert it by parsing + return netip.ParseAddr(data.(string)) + } +} + +// StringToNetIPAddrPortHookFunc returns a DecodeHookFunc that converts +// strings to netip.AddrPort. +func StringToNetIPAddrPortHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.AddrPort{}) { + return data, nil + } + + // Convert it by parsing + return netip.ParseAddrPort(data.(string)) + } +} + +// StringToBasicTypeHookFunc returns a DecodeHookFunc that converts +// strings to basic types. +// int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, float32, float64, bool, byte, rune, complex64, complex128 +func StringToBasicTypeHookFunc() DecodeHookFunc { + return ComposeDecodeHookFunc( + StringToInt8HookFunc(), + StringToUint8HookFunc(), + StringToInt16HookFunc(), + StringToUint16HookFunc(), + StringToInt32HookFunc(), + StringToUint32HookFunc(), + StringToInt64HookFunc(), + StringToUint64HookFunc(), + StringToIntHookFunc(), + StringToUintHookFunc(), + StringToFloat32HookFunc(), + StringToFloat64HookFunc(), + StringToBoolHookFunc(), + // byte and rune are aliases for uint8 and int32 respectively + // StringToByteHookFunc(), + // StringToRuneHookFunc(), + StringToComplex64HookFunc(), + StringToComplex128HookFunc(), + ) +} + +// StringToInt8HookFunc returns a DecodeHookFunc that converts +// strings to int8. +func StringToInt8HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int8 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 8) + return int8(i64), err + } +} + +// StringToUint8HookFunc returns a DecodeHookFunc that converts +// strings to uint8. +func StringToUint8HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 8) + return uint8(u64), err + } +} + +// StringToInt16HookFunc returns a DecodeHookFunc that converts +// strings to int16. +func StringToInt16HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int16 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 16) + return int16(i64), err + } +} + +// StringToUint16HookFunc returns a DecodeHookFunc that converts +// strings to uint16. +func StringToUint16HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 16) + return uint16(u64), err + } +} + +// StringToInt32HookFunc returns a DecodeHookFunc that converts +// strings to int32. +func StringToInt32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int32 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 32) + return int32(i64), err + } +} + +// StringToUint32HookFunc returns a DecodeHookFunc that converts +// strings to uint32. +func StringToUint32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 32) + return uint32(u64), err + } +} + +// StringToInt64HookFunc returns a DecodeHookFunc that converts +// strings to int64. +func StringToInt64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseInt(data.(string), 0, 64) + } +} + +// StringToUint64HookFunc returns a DecodeHookFunc that converts +// strings to uint64. +func StringToUint64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseUint(data.(string), 0, 64) + } +} + +// StringToIntHookFunc returns a DecodeHookFunc that converts +// strings to int. +func StringToIntHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 0) + return int(i64), err + } +} + +// StringToUintHookFunc returns a DecodeHookFunc that converts +// strings to uint. +func StringToUintHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 0) + return uint(u64), err + } +} + +// StringToFloat32HookFunc returns a DecodeHookFunc that converts +// strings to float32. +func StringToFloat32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Float32 { + return data, nil + } + + // Convert it by parsing + f64, err := strconv.ParseFloat(data.(string), 32) + return float32(f64), err + } +} + +// StringToFloat64HookFunc returns a DecodeHookFunc that converts +// strings to float64. +func StringToFloat64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Float64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseFloat(data.(string), 64) + } +} + +// StringToBoolHookFunc returns a DecodeHookFunc that converts +// strings to bool. +func StringToBoolHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Bool { + return data, nil + } + + // Convert it by parsing + return strconv.ParseBool(data.(string)) + } +} + +// StringToByteHookFunc returns a DecodeHookFunc that converts +// strings to byte. +func StringToByteHookFunc() DecodeHookFunc { + return StringToUint8HookFunc() +} + +// StringToRuneHookFunc returns a DecodeHookFunc that converts +// strings to rune. +func StringToRuneHookFunc() DecodeHookFunc { + return StringToInt32HookFunc() +} + +// StringToComplex64HookFunc returns a DecodeHookFunc that converts +// strings to complex64. +func StringToComplex64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 { + return data, nil + } + + // Convert it by parsing + c128, err := strconv.ParseComplex(data.(string), 64) + return complex64(c128), err + } +} + +// StringToComplex128HookFunc returns a DecodeHookFunc that converts +// strings to complex128. +func StringToComplex128HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseComplex(data.(string), 128) + } +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/vendor/github.com/go-viper/mapstructure/v2/flake.lock new file mode 100644 index 00000000..4bea8154 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.lock @@ -0,0 +1,472 @@ +{ + "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1717245169, + "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "owner": "cachix", + "repo": "devenv", + "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717112898, + "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_3" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/vendor/github.com/go-viper/mapstructure/v2/flake.nix similarity index 54% rename from vendor/github.com/sagikazarmark/slog-shim/flake.nix rename to vendor/github.com/go-viper/mapstructure/v2/flake.nix index 7239bbc2..4ed0f533 100644 --- a/vendor/github.com/sagikazarmark/slog-shim/flake.nix +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.nix @@ -1,7 +1,6 @@ { inputs = { - # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - nixpkgs.url = "github:NixOS/nixpkgs/master"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; devenv.url = "github:cachix/devenv"; }; @@ -19,38 +18,21 @@ default = { languages = { go.enable = true; - go.package = pkgs.lib.mkDefault pkgs.go_1_21; }; - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; - - ci = devenv.shells.default; - - ci_1_19 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_19; + pre-commit.hooks = { + nixpkgs-fmt.enable = true; }; - }; - ci_1_20 = { - imports = [ devenv.shells.ci ]; + packages = with pkgs; [ + golangci-lint + ]; - languages = { - go.package = pkgs.go_1_20; - }; + # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 + containers = pkgs.lib.mkForce { }; }; - ci_1_21 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_21; - }; - }; + ci = devenv.shells.default; }; }; }; diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go new file mode 100644 index 00000000..d1c15e47 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go @@ -0,0 +1,11 @@ +package errors + +import "errors" + +func New(text string) error { + return errors.New(text) +} + +func As(err error, target interface{}) bool { + return errors.As(err, target) +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go new file mode 100644 index 00000000..d74e3a0b --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go @@ -0,0 +1,9 @@ +//go:build go1.20 + +package errors + +import "errors" + +func Join(errs ...error) error { + return errors.Join(errs...) +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go new file mode 100644 index 00000000..700b4022 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go @@ -0,0 +1,61 @@ +//go:build !go1.20 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package errors + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if every value in errs is nil. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. +// +// A non-nil error returned by Join implements the Unwrap() []error method. +func Join(errs ...error) error { + n := 0 + for _, err := range errs { + if err != nil { + n++ + } + } + if n == 0 { + return nil + } + e := &joinError{ + errs: make([]error, 0, n), + } + for _, err := range errs { + if err != nil { + e.errs = append(e.errs, err) + } + } + return e +} + +type joinError struct { + errs []error +} + +func (e *joinError) Error() string { + // Since Join returns nil if every value in errs is nil, + // e.errs cannot be empty. + if len(e.errs) == 1 { + return e.errs[0].Error() + } + + b := []byte(e.errs[0].Error()) + for _, err := range e.errs[1:] { + b = append(b, '\n') + b = append(b, err.Error()...) + } + // At this point, b has at least one byte '\n'. + // return unsafe.String(&b[0], len(b)) + return string(b) +} + +func (e *joinError) Unwrap() []error { + return e.errs +} diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go similarity index 92% rename from vendor/github.com/mitchellh/mapstructure/mapstructure.go rename to vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index 1efb22ac..4b54fae0 100644 --- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -9,84 +9,84 @@ // // The simplest function to start with is Decode. // -// Field Tags +// # Field Tags // // When decoding to a struct, mapstructure will use the field name by // default to perform the mapping. For example, if a struct has a field // "Username" then mapstructure will look for a key in the source value // of "username" (case insensitive). // -// type User struct { -// Username string -// } +// type User struct { +// Username string +// } // // You can change the behavior of mapstructure by using struct tags. // The default struct tag that mapstructure looks for is "mapstructure" // but you can customize it using DecoderConfig. // -// Renaming Fields +// # Renaming Fields // // To rename the key that mapstructure looks for, use the "mapstructure" // tag and set a value directly. For example, to change the "username" example // above to "user": // -// type User struct { -// Username string `mapstructure:"user"` -// } +// type User struct { +// Username string `mapstructure:"user"` +// } // -// Embedded Structs and Squashing +// # Embedded Structs and Squashing // // Embedded structs are treated as if they're another field with that name. // By default, the two structs below are equivalent when decoding with // mapstructure: // -// type Person struct { -// Name string -// } +// type Person struct { +// Name string +// } // -// type Friend struct { -// Person -// } +// type Friend struct { +// Person +// } // -// type Friend struct { -// Person Person -// } +// type Friend struct { +// Person Person +// } // // This would require an input that looks like below: // -// map[string]interface{}{ -// "person": map[string]interface{}{"name": "alice"}, -// } +// map[string]interface{}{ +// "person": map[string]interface{}{"name": "alice"}, +// } // // If your "person" value is NOT nested, then you can append ",squash" to // your tag value and mapstructure will treat it as if the embedded struct // were part of the struct directly. Example: // -// type Friend struct { -// Person `mapstructure:",squash"` -// } +// type Friend struct { +// Person `mapstructure:",squash"` +// } // // Now the following input would be accepted: // -// map[string]interface{}{ -// "name": "alice", -// } +// map[string]interface{}{ +// "name": "alice", +// } // // When decoding from a struct to a map, the squash tag squashes the struct // fields into a single map. Using the example structs from above: // -// Friend{Person: Person{Name: "alice"}} +// Friend{Person: Person{Name: "alice"}} // // Will be decoded into a map: // -// map[string]interface{}{ -// "name": "alice", -// } +// map[string]interface{}{ +// "name": "alice", +// } // // DecoderConfig has a field that changes the behavior of mapstructure // to always squash embedded structs. // -// Remainder Values +// # Remainder Values // // If there are any unmapped keys in the source value, mapstructure by // default will silently ignore them. You can error by setting ErrorUnused @@ -98,20 +98,20 @@ // probably be a "map[string]interface{}" or "map[interface{}]interface{}". // See example below: // -// type Friend struct { -// Name string -// Other map[string]interface{} `mapstructure:",remain"` -// } +// type Friend struct { +// Name string +// Other map[string]interface{} `mapstructure:",remain"` +// } // // Given the input below, Other would be populated with the other // values that weren't used (everything but "name"): // -// map[string]interface{}{ -// "name": "bob", -// "address": "123 Maple St.", -// } +// map[string]interface{}{ +// "name": "bob", +// "address": "123 Maple St.", +// } // -// Omit Empty Values +// # Omit Empty Values // // When decoding from a struct to any other value, you may use the // ",omitempty" suffix on your tag to omit that value if it equates to @@ -122,37 +122,37 @@ // field value is zero and a numeric type, the field is empty, and it won't // be encoded into the destination type. // -// type Source struct { -// Age int `mapstructure:",omitempty"` -// } +// type Source struct { +// Age int `mapstructure:",omitempty"` +// } // -// Unexported fields +// # Unexported fields // // Since unexported (private) struct fields cannot be set outside the package // where they are defined, the decoder will simply skip them. // // For this output type definition: // -// type Exported struct { -// private string // this unexported field will be skipped -// Public string -// } +// type Exported struct { +// private string // this unexported field will be skipped +// Public string +// } // // Using this map as input: // -// map[string]interface{}{ -// "private": "I will be ignored", -// "Public": "I made it through!", -// } +// map[string]interface{}{ +// "private": "I will be ignored", +// "Public": "I made it through!", +// } // // The following struct will be decoded: // -// type Exported struct { -// private: "" // field is left with an empty string (zero value) -// Public: "I made it through!" -// } +// type Exported struct { +// private: "" // field is left with an empty string (zero value) +// Public: "I made it through!" +// } // -// Other Configuration +// # Other Configuration // // mapstructure is highly configurable. See the DecoderConfig struct // for other features and options that are supported. @@ -160,12 +160,13 @@ package mapstructure import ( "encoding/json" - "errors" "fmt" "reflect" "sort" "strconv" "strings" + + "github.com/go-viper/mapstructure/v2/internal/errors" ) // DecodeHookFunc is the callback function that can be used for @@ -414,7 +415,15 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { // Decode decodes the given raw interface to the target pointer specified // by the configuration. func (d *Decoder) Decode(input interface{}) error { - return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) + err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) + + // Retain some of the original behavior when multiple errors ocurr + var joinedErr interface{ Unwrap() []error } + if errors.As(err, &joinedErr) { + return fmt.Errorf("decoding failed due to the following error(s):\n\n%w", err) + } + + return err } // Decodes an unknown data type into a specific reflection value. @@ -458,7 +467,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e var err error input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) if err != nil { - return fmt.Errorf("error decoding '%s': %s", name, err) + return fmt.Errorf("error decoding '%s': %w", name, err) } } @@ -478,6 +487,8 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e err = d.decodeUint(name, input, outVal) case reflect.Float32: err = d.decodeFloat(name, input, outVal) + case reflect.Complex64: + err = d.decodeComplex(name, input, outVal) case reflect.Struct: err = d.decodeStruct(name, input, outVal) case reflect.Map: @@ -796,6 +807,22 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) return nil } +func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Complex64: + val.SetComplex(dataVal.Complex()) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { valType := val.Type() valKeyType := valType.Key() @@ -811,8 +838,14 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er valMap = reflect.MakeMap(mapType) } + dataVal := reflect.ValueOf(data) + + // Resolve any levels of indirection + for dataVal.Kind() == reflect.Pointer { + dataVal = reflect.Indirect(dataVal) + } + // Check input type and based on the input type jump to the proper func - dataVal := reflect.Indirect(reflect.ValueOf(data)) switch dataVal.Kind() { case reflect.Map: return d.decodeMapFromMap(name, dataVal, val, valMap) @@ -857,7 +890,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle valElemType := valType.Elem() // Accumulate errors - errors := make([]string, 0) + var errs []error // If the input data is empty, then we just match what the input data is. if dataVal.Len() == 0 { @@ -879,7 +912,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle // First decode the key into the proper type currentKey := reflect.Indirect(reflect.New(valKeyType)) if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) continue } @@ -887,7 +920,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle v := dataVal.MapIndex(k).Interface() currentVal := reflect.Indirect(reflect.New(valElemType)) if err := d.decode(fieldName, v, currentVal); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) continue } @@ -897,12 +930,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle // Set the built up map to the value val.Set(valMap) - // If we had errors, return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil + return errors.Join(errs...) } func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { @@ -956,6 +984,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re if v.Kind() != reflect.Struct { return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) } + } else { + if strings.Index(tagValue[index+1:], "remain") != -1 { + if v.Kind() != reflect.Map { + return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type()) + } + + ptr := v.MapRange() + for ptr.Next() { + valMap.SetMapIndex(ptr.Key(), ptr.Value()) + } + continue + } } if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { keyName = keyNameTagValue @@ -1123,10 +1163,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) if valSlice.IsNil() || d.config.ZeroFields { // Make a new slice to hold our result, same size as the original data. valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } else if valSlice.Len() > dataVal.Len() { + valSlice = valSlice.Slice(0, dataVal.Len()) } // Accumulate any errors - errors := make([]string, 0) + var errs []error for i := 0; i < dataVal.Len(); i++ { currentData := dataVal.Index(i).Interface() @@ -1137,19 +1179,14 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) fieldName := name + "[" + strconv.Itoa(i) + "]" if err := d.decode(fieldName, currentData, currentField); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) } } // Finally, set the value to the slice we built up val.Set(valSlice) - // If there were errors, we return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil + return errors.Join(errs...) } func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { @@ -1161,7 +1198,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) valArray := val - if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + if isComparable(valArray) && valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { // Check input type if dataValKind != reflect.Array && dataValKind != reflect.Slice { if d.config.WeaklyTypedInput { @@ -1188,7 +1225,6 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) if dataVal.Len() > arrayType.Len() { return fmt.Errorf( "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) - } // Make a new array to hold our result, same size as the original data. @@ -1196,7 +1232,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) } // Accumulate any errors - errors := make([]string, 0) + var errs []error for i := 0; i < dataVal.Len(); i++ { currentData := dataVal.Index(i).Interface() @@ -1204,19 +1240,14 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) fieldName := name + "[" + strconv.Itoa(i) + "]" if err := d.decode(fieldName, currentData, currentField); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) } } // Finally, set the value to the array we built up val.Set(valArray) - // If there were errors, we return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil + return errors.Join(errs...) } func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { @@ -1278,7 +1309,8 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } targetValKeysUnused := make(map[interface{}]struct{}) - errors := make([]string, 0) + + var errs []error // This slice will keep track of all the structs we'll be decoding. // There can be more than one struct if there are embedded structs @@ -1332,8 +1364,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e if squash { if fieldVal.Kind() != reflect.Struct { - errors = appendErrors(errors, - fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) } else { structs = append(structs, fieldVal) } @@ -1356,6 +1387,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e fieldName := field.Name tagValue := field.Tag.Get(d.config.TagName) + if tagValue == "" && d.config.IgnoreUntaggedFields { + continue + } tagValue = strings.SplitN(tagValue, ",", 2)[0] if tagValue != "" { fieldName = tagValue @@ -1409,7 +1443,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) } } @@ -1424,7 +1458,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // Decode it as-if we were just decoding this map onto our map. if err := d.decodeMap(name, remain, remainField.val); err != nil { - errors = appendErrors(errors, err) + errs = append(errs, err) } // Set the map to nil so we have none so that the next check will @@ -1440,7 +1474,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e sort.Strings(keys) err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) - errors = appendErrors(errors, err) + errs = append(errs, err) } if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { @@ -1451,11 +1485,11 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e sort.Strings(keys) err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) - errors = appendErrors(errors, err) + errs = append(errs, err) } - if len(errors) > 0 { - return &Error{errors} + if err := errors.Join(errs...); err != nil { + return err } // Add the unused keys to the list of unused keys if we're tracking metadata @@ -1509,6 +1543,8 @@ func getKind(val reflect.Value) reflect.Kind { return reflect.Uint case kind >= reflect.Float32 && kind <= reflect.Float64: return reflect.Float32 + case kind >= reflect.Complex64 && kind <= reflect.Complex128: + return reflect.Complex64 default: return kind } diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go new file mode 100644 index 00000000..d0913fff --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go @@ -0,0 +1,44 @@ +//go:build !go1.20 + +package mapstructure + +import "reflect" + +func isComparable(v reflect.Value) bool { + k := v.Kind() + switch k { + case reflect.Invalid: + return false + + case reflect.Array: + switch v.Type().Elem().Kind() { + case reflect.Interface, reflect.Array, reflect.Struct: + for i := 0; i < v.Type().Len(); i++ { + // if !v.Index(i).Comparable() { + if !isComparable(v.Index(i)) { + return false + } + } + return true + } + return v.Type().Comparable() + + case reflect.Interface: + // return v.Elem().Comparable() + return isComparable(v.Elem()) + + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + return false + + // if !v.Field(i).Comparable() { + if !isComparable(v.Field(i)) { + return false + } + } + return true + + default: + return v.Type().Comparable() + } +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go new file mode 100644 index 00000000..f8255a1b --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go @@ -0,0 +1,10 @@ +//go:build go1.20 + +package mapstructure + +import "reflect" + +// TODO: remove once we drop support for Go <1.20 +func isComparable(v reflect.Value) bool { + return v.Comparable() +} diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md deleted file mode 100644 index 0018dc7d..00000000 --- a/vendor/github.com/mitchellh/mapstructure/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) - -mapstructure is a Go library for decoding generic map values to structures -and vice versa, while providing helpful error handling. - -This library is most useful when decoding values from some data stream (JSON, -Gob, etc.) where you don't _quite_ know the structure of the underlying data -until you read a part of it. You can therefore read a `map[string]interface{}` -and use this library to decode it into the proper underlying native Go -structure. - -## Installation - -Standard `go get`: - -``` -$ go get github.com/mitchellh/mapstructure -``` - -## Usage & Example - -For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). - -The `Decode` function has examples associated with it there. - -## But Why?! - -Go offers fantastic standard libraries for decoding formats such as JSON. -The standard method is to have a struct pre-created, and populate that struct -from the bytes of the encoded format. This is great, but the problem is if -you have configuration or an encoding that changes slightly depending on -specific fields. For example, consider this JSON: - -```json -{ - "type": "person", - "name": "Mitchell" -} -``` - -Perhaps we can't populate a specific structure without first reading -the "type" field from the JSON. We could always do two passes over the -decoding of the JSON (reading the "type" first, and the rest later). -However, it is much simpler to just decode this into a `map[string]interface{}` -structure, read the "type" key, then use something like this library -to decode it into the proper structure. diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go deleted file mode 100644 index 3a754ca7..00000000 --- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go +++ /dev/null @@ -1,279 +0,0 @@ -package mapstructure - -import ( - "encoding" - "errors" - "fmt" - "net" - "reflect" - "strconv" - "strings" - "time" -) - -// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns -// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. -func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { - // Create variables here so we can reference them with the reflect pkg - var f1 DecodeHookFuncType - var f2 DecodeHookFuncKind - var f3 DecodeHookFuncValue - - // Fill in the variables into this interface and the rest is done - // automatically using the reflect package. - potential := []interface{}{f1, f2, f3} - - v := reflect.ValueOf(h) - vt := v.Type() - for _, raw := range potential { - pt := reflect.ValueOf(raw).Type() - if vt.ConvertibleTo(pt) { - return v.Convert(pt).Interface() - } - } - - return nil -} - -// DecodeHookExec executes the given decode hook. This should be used -// since it'll naturally degrade to the older backwards compatible DecodeHookFunc -// that took reflect.Kind instead of reflect.Type. -func DecodeHookExec( - raw DecodeHookFunc, - from reflect.Value, to reflect.Value) (interface{}, error) { - - switch f := typedDecodeHook(raw).(type) { - case DecodeHookFuncType: - return f(from.Type(), to.Type(), from.Interface()) - case DecodeHookFuncKind: - return f(from.Kind(), to.Kind(), from.Interface()) - case DecodeHookFuncValue: - return f(from, to) - default: - return nil, errors.New("invalid decode hook signature") - } -} - -// ComposeDecodeHookFunc creates a single DecodeHookFunc that -// automatically composes multiple DecodeHookFuncs. -// -// The composed funcs are called in order, with the result of the -// previous transformation. -func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { - var err error - data := f.Interface() - - newFrom := f - for _, f1 := range fs { - data, err = DecodeHookExec(f1, newFrom, t) - if err != nil { - return nil, err - } - newFrom = reflect.ValueOf(data) - } - - return data, nil - } -} - -// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. -// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. -func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { - return func(a, b reflect.Value) (interface{}, error) { - var allErrs string - var out interface{} - var err error - - for _, f := range ff { - out, err = DecodeHookExec(f, a, b) - if err != nil { - allErrs += err.Error() + "\n" - continue - } - - return out, nil - } - - return nil, errors.New(allErrs) - } -} - -// StringToSliceHookFunc returns a DecodeHookFunc that converts -// string to []string by splitting on the given sep. -func StringToSliceHookFunc(sep string) DecodeHookFunc { - return func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - if f != reflect.String || t != reflect.Slice { - return data, nil - } - - raw := data.(string) - if raw == "" { - return []string{}, nil - } - - return strings.Split(raw, sep), nil - } -} - -// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts -// strings to time.Duration. -func StringToTimeDurationHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(time.Duration(5)) { - return data, nil - } - - // Convert it by parsing - return time.ParseDuration(data.(string)) - } -} - -// StringToIPHookFunc returns a DecodeHookFunc that converts -// strings to net.IP -func StringToIPHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(net.IP{}) { - return data, nil - } - - // Convert it by parsing - ip := net.ParseIP(data.(string)) - if ip == nil { - return net.IP{}, fmt.Errorf("failed parsing ip %v", data) - } - - return ip, nil - } -} - -// StringToIPNetHookFunc returns a DecodeHookFunc that converts -// strings to net.IPNet -func StringToIPNetHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(net.IPNet{}) { - return data, nil - } - - // Convert it by parsing - _, net, err := net.ParseCIDR(data.(string)) - return net, err - } -} - -// StringToTimeHookFunc returns a DecodeHookFunc that converts -// strings to time.Time. -func StringToTimeHookFunc(layout string) DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(time.Time{}) { - return data, nil - } - - // Convert it by parsing - return time.Parse(layout, data.(string)) - } -} - -// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to -// the decoder. -// -// Note that this is significantly different from the WeaklyTypedInput option -// of the DecoderConfig. -func WeaklyTypedHook( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - dataVal := reflect.ValueOf(data) - switch t { - case reflect.String: - switch f { - case reflect.Bool: - if dataVal.Bool() { - return "1", nil - } - return "0", nil - case reflect.Float32: - return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil - case reflect.Int: - return strconv.FormatInt(dataVal.Int(), 10), nil - case reflect.Slice: - dataType := dataVal.Type() - elemKind := dataType.Elem().Kind() - if elemKind == reflect.Uint8 { - return string(dataVal.Interface().([]uint8)), nil - } - case reflect.Uint: - return strconv.FormatUint(dataVal.Uint(), 10), nil - } - } - - return data, nil -} - -func RecursiveStructToMapHookFunc() DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { - if f.Kind() != reflect.Struct { - return f.Interface(), nil - } - - var i interface{} = struct{}{} - if t.Type() != reflect.TypeOf(&i).Elem() { - return f.Interface(), nil - } - - m := make(map[string]interface{}) - t.Set(reflect.ValueOf(m)) - - return f.Interface(), nil - } -} - -// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies -// strings to the UnmarshalText function, when the target type -// implements the encoding.TextUnmarshaler interface -func TextUnmarshallerHookFunc() DecodeHookFuncType { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - result := reflect.New(t).Interface() - unmarshaller, ok := result.(encoding.TextUnmarshaler) - if !ok { - return data, nil - } - if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { - return nil, err - } - return result, nil - } -} diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go deleted file mode 100644 index 47a99e5a..00000000 --- a/vendor/github.com/mitchellh/mapstructure/error.go +++ /dev/null @@ -1,50 +0,0 @@ -package mapstructure - -import ( - "errors" - "fmt" - "sort" - "strings" -) - -// Error implements the error interface and can represents multiple -// errors that occur in the course of a single decode. -type Error struct { - Errors []string -} - -func (e *Error) Error() string { - points := make([]string, len(e.Errors)) - for i, err := range e.Errors { - points[i] = fmt.Sprintf("* %s", err) - } - - sort.Strings(points) - return fmt.Sprintf( - "%d error(s) decoding:\n\n%s", - len(e.Errors), strings.Join(points, "\n")) -} - -// WrappedErrors implements the errwrap.Wrapper interface to make this -// return value more useful with the errwrap and go-multierror libraries. -func (e *Error) WrappedErrors() []error { - if e == nil { - return nil - } - - result := make([]error, len(e.Errors)) - for i, e := range e.Errors { - result[i] = errors.New(e) - } - - return result -} - -func appendErrors(errors []string, err error) []string { - switch e := err.(type) { - case *Error: - return append(errors, e.Errors...) - default: - return append(errors, e.Error()) - } -} diff --git a/vendor/github.com/sagikazarmark/locafero/.envrc b/vendor/github.com/sagikazarmark/locafero/.envrc index 3ce7171a..2e0f9f5f 100644 --- a/vendor/github.com/sagikazarmark/locafero/.envrc +++ b/vendor/github.com/sagikazarmark/locafero/.envrc @@ -1,4 +1,4 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" fi use flake . --impure diff --git a/vendor/github.com/sagikazarmark/locafero/finder.go b/vendor/github.com/sagikazarmark/locafero/finder.go index 754c8b26..ef8d5471 100644 --- a/vendor/github.com/sagikazarmark/locafero/finder.go +++ b/vendor/github.com/sagikazarmark/locafero/finder.go @@ -27,7 +27,7 @@ type Finder struct { // It provides the capability to search for entries with depth, // meaning it can target deeper locations within the directory structure. // - // It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns. + // It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns. // // Examples: // - config.yaml @@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { // pool.Go(func() ([]string, error) { // // If the name contains any glob character, perform a glob match - // if strings.ContainsAny(searchName, "*?[]\\^") { + // if strings.ContainsAny(searchName, globMatch) { // return globWalkSearch(fsys, searchPath, searchName, f.Type) // } // @@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) { // If the name contains any glob character, perform a glob match - if strings.ContainsAny(item.name, "*?[]\\^") { + if strings.ContainsAny(item.name, globMatch) { return globWalkSearch(fsys, item.path, item.name, f.Type) } diff --git a/vendor/github.com/sagikazarmark/locafero/flake.lock b/vendor/github.com/sagikazarmark/locafero/flake.lock index 46d28f80..4bea8154 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.lock +++ b/vendor/github.com/sagikazarmark/locafero/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1717245169, + "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "owner": "cachix", + "repo": "devenv", + "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", "type": "github" }, "original": { @@ -60,11 +138,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -82,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -95,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": [ + "devenv", + "flake-compat" + ], "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -153,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -187,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1694343207, - "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717112898, + "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "78058d810644f5ed276804ce7ea9e82d92bee293", + "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", "type": "github" }, "original": { @@ -217,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -232,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -249,7 +433,7 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "systems": { @@ -266,6 +450,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/vendor/github.com/sagikazarmark/locafero/flake.nix b/vendor/github.com/sagikazarmark/locafero/flake.nix index 209ecf28..cddf1d40 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.nix +++ b/vendor/github.com/sagikazarmark/locafero/flake.nix @@ -34,11 +34,11 @@ ci = devenv.shells.default; - ci_1_20 = { + ci_1_21 = { imports = [ devenv.shells.ci ]; languages = { - go.package = pkgs.go_1_20; + go.package = pkgs.go_1_21; }; }; }; diff --git a/vendor/github.com/sagikazarmark/locafero/glob.go b/vendor/github.com/sagikazarmark/locafero/glob.go new file mode 100644 index 00000000..00f833e9 --- /dev/null +++ b/vendor/github.com/sagikazarmark/locafero/glob.go @@ -0,0 +1,5 @@ +//go:build !windows + +package locafero + +const globMatch = "*?[]\\^" diff --git a/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/vendor/github.com/sagikazarmark/locafero/glob_windows.go new file mode 100644 index 00000000..7aec2b24 --- /dev/null +++ b/vendor/github.com/sagikazarmark/locafero/glob_windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package locafero + +// See [filepath.Match]: +// +// On Windows, escaping is disabled. Instead, '\\' is treated as path separator. +const globMatch = "*?[]^" diff --git a/vendor/github.com/sagikazarmark/slog-shim/.envrc b/vendor/github.com/sagikazarmark/slog-shim/.envrc deleted file mode 100644 index 3ce7171a..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" -fi -use flake . --impure diff --git a/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/vendor/github.com/sagikazarmark/slog-shim/.gitignore deleted file mode 100644 index dc6d8b58..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.devenv/ -/.direnv/ -/.task/ -/build/ diff --git a/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/vendor/github.com/sagikazarmark/slog-shim/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/sagikazarmark/slog-shim/README.md b/vendor/github.com/sagikazarmark/slog-shim/README.md deleted file mode 100644 index 1f5be85e..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# [slog](https://pkg.go.dev/log/slog) shim - -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square) -[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org) - -Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library. -Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately, -especially since updating to Go 1.21 is a decision that most libraries won't make overnight. - -Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog). -While it's generally advised against using experimental packages in production, -this one served as a sort of backport package for the last few years, -incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`). - -This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`. - -**How does it achieve backwards compatibility?** - -Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is. -(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.) - -This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`. -Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly. - -For older Go versions, the library might become unstable after removing the shim. -However, since those older versions are no longer supported, the promise of backward compatibility remains intact. - -## Installation - -```shell -go get github.com/sagikazarmark/slog-shim -``` - -## Usage - -Import this package into your library and use it in your public API: - -```go -package mylib - -import slog "github.com/sagikazarmark/slog-shim" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21): - -```go -package main - -import "log/slog" - -// OR - -import "golang.org/x/exp/slog" - -mylib.New(slog.Default()) -``` - -**Make sure consumers are aware that your API behaves differently on different Go versions.** - -Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code: - -```diff -package mylib - -- import slog "github.com/sagikazarmark/slog-shim" -+ import "log/slog" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -## License - -The project is licensed under a [BSD-style license](LICENSE). diff --git a/vendor/github.com/sagikazarmark/slog-shim/attr.go b/vendor/github.com/sagikazarmark/slog-shim/attr.go deleted file mode 100644 index 89608bf3..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/attr.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/vendor/github.com/sagikazarmark/slog-shim/attr_120.go deleted file mode 100644 index b6648133..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/attr_120.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/vendor/github.com/sagikazarmark/slog-shim/flake.lock deleted file mode 100644 index 7e8898e9..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/flake.lock +++ /dev/null @@ -1,273 +0,0 @@ -{ - "nodes": { - "devenv": { - "inputs": { - "flake-compat": "flake-compat", - "nix": "nix", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", - "owner": "cachix", - "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "lowdown-src": { - "flake": false, - "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", - "type": "github" - }, - "original": { - "owner": "kristapsdz", - "repo": "lowdown", - "type": "github" - } - }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", - "owner": "domenkozar", - "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "relaxed-flakes", - "repo": "nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1694345580, - "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "master", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/handler.go b/vendor/github.com/sagikazarmark/slog-shim/handler.go deleted file mode 100644 index f55556ae..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/handler.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/handler_120.go deleted file mode 100644 index 67005757..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/handler_120.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/vendor/github.com/sagikazarmark/slog-shim/json_handler.go deleted file mode 100644 index 7c22bd81..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/json_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go deleted file mode 100644 index 7b14f10b..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/level.go b/vendor/github.com/sagikazarmark/slog-shim/level.go deleted file mode 100644 index 07288cf8..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/level.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/vendor/github.com/sagikazarmark/slog-shim/level_120.go deleted file mode 100644 index d3feb942..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/level_120.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/vendor/github.com/sagikazarmark/slog-shim/logger.go b/vendor/github.com/sagikazarmark/slog-shim/logger.go deleted file mode 100644 index e80036be..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/logger.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "context" - "log" - "log/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/vendor/github.com/sagikazarmark/slog-shim/logger_120.go deleted file mode 100644 index 97ebdd5e..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/logger_120.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "context" - "log" - - "golang.org/x/exp/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/record.go b/vendor/github.com/sagikazarmark/slog-shim/record.go deleted file mode 100644 index 85ad1f78..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/record.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/vendor/github.com/sagikazarmark/slog-shim/record_120.go deleted file mode 100644 index c2eaf4e7..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/record_120.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/vendor/github.com/sagikazarmark/slog-shim/text_handler.go deleted file mode 100644 index 45f6cfcb..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/text_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go deleted file mode 100644 index a69d63cc..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/value.go b/vendor/github.com/sagikazarmark/slog-shim/value.go deleted file mode 100644 index 61173eb9..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/value.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/vendor/github.com/sagikazarmark/slog-shim/value_120.go deleted file mode 100644 index 0f9f871e..00000000 --- a/vendor/github.com/sagikazarmark/slog-shim/value_120.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/vendor/github.com/spf13/viper/.envrc b/vendor/github.com/spf13/viper/.envrc index 3ce7171a..2e0f9f5f 100644 --- a/vendor/github.com/spf13/viper/.envrc +++ b/vendor/github.com/spf13/viper/.envrc @@ -1,4 +1,4 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" fi use flake . --impure diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md index 3fc7d84f..c2b2237c 100644 --- a/vendor/github.com/spf13/viper/README.md +++ b/vendor/github.com/spf13/viper/README.md @@ -11,7 +11,7 @@ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper) **Go configuration with fangs!** @@ -802,7 +802,7 @@ if err != nil { } ``` -Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. +Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. ### Decoding custom formats @@ -836,13 +836,15 @@ func yamlStringSettings() string { ## Viper or Vipers? -Viper comes ready to use out of the box. There is no configuration or -initialization needed to begin using Viper. Since most applications will want -to use a single central repository for their configuration, the viper package -provides this. It is similar to a singleton. +Viper comes with a global instance (singleton) out of the box. -In all of the examples above, they demonstrate using viper in its singleton -style approach. +Although it makes setting up configuration easy, +using it is generally discouraged as it makes testing harder and can lead to unexpected behavior. + +The best practice is to initialize a Viper instance and pass that around when necessary. + +The global instance _MAY_ be deprecated in the future. +See [#1855](https://github.com/spf13/viper/issues/1855) for more details. ### Working with multiple vipers diff --git a/vendor/github.com/spf13/viper/experimental.go b/vendor/github.com/spf13/viper/experimental.go new file mode 100644 index 00000000..6e19e8a1 --- /dev/null +++ b/vendor/github.com/spf13/viper/experimental.go @@ -0,0 +1,8 @@ +package viper + +// ExperimentalBindStruct tells Viper to use the new bind struct feature. +func ExperimentalBindStruct() Option { + return optionFunc(func(v *Viper) { + v.experimentalBindStruct = true + }) +} diff --git a/vendor/github.com/spf13/viper/file.go b/vendor/github.com/spf13/viper/file.go index a54fe5a7..50a40581 100644 --- a/vendor/github.com/spf13/viper/file.go +++ b/vendor/github.com/spf13/viper/file.go @@ -1,5 +1,3 @@ -//go:build !finder - package viper import ( @@ -7,12 +5,62 @@ import ( "os" "path/filepath" + "github.com/sagikazarmark/locafero" "github.com/spf13/afero" ) +// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files. +func ExperimentalFinder() Option { + return optionFunc(func(v *Viper) { + v.experimentalFinder = true + }) +} + +// Search for a config file. +func (v *Viper) findConfigFile() (string, error) { + finder := v.finder + + if finder == nil && v.experimentalFinder { + var names []string + + if v.configType != "" { + names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...) + } else { + names = locafero.NameWithExtensions(v.configName, SupportedExts...) + } + + finder = locafero.Finder{ + Paths: v.configPaths, + Names: names, + Type: locafero.FileTypeFile, + } + } + + if finder != nil { + return v.findConfigFileWithFinder(finder) + } + + return v.findConfigFileOld() +} + +func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) { + results, err := finder.Find(v.fs) + if err != nil { + return "", err + } + + if len(results) == 0 { + return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} + } + + // We call clean on the final result to ensure that the path is in its canonical form. + // This is mostly for consistent path handling and to make sure tests pass. + return results[0], nil +} + // Search all configPaths for any config file. // Returns the first path that exists (and is a config file). -func (v *Viper) findConfigFile() (string, error) { +func (v *Viper) findConfigFileOld() (string, error) { v.logger.Info("searching for config in paths", "paths", v.configPaths) for _, cp := range v.configPaths { diff --git a/vendor/github.com/spf13/viper/file_finder.go b/vendor/github.com/spf13/viper/file_finder.go deleted file mode 100644 index d96a1bd2..00000000 --- a/vendor/github.com/spf13/viper/file_finder.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build finder - -package viper - -import ( - "fmt" - - "github.com/sagikazarmark/locafero" -) - -// Search all configPaths for any config file. -// Returns the first path that exists (and is a config file). -func (v *Viper) findConfigFile() (string, error) { - var names []string - - if v.configType != "" { - names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...) - } else { - names = locafero.NameWithExtensions(v.configName, SupportedExts...) - } - - finder := locafero.Finder{ - Paths: v.configPaths, - Names: names, - Type: locafero.FileTypeFile, - } - - results, err := finder.Find(v.fs) - if err != nil { - return "", err - } - - if len(results) == 0 { - return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} - } - - return results[0], nil -} diff --git a/vendor/github.com/spf13/viper/finder.go b/vendor/github.com/spf13/viper/finder.go new file mode 100644 index 00000000..ab4b5950 --- /dev/null +++ b/vendor/github.com/spf13/viper/finder.go @@ -0,0 +1,47 @@ +package viper + +import ( + "errors" + + "github.com/spf13/afero" +) + +// WithFinder sets a custom [Finder]. +func WithFinder(f Finder) Option { + return optionFunc(func(v *Viper) { + v.finder = f + }) +} + +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} + +// Finders combines multiple finders into one. +func Finders(finders ...Finder) Finder { + return &combinedFinder{finders: finders} +} + +// combinedFinder is a Finder that combines multiple finders. +type combinedFinder struct { + finders []Finder +} + +// Find implements the [Finder] interface. +func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) { + var results []string + var errs []error + + for _, finder := range c.finders { + r, err := finder.Find(fsys) + if err != nil { + errs = append(errs, err) + continue + } + + results = append(results, r...) + } + + return results, errors.Join(errs...) +} diff --git a/vendor/github.com/spf13/viper/flake.lock b/vendor/github.com/spf13/viper/flake.lock index 3840614f..4bea8154 100644 --- a/vendor/github.com/spf13/viper/flake.lock +++ b/vendor/github.com/spf13/viper/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1717245169, + "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "owner": "cachix", + "repo": "devenv", + "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1707817777, - "narHash": "sha256-vHyIs1OULQ3/91wD6xOiuayfI71JXALGA5KLnDKAcy0=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "5a30b9e5ac7c6167e61b1f4193d5130bb9f8defa", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1706830856, - "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", "type": "github" }, "original": { @@ -60,11 +138,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -82,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -95,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": [ + "devenv", + "flake-compat" + ], "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -153,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1706550542, - "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -187,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1707939175, - "narHash": "sha256-D1xan0lgxbmXDyzVqXTiSYHLmAMrMRdD+alKzEO/p3w=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717112898, + "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f7e8132daca31b1e3859ac0fb49741754375ac3d", + "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", "type": "github" }, "original": { @@ -217,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -232,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1704725188, - "narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "ea96f0c05924341c551a797aaba8126334c505d2", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -249,7 +433,7 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "systems": { @@ -266,6 +450,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/vendor/github.com/spf13/viper/internal/features/finder.go b/vendor/github.com/spf13/viper/internal/features/finder.go new file mode 100644 index 00000000..983ea3a9 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/features/finder.go @@ -0,0 +1,5 @@ +//go:build viper_finder + +package features + +const Finder = true diff --git a/vendor/github.com/spf13/viper/internal/features/finder_default.go b/vendor/github.com/spf13/viper/internal/features/finder_default.go new file mode 100644 index 00000000..89bcb06e --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/features/finder_default.go @@ -0,0 +1,5 @@ +//go:build !viper_finder + +package features + +const Finder = false diff --git a/vendor/github.com/spf13/viper/logger.go b/vendor/github.com/spf13/viper/logger.go index 8938053b..828042f2 100644 --- a/vendor/github.com/spf13/viper/logger.go +++ b/vendor/github.com/spf13/viper/logger.go @@ -2,46 +2,9 @@ package viper import ( "context" - - slog "github.com/sagikazarmark/slog-shim" + "log/slog" ) -// Logger is a unified interface for various logging use cases and practices, including: -// - leveled logging -// - structured logging -// -// Deprecated: use `log/slog` instead. -type Logger interface { - // Trace logs a Trace event. - // - // Even more fine-grained information than Debug events. - // Loggers not supporting this level should fall back to Debug. - Trace(msg string, keyvals ...any) - - // Debug logs a Debug event. - // - // A verbose series of information events. - // They are useful when debugging the system. - Debug(msg string, keyvals ...any) - - // Info logs an Info event. - // - // General information about what's happening inside the system. - Info(msg string, keyvals ...any) - - // Warn logs a Warn(ing) event. - // - // Non-critical events that should be looked at. - Warn(msg string, keyvals ...any) - - // Error logs an Error event. - // - // Critical events that require immediate attention. - // Loggers commonly provide Fatal and Panic levels above Error level, - // but exiting and panicking is out of scope for a logging library. - Error(msg string, keyvals ...any) -} - // WithLogger sets a custom logger. func WithLogger(l *slog.Logger) Option { return optionFunc(func(v *Viper) { diff --git a/vendor/github.com/spf13/viper/remote.go b/vendor/github.com/spf13/viper/remote.go new file mode 100644 index 00000000..2c07f81f --- /dev/null +++ b/vendor/github.com/spf13/viper/remote.go @@ -0,0 +1,255 @@ +package viper + +import ( + "bytes" + "fmt" + "io" + "reflect" +) + +// SupportedRemoteProviders are universally supported remote providers. +var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} + +func resetRemote() { + SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} +} + +type remoteConfigFactory interface { + Get(rp RemoteProvider) (io.Reader, error) + Watch(rp RemoteProvider) (io.Reader, error) + WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) +} + +type RemoteResponse struct { + Value []byte + Error error +} + +// RemoteConfig is optional, see the remote package. +var RemoteConfig remoteConfigFactory + +// UnsupportedRemoteProviderError denotes encountering an unsupported remote +// provider. Currently only etcd and Consul are supported. +type UnsupportedRemoteProviderError string + +// Error returns the formatted remote provider error. +func (str UnsupportedRemoteProviderError) Error() string { + return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) +} + +// RemoteConfigError denotes encountering an error while trying to +// pull the configuration from the remote provider. +type RemoteConfigError string + +// Error returns the formatted remote provider error. +func (rce RemoteConfigError) Error() string { + return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) +} + +type defaultRemoteProvider struct { + provider string + endpoint string + path string + secretKeyring string +} + +func (rp defaultRemoteProvider) Provider() string { + return rp.provider +} + +func (rp defaultRemoteProvider) Endpoint() string { + return rp.endpoint +} + +func (rp defaultRemoteProvider) Path() string { + return rp.path +} + +func (rp defaultRemoteProvider) SecretKeyring() string { + return rp.secretKeyring +} + +// RemoteProvider stores the configuration necessary +// to connect to a remote key/value store. +// Optional secretKeyring to unencrypt encrypted values +// can be provided. +type RemoteProvider interface { + Provider() string + Endpoint() string + Path() string + SecretKeyring() string +} + +// AddRemoteProvider adds a remote configuration source. +// Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +func AddRemoteProvider(provider, endpoint, path string) error { + return v.AddRemoteProvider(provider, endpoint, path) +} + +func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +// AddSecureRemoteProvider adds a remote configuration source. +// Secure Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt. +func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) +} + +func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + secretKeyring: secretkeyring, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { + for _, y := range v.remoteProviders { + if reflect.DeepEqual(y, p) { + return true + } + } + return false +} + +// ReadRemoteConfig attempts to get configuration from a remote source +// and read it in the remote configuration registry. +func ReadRemoteConfig() error { return v.ReadRemoteConfig() } + +func (v *Viper) ReadRemoteConfig() error { + return v.getKeyValueConfig() +} + +func WatchRemoteConfig() error { return v.WatchRemoteConfig() } +func (v *Viper) WatchRemoteConfig() error { + return v.watchKeyValueConfig() +} + +func (v *Viper) WatchRemoteConfigOnChannel() error { + return v.watchKeyValueConfigOnChannel() +} + +// Retrieve the first found remote configuration. +func (v *Viper) getKeyValueConfig() error { + if RemoteConfig == nil { + return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") + } + + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.getRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) + + continue + } + + v.kvstore = val + + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Get(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfigOnChannel() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + respc, _ := RemoteConfig.WatchChannel(rp) + // Todo: Add quit channel + go func(rc <-chan *RemoteResponse) { + for { + b := <-rc + reader := bytes.NewReader(b.Value) + v.unmarshalReader(reader, v.kvstore) + } + }(respc) + return nil + } + return RemoteConfigError("No Files Found") +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfig() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.watchRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) + + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Watch(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go index 117c6ac3..9a6a5a8a 100644 --- a/vendor/github.com/spf13/viper/util.go +++ b/vendor/github.com/spf13/viper/util.go @@ -12,13 +12,13 @@ package viper import ( "fmt" + "log/slog" "os" "path/filepath" "runtime" "strings" "unicode" - slog "github.com/sagikazarmark/slog-shim" "github.com/spf13/cast" ) diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index da68d994..30ae4aa9 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -25,6 +25,7 @@ import ( "errors" "fmt" "io" + "log/slog" "os" "path/filepath" "reflect" @@ -34,8 +35,7 @@ import ( "time" "github.com/fsnotify/fsnotify" - "github.com/mitchellh/mapstructure" - slog "github.com/sagikazarmark/slog-shim" + "github.com/go-viper/mapstructure/v2" "github.com/spf13/afero" "github.com/spf13/cast" "github.com/spf13/pflag" @@ -63,24 +63,10 @@ func (e ConfigMarshalError) Error() string { var v *Viper -type RemoteResponse struct { - Value []byte - Error error -} - func init() { v = New() } -type remoteConfigFactory interface { - Get(rp RemoteProvider) (io.Reader, error) - Watch(rp RemoteProvider) (io.Reader, error) - WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) -} - -// RemoteConfig is optional, see the remote package. -var RemoteConfig remoteConfigFactory - // UnsupportedConfigError denotes encountering an unsupported // configuration filetype. type UnsupportedConfigError string @@ -90,24 +76,6 @@ func (str UnsupportedConfigError) Error() string { return fmt.Sprintf("Unsupported Config Type %q", string(str)) } -// UnsupportedRemoteProviderError denotes encountering an unsupported remote -// provider. Currently only etcd and Consul are supported. -type UnsupportedRemoteProviderError string - -// Error returns the formatted remote provider error. -func (str UnsupportedRemoteProviderError) Error() string { - return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) -} - -// RemoteConfigError denotes encountering an error while trying to -// pull the configuration from the remote provider. -type RemoteConfigError string - -// Error returns the formatted remote provider error. -func (rce RemoteConfigError) Error() string { - return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) -} - // ConfigFileNotFoundError denotes failing to find configuration file. type ConfigFileNotFoundError struct { name, locations string @@ -190,6 +158,8 @@ type Viper struct { // The filesystem to read config from. fs afero.Fs + finder Finder + // A set of remote providers to search for the configuration remoteProviders []*defaultRemoteProvider @@ -224,6 +194,9 @@ type Viper struct { // TODO: should probably be protected with a mutex encoderRegistry *encoding.EncoderRegistry decoderRegistry *encoding.DecoderRegistry + + experimentalFinder bool + experimentalBindStruct bool } // New returns an initialized Viper instance. @@ -246,6 +219,9 @@ func New() *Viper { v.resetEncoding() + v.experimentalFinder = features.Finder + v.experimentalBindStruct = features.BindStruct + return v } @@ -297,13 +273,31 @@ func NewWithOptions(opts ...Option) *Viper { return v } +// SetOptions sets the options on the global Viper instance. +// +// Be careful when using this function: subsequent calls may override options you set. +// It's always better to use a local Viper instance. +func SetOptions(opts ...Option) { + keyDelim := v.keyDelim + + for _, opt := range opts { + opt.apply(v) + } + + // reset encoding if key delimiter changed + if keyDelim != v.keyDelim { + v.resetEncoding() + } +} + // Reset is intended for testing, will reset all to default settings. // In the public interface for the viper package so applications // can use it in their testing as well. func Reset() { v = New() SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} - SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} + + resetRemote() } // TODO: make this lazy initialization instead. @@ -384,46 +378,9 @@ func (v *Viper) resetEncoding() { v.decoderRegistry = decoderRegistry } -type defaultRemoteProvider struct { - provider string - endpoint string - path string - secretKeyring string -} - -func (rp defaultRemoteProvider) Provider() string { - return rp.provider -} - -func (rp defaultRemoteProvider) Endpoint() string { - return rp.endpoint -} - -func (rp defaultRemoteProvider) Path() string { - return rp.path -} - -func (rp defaultRemoteProvider) SecretKeyring() string { - return rp.secretKeyring -} - -// RemoteProvider stores the configuration necessary -// to connect to a remote key/value store. -// Optional secretKeyring to unencrypt encrypted values -// can be provided. -type RemoteProvider interface { - Provider() string - Endpoint() string - Path() string - SecretKeyring() string -} - // SupportedExts are universally supported extensions. var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} -// SupportedRemoteProviders are universally supported remote providers. -var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} - // OnConfigChange sets the event handler that is called when a config file changes. func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } @@ -574,6 +531,10 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile } func AddConfigPath(in string) { v.AddConfigPath(in) } func (v *Viper) AddConfigPath(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath")) + } + if in != "" { absin := absPathify(v.logger, in) @@ -584,80 +545,6 @@ func (v *Viper) AddConfigPath(in string) { } } -// AddRemoteProvider adds a remote configuration source. -// Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp". -func AddRemoteProvider(provider, endpoint, path string) error { - return v.AddRemoteProvider(provider, endpoint, path) -} - -func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -// AddSecureRemoteProvider adds a remote configuration source. -// Secure Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port consul requires ip:port -// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp". -// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt. -func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) -} - -func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - secretKeyring: secretkeyring, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { - for _, y := range v.remoteProviders { - if reflect.DeepEqual(y, p) { - return true - } - } - return false -} - // searchMap recursively searches for a value for path in source map. // Returns nil if not found. // Note: This assumes that the path entries and map keys are lower cased. @@ -1117,7 +1004,7 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error { func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { keys := v.AllKeys() - if features.BindStruct { + if v.experimentalBindStruct { // TODO: make this optional? structKeys, err := v.decodeStructKeys(rawVal, opts...) if err != nil { @@ -1158,7 +1045,8 @@ func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure WeaklyTypedInput: true, DecodeHook: mapstructure.ComposeDecodeHookFunc( mapstructure.StringToTimeDurationHookFunc(), - mapstructure.StringToSliceHookFunc(","), + // mapstructure.StringToSliceHookFunc(","), + stringToWeakSliceHookFunc(","), ), } for _, opt := range opts { @@ -1167,6 +1055,28 @@ func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure return c } +// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice. +// This function removes that check. +// TODO: implement a function that checks if the value can be converted to the return type and use it instead. +func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + // decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality. func decode(input any, config *mapstructure.DecoderConfig) error { decoder, err := mapstructure.NewDecoder(config) @@ -1188,7 +1098,7 @@ func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { keys := v.AllKeys() - if features.BindStruct { + if v.experimentalBindStruct { // TODO: make this optional? structKeys, err := v.decodeStructKeys(rawVal, opts...) if err != nil { @@ -1686,6 +1596,10 @@ func (v *Viper) MergeInConfig() error { func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } func (v *Viper) ReadConfig(in io.Reader) error { + if v.configType == "" { + return errors.New("cannot decode configuration: config type is not set") + } + v.config = make(map[string]any) return v.unmarshalReader(in, v.config) } @@ -1694,6 +1608,10 @@ func (v *Viper) ReadConfig(in io.Reader) error { func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } func (v *Viper) MergeConfig(in io.Reader) error { + if v.configType == "" { + return errors.New("cannot decode configuration: config type is not set") + } + cfg := make(map[string]any) if err := v.unmarshalReader(in, cfg); err != nil { return err @@ -1953,106 +1871,6 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) { } } -// ReadRemoteConfig attempts to get configuration from a remote source -// and read it in the remote configuration registry. -func ReadRemoteConfig() error { return v.ReadRemoteConfig() } - -func (v *Viper) ReadRemoteConfig() error { - return v.getKeyValueConfig() -} - -func WatchRemoteConfig() error { return v.WatchRemoteConfig() } -func (v *Viper) WatchRemoteConfig() error { - return v.watchKeyValueConfig() -} - -func (v *Viper) WatchRemoteConfigOnChannel() error { - return v.watchKeyValueConfigOnChannel() -} - -// Retrieve the first found remote configuration. -func (v *Viper) getKeyValueConfig() error { - if RemoteConfig == nil { - return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") - } - - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.getRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) - - continue - } - - v.kvstore = val - - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Get(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfigOnChannel() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - respc, _ := RemoteConfig.WatchChannel(rp) - // Todo: Add quit channel - go func(rc <-chan *RemoteResponse) { - for { - b := <-rc - reader := bytes.NewReader(b.Value) - v.unmarshalReader(reader, v.kvstore) - } - }(respc) - return nil - } - return RemoteConfigError("No Files Found") -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfig() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.watchRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) - - continue - } - v.kvstore = val - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Watch(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - // AllKeys returns all keys holding a value, regardless of where they are set. // Nested keys are returned with a v.keyDelim separator. func AllKeys() []string { return v.AllKeys() } @@ -2174,6 +1992,10 @@ func (v *Viper) SetFs(fs afero.Fs) { func SetConfigName(in string) { v.SetConfigName(in) } func (v *Viper) SetConfigName(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName")) + } + if in != "" { v.configName = in v.configFile = "" diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE deleted file mode 100644 index 2a7cf70d..00000000 --- a/vendor/golang.org/x/exp/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/PATENTS b/vendor/golang.org/x/exp/PATENTS deleted file mode 100644 index 73309904..00000000 --- a/vendor/golang.org/x/exp/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/exp/constraints/constraints.go b/vendor/golang.org/x/exp/constraints/constraints.go deleted file mode 100644 index 2c033dff..00000000 --- a/vendor/golang.org/x/exp/constraints/constraints.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package constraints defines a set of useful constraints to be used -// with type parameters. -package constraints - -// Signed is a constraint that permits any signed integer type. -// If future releases of Go add new predeclared signed integer types, -// this constraint will be modified to include them. -type Signed interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 -} - -// Unsigned is a constraint that permits any unsigned integer type. -// If future releases of Go add new predeclared unsigned integer types, -// this constraint will be modified to include them. -type Unsigned interface { - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// Integer is a constraint that permits any integer type. -// If future releases of Go add new predeclared integer types, -// this constraint will be modified to include them. -type Integer interface { - Signed | Unsigned -} - -// Float is a constraint that permits any floating-point type. -// If future releases of Go add new predeclared floating-point types, -// this constraint will be modified to include them. -type Float interface { - ~float32 | ~float64 -} - -// Complex is a constraint that permits any complex numeric type. -// If future releases of Go add new predeclared complex numeric types, -// this constraint will be modified to include them. -type Complex interface { - ~complex64 | ~complex128 -} - -// Ordered is a constraint that permits any ordered type: any type -// that supports the operators < <= >= >. -// If future releases of Go add new ordered types, -// this constraint will be modified to include them. -type Ordered interface { - Integer | Float | ~string -} diff --git a/vendor/golang.org/x/exp/slices/cmp.go b/vendor/golang.org/x/exp/slices/cmp.go deleted file mode 100644 index fbf1934a..00000000 --- a/vendor/golang.org/x/exp/slices/cmp.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// min is a version of the predeclared function from the Go 1.21 release. -func min[T constraints.Ordered](a, b T) T { - if a < b || isNaN(a) { - return a - } - return b -} - -// max is a version of the predeclared function from the Go 1.21 release. -func max[T constraints.Ordered](a, b T) T { - if a > b || isNaN(a) { - return a - } - return b -} - -// cmpLess is a copy of cmp.Less from the Go 1.21 release. -func cmpLess[T constraints.Ordered](x, y T) bool { - return (isNaN(x) && !isNaN(y)) || x < y -} - -// cmpCompare is a copy of cmp.Compare from the Go 1.21 release. -func cmpCompare[T constraints.Ordered](x, y T) int { - xNaN := isNaN(x) - yNaN := isNaN(y) - if xNaN && yNaN { - return 0 - } - if xNaN || x < y { - return -1 - } - if yNaN || x > y { - return +1 - } - return 0 -} diff --git a/vendor/golang.org/x/exp/slices/slices.go b/vendor/golang.org/x/exp/slices/slices.go deleted file mode 100644 index 46ceac34..00000000 --- a/vendor/golang.org/x/exp/slices/slices.go +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package slices defines various functions useful with slices of any type. -package slices - -import ( - "unsafe" - - "golang.org/x/exp/constraints" -) - -// Equal reports whether two slices are equal: the same length and all -// elements equal. If the lengths are different, Equal returns false. -// Otherwise, the elements are compared in increasing index order, and the -// comparison stops at the first unequal pair. -// Floating point NaNs are not considered equal. -func Equal[S ~[]E, E comparable](s1, s2 S) bool { - if len(s1) != len(s2) { - return false - } - for i := range s1 { - if s1[i] != s2[i] { - return false - } - } - return true -} - -// EqualFunc reports whether two slices are equal using an equality -// function on each pair of elements. If the lengths are different, -// EqualFunc returns false. Otherwise, the elements are compared in -// increasing index order, and the comparison stops at the first index -// for which eq returns false. -func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool { - if len(s1) != len(s2) { - return false - } - for i, v1 := range s1 { - v2 := s2[i] - if !eq(v1, v2) { - return false - } - } - return true -} - -// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair -// of elements. The elements are compared sequentially, starting at index 0, -// until one element is not equal to the other. -// The result of comparing the first non-matching elements is returned. -// If both slices are equal until one of them ends, the shorter slice is -// considered less than the longer one. -// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. -func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmpCompare(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// CompareFunc is like [Compare] but uses a custom comparison function on each -// pair of elements. -// The result is the first non-zero result of cmp; if cmp always -// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), -// and +1 if len(s1) > len(s2). -func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmp(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// Index returns the index of the first occurrence of v in s, -// or -1 if not present. -func Index[S ~[]E, E comparable](s S, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 -} - -// IndexFunc returns the first index i satisfying f(s[i]), -// or -1 if none do. -func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { - for i := range s { - if f(s[i]) { - return i - } - } - return -1 -} - -// Contains reports whether v is present in s. -func Contains[S ~[]E, E comparable](s S, v E) bool { - return Index(s, v) >= 0 -} - -// ContainsFunc reports whether at least one -// element e of s satisfies f(e). -func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool { - return IndexFunc(s, f) >= 0 -} - -// Insert inserts the values v... into s at index i, -// returning the modified slice. -// The elements at s[i:] are shifted up to make room. -// In the returned slice r, r[i] == v[0], -// and r[i+len(v)] == value originally at r[i]. -// Insert panics if i is out of range. -// This function is O(len(s) + len(v)). -func Insert[S ~[]E, E any](s S, i int, v ...E) S { - m := len(v) - if m == 0 { - return s - } - n := len(s) - if i == n { - return append(s, v...) - } - if n+m > cap(s) { - // Use append rather than make so that we bump the size of - // the slice up to the next storage class. - // This is what Grow does but we don't call Grow because - // that might copy the values twice. - s2 := append(s[:i], make(S, n+m-i)...) - copy(s2[i:], v) - copy(s2[i+m:], s[i:]) - return s2 - } - s = s[:n+m] - - // before: - // s: aaaaaaaabbbbccccccccdddd - // ^ ^ ^ ^ - // i i+m n n+m - // after: - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // - // a are the values that don't move in s. - // v are the values copied in from v. - // b and c are the values from s that are shifted up in index. - // d are the values that get overwritten, never to be seen again. - - if !overlaps(v, s[i+m:]) { - // Easy case - v does not overlap either the c or d regions. - // (It might be in some of a or b, or elsewhere entirely.) - // The data we copy up doesn't write to v at all, so just do it. - - copy(s[i+m:], s[i:]) - - // Now we have - // s: aaaaaaaabbbbbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // Note the b values are duplicated. - - copy(s[i:], v) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s - } - - // The hard case - v overlaps c or d. We can't just shift up - // the data because we'd move or clobber the values we're trying - // to insert. - // So instead, write v on top of d, then rotate. - copy(s[n:], v) - - // Now we have - // s: aaaaaaaabbbbccccccccvvvv - // ^ ^ ^ ^ - // i i+m n n+m - - rotateRight(s[i:], m) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s -} - -// clearSlice sets all elements up to the length of s to the zero value of E. -// We may use the builtin clear func instead, and remove clearSlice, when upgrading -// to Go 1.21+. -func clearSlice[S ~[]E, E any](s S) { - var zero E - for i := range s { - s[i] = zero - } -} - -// Delete removes the elements s[i:j] from s, returning the modified slice. -// Delete panics if j > len(s) or s[i:j] is not a valid slice of s. -// Delete is O(len(s)-i), so if many items must be deleted, it is better to -// make a single call deleting them all together than to delete one at a time. -// Delete zeroes the elements s[len(s)-(j-i):len(s)]. -func Delete[S ~[]E, E any](s S, i, j int) S { - _ = s[i:j:len(s)] // bounds check - - if i == j { - return s - } - - oldlen := len(s) - s = append(s[:i], s[j:]...) - clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC - return s -} - -// DeleteFunc removes any elements from s for which del returns true, -// returning the modified slice. -// DeleteFunc zeroes the elements between the new length and the original length. -func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { - i := IndexFunc(s, del) - if i == -1 { - return s - } - // Don't start copying elements until we find one to delete. - for j := i + 1; j < len(s); j++ { - if v := s[j]; !del(v) { - s[i] = v - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Replace replaces the elements s[i:j] by the given v, and returns the -// modified slice. Replace panics if s[i:j] is not a valid slice of s. -// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length. -func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { - _ = s[i:j] // verify that i:j is a valid subslice - - if i == j { - return Insert(s, i, v...) - } - if j == len(s) { - return append(s[:i], v...) - } - - tot := len(s[:i]) + len(v) + len(s[j:]) - if tot > cap(s) { - // Too big to fit, allocate and copy over. - s2 := append(s[:i], make(S, tot-i)...) // See Insert - copy(s2[i:], v) - copy(s2[i+len(v):], s[j:]) - return s2 - } - - r := s[:tot] - - if i+len(v) <= j { - // Easy, as v fits in the deleted portion. - copy(r[i:], v) - if i+len(v) != j { - copy(r[i+len(v):], s[j:]) - } - clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC - return r - } - - // We are expanding (v is bigger than j-i). - // The situation is something like this: - // (example has i=4,j=8,len(s)=16,len(v)=6) - // s: aaaaxxxxbbbbbbbbyy - // ^ ^ ^ ^ - // i j len(s) tot - // a: prefix of s - // x: deleted range - // b: more of s - // y: area to expand into - - if !overlaps(r[i+len(v):], v) { - // Easy, as v is not clobbered by the first copy. - copy(r[i+len(v):], s[j:]) - copy(r[i:], v) - return r - } - - // This is a situation where we don't have a single place to which - // we can copy v. Parts of it need to go to two different places. - // We want to copy the prefix of v into y and the suffix into x, then - // rotate |y| spots to the right. - // - // v[2:] v[:2] - // | | - // s: aaaavvvvbbbbbbbbvv - // ^ ^ ^ ^ - // i j len(s) tot - // - // If either of those two destinations don't alias v, then we're good. - y := len(v) - (j - i) // length of y portion - - if !overlaps(r[i:j], v) { - copy(r[i:j], v[y:]) - copy(r[len(s):], v[:y]) - rotateRight(r[i:], y) - return r - } - if !overlaps(r[len(s):], v) { - copy(r[len(s):], v[:y]) - copy(r[i:j], v[y:]) - rotateRight(r[i:], y) - return r - } - - // Now we know that v overlaps both x and y. - // That means that the entirety of b is *inside* v. - // So we don't need to preserve b at all; instead we - // can copy v first, then copy the b part of v out of - // v to the right destination. - k := startIdx(v, s[j:]) - copy(r[i:], v) - copy(r[i+len(v):], r[i+k:]) - return r -} - -// Clone returns a copy of the slice. -// The elements are copied using assignment, so this is a shallow clone. -func Clone[S ~[]E, E any](s S) S { - // Preserve nil in case it matters. - if s == nil { - return nil - } - return append(S([]E{}), s...) -} - -// Compact replaces consecutive runs of equal elements with a single copy. -// This is like the uniq command found on Unix. -// Compact modifies the contents of the slice s and returns the modified slice, -// which may have a smaller length. -// Compact zeroes the elements between the new length and the original length. -func Compact[S ~[]E, E comparable](s S) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if s[k] != s[k-1] { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// CompactFunc is like [Compact] but uses an equality function to compare elements. -// For runs of elements that compare equal, CompactFunc keeps the first one. -// CompactFunc zeroes the elements between the new length and the original length. -func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if !eq(s[k], s[k-1]) { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Grow increases the slice's capacity, if necessary, to guarantee space for -// another n elements. After Grow(n), at least n elements can be appended -// to the slice without another allocation. If n is negative or too large to -// allocate the memory, Grow panics. -func Grow[S ~[]E, E any](s S, n int) S { - if n < 0 { - panic("cannot be negative") - } - if n -= cap(s) - len(s); n > 0 { - // TODO(https://go.dev/issue/53888): Make using []E instead of S - // to workaround a compiler bug where the runtime.growslice optimization - // does not take effect. Revert when the compiler is fixed. - s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)] - } - return s -} - -// Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. -func Clip[S ~[]E, E any](s S) S { - return s[:len(s):len(s)] -} - -// Rotation algorithm explanation: -// -// rotate left by 2 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join first parts -// 89234567 01 -// recursively rotate first left part by 2 -// 23456789 01 -// join at the end -// 2345678901 -// -// rotate left by 8 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join last parts -// 89 23456701 -// recursively rotate second part left by 6 -// 89 01234567 -// join at the end -// 8901234567 - -// TODO: There are other rotate algorithms. -// This algorithm has the desirable property that it moves each element exactly twice. -// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes. -// The follow-cycles algorithm can be 1-write but it is not very cache friendly. - -// rotateLeft rotates b left by n spaces. -// s_final[i] = s_orig[i+r], wrapping around. -func rotateLeft[E any](s []E, r int) { - for r != 0 && r != len(s) { - if r*2 <= len(s) { - swap(s[:r], s[len(s)-r:]) - s = s[:len(s)-r] - } else { - swap(s[:len(s)-r], s[r:]) - s, r = s[len(s)-r:], r*2-len(s) - } - } -} -func rotateRight[E any](s []E, r int) { - rotateLeft(s, len(s)-r) -} - -// swap swaps the contents of x and y. x and y must be equal length and disjoint. -func swap[E any](x, y []E) { - for i := 0; i < len(x); i++ { - x[i], y[i] = y[i], x[i] - } -} - -// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap. -func overlaps[E any](a, b []E) bool { - if len(a) == 0 || len(b) == 0 { - return false - } - elemSize := unsafe.Sizeof(a[0]) - if elemSize == 0 { - return false - } - // TODO: use a runtime/unsafe facility once one becomes available. See issue 12445. - // Also see crypto/internal/alias/alias.go:AnyOverlap - return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) && - uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1) -} - -// startIdx returns the index in haystack where the needle starts. -// prerequisite: the needle must be aliased entirely inside the haystack. -func startIdx[E any](haystack, needle []E) int { - p := &needle[0] - for i := range haystack { - if p == &haystack[i] { - return i - } - } - // TODO: what if the overlap is by a non-integral number of Es? - panic("needle not found") -} - -// Reverse reverses the elements of the slice in place. -func Reverse[S ~[]E, E any](s S) { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } -} diff --git a/vendor/golang.org/x/exp/slices/sort.go b/vendor/golang.org/x/exp/slices/sort.go deleted file mode 100644 index f58bbc7b..00000000 --- a/vendor/golang.org/x/exp/slices/sort.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp - -package slices - -import ( - "math/bits" - - "golang.org/x/exp/constraints" -) - -// Sort sorts a slice of any ordered type in ascending order. -// When sorting floating-point numbers, NaNs are ordered before other values. -func Sort[S ~[]E, E constraints.Ordered](x S) { - n := len(x) - pdqsortOrdered(x, 0, n, bits.Len(uint(n))) -} - -// SortFunc sorts the slice x in ascending order as determined by the cmp -// function. This sort is not guaranteed to be stable. -// cmp(a, b) should return a negative number when a < b, a positive number when -// a > b and zero when a == b or when a is not comparable to b in the sense -// of the formal definition of Strict Weak Ordering. -// -// SortFunc requires that cmp is a strict weak ordering. -// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. -// To indicate 'uncomparable', return 0 from the function. -func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - n := len(x) - pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp) -} - -// SortStableFunc sorts the slice x while keeping the original order of equal -// elements, using cmp to compare elements in the same way as [SortFunc]. -func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - stableCmpFunc(x, len(x), cmp) -} - -// IsSorted reports whether x is sorted in ascending order. -func IsSorted[S ~[]E, E constraints.Ordered](x S) bool { - for i := len(x) - 1; i > 0; i-- { - if cmpLess(x[i], x[i-1]) { - return false - } - } - return true -} - -// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the -// comparison function as defined by [SortFunc]. -func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool { - for i := len(x) - 1; i > 0; i-- { - if cmp(x[i], x[i-1]) < 0 { - return false - } - } - return true -} - -// Min returns the minimal value in x. It panics if x is empty. -// For floating-point numbers, Min propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Min[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Min: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = min(m, x[i]) - } - return m -} - -// MinFunc returns the minimal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one minimal element -// according to the cmp function, MinFunc returns the first one. -func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MinFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) < 0 { - m = x[i] - } - } - return m -} - -// Max returns the maximal value in x. It panics if x is empty. -// For floating-point E, Max propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Max[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Max: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = max(m, x[i]) - } - return m -} - -// MaxFunc returns the maximal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one maximal element -// according to the cmp function, MaxFunc returns the first one. -func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MaxFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) > 0 { - m = x[i] - } - } - return m -} - -// BinarySearch searches for target in a sorted slice and returns the position -// where target is found, or the position where target would appear in the -// sort order; it also returns a bool saying whether the target is really found -// in the slice. The slice must be sorted in increasing order. -func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) { - // Inlining is faster than calling BinarySearchFunc with a lambda. - n := len(x) - // Define x[-1] < target and x[n] >= target. - // Invariant: x[i-1] < target, x[j] >= target. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmpLess(x[h], target) { - i = h + 1 // preserves x[i-1] < target - } else { - j = h // preserves x[j] >= target - } - } - // i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i. - return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target))) -} - -// BinarySearchFunc works like [BinarySearch], but uses a custom comparison -// function. The slice must be sorted in increasing order, where "increasing" -// is defined by cmp. cmp should return 0 if the slice element matches -// the target, a negative number if the slice element precedes the target, -// or a positive number if the slice element follows the target. -// cmp must implement the same ordering as the slice, such that if -// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice. -func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) { - n := len(x) - // Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 . - // Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmp(x[h], target) < 0 { - i = h + 1 // preserves cmp(x[i - 1], target) < 0 - } else { - j = h // preserves cmp(x[j], target) >= 0 - } - } - // i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i. - return i, i < n && cmp(x[i], target) == 0 -} - -type sortedHint int // hint for pdqsort when choosing the pivot - -const ( - unknownHint sortedHint = iota - increasingHint - decreasingHint -) - -// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf -type xorshift uint64 - -func (r *xorshift) Next() uint64 { - *r ^= *r << 13 - *r ^= *r >> 17 - *r ^= *r << 5 - return uint64(*r) -} - -func nextPowerOfTwo(length int) uint { - return 1 << bits.Len(uint(length)) -} - -// isNaN reports whether x is a NaN without requiring the math package. -// This will always return false if T is not floating-point. -func isNaN[T constraints.Ordered](x T) bool { - return x != x -} diff --git a/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/vendor/golang.org/x/exp/slices/zsortanyfunc.go deleted file mode 100644 index 06f2c7a2..00000000 --- a/vendor/golang.org/x/exp/slices/zsortanyfunc.go +++ /dev/null @@ -1,479 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -// insertionSortCmpFunc sorts data[a:b] using insertion sort. -func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownCmpFunc implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) { - child++ - } - if !(cmp(data[first+root], data[first+child]) < 0) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownCmpFunc(data, i, hi, first, cmp) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownCmpFunc(data, lo, i, first, cmp) - } -} - -// pdqsortCmpFunc sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortCmpFunc(data, a, b, cmp) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortCmpFunc(data, a, b, cmp) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsCmpFunc(data, a, b, cmp) - limit-- - } - - pivot, hint := choosePivotCmpFunc(data, a, b, cmp) - if hint == decreasingHint { - reverseRangeCmpFunc(data, a, b, cmp) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortCmpFunc(data, a, b, cmp) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) { - mid := partitionEqualCmpFunc(data, a, b, pivot, cmp) - a = mid - continue - } - - mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortCmpFunc(data, a, mid, limit, cmp) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortCmpFunc(data, mid+1, b, limit, cmp) - b = mid - } - } -} - -// partitionCmpFunc does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/vendor/golang.org/x/exp/slices/zsortordered.go b/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c39..00000000 --- a/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/vendor/golang.org/x/exp/slog/attr.go b/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1..00000000 --- a/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/vendor/golang.org/x/exp/slog/doc.go b/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf867..00000000 --- a/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/vendor/golang.org/x/exp/slog/handler.go b/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb8..00000000 --- a/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166..00000000 --- a/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426..00000000 --- a/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/vendor/golang.org/x/exp/slog/json_handler.go b/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada86..00000000 --- a/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/vendor/golang.org/x/exp/slog/level.go b/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0a..00000000 --- a/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/vendor/golang.org/x/exp/slog/logger.go b/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec993..00000000 --- a/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/golang.org/x/exp/slog/noplog.bench b/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff..00000000 --- a/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/vendor/golang.org/x/exp/slog/record.go b/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f..00000000 --- a/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/vendor/golang.org/x/exp/slog/text_handler.go b/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b71..00000000 --- a/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/vendor/golang.org/x/exp/slog/value.go b/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46f..00000000 --- a/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/vendor/golang.org/x/exp/slog/value_119.go b/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d732..00000000 --- a/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/vendor/golang.org/x/exp/slog/value_120.go b/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c093..00000000 --- a/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 8b858249..a23b6cbe 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -23,6 +23,10 @@ github.com/fsnotify/fsnotify ## explicit; go 1.21 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash +# github.com/go-viper/mapstructure/v2 v2.0.0 +## explicit; go 1.18 +github.com/go-viper/mapstructure/v2 +github.com/go-viper/mapstructure/v2/internal/errors # github.com/google/go-github/v68 v68.0.0 ## explicit; go 1.21 github.com/google/go-github/v68/github @@ -103,9 +107,6 @@ github.com/mattn/go-runewidth # github.com/mitchellh/copystructure v1.2.0 ## explicit; go 1.15 github.com/mitchellh/copystructure -# github.com/mitchellh/mapstructure v1.5.0 -## explicit; go 1.14 -github.com/mitchellh/mapstructure # github.com/mitchellh/reflectwalk v1.0.2 ## explicit github.com/mitchellh/reflectwalk @@ -139,12 +140,9 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/sagikazarmark/locafero v0.4.0 +# github.com/sagikazarmark/locafero v0.6.0 ## explicit; go 1.20 github.com/sagikazarmark/locafero -# github.com/sagikazarmark/slog-shim v0.1.0 -## explicit; go 1.20 -github.com/sagikazarmark/slog-shim # github.com/shopspring/decimal v1.4.0 ## explicit; go 1.10 github.com/shopspring/decimal @@ -168,8 +166,8 @@ github.com/spf13/cast # github.com/spf13/pflag v1.0.5 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/spf13/viper v1.19.0 -## explicit; go 1.20 +# github.com/spf13/viper v1.20.0-alpha.1 +## explicit; go 1.21 github.com/spf13/viper github.com/spf13/viper/internal/encoding github.com/spf13/viper/internal/encoding/dotenv @@ -203,13 +201,6 @@ golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 -## explicit; go 1.20 -golang.org/x/exp/constraints -golang.org/x/exp/slices -golang.org/x/exp/slog -golang.org/x/exp/slog/internal -golang.org/x/exp/slog/internal/buffer # golang.org/x/oauth2 v0.30.0 ## explicit; go 1.23.0 golang.org/x/oauth2 From f03abba46b664a5c65f5479b7a361a16f019b22d Mon Sep 17 00:00:00 2001 From: Chris Blackburn Date: Wed, 14 May 2025 15:17:01 -0400 Subject: [PATCH 17/35] bump viper to latest (#171) This is the second half of a two-step process to upgrade viper (see #168 for part 1). We needed to split this because the diff was too large which caused the e2e-tests GHA job to fail. --- go.mod | 19 +- go.sum | 46 +- .../github.com/fsnotify/fsnotify/.cirrus.yml | 7 +- .../fsnotify/fsnotify/.gitattributes | 1 - .../github.com/fsnotify/fsnotify/.gitignore | 3 + .../github.com/fsnotify/fsnotify/CHANGELOG.md | 34 +- .../fsnotify/fsnotify/CONTRIBUTING.md | 120 ++- .../fsnotify/fsnotify/backend_fen.go | 324 ++----- .../fsnotify/fsnotify/backend_inotify.go | 594 ++++++------ .../fsnotify/fsnotify/backend_kqueue.go | 747 +++++++-------- .../fsnotify/fsnotify/backend_other.go | 204 +---- .../fsnotify/fsnotify/backend_windows.go | 305 ++----- .../github.com/fsnotify/fsnotify/fsnotify.go | 368 +++++++- .../fsnotify/fsnotify/internal/darwin.go | 39 + .../fsnotify/internal/debug_darwin.go | 57 ++ .../fsnotify/internal/debug_dragonfly.go | 33 + .../fsnotify/internal/debug_freebsd.go | 42 + .../fsnotify/internal/debug_kqueue.go | 32 + .../fsnotify/fsnotify/internal/debug_linux.go | 56 ++ .../fsnotify/internal/debug_netbsd.go | 25 + .../fsnotify/internal/debug_openbsd.go | 28 + .../fsnotify/internal/debug_solaris.go | 45 + .../fsnotify/internal/debug_windows.go | 40 + .../fsnotify/fsnotify/internal/freebsd.go | 31 + .../fsnotify/fsnotify/internal/internal.go | 2 + .../fsnotify/fsnotify/internal/unix.go | 31 + .../fsnotify/fsnotify/internal/unix2.go | 7 + .../fsnotify/fsnotify/internal/windows.go | 41 + vendor/github.com/fsnotify/fsnotify/mkdoc.zsh | 259 ------ .../fsnotify/fsnotify/system_bsd.go | 1 - .../fsnotify/fsnotify/system_darwin.go | 1 - .../go-viper/mapstructure/v2/decode_hooks.go | 61 +- .../go-viper/mapstructure/v2/mapstructure.go | 102 ++- vendor/github.com/hashicorp/hcl/.gitignore | 9 - vendor/github.com/hashicorp/hcl/.travis.yml | 13 - vendor/github.com/hashicorp/hcl/LICENSE | 354 -------- vendor/github.com/hashicorp/hcl/Makefile | 18 - vendor/github.com/hashicorp/hcl/README.md | 125 --- vendor/github.com/hashicorp/hcl/appveyor.yml | 19 - vendor/github.com/hashicorp/hcl/decoder.go | 729 --------------- vendor/github.com/hashicorp/hcl/hcl.go | 11 - .../github.com/hashicorp/hcl/hcl/ast/ast.go | 219 ----- .../github.com/hashicorp/hcl/hcl/ast/walk.go | 52 -- .../hashicorp/hcl/hcl/parser/error.go | 17 - .../hashicorp/hcl/hcl/parser/parser.go | 532 ----------- .../hashicorp/hcl/hcl/printer/nodes.go | 789 ---------------- .../hashicorp/hcl/hcl/printer/printer.go | 66 -- .../hashicorp/hcl/hcl/scanner/scanner.go | 652 -------------- .../hashicorp/hcl/hcl/strconv/quote.go | 241 ----- .../hashicorp/hcl/hcl/token/position.go | 46 - .../hashicorp/hcl/hcl/token/token.go | 219 ----- .../hashicorp/hcl/json/parser/flatten.go | 117 --- .../hashicorp/hcl/json/parser/parser.go | 313 ------- .../hashicorp/hcl/json/scanner/scanner.go | 451 ---------- .../hashicorp/hcl/json/token/position.go | 46 - .../hashicorp/hcl/json/token/token.go | 118 --- vendor/github.com/hashicorp/hcl/lex.go | 38 - vendor/github.com/hashicorp/hcl/parse.go | 39 - .../magiconair/properties/.gitignore | 6 - .../magiconair/properties/CHANGELOG.md | 205 ----- .../magiconair/properties/LICENSE.md | 24 - .../magiconair/properties/README.md | 128 --- .../magiconair/properties/decode.go | 289 ------ .../github.com/magiconair/properties/doc.go | 155 ---- .../magiconair/properties/integrate.go | 35 - .../github.com/magiconair/properties/lex.go | 395 -------- .../github.com/magiconair/properties/load.go | 293 ------ .../magiconair/properties/parser.go | 86 -- .../magiconair/properties/properties.go | 848 ------------------ .../magiconair/properties/rangecheck.go | 31 - .../pelletier/go-toml/v2/.goreleaser.yaml | 1 + .../github.com/pelletier/go-toml/v2/README.md | 2 +- .../pelletier/go-toml/v2/marshaler.go | 24 +- .../pelletier/go-toml/v2/unmarshaler.go | 45 +- .../sagikazarmark/locafero/flake.lock | 26 +- .../sagikazarmark/locafero/flake.nix | 17 + .../fsnotify => spf13/afero}/.editorconfig | 12 +- vendor/github.com/spf13/afero/.golangci.yaml | 18 + vendor/github.com/spf13/afero/README.md | 2 +- vendor/github.com/spf13/afero/iofs.go | 1 - vendor/github.com/spf13/afero/memmap.go | 2 - vendor/github.com/spf13/cast/README.md | 2 +- vendor/github.com/spf13/cast/caste.go | 4 +- .../spf13/pflag}/.editorconfig | 8 +- vendor/github.com/spf13/pflag/.golangci.yaml | 4 + vendor/github.com/spf13/pflag/flag.go | 29 +- vendor/github.com/spf13/pflag/ip.go | 3 + vendor/github.com/spf13/pflag/ipnet_slice.go | 147 +++ vendor/github.com/spf13/pflag/string_array.go | 4 - vendor/github.com/spf13/viper/.golangci.yaml | 3 - vendor/github.com/spf13/viper/README.md | 3 +- vendor/github.com/spf13/viper/UPDATES.md | 126 +++ vendor/github.com/spf13/viper/encoding.go | 181 ++++ vendor/github.com/spf13/viper/finder.go | 8 + vendor/github.com/spf13/viper/flake.lock | 26 +- vendor/github.com/spf13/viper/flake.nix | 2 +- .../spf13/viper/internal/encoding/decoder.go | 61 -- .../spf13/viper/internal/encoding/encoder.go | 60 -- .../spf13/viper/internal/encoding/error.go | 7 - .../viper/internal/encoding/hcl/codec.go | 40 - .../viper/internal/encoding/ini/codec.go | 99 -- .../viper/internal/encoding/ini/map_utils.go | 74 -- .../internal/encoding/javaproperties/codec.go | 86 -- .../encoding/javaproperties/map_utils.go | 74 -- vendor/github.com/spf13/viper/remote.go | 5 +- vendor/github.com/spf13/viper/util.go | 9 - vendor/github.com/spf13/viper/viper.go | 267 +++--- vendor/gopkg.in/ini.v1/.gitignore | 7 - vendor/gopkg.in/ini.v1/.golangci.yml | 27 - vendor/gopkg.in/ini.v1/LICENSE | 191 ---- vendor/gopkg.in/ini.v1/Makefile | 15 - vendor/gopkg.in/ini.v1/README.md | 43 - vendor/gopkg.in/ini.v1/codecov.yml | 16 - vendor/gopkg.in/ini.v1/data_source.go | 76 -- vendor/gopkg.in/ini.v1/deprecated.go | 22 - vendor/gopkg.in/ini.v1/error.go | 49 - vendor/gopkg.in/ini.v1/file.go | 541 ----------- vendor/gopkg.in/ini.v1/helper.go | 24 - vendor/gopkg.in/ini.v1/ini.go | 176 ---- vendor/gopkg.in/ini.v1/key.go | 837 ----------------- vendor/gopkg.in/ini.v1/parser.go | 520 ----------- vendor/gopkg.in/ini.v1/section.go | 256 ------ vendor/gopkg.in/ini.v1/struct.go | 747 --------------- vendor/modules.txt | 47 +- 124 files changed, 2782 insertions(+), 13727 deletions(-) delete mode 100644 vendor/github.com/fsnotify/fsnotify/.gitattributes create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/darwin.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/freebsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/internal.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/unix.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/unix2.go create mode 100644 vendor/github.com/fsnotify/fsnotify/internal/windows.go delete mode 100644 vendor/github.com/fsnotify/fsnotify/mkdoc.zsh delete mode 100644 vendor/github.com/hashicorp/hcl/.gitignore delete mode 100644 vendor/github.com/hashicorp/hcl/.travis.yml delete mode 100644 vendor/github.com/hashicorp/hcl/LICENSE delete mode 100644 vendor/github.com/hashicorp/hcl/Makefile delete mode 100644 vendor/github.com/hashicorp/hcl/README.md delete mode 100644 vendor/github.com/hashicorp/hcl/appveyor.yml delete mode 100644 vendor/github.com/hashicorp/hcl/decoder.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/ast/ast.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/ast/walk.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/parser/error.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/parser/parser.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/printer.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/token/position.go delete mode 100644 vendor/github.com/hashicorp/hcl/hcl/token/token.go delete mode 100644 vendor/github.com/hashicorp/hcl/json/parser/flatten.go delete mode 100644 vendor/github.com/hashicorp/hcl/json/parser/parser.go delete mode 100644 vendor/github.com/hashicorp/hcl/json/scanner/scanner.go delete mode 100644 vendor/github.com/hashicorp/hcl/json/token/position.go delete mode 100644 vendor/github.com/hashicorp/hcl/json/token/token.go delete mode 100644 vendor/github.com/hashicorp/hcl/lex.go delete mode 100644 vendor/github.com/hashicorp/hcl/parse.go delete mode 100644 vendor/github.com/magiconair/properties/.gitignore delete mode 100644 vendor/github.com/magiconair/properties/CHANGELOG.md delete mode 100644 vendor/github.com/magiconair/properties/LICENSE.md delete mode 100644 vendor/github.com/magiconair/properties/README.md delete mode 100644 vendor/github.com/magiconair/properties/decode.go delete mode 100644 vendor/github.com/magiconair/properties/doc.go delete mode 100644 vendor/github.com/magiconair/properties/integrate.go delete mode 100644 vendor/github.com/magiconair/properties/lex.go delete mode 100644 vendor/github.com/magiconair/properties/load.go delete mode 100644 vendor/github.com/magiconair/properties/parser.go delete mode 100644 vendor/github.com/magiconair/properties/properties.go delete mode 100644 vendor/github.com/magiconair/properties/rangecheck.go rename vendor/github.com/{fsnotify/fsnotify => spf13/afero}/.editorconfig (69%) create mode 100644 vendor/github.com/spf13/afero/.golangci.yaml rename vendor/{gopkg.in/ini.v1 => github.com/spf13/pflag}/.editorconfig (60%) create mode 100644 vendor/github.com/spf13/pflag/.golangci.yaml create mode 100644 vendor/github.com/spf13/pflag/ipnet_slice.go create mode 100644 vendor/github.com/spf13/viper/UPDATES.md create mode 100644 vendor/github.com/spf13/viper/encoding.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/decoder.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/encoder.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/error.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/ini/codec.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go delete mode 100644 vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go delete mode 100644 vendor/gopkg.in/ini.v1/.gitignore delete mode 100644 vendor/gopkg.in/ini.v1/.golangci.yml delete mode 100644 vendor/gopkg.in/ini.v1/LICENSE delete mode 100644 vendor/gopkg.in/ini.v1/Makefile delete mode 100644 vendor/gopkg.in/ini.v1/README.md delete mode 100644 vendor/gopkg.in/ini.v1/codecov.yml delete mode 100644 vendor/gopkg.in/ini.v1/data_source.go delete mode 100644 vendor/gopkg.in/ini.v1/deprecated.go delete mode 100644 vendor/gopkg.in/ini.v1/error.go delete mode 100644 vendor/gopkg.in/ini.v1/file.go delete mode 100644 vendor/gopkg.in/ini.v1/helper.go delete mode 100644 vendor/gopkg.in/ini.v1/ini.go delete mode 100644 vendor/gopkg.in/ini.v1/key.go delete mode 100644 vendor/gopkg.in/ini.v1/parser.go delete mode 100644 vendor/gopkg.in/ini.v1/section.go delete mode 100644 vendor/gopkg.in/ini.v1/struct.go diff --git a/go.mod b/go.mod index f9de4864..7052a0aa 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/sourcegraph/go-diff v0.6.1 - github.com/spf13/viper v1.20.0-alpha.1 + github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.10.0 golang.org/x/oauth2 v0.30.0 ) @@ -21,14 +21,11 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect - github.com/go-viper/mapstructure/v2 v2.0.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/sagikazarmark/locafero v0.6.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect ) require ( @@ -36,7 +33,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-git/go-git/v5 v5.13.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -52,15 +49,15 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/shopspring/decimal v1.4.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.7.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/wacul/ptr v1.0.0 // indirect golang.org/x/crypto v0.35.0 // indirect diff --git a/go.sum b/go.sum index 68be30a3..cbc0638d 100644 --- a/go.sum +++ b/go.sum @@ -61,15 +61,15 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= -github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -133,8 +133,6 @@ github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISH github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= @@ -162,8 +160,6 @@ github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f h1:jfiPiz2 github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f/go.mod h1:CHbYdMs8UjvNnS2fatlQvi4UYnBTRYGxRHc/0kQupSQ= github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0 h1:9+6tFBKH3YY/QNm6kc/6H75QRNdirT+nITP/9+GSYx4= github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0/go.mod h1:U+Ji+WaxJN2KYyaXDIkayj3DsypoogiWguw2D/75ohc= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -180,8 +176,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -197,8 +193,8 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= -github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -207,24 +203,17 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= -github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.0-alpha.1 h1:ScUDXU3yX4i/I1ovQQtaGe9kwl63fGzG3UsFr+pGtyY= -github.com/spf13/viper v1.20.0-alpha.1/go.mod h1:VJcuMrHwg6XArbUYF9KBRrFpavzx9NrQMFtdcRsZCLs= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -484,12 +473,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml index ffc7b992..f4e7dbf3 100644 --- a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml +++ b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml @@ -1,7 +1,7 @@ freebsd_task: name: 'FreeBSD' freebsd_instance: - image_family: freebsd-13-2 + image_family: freebsd-14-1 install_script: - pkg update -f - pkg install -y go @@ -9,5 +9,6 @@ freebsd_task: # run tests as user "cirrus" instead of root - pw useradd cirrus -m - chown -R cirrus:cirrus . - - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... - - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./... diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes deleted file mode 100644 index 32f1001b..00000000 --- a/vendor/github.com/fsnotify/fsnotify/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -go.sum linguist-generated diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore index 391cc076..daea9dd6 100644 --- a/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -5,3 +5,6 @@ # Output of go build ./cmd/fsnotify /fsnotify /fsnotify.exe + +/test/kqueue +/test/a.out diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index e0e57575..fa854785 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,8 +1,36 @@ # Changelog -Unreleased ----------- -Nothing yet. +1.8.0 2023-10-31 +---------------- + +### Additions + +- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619]) + +### Changes and fixes + +- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610]) + +- kqueue: ignore events with Ident=0 ([#590]) + +- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617]) + +- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625]) + +- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620]) + +- inotify: fix panic when calling Remove() in a goroutine ([#650]) + +- fen: allow watching subdirectories of watched directories ([#621]) + +[#590]: https://github.com/fsnotify/fsnotify/pull/590 +[#610]: https://github.com/fsnotify/fsnotify/pull/610 +[#617]: https://github.com/fsnotify/fsnotify/pull/617 +[#619]: https://github.com/fsnotify/fsnotify/pull/619 +[#620]: https://github.com/fsnotify/fsnotify/pull/620 +[#621]: https://github.com/fsnotify/fsnotify/pull/621 +[#625]: https://github.com/fsnotify/fsnotify/pull/625 +[#650]: https://github.com/fsnotify/fsnotify/pull/650 1.7.0 - 2023-10-22 ------------------ diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md index ea379759..e4ac2a2f 100644 --- a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -1,7 +1,7 @@ Thank you for your interest in contributing to fsnotify! We try to review and merge PRs in a reasonable timeframe, but please be aware that: -- To avoid "wasted" work, please discus changes on the issue tracker first. You +- To avoid "wasted" work, please discuss changes on the issue tracker first. You can just send PRs, but they may end up being rejected for one reason or the other. @@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like Use the `-short` flag to make the "stress test" run faster. +Writing new tests +----------------- +Scripts in the testdata directory allow creating test cases in a "shell-like" +syntax. The basic format is: + + script + + Output: + desired output + +For example: + + # Create a new empty file with some data. + watch / + echo data >/file + + Output: + create /file + write /file + +Just create a new file to add a new test; select which tests to run with +`-run TestScript/[path]`. + +script +------ +The script is a "shell-like" script: + + cmd arg arg + +Comments are supported with `#`: + + # Comment + cmd arg arg # Comment + +All operations are done in a temp directory; a path like "/foo" is rewritten to +"/tmp/TestFoo/foo". + +Arguments can be quoted with `"` or `'`; there are no escapes and they're +functionally identical right now, but this may change in the future, so best to +assume shell-like rules. + + touch "/file with spaces" + +End-of-line escapes with `\` are not supported. + +### Supported commands + + watch path [ops] # Watch the path, reporting events for it. Nothing is + # watched by default. Optionally a list of ops can be + # given, as with AddWith(path, WithOps(...)). + unwatch path # Stop watching the path. + watchlist n # Assert watchlist length. + + stop # Stop running the script; for debugging. + debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in + parallel by default, so -parallel=1 is probably a good + idea). + + touch path + mkdir [-p] dir + ln -s target link # Only ln -s supported. + mkfifo path + mknod dev path + mv src dst + rm [-r] path + chmod mode path # Octal only + sleep time-in-ms + + cat path # Read path (does nothing with the data; just reads it). + echo str >>path # Append "str" to "path". + echo str >path # Truncate "path" and write "str". + + require reason # Skip the test if "reason" is true; "skip" and + skip reason # "require" behave identical; it supports both for + # readability. Possible reasons are: + # + # always Always skip this test. + # symlink Symlinks are supported (requires admin + # permissions on Windows). + # mkfifo Platform doesn't support FIFO named sockets. + # mknod Platform doesn't support device nodes. + + +output +------ +After `Output:` the desired output is given; this is indented by convention, but +that's not required. + +The format of that is: + + # Comment + event path # Comment + + system: + event path + system2: + event path + +Every event is one line, and any whitespace between the event and path are +ignored. The path can optionally be surrounded in ". Anything after a "#" is +ignored. + +Platform-specific tests can be added after GOOS; for example: + + watch / + touch /file + + Output: + # Tested if nothing else matches + create /file + + # Windows-specific test. + windows: + write /file + +You can specify multiple platforms with a comma (e.g. "windows, linux:"). +"kqueue" is a shortcut for all kqueue systems (BSD, macOS). + [goon]: https://github.com/arp242/goon [Vagrant]: https://www.vagrantup.com/ diff --git a/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/vendor/github.com/fsnotify/fsnotify/backend_fen.go index 28497f1d..c349c326 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_fen.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_fen.go @@ -1,8 +1,8 @@ //go:build solaris -// +build solaris -// Note: the documentation on the Watcher type and methods is generated from -// mkdoc.zsh +// FEN backend for illumos (supported) and Solaris (untested, but should work). +// +// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create package fsnotify @@ -12,150 +12,33 @@ import ( "os" "path/filepath" "sync" + "time" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # Windows notes -// -// Paths can be added as "C:\path\to\dir", but forward slashes -// ("C:/path/to/dir") will also work. -// -// When a watched directory is removed it will always send an event for the -// directory itself, but may not send events for all files in that directory. -// Sometimes it will send events for all times, sometimes it will send no -// events, and often only for some files. -// -// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest -// value that is guaranteed to work with SMB filesystems. If you have many -// events in quick succession this may not be enough, and you will have to use -// [WithBufferSize] to increase the value. -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, and you may - // want to wait until you've stopped receiving them - // (see the dedup example in cmd/fsnotify). - // - // Some systems may send Write event for directories - // when the directory content changes. - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // when a file is truncated. On Windows it's never - // sent. +type fen struct { Events chan Event - - // Errors sends any errors. - // - // ErrEventOverflow is used to indicate there are too many events: - // - // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) - // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. - // - kqueue, fen: Not used. Errors chan error mu sync.Mutex port *unix.EventPort - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - dirs map[string]struct{} // Explicitly watched directories - watches map[string]struct{} // Explicitly watched non-directories + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + dirs map[string]Op // Explicitly watched directories + watches map[string]Op // Explicitly watched non-directories } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return NewBufferedWatcher(0) +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) } -// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events -// channel. -// -// The main use case for this is situations with a very large number of events -// where the kernel buffer size can't be increased (e.g. due to lack of -// permissions). An unbuffered Watcher will perform better for almost all use -// cases, and whenever possible you will be better off increasing the kernel -// buffers instead of adding a large userspace buffer. -func NewBufferedWatcher(sz uint) (*Watcher, error) { - w := &Watcher{ - Events: make(chan Event, sz), - Errors: make(chan error), - dirs: make(map[string]struct{}), - watches: make(map[string]struct{}), +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + w := &fen{ + Events: ev, + Errors: errs, + dirs: make(map[string]Op), + watches: make(map[string]Op), done: make(chan struct{}), } @@ -171,27 +54,30 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) { // sendEvent attempts to send an event to the user, returning true if the event // was put in the channel successfully and false if the watcher has been closed. -func (w *Watcher) sendEvent(name string, op Op) (sent bool) { +func (w *fen) sendEvent(name string, op Op) (sent bool) { select { - case w.Events <- Event{Name: name, Op: op}: - return true case <-w.done: return false + case w.Events <- Event{Name: name, Op: op}: + return true } } // sendError attempts to send an error to the user, returning true if the error // was put in the channel successfully and false if the watcher has been closed. -func (w *Watcher) sendError(err error) (sent bool) { - select { - case w.Errors <- err: +func (w *fen) sendError(err error) (sent bool) { + if err == nil { return true + } + select { case <-w.done: return false + case w.Errors <- err: + return true } } -func (w *Watcher) isClosed() bool { +func (w *fen) isClosed() bool { select { case <-w.done: return true @@ -200,8 +86,7 @@ func (w *Watcher) isClosed() bool { } } -// Close removes all watches and closes the Events channel. -func (w *Watcher) Close() error { +func (w *fen) Close() error { // Take the lock used by associateFile to prevent lingering events from // being processed after the close w.mu.Lock() @@ -213,60 +98,21 @@ func (w *Watcher) Close() error { return w.port.Close() } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; watching it more than once is a no-op and will -// not return an error. Paths that do not yet exist on the filesystem cannot be -// watched. -// -// A watch will be automatically removed if the watched path is deleted or -// renamed. The exception is the Windows backend, which doesn't remove the -// watcher on renames. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// Returns [ErrClosed] if [Watcher.Close] was called. -// -// See [Watcher.AddWith] for a version that allows adding options. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many programs (especially editors) update files atomically: it -// will write to a temporary file which is then moved to to destination, -// overwriting the original (or some variant thereof). The watcher on the -// original file is now lost, as that no longer exists. -// -// The upshot of this is that a power failure or crash won't leave a -// half-written file. -// -// Watch the parent directory and use Event.Name to filter out files you're not -// interested in. There is an example of this in cmd/fsnotify/file.go. -func (w *Watcher) Add(name string) error { return w.AddWith(name) } +func (w *fen) Add(name string) error { return w.AddWith(name) } -// AddWith is like [Watcher.Add], but allows adding options. When using Add() -// the defaults described below are used. -// -// Possible options are: -// -// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on -// other platforms. The default is 64K (65536 bytes). -func (w *Watcher) AddWith(name string, opts ...addOpt) error { +func (w *fen) AddWith(name string, opts ...addOpt) error { if w.isClosed() { return ErrClosed } - if w.port.PathIsWatched(name) { - return nil + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) } - _ = getOptions(opts...) + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } // Currently we resolve symlinks that were explicitly requested to be // watched. Otherwise we would use LStat here. @@ -283,7 +129,7 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error { } w.mu.Lock() - w.dirs[name] = struct{}{} + w.dirs[name] = with.op w.mu.Unlock() return nil } @@ -294,26 +140,22 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error { } w.mu.Lock() - w.watches[name] = struct{}{} + w.watches[name] = with.op w.mu.Unlock() return nil } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) Remove(name string) error { +func (w *fen) Remove(name string) error { if w.isClosed() { return nil } if !w.port.PathIsWatched(name) { return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } // The user has expressed an intent. Immediately remove this name from // whichever watch list it might be in. If it's not in there the delete @@ -346,7 +188,7 @@ func (w *Watcher) Remove(name string) error { } // readEvents contains the main loop that runs in a goroutine watching for events. -func (w *Watcher) readEvents() { +func (w *fen) readEvents() { // If this function returns, the watcher has been closed and we can close // these channels defer func() { @@ -382,17 +224,19 @@ func (w *Watcher) readEvents() { continue } + if debug { + internal.Debug(pevent.Path, pevent.Events) + } + err = w.handleEvent(&pevent) - if err != nil { - if !w.sendError(err) { - return - } + if !w.sendError(err) { + return } } } } -func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error { +func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error { files, err := os.ReadDir(path) if err != nil { return err @@ -418,7 +262,7 @@ func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, ha // bitmap matches more than one event type (e.g. the file was both modified and // had the attributes changed between when the association was created and the // when event was returned) -func (w *Watcher) handleEvent(event *unix.PortEvent) error { +func (w *fen) handleEvent(event *unix.PortEvent) error { var ( events = event.Events path = event.Path @@ -510,15 +354,9 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error { } if events&unix.FILE_MODIFIED != 0 { - if fmode.IsDir() { - if watchedDir { - if err := w.updateDirectory(path); err != nil { - return err - } - } else { - if !w.sendEvent(path, Write) { - return nil - } + if fmode.IsDir() && watchedDir { + if err := w.updateDirectory(path); err != nil { + return err } } else { if !w.sendEvent(path, Write) { @@ -543,7 +381,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error { return nil } -func (w *Watcher) updateDirectory(path string) error { +func (w *fen) updateDirectory(path string) error { // The directory was modified, so we must find unwatched entities and watch // them. If something was removed from the directory, nothing will happen, // as everything else should still be watched. @@ -563,10 +401,8 @@ func (w *Watcher) updateDirectory(path string) error { return err } err = w.associateFile(path, finfo, false) - if err != nil { - if !w.sendError(err) { - return nil - } + if !w.sendError(err) { + return nil } if !w.sendEvent(path, Create) { return nil @@ -575,7 +411,7 @@ func (w *Watcher) updateDirectory(path string) error { return nil } -func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) error { +func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error { if w.isClosed() { return ErrClosed } @@ -593,34 +429,34 @@ func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) erro // cleared up that discrepancy. The most likely cause is that the event // has fired but we haven't processed it yet. err := w.port.DissociatePath(path) - if err != nil && err != unix.ENOENT { + if err != nil && !errors.Is(err, unix.ENOENT) { return err } } - // FILE_NOFOLLOW means we watch symlinks themselves rather than their - // targets. - events := unix.FILE_MODIFIED | unix.FILE_ATTRIB | unix.FILE_NOFOLLOW - if follow { - // We *DO* follow symlinks for explicitly watched entries. - events = unix.FILE_MODIFIED | unix.FILE_ATTRIB + + var events int + if !follow { + // Watch symlinks themselves rather than their targets unless this entry + // is explicitly watched. + events |= unix.FILE_NOFOLLOW + } + if true { // TODO: implement withOps() + events |= unix.FILE_MODIFIED } - return w.port.AssociatePath(path, stat, - events, - stat.Mode()) + if true { + events |= unix.FILE_ATTRIB + } + return w.port.AssociatePath(path, stat, events, stat.Mode()) } -func (w *Watcher) dissociateFile(path string, stat os.FileInfo, unused bool) error { +func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error { if !w.port.PathIsWatched(path) { return nil } return w.port.DissociatePath(path) } -// WatchList returns all paths explicitly added with [Watcher.Add] (and are not -// yet removed). -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) WatchList() []string { +func (w *fen) WatchList() []string { if w.isClosed() { return nil } @@ -638,3 +474,11 @@ func (w *Watcher) WatchList() []string { return entries } + +func (w *fen) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go index 921c1c1e..36c31169 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -1,8 +1,4 @@ //go:build linux && !appengine -// +build linux,!appengine - -// Note: the documentation on the Watcher type and methods is generated from -// mkdoc.zsh package fsnotify @@ -10,127 +6,20 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "strings" "sync" + "time" "unsafe" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # Windows notes -// -// Paths can be added as "C:\path\to\dir", but forward slashes -// ("C:/path/to/dir") will also work. -// -// When a watched directory is removed it will always send an event for the -// directory itself, but may not send events for all files in that directory. -// Sometimes it will send events for all times, sometimes it will send no -// events, and often only for some files. -// -// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest -// value that is guaranteed to work with SMB filesystems. If you have many -// events in quick succession this may not be enough, and you will have to use -// [WithBufferSize] to increase the value. -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, and you may - // want to wait until you've stopped receiving them - // (see the dedup example in cmd/fsnotify). - // - // Some systems may send Write event for directories - // when the directory content changes. - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // when a file is truncated. On Windows it's never - // sent. +type inotify struct { Events chan Event - - // Errors sends any errors. - // - // ErrEventOverflow is used to indicate there are too many events: - // - // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) - // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. - // - kqueue, fen: Not used. Errors chan error // Store fd here as os.File.Read() will no longer return on close after @@ -139,8 +28,26 @@ type Watcher struct { inotifyFile *os.File watches *watches done chan struct{} // Channel for sending a "quit message" to the reader goroutine - closeMu sync.Mutex + doneMu sync.Mutex doneResp chan struct{} // Channel to respond to Close + + // Store rename cookies in an array, with the index wrapping to 0. Almost + // all of the time what we get is a MOVED_FROM to set the cookie and the + // next event inotify sends will be MOVED_TO to read it. However, this is + // not guaranteed – as described in inotify(7) – and we may get other events + // between the two MOVED_* events (including other MOVED_* ones). + // + // A second issue is that moving a file outside the watched directory will + // trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to + // read and delete it. So just storing it in a map would slowly leak memory. + // + // Doing it like this gives us a simple fast LRU-cache that won't allocate. + // Ten items should be more than enough for our purpose, and a loop over + // such a short array is faster than a map access anyway (not that it hugely + // matters since we're talking about hundreds of ns at the most, but still). + cookies [10]koekje + cookieIndex uint8 + cookiesMu sync.Mutex } type ( @@ -150,9 +57,14 @@ type ( path map[string]uint32 // pathname → wd } watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) - path string // Watch path. + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) + path string // Watch path. + recurse bool // Recursion with ./...? + } + koekje struct { + cookie uint32 + path string } ) @@ -179,23 +91,45 @@ func (w *watches) add(ww *watch) { func (w *watches) remove(wd uint32) { w.mu.Lock() defer w.mu.Unlock() - delete(w.path, w.wd[wd].path) + watch := w.wd[wd] // Could have had Remove() called. See #616. + if watch == nil { + return + } + delete(w.path, watch.path) delete(w.wd, wd) } -func (w *watches) removePath(path string) (uint32, bool) { +func (w *watches) removePath(path string) ([]uint32, error) { w.mu.Lock() defer w.mu.Unlock() + path, recurse := recursivePath(path) wd, ok := w.path[path] if !ok { - return 0, false + return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path) + } + + watch := w.wd[wd] + if recurse && !watch.recurse { + return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path) } delete(w.path, path) delete(w.wd, wd) + if !watch.recurse { + return []uint32{wd}, nil + } - return wd, true + wds := make([]uint32, 0, 8) + wds = append(wds, wd) + for p, rwd := range w.path { + if filepath.HasPrefix(p, path) { + delete(w.path, p) + delete(w.wd, rwd) + wds = append(wds, rwd) + } + } + return wds, nil } func (w *watches) byPath(path string) *watch { @@ -236,20 +170,11 @@ func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error return nil } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return NewBufferedWatcher(0) +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) } -// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events -// channel. -// -// The main use case for this is situations with a very large number of events -// where the kernel buffer size can't be increased (e.g. due to lack of -// permissions). An unbuffered Watcher will perform better for almost all use -// cases, and whenever possible you will be better off increasing the kernel -// buffers instead of adding a large userspace buffer. -func NewBufferedWatcher(sz uint) (*Watcher, error) { +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { // Need to set nonblocking mode for SetDeadline to work, otherwise blocking // I/O operations won't terminate on close. fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) @@ -257,12 +182,12 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) { return nil, errno } - w := &Watcher{ + w := &inotify{ + Events: ev, + Errors: errs, fd: fd, inotifyFile: os.NewFile(uintptr(fd), ""), watches: newWatches(), - Events: make(chan Event, sz), - Errors: make(chan error), done: make(chan struct{}), doneResp: make(chan struct{}), } @@ -272,26 +197,29 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) { } // Returns true if the event was sent, or false if watcher is closed. -func (w *Watcher) sendEvent(e Event) bool { +func (w *inotify) sendEvent(e Event) bool { select { - case w.Events <- e: - return true case <-w.done: return false + case w.Events <- e: + return true } } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { - select { - case w.Errors <- err: +func (w *inotify) sendError(err error) bool { + if err == nil { return true + } + select { case <-w.done: return false + case w.Errors <- err: + return true } } -func (w *Watcher) isClosed() bool { +func (w *inotify) isClosed() bool { select { case <-w.done: return true @@ -300,15 +228,14 @@ func (w *Watcher) isClosed() bool { } } -// Close removes all watches and closes the Events channel. -func (w *Watcher) Close() error { - w.closeMu.Lock() +func (w *inotify) Close() error { + w.doneMu.Lock() if w.isClosed() { - w.closeMu.Unlock() + w.doneMu.Unlock() return nil } close(w.done) - w.closeMu.Unlock() + w.doneMu.Unlock() // Causes any blocking reads to return with an error, provided the file // still supports deadline operations. @@ -323,78 +250,104 @@ func (w *Watcher) Close() error { return nil } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; watching it more than once is a no-op and will -// not return an error. Paths that do not yet exist on the filesystem cannot be -// watched. -// -// A watch will be automatically removed if the watched path is deleted or -// renamed. The exception is the Windows backend, which doesn't remove the -// watcher on renames. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// Returns [ErrClosed] if [Watcher.Close] was called. -// -// See [Watcher.AddWith] for a version that allows adding options. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many programs (especially editors) update files atomically: it -// will write to a temporary file which is then moved to to destination, -// overwriting the original (or some variant thereof). The watcher on the -// original file is now lost, as that no longer exists. -// -// The upshot of this is that a power failure or crash won't leave a -// half-written file. -// -// Watch the parent directory and use Event.Name to filter out files you're not -// interested in. There is an example of this in cmd/fsnotify/file.go. -func (w *Watcher) Add(name string) error { return w.AddWith(name) } - -// AddWith is like [Watcher.Add], but allows adding options. When using Add() -// the defaults described below are used. -// -// Possible options are: -// -// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on -// other platforms. The default is 64K (65536 bytes). -func (w *Watcher) AddWith(name string, opts ...addOpt) error { +func (w *inotify) Add(name string) error { return w.AddWith(name) } + +func (w *inotify) AddWith(path string, opts ...addOpt) error { if w.isClosed() { return ErrClosed } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), path) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } - name = filepath.Clean(name) - _ = getOptions(opts...) + path, recurse := recursivePath(path) + if recurse { + return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + if root == path { + return fmt.Errorf("fsnotify: not a directory: %q", path) + } + return nil + } - var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | - unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | - unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF + // Send a Create event when adding new directory from a recursive + // watch; this is for "mkdir -p one/two/three". Usually all those + // directories will be created before we can set up watchers on the + // subdirectories, so only "one" would be sent as a Create event and + // not "one/two" and "one/two/three" (inotifywait -r has the same + // problem). + if with.sendCreate && root != path { + w.sendEvent(Event{Name: root, Op: Create}) + } + + return w.add(root, with, true) + }) + } - return w.watches.updatePath(name, func(existing *watch) (*watch, error) { + return w.add(path, with, false) +} + +func (w *inotify) add(path string, with withOpts, recurse bool) error { + var flags uint32 + if with.noFollow { + flags |= unix.IN_DONT_FOLLOW + } + if with.op.Has(Create) { + flags |= unix.IN_CREATE + } + if with.op.Has(Write) { + flags |= unix.IN_MODIFY + } + if with.op.Has(Remove) { + flags |= unix.IN_DELETE | unix.IN_DELETE_SELF + } + if with.op.Has(Rename) { + flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF + } + if with.op.Has(Chmod) { + flags |= unix.IN_ATTRIB + } + if with.op.Has(xUnportableOpen) { + flags |= unix.IN_OPEN + } + if with.op.Has(xUnportableRead) { + flags |= unix.IN_ACCESS + } + if with.op.Has(xUnportableCloseWrite) { + flags |= unix.IN_CLOSE_WRITE + } + if with.op.Has(xUnportableCloseRead) { + flags |= unix.IN_CLOSE_NOWRITE + } + return w.register(path, flags, recurse) +} + +func (w *inotify) register(path string, flags uint32, recurse bool) error { + return w.watches.updatePath(path, func(existing *watch) (*watch, error) { if existing != nil { flags |= existing.flags | unix.IN_MASK_ADD } - wd, err := unix.InotifyAddWatch(w.fd, name, flags) + wd, err := unix.InotifyAddWatch(w.fd, path, flags) if wd == -1 { return nil, err } if existing == nil { return &watch{ - wd: uint32(wd), - path: name, - flags: flags, + wd: uint32(wd), + path: path, + flags: flags, + recurse: recurse, }, nil } @@ -404,49 +357,44 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error { }) } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) Remove(name string) error { +func (w *inotify) Remove(name string) error { if w.isClosed() { return nil } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } return w.remove(filepath.Clean(name)) } -func (w *Watcher) remove(name string) error { - wd, ok := w.watches.removePath(name) - if !ok { - return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) - } - - success, errno := unix.InotifyRmWatch(w.fd, wd) - if success == -1 { - // TODO: Perhaps it's not helpful to return an error here in every case; - // The only two possible errors are: - // - // - EBADF, which happens when w.fd is not a valid file descriptor - // of any kind. - // - EINVAL, which is when fd is not an inotify descriptor or wd - // is not a valid watch descriptor. Watch descriptors are - // invalidated when they are removed explicitly or implicitly; - // explicitly by inotify_rm_watch, implicitly when the file they - // are watching is deleted. - return errno +func (w *inotify) remove(name string) error { + wds, err := w.watches.removePath(name) + if err != nil { + return err + } + + for _, wd := range wds { + _, err := unix.InotifyRmWatch(w.fd, wd) + if err != nil { + // TODO: Perhaps it's not helpful to return an error here in every + // case; the only two possible errors are: + // + // EBADF, which happens when w.fd is not a valid file descriptor of + // any kind. + // + // EINVAL, which is when fd is not an inotify descriptor or wd is + // not a valid watch descriptor. Watch descriptors are invalidated + // when they are removed explicitly or implicitly; explicitly by + // inotify_rm_watch, implicitly when the file they are watching is + // deleted. + return err + } } return nil } -// WatchList returns all paths explicitly added with [Watcher.Add] (and are not -// yet removed). -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) WatchList() []string { +func (w *inotify) WatchList() []string { if w.isClosed() { return nil } @@ -463,7 +411,7 @@ func (w *Watcher) WatchList() []string { // readEvents reads from the inotify file descriptor, converts the // received events into Event objects and sends them via the Events channel -func (w *Watcher) readEvents() { +func (w *inotify) readEvents() { defer func() { close(w.doneResp) close(w.Errors) @@ -506,15 +454,17 @@ func (w *Watcher) readEvents() { continue } - var offset uint32 // We don't know how many events we just read into the buffer // While the offset points to at least one whole event... + var offset uint32 for offset <= uint32(n-unix.SizeofInotifyEvent) { var ( // Point "raw" to the event in the buffer raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) mask = uint32(raw.Mask) nameLen = uint32(raw.Len) + // Move to the next event in the buffer + next = func() { offset += unix.SizeofInotifyEvent + nameLen } ) if mask&unix.IN_Q_OVERFLOW != 0 { @@ -523,21 +473,53 @@ func (w *Watcher) readEvents() { } } - // If the event happened to the watched directory or the watched file, the kernel - // doesn't append the filename to the event, but we would like to always fill the - // the "Name" field with a valid filename. We retrieve the path of the watch from - // the "paths" map. + /// If the event happened to the watched directory or the watched + /// file, the kernel doesn't append the filename to the event, but + /// we would like to always fill the the "Name" field with a valid + /// filename. We retrieve the path of the watch from the "paths" + /// map. watch := w.watches.byWd(uint32(raw.Wd)) + /// Can be nil if Remove() was called in another goroutine for this + /// path inbetween reading the events from the kernel and reading + /// the internal state. Not much we can do about it, so just skip. + /// See #616. + if watch == nil { + next() + continue + } + + name := watch.path + if nameLen > 0 { + /// Point "bytes" at the first byte of the filename + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] + /// The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + if debug { + internal.Debug(name, raw.Mask, raw.Cookie) + } + + if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0 + next() + continue + } // inotify will automatically remove the watch on deletes; just need // to clean our state here. - if watch != nil && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { w.watches.remove(watch.wd) } + // We can't really update the state when a watched path is moved; // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove // the watch. - if watch != nil && mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF { + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF { + if watch.recurse { + next() // Do nothing + continue + } + err := w.remove(watch.path) if err != nil && !errors.Is(err, ErrNonExistentWatch) { if !w.sendError(err) { @@ -546,34 +528,69 @@ func (w *Watcher) readEvents() { } } - var name string - if watch != nil { - name = watch.path - } - if nameLen > 0 { - // Point "bytes" at the first byte of the filename - bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] - // The filename is padded with NULL bytes. TrimRight() gets rid of those. - name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + /// Skip if we're watching both this path and the parent; the parent + /// will already send a delete so no need to do it twice. + if mask&unix.IN_DELETE_SELF != 0 { + if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok { + next() + continue + } } - event := w.newEvent(name, mask) + ev := w.newEvent(name, mask, raw.Cookie) + // Need to update watch path for recurse. + if watch.recurse { + isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR + /// New directory created: set up watch on it. + if isDir && ev.Has(Create) { + err := w.register(ev.Name, watch.flags, true) + if !w.sendError(err) { + return + } - // Send the events that are not ignored on the events channel - if mask&unix.IN_IGNORED == 0 { - if !w.sendEvent(event) { - return + // This was a directory rename, so we need to update all + // the children. + // + // TODO: this is of course pretty slow; we should use a + // better data structure for storing all of this, e.g. store + // children in the watch. I have some code for this in my + // kqueue refactor we can use in the future. For now I'm + // okay with this as it's not publicly available. + // Correctness first, performance second. + if ev.renamedFrom != "" { + w.watches.mu.Lock() + for k, ww := range w.watches.wd { + if k == watch.wd || ww.path == ev.Name { + continue + } + if strings.HasPrefix(ww.path, ev.renamedFrom) { + ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1) + w.watches.wd[k] = ww + } + } + w.watches.mu.Unlock() + } } } - // Move to the next event in the buffer - offset += unix.SizeofInotifyEvent + nameLen + /// Send the events that are not ignored on the events channel + if !w.sendEvent(ev) { + return + } + next() } } } -// newEvent returns an platform-independent Event based on an inotify mask. -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *inotify) isRecursive(path string) bool { + ww := w.watches.byPath(path) + if ww == nil { // path could be a file, so also check the Dir. + ww = w.watches.byPath(filepath.Dir(path)) + } + return ww != nil && ww.recurse +} + +func (w *inotify) newEvent(name string, mask, cookie uint32) Event { e := Event{Name: name} if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { e.Op |= Create @@ -584,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&unix.IN_MODIFY == unix.IN_MODIFY { e.Op |= Write } + if mask&unix.IN_OPEN == unix.IN_OPEN { + e.Op |= xUnportableOpen + } + if mask&unix.IN_ACCESS == unix.IN_ACCESS { + e.Op |= xUnportableRead + } + if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE { + e.Op |= xUnportableCloseWrite + } + if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE { + e.Op |= xUnportableCloseRead + } if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { e.Op |= Rename } if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { e.Op |= Chmod } + + if cookie != 0 { + if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + w.cookiesMu.Lock() + w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name} + w.cookieIndex++ + if w.cookieIndex > 9 { + w.cookieIndex = 0 + } + w.cookiesMu.Unlock() + } else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + w.cookiesMu.Lock() + var prev string + for _, c := range w.cookies { + if c.cookie == cookie { + prev = c.path + break + } + } + w.cookiesMu.Unlock() + e.renamedFrom = prev + } + } return e } + +func (w *inotify) xSupports(op Op) bool { + return true // Supports everything. +} + +func (w *inotify) state() { + w.watches.mu.Lock() + defer w.watches.mu.Unlock() + for wd, ww := range w.watches.wd { + fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path) + } +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go index 063a0915..d8de5ab7 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go @@ -1,8 +1,4 @@ //go:build freebsd || openbsd || netbsd || dragonfly || darwin -// +build freebsd openbsd netbsd dragonfly darwin - -// Note: the documentation on the Watcher type and methods is generated from -// mkdoc.zsh package fsnotify @@ -11,174 +7,195 @@ import ( "fmt" "os" "path/filepath" + "runtime" "sync" + "time" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # Windows notes -// -// Paths can be added as "C:\path\to\dir", but forward slashes -// ("C:/path/to/dir") will also work. -// -// When a watched directory is removed it will always send an event for the -// directory itself, but may not send events for all files in that directory. -// Sometimes it will send events for all times, sometimes it will send no -// events, and often only for some files. -// -// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest -// value that is guaranteed to work with SMB filesystems. If you have many -// events in quick succession this may not be enough, and you will have to use -// [WithBufferSize] to increase the value. -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, and you may - // want to wait until you've stopped receiving them - // (see the dedup example in cmd/fsnotify). - // - // Some systems may send Write event for directories - // when the directory content changes. - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // when a file is truncated. On Windows it's never - // sent. +type kqueue struct { Events chan Event - - // Errors sends any errors. - // - // ErrEventOverflow is used to indicate there are too many events: - // - // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) - // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. - // - kqueue, fen: Not used. Errors chan error - done chan struct{} - kq int // File descriptor (as returned by the kqueue() syscall). - closepipe [2]int // Pipe used for closing. - mu sync.Mutex // Protects access to watcher data - watches map[string]int // Watched file descriptors (key: path). - watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)). - userWatches map[string]struct{} // Watches added with Watcher.Add() - dirFlags map[string]uint32 // Watched directories to fflags used in kqueue. - paths map[int]pathInfo // File descriptors to path names for processing kqueue events. - fileExists map[string]struct{} // Keep track of if we know this file exists (to stop duplicate create events). - isClosed bool // Set to true when Close() is first called + kq int // File descriptor (as returned by the kqueue() syscall). + closepipe [2]int // Pipe used for closing kq. + watches *watches + done chan struct{} + doneMu sync.Mutex } -type pathInfo struct { - name string - isDir bool +type ( + watches struct { + mu sync.RWMutex + wd map[int]watch // wd → watch + path map[string]int // pathname → wd + byDir map[string]map[int]struct{} // dirname(path) → wd + seen map[string]struct{} // Keep track of if we know this file exists. + byUser map[string]struct{} // Watches added with Watcher.Add() + } + watch struct { + wd int + name string + linkName string // In case of links; name is the target, and this is the link. + isDir bool + dirFlags uint32 + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[int]watch), + path: make(map[string]int), + byDir: make(map[string]map[int]struct{}), + seen: make(map[string]struct{}), + byUser: make(map[string]struct{}), + } } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return NewBufferedWatcher(0) +func (w *watches) listPaths(userOnly bool) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + if userOnly { + l := make([]string, 0, len(w.byUser)) + for p := range w.byUser { + l = append(l, p) + } + return l + } + + l := make([]string, 0, len(w.path)) + for p := range w.path { + l = append(l, p) + } + return l } -// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events -// channel. -// -// The main use case for this is situations with a very large number of events -// where the kernel buffer size can't be increased (e.g. due to lack of -// permissions). An unbuffered Watcher will perform better for almost all use -// cases, and whenever possible you will be better off increasing the kernel -// buffers instead of adding a large userspace buffer. -func NewBufferedWatcher(sz uint) (*Watcher, error) { +func (w *watches) watchesInDir(path string) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + l := make([]string, 0, 4) + for fd := range w.byDir[path] { + info := w.wd[fd] + if _, ok := w.byUser[info.name]; !ok { + l = append(l, info.name) + } + } + return l +} + +// Mark path as added by the user. +func (w *watches) addUserWatch(path string) { + w.mu.Lock() + defer w.mu.Unlock() + w.byUser[path] = struct{}{} +} + +func (w *watches) addLink(path string, fd int) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.seen[path] = struct{}{} +} + +func (w *watches) add(path, linkPath string, fd int, isDir bool) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir} + + parent := filepath.Dir(path) + byDir, ok := w.byDir[parent] + if !ok { + byDir = make(map[int]struct{}, 1) + w.byDir[parent] = byDir + } + byDir[fd] = struct{}{} +} + +func (w *watches) byWd(fd int) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[fd] + return info, ok +} + +func (w *watches) byPath(path string) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[w.path[path]] + return info, ok +} + +func (w *watches) updateDirFlags(path string, flags uint32) { + w.mu.Lock() + defer w.mu.Unlock() + + fd := w.path[path] + info := w.wd[fd] + info.dirFlags = flags + w.wd[fd] = info +} + +func (w *watches) remove(fd int, path string) bool { + w.mu.Lock() + defer w.mu.Unlock() + + isDir := w.wd[fd].isDir + delete(w.path, path) + delete(w.byUser, path) + + parent := filepath.Dir(path) + delete(w.byDir[parent], fd) + + if len(w.byDir[parent]) == 0 { + delete(w.byDir, parent) + } + + delete(w.wd, fd) + delete(w.seen, path) + return isDir +} + +func (w *watches) markSeen(path string, exists bool) { + w.mu.Lock() + defer w.mu.Unlock() + if exists { + w.seen[path] = struct{}{} + } else { + delete(w.seen, path) + } +} + +func (w *watches) seenBefore(path string) bool { + w.mu.RLock() + defer w.mu.RUnlock() + _, ok := w.seen[path] + return ok +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { kq, closepipe, err := newKqueue() if err != nil { return nil, err } - w := &Watcher{ - kq: kq, - closepipe: closepipe, - watches: make(map[string]int), - watchesByDir: make(map[string]map[int]struct{}), - dirFlags: make(map[string]uint32), - paths: make(map[int]pathInfo), - fileExists: make(map[string]struct{}), - userWatches: make(map[string]struct{}), - Events: make(chan Event, sz), - Errors: make(chan error), - done: make(chan struct{}), + w := &kqueue{ + Events: ev, + Errors: errs, + kq: kq, + closepipe: closepipe, + done: make(chan struct{}), + watches: newWatches(), } go w.readEvents() @@ -203,6 +220,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) { unix.Close(kq) return kq, closepipe, err } + unix.CloseOnExec(closepipe[0]) + unix.CloseOnExec(closepipe[1]) // Register changes to listen on the closepipe. changes := make([]unix.Kevent_t, 1) @@ -221,166 +240,108 @@ func newKqueue() (kq int, closepipe [2]int, err error) { } // Returns true if the event was sent, or false if watcher is closed. -func (w *Watcher) sendEvent(e Event) bool { +func (w *kqueue) sendEvent(e Event) bool { select { - case w.Events <- e: - return true case <-w.done: return false + case w.Events <- e: + return true } } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { +func (w *kqueue) sendError(err error) bool { + if err == nil { + return true + } select { + case <-w.done: + return false case w.Errors <- err: return true + } +} + +func (w *kqueue) isClosed() bool { + select { case <-w.done: + return true + default: return false } } -// Close removes all watches and closes the Events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() +func (w *kqueue) Close() error { + w.doneMu.Lock() + if w.isClosed() { + w.doneMu.Unlock() return nil } - w.isClosed = true + close(w.done) + w.doneMu.Unlock() - // copy paths to remove while locked - pathsToRemove := make([]string, 0, len(w.watches)) - for name := range w.watches { - pathsToRemove = append(pathsToRemove, name) - } - w.mu.Unlock() // Unlock before calling Remove, which also locks + pathsToRemove := w.watches.listPaths(false) for _, name := range pathsToRemove { w.Remove(name) } // Send "quit" message to the reader goroutine. unix.Close(w.closepipe[1]) - close(w.done) - return nil } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; watching it more than once is a no-op and will -// not return an error. Paths that do not yet exist on the filesystem cannot be -// watched. -// -// A watch will be automatically removed if the watched path is deleted or -// renamed. The exception is the Windows backend, which doesn't remove the -// watcher on renames. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// Returns [ErrClosed] if [Watcher.Close] was called. -// -// See [Watcher.AddWith] for a version that allows adding options. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many programs (especially editors) update files atomically: it -// will write to a temporary file which is then moved to to destination, -// overwriting the original (or some variant thereof). The watcher on the -// original file is now lost, as that no longer exists. -// -// The upshot of this is that a power failure or crash won't leave a -// half-written file. -// -// Watch the parent directory and use Event.Name to filter out files you're not -// interested in. There is an example of this in cmd/fsnotify/file.go. -func (w *Watcher) Add(name string) error { return w.AddWith(name) } +func (w *kqueue) Add(name string) error { return w.AddWith(name) } -// AddWith is like [Watcher.Add], but allows adding options. When using Add() -// the defaults described below are used. -// -// Possible options are: -// -// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on -// other platforms. The default is 64K (65536 bytes). -func (w *Watcher) AddWith(name string, opts ...addOpt) error { - _ = getOptions(opts...) +func (w *kqueue) AddWith(name string, opts ...addOpt) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } - w.mu.Lock() - w.userWatches[name] = struct{}{} - w.mu.Unlock() _, err := w.addWatch(name, noteAllEvents) - return err + if err != nil { + return err + } + w.watches.addUserWatch(name) + return nil } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) Remove(name string) error { +func (w *kqueue) Remove(name string) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } return w.remove(name, true) } -func (w *Watcher) remove(name string, unwatchFiles bool) error { - name = filepath.Clean(name) - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() +func (w *kqueue) remove(name string, unwatchFiles bool) error { + if w.isClosed() { return nil } - watchfd, ok := w.watches[name] - w.mu.Unlock() + + name = filepath.Clean(name) + info, ok := w.watches.byPath(name) if !ok { return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) } - err := w.register([]int{watchfd}, unix.EV_DELETE, 0) + err := w.register([]int{info.wd}, unix.EV_DELETE, 0) if err != nil { return err } - unix.Close(watchfd) - - w.mu.Lock() - isDir := w.paths[watchfd].isDir - delete(w.watches, name) - delete(w.userWatches, name) - - parentName := filepath.Dir(name) - delete(w.watchesByDir[parentName], watchfd) - - if len(w.watchesByDir[parentName]) == 0 { - delete(w.watchesByDir, parentName) - } + unix.Close(info.wd) - delete(w.paths, watchfd) - delete(w.dirFlags, name) - delete(w.fileExists, name) - w.mu.Unlock() + isDir := w.watches.remove(info.wd, name) // Find all watched paths that are in this directory that are not external. if unwatchFiles && isDir { - var pathsToRemove []string - w.mu.Lock() - for fd := range w.watchesByDir[name] { - path := w.paths[fd] - if _, ok := w.userWatches[path.name]; !ok { - pathsToRemove = append(pathsToRemove, path.name) - } - } - w.mu.Unlock() + pathsToRemove := w.watches.watchesInDir(name) for _, name := range pathsToRemove { // Since these are internal, not much sense in propagating error to // the user, as that will just confuse them with an error about a @@ -391,23 +352,11 @@ func (w *Watcher) remove(name string, unwatchFiles bool) error { return nil } -// WatchList returns all paths explicitly added with [Watcher.Add] (and are not -// yet removed). -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - if w.isClosed { +func (w *kqueue) WatchList() []string { + if w.isClosed() { return nil } - - entries := make([]string, 0, len(w.userWatches)) - for pathname := range w.userWatches { - entries = append(entries, pathname) - } - - return entries + return w.watches.listPaths(true) } // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) @@ -417,34 +366,26 @@ const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | un // described in kevent(2). // // Returns the real path to the file which was added, with symlinks resolved. -func (w *Watcher) addWatch(name string, flags uint32) (string, error) { - var isDir bool - name = filepath.Clean(name) - - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() +func (w *kqueue) addWatch(name string, flags uint32) (string, error) { + if w.isClosed() { return "", ErrClosed } - watchfd, alreadyWatching := w.watches[name] - // We already have a watch, but we can still override flags. - if alreadyWatching { - isDir = w.paths[watchfd].isDir - } - w.mu.Unlock() + name = filepath.Clean(name) + + info, alreadyWatching := w.watches.byPath(name) if !alreadyWatching { fi, err := os.Lstat(name) if err != nil { return "", err } - // Don't watch sockets or named pipes + // Don't watch sockets or named pipes. if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) { return "", nil } - // Follow Symlinks. + // Follow symlinks. if fi.Mode()&os.ModeSymlink == os.ModeSymlink { link, err := os.Readlink(name) if err != nil { @@ -455,18 +396,15 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { return "", nil } - w.mu.Lock() - _, alreadyWatching = w.watches[link] - w.mu.Unlock() - + _, alreadyWatching = w.watches.byPath(link) if alreadyWatching { // Add to watches so we don't get spurious Create events later // on when we diff the directories. - w.watches[name] = 0 - w.fileExists[name] = struct{}{} + w.watches.addLink(name, 0) return link, nil } + info.linkName = name name = link fi, err = os.Lstat(name) if err != nil { @@ -477,7 +415,7 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { // Retry on EINTR; open() can return EINTR in practice on macOS. // See #354, and Go issues 11180 and 39237. for { - watchfd, err = unix.Open(name, openMode, 0) + info.wd, err = unix.Open(name, openMode, 0) if err == nil { break } @@ -488,40 +426,25 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { return "", err } - isDir = fi.IsDir() + info.isDir = fi.IsDir() } - err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) + err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) if err != nil { - unix.Close(watchfd) + unix.Close(info.wd) return "", err } if !alreadyWatching { - w.mu.Lock() - parentName := filepath.Dir(name) - w.watches[name] = watchfd - - watchesByDir, ok := w.watchesByDir[parentName] - if !ok { - watchesByDir = make(map[int]struct{}, 1) - w.watchesByDir[parentName] = watchesByDir - } - watchesByDir[watchfd] = struct{}{} - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} - w.mu.Unlock() + w.watches.add(name, info.linkName, info.wd, info.isDir) } - if isDir { - // Watch the directory if it has not been watched before, or if it was - // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) - w.mu.Lock() - + // Watch the directory if it has not been watched before, or if it was + // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + if info.isDir { watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && - (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) - // Store flags so this watch can be updated later - w.dirFlags[name] = flags - w.mu.Unlock() + (!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE) + w.watches.updateDirFlags(name, flags) if watchDir { if err := w.watchDirectoryFiles(name); err != nil { @@ -534,7 +457,7 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { // readEvents reads from kqueue and converts the received kevents into // Event values that it sends down the Events channel. -func (w *Watcher) readEvents() { +func (w *kqueue) readEvents() { defer func() { close(w.Events) close(w.Errors) @@ -543,50 +466,65 @@ func (w *Watcher) readEvents() { }() eventBuffer := make([]unix.Kevent_t, 10) - for closed := false; !closed; { + for { kevents, err := w.read(eventBuffer) // EINTR is okay, the syscall was interrupted before timeout expired. if err != nil && err != unix.EINTR { if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) { - closed = true + return } - continue } - // Flush the events we received to the Events channel for _, kevent := range kevents { var ( - watchfd = int(kevent.Ident) - mask = uint32(kevent.Fflags) + wd = int(kevent.Ident) + mask = uint32(kevent.Fflags) ) // Shut down the loop when the pipe is closed, but only after all // other events have been processed. - if watchfd == w.closepipe[0] { - closed = true - continue + if wd == w.closepipe[0] { + return } - w.mu.Lock() - path := w.paths[watchfd] - w.mu.Unlock() + path, ok := w.watches.byWd(wd) + if debug { + internal.Debug(path.name, &kevent) + } - event := w.newEvent(path.name, mask) + // On macOS it seems that sometimes an event with Ident=0 is + // delivered, and no other flags/information beyond that, even + // though we never saw such a file descriptor. For example in + // TestWatchSymlink/277 (usually at the end, but sometimes sooner): + // + // fmt.Printf("READ: %2d %#v\n", kevent.Ident, kevent) + // unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // unix.Kevent_t{Ident:0x0, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // + // The first is a normal event, the second with Ident 0. No error + // flag, no data, no ... nothing. + // + // I read a bit through bsd/kern_event.c from the xnu source, but I + // don't really see an obvious location where this is triggered – + // this doesn't seem intentional, but idk... + // + // Technically fd 0 is a valid descriptor, so only skip it if + // there's no path, and if we're on macOS. + if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" { + continue + } + + event := w.newEvent(path.name, path.linkName, mask) if event.Has(Rename) || event.Has(Remove) { w.remove(event.Name, false) - w.mu.Lock() - delete(w.fileExists, event.Name) - w.mu.Unlock() + w.watches.markSeen(event.Name, false) } if path.isDir && event.Has(Write) && !event.Has(Remove) { - w.sendDirectoryChangeEvents(event.Name) - } else { - if !w.sendEvent(event) { - closed = true - continue - } + w.dirChange(event.Name) + } else if !w.sendEvent(event) { + return } if event.Has(Remove) { @@ -594,25 +532,34 @@ func (w *Watcher) readEvents() { // mv f1 f2 will delete f2, then create f2. if path.isDir { fileDir := filepath.Clean(event.Name) - w.mu.Lock() - _, found := w.watches[fileDir] - w.mu.Unlock() + _, found := w.watches.byPath(fileDir) if found { - err := w.sendDirectoryChangeEvents(fileDir) - if err != nil { - if !w.sendError(err) { - closed = true - } + // TODO: this branch is never triggered in any test. + // Added in d6220df (2012). + // isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111 + // + // I don't really get how this can be triggered either. + // And it wasn't triggered in the patch that added it, + // either. + // + // Original also had a comment: + // make sure the directory exists before we watch for + // changes. When we do a recursive watch and perform + // rm -rf, the parent directory might have gone + // missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the + // parent directory. + err := w.dirChange(fileDir) + if !w.sendError(err) { + return } } } else { - filePath := filepath.Clean(event.Name) - if fi, err := os.Lstat(filePath); err == nil { - err := w.sendFileCreatedEventIfNew(filePath, fi) - if err != nil { - if !w.sendError(err) { - closed = true - } + path := filepath.Clean(event.Name) + if fi, err := os.Lstat(path); err == nil { + err := w.sendCreateIfNew(path, fi) + if !w.sendError(err) { + return } } } @@ -622,8 +569,14 @@ func (w *Watcher) readEvents() { } // newEvent returns an platform-independent Event based on kqueue Fflags. -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *kqueue) newEvent(name, linkName string, mask uint32) Event { e := Event{Name: name} + if linkName != "" { + // If the user watched "/path/link" then emit events as "/path/link" + // rather than "/path/target". + e.Name = linkName + } + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { e.Op |= Remove } @@ -645,8 +598,7 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { } // watchDirectoryFiles to mimic inotify when adding a watch on a directory -func (w *Watcher) watchDirectoryFiles(dirPath string) error { - // Get all files +func (w *kqueue) watchDirectoryFiles(dirPath string) error { files, err := os.ReadDir(dirPath) if err != nil { return err @@ -674,9 +626,7 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { } } - w.mu.Lock() - w.fileExists[cleanPath] = struct{}{} - w.mu.Unlock() + w.watches.markSeen(cleanPath, true) } return nil @@ -686,7 +636,7 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { // // This functionality is to have the BSD watcher match the inotify, which sends // a create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dir string) error { +func (w *kqueue) dirChange(dir string) error { files, err := os.ReadDir(dir) if err != nil { // Directory no longer exists: we can ignore this safely. kqueue will @@ -694,61 +644,51 @@ func (w *Watcher) sendDirectoryChangeEvents(dir string) error { if errors.Is(err, os.ErrNotExist) { return nil } - return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) + return fmt.Errorf("fsnotify.dirChange: %w", err) } for _, f := range files { fi, err := f.Info() if err != nil { - return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) + return fmt.Errorf("fsnotify.dirChange: %w", err) } - err = w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi) + err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi) if err != nil { // Don't need to send an error if this file isn't readable. if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) { return nil } - return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) + return fmt.Errorf("fsnotify.dirChange: %w", err) } } return nil } -// sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fi os.FileInfo) (err error) { - w.mu.Lock() - _, doesExist := w.fileExists[filePath] - w.mu.Unlock() - if !doesExist { - if !w.sendEvent(Event{Name: filePath, Op: Create}) { - return +// Send a create event if the file isn't already being tracked, and start +// watching this file. +func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error { + if !w.watches.seenBefore(path) { + if !w.sendEvent(Event{Name: path, Op: Create}) { + return nil } } - // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fi) + // Like watchDirectoryFiles, but without doing another ReadDir. + path, err := w.internalWatch(path, fi) if err != nil { return err } - - w.mu.Lock() - w.fileExists[filePath] = struct{}{} - w.mu.Unlock() - + w.watches.markSeen(path, true) return nil } -func (w *Watcher) internalWatch(name string, fi os.FileInfo) (string, error) { +func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) { if fi.IsDir() { // mimic Linux providing delete events for subdirectories, but preserve // the flags used if currently watching subdirectory - w.mu.Lock() - flags := w.dirFlags[name] - w.mu.Unlock() - - flags |= unix.NOTE_DELETE | unix.NOTE_RENAME - return w.addWatch(name, flags) + info, _ := w.watches.byPath(name) + return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME) } // watch file to mimic Linux inotify @@ -756,7 +696,7 @@ func (w *Watcher) internalWatch(name string, fi os.FileInfo) (string, error) { } // Register events with the queue. -func (w *Watcher) register(fds []int, flags int, fflags uint32) error { +func (w *kqueue) register(fds []int, flags int, fflags uint32) error { changes := make([]unix.Kevent_t, len(fds)) for i, fd := range fds { // SetKevent converts int to the platform-specific types. @@ -773,10 +713,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error { } // read retrieves pending events, or waits until an event occurs. -func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { +func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { n, err := unix.Kevent(w.kq, nil, events, nil) if err != nil { return nil, err } return events[0:n], nil } + +func (w *kqueue) xSupports(op Op) bool { + if runtime.GOOS == "freebsd" { + //return true // Supports everything. + } + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_other.go b/vendor/github.com/fsnotify/fsnotify/backend_other.go index d34a23c0..5eb5dbc6 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_other.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_other.go @@ -1,205 +1,23 @@ //go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) -// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows - -// Note: the documentation on the Watcher type and methods is generated from -// mkdoc.zsh package fsnotify import "errors" -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # Windows notes -// -// Paths can be added as "C:\path\to\dir", but forward slashes -// ("C:/path/to/dir") will also work. -// -// When a watched directory is removed it will always send an event for the -// directory itself, but may not send events for all files in that directory. -// Sometimes it will send events for all times, sometimes it will send no -// events, and often only for some files. -// -// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest -// value that is guaranteed to work with SMB filesystems. If you have many -// events in quick succession this may not be enough, and you will have to use -// [WithBufferSize] to increase the value. -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, and you may - // want to wait until you've stopped receiving them - // (see the dedup example in cmd/fsnotify). - // - // Some systems may send Write event for directories - // when the directory content changes. - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // when a file is truncated. On Windows it's never - // sent. +type other struct { Events chan Event - - // Errors sends any errors. - // - // ErrEventOverflow is used to indicate there are too many events: - // - // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) - // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. - // - kqueue, fen: Not used. Errors chan error } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { +func newBackend(ev chan Event, errs chan error) (backend, error) { return nil, errors.New("fsnotify not supported on the current platform") } - -// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events -// channel. -// -// The main use case for this is situations with a very large number of events -// where the kernel buffer size can't be increased (e.g. due to lack of -// permissions). An unbuffered Watcher will perform better for almost all use -// cases, and whenever possible you will be better off increasing the kernel -// buffers instead of adding a large userspace buffer. -func NewBufferedWatcher(sz uint) (*Watcher, error) { return NewWatcher() } - -// Close removes all watches and closes the Events channel. -func (w *Watcher) Close() error { return nil } - -// WatchList returns all paths explicitly added with [Watcher.Add] (and are not -// yet removed). -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) WatchList() []string { return nil } - -// Add starts monitoring the path for changes. -// -// A path can only be watched once; watching it more than once is a no-op and will -// not return an error. Paths that do not yet exist on the filesystem cannot be -// watched. -// -// A watch will be automatically removed if the watched path is deleted or -// renamed. The exception is the Windows backend, which doesn't remove the -// watcher on renames. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// Returns [ErrClosed] if [Watcher.Close] was called. -// -// See [Watcher.AddWith] for a version that allows adding options. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many programs (especially editors) update files atomically: it -// will write to a temporary file which is then moved to to destination, -// overwriting the original (or some variant thereof). The watcher on the -// original file is now lost, as that no longer exists. -// -// The upshot of this is that a power failure or crash won't leave a -// half-written file. -// -// Watch the parent directory and use Event.Name to filter out files you're not -// interested in. There is an example of this in cmd/fsnotify/file.go. -func (w *Watcher) Add(name string) error { return nil } - -// AddWith is like [Watcher.Add], but allows adding options. When using Add() -// the defaults described below are used. -// -// Possible options are: -// -// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on -// other platforms. The default is 64K (65536 bytes). -func (w *Watcher) AddWith(name string, opts ...addOpt) error { return nil } - -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) Remove(name string) error { return nil } +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + return newBackend(ev, errs) +} +func (w *other) Close() error { return nil } +func (w *other) WatchList() []string { return nil } +func (w *other) Add(name string) error { return nil } +func (w *other) AddWith(name string, opts ...addOpt) error { return nil } +func (w *other) Remove(name string) error { return nil } +func (w *other) xSupports(op Op) bool { return false } diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go index 9bc91e5d..c54a6308 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_windows.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -1,12 +1,8 @@ //go:build windows -// +build windows // Windows backend based on ReadDirectoryChangesW() // // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw -// -// Note: the documentation on the Watcher type and methods is generated from -// mkdoc.zsh package fsnotify @@ -19,123 +15,15 @@ import ( "runtime" "strings" "sync" + "time" "unsafe" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/windows" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # Windows notes -// -// Paths can be added as "C:\path\to\dir", but forward slashes -// ("C:/path/to/dir") will also work. -// -// When a watched directory is removed it will always send an event for the -// directory itself, but may not send events for all files in that directory. -// Sometimes it will send events for all times, sometimes it will send no -// events, and often only for some files. -// -// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest -// value that is guaranteed to work with SMB filesystems. If you have many -// events in quick succession this may not be enough, and you will have to use -// [WithBufferSize] to increase the value. -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, and you may - // want to wait until you've stopped receiving them - // (see the dedup example in cmd/fsnotify). - // - // Some systems may send Write event for directories - // when the directory content changes. - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // when a file is truncated. On Windows it's never - // sent. +type readDirChangesW struct { Events chan Event - - // Errors sends any errors. - // - // ErrEventOverflow is used to indicate there are too many events: - // - // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) - // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. - // - kqueue, fen: Not used. Errors chan error port windows.Handle // Handle to completion port @@ -147,48 +35,40 @@ type Watcher struct { closed bool // Set to true when Close() is first called } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return NewBufferedWatcher(50) +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(50, ev, errs) } -// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events -// channel. -// -// The main use case for this is situations with a very large number of events -// where the kernel buffer size can't be increased (e.g. due to lack of -// permissions). An unbuffered Watcher will perform better for almost all use -// cases, and whenever possible you will be better off increasing the kernel -// buffers instead of adding a large userspace buffer. -func NewBufferedWatcher(sz uint) (*Watcher, error) { +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) if err != nil { return nil, os.NewSyscallError("CreateIoCompletionPort", err) } - w := &Watcher{ + w := &readDirChangesW{ + Events: ev, + Errors: errs, port: port, watches: make(watchMap), input: make(chan *input, 1), - Events: make(chan Event, sz), - Errors: make(chan error), quit: make(chan chan<- error, 1), } go w.readEvents() return w, nil } -func (w *Watcher) isClosed() bool { +func (w *readDirChangesW) isClosed() bool { w.mu.Lock() defer w.mu.Unlock() return w.closed } -func (w *Watcher) sendEvent(name string, mask uint64) bool { +func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool { if mask == 0 { return false } event := w.newEvent(name, uint32(mask)) + event.renamedFrom = renamedFrom select { case ch := <-w.quit: w.quit <- ch @@ -198,17 +78,19 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool { } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { +func (w *readDirChangesW) sendError(err error) bool { + if err == nil { + return true + } select { case w.Errors <- err: return true case <-w.quit: + return false } - return false } -// Close removes all watches and closes the Events channel. -func (w *Watcher) Close() error { +func (w *readDirChangesW) Close() error { if w.isClosed() { return nil } @@ -226,57 +108,21 @@ func (w *Watcher) Close() error { return <-ch } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; watching it more than once is a no-op and will -// not return an error. Paths that do not yet exist on the filesystem cannot be -// watched. -// -// A watch will be automatically removed if the watched path is deleted or -// renamed. The exception is the Windows backend, which doesn't remove the -// watcher on renames. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// Returns [ErrClosed] if [Watcher.Close] was called. -// -// See [Watcher.AddWith] for a version that allows adding options. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many programs (especially editors) update files atomically: it -// will write to a temporary file which is then moved to to destination, -// overwriting the original (or some variant thereof). The watcher on the -// original file is now lost, as that no longer exists. -// -// The upshot of this is that a power failure or crash won't leave a -// half-written file. -// -// Watch the parent directory and use Event.Name to filter out files you're not -// interested in. There is an example of this in cmd/fsnotify/file.go. -func (w *Watcher) Add(name string) error { return w.AddWith(name) } +func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) } -// AddWith is like [Watcher.Add], but allows adding options. When using Add() -// the defaults described below are used. -// -// Possible options are: -// -// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on -// other platforms. The default is 64K (65536 bytes). -func (w *Watcher) AddWith(name string, opts ...addOpt) error { +func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error { if w.isClosed() { return ErrClosed } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } if with.bufsize < 4096 { return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes") } @@ -295,18 +141,14 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error { return <-in.reply } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) Remove(name string) error { +func (w *readDirChangesW) Remove(name string) error { if w.isClosed() { return nil } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } in := &input{ op: opRemoveWatch, @@ -320,11 +162,7 @@ func (w *Watcher) Remove(name string) error { return <-in.reply } -// WatchList returns all paths explicitly added with [Watcher.Add] (and are not -// yet removed). -// -// Returns nil if [Watcher.Close] was called. -func (w *Watcher) WatchList() []string { +func (w *readDirChangesW) WatchList() []string { if w.isClosed() { return nil } @@ -335,7 +173,13 @@ func (w *Watcher) WatchList() []string { entries := make([]string, 0, len(w.watches)) for _, entry := range w.watches { for _, watchEntry := range entry { - entries = append(entries, watchEntry.path) + for name := range watchEntry.names { + entries = append(entries, filepath.Join(watchEntry.path, name)) + } + // the directory itself is being watched + if watchEntry.mask != 0 { + entries = append(entries, watchEntry.path) + } } } @@ -361,7 +205,7 @@ const ( sysFSIGNORED = 0x8000 ) -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *readDirChangesW) newEvent(name string, mask uint32) Event { e := Event{Name: name} if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { e.Op |= Create @@ -417,7 +261,7 @@ type ( watchMap map[uint32]indexMap ) -func (w *Watcher) wakeupReader() error { +func (w *readDirChangesW) wakeupReader() error { err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil) if err != nil { return os.NewSyscallError("PostQueuedCompletionStatus", err) @@ -425,7 +269,7 @@ func (w *Watcher) wakeupReader() error { return nil } -func (w *Watcher) getDir(pathname string) (dir string, err error) { +func (w *readDirChangesW) getDir(pathname string) (dir string, err error) { attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname)) if err != nil { return "", os.NewSyscallError("GetFileAttributes", err) @@ -439,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) { return } -func (w *Watcher) getIno(path string) (ino *inode, err error) { +func (w *readDirChangesW) getIno(path string) (ino *inode, err error) { h, err := windows.CreateFile(windows.StringToUTF16Ptr(path), windows.FILE_LIST_DIRECTORY, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, @@ -482,9 +326,8 @@ func (m watchMap) set(ino *inode, watch *watch) { } // Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error { - //pathname, recurse := recursivePath(pathname) - recurse := false +func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error { + pathname, recurse := recursivePath(pathname) dir, err := w.getDir(pathname) if err != nil { @@ -538,7 +381,7 @@ func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error { } // Must run within the I/O thread. -func (w *Watcher) remWatch(pathname string) error { +func (w *readDirChangesW) remWatch(pathname string) error { pathname, recurse := recursivePath(pathname) dir, err := w.getDir(pathname) @@ -566,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error { return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname) } if pathname == dir { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) watch.mask = 0 } else { name := filepath.Base(pathname) - w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) + w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED) delete(watch.names, name) } @@ -578,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error { } // Must run within the I/O thread. -func (w *Watcher) deleteWatch(watch *watch) { +func (w *readDirChangesW) deleteWatch(watch *watch) { for name, mask := range watch.names { if mask&provisional == 0 { - w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) + w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED) } delete(watch.names, name) } if watch.mask != 0 { if watch.mask&provisional == 0 { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) } watch.mask = 0 } } // Must run within the I/O thread. -func (w *Watcher) startRead(watch *watch) error { +func (w *readDirChangesW) startRead(watch *watch) error { err := windows.CancelIo(watch.ino.handle) if err != nil { w.sendError(os.NewSyscallError("CancelIo", err)) @@ -624,7 +467,7 @@ func (w *Watcher) startRead(watch *watch) error { err := os.NewSyscallError("ReadDirectoryChanges", rdErr) if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) err = nil } w.deleteWatch(watch) @@ -637,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error { // readEvents reads from the I/O completion port, converts the // received events into Event objects and sends them via the Events channel. // Entry point to the I/O thread. -func (w *Watcher) readEvents() { +func (w *readDirChangesW) readEvents() { var ( n uint32 key uintptr @@ -700,7 +543,7 @@ func (w *Watcher) readEvents() { } case windows.ERROR_ACCESS_DENIED: // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) w.deleteWatch(watch) w.startRead(watch) continue @@ -733,6 +576,10 @@ func (w *Watcher) readEvents() { name := windows.UTF16ToString(buf) fullname := filepath.Join(watch.path, name) + if debug { + internal.Debug(fullname, raw.Action) + } + var mask uint64 switch raw.Action { case windows.FILE_ACTION_REMOVED: @@ -761,21 +608,22 @@ func (w *Watcher) readEvents() { } } - sendNameEvent := func() { - w.sendEvent(fullname, watch.names[name]&mask) - } if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME { - sendNameEvent() + w.sendEvent(fullname, "", watch.names[name]&mask) } if raw.Action == windows.FILE_ACTION_REMOVED { - w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) + w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED) delete(watch.names, name) } - w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action)) + if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { + w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action)) + } else { + w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action)) + } + if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { - fullname = filepath.Join(watch.path, watch.rename) - sendNameEvent() + w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask) } // Move to the next event in the buffer @@ -787,8 +635,7 @@ func (w *Watcher) readEvents() { // Error! if offset >= n { //lint:ignore ST1005 Windows should be capitalized - w.sendError(errors.New( - "Windows system assumed buffer larger than it is, events have likely been missed")) + w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed")) break } } @@ -799,7 +646,7 @@ func (w *Watcher) readEvents() { } } -func (w *Watcher) toWindowsFlags(mask uint64) uint32 { +func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 { var m uint32 if mask&sysFSMODIFY != 0 { m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE @@ -810,7 +657,7 @@ func (w *Watcher) toWindowsFlags(mask uint64) uint32 { return m } -func (w *Watcher) toFSnotifyFlags(action uint32) uint64 { +func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 { switch action { case windows.FILE_ACTION_ADDED: return sysFSCREATE @@ -825,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 { } return 0 } + +func (w *readDirChangesW) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 24c99cc4..0760efe9 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -3,19 +3,146 @@ // // Currently supported systems: // -// Linux 2.6.32+ via inotify -// BSD, macOS via kqueue -// Windows via ReadDirectoryChangesW -// illumos via FEN +// - Linux via inotify +// - BSD, macOS via kqueue +// - Windows via ReadDirectoryChangesW +// - illumos via FEN +// +// # FSNOTIFY_DEBUG +// +// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to +// stderr. This can be useful to track down some problems, especially in cases +// where fsnotify is used as an indirect dependency. +// +// Every event will be printed as soon as there's something useful to print, +// with as little processing from fsnotify. +// +// Example output: +// +// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1" package fsnotify import ( "errors" "fmt" + "os" "path/filepath" "strings" ) +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # Windows notes +// +// Paths can be added as "C:\\path\\to\\dir", but forward slashes +// ("C:/path/to/dir") will also work. +// +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all files, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. +type Watcher struct { + b backend + + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // when a file is truncated. On Windows it's never + // sent. + Events chan Event + + // Errors sends any errors. + Errors chan error +} + // Event represents a file system notification. type Event struct { // Path to the file or directory. @@ -30,6 +157,16 @@ type Event struct { // This is a bitmask and some systems may send multiple operations at once. // Use the Event.Has() method instead of comparing with ==. Op Op + + // Create events will have this set to the old path if it's a rename. This + // only works when both the source and destination are watched. It's not + // reliable when watching individual files, only directories. + // + // For example "mv /tmp/file /tmp/rename" will emit: + // + // Event{Op: Rename, Name: "/tmp/file"} + // Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"} + renamedFrom string } // Op describes a set of file operations. @@ -50,7 +187,7 @@ const ( // example "remove to trash" is often a rename). Remove - // The path was renamed to something else; any watched on it will be + // The path was renamed to something else; any watches on it will be // removed. Rename @@ -60,15 +197,155 @@ const ( // get triggered very frequently by some software. For example, Spotlight // indexing on macOS, anti-virus software, backup software, etc. Chmod + + // File descriptor was opened. + // + // Only works on Linux and FreeBSD. + xUnportableOpen + + // File was read from. + // + // Only works on Linux and FreeBSD. + xUnportableRead + + // File opened for writing was closed. + // + // Only works on Linux and FreeBSD. + // + // The advantage of using this over Write is that it's more reliable than + // waiting for Write events to stop. It's also faster (if you're not + // listening to Write events): copying a file of a few GB can easily + // generate tens of thousands of Write events in a short span of time. + xUnportableCloseWrite + + // File opened for reading was closed. + // + // Only works on Linux and FreeBSD. + xUnportableCloseRead ) -// Common errors that can be reported. var ( + // ErrNonExistentWatch is used when Remove() is called on a path that's not + // added. ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch") - ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") - ErrClosed = errors.New("fsnotify: watcher already closed") + + // ErrClosed is used when trying to operate on a closed Watcher. + ErrClosed = errors.New("fsnotify: watcher already closed") + + // ErrEventOverflow is reported from the Errors channel when there are too + // many events: + // + // - inotify: inotify returns IN_Q_OVERFLOW – because there are too + // many queued events (the fs.inotify.max_queued_events + // sysctl can be used to increase this). + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. + ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") + + // ErrUnsupported is returned by AddWith() when WithOps() specified an + // Unportable event that's not supported on this platform. + xErrUnsupported = errors.New("fsnotify: not supported with this backend") ) +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBackend(ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBufferedBackend(sz, ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. +// +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(path string) error { return w.b.Add(path) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) } + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) Remove(path string) error { return w.b.Remove(path) } + +// Close removes all watches and closes the Events channel. +func (w *Watcher) Close() error { return w.b.Close() } + +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { return w.b.WatchList() } + +// Supports reports if all the listed operations are supported by this platform. +// +// Create, Write, Remove, Rename, and Chmod are always supported. It can only +// return false for an Op starting with Unportable. +func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) } + func (o Op) String() string { var b strings.Builder if o.Has(Create) { @@ -80,6 +357,18 @@ func (o Op) String() string { if o.Has(Write) { b.WriteString("|WRITE") } + if o.Has(xUnportableOpen) { + b.WriteString("|OPEN") + } + if o.Has(xUnportableRead) { + b.WriteString("|READ") + } + if o.Has(xUnportableCloseWrite) { + b.WriteString("|CLOSE_WRITE") + } + if o.Has(xUnportableCloseRead) { + b.WriteString("|CLOSE_READ") + } if o.Has(Rename) { b.WriteString("|RENAME") } @@ -100,24 +389,48 @@ func (e Event) Has(op Op) bool { return e.Op.Has(op) } // String returns a string representation of the event with their path. func (e Event) String() string { + if e.renamedFrom != "" { + return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom) + } return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } type ( + backend interface { + Add(string) error + AddWith(string, ...addOpt) error + Remove(string) error + WatchList() []string + Close() error + xSupports(Op) bool + } addOpt func(opt *withOpts) withOpts struct { - bufsize int + bufsize int + op Op + noFollow bool + sendCreate bool } ) +var debug = func() bool { + // Check for exactly "1" (rather than mere existence) so we can add + // options/flags in the future. I don't know if we ever want that, but it's + // nice to leave the option open. + return os.Getenv("FSNOTIFY_DEBUG") == "1" +}() + var defaultOpts = withOpts{ bufsize: 65536, // 64K + op: Create | Write | Remove | Rename | Chmod, } func getOptions(opts ...addOpt) withOpts { with := defaultOpts for _, o := range opts { - o(&with) + if o != nil { + o(&with) + } } return with } @@ -136,9 +449,44 @@ func WithBufferSize(bytes int) addOpt { return func(opt *withOpts) { opt.bufsize = bytes } } +// WithOps sets which operations to listen for. The default is [Create], +// [Write], [Remove], [Rename], and [Chmod]. +// +// Excluding operations you're not interested in can save quite a bit of CPU +// time; in some use cases there may be hundreds of thousands of useless Write +// or Chmod operations per second. +// +// This can also be used to add unportable operations not supported by all +// platforms; unportable operations all start with "Unportable": +// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and +// [UnportableCloseRead]. +// +// AddWith returns an error when using an unportable operation that's not +// supported. Use [Watcher.Support] to check for support. +func withOps(op Op) addOpt { + return func(opt *withOpts) { opt.op = op } +} + +// WithNoFollow disables following symlinks, so the symlinks themselves are +// watched. +func withNoFollow() addOpt { + return func(opt *withOpts) { opt.noFollow = true } +} + +// "Internal" option for recursive watches on inotify. +func withCreate() addOpt { + return func(opt *withOpts) { opt.sendCreate = true } +} + +var enableRecurse = false + // Check if this path is recursive (ends with "/..." or "\..."), and return the // path with the /... stripped. func recursivePath(path string) (string, bool) { + path = filepath.Clean(path) + if !enableRecurse { // Only enabled in tests for now. + return path, false + } if filepath.Base(path) == "..." { return filepath.Dir(path), true } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go new file mode 100644 index 00000000..b0eab100 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go @@ -0,0 +1,39 @@ +//go:build darwin + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ +func SetRlimit() { + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = l.Cur + + if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } + + if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go new file mode 100644 index 00000000..928319fb --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go @@ -0,0 +1,57 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_BACKGROUND", unix.NOTE_BACKGROUND}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CRITICAL", unix.NOTE_CRITICAL}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS}, + {"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR}, + {"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL}, + {"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL}, + {"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK}, + {"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY}, + {"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_FUNLOCK", unix.NOTE_FUNLOCK}, + {"NOTE_LEEWAY", unix.NOTE_LEEWAY}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MACHTIME", unix.NOTE_MACHTIME}, + {"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME}, + {"NOTE_NONE", unix.NOTE_NONE}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OOB", unix.NOTE_OOB}, + //{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!) + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_REAP", unix.NOTE_REAP}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_SIGNAL", unix.NOTE_SIGNAL}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_VM_ERROR", unix.NOTE_VM_ERROR}, + {"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE}, + {"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE}, + {"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go new file mode 100644 index 00000000..3186b0c3 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go @@ -0,0 +1,33 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_OOB", unix.NOTE_OOB}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go new file mode 100644 index 00000000..f69fdb93 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go @@ -0,0 +1,42 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSTIME", unix.NOTE_ABSTIME}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CLOSE", unix.NOTE_CLOSE}, + {"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FILE_POLL", unix.NOTE_FILE_POLL}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MSECONDS", unix.NOTE_MSECONDS}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OPEN", unix.NOTE_OPEN}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_READ", unix.NOTE_READ}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go new file mode 100644 index 00000000..607e683b --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go @@ -0,0 +1,32 @@ +//go:build freebsd || openbsd || netbsd || dragonfly || darwin + +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, kevent *unix.Kevent_t) { + mask := uint32(kevent.Fflags) + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-60s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go new file mode 100644 index 00000000..35c734be --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go @@ -0,0 +1,56 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask, cookie uint32) { + names := []struct { + n string + m uint32 + }{ + {"IN_ACCESS", unix.IN_ACCESS}, + {"IN_ATTRIB", unix.IN_ATTRIB}, + {"IN_CLOSE", unix.IN_CLOSE}, + {"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE}, + {"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE}, + {"IN_CREATE", unix.IN_CREATE}, + {"IN_DELETE", unix.IN_DELETE}, + {"IN_DELETE_SELF", unix.IN_DELETE_SELF}, + {"IN_IGNORED", unix.IN_IGNORED}, + {"IN_ISDIR", unix.IN_ISDIR}, + {"IN_MODIFY", unix.IN_MODIFY}, + {"IN_MOVE", unix.IN_MOVE}, + {"IN_MOVED_FROM", unix.IN_MOVED_FROM}, + {"IN_MOVED_TO", unix.IN_MOVED_TO}, + {"IN_MOVE_SELF", unix.IN_MOVE_SELF}, + {"IN_OPEN", unix.IN_OPEN}, + {"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW}, + {"IN_UNMOUNT", unix.IN_UNMOUNT}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + var c string + if cookie > 0 { + c = fmt.Sprintf("(cookie: %d) ", cookie) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-30s → %s%q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go new file mode 100644 index 00000000..e5b3b6f6 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go @@ -0,0 +1,25 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go new file mode 100644 index 00000000..1dd455bc --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go @@ -0,0 +1,28 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + // {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386? + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EOF", unix.NOTE_EOF}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRUNCATE", unix.NOTE_TRUNCATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go new file mode 100644 index 00000000..f1b2e73b --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go @@ -0,0 +1,45 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask int32) { + names := []struct { + n string + m int32 + }{ + {"FILE_ACCESS", unix.FILE_ACCESS}, + {"FILE_MODIFIED", unix.FILE_MODIFIED}, + {"FILE_ATTRIB", unix.FILE_ATTRIB}, + {"FILE_TRUNC", unix.FILE_TRUNC}, + {"FILE_NOFOLLOW", unix.FILE_NOFOLLOW}, + {"FILE_DELETE", unix.FILE_DELETE}, + {"FILE_RENAME_TO", unix.FILE_RENAME_TO}, + {"FILE_RENAME_FROM", unix.FILE_RENAME_FROM}, + {"UNMOUNTED", unix.UNMOUNTED}, + {"MOUNTEDOVER", unix.MOUNTEDOVER}, + {"FILE_EXCEPTION", unix.FILE_EXCEPTION}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-30s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go new file mode 100644 index 00000000..52bf4ce5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go @@ -0,0 +1,40 @@ +package internal + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/sys/windows" +) + +func Debug(name string, mask uint32) { + names := []struct { + n string + m uint32 + }{ + {"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED}, + {"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED}, + {"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED}, + {"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME}, + {"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-65s → %q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name)) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go new file mode 100644 index 00000000..547df1df --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go @@ -0,0 +1,31 @@ +//go:build freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/vendor/github.com/fsnotify/fsnotify/internal/internal.go new file mode 100644 index 00000000..7daa45e1 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/internal.go @@ -0,0 +1,2 @@ +// Package internal contains some helpers. +package internal diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/vendor/github.com/fsnotify/fsnotify/internal/unix.go new file mode 100644 index 00000000..30976ce9 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/unix.go @@ -0,0 +1,31 @@ +//go:build !windows && !darwin && !freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go new file mode 100644 index 00000000..37dfeddc --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go @@ -0,0 +1,7 @@ +//go:build !windows + +package internal + +func HasPrivilegesForSymlink() bool { + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/vendor/github.com/fsnotify/fsnotify/internal/windows.go new file mode 100644 index 00000000..a72c6495 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/windows.go @@ -0,0 +1,41 @@ +//go:build windows + +package internal + +import ( + "errors" + + "golang.org/x/sys/windows" +) + +// Just a dummy. +var ( + SyscallEACCES = errors.New("dummy") + UnixEACCES = errors.New("dummy") +) + +func SetRlimit() {} +func Maxfiles() uint64 { return 1<<64 - 1 } +func Mkfifo(path string, mode uint32) error { return errors.New("no FIFOs on Windows") } +func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") } + +func HasPrivilegesForSymlink() bool { + var sid *windows.SID + err := windows.AllocateAndInitializeSid( + &windows.SECURITY_NT_AUTHORITY, + 2, + windows.SECURITY_BUILTIN_DOMAIN_RID, + windows.DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid) + if err != nil { + return false + } + defer windows.FreeSid(sid) + token := windows.Token(0) + member, err := token.IsMember(sid) + if err != nil { + return false + } + return member || token.IsElevated() +} diff --git a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh deleted file mode 100644 index 99012ae6..00000000 --- a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env zsh -[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 -setopt err_exit no_unset pipefail extended_glob - -# Simple script to update the godoc comments on all watchers so you don't need -# to update the same comment 5 times. - -watcher=$(</tmp/x - print -r -- $cmt >>/tmp/x - tail -n+$(( end + 1 )) $file >>/tmp/x - mv /tmp/x $file - done -} - -set-cmt '^type Watcher struct ' $watcher -set-cmt '^func NewWatcher(' $new -set-cmt '^func NewBufferedWatcher(' $newbuffered -set-cmt '^func (w \*Watcher) Add(' $add -set-cmt '^func (w \*Watcher) AddWith(' $addwith -set-cmt '^func (w \*Watcher) Remove(' $remove -set-cmt '^func (w \*Watcher) Close(' $close -set-cmt '^func (w \*Watcher) WatchList(' $watchlist -set-cmt '^[[:space:]]*Events *chan Event$' $events -set-cmt '^[[:space:]]*Errors *chan error$' $errors diff --git a/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/vendor/github.com/fsnotify/fsnotify/system_bsd.go index 4322b0b8..f65e8fe3 100644 --- a/vendor/github.com/fsnotify/fsnotify/system_bsd.go +++ b/vendor/github.com/fsnotify/fsnotify/system_bsd.go @@ -1,5 +1,4 @@ //go:build freebsd || openbsd || netbsd || dragonfly -// +build freebsd openbsd netbsd dragonfly package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/vendor/github.com/fsnotify/fsnotify/system_darwin.go index 5da5ffa7..a29fc7aa 100644 --- a/vendor/github.com/fsnotify/fsnotify/system_darwin.go +++ b/vendor/github.com/fsnotify/fsnotify/system_darwin.go @@ -1,5 +1,4 @@ //go:build darwin -// +build darwin package fsnotify diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go index 24d82f07..1f3c69d4 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/netip" + "net/url" "reflect" "strconv" "strings" @@ -36,6 +37,30 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { return nil } +// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into a closure to be used directly +// if the type fails to convert we return a closure always erroring to keep the previous behaviour +func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from.Type(), to.Type(), from.Interface()) + } + case DecodeHookFuncKind: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from.Kind(), to.Kind(), from.Interface()) + } + case DecodeHookFuncValue: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from, to) + } + default: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return nil, errors.New("invalid decode hook signature") + } + } +} + // DecodeHookExec executes the given decode hook. This should be used // since it'll naturally degrade to the older backwards compatible DecodeHookFunc // that took reflect.Kind instead of reflect.Type. @@ -61,13 +86,17 @@ func DecodeHookExec( // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs)) + for _, f := range fs { + cached = append(cached, cachedDecodeHook(f)) + } return func(f reflect.Value, t reflect.Value) (interface{}, error) { var err error data := f.Interface() newFrom := f - for _, f1 := range fs { - data, err = DecodeHookExec(f1, newFrom, t) + for _, c := range cached { + data, err = c(newFrom, t) if err != nil { return nil, err } @@ -81,13 +110,17 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { + cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff)) + for _, f := range ff { + cached = append(cached, cachedDecodeHook(f)) + } return func(a, b reflect.Value) (interface{}, error) { var allErrs string var out interface{} var err error - for _, f := range ff { - out, err = DecodeHookExec(f, a, b) + for _, c := range cached { + out, err = c(a, b) if err != nil { allErrs += err.Error() + "\n" continue @@ -144,6 +177,26 @@ func StringToTimeDurationHookFunc() DecodeHookFunc { } } +// StringToURLHookFunc returns a DecodeHookFunc that converts +// strings to *url.URL. +func StringToURLHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(&url.URL{}) { + return data, nil + } + + // Convert it by parsing + return url.Parse(data.(string)) + } +} + // StringToIPHookFunc returns a DecodeHookFunc that converts // strings to net.IP func StringToIPHookFunc() DecodeHookFunc { diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index 4b54fae0..e77e63ba 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -266,6 +266,10 @@ type DecoderConfig struct { // defaults to "mapstructure" TagName string + // The option of the value in the tag that indicates a field should + // be squashed. This defaults to "squash". + SquashTagOption string + // IgnoreUntaggedFields ignores all struct fields without explicit // TagName, comparable to `mapstructure:"-"` as default behaviour. IgnoreUntaggedFields bool @@ -274,6 +278,10 @@ type DecoderConfig struct { // field name or tag. Defaults to `strings.EqualFold`. This can be used // to implement case-sensitive tag values, support snake casing, etc. MatchName func(mapKey, fieldName string) bool + + // DecodeNil, if set to true, will cause the DecodeHook (if present) to run + // even if the input is nil. This can be used to provide default values. + DecodeNil bool } // A Decoder takes a raw interface value and turns it into structured @@ -283,7 +291,8 @@ type DecoderConfig struct { // structure. The top-level Decode method is just a convenience that sets // up the most basic Decoder. type Decoder struct { - config *DecoderConfig + config *DecoderConfig + cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error) } // Metadata contains information about decoding a structure that @@ -401,6 +410,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { config.TagName = "mapstructure" } + if config.SquashTagOption == "" { + config.SquashTagOption = "squash" + } + if config.MatchName == nil { config.MatchName = strings.EqualFold } @@ -408,6 +421,9 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { result := &Decoder{ config: config, } + if config.DecodeHook != nil { + result.cachedDecodeHook = cachedDecodeHook(config.DecodeHook) + } return result, nil } @@ -426,19 +442,26 @@ func (d *Decoder) Decode(input interface{}) error { return err } +// isNil returns true if the input is nil or a typed nil pointer. +func isNil(input interface{}) bool { + if input == nil { + return true + } + val := reflect.ValueOf(input) + return val.Kind() == reflect.Ptr && val.IsNil() +} + // Decodes an unknown data type into a specific reflection value. func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { - var inputVal reflect.Value - if input != nil { - inputVal = reflect.ValueOf(input) - - // We need to check here if input is a typed nil. Typed nils won't - // match the "input == nil" below so we check that here. - if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { - input = nil - } + var ( + inputVal = reflect.ValueOf(input) + outputKind = getKind(outVal) + decodeNil = d.config.DecodeNil && d.cachedDecodeHook != nil + ) + if isNil(input) { + // Typed nils won't match the "input == nil" below, so reset input. + input = nil } - if input == nil { // If the data is nil, then we don't set anything, unless ZeroFields is set // to true. @@ -449,30 +472,46 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) } } - return nil + if !decodeNil { + return nil + } } - if !inputVal.IsValid() { - // If the input value is invalid, then we just set the value - // to be the zero value. - outVal.Set(reflect.Zero(outVal.Type())) - if d.config.Metadata != nil && name != "" { - d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + if !decodeNil { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + // Hooks need a valid inputVal, so reset it to zero value of outVal type. + switch outputKind { + case reflect.Struct, reflect.Map: + var mapVal map[string]interface{} + inputVal = reflect.ValueOf(mapVal) // create nil map pointer + case reflect.Slice, reflect.Array: + var sliceVal []interface{} + inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer + default: + inputVal = reflect.Zero(outVal.Type()) } - return nil } - if d.config.DecodeHook != nil { + if d.cachedDecodeHook != nil { // We have a DecodeHook, so let's pre-process the input. var err error - input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) + input, err = d.cachedDecodeHook(inputVal, outVal) if err != nil { return fmt.Errorf("error decoding '%s': %w", name, err) } } + if isNil(input) { + return nil + } var err error - outputKind := getKind(outVal) addMetaKey := true switch outputKind { case reflect.Bool: @@ -753,8 +792,8 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } default: return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + "'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'", + name, val, dataVal, data) } return nil @@ -973,7 +1012,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re } // If "squash" is specified in the tag, we squash the field down. - squash = squash || strings.Index(tagValue[index+1:], "squash") != -1 + squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption) if squash { // When squashing, the embedded type can be a pointer to a struct. if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { @@ -1351,7 +1390,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // We always parse the tags cause we're looking for other tags too tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") for _, tag := range tagParts[1:] { - if tag == "squash" { + if tag == d.config.SquashTagOption { squash = true break } @@ -1363,10 +1402,15 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } if squash { - if fieldVal.Kind() != reflect.Struct { - errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) - } else { + switch fieldVal.Kind() { + case reflect.Struct: structs = append(structs, fieldVal) + case reflect.Interface: + if !fieldVal.IsNil() { + structs = append(structs, fieldVal.Elem().Elem()) + } + default: + errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) } continue } diff --git a/vendor/github.com/hashicorp/hcl/.gitignore b/vendor/github.com/hashicorp/hcl/.gitignore deleted file mode 100644 index 15586a2b..00000000 --- a/vendor/github.com/hashicorp/hcl/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -y.output - -# ignore intellij files -.idea -*.iml -*.ipr -*.iws - -*.test diff --git a/vendor/github.com/hashicorp/hcl/.travis.yml b/vendor/github.com/hashicorp/hcl/.travis.yml deleted file mode 100644 index cb63a321..00000000 --- a/vendor/github.com/hashicorp/hcl/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -sudo: false - -language: go - -go: - - 1.x - - tip - -branches: - only: - - master - -script: make test diff --git a/vendor/github.com/hashicorp/hcl/LICENSE b/vendor/github.com/hashicorp/hcl/LICENSE deleted file mode 100644 index c33dcc7c..00000000 --- a/vendor/github.com/hashicorp/hcl/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/vendor/github.com/hashicorp/hcl/Makefile b/vendor/github.com/hashicorp/hcl/Makefile deleted file mode 100644 index 84fd743f..00000000 --- a/vendor/github.com/hashicorp/hcl/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -TEST?=./... - -default: test - -fmt: generate - go fmt ./... - -test: generate - go get -t ./... - go test $(TEST) $(TESTARGS) - -generate: - go generate ./... - -updatedeps: - go get -u golang.org/x/tools/cmd/stringer - -.PHONY: default generate test updatedeps diff --git a/vendor/github.com/hashicorp/hcl/README.md b/vendor/github.com/hashicorp/hcl/README.md deleted file mode 100644 index c8223326..00000000 --- a/vendor/github.com/hashicorp/hcl/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# HCL - -[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl) - -HCL (HashiCorp Configuration Language) is a configuration language built -by HashiCorp. The goal of HCL is to build a structured configuration language -that is both human and machine friendly for use with command-line tools, but -specifically targeted towards DevOps tools, servers, etc. - -HCL is also fully JSON compatible. That is, JSON can be used as completely -valid input to a system expecting HCL. This helps makes systems -interoperable with other systems. - -HCL is heavily inspired by -[libucl](https://github.com/vstakhov/libucl), -nginx configuration, and others similar. - -## Why? - -A common question when viewing HCL is to ask the question: why not -JSON, YAML, etc.? - -Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com) -used a variety of configuration languages from full programming languages -such as Ruby to complete data structure languages such as JSON. What we -learned is that some people wanted human-friendly configuration languages -and some people wanted machine-friendly languages. - -JSON fits a nice balance in this, but is fairly verbose and most -importantly doesn't support comments. With YAML, we found that beginners -had a really hard time determining what the actual structure was, and -ended up guessing more often than not whether to use a hyphen, colon, etc. -in order to represent some configuration key. - -Full programming languages such as Ruby enable complex behavior -a configuration language shouldn't usually allow, and also forces -people to learn some set of Ruby. - -Because of this, we decided to create our own configuration language -that is JSON-compatible. Our configuration language (HCL) is designed -to be written and modified by humans. The API for HCL allows JSON -as an input so that it is also machine-friendly (machines can generate -JSON instead of trying to generate HCL). - -Our goal with HCL is not to alienate other configuration languages. -It is instead to provide HCL as a specialized language for our tools, -and JSON as the interoperability layer. - -## Syntax - -For a complete grammar, please see the parser itself. A high-level overview -of the syntax and grammar is listed here. - - * Single line comments start with `#` or `//` - - * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments - are not allowed. A multi-line comment (also known as a block comment) - terminates at the first `*/` found. - - * Values are assigned with the syntax `key = value` (whitespace doesn't - matter). The value can be any primitive: a string, number, boolean, - object, or list. - - * Strings are double-quoted and can contain any UTF-8 characters. - Example: `"Hello, World"` - - * Multi-line strings start with `<- - echo %Path% - - go version - - go env - - go get -t ./... - -build_script: -- cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go deleted file mode 100644 index bed9ebbe..00000000 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ /dev/null @@ -1,729 +0,0 @@ -package hcl - -import ( - "errors" - "fmt" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" - "github.com/hashicorp/hcl/hcl/token" -) - -// This is the tag to use with structures to have settings for HCL -const tagName = "hcl" - -var ( - // nodeType holds a reference to the type of ast.Node - nodeType reflect.Type = findNodeType() -) - -// Unmarshal accepts a byte slice as input and writes the -// data to the value pointed to by v. -func Unmarshal(bs []byte, v interface{}) error { - root, err := parse(bs) - if err != nil { - return err - } - - return DecodeObject(v, root) -} - -// Decode reads the given input and decodes it into the structure -// given by `out`. -func Decode(out interface{}, in string) error { - obj, err := Parse(in) - if err != nil { - return err - } - - return DecodeObject(out, obj) -} - -// DecodeObject is a lower-level version of Decode. It decodes a -// raw Object into the given output. -func DecodeObject(out interface{}, n ast.Node) error { - val := reflect.ValueOf(out) - if val.Kind() != reflect.Ptr { - return errors.New("result must be a pointer") - } - - // If we have the file, we really decode the root node - if f, ok := n.(*ast.File); ok { - n = f.Node - } - - var d decoder - return d.decode("root", n, val.Elem()) -} - -type decoder struct { - stack []reflect.Kind -} - -func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error { - k := result - - // If we have an interface with a valid value, we use that - // for the check. - if result.Kind() == reflect.Interface { - elem := result.Elem() - if elem.IsValid() { - k = elem - } - } - - // Push current onto stack unless it is an interface. - if k.Kind() != reflect.Interface { - d.stack = append(d.stack, k.Kind()) - - // Schedule a pop - defer func() { - d.stack = d.stack[:len(d.stack)-1] - }() - } - - switch k.Kind() { - case reflect.Bool: - return d.decodeBool(name, node, result) - case reflect.Float32, reflect.Float64: - return d.decodeFloat(name, node, result) - case reflect.Int, reflect.Int32, reflect.Int64: - return d.decodeInt(name, node, result) - case reflect.Interface: - // When we see an interface, we make our own thing - return d.decodeInterface(name, node, result) - case reflect.Map: - return d.decodeMap(name, node, result) - case reflect.Ptr: - return d.decodePtr(name, node, result) - case reflect.Slice: - return d.decodeSlice(name, node, result) - case reflect.String: - return d.decodeString(name, node, result) - case reflect.Struct: - return d.decodeStruct(name, node, result) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()), - } - } -} - -func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.BOOL { - v, err := strconv.ParseBool(n.Token.Text) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v)) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { - v, err := strconv.ParseFloat(n.Token.Text, 64) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - v, err := strconv.ParseInt(n.Token.Text, 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - case token.STRING: - v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error { - // When we see an ast.Node, we retain the value to enable deferred decoding. - // Very useful in situations where we want to preserve ast.Node information - // like Pos - if result.Type() == nodeType && result.CanSet() { - result.Set(reflect.ValueOf(node)) - return nil - } - - var set reflect.Value - redecode := true - - // For testing types, ObjectType should just be treated as a list. We - // set this to a temporary var because we want to pass in the real node. - testNode := node - if ot, ok := node.(*ast.ObjectType); ok { - testNode = ot.List - } - - switch n := testNode.(type) { - case *ast.ObjectList: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items)) - set = result - } - case *ast.ObjectType: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 1) - set = result - } - case *ast.ListType: - var temp []interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 0) - set = result - case *ast.LiteralType: - switch n.Token.Type { - case token.BOOL: - var result bool - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.FLOAT: - var result float64 - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.NUMBER: - var result int - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.STRING, token.HEREDOC: - set = reflect.Indirect(reflect.New(reflect.TypeOf(""))) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node), - } - } - default: - return fmt.Errorf( - "%s: cannot decode into interface: %T", - name, node) - } - - // Set the result to what its supposed to be, then reset - // result so we don't reflect into this method anymore. - result.Set(set) - - if redecode { - // Revisit the node so that we can use the newly instantiated - // thing and populate it. - if err := d.decode(name, node, result); err != nil { - return err - } - } - - return nil -} - -func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error { - if item, ok := node.(*ast.ObjectItem); ok { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - n, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for map (%T)", name, node), - } - } - - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - - resultType := result.Type() - resultElemType := resultType.Elem() - resultKeyType := resultType.Key() - if resultKeyType.Kind() != reflect.String { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Make a map if it is nil - resultMap := result - if result.IsNil() { - resultMap = reflect.MakeMap( - reflect.MapOf(resultKeyType, resultElemType)) - } - - // Go through each element and decode it. - done := make(map[string]struct{}) - for _, item := range n.Items { - if item.Val == nil { - continue - } - - // github.com/hashicorp/terraform/issue/5740 - if len(item.Keys) == 0 { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Get the key we're dealing with, which is the first item - keyStr := item.Keys[0].Token.Value().(string) - - // If we've already processed this key, then ignore it - if _, ok := done[keyStr]; ok { - continue - } - - // Determine the value. If we have more than one key, then we - // get the objectlist of only these keys. - itemVal := item.Val - if len(item.Keys) > 1 { - itemVal = n.Filter(keyStr) - done[keyStr] = struct{}{} - } - - // Make the field name - fieldName := fmt.Sprintf("%s.%s", name, keyStr) - - // Get the key/value as reflection values - key := reflect.ValueOf(keyStr) - val := reflect.Indirect(reflect.New(resultElemType)) - - // If we have a pre-existing value in the map, use that - oldVal := resultMap.MapIndex(key) - if oldVal.IsValid() { - val.Set(oldVal) - } - - // Decode! - if err := d.decode(fieldName, itemVal, val); err != nil { - return err - } - - // Set the value on the map - resultMap.SetMapIndex(key, val) - } - - // Set the final map if we can - set.Set(resultMap) - return nil -} - -func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error { - // Create an element of the concrete (non pointer) type and decode - // into that. Then set the value of the pointer to this type. - resultType := result.Type() - resultElemType := resultType.Elem() - val := reflect.New(resultElemType) - if err := d.decode(name, node, reflect.Indirect(val)); err != nil { - return err - } - - result.Set(val) - return nil -} - -func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error { - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - // Create the slice if it isn't nil - resultType := result.Type() - resultElemType := resultType.Elem() - if result.IsNil() { - resultSliceType := reflect.SliceOf(resultElemType) - result = reflect.MakeSlice( - resultSliceType, 0, 0) - } - - // Figure out the items we'll be copying into the slice - var items []ast.Node - switch n := node.(type) { - case *ast.ObjectList: - items = make([]ast.Node, len(n.Items)) - for i, item := range n.Items { - items[i] = item - } - case *ast.ObjectType: - items = []ast.Node{n} - case *ast.ListType: - items = n.List - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("unknown slice type: %T", node), - } - } - - for i, item := range items { - fieldName := fmt.Sprintf("%s[%d]", name, i) - - // Decode - val := reflect.Indirect(reflect.New(resultElemType)) - - // if item is an object that was decoded from ambiguous JSON and - // flattened, make sure it's expanded if it needs to decode into a - // defined structure. - item := expandObject(item, val) - - if err := d.decode(fieldName, item, val); err != nil { - return err - } - - // Append it onto the slice - result = reflect.Append(result, val) - } - - set.Set(result) - return nil -} - -// expandObject detects if an ambiguous JSON object was flattened to a List which -// should be decoded into a struct, and expands the ast to properly deocode. -func expandObject(node ast.Node, result reflect.Value) ast.Node { - item, ok := node.(*ast.ObjectItem) - if !ok { - return node - } - - elemType := result.Type() - - // our target type must be a struct - switch elemType.Kind() { - case reflect.Ptr: - switch elemType.Elem().Kind() { - case reflect.Struct: - //OK - default: - return node - } - case reflect.Struct: - //OK - default: - return node - } - - // A list value will have a key and field name. If it had more fields, - // it wouldn't have been flattened. - if len(item.Keys) != 2 { - return node - } - - keyToken := item.Keys[0].Token - item.Keys = item.Keys[1:] - - // we need to un-flatten the ast enough to decode - newNode := &ast.ObjectItem{ - Keys: []*ast.ObjectKey{ - &ast.ObjectKey{ - Token: keyToken, - }, - }, - Val: &ast.ObjectType{ - List: &ast.ObjectList{ - Items: []*ast.ObjectItem{item}, - }, - }, - } - - return newNode -} - -func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type())) - return nil - case token.STRING, token.HEREDOC: - result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type for string %T", name, node), - } -} - -func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error { - var item *ast.ObjectItem - if it, ok := node.(*ast.ObjectItem); ok { - item = it - node = it.Val - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - // Handle the special case where the object itself is a literal. Previously - // the yacc parser would always ensure top-level elements were arrays. The new - // parser does not make the same guarantees, thus we need to convert any - // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok && item != nil { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - list, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node), - } - } - - // This slice will keep track of all the structs we'll be decoding. - // There can be more than one struct if there are embedded structs - // that are squashed. - structs := make([]reflect.Value, 1, 5) - structs[0] = result - - // Compile the list of all the fields that we're going to be decoding - // from all the structs. - type field struct { - field reflect.StructField - val reflect.Value - } - fields := []field{} - for len(structs) > 0 { - structVal := structs[0] - structs = structs[1:] - - structType := structVal.Type() - for i := 0; i < structType.NumField(); i++ { - fieldType := structType.Field(i) - tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") - - // Ignore fields with tag name "-" - if tagParts[0] == "-" { - continue - } - - if fieldType.Anonymous { - fieldKind := fieldType.Type.Kind() - if fieldKind != reflect.Struct { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unsupported type to struct: %s", - fieldType.Name, fieldKind), - } - } - - // We have an embedded field. We "squash" the fields down - // if specified in the tag. - squash := false - for _, tag := range tagParts[1:] { - if tag == "squash" { - squash = true - break - } - } - - if squash { - structs = append( - structs, result.FieldByName(fieldType.Name)) - continue - } - } - - // Normal struct field, store it away - fields = append(fields, field{fieldType, structVal.Field(i)}) - } - } - - usedKeys := make(map[string]struct{}) - decodedFields := make([]string, 0, len(fields)) - decodedFieldsVal := make([]reflect.Value, 0) - unusedKeysVal := make([]reflect.Value, 0) - for _, f := range fields { - field, fieldValue := f.field, f.val - if !fieldValue.IsValid() { - // This should never happen - panic("field is not valid") - } - - // If we can't set the field, then it is unexported or something, - // and we just continue onwards. - if !fieldValue.CanSet() { - continue - } - - fieldName := field.Name - - tagValue := field.Tag.Get(tagName) - tagParts := strings.SplitN(tagValue, ",", 2) - if len(tagParts) >= 2 { - switch tagParts[1] { - case "decodedFields": - decodedFieldsVal = append(decodedFieldsVal, fieldValue) - continue - case "key": - if item == nil { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: %s asked for 'key', impossible", - name, fieldName), - } - } - - fieldValue.SetString(item.Keys[0].Token.Value().(string)) - continue - case "unusedKeys": - unusedKeysVal = append(unusedKeysVal, fieldValue) - continue - } - } - - if tagParts[0] != "" { - fieldName = tagParts[0] - } - - // Determine the element we'll use to decode. If it is a single - // match (only object with the field), then we decode it exactly. - // If it is a prefix match, then we decode the matches. - filter := list.Filter(fieldName) - - prefixMatches := filter.Children() - matches := filter.Elem() - if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { - continue - } - - // Track the used key - usedKeys[fieldName] = struct{}{} - - // Create the field name and decode. We range over the elements - // because we actually want the value. - fieldName = fmt.Sprintf("%s.%s", name, fieldName) - if len(prefixMatches.Items) > 0 { - if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { - return err - } - } - for _, match := range matches.Items { - var decodeNode ast.Node = match.Val - if ot, ok := decodeNode.(*ast.ObjectType); ok { - decodeNode = &ast.ObjectList{Items: ot.List.Items} - } - - if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { - return err - } - } - - decodedFields = append(decodedFields, field.Name) - } - - if len(decodedFieldsVal) > 0 { - // Sort it so that it is deterministic - sort.Strings(decodedFields) - - for _, v := range decodedFieldsVal { - v.Set(reflect.ValueOf(decodedFields)) - } - } - - return nil -} - -// findNodeType returns the type of ast.Node -func findNodeType() reflect.Type { - var nodeContainer struct { - Node ast.Node - } - value := reflect.ValueOf(nodeContainer).FieldByName("Node") - return value.Type() -} diff --git a/vendor/github.com/hashicorp/hcl/hcl.go b/vendor/github.com/hashicorp/hcl/hcl.go deleted file mode 100644 index 575a20b5..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl.go +++ /dev/null @@ -1,11 +0,0 @@ -// Package hcl decodes HCL into usable Go structures. -// -// hcl input can come in either pure HCL format or JSON format. -// It can be parsed into an AST, and then decoded into a structure, -// or it can be decoded directly from a string into a structure. -// -// If you choose to parse HCL into a raw AST, the benefit is that you -// can write custom visitor implementations to implement custom -// semantic checks. By default, HCL does not perform any semantic -// checks. -package hcl diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go deleted file mode 100644 index 6e5ef654..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package ast declares the types used to represent syntax trees for HCL -// (HashiCorp Configuration Language) -package ast - -import ( - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/token" -) - -// Node is an element in the abstract syntax tree. -type Node interface { - node() - Pos() token.Pos -} - -func (File) node() {} -func (ObjectList) node() {} -func (ObjectKey) node() {} -func (ObjectItem) node() {} -func (Comment) node() {} -func (CommentGroup) node() {} -func (ObjectType) node() {} -func (LiteralType) node() {} -func (ListType) node() {} - -// File represents a single HCL file -type File struct { - Node Node // usually a *ObjectList - Comments []*CommentGroup // list of all comments in the source -} - -func (f *File) Pos() token.Pos { - return f.Node.Pos() -} - -// ObjectList represents a list of ObjectItems. An HCL file itself is an -// ObjectList. -type ObjectList struct { - Items []*ObjectItem -} - -func (o *ObjectList) Add(item *ObjectItem) { - o.Items = append(o.Items, item) -} - -// Filter filters out the objects with the given key list as a prefix. -// -// The returned list of objects contain ObjectItems where the keys have -// this prefix already stripped off. This might result in objects with -// zero-length key lists if they have no children. -// -// If no matches are found, an empty ObjectList (non-nil) is returned. -func (o *ObjectList) Filter(keys ...string) *ObjectList { - var result ObjectList - for _, item := range o.Items { - // If there aren't enough keys, then ignore this - if len(item.Keys) < len(keys) { - continue - } - - match := true - for i, key := range item.Keys[:len(keys)] { - key := key.Token.Value().(string) - if key != keys[i] && !strings.EqualFold(key, keys[i]) { - match = false - break - } - } - if !match { - continue - } - - // Strip off the prefix from the children - newItem := *item - newItem.Keys = newItem.Keys[len(keys):] - result.Add(&newItem) - } - - return &result -} - -// Children returns further nested objects (key length > 0) within this -// ObjectList. This should be used with Filter to get at child items. -func (o *ObjectList) Children() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) > 0 { - result.Add(item) - } - } - - return &result -} - -// Elem returns items in the list that are direct element assignments -// (key length == 0). This should be used with Filter to get at elements. -func (o *ObjectList) Elem() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) == 0 { - result.Add(item) - } - } - - return &result -} - -func (o *ObjectList) Pos() token.Pos { - // always returns the uninitiliazed position - return o.Items[0].Pos() -} - -// ObjectItem represents a HCL Object Item. An item is represented with a key -// (or keys). It can be an assignment or an object (both normal and nested) -type ObjectItem struct { - // keys is only one length long if it's of type assignment. If it's a - // nested object it can be larger than one. In that case "assign" is - // invalid as there is no assignments for a nested object. - Keys []*ObjectKey - - // assign contains the position of "=", if any - Assign token.Pos - - // val is the item itself. It can be an object,list, number, bool or a - // string. If key length is larger than one, val can be only of type - // Object. - Val Node - - LeadComment *CommentGroup // associated lead comment - LineComment *CommentGroup // associated line comment -} - -func (o *ObjectItem) Pos() token.Pos { - // I'm not entirely sure what causes this, but removing this causes - // a test failure. We should investigate at some point. - if len(o.Keys) == 0 { - return token.Pos{} - } - - return o.Keys[0].Pos() -} - -// ObjectKeys are either an identifier or of type string. -type ObjectKey struct { - Token token.Token -} - -func (o *ObjectKey) Pos() token.Pos { - return o.Token.Pos -} - -// LiteralType represents a literal of basic type. Valid types are: -// token.NUMBER, token.FLOAT, token.BOOL and token.STRING -type LiteralType struct { - Token token.Token - - // comment types, only used when in a list - LeadComment *CommentGroup - LineComment *CommentGroup -} - -func (l *LiteralType) Pos() token.Pos { - return l.Token.Pos -} - -// ListStatement represents a HCL List type -type ListType struct { - Lbrack token.Pos // position of "[" - Rbrack token.Pos // position of "]" - List []Node // the elements in lexical order -} - -func (l *ListType) Pos() token.Pos { - return l.Lbrack -} - -func (l *ListType) Add(node Node) { - l.List = append(l.List, node) -} - -// ObjectType represents a HCL Object Type -type ObjectType struct { - Lbrace token.Pos // position of "{" - Rbrace token.Pos // position of "}" - List *ObjectList // the nodes in lexical order -} - -func (o *ObjectType) Pos() token.Pos { - return o.Lbrace -} - -// Comment node represents a single //, # style or /*- style commment -type Comment struct { - Start token.Pos // position of / or # - Text string -} - -func (c *Comment) Pos() token.Pos { - return c.Start -} - -// CommentGroup node represents a sequence of comments with no other tokens and -// no empty lines between. -type CommentGroup struct { - List []*Comment // len(List) > 0 -} - -func (c *CommentGroup) Pos() token.Pos { - return c.List[0].Pos() -} - -//------------------------------------------------------------------- -// GoStringer -//------------------------------------------------------------------- - -func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } -func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go deleted file mode 100644 index ba07ad42..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go +++ /dev/null @@ -1,52 +0,0 @@ -package ast - -import "fmt" - -// WalkFunc describes a function to be called for each node during a Walk. The -// returned node can be used to rewrite the AST. Walking stops the returned -// bool is false. -type WalkFunc func(Node) (Node, bool) - -// Walk traverses an AST in depth-first order: It starts by calling fn(node); -// node must not be nil. If fn returns true, Walk invokes fn recursively for -// each of the non-nil children of node, followed by a call of fn(nil). The -// returned node of fn can be used to rewrite the passed node to fn. -func Walk(node Node, fn WalkFunc) Node { - rewritten, ok := fn(node) - if !ok { - return rewritten - } - - switch n := node.(type) { - case *File: - n.Node = Walk(n.Node, fn) - case *ObjectList: - for i, item := range n.Items { - n.Items[i] = Walk(item, fn).(*ObjectItem) - } - case *ObjectKey: - // nothing to do - case *ObjectItem: - for i, k := range n.Keys { - n.Keys[i] = Walk(k, fn).(*ObjectKey) - } - - if n.Val != nil { - n.Val = Walk(n.Val, fn) - } - case *LiteralType: - // nothing to do - case *ListType: - for i, l := range n.List { - n.List[i] = Walk(l, fn) - } - case *ObjectType: - n.List = Walk(n.List, fn).(*ObjectList) - default: - // should we panic here? - fmt.Printf("unknown type: %T\n", n) - } - - fn(nil) - return rewritten -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/vendor/github.com/hashicorp/hcl/hcl/parser/error.go deleted file mode 100644 index 5c99381d..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/error.go +++ /dev/null @@ -1,17 +0,0 @@ -package parser - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/token" -) - -// PosError is a parse error that contains a position. -type PosError struct { - Pos token.Pos - Err error -} - -func (e *PosError) Error() string { - return fmt.Sprintf("At %s: %s", e.Pos, e.Err) -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go deleted file mode 100644 index 64c83bcf..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go +++ /dev/null @@ -1,532 +0,0 @@ -// Package parser implements a parser for HCL (HashiCorp Configuration -// Language) -package parser - -import ( - "bytes" - "errors" - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/scanner" - "github.com/hashicorp/hcl/hcl/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - comments []*ast.CommentGroup - leadComment *ast.CommentGroup // last lead comment - lineComment *ast.CommentGroup // last line comment - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - // normalize all line endings - // since the scanner and output only work with "\n" line endings, we may - // end up with dangling "\r" characters in the parsed data. - src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) - - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = &PosError{Pos: pos, Err: errors.New(msg)} - } - - f.Node, err = p.objectList(false) - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - f.Comments = p.comments - return f, nil -} - -// objectList parses a list of items within an object (generally k/v pairs). -// The parameter" obj" tells this whether to we are within an object (braces: -// '{', '}') or just at the top level. If we're within an object, we end -// at an RBRACE. -func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - if obj { - tok := p.scan() - p.unscan() - if tok.Type == token.RBRACE { - break - } - } - - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // object lists can be optionally comma-delimited e.g. when a list of maps - // is being expressed, so a comma is allowed here - it's simply consumed - tok := p.scan() - if tok.Type != token.COMMA { - p.unscan() - } - } - return node, nil -} - -func (p *Parser) consumeComment() (comment *ast.Comment, endline int) { - endline = p.tok.Pos.Line - - // count the endline if it's multiline comment, ie starting with /* - if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' { - // don't use range here - no need to decode Unicode code points - for i := 0; i < len(p.tok.Text); i++ { - if p.tok.Text[i] == '\n' { - endline++ - } - } - } - - comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text} - p.tok = p.sc.Scan() - return -} - -func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) { - var list []*ast.Comment - endline = p.tok.Pos.Line - - for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n { - var comment *ast.Comment - comment, endline = p.consumeComment() - list = append(list, comment) - } - - // add comment group to the comments list - comments = &ast.CommentGroup{List: list} - p.comments = append(p.comments, comments) - - return -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if len(keys) > 0 && err == errEofToken { - // We ignore eof token here since it is an error if we didn't - // receive a value (but we did receive a key) for the item. - err = nil - } - if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE { - // This is a strange boolean statement, but what it means is: - // We have keys with no value, and we're likely in an object - // (since RBrace ends an object). For this, we set err to nil so - // we continue and get the error below of having the wrong value - // type. - err = nil - - // Reset the token type so we don't think it completed fine. See - // objectType which uses p.tok.Type to check if we're done with - // the object. - p.tok.Type = token.EOF - } - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - if p.leadComment != nil { - o.LeadComment = p.leadComment - p.leadComment = nil - } - - switch p.tok.Type { - case token.ASSIGN: - o.Assign = p.tok.Pos - o.Val, err = p.object() - if err != nil { - return nil, err - } - case token.LBRACE: - o.Val, err = p.objectType() - if err != nil { - return nil, err - } - default: - keyStr := make([]string, 0, len(keys)) - for _, k := range keys { - keyStr = append(keyStr, k.Token.Text) - } - - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf( - "key '%s' expected start of object ('{') or assignment ('=')", - strings.Join(keyStr, " ")), - } - } - - // key=#comment - // val - if p.lineComment != nil { - o.LineComment, p.lineComment = p.lineComment, nil - } - - // do a look-ahead for line comment - p.scan() - if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil { - o.LineComment = p.lineComment - p.lineComment = nil - } - p.unscan() - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - // It is very important to also return the keys here as well as - // the error. This is because we need to be able to tell if we - // did parse keys prior to finding the EOF, or if we just found - // a bare EOF. - return keys, errEofToken - case token.ASSIGN: - // assignment or object only, but not nested objects. this is not - // allowed: `foo bar = {}` - if keyCount > 1 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type), - } - } - - if keyCount == 0 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: errors.New("no object keys found!"), - } - } - - return keys, nil - case token.LBRACE: - var err error - - // If we have no keys, then it is a syntax error. i.e. {{}} is not - // allowed. - if len(keys) == 0 { - err = &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), - } - } - - // object - return keys, err - case token.IDENT, token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{Token: p.tok}) - case token.ILLEGAL: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("illegal character"), - } - default: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type), - } - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (ast.Node, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.COMMENT: - // implement comment - case token.EOF: - return nil, errEofToken - } - - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("Unknown token: %+v", tok), - } -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{ - Lbrace: p.tok.Pos, - } - - l, err := p.objectList(true) - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - // No error, scan and expect the ending to be a brace - if tok := p.scan(); tok.Type != token.RBRACE { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), - } - } - - o.List = l - o.Rbrace = p.tok.Pos // advanced via parseObjectList - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{ - Lbrack: p.tok.Pos, - } - - needComma := false - for { - tok := p.scan() - if needComma { - switch tok.Type { - case token.COMMA, token.RBRACK: - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error parsing list, expected comma or list end, got: %s", - tok.Type), - } - } - } - switch tok.Type { - case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: - node, err := p.literalType() - if err != nil { - return nil, err - } - - // If there is a lead comment, apply it - if p.leadComment != nil { - node.LeadComment = p.leadComment - p.leadComment = nil - } - - l.Add(node) - needComma = true - case token.COMMA: - // get next list item or we are at the end - // do a look-ahead for line comment - p.scan() - if p.lineComment != nil && len(l.List) > 0 { - lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) - if ok { - lit.LineComment = p.lineComment - l.List[len(l.List)-1] = lit - p.lineComment = nil - } - } - p.unscan() - - needComma = false - continue - case token.LBRACE: - // Looks like a nested object, so parse it out - node, err := p.objectType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse object within list: %s", err), - } - } - l.Add(node) - needComma = true - case token.LBRACK: - node, err := p.listType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse list within list: %s", err), - } - } - l.Add(node) - case token.RBRACK: - // finished - l.Rbrack = p.tok.Pos - return l, nil - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type), - } - } - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok, - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. In the process, it collects any -// comment groups encountered, and remembers the last lead and line comments. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - // Otherwise read the next token from the scanner and Save it to the buffer - // in case we unscan later. - prev := p.tok - p.tok = p.sc.Scan() - - if p.tok.Type == token.COMMENT { - var comment *ast.CommentGroup - var endline int - - // fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n", - // p.tok.Pos.Line, prev.Pos.Line, endline) - if p.tok.Pos.Line == prev.Pos.Line { - // The comment is on same line as the previous token; it - // cannot be a lead comment but may be a line comment. - comment, endline = p.consumeCommentGroup(0) - if p.tok.Pos.Line != endline { - // The next token is on a different line, thus - // the last comment group is a line comment. - p.lineComment = comment - } - } - - // consume successor comments, if any - endline = -1 - for p.tok.Type == token.COMMENT { - comment, endline = p.consumeCommentGroup(1) - } - - if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE { - switch p.tok.Type { - case token.RBRACE, token.RBRACK: - // Do not count for these cases - default: - // The next token is following on the line immediately after the - // comment group, thus the last comment group is a lead comment. - p.leadComment = comment - } - } - - } - - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go deleted file mode 100644 index 7c038d12..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go +++ /dev/null @@ -1,789 +0,0 @@ -package printer - -import ( - "bytes" - "fmt" - "sort" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/token" -) - -const ( - blank = byte(' ') - newline = byte('\n') - tab = byte('\t') - infinity = 1 << 30 // offset or line -) - -var ( - unindent = []byte("\uE123") // in the private use space -) - -type printer struct { - cfg Config - prev token.Pos - - comments []*ast.CommentGroup // may be nil, contains all comments - standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) - - enableTrace bool - indentTrace int -} - -type ByPosition []*ast.CommentGroup - -func (b ByPosition) Len() int { return len(b) } -func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) } - -// collectComments comments all standalone comments which are not lead or line -// comment -func (p *printer) collectComments(node ast.Node) { - // first collect all comments. This is already stored in - // ast.File.(comments) - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.File: - p.comments = t.Comments - return nn, false - } - return nn, true - }) - - standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0) - for _, c := range p.comments { - standaloneComments[c.Pos()] = c - } - - // next remove all lead and line comments from the overall comment map. - // This will give us comments which are standalone, comments which are not - // assigned to any kind of node. - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.LiteralType: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - case *ast.ObjectItem: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - } - - return nn, true - }) - - for _, c := range standaloneComments { - p.standaloneComments = append(p.standaloneComments, c) - } - - sort.Sort(ByPosition(p.standaloneComments)) -} - -// output prints creates b printable HCL output and returns it. -func (p *printer) output(n interface{}) []byte { - var buf bytes.Buffer - - switch t := n.(type) { - case *ast.File: - // File doesn't trace so we add the tracing here - defer un(trace(p, "File")) - return p.output(t.Node) - case *ast.ObjectList: - defer un(trace(p, "ObjectList")) - - var index int - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is at "infinity" - var nextItem token.Pos - if index != len(t.Items) { - nextItem = t.Items[index].Pos() - } else { - nextItem = token.Pos{Offset: infinity, Line: infinity} - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - // Go through all the comments in the group. The group - // should be printed together, not separated by double newlines. - printed := false - newlinePrinted := false - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // if we hit the end add newlines so we can print the comment - // we don't do this if prev is invalid which means the - // beginning of the file since the first comment should - // be at the first line. - if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) { - buf.Write([]byte{newline, newline}) - newlinePrinted = true - } - - // Write the actual comment. - buf.WriteString(comment.Text) - buf.WriteByte(newline) - - // Set printed to true to note that we printed something - printed = true - } - } - - // If we're not at the last item, write a new line so - // that there is a newline separating this comment from - // the next object. - if printed && index != len(t.Items) { - buf.WriteByte(newline) - } - } - - if index == len(t.Items) { - break - } - - buf.Write(p.output(t.Items[index])) - if index != len(t.Items)-1 { - // Always write a newline to separate us from the next item - buf.WriteByte(newline) - - // Need to determine if we're going to separate the next item - // with a blank line. The logic here is simple, though there - // are a few conditions: - // - // 1. The next object is more than one line away anyways, - // so we need an empty line. - // - // 2. The next object is not a "single line" object, so - // we need an empty line. - // - // 3. This current object is not a single line object, - // so we need an empty line. - current := t.Items[index] - next := t.Items[index+1] - if next.Pos().Line != t.Items[index].Pos().Line+1 || - !p.isSingleLineObject(next) || - !p.isSingleLineObject(current) { - buf.WriteByte(newline) - } - } - index++ - } - case *ast.ObjectKey: - buf.WriteString(t.Token.Text) - case *ast.ObjectItem: - p.prev = t.Pos() - buf.Write(p.objectItem(t)) - case *ast.LiteralType: - buf.Write(p.literalType(t)) - case *ast.ListType: - buf.Write(p.list(t)) - case *ast.ObjectType: - buf.Write(p.objectType(t)) - default: - fmt.Printf(" unknown type: %T\n", n) - } - - return buf.Bytes() -} - -func (p *printer) literalType(lit *ast.LiteralType) []byte { - result := []byte(lit.Token.Text) - switch lit.Token.Type { - case token.HEREDOC: - // Clear the trailing newline from heredocs - if result[len(result)-1] == '\n' { - result = result[:len(result)-1] - } - - // Poison lines 2+ so that we don't indent them - result = p.heredocIndent(result) - case token.STRING: - // If this is a multiline string, poison lines 2+ so we don't - // indent them. - if bytes.IndexRune(result, '\n') >= 0 { - result = p.heredocIndent(result) - } - } - - return result -} - -// objectItem returns the printable HCL form of an object item. An object type -// starts with one/multiple keys and has a value. The value might be of any -// type. -func (p *printer) objectItem(o *ast.ObjectItem) []byte { - defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text))) - var buf bytes.Buffer - - if o.LeadComment != nil { - for _, comment := range o.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - // If key and val are on different lines, treat line comments like lead comments. - if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line { - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range o.Keys { - buf.WriteString(k.Token.Text) - buf.WriteByte(blank) - - // reach end of key - if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - buf.Write(p.output(o.Val)) - - if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line { - buf.WriteByte(blank) - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - } - } - - return buf.Bytes() -} - -// objectType returns the printable HCL form of an object type. An object type -// begins with a brace and ends with a brace. -func (p *printer) objectType(o *ast.ObjectType) []byte { - defer un(trace(p, "ObjectType")) - var buf bytes.Buffer - buf.WriteString("{") - - var index int - var nextItem token.Pos - var commented, newlinePrinted bool - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is the closing brace - if index != len(o.List.Items) { - nextItem = o.List.Items[index].Pos() - } else { - nextItem = o.Rbrace - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - printed := false - var lastCommentPos token.Pos - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // If there are standalone comments and the initial newline has not - // been printed yet, do it now. - if !newlinePrinted { - newlinePrinted = true - buf.WriteByte(newline) - } - - // add newline if it's between other printed nodes - if index > 0 { - commented = true - buf.WriteByte(newline) - } - - // Store this position - lastCommentPos = comment.Pos() - - // output the comment itself - buf.Write(p.indent(p.heredocIndent([]byte(comment.Text)))) - - // Set printed to true to note that we printed something - printed = true - - /* - if index != len(o.List.Items) { - buf.WriteByte(newline) // do not print on the end - } - */ - } - } - - // Stuff to do if we had comments - if printed { - // Always write a newline - buf.WriteByte(newline) - - // If there is another item in the object and our comment - // didn't hug it directly, then make sure there is a blank - // line separating them. - if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 { - buf.WriteByte(newline) - } - } - } - - if index == len(o.List.Items) { - p.prev = o.Rbrace - break - } - - // At this point we are sure that it's not a totally empty block: print - // the initial newline if it hasn't been printed yet by the previous - // block about standalone comments. - if !newlinePrinted { - buf.WriteByte(newline) - newlinePrinted = true - } - - // check if we have adjacent one liner items. If yes we'll going to align - // the comments. - var aligned []*ast.ObjectItem - for _, item := range o.List.Items[index:] { - // we don't group one line lists - if len(o.List.Items) == 1 { - break - } - - // one means a oneliner with out any lead comment - // two means a oneliner with lead comment - // anything else might be something else - cur := lines(string(p.objectItem(item))) - if cur > 2 { - break - } - - curPos := item.Pos() - - nextPos := token.Pos{} - if index != len(o.List.Items)-1 { - nextPos = o.List.Items[index+1].Pos() - } - - prevPos := token.Pos{} - if index != 0 { - prevPos = o.List.Items[index-1].Pos() - } - - // fmt.Println("DEBUG ----------------") - // fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos) - // fmt.Printf("cur = %+v curPos: %s\n", cur, curPos) - // fmt.Printf("next = %+v nextPos: %s\n", next, nextPos) - - if curPos.Line+1 == nextPos.Line { - aligned = append(aligned, item) - index++ - continue - } - - if curPos.Line-1 == prevPos.Line { - aligned = append(aligned, item) - index++ - - // finish if we have a new line or comment next. This happens - // if the next item is not adjacent - if curPos.Line+1 != nextPos.Line { - break - } - continue - } - - break - } - - // put newlines if the items are between other non aligned items. - // newlines are also added if there is a standalone comment already, so - // check it too - if !commented && index != len(aligned) { - buf.WriteByte(newline) - } - - if len(aligned) >= 1 { - p.prev = aligned[len(aligned)-1].Pos() - - items := p.alignedItems(aligned) - buf.Write(p.indent(items)) - } else { - p.prev = o.List.Items[index].Pos() - - buf.Write(p.indent(p.objectItem(o.List.Items[index]))) - index++ - } - - buf.WriteByte(newline) - } - - buf.WriteString("}") - return buf.Bytes() -} - -func (p *printer) alignedItems(items []*ast.ObjectItem) []byte { - var buf bytes.Buffer - - // find the longest key and value length, needed for alignment - var longestKeyLen int // longest key length - var longestValLen int // longest value length - for _, item := range items { - key := len(item.Keys[0].Token.Text) - val := len(p.output(item.Val)) - - if key > longestKeyLen { - longestKeyLen = key - } - - if val > longestValLen { - longestValLen = val - } - } - - for i, item := range items { - if item.LeadComment != nil { - for _, comment := range item.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range item.Keys { - keyLen := len(k.Token.Text) - buf.WriteString(k.Token.Text) - for i := 0; i < longestKeyLen-keyLen+1; i++ { - buf.WriteByte(blank) - } - - // reach end of key - if i == len(item.Keys)-1 && len(item.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - val := p.output(item.Val) - valLen := len(val) - buf.Write(val) - - if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil { - for i := 0; i < longestValLen-valLen+1; i++ { - buf.WriteByte(blank) - } - - for _, comment := range item.LineComment.List { - buf.WriteString(comment.Text) - } - } - - // do not print for the last item - if i != len(items)-1 { - buf.WriteByte(newline) - } - } - - return buf.Bytes() -} - -// list returns the printable HCL form of an list type. -func (p *printer) list(l *ast.ListType) []byte { - if p.isSingleLineList(l) { - return p.singleLineList(l) - } - - var buf bytes.Buffer - buf.WriteString("[") - buf.WriteByte(newline) - - var longestLine int - for _, item := range l.List { - // for now we assume that the list only contains literal types - if lit, ok := item.(*ast.LiteralType); ok { - lineLen := len(lit.Token.Text) - if lineLen > longestLine { - longestLine = lineLen - } - } - } - - haveEmptyLine := false - for i, item := range l.List { - // If we have a lead comment, then we want to write that first - leadComment := false - if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil { - leadComment = true - - // Ensure an empty line before every element with a - // lead comment (except the first item in a list). - if !haveEmptyLine && i != 0 { - buf.WriteByte(newline) - } - - for _, comment := range lit.LeadComment.List { - buf.Write(p.indent([]byte(comment.Text))) - buf.WriteByte(newline) - } - } - - // also indent each line - val := p.output(item) - curLen := len(val) - buf.Write(p.indent(val)) - - // if this item is a heredoc, then we output the comma on - // the next line. This is the only case this happens. - comma := []byte{','} - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - comma = p.indent(comma) - } - - buf.Write(comma) - - if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil { - // if the next item doesn't have any comments, do not align - buf.WriteByte(blank) // align one space - for i := 0; i < longestLine-curLen; i++ { - buf.WriteByte(blank) - } - - for _, comment := range lit.LineComment.List { - buf.WriteString(comment.Text) - } - } - - buf.WriteByte(newline) - - // Ensure an empty line after every element with a - // lead comment (except the first item in a list). - haveEmptyLine = leadComment && i != len(l.List)-1 - if haveEmptyLine { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// isSingleLineList returns true if: -// * they were previously formatted entirely on one line -// * they consist entirely of literals -// * there are either no heredoc strings or the list has exactly one element -// * there are no line comments -func (printer) isSingleLineList(l *ast.ListType) bool { - for _, item := range l.List { - if item.Pos().Line != l.Lbrack.Line { - return false - } - - lit, ok := item.(*ast.LiteralType) - if !ok { - return false - } - - if lit.Token.Type == token.HEREDOC && len(l.List) != 1 { - return false - } - - if lit.LineComment != nil { - return false - } - } - - return true -} - -// singleLineList prints a simple single line list. -// For a definition of "simple", see isSingleLineList above. -func (p *printer) singleLineList(l *ast.ListType) []byte { - buf := &bytes.Buffer{} - - buf.WriteString("[") - for i, item := range l.List { - if i != 0 { - buf.WriteString(", ") - } - - // Output the item itself - buf.Write(p.output(item)) - - // The heredoc marker needs to be at the end of line. - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// indent indents the lines of the given buffer for each non-empty line -func (p *printer) indent(buf []byte) []byte { - var prefix []byte - if p.cfg.SpacesWidth != 0 { - for i := 0; i < p.cfg.SpacesWidth; i++ { - prefix = append(prefix, blank) - } - } else { - prefix = []byte{tab} - } - - var res []byte - bol := true - for _, c := range buf { - if bol && c != '\n' { - res = append(res, prefix...) - } - - res = append(res, c) - bol = c == '\n' - } - return res -} - -// unindent removes all the indentation from the tombstoned lines -func (p *printer) unindent(buf []byte) []byte { - var res []byte - for i := 0; i < len(buf); i++ { - skip := len(buf)-i <= len(unindent) - if !skip { - skip = !bytes.Equal(unindent, buf[i:i+len(unindent)]) - } - if skip { - res = append(res, buf[i]) - continue - } - - // We have a marker. we have to backtrace here and clean out - // any whitespace ahead of our tombstone up to a \n - for j := len(res) - 1; j >= 0; j-- { - if res[j] == '\n' { - break - } - - res = res[:j] - } - - // Skip the entire unindent marker - i += len(unindent) - 1 - } - - return res -} - -// heredocIndent marks all the 2nd and further lines as unindentable -func (p *printer) heredocIndent(buf []byte) []byte { - var res []byte - bol := false - for _, c := range buf { - if bol && c != '\n' { - res = append(res, unindent...) - } - res = append(res, c) - bol = c == '\n' - } - return res -} - -// isSingleLineObject tells whether the given object item is a single -// line object such as "obj {}". -// -// A single line object: -// -// * has no lead comments (hence multi-line) -// * has no assignment -// * has no values in the stanza (within {}) -// -func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool { - // If there is a lead comment, can't be one line - if val.LeadComment != nil { - return false - } - - // If there is assignment, we always break by line - if val.Assign.IsValid() { - return false - } - - // If it isn't an object type, then its not a single line object - ot, ok := val.Val.(*ast.ObjectType) - if !ok { - return false - } - - // If the object has no items, it is single line! - return len(ot.List.Items) == 0 -} - -func lines(txt string) int { - endline := 1 - for i := 0; i < len(txt); i++ { - if txt[i] == '\n' { - endline++ - } - } - return endline -} - -// ---------------------------------------------------------------------------- -// Tracing support - -func (p *printer) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - i := 2 * p.indentTrace - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *printer, msg string) *printer { - p.printTrace(msg, "(") - p.indentTrace++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *printer) { - p.indentTrace-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go deleted file mode 100644 index 6617ab8e..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package printer implements printing of AST nodes to HCL format. -package printer - -import ( - "bytes" - "io" - "text/tabwriter" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" -) - -var DefaultConfig = Config{ - SpacesWidth: 2, -} - -// A Config node controls the output of Fprint. -type Config struct { - SpacesWidth int // if set, it will use spaces instead of tabs for alignment -} - -func (c *Config) Fprint(output io.Writer, node ast.Node) error { - p := &printer{ - cfg: *c, - comments: make([]*ast.CommentGroup, 0), - standaloneComments: make([]*ast.CommentGroup, 0), - // enableTrace: true, - } - - p.collectComments(node) - - if _, err := output.Write(p.unindent(p.output(node))); err != nil { - return err - } - - // flush tabwriter, if any - var err error - if tw, _ := output.(*tabwriter.Writer); tw != nil { - err = tw.Flush() - } - - return err -} - -// Fprint "pretty-prints" an HCL node to output -// It calls Config.Fprint with default settings. -func Fprint(output io.Writer, node ast.Node) error { - return DefaultConfig.Fprint(output, node) -} - -// Format formats src HCL and returns the result. -func Format(src []byte) ([]byte, error) { - node, err := parser.Parse(src) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - if err := DefaultConfig.Fprint(&buf, node); err != nil { - return nil, err - } - - // Add trailing newline to result - buf.WriteString("\n") - return buf.Bytes(), nil -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go deleted file mode 100644 index 624a18fe..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go +++ /dev/null @@ -1,652 +0,0 @@ -// Package scanner implements a scanner for HCL (HashiCorp Configuration -// Language) source text. -package scanner - -import ( - "bytes" - "fmt" - "os" - "regexp" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/hcl/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == utf8.RuneError && size == 1 { - s.err("illegal UTF-8 encoding") - return ch - } - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - if ch == '\x00' { - s.err("unexpected null character (0x00)") - return eof - } - - if ch == '\uE123' { - s.err("unicode code point U+E123 reserved for internal use") - return utf8.RuneError - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - tok = token.IDENT - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '#', '/': - tok = token.COMMENT - s.scanComment(ch) - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '<': - tok = token.HEREDOC - s.scanHeredoc() - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case '=': - tok = token.ASSIGN - case '+': - tok = token.ADD - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - tok = token.SUB - } - default: - s.err("illegal char") - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -func (s *Scanner) scanComment(ch rune) { - // single line comments - if ch == '#' || (ch == '/' && s.peek() != '*') { - if ch == '/' && s.peek() != '/' { - s.err("expected '/' for comment") - return - } - - ch = s.next() - for ch != '\n' && ch >= 0 && ch != eof { - ch = s.next() - } - if ch != eof && ch >= 0 { - s.unread() - } - return - } - - // be sure we get the character after /* This allows us to find comment's - // that are not erminated - if ch == '/' { - s.next() - ch = s.next() // read character after "/*" - } - - // look for /* - style comments - for { - if ch < 0 || ch == eof { - s.err("comment not terminated") - break - } - - ch0 := ch - ch = s.next() - if ch0 == '*' && ch == '/' { - break - } - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - if ch == '0' { - // check for hexadecimal, octal or float - ch = s.next() - if ch == 'x' || ch == 'X' { - // hexadecimal - ch = s.next() - found := false - for isHexadecimal(ch) { - ch = s.next() - found = true - } - - if !found { - s.err("illegal hexadecimal number") - } - - if ch != eof { - s.unread() - } - - return token.NUMBER - } - - // now it's either something like: 0421(octal) or 0.1231(float) - illegalOctal := false - for isDecimal(ch) { - ch = s.next() - if ch == '8' || ch == '9' { - // this is just a possibility. For example 0159 is illegal, but - // 0159.23 is valid. So we mark a possible illegal octal. If - // the next character is not a period, we'll print the error. - illegalOctal = true - } - } - - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if illegalOctal { - s.err("illegal octal number") - } - - if ch != eof { - s.unread() - } - return token.NUMBER - } - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanHeredoc scans a heredoc string -func (s *Scanner) scanHeredoc() { - // Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) { - break - } - - // Not an anchor match, record the start of a new line - lineStart = s.srcPos.Offset - } - - if ch == eof { - s.err("heredoc not terminated") - return - } - } - - return -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' && braces == 0 { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - start := n - for n > 0 && digitVal(ch) < base { - ch = s.next() - if ch == eof { - // If we see an EOF, we halt any more scanning of digits - // immediately. - break - } - - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - if n != start && ch != eof { - // we scanned all digits, put the last non digit char back, - // only if we read anything at all - s.unread() - } - - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isDigit returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isDecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go deleted file mode 100644 index 5f981eaa..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go +++ /dev/null @@ -1,241 +0,0 @@ -package strconv - -import ( - "errors" - "unicode/utf8" -) - -// ErrSyntax indicates that a value does not have the right syntax for the target type. -var ErrSyntax = errors.New("invalid syntax") - -// Unquote interprets s as a single-quoted, double-quoted, -// or backquoted Go string literal, returning the string value -// that s quotes. (If s is single-quoted, it would be a Go -// character literal; Unquote returns the corresponding -// one-character string.) -func Unquote(s string) (t string, err error) { - n := len(s) - if n < 2 { - return "", ErrSyntax - } - quote := s[0] - if quote != s[n-1] { - return "", ErrSyntax - } - s = s[1 : n-1] - - if quote != '"' { - return "", ErrSyntax - } - if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { - return "", ErrSyntax - } - - // Is it trivial? Avoid allocation. - if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') { - switch quote { - case '"': - return s, nil - case '\'': - r, size := utf8.DecodeRuneInString(s) - if size == len(s) && (r != utf8.RuneError || size != 1) { - return s, nil - } - } - } - - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. - for len(s) > 0 { - // If we're starting a '${}' then let it through un-unquoted. - // Specifically: we don't unquote any characters within the `${}` - // section. - if s[0] == '$' && len(s) > 1 && s[1] == '{' { - buf = append(buf, '$', '{') - s = s[2:] - - // Continue reading until we find the closing brace, copying as-is - braces := 1 - for len(s) > 0 && braces > 0 { - r, size := utf8.DecodeRuneInString(s) - if r == utf8.RuneError { - return "", ErrSyntax - } - - s = s[size:] - - n := utf8.EncodeRune(runeTmp[:], r) - buf = append(buf, runeTmp[:n]...) - - switch r { - case '{': - braces++ - case '}': - braces-- - } - } - if braces != 0 { - return "", ErrSyntax - } - if len(s) == 0 { - // If there's no string left, we're done! - break - } else { - // If there's more left, we need to pop back up to the top of the loop - // in case there's another interpolation in this string. - continue - } - } - - if s[0] == '\n' { - return "", ErrSyntax - } - - c, multibyte, ss, err := unquoteChar(s, quote) - if err != nil { - return "", err - } - s = ss - if c < utf8.RuneSelf || !multibyte { - buf = append(buf, byte(c)) - } else { - n := utf8.EncodeRune(runeTmp[:], c) - buf = append(buf, runeTmp[:n]...) - } - if quote == '\'' && len(s) != 0 { - // single-quoted must be single character - return "", ErrSyntax - } - } - return string(buf), nil -} - -// contains reports whether the string contains the byte c. -func contains(s string, c byte) bool { - for i := 0; i < len(s); i++ { - if s[i] == c { - return true - } - } - return false -} - -func unhex(b byte) (v rune, ok bool) { - c := rune(b) - switch { - case '0' <= c && c <= '9': - return c - '0', true - case 'a' <= c && c <= 'f': - return c - 'a' + 10, true - case 'A' <= c && c <= 'F': - return c - 'A' + 10, true - } - return -} - -func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) { - // easy cases - switch c := s[0]; { - case c == quote && (quote == '\'' || quote == '"'): - err = ErrSyntax - return - case c >= utf8.RuneSelf: - r, size := utf8.DecodeRuneInString(s) - return r, true, s[size:], nil - case c != '\\': - return rune(s[0]), false, s[1:], nil - } - - // hard case: c is backslash - if len(s) <= 1 { - err = ErrSyntax - return - } - c := s[1] - s = s[2:] - - switch c { - case 'a': - value = '\a' - case 'b': - value = '\b' - case 'f': - value = '\f' - case 'n': - value = '\n' - case 'r': - value = '\r' - case 't': - value = '\t' - case 'v': - value = '\v' - case 'x', 'u', 'U': - n := 0 - switch c { - case 'x': - n = 2 - case 'u': - n = 4 - case 'U': - n = 8 - } - var v rune - if len(s) < n { - err = ErrSyntax - return - } - for j := 0; j < n; j++ { - x, ok := unhex(s[j]) - if !ok { - err = ErrSyntax - return - } - v = v<<4 | x - } - s = s[n:] - if c == 'x' { - // single-byte string, possibly not UTF-8 - value = v - break - } - if v > utf8.MaxRune { - err = ErrSyntax - return - } - value = v - multibyte = true - case '0', '1', '2', '3', '4', '5', '6', '7': - v := rune(c) - '0' - if len(s) < 2 { - err = ErrSyntax - return - } - for j := 0; j < 2; j++ { // one digit already; two more - x := rune(s[j]) - '0' - if x < 0 || x > 7 { - err = ErrSyntax - return - } - v = (v << 3) | x - } - s = s[2:] - if v > 255 { - err = ErrSyntax - return - } - value = v - case '\\': - value = '\\' - case '\'', '"': - if c != quote { - err = ErrSyntax - return - } - value = rune(c) - default: - err = ErrSyntax - return - } - tail = s - return -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/vendor/github.com/hashicorp/hcl/hcl/token/position.go deleted file mode 100644 index 59c1bb72..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/vendor/github.com/hashicorp/hcl/hcl/token/token.go deleted file mode 100644 index e37c0664..00000000 --- a/vendor/github.com/hashicorp/hcl/hcl/token/token.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package token defines constants representing the lexical tokens for HCL -// (HashiCorp Configuration Language) -package token - -import ( - "fmt" - "strconv" - "strings" - - hclstrconv "github.com/hashicorp/hcl/hcl/strconv" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string - JSON bool -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - COMMENT - - identifier_beg - IDENT // literals - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - HEREDOC // < 0 { - // Pop the current item - n := len(frontier) - item := frontier[n-1] - frontier = frontier[:n-1] - - switch v := item.Val.(type) { - case *ast.ObjectType: - items, frontier = flattenObjectType(v, item, items, frontier) - case *ast.ListType: - items, frontier = flattenListType(v, item, items, frontier) - default: - items = append(items, item) - } - } - - // Reverse the list since the frontier model runs things backwards - for i := len(items)/2 - 1; i >= 0; i-- { - opp := len(items) - 1 - i - items[i], items[opp] = items[opp], items[i] - } - - // Done! Set the original items - list.Items = items - return n, true - }) -} - -func flattenListType( - ot *ast.ListType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list is empty, keep the original list - if len(ot.List) == 0 { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List { - if _, ok := subitem.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, elem := range ot.List { - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: item.Keys, - Assign: item.Assign, - Val: elem, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} - -func flattenObjectType( - ot *ast.ObjectType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list has no items we do not have to flatten anything - if ot.List.Items == nil { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List.Items { - if _, ok := subitem.Val.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, subitem := range ot.List.Items { - // Copy the new key - keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys)) - copy(keys, item.Keys) - copy(keys[len(item.Keys):], subitem.Keys) - - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: keys, - Assign: item.Assign, - Val: subitem.Val, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go deleted file mode 100644 index 125a5f07..00000000 --- a/vendor/github.com/hashicorp/hcl/json/parser/parser.go +++ /dev/null @@ -1,313 +0,0 @@ -package parser - -import ( - "errors" - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hcltoken "github.com/hashicorp/hcl/hcl/token" - "github.com/hashicorp/hcl/json/scanner" - "github.com/hashicorp/hcl/json/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = fmt.Errorf("%s: %s", pos, msg) - } - - // The root must be an object in JSON - object, err := p.object() - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - // We make our final node an object list so it is more HCL compatible - f.Node = object.List - - // Flatten it, which finds patterns and turns them into more HCL-like - // AST trees. - flattenObjects(f.Node) - - return f, nil -} - -func (p *Parser) objectList() (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // Check for a followup comma. If it isn't a comma, then we're done - if tok := p.scan(); tok.Type != token.COMMA { - break - } - } - - return node, nil -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - switch p.tok.Type { - case token.COLON: - pos := p.tok.Pos - o.Assign = hcltoken.Pos{ - Filename: pos.Filename, - Offset: pos.Offset, - Line: pos.Line, - Column: pos.Column, - } - - o.Val, err = p.objectValue() - if err != nil { - return nil, err - } - } - - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - return nil, errEofToken - case token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{ - Token: p.tok.HCLToken(), - }) - case token.COLON: - // If we have a zero keycount it means that we never got - // an object key, i.e. `{ :`. This is a syntax error. - if keyCount == 0 { - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - - // Done - return keys, nil - case token.ILLEGAL: - return nil, errors.New("illegal") - default: - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) objectValue() (ast.Node, error) { - defer un(trace(p, "ParseObjectValue")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok) -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (*ast.ObjectType, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.LBRACE: - return p.objectType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok) -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{} - - l, err := p.objectList() - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - o.List = l - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{} - - for { - tok := p.scan() - switch tok.Type { - case token.NUMBER, token.FLOAT, token.STRING: - node, err := p.literalType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.COMMA: - continue - case token.LBRACE: - node, err := p.objectType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.BOOL: - // TODO(arslan) should we support? not supported by HCL yet - case token.LBRACK: - // TODO(arslan) should we support nested lists? Even though it's - // written in README of HCL, it's not a part of the grammar - // (not defined in parse.y) - case token.RBRACK: - // finished - return l, nil - default: - return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type) - } - - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok.HCLToken(), - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - p.tok = p.sc.Scan() - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go deleted file mode 100644 index fe3f0f09..00000000 --- a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go +++ /dev/null @@ -1,451 +0,0 @@ -package scanner - -import ( - "bytes" - "fmt" - "os" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/json/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - if ch == utf8.RuneError && size == 1 { - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - s.err("illegal UTF-8 encoding") - return ch - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } else if lit == "null" { - tok = token.NULL - } else { - s.err("illegal char") - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case ':': - tok = token.COLON - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - s.err("illegal char") - } - default: - s.err("illegal char: " + string(ch)) - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - zero := ch == '0' - pos := s.srcPos - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - - // If we have a larger number and this is zero, error - if zero && pos != s.srcPos { - s.err("numbers cannot start with 0") - } - - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if ch == '\n' || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - for n > 0 && digitVal(ch) < base { - ch = s.next() - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - // we scanned all digits, put the last non digit char back - s.unread() - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isHexadecimal returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isHexadecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/vendor/github.com/hashicorp/hcl/json/token/position.go b/vendor/github.com/hashicorp/hcl/json/token/position.go deleted file mode 100644 index 59c1bb72..00000000 --- a/vendor/github.com/hashicorp/hcl/json/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/vendor/github.com/hashicorp/hcl/json/token/token.go b/vendor/github.com/hashicorp/hcl/json/token/token.go deleted file mode 100644 index 95a0c3ee..00000000 --- a/vendor/github.com/hashicorp/hcl/json/token/token.go +++ /dev/null @@ -1,118 +0,0 @@ -package token - -import ( - "fmt" - "strconv" - - hcltoken "github.com/hashicorp/hcl/hcl/token" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - - identifier_beg - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - NULL // null - literal_end - identifier_end - - operator_beg - LBRACK // [ - LBRACE // { - COMMA // , - PERIOD // . - COLON // : - - RBRACK // ] - RBRACE // } - - operator_end -) - -var tokens = [...]string{ - ILLEGAL: "ILLEGAL", - - EOF: "EOF", - - NUMBER: "NUMBER", - FLOAT: "FLOAT", - BOOL: "BOOL", - STRING: "STRING", - NULL: "NULL", - - LBRACK: "LBRACK", - LBRACE: "LBRACE", - COMMA: "COMMA", - PERIOD: "PERIOD", - COLON: "COLON", - - RBRACK: "RBRACK", - RBRACE: "RBRACE", -} - -// String returns the string corresponding to the token tok. -func (t Type) String() string { - s := "" - if 0 <= t && t < Type(len(tokens)) { - s = tokens[t] - } - if s == "" { - s = "token(" + strconv.Itoa(int(t)) + ")" - } - return s -} - -// IsIdentifier returns true for tokens corresponding to identifiers and basic -// type literals; it returns false otherwise. -func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end } - -// IsLiteral returns true for tokens corresponding to basic type literals; it -// returns false otherwise. -func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end } - -// IsOperator returns true for tokens corresponding to operators and -// delimiters; it returns false otherwise. -func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end } - -// String returns the token's literal text. Note that this is only -// applicable for certain token types, such as token.IDENT, -// token.STRING, etc.. -func (t Token) String() string { - return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text) -} - -// HCLToken converts this token to an HCL token. -// -// The token type must be a literal type or this will panic. -func (t Token) HCLToken() hcltoken.Token { - switch t.Type { - case BOOL: - return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text} - case FLOAT: - return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text} - case NULL: - return hcltoken.Token{Type: hcltoken.STRING, Text: ""} - case NUMBER: - return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text} - case STRING: - return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true} - default: - panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type)) - } -} diff --git a/vendor/github.com/hashicorp/hcl/lex.go b/vendor/github.com/hashicorp/hcl/lex.go deleted file mode 100644 index d9993c29..00000000 --- a/vendor/github.com/hashicorp/hcl/lex.go +++ /dev/null @@ -1,38 +0,0 @@ -package hcl - -import ( - "unicode" - "unicode/utf8" -) - -type lexModeValue byte - -const ( - lexModeUnknown lexModeValue = iota - lexModeHcl - lexModeJson -) - -// lexMode returns whether we're going to be parsing in JSON -// mode or HCL mode. -func lexMode(v []byte) lexModeValue { - var ( - r rune - w int - offset int - ) - - for { - r, w = utf8.DecodeRune(v[offset:]) - offset += w - if unicode.IsSpace(r) { - continue - } - if r == '{' { - return lexModeJson - } - break - } - - return lexModeHcl -} diff --git a/vendor/github.com/hashicorp/hcl/parse.go b/vendor/github.com/hashicorp/hcl/parse.go deleted file mode 100644 index 1fca53c4..00000000 --- a/vendor/github.com/hashicorp/hcl/parse.go +++ /dev/null @@ -1,39 +0,0 @@ -package hcl - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hclParser "github.com/hashicorp/hcl/hcl/parser" - jsonParser "github.com/hashicorp/hcl/json/parser" -) - -// ParseBytes accepts as input byte slice and returns ast tree. -// -// Input can be either JSON or HCL -func ParseBytes(in []byte) (*ast.File, error) { - return parse(in) -} - -// ParseString accepts input as a string and returns ast tree. -func ParseString(input string) (*ast.File, error) { - return parse([]byte(input)) -} - -func parse(in []byte) (*ast.File, error) { - switch lexMode(in) { - case lexModeHcl: - return hclParser.Parse(in) - case lexModeJson: - return jsonParser.Parse(in) - } - - return nil, fmt.Errorf("unknown config format") -} - -// Parse parses the given input and returns the root object. -// -// The input format can be either HCL or JSON. -func Parse(input string) (*ast.File, error) { - return parse([]byte(input)) -} diff --git a/vendor/github.com/magiconair/properties/.gitignore b/vendor/github.com/magiconair/properties/.gitignore deleted file mode 100644 index e7081ff5..00000000 --- a/vendor/github.com/magiconair/properties/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.sublime-project -*.sublime-workspace -*.un~ -*.swp -.idea/ -*.iml diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md deleted file mode 100644 index 842e8e24..00000000 --- a/vendor/github.com/magiconair/properties/CHANGELOG.md +++ /dev/null @@ -1,205 +0,0 @@ -## Changelog - -### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022 - - * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge - - Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch. - - * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions - -### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022 - - * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error - - Thanks to [@ellie](https://github.com/ellie) for the patch. - - * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible - - This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the - author happy until it affects real users. - - Thanks to [@maage](https://github.com/maage) for the patch. - -### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021 - - * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments - - When reading comments \ are loaded correctly, but when writing they are then - replaced by \\. This leads to wrong comments when writing and reading multiple times. - - Thanks to [@doxsch](https://github.com/doxsch) for the patch. - -### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020 - - * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references - - Thanks to [@sriv](https://github.com/sriv) for the patch. - -### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020 - - * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference - - The change is include the key in the error message which is causing the circular - reference when parsing/loading the properties files. - - Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch. - -### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020 - - * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write - - This patch ensures that backslashes are escaped on write. Existing applications which - rely on the old behavior may need to be updated. - - Thanks to [@apesternikov](https://github.com/apesternikov) for the patch. - - * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL() - - Thanks to [@aliras1](https://github.com/aliras1) for the patch. - - * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write() - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - - * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - -### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019 - - * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request - - This patch ensures that in `LoadURL` the response body is always closed. - - Thanks to [@liubog2008](https://github.com/liubog2008) for the patch. - -### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018 - - * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading - - This adds the option to disable property expansion during loading. - - Thanks to [@kmala](https://github.com/kmala) for the patch. - -### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018 - - * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases. - - See PR for an example. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018 - - * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value - - Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail - with a `circular reference error`. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017 - - * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces - - * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled - - Thanks to [@mgurov](https://github.com/mgurov) for the fix. - -### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017 - - * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically - * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map - -### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017 - - * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency - * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc) - -### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017 - - * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER` - * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs - * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy - * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function - -### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016 - - * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL. - * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string. - * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) - -### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015 - - * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. - -### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015 - - * Vendored in gopkg.in/check.v1 - -### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015 - - * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) - -### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015 - - * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. - -### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015 - - * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) - -### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015 - - * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty - * Add clickable links to README - -### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014 - - * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with - [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). - -### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014 - - * Added support for single and multi-line comments (reading, writing and updating) - * The order of keys is now preserved - * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry - * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method - * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) - -### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014 - - * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one - -### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014 - - * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string - -### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014 - - * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys - * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties - -### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014 - -* Added support for time.Duration -* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom) -* Changed default of MustXXX() failure from panic to log.Fatal - -### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014 - -* Added MustGet... functions -* Added support for int and uint with range checks on 32 bit platforms - -### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014 - -* Renamed from goproperties to properties -* Added support for expansion of environment vars in - filenames and value expressions -* Fixed bug where value expressions were not at the - start of the string - -### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014 - -* Initial release diff --git a/vendor/github.com/magiconair/properties/LICENSE.md b/vendor/github.com/magiconair/properties/LICENSE.md deleted file mode 100644 index 79c87e3e..00000000 --- a/vendor/github.com/magiconair/properties/LICENSE.md +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2013-2020, Frank Schroeder - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/magiconair/properties/README.md b/vendor/github.com/magiconair/properties/README.md deleted file mode 100644 index e2edda02..00000000 --- a/vendor/github.com/magiconair/properties/README.md +++ /dev/null @@ -1,128 +0,0 @@ -[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) -[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties) -[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) -[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -# Overview - -#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why. - -properties is a Go library for reading and writing properties files. - -It supports reading from multiple files or URLs and Spring style recursive -property expansion of expressions like `${key}` to their corresponding value. -Value expressions can refer to other keys like in `${key}` or to environment -variables like in `${USER}`. Filenames can also contain environment variables -like in `/home/${USER}/myapp.properties`. - -Properties can be decoded into structs, maps, arrays and values through -struct tags. - -Comments and the order of keys are preserved. Comments can be modified -and can be written to the output. - -The properties library supports both ISO-8859-1 and UTF-8 encoded data. - -Starting from version 1.3.0 the behavior of the MustXXX() functions is -configurable by providing a custom `ErrorHandler` function. The default has -changed from `panic` to `log.Fatal` but this is configurable and custom -error handling functions can be provided. See the package documentation for -details. - -Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -## Getting Started - -```go -import ( - "flag" - "github.com/magiconair/properties" -) - -func main() { - // init from a file - p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) - - // or multiple files - p = properties.MustLoadFiles([]string{ - "${HOME}/config.properties", - "${HOME}/config-${USER}.properties", - }, properties.UTF8, true) - - // or from a map - p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) - - // or from a string - p = properties.MustLoadString("key=value\nabc=def") - - // or from a URL - p = properties.MustLoadURL("http://host/path") - - // or from multiple URLs - p = properties.MustLoadURL([]string{ - "http://host/config", - "http://host/config-${USER}", - }, true) - - // or from flags - p.MustFlag(flag.CommandLine) - - // get values through getters - host := p.MustGetString("host") - port := p.GetInt("port", 8080) - - // or through Decode - type Config struct { - Host string `properties:"host"` - Port int `properties:"port,default=9000"` - Accept []string `properties:"accept,default=image/png;image;gif"` - Timeout time.Duration `properties:"timeout,default=5s"` - } - var cfg Config - if err := p.Decode(&cfg); err != nil { - log.Fatal(err) - } -} - -``` - -## Installation and Upgrade - -``` -$ go get -u github.com/magiconair/properties -``` - -## License - -2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. - -## ToDo - -* Dump contents with passwords and secrets obscured - -## Updated Git tags - -#### 13 Feb 2018 - -I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags -and I've only recently learned that this doesn't play well with `git describe` 😞 - -I have replaced all lightweight tags with signed tags using this script which should -retain the commit date, name and email address. Please run `git pull --tags` to update them. - -Worst case you have to reclone the repo. - -```shell -#!/bin/bash -tag=$1 -echo "Updating $tag" -date=$(git show ${tag}^0 --format=%aD | head -1) -email=$(git show ${tag}^0 --format=%aE | head -1) -name=$(git show ${tag}^0 --format=%aN | head -1) -GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag} -``` - -I apologize for the inconvenience. - -Frank - diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go deleted file mode 100644 index 8e6aa441..00000000 --- a/vendor/github.com/magiconair/properties/decode.go +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "reflect" - "strconv" - "strings" - "time" -) - -// Decode assigns property values to exported fields of a struct. -// -// Decode traverses v recursively and returns an error if a value cannot be -// converted to the field type or a required value is missing for a field. -// -// The following type dependent decodings are used: -// -// String, boolean, numeric fields have the value of the property key assigned. -// The property key name is the name of the field. A different key and a default -// value can be set in the field's tag. Fields without default value are -// required. If the value cannot be converted to the field type an error is -// returned. -// -// time.Duration fields have the result of time.ParseDuration() assigned. -// -// time.Time fields have the vaule of time.Parse() assigned. The default layout -// is time.RFC3339 but can be set in the field's tag. -// -// Arrays and slices of string, boolean, numeric, time.Duration and time.Time -// fields have the value interpreted as a comma separated list of values. The -// individual values are trimmed of whitespace and empty values are ignored. A -// default value can be provided as a semicolon separated list in the field's -// tag. -// -// Struct fields are decoded recursively using the field name plus "." as -// prefix. The prefix (without dot) can be overridden in the field's tag. -// Default values are not supported in the field's tag. Specify them on the -// fields of the inner struct instead. -// -// Map fields must have a key of type string and are decoded recursively by -// using the field's name plus ".' as prefix and the next element of the key -// name as map key. The prefix (without dot) can be overridden in the field's -// tag. Default values are not supported. -// -// Examples: -// -// // Field is ignored. -// Field int `properties:"-"` -// -// // Field is assigned value of 'Field'. -// Field int -// -// // Field is assigned value of 'myName'. -// Field int `properties:"myName"` -// -// // Field is assigned value of key 'myName' and has a default -// // value 15 if the key does not exist. -// Field int `properties:"myName,default=15"` -// -// // Field is assigned value of key 'Field' and has a default -// // value 15 if the key does not exist. -// Field int `properties:",default=15"` -// -// // Field is assigned value of key 'date' and the date -// // is in format 2006-01-02 -// Field time.Time `properties:"date,layout=2006-01-02"` -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas. -// Field []string -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas and has a default -// // value ["a", "b", "c"] if the key does not exist. -// Field []string `properties:",default=a;b;c"` -// -// // Field is decoded recursively with "Field." as key prefix. -// Field SomeStruct -// -// // Field is decoded recursively with "myName." as key prefix. -// Field SomeStruct `properties:"myName"` -// -// // Field is decoded recursively with "Field." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string -// -// // Field is decoded recursively with "myName." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string `properties:"myName"` -func (p *Properties) Decode(x interface{}) error { - t, v := reflect.TypeOf(x), reflect.ValueOf(x) - if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { - return fmt.Errorf("not a pointer to struct: %s", t) - } - if err := dec(p, "", nil, nil, v); err != nil { - return err - } - return nil -} - -func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error { - t := v.Type() - - // value returns the property value for key or the default if provided. - value := func() (string, error) { - if val, ok := p.Get(key); ok { - return val, nil - } - if def != nil { - return *def, nil - } - return "", fmt.Errorf("missing required key %s", key) - } - - // conv converts a string to a value of the given type. - conv := func(s string, t reflect.Type) (val reflect.Value, err error) { - var v interface{} - - switch { - case isDuration(t): - v, err = time.ParseDuration(s) - - case isTime(t): - layout := opts["layout"] - if layout == "" { - layout = time.RFC3339 - } - v, err = time.Parse(layout, s) - - case isBool(t): - v, err = boolVal(s), nil - - case isString(t): - v, err = s, nil - - case isFloat(t): - v, err = strconv.ParseFloat(s, 64) - - case isInt(t): - v, err = strconv.ParseInt(s, 10, 64) - - case isUint(t): - v, err = strconv.ParseUint(s, 10, 64) - - default: - return reflect.Zero(t), fmt.Errorf("unsupported type %s", t) - } - if err != nil { - return reflect.Zero(t), err - } - return reflect.ValueOf(v).Convert(t), nil - } - - // keydef returns the property key and the default value based on the - // name of the struct field and the options in the tag. - keydef := func(f reflect.StructField) (string, *string, map[string]string) { - _key, _opts := parseTag(f.Tag.Get("properties")) - - var _def *string - if d, ok := _opts["default"]; ok { - _def = &d - } - if _key != "" { - return _key, _def, _opts - } - return f.Name, _def, _opts - } - - switch { - case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t): - s, err := value() - if err != nil { - return err - } - val, err := conv(s, t) - if err != nil { - return err - } - v.Set(val) - - case isPtr(t): - return dec(p, key, def, opts, v.Elem()) - - case isStruct(t): - for i := 0; i < v.NumField(); i++ { - fv := v.Field(i) - fk, def, opts := keydef(t.Field(i)) - if !fv.CanSet() { - return fmt.Errorf("cannot set %s", t.Field(i).Name) - } - if fk == "-" { - continue - } - if key != "" { - fk = key + "." + fk - } - if err := dec(p, fk, def, opts, fv); err != nil { - return err - } - } - return nil - - case isArray(t): - val, err := value() - if err != nil { - return err - } - vals := split(val, ";") - a := reflect.MakeSlice(t, 0, len(vals)) - for _, s := range vals { - val, err := conv(s, t.Elem()) - if err != nil { - return err - } - a = reflect.Append(a, val) - } - v.Set(a) - - case isMap(t): - valT := t.Elem() - m := reflect.MakeMap(t) - for postfix := range p.FilterStripPrefix(key + ".").m { - pp := strings.SplitN(postfix, ".", 2) - mk, mv := pp[0], reflect.New(valT) - if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { - return err - } - m.SetMapIndex(reflect.ValueOf(mk), mv.Elem()) - } - v.Set(m) - - default: - return fmt.Errorf("unsupported type %s", t) - } - return nil -} - -// split splits a string on sep, trims whitespace of elements -// and omits empty elements -func split(s string, sep string) []string { - var a []string - for _, v := range strings.Split(s, sep) { - if v = strings.TrimSpace(v); v != "" { - a = append(a, v) - } - } - return a -} - -// parseTag parses a "key,k=v,k=v,..." -func parseTag(tag string) (key string, opts map[string]string) { - opts = map[string]string{} - for i, s := range strings.Split(tag, ",") { - if i == 0 { - key = s - continue - } - - pp := strings.SplitN(s, "=", 2) - if len(pp) == 1 { - opts[pp[0]] = "" - } else { - opts[pp[0]] = pp[1] - } - } - return key, opts -} - -func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice } -func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } -func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } -func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } -func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } -func isString(t reflect.Type) bool { return t.Kind() == reflect.String } -func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } -func isTime(t reflect.Type) bool { return t == reflect.TypeOf(time.Time{}) } -func isFloat(t reflect.Type) bool { - return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 -} -func isInt(t reflect.Type) bool { - return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64 -} -func isUint(t reflect.Type) bool { - return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64 -} diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go deleted file mode 100644 index 7c797931..00000000 --- a/vendor/github.com/magiconair/properties/doc.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package properties provides functions for reading and writing -// ISO-8859-1 and UTF-8 encoded .properties files and has -// support for recursive property expansion. -// -// Java properties files are ISO-8859-1 encoded and use Unicode -// literals for characters outside the ISO character set. Unicode -// literals can be used in UTF-8 encoded properties files but -// aren't necessary. -// -// To load a single properties file use MustLoadFile(): -// -// p := properties.MustLoadFile(filename, properties.UTF8) -// -// To load multiple properties files use MustLoadFiles() -// which loads the files in the given order and merges the -// result. Missing properties files can be ignored if the -// 'ignoreMissing' flag is set to true. -// -// Filenames can contain environment variables which are expanded -// before loading. -// -// f1 := "/etc/myapp/myapp.conf" -// f2 := "/home/${USER}/myapp.conf" -// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) -// -// All of the different key/value delimiters ' ', ':' and '=' are -// supported as well as the comment characters '!' and '#' and -// multi-line values. -// -// ! this is a comment -// # and so is this -// -// # the following expressions are equal -// key value -// key=value -// key:value -// key = value -// key : value -// key = val\ -// ue -// -// Properties stores all comments preceding a key and provides -// GetComments() and SetComments() methods to retrieve and -// update them. The convenience functions GetComment() and -// SetComment() allow access to the last comment. The -// WriteComment() method writes properties files including -// the comments and with the keys in the original order. -// This can be used for sanitizing properties files. -// -// Property expansion is recursive and circular references -// and malformed expressions are not allowed and cause an -// error. Expansion of environment variables is supported. -// -// # standard property -// key = value -// -// # property expansion: key2 = value -// key2 = ${key} -// -// # recursive expansion: key3 = value -// key3 = ${key2} -// -// # circular reference (error) -// key = ${key} -// -// # malformed expression (error) -// key = ${ke -// -// # refers to the users' home dir -// home = ${HOME} -// -// # local key takes precedence over env var: u = foo -// USER = foo -// u = ${USER} -// -// The default property expansion format is ${key} but can be -// changed by setting different pre- and postfix values on the -// Properties object. -// -// p := properties.NewProperties() -// p.Prefix = "#[" -// p.Postfix = "]#" -// -// Properties provides convenience functions for getting typed -// values with default values if the key does not exist or the -// type conversion failed. -// -// # Returns true if the value is either "1", "on", "yes" or "true" -// # Returns false for every other value and the default value if -// # the key does not exist. -// v = p.GetBool("key", false) -// -// # Returns the value if the key exists and the format conversion -// # was successful. Otherwise, the default value is returned. -// v = p.GetInt64("key", 999) -// v = p.GetUint64("key", 999) -// v = p.GetFloat64("key", 123.0) -// v = p.GetString("key", "def") -// v = p.GetDuration("key", 999) -// -// As an alternative properties may be applied with the standard -// library's flag implementation at any time. -// -// # Standard configuration -// v = flag.Int("key", 999, "help message") -// flag.Parse() -// -// # Merge p into the flag set -// p.MustFlag(flag.CommandLine) -// -// Properties provides several MustXXX() convenience functions -// which will terminate the app if an error occurs. The behavior -// of the failure is configurable and the default is to call -// log.Fatal(err). To have the MustXXX() functions panic instead -// of logging the error set a different ErrorHandler before -// you use the Properties package. -// -// properties.ErrorHandler = properties.PanicHandler -// -// # Will panic instead of logging an error -// p := properties.MustLoadFile("config.properties") -// -// You can also provide your own ErrorHandler function. The only requirement -// is that the error handler function must exit after handling the error. -// -// properties.ErrorHandler = func(err error) { -// fmt.Println(err) -// os.Exit(1) -// } -// -// # Will write to stdout and then exit -// p := properties.MustLoadFile("config.properties") -// -// Properties can also be loaded into a struct via the `Decode` -// method, e.g. -// -// type S struct { -// A string `properties:"a,default=foo"` -// D time.Duration `properties:"timeout,default=5s"` -// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` -// } -// -// See `Decode()` method for the full documentation. -// -// The following documents provide a description of the properties -// file format. -// -// http://en.wikipedia.org/wiki/.properties -// -// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 -package properties diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go deleted file mode 100644 index 35d0ae97..00000000 --- a/vendor/github.com/magiconair/properties/integrate.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import "flag" - -// MustFlag sets flags that are skipped by dst.Parse when p contains -// the respective key for flag.Flag.Name. -// -// It's use is recommended with command line arguments as in: -// -// flag.Parse() -// p.MustFlag(flag.CommandLine) -func (p *Properties) MustFlag(dst *flag.FlagSet) { - m := make(map[string]*flag.Flag) - dst.VisitAll(func(f *flag.Flag) { - m[f.Name] = f - }) - dst.Visit(func(f *flag.Flag) { - delete(m, f.Name) // overridden - }) - - for name, f := range m { - v, ok := p.Get(name) - if !ok { - continue - } - - if err := f.Value.Set(v); err != nil { - ErrorHandler(err) - } - } -} diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go deleted file mode 100644 index 3d15a1f6..00000000 --- a/vendor/github.com/magiconair/properties/lex.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Parts of the lexer are from the template/text/parser package -// For these parts the following applies: -// -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file of the go 1.2 -// distribution. - -package properties - -import ( - "fmt" - "strconv" - "strings" - "unicode/utf8" -) - -// item represents a token or text string returned from the scanner. -type item struct { - typ itemType // The type of this item. - pos int // The starting position, in bytes, of this item in the input string. - val string // The value of this item. -} - -func (i item) String() string { - switch { - case i.typ == itemEOF: - return "EOF" - case i.typ == itemError: - return i.val - case len(i.val) > 10: - return fmt.Sprintf("%.10q...", i.val) - } - return fmt.Sprintf("%q", i.val) -} - -// itemType identifies the type of lex items. -type itemType int - -const ( - itemError itemType = iota // error occurred; value is text of error - itemEOF - itemKey // a key - itemValue // a value - itemComment // a comment -) - -// defines a constant for EOF -const eof = -1 - -// permitted whitespace characters space, FF and TAB -const whitespace = " \f\t" - -// stateFn represents the state of the scanner as a function that returns the next state. -type stateFn func(*lexer) stateFn - -// lexer holds the state of the scanner. -type lexer struct { - input string // the string being scanned - state stateFn // the next lexing function to enter - pos int // current position in the input - start int // start position of this item - width int // width of last rune read from input - lastPos int // position of most recent item returned by nextItem - runes []rune // scanned runes for this item - items chan item // channel of scanned items -} - -// next returns the next rune in the input. -func (l *lexer) next() rune { - if l.pos >= len(l.input) { - l.width = 0 - return eof - } - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = w - l.pos += l.width - return r -} - -// peek returns but does not consume the next rune in the input. -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one rune. Can only be called once per call of next. -func (l *lexer) backup() { - l.pos -= l.width -} - -// emit passes an item back to the client. -func (l *lexer) emit(t itemType) { - i := item{t, l.start, string(l.runes)} - l.items <- i - l.start = l.pos - l.runes = l.runes[:0] -} - -// ignore skips over the pending input before this point. -func (l *lexer) ignore() { - l.start = l.pos -} - -// appends the rune to the current value -func (l *lexer) appendRune(r rune) { - l.runes = append(l.runes, r) -} - -// accept consumes the next rune if it's from the valid set. -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - l.backup() - return false -} - -// acceptRun consumes a run of runes from the valid set. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// lineNumber reports which line we're on, based on the position of -// the previous item returned by nextItem. Doing it this way -// means we don't have to worry about peek double counting. -func (l *lexer) lineNumber() int { - return 1 + strings.Count(l.input[:l.lastPos], "\n") -} - -// errorf returns an error token and terminates the scan by passing -// back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { - l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} - return nil -} - -// nextItem returns the next item from the input. -func (l *lexer) nextItem() item { - i := <-l.items - l.lastPos = i.pos - return i -} - -// lex creates a new scanner for the input string. -func lex(input string) *lexer { - l := &lexer{ - input: input, - items: make(chan item), - runes: make([]rune, 0, 32), - } - go l.run() - return l -} - -// run runs the state machine for the lexer. -func (l *lexer) run() { - for l.state = lexBeforeKey(l); l.state != nil; { - l.state = l.state(l) - } -} - -// state functions - -// lexBeforeKey scans until a key begins. -func lexBeforeKey(l *lexer) stateFn { - switch r := l.next(); { - case isEOF(r): - l.emit(itemEOF) - return nil - - case isEOL(r): - l.ignore() - return lexBeforeKey - - case isComment(r): - return lexComment - - case isWhitespace(r): - l.ignore() - return lexBeforeKey - - default: - l.backup() - return lexKey - } -} - -// lexComment scans a comment line. The comment character has already been scanned. -func lexComment(l *lexer) stateFn { - l.acceptRun(whitespace) - l.ignore() - for { - switch r := l.next(); { - case isEOF(r): - l.ignore() - l.emit(itemEOF) - return nil - case isEOL(r): - l.emit(itemComment) - return lexBeforeKey - default: - l.appendRune(r) - } - } -} - -// lexKey scans the key up to a delimiter -func lexKey(l *lexer) stateFn { - var r rune - -Loop: - for { - switch r = l.next(); { - - case isEscape(r): - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - - case isEndOfKey(r): - l.backup() - break Loop - - case isEOF(r): - break Loop - - default: - l.appendRune(r) - } - } - - if len(l.runes) > 0 { - l.emit(itemKey) - } - - if isEOF(r) { - l.emit(itemEOF) - return nil - } - - return lexBeforeValue -} - -// lexBeforeValue scans the delimiter between key and value. -// Leading and trailing whitespace is ignored. -// We expect to be just after the key. -func lexBeforeValue(l *lexer) stateFn { - l.acceptRun(whitespace) - l.accept(":=") - l.acceptRun(whitespace) - l.ignore() - return lexValue -} - -// lexValue scans text until the end of the line. We expect to be just after the delimiter. -func lexValue(l *lexer) stateFn { - for { - switch r := l.next(); { - case isEscape(r): - if isEOL(l.peek()) { - l.next() - l.acceptRun(whitespace) - } else { - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - } - - case isEOL(r): - l.emit(itemValue) - l.ignore() - return lexBeforeKey - - case isEOF(r): - l.emit(itemValue) - l.emit(itemEOF) - return nil - - default: - l.appendRune(r) - } - } -} - -// scanEscapeSequence scans either one of the escaped characters -// or a unicode literal. We expect to be after the escape character. -func (l *lexer) scanEscapeSequence() error { - switch r := l.next(); { - - case isEscapedCharacter(r): - l.appendRune(decodeEscapedCharacter(r)) - return nil - - case atUnicodeLiteral(r): - return l.scanUnicodeLiteral() - - case isEOF(r): - return fmt.Errorf("premature EOF") - - // silently drop the escape character and append the rune as is - default: - l.appendRune(r) - return nil - } -} - -// scans a unicode literal in the form \uXXXX. We expect to be after the \u. -func (l *lexer) scanUnicodeLiteral() error { - // scan the digits - d := make([]rune, 4) - for i := 0; i < 4; i++ { - d[i] = l.next() - if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) { - return fmt.Errorf("invalid unicode literal") - } - } - - // decode the digits into a rune - r, err := strconv.ParseInt(string(d), 16, 0) - if err != nil { - return err - } - - l.appendRune(rune(r)) - return nil -} - -// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character. -func decodeEscapedCharacter(r rune) rune { - switch r { - case 'f': - return '\f' - case 'n': - return '\n' - case 'r': - return '\r' - case 't': - return '\t' - default: - return r - } -} - -// atUnicodeLiteral reports whether we are at a unicode literal. -// The escape character has already been consumed. -func atUnicodeLiteral(r rune) bool { - return r == 'u' -} - -// isComment reports whether we are at the start of a comment. -func isComment(r rune) bool { - return r == '#' || r == '!' -} - -// isEndOfKey reports whether the rune terminates the current key. -func isEndOfKey(r rune) bool { - return strings.ContainsRune(" \f\t\r\n:=", r) -} - -// isEOF reports whether we are at EOF. -func isEOF(r rune) bool { - return r == eof -} - -// isEOL reports whether we are at a new line character. -func isEOL(r rune) bool { - return r == '\n' || r == '\r' -} - -// isEscape reports whether the rune is the escape character which -// prefixes unicode literals and other escaped characters. -func isEscape(r rune) bool { - return r == '\\' -} - -// isEscapedCharacter reports whether we are at one of the characters that need escaping. -// The escape character has already been consumed. -func isEscapedCharacter(r rune) bool { - return strings.ContainsRune(" :=fnrt", r) -} - -// isWhitespace reports whether the rune is a whitespace character. -func isWhitespace(r rune) bool { - return strings.ContainsRune(whitespace, r) -} diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go deleted file mode 100644 index 635368dc..00000000 --- a/vendor/github.com/magiconair/properties/load.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "strings" -) - -// Encoding specifies encoding of the input data. -type Encoding uint - -const ( - // utf8Default is a private placeholder for the zero value of Encoding to - // ensure that it has the correct meaning. UTF8 is the default encoding but - // was assigned a non-zero value which cannot be changed without breaking - // existing code. Clients should continue to use the public constants. - utf8Default Encoding = iota - - // UTF8 interprets the input data as UTF-8. - UTF8 - - // ISO_8859_1 interprets the input data as ISO-8859-1. - ISO_8859_1 -) - -type Loader struct { - // Encoding determines how the data from files and byte buffers - // is interpreted. For URLs the Content-Type header is used - // to determine the encoding of the data. - Encoding Encoding - - // DisableExpansion configures the property expansion of the - // returned property object. When set to true, the property values - // will not be expanded and the Property object will not be checked - // for invalid expansion expressions. - DisableExpansion bool - - // IgnoreMissing configures whether missing files or URLs which return - // 404 are reported as errors. When set to true, missing files and 404 - // status codes are not reported as errors. - IgnoreMissing bool -} - -// Load reads a buffer into a Properties struct. -func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { - return l.loadBytes(buf, l.Encoding) -} - -// LoadAll reads the content of multiple URLs or files in the given order into -// a Properties struct. If IgnoreMissing is true then a 404 status code or -// missing file will not be reported as error. Encoding sets the encoding for -// files. For the URLs see LoadURL for the Content-Type header and the -// encoding. -func (l *Loader) LoadAll(names []string) (*Properties, error) { - all := NewProperties() - for _, name := range names { - n, err := expandName(name) - if err != nil { - return nil, err - } - - var p *Properties - switch { - case strings.HasPrefix(n, "http://"): - p, err = l.LoadURL(n) - case strings.HasPrefix(n, "https://"): - p, err = l.LoadURL(n) - default: - p, err = l.LoadFile(n) - } - if err != nil { - return nil, err - } - all.Merge(p) - } - - all.DisableExpansion = l.DisableExpansion - if all.DisableExpansion { - return all, nil - } - return all, all.check() -} - -// LoadFile reads a file into a Properties struct. -// If IgnoreMissing is true then a missing file will not be -// reported as error. -func (l *Loader) LoadFile(filename string) (*Properties, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - if l.IgnoreMissing && os.IsNotExist(err) { - LogPrintf("properties: %s not found. skipping", filename) - return NewProperties(), nil - } - return nil, err - } - return l.loadBytes(data, l.Encoding) -} - -// LoadURL reads the content of the URL into a Properties struct. -// -// The encoding is determined via the Content-Type header which -// should be set to 'text/plain'. If the 'charset' parameter is -// missing, 'iso-8859-1' or 'latin1' the encoding is set to -// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the -// encoding is set to UTF-8. A missing content type header is -// interpreted as 'text/plain; charset=utf-8'. -func (l *Loader) LoadURL(url string) (*Properties, error) { - resp, err := http.Get(url) - if err != nil { - return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) - } - defer resp.Body.Close() - - if resp.StatusCode == 404 && l.IgnoreMissing { - LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) - return NewProperties(), nil - } - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) - } - - ct := resp.Header.Get("Content-Type") - ct = strings.Join(strings.Fields(ct), "") - var enc Encoding - switch strings.ToLower(ct) { - case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1": - enc = ISO_8859_1 - case "", "text/plain;charset=utf-8": - enc = UTF8 - default: - return nil, fmt.Errorf("properties: invalid content type %s", ct) - } - - return l.loadBytes(body, enc) -} - -func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { - p, err := parse(convert(buf, enc)) - if err != nil { - return nil, err - } - p.DisableExpansion = l.DisableExpansion - if p.DisableExpansion { - return p, nil - } - return p, p.check() -} - -// Load reads a buffer into a Properties struct. -func Load(buf []byte, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadBytes(buf) -} - -// LoadString reads an UTF8 string into a properties struct. -func LoadString(s string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadBytes([]byte(s)) -} - -// LoadMap creates a new Properties struct from a string map. -func LoadMap(m map[string]string) *Properties { - p := NewProperties() - for k, v := range m { - p.Set(k, v) - } - return p -} - -// LoadFile reads a file into a Properties struct. -func LoadFile(filename string, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadAll([]string{filename}) -} - -// LoadFiles reads multiple files in the given order into -// a Properties struct. If 'ignoreMissing' is true then -// non-existent files will not be reported as error. -func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(filenames) -} - -// LoadURL reads the content of the URL into a Properties struct. -// See Loader#LoadURL for details. -func LoadURL(url string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadAll([]string{url}) -} - -// LoadURLs reads the content of multiple URLs in the given order into a -// Properties struct. If IgnoreMissing is true then a 404 status code will -// not be reported as error. See Loader#LoadURL for the Content-Type header -// and the encoding. -func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} - return l.LoadAll(urls) -} - -// LoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. -func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(names) -} - -// MustLoadString reads an UTF8 string into a Properties struct and -// panics on error. -func MustLoadString(s string) *Properties { - return must(LoadString(s)) -} - -// MustLoadFile reads a file into a Properties struct and -// panics on error. -func MustLoadFile(filename string, enc Encoding) *Properties { - return must(LoadFile(filename, enc)) -} - -// MustLoadFiles reads multiple files in the given order into -// a Properties struct and panics on error. If 'ignoreMissing' -// is true then non-existent files will not be reported as error. -func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadFiles(filenames, enc, ignoreMissing)) -} - -// MustLoadURL reads the content of a URL into a Properties struct and -// panics on error. -func MustLoadURL(url string) *Properties { - return must(LoadURL(url)) -} - -// MustLoadURLs reads the content of multiple URLs in the given order into a -// Properties struct and panics on error. If 'ignoreMissing' is true then a 404 -// status code will not be reported as error. -func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { - return must(LoadURLs(urls, ignoreMissing)) -} - -// MustLoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. It panics on error. -func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadAll(names, enc, ignoreMissing)) -} - -func must(p *Properties, err error) *Properties { - if err != nil { - ErrorHandler(err) - } - return p -} - -// expandName expands ${ENV_VAR} expressions in a name. -// If the environment variable does not exist then it will be replaced -// with an empty string. Malformed expressions like "${ENV_VAR" will -// be reported as error. -func expandName(name string) (string, error) { - return expand(name, []string{}, "${", "}", make(map[string]string)) -} - -// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. -// For ISO-8859-1 we can convert each byte straight into a rune since the -// first 256 unicode code points cover ISO-8859-1. -func convert(buf []byte, enc Encoding) string { - switch enc { - case utf8Default, UTF8: - return string(buf) - case ISO_8859_1: - runes := make([]rune, len(buf)) - for i, b := range buf { - runes[i] = rune(b) - } - return string(runes) - default: - ErrorHandler(fmt.Errorf("unsupported encoding %v", enc)) - } - panic("ErrorHandler should exit") -} diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go deleted file mode 100644 index fccfd39f..00000000 --- a/vendor/github.com/magiconair/properties/parser.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "runtime" -) - -type parser struct { - lex *lexer -} - -func parse(input string) (properties *Properties, err error) { - p := &parser{lex: lex(input)} - defer p.recover(&err) - - properties = NewProperties() - key := "" - comments := []string{} - - for { - token := p.expectOneOf(itemComment, itemKey, itemEOF) - switch token.typ { - case itemEOF: - goto done - case itemComment: - comments = append(comments, token.val) - continue - case itemKey: - key = token.val - if _, ok := properties.m[key]; !ok { - properties.k = append(properties.k, key) - } - } - - token = p.expectOneOf(itemValue, itemEOF) - if len(comments) > 0 { - properties.c[key] = comments - comments = []string{} - } - switch token.typ { - case itemEOF: - properties.m[key] = "" - goto done - case itemValue: - properties.m[key] = token.val - } - } - -done: - return properties, nil -} - -func (p *parser) errorf(format string, args ...interface{}) { - format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format) - panic(fmt.Errorf(format, args...)) -} - -func (p *parser) expectOneOf(expected ...itemType) (token item) { - token = p.lex.nextItem() - for _, v := range expected { - if token.typ == v { - return token - } - } - p.unexpected(token) - panic("unexpected token") -} - -func (p *parser) unexpected(token item) { - p.errorf(token.String()) -} - -// recover is the handler that turns panics into returns from the top level of Parse. -func (p *parser) recover(errp *error) { - e := recover() - if e != nil { - if _, ok := e.(runtime.Error); ok { - panic(e) - } - *errp = e.(error) - } -} diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go deleted file mode 100644 index fb2f7b40..00000000 --- a/vendor/github.com/magiconair/properties/properties.go +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer. -// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. - -import ( - "bytes" - "fmt" - "io" - "log" - "os" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -const maxExpansionDepth = 64 - -// ErrorHandlerFunc defines the type of function which handles failures -// of the MustXXX() functions. An error handler function must exit -// the application after handling the error. -type ErrorHandlerFunc func(error) - -// ErrorHandler is the function which handles failures of the MustXXX() -// functions. The default is LogFatalHandler. -var ErrorHandler ErrorHandlerFunc = LogFatalHandler - -// LogHandlerFunc defines the function prototype for logging errors. -type LogHandlerFunc func(fmt string, args ...interface{}) - -// LogPrintf defines a log handler which uses log.Printf. -var LogPrintf LogHandlerFunc = log.Printf - -// LogFatalHandler handles the error by logging a fatal error and exiting. -func LogFatalHandler(err error) { - log.Fatal(err) -} - -// PanicHandler handles the error by panicking. -func PanicHandler(err error) { - panic(err) -} - -// ----------------------------------------------------------------------------- - -// A Properties contains the key/value pairs from the properties input. -// All values are stored in unexpanded form and are expanded at runtime -type Properties struct { - // Pre-/Postfix for property expansion. - Prefix string - Postfix string - - // DisableExpansion controls the expansion of properties on Get() - // and the check for circular references on Set(). When set to - // true Properties behaves like a simple key/value store and does - // not check for circular references on Get() or on Set(). - DisableExpansion bool - - // Stores the key/value pairs - m map[string]string - - // Stores the comments per key. - c map[string][]string - - // Stores the keys in order of appearance. - k []string - - // WriteSeparator specifies the separator of key and value while writing the properties. - WriteSeparator string -} - -// NewProperties creates a new Properties struct with the default -// configuration for "${key}" expressions. -func NewProperties() *Properties { - return &Properties{ - Prefix: "${", - Postfix: "}", - m: map[string]string{}, - c: map[string][]string{}, - k: []string{}, - } -} - -// Load reads a buffer into the given Properties struct. -func (p *Properties) Load(buf []byte, enc Encoding) error { - l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} - newProperties, err := l.LoadBytes(buf) - if err != nil { - return err - } - p.Merge(newProperties) - return nil -} - -// Get returns the expanded value for the given key if exists. -// Otherwise, ok is false. -func (p *Properties) Get(key string) (value string, ok bool) { - v, ok := p.m[key] - if p.DisableExpansion { - return v, ok - } - if !ok { - return "", false - } - - expanded, err := p.expand(key, v) - - // we guarantee that the expanded value is free of - // circular references and malformed expressions - // so we panic if we still get an error here. - if err != nil { - ErrorHandler(err) - } - - return expanded, true -} - -// MustGet returns the expanded value for the given key if exists. -// Otherwise, it panics. -func (p *Properties) MustGet(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// ClearComments removes the comments for all keys. -func (p *Properties) ClearComments() { - p.c = map[string][]string{} -} - -// ---------------------------------------------------------------------------- - -// GetComment returns the last comment before the given key or an empty string. -func (p *Properties) GetComment(key string) string { - comments, ok := p.c[key] - if !ok || len(comments) == 0 { - return "" - } - return comments[len(comments)-1] -} - -// ---------------------------------------------------------------------------- - -// GetComments returns all comments that appeared before the given key or nil. -func (p *Properties) GetComments(key string) []string { - if comments, ok := p.c[key]; ok { - return comments - } - return nil -} - -// ---------------------------------------------------------------------------- - -// SetComment sets the comment for the key. -func (p *Properties) SetComment(key, comment string) { - p.c[key] = []string{comment} -} - -// ---------------------------------------------------------------------------- - -// SetComments sets the comments for the key. If the comments are nil then -// all comments for this key are deleted. -func (p *Properties) SetComments(key string, comments []string) { - if comments == nil { - delete(p.c, key) - return - } - p.c[key] = comments -} - -// ---------------------------------------------------------------------------- - -// GetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the default value is returned. -func (p *Properties) GetBool(key string, def bool) bool { - v, err := p.getBool(key) - if err != nil { - return def - } - return v -} - -// MustGetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the function panics. -func (p *Properties) MustGetBool(key string) bool { - v, err := p.getBool(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getBool(key string) (value bool, err error) { - if v, ok := p.Get(key); ok { - return boolVal(v), nil - } - return false, invalidKeyError(key) -} - -func boolVal(v string) bool { - v = strings.ToLower(v) - return v == "1" || v == "true" || v == "yes" || v == "on" -} - -// ---------------------------------------------------------------------------- - -// GetDuration parses the expanded value as an time.Duration (in ns) if the -// key exists. If key does not exist or the value cannot be parsed the default -// value is returned. In almost all cases you want to use GetParsedDuration(). -func (p *Properties) GetDuration(key string, def time.Duration) time.Duration { - v, err := p.getInt64(key) - if err != nil { - return def - } - return time.Duration(v) -} - -// MustGetDuration parses the expanded value as an time.Duration (in ns) if -// the key exists. If key does not exist or the value cannot be parsed the -// function panics. In almost all cases you want to use MustGetParsedDuration(). -func (p *Properties) MustGetDuration(key string) time.Duration { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return time.Duration(v) -} - -// ---------------------------------------------------------------------------- - -// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration { - s, ok := p.Get(key) - if !ok { - return def - } - v, err := time.ParseDuration(s) - if err != nil { - return def - } - return v -} - -// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetParsedDuration(key string) time.Duration { - s, ok := p.Get(key) - if !ok { - ErrorHandler(invalidKeyError(key)) - } - v, err := time.ParseDuration(s) - if err != nil { - ErrorHandler(err) - } - return v -} - -// ---------------------------------------------------------------------------- - -// GetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetFloat64(key string, def float64) float64 { - v, err := p.getFloat64(key) - if err != nil { - return def - } - return v -} - -// MustGetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetFloat64(key string) float64 { - v, err := p.getFloat64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getFloat64(key string) (value float64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseFloat(v, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetInt(key string, def int) int { - v, err := p.getInt64(key) - if err != nil { - return def - } - return intRangeCheck(key, v) -} - -// MustGetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetInt(key string) int { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return intRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetInt64 parses the expanded value as an int64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetInt64(key string, def int64) int64 { - v, err := p.getInt64(key) - if err != nil { - return def - } - return v -} - -// MustGetInt64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetInt64(key string) int64 { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getInt64(key string) (value int64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseInt(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetUint parses the expanded value as an uint if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetUint(key string, def uint) uint { - v, err := p.getUint64(key) - if err != nil { - return def - } - return uintRangeCheck(key, v) -} - -// MustGetUint parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetUint(key string) uint { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return uintRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetUint64 parses the expanded value as an uint64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetUint64(key string, def uint64) uint64 { - v, err := p.getUint64(key) - if err != nil { - return def - } - return v -} - -// MustGetUint64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetUint64(key string) uint64 { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getUint64(key string) (value uint64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseUint(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetString returns the expanded value for the given key if exists or -// the default value otherwise. -func (p *Properties) GetString(key, def string) string { - if v, ok := p.Get(key); ok { - return v - } - return def -} - -// MustGetString returns the expanded value for the given key if exists or -// panics otherwise. -func (p *Properties) MustGetString(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// Filter returns a new properties object which contains all properties -// for which the key matches the pattern. -func (p *Properties) Filter(pattern string) (*Properties, error) { - re, err := regexp.Compile(pattern) - if err != nil { - return nil, err - } - - return p.FilterRegexp(re), nil -} - -// FilterRegexp returns a new properties object which contains all properties -// for which the key matches the regular expression. -func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { - pp := NewProperties() - for _, k := range p.k { - if re.MatchString(k) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterPrefix returns a new properties object with a subset of all keys -// with the given prefix. -func (p *Properties) FilterPrefix(prefix string) *Properties { - pp := NewProperties() - for _, k := range p.k { - if strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterStripPrefix returns a new properties object with a subset of all keys -// with the given prefix and the prefix removed from the keys. -func (p *Properties) FilterStripPrefix(prefix string) *Properties { - pp := NewProperties() - n := len(prefix) - for _, k := range p.k { - if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference - // TODO(fs): this function should probably return an error but the signature is fixed - pp.Set(k[n:], p.m[k]) - } - } - return pp -} - -// Len returns the number of keys. -func (p *Properties) Len() int { - return len(p.m) -} - -// Keys returns all keys in the same order as in the input. -func (p *Properties) Keys() []string { - keys := make([]string, len(p.k)) - copy(keys, p.k) - return keys -} - -// Set sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. If the value contains a -// circular reference or a malformed expression then -// an error is returned. -// An empty key is silently ignored. -func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { - if key == "" { - return "", false, nil - } - - // if expansion is disabled we allow circular references - if p.DisableExpansion { - prev, ok = p.Get(key) - p.m[key] = value - if !ok { - p.k = append(p.k, key) - } - return prev, ok, nil - } - - // to check for a circular reference we temporarily need - // to set the new value. If there is an error then revert - // to the previous state. Only if all tests are successful - // then we add the key to the p.k list. - prev, ok = p.Get(key) - p.m[key] = value - - // now check for a circular reference - _, err = p.expand(key, value) - if err != nil { - - // revert to the previous state - if ok { - p.m[key] = prev - } else { - delete(p.m, key) - } - - return "", false, err - } - - if !ok { - p.k = append(p.k, key) - } - - return prev, ok, nil -} - -// SetValue sets property key to the default string value -// as defined by fmt.Sprintf("%v"). -func (p *Properties) SetValue(key string, value interface{}) error { - _, _, err := p.Set(key, fmt.Sprintf("%v", value)) - return err -} - -// MustSet sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. An empty key is silently ignored. -func (p *Properties) MustSet(key, value string) (prev string, ok bool) { - prev, ok, err := p.Set(key, value) - if err != nil { - ErrorHandler(err) - } - return prev, ok -} - -// String returns a string of all expanded 'key = value' pairs. -func (p *Properties) String() string { - var s string - for _, key := range p.k { - value, _ := p.Get(key) - s = fmt.Sprintf("%s%s = %s\n", s, key, value) - } - return s -} - -// Sort sorts the properties keys in alphabetical order. -// This is helpfully before writing the properties. -func (p *Properties) Sort() { - sort.Strings(p.k) -} - -// Write writes all unexpanded 'key = value' pairs to the given writer. -// Write returns the number of bytes written and any write error encountered. -func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { - return p.WriteComment(w, "", enc) -} - -// WriteComment writes all unexpanced 'key = value' pairs to the given writer. -// If prefix is not empty then comments are written with a blank line and the -// given prefix. The prefix should be either "# " or "! " to be compatible with -// the properties file format. Otherwise, the properties parser will not be -// able to read the file back in. It returns the number of bytes written and -// any write error encountered. -func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) { - var x int - - for _, key := range p.k { - value := p.m[key] - - if prefix != "" { - if comments, ok := p.c[key]; ok { - // don't print comments if they are all empty - allEmpty := true - for _, c := range comments { - if c != "" { - allEmpty = false - break - } - } - - if !allEmpty { - // add a blank line between entries but not at the top - if len(comments) > 0 && n > 0 { - x, err = fmt.Fprintln(w) - if err != nil { - return - } - n += x - } - - for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) - if err != nil { - return - } - n += x - } - } - } - } - sep := " = " - if p.WriteSeparator != "" { - sep = p.WriteSeparator - } - x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc)) - if err != nil { - return - } - n += x - } - return -} - -// Map returns a copy of the properties as a map. -func (p *Properties) Map() map[string]string { - m := make(map[string]string) - for k, v := range p.m { - m[k] = v - } - return m -} - -// FilterFunc returns a copy of the properties which includes the values which passed all filters. -func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { - pp := NewProperties() -outer: - for k, v := range p.m { - for _, f := range filters { - if !f(k, v) { - continue outer - } - pp.Set(k, v) - } - } - return pp -} - -// ---------------------------------------------------------------------------- - -// Delete removes the key and its comments. -func (p *Properties) Delete(key string) { - delete(p.m, key) - delete(p.c, key) - newKeys := []string{} - for _, k := range p.k { - if k != key { - newKeys = append(newKeys, k) - } - } - p.k = newKeys -} - -// Merge merges properties, comments and keys from other *Properties into p -func (p *Properties) Merge(other *Properties) { - for _, k := range other.k { - if _, ok := p.m[k]; !ok { - p.k = append(p.k, k) - } - } - for k, v := range other.m { - p.m[k] = v - } - for k, v := range other.c { - p.c[k] = v - } -} - -// ---------------------------------------------------------------------------- - -// check expands all values and returns an error if a circular reference or -// a malformed expression was found. -func (p *Properties) check() error { - for key, value := range p.m { - if _, err := p.expand(key, value); err != nil { - return err - } - } - return nil -} - -func (p *Properties) expand(key, input string) (string, error) { - // no pre/postfix -> nothing to expand - if p.Prefix == "" && p.Postfix == "" { - return input, nil - } - - return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) -} - -// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. -// The function keeps track of the keys that were already expanded and stops if it -// detects a circular reference or a malformed expression of the form '(prefix)key'. -func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { - if len(keys) > maxExpansionDepth { - return "", fmt.Errorf("expansion too deep") - } - - for { - start := strings.Index(s, prefix) - if start == -1 { - return s, nil - } - - keyStart := start + len(prefix) - keyLen := strings.Index(s[keyStart:], postfix) - if keyLen == -1 { - return "", fmt.Errorf("malformed expression") - } - - end := keyStart + keyLen + len(postfix) - 1 - key := s[keyStart : keyStart+keyLen] - - // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) - - for _, k := range keys { - if key == k { - var b bytes.Buffer - b.WriteString("circular reference in:\n") - for _, k1 := range keys { - fmt.Fprintf(&b, "%s=%s\n", k1, values[k1]) - } - return "", fmt.Errorf(b.String()) - } - } - - val, ok := values[key] - if !ok { - val = os.Getenv(key) - } - new_val, err := expand(val, append(keys, key), prefix, postfix, values) - if err != nil { - return "", err - } - s = s[:start] + new_val + s[end+1:] - } -} - -// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. -func encode(s string, special string, enc Encoding) string { - switch enc { - case UTF8: - return encodeUtf8(s, special) - case ISO_8859_1: - return encodeIso(s, special) - default: - panic(fmt.Sprintf("unsupported encoding %v", enc)) - } -} - -func encodeUtf8(s string, special string) string { - v := "" - for pos := 0; pos < len(s); { - r, w := utf8.DecodeRuneInString(s[pos:]) - pos += w - v += escape(r, special) - } - return v -} - -func encodeIso(s string, special string) string { - var r rune - var w int - var v string - for pos := 0; pos < len(s); { - switch r, w = utf8.DecodeRuneInString(s[pos:]); { - case r < 1<<8: // single byte rune -> escape special chars only - v += escape(r, special) - case r < 1<<16: // two byte rune -> unicode literal - v += fmt.Sprintf("\\u%04x", r) - default: // more than two bytes per rune -> can't encode - v += "?" - } - pos += w - } - return v -} - -func escape(r rune, special string) string { - switch r { - case '\f': - return "\\f" - case '\n': - return "\\n" - case '\r': - return "\\r" - case '\t': - return "\\t" - case '\\': - return "\\\\" - default: - if strings.ContainsRune(special, r) { - return "\\" + string(r) - } - return string(r) - } -} - -func invalidKeyError(key string) error { - return fmt.Errorf("unknown property: %s", key) -} diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go deleted file mode 100644 index dbd60b36..00000000 --- a/vendor/github.com/magiconair/properties/rangecheck.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "math" -) - -// make this a var to overwrite it in a test -var is32Bit = ^uint(0) == math.MaxUint32 - -// intRangeCheck checks if the value fits into the int type and -// panics if it does not. -func intRangeCheck(key string, v int64) int { - if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return int(v) -} - -// uintRangeCheck checks if the value fits into the uint type and -// panics if it does not. -func uintRangeCheck(key string, v uint64) uint { - if is32Bit && v > math.MaxUint32 { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return uint(v) -} diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml index 1d8b69e6..ec52857a 100644 --- a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml +++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml @@ -1,3 +1,4 @@ +version: 2 before: hooks: - go mod tidy diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md index d964b25f..0755e556 100644 --- a/vendor/github.com/pelletier/go-toml/v2/README.md +++ b/vendor/github.com/pelletier/go-toml/v2/README.md @@ -565,7 +565,7 @@ complete solutions exist out there. ## Versioning -Expect for parts explicitely marked otherwise, go-toml follows [Semantic +Expect for parts explicitly marked otherwise, go-toml follows [Semantic Versioning](https://semver.org). The supported version of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of this document. The last two major versions of Go are supported (see [Go Release diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go index 7f4e20c1..161acd93 100644 --- a/vendor/github.com/pelletier/go-toml/v2/marshaler.go +++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go @@ -8,7 +8,7 @@ import ( "io" "math" "reflect" - "sort" + "slices" "strconv" "strings" "time" @@ -280,7 +280,7 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e } hasTextMarshaler := v.Type().Implements(textMarshalerType) - if hasTextMarshaler || (v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) { + if hasTextMarshaler || (v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { if !hasTextMarshaler { v = v.Addr() } @@ -631,6 +631,18 @@ func (enc *Encoder) keyToString(k reflect.Value) (string, error) { return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err) } return string(keyB), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + return strconv.FormatInt(k.Int(), 10), nil + + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + return strconv.FormatUint(k.Uint(), 10), nil + + case keyType.Kind() == reflect.Float32: + return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil + + case keyType.Kind() == reflect.Float64: + return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil } return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind()) } @@ -668,8 +680,8 @@ func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte } func sortEntriesByKey(e []entry) { - sort.Slice(e, func(i, j int) bool { - return e[i].Key < e[j].Key + slices.SortFunc(e, func(a, b entry) int { + return strings.Compare(a.Key, b.Key) }) } @@ -732,7 +744,7 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) { if fieldType.Anonymous { if fieldType.Type.Kind() == reflect.Struct { walkStruct(ctx, t, f) - } else if fieldType.Type.Kind() == reflect.Pointer && !f.IsNil() && f.Elem().Kind() == reflect.Struct { + } else if fieldType.Type.Kind() == reflect.Ptr && !f.IsNil() && f.Elem().Kind() == reflect.Struct { walkStruct(ctx, t, f.Elem()) } continue @@ -951,7 +963,7 @@ func willConvertToTable(ctx encoderCtx, v reflect.Value) bool { if !v.IsValid() { return false } - if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) { + if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { return false } diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go index 98231bae..c3df8bee 100644 --- a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go +++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "reflect" + "strconv" "strings" "sync/atomic" "time" @@ -21,10 +21,8 @@ import ( // // It is a shortcut for Decoder.Decode() with the default options. func Unmarshal(data []byte, v interface{}) error { - p := unstable.Parser{} - p.Reset(data) - d := decoder{p: &p} - + d := decoder{} + d.p.Reset(data) return d.FromParser(v) } @@ -117,27 +115,25 @@ func (d *Decoder) EnableUnmarshalerInterface() *Decoder { // Inline Table -> same as Table // Array of Tables -> same as Array and Table func (d *Decoder) Decode(v interface{}) error { - b, err := ioutil.ReadAll(d.r) + b, err := io.ReadAll(d.r) if err != nil { return fmt.Errorf("toml: %w", err) } - p := unstable.Parser{} - p.Reset(b) dec := decoder{ - p: &p, strict: strict{ Enabled: d.strict, }, unmarshalerInterface: d.unmarshalerInterface, } + dec.p.Reset(b) return dec.FromParser(v) } type decoder struct { // Which parser instance in use for this decoding session. - p *unstable.Parser + p unstable.Parser // Flag indicating that the current expression is stashed. // If set to true, calling nextExpr will not actually pull a new expression @@ -1078,12 +1074,39 @@ func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, } return mk, nil - case reflect.PtrTo(keyType).Implements(textUnmarshalerType): + case reflect.PointerTo(keyType).Implements(textUnmarshalerType): mk := reflect.New(keyType) if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err) } return mk.Elem(), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + key, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + key, err := strconv.ParseUint(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + + case keyType.Kind() == reflect.Float32: + key, err := strconv.ParseFloat(string(data), 32) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float32(key)), nil + + case keyType.Kind() == reflect.Float64: + key, err := strconv.ParseFloat(string(data), 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float64(key)), nil } return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType) } diff --git a/vendor/github.com/sagikazarmark/locafero/flake.lock b/vendor/github.com/sagikazarmark/locafero/flake.lock index 4bea8154..df2a8cce 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.lock +++ b/vendor/github.com/sagikazarmark/locafero/flake.lock @@ -39,11 +39,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1717245169, - "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "lastModified": 1725907707, + "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=", "owner": "cachix", "repo": "devenv", - "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "rev": "2bbbbc468fc02257265a79652a8350651cca495a", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", "type": "github" }, "original": { @@ -286,14 +286,14 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1717284937, - "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" } }, "nixpkgs-regression": { @@ -362,11 +362,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1717112898, - "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "lastModified": 1725910328, + "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4", "type": "github" }, "original": { diff --git a/vendor/github.com/sagikazarmark/locafero/flake.nix b/vendor/github.com/sagikazarmark/locafero/flake.nix index cddf1d40..312f1ec8 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.nix +++ b/vendor/github.com/sagikazarmark/locafero/flake.nix @@ -20,6 +20,7 @@ default = { languages = { go.enable = true; + go.package = pkgs.lib.mkDefault pkgs.go_1_23; }; packages = with pkgs; [ @@ -41,6 +42,22 @@ go.package = pkgs.go_1_21; }; }; + + ci_1_22 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_22; + }; + }; + + ci_1_23 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_23; + }; + }; }; }; }; diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/spf13/afero/.editorconfig similarity index 69% rename from vendor/github.com/fsnotify/fsnotify/.editorconfig rename to vendor/github.com/spf13/afero/.editorconfig index fad89585..4492e9f9 100644 --- a/vendor/github.com/fsnotify/fsnotify/.editorconfig +++ b/vendor/github.com/spf13/afero/.editorconfig @@ -1,12 +1,12 @@ root = true -[*.go] -indent_style = tab +[*] +charset = utf-8 +end_of_line = lf indent_size = 4 -insert_final_newline = true - -[*.{yml,yaml}] indent_style = space -indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true + +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/afero/.golangci.yaml b/vendor/github.com/spf13/afero/.golangci.yaml new file mode 100644 index 00000000..806289a2 --- /dev/null +++ b/vendor/github.com/spf13/afero/.golangci.yaml @@ -0,0 +1,18 @@ +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/spf13/afero) + +linters: + disable-all: true + enable: + - gci + - gofmt + - gofumpt + - staticcheck + +issues: + exclude-dirs: + - gcsfs/internal/stiface diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md index 3bafbfdf..619af574 100644 --- a/vendor/github.com/spf13/afero/README.md +++ b/vendor/github.com/spf13/afero/README.md @@ -12,7 +12,7 @@ types and methods. Afero has an exceptionally clean interface and simple design without needless constructors or initialization methods. Afero is also a library providing a base set of interoperable backend -filesystems that make it easy to work with afero while retaining all the power +filesystems that make it easy to work with, while retaining all the power and benefit of the os and ioutil packages. Afero provides significant improvements over using the os package alone, most diff --git a/vendor/github.com/spf13/afero/iofs.go b/vendor/github.com/spf13/afero/iofs.go index 938b9316..b13155ca 100644 --- a/vendor/github.com/spf13/afero/iofs.go +++ b/vendor/github.com/spf13/afero/iofs.go @@ -255,7 +255,6 @@ func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) { ret := make([]os.FileInfo, len(entries)) for i := range entries { ret[i], err = entries[i].Info() - if err != nil { return nil, err } diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go index d6c744e8..ed92f564 100644 --- a/vendor/github.com/spf13/afero/memmap.go +++ b/vendor/github.com/spf13/afero/memmap.go @@ -16,11 +16,9 @@ package afero import ( "fmt" "io" - "log" "os" "path/filepath" - "sort" "strings" "sync" diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md index 0e9e1459..1be666a4 100644 --- a/vendor/github.com/spf13/cast/README.md +++ b/vendor/github.com/spf13/cast/README.md @@ -1,6 +1,6 @@ # cast -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/ci.yaml) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast) ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast) diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go index cd9c0488..4181a2e7 100644 --- a/vendor/github.com/spf13/cast/caste.go +++ b/vendor/github.com/spf13/cast/caste.go @@ -613,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) { switch s := i.(type) { case string: - v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0) if err == nil { if v < 0 { return 0, errNegativeNotAllowed } - return uint64(v), nil + return v, nil } return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) case json.Number: diff --git a/vendor/gopkg.in/ini.v1/.editorconfig b/vendor/github.com/spf13/pflag/.editorconfig similarity index 60% rename from vendor/gopkg.in/ini.v1/.editorconfig rename to vendor/github.com/spf13/pflag/.editorconfig index 4a2d9180..4492e9f9 100644 --- a/vendor/gopkg.in/ini.v1/.editorconfig +++ b/vendor/github.com/spf13/pflag/.editorconfig @@ -1,12 +1,12 @@ -# http://editorconfig.org - root = true [*] charset = utf-8 end_of_line = lf +indent_size = 4 +indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[*_test.go] -trim_trailing_whitespace = false +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/pflag/.golangci.yaml b/vendor/github.com/spf13/pflag/.golangci.yaml new file mode 100644 index 00000000..b274f248 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.golangci.yaml @@ -0,0 +1,4 @@ +linters: + disable-all: true + enable: + - nolintlint diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 24a5036e..7c058de3 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -160,7 +160,7 @@ type FlagSet struct { args []string // arguments after flags argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- errorHandling ErrorHandling - output io.Writer // nil means stderr; use out() accessor + output io.Writer // nil means stderr; use Output() accessor interspersed bool // allow interspersed option/non-option args normalizeNameFunc func(f *FlagSet, name string) NormalizedName @@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName { return n(f, name) } -func (f *FlagSet) out() io.Writer { +// Output returns the destination for usage and error messages. os.Stderr is returned if +// output was not set or was set to nil. +func (f *FlagSet) Output() io.Writer { if f.output == nil { return os.Stderr } return f.output } +// Name returns the name of the flag set. +func (f *FlagSet) Name() string { + return f.name +} + // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (f *FlagSet) SetOutput(output io.Writer) { @@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag { } if len(name) > 1 { msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } c := name[0] @@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error { } if flag.Deprecated != "" { - fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) } return nil } @@ -523,7 +530,7 @@ func Set(name, value string) error { // otherwise, the default values of all defined flags in the set. func (f *FlagSet) PrintDefaults() { usages := f.FlagUsages() - fmt.Fprint(f.out(), usages) + fmt.Fprint(f.Output(), usages) } // defaultIsZeroValue returns true if the default value for this flag represents @@ -758,7 +765,7 @@ func PrintDefaults() { // defaultUsage is the default function to print a usage message. func defaultUsage(f *FlagSet) { - fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) + fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) f.PrintDefaults() } @@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { _, alreadyThere := f.formal[normalizedFlagName] if alreadyThere { msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) - fmt.Fprintln(f.out(), msg) + fmt.Fprintln(f.Output(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { @@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { } if len(flag.Shorthand) > 1 { msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } if f.shorthands == nil { @@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { used, alreadyThere := f.shorthands[c] if alreadyThere { msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } f.shorthands[c] = flag @@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) { func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) if f.errorHandling != ContinueOnError { - fmt.Fprintln(f.out(), err) + fmt.Fprintln(f.Output(), err) f.usage() } return err @@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse } if flag.ShorthandDeprecated != "" { - fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) } err = fn(flag, value) diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go index 3d414ba6..06b8bcb5 100644 --- a/vendor/github.com/spf13/pflag/ip.go +++ b/vendor/github.com/spf13/pflag/ip.go @@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue { func (i *ipValue) String() string { return net.IP(*i).String() } func (i *ipValue) Set(s string) error { + if s == "" { + return nil + } ip := net.ParseIP(strings.TrimSpace(s)) if ip == nil { return fmt.Errorf("failed to parse IP: %q", s) diff --git a/vendor/github.com/spf13/pflag/ipnet_slice.go b/vendor/github.com/spf13/pflag/ipnet_slice.go new file mode 100644 index 00000000..6b541aa8 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipnet_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipNetSlice Value +type ipNetSliceValue struct { + value *[]net.IPNet + changed bool +} + +func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue { + ipnsv := new(ipNetSliceValue) + ipnsv.value = p + *ipnsv.value = val + return ipnsv +} + +// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag. +// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended. +func (s *ipNetSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IPNet, 0, len(ipNetStrSlice)) + for _, ipNetStr := range ipNetStrSlice { + _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr)) + if err != nil { + return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr) + } + out = append(out, *n) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipNetSliceValue) Type() string { + return "ipNetSlice" +} + +// String defines a "native" format for this net.IPNet slice flag value. +func (s *ipNetSliceValue) String() string { + + ipNetStrSlice := make([]string, len(*s.value)) + for i, n := range *s.value { + ipNetStrSlice[i] = n.String() + } + + out, _ := writeAsCSV(ipNetStrSlice) + return "[" + out + "]" +} + +func ipNetSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IPNet{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IPNet, len(ss)) + for i, sval := range ss { + _, n, err := net.ParseCIDR(strings.TrimSpace(sval)) + if err != nil { + return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval) + } + out[i] = *n + } + return out, nil +} + +// GetIPNetSlice returns the []net.IPNet value of a flag with the given name +func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) { + val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv) + if err != nil { + return []net.IPNet{}, err + } + return val.([]net.IPNet), nil +} + +// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IPNet variable that stores the value of that flag. +func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, "", value, usage) +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 4894af81..d1ff0a96 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error { func (s *stringArrayValue) Replace(val []string) error { out := make([]string, len(val)) for i, d := range val { - var err error out[i] = d - if err != nil { - return err - } } *s.value = out return nil diff --git a/vendor/github.com/spf13/viper/.golangci.yaml b/vendor/github.com/spf13/viper/.golangci.yaml index 1faeae42..474f4163 100644 --- a/vendor/github.com/spf13/viper/.golangci.yaml +++ b/vendor/github.com/spf13/viper/.golangci.yaml @@ -17,8 +17,6 @@ linters-settings: disabled-checks: - importShadow - unnamedResult - golint: - min-confidence: 0 goimports: local-prefixes: github.com/spf13/viper @@ -30,7 +28,6 @@ linters: - dupl - durationcheck - exhaustive - - exportloopref - gci - gocritic - godot diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md index c2b2237c..769a5d90 100644 --- a/vendor/github.com/spf13/viper/README.md +++ b/vendor/github.com/spf13/viper/README.md @@ -3,7 +3,8 @@ > > **Thank you!** -![Viper](.github/logo.png?raw=true) +![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e) + [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration) [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go) diff --git a/vendor/github.com/spf13/viper/UPDATES.md b/vendor/github.com/spf13/viper/UPDATES.md new file mode 100644 index 00000000..ccf413ed --- /dev/null +++ b/vendor/github.com/spf13/viper/UPDATES.md @@ -0,0 +1,126 @@ +# Update Log + +**This document details any major updates required to use new features or improvements in Viper.** + +## v1.20.x + +### New file searching API + +Viper now includes a new file searching API that allows users to customize how Viper looks for config files. + +Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation: + +```go +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} +``` + +It is supposed to return a list of paths to config files. + +The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood. + +You can supply your own implementation using `WithFinder`: + +```go +v := viper.NewWithOptions( + viper.WithFinder(&MyFinder{}), +) +``` + +For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder) +and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package. + +### New encoding API + +Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data: + +```go +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} +``` + +By default, Viper includes the following codecs: + +- JSON +- TOML +- YAML +- Dotenv + +The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding) + +Customizing the encoding layer is possible by providing a custom registry of codecs: + +- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry) +- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry) +- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry) + +You can supply the registry of codecs to Viper using the appropriate `With*Registry` function: + +```go +codecRegistry := viper.NewCodecRegistry() + +codecRegistry.RegisterCodec("myformat", &MyCodec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` + +### BREAKING: HCL, Java properties, INI removed from core + +In order to reduce third-party dependencies, Viper dropped support for the following formats from the core: + +- HCL +- Java properties +- INI + +You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding): + +```go +import ( + "github.com/go-viper/encoding/hcl" + "github.com/go-viper/encoding/javaproperties" + "github.com/go-viper/encoding/ini" +) + +codecRegistry := viper.NewCodecRegistry() + +{ + codec := hcl.Codec{} + + codecRegistry.RegisterCodec("hcl", codec) + codecRegistry.RegisterCodec("tfvars", codec) + +} + +{ + codec := &javaproperties.Codec{} + + codecRegistry.RegisterCodec("properties", codec) + codecRegistry.RegisterCodec("props", codec) + codecRegistry.RegisterCodec("prop", codec) +} + +codecRegistry.RegisterCodec("ini", ini.Codec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` diff --git a/vendor/github.com/spf13/viper/encoding.go b/vendor/github.com/spf13/viper/encoding.go new file mode 100644 index 00000000..a7da5586 --- /dev/null +++ b/vendor/github.com/spf13/viper/encoding.go @@ -0,0 +1,181 @@ +package viper + +import ( + "errors" + "strings" + "sync" + + "github.com/spf13/viper/internal/encoding/dotenv" + "github.com/spf13/viper/internal/encoding/json" + "github.com/spf13/viper/internal/encoding/toml" + "github.com/spf13/viper/internal/encoding/yaml" +) + +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} + +// TODO: consider adding specific errors for not found scenarios + +// EncoderRegistry returns an [Encoder] for a given format. +// +// Format is case-insensitive. +// +// [EncoderRegistry] returns an error if no [Encoder] is registered for the format. +type EncoderRegistry interface { + Encoder(format string) (Encoder, error) +} + +// DecoderRegistry returns an [Decoder] for a given format. +// +// Format is case-insensitive. +// +// [DecoderRegistry] returns an error if no [Decoder] is registered for the format. +type DecoderRegistry interface { + Decoder(format string) (Decoder, error) +} + +// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces. +type CodecRegistry interface { + EncoderRegistry + DecoderRegistry +} + +// WithEncoderRegistry sets a custom [EncoderRegistry]. +func WithEncoderRegistry(r EncoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + }) +} + +// WithDecoderRegistry sets a custom [DecoderRegistry]. +func WithDecoderRegistry(r DecoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.decoderRegistry = r + }) +} + +// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry]. +func WithCodecRegistry(r CodecRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + v.decoderRegistry = r + }) +} + +// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s. +type DefaultCodecRegistry struct { + codecs map[string]Codec + + mu sync.RWMutex + once sync.Once +} + +// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s. +func NewCodecRegistry() *DefaultCodecRegistry { + r := &DefaultCodecRegistry{} + + r.init() + + return r +} + +func (r *DefaultCodecRegistry) init() { + r.once.Do(func() { + r.codecs = map[string]Codec{} + }) +} + +// RegisterCodec registers a custom [Codec]. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error { + r.init() + + r.mu.Lock() + defer r.mu.Unlock() + + r.codecs[strings.ToLower(format)] = codec + + return nil +} + +// Encoder implements the [EncoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) { + encoder, ok := r.codec(format) + if !ok { + return nil, errors.New("encoder not found for this format") + } + + return encoder, nil +} + +// Decoder implements the [DecoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) { + decoder, ok := r.codec(format) + if !ok { + return nil, errors.New("decoder not found for this format") + } + + return decoder, nil +} + +func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) { + r.mu.Lock() + defer r.mu.Unlock() + + format = strings.ToLower(format) + + if r.codecs != nil { + codec, ok := r.codecs[format] + if ok { + return codec, true + } + } + + switch format { + case "yaml", "yml": + return yaml.Codec{}, true + + case "json": + return json.Codec{}, true + + case "toml": + return toml.Codec{}, true + + case "dotenv", "env": + return &dotenv.Codec{}, true + } + + return nil, false +} diff --git a/vendor/github.com/spf13/viper/finder.go b/vendor/github.com/spf13/viper/finder.go index ab4b5950..9b203ea6 100644 --- a/vendor/github.com/spf13/viper/finder.go +++ b/vendor/github.com/spf13/viper/finder.go @@ -9,6 +9,10 @@ import ( // WithFinder sets a custom [Finder]. func WithFinder(f Finder) Option { return optionFunc(func(v *Viper) { + if f == nil { + return + } + v.finder = f }) } @@ -34,6 +38,10 @@ func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) { var errs []error for _, finder := range c.finders { + if finder == nil { + continue + } + r, err := finder.Find(fsys) if err != nil { errs = append(errs, err) diff --git a/vendor/github.com/spf13/viper/flake.lock b/vendor/github.com/spf13/viper/flake.lock index 4bea8154..d76dfbdd 100644 --- a/vendor/github.com/spf13/viper/flake.lock +++ b/vendor/github.com/spf13/viper/flake.lock @@ -39,11 +39,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1717245169, - "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "lastModified": 1724763216, + "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=", "owner": "cachix", "repo": "devenv", - "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -286,14 +286,14 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1717284937, - "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" } }, "nixpkgs-regression": { @@ -362,11 +362,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1717112898, - "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "lastModified": 1724748588, + "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99", "type": "github" }, "original": { diff --git a/vendor/github.com/spf13/viper/flake.nix b/vendor/github.com/spf13/viper/flake.nix index 0230668c..52ad7d58 100644 --- a/vendor/github.com/spf13/viper/flake.nix +++ b/vendor/github.com/spf13/viper/flake.nix @@ -20,7 +20,7 @@ default = { languages = { go.enable = true; - go.package = pkgs.go_1_22; + go.package = pkgs.go_1_23; }; pre-commit.hooks = { diff --git a/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/vendor/github.com/spf13/viper/internal/encoding/decoder.go deleted file mode 100644 index 8a7b1dbc..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/decoder.go +++ /dev/null @@ -1,61 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Decoder decodes the contents of b into v. -// It's primarily used for decoding contents of a file into a map[string]any. -type Decoder interface { - Decode(b []byte, v map[string]any) error -} - -const ( - // ErrDecoderNotFound is returned when there is no decoder registered for a format. - ErrDecoderNotFound = encodingError("decoder not found for this format") - - // ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format. - ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format") -) - -// DecoderRegistry can choose an appropriate Decoder based on the provided format. -type DecoderRegistry struct { - decoders map[string]Decoder - - mu sync.RWMutex -} - -// NewDecoderRegistry returns a new, initialized DecoderRegistry. -func NewDecoderRegistry() *DecoderRegistry { - return &DecoderRegistry{ - decoders: make(map[string]Decoder), - } -} - -// RegisterDecoder registers a Decoder for a format. -// Registering a Decoder for an already existing format is not supported. -func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.decoders[format]; ok { - return ErrDecoderFormatAlreadyRegistered - } - - e.decoders[format] = enc - - return nil -} - -// Decode calls the underlying Decoder based on the format. -func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error { - e.mu.RLock() - decoder, ok := e.decoders[format] - e.mu.RUnlock() - - if !ok { - return ErrDecoderNotFound - } - - return decoder.Decode(b, v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/vendor/github.com/spf13/viper/internal/encoding/encoder.go deleted file mode 100644 index 65958596..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/encoder.go +++ /dev/null @@ -1,60 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Encoder encodes the contents of v into a byte representation. -// It's primarily used for encoding a map[string]any into a file format. -type Encoder interface { - Encode(v map[string]any) ([]byte, error) -} - -const ( - // ErrEncoderNotFound is returned when there is no encoder registered for a format. - ErrEncoderNotFound = encodingError("encoder not found for this format") - - // ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format. - ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format") -) - -// EncoderRegistry can choose an appropriate Encoder based on the provided format. -type EncoderRegistry struct { - encoders map[string]Encoder - - mu sync.RWMutex -} - -// NewEncoderRegistry returns a new, initialized EncoderRegistry. -func NewEncoderRegistry() *EncoderRegistry { - return &EncoderRegistry{ - encoders: make(map[string]Encoder), - } -} - -// RegisterEncoder registers an Encoder for a format. -// Registering a Encoder for an already existing format is not supported. -func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.encoders[format]; ok { - return ErrEncoderFormatAlreadyRegistered - } - - e.encoders[format] = enc - - return nil -} - -func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) { - e.mu.RLock() - encoder, ok := e.encoders[format] - e.mu.RUnlock() - - if !ok { - return nil, ErrEncoderNotFound - } - - return encoder.Encode(v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/error.go b/vendor/github.com/spf13/viper/internal/encoding/error.go deleted file mode 100644 index e4cde02d..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/error.go +++ /dev/null @@ -1,7 +0,0 @@ -package encoding - -type encodingError string - -func (e encodingError) Error() string { - return string(e) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go deleted file mode 100644 index d7fa8a1b..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go +++ /dev/null @@ -1,40 +0,0 @@ -package hcl - -import ( - "bytes" - "encoding/json" - - "github.com/hashicorp/hcl" - "github.com/hashicorp/hcl/hcl/printer" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding. -// TODO: add printer config to the codec? -type Codec struct{} - -func (Codec) Encode(v map[string]any) ([]byte, error) { - b, err := json.Marshal(v) - if err != nil { - return nil, err - } - - // TODO: use printer.Format? Is the trailing newline an issue? - - ast, err := hcl.Parse(string(b)) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - - err = printer.Fprint(&buf, ast.Node) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (Codec) Decode(b []byte, v map[string]any) error { - return hcl.Unmarshal(b, &v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go deleted file mode 100644 index d91cf59d..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go +++ /dev/null @@ -1,99 +0,0 @@ -package ini - -import ( - "bytes" - "sort" - "strings" - - "github.com/spf13/cast" - "gopkg.in/ini.v1" -) - -// LoadOptions contains all customized options used for load data source(s). -// This type is added here for convenience: this way consumers can import a single package called "ini". -type LoadOptions = ini.LoadOptions - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding. -type Codec struct { - KeyDelimiter string - LoadOptions LoadOptions -} - -func (c Codec) Encode(v map[string]any) ([]byte, error) { - cfg := ini.Empty() - ini.PrettyFormat = false - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - sectionName, keyName := "", key - - lastSep := strings.LastIndex(key, ".") - if lastSep != -1 { - sectionName = key[:(lastSep)] - keyName = key[(lastSep + 1):] - } - - // TODO: is this a good idea? - if sectionName == "default" { - sectionName = "" - } - - cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key])) - } - - var buf bytes.Buffer - - _, err := cfg.WriteTo(&buf) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c Codec) Decode(b []byte, v map[string]any) error { - cfg := ini.Empty(c.LoadOptions) - - err := cfg.Append(b) - if err != nil { - return err - } - - sections := cfg.Sections() - - for i := 0; i < len(sections); i++ { - section := sections[i] - keys := section.Keys() - - for j := 0; j < len(keys); j++ { - key := keys[j] - value := cfg.Section(section.Name()).Key(key.Name()).String() - - deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter())) - - // set innermost value - deepestMap[key.Name()] = value - } - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go deleted file mode 100644 index 490ab594..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package ini - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// In case intermediate keys do not exist, or map to a non-map value, -// a new map is created and inserted, and the search continues from there: -// the initial map "m" may be modified! -func deepSearch(m map[string]any, path []string) map[string]any { - for _, k := range path { - m2, ok := m[k] - if !ok { - // intermediate key does not exist - // => create it and continue from there - m3 := make(map[string]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// flattenAndMergeMap recursively flattens the given map into a new map -// Code is based on the function with the same name in the main package. -// TODO: move it to a common place. -func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { - if shadow != nil && prefix != "" && shadow[prefix] != nil { - // prefix is shadowed => nothing more to flatten - return shadow - } - if shadow == nil { - shadow = make(map[string]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go deleted file mode 100644 index e92e5172..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go +++ /dev/null @@ -1,86 +0,0 @@ -package javaproperties - -import ( - "bytes" - "sort" - "strings" - - "github.com/magiconair/properties" - "github.com/spf13/cast" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding. -type Codec struct { - KeyDelimiter string - - // Store read properties on the object so that we can write back in order with comments. - // This will only be used if the configuration read is a properties file. - // TODO: drop this feature in v2 - // TODO: make use of the global properties object optional - Properties *properties.Properties -} - -func (c *Codec) Encode(v map[string]any) ([]byte, error) { - if c.Properties == nil { - c.Properties = properties.NewProperties() - } - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - _, _, err := c.Properties.Set(key, cast.ToString(flattened[key])) - if err != nil { - return nil, err - } - } - - var buf bytes.Buffer - - _, err := c.Properties.WriteComment(&buf, "#", properties.UTF8) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c *Codec) Decode(b []byte, v map[string]any) error { - var err error - c.Properties, err = properties.Load(b, properties.UTF8) - if err != nil { - return err - } - - for _, key := range c.Properties.Keys() { - // ignore existence check: we know it's there - value, _ := c.Properties.Get(key) - - // recursively build nested maps - path := strings.Split(key, c.keyDelimiter()) - lastKey := strings.ToLower(path[len(path)-1]) - deepestMap := deepSearch(v, path[0:len(path)-1]) - - // set innermost value - deepestMap[lastKey] = value - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go deleted file mode 100644 index 6e1aff22..00000000 --- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package javaproperties - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// In case intermediate keys do not exist, or map to a non-map value, -// a new map is created and inserted, and the search continues from there: -// the initial map "m" may be modified! -func deepSearch(m map[string]any, path []string) map[string]any { - for _, k := range path { - m2, ok := m[k] - if !ok { - // intermediate key does not exist - // => create it and continue from there - m3 := make(map[string]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// flattenAndMergeMap recursively flattens the given map into a new map -// Code is based on the function with the same name in the main package. -// TODO: move it to a common place. -func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { - if shadow != nil && prefix != "" && shadow[prefix] != nil { - // prefix is shadowed => nothing more to flatten - return shadow - } - if shadow == nil { - shadow = make(map[string]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/vendor/github.com/spf13/viper/remote.go b/vendor/github.com/spf13/viper/remote.go index 2c07f81f..bdde7de2 100644 --- a/vendor/github.com/spf13/viper/remote.go +++ b/vendor/github.com/spf13/viper/remote.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "reflect" + "slices" ) // SupportedRemoteProviders are universally supported remote providers. @@ -93,7 +94,7 @@ func AddRemoteProvider(provider, endpoint, path string) error { } func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { + if !slices.Contains(SupportedRemoteProviders, provider) { return UnsupportedRemoteProviderError(provider) } if provider != "" && endpoint != "" { @@ -126,7 +127,7 @@ func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) err } func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { + if !slices.Contains(SupportedRemoteProviders, provider) { return UnsupportedRemoteProviderError(provider) } if provider != "" && endpoint != "" { diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go index 9a6a5a8a..2a08074b 100644 --- a/vendor/github.com/spf13/viper/util.go +++ b/vendor/github.com/spf13/viper/util.go @@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string { return "" } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - func userHomeDir() string { if runtime.GOOS == "windows" { home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index 30ae4aa9..a58d757b 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -29,6 +29,7 @@ import ( "os" "path/filepath" "reflect" + "slices" "strconv" "strings" "sync" @@ -40,14 +41,6 @@ import ( "github.com/spf13/cast" "github.com/spf13/pflag" - "github.com/spf13/viper/internal/encoding" - "github.com/spf13/viper/internal/encoding/dotenv" - "github.com/spf13/viper/internal/encoding/hcl" - "github.com/spf13/viper/internal/encoding/ini" - "github.com/spf13/viper/internal/encoding/javaproperties" - "github.com/spf13/viper/internal/encoding/json" - "github.com/spf13/viper/internal/encoding/toml" - "github.com/spf13/viper/internal/encoding/yaml" "github.com/spf13/viper/internal/features" ) @@ -170,9 +163,6 @@ type Viper struct { configPermissions os.FileMode envPrefix string - // Specific commands for ini parsing - iniLoadOptions ini.LoadOptions - automaticEnvApplied bool envKeyReplacer StringReplacer allowEmptyEnv bool @@ -191,9 +181,10 @@ type Viper struct { logger *slog.Logger - // TODO: should probably be protected with a mutex - encoderRegistry *encoding.EncoderRegistry - decoderRegistry *encoding.DecoderRegistry + encoderRegistry EncoderRegistry + decoderRegistry DecoderRegistry + + decodeHook mapstructure.DecodeHookFunc experimentalFinder bool experimentalBindStruct bool @@ -217,7 +208,10 @@ func New() *Viper { v.typeByDefValue = false v.logger = slog.New(&discardHandler{}) - v.resetEncoding() + codecRegistry := NewCodecRegistry() + + v.encoderRegistry = codecRegistry + v.decoderRegistry = codecRegistry v.experimentalFinder = features.Finder v.experimentalBindStruct = features.BindStruct @@ -256,10 +250,25 @@ type StringReplacer interface { // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys. func EnvKeyReplacer(r StringReplacer) Option { return optionFunc(func(v *Viper) { + if r == nil { + return + } + v.envKeyReplacer = r }) } +// WithDecodeHook sets a default decode hook for mapstructure. +func WithDecodeHook(h mapstructure.DecodeHookFunc) Option { + return optionFunc(func(v *Viper) { + if h == nil { + return + } + + v.decodeHook = h + }) +} + // NewWithOptions creates a new Viper instance. func NewWithOptions(opts ...Option) *Viper { v := New() @@ -268,8 +277,6 @@ func NewWithOptions(opts ...Option) *Viper { opt.apply(v) } - v.resetEncoding() - return v } @@ -278,16 +285,9 @@ func NewWithOptions(opts ...Option) *Viper { // Be careful when using this function: subsequent calls may override options you set. // It's always better to use a local Viper instance. func SetOptions(opts ...Option) { - keyDelim := v.keyDelim - for _, opt := range opts { opt.apply(v) } - - // reset encoding if key delimiter changed - if keyDelim != v.keyDelim { - v.resetEncoding() - } } // Reset is intended for testing, will reset all to default settings. @@ -300,84 +300,6 @@ func Reset() { resetRemote() } -// TODO: make this lazy initialization instead. -func (v *Viper) resetEncoding() { - encoderRegistry := encoding.NewEncoderRegistry() - decoderRegistry := encoding.NewDecoderRegistry() - - { - codec := yaml.Codec{} - - encoderRegistry.RegisterEncoder("yaml", codec) - decoderRegistry.RegisterDecoder("yaml", codec) - - encoderRegistry.RegisterEncoder("yml", codec) - decoderRegistry.RegisterDecoder("yml", codec) - } - - { - codec := json.Codec{} - - encoderRegistry.RegisterEncoder("json", codec) - decoderRegistry.RegisterDecoder("json", codec) - } - - { - codec := toml.Codec{} - - encoderRegistry.RegisterEncoder("toml", codec) - decoderRegistry.RegisterDecoder("toml", codec) - } - - { - codec := hcl.Codec{} - - encoderRegistry.RegisterEncoder("hcl", codec) - decoderRegistry.RegisterDecoder("hcl", codec) - - encoderRegistry.RegisterEncoder("tfvars", codec) - decoderRegistry.RegisterDecoder("tfvars", codec) - } - - { - codec := ini.Codec{ - KeyDelimiter: v.keyDelim, - LoadOptions: v.iniLoadOptions, - } - - encoderRegistry.RegisterEncoder("ini", codec) - decoderRegistry.RegisterDecoder("ini", codec) - } - - { - codec := &javaproperties.Codec{ - KeyDelimiter: v.keyDelim, - } - - encoderRegistry.RegisterEncoder("properties", codec) - decoderRegistry.RegisterDecoder("properties", codec) - - encoderRegistry.RegisterEncoder("props", codec) - decoderRegistry.RegisterDecoder("props", codec) - - encoderRegistry.RegisterEncoder("prop", codec) - decoderRegistry.RegisterDecoder("prop", codec) - } - - { - codec := &dotenv.Codec{} - - encoderRegistry.RegisterEncoder("dotenv", codec) - decoderRegistry.RegisterDecoder("dotenv", codec) - - encoderRegistry.RegisterEncoder("env", codec) - decoderRegistry.RegisterDecoder("env", codec) - } - - v.encoderRegistry = encoderRegistry - v.decoderRegistry = decoderRegistry -} - // SupportedExts are universally supported extensions. var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} @@ -539,7 +461,7 @@ func (v *Viper) AddConfigPath(in string) { absin := absPathify(v.logger, in) v.logger.Info("adding path to search paths", "path", absin) - if !stringInSlice(absin, v.configPaths) { + if !slices.Contains(v.configPaths, absin) { v.configPaths = append(v.configPaths, absin) } } @@ -852,6 +774,7 @@ func (v *Viper) Sub(key string) *Viper { subv.automaticEnvApplied = v.automaticEnvApplied subv.envPrefix = v.envPrefix subv.envKeyReplacer = v.envKeyReplacer + subv.keyDelim = v.keyDelim subv.config = cast.ToStringMap(data) return subv } @@ -893,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 { return cast.ToInt64(v.Get(key)) } +// GetUint8 returns the value associated with the key as an unsigned integer. +func GetUint8(key string) uint8 { return v.GetUint8(key) } + +func (v *Viper) GetUint8(key string) uint8 { + return cast.ToUint8(v.Get(key)) +} + // GetUint returns the value associated with the key as an unsigned integer. func GetUint(key string) uint { return v.GetUint(key) } @@ -992,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { - return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) + return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...)) } // Unmarshal unmarshals the config into a Struct. Make sure that the tags @@ -1015,13 +945,13 @@ func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { } // TODO: struct keys should be enough? - return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...)) + return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...)) } func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) { var structKeyMap map[string]any - err := decode(input, defaultDecoderConfig(&structKeyMap, opts...)) + err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...)) if err != nil { return nil, err } @@ -1038,20 +968,29 @@ func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]stri // defaultDecoderConfig returns default mapstructure.DecoderConfig with support // of time.Duration values & string slices. -func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { - c := &mapstructure.DecoderConfig{ - Metadata: nil, - Result: output, - WeaklyTypedInput: true, - DecodeHook: mapstructure.ComposeDecodeHookFunc( +func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { + decodeHook := v.decodeHook + if decodeHook == nil { + decodeHook = mapstructure.ComposeDecodeHookFunc( mapstructure.StringToTimeDurationHookFunc(), // mapstructure.StringToSliceHookFunc(","), stringToWeakSliceHookFunc(","), - ), + ) + } + + c := &mapstructure.DecoderConfig{ + Metadata: nil, + WeaklyTypedInput: true, + DecodeHook: decodeHook, } + for _, opt := range opts { opt(c) } + + // Do not allow overwriting the output + c.Result = output + return c } @@ -1093,7 +1032,7 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { - config := defaultDecoderConfig(rawVal, opts...) + config := v.defaultDecoderConfig(rawVal, opts...) config.ErrorUnused = true keys := v.AllKeys() @@ -1548,7 +1487,7 @@ func (v *Viper) ReadInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1579,7 +1518,7 @@ func (v *Viper) MergeInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1596,27 +1535,29 @@ func (v *Viper) MergeInConfig() error { func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } func (v *Viper) ReadConfig(in io.Reader) error { - if v.configType == "" { - return errors.New("cannot decode configuration: config type is not set") + config := make(map[string]any) + + err := v.unmarshalReader(in, config) + if err != nil { + return err } - v.config = make(map[string]any) - return v.unmarshalReader(in, v.config) + v.config = config + + return nil } // MergeConfig merges a new configuration with an existing config. func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } func (v *Viper) MergeConfig(in io.Reader) error { - if v.configType == "" { - return errors.New("cannot decode configuration: config type is not set") - } + config := make(map[string]any) - cfg := make(map[string]any) - if err := v.unmarshalReader(in, cfg); err != nil { + if err := v.unmarshalReader(in, config); err != nil { return err } - return v.MergeConfigMap(cfg) + + return v.MergeConfigMap(config) } // MergeConfigMap merges the configuration from the map given with an existing config. @@ -1660,6 +1601,19 @@ func (v *Viper) WriteConfigAs(filename string) error { return v.writeConfig(filename, true) } +// WriteConfigTo writes current configuration to an [io.Writer]. +func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) } + +func (v *Viper) WriteConfigTo(w io.Writer) error { + format := strings.ToLower(v.getConfigType()) + + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + return v.marshalWriter(w, format) +} + // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } @@ -1686,7 +1640,7 @@ func (v *Viper) writeConfig(filename string, force bool) error { return fmt.Errorf("config type could not be determined for %s", filename) } - if !stringInSlice(configType, SupportedExts) { + if !slices.Contains(SupportedExts, configType) { return UnsupportedConfigError(configType) } if v.config == nil { @@ -1710,15 +1664,29 @@ func (v *Viper) writeConfig(filename string, force bool) error { } func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error { + format := strings.ToLower(v.getConfigType()) + if format == "" { + return errors.New("cannot decode configuration: unable to determine config type") + } + buf := new(bytes.Buffer) buf.ReadFrom(in) - switch format := strings.ToLower(v.getConfigType()); format { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env": - err := v.decoderRegistry.Decode(format, buf.Bytes(), c) - if err != nil { - return ConfigParseError{err} - } + // TODO: remove this once SupportedExts is deprecated/removed + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + // TODO: return [UnsupportedConfigError] if the registry does not contain the format + // TODO: consider deprecating this error type + decoder, err := v.decoderRegistry.Decoder(format) + if err != nil { + return ConfigParseError{err} + } + + err = decoder.Decode(buf.Bytes(), c) + if err != nil { + return ConfigParseError{err} } insensitiviseMap(c) @@ -1726,20 +1694,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error { } // Marshal a map into Writer. -func (v *Viper) marshalWriter(f afero.File, configType string) error { +func (v *Viper) marshalWriter(w io.Writer, configType string) error { c := v.AllSettings() - switch configType { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env": - b, err := v.encoderRegistry.Encode(configType, c) - if err != nil { - return ConfigMarshalError{err} - } - _, err = f.WriteString(string(b)) - if err != nil { - return ConfigMarshalError{err} - } + encoder, err := v.encoderRegistry.Encoder(configType) + if err != nil { + return ConfigMarshalError{err} } + + b, err := encoder.Encode(c) + if err != nil { + return ConfigMarshalError{err} + } + + _, err = w.Write(b) + if err != nil { + return ConfigMarshalError{err} + } + return nil } @@ -2019,13 +1991,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) { v.configPermissions = perm.Perm() } -// IniLoadOptions sets the load options for ini parsing. -func IniLoadOptions(in ini.LoadOptions) Option { - return optionFunc(func(v *Viper) { - v.iniLoadOptions = in - }) -} - func (v *Viper) getConfigType() string { if v.configType != "" { return v.configType diff --git a/vendor/gopkg.in/ini.v1/.gitignore b/vendor/gopkg.in/ini.v1/.gitignore deleted file mode 100644 index 588388bd..00000000 --- a/vendor/gopkg.in/ini.v1/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -testdata/conf_out.ini -ini.sublime-project -ini.sublime-workspace -testdata/conf_reflect.ini -.idea -/.vscode -.DS_Store diff --git a/vendor/gopkg.in/ini.v1/.golangci.yml b/vendor/gopkg.in/ini.v1/.golangci.yml deleted file mode 100644 index 631e3692..00000000 --- a/vendor/gopkg.in/ini.v1/.golangci.yml +++ /dev/null @@ -1,27 +0,0 @@ -linters-settings: - staticcheck: - checks: [ - "all", - "-SA1019" # There are valid use cases of strings.Title - ] - nakedret: - max-func-lines: 0 # Disallow any unnamed return statement - -linters: - enable: - - deadcode - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - structcheck - - typecheck - - unused - - varcheck - - nakedret - - gofmt - - rowserrcheck - - unconvert - - goimports - - unparam diff --git a/vendor/gopkg.in/ini.v1/LICENSE b/vendor/gopkg.in/ini.v1/LICENSE deleted file mode 100644 index d361bbcd..00000000 --- a/vendor/gopkg.in/ini.v1/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright 2014 Unknwon - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/gopkg.in/ini.v1/Makefile b/vendor/gopkg.in/ini.v1/Makefile deleted file mode 100644 index f3b0dae2..00000000 --- a/vendor/gopkg.in/ini.v1/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: build test bench vet coverage - -build: vet bench - -test: - go test -v -cover -race - -bench: - go test -v -cover -test.bench=. -test.benchmem - -vet: - go vet - -coverage: - go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out diff --git a/vendor/gopkg.in/ini.v1/README.md b/vendor/gopkg.in/ini.v1/README.md deleted file mode 100644 index 30606d97..00000000 --- a/vendor/gopkg.in/ini.v1/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# INI - -[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain) -[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini) -[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc) -[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini) - -![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200) - -Package ini provides INI file read and write functionality in Go. - -## Features - -- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites. -- Read with recursion values. -- Read with parent-child sections. -- Read with auto-increment key names. -- Read with multiple-line values. -- Read with tons of helper methods. -- Read and convert values to Go types. -- Read and **WRITE** comments of sections and keys. -- Manipulate sections, keys and comments with ease. -- Keep sections and keys in order as you parse and save. - -## Installation - -The minimum requirement of Go is **1.13**. - -```sh -$ go get gopkg.in/ini.v1 -``` - -Please add `-u` flag to update in the future. - -## Getting Help - -- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started) -- [API Documentation](https://gowalker.org/gopkg.in/ini.v1) -- 中国大陆镜像:https://ini.unknwon.cn - -## License - -This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. diff --git a/vendor/gopkg.in/ini.v1/codecov.yml b/vendor/gopkg.in/ini.v1/codecov.yml deleted file mode 100644 index e02ec84b..00000000 --- a/vendor/gopkg.in/ini.v1/codecov.yml +++ /dev/null @@ -1,16 +0,0 @@ -coverage: - range: "60...95" - status: - project: - default: - threshold: 1% - informational: true - patch: - defualt: - only_pulls: true - informational: true - -comment: - layout: 'diff' - -github_checks: false diff --git a/vendor/gopkg.in/ini.v1/data_source.go b/vendor/gopkg.in/ini.v1/data_source.go deleted file mode 100644 index c3a541f1..00000000 --- a/vendor/gopkg.in/ini.v1/data_source.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" -) - -var ( - _ dataSource = (*sourceFile)(nil) - _ dataSource = (*sourceData)(nil) - _ dataSource = (*sourceReadCloser)(nil) -) - -// dataSource is an interface that returns object which can be read and closed. -type dataSource interface { - ReadCloser() (io.ReadCloser, error) -} - -// sourceFile represents an object that contains content on the local file system. -type sourceFile struct { - name string -} - -func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) { - return os.Open(s.name) -} - -// sourceData represents an object that contains content in memory. -type sourceData struct { - data []byte -} - -func (s *sourceData) ReadCloser() (io.ReadCloser, error) { - return ioutil.NopCloser(bytes.NewReader(s.data)), nil -} - -// sourceReadCloser represents an input stream with Close method. -type sourceReadCloser struct { - reader io.ReadCloser -} - -func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) { - return s.reader, nil -} - -func parseDataSource(source interface{}) (dataSource, error) { - switch s := source.(type) { - case string: - return sourceFile{s}, nil - case []byte: - return &sourceData{s}, nil - case io.ReadCloser: - return &sourceReadCloser{s}, nil - case io.Reader: - return &sourceReadCloser{ioutil.NopCloser(s)}, nil - default: - return nil, fmt.Errorf("error parsing data source: unknown type %q", s) - } -} diff --git a/vendor/gopkg.in/ini.v1/deprecated.go b/vendor/gopkg.in/ini.v1/deprecated.go deleted file mode 100644 index 48b8e66d..00000000 --- a/vendor/gopkg.in/ini.v1/deprecated.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -var ( - // Deprecated: Use "DefaultSection" instead. - DEFAULT_SECTION = DefaultSection - // Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. - AllCapsUnderscore = SnackCase -) diff --git a/vendor/gopkg.in/ini.v1/error.go b/vendor/gopkg.in/ini.v1/error.go deleted file mode 100644 index f66bc94b..00000000 --- a/vendor/gopkg.in/ini.v1/error.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "fmt" -) - -// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one. -type ErrDelimiterNotFound struct { - Line string -} - -// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound. -func IsErrDelimiterNotFound(err error) bool { - _, ok := err.(ErrDelimiterNotFound) - return ok -} - -func (err ErrDelimiterNotFound) Error() string { - return fmt.Sprintf("key-value delimiter not found: %s", err.Line) -} - -// ErrEmptyKeyName indicates the error type of no key name is found which there should be one. -type ErrEmptyKeyName struct { - Line string -} - -// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName. -func IsErrEmptyKeyName(err error) bool { - _, ok := err.(ErrEmptyKeyName) - return ok -} - -func (err ErrEmptyKeyName) Error() string { - return fmt.Sprintf("empty key name: %s", err.Line) -} diff --git a/vendor/gopkg.in/ini.v1/file.go b/vendor/gopkg.in/ini.v1/file.go deleted file mode 100644 index f8b22408..00000000 --- a/vendor/gopkg.in/ini.v1/file.go +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright 2017 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "bytes" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "strings" - "sync" -) - -// File represents a combination of one or more INI files in memory. -type File struct { - options LoadOptions - dataSources []dataSource - - // Should make things safe, but sometimes doesn't matter. - BlockMode bool - lock sync.RWMutex - - // To keep data in order. - sectionList []string - // To keep track of the index of a section with same name. - // This meta list is only used with non-unique section names are allowed. - sectionIndexes []int - - // Actual data is stored here. - sections map[string][]*Section - - NameMapper - ValueMapper -} - -// newFile initializes File object with given data sources. -func newFile(dataSources []dataSource, opts LoadOptions) *File { - if len(opts.KeyValueDelimiters) == 0 { - opts.KeyValueDelimiters = "=:" - } - if len(opts.KeyValueDelimiterOnWrite) == 0 { - opts.KeyValueDelimiterOnWrite = "=" - } - if len(opts.ChildSectionDelimiter) == 0 { - opts.ChildSectionDelimiter = "." - } - - return &File{ - BlockMode: true, - dataSources: dataSources, - sections: make(map[string][]*Section), - options: opts, - } -} - -// Empty returns an empty file object. -func Empty(opts ...LoadOptions) *File { - var opt LoadOptions - if len(opts) > 0 { - opt = opts[0] - } - - // Ignore error here, we are sure our data is good. - f, _ := LoadSources(opt, []byte("")) - return f -} - -// NewSection creates a new section. -func (f *File) NewSection(name string) (*Section, error) { - if len(name) == 0 { - return nil, errors.New("empty section name") - } - - if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) { - return f.sections[name][0], nil - } - - f.sectionList = append(f.sectionList, name) - - // NOTE: Append to indexes must happen before appending to sections, - // otherwise index will have off-by-one problem. - f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name])) - - sec := newSection(f, name) - f.sections[name] = append(f.sections[name], sec) - - return sec, nil -} - -// NewRawSection creates a new section with an unparseable body. -func (f *File) NewRawSection(name, body string) (*Section, error) { - section, err := f.NewSection(name) - if err != nil { - return nil, err - } - - section.isRawSection = true - section.rawBody = body - return section, nil -} - -// NewSections creates a list of sections. -func (f *File) NewSections(names ...string) (err error) { - for _, name := range names { - if _, err = f.NewSection(name); err != nil { - return err - } - } - return nil -} - -// GetSection returns section by given name. -func (f *File) GetSection(name string) (*Section, error) { - secs, err := f.SectionsByName(name) - if err != nil { - return nil, err - } - - return secs[0], err -} - -// HasSection returns true if the file contains a section with given name. -func (f *File) HasSection(name string) bool { - section, _ := f.GetSection(name) - return section != nil -} - -// SectionsByName returns all sections with given name. -func (f *File) SectionsByName(name string) ([]*Section, error) { - if len(name) == 0 { - name = DefaultSection - } - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - secs := f.sections[name] - if len(secs) == 0 { - return nil, fmt.Errorf("section %q does not exist", name) - } - - return secs, nil -} - -// Section assumes named section exists and returns a zero-value when not. -func (f *File) Section(name string) *Section { - sec, err := f.GetSection(name) - if err != nil { - if name == "" { - name = DefaultSection - } - sec, _ = f.NewSection(name) - return sec - } - return sec -} - -// SectionWithIndex assumes named section exists and returns a new section when not. -func (f *File) SectionWithIndex(name string, index int) *Section { - secs, err := f.SectionsByName(name) - if err != nil || len(secs) <= index { - // NOTE: It's OK here because the only possible error is empty section name, - // but if it's empty, this piece of code won't be executed. - newSec, _ := f.NewSection(name) - return newSec - } - - return secs[index] -} - -// Sections returns a list of Section stored in the current instance. -func (f *File) Sections() []*Section { - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - sections := make([]*Section, len(f.sectionList)) - for i, name := range f.sectionList { - sections[i] = f.sections[name][f.sectionIndexes[i]] - } - return sections -} - -// ChildSections returns a list of child sections of given section name. -func (f *File) ChildSections(name string) []*Section { - return f.Section(name).ChildSections() -} - -// SectionStrings returns list of section names. -func (f *File) SectionStrings() []string { - list := make([]string, len(f.sectionList)) - copy(list, f.sectionList) - return list -} - -// DeleteSection deletes a section or all sections with given name. -func (f *File) DeleteSection(name string) { - secs, err := f.SectionsByName(name) - if err != nil { - return - } - - for i := 0; i < len(secs); i++ { - // For non-unique sections, it is always needed to remove the first one so - // in the next iteration, the subsequent section continue having index 0. - // Ignoring the error as index 0 never returns an error. - _ = f.DeleteSectionWithIndex(name, 0) - } -} - -// DeleteSectionWithIndex deletes a section with given name and index. -func (f *File) DeleteSectionWithIndex(name string, index int) error { - if !f.options.AllowNonUniqueSections && index != 0 { - return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled") - } - - if len(name) == 0 { - name = DefaultSection - } - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - // Count occurrences of the sections - occurrences := 0 - - sectionListCopy := make([]string, len(f.sectionList)) - copy(sectionListCopy, f.sectionList) - - for i, s := range sectionListCopy { - if s != name { - continue - } - - if occurrences == index { - if len(f.sections[name]) <= 1 { - delete(f.sections, name) // The last one in the map - } else { - f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...) - } - - // Fix section lists - f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) - f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...) - - } else if occurrences > index { - // Fix the indices of all following sections with this name. - f.sectionIndexes[i-1]-- - } - - occurrences++ - } - - return nil -} - -func (f *File) reload(s dataSource) error { - r, err := s.ReadCloser() - if err != nil { - return err - } - defer r.Close() - - return f.parse(r) -} - -// Reload reloads and parses all data sources. -func (f *File) Reload() (err error) { - for _, s := range f.dataSources { - if err = f.reload(s); err != nil { - // In loose mode, we create an empty default section for nonexistent files. - if os.IsNotExist(err) && f.options.Loose { - _ = f.parse(bytes.NewBuffer(nil)) - continue - } - return err - } - if f.options.ShortCircuit { - return nil - } - } - return nil -} - -// Append appends one or more data sources and reloads automatically. -func (f *File) Append(source interface{}, others ...interface{}) error { - ds, err := parseDataSource(source) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - for _, s := range others { - ds, err = parseDataSource(s) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - } - return f.Reload() -} - -func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) { - equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight - - if PrettyFormat || PrettyEqual { - equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite) - } - - // Use buffer to make sure target is safe until finish encoding. - buf := bytes.NewBuffer(nil) - lastSectionIdx := len(f.sectionList) - 1 - for i, sname := range f.sectionList { - sec := f.SectionWithIndex(sname, f.sectionIndexes[i]) - if len(sec.Comment) > 0 { - // Support multiline comments - lines := strings.Split(sec.Comment, LineBreak) - for i := range lines { - if lines[i][0] != '#' && lines[i][0] != ';' { - lines[i] = "; " + lines[i] - } else { - lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) - } - - if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { - return nil, err - } - } - } - - if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) { - if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil { - return nil, err - } - } else { - // Write nothing if default section is empty - if len(sec.keyList) == 0 { - continue - } - } - - isLastSection := i == lastSectionIdx - if sec.isRawSection { - if _, err := buf.WriteString(sec.rawBody); err != nil { - return nil, err - } - - if PrettySection && !isLastSection { - // Put a line between sections - if _, err := buf.WriteString(LineBreak); err != nil { - return nil, err - } - } - continue - } - - // Count and generate alignment length and buffer spaces using the - // longest key. Keys may be modified if they contain certain characters so - // we need to take that into account in our calculation. - alignLength := 0 - if PrettyFormat { - for _, kname := range sec.keyList { - keyLength := len(kname) - // First case will surround key by ` and second by """ - if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) { - keyLength += 2 - } else if strings.Contains(kname, "`") { - keyLength += 6 - } - - if keyLength > alignLength { - alignLength = keyLength - } - } - } - alignSpaces := bytes.Repeat([]byte(" "), alignLength) - - KeyList: - for _, kname := range sec.keyList { - key := sec.Key(kname) - if len(key.Comment) > 0 { - if len(indent) > 0 && sname != DefaultSection { - buf.WriteString(indent) - } - - // Support multiline comments - lines := strings.Split(key.Comment, LineBreak) - for i := range lines { - if lines[i][0] != '#' && lines[i][0] != ';' { - lines[i] = "; " + strings.TrimSpace(lines[i]) - } else { - lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) - } - - if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { - return nil, err - } - } - } - - if len(indent) > 0 && sname != DefaultSection { - buf.WriteString(indent) - } - - switch { - case key.isAutoIncrement: - kname = "-" - case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters): - kname = "`" + kname + "`" - case strings.Contains(kname, "`"): - kname = `"""` + kname + `"""` - } - - writeKeyValue := func(val string) (bool, error) { - if _, err := buf.WriteString(kname); err != nil { - return false, err - } - - if key.isBooleanType { - buf.WriteString(LineBreak) - return true, nil - } - - // Write out alignment spaces before "=" sign - if PrettyFormat { - buf.Write(alignSpaces[:alignLength-len(kname)]) - } - - // In case key value contains "\n", "`", "\"", "#" or ";" - if strings.ContainsAny(val, "\n`") { - val = `"""` + val + `"""` - } else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") { - val = "`" + val + "`" - } else if len(strings.TrimSpace(val)) != len(val) { - val = `"` + val + `"` - } - if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil { - return false, err - } - return false, nil - } - - shadows := key.ValueWithShadows() - if len(shadows) == 0 { - if _, err := writeKeyValue(""); err != nil { - return nil, err - } - } - - for _, val := range shadows { - exitLoop, err := writeKeyValue(val) - if err != nil { - return nil, err - } else if exitLoop { - continue KeyList - } - } - - for _, val := range key.nestedValues { - if _, err := buf.WriteString(indent + " " + val + LineBreak); err != nil { - return nil, err - } - } - } - - if PrettySection && !isLastSection { - // Put a line between sections - if _, err := buf.WriteString(LineBreak); err != nil { - return nil, err - } - } - } - - return buf, nil -} - -// WriteToIndent writes content into io.Writer with given indention. -// If PrettyFormat has been set to be true, -// it will align "=" sign with spaces under each section. -func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) { - buf, err := f.writeToBuffer(indent) - if err != nil { - return 0, err - } - return buf.WriteTo(w) -} - -// WriteTo writes file content into io.Writer. -func (f *File) WriteTo(w io.Writer) (int64, error) { - return f.WriteToIndent(w, "") -} - -// SaveToIndent writes content to file system with given value indention. -func (f *File) SaveToIndent(filename, indent string) error { - // Note: Because we are truncating with os.Create, - // so it's safer to save to a temporary file location and rename after done. - buf, err := f.writeToBuffer(indent) - if err != nil { - return err - } - - return ioutil.WriteFile(filename, buf.Bytes(), 0666) -} - -// SaveTo writes content to file system. -func (f *File) SaveTo(filename string) error { - return f.SaveToIndent(filename, "") -} diff --git a/vendor/gopkg.in/ini.v1/helper.go b/vendor/gopkg.in/ini.v1/helper.go deleted file mode 100644 index f9d80a68..00000000 --- a/vendor/gopkg.in/ini.v1/helper.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -func inSlice(str string, s []string) bool { - for _, v := range s { - if str == v { - return true - } - } - return false -} diff --git a/vendor/gopkg.in/ini.v1/ini.go b/vendor/gopkg.in/ini.v1/ini.go deleted file mode 100644 index 99e7f865..00000000 --- a/vendor/gopkg.in/ini.v1/ini.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -// Package ini provides INI file read and write functionality in Go. -package ini - -import ( - "os" - "regexp" - "runtime" - "strings" -) - -const ( - // Maximum allowed depth when recursively substituing variable names. - depthValues = 99 -) - -var ( - // DefaultSection is the name of default section. You can use this var or the string literal. - // In most of cases, an empty string is all you need to access the section. - DefaultSection = "DEFAULT" - - // LineBreak is the delimiter to determine or compose a new line. - // This variable will be changed to "\r\n" automatically on Windows at package init time. - LineBreak = "\n" - - // Variable regexp pattern: %(variable)s - varPattern = regexp.MustCompile(`%\(([^)]+)\)s`) - - // DefaultHeader explicitly writes default section header. - DefaultHeader = false - - // PrettySection indicates whether to put a line between sections. - PrettySection = true - // PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output - // or reduce all possible spaces for compact format. - PrettyFormat = true - // PrettyEqual places spaces around "=" sign even when PrettyFormat is false. - PrettyEqual = false - // DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled. - DefaultFormatLeft = "" - // DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled. - DefaultFormatRight = "" -) - -var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") - -func init() { - if runtime.GOOS == "windows" && !inTest { - LineBreak = "\r\n" - } -} - -// LoadOptions contains all customized options used for load data source(s). -type LoadOptions struct { - // Loose indicates whether the parser should ignore nonexistent files or return error. - Loose bool - // Insensitive indicates whether the parser forces all section and key names to lowercase. - Insensitive bool - // InsensitiveSections indicates whether the parser forces all section to lowercase. - InsensitiveSections bool - // InsensitiveKeys indicates whether the parser forces all key names to lowercase. - InsensitiveKeys bool - // IgnoreContinuation indicates whether to ignore continuation lines while parsing. - IgnoreContinuation bool - // IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value. - IgnoreInlineComment bool - // SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs. - SkipUnrecognizableLines bool - // ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source. - ShortCircuit bool - // AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing. - // This type of keys are mostly used in my.cnf. - AllowBooleanKeys bool - // AllowShadows indicates whether to keep track of keys with same name under same section. - AllowShadows bool - // AllowNestedValues indicates whether to allow AWS-like nested values. - // Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values - AllowNestedValues bool - // AllowPythonMultilineValues indicates whether to allow Python-like multi-line values. - // Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure - // Relevant quote: Values can also span multiple lines, as long as they are indented deeper - // than the first line of the value. - AllowPythonMultilineValues bool - // SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value. - // Docs: https://docs.python.org/2/library/configparser.html - // Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names. - // In the latter case, they need to be preceded by a whitespace character to be recognized as a comment. - SpaceBeforeInlineComment bool - // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format - // when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value" - UnescapeValueDoubleQuotes bool - // UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format - // when value is NOT surrounded by any quotes. - // Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all. - UnescapeValueCommentSymbols bool - // UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise - // conform to key/value pairs. Specify the names of those blocks here. - UnparseableSections []string - // KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:". - KeyValueDelimiters string - // KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=". - KeyValueDelimiterOnWrite string - // ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".". - ChildSectionDelimiter string - // PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes). - PreserveSurroundedQuote bool - // DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values). - DebugFunc DebugFunc - // ReaderBufferSize is the buffer size of the reader in bytes. - ReaderBufferSize int - // AllowNonUniqueSections indicates whether to allow sections with the same name multiple times. - AllowNonUniqueSections bool - // AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated. - AllowDuplicateShadowValues bool -} - -// DebugFunc is the type of function called to log parse events. -type DebugFunc func(message string) - -// LoadSources allows caller to apply customized options for loading from data source(s). -func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) { - sources := make([]dataSource, len(others)+1) - sources[0], err = parseDataSource(source) - if err != nil { - return nil, err - } - for i := range others { - sources[i+1], err = parseDataSource(others[i]) - if err != nil { - return nil, err - } - } - f := newFile(sources, opts) - if err = f.Reload(); err != nil { - return nil, err - } - return f, nil -} - -// Load loads and parses from INI data sources. -// Arguments can be mixed of file name with string type, or raw data in []byte. -// It will return error if list contains nonexistent files. -func Load(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{}, source, others...) -} - -// LooseLoad has exactly same functionality as Load function -// except it ignores nonexistent files instead of returning error. -func LooseLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{Loose: true}, source, others...) -} - -// InsensitiveLoad has exactly same functionality as Load function -// except it forces all section and key names to be lowercased. -func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{Insensitive: true}, source, others...) -} - -// ShadowLoad has exactly same functionality as Load function -// except it allows have shadow keys. -func ShadowLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{AllowShadows: true}, source, others...) -} diff --git a/vendor/gopkg.in/ini.v1/key.go b/vendor/gopkg.in/ini.v1/key.go deleted file mode 100644 index a19d9f38..00000000 --- a/vendor/gopkg.in/ini.v1/key.go +++ /dev/null @@ -1,837 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "bytes" - "errors" - "fmt" - "strconv" - "strings" - "time" -) - -// Key represents a key under a section. -type Key struct { - s *Section - Comment string - name string - value string - isAutoIncrement bool - isBooleanType bool - - isShadow bool - shadows []*Key - - nestedValues []string -} - -// newKey simply return a key object with given values. -func newKey(s *Section, name, val string) *Key { - return &Key{ - s: s, - name: name, - value: val, - } -} - -func (k *Key) addShadow(val string) error { - if k.isShadow { - return errors.New("cannot add shadow to another shadow key") - } else if k.isAutoIncrement || k.isBooleanType { - return errors.New("cannot add shadow to auto-increment or boolean key") - } - - if !k.s.f.options.AllowDuplicateShadowValues { - // Deduplicate shadows based on their values. - if k.value == val { - return nil - } - for i := range k.shadows { - if k.shadows[i].value == val { - return nil - } - } - } - - shadow := newKey(k.s, k.name, val) - shadow.isShadow = true - k.shadows = append(k.shadows, shadow) - return nil -} - -// AddShadow adds a new shadow key to itself. -func (k *Key) AddShadow(val string) error { - if !k.s.f.options.AllowShadows { - return errors.New("shadow key is not allowed") - } - return k.addShadow(val) -} - -func (k *Key) addNestedValue(val string) error { - if k.isAutoIncrement || k.isBooleanType { - return errors.New("cannot add nested value to auto-increment or boolean key") - } - - k.nestedValues = append(k.nestedValues, val) - return nil -} - -// AddNestedValue adds a nested value to the key. -func (k *Key) AddNestedValue(val string) error { - if !k.s.f.options.AllowNestedValues { - return errors.New("nested value is not allowed") - } - return k.addNestedValue(val) -} - -// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv -type ValueMapper func(string) string - -// Name returns name of key. -func (k *Key) Name() string { - return k.name -} - -// Value returns raw value of key for performance purpose. -func (k *Key) Value() string { - return k.value -} - -// ValueWithShadows returns raw values of key and its shadows if any. Shadow -// keys with empty values are ignored from the returned list. -func (k *Key) ValueWithShadows() []string { - if len(k.shadows) == 0 { - if k.value == "" { - return []string{} - } - return []string{k.value} - } - - vals := make([]string, 0, len(k.shadows)+1) - if k.value != "" { - vals = append(vals, k.value) - } - for _, s := range k.shadows { - if s.value != "" { - vals = append(vals, s.value) - } - } - return vals -} - -// NestedValues returns nested values stored in the key. -// It is possible returned value is nil if no nested values stored in the key. -func (k *Key) NestedValues() []string { - return k.nestedValues -} - -// transformValue takes a raw value and transforms to its final string. -func (k *Key) transformValue(val string) string { - if k.s.f.ValueMapper != nil { - val = k.s.f.ValueMapper(val) - } - - // Fail-fast if no indicate char found for recursive value - if !strings.Contains(val, "%") { - return val - } - for i := 0; i < depthValues; i++ { - vr := varPattern.FindString(val) - if len(vr) == 0 { - break - } - - // Take off leading '%(' and trailing ')s'. - noption := vr[2 : len(vr)-2] - - // Search in the same section. - // If not found or found the key itself, then search again in default section. - nk, err := k.s.GetKey(noption) - if err != nil || k == nk { - nk, _ = k.s.f.Section("").GetKey(noption) - if nk == nil { - // Stop when no results found in the default section, - // and returns the value as-is. - break - } - } - - // Substitute by new value and take off leading '%(' and trailing ')s'. - val = strings.Replace(val, vr, nk.value, -1) - } - return val -} - -// String returns string representation of value. -func (k *Key) String() string { - return k.transformValue(k.value) -} - -// Validate accepts a validate function which can -// return modifed result as key value. -func (k *Key) Validate(fn func(string) string) string { - return fn(k.String()) -} - -// parseBool returns the boolean value represented by the string. -// -// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On, -// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off. -// Any other value returns an error. -func parseBool(str string) (value bool, err error) { - switch str { - case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On": - return true, nil - case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off": - return false, nil - } - return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) -} - -// Bool returns bool type value. -func (k *Key) Bool() (bool, error) { - return parseBool(k.String()) -} - -// Float64 returns float64 type value. -func (k *Key) Float64() (float64, error) { - return strconv.ParseFloat(k.String(), 64) -} - -// Int returns int type value. -func (k *Key) Int() (int, error) { - v, err := strconv.ParseInt(k.String(), 0, 64) - return int(v), err -} - -// Int64 returns int64 type value. -func (k *Key) Int64() (int64, error) { - return strconv.ParseInt(k.String(), 0, 64) -} - -// Uint returns uint type valued. -func (k *Key) Uint() (uint, error) { - u, e := strconv.ParseUint(k.String(), 0, 64) - return uint(u), e -} - -// Uint64 returns uint64 type value. -func (k *Key) Uint64() (uint64, error) { - return strconv.ParseUint(k.String(), 0, 64) -} - -// Duration returns time.Duration type value. -func (k *Key) Duration() (time.Duration, error) { - return time.ParseDuration(k.String()) -} - -// TimeFormat parses with given format and returns time.Time type value. -func (k *Key) TimeFormat(format string) (time.Time, error) { - return time.Parse(format, k.String()) -} - -// Time parses with RFC3339 format and returns time.Time type value. -func (k *Key) Time() (time.Time, error) { - return k.TimeFormat(time.RFC3339) -} - -// MustString returns default value if key value is empty. -func (k *Key) MustString(defaultVal string) string { - val := k.String() - if len(val) == 0 { - k.value = defaultVal - return defaultVal - } - return val -} - -// MustBool always returns value without error, -// it returns false if error occurs. -func (k *Key) MustBool(defaultVal ...bool) bool { - val, err := k.Bool() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatBool(defaultVal[0]) - return defaultVal[0] - } - return val -} - -// MustFloat64 always returns value without error, -// it returns 0.0 if error occurs. -func (k *Key) MustFloat64(defaultVal ...float64) float64 { - val, err := k.Float64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64) - return defaultVal[0] - } - return val -} - -// MustInt always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt(defaultVal ...int) int { - val, err := k.Int() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatInt(int64(defaultVal[0]), 10) - return defaultVal[0] - } - return val -} - -// MustInt64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt64(defaultVal ...int64) int64 { - val, err := k.Int64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatInt(defaultVal[0], 10) - return defaultVal[0] - } - return val -} - -// MustUint always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint(defaultVal ...uint) uint { - val, err := k.Uint() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatUint(uint64(defaultVal[0]), 10) - return defaultVal[0] - } - return val -} - -// MustUint64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint64(defaultVal ...uint64) uint64 { - val, err := k.Uint64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatUint(defaultVal[0], 10) - return defaultVal[0] - } - return val -} - -// MustDuration always returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration { - val, err := k.Duration() - if len(defaultVal) > 0 && err != nil { - k.value = defaultVal[0].String() - return defaultVal[0] - } - return val -} - -// MustTimeFormat always parses with given format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { - val, err := k.TimeFormat(format) - if len(defaultVal) > 0 && err != nil { - k.value = defaultVal[0].Format(format) - return defaultVal[0] - } - return val -} - -// MustTime always parses with RFC3339 format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTime(defaultVal ...time.Time) time.Time { - return k.MustTimeFormat(time.RFC3339, defaultVal...) -} - -// In always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) In(defaultVal string, candidates []string) string { - val := k.String() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InFloat64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { - val := k.MustFloat64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt(defaultVal int, candidates []int) int { - val := k.MustInt() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { - val := k.MustInt64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint(defaultVal uint, candidates []uint) uint { - val := k.MustUint() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 { - val := k.MustUint64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTimeFormat always parses with given format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { - val := k.MustTimeFormat(format) - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTime always parses with RFC3339 format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { - return k.InTimeFormat(time.RFC3339, defaultVal, candidates) -} - -// RangeFloat64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { - val := k.MustFloat64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt(defaultVal, min, max int) int { - val := k.MustInt() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { - val := k.MustInt64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeTimeFormat checks if value with given format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { - val := k.MustTimeFormat(format) - if val.Unix() < min.Unix() || val.Unix() > max.Unix() { - return defaultVal - } - return val -} - -// RangeTime checks if value with RFC3339 format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { - return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) -} - -// Strings returns list of string divided by given delimiter. -func (k *Key) Strings(delim string) []string { - str := k.String() - if len(str) == 0 { - return []string{} - } - - runes := []rune(str) - vals := make([]string, 0, 2) - var buf bytes.Buffer - escape := false - idx := 0 - for { - if escape { - escape = false - if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) { - buf.WriteRune('\\') - } - buf.WriteRune(runes[idx]) - } else { - if runes[idx] == '\\' { - escape = true - } else if strings.HasPrefix(string(runes[idx:]), delim) { - idx += len(delim) - 1 - vals = append(vals, strings.TrimSpace(buf.String())) - buf.Reset() - } else { - buf.WriteRune(runes[idx]) - } - } - idx++ - if idx == len(runes) { - break - } - } - - if buf.Len() > 0 { - vals = append(vals, strings.TrimSpace(buf.String())) - } - - return vals -} - -// StringsWithShadows returns list of string divided by given delimiter. -// Shadows will also be appended if any. -func (k *Key) StringsWithShadows(delim string) []string { - vals := k.ValueWithShadows() - results := make([]string, 0, len(vals)*2) - for i := range vals { - if len(vals) == 0 { - continue - } - - results = append(results, strings.Split(vals[i], delim)...) - } - - for i := range results { - results[i] = k.transformValue(strings.TrimSpace(results[i])) - } - return results -} - -// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Float64s(delim string) []float64 { - vals, _ := k.parseFloat64s(k.Strings(delim), true, false) - return vals -} - -// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Ints(delim string) []int { - vals, _ := k.parseInts(k.Strings(delim), true, false) - return vals -} - -// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Int64s(delim string) []int64 { - vals, _ := k.parseInt64s(k.Strings(delim), true, false) - return vals -} - -// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Uints(delim string) []uint { - vals, _ := k.parseUints(k.Strings(delim), true, false) - return vals -} - -// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Uint64s(delim string) []uint64 { - vals, _ := k.parseUint64s(k.Strings(delim), true, false) - return vals -} - -// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Bools(delim string) []bool { - vals, _ := k.parseBools(k.Strings(delim), true, false) - return vals -} - -// TimesFormat parses with given format and returns list of time.Time divided by given delimiter. -// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). -func (k *Key) TimesFormat(format, delim string) []time.Time { - vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false) - return vals -} - -// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter. -// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). -func (k *Key) Times(delim string) []time.Time { - return k.TimesFormat(time.RFC3339, delim) -} - -// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then -// it will not be included to result list. -func (k *Key) ValidFloat64s(delim string) []float64 { - vals, _ := k.parseFloat64s(k.Strings(delim), false, false) - return vals -} - -// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will -// not be included to result list. -func (k *Key) ValidInts(delim string) []int { - vals, _ := k.parseInts(k.Strings(delim), false, false) - return vals -} - -// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer, -// then it will not be included to result list. -func (k *Key) ValidInt64s(delim string) []int64 { - vals, _ := k.parseInt64s(k.Strings(delim), false, false) - return vals -} - -// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer, -// then it will not be included to result list. -func (k *Key) ValidUints(delim string) []uint { - vals, _ := k.parseUints(k.Strings(delim), false, false) - return vals -} - -// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned -// integer, then it will not be included to result list. -func (k *Key) ValidUint64s(delim string) []uint64 { - vals, _ := k.parseUint64s(k.Strings(delim), false, false) - return vals -} - -// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned -// integer, then it will not be included to result list. -func (k *Key) ValidBools(delim string) []bool { - vals, _ := k.parseBools(k.Strings(delim), false, false) - return vals -} - -// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter. -func (k *Key) ValidTimesFormat(format, delim string) []time.Time { - vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false) - return vals -} - -// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter. -func (k *Key) ValidTimes(delim string) []time.Time { - return k.ValidTimesFormat(time.RFC3339, delim) -} - -// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictFloat64s(delim string) ([]float64, error) { - return k.parseFloat64s(k.Strings(delim), false, true) -} - -// StrictInts returns list of int divided by given delimiter or error on first invalid input. -func (k *Key) StrictInts(delim string) ([]int, error) { - return k.parseInts(k.Strings(delim), false, true) -} - -// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictInt64s(delim string) ([]int64, error) { - return k.parseInt64s(k.Strings(delim), false, true) -} - -// StrictUints returns list of uint divided by given delimiter or error on first invalid input. -func (k *Key) StrictUints(delim string) ([]uint, error) { - return k.parseUints(k.Strings(delim), false, true) -} - -// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictUint64s(delim string) ([]uint64, error) { - return k.parseUint64s(k.Strings(delim), false, true) -} - -// StrictBools returns list of bool divided by given delimiter or error on first invalid input. -func (k *Key) StrictBools(delim string) ([]bool, error) { - return k.parseBools(k.Strings(delim), false, true) -} - -// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter -// or error on first invalid input. -func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) { - return k.parseTimesFormat(format, k.Strings(delim), false, true) -} - -// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter -// or error on first invalid input. -func (k *Key) StrictTimes(delim string) ([]time.Time, error) { - return k.StrictTimesFormat(time.RFC3339, delim) -} - -// parseBools transforms strings to bools. -func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) { - vals := make([]bool, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := parseBool(str) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(bool)) - } - } - return vals, err -} - -// parseFloat64s transforms strings to float64s. -func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) { - vals := make([]float64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseFloat(str, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(float64)) - } - } - return vals, err -} - -// parseInts transforms strings to ints. -func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) { - vals := make([]int, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseInt(str, 0, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, int(val.(int64))) - } - } - return vals, err -} - -// parseInt64s transforms strings to int64s. -func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) { - vals := make([]int64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseInt(str, 0, 64) - return val, err - } - - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(int64)) - } - } - return vals, err -} - -// parseUints transforms strings to uints. -func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) { - vals := make([]uint, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseUint(str, 0, 64) - return val, err - } - - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, uint(val.(uint64))) - } - } - return vals, err -} - -// parseUint64s transforms strings to uint64s. -func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) { - vals := make([]uint64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseUint(str, 0, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(uint64)) - } - } - return vals, err -} - -type Parser func(str string) (interface{}, error) - -// parseTimesFormat transforms strings to times in given format. -func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) { - vals := make([]time.Time, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := time.Parse(format, str) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(time.Time)) - } - } - return vals, err -} - -// doParse transforms strings to different types -func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) { - vals := make([]interface{}, 0, len(strs)) - for _, str := range strs { - val, err := parser(str) - if err != nil && returnOnInvalid { - return nil, err - } - if err == nil || addInvalid { - vals = append(vals, val) - } - } - return vals, nil -} - -// SetValue changes key value. -func (k *Key) SetValue(v string) { - if k.s.f.BlockMode { - k.s.f.lock.Lock() - defer k.s.f.lock.Unlock() - } - - k.value = v - k.s.keysHash[k.name] = v -} diff --git a/vendor/gopkg.in/ini.v1/parser.go b/vendor/gopkg.in/ini.v1/parser.go deleted file mode 100644 index 44fc526c..00000000 --- a/vendor/gopkg.in/ini.v1/parser.go +++ /dev/null @@ -1,520 +0,0 @@ -// Copyright 2015 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "bufio" - "bytes" - "fmt" - "io" - "regexp" - "strconv" - "strings" - "unicode" -) - -const minReaderBufferSize = 4096 - -var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`) - -type parserOptions struct { - IgnoreContinuation bool - IgnoreInlineComment bool - AllowPythonMultilineValues bool - SpaceBeforeInlineComment bool - UnescapeValueDoubleQuotes bool - UnescapeValueCommentSymbols bool - PreserveSurroundedQuote bool - DebugFunc DebugFunc - ReaderBufferSize int -} - -type parser struct { - buf *bufio.Reader - options parserOptions - - isEOF bool - count int - comment *bytes.Buffer -} - -func (p *parser) debug(format string, args ...interface{}) { - if p.options.DebugFunc != nil { - p.options.DebugFunc(fmt.Sprintf(format, args...)) - } -} - -func newParser(r io.Reader, opts parserOptions) *parser { - size := opts.ReaderBufferSize - if size < minReaderBufferSize { - size = minReaderBufferSize - } - - return &parser{ - buf: bufio.NewReaderSize(r, size), - options: opts, - count: 1, - comment: &bytes.Buffer{}, - } -} - -// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format. -// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding -func (p *parser) BOM() error { - mask, err := p.buf.Peek(2) - if err != nil && err != io.EOF { - return err - } else if len(mask) < 2 { - return nil - } - - switch { - case mask[0] == 254 && mask[1] == 255: - fallthrough - case mask[0] == 255 && mask[1] == 254: - _, err = p.buf.Read(mask) - if err != nil { - return err - } - case mask[0] == 239 && mask[1] == 187: - mask, err := p.buf.Peek(3) - if err != nil && err != io.EOF { - return err - } else if len(mask) < 3 { - return nil - } - if mask[2] == 191 { - _, err = p.buf.Read(mask) - if err != nil { - return err - } - } - } - return nil -} - -func (p *parser) readUntil(delim byte) ([]byte, error) { - data, err := p.buf.ReadBytes(delim) - if err != nil { - if err == io.EOF { - p.isEOF = true - } else { - return nil, err - } - } - return data, nil -} - -func cleanComment(in []byte) ([]byte, bool) { - i := bytes.IndexAny(in, "#;") - if i == -1 { - return nil, false - } - return in[i:], true -} - -func readKeyName(delimiters string, in []byte) (string, int, error) { - line := string(in) - - // Check if key name surrounded by quotes. - var keyQuote string - if line[0] == '"' { - if len(line) > 6 && line[0:3] == `"""` { - keyQuote = `"""` - } else { - keyQuote = `"` - } - } else if line[0] == '`' { - keyQuote = "`" - } - - // Get out key name - var endIdx int - if len(keyQuote) > 0 { - startIdx := len(keyQuote) - // FIXME: fail case -> """"""name"""=value - pos := strings.Index(line[startIdx:], keyQuote) - if pos == -1 { - return "", -1, fmt.Errorf("missing closing key quote: %s", line) - } - pos += startIdx - - // Find key-value delimiter - i := strings.IndexAny(line[pos+startIdx:], delimiters) - if i < 0 { - return "", -1, ErrDelimiterNotFound{line} - } - endIdx = pos + i - return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil - } - - endIdx = strings.IndexAny(line, delimiters) - if endIdx < 0 { - return "", -1, ErrDelimiterNotFound{line} - } - if endIdx == 0 { - return "", -1, ErrEmptyKeyName{line} - } - - return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil -} - -func (p *parser) readMultilines(line, val, valQuote string) (string, error) { - for { - data, err := p.readUntil('\n') - if err != nil { - return "", err - } - next := string(data) - - pos := strings.LastIndex(next, valQuote) - if pos > -1 { - val += next[:pos] - - comment, has := cleanComment([]byte(next[pos:])) - if has { - p.comment.Write(bytes.TrimSpace(comment)) - } - break - } - val += next - if p.isEOF { - return "", fmt.Errorf("missing closing key quote from %q to %q", line, next) - } - } - return val, nil -} - -func (p *parser) readContinuationLines(val string) (string, error) { - for { - data, err := p.readUntil('\n') - if err != nil { - return "", err - } - next := strings.TrimSpace(string(data)) - - if len(next) == 0 { - break - } - val += next - if val[len(val)-1] != '\\' { - break - } - val = val[:len(val)-1] - } - return val, nil -} - -// hasSurroundedQuote check if and only if the first and last characters -// are quotes \" or \'. -// It returns false if any other parts also contain same kind of quotes. -func hasSurroundedQuote(in string, quote byte) bool { - return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote && - strings.IndexByte(in[1:], quote) == len(in)-2 -} - -func (p *parser) readValue(in []byte, bufferSize int) (string, error) { - - line := strings.TrimLeftFunc(string(in), unicode.IsSpace) - if len(line) == 0 { - if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' { - return p.readPythonMultilines(line, bufferSize) - } - return "", nil - } - - var valQuote string - if len(line) > 3 && line[0:3] == `"""` { - valQuote = `"""` - } else if line[0] == '`' { - valQuote = "`" - } else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' { - valQuote = `"` - } - - if len(valQuote) > 0 { - startIdx := len(valQuote) - pos := strings.LastIndex(line[startIdx:], valQuote) - // Check for multi-line value - if pos == -1 { - return p.readMultilines(line, line[startIdx:], valQuote) - } - - if p.options.UnescapeValueDoubleQuotes && valQuote == `"` { - return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil - } - return line[startIdx : pos+startIdx], nil - } - - lastChar := line[len(line)-1] - // Won't be able to reach here if value only contains whitespace - line = strings.TrimSpace(line) - trimmedLastChar := line[len(line)-1] - - // Check continuation lines when desired - if !p.options.IgnoreContinuation && trimmedLastChar == '\\' { - return p.readContinuationLines(line[:len(line)-1]) - } - - // Check if ignore inline comment - if !p.options.IgnoreInlineComment { - var i int - if p.options.SpaceBeforeInlineComment { - i = strings.Index(line, " #") - if i == -1 { - i = strings.Index(line, " ;") - } - - } else { - i = strings.IndexAny(line, "#;") - } - - if i > -1 { - p.comment.WriteString(line[i:]) - line = strings.TrimSpace(line[:i]) - } - - } - - // Trim single and double quotes - if (hasSurroundedQuote(line, '\'') || - hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote { - line = line[1 : len(line)-1] - } else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols { - line = strings.ReplaceAll(line, `\;`, ";") - line = strings.ReplaceAll(line, `\#`, "#") - } else if p.options.AllowPythonMultilineValues && lastChar == '\n' { - return p.readPythonMultilines(line, bufferSize) - } - - return line, nil -} - -func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) { - parserBufferPeekResult, _ := p.buf.Peek(bufferSize) - peekBuffer := bytes.NewBuffer(parserBufferPeekResult) - - for { - peekData, peekErr := peekBuffer.ReadBytes('\n') - if peekErr != nil && peekErr != io.EOF { - p.debug("readPythonMultilines: failed to peek with error: %v", peekErr) - return "", peekErr - } - - p.debug("readPythonMultilines: parsing %q", string(peekData)) - - peekMatches := pythonMultiline.FindStringSubmatch(string(peekData)) - p.debug("readPythonMultilines: matched %d parts", len(peekMatches)) - for n, v := range peekMatches { - p.debug(" %d: %q", n, v) - } - - // Return if not a Python multiline value. - if len(peekMatches) != 3 { - p.debug("readPythonMultilines: end of value, got: %q", line) - return line, nil - } - - // Advance the parser reader (buffer) in-sync with the peek buffer. - _, err := p.buf.Discard(len(peekData)) - if err != nil { - p.debug("readPythonMultilines: failed to skip to the end, returning error") - return "", err - } - - line += "\n" + peekMatches[0] - } -} - -// parse parses data through an io.Reader. -func (f *File) parse(reader io.Reader) (err error) { - p := newParser(reader, parserOptions{ - IgnoreContinuation: f.options.IgnoreContinuation, - IgnoreInlineComment: f.options.IgnoreInlineComment, - AllowPythonMultilineValues: f.options.AllowPythonMultilineValues, - SpaceBeforeInlineComment: f.options.SpaceBeforeInlineComment, - UnescapeValueDoubleQuotes: f.options.UnescapeValueDoubleQuotes, - UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols, - PreserveSurroundedQuote: f.options.PreserveSurroundedQuote, - DebugFunc: f.options.DebugFunc, - ReaderBufferSize: f.options.ReaderBufferSize, - }) - if err = p.BOM(); err != nil { - return fmt.Errorf("BOM: %v", err) - } - - // Ignore error because default section name is never empty string. - name := DefaultSection - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(DefaultSection) - } - section, _ := f.NewSection(name) - - // This "last" is not strictly equivalent to "previous one" if current key is not the first nested key - var isLastValueEmpty bool - var lastRegularKey *Key - - var line []byte - var inUnparseableSection bool - - // NOTE: Iterate and increase `currentPeekSize` until - // the size of the parser buffer is found. - // TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`. - parserBufferSize := 0 - // NOTE: Peek 4kb at a time. - currentPeekSize := minReaderBufferSize - - if f.options.AllowPythonMultilineValues { - for { - peekBytes, _ := p.buf.Peek(currentPeekSize) - peekBytesLength := len(peekBytes) - - if parserBufferSize >= peekBytesLength { - break - } - - currentPeekSize *= 2 - parserBufferSize = peekBytesLength - } - } - - for !p.isEOF { - line, err = p.readUntil('\n') - if err != nil { - return err - } - - if f.options.AllowNestedValues && - isLastValueEmpty && len(line) > 0 { - if line[0] == ' ' || line[0] == '\t' { - err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line))) - if err != nil { - return err - } - continue - } - } - - line = bytes.TrimLeftFunc(line, unicode.IsSpace) - if len(line) == 0 { - continue - } - - // Comments - if line[0] == '#' || line[0] == ';' { - // Note: we do not care ending line break, - // it is needed for adding second line, - // so just clean it once at the end when set to value. - p.comment.Write(line) - continue - } - - // Section - if line[0] == '[' { - // Read to the next ']' (TODO: support quoted strings) - closeIdx := bytes.LastIndexByte(line, ']') - if closeIdx == -1 { - return fmt.Errorf("unclosed section: %s", line) - } - - name := string(line[1:closeIdx]) - section, err = f.NewSection(name) - if err != nil { - return err - } - - comment, has := cleanComment(line[closeIdx+1:]) - if has { - p.comment.Write(comment) - } - - section.Comment = strings.TrimSpace(p.comment.String()) - - // Reset auto-counter and comments - p.comment.Reset() - p.count = 1 - // Nested values can't span sections - isLastValueEmpty = false - - inUnparseableSection = false - for i := range f.options.UnparseableSections { - if f.options.UnparseableSections[i] == name || - ((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) { - inUnparseableSection = true - continue - } - } - continue - } - - if inUnparseableSection { - section.isRawSection = true - section.rawBody += string(line) - continue - } - - kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line) - if err != nil { - switch { - // Treat as boolean key when desired, and whole line is key name. - case IsErrDelimiterNotFound(err): - switch { - case f.options.AllowBooleanKeys: - kname, err := p.readValue(line, parserBufferSize) - if err != nil { - return err - } - key, err := section.NewBooleanKey(kname) - if err != nil { - return err - } - key.Comment = strings.TrimSpace(p.comment.String()) - p.comment.Reset() - continue - - case f.options.SkipUnrecognizableLines: - continue - } - case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines: - continue - } - return err - } - - // Auto increment. - isAutoIncr := false - if kname == "-" { - isAutoIncr = true - kname = "#" + strconv.Itoa(p.count) - p.count++ - } - - value, err := p.readValue(line[offset:], parserBufferSize) - if err != nil { - return err - } - isLastValueEmpty = len(value) == 0 - - key, err := section.NewKey(kname, value) - if err != nil { - return err - } - key.isAutoIncrement = isAutoIncr - key.Comment = strings.TrimSpace(p.comment.String()) - p.comment.Reset() - lastRegularKey = key - } - return nil -} diff --git a/vendor/gopkg.in/ini.v1/section.go b/vendor/gopkg.in/ini.v1/section.go deleted file mode 100644 index a3615d82..00000000 --- a/vendor/gopkg.in/ini.v1/section.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "errors" - "fmt" - "strings" -) - -// Section represents a config section. -type Section struct { - f *File - Comment string - name string - keys map[string]*Key - keyList []string - keysHash map[string]string - - isRawSection bool - rawBody string -} - -func newSection(f *File, name string) *Section { - return &Section{ - f: f, - name: name, - keys: make(map[string]*Key), - keyList: make([]string, 0, 10), - keysHash: make(map[string]string), - } -} - -// Name returns name of Section. -func (s *Section) Name() string { - return s.name -} - -// Body returns rawBody of Section if the section was marked as unparseable. -// It still follows the other rules of the INI format surrounding leading/trailing whitespace. -func (s *Section) Body() string { - return strings.TrimSpace(s.rawBody) -} - -// SetBody updates body content only if section is raw. -func (s *Section) SetBody(body string) { - if !s.isRawSection { - return - } - s.rawBody = body -} - -// NewKey creates a new key to given section. -func (s *Section) NewKey(name, val string) (*Key, error) { - if len(name) == 0 { - return nil, errors.New("error creating new key: empty key name") - } else if s.f.options.Insensitive || s.f.options.InsensitiveKeys { - name = strings.ToLower(name) - } - - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - if inSlice(name, s.keyList) { - if s.f.options.AllowShadows { - if err := s.keys[name].addShadow(val); err != nil { - return nil, err - } - } else { - s.keys[name].value = val - s.keysHash[name] = val - } - return s.keys[name], nil - } - - s.keyList = append(s.keyList, name) - s.keys[name] = newKey(s, name, val) - s.keysHash[name] = val - return s.keys[name], nil -} - -// NewBooleanKey creates a new boolean type key to given section. -func (s *Section) NewBooleanKey(name string) (*Key, error) { - key, err := s.NewKey(name, "true") - if err != nil { - return nil, err - } - - key.isBooleanType = true - return key, nil -} - -// GetKey returns key in section by given name. -func (s *Section) GetKey(name string) (*Key, error) { - if s.f.BlockMode { - s.f.lock.RLock() - } - if s.f.options.Insensitive || s.f.options.InsensitiveKeys { - name = strings.ToLower(name) - } - key := s.keys[name] - if s.f.BlockMode { - s.f.lock.RUnlock() - } - - if key == nil { - // Check if it is a child-section. - sname := s.name - for { - if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { - sname = sname[:i] - sec, err := s.f.GetSection(sname) - if err != nil { - continue - } - return sec.GetKey(name) - } - break - } - return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name) - } - return key, nil -} - -// HasKey returns true if section contains a key with given name. -func (s *Section) HasKey(name string) bool { - key, _ := s.GetKey(name) - return key != nil -} - -// Deprecated: Use "HasKey" instead. -func (s *Section) Haskey(name string) bool { - return s.HasKey(name) -} - -// HasValue returns true if section contains given raw value. -func (s *Section) HasValue(value string) bool { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - for _, k := range s.keys { - if value == k.value { - return true - } - } - return false -} - -// Key assumes named Key exists in section and returns a zero-value when not. -func (s *Section) Key(name string) *Key { - key, err := s.GetKey(name) - if err != nil { - // It's OK here because the only possible error is empty key name, - // but if it's empty, this piece of code won't be executed. - key, _ = s.NewKey(name, "") - return key - } - return key -} - -// Keys returns list of keys of section. -func (s *Section) Keys() []*Key { - keys := make([]*Key, len(s.keyList)) - for i := range s.keyList { - keys[i] = s.Key(s.keyList[i]) - } - return keys -} - -// ParentKeys returns list of keys of parent section. -func (s *Section) ParentKeys() []*Key { - var parentKeys []*Key - sname := s.name - for { - if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { - sname = sname[:i] - sec, err := s.f.GetSection(sname) - if err != nil { - continue - } - parentKeys = append(parentKeys, sec.Keys()...) - } else { - break - } - - } - return parentKeys -} - -// KeyStrings returns list of key names of section. -func (s *Section) KeyStrings() []string { - list := make([]string, len(s.keyList)) - copy(list, s.keyList) - return list -} - -// KeysHash returns keys hash consisting of names and values. -func (s *Section) KeysHash() map[string]string { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - hash := make(map[string]string, len(s.keysHash)) - for key, value := range s.keysHash { - hash[key] = value - } - return hash -} - -// DeleteKey deletes a key from section. -func (s *Section) DeleteKey(name string) { - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - for i, k := range s.keyList { - if k == name { - s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) - delete(s.keys, name) - delete(s.keysHash, name) - return - } - } -} - -// ChildSections returns a list of child sections of current section. -// For example, "[parent.child1]" and "[parent.child12]" are child sections -// of section "[parent]". -func (s *Section) ChildSections() []*Section { - prefix := s.name + s.f.options.ChildSectionDelimiter - children := make([]*Section, 0, 3) - for _, name := range s.f.sectionList { - if strings.HasPrefix(name, prefix) { - children = append(children, s.f.sections[name]...) - } - } - return children -} diff --git a/vendor/gopkg.in/ini.v1/struct.go b/vendor/gopkg.in/ini.v1/struct.go deleted file mode 100644 index a486b2fe..00000000 --- a/vendor/gopkg.in/ini.v1/struct.go +++ /dev/null @@ -1,747 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "strings" - "time" - "unicode" -) - -// NameMapper represents a ini tag name mapper. -type NameMapper func(string) string - -// Built-in name getters. -var ( - // SnackCase converts to format SNACK_CASE. - SnackCase NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - } - newstr = append(newstr, unicode.ToUpper(chr)) - } - return string(newstr) - } - // TitleUnderscore converts to format title_underscore. - TitleUnderscore NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - chr -= 'A' - 'a' - } - newstr = append(newstr, chr) - } - return string(newstr) - } -) - -func (s *Section) parseFieldName(raw, actual string) string { - if len(actual) > 0 { - return actual - } - if s.f.NameMapper != nil { - return s.f.NameMapper(raw) - } - return raw -} - -func parseDelim(actual string) string { - if len(actual) > 0 { - return actual - } - return "," -} - -var reflectTime = reflect.TypeOf(time.Now()).Kind() - -// setSliceWithProperType sets proper values to slice based on its type. -func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { - var strs []string - if allowShadow { - strs = key.StringsWithShadows(delim) - } else { - strs = key.Strings(delim) - } - - numVals := len(strs) - if numVals == 0 { - return nil - } - - var vals interface{} - var err error - - sliceOf := field.Type().Elem().Kind() - switch sliceOf { - case reflect.String: - vals = strs - case reflect.Int: - vals, err = key.parseInts(strs, true, false) - case reflect.Int64: - vals, err = key.parseInt64s(strs, true, false) - case reflect.Uint: - vals, err = key.parseUints(strs, true, false) - case reflect.Uint64: - vals, err = key.parseUint64s(strs, true, false) - case reflect.Float64: - vals, err = key.parseFloat64s(strs, true, false) - case reflect.Bool: - vals, err = key.parseBools(strs, true, false) - case reflectTime: - vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - if err != nil && isStrict { - return err - } - - slice := reflect.MakeSlice(field.Type(), numVals, numVals) - for i := 0; i < numVals; i++ { - switch sliceOf { - case reflect.String: - slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i])) - case reflect.Int: - slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i])) - case reflect.Int64: - slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i])) - case reflect.Uint: - slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i])) - case reflect.Uint64: - slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i])) - case reflect.Float64: - slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i])) - case reflect.Bool: - slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i])) - case reflectTime: - slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i])) - } - } - field.Set(slice) - return nil -} - -func wrapStrictError(err error, isStrict bool) error { - if isStrict { - return err - } - return nil -} - -// setWithProperType sets proper value to field based on its type, -// but it does not return error for failing parsing, -// because we want to use default value that is already assigned to struct. -func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { - vt := t - isPtr := t.Kind() == reflect.Ptr - if isPtr { - vt = t.Elem() - } - switch vt.Kind() { - case reflect.String: - stringVal := key.String() - if isPtr { - field.Set(reflect.ValueOf(&stringVal)) - } else if len(stringVal) > 0 { - field.SetString(key.String()) - } - case reflect.Bool: - boolVal, err := key.Bool() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&boolVal)) - } else { - field.SetBool(boolVal) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // ParseDuration will not return err for `0`, so check the type name - if vt.Name() == "Duration" { - durationVal, err := key.Duration() - if err != nil { - if intVal, err := key.Int64(); err == nil { - field.SetInt(intVal) - return nil - } - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&durationVal)) - } else if int64(durationVal) > 0 { - field.Set(reflect.ValueOf(durationVal)) - } - return nil - } - - intVal, err := key.Int64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetInt(intVal) - field.Set(pv) - } else { - field.SetInt(intVal) - } - // byte is an alias for uint8, so supporting uint8 breaks support for byte - case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: - durationVal, err := key.Duration() - // Skip zero value - if err == nil && uint64(durationVal) > 0 { - if isPtr { - field.Set(reflect.ValueOf(&durationVal)) - } else { - field.Set(reflect.ValueOf(durationVal)) - } - return nil - } - - uintVal, err := key.Uint64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetUint(uintVal) - field.Set(pv) - } else { - field.SetUint(uintVal) - } - - case reflect.Float32, reflect.Float64: - floatVal, err := key.Float64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetFloat(floatVal) - field.Set(pv) - } else { - field.SetFloat(floatVal) - } - case reflectTime: - timeVal, err := key.Time() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&timeVal)) - } else { - field.Set(reflect.ValueOf(timeVal)) - } - case reflect.Slice: - return setSliceWithProperType(key, field, delim, allowShadow, isStrict) - default: - return fmt.Errorf("unsupported type %q", t) - } - return nil -} - -func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) { - opts := strings.SplitN(tag, ",", 5) - rawName = opts[0] - for _, opt := range opts[1:] { - omitEmpty = omitEmpty || (opt == "omitempty") - allowShadow = allowShadow || (opt == "allowshadow") - allowNonUnique = allowNonUnique || (opt == "nonunique") - extends = extends || (opt == "extends") - } - return rawName, omitEmpty, allowShadow, allowNonUnique, extends -} - -// mapToField maps the given value to the matching field of the given section. -// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added. -func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error { - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - typ := val.Type() - - for i := 0; i < typ.NumField(); i++ { - field := val.Field(i) - tpField := typ.Field(i) - - tag := tpField.Tag.Get("ini") - if tag == "-" { - continue - } - - rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag) - fieldName := s.parseFieldName(tpField.Name, rawName) - if len(fieldName) == 0 || !field.CanSet() { - continue - } - - isStruct := tpField.Type.Kind() == reflect.Struct - isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct - isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous - if isAnonymousPtr { - field.Set(reflect.New(tpField.Type.Elem())) - } - - if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) { - if isStructPtr && field.IsNil() { - field.Set(reflect.New(tpField.Type.Elem())) - } - fieldSection := s - if rawName != "" { - sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName - if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) { - fieldSection = secs[sectionIndex] - } - } - if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil { - return fmt.Errorf("map to field %q: %v", fieldName, err) - } - } else if isAnonymousPtr || isStruct || isStructPtr { - if secs, err := s.f.SectionsByName(fieldName); err == nil { - if len(secs) <= sectionIndex { - return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName) - } - // Only set the field to non-nil struct value if we have a section for it. - // Otherwise, we end up with a non-nil struct ptr even though there is no data. - if isStructPtr && field.IsNil() { - field.Set(reflect.New(tpField.Type.Elem())) - } - if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil { - return fmt.Errorf("map to field %q: %v", fieldName, err) - } - continue - } - } - - // Map non-unique sections - if allowNonUnique && tpField.Type.Kind() == reflect.Slice { - newField, err := s.mapToSlice(fieldName, field, isStrict) - if err != nil { - return fmt.Errorf("map to slice %q: %v", fieldName, err) - } - - field.Set(newField) - continue - } - - if key, err := s.GetKey(fieldName); err == nil { - delim := parseDelim(tpField.Tag.Get("delim")) - if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil { - return fmt.Errorf("set field %q: %v", fieldName, err) - } - } - } - return nil -} - -// mapToSlice maps all sections with the same name and returns the new value. -// The type of the Value must be a slice. -func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) { - secs, err := s.f.SectionsByName(secName) - if err != nil { - return reflect.Value{}, err - } - - typ := val.Type().Elem() - for i, sec := range secs { - elem := reflect.New(typ) - if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil { - return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err) - } - - val = reflect.Append(val, elem.Elem()) - } - return val, nil -} - -// mapTo maps a section to object v. -func (s *Section) mapTo(v interface{}, isStrict bool) error { - typ := reflect.TypeOf(v) - val := reflect.ValueOf(v) - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - val = val.Elem() - } else { - return errors.New("not a pointer to a struct") - } - - if typ.Kind() == reflect.Slice { - newField, err := s.mapToSlice(s.name, val, isStrict) - if err != nil { - return err - } - - val.Set(newField) - return nil - } - - return s.mapToField(val, isStrict, 0, s.name) -} - -// MapTo maps section to given struct. -func (s *Section) MapTo(v interface{}) error { - return s.mapTo(v, false) -} - -// StrictMapTo maps section to given struct in strict mode, -// which returns all possible error including value parsing error. -func (s *Section) StrictMapTo(v interface{}) error { - return s.mapTo(v, true) -} - -// MapTo maps file to given struct. -func (f *File) MapTo(v interface{}) error { - return f.Section("").MapTo(v) -} - -// StrictMapTo maps file to given struct in strict mode, -// which returns all possible error including value parsing error. -func (f *File) StrictMapTo(v interface{}) error { - return f.Section("").StrictMapTo(v) -} - -// MapToWithMapper maps data sources to given struct with name mapper. -func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { - cfg, err := Load(source, others...) - if err != nil { - return err - } - cfg.NameMapper = mapper - return cfg.MapTo(v) -} - -// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode, -// which returns all possible error including value parsing error. -func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { - cfg, err := Load(source, others...) - if err != nil { - return err - } - cfg.NameMapper = mapper - return cfg.StrictMapTo(v) -} - -// MapTo maps data sources to given struct. -func MapTo(v, source interface{}, others ...interface{}) error { - return MapToWithMapper(v, nil, source, others...) -} - -// StrictMapTo maps data sources to given struct in strict mode, -// which returns all possible error including value parsing error. -func StrictMapTo(v, source interface{}, others ...interface{}) error { - return StrictMapToWithMapper(v, nil, source, others...) -} - -// reflectSliceWithProperType does the opposite thing as setSliceWithProperType. -func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error { - slice := field.Slice(0, field.Len()) - if field.Len() == 0 { - return nil - } - sliceOf := field.Type().Elem().Kind() - - if allowShadow { - var keyWithShadows *Key - for i := 0; i < field.Len(); i++ { - var val string - switch sliceOf { - case reflect.String: - val = slice.Index(i).String() - case reflect.Int, reflect.Int64: - val = fmt.Sprint(slice.Index(i).Int()) - case reflect.Uint, reflect.Uint64: - val = fmt.Sprint(slice.Index(i).Uint()) - case reflect.Float64: - val = fmt.Sprint(slice.Index(i).Float()) - case reflect.Bool: - val = fmt.Sprint(slice.Index(i).Bool()) - case reflectTime: - val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - - if i == 0 { - keyWithShadows = newKey(key.s, key.name, val) - } else { - _ = keyWithShadows.AddShadow(val) - } - } - *key = *keyWithShadows - return nil - } - - var buf bytes.Buffer - for i := 0; i < field.Len(); i++ { - switch sliceOf { - case reflect.String: - buf.WriteString(slice.Index(i).String()) - case reflect.Int, reflect.Int64: - buf.WriteString(fmt.Sprint(slice.Index(i).Int())) - case reflect.Uint, reflect.Uint64: - buf.WriteString(fmt.Sprint(slice.Index(i).Uint())) - case reflect.Float64: - buf.WriteString(fmt.Sprint(slice.Index(i).Float())) - case reflect.Bool: - buf.WriteString(fmt.Sprint(slice.Index(i).Bool())) - case reflectTime: - buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339)) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - buf.WriteString(delim) - } - key.SetValue(buf.String()[:buf.Len()-len(delim)]) - return nil -} - -// reflectWithProperType does the opposite thing as setWithProperType. -func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error { - switch t.Kind() { - case reflect.String: - key.SetValue(field.String()) - case reflect.Bool: - key.SetValue(fmt.Sprint(field.Bool())) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - key.SetValue(fmt.Sprint(field.Int())) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - key.SetValue(fmt.Sprint(field.Uint())) - case reflect.Float32, reflect.Float64: - key.SetValue(fmt.Sprint(field.Float())) - case reflectTime: - key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339))) - case reflect.Slice: - return reflectSliceWithProperType(key, field, delim, allowShadow) - case reflect.Ptr: - if !field.IsNil() { - return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow) - } - default: - return fmt.Errorf("unsupported type %q", t) - } - return nil -} - -// CR: copied from encoding/json/encode.go with modifications of time.Time support. -// TODO: add more test coverage. -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflectTime: - t, ok := v.Interface().(time.Time) - return ok && t.IsZero() - } - return false -} - -// StructReflector is the interface implemented by struct types that can extract themselves into INI objects. -type StructReflector interface { - ReflectINIStruct(*File) error -} - -func (s *Section) reflectFrom(val reflect.Value) error { - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - typ := val.Type() - - for i := 0; i < typ.NumField(); i++ { - if !val.Field(i).CanInterface() { - continue - } - - field := val.Field(i) - tpField := typ.Field(i) - - tag := tpField.Tag.Get("ini") - if tag == "-" { - continue - } - - rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag) - if omitEmpty && isEmptyValue(field) { - continue - } - - if r, ok := field.Interface().(StructReflector); ok { - return r.ReflectINIStruct(s.f) - } - - fieldName := s.parseFieldName(tpField.Name, rawName) - if len(fieldName) == 0 || !field.CanSet() { - continue - } - - if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) { - if err := s.reflectFrom(field); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - continue - } - - if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) || - (tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") { - // Note: The only error here is section doesn't exist. - sec, err := s.f.GetSection(fieldName) - if err != nil { - // Note: fieldName can never be empty here, ignore error. - sec, _ = s.f.NewSection(fieldName) - } - - // Add comment from comment tag - if len(sec.Comment) == 0 { - sec.Comment = tpField.Tag.Get("comment") - } - - if err = sec.reflectFrom(field); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - continue - } - - if allowNonUnique && tpField.Type.Kind() == reflect.Slice { - slice := field.Slice(0, field.Len()) - if field.Len() == 0 { - return nil - } - sliceOf := field.Type().Elem().Kind() - - for i := 0; i < field.Len(); i++ { - if sliceOf != reflect.Struct && sliceOf != reflect.Ptr { - return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName) - } - - sec, err := s.f.NewSection(fieldName) - if err != nil { - return err - } - - // Add comment from comment tag - if len(sec.Comment) == 0 { - sec.Comment = tpField.Tag.Get("comment") - } - - if err := sec.reflectFrom(slice.Index(i)); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - } - continue - } - - // Note: Same reason as section. - key, err := s.GetKey(fieldName) - if err != nil { - key, _ = s.NewKey(fieldName, "") - } - - // Add comment from comment tag - if len(key.Comment) == 0 { - key.Comment = tpField.Tag.Get("comment") - } - - delim := parseDelim(tpField.Tag.Get("delim")) - if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil { - return fmt.Errorf("reflect field %q: %v", fieldName, err) - } - - } - return nil -} - -// ReflectFrom reflects section from given struct. It overwrites existing ones. -func (s *Section) ReflectFrom(v interface{}) error { - typ := reflect.TypeOf(v) - val := reflect.ValueOf(v) - - if s.name != DefaultSection && s.f.options.AllowNonUniqueSections && - (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) { - // Clear sections to make sure none exists before adding the new ones - s.f.DeleteSection(s.name) - - if typ.Kind() == reflect.Ptr { - sec, err := s.f.NewSection(s.name) - if err != nil { - return err - } - return sec.reflectFrom(val.Elem()) - } - - slice := val.Slice(0, val.Len()) - sliceOf := val.Type().Elem().Kind() - if sliceOf != reflect.Ptr { - return fmt.Errorf("not a slice of pointers") - } - - for i := 0; i < slice.Len(); i++ { - sec, err := s.f.NewSection(s.name) - if err != nil { - return err - } - - err = sec.reflectFrom(slice.Index(i)) - if err != nil { - return fmt.Errorf("reflect from %dth field: %v", i, err) - } - } - - return nil - } - - if typ.Kind() == reflect.Ptr { - val = val.Elem() - } else { - return errors.New("not a pointer to a struct") - } - - return s.reflectFrom(val) -} - -// ReflectFrom reflects file from given struct. -func (f *File) ReflectFrom(v interface{}) error { - return f.Section("").ReflectFrom(v) -} - -// ReflectFromWithMapper reflects data sources from given struct with name mapper. -func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error { - cfg.NameMapper = mapper - return cfg.ReflectFrom(v) -} - -// ReflectFrom reflects data sources from given struct. -func ReflectFrom(cfg *File, v interface{}) error { - return ReflectFromWithMapper(cfg, v, nil) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index a23b6cbe..f0247962 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -16,14 +16,15 @@ github.com/bmatcuk/doublestar/v4 # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew -# github.com/fsnotify/fsnotify v1.7.0 +# github.com/fsnotify/fsnotify v1.8.0 ## explicit; go 1.17 github.com/fsnotify/fsnotify +github.com/fsnotify/fsnotify/internal # github.com/go-git/go-git/v5 v5.13.0 ## explicit; go 1.21 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash -# github.com/go-viper/mapstructure/v2 v2.0.0 +# github.com/go-viper/mapstructure/v2 v2.2.1 ## explicit; go 1.18 github.com/go-viper/mapstructure/v2 github.com/go-viper/mapstructure/v2/internal/errors @@ -42,18 +43,6 @@ github.com/hashicorp/go-cleanhttp # github.com/hashicorp/go-retryablehttp v0.7.7 ## explicit; go 1.19 github.com/hashicorp/go-retryablehttp -# github.com/hashicorp/hcl v1.0.0 -## explicit -github.com/hashicorp/hcl -github.com/hashicorp/hcl/hcl/ast -github.com/hashicorp/hcl/hcl/parser -github.com/hashicorp/hcl/hcl/printer -github.com/hashicorp/hcl/hcl/scanner -github.com/hashicorp/hcl/hcl/strconv -github.com/hashicorp/hcl/hcl/token -github.com/hashicorp/hcl/json/parser -github.com/hashicorp/hcl/json/scanner -github.com/hashicorp/hcl/json/token # github.com/huandu/xstrings v1.5.0 ## explicit; go 1.12 github.com/huandu/xstrings @@ -95,9 +84,6 @@ github.com/launchdarkly/ld-find-code-refs/v2/internal/validation github.com/launchdarkly/ld-find-code-refs/v2/internal/version github.com/launchdarkly/ld-find-code-refs/v2/options github.com/launchdarkly/ld-find-code-refs/v2/search -# github.com/magiconair/properties v1.8.7 -## explicit; go 1.19 -github.com/magiconair/properties # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty @@ -119,8 +105,8 @@ github.com/morikuni/aec # github.com/olekukonko/tablewriter v0.0.5 ## explicit; go 1.12 github.com/olekukonko/tablewriter -# github.com/pelletier/go-toml/v2 v2.2.2 -## explicit; go 1.16 +# github.com/pelletier/go-toml/v2 v2.2.3 +## explicit; go 1.21.0 github.com/pelletier/go-toml/v2 github.com/pelletier/go-toml/v2/internal/characters github.com/pelletier/go-toml/v2/internal/danger @@ -140,8 +126,8 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/sagikazarmark/locafero v0.6.0 -## explicit; go 1.20 +# github.com/sagikazarmark/locafero v0.7.0 +## explicit; go 1.21 github.com/sagikazarmark/locafero # github.com/shopspring/decimal v1.4.0 ## explicit; go 1.10 @@ -155,25 +141,21 @@ github.com/sourcegraph/conc/panics # github.com/sourcegraph/go-diff v0.6.1 ## explicit; go 1.14 github.com/sourcegraph/go-diff/diff -# github.com/spf13/afero v1.11.0 -## explicit; go 1.19 +# github.com/spf13/afero v1.12.0 +## explicit; go 1.21 github.com/spf13/afero github.com/spf13/afero/internal/common github.com/spf13/afero/mem -# github.com/spf13/cast v1.7.0 +# github.com/spf13/cast v1.7.1 ## explicit; go 1.19 github.com/spf13/cast -# github.com/spf13/pflag v1.0.5 +# github.com/spf13/pflag v1.0.6 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/spf13/viper v1.20.0-alpha.1 -## explicit; go 1.21 +# github.com/spf13/viper v1.20.1 +## explicit; go 1.21.0 github.com/spf13/viper -github.com/spf13/viper/internal/encoding github.com/spf13/viper/internal/encoding/dotenv -github.com/spf13/viper/internal/encoding/hcl -github.com/spf13/viper/internal/encoding/ini -github.com/spf13/viper/internal/encoding/javaproperties github.com/spf13/viper/internal/encoding/json github.com/spf13/viper/internal/encoding/toml github.com/spf13/viper/internal/encoding/yaml @@ -223,9 +205,6 @@ golang.org/x/text/unicode/norm ## explicit; go 1.22.0 golang.org/x/tools/godoc/util golang.org/x/tools/godoc/vfs -# gopkg.in/ini.v1 v1.67.0 -## explicit -gopkg.in/ini.v1 # gopkg.in/yaml.v2 v2.4.0 ## explicit; go 1.15 gopkg.in/yaml.v2 From 564fe402650f0647f385e3223d23f9e354302151 Mon Sep 17 00:00:00 2001 From: Chris Blackburn Date: Mon, 9 Jun 2025 10:26:44 -0400 Subject: [PATCH 18/35] [REL-5292] Cblackburn/rel 5292/handle large diffs (#172) Fallback to normal `git diff` if we get a 406 from the github api for too large a diff. I made a change that I know will result in a large diff to test that the test passes. I'll revert this once we're sure the fallback works. --- Related Jira issue: [REL-5292: Code-Refs GHA should support large diffs](https://launchdarkly.atlassian.net/browse/REL-5292) --- errors/errors.go | 1 + main.go | 46 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/errors/errors.go b/errors/errors.go index fbe6ea6c..59ff8716 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -4,4 +4,5 @@ import "errors" var ( UnauthorizedError = errors.New("`repo-token` lacks required permissions") + NoGitError = errors.New("`git` not installed") ) diff --git a/main.go b/main.go index 077eddf7..332351de 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "os" + "os/exec" "sort" "strings" @@ -165,18 +166,55 @@ func postGithubComment(ctx context.Context, flagsRef references.ReferenceSummary func getDiffs(ctx context.Context, config *lcr.Config, prNumber int) ([]*diff.FileDiff, error) { gha.Debug("Getting pull request diff...") - rawOpts := github.RawOptions{Type: github.Diff} - raw, resp, err := config.GHClient.PullRequests.GetRaw(ctx, config.Owner, config.Repo, prNumber, rawOpts) + + var ( + client = config.GHClient + owner = config.Owner + repo = config.Repo + rawOpts = github.RawOptions{Type: github.Diff} + rawDiff []byte + ) + + raw, resp, err := client.PullRequests.GetRaw(ctx, owner, repo, prNumber, rawOpts) + rawDiff = []byte(raw) if err != nil { // TODO use this elsewhere if resp.StatusCode == http.StatusUnauthorized { return nil, e.UnauthorizedError } - return nil, err + // check that git is installed + if _, gitCmdErr := exec.Command("git", "-v").CombinedOutput(); gitCmdErr != nil { + return nil, e.NoGitError + } + + // For very large diffs, the github api will return a 406, when this + // happens, fallback to calling `git diff` directly + if resp != nil && resp.StatusCode == http.StatusNotAcceptable { + gha.Debug("Diff too large, fallback to traditional git command") + pr, _, err := client.PullRequests.Get(ctx, owner, repo, prNumber) + if err != nil { + return nil, err + } + + headSha := pr.GetHead().GetSHA() + + commitsComparison, _, err := client.Repositories.CompareCommits(ctx, owner, repo, headSha, pr.GetBase().GetSHA(), nil) + if err != nil { + return nil, err + } + + mergeBaseSha := commitsComparison.GetMergeBaseCommit().GetSHA() + rawDiff, err = exec.Command("git", "diff", "--find-renames", mergeBaseSha, headSha).CombinedOutput() + // git diff return exit status 1 if there is a diff, so that does + // not indicate an error + if err != nil && err.Error() != "exit status 1" { + return nil, fmt.Errorf("failed to run git diff: %w", err) + } + } } - multi, err := diff.ParseMultiFileDiff([]byte(raw)) + multi, err := diff.ParseMultiFileDiff(rawDiff) if err != nil { return nil, err } From e8ebad1c07c86d0feef43d01c7b64caed60c0e50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:09:06 +0200 Subject: [PATCH 19/35] chore(deps): bump actions/checkout from 4.2.2 to 4.3.0 (#175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 4.3.0.

Release notes

Sourced from actions/checkout's releases.

v4.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4...v4.3.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

V4.3.0

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.2&new-version=4.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9e814a50..ed01a836 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 @@ -73,7 +73,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 - name: Find LaunchDarkly feature flags in diff uses: ./ # Uses an action in the root directory id: find-flags @@ -118,7 +118,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 - name: Set up Python uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 From de9a4c72739a7dc4194238e0a9c49b4b38c17b78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:14:34 +0200 Subject: [PATCH 20/35] chore(deps): bump actions/checkout from 4.3.0 to 5.0.0 (#176) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.3.0 to 5.0.0.
Release notes

Sourced from actions/checkout's releases.

v5.0.0

What's Changed

⚠️ Minimum Compatible Runner Version

v2.327.1
Release Notes

Make sure your runner is updated to this version or newer to use this release.

Full Changelog: https://github.com/actions/checkout/compare/v4...v5.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

V5.0.0

V4.3.0

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.3.0&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ed01a836..e5131477 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 @@ -73,7 +73,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Find LaunchDarkly feature flags in diff uses: ./ # Uses an action in the root directory id: find-flags @@ -118,7 +118,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Set up Python uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 From 061d7a137e627947f57d1807f93d2f0cd216eaa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:09:58 +0200 Subject: [PATCH 21/35] chore(deps): bump github.com/launchdarkly/ld-find-code-refs/v2 from 2.13.0 to 2.14.0 (#177) Bumps [github.com/launchdarkly/ld-find-code-refs/v2](https://github.com/launchdarkly/ld-find-code-refs) from 2.13.0 to 2.14.0.
Release notes

Sourced from github.com/launchdarkly/ld-find-code-refs/v2's releases.

v2.14.0

Added:

  • --skipArchivedFlags option to instruct the tool to ignore any flag keys it finds from archived flags

Changed:

  • replaced the stdlib regexp with go-re2 for improved regexp compilation and pattern matching
  • now using caching to optimize file globbing and regex compilation
  • move off of legacy olekukonko/tablewriter and onto v1.x
  • updated to the latest version of the LaunchDarkly API

Fixed:

  • subdirectory option now works with projects[*].dir configuration, and produces correct "View in source" links in the LD UI
Changelog

Sourced from github.com/launchdarkly/ld-find-code-refs/v2's changelog.

[2.14.0] - 2025-08-12

Added:

  • --skipArchivedFlags option to instruct the tool to ignore any flag keys it finds from archived flags

Changed:

  • replaced the stdlib regexp with go-re2 for improved regexp compilation and pattern matching
  • now using caching to optimize file globbing and regex compilation
  • move off of legacy olekukonko/tablewriter and onto v1.x
  • updated to the latest version of the LaunchDarkly API (17.2.0)

Fixed:

  • subdirectory option now works with projects[*].dir configuration, and produces correct "View in source" links in the LD UI
Commits
  • 295c167 feat: [REL-8033] Prepare release of version 2.14.0 (#563)
  • 91005da chore: [REL-4161] use elevated token for git stuff (#562)
  • b4da482 chore(deps): bump golang.org/x/tools from 0.35.0 to 0.36.0 (#560)
  • 6c6e4ba chore: [REL-4161] make the circleci orb check more reliable (#559)
  • 25d9b55 chore: [REL-4161] fix up tag checks (#558)
  • 4eea47f chore: [REL-4161] dont run setup or cleanup if tag already exists (#557)
  • d6f2654 chore: [REL-4161] ensure tag is being created in the correct directory (#556)
  • 2c3137e chore: [REL-4161] dont bomb out if ssh dir exists (#555)
  • d6b3c6a chore: [REL-4161] use printf to ensure we get the exact value for homebrew ke...
  • 0323f0d chore: [REL-4161] write deploy key to file instead of adding contents directl...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/launchdarkly/ld-find-code-refs/v2&package-manager=go_modules&previous-version=2.13.0&new-version=2.14.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
[REL-8033]: https://launchdarkly.atlassian.net/browse/REL-8033?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Isabelle Miller --- go.mod | 35 +- go.sum | 76 +- internal/extinctions/extinctions.go | 2 +- .../bmatcuk/doublestar/v4/README.md | 19 +- .../github.com/bmatcuk/doublestar/v4/glob.go | 5 +- .../bmatcuk/doublestar/v4/globoptions.go | 24 +- .../bmatcuk/doublestar/v4/globwalk.go | 5 +- .../github.com/bmatcuk/doublestar/v4/match.go | 110 +- .../github.com/bmatcuk/doublestar/v4/utils.go | 5 +- vendor/github.com/fatih/color/LICENSE.md | 20 + vendor/github.com/fatih/color/README.md | 176 + vendor/github.com/fatih/color/color.go | 650 ++ .../github.com/fatih/color/color_windows.go | 19 + vendor/github.com/fatih/color/doc.go | 134 + .../go-viper/mapstructure/v2/.editorconfig | 3 + .../go-viper/mapstructure/v2/.golangci.yaml | 46 +- .../go-viper/mapstructure/v2/README.md | 9 +- .../go-viper/mapstructure/v2/decode_hooks.go | 26 +- .../go-viper/mapstructure/v2/errors.go | 74 + .../go-viper/mapstructure/v2/flake.lock | 390 +- .../go-viper/mapstructure/v2/flake.nix | 45 +- .../go-viper/mapstructure/v2/mapstructure.go | 220 +- .../hashicorp/go-retryablehttp/.go-version | 2 +- .../hashicorp/go-retryablehttp/.golangci.yml | 11 + .../hashicorp/go-retryablehttp/CODEOWNERS | 14 +- .../hashicorp/go-retryablehttp/Makefile | 2 +- .../hashicorp/go-retryablehttp/client.go | 19 + .../launchdarkly/api-client-go/v17/.gitignore | 24 + .../v17/.openapi-generator-ignore | 23 + .../api-client-go/v17/.travis.yml | 8 + .../api-client-go/v17/LICENSE.txt | 13 + .../launchdarkly/api-client-go/v17/README.md | 1413 ++++ .../api-client-go/v17/api_access_tokens.go | 1114 ++++ .../api-client-go/v17/api_account_members.go | 1355 ++++ .../v17/api_account_members_beta.go | 512 ++ .../v17/api_account_usage_beta.go | 2575 ++++++++ .../api-client-go/v17/api_ai_configs_beta.go | 3008 +++++++++ .../api-client-go/v17/api_announcements.go | 754 +++ .../v17/api_applications_beta.go | 1426 +++++ .../api-client-go/v17/api_approvals.go | 2608 ++++++++ .../api-client-go/v17/api_approvals_beta.go | 473 ++ .../api-client-go/v17/api_audit_log.go | 651 ++ .../api-client-go/v17/api_code_references.go | 2463 +++++++ .../api-client-go/v17/api_context_settings.go | 240 + .../api-client-go/v17/api_contexts.go | 2174 +++++++ .../api-client-go/v17/api_custom_roles.go | 903 +++ .../v17/api_data_export_destinations.go | 1229 ++++ .../api-client-go/v17/api_environments.go | 1494 +++++ .../api-client-go/v17/api_experiments.go | 2265 +++++++ .../api-client-go/v17/api_feature_flags.go | 5704 +++++++++++++++++ .../v17/api_feature_flags_beta.go | 405 ++ .../api_flag_import_configurations_beta.go | 1202 ++++ .../api-client-go/v17/api_flag_links_beta.go | 782 +++ .../api-client-go/v17/api_flag_triggers.go | 1126 ++++ .../api-client-go/v17/api_follow_flags.go | 733 +++ .../api-client-go/v17/api_holdouts_beta.go | 1187 ++++ .../v17/api_insights_charts_beta.go | 1349 ++++ .../v17/api_insights_deployments_beta.go | 926 +++ .../v17/api_insights_flag_events_beta.go | 357 ++ .../v17/api_insights_pull_requests_beta.go | 351 + .../v17/api_insights_repositories_beta.go | 597 ++ .../v17/api_insights_scores_beta.go | 1251 ++++ ...api_integration_audit_log_subscriptions.go | 928 +++ ...ntegration_delivery_configurations_beta.go | 1335 ++++ .../v17/api_integrations_beta.go | 953 +++ .../api-client-go/v17/api_layers.go | 766 +++ .../api-client-go/v17/api_metrics.go | 1086 ++++ .../api-client-go/v17/api_metrics_beta.go | 1176 ++++ .../api-client-go/v17/api_o_auth2_clients.go | 863 +++ .../api-client-go/v17/api_other.go | 725 +++ .../api_persistent_store_integrations_beta.go | 1043 +++ .../api-client-go/v17/api_projects.go | 1642 +++++ .../v17/api_relay_proxy_configurations.go | 1064 +++ .../v17/api_release_pipelines_beta.go | 1062 +++ .../api-client-go/v17/api_releases_beta.go | 924 +++ .../v17/api_scheduled_changes.go | 1182 ++++ .../api-client-go/v17/api_segments.go | 5019 +++++++++++++++ .../api-client-go/v17/api_tags.go | 272 + .../api-client-go/v17/api_teams.go | 2345 +++++++ .../api-client-go/v17/api_teams_beta.go | 352 + .../api-client-go/v17/api_user_settings.go | 1121 ++++ .../api-client-go/v17/api_users.go | 937 +++ .../api-client-go/v17/api_users_beta.go | 222 + .../api-client-go/v17/api_webhooks.go | 883 +++ .../v17/api_workflow_templates.go | 550 ++ .../api-client-go/v17/api_workflows.go | 1031 +++ .../launchdarkly/api-client-go/v17/client.go | 720 +++ .../api-client-go/v17/configuration.go | 235 + .../api-client-go/v17/git_push.sh | 57 + .../api-client-go/v17/model_access.go | 138 + .../v17/model_access_allowed_reason.go | 294 + .../v17/model_access_allowed_rep.go | 138 + .../api-client-go/v17/model_access_denied.go | 138 + .../v17/model_access_denied_reason.go | 294 + .../v17/model_access_token_post.go | 339 + .../api-client-go/v17/model_action_input.go | 118 + .../api-client-go/v17/model_action_output.go | 139 + .../api-client-go/v17/model_ai_config.go | 420 ++ .../v17/model_ai_config__maintainer.go | 149 + .../v17/model_ai_config_patch.go | 260 + .../api-client-go/v17/model_ai_config_post.go | 286 + .../v17/model_ai_config_variation.go | 434 ++ .../v17/model_ai_config_variation_patch.go | 297 + .../v17/model_ai_config_variation_post.go | 232 + .../model_ai_config_variations_response.go | 138 + .../api-client-go/v17/model_ai_configs.go | 174 + .../v17/model_ai_configs_access.go | 138 + .../model_ai_configs_access_allowed_reason.go | 294 + .../model_ai_configs_access_allowed_rep.go | 138 + .../v17/model_ai_configs_access_denied.go | 138 + .../model_ai_configs_access_denied_reason.go | 294 + .../v17/model_ai_configs_link.go | 152 + .../v17/model_ai_configs_maintainer_team.go | 138 + .../v17/model_announcement_access.go | 138 + ...odel_announcement_access_allowed_reason.go | 294 + .../model_announcement_access_allowed_rep.go | 138 + .../v17/model_announcement_access_denied.go | 138 + ...model_announcement_access_denied_reason.go | 294 + .../v17/model_announcement_access_rep.go | 138 + .../v17/model_announcement_link.go | 152 + .../v17/model_announcement_paginated_links.go | 253 + .../v17/model_announcement_patch_operation.go | 178 + .../v17/model_announcement_response.go | 392 ++ .../v17/model_announcement_response__links.go | 109 + .../v17/model_application_collection_rep.go | 191 + .../model_application_flag_collection_rep.go | 191 + .../v17/model_application_rep.go | 455 ++ .../v17/model_application_version_rep.go | 353 + ...del_application_versions_collection_rep.go | 191 + .../v17/model_approval_request_response.go | 845 +++ .../v17/model_approval_settings.go | 430 ++ .../v17/model_approvals_capability_config.go | 117 + .../v17/model_assigned_to_rep.go | 154 + .../api-client-go/v17/model_audience.go | 219 + .../v17/model_audience_configuration.go | 249 + .../api-client-go/v17/model_audience_post.go | 213 + .../v17/model_audit_log_entry_listing_rep.go | 675 ++ ..._audit_log_entry_listing_rep_collection.go | 140 + .../v17/model_audit_log_entry_rep.go | 901 +++ ..._log_events_hook_capability_config_post.go | 116 + ...t_log_events_hook_capability_config_rep.go | 117 + .../v17/model_authorized_app_data_rep.go | 264 + .../model_bayesian_beta_binomial_stats_rep.go | 228 + .../v17/model_bayesian_normal_stats_rep.go | 154 + .../model_big_segment_store_integration.go | 443 ++ ...ig_segment_store_integration_collection.go | 139 + ...ment_store_integration_collection_links.go | 145 + ...del_big_segment_store_integration_links.go | 196 + .../v17/model_big_segment_store_status.go | 262 + .../v17/model_big_segment_target.go | 170 + .../v17/model_boolean_defaults.go | 302 + .../v17/model_boolean_flag_defaults.go | 260 + .../v17/model_branch_collection_rep.go | 140 + .../api-client-go/v17/model_branch_rep.go | 273 + .../v17/model_bulk_edit_members_rep.go | 154 + .../v17/model_bulk_edit_teams_rep.go | 191 + .../v17/model_caller_identity_rep.go | 512 ++ .../v17/model_capability_config_post.go | 152 + .../v17/model_capability_config_rep.go | 152 + .../api-client-go/v17/model_clause.go | 268 + .../api-client-go/v17/model_client.go | 333 + .../v17/model_client_collection.go | 140 + .../v17/model_client_side_availability.go | 152 + .../model_client_side_availability_post.go | 140 + .../api-client-go/v17/model_completed_by.go | 152 + .../v17/model_condition_input.go | 409 ++ .../v17/model_condition_output.go | 470 ++ .../api-client-go/v17/model_conflict.go | 153 + .../v17/model_conflict_output.go | 140 + .../v17/model_context_attribute_name.go | 177 + .../v17/model_context_attribute_names.go | 140 + ...odel_context_attribute_names_collection.go | 110 + .../v17/model_context_attribute_value.go | 142 + .../v17/model_context_attribute_values.go | 140 + ...del_context_attribute_values_collection.go | 110 + .../v17/model_context_instance_evaluation.go | 238 + ...odel_context_instance_evaluation_reason.go | 295 + .../v17/model_context_instance_evaluations.go | 177 + .../v17/model_context_instance_record.go | 327 + .../v17/model_context_instance_search.go | 228 + ...del_context_instance_segment_membership.go | 350 + ...el_context_instance_segment_memberships.go | 139 + .../v17/model_context_instances.go | 251 + .../v17/model_context_kind_rep.go | 434 ++ .../v17/model_context_kinds_collection_rep.go | 140 + .../api-client-go/v17/model_context_record.go | 297 + .../api-client-go/v17/model_context_search.go | 228 + .../api-client-go/v17/model_contexts.go | 251 + .../v17/model_copied_from_env.go | 147 + .../api-client-go/v17/model_core_link.go | 138 + .../v17/model_create_announcement_body.go | 267 + .../model_create_approval_request_request.go | 316 + ...py_flag_config_approval_request_request.go | 324 + ...te_flag_config_approval_request_request.go | 359 ++ .../v17/model_create_phase_input.go | 176 + .../v17/model_create_release_input.go | 147 + .../model_create_release_pipeline_input.go | 318 + .../model_create_workflow_template_input.go | 361 ++ .../v17/model_credible_interval_rep.go | 154 + .../v17/model_custom_property.go | 140 + .../api-client-go/v17/model_custom_role.go | 485 ++ .../v17/model_custom_role_post.go | 278 + .../api-client-go/v17/model_custom_roles.go | 184 + .../v17/model_custom_workflow_input.go | 257 + .../v17/model_custom_workflow_meta.go | 153 + .../v17/model_custom_workflow_output.go | 502 ++ .../v17/model_custom_workflow_stage_meta.go | 154 + .../model_custom_workflows_listing_output.go | 170 + .../model_default_client_side_availability.go | 140 + ...l_default_client_side_availability_post.go | 140 + .../api-client-go/v17/model_defaults.go | 140 + .../v17/model_dependent_experiment_rep.go | 295 + .../api-client-go/v17/model_dependent_flag.go | 206 + .../v17/model_dependent_flag_environment.go | 206 + .../model_dependent_flags_by_environment.go | 169 + .../v17/model_dependent_metric_group_rep.go | 200 + ...dependent_metric_group_rep_with_metrics.go | 237 + ...el_dependent_metric_or_metric_group_rep.go | 334 + .../v17/model_deployment_collection_rep.go | 177 + .../api-client-go/v17/model_deployment_rep.go | 715 +++ .../api-client-go/v17/model_destination.go | 375 ++ .../v17/model_destination_post.go | 229 + .../api-client-go/v17/model_destinations.go | 154 + .../api-client-go/v17/model_distribution.go | 154 + .../v17/model_dynamic_options.go | 152 + .../v17/model_dynamic_options_parser.go | 152 + .../api-client-go/v17/model_endpoint.go | 224 + .../api-client-go/v17/model_environment.go | 573 ++ .../v17/model_environment_post.go | 465 ++ .../v17/model_environment_summary.go | 200 + .../api-client-go/v17/model_environments.go | 184 + .../api-client-go/v17/model_error.go | 138 + .../v17/model_evaluation_reason.go | 295 + .../v17/model_evaluations_summary.go | 117 + .../v17/model_execution_output.go | 146 + ...el_expandable_approval_request_response.go | 990 +++ ...l_expandable_approval_requests_response.go | 170 + .../v17/model_expanded_flag_rep.go | 667 ++ .../v17/model_expanded_resource_rep.go | 182 + .../api-client-go/v17/model_experiment.go | 514 ++ .../v17/model_experiment_allocation_rep.go | 138 + .../model_experiment_bayesian_results_rep.go | 268 + .../v17/model_experiment_collection_rep.go | 184 + .../model_experiment_enabled_period_rep.go | 152 + ...odel_experiment_environment_setting_rep.go | 188 + .../v17/model_experiment_info_rep.go | 138 + .../v17/model_experiment_patch_input.go | 146 + .../v17/model_experiment_post.go | 280 + .../v17/model_expiring_target.go | 332 + .../v17/model_expiring_target_error.go | 140 + .../v17/model_expiring_target_get_response.go | 147 + .../model_expiring_target_patch_response.go | 291 + ...model_expiring_user_target_get_response.go | 147 + .../v17/model_expiring_user_target_item.go | 302 + ...del_expiring_user_target_patch_response.go | 295 + .../api-client-go/v17/model_export.go | 318 + .../api-client-go/v17/model_extinction.go | 229 + .../v17/model_extinction_collection_rep.go | 140 + .../v17/model_failure_reason_rep.go | 140 + .../api-client-go/v17/model_feature_flag.go | 992 +++ .../v17/model_feature_flag_body.go | 621 ++ .../v17/model_feature_flag_config.go | 777 +++ .../model_feature_flag_scheduled_change.go | 331 + .../model_feature_flag_scheduled_changes.go | 147 + .../v17/model_feature_flag_status.go | 186 + ...feature_flag_status_across_environments.go | 169 + .../v17/model_feature_flag_statuses.go | 145 + .../api-client-go/v17/model_feature_flags.go | 214 + .../api-client-go/v17/model_file_rep.go | 154 + ...l_flag_config_approval_request_response.go | 772 +++ ..._flag_config_approval_requests_response.go | 140 + .../v17/model_flag_config_evaluation.go | 116 + ...odel_flag_config_migration_settings_rep.go | 116 + .../v17/model_flag_copy_config_environment.go | 147 + .../v17/model_flag_copy_config_post.go | 249 + .../v17/model_flag_defaults_rep.go | 300 + .../v17/model_flag_event_collection_rep.go | 177 + .../v17/model_flag_event_experiment.go | 206 + .../model_flag_event_experiment_collection.go | 140 + .../model_flag_event_experiment_iteration.go | 241 + .../v17/model_flag_event_impact_rep.go | 226 + .../v17/model_flag_event_member_rep.go | 200 + .../api-client-go/v17/model_flag_event_rep.go | 537 ++ ...odel_flag_followers_by_proj_env_get_rep.go | 147 + .../v17/model_flag_followers_get_rep.go | 140 + .../model_flag_import_configuration_post.go | 183 + .../v17/model_flag_import_integration.go | 383 ++ ...odel_flag_import_integration_collection.go | 139 + ...lag_import_integration_collection_links.go | 145 + .../model_flag_import_integration_links.go | 167 + .../v17/model_flag_import_status.go | 225 + .../api-client-go/v17/model_flag_input.go | 177 + .../v17/model_flag_link_collection_rep.go | 140 + .../v17/model_flag_link_member.go | 210 + .../api-client-go/v17/model_flag_link_post.go | 338 + .../api-client-go/v17/model_flag_link_rep.go | 449 ++ .../v17/model_flag_listing_rep.go | 212 + .../v17/model_flag_migration_settings_rep.go | 154 + .../v17/model_flag_prerequisite_post.go | 140 + .../model_flag_reference_collection_rep.go | 140 + .../v17/model_flag_reference_rep.go | 200 + .../api-client-go/v17/model_flag_rep.go | 295 + .../v17/model_flag_scheduled_changes_input.go | 146 + .../api-client-go/v17/model_flag_sempatch.go | 145 + .../v17/model_flag_status_rep.go | 215 + .../api-client-go/v17/model_flag_summary.go | 139 + .../v17/model_flag_trigger_input.go | 154 + .../v17/model_follow_flag_member.go | 274 + .../v17/model_followers_per_flag.go | 154 + .../v17/model_forbidden_error_rep.go | 140 + .../api-client-go/v17/model_form_variable.go | 405 ++ ...warehouse_destination_key_pair_post_rep.go | 154 + ...l_get_announcements_public_200_response.go | 138 + .../api-client-go/v17/model_header_items.go | 152 + .../api-client-go/v17/model_hmac_signature.go | 152 + .../v17/model_holdout_detail_rep.go | 364 ++ .../v17/model_holdout_patch_input.go | 146 + .../v17/model_holdout_post_request.go | 450 ++ .../api-client-go/v17/model_holdout_rep.go | 327 + .../v17/model_holdouts_collection_rep.go | 190 + .../api-client-go/v17/model_hunk_rep.go | 258 + .../api-client-go/v17/model_import.go | 296 + .../api-client-go/v17/model_initiator_rep.go | 154 + .../api-client-go/v17/model_insight_group.go | 374 ++ .../v17/model_insight_group_collection.go | 249 + ...model_insight_group_collection_metadata.go | 109 + ...insight_group_collection_score_metadata.go | 138 + .../v17/model_insight_group_scores.go | 406 ++ ...model_insight_groups_count_by_indicator.go | 290 + .../api-client-go/v17/model_insight_period.go | 138 + .../api-client-go/v17/model_insight_scores.go | 204 + .../api-client-go/v17/model_insights_chart.go | 139 + .../v17/model_insights_chart_bounds.go | 140 + .../v17/model_insights_chart_metadata.go | 240 + .../v17/model_insights_chart_metric.go | 230 + .../v17/model_insights_chart_series.go | 139 + .../model_insights_chart_series_data_point.go | 177 + .../model_insights_chart_series_metadata.go | 184 + ...del_insights_chart_series_metadata_axis.go | 110 + .../model_insights_metric_indicator_range.go | 140 + .../v17/model_insights_metric_score.go | 277 + .../model_insights_metric_tier_definition.go | 140 + .../v17/model_insights_repository.go | 296 + .../model_insights_repository_collection.go | 177 + .../v17/model_insights_repository_project.go | 140 + ..._insights_repository_project_collection.go | 177 + ...el_insights_repository_project_mappings.go | 109 + .../v17/model_instruction_user_request.go | 244 + .../api-client-go/v17/model_integration.go | 522 ++ ...ntegration_configuration_collection_rep.go | 140 + .../model_integration_configuration_post.go | 250 + .../model_integration_configurations_rep.go | 426 ++ ...odel_integration_delivery_configuration.go | 414 ++ ...ation_delivery_configuration_collection.go | 139 + ...delivery_configuration_collection_links.go | 145 + ...ntegration_delivery_configuration_links.go | 196 + ...integration_delivery_configuration_post.go | 220 + ...gration_delivery_configuration_response.go | 226 + .../v17/model_integration_metadata.go | 196 + .../v17/model_integration_status.go | 138 + .../v17/model_integration_status_rep.go | 188 + ...del_integration_subscription_status_rep.go | 260 + .../api-client-go/v17/model_integrations.go | 188 + .../v17/model_invalid_request_error_rep.go | 140 + .../api-client-go/v17/model_ip_list.go | 140 + .../v17/model_iteration_input.go | 382 ++ .../api-client-go/v17/model_iteration_rep.go | 759 +++ .../v17/model_last_seen_metadata.go | 117 + .../v17/model_layer_collection_rep.go | 170 + .../v17/model_layer_configuration_rep.go | 110 + .../v17/model_layer_patch_input.go | 183 + .../api-client-go/v17/model_layer_post.go | 170 + .../api-client-go/v17/model_layer_rep.go | 273 + .../v17/model_layer_reservation_rep.go | 170 + .../v17/model_layer_snapshot_rep.go | 200 + .../v17/model_lead_time_stages_rep.go | 258 + .../v17/model_legacy_experiment_rep.go | 224 + .../api-client-go/v17/model_link.go | 152 + .../v17/model_maintainer_member.go | 239 + .../api-client-go/v17/model_maintainer_rep.go | 152 + .../v17/model_maintainer_team.go | 177 + .../api-client-go/v17/model_member.go | 782 +++ .../v17/model_member_data_rep.go | 264 + .../v17/model_member_import_item.go | 177 + ...del_member_permission_grant_summary_rep.go | 184 + .../api-client-go/v17/model_member_summary.go | 274 + .../v17/model_member_team_summary_rep.go | 206 + .../v17/model_member_teams_post_input.go | 110 + .../api-client-go/v17/model_members.go | 177 + .../v17/model_members_patch_input.go | 146 + .../api-client-go/v17/model_message.go | 138 + .../v17/model_method_not_allowed_error_rep.go | 140 + .../v17/model_metric_by_variation.go | 152 + .../v17/model_metric_collection_rep.go | 190 + .../v17/model_metric_event_default_rep.go | 154 + .../v17/model_metric_group_collection_rep.go | 183 + .../v17/model_metric_group_post.go | 297 + .../v17/model_metric_group_rep.go | 553 ++ .../v17/model_metric_group_results_rep.go | 140 + .../v17/model_metric_in_group_rep.go | 385 ++ .../v17/model_metric_in_group_results_rep.go | 138 + .../v17/model_metric_in_metric_group_input.go | 140 + .../api-client-go/v17/model_metric_input.go | 188 + .../v17/model_metric_listing_rep.go | 1017 +++ .../api-client-go/v17/model_metric_post.go | 694 ++ .../api-client-go/v17/model_metric_rep.go | 1274 ++++ .../api-client-go/v17/model_metric_seen.go | 154 + .../api-client-go/v17/model_metric_v2_rep.go | 311 + .../api-client-go/v17/model_metrics.go | 558 ++ .../v17/model_migration_safety_issue_rep.go | 228 + .../v17/model_migration_settings_post.go | 146 + .../api-client-go/v17/model_model_config.go | 514 ++ .../v17/model_model_config_post.go | 426 ++ .../api-client-go/v17/model_modification.go | 117 + .../model_multi_environment_dependent_flag.go | 177 + ...model_multi_environment_dependent_flags.go | 169 + .../v17/model_naming_convention.go | 154 + .../v17/model_new_member_form.go | 368 ++ .../v17/model_not_found_error_rep.go | 140 + .../v17/model_oauth_client_post.go | 191 + .../api-client-go/v17/model_options_array.go | 152 + .../v17/model_paginated_links.go | 253 + .../v17/model_parameter_default.go | 191 + .../api-client-go/v17/model_parameter_rep.go | 152 + .../v17/model_parent_and_self_links.go | 138 + .../api-client-go/v17/model_parent_link.go | 109 + .../v17/model_parent_resource_rep.go | 190 + .../v17/model_patch_failed_error_rep.go | 140 + .../v17/model_patch_flags_request.go | 147 + .../v17/model_patch_operation.go | 178 + ...patch_segment_expiring_target_input_rep.go | 147 + ...tch_segment_expiring_target_instruction.go | 274 + .../v17/model_patch_segment_instruction.go | 244 + .../v17/model_patch_segment_request.go | 147 + .../v17/model_patch_users_request.go | 147 + .../v17/model_patch_with_comment.go | 146 + .../v17/model_permission_grant_input.go | 191 + .../api-client-go/v17/model_phase.go | 205 + .../api-client-go/v17/model_phase_info.go | 170 + ...del_post_approval_request_apply_request.go | 117 + ...el_post_approval_request_review_request.go | 154 + .../v17/model_post_deployment_event_input.go | 451 ++ ...model_post_flag_scheduled_changes_input.go | 175 + .../v17/model_post_insight_group_params.go | 237 + .../api-client-go/v17/model_prerequisite.go | 138 + .../api-client-go/v17/model_project.go | 405 ++ .../api-client-go/v17/model_project_post.go | 323 + .../api-client-go/v17/model_project_rep.go | 399 ++ .../v17/model_project_summary.go | 200 + .../v17/model_project_summary_collection.go | 174 + .../api-client-go/v17/model_projects.go | 176 + .../v17/model_pull_request_collection_rep.go | 177 + .../v17/model_pull_request_lead_time_rep.go | 369 ++ .../v17/model_pull_request_rep.go | 620 ++ .../api-client-go/v17/model_put_branch.go | 279 + .../v17/model_randomization_settings_put.go | 110 + .../v17/model_randomization_settings_rep.go | 264 + .../v17/model_randomization_unit_input.go | 177 + .../v17/model_randomization_unit_rep.go | 264 + .../v17/model_rate_limited_error_rep.go | 140 + .../v17/model_recent_trigger_body.go | 153 + .../api-client-go/v17/model_reference_rep.go | 176 + .../v17/model_related_experiment_rep.go | 188 + .../v17/model_relative_difference_rep.go | 265 + .../model_relay_auto_config_collection_rep.go | 110 + .../v17/model_relay_auto_config_post.go | 140 + .../v17/model_relay_auto_config_rep.go | 359 ++ .../api-client-go/v17/model_release.go | 340 + .../v17/model_release_audience.go | 359 ++ .../model_release_guardian_configuration.go | 207 + ...el_release_guardian_configuration_input.go | 228 + .../api-client-go/v17/model_release_phase.go | 446 ++ .../v17/model_release_pipeline.go | 422 ++ .../v17/model_release_pipeline_collection.go | 140 + .../v17/model_release_progression.go | 242 + .../model_release_progression_collection.go | 260 + .../model_releaser_audience_config_input.go | 227 + .../v17/model_repository_collection_rep.go | 139 + .../v17/model_repository_post.go | 295 + .../api-client-go/v17/model_repository_rep.go | 443 ++ .../v17/model_resource_access.go | 152 + .../api-client-go/v17/model_resource_id.go | 268 + .../v17/model_resource_id_response.go | 260 + .../api-client-go/v17/model_review_output.go | 282 + .../v17/model_review_response.go | 287 + .../api-client-go/v17/model_rollout.go | 253 + .../api-client-go/v17/model_root_response.go | 109 + .../api-client-go/v17/model_rule.go | 323 + .../api-client-go/v17/model_rule_clause.go | 191 + .../api-client-go/v17/model_sdk_list_rep.go | 140 + .../v17/model_sdk_version_list_rep.go | 140 + .../v17/model_sdk_version_rep.go | 140 + .../api-client-go/v17/model_segment_body.go | 288 + .../v17/model_segment_metadata.go | 332 + .../api-client-go/v17/model_segment_target.go | 152 + .../v17/model_segment_user_list.go | 152 + .../v17/model_segment_user_state.go | 152 + .../api-client-go/v17/model_series.go | 140 + .../v17/model_series_intervals_rep.go | 140 + .../v17/model_series_list_rep.go | 170 + .../v17/model_simple_holdout_rep.go | 332 + .../v17/model_sliced_results_rep.go | 191 + .../api-client-go/v17/model_source_env.go | 154 + .../api-client-go/v17/model_source_flag.go | 147 + .../api-client-go/v17/model_stage_input.go | 227 + .../api-client-go/v17/model_stage_output.go | 235 + .../api-client-go/v17/model_statement.go | 258 + .../api-client-go/v17/model_statement_post.go | 258 + .../v17/model_statistic_collection_rep.go | 140 + .../api-client-go/v17/model_statistic_rep.go | 386 ++ .../v17/model_statistics_root.go | 153 + .../v17/model_status_conflict_error_rep.go | 140 + .../v17/model_status_response.go | 224 + .../v17/model_status_service_unavailable.go | 140 + .../v17/model_store_integration_error.go | 188 + .../v17/model_subject_data_rep.go | 190 + .../v17/model_subscription_post.go | 324 + .../v17/model_tags_collection.go | 176 + .../api-client-go/v17/model_tags_link.go | 152 + .../api-client-go/v17/model_target.go | 177 + .../v17/model_target_resource_rep.go | 190 + .../api-client-go/v17/model_team.go | 590 ++ .../v17/model_team_custom_role.go | 226 + .../v17/model_team_custom_roles.go | 191 + .../v17/model_team_imports_rep.go | 117 + .../v17/model_team_maintainers.go | 191 + .../api-client-go/v17/model_team_members.go | 117 + .../v17/model_team_patch_input.go | 146 + .../v17/model_team_post_input.go | 324 + .../api-client-go/v17/model_team_projects.go | 153 + .../api-client-go/v17/model_teams.go | 184 + .../v17/model_teams_patch_input.go | 146 + .../api-client-go/v17/model_timestamp_rep.go | 224 + .../api-client-go/v17/model_token.go | 623 ++ .../api-client-go/v17/model_token_summary.go | 263 + .../api-client-go/v17/model_tokens.go | 190 + .../v17/model_treatment_input.go | 200 + .../v17/model_treatment_parameter_input.go | 140 + .../api-client-go/v17/model_treatment_rep.go | 251 + .../v17/model_treatment_result_rep.go | 779 +++ .../api-client-go/v17/model_trigger_post.go | 184 + .../model_trigger_workflow_collection_rep.go | 154 + .../v17/model_trigger_workflow_rep.go | 556 ++ .../v17/model_unauthorized_error_rep.go | 140 + .../v17/model_update_phase_status_input.go | 153 + .../model_update_release_pipeline_input.go | 214 + .../v17/model_upsert_context_kind_payload.go | 258 + .../v17/model_upsert_flag_defaults_payload.go | 198 + .../v17/model_upsert_payload_rep.go | 235 + .../v17/model_upsert_response_rep.go | 154 + .../api-client-go/v17/model_url_post.go | 224 + .../api-client-go/v17/model_user.go | 524 ++ .../v17/model_user_attribute_names_rep.go | 191 + .../v17/model_user_flag_setting.go | 210 + .../v17/model_user_flag_settings.go | 140 + .../api-client-go/v17/model_user_record.go | 337 + .../api-client-go/v17/model_user_segment.go | 855 +++ .../v17/model_user_segment_rule.go | 289 + .../api-client-go/v17/model_user_segments.go | 177 + .../api-client-go/v17/model_users.go | 177 + .../api-client-go/v17/model_users_rep.go | 177 + .../v17/model_validation_failed_error_rep.go | 170 + .../api-client-go/v17/model_value_put.go | 155 + .../api-client-go/v17/model_variation.go | 223 + .../v17/model_variation_eval_summary.go | 192 + .../v17/model_variation_or_rollout_rep.go | 153 + .../v17/model_variation_summary.go | 340 + .../api-client-go/v17/model_versions_rep.go | 205 + .../api-client-go/v17/model_webhook.go | 377 ++ .../api-client-go/v17/model_webhook_post.go | 317 + .../api-client-go/v17/model_webhooks.go | 140 + .../v17/model_weighted_variation.go | 174 + .../v17/model_workflow_template_metadata.go | 116 + .../v17/model_workflow_template_output.go | 362 ++ .../v17/model_workflow_template_parameter.go | 226 + ...l_workflow_templates_listing_output_rep.go | 109 + .../api-client-go/v17/response.go | 48 + .../launchdarkly/api-client-go/v17/utils.go | 329 + .../ld-find-code-refs/v2/aliases/alias.go | 36 +- .../ld-find-code-refs/v2/flags/flags.go | 6 +- .../ld-find-code-refs/v2/internal/ld/ld.go | 102 +- .../v2/internal/version/version.go | 2 +- .../ld-find-code-refs/v2/options/flags.go | 9 +- .../ld-find-code-refs/v2/options/options.go | 5 +- .../ld-find-code-refs/v2/search/files.go | 15 +- .../ld-find-code-refs/v2/search/matcher.go | 2 +- .../ld-find-code-refs/v2/search/scan.go | 2 +- .../ld-find-code-refs/v2/search/search.go | 5 +- vendor/github.com/mattn/go-colorable/LICENSE | 21 + .../github.com/mattn/go-colorable/README.md | 48 + .../mattn/go-colorable/colorable_appengine.go | 38 + .../mattn/go-colorable/colorable_others.go | 38 + .../mattn/go-colorable/colorable_windows.go | 1047 +++ .../{go-runewidth => go-colorable}/go.test.sh | 0 .../mattn/go-colorable/noncolorable.go | 57 + .../github.com/mattn/go-runewidth/.travis.yml | 16 - .../github.com/mattn/go-runewidth/README.md | 2 +- .../mattn/go-runewidth/runewidth.go | 205 +- .../mattn/go-runewidth/runewidth_appengine.go | 1 + .../mattn/go-runewidth/runewidth_js.go | 4 +- .../mattn/go-runewidth/runewidth_posix.go | 5 +- .../mattn/go-runewidth/runewidth_table.go | 329 +- .../mattn/go-runewidth/runewidth_windows.go | 4 +- .../github.com/olekukonko/errors/.gitignore | 3 + vendor/github.com/olekukonko/errors/LICENSE | 21 + vendor/github.com/olekukonko/errors/README.md | 1358 ++++ vendor/github.com/olekukonko/errors/errors.go | 957 +++ vendor/github.com/olekukonko/errors/helper.go | 423 ++ .../olekukonko/errors/multi_error.go | 325 + vendor/github.com/olekukonko/errors/pool.go | 75 + .../olekukonko/errors/pool_above_1_24.go | 24 + .../olekukonko/errors/pool_below_1_24.go | 24 + vendor/github.com/olekukonko/errors/retry.go | 286 + vendor/github.com/olekukonko/errors/utils.go | 153 + vendor/github.com/olekukonko/ll/.gitignore | 5 + vendor/github.com/olekukonko/ll/LICENSE | 21 + vendor/github.com/olekukonko/ll/README.md | 359 ++ vendor/github.com/olekukonko/ll/concat.go | 421 ++ .../github.com/olekukonko/ll/conditional.go | 340 + vendor/github.com/olekukonko/ll/field.go | 374 ++ vendor/github.com/olekukonko/ll/global.go | 659 ++ vendor/github.com/olekukonko/ll/lc.go | 48 + .../github.com/olekukonko/ll/lh/buffered.go | 279 + .../github.com/olekukonko/ll/lh/colorized.go | 439 ++ vendor/github.com/olekukonko/ll/lh/json.go | 170 + vendor/github.com/olekukonko/ll/lh/memory.go | 93 + vendor/github.com/olekukonko/ll/lh/multi.go | 51 + vendor/github.com/olekukonko/ll/lh/slog.go | 89 + vendor/github.com/olekukonko/ll/lh/text.go | 193 + vendor/github.com/olekukonko/ll/ll.go | 1412 ++++ vendor/github.com/olekukonko/ll/lx/lx.go | 154 + vendor/github.com/olekukonko/ll/lx/ns.go | 102 + vendor/github.com/olekukonko/ll/middleware.go | 124 + .../olekukonko/tablewriter/.gitignore | 21 +- .../olekukonko/tablewriter/.travis.yml | 22 - .../olekukonko/tablewriter/MIGRATION.md | 3280 ++++++++++ .../olekukonko/tablewriter/README.md | 1308 +++- .../olekukonko/tablewriter/README_LEGACY.md | 466 ++ .../olekukonko/tablewriter/config.go | 960 +++ .../github.com/olekukonko/tablewriter/csv.go | 88 +- .../olekukonko/tablewriter/deprecated.go | 220 + .../olekukonko/tablewriter/option.go | 891 +++ .../olekukonko/tablewriter/pkg/twwarp/wrap.go | 237 + .../tablewriter/pkg/twwidth/width.go | 321 + .../tablewriter/renderer/blueprint.go | 581 ++ .../tablewriter/renderer/colorized.go | 719 +++ .../olekukonko/tablewriter/renderer/fn.go | 236 + .../olekukonko/tablewriter/renderer/html.go | 441 ++ .../tablewriter/renderer/junction.go | 273 + .../tablewriter/renderer/markdown.go | 419 ++ .../olekukonko/tablewriter/renderer/ocean.go | 470 ++ .../olekukonko/tablewriter/renderer/svg.go | 703 ++ .../olekukonko/tablewriter/stream.go | 1164 ++++ .../olekukonko/tablewriter/table.go | 967 --- .../tablewriter/table_with_color.go | 136 - .../olekukonko/tablewriter/tablewriter.go | 2213 +++++++ .../olekukonko/tablewriter/tw/cell.go | 64 + .../olekukonko/tablewriter/tw/deprecated.go | 137 + .../olekukonko/tablewriter/tw/fn.go | 231 + .../olekukonko/tablewriter/tw/mapper.go | 220 + .../olekukonko/tablewriter/tw/preset.go | 18 + .../olekukonko/tablewriter/tw/renderer.go | 132 + .../olekukonko/tablewriter/tw/slicer.go | 147 + .../olekukonko/tablewriter/tw/state.go | 51 + .../olekukonko/tablewriter/tw/symbols.go | 1012 +++ .../olekukonko/tablewriter/tw/tw.go | 107 + .../olekukonko/tablewriter/tw/types.go | 199 + .../github.com/olekukonko/tablewriter/util.go | 93 - .../github.com/olekukonko/tablewriter/wrap.go | 99 - .../github.com/olekukonko/tablewriter/zoo.go | 1696 +++++ vendor/github.com/pjbgf/sha1cd/Dockerfile.arm | 3 +- .../github.com/pjbgf/sha1cd/Dockerfile.arm64 | 2 +- vendor/github.com/pjbgf/sha1cd/LICENSE | 2 +- vendor/github.com/pjbgf/sha1cd/Makefile | 3 +- vendor/github.com/pjbgf/sha1cd/sha1cd.go | 2 + .../pjbgf/sha1cd/sha1cdblock_amd64.s | 3 +- .../pjbgf/sha1cd/ubc/{doc.go => ubc.go} | 2 + .../github.com/pjbgf/sha1cd/ubc/ubc_amd64.go | 14 + .../github.com/pjbgf/sha1cd/ubc/ubc_amd64.s | 1897 ++++++ .../sha1cd/ubc/{check.go => ubc_generic.go} | 2 +- .../github.com/pjbgf/sha1cd/ubc/ubc_noasm.go | 12 + vendor/github.com/rivo/uniseg/LICENSE.txt | 21 + vendor/github.com/rivo/uniseg/README.md | 62 + vendor/github.com/rivo/uniseg/doc.go | 8 + vendor/github.com/rivo/uniseg/grapheme.go | 268 + vendor/github.com/rivo/uniseg/properties.go | 1658 +++++ vendor/github.com/spf13/pflag/README.md | 27 + vendor/github.com/spf13/pflag/bool_func.go | 40 + vendor/github.com/spf13/pflag/count.go | 2 +- vendor/github.com/spf13/pflag/errors.go | 149 + vendor/github.com/spf13/pflag/flag.go | 85 +- vendor/github.com/spf13/pflag/func.go | 37 + vendor/github.com/spf13/pflag/golangflag.go | 22 + vendor/github.com/spf13/pflag/ipnet_slice.go | 2 +- vendor/github.com/spf13/pflag/text.go | 81 + vendor/github.com/spf13/pflag/time.go | 118 + .../tetratelabs/wazero/.editorconfig | 7 + .../tetratelabs/wazero/.gitattributes | 2 + .../github.com/tetratelabs/wazero/.gitignore | 46 + .../github.com/tetratelabs/wazero/.gitmodules | 3 + .../tetratelabs/wazero/CONTRIBUTING.md | 75 + vendor/github.com/tetratelabs/wazero/LICENSE | 201 + vendor/github.com/tetratelabs/wazero/Makefile | 364 ++ vendor/github.com/tetratelabs/wazero/NOTICE | 2 + .../tetratelabs/wazero/RATIONALE.md | 1587 +++++ .../github.com/tetratelabs/wazero/README.md | 139 + .../tetratelabs/wazero/api/features.go | 214 + .../github.com/tetratelabs/wazero/api/wasm.go | 766 +++ .../github.com/tetratelabs/wazero/builder.go | 367 ++ vendor/github.com/tetratelabs/wazero/cache.go | 123 + .../github.com/tetratelabs/wazero/codecov.yml | 9 + .../github.com/tetratelabs/wazero/config.go | 899 +++ .../wazero/experimental/checkpoint.go | 35 + .../tetratelabs/wazero/experimental/close.go | 63 + .../wazero/experimental/experimental.go | 41 + .../wazero/experimental/features.go | 15 + .../wazero/experimental/importresolver.go | 19 + .../wazero/experimental/listener.go | 324 + .../tetratelabs/wazero/experimental/memory.go | 52 + .../wazero/experimental/sys/dir.go | 92 + .../wazero/experimental/sys/errno.go | 98 + .../wazero/experimental/sys/error.go | 45 + .../wazero/experimental/sys/file.go | 316 + .../tetratelabs/wazero/experimental/sys/fs.go | 292 + .../wazero/experimental/sys/oflag.go | 70 + .../wazero/experimental/sys/syscall_errno.go | 106 + .../sys/syscall_errno_notwindows.go | 13 + .../sys/syscall_errno_unsupported.go | 7 + .../experimental/sys/syscall_errno_windows.go | 66 + .../wazero/experimental/sys/time.go | 10 + .../wazero/experimental/sys/unimplemented.go | 160 + .../github.com/tetratelabs/wazero/fsconfig.go | 213 + .../imports/wasi_snapshot_preview1/args.go | 97 + .../imports/wasi_snapshot_preview1/clock.go | 116 + .../imports/wasi_snapshot_preview1/environ.go | 100 + .../imports/wasi_snapshot_preview1/fs.go | 2010 ++++++ .../imports/wasi_snapshot_preview1/poll.go | 237 + .../imports/wasi_snapshot_preview1/proc.go | 44 + .../imports/wasi_snapshot_preview1/random.go | 55 + .../imports/wasi_snapshot_preview1/sched.go | 22 + .../imports/wasi_snapshot_preview1/sock.go | 188 + .../imports/wasi_snapshot_preview1/wasi.go | 314 + .../wazero/internal/descriptor/table.go | 149 + .../internal/engine/interpreter/compiler.go | 3632 +++++++++++ .../internal/engine/interpreter/format.go | 22 + .../engine/interpreter/interpreter.go | 4596 +++++++++++++ .../internal/engine/interpreter/operations.go | 2812 ++++++++ .../internal/engine/interpreter/signature.go | 767 +++ .../internal/engine/wazevo/backend/abi.go | 170 + .../internal/engine/wazevo/backend/backend.go | 3 + .../engine/wazevo/backend/compiler.go | 399 ++ .../engine/wazevo/backend/compiler_lower.go | 226 + .../internal/engine/wazevo/backend/go_call.go | 33 + .../engine/wazevo/backend/isa/amd64/abi.go | 186 + .../backend/isa/amd64/abi_entry_amd64.go | 9 + .../backend/isa/amd64/abi_entry_amd64.s | 29 + .../backend/isa/amd64/abi_entry_preamble.go | 248 + .../wazevo/backend/isa/amd64/abi_go_call.go | 440 ++ .../engine/wazevo/backend/isa/amd64/cond.go | 168 + .../engine/wazevo/backend/isa/amd64/ext.go | 35 + .../engine/wazevo/backend/isa/amd64/instr.go | 2447 +++++++ .../backend/isa/amd64/instr_encoding.go | 1683 +++++ .../backend/isa/amd64/lower_constant.go | 71 + .../wazevo/backend/isa/amd64/lower_mem.go | 187 + .../wazevo/backend/isa/amd64/machine.go | 3733 +++++++++++ .../isa/amd64/machine_pro_epi_logue.go | 303 + .../backend/isa/amd64/machine_regalloc.go | 352 + .../wazevo/backend/isa/amd64/machine_vec.go | 992 +++ .../wazevo/backend/isa/amd64/operands.go | 336 + .../engine/wazevo/backend/isa/amd64/reg.go | 181 + .../engine/wazevo/backend/isa/amd64/stack.go | 130 + .../engine/wazevo/backend/isa/arm64/abi.go | 333 + .../backend/isa/arm64/abi_entry_arm64.go | 9 + .../backend/isa/arm64/abi_entry_arm64.s | 29 + .../backend/isa/arm64/abi_entry_preamble.go | 233 + .../wazevo/backend/isa/arm64/abi_go_call.go | 430 ++ .../engine/wazevo/backend/isa/arm64/cond.go | 215 + .../engine/wazevo/backend/isa/arm64/instr.go | 2534 ++++++++ .../backend/isa/arm64/instr_encoding.go | 2351 +++++++ .../backend/isa/arm64/lower_constant.go | 301 + .../wazevo/backend/isa/arm64/lower_instr.go | 2224 +++++++ .../backend/isa/arm64/lower_instr_operands.go | 340 + .../wazevo/backend/isa/arm64/lower_mem.go | 451 ++ .../wazevo/backend/isa/arm64/machine.go | 631 ++ .../isa/arm64/machine_pro_epi_logue.go | 467 ++ .../backend/isa/arm64/machine_regalloc.go | 351 + .../backend/isa/arm64/machine_relocation.go | 122 + .../engine/wazevo/backend/isa/arm64/reg.go | 397 ++ .../wazevo/backend/isa/arm64/unwind_stack.go | 84 + .../internal/engine/wazevo/backend/machine.go | 119 + .../engine/wazevo/backend/regalloc/api.go | 124 + .../engine/wazevo/backend/regalloc/reg.go | 123 + .../wazevo/backend/regalloc/regalloc.go | 1189 ++++ .../engine/wazevo/backend/regalloc/regset.go | 96 + .../internal/engine/wazevo/backend/vdef.go | 19 + .../internal/engine/wazevo/call_engine.go | 708 ++ .../wazero/internal/engine/wazevo/engine.go | 843 +++ .../internal/engine/wazevo/engine_cache.go | 303 + .../engine/wazevo/entrypoint_amd64.go | 15 + .../engine/wazevo/entrypoint_arm64.go | 15 + .../engine/wazevo/entrypoint_others.go | 15 + .../engine/wazevo/frontend/frontend.go | 567 ++ .../internal/engine/wazevo/frontend/lower.go | 4261 ++++++++++++ .../internal/engine/wazevo/frontend/misc.go | 10 + .../engine/wazevo/frontend/sort_id.go | 13 + .../internal/engine/wazevo/hostmodule.go | 88 + .../internal/engine/wazevo/isa_amd64.go | 30 + .../internal/engine/wazevo/isa_arm64.go | 32 + .../internal/engine/wazevo/isa_other.go | 29 + .../wazero/internal/engine/wazevo/memmove.go | 11 + .../internal/engine/wazevo/module_engine.go | 331 + .../internal/engine/wazevo/ssa/basic_block.go | 379 ++ .../engine/wazevo/ssa/basic_block_sort.go | 32 + .../internal/engine/wazevo/ssa/builder.go | 790 +++ .../wazero/internal/engine/wazevo/ssa/cmp.go | 107 + .../internal/engine/wazevo/ssa/funcref.go | 12 + .../engine/wazevo/ssa/instructions.go | 2976 +++++++++ .../wazero/internal/engine/wazevo/ssa/pass.go | 393 ++ .../engine/wazevo/ssa/pass_blk_layouts.go | 334 + .../internal/engine/wazevo/ssa/pass_cfg.go | 313 + .../internal/engine/wazevo/ssa/signature.go | 49 + .../wazero/internal/engine/wazevo/ssa/ssa.go | 14 + .../wazero/internal/engine/wazevo/ssa/type.go | 115 + .../wazero/internal/engine/wazevo/ssa/vs.go | 114 + .../engine/wazevo/wazevoapi/debug_options.go | 196 + .../engine/wazevo/wazevoapi/exitcode.go | 109 + .../engine/wazevo/wazevoapi/offsetdata.go | 216 + .../engine/wazevo/wazevoapi/perfmap.go | 96 + .../wazevo/wazevoapi/perfmap_disabled.go | 5 + .../wazevo/wazevoapi/perfmap_enabled.go | 5 + .../internal/engine/wazevo/wazevoapi/pool.go | 215 + .../internal/engine/wazevo/wazevoapi/ptr.go | 15 + .../internal/engine/wazevo/wazevoapi/queue.go | 26 + .../engine/wazevo/wazevoapi/resetmap.go | 11 + .../wazero/internal/expctxkeys/checkpoint.go | 10 + .../wazero/internal/expctxkeys/close.go | 5 + .../wazero/internal/expctxkeys/expctxkeys.go | 2 + .../internal/expctxkeys/importresolver.go | 6 + .../wazero/internal/expctxkeys/listener.go | 7 + .../wazero/internal/expctxkeys/memory.go | 4 + .../internal/filecache/compilationcache.go | 42 + .../wazero/internal/filecache/file_cache.go | 76 + .../tetratelabs/wazero/internal/fsapi/file.go | 69 + .../tetratelabs/wazero/internal/fsapi/poll.go | 20 + .../wazero/internal/fsapi/unimplemented.go | 27 + .../wazero/internal/ieee754/ieee754.go | 29 + .../wazero/internal/internalapi/internal.go | 9 + .../wazero/internal/leb128/leb128.go | 285 + .../wazero/internal/moremath/moremath.go | 271 + .../wazero/internal/platform/cpuid.go | 35 + .../wazero/internal/platform/cpuid_amd64.go | 80 + .../wazero/internal/platform/cpuid_amd64.s | 16 + .../wazero/internal/platform/cpuid_arm64.go | 71 + .../wazero/internal/platform/cpuid_arm64.s | 21 + .../internal/platform/cpuid_unsupported.go | 17 + .../wazero/internal/platform/crypto.go | 17 + .../wazero/internal/platform/mmap_linux.go | 76 + .../wazero/internal/platform/mmap_other.go | 18 + .../wazero/internal/platform/mmap_unix.go | 32 + .../internal/platform/mmap_unsupported.go | 26 + .../wazero/internal/platform/mmap_windows.go | 95 + .../wazero/internal/platform/mprotect_bsd.go | 22 + .../internal/platform/mprotect_syscall.go | 10 + .../internal/platform/mprotect_unsupported.go | 9 + .../wazero/internal/platform/path.go | 6 + .../wazero/internal/platform/path_windows.go | 17 + .../wazero/internal/platform/platform.go | 56 + .../wazero/internal/platform/time.go | 76 + .../wazero/internal/platform/time_cgo.go | 11 + .../wazero/internal/platform/time_notcgo.go | 7 + .../wazero/internal/platform/time_windows.go | 40 + .../tetratelabs/wazero/internal/sock/sock.go | 89 + .../wazero/internal/sock/sock_supported.go | 11 + .../wazero/internal/sock/sock_unsupported.go | 10 + .../tetratelabs/wazero/internal/sys/fs.go | 457 ++ .../tetratelabs/wazero/internal/sys/lazy.go | 151 + .../tetratelabs/wazero/internal/sys/stdio.go | 128 + .../tetratelabs/wazero/internal/sys/sys.go | 228 + .../wazero/internal/sysfs/adapter.go | 105 + .../wazero/internal/sysfs/datasync_linux.go | 14 + .../wazero/internal/sysfs/datasync_tinygo.go | 13 + .../internal/sysfs/datasync_unsupported.go | 14 + .../tetratelabs/wazero/internal/sysfs/dir.go | 24 + .../wazero/internal/sysfs/dirfs.go | 99 + .../wazero/internal/sysfs/dirfs_supported.go | 48 + .../internal/sysfs/dirfs_unsupported.go | 34 + .../tetratelabs/wazero/internal/sysfs/file.go | 523 ++ .../wazero/internal/sysfs/file_unix.go | 39 + .../wazero/internal/sysfs/file_unsupported.go | 28 + .../wazero/internal/sysfs/file_windows.go | 175 + .../wazero/internal/sysfs/futimens.go | 37 + .../wazero/internal/sysfs/futimens_darwin.go | 51 + .../wazero/internal/sysfs/futimens_darwin.s | 8 + .../wazero/internal/sysfs/futimens_linux.go | 49 + .../internal/sysfs/futimens_unsupported.go | 18 + .../wazero/internal/sysfs/futimens_windows.go | 42 + .../tetratelabs/wazero/internal/sysfs/ino.go | 22 + .../wazero/internal/sysfs/ino_plan9.go | 15 + .../wazero/internal/sysfs/ino_tinygo.go | 14 + .../wazero/internal/sysfs/ino_windows.go | 28 + .../wazero/internal/sysfs/nonblock_unix.go | 17 + .../internal/sysfs/nonblock_unsupported.go | 13 + .../wazero/internal/sysfs/nonblock_windows.go | 23 + .../wazero/internal/sysfs/oflag.go | 38 + .../wazero/internal/sysfs/open_file_darwin.go | 26 + .../internal/sysfs/open_file_freebsd.go | 24 + .../wazero/internal/sysfs/open_file_linux.go | 30 + .../internal/sysfs/open_file_notwindows.go | 20 + .../wazero/internal/sysfs/open_file_sun.go | 31 + .../wazero/internal/sysfs/open_file_tinygo.go | 25 + .../internal/sysfs/open_file_unsupported.go | 18 + .../internal/sysfs/open_file_windows.go | 161 + .../wazero/internal/sysfs/osfile.go | 319 + .../tetratelabs/wazero/internal/sysfs/poll.go | 18 + .../wazero/internal/sysfs/poll_darwin.go | 55 + .../wazero/internal/sysfs/poll_darwin.s | 8 + .../wazero/internal/sysfs/poll_linux.go | 59 + .../wazero/internal/sysfs/poll_unsupported.go | 13 + .../wazero/internal/sysfs/poll_windows.go | 224 + .../wazero/internal/sysfs/readfs.go | 117 + .../wazero/internal/sysfs/rename.go | 16 + .../wazero/internal/sysfs/rename_plan9.go | 14 + .../wazero/internal/sysfs/rename_windows.go | 55 + .../tetratelabs/wazero/internal/sysfs/sock.go | 187 + .../wazero/internal/sysfs/sock_supported.go | 77 + .../wazero/internal/sysfs/sock_unix.go | 49 + .../wazero/internal/sysfs/sock_unsupported.go | 81 + .../wazero/internal/sysfs/sock_windows.go | 80 + .../tetratelabs/wazero/internal/sysfs/stat.go | 16 + .../wazero/internal/sysfs/stat_bsd.go | 37 + .../wazero/internal/sysfs/stat_linux.go | 40 + .../wazero/internal/sysfs/stat_unsupported.go | 40 + .../wazero/internal/sysfs/stat_windows.go | 120 + .../tetratelabs/wazero/internal/sysfs/sync.go | 13 + .../wazero/internal/sysfs/sync_windows.go | 20 + .../wazero/internal/sysfs/syscall6_darwin.go | 13 + .../wazero/internal/sysfs/sysfs.go | 6 + .../wazero/internal/sysfs/unlink.go | 17 + .../wazero/internal/sysfs/unlink_plan9.go | 12 + .../wazero/internal/sysfs/unlink_windows.go | 25 + .../tetratelabs/wazero/internal/u32/u32.go | 11 + .../tetratelabs/wazero/internal/u64/u64.go | 15 + .../wazero/internal/version/version.go | 52 + .../wazero/internal/wasip1/args.go | 6 + .../wazero/internal/wasip1/clock.go | 16 + .../wazero/internal/wasip1/environ.go | 6 + .../wazero/internal/wasip1/errno.go | 314 + .../tetratelabs/wazero/internal/wasip1/fs.go | 164 + .../wazero/internal/wasip1/poll.go | 15 + .../wazero/internal/wasip1/proc.go | 6 + .../wazero/internal/wasip1/random.go | 3 + .../wazero/internal/wasip1/rights.go | 148 + .../wazero/internal/wasip1/sched.go | 3 + .../wazero/internal/wasip1/sock.go | 71 + .../wazero/internal/wasip1/wasi.go | 26 + .../wazero/internal/wasm/binary/code.go | 100 + .../wazero/internal/wasm/binary/const_expr.go | 105 + .../wazero/internal/wasm/binary/custom.go | 22 + .../wazero/internal/wasm/binary/data.go | 79 + .../wazero/internal/wasm/binary/decoder.go | 193 + .../wazero/internal/wasm/binary/element.go | 269 + .../wazero/internal/wasm/binary/errors.go | 11 + .../wazero/internal/wasm/binary/export.go | 32 + .../wazero/internal/wasm/binary/function.go | 56 + .../wazero/internal/wasm/binary/global.go | 50 + .../wazero/internal/wasm/binary/header.go | 9 + .../wazero/internal/wasm/binary/import.go | 52 + .../wazero/internal/wasm/binary/limits.go | 47 + .../wazero/internal/wasm/binary/memory.go | 42 + .../wazero/internal/wasm/binary/names.go | 151 + .../wazero/internal/wasm/binary/section.go | 226 + .../wazero/internal/wasm/binary/table.go | 43 + .../wazero/internal/wasm/binary/value.go | 59 + .../wazero/internal/wasm/counts.go | 51 + .../wazero/internal/wasm/engine.go | 76 + .../wazero/internal/wasm/func_validation.go | 2336 +++++++ .../internal/wasm/function_definition.go | 188 + .../wazero/internal/wasm/global.go | 55 + .../wazero/internal/wasm/gofunc.go | 279 + .../tetratelabs/wazero/internal/wasm/host.go | 179 + .../wazero/internal/wasm/instruction.go | 1866 ++++++ .../wazero/internal/wasm/memory.go | 476 ++ .../wazero/internal/wasm/memory_definition.go | 128 + .../wazero/internal/wasm/module.go | 1078 ++++ .../wazero/internal/wasm/module_instance.go | 251 + .../internal/wasm/module_instance_lookup.go | 73 + .../tetratelabs/wazero/internal/wasm/store.go | 679 ++ .../wazero/internal/wasm/store_module_list.go | 95 + .../tetratelabs/wazero/internal/wasm/table.go | 339 + .../wazero/internal/wasmdebug/debug.go | 170 + .../wazero/internal/wasmdebug/dwarf.go | 225 + .../wazero/internal/wasmruntime/errors.go | 50 + .../tetratelabs/wazero/netlify.toml | 15 + .../github.com/tetratelabs/wazero/runtime.go | 399 ++ .../tetratelabs/wazero/sys/clock.go | 26 + .../tetratelabs/wazero/sys/error.go | 83 + .../github.com/tetratelabs/wazero/sys/stat.go | 105 + .../tetratelabs/wazero/sys/stat_bsd.go | 29 + .../tetratelabs/wazero/sys/stat_linux.go | 32 + .../wazero/sys/stat_unsupported.go | 14 + .../tetratelabs/wazero/sys/stat_windows.go | 26 + .../github.com/wasilibs/go-re2/.gitattributes | 1 + vendor/github.com/wasilibs/go-re2/.gitignore | 3 + .../github.com/wasilibs/go-re2/.golangci.yml | 19 + .../github.com/wasilibs/go-re2/.yamllint.yaml | 5 + .../wasilibs/go-re2/CODE_OF_CONDUCT.md | 132 + vendor/github.com/wasilibs/go-re2/LICENSE | 21 + vendor/github.com/wasilibs/go-re2/NOTICE.txt | 29 + .../github.com/wasilibs/go-re2/RATIONALE.md | 34 + vendor/github.com/wasilibs/go-re2/README.md | 274 + .../wasilibs/go-re2/go-re2.code-workspace | 24 + vendor/github.com/wasilibs/go-re2/go.work | 8 + .../wasilibs/go-re2/internal/cre2/NOTICE.txt | 32 + .../wasilibs/go-re2/internal/cre2/cre2.cpp | 719 +++ .../wasilibs/go-re2/internal/cre2/cre2.go | 168 + .../wasilibs/go-re2/internal/cre2/cre2.h | 343 + .../go-re2/internal/cre2/cre2_re2_cgo.go | 9 + .../wasilibs/go-re2/internal/re2.go | 1043 +++ .../wasilibs/go-re2/internal/re2_re2_cgo.go | 216 + .../wasilibs/go-re2/internal/re2_wazero.go | 739 +++ .../go-re2/internal/re2_wazero_config.go | 5 + .../go-re2/internal/re2_wazero_config_wasm.go | 8 + .../wasilibs/go-re2/internal/set.go | 117 + .../go-re2/internal/wasm/libcre2.wasm | Bin 0 -> 3181648 bytes .../wasilibs/go-re2/internal/wasm/memory.wasm | Bin 0 -> 28 bytes vendor/github.com/wasilibs/go-re2/re2.go | 99 + .../wasilibs/wazero-helpers/LICENSE | 21 + .../wazero-helpers/allocator/nonmoving.go | 28 + .../allocator/nonmoving_other.go | 11 + .../allocator/nonmoving_slice.go | 24 + .../allocator/nonmoving_unix.go | 89 + .../allocator/nonmoving_windows.go | 93 + vendor/golang.org/x/crypto/bcrypt/bcrypt.go | 2 +- vendor/golang.org/x/sys/unix/mkerrors.sh | 3 + .../golang.org/x/sys/unix/syscall_darwin.go | 93 + vendor/golang.org/x/sys/unix/syscall_linux.go | 42 +- vendor/golang.org/x/sys/unix/zerrors_linux.go | 63 +- .../x/sys/unix/zerrors_linux_386.go | 3 + .../x/sys/unix/zerrors_linux_amd64.go | 3 + .../x/sys/unix/zerrors_linux_arm.go | 3 + .../x/sys/unix/zerrors_linux_arm64.go | 3 + .../x/sys/unix/zerrors_linux_loong64.go | 3 + .../x/sys/unix/zerrors_linux_mips.go | 3 + .../x/sys/unix/zerrors_linux_mips64.go | 3 + .../x/sys/unix/zerrors_linux_mips64le.go | 3 + .../x/sys/unix/zerrors_linux_mipsle.go | 3 + .../x/sys/unix/zerrors_linux_ppc.go | 3 + .../x/sys/unix/zerrors_linux_ppc64.go | 3 + .../x/sys/unix/zerrors_linux_ppc64le.go | 3 + .../x/sys/unix/zerrors_linux_riscv64.go | 3 + .../x/sys/unix/zerrors_linux_s390x.go | 3 + .../x/sys/unix/zerrors_linux_sparc64.go | 3 + .../x/sys/unix/zsyscall_darwin_amd64.go | 84 + .../x/sys/unix/zsyscall_darwin_amd64.s | 20 + .../x/sys/unix/zsyscall_darwin_arm64.go | 84 + .../x/sys/unix/zsyscall_darwin_arm64.s | 20 + .../x/sys/unix/zsysnum_linux_386.go | 1 + .../x/sys/unix/zsysnum_linux_amd64.go | 1 + .../x/sys/unix/zsysnum_linux_arm.go | 1 + .../x/sys/unix/zsysnum_linux_arm64.go | 1 + .../x/sys/unix/zsysnum_linux_loong64.go | 1 + .../x/sys/unix/zsysnum_linux_mips.go | 1 + .../x/sys/unix/zsysnum_linux_mips64.go | 1 + .../x/sys/unix/zsysnum_linux_mips64le.go | 1 + .../x/sys/unix/zsysnum_linux_mipsle.go | 1 + .../x/sys/unix/zsysnum_linux_ppc.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 1 + .../x/sys/unix/zsysnum_linux_riscv64.go | 1 + .../x/sys/unix/zsysnum_linux_s390x.go | 1 + .../x/sys/unix/zsysnum_linux_sparc64.go | 1 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 139 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 18 +- .../x/sys/unix/ztypes_linux_amd64.go | 16 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 20 +- .../x/sys/unix/ztypes_linux_arm64.go | 16 + .../x/sys/unix/ztypes_linux_loong64.go | 16 + .../x/sys/unix/ztypes_linux_mips.go | 18 +- .../x/sys/unix/ztypes_linux_mips64.go | 16 + .../x/sys/unix/ztypes_linux_mips64le.go | 16 + .../x/sys/unix/ztypes_linux_mipsle.go | 18 +- .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 20 +- .../x/sys/unix/ztypes_linux_ppc64.go | 16 + .../x/sys/unix/ztypes_linux_ppc64le.go | 16 + .../x/sys/unix/ztypes_linux_riscv64.go | 16 + .../x/sys/unix/ztypes_linux_s390x.go | 16 + .../x/sys/unix/ztypes_linux_sparc64.go | 16 + .../x/sys/windows/security_windows.go | 49 +- .../x/sys/windows/syscall_windows.go | 6 +- .../golang.org/x/sys/windows/types_windows.go | 239 + .../x/sys/windows/zsyscall_windows.go | 9 + vendor/golang.org/x/tools/godoc/util/util.go | 6 +- .../golang.org/x/tools/godoc/vfs/emptyvfs.go | 2 +- vendor/golang.org/x/tools/godoc/vfs/fs.go | 1 - .../golang.org/x/tools/godoc/vfs/namespace.go | 2 +- vendor/golang.org/x/tools/godoc/vfs/os.go | 7 +- vendor/modules.txt | 111 +- 1097 files changed, 309986 insertions(+), 2603 deletions(-) create mode 100644 vendor/github.com/fatih/color/LICENSE.md create mode 100644 vendor/github.com/fatih/color/README.md create mode 100644 vendor/github.com/fatih/color/color.go create mode 100644 vendor/github.com/fatih/color/color_windows.go create mode 100644 vendor/github.com/fatih/color/doc.go create mode 100644 vendor/github.com/go-viper/mapstructure/v2/errors.go create mode 100644 vendor/github.com/hashicorp/go-retryablehttp/.golangci.yml create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/.gitignore create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/.openapi-generator-ignore create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/.travis.yml create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/LICENSE.txt create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/README.md create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_access_tokens.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_account_members.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_account_members_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_account_usage_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_ai_configs_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_announcements.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_applications_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_approvals.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_approvals_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_audit_log.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_code_references.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_context_settings.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_contexts.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_custom_roles.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_data_export_destinations.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_environments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_experiments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_flag_import_configurations_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_flag_links_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_flag_triggers.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_follow_flags.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_holdouts_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_charts_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_deployments_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_flag_events_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_pull_requests_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_repositories_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_insights_scores_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_integration_audit_log_subscriptions.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_integration_delivery_configurations_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_integrations_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_layers.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_metrics.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_metrics_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_o_auth2_clients.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_other.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_persistent_store_integrations_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_projects.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_relay_proxy_configurations.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_release_pipelines_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_releases_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_scheduled_changes.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_segments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_tags.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_teams.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_teams_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_user_settings.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_users.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_users_beta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_webhooks.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_workflow_templates.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/api_workflows.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/client.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/configuration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/git_push.sh create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_access_token_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_action_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_action_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config__maintainer.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_patch.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_patch.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variations_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_maintainer_team.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_paginated_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_patch_operation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response__links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_application_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_application_flag_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_application_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_application_version_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_application_versions_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_approval_request_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_approval_settings.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_approvals_capability_config.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_assigned_to_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audience.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audience_configuration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audience_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_authorized_app_data_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_beta_binomial_stats_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_normal_stats_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_status.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_target.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_defaults.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_flag_defaults.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_branch_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_branch_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_members_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_teams_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_caller_identity_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_clause.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_client.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_client_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_completed_by.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_condition_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_condition_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_conflict.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_conflict_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_name.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_value.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluations.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_record.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_search.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_membership.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_memberships.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_instances.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_kind_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_kinds_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_record.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_context_search.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_contexts.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_copied_from_env.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_core_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_announcement_body.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_approval_request_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_copy_flag_config_approval_request_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_flag_config_approval_request_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_phase_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_pipeline_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_create_workflow_template_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_credible_interval_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_property.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_roles.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_meta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_stage_meta.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflows_listing_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_defaults.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_experiment_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag_environment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flags_by_environment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep_with_metrics.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_or_metric_group_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_destination.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_destination_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_destinations.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_distribution.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options_parser.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_endpoint.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_environment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_environment_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_environment_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_environments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_error.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_evaluation_reason.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_evaluations_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_execution_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_request_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_requests_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_flag_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_resource_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_allocation_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_bayesian_results_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_enabled_period_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_environment_setting_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_info_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_error.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_get_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_patch_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_get_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_item.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_patch_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_export.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_extinction.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_extinction_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_failure_reason_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_body.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_config.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_change.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_changes.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status_across_environments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_statuses.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flags.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_file_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_request_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_requests_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_evaluation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_migration_settings_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_environment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_defaults_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_iteration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_impact_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_member_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_by_proj_env_get_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_get_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_configuration_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_status.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_member.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_listing_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_migration_settings_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_prerequisite_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_scheduled_changes_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_sempatch.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_status_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_flag_trigger_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_follow_flag_member.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_followers_per_flag.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_forbidden_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_form_variable.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_generate_warehouse_destination_key_pair_post_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_get_announcements_public_200_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_header_items.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_hmac_signature.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_detail_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_post_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_holdouts_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_hunk_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_import.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_initiator_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_score_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_scores.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_groups_count_by_indicator.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_period.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insight_scores.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_bounds.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metric.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_data_point.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata_axis.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_indicator_range.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_score.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_tier_definition.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_mappings.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_instruction_user_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configurations_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integration_subscription_status_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_integrations.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_invalid_request_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_ip_list.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_last_seen_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_configuration_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_reservation_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_layer_snapshot_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_lead_time_stages_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_legacy_experiment_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_member.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_team.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_data_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_import_item.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_permission_grant_summary_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_team_summary_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_member_teams_post_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_members.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_members_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_message.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_method_not_allowed_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_by_variation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_event_default_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_results_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_results_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_metric_group_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_listing_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_seen.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metric_v2_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_metrics.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_migration_safety_issue_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_migration_settings_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_model_config.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_model_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_modification.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flag.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flags.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_naming_convention.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_new_member_form.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_not_found_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_oauth_client_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_options_array.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_paginated_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_default.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_parent_and_self_links.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_parent_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_parent_resource_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_failed_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_flags_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_operation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_input_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_instruction.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_instruction.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_users_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_patch_with_comment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_permission_grant_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_phase.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_phase_info.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_apply_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_review_request.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_post_deployment_event_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_post_flag_scheduled_changes_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_post_insight_group_params.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_prerequisite.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_project.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_project_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_project_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_projects.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_lead_time_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_put_branch.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_put.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_rate_limited_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_recent_trigger_body.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_reference_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_related_experiment_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_relative_difference_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_audience.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_phase.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_releaser_audience_config_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_repository_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_repository_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_repository_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_resource_access.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_review_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_review_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_rollout.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_root_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_rule.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_rule_clause.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_list_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_list_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_segment_body.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_segment_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_segment_target.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_list.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_state.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_series.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_series_intervals_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_series_list_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_simple_holdout_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_sliced_results_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_source_env.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_source_flag.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_stage_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_stage_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_statement.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_statement_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_statistics_root.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_status_conflict_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_status_response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_status_service_unavailable.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_store_integration_error.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_subject_data_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_subscription_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_tags_collection.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_tags_link.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_target.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_target_resource_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_role.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_roles.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_imports_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_maintainers.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_members.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_post_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_team_projects.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_teams.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_teams_patch_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_timestamp_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_token.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_token_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_tokens.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_parameter_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_result_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_collection_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_unauthorized_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_update_phase_status_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_update_release_pipeline_input.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_context_kind_payload.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_flag_defaults_payload.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_payload_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_response_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_url_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_attribute_names_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_setting.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_settings.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_record.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment_rule.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_user_segments.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_users.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_users_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_validation_failed_error_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_value_put.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_variation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_variation_eval_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_variation_or_rollout_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_variation_summary.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_versions_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_webhook.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_webhook_post.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_webhooks.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_weighted_variation.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_metadata.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_output.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_parameter.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_templates_listing_output_rep.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/response.go create mode 100644 vendor/github.com/launchdarkly/api-client-go/v17/utils.go create mode 100644 vendor/github.com/mattn/go-colorable/LICENSE create mode 100644 vendor/github.com/mattn/go-colorable/README.md create mode 100644 vendor/github.com/mattn/go-colorable/colorable_appengine.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_others.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_windows.go rename vendor/github.com/mattn/{go-runewidth => go-colorable}/go.test.sh (100%) create mode 100644 vendor/github.com/mattn/go-colorable/noncolorable.go delete mode 100644 vendor/github.com/mattn/go-runewidth/.travis.yml create mode 100644 vendor/github.com/olekukonko/errors/.gitignore create mode 100644 vendor/github.com/olekukonko/errors/LICENSE create mode 100644 vendor/github.com/olekukonko/errors/README.md create mode 100644 vendor/github.com/olekukonko/errors/errors.go create mode 100644 vendor/github.com/olekukonko/errors/helper.go create mode 100644 vendor/github.com/olekukonko/errors/multi_error.go create mode 100644 vendor/github.com/olekukonko/errors/pool.go create mode 100644 vendor/github.com/olekukonko/errors/pool_above_1_24.go create mode 100644 vendor/github.com/olekukonko/errors/pool_below_1_24.go create mode 100644 vendor/github.com/olekukonko/errors/retry.go create mode 100644 vendor/github.com/olekukonko/errors/utils.go create mode 100644 vendor/github.com/olekukonko/ll/.gitignore create mode 100644 vendor/github.com/olekukonko/ll/LICENSE create mode 100644 vendor/github.com/olekukonko/ll/README.md create mode 100644 vendor/github.com/olekukonko/ll/concat.go create mode 100644 vendor/github.com/olekukonko/ll/conditional.go create mode 100644 vendor/github.com/olekukonko/ll/field.go create mode 100644 vendor/github.com/olekukonko/ll/global.go create mode 100644 vendor/github.com/olekukonko/ll/lc.go create mode 100644 vendor/github.com/olekukonko/ll/lh/buffered.go create mode 100644 vendor/github.com/olekukonko/ll/lh/colorized.go create mode 100644 vendor/github.com/olekukonko/ll/lh/json.go create mode 100644 vendor/github.com/olekukonko/ll/lh/memory.go create mode 100644 vendor/github.com/olekukonko/ll/lh/multi.go create mode 100644 vendor/github.com/olekukonko/ll/lh/slog.go create mode 100644 vendor/github.com/olekukonko/ll/lh/text.go create mode 100644 vendor/github.com/olekukonko/ll/ll.go create mode 100644 vendor/github.com/olekukonko/ll/lx/lx.go create mode 100644 vendor/github.com/olekukonko/ll/lx/ns.go create mode 100644 vendor/github.com/olekukonko/ll/middleware.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/.travis.yml create mode 100644 vendor/github.com/olekukonko/tablewriter/MIGRATION.md create mode 100644 vendor/github.com/olekukonko/tablewriter/README_LEGACY.md create mode 100644 vendor/github.com/olekukonko/tablewriter/config.go create mode 100644 vendor/github.com/olekukonko/tablewriter/deprecated.go create mode 100644 vendor/github.com/olekukonko/tablewriter/option.go create mode 100644 vendor/github.com/olekukonko/tablewriter/pkg/twwarp/wrap.go create mode 100644 vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/blueprint.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/colorized.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/fn.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/html.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/junction.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/markdown.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/ocean.go create mode 100644 vendor/github.com/olekukonko/tablewriter/renderer/svg.go create mode 100644 vendor/github.com/olekukonko/tablewriter/stream.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/table.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/table_with_color.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tablewriter.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/cell.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/deprecated.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/fn.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/mapper.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/preset.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/renderer.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/slicer.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/state.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/symbols.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/tw.go create mode 100644 vendor/github.com/olekukonko/tablewriter/tw/types.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/util.go delete mode 100644 vendor/github.com/olekukonko/tablewriter/wrap.go create mode 100644 vendor/github.com/olekukonko/tablewriter/zoo.go rename vendor/github.com/pjbgf/sha1cd/ubc/{doc.go => ubc.go} (68%) create mode 100644 vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go create mode 100644 vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s rename vendor/github.com/pjbgf/sha1cd/ubc/{check.go => ubc_generic.go} (99%) create mode 100644 vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go create mode 100644 vendor/github.com/rivo/uniseg/LICENSE.txt create mode 100644 vendor/github.com/rivo/uniseg/README.md create mode 100644 vendor/github.com/rivo/uniseg/doc.go create mode 100644 vendor/github.com/rivo/uniseg/grapheme.go create mode 100644 vendor/github.com/rivo/uniseg/properties.go create mode 100644 vendor/github.com/spf13/pflag/bool_func.go create mode 100644 vendor/github.com/spf13/pflag/errors.go create mode 100644 vendor/github.com/spf13/pflag/func.go create mode 100644 vendor/github.com/spf13/pflag/text.go create mode 100644 vendor/github.com/spf13/pflag/time.go create mode 100644 vendor/github.com/tetratelabs/wazero/.editorconfig create mode 100644 vendor/github.com/tetratelabs/wazero/.gitattributes create mode 100644 vendor/github.com/tetratelabs/wazero/.gitignore create mode 100644 vendor/github.com/tetratelabs/wazero/.gitmodules create mode 100644 vendor/github.com/tetratelabs/wazero/CONTRIBUTING.md create mode 100644 vendor/github.com/tetratelabs/wazero/LICENSE create mode 100644 vendor/github.com/tetratelabs/wazero/Makefile create mode 100644 vendor/github.com/tetratelabs/wazero/NOTICE create mode 100644 vendor/github.com/tetratelabs/wazero/RATIONALE.md create mode 100644 vendor/github.com/tetratelabs/wazero/README.md create mode 100644 vendor/github.com/tetratelabs/wazero/api/features.go create mode 100644 vendor/github.com/tetratelabs/wazero/api/wasm.go create mode 100644 vendor/github.com/tetratelabs/wazero/builder.go create mode 100644 vendor/github.com/tetratelabs/wazero/cache.go create mode 100644 vendor/github.com/tetratelabs/wazero/codecov.yml create mode 100644 vendor/github.com/tetratelabs/wazero/config.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/close.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/experimental.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/features.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/importresolver.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/listener.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/memory.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/error.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/file.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/time.go create mode 100644 vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go create mode 100644 vendor/github.com/tetratelabs/wazero/fsconfig.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/args.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/clock.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/environ.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/fs.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/poll.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/proc.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/random.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sched.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sock.go create mode 100644 vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/wasi.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/descriptor/table.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/compiler.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/format.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/interpreter.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/operations.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/signature.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/abi.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/backend.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler_lower.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/go_call.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/cond.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/ext.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_constant.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_mem.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_pro_epi_logue.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_regalloc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_vec.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/operands.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/reg.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/stack.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_preamble.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_go_call.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/cond.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_constant.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_mem.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_regalloc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_relocation.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/reg.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/machine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/api.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/reg.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regalloc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regset.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/vdef.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/call_engine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine_cache.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_amd64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_arm64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_others.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/frontend.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/lower.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/misc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/sort_id.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/hostmodule.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_amd64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_arm64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_other.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/memmove.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/module_engine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/cmp.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/funcref.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/signature.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/ssa.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/debug_options.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/exitcode.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/offsetdata.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_disabled.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_enabled.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/pool.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/ptr.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/queue.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/resetmap.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/checkpoint.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/close.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/expctxkeys.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/importresolver.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/listener.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/expctxkeys/memory.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/filecache/compilationcache.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/filecache/file_cache.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/fsapi/file.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/fsapi/poll.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/fsapi/unimplemented.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/ieee754/ieee754.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/internalapi/internal.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/leb128/leb128.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/moremath/moremath.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_bsd.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_syscall.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/path.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/platform.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/time.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sock/sock.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sock/sock_supported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sock/sock_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sys/fs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sys/lazy.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sys/stdio.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sys/sys.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/adapter.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_tinygo.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/dir.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_supported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unix.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/file_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/ino.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_plan9.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_tinygo.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unix.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/oflag.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_darwin.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_freebsd.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_notwindows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_sun.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_tinygo.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/osfile.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.s create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/readfs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/rename.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_plan9.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sock.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_supported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unix.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/stat.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_bsd.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sync.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sync_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/syscall6_darwin.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/sysfs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_plan9.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_windows.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/u32/u32.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/u64/u64.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/version/version.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/args.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/clock.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/environ.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/errno.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/fs.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/poll.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/proc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/random.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/rights.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/sched.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/sock.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasip1/wasi.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/global.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/host.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/module.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/store.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasm/table.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasmdebug/debug.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasmdebug/dwarf.go create mode 100644 vendor/github.com/tetratelabs/wazero/internal/wasmruntime/errors.go create mode 100644 vendor/github.com/tetratelabs/wazero/netlify.toml create mode 100644 vendor/github.com/tetratelabs/wazero/runtime.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/clock.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/error.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/stat.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/stat_bsd.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/stat_linux.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/stat_unsupported.go create mode 100644 vendor/github.com/tetratelabs/wazero/sys/stat_windows.go create mode 100644 vendor/github.com/wasilibs/go-re2/.gitattributes create mode 100644 vendor/github.com/wasilibs/go-re2/.gitignore create mode 100644 vendor/github.com/wasilibs/go-re2/.golangci.yml create mode 100644 vendor/github.com/wasilibs/go-re2/.yamllint.yaml create mode 100644 vendor/github.com/wasilibs/go-re2/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/wasilibs/go-re2/LICENSE create mode 100644 vendor/github.com/wasilibs/go-re2/NOTICE.txt create mode 100644 vendor/github.com/wasilibs/go-re2/RATIONALE.md create mode 100644 vendor/github.com/wasilibs/go-re2/README.md create mode 100644 vendor/github.com/wasilibs/go-re2/go-re2.code-workspace create mode 100644 vendor/github.com/wasilibs/go-re2/go.work create mode 100644 vendor/github.com/wasilibs/go-re2/internal/cre2/NOTICE.txt create mode 100644 vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.cpp create mode 100644 vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.h create mode 100644 vendor/github.com/wasilibs/go-re2/internal/cre2/cre2_re2_cgo.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/re2.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/re2_re2_cgo.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/re2_wazero.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config_wasm.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/set.go create mode 100644 vendor/github.com/wasilibs/go-re2/internal/wasm/libcre2.wasm create mode 100644 vendor/github.com/wasilibs/go-re2/internal/wasm/memory.wasm create mode 100644 vendor/github.com/wasilibs/go-re2/re2.go create mode 100644 vendor/github.com/wasilibs/wazero-helpers/LICENSE create mode 100644 vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving.go create mode 100644 vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_other.go create mode 100644 vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_slice.go create mode 100644 vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_unix.go create mode 100644 vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_windows.go diff --git a/go.mod b/go.mod index 7052a0aa..d1521ccd 100644 --- a/go.mod +++ b/go.mod @@ -16,14 +16,23 @@ require ( github.com/google/go-github/v68 v68.0.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/kyoh86/richgo v0.3.12 - github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0 + github.com/launchdarkly/ld-find-code-refs/v2 v2.14.0 ) require ( dario.cat/mergo v1.0.1 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/launchdarkly/api-client-go/v17 v17.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect + github.com/olekukonko/ll v0.0.8 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect + github.com/tetratelabs/wazero v1.9.0 // indirect + github.com/wasilibs/go-re2 v1.10.0 // indirect + github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect ) @@ -31,39 +40,39 @@ require ( require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect + github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect - github.com/go-git/go-git/v5 v5.13.0 // indirect + github.com/go-git/go-git/v5 v5.16.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/kyoh86/xdg v1.2.0 // indirect github.com/launchdarkly/api-client-go/v15 v15.1.0 github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/olekukonko/tablewriter v1.0.8 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.7 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/wacul/ptr v1.0.0 // indirect - golang.org/x/crypto v0.35.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect - golang.org/x/tools v0.28.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cbc0638d..ddc96569 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+ github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= -github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= -github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE= +github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -63,13 +63,13 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= -github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= +github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= +github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= +github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -105,8 +105,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -129,8 +129,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= @@ -156,16 +156,19 @@ github.com/kyoh86/xdg v1.2.0 h1:CERuT/ShdTDj+A2UaX3hQ3mOV369+Sj+wyn2nIRIIkI= github.com/kyoh86/xdg v1.2.0/go.mod h1:/mg8zwu1+qe76oTFUBnyS7rJzk7LLC0VGEzJyJ19DHs= github.com/launchdarkly/api-client-go/v15 v15.1.0 h1:SSBqU4x36OWJql7uKuEl6awsPNC3bMFWSiDI/s3OD/I= github.com/launchdarkly/api-client-go/v15 v15.1.0/go.mod h1:7dpsX/epfhhRbCv5sEIxKng0xxYbzRYXlp0oJB3+XrQ= +github.com/launchdarkly/api-client-go/v17 v17.2.0 h1:5CJxDaL7ZgqALAcohNUMlV7hfXR65s2czZ4XmZjW/qI= +github.com/launchdarkly/api-client-go/v17 v17.2.0/go.mod h1:lMTmhEjepXfam8xm8b0ERBJbV9g8vdu9nbKueDXcB5o= github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f h1:jfiPiz2hE/7mHv2NOS4cm07sSJCsKlbxmR7pzPhhvpU= github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f/go.mod h1:CHbYdMs8UjvNnS2fatlQvi4UYnBTRYGxRHc/0kQupSQ= -github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0 h1:9+6tFBKH3YY/QNm6kc/6H75QRNdirT+nITP/9+GSYx4= -github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0/go.mod h1:U+Ji+WaxJN2KYyaXDIkayj3DsypoogiWguw2D/75ohc= +github.com/launchdarkly/ld-find-code-refs/v2 v2.14.0 h1:IVdVxpnvQiaFBriu6V+a1fDooo1Y0cDgm4tibpEW8sQ= +github.com/launchdarkly/ld-find-code-refs/v2 v2.14.0/go.mod h1:AlS+NDM45xG1c0ZZFQWodaub9G5sUojfHXJOzjZW4SU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= @@ -174,14 +177,18 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 h1:r3FaAI0NZK3hSmtTDrBVREhKULp8oUeqLT5Eyl2mSPo= +github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.8 h1:sbGZ1Fx4QxJXEqL/6IG8GEFnYojUSQ45dJVwN2FH2fc= +github.com/olekukonko/ll v0.0.8/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ= +github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -190,9 +197,11 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= @@ -207,8 +216,8 @@ github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -218,8 +227,14 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= github.com/wacul/ptr v1.0.0 h1:FIKu08Wx0YUIf9MNsfF62OCmBSmz5A1Tk65zWhOIL/I= github.com/wacul/ptr v1.0.0/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc= +github.com/wasilibs/go-re2 v1.10.0 h1:vQZEBYZOCA9jdBMmrO4+CvqyCj0x4OomXTJ4a5/urQ0= +github.com/wasilibs/go-re2 v1.10.0/go.mod h1:k+5XqO2bCJS+QpGOnqugyfwC04nw0jaglmjrrkG8U6o= +github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 h1:OvLBa8SqJnZ6P+mjlzc2K7PM22rRUPE1x32G9DTPrC4= +github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52/go.mod h1:jMeV4Vpbi8osrE/pKUxRZkVaA0EX7NZN0A9/oRzgpgY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -237,8 +252,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -336,16 +351,17 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -389,8 +405,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/extinctions/extinctions.go b/internal/extinctions/extinctions.go index a69a8b9c..51f4ce1c 100644 --- a/internal/extinctions/extinctions.go +++ b/internal/extinctions/extinctions.go @@ -22,7 +22,7 @@ func CheckExtinctions(opts options.Options, builder *refs.ReferenceSummaryBuilde } gha.Debug("Searching for any remaining references to %d removed flags...", len(flagKeys)) - references, err := ld_search.SearchForRefs(opts.Dir, matcher) + references, err := ld_search.SearchForRefs(opts.Dir, opts.Subdirectory, matcher) if err != nil { return err } diff --git a/vendor/github.com/bmatcuk/doublestar/v4/README.md b/vendor/github.com/bmatcuk/doublestar/v4/README.md index 21929a95..e4d1941e 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/README.md +++ b/vendor/github.com/bmatcuk/doublestar/v4/README.md @@ -138,6 +138,15 @@ Options that may be passed to `Glob`, `GlobWalk`, or `FilepathGlob`. Any number of options may be passed to these functions, and in any order, as the last argument(s). +```go +WithCaseInsensitive() +``` + +WithCaseInsensitive is an option that can be passed to Glob, GlobWalk, or +FilepathGlob. If passed, doublestar will treat all alphabetic characters as +case insensitive (i.e. "a" in the pattern would match "a" or "A"). This is +useful for platforms like Windows where paths are case insensitive by default. + ```go WithFailOnIOErrors() ``` @@ -319,6 +328,9 @@ If SplitPattern cannot find somewhere to split the pattern (for example, `meta*/**`), it will return "." and the unaltered pattern (`meta*/**` in this example). +Note that SplitPattern will also unescape any meta characters in the returned +base string, so that it can be passed straight to os.DirFS(). + Of course, it is your responsibility to decide if the returned base path is "safe" in the context of your application. Perhaps you could use Match() to validate against a list of approved base directories? @@ -373,8 +385,9 @@ Character classes support the following: Class | Meaning ---------- | ------- -`[abc]` | matches any single character within the set -`[a-z]` | matches any single character in the range +`[abc123]` | matches any single character within the set +`[a-z0-9]` | matches any single character in the range a-z or 0-9 +`[125-79]` | matches any single character within the set 129, or the range 5-7 `[^class]` | matches any single character which does *not* match the class `[!class]` | same as `^`: negates the class @@ -414,8 +427,6 @@ ever since. In that time, it has grown into one of the most popular globbing libraries in the Go ecosystem. So, if **doublestar** is a useful library in your project, consider [sponsoring] my work! I'd really appreciate it! -[![MASV](../sponsors/MASV.png?raw=true)](https://massive.io/) - Thanks for sponsoring me! ## License diff --git a/vendor/github.com/bmatcuk/doublestar/v4/glob.go b/vendor/github.com/bmatcuk/doublestar/v4/glob.go index 519601b1..3471bea7 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/glob.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/glob.go @@ -29,7 +29,6 @@ import ( // // Note: users should _not_ count on the returned error, // doublestar.ErrBadPattern, being equal to path.ErrBadPattern. -// func Glob(fsys fs.FS, pattern string, opts ...GlobOption) ([]string, error) { if !ValidatePattern(pattern) { return nil, ErrBadPattern @@ -107,7 +106,7 @@ func (g *glob) doGlob(fsys fs.FS, pattern string, m []string, firstSegment, befo // characters. They would be equal if they are both -1, which means `dir` // will be ".", and we know that doesn't have meta characters either. if splitIdx <= patternStart { - return g.globDir(fsys, dir, pattern, matches, firstSegment, beforeMeta) + return g.globDir(fsys, unescapeMeta(dir), pattern, matches, firstSegment, beforeMeta) } var dirs []string @@ -226,7 +225,7 @@ func (g *glob) globDir(fsys fs.FS, dir, pattern string, matches []string, canMat var matched bool for _, info := range dirs { name := info.Name() - matched, e = matchWithSeparator(pattern, name, '/', false) + matched, e = matchWithSeparator(pattern, name, '/', false, g.caseInsensitive) if e != nil { return } diff --git a/vendor/github.com/bmatcuk/doublestar/v4/globoptions.go b/vendor/github.com/bmatcuk/doublestar/v4/globoptions.go index 9483c4bb..62983560 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/globoptions.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/globoptions.go @@ -4,6 +4,7 @@ import "strings" // glob is an internal type to store options during globbing. type glob struct { + caseInsensitive bool failOnIOErrors bool failOnPatternNotExist bool filesOnly bool @@ -23,12 +24,21 @@ func newGlob(opts ...GlobOption) *glob { return g } +// WithCaseInsensitive is an option that can be passed to Glob, GlobWalk, or +// FilepathGlob. If passed, doublestar will treat all alphabetic characters as +// case insensitive (i.e. "a" in the pattern would match "a" or "A"). This is +// useful for platforms like Windows where paths are case insensitive by default. +func WithCaseInsensitive() GlobOption { + return func(g *glob) { + g.caseInsensitive = true + } +} + // WithFailOnIOErrors is an option that can be passed to Glob, GlobWalk, or // FilepathGlob. If passed, doublestar will abort and return IO errors when // encountered. Note that if the glob pattern references a path that does not // exist (such as `nonexistent/path/*`), this is _not_ considered an IO error: // it is considered a pattern with no matches. -// func WithFailOnIOErrors() GlobOption { return func(g *glob) { g.failOnIOErrors = true @@ -42,7 +52,6 @@ func WithFailOnIOErrors() GlobOption { // `{...}`) are expanded before this check. In other words, a pattern such as // `{a,b}/*` may fail if either `a` or `b` do not exist but `*/{a,b}` will // never fail because the star may match nothing. -// func WithFailOnPatternNotExist() GlobOption { return func(g *glob) { g.failOnPatternNotExist = true @@ -56,7 +65,6 @@ func WithFailOnPatternNotExist() GlobOption { // Note: if combined with the WithNoFollow option, symlinks to directories // _will_ be included in the result since no attempt is made to follow the // symlink. -// func WithFilesOnly() GlobOption { return func(g *glob) { g.filesOnly = true @@ -76,7 +84,6 @@ func WithFilesOnly() GlobOption { // Note: if combined with the WithFilesOnly option, symlinks to directories // _will_ be included in the result since no attempt is made to follow the // symlink. -// func WithNoFollow() GlobOption { return func(g *glob) { g.noFollow = true @@ -86,7 +93,6 @@ func WithNoFollow() GlobOption { // forwardErrIfFailOnIOErrors is used to wrap the return values of I/O // functions. When failOnIOErrors is enabled, it will return err; otherwise, it // always returns nil. -// func (g *glob) forwardErrIfFailOnIOErrors(err error) error { if g.failOnIOErrors { return err @@ -97,7 +103,6 @@ func (g *glob) forwardErrIfFailOnIOErrors(err error) error { // handleErrNotExist handles fs.ErrNotExist errors. If // WithFailOnPatternNotExist has been enabled and canFail is true, this will // return ErrPatternNotExist. Otherwise, it will return nil. -// func (g *glob) handlePatternNotExist(canFail bool) error { if canFail && g.failOnPatternNotExist { return ErrPatternNotExist @@ -111,7 +116,14 @@ func (g *glob) GoString() string { b.WriteString("opts: ") hasOpts := false + if g.caseInsensitive { + b.WriteString("WithCaseInsensitive") + hasOpts = true + } if g.failOnIOErrors { + if hasOpts { + b.WriteString(", ") + } b.WriteString("WithFailOnIOErrors") hasOpts = true } diff --git a/vendor/github.com/bmatcuk/doublestar/v4/globwalk.go b/vendor/github.com/bmatcuk/doublestar/v4/globwalk.go index 84e764f0..16601b76 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/globwalk.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/globwalk.go @@ -50,7 +50,6 @@ type GlobWalkFunc func(path string, d fs.DirEntry) error // // Note: users should _not_ count on the returned error, // doublestar.ErrBadPattern, being equal to path.ErrBadPattern. -// func GlobWalk(fsys fs.FS, pattern string, fn GlobWalkFunc, opts ...GlobOption) error { if !ValidatePattern(pattern) { return ErrBadPattern @@ -112,7 +111,7 @@ func (g *glob) doGlobWalk(fsys fs.FS, pattern string, firstSegment, beforeMeta b // characters. They would be equal if they are both -1, which means `dir` // will be ".", and we know that doesn't have meta characters either. if splitIdx <= patternStart { - return g.globDirWalk(fsys, dir, pattern, firstSegment, beforeMeta, fn) + return g.globDirWalk(fsys, unescapeMeta(dir), pattern, firstSegment, beforeMeta, fn) } return g.doGlobWalk(fsys, dir, false, beforeMeta, func(p string, d fs.DirEntry) error { @@ -290,7 +289,7 @@ func (g *glob) globDirWalk(fsys fs.FS, dir, pattern string, canMatchFiles, befor var matched bool for _, info := range dirs { name := info.Name() - matched, e = matchWithSeparator(pattern, name, '/', false) + matched, e = matchWithSeparator(pattern, name, '/', false, g.caseInsensitive) if e != nil { return } diff --git a/vendor/github.com/bmatcuk/doublestar/v4/match.go b/vendor/github.com/bmatcuk/doublestar/v4/match.go index c0f20afa..1ff50f61 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/match.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/match.go @@ -2,30 +2,31 @@ package doublestar import ( "path/filepath" + "unicode" "unicode/utf8" ) // Match reports whether name matches the shell pattern. // The pattern syntax is: // -// pattern: -// { term } -// term: -// '*' matches any sequence of non-path-separators -// '/**/' matches zero or more directories -// '?' matches any single non-path-separator character -// '[' [ '^' '!' ] { character-range } ']' -// character class (must be non-empty) -// starting with `^` or `!` negates the class -// '{' { term } [ ',' { term } ... ] '}' -// alternatives -// c matches character c (c != '*', '?', '\\', '[') -// '\\' c matches character c +// pattern: +// { term } +// term: +// '*' matches any sequence of non-path-separators +// '/**/' matches zero or more directories +// '?' matches any single non-path-separator character +// '[' [ '^' '!' ] { character-range } ']' +// character class (must be non-empty) +// starting with `^` or `!` negates the class +// '{' { term } [ ',' { term } ... ] '}' +// alternatives +// c matches character c (c != '*', '?', '\\', '[') +// '\\' c matches character c // -// character-range: -// c matches character c (c != '\\', '-', ']') -// '\\' c matches character c -// lo '-' hi matches character c for lo <= c <= hi +// character-range: +// c matches character c (c != '\\', '-', ']') +// '\\' c matches character c +// lo '-' hi matches character c for lo <= c <= hi // // Match returns true if `name` matches the file name `pattern`. `name` and // `pattern` are split on forward slash (`/`) characters and may be relative or @@ -48,9 +49,8 @@ import ( // // Note: users should _not_ count on the returned error, // doublestar.ErrBadPattern, being equal to path.ErrBadPattern. -// func Match(pattern, name string) (bool, error) { - return matchWithSeparator(pattern, name, '/', true) + return matchWithSeparator(pattern, name, '/', true, false) } // MatchUnvalidated can provide a small performance improvement if you don't @@ -60,7 +60,7 @@ func Match(pattern, name string) (bool, error) { // of `name` before reaching the end of `pattern`, such as `Match("a/b/c", // "a")`. func MatchUnvalidated(pattern, name string) bool { - matched, _ := matchWithSeparator(pattern, name, '/', false) + matched, _ := matchWithSeparator(pattern, name, '/', false, false) return matched } @@ -73,9 +73,8 @@ func MatchUnvalidated(pattern, name string) bool { // assumes that both `pattern` and `name` are using the system's path // separator. If you can't be sure of that, use filepath.ToSlash() on both // `pattern` and `name`, and then use the Match() function instead. -// func PathMatch(pattern, name string) (bool, error) { - return matchWithSeparator(pattern, name, filepath.Separator, true) + return matchWithSeparator(pattern, name, filepath.Separator, true, false) } // PathMatchUnvalidated can provide a small performance improvement if you @@ -85,15 +84,15 @@ func PathMatch(pattern, name string) (bool, error) { // end of `name` before reaching the end of `pattern`, such as `Match("a/b/c", // "a")`. func PathMatchUnvalidated(pattern, name string) bool { - matched, _ := matchWithSeparator(pattern, name, filepath.Separator, false) + matched, _ := matchWithSeparator(pattern, name, filepath.Separator, false, false) return matched } -func matchWithSeparator(pattern, name string, separator rune, validate bool) (matched bool, err error) { - return doMatchWithSeparator(pattern, name, separator, validate, -1, -1, -1, -1, 0, 0) +func matchWithSeparator(pattern, name string, separator rune, validate bool, caseInsensitive bool) (matched bool, err error) { + return doMatchWithSeparator(pattern, name, separator, validate, caseInsensitive, -1, -1, -1, -1, 0, 0) } -func doMatchWithSeparator(pattern, name string, separator rune, validate bool, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, patIdx, nameIdx int) (matched bool, err error) { +func doMatchWithSeparator(pattern, name string, separator rune, validate bool, caseInsensitive bool, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, patIdx, nameIdx int) (matched bool, err error) { patLen := len(pattern) nameLen := len(name) startOfSegment := true @@ -194,7 +193,7 @@ MATCH: } // check if the rune matches - if patRune == nameRune { + if matchRune(patRune, nameRune, caseInsensitive) { matched = true break } @@ -240,14 +239,14 @@ MATCH: } commaIdx += patIdx - result, err := doMatchWithSeparator(pattern[:beforeIdx]+pattern[patIdx:commaIdx]+pattern[closingIdx+1:], name, separator, validate, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, beforeIdx, nameIdx) + result, err := doMatchWithSeparator(pattern[:beforeIdx]+pattern[patIdx:commaIdx]+pattern[closingIdx+1:], name, separator, validate, caseInsensitive, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, beforeIdx, nameIdx) if result || err != nil { return result, err } patIdx = commaIdx + 1 } - return doMatchWithSeparator(pattern[:beforeIdx]+pattern[patIdx:closingIdx]+pattern[closingIdx+1:], name, separator, validate, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, beforeIdx, nameIdx) + return doMatchWithSeparator(pattern[:beforeIdx]+pattern[patIdx:closingIdx]+pattern[closingIdx+1:], name, separator, validate, caseInsensitive, doublestarPatternBacktrack, doublestarNameBacktrack, starPatternBacktrack, starNameBacktrack, beforeIdx, nameIdx) case '\\': if separator != '\\' { @@ -262,7 +261,7 @@ MATCH: default: patRune, patRuneLen := utf8.DecodeRuneInString(pattern[patIdx:]) nameRune, nameRuneLen := utf8.DecodeRuneInString(name[nameIdx:]) - if patRune != nameRune { + if !matchRune(patRune, nameRune, caseInsensitive) { if separator != '\\' && patIdx > 0 && pattern[patIdx-1] == '\\' { // if this rune was meant to be escaped, we need to move patIdx // back to the backslash before backtracking or validating below @@ -311,27 +310,44 @@ MATCH: return false, nil } - if nameIdx < nameLen { - // we reached the end of `pattern` before the end of `name` - return false, nil - } - // we've reached the end of `name`; we've successfully matched if we've also // reached the end of `pattern`, or if the rest of `pattern` can match a // zero-length string - return isZeroLengthPattern(pattern[patIdx:], separator) + return isZeroLengthPattern(pattern[patIdx:], separator, validate) +} + +func matchRune(a, b rune, caseInsensitive bool) bool { + if caseInsensitive { + return unicode.ToLower(a) == unicode.ToLower(b) + } + return a == b } -func isZeroLengthPattern(pattern string, separator rune) (ret bool, err error) { +func isZeroLengthPattern(pattern string, separator rune, validate bool) (ret bool, err error) { // `/**`, `**/`, and `/**/` are special cases - a pattern such as `path/to/a/**` or `path/to/a/**/` - // *should* match `path/to/a` because `a` might be a directory - if pattern == "" || - pattern == "*" || - pattern == "**" || - pattern == string(separator)+"**" || - pattern == "**"+string(separator) || - pattern == string(separator)+"**"+string(separator) { + // *should* match `path/to/a` because `a` might be a directory. + // This code is optimized to avoid string concatenation, giving a little performance bump. + switch len(pattern) { + case 0: return true, nil + case 1: + if pattern == "*" { + return true, nil + } + case 2: + if pattern == "**" { + return true, nil + } + case 3: + if pattern[1:] == "**" && rune(pattern[0]) == separator { + return true, nil + } else if pattern[:2] == "**" && rune(pattern[2]) == separator { + return true, nil + } + case 4: + if pattern[1:3] == "**" && rune(pattern[0]) == separator && rune(pattern[3]) == separator { + return true, nil + } } if pattern[0] == '{' { @@ -350,18 +366,18 @@ func isZeroLengthPattern(pattern string, separator rune) (ret bool, err error) { } commaIdx += patIdx - ret, err = isZeroLengthPattern(pattern[patIdx:commaIdx]+pattern[closingIdx+1:], separator) + ret, err = isZeroLengthPattern(pattern[patIdx:commaIdx]+pattern[closingIdx+1:], separator, validate) if ret || err != nil { return } patIdx = commaIdx + 1 } - return isZeroLengthPattern(pattern[patIdx:closingIdx]+pattern[closingIdx+1:], separator) + return isZeroLengthPattern(pattern[patIdx:closingIdx]+pattern[closingIdx+1:], separator, validate) } // no luck - validate the rest of the pattern - if !doValidatePattern(pattern, separator) { + if validate && !doValidatePattern(pattern, separator) { return false, ErrBadPattern } return false, nil diff --git a/vendor/github.com/bmatcuk/doublestar/v4/utils.go b/vendor/github.com/bmatcuk/doublestar/v4/utils.go index 6b8df9a3..7831e5c3 100644 --- a/vendor/github.com/bmatcuk/doublestar/v4/utils.go +++ b/vendor/github.com/bmatcuk/doublestar/v4/utils.go @@ -29,6 +29,9 @@ import ( // `meta*/**`), it will return "." and the unaltered pattern (`meta*/**` in // this example). // +// Note that SplitPattern will also unescape any meta characters in the +// returned base string, so that it can be passed straight to os.DirFS(). +// // Of course, it is your responsibility to decide if the returned base path is // "safe" in the context of your application. Perhaps you could use Match() to // validate against a list of approved base directories? @@ -52,7 +55,7 @@ func SplitPattern(p string) (base, pattern string) { if splitIdx == 0 { return "/", p[1:] } else if splitIdx > 0 { - return p[:splitIdx], p[splitIdx+1:] + return unescapeMeta(p[:splitIdx]), p[splitIdx+1:] } return diff --git a/vendor/github.com/fatih/color/LICENSE.md b/vendor/github.com/fatih/color/LICENSE.md new file mode 100644 index 00000000..25fdaf63 --- /dev/null +++ b/vendor/github.com/fatih/color/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Fatih Arslan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md new file mode 100644 index 00000000..be82827c --- /dev/null +++ b/vendor/github.com/fatih/color/README.md @@ -0,0 +1,176 @@ +# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color) + +Color lets you use colorized outputs in terms of [ANSI Escape +Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It +has support for Windows too! The API can be used in several ways, pick one that +suits you. + +![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg) + +## Install + +```bash +go get github.com/fatih/color +``` + +## Examples + +### Standard colors + +```go +// Print with default helper functions +color.Cyan("Prints text in cyan.") + +// A newline will be appended automatically +color.Blue("Prints %s in blue.", "text") + +// These are using the default foreground colors +color.Red("We have red") +color.Magenta("And many others ..") + +``` + +### Mix and reuse colors + +```go +// Create a new color object +c := color.New(color.FgCyan).Add(color.Underline) +c.Println("Prints cyan text with an underline.") + +// Or just add them to New() +d := color.New(color.FgCyan, color.Bold) +d.Printf("This prints bold cyan %s\n", "too!.") + +// Mix up foreground and background colors, create new mixes! +red := color.New(color.FgRed) + +boldRed := red.Add(color.Bold) +boldRed.Println("This will print text in bold red.") + +whiteBackground := red.Add(color.BgWhite) +whiteBackground.Println("Red text with white background.") +``` + +### Use your own output (io.Writer) + +```go +// Use your own io.Writer output +color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + +blue := color.New(color.FgBlue) +blue.Fprint(writer, "This will print text in blue.") +``` + +### Custom print functions (PrintFunc) + +```go +// Create a custom print function for convenience +red := color.New(color.FgRed).PrintfFunc() +red("Warning") +red("Error: %s", err) + +// Mix up multiple attributes +notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() +notice("Don't forget this...") +``` + +### Custom fprint functions (FprintFunc) + +```go +blue := color.New(color.FgBlue).FprintfFunc() +blue(myWriter, "important notice: %s", stars) + +// Mix up with multiple attributes +success := color.New(color.Bold, color.FgGreen).FprintlnFunc() +success(myWriter, "Don't forget this...") +``` + +### Insert into noncolor strings (SprintFunc) + +```go +// Create SprintXxx functions to mix strings with other non-colorized strings: +yellow := color.New(color.FgYellow).SprintFunc() +red := color.New(color.FgRed).SprintFunc() +fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) + +info := color.New(color.FgWhite, color.BgGreen).SprintFunc() +fmt.Printf("This %s rocks!\n", info("package")) + +// Use helper functions +fmt.Println("This", color.RedString("warning"), "should be not neglected.") +fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") + +// Windows supported too! Just don't forget to change the output to color.Output +fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) +``` + +### Plug into existing code + +```go +// Use handy standard colors +color.Set(color.FgYellow) + +fmt.Println("Existing text will now be in yellow") +fmt.Printf("This one %s\n", "too") + +color.Unset() // Don't forget to unset + +// You can mix up parameters +color.Set(color.FgMagenta, color.Bold) +defer color.Unset() // Use it in your function + +fmt.Println("All text will now be bold magenta.") +``` + +### Disable/Enable color + +There might be a case where you want to explicitly disable/enable color output. the +`go-isatty` package will automatically disable color output for non-tty output streams +(for example if the output were piped directly to `less`). + +The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment +variable is set to a non-empty string. + +`Color` has support to disable/enable colors programmatically both globally and +for single color definitions. For example suppose you have a CLI app and a +`-no-color` bool flag. You can easily disable the color output with: + +```go +var flagNoColor = flag.Bool("no-color", false, "Disable color output") + +if *flagNoColor { + color.NoColor = true // disables colorized output +} +``` + +It also has support for single color definitions (local). You can +disable/enable color output on the fly: + +```go +c := color.New(color.FgCyan) +c.Println("Prints cyan text") + +c.DisableColor() +c.Println("This is printed without any color") + +c.EnableColor() +c.Println("This prints again cyan...") +``` + +## GitHub Actions + +To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. + +## Todo + +* Save/Return previous values +* Evaluate fmt.Formatter interface + +## Credits + +* [Fatih Arslan](https://github.com/fatih) +* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable) + +## License + +The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go new file mode 100644 index 00000000..c4234287 --- /dev/null +++ b/vendor/github.com/fatih/color/color.go @@ -0,0 +1,650 @@ +package color + +import ( + "fmt" + "io" + "os" + "strconv" + "strings" + "sync" + + "github.com/mattn/go-colorable" + "github.com/mattn/go-isatty" +) + +var ( + // NoColor defines if the output is colorized or not. It's dynamically set to + // false or true based on the stdout's file descriptor referring to a terminal + // or not. It's also set to true if the NO_COLOR environment variable is + // set (regardless of its value). This is a global option and affects all + // colors. For more control over each color block use the methods + // DisableColor() individually. + NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" || + (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) + + // Output defines the standard output of the print functions. By default, + // os.Stdout is used. + Output = colorable.NewColorableStdout() + + // Error defines a color supporting writer for os.Stderr. + Error = colorable.NewColorableStderr() + + // colorsCache is used to reduce the count of created Color objects and + // allows to reuse already created objects with required Attribute. + colorsCache = make(map[Attribute]*Color) + colorsCacheMu sync.Mutex // protects colorsCache +) + +// noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string. +func noColorIsSet() bool { + return os.Getenv("NO_COLOR") != "" +} + +// Color defines a custom color object which is defined by SGR parameters. +type Color struct { + params []Attribute + noColor *bool +} + +// Attribute defines a single SGR Code +type Attribute int + +const escape = "\x1b" + +// Base attributes +const ( + Reset Attribute = iota + Bold + Faint + Italic + Underline + BlinkSlow + BlinkRapid + ReverseVideo + Concealed + CrossedOut +) + +const ( + ResetBold Attribute = iota + 22 + ResetItalic + ResetUnderline + ResetBlinking + _ + ResetReversed + ResetConcealed + ResetCrossedOut +) + +var mapResetAttributes map[Attribute]Attribute = map[Attribute]Attribute{ + Bold: ResetBold, + Faint: ResetBold, + Italic: ResetItalic, + Underline: ResetUnderline, + BlinkSlow: ResetBlinking, + BlinkRapid: ResetBlinking, + ReverseVideo: ResetReversed, + Concealed: ResetConcealed, + CrossedOut: ResetCrossedOut, +} + +// Foreground text colors +const ( + FgBlack Attribute = iota + 30 + FgRed + FgGreen + FgYellow + FgBlue + FgMagenta + FgCyan + FgWhite +) + +// Foreground Hi-Intensity text colors +const ( + FgHiBlack Attribute = iota + 90 + FgHiRed + FgHiGreen + FgHiYellow + FgHiBlue + FgHiMagenta + FgHiCyan + FgHiWhite +) + +// Background text colors +const ( + BgBlack Attribute = iota + 40 + BgRed + BgGreen + BgYellow + BgBlue + BgMagenta + BgCyan + BgWhite +) + +// Background Hi-Intensity text colors +const ( + BgHiBlack Attribute = iota + 100 + BgHiRed + BgHiGreen + BgHiYellow + BgHiBlue + BgHiMagenta + BgHiCyan + BgHiWhite +) + +// New returns a newly created color object. +func New(value ...Attribute) *Color { + c := &Color{ + params: make([]Attribute, 0), + } + + if noColorIsSet() { + c.noColor = boolPtr(true) + } + + c.Add(value...) + return c +} + +// Set sets the given parameters immediately. It will change the color of +// output with the given SGR parameters until color.Unset() is called. +func Set(p ...Attribute) *Color { + c := New(p...) + c.Set() + return c +} + +// Unset resets all escape attributes and clears the output. Usually should +// be called after Set(). +func Unset() { + if NoColor { + return + } + + fmt.Fprintf(Output, "%s[%dm", escape, Reset) +} + +// Set sets the SGR sequence. +func (c *Color) Set() *Color { + if c.isNoColorSet() { + return c + } + + fmt.Fprint(Output, c.format()) + return c +} + +func (c *Color) unset() { + if c.isNoColorSet() { + return + } + + Unset() +} + +// SetWriter is used to set the SGR sequence with the given io.Writer. This is +// a low-level function, and users should use the higher-level functions, such +// as color.Fprint, color.Print, etc. +func (c *Color) SetWriter(w io.Writer) *Color { + if c.isNoColorSet() { + return c + } + + fmt.Fprint(w, c.format()) + return c +} + +// UnsetWriter resets all escape attributes and clears the output with the give +// io.Writer. Usually should be called after SetWriter(). +func (c *Color) UnsetWriter(w io.Writer) { + if c.isNoColorSet() { + return + } + + if NoColor { + return + } + + fmt.Fprintf(w, "%s[%dm", escape, Reset) +} + +// Add is used to chain SGR parameters. Use as many as parameters to combine +// and create custom color objects. Example: Add(color.FgRed, color.Underline). +func (c *Color) Add(value ...Attribute) *Color { + c.params = append(c.params, value...) + return c +} + +// Fprint formats using the default formats for its operands and writes to w. +// Spaces are added between operands when neither is a string. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + c.SetWriter(w) + defer c.UnsetWriter(w) + + return fmt.Fprint(w, a...) +} + +// Print formats using the default formats for its operands and writes to +// standard output. Spaces are added between operands when neither is a +// string. It returns the number of bytes written and any write error +// encountered. This is the standard fmt.Print() method wrapped with the given +// color. +func (c *Color) Print(a ...interface{}) (n int, err error) { + c.Set() + defer c.unset() + + return fmt.Fprint(Output, a...) +} + +// Fprintf formats according to a format specifier and writes to w. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + c.SetWriter(w) + defer c.UnsetWriter(w) + + return fmt.Fprintf(w, format, a...) +} + +// Printf formats according to a format specifier and writes to standard output. +// It returns the number of bytes written and any write error encountered. +// This is the standard fmt.Printf() method wrapped with the given color. +func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { + c.Set() + defer c.unset() + + return fmt.Fprintf(Output, format, a...) +} + +// Fprintln formats using the default formats for its operands and writes to w. +// Spaces are always added between operands and a newline is appended. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.wrap(fmt.Sprint(a...))) +} + +// Println formats using the default formats for its operands and writes to +// standard output. Spaces are always added between operands and a newline is +// appended. It returns the number of bytes written and any write error +// encountered. This is the standard fmt.Print() method wrapped with the given +// color. +func (c *Color) Println(a ...interface{}) (n int, err error) { + return fmt.Fprintln(Output, c.wrap(fmt.Sprint(a...))) +} + +// Sprint is just like Print, but returns a string instead of printing it. +func (c *Color) Sprint(a ...interface{}) string { + return c.wrap(fmt.Sprint(a...)) +} + +// Sprintln is just like Println, but returns a string instead of printing it. +func (c *Color) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.Sprint(a...)) +} + +// Sprintf is just like Printf, but returns a string instead of printing it. +func (c *Color) Sprintf(format string, a ...interface{}) string { + return c.wrap(fmt.Sprintf(format, a...)) +} + +// FprintFunc returns a new function that prints the passed arguments as +// colorized with color.Fprint(). +func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprint(w, a...) + } +} + +// PrintFunc returns a new function that prints the passed arguments as +// colorized with color.Print(). +func (c *Color) PrintFunc() func(a ...interface{}) { + return func(a ...interface{}) { + c.Print(a...) + } +} + +// FprintfFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintf(). +func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) { + return func(w io.Writer, format string, a ...interface{}) { + c.Fprintf(w, format, a...) + } +} + +// PrintfFunc returns a new function that prints the passed arguments as +// colorized with color.Printf(). +func (c *Color) PrintfFunc() func(format string, a ...interface{}) { + return func(format string, a ...interface{}) { + c.Printf(format, a...) + } +} + +// FprintlnFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintln(). +func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprintln(w, a...) + } +} + +// PrintlnFunc returns a new function that prints the passed arguments as +// colorized with color.Println(). +func (c *Color) PrintlnFunc() func(a ...interface{}) { + return func(a ...interface{}) { + c.Println(a...) + } +} + +// SprintFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprint(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output, example: +// +// put := New(FgYellow).SprintFunc() +// fmt.Fprintf(color.Output, "This is a %s", put("warning")) +func (c *Color) SprintFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return c.wrap(fmt.Sprint(a...)) + } +} + +// SprintfFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprintf(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output. +func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { + return func(format string, a ...interface{}) string { + return c.wrap(fmt.Sprintf(format, a...)) + } +} + +// SprintlnFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprintln(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output. +func (c *Color) SprintlnFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return fmt.Sprintln(c.Sprint(a...)) + } +} + +// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m" +// an example output might be: "1;36" -> bold cyan +func (c *Color) sequence() string { + format := make([]string, len(c.params)) + for i, v := range c.params { + format[i] = strconv.Itoa(int(v)) + } + + return strings.Join(format, ";") +} + +// wrap wraps the s string with the colors attributes. The string is ready to +// be printed. +func (c *Color) wrap(s string) string { + if c.isNoColorSet() { + return s + } + + return c.format() + s + c.unformat() +} + +func (c *Color) format() string { + return fmt.Sprintf("%s[%sm", escape, c.sequence()) +} + +func (c *Color) unformat() string { + //return fmt.Sprintf("%s[%dm", escape, Reset) + //for each element in sequence let's use the speficic reset escape, ou the generic one if not found + format := make([]string, len(c.params)) + for i, v := range c.params { + format[i] = strconv.Itoa(int(Reset)) + ra, ok := mapResetAttributes[v] + if ok { + format[i] = strconv.Itoa(int(ra)) + } + } + + return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";")) +} + +// DisableColor disables the color output. Useful to not change any existing +// code and still being able to output. Can be used for flags like +// "--no-color". To enable back use EnableColor() method. +func (c *Color) DisableColor() { + c.noColor = boolPtr(true) +} + +// EnableColor enables the color output. Use it in conjunction with +// DisableColor(). Otherwise, this method has no side effects. +func (c *Color) EnableColor() { + c.noColor = boolPtr(false) +} + +func (c *Color) isNoColorSet() bool { + // check first if we have user set action + if c.noColor != nil { + return *c.noColor + } + + // if not return the global option, which is disabled by default + return NoColor +} + +// Equals returns a boolean value indicating whether two colors are equal. +func (c *Color) Equals(c2 *Color) bool { + if c == nil && c2 == nil { + return true + } + if c == nil || c2 == nil { + return false + } + if len(c.params) != len(c2.params) { + return false + } + + for _, attr := range c.params { + if !c2.attrExists(attr) { + return false + } + } + + return true +} + +func (c *Color) attrExists(a Attribute) bool { + for _, attr := range c.params { + if attr == a { + return true + } + } + + return false +} + +func boolPtr(v bool) *bool { + return &v +} + +func getCachedColor(p Attribute) *Color { + colorsCacheMu.Lock() + defer colorsCacheMu.Unlock() + + c, ok := colorsCache[p] + if !ok { + c = New(p) + colorsCache[p] = c + } + + return c +} + +func colorPrint(format string, p Attribute, a ...interface{}) { + c := getCachedColor(p) + + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + + if len(a) == 0 { + c.Print(format) + } else { + c.Printf(format, a...) + } +} + +func colorString(format string, p Attribute, a ...interface{}) string { + c := getCachedColor(p) + + if len(a) == 0 { + return c.SprintFunc()(format) + } + + return c.SprintfFunc()(format, a...) +} + +// Black is a convenient helper function to print with black foreground. A +// newline is appended to format by default. +func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) } + +// Red is a convenient helper function to print with red foreground. A +// newline is appended to format by default. +func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) } + +// Green is a convenient helper function to print with green foreground. A +// newline is appended to format by default. +func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) } + +// Yellow is a convenient helper function to print with yellow foreground. +// A newline is appended to format by default. +func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) } + +// Blue is a convenient helper function to print with blue foreground. A +// newline is appended to format by default. +func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) } + +// Magenta is a convenient helper function to print with magenta foreground. +// A newline is appended to format by default. +func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) } + +// Cyan is a convenient helper function to print with cyan foreground. A +// newline is appended to format by default. +func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) } + +// White is a convenient helper function to print with white foreground. A +// newline is appended to format by default. +func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) } + +// BlackString is a convenient helper function to return a string with black +// foreground. +func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } + +// RedString is a convenient helper function to return a string with red +// foreground. +func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } + +// GreenString is a convenient helper function to return a string with green +// foreground. +func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } + +// YellowString is a convenient helper function to return a string with yellow +// foreground. +func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } + +// BlueString is a convenient helper function to return a string with blue +// foreground. +func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } + +// MagentaString is a convenient helper function to return a string with magenta +// foreground. +func MagentaString(format string, a ...interface{}) string { + return colorString(format, FgMagenta, a...) +} + +// CyanString is a convenient helper function to return a string with cyan +// foreground. +func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } + +// WhiteString is a convenient helper function to return a string with white +// foreground. +func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } + +// HiBlack is a convenient helper function to print with hi-intensity black foreground. A +// newline is appended to format by default. +func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) } + +// HiRed is a convenient helper function to print with hi-intensity red foreground. A +// newline is appended to format by default. +func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) } + +// HiGreen is a convenient helper function to print with hi-intensity green foreground. A +// newline is appended to format by default. +func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) } + +// HiYellow is a convenient helper function to print with hi-intensity yellow foreground. +// A newline is appended to format by default. +func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) } + +// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A +// newline is appended to format by default. +func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) } + +// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground. +// A newline is appended to format by default. +func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) } + +// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A +// newline is appended to format by default. +func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) } + +// HiWhite is a convenient helper function to print with hi-intensity white foreground. A +// newline is appended to format by default. +func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) } + +// HiBlackString is a convenient helper function to return a string with hi-intensity black +// foreground. +func HiBlackString(format string, a ...interface{}) string { + return colorString(format, FgHiBlack, a...) +} + +// HiRedString is a convenient helper function to return a string with hi-intensity red +// foreground. +func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) } + +// HiGreenString is a convenient helper function to return a string with hi-intensity green +// foreground. +func HiGreenString(format string, a ...interface{}) string { + return colorString(format, FgHiGreen, a...) +} + +// HiYellowString is a convenient helper function to return a string with hi-intensity yellow +// foreground. +func HiYellowString(format string, a ...interface{}) string { + return colorString(format, FgHiYellow, a...) +} + +// HiBlueString is a convenient helper function to return a string with hi-intensity blue +// foreground. +func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) } + +// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta +// foreground. +func HiMagentaString(format string, a ...interface{}) string { + return colorString(format, FgHiMagenta, a...) +} + +// HiCyanString is a convenient helper function to return a string with hi-intensity cyan +// foreground. +func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) } + +// HiWhiteString is a convenient helper function to return a string with hi-intensity white +// foreground. +func HiWhiteString(format string, a ...interface{}) string { + return colorString(format, FgHiWhite, a...) +} diff --git a/vendor/github.com/fatih/color/color_windows.go b/vendor/github.com/fatih/color/color_windows.go new file mode 100644 index 00000000..be01c558 --- /dev/null +++ b/vendor/github.com/fatih/color/color_windows.go @@ -0,0 +1,19 @@ +package color + +import ( + "os" + + "golang.org/x/sys/windows" +) + +func init() { + // Opt-in for ansi color support for current process. + // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#output-sequences + var outMode uint32 + out := windows.Handle(os.Stdout.Fd()) + if err := windows.GetConsoleMode(out, &outMode); err != nil { + return + } + outMode |= windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING + _ = windows.SetConsoleMode(out, outMode) +} diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go new file mode 100644 index 00000000..9491ad54 --- /dev/null +++ b/vendor/github.com/fatih/color/doc.go @@ -0,0 +1,134 @@ +/* +Package color is an ANSI color package to output colorized or SGR defined +output to the standard output. The API can be used in several way, pick one +that suits you. + +Use simple and default helper functions with predefined foreground colors: + + color.Cyan("Prints text in cyan.") + + // a newline will be appended automatically + color.Blue("Prints %s in blue.", "text") + + // More default foreground colors.. + color.Red("We have red") + color.Yellow("Yellow color too!") + color.Magenta("And many others ..") + + // Hi-intensity colors + color.HiGreen("Bright green color.") + color.HiBlack("Bright black means gray..") + color.HiWhite("Shiny white color!") + +However, there are times when custom color mixes are required. Below are some +examples to create custom color objects and use the print functions of each +separate color object. + + // Create a new color object + c := color.New(color.FgCyan).Add(color.Underline) + c.Println("Prints cyan text with an underline.") + + // Or just add them to New() + d := color.New(color.FgCyan, color.Bold) + d.Printf("This prints bold cyan %s\n", "too!.") + + + // Mix up foreground and background colors, create new mixes! + red := color.New(color.FgRed) + + boldRed := red.Add(color.Bold) + boldRed.Println("This will print text in bold red.") + + whiteBackground := red.Add(color.BgWhite) + whiteBackground.Println("Red text with White background.") + + // Use your own io.Writer output + color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + + blue := color.New(color.FgBlue) + blue.Fprint(myWriter, "This will print text in blue.") + +You can create PrintXxx functions to simplify even more: + + // Create a custom print function for convenient + red := color.New(color.FgRed).PrintfFunc() + red("warning") + red("error: %s", err) + + // Mix up multiple attributes + notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() + notice("don't forget this...") + +You can also FprintXxx functions to pass your own io.Writer: + + blue := color.New(FgBlue).FprintfFunc() + blue(myWriter, "important notice: %s", stars) + + // Mix up with multiple attributes + success := color.New(color.Bold, color.FgGreen).FprintlnFunc() + success(myWriter, don't forget this...") + +Or create SprintXxx functions to mix strings with other non-colorized strings: + + yellow := New(FgYellow).SprintFunc() + red := New(FgRed).SprintFunc() + + fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error")) + + info := New(FgWhite, BgGreen).SprintFunc() + fmt.Printf("this %s rocks!\n", info("package")) + +Windows support is enabled by default. All Print functions work as intended. +However, only for color.SprintXXX functions, user should use fmt.FprintXXX and +set the output to color.Output: + + fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) + + info := New(FgWhite, BgGreen).SprintFunc() + fmt.Fprintf(color.Output, "this %s rocks!\n", info("package")) + +Using with existing code is possible. Just use the Set() method to set the +standard output to the given parameters. That way a rewrite of an existing +code is not required. + + // Use handy standard colors. + color.Set(color.FgYellow) + + fmt.Println("Existing text will be now in Yellow") + fmt.Printf("This one %s\n", "too") + + color.Unset() // don't forget to unset + + // You can mix up parameters + color.Set(color.FgMagenta, color.Bold) + defer color.Unset() // use it in your function + + fmt.Println("All text will be now bold magenta.") + +There might be a case where you want to disable color output (for example to +pipe the standard output of your app to somewhere else). `Color` has support to +disable colors both globally and for single color definition. For example +suppose you have a CLI app and a `--no-color` bool flag. You can easily disable +the color output with: + + var flagNoColor = flag.Bool("no-color", false, "Disable color output") + + if *flagNoColor { + color.NoColor = true // disables colorized output + } + +You can also disable the color by setting the NO_COLOR environment variable to any value. + +It also has support for single color definitions (local). You can +disable/enable color output on the fly: + + c := color.New(color.FgCyan) + c.Println("Prints cyan text") + + c.DisableColor() + c.Println("This is printed without any color") + + c.EnableColor() + c.Println("This prints again cyan...") +*/ +package color diff --git a/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig index 1f664d13..faef0c91 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/.editorconfig +++ b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig @@ -16,3 +16,6 @@ indent_style = tab [*.nix] indent_size = 2 + +[.golangci.yaml] +indent_size = 2 diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml index 763143aa..ec1680b3 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml +++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -1,23 +1,39 @@ -run: - timeout: 5m +version: "2" -linters-settings: - gci: - sections: - - standard - - default - - prefix(github.com/go-viper/mapstructure) - golint: - min-confidence: 0 - goimports: - local-prefixes: github.com/go-viper/maptstructure +run: + timeout: 10m linters: - disable-all: true + enable: + - govet + - ineffassign + # - misspell + - nolintlint + # - revive + + disable: + - errcheck + - staticcheck + - unused + + settings: + misspell: + locale: US + nolintlint: + allow-unused: false # report any unused nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + +formatters: enable: - gci - gofmt - gofumpt - goimports - - staticcheck - # - stylecheck + # - golines + + settings: + gci: + sections: + - standard + - default + - localmodule diff --git a/vendor/github.com/go-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md index dd5ec69d..bc4be08e 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/README.md +++ b/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -1,8 +1,9 @@ # mapstructure -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml) +[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2) mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. @@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else. Here is a script that can help you with the migration: ```shell -sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go') ``` If you need more time to migrate your code, that is absolutely fine. diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go index 1f3c69d4..57c6de69 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { if err != nil { return nil, err } - newFrom = reflect.ValueOf(data) + if v, ok := data.(reflect.Value); ok { + newFrom = v + } else { + newFrom = reflect.ValueOf(data) + } } return data, nil @@ -386,6 +390,26 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { } } +// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts +// strings to netip.Prefix. +func StringToNetIPPrefixHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.Prefix{}) { + return data, nil + } + + // Convert it by parsing + return netip.ParsePrefix(data.(string)) + } +} + // StringToBasicTypeHookFunc returns a DecodeHookFunc that converts // strings to basic types. // int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, float32, float64, bool, byte, rune, complex64, complex128 diff --git a/vendor/github.com/go-viper/mapstructure/v2/errors.go b/vendor/github.com/go-viper/mapstructure/v2/errors.go new file mode 100644 index 00000000..31a3edfb --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/errors.go @@ -0,0 +1,74 @@ +package mapstructure + +import ( + "fmt" + "reflect" +) + +// Error interface is implemented by all errors emitted by mapstructure. +// +// Use [errors.As] to check if an error implements this interface. +type Error interface { + error + + mapstructure() +} + +// DecodeError is a generic error type that holds information about +// a decoding error together with the name of the field that caused the error. +type DecodeError struct { + name string + err error +} + +func newDecodeError(name string, err error) *DecodeError { + return &DecodeError{ + name: name, + err: err, + } +} + +func (e *DecodeError) Name() string { + return e.name +} + +func (e *DecodeError) Unwrap() error { + return e.err +} + +func (e *DecodeError) Error() string { + return fmt.Sprintf("'%s' %s", e.name, e.err) +} + +func (*DecodeError) mapstructure() {} + +// ParseError is an error type that indicates a value could not be parsed +// into the expected type. +type ParseError struct { + Expected reflect.Value + Value any + Err error +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err) +} + +func (*ParseError) mapstructure() {} + +// UnconvertibleTypeError is an error type that indicates a value could not be +// converted to the expected type. +type UnconvertibleTypeError struct { + Expected reflect.Value + Value any +} + +func (e *UnconvertibleTypeError) Error() string { + return fmt.Sprintf( + "expected type '%s', got unconvertible type '%s'", + e.Expected.Type(), + reflect.TypeOf(e.Value), + ) +} + +func (*UnconvertibleTypeError) mapstructure() {} diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/vendor/github.com/go-viper/mapstructure/v2/flake.lock index 4bea8154..5e67bdd6 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/flake.lock +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.lock @@ -2,30 +2,28 @@ "nodes": { "cachix": { "inputs": { - "devenv": "devenv_2", + "devenv": [ + "devenv" + ], "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "git-hooks": [ + "devenv" ], - "pre-commit-hooks": [ - "devenv", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1712055811, - "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "lastModified": 1742042642, + "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=", "owner": "cachix", "repo": "cachix", - "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203", "type": "github" }, "original": { "owner": "cachix", + "ref": "latest", "repo": "cachix", "type": "github" } @@ -33,52 +31,21 @@ "devenv": { "inputs": { "cachix": "cachix", - "flake-compat": "flake-compat_2", - "nix": "nix_2", - "nixpkgs": "nixpkgs_2", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1717245169, - "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", - "owner": "cachix", - "repo": "devenv", - "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "devenv_2": { - "inputs": { - "flake-compat": [ - "devenv", - "cachix", - "flake-compat" - ], + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", "nix": "nix", - "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix", - "pre-commit-hooks": [ - "devenv", - "cachix", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1708704632, - "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "lastModified": 1744876578, + "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=", "owner": "cachix", "repo": "devenv", - "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1", "type": "github" }, "original": { "owner": "cachix", - "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -86,27 +53,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -117,14 +68,18 @@ }, "flake-parts": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "type": "github" }, "original": { @@ -133,39 +88,46 @@ "type": "github" } }, - "flake-utils": { + "flake-parts_2": { "inputs": { - "systems": "systems" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "flake-utils_2": { + "git-hooks": { "inputs": { - "systems": "systems_2" + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "cachix", + "repo": "git-hooks.nix", "type": "github" } }, @@ -173,7 +135,7 @@ "inputs": { "nixpkgs": [ "devenv", - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -191,166 +153,109 @@ "type": "github" } }, - "nix": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", - "owner": "domenkozar", - "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "devenv-2.21", - "repo": "nix", - "type": "github" - } - }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "poetry2nix", - "nixpkgs" - ] - }, + "libgit2": { + "flake": false, "locked": { - "lastModified": 1688870561, - "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nix-github-actions", + "owner": "libgit2", + "repo": "libgit2", "type": "github" } }, - "nix_2": { + "nix": { "inputs": { "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" ], - "nixpkgs-regression": "nixpkgs-regression_2" + "pre-commit-hooks": [ + "devenv" + ] }, "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "lastModified": 1741798497, + "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=", "owner": "domenkozar", "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "devenv-2.21", + "ref": "devenv-2.24", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1692808169, - "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-lib": { "locked": { - "lastModified": 1717284937, - "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-regression_2": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", "type": "github" }, "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs_2": { "locked": { - "lastModified": 1710695816, - "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "release-24.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_3": { "locked": { - "lastModified": 1713361204, - "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "lastModified": 1733477122, + "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=", "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", "type": "github" }, "original": { @@ -360,13 +265,13 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { - "lastModified": 1717112898, - "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", "type": "github" }, "original": { @@ -376,94 +281,11 @@ "type": "github" } }, - "poetry2nix": { - "inputs": { - "flake-utils": "flake-utils", - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1692876271, - "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils_2", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1713775815, - "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_3" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4" } } }, diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/vendor/github.com/go-viper/mapstructure/v2/flake.nix index 4ed0f533..3b116f42 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/flake.nix +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.nix @@ -5,35 +5,42 @@ devenv.url = "github:cachix/devenv"; }; - outputs = inputs@{ flake-parts, ... }: + outputs = + inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { imports = [ inputs.devenv.flakeModule ]; - systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; + systems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; - perSystem = { config, self', inputs', pkgs, system, ... }: rec { - devenv.shells = { - default = { - languages = { - go.enable = true; - }; + perSystem = + { pkgs, ... }: + rec { + devenv.shells = { + default = { + languages = { + go.enable = true; + }; - pre-commit.hooks = { - nixpkgs-fmt.enable = true; - }; + pre-commit.hooks = { + nixpkgs-fmt.enable = true; + }; - packages = with pkgs; [ - golangci-lint - ]; + packages = with pkgs; [ + golangci-lint + ]; - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; + # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 + containers = pkgs.lib.mkForce { }; + }; - ci = devenv.shells.default; + ci = devenv.shells.default; + }; }; - }; }; } diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index e77e63ba..4b738a3a 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -115,15 +115,36 @@ // // When decoding from a struct to any other value, you may use the // ",omitempty" suffix on your tag to omit that value if it equates to -// the zero value. The zero value of all types is specified in the Go -// specification. +// the zero value, or a zero-length element. The zero value of all types is +// specified in the Go specification. // // For example, the zero type of a numeric type is zero ("0"). If the struct // field value is zero and a numeric type, the field is empty, and it won't -// be encoded into the destination type. +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil or empty, it won't be encoded into the destination type. // // type Source struct { -// Age int `mapstructure:",omitempty"` +// Age int `mapstructure:",omitempty"` +// URLs []string `mapstructure:",omitempty"` +// } +// +// # Omit Zero Values +// +// When decoding from a struct to any other value, you may use the +// ",omitzero" suffix on your tag to omit that value if it equates to the zero +// value. The zero value of all types is specified in the Go specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil, it won't be encoded into the destination type. +// +// Note that if the field is a slice, and it is empty but not nil, it will +// still be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitzero"` +// URLs []string `mapstructure:",omitzero"` // } // // # Unexported fields @@ -222,6 +243,12 @@ type DecoderConfig struct { // will affect all nested structs as well. ErrorUnset bool + // AllowUnsetPointer, if set to true, will prevent fields with pointer types + // from being reported as unset, even if ErrorUnset is true and the field was + // not present in the input data. This allows pointer fields to be optional + // without triggering an error when they are missing. + AllowUnsetPointer bool + // ZeroFields, if set to true, will zero fields before writing them. // For example, a map will be emptied before decoded values are put in // it. If this is false, a map will be merged. @@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e var err error input, err = d.cachedDecodeHook(inputVal, outVal) if err != nil { - return fmt.Errorf("error decoding '%s': %w", name, err) + return newDecodeError(name, err) } } if isNil(input) { @@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e err = d.decodeFunc(name, input, outVal) default: // If we reached this point then we weren't able to decode it - return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind)) } // If we reached here, then we successfully decoded SOMETHING, so @@ -603,9 +630,10 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) dataValType := dataVal.Type() if !dataValType.AssignableTo(val.Type()) { - return fmt.Errorf( - "'%s' expected type '%s', got '%s'", - name, val.Type(), dataValType) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) @@ -656,9 +684,10 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) } if !converted { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -692,20 +721,28 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er if err == nil { val.SetInt(i) } else { - return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Int64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetInt(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Int: i := dataVal.Int() if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%d overflows uint", i), + }) } val.SetUint(uint64(i)) case dataKind == reflect.Uint: @@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Float32: f := dataVal.Float() if f < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %f overflows uint", - name, f) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%f overflows uint", f), + }) } val.SetUint(uint64(f)) case dataKind == reflect.Bool && d.config.WeaklyTypedInput: @@ -749,20 +792,28 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e if err == nil { val.SetUint(i) } else { - return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetUint(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -788,12 +839,17 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } else if dataVal.String() == "" { val.SetBool(false) } else { - return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'", - name, val, dataVal, data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -827,20 +883,28 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) if err == nil { val.SetFloat(f) } else { - return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Float64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetFloat(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -854,9 +918,10 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value case dataKind == reflect.Complex64: val.SetComplex(dataVal.Complex()) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil @@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er fallthrough default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } } @@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // to the map value. v := dataVal.Field(i) if !v.Type().AssignableTo(valMap.Type().Elem()) { - return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()), + ) } tagValue := f.Tag.Get(d.config.TagName) @@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re continue } + // If "omitzero" is specified in the tag, it ignores zero values. + if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() { + continue + } + // If "squash" is specified in the tag, we squash the field down. squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption) if squash { @@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // The final type must be a struct if v.Kind() != reflect.Struct { - return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot squash non-struct type %q", v.Type()), + ) } } else { if strings.Index(tagValue[index+1:], "remain") != -1 { if v.Kind() != reflect.Map { - return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()), + ) } ptr := v.MapRange() @@ -1146,9 +1228,10 @@ func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) e // into that. Then set the value of the pointer to this type. dataVal := reflect.Indirect(reflect.ValueOf(data)) if val.Type() != dataVal.Type() { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) return nil @@ -1189,8 +1272,8 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } // If the input value is nil, then don't allocate since empty != nil @@ -1257,13 +1340,13 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } if dataVal.Len() > arrayType.Len() { - return fmt.Errorf( - "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + return newDecodeError(name, + fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len())) } // Make a new array to hold our result, same size as the original data. @@ -1328,16 +1411,16 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) return result default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, + fmt.Errorf("expected a map or struct, got %q", dataValKind)) } } func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { dataValType := dataVal.Type() if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { - return fmt.Errorf( - "'%s' needs a map with string keys, has '%s' keys", - name, dataValType.Key().Kind()) + return newDecodeError(name, + fmt.Errorf("needs a map with string keys, has %q keys", kind)) } dataValKeys := make(map[reflect.Value]struct{}) @@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e structs = append(structs, fieldVal.Elem().Elem()) } default: - errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + errs = append(errs, newDecodeError( + name+"."+fieldType.Name, + fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()), + )) } continue } @@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e if !rawMapVal.IsValid() { // There was no matching key in the map for the value in // the struct. Remember it for potential errors and metadata. - targetValKeysUnused[fieldName] = struct{}{} + if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) { + targetValKeysUnused[fieldName] = struct{}{} + } continue } } @@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")), + )) } if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { @@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")), + )) } if err := errors.Join(errs...); err != nil { diff --git a/vendor/github.com/hashicorp/go-retryablehttp/.go-version b/vendor/github.com/hashicorp/go-retryablehttp/.go-version index 6fee2fed..a1b6e17d 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/.go-version +++ b/vendor/github.com/hashicorp/go-retryablehttp/.go-version @@ -1 +1 @@ -1.22.2 +1.23 diff --git a/vendor/github.com/hashicorp/go-retryablehttp/.golangci.yml b/vendor/github.com/hashicorp/go-retryablehttp/.golangci.yml new file mode 100644 index 00000000..4ff1a93b --- /dev/null +++ b/vendor/github.com/hashicorp/go-retryablehttp/.golangci.yml @@ -0,0 +1,11 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +linters: + disable-all: true + enable: + - errcheck + - staticcheck + - gosimple + - govet +output_format: colored-line-number diff --git a/vendor/github.com/hashicorp/go-retryablehttp/CODEOWNERS b/vendor/github.com/hashicorp/go-retryablehttp/CODEOWNERS index d6dd78a2..85b44a12 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/CODEOWNERS +++ b/vendor/github.com/hashicorp/go-retryablehttp/CODEOWNERS @@ -1 +1,13 @@ -* @hashicorp/go-retryablehttp-maintainers +# Each line is a file pattern followed by one or more owners. +# More on CODEOWNERS files: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners + +# Default owner +* @hashicorp/team-ip-compliance @hashicorp/go-retryablehttp-maintainers + +# Add override rules below. Each line is a file/folder pattern followed by one or more owners. +# Being an owner means those groups or individuals will be added as reviewers to PRs affecting +# those areas of the code. +# Examples: +# /docs/ @docs-team +# *.js @js-team +# *.go @go-team diff --git a/vendor/github.com/hashicorp/go-retryablehttp/Makefile b/vendor/github.com/hashicorp/go-retryablehttp/Makefile index 52552419..07b85a13 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/Makefile +++ b/vendor/github.com/hashicorp/go-retryablehttp/Makefile @@ -2,7 +2,7 @@ default: test test: go vet ./... - go test -v -race ./... + go test -v -race ./... -coverprofile=coverage.out updatedeps: go get -f -t -u ./... diff --git a/vendor/github.com/hashicorp/go-retryablehttp/client.go b/vendor/github.com/hashicorp/go-retryablehttp/client.go index efee53c4..91059f7d 100644 --- a/vendor/github.com/hashicorp/go-retryablehttp/client.go +++ b/vendor/github.com/hashicorp/go-retryablehttp/client.go @@ -638,6 +638,23 @@ func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Resp return time.Duration(jitterMin * int64(attemptNum)) } +// RateLimitLinearJitterBackoff wraps the retryablehttp.LinearJitterBackoff. +// It first checks if the response status code is http.StatusTooManyRequests +// (HTTP Code 429) or http.StatusServiceUnavailable (HTTP Code 503). If it is +// and the response contains a Retry-After response header, it will wait the +// amount of time specified by the header. Otherwise, this calls +// LinearJitterBackoff. +func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { + if resp != nil { + if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode == http.StatusServiceUnavailable { + if sleep, ok := parseRetryAfterHeader(resp.Header["Retry-After"]); ok { + return sleep + } + } + } + return LinearJitterBackoff(min, max, attemptNum, resp) +} + // PassthroughErrorHandler is an ErrorHandler that directly passes through the // values from the net/http library for the final request. The body is not // closed. @@ -870,11 +887,13 @@ func (c *Client) Head(url string) (*http.Response, error) { } // Post is a shortcut for doing a POST request without making a new client. +// The bodyType parameter sets the "Content-Type" header of the request. func Post(url, bodyType string, body interface{}) (*http.Response, error) { return defaultClient.Post(url, bodyType, body) } // Post is a convenience method for doing simple POST requests. +// The bodyType parameter sets the "Content-Type" header of the request. func (c *Client) Post(url, bodyType string, body interface{}) (*http.Response, error) { req, err := NewRequest("POST", url, body) if err != nil { diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/.gitignore b/vendor/github.com/launchdarkly/api-client-go/v17/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/.openapi-generator-ignore b/vendor/github.com/launchdarkly/api-client-go/v17/.openapi-generator-ignore new file mode 100644 index 00000000..7484ee59 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/.travis.yml b/vendor/github.com/launchdarkly/api-client-go/v17/.travis.yml new file mode 100644 index 00000000..f5cb2ce9 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/.travis.yml @@ -0,0 +1,8 @@ +language: go + +install: + - go get -d -v . + +script: + - go build -v ./ + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/LICENSE.txt b/vendor/github.com/launchdarkly/api-client-go/v17/LICENSE.txt new file mode 100644 index 00000000..21b4f4bc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright 2017 Catamorphic, Co. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/README.md b/vendor/github.com/launchdarkly/api-client-go/v17/README.md new file mode 100644 index 00000000..53956b93 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/README.md @@ -0,0 +1,1413 @@ +This repository contains a client library for LaunchDarkly's REST API. This client was automatically +generated from our [OpenAPI specification](https://app.launchdarkly.com/api/v2/openapi.json) using a [code generation library](https://github.com/launchdarkly/ld-openapi). + +This REST API is for custom integrations, data export, or automating your feature flag workflows. *DO NOT* use this client library to include feature flags in your web or mobile application. To integrate feature flags with your application, read the [SDK documentation](https://docs.launchdarkly.com/sdk). + +This client library is only compatible with the latest version of our REST API. Previous versions of this client library are compatible with earlier versions of our REST API. When you create an access token, you can set the REST API version associated with the token. By default, API requests you send using the token will use the specified API version. To learn more, read [Versioning](https://apidocs.launchdarkly.com/#section/Overview/Versioning). +View our [sample code](#sample-code) for example usage. + +# Go API client for ldapi + +This documentation describes LaunchDarkly's REST API. + +To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). + +## Authentication + +LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. + +All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. + +LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. + +| Auth mechanism | Allowed resources | Use cases | +| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | +| [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | +| SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | +| Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | +| Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | + +> #### Keep your access tokens and SDK keys private +> +> Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. +> +> The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. + +### Authentication using request header + +The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. + +Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. + +### Authentication using session cookie + +For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. + +If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. + +> ### Modifying the Origin header causes an error +> +> LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. +> +> If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. +> +> Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. +> +> To prevent this error, do not modify your Origin header. +> +> LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. + +## Representations + +All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). + +In practice this means that you always get a response with a `Content-Type` header set to `application/json`. + +In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. + +### Summary and detailed representations + +When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. + +The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. + +### Expanding responses + +Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. + +To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. + +### Links and addressability + +The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: + +- Links to other resources within the API are encapsulated in a `_links` object +- If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link + +Each link has two attributes: + +- An `href`, which contains the URL +- A `type`, which describes the content type + +For example, a feature resource might return the following: + +```json +{ + \"_links\": { + \"parent\": { + \"href\": \"/api/features\", + \"type\": \"application/json\" + }, + \"self\": { + \"href\": \"/api/features/sort.order\", + \"type\": \"application/json\" + } + }, + \"_site\": { + \"href\": \"/features/sort.order\", + \"type\": \"text/html\" + } +} +``` + +From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. + +Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. + +Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. + +## Updates + +Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. + +When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. + +### Updates using JSON patch + +[JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. + +For example, in this feature flag representation: + +```json +{ + \"name\": \"New recommendations engine\", + \"key\": \"engine.enable\", + \"description\": \"This is the description\", + ... +} +``` +You can change the feature flag's description with the following patch document: + +```json +[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] +``` + +You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: + +```json +[ + { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, + { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } +] +``` + +The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. + +Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. + +### Updates using JSON merge patch + +[JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: + +```json +{ + \"description\": \"New flag description\" +} +``` + +### Updates using semantic patch + +Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. + +Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. + +Here's how: + +``` +Content-Type: application/json; domain-model=launchdarkly.semanticpatch +``` + +If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. + +The body of a semantic patch request takes the following properties: + +* `comment` (string): (Optional) A description of the update. +* `environmentKey` (string): (Required for some resources only) The environment key. +* `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. + +For example: + +```json +{ + \"comment\": \"optional comment\", + \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] +} +``` + +Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. + +### Updates with comments + +You can submit optional comments with `PATCH` changes. + +To submit a comment along with a JSON patch document, use the following format: + +```json +{ + \"comment\": \"This is a comment string\", + \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] +} +``` + +To submit a comment along with a JSON merge patch document, use the following format: + +```json +{ + \"comment\": \"This is a comment string\", + \"merge\": { \"description\": \"New flag description\" } +} +``` + +To submit a comment along with a semantic patch, use the following format: + +```json +{ + \"comment\": \"This is a comment string\", + \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] +} +``` + +## Errors + +The API always returns errors in a common format. Here's an example: + +```json +{ + \"code\": \"invalid_request\", + \"message\": \"A feature with that key already exists\", + \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" +} +``` + +The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. + +### HTTP status error response codes + +| Code | Definition | Description | Possible Solution | +| ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | +| 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | +| 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | +| 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | +| 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | +| 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | +| 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. +| 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | + +## CORS + +The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: + +```http +Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization +Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH +Access-Control-Allow-Origin: * +Access-Control-Max-Age: 300 +``` + +You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. + +## Rate limiting + +We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. + +> ### Rate limiting and SDKs +> +> LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. + +### Global rate limits + +Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: + +| Header name | Description | +| ------------------------------ | -------------------------------------------------------------------------------- | +| `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | +| `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | + +We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. + +### Route-level rate limits + +Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: + +| Header name | Description | +| ----------------------------- | ----------------------------------------------------------------------------------------------------- | +| `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | +| `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | + +A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. + +We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. + +### IP-based rate limiting + +We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. + +## OpenAPI (Swagger) and client libraries + +We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. + +We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. + +Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. + +## Method overriding + +Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. + +To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. + +For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. + +## Beta resources + +We sometimes release new API resources in **beta** status before we release them with general availability. + +Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. + +We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. + +We mark beta resources with a \"Beta\" callout in our documentation, pictured below: + +> ### This feature is in beta +> +> To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). +> +> Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. + +### Using beta resources + +To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. + +Use this header: + +``` +LD-API-Version: beta +``` + +## Federal environments + +The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. + +If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. + +To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). + +## Versioning + +We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. + +Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. + +### Setting the API version per request + +You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: + +``` +LD-API-Version: 20240415 +``` + +The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. + +### Setting the API version per access token + +When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. + +Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. + +If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. + +> ### Best practice: Set the header for every client or integration +> +> We recommend that you set the API version header explicitly in any client or integration you build. +> +> Only rely on the access token API version during manual testing. + +### API version changelog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VersionChangesEnd of life (EOL)
`20240415` +
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
+
Current
`20220603` +
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
+
2025-04-15
`20210729` +
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
+
2023-06-03
`20191212` +
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
+
2022-07-29
`20160426` +
  • Initial versioning of API. Tokens created before versioning have their version set to this.
+
2020-12-12
+ +To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + + +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-spec](https://www.openapis.org/) from a remote server, you can easily generate an API client. + +- API version: 2.0 +- Package version: 17 +- Build package: org.openapitools.codegen.languages.GoClientCodegen +For more information, please visit [https://support.launchdarkly.com](https://support.launchdarkly.com) + +## Installation + +Install the following dependencies: + +```shell +go get github.com/stretchr/testify/assert +go get golang.org/x/oauth2 +go get golang.org/x/net/context +``` + +Put the package under your project folder and add the following in import: + +```golang +import ldapi "github.com/launchdarkly/api-client-go" +``` + +To use a proxy, set the environment variable `HTTP_PROXY`: + +```golang +os.Setenv("HTTP_PROXY", "http://proxy_name:proxy_port") +``` + +## Configuration of Server URL + +Default configuration comes with `Servers` field that contains server objects as defined in the OpenAPI specification. + +### Select Server Configuration + +For using other server than the one defined on index 0 set context value `sw.ContextServerIndex` of type `int`. + +```golang +ctx := context.WithValue(context.Background(), ldapi.ContextServerIndex, 1) +``` + +### Templated Server URL + +Templated server URL is formatted using default variables from configuration or from context value `sw.ContextServerVariables` of type `map[string]string`. + +```golang +ctx := context.WithValue(context.Background(), ldapi.ContextServerVariables, map[string]string{ + "basePath": "v2", +}) +``` + +Note, enum values are always validated and all unused variables are silently ignored. + +### URLs Configuration per Operation + +Each operation can use different server URL defined using `OperationServers` map in the `Configuration`. +An operation is uniquely identified by `"{classname}Service.{nickname}"` string. +Similar rules for overriding default operation server index and variables applies by using `sw.ContextOperationServerIndices` and `sw.ContextOperationServerVariables` context maps. + +``` +ctx := context.WithValue(context.Background(), ldapi.ContextOperationServerIndices, map[string]int{ + "{classname}Service.{nickname}": 2, +}) +ctx = context.WithValue(context.Background(), ldapi.ContextOperationServerVariables, map[string]map[string]string{ + "{classname}Service.{nickname}": { + "port": "8443", + }, +}) +``` + +## Documentation for API Endpoints + +All URIs are relative to *https://app.launchdarkly.com* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AIConfigsBetaApi* | [**DeleteAIConfig**](docs/AIConfigsBetaApi.md#deleteaiconfig) | **Delete** /api/v2/projects/{projectKey}/ai-configs/{configKey} | Delete AI Config +*AIConfigsBetaApi* | [**DeleteAIConfigVariation**](docs/AIConfigsBetaApi.md#deleteaiconfigvariation) | **Delete** /api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} | Delete AI Config variation +*AIConfigsBetaApi* | [**DeleteModelConfig**](docs/AIConfigsBetaApi.md#deletemodelconfig) | **Delete** /api/v2/projects/{projectKey}/ai-configs/model-configs/{modelConfigKey} | Delete an AI model config +*AIConfigsBetaApi* | [**GetAIConfig**](docs/AIConfigsBetaApi.md#getaiconfig) | **Get** /api/v2/projects/{projectKey}/ai-configs/{configKey} | Get AI Config +*AIConfigsBetaApi* | [**GetAIConfigMetrics**](docs/AIConfigsBetaApi.md#getaiconfigmetrics) | **Get** /api/v2/projects/{projectKey}/ai-configs/{configKey}/metrics | Get AI Config metrics +*AIConfigsBetaApi* | [**GetAIConfigMetricsByVariation**](docs/AIConfigsBetaApi.md#getaiconfigmetricsbyvariation) | **Get** /api/v2/projects/{projectKey}/ai-configs/{configKey}/metrics-by-variation | Get AI Config metrics by variation +*AIConfigsBetaApi* | [**GetAIConfigVariation**](docs/AIConfigsBetaApi.md#getaiconfigvariation) | **Get** /api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} | Get AI Config variation +*AIConfigsBetaApi* | [**GetAIConfigs**](docs/AIConfigsBetaApi.md#getaiconfigs) | **Get** /api/v2/projects/{projectKey}/ai-configs | List AI Configs +*AIConfigsBetaApi* | [**GetModelConfig**](docs/AIConfigsBetaApi.md#getmodelconfig) | **Get** /api/v2/projects/{projectKey}/ai-configs/model-configs/{modelConfigKey} | Get AI model config +*AIConfigsBetaApi* | [**ListModelConfigs**](docs/AIConfigsBetaApi.md#listmodelconfigs) | **Get** /api/v2/projects/{projectKey}/ai-configs/model-configs | List AI model configs +*AIConfigsBetaApi* | [**PatchAIConfig**](docs/AIConfigsBetaApi.md#patchaiconfig) | **Patch** /api/v2/projects/{projectKey}/ai-configs/{configKey} | Update AI Config +*AIConfigsBetaApi* | [**PatchAIConfigVariation**](docs/AIConfigsBetaApi.md#patchaiconfigvariation) | **Patch** /api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} | Update AI Config variation +*AIConfigsBetaApi* | [**PostAIConfig**](docs/AIConfigsBetaApi.md#postaiconfig) | **Post** /api/v2/projects/{projectKey}/ai-configs | Create new AI Config +*AIConfigsBetaApi* | [**PostAIConfigVariation**](docs/AIConfigsBetaApi.md#postaiconfigvariation) | **Post** /api/v2/projects/{projectKey}/ai-configs/{configKey}/variations | Create AI Config variation +*AIConfigsBetaApi* | [**PostModelConfig**](docs/AIConfigsBetaApi.md#postmodelconfig) | **Post** /api/v2/projects/{projectKey}/ai-configs/model-configs | Create an AI model config +*AccessTokensApi* | [**DeleteToken**](docs/AccessTokensApi.md#deletetoken) | **Delete** /api/v2/tokens/{id} | Delete access token +*AccessTokensApi* | [**GetToken**](docs/AccessTokensApi.md#gettoken) | **Get** /api/v2/tokens/{id} | Get access token +*AccessTokensApi* | [**GetTokens**](docs/AccessTokensApi.md#gettokens) | **Get** /api/v2/tokens | List access tokens +*AccessTokensApi* | [**PatchToken**](docs/AccessTokensApi.md#patchtoken) | **Patch** /api/v2/tokens/{id} | Patch access token +*AccessTokensApi* | [**PostToken**](docs/AccessTokensApi.md#posttoken) | **Post** /api/v2/tokens | Create access token +*AccessTokensApi* | [**ResetToken**](docs/AccessTokensApi.md#resettoken) | **Post** /api/v2/tokens/{id}/reset | Reset access token +*AccountMembersApi* | [**DeleteMember**](docs/AccountMembersApi.md#deletemember) | **Delete** /api/v2/members/{id} | Delete account member +*AccountMembersApi* | [**GetMember**](docs/AccountMembersApi.md#getmember) | **Get** /api/v2/members/{id} | Get account member +*AccountMembersApi* | [**GetMembers**](docs/AccountMembersApi.md#getmembers) | **Get** /api/v2/members | List account members +*AccountMembersApi* | [**PatchMember**](docs/AccountMembersApi.md#patchmember) | **Patch** /api/v2/members/{id} | Modify an account member +*AccountMembersApi* | [**PostMemberTeams**](docs/AccountMembersApi.md#postmemberteams) | **Post** /api/v2/members/{id}/teams | Add a member to teams +*AccountMembersApi* | [**PostMembers**](docs/AccountMembersApi.md#postmembers) | **Post** /api/v2/members | Invite new members +*AccountMembersBetaApi* | [**PatchMembers**](docs/AccountMembersBetaApi.md#patchmembers) | **Patch** /api/v2/members | Modify account members +*AccountUsageBetaApi* | [**GetDataExportEventsUsage**](docs/AccountUsageBetaApi.md#getdataexporteventsusage) | **Get** /api/v2/usage/data-export-events | Get data export events usage +*AccountUsageBetaApi* | [**GetEvaluationsUsage**](docs/AccountUsageBetaApi.md#getevaluationsusage) | **Get** /api/v2/usage/evaluations/{projectKey}/{environmentKey}/{featureFlagKey} | Get evaluations usage +*AccountUsageBetaApi* | [**GetEventsUsage**](docs/AccountUsageBetaApi.md#geteventsusage) | **Get** /api/v2/usage/events/{type} | Get events usage +*AccountUsageBetaApi* | [**GetExperimentationKeysUsage**](docs/AccountUsageBetaApi.md#getexperimentationkeysusage) | **Get** /api/v2/usage/experimentation-keys | Get experimentation keys usage +*AccountUsageBetaApi* | [**GetExperimentationUnitsUsage**](docs/AccountUsageBetaApi.md#getexperimentationunitsusage) | **Get** /api/v2/usage/experimentation-units | Get experimentation units usage +*AccountUsageBetaApi* | [**GetMauSdksByType**](docs/AccountUsageBetaApi.md#getmausdksbytype) | **Get** /api/v2/usage/mau/sdks | Get MAU SDKs by type +*AccountUsageBetaApi* | [**GetMauUsage**](docs/AccountUsageBetaApi.md#getmauusage) | **Get** /api/v2/usage/mau | Get MAU usage +*AccountUsageBetaApi* | [**GetMauUsageByCategory**](docs/AccountUsageBetaApi.md#getmauusagebycategory) | **Get** /api/v2/usage/mau/bycategory | Get MAU usage by category +*AccountUsageBetaApi* | [**GetServiceConnectionUsage**](docs/AccountUsageBetaApi.md#getserviceconnectionusage) | **Get** /api/v2/usage/service-connections | Get service connection usage +*AccountUsageBetaApi* | [**GetStreamUsage**](docs/AccountUsageBetaApi.md#getstreamusage) | **Get** /api/v2/usage/streams/{source} | Get stream usage +*AccountUsageBetaApi* | [**GetStreamUsageBySdkVersion**](docs/AccountUsageBetaApi.md#getstreamusagebysdkversion) | **Get** /api/v2/usage/streams/{source}/bysdkversion | Get stream usage by SDK version +*AccountUsageBetaApi* | [**GetStreamUsageSdkversion**](docs/AccountUsageBetaApi.md#getstreamusagesdkversion) | **Get** /api/v2/usage/streams/{source}/sdkversions | Get stream usage SDK versions +*AnnouncementsApi* | [**CreateAnnouncementPublic**](docs/AnnouncementsApi.md#createannouncementpublic) | **Post** /api/v2/announcements | Create an announcement +*AnnouncementsApi* | [**DeleteAnnouncementPublic**](docs/AnnouncementsApi.md#deleteannouncementpublic) | **Delete** /api/v2/announcements/{announcementId} | Delete an announcement +*AnnouncementsApi* | [**GetAnnouncementsPublic**](docs/AnnouncementsApi.md#getannouncementspublic) | **Get** /api/v2/announcements | Get announcements +*AnnouncementsApi* | [**UpdateAnnouncementPublic**](docs/AnnouncementsApi.md#updateannouncementpublic) | **Patch** /api/v2/announcements/{announcementId} | Update an announcement +*ApplicationsBetaApi* | [**DeleteApplication**](docs/ApplicationsBetaApi.md#deleteapplication) | **Delete** /api/v2/applications/{applicationKey} | Delete application +*ApplicationsBetaApi* | [**DeleteApplicationVersion**](docs/ApplicationsBetaApi.md#deleteapplicationversion) | **Delete** /api/v2/applications/{applicationKey}/versions/{versionKey} | Delete application version +*ApplicationsBetaApi* | [**GetApplication**](docs/ApplicationsBetaApi.md#getapplication) | **Get** /api/v2/applications/{applicationKey} | Get application by key +*ApplicationsBetaApi* | [**GetApplicationVersions**](docs/ApplicationsBetaApi.md#getapplicationversions) | **Get** /api/v2/applications/{applicationKey}/versions | Get application versions by application key +*ApplicationsBetaApi* | [**GetApplications**](docs/ApplicationsBetaApi.md#getapplications) | **Get** /api/v2/applications | Get applications +*ApplicationsBetaApi* | [**PatchApplication**](docs/ApplicationsBetaApi.md#patchapplication) | **Patch** /api/v2/applications/{applicationKey} | Update application +*ApplicationsBetaApi* | [**PatchApplicationVersion**](docs/ApplicationsBetaApi.md#patchapplicationversion) | **Patch** /api/v2/applications/{applicationKey}/versions/{versionKey} | Update application version +*ApprovalsApi* | [**DeleteApprovalRequest**](docs/ApprovalsApi.md#deleteapprovalrequest) | **Delete** /api/v2/approval-requests/{id} | Delete approval request +*ApprovalsApi* | [**DeleteApprovalRequestForFlag**](docs/ApprovalsApi.md#deleteapprovalrequestforflag) | **Delete** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id} | Delete approval request for a flag +*ApprovalsApi* | [**GetApprovalForFlag**](docs/ApprovalsApi.md#getapprovalforflag) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id} | Get approval request for a flag +*ApprovalsApi* | [**GetApprovalRequest**](docs/ApprovalsApi.md#getapprovalrequest) | **Get** /api/v2/approval-requests/{id} | Get approval request +*ApprovalsApi* | [**GetApprovalRequests**](docs/ApprovalsApi.md#getapprovalrequests) | **Get** /api/v2/approval-requests | List approval requests +*ApprovalsApi* | [**GetApprovalsForFlag**](docs/ApprovalsApi.md#getapprovalsforflag) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests | List approval requests for a flag +*ApprovalsApi* | [**PostApprovalRequest**](docs/ApprovalsApi.md#postapprovalrequest) | **Post** /api/v2/approval-requests | Create approval request +*ApprovalsApi* | [**PostApprovalRequestApply**](docs/ApprovalsApi.md#postapprovalrequestapply) | **Post** /api/v2/approval-requests/{id}/apply | Apply approval request +*ApprovalsApi* | [**PostApprovalRequestApplyForFlag**](docs/ApprovalsApi.md#postapprovalrequestapplyforflag) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}/apply | Apply approval request for a flag +*ApprovalsApi* | [**PostApprovalRequestForFlag**](docs/ApprovalsApi.md#postapprovalrequestforflag) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests | Create approval request for a flag +*ApprovalsApi* | [**PostApprovalRequestReview**](docs/ApprovalsApi.md#postapprovalrequestreview) | **Post** /api/v2/approval-requests/{id}/reviews | Review approval request +*ApprovalsApi* | [**PostApprovalRequestReviewForFlag**](docs/ApprovalsApi.md#postapprovalrequestreviewforflag) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}/reviews | Review approval request for a flag +*ApprovalsApi* | [**PostFlagCopyConfigApprovalRequest**](docs/ApprovalsApi.md#postflagcopyconfigapprovalrequest) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests-flag-copy | Create approval request to copy flag configurations across environments +*ApprovalsBetaApi* | [**PatchApprovalRequest**](docs/ApprovalsBetaApi.md#patchapprovalrequest) | **Patch** /api/v2/approval-requests/{id} | Update approval request +*ApprovalsBetaApi* | [**PatchFlagConfigApprovalRequest**](docs/ApprovalsBetaApi.md#patchflagconfigapprovalrequest) | **Patch** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id} | Update flag approval request +*AuditLogApi* | [**GetAuditLogEntries**](docs/AuditLogApi.md#getauditlogentries) | **Get** /api/v2/auditlog | List audit log entries +*AuditLogApi* | [**GetAuditLogEntry**](docs/AuditLogApi.md#getauditlogentry) | **Get** /api/v2/auditlog/{id} | Get audit log entry +*AuditLogApi* | [**PostAuditLogEntries**](docs/AuditLogApi.md#postauditlogentries) | **Post** /api/v2/auditlog | Search audit log entries +*CodeReferencesApi* | [**DeleteBranches**](docs/CodeReferencesApi.md#deletebranches) | **Post** /api/v2/code-refs/repositories/{repo}/branch-delete-tasks | Delete branches +*CodeReferencesApi* | [**DeleteRepository**](docs/CodeReferencesApi.md#deleterepository) | **Delete** /api/v2/code-refs/repositories/{repo} | Delete repository +*CodeReferencesApi* | [**GetBranch**](docs/CodeReferencesApi.md#getbranch) | **Get** /api/v2/code-refs/repositories/{repo}/branches/{branch} | Get branch +*CodeReferencesApi* | [**GetBranches**](docs/CodeReferencesApi.md#getbranches) | **Get** /api/v2/code-refs/repositories/{repo}/branches | List branches +*CodeReferencesApi* | [**GetExtinctions**](docs/CodeReferencesApi.md#getextinctions) | **Get** /api/v2/code-refs/extinctions | List extinctions +*CodeReferencesApi* | [**GetRepositories**](docs/CodeReferencesApi.md#getrepositories) | **Get** /api/v2/code-refs/repositories | List repositories +*CodeReferencesApi* | [**GetRepository**](docs/CodeReferencesApi.md#getrepository) | **Get** /api/v2/code-refs/repositories/{repo} | Get repository +*CodeReferencesApi* | [**GetRootStatistic**](docs/CodeReferencesApi.md#getrootstatistic) | **Get** /api/v2/code-refs/statistics | Get links to code reference repositories for each project +*CodeReferencesApi* | [**GetStatistics**](docs/CodeReferencesApi.md#getstatistics) | **Get** /api/v2/code-refs/statistics/{projectKey} | Get code references statistics for flags +*CodeReferencesApi* | [**PatchRepository**](docs/CodeReferencesApi.md#patchrepository) | **Patch** /api/v2/code-refs/repositories/{repo} | Update repository +*CodeReferencesApi* | [**PostExtinction**](docs/CodeReferencesApi.md#postextinction) | **Post** /api/v2/code-refs/repositories/{repo}/branches/{branch}/extinction-events | Create extinction +*CodeReferencesApi* | [**PostRepository**](docs/CodeReferencesApi.md#postrepository) | **Post** /api/v2/code-refs/repositories | Create repository +*CodeReferencesApi* | [**PutBranch**](docs/CodeReferencesApi.md#putbranch) | **Put** /api/v2/code-refs/repositories/{repo}/branches/{branch} | Upsert branch +*ContextSettingsApi* | [**PutContextFlagSetting**](docs/ContextSettingsApi.md#putcontextflagsetting) | **Put** /api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/{contextKind}/{contextKey}/flags/{featureFlagKey} | Update flag settings for context +*ContextsApi* | [**DeleteContextInstances**](docs/ContextsApi.md#deletecontextinstances) | **Delete** /api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/{id} | Delete context instances +*ContextsApi* | [**EvaluateContextInstance**](docs/ContextsApi.md#evaluatecontextinstance) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/flags/evaluate | Evaluate flags for context instance +*ContextsApi* | [**GetContextAttributeNames**](docs/ContextsApi.md#getcontextattributenames) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/context-attributes | Get context attribute names +*ContextsApi* | [**GetContextAttributeValues**](docs/ContextsApi.md#getcontextattributevalues) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/context-attributes/{attributeName} | Get context attribute values +*ContextsApi* | [**GetContextInstances**](docs/ContextsApi.md#getcontextinstances) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/{id} | Get context instances +*ContextsApi* | [**GetContextKindsByProjectKey**](docs/ContextsApi.md#getcontextkindsbyprojectkey) | **Get** /api/v2/projects/{projectKey}/context-kinds | Get context kinds +*ContextsApi* | [**GetContexts**](docs/ContextsApi.md#getcontexts) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/{kind}/{key} | Get contexts +*ContextsApi* | [**PutContextKind**](docs/ContextsApi.md#putcontextkind) | **Put** /api/v2/projects/{projectKey}/context-kinds/{key} | Create or update context kind +*ContextsApi* | [**SearchContextInstances**](docs/ContextsApi.md#searchcontextinstances) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/search | Search for context instances +*ContextsApi* | [**SearchContexts**](docs/ContextsApi.md#searchcontexts) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/search | Search for contexts +*CustomRolesApi* | [**DeleteCustomRole**](docs/CustomRolesApi.md#deletecustomrole) | **Delete** /api/v2/roles/{customRoleKey} | Delete custom role +*CustomRolesApi* | [**GetCustomRole**](docs/CustomRolesApi.md#getcustomrole) | **Get** /api/v2/roles/{customRoleKey} | Get custom role +*CustomRolesApi* | [**GetCustomRoles**](docs/CustomRolesApi.md#getcustomroles) | **Get** /api/v2/roles | List custom roles +*CustomRolesApi* | [**PatchCustomRole**](docs/CustomRolesApi.md#patchcustomrole) | **Patch** /api/v2/roles/{customRoleKey} | Update custom role +*CustomRolesApi* | [**PostCustomRole**](docs/CustomRolesApi.md#postcustomrole) | **Post** /api/v2/roles | Create custom role +*DataExportDestinationsApi* | [**DeleteDestination**](docs/DataExportDestinationsApi.md#deletedestination) | **Delete** /api/v2/destinations/{projectKey}/{environmentKey}/{id} | Delete Data Export destination +*DataExportDestinationsApi* | [**GetDestination**](docs/DataExportDestinationsApi.md#getdestination) | **Get** /api/v2/destinations/{projectKey}/{environmentKey}/{id} | Get destination +*DataExportDestinationsApi* | [**GetDestinations**](docs/DataExportDestinationsApi.md#getdestinations) | **Get** /api/v2/destinations | List destinations +*DataExportDestinationsApi* | [**PatchDestination**](docs/DataExportDestinationsApi.md#patchdestination) | **Patch** /api/v2/destinations/{projectKey}/{environmentKey}/{id} | Update Data Export destination +*DataExportDestinationsApi* | [**PostDestination**](docs/DataExportDestinationsApi.md#postdestination) | **Post** /api/v2/destinations/{projectKey}/{environmentKey} | Create Data Export destination +*DataExportDestinationsApi* | [**PostGenerateWarehouseDestinationKeyPair**](docs/DataExportDestinationsApi.md#postgeneratewarehousedestinationkeypair) | **Post** /api/v2/destinations/generate-warehouse-destination-key-pair | Generate Snowflake destination key pair +*EnvironmentsApi* | [**DeleteEnvironment**](docs/EnvironmentsApi.md#deleteenvironment) | **Delete** /api/v2/projects/{projectKey}/environments/{environmentKey} | Delete environment +*EnvironmentsApi* | [**GetEnvironment**](docs/EnvironmentsApi.md#getenvironment) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey} | Get environment +*EnvironmentsApi* | [**GetEnvironmentsByProject**](docs/EnvironmentsApi.md#getenvironmentsbyproject) | **Get** /api/v2/projects/{projectKey}/environments | List environments +*EnvironmentsApi* | [**PatchEnvironment**](docs/EnvironmentsApi.md#patchenvironment) | **Patch** /api/v2/projects/{projectKey}/environments/{environmentKey} | Update environment +*EnvironmentsApi* | [**PostEnvironment**](docs/EnvironmentsApi.md#postenvironment) | **Post** /api/v2/projects/{projectKey}/environments | Create environment +*EnvironmentsApi* | [**ResetEnvironmentMobileKey**](docs/EnvironmentsApi.md#resetenvironmentmobilekey) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/mobileKey | Reset environment mobile SDK key +*EnvironmentsApi* | [**ResetEnvironmentSDKKey**](docs/EnvironmentsApi.md#resetenvironmentsdkkey) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/apiKey | Reset environment SDK key +*ExperimentsApi* | [**CreateExperiment**](docs/ExperimentsApi.md#createexperiment) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments | Create experiment +*ExperimentsApi* | [**CreateIteration**](docs/ExperimentsApi.md#createiteration) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/iterations | Create iteration +*ExperimentsApi* | [**GetExperiment**](docs/ExperimentsApi.md#getexperiment) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey} | Get experiment +*ExperimentsApi* | [**GetExperimentResults**](docs/ExperimentsApi.md#getexperimentresults) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/metrics/{metricKey}/results | Get experiment results (Deprecated) +*ExperimentsApi* | [**GetExperimentResultsForMetricGroup**](docs/ExperimentsApi.md#getexperimentresultsformetricgroup) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/metric-groups/{metricGroupKey}/results | Get experiment results for metric group (Deprecated) +*ExperimentsApi* | [**GetExperimentationSettings**](docs/ExperimentsApi.md#getexperimentationsettings) | **Get** /api/v2/projects/{projectKey}/experimentation-settings | Get experimentation settings +*ExperimentsApi* | [**GetExperiments**](docs/ExperimentsApi.md#getexperiments) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments | Get experiments +*ExperimentsApi* | [**PatchExperiment**](docs/ExperimentsApi.md#patchexperiment) | **Patch** /api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey} | Patch experiment +*ExperimentsApi* | [**PutExperimentationSettings**](docs/ExperimentsApi.md#putexperimentationsettings) | **Put** /api/v2/projects/{projectKey}/experimentation-settings | Update experimentation settings +*FeatureFlagsApi* | [**CopyFeatureFlag**](docs/FeatureFlagsApi.md#copyfeatureflag) | **Post** /api/v2/flags/{projectKey}/{featureFlagKey}/copy | Copy feature flag +*FeatureFlagsApi* | [**DeleteFeatureFlag**](docs/FeatureFlagsApi.md#deletefeatureflag) | **Delete** /api/v2/flags/{projectKey}/{featureFlagKey} | Delete feature flag +*FeatureFlagsApi* | [**GetExpiringContextTargets**](docs/FeatureFlagsApi.md#getexpiringcontexttargets) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey}/expiring-targets/{environmentKey} | Get expiring context targets for feature flag +*FeatureFlagsApi* | [**GetExpiringUserTargets**](docs/FeatureFlagsApi.md#getexpiringusertargets) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey}/expiring-user-targets/{environmentKey} | Get expiring user targets for feature flag +*FeatureFlagsApi* | [**GetFeatureFlag**](docs/FeatureFlagsApi.md#getfeatureflag) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey} | Get feature flag +*FeatureFlagsApi* | [**GetFeatureFlagStatus**](docs/FeatureFlagsApi.md#getfeatureflagstatus) | **Get** /api/v2/flag-statuses/{projectKey}/{environmentKey}/{featureFlagKey} | Get feature flag status +*FeatureFlagsApi* | [**GetFeatureFlagStatusAcrossEnvironments**](docs/FeatureFlagsApi.md#getfeatureflagstatusacrossenvironments) | **Get** /api/v2/flag-status/{projectKey}/{featureFlagKey} | Get flag status across environments +*FeatureFlagsApi* | [**GetFeatureFlagStatuses**](docs/FeatureFlagsApi.md#getfeatureflagstatuses) | **Get** /api/v2/flag-statuses/{projectKey}/{environmentKey} | List feature flag statuses +*FeatureFlagsApi* | [**GetFeatureFlags**](docs/FeatureFlagsApi.md#getfeatureflags) | **Get** /api/v2/flags/{projectKey} | List feature flags +*FeatureFlagsApi* | [**PatchExpiringTargets**](docs/FeatureFlagsApi.md#patchexpiringtargets) | **Patch** /api/v2/flags/{projectKey}/{featureFlagKey}/expiring-targets/{environmentKey} | Update expiring context targets on feature flag +*FeatureFlagsApi* | [**PatchExpiringUserTargets**](docs/FeatureFlagsApi.md#patchexpiringusertargets) | **Patch** /api/v2/flags/{projectKey}/{featureFlagKey}/expiring-user-targets/{environmentKey} | Update expiring user targets on feature flag +*FeatureFlagsApi* | [**PatchFeatureFlag**](docs/FeatureFlagsApi.md#patchfeatureflag) | **Patch** /api/v2/flags/{projectKey}/{featureFlagKey} | Update feature flag +*FeatureFlagsApi* | [**PostFeatureFlag**](docs/FeatureFlagsApi.md#postfeatureflag) | **Post** /api/v2/flags/{projectKey} | Create a feature flag +*FeatureFlagsApi* | [**PostMigrationSafetyIssues**](docs/FeatureFlagsApi.md#postmigrationsafetyissues) | **Post** /api/v2/projects/{projectKey}/flags/{flagKey}/environments/{environmentKey}/migration-safety-issues | Get migration safety issues +*FeatureFlagsBetaApi* | [**GetDependentFlags**](docs/FeatureFlagsBetaApi.md#getdependentflags) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey}/dependent-flags | List dependent feature flags +*FeatureFlagsBetaApi* | [**GetDependentFlagsByEnv**](docs/FeatureFlagsBetaApi.md#getdependentflagsbyenv) | **Get** /api/v2/flags/{projectKey}/{environmentKey}/{featureFlagKey}/dependent-flags | List dependent feature flags by environment +*FlagImportConfigurationsBetaApi* | [**CreateFlagImportConfiguration**](docs/FlagImportConfigurationsBetaApi.md#createflagimportconfiguration) | **Post** /api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey} | Create a flag import configuration +*FlagImportConfigurationsBetaApi* | [**DeleteFlagImportConfiguration**](docs/FlagImportConfigurationsBetaApi.md#deleteflagimportconfiguration) | **Delete** /api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId} | Delete a flag import configuration +*FlagImportConfigurationsBetaApi* | [**GetFlagImportConfiguration**](docs/FlagImportConfigurationsBetaApi.md#getflagimportconfiguration) | **Get** /api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId} | Get a single flag import configuration +*FlagImportConfigurationsBetaApi* | [**GetFlagImportConfigurations**](docs/FlagImportConfigurationsBetaApi.md#getflagimportconfigurations) | **Get** /api/v2/integration-capabilities/flag-import | List all flag import configurations +*FlagImportConfigurationsBetaApi* | [**PatchFlagImportConfiguration**](docs/FlagImportConfigurationsBetaApi.md#patchflagimportconfiguration) | **Patch** /api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId} | Update a flag import configuration +*FlagImportConfigurationsBetaApi* | [**TriggerFlagImportJob**](docs/FlagImportConfigurationsBetaApi.md#triggerflagimportjob) | **Post** /api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId}/trigger | Trigger a single flag import run +*FlagLinksBetaApi* | [**CreateFlagLink**](docs/FlagLinksBetaApi.md#createflaglink) | **Post** /api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey} | Create flag link +*FlagLinksBetaApi* | [**DeleteFlagLink**](docs/FlagLinksBetaApi.md#deleteflaglink) | **Delete** /api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}/{id} | Delete flag link +*FlagLinksBetaApi* | [**GetFlagLinks**](docs/FlagLinksBetaApi.md#getflaglinks) | **Get** /api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey} | List flag links +*FlagLinksBetaApi* | [**UpdateFlagLink**](docs/FlagLinksBetaApi.md#updateflaglink) | **Patch** /api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}/{id} | Update flag link +*FlagTriggersApi* | [**CreateTriggerWorkflow**](docs/FlagTriggersApi.md#createtriggerworkflow) | **Post** /api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey} | Create flag trigger +*FlagTriggersApi* | [**DeleteTriggerWorkflow**](docs/FlagTriggersApi.md#deletetriggerworkflow) | **Delete** /api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id} | Delete flag trigger +*FlagTriggersApi* | [**GetTriggerWorkflowById**](docs/FlagTriggersApi.md#gettriggerworkflowbyid) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id} | Get flag trigger by ID +*FlagTriggersApi* | [**GetTriggerWorkflows**](docs/FlagTriggersApi.md#gettriggerworkflows) | **Get** /api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey} | List flag triggers +*FlagTriggersApi* | [**PatchTriggerWorkflow**](docs/FlagTriggersApi.md#patchtriggerworkflow) | **Patch** /api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id} | Update flag trigger +*FollowFlagsApi* | [**DeleteFlagFollower**](docs/FollowFlagsApi.md#deleteflagfollower) | **Delete** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers/{memberId} | Remove a member as a follower of a flag in a project and environment +*FollowFlagsApi* | [**GetFlagFollowers**](docs/FollowFlagsApi.md#getflagfollowers) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers | Get followers of a flag in a project and environment +*FollowFlagsApi* | [**GetFollowersByProjEnv**](docs/FollowFlagsApi.md#getfollowersbyprojenv) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/followers | Get followers of all flags in a given project and environment +*FollowFlagsApi* | [**PutFlagFollower**](docs/FollowFlagsApi.md#putflagfollower) | **Put** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers/{memberId} | Add a member as a follower of a flag in a project and environment +*HoldoutsBetaApi* | [**GetAllHoldouts**](docs/HoldoutsBetaApi.md#getallholdouts) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts | Get all holdouts +*HoldoutsBetaApi* | [**GetHoldout**](docs/HoldoutsBetaApi.md#getholdout) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/{holdoutKey} | Get holdout +*HoldoutsBetaApi* | [**GetHoldoutById**](docs/HoldoutsBetaApi.md#getholdoutbyid) | **Get** /api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/id/{holdoutId} | Get Holdout by Id +*HoldoutsBetaApi* | [**PatchHoldout**](docs/HoldoutsBetaApi.md#patchholdout) | **Patch** /api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/{holdoutKey} | Patch holdout +*HoldoutsBetaApi* | [**PostHoldout**](docs/HoldoutsBetaApi.md#postholdout) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts | Create holdout +*InsightsChartsBetaApi* | [**GetDeploymentFrequencyChart**](docs/InsightsChartsBetaApi.md#getdeploymentfrequencychart) | **Get** /api/v2/engineering-insights/charts/deployments/frequency | Get deployment frequency chart data +*InsightsChartsBetaApi* | [**GetFlagStatusChart**](docs/InsightsChartsBetaApi.md#getflagstatuschart) | **Get** /api/v2/engineering-insights/charts/flags/status | Get flag status chart data +*InsightsChartsBetaApi* | [**GetLeadTimeChart**](docs/InsightsChartsBetaApi.md#getleadtimechart) | **Get** /api/v2/engineering-insights/charts/lead-time | Get lead time chart data +*InsightsChartsBetaApi* | [**GetReleaseFrequencyChart**](docs/InsightsChartsBetaApi.md#getreleasefrequencychart) | **Get** /api/v2/engineering-insights/charts/releases/frequency | Get release frequency chart data +*InsightsChartsBetaApi* | [**GetStaleFlagsChart**](docs/InsightsChartsBetaApi.md#getstaleflagschart) | **Get** /api/v2/engineering-insights/charts/flags/stale | Get stale flags chart data +*InsightsDeploymentsBetaApi* | [**CreateDeploymentEvent**](docs/InsightsDeploymentsBetaApi.md#createdeploymentevent) | **Post** /api/v2/engineering-insights/deployment-events | Create deployment event +*InsightsDeploymentsBetaApi* | [**GetDeployment**](docs/InsightsDeploymentsBetaApi.md#getdeployment) | **Get** /api/v2/engineering-insights/deployments/{deploymentID} | Get deployment +*InsightsDeploymentsBetaApi* | [**GetDeployments**](docs/InsightsDeploymentsBetaApi.md#getdeployments) | **Get** /api/v2/engineering-insights/deployments | List deployments +*InsightsDeploymentsBetaApi* | [**UpdateDeployment**](docs/InsightsDeploymentsBetaApi.md#updatedeployment) | **Patch** /api/v2/engineering-insights/deployments/{deploymentID} | Update deployment +*InsightsFlagEventsBetaApi* | [**GetFlagEvents**](docs/InsightsFlagEventsBetaApi.md#getflagevents) | **Get** /api/v2/engineering-insights/flag-events | List flag events +*InsightsPullRequestsBetaApi* | [**GetPullRequests**](docs/InsightsPullRequestsBetaApi.md#getpullrequests) | **Get** /api/v2/engineering-insights/pull-requests | List pull requests +*InsightsRepositoriesBetaApi* | [**AssociateRepositoriesAndProjects**](docs/InsightsRepositoriesBetaApi.md#associaterepositoriesandprojects) | **Put** /api/v2/engineering-insights/repositories/projects | Associate repositories with projects +*InsightsRepositoriesBetaApi* | [**DeleteRepositoryProject**](docs/InsightsRepositoriesBetaApi.md#deleterepositoryproject) | **Delete** /api/v2/engineering-insights/repositories/{repositoryKey}/projects/{projectKey} | Remove repository project association +*InsightsRepositoriesBetaApi* | [**GetInsightsRepositories**](docs/InsightsRepositoriesBetaApi.md#getinsightsrepositories) | **Get** /api/v2/engineering-insights/repositories | List repositories +*InsightsScoresBetaApi* | [**CreateInsightGroup**](docs/InsightsScoresBetaApi.md#createinsightgroup) | **Post** /api/v2/engineering-insights/insights/group | Create insight group +*InsightsScoresBetaApi* | [**DeleteInsightGroup**](docs/InsightsScoresBetaApi.md#deleteinsightgroup) | **Delete** /api/v2/engineering-insights/insights/groups/{insightGroupKey} | Delete insight group +*InsightsScoresBetaApi* | [**GetInsightGroup**](docs/InsightsScoresBetaApi.md#getinsightgroup) | **Get** /api/v2/engineering-insights/insights/groups/{insightGroupKey} | Get insight group +*InsightsScoresBetaApi* | [**GetInsightGroups**](docs/InsightsScoresBetaApi.md#getinsightgroups) | **Get** /api/v2/engineering-insights/insights/groups | List insight groups +*InsightsScoresBetaApi* | [**GetInsightsScores**](docs/InsightsScoresBetaApi.md#getinsightsscores) | **Get** /api/v2/engineering-insights/insights/scores | Get insight scores +*InsightsScoresBetaApi* | [**PatchInsightGroup**](docs/InsightsScoresBetaApi.md#patchinsightgroup) | **Patch** /api/v2/engineering-insights/insights/groups/{insightGroupKey} | Patch insight group +*IntegrationAuditLogSubscriptionsApi* | [**CreateSubscription**](docs/IntegrationAuditLogSubscriptionsApi.md#createsubscription) | **Post** /api/v2/integrations/{integrationKey} | Create audit log subscription +*IntegrationAuditLogSubscriptionsApi* | [**DeleteSubscription**](docs/IntegrationAuditLogSubscriptionsApi.md#deletesubscription) | **Delete** /api/v2/integrations/{integrationKey}/{id} | Delete audit log subscription +*IntegrationAuditLogSubscriptionsApi* | [**GetSubscriptionByID**](docs/IntegrationAuditLogSubscriptionsApi.md#getsubscriptionbyid) | **Get** /api/v2/integrations/{integrationKey}/{id} | Get audit log subscription by ID +*IntegrationAuditLogSubscriptionsApi* | [**GetSubscriptions**](docs/IntegrationAuditLogSubscriptionsApi.md#getsubscriptions) | **Get** /api/v2/integrations/{integrationKey} | Get audit log subscriptions by integration +*IntegrationAuditLogSubscriptionsApi* | [**UpdateSubscription**](docs/IntegrationAuditLogSubscriptionsApi.md#updatesubscription) | **Patch** /api/v2/integrations/{integrationKey}/{id} | Update audit log subscription +*IntegrationDeliveryConfigurationsBetaApi* | [**CreateIntegrationDeliveryConfiguration**](docs/IntegrationDeliveryConfigurationsBetaApi.md#createintegrationdeliveryconfiguration) | **Post** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey} | Create delivery configuration +*IntegrationDeliveryConfigurationsBetaApi* | [**DeleteIntegrationDeliveryConfiguration**](docs/IntegrationDeliveryConfigurationsBetaApi.md#deleteintegrationdeliveryconfiguration) | **Delete** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id} | Delete delivery configuration +*IntegrationDeliveryConfigurationsBetaApi* | [**GetIntegrationDeliveryConfigurationByEnvironment**](docs/IntegrationDeliveryConfigurationsBetaApi.md#getintegrationdeliveryconfigurationbyenvironment) | **Get** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey} | Get delivery configurations by environment +*IntegrationDeliveryConfigurationsBetaApi* | [**GetIntegrationDeliveryConfigurationById**](docs/IntegrationDeliveryConfigurationsBetaApi.md#getintegrationdeliveryconfigurationbyid) | **Get** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id} | Get delivery configuration by ID +*IntegrationDeliveryConfigurationsBetaApi* | [**GetIntegrationDeliveryConfigurations**](docs/IntegrationDeliveryConfigurationsBetaApi.md#getintegrationdeliveryconfigurations) | **Get** /api/v2/integration-capabilities/featureStore | List all delivery configurations +*IntegrationDeliveryConfigurationsBetaApi* | [**PatchIntegrationDeliveryConfiguration**](docs/IntegrationDeliveryConfigurationsBetaApi.md#patchintegrationdeliveryconfiguration) | **Patch** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id} | Update delivery configuration +*IntegrationDeliveryConfigurationsBetaApi* | [**ValidateIntegrationDeliveryConfiguration**](docs/IntegrationDeliveryConfigurationsBetaApi.md#validateintegrationdeliveryconfiguration) | **Post** /api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id}/validate | Validate delivery configuration +*IntegrationsBetaApi* | [**CreateIntegrationConfiguration**](docs/IntegrationsBetaApi.md#createintegrationconfiguration) | **Post** /api/v2/integration-configurations/keys/{integrationKey} | Create integration configuration +*IntegrationsBetaApi* | [**DeleteIntegrationConfiguration**](docs/IntegrationsBetaApi.md#deleteintegrationconfiguration) | **Delete** /api/v2/integration-configurations/{integrationConfigurationId} | Delete integration configuration +*IntegrationsBetaApi* | [**GetAllIntegrationConfigurations**](docs/IntegrationsBetaApi.md#getallintegrationconfigurations) | **Get** /api/v2/integration-configurations/keys/{integrationKey} | Get all configurations for the integration +*IntegrationsBetaApi* | [**GetIntegrationConfiguration**](docs/IntegrationsBetaApi.md#getintegrationconfiguration) | **Get** /api/v2/integration-configurations/{integrationConfigurationId} | Get an integration configuration +*IntegrationsBetaApi* | [**UpdateIntegrationConfiguration**](docs/IntegrationsBetaApi.md#updateintegrationconfiguration) | **Patch** /api/v2/integration-configurations/{integrationConfigurationId} | Update integration configuration +*LayersApi* | [**CreateLayer**](docs/LayersApi.md#createlayer) | **Post** /api/v2/projects/{projectKey}/layers | Create layer +*LayersApi* | [**GetLayers**](docs/LayersApi.md#getlayers) | **Get** /api/v2/projects/{projectKey}/layers | Get layers +*LayersApi* | [**UpdateLayer**](docs/LayersApi.md#updatelayer) | **Patch** /api/v2/projects/{projectKey}/layers/{layerKey} | Update layer +*MetricsApi* | [**DeleteMetric**](docs/MetricsApi.md#deletemetric) | **Delete** /api/v2/metrics/{projectKey}/{metricKey} | Delete metric +*MetricsApi* | [**GetMetric**](docs/MetricsApi.md#getmetric) | **Get** /api/v2/metrics/{projectKey}/{metricKey} | Get metric +*MetricsApi* | [**GetMetrics**](docs/MetricsApi.md#getmetrics) | **Get** /api/v2/metrics/{projectKey} | List metrics +*MetricsApi* | [**PatchMetric**](docs/MetricsApi.md#patchmetric) | **Patch** /api/v2/metrics/{projectKey}/{metricKey} | Update metric +*MetricsApi* | [**PostMetric**](docs/MetricsApi.md#postmetric) | **Post** /api/v2/metrics/{projectKey} | Create metric +*MetricsBetaApi* | [**CreateMetricGroup**](docs/MetricsBetaApi.md#createmetricgroup) | **Post** /api/v2/projects/{projectKey}/metric-groups | Create metric group +*MetricsBetaApi* | [**DeleteMetricGroup**](docs/MetricsBetaApi.md#deletemetricgroup) | **Delete** /api/v2/projects/{projectKey}/metric-groups/{metricGroupKey} | Delete metric group +*MetricsBetaApi* | [**GetMetricGroup**](docs/MetricsBetaApi.md#getmetricgroup) | **Get** /api/v2/projects/{projectKey}/metric-groups/{metricGroupKey} | Get metric group +*MetricsBetaApi* | [**GetMetricGroups**](docs/MetricsBetaApi.md#getmetricgroups) | **Get** /api/v2/projects/{projectKey}/metric-groups | List metric groups +*MetricsBetaApi* | [**PatchMetricGroup**](docs/MetricsBetaApi.md#patchmetricgroup) | **Patch** /api/v2/projects/{projectKey}/metric-groups/{metricGroupKey} | Patch metric group +*OAuth2ClientsApi* | [**CreateOAuth2Client**](docs/OAuth2ClientsApi.md#createoauth2client) | **Post** /api/v2/oauth/clients | Create a LaunchDarkly OAuth 2.0 client +*OAuth2ClientsApi* | [**DeleteOAuthClient**](docs/OAuth2ClientsApi.md#deleteoauthclient) | **Delete** /api/v2/oauth/clients/{clientId} | Delete OAuth 2.0 client +*OAuth2ClientsApi* | [**GetOAuthClientById**](docs/OAuth2ClientsApi.md#getoauthclientbyid) | **Get** /api/v2/oauth/clients/{clientId} | Get client by ID +*OAuth2ClientsApi* | [**GetOAuthClients**](docs/OAuth2ClientsApi.md#getoauthclients) | **Get** /api/v2/oauth/clients | Get clients +*OAuth2ClientsApi* | [**PatchOAuthClient**](docs/OAuth2ClientsApi.md#patchoauthclient) | **Patch** /api/v2/oauth/clients/{clientId} | Patch client by ID +*OtherApi* | [**GetCallerIdentity**](docs/OtherApi.md#getcalleridentity) | **Get** /api/v2/caller-identity | Identify the caller +*OtherApi* | [**GetIps**](docs/OtherApi.md#getips) | **Get** /api/v2/public-ip-list | Gets the public IP list +*OtherApi* | [**GetOpenapiSpec**](docs/OtherApi.md#getopenapispec) | **Get** /api/v2/openapi.json | Gets the OpenAPI spec in json +*OtherApi* | [**GetRoot**](docs/OtherApi.md#getroot) | **Get** /api/v2 | Root resource +*OtherApi* | [**GetVersions**](docs/OtherApi.md#getversions) | **Get** /api/v2/versions | Get version information +*PersistentStoreIntegrationsBetaApi* | [**CreateBigSegmentStoreIntegration**](docs/PersistentStoreIntegrationsBetaApi.md#createbigsegmentstoreintegration) | **Post** /api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey} | Create big segment store integration +*PersistentStoreIntegrationsBetaApi* | [**DeleteBigSegmentStoreIntegration**](docs/PersistentStoreIntegrationsBetaApi.md#deletebigsegmentstoreintegration) | **Delete** /api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId} | Delete big segment store integration +*PersistentStoreIntegrationsBetaApi* | [**GetBigSegmentStoreIntegration**](docs/PersistentStoreIntegrationsBetaApi.md#getbigsegmentstoreintegration) | **Get** /api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId} | Get big segment store integration by ID +*PersistentStoreIntegrationsBetaApi* | [**GetBigSegmentStoreIntegrations**](docs/PersistentStoreIntegrationsBetaApi.md#getbigsegmentstoreintegrations) | **Get** /api/v2/integration-capabilities/big-segment-store | List all big segment store integrations +*PersistentStoreIntegrationsBetaApi* | [**PatchBigSegmentStoreIntegration**](docs/PersistentStoreIntegrationsBetaApi.md#patchbigsegmentstoreintegration) | **Patch** /api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId} | Update big segment store integration +*ProjectsApi* | [**DeleteProject**](docs/ProjectsApi.md#deleteproject) | **Delete** /api/v2/projects/{projectKey} | Delete project +*ProjectsApi* | [**GetFlagDefaultsByProject**](docs/ProjectsApi.md#getflagdefaultsbyproject) | **Get** /api/v2/projects/{projectKey}/flag-defaults | Get flag defaults for project +*ProjectsApi* | [**GetProject**](docs/ProjectsApi.md#getproject) | **Get** /api/v2/projects/{projectKey} | Get project +*ProjectsApi* | [**GetProjects**](docs/ProjectsApi.md#getprojects) | **Get** /api/v2/projects | List projects +*ProjectsApi* | [**PatchFlagDefaultsByProject**](docs/ProjectsApi.md#patchflagdefaultsbyproject) | **Patch** /api/v2/projects/{projectKey}/flag-defaults | Update flag default for project +*ProjectsApi* | [**PatchProject**](docs/ProjectsApi.md#patchproject) | **Patch** /api/v2/projects/{projectKey} | Update project +*ProjectsApi* | [**PostProject**](docs/ProjectsApi.md#postproject) | **Post** /api/v2/projects | Create project +*ProjectsApi* | [**PutFlagDefaultsByProject**](docs/ProjectsApi.md#putflagdefaultsbyproject) | **Put** /api/v2/projects/{projectKey}/flag-defaults | Create or update flag defaults for project +*RelayProxyConfigurationsApi* | [**DeleteRelayAutoConfig**](docs/RelayProxyConfigurationsApi.md#deleterelayautoconfig) | **Delete** /api/v2/account/relay-auto-configs/{id} | Delete Relay Proxy config by ID +*RelayProxyConfigurationsApi* | [**GetRelayProxyConfig**](docs/RelayProxyConfigurationsApi.md#getrelayproxyconfig) | **Get** /api/v2/account/relay-auto-configs/{id} | Get Relay Proxy config +*RelayProxyConfigurationsApi* | [**GetRelayProxyConfigs**](docs/RelayProxyConfigurationsApi.md#getrelayproxyconfigs) | **Get** /api/v2/account/relay-auto-configs | List Relay Proxy configs +*RelayProxyConfigurationsApi* | [**PatchRelayAutoConfig**](docs/RelayProxyConfigurationsApi.md#patchrelayautoconfig) | **Patch** /api/v2/account/relay-auto-configs/{id} | Update a Relay Proxy config +*RelayProxyConfigurationsApi* | [**PostRelayAutoConfig**](docs/RelayProxyConfigurationsApi.md#postrelayautoconfig) | **Post** /api/v2/account/relay-auto-configs | Create a new Relay Proxy config +*RelayProxyConfigurationsApi* | [**ResetRelayAutoConfig**](docs/RelayProxyConfigurationsApi.md#resetrelayautoconfig) | **Post** /api/v2/account/relay-auto-configs/{id}/reset | Reset Relay Proxy configuration key +*ReleasePipelinesBetaApi* | [**DeleteReleasePipeline**](docs/ReleasePipelinesBetaApi.md#deletereleasepipeline) | **Delete** /api/v2/projects/{projectKey}/release-pipelines/{pipelineKey} | Delete release pipeline +*ReleasePipelinesBetaApi* | [**GetAllReleasePipelines**](docs/ReleasePipelinesBetaApi.md#getallreleasepipelines) | **Get** /api/v2/projects/{projectKey}/release-pipelines | Get all release pipelines +*ReleasePipelinesBetaApi* | [**GetAllReleaseProgressionsForReleasePipeline**](docs/ReleasePipelinesBetaApi.md#getallreleaseprogressionsforreleasepipeline) | **Get** /api/v2/projects/{projectKey}/release-pipelines/{pipelineKey}/releases | Get release progressions for release pipeline +*ReleasePipelinesBetaApi* | [**GetReleasePipelineByKey**](docs/ReleasePipelinesBetaApi.md#getreleasepipelinebykey) | **Get** /api/v2/projects/{projectKey}/release-pipelines/{pipelineKey} | Get release pipeline by key +*ReleasePipelinesBetaApi* | [**PostReleasePipeline**](docs/ReleasePipelinesBetaApi.md#postreleasepipeline) | **Post** /api/v2/projects/{projectKey}/release-pipelines | Create a release pipeline +*ReleasePipelinesBetaApi* | [**PutReleasePipeline**](docs/ReleasePipelinesBetaApi.md#putreleasepipeline) | **Put** /api/v2/projects/{projectKey}/release-pipelines/{pipelineKey} | Update a release pipeline +*ReleasesBetaApi* | [**CreateReleaseForFlag**](docs/ReleasesBetaApi.md#createreleaseforflag) | **Put** /api/v2/projects/{projectKey}/flags/{flagKey}/release | Create a new release for flag +*ReleasesBetaApi* | [**DeleteReleaseByFlagKey**](docs/ReleasesBetaApi.md#deletereleasebyflagkey) | **Delete** /api/v2/flags/{projectKey}/{flagKey}/release | Delete a release for flag +*ReleasesBetaApi* | [**GetReleaseByFlagKey**](docs/ReleasesBetaApi.md#getreleasebyflagkey) | **Get** /api/v2/flags/{projectKey}/{flagKey}/release | Get release for flag +*ReleasesBetaApi* | [**PatchReleaseByFlagKey**](docs/ReleasesBetaApi.md#patchreleasebyflagkey) | **Patch** /api/v2/flags/{projectKey}/{flagKey}/release | Patch release for flag +*ReleasesBetaApi* | [**UpdatePhaseStatus**](docs/ReleasesBetaApi.md#updatephasestatus) | **Put** /api/v2/projects/{projectKey}/flags/{flagKey}/release/phases/{phaseId} | Update phase status for release +*ScheduledChangesApi* | [**DeleteFlagConfigScheduledChanges**](docs/ScheduledChangesApi.md#deleteflagconfigscheduledchanges) | **Delete** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id} | Delete scheduled changes workflow +*ScheduledChangesApi* | [**GetFeatureFlagScheduledChange**](docs/ScheduledChangesApi.md#getfeatureflagscheduledchange) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id} | Get a scheduled change +*ScheduledChangesApi* | [**GetFlagConfigScheduledChanges**](docs/ScheduledChangesApi.md#getflagconfigscheduledchanges) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes | List scheduled changes +*ScheduledChangesApi* | [**PatchFlagConfigScheduledChange**](docs/ScheduledChangesApi.md#patchflagconfigscheduledchange) | **Patch** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id} | Update scheduled changes workflow +*ScheduledChangesApi* | [**PostFlagConfigScheduledChanges**](docs/ScheduledChangesApi.md#postflagconfigscheduledchanges) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes | Create scheduled changes workflow +*SegmentsApi* | [**CreateBigSegmentExport**](docs/SegmentsApi.md#createbigsegmentexport) | **Post** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/exports | Create big segment export +*SegmentsApi* | [**CreateBigSegmentImport**](docs/SegmentsApi.md#createbigsegmentimport) | **Post** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/imports | Create big segment import +*SegmentsApi* | [**DeleteSegment**](docs/SegmentsApi.md#deletesegment) | **Delete** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey} | Delete segment +*SegmentsApi* | [**GetBigSegmentExport**](docs/SegmentsApi.md#getbigsegmentexport) | **Get** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/exports/{exportID} | Get big segment export +*SegmentsApi* | [**GetBigSegmentImport**](docs/SegmentsApi.md#getbigsegmentimport) | **Get** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/imports/{importID} | Get big segment import +*SegmentsApi* | [**GetContextInstanceSegmentsMembershipByEnv**](docs/SegmentsApi.md#getcontextinstancesegmentsmembershipbyenv) | **Post** /api/v2/projects/{projectKey}/environments/{environmentKey}/segments/evaluate | List segment memberships for context instance +*SegmentsApi* | [**GetExpiringTargetsForSegment**](docs/SegmentsApi.md#getexpiringtargetsforsegment) | **Get** /api/v2/segments/{projectKey}/{segmentKey}/expiring-targets/{environmentKey} | Get expiring targets for segment +*SegmentsApi* | [**GetExpiringUserTargetsForSegment**](docs/SegmentsApi.md#getexpiringusertargetsforsegment) | **Get** /api/v2/segments/{projectKey}/{segmentKey}/expiring-user-targets/{environmentKey} | Get expiring user targets for segment +*SegmentsApi* | [**GetSegment**](docs/SegmentsApi.md#getsegment) | **Get** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey} | Get segment +*SegmentsApi* | [**GetSegmentMembershipForContext**](docs/SegmentsApi.md#getsegmentmembershipforcontext) | **Get** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/contexts/{contextKey} | Get big segment membership for context +*SegmentsApi* | [**GetSegmentMembershipForUser**](docs/SegmentsApi.md#getsegmentmembershipforuser) | **Get** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/users/{userKey} | Get big segment membership for user +*SegmentsApi* | [**GetSegments**](docs/SegmentsApi.md#getsegments) | **Get** /api/v2/segments/{projectKey}/{environmentKey} | List segments +*SegmentsApi* | [**PatchExpiringTargetsForSegment**](docs/SegmentsApi.md#patchexpiringtargetsforsegment) | **Patch** /api/v2/segments/{projectKey}/{segmentKey}/expiring-targets/{environmentKey} | Update expiring targets for segment +*SegmentsApi* | [**PatchExpiringUserTargetsForSegment**](docs/SegmentsApi.md#patchexpiringusertargetsforsegment) | **Patch** /api/v2/segments/{projectKey}/{segmentKey}/expiring-user-targets/{environmentKey} | Update expiring user targets for segment +*SegmentsApi* | [**PatchSegment**](docs/SegmentsApi.md#patchsegment) | **Patch** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey} | Patch segment +*SegmentsApi* | [**PostSegment**](docs/SegmentsApi.md#postsegment) | **Post** /api/v2/segments/{projectKey}/{environmentKey} | Create segment +*SegmentsApi* | [**UpdateBigSegmentContextTargets**](docs/SegmentsApi.md#updatebigsegmentcontexttargets) | **Post** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/contexts | Update context targets on a big segment +*SegmentsApi* | [**UpdateBigSegmentTargets**](docs/SegmentsApi.md#updatebigsegmenttargets) | **Post** /api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/users | Update user context targets on a big segment +*TagsApi* | [**GetTags**](docs/TagsApi.md#gettags) | **Get** /api/v2/tags | List tags +*TeamsApi* | [**DeleteTeam**](docs/TeamsApi.md#deleteteam) | **Delete** /api/v2/teams/{teamKey} | Delete team +*TeamsApi* | [**GetTeam**](docs/TeamsApi.md#getteam) | **Get** /api/v2/teams/{teamKey} | Get team +*TeamsApi* | [**GetTeamMaintainers**](docs/TeamsApi.md#getteammaintainers) | **Get** /api/v2/teams/{teamKey}/maintainers | Get team maintainers +*TeamsApi* | [**GetTeamRoles**](docs/TeamsApi.md#getteamroles) | **Get** /api/v2/teams/{teamKey}/roles | Get team custom roles +*TeamsApi* | [**GetTeams**](docs/TeamsApi.md#getteams) | **Get** /api/v2/teams | List teams +*TeamsApi* | [**PatchTeam**](docs/TeamsApi.md#patchteam) | **Patch** /api/v2/teams/{teamKey} | Update team +*TeamsApi* | [**PostTeam**](docs/TeamsApi.md#postteam) | **Post** /api/v2/teams | Create team +*TeamsApi* | [**PostTeamMembers**](docs/TeamsApi.md#postteammembers) | **Post** /api/v2/teams/{teamKey}/members | Add multiple members to team +*TeamsBetaApi* | [**PatchTeams**](docs/TeamsBetaApi.md#patchteams) | **Patch** /api/v2/teams | Update teams +*UserSettingsApi* | [**GetExpiringFlagsForUser**](docs/UserSettingsApi.md#getexpiringflagsforuser) | **Get** /api/v2/users/{projectKey}/{userKey}/expiring-user-targets/{environmentKey} | Get expiring dates on flags for user +*UserSettingsApi* | [**GetUserFlagSetting**](docs/UserSettingsApi.md#getuserflagsetting) | **Get** /api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags/{featureFlagKey} | Get flag setting for user +*UserSettingsApi* | [**GetUserFlagSettings**](docs/UserSettingsApi.md#getuserflagsettings) | **Get** /api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags | List flag settings for user +*UserSettingsApi* | [**PatchExpiringFlagsForUser**](docs/UserSettingsApi.md#patchexpiringflagsforuser) | **Patch** /api/v2/users/{projectKey}/{userKey}/expiring-user-targets/{environmentKey} | Update expiring user target for flags +*UserSettingsApi* | [**PutFlagSetting**](docs/UserSettingsApi.md#putflagsetting) | **Put** /api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags/{featureFlagKey} | Update flag settings for user +*UsersApi* | [**DeleteUser**](docs/UsersApi.md#deleteuser) | **Delete** /api/v2/users/{projectKey}/{environmentKey}/{userKey} | Delete user +*UsersApi* | [**GetSearchUsers**](docs/UsersApi.md#getsearchusers) | **Get** /api/v2/user-search/{projectKey}/{environmentKey} | Find users +*UsersApi* | [**GetUser**](docs/UsersApi.md#getuser) | **Get** /api/v2/users/{projectKey}/{environmentKey}/{userKey} | Get user +*UsersApi* | [**GetUsers**](docs/UsersApi.md#getusers) | **Get** /api/v2/users/{projectKey}/{environmentKey} | List users +*UsersBetaApi* | [**GetUserAttributeNames**](docs/UsersBetaApi.md#getuserattributenames) | **Get** /api/v2/user-attributes/{projectKey}/{environmentKey} | Get user attribute names +*WebhooksApi* | [**DeleteWebhook**](docs/WebhooksApi.md#deletewebhook) | **Delete** /api/v2/webhooks/{id} | Delete webhook +*WebhooksApi* | [**GetAllWebhooks**](docs/WebhooksApi.md#getallwebhooks) | **Get** /api/v2/webhooks | List webhooks +*WebhooksApi* | [**GetWebhook**](docs/WebhooksApi.md#getwebhook) | **Get** /api/v2/webhooks/{id} | Get webhook +*WebhooksApi* | [**PatchWebhook**](docs/WebhooksApi.md#patchwebhook) | **Patch** /api/v2/webhooks/{id} | Update webhook +*WebhooksApi* | [**PostWebhook**](docs/WebhooksApi.md#postwebhook) | **Post** /api/v2/webhooks | Creates a webhook +*WorkflowTemplatesApi* | [**CreateWorkflowTemplate**](docs/WorkflowTemplatesApi.md#createworkflowtemplate) | **Post** /api/v2/templates | Create workflow template +*WorkflowTemplatesApi* | [**DeleteWorkflowTemplate**](docs/WorkflowTemplatesApi.md#deleteworkflowtemplate) | **Delete** /api/v2/templates/{templateKey} | Delete workflow template +*WorkflowTemplatesApi* | [**GetWorkflowTemplates**](docs/WorkflowTemplatesApi.md#getworkflowtemplates) | **Get** /api/v2/templates | Get workflow templates +*WorkflowsApi* | [**DeleteWorkflow**](docs/WorkflowsApi.md#deleteworkflow) | **Delete** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows/{workflowId} | Delete workflow +*WorkflowsApi* | [**GetCustomWorkflow**](docs/WorkflowsApi.md#getcustomworkflow) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows/{workflowId} | Get custom workflow +*WorkflowsApi* | [**GetWorkflows**](docs/WorkflowsApi.md#getworkflows) | **Get** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows | Get workflows +*WorkflowsApi* | [**PostWorkflow**](docs/WorkflowsApi.md#postworkflow) | **Post** /api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows | Create workflow + + +## Documentation For Models + + - [AIConfig](docs/AIConfig.md) + - [AIConfigMaintainer](docs/AIConfigMaintainer.md) + - [AIConfigPatch](docs/AIConfigPatch.md) + - [AIConfigPost](docs/AIConfigPost.md) + - [AIConfigVariation](docs/AIConfigVariation.md) + - [AIConfigVariationPatch](docs/AIConfigVariationPatch.md) + - [AIConfigVariationPost](docs/AIConfigVariationPost.md) + - [AIConfigVariationsResponse](docs/AIConfigVariationsResponse.md) + - [AIConfigs](docs/AIConfigs.md) + - [Access](docs/Access.md) + - [AccessAllowedReason](docs/AccessAllowedReason.md) + - [AccessAllowedRep](docs/AccessAllowedRep.md) + - [AccessDenied](docs/AccessDenied.md) + - [AccessDeniedReason](docs/AccessDeniedReason.md) + - [AccessTokenPost](docs/AccessTokenPost.md) + - [ActionInput](docs/ActionInput.md) + - [ActionOutput](docs/ActionOutput.md) + - [AiConfigsAccess](docs/AiConfigsAccess.md) + - [AiConfigsAccessAllowedReason](docs/AiConfigsAccessAllowedReason.md) + - [AiConfigsAccessAllowedRep](docs/AiConfigsAccessAllowedRep.md) + - [AiConfigsAccessDenied](docs/AiConfigsAccessDenied.md) + - [AiConfigsAccessDeniedReason](docs/AiConfigsAccessDeniedReason.md) + - [AiConfigsLink](docs/AiConfigsLink.md) + - [AiConfigsMaintainerTeam](docs/AiConfigsMaintainerTeam.md) + - [AnnouncementAccess](docs/AnnouncementAccess.md) + - [AnnouncementAccessAllowedReason](docs/AnnouncementAccessAllowedReason.md) + - [AnnouncementAccessAllowedRep](docs/AnnouncementAccessAllowedRep.md) + - [AnnouncementAccessDenied](docs/AnnouncementAccessDenied.md) + - [AnnouncementAccessDeniedReason](docs/AnnouncementAccessDeniedReason.md) + - [AnnouncementAccessRep](docs/AnnouncementAccessRep.md) + - [AnnouncementLink](docs/AnnouncementLink.md) + - [AnnouncementPaginatedLinks](docs/AnnouncementPaginatedLinks.md) + - [AnnouncementPatchOperation](docs/AnnouncementPatchOperation.md) + - [AnnouncementResponse](docs/AnnouncementResponse.md) + - [AnnouncementResponseLinks](docs/AnnouncementResponseLinks.md) + - [ApplicationCollectionRep](docs/ApplicationCollectionRep.md) + - [ApplicationFlagCollectionRep](docs/ApplicationFlagCollectionRep.md) + - [ApplicationRep](docs/ApplicationRep.md) + - [ApplicationVersionRep](docs/ApplicationVersionRep.md) + - [ApplicationVersionsCollectionRep](docs/ApplicationVersionsCollectionRep.md) + - [ApprovalRequestResponse](docs/ApprovalRequestResponse.md) + - [ApprovalSettings](docs/ApprovalSettings.md) + - [ApprovalsCapabilityConfig](docs/ApprovalsCapabilityConfig.md) + - [AssignedToRep](docs/AssignedToRep.md) + - [Audience](docs/Audience.md) + - [AudienceConfiguration](docs/AudienceConfiguration.md) + - [AudiencePost](docs/AudiencePost.md) + - [AuditLogEntryListingRep](docs/AuditLogEntryListingRep.md) + - [AuditLogEntryListingRepCollection](docs/AuditLogEntryListingRepCollection.md) + - [AuditLogEntryRep](docs/AuditLogEntryRep.md) + - [AuditLogEventsHookCapabilityConfigPost](docs/AuditLogEventsHookCapabilityConfigPost.md) + - [AuditLogEventsHookCapabilityConfigRep](docs/AuditLogEventsHookCapabilityConfigRep.md) + - [AuthorizedAppDataRep](docs/AuthorizedAppDataRep.md) + - [BayesianBetaBinomialStatsRep](docs/BayesianBetaBinomialStatsRep.md) + - [BayesianNormalStatsRep](docs/BayesianNormalStatsRep.md) + - [BigSegmentStoreIntegration](docs/BigSegmentStoreIntegration.md) + - [BigSegmentStoreIntegrationCollection](docs/BigSegmentStoreIntegrationCollection.md) + - [BigSegmentStoreIntegrationCollectionLinks](docs/BigSegmentStoreIntegrationCollectionLinks.md) + - [BigSegmentStoreIntegrationLinks](docs/BigSegmentStoreIntegrationLinks.md) + - [BigSegmentStoreStatus](docs/BigSegmentStoreStatus.md) + - [BigSegmentTarget](docs/BigSegmentTarget.md) + - [BooleanDefaults](docs/BooleanDefaults.md) + - [BooleanFlagDefaults](docs/BooleanFlagDefaults.md) + - [BranchCollectionRep](docs/BranchCollectionRep.md) + - [BranchRep](docs/BranchRep.md) + - [BulkEditMembersRep](docs/BulkEditMembersRep.md) + - [BulkEditTeamsRep](docs/BulkEditTeamsRep.md) + - [CallerIdentityRep](docs/CallerIdentityRep.md) + - [CapabilityConfigPost](docs/CapabilityConfigPost.md) + - [CapabilityConfigRep](docs/CapabilityConfigRep.md) + - [Clause](docs/Clause.md) + - [Client](docs/Client.md) + - [ClientCollection](docs/ClientCollection.md) + - [ClientSideAvailability](docs/ClientSideAvailability.md) + - [ClientSideAvailabilityPost](docs/ClientSideAvailabilityPost.md) + - [CompletedBy](docs/CompletedBy.md) + - [ConditionInput](docs/ConditionInput.md) + - [ConditionOutput](docs/ConditionOutput.md) + - [Conflict](docs/Conflict.md) + - [ConflictOutput](docs/ConflictOutput.md) + - [ContextAttributeName](docs/ContextAttributeName.md) + - [ContextAttributeNames](docs/ContextAttributeNames.md) + - [ContextAttributeNamesCollection](docs/ContextAttributeNamesCollection.md) + - [ContextAttributeValue](docs/ContextAttributeValue.md) + - [ContextAttributeValues](docs/ContextAttributeValues.md) + - [ContextAttributeValuesCollection](docs/ContextAttributeValuesCollection.md) + - [ContextInstanceEvaluation](docs/ContextInstanceEvaluation.md) + - [ContextInstanceEvaluationReason](docs/ContextInstanceEvaluationReason.md) + - [ContextInstanceEvaluations](docs/ContextInstanceEvaluations.md) + - [ContextInstanceRecord](docs/ContextInstanceRecord.md) + - [ContextInstanceSearch](docs/ContextInstanceSearch.md) + - [ContextInstanceSegmentMembership](docs/ContextInstanceSegmentMembership.md) + - [ContextInstanceSegmentMemberships](docs/ContextInstanceSegmentMemberships.md) + - [ContextInstances](docs/ContextInstances.md) + - [ContextKindRep](docs/ContextKindRep.md) + - [ContextKindsCollectionRep](docs/ContextKindsCollectionRep.md) + - [ContextRecord](docs/ContextRecord.md) + - [ContextSearch](docs/ContextSearch.md) + - [Contexts](docs/Contexts.md) + - [CopiedFromEnv](docs/CopiedFromEnv.md) + - [CoreLink](docs/CoreLink.md) + - [CreateAnnouncementBody](docs/CreateAnnouncementBody.md) + - [CreateApprovalRequestRequest](docs/CreateApprovalRequestRequest.md) + - [CreateCopyFlagConfigApprovalRequestRequest](docs/CreateCopyFlagConfigApprovalRequestRequest.md) + - [CreateFlagConfigApprovalRequestRequest](docs/CreateFlagConfigApprovalRequestRequest.md) + - [CreatePhaseInput](docs/CreatePhaseInput.md) + - [CreateReleaseInput](docs/CreateReleaseInput.md) + - [CreateReleasePipelineInput](docs/CreateReleasePipelineInput.md) + - [CreateWorkflowTemplateInput](docs/CreateWorkflowTemplateInput.md) + - [CredibleIntervalRep](docs/CredibleIntervalRep.md) + - [CustomProperty](docs/CustomProperty.md) + - [CustomRole](docs/CustomRole.md) + - [CustomRolePost](docs/CustomRolePost.md) + - [CustomRoles](docs/CustomRoles.md) + - [CustomWorkflowInput](docs/CustomWorkflowInput.md) + - [CustomWorkflowMeta](docs/CustomWorkflowMeta.md) + - [CustomWorkflowOutput](docs/CustomWorkflowOutput.md) + - [CustomWorkflowStageMeta](docs/CustomWorkflowStageMeta.md) + - [CustomWorkflowsListingOutput](docs/CustomWorkflowsListingOutput.md) + - [DefaultClientSideAvailability](docs/DefaultClientSideAvailability.md) + - [DefaultClientSideAvailabilityPost](docs/DefaultClientSideAvailabilityPost.md) + - [Defaults](docs/Defaults.md) + - [DependentExperimentRep](docs/DependentExperimentRep.md) + - [DependentFlag](docs/DependentFlag.md) + - [DependentFlagEnvironment](docs/DependentFlagEnvironment.md) + - [DependentFlagsByEnvironment](docs/DependentFlagsByEnvironment.md) + - [DependentMetricGroupRep](docs/DependentMetricGroupRep.md) + - [DependentMetricGroupRepWithMetrics](docs/DependentMetricGroupRepWithMetrics.md) + - [DependentMetricOrMetricGroupRep](docs/DependentMetricOrMetricGroupRep.md) + - [DeploymentCollectionRep](docs/DeploymentCollectionRep.md) + - [DeploymentRep](docs/DeploymentRep.md) + - [Destination](docs/Destination.md) + - [DestinationPost](docs/DestinationPost.md) + - [Destinations](docs/Destinations.md) + - [Distribution](docs/Distribution.md) + - [DynamicOptions](docs/DynamicOptions.md) + - [DynamicOptionsParser](docs/DynamicOptionsParser.md) + - [Endpoint](docs/Endpoint.md) + - [Environment](docs/Environment.md) + - [EnvironmentPost](docs/EnvironmentPost.md) + - [EnvironmentSummary](docs/EnvironmentSummary.md) + - [Environments](docs/Environments.md) + - [Error](docs/Error.md) + - [EvaluationReason](docs/EvaluationReason.md) + - [EvaluationsSummary](docs/EvaluationsSummary.md) + - [ExecutionOutput](docs/ExecutionOutput.md) + - [ExpandableApprovalRequestResponse](docs/ExpandableApprovalRequestResponse.md) + - [ExpandableApprovalRequestsResponse](docs/ExpandableApprovalRequestsResponse.md) + - [ExpandedFlagRep](docs/ExpandedFlagRep.md) + - [ExpandedResourceRep](docs/ExpandedResourceRep.md) + - [Experiment](docs/Experiment.md) + - [ExperimentAllocationRep](docs/ExperimentAllocationRep.md) + - [ExperimentBayesianResultsRep](docs/ExperimentBayesianResultsRep.md) + - [ExperimentCollectionRep](docs/ExperimentCollectionRep.md) + - [ExperimentEnabledPeriodRep](docs/ExperimentEnabledPeriodRep.md) + - [ExperimentEnvironmentSettingRep](docs/ExperimentEnvironmentSettingRep.md) + - [ExperimentInfoRep](docs/ExperimentInfoRep.md) + - [ExperimentPatchInput](docs/ExperimentPatchInput.md) + - [ExperimentPost](docs/ExperimentPost.md) + - [ExpiringTarget](docs/ExpiringTarget.md) + - [ExpiringTargetError](docs/ExpiringTargetError.md) + - [ExpiringTargetGetResponse](docs/ExpiringTargetGetResponse.md) + - [ExpiringTargetPatchResponse](docs/ExpiringTargetPatchResponse.md) + - [ExpiringUserTargetGetResponse](docs/ExpiringUserTargetGetResponse.md) + - [ExpiringUserTargetItem](docs/ExpiringUserTargetItem.md) + - [ExpiringUserTargetPatchResponse](docs/ExpiringUserTargetPatchResponse.md) + - [Export](docs/Export.md) + - [Extinction](docs/Extinction.md) + - [ExtinctionCollectionRep](docs/ExtinctionCollectionRep.md) + - [FailureReasonRep](docs/FailureReasonRep.md) + - [FeatureFlag](docs/FeatureFlag.md) + - [FeatureFlagBody](docs/FeatureFlagBody.md) + - [FeatureFlagConfig](docs/FeatureFlagConfig.md) + - [FeatureFlagScheduledChange](docs/FeatureFlagScheduledChange.md) + - [FeatureFlagScheduledChanges](docs/FeatureFlagScheduledChanges.md) + - [FeatureFlagStatus](docs/FeatureFlagStatus.md) + - [FeatureFlagStatusAcrossEnvironments](docs/FeatureFlagStatusAcrossEnvironments.md) + - [FeatureFlagStatuses](docs/FeatureFlagStatuses.md) + - [FeatureFlags](docs/FeatureFlags.md) + - [FileRep](docs/FileRep.md) + - [FlagConfigApprovalRequestResponse](docs/FlagConfigApprovalRequestResponse.md) + - [FlagConfigApprovalRequestsResponse](docs/FlagConfigApprovalRequestsResponse.md) + - [FlagConfigEvaluation](docs/FlagConfigEvaluation.md) + - [FlagConfigMigrationSettingsRep](docs/FlagConfigMigrationSettingsRep.md) + - [FlagCopyConfigEnvironment](docs/FlagCopyConfigEnvironment.md) + - [FlagCopyConfigPost](docs/FlagCopyConfigPost.md) + - [FlagDefaultsRep](docs/FlagDefaultsRep.md) + - [FlagEventCollectionRep](docs/FlagEventCollectionRep.md) + - [FlagEventExperiment](docs/FlagEventExperiment.md) + - [FlagEventExperimentCollection](docs/FlagEventExperimentCollection.md) + - [FlagEventExperimentIteration](docs/FlagEventExperimentIteration.md) + - [FlagEventImpactRep](docs/FlagEventImpactRep.md) + - [FlagEventMemberRep](docs/FlagEventMemberRep.md) + - [FlagEventRep](docs/FlagEventRep.md) + - [FlagFollowersByProjEnvGetRep](docs/FlagFollowersByProjEnvGetRep.md) + - [FlagFollowersGetRep](docs/FlagFollowersGetRep.md) + - [FlagImportConfigurationPost](docs/FlagImportConfigurationPost.md) + - [FlagImportIntegration](docs/FlagImportIntegration.md) + - [FlagImportIntegrationCollection](docs/FlagImportIntegrationCollection.md) + - [FlagImportIntegrationCollectionLinks](docs/FlagImportIntegrationCollectionLinks.md) + - [FlagImportIntegrationLinks](docs/FlagImportIntegrationLinks.md) + - [FlagImportStatus](docs/FlagImportStatus.md) + - [FlagInput](docs/FlagInput.md) + - [FlagLinkCollectionRep](docs/FlagLinkCollectionRep.md) + - [FlagLinkMember](docs/FlagLinkMember.md) + - [FlagLinkPost](docs/FlagLinkPost.md) + - [FlagLinkRep](docs/FlagLinkRep.md) + - [FlagListingRep](docs/FlagListingRep.md) + - [FlagMigrationSettingsRep](docs/FlagMigrationSettingsRep.md) + - [FlagPrerequisitePost](docs/FlagPrerequisitePost.md) + - [FlagReferenceCollectionRep](docs/FlagReferenceCollectionRep.md) + - [FlagReferenceRep](docs/FlagReferenceRep.md) + - [FlagRep](docs/FlagRep.md) + - [FlagScheduledChangesInput](docs/FlagScheduledChangesInput.md) + - [FlagSempatch](docs/FlagSempatch.md) + - [FlagStatusRep](docs/FlagStatusRep.md) + - [FlagSummary](docs/FlagSummary.md) + - [FlagTriggerInput](docs/FlagTriggerInput.md) + - [FollowFlagMember](docs/FollowFlagMember.md) + - [FollowersPerFlag](docs/FollowersPerFlag.md) + - [ForbiddenErrorRep](docs/ForbiddenErrorRep.md) + - [FormVariable](docs/FormVariable.md) + - [GenerateWarehouseDestinationKeyPairPostRep](docs/GenerateWarehouseDestinationKeyPairPostRep.md) + - [GetAnnouncementsPublic200Response](docs/GetAnnouncementsPublic200Response.md) + - [HMACSignature](docs/HMACSignature.md) + - [HeaderItems](docs/HeaderItems.md) + - [HoldoutDetailRep](docs/HoldoutDetailRep.md) + - [HoldoutPatchInput](docs/HoldoutPatchInput.md) + - [HoldoutPostRequest](docs/HoldoutPostRequest.md) + - [HoldoutRep](docs/HoldoutRep.md) + - [HoldoutsCollectionRep](docs/HoldoutsCollectionRep.md) + - [HunkRep](docs/HunkRep.md) + - [Import](docs/Import.md) + - [InitiatorRep](docs/InitiatorRep.md) + - [InsightGroup](docs/InsightGroup.md) + - [InsightGroupCollection](docs/InsightGroupCollection.md) + - [InsightGroupCollectionMetadata](docs/InsightGroupCollectionMetadata.md) + - [InsightGroupCollectionScoreMetadata](docs/InsightGroupCollectionScoreMetadata.md) + - [InsightGroupScores](docs/InsightGroupScores.md) + - [InsightGroupsCountByIndicator](docs/InsightGroupsCountByIndicator.md) + - [InsightPeriod](docs/InsightPeriod.md) + - [InsightScores](docs/InsightScores.md) + - [InsightsChart](docs/InsightsChart.md) + - [InsightsChartBounds](docs/InsightsChartBounds.md) + - [InsightsChartMetadata](docs/InsightsChartMetadata.md) + - [InsightsChartMetric](docs/InsightsChartMetric.md) + - [InsightsChartSeries](docs/InsightsChartSeries.md) + - [InsightsChartSeriesDataPoint](docs/InsightsChartSeriesDataPoint.md) + - [InsightsChartSeriesMetadata](docs/InsightsChartSeriesMetadata.md) + - [InsightsChartSeriesMetadataAxis](docs/InsightsChartSeriesMetadataAxis.md) + - [InsightsMetricIndicatorRange](docs/InsightsMetricIndicatorRange.md) + - [InsightsMetricScore](docs/InsightsMetricScore.md) + - [InsightsMetricTierDefinition](docs/InsightsMetricTierDefinition.md) + - [InsightsRepository](docs/InsightsRepository.md) + - [InsightsRepositoryCollection](docs/InsightsRepositoryCollection.md) + - [InsightsRepositoryProject](docs/InsightsRepositoryProject.md) + - [InsightsRepositoryProjectCollection](docs/InsightsRepositoryProjectCollection.md) + - [InsightsRepositoryProjectMappings](docs/InsightsRepositoryProjectMappings.md) + - [InstructionUserRequest](docs/InstructionUserRequest.md) + - [Integration](docs/Integration.md) + - [IntegrationConfigurationCollectionRep](docs/IntegrationConfigurationCollectionRep.md) + - [IntegrationConfigurationPost](docs/IntegrationConfigurationPost.md) + - [IntegrationConfigurationsRep](docs/IntegrationConfigurationsRep.md) + - [IntegrationDeliveryConfiguration](docs/IntegrationDeliveryConfiguration.md) + - [IntegrationDeliveryConfigurationCollection](docs/IntegrationDeliveryConfigurationCollection.md) + - [IntegrationDeliveryConfigurationCollectionLinks](docs/IntegrationDeliveryConfigurationCollectionLinks.md) + - [IntegrationDeliveryConfigurationLinks](docs/IntegrationDeliveryConfigurationLinks.md) + - [IntegrationDeliveryConfigurationPost](docs/IntegrationDeliveryConfigurationPost.md) + - [IntegrationDeliveryConfigurationResponse](docs/IntegrationDeliveryConfigurationResponse.md) + - [IntegrationMetadata](docs/IntegrationMetadata.md) + - [IntegrationStatus](docs/IntegrationStatus.md) + - [IntegrationStatusRep](docs/IntegrationStatusRep.md) + - [IntegrationSubscriptionStatusRep](docs/IntegrationSubscriptionStatusRep.md) + - [Integrations](docs/Integrations.md) + - [InvalidRequestErrorRep](docs/InvalidRequestErrorRep.md) + - [IpList](docs/IpList.md) + - [IterationInput](docs/IterationInput.md) + - [IterationRep](docs/IterationRep.md) + - [LastSeenMetadata](docs/LastSeenMetadata.md) + - [LayerCollectionRep](docs/LayerCollectionRep.md) + - [LayerConfigurationRep](docs/LayerConfigurationRep.md) + - [LayerPatchInput](docs/LayerPatchInput.md) + - [LayerPost](docs/LayerPost.md) + - [LayerRep](docs/LayerRep.md) + - [LayerReservationRep](docs/LayerReservationRep.md) + - [LayerSnapshotRep](docs/LayerSnapshotRep.md) + - [LeadTimeStagesRep](docs/LeadTimeStagesRep.md) + - [LegacyExperimentRep](docs/LegacyExperimentRep.md) + - [Link](docs/Link.md) + - [MaintainerMember](docs/MaintainerMember.md) + - [MaintainerRep](docs/MaintainerRep.md) + - [MaintainerTeam](docs/MaintainerTeam.md) + - [Member](docs/Member.md) + - [MemberDataRep](docs/MemberDataRep.md) + - [MemberImportItem](docs/MemberImportItem.md) + - [MemberPermissionGrantSummaryRep](docs/MemberPermissionGrantSummaryRep.md) + - [MemberSummary](docs/MemberSummary.md) + - [MemberTeamSummaryRep](docs/MemberTeamSummaryRep.md) + - [MemberTeamsPostInput](docs/MemberTeamsPostInput.md) + - [Members](docs/Members.md) + - [MembersPatchInput](docs/MembersPatchInput.md) + - [Message](docs/Message.md) + - [MethodNotAllowedErrorRep](docs/MethodNotAllowedErrorRep.md) + - [MetricByVariation](docs/MetricByVariation.md) + - [MetricCollectionRep](docs/MetricCollectionRep.md) + - [MetricEventDefaultRep](docs/MetricEventDefaultRep.md) + - [MetricGroupCollectionRep](docs/MetricGroupCollectionRep.md) + - [MetricGroupPost](docs/MetricGroupPost.md) + - [MetricGroupRep](docs/MetricGroupRep.md) + - [MetricGroupResultsRep](docs/MetricGroupResultsRep.md) + - [MetricInGroupRep](docs/MetricInGroupRep.md) + - [MetricInGroupResultsRep](docs/MetricInGroupResultsRep.md) + - [MetricInMetricGroupInput](docs/MetricInMetricGroupInput.md) + - [MetricInput](docs/MetricInput.md) + - [MetricListingRep](docs/MetricListingRep.md) + - [MetricPost](docs/MetricPost.md) + - [MetricRep](docs/MetricRep.md) + - [MetricSeen](docs/MetricSeen.md) + - [MetricV2Rep](docs/MetricV2Rep.md) + - [Metrics](docs/Metrics.md) + - [MigrationSafetyIssueRep](docs/MigrationSafetyIssueRep.md) + - [MigrationSettingsPost](docs/MigrationSettingsPost.md) + - [ModelConfig](docs/ModelConfig.md) + - [ModelConfigPost](docs/ModelConfigPost.md) + - [Modification](docs/Modification.md) + - [MultiEnvironmentDependentFlag](docs/MultiEnvironmentDependentFlag.md) + - [MultiEnvironmentDependentFlags](docs/MultiEnvironmentDependentFlags.md) + - [NamingConvention](docs/NamingConvention.md) + - [NewMemberForm](docs/NewMemberForm.md) + - [NotFoundErrorRep](docs/NotFoundErrorRep.md) + - [OauthClientPost](docs/OauthClientPost.md) + - [OptionsArray](docs/OptionsArray.md) + - [PaginatedLinks](docs/PaginatedLinks.md) + - [ParameterDefault](docs/ParameterDefault.md) + - [ParameterRep](docs/ParameterRep.md) + - [ParentAndSelfLinks](docs/ParentAndSelfLinks.md) + - [ParentLink](docs/ParentLink.md) + - [ParentResourceRep](docs/ParentResourceRep.md) + - [PatchFailedErrorRep](docs/PatchFailedErrorRep.md) + - [PatchFlagsRequest](docs/PatchFlagsRequest.md) + - [PatchOperation](docs/PatchOperation.md) + - [PatchSegmentExpiringTargetInputRep](docs/PatchSegmentExpiringTargetInputRep.md) + - [PatchSegmentExpiringTargetInstruction](docs/PatchSegmentExpiringTargetInstruction.md) + - [PatchSegmentInstruction](docs/PatchSegmentInstruction.md) + - [PatchSegmentRequest](docs/PatchSegmentRequest.md) + - [PatchUsersRequest](docs/PatchUsersRequest.md) + - [PatchWithComment](docs/PatchWithComment.md) + - [PermissionGrantInput](docs/PermissionGrantInput.md) + - [Phase](docs/Phase.md) + - [PhaseInfo](docs/PhaseInfo.md) + - [PostApprovalRequestApplyRequest](docs/PostApprovalRequestApplyRequest.md) + - [PostApprovalRequestReviewRequest](docs/PostApprovalRequestReviewRequest.md) + - [PostDeploymentEventInput](docs/PostDeploymentEventInput.md) + - [PostFlagScheduledChangesInput](docs/PostFlagScheduledChangesInput.md) + - [PostInsightGroupParams](docs/PostInsightGroupParams.md) + - [Prerequisite](docs/Prerequisite.md) + - [Project](docs/Project.md) + - [ProjectPost](docs/ProjectPost.md) + - [ProjectRep](docs/ProjectRep.md) + - [ProjectSummary](docs/ProjectSummary.md) + - [ProjectSummaryCollection](docs/ProjectSummaryCollection.md) + - [Projects](docs/Projects.md) + - [PullRequestCollectionRep](docs/PullRequestCollectionRep.md) + - [PullRequestLeadTimeRep](docs/PullRequestLeadTimeRep.md) + - [PullRequestRep](docs/PullRequestRep.md) + - [PutBranch](docs/PutBranch.md) + - [RandomizationSettingsPut](docs/RandomizationSettingsPut.md) + - [RandomizationSettingsRep](docs/RandomizationSettingsRep.md) + - [RandomizationUnitInput](docs/RandomizationUnitInput.md) + - [RandomizationUnitRep](docs/RandomizationUnitRep.md) + - [RateLimitedErrorRep](docs/RateLimitedErrorRep.md) + - [RecentTriggerBody](docs/RecentTriggerBody.md) + - [ReferenceRep](docs/ReferenceRep.md) + - [RelatedExperimentRep](docs/RelatedExperimentRep.md) + - [RelativeDifferenceRep](docs/RelativeDifferenceRep.md) + - [RelayAutoConfigCollectionRep](docs/RelayAutoConfigCollectionRep.md) + - [RelayAutoConfigPost](docs/RelayAutoConfigPost.md) + - [RelayAutoConfigRep](docs/RelayAutoConfigRep.md) + - [Release](docs/Release.md) + - [ReleaseAudience](docs/ReleaseAudience.md) + - [ReleaseGuardianConfiguration](docs/ReleaseGuardianConfiguration.md) + - [ReleaseGuardianConfigurationInput](docs/ReleaseGuardianConfigurationInput.md) + - [ReleasePhase](docs/ReleasePhase.md) + - [ReleasePipeline](docs/ReleasePipeline.md) + - [ReleasePipelineCollection](docs/ReleasePipelineCollection.md) + - [ReleaseProgression](docs/ReleaseProgression.md) + - [ReleaseProgressionCollection](docs/ReleaseProgressionCollection.md) + - [ReleaserAudienceConfigInput](docs/ReleaserAudienceConfigInput.md) + - [RepositoryCollectionRep](docs/RepositoryCollectionRep.md) + - [RepositoryPost](docs/RepositoryPost.md) + - [RepositoryRep](docs/RepositoryRep.md) + - [ResourceAccess](docs/ResourceAccess.md) + - [ResourceIDResponse](docs/ResourceIDResponse.md) + - [ResourceId](docs/ResourceId.md) + - [ReviewOutput](docs/ReviewOutput.md) + - [ReviewResponse](docs/ReviewResponse.md) + - [Rollout](docs/Rollout.md) + - [RootResponse](docs/RootResponse.md) + - [Rule](docs/Rule.md) + - [RuleClause](docs/RuleClause.md) + - [SdkListRep](docs/SdkListRep.md) + - [SdkVersionListRep](docs/SdkVersionListRep.md) + - [SdkVersionRep](docs/SdkVersionRep.md) + - [SegmentBody](docs/SegmentBody.md) + - [SegmentMetadata](docs/SegmentMetadata.md) + - [SegmentTarget](docs/SegmentTarget.md) + - [SegmentUserList](docs/SegmentUserList.md) + - [SegmentUserState](docs/SegmentUserState.md) + - [Series](docs/Series.md) + - [SeriesIntervalsRep](docs/SeriesIntervalsRep.md) + - [SeriesListRep](docs/SeriesListRep.md) + - [SimpleHoldoutRep](docs/SimpleHoldoutRep.md) + - [SlicedResultsRep](docs/SlicedResultsRep.md) + - [SourceEnv](docs/SourceEnv.md) + - [SourceFlag](docs/SourceFlag.md) + - [StageInput](docs/StageInput.md) + - [StageOutput](docs/StageOutput.md) + - [Statement](docs/Statement.md) + - [StatementPost](docs/StatementPost.md) + - [StatisticCollectionRep](docs/StatisticCollectionRep.md) + - [StatisticRep](docs/StatisticRep.md) + - [StatisticsRoot](docs/StatisticsRoot.md) + - [StatusConflictErrorRep](docs/StatusConflictErrorRep.md) + - [StatusResponse](docs/StatusResponse.md) + - [StatusServiceUnavailable](docs/StatusServiceUnavailable.md) + - [StoreIntegrationError](docs/StoreIntegrationError.md) + - [SubjectDataRep](docs/SubjectDataRep.md) + - [SubscriptionPost](docs/SubscriptionPost.md) + - [TagsCollection](docs/TagsCollection.md) + - [TagsLink](docs/TagsLink.md) + - [Target](docs/Target.md) + - [TargetResourceRep](docs/TargetResourceRep.md) + - [Team](docs/Team.md) + - [TeamCustomRole](docs/TeamCustomRole.md) + - [TeamCustomRoles](docs/TeamCustomRoles.md) + - [TeamImportsRep](docs/TeamImportsRep.md) + - [TeamMaintainers](docs/TeamMaintainers.md) + - [TeamMembers](docs/TeamMembers.md) + - [TeamPatchInput](docs/TeamPatchInput.md) + - [TeamPostInput](docs/TeamPostInput.md) + - [TeamProjects](docs/TeamProjects.md) + - [Teams](docs/Teams.md) + - [TeamsPatchInput](docs/TeamsPatchInput.md) + - [TimestampRep](docs/TimestampRep.md) + - [Token](docs/Token.md) + - [TokenSummary](docs/TokenSummary.md) + - [Tokens](docs/Tokens.md) + - [TreatmentInput](docs/TreatmentInput.md) + - [TreatmentParameterInput](docs/TreatmentParameterInput.md) + - [TreatmentRep](docs/TreatmentRep.md) + - [TreatmentResultRep](docs/TreatmentResultRep.md) + - [TriggerPost](docs/TriggerPost.md) + - [TriggerWorkflowCollectionRep](docs/TriggerWorkflowCollectionRep.md) + - [TriggerWorkflowRep](docs/TriggerWorkflowRep.md) + - [UnauthorizedErrorRep](docs/UnauthorizedErrorRep.md) + - [UpdatePhaseStatusInput](docs/UpdatePhaseStatusInput.md) + - [UpdateReleasePipelineInput](docs/UpdateReleasePipelineInput.md) + - [UpsertContextKindPayload](docs/UpsertContextKindPayload.md) + - [UpsertFlagDefaultsPayload](docs/UpsertFlagDefaultsPayload.md) + - [UpsertPayloadRep](docs/UpsertPayloadRep.md) + - [UpsertResponseRep](docs/UpsertResponseRep.md) + - [UrlPost](docs/UrlPost.md) + - [User](docs/User.md) + - [UserAttributeNamesRep](docs/UserAttributeNamesRep.md) + - [UserFlagSetting](docs/UserFlagSetting.md) + - [UserFlagSettings](docs/UserFlagSettings.md) + - [UserRecord](docs/UserRecord.md) + - [UserSegment](docs/UserSegment.md) + - [UserSegmentRule](docs/UserSegmentRule.md) + - [UserSegments](docs/UserSegments.md) + - [Users](docs/Users.md) + - [UsersRep](docs/UsersRep.md) + - [ValidationFailedErrorRep](docs/ValidationFailedErrorRep.md) + - [ValuePut](docs/ValuePut.md) + - [Variation](docs/Variation.md) + - [VariationEvalSummary](docs/VariationEvalSummary.md) + - [VariationOrRolloutRep](docs/VariationOrRolloutRep.md) + - [VariationSummary](docs/VariationSummary.md) + - [VersionsRep](docs/VersionsRep.md) + - [Webhook](docs/Webhook.md) + - [WebhookPost](docs/WebhookPost.md) + - [Webhooks](docs/Webhooks.md) + - [WeightedVariation](docs/WeightedVariation.md) + - [WorkflowTemplateMetadata](docs/WorkflowTemplateMetadata.md) + - [WorkflowTemplateOutput](docs/WorkflowTemplateOutput.md) + - [WorkflowTemplateParameter](docs/WorkflowTemplateParameter.md) + - [WorkflowTemplatesListingOutputRep](docs/WorkflowTemplatesListingOutputRep.md) + + +## Documentation For Authorization + + + +### ApiKey + +- **Type**: API key +- **API key parameter name**: Authorization +- **Location**: HTTP header + +Note, each API key must be added to a map of `map[string]APIKey` where the key is: Authorization and passed in as the auth context for each request. + + +## Documentation for Utility Methods + +Due to the fact that model structure members are all pointers, this package contains +a number of utility functions to easily obtain pointers to values of basic types. +Each of these functions takes a value of the given basic type and returns a pointer to it: + +* `PtrBool` +* `PtrInt` +* `PtrInt32` +* `PtrInt64` +* `PtrFloat` +* `PtrFloat32` +* `PtrFloat64` +* `PtrString` +* `PtrTime` + +## Author + +support@launchdarkly.com + +## Sample Code + +```go +package main + +import ( + "context" + "fmt" + "os" + + ldapi "github.com/launchdarkly/api-client-go" +) + +func main() { + apiKey := os.Getenv("LD_API_KEY") + if apiKey == "" { + panic("LD_API_KEY env var was empty!") + } + client := ldapi.NewAPIClient(ldapi.NewConfiguration()) + + auth := make(map[string]ldapi.APIKey) + auth["ApiKey"] = ldapi.APIKey{ + Key: apiKey, + } + + ctx := context.WithValue(context.Background(), ldapi.ContextAPIKeys, auth) + + flagName := "Test Flag Go" + flagKey := "test-go" + // Create a multi-variate feature flag + valOneVal := []int{1, 2} + valOne := map[string]interface{}{"one": valOneVal} + valTwoVal := []int{4, 5} + valTwo := map[string]interface{}{"two": valTwoVal} + + body := ldapi.FeatureFlagBody{ + Name: flagName, + Key: flagKey, + Variations: []ldapi.Variation{ + {Value: &valOne}, + {Value: &valTwo}, + }, + } + flag, resp, err := client.FeatureFlagsApi.PostFeatureFlag(ctx, "openapi").FeatureFlagBody(body).Execute() + if err != nil { + if resp.StatusCode != 409 { + panic(fmt.Errorf("create failed: %s", err)) + } else { + if _, err := client.FeatureFlagsApi.DeleteFeatureFlag(ctx, "openapi", body.Key).Execute(); err != nil { + panic(fmt.Errorf("delete failed: %s", err)) + } + flag, resp, err = client.FeatureFlagsApi.PostFeatureFlag(ctx, "openapi").FeatureFlagBody(body).Execute() + if err != nil { + panic(fmt.Errorf("create failed: %s", err)) + } + } + } + fmt.Printf("Created flag: %+v\n", flag) + // Clean up new flag + defer func() { + if _, err := client.FeatureFlagsApi.DeleteFeatureFlag(ctx, "openapi", body.Key).Execute(); err != nil { + panic(fmt.Errorf("delete failed: %s", err)) + } + }() +} + +func intfPtr(i interface{}) *interface{} { + return &i +} +``` diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_access_tokens.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_access_tokens.go new file mode 100644 index 00000000..6ad1aa05 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_access_tokens.go @@ -0,0 +1,1114 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AccessTokensApi interface { + + /* + DeleteToken Delete access token + + Delete an access token by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiDeleteTokenRequest + */ + DeleteToken(ctx context.Context, id string) ApiDeleteTokenRequest + + // DeleteTokenExecute executes the request + DeleteTokenExecute(r ApiDeleteTokenRequest) (*http.Response, error) + + /* + GetToken Get access token + + Get a single access token by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token + @return ApiGetTokenRequest + */ + GetToken(ctx context.Context, id string) ApiGetTokenRequest + + // GetTokenExecute executes the request + // @return Token + GetTokenExecute(r ApiGetTokenRequest) (*Token, *http.Response, error) + + /* + GetTokens List access tokens + + Fetch a list of all access tokens. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTokensRequest + */ + GetTokens(ctx context.Context) ApiGetTokensRequest + + // GetTokensExecute executes the request + // @return Tokens + GetTokensExecute(r ApiGetTokensRequest) (*Tokens, *http.Response, error) + + /* + PatchToken Patch access token + + Update an access token's settings. Updating an access token uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiPatchTokenRequest + */ + PatchToken(ctx context.Context, id string) ApiPatchTokenRequest + + // PatchTokenExecute executes the request + // @return Token + PatchTokenExecute(r ApiPatchTokenRequest) (*Token, *http.Response, error) + + /* + PostToken Create access token + + Create a new access token. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostTokenRequest + */ + PostToken(ctx context.Context) ApiPostTokenRequest + + // PostTokenExecute executes the request + // @return Token + PostTokenExecute(r ApiPostTokenRequest) (*Token, *http.Response, error) + + /* + ResetToken Reset access token + + Reset an access token's secret key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiResetTokenRequest + */ + ResetToken(ctx context.Context, id string) ApiResetTokenRequest + + // ResetTokenExecute executes the request + // @return Token + ResetTokenExecute(r ApiResetTokenRequest) (*Token, *http.Response, error) +} + +// AccessTokensApiService AccessTokensApi service +type AccessTokensApiService service + +type ApiDeleteTokenRequest struct { + ctx context.Context + ApiService AccessTokensApi + id string +} + +func (r ApiDeleteTokenRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteTokenExecute(r) +} + +/* +DeleteToken Delete access token + +Delete an access token by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiDeleteTokenRequest +*/ +func (a *AccessTokensApiService) DeleteToken(ctx context.Context, id string) ApiDeleteTokenRequest { + return ApiDeleteTokenRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +func (a *AccessTokensApiService) DeleteTokenExecute(r ApiDeleteTokenRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.DeleteToken") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetTokenRequest struct { + ctx context.Context + ApiService AccessTokensApi + id string +} + +func (r ApiGetTokenRequest) Execute() (*Token, *http.Response, error) { + return r.ApiService.GetTokenExecute(r) +} + +/* +GetToken Get access token + +Get a single access token by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token + @return ApiGetTokenRequest +*/ +func (a *AccessTokensApiService) GetToken(ctx context.Context, id string) ApiGetTokenRequest { + return ApiGetTokenRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Token +func (a *AccessTokensApiService) GetTokenExecute(r ApiGetTokenRequest) (*Token, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Token + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.GetToken") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetTokensRequest struct { + ctx context.Context + ApiService AccessTokensApi + showAll *bool + limit *int64 + offset *int64 +} + +// If set to true, and the authentication access token has the 'Admin' role, personal access tokens for all members will be retrieved. +func (r ApiGetTokensRequest) ShowAll(showAll bool) ApiGetTokensRequest { + r.showAll = &showAll + return r +} + +// The number of access tokens to return in the response. Defaults to 25. +func (r ApiGetTokensRequest) Limit(limit int64) ApiGetTokensRequest { + r.limit = &limit + return r +} + +// Where to start in the list. This is for use with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetTokensRequest) Offset(offset int64) ApiGetTokensRequest { + r.offset = &offset + return r +} + +func (r ApiGetTokensRequest) Execute() (*Tokens, *http.Response, error) { + return r.ApiService.GetTokensExecute(r) +} + +/* +GetTokens List access tokens + +Fetch a list of all access tokens. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTokensRequest +*/ +func (a *AccessTokensApiService) GetTokens(ctx context.Context) ApiGetTokensRequest { + return ApiGetTokensRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Tokens +func (a *AccessTokensApiService) GetTokensExecute(r ApiGetTokensRequest) (*Tokens, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Tokens + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.GetTokens") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.showAll != nil { + localVarQueryParams.Add("showAll", parameterToString(*r.showAll, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchTokenRequest struct { + ctx context.Context + ApiService AccessTokensApi + id string + patchOperation *[]PatchOperation +} + +func (r ApiPatchTokenRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchTokenRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchTokenRequest) Execute() (*Token, *http.Response, error) { + return r.ApiService.PatchTokenExecute(r) +} + +/* +PatchToken Patch access token + +Update an access token's settings. Updating an access token uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiPatchTokenRequest +*/ +func (a *AccessTokensApiService) PatchToken(ctx context.Context, id string) ApiPatchTokenRequest { + return ApiPatchTokenRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Token +func (a *AccessTokensApiService) PatchTokenExecute(r ApiPatchTokenRequest) (*Token, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Token + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.PatchToken") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 422 { + var v PatchFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostTokenRequest struct { + ctx context.Context + ApiService AccessTokensApi + accessTokenPost *AccessTokenPost +} + +func (r ApiPostTokenRequest) AccessTokenPost(accessTokenPost AccessTokenPost) ApiPostTokenRequest { + r.accessTokenPost = &accessTokenPost + return r +} + +func (r ApiPostTokenRequest) Execute() (*Token, *http.Response, error) { + return r.ApiService.PostTokenExecute(r) +} + +/* +PostToken Create access token + +Create a new access token. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostTokenRequest +*/ +func (a *AccessTokensApiService) PostToken(ctx context.Context) ApiPostTokenRequest { + return ApiPostTokenRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Token +func (a *AccessTokensApiService) PostTokenExecute(r ApiPostTokenRequest) (*Token, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Token + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.PostToken") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.accessTokenPost == nil { + return localVarReturnValue, nil, reportError("accessTokenPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.accessTokenPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiResetTokenRequest struct { + ctx context.Context + ApiService AccessTokensApi + id string + expiry *int64 +} + +// An expiration time for the old token key, expressed as a Unix epoch time in milliseconds. By default, the token will expire immediately. +func (r ApiResetTokenRequest) Expiry(expiry int64) ApiResetTokenRequest { + r.expiry = &expiry + return r +} + +func (r ApiResetTokenRequest) Execute() (*Token, *http.Response, error) { + return r.ApiService.ResetTokenExecute(r) +} + +/* +ResetToken Reset access token + +Reset an access token's secret key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the access token to update + @return ApiResetTokenRequest +*/ +func (a *AccessTokensApiService) ResetToken(ctx context.Context, id string) ApiResetTokenRequest { + return ApiResetTokenRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Token +func (a *AccessTokensApiService) ResetTokenExecute(r ApiResetTokenRequest) (*Token, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Token + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccessTokensApiService.ResetToken") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tokens/{id}/reset" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expiry != nil { + localVarQueryParams.Add("expiry", parameterToString(*r.expiry, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members.go new file mode 100644 index 00000000..8b6b4618 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members.go @@ -0,0 +1,1355 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AccountMembersApi interface { + + /* + DeleteMember Delete account member + + Delete a single account member by ID. Requests to delete account members will not work if SCIM is enabled for the account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiDeleteMemberRequest + */ + DeleteMember(ctx context.Context, id string) ApiDeleteMemberRequest + + // DeleteMemberExecute executes the request + DeleteMemberExecute(r ApiDeleteMemberRequest) (*http.Response, error) + + /* + GetMember Get account member + + Get a single account member by member ID. + +`me` is a reserved value for the `id` parameter that returns the caller's member information. + +### Expanding the member response +LaunchDarkly supports one field for expanding the "Get member" response. By default, this field is **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `roleAttributes` includes a list of the role attributes that you have assigned to the member. + +For example, `expand=roleAttributes` includes `roleAttributes` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiGetMemberRequest + */ + GetMember(ctx context.Context, id string) ApiGetMemberRequest + + // GetMemberExecute executes the request + // @return Member + GetMemberExecute(r ApiGetMemberRequest) (*Member, *http.Response, error) + + /* + GetMembers List account members + + Return a list of account members. + +By default, this returns the first 20 members. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the returned `_links` field. These links are not present if the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page. + +### Filtering members + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the members' emails and names. It is not case sensitive. +- `role` is a `|` separated list of roles and custom roles. It filters the list to members who have any of the roles in the list. For the purposes of this filtering, `Owner` counts as `Admin`. +- `id` is a `|` separated list of member IDs. It filters the list to members who match any of the IDs in the list. +- `email` is a `|` separated list of member emails. It filters the list to members who match any of the emails in the list. +- `team` is a string that matches against the key of the teams the members belong to. It is not case sensitive. +- `noteam` is a boolean that filters the list of members who are not on a team if true and members on a team if false. +- `lastSeen` is a JSON object in one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `accessCheck` is a string that represents a specific action on a specific resource and is in the format `:`. It filters the list to members who have the ability to perform that action on that resource. Note: `accessCheck` is only supported in API version `20220603` and earlier. To learn more, read [Versioning](https://launchdarkly.com/docs/api#versioning). + - For example, the filter `accessCheck:createApprovalRequest:proj/default:env/test:flag/alternate-page` matches members with the ability to create an approval request for the `alternate-page` flag in the `test` environment of the `default` project. + - Wildcard and tag filters are not supported when filtering for access. + +For example, the filter `query:abc,role:admin|customrole` matches members with the string `abc` in their email or name, ignoring case, who also are either an `Owner` or `Admin` or have the custom role `customrole`. + +### Sorting members + +LaunchDarkly supports two fields for sorting: `displayName` and `lastSeen`: + +- `displayName` sorts by first + last name, using the member's email if no name is set. +- `lastSeen` sorts by the `_lastSeen` property. LaunchDarkly considers members that have never been seen or have no data the oldest. + +### Expanding the members response +LaunchDarkly supports two fields for expanding the "List members" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `customRoles` includes a list of the roles that you have assigned to the member. +* `roleAttributes` includes a list of the role attributes that you have assigned to the member. + +For example, `expand=roleAttributes` includes `roleAttributes` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMembersRequest + */ + GetMembers(ctx context.Context) ApiGetMembersRequest + + // GetMembersExecute executes the request + // @return Members + GetMembersExecute(r ApiGetMembersRequest) (*Members, *http.Response, error) + + /* + PatchMember Modify an account member + + +Update a single account member. Updating a member uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +To update fields in the account member object that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. For example, to add a new custom role to a member, use the following request body: + +``` + [ + { + "op": "add", + "path": "/customRoles/0", + "value": "some-role-id" + } + ] +``` + +You can update only an account member's role or custom role using a JSON patch. Members can update their own names and email addresses though the LaunchDarkly UI. + +When SAML SSO or SCIM is enabled for the account, account members are managed in the Identity Provider (IdP). Requests to update account members will succeed, but the IdP will override the update shortly afterwards. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiPatchMemberRequest + */ + PatchMember(ctx context.Context, id string) ApiPatchMemberRequest + + // PatchMemberExecute executes the request + // @return Member + PatchMemberExecute(r ApiPatchMemberRequest) (*Member, *http.Response, error) + + /* + PostMemberTeams Add a member to teams + + Add one member to one or more teams. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiPostMemberTeamsRequest + */ + PostMemberTeams(ctx context.Context, id string) ApiPostMemberTeamsRequest + + // PostMemberTeamsExecute executes the request + // @return Member + PostMemberTeamsExecute(r ApiPostMemberTeamsRequest) (*Member, *http.Response, error) + + /* + PostMembers Invite new members + + Invite one or more new members to join an account. Each member is sent an invitation. Members with "admin" or "owner" roles may create new members, as well as anyone with a "createMember" permission for "member/\*". If a member cannot be invited, the entire request is rejected and no members are invited from that request. + +Each member _must_ have an `email` field and either a `role` or a `customRoles` field. If any of the fields are not populated correctly, the request is rejected with the reason specified in the "message" field of the response. + +Requests to create account members will not work if SCIM is enabled for the account. + +_No more than 50 members may be created per request._ + +A request may also fail because of conflicts with existing members. These conflicts are reported using the additional `code` and `invalid_emails` response fields with the following possible values for `code`: + +- **email_already_exists_in_account**: A member with this email address already exists in this account. +- **email_taken_in_different_account**: A member with this email address exists in another account. +- **duplicate_email**s: This request contains two or more members with the same email address. + +A request that fails for one of the above reasons returns an HTTP response code of 400 (Bad Request). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostMembersRequest + */ + PostMembers(ctx context.Context) ApiPostMembersRequest + + // PostMembersExecute executes the request + // @return Members + PostMembersExecute(r ApiPostMembersRequest) (*Members, *http.Response, error) +} + +// AccountMembersApiService AccountMembersApi service +type AccountMembersApiService service + +type ApiDeleteMemberRequest struct { + ctx context.Context + ApiService AccountMembersApi + id string +} + +func (r ApiDeleteMemberRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteMemberExecute(r) +} + +/* +DeleteMember Delete account member + +Delete a single account member by ID. Requests to delete account members will not work if SCIM is enabled for the account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiDeleteMemberRequest +*/ +func (a *AccountMembersApiService) DeleteMember(ctx context.Context, id string) ApiDeleteMemberRequest { + return ApiDeleteMemberRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +func (a *AccountMembersApiService) DeleteMemberExecute(r ApiDeleteMemberRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.DeleteMember") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetMemberRequest struct { + ctx context.Context + ApiService AccountMembersApi + id string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMemberRequest) Expand(expand string) ApiGetMemberRequest { + r.expand = &expand + return r +} + +func (r ApiGetMemberRequest) Execute() (*Member, *http.Response, error) { + return r.ApiService.GetMemberExecute(r) +} + +/* +GetMember Get account member + +Get a single account member by member ID. + +`me` is a reserved value for the `id` parameter that returns the caller's member information. + +### Expanding the member response +LaunchDarkly supports one field for expanding the "Get member" response. By default, this field is **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `roleAttributes` includes a list of the role attributes that you have assigned to the member. + +For example, `expand=roleAttributes` includes `roleAttributes` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiGetMemberRequest +*/ +func (a *AccountMembersApiService) GetMember(ctx context.Context, id string) ApiGetMemberRequest { + return ApiGetMemberRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Member +func (a *AccountMembersApiService) GetMemberExecute(r ApiGetMemberRequest) (*Member, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Member + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.GetMember") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMembersRequest struct { + ctx context.Context + ApiService AccountMembersApi + limit *int64 + offset *int64 + filter *string + expand *string + sort *string +} + +// The number of members to return in the response. Defaults to 20. +func (r ApiGetMembersRequest) Limit(limit int64) ApiGetMembersRequest { + r.limit = &limit + return r +} + +// Where to start in the list. This is for use with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetMembersRequest) Offset(offset int64) ApiGetMembersRequest { + r.offset = &offset + return r +} + +// A comma-separated list of filters. Each filter is of the form `field:value`. Supported fields are explained above. +func (r ApiGetMembersRequest) Filter(filter string) ApiGetMembersRequest { + r.filter = &filter + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMembersRequest) Expand(expand string) ApiGetMembersRequest { + r.expand = &expand + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order. +func (r ApiGetMembersRequest) Sort(sort string) ApiGetMembersRequest { + r.sort = &sort + return r +} + +func (r ApiGetMembersRequest) Execute() (*Members, *http.Response, error) { + return r.ApiService.GetMembersExecute(r) +} + +/* +GetMembers List account members + +Return a list of account members. + +By default, this returns the first 20 members. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the returned `_links` field. These links are not present if the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page. + +### Filtering members + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the members' emails and names. It is not case sensitive. +- `role` is a `|` separated list of roles and custom roles. It filters the list to members who have any of the roles in the list. For the purposes of this filtering, `Owner` counts as `Admin`. +- `id` is a `|` separated list of member IDs. It filters the list to members who match any of the IDs in the list. +- `email` is a `|` separated list of member emails. It filters the list to members who match any of the emails in the list. +- `team` is a string that matches against the key of the teams the members belong to. It is not case sensitive. +- `noteam` is a boolean that filters the list of members who are not on a team if true and members on a team if false. +- `lastSeen` is a JSON object in one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `accessCheck` is a string that represents a specific action on a specific resource and is in the format `:`. It filters the list to members who have the ability to perform that action on that resource. Note: `accessCheck` is only supported in API version `20220603` and earlier. To learn more, read [Versioning](https://launchdarkly.com/docs/api#versioning). + - For example, the filter `accessCheck:createApprovalRequest:proj/default:env/test:flag/alternate-page` matches members with the ability to create an approval request for the `alternate-page` flag in the `test` environment of the `default` project. + - Wildcard and tag filters are not supported when filtering for access. + +For example, the filter `query:abc,role:admin|customrole` matches members with the string `abc` in their email or name, ignoring case, who also are either an `Owner` or `Admin` or have the custom role `customrole`. + +### Sorting members + +LaunchDarkly supports two fields for sorting: `displayName` and `lastSeen`: + +- `displayName` sorts by first + last name, using the member's email if no name is set. +- `lastSeen` sorts by the `_lastSeen` property. LaunchDarkly considers members that have never been seen or have no data the oldest. + +### Expanding the members response +LaunchDarkly supports two fields for expanding the "List members" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `customRoles` includes a list of the roles that you have assigned to the member. +* `roleAttributes` includes a list of the role attributes that you have assigned to the member. + +For example, `expand=roleAttributes` includes `roleAttributes` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMembersRequest +*/ +func (a *AccountMembersApiService) GetMembers(ctx context.Context) ApiGetMembersRequest { + return ApiGetMembersRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Members +func (a *AccountMembersApiService) GetMembersExecute(r ApiGetMembersRequest) (*Members, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Members + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.GetMembers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchMemberRequest struct { + ctx context.Context + ApiService AccountMembersApi + id string + patchOperation *[]PatchOperation +} + +func (r ApiPatchMemberRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchMemberRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchMemberRequest) Execute() (*Member, *http.Response, error) { + return r.ApiService.PatchMemberExecute(r) +} + +/* +PatchMember Modify an account member + + +Update a single account member. Updating a member uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +To update fields in the account member object that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. For example, to add a new custom role to a member, use the following request body: + +``` + [ + { + "op": "add", + "path": "/customRoles/0", + "value": "some-role-id" + } + ] +``` + +You can update only an account member's role or custom role using a JSON patch. Members can update their own names and email addresses though the LaunchDarkly UI. + +When SAML SSO or SCIM is enabled for the account, account members are managed in the Identity Provider (IdP). Requests to update account members will succeed, but the IdP will override the update shortly afterwards. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiPatchMemberRequest +*/ +func (a *AccountMembersApiService) PatchMember(ctx context.Context, id string) ApiPatchMemberRequest { + return ApiPatchMemberRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Member +func (a *AccountMembersApiService) PatchMemberExecute(r ApiPatchMemberRequest) (*Member, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Member + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.PatchMember") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostMemberTeamsRequest struct { + ctx context.Context + ApiService AccountMembersApi + id string + memberTeamsPostInput *MemberTeamsPostInput +} + +func (r ApiPostMemberTeamsRequest) MemberTeamsPostInput(memberTeamsPostInput MemberTeamsPostInput) ApiPostMemberTeamsRequest { + r.memberTeamsPostInput = &memberTeamsPostInput + return r +} + +func (r ApiPostMemberTeamsRequest) Execute() (*Member, *http.Response, error) { + return r.ApiService.PostMemberTeamsExecute(r) +} + +/* +PostMemberTeams Add a member to teams + +Add one member to one or more teams. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The member ID + @return ApiPostMemberTeamsRequest +*/ +func (a *AccountMembersApiService) PostMemberTeams(ctx context.Context, id string) ApiPostMemberTeamsRequest { + return ApiPostMemberTeamsRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Member +func (a *AccountMembersApiService) PostMemberTeamsExecute(r ApiPostMemberTeamsRequest) (*Member, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Member + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.PostMemberTeams") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members/{id}/teams" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.memberTeamsPostInput == nil { + return localVarReturnValue, nil, reportError("memberTeamsPostInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.memberTeamsPostInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostMembersRequest struct { + ctx context.Context + ApiService AccountMembersApi + newMemberForm *[]NewMemberForm +} + +func (r ApiPostMembersRequest) NewMemberForm(newMemberForm []NewMemberForm) ApiPostMembersRequest { + r.newMemberForm = &newMemberForm + return r +} + +func (r ApiPostMembersRequest) Execute() (*Members, *http.Response, error) { + return r.ApiService.PostMembersExecute(r) +} + +/* +PostMembers Invite new members + +Invite one or more new members to join an account. Each member is sent an invitation. Members with "admin" or "owner" roles may create new members, as well as anyone with a "createMember" permission for "member/\*". If a member cannot be invited, the entire request is rejected and no members are invited from that request. + +Each member _must_ have an `email` field and either a `role` or a `customRoles` field. If any of the fields are not populated correctly, the request is rejected with the reason specified in the "message" field of the response. + +Requests to create account members will not work if SCIM is enabled for the account. + +_No more than 50 members may be created per request._ + +A request may also fail because of conflicts with existing members. These conflicts are reported using the additional `code` and `invalid_emails` response fields with the following possible values for `code`: + +- **email_already_exists_in_account**: A member with this email address already exists in this account. +- **email_taken_in_different_account**: A member with this email address exists in another account. +- **duplicate_email**s: This request contains two or more members with the same email address. + +A request that fails for one of the above reasons returns an HTTP response code of 400 (Bad Request). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostMembersRequest +*/ +func (a *AccountMembersApiService) PostMembers(ctx context.Context) ApiPostMembersRequest { + return ApiPostMembersRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Members +func (a *AccountMembersApiService) PostMembersExecute(r ApiPostMembersRequest) (*Members, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Members + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersApiService.PostMembers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.newMemberForm == nil { + return localVarReturnValue, nil, reportError("newMemberForm is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.newMemberForm + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members_beta.go new file mode 100644 index 00000000..56fd4148 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_members_beta.go @@ -0,0 +1,512 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" +) + + +type AccountMembersBetaApi interface { + + /* + PatchMembers Modify account members + + > ### Full use of this API resource is an Enterprise feature +> +> The ability to perform a partial update to multiple members is available to customers on an Enterprise plan. If you are on another plan, you can update members individually. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +Perform a partial update to multiple members. Updating members uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating members. + +
+Click to expand instructions for updating members + +#### replaceMembersRoles + +Replaces the roles of the specified members. This also removes all custom roles assigned to the specified members. + +##### Parameters + +- `value`: The new role. Must be a valid built-in role. To learn more about built-in roles, read [LaunchDarkly's built-in roles](https://launchdarkly.com/docs/home/account/built-in-roles). +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMemberRoles", + "value": "reader", + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +#### replaceAllMembersRoles + +Replaces the roles of all members. This also removes all custom roles assigned to the specified members. + +Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `value`: The new role. Must be a valid built-in role. To learn more about built-in roles, read [LaunchDarkly's built-in roles](https://launchdarkly.com/docs/home/account/built-in-roles). +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceAllMembersRoles", + "value": "reader", + "filterLastSeen": { "never": true } + }] +} +``` + +#### replaceMembersCustomRoles + +Replaces the custom roles of the specified members. + +##### Parameters + +- `values`: List of new custom roles. Must be a valid custom role key or ID. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembersCustomRoles", + "values": [ "example-custom-role" ], + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +#### replaceAllMembersCustomRoles + +Replaces the custom roles of all members. Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `values`: List of new roles. Must be a valid custom role key or ID. +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceAllMembersCustomRoles", + "values": [ "example-custom-role" ], + "filterLastSeen": { "never": true } + }] +} +``` + +#### replaceMembersRoleAttributes + +Replaces the role attributes of the specified members. + +##### Parameters + +- `value`: Map of role attribute keys to lists of values. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembersRoleAttributes", + "value": { + "myRoleProjectKey": ["mobile", "web"], + "myRoleEnvironmentKey": ["production"] + }, + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPatchMembersRequest + */ + PatchMembers(ctx context.Context) ApiPatchMembersRequest + + // PatchMembersExecute executes the request + // @return BulkEditMembersRep + PatchMembersExecute(r ApiPatchMembersRequest) (*BulkEditMembersRep, *http.Response, error) +} + +// AccountMembersBetaApiService AccountMembersBetaApi service +type AccountMembersBetaApiService service + +type ApiPatchMembersRequest struct { + ctx context.Context + ApiService AccountMembersBetaApi + membersPatchInput *MembersPatchInput +} + +func (r ApiPatchMembersRequest) MembersPatchInput(membersPatchInput MembersPatchInput) ApiPatchMembersRequest { + r.membersPatchInput = &membersPatchInput + return r +} + +func (r ApiPatchMembersRequest) Execute() (*BulkEditMembersRep, *http.Response, error) { + return r.ApiService.PatchMembersExecute(r) +} + +/* +PatchMembers Modify account members + +> ### Full use of this API resource is an Enterprise feature +> +> The ability to perform a partial update to multiple members is available to customers on an Enterprise plan. If you are on another plan, you can update members individually. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +Perform a partial update to multiple members. Updating members uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating members. + +
+Click to expand instructions for updating members + +#### replaceMembersRoles + +Replaces the roles of the specified members. This also removes all custom roles assigned to the specified members. + +##### Parameters + +- `value`: The new role. Must be a valid built-in role. To learn more about built-in roles, read [LaunchDarkly's built-in roles](https://launchdarkly.com/docs/home/account/built-in-roles). +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMemberRoles", + "value": "reader", + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +#### replaceAllMembersRoles + +Replaces the roles of all members. This also removes all custom roles assigned to the specified members. + +Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `value`: The new role. Must be a valid built-in role. To learn more about built-in roles, read [LaunchDarkly's built-in roles](https://launchdarkly.com/docs/home/account/built-in-roles). +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceAllMembersRoles", + "value": "reader", + "filterLastSeen": { "never": true } + }] +} +``` + +#### replaceMembersCustomRoles + +Replaces the custom roles of the specified members. + +##### Parameters + +- `values`: List of new custom roles. Must be a valid custom role key or ID. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembersCustomRoles", + "values": [ "example-custom-role" ], + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +#### replaceAllMembersCustomRoles + +Replaces the custom roles of all members. Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `values`: List of new roles. Must be a valid custom role key or ID. +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceAllMembersCustomRoles", + "values": [ "example-custom-role" ], + "filterLastSeen": { "never": true } + }] +} +``` + +#### replaceMembersRoleAttributes + +Replaces the role attributes of the specified members. + +##### Parameters + +- `value`: Map of role attribute keys to lists of values. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembersRoleAttributes", + "value": { + "myRoleProjectKey": ["mobile", "web"], + "myRoleEnvironmentKey": ["production"] + }, + "memberIDs": [ + "1234a56b7c89d012345e678f", + "507f1f77bcf86cd799439011" + ] + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPatchMembersRequest +*/ +func (a *AccountMembersBetaApiService) PatchMembers(ctx context.Context) ApiPatchMembersRequest { + return ApiPatchMembersRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return BulkEditMembersRep +func (a *AccountMembersBetaApiService) PatchMembersExecute(r ApiPatchMembersRequest) (*BulkEditMembersRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BulkEditMembersRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountMembersBetaApiService.PatchMembers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/members" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.membersPatchInput == nil { + return localVarReturnValue, nil, reportError("membersPatchInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.membersPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_account_usage_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_usage_beta.go new file mode 100644 index 00000000..bfe04f3a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_account_usage_beta.go @@ -0,0 +1,2575 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AccountUsageBetaApi interface { + + /* + GetDataExportEventsUsage Get data export events usage + + Get a time-series array of the number of monthly data export events from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDataExportEventsUsageRequest + */ + GetDataExportEventsUsage(ctx context.Context) ApiGetDataExportEventsUsageRequest + + // GetDataExportEventsUsageExecute executes the request + // @return SeriesIntervalsRep + GetDataExportEventsUsageExecute(r ApiGetDataExportEventsUsageRequest) (*SeriesIntervalsRep, *http.Response, error) + + /* + GetEvaluationsUsage Get evaluations usage + + Get time-series arrays of the number of times a flag is evaluated, broken down by the variation that resulted from that evaluation. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetEvaluationsUsageRequest + */ + GetEvaluationsUsage(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetEvaluationsUsageRequest + + // GetEvaluationsUsageExecute executes the request + // @return SeriesListRep + GetEvaluationsUsageExecute(r ApiGetEvaluationsUsageRequest) (*SeriesListRep, *http.Response, error) + + /* + GetEventsUsage Get events usage + + Get time-series arrays of the number of times a flag is evaluated, broken down by the variation that resulted from that evaluation. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param type_ The type of event to retrieve. Must be either `received` or `published`. + @return ApiGetEventsUsageRequest + */ + GetEventsUsage(ctx context.Context, type_ string) ApiGetEventsUsageRequest + + // GetEventsUsageExecute executes the request + // @return SeriesListRep + GetEventsUsageExecute(r ApiGetEventsUsageRequest) (*SeriesListRep, *http.Response, error) + + /* + GetExperimentationKeysUsage Get experimentation keys usage + + Get a time-series array of the number of monthly experimentation keys from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExperimentationKeysUsageRequest + */ + GetExperimentationKeysUsage(ctx context.Context) ApiGetExperimentationKeysUsageRequest + + // GetExperimentationKeysUsageExecute executes the request + // @return SeriesIntervalsRep + GetExperimentationKeysUsageExecute(r ApiGetExperimentationKeysUsageRequest) (*SeriesIntervalsRep, *http.Response, error) + + /* + GetExperimentationUnitsUsage Get experimentation units usage + + Get a time-series array of the number of monthly experimentation units from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExperimentationUnitsUsageRequest + */ + GetExperimentationUnitsUsage(ctx context.Context) ApiGetExperimentationUnitsUsageRequest + + // GetExperimentationUnitsUsageExecute executes the request + // @return SeriesIntervalsRep + GetExperimentationUnitsUsageExecute(r ApiGetExperimentationUnitsUsageRequest) (*SeriesIntervalsRep, *http.Response, error) + + /* + GetMauSdksByType Get MAU SDKs by type + + Get a list of SDKs. These are all of the SDKs that have connected to LaunchDarkly by monthly active users (MAU) in the requested time period.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauSdksByTypeRequest + */ + GetMauSdksByType(ctx context.Context) ApiGetMauSdksByTypeRequest + + // GetMauSdksByTypeExecute executes the request + // @return SdkListRep + GetMauSdksByTypeExecute(r ApiGetMauSdksByTypeRequest) (*SdkListRep, *http.Response, error) + + /* + GetMauUsage Get MAU usage + + Get a time-series array of the number of monthly active users (MAU) seen by LaunchDarkly from your account. The granularity is always daily.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauUsageRequest + */ + GetMauUsage(ctx context.Context) ApiGetMauUsageRequest + + // GetMauUsageExecute executes the request + // @return SeriesListRep + GetMauUsageExecute(r ApiGetMauUsageRequest) (*SeriesListRep, *http.Response, error) + + /* + GetMauUsageByCategory Get MAU usage by category + + Get time-series arrays of the number of monthly active users (MAU) seen by LaunchDarkly from your account, broken down by the category of users. The category is either `browser`, `mobile`, or `backend`.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauUsageByCategoryRequest + */ + GetMauUsageByCategory(ctx context.Context) ApiGetMauUsageByCategoryRequest + + // GetMauUsageByCategoryExecute executes the request + // @return SeriesListRep + GetMauUsageByCategoryExecute(r ApiGetMauUsageByCategoryRequest) (*SeriesListRep, *http.Response, error) + + /* + GetServiceConnectionUsage Get service connection usage + + Get a time-series array of the number of monthly service connections from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetServiceConnectionUsageRequest + */ + GetServiceConnectionUsage(ctx context.Context) ApiGetServiceConnectionUsageRequest + + // GetServiceConnectionUsageExecute executes the request + // @return SeriesIntervalsRep + GetServiceConnectionUsageExecute(r ApiGetServiceConnectionUsageRequest) (*SeriesIntervalsRep, *http.Response, error) + + /* + GetStreamUsage Get stream usage + + Get a time-series array of the number of streaming connections to LaunchDarkly in each time period. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageRequest + */ + GetStreamUsage(ctx context.Context, source string) ApiGetStreamUsageRequest + + // GetStreamUsageExecute executes the request + // @return SeriesListRep + GetStreamUsageExecute(r ApiGetStreamUsageRequest) (*SeriesListRep, *http.Response, error) + + /* + GetStreamUsageBySdkVersion Get stream usage by SDK version + + Get multiple series of the number of streaming connections to LaunchDarkly in each time period, separated by SDK type and version. Information about each series is in the metadata array. The granularity of the data depends on the age of the data requested. If the requested range is within the past 2 hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageBySdkVersionRequest + */ + GetStreamUsageBySdkVersion(ctx context.Context, source string) ApiGetStreamUsageBySdkVersionRequest + + // GetStreamUsageBySdkVersionExecute executes the request + // @return SeriesListRep + GetStreamUsageBySdkVersionExecute(r ApiGetStreamUsageBySdkVersionRequest) (*SeriesListRep, *http.Response, error) + + /* + GetStreamUsageSdkversion Get stream usage SDK versions + + Get a list of SDK version objects, which contain an SDK name and version. These are all of the SDKs that have connected to LaunchDarkly from your account in the past 60 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageSdkversionRequest + */ + GetStreamUsageSdkversion(ctx context.Context, source string) ApiGetStreamUsageSdkversionRequest + + // GetStreamUsageSdkversionExecute executes the request + // @return SdkVersionListRep + GetStreamUsageSdkversionExecute(r ApiGetStreamUsageSdkversionRequest) (*SdkVersionListRep, *http.Response, error) +} + +// AccountUsageBetaApiService AccountUsageBetaApi service +type AccountUsageBetaApiService service + +type ApiGetDataExportEventsUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + projectKey *string + environmentKey *string +} + +// The series of data returned starts from this timestamp (Unix seconds). Defaults to the beginning of the current month. +func (r ApiGetDataExportEventsUsageRequest) From(from string) ApiGetDataExportEventsUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp (Unix seconds). Defaults to the current time. +func (r ApiGetDataExportEventsUsageRequest) To(to string) ApiGetDataExportEventsUsageRequest { + r.to = &to + return r +} + +// A project key. If specified, `environmentKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetDataExportEventsUsageRequest) ProjectKey(projectKey string) ApiGetDataExportEventsUsageRequest { + r.projectKey = &projectKey + return r +} + +// An environment key. If specified, `projectKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetDataExportEventsUsageRequest) EnvironmentKey(environmentKey string) ApiGetDataExportEventsUsageRequest { + r.environmentKey = &environmentKey + return r +} + +func (r ApiGetDataExportEventsUsageRequest) Execute() (*SeriesIntervalsRep, *http.Response, error) { + return r.ApiService.GetDataExportEventsUsageExecute(r) +} + +/* +GetDataExportEventsUsage Get data export events usage + +Get a time-series array of the number of monthly data export events from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDataExportEventsUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetDataExportEventsUsage(ctx context.Context) ApiGetDataExportEventsUsageRequest { + return ApiGetDataExportEventsUsageRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesIntervalsRep +func (a *AccountUsageBetaApiService) GetDataExportEventsUsageExecute(r ApiGetDataExportEventsUsageRequest) (*SeriesIntervalsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesIntervalsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetDataExportEventsUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/data-export-events" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.projectKey != nil { + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + } + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 503 { + var v StatusServiceUnavailable + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetEvaluationsUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + projectKey string + environmentKey string + featureFlagKey string + from *string + to *string + tz *string +} + +// The series of data returned starts from this timestamp. Defaults to 30 days ago. +func (r ApiGetEvaluationsUsageRequest) From(from string) ApiGetEvaluationsUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetEvaluationsUsageRequest) To(to string) ApiGetEvaluationsUsageRequest { + r.to = &to + return r +} + +// The timezone to use for breaks between days when returning daily data. +func (r ApiGetEvaluationsUsageRequest) Tz(tz string) ApiGetEvaluationsUsageRequest { + r.tz = &tz + return r +} + +func (r ApiGetEvaluationsUsageRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetEvaluationsUsageExecute(r) +} + +/* +GetEvaluationsUsage Get evaluations usage + +Get time-series arrays of the number of times a flag is evaluated, broken down by the variation that resulted from that evaluation. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetEvaluationsUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetEvaluationsUsage(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetEvaluationsUsageRequest { + return ApiGetEvaluationsUsageRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetEvaluationsUsageExecute(r ApiGetEvaluationsUsageRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetEvaluationsUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/evaluations/{projectKey}/{environmentKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.tz != nil { + localVarQueryParams.Add("tz", parameterToString(*r.tz, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetEventsUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + type_ string + from *string + to *string +} + +// The series of data returned starts from this timestamp. Defaults to 24 hours ago. +func (r ApiGetEventsUsageRequest) From(from string) ApiGetEventsUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetEventsUsageRequest) To(to string) ApiGetEventsUsageRequest { + r.to = &to + return r +} + +func (r ApiGetEventsUsageRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetEventsUsageExecute(r) +} + +/* +GetEventsUsage Get events usage + +Get time-series arrays of the number of times a flag is evaluated, broken down by the variation that resulted from that evaluation. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param type_ The type of event to retrieve. Must be either `received` or `published`. + @return ApiGetEventsUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetEventsUsage(ctx context.Context, type_ string) ApiGetEventsUsageRequest { + return ApiGetEventsUsageRequest{ + ApiService: a, + ctx: ctx, + type_: type_, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetEventsUsageExecute(r ApiGetEventsUsageRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetEventsUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/events/{type}" + localVarPath = strings.Replace(localVarPath, "{"+"type"+"}", url.PathEscape(parameterToString(r.type_, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentationKeysUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + projectKey *string + environmentKey *string +} + +// The series of data returned starts from this timestamp (Unix seconds). Defaults to the beginning of the current month. +func (r ApiGetExperimentationKeysUsageRequest) From(from string) ApiGetExperimentationKeysUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp (Unix seconds). Defaults to the current time. +func (r ApiGetExperimentationKeysUsageRequest) To(to string) ApiGetExperimentationKeysUsageRequest { + r.to = &to + return r +} + +// A project key. If specified, `environmentKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetExperimentationKeysUsageRequest) ProjectKey(projectKey string) ApiGetExperimentationKeysUsageRequest { + r.projectKey = &projectKey + return r +} + +// An environment key. If specified, `projectKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetExperimentationKeysUsageRequest) EnvironmentKey(environmentKey string) ApiGetExperimentationKeysUsageRequest { + r.environmentKey = &environmentKey + return r +} + +func (r ApiGetExperimentationKeysUsageRequest) Execute() (*SeriesIntervalsRep, *http.Response, error) { + return r.ApiService.GetExperimentationKeysUsageExecute(r) +} + +/* +GetExperimentationKeysUsage Get experimentation keys usage + +Get a time-series array of the number of monthly experimentation keys from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExperimentationKeysUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetExperimentationKeysUsage(ctx context.Context) ApiGetExperimentationKeysUsageRequest { + return ApiGetExperimentationKeysUsageRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesIntervalsRep +func (a *AccountUsageBetaApiService) GetExperimentationKeysUsageExecute(r ApiGetExperimentationKeysUsageRequest) (*SeriesIntervalsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesIntervalsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetExperimentationKeysUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/experimentation-keys" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.projectKey != nil { + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + } + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 503 { + var v StatusServiceUnavailable + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentationUnitsUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + projectKey *string + environmentKey *string +} + +// The series of data returned starts from this timestamp (Unix seconds). Defaults to the beginning of the current month. +func (r ApiGetExperimentationUnitsUsageRequest) From(from string) ApiGetExperimentationUnitsUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp (Unix seconds). Defaults to the current time. +func (r ApiGetExperimentationUnitsUsageRequest) To(to string) ApiGetExperimentationUnitsUsageRequest { + r.to = &to + return r +} + +// A project key. If specified, `environmentKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetExperimentationUnitsUsageRequest) ProjectKey(projectKey string) ApiGetExperimentationUnitsUsageRequest { + r.projectKey = &projectKey + return r +} + +// An environment key. If specified, `projectKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetExperimentationUnitsUsageRequest) EnvironmentKey(environmentKey string) ApiGetExperimentationUnitsUsageRequest { + r.environmentKey = &environmentKey + return r +} + +func (r ApiGetExperimentationUnitsUsageRequest) Execute() (*SeriesIntervalsRep, *http.Response, error) { + return r.ApiService.GetExperimentationUnitsUsageExecute(r) +} + +/* +GetExperimentationUnitsUsage Get experimentation units usage + +Get a time-series array of the number of monthly experimentation units from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExperimentationUnitsUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetExperimentationUnitsUsage(ctx context.Context) ApiGetExperimentationUnitsUsageRequest { + return ApiGetExperimentationUnitsUsageRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesIntervalsRep +func (a *AccountUsageBetaApiService) GetExperimentationUnitsUsageExecute(r ApiGetExperimentationUnitsUsageRequest) (*SeriesIntervalsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesIntervalsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetExperimentationUnitsUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/experimentation-units" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.projectKey != nil { + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + } + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 503 { + var v StatusServiceUnavailable + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMauSdksByTypeRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + sdktype *string +} + +// The data returned starts from this timestamp. Defaults to seven days ago. The timestamp is in Unix milliseconds, for example, 1656694800000. +func (r ApiGetMauSdksByTypeRequest) From(from string) ApiGetMauSdksByTypeRequest { + r.from = &from + return r +} + +// The data returned ends at this timestamp. Defaults to the current time. The timestamp is in Unix milliseconds, for example, 1657904400000. +func (r ApiGetMauSdksByTypeRequest) To(to string) ApiGetMauSdksByTypeRequest { + r.to = &to + return r +} + +// The type of SDK with monthly active users (MAU) to list. Must be either `client` or `server`. +func (r ApiGetMauSdksByTypeRequest) Sdktype(sdktype string) ApiGetMauSdksByTypeRequest { + r.sdktype = &sdktype + return r +} + +func (r ApiGetMauSdksByTypeRequest) Execute() (*SdkListRep, *http.Response, error) { + return r.ApiService.GetMauSdksByTypeExecute(r) +} + +/* +GetMauSdksByType Get MAU SDKs by type + +Get a list of SDKs. These are all of the SDKs that have connected to LaunchDarkly by monthly active users (MAU) in the requested time period.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauSdksByTypeRequest +*/ +func (a *AccountUsageBetaApiService) GetMauSdksByType(ctx context.Context) ApiGetMauSdksByTypeRequest { + return ApiGetMauSdksByTypeRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SdkListRep +func (a *AccountUsageBetaApiService) GetMauSdksByTypeExecute(r ApiGetMauSdksByTypeRequest) (*SdkListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SdkListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetMauSdksByType") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/mau/sdks" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.sdktype != nil { + localVarQueryParams.Add("sdktype", parameterToString(*r.sdktype, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMauUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + project *string + environment *string + sdktype *string + sdk *string + anonymous *string + groupby *string + aggregationType *string + contextKind *string +} + +// The series of data returned starts from this timestamp. Defaults to 30 days ago. +func (r ApiGetMauUsageRequest) From(from string) ApiGetMauUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetMauUsageRequest) To(to string) ApiGetMauUsageRequest { + r.to = &to + return r +} + +// A project key to filter results to. Can be specified multiple times, one query parameter per project key, to view data for multiple projects. +func (r ApiGetMauUsageRequest) Project(project string) ApiGetMauUsageRequest { + r.project = &project + return r +} + +// An environment key to filter results to. When using this parameter, exactly one project key must also be set. Can be specified multiple times as separate query parameters to view data for multiple environments within a single project. +func (r ApiGetMauUsageRequest) Environment(environment string) ApiGetMauUsageRequest { + r.environment = &environment + return r +} + +// An SDK type to filter results to. Can be specified multiple times, one query parameter per SDK type. Valid values: client, server +func (r ApiGetMauUsageRequest) Sdktype(sdktype string) ApiGetMauUsageRequest { + r.sdktype = &sdktype + return r +} + +// An SDK name to filter results to. Can be specified multiple times, one query parameter per SDK. +func (r ApiGetMauUsageRequest) Sdk(sdk string) ApiGetMauUsageRequest { + r.sdk = &sdk + return r +} + +// If specified, filters results to either anonymous or nonanonymous users. +func (r ApiGetMauUsageRequest) Anonymous(anonymous string) ApiGetMauUsageRequest { + r.anonymous = &anonymous + return r +} + +// If specified, returns data for each distinct value of the given field. Can be specified multiple times to group data by multiple dimensions (for example, to group by both project and SDK). Valid values: project, environment, sdktype, sdk, anonymous, contextKind, sdkAppId +func (r ApiGetMauUsageRequest) Groupby(groupby string) ApiGetMauUsageRequest { + r.groupby = &groupby + return r +} + +// If specified, queries for rolling 30-day, month-to-date, or daily incremental counts. Default is rolling 30-day. Valid values: rolling_30d, month_to_date, daily_incremental +func (r ApiGetMauUsageRequest) AggregationType(aggregationType string) ApiGetMauUsageRequest { + r.aggregationType = &aggregationType + return r +} + +// Filters results to the specified context kinds. Can be specified multiple times, one query parameter per context kind. If not set, queries for the user context kind. +func (r ApiGetMauUsageRequest) ContextKind(contextKind string) ApiGetMauUsageRequest { + r.contextKind = &contextKind + return r +} + +func (r ApiGetMauUsageRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetMauUsageExecute(r) +} + +/* +GetMauUsage Get MAU usage + +Get a time-series array of the number of monthly active users (MAU) seen by LaunchDarkly from your account. The granularity is always daily.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetMauUsage(ctx context.Context) ApiGetMauUsageRequest { + return ApiGetMauUsageRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetMauUsageExecute(r ApiGetMauUsageRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetMauUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/mau" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.project != nil { + localVarQueryParams.Add("project", parameterToString(*r.project, "")) + } + if r.environment != nil { + localVarQueryParams.Add("environment", parameterToString(*r.environment, "")) + } + if r.sdktype != nil { + localVarQueryParams.Add("sdktype", parameterToString(*r.sdktype, "")) + } + if r.sdk != nil { + localVarQueryParams.Add("sdk", parameterToString(*r.sdk, "")) + } + if r.anonymous != nil { + localVarQueryParams.Add("anonymous", parameterToString(*r.anonymous, "")) + } + if r.groupby != nil { + localVarQueryParams.Add("groupby", parameterToString(*r.groupby, "")) + } + if r.aggregationType != nil { + localVarQueryParams.Add("aggregationType", parameterToString(*r.aggregationType, "")) + } + if r.contextKind != nil { + localVarQueryParams.Add("contextKind", parameterToString(*r.contextKind, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMauUsageByCategoryRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string +} + +// The series of data returned starts from this timestamp. Defaults to 30 days ago. +func (r ApiGetMauUsageByCategoryRequest) From(from string) ApiGetMauUsageByCategoryRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetMauUsageByCategoryRequest) To(to string) ApiGetMauUsageByCategoryRequest { + r.to = &to + return r +} + +func (r ApiGetMauUsageByCategoryRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetMauUsageByCategoryExecute(r) +} + +/* +GetMauUsageByCategory Get MAU usage by category + +Get time-series arrays of the number of monthly active users (MAU) seen by LaunchDarkly from your account, broken down by the category of users. The category is either `browser`, `mobile`, or `backend`.

Endpoints for retrieving monthly active users (MAU) do not return information about active context instances. After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should not rely on this endpoint. To learn more, read [Account usage metrics](https://launchdarkly.com/docs/home/account/metrics). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetMauUsageByCategoryRequest +*/ +func (a *AccountUsageBetaApiService) GetMauUsageByCategory(ctx context.Context) ApiGetMauUsageByCategoryRequest { + return ApiGetMauUsageByCategoryRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetMauUsageByCategoryExecute(r ApiGetMauUsageByCategoryRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetMauUsageByCategory") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/mau/bycategory" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetServiceConnectionUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + from *string + to *string + projectKey *string + environmentKey *string +} + +// The series of data returned starts from this timestamp (Unix seconds). Defaults to the beginning of the current month. +func (r ApiGetServiceConnectionUsageRequest) From(from string) ApiGetServiceConnectionUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp (Unix seconds). Defaults to the current time. +func (r ApiGetServiceConnectionUsageRequest) To(to string) ApiGetServiceConnectionUsageRequest { + r.to = &to + return r +} + +// A project key. If specified, `environmentKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetServiceConnectionUsageRequest) ProjectKey(projectKey string) ApiGetServiceConnectionUsageRequest { + r.projectKey = &projectKey + return r +} + +// An environment key. If specified, `projectKey` is required and results apply to the corresponding environment in this project. +func (r ApiGetServiceConnectionUsageRequest) EnvironmentKey(environmentKey string) ApiGetServiceConnectionUsageRequest { + r.environmentKey = &environmentKey + return r +} + +func (r ApiGetServiceConnectionUsageRequest) Execute() (*SeriesIntervalsRep, *http.Response, error) { + return r.ApiService.GetServiceConnectionUsageExecute(r) +} + +/* +GetServiceConnectionUsage Get service connection usage + +Get a time-series array of the number of monthly service connections from your account. The granularity is always daily, with a maximum of 31 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetServiceConnectionUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetServiceConnectionUsage(ctx context.Context) ApiGetServiceConnectionUsageRequest { + return ApiGetServiceConnectionUsageRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return SeriesIntervalsRep +func (a *AccountUsageBetaApiService) GetServiceConnectionUsageExecute(r ApiGetServiceConnectionUsageRequest) (*SeriesIntervalsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesIntervalsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetServiceConnectionUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/service-connections" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.projectKey != nil { + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + } + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 503 { + var v StatusServiceUnavailable + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetStreamUsageRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + source string + from *string + to *string + tz *string +} + +// The series of data returned starts from this timestamp. Defaults to 30 days ago. +func (r ApiGetStreamUsageRequest) From(from string) ApiGetStreamUsageRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetStreamUsageRequest) To(to string) ApiGetStreamUsageRequest { + r.to = &to + return r +} + +// The timezone to use for breaks between days when returning daily data. +func (r ApiGetStreamUsageRequest) Tz(tz string) ApiGetStreamUsageRequest { + r.tz = &tz + return r +} + +func (r ApiGetStreamUsageRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetStreamUsageExecute(r) +} + +/* +GetStreamUsage Get stream usage + +Get a time-series array of the number of streaming connections to LaunchDarkly in each time period. The granularity of the data depends on the age of the data requested. If the requested range is within the past two hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageRequest +*/ +func (a *AccountUsageBetaApiService) GetStreamUsage(ctx context.Context, source string) ApiGetStreamUsageRequest { + return ApiGetStreamUsageRequest{ + ApiService: a, + ctx: ctx, + source: source, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetStreamUsageExecute(r ApiGetStreamUsageRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetStreamUsage") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/streams/{source}" + localVarPath = strings.Replace(localVarPath, "{"+"source"+"}", url.PathEscape(parameterToString(r.source, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.tz != nil { + localVarQueryParams.Add("tz", parameterToString(*r.tz, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetStreamUsageBySdkVersionRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + source string + from *string + to *string + tz *string + sdk *string + version *string +} + +// The series of data returned starts from this timestamp. Defaults to 24 hours ago. +func (r ApiGetStreamUsageBySdkVersionRequest) From(from string) ApiGetStreamUsageBySdkVersionRequest { + r.from = &from + return r +} + +// The series of data returned ends at this timestamp. Defaults to the current time. +func (r ApiGetStreamUsageBySdkVersionRequest) To(to string) ApiGetStreamUsageBySdkVersionRequest { + r.to = &to + return r +} + +// The timezone to use for breaks between days when returning daily data. +func (r ApiGetStreamUsageBySdkVersionRequest) Tz(tz string) ApiGetStreamUsageBySdkVersionRequest { + r.tz = &tz + return r +} + +// If included, this filters the returned series to only those that match this SDK name. +func (r ApiGetStreamUsageBySdkVersionRequest) Sdk(sdk string) ApiGetStreamUsageBySdkVersionRequest { + r.sdk = &sdk + return r +} + +// If included, this filters the returned series to only those that match this SDK version. +func (r ApiGetStreamUsageBySdkVersionRequest) Version(version string) ApiGetStreamUsageBySdkVersionRequest { + r.version = &version + return r +} + +func (r ApiGetStreamUsageBySdkVersionRequest) Execute() (*SeriesListRep, *http.Response, error) { + return r.ApiService.GetStreamUsageBySdkVersionExecute(r) +} + +/* +GetStreamUsageBySdkVersion Get stream usage by SDK version + +Get multiple series of the number of streaming connections to LaunchDarkly in each time period, separated by SDK type and version. Information about each series is in the metadata array. The granularity of the data depends on the age of the data requested. If the requested range is within the past 2 hours, minutely data is returned. If it is within the last two days, hourly data is returned. Otherwise, daily data is returned. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageBySdkVersionRequest +*/ +func (a *AccountUsageBetaApiService) GetStreamUsageBySdkVersion(ctx context.Context, source string) ApiGetStreamUsageBySdkVersionRequest { + return ApiGetStreamUsageBySdkVersionRequest{ + ApiService: a, + ctx: ctx, + source: source, + } +} + +// Execute executes the request +// @return SeriesListRep +func (a *AccountUsageBetaApiService) GetStreamUsageBySdkVersionExecute(r ApiGetStreamUsageBySdkVersionRequest) (*SeriesListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SeriesListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetStreamUsageBySdkVersion") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/streams/{source}/bysdkversion" + localVarPath = strings.Replace(localVarPath, "{"+"source"+"}", url.PathEscape(parameterToString(r.source, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.tz != nil { + localVarQueryParams.Add("tz", parameterToString(*r.tz, "")) + } + if r.sdk != nil { + localVarQueryParams.Add("sdk", parameterToString(*r.sdk, "")) + } + if r.version != nil { + localVarQueryParams.Add("version", parameterToString(*r.version, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetStreamUsageSdkversionRequest struct { + ctx context.Context + ApiService AccountUsageBetaApi + source string +} + +func (r ApiGetStreamUsageSdkversionRequest) Execute() (*SdkVersionListRep, *http.Response, error) { + return r.ApiService.GetStreamUsageSdkversionExecute(r) +} + +/* +GetStreamUsageSdkversion Get stream usage SDK versions + +Get a list of SDK version objects, which contain an SDK name and version. These are all of the SDKs that have connected to LaunchDarkly from your account in the past 60 days. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param source The source of streaming connections to describe. Must be either `client` or `server`. + @return ApiGetStreamUsageSdkversionRequest +*/ +func (a *AccountUsageBetaApiService) GetStreamUsageSdkversion(ctx context.Context, source string) ApiGetStreamUsageSdkversionRequest { + return ApiGetStreamUsageSdkversionRequest{ + ApiService: a, + ctx: ctx, + source: source, + } +} + +// Execute executes the request +// @return SdkVersionListRep +func (a *AccountUsageBetaApiService) GetStreamUsageSdkversionExecute(r ApiGetStreamUsageSdkversionRequest) (*SdkVersionListRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *SdkVersionListRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AccountUsageBetaApiService.GetStreamUsageSdkversion") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/usage/streams/{source}/sdkversions" + localVarPath = strings.Replace(localVarPath, "{"+"source"+"}", url.PathEscape(parameterToString(r.source, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_ai_configs_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_ai_configs_beta.go new file mode 100644 index 00000000..4e1f90fc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_ai_configs_beta.go @@ -0,0 +1,3008 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AIConfigsBetaApi interface { + + /* + DeleteAIConfig Delete AI Config + + Delete an existing AI Config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiDeleteAIConfigRequest + */ + DeleteAIConfig(ctx context.Context, projectKey string, configKey string) ApiDeleteAIConfigRequest + + // DeleteAIConfigExecute executes the request + DeleteAIConfigExecute(r ApiDeleteAIConfigRequest) (*http.Response, error) + + /* + DeleteAIConfigVariation Delete AI Config variation + + Delete a specific variation of an AI Config by config key and variation key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiDeleteAIConfigVariationRequest + */ + DeleteAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiDeleteAIConfigVariationRequest + + // DeleteAIConfigVariationExecute executes the request + DeleteAIConfigVariationExecute(r ApiDeleteAIConfigVariationRequest) (*http.Response, error) + + /* + DeleteModelConfig Delete an AI model config + + Delete an AI model config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param modelConfigKey + @return ApiDeleteModelConfigRequest + */ + DeleteModelConfig(ctx context.Context, projectKey string, modelConfigKey string) ApiDeleteModelConfigRequest + + // DeleteModelConfigExecute executes the request + DeleteModelConfigExecute(r ApiDeleteModelConfigRequest) (*http.Response, error) + + /* + GetAIConfig Get AI Config + + Retrieve a specific AI Config by its key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigRequest + */ + GetAIConfig(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigRequest + + // GetAIConfigExecute executes the request + // @return AIConfig + GetAIConfigExecute(r ApiGetAIConfigRequest) (*AIConfig, *http.Response, error) + + /* + GetAIConfigMetrics Get AI Config metrics + + Retrieve usage metrics for an AI Config by config key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigMetricsRequest + */ + GetAIConfigMetrics(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigMetricsRequest + + // GetAIConfigMetricsExecute executes the request + // @return Metrics + GetAIConfigMetricsExecute(r ApiGetAIConfigMetricsRequest) (*Metrics, *http.Response, error) + + /* + GetAIConfigMetricsByVariation Get AI Config metrics by variation + + Retrieve usage metrics for an AI Config by config key, with results split by variation. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigMetricsByVariationRequest + */ + GetAIConfigMetricsByVariation(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigMetricsByVariationRequest + + // GetAIConfigMetricsByVariationExecute executes the request + // @return []MetricByVariation + GetAIConfigMetricsByVariationExecute(r ApiGetAIConfigMetricsByVariationRequest) ([]MetricByVariation, *http.Response, error) + + /* + GetAIConfigVariation Get AI Config variation + + Get an AI Config variation by key. The response includes all variation versions for the given variation key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiGetAIConfigVariationRequest + */ + GetAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiGetAIConfigVariationRequest + + // GetAIConfigVariationExecute executes the request + // @return AIConfigVariationsResponse + GetAIConfigVariationExecute(r ApiGetAIConfigVariationRequest) (*AIConfigVariationsResponse, *http.Response, error) + + /* + GetAIConfigs List AI Configs + + Get a list of all AI Configs in the given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiGetAIConfigsRequest + */ + GetAIConfigs(ctx context.Context, projectKey string) ApiGetAIConfigsRequest + + // GetAIConfigsExecute executes the request + // @return AIConfigs + GetAIConfigsExecute(r ApiGetAIConfigsRequest) (*AIConfigs, *http.Response, error) + + /* + GetModelConfig Get AI model config + + Get an AI model config by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param modelConfigKey + @return ApiGetModelConfigRequest + */ + GetModelConfig(ctx context.Context, projectKey string, modelConfigKey string) ApiGetModelConfigRequest + + // GetModelConfigExecute executes the request + // @return ModelConfig + GetModelConfigExecute(r ApiGetModelConfigRequest) (*ModelConfig, *http.Response, error) + + /* + ListModelConfigs List AI model configs + + Get all AI model configs for a project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiListModelConfigsRequest + */ + ListModelConfigs(ctx context.Context, projectKey string) ApiListModelConfigsRequest + + // ListModelConfigsExecute executes the request + // @return []ModelConfig + ListModelConfigsExecute(r ApiListModelConfigsRequest) ([]ModelConfig, *http.Response, error) + + /* + PatchAIConfig Update AI Config + + Edit an existing AI Config. + +The request body must be a JSON object of the fields to update. The values you include replace the existing values for the fields. + +Here's an example: + ``` + { + "description": "Example updated description", + "tags": ["new-tag"] + } + ``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiPatchAIConfigRequest + */ + PatchAIConfig(ctx context.Context, projectKey string, configKey string) ApiPatchAIConfigRequest + + // PatchAIConfigExecute executes the request + // @return AIConfig + PatchAIConfigExecute(r ApiPatchAIConfigRequest) (*AIConfig, *http.Response, error) + + /* + PatchAIConfigVariation Update AI Config variation + + Edit an existing variation of an AI Config. This creates a new version of the variation. + +The request body must be a JSON object of the fields to update. The values you include replace the existing values for the fields. + +Here's an example: +``` + { + "messages": [ + { + "role": "system", + "content": "The new message" + } + ] + } +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiPatchAIConfigVariationRequest + */ + PatchAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiPatchAIConfigVariationRequest + + // PatchAIConfigVariationExecute executes the request + // @return AIConfigVariation + PatchAIConfigVariationExecute(r ApiPatchAIConfigVariationRequest) (*AIConfigVariation, *http.Response, error) + + /* + PostAIConfig Create new AI Config + + Create a new AI Config within the given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiPostAIConfigRequest + */ + PostAIConfig(ctx context.Context, projectKey string) ApiPostAIConfigRequest + + // PostAIConfigExecute executes the request + // @return AIConfig + PostAIConfigExecute(r ApiPostAIConfigRequest) (*AIConfig, *http.Response, error) + + /* + PostAIConfigVariation Create AI Config variation + + Create a new variation for a given AI Config. + +The model in the request body requires a modelName and parameters, for example: + +``` + "model": { + "modelName": "claude-3-opus-20240229", + "parameters": { + "max_tokens": 1024 + } + } +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiPostAIConfigVariationRequest + */ + PostAIConfigVariation(ctx context.Context, projectKey string, configKey string) ApiPostAIConfigVariationRequest + + // PostAIConfigVariationExecute executes the request + // @return AIConfigVariation + PostAIConfigVariationExecute(r ApiPostAIConfigVariationRequest) (*AIConfigVariation, *http.Response, error) + + /* + PostModelConfig Create an AI model config + + Create an AI model config. You can use this in any variation for any AI Config in your project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiPostModelConfigRequest + */ + PostModelConfig(ctx context.Context, projectKey string) ApiPostModelConfigRequest + + // PostModelConfigExecute executes the request + // @return ModelConfig + PostModelConfigExecute(r ApiPostModelConfigRequest) (*ModelConfig, *http.Response, error) +} + +// AIConfigsBetaApiService AIConfigsBetaApi service +type AIConfigsBetaApiService service + +type ApiDeleteAIConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string +} + +// Version of the endpoint. +func (r ApiDeleteAIConfigRequest) LDAPIVersion(lDAPIVersion string) ApiDeleteAIConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiDeleteAIConfigRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteAIConfigExecute(r) +} + +/* +DeleteAIConfig Delete AI Config + +Delete an existing AI Config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiDeleteAIConfigRequest +*/ +func (a *AIConfigsBetaApiService) DeleteAIConfig(ctx context.Context, projectKey string, configKey string) ApiDeleteAIConfigRequest { + return ApiDeleteAIConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +func (a *AIConfigsBetaApiService) DeleteAIConfigExecute(r ApiDeleteAIConfigRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.DeleteAIConfig") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteAIConfigVariationRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + variationKey string +} + +// Version of the endpoint. +func (r ApiDeleteAIConfigVariationRequest) LDAPIVersion(lDAPIVersion string) ApiDeleteAIConfigVariationRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiDeleteAIConfigVariationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteAIConfigVariationExecute(r) +} + +/* +DeleteAIConfigVariation Delete AI Config variation + +Delete a specific variation of an AI Config by config key and variation key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiDeleteAIConfigVariationRequest +*/ +func (a *AIConfigsBetaApiService) DeleteAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiDeleteAIConfigVariationRequest { + return ApiDeleteAIConfigVariationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + variationKey: variationKey, + } +} + +// Execute executes the request +func (a *AIConfigsBetaApiService) DeleteAIConfigVariationExecute(r ApiDeleteAIConfigVariationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.DeleteAIConfigVariation") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"variationKey"+"}", url.PathEscape(parameterToString(r.variationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteModelConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + modelConfigKey string +} + +// Version of the endpoint. +func (r ApiDeleteModelConfigRequest) LDAPIVersion(lDAPIVersion string) ApiDeleteModelConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiDeleteModelConfigRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteModelConfigExecute(r) +} + +/* +DeleteModelConfig Delete an AI model config + +Delete an AI model config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param modelConfigKey + @return ApiDeleteModelConfigRequest +*/ +func (a *AIConfigsBetaApiService) DeleteModelConfig(ctx context.Context, projectKey string, modelConfigKey string) ApiDeleteModelConfigRequest { + return ApiDeleteModelConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + modelConfigKey: modelConfigKey, + } +} + +// Execute executes the request +func (a *AIConfigsBetaApiService) DeleteModelConfigExecute(r ApiDeleteModelConfigRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.DeleteModelConfig") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/model-configs/{modelConfigKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"modelConfigKey"+"}", url.PathEscape(parameterToString(r.modelConfigKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetAIConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string +} + +// Version of the endpoint. +func (r ApiGetAIConfigRequest) LDAPIVersion(lDAPIVersion string) ApiGetAIConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiGetAIConfigRequest) Execute() (*AIConfig, *http.Response, error) { + return r.ApiService.GetAIConfigExecute(r) +} + +/* +GetAIConfig Get AI Config + +Retrieve a specific AI Config by its key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigRequest +*/ +func (a *AIConfigsBetaApiService) GetAIConfig(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigRequest { + return ApiGetAIConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +// @return AIConfig +func (a *AIConfigsBetaApiService) GetAIConfigExecute(r ApiGetAIConfigRequest) (*AIConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetAIConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAIConfigMetricsRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + from *int32 + to *int32 + env *string +} + +// Version of the endpoint. +func (r ApiGetAIConfigMetricsRequest) LDAPIVersion(lDAPIVersion string) ApiGetAIConfigMetricsRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// The starting time, as milliseconds since epoch (inclusive). +func (r ApiGetAIConfigMetricsRequest) From(from int32) ApiGetAIConfigMetricsRequest { + r.from = &from + return r +} + +// The ending time, as milliseconds since epoch (exclusive). May not be more than 100 days after `from`. +func (r ApiGetAIConfigMetricsRequest) To(to int32) ApiGetAIConfigMetricsRequest { + r.to = &to + return r +} + +// An environment key. Only metrics from this environment will be included. +func (r ApiGetAIConfigMetricsRequest) Env(env string) ApiGetAIConfigMetricsRequest { + r.env = &env + return r +} + +func (r ApiGetAIConfigMetricsRequest) Execute() (*Metrics, *http.Response, error) { + return r.ApiService.GetAIConfigMetricsExecute(r) +} + +/* +GetAIConfigMetrics Get AI Config metrics + +Retrieve usage metrics for an AI Config by config key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigMetricsRequest +*/ +func (a *AIConfigsBetaApiService) GetAIConfigMetrics(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigMetricsRequest { + return ApiGetAIConfigMetricsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +// @return Metrics +func (a *AIConfigsBetaApiService) GetAIConfigMetricsExecute(r ApiGetAIConfigMetricsRequest) (*Metrics, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Metrics + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetAIConfigMetrics") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/metrics" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + if r.from == nil { + return localVarReturnValue, nil, reportError("from is required and must be specified") + } + if r.to == nil { + return localVarReturnValue, nil, reportError("to is required and must be specified") + } + if r.env == nil { + return localVarReturnValue, nil, reportError("env is required and must be specified") + } + + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + localVarQueryParams.Add("env", parameterToString(*r.env, "")) + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAIConfigMetricsByVariationRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + from *int32 + to *int32 + env *string +} + +// Version of the endpoint. +func (r ApiGetAIConfigMetricsByVariationRequest) LDAPIVersion(lDAPIVersion string) ApiGetAIConfigMetricsByVariationRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// The starting time, as milliseconds since epoch (inclusive). +func (r ApiGetAIConfigMetricsByVariationRequest) From(from int32) ApiGetAIConfigMetricsByVariationRequest { + r.from = &from + return r +} + +// The ending time, as milliseconds since epoch (exclusive). May not be more than 100 days after `from`. +func (r ApiGetAIConfigMetricsByVariationRequest) To(to int32) ApiGetAIConfigMetricsByVariationRequest { + r.to = &to + return r +} + +// An environment key. Only metrics from this environment will be included. +func (r ApiGetAIConfigMetricsByVariationRequest) Env(env string) ApiGetAIConfigMetricsByVariationRequest { + r.env = &env + return r +} + +func (r ApiGetAIConfigMetricsByVariationRequest) Execute() ([]MetricByVariation, *http.Response, error) { + return r.ApiService.GetAIConfigMetricsByVariationExecute(r) +} + +/* +GetAIConfigMetricsByVariation Get AI Config metrics by variation + +Retrieve usage metrics for an AI Config by config key, with results split by variation. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiGetAIConfigMetricsByVariationRequest +*/ +func (a *AIConfigsBetaApiService) GetAIConfigMetricsByVariation(ctx context.Context, projectKey string, configKey string) ApiGetAIConfigMetricsByVariationRequest { + return ApiGetAIConfigMetricsByVariationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +// @return []MetricByVariation +func (a *AIConfigsBetaApiService) GetAIConfigMetricsByVariationExecute(r ApiGetAIConfigMetricsByVariationRequest) ([]MetricByVariation, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []MetricByVariation + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetAIConfigMetricsByVariation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/metrics-by-variation" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + if r.from == nil { + return localVarReturnValue, nil, reportError("from is required and must be specified") + } + if r.to == nil { + return localVarReturnValue, nil, reportError("to is required and must be specified") + } + if r.env == nil { + return localVarReturnValue, nil, reportError("env is required and must be specified") + } + + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + localVarQueryParams.Add("env", parameterToString(*r.env, "")) + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAIConfigVariationRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + variationKey string +} + +// Version of the endpoint. +func (r ApiGetAIConfigVariationRequest) LDAPIVersion(lDAPIVersion string) ApiGetAIConfigVariationRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiGetAIConfigVariationRequest) Execute() (*AIConfigVariationsResponse, *http.Response, error) { + return r.ApiService.GetAIConfigVariationExecute(r) +} + +/* +GetAIConfigVariation Get AI Config variation + +Get an AI Config variation by key. The response includes all variation versions for the given variation key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiGetAIConfigVariationRequest +*/ +func (a *AIConfigsBetaApiService) GetAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiGetAIConfigVariationRequest { + return ApiGetAIConfigVariationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + variationKey: variationKey, + } +} + +// Execute executes the request +// @return AIConfigVariationsResponse +func (a *AIConfigsBetaApiService) GetAIConfigVariationExecute(r ApiGetAIConfigVariationRequest) (*AIConfigVariationsResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfigVariationsResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetAIConfigVariation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"variationKey"+"}", url.PathEscape(parameterToString(r.variationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAIConfigsRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + sort *string + limit *int32 + offset *int32 + filter *string +} + +// Version of the endpoint. +func (r ApiGetAIConfigsRequest) LDAPIVersion(lDAPIVersion string) ApiGetAIConfigsRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// A sort to apply to the list of AI Configs. +func (r ApiGetAIConfigsRequest) Sort(sort string) ApiGetAIConfigsRequest { + r.sort = &sort + return r +} + +// The number of AI Configs to return. +func (r ApiGetAIConfigsRequest) Limit(limit int32) ApiGetAIConfigsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetAIConfigsRequest) Offset(offset int32) ApiGetAIConfigsRequest { + r.offset = &offset + return r +} + +// A filter to apply to the list of AI Configs. +func (r ApiGetAIConfigsRequest) Filter(filter string) ApiGetAIConfigsRequest { + r.filter = &filter + return r +} + +func (r ApiGetAIConfigsRequest) Execute() (*AIConfigs, *http.Response, error) { + return r.ApiService.GetAIConfigsExecute(r) +} + +/* +GetAIConfigs List AI Configs + +Get a list of all AI Configs in the given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiGetAIConfigsRequest +*/ +func (a *AIConfigsBetaApiService) GetAIConfigs(ctx context.Context, projectKey string) ApiGetAIConfigsRequest { + return ApiGetAIConfigsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return AIConfigs +func (a *AIConfigsBetaApiService) GetAIConfigsExecute(r ApiGetAIConfigsRequest) (*AIConfigs, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfigs + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetAIConfigs") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetModelConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + modelConfigKey string +} + +// Version of the endpoint. +func (r ApiGetModelConfigRequest) LDAPIVersion(lDAPIVersion string) ApiGetModelConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiGetModelConfigRequest) Execute() (*ModelConfig, *http.Response, error) { + return r.ApiService.GetModelConfigExecute(r) +} + +/* +GetModelConfig Get AI model config + +Get an AI model config by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param modelConfigKey + @return ApiGetModelConfigRequest +*/ +func (a *AIConfigsBetaApiService) GetModelConfig(ctx context.Context, projectKey string, modelConfigKey string) ApiGetModelConfigRequest { + return ApiGetModelConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + modelConfigKey: modelConfigKey, + } +} + +// Execute executes the request +// @return ModelConfig +func (a *AIConfigsBetaApiService) GetModelConfigExecute(r ApiGetModelConfigRequest) (*ModelConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ModelConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.GetModelConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/model-configs/{modelConfigKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"modelConfigKey"+"}", url.PathEscape(parameterToString(r.modelConfigKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiListModelConfigsRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string +} + +// Version of the endpoint. +func (r ApiListModelConfigsRequest) LDAPIVersion(lDAPIVersion string) ApiListModelConfigsRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +func (r ApiListModelConfigsRequest) Execute() ([]ModelConfig, *http.Response, error) { + return r.ApiService.ListModelConfigsExecute(r) +} + +/* +ListModelConfigs List AI model configs + +Get all AI model configs for a project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiListModelConfigsRequest +*/ +func (a *AIConfigsBetaApiService) ListModelConfigs(ctx context.Context, projectKey string) ApiListModelConfigsRequest { + return ApiListModelConfigsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return []ModelConfig +func (a *AIConfigsBetaApiService) ListModelConfigsExecute(r ApiListModelConfigsRequest) ([]ModelConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []ModelConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.ListModelConfigs") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/model-configs" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchAIConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + aIConfigPatch *AIConfigPatch +} + +// Version of the endpoint. +func (r ApiPatchAIConfigRequest) LDAPIVersion(lDAPIVersion string) ApiPatchAIConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// AI Config object to update +func (r ApiPatchAIConfigRequest) AIConfigPatch(aIConfigPatch AIConfigPatch) ApiPatchAIConfigRequest { + r.aIConfigPatch = &aIConfigPatch + return r +} + +func (r ApiPatchAIConfigRequest) Execute() (*AIConfig, *http.Response, error) { + return r.ApiService.PatchAIConfigExecute(r) +} + +/* +PatchAIConfig Update AI Config + +Edit an existing AI Config. + +The request body must be a JSON object of the fields to update. The values you include replace the existing values for the fields. + +Here's an example: + ``` + { + "description": "Example updated description", + "tags": ["new-tag"] + } + ``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiPatchAIConfigRequest +*/ +func (a *AIConfigsBetaApiService) PatchAIConfig(ctx context.Context, projectKey string, configKey string) ApiPatchAIConfigRequest { + return ApiPatchAIConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +// @return AIConfig +func (a *AIConfigsBetaApiService) PatchAIConfigExecute(r ApiPatchAIConfigRequest) (*AIConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.PatchAIConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + // body params + localVarPostBody = r.aIConfigPatch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchAIConfigVariationRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + variationKey string + aIConfigVariationPatch *AIConfigVariationPatch +} + +// Version of the endpoint. +func (r ApiPatchAIConfigVariationRequest) LDAPIVersion(lDAPIVersion string) ApiPatchAIConfigVariationRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// AI Config variation object to update +func (r ApiPatchAIConfigVariationRequest) AIConfigVariationPatch(aIConfigVariationPatch AIConfigVariationPatch) ApiPatchAIConfigVariationRequest { + r.aIConfigVariationPatch = &aIConfigVariationPatch + return r +} + +func (r ApiPatchAIConfigVariationRequest) Execute() (*AIConfigVariation, *http.Response, error) { + return r.ApiService.PatchAIConfigVariationExecute(r) +} + +/* +PatchAIConfigVariation Update AI Config variation + +Edit an existing variation of an AI Config. This creates a new version of the variation. + +The request body must be a JSON object of the fields to update. The values you include replace the existing values for the fields. + +Here's an example: +``` + { + "messages": [ + { + "role": "system", + "content": "The new message" + } + ] + } +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @param variationKey + @return ApiPatchAIConfigVariationRequest +*/ +func (a *AIConfigsBetaApiService) PatchAIConfigVariation(ctx context.Context, projectKey string, configKey string, variationKey string) ApiPatchAIConfigVariationRequest { + return ApiPatchAIConfigVariationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + variationKey: variationKey, + } +} + +// Execute executes the request +// @return AIConfigVariation +func (a *AIConfigsBetaApiService) PatchAIConfigVariationExecute(r ApiPatchAIConfigVariationRequest) (*AIConfigVariation, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfigVariation + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.PatchAIConfigVariation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"variationKey"+"}", url.PathEscape(parameterToString(r.variationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + // body params + localVarPostBody = r.aIConfigVariationPatch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostAIConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + aIConfigPost *AIConfigPost +} + +// Version of the endpoint. +func (r ApiPostAIConfigRequest) LDAPIVersion(lDAPIVersion string) ApiPostAIConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// AI Config object to create +func (r ApiPostAIConfigRequest) AIConfigPost(aIConfigPost AIConfigPost) ApiPostAIConfigRequest { + r.aIConfigPost = &aIConfigPost + return r +} + +func (r ApiPostAIConfigRequest) Execute() (*AIConfig, *http.Response, error) { + return r.ApiService.PostAIConfigExecute(r) +} + +/* +PostAIConfig Create new AI Config + +Create a new AI Config within the given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiPostAIConfigRequest +*/ +func (a *AIConfigsBetaApiService) PostAIConfig(ctx context.Context, projectKey string) ApiPostAIConfigRequest { + return ApiPostAIConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return AIConfig +func (a *AIConfigsBetaApiService) PostAIConfigExecute(r ApiPostAIConfigRequest) (*AIConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.PostAIConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + if r.aIConfigPost == nil { + return localVarReturnValue, nil, reportError("aIConfigPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + // body params + localVarPostBody = r.aIConfigPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostAIConfigVariationRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + configKey string + aIConfigVariationPost *AIConfigVariationPost +} + +// Version of the endpoint. +func (r ApiPostAIConfigVariationRequest) LDAPIVersion(lDAPIVersion string) ApiPostAIConfigVariationRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// AI Config variation object to create +func (r ApiPostAIConfigVariationRequest) AIConfigVariationPost(aIConfigVariationPost AIConfigVariationPost) ApiPostAIConfigVariationRequest { + r.aIConfigVariationPost = &aIConfigVariationPost + return r +} + +func (r ApiPostAIConfigVariationRequest) Execute() (*AIConfigVariation, *http.Response, error) { + return r.ApiService.PostAIConfigVariationExecute(r) +} + +/* +PostAIConfigVariation Create AI Config variation + +Create a new variation for a given AI Config. + +The model in the request body requires a modelName and parameters, for example: + +``` + "model": { + "modelName": "claude-3-opus-20240229", + "parameters": { + "max_tokens": 1024 + } + } +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @param configKey + @return ApiPostAIConfigVariationRequest +*/ +func (a *AIConfigsBetaApiService) PostAIConfigVariation(ctx context.Context, projectKey string, configKey string) ApiPostAIConfigVariationRequest { + return ApiPostAIConfigVariationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + configKey: configKey, + } +} + +// Execute executes the request +// @return AIConfigVariation +func (a *AIConfigsBetaApiService) PostAIConfigVariationExecute(r ApiPostAIConfigVariationRequest) (*AIConfigVariation, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AIConfigVariation + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.PostAIConfigVariation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"configKey"+"}", url.PathEscape(parameterToString(r.configKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + if r.aIConfigVariationPost == nil { + return localVarReturnValue, nil, reportError("aIConfigVariationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + // body params + localVarPostBody = r.aIConfigVariationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostModelConfigRequest struct { + ctx context.Context + ApiService AIConfigsBetaApi + lDAPIVersion *string + projectKey string + modelConfigPost *ModelConfigPost +} + +// Version of the endpoint. +func (r ApiPostModelConfigRequest) LDAPIVersion(lDAPIVersion string) ApiPostModelConfigRequest { + r.lDAPIVersion = &lDAPIVersion + return r +} + +// AI model config object to create +func (r ApiPostModelConfigRequest) ModelConfigPost(modelConfigPost ModelConfigPost) ApiPostModelConfigRequest { + r.modelConfigPost = &modelConfigPost + return r +} + +func (r ApiPostModelConfigRequest) Execute() (*ModelConfig, *http.Response, error) { + return r.ApiService.PostModelConfigExecute(r) +} + +/* +PostModelConfig Create an AI model config + +Create an AI model config. You can use this in any variation for any AI Config in your project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey + @return ApiPostModelConfigRequest +*/ +func (a *AIConfigsBetaApiService) PostModelConfig(ctx context.Context, projectKey string) ApiPostModelConfigRequest { + return ApiPostModelConfigRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return ModelConfig +func (a *AIConfigsBetaApiService) PostModelConfigExecute(r ApiPostModelConfigRequest) (*ModelConfig, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ModelConfig + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AIConfigsBetaApiService.PostModelConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/ai-configs/model-configs" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.lDAPIVersion == nil { + return localVarReturnValue, nil, reportError("lDAPIVersion is required and must be specified") + } + if r.modelConfigPost == nil { + return localVarReturnValue, nil, reportError("modelConfigPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarHeaderParams["LD-API-Version"] = parameterToString(*r.lDAPIVersion, "") + // body params + localVarPostBody = r.modelConfigPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_announcements.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_announcements.go new file mode 100644 index 00000000..5cbc23f8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_announcements.go @@ -0,0 +1,754 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AnnouncementsApi interface { + + /* + CreateAnnouncementPublic Create an announcement + + Create an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateAnnouncementPublicRequest + */ + CreateAnnouncementPublic(ctx context.Context) ApiCreateAnnouncementPublicRequest + + // CreateAnnouncementPublicExecute executes the request + // @return AnnouncementResponse + CreateAnnouncementPublicExecute(r ApiCreateAnnouncementPublicRequest) (*AnnouncementResponse, *http.Response, error) + + /* + DeleteAnnouncementPublic Delete an announcement + + Delete an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param announcementId + @return ApiDeleteAnnouncementPublicRequest + */ + DeleteAnnouncementPublic(ctx context.Context, announcementId string) ApiDeleteAnnouncementPublicRequest + + // DeleteAnnouncementPublicExecute executes the request + DeleteAnnouncementPublicExecute(r ApiDeleteAnnouncementPublicRequest) (*http.Response, error) + + /* + GetAnnouncementsPublic Get announcements + + Get announcements + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAnnouncementsPublicRequest + */ + GetAnnouncementsPublic(ctx context.Context) ApiGetAnnouncementsPublicRequest + + // GetAnnouncementsPublicExecute executes the request + // @return GetAnnouncementsPublic200Response + GetAnnouncementsPublicExecute(r ApiGetAnnouncementsPublicRequest) (*GetAnnouncementsPublic200Response, *http.Response, error) + + /* + UpdateAnnouncementPublic Update an announcement + + Update an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param announcementId + @return ApiUpdateAnnouncementPublicRequest + */ + UpdateAnnouncementPublic(ctx context.Context, announcementId string) ApiUpdateAnnouncementPublicRequest + + // UpdateAnnouncementPublicExecute executes the request + // @return AnnouncementResponse + UpdateAnnouncementPublicExecute(r ApiUpdateAnnouncementPublicRequest) (*AnnouncementResponse, *http.Response, error) +} + +// AnnouncementsApiService AnnouncementsApi service +type AnnouncementsApiService service + +type ApiCreateAnnouncementPublicRequest struct { + ctx context.Context + ApiService AnnouncementsApi + createAnnouncementBody *CreateAnnouncementBody +} + +// Announcement request body +func (r ApiCreateAnnouncementPublicRequest) CreateAnnouncementBody(createAnnouncementBody CreateAnnouncementBody) ApiCreateAnnouncementPublicRequest { + r.createAnnouncementBody = &createAnnouncementBody + return r +} + +func (r ApiCreateAnnouncementPublicRequest) Execute() (*AnnouncementResponse, *http.Response, error) { + return r.ApiService.CreateAnnouncementPublicExecute(r) +} + +/* +CreateAnnouncementPublic Create an announcement + +Create an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateAnnouncementPublicRequest +*/ +func (a *AnnouncementsApiService) CreateAnnouncementPublic(ctx context.Context) ApiCreateAnnouncementPublicRequest { + return ApiCreateAnnouncementPublicRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return AnnouncementResponse +func (a *AnnouncementsApiService) CreateAnnouncementPublicExecute(r ApiCreateAnnouncementPublicRequest) (*AnnouncementResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AnnouncementResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AnnouncementsApiService.CreateAnnouncementPublic") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/announcements" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createAnnouncementBody == nil { + return localVarReturnValue, nil, reportError("createAnnouncementBody is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createAnnouncementBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteAnnouncementPublicRequest struct { + ctx context.Context + ApiService AnnouncementsApi + announcementId string +} + +func (r ApiDeleteAnnouncementPublicRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteAnnouncementPublicExecute(r) +} + +/* +DeleteAnnouncementPublic Delete an announcement + +Delete an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param announcementId + @return ApiDeleteAnnouncementPublicRequest +*/ +func (a *AnnouncementsApiService) DeleteAnnouncementPublic(ctx context.Context, announcementId string) ApiDeleteAnnouncementPublicRequest { + return ApiDeleteAnnouncementPublicRequest{ + ApiService: a, + ctx: ctx, + announcementId: announcementId, + } +} + +// Execute executes the request +func (a *AnnouncementsApiService) DeleteAnnouncementPublicExecute(r ApiDeleteAnnouncementPublicRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AnnouncementsApiService.DeleteAnnouncementPublic") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/announcements/{announcementId}" + localVarPath = strings.Replace(localVarPath, "{"+"announcementId"+"}", url.PathEscape(parameterToString(r.announcementId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetAnnouncementsPublicRequest struct { + ctx context.Context + ApiService AnnouncementsApi + status *string + limit *int32 + offset *int32 +} + +// Filter announcements by status. +func (r ApiGetAnnouncementsPublicRequest) Status(status string) ApiGetAnnouncementsPublicRequest { + r.status = &status + return r +} + +// The number of announcements to return. +func (r ApiGetAnnouncementsPublicRequest) Limit(limit int32) ApiGetAnnouncementsPublicRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetAnnouncementsPublicRequest) Offset(offset int32) ApiGetAnnouncementsPublicRequest { + r.offset = &offset + return r +} + +func (r ApiGetAnnouncementsPublicRequest) Execute() (*GetAnnouncementsPublic200Response, *http.Response, error) { + return r.ApiService.GetAnnouncementsPublicExecute(r) +} + +/* +GetAnnouncementsPublic Get announcements + +Get announcements + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAnnouncementsPublicRequest +*/ +func (a *AnnouncementsApiService) GetAnnouncementsPublic(ctx context.Context) ApiGetAnnouncementsPublicRequest { + return ApiGetAnnouncementsPublicRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return GetAnnouncementsPublic200Response +func (a *AnnouncementsApiService) GetAnnouncementsPublicExecute(r ApiGetAnnouncementsPublicRequest) (*GetAnnouncementsPublic200Response, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *GetAnnouncementsPublic200Response + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AnnouncementsApiService.GetAnnouncementsPublic") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/announcements" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.status != nil { + localVarQueryParams.Add("status", parameterToString(*r.status, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateAnnouncementPublicRequest struct { + ctx context.Context + ApiService AnnouncementsApi + announcementId string + announcementPatchOperation *[]AnnouncementPatchOperation +} + +// Update announcement request body +func (r ApiUpdateAnnouncementPublicRequest) AnnouncementPatchOperation(announcementPatchOperation []AnnouncementPatchOperation) ApiUpdateAnnouncementPublicRequest { + r.announcementPatchOperation = &announcementPatchOperation + return r +} + +func (r ApiUpdateAnnouncementPublicRequest) Execute() (*AnnouncementResponse, *http.Response, error) { + return r.ApiService.UpdateAnnouncementPublicExecute(r) +} + +/* +UpdateAnnouncementPublic Update an announcement + +Update an announcement + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param announcementId + @return ApiUpdateAnnouncementPublicRequest +*/ +func (a *AnnouncementsApiService) UpdateAnnouncementPublic(ctx context.Context, announcementId string) ApiUpdateAnnouncementPublicRequest { + return ApiUpdateAnnouncementPublicRequest{ + ApiService: a, + ctx: ctx, + announcementId: announcementId, + } +} + +// Execute executes the request +// @return AnnouncementResponse +func (a *AnnouncementsApiService) UpdateAnnouncementPublicExecute(r ApiUpdateAnnouncementPublicRequest) (*AnnouncementResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AnnouncementResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AnnouncementsApiService.UpdateAnnouncementPublic") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/announcements/{announcementId}" + localVarPath = strings.Replace(localVarPath, "{"+"announcementId"+"}", url.PathEscape(parameterToString(r.announcementId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.announcementPatchOperation == nil { + return localVarReturnValue, nil, reportError("announcementPatchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.announcementPatchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_applications_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_applications_beta.go new file mode 100644 index 00000000..432522e2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_applications_beta.go @@ -0,0 +1,1426 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ApplicationsBetaApi interface { + + /* + DeleteApplication Delete application + + Delete an application. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiDeleteApplicationRequest + */ + DeleteApplication(ctx context.Context, applicationKey string) ApiDeleteApplicationRequest + + // DeleteApplicationExecute executes the request + DeleteApplicationExecute(r ApiDeleteApplicationRequest) (*http.Response, error) + + /* + DeleteApplicationVersion Delete application version + + Delete an application version. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @param versionKey The application version key + @return ApiDeleteApplicationVersionRequest + */ + DeleteApplicationVersion(ctx context.Context, applicationKey string, versionKey string) ApiDeleteApplicationVersionRequest + + // DeleteApplicationVersionExecute executes the request + DeleteApplicationVersionExecute(r ApiDeleteApplicationVersionRequest) (*http.Response, error) + + /* + GetApplication Get application by key + + +Retrieve an application by the application key. + +### Expanding the application response + +LaunchDarkly supports expanding the "Get application" response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `flags` includes details on the flags that have been evaluated by the application + +For example, use `?expand=flags` to include the `flags` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiGetApplicationRequest + */ + GetApplication(ctx context.Context, applicationKey string) ApiGetApplicationRequest + + // GetApplicationExecute executes the request + // @return ApplicationRep + GetApplicationExecute(r ApiGetApplicationRequest) (*ApplicationRep, *http.Response, error) + + /* + GetApplicationVersions Get application versions by application key + + Get a list of versions for a specific application in an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiGetApplicationVersionsRequest + */ + GetApplicationVersions(ctx context.Context, applicationKey string) ApiGetApplicationVersionsRequest + + // GetApplicationVersionsExecute executes the request + // @return ApplicationVersionsCollectionRep + GetApplicationVersionsExecute(r ApiGetApplicationVersionsRequest) (*ApplicationVersionsCollectionRep, *http.Response, error) + + /* + GetApplications Get applications + + +Get a list of applications. + +### Expanding the applications response + +LaunchDarkly supports expanding the "Get applications" response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `flags` includes details on the flags that have been evaluated by the application + +For example, use `?expand=flags` to include the `flags` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetApplicationsRequest + */ + GetApplications(ctx context.Context) ApiGetApplicationsRequest + + // GetApplicationsExecute executes the request + // @return ApplicationCollectionRep + GetApplicationsExecute(r ApiGetApplicationsRequest) (*ApplicationCollectionRep, *http.Response, error) + + /* + PatchApplication Update application + + Update an application. You can update the `description` and `kind` fields. Requires a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes to the application. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiPatchApplicationRequest + */ + PatchApplication(ctx context.Context, applicationKey string) ApiPatchApplicationRequest + + // PatchApplicationExecute executes the request + // @return ApplicationRep + PatchApplicationExecute(r ApiPatchApplicationRequest) (*ApplicationRep, *http.Response, error) + + /* + PatchApplicationVersion Update application version + + Update an application version. You can update the `supported` field. Requires a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes to the application version. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @param versionKey The application version key + @return ApiPatchApplicationVersionRequest + */ + PatchApplicationVersion(ctx context.Context, applicationKey string, versionKey string) ApiPatchApplicationVersionRequest + + // PatchApplicationVersionExecute executes the request + // @return ApplicationVersionRep + PatchApplicationVersionExecute(r ApiPatchApplicationVersionRequest) (*ApplicationVersionRep, *http.Response, error) +} + +// ApplicationsBetaApiService ApplicationsBetaApi service +type ApplicationsBetaApiService service + +type ApiDeleteApplicationRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string +} + +func (r ApiDeleteApplicationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteApplicationExecute(r) +} + +/* +DeleteApplication Delete application + +Delete an application. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiDeleteApplicationRequest +*/ +func (a *ApplicationsBetaApiService) DeleteApplication(ctx context.Context, applicationKey string) ApiDeleteApplicationRequest { + return ApiDeleteApplicationRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + } +} + +// Execute executes the request +func (a *ApplicationsBetaApiService) DeleteApplicationExecute(r ApiDeleteApplicationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.DeleteApplication") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteApplicationVersionRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string + versionKey string +} + +func (r ApiDeleteApplicationVersionRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteApplicationVersionExecute(r) +} + +/* +DeleteApplicationVersion Delete application version + +Delete an application version. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @param versionKey The application version key + @return ApiDeleteApplicationVersionRequest +*/ +func (a *ApplicationsBetaApiService) DeleteApplicationVersion(ctx context.Context, applicationKey string, versionKey string) ApiDeleteApplicationVersionRequest { + return ApiDeleteApplicationVersionRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + versionKey: versionKey, + } +} + +// Execute executes the request +func (a *ApplicationsBetaApiService) DeleteApplicationVersionExecute(r ApiDeleteApplicationVersionRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.DeleteApplicationVersion") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}/versions/{versionKey}" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"versionKey"+"}", url.PathEscape(parameterToString(r.versionKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetApplicationRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. Options: `flags`. +func (r ApiGetApplicationRequest) Expand(expand string) ApiGetApplicationRequest { + r.expand = &expand + return r +} + +func (r ApiGetApplicationRequest) Execute() (*ApplicationRep, *http.Response, error) { + return r.ApiService.GetApplicationExecute(r) +} + +/* +GetApplication Get application by key + + +Retrieve an application by the application key. + +### Expanding the application response + +LaunchDarkly supports expanding the "Get application" response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `flags` includes details on the flags that have been evaluated by the application + +For example, use `?expand=flags` to include the `flags` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiGetApplicationRequest +*/ +func (a *ApplicationsBetaApiService) GetApplication(ctx context.Context, applicationKey string) ApiGetApplicationRequest { + return ApiGetApplicationRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + } +} + +// Execute executes the request +// @return ApplicationRep +func (a *ApplicationsBetaApiService) GetApplicationExecute(r ApiGetApplicationRequest) (*ApplicationRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApplicationRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.GetApplication") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetApplicationVersionsRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string + filter *string + limit *int64 + offset *int64 + sort *string +} + +// Accepts filter by `key`, `name`, `supported`, and `autoAdded`. To learn more about the filter syntax, read [Filtering applications and application versions](https://launchdarkly.com/docs/api/applications-beta#filtering-applications-and-application-versions). +func (r ApiGetApplicationVersionsRequest) Filter(filter string) ApiGetApplicationVersionsRequest { + r.filter = &filter + return r +} + +// The number of versions to return. Defaults to 50. +func (r ApiGetApplicationVersionsRequest) Limit(limit int64) ApiGetApplicationVersionsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetApplicationVersionsRequest) Offset(offset int64) ApiGetApplicationVersionsRequest { + r.offset = &offset + return r +} + +// Accepts sorting order and fields. Fields can be comma separated. Possible fields are `creationDate`, `name`. Examples: `sort=name` sort by names ascending, `sort=-name,creationDate` sort by names descending and creationDate ascending. +func (r ApiGetApplicationVersionsRequest) Sort(sort string) ApiGetApplicationVersionsRequest { + r.sort = &sort + return r +} + +func (r ApiGetApplicationVersionsRequest) Execute() (*ApplicationVersionsCollectionRep, *http.Response, error) { + return r.ApiService.GetApplicationVersionsExecute(r) +} + +/* +GetApplicationVersions Get application versions by application key + +Get a list of versions for a specific application in an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiGetApplicationVersionsRequest +*/ +func (a *ApplicationsBetaApiService) GetApplicationVersions(ctx context.Context, applicationKey string) ApiGetApplicationVersionsRequest { + return ApiGetApplicationVersionsRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + } +} + +// Execute executes the request +// @return ApplicationVersionsCollectionRep +func (a *ApplicationsBetaApiService) GetApplicationVersionsExecute(r ApiGetApplicationVersionsRequest) (*ApplicationVersionsCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApplicationVersionsCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.GetApplicationVersions") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}/versions" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetApplicationsRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + filter *string + limit *int64 + offset *int64 + sort *string + expand *string +} + +// Accepts filter by `key`, `name`, `kind`, and `autoAdded`. To learn more about the filter syntax, read [Filtering applications and application versions](https://launchdarkly.com/docs/api/applications-beta#filtering-applications-and-application-versions). +func (r ApiGetApplicationsRequest) Filter(filter string) ApiGetApplicationsRequest { + r.filter = &filter + return r +} + +// The number of applications to return. Defaults to 10. +func (r ApiGetApplicationsRequest) Limit(limit int64) ApiGetApplicationsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetApplicationsRequest) Offset(offset int64) ApiGetApplicationsRequest { + r.offset = &offset + return r +} + +// Accepts sorting order and fields. Fields can be comma separated. Possible fields are `creationDate`, `name`. Examples: `sort=name` sort by names ascending, `sort=-name,creationDate` sort by names descending and creationDate ascending. +func (r ApiGetApplicationsRequest) Sort(sort string) ApiGetApplicationsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. Options: `flags`. +func (r ApiGetApplicationsRequest) Expand(expand string) ApiGetApplicationsRequest { + r.expand = &expand + return r +} + +func (r ApiGetApplicationsRequest) Execute() (*ApplicationCollectionRep, *http.Response, error) { + return r.ApiService.GetApplicationsExecute(r) +} + +/* +GetApplications Get applications + + +Get a list of applications. + +### Expanding the applications response + +LaunchDarkly supports expanding the "Get applications" response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `flags` includes details on the flags that have been evaluated by the application + +For example, use `?expand=flags` to include the `flags` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetApplicationsRequest +*/ +func (a *ApplicationsBetaApiService) GetApplications(ctx context.Context) ApiGetApplicationsRequest { + return ApiGetApplicationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ApplicationCollectionRep +func (a *ApplicationsBetaApiService) GetApplicationsExecute(r ApiGetApplicationsRequest) (*ApplicationCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApplicationCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.GetApplications") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchApplicationRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchApplicationRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchApplicationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchApplicationRequest) Execute() (*ApplicationRep, *http.Response, error) { + return r.ApiService.PatchApplicationExecute(r) +} + +/* +PatchApplication Update application + +Update an application. You can update the `description` and `kind` fields. Requires a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes to the application. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @return ApiPatchApplicationRequest +*/ +func (a *ApplicationsBetaApiService) PatchApplication(ctx context.Context, applicationKey string) ApiPatchApplicationRequest { + return ApiPatchApplicationRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + } +} + +// Execute executes the request +// @return ApplicationRep +func (a *ApplicationsBetaApiService) PatchApplicationExecute(r ApiPatchApplicationRequest) (*ApplicationRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApplicationRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.PatchApplication") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchApplicationVersionRequest struct { + ctx context.Context + ApiService ApplicationsBetaApi + applicationKey string + versionKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchApplicationVersionRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchApplicationVersionRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchApplicationVersionRequest) Execute() (*ApplicationVersionRep, *http.Response, error) { + return r.ApiService.PatchApplicationVersionExecute(r) +} + +/* +PatchApplicationVersion Update application version + +Update an application version. You can update the `supported` field. Requires a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes to the application version. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param applicationKey The application key + @param versionKey The application version key + @return ApiPatchApplicationVersionRequest +*/ +func (a *ApplicationsBetaApiService) PatchApplicationVersion(ctx context.Context, applicationKey string, versionKey string) ApiPatchApplicationVersionRequest { + return ApiPatchApplicationVersionRequest{ + ApiService: a, + ctx: ctx, + applicationKey: applicationKey, + versionKey: versionKey, + } +} + +// Execute executes the request +// @return ApplicationVersionRep +func (a *ApplicationsBetaApiService) PatchApplicationVersionExecute(r ApiPatchApplicationVersionRequest) (*ApplicationVersionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApplicationVersionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApplicationsBetaApiService.PatchApplicationVersion") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/applications/{applicationKey}/versions/{versionKey}" + localVarPath = strings.Replace(localVarPath, "{"+"applicationKey"+"}", url.PathEscape(parameterToString(r.applicationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"versionKey"+"}", url.PathEscape(parameterToString(r.versionKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals.go new file mode 100644 index 00000000..d83d1d00 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals.go @@ -0,0 +1,2608 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ApprovalsApi interface { + + /* + DeleteApprovalRequest Delete approval request + + Delete an approval request. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiDeleteApprovalRequestRequest + */ + DeleteApprovalRequest(ctx context.Context, id string) ApiDeleteApprovalRequestRequest + + // DeleteApprovalRequestExecute executes the request + DeleteApprovalRequestExecute(r ApiDeleteApprovalRequestRequest) (*http.Response, error) + + /* + DeleteApprovalRequestForFlag Delete approval request for a flag + + Delete an approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiDeleteApprovalRequestForFlagRequest + */ + DeleteApprovalRequestForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiDeleteApprovalRequestForFlagRequest + + // DeleteApprovalRequestForFlagExecute executes the request + DeleteApprovalRequestForFlagExecute(r ApiDeleteApprovalRequestForFlagRequest) (*http.Response, error) + + /* + GetApprovalForFlag Get approval request for a flag + + Get a single approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiGetApprovalForFlagRequest + */ + GetApprovalForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetApprovalForFlagRequest + + // GetApprovalForFlagExecute executes the request + // @return FlagConfigApprovalRequestResponse + GetApprovalForFlagExecute(r ApiGetApprovalForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) + + /* + GetApprovalRequest Get approval request + + Get an approval request by approval request ID. + +### Expanding approval response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `environments` includes the environments the approval request relates to +- `flag` includes the flag the approval request belongs to +- `project` includes the project the approval request belongs to +- `resource` includes details on the resource (flag or segment) the approval request relates to + +For example, `expand=project,flag` includes the `project` and `flag` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiGetApprovalRequestRequest + */ + GetApprovalRequest(ctx context.Context, id string) ApiGetApprovalRequestRequest + + // GetApprovalRequestExecute executes the request + // @return ExpandableApprovalRequestResponse + GetApprovalRequestExecute(r ApiGetApprovalRequestRequest) (*ExpandableApprovalRequestResponse, *http.Response, error) + + /* + GetApprovalRequests List approval requests + + Get all approval requests. + +### Filtering approvals + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `notifyMemberIds` filters for only approvals that are assigned to a member in the specified list. For example: `filter=notifyMemberIds anyOf ["memberId1", "memberId2"]`. +- `requestorId` filters for only approvals that correspond to the ID of the member who requested the approval. For example: `filter=requestorId equals 457034721476302714390214`. +- `resourceId` filters for only approvals that correspond to the the specified resource identifier. For example: `filter=resourceId equals proj/my-project:env/my-environment:flag/my-flag`. +- `resourceKind` filters for only approvals that correspond to the specified resource kind. For example: `filter=resourceKind equals flag`. Currently, `flag` and `segment` resource kinds are supported. +- `reviewStatus` filters for only approvals which correspond to the review status in the specified list. The possible values are `approved`, `declined`, and `pending`. For example: `filter=reviewStatus anyOf ["pending", "approved"]`. +- `status` filters for only approvals which correspond to the status in the specified list. The possible values are `pending`, `scheduled`, `failed`, and `completed`. For example: `filter=status anyOf ["pending", "scheduled"]`. + +You can also apply multiple filters at once. For example, setting `filter=projectKey equals my-project, reviewStatus anyOf ["pending","approved"]` matches approval requests which correspond to the `my-project` project key, and a review status of either `pending` or `approved`. + +### Expanding approval response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `flag` includes the flag the approval request belongs to +- `project` includes the project the approval request belongs to +- `environments` includes the environments the approval request relates to + +For example, `expand=project,flag` includes the `project` and `flag` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetApprovalRequestsRequest + */ + GetApprovalRequests(ctx context.Context) ApiGetApprovalRequestsRequest + + // GetApprovalRequestsExecute executes the request + // @return ExpandableApprovalRequestsResponse + GetApprovalRequestsExecute(r ApiGetApprovalRequestsRequest) (*ExpandableApprovalRequestsResponse, *http.Response, error) + + /* + GetApprovalsForFlag List approval requests for a flag + + Get all approval requests for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetApprovalsForFlagRequest + */ + GetApprovalsForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetApprovalsForFlagRequest + + // GetApprovalsForFlagExecute executes the request + // @return FlagConfigApprovalRequestsResponse + GetApprovalsForFlagExecute(r ApiGetApprovalsForFlagRequest) (*FlagConfigApprovalRequestsResponse, *http.Response, error) + + /* + PostApprovalRequest Create approval request + + Create an approval request. + +This endpoint requires a list of `instructions`, in semantic patch format, that will be applied when the approval request is approved and applied. + +If you are creating an approval request for a flag, you can use the following `instructions`: + +- `addVariation` +- `removeVariation` +- `updateVariation` +- `updateDefaultVariation` + +For details on using these instructions, read [Update feature flag](https://launchdarkly.com/docs/api/feature-flags/patch-feature-flag). + +To create an approval for a flag specific to an environment, use [Create approval request for a flag](https://launchdarkly.com/docs/api/approvals/post-approval-request-for-flag). + +If you are creating an approval request for a segment, you can use the following read [Patch segment](https://launchdarkly.com/docs/api/segments/patch-segment) for details on the available `instructions`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostApprovalRequestRequest + */ + PostApprovalRequest(ctx context.Context) ApiPostApprovalRequestRequest + + // PostApprovalRequestExecute executes the request + // @return ApprovalRequestResponse + PostApprovalRequestExecute(r ApiPostApprovalRequestRequest) (*ApprovalRequestResponse, *http.Response, error) + + /* + PostApprovalRequestApply Apply approval request + + Apply an approval request that has been approved. This endpoint works with approval requests for either flag or segment changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiPostApprovalRequestApplyRequest + */ + PostApprovalRequestApply(ctx context.Context, id string) ApiPostApprovalRequestApplyRequest + + // PostApprovalRequestApplyExecute executes the request + // @return ApprovalRequestResponse + PostApprovalRequestApplyExecute(r ApiPostApprovalRequestApplyRequest) (*ApprovalRequestResponse, *http.Response, error) + + /* + PostApprovalRequestApplyForFlag Apply approval request for a flag + + Apply an approval request that has been approved. This endpoint requires a feature flag key, and can only be used for applying approval requests on flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiPostApprovalRequestApplyForFlagRequest + */ + PostApprovalRequestApplyForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPostApprovalRequestApplyForFlagRequest + + // PostApprovalRequestApplyForFlagExecute executes the request + // @return FlagConfigApprovalRequestResponse + PostApprovalRequestApplyForFlagExecute(r ApiPostApprovalRequestApplyForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) + + /* + PostApprovalRequestForFlag Create approval request for a flag + + Create an approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostApprovalRequestForFlagRequest + */ + PostApprovalRequestForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostApprovalRequestForFlagRequest + + // PostApprovalRequestForFlagExecute executes the request + // @return FlagConfigApprovalRequestResponse + PostApprovalRequestForFlagExecute(r ApiPostApprovalRequestForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) + + /* + PostApprovalRequestReview Review approval request + + Review an approval request by approving or denying changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiPostApprovalRequestReviewRequest + */ + PostApprovalRequestReview(ctx context.Context, id string) ApiPostApprovalRequestReviewRequest + + // PostApprovalRequestReviewExecute executes the request + // @return ApprovalRequestResponse + PostApprovalRequestReviewExecute(r ApiPostApprovalRequestReviewRequest) (*ApprovalRequestResponse, *http.Response, error) + + /* + PostApprovalRequestReviewForFlag Review approval request for a flag + + Review an approval request by approving or denying changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiPostApprovalRequestReviewForFlagRequest + */ + PostApprovalRequestReviewForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPostApprovalRequestReviewForFlagRequest + + // PostApprovalRequestReviewForFlagExecute executes the request + // @return FlagConfigApprovalRequestResponse + PostApprovalRequestReviewForFlagExecute(r ApiPostApprovalRequestReviewForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) + + /* + PostFlagCopyConfigApprovalRequest Create approval request to copy flag configurations across environments + + Create an approval request to copy a feature flag's configuration across environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key for the target environment + @return ApiPostFlagCopyConfigApprovalRequestRequest + */ + PostFlagCopyConfigApprovalRequest(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostFlagCopyConfigApprovalRequestRequest + + // PostFlagCopyConfigApprovalRequestExecute executes the request + // @return FlagConfigApprovalRequestResponse + PostFlagCopyConfigApprovalRequestExecute(r ApiPostFlagCopyConfigApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) +} + +// ApprovalsApiService ApprovalsApi service +type ApprovalsApiService service + +type ApiDeleteApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsApi + id string +} + +func (r ApiDeleteApprovalRequestRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteApprovalRequestExecute(r) +} + +/* +DeleteApprovalRequest Delete approval request + +Delete an approval request. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiDeleteApprovalRequestRequest +*/ +func (a *ApprovalsApiService) DeleteApprovalRequest(ctx context.Context, id string) ApiDeleteApprovalRequestRequest { + return ApiDeleteApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +func (a *ApprovalsApiService) DeleteApprovalRequestExecute(r ApiDeleteApprovalRequestRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.DeleteApprovalRequest") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteApprovalRequestForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiDeleteApprovalRequestForFlagRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteApprovalRequestForFlagExecute(r) +} + +/* +DeleteApprovalRequestForFlag Delete approval request for a flag + +Delete an approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiDeleteApprovalRequestForFlagRequest +*/ +func (a *ApprovalsApiService) DeleteApprovalRequestForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiDeleteApprovalRequestForFlagRequest { + return ApiDeleteApprovalRequestForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +func (a *ApprovalsApiService) DeleteApprovalRequestForFlagExecute(r ApiDeleteApprovalRequestForFlagRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.DeleteApprovalRequestForFlag") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetApprovalForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiGetApprovalForFlagRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.GetApprovalForFlagExecute(r) +} + +/* +GetApprovalForFlag Get approval request for a flag + +Get a single approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiGetApprovalForFlagRequest +*/ +func (a *ApprovalsApiService) GetApprovalForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetApprovalForFlagRequest { + return ApiGetApprovalForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsApiService) GetApprovalForFlagExecute(r ApiGetApprovalForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.GetApprovalForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsApi + id string + expand *string +} + +// A comma-separated list of fields to expand in the response. Supported fields are explained above. +func (r ApiGetApprovalRequestRequest) Expand(expand string) ApiGetApprovalRequestRequest { + r.expand = &expand + return r +} + +func (r ApiGetApprovalRequestRequest) Execute() (*ExpandableApprovalRequestResponse, *http.Response, error) { + return r.ApiService.GetApprovalRequestExecute(r) +} + +/* +GetApprovalRequest Get approval request + +Get an approval request by approval request ID. + +### Expanding approval response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `environments` includes the environments the approval request relates to +- `flag` includes the flag the approval request belongs to +- `project` includes the project the approval request belongs to +- `resource` includes details on the resource (flag or segment) the approval request relates to + +For example, `expand=project,flag` includes the `project` and `flag` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiGetApprovalRequestRequest +*/ +func (a *ApprovalsApiService) GetApprovalRequest(ctx context.Context, id string) ApiGetApprovalRequestRequest { + return ApiGetApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return ExpandableApprovalRequestResponse +func (a *ApprovalsApiService) GetApprovalRequestExecute(r ApiGetApprovalRequestRequest) (*ExpandableApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpandableApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.GetApprovalRequest") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetApprovalRequestsRequest struct { + ctx context.Context + ApiService ApprovalsApi + filter *string + expand *string + limit *int64 + offset *int64 +} + +// A comma-separated list of filters. Each filter is of the form `field operator value`. Supported fields are explained above. +func (r ApiGetApprovalRequestsRequest) Filter(filter string) ApiGetApprovalRequestsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of fields to expand in the response. Supported fields are explained above. +func (r ApiGetApprovalRequestsRequest) Expand(expand string) ApiGetApprovalRequestsRequest { + r.expand = &expand + return r +} + +// The number of approvals to return. Defaults to 20. Maximum limit is 200. +func (r ApiGetApprovalRequestsRequest) Limit(limit int64) ApiGetApprovalRequestsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetApprovalRequestsRequest) Offset(offset int64) ApiGetApprovalRequestsRequest { + r.offset = &offset + return r +} + +func (r ApiGetApprovalRequestsRequest) Execute() (*ExpandableApprovalRequestsResponse, *http.Response, error) { + return r.ApiService.GetApprovalRequestsExecute(r) +} + +/* +GetApprovalRequests List approval requests + +Get all approval requests. + +### Filtering approvals + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `notifyMemberIds` filters for only approvals that are assigned to a member in the specified list. For example: `filter=notifyMemberIds anyOf ["memberId1", "memberId2"]`. +- `requestorId` filters for only approvals that correspond to the ID of the member who requested the approval. For example: `filter=requestorId equals 457034721476302714390214`. +- `resourceId` filters for only approvals that correspond to the the specified resource identifier. For example: `filter=resourceId equals proj/my-project:env/my-environment:flag/my-flag`. +- `resourceKind` filters for only approvals that correspond to the specified resource kind. For example: `filter=resourceKind equals flag`. Currently, `flag` and `segment` resource kinds are supported. +- `reviewStatus` filters for only approvals which correspond to the review status in the specified list. The possible values are `approved`, `declined`, and `pending`. For example: `filter=reviewStatus anyOf ["pending", "approved"]`. +- `status` filters for only approvals which correspond to the status in the specified list. The possible values are `pending`, `scheduled`, `failed`, and `completed`. For example: `filter=status anyOf ["pending", "scheduled"]`. + +You can also apply multiple filters at once. For example, setting `filter=projectKey equals my-project, reviewStatus anyOf ["pending","approved"]` matches approval requests which correspond to the `my-project` project key, and a review status of either `pending` or `approved`. + +### Expanding approval response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `flag` includes the flag the approval request belongs to +- `project` includes the project the approval request belongs to +- `environments` includes the environments the approval request relates to + +For example, `expand=project,flag` includes the `project` and `flag` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetApprovalRequestsRequest +*/ +func (a *ApprovalsApiService) GetApprovalRequests(ctx context.Context) ApiGetApprovalRequestsRequest { + return ApiGetApprovalRequestsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ExpandableApprovalRequestsResponse +func (a *ApprovalsApiService) GetApprovalRequestsExecute(r ApiGetApprovalRequestsRequest) (*ExpandableApprovalRequestsResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpandableApprovalRequestsResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.GetApprovalRequests") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetApprovalsForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string +} + +func (r ApiGetApprovalsForFlagRequest) Execute() (*FlagConfigApprovalRequestsResponse, *http.Response, error) { + return r.ApiService.GetApprovalsForFlagExecute(r) +} + +/* +GetApprovalsForFlag List approval requests for a flag + +Get all approval requests for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetApprovalsForFlagRequest +*/ +func (a *ApprovalsApiService) GetApprovalsForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetApprovalsForFlagRequest { + return ApiGetApprovalsForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestsResponse +func (a *ApprovalsApiService) GetApprovalsForFlagExecute(r ApiGetApprovalsForFlagRequest) (*FlagConfigApprovalRequestsResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestsResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.GetApprovalsForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsApi + createApprovalRequestRequest *CreateApprovalRequestRequest +} + +func (r ApiPostApprovalRequestRequest) CreateApprovalRequestRequest(createApprovalRequestRequest CreateApprovalRequestRequest) ApiPostApprovalRequestRequest { + r.createApprovalRequestRequest = &createApprovalRequestRequest + return r +} + +func (r ApiPostApprovalRequestRequest) Execute() (*ApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestExecute(r) +} + +/* +PostApprovalRequest Create approval request + +Create an approval request. + +This endpoint requires a list of `instructions`, in semantic patch format, that will be applied when the approval request is approved and applied. + +If you are creating an approval request for a flag, you can use the following `instructions`: + +- `addVariation` +- `removeVariation` +- `updateVariation` +- `updateDefaultVariation` + +For details on using these instructions, read [Update feature flag](https://launchdarkly.com/docs/api/feature-flags/patch-feature-flag). + +To create an approval for a flag specific to an environment, use [Create approval request for a flag](https://launchdarkly.com/docs/api/approvals/post-approval-request-for-flag). + +If you are creating an approval request for a segment, you can use the following read [Patch segment](https://launchdarkly.com/docs/api/segments/patch-segment) for details on the available `instructions`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostApprovalRequestRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequest(ctx context.Context) ApiPostApprovalRequestRequest { + return ApiPostApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestExecute(r ApiPostApprovalRequestRequest) (*ApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequest") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createApprovalRequestRequest == nil { + return localVarReturnValue, nil, reportError("createApprovalRequestRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createApprovalRequestRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestApplyRequest struct { + ctx context.Context + ApiService ApprovalsApi + id string + postApprovalRequestApplyRequest *PostApprovalRequestApplyRequest +} + +func (r ApiPostApprovalRequestApplyRequest) PostApprovalRequestApplyRequest(postApprovalRequestApplyRequest PostApprovalRequestApplyRequest) ApiPostApprovalRequestApplyRequest { + r.postApprovalRequestApplyRequest = &postApprovalRequestApplyRequest + return r +} + +func (r ApiPostApprovalRequestApplyRequest) Execute() (*ApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestApplyExecute(r) +} + +/* +PostApprovalRequestApply Apply approval request + +Apply an approval request that has been approved. This endpoint works with approval requests for either flag or segment changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiPostApprovalRequestApplyRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequestApply(ctx context.Context, id string) ApiPostApprovalRequestApplyRequest { + return ApiPostApprovalRequestApplyRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return ApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestApplyExecute(r ApiPostApprovalRequestApplyRequest) (*ApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequestApply") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests/{id}/apply" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postApprovalRequestApplyRequest == nil { + return localVarReturnValue, nil, reportError("postApprovalRequestApplyRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postApprovalRequestApplyRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestApplyForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + id string + postApprovalRequestApplyRequest *PostApprovalRequestApplyRequest +} + +func (r ApiPostApprovalRequestApplyForFlagRequest) PostApprovalRequestApplyRequest(postApprovalRequestApplyRequest PostApprovalRequestApplyRequest) ApiPostApprovalRequestApplyForFlagRequest { + r.postApprovalRequestApplyRequest = &postApprovalRequestApplyRequest + return r +} + +func (r ApiPostApprovalRequestApplyForFlagRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestApplyForFlagExecute(r) +} + +/* +PostApprovalRequestApplyForFlag Apply approval request for a flag + +Apply an approval request that has been approved. This endpoint requires a feature flag key, and can only be used for applying approval requests on flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiPostApprovalRequestApplyForFlagRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequestApplyForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPostApprovalRequestApplyForFlagRequest { + return ApiPostApprovalRequestApplyForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestApplyForFlagExecute(r ApiPostApprovalRequestApplyForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequestApplyForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}/apply" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postApprovalRequestApplyRequest == nil { + return localVarReturnValue, nil, reportError("postApprovalRequestApplyRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postApprovalRequestApplyRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + createFlagConfigApprovalRequestRequest *CreateFlagConfigApprovalRequestRequest +} + +func (r ApiPostApprovalRequestForFlagRequest) CreateFlagConfigApprovalRequestRequest(createFlagConfigApprovalRequestRequest CreateFlagConfigApprovalRequestRequest) ApiPostApprovalRequestForFlagRequest { + r.createFlagConfigApprovalRequestRequest = &createFlagConfigApprovalRequestRequest + return r +} + +func (r ApiPostApprovalRequestForFlagRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestForFlagExecute(r) +} + +/* +PostApprovalRequestForFlag Create approval request for a flag + +Create an approval request for a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostApprovalRequestForFlagRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequestForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostApprovalRequestForFlagRequest { + return ApiPostApprovalRequestForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestForFlagExecute(r ApiPostApprovalRequestForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequestForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createFlagConfigApprovalRequestRequest == nil { + return localVarReturnValue, nil, reportError("createFlagConfigApprovalRequestRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createFlagConfigApprovalRequestRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestReviewRequest struct { + ctx context.Context + ApiService ApprovalsApi + id string + postApprovalRequestReviewRequest *PostApprovalRequestReviewRequest +} + +func (r ApiPostApprovalRequestReviewRequest) PostApprovalRequestReviewRequest(postApprovalRequestReviewRequest PostApprovalRequestReviewRequest) ApiPostApprovalRequestReviewRequest { + r.postApprovalRequestReviewRequest = &postApprovalRequestReviewRequest + return r +} + +func (r ApiPostApprovalRequestReviewRequest) Execute() (*ApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestReviewExecute(r) +} + +/* +PostApprovalRequestReview Review approval request + +Review an approval request by approving or denying changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval request ID + @return ApiPostApprovalRequestReviewRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequestReview(ctx context.Context, id string) ApiPostApprovalRequestReviewRequest { + return ApiPostApprovalRequestReviewRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return ApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestReviewExecute(r ApiPostApprovalRequestReviewRequest) (*ApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequestReview") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests/{id}/reviews" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postApprovalRequestReviewRequest == nil { + return localVarReturnValue, nil, reportError("postApprovalRequestReviewRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postApprovalRequestReviewRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostApprovalRequestReviewForFlagRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + id string + postApprovalRequestReviewRequest *PostApprovalRequestReviewRequest +} + +func (r ApiPostApprovalRequestReviewForFlagRequest) PostApprovalRequestReviewRequest(postApprovalRequestReviewRequest PostApprovalRequestReviewRequest) ApiPostApprovalRequestReviewForFlagRequest { + r.postApprovalRequestReviewRequest = &postApprovalRequestReviewRequest + return r +} + +func (r ApiPostApprovalRequestReviewForFlagRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostApprovalRequestReviewForFlagExecute(r) +} + +/* +PostApprovalRequestReviewForFlag Review approval request for a flag + +Review an approval request by approving or denying changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The feature flag approval request ID + @return ApiPostApprovalRequestReviewForFlagRequest +*/ +func (a *ApprovalsApiService) PostApprovalRequestReviewForFlag(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPostApprovalRequestReviewForFlagRequest { + return ApiPostApprovalRequestReviewForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsApiService) PostApprovalRequestReviewForFlagExecute(r ApiPostApprovalRequestReviewForFlagRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostApprovalRequestReviewForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}/reviews" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postApprovalRequestReviewRequest == nil { + return localVarReturnValue, nil, reportError("postApprovalRequestReviewRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postApprovalRequestReviewRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostFlagCopyConfigApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsApi + projectKey string + featureFlagKey string + environmentKey string + createCopyFlagConfigApprovalRequestRequest *CreateCopyFlagConfigApprovalRequestRequest +} + +func (r ApiPostFlagCopyConfigApprovalRequestRequest) CreateCopyFlagConfigApprovalRequestRequest(createCopyFlagConfigApprovalRequestRequest CreateCopyFlagConfigApprovalRequestRequest) ApiPostFlagCopyConfigApprovalRequestRequest { + r.createCopyFlagConfigApprovalRequestRequest = &createCopyFlagConfigApprovalRequestRequest + return r +} + +func (r ApiPostFlagCopyConfigApprovalRequestRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PostFlagCopyConfigApprovalRequestExecute(r) +} + +/* +PostFlagCopyConfigApprovalRequest Create approval request to copy flag configurations across environments + +Create an approval request to copy a feature flag's configuration across environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key for the target environment + @return ApiPostFlagCopyConfigApprovalRequestRequest +*/ +func (a *ApprovalsApiService) PostFlagCopyConfigApprovalRequest(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostFlagCopyConfigApprovalRequestRequest { + return ApiPostFlagCopyConfigApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsApiService) PostFlagCopyConfigApprovalRequestExecute(r ApiPostFlagCopyConfigApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsApiService.PostFlagCopyConfigApprovalRequest") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests-flag-copy" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createCopyFlagConfigApprovalRequestRequest == nil { + return localVarReturnValue, nil, reportError("createCopyFlagConfigApprovalRequestRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createCopyFlagConfigApprovalRequestRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals_beta.go new file mode 100644 index 00000000..e4fb72b4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_approvals_beta.go @@ -0,0 +1,473 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ApprovalsBetaApi interface { + + /* + PatchApprovalRequest Update approval request + + Perform a partial update to an approval request. Updating an approval request uses the semantic patch format. This endpoint works with approval requests for either flag or segment changes. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instruction for updating an approval request. + +#### addReviewers + +Adds the specified members and teams to the existing list of reviewers. You must include at least one of `notifyMemberIds` and `notifyTeamKeys`. + +##### Parameters + +- `notifyMemberIds`: (Optional) List of member IDs. +- `notifyTeamKeys`: (Optional) List of team keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addReviewers", + "notifyMemberIds": [ "user-key-123abc", "user-key-456def" ], + "notifyTeamKeys": [ "team-key-789abc"] + }] +} +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval ID + @return ApiPatchApprovalRequestRequest + */ + PatchApprovalRequest(ctx context.Context, id string) ApiPatchApprovalRequestRequest + + // PatchApprovalRequestExecute executes the request + // @return FlagConfigApprovalRequestResponse + PatchApprovalRequestExecute(r ApiPatchApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) + + /* + PatchFlagConfigApprovalRequest Update flag approval request + + Perform a partial update to an approval request. Updating an approval request uses the semantic patch format. This endpoint requires a feature flag key, and can only be used for updating approval requests for flags. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instruction for updating an approval request. + +#### addReviewers + +Adds the specified members and teams to the existing list of reviewers. You must include at least one of `notifyMemberIds` and `notifyTeamKeys`. + +##### Parameters + +- `notifyMemberIds`: (Optional) List of member IDs. +- `notifyTeamKeys`: (Optional) List of team keys. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The approval ID + @return ApiPatchFlagConfigApprovalRequestRequest + */ + PatchFlagConfigApprovalRequest(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPatchFlagConfigApprovalRequestRequest + + // PatchFlagConfigApprovalRequestExecute executes the request + // @return FlagConfigApprovalRequestResponse + PatchFlagConfigApprovalRequestExecute(r ApiPatchFlagConfigApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) +} + +// ApprovalsBetaApiService ApprovalsBetaApi service +type ApprovalsBetaApiService service + +type ApiPatchApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsBetaApi + id string +} + +func (r ApiPatchApprovalRequestRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PatchApprovalRequestExecute(r) +} + +/* +PatchApprovalRequest Update approval request + +Perform a partial update to an approval request. Updating an approval request uses the semantic patch format. This endpoint works with approval requests for either flag or segment changes. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instruction for updating an approval request. + +#### addReviewers + +Adds the specified members and teams to the existing list of reviewers. You must include at least one of `notifyMemberIds` and `notifyTeamKeys`. + +##### Parameters + +- `notifyMemberIds`: (Optional) List of member IDs. +- `notifyTeamKeys`: (Optional) List of team keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addReviewers", + "notifyMemberIds": [ "user-key-123abc", "user-key-456def" ], + "notifyTeamKeys": [ "team-key-789abc"] + }] +} +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The approval ID + @return ApiPatchApprovalRequestRequest +*/ +func (a *ApprovalsBetaApiService) PatchApprovalRequest(ctx context.Context, id string) ApiPatchApprovalRequestRequest { + return ApiPatchApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsBetaApiService) PatchApprovalRequestExecute(r ApiPatchApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsBetaApiService.PatchApprovalRequest") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchFlagConfigApprovalRequestRequest struct { + ctx context.Context + ApiService ApprovalsBetaApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiPatchFlagConfigApprovalRequestRequest) Execute() (*FlagConfigApprovalRequestResponse, *http.Response, error) { + return r.ApiService.PatchFlagConfigApprovalRequestExecute(r) +} + +/* +PatchFlagConfigApprovalRequest Update flag approval request + +Perform a partial update to an approval request. Updating an approval request uses the semantic patch format. This endpoint requires a feature flag key, and can only be used for updating approval requests for flags. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instruction for updating an approval request. + +#### addReviewers + +Adds the specified members and teams to the existing list of reviewers. You must include at least one of `notifyMemberIds` and `notifyTeamKeys`. + +##### Parameters + +- `notifyMemberIds`: (Optional) List of member IDs. +- `notifyTeamKeys`: (Optional) List of team keys. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The approval ID + @return ApiPatchFlagConfigApprovalRequestRequest +*/ +func (a *ApprovalsBetaApiService) PatchFlagConfigApprovalRequest(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPatchFlagConfigApprovalRequestRequest { + return ApiPatchFlagConfigApprovalRequestRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FlagConfigApprovalRequestResponse +func (a *ApprovalsBetaApiService) PatchFlagConfigApprovalRequestExecute(r ApiPatchFlagConfigApprovalRequestRequest) (*FlagConfigApprovalRequestResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagConfigApprovalRequestResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ApprovalsBetaApiService.PatchFlagConfigApprovalRequest") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/approval-requests/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_audit_log.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_audit_log.go new file mode 100644 index 00000000..fd977b09 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_audit_log.go @@ -0,0 +1,651 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type AuditLogApi interface { + + /* + GetAuditLogEntries List audit log entries + + Get a list of all audit log entries. The query parameters let you restrict the results that return by date ranges, resource specifiers, or a full-text search query. + +LaunchDarkly uses a resource specifier syntax to name resources or collections of resources. To learn more, read [About the resource specifier syntax](https://launchdarkly.com/docs/home/account/role-resources#about-the-resource-specifier-syntax). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAuditLogEntriesRequest + */ + GetAuditLogEntries(ctx context.Context) ApiGetAuditLogEntriesRequest + + // GetAuditLogEntriesExecute executes the request + // @return AuditLogEntryListingRepCollection + GetAuditLogEntriesExecute(r ApiGetAuditLogEntriesRequest) (*AuditLogEntryListingRepCollection, *http.Response, error) + + /* + GetAuditLogEntry Get audit log entry + + Fetch a detailed audit log entry representation. The detailed representation includes several fields that are not present in the summary representation, including: + +- `delta`: the JSON patch body that was used in the request to update the entity +- `previousVersion`: a JSON representation of the previous version of the entity +- `currentVersion`: a JSON representation of the current version of the entity + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the audit log entry + @return ApiGetAuditLogEntryRequest + */ + GetAuditLogEntry(ctx context.Context, id string) ApiGetAuditLogEntryRequest + + // GetAuditLogEntryExecute executes the request + // @return AuditLogEntryRep + GetAuditLogEntryExecute(r ApiGetAuditLogEntryRequest) (*AuditLogEntryRep, *http.Response, error) + + /* + PostAuditLogEntries Search audit log entries + + Search your audit log entries. The query parameters let you restrict the results that return by date ranges, or a full-text search query. The request body lets you restrict the results that return by resource specifiers. + +LaunchDarkly uses a resource specifier syntax to name resources or collections of resources. To learn more, read [About the resource specifier syntax](https://launchdarkly.com/docs/home/account/role-resources#about-the-resource-specifier-syntax). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostAuditLogEntriesRequest + */ + PostAuditLogEntries(ctx context.Context) ApiPostAuditLogEntriesRequest + + // PostAuditLogEntriesExecute executes the request + // @return AuditLogEntryListingRepCollection + PostAuditLogEntriesExecute(r ApiPostAuditLogEntriesRequest) (*AuditLogEntryListingRepCollection, *http.Response, error) +} + +// AuditLogApiService AuditLogApi service +type AuditLogApiService service + +type ApiGetAuditLogEntriesRequest struct { + ctx context.Context + ApiService AuditLogApi + before *int64 + after *int64 + q *string + limit *int64 + spec *string +} + +// A timestamp filter, expressed as a Unix epoch time in milliseconds. All entries this returns occurred before the timestamp. +func (r ApiGetAuditLogEntriesRequest) Before(before int64) ApiGetAuditLogEntriesRequest { + r.before = &before + return r +} + +// A timestamp filter, expressed as a Unix epoch time in milliseconds. All entries this returns occurred after the timestamp. +func (r ApiGetAuditLogEntriesRequest) After(after int64) ApiGetAuditLogEntriesRequest { + r.after = &after + return r +} + +// Text to search for. You can search for the full or partial name of the resource. +func (r ApiGetAuditLogEntriesRequest) Q(q string) ApiGetAuditLogEntriesRequest { + r.q = &q + return r +} + +// A limit on the number of audit log entries that return. Set between 1 and 20. The default is 10. +func (r ApiGetAuditLogEntriesRequest) Limit(limit int64) ApiGetAuditLogEntriesRequest { + r.limit = &limit + return r +} + +// A resource specifier that lets you filter audit log listings by resource +func (r ApiGetAuditLogEntriesRequest) Spec(spec string) ApiGetAuditLogEntriesRequest { + r.spec = &spec + return r +} + +func (r ApiGetAuditLogEntriesRequest) Execute() (*AuditLogEntryListingRepCollection, *http.Response, error) { + return r.ApiService.GetAuditLogEntriesExecute(r) +} + +/* +GetAuditLogEntries List audit log entries + +Get a list of all audit log entries. The query parameters let you restrict the results that return by date ranges, resource specifiers, or a full-text search query. + +LaunchDarkly uses a resource specifier syntax to name resources or collections of resources. To learn more, read [About the resource specifier syntax](https://launchdarkly.com/docs/home/account/role-resources#about-the-resource-specifier-syntax). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAuditLogEntriesRequest +*/ +func (a *AuditLogApiService) GetAuditLogEntries(ctx context.Context) ApiGetAuditLogEntriesRequest { + return ApiGetAuditLogEntriesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return AuditLogEntryListingRepCollection +func (a *AuditLogApiService) GetAuditLogEntriesExecute(r ApiGetAuditLogEntriesRequest) (*AuditLogEntryListingRepCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AuditLogEntryListingRepCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AuditLogApiService.GetAuditLogEntries") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/auditlog" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.before != nil { + localVarQueryParams.Add("before", parameterToString(*r.before, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.q != nil { + localVarQueryParams.Add("q", parameterToString(*r.q, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.spec != nil { + localVarQueryParams.Add("spec", parameterToString(*r.spec, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAuditLogEntryRequest struct { + ctx context.Context + ApiService AuditLogApi + id string +} + +func (r ApiGetAuditLogEntryRequest) Execute() (*AuditLogEntryRep, *http.Response, error) { + return r.ApiService.GetAuditLogEntryExecute(r) +} + +/* +GetAuditLogEntry Get audit log entry + +Fetch a detailed audit log entry representation. The detailed representation includes several fields that are not present in the summary representation, including: + +- `delta`: the JSON patch body that was used in the request to update the entity +- `previousVersion`: a JSON representation of the previous version of the entity +- `currentVersion`: a JSON representation of the current version of the entity + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the audit log entry + @return ApiGetAuditLogEntryRequest +*/ +func (a *AuditLogApiService) GetAuditLogEntry(ctx context.Context, id string) ApiGetAuditLogEntryRequest { + return ApiGetAuditLogEntryRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return AuditLogEntryRep +func (a *AuditLogApiService) GetAuditLogEntryExecute(r ApiGetAuditLogEntryRequest) (*AuditLogEntryRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AuditLogEntryRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AuditLogApiService.GetAuditLogEntry") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/auditlog/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostAuditLogEntriesRequest struct { + ctx context.Context + ApiService AuditLogApi + before *int64 + after *int64 + q *string + limit *int64 + statementPost *[]StatementPost +} + +// A timestamp filter, expressed as a Unix epoch time in milliseconds. All entries returned occurred before the timestamp. +func (r ApiPostAuditLogEntriesRequest) Before(before int64) ApiPostAuditLogEntriesRequest { + r.before = &before + return r +} + +// A timestamp filter, expressed as a Unix epoch time in milliseconds. All entries returned occurred after the timestamp. +func (r ApiPostAuditLogEntriesRequest) After(after int64) ApiPostAuditLogEntriesRequest { + r.after = &after + return r +} + +// Text to search for. You can search for the full or partial name of the resource. +func (r ApiPostAuditLogEntriesRequest) Q(q string) ApiPostAuditLogEntriesRequest { + r.q = &q + return r +} + +// A limit on the number of audit log entries that return. Set between 1 and 20. The default is 10. +func (r ApiPostAuditLogEntriesRequest) Limit(limit int64) ApiPostAuditLogEntriesRequest { + r.limit = &limit + return r +} + +func (r ApiPostAuditLogEntriesRequest) StatementPost(statementPost []StatementPost) ApiPostAuditLogEntriesRequest { + r.statementPost = &statementPost + return r +} + +func (r ApiPostAuditLogEntriesRequest) Execute() (*AuditLogEntryListingRepCollection, *http.Response, error) { + return r.ApiService.PostAuditLogEntriesExecute(r) +} + +/* +PostAuditLogEntries Search audit log entries + +Search your audit log entries. The query parameters let you restrict the results that return by date ranges, or a full-text search query. The request body lets you restrict the results that return by resource specifiers. + +LaunchDarkly uses a resource specifier syntax to name resources or collections of resources. To learn more, read [About the resource specifier syntax](https://launchdarkly.com/docs/home/account/role-resources#about-the-resource-specifier-syntax). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostAuditLogEntriesRequest +*/ +func (a *AuditLogApiService) PostAuditLogEntries(ctx context.Context) ApiPostAuditLogEntriesRequest { + return ApiPostAuditLogEntriesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return AuditLogEntryListingRepCollection +func (a *AuditLogApiService) PostAuditLogEntriesExecute(r ApiPostAuditLogEntriesRequest) (*AuditLogEntryListingRepCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AuditLogEntryListingRepCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AuditLogApiService.PostAuditLogEntries") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/auditlog" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.before != nil { + localVarQueryParams.Add("before", parameterToString(*r.before, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.q != nil { + localVarQueryParams.Add("q", parameterToString(*r.q, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.statementPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_code_references.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_code_references.go new file mode 100644 index 00000000..a122fede --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_code_references.go @@ -0,0 +1,2463 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type CodeReferencesApi interface { + + /* + DeleteBranches Delete branches + + Asynchronously delete a number of branches. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name to delete branches for. + @return ApiDeleteBranchesRequest + */ + DeleteBranches(ctx context.Context, repo string) ApiDeleteBranchesRequest + + // DeleteBranchesExecute executes the request + DeleteBranchesExecute(r ApiDeleteBranchesRequest) (*http.Response, error) + + /* + DeleteRepository Delete repository + + Delete a repository with the specified name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiDeleteRepositoryRequest + */ + DeleteRepository(ctx context.Context, repo string) ApiDeleteRepositoryRequest + + // DeleteRepositoryExecute executes the request + DeleteRepositoryExecute(r ApiDeleteRepositoryRequest) (*http.Response, error) + + /* + GetBranch Get branch + + Get a specific branch in a repository. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The url-encoded branch name + @return ApiGetBranchRequest + */ + GetBranch(ctx context.Context, repo string, branch string) ApiGetBranchRequest + + // GetBranchExecute executes the request + // @return BranchRep + GetBranchExecute(r ApiGetBranchRequest) (*BranchRep, *http.Response, error) + + /* + GetBranches List branches + + Get a list of branches. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiGetBranchesRequest + */ + GetBranches(ctx context.Context, repo string) ApiGetBranchesRequest + + // GetBranchesExecute executes the request + // @return BranchCollectionRep + GetBranchesExecute(r ApiGetBranchesRequest) (*BranchCollectionRep, *http.Response, error) + + /* + GetExtinctions List extinctions + + Get a list of all extinctions. LaunchDarkly creates an extinction event after you remove all code references to a flag. To learn more, read [About extinction events](https://launchdarkly.com/docs/home/observability/code-references#about-extinction-events). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExtinctionsRequest + */ + GetExtinctions(ctx context.Context) ApiGetExtinctionsRequest + + // GetExtinctionsExecute executes the request + // @return ExtinctionCollectionRep + GetExtinctionsExecute(r ApiGetExtinctionsRequest) (*ExtinctionCollectionRep, *http.Response, error) + + /* + GetRepositories List repositories + + Get a list of connected repositories. Optionally, you can include branch metadata with the `withBranches` query parameter. Embed references for the default branch with `ReferencesForDefaultBranch`. You can also filter the list of code references by project key and flag key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRepositoriesRequest + */ + GetRepositories(ctx context.Context) ApiGetRepositoriesRequest + + // GetRepositoriesExecute executes the request + // @return RepositoryCollectionRep + GetRepositoriesExecute(r ApiGetRepositoriesRequest) (*RepositoryCollectionRep, *http.Response, error) + + /* + GetRepository Get repository + + Get a single repository by name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiGetRepositoryRequest + */ + GetRepository(ctx context.Context, repo string) ApiGetRepositoryRequest + + // GetRepositoryExecute executes the request + // @return RepositoryRep + GetRepositoryExecute(r ApiGetRepositoryRequest) (*RepositoryRep, *http.Response, error) + + /* + GetRootStatistic Get links to code reference repositories for each project + + Get links for all projects that have code references. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRootStatisticRequest + */ + GetRootStatistic(ctx context.Context) ApiGetRootStatisticRequest + + // GetRootStatisticExecute executes the request + // @return StatisticsRoot + GetRootStatisticExecute(r ApiGetRootStatisticRequest) (*StatisticsRoot, *http.Response, error) + + /* + GetStatistics Get code references statistics for flags + + Get statistics about all the code references across repositories for all flags in your project that have code references in the default branch, for example, `main`. Optionally, you can include the `flagKey` query parameter to limit your request to statistics about code references for a single flag. This endpoint returns the number of references to your flag keys in your repositories, as well as a link to each repository. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetStatisticsRequest + */ + GetStatistics(ctx context.Context, projectKey string) ApiGetStatisticsRequest + + // GetStatisticsExecute executes the request + // @return StatisticCollectionRep + GetStatisticsExecute(r ApiGetStatisticsRequest) (*StatisticCollectionRep, *http.Response, error) + + /* + PatchRepository Update repository + + Update a repository's settings. Updating repository settings uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiPatchRepositoryRequest + */ + PatchRepository(ctx context.Context, repo string) ApiPatchRepositoryRequest + + // PatchRepositoryExecute executes the request + // @return RepositoryRep + PatchRepositoryExecute(r ApiPatchRepositoryRequest) (*RepositoryRep, *http.Response, error) + + /* + PostExtinction Create extinction + + Create a new extinction. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The URL-encoded branch name + @return ApiPostExtinctionRequest + */ + PostExtinction(ctx context.Context, repo string, branch string) ApiPostExtinctionRequest + + // PostExtinctionExecute executes the request + PostExtinctionExecute(r ApiPostExtinctionRequest) (*http.Response, error) + + /* + PostRepository Create repository + + Create a repository with the specified name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostRepositoryRequest + */ + PostRepository(ctx context.Context) ApiPostRepositoryRequest + + // PostRepositoryExecute executes the request + // @return RepositoryRep + PostRepositoryExecute(r ApiPostRepositoryRequest) (*RepositoryRep, *http.Response, error) + + /* + PutBranch Upsert branch + + Create a new branch if it doesn't exist, or update the branch if it already exists. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The URL-encoded branch name + @return ApiPutBranchRequest + */ + PutBranch(ctx context.Context, repo string, branch string) ApiPutBranchRequest + + // PutBranchExecute executes the request + PutBranchExecute(r ApiPutBranchRequest) (*http.Response, error) +} + +// CodeReferencesApiService CodeReferencesApi service +type CodeReferencesApiService service + +type ApiDeleteBranchesRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string + requestBody *[]string +} + +func (r ApiDeleteBranchesRequest) RequestBody(requestBody []string) ApiDeleteBranchesRequest { + r.requestBody = &requestBody + return r +} + +func (r ApiDeleteBranchesRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteBranchesExecute(r) +} + +/* +DeleteBranches Delete branches + +Asynchronously delete a number of branches. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name to delete branches for. + @return ApiDeleteBranchesRequest +*/ +func (a *CodeReferencesApiService) DeleteBranches(ctx context.Context, repo string) ApiDeleteBranchesRequest { + return ApiDeleteBranchesRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + } +} + +// Execute executes the request +func (a *CodeReferencesApiService) DeleteBranchesExecute(r ApiDeleteBranchesRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.DeleteBranches") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}/branch-delete-tasks" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.requestBody == nil { + return nil, reportError("requestBody is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.requestBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteRepositoryRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string +} + +func (r ApiDeleteRepositoryRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteRepositoryExecute(r) +} + +/* +DeleteRepository Delete repository + +Delete a repository with the specified name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiDeleteRepositoryRequest +*/ +func (a *CodeReferencesApiService) DeleteRepository(ctx context.Context, repo string) ApiDeleteRepositoryRequest { + return ApiDeleteRepositoryRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + } +} + +// Execute executes the request +func (a *CodeReferencesApiService) DeleteRepositoryExecute(r ApiDeleteRepositoryRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.DeleteRepository") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetBranchRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string + branch string + projKey *string + flagKey *string +} + +// Filter results to a specific project +func (r ApiGetBranchRequest) ProjKey(projKey string) ApiGetBranchRequest { + r.projKey = &projKey + return r +} + +// Filter results to a specific flag key +func (r ApiGetBranchRequest) FlagKey(flagKey string) ApiGetBranchRequest { + r.flagKey = &flagKey + return r +} + +func (r ApiGetBranchRequest) Execute() (*BranchRep, *http.Response, error) { + return r.ApiService.GetBranchExecute(r) +} + +/* +GetBranch Get branch + +Get a specific branch in a repository. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The url-encoded branch name + @return ApiGetBranchRequest +*/ +func (a *CodeReferencesApiService) GetBranch(ctx context.Context, repo string, branch string) ApiGetBranchRequest { + return ApiGetBranchRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + branch: branch, + } +} + +// Execute executes the request +// @return BranchRep +func (a *CodeReferencesApiService) GetBranchExecute(r ApiGetBranchRequest) (*BranchRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BranchRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetBranch") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}/branches/{branch}" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"branch"+"}", url.PathEscape(parameterToString(r.branch, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.projKey != nil { + localVarQueryParams.Add("projKey", parameterToString(*r.projKey, "")) + } + if r.flagKey != nil { + localVarQueryParams.Add("flagKey", parameterToString(*r.flagKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetBranchesRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string +} + +func (r ApiGetBranchesRequest) Execute() (*BranchCollectionRep, *http.Response, error) { + return r.ApiService.GetBranchesExecute(r) +} + +/* +GetBranches List branches + +Get a list of branches. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiGetBranchesRequest +*/ +func (a *CodeReferencesApiService) GetBranches(ctx context.Context, repo string) ApiGetBranchesRequest { + return ApiGetBranchesRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + } +} + +// Execute executes the request +// @return BranchCollectionRep +func (a *CodeReferencesApiService) GetBranchesExecute(r ApiGetBranchesRequest) (*BranchCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BranchCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetBranches") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}/branches" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExtinctionsRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repoName *string + branchName *string + projKey *string + flagKey *string + from *int64 + to *int64 +} + +// Filter results to a specific repository +func (r ApiGetExtinctionsRequest) RepoName(repoName string) ApiGetExtinctionsRequest { + r.repoName = &repoName + return r +} + +// Filter results to a specific branch. By default, only the default branch will be queried for extinctions. +func (r ApiGetExtinctionsRequest) BranchName(branchName string) ApiGetExtinctionsRequest { + r.branchName = &branchName + return r +} + +// Filter results to a specific project +func (r ApiGetExtinctionsRequest) ProjKey(projKey string) ApiGetExtinctionsRequest { + r.projKey = &projKey + return r +} + +// Filter results to a specific flag key +func (r ApiGetExtinctionsRequest) FlagKey(flagKey string) ApiGetExtinctionsRequest { + r.flagKey = &flagKey + return r +} + +// Filter results to a specific timeframe based on commit time, expressed as a Unix epoch time in milliseconds. Must be used with `to`. +func (r ApiGetExtinctionsRequest) From(from int64) ApiGetExtinctionsRequest { + r.from = &from + return r +} + +// Filter results to a specific timeframe based on commit time, expressed as a Unix epoch time in milliseconds. Must be used with `from`. +func (r ApiGetExtinctionsRequest) To(to int64) ApiGetExtinctionsRequest { + r.to = &to + return r +} + +func (r ApiGetExtinctionsRequest) Execute() (*ExtinctionCollectionRep, *http.Response, error) { + return r.ApiService.GetExtinctionsExecute(r) +} + +/* +GetExtinctions List extinctions + +Get a list of all extinctions. LaunchDarkly creates an extinction event after you remove all code references to a flag. To learn more, read [About extinction events](https://launchdarkly.com/docs/home/observability/code-references#about-extinction-events). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetExtinctionsRequest +*/ +func (a *CodeReferencesApiService) GetExtinctions(ctx context.Context) ApiGetExtinctionsRequest { + return ApiGetExtinctionsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ExtinctionCollectionRep +func (a *CodeReferencesApiService) GetExtinctionsExecute(r ApiGetExtinctionsRequest) (*ExtinctionCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExtinctionCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetExtinctions") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/extinctions" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.repoName != nil { + localVarQueryParams.Add("repoName", parameterToString(*r.repoName, "")) + } + if r.branchName != nil { + localVarQueryParams.Add("branchName", parameterToString(*r.branchName, "")) + } + if r.projKey != nil { + localVarQueryParams.Add("projKey", parameterToString(*r.projKey, "")) + } + if r.flagKey != nil { + localVarQueryParams.Add("flagKey", parameterToString(*r.flagKey, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetRepositoriesRequest struct { + ctx context.Context + ApiService CodeReferencesApi + withBranches *string + withReferencesForDefaultBranch *string + projKey *string + flagKey *string +} + +// If set to any value, the endpoint returns repositories with associated branch data +func (r ApiGetRepositoriesRequest) WithBranches(withBranches string) ApiGetRepositoriesRequest { + r.withBranches = &withBranches + return r +} + +// If set to any value, the endpoint returns repositories with associated branch data, as well as code references for the default git branch +func (r ApiGetRepositoriesRequest) WithReferencesForDefaultBranch(withReferencesForDefaultBranch string) ApiGetRepositoriesRequest { + r.withReferencesForDefaultBranch = &withReferencesForDefaultBranch + return r +} + +// A LaunchDarkly project key. If provided, this filters code reference results to the specified project. +func (r ApiGetRepositoriesRequest) ProjKey(projKey string) ApiGetRepositoriesRequest { + r.projKey = &projKey + return r +} + +// If set to any value, the endpoint returns repositories with associated branch data, as well as code references for the default git branch +func (r ApiGetRepositoriesRequest) FlagKey(flagKey string) ApiGetRepositoriesRequest { + r.flagKey = &flagKey + return r +} + +func (r ApiGetRepositoriesRequest) Execute() (*RepositoryCollectionRep, *http.Response, error) { + return r.ApiService.GetRepositoriesExecute(r) +} + +/* +GetRepositories List repositories + +Get a list of connected repositories. Optionally, you can include branch metadata with the `withBranches` query parameter. Embed references for the default branch with `ReferencesForDefaultBranch`. You can also filter the list of code references by project key and flag key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRepositoriesRequest +*/ +func (a *CodeReferencesApiService) GetRepositories(ctx context.Context) ApiGetRepositoriesRequest { + return ApiGetRepositoriesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return RepositoryCollectionRep +func (a *CodeReferencesApiService) GetRepositoriesExecute(r ApiGetRepositoriesRequest) (*RepositoryCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RepositoryCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetRepositories") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.withBranches != nil { + localVarQueryParams.Add("withBranches", parameterToString(*r.withBranches, "")) + } + if r.withReferencesForDefaultBranch != nil { + localVarQueryParams.Add("withReferencesForDefaultBranch", parameterToString(*r.withReferencesForDefaultBranch, "")) + } + if r.projKey != nil { + localVarQueryParams.Add("projKey", parameterToString(*r.projKey, "")) + } + if r.flagKey != nil { + localVarQueryParams.Add("flagKey", parameterToString(*r.flagKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetRepositoryRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string +} + +func (r ApiGetRepositoryRequest) Execute() (*RepositoryRep, *http.Response, error) { + return r.ApiService.GetRepositoryExecute(r) +} + +/* +GetRepository Get repository + +Get a single repository by name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiGetRepositoryRequest +*/ +func (a *CodeReferencesApiService) GetRepository(ctx context.Context, repo string) ApiGetRepositoryRequest { + return ApiGetRepositoryRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + } +} + +// Execute executes the request +// @return RepositoryRep +func (a *CodeReferencesApiService) GetRepositoryExecute(r ApiGetRepositoryRequest) (*RepositoryRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RepositoryRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetRepository") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetRootStatisticRequest struct { + ctx context.Context + ApiService CodeReferencesApi +} + +func (r ApiGetRootStatisticRequest) Execute() (*StatisticsRoot, *http.Response, error) { + return r.ApiService.GetRootStatisticExecute(r) +} + +/* +GetRootStatistic Get links to code reference repositories for each project + +Get links for all projects that have code references. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRootStatisticRequest +*/ +func (a *CodeReferencesApiService) GetRootStatistic(ctx context.Context) ApiGetRootStatisticRequest { + return ApiGetRootStatisticRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return StatisticsRoot +func (a *CodeReferencesApiService) GetRootStatisticExecute(r ApiGetRootStatisticRequest) (*StatisticsRoot, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *StatisticsRoot + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetRootStatistic") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/statistics" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetStatisticsRequest struct { + ctx context.Context + ApiService CodeReferencesApi + projectKey string + flagKey *string +} + +// Filter results to a specific flag key +func (r ApiGetStatisticsRequest) FlagKey(flagKey string) ApiGetStatisticsRequest { + r.flagKey = &flagKey + return r +} + +func (r ApiGetStatisticsRequest) Execute() (*StatisticCollectionRep, *http.Response, error) { + return r.ApiService.GetStatisticsExecute(r) +} + +/* +GetStatistics Get code references statistics for flags + +Get statistics about all the code references across repositories for all flags in your project that have code references in the default branch, for example, `main`. Optionally, you can include the `flagKey` query parameter to limit your request to statistics about code references for a single flag. This endpoint returns the number of references to your flag keys in your repositories, as well as a link to each repository. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetStatisticsRequest +*/ +func (a *CodeReferencesApiService) GetStatistics(ctx context.Context, projectKey string) ApiGetStatisticsRequest { + return ApiGetStatisticsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return StatisticCollectionRep +func (a *CodeReferencesApiService) GetStatisticsExecute(r ApiGetStatisticsRequest) (*StatisticCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *StatisticCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.GetStatistics") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/statistics/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.flagKey != nil { + localVarQueryParams.Add("flagKey", parameterToString(*r.flagKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchRepositoryRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string + patchOperation *[]PatchOperation +} + +func (r ApiPatchRepositoryRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchRepositoryRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchRepositoryRequest) Execute() (*RepositoryRep, *http.Response, error) { + return r.ApiService.PatchRepositoryExecute(r) +} + +/* +PatchRepository Update repository + +Update a repository's settings. Updating repository settings uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @return ApiPatchRepositoryRequest +*/ +func (a *CodeReferencesApiService) PatchRepository(ctx context.Context, repo string) ApiPatchRepositoryRequest { + return ApiPatchRepositoryRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + } +} + +// Execute executes the request +// @return RepositoryRep +func (a *CodeReferencesApiService) PatchRepositoryExecute(r ApiPatchRepositoryRequest) (*RepositoryRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RepositoryRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.PatchRepository") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostExtinctionRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string + branch string + extinction *[]Extinction +} + +func (r ApiPostExtinctionRequest) Extinction(extinction []Extinction) ApiPostExtinctionRequest { + r.extinction = &extinction + return r +} + +func (r ApiPostExtinctionRequest) Execute() (*http.Response, error) { + return r.ApiService.PostExtinctionExecute(r) +} + +/* +PostExtinction Create extinction + +Create a new extinction. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The URL-encoded branch name + @return ApiPostExtinctionRequest +*/ +func (a *CodeReferencesApiService) PostExtinction(ctx context.Context, repo string, branch string) ApiPostExtinctionRequest { + return ApiPostExtinctionRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + branch: branch, + } +} + +// Execute executes the request +func (a *CodeReferencesApiService) PostExtinctionExecute(r ApiPostExtinctionRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.PostExtinction") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}/branches/{branch}/extinction-events" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"branch"+"}", url.PathEscape(parameterToString(r.branch, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.extinction == nil { + return nil, reportError("extinction is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.extinction + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiPostRepositoryRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repositoryPost *RepositoryPost +} + +func (r ApiPostRepositoryRequest) RepositoryPost(repositoryPost RepositoryPost) ApiPostRepositoryRequest { + r.repositoryPost = &repositoryPost + return r +} + +func (r ApiPostRepositoryRequest) Execute() (*RepositoryRep, *http.Response, error) { + return r.ApiService.PostRepositoryExecute(r) +} + +/* +PostRepository Create repository + +Create a repository with the specified name. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostRepositoryRequest +*/ +func (a *CodeReferencesApiService) PostRepository(ctx context.Context) ApiPostRepositoryRequest { + return ApiPostRepositoryRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return RepositoryRep +func (a *CodeReferencesApiService) PostRepositoryExecute(r ApiPostRepositoryRequest) (*RepositoryRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RepositoryRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.PostRepository") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.repositoryPost == nil { + return localVarReturnValue, nil, reportError("repositoryPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.repositoryPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutBranchRequest struct { + ctx context.Context + ApiService CodeReferencesApi + repo string + branch string + putBranch *PutBranch +} + +func (r ApiPutBranchRequest) PutBranch(putBranch PutBranch) ApiPutBranchRequest { + r.putBranch = &putBranch + return r +} + +func (r ApiPutBranchRequest) Execute() (*http.Response, error) { + return r.ApiService.PutBranchExecute(r) +} + +/* +PutBranch Upsert branch + +Create a new branch if it doesn't exist, or update the branch if it already exists. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repo The repository name + @param branch The URL-encoded branch name + @return ApiPutBranchRequest +*/ +func (a *CodeReferencesApiService) PutBranch(ctx context.Context, repo string, branch string) ApiPutBranchRequest { + return ApiPutBranchRequest{ + ApiService: a, + ctx: ctx, + repo: repo, + branch: branch, + } +} + +// Execute executes the request +func (a *CodeReferencesApiService) PutBranchExecute(r ApiPutBranchRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CodeReferencesApiService.PutBranch") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/code-refs/repositories/{repo}/branches/{branch}" + localVarPath = strings.Replace(localVarPath, "{"+"repo"+"}", url.PathEscape(parameterToString(r.repo, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"branch"+"}", url.PathEscape(parameterToString(r.branch, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.putBranch == nil { + return nil, reportError("putBranch is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.putBranch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_context_settings.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_context_settings.go new file mode 100644 index 00000000..4d42a6e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_context_settings.go @@ -0,0 +1,240 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ContextSettingsApi interface { + + /* + PutContextFlagSetting Update flag settings for context + + +Enable or disable a feature flag for a context based on its context kind and key. + +Omitting the `setting` attribute from the request body, or including a `setting` of `null`, erases the current setting for a context. + +If you previously patched the flag, and the patch included the context's data, LaunchDarkly continues to use that data. If LaunchDarkly has never encountered the combination of the context's key and kind before, it calculates the flag values based on the context kind and key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param contextKind The context kind + @param contextKey The context key + @param featureFlagKey The feature flag key + @return ApiPutContextFlagSettingRequest + */ + PutContextFlagSetting(ctx context.Context, projectKey string, environmentKey string, contextKind string, contextKey string, featureFlagKey string) ApiPutContextFlagSettingRequest + + // PutContextFlagSettingExecute executes the request + PutContextFlagSettingExecute(r ApiPutContextFlagSettingRequest) (*http.Response, error) +} + +// ContextSettingsApiService ContextSettingsApi service +type ContextSettingsApiService service + +type ApiPutContextFlagSettingRequest struct { + ctx context.Context + ApiService ContextSettingsApi + projectKey string + environmentKey string + contextKind string + contextKey string + featureFlagKey string + valuePut *ValuePut +} + +func (r ApiPutContextFlagSettingRequest) ValuePut(valuePut ValuePut) ApiPutContextFlagSettingRequest { + r.valuePut = &valuePut + return r +} + +func (r ApiPutContextFlagSettingRequest) Execute() (*http.Response, error) { + return r.ApiService.PutContextFlagSettingExecute(r) +} + +/* +PutContextFlagSetting Update flag settings for context + + +Enable or disable a feature flag for a context based on its context kind and key. + +Omitting the `setting` attribute from the request body, or including a `setting` of `null`, erases the current setting for a context. + +If you previously patched the flag, and the patch included the context's data, LaunchDarkly continues to use that data. If LaunchDarkly has never encountered the combination of the context's key and kind before, it calculates the flag values based on the context kind and key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param contextKind The context kind + @param contextKey The context key + @param featureFlagKey The feature flag key + @return ApiPutContextFlagSettingRequest +*/ +func (a *ContextSettingsApiService) PutContextFlagSetting(ctx context.Context, projectKey string, environmentKey string, contextKind string, contextKey string, featureFlagKey string) ApiPutContextFlagSettingRequest { + return ApiPutContextFlagSettingRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + contextKind: contextKind, + contextKey: contextKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +func (a *ContextSettingsApiService) PutContextFlagSettingExecute(r ApiPutContextFlagSettingRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextSettingsApiService.PutContextFlagSetting") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/{contextKind}/{contextKey}/flags/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"contextKind"+"}", url.PathEscape(parameterToString(r.contextKind, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"contextKey"+"}", url.PathEscape(parameterToString(r.contextKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.valuePut == nil { + return nil, reportError("valuePut is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.valuePut + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_contexts.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_contexts.go new file mode 100644 index 00000000..6719fc98 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_contexts.go @@ -0,0 +1,2174 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ContextsApi interface { + + /* + DeleteContextInstances Delete context instances + + Delete context instances by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The context instance ID + @return ApiDeleteContextInstancesRequest + */ + DeleteContextInstances(ctx context.Context, projectKey string, environmentKey string, id string) ApiDeleteContextInstancesRequest + + // DeleteContextInstancesExecute executes the request + DeleteContextInstancesExecute(r ApiDeleteContextInstancesRequest) (*http.Response, error) + + /* + EvaluateContextInstance Evaluate flags for context instance + + Evaluate flags for a context instance, for example, to determine the expected flag variation. **Do not use this API instead of an SDK.** The LaunchDarkly SDKs are specialized for the tasks of evaluating feature flags in your application at scale and generating analytics events based on those evaluations. This API is not designed for that use case. Any evaluations you perform with this API will not be reflected in features such as flag statuses and flag insights. Context instances evaluated by this API will not appear in the Contexts list. To learn more, read [Comparing LaunchDarkly's SDKs and REST API](https://launchdarkly.com/docs/guides/api/comparing-sdk-rest-api). + +### Filtering + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `query` filters for a string that matches against the flags' keys and names. It is not case sensitive. For example: `filter=query equals dark-mode`. +- `tags` filters the list to flags that have all of the tags in the list. For example: `filter=tags contains ["beta","q1"]`. + +You can also apply multiple filters at once. For example, setting `filter=query equals dark-mode, tags contains ["beta","q1"]` matches flags which match the key or name `dark-mode` and are tagged `beta` and `q1`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiEvaluateContextInstanceRequest + */ + EvaluateContextInstance(ctx context.Context, projectKey string, environmentKey string) ApiEvaluateContextInstanceRequest + + // EvaluateContextInstanceExecute executes the request + // @return ContextInstanceEvaluations + EvaluateContextInstanceExecute(r ApiEvaluateContextInstanceRequest) (*ContextInstanceEvaluations, *http.Response, error) + + /* + GetContextAttributeNames Get context attribute names + + Get context attribute names. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetContextAttributeNamesRequest + */ + GetContextAttributeNames(ctx context.Context, projectKey string, environmentKey string) ApiGetContextAttributeNamesRequest + + // GetContextAttributeNamesExecute executes the request + // @return ContextAttributeNamesCollection + GetContextAttributeNamesExecute(r ApiGetContextAttributeNamesRequest) (*ContextAttributeNamesCollection, *http.Response, error) + + /* + GetContextAttributeValues Get context attribute values + + Get context attribute values. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param attributeName The attribute name + @return ApiGetContextAttributeValuesRequest + */ + GetContextAttributeValues(ctx context.Context, projectKey string, environmentKey string, attributeName string) ApiGetContextAttributeValuesRequest + + // GetContextAttributeValuesExecute executes the request + // @return ContextAttributeValuesCollection + GetContextAttributeValuesExecute(r ApiGetContextAttributeValuesRequest) (*ContextAttributeValuesCollection, *http.Response, error) + + /* + GetContextInstances Get context instances + + Get context instances by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The context instance ID + @return ApiGetContextInstancesRequest + */ + GetContextInstances(ctx context.Context, projectKey string, environmentKey string, id string) ApiGetContextInstancesRequest + + // GetContextInstancesExecute executes the request + // @return ContextInstances + GetContextInstancesExecute(r ApiGetContextInstancesRequest) (*ContextInstances, *http.Response, error) + + /* + GetContextKindsByProjectKey Get context kinds + + Get all context kinds for a given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetContextKindsByProjectKeyRequest + */ + GetContextKindsByProjectKey(ctx context.Context, projectKey string) ApiGetContextKindsByProjectKeyRequest + + // GetContextKindsByProjectKeyExecute executes the request + // @return ContextKindsCollectionRep + GetContextKindsByProjectKeyExecute(r ApiGetContextKindsByProjectKeyRequest) (*ContextKindsCollectionRep, *http.Response, error) + + /* + GetContexts Get contexts + + Get contexts based on kind and key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param kind The context kind + @param key The context key + @return ApiGetContextsRequest + */ + GetContexts(ctx context.Context, projectKey string, environmentKey string, kind string, key string) ApiGetContextsRequest + + // GetContextsExecute executes the request + // @return Contexts + GetContextsExecute(r ApiGetContextsRequest) (*Contexts, *http.Response, error) + + /* + PutContextKind Create or update context kind + + Create or update a context kind by key. Only the included fields will be updated. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param key The context kind key + @return ApiPutContextKindRequest + */ + PutContextKind(ctx context.Context, projectKey string, key string) ApiPutContextKindRequest + + // PutContextKindExecute executes the request + // @return UpsertResponseRep + PutContextKindExecute(r ApiPutContextKindRequest) (*UpsertResponseRep, *http.Response, error) + + /* + SearchContextInstances Search for context instances + + +Search for context instances. + +You can use either the query parameters or the request body parameters. If both are provided, there is an error. + +To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). To learn more about context instances, read [Context instances](https://launchdarkly.com/docs/home/observability/multi-contexts#context-instances). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiSearchContextInstancesRequest + */ + SearchContextInstances(ctx context.Context, projectKey string, environmentKey string) ApiSearchContextInstancesRequest + + // SearchContextInstancesExecute executes the request + // @return ContextInstances + SearchContextInstancesExecute(r ApiSearchContextInstancesRequest) (*ContextInstances, *http.Response, error) + + /* + SearchContexts Search for contexts + + +Search for contexts. + +You can use either the query parameters or the request body parameters. If both are provided, there is an error. + +To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). To learn more about contexts, read [Contexts and context kinds](https://launchdarkly.com/docs/home/observability/contexts#contexts-and-context-kinds). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiSearchContextsRequest + */ + SearchContexts(ctx context.Context, projectKey string, environmentKey string) ApiSearchContextsRequest + + // SearchContextsExecute executes the request + // @return Contexts + SearchContextsExecute(r ApiSearchContextsRequest) (*Contexts, *http.Response, error) +} + +// ContextsApiService ContextsApi service +type ContextsApiService service + +type ApiDeleteContextInstancesRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + id string +} + +func (r ApiDeleteContextInstancesRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteContextInstancesExecute(r) +} + +/* +DeleteContextInstances Delete context instances + +Delete context instances by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The context instance ID + @return ApiDeleteContextInstancesRequest +*/ +func (a *ContextsApiService) DeleteContextInstances(ctx context.Context, projectKey string, environmentKey string, id string) ApiDeleteContextInstancesRequest { + return ApiDeleteContextInstancesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +func (a *ContextsApiService) DeleteContextInstancesExecute(r ApiDeleteContextInstancesRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.DeleteContextInstances") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiEvaluateContextInstanceRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + requestBody *map[string]interface{} + limit *int64 + offset *int64 + sort *string + filter *string +} + +func (r ApiEvaluateContextInstanceRequest) RequestBody(requestBody map[string]interface{}) ApiEvaluateContextInstanceRequest { + r.requestBody = &requestBody + return r +} + +// The number of feature flags to return. Defaults to -1, which returns all flags +func (r ApiEvaluateContextInstanceRequest) Limit(limit int64) ApiEvaluateContextInstanceRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiEvaluateContextInstanceRequest) Offset(offset int64) ApiEvaluateContextInstanceRequest { + r.offset = &offset + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order +func (r ApiEvaluateContextInstanceRequest) Sort(sort string) ApiEvaluateContextInstanceRequest { + r.sort = &sort + return r +} + +// A comma-separated list of filters. Each filter is of the form `field operator value`. Supported fields are explained above. +func (r ApiEvaluateContextInstanceRequest) Filter(filter string) ApiEvaluateContextInstanceRequest { + r.filter = &filter + return r +} + +func (r ApiEvaluateContextInstanceRequest) Execute() (*ContextInstanceEvaluations, *http.Response, error) { + return r.ApiService.EvaluateContextInstanceExecute(r) +} + +/* +EvaluateContextInstance Evaluate flags for context instance + +Evaluate flags for a context instance, for example, to determine the expected flag variation. **Do not use this API instead of an SDK.** The LaunchDarkly SDKs are specialized for the tasks of evaluating feature flags in your application at scale and generating analytics events based on those evaluations. This API is not designed for that use case. Any evaluations you perform with this API will not be reflected in features such as flag statuses and flag insights. Context instances evaluated by this API will not appear in the Contexts list. To learn more, read [Comparing LaunchDarkly's SDKs and REST API](https://launchdarkly.com/docs/guides/api/comparing-sdk-rest-api). + +### Filtering + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `query` filters for a string that matches against the flags' keys and names. It is not case sensitive. For example: `filter=query equals dark-mode`. +- `tags` filters the list to flags that have all of the tags in the list. For example: `filter=tags contains ["beta","q1"]`. + +You can also apply multiple filters at once. For example, setting `filter=query equals dark-mode, tags contains ["beta","q1"]` matches flags which match the key or name `dark-mode` and are tagged `beta` and `q1`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiEvaluateContextInstanceRequest +*/ +func (a *ContextsApiService) EvaluateContextInstance(ctx context.Context, projectKey string, environmentKey string) ApiEvaluateContextInstanceRequest { + return ApiEvaluateContextInstanceRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ContextInstanceEvaluations +func (a *ContextsApiService) EvaluateContextInstanceExecute(r ApiEvaluateContextInstanceRequest) (*ContextInstanceEvaluations, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextInstanceEvaluations + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.EvaluateContextInstance") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/flags/evaluate" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.requestBody == nil { + return localVarReturnValue, nil, reportError("requestBody is required and must be specified") + } + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.requestBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextAttributeNamesRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + filter *string + limit *int64 +} + +// A comma-separated list of context filters. This endpoint only accepts `kind` filters, with the `equals` operator, and `name` filters, with the `startsWith` operator. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiGetContextAttributeNamesRequest) Filter(filter string) ApiGetContextAttributeNamesRequest { + r.filter = &filter + return r +} + +// Specifies the maximum number of items in the collection to return (max: 100, default: 100) +func (r ApiGetContextAttributeNamesRequest) Limit(limit int64) ApiGetContextAttributeNamesRequest { + r.limit = &limit + return r +} + +func (r ApiGetContextAttributeNamesRequest) Execute() (*ContextAttributeNamesCollection, *http.Response, error) { + return r.ApiService.GetContextAttributeNamesExecute(r) +} + +/* +GetContextAttributeNames Get context attribute names + +Get context attribute names. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetContextAttributeNamesRequest +*/ +func (a *ContextsApiService) GetContextAttributeNames(ctx context.Context, projectKey string, environmentKey string) ApiGetContextAttributeNamesRequest { + return ApiGetContextAttributeNamesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ContextAttributeNamesCollection +func (a *ContextsApiService) GetContextAttributeNamesExecute(r ApiGetContextAttributeNamesRequest) (*ContextAttributeNamesCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextAttributeNamesCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.GetContextAttributeNames") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/context-attributes" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextAttributeValuesRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + attributeName string + filter *string + limit *int64 +} + +// A comma-separated list of context filters. This endpoint only accepts `kind` filters, with the `equals` operator, and `value` filters, with the `startsWith` operator. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiGetContextAttributeValuesRequest) Filter(filter string) ApiGetContextAttributeValuesRequest { + r.filter = &filter + return r +} + +// Specifies the maximum number of items in the collection to return (max: 100, default: 50) +func (r ApiGetContextAttributeValuesRequest) Limit(limit int64) ApiGetContextAttributeValuesRequest { + r.limit = &limit + return r +} + +func (r ApiGetContextAttributeValuesRequest) Execute() (*ContextAttributeValuesCollection, *http.Response, error) { + return r.ApiService.GetContextAttributeValuesExecute(r) +} + +/* +GetContextAttributeValues Get context attribute values + +Get context attribute values. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param attributeName The attribute name + @return ApiGetContextAttributeValuesRequest +*/ +func (a *ContextsApiService) GetContextAttributeValues(ctx context.Context, projectKey string, environmentKey string, attributeName string) ApiGetContextAttributeValuesRequest { + return ApiGetContextAttributeValuesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + attributeName: attributeName, + } +} + +// Execute executes the request +// @return ContextAttributeValuesCollection +func (a *ContextsApiService) GetContextAttributeValuesExecute(r ApiGetContextAttributeValuesRequest) (*ContextAttributeValuesCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextAttributeValuesCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.GetContextAttributeValues") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/context-attributes/{attributeName}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"attributeName"+"}", url.PathEscape(parameterToString(r.attributeName, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextInstancesRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + id string + limit *int64 + continuationToken *string + sort *string + filter *string + includeTotalCount *bool +} + +// Specifies the maximum number of context instances to return (max: 50, default: 20) +func (r ApiGetContextInstancesRequest) Limit(limit int64) ApiGetContextInstancesRequest { + r.limit = &limit + return r +} + +// Limits results to context instances with sort values after the value specified. You can use this for pagination, however, we recommend using the `next` link we provide instead. +func (r ApiGetContextInstancesRequest) ContinuationToken(continuationToken string) ApiGetContextInstancesRequest { + r.continuationToken = &continuationToken + return r +} + +// Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying `ts` for this value, or descending order by specifying `-ts`. +func (r ApiGetContextInstancesRequest) Sort(sort string) ApiGetContextInstancesRequest { + r.sort = &sort + return r +} + +// A comma-separated list of context filters. This endpoint only accepts an `applicationId` filter. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiGetContextInstancesRequest) Filter(filter string) ApiGetContextInstancesRequest { + r.filter = &filter + return r +} + +// Specifies whether to include or omit the total count of matching context instances. Defaults to true. +func (r ApiGetContextInstancesRequest) IncludeTotalCount(includeTotalCount bool) ApiGetContextInstancesRequest { + r.includeTotalCount = &includeTotalCount + return r +} + +func (r ApiGetContextInstancesRequest) Execute() (*ContextInstances, *http.Response, error) { + return r.ApiService.GetContextInstancesExecute(r) +} + +/* +GetContextInstances Get context instances + +Get context instances by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The context instance ID + @return ApiGetContextInstancesRequest +*/ +func (a *ContextsApiService) GetContextInstances(ctx context.Context, projectKey string, environmentKey string, id string) ApiGetContextInstancesRequest { + return ApiGetContextInstancesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return ContextInstances +func (a *ContextsApiService) GetContextInstancesExecute(r ApiGetContextInstancesRequest) (*ContextInstances, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextInstances + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.GetContextInstances") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.continuationToken != nil { + localVarQueryParams.Add("continuationToken", parameterToString(*r.continuationToken, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.includeTotalCount != nil { + localVarQueryParams.Add("includeTotalCount", parameterToString(*r.includeTotalCount, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextKindsByProjectKeyRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string +} + +func (r ApiGetContextKindsByProjectKeyRequest) Execute() (*ContextKindsCollectionRep, *http.Response, error) { + return r.ApiService.GetContextKindsByProjectKeyExecute(r) +} + +/* +GetContextKindsByProjectKey Get context kinds + +Get all context kinds for a given project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetContextKindsByProjectKeyRequest +*/ +func (a *ContextsApiService) GetContextKindsByProjectKey(ctx context.Context, projectKey string) ApiGetContextKindsByProjectKeyRequest { + return ApiGetContextKindsByProjectKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return ContextKindsCollectionRep +func (a *ContextsApiService) GetContextKindsByProjectKeyExecute(r ApiGetContextKindsByProjectKeyRequest) (*ContextKindsCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextKindsCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.GetContextKindsByProjectKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/context-kinds" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextsRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + kind string + key string + limit *int64 + continuationToken *string + sort *string + filter *string + includeTotalCount *bool +} + +// Specifies the maximum number of items in the collection to return (max: 50, default: 20) +func (r ApiGetContextsRequest) Limit(limit int64) ApiGetContextsRequest { + r.limit = &limit + return r +} + +// Limits results to contexts with sort values after the value specified. You can use this for pagination, however, we recommend using the `next` link we provide instead. +func (r ApiGetContextsRequest) ContinuationToken(continuationToken string) ApiGetContextsRequest { + r.continuationToken = &continuationToken + return r +} + +// Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying `ts` for this value, or descending order by specifying `-ts`. +func (r ApiGetContextsRequest) Sort(sort string) ApiGetContextsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of context filters. This endpoint only accepts an `applicationId` filter. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiGetContextsRequest) Filter(filter string) ApiGetContextsRequest { + r.filter = &filter + return r +} + +// Specifies whether to include or omit the total count of matching contexts. Defaults to true. +func (r ApiGetContextsRequest) IncludeTotalCount(includeTotalCount bool) ApiGetContextsRequest { + r.includeTotalCount = &includeTotalCount + return r +} + +func (r ApiGetContextsRequest) Execute() (*Contexts, *http.Response, error) { + return r.ApiService.GetContextsExecute(r) +} + +/* +GetContexts Get contexts + +Get contexts based on kind and key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param kind The context kind + @param key The context key + @return ApiGetContextsRequest +*/ +func (a *ContextsApiService) GetContexts(ctx context.Context, projectKey string, environmentKey string, kind string, key string) ApiGetContextsRequest { + return ApiGetContextsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + kind: kind, + key: key, + } +} + +// Execute executes the request +// @return Contexts +func (a *ContextsApiService) GetContextsExecute(r ApiGetContextsRequest) (*Contexts, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Contexts + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.GetContexts") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/{kind}/{key}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"kind"+"}", url.PathEscape(parameterToString(r.kind, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"key"+"}", url.PathEscape(parameterToString(r.key, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.continuationToken != nil { + localVarQueryParams.Add("continuationToken", parameterToString(*r.continuationToken, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.includeTotalCount != nil { + localVarQueryParams.Add("includeTotalCount", parameterToString(*r.includeTotalCount, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutContextKindRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + key string + upsertContextKindPayload *UpsertContextKindPayload +} + +func (r ApiPutContextKindRequest) UpsertContextKindPayload(upsertContextKindPayload UpsertContextKindPayload) ApiPutContextKindRequest { + r.upsertContextKindPayload = &upsertContextKindPayload + return r +} + +func (r ApiPutContextKindRequest) Execute() (*UpsertResponseRep, *http.Response, error) { + return r.ApiService.PutContextKindExecute(r) +} + +/* +PutContextKind Create or update context kind + +Create or update a context kind by key. Only the included fields will be updated. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param key The context kind key + @return ApiPutContextKindRequest +*/ +func (a *ContextsApiService) PutContextKind(ctx context.Context, projectKey string, key string) ApiPutContextKindRequest { + return ApiPutContextKindRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + key: key, + } +} + +// Execute executes the request +// @return UpsertResponseRep +func (a *ContextsApiService) PutContextKindExecute(r ApiPutContextKindRequest) (*UpsertResponseRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UpsertResponseRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.PutContextKind") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/context-kinds/{key}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"key"+"}", url.PathEscape(parameterToString(r.key, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.upsertContextKindPayload == nil { + return localVarReturnValue, nil, reportError("upsertContextKindPayload is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.upsertContextKindPayload + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiSearchContextInstancesRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + contextInstanceSearch *ContextInstanceSearch + limit *int64 + continuationToken *string + sort *string + filter *string + includeTotalCount *bool +} + +func (r ApiSearchContextInstancesRequest) ContextInstanceSearch(contextInstanceSearch ContextInstanceSearch) ApiSearchContextInstancesRequest { + r.contextInstanceSearch = &contextInstanceSearch + return r +} + +// Specifies the maximum number of items in the collection to return (max: 50, default: 20) +func (r ApiSearchContextInstancesRequest) Limit(limit int64) ApiSearchContextInstancesRequest { + r.limit = &limit + return r +} + +// Limits results to context instances with sort values after the value specified. You can use this for pagination, however, we recommend using the `next` link we provide instead. +func (r ApiSearchContextInstancesRequest) ContinuationToken(continuationToken string) ApiSearchContextInstancesRequest { + r.continuationToken = &continuationToken + return r +} + +// Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying `ts` for this value, or descending order by specifying `-ts`. +func (r ApiSearchContextInstancesRequest) Sort(sort string) ApiSearchContextInstancesRequest { + r.sort = &sort + return r +} + +// A comma-separated list of context filters. This endpoint only accepts an `applicationId` filter. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiSearchContextInstancesRequest) Filter(filter string) ApiSearchContextInstancesRequest { + r.filter = &filter + return r +} + +// Specifies whether to include or omit the total count of matching context instances. Defaults to true. +func (r ApiSearchContextInstancesRequest) IncludeTotalCount(includeTotalCount bool) ApiSearchContextInstancesRequest { + r.includeTotalCount = &includeTotalCount + return r +} + +func (r ApiSearchContextInstancesRequest) Execute() (*ContextInstances, *http.Response, error) { + return r.ApiService.SearchContextInstancesExecute(r) +} + +/* +SearchContextInstances Search for context instances + + +Search for context instances. + +You can use either the query parameters or the request body parameters. If both are provided, there is an error. + +To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). To learn more about context instances, read [Context instances](https://launchdarkly.com/docs/home/observability/multi-contexts#context-instances). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiSearchContextInstancesRequest +*/ +func (a *ContextsApiService) SearchContextInstances(ctx context.Context, projectKey string, environmentKey string) ApiSearchContextInstancesRequest { + return ApiSearchContextInstancesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ContextInstances +func (a *ContextsApiService) SearchContextInstancesExecute(r ApiSearchContextInstancesRequest) (*ContextInstances, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextInstances + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.SearchContextInstances") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/context-instances/search" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.contextInstanceSearch == nil { + return localVarReturnValue, nil, reportError("contextInstanceSearch is required and must be specified") + } + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.continuationToken != nil { + localVarQueryParams.Add("continuationToken", parameterToString(*r.continuationToken, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.includeTotalCount != nil { + localVarQueryParams.Add("includeTotalCount", parameterToString(*r.includeTotalCount, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.contextInstanceSearch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiSearchContextsRequest struct { + ctx context.Context + ApiService ContextsApi + projectKey string + environmentKey string + contextSearch *ContextSearch + limit *int64 + continuationToken *string + sort *string + filter *string + includeTotalCount *bool +} + +func (r ApiSearchContextsRequest) ContextSearch(contextSearch ContextSearch) ApiSearchContextsRequest { + r.contextSearch = &contextSearch + return r +} + +// Specifies the maximum number of items in the collection to return (max: 50, default: 20) +func (r ApiSearchContextsRequest) Limit(limit int64) ApiSearchContextsRequest { + r.limit = &limit + return r +} + +// Limits results to contexts with sort values after the value specified. You can use this for pagination, however, we recommend using the `next` link we provide instead. +func (r ApiSearchContextsRequest) ContinuationToken(continuationToken string) ApiSearchContextsRequest { + r.continuationToken = &continuationToken + return r +} + +// Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying `ts` for this value, or descending order by specifying `-ts`. +func (r ApiSearchContextsRequest) Sort(sort string) ApiSearchContextsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of context filters. To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). +func (r ApiSearchContextsRequest) Filter(filter string) ApiSearchContextsRequest { + r.filter = &filter + return r +} + +// Specifies whether to include or omit the total count of matching contexts. Defaults to true. +func (r ApiSearchContextsRequest) IncludeTotalCount(includeTotalCount bool) ApiSearchContextsRequest { + r.includeTotalCount = &includeTotalCount + return r +} + +func (r ApiSearchContextsRequest) Execute() (*Contexts, *http.Response, error) { + return r.ApiService.SearchContextsExecute(r) +} + +/* +SearchContexts Search for contexts + + +Search for contexts. + +You can use either the query parameters or the request body parameters. If both are provided, there is an error. + +To learn more about the filter syntax, read [Filtering contexts and context instances](https://launchdarkly.com/docs/ld-docs/api/contexts#filtering-contexts-and-context-instances). To learn more about contexts, read [Contexts and context kinds](https://launchdarkly.com/docs/home/observability/contexts#contexts-and-context-kinds). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiSearchContextsRequest +*/ +func (a *ContextsApiService) SearchContexts(ctx context.Context, projectKey string, environmentKey string) ApiSearchContextsRequest { + return ApiSearchContextsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Contexts +func (a *ContextsApiService) SearchContextsExecute(r ApiSearchContextsRequest) (*Contexts, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Contexts + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ContextsApiService.SearchContexts") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/contexts/search" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.contextSearch == nil { + return localVarReturnValue, nil, reportError("contextSearch is required and must be specified") + } + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.continuationToken != nil { + localVarQueryParams.Add("continuationToken", parameterToString(*r.continuationToken, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.includeTotalCount != nil { + localVarQueryParams.Add("includeTotalCount", parameterToString(*r.includeTotalCount, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.contextSearch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_custom_roles.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_custom_roles.go new file mode 100644 index 00000000..7305f9da --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_custom_roles.go @@ -0,0 +1,903 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type CustomRolesApi interface { + + /* + DeleteCustomRole Delete custom role + + Delete a custom role by key + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key + @return ApiDeleteCustomRoleRequest + */ + DeleteCustomRole(ctx context.Context, customRoleKey string) ApiDeleteCustomRoleRequest + + // DeleteCustomRoleExecute executes the request + DeleteCustomRoleExecute(r ApiDeleteCustomRoleRequest) (*http.Response, error) + + /* + GetCustomRole Get custom role + + Get a single custom role by key or ID + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key or ID + @return ApiGetCustomRoleRequest + */ + GetCustomRole(ctx context.Context, customRoleKey string) ApiGetCustomRoleRequest + + // GetCustomRoleExecute executes the request + // @return CustomRole + GetCustomRoleExecute(r ApiGetCustomRoleRequest) (*CustomRole, *http.Response, error) + + /* + GetCustomRoles List custom roles + + Get a complete list of custom roles. Custom roles let you create flexible policies providing fine-grained access control to everything in LaunchDarkly, from feature flags to goals, environments, and teams. With custom roles, it's possible to enforce access policies that meet your exact workflow needs. Custom roles are available to customers on our enterprise plans. If you're interested in learning more about our enterprise plans, contact sales@launchdarkly.com. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetCustomRolesRequest + */ + GetCustomRoles(ctx context.Context) ApiGetCustomRolesRequest + + // GetCustomRolesExecute executes the request + // @return CustomRoles + GetCustomRolesExecute(r ApiGetCustomRolesRequest) (*CustomRoles, *http.Response, error) + + /* + PatchCustomRole Update custom role + + Update a single custom role. Updating a custom role uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the `policy` array, set the `path` to `/policy` and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key + @return ApiPatchCustomRoleRequest + */ + PatchCustomRole(ctx context.Context, customRoleKey string) ApiPatchCustomRoleRequest + + // PatchCustomRoleExecute executes the request + // @return CustomRole + PatchCustomRoleExecute(r ApiPatchCustomRoleRequest) (*CustomRole, *http.Response, error) + + /* + PostCustomRole Create custom role + + Create a new custom role + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostCustomRoleRequest + */ + PostCustomRole(ctx context.Context) ApiPostCustomRoleRequest + + // PostCustomRoleExecute executes the request + // @return CustomRole + PostCustomRoleExecute(r ApiPostCustomRoleRequest) (*CustomRole, *http.Response, error) +} + +// CustomRolesApiService CustomRolesApi service +type CustomRolesApiService service + +type ApiDeleteCustomRoleRequest struct { + ctx context.Context + ApiService CustomRolesApi + customRoleKey string +} + +func (r ApiDeleteCustomRoleRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteCustomRoleExecute(r) +} + +/* +DeleteCustomRole Delete custom role + +Delete a custom role by key + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key + @return ApiDeleteCustomRoleRequest +*/ +func (a *CustomRolesApiService) DeleteCustomRole(ctx context.Context, customRoleKey string) ApiDeleteCustomRoleRequest { + return ApiDeleteCustomRoleRequest{ + ApiService: a, + ctx: ctx, + customRoleKey: customRoleKey, + } +} + +// Execute executes the request +func (a *CustomRolesApiService) DeleteCustomRoleExecute(r ApiDeleteCustomRoleRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CustomRolesApiService.DeleteCustomRole") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/roles/{customRoleKey}" + localVarPath = strings.Replace(localVarPath, "{"+"customRoleKey"+"}", url.PathEscape(parameterToString(r.customRoleKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetCustomRoleRequest struct { + ctx context.Context + ApiService CustomRolesApi + customRoleKey string +} + +func (r ApiGetCustomRoleRequest) Execute() (*CustomRole, *http.Response, error) { + return r.ApiService.GetCustomRoleExecute(r) +} + +/* +GetCustomRole Get custom role + +Get a single custom role by key or ID + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key or ID + @return ApiGetCustomRoleRequest +*/ +func (a *CustomRolesApiService) GetCustomRole(ctx context.Context, customRoleKey string) ApiGetCustomRoleRequest { + return ApiGetCustomRoleRequest{ + ApiService: a, + ctx: ctx, + customRoleKey: customRoleKey, + } +} + +// Execute executes the request +// @return CustomRole +func (a *CustomRolesApiService) GetCustomRoleExecute(r ApiGetCustomRoleRequest) (*CustomRole, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomRole + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CustomRolesApiService.GetCustomRole") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/roles/{customRoleKey}" + localVarPath = strings.Replace(localVarPath, "{"+"customRoleKey"+"}", url.PathEscape(parameterToString(r.customRoleKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetCustomRolesRequest struct { + ctx context.Context + ApiService CustomRolesApi + limit *int64 + offset *int64 +} + +// The maximum number of custom roles to return. Defaults to 20. +func (r ApiGetCustomRolesRequest) Limit(limit int64) ApiGetCustomRolesRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Defaults to 0. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetCustomRolesRequest) Offset(offset int64) ApiGetCustomRolesRequest { + r.offset = &offset + return r +} + +func (r ApiGetCustomRolesRequest) Execute() (*CustomRoles, *http.Response, error) { + return r.ApiService.GetCustomRolesExecute(r) +} + +/* +GetCustomRoles List custom roles + +Get a complete list of custom roles. Custom roles let you create flexible policies providing fine-grained access control to everything in LaunchDarkly, from feature flags to goals, environments, and teams. With custom roles, it's possible to enforce access policies that meet your exact workflow needs. Custom roles are available to customers on our enterprise plans. If you're interested in learning more about our enterprise plans, contact sales@launchdarkly.com. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetCustomRolesRequest +*/ +func (a *CustomRolesApiService) GetCustomRoles(ctx context.Context) ApiGetCustomRolesRequest { + return ApiGetCustomRolesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return CustomRoles +func (a *CustomRolesApiService) GetCustomRolesExecute(r ApiGetCustomRolesRequest) (*CustomRoles, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomRoles + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CustomRolesApiService.GetCustomRoles") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/roles" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchCustomRoleRequest struct { + ctx context.Context + ApiService CustomRolesApi + customRoleKey string + patchWithComment *PatchWithComment +} + +func (r ApiPatchCustomRoleRequest) PatchWithComment(patchWithComment PatchWithComment) ApiPatchCustomRoleRequest { + r.patchWithComment = &patchWithComment + return r +} + +func (r ApiPatchCustomRoleRequest) Execute() (*CustomRole, *http.Response, error) { + return r.ApiService.PatchCustomRoleExecute(r) +} + +/* +PatchCustomRole Update custom role + +Update a single custom role. Updating a custom role uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the `policy` array, set the `path` to `/policy` and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param customRoleKey The custom role key + @return ApiPatchCustomRoleRequest +*/ +func (a *CustomRolesApiService) PatchCustomRole(ctx context.Context, customRoleKey string) ApiPatchCustomRoleRequest { + return ApiPatchCustomRoleRequest{ + ApiService: a, + ctx: ctx, + customRoleKey: customRoleKey, + } +} + +// Execute executes the request +// @return CustomRole +func (a *CustomRolesApiService) PatchCustomRoleExecute(r ApiPatchCustomRoleRequest) (*CustomRole, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomRole + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CustomRolesApiService.PatchCustomRole") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/roles/{customRoleKey}" + localVarPath = strings.Replace(localVarPath, "{"+"customRoleKey"+"}", url.PathEscape(parameterToString(r.customRoleKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchWithComment == nil { + return localVarReturnValue, nil, reportError("patchWithComment is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchWithComment + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostCustomRoleRequest struct { + ctx context.Context + ApiService CustomRolesApi + customRolePost *CustomRolePost +} + +func (r ApiPostCustomRoleRequest) CustomRolePost(customRolePost CustomRolePost) ApiPostCustomRoleRequest { + r.customRolePost = &customRolePost + return r +} + +func (r ApiPostCustomRoleRequest) Execute() (*CustomRole, *http.Response, error) { + return r.ApiService.PostCustomRoleExecute(r) +} + +/* +PostCustomRole Create custom role + +Create a new custom role + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostCustomRoleRequest +*/ +func (a *CustomRolesApiService) PostCustomRole(ctx context.Context) ApiPostCustomRoleRequest { + return ApiPostCustomRoleRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return CustomRole +func (a *CustomRolesApiService) PostCustomRoleExecute(r ApiPostCustomRoleRequest) (*CustomRole, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomRole + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CustomRolesApiService.PostCustomRole") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/roles" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.customRolePost == nil { + return localVarReturnValue, nil, reportError("customRolePost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.customRolePost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_data_export_destinations.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_data_export_destinations.go new file mode 100644 index 00000000..ef89d93d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_data_export_destinations.go @@ -0,0 +1,1229 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type DataExportDestinationsApi interface { + + /* + DeleteDestination Delete Data Export destination + + Delete a Data Export destination by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiDeleteDestinationRequest + */ + DeleteDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiDeleteDestinationRequest + + // DeleteDestinationExecute executes the request + DeleteDestinationExecute(r ApiDeleteDestinationRequest) (*http.Response, error) + + /* + GetDestination Get destination + + Get a single Data Export destination by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiGetDestinationRequest + */ + GetDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiGetDestinationRequest + + // GetDestinationExecute executes the request + // @return Destination + GetDestinationExecute(r ApiGetDestinationRequest) (*Destination, *http.Response, error) + + /* + GetDestinations List destinations + + Get a list of Data Export destinations configured across all projects and environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDestinationsRequest + */ + GetDestinations(ctx context.Context) ApiGetDestinationsRequest + + // GetDestinationsExecute executes the request + // @return Destinations + GetDestinationsExecute(r ApiGetDestinationsRequest) (*Destinations, *http.Response, error) + + /* + PatchDestination Update Data Export destination + + Update a Data Export destination. Updating a destination uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiPatchDestinationRequest + */ + PatchDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiPatchDestinationRequest + + // PatchDestinationExecute executes the request + // @return Destination + PatchDestinationExecute(r ApiPatchDestinationRequest) (*Destination, *http.Response, error) + + /* + PostDestination Create Data Export destination + + +Create a new Data Export destination. + +In the `config` request body parameter, the fields required depend on the type of Data Export destination. + +
+Click to expand config parameter details + +#### Azure Event Hubs + +To create a Data Export destination with a `kind` of `azure-event-hubs`, the `config` object requires the following fields: + +* `namespace`: The Event Hub Namespace name +* `name`: The Event Hub name +* `policyName`: The shared access signature policy name. You can find your policy name in the settings of your Azure Event Hubs Namespace. +* `policyKey`: The shared access signature key. You can find your policy key in the settings of your Azure Event Hubs Namespace. + +#### Google Cloud Pub/Sub + +To create a Data Export destination with a `kind` of `google-pubsub`, the `config` object requires the following fields: + +* `project`: The Google PubSub project ID for the project to publish to +* `topic`: The Google PubSub topic ID for the topic to publish to + +#### Amazon Kinesis + +To create a Data Export destination with a `kind` of `kinesis`, the `config` object requires the following fields: + +* `region`: The Kinesis stream's AWS region key +* `roleArn`: The Amazon Resource Name (ARN) of the AWS role that will be writing to Kinesis +* `streamName`: The name of the Kinesis stream that LaunchDarkly is sending events to. This is not the ARN of the stream. + +#### mParticle + +To create a Data Export destination with a `kind` of `mparticle`, the `config` object requires the following fields: + +* `apiKey`: The mParticle API key +* `secret`: The mParticle API secret +* `userIdentity`: The type of identifier you use to identify your end users in mParticle +* `anonymousUserIdentity`: The type of identifier you use to identify your anonymous end users in mParticle + +#### Segment + +To create a Data Export destination with a `kind` of `segment`, the `config` object requires the following fields: + +* `writeKey`: The Segment write key. This is used to authenticate LaunchDarkly's calls to Segment. + +#### Snowflake + +To create a Data Export destination with a `kind` of `snowflake-v2`, the `config` object requires the following fields: + +* `publicKey`: The `publicKey` is returned as part of the [Generate Snowflake destination key pair](https://launchdarkly.com/docs/api/data-export-destinations/post-generate-warehouse-destination-key-pair) response. It is the `public_key` field. +* `snowflakeHostAddress`: Your Snowflake account URL. + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostDestinationRequest + */ + PostDestination(ctx context.Context, projectKey string, environmentKey string) ApiPostDestinationRequest + + // PostDestinationExecute executes the request + // @return Destination + PostDestinationExecute(r ApiPostDestinationRequest) (*Destination, *http.Response, error) + + /* + PostGenerateWarehouseDestinationKeyPair Generate Snowflake destination key pair + + Generate key pair to allow Data Export to authenticate into a Snowflake warehouse destination + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostGenerateWarehouseDestinationKeyPairRequest + */ + PostGenerateWarehouseDestinationKeyPair(ctx context.Context) ApiPostGenerateWarehouseDestinationKeyPairRequest + + // PostGenerateWarehouseDestinationKeyPairExecute executes the request + // @return GenerateWarehouseDestinationKeyPairPostRep + PostGenerateWarehouseDestinationKeyPairExecute(r ApiPostGenerateWarehouseDestinationKeyPairRequest) (*GenerateWarehouseDestinationKeyPairPostRep, *http.Response, error) +} + +// DataExportDestinationsApiService DataExportDestinationsApi service +type DataExportDestinationsApiService service + +type ApiDeleteDestinationRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi + projectKey string + environmentKey string + id string +} + +func (r ApiDeleteDestinationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteDestinationExecute(r) +} + +/* +DeleteDestination Delete Data Export destination + +Delete a Data Export destination by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiDeleteDestinationRequest +*/ +func (a *DataExportDestinationsApiService) DeleteDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiDeleteDestinationRequest { + return ApiDeleteDestinationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +func (a *DataExportDestinationsApiService) DeleteDestinationExecute(r ApiDeleteDestinationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.DeleteDestination") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations/{projectKey}/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetDestinationRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi + projectKey string + environmentKey string + id string +} + +func (r ApiGetDestinationRequest) Execute() (*Destination, *http.Response, error) { + return r.ApiService.GetDestinationExecute(r) +} + +/* +GetDestination Get destination + +Get a single Data Export destination by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiGetDestinationRequest +*/ +func (a *DataExportDestinationsApiService) GetDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiGetDestinationRequest { + return ApiGetDestinationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return Destination +func (a *DataExportDestinationsApiService) GetDestinationExecute(r ApiGetDestinationRequest) (*Destination, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Destination + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.GetDestination") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations/{projectKey}/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetDestinationsRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi +} + +func (r ApiGetDestinationsRequest) Execute() (*Destinations, *http.Response, error) { + return r.ApiService.GetDestinationsExecute(r) +} + +/* +GetDestinations List destinations + +Get a list of Data Export destinations configured across all projects and environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDestinationsRequest +*/ +func (a *DataExportDestinationsApiService) GetDestinations(ctx context.Context) ApiGetDestinationsRequest { + return ApiGetDestinationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Destinations +func (a *DataExportDestinationsApiService) GetDestinationsExecute(r ApiGetDestinationsRequest) (*Destinations, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Destinations + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.GetDestinations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchDestinationRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi + projectKey string + environmentKey string + id string + patchOperation *[]PatchOperation +} + +func (r ApiPatchDestinationRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchDestinationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchDestinationRequest) Execute() (*Destination, *http.Response, error) { + return r.ApiService.PatchDestinationExecute(r) +} + +/* +PatchDestination Update Data Export destination + +Update a Data Export destination. Updating a destination uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param id The Data Export destination ID + @return ApiPatchDestinationRequest +*/ +func (a *DataExportDestinationsApiService) PatchDestination(ctx context.Context, projectKey string, environmentKey string, id string) ApiPatchDestinationRequest { + return ApiPatchDestinationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return Destination +func (a *DataExportDestinationsApiService) PatchDestinationExecute(r ApiPatchDestinationRequest) (*Destination, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Destination + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.PatchDestination") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations/{projectKey}/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostDestinationRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi + projectKey string + environmentKey string + destinationPost *DestinationPost +} + +func (r ApiPostDestinationRequest) DestinationPost(destinationPost DestinationPost) ApiPostDestinationRequest { + r.destinationPost = &destinationPost + return r +} + +func (r ApiPostDestinationRequest) Execute() (*Destination, *http.Response, error) { + return r.ApiService.PostDestinationExecute(r) +} + +/* +PostDestination Create Data Export destination + + +Create a new Data Export destination. + +In the `config` request body parameter, the fields required depend on the type of Data Export destination. + +
+Click to expand config parameter details + +#### Azure Event Hubs + +To create a Data Export destination with a `kind` of `azure-event-hubs`, the `config` object requires the following fields: + +* `namespace`: The Event Hub Namespace name +* `name`: The Event Hub name +* `policyName`: The shared access signature policy name. You can find your policy name in the settings of your Azure Event Hubs Namespace. +* `policyKey`: The shared access signature key. You can find your policy key in the settings of your Azure Event Hubs Namespace. + +#### Google Cloud Pub/Sub + +To create a Data Export destination with a `kind` of `google-pubsub`, the `config` object requires the following fields: + +* `project`: The Google PubSub project ID for the project to publish to +* `topic`: The Google PubSub topic ID for the topic to publish to + +#### Amazon Kinesis + +To create a Data Export destination with a `kind` of `kinesis`, the `config` object requires the following fields: + +* `region`: The Kinesis stream's AWS region key +* `roleArn`: The Amazon Resource Name (ARN) of the AWS role that will be writing to Kinesis +* `streamName`: The name of the Kinesis stream that LaunchDarkly is sending events to. This is not the ARN of the stream. + +#### mParticle + +To create a Data Export destination with a `kind` of `mparticle`, the `config` object requires the following fields: + +* `apiKey`: The mParticle API key +* `secret`: The mParticle API secret +* `userIdentity`: The type of identifier you use to identify your end users in mParticle +* `anonymousUserIdentity`: The type of identifier you use to identify your anonymous end users in mParticle + +#### Segment + +To create a Data Export destination with a `kind` of `segment`, the `config` object requires the following fields: + +* `writeKey`: The Segment write key. This is used to authenticate LaunchDarkly's calls to Segment. + +#### Snowflake + +To create a Data Export destination with a `kind` of `snowflake-v2`, the `config` object requires the following fields: + +* `publicKey`: The `publicKey` is returned as part of the [Generate Snowflake destination key pair](https://launchdarkly.com/docs/api/data-export-destinations/post-generate-warehouse-destination-key-pair) response. It is the `public_key` field. +* `snowflakeHostAddress`: Your Snowflake account URL. + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostDestinationRequest +*/ +func (a *DataExportDestinationsApiService) PostDestination(ctx context.Context, projectKey string, environmentKey string) ApiPostDestinationRequest { + return ApiPostDestinationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Destination +func (a *DataExportDestinationsApiService) PostDestinationExecute(r ApiPostDestinationRequest) (*Destination, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Destination + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.PostDestination") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.destinationPost == nil { + return localVarReturnValue, nil, reportError("destinationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.destinationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostGenerateWarehouseDestinationKeyPairRequest struct { + ctx context.Context + ApiService DataExportDestinationsApi +} + +func (r ApiPostGenerateWarehouseDestinationKeyPairRequest) Execute() (*GenerateWarehouseDestinationKeyPairPostRep, *http.Response, error) { + return r.ApiService.PostGenerateWarehouseDestinationKeyPairExecute(r) +} + +/* +PostGenerateWarehouseDestinationKeyPair Generate Snowflake destination key pair + +Generate key pair to allow Data Export to authenticate into a Snowflake warehouse destination + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostGenerateWarehouseDestinationKeyPairRequest +*/ +func (a *DataExportDestinationsApiService) PostGenerateWarehouseDestinationKeyPair(ctx context.Context) ApiPostGenerateWarehouseDestinationKeyPairRequest { + return ApiPostGenerateWarehouseDestinationKeyPairRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return GenerateWarehouseDestinationKeyPairPostRep +func (a *DataExportDestinationsApiService) PostGenerateWarehouseDestinationKeyPairExecute(r ApiPostGenerateWarehouseDestinationKeyPairRequest) (*GenerateWarehouseDestinationKeyPairPostRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *GenerateWarehouseDestinationKeyPairPostRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DataExportDestinationsApiService.PostGenerateWarehouseDestinationKeyPair") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/destinations/generate-warehouse-destination-key-pair" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_environments.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_environments.go new file mode 100644 index 00000000..f765be42 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_environments.go @@ -0,0 +1,1494 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type EnvironmentsApi interface { + + /* + DeleteEnvironment Delete environment + + Delete a environment by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiDeleteEnvironmentRequest + */ + DeleteEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiDeleteEnvironmentRequest + + // DeleteEnvironmentExecute executes the request + DeleteEnvironmentExecute(r ApiDeleteEnvironmentRequest) (*http.Response, error) + + /* + GetEnvironment Get environment + + > ### Approval settings +> +> The `approvalSettings` key is only returned when [approvals](https://launchdarkly.com/docs/home/releases/approvals) for flags or segments are enabled. + +Get an environment given a project and key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetEnvironmentRequest + */ + GetEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiGetEnvironmentRequest + + // GetEnvironmentExecute executes the request + // @return Environment + GetEnvironmentExecute(r ApiGetEnvironmentRequest) (*Environment, *http.Response, error) + + /* + GetEnvironmentsByProject List environments + + Return a list of environments for the specified project. + +By default, this returns the first 20 environments. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering environments + +LaunchDarkly supports two fields for filters: +- `query` is a string that matches against the environments' names and keys. It is not case sensitive. +- `tags` is a `+`-separated list of environment tags. It filters the list of environments that have all of the tags in the list. + +For example, the filter `filter=query:abc,tags:tag-1+tag-2` matches environments with the string `abc` in their name or key and also are tagged with `tag-1` and `tag-2`. The filter is not case-sensitive. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `+` in `filter=tags:tag-1+tag-2` must be encoded to `%2B`. + +### Sorting environments + +LaunchDarkly supports the following fields for sorting: + +- `createdOn` sorts by the creation date of the environment. +- `critical` sorts by whether the environments are marked as critical. +- `name` sorts by environment name. + +For example, `sort=name` sorts the response by environment name in ascending order. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetEnvironmentsByProjectRequest + */ + GetEnvironmentsByProject(ctx context.Context, projectKey string) ApiGetEnvironmentsByProjectRequest + + // GetEnvironmentsByProjectExecute executes the request + // @return Environments + GetEnvironmentsByProjectExecute(r ApiGetEnvironmentsByProjectRequest) (*Environments, *http.Response, error) + + /* + PatchEnvironment Update environment + + +Update an environment. Updating an environment uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +To update fields in the environment object that are arrays, set the `path` to the name of the field and then append `/`. Using `/0` appends to the beginning of the array. + +### Approval settings + +This request only returns the `approvalSettings` key if the [approvals](https://launchdarkly.com/docs/home/releases/approvals/) feature is enabled. + +Only the `canReviewOwnRequest`, `canApplyDeclinedChanges`, `minNumApprovals`, `required` and `requiredApprovalTagsfields` are editable. + +If you try to patch the environment by setting both `required` and `requiredApprovalTags`, the request fails and an error appears. You can specify either required approvals for all flags in an environment or those with specific tags, but not both. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPatchEnvironmentRequest + */ + PatchEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiPatchEnvironmentRequest + + // PatchEnvironmentExecute executes the request + // @return Environment + PatchEnvironmentExecute(r ApiPatchEnvironmentRequest) (*Environment, *http.Response, error) + + /* + PostEnvironment Create environment + + > ### Approval settings +> +> The `approvalSettings` key is only returned when the [approvals](https://launchdarkly.com/docs/home/releases/approvals/) feature is enabled. +> +> You cannot update approval settings when creating new environments. Update approval settings with the [https://launchdarkly.com/docs/api/environments/patch-environment). + +Create a new environment in a specified project with a given name, key, swatch color, and default TTL. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostEnvironmentRequest + */ + PostEnvironment(ctx context.Context, projectKey string) ApiPostEnvironmentRequest + + // PostEnvironmentExecute executes the request + // @return Environment + PostEnvironmentExecute(r ApiPostEnvironmentRequest) (*Environment, *http.Response, error) + + /* + ResetEnvironmentMobileKey Reset environment mobile SDK key + + Reset an environment's mobile key. The optional expiry for the old key is deprecated for this endpoint, so the old key will always expire immediately. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiResetEnvironmentMobileKeyRequest + */ + ResetEnvironmentMobileKey(ctx context.Context, projectKey string, environmentKey string) ApiResetEnvironmentMobileKeyRequest + + // ResetEnvironmentMobileKeyExecute executes the request + // @return Environment + ResetEnvironmentMobileKeyExecute(r ApiResetEnvironmentMobileKeyRequest) (*Environment, *http.Response, error) + + /* + ResetEnvironmentSDKKey Reset environment SDK key + + Reset an environment's SDK key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiResetEnvironmentSDKKeyRequest + */ + ResetEnvironmentSDKKey(ctx context.Context, projectKey string, environmentKey string) ApiResetEnvironmentSDKKeyRequest + + // ResetEnvironmentSDKKeyExecute executes the request + // @return Environment + ResetEnvironmentSDKKeyExecute(r ApiResetEnvironmentSDKKeyRequest) (*Environment, *http.Response, error) +} + +// EnvironmentsApiService EnvironmentsApi service +type EnvironmentsApiService service + +type ApiDeleteEnvironmentRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentKey string +} + +func (r ApiDeleteEnvironmentRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteEnvironmentExecute(r) +} + +/* +DeleteEnvironment Delete environment + +Delete a environment by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiDeleteEnvironmentRequest +*/ +func (a *EnvironmentsApiService) DeleteEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiDeleteEnvironmentRequest { + return ApiDeleteEnvironmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +func (a *EnvironmentsApiService) DeleteEnvironmentExecute(r ApiDeleteEnvironmentRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.DeleteEnvironment") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetEnvironmentRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentKey string +} + +func (r ApiGetEnvironmentRequest) Execute() (*Environment, *http.Response, error) { + return r.ApiService.GetEnvironmentExecute(r) +} + +/* +GetEnvironment Get environment + +> ### Approval settings +> +> The `approvalSettings` key is only returned when [approvals](https://launchdarkly.com/docs/home/releases/approvals) for flags or segments are enabled. + +Get an environment given a project and key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetEnvironmentRequest +*/ +func (a *EnvironmentsApiService) GetEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiGetEnvironmentRequest { + return ApiGetEnvironmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Environment +func (a *EnvironmentsApiService) GetEnvironmentExecute(r ApiGetEnvironmentRequest) (*Environment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.GetEnvironment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetEnvironmentsByProjectRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + limit *int64 + offset *int64 + filter *string + sort *string +} + +// The number of environments to return in the response. Defaults to 20. +func (r ApiGetEnvironmentsByProjectRequest) Limit(limit int64) ApiGetEnvironmentsByProjectRequest { + r.limit = &limit + return r +} + +// Where to start in the list. This is for use with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetEnvironmentsByProjectRequest) Offset(offset int64) ApiGetEnvironmentsByProjectRequest { + r.offset = &offset + return r +} + +// A comma-separated list of filters. Each filter is of the form `field:value`. +func (r ApiGetEnvironmentsByProjectRequest) Filter(filter string) ApiGetEnvironmentsByProjectRequest { + r.filter = &filter + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order. +func (r ApiGetEnvironmentsByProjectRequest) Sort(sort string) ApiGetEnvironmentsByProjectRequest { + r.sort = &sort + return r +} + +func (r ApiGetEnvironmentsByProjectRequest) Execute() (*Environments, *http.Response, error) { + return r.ApiService.GetEnvironmentsByProjectExecute(r) +} + +/* +GetEnvironmentsByProject List environments + +Return a list of environments for the specified project. + +By default, this returns the first 20 environments. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering environments + +LaunchDarkly supports two fields for filters: +- `query` is a string that matches against the environments' names and keys. It is not case sensitive. +- `tags` is a `+`-separated list of environment tags. It filters the list of environments that have all of the tags in the list. + +For example, the filter `filter=query:abc,tags:tag-1+tag-2` matches environments with the string `abc` in their name or key and also are tagged with `tag-1` and `tag-2`. The filter is not case-sensitive. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `+` in `filter=tags:tag-1+tag-2` must be encoded to `%2B`. + +### Sorting environments + +LaunchDarkly supports the following fields for sorting: + +- `createdOn` sorts by the creation date of the environment. +- `critical` sorts by whether the environments are marked as critical. +- `name` sorts by environment name. + +For example, `sort=name` sorts the response by environment name in ascending order. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetEnvironmentsByProjectRequest +*/ +func (a *EnvironmentsApiService) GetEnvironmentsByProject(ctx context.Context, projectKey string) ApiGetEnvironmentsByProjectRequest { + return ApiGetEnvironmentsByProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return Environments +func (a *EnvironmentsApiService) GetEnvironmentsByProjectExecute(r ApiGetEnvironmentsByProjectRequest) (*Environments, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environments + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.GetEnvironmentsByProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchEnvironmentRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchEnvironmentRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchEnvironmentRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchEnvironmentRequest) Execute() (*Environment, *http.Response, error) { + return r.ApiService.PatchEnvironmentExecute(r) +} + +/* +PatchEnvironment Update environment + + +Update an environment. Updating an environment uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +To update fields in the environment object that are arrays, set the `path` to the name of the field and then append `/`. Using `/0` appends to the beginning of the array. + +### Approval settings + +This request only returns the `approvalSettings` key if the [approvals](https://launchdarkly.com/docs/home/releases/approvals/) feature is enabled. + +Only the `canReviewOwnRequest`, `canApplyDeclinedChanges`, `minNumApprovals`, `required` and `requiredApprovalTagsfields` are editable. + +If you try to patch the environment by setting both `required` and `requiredApprovalTags`, the request fails and an error appears. You can specify either required approvals for all flags in an environment or those with specific tags, but not both. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPatchEnvironmentRequest +*/ +func (a *EnvironmentsApiService) PatchEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiPatchEnvironmentRequest { + return ApiPatchEnvironmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Environment +func (a *EnvironmentsApiService) PatchEnvironmentExecute(r ApiPatchEnvironmentRequest) (*Environment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.PatchEnvironment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostEnvironmentRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentPost *EnvironmentPost +} + +func (r ApiPostEnvironmentRequest) EnvironmentPost(environmentPost EnvironmentPost) ApiPostEnvironmentRequest { + r.environmentPost = &environmentPost + return r +} + +func (r ApiPostEnvironmentRequest) Execute() (*Environment, *http.Response, error) { + return r.ApiService.PostEnvironmentExecute(r) +} + +/* +PostEnvironment Create environment + +> ### Approval settings +> +> The `approvalSettings` key is only returned when the [approvals](https://launchdarkly.com/docs/home/releases/approvals/) feature is enabled. +> +> You cannot update approval settings when creating new environments. Update approval settings with the [https://launchdarkly.com/docs/api/environments/patch-environment). + +Create a new environment in a specified project with a given name, key, swatch color, and default TTL. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostEnvironmentRequest +*/ +func (a *EnvironmentsApiService) PostEnvironment(ctx context.Context, projectKey string) ApiPostEnvironmentRequest { + return ApiPostEnvironmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return Environment +func (a *EnvironmentsApiService) PostEnvironmentExecute(r ApiPostEnvironmentRequest) (*Environment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.PostEnvironment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.environmentPost == nil { + return localVarReturnValue, nil, reportError("environmentPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.environmentPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiResetEnvironmentMobileKeyRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentKey string +} + +func (r ApiResetEnvironmentMobileKeyRequest) Execute() (*Environment, *http.Response, error) { + return r.ApiService.ResetEnvironmentMobileKeyExecute(r) +} + +/* +ResetEnvironmentMobileKey Reset environment mobile SDK key + +Reset an environment's mobile key. The optional expiry for the old key is deprecated for this endpoint, so the old key will always expire immediately. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiResetEnvironmentMobileKeyRequest +*/ +func (a *EnvironmentsApiService) ResetEnvironmentMobileKey(ctx context.Context, projectKey string, environmentKey string) ApiResetEnvironmentMobileKeyRequest { + return ApiResetEnvironmentMobileKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Environment +func (a *EnvironmentsApiService) ResetEnvironmentMobileKeyExecute(r ApiResetEnvironmentMobileKeyRequest) (*Environment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.ResetEnvironmentMobileKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/mobileKey" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiResetEnvironmentSDKKeyRequest struct { + ctx context.Context + ApiService EnvironmentsApi + projectKey string + environmentKey string + expiry *int64 +} + +// The time at which you want the old SDK key to expire, in UNIX milliseconds. By default, the key expires immediately. During the period between this call and the time when the old SDK key expires, both the old SDK key and the new SDK key will work. +func (r ApiResetEnvironmentSDKKeyRequest) Expiry(expiry int64) ApiResetEnvironmentSDKKeyRequest { + r.expiry = &expiry + return r +} + +func (r ApiResetEnvironmentSDKKeyRequest) Execute() (*Environment, *http.Response, error) { + return r.ApiService.ResetEnvironmentSDKKeyExecute(r) +} + +/* +ResetEnvironmentSDKKey Reset environment SDK key + +Reset an environment's SDK key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiResetEnvironmentSDKKeyRequest +*/ +func (a *EnvironmentsApiService) ResetEnvironmentSDKKey(ctx context.Context, projectKey string, environmentKey string) ApiResetEnvironmentSDKKeyRequest { + return ApiResetEnvironmentSDKKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Environment +func (a *EnvironmentsApiService) ResetEnvironmentSDKKeyExecute(r ApiResetEnvironmentSDKKeyRequest) (*Environment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Environment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "EnvironmentsApiService.ResetEnvironmentSDKKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/apiKey" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expiry != nil { + localVarQueryParams.Add("expiry", parameterToString(*r.expiry, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_experiments.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_experiments.go new file mode 100644 index 00000000..23945538 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_experiments.go @@ -0,0 +1,2265 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ExperimentsApi interface { + + /* + CreateExperiment Create experiment + + Create an experiment. + +To run this experiment, you'll need to [create an iteration](https://launchdarkly.com/docs/ld-docs/api/experiments/create-iteration) and then [update the experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/patch-experiment) with the `startIteration` instruction. + +To learn more, read [Creating experiments](https://launchdarkly.com/docs/home/experimentation/create). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiCreateExperimentRequest + */ + CreateExperiment(ctx context.Context, projectKey string, environmentKey string) ApiCreateExperimentRequest + + // CreateExperimentExecute executes the request + // @return Experiment + CreateExperimentExecute(r ApiCreateExperimentRequest) (*Experiment, *http.Response, error) + + /* + CreateIteration Create iteration + + Create an experiment iteration. + +Experiment iterations let you record experiments in individual blocks of time. Initially, iterations are created with a status of `not_started` and appear in the `draftIteration` field of an experiment. To start or stop an iteration, [update the experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/patch-experiment) with the `startIteration` or `stopIteration` instruction. + +To learn more, read [Start experiment iterations](https://launchdarkly.com/docs/home/experimentation/feature#start-experiment-iterations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiCreateIterationRequest + */ + CreateIteration(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiCreateIterationRequest + + // CreateIterationExecute executes the request + // @return IterationRep + CreateIterationExecute(r ApiCreateIterationRequest) (*IterationRep, *http.Response, error) + + /* + GetExperiment Get experiment + + Get details about an experiment. + +### Expanding the experiment response + +LaunchDarkly supports four fields for expanding the "Get experiment" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `previousIterations` includes all iterations prior to the current iteration. By default only the current iteration is included in the response. +- `draftIteration` includes the iteration which has not been started yet, if any. +- `secondaryMetrics` includes secondary metrics. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details. By default treatment data is not included in the response. + +For example, `expand=draftIteration,treatments` includes the `draftIteration` and `treatments` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiGetExperimentRequest + */ + GetExperiment(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiGetExperimentRequest + + // GetExperimentExecute executes the request + // @return Experiment + GetExperimentExecute(r ApiGetExperimentRequest) (*Experiment, *http.Response, error) + + /* + GetExperimentResults Get experiment results (Deprecated) + + Get results from an experiment for a particular metric. + +LaunchDarkly supports one field for expanding the "Get experiment results" response. By default, this field is **not** included in the response. + +To expand the response, append the `expand` query parameter with the following field: +* `traffic` includes the total count of units for each treatment. + +For example, `expand=traffic` includes the `traffic` field for the project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @param metricKey The metric key + @return ApiGetExperimentResultsRequest + + Deprecated + */ + GetExperimentResults(ctx context.Context, projectKey string, environmentKey string, experimentKey string, metricKey string) ApiGetExperimentResultsRequest + + // GetExperimentResultsExecute executes the request + // @return ExperimentBayesianResultsRep + // Deprecated + GetExperimentResultsExecute(r ApiGetExperimentResultsRequest) (*ExperimentBayesianResultsRep, *http.Response, error) + + /* + GetExperimentResultsForMetricGroup Get experiment results for metric group (Deprecated) + + Get results from an experiment for a particular metric group. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @param metricGroupKey The metric group key + @return ApiGetExperimentResultsForMetricGroupRequest + + Deprecated + */ + GetExperimentResultsForMetricGroup(ctx context.Context, projectKey string, environmentKey string, experimentKey string, metricGroupKey string) ApiGetExperimentResultsForMetricGroupRequest + + // GetExperimentResultsForMetricGroupExecute executes the request + // @return MetricGroupResultsRep + // Deprecated + GetExperimentResultsForMetricGroupExecute(r ApiGetExperimentResultsForMetricGroupRequest) (*MetricGroupResultsRep, *http.Response, error) + + /* + GetExperimentationSettings Get experimentation settings + + Get current experimentation settings for the given project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetExperimentationSettingsRequest + */ + GetExperimentationSettings(ctx context.Context, projectKey string) ApiGetExperimentationSettingsRequest + + // GetExperimentationSettingsExecute executes the request + // @return RandomizationSettingsRep + GetExperimentationSettingsExecute(r ApiGetExperimentationSettingsRequest) (*RandomizationSettingsRep, *http.Response, error) + + /* + GetExperiments Get experiments + + Get details about all experiments in an environment. + +### Filtering experiments + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `flagKey` filters for only experiments that use the flag with the given key. +- `metricKey` filters for only experiments that use the metric with the given key. +- `status` filters for only experiments with an iteration with the given status. An iteration can have the status `not_started`, `running` or `stopped`. + +For example, `filter=flagKey:my-flag,status:running,metricKey:page-load-ms` filters for experiments for the given flag key and the given metric key which have a currently running iteration. + +### Expanding the experiments response + +LaunchDarkly supports four fields for expanding the "Get experiments" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `previousIterations` includes all iterations prior to the current iteration. By default only the current iteration is included in the response. +- `draftIteration` includes the iteration which has not been started yet, if any. +- `secondaryMetrics` includes secondary metrics. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details. By default treatment data is not included in the response. + +For example, `expand=draftIteration,treatments` includes the `draftIteration` and `treatments` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetExperimentsRequest + */ + GetExperiments(ctx context.Context, projectKey string, environmentKey string) ApiGetExperimentsRequest + + // GetExperimentsExecute executes the request + // @return ExperimentCollectionRep + GetExperimentsExecute(r ApiGetExperimentsRequest) (*ExperimentCollectionRep, *http.Response, error) + + /* + PatchExperiment Patch experiment + + Update an experiment. Updating an experiment uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating experiments. + +#### updateName + +Updates the experiment name. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Example updated experiment name" + }] +} +``` + +#### updateDescription + +Updates the experiment description. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "value": "Example updated description" + }] +} +``` + +#### startIteration + +Starts a new iteration for this experiment. You must [create a new iteration](https://launchdarkly.com/docs/ld-docs/api/experiments/create-iteration) before calling this instruction. + +An iteration may not be started until it meets the following criteria: + +* Its associated flag is toggled on and is not archived +* Its `randomizationUnit` is set +* At least one of its `treatments` has a non-zero `allocationPercent` + +##### Parameters + +- `changeJustification`: The reason for starting a new iteration. Required when you call `startIteration` on an already running experiment, otherwise optional. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "startIteration", + "changeJustification": "It's time to start a new iteration" + }] +} +``` + +#### stopIteration + +Stops the current iteration for this experiment. + +##### Parameters + +- `winningTreatmentId`: The ID of the winning treatment. Treatment IDs are returned as part of the [Get experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/get-experiment) response. They are the `_id` of each element in the `treatments` array. +- `winningReason`: The reason for the winner + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "stopIteration", + "winningTreatmentId": "3a548ec2-72ac-4e59-8518-5c24f5609ccf", + "winningReason": "Example reason to stop the iteration" + }] +} +``` + +#### archiveExperiment + +Archives this experiment. Archived experiments are hidden by default in the LaunchDarkly user interface. You cannot start new iterations for archived experiments. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "archiveExperiment" }] +} +``` + +#### restoreExperiment + +Restores an archived experiment. After restoring an experiment, you can start new iterations for it again. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "restoreExperiment" }] +} +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiPatchExperimentRequest + */ + PatchExperiment(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiPatchExperimentRequest + + // PatchExperimentExecute executes the request + // @return Experiment + PatchExperimentExecute(r ApiPatchExperimentRequest) (*Experiment, *http.Response, error) + + /* + PutExperimentationSettings Update experimentation settings + + Update experimentation settings for the given project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPutExperimentationSettingsRequest + */ + PutExperimentationSettings(ctx context.Context, projectKey string) ApiPutExperimentationSettingsRequest + + // PutExperimentationSettingsExecute executes the request + // @return RandomizationSettingsRep + PutExperimentationSettingsExecute(r ApiPutExperimentationSettingsRequest) (*RandomizationSettingsRep, *http.Response, error) +} + +// ExperimentsApiService ExperimentsApi service +type ExperimentsApiService service + +type ApiCreateExperimentRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentPost *ExperimentPost +} + +func (r ApiCreateExperimentRequest) ExperimentPost(experimentPost ExperimentPost) ApiCreateExperimentRequest { + r.experimentPost = &experimentPost + return r +} + +func (r ApiCreateExperimentRequest) Execute() (*Experiment, *http.Response, error) { + return r.ApiService.CreateExperimentExecute(r) +} + +/* +CreateExperiment Create experiment + +Create an experiment. + +To run this experiment, you'll need to [create an iteration](https://launchdarkly.com/docs/ld-docs/api/experiments/create-iteration) and then [update the experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/patch-experiment) with the `startIteration` instruction. + +To learn more, read [Creating experiments](https://launchdarkly.com/docs/home/experimentation/create). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiCreateExperimentRequest +*/ +func (a *ExperimentsApiService) CreateExperiment(ctx context.Context, projectKey string, environmentKey string) ApiCreateExperimentRequest { + return ApiCreateExperimentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Experiment +func (a *ExperimentsApiService) CreateExperimentExecute(r ApiCreateExperimentRequest) (*Experiment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Experiment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.CreateExperiment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.experimentPost == nil { + return localVarReturnValue, nil, reportError("experimentPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.experimentPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiCreateIterationRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentKey string + iterationInput *IterationInput +} + +func (r ApiCreateIterationRequest) IterationInput(iterationInput IterationInput) ApiCreateIterationRequest { + r.iterationInput = &iterationInput + return r +} + +func (r ApiCreateIterationRequest) Execute() (*IterationRep, *http.Response, error) { + return r.ApiService.CreateIterationExecute(r) +} + +/* +CreateIteration Create iteration + +Create an experiment iteration. + +Experiment iterations let you record experiments in individual blocks of time. Initially, iterations are created with a status of `not_started` and appear in the `draftIteration` field of an experiment. To start or stop an iteration, [update the experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/patch-experiment) with the `startIteration` or `stopIteration` instruction. + +To learn more, read [Start experiment iterations](https://launchdarkly.com/docs/home/experimentation/feature#start-experiment-iterations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiCreateIterationRequest +*/ +func (a *ExperimentsApiService) CreateIteration(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiCreateIterationRequest { + return ApiCreateIterationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + experimentKey: experimentKey, + } +} + +// Execute executes the request +// @return IterationRep +func (a *ExperimentsApiService) CreateIterationExecute(r ApiCreateIterationRequest) (*IterationRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IterationRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.CreateIteration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/iterations" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"experimentKey"+"}", url.PathEscape(parameterToString(r.experimentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.iterationInput == nil { + return localVarReturnValue, nil, reportError("iterationInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.iterationInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. Supported fields are explained above. +func (r ApiGetExperimentRequest) Expand(expand string) ApiGetExperimentRequest { + r.expand = &expand + return r +} + +func (r ApiGetExperimentRequest) Execute() (*Experiment, *http.Response, error) { + return r.ApiService.GetExperimentExecute(r) +} + +/* +GetExperiment Get experiment + +Get details about an experiment. + +### Expanding the experiment response + +LaunchDarkly supports four fields for expanding the "Get experiment" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `previousIterations` includes all iterations prior to the current iteration. By default only the current iteration is included in the response. +- `draftIteration` includes the iteration which has not been started yet, if any. +- `secondaryMetrics` includes secondary metrics. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details. By default treatment data is not included in the response. + +For example, `expand=draftIteration,treatments` includes the `draftIteration` and `treatments` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiGetExperimentRequest +*/ +func (a *ExperimentsApiService) GetExperiment(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiGetExperimentRequest { + return ApiGetExperimentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + experimentKey: experimentKey, + } +} + +// Execute executes the request +// @return Experiment +func (a *ExperimentsApiService) GetExperimentExecute(r ApiGetExperimentRequest) (*Experiment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Experiment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.GetExperiment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"experimentKey"+"}", url.PathEscape(parameterToString(r.experimentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentResultsRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentKey string + metricKey string + iterationId *string + expand *string +} + +// The iteration ID +func (r ApiGetExperimentResultsRequest) IterationId(iterationId string) ApiGetExperimentResultsRequest { + r.iterationId = &iterationId + return r +} + +// A comma-separated list of fields to expand in the response. Supported fields are explained above. +func (r ApiGetExperimentResultsRequest) Expand(expand string) ApiGetExperimentResultsRequest { + r.expand = &expand + return r +} + +func (r ApiGetExperimentResultsRequest) Execute() (*ExperimentBayesianResultsRep, *http.Response, error) { + return r.ApiService.GetExperimentResultsExecute(r) +} + +/* +GetExperimentResults Get experiment results (Deprecated) + +Get results from an experiment for a particular metric. + +LaunchDarkly supports one field for expanding the "Get experiment results" response. By default, this field is **not** included in the response. + +To expand the response, append the `expand` query parameter with the following field: +* `traffic` includes the total count of units for each treatment. + +For example, `expand=traffic` includes the `traffic` field for the project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @param metricKey The metric key + @return ApiGetExperimentResultsRequest + +Deprecated +*/ +func (a *ExperimentsApiService) GetExperimentResults(ctx context.Context, projectKey string, environmentKey string, experimentKey string, metricKey string) ApiGetExperimentResultsRequest { + return ApiGetExperimentResultsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + experimentKey: experimentKey, + metricKey: metricKey, + } +} + +// Execute executes the request +// @return ExperimentBayesianResultsRep +// Deprecated +func (a *ExperimentsApiService) GetExperimentResultsExecute(r ApiGetExperimentResultsRequest) (*ExperimentBayesianResultsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExperimentBayesianResultsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.GetExperimentResults") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/metrics/{metricKey}/results" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"experimentKey"+"}", url.PathEscape(parameterToString(r.experimentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricKey"+"}", url.PathEscape(parameterToString(r.metricKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.iterationId != nil { + localVarQueryParams.Add("iterationId", parameterToString(*r.iterationId, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentResultsForMetricGroupRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentKey string + metricGroupKey string + iterationId *string +} + +// The iteration ID +func (r ApiGetExperimentResultsForMetricGroupRequest) IterationId(iterationId string) ApiGetExperimentResultsForMetricGroupRequest { + r.iterationId = &iterationId + return r +} + +func (r ApiGetExperimentResultsForMetricGroupRequest) Execute() (*MetricGroupResultsRep, *http.Response, error) { + return r.ApiService.GetExperimentResultsForMetricGroupExecute(r) +} + +/* +GetExperimentResultsForMetricGroup Get experiment results for metric group (Deprecated) + +Get results from an experiment for a particular metric group. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @param metricGroupKey The metric group key + @return ApiGetExperimentResultsForMetricGroupRequest + +Deprecated +*/ +func (a *ExperimentsApiService) GetExperimentResultsForMetricGroup(ctx context.Context, projectKey string, environmentKey string, experimentKey string, metricGroupKey string) ApiGetExperimentResultsForMetricGroupRequest { + return ApiGetExperimentResultsForMetricGroupRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + experimentKey: experimentKey, + metricGroupKey: metricGroupKey, + } +} + +// Execute executes the request +// @return MetricGroupResultsRep +// Deprecated +func (a *ExperimentsApiService) GetExperimentResultsForMetricGroupExecute(r ApiGetExperimentResultsForMetricGroupRequest) (*MetricGroupResultsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricGroupResultsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.GetExperimentResultsForMetricGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}/metric-groups/{metricGroupKey}/results" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"experimentKey"+"}", url.PathEscape(parameterToString(r.experimentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricGroupKey"+"}", url.PathEscape(parameterToString(r.metricGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.iterationId != nil { + localVarQueryParams.Add("iterationId", parameterToString(*r.iterationId, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentationSettingsRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string +} + +func (r ApiGetExperimentationSettingsRequest) Execute() (*RandomizationSettingsRep, *http.Response, error) { + return r.ApiService.GetExperimentationSettingsExecute(r) +} + +/* +GetExperimentationSettings Get experimentation settings + +Get current experimentation settings for the given project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetExperimentationSettingsRequest +*/ +func (a *ExperimentsApiService) GetExperimentationSettings(ctx context.Context, projectKey string) ApiGetExperimentationSettingsRequest { + return ApiGetExperimentationSettingsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return RandomizationSettingsRep +func (a *ExperimentsApiService) GetExperimentationSettingsExecute(r ApiGetExperimentationSettingsRequest) (*RandomizationSettingsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RandomizationSettingsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.GetExperimentationSettings") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/experimentation-settings" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExperimentsRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + limit *int64 + offset *int64 + filter *string + expand *string + lifecycleState *string +} + +// The maximum number of experiments to return. Defaults to 20. +func (r ApiGetExperimentsRequest) Limit(limit int64) ApiGetExperimentsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetExperimentsRequest) Offset(offset int64) ApiGetExperimentsRequest { + r.offset = &offset + return r +} + +// A comma-separated list of filters. Each filter is of the form `field:value`. Supported fields are explained above. +func (r ApiGetExperimentsRequest) Filter(filter string) ApiGetExperimentsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. Supported fields are explained above. +func (r ApiGetExperimentsRequest) Expand(expand string) ApiGetExperimentsRequest { + r.expand = &expand + return r +} + +// A comma-separated list of experiment archived states. Supports `archived`, `active`, or both. Defaults to `active` experiments. +func (r ApiGetExperimentsRequest) LifecycleState(lifecycleState string) ApiGetExperimentsRequest { + r.lifecycleState = &lifecycleState + return r +} + +func (r ApiGetExperimentsRequest) Execute() (*ExperimentCollectionRep, *http.Response, error) { + return r.ApiService.GetExperimentsExecute(r) +} + +/* +GetExperiments Get experiments + +Get details about all experiments in an environment. + +### Filtering experiments + +LaunchDarkly supports the `filter` query param for filtering, with the following fields: + +- `flagKey` filters for only experiments that use the flag with the given key. +- `metricKey` filters for only experiments that use the metric with the given key. +- `status` filters for only experiments with an iteration with the given status. An iteration can have the status `not_started`, `running` or `stopped`. + +For example, `filter=flagKey:my-flag,status:running,metricKey:page-load-ms` filters for experiments for the given flag key and the given metric key which have a currently running iteration. + +### Expanding the experiments response + +LaunchDarkly supports four fields for expanding the "Get experiments" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `previousIterations` includes all iterations prior to the current iteration. By default only the current iteration is included in the response. +- `draftIteration` includes the iteration which has not been started yet, if any. +- `secondaryMetrics` includes secondary metrics. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details. By default treatment data is not included in the response. + +For example, `expand=draftIteration,treatments` includes the `draftIteration` and `treatments` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetExperimentsRequest +*/ +func (a *ExperimentsApiService) GetExperiments(ctx context.Context, projectKey string, environmentKey string) ApiGetExperimentsRequest { + return ApiGetExperimentsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ExperimentCollectionRep +func (a *ExperimentsApiService) GetExperimentsExecute(r ApiGetExperimentsRequest) (*ExperimentCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExperimentCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.GetExperiments") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.lifecycleState != nil { + localVarQueryParams.Add("lifecycleState", parameterToString(*r.lifecycleState, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExperimentRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + environmentKey string + experimentKey string + experimentPatchInput *ExperimentPatchInput +} + +func (r ApiPatchExperimentRequest) ExperimentPatchInput(experimentPatchInput ExperimentPatchInput) ApiPatchExperimentRequest { + r.experimentPatchInput = &experimentPatchInput + return r +} + +func (r ApiPatchExperimentRequest) Execute() (*Experiment, *http.Response, error) { + return r.ApiService.PatchExperimentExecute(r) +} + +/* +PatchExperiment Patch experiment + +Update an experiment. Updating an experiment uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating experiments. + +#### updateName + +Updates the experiment name. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Example updated experiment name" + }] +} +``` + +#### updateDescription + +Updates the experiment description. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "value": "Example updated description" + }] +} +``` + +#### startIteration + +Starts a new iteration for this experiment. You must [create a new iteration](https://launchdarkly.com/docs/ld-docs/api/experiments/create-iteration) before calling this instruction. + +An iteration may not be started until it meets the following criteria: + +* Its associated flag is toggled on and is not archived +* Its `randomizationUnit` is set +* At least one of its `treatments` has a non-zero `allocationPercent` + +##### Parameters + +- `changeJustification`: The reason for starting a new iteration. Required when you call `startIteration` on an already running experiment, otherwise optional. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "startIteration", + "changeJustification": "It's time to start a new iteration" + }] +} +``` + +#### stopIteration + +Stops the current iteration for this experiment. + +##### Parameters + +- `winningTreatmentId`: The ID of the winning treatment. Treatment IDs are returned as part of the [Get experiment](https://launchdarkly.com/docs/ld-docs/api/experiments/get-experiment) response. They are the `_id` of each element in the `treatments` array. +- `winningReason`: The reason for the winner + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "stopIteration", + "winningTreatmentId": "3a548ec2-72ac-4e59-8518-5c24f5609ccf", + "winningReason": "Example reason to stop the iteration" + }] +} +``` + +#### archiveExperiment + +Archives this experiment. Archived experiments are hidden by default in the LaunchDarkly user interface. You cannot start new iterations for archived experiments. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "archiveExperiment" }] +} +``` + +#### restoreExperiment + +Restores an archived experiment. After restoring an experiment, you can start new iterations for it again. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "restoreExperiment" }] +} +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param experimentKey The experiment key + @return ApiPatchExperimentRequest +*/ +func (a *ExperimentsApiService) PatchExperiment(ctx context.Context, projectKey string, environmentKey string, experimentKey string) ApiPatchExperimentRequest { + return ApiPatchExperimentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + experimentKey: experimentKey, + } +} + +// Execute executes the request +// @return Experiment +func (a *ExperimentsApiService) PatchExperimentExecute(r ApiPatchExperimentRequest) (*Experiment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Experiment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.PatchExperiment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/experiments/{experimentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"experimentKey"+"}", url.PathEscape(parameterToString(r.experimentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.experimentPatchInput == nil { + return localVarReturnValue, nil, reportError("experimentPatchInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.experimentPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutExperimentationSettingsRequest struct { + ctx context.Context + ApiService ExperimentsApi + projectKey string + randomizationSettingsPut *RandomizationSettingsPut +} + +func (r ApiPutExperimentationSettingsRequest) RandomizationSettingsPut(randomizationSettingsPut RandomizationSettingsPut) ApiPutExperimentationSettingsRequest { + r.randomizationSettingsPut = &randomizationSettingsPut + return r +} + +func (r ApiPutExperimentationSettingsRequest) Execute() (*RandomizationSettingsRep, *http.Response, error) { + return r.ApiService.PutExperimentationSettingsExecute(r) +} + +/* +PutExperimentationSettings Update experimentation settings + +Update experimentation settings for the given project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPutExperimentationSettingsRequest +*/ +func (a *ExperimentsApiService) PutExperimentationSettings(ctx context.Context, projectKey string) ApiPutExperimentationSettingsRequest { + return ApiPutExperimentationSettingsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return RandomizationSettingsRep +func (a *ExperimentsApiService) PutExperimentationSettingsExecute(r ApiPutExperimentationSettingsRequest) (*RandomizationSettingsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RandomizationSettingsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ExperimentsApiService.PutExperimentationSettings") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/experimentation-settings" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.randomizationSettingsPut == nil { + return localVarReturnValue, nil, reportError("randomizationSettingsPut is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.randomizationSettingsPut + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags.go new file mode 100644 index 00000000..a9a56340 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags.go @@ -0,0 +1,5704 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FeatureFlagsApi interface { + + /* + CopyFeatureFlag Copy feature flag + + +> ### Copying flag settings is an Enterprise feature +> +> Copying flag settings is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +Copy flag settings from a source environment to a target environment. + +By default, this operation copies the entire flag configuration. You can use the `includedActions` or `excludedActions` to specify that only part of the flag configuration is copied. + +If you provide the optional `currentVersion` of a flag, this operation tests to ensure that the current flag version in the environment matches the version you've specified. The operation rejects attempts to copy flag settings if the environment's current version of the flag does not match the version you've specified. You can use this to enforce optimistic locking on copy attempts. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiCopyFeatureFlagRequest + */ + CopyFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiCopyFeatureFlagRequest + + // CopyFeatureFlagExecute executes the request + // @return FeatureFlag + CopyFeatureFlagExecute(r ApiCopyFeatureFlagRequest) (*FeatureFlag, *http.Response, error) + + /* + DeleteFeatureFlag Delete feature flag + + Delete a feature flag in all environments. Use with caution: only delete feature flags your application no longer uses. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiDeleteFeatureFlagRequest + */ + DeleteFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiDeleteFeatureFlagRequest + + // DeleteFeatureFlagExecute executes the request + DeleteFeatureFlagExecute(r ApiDeleteFeatureFlagRequest) (*http.Response, error) + + /* + GetExpiringContextTargets Get expiring context targets for feature flag + + Get a list of context targets on a feature flag that are scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetExpiringContextTargetsRequest + */ + GetExpiringContextTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetExpiringContextTargetsRequest + + // GetExpiringContextTargetsExecute executes the request + // @return ExpiringTargetGetResponse + GetExpiringContextTargetsExecute(r ApiGetExpiringContextTargetsRequest) (*ExpiringTargetGetResponse, *http.Response, error) + + /* + GetExpiringUserTargets Get expiring user targets for feature flag + + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring context targets for feature flag](https://launchdarkly.com/docs/api/feature-flags/get-expiring-context-targets) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get a list of user targets on a feature flag that are scheduled for removal. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetExpiringUserTargetsRequest + */ + GetExpiringUserTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetExpiringUserTargetsRequest + + // GetExpiringUserTargetsExecute executes the request + // @return ExpiringUserTargetGetResponse + GetExpiringUserTargetsExecute(r ApiGetExpiringUserTargetsRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) + + /* + GetFeatureFlag Get feature flag + + Get a single feature flag by key. By default, this returns the configurations for all environments. You can filter environments with the `env` query parameter. For example, setting `env=production` restricts the returned configurations to just the `production` environment. + +> #### Recommended use +> +> This endpoint can return a large amount of information. Specifying one or multiple environments with the `env` parameter can decrease response time and overall payload size. We recommend using this parameter to return only the environments relevant to your query. + +### Expanding response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `evaluation` includes evaluation information within returned environments, including which context kinds the flag has been evaluated for in the past 30 days +- `migrationSettings` includes migration settings information within the flag and within returned environments. These settings are only included for migration flags, that is, where `purpose` is `migration`. + +For example, `expand=evaluation` includes the `evaluation` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagRequest + */ + GetFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFeatureFlagRequest + + // GetFeatureFlagExecute executes the request + // @return FeatureFlag + GetFeatureFlagExecute(r ApiGetFeatureFlagRequest) (*FeatureFlag, *http.Response, error) + + /* + GetFeatureFlagStatus Get feature flag status + + Get the status for a particular feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagStatusRequest + */ + GetFeatureFlagStatus(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetFeatureFlagStatusRequest + + // GetFeatureFlagStatusExecute executes the request + // @return FlagStatusRep + GetFeatureFlagStatusExecute(r ApiGetFeatureFlagStatusRequest) (*FlagStatusRep, *http.Response, error) + + /* + GetFeatureFlagStatusAcrossEnvironments Get flag status across environments + + Get the status for a particular feature flag across environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagStatusAcrossEnvironmentsRequest + */ + GetFeatureFlagStatusAcrossEnvironments(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFeatureFlagStatusAcrossEnvironmentsRequest + + // GetFeatureFlagStatusAcrossEnvironmentsExecute executes the request + // @return FeatureFlagStatusAcrossEnvironments + GetFeatureFlagStatusAcrossEnvironmentsExecute(r ApiGetFeatureFlagStatusAcrossEnvironmentsRequest) (*FeatureFlagStatusAcrossEnvironments, *http.Response, error) + + /* + GetFeatureFlagStatuses List feature flag statuses + + Get a list of statuses for all feature flags. The status includes the last time the feature flag was requested, as well as a state, which is one of the following: + +- `new`: You created the flag fewer than seven days ago and it has never been requested. +- `active`: LaunchDarkly is receiving requests for this flag, but there are either multiple variations configured, or it is toggled off, or there have been changes to configuration in the past seven days. +- `inactive`: You created the feature flag more than seven days ago, and hasn't been requested within the past seven days. +- `launched`: LaunchDarkly is receiving requests for this flag, it is toggled on, there is only one variation configured, and there have been no changes to configuration in the past seven days. + +To learn more, read [Flag statuses](https://launchdarkly.com/docs/home/observability/flag-status). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetFeatureFlagStatusesRequest + */ + GetFeatureFlagStatuses(ctx context.Context, projectKey string, environmentKey string) ApiGetFeatureFlagStatusesRequest + + // GetFeatureFlagStatusesExecute executes the request + // @return FeatureFlagStatuses + GetFeatureFlagStatusesExecute(r ApiGetFeatureFlagStatusesRequest) (*FeatureFlagStatuses, *http.Response, error) + + /* + GetFeatureFlags List feature flags + + Get a list of all feature flags in the given project. You can include information specific to different environments by adding `env` query parameter. For example, setting `env=production` adds configuration details about your production environment to the response. You can also filter feature flags by tag with the `tag` query parameter. + +> #### Recommended use +> +> This endpoint can return a large amount of information. We recommend using some or all of these query parameters to decrease response time and overall payload size: `limit`, `env`, `query`, and `filter=creationDate`. + +### Filtering flags + +You can filter on certain fields using the `filter` query parameter. For example, setting `filter=query:dark-mode,tags:beta+test` matches flags with the string `dark-mode` in their key or name, ignoring case, which also have the tags `beta` and `test`. + +The `filter` query parameter supports the following arguments: + +| Filter argument | Description | Example | +|-----------------------|-------------|----------------------| +| `applicationEvaluated` | A string. It filters the list to flags that are evaluated in the application with the given key. | `filter=applicationEvaluated:com.launchdarkly.cafe` | +| `archived` | (deprecated) A boolean value. It filters the list to archived flags. | Use `filter=state:archived` instead | +| `contextKindsEvaluated` | A `+`-separated list of context kind keys. It filters the list to flags which have been evaluated in the past 30 days for all of the context kinds in the list. | `filter=contextKindsEvaluated:user+application` | +| `codeReferences.max` | An integer value. Use `0` to return flags that do not have code references. | `filter=codeReferences.max:0` | +| `codeReferences.min` | An integer value. Use `1` to return flags that do have code references. | `filter=codeReferences.min:1` | +| `creationDate` | An object with an optional `before` field whose value is Unix time in milliseconds. It filters the list to flags created before the date. | `filter=creationDate:{"before":1690527600000}` | +| `evaluated` | An object that contains a key of `after` and a value in Unix time in milliseconds. It filters the list to all flags that have been evaluated since the time you specify, in the environment provided. This filter requires the `filterEnv` filter. | `filter=evaluated:{"after":1690527600000},filterEnv:production` | +| `filterEnv` | A valid environment key. You must use this field for filters that are environment-specific. If there are multiple environment-specific filters, you only need to include this field once. | `filter=evaluated:{"after": 1590768455282},filterEnv:production` | +| `hasExperiment` | A boolean value. It filters the list to flags that are used in an experiment. | `filter=hasExperiment:true` | +| `maintainerId` | A valid member ID. It filters the list to flags that are maintained by this member. | `filter=maintainerId:12ab3c45de678910abc12345` | +| `maintainerTeamKey` | A string. It filters the list to flags that are maintained by the team with this key. | `filter=maintainerTeamKey:example-team-key` | +| `query` | A string. It filters the list to flags that include the specified string in their key or name. It is not case sensitive. | `filter=query:example` | +| `releasePipeline` | A release pipeline key. It filters the list to flags that are either currently active in the release pipeline or have completed the release pipeline. | `filter=releasePipeline:default-release-pipeline` | +| `state` | A string, either `live`, `deprecated`, or `archived`. It filters the list to flags in this state. | `filter=state:archived` | +| `sdkAvailability` | A string, one of `client`, `mobile`, `anyClient`, `server`. Using `client` filters the list to flags whose client-side SDK availability is set to use the client-side ID. Using `mobile` filters to flags set to use the mobile key. Using `anyClient` filters to flags set to use either the client-side ID or the mobile key. Using `server` filters to flags set to use neither, that is, to flags only available in server-side SDKs. | `filter=sdkAvailability:client` | +| `tags` | A `+`-separated list of tags. It filters the list to flags that have all of the tags in the list. | `filter=tags:beta+test` | +| `type` | A string, either `temporary` or `permanent`. It filters the list to flags with the specified type. | `filter=type:permanent` | + +The documented values for the `filter` query are prior to URL encoding. For example, the `+` in `filter=tags:beta+test` must be encoded to `%2B`. + +By default, this endpoint returns all flags. You can page through the list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the returned `_links` field. These links will not be present if the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page. + +### Sorting flags + +You can sort flags based on the following fields: + +- `creationDate` sorts by the creation date of the flag. +- `key` sorts by the key of the flag. +- `maintainerId` sorts by the flag maintainer. +- `name` sorts by flag name. +- `tags` sorts by tags. +- `targetingModifiedDate` sorts by the date that the flag's targeting rules were last modified in a given environment. It must be used with `env` parameter and it can not be combined with any other sort. If multiple `env` values are provided, it will perform sort using the first one. For example, `sort=-targetingModifiedDate&env=production&env=staging` returns results sorted by `targetingModifiedDate` for the `production` environment. +- `type` sorts by flag type + +All fields are sorted in ascending order by default. To sort in descending order, prefix the field with a dash ( - ). For example, `sort=-name` sorts the response by flag name in descending order. + +### Expanding response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `codeReferences` includes code references for the feature flag +- `evaluation` includes evaluation information within returned environments, including which context kinds the flag has been evaluated for in the past 30 days +- `migrationSettings` includes migration settings information within the flag and within returned environments. These settings are only included for migration flags, that is, where `purpose` is `migration`. + +For example, `expand=evaluation` includes the `evaluation` field in the response. + +### Migration flags +For migration flags, the cohort information is included in the `rules` property of a flag's response, and default cohort information is included in the `fallthrough` property of a flag's response. +To learn more, read [Migration Flags](https://launchdarkly.com/docs/home/flags/migration). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetFeatureFlagsRequest + */ + GetFeatureFlags(ctx context.Context, projectKey string) ApiGetFeatureFlagsRequest + + // GetFeatureFlagsExecute executes the request + // @return FeatureFlags + GetFeatureFlagsExecute(r ApiGetFeatureFlagsRequest) (*FeatureFlags, *http.Response, error) + + /* + PatchExpiringTargets Update expiring context targets on feature flag + + Schedule a context for removal from individual targeting on a feature flag. The flag must already individually target the context. + +You can add, update, or remove a scheduled removal date. You can only schedule a context for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring targets. + +
+Click to expand instructions for updating expiring targets + +#### addExpiringTarget + +Adds a date and time that LaunchDarkly will remove the context from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the context from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExpiringTarget", + "value": 1754006460000, + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +#### updateExpiringTarget + +Updates the date and time that LaunchDarkly will remove the context from the flag's individual targeting + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the context from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` +* `version`: (Optional) The version of the expiring target to update. If included, update will fail if version doesn't match current version of the expiring target. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateExpiringTarget", + "value": 1754006460000, + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +#### removeExpiringTarget + +Removes the scheduled removal of the context from the flag's individual targeting. The context will remain part of the flag's individual targeting until you explicitly remove it, or until you schedule another removal. + +##### Parameters + +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExpiringTarget", + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiPatchExpiringTargetsRequest + */ + PatchExpiringTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiPatchExpiringTargetsRequest + + // PatchExpiringTargetsExecute executes the request + // @return ExpiringTargetPatchResponse + PatchExpiringTargetsExecute(r ApiPatchExpiringTargetsRequest) (*ExpiringTargetPatchResponse, *http.Response, error) + + /* + PatchExpiringUserTargets Update expiring user targets on feature flag + + > ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Update expiring context targets on feature flag](https://launchdarkly.com/docs/api/feature-flags/patch-expiring-targets) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Schedule a target for removal from individual targeting on a feature flag. The flag must already serve a variation to specific targets based on their key. + +You can add, update, or remove a scheduled removal date. You can only schedule a target for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Adds a date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting + +#### updateExpireUserTargetDate + +Updates the date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting +* `version`: (Optional) The version of the expiring user target to update. If included, update will fail if version doesn't match current version of the expiring user target. + +#### removeExpireUserTargetDate + +Removes the scheduled removal of the user from the flag's individual targeting. The user will remain part of the flag's individual targeting until you explicitly remove them, or until you schedule another removal. + +##### Parameters + +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiPatchExpiringUserTargetsRequest + */ + PatchExpiringUserTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiPatchExpiringUserTargetsRequest + + // PatchExpiringUserTargetsExecute executes the request + // @return ExpiringUserTargetPatchResponse + PatchExpiringUserTargetsExecute(r ApiPatchExpiringUserTargetsRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) + + /* + PatchFeatureFlag Update feature flag + + Perform a partial update to a feature flag. The request body must be a valid semantic patch, JSON patch, or JSON merge patch. To learn more the different formats, read [Updates](https://launchdarkly.com/docs/api#updates). + +### Using semantic patches on a feature flag + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +The body of a semantic patch request for updating feature flags takes the following properties: + +* `comment` (string): (Optional) A description of the update. +* `environmentKey` (string): (Required for some instructions only) The key of the LaunchDarkly environment. +* `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the action requires parameters, you must include those parameters as additional fields in the object. The body of a single semantic patch can contain many different instructions. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating feature flags. + +
+Click to expand instructions for turning flags on and off + +These instructions require the `environmentKey` parameter. + +#### turnFlagOff + +Sets the flag's targeting state to **Off**. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "turnFlagOff" } ] +} +``` + +#### turnFlagOn + +Sets the flag's targeting state to **On**. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "turnFlagOn" } ] +} +``` + +

+ +
+Click to expand instructions for working with targeting and variations + +These instructions require the `environmentKey` parameter. + +Several of the instructions for working with targeting and variations require flag rule IDs, variation IDs, or clause IDs as parameters. Each of these are returned as part of the [Get feature flag](https://launchdarkly.com/docs/api/feature-flags/get-feature-flag) response. The flag rule ID is the `_id` field of each element in the `rules` array within each environment listed in the `environments` object. The variation ID is the `_id` field in each element of the `variations` array. The clause ID is the `_id` field of each element of the `clauses` array within the `rules` array within each environment listed in the `environments` object. + +#### addClauses + +Adds the given clauses to the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauses": [{ + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["USA", "Canada"] + }] + }] +} +``` + +#### addPrerequisite + +Adds the flag indicated by `key` with variation `variationId` as a prerequisite to the flag in the path parameter. + +##### Parameters + +- `key`: Flag key of the prerequisite flag. +- `variationId`: ID of a variation of the prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addPrerequisite", + "key": "example-prereq-flag-key", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addRule + +Adds a new targeting rule to the flag. The rule may contain `clauses` and serve the variation that `variationId` indicates, or serve a percentage rollout that `rolloutWeights`, `rolloutBucketBy`, and `rolloutContextKind` indicate. + +If you set `beforeRuleId`, this adds the new rule before the indicated rule. Otherwise, adds the new rule to the end of the list. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `beforeRuleId`: (Optional) ID of a flag rule. +- Either + - `variationId`: ID of a variation of the flag. + + or + + - `rolloutWeights`: (Optional) Map of `variationId` to weight, in thousandths of a percent (0-100000). + - `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. + - `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example that uses a `variationId`: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addRule", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "clauses": [{ + "contextKind": "organization", + "attribute": "located_in", + "op": "in", + "negate": false, + "values": ["Sweden", "Norway"] + }] + }] +} +``` + +Here's an example that uses a percentage rollout: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addRule", + "clauses": [{ + "contextKind": "organization", + "attribute": "located_in", + "op": "in", + "negate": false, + "values": ["Sweden", "Norway"] + }], + "rolloutContextKind": "organization", + "rolloutWeights": { + "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation + "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000 // serve 85% this variation + } + }] +} +``` + +#### addTargets + +Adds context keys to the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Returns an error if this causes the flag to target the same context key in multiple variations. + +##### Parameters + +- `values`: List of context keys. +- `contextKind`: (Optional) Context kind to target, defaults to `user` +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addTargets", + "values": ["context-key-123abc", "context-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addUserTargets + +Adds user keys to the individual user targets for the variation that `variationId` specifies. Returns an error if this causes the flag to target the same user key in multiple variations. If you are working with contexts, use `addTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addUserTargets", + "values": ["user-key-123abc", "user-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addValuesToClause + +Adds `values` to the values of the clause that `ruleId` and `clauseId` indicate. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addValuesToClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### addVariation + +Adds a variation to the flag. + +##### Parameters + +- `value`: The variation value. +- `name`: (Optional) The variation name. +- `description`: (Optional) A description for the variation. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "addVariation", "value": 20, "name": "New variation" } ] +} +``` + +#### clearTargets + +Removes all individual targets from the variation that `variationId` specifies. This includes both user and non-user targets. + +##### Parameters + +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "clearTargets", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### clearUserTargets + +Removes all individual user targets from the variation that `variationId` specifies. If you are working with contexts, use `clearTargets` instead of this instruction. + +##### Parameters + +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "clearUserTargets", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### removeClauses + +Removes the clauses specified by `clauseIds` from the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseIds`: Array of IDs of clauses in the rule. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseIds": ["10a58772-3121-400f-846b-b8a04e8944ed", "36a461dc-235e-4b08-97b9-73ce9365873e"] + }] +} +``` + +#### removePrerequisite + +Removes the prerequisite flag indicated by `key`. Does nothing if this prerequisite does not exist. + +##### Parameters + +- `key`: Flag key of an existing prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "removePrerequisite", "key": "prereq-flag-key-123abc" } ] +} +``` + +#### removeRule + +Removes the targeting rule specified by `ruleId`. Does nothing if the rule does not exist. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "removeRule", "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" } ] +} +``` + +#### removeTargets + +Removes context keys from the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Does nothing if the flag does not target the context keys. + +##### Parameters + +- `values`: List of context keys. +- `contextKind`: (Optional) Context kind to target, defaults to `user` +- `variationId`: ID of a flag variation. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeTargets", + "values": ["context-key-123abc", "context-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### removeUserTargets + +Removes user keys from the individual user targets for the variation that `variationId` specifies. Does nothing if the flag does not target the user keys. If you are working with contexts, use `removeTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. +- `variationId`: ID of a flag variation. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeUserTargets", + "values": ["user-key-123abc", "user-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### removeValuesFromClause + +Removes `values` from the values of the clause indicated by `ruleId` and `clauseId`. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeValuesFromClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### removeVariation + +Removes a variation from the flag. + +##### Parameters + +- `variationId`: ID of a variation of the flag to remove. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### reorderRules + +Rearranges the rules to match the order given in `ruleIds`. Returns an error if `ruleIds` does not match the current set of rules on the flag. + +##### Parameters + +- `ruleIds`: Array of IDs of all rules in the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "reorderRules", + "ruleIds": ["a902ef4a-2faf-4eaf-88e1-ecc356708a29", "63c238d1-835d-435e-8f21-c8d5e40b2a3d"] + }] +} +``` + +#### replacePrerequisites + +Removes all existing prerequisites and replaces them with the list you provide. + +##### Parameters + +- `prerequisites`: A list of prerequisites. Each item in the list must include a flag `key` and `variationId`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replacePrerequisites", + "prerequisites": [ + { + "key": "prereq-flag-key-123abc", + "variationId": "10a58772-3121-400f-846b-b8a04e8944ed" + }, + { + "key": "another-prereq-flag-key-456def", + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43" + } + ] + } + ] +} +``` + +#### replaceRules + +Removes all targeting rules for the flag and replaces them with the list you provide. + +##### Parameters + +- `rules`: A list of rules. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceRules", + "rules": [ + { + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "description": "My new rule", + "clauses": [ + { + "contextKind": "user", + "attribute": "segmentMatch", + "op": "segmentMatch", + "values": ["test"] + } + ], + "trackEvents": true + } + ] + } + ] +} +``` + +#### replaceTargets + +Removes all existing targeting and replaces it with the list of targets you provide. + +##### Parameters + +- `targets`: A list of context targeting. Each item in the list includes an optional `contextKind` that defaults to `user`, a required `variationId`, and a required list of `values`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceTargets", + "targets": [ + { + "contextKind": "user", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "values": ["user-key-123abc"] + }, + { + "contextKind": "device", + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43", + "values": ["device-key-456def"] + } + ] + } + ] +} +``` + +#### replaceUserTargets + +Removes all existing user targeting and replaces it with the list of targets you provide. In the list of targets, you must include a target for each of the flag's variations. If you are working with contexts, use `replaceTargets` instead of this instruction. + +##### Parameters + +- `targets`: A list of user targeting. Each item in the list must include a `variationId` and a list of `values`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceUserTargets", + "targets": [ + { + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "values": ["user-key-123abc", "user-key-456def"] + }, + { + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43", + "values": ["user-key-789ghi"] + } + ] + } + ] +} +``` + +#### updateClause + +Replaces the clause indicated by `ruleId` and `clauseId` with `clause`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `clause`: New `clause` object, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10c7462a-2062-45ba-a8bb-dfb3de0f8af5", + "clause": { + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["Mexico", "Canada"] + } + }] +} +``` + +#### updateDefaultVariation + +Updates the default on or off variation of the flag. + +##### Parameters + +- `onVariationValue`: (Optional) The value of the variation of the new on variation. +- `offVariationValue`: (Optional) The value of the variation of the new off variation + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateDefaultVariation", "OnVariationValue": true, "OffVariationValue": false } ] +} +``` + +#### updateFallthroughVariationOrRollout + +Updates the default or "fallthrough" rule for the flag, which the flag serves when a context matches none of the targeting rules. The rule can serve either the variation that `variationId` indicates, or a percentage rollout that `rolloutWeights` and `rolloutBucketBy` indicate. + +##### Parameters + +- `variationId`: ID of a variation of the flag. + +or + +- `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000). +- `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. +- `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example that uses a `variationId`: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateFallthroughVariationOrRollout", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +Here's an example that uses a percentage rollout: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateFallthroughVariationOrRollout", + "rolloutContextKind": "user", + "rolloutWeights": { + "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation + "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000 // serve 85% this variation + } + }] +} +``` + +#### updateOffVariation + +Updates the default off variation to `variationId`. The flag serves the default off variation when the flag's targeting is **Off**. + +##### Parameters + +- `variationId`: ID of a variation of the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateOffVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### updatePrerequisite + +Changes the prerequisite flag that `key` indicates to use the variation that `variationId` indicates. Returns an error if this prerequisite does not exist. + +##### Parameters + +- `key`: Flag key of an existing prerequisite flag. +- `variationId`: ID of a variation of the prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updatePrerequisite", + "key": "example-prereq-flag-key", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### updateRuleDescription + +Updates the description of the feature flag rule. + +##### Parameters + +- `description`: The new human-readable description for this rule. +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleDescription", + "description": "New rule description", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### updateRuleTrackEvents + +Updates whether or not LaunchDarkly tracks events for the feature flag associated with this rule. + +##### Parameters + +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the flag. +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleTrackEvents", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "trackEvents": true + }] +} +``` + +#### updateRuleVariationOrRollout + +Updates what `ruleId` serves when its clauses evaluate to true. The rule can serve either the variation that `variationId` indicates, or a percent rollout that `rolloutWeights` and `rolloutBucketBy` indicate. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `variationId`: ID of a variation of the flag. + + or + +- `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000). +- `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. +- `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleVariationOrRollout", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### updateTrackEvents + +Updates whether or not LaunchDarkly tracks events for the feature flag, for all rules. + +##### Parameters + +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateTrackEvents", "trackEvents": true } ] +} +``` + +#### updateTrackEventsFallthrough + +Updates whether or not LaunchDarkly tracks events for the feature flag, for the default rule. + +##### Parameters + +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateTrackEventsFallthrough", "trackEvents": true } ] +} +``` + +#### updateVariation + +Updates a variation of the flag. + +##### Parameters + +- `variationId`: The ID of the variation to update. +- `name`: (Optional) The updated variation name. +- `value`: (Optional) The updated variation value. +- `description`: (Optional) The updated variation description. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", "value": 20 } ] +} +``` + +

+ +
+Click to expand instructions for updating flag settings + +These instructions do not require the `environmentKey` parameter. They make changes that apply to the flag across all environments. + +#### addCustomProperties + +Adds a new custom property to the feature flag. Custom properties are used to associate feature flags with LaunchDarkly integrations. For example, if you create an integration with an issue tracking service, you may want to associate a flag with a list of issues related to a feature's development. + +##### Parameters + + - `key`: The custom property key. + - `name`: The custom property name. + - `values`: A list of the associated values for the custom property. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addCustomProperties", + "key": "example-custom-property", + "name": "Example custom property", + "values": ["value1", "value2"] + }] +} +``` + +#### addTags + +Adds tags to the feature flag. + +##### Parameters + +- `values`: A list of tags to add. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "addTags", "values": ["tag1", "tag2"] } ] +} +``` + +#### makeFlagPermanent + +Marks the feature flag as permanent. LaunchDarkly does not prompt you to remove permanent flags, even if one variation is rolled out to all your customers. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "makeFlagPermanent" } ] +} +``` + +#### makeFlagTemporary + +Marks the feature flag as temporary. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "makeFlagTemporary" } ] +} +``` + +#### removeCustomProperties + +Removes the associated values from a custom property. If all the associated values are removed, this instruction also removes the custom property. + +##### Parameters + + - `key`: The custom property key. + - `values`: A list of the associated values to remove from the custom property. + +```json +{ + "instructions": [{ + "kind": "replaceCustomProperties", + "key": "example-custom-property", + "values": ["value1", "value2"] + }] +} +``` + +#### removeMaintainer + +Removes the flag's maintainer. To set a new maintainer, use the `updateMaintainerMember` or `updateMaintainerTeam` instructions. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeMaintainer" } ] +} +``` + +#### removeTags + +Removes tags from the feature flag. + +##### Parameters + +- `values`: A list of tags to remove. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeTags", "values": ["tag1", "tag2"] } ] +} +``` + +#### replaceCustomProperties + +Replaces the existing associated values for a custom property with the new values. + +##### Parameters + + - `key`: The custom property key. + - `name`: The custom property name. + - `values`: A list of the new associated values for the custom property. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceCustomProperties", + "key": "example-custom-property", + "name": "Example custom property", + "values": ["value1", "value2"] + }] +} +``` + +#### turnOffClientSideAvailability + +Turns off client-side SDK availability for the flag. This is equivalent to unchecking the **SDKs using Mobile key** and/or **SDKs using Client-side ID** boxes for the flag. If you're using a client-side or mobile SDK, you must expose your feature flags in order for the client-side or mobile SDKs to evaluate them. + +##### Parameters + +- `value`: Use "usingMobileKey" to turn off availability for mobile SDKs. Use "usingEnvironmentId" to turn on availability for client-side SDKs. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "turnOffClientSideAvailability", "value": "usingMobileKey" } ] +} +``` + +#### turnOnClientSideAvailability + +Turns on client-side SDK availability for the flag. This is equivalent to checking the **SDKs using Mobile key** and/or **SDKs using Client-side ID** boxes for the flag. If you're using a client-side or mobile SDK, you must expose your feature flags in order for the client-side or mobile SDKs to evaluate them. + +##### Parameters + +- `value`: Use "usingMobileKey" to turn on availability for mobile SDKs. Use "usingEnvironmentId" to turn on availability for client-side SDKs. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "turnOnClientSideAvailability", "value": "usingMobileKey" } ] +} +``` + +#### updateDescription + +Updates the feature flag description. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateDescription", "value": "Updated flag description" } ] +} +``` +#### updateMaintainerMember + +Updates the maintainer of the flag to an existing member and removes the existing maintainer. + +##### Parameters + +- `value`: The ID of the member. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateMaintainerMember", "value": "61e9b714fd47591727db558a" } ] +} +``` + +#### updateMaintainerTeam + +Updates the maintainer of the flag to an existing team and removes the existing maintainer. + +##### Parameters + +- `value`: The key of the team. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateMaintainerTeam", "value": "example-team-key" } ] +} +``` + +#### updateName + +Updates the feature flag name. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateName", "value": "Updated flag name" } ] +} +``` + +

+ +
+Click to expand instructions for updating the flag lifecycle + +These instructions do not require the `environmentKey` parameter. They make changes that apply to the flag across all environments. + +#### archiveFlag + +Archives the feature flag. This retires it from LaunchDarkly without deleting it. You cannot archive a flag that is a prerequisite of other flags. + +```json +{ + "instructions": [ { "kind": "archiveFlag" } ] +} +``` + +#### deleteFlag + +Deletes the feature flag and its rules. You cannot restore a deleted flag. If this flag is requested again, the flag value defined in code will be returned for all contexts. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "deleteFlag" } ] +} +``` + +#### deprecateFlag + +Deprecates the feature flag. This hides it from the live flags list without archiving or deleting it. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "deprecateFlag" } ] +} +``` + +#### restoreDeprecatedFlag + +Restores the feature flag if it was previously deprecated. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "restoreDeprecatedFlag" } ] +} +``` + +#### restoreFlag + +Restores the feature flag if it was previously archived. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "restoreFlag" } ] +} +``` + +
+ +### Using JSON patches on a feature flag + +If you do not include the semantic patch header described above, you can use a [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. + +In the JSON patch representation, use a JSON pointer in the `path` element to describe what field to change. Use the [Get feature flag](https://launchdarkly.com/docs/api/feature-flags/get-feature-flag) endpoint to find the field you want to update. + +There are a few special cases to keep in mind when determining the value of the `path` element: + + * To add an individual target to a specific variation if the flag variation already has individual targets, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/environments/devint/targets/0/values/-", + "value": "TestClient10" + } + ] + ``` + + * To add an individual target to a specific variation if the flag variation does not already have individual targets, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/environments/devint/targets/-", + "value": { "variation": 0, "values": ["TestClient10"] } + } + ] + ``` + + * To add a flag to a release pipeline, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/releasePipelineKey", + "value": "example-release-pipeline-key" + } + ] + ``` + +### Required approvals +If a request attempts to alter a flag configuration in an environment where approvals are required for the flag, the request will fail with a 405. Changes to the flag configuration in that environment will require creating an [approval request](https://launchdarkly.com/docs/api/approvals) or a [workflow](https://launchdarkly.com/docs/api/workflows). + +### Conflicts +If a flag configuration change made through this endpoint would cause a pending scheduled change or approval request to fail, this endpoint will return a 400. You can ignore this check by adding an `ignoreConflicts` query parameter set to `true`. + +### Migration flags +For migration flags, the cohort information is included in the `rules` property of a flag's response. You can update cohorts by updating `rules`. Default cohort information is included in the `fallthrough` property of a flag's response. You can update the default cohort by updating `fallthrough`. +When you update the rollout for a cohort or the default cohort through the API, provide a rollout instead of a single `variationId`. +To learn more, read [Migration flags](https://launchdarkly.com/docs/home/flags/migration). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiPatchFeatureFlagRequest + */ + PatchFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiPatchFeatureFlagRequest + + // PatchFeatureFlagExecute executes the request + // @return FeatureFlag + PatchFeatureFlagExecute(r ApiPatchFeatureFlagRequest) (*FeatureFlag, *http.Response, error) + + /* + PostFeatureFlag Create a feature flag + + Create a feature flag with the given name, key, and variations. + +
+Click to expand instructions for creating a migration flag + +### Creating a migration flag + +When you create a migration flag, the variations are pre-determined based on the number of stages in the migration. + +To create a migration flag, omit the `variations` and `defaults` information. Instead, provide a `purpose` of `migration`, and `migrationSettings`. If you create a migration flag with six stages, `contextKind` is required. Otherwise, it should be omitted. + +Here's an example: + +```json +{ + "key": "flag-key-123", + "purpose": "migration", + "migrationSettings": { + "stageCount": 6, + "contextKind": "account" + } +} +``` + +To learn more, read [Migration Flags](https://launchdarkly.com/docs/home/flags/migration). + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostFeatureFlagRequest + */ + PostFeatureFlag(ctx context.Context, projectKey string) ApiPostFeatureFlagRequest + + // PostFeatureFlagExecute executes the request + // @return FeatureFlag + PostFeatureFlagExecute(r ApiPostFeatureFlagRequest) (*FeatureFlag, *http.Response, error) + + /* + PostMigrationSafetyIssues Get migration safety issues + + Returns the migration safety issues that are associated with the POSTed flag patch. The patch must use the semantic patch format for updating feature flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The migration flag key + @param environmentKey The environment key + @return ApiPostMigrationSafetyIssuesRequest + */ + PostMigrationSafetyIssues(ctx context.Context, projectKey string, flagKey string, environmentKey string) ApiPostMigrationSafetyIssuesRequest + + // PostMigrationSafetyIssuesExecute executes the request + // @return []MigrationSafetyIssueRep + PostMigrationSafetyIssuesExecute(r ApiPostMigrationSafetyIssuesRequest) ([]MigrationSafetyIssueRep, *http.Response, error) +} + +// FeatureFlagsApiService FeatureFlagsApi service +type FeatureFlagsApiService service + +type ApiCopyFeatureFlagRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagKey string + flagCopyConfigPost *FlagCopyConfigPost +} + +func (r ApiCopyFeatureFlagRequest) FlagCopyConfigPost(flagCopyConfigPost FlagCopyConfigPost) ApiCopyFeatureFlagRequest { + r.flagCopyConfigPost = &flagCopyConfigPost + return r +} + +func (r ApiCopyFeatureFlagRequest) Execute() (*FeatureFlag, *http.Response, error) { + return r.ApiService.CopyFeatureFlagExecute(r) +} + +/* +CopyFeatureFlag Copy feature flag + + +> ### Copying flag settings is an Enterprise feature +> +> Copying flag settings is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +Copy flag settings from a source environment to a target environment. + +By default, this operation copies the entire flag configuration. You can use the `includedActions` or `excludedActions` to specify that only part of the flag configuration is copied. + +If you provide the optional `currentVersion` of a flag, this operation tests to ensure that the current flag version in the environment matches the version you've specified. The operation rejects attempts to copy flag settings if the environment's current version of the flag does not match the version you've specified. You can use this to enforce optimistic locking on copy attempts. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiCopyFeatureFlagRequest +*/ +func (a *FeatureFlagsApiService) CopyFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiCopyFeatureFlagRequest { + return ApiCopyFeatureFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FeatureFlag +func (a *FeatureFlagsApiService) CopyFeatureFlagExecute(r ApiCopyFeatureFlagRequest) (*FeatureFlag, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlag + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.CopyFeatureFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/copy" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagCopyConfigPost == nil { + return localVarReturnValue, nil, reportError("flagCopyConfigPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagCopyConfigPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteFeatureFlagRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagKey string +} + +func (r ApiDeleteFeatureFlagRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteFeatureFlagExecute(r) +} + +/* +DeleteFeatureFlag Delete feature flag + +Delete a feature flag in all environments. Use with caution: only delete feature flags your application no longer uses. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiDeleteFeatureFlagRequest +*/ +func (a *FeatureFlagsApiService) DeleteFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiDeleteFeatureFlagRequest { + return ApiDeleteFeatureFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +func (a *FeatureFlagsApiService) DeleteFeatureFlagExecute(r ApiDeleteFeatureFlagRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.DeleteFeatureFlag") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetExpiringContextTargetsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string + featureFlagKey string +} + +func (r ApiGetExpiringContextTargetsRequest) Execute() (*ExpiringTargetGetResponse, *http.Response, error) { + return r.ApiService.GetExpiringContextTargetsExecute(r) +} + +/* +GetExpiringContextTargets Get expiring context targets for feature flag + +Get a list of context targets on a feature flag that are scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetExpiringContextTargetsRequest +*/ +func (a *FeatureFlagsApiService) GetExpiringContextTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetExpiringContextTargetsRequest { + return ApiGetExpiringContextTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return ExpiringTargetGetResponse +func (a *FeatureFlagsApiService) GetExpiringContextTargetsExecute(r ApiGetExpiringContextTargetsRequest) (*ExpiringTargetGetResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringTargetGetResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetExpiringContextTargets") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/expiring-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExpiringUserTargetsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string + featureFlagKey string +} + +func (r ApiGetExpiringUserTargetsRequest) Execute() (*ExpiringUserTargetGetResponse, *http.Response, error) { + return r.ApiService.GetExpiringUserTargetsExecute(r) +} + +/* +GetExpiringUserTargets Get expiring user targets for feature flag + + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring context targets for feature flag](https://launchdarkly.com/docs/api/feature-flags/get-expiring-context-targets) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get a list of user targets on a feature flag that are scheduled for removal. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetExpiringUserTargetsRequest +*/ +func (a *FeatureFlagsApiService) GetExpiringUserTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetExpiringUserTargetsRequest { + return ApiGetExpiringUserTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetGetResponse +func (a *FeatureFlagsApiService) GetExpiringUserTargetsExecute(r ApiGetExpiringUserTargetsRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetGetResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetExpiringUserTargets") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagKey string + env *string + expand *string +} + +// Filter configurations by environment +func (r ApiGetFeatureFlagRequest) Env(env string) ApiGetFeatureFlagRequest { + r.env = &env + return r +} + +// A comma-separated list of fields to expand in the response. Supported fields are explained above. +func (r ApiGetFeatureFlagRequest) Expand(expand string) ApiGetFeatureFlagRequest { + r.expand = &expand + return r +} + +func (r ApiGetFeatureFlagRequest) Execute() (*FeatureFlag, *http.Response, error) { + return r.ApiService.GetFeatureFlagExecute(r) +} + +/* +GetFeatureFlag Get feature flag + +Get a single feature flag by key. By default, this returns the configurations for all environments. You can filter environments with the `env` query parameter. For example, setting `env=production` restricts the returned configurations to just the `production` environment. + +> #### Recommended use +> +> This endpoint can return a large amount of information. Specifying one or multiple environments with the `env` parameter can decrease response time and overall payload size. We recommend using this parameter to return only the environments relevant to your query. + +### Expanding response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `evaluation` includes evaluation information within returned environments, including which context kinds the flag has been evaluated for in the past 30 days +- `migrationSettings` includes migration settings information within the flag and within returned environments. These settings are only included for migration flags, that is, where `purpose` is `migration`. + +For example, `expand=evaluation` includes the `evaluation` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagRequest +*/ +func (a *FeatureFlagsApiService) GetFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFeatureFlagRequest { + return ApiGetFeatureFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FeatureFlag +func (a *FeatureFlagsApiService) GetFeatureFlagExecute(r ApiGetFeatureFlagRequest) (*FeatureFlag, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlag + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetFeatureFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.env != nil { + localVarQueryParams.Add("env", parameterToString(*r.env, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagStatusRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string + featureFlagKey string +} + +func (r ApiGetFeatureFlagStatusRequest) Execute() (*FlagStatusRep, *http.Response, error) { + return r.ApiService.GetFeatureFlagStatusExecute(r) +} + +/* +GetFeatureFlagStatus Get feature flag status + +Get the status for a particular feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagStatusRequest +*/ +func (a *FeatureFlagsApiService) GetFeatureFlagStatus(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetFeatureFlagStatusRequest { + return ApiGetFeatureFlagStatusRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FlagStatusRep +func (a *FeatureFlagsApiService) GetFeatureFlagStatusExecute(r ApiGetFeatureFlagStatusRequest) (*FlagStatusRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagStatusRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetFeatureFlagStatus") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-statuses/{projectKey}/{environmentKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagStatusAcrossEnvironmentsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagKey string + env *string +} + +// Optional environment filter +func (r ApiGetFeatureFlagStatusAcrossEnvironmentsRequest) Env(env string) ApiGetFeatureFlagStatusAcrossEnvironmentsRequest { + r.env = &env + return r +} + +func (r ApiGetFeatureFlagStatusAcrossEnvironmentsRequest) Execute() (*FeatureFlagStatusAcrossEnvironments, *http.Response, error) { + return r.ApiService.GetFeatureFlagStatusAcrossEnvironmentsExecute(r) +} + +/* +GetFeatureFlagStatusAcrossEnvironments Get flag status across environments + +Get the status for a particular feature flag across environments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFeatureFlagStatusAcrossEnvironmentsRequest +*/ +func (a *FeatureFlagsApiService) GetFeatureFlagStatusAcrossEnvironments(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFeatureFlagStatusAcrossEnvironmentsRequest { + return ApiGetFeatureFlagStatusAcrossEnvironmentsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FeatureFlagStatusAcrossEnvironments +func (a *FeatureFlagsApiService) GetFeatureFlagStatusAcrossEnvironmentsExecute(r ApiGetFeatureFlagStatusAcrossEnvironmentsRequest) (*FeatureFlagStatusAcrossEnvironments, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagStatusAcrossEnvironments + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetFeatureFlagStatusAcrossEnvironments") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-status/{projectKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.env != nil { + localVarQueryParams.Add("env", parameterToString(*r.env, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagStatusesRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string +} + +func (r ApiGetFeatureFlagStatusesRequest) Execute() (*FeatureFlagStatuses, *http.Response, error) { + return r.ApiService.GetFeatureFlagStatusesExecute(r) +} + +/* +GetFeatureFlagStatuses List feature flag statuses + +Get a list of statuses for all feature flags. The status includes the last time the feature flag was requested, as well as a state, which is one of the following: + +- `new`: You created the flag fewer than seven days ago and it has never been requested. +- `active`: LaunchDarkly is receiving requests for this flag, but there are either multiple variations configured, or it is toggled off, or there have been changes to configuration in the past seven days. +- `inactive`: You created the feature flag more than seven days ago, and hasn't been requested within the past seven days. +- `launched`: LaunchDarkly is receiving requests for this flag, it is toggled on, there is only one variation configured, and there have been no changes to configuration in the past seven days. + +To learn more, read [Flag statuses](https://launchdarkly.com/docs/home/observability/flag-status). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetFeatureFlagStatusesRequest +*/ +func (a *FeatureFlagsApiService) GetFeatureFlagStatuses(ctx context.Context, projectKey string, environmentKey string) ApiGetFeatureFlagStatusesRequest { + return ApiGetFeatureFlagStatusesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FeatureFlagStatuses +func (a *FeatureFlagsApiService) GetFeatureFlagStatusesExecute(r ApiGetFeatureFlagStatusesRequest) (*FeatureFlagStatuses, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagStatuses + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetFeatureFlagStatuses") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-statuses/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + env *string + tag *string + limit *int64 + offset *int64 + archived *bool + summary *bool + filter *string + sort *string + compare *bool + expand *string +} + +// Filter configurations by environment +func (r ApiGetFeatureFlagsRequest) Env(env string) ApiGetFeatureFlagsRequest { + r.env = &env + return r +} + +// Filter feature flags by tag +func (r ApiGetFeatureFlagsRequest) Tag(tag string) ApiGetFeatureFlagsRequest { + r.tag = &tag + return r +} + +// The number of feature flags to return. Defaults to 20. +func (r ApiGetFeatureFlagsRequest) Limit(limit int64) ApiGetFeatureFlagsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetFeatureFlagsRequest) Offset(offset int64) ApiGetFeatureFlagsRequest { + r.offset = &offset + return r +} + +// Deprecated, use `filter=archived:true` instead. A boolean to filter the list to archived flags. When this is absent, only unarchived flags will be returned +// Deprecated +func (r ApiGetFeatureFlagsRequest) Archived(archived bool) ApiGetFeatureFlagsRequest { + r.archived = &archived + return r +} + +// By default, flags do _not_ include their lists of prerequisites, targets, or rules for each environment. Set `summary=0` to include these fields for each flag returned. +func (r ApiGetFeatureFlagsRequest) Summary(summary bool) ApiGetFeatureFlagsRequest { + r.summary = &summary + return r +} + +// A comma-separated list of filters. Each filter is of the form field:value. Read the endpoint description for a full list of available filter fields. +func (r ApiGetFeatureFlagsRequest) Filter(filter string) ApiGetFeatureFlagsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order. Read the endpoint description for a full list of available sort fields. +func (r ApiGetFeatureFlagsRequest) Sort(sort string) ApiGetFeatureFlagsRequest { + r.sort = &sort + return r +} + +// Deprecated, unavailable in API version `20240415`. A boolean to filter results by only flags that have differences between environments. +// Deprecated +func (r ApiGetFeatureFlagsRequest) Compare(compare bool) ApiGetFeatureFlagsRequest { + r.compare = &compare + return r +} + +// A comma-separated list of fields to expand in the response. Supported fields are explained above. +func (r ApiGetFeatureFlagsRequest) Expand(expand string) ApiGetFeatureFlagsRequest { + r.expand = &expand + return r +} + +func (r ApiGetFeatureFlagsRequest) Execute() (*FeatureFlags, *http.Response, error) { + return r.ApiService.GetFeatureFlagsExecute(r) +} + +/* +GetFeatureFlags List feature flags + +Get a list of all feature flags in the given project. You can include information specific to different environments by adding `env` query parameter. For example, setting `env=production` adds configuration details about your production environment to the response. You can also filter feature flags by tag with the `tag` query parameter. + +> #### Recommended use +> +> This endpoint can return a large amount of information. We recommend using some or all of these query parameters to decrease response time and overall payload size: `limit`, `env`, `query`, and `filter=creationDate`. + +### Filtering flags + +You can filter on certain fields using the `filter` query parameter. For example, setting `filter=query:dark-mode,tags:beta+test` matches flags with the string `dark-mode` in their key or name, ignoring case, which also have the tags `beta` and `test`. + +The `filter` query parameter supports the following arguments: + +| Filter argument | Description | Example | +|-----------------------|-------------|----------------------| +| `applicationEvaluated` | A string. It filters the list to flags that are evaluated in the application with the given key. | `filter=applicationEvaluated:com.launchdarkly.cafe` | +| `archived` | (deprecated) A boolean value. It filters the list to archived flags. | Use `filter=state:archived` instead | +| `contextKindsEvaluated` | A `+`-separated list of context kind keys. It filters the list to flags which have been evaluated in the past 30 days for all of the context kinds in the list. | `filter=contextKindsEvaluated:user+application` | +| `codeReferences.max` | An integer value. Use `0` to return flags that do not have code references. | `filter=codeReferences.max:0` | +| `codeReferences.min` | An integer value. Use `1` to return flags that do have code references. | `filter=codeReferences.min:1` | +| `creationDate` | An object with an optional `before` field whose value is Unix time in milliseconds. It filters the list to flags created before the date. | `filter=creationDate:{"before":1690527600000}` | +| `evaluated` | An object that contains a key of `after` and a value in Unix time in milliseconds. It filters the list to all flags that have been evaluated since the time you specify, in the environment provided. This filter requires the `filterEnv` filter. | `filter=evaluated:{"after":1690527600000},filterEnv:production` | +| `filterEnv` | A valid environment key. You must use this field for filters that are environment-specific. If there are multiple environment-specific filters, you only need to include this field once. | `filter=evaluated:{"after": 1590768455282},filterEnv:production` | +| `hasExperiment` | A boolean value. It filters the list to flags that are used in an experiment. | `filter=hasExperiment:true` | +| `maintainerId` | A valid member ID. It filters the list to flags that are maintained by this member. | `filter=maintainerId:12ab3c45de678910abc12345` | +| `maintainerTeamKey` | A string. It filters the list to flags that are maintained by the team with this key. | `filter=maintainerTeamKey:example-team-key` | +| `query` | A string. It filters the list to flags that include the specified string in their key or name. It is not case sensitive. | `filter=query:example` | +| `releasePipeline` | A release pipeline key. It filters the list to flags that are either currently active in the release pipeline or have completed the release pipeline. | `filter=releasePipeline:default-release-pipeline` | +| `state` | A string, either `live`, `deprecated`, or `archived`. It filters the list to flags in this state. | `filter=state:archived` | +| `sdkAvailability` | A string, one of `client`, `mobile`, `anyClient`, `server`. Using `client` filters the list to flags whose client-side SDK availability is set to use the client-side ID. Using `mobile` filters to flags set to use the mobile key. Using `anyClient` filters to flags set to use either the client-side ID or the mobile key. Using `server` filters to flags set to use neither, that is, to flags only available in server-side SDKs. | `filter=sdkAvailability:client` | +| `tags` | A `+`-separated list of tags. It filters the list to flags that have all of the tags in the list. | `filter=tags:beta+test` | +| `type` | A string, either `temporary` or `permanent`. It filters the list to flags with the specified type. | `filter=type:permanent` | + +The documented values for the `filter` query are prior to URL encoding. For example, the `+` in `filter=tags:beta+test` must be encoded to `%2B`. + +By default, this endpoint returns all flags. You can page through the list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the returned `_links` field. These links will not be present if the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page. + +### Sorting flags + +You can sort flags based on the following fields: + +- `creationDate` sorts by the creation date of the flag. +- `key` sorts by the key of the flag. +- `maintainerId` sorts by the flag maintainer. +- `name` sorts by flag name. +- `tags` sorts by tags. +- `targetingModifiedDate` sorts by the date that the flag's targeting rules were last modified in a given environment. It must be used with `env` parameter and it can not be combined with any other sort. If multiple `env` values are provided, it will perform sort using the first one. For example, `sort=-targetingModifiedDate&env=production&env=staging` returns results sorted by `targetingModifiedDate` for the `production` environment. +- `type` sorts by flag type + +All fields are sorted in ascending order by default. To sort in descending order, prefix the field with a dash ( - ). For example, `sort=-name` sorts the response by flag name in descending order. + +### Expanding response + +LaunchDarkly supports the `expand` query param to include additional fields in the response, with the following fields: + +- `codeReferences` includes code references for the feature flag +- `evaluation` includes evaluation information within returned environments, including which context kinds the flag has been evaluated for in the past 30 days +- `migrationSettings` includes migration settings information within the flag and within returned environments. These settings are only included for migration flags, that is, where `purpose` is `migration`. + +For example, `expand=evaluation` includes the `evaluation` field in the response. + +### Migration flags +For migration flags, the cohort information is included in the `rules` property of a flag's response, and default cohort information is included in the `fallthrough` property of a flag's response. +To learn more, read [Migration Flags](https://launchdarkly.com/docs/home/flags/migration). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetFeatureFlagsRequest +*/ +func (a *FeatureFlagsApiService) GetFeatureFlags(ctx context.Context, projectKey string) ApiGetFeatureFlagsRequest { + return ApiGetFeatureFlagsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return FeatureFlags +func (a *FeatureFlagsApiService) GetFeatureFlagsExecute(r ApiGetFeatureFlagsRequest) (*FeatureFlags, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlags + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.GetFeatureFlags") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.env != nil { + localVarQueryParams.Add("env", parameterToString(*r.env, "")) + } + if r.tag != nil { + localVarQueryParams.Add("tag", parameterToString(*r.tag, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.archived != nil { + localVarQueryParams.Add("archived", parameterToString(*r.archived, "")) + } + if r.summary != nil { + localVarQueryParams.Add("summary", parameterToString(*r.summary, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.compare != nil { + localVarQueryParams.Add("compare", parameterToString(*r.compare, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExpiringTargetsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string + featureFlagKey string + patchFlagsRequest *PatchFlagsRequest +} + +func (r ApiPatchExpiringTargetsRequest) PatchFlagsRequest(patchFlagsRequest PatchFlagsRequest) ApiPatchExpiringTargetsRequest { + r.patchFlagsRequest = &patchFlagsRequest + return r +} + +func (r ApiPatchExpiringTargetsRequest) Execute() (*ExpiringTargetPatchResponse, *http.Response, error) { + return r.ApiService.PatchExpiringTargetsExecute(r) +} + +/* +PatchExpiringTargets Update expiring context targets on feature flag + +Schedule a context for removal from individual targeting on a feature flag. The flag must already individually target the context. + +You can add, update, or remove a scheduled removal date. You can only schedule a context for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring targets. + +
+Click to expand instructions for updating expiring targets + +#### addExpiringTarget + +Adds a date and time that LaunchDarkly will remove the context from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the context from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExpiringTarget", + "value": 1754006460000, + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +#### updateExpiringTarget + +Updates the date and time that LaunchDarkly will remove the context from the flag's individual targeting + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the context from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` +* `version`: (Optional) The version of the expiring target to update. If included, update will fail if version doesn't match current version of the expiring target. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateExpiringTarget", + "value": 1754006460000, + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +#### removeExpiringTarget + +Removes the scheduled removal of the context from the flag's individual targeting. The context will remain part of the flag's individual targeting until you explicitly remove it, or until you schedule another removal. + +##### Parameters + +* `variationId`: ID of a variation on the flag +* `contextKey`: The context key for the context to remove from individual targeting +* `contextKind`: The kind of context represented by the `contextKey` + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExpiringTarget", + "variationId": "4254742c-71ae-411f-a992-43b18a51afe0", + "contextKey": "user-key-123abc", + "contextKind": "user" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiPatchExpiringTargetsRequest +*/ +func (a *FeatureFlagsApiService) PatchExpiringTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiPatchExpiringTargetsRequest { + return ApiPatchExpiringTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return ExpiringTargetPatchResponse +func (a *FeatureFlagsApiService) PatchExpiringTargetsExecute(r ApiPatchExpiringTargetsRequest) (*ExpiringTargetPatchResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringTargetPatchResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.PatchExpiringTargets") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/expiring-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchFlagsRequest == nil { + return localVarReturnValue, nil, reportError("patchFlagsRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchFlagsRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExpiringUserTargetsRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + environmentKey string + featureFlagKey string + patchFlagsRequest *PatchFlagsRequest +} + +func (r ApiPatchExpiringUserTargetsRequest) PatchFlagsRequest(patchFlagsRequest PatchFlagsRequest) ApiPatchExpiringUserTargetsRequest { + r.patchFlagsRequest = &patchFlagsRequest + return r +} + +func (r ApiPatchExpiringUserTargetsRequest) Execute() (*ExpiringUserTargetPatchResponse, *http.Response, error) { + return r.ApiService.PatchExpiringUserTargetsExecute(r) +} + +/* +PatchExpiringUserTargets Update expiring user targets on feature flag + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Update expiring context targets on feature flag](https://launchdarkly.com/docs/api/feature-flags/patch-expiring-targets) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Schedule a target for removal from individual targeting on a feature flag. The flag must already serve a variation to specific targets based on their key. + +You can add, update, or remove a scheduled removal date. You can only schedule a target for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Adds a date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting + +#### updateExpireUserTargetDate + +Updates the date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting +* `version`: (Optional) The version of the expiring user target to update. If included, update will fail if version doesn't match current version of the expiring user target. + +#### removeExpireUserTargetDate + +Removes the scheduled removal of the user from the flag's individual targeting. The user will remain part of the flag's individual targeting until you explicitly remove them, or until you schedule another removal. + +##### Parameters + +* `variationId`: ID of a variation on the flag +* `userKey`: The user key for the user to remove from individual targeting + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiPatchExpiringUserTargetsRequest +*/ +func (a *FeatureFlagsApiService) PatchExpiringUserTargets(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiPatchExpiringUserTargetsRequest { + return ApiPatchExpiringUserTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetPatchResponse +func (a *FeatureFlagsApiService) PatchExpiringUserTargetsExecute(r ApiPatchExpiringUserTargetsRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetPatchResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.PatchExpiringUserTargets") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchFlagsRequest == nil { + return localVarReturnValue, nil, reportError("patchFlagsRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchFlagsRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchFeatureFlagRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagKey string + patchWithComment *PatchWithComment + ignoreConflicts *bool +} + +func (r ApiPatchFeatureFlagRequest) PatchWithComment(patchWithComment PatchWithComment) ApiPatchFeatureFlagRequest { + r.patchWithComment = &patchWithComment + return r +} + +// If true, the patch will be applied even if it causes a pending scheduled change or approval request to fail. +func (r ApiPatchFeatureFlagRequest) IgnoreConflicts(ignoreConflicts bool) ApiPatchFeatureFlagRequest { + r.ignoreConflicts = &ignoreConflicts + return r +} + +func (r ApiPatchFeatureFlagRequest) Execute() (*FeatureFlag, *http.Response, error) { + return r.ApiService.PatchFeatureFlagExecute(r) +} + +/* +PatchFeatureFlag Update feature flag + +Perform a partial update to a feature flag. The request body must be a valid semantic patch, JSON patch, or JSON merge patch. To learn more the different formats, read [Updates](https://launchdarkly.com/docs/api#updates). + +### Using semantic patches on a feature flag + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +The body of a semantic patch request for updating feature flags takes the following properties: + +* `comment` (string): (Optional) A description of the update. +* `environmentKey` (string): (Required for some instructions only) The key of the LaunchDarkly environment. +* `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the action requires parameters, you must include those parameters as additional fields in the object. The body of a single semantic patch can contain many different instructions. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating feature flags. + +
+Click to expand instructions for turning flags on and off + +These instructions require the `environmentKey` parameter. + +#### turnFlagOff + +Sets the flag's targeting state to **Off**. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "turnFlagOff" } ] +} +``` + +#### turnFlagOn + +Sets the flag's targeting state to **On**. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "turnFlagOn" } ] +} +``` + +

+ +
+Click to expand instructions for working with targeting and variations + +These instructions require the `environmentKey` parameter. + +Several of the instructions for working with targeting and variations require flag rule IDs, variation IDs, or clause IDs as parameters. Each of these are returned as part of the [Get feature flag](https://launchdarkly.com/docs/api/feature-flags/get-feature-flag) response. The flag rule ID is the `_id` field of each element in the `rules` array within each environment listed in the `environments` object. The variation ID is the `_id` field in each element of the `variations` array. The clause ID is the `_id` field of each element of the `clauses` array within the `rules` array within each environment listed in the `environments` object. + +#### addClauses + +Adds the given clauses to the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauses": [{ + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["USA", "Canada"] + }] + }] +} +``` + +#### addPrerequisite + +Adds the flag indicated by `key` with variation `variationId` as a prerequisite to the flag in the path parameter. + +##### Parameters + +- `key`: Flag key of the prerequisite flag. +- `variationId`: ID of a variation of the prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addPrerequisite", + "key": "example-prereq-flag-key", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addRule + +Adds a new targeting rule to the flag. The rule may contain `clauses` and serve the variation that `variationId` indicates, or serve a percentage rollout that `rolloutWeights`, `rolloutBucketBy`, and `rolloutContextKind` indicate. + +If you set `beforeRuleId`, this adds the new rule before the indicated rule. Otherwise, adds the new rule to the end of the list. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `beforeRuleId`: (Optional) ID of a flag rule. +- Either + - `variationId`: ID of a variation of the flag. + + or + + - `rolloutWeights`: (Optional) Map of `variationId` to weight, in thousandths of a percent (0-100000). + - `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. + - `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example that uses a `variationId`: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addRule", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "clauses": [{ + "contextKind": "organization", + "attribute": "located_in", + "op": "in", + "negate": false, + "values": ["Sweden", "Norway"] + }] + }] +} +``` + +Here's an example that uses a percentage rollout: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addRule", + "clauses": [{ + "contextKind": "organization", + "attribute": "located_in", + "op": "in", + "negate": false, + "values": ["Sweden", "Norway"] + }], + "rolloutContextKind": "organization", + "rolloutWeights": { + "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation + "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000 // serve 85% this variation + } + }] +} +``` + +#### addTargets + +Adds context keys to the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Returns an error if this causes the flag to target the same context key in multiple variations. + +##### Parameters + +- `values`: List of context keys. +- `contextKind`: (Optional) Context kind to target, defaults to `user` +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addTargets", + "values": ["context-key-123abc", "context-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addUserTargets + +Adds user keys to the individual user targets for the variation that `variationId` specifies. Returns an error if this causes the flag to target the same user key in multiple variations. If you are working with contexts, use `addTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addUserTargets", + "values": ["user-key-123abc", "user-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### addValuesToClause + +Adds `values` to the values of the clause that `ruleId` and `clauseId` indicate. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "addValuesToClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### addVariation + +Adds a variation to the flag. + +##### Parameters + +- `value`: The variation value. +- `name`: (Optional) The variation name. +- `description`: (Optional) A description for the variation. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "addVariation", "value": 20, "name": "New variation" } ] +} +``` + +#### clearTargets + +Removes all individual targets from the variation that `variationId` specifies. This includes both user and non-user targets. + +##### Parameters + +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "clearTargets", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### clearUserTargets + +Removes all individual user targets from the variation that `variationId` specifies. If you are working with contexts, use `clearTargets` instead of this instruction. + +##### Parameters + +- `variationId`: ID of a variation on the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "clearUserTargets", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### removeClauses + +Removes the clauses specified by `clauseIds` from the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseIds`: Array of IDs of clauses in the rule. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseIds": ["10a58772-3121-400f-846b-b8a04e8944ed", "36a461dc-235e-4b08-97b9-73ce9365873e"] + }] +} +``` + +#### removePrerequisite + +Removes the prerequisite flag indicated by `key`. Does nothing if this prerequisite does not exist. + +##### Parameters + +- `key`: Flag key of an existing prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "removePrerequisite", "key": "prereq-flag-key-123abc" } ] +} +``` + +#### removeRule + +Removes the targeting rule specified by `ruleId`. Does nothing if the rule does not exist. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "removeRule", "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" } ] +} +``` + +#### removeTargets + +Removes context keys from the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Does nothing if the flag does not target the context keys. + +##### Parameters + +- `values`: List of context keys. +- `contextKind`: (Optional) Context kind to target, defaults to `user` +- `variationId`: ID of a flag variation. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeTargets", + "values": ["context-key-123abc", "context-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### removeUserTargets + +Removes user keys from the individual user targets for the variation that `variationId` specifies. Does nothing if the flag does not target the user keys. If you are working with contexts, use `removeTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. +- `variationId`: ID of a flag variation. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeUserTargets", + "values": ["user-key-123abc", "user-key-456def"], + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### removeValuesFromClause + +Removes `values` from the values of the clause indicated by `ruleId` and `clauseId`. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "removeValuesFromClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### removeVariation + +Removes a variation from the flag. + +##### Parameters + +- `variationId`: ID of a variation of the flag to remove. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### reorderRules + +Rearranges the rules to match the order given in `ruleIds`. Returns an error if `ruleIds` does not match the current set of rules on the flag. + +##### Parameters + +- `ruleIds`: Array of IDs of all rules in the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "reorderRules", + "ruleIds": ["a902ef4a-2faf-4eaf-88e1-ecc356708a29", "63c238d1-835d-435e-8f21-c8d5e40b2a3d"] + }] +} +``` + +#### replacePrerequisites + +Removes all existing prerequisites and replaces them with the list you provide. + +##### Parameters + +- `prerequisites`: A list of prerequisites. Each item in the list must include a flag `key` and `variationId`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replacePrerequisites", + "prerequisites": [ + { + "key": "prereq-flag-key-123abc", + "variationId": "10a58772-3121-400f-846b-b8a04e8944ed" + }, + { + "key": "another-prereq-flag-key-456def", + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43" + } + ] + } + ] +} +``` + +#### replaceRules + +Removes all targeting rules for the flag and replaces them with the list you provide. + +##### Parameters + +- `rules`: A list of rules. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceRules", + "rules": [ + { + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "description": "My new rule", + "clauses": [ + { + "contextKind": "user", + "attribute": "segmentMatch", + "op": "segmentMatch", + "values": ["test"] + } + ], + "trackEvents": true + } + ] + } + ] +} +``` + +#### replaceTargets + +Removes all existing targeting and replaces it with the list of targets you provide. + +##### Parameters + +- `targets`: A list of context targeting. Each item in the list includes an optional `contextKind` that defaults to `user`, a required `variationId`, and a required list of `values`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceTargets", + "targets": [ + { + "contextKind": "user", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "values": ["user-key-123abc"] + }, + { + "contextKind": "device", + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43", + "values": ["device-key-456def"] + } + ] + } + ] +} +``` + +#### replaceUserTargets + +Removes all existing user targeting and replaces it with the list of targets you provide. In the list of targets, you must include a target for each of the flag's variations. If you are working with contexts, use `replaceTargets` instead of this instruction. + +##### Parameters + +- `targets`: A list of user targeting. Each item in the list must include a `variationId` and a list of `values`. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ + { + "kind": "replaceUserTargets", + "targets": [ + { + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", + "values": ["user-key-123abc", "user-key-456def"] + }, + { + "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43", + "values": ["user-key-789ghi"] + } + ] + } + ] +} +``` + +#### updateClause + +Replaces the clause indicated by `ruleId` and `clauseId` with `clause`. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `clauseId`: ID of a clause in that rule. +- `clause`: New `clause` object, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10c7462a-2062-45ba-a8bb-dfb3de0f8af5", + "clause": { + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["Mexico", "Canada"] + } + }] +} +``` + +#### updateDefaultVariation + +Updates the default on or off variation of the flag. + +##### Parameters + +- `onVariationValue`: (Optional) The value of the variation of the new on variation. +- `offVariationValue`: (Optional) The value of the variation of the new off variation + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateDefaultVariation", "OnVariationValue": true, "OffVariationValue": false } ] +} +``` + +#### updateFallthroughVariationOrRollout + +Updates the default or "fallthrough" rule for the flag, which the flag serves when a context matches none of the targeting rules. The rule can serve either the variation that `variationId` indicates, or a percentage rollout that `rolloutWeights` and `rolloutBucketBy` indicate. + +##### Parameters + +- `variationId`: ID of a variation of the flag. + +or + +- `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000). +- `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. +- `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example that uses a `variationId`: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateFallthroughVariationOrRollout", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +Here's an example that uses a percentage rollout: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateFallthroughVariationOrRollout", + "rolloutContextKind": "user", + "rolloutWeights": { + "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation + "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000 // serve 85% this variation + } + }] +} +``` + +#### updateOffVariation + +Updates the default off variation to `variationId`. The flag serves the default off variation when the flag's targeting is **Off**. + +##### Parameters + +- `variationId`: ID of a variation of the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateOffVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ] +} +``` + +#### updatePrerequisite + +Changes the prerequisite flag that `key` indicates to use the variation that `variationId` indicates. Returns an error if this prerequisite does not exist. + +##### Parameters + +- `key`: Flag key of an existing prerequisite flag. +- `variationId`: ID of a variation of the prerequisite flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updatePrerequisite", + "key": "example-prereq-flag-key", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### updateRuleDescription + +Updates the description of the feature flag rule. + +##### Parameters + +- `description`: The new human-readable description for this rule. +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the flag. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleDescription", + "description": "New rule description", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### updateRuleTrackEvents + +Updates whether or not LaunchDarkly tracks events for the feature flag associated with this rule. + +##### Parameters + +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the flag. +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleTrackEvents", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "trackEvents": true + }] +} +``` + +#### updateRuleVariationOrRollout + +Updates what `ruleId` serves when its clauses evaluate to true. The rule can serve either the variation that `variationId` indicates, or a percent rollout that `rolloutWeights` and `rolloutBucketBy` indicate. + +##### Parameters + +- `ruleId`: ID of a rule in the flag. +- `variationId`: ID of a variation of the flag. + + or + +- `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000). +- `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`. +- `rolloutContextKind`: (Optional) Context kind, defaults to `user` + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [{ + "kind": "updateRuleVariationOrRollout", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" + }] +} +``` + +#### updateTrackEvents + +Updates whether or not LaunchDarkly tracks events for the feature flag, for all rules. + +##### Parameters + +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateTrackEvents", "trackEvents": true } ] +} +``` + +#### updateTrackEventsFallthrough + +Updates whether or not LaunchDarkly tracks events for the feature flag, for the default rule. + +##### Parameters + +- `trackEvents`: Whether or not events are tracked. + +Here's an example: + +```json +{ + "environmentKey": "environment-key-123abc", + "instructions": [ { "kind": "updateTrackEventsFallthrough", "trackEvents": true } ] +} +``` + +#### updateVariation + +Updates a variation of the flag. + +##### Parameters + +- `variationId`: The ID of the variation to update. +- `name`: (Optional) The updated variation name. +- `value`: (Optional) The updated variation value. +- `description`: (Optional) The updated variation description. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00", "value": 20 } ] +} +``` + +

+ +
+Click to expand instructions for updating flag settings + +These instructions do not require the `environmentKey` parameter. They make changes that apply to the flag across all environments. + +#### addCustomProperties + +Adds a new custom property to the feature flag. Custom properties are used to associate feature flags with LaunchDarkly integrations. For example, if you create an integration with an issue tracking service, you may want to associate a flag with a list of issues related to a feature's development. + +##### Parameters + + - `key`: The custom property key. + - `name`: The custom property name. + - `values`: A list of the associated values for the custom property. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addCustomProperties", + "key": "example-custom-property", + "name": "Example custom property", + "values": ["value1", "value2"] + }] +} +``` + +#### addTags + +Adds tags to the feature flag. + +##### Parameters + +- `values`: A list of tags to add. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "addTags", "values": ["tag1", "tag2"] } ] +} +``` + +#### makeFlagPermanent + +Marks the feature flag as permanent. LaunchDarkly does not prompt you to remove permanent flags, even if one variation is rolled out to all your customers. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "makeFlagPermanent" } ] +} +``` + +#### makeFlagTemporary + +Marks the feature flag as temporary. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "makeFlagTemporary" } ] +} +``` + +#### removeCustomProperties + +Removes the associated values from a custom property. If all the associated values are removed, this instruction also removes the custom property. + +##### Parameters + + - `key`: The custom property key. + - `values`: A list of the associated values to remove from the custom property. + +```json +{ + "instructions": [{ + "kind": "replaceCustomProperties", + "key": "example-custom-property", + "values": ["value1", "value2"] + }] +} +``` + +#### removeMaintainer + +Removes the flag's maintainer. To set a new maintainer, use the `updateMaintainerMember` or `updateMaintainerTeam` instructions. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeMaintainer" } ] +} +``` + +#### removeTags + +Removes tags from the feature flag. + +##### Parameters + +- `values`: A list of tags to remove. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "removeTags", "values": ["tag1", "tag2"] } ] +} +``` + +#### replaceCustomProperties + +Replaces the existing associated values for a custom property with the new values. + +##### Parameters + + - `key`: The custom property key. + - `name`: The custom property name. + - `values`: A list of the new associated values for the custom property. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceCustomProperties", + "key": "example-custom-property", + "name": "Example custom property", + "values": ["value1", "value2"] + }] +} +``` + +#### turnOffClientSideAvailability + +Turns off client-side SDK availability for the flag. This is equivalent to unchecking the **SDKs using Mobile key** and/or **SDKs using Client-side ID** boxes for the flag. If you're using a client-side or mobile SDK, you must expose your feature flags in order for the client-side or mobile SDKs to evaluate them. + +##### Parameters + +- `value`: Use "usingMobileKey" to turn off availability for mobile SDKs. Use "usingEnvironmentId" to turn on availability for client-side SDKs. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "turnOffClientSideAvailability", "value": "usingMobileKey" } ] +} +``` + +#### turnOnClientSideAvailability + +Turns on client-side SDK availability for the flag. This is equivalent to checking the **SDKs using Mobile key** and/or **SDKs using Client-side ID** boxes for the flag. If you're using a client-side or mobile SDK, you must expose your feature flags in order for the client-side or mobile SDKs to evaluate them. + +##### Parameters + +- `value`: Use "usingMobileKey" to turn on availability for mobile SDKs. Use "usingEnvironmentId" to turn on availability for client-side SDKs. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "turnOnClientSideAvailability", "value": "usingMobileKey" } ] +} +``` + +#### updateDescription + +Updates the feature flag description. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateDescription", "value": "Updated flag description" } ] +} +``` +#### updateMaintainerMember + +Updates the maintainer of the flag to an existing member and removes the existing maintainer. + +##### Parameters + +- `value`: The ID of the member. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateMaintainerMember", "value": "61e9b714fd47591727db558a" } ] +} +``` + +#### updateMaintainerTeam + +Updates the maintainer of the flag to an existing team and removes the existing maintainer. + +##### Parameters + +- `value`: The key of the team. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateMaintainerTeam", "value": "example-team-key" } ] +} +``` + +#### updateName + +Updates the feature flag name. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "updateName", "value": "Updated flag name" } ] +} +``` + +

+ +
+Click to expand instructions for updating the flag lifecycle + +These instructions do not require the `environmentKey` parameter. They make changes that apply to the flag across all environments. + +#### archiveFlag + +Archives the feature flag. This retires it from LaunchDarkly without deleting it. You cannot archive a flag that is a prerequisite of other flags. + +```json +{ + "instructions": [ { "kind": "archiveFlag" } ] +} +``` + +#### deleteFlag + +Deletes the feature flag and its rules. You cannot restore a deleted flag. If this flag is requested again, the flag value defined in code will be returned for all contexts. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "deleteFlag" } ] +} +``` + +#### deprecateFlag + +Deprecates the feature flag. This hides it from the live flags list without archiving or deleting it. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "deprecateFlag" } ] +} +``` + +#### restoreDeprecatedFlag + +Restores the feature flag if it was previously deprecated. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "restoreDeprecatedFlag" } ] +} +``` + +#### restoreFlag + +Restores the feature flag if it was previously archived. + +Here's an example: + +```json +{ + "instructions": [ { "kind": "restoreFlag" } ] +} +``` + +
+ +### Using JSON patches on a feature flag + +If you do not include the semantic patch header described above, you can use a [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. + +In the JSON patch representation, use a JSON pointer in the `path` element to describe what field to change. Use the [Get feature flag](https://launchdarkly.com/docs/api/feature-flags/get-feature-flag) endpoint to find the field you want to update. + +There are a few special cases to keep in mind when determining the value of the `path` element: + + * To add an individual target to a specific variation if the flag variation already has individual targets, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/environments/devint/targets/0/values/-", + "value": "TestClient10" + } + ] + ``` + + * To add an individual target to a specific variation if the flag variation does not already have individual targets, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/environments/devint/targets/-", + "value": { "variation": 0, "values": ["TestClient10"] } + } + ] + ``` + + * To add a flag to a release pipeline, the path for the JSON patch operation is: + + ```json + [ + { + "op": "add", + "path": "/releasePipelineKey", + "value": "example-release-pipeline-key" + } + ] + ``` + +### Required approvals +If a request attempts to alter a flag configuration in an environment where approvals are required for the flag, the request will fail with a 405. Changes to the flag configuration in that environment will require creating an [approval request](https://launchdarkly.com/docs/api/approvals) or a [workflow](https://launchdarkly.com/docs/api/workflows). + +### Conflicts +If a flag configuration change made through this endpoint would cause a pending scheduled change or approval request to fail, this endpoint will return a 400. You can ignore this check by adding an `ignoreConflicts` query parameter set to `true`. + +### Migration flags +For migration flags, the cohort information is included in the `rules` property of a flag's response. You can update cohorts by updating `rules`. Default cohort information is included in the `fallthrough` property of a flag's response. You can update the default cohort by updating `fallthrough`. +When you update the rollout for a cohort or the default cohort through the API, provide a rollout instead of a single `variationId`. +To learn more, read [Migration flags](https://launchdarkly.com/docs/home/flags/migration). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key. The key identifies the flag in your code. + @return ApiPatchFeatureFlagRequest +*/ +func (a *FeatureFlagsApiService) PatchFeatureFlag(ctx context.Context, projectKey string, featureFlagKey string) ApiPatchFeatureFlagRequest { + return ApiPatchFeatureFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FeatureFlag +func (a *FeatureFlagsApiService) PatchFeatureFlagExecute(r ApiPatchFeatureFlagRequest) (*FeatureFlag, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlag + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.PatchFeatureFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchWithComment == nil { + return localVarReturnValue, nil, reportError("patchWithComment is required and must be specified") + } + + if r.ignoreConflicts != nil { + localVarQueryParams.Add("ignoreConflicts", parameterToString(*r.ignoreConflicts, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchWithComment + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostFeatureFlagRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + featureFlagBody *FeatureFlagBody + clone *string +} + +func (r ApiPostFeatureFlagRequest) FeatureFlagBody(featureFlagBody FeatureFlagBody) ApiPostFeatureFlagRequest { + r.featureFlagBody = &featureFlagBody + return r +} + +// The key of the feature flag to be cloned. The key identifies the flag in your code. For example, setting `clone=flagKey` copies the full targeting configuration for all environments, including `on/off` state, from the original flag to the new flag. +func (r ApiPostFeatureFlagRequest) Clone(clone string) ApiPostFeatureFlagRequest { + r.clone = &clone + return r +} + +func (r ApiPostFeatureFlagRequest) Execute() (*FeatureFlag, *http.Response, error) { + return r.ApiService.PostFeatureFlagExecute(r) +} + +/* +PostFeatureFlag Create a feature flag + +Create a feature flag with the given name, key, and variations. + +
+Click to expand instructions for creating a migration flag + +### Creating a migration flag + +When you create a migration flag, the variations are pre-determined based on the number of stages in the migration. + +To create a migration flag, omit the `variations` and `defaults` information. Instead, provide a `purpose` of `migration`, and `migrationSettings`. If you create a migration flag with six stages, `contextKind` is required. Otherwise, it should be omitted. + +Here's an example: + +```json +{ + "key": "flag-key-123", + "purpose": "migration", + "migrationSettings": { + "stageCount": 6, + "contextKind": "account" + } +} +``` + +To learn more, read [Migration Flags](https://launchdarkly.com/docs/home/flags/migration). + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostFeatureFlagRequest +*/ +func (a *FeatureFlagsApiService) PostFeatureFlag(ctx context.Context, projectKey string) ApiPostFeatureFlagRequest { + return ApiPostFeatureFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return FeatureFlag +func (a *FeatureFlagsApiService) PostFeatureFlagExecute(r ApiPostFeatureFlagRequest) (*FeatureFlag, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlag + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.PostFeatureFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.featureFlagBody == nil { + return localVarReturnValue, nil, reportError("featureFlagBody is required and must be specified") + } + + if r.clone != nil { + localVarQueryParams.Add("clone", parameterToString(*r.clone, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.featureFlagBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostMigrationSafetyIssuesRequest struct { + ctx context.Context + ApiService FeatureFlagsApi + projectKey string + flagKey string + environmentKey string + flagSempatch *FlagSempatch +} + +func (r ApiPostMigrationSafetyIssuesRequest) FlagSempatch(flagSempatch FlagSempatch) ApiPostMigrationSafetyIssuesRequest { + r.flagSempatch = &flagSempatch + return r +} + +func (r ApiPostMigrationSafetyIssuesRequest) Execute() ([]MigrationSafetyIssueRep, *http.Response, error) { + return r.ApiService.PostMigrationSafetyIssuesExecute(r) +} + +/* +PostMigrationSafetyIssues Get migration safety issues + +Returns the migration safety issues that are associated with the POSTed flag patch. The patch must use the semantic patch format for updating feature flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The migration flag key + @param environmentKey The environment key + @return ApiPostMigrationSafetyIssuesRequest +*/ +func (a *FeatureFlagsApiService) PostMigrationSafetyIssues(ctx context.Context, projectKey string, flagKey string, environmentKey string) ApiPostMigrationSafetyIssuesRequest { + return ApiPostMigrationSafetyIssuesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return []MigrationSafetyIssueRep +func (a *FeatureFlagsApiService) PostMigrationSafetyIssuesExecute(r ApiPostMigrationSafetyIssuesRequest) ([]MigrationSafetyIssueRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []MigrationSafetyIssueRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsApiService.PostMigrationSafetyIssues") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{flagKey}/environments/{environmentKey}/migration-safety-issues" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagSempatch == nil { + return localVarReturnValue, nil, reportError("flagSempatch is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagSempatch + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 503 { + var v StatusServiceUnavailable + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags_beta.go new file mode 100644 index 00000000..63d3f7ca --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_feature_flags_beta.go @@ -0,0 +1,405 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FeatureFlagsBetaApi interface { + + /* + GetDependentFlags List dependent feature flags + + > ### Flag prerequisites is an Enterprise feature +> +> Flag prerequisites is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +List dependent flags across all environments for the flag specified in the path parameters. A dependent flag is a flag that uses another flag as a prerequisite. To learn more, read [Flag prerequisites](https://launchdarkly.com/docs/home/flags/prereqs). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetDependentFlagsRequest + */ + GetDependentFlags(ctx context.Context, projectKey string, featureFlagKey string) ApiGetDependentFlagsRequest + + // GetDependentFlagsExecute executes the request + // @return MultiEnvironmentDependentFlags + GetDependentFlagsExecute(r ApiGetDependentFlagsRequest) (*MultiEnvironmentDependentFlags, *http.Response, error) + + /* + GetDependentFlagsByEnv List dependent feature flags by environment + + > ### Flag prerequisites is an Enterprise feature +> +> Flag prerequisites is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +List dependent flags across all environments for the flag specified in the path parameters. A dependent flag is a flag that uses another flag as a prerequisite. To learn more, read [Flag prerequisites](https://launchdarkly.com/docs/home/flags/prereqs). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetDependentFlagsByEnvRequest + */ + GetDependentFlagsByEnv(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetDependentFlagsByEnvRequest + + // GetDependentFlagsByEnvExecute executes the request + // @return DependentFlagsByEnvironment + GetDependentFlagsByEnvExecute(r ApiGetDependentFlagsByEnvRequest) (*DependentFlagsByEnvironment, *http.Response, error) +} + +// FeatureFlagsBetaApiService FeatureFlagsBetaApi service +type FeatureFlagsBetaApiService service + +type ApiGetDependentFlagsRequest struct { + ctx context.Context + ApiService FeatureFlagsBetaApi + projectKey string + featureFlagKey string +} + +func (r ApiGetDependentFlagsRequest) Execute() (*MultiEnvironmentDependentFlags, *http.Response, error) { + return r.ApiService.GetDependentFlagsExecute(r) +} + +/* +GetDependentFlags List dependent feature flags + +> ### Flag prerequisites is an Enterprise feature +> +> Flag prerequisites is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +List dependent flags across all environments for the flag specified in the path parameters. A dependent flag is a flag that uses another flag as a prerequisite. To learn more, read [Flag prerequisites](https://launchdarkly.com/docs/home/flags/prereqs). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetDependentFlagsRequest +*/ +func (a *FeatureFlagsBetaApiService) GetDependentFlags(ctx context.Context, projectKey string, featureFlagKey string) ApiGetDependentFlagsRequest { + return ApiGetDependentFlagsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return MultiEnvironmentDependentFlags +func (a *FeatureFlagsBetaApiService) GetDependentFlagsExecute(r ApiGetDependentFlagsRequest) (*MultiEnvironmentDependentFlags, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MultiEnvironmentDependentFlags + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsBetaApiService.GetDependentFlags") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/dependent-flags" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetDependentFlagsByEnvRequest struct { + ctx context.Context + ApiService FeatureFlagsBetaApi + projectKey string + environmentKey string + featureFlagKey string +} + +func (r ApiGetDependentFlagsByEnvRequest) Execute() (*DependentFlagsByEnvironment, *http.Response, error) { + return r.ApiService.GetDependentFlagsByEnvExecute(r) +} + +/* +GetDependentFlagsByEnv List dependent feature flags by environment + +> ### Flag prerequisites is an Enterprise feature +> +> Flag prerequisites is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/). + +List dependent flags across all environments for the flag specified in the path parameters. A dependent flag is a flag that uses another flag as a prerequisite. To learn more, read [Flag prerequisites](https://launchdarkly.com/docs/home/flags/prereqs). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetDependentFlagsByEnvRequest +*/ +func (a *FeatureFlagsBetaApiService) GetDependentFlagsByEnv(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetDependentFlagsByEnvRequest { + return ApiGetDependentFlagsByEnvRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return DependentFlagsByEnvironment +func (a *FeatureFlagsBetaApiService) GetDependentFlagsByEnvExecute(r ApiGetDependentFlagsByEnvRequest) (*DependentFlagsByEnvironment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *DependentFlagsByEnvironment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FeatureFlagsBetaApiService.GetDependentFlagsByEnv") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{environmentKey}/{featureFlagKey}/dependent-flags" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_import_configurations_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_import_configurations_beta.go new file mode 100644 index 00000000..f8d0f51f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_import_configurations_beta.go @@ -0,0 +1,1202 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FlagImportConfigurationsBetaApi interface { + + /* + CreateFlagImportConfiguration Create a flag import configuration + + Create a new flag import configuration. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. The `config` object in the request body schema is described by the global integration settings, as specified by the formVariables in the manifest.json for this integration. It varies slightly based on the `integrationKey`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @return ApiCreateFlagImportConfigurationRequest + */ + CreateFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string) ApiCreateFlagImportConfigurationRequest + + // CreateFlagImportConfigurationExecute executes the request + // @return FlagImportIntegration + CreateFlagImportConfigurationExecute(r ApiCreateFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) + + /* + DeleteFlagImportConfiguration Delete a flag import configuration + + Delete a flag import configuration by ID. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiDeleteFlagImportConfigurationRequest + */ + DeleteFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiDeleteFlagImportConfigurationRequest + + // DeleteFlagImportConfigurationExecute executes the request + DeleteFlagImportConfigurationExecute(r ApiDeleteFlagImportConfigurationRequest) (*http.Response, error) + + /* + GetFlagImportConfiguration Get a single flag import configuration + + Get a single flag import configuration by ID. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key, for example, `split` + @param integrationId The integration ID + @return ApiGetFlagImportConfigurationRequest + */ + GetFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiGetFlagImportConfigurationRequest + + // GetFlagImportConfigurationExecute executes the request + // @return FlagImportIntegration + GetFlagImportConfigurationExecute(r ApiGetFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) + + /* + GetFlagImportConfigurations List all flag import configurations + + List all flag import configurations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagImportConfigurationsRequest + */ + GetFlagImportConfigurations(ctx context.Context) ApiGetFlagImportConfigurationsRequest + + // GetFlagImportConfigurationsExecute executes the request + // @return FlagImportIntegrationCollection + GetFlagImportConfigurationsExecute(r ApiGetFlagImportConfigurationsRequest) (*FlagImportIntegrationCollection, *http.Response, error) + + /* + PatchFlagImportConfiguration Update a flag import configuration + + Updating a flag import configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the import configuration fields that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array.

You can update the `config`, `tags`, and `name` of the flag import configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiPatchFlagImportConfigurationRequest + */ + PatchFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiPatchFlagImportConfigurationRequest + + // PatchFlagImportConfigurationExecute executes the request + // @return FlagImportIntegration + PatchFlagImportConfigurationExecute(r ApiPatchFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) + + /* + TriggerFlagImportJob Trigger a single flag import run + + Trigger a single flag import run for an existing flag import configuration. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiTriggerFlagImportJobRequest + */ + TriggerFlagImportJob(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiTriggerFlagImportJobRequest + + // TriggerFlagImportJobExecute executes the request + TriggerFlagImportJobExecute(r ApiTriggerFlagImportJobRequest) (*http.Response, error) +} + +// FlagImportConfigurationsBetaApiService FlagImportConfigurationsBetaApi service +type FlagImportConfigurationsBetaApiService service + +type ApiCreateFlagImportConfigurationRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi + projectKey string + integrationKey string + flagImportConfigurationPost *FlagImportConfigurationPost +} + +func (r ApiCreateFlagImportConfigurationRequest) FlagImportConfigurationPost(flagImportConfigurationPost FlagImportConfigurationPost) ApiCreateFlagImportConfigurationRequest { + r.flagImportConfigurationPost = &flagImportConfigurationPost + return r +} + +func (r ApiCreateFlagImportConfigurationRequest) Execute() (*FlagImportIntegration, *http.Response, error) { + return r.ApiService.CreateFlagImportConfigurationExecute(r) +} + +/* +CreateFlagImportConfiguration Create a flag import configuration + +Create a new flag import configuration. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. The `config` object in the request body schema is described by the global integration settings, as specified by the formVariables in the manifest.json for this integration. It varies slightly based on the `integrationKey`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @return ApiCreateFlagImportConfigurationRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) CreateFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string) ApiCreateFlagImportConfigurationRequest { + return ApiCreateFlagImportConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return FlagImportIntegration +func (a *FlagImportConfigurationsBetaApiService) CreateFlagImportConfigurationExecute(r ApiCreateFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagImportIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.CreateFlagImportConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagImportConfigurationPost == nil { + return localVarReturnValue, nil, reportError("flagImportConfigurationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagImportConfigurationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteFlagImportConfigurationRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi + projectKey string + integrationKey string + integrationId string +} + +func (r ApiDeleteFlagImportConfigurationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteFlagImportConfigurationExecute(r) +} + +/* +DeleteFlagImportConfiguration Delete a flag import configuration + +Delete a flag import configuration by ID. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiDeleteFlagImportConfigurationRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) DeleteFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiDeleteFlagImportConfigurationRequest { + return ApiDeleteFlagImportConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +func (a *FlagImportConfigurationsBetaApiService) DeleteFlagImportConfigurationExecute(r ApiDeleteFlagImportConfigurationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.DeleteFlagImportConfiguration") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetFlagImportConfigurationRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi + projectKey string + integrationKey string + integrationId string +} + +func (r ApiGetFlagImportConfigurationRequest) Execute() (*FlagImportIntegration, *http.Response, error) { + return r.ApiService.GetFlagImportConfigurationExecute(r) +} + +/* +GetFlagImportConfiguration Get a single flag import configuration + +Get a single flag import configuration by ID. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key, for example, `split` + @param integrationId The integration ID + @return ApiGetFlagImportConfigurationRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) GetFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiGetFlagImportConfigurationRequest { + return ApiGetFlagImportConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +// @return FlagImportIntegration +func (a *FlagImportConfigurationsBetaApiService) GetFlagImportConfigurationExecute(r ApiGetFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagImportIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.GetFlagImportConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFlagImportConfigurationsRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi +} + +func (r ApiGetFlagImportConfigurationsRequest) Execute() (*FlagImportIntegrationCollection, *http.Response, error) { + return r.ApiService.GetFlagImportConfigurationsExecute(r) +} + +/* +GetFlagImportConfigurations List all flag import configurations + +List all flag import configurations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagImportConfigurationsRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) GetFlagImportConfigurations(ctx context.Context) ApiGetFlagImportConfigurationsRequest { + return ApiGetFlagImportConfigurationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return FlagImportIntegrationCollection +func (a *FlagImportConfigurationsBetaApiService) GetFlagImportConfigurationsExecute(r ApiGetFlagImportConfigurationsRequest) (*FlagImportIntegrationCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagImportIntegrationCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.GetFlagImportConfigurations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchFlagImportConfigurationRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi + projectKey string + integrationKey string + integrationId string + patchOperation *[]PatchOperation +} + +func (r ApiPatchFlagImportConfigurationRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchFlagImportConfigurationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchFlagImportConfigurationRequest) Execute() (*FlagImportIntegration, *http.Response, error) { + return r.ApiService.PatchFlagImportConfigurationExecute(r) +} + +/* +PatchFlagImportConfiguration Update a flag import configuration + +Updating a flag import configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the import configuration fields that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array.

You can update the `config`, `tags`, and `name` of the flag import configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiPatchFlagImportConfigurationRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) PatchFlagImportConfiguration(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiPatchFlagImportConfigurationRequest { + return ApiPatchFlagImportConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +// @return FlagImportIntegration +func (a *FlagImportConfigurationsBetaApiService) PatchFlagImportConfigurationExecute(r ApiPatchFlagImportConfigurationRequest) (*FlagImportIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagImportIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.PatchFlagImportConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiTriggerFlagImportJobRequest struct { + ctx context.Context + ApiService FlagImportConfigurationsBetaApi + projectKey string + integrationKey string + integrationId string +} + +func (r ApiTriggerFlagImportJobRequest) Execute() (*http.Response, error) { + return r.ApiService.TriggerFlagImportJobExecute(r) +} + +/* +TriggerFlagImportJob Trigger a single flag import run + +Trigger a single flag import run for an existing flag import configuration. The `integrationKey` path parameter identifies the feature management system from which the import occurs, for example, `split`. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param integrationKey The integration key + @param integrationId The integration ID + @return ApiTriggerFlagImportJobRequest +*/ +func (a *FlagImportConfigurationsBetaApiService) TriggerFlagImportJob(ctx context.Context, projectKey string, integrationKey string, integrationId string) ApiTriggerFlagImportJobRequest { + return ApiTriggerFlagImportJobRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +func (a *FlagImportConfigurationsBetaApiService) TriggerFlagImportJobExecute(r ApiTriggerFlagImportJobRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagImportConfigurationsBetaApiService.TriggerFlagImportJob") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/flag-import/{projectKey}/{integrationKey}/{integrationId}/trigger" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_links_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_links_beta.go new file mode 100644 index 00000000..585fad1e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_links_beta.go @@ -0,0 +1,782 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FlagLinksBetaApi interface { + + /* + CreateFlagLink Create flag link + + Create a new flag link. Flag links let you reference external resources and associate them with your flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiCreateFlagLinkRequest + */ + CreateFlagLink(ctx context.Context, projectKey string, featureFlagKey string) ApiCreateFlagLinkRequest + + // CreateFlagLinkExecute executes the request + // @return FlagLinkRep + CreateFlagLinkExecute(r ApiCreateFlagLinkRequest) (*FlagLinkRep, *http.Response, error) + + /* + DeleteFlagLink Delete flag link + + Delete a flag link by ID or key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param id The flag link ID or Key + @return ApiDeleteFlagLinkRequest + */ + DeleteFlagLink(ctx context.Context, projectKey string, featureFlagKey string, id string) ApiDeleteFlagLinkRequest + + // DeleteFlagLinkExecute executes the request + DeleteFlagLinkExecute(r ApiDeleteFlagLinkRequest) (*http.Response, error) + + /* + GetFlagLinks List flag links + + Get a list of all flag links. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFlagLinksRequest + */ + GetFlagLinks(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFlagLinksRequest + + // GetFlagLinksExecute executes the request + // @return FlagLinkCollectionRep + GetFlagLinksExecute(r ApiGetFlagLinksRequest) (*FlagLinkCollectionRep, *http.Response, error) + + /* + UpdateFlagLink Update flag link + + Update a flag link. Updating a flag link uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param id The flag link ID + @return ApiUpdateFlagLinkRequest + */ + UpdateFlagLink(ctx context.Context, projectKey string, featureFlagKey string, id string) ApiUpdateFlagLinkRequest + + // UpdateFlagLinkExecute executes the request + // @return FlagLinkRep + UpdateFlagLinkExecute(r ApiUpdateFlagLinkRequest) (*FlagLinkRep, *http.Response, error) +} + +// FlagLinksBetaApiService FlagLinksBetaApi service +type FlagLinksBetaApiService service + +type ApiCreateFlagLinkRequest struct { + ctx context.Context + ApiService FlagLinksBetaApi + projectKey string + featureFlagKey string + flagLinkPost *FlagLinkPost +} + +func (r ApiCreateFlagLinkRequest) FlagLinkPost(flagLinkPost FlagLinkPost) ApiCreateFlagLinkRequest { + r.flagLinkPost = &flagLinkPost + return r +} + +func (r ApiCreateFlagLinkRequest) Execute() (*FlagLinkRep, *http.Response, error) { + return r.ApiService.CreateFlagLinkExecute(r) +} + +/* +CreateFlagLink Create flag link + +Create a new flag link. Flag links let you reference external resources and associate them with your flags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiCreateFlagLinkRequest +*/ +func (a *FlagLinksBetaApiService) CreateFlagLink(ctx context.Context, projectKey string, featureFlagKey string) ApiCreateFlagLinkRequest { + return ApiCreateFlagLinkRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FlagLinkRep +func (a *FlagLinksBetaApiService) CreateFlagLinkExecute(r ApiCreateFlagLinkRequest) (*FlagLinkRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagLinkRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagLinksBetaApiService.CreateFlagLink") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagLinkPost == nil { + return localVarReturnValue, nil, reportError("flagLinkPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagLinkPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteFlagLinkRequest struct { + ctx context.Context + ApiService FlagLinksBetaApi + projectKey string + featureFlagKey string + id string +} + +func (r ApiDeleteFlagLinkRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteFlagLinkExecute(r) +} + +/* +DeleteFlagLink Delete flag link + +Delete a flag link by ID or key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param id The flag link ID or Key + @return ApiDeleteFlagLinkRequest +*/ +func (a *FlagLinksBetaApiService) DeleteFlagLink(ctx context.Context, projectKey string, featureFlagKey string, id string) ApiDeleteFlagLinkRequest { + return ApiDeleteFlagLinkRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + id: id, + } +} + +// Execute executes the request +func (a *FlagLinksBetaApiService) DeleteFlagLinkExecute(r ApiDeleteFlagLinkRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagLinksBetaApiService.DeleteFlagLink") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetFlagLinksRequest struct { + ctx context.Context + ApiService FlagLinksBetaApi + projectKey string + featureFlagKey string +} + +func (r ApiGetFlagLinksRequest) Execute() (*FlagLinkCollectionRep, *http.Response, error) { + return r.ApiService.GetFlagLinksExecute(r) +} + +/* +GetFlagLinks List flag links + +Get a list of all flag links. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @return ApiGetFlagLinksRequest +*/ +func (a *FlagLinksBetaApiService) GetFlagLinks(ctx context.Context, projectKey string, featureFlagKey string) ApiGetFlagLinksRequest { + return ApiGetFlagLinksRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return FlagLinkCollectionRep +func (a *FlagLinksBetaApiService) GetFlagLinksExecute(r ApiGetFlagLinksRequest) (*FlagLinkCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagLinkCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagLinksBetaApiService.GetFlagLinks") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateFlagLinkRequest struct { + ctx context.Context + ApiService FlagLinksBetaApi + projectKey string + featureFlagKey string + id string + patchOperation *[]PatchOperation +} + +func (r ApiUpdateFlagLinkRequest) PatchOperation(patchOperation []PatchOperation) ApiUpdateFlagLinkRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiUpdateFlagLinkRequest) Execute() (*FlagLinkRep, *http.Response, error) { + return r.ApiService.UpdateFlagLinkExecute(r) +} + +/* +UpdateFlagLink Update flag link + +Update a flag link. Updating a flag link uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param id The flag link ID + @return ApiUpdateFlagLinkRequest +*/ +func (a *FlagLinksBetaApiService) UpdateFlagLink(ctx context.Context, projectKey string, featureFlagKey string, id string) ApiUpdateFlagLinkRequest { + return ApiUpdateFlagLinkRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + id: id, + } +} + +// Execute executes the request +// @return FlagLinkRep +func (a *FlagLinksBetaApiService) UpdateFlagLinkExecute(r ApiUpdateFlagLinkRequest) (*FlagLinkRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagLinkRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagLinksBetaApiService.UpdateFlagLink") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flag-links/projects/{projectKey}/flags/{featureFlagKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_triggers.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_triggers.go new file mode 100644 index 00000000..300aad54 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_flag_triggers.go @@ -0,0 +1,1126 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FlagTriggersApi interface { + + /* + CreateTriggerWorkflow Create flag trigger + + Create a new flag trigger. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiCreateTriggerWorkflowRequest + */ + CreateTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiCreateTriggerWorkflowRequest + + // CreateTriggerWorkflowExecute executes the request + // @return TriggerWorkflowRep + CreateTriggerWorkflowExecute(r ApiCreateTriggerWorkflowRequest) (*TriggerWorkflowRep, *http.Response, error) + + /* + DeleteTriggerWorkflow Delete flag trigger + + Delete a flag trigger by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @param id The flag trigger ID + @return ApiDeleteTriggerWorkflowRequest + */ + DeleteTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string, id string) ApiDeleteTriggerWorkflowRequest + + // DeleteTriggerWorkflowExecute executes the request + DeleteTriggerWorkflowExecute(r ApiDeleteTriggerWorkflowRequest) (*http.Response, error) + + /* + GetTriggerWorkflowById Get flag trigger by ID + + Get a flag trigger by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The flag trigger ID + @return ApiGetTriggerWorkflowByIdRequest + */ + GetTriggerWorkflowById(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetTriggerWorkflowByIdRequest + + // GetTriggerWorkflowByIdExecute executes the request + // @return TriggerWorkflowRep + GetTriggerWorkflowByIdExecute(r ApiGetTriggerWorkflowByIdRequest) (*TriggerWorkflowRep, *http.Response, error) + + /* + GetTriggerWorkflows List flag triggers + + Get a list of all flag triggers. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetTriggerWorkflowsRequest + */ + GetTriggerWorkflows(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetTriggerWorkflowsRequest + + // GetTriggerWorkflowsExecute executes the request + // @return TriggerWorkflowCollectionRep + GetTriggerWorkflowsExecute(r ApiGetTriggerWorkflowsRequest) (*TriggerWorkflowCollectionRep, *http.Response, error) + + /* + PatchTriggerWorkflow Update flag trigger + + Update a flag trigger. Updating a flag trigger uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating flag triggers. + +
+Click to expand instructions for updating flag triggers + +#### replaceTriggerActionInstructions + +Removes the existing trigger action and replaces it with the new instructions. + +##### Parameters + +- `value`: An array of the new `kind`s of actions to perform when triggering. Supported flag actions are `turnFlagOn` and `turnFlagOff`. + +Here's an example that replaces the existing action with new instructions to turn flag targeting off: + +```json +{ + "instructions": [ + { + "kind": "replaceTriggerActionInstructions", + "value": [ {"kind": "turnFlagOff"} ] + } + ] +} +``` + +#### cycleTriggerUrl + +Generates a new URL for this trigger. You must update any clients using the trigger to use this new URL. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "cycleTriggerUrl" }] +} +``` + +#### disableTrigger + +Disables the trigger. This saves the trigger configuration, but the trigger stops running. To re-enable, use `enableTrigger`. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "disableTrigger" }] +} +``` + +#### enableTrigger + +Enables the trigger. If you previously disabled the trigger, it begins running again. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "enableTrigger" }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @param id The flag trigger ID + @return ApiPatchTriggerWorkflowRequest + */ + PatchTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string, id string) ApiPatchTriggerWorkflowRequest + + // PatchTriggerWorkflowExecute executes the request + // @return TriggerWorkflowRep + PatchTriggerWorkflowExecute(r ApiPatchTriggerWorkflowRequest) (*TriggerWorkflowRep, *http.Response, error) +} + +// FlagTriggersApiService FlagTriggersApi service +type FlagTriggersApiService service + +type ApiCreateTriggerWorkflowRequest struct { + ctx context.Context + ApiService FlagTriggersApi + projectKey string + environmentKey string + featureFlagKey string + triggerPost *TriggerPost +} + +func (r ApiCreateTriggerWorkflowRequest) TriggerPost(triggerPost TriggerPost) ApiCreateTriggerWorkflowRequest { + r.triggerPost = &triggerPost + return r +} + +func (r ApiCreateTriggerWorkflowRequest) Execute() (*TriggerWorkflowRep, *http.Response, error) { + return r.ApiService.CreateTriggerWorkflowExecute(r) +} + +/* +CreateTriggerWorkflow Create flag trigger + +Create a new flag trigger. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiCreateTriggerWorkflowRequest +*/ +func (a *FlagTriggersApiService) CreateTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiCreateTriggerWorkflowRequest { + return ApiCreateTriggerWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return TriggerWorkflowRep +func (a *FlagTriggersApiService) CreateTriggerWorkflowExecute(r ApiCreateTriggerWorkflowRequest) (*TriggerWorkflowRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TriggerWorkflowRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagTriggersApiService.CreateTriggerWorkflow") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.triggerPost == nil { + return localVarReturnValue, nil, reportError("triggerPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.triggerPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteTriggerWorkflowRequest struct { + ctx context.Context + ApiService FlagTriggersApi + projectKey string + environmentKey string + featureFlagKey string + id string +} + +func (r ApiDeleteTriggerWorkflowRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteTriggerWorkflowExecute(r) +} + +/* +DeleteTriggerWorkflow Delete flag trigger + +Delete a flag trigger by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @param id The flag trigger ID + @return ApiDeleteTriggerWorkflowRequest +*/ +func (a *FlagTriggersApiService) DeleteTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string, id string) ApiDeleteTriggerWorkflowRequest { + return ApiDeleteTriggerWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + id: id, + } +} + +// Execute executes the request +func (a *FlagTriggersApiService) DeleteTriggerWorkflowExecute(r ApiDeleteTriggerWorkflowRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagTriggersApiService.DeleteTriggerWorkflow") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetTriggerWorkflowByIdRequest struct { + ctx context.Context + ApiService FlagTriggersApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiGetTriggerWorkflowByIdRequest) Execute() (*TriggerWorkflowRep, *http.Response, error) { + return r.ApiService.GetTriggerWorkflowByIdExecute(r) +} + +/* +GetTriggerWorkflowById Get flag trigger by ID + +Get a flag trigger by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The flag trigger ID + @return ApiGetTriggerWorkflowByIdRequest +*/ +func (a *FlagTriggersApiService) GetTriggerWorkflowById(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetTriggerWorkflowByIdRequest { + return ApiGetTriggerWorkflowByIdRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return TriggerWorkflowRep +func (a *FlagTriggersApiService) GetTriggerWorkflowByIdExecute(r ApiGetTriggerWorkflowByIdRequest) (*TriggerWorkflowRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TriggerWorkflowRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagTriggersApiService.GetTriggerWorkflowById") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetTriggerWorkflowsRequest struct { + ctx context.Context + ApiService FlagTriggersApi + projectKey string + environmentKey string + featureFlagKey string +} + +func (r ApiGetTriggerWorkflowsRequest) Execute() (*TriggerWorkflowCollectionRep, *http.Response, error) { + return r.ApiService.GetTriggerWorkflowsExecute(r) +} + +/* +GetTriggerWorkflows List flag triggers + +Get a list of all flag triggers. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @return ApiGetTriggerWorkflowsRequest +*/ +func (a *FlagTriggersApiService) GetTriggerWorkflows(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string) ApiGetTriggerWorkflowsRequest { + return ApiGetTriggerWorkflowsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return TriggerWorkflowCollectionRep +func (a *FlagTriggersApiService) GetTriggerWorkflowsExecute(r ApiGetTriggerWorkflowsRequest) (*TriggerWorkflowCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TriggerWorkflowCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagTriggersApiService.GetTriggerWorkflows") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchTriggerWorkflowRequest struct { + ctx context.Context + ApiService FlagTriggersApi + projectKey string + environmentKey string + featureFlagKey string + id string + flagTriggerInput *FlagTriggerInput +} + +func (r ApiPatchTriggerWorkflowRequest) FlagTriggerInput(flagTriggerInput FlagTriggerInput) ApiPatchTriggerWorkflowRequest { + r.flagTriggerInput = &flagTriggerInput + return r +} + +func (r ApiPatchTriggerWorkflowRequest) Execute() (*TriggerWorkflowRep, *http.Response, error) { + return r.ApiService.PatchTriggerWorkflowExecute(r) +} + +/* +PatchTriggerWorkflow Update flag trigger + +Update a flag trigger. Updating a flag trigger uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating flag triggers. + +
+Click to expand instructions for updating flag triggers + +#### replaceTriggerActionInstructions + +Removes the existing trigger action and replaces it with the new instructions. + +##### Parameters + +- `value`: An array of the new `kind`s of actions to perform when triggering. Supported flag actions are `turnFlagOn` and `turnFlagOff`. + +Here's an example that replaces the existing action with new instructions to turn flag targeting off: + +```json +{ + "instructions": [ + { + "kind": "replaceTriggerActionInstructions", + "value": [ {"kind": "turnFlagOff"} ] + } + ] +} +``` + +#### cycleTriggerUrl + +Generates a new URL for this trigger. You must update any clients using the trigger to use this new URL. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "cycleTriggerUrl" }] +} +``` + +#### disableTrigger + +Disables the trigger. This saves the trigger configuration, but the trigger stops running. To re-enable, use `enableTrigger`. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "disableTrigger" }] +} +``` + +#### enableTrigger + +Enables the trigger. If you previously disabled the trigger, it begins running again. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "enableTrigger" }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param featureFlagKey The feature flag key + @param id The flag trigger ID + @return ApiPatchTriggerWorkflowRequest +*/ +func (a *FlagTriggersApiService) PatchTriggerWorkflow(ctx context.Context, projectKey string, environmentKey string, featureFlagKey string, id string) ApiPatchTriggerWorkflowRequest { + return ApiPatchTriggerWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + featureFlagKey: featureFlagKey, + id: id, + } +} + +// Execute executes the request +// @return TriggerWorkflowRep +func (a *FlagTriggersApiService) PatchTriggerWorkflowExecute(r ApiPatchTriggerWorkflowRequest) (*TriggerWorkflowRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TriggerWorkflowRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FlagTriggersApiService.PatchTriggerWorkflow") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{featureFlagKey}/triggers/{environmentKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagTriggerInput == nil { + return localVarReturnValue, nil, reportError("flagTriggerInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagTriggerInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_follow_flags.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_follow_flags.go new file mode 100644 index 00000000..52b2211f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_follow_flags.go @@ -0,0 +1,733 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type FollowFlagsApi interface { + + /* + DeleteFlagFollower Remove a member as a follower of a flag in a project and environment + + Remove a member as a follower to a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param memberId The memberId of the member to remove as a follower of the flag. Reader roles can only remove themselves. + @return ApiDeleteFlagFollowerRequest + */ + DeleteFlagFollower(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, memberId string) ApiDeleteFlagFollowerRequest + + // DeleteFlagFollowerExecute executes the request + DeleteFlagFollowerExecute(r ApiDeleteFlagFollowerRequest) (*http.Response, error) + + /* + GetFlagFollowers Get followers of a flag in a project and environment + + Get a list of members following a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetFlagFollowersRequest + */ + GetFlagFollowers(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetFlagFollowersRequest + + // GetFlagFollowersExecute executes the request + // @return FlagFollowersGetRep + GetFlagFollowersExecute(r ApiGetFlagFollowersRequest) (*FlagFollowersGetRep, *http.Response, error) + + /* + GetFollowersByProjEnv Get followers of all flags in a given project and environment + + Get followers of all flags in a given environment and project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetFollowersByProjEnvRequest + */ + GetFollowersByProjEnv(ctx context.Context, projectKey string, environmentKey string) ApiGetFollowersByProjEnvRequest + + // GetFollowersByProjEnvExecute executes the request + // @return FlagFollowersByProjEnvGetRep + GetFollowersByProjEnvExecute(r ApiGetFollowersByProjEnvRequest) (*FlagFollowersByProjEnvGetRep, *http.Response, error) + + /* + PutFlagFollower Add a member as a follower of a flag in a project and environment + + Add a member as a follower to a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param memberId The memberId of the member to add as a follower of the flag. Reader roles can only add themselves. + @return ApiPutFlagFollowerRequest + */ + PutFlagFollower(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, memberId string) ApiPutFlagFollowerRequest + + // PutFlagFollowerExecute executes the request + PutFlagFollowerExecute(r ApiPutFlagFollowerRequest) (*http.Response, error) +} + +// FollowFlagsApiService FollowFlagsApi service +type FollowFlagsApiService service + +type ApiDeleteFlagFollowerRequest struct { + ctx context.Context + ApiService FollowFlagsApi + projectKey string + featureFlagKey string + environmentKey string + memberId string +} + +func (r ApiDeleteFlagFollowerRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteFlagFollowerExecute(r) +} + +/* +DeleteFlagFollower Remove a member as a follower of a flag in a project and environment + +Remove a member as a follower to a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param memberId The memberId of the member to remove as a follower of the flag. Reader roles can only remove themselves. + @return ApiDeleteFlagFollowerRequest +*/ +func (a *FollowFlagsApiService) DeleteFlagFollower(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, memberId string) ApiDeleteFlagFollowerRequest { + return ApiDeleteFlagFollowerRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + memberId: memberId, + } +} + +// Execute executes the request +func (a *FollowFlagsApiService) DeleteFlagFollowerExecute(r ApiDeleteFlagFollowerRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FollowFlagsApiService.DeleteFlagFollower") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers/{memberId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"memberId"+"}", url.PathEscape(parameterToString(r.memberId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetFlagFollowersRequest struct { + ctx context.Context + ApiService FollowFlagsApi + projectKey string + featureFlagKey string + environmentKey string +} + +func (r ApiGetFlagFollowersRequest) Execute() (*FlagFollowersGetRep, *http.Response, error) { + return r.ApiService.GetFlagFollowersExecute(r) +} + +/* +GetFlagFollowers Get followers of a flag in a project and environment + +Get a list of members following a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetFlagFollowersRequest +*/ +func (a *FollowFlagsApiService) GetFlagFollowers(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetFlagFollowersRequest { + return ApiGetFlagFollowersRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FlagFollowersGetRep +func (a *FollowFlagsApiService) GetFlagFollowersExecute(r ApiGetFlagFollowersRequest) (*FlagFollowersGetRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagFollowersGetRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FollowFlagsApiService.GetFlagFollowers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFollowersByProjEnvRequest struct { + ctx context.Context + ApiService FollowFlagsApi + projectKey string + environmentKey string +} + +func (r ApiGetFollowersByProjEnvRequest) Execute() (*FlagFollowersByProjEnvGetRep, *http.Response, error) { + return r.ApiService.GetFollowersByProjEnvExecute(r) +} + +/* +GetFollowersByProjEnv Get followers of all flags in a given project and environment + +Get followers of all flags in a given environment and project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetFollowersByProjEnvRequest +*/ +func (a *FollowFlagsApiService) GetFollowersByProjEnv(ctx context.Context, projectKey string, environmentKey string) ApiGetFollowersByProjEnvRequest { + return ApiGetFollowersByProjEnvRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FlagFollowersByProjEnvGetRep +func (a *FollowFlagsApiService) GetFollowersByProjEnvExecute(r ApiGetFollowersByProjEnvRequest) (*FlagFollowersByProjEnvGetRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagFollowersByProjEnvGetRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FollowFlagsApiService.GetFollowersByProjEnv") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/followers" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutFlagFollowerRequest struct { + ctx context.Context + ApiService FollowFlagsApi + projectKey string + featureFlagKey string + environmentKey string + memberId string +} + +func (r ApiPutFlagFollowerRequest) Execute() (*http.Response, error) { + return r.ApiService.PutFlagFollowerExecute(r) +} + +/* +PutFlagFollower Add a member as a follower of a flag in a project and environment + +Add a member as a follower to a flag in a project and environment + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param memberId The memberId of the member to add as a follower of the flag. Reader roles can only add themselves. + @return ApiPutFlagFollowerRequest +*/ +func (a *FollowFlagsApiService) PutFlagFollower(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, memberId string) ApiPutFlagFollowerRequest { + return ApiPutFlagFollowerRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + memberId: memberId, + } +} + +// Execute executes the request +func (a *FollowFlagsApiService) PutFlagFollowerExecute(r ApiPutFlagFollowerRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FollowFlagsApiService.PutFlagFollower") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/followers/{memberId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"memberId"+"}", url.PathEscape(parameterToString(r.memberId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_holdouts_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_holdouts_beta.go new file mode 100644 index 00000000..054cf068 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_holdouts_beta.go @@ -0,0 +1,1187 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type HoldoutsBetaApi interface { + + /* + GetAllHoldouts Get all holdouts + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetAllHoldoutsRequest + */ + GetAllHoldouts(ctx context.Context, projectKey string, environmentKey string) ApiGetAllHoldoutsRequest + + // GetAllHoldoutsExecute executes the request + // @return HoldoutsCollectionRep + GetAllHoldoutsExecute(r ApiGetAllHoldoutsRequest) (*HoldoutsCollectionRep, *http.Response, error) + + /* + GetHoldout Get holdout + + Get details about a holdout. + +### Expanding the holdout response + +LaunchDarkly supports the following fields for expanding the "Get holdout" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `draftIteration` includes the iteration which has not been started yet, if any, for this holdout. +- `previousIterations` includes all iterations prior to the current iteration, for this holdout. By default only the current iteration is included in the response. +- `rel-draftIteration` includes the iteration which has not been started yet, if any, for the experiments related to this holdout. +- `rel-metrics` includes metrics for experiments related to this holdout. +- `rel-previousIterations` includes all iterations prior to the current iteration, for the experiments related to this holdout. +- `rel-secondaryMetrics` includes secondary metrics for experiments related to this holdout. +- `rel-treatments` includes all treatment and parameter details for experiments related to this holdout. +- `secondaryMetrics` includes secondary metrics for this holdout. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details for this holdout. By default treatment data is not included in the response. + +For example, `expand=draftIteration,rel-draftIteration` includes the `draftIteration` and `rel-draftIteration` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutKey The holdout experiment key + @return ApiGetHoldoutRequest + */ + GetHoldout(ctx context.Context, projectKey string, environmentKey string, holdoutKey string) ApiGetHoldoutRequest + + // GetHoldoutExecute executes the request + // @return HoldoutDetailRep + GetHoldoutExecute(r ApiGetHoldoutRequest) (*HoldoutDetailRep, *http.Response, error) + + /* + GetHoldoutById Get Holdout by Id + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutId The holdout experiment ID + @return ApiGetHoldoutByIdRequest + */ + GetHoldoutById(ctx context.Context, projectKey string, environmentKey string, holdoutId string) ApiGetHoldoutByIdRequest + + // GetHoldoutByIdExecute executes the request + // @return HoldoutRep + GetHoldoutByIdExecute(r ApiGetHoldoutByIdRequest) (*HoldoutRep, *http.Response, error) + + /* + PatchHoldout Patch holdout + + Updates an existing holdout, and returns the updated holdout. Updating holdouts uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating holdouts. + +
+Click to expand instructions for updating holdouts + +#### endHoldout + +Ends a holdout. + +##### Parameters + +None. + +Here's an example: + +```json +{ + "comment": "Optional comment describing why the holdout is ending", + "instructions": [{ + "kind": "endHoldout" + }] +} +``` + +#### removeExperiment + +Removes an experiment from a holdout. + +##### Parameters + +- `value`: The key of the experiment to remove + +Here's an example: + +```json +{ + "comment": "Optional comment describing the change", + "instructions": [{ + "kind": "removeExperiment", + "value": "experiment-key" + }] +} +``` + +#### updateDescription + +Updates the description of the holdout. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "comment": "Optional comment describing the update", + "instructions": [{ + "kind": "updateDescription", + "value": "Updated holdout description" + }] +} +``` + +#### updateName + +Updates the name of the holdout. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "comment": "Optional comment describing the update", + "instructions": [{ + "kind": "updateName", + "value": "Updated holdout name" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutKey The holdout key + @return ApiPatchHoldoutRequest + */ + PatchHoldout(ctx context.Context, projectKey string, environmentKey string, holdoutKey string) ApiPatchHoldoutRequest + + // PatchHoldoutExecute executes the request + // @return HoldoutRep + PatchHoldoutExecute(r ApiPatchHoldoutRequest) (*HoldoutRep, *http.Response, error) + + /* + PostHoldout Create holdout + + Create a new holdout in the specified project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostHoldoutRequest + */ + PostHoldout(ctx context.Context, projectKey string, environmentKey string) ApiPostHoldoutRequest + + // PostHoldoutExecute executes the request + // @return HoldoutRep + PostHoldoutExecute(r ApiPostHoldoutRequest) (*HoldoutRep, *http.Response, error) +} + +// HoldoutsBetaApiService HoldoutsBetaApi service +type HoldoutsBetaApiService service + +type ApiGetAllHoldoutsRequest struct { + ctx context.Context + ApiService HoldoutsBetaApi + projectKey string + environmentKey string + limit *int64 + offset *int64 +} + +// The number of holdouts to return in the response. Defaults to 20 +func (r ApiGetAllHoldoutsRequest) Limit(limit int64) ApiGetAllHoldoutsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an `offset` of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetAllHoldoutsRequest) Offset(offset int64) ApiGetAllHoldoutsRequest { + r.offset = &offset + return r +} + +func (r ApiGetAllHoldoutsRequest) Execute() (*HoldoutsCollectionRep, *http.Response, error) { + return r.ApiService.GetAllHoldoutsExecute(r) +} + +/* +GetAllHoldouts Get all holdouts + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetAllHoldoutsRequest +*/ +func (a *HoldoutsBetaApiService) GetAllHoldouts(ctx context.Context, projectKey string, environmentKey string) ApiGetAllHoldoutsRequest { + return ApiGetAllHoldoutsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return HoldoutsCollectionRep +func (a *HoldoutsBetaApiService) GetAllHoldoutsExecute(r ApiGetAllHoldoutsRequest) (*HoldoutsCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *HoldoutsCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HoldoutsBetaApiService.GetAllHoldouts") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetHoldoutRequest struct { + ctx context.Context + ApiService HoldoutsBetaApi + projectKey string + environmentKey string + holdoutKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. Supported fields are explained above. Holdout experiment expansion fields have no prefix. Related experiment expansion fields have `rel-` as a prefix. +func (r ApiGetHoldoutRequest) Expand(expand string) ApiGetHoldoutRequest { + r.expand = &expand + return r +} + +func (r ApiGetHoldoutRequest) Execute() (*HoldoutDetailRep, *http.Response, error) { + return r.ApiService.GetHoldoutExecute(r) +} + +/* +GetHoldout Get holdout + +Get details about a holdout. + +### Expanding the holdout response + +LaunchDarkly supports the following fields for expanding the "Get holdout" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `draftIteration` includes the iteration which has not been started yet, if any, for this holdout. +- `previousIterations` includes all iterations prior to the current iteration, for this holdout. By default only the current iteration is included in the response. +- `rel-draftIteration` includes the iteration which has not been started yet, if any, for the experiments related to this holdout. +- `rel-metrics` includes metrics for experiments related to this holdout. +- `rel-previousIterations` includes all iterations prior to the current iteration, for the experiments related to this holdout. +- `rel-secondaryMetrics` includes secondary metrics for experiments related to this holdout. +- `rel-treatments` includes all treatment and parameter details for experiments related to this holdout. +- `secondaryMetrics` includes secondary metrics for this holdout. By default only the primary metric is included in the response. +- `treatments` includes all treatment and parameter details for this holdout. By default treatment data is not included in the response. + +For example, `expand=draftIteration,rel-draftIteration` includes the `draftIteration` and `rel-draftIteration` fields in the response. If fields that you request with the `expand` query parameter are empty, they are not included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutKey The holdout experiment key + @return ApiGetHoldoutRequest +*/ +func (a *HoldoutsBetaApiService) GetHoldout(ctx context.Context, projectKey string, environmentKey string, holdoutKey string) ApiGetHoldoutRequest { + return ApiGetHoldoutRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + holdoutKey: holdoutKey, + } +} + +// Execute executes the request +// @return HoldoutDetailRep +func (a *HoldoutsBetaApiService) GetHoldoutExecute(r ApiGetHoldoutRequest) (*HoldoutDetailRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *HoldoutDetailRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HoldoutsBetaApiService.GetHoldout") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/{holdoutKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"holdoutKey"+"}", url.PathEscape(parameterToString(r.holdoutKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetHoldoutByIdRequest struct { + ctx context.Context + ApiService HoldoutsBetaApi + projectKey string + environmentKey string + holdoutId string +} + +func (r ApiGetHoldoutByIdRequest) Execute() (*HoldoutRep, *http.Response, error) { + return r.ApiService.GetHoldoutByIdExecute(r) +} + +/* +GetHoldoutById Get Holdout by Id + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutId The holdout experiment ID + @return ApiGetHoldoutByIdRequest +*/ +func (a *HoldoutsBetaApiService) GetHoldoutById(ctx context.Context, projectKey string, environmentKey string, holdoutId string) ApiGetHoldoutByIdRequest { + return ApiGetHoldoutByIdRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + holdoutId: holdoutId, + } +} + +// Execute executes the request +// @return HoldoutRep +func (a *HoldoutsBetaApiService) GetHoldoutByIdExecute(r ApiGetHoldoutByIdRequest) (*HoldoutRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *HoldoutRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HoldoutsBetaApiService.GetHoldoutById") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/id/{holdoutId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"holdoutId"+"}", url.PathEscape(parameterToString(r.holdoutId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchHoldoutRequest struct { + ctx context.Context + ApiService HoldoutsBetaApi + projectKey string + environmentKey string + holdoutKey string + holdoutPatchInput *HoldoutPatchInput +} + +func (r ApiPatchHoldoutRequest) HoldoutPatchInput(holdoutPatchInput HoldoutPatchInput) ApiPatchHoldoutRequest { + r.holdoutPatchInput = &holdoutPatchInput + return r +} + +func (r ApiPatchHoldoutRequest) Execute() (*HoldoutRep, *http.Response, error) { + return r.ApiService.PatchHoldoutExecute(r) +} + +/* +PatchHoldout Patch holdout + +Updates an existing holdout, and returns the updated holdout. Updating holdouts uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating holdouts. + +
+Click to expand instructions for updating holdouts + +#### endHoldout + +Ends a holdout. + +##### Parameters + +None. + +Here's an example: + +```json +{ + "comment": "Optional comment describing why the holdout is ending", + "instructions": [{ + "kind": "endHoldout" + }] +} +``` + +#### removeExperiment + +Removes an experiment from a holdout. + +##### Parameters + +- `value`: The key of the experiment to remove + +Here's an example: + +```json +{ + "comment": "Optional comment describing the change", + "instructions": [{ + "kind": "removeExperiment", + "value": "experiment-key" + }] +} +``` + +#### updateDescription + +Updates the description of the holdout. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "comment": "Optional comment describing the update", + "instructions": [{ + "kind": "updateDescription", + "value": "Updated holdout description" + }] +} +``` + +#### updateName + +Updates the name of the holdout. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "comment": "Optional comment describing the update", + "instructions": [{ + "kind": "updateName", + "value": "Updated holdout name" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param holdoutKey The holdout key + @return ApiPatchHoldoutRequest +*/ +func (a *HoldoutsBetaApiService) PatchHoldout(ctx context.Context, projectKey string, environmentKey string, holdoutKey string) ApiPatchHoldoutRequest { + return ApiPatchHoldoutRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + holdoutKey: holdoutKey, + } +} + +// Execute executes the request +// @return HoldoutRep +func (a *HoldoutsBetaApiService) PatchHoldoutExecute(r ApiPatchHoldoutRequest) (*HoldoutRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *HoldoutRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HoldoutsBetaApiService.PatchHoldout") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts/{holdoutKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"holdoutKey"+"}", url.PathEscape(parameterToString(r.holdoutKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.holdoutPatchInput == nil { + return localVarReturnValue, nil, reportError("holdoutPatchInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.holdoutPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostHoldoutRequest struct { + ctx context.Context + ApiService HoldoutsBetaApi + projectKey string + environmentKey string + holdoutPostRequest *HoldoutPostRequest +} + +func (r ApiPostHoldoutRequest) HoldoutPostRequest(holdoutPostRequest HoldoutPostRequest) ApiPostHoldoutRequest { + r.holdoutPostRequest = &holdoutPostRequest + return r +} + +func (r ApiPostHoldoutRequest) Execute() (*HoldoutRep, *http.Response, error) { + return r.ApiService.PostHoldoutExecute(r) +} + +/* +PostHoldout Create holdout + +Create a new holdout in the specified project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostHoldoutRequest +*/ +func (a *HoldoutsBetaApiService) PostHoldout(ctx context.Context, projectKey string, environmentKey string) ApiPostHoldoutRequest { + return ApiPostHoldoutRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return HoldoutRep +func (a *HoldoutsBetaApiService) PostHoldoutExecute(r ApiPostHoldoutRequest) (*HoldoutRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *HoldoutRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "HoldoutsBetaApiService.PostHoldout") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/holdouts" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.holdoutPostRequest == nil { + return localVarReturnValue, nil, reportError("holdoutPostRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.holdoutPostRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_charts_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_charts_beta.go new file mode 100644 index 00000000..4d74b773 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_charts_beta.go @@ -0,0 +1,1349 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "time" +) + + +type InsightsChartsBetaApi interface { + + /* + GetDeploymentFrequencyChart Get deployment frequency chart data + + Get deployment frequency chart data. Engineering insights displays deployment frequency data in the [deployment frequency metric view](https://launchdarkly.com/docs/home/observability/deployments). + +### Expanding the chart response + +LaunchDarkly supports expanding the chart response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `metrics` includes details on the metrics related to deployment frequency + +For example, use `?expand=metrics` to include the `metrics` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDeploymentFrequencyChartRequest + */ + GetDeploymentFrequencyChart(ctx context.Context) ApiGetDeploymentFrequencyChartRequest + + // GetDeploymentFrequencyChartExecute executes the request + // @return InsightsChart + GetDeploymentFrequencyChartExecute(r ApiGetDeploymentFrequencyChartRequest) (*InsightsChart, *http.Response, error) + + /* + GetFlagStatusChart Get flag status chart data + + Get flag status chart data. To learn more, read [Flag statuses](https://launchdarkly.com/docs/home/observability/flag-health#flag-statuses). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagStatusChartRequest + */ + GetFlagStatusChart(ctx context.Context) ApiGetFlagStatusChartRequest + + // GetFlagStatusChartExecute executes the request + // @return InsightsChart + GetFlagStatusChartExecute(r ApiGetFlagStatusChartRequest) (*InsightsChart, *http.Response, error) + + /* + GetLeadTimeChart Get lead time chart data + + Get lead time chart data. The engineering insights UI displays lead time data in the [lead time metric view](https://launchdarkly.com/docs/home/observability/lead-time). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetLeadTimeChartRequest + */ + GetLeadTimeChart(ctx context.Context) ApiGetLeadTimeChartRequest + + // GetLeadTimeChartExecute executes the request + // @return InsightsChart + GetLeadTimeChartExecute(r ApiGetLeadTimeChartRequest) (*InsightsChart, *http.Response, error) + + /* + GetReleaseFrequencyChart Get release frequency chart data + + Get release frequency chart data. Engineering insights displays release frequency data in the [release frequency metric view](https://launchdarkly.com/docs/home/observability/releases). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetReleaseFrequencyChartRequest + */ + GetReleaseFrequencyChart(ctx context.Context) ApiGetReleaseFrequencyChartRequest + + // GetReleaseFrequencyChartExecute executes the request + // @return InsightsChart + GetReleaseFrequencyChartExecute(r ApiGetReleaseFrequencyChartRequest) (*InsightsChart, *http.Response, error) + + /* + GetStaleFlagsChart Get stale flags chart data + + Get stale flags chart data. Engineering insights displays stale flags data in the [flag health metric view](https://launchdarkly.com/docs/home/observability/flag-health). + +### Expanding the chart response + +LaunchDarkly supports expanding the chart response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `metrics` includes details on the metrics related to stale flags + +For example, use `?expand=metrics` to include the `metrics` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetStaleFlagsChartRequest + */ + GetStaleFlagsChart(ctx context.Context) ApiGetStaleFlagsChartRequest + + // GetStaleFlagsChartExecute executes the request + // @return InsightsChart + GetStaleFlagsChartExecute(r ApiGetStaleFlagsChartRequest) (*InsightsChart, *http.Response, error) +} + +// InsightsChartsBetaApiService InsightsChartsBetaApi service +type InsightsChartsBetaApiService service + +type ApiGetDeploymentFrequencyChartRequest struct { + ctx context.Context + ApiService InsightsChartsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + from *time.Time + to *time.Time + bucketType *string + bucketMs *int64 + groupBy *string + expand *string +} + +// The project key +func (r ApiGetDeploymentFrequencyChartRequest) ProjectKey(projectKey string) ApiGetDeploymentFrequencyChartRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetDeploymentFrequencyChartRequest) EnvironmentKey(environmentKey string) ApiGetDeploymentFrequencyChartRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetDeploymentFrequencyChartRequest) ApplicationKey(applicationKey string) ApiGetDeploymentFrequencyChartRequest { + r.applicationKey = &applicationKey + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetDeploymentFrequencyChartRequest) From(from time.Time) ApiGetDeploymentFrequencyChartRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetDeploymentFrequencyChartRequest) To(to time.Time) ApiGetDeploymentFrequencyChartRequest { + r.to = &to + return r +} + +// Specify type of bucket. Options: `rolling`, `hour`, `day`. Default: `rolling`. +func (r ApiGetDeploymentFrequencyChartRequest) BucketType(bucketType string) ApiGetDeploymentFrequencyChartRequest { + r.bucketType = &bucketType + return r +} + +// Duration of intervals for x-axis in milliseconds. Default value is one day (`86400000` milliseconds). +func (r ApiGetDeploymentFrequencyChartRequest) BucketMs(bucketMs int64) ApiGetDeploymentFrequencyChartRequest { + r.bucketMs = &bucketMs + return r +} + +// Options: `application`, `kind` +func (r ApiGetDeploymentFrequencyChartRequest) GroupBy(groupBy string) ApiGetDeploymentFrequencyChartRequest { + r.groupBy = &groupBy + return r +} + +// Options: `metrics` +func (r ApiGetDeploymentFrequencyChartRequest) Expand(expand string) ApiGetDeploymentFrequencyChartRequest { + r.expand = &expand + return r +} + +func (r ApiGetDeploymentFrequencyChartRequest) Execute() (*InsightsChart, *http.Response, error) { + return r.ApiService.GetDeploymentFrequencyChartExecute(r) +} + +/* +GetDeploymentFrequencyChart Get deployment frequency chart data + +Get deployment frequency chart data. Engineering insights displays deployment frequency data in the [deployment frequency metric view](https://launchdarkly.com/docs/home/observability/deployments). + +### Expanding the chart response + +LaunchDarkly supports expanding the chart response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `metrics` includes details on the metrics related to deployment frequency + +For example, use `?expand=metrics` to include the `metrics` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDeploymentFrequencyChartRequest +*/ +func (a *InsightsChartsBetaApiService) GetDeploymentFrequencyChart(ctx context.Context) ApiGetDeploymentFrequencyChartRequest { + return ApiGetDeploymentFrequencyChartRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsChart +func (a *InsightsChartsBetaApiService) GetDeploymentFrequencyChartExecute(r ApiGetDeploymentFrequencyChartRequest) (*InsightsChart, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsChart + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsChartsBetaApiService.GetDeploymentFrequencyChart") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/charts/deployments/frequency" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.projectKey != nil { + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + } + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.bucketType != nil { + localVarQueryParams.Add("bucketType", parameterToString(*r.bucketType, "")) + } + if r.bucketMs != nil { + localVarQueryParams.Add("bucketMs", parameterToString(*r.bucketMs, "")) + } + if r.groupBy != nil { + localVarQueryParams.Add("groupBy", parameterToString(*r.groupBy, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFlagStatusChartRequest struct { + ctx context.Context + ApiService InsightsChartsBetaApi + projectKey *string + environmentKey *string + applicationKey *string +} + +// The project key +func (r ApiGetFlagStatusChartRequest) ProjectKey(projectKey string) ApiGetFlagStatusChartRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetFlagStatusChartRequest) EnvironmentKey(environmentKey string) ApiGetFlagStatusChartRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetFlagStatusChartRequest) ApplicationKey(applicationKey string) ApiGetFlagStatusChartRequest { + r.applicationKey = &applicationKey + return r +} + +func (r ApiGetFlagStatusChartRequest) Execute() (*InsightsChart, *http.Response, error) { + return r.ApiService.GetFlagStatusChartExecute(r) +} + +/* +GetFlagStatusChart Get flag status chart data + +Get flag status chart data. To learn more, read [Flag statuses](https://launchdarkly.com/docs/home/observability/flag-health#flag-statuses). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagStatusChartRequest +*/ +func (a *InsightsChartsBetaApiService) GetFlagStatusChart(ctx context.Context) ApiGetFlagStatusChartRequest { + return ApiGetFlagStatusChartRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsChart +func (a *InsightsChartsBetaApiService) GetFlagStatusChartExecute(r ApiGetFlagStatusChartRequest) (*InsightsChart, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsChart + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsChartsBetaApiService.GetFlagStatusChart") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/charts/flags/status" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetLeadTimeChartRequest struct { + ctx context.Context + ApiService InsightsChartsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + from *int64 + to *int64 + bucketType *string + bucketMs *int64 + groupBy *string + expand *string +} + +// The project key +func (r ApiGetLeadTimeChartRequest) ProjectKey(projectKey string) ApiGetLeadTimeChartRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetLeadTimeChartRequest) EnvironmentKey(environmentKey string) ApiGetLeadTimeChartRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetLeadTimeChartRequest) ApplicationKey(applicationKey string) ApiGetLeadTimeChartRequest { + r.applicationKey = &applicationKey + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetLeadTimeChartRequest) From(from int64) ApiGetLeadTimeChartRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetLeadTimeChartRequest) To(to int64) ApiGetLeadTimeChartRequest { + r.to = &to + return r +} + +// Specify type of bucket. Options: `rolling`, `hour`, `day`. Default: `rolling`. +func (r ApiGetLeadTimeChartRequest) BucketType(bucketType string) ApiGetLeadTimeChartRequest { + r.bucketType = &bucketType + return r +} + +// Duration of intervals for x-axis in milliseconds. Default value is one day (`86400000` milliseconds). +func (r ApiGetLeadTimeChartRequest) BucketMs(bucketMs int64) ApiGetLeadTimeChartRequest { + r.bucketMs = &bucketMs + return r +} + +// Options: `application`, `stage`. Default: `stage`. +func (r ApiGetLeadTimeChartRequest) GroupBy(groupBy string) ApiGetLeadTimeChartRequest { + r.groupBy = &groupBy + return r +} + +// Options: `metrics`, `percentiles`. +func (r ApiGetLeadTimeChartRequest) Expand(expand string) ApiGetLeadTimeChartRequest { + r.expand = &expand + return r +} + +func (r ApiGetLeadTimeChartRequest) Execute() (*InsightsChart, *http.Response, error) { + return r.ApiService.GetLeadTimeChartExecute(r) +} + +/* +GetLeadTimeChart Get lead time chart data + +Get lead time chart data. The engineering insights UI displays lead time data in the [lead time metric view](https://launchdarkly.com/docs/home/observability/lead-time). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetLeadTimeChartRequest +*/ +func (a *InsightsChartsBetaApiService) GetLeadTimeChart(ctx context.Context) ApiGetLeadTimeChartRequest { + return ApiGetLeadTimeChartRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsChart +func (a *InsightsChartsBetaApiService) GetLeadTimeChartExecute(r ApiGetLeadTimeChartRequest) (*InsightsChart, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsChart + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsChartsBetaApiService.GetLeadTimeChart") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/charts/lead-time" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.bucketType != nil { + localVarQueryParams.Add("bucketType", parameterToString(*r.bucketType, "")) + } + if r.bucketMs != nil { + localVarQueryParams.Add("bucketMs", parameterToString(*r.bucketMs, "")) + } + if r.groupBy != nil { + localVarQueryParams.Add("groupBy", parameterToString(*r.groupBy, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetReleaseFrequencyChartRequest struct { + ctx context.Context + ApiService InsightsChartsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + hasExperiments *bool + global *string + groupBy *string + from *time.Time + to *time.Time + bucketType *string + bucketMs *int64 + expand *string +} + +// The project key +func (r ApiGetReleaseFrequencyChartRequest) ProjectKey(projectKey string) ApiGetReleaseFrequencyChartRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetReleaseFrequencyChartRequest) EnvironmentKey(environmentKey string) ApiGetReleaseFrequencyChartRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetReleaseFrequencyChartRequest) ApplicationKey(applicationKey string) ApiGetReleaseFrequencyChartRequest { + r.applicationKey = &applicationKey + return r +} + +// Filter events to those associated with an experiment (`true`) or without an experiment (`false`) +func (r ApiGetReleaseFrequencyChartRequest) HasExperiments(hasExperiments bool) ApiGetReleaseFrequencyChartRequest { + r.hasExperiments = &hasExperiments + return r +} + +// Filter to include or exclude global events. Default value is `include`. Options: `include`, `exclude` +func (r ApiGetReleaseFrequencyChartRequest) Global(global string) ApiGetReleaseFrequencyChartRequest { + r.global = &global + return r +} + +// Property to group results by. Options: `impact` +func (r ApiGetReleaseFrequencyChartRequest) GroupBy(groupBy string) ApiGetReleaseFrequencyChartRequest { + r.groupBy = &groupBy + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetReleaseFrequencyChartRequest) From(from time.Time) ApiGetReleaseFrequencyChartRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetReleaseFrequencyChartRequest) To(to time.Time) ApiGetReleaseFrequencyChartRequest { + r.to = &to + return r +} + +// Specify type of bucket. Options: `rolling`, `hour`, `day`. Default: `rolling`. +func (r ApiGetReleaseFrequencyChartRequest) BucketType(bucketType string) ApiGetReleaseFrequencyChartRequest { + r.bucketType = &bucketType + return r +} + +// Duration of intervals for x-axis in milliseconds. Default value is one day (`86400000` milliseconds). +func (r ApiGetReleaseFrequencyChartRequest) BucketMs(bucketMs int64) ApiGetReleaseFrequencyChartRequest { + r.bucketMs = &bucketMs + return r +} + +// Options: `metrics` +func (r ApiGetReleaseFrequencyChartRequest) Expand(expand string) ApiGetReleaseFrequencyChartRequest { + r.expand = &expand + return r +} + +func (r ApiGetReleaseFrequencyChartRequest) Execute() (*InsightsChart, *http.Response, error) { + return r.ApiService.GetReleaseFrequencyChartExecute(r) +} + +/* +GetReleaseFrequencyChart Get release frequency chart data + +Get release frequency chart data. Engineering insights displays release frequency data in the [release frequency metric view](https://launchdarkly.com/docs/home/observability/releases). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetReleaseFrequencyChartRequest +*/ +func (a *InsightsChartsBetaApiService) GetReleaseFrequencyChart(ctx context.Context) ApiGetReleaseFrequencyChartRequest { + return ApiGetReleaseFrequencyChartRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsChart +func (a *InsightsChartsBetaApiService) GetReleaseFrequencyChartExecute(r ApiGetReleaseFrequencyChartRequest) (*InsightsChart, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsChart + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsChartsBetaApiService.GetReleaseFrequencyChart") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/charts/releases/frequency" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.hasExperiments != nil { + localVarQueryParams.Add("hasExperiments", parameterToString(*r.hasExperiments, "")) + } + if r.global != nil { + localVarQueryParams.Add("global", parameterToString(*r.global, "")) + } + if r.groupBy != nil { + localVarQueryParams.Add("groupBy", parameterToString(*r.groupBy, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.bucketType != nil { + localVarQueryParams.Add("bucketType", parameterToString(*r.bucketType, "")) + } + if r.bucketMs != nil { + localVarQueryParams.Add("bucketMs", parameterToString(*r.bucketMs, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetStaleFlagsChartRequest struct { + ctx context.Context + ApiService InsightsChartsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + groupBy *string + maintainerId *string + maintainerTeamKey *string + expand *string +} + +// The project key +func (r ApiGetStaleFlagsChartRequest) ProjectKey(projectKey string) ApiGetStaleFlagsChartRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetStaleFlagsChartRequest) EnvironmentKey(environmentKey string) ApiGetStaleFlagsChartRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetStaleFlagsChartRequest) ApplicationKey(applicationKey string) ApiGetStaleFlagsChartRequest { + r.applicationKey = &applicationKey + return r +} + +// Property to group results by. Options: `maintainer` +func (r ApiGetStaleFlagsChartRequest) GroupBy(groupBy string) ApiGetStaleFlagsChartRequest { + r.groupBy = &groupBy + return r +} + +// Comma-separated list of individual maintainers to filter results. +func (r ApiGetStaleFlagsChartRequest) MaintainerId(maintainerId string) ApiGetStaleFlagsChartRequest { + r.maintainerId = &maintainerId + return r +} + +// Comma-separated list of team maintainer keys to filter results. +func (r ApiGetStaleFlagsChartRequest) MaintainerTeamKey(maintainerTeamKey string) ApiGetStaleFlagsChartRequest { + r.maintainerTeamKey = &maintainerTeamKey + return r +} + +// Options: `metrics` +func (r ApiGetStaleFlagsChartRequest) Expand(expand string) ApiGetStaleFlagsChartRequest { + r.expand = &expand + return r +} + +func (r ApiGetStaleFlagsChartRequest) Execute() (*InsightsChart, *http.Response, error) { + return r.ApiService.GetStaleFlagsChartExecute(r) +} + +/* +GetStaleFlagsChart Get stale flags chart data + +Get stale flags chart data. Engineering insights displays stale flags data in the [flag health metric view](https://launchdarkly.com/docs/home/observability/flag-health). + +### Expanding the chart response + +LaunchDarkly supports expanding the chart response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `metrics` includes details on the metrics related to stale flags + +For example, use `?expand=metrics` to include the `metrics` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetStaleFlagsChartRequest +*/ +func (a *InsightsChartsBetaApiService) GetStaleFlagsChart(ctx context.Context) ApiGetStaleFlagsChartRequest { + return ApiGetStaleFlagsChartRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsChart +func (a *InsightsChartsBetaApiService) GetStaleFlagsChartExecute(r ApiGetStaleFlagsChartRequest) (*InsightsChart, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsChart + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsChartsBetaApiService.GetStaleFlagsChart") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/charts/flags/stale" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.groupBy != nil { + localVarQueryParams.Add("groupBy", parameterToString(*r.groupBy, "")) + } + if r.maintainerId != nil { + localVarQueryParams.Add("maintainerId", parameterToString(*r.maintainerId, "")) + } + if r.maintainerTeamKey != nil { + localVarQueryParams.Add("maintainerTeamKey", parameterToString(*r.maintainerTeamKey, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_deployments_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_deployments_beta.go new file mode 100644 index 00000000..f37b22c8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_deployments_beta.go @@ -0,0 +1,926 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type InsightsDeploymentsBetaApi interface { + + /* + CreateDeploymentEvent Create deployment event + + Create deployment event + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateDeploymentEventRequest + */ + CreateDeploymentEvent(ctx context.Context) ApiCreateDeploymentEventRequest + + // CreateDeploymentEventExecute executes the request + CreateDeploymentEventExecute(r ApiCreateDeploymentEventRequest) (*http.Response, error) + + /* + GetDeployment Get deployment + + Get a deployment by ID. + +The deployment ID is returned as part of the [List deployments](https://launchdarkly.com/docs/api/insights-deployments-beta/get-deployments) response. It is the `id` field of each element in the `items` array. + +### Expanding the deployment response + +LaunchDarkly supports expanding the deployment response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `pullRequests` includes details on all of the pull requests associated with each deployment +* `flagReferences` includes details on all of the references to flags in each deployment + +For example, use `?expand=pullRequests` to include the `pullRequests` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param deploymentID The deployment ID + @return ApiGetDeploymentRequest + */ + GetDeployment(ctx context.Context, deploymentID string) ApiGetDeploymentRequest + + // GetDeploymentExecute executes the request + // @return DeploymentRep + GetDeploymentExecute(r ApiGetDeploymentRequest) (*DeploymentRep, *http.Response, error) + + /* + GetDeployments List deployments + + Get a list of deployments + +### Expanding the deployment collection response + +LaunchDarkly supports expanding the deployment collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `pullRequests` includes details on all of the pull requests associated with each deployment +* `flagReferences` includes details on all of the references to flags in each deployment + +For example, use `?expand=pullRequests` to include the `pullRequests` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDeploymentsRequest + */ + GetDeployments(ctx context.Context) ApiGetDeploymentsRequest + + // GetDeploymentsExecute executes the request + // @return DeploymentCollectionRep + GetDeploymentsExecute(r ApiGetDeploymentsRequest) (*DeploymentCollectionRep, *http.Response, error) + + /* + UpdateDeployment Update deployment + + Update a deployment by ID. Updating a deployment uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

The deployment ID is returned as part of the [List deployments](https://launchdarkly.com/docs/api/insights-deployments-beta/get-deployments) response. It is the `id` field of each element in the `items` array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param deploymentID The deployment ID + @return ApiUpdateDeploymentRequest + */ + UpdateDeployment(ctx context.Context, deploymentID string) ApiUpdateDeploymentRequest + + // UpdateDeploymentExecute executes the request + // @return DeploymentRep + UpdateDeploymentExecute(r ApiUpdateDeploymentRequest) (*DeploymentRep, *http.Response, error) +} + +// InsightsDeploymentsBetaApiService InsightsDeploymentsBetaApi service +type InsightsDeploymentsBetaApiService service + +type ApiCreateDeploymentEventRequest struct { + ctx context.Context + ApiService InsightsDeploymentsBetaApi + postDeploymentEventInput *PostDeploymentEventInput +} + +func (r ApiCreateDeploymentEventRequest) PostDeploymentEventInput(postDeploymentEventInput PostDeploymentEventInput) ApiCreateDeploymentEventRequest { + r.postDeploymentEventInput = &postDeploymentEventInput + return r +} + +func (r ApiCreateDeploymentEventRequest) Execute() (*http.Response, error) { + return r.ApiService.CreateDeploymentEventExecute(r) +} + +/* +CreateDeploymentEvent Create deployment event + +Create deployment event + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateDeploymentEventRequest +*/ +func (a *InsightsDeploymentsBetaApiService) CreateDeploymentEvent(ctx context.Context) ApiCreateDeploymentEventRequest { + return ApiCreateDeploymentEventRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +func (a *InsightsDeploymentsBetaApiService) CreateDeploymentEventExecute(r ApiCreateDeploymentEventRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsDeploymentsBetaApiService.CreateDeploymentEvent") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/deployment-events" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postDeploymentEventInput == nil { + return nil, reportError("postDeploymentEventInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postDeploymentEventInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetDeploymentRequest struct { + ctx context.Context + ApiService InsightsDeploymentsBetaApi + deploymentID string + expand *string +} + +// Expand properties in response. Options: `pullRequests`, `flagReferences` +func (r ApiGetDeploymentRequest) Expand(expand string) ApiGetDeploymentRequest { + r.expand = &expand + return r +} + +func (r ApiGetDeploymentRequest) Execute() (*DeploymentRep, *http.Response, error) { + return r.ApiService.GetDeploymentExecute(r) +} + +/* +GetDeployment Get deployment + +Get a deployment by ID. + +The deployment ID is returned as part of the [List deployments](https://launchdarkly.com/docs/api/insights-deployments-beta/get-deployments) response. It is the `id` field of each element in the `items` array. + +### Expanding the deployment response + +LaunchDarkly supports expanding the deployment response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `pullRequests` includes details on all of the pull requests associated with each deployment +* `flagReferences` includes details on all of the references to flags in each deployment + +For example, use `?expand=pullRequests` to include the `pullRequests` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param deploymentID The deployment ID + @return ApiGetDeploymentRequest +*/ +func (a *InsightsDeploymentsBetaApiService) GetDeployment(ctx context.Context, deploymentID string) ApiGetDeploymentRequest { + return ApiGetDeploymentRequest{ + ApiService: a, + ctx: ctx, + deploymentID: deploymentID, + } +} + +// Execute executes the request +// @return DeploymentRep +func (a *InsightsDeploymentsBetaApiService) GetDeploymentExecute(r ApiGetDeploymentRequest) (*DeploymentRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *DeploymentRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsDeploymentsBetaApiService.GetDeployment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/deployments/{deploymentID}" + localVarPath = strings.Replace(localVarPath, "{"+"deploymentID"+"}", url.PathEscape(parameterToString(r.deploymentID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetDeploymentsRequest struct { + ctx context.Context + ApiService InsightsDeploymentsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + limit *int64 + expand *string + from *int64 + to *int64 + after *string + before *string + kind *string + status *string +} + +// The project key +func (r ApiGetDeploymentsRequest) ProjectKey(projectKey string) ApiGetDeploymentsRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetDeploymentsRequest) EnvironmentKey(environmentKey string) ApiGetDeploymentsRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetDeploymentsRequest) ApplicationKey(applicationKey string) ApiGetDeploymentsRequest { + r.applicationKey = &applicationKey + return r +} + +// The number of deployments to return. Default is 20. Maximum allowed is 100. +func (r ApiGetDeploymentsRequest) Limit(limit int64) ApiGetDeploymentsRequest { + r.limit = &limit + return r +} + +// Expand properties in response. Options: `pullRequests`, `flagReferences` +func (r ApiGetDeploymentsRequest) Expand(expand string) ApiGetDeploymentsRequest { + r.expand = &expand + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetDeploymentsRequest) From(from int64) ApiGetDeploymentsRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetDeploymentsRequest) To(to int64) ApiGetDeploymentsRequest { + r.to = &to + return r +} + +// Identifier used for pagination +func (r ApiGetDeploymentsRequest) After(after string) ApiGetDeploymentsRequest { + r.after = &after + return r +} + +// Identifier used for pagination +func (r ApiGetDeploymentsRequest) Before(before string) ApiGetDeploymentsRequest { + r.before = &before + return r +} + +// The deployment kind +func (r ApiGetDeploymentsRequest) Kind(kind string) ApiGetDeploymentsRequest { + r.kind = &kind + return r +} + +// The deployment status +func (r ApiGetDeploymentsRequest) Status(status string) ApiGetDeploymentsRequest { + r.status = &status + return r +} + +func (r ApiGetDeploymentsRequest) Execute() (*DeploymentCollectionRep, *http.Response, error) { + return r.ApiService.GetDeploymentsExecute(r) +} + +/* +GetDeployments List deployments + +Get a list of deployments + +### Expanding the deployment collection response + +LaunchDarkly supports expanding the deployment collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `pullRequests` includes details on all of the pull requests associated with each deployment +* `flagReferences` includes details on all of the references to flags in each deployment + +For example, use `?expand=pullRequests` to include the `pullRequests` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetDeploymentsRequest +*/ +func (a *InsightsDeploymentsBetaApiService) GetDeployments(ctx context.Context) ApiGetDeploymentsRequest { + return ApiGetDeploymentsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return DeploymentCollectionRep +func (a *InsightsDeploymentsBetaApiService) GetDeploymentsExecute(r ApiGetDeploymentsRequest) (*DeploymentCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *DeploymentCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsDeploymentsBetaApiService.GetDeployments") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/deployments" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.before != nil { + localVarQueryParams.Add("before", parameterToString(*r.before, "")) + } + if r.kind != nil { + localVarQueryParams.Add("kind", parameterToString(*r.kind, "")) + } + if r.status != nil { + localVarQueryParams.Add("status", parameterToString(*r.status, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateDeploymentRequest struct { + ctx context.Context + ApiService InsightsDeploymentsBetaApi + deploymentID string + patchOperation *[]PatchOperation +} + +func (r ApiUpdateDeploymentRequest) PatchOperation(patchOperation []PatchOperation) ApiUpdateDeploymentRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiUpdateDeploymentRequest) Execute() (*DeploymentRep, *http.Response, error) { + return r.ApiService.UpdateDeploymentExecute(r) +} + +/* +UpdateDeployment Update deployment + +Update a deployment by ID. Updating a deployment uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

The deployment ID is returned as part of the [List deployments](https://launchdarkly.com/docs/api/insights-deployments-beta/get-deployments) response. It is the `id` field of each element in the `items` array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param deploymentID The deployment ID + @return ApiUpdateDeploymentRequest +*/ +func (a *InsightsDeploymentsBetaApiService) UpdateDeployment(ctx context.Context, deploymentID string) ApiUpdateDeploymentRequest { + return ApiUpdateDeploymentRequest{ + ApiService: a, + ctx: ctx, + deploymentID: deploymentID, + } +} + +// Execute executes the request +// @return DeploymentRep +func (a *InsightsDeploymentsBetaApiService) UpdateDeploymentExecute(r ApiUpdateDeploymentRequest) (*DeploymentRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *DeploymentRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsDeploymentsBetaApiService.UpdateDeployment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/deployments/{deploymentID}" + localVarPath = strings.Replace(localVarPath, "{"+"deploymentID"+"}", url.PathEscape(parameterToString(r.deploymentID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_flag_events_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_flag_events_beta.go new file mode 100644 index 00000000..abeeb567 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_flag_events_beta.go @@ -0,0 +1,357 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" +) + + +type InsightsFlagEventsBetaApi interface { + + /* + GetFlagEvents List flag events + + Get a list of flag events + +### Expanding the flag event collection response + +LaunchDarkly supports expanding the flag event collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `experiments` includes details on all of the experiments run on each flag + +For example, use `?expand=experiments` to include the `experiments` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagEventsRequest + */ + GetFlagEvents(ctx context.Context) ApiGetFlagEventsRequest + + // GetFlagEventsExecute executes the request + // @return FlagEventCollectionRep + GetFlagEventsExecute(r ApiGetFlagEventsRequest) (*FlagEventCollectionRep, *http.Response, error) +} + +// InsightsFlagEventsBetaApiService InsightsFlagEventsBetaApi service +type InsightsFlagEventsBetaApiService service + +type ApiGetFlagEventsRequest struct { + ctx context.Context + ApiService InsightsFlagEventsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + query *string + impactSize *string + hasExperiments *bool + global *string + expand *string + limit *int64 + from *int64 + to *int64 + after *string + before *string +} + +// The project key +func (r ApiGetFlagEventsRequest) ProjectKey(projectKey string) ApiGetFlagEventsRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetFlagEventsRequest) EnvironmentKey(environmentKey string) ApiGetFlagEventsRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetFlagEventsRequest) ApplicationKey(applicationKey string) ApiGetFlagEventsRequest { + r.applicationKey = &applicationKey + return r +} + +// Filter events by flag key +func (r ApiGetFlagEventsRequest) Query(query string) ApiGetFlagEventsRequest { + r.query = &query + return r +} + +// Filter events by impact size. A small impact created a less than 20% change in the proportion of end users receiving one or more flag variations. A medium impact created between a 20%-80% change. A large impact created a more than 80% change. Options: `none`, `small`, `medium`, `large` +func (r ApiGetFlagEventsRequest) ImpactSize(impactSize string) ApiGetFlagEventsRequest { + r.impactSize = &impactSize + return r +} + +// Filter events to those associated with an experiment (`true`) or without an experiment (`false`) +func (r ApiGetFlagEventsRequest) HasExperiments(hasExperiments bool) ApiGetFlagEventsRequest { + r.hasExperiments = &hasExperiments + return r +} + +// Filter to include or exclude global events. Default value is `include`. Options: `include`, `exclude` +func (r ApiGetFlagEventsRequest) Global(global string) ApiGetFlagEventsRequest { + r.global = &global + return r +} + +// Expand properties in response. Options: `experiments` +func (r ApiGetFlagEventsRequest) Expand(expand string) ApiGetFlagEventsRequest { + r.expand = &expand + return r +} + +// The number of deployments to return. Default is 20. Maximum allowed is 100. +func (r ApiGetFlagEventsRequest) Limit(limit int64) ApiGetFlagEventsRequest { + r.limit = &limit + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetFlagEventsRequest) From(from int64) ApiGetFlagEventsRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetFlagEventsRequest) To(to int64) ApiGetFlagEventsRequest { + r.to = &to + return r +} + +// Identifier used for pagination +func (r ApiGetFlagEventsRequest) After(after string) ApiGetFlagEventsRequest { + r.after = &after + return r +} + +// Identifier used for pagination +func (r ApiGetFlagEventsRequest) Before(before string) ApiGetFlagEventsRequest { + r.before = &before + return r +} + +func (r ApiGetFlagEventsRequest) Execute() (*FlagEventCollectionRep, *http.Response, error) { + return r.ApiService.GetFlagEventsExecute(r) +} + +/* +GetFlagEvents List flag events + +Get a list of flag events + +### Expanding the flag event collection response + +LaunchDarkly supports expanding the flag event collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `experiments` includes details on all of the experiments run on each flag + +For example, use `?expand=experiments` to include the `experiments` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetFlagEventsRequest +*/ +func (a *InsightsFlagEventsBetaApiService) GetFlagEvents(ctx context.Context) ApiGetFlagEventsRequest { + return ApiGetFlagEventsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return FlagEventCollectionRep +func (a *InsightsFlagEventsBetaApiService) GetFlagEventsExecute(r ApiGetFlagEventsRequest) (*FlagEventCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagEventCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsFlagEventsBetaApiService.GetFlagEvents") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/flag-events" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.query != nil { + localVarQueryParams.Add("query", parameterToString(*r.query, "")) + } + if r.impactSize != nil { + localVarQueryParams.Add("impactSize", parameterToString(*r.impactSize, "")) + } + if r.hasExperiments != nil { + localVarQueryParams.Add("hasExperiments", parameterToString(*r.hasExperiments, "")) + } + if r.global != nil { + localVarQueryParams.Add("global", parameterToString(*r.global, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.before != nil { + localVarQueryParams.Add("before", parameterToString(*r.before, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_pull_requests_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_pull_requests_beta.go new file mode 100644 index 00000000..dd15cce7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_pull_requests_beta.go @@ -0,0 +1,351 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "time" +) + + +type InsightsPullRequestsBetaApi interface { + + /* + GetPullRequests List pull requests + + Get a list of pull requests + +### Expanding the pull request collection response + +LaunchDarkly supports expanding the pull request collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `deployments` includes details on all of the deployments associated with each pull request +* `flagReferences` includes details on all of the references to flags in each pull request +* `leadTime` includes details about the lead time of the pull request for each stage + +For example, use `?expand=deployments` to include the `deployments` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetPullRequestsRequest + */ + GetPullRequests(ctx context.Context) ApiGetPullRequestsRequest + + // GetPullRequestsExecute executes the request + // @return PullRequestCollectionRep + GetPullRequestsExecute(r ApiGetPullRequestsRequest) (*PullRequestCollectionRep, *http.Response, error) +} + +// InsightsPullRequestsBetaApiService InsightsPullRequestsBetaApi service +type InsightsPullRequestsBetaApiService service + +type ApiGetPullRequestsRequest struct { + ctx context.Context + ApiService InsightsPullRequestsBetaApi + projectKey *string + environmentKey *string + applicationKey *string + status *string + query *string + limit *int64 + expand *string + sort *string + from *time.Time + to *time.Time + after *string + before *string +} + +// The project key +func (r ApiGetPullRequestsRequest) ProjectKey(projectKey string) ApiGetPullRequestsRequest { + r.projectKey = &projectKey + return r +} + +// Required if you are using the <code>sort</code> parameter's <code>leadTime</code> option to sort pull requests. +func (r ApiGetPullRequestsRequest) EnvironmentKey(environmentKey string) ApiGetPullRequestsRequest { + r.environmentKey = &environmentKey + return r +} + +// Filter the results to pull requests deployed to a comma separated list of applications +func (r ApiGetPullRequestsRequest) ApplicationKey(applicationKey string) ApiGetPullRequestsRequest { + r.applicationKey = &applicationKey + return r +} + +// Filter results to pull requests with the given status. Options: `open`, `merged`, `closed`, `deployed`. +func (r ApiGetPullRequestsRequest) Status(status string) ApiGetPullRequestsRequest { + r.status = &status + return r +} + +// Filter list of pull requests by title or author +func (r ApiGetPullRequestsRequest) Query(query string) ApiGetPullRequestsRequest { + r.query = &query + return r +} + +// The number of pull requests to return. Default is 20. Maximum allowed is 100. +func (r ApiGetPullRequestsRequest) Limit(limit int64) ApiGetPullRequestsRequest { + r.limit = &limit + return r +} + +// Expand properties in response. Options: `deployments`, `flagReferences`, `leadTime`. +func (r ApiGetPullRequestsRequest) Expand(expand string) ApiGetPullRequestsRequest { + r.expand = &expand + return r +} + +// Sort results. Requires the `environmentKey` to be set. Options: `leadTime` (asc) and `-leadTime` (desc). When query option is excluded, default sort is by created or merged date. +func (r ApiGetPullRequestsRequest) Sort(sort string) ApiGetPullRequestsRequest { + r.sort = &sort + return r +} + +// Unix timestamp in milliseconds. Default value is 7 days ago. +func (r ApiGetPullRequestsRequest) From(from time.Time) ApiGetPullRequestsRequest { + r.from = &from + return r +} + +// Unix timestamp in milliseconds. Default value is now. +func (r ApiGetPullRequestsRequest) To(to time.Time) ApiGetPullRequestsRequest { + r.to = &to + return r +} + +// Identifier used for pagination +func (r ApiGetPullRequestsRequest) After(after string) ApiGetPullRequestsRequest { + r.after = &after + return r +} + +// Identifier used for pagination +func (r ApiGetPullRequestsRequest) Before(before string) ApiGetPullRequestsRequest { + r.before = &before + return r +} + +func (r ApiGetPullRequestsRequest) Execute() (*PullRequestCollectionRep, *http.Response, error) { + return r.ApiService.GetPullRequestsExecute(r) +} + +/* +GetPullRequests List pull requests + +Get a list of pull requests + +### Expanding the pull request collection response + +LaunchDarkly supports expanding the pull request collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `deployments` includes details on all of the deployments associated with each pull request +* `flagReferences` includes details on all of the references to flags in each pull request +* `leadTime` includes details about the lead time of the pull request for each stage + +For example, use `?expand=deployments` to include the `deployments` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetPullRequestsRequest +*/ +func (a *InsightsPullRequestsBetaApiService) GetPullRequests(ctx context.Context) ApiGetPullRequestsRequest { + return ApiGetPullRequestsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return PullRequestCollectionRep +func (a *InsightsPullRequestsBetaApiService) GetPullRequestsExecute(r ApiGetPullRequestsRequest) (*PullRequestCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *PullRequestCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsPullRequestsBetaApiService.GetPullRequests") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/pull-requests" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + if r.environmentKey != nil { + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + } + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + if r.status != nil { + localVarQueryParams.Add("status", parameterToString(*r.status, "")) + } + if r.query != nil { + localVarQueryParams.Add("query", parameterToString(*r.query, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.from != nil { + localVarQueryParams.Add("from", parameterToString(*r.from, "")) + } + if r.to != nil { + localVarQueryParams.Add("to", parameterToString(*r.to, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.before != nil { + localVarQueryParams.Add("before", parameterToString(*r.before, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_repositories_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_repositories_beta.go new file mode 100644 index 00000000..9df5de48 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_repositories_beta.go @@ -0,0 +1,597 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type InsightsRepositoriesBetaApi interface { + + /* + AssociateRepositoriesAndProjects Associate repositories with projects + + Associate repositories with projects + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiAssociateRepositoriesAndProjectsRequest + */ + AssociateRepositoriesAndProjects(ctx context.Context) ApiAssociateRepositoriesAndProjectsRequest + + // AssociateRepositoriesAndProjectsExecute executes the request + // @return InsightsRepositoryProjectCollection + AssociateRepositoriesAndProjectsExecute(r ApiAssociateRepositoriesAndProjectsRequest) (*InsightsRepositoryProjectCollection, *http.Response, error) + + /* + DeleteRepositoryProject Remove repository project association + + Remove repository project association + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repositoryKey The repository key + @param projectKey The project key + @return ApiDeleteRepositoryProjectRequest + */ + DeleteRepositoryProject(ctx context.Context, repositoryKey string, projectKey string) ApiDeleteRepositoryProjectRequest + + // DeleteRepositoryProjectExecute executes the request + DeleteRepositoryProjectExecute(r ApiDeleteRepositoryProjectRequest) (*http.Response, error) + + /* + GetInsightsRepositories List repositories + + Get a list of repositories + +### Expanding the repository collection response + +LaunchDarkly supports expanding the repository collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `projects` includes details on all of the LaunchDarkly projects associated with each repository + +For example, use `?expand=projects` to include the `projects` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightsRepositoriesRequest + */ + GetInsightsRepositories(ctx context.Context) ApiGetInsightsRepositoriesRequest + + // GetInsightsRepositoriesExecute executes the request + // @return InsightsRepositoryCollection + GetInsightsRepositoriesExecute(r ApiGetInsightsRepositoriesRequest) (*InsightsRepositoryCollection, *http.Response, error) +} + +// InsightsRepositoriesBetaApiService InsightsRepositoriesBetaApi service +type InsightsRepositoriesBetaApiService service + +type ApiAssociateRepositoriesAndProjectsRequest struct { + ctx context.Context + ApiService InsightsRepositoriesBetaApi + insightsRepositoryProjectMappings *InsightsRepositoryProjectMappings +} + +func (r ApiAssociateRepositoriesAndProjectsRequest) InsightsRepositoryProjectMappings(insightsRepositoryProjectMappings InsightsRepositoryProjectMappings) ApiAssociateRepositoriesAndProjectsRequest { + r.insightsRepositoryProjectMappings = &insightsRepositoryProjectMappings + return r +} + +func (r ApiAssociateRepositoriesAndProjectsRequest) Execute() (*InsightsRepositoryProjectCollection, *http.Response, error) { + return r.ApiService.AssociateRepositoriesAndProjectsExecute(r) +} + +/* +AssociateRepositoriesAndProjects Associate repositories with projects + +Associate repositories with projects + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiAssociateRepositoriesAndProjectsRequest +*/ +func (a *InsightsRepositoriesBetaApiService) AssociateRepositoriesAndProjects(ctx context.Context) ApiAssociateRepositoriesAndProjectsRequest { + return ApiAssociateRepositoriesAndProjectsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsRepositoryProjectCollection +func (a *InsightsRepositoriesBetaApiService) AssociateRepositoriesAndProjectsExecute(r ApiAssociateRepositoriesAndProjectsRequest) (*InsightsRepositoryProjectCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsRepositoryProjectCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsRepositoriesBetaApiService.AssociateRepositoriesAndProjects") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/repositories/projects" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.insightsRepositoryProjectMappings == nil { + return localVarReturnValue, nil, reportError("insightsRepositoryProjectMappings is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.insightsRepositoryProjectMappings + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteRepositoryProjectRequest struct { + ctx context.Context + ApiService InsightsRepositoriesBetaApi + repositoryKey string + projectKey string +} + +func (r ApiDeleteRepositoryProjectRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteRepositoryProjectExecute(r) +} + +/* +DeleteRepositoryProject Remove repository project association + +Remove repository project association + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param repositoryKey The repository key + @param projectKey The project key + @return ApiDeleteRepositoryProjectRequest +*/ +func (a *InsightsRepositoriesBetaApiService) DeleteRepositoryProject(ctx context.Context, repositoryKey string, projectKey string) ApiDeleteRepositoryProjectRequest { + return ApiDeleteRepositoryProjectRequest{ + ApiService: a, + ctx: ctx, + repositoryKey: repositoryKey, + projectKey: projectKey, + } +} + +// Execute executes the request +func (a *InsightsRepositoriesBetaApiService) DeleteRepositoryProjectExecute(r ApiDeleteRepositoryProjectRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsRepositoriesBetaApiService.DeleteRepositoryProject") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/repositories/{repositoryKey}/projects/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"repositoryKey"+"}", url.PathEscape(parameterToString(r.repositoryKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetInsightsRepositoriesRequest struct { + ctx context.Context + ApiService InsightsRepositoriesBetaApi + expand *string +} + +// Expand properties in response. Options: `projects` +func (r ApiGetInsightsRepositoriesRequest) Expand(expand string) ApiGetInsightsRepositoriesRequest { + r.expand = &expand + return r +} + +func (r ApiGetInsightsRepositoriesRequest) Execute() (*InsightsRepositoryCollection, *http.Response, error) { + return r.ApiService.GetInsightsRepositoriesExecute(r) +} + +/* +GetInsightsRepositories List repositories + +Get a list of repositories + +### Expanding the repository collection response + +LaunchDarkly supports expanding the repository collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `projects` includes details on all of the LaunchDarkly projects associated with each repository + +For example, use `?expand=projects` to include the `projects` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightsRepositoriesRequest +*/ +func (a *InsightsRepositoriesBetaApiService) GetInsightsRepositories(ctx context.Context) ApiGetInsightsRepositoriesRequest { + return ApiGetInsightsRepositoriesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightsRepositoryCollection +func (a *InsightsRepositoriesBetaApiService) GetInsightsRepositoriesExecute(r ApiGetInsightsRepositoriesRequest) (*InsightsRepositoryCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightsRepositoryCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsRepositoriesBetaApiService.GetInsightsRepositories") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/repositories" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_scores_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_scores_beta.go new file mode 100644 index 00000000..00f9674b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_insights_scores_beta.go @@ -0,0 +1,1251 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type InsightsScoresBetaApi interface { + + /* + CreateInsightGroup Create insight group + + Create insight group + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateInsightGroupRequest + */ + CreateInsightGroup(ctx context.Context) ApiCreateInsightGroupRequest + + // CreateInsightGroupExecute executes the request + // @return InsightGroup + CreateInsightGroupExecute(r ApiCreateInsightGroupRequest) (*InsightGroup, *http.Response, error) + + /* + DeleteInsightGroup Delete insight group + + Delete insight group + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiDeleteInsightGroupRequest + */ + DeleteInsightGroup(ctx context.Context, insightGroupKey string) ApiDeleteInsightGroupRequest + + // DeleteInsightGroupExecute executes the request + DeleteInsightGroupExecute(r ApiDeleteInsightGroupRequest) (*http.Response, error) + + /* + GetInsightGroup Get insight group + + Get insight group + +### Expanding the insight group response + +LaunchDarkly supports expanding the insight group response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `scores` includes details on all of the scores used in the engineering insights metrics views for this group +* `environment` includes details on each environment associated with this group + +For example, use `?expand=scores` to include the `scores` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiGetInsightGroupRequest + */ + GetInsightGroup(ctx context.Context, insightGroupKey string) ApiGetInsightGroupRequest + + // GetInsightGroupExecute executes the request + // @return InsightGroup + GetInsightGroupExecute(r ApiGetInsightGroupRequest) (*InsightGroup, *http.Response, error) + + /* + GetInsightGroups List insight groups + + List groups for which you are collecting insights + +### Expanding the insight groups collection response + +LaunchDarkly supports expanding the insight groups collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `scores` includes details on all of the scores used in the engineering insights metrics views for each group +* `environment` includes details on each environment associated with each group +* `metadata` includes counts of the number of insight groups with particular indicators, such as "excellent," "good," "fair," and so on. + +For example, use `?expand=scores` to include the `scores` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightGroupsRequest + */ + GetInsightGroups(ctx context.Context) ApiGetInsightGroupsRequest + + // GetInsightGroupsExecute executes the request + // @return InsightGroupCollection + GetInsightGroupsExecute(r ApiGetInsightGroupsRequest) (*InsightGroupCollection, *http.Response, error) + + /* + GetInsightsScores Get insight scores + + Return insights scores, based on the given parameters. This data is also used in engineering insights metrics views. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightsScoresRequest + */ + GetInsightsScores(ctx context.Context) ApiGetInsightsScoresRequest + + // GetInsightsScoresExecute executes the request + // @return InsightScores + GetInsightsScoresExecute(r ApiGetInsightsScoresRequest) (*InsightScores, *http.Response, error) + + /* + PatchInsightGroup Patch insight group + + Update an insight group. Updating an insight group uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiPatchInsightGroupRequest + */ + PatchInsightGroup(ctx context.Context, insightGroupKey string) ApiPatchInsightGroupRequest + + // PatchInsightGroupExecute executes the request + // @return InsightGroup + PatchInsightGroupExecute(r ApiPatchInsightGroupRequest) (*InsightGroup, *http.Response, error) +} + +// InsightsScoresBetaApiService InsightsScoresBetaApi service +type InsightsScoresBetaApiService service + +type ApiCreateInsightGroupRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + postInsightGroupParams *PostInsightGroupParams +} + +func (r ApiCreateInsightGroupRequest) PostInsightGroupParams(postInsightGroupParams PostInsightGroupParams) ApiCreateInsightGroupRequest { + r.postInsightGroupParams = &postInsightGroupParams + return r +} + +func (r ApiCreateInsightGroupRequest) Execute() (*InsightGroup, *http.Response, error) { + return r.ApiService.CreateInsightGroupExecute(r) +} + +/* +CreateInsightGroup Create insight group + +Create insight group + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateInsightGroupRequest +*/ +func (a *InsightsScoresBetaApiService) CreateInsightGroup(ctx context.Context) ApiCreateInsightGroupRequest { + return ApiCreateInsightGroupRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightGroup +func (a *InsightsScoresBetaApiService) CreateInsightGroupExecute(r ApiCreateInsightGroupRequest) (*InsightGroup, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightGroup + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.CreateInsightGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/group" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postInsightGroupParams == nil { + return localVarReturnValue, nil, reportError("postInsightGroupParams is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postInsightGroupParams + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteInsightGroupRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + insightGroupKey string +} + +func (r ApiDeleteInsightGroupRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteInsightGroupExecute(r) +} + +/* +DeleteInsightGroup Delete insight group + +Delete insight group + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiDeleteInsightGroupRequest +*/ +func (a *InsightsScoresBetaApiService) DeleteInsightGroup(ctx context.Context, insightGroupKey string) ApiDeleteInsightGroupRequest { + return ApiDeleteInsightGroupRequest{ + ApiService: a, + ctx: ctx, + insightGroupKey: insightGroupKey, + } +} + +// Execute executes the request +func (a *InsightsScoresBetaApiService) DeleteInsightGroupExecute(r ApiDeleteInsightGroupRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.DeleteInsightGroup") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/groups/{insightGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"insightGroupKey"+"}", url.PathEscape(parameterToString(r.insightGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetInsightGroupRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + insightGroupKey string + expand *string +} + +// Options: `scores`, `environment` +func (r ApiGetInsightGroupRequest) Expand(expand string) ApiGetInsightGroupRequest { + r.expand = &expand + return r +} + +func (r ApiGetInsightGroupRequest) Execute() (*InsightGroup, *http.Response, error) { + return r.ApiService.GetInsightGroupExecute(r) +} + +/* +GetInsightGroup Get insight group + +Get insight group + +### Expanding the insight group response + +LaunchDarkly supports expanding the insight group response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `scores` includes details on all of the scores used in the engineering insights metrics views for this group +* `environment` includes details on each environment associated with this group + +For example, use `?expand=scores` to include the `scores` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiGetInsightGroupRequest +*/ +func (a *InsightsScoresBetaApiService) GetInsightGroup(ctx context.Context, insightGroupKey string) ApiGetInsightGroupRequest { + return ApiGetInsightGroupRequest{ + ApiService: a, + ctx: ctx, + insightGroupKey: insightGroupKey, + } +} + +// Execute executes the request +// @return InsightGroup +func (a *InsightsScoresBetaApiService) GetInsightGroupExecute(r ApiGetInsightGroupRequest) (*InsightGroup, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightGroup + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.GetInsightGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/groups/{insightGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"insightGroupKey"+"}", url.PathEscape(parameterToString(r.insightGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetInsightGroupsRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + limit *int64 + offset *int64 + sort *string + query *string + expand *string +} + +// The number of insight groups to return. Default is 20. Must be between 1 and 20 inclusive. +func (r ApiGetInsightGroupsRequest) Limit(limit int64) ApiGetInsightGroupsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetInsightGroupsRequest) Offset(offset int64) ApiGetInsightGroupsRequest { + r.offset = &offset + return r +} + +// Sort flag list by field. Prefix field with <code>-</code> to sort in descending order. Allowed fields: name +func (r ApiGetInsightGroupsRequest) Sort(sort string) ApiGetInsightGroupsRequest { + r.sort = &sort + return r +} + +// Filter list of insights groups by name. +func (r ApiGetInsightGroupsRequest) Query(query string) ApiGetInsightGroupsRequest { + r.query = &query + return r +} + +// Options: `scores`, `environment`, `metadata` +func (r ApiGetInsightGroupsRequest) Expand(expand string) ApiGetInsightGroupsRequest { + r.expand = &expand + return r +} + +func (r ApiGetInsightGroupsRequest) Execute() (*InsightGroupCollection, *http.Response, error) { + return r.ApiService.GetInsightGroupsExecute(r) +} + +/* +GetInsightGroups List insight groups + +List groups for which you are collecting insights + +### Expanding the insight groups collection response + +LaunchDarkly supports expanding the insight groups collection response to include additional fields. + +To expand the response, append the `expand` query parameter and include the following: + +* `scores` includes details on all of the scores used in the engineering insights metrics views for each group +* `environment` includes details on each environment associated with each group +* `metadata` includes counts of the number of insight groups with particular indicators, such as "excellent," "good," "fair," and so on. + +For example, use `?expand=scores` to include the `scores` field in the response. By default, this field is **not** included in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightGroupsRequest +*/ +func (a *InsightsScoresBetaApiService) GetInsightGroups(ctx context.Context) ApiGetInsightGroupsRequest { + return ApiGetInsightGroupsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightGroupCollection +func (a *InsightsScoresBetaApiService) GetInsightGroupsExecute(r ApiGetInsightGroupsRequest) (*InsightGroupCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightGroupCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.GetInsightGroups") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/groups" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.query != nil { + localVarQueryParams.Add("query", parameterToString(*r.query, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetInsightsScoresRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + projectKey *string + environmentKey *string + applicationKey *string +} + +// The project key +func (r ApiGetInsightsScoresRequest) ProjectKey(projectKey string) ApiGetInsightsScoresRequest { + r.projectKey = &projectKey + return r +} + +// The environment key +func (r ApiGetInsightsScoresRequest) EnvironmentKey(environmentKey string) ApiGetInsightsScoresRequest { + r.environmentKey = &environmentKey + return r +} + +// Comma separated list of application keys +func (r ApiGetInsightsScoresRequest) ApplicationKey(applicationKey string) ApiGetInsightsScoresRequest { + r.applicationKey = &applicationKey + return r +} + +func (r ApiGetInsightsScoresRequest) Execute() (*InsightScores, *http.Response, error) { + return r.ApiService.GetInsightsScoresExecute(r) +} + +/* +GetInsightsScores Get insight scores + +Return insights scores, based on the given parameters. This data is also used in engineering insights metrics views. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetInsightsScoresRequest +*/ +func (a *InsightsScoresBetaApiService) GetInsightsScores(ctx context.Context) ApiGetInsightsScoresRequest { + return ApiGetInsightsScoresRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return InsightScores +func (a *InsightsScoresBetaApiService) GetInsightsScoresExecute(r ApiGetInsightsScoresRequest) (*InsightScores, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightScores + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.GetInsightsScores") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/scores" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectKey == nil { + return localVarReturnValue, nil, reportError("projectKey is required and must be specified") + } + if r.environmentKey == nil { + return localVarReturnValue, nil, reportError("environmentKey is required and must be specified") + } + + localVarQueryParams.Add("projectKey", parameterToString(*r.projectKey, "")) + localVarQueryParams.Add("environmentKey", parameterToString(*r.environmentKey, "")) + if r.applicationKey != nil { + localVarQueryParams.Add("applicationKey", parameterToString(*r.applicationKey, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchInsightGroupRequest struct { + ctx context.Context + ApiService InsightsScoresBetaApi + insightGroupKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchInsightGroupRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchInsightGroupRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchInsightGroupRequest) Execute() (*InsightGroup, *http.Response, error) { + return r.ApiService.PatchInsightGroupExecute(r) +} + +/* +PatchInsightGroup Patch insight group + +Update an insight group. Updating an insight group uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param insightGroupKey The insight group key + @return ApiPatchInsightGroupRequest +*/ +func (a *InsightsScoresBetaApiService) PatchInsightGroup(ctx context.Context, insightGroupKey string) ApiPatchInsightGroupRequest { + return ApiPatchInsightGroupRequest{ + ApiService: a, + ctx: ctx, + insightGroupKey: insightGroupKey, + } +} + +// Execute executes the request +// @return InsightGroup +func (a *InsightsScoresBetaApiService) PatchInsightGroupExecute(r ApiPatchInsightGroupRequest) (*InsightGroup, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InsightGroup + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InsightsScoresBetaApiService.PatchInsightGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/engineering-insights/insights/groups/{insightGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"insightGroupKey"+"}", url.PathEscape(parameterToString(r.insightGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v ValidationFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 422 { + var v PatchFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_audit_log_subscriptions.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_audit_log_subscriptions.go new file mode 100644 index 00000000..aafc063e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_audit_log_subscriptions.go @@ -0,0 +1,928 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type IntegrationAuditLogSubscriptionsApi interface { + + /* + CreateSubscription Create audit log subscription + + Create an audit log subscription.

For each subscription, you must specify the set of resources you wish to subscribe to audit log notifications for. You can describe these resources using a custom role policy. To learn more, read [Custom role concepts](https://launchdarkly.com/docs/home/account/role-concepts). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiCreateSubscriptionRequest + */ + CreateSubscription(ctx context.Context, integrationKey string) ApiCreateSubscriptionRequest + + // CreateSubscriptionExecute executes the request + // @return Integration + CreateSubscriptionExecute(r ApiCreateSubscriptionRequest) (*Integration, *http.Response, error) + + /* + DeleteSubscription Delete audit log subscription + + Delete an audit log subscription. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The subscription ID + @return ApiDeleteSubscriptionRequest + */ + DeleteSubscription(ctx context.Context, integrationKey string, id string) ApiDeleteSubscriptionRequest + + // DeleteSubscriptionExecute executes the request + DeleteSubscriptionExecute(r ApiDeleteSubscriptionRequest) (*http.Response, error) + + /* + GetSubscriptionByID Get audit log subscription by ID + + Get an audit log subscription by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The subscription ID + @return ApiGetSubscriptionByIDRequest + */ + GetSubscriptionByID(ctx context.Context, integrationKey string, id string) ApiGetSubscriptionByIDRequest + + // GetSubscriptionByIDExecute executes the request + // @return Integration + GetSubscriptionByIDExecute(r ApiGetSubscriptionByIDRequest) (*Integration, *http.Response, error) + + /* + GetSubscriptions Get audit log subscriptions by integration + + Get all audit log subscriptions associated with a given integration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiGetSubscriptionsRequest + */ + GetSubscriptions(ctx context.Context, integrationKey string) ApiGetSubscriptionsRequest + + // GetSubscriptionsExecute executes the request + // @return Integrations + GetSubscriptionsExecute(r ApiGetSubscriptionsRequest) (*Integrations, *http.Response, error) + + /* + UpdateSubscription Update audit log subscription + + Update an audit log subscription configuration. Updating an audit log subscription uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The ID of the audit log subscription + @return ApiUpdateSubscriptionRequest + */ + UpdateSubscription(ctx context.Context, integrationKey string, id string) ApiUpdateSubscriptionRequest + + // UpdateSubscriptionExecute executes the request + // @return Integration + UpdateSubscriptionExecute(r ApiUpdateSubscriptionRequest) (*Integration, *http.Response, error) +} + +// IntegrationAuditLogSubscriptionsApiService IntegrationAuditLogSubscriptionsApi service +type IntegrationAuditLogSubscriptionsApiService service + +type ApiCreateSubscriptionRequest struct { + ctx context.Context + ApiService IntegrationAuditLogSubscriptionsApi + integrationKey string + subscriptionPost *SubscriptionPost +} + +func (r ApiCreateSubscriptionRequest) SubscriptionPost(subscriptionPost SubscriptionPost) ApiCreateSubscriptionRequest { + r.subscriptionPost = &subscriptionPost + return r +} + +func (r ApiCreateSubscriptionRequest) Execute() (*Integration, *http.Response, error) { + return r.ApiService.CreateSubscriptionExecute(r) +} + +/* +CreateSubscription Create audit log subscription + +Create an audit log subscription.

For each subscription, you must specify the set of resources you wish to subscribe to audit log notifications for. You can describe these resources using a custom role policy. To learn more, read [Custom role concepts](https://launchdarkly.com/docs/home/account/role-concepts). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiCreateSubscriptionRequest +*/ +func (a *IntegrationAuditLogSubscriptionsApiService) CreateSubscription(ctx context.Context, integrationKey string) ApiCreateSubscriptionRequest { + return ApiCreateSubscriptionRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return Integration +func (a *IntegrationAuditLogSubscriptionsApiService) CreateSubscriptionExecute(r ApiCreateSubscriptionRequest) (*Integration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Integration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationAuditLogSubscriptionsApiService.CreateSubscription") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integrations/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.subscriptionPost == nil { + return localVarReturnValue, nil, reportError("subscriptionPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.subscriptionPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteSubscriptionRequest struct { + ctx context.Context + ApiService IntegrationAuditLogSubscriptionsApi + integrationKey string + id string +} + +func (r ApiDeleteSubscriptionRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteSubscriptionExecute(r) +} + +/* +DeleteSubscription Delete audit log subscription + +Delete an audit log subscription. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The subscription ID + @return ApiDeleteSubscriptionRequest +*/ +func (a *IntegrationAuditLogSubscriptionsApiService) DeleteSubscription(ctx context.Context, integrationKey string, id string) ApiDeleteSubscriptionRequest { + return ApiDeleteSubscriptionRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +func (a *IntegrationAuditLogSubscriptionsApiService) DeleteSubscriptionExecute(r ApiDeleteSubscriptionRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationAuditLogSubscriptionsApiService.DeleteSubscription") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integrations/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetSubscriptionByIDRequest struct { + ctx context.Context + ApiService IntegrationAuditLogSubscriptionsApi + integrationKey string + id string +} + +func (r ApiGetSubscriptionByIDRequest) Execute() (*Integration, *http.Response, error) { + return r.ApiService.GetSubscriptionByIDExecute(r) +} + +/* +GetSubscriptionByID Get audit log subscription by ID + +Get an audit log subscription by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The subscription ID + @return ApiGetSubscriptionByIDRequest +*/ +func (a *IntegrationAuditLogSubscriptionsApiService) GetSubscriptionByID(ctx context.Context, integrationKey string, id string) ApiGetSubscriptionByIDRequest { + return ApiGetSubscriptionByIDRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +// @return Integration +func (a *IntegrationAuditLogSubscriptionsApiService) GetSubscriptionByIDExecute(r ApiGetSubscriptionByIDRequest) (*Integration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Integration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationAuditLogSubscriptionsApiService.GetSubscriptionByID") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integrations/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetSubscriptionsRequest struct { + ctx context.Context + ApiService IntegrationAuditLogSubscriptionsApi + integrationKey string +} + +func (r ApiGetSubscriptionsRequest) Execute() (*Integrations, *http.Response, error) { + return r.ApiService.GetSubscriptionsExecute(r) +} + +/* +GetSubscriptions Get audit log subscriptions by integration + +Get all audit log subscriptions associated with a given integration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiGetSubscriptionsRequest +*/ +func (a *IntegrationAuditLogSubscriptionsApiService) GetSubscriptions(ctx context.Context, integrationKey string) ApiGetSubscriptionsRequest { + return ApiGetSubscriptionsRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return Integrations +func (a *IntegrationAuditLogSubscriptionsApiService) GetSubscriptionsExecute(r ApiGetSubscriptionsRequest) (*Integrations, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Integrations + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationAuditLogSubscriptionsApiService.GetSubscriptions") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integrations/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateSubscriptionRequest struct { + ctx context.Context + ApiService IntegrationAuditLogSubscriptionsApi + integrationKey string + id string + patchOperation *[]PatchOperation +} + +func (r ApiUpdateSubscriptionRequest) PatchOperation(patchOperation []PatchOperation) ApiUpdateSubscriptionRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiUpdateSubscriptionRequest) Execute() (*Integration, *http.Response, error) { + return r.ApiService.UpdateSubscriptionExecute(r) +} + +/* +UpdateSubscription Update audit log subscription + +Update an audit log subscription configuration. Updating an audit log subscription uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @param id The ID of the audit log subscription + @return ApiUpdateSubscriptionRequest +*/ +func (a *IntegrationAuditLogSubscriptionsApiService) UpdateSubscription(ctx context.Context, integrationKey string, id string) ApiUpdateSubscriptionRequest { + return ApiUpdateSubscriptionRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +// @return Integration +func (a *IntegrationAuditLogSubscriptionsApiService) UpdateSubscriptionExecute(r ApiUpdateSubscriptionRequest) (*Integration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Integration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationAuditLogSubscriptionsApiService.UpdateSubscription") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integrations/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_delivery_configurations_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_delivery_configurations_beta.go new file mode 100644 index 00000000..ab4e1599 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_integration_delivery_configurations_beta.go @@ -0,0 +1,1335 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type IntegrationDeliveryConfigurationsBetaApi interface { + + /* + CreateIntegrationDeliveryConfiguration Create delivery configuration + + Create a delivery configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @return ApiCreateIntegrationDeliveryConfigurationRequest + */ + CreateIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string) ApiCreateIntegrationDeliveryConfigurationRequest + + // CreateIntegrationDeliveryConfigurationExecute executes the request + // @return IntegrationDeliveryConfiguration + CreateIntegrationDeliveryConfigurationExecute(r ApiCreateIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) + + /* + DeleteIntegrationDeliveryConfiguration Delete delivery configuration + + Delete a delivery configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiDeleteIntegrationDeliveryConfigurationRequest + */ + DeleteIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiDeleteIntegrationDeliveryConfigurationRequest + + // DeleteIntegrationDeliveryConfigurationExecute executes the request + DeleteIntegrationDeliveryConfigurationExecute(r ApiDeleteIntegrationDeliveryConfigurationRequest) (*http.Response, error) + + /* + GetIntegrationDeliveryConfigurationByEnvironment Get delivery configurations by environment + + Get delivery configurations by environment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest + */ + GetIntegrationDeliveryConfigurationByEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest + + // GetIntegrationDeliveryConfigurationByEnvironmentExecute executes the request + // @return IntegrationDeliveryConfigurationCollection + GetIntegrationDeliveryConfigurationByEnvironmentExecute(r ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest) (*IntegrationDeliveryConfigurationCollection, *http.Response, error) + + /* + GetIntegrationDeliveryConfigurationById Get delivery configuration by ID + + Get delivery configuration by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiGetIntegrationDeliveryConfigurationByIdRequest + */ + GetIntegrationDeliveryConfigurationById(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiGetIntegrationDeliveryConfigurationByIdRequest + + // GetIntegrationDeliveryConfigurationByIdExecute executes the request + // @return IntegrationDeliveryConfiguration + GetIntegrationDeliveryConfigurationByIdExecute(r ApiGetIntegrationDeliveryConfigurationByIdRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) + + /* + GetIntegrationDeliveryConfigurations List all delivery configurations + + List all delivery configurations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetIntegrationDeliveryConfigurationsRequest + */ + GetIntegrationDeliveryConfigurations(ctx context.Context) ApiGetIntegrationDeliveryConfigurationsRequest + + // GetIntegrationDeliveryConfigurationsExecute executes the request + // @return IntegrationDeliveryConfigurationCollection + GetIntegrationDeliveryConfigurationsExecute(r ApiGetIntegrationDeliveryConfigurationsRequest) (*IntegrationDeliveryConfigurationCollection, *http.Response, error) + + /* + PatchIntegrationDeliveryConfiguration Update delivery configuration + + Update an integration delivery configuration. Updating an integration delivery configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiPatchIntegrationDeliveryConfigurationRequest + */ + PatchIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiPatchIntegrationDeliveryConfigurationRequest + + // PatchIntegrationDeliveryConfigurationExecute executes the request + // @return IntegrationDeliveryConfiguration + PatchIntegrationDeliveryConfigurationExecute(r ApiPatchIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) + + /* + ValidateIntegrationDeliveryConfiguration Validate delivery configuration + + Validate the saved delivery configuration, using the `validationRequest` in the integration's `manifest.json` file. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiValidateIntegrationDeliveryConfigurationRequest + */ + ValidateIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiValidateIntegrationDeliveryConfigurationRequest + + // ValidateIntegrationDeliveryConfigurationExecute executes the request + // @return IntegrationDeliveryConfigurationResponse + ValidateIntegrationDeliveryConfigurationExecute(r ApiValidateIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfigurationResponse, *http.Response, error) +} + +// IntegrationDeliveryConfigurationsBetaApiService IntegrationDeliveryConfigurationsBetaApi service +type IntegrationDeliveryConfigurationsBetaApiService service + +type ApiCreateIntegrationDeliveryConfigurationRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string + integrationKey string + integrationDeliveryConfigurationPost *IntegrationDeliveryConfigurationPost +} + +func (r ApiCreateIntegrationDeliveryConfigurationRequest) IntegrationDeliveryConfigurationPost(integrationDeliveryConfigurationPost IntegrationDeliveryConfigurationPost) ApiCreateIntegrationDeliveryConfigurationRequest { + r.integrationDeliveryConfigurationPost = &integrationDeliveryConfigurationPost + return r +} + +func (r ApiCreateIntegrationDeliveryConfigurationRequest) Execute() (*IntegrationDeliveryConfiguration, *http.Response, error) { + return r.ApiService.CreateIntegrationDeliveryConfigurationExecute(r) +} + +/* +CreateIntegrationDeliveryConfiguration Create delivery configuration + +Create a delivery configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @return ApiCreateIntegrationDeliveryConfigurationRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) CreateIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string) ApiCreateIntegrationDeliveryConfigurationRequest { + return ApiCreateIntegrationDeliveryConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfiguration +func (a *IntegrationDeliveryConfigurationsBetaApiService) CreateIntegrationDeliveryConfigurationExecute(r ApiCreateIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfiguration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.CreateIntegrationDeliveryConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.integrationDeliveryConfigurationPost == nil { + return localVarReturnValue, nil, reportError("integrationDeliveryConfigurationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.integrationDeliveryConfigurationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteIntegrationDeliveryConfigurationRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string + integrationKey string + id string +} + +func (r ApiDeleteIntegrationDeliveryConfigurationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteIntegrationDeliveryConfigurationExecute(r) +} + +/* +DeleteIntegrationDeliveryConfiguration Delete delivery configuration + +Delete a delivery configuration. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiDeleteIntegrationDeliveryConfigurationRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) DeleteIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiDeleteIntegrationDeliveryConfigurationRequest { + return ApiDeleteIntegrationDeliveryConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +func (a *IntegrationDeliveryConfigurationsBetaApiService) DeleteIntegrationDeliveryConfigurationExecute(r ApiDeleteIntegrationDeliveryConfigurationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.DeleteIntegrationDeliveryConfiguration") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string +} + +func (r ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest) Execute() (*IntegrationDeliveryConfigurationCollection, *http.Response, error) { + return r.ApiService.GetIntegrationDeliveryConfigurationByEnvironmentExecute(r) +} + +/* +GetIntegrationDeliveryConfigurationByEnvironment Get delivery configurations by environment + +Get delivery configurations by environment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurationByEnvironment(ctx context.Context, projectKey string, environmentKey string) ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest { + return ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfigurationCollection +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurationByEnvironmentExecute(r ApiGetIntegrationDeliveryConfigurationByEnvironmentRequest) (*IntegrationDeliveryConfigurationCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfigurationCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.GetIntegrationDeliveryConfigurationByEnvironment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetIntegrationDeliveryConfigurationByIdRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string + integrationKey string + id string +} + +func (r ApiGetIntegrationDeliveryConfigurationByIdRequest) Execute() (*IntegrationDeliveryConfiguration, *http.Response, error) { + return r.ApiService.GetIntegrationDeliveryConfigurationByIdExecute(r) +} + +/* +GetIntegrationDeliveryConfigurationById Get delivery configuration by ID + +Get delivery configuration by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiGetIntegrationDeliveryConfigurationByIdRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurationById(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiGetIntegrationDeliveryConfigurationByIdRequest { + return ApiGetIntegrationDeliveryConfigurationByIdRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfiguration +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurationByIdExecute(r ApiGetIntegrationDeliveryConfigurationByIdRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfiguration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.GetIntegrationDeliveryConfigurationById") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetIntegrationDeliveryConfigurationsRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi +} + +func (r ApiGetIntegrationDeliveryConfigurationsRequest) Execute() (*IntegrationDeliveryConfigurationCollection, *http.Response, error) { + return r.ApiService.GetIntegrationDeliveryConfigurationsExecute(r) +} + +/* +GetIntegrationDeliveryConfigurations List all delivery configurations + +List all delivery configurations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetIntegrationDeliveryConfigurationsRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurations(ctx context.Context) ApiGetIntegrationDeliveryConfigurationsRequest { + return ApiGetIntegrationDeliveryConfigurationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfigurationCollection +func (a *IntegrationDeliveryConfigurationsBetaApiService) GetIntegrationDeliveryConfigurationsExecute(r ApiGetIntegrationDeliveryConfigurationsRequest) (*IntegrationDeliveryConfigurationCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfigurationCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.GetIntegrationDeliveryConfigurations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchIntegrationDeliveryConfigurationRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string + integrationKey string + id string + patchOperation *[]PatchOperation +} + +func (r ApiPatchIntegrationDeliveryConfigurationRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchIntegrationDeliveryConfigurationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchIntegrationDeliveryConfigurationRequest) Execute() (*IntegrationDeliveryConfiguration, *http.Response, error) { + return r.ApiService.PatchIntegrationDeliveryConfigurationExecute(r) +} + +/* +PatchIntegrationDeliveryConfiguration Update delivery configuration + +Update an integration delivery configuration. Updating an integration delivery configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiPatchIntegrationDeliveryConfigurationRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) PatchIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiPatchIntegrationDeliveryConfigurationRequest { + return ApiPatchIntegrationDeliveryConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfiguration +func (a *IntegrationDeliveryConfigurationsBetaApiService) PatchIntegrationDeliveryConfigurationExecute(r ApiPatchIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfiguration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfiguration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.PatchIntegrationDeliveryConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 422 { + var v PatchFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiValidateIntegrationDeliveryConfigurationRequest struct { + ctx context.Context + ApiService IntegrationDeliveryConfigurationsBetaApi + projectKey string + environmentKey string + integrationKey string + id string +} + +func (r ApiValidateIntegrationDeliveryConfigurationRequest) Execute() (*IntegrationDeliveryConfigurationResponse, *http.Response, error) { + return r.ApiService.ValidateIntegrationDeliveryConfigurationExecute(r) +} + +/* +ValidateIntegrationDeliveryConfiguration Validate delivery configuration + +Validate the saved delivery configuration, using the `validationRequest` in the integration's `manifest.json` file. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key + @param id The configuration ID + @return ApiValidateIntegrationDeliveryConfigurationRequest +*/ +func (a *IntegrationDeliveryConfigurationsBetaApiService) ValidateIntegrationDeliveryConfiguration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, id string) ApiValidateIntegrationDeliveryConfigurationRequest { + return ApiValidateIntegrationDeliveryConfigurationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + id: id, + } +} + +// Execute executes the request +// @return IntegrationDeliveryConfigurationResponse +func (a *IntegrationDeliveryConfigurationsBetaApiService) ValidateIntegrationDeliveryConfigurationExecute(r ApiValidateIntegrationDeliveryConfigurationRequest) (*IntegrationDeliveryConfigurationResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationDeliveryConfigurationResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationDeliveryConfigurationsBetaApiService.ValidateIntegrationDeliveryConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/featureStore/{projectKey}/{environmentKey}/{integrationKey}/{id}/validate" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_integrations_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_integrations_beta.go new file mode 100644 index 00000000..c0f954a8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_integrations_beta.go @@ -0,0 +1,953 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type IntegrationsBetaApi interface { + + /* + CreateIntegrationConfiguration Create integration configuration + + Create a new integration configuration. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiCreateIntegrationConfigurationRequest + */ + CreateIntegrationConfiguration(ctx context.Context, integrationKey string) ApiCreateIntegrationConfigurationRequest + + // CreateIntegrationConfigurationExecute executes the request + // @return IntegrationConfigurationsRep + CreateIntegrationConfigurationExecute(r ApiCreateIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) + + /* + DeleteIntegrationConfiguration Delete integration configuration + + Delete an integration configuration by ID. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId The ID of the integration configuration to be deleted + @return ApiDeleteIntegrationConfigurationRequest + */ + DeleteIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiDeleteIntegrationConfigurationRequest + + // DeleteIntegrationConfigurationExecute executes the request + DeleteIntegrationConfigurationExecute(r ApiDeleteIntegrationConfigurationRequest) (*http.Response, error) + + /* + GetAllIntegrationConfigurations Get all configurations for the integration + + Get all integration configurations with the specified integration key. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey Integration key + @return ApiGetAllIntegrationConfigurationsRequest + */ + GetAllIntegrationConfigurations(ctx context.Context, integrationKey string) ApiGetAllIntegrationConfigurationsRequest + + // GetAllIntegrationConfigurationsExecute executes the request + // @return IntegrationConfigurationCollectionRep + GetAllIntegrationConfigurationsExecute(r ApiGetAllIntegrationConfigurationsRequest) (*IntegrationConfigurationCollectionRep, *http.Response, error) + + /* + GetIntegrationConfiguration Get an integration configuration + + Get integration configuration with the specified ID. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId Integration configuration ID + @return ApiGetIntegrationConfigurationRequest + */ + GetIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiGetIntegrationConfigurationRequest + + // GetIntegrationConfigurationExecute executes the request + // @return IntegrationConfigurationsRep + GetIntegrationConfigurationExecute(r ApiGetIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) + + /* + UpdateIntegrationConfiguration Update integration configuration + + Update an integration configuration. Updating an integration configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId The ID of the integration configuration + @return ApiUpdateIntegrationConfigurationRequest + */ + UpdateIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiUpdateIntegrationConfigurationRequest + + // UpdateIntegrationConfigurationExecute executes the request + // @return IntegrationConfigurationsRep + UpdateIntegrationConfigurationExecute(r ApiUpdateIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) +} + +// IntegrationsBetaApiService IntegrationsBetaApi service +type IntegrationsBetaApiService service + +type ApiCreateIntegrationConfigurationRequest struct { + ctx context.Context + ApiService IntegrationsBetaApi + integrationKey string + integrationConfigurationPost *IntegrationConfigurationPost +} + +func (r ApiCreateIntegrationConfigurationRequest) IntegrationConfigurationPost(integrationConfigurationPost IntegrationConfigurationPost) ApiCreateIntegrationConfigurationRequest { + r.integrationConfigurationPost = &integrationConfigurationPost + return r +} + +func (r ApiCreateIntegrationConfigurationRequest) Execute() (*IntegrationConfigurationsRep, *http.Response, error) { + return r.ApiService.CreateIntegrationConfigurationExecute(r) +} + +/* +CreateIntegrationConfiguration Create integration configuration + +Create a new integration configuration. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey The integration key + @return ApiCreateIntegrationConfigurationRequest +*/ +func (a *IntegrationsBetaApiService) CreateIntegrationConfiguration(ctx context.Context, integrationKey string) ApiCreateIntegrationConfigurationRequest { + return ApiCreateIntegrationConfigurationRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return IntegrationConfigurationsRep +func (a *IntegrationsBetaApiService) CreateIntegrationConfigurationExecute(r ApiCreateIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationConfigurationsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationsBetaApiService.CreateIntegrationConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-configurations/keys/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.integrationConfigurationPost == nil { + return localVarReturnValue, nil, reportError("integrationConfigurationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.integrationConfigurationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteIntegrationConfigurationRequest struct { + ctx context.Context + ApiService IntegrationsBetaApi + integrationConfigurationId string +} + +func (r ApiDeleteIntegrationConfigurationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteIntegrationConfigurationExecute(r) +} + +/* +DeleteIntegrationConfiguration Delete integration configuration + +Delete an integration configuration by ID. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId The ID of the integration configuration to be deleted + @return ApiDeleteIntegrationConfigurationRequest +*/ +func (a *IntegrationsBetaApiService) DeleteIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiDeleteIntegrationConfigurationRequest { + return ApiDeleteIntegrationConfigurationRequest{ + ApiService: a, + ctx: ctx, + integrationConfigurationId: integrationConfigurationId, + } +} + +// Execute executes the request +func (a *IntegrationsBetaApiService) DeleteIntegrationConfigurationExecute(r ApiDeleteIntegrationConfigurationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationsBetaApiService.DeleteIntegrationConfiguration") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-configurations/{integrationConfigurationId}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationConfigurationId"+"}", url.PathEscape(parameterToString(r.integrationConfigurationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetAllIntegrationConfigurationsRequest struct { + ctx context.Context + ApiService IntegrationsBetaApi + integrationKey string +} + +func (r ApiGetAllIntegrationConfigurationsRequest) Execute() (*IntegrationConfigurationCollectionRep, *http.Response, error) { + return r.ApiService.GetAllIntegrationConfigurationsExecute(r) +} + +/* +GetAllIntegrationConfigurations Get all configurations for the integration + +Get all integration configurations with the specified integration key. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationKey Integration key + @return ApiGetAllIntegrationConfigurationsRequest +*/ +func (a *IntegrationsBetaApiService) GetAllIntegrationConfigurations(ctx context.Context, integrationKey string) ApiGetAllIntegrationConfigurationsRequest { + return ApiGetAllIntegrationConfigurationsRequest{ + ApiService: a, + ctx: ctx, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return IntegrationConfigurationCollectionRep +func (a *IntegrationsBetaApiService) GetAllIntegrationConfigurationsExecute(r ApiGetAllIntegrationConfigurationsRequest) (*IntegrationConfigurationCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationConfigurationCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationsBetaApiService.GetAllIntegrationConfigurations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-configurations/keys/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetIntegrationConfigurationRequest struct { + ctx context.Context + ApiService IntegrationsBetaApi + integrationConfigurationId string +} + +func (r ApiGetIntegrationConfigurationRequest) Execute() (*IntegrationConfigurationsRep, *http.Response, error) { + return r.ApiService.GetIntegrationConfigurationExecute(r) +} + +/* +GetIntegrationConfiguration Get an integration configuration + +Get integration configuration with the specified ID. (Excludes [persistent store](https://launchdarkly.com/docs/api/persistent-store-integrations-beta) and [flag import configurations](https://launchdarkly.com/docs/api/flag-import-configurations-beta).) + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId Integration configuration ID + @return ApiGetIntegrationConfigurationRequest +*/ +func (a *IntegrationsBetaApiService) GetIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiGetIntegrationConfigurationRequest { + return ApiGetIntegrationConfigurationRequest{ + ApiService: a, + ctx: ctx, + integrationConfigurationId: integrationConfigurationId, + } +} + +// Execute executes the request +// @return IntegrationConfigurationsRep +func (a *IntegrationsBetaApiService) GetIntegrationConfigurationExecute(r ApiGetIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationConfigurationsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationsBetaApiService.GetIntegrationConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-configurations/{integrationConfigurationId}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationConfigurationId"+"}", url.PathEscape(parameterToString(r.integrationConfigurationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateIntegrationConfigurationRequest struct { + ctx context.Context + ApiService IntegrationsBetaApi + integrationConfigurationId string + patchOperation *[]PatchOperation +} + +func (r ApiUpdateIntegrationConfigurationRequest) PatchOperation(patchOperation []PatchOperation) ApiUpdateIntegrationConfigurationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiUpdateIntegrationConfigurationRequest) Execute() (*IntegrationConfigurationsRep, *http.Response, error) { + return r.ApiService.UpdateIntegrationConfigurationExecute(r) +} + +/* +UpdateIntegrationConfiguration Update integration configuration + +Update an integration configuration. Updating an integration configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param integrationConfigurationId The ID of the integration configuration + @return ApiUpdateIntegrationConfigurationRequest +*/ +func (a *IntegrationsBetaApiService) UpdateIntegrationConfiguration(ctx context.Context, integrationConfigurationId string) ApiUpdateIntegrationConfigurationRequest { + return ApiUpdateIntegrationConfigurationRequest{ + ApiService: a, + ctx: ctx, + integrationConfigurationId: integrationConfigurationId, + } +} + +// Execute executes the request +// @return IntegrationConfigurationsRep +func (a *IntegrationsBetaApiService) UpdateIntegrationConfigurationExecute(r ApiUpdateIntegrationConfigurationRequest) (*IntegrationConfigurationsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IntegrationConfigurationsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "IntegrationsBetaApiService.UpdateIntegrationConfiguration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-configurations/{integrationConfigurationId}" + localVarPath = strings.Replace(localVarPath, "{"+"integrationConfigurationId"+"}", url.PathEscape(parameterToString(r.integrationConfigurationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_layers.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_layers.go new file mode 100644 index 00000000..161ee406 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_layers.go @@ -0,0 +1,766 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type LayersApi interface { + + /* + CreateLayer Create layer + + Create a layer. Experiments running in the same layer are granted mutually-exclusive traffic. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiCreateLayerRequest + */ + CreateLayer(ctx context.Context, projectKey string) ApiCreateLayerRequest + + // CreateLayerExecute executes the request + // @return LayerRep + CreateLayerExecute(r ApiCreateLayerRequest) (*LayerRep, *http.Response, error) + + /* + GetLayers Get layers + + Get a collection of all layers for a project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetLayersRequest + */ + GetLayers(ctx context.Context, projectKey string) ApiGetLayersRequest + + // GetLayersExecute executes the request + // @return LayerCollectionRep + GetLayersExecute(r ApiGetLayersRequest) (*LayerCollectionRep, *http.Response, error) + + /* + UpdateLayer Update layer + + Update a layer by adding, changing, or removing traffic reservations for experiments, or by changing layer name or description. +Updating a layer uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating layers. + +
+Click to expand instructions for updating layers + +#### updateName + +Updates the layer name. + +##### Parameters + +- `name`: The new layer name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "name": "New name" + }] +} +``` + +#### updateDescription + +Updates the layer description. + +##### Parameters + +- `description`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "description": "New description" + }] +} +``` + +#### updateExperimentReservation + +Adds or updates a traffic reservation for an experiment in a layer. + +##### Parameters + +- `experimentKey`: The key of the experiment whose reservation you are adding to or updating in the layer. +- `reservationPercent`: The amount of traffic in the layer to reserve. Must be an integer. Zero is allowed until iteration start. + +Here's an example: + +```json +{ + "environmentKey": "production", + "instructions": [{ + "kind": "updateExperimentReservation", + "experimentKey": "exp-key", + "reservationPercent": 10 + }] +} +``` + +#### removeExperiment + +Removes a traffic reservation for an experiment from a layer. + +##### Parameters + +- `experimentKey`: The key of the experiment whose reservation you want to remove from the layer. + +Here's an example: + +```json +{ + "environmentKey": "production", + "instructions": [{ + "kind": "removeExperiment", + "experimentKey": "exp-key" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param layerKey The layer key + @return ApiUpdateLayerRequest + */ + UpdateLayer(ctx context.Context, projectKey string, layerKey string) ApiUpdateLayerRequest + + // UpdateLayerExecute executes the request + // @return LayerRep + UpdateLayerExecute(r ApiUpdateLayerRequest) (*LayerRep, *http.Response, error) +} + +// LayersApiService LayersApi service +type LayersApiService service + +type ApiCreateLayerRequest struct { + ctx context.Context + ApiService LayersApi + projectKey string + layerPost *LayerPost +} + +func (r ApiCreateLayerRequest) LayerPost(layerPost LayerPost) ApiCreateLayerRequest { + r.layerPost = &layerPost + return r +} + +func (r ApiCreateLayerRequest) Execute() (*LayerRep, *http.Response, error) { + return r.ApiService.CreateLayerExecute(r) +} + +/* +CreateLayer Create layer + +Create a layer. Experiments running in the same layer are granted mutually-exclusive traffic. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiCreateLayerRequest +*/ +func (a *LayersApiService) CreateLayer(ctx context.Context, projectKey string) ApiCreateLayerRequest { + return ApiCreateLayerRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return LayerRep +func (a *LayersApiService) CreateLayerExecute(r ApiCreateLayerRequest) (*LayerRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *LayerRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "LayersApiService.CreateLayer") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/layers" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.layerPost == nil { + return localVarReturnValue, nil, reportError("layerPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.layerPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetLayersRequest struct { + ctx context.Context + ApiService LayersApi + projectKey string + filter *string +} + +// A comma-separated list of filters. This endpoint only accepts filtering by `experimentKey`. The filter returns layers which include that experiment for the selected environment(s). For example: `filter=reservations.experimentKey contains expKey`. +func (r ApiGetLayersRequest) Filter(filter string) ApiGetLayersRequest { + r.filter = &filter + return r +} + +func (r ApiGetLayersRequest) Execute() (*LayerCollectionRep, *http.Response, error) { + return r.ApiService.GetLayersExecute(r) +} + +/* +GetLayers Get layers + +Get a collection of all layers for a project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetLayersRequest +*/ +func (a *LayersApiService) GetLayers(ctx context.Context, projectKey string) ApiGetLayersRequest { + return ApiGetLayersRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return LayerCollectionRep +func (a *LayersApiService) GetLayersExecute(r ApiGetLayersRequest) (*LayerCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *LayerCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "LayersApiService.GetLayers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/layers" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateLayerRequest struct { + ctx context.Context + ApiService LayersApi + projectKey string + layerKey string + layerPatchInput *LayerPatchInput +} + +func (r ApiUpdateLayerRequest) LayerPatchInput(layerPatchInput LayerPatchInput) ApiUpdateLayerRequest { + r.layerPatchInput = &layerPatchInput + return r +} + +func (r ApiUpdateLayerRequest) Execute() (*LayerRep, *http.Response, error) { + return r.ApiService.UpdateLayerExecute(r) +} + +/* +UpdateLayer Update layer + +Update a layer by adding, changing, or removing traffic reservations for experiments, or by changing layer name or description. +Updating a layer uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating layers. + +
+Click to expand instructions for updating layers + +#### updateName + +Updates the layer name. + +##### Parameters + +- `name`: The new layer name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "name": "New name" + }] +} +``` + +#### updateDescription + +Updates the layer description. + +##### Parameters + +- `description`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "description": "New description" + }] +} +``` + +#### updateExperimentReservation + +Adds or updates a traffic reservation for an experiment in a layer. + +##### Parameters + +- `experimentKey`: The key of the experiment whose reservation you are adding to or updating in the layer. +- `reservationPercent`: The amount of traffic in the layer to reserve. Must be an integer. Zero is allowed until iteration start. + +Here's an example: + +```json +{ + "environmentKey": "production", + "instructions": [{ + "kind": "updateExperimentReservation", + "experimentKey": "exp-key", + "reservationPercent": 10 + }] +} +``` + +#### removeExperiment + +Removes a traffic reservation for an experiment from a layer. + +##### Parameters + +- `experimentKey`: The key of the experiment whose reservation you want to remove from the layer. + +Here's an example: + +```json +{ + "environmentKey": "production", + "instructions": [{ + "kind": "removeExperiment", + "experimentKey": "exp-key" + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param layerKey The layer key + @return ApiUpdateLayerRequest +*/ +func (a *LayersApiService) UpdateLayer(ctx context.Context, projectKey string, layerKey string) ApiUpdateLayerRequest { + return ApiUpdateLayerRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + layerKey: layerKey, + } +} + +// Execute executes the request +// @return LayerRep +func (a *LayersApiService) UpdateLayerExecute(r ApiUpdateLayerRequest) (*LayerRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *LayerRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "LayersApiService.UpdateLayer") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/layers/{layerKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"layerKey"+"}", url.PathEscape(parameterToString(r.layerKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.layerPatchInput == nil { + return localVarReturnValue, nil, reportError("layerPatchInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.layerPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics.go new file mode 100644 index 00000000..a14cec4d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics.go @@ -0,0 +1,1086 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type MetricsApi interface { + + /* + DeleteMetric Delete metric + + Delete a metric by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiDeleteMetricRequest + */ + DeleteMetric(ctx context.Context, projectKey string, metricKey string) ApiDeleteMetricRequest + + // DeleteMetricExecute executes the request + DeleteMetricExecute(r ApiDeleteMetricRequest) (*http.Response, error) + + /* + GetMetric Get metric + + Get information for a single metric from the specific project. + +### Expanding the metric response +LaunchDarkly supports four fields for expanding the "Get metric" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `experiments` includes all experiments from the specific project that use the metric +- `experimentCount` includes the number of experiments from the specific project that use the metric +- `metricGroups` includes all metric groups from the specific project that use the metric +- `metricGroupCount` includes the number of metric groups from the specific project that use the metric + +For example, `expand=experiments` includes the `experiments` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiGetMetricRequest + */ + GetMetric(ctx context.Context, projectKey string, metricKey string) ApiGetMetricRequest + + // GetMetricExecute executes the request + // @return MetricRep + GetMetricExecute(r ApiGetMetricRequest) (*MetricRep, *http.Response, error) + + /* + GetMetrics List metrics + + Get a list of all metrics for the specified project. + +### Filtering metrics + +The `filter` parameter supports the following operators: `contains`, `equals`. + +#### Supported fields and operators + +You can only filter certain fields in metrics when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for metrics, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `eventKind` | The metric event kind. One of `custom`, `pageview`, `click`. | `equals` | +| `hasConnections` | Whether the metric has connections to experiments or guarded rollouts. One of `true`, `false`. | `equals` | +| `isNumeric` | Whether the metric is numeric. One of `true`, `false`. | `equals` | +| `maintainerIds` | A comma-separated list of metric maintainer IDs. | `equals` | +| `maintainerTeamKey` | The metric maintainer team key. | `equals` | +| `query` | A "fuzzy" search across metric key and name. Supply a string or list of strings to the operator. | `equals` | +| `tags` | The metric tags. | `contains` | +| `unitAggregationType` | The metric's unit aggregation type. One of `sum`, `average`. | `equals` | + +For example, the filter `?filter=tags contains ["tag1", "tag2", "tag3"]` matches metrics that have all three tags. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `[` in `?filter=tags contains ["tag1", "tag2", "tag3"]` must be encoded to `%5B`. + +### Expanding the metric list response + +LaunchDarkly supports expanding the "List metrics" response. By default, the expandable field is **not** included in the response. + +To expand the response, append the `expand` query parameter and add the following supported field: + +- `experimentCount` includes the number of experiments from the specific project that use the metric + +For example, `expand=experimentCount` includes the `experimentCount` field for each metric in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetMetricsRequest + */ + GetMetrics(ctx context.Context, projectKey string) ApiGetMetricsRequest + + // GetMetricsExecute executes the request + // @return MetricCollectionRep + GetMetricsExecute(r ApiGetMetricsRequest) (*MetricCollectionRep, *http.Response, error) + + /* + PatchMetric Update metric + + Patch a metric by key. Updating a metric uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiPatchMetricRequest + */ + PatchMetric(ctx context.Context, projectKey string, metricKey string) ApiPatchMetricRequest + + // PatchMetricExecute executes the request + // @return MetricRep + PatchMetricExecute(r ApiPatchMetricRequest) (*MetricRep, *http.Response, error) + + /* + PostMetric Create metric + + Create a new metric in the specified project. The expected `POST` body differs depending on the specified `kind` property. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostMetricRequest + */ + PostMetric(ctx context.Context, projectKey string) ApiPostMetricRequest + + // PostMetricExecute executes the request + // @return MetricRep + PostMetricExecute(r ApiPostMetricRequest) (*MetricRep, *http.Response, error) +} + +// MetricsApiService MetricsApi service +type MetricsApiService service + +type ApiDeleteMetricRequest struct { + ctx context.Context + ApiService MetricsApi + projectKey string + metricKey string +} + +func (r ApiDeleteMetricRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteMetricExecute(r) +} + +/* +DeleteMetric Delete metric + +Delete a metric by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiDeleteMetricRequest +*/ +func (a *MetricsApiService) DeleteMetric(ctx context.Context, projectKey string, metricKey string) ApiDeleteMetricRequest { + return ApiDeleteMetricRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricKey: metricKey, + } +} + +// Execute executes the request +func (a *MetricsApiService) DeleteMetricExecute(r ApiDeleteMetricRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsApiService.DeleteMetric") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/metrics/{projectKey}/{metricKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricKey"+"}", url.PathEscape(parameterToString(r.metricKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetMetricRequest struct { + ctx context.Context + ApiService MetricsApi + projectKey string + metricKey string + expand *string + versionId *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMetricRequest) Expand(expand string) ApiGetMetricRequest { + r.expand = &expand + return r +} + +// The specific version ID of the metric +func (r ApiGetMetricRequest) VersionId(versionId string) ApiGetMetricRequest { + r.versionId = &versionId + return r +} + +func (r ApiGetMetricRequest) Execute() (*MetricRep, *http.Response, error) { + return r.ApiService.GetMetricExecute(r) +} + +/* +GetMetric Get metric + +Get information for a single metric from the specific project. + +### Expanding the metric response +LaunchDarkly supports four fields for expanding the "Get metric" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +- `experiments` includes all experiments from the specific project that use the metric +- `experimentCount` includes the number of experiments from the specific project that use the metric +- `metricGroups` includes all metric groups from the specific project that use the metric +- `metricGroupCount` includes the number of metric groups from the specific project that use the metric + +For example, `expand=experiments` includes the `experiments` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiGetMetricRequest +*/ +func (a *MetricsApiService) GetMetric(ctx context.Context, projectKey string, metricKey string) ApiGetMetricRequest { + return ApiGetMetricRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricKey: metricKey, + } +} + +// Execute executes the request +// @return MetricRep +func (a *MetricsApiService) GetMetricExecute(r ApiGetMetricRequest) (*MetricRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsApiService.GetMetric") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/metrics/{projectKey}/{metricKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricKey"+"}", url.PathEscape(parameterToString(r.metricKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.versionId != nil { + localVarQueryParams.Add("versionId", parameterToString(*r.versionId, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMetricsRequest struct { + ctx context.Context + ApiService MetricsApi + projectKey string + expand *string + limit *int64 + offset *int64 + sort *string + filter *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMetricsRequest) Expand(expand string) ApiGetMetricsRequest { + r.expand = &expand + return r +} + +// The number of metrics to return in the response. Defaults to 20. Maximum limit is 50. +func (r ApiGetMetricsRequest) Limit(limit int64) ApiGetMetricsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and returns the next `limit` items. +func (r ApiGetMetricsRequest) Offset(offset int64) ApiGetMetricsRequest { + r.offset = &offset + return r +} + +// A field to sort the items by. Prefix field by a dash ( - ) to sort in descending order. This endpoint supports sorting by `createdAt` or `name`. +func (r ApiGetMetricsRequest) Sort(sort string) ApiGetMetricsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of filters. This endpoint accepts filtering by `query`, `tags`, 'eventKind', 'isNumeric', 'unitAggregationType`, `hasConnections`, `maintainerIds`, and `maintainerTeamKey`. To learn more about the filter syntax, read the 'Filtering metrics' section above. +func (r ApiGetMetricsRequest) Filter(filter string) ApiGetMetricsRequest { + r.filter = &filter + return r +} + +func (r ApiGetMetricsRequest) Execute() (*MetricCollectionRep, *http.Response, error) { + return r.ApiService.GetMetricsExecute(r) +} + +/* +GetMetrics List metrics + +Get a list of all metrics for the specified project. + +### Filtering metrics + +The `filter` parameter supports the following operators: `contains`, `equals`. + +#### Supported fields and operators + +You can only filter certain fields in metrics when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for metrics, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `eventKind` | The metric event kind. One of `custom`, `pageview`, `click`. | `equals` | +| `hasConnections` | Whether the metric has connections to experiments or guarded rollouts. One of `true`, `false`. | `equals` | +| `isNumeric` | Whether the metric is numeric. One of `true`, `false`. | `equals` | +| `maintainerIds` | A comma-separated list of metric maintainer IDs. | `equals` | +| `maintainerTeamKey` | The metric maintainer team key. | `equals` | +| `query` | A "fuzzy" search across metric key and name. Supply a string or list of strings to the operator. | `equals` | +| `tags` | The metric tags. | `contains` | +| `unitAggregationType` | The metric's unit aggregation type. One of `sum`, `average`. | `equals` | + +For example, the filter `?filter=tags contains ["tag1", "tag2", "tag3"]` matches metrics that have all three tags. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `[` in `?filter=tags contains ["tag1", "tag2", "tag3"]` must be encoded to `%5B`. + +### Expanding the metric list response + +LaunchDarkly supports expanding the "List metrics" response. By default, the expandable field is **not** included in the response. + +To expand the response, append the `expand` query parameter and add the following supported field: + +- `experimentCount` includes the number of experiments from the specific project that use the metric + +For example, `expand=experimentCount` includes the `experimentCount` field for each metric in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetMetricsRequest +*/ +func (a *MetricsApiService) GetMetrics(ctx context.Context, projectKey string) ApiGetMetricsRequest { + return ApiGetMetricsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return MetricCollectionRep +func (a *MetricsApiService) GetMetricsExecute(r ApiGetMetricsRequest) (*MetricCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsApiService.GetMetrics") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/metrics/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchMetricRequest struct { + ctx context.Context + ApiService MetricsApi + projectKey string + metricKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchMetricRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchMetricRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchMetricRequest) Execute() (*MetricRep, *http.Response, error) { + return r.ApiService.PatchMetricExecute(r) +} + +/* +PatchMetric Update metric + +Patch a metric by key. Updating a metric uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricKey The metric key + @return ApiPatchMetricRequest +*/ +func (a *MetricsApiService) PatchMetric(ctx context.Context, projectKey string, metricKey string) ApiPatchMetricRequest { + return ApiPatchMetricRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricKey: metricKey, + } +} + +// Execute executes the request +// @return MetricRep +func (a *MetricsApiService) PatchMetricExecute(r ApiPatchMetricRequest) (*MetricRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsApiService.PatchMetric") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/metrics/{projectKey}/{metricKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricKey"+"}", url.PathEscape(parameterToString(r.metricKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostMetricRequest struct { + ctx context.Context + ApiService MetricsApi + projectKey string + metricPost *MetricPost +} + +func (r ApiPostMetricRequest) MetricPost(metricPost MetricPost) ApiPostMetricRequest { + r.metricPost = &metricPost + return r +} + +func (r ApiPostMetricRequest) Execute() (*MetricRep, *http.Response, error) { + return r.ApiService.PostMetricExecute(r) +} + +/* +PostMetric Create metric + +Create a new metric in the specified project. The expected `POST` body differs depending on the specified `kind` property. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostMetricRequest +*/ +func (a *MetricsApiService) PostMetric(ctx context.Context, projectKey string) ApiPostMetricRequest { + return ApiPostMetricRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return MetricRep +func (a *MetricsApiService) PostMetricExecute(r ApiPostMetricRequest) (*MetricRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsApiService.PostMetric") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/metrics/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.metricPost == nil { + return localVarReturnValue, nil, reportError("metricPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.metricPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics_beta.go new file mode 100644 index 00000000..d53b8f3a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_metrics_beta.go @@ -0,0 +1,1176 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type MetricsBetaApi interface { + + /* + CreateMetricGroup Create metric group + + Create a new metric group in the specified project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiCreateMetricGroupRequest + */ + CreateMetricGroup(ctx context.Context, projectKey string) ApiCreateMetricGroupRequest + + // CreateMetricGroupExecute executes the request + // @return MetricGroupRep + CreateMetricGroupExecute(r ApiCreateMetricGroupRequest) (*MetricGroupRep, *http.Response, error) + + /* + DeleteMetricGroup Delete metric group + + Delete a metric group by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiDeleteMetricGroupRequest + */ + DeleteMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiDeleteMetricGroupRequest + + // DeleteMetricGroupExecute executes the request + DeleteMetricGroupExecute(r ApiDeleteMetricGroupRequest) (*http.Response, error) + + /* + GetMetricGroup Get metric group + + Get information for a single metric group from the specific project. + +### Expanding the metric group response +LaunchDarkly supports two fields for expanding the "Get metric group" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with either or both of the following fields: + +- `experiments` includes all experiments from the specific project that use the metric group +- `experimentCount` includes the number of experiments from the specific project that use the metric group + +For example, `expand=experiments` includes the `experiments` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiGetMetricGroupRequest + */ + GetMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiGetMetricGroupRequest + + // GetMetricGroupExecute executes the request + // @return MetricGroupRep + GetMetricGroupExecute(r ApiGetMetricGroupRequest) (*MetricGroupRep, *http.Response, error) + + /* + GetMetricGroups List metric groups + + Get a list of all metric groups for the specified project. + +### Expanding the metric groups response +LaunchDarkly supports one field for expanding the "Get metric groups" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with the following field: + +- `experiments` includes all experiments from the specific project that use the metric group + +For example, `expand=experiments` includes the `experiments` field in the response. + +### Filtering metric groups + +The `filter` parameter supports the following operators: `contains`, `equals`. + +#### Supported fields and operators + +You can only filter certain fields in metrics when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for metrics, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `experimentStatus` | The experiment's status. One of `not_started`, `running`, `stopped`, `started`. | `equals` | +| `hasConnections` | Whether the metric group has connections to experiments or guarded rollouts. One of `true`, `false`. | `equals` | +| `kind` | The metric group kind. One of `funnel`, `standard`. | `equals` | +| `maintainerIds` | The metric maintainer IDs. | `equals` | +| `maintainerTeamKey` | The metric maintainer team key. | `equals` | +| `query` | A "fuzzy" search across metric group key and name. Supply a string or list of strings to the operator. | `equals` | + +### Sorting metric groups + +LaunchDarkly supports the following fields for sorting: + +- `name` sorts by metric group name. +- `createdAt` sorts by the creation date of the metric group. +- `connectionCount` sorts by the number of connections to experiments the metric group has. + +By default, the sort is in ascending order. Use `-` to sort in descending order. For example, `?sort=name` sorts the response by metric group name in ascending order, and `?sort=-name` sorts in descending order. + +#### Sample query + +`filter=experimentStatus equals 'not_started' and query equals 'metric name'` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetMetricGroupsRequest + */ + GetMetricGroups(ctx context.Context, projectKey string) ApiGetMetricGroupsRequest + + // GetMetricGroupsExecute executes the request + // @return MetricGroupCollectionRep + GetMetricGroupsExecute(r ApiGetMetricGroupsRequest) (*MetricGroupCollectionRep, *http.Response, error) + + /* + PatchMetricGroup Patch metric group + + Patch a metric group by key. Updating a metric group uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiPatchMetricGroupRequest + */ + PatchMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiPatchMetricGroupRequest + + // PatchMetricGroupExecute executes the request + // @return MetricGroupRep + PatchMetricGroupExecute(r ApiPatchMetricGroupRequest) (*MetricGroupRep, *http.Response, error) +} + +// MetricsBetaApiService MetricsBetaApi service +type MetricsBetaApiService service + +type ApiCreateMetricGroupRequest struct { + ctx context.Context + ApiService MetricsBetaApi + projectKey string + metricGroupPost *MetricGroupPost +} + +func (r ApiCreateMetricGroupRequest) MetricGroupPost(metricGroupPost MetricGroupPost) ApiCreateMetricGroupRequest { + r.metricGroupPost = &metricGroupPost + return r +} + +func (r ApiCreateMetricGroupRequest) Execute() (*MetricGroupRep, *http.Response, error) { + return r.ApiService.CreateMetricGroupExecute(r) +} + +/* +CreateMetricGroup Create metric group + +Create a new metric group in the specified project + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiCreateMetricGroupRequest +*/ +func (a *MetricsBetaApiService) CreateMetricGroup(ctx context.Context, projectKey string) ApiCreateMetricGroupRequest { + return ApiCreateMetricGroupRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return MetricGroupRep +func (a *MetricsBetaApiService) CreateMetricGroupExecute(r ApiCreateMetricGroupRequest) (*MetricGroupRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricGroupRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsBetaApiService.CreateMetricGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/metric-groups" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.metricGroupPost == nil { + return localVarReturnValue, nil, reportError("metricGroupPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.metricGroupPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteMetricGroupRequest struct { + ctx context.Context + ApiService MetricsBetaApi + projectKey string + metricGroupKey string +} + +func (r ApiDeleteMetricGroupRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteMetricGroupExecute(r) +} + +/* +DeleteMetricGroup Delete metric group + +Delete a metric group by key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiDeleteMetricGroupRequest +*/ +func (a *MetricsBetaApiService) DeleteMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiDeleteMetricGroupRequest { + return ApiDeleteMetricGroupRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricGroupKey: metricGroupKey, + } +} + +// Execute executes the request +func (a *MetricsBetaApiService) DeleteMetricGroupExecute(r ApiDeleteMetricGroupRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsBetaApiService.DeleteMetricGroup") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/metric-groups/{metricGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricGroupKey"+"}", url.PathEscape(parameterToString(r.metricGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetMetricGroupRequest struct { + ctx context.Context + ApiService MetricsBetaApi + projectKey string + metricGroupKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMetricGroupRequest) Expand(expand string) ApiGetMetricGroupRequest { + r.expand = &expand + return r +} + +func (r ApiGetMetricGroupRequest) Execute() (*MetricGroupRep, *http.Response, error) { + return r.ApiService.GetMetricGroupExecute(r) +} + +/* +GetMetricGroup Get metric group + +Get information for a single metric group from the specific project. + +### Expanding the metric group response +LaunchDarkly supports two fields for expanding the "Get metric group" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with either or both of the following fields: + +- `experiments` includes all experiments from the specific project that use the metric group +- `experimentCount` includes the number of experiments from the specific project that use the metric group + +For example, `expand=experiments` includes the `experiments` field in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiGetMetricGroupRequest +*/ +func (a *MetricsBetaApiService) GetMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiGetMetricGroupRequest { + return ApiGetMetricGroupRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricGroupKey: metricGroupKey, + } +} + +// Execute executes the request +// @return MetricGroupRep +func (a *MetricsBetaApiService) GetMetricGroupExecute(r ApiGetMetricGroupRequest) (*MetricGroupRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricGroupRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsBetaApiService.GetMetricGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/metric-groups/{metricGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricGroupKey"+"}", url.PathEscape(parameterToString(r.metricGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetMetricGroupsRequest struct { + ctx context.Context + ApiService MetricsBetaApi + projectKey string + filter *string + sort *string + expand *string + limit *int64 + offset *int64 +} + +// Accepts filter by `experimentStatus`, `query`, `kind`, `hasConnections`, `maintainerIds`, and `maintainerTeamKey`. Example: `filter=experimentStatus equals 'running' and query equals 'test'`. +func (r ApiGetMetricGroupsRequest) Filter(filter string) ApiGetMetricGroupsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order. Read the endpoint description for a full list of available sort fields. +func (r ApiGetMetricGroupsRequest) Sort(sort string) ApiGetMetricGroupsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetMetricGroupsRequest) Expand(expand string) ApiGetMetricGroupsRequest { + r.expand = &expand + return r +} + +// The number of metric groups to return in the response. Defaults to 20. Maximum limit is 50. +func (r ApiGetMetricGroupsRequest) Limit(limit int64) ApiGetMetricGroupsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and returns the next `limit` items. +func (r ApiGetMetricGroupsRequest) Offset(offset int64) ApiGetMetricGroupsRequest { + r.offset = &offset + return r +} + +func (r ApiGetMetricGroupsRequest) Execute() (*MetricGroupCollectionRep, *http.Response, error) { + return r.ApiService.GetMetricGroupsExecute(r) +} + +/* +GetMetricGroups List metric groups + +Get a list of all metric groups for the specified project. + +### Expanding the metric groups response +LaunchDarkly supports one field for expanding the "Get metric groups" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with the following field: + +- `experiments` includes all experiments from the specific project that use the metric group + +For example, `expand=experiments` includes the `experiments` field in the response. + +### Filtering metric groups + +The `filter` parameter supports the following operators: `contains`, `equals`. + +#### Supported fields and operators + +You can only filter certain fields in metrics when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for metrics, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `experimentStatus` | The experiment's status. One of `not_started`, `running`, `stopped`, `started`. | `equals` | +| `hasConnections` | Whether the metric group has connections to experiments or guarded rollouts. One of `true`, `false`. | `equals` | +| `kind` | The metric group kind. One of `funnel`, `standard`. | `equals` | +| `maintainerIds` | The metric maintainer IDs. | `equals` | +| `maintainerTeamKey` | The metric maintainer team key. | `equals` | +| `query` | A "fuzzy" search across metric group key and name. Supply a string or list of strings to the operator. | `equals` | + +### Sorting metric groups + +LaunchDarkly supports the following fields for sorting: + +- `name` sorts by metric group name. +- `createdAt` sorts by the creation date of the metric group. +- `connectionCount` sorts by the number of connections to experiments the metric group has. + +By default, the sort is in ascending order. Use `-` to sort in descending order. For example, `?sort=name` sorts the response by metric group name in ascending order, and `?sort=-name` sorts in descending order. + +#### Sample query + +`filter=experimentStatus equals 'not_started' and query equals 'metric name'` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetMetricGroupsRequest +*/ +func (a *MetricsBetaApiService) GetMetricGroups(ctx context.Context, projectKey string) ApiGetMetricGroupsRequest { + return ApiGetMetricGroupsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return MetricGroupCollectionRep +func (a *MetricsBetaApiService) GetMetricGroupsExecute(r ApiGetMetricGroupsRequest) (*MetricGroupCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricGroupCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsBetaApiService.GetMetricGroups") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/metric-groups" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchMetricGroupRequest struct { + ctx context.Context + ApiService MetricsBetaApi + projectKey string + metricGroupKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchMetricGroupRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchMetricGroupRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchMetricGroupRequest) Execute() (*MetricGroupRep, *http.Response, error) { + return r.ApiService.PatchMetricGroupExecute(r) +} + +/* +PatchMetricGroup Patch metric group + +Patch a metric group by key. Updating a metric group uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param metricGroupKey The metric group key + @return ApiPatchMetricGroupRequest +*/ +func (a *MetricsBetaApiService) PatchMetricGroup(ctx context.Context, projectKey string, metricGroupKey string) ApiPatchMetricGroupRequest { + return ApiPatchMetricGroupRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + metricGroupKey: metricGroupKey, + } +} + +// Execute executes the request +// @return MetricGroupRep +func (a *MetricsBetaApiService) PatchMetricGroupExecute(r ApiPatchMetricGroupRequest) (*MetricGroupRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *MetricGroupRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "MetricsBetaApiService.PatchMetricGroup") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/metric-groups/{metricGroupKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"metricGroupKey"+"}", url.PathEscape(parameterToString(r.metricGroupKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_o_auth2_clients.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_o_auth2_clients.go new file mode 100644 index 00000000..6e351505 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_o_auth2_clients.go @@ -0,0 +1,863 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type OAuth2ClientsApi interface { + + /* + CreateOAuth2Client Create a LaunchDarkly OAuth 2.0 client + + Create (register) a LaunchDarkly OAuth2 client. OAuth2 clients allow you to build custom integrations using LaunchDarkly as your identity provider. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateOAuth2ClientRequest + */ + CreateOAuth2Client(ctx context.Context) ApiCreateOAuth2ClientRequest + + // CreateOAuth2ClientExecute executes the request + // @return Client + CreateOAuth2ClientExecute(r ApiCreateOAuth2ClientRequest) (*Client, *http.Response, error) + + /* + DeleteOAuthClient Delete OAuth 2.0 client + + Delete an existing OAuth 2.0 client by unique client ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiDeleteOAuthClientRequest + */ + DeleteOAuthClient(ctx context.Context, clientId string) ApiDeleteOAuthClientRequest + + // DeleteOAuthClientExecute executes the request + DeleteOAuthClientExecute(r ApiDeleteOAuthClientRequest) (*http.Response, error) + + /* + GetOAuthClientById Get client by ID + + Get a registered OAuth 2.0 client by unique client ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiGetOAuthClientByIdRequest + */ + GetOAuthClientById(ctx context.Context, clientId string) ApiGetOAuthClientByIdRequest + + // GetOAuthClientByIdExecute executes the request + // @return Client + GetOAuthClientByIdExecute(r ApiGetOAuthClientByIdRequest) (*Client, *http.Response, error) + + /* + GetOAuthClients Get clients + + Get all OAuth 2.0 clients registered by your account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetOAuthClientsRequest + */ + GetOAuthClients(ctx context.Context) ApiGetOAuthClientsRequest + + // GetOAuthClientsExecute executes the request + // @return ClientCollection + GetOAuthClientsExecute(r ApiGetOAuthClientsRequest) (*ClientCollection, *http.Response, error) + + /* + PatchOAuthClient Patch client by ID + + Patch an existing OAuth 2.0 client by client ID. Updating an OAuth2 client uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). Only `name`, `description`, and `redirectUri` may be patched. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiPatchOAuthClientRequest + */ + PatchOAuthClient(ctx context.Context, clientId string) ApiPatchOAuthClientRequest + + // PatchOAuthClientExecute executes the request + // @return Client + PatchOAuthClientExecute(r ApiPatchOAuthClientRequest) (*Client, *http.Response, error) +} + +// OAuth2ClientsApiService OAuth2ClientsApi service +type OAuth2ClientsApiService service + +type ApiCreateOAuth2ClientRequest struct { + ctx context.Context + ApiService OAuth2ClientsApi + oauthClientPost *OauthClientPost +} + +func (r ApiCreateOAuth2ClientRequest) OauthClientPost(oauthClientPost OauthClientPost) ApiCreateOAuth2ClientRequest { + r.oauthClientPost = &oauthClientPost + return r +} + +func (r ApiCreateOAuth2ClientRequest) Execute() (*Client, *http.Response, error) { + return r.ApiService.CreateOAuth2ClientExecute(r) +} + +/* +CreateOAuth2Client Create a LaunchDarkly OAuth 2.0 client + +Create (register) a LaunchDarkly OAuth2 client. OAuth2 clients allow you to build custom integrations using LaunchDarkly as your identity provider. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateOAuth2ClientRequest +*/ +func (a *OAuth2ClientsApiService) CreateOAuth2Client(ctx context.Context) ApiCreateOAuth2ClientRequest { + return ApiCreateOAuth2ClientRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Client +func (a *OAuth2ClientsApiService) CreateOAuth2ClientExecute(r ApiCreateOAuth2ClientRequest) (*Client, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Client + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OAuth2ClientsApiService.CreateOAuth2Client") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/oauth/clients" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.oauthClientPost == nil { + return localVarReturnValue, nil, reportError("oauthClientPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.oauthClientPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteOAuthClientRequest struct { + ctx context.Context + ApiService OAuth2ClientsApi + clientId string +} + +func (r ApiDeleteOAuthClientRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteOAuthClientExecute(r) +} + +/* +DeleteOAuthClient Delete OAuth 2.0 client + +Delete an existing OAuth 2.0 client by unique client ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiDeleteOAuthClientRequest +*/ +func (a *OAuth2ClientsApiService) DeleteOAuthClient(ctx context.Context, clientId string) ApiDeleteOAuthClientRequest { + return ApiDeleteOAuthClientRequest{ + ApiService: a, + ctx: ctx, + clientId: clientId, + } +} + +// Execute executes the request +func (a *OAuth2ClientsApiService) DeleteOAuthClientExecute(r ApiDeleteOAuthClientRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OAuth2ClientsApiService.DeleteOAuthClient") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/oauth/clients/{clientId}" + localVarPath = strings.Replace(localVarPath, "{"+"clientId"+"}", url.PathEscape(parameterToString(r.clientId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetOAuthClientByIdRequest struct { + ctx context.Context + ApiService OAuth2ClientsApi + clientId string +} + +func (r ApiGetOAuthClientByIdRequest) Execute() (*Client, *http.Response, error) { + return r.ApiService.GetOAuthClientByIdExecute(r) +} + +/* +GetOAuthClientById Get client by ID + +Get a registered OAuth 2.0 client by unique client ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiGetOAuthClientByIdRequest +*/ +func (a *OAuth2ClientsApiService) GetOAuthClientById(ctx context.Context, clientId string) ApiGetOAuthClientByIdRequest { + return ApiGetOAuthClientByIdRequest{ + ApiService: a, + ctx: ctx, + clientId: clientId, + } +} + +// Execute executes the request +// @return Client +func (a *OAuth2ClientsApiService) GetOAuthClientByIdExecute(r ApiGetOAuthClientByIdRequest) (*Client, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Client + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OAuth2ClientsApiService.GetOAuthClientById") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/oauth/clients/{clientId}" + localVarPath = strings.Replace(localVarPath, "{"+"clientId"+"}", url.PathEscape(parameterToString(r.clientId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetOAuthClientsRequest struct { + ctx context.Context + ApiService OAuth2ClientsApi +} + +func (r ApiGetOAuthClientsRequest) Execute() (*ClientCollection, *http.Response, error) { + return r.ApiService.GetOAuthClientsExecute(r) +} + +/* +GetOAuthClients Get clients + +Get all OAuth 2.0 clients registered by your account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetOAuthClientsRequest +*/ +func (a *OAuth2ClientsApiService) GetOAuthClients(ctx context.Context) ApiGetOAuthClientsRequest { + return ApiGetOAuthClientsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ClientCollection +func (a *OAuth2ClientsApiService) GetOAuthClientsExecute(r ApiGetOAuthClientsRequest) (*ClientCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ClientCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OAuth2ClientsApiService.GetOAuthClients") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/oauth/clients" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchOAuthClientRequest struct { + ctx context.Context + ApiService OAuth2ClientsApi + clientId string + patchOperation *[]PatchOperation +} + +func (r ApiPatchOAuthClientRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchOAuthClientRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchOAuthClientRequest) Execute() (*Client, *http.Response, error) { + return r.ApiService.PatchOAuthClientExecute(r) +} + +/* +PatchOAuthClient Patch client by ID + +Patch an existing OAuth 2.0 client by client ID. Updating an OAuth2 client uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). Only `name`, `description`, and `redirectUri` may be patched. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param clientId The client ID + @return ApiPatchOAuthClientRequest +*/ +func (a *OAuth2ClientsApiService) PatchOAuthClient(ctx context.Context, clientId string) ApiPatchOAuthClientRequest { + return ApiPatchOAuthClientRequest{ + ApiService: a, + ctx: ctx, + clientId: clientId, + } +} + +// Execute executes the request +// @return Client +func (a *OAuth2ClientsApiService) PatchOAuthClientExecute(r ApiPatchOAuthClientRequest) (*Client, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Client + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OAuth2ClientsApiService.PatchOAuthClient") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/oauth/clients/{clientId}" + localVarPath = strings.Replace(localVarPath, "{"+"clientId"+"}", url.PathEscape(parameterToString(r.clientId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_other.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_other.go new file mode 100644 index 00000000..8db1a10f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_other.go @@ -0,0 +1,725 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" +) + + +type OtherApi interface { + + /* + GetCallerIdentity Identify the caller + + Get basic information about the identity used (session cookie, API token, SDK keys, etc.) to call the API + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetCallerIdentityRequest + */ + GetCallerIdentity(ctx context.Context) ApiGetCallerIdentityRequest + + // GetCallerIdentityExecute executes the request + // @return CallerIdentityRep + GetCallerIdentityExecute(r ApiGetCallerIdentityRequest) (*CallerIdentityRep, *http.Response, error) + + /* + GetIps Gets the public IP list + + Get a list of IP ranges the LaunchDarkly service uses. You can use this list to allow LaunchDarkly through your firewall. We post upcoming changes to this list in advance on our [status page](https://status.launchdarkly.com/).

In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetIpsRequest + */ + GetIps(ctx context.Context) ApiGetIpsRequest + + // GetIpsExecute executes the request + // @return IpList + GetIpsExecute(r ApiGetIpsRequest) (*IpList, *http.Response, error) + + /* + GetOpenapiSpec Gets the OpenAPI spec in json + + Get the latest version of the OpenAPI specification for LaunchDarkly's API in JSON format. In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetOpenapiSpecRequest + */ + GetOpenapiSpec(ctx context.Context) ApiGetOpenapiSpecRequest + + // GetOpenapiSpecExecute executes the request + GetOpenapiSpecExecute(r ApiGetOpenapiSpecRequest) (*http.Response, error) + + /* + GetRoot Root resource + + Get all of the resource categories the API supports. In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRootRequest + */ + GetRoot(ctx context.Context) ApiGetRootRequest + + // GetRootExecute executes the request + // @return RootResponse + GetRootExecute(r ApiGetRootRequest) (*RootResponse, *http.Response, error) + + /* + GetVersions Get version information + + Get the latest API version, the list of valid API versions in ascending order, and the version being used for this request. These are all in the external, date-based format. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetVersionsRequest + */ + GetVersions(ctx context.Context) ApiGetVersionsRequest + + // GetVersionsExecute executes the request + // @return VersionsRep + GetVersionsExecute(r ApiGetVersionsRequest) (*VersionsRep, *http.Response, error) +} + +// OtherApiService OtherApi service +type OtherApiService service + +type ApiGetCallerIdentityRequest struct { + ctx context.Context + ApiService OtherApi +} + +func (r ApiGetCallerIdentityRequest) Execute() (*CallerIdentityRep, *http.Response, error) { + return r.ApiService.GetCallerIdentityExecute(r) +} + +/* +GetCallerIdentity Identify the caller + +Get basic information about the identity used (session cookie, API token, SDK keys, etc.) to call the API + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetCallerIdentityRequest +*/ +func (a *OtherApiService) GetCallerIdentity(ctx context.Context) ApiGetCallerIdentityRequest { + return ApiGetCallerIdentityRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return CallerIdentityRep +func (a *OtherApiService) GetCallerIdentityExecute(r ApiGetCallerIdentityRequest) (*CallerIdentityRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CallerIdentityRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OtherApiService.GetCallerIdentity") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/caller-identity" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetIpsRequest struct { + ctx context.Context + ApiService OtherApi +} + +func (r ApiGetIpsRequest) Execute() (*IpList, *http.Response, error) { + return r.ApiService.GetIpsExecute(r) +} + +/* +GetIps Gets the public IP list + +Get a list of IP ranges the LaunchDarkly service uses. You can use this list to allow LaunchDarkly through your firewall. We post upcoming changes to this list in advance on our [status page](https://status.launchdarkly.com/).

In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetIpsRequest +*/ +func (a *OtherApiService) GetIps(ctx context.Context) ApiGetIpsRequest { + return ApiGetIpsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return IpList +func (a *OtherApiService) GetIpsExecute(r ApiGetIpsRequest) (*IpList, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *IpList + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OtherApiService.GetIps") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/public-ip-list" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetOpenapiSpecRequest struct { + ctx context.Context + ApiService OtherApi +} + +func (r ApiGetOpenapiSpecRequest) Execute() (*http.Response, error) { + return r.ApiService.GetOpenapiSpecExecute(r) +} + +/* +GetOpenapiSpec Gets the OpenAPI spec in json + +Get the latest version of the OpenAPI specification for LaunchDarkly's API in JSON format. In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetOpenapiSpecRequest +*/ +func (a *OtherApiService) GetOpenapiSpec(ctx context.Context) ApiGetOpenapiSpecRequest { + return ApiGetOpenapiSpecRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +func (a *OtherApiService) GetOpenapiSpecExecute(r ApiGetOpenapiSpecRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OtherApiService.GetOpenapiSpec") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/openapi.json" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetRootRequest struct { + ctx context.Context + ApiService OtherApi +} + +func (r ApiGetRootRequest) Execute() (*RootResponse, *http.Response, error) { + return r.ApiService.GetRootExecute(r) +} + +/* +GetRoot Root resource + +Get all of the resource categories the API supports. In the sandbox, click 'Play' and enter any string in the 'Authorization' field to test this endpoint. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRootRequest +*/ +func (a *OtherApiService) GetRoot(ctx context.Context) ApiGetRootRequest { + return ApiGetRootRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return RootResponse +func (a *OtherApiService) GetRootExecute(r ApiGetRootRequest) (*RootResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RootResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OtherApiService.GetRoot") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetVersionsRequest struct { + ctx context.Context + ApiService OtherApi +} + +func (r ApiGetVersionsRequest) Execute() (*VersionsRep, *http.Response, error) { + return r.ApiService.GetVersionsExecute(r) +} + +/* +GetVersions Get version information + +Get the latest API version, the list of valid API versions in ascending order, and the version being used for this request. These are all in the external, date-based format. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetVersionsRequest +*/ +func (a *OtherApiService) GetVersions(ctx context.Context) ApiGetVersionsRequest { + return ApiGetVersionsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return VersionsRep +func (a *OtherApiService) GetVersionsExecute(r ApiGetVersionsRequest) (*VersionsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *VersionsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OtherApiService.GetVersions") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/versions" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_persistent_store_integrations_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_persistent_store_integrations_beta.go new file mode 100644 index 00000000..d5693622 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_persistent_store_integrations_beta.go @@ -0,0 +1,1043 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type PersistentStoreIntegrationsBetaApi interface { + + /* + CreateBigSegmentStoreIntegration Create big segment store integration + + +Create a persistent store integration. + +If you are using server-side SDKs, segments synced from external tools and larger list-based segments require a persistent store within your infrastructure. LaunchDarkly keeps the persistent store up to date and consults it during flag evaluation. + +You can use either Redis or DynamoDB as your persistent store. When you create a persistent store integration, the fields in the `config` object in the request vary depending on which persistent store you use. + +If you are using Redis to create your persistent store integration, you will need to know: + +* Your Redis host +* Your Redis port +* Your Redis username +* Your Redis password +* Whether or not LaunchDarkly should connect using TLS + +If you are using DynamoDB to create your persistent store integration, you will need to know: + +* Your DynamoDB table name. The table must have the following schema: + * Partition key: `namespace` (string) + * Sort key: `key` (string) +* Your DynamoDB Amazon Web Services (AWS) region. +* Your AWS role Amazon Resource Name (ARN). This is the role that LaunchDarkly will assume to manage your DynamoDB table. +* The External ID you specified when creating your Amazon Resource Name (ARN). + +To learn more, read [Segment configuration](https://launchdarkly.com/docs/home/flags/segment-config). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @return ApiCreateBigSegmentStoreIntegrationRequest + */ + CreateBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string) ApiCreateBigSegmentStoreIntegrationRequest + + // CreateBigSegmentStoreIntegrationExecute executes the request + // @return BigSegmentStoreIntegration + CreateBigSegmentStoreIntegrationExecute(r ApiCreateBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) + + /* + DeleteBigSegmentStoreIntegration Delete big segment store integration + + Delete a persistent store integration. Each integration uses either Redis or DynamoDB. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiDeleteBigSegmentStoreIntegrationRequest + */ + DeleteBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiDeleteBigSegmentStoreIntegrationRequest + + // DeleteBigSegmentStoreIntegrationExecute executes the request + DeleteBigSegmentStoreIntegrationExecute(r ApiDeleteBigSegmentStoreIntegrationRequest) (*http.Response, error) + + /* + GetBigSegmentStoreIntegration Get big segment store integration by ID + + Get a big segment store integration by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiGetBigSegmentStoreIntegrationRequest + */ + GetBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiGetBigSegmentStoreIntegrationRequest + + // GetBigSegmentStoreIntegrationExecute executes the request + // @return BigSegmentStoreIntegration + GetBigSegmentStoreIntegrationExecute(r ApiGetBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) + + /* + GetBigSegmentStoreIntegrations List all big segment store integrations + + List all big segment store integrations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetBigSegmentStoreIntegrationsRequest + */ + GetBigSegmentStoreIntegrations(ctx context.Context) ApiGetBigSegmentStoreIntegrationsRequest + + // GetBigSegmentStoreIntegrationsExecute executes the request + // @return BigSegmentStoreIntegrationCollection + GetBigSegmentStoreIntegrationsExecute(r ApiGetBigSegmentStoreIntegrationsRequest) (*BigSegmentStoreIntegrationCollection, *http.Response, error) + + /* + PatchBigSegmentStoreIntegration Update big segment store integration + + Update a big segment store integration. Updating a big segment store requires a [JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiPatchBigSegmentStoreIntegrationRequest + */ + PatchBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiPatchBigSegmentStoreIntegrationRequest + + // PatchBigSegmentStoreIntegrationExecute executes the request + // @return BigSegmentStoreIntegration + PatchBigSegmentStoreIntegrationExecute(r ApiPatchBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) +} + +// PersistentStoreIntegrationsBetaApiService PersistentStoreIntegrationsBetaApi service +type PersistentStoreIntegrationsBetaApiService service + +type ApiCreateBigSegmentStoreIntegrationRequest struct { + ctx context.Context + ApiService PersistentStoreIntegrationsBetaApi + projectKey string + environmentKey string + integrationKey string + integrationDeliveryConfigurationPost *IntegrationDeliveryConfigurationPost +} + +func (r ApiCreateBigSegmentStoreIntegrationRequest) IntegrationDeliveryConfigurationPost(integrationDeliveryConfigurationPost IntegrationDeliveryConfigurationPost) ApiCreateBigSegmentStoreIntegrationRequest { + r.integrationDeliveryConfigurationPost = &integrationDeliveryConfigurationPost + return r +} + +func (r ApiCreateBigSegmentStoreIntegrationRequest) Execute() (*BigSegmentStoreIntegration, *http.Response, error) { + return r.ApiService.CreateBigSegmentStoreIntegrationExecute(r) +} + +/* +CreateBigSegmentStoreIntegration Create big segment store integration + + +Create a persistent store integration. + +If you are using server-side SDKs, segments synced from external tools and larger list-based segments require a persistent store within your infrastructure. LaunchDarkly keeps the persistent store up to date and consults it during flag evaluation. + +You can use either Redis or DynamoDB as your persistent store. When you create a persistent store integration, the fields in the `config` object in the request vary depending on which persistent store you use. + +If you are using Redis to create your persistent store integration, you will need to know: + +* Your Redis host +* Your Redis port +* Your Redis username +* Your Redis password +* Whether or not LaunchDarkly should connect using TLS + +If you are using DynamoDB to create your persistent store integration, you will need to know: + +* Your DynamoDB table name. The table must have the following schema: + * Partition key: `namespace` (string) + * Sort key: `key` (string) +* Your DynamoDB Amazon Web Services (AWS) region. +* Your AWS role Amazon Resource Name (ARN). This is the role that LaunchDarkly will assume to manage your DynamoDB table. +* The External ID you specified when creating your Amazon Resource Name (ARN). + +To learn more, read [Segment configuration](https://launchdarkly.com/docs/home/flags/segment-config). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @return ApiCreateBigSegmentStoreIntegrationRequest +*/ +func (a *PersistentStoreIntegrationsBetaApiService) CreateBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string) ApiCreateBigSegmentStoreIntegrationRequest { + return ApiCreateBigSegmentStoreIntegrationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + } +} + +// Execute executes the request +// @return BigSegmentStoreIntegration +func (a *PersistentStoreIntegrationsBetaApiService) CreateBigSegmentStoreIntegrationExecute(r ApiCreateBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentStoreIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PersistentStoreIntegrationsBetaApiService.CreateBigSegmentStoreIntegration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.integrationDeliveryConfigurationPost == nil { + return localVarReturnValue, nil, reportError("integrationDeliveryConfigurationPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.integrationDeliveryConfigurationPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteBigSegmentStoreIntegrationRequest struct { + ctx context.Context + ApiService PersistentStoreIntegrationsBetaApi + projectKey string + environmentKey string + integrationKey string + integrationId string +} + +func (r ApiDeleteBigSegmentStoreIntegrationRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteBigSegmentStoreIntegrationExecute(r) +} + +/* +DeleteBigSegmentStoreIntegration Delete big segment store integration + +Delete a persistent store integration. Each integration uses either Redis or DynamoDB. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiDeleteBigSegmentStoreIntegrationRequest +*/ +func (a *PersistentStoreIntegrationsBetaApiService) DeleteBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiDeleteBigSegmentStoreIntegrationRequest { + return ApiDeleteBigSegmentStoreIntegrationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +func (a *PersistentStoreIntegrationsBetaApiService) DeleteBigSegmentStoreIntegrationExecute(r ApiDeleteBigSegmentStoreIntegrationRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PersistentStoreIntegrationsBetaApiService.DeleteBigSegmentStoreIntegration") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetBigSegmentStoreIntegrationRequest struct { + ctx context.Context + ApiService PersistentStoreIntegrationsBetaApi + projectKey string + environmentKey string + integrationKey string + integrationId string +} + +func (r ApiGetBigSegmentStoreIntegrationRequest) Execute() (*BigSegmentStoreIntegration, *http.Response, error) { + return r.ApiService.GetBigSegmentStoreIntegrationExecute(r) +} + +/* +GetBigSegmentStoreIntegration Get big segment store integration by ID + +Get a big segment store integration by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiGetBigSegmentStoreIntegrationRequest +*/ +func (a *PersistentStoreIntegrationsBetaApiService) GetBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiGetBigSegmentStoreIntegrationRequest { + return ApiGetBigSegmentStoreIntegrationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +// @return BigSegmentStoreIntegration +func (a *PersistentStoreIntegrationsBetaApiService) GetBigSegmentStoreIntegrationExecute(r ApiGetBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentStoreIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PersistentStoreIntegrationsBetaApiService.GetBigSegmentStoreIntegration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetBigSegmentStoreIntegrationsRequest struct { + ctx context.Context + ApiService PersistentStoreIntegrationsBetaApi +} + +func (r ApiGetBigSegmentStoreIntegrationsRequest) Execute() (*BigSegmentStoreIntegrationCollection, *http.Response, error) { + return r.ApiService.GetBigSegmentStoreIntegrationsExecute(r) +} + +/* +GetBigSegmentStoreIntegrations List all big segment store integrations + +List all big segment store integrations. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetBigSegmentStoreIntegrationsRequest +*/ +func (a *PersistentStoreIntegrationsBetaApiService) GetBigSegmentStoreIntegrations(ctx context.Context) ApiGetBigSegmentStoreIntegrationsRequest { + return ApiGetBigSegmentStoreIntegrationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return BigSegmentStoreIntegrationCollection +func (a *PersistentStoreIntegrationsBetaApiService) GetBigSegmentStoreIntegrationsExecute(r ApiGetBigSegmentStoreIntegrationsRequest) (*BigSegmentStoreIntegrationCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentStoreIntegrationCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PersistentStoreIntegrationsBetaApiService.GetBigSegmentStoreIntegrations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/big-segment-store" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchBigSegmentStoreIntegrationRequest struct { + ctx context.Context + ApiService PersistentStoreIntegrationsBetaApi + projectKey string + environmentKey string + integrationKey string + integrationId string + patchOperation *[]PatchOperation +} + +func (r ApiPatchBigSegmentStoreIntegrationRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchBigSegmentStoreIntegrationRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchBigSegmentStoreIntegrationRequest) Execute() (*BigSegmentStoreIntegration, *http.Response, error) { + return r.ApiService.PatchBigSegmentStoreIntegrationExecute(r) +} + +/* +PatchBigSegmentStoreIntegration Update big segment store integration + +Update a big segment store integration. Updating a big segment store requires a [JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param integrationKey The integration key, either `redis` or `dynamodb` + @param integrationId The integration ID + @return ApiPatchBigSegmentStoreIntegrationRequest +*/ +func (a *PersistentStoreIntegrationsBetaApiService) PatchBigSegmentStoreIntegration(ctx context.Context, projectKey string, environmentKey string, integrationKey string, integrationId string) ApiPatchBigSegmentStoreIntegrationRequest { + return ApiPatchBigSegmentStoreIntegrationRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + integrationKey: integrationKey, + integrationId: integrationId, + } +} + +// Execute executes the request +// @return BigSegmentStoreIntegration +func (a *PersistentStoreIntegrationsBetaApiService) PatchBigSegmentStoreIntegrationExecute(r ApiPatchBigSegmentStoreIntegrationRequest) (*BigSegmentStoreIntegration, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentStoreIntegration + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "PersistentStoreIntegrationsBetaApiService.PatchBigSegmentStoreIntegration") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/integration-capabilities/big-segment-store/{projectKey}/{environmentKey}/{integrationKey}/{integrationId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationKey"+"}", url.PathEscape(parameterToString(r.integrationKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"integrationId"+"}", url.PathEscape(parameterToString(r.integrationId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_projects.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_projects.go new file mode 100644 index 00000000..44c9ec26 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_projects.go @@ -0,0 +1,1642 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ProjectsApi interface { + + /* + DeleteProject Delete project + + Delete a project by key. Use this endpoint with caution. Deleting a project will delete all associated environments and feature flags. You cannot delete the last project in an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiDeleteProjectRequest + */ + DeleteProject(ctx context.Context, projectKey string) ApiDeleteProjectRequest + + // DeleteProjectExecute executes the request + DeleteProjectExecute(r ApiDeleteProjectRequest) (*http.Response, error) + + /* + GetFlagDefaultsByProject Get flag defaults for project + + Get the flag defaults for a specific project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetFlagDefaultsByProjectRequest + */ + GetFlagDefaultsByProject(ctx context.Context, projectKey string) ApiGetFlagDefaultsByProjectRequest + + // GetFlagDefaultsByProjectExecute executes the request + // @return FlagDefaultsRep + GetFlagDefaultsByProjectExecute(r ApiGetFlagDefaultsByProjectRequest) (*FlagDefaultsRep, *http.Response, error) + + /* + GetProject Get project + + Get a single project by key. + +### Expanding the project response + +LaunchDarkly supports one field for expanding the "Get project" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: +* `environments` includes a paginated list of the project environments. + +For example, `expand=environments` includes the `environments` field for the project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key. + @return ApiGetProjectRequest + */ + GetProject(ctx context.Context, projectKey string) ApiGetProjectRequest + + // GetProjectExecute executes the request + // @return Project + GetProjectExecute(r ApiGetProjectRequest) (*Project, *http.Response, error) + + /* + GetProjects List projects + + Return a list of projects. + +By default, this returns the first 20 projects. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering projects + +LaunchDarkly supports three fields for filters: +- `query` is a string that matches against the projects' names and keys. It is not case sensitive. +- `tags` is a `+`-separated list of project tags. It filters the list of projects that have all of the tags in the list. +- `keys` is a `|` separated list of project keys. It filters the list to projects that have any of the keys in the list. + +For example, the filter `filter=query:abc,tags:tag-1+tag-2` matches projects with the string `abc` in their name or key and also are tagged with `tag-1` and `tag-2`. The filter is not case-sensitive. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `+` in `filter=tags:tag-1+tag-2` must be encoded to `%2B`. + +### Sorting projects + +LaunchDarkly supports two fields for sorting: +- `name` sorts by project name. +- `createdOn` sorts by the creation date of the project. + +For example, `sort=name` sorts the response by project name in ascending order. + +### Expanding the projects response + +LaunchDarkly supports one field for expanding the "List projects" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with the `environments` field. + +* `environments` includes a paginated list of the project environments. + +For example, `expand=environments` includes the `environments` field for each project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetProjectsRequest + */ + GetProjects(ctx context.Context) ApiGetProjectsRequest + + // GetProjectsExecute executes the request + // @return Projects + GetProjectsExecute(r ApiGetProjectsRequest) (*Projects, *http.Response, error) + + /* + PatchFlagDefaultsByProject Update flag default for project + + Update a flag default. Updating a flag default uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPatchFlagDefaultsByProjectRequest + */ + PatchFlagDefaultsByProject(ctx context.Context, projectKey string) ApiPatchFlagDefaultsByProjectRequest + + // PatchFlagDefaultsByProjectExecute executes the request + // @return UpsertPayloadRep + PatchFlagDefaultsByProjectExecute(r ApiPatchFlagDefaultsByProjectRequest) (*UpsertPayloadRep, *http.Response, error) + + /* + PatchProject Update project + + Update a project. Updating a project uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the project fields that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPatchProjectRequest + */ + PatchProject(ctx context.Context, projectKey string) ApiPatchProjectRequest + + // PatchProjectExecute executes the request + // @return ProjectRep + PatchProjectExecute(r ApiPatchProjectRequest) (*ProjectRep, *http.Response, error) + + /* + PostProject Create project + + Create a new project with the given key and name. Project keys must be unique within an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostProjectRequest + */ + PostProject(ctx context.Context) ApiPostProjectRequest + + // PostProjectExecute executes the request + // @return ProjectRep + PostProjectExecute(r ApiPostProjectRequest) (*ProjectRep, *http.Response, error) + + /* + PutFlagDefaultsByProject Create or update flag defaults for project + + Create or update flag defaults for a project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPutFlagDefaultsByProjectRequest + */ + PutFlagDefaultsByProject(ctx context.Context, projectKey string) ApiPutFlagDefaultsByProjectRequest + + // PutFlagDefaultsByProjectExecute executes the request + // @return UpsertPayloadRep + PutFlagDefaultsByProjectExecute(r ApiPutFlagDefaultsByProjectRequest) (*UpsertPayloadRep, *http.Response, error) +} + +// ProjectsApiService ProjectsApi service +type ProjectsApiService service + +type ApiDeleteProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string +} + +func (r ApiDeleteProjectRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteProjectExecute(r) +} + +/* +DeleteProject Delete project + +Delete a project by key. Use this endpoint with caution. Deleting a project will delete all associated environments and feature flags. You cannot delete the last project in an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiDeleteProjectRequest +*/ +func (a *ProjectsApiService) DeleteProject(ctx context.Context, projectKey string) ApiDeleteProjectRequest { + return ApiDeleteProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +func (a *ProjectsApiService) DeleteProjectExecute(r ApiDeleteProjectRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.DeleteProject") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetFlagDefaultsByProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string +} + +func (r ApiGetFlagDefaultsByProjectRequest) Execute() (*FlagDefaultsRep, *http.Response, error) { + return r.ApiService.GetFlagDefaultsByProjectExecute(r) +} + +/* +GetFlagDefaultsByProject Get flag defaults for project + +Get the flag defaults for a specific project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetFlagDefaultsByProjectRequest +*/ +func (a *ProjectsApiService) GetFlagDefaultsByProject(ctx context.Context, projectKey string) ApiGetFlagDefaultsByProjectRequest { + return ApiGetFlagDefaultsByProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return FlagDefaultsRep +func (a *ProjectsApiService) GetFlagDefaultsByProjectExecute(r ApiGetFlagDefaultsByProjectRequest) (*FlagDefaultsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FlagDefaultsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.GetFlagDefaultsByProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flag-defaults" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetProjectRequest) Expand(expand string) ApiGetProjectRequest { + r.expand = &expand + return r +} + +func (r ApiGetProjectRequest) Execute() (*Project, *http.Response, error) { + return r.ApiService.GetProjectExecute(r) +} + +/* +GetProject Get project + +Get a single project by key. + +### Expanding the project response + +LaunchDarkly supports one field for expanding the "Get project" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: +* `environments` includes a paginated list of the project environments. + +For example, `expand=environments` includes the `environments` field for the project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key. + @return ApiGetProjectRequest +*/ +func (a *ProjectsApiService) GetProject(ctx context.Context, projectKey string) ApiGetProjectRequest { + return ApiGetProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return Project +func (a *ProjectsApiService) GetProjectExecute(r ApiGetProjectRequest) (*Project, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Project + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.GetProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetProjectsRequest struct { + ctx context.Context + ApiService ProjectsApi + limit *int64 + offset *int64 + filter *string + sort *string + expand *string +} + +// The number of projects to return in the response. Defaults to 20. +func (r ApiGetProjectsRequest) Limit(limit int64) ApiGetProjectsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and returns the next `limit` items. +func (r ApiGetProjectsRequest) Offset(offset int64) ApiGetProjectsRequest { + r.offset = &offset + return r +} + +// A comma-separated list of filters. Each filter is constructed as `field:value`. +func (r ApiGetProjectsRequest) Filter(filter string) ApiGetProjectsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of fields to sort by. Fields prefixed by a dash ( - ) sort in descending order. +func (r ApiGetProjectsRequest) Sort(sort string) ApiGetProjectsRequest { + r.sort = &sort + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetProjectsRequest) Expand(expand string) ApiGetProjectsRequest { + r.expand = &expand + return r +} + +func (r ApiGetProjectsRequest) Execute() (*Projects, *http.Response, error) { + return r.ApiService.GetProjectsExecute(r) +} + +/* +GetProjects List projects + +Return a list of projects. + +By default, this returns the first 20 projects. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering projects + +LaunchDarkly supports three fields for filters: +- `query` is a string that matches against the projects' names and keys. It is not case sensitive. +- `tags` is a `+`-separated list of project tags. It filters the list of projects that have all of the tags in the list. +- `keys` is a `|` separated list of project keys. It filters the list to projects that have any of the keys in the list. + +For example, the filter `filter=query:abc,tags:tag-1+tag-2` matches projects with the string `abc` in their name or key and also are tagged with `tag-1` and `tag-2`. The filter is not case-sensitive. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `+` in `filter=tags:tag-1+tag-2` must be encoded to `%2B`. + +### Sorting projects + +LaunchDarkly supports two fields for sorting: +- `name` sorts by project name. +- `createdOn` sorts by the creation date of the project. + +For example, `sort=name` sorts the response by project name in ascending order. + +### Expanding the projects response + +LaunchDarkly supports one field for expanding the "List projects" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with the `environments` field. + +* `environments` includes a paginated list of the project environments. + +For example, `expand=environments` includes the `environments` field for each project in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetProjectsRequest +*/ +func (a *ProjectsApiService) GetProjects(ctx context.Context) ApiGetProjectsRequest { + return ApiGetProjectsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Projects +func (a *ProjectsApiService) GetProjectsExecute(r ApiGetProjectsRequest) (*Projects, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Projects + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.GetProjects") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchFlagDefaultsByProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchFlagDefaultsByProjectRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchFlagDefaultsByProjectRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchFlagDefaultsByProjectRequest) Execute() (*UpsertPayloadRep, *http.Response, error) { + return r.ApiService.PatchFlagDefaultsByProjectExecute(r) +} + +/* +PatchFlagDefaultsByProject Update flag default for project + +Update a flag default. Updating a flag default uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPatchFlagDefaultsByProjectRequest +*/ +func (a *ProjectsApiService) PatchFlagDefaultsByProject(ctx context.Context, projectKey string) ApiPatchFlagDefaultsByProjectRequest { + return ApiPatchFlagDefaultsByProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return UpsertPayloadRep +func (a *ProjectsApiService) PatchFlagDefaultsByProjectExecute(r ApiPatchFlagDefaultsByProjectRequest) (*UpsertPayloadRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UpsertPayloadRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.PatchFlagDefaultsByProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flag-defaults" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchProjectRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchProjectRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchProjectRequest) Execute() (*ProjectRep, *http.Response, error) { + return r.ApiService.PatchProjectExecute(r) +} + +/* +PatchProject Update project + +Update a project. Updating a project uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates).

To add an element to the project fields that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add to the beginning of the array. Use `/-` to add to the end of the array. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPatchProjectRequest +*/ +func (a *ProjectsApiService) PatchProject(ctx context.Context, projectKey string) ApiPatchProjectRequest { + return ApiPatchProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return ProjectRep +func (a *ProjectsApiService) PatchProjectExecute(r ApiPatchProjectRequest) (*ProjectRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ProjectRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.PatchProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectPost *ProjectPost +} + +func (r ApiPostProjectRequest) ProjectPost(projectPost ProjectPost) ApiPostProjectRequest { + r.projectPost = &projectPost + return r +} + +func (r ApiPostProjectRequest) Execute() (*ProjectRep, *http.Response, error) { + return r.ApiService.PostProjectExecute(r) +} + +/* +PostProject Create project + +Create a new project with the given key and name. Project keys must be unique within an account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostProjectRequest +*/ +func (a *ProjectsApiService) PostProject(ctx context.Context) ApiPostProjectRequest { + return ApiPostProjectRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return ProjectRep +func (a *ProjectsApiService) PostProjectExecute(r ApiPostProjectRequest) (*ProjectRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ProjectRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.PostProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.projectPost == nil { + return localVarReturnValue, nil, reportError("projectPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.projectPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutFlagDefaultsByProjectRequest struct { + ctx context.Context + ApiService ProjectsApi + projectKey string + upsertFlagDefaultsPayload *UpsertFlagDefaultsPayload +} + +func (r ApiPutFlagDefaultsByProjectRequest) UpsertFlagDefaultsPayload(upsertFlagDefaultsPayload UpsertFlagDefaultsPayload) ApiPutFlagDefaultsByProjectRequest { + r.upsertFlagDefaultsPayload = &upsertFlagDefaultsPayload + return r +} + +func (r ApiPutFlagDefaultsByProjectRequest) Execute() (*UpsertPayloadRep, *http.Response, error) { + return r.ApiService.PutFlagDefaultsByProjectExecute(r) +} + +/* +PutFlagDefaultsByProject Create or update flag defaults for project + +Create or update flag defaults for a project. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPutFlagDefaultsByProjectRequest +*/ +func (a *ProjectsApiService) PutFlagDefaultsByProject(ctx context.Context, projectKey string) ApiPutFlagDefaultsByProjectRequest { + return ApiPutFlagDefaultsByProjectRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return UpsertPayloadRep +func (a *ProjectsApiService) PutFlagDefaultsByProjectExecute(r ApiPutFlagDefaultsByProjectRequest) (*UpsertPayloadRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UpsertPayloadRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ProjectsApiService.PutFlagDefaultsByProject") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flag-defaults" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.upsertFlagDefaultsPayload == nil { + return localVarReturnValue, nil, reportError("upsertFlagDefaultsPayload is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.upsertFlagDefaultsPayload + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_relay_proxy_configurations.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_relay_proxy_configurations.go new file mode 100644 index 00000000..0bc2f4c0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_relay_proxy_configurations.go @@ -0,0 +1,1064 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type RelayProxyConfigurationsApi interface { + + /* + DeleteRelayAutoConfig Delete Relay Proxy config by ID + + Delete a Relay Proxy config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiDeleteRelayAutoConfigRequest + */ + DeleteRelayAutoConfig(ctx context.Context, id string) ApiDeleteRelayAutoConfigRequest + + // DeleteRelayAutoConfigExecute executes the request + DeleteRelayAutoConfigExecute(r ApiDeleteRelayAutoConfigRequest) (*http.Response, error) + + /* + GetRelayProxyConfig Get Relay Proxy config + + Get a single Relay Proxy auto config by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiGetRelayProxyConfigRequest + */ + GetRelayProxyConfig(ctx context.Context, id string) ApiGetRelayProxyConfigRequest + + // GetRelayProxyConfigExecute executes the request + // @return RelayAutoConfigRep + GetRelayProxyConfigExecute(r ApiGetRelayProxyConfigRequest) (*RelayAutoConfigRep, *http.Response, error) + + /* + GetRelayProxyConfigs List Relay Proxy configs + + Get a list of Relay Proxy configurations in the account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRelayProxyConfigsRequest + */ + GetRelayProxyConfigs(ctx context.Context) ApiGetRelayProxyConfigsRequest + + // GetRelayProxyConfigsExecute executes the request + // @return RelayAutoConfigCollectionRep + GetRelayProxyConfigsExecute(r ApiGetRelayProxyConfigsRequest) (*RelayAutoConfigCollectionRep, *http.Response, error) + + /* + PatchRelayAutoConfig Update a Relay Proxy config + + Update a Relay Proxy configuration. Updating a configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiPatchRelayAutoConfigRequest + */ + PatchRelayAutoConfig(ctx context.Context, id string) ApiPatchRelayAutoConfigRequest + + // PatchRelayAutoConfigExecute executes the request + // @return RelayAutoConfigRep + PatchRelayAutoConfigExecute(r ApiPatchRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) + + /* + PostRelayAutoConfig Create a new Relay Proxy config + + Create a Relay Proxy config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostRelayAutoConfigRequest + */ + PostRelayAutoConfig(ctx context.Context) ApiPostRelayAutoConfigRequest + + // PostRelayAutoConfigExecute executes the request + // @return RelayAutoConfigRep + PostRelayAutoConfigExecute(r ApiPostRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) + + /* + ResetRelayAutoConfig Reset Relay Proxy configuration key + + Reset a Relay Proxy configuration's secret key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The Relay Proxy configuration ID + @return ApiResetRelayAutoConfigRequest + */ + ResetRelayAutoConfig(ctx context.Context, id string) ApiResetRelayAutoConfigRequest + + // ResetRelayAutoConfigExecute executes the request + // @return RelayAutoConfigRep + ResetRelayAutoConfigExecute(r ApiResetRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) +} + +// RelayProxyConfigurationsApiService RelayProxyConfigurationsApi service +type RelayProxyConfigurationsApiService service + +type ApiDeleteRelayAutoConfigRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi + id string +} + +func (r ApiDeleteRelayAutoConfigRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteRelayAutoConfigExecute(r) +} + +/* +DeleteRelayAutoConfig Delete Relay Proxy config by ID + +Delete a Relay Proxy config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiDeleteRelayAutoConfigRequest +*/ +func (a *RelayProxyConfigurationsApiService) DeleteRelayAutoConfig(ctx context.Context, id string) ApiDeleteRelayAutoConfigRequest { + return ApiDeleteRelayAutoConfigRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +func (a *RelayProxyConfigurationsApiService) DeleteRelayAutoConfigExecute(r ApiDeleteRelayAutoConfigRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.DeleteRelayAutoConfig") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetRelayProxyConfigRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi + id string +} + +func (r ApiGetRelayProxyConfigRequest) Execute() (*RelayAutoConfigRep, *http.Response, error) { + return r.ApiService.GetRelayProxyConfigExecute(r) +} + +/* +GetRelayProxyConfig Get Relay Proxy config + +Get a single Relay Proxy auto config by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiGetRelayProxyConfigRequest +*/ +func (a *RelayProxyConfigurationsApiService) GetRelayProxyConfig(ctx context.Context, id string) ApiGetRelayProxyConfigRequest { + return ApiGetRelayProxyConfigRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return RelayAutoConfigRep +func (a *RelayProxyConfigurationsApiService) GetRelayProxyConfigExecute(r ApiGetRelayProxyConfigRequest) (*RelayAutoConfigRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RelayAutoConfigRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.GetRelayProxyConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetRelayProxyConfigsRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi +} + +func (r ApiGetRelayProxyConfigsRequest) Execute() (*RelayAutoConfigCollectionRep, *http.Response, error) { + return r.ApiService.GetRelayProxyConfigsExecute(r) +} + +/* +GetRelayProxyConfigs List Relay Proxy configs + +Get a list of Relay Proxy configurations in the account. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetRelayProxyConfigsRequest +*/ +func (a *RelayProxyConfigurationsApiService) GetRelayProxyConfigs(ctx context.Context) ApiGetRelayProxyConfigsRequest { + return ApiGetRelayProxyConfigsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return RelayAutoConfigCollectionRep +func (a *RelayProxyConfigurationsApiService) GetRelayProxyConfigsExecute(r ApiGetRelayProxyConfigsRequest) (*RelayAutoConfigCollectionRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RelayAutoConfigCollectionRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.GetRelayProxyConfigs") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchRelayAutoConfigRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi + id string + patchWithComment *PatchWithComment +} + +func (r ApiPatchRelayAutoConfigRequest) PatchWithComment(patchWithComment PatchWithComment) ApiPatchRelayAutoConfigRequest { + r.patchWithComment = &patchWithComment + return r +} + +func (r ApiPatchRelayAutoConfigRequest) Execute() (*RelayAutoConfigRep, *http.Response, error) { + return r.ApiService.PatchRelayAutoConfigExecute(r) +} + +/* +PatchRelayAutoConfig Update a Relay Proxy config + +Update a Relay Proxy configuration. Updating a configuration uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The relay auto config id + @return ApiPatchRelayAutoConfigRequest +*/ +func (a *RelayProxyConfigurationsApiService) PatchRelayAutoConfig(ctx context.Context, id string) ApiPatchRelayAutoConfigRequest { + return ApiPatchRelayAutoConfigRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return RelayAutoConfigRep +func (a *RelayProxyConfigurationsApiService) PatchRelayAutoConfigExecute(r ApiPatchRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RelayAutoConfigRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.PatchRelayAutoConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchWithComment == nil { + return localVarReturnValue, nil, reportError("patchWithComment is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchWithComment + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 422 { + var v PatchFailedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostRelayAutoConfigRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi + relayAutoConfigPost *RelayAutoConfigPost +} + +func (r ApiPostRelayAutoConfigRequest) RelayAutoConfigPost(relayAutoConfigPost RelayAutoConfigPost) ApiPostRelayAutoConfigRequest { + r.relayAutoConfigPost = &relayAutoConfigPost + return r +} + +func (r ApiPostRelayAutoConfigRequest) Execute() (*RelayAutoConfigRep, *http.Response, error) { + return r.ApiService.PostRelayAutoConfigExecute(r) +} + +/* +PostRelayAutoConfig Create a new Relay Proxy config + +Create a Relay Proxy config. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostRelayAutoConfigRequest +*/ +func (a *RelayProxyConfigurationsApiService) PostRelayAutoConfig(ctx context.Context) ApiPostRelayAutoConfigRequest { + return ApiPostRelayAutoConfigRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return RelayAutoConfigRep +func (a *RelayProxyConfigurationsApiService) PostRelayAutoConfigExecute(r ApiPostRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RelayAutoConfigRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.PostRelayAutoConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.relayAutoConfigPost == nil { + return localVarReturnValue, nil, reportError("relayAutoConfigPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.relayAutoConfigPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiResetRelayAutoConfigRequest struct { + ctx context.Context + ApiService RelayProxyConfigurationsApi + id string + expiry *int64 +} + +// An expiration time for the old Relay Proxy configuration key, expressed as a Unix epoch time in milliseconds. By default, the Relay Proxy configuration will expire immediately. +func (r ApiResetRelayAutoConfigRequest) Expiry(expiry int64) ApiResetRelayAutoConfigRequest { + r.expiry = &expiry + return r +} + +func (r ApiResetRelayAutoConfigRequest) Execute() (*RelayAutoConfigRep, *http.Response, error) { + return r.ApiService.ResetRelayAutoConfigExecute(r) +} + +/* +ResetRelayAutoConfig Reset Relay Proxy configuration key + +Reset a Relay Proxy configuration's secret key with an optional expiry time for the old key. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The Relay Proxy configuration ID + @return ApiResetRelayAutoConfigRequest +*/ +func (a *RelayProxyConfigurationsApiService) ResetRelayAutoConfig(ctx context.Context, id string) ApiResetRelayAutoConfigRequest { + return ApiResetRelayAutoConfigRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return RelayAutoConfigRep +func (a *RelayProxyConfigurationsApiService) ResetRelayAutoConfigExecute(r ApiResetRelayAutoConfigRequest) (*RelayAutoConfigRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *RelayAutoConfigRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "RelayProxyConfigurationsApiService.ResetRelayAutoConfig") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/account/relay-auto-configs/{id}/reset" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expiry != nil { + localVarQueryParams.Add("expiry", parameterToString(*r.expiry, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_release_pipelines_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_release_pipelines_beta.go new file mode 100644 index 00000000..3238e1ca --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_release_pipelines_beta.go @@ -0,0 +1,1062 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ReleasePipelinesBetaApi interface { + + /* + DeleteReleasePipeline Delete release pipeline + + Deletes a release pipeline. + +You cannot delete the default release pipeline. + +If you want to delete a release pipeline that is currently the default, create a second release pipeline and set it as the default. Then delete the first release pipeline. To change the default release pipeline, use the [Update project](https://launchdarkly.com/docs/ld-docs/api/projects/patch-project) API to set the `defaultReleasePipelineKey`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiDeleteReleasePipelineRequest + */ + DeleteReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiDeleteReleasePipelineRequest + + // DeleteReleasePipelineExecute executes the request + DeleteReleasePipelineExecute(r ApiDeleteReleasePipelineRequest) (*http.Response, error) + + /* + GetAllReleasePipelines Get all release pipelines + + Get all release pipelines for a project. + +### Filtering release pipelines + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the release pipeline `key`, `name`, and `description`. It is not case sensitive. For example: `?filter=query:examplePipeline`. + +- `env` is a string that matches an environment key. For example: `?filter=env:production`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetAllReleasePipelinesRequest + */ + GetAllReleasePipelines(ctx context.Context, projectKey string) ApiGetAllReleasePipelinesRequest + + // GetAllReleasePipelinesExecute executes the request + // @return ReleasePipelineCollection + GetAllReleasePipelinesExecute(r ApiGetAllReleasePipelinesRequest) (*ReleasePipelineCollection, *http.Response, error) + + /* + GetAllReleaseProgressionsForReleasePipeline Get release progressions for release pipeline + + Get details on the progression of all releases, across all flags, for a release pipeline + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The pipeline key + @return ApiGetAllReleaseProgressionsForReleasePipelineRequest + */ + GetAllReleaseProgressionsForReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiGetAllReleaseProgressionsForReleasePipelineRequest + + // GetAllReleaseProgressionsForReleasePipelineExecute executes the request + // @return ReleaseProgressionCollection + GetAllReleaseProgressionsForReleasePipelineExecute(r ApiGetAllReleaseProgressionsForReleasePipelineRequest) (*ReleaseProgressionCollection, *http.Response, error) + + /* + GetReleasePipelineByKey Get release pipeline by key + + Get a release pipeline by key + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiGetReleasePipelineByKeyRequest + */ + GetReleasePipelineByKey(ctx context.Context, projectKey string, pipelineKey string) ApiGetReleasePipelineByKeyRequest + + // GetReleasePipelineByKeyExecute executes the request + // @return ReleasePipeline + GetReleasePipelineByKeyExecute(r ApiGetReleasePipelineByKeyRequest) (*ReleasePipeline, *http.Response, error) + + /* + PostReleasePipeline Create a release pipeline + + Creates a new release pipeline. + +The first release pipeline you create is automatically set as the default release pipeline for your project. To change the default release pipeline, use the [Update project](https://launchdarkly.com/docs/ld-docs/api/projects/patch-project) API to set the `defaultReleasePipelineKey`. + +You can create up to 20 release pipelines per project. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostReleasePipelineRequest + */ + PostReleasePipeline(ctx context.Context, projectKey string) ApiPostReleasePipelineRequest + + // PostReleasePipelineExecute executes the request + // @return ReleasePipeline + PostReleasePipelineExecute(r ApiPostReleasePipelineRequest) (*ReleasePipeline, *http.Response, error) + + /* + PutReleasePipeline Update a release pipeline + + Updates a release pipeline. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiPutReleasePipelineRequest + */ + PutReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiPutReleasePipelineRequest + + // PutReleasePipelineExecute executes the request + // @return ReleasePipeline + PutReleasePipelineExecute(r ApiPutReleasePipelineRequest) (*ReleasePipeline, *http.Response, error) +} + +// ReleasePipelinesBetaApiService ReleasePipelinesBetaApi service +type ReleasePipelinesBetaApiService service + +type ApiDeleteReleasePipelineRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + pipelineKey string +} + +func (r ApiDeleteReleasePipelineRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteReleasePipelineExecute(r) +} + +/* +DeleteReleasePipeline Delete release pipeline + +Deletes a release pipeline. + +You cannot delete the default release pipeline. + +If you want to delete a release pipeline that is currently the default, create a second release pipeline and set it as the default. Then delete the first release pipeline. To change the default release pipeline, use the [Update project](https://launchdarkly.com/docs/ld-docs/api/projects/patch-project) API to set the `defaultReleasePipelineKey`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiDeleteReleasePipelineRequest +*/ +func (a *ReleasePipelinesBetaApiService) DeleteReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiDeleteReleasePipelineRequest { + return ApiDeleteReleasePipelineRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + pipelineKey: pipelineKey, + } +} + +// Execute executes the request +func (a *ReleasePipelinesBetaApiService) DeleteReleasePipelineExecute(r ApiDeleteReleasePipelineRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.DeleteReleasePipeline") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines/{pipelineKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"pipelineKey"+"}", url.PathEscape(parameterToString(r.pipelineKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetAllReleasePipelinesRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + filter *string + limit *int64 + offset *int64 +} + +// A comma-separated list of filters. Each filter is of the form field:value. Read the endpoint description for a full list of available filter fields. +func (r ApiGetAllReleasePipelinesRequest) Filter(filter string) ApiGetAllReleasePipelinesRequest { + r.filter = &filter + return r +} + +// The maximum number of items to return. Defaults to 20. +func (r ApiGetAllReleasePipelinesRequest) Limit(limit int64) ApiGetAllReleasePipelinesRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Defaults to 0. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetAllReleasePipelinesRequest) Offset(offset int64) ApiGetAllReleasePipelinesRequest { + r.offset = &offset + return r +} + +func (r ApiGetAllReleasePipelinesRequest) Execute() (*ReleasePipelineCollection, *http.Response, error) { + return r.ApiService.GetAllReleasePipelinesExecute(r) +} + +/* +GetAllReleasePipelines Get all release pipelines + +Get all release pipelines for a project. + +### Filtering release pipelines + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the release pipeline `key`, `name`, and `description`. It is not case sensitive. For example: `?filter=query:examplePipeline`. + +- `env` is a string that matches an environment key. For example: `?filter=env:production`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiGetAllReleasePipelinesRequest +*/ +func (a *ReleasePipelinesBetaApiService) GetAllReleasePipelines(ctx context.Context, projectKey string) ApiGetAllReleasePipelinesRequest { + return ApiGetAllReleasePipelinesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return ReleasePipelineCollection +func (a *ReleasePipelinesBetaApiService) GetAllReleasePipelinesExecute(r ApiGetAllReleasePipelinesRequest) (*ReleasePipelineCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ReleasePipelineCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.GetAllReleasePipelines") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetAllReleaseProgressionsForReleasePipelineRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + pipelineKey string + filter *string + limit *int64 + offset *int64 +} + +// Accepts filter by `status` and `activePhaseId`. `status` can take a value of `completed` or `active`. `activePhaseId` takes a UUID and will filter results down to releases active on the specified phase. Providing `status equals completed` along with an `activePhaseId` filter will return an error as they are disjoint sets of data. The combination of `status equals active` and `activePhaseId` will return the same results as `activePhaseId` alone. +func (r ApiGetAllReleaseProgressionsForReleasePipelineRequest) Filter(filter string) ApiGetAllReleaseProgressionsForReleasePipelineRequest { + r.filter = &filter + return r +} + +// The maximum number of items to return. Defaults to 20. +func (r ApiGetAllReleaseProgressionsForReleasePipelineRequest) Limit(limit int64) ApiGetAllReleaseProgressionsForReleasePipelineRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Defaults to 0. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetAllReleaseProgressionsForReleasePipelineRequest) Offset(offset int64) ApiGetAllReleaseProgressionsForReleasePipelineRequest { + r.offset = &offset + return r +} + +func (r ApiGetAllReleaseProgressionsForReleasePipelineRequest) Execute() (*ReleaseProgressionCollection, *http.Response, error) { + return r.ApiService.GetAllReleaseProgressionsForReleasePipelineExecute(r) +} + +/* +GetAllReleaseProgressionsForReleasePipeline Get release progressions for release pipeline + +Get details on the progression of all releases, across all flags, for a release pipeline + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The pipeline key + @return ApiGetAllReleaseProgressionsForReleasePipelineRequest +*/ +func (a *ReleasePipelinesBetaApiService) GetAllReleaseProgressionsForReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiGetAllReleaseProgressionsForReleasePipelineRequest { + return ApiGetAllReleaseProgressionsForReleasePipelineRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + pipelineKey: pipelineKey, + } +} + +// Execute executes the request +// @return ReleaseProgressionCollection +func (a *ReleasePipelinesBetaApiService) GetAllReleaseProgressionsForReleasePipelineExecute(r ApiGetAllReleaseProgressionsForReleasePipelineRequest) (*ReleaseProgressionCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ReleaseProgressionCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.GetAllReleaseProgressionsForReleasePipeline") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines/{pipelineKey}/releases" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"pipelineKey"+"}", url.PathEscape(parameterToString(r.pipelineKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetReleasePipelineByKeyRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + pipelineKey string +} + +func (r ApiGetReleasePipelineByKeyRequest) Execute() (*ReleasePipeline, *http.Response, error) { + return r.ApiService.GetReleasePipelineByKeyExecute(r) +} + +/* +GetReleasePipelineByKey Get release pipeline by key + +Get a release pipeline by key + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiGetReleasePipelineByKeyRequest +*/ +func (a *ReleasePipelinesBetaApiService) GetReleasePipelineByKey(ctx context.Context, projectKey string, pipelineKey string) ApiGetReleasePipelineByKeyRequest { + return ApiGetReleasePipelineByKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + pipelineKey: pipelineKey, + } +} + +// Execute executes the request +// @return ReleasePipeline +func (a *ReleasePipelinesBetaApiService) GetReleasePipelineByKeyExecute(r ApiGetReleasePipelineByKeyRequest) (*ReleasePipeline, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ReleasePipeline + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.GetReleasePipelineByKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines/{pipelineKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"pipelineKey"+"}", url.PathEscape(parameterToString(r.pipelineKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostReleasePipelineRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + createReleasePipelineInput *CreateReleasePipelineInput +} + +func (r ApiPostReleasePipelineRequest) CreateReleasePipelineInput(createReleasePipelineInput CreateReleasePipelineInput) ApiPostReleasePipelineRequest { + r.createReleasePipelineInput = &createReleasePipelineInput + return r +} + +func (r ApiPostReleasePipelineRequest) Execute() (*ReleasePipeline, *http.Response, error) { + return r.ApiService.PostReleasePipelineExecute(r) +} + +/* +PostReleasePipeline Create a release pipeline + +Creates a new release pipeline. + +The first release pipeline you create is automatically set as the default release pipeline for your project. To change the default release pipeline, use the [Update project](https://launchdarkly.com/docs/ld-docs/api/projects/patch-project) API to set the `defaultReleasePipelineKey`. + +You can create up to 20 release pipelines per project. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @return ApiPostReleasePipelineRequest +*/ +func (a *ReleasePipelinesBetaApiService) PostReleasePipeline(ctx context.Context, projectKey string) ApiPostReleasePipelineRequest { + return ApiPostReleasePipelineRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + } +} + +// Execute executes the request +// @return ReleasePipeline +func (a *ReleasePipelinesBetaApiService) PostReleasePipelineExecute(r ApiPostReleasePipelineRequest) (*ReleasePipeline, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ReleasePipeline + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.PostReleasePipeline") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createReleasePipelineInput == nil { + return localVarReturnValue, nil, reportError("createReleasePipelineInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createReleasePipelineInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutReleasePipelineRequest struct { + ctx context.Context + ApiService ReleasePipelinesBetaApi + projectKey string + pipelineKey string + updateReleasePipelineInput *UpdateReleasePipelineInput +} + +func (r ApiPutReleasePipelineRequest) UpdateReleasePipelineInput(updateReleasePipelineInput UpdateReleasePipelineInput) ApiPutReleasePipelineRequest { + r.updateReleasePipelineInput = &updateReleasePipelineInput + return r +} + +func (r ApiPutReleasePipelineRequest) Execute() (*ReleasePipeline, *http.Response, error) { + return r.ApiService.PutReleasePipelineExecute(r) +} + +/* +PutReleasePipeline Update a release pipeline + +Updates a release pipeline. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param pipelineKey The release pipeline key + @return ApiPutReleasePipelineRequest +*/ +func (a *ReleasePipelinesBetaApiService) PutReleasePipeline(ctx context.Context, projectKey string, pipelineKey string) ApiPutReleasePipelineRequest { + return ApiPutReleasePipelineRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + pipelineKey: pipelineKey, + } +} + +// Execute executes the request +// @return ReleasePipeline +func (a *ReleasePipelinesBetaApiService) PutReleasePipelineExecute(r ApiPutReleasePipelineRequest) (*ReleasePipeline, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ReleasePipeline + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasePipelinesBetaApiService.PutReleasePipeline") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/release-pipelines/{pipelineKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"pipelineKey"+"}", url.PathEscape(parameterToString(r.pipelineKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.updateReleasePipelineInput == nil { + return localVarReturnValue, nil, reportError("updateReleasePipelineInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.updateReleasePipelineInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_releases_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_releases_beta.go new file mode 100644 index 00000000..dc47fa28 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_releases_beta.go @@ -0,0 +1,924 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ReleasesBetaApi interface { + + /* + CreateReleaseForFlag Create a new release for flag + + Creates a release by adding a flag to a release pipeline + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiCreateReleaseForFlagRequest + */ + CreateReleaseForFlag(ctx context.Context, projectKey string, flagKey string) ApiCreateReleaseForFlagRequest + + // CreateReleaseForFlagExecute executes the request + // @return Release + CreateReleaseForFlagExecute(r ApiCreateReleaseForFlagRequest) (*Release, *http.Response, error) + + /* + DeleteReleaseByFlagKey Delete a release for flag + + Deletes a release from a flag + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiDeleteReleaseByFlagKeyRequest + */ + DeleteReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiDeleteReleaseByFlagKeyRequest + + // DeleteReleaseByFlagKeyExecute executes the request + DeleteReleaseByFlagKeyExecute(r ApiDeleteReleaseByFlagKeyRequest) (*http.Response, error) + + /* + GetReleaseByFlagKey Get release for flag + + Get currently active release for a flag + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiGetReleaseByFlagKeyRequest + */ + GetReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiGetReleaseByFlagKeyRequest + + // GetReleaseByFlagKeyExecute executes the request + // @return Release + GetReleaseByFlagKeyExecute(r ApiGetReleaseByFlagKeyRequest) (*Release, *http.Response, error) + + /* + PatchReleaseByFlagKey Patch release for flag + + This endpoint is only available for releases that are part of a legacy release pipeline. Releases for new release pipelines should use the [Update phase status for release](https://launchdarkly.com/docs/api/releases-beta/update-phase-status) endpoint. To learn more about migrating from legacy release pipelines to fully automated release pipelines, read the [Release pipeline migration guide](https://launchdarkly.com/docs/guides/flags/release-pipeline-migration). + +Update currently active release for a flag. Updating releases requires the [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) format. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +You can only use this endpoint to mark a release phase complete or incomplete. To indicate which phase to update, use the array index in the `path`. For example, to mark the first phase of a release as complete, use the following request body: + +``` + [ + { + "op": "replace", + "path": "/phase/0/complete", + "value": true + } + ] +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiPatchReleaseByFlagKeyRequest + */ + PatchReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiPatchReleaseByFlagKeyRequest + + // PatchReleaseByFlagKeyExecute executes the request + // @return Release + PatchReleaseByFlagKeyExecute(r ApiPatchReleaseByFlagKeyRequest) (*Release, *http.Response, error) + + /* + UpdatePhaseStatus Update phase status for release + + Updates the execution status of a phase of a release + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @param phaseId The phase ID + @return ApiUpdatePhaseStatusRequest + */ + UpdatePhaseStatus(ctx context.Context, projectKey string, flagKey string, phaseId string) ApiUpdatePhaseStatusRequest + + // UpdatePhaseStatusExecute executes the request + // @return Release + UpdatePhaseStatusExecute(r ApiUpdatePhaseStatusRequest) (*Release, *http.Response, error) +} + +// ReleasesBetaApiService ReleasesBetaApi service +type ReleasesBetaApiService service + +type ApiCreateReleaseForFlagRequest struct { + ctx context.Context + ApiService ReleasesBetaApi + projectKey string + flagKey string + createReleaseInput *CreateReleaseInput +} + +func (r ApiCreateReleaseForFlagRequest) CreateReleaseInput(createReleaseInput CreateReleaseInput) ApiCreateReleaseForFlagRequest { + r.createReleaseInput = &createReleaseInput + return r +} + +func (r ApiCreateReleaseForFlagRequest) Execute() (*Release, *http.Response, error) { + return r.ApiService.CreateReleaseForFlagExecute(r) +} + +/* +CreateReleaseForFlag Create a new release for flag + +Creates a release by adding a flag to a release pipeline + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiCreateReleaseForFlagRequest +*/ +func (a *ReleasesBetaApiService) CreateReleaseForFlag(ctx context.Context, projectKey string, flagKey string) ApiCreateReleaseForFlagRequest { + return ApiCreateReleaseForFlagRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + } +} + +// Execute executes the request +// @return Release +func (a *ReleasesBetaApiService) CreateReleaseForFlagExecute(r ApiCreateReleaseForFlagRequest) (*Release, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Release + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasesBetaApiService.CreateReleaseForFlag") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{flagKey}/release" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createReleaseInput == nil { + return localVarReturnValue, nil, reportError("createReleaseInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createReleaseInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteReleaseByFlagKeyRequest struct { + ctx context.Context + ApiService ReleasesBetaApi + projectKey string + flagKey string +} + +func (r ApiDeleteReleaseByFlagKeyRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteReleaseByFlagKeyExecute(r) +} + +/* +DeleteReleaseByFlagKey Delete a release for flag + +Deletes a release from a flag + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiDeleteReleaseByFlagKeyRequest +*/ +func (a *ReleasesBetaApiService) DeleteReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiDeleteReleaseByFlagKeyRequest { + return ApiDeleteReleaseByFlagKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + } +} + +// Execute executes the request +func (a *ReleasesBetaApiService) DeleteReleaseByFlagKeyExecute(r ApiDeleteReleaseByFlagKeyRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasesBetaApiService.DeleteReleaseByFlagKey") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{flagKey}/release" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetReleaseByFlagKeyRequest struct { + ctx context.Context + ApiService ReleasesBetaApi + projectKey string + flagKey string +} + +func (r ApiGetReleaseByFlagKeyRequest) Execute() (*Release, *http.Response, error) { + return r.ApiService.GetReleaseByFlagKeyExecute(r) +} + +/* +GetReleaseByFlagKey Get release for flag + +Get currently active release for a flag + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiGetReleaseByFlagKeyRequest +*/ +func (a *ReleasesBetaApiService) GetReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiGetReleaseByFlagKeyRequest { + return ApiGetReleaseByFlagKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + } +} + +// Execute executes the request +// @return Release +func (a *ReleasesBetaApiService) GetReleaseByFlagKeyExecute(r ApiGetReleaseByFlagKeyRequest) (*Release, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Release + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasesBetaApiService.GetReleaseByFlagKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{flagKey}/release" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchReleaseByFlagKeyRequest struct { + ctx context.Context + ApiService ReleasesBetaApi + projectKey string + flagKey string + patchOperation *[]PatchOperation +} + +func (r ApiPatchReleaseByFlagKeyRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchReleaseByFlagKeyRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchReleaseByFlagKeyRequest) Execute() (*Release, *http.Response, error) { + return r.ApiService.PatchReleaseByFlagKeyExecute(r) +} + +/* +PatchReleaseByFlagKey Patch release for flag + +This endpoint is only available for releases that are part of a legacy release pipeline. Releases for new release pipelines should use the [Update phase status for release](https://launchdarkly.com/docs/api/releases-beta/update-phase-status) endpoint. To learn more about migrating from legacy release pipelines to fully automated release pipelines, read the [Release pipeline migration guide](https://launchdarkly.com/docs/guides/flags/release-pipeline-migration). + +Update currently active release for a flag. Updating releases requires the [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) format. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + +You can only use this endpoint to mark a release phase complete or incomplete. To indicate which phase to update, use the array index in the `path`. For example, to mark the first phase of a release as complete, use the following request body: + +``` + [ + { + "op": "replace", + "path": "/phase/0/complete", + "value": true + } + ] +``` + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @return ApiPatchReleaseByFlagKeyRequest +*/ +func (a *ReleasesBetaApiService) PatchReleaseByFlagKey(ctx context.Context, projectKey string, flagKey string) ApiPatchReleaseByFlagKeyRequest { + return ApiPatchReleaseByFlagKeyRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + } +} + +// Execute executes the request +// @return Release +func (a *ReleasesBetaApiService) PatchReleaseByFlagKeyExecute(r ApiPatchReleaseByFlagKeyRequest) (*Release, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Release + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasesBetaApiService.PatchReleaseByFlagKey") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/flags/{projectKey}/{flagKey}/release" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdatePhaseStatusRequest struct { + ctx context.Context + ApiService ReleasesBetaApi + projectKey string + flagKey string + phaseId string + updatePhaseStatusInput *UpdatePhaseStatusInput +} + +func (r ApiUpdatePhaseStatusRequest) UpdatePhaseStatusInput(updatePhaseStatusInput UpdatePhaseStatusInput) ApiUpdatePhaseStatusRequest { + r.updatePhaseStatusInput = &updatePhaseStatusInput + return r +} + +func (r ApiUpdatePhaseStatusRequest) Execute() (*Release, *http.Response, error) { + return r.ApiService.UpdatePhaseStatusExecute(r) +} + +/* +UpdatePhaseStatus Update phase status for release + +Updates the execution status of a phase of a release + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param flagKey The flag key + @param phaseId The phase ID + @return ApiUpdatePhaseStatusRequest +*/ +func (a *ReleasesBetaApiService) UpdatePhaseStatus(ctx context.Context, projectKey string, flagKey string, phaseId string) ApiUpdatePhaseStatusRequest { + return ApiUpdatePhaseStatusRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + flagKey: flagKey, + phaseId: phaseId, + } +} + +// Execute executes the request +// @return Release +func (a *ReleasesBetaApiService) UpdatePhaseStatusExecute(r ApiUpdatePhaseStatusRequest) (*Release, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Release + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReleasesBetaApiService.UpdatePhaseStatus") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{flagKey}/release/phases/{phaseId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"flagKey"+"}", url.PathEscape(parameterToString(r.flagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"phaseId"+"}", url.PathEscape(parameterToString(r.phaseId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.updatePhaseStatusInput == nil { + return localVarReturnValue, nil, reportError("updatePhaseStatusInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.updatePhaseStatusInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_scheduled_changes.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_scheduled_changes.go new file mode 100644 index 00000000..afa5ee49 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_scheduled_changes.go @@ -0,0 +1,1182 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type ScheduledChangesApi interface { + + /* + DeleteFlagConfigScheduledChanges Delete scheduled changes workflow + + Delete a scheduled changes workflow. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change id + @return ApiDeleteFlagConfigScheduledChangesRequest + */ + DeleteFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiDeleteFlagConfigScheduledChangesRequest + + // DeleteFlagConfigScheduledChangesExecute executes the request + DeleteFlagConfigScheduledChangesExecute(r ApiDeleteFlagConfigScheduledChangesRequest) (*http.Response, error) + + /* + GetFeatureFlagScheduledChange Get a scheduled change + + Get a scheduled change that will be applied to the feature flag by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change id + @return ApiGetFeatureFlagScheduledChangeRequest + */ + GetFeatureFlagScheduledChange(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetFeatureFlagScheduledChangeRequest + + // GetFeatureFlagScheduledChangeExecute executes the request + // @return FeatureFlagScheduledChange + GetFeatureFlagScheduledChangeExecute(r ApiGetFeatureFlagScheduledChangeRequest) (*FeatureFlagScheduledChange, *http.Response, error) + + /* + GetFlagConfigScheduledChanges List scheduled changes + + Get a list of scheduled changes that will be applied to the feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetFlagConfigScheduledChangesRequest + */ + GetFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetFlagConfigScheduledChangesRequest + + // GetFlagConfigScheduledChangesExecute executes the request + // @return FeatureFlagScheduledChanges + GetFlagConfigScheduledChangesExecute(r ApiGetFlagConfigScheduledChangesRequest) (*FeatureFlagScheduledChanges, *http.Response, error) + + /* + PatchFlagConfigScheduledChange Update scheduled changes workflow + + +Update a scheduled change, overriding existing instructions with the new ones. Updating a scheduled change uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating scheduled changes. + +
+Click to expand instructions for updating scheduled changes + +#### deleteScheduledChange + +Removes the scheduled change. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "deleteScheduledChange" }] +} +``` + +#### replaceScheduledChangesInstructions + +Removes the existing scheduled changes and replaces them with the new instructions. + +##### Parameters + +- `value`: An array of the new actions to perform when the execution date for these scheduled changes arrives. Supported scheduled actions are `turnFlagOn` and `turnFlagOff`. + +Here's an example that replaces the scheduled changes with new instructions to turn flag targeting off: + +```json +{ + "instructions": [ + { + "kind": "replaceScheduledChangesInstructions", + "value": [ {"kind": "turnFlagOff"} ] + } + ] +} +``` + +#### updateScheduledChangesExecutionDate + +Updates the execution date for the scheduled changes. + +##### Parameters + +- `value`: the new execution date, in Unix milliseconds. + +Here's an example: + +```json +{ + "instructions": [ + { + "kind": "updateScheduledChangesExecutionDate", + "value": 1754092860000 + } + ] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change ID + @return ApiPatchFlagConfigScheduledChangeRequest + */ + PatchFlagConfigScheduledChange(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPatchFlagConfigScheduledChangeRequest + + // PatchFlagConfigScheduledChangeExecute executes the request + // @return FeatureFlagScheduledChange + PatchFlagConfigScheduledChangeExecute(r ApiPatchFlagConfigScheduledChangeRequest) (*FeatureFlagScheduledChange, *http.Response, error) + + /* + PostFlagConfigScheduledChanges Create scheduled changes workflow + + Create scheduled changes for a feature flag. If the `ignoreConficts` query parameter is false and there are conflicts between these instructions and existing scheduled changes, the request will fail. If the parameter is true and there are conflicts, the request will succeed. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostFlagConfigScheduledChangesRequest + */ + PostFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostFlagConfigScheduledChangesRequest + + // PostFlagConfigScheduledChangesExecute executes the request + // @return FeatureFlagScheduledChange + PostFlagConfigScheduledChangesExecute(r ApiPostFlagConfigScheduledChangesRequest) (*FeatureFlagScheduledChange, *http.Response, error) +} + +// ScheduledChangesApiService ScheduledChangesApi service +type ScheduledChangesApiService service + +type ApiDeleteFlagConfigScheduledChangesRequest struct { + ctx context.Context + ApiService ScheduledChangesApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiDeleteFlagConfigScheduledChangesRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteFlagConfigScheduledChangesExecute(r) +} + +/* +DeleteFlagConfigScheduledChanges Delete scheduled changes workflow + +Delete a scheduled changes workflow. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change id + @return ApiDeleteFlagConfigScheduledChangesRequest +*/ +func (a *ScheduledChangesApiService) DeleteFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiDeleteFlagConfigScheduledChangesRequest { + return ApiDeleteFlagConfigScheduledChangesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +func (a *ScheduledChangesApiService) DeleteFlagConfigScheduledChangesExecute(r ApiDeleteFlagConfigScheduledChangesRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ScheduledChangesApiService.DeleteFlagConfigScheduledChanges") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetFeatureFlagScheduledChangeRequest struct { + ctx context.Context + ApiService ScheduledChangesApi + projectKey string + featureFlagKey string + environmentKey string + id string +} + +func (r ApiGetFeatureFlagScheduledChangeRequest) Execute() (*FeatureFlagScheduledChange, *http.Response, error) { + return r.ApiService.GetFeatureFlagScheduledChangeExecute(r) +} + +/* +GetFeatureFlagScheduledChange Get a scheduled change + +Get a scheduled change that will be applied to the feature flag by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change id + @return ApiGetFeatureFlagScheduledChangeRequest +*/ +func (a *ScheduledChangesApiService) GetFeatureFlagScheduledChange(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiGetFeatureFlagScheduledChangeRequest { + return ApiGetFeatureFlagScheduledChangeRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FeatureFlagScheduledChange +func (a *ScheduledChangesApiService) GetFeatureFlagScheduledChangeExecute(r ApiGetFeatureFlagScheduledChangeRequest) (*FeatureFlagScheduledChange, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagScheduledChange + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ScheduledChangesApiService.GetFeatureFlagScheduledChange") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetFlagConfigScheduledChangesRequest struct { + ctx context.Context + ApiService ScheduledChangesApi + projectKey string + featureFlagKey string + environmentKey string +} + +func (r ApiGetFlagConfigScheduledChangesRequest) Execute() (*FeatureFlagScheduledChanges, *http.Response, error) { + return r.ApiService.GetFlagConfigScheduledChangesExecute(r) +} + +/* +GetFlagConfigScheduledChanges List scheduled changes + +Get a list of scheduled changes that will be applied to the feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetFlagConfigScheduledChangesRequest +*/ +func (a *ScheduledChangesApiService) GetFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetFlagConfigScheduledChangesRequest { + return ApiGetFlagConfigScheduledChangesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FeatureFlagScheduledChanges +func (a *ScheduledChangesApiService) GetFlagConfigScheduledChangesExecute(r ApiGetFlagConfigScheduledChangesRequest) (*FeatureFlagScheduledChanges, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagScheduledChanges + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ScheduledChangesApiService.GetFlagConfigScheduledChanges") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchFlagConfigScheduledChangeRequest struct { + ctx context.Context + ApiService ScheduledChangesApi + projectKey string + featureFlagKey string + environmentKey string + id string + flagScheduledChangesInput *FlagScheduledChangesInput + ignoreConflicts *bool +} + +func (r ApiPatchFlagConfigScheduledChangeRequest) FlagScheduledChangesInput(flagScheduledChangesInput FlagScheduledChangesInput) ApiPatchFlagConfigScheduledChangeRequest { + r.flagScheduledChangesInput = &flagScheduledChangesInput + return r +} + +// Whether to succeed (`true`) or fail (`false`) when these new instructions conflict with existing scheduled changes +func (r ApiPatchFlagConfigScheduledChangeRequest) IgnoreConflicts(ignoreConflicts bool) ApiPatchFlagConfigScheduledChangeRequest { + r.ignoreConflicts = &ignoreConflicts + return r +} + +func (r ApiPatchFlagConfigScheduledChangeRequest) Execute() (*FeatureFlagScheduledChange, *http.Response, error) { + return r.ApiService.PatchFlagConfigScheduledChangeExecute(r) +} + +/* +PatchFlagConfigScheduledChange Update scheduled changes workflow + + +Update a scheduled change, overriding existing instructions with the new ones. Updating a scheduled change uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating scheduled changes. + +
+Click to expand instructions for updating scheduled changes + +#### deleteScheduledChange + +Removes the scheduled change. + +Here's an example: + +```json +{ + "instructions": [{ "kind": "deleteScheduledChange" }] +} +``` + +#### replaceScheduledChangesInstructions + +Removes the existing scheduled changes and replaces them with the new instructions. + +##### Parameters + +- `value`: An array of the new actions to perform when the execution date for these scheduled changes arrives. Supported scheduled actions are `turnFlagOn` and `turnFlagOff`. + +Here's an example that replaces the scheduled changes with new instructions to turn flag targeting off: + +```json +{ + "instructions": [ + { + "kind": "replaceScheduledChangesInstructions", + "value": [ {"kind": "turnFlagOff"} ] + } + ] +} +``` + +#### updateScheduledChangesExecutionDate + +Updates the execution date for the scheduled changes. + +##### Parameters + +- `value`: the new execution date, in Unix milliseconds. + +Here's an example: + +```json +{ + "instructions": [ + { + "kind": "updateScheduledChangesExecutionDate", + "value": 1754092860000 + } + ] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param id The scheduled change ID + @return ApiPatchFlagConfigScheduledChangeRequest +*/ +func (a *ScheduledChangesApiService) PatchFlagConfigScheduledChange(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, id string) ApiPatchFlagConfigScheduledChangeRequest { + return ApiPatchFlagConfigScheduledChangeRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + id: id, + } +} + +// Execute executes the request +// @return FeatureFlagScheduledChange +func (a *ScheduledChangesApiService) PatchFlagConfigScheduledChangeExecute(r ApiPatchFlagConfigScheduledChangeRequest) (*FeatureFlagScheduledChange, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagScheduledChange + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ScheduledChangesApiService.PatchFlagConfigScheduledChange") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.flagScheduledChangesInput == nil { + return localVarReturnValue, nil, reportError("flagScheduledChangesInput is required and must be specified") + } + + if r.ignoreConflicts != nil { + localVarQueryParams.Add("ignoreConflicts", parameterToString(*r.ignoreConflicts, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.flagScheduledChangesInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostFlagConfigScheduledChangesRequest struct { + ctx context.Context + ApiService ScheduledChangesApi + projectKey string + featureFlagKey string + environmentKey string + postFlagScheduledChangesInput *PostFlagScheduledChangesInput + ignoreConflicts *bool +} + +func (r ApiPostFlagConfigScheduledChangesRequest) PostFlagScheduledChangesInput(postFlagScheduledChangesInput PostFlagScheduledChangesInput) ApiPostFlagConfigScheduledChangesRequest { + r.postFlagScheduledChangesInput = &postFlagScheduledChangesInput + return r +} + +// Whether to succeed (`true`) or fail (`false`) when these instructions conflict with existing scheduled changes +func (r ApiPostFlagConfigScheduledChangesRequest) IgnoreConflicts(ignoreConflicts bool) ApiPostFlagConfigScheduledChangesRequest { + r.ignoreConflicts = &ignoreConflicts + return r +} + +func (r ApiPostFlagConfigScheduledChangesRequest) Execute() (*FeatureFlagScheduledChange, *http.Response, error) { + return r.ApiService.PostFlagConfigScheduledChangesExecute(r) +} + +/* +PostFlagConfigScheduledChanges Create scheduled changes workflow + +Create scheduled changes for a feature flag. If the `ignoreConficts` query parameter is false and there are conflicts between these instructions and existing scheduled changes, the request will fail. If the parameter is true and there are conflicts, the request will succeed. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostFlagConfigScheduledChangesRequest +*/ +func (a *ScheduledChangesApiService) PostFlagConfigScheduledChanges(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostFlagConfigScheduledChangesRequest { + return ApiPostFlagConfigScheduledChangesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return FeatureFlagScheduledChange +func (a *ScheduledChangesApiService) PostFlagConfigScheduledChangesExecute(r ApiPostFlagConfigScheduledChangesRequest) (*FeatureFlagScheduledChange, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *FeatureFlagScheduledChange + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ScheduledChangesApiService.PostFlagConfigScheduledChanges") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/scheduled-changes" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.postFlagScheduledChangesInput == nil { + return localVarReturnValue, nil, reportError("postFlagScheduledChangesInput is required and must be specified") + } + + if r.ignoreConflicts != nil { + localVarQueryParams.Add("ignoreConflicts", parameterToString(*r.ignoreConflicts, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.postFlagScheduledChangesInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_segments.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_segments.go new file mode 100644 index 00000000..af965c03 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_segments.go @@ -0,0 +1,5019 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "os" +) + + +type SegmentsApi interface { + + /* + CreateBigSegmentExport Create big segment export + + Starts a new export process for a big segment. This is an export for a synced segment or a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiCreateBigSegmentExportRequest + */ + CreateBigSegmentExport(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiCreateBigSegmentExportRequest + + // CreateBigSegmentExportExecute executes the request + CreateBigSegmentExportExecute(r ApiCreateBigSegmentExportRequest) (*http.Response, error) + + /* + CreateBigSegmentImport Create big segment import + + Start a new import process for a big segment. This is an import for a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiCreateBigSegmentImportRequest + */ + CreateBigSegmentImport(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiCreateBigSegmentImportRequest + + // CreateBigSegmentImportExecute executes the request + CreateBigSegmentImportExecute(r ApiCreateBigSegmentImportRequest) (*http.Response, error) + + /* + DeleteSegment Delete segment + + Delete a segment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiDeleteSegmentRequest + */ + DeleteSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiDeleteSegmentRequest + + // DeleteSegmentExecute executes the request + DeleteSegmentExecute(r ApiDeleteSegmentRequest) (*http.Response, error) + + /* + GetBigSegmentExport Get big segment export + + Returns information about a big segment export process. This is an export for a synced segment or a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param exportID The export ID + @return ApiGetBigSegmentExportRequest + */ + GetBigSegmentExport(ctx context.Context, projectKey string, environmentKey string, segmentKey string, exportID string) ApiGetBigSegmentExportRequest + + // GetBigSegmentExportExecute executes the request + // @return Export + GetBigSegmentExportExecute(r ApiGetBigSegmentExportRequest) (*Export, *http.Response, error) + + /* + GetBigSegmentImport Get big segment import + + Returns information about a big segment import process. This is the import of a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param importID The import ID + @return ApiGetBigSegmentImportRequest + */ + GetBigSegmentImport(ctx context.Context, projectKey string, environmentKey string, segmentKey string, importID string) ApiGetBigSegmentImportRequest + + // GetBigSegmentImportExecute executes the request + // @return Import + GetBigSegmentImportExecute(r ApiGetBigSegmentImportRequest) (*Import, *http.Response, error) + + /* + GetContextInstanceSegmentsMembershipByEnv List segment memberships for context instance + + For a given context instance with attributes, get membership details for all segments. In the request body, pass in the context instance. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetContextInstanceSegmentsMembershipByEnvRequest + */ + GetContextInstanceSegmentsMembershipByEnv(ctx context.Context, projectKey string, environmentKey string) ApiGetContextInstanceSegmentsMembershipByEnvRequest + + // GetContextInstanceSegmentsMembershipByEnvExecute executes the request + // @return ContextInstanceSegmentMemberships + GetContextInstanceSegmentsMembershipByEnvExecute(r ApiGetContextInstanceSegmentsMembershipByEnvRequest) (*ContextInstanceSegmentMemberships, *http.Response, error) + + /* + GetExpiringTargetsForSegment Get expiring targets for segment + + Get a list of a segment's context targets that are scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetExpiringTargetsForSegmentRequest + */ + GetExpiringTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetExpiringTargetsForSegmentRequest + + // GetExpiringTargetsForSegmentExecute executes the request + // @return ExpiringTargetGetResponse + GetExpiringTargetsForSegmentExecute(r ApiGetExpiringTargetsForSegmentRequest) (*ExpiringTargetGetResponse, *http.Response, error) + + /* + GetExpiringUserTargetsForSegment Get expiring user targets for segment + + > ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/get-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get a list of a segment's user targets that are scheduled for removal. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetExpiringUserTargetsForSegmentRequest + */ + GetExpiringUserTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetExpiringUserTargetsForSegmentRequest + + // GetExpiringUserTargetsForSegmentExecute executes the request + // @return ExpiringUserTargetGetResponse + GetExpiringUserTargetsForSegmentExecute(r ApiGetExpiringUserTargetsForSegmentRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) + + /* + GetSegment Get segment + + Get a single segment by key.

Segments can be rule-based, list-based, or synced. Big segments include larger list-based segments and synced segments. Some fields in the response only apply to big segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetSegmentRequest + */ + GetSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetSegmentRequest + + // GetSegmentExecute executes the request + // @return UserSegment + GetSegmentExecute(r ApiGetSegmentRequest) (*UserSegment, *http.Response, error) + + /* + GetSegmentMembershipForContext Get big segment membership for context + + Get the membership status (included/excluded) for a given context in this big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param contextKey The context key + @return ApiGetSegmentMembershipForContextRequest + */ + GetSegmentMembershipForContext(ctx context.Context, projectKey string, environmentKey string, segmentKey string, contextKey string) ApiGetSegmentMembershipForContextRequest + + // GetSegmentMembershipForContextExecute executes the request + // @return BigSegmentTarget + GetSegmentMembershipForContextExecute(r ApiGetSegmentMembershipForContextRequest) (*BigSegmentTarget, *http.Response, error) + + /* + GetSegmentMembershipForUser Get big segment membership for user + + > ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/get-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get the membership status (included/excluded) for a given user in this big segment. This operation does not support standard segments. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param userKey The user key + @return ApiGetSegmentMembershipForUserRequest + */ + GetSegmentMembershipForUser(ctx context.Context, projectKey string, environmentKey string, segmentKey string, userKey string) ApiGetSegmentMembershipForUserRequest + + // GetSegmentMembershipForUserExecute executes the request + // @return BigSegmentTarget + GetSegmentMembershipForUserExecute(r ApiGetSegmentMembershipForUserRequest) (*BigSegmentTarget, *http.Response, error) + + /* + GetSegments List segments + + Get a list of all segments in the given project. + +Segments can be rule-based, list-based, or synced. Big segments include larger list-based segments and synced segments. Some fields in the response only apply to big segments. + +### Filtering segments + +The `filter` parameter supports the following operators: `equals`, `anyOf`, and `exists`. + +You can also combine filters in the following ways: + +- Use a comma (`,`) as an AND operator +- Use a vertical bar (`|`) as an OR operator +- Use parentheses (`()`) to group filters + +#### Supported fields and operators + +You can only filter certain fields in segments when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for segments, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `excludedKeys` | The segment keys of segments to exclude from the results. | `anyOf` | +| `external` | Whether the segment is a synced segment. | `exists` | +| `includedKeys` | The segment keys of segments to include in the results. | `anyOf` | +| `query` | A "fuzzy" search across segment key, name, and description. Supply a string or list of strings to the operator. | `equals` | +| `tags` | The segment tags. | `anyOf` | +| `unbounded` | Whether the segment is a standard segment (`false`) or a big segment (`true`). Standard segments include rule-based segments and smaller list-based segments. Big segments include larger list-based segments and synced segments. | `equals` | + +Here are a few examples: + +* The filter `?filter=tags anyOf ["enterprise", "beta"],query equals "toggle"` matches segments with "toggle" in their key, name, or description that also have "enterprise" or "beta" as a tag. +* The filter `?filter=excludedKeys anyOf ["segmentKey1", "segmentKey2"]` excludes the segments with those keys from the results. +* The filter `?filter=unbounded equals true` matches larger list-based segments and synced segments. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `[` in `?filter=tags anyOf ["enterprise", "beta"]` must be encoded to `%5B`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetSegmentsRequest + */ + GetSegments(ctx context.Context, projectKey string, environmentKey string) ApiGetSegmentsRequest + + // GetSegmentsExecute executes the request + // @return UserSegments + GetSegmentsExecute(r ApiGetSegmentsRequest) (*UserSegments, *http.Response, error) + + /* + PatchExpiringTargetsForSegment Update expiring targets for segment + + +Update expiring context targets for a segment. Updating a context target expiration uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +If the request is well-formed but any of its instructions failed to process, this operation returns status code `200`. In this case, the response `errors` array will be non-empty. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring context targets. + +
+Click to expand instructions for updating expiring context targets + +#### addExpiringTarget + +Schedules a date and time when LaunchDarkly will remove a context from segment targeting. The segment must already have the context as an individual target. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. +- `value`: The date when the context should expire from the segment targeting, in Unix milliseconds. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + "value": 1754092860000 + }] +} +``` + +#### updateExpiringTarget + +Updates the date and time when LaunchDarkly will remove a context from segment targeting. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. +- `value`: The new date when the context should expire from the segment targeting, in Unix milliseconds. +- `version`: (Optional) The version of the expiring target to update. If included, update will fail if version doesn't match current version of the expiring target. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + "value": 1754179260000 + }] +} +``` + +#### removeExpiringTarget + +Removes the scheduled expiration for the context in the segment. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchExpiringTargetsForSegmentRequest + */ + PatchExpiringTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchExpiringTargetsForSegmentRequest + + // PatchExpiringTargetsForSegmentExecute executes the request + // @return ExpiringTargetPatchResponse + PatchExpiringTargetsForSegmentExecute(r ApiPatchExpiringTargetsForSegmentRequest) (*ExpiringTargetPatchResponse, *http.Response, error) + + /* + PatchExpiringUserTargetsForSegment Update expiring user targets for segment + + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Update expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/patch-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Update expiring user targets for a segment. Updating a user target expiration uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +If the request is well-formed but any of its instructions failed to process, this operation returns status code `200`. In this case, the response `errors` array will be non-empty. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Schedules a date and time when LaunchDarkly will remove a user from segment targeting. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. +- `value`: The date when the user should expire from the segment targeting, in Unix milliseconds. + +#### updateExpireUserTargetDate + +Updates the date and time when LaunchDarkly will remove a user from segment targeting. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. +- `value`: The new date when the user should expire from the segment targeting, in Unix milliseconds. +- `version`: The segment version. + +#### removeExpireUserTargetDate + +Removes the scheduled expiration for the user in the segment. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchExpiringUserTargetsForSegmentRequest + */ + PatchExpiringUserTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchExpiringUserTargetsForSegmentRequest + + // PatchExpiringUserTargetsForSegmentExecute executes the request + // @return ExpiringUserTargetPatchResponse + PatchExpiringUserTargetsForSegmentExecute(r ApiPatchExpiringUserTargetsForSegmentRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) + + /* + PatchSegment Patch segment + + Update a segment. The request body must be a valid semantic patch, JSON patch, or JSON merge patch. To learn more the different formats, read [Updates](https://launchdarkly.com/docs/api#updates). + +### Using semantic patches on a segment + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +The body of a semantic patch request for updating segments requires an `environmentKey` in addition to `instructions` and an optional `comment`. The body of the request takes the following properties: + +* `comment` (string): (Optional) A description of the update. +* `environmentKey` (string): (Required) The key of the LaunchDarkly environment. +* `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the action requires parameters, you must include those parameters as additional fields in the object. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating segments. + +
+Click to expand instructions for updating segment details and settings + +#### addTags + +Adds tags to the segment. + +##### Parameters + +- `values`: A list of tags to add. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addTags", + "values": ["tag1", "tag2"] + }] +} +``` + +#### removeTags + +Removes tags from the segment. + +##### Parameters + +- `values`: A list of tags to remove. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeTags", + "values": ["tag1", "tag2"] + }] +} +``` + +#### updateName + +Updates the name of the segment. + +##### Parameters + +- `value`: Name of the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Updated segment name" + }] +} +``` + +
+ +
+Click to expand instructions for updating segment individual targets + +#### addExcludedTargets + +Adds context keys to the individual context targets excluded from the segment for the specified `contextKind`. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `contextKind`: The context kind the targets should be added to. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExcludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addExcludedUsers + +Adds user keys to the individual user targets excluded from the segment. Returns an error if this causes the same user key to be both included and excluded. If you are working with contexts, use `addExcludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExcludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### addIncludedTargets + +Adds context keys to the individual context targets included in the segment for the specified `contextKind`. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `contextKind`: The context kind the targets should be added to. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addIncludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addIncludedUsers + +Adds user keys to the individual user targets included in the segment. Returns an error if this causes the same user key to be both included and excluded. If you are working with contexts, use `addIncludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addIncludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### removeExcludedTargets + +Removes context keys from the individual context targets excluded from the segment for the specified `contextKind`. + +##### Parameters + +- `contextKind`: The context kind the targets should be removed from. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExcludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeExcludedUsers + +Removes user keys from the individual user targets excluded from the segment. If you are working with contexts, use `removeExcludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExcludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### removeIncludedTargets + +Removes context keys from the individual context targets included in the segment for the specified `contextKind`. + +##### Parameters + +- `contextKind`: The context kind the targets should be removed from. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeIncludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeIncludedUsers + +Removes user keys from the individual user targets included in the segment. If you are working with contexts, use `removeIncludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeIncludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +
+ +
+Click to expand instructions for updating segment targeting rules + +#### addClauses + +Adds the given clauses to the rule indicated by `ruleId`. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `ruleId`: ID of a rule in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addClauses", + "clauses": [ + { + "attribute": "email", + "negate": false, + "op": "contains", + "values": ["value1"] + } + ], + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + }] +} +``` + +#### addRule + +Adds a new targeting rule to the segment. The rule may contain `clauses`. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `description`: A description of the rule. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addRule", + "clauses": [ + { + "attribute": "email", + "op": "contains", + "negate": false, + "values": ["@launchdarkly.com"] + } + ], + "description": "Targeting rule for LaunchDarkly employees", + }] +} +``` + +#### addValuesToClause + +Adds `values` to the values of the clause that `ruleId` and `clauseId` indicate. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addValuesToClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### removeClauses + +Removes the clauses specified by `clauseIds` from the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseIds`: Array of IDs of clauses in the rule. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseIds": ["10a58772-3121-400f-846b-b8a04e8944ed", "36a461dc-235e-4b08-97b9-73ce9365873e"] + }] +} +``` + +#### removeRule + +Removes the targeting rule specified by `ruleId`. Does nothing if the rule does not exist. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeRule", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### removeValuesFromClause + +Removes `values` from the values of the clause indicated by `ruleId` and `clauseId`. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeValuesFromClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### reorderRules + +Rearranges the rules to match the order given in `ruleIds`. Returns an error if `ruleIds` does not match the current set of rules in the segment. + +##### Parameters + +- `ruleIds`: Array of IDs of all targeting rules in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "reorderRules", + "ruleIds": ["a902ef4a-2faf-4eaf-88e1-ecc356708a29", "63c238d1-835d-435e-8f21-c8d5e40b2a3d"] + }] +} +``` + +#### updateClause + +Replaces the clause indicated by `ruleId` and `clauseId` with `clause`. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `clause`: New `clause` object, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10c7462a-2062-45ba-a8bb-dfb3de0f8af5", + "clause": { + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["Mexico", "Canada"] + } + }] +} +``` + +#### updateRuleDescription + +Updates the description of the segment targeting rule. + +##### Parameters + +- `description`: The new human-readable description for this rule. +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateRuleDescription", + "description": "New rule description", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### updateRuleRolloutAndContextKind + +For a rule that includes a percentage of targets, updates the percentage and the context kind of the targets to include. + +##### Parameters + +- `ruleId`: The ID of a targeting rule in the segment that includes a percentage of targets. +- `weight`: The weight, in thousandths of a percent (0-100000). +- `contextKind`: The context kind. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "reorderRules", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "weight": "20000", + "contextKind": "device" + }] +} +``` + +
+ +
+Click to expand instructions for working with Big Segments + +A "big segment" is a segment that is either a synced segment, or a list-based segment with more than 15,000 entries that includes only one targeted context kind. LaunchDarkly uses different implementations for different types of segments so that all of your segments have good performance. + +The following semantic patch instructions apply only to these [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments). + +#### addBigSegmentExcludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Adds context keys to the context targets excluded from the segment. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addBigSegmentExcludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addBigSegmentIncludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Adds context keys to the context targets included in the segment. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addBigSegmentIncludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### processBigSegmentImport + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Processes a segment import. + +##### Parameters + +- `importId`: The ID of the import. The import ID is returned in the `Location` header as part of the [Create big segment import](https://launchdarkly.com/docs/api/segments/create-big-segment-import) request. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "processBigSegmentImport", + "importId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + + +#### removeBigSegmentExcludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Removes context keys from the context targets excluded from the segment. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeBigSegmentExcludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeBigSegmentIncludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Removes context keys from the context targets included in the segment. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeBigSegmentIncludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +
+ +### Using JSON patches on a segment + +If you do not include the header described above, you can use a [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. + +For example, to update the description for a segment with a JSON patch, use the following request body: + +```json +{ + "patch": [ + { + "op": "replace", + "path": "/description", + "value": "new description" + } + ] +} +``` + +To update fields in the segment that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add the new entry to the beginning of the array. Use `/-` to add the new entry to the end of the array. + +For example, to add a rule to a segment, use the following request body: + +```json +{ + "patch":[ + { + "op": "add", + "path": "/rules/0", + "value": { + "clauses": [{ "contextKind": "user", "attribute": "email", "op": "endsWith", "values": [".edu"], "negate": false }] + } + } + ] +} +``` + +To add or remove targets from segments, we recommend using semantic patch. Semantic patch for segments includes specific instructions for adding and removing both included and excluded targets. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchSegmentRequest + */ + PatchSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchSegmentRequest + + // PatchSegmentExecute executes the request + // @return UserSegment + PatchSegmentExecute(r ApiPatchSegmentRequest) (*UserSegment, *http.Response, error) + + /* + PostSegment Create segment + + Create a new segment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostSegmentRequest + */ + PostSegment(ctx context.Context, projectKey string, environmentKey string) ApiPostSegmentRequest + + // PostSegmentExecute executes the request + // @return UserSegment + PostSegmentExecute(r ApiPostSegmentRequest) (*UserSegment, *http.Response, error) + + /* + UpdateBigSegmentContextTargets Update context targets on a big segment + + Update context targets included or excluded in a big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiUpdateBigSegmentContextTargetsRequest + */ + UpdateBigSegmentContextTargets(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiUpdateBigSegmentContextTargetsRequest + + // UpdateBigSegmentContextTargetsExecute executes the request + UpdateBigSegmentContextTargetsExecute(r ApiUpdateBigSegmentContextTargetsRequest) (*http.Response, error) + + /* + UpdateBigSegmentTargets Update user context targets on a big segment + + Update user context targets included or excluded in a big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiUpdateBigSegmentTargetsRequest + */ + UpdateBigSegmentTargets(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiUpdateBigSegmentTargetsRequest + + // UpdateBigSegmentTargetsExecute executes the request + UpdateBigSegmentTargetsExecute(r ApiUpdateBigSegmentTargetsRequest) (*http.Response, error) +} + +// SegmentsApiService SegmentsApi service +type SegmentsApiService service + +type ApiCreateBigSegmentExportRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string +} + +func (r ApiCreateBigSegmentExportRequest) Execute() (*http.Response, error) { + return r.ApiService.CreateBigSegmentExportExecute(r) +} + +/* +CreateBigSegmentExport Create big segment export + +Starts a new export process for a big segment. This is an export for a synced segment or a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiCreateBigSegmentExportRequest +*/ +func (a *SegmentsApiService) CreateBigSegmentExport(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiCreateBigSegmentExportRequest { + return ApiCreateBigSegmentExportRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +func (a *SegmentsApiService) CreateBigSegmentExportExecute(r ApiCreateBigSegmentExportRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.CreateBigSegmentExport") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/exports" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiCreateBigSegmentImportRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + file **os.File + mode *string + waitOnApprovals *bool +} + +// CSV file containing keys +func (r ApiCreateBigSegmentImportRequest) File(file *os.File) ApiCreateBigSegmentImportRequest { + r.file = &file + return r +} + +// Import mode. Use either `merge` or `replace` +func (r ApiCreateBigSegmentImportRequest) Mode(mode string) ApiCreateBigSegmentImportRequest { + r.mode = &mode + return r +} + +// Whether to wait for approvals before processing the import +func (r ApiCreateBigSegmentImportRequest) WaitOnApprovals(waitOnApprovals bool) ApiCreateBigSegmentImportRequest { + r.waitOnApprovals = &waitOnApprovals + return r +} + +func (r ApiCreateBigSegmentImportRequest) Execute() (*http.Response, error) { + return r.ApiService.CreateBigSegmentImportExecute(r) +} + +/* +CreateBigSegmentImport Create big segment import + +Start a new import process for a big segment. This is an import for a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiCreateBigSegmentImportRequest +*/ +func (a *SegmentsApiService) CreateBigSegmentImport(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiCreateBigSegmentImportRequest { + return ApiCreateBigSegmentImportRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +func (a *SegmentsApiService) CreateBigSegmentImportExecute(r ApiCreateBigSegmentImportRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.CreateBigSegmentImport") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/imports" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"multipart/form-data"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + var fileLocalVarFormFileName string + var fileLocalVarFileName string + var fileLocalVarFileBytes []byte + + fileLocalVarFormFileName = "file" + + var fileLocalVarFile *os.File + if r.file != nil { + fileLocalVarFile = *r.file + } + if fileLocalVarFile != nil { + fbs, _ := ioutil.ReadAll(fileLocalVarFile) + fileLocalVarFileBytes = fbs + fileLocalVarFileName = fileLocalVarFile.Name() + fileLocalVarFile.Close() + } + formFiles = append(formFiles, formFile{fileBytes: fileLocalVarFileBytes, fileName: fileLocalVarFileName, formFileName: fileLocalVarFormFileName}) + if r.mode != nil { + localVarFormParams.Add("mode", parameterToString(*r.mode, "")) + } + if r.waitOnApprovals != nil { + localVarFormParams.Add("waitOnApprovals", parameterToString(*r.waitOnApprovals, "")) + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiDeleteSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string +} + +func (r ApiDeleteSegmentRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteSegmentExecute(r) +} + +/* +DeleteSegment Delete segment + +Delete a segment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiDeleteSegmentRequest +*/ +func (a *SegmentsApiService) DeleteSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiDeleteSegmentRequest { + return ApiDeleteSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +func (a *SegmentsApiService) DeleteSegmentExecute(r ApiDeleteSegmentRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.DeleteSegment") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetBigSegmentExportRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + exportID string +} + +func (r ApiGetBigSegmentExportRequest) Execute() (*Export, *http.Response, error) { + return r.ApiService.GetBigSegmentExportExecute(r) +} + +/* +GetBigSegmentExport Get big segment export + +Returns information about a big segment export process. This is an export for a synced segment or a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param exportID The export ID + @return ApiGetBigSegmentExportRequest +*/ +func (a *SegmentsApiService) GetBigSegmentExport(ctx context.Context, projectKey string, environmentKey string, segmentKey string, exportID string) ApiGetBigSegmentExportRequest { + return ApiGetBigSegmentExportRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + exportID: exportID, + } +} + +// Execute executes the request +// @return Export +func (a *SegmentsApiService) GetBigSegmentExportExecute(r ApiGetBigSegmentExportRequest) (*Export, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Export + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetBigSegmentExport") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/exports/{exportID}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"exportID"+"}", url.PathEscape(parameterToString(r.exportID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetBigSegmentImportRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + importID string +} + +func (r ApiGetBigSegmentImportRequest) Execute() (*Import, *http.Response, error) { + return r.ApiService.GetBigSegmentImportExecute(r) +} + +/* +GetBigSegmentImport Get big segment import + +Returns information about a big segment import process. This is the import of a list-based segment that can include more than 15,000 entries. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param importID The import ID + @return ApiGetBigSegmentImportRequest +*/ +func (a *SegmentsApiService) GetBigSegmentImport(ctx context.Context, projectKey string, environmentKey string, segmentKey string, importID string) ApiGetBigSegmentImportRequest { + return ApiGetBigSegmentImportRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + importID: importID, + } +} + +// Execute executes the request +// @return Import +func (a *SegmentsApiService) GetBigSegmentImportExecute(r ApiGetBigSegmentImportRequest) (*Import, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Import + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetBigSegmentImport") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/imports/{importID}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"importID"+"}", url.PathEscape(parameterToString(r.importID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetContextInstanceSegmentsMembershipByEnvRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + requestBody *map[string]interface{} +} + +func (r ApiGetContextInstanceSegmentsMembershipByEnvRequest) RequestBody(requestBody map[string]interface{}) ApiGetContextInstanceSegmentsMembershipByEnvRequest { + r.requestBody = &requestBody + return r +} + +func (r ApiGetContextInstanceSegmentsMembershipByEnvRequest) Execute() (*ContextInstanceSegmentMemberships, *http.Response, error) { + return r.ApiService.GetContextInstanceSegmentsMembershipByEnvExecute(r) +} + +/* +GetContextInstanceSegmentsMembershipByEnv List segment memberships for context instance + +For a given context instance with attributes, get membership details for all segments. In the request body, pass in the context instance. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetContextInstanceSegmentsMembershipByEnvRequest +*/ +func (a *SegmentsApiService) GetContextInstanceSegmentsMembershipByEnv(ctx context.Context, projectKey string, environmentKey string) ApiGetContextInstanceSegmentsMembershipByEnvRequest { + return ApiGetContextInstanceSegmentsMembershipByEnvRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ContextInstanceSegmentMemberships +func (a *SegmentsApiService) GetContextInstanceSegmentsMembershipByEnvExecute(r ApiGetContextInstanceSegmentsMembershipByEnvRequest) (*ContextInstanceSegmentMemberships, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ContextInstanceSegmentMemberships + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetContextInstanceSegmentsMembershipByEnv") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/environments/{environmentKey}/segments/evaluate" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.requestBody == nil { + return localVarReturnValue, nil, reportError("requestBody is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.requestBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExpiringTargetsForSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string +} + +func (r ApiGetExpiringTargetsForSegmentRequest) Execute() (*ExpiringTargetGetResponse, *http.Response, error) { + return r.ApiService.GetExpiringTargetsForSegmentExecute(r) +} + +/* +GetExpiringTargetsForSegment Get expiring targets for segment + +Get a list of a segment's context targets that are scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetExpiringTargetsForSegmentRequest +*/ +func (a *SegmentsApiService) GetExpiringTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetExpiringTargetsForSegmentRequest { + return ApiGetExpiringTargetsForSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return ExpiringTargetGetResponse +func (a *SegmentsApiService) GetExpiringTargetsForSegmentExecute(r ApiGetExpiringTargetsForSegmentRequest) (*ExpiringTargetGetResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringTargetGetResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetExpiringTargetsForSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{segmentKey}/expiring-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetExpiringUserTargetsForSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string +} + +func (r ApiGetExpiringUserTargetsForSegmentRequest) Execute() (*ExpiringUserTargetGetResponse, *http.Response, error) { + return r.ApiService.GetExpiringUserTargetsForSegmentExecute(r) +} + +/* +GetExpiringUserTargetsForSegment Get expiring user targets for segment + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/get-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get a list of a segment's user targets that are scheduled for removal. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetExpiringUserTargetsForSegmentRequest +*/ +func (a *SegmentsApiService) GetExpiringUserTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetExpiringUserTargetsForSegmentRequest { + return ApiGetExpiringUserTargetsForSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetGetResponse +func (a *SegmentsApiService) GetExpiringUserTargetsForSegmentExecute(r ApiGetExpiringUserTargetsForSegmentRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetGetResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetExpiringUserTargetsForSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{segmentKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string +} + +func (r ApiGetSegmentRequest) Execute() (*UserSegment, *http.Response, error) { + return r.ApiService.GetSegmentExecute(r) +} + +/* +GetSegment Get segment + +Get a single segment by key.

Segments can be rule-based, list-based, or synced. Big segments include larger list-based segments and synced segments. Some fields in the response only apply to big segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiGetSegmentRequest +*/ +func (a *SegmentsApiService) GetSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiGetSegmentRequest { + return ApiGetSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return UserSegment +func (a *SegmentsApiService) GetSegmentExecute(r ApiGetSegmentRequest) (*UserSegment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserSegment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetSegmentMembershipForContextRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + contextKey string +} + +func (r ApiGetSegmentMembershipForContextRequest) Execute() (*BigSegmentTarget, *http.Response, error) { + return r.ApiService.GetSegmentMembershipForContextExecute(r) +} + +/* +GetSegmentMembershipForContext Get big segment membership for context + +Get the membership status (included/excluded) for a given context in this big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param contextKey The context key + @return ApiGetSegmentMembershipForContextRequest +*/ +func (a *SegmentsApiService) GetSegmentMembershipForContext(ctx context.Context, projectKey string, environmentKey string, segmentKey string, contextKey string) ApiGetSegmentMembershipForContextRequest { + return ApiGetSegmentMembershipForContextRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + contextKey: contextKey, + } +} + +// Execute executes the request +// @return BigSegmentTarget +func (a *SegmentsApiService) GetSegmentMembershipForContextExecute(r ApiGetSegmentMembershipForContextRequest) (*BigSegmentTarget, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentTarget + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetSegmentMembershipForContext") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/contexts/{contextKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"contextKey"+"}", url.PathEscape(parameterToString(r.contextKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetSegmentMembershipForUserRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + userKey string +} + +func (r ApiGetSegmentMembershipForUserRequest) Execute() (*BigSegmentTarget, *http.Response, error) { + return r.ApiService.GetSegmentMembershipForUserExecute(r) +} + +/* +GetSegmentMembershipForUser Get big segment membership for user + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/get-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Get the membership status (included/excluded) for a given user in this big segment. This operation does not support standard segments. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @param userKey The user key + @return ApiGetSegmentMembershipForUserRequest +*/ +func (a *SegmentsApiService) GetSegmentMembershipForUser(ctx context.Context, projectKey string, environmentKey string, segmentKey string, userKey string) ApiGetSegmentMembershipForUserRequest { + return ApiGetSegmentMembershipForUserRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + userKey: userKey, + } +} + +// Execute executes the request +// @return BigSegmentTarget +func (a *SegmentsApiService) GetSegmentMembershipForUserExecute(r ApiGetSegmentMembershipForUserRequest) (*BigSegmentTarget, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BigSegmentTarget + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetSegmentMembershipForUser") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/users/{userKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetSegmentsRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + limit *int64 + offset *int64 + sort *string + filter *string +} + +// The number of segments to return. Defaults to 20. +func (r ApiGetSegmentsRequest) Limit(limit int64) ApiGetSegmentsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetSegmentsRequest) Offset(offset int64) ApiGetSegmentsRequest { + r.offset = &offset + return r +} + +// Accepts sorting order and fields. Fields can be comma separated. Possible fields are 'creationDate', 'name', 'lastModified'. Example: `sort=name` sort by names ascending or `sort=-name,creationDate` sort by names descending and creationDate ascending. +func (r ApiGetSegmentsRequest) Sort(sort string) ApiGetSegmentsRequest { + r.sort = &sort + return r +} + +// Accepts filter by `excludedKeys`, `external`, `includedKeys`, `query`, `tags`, `unbounded`. To learn more about the filter syntax, read the 'Filtering segments' section above. +func (r ApiGetSegmentsRequest) Filter(filter string) ApiGetSegmentsRequest { + r.filter = &filter + return r +} + +func (r ApiGetSegmentsRequest) Execute() (*UserSegments, *http.Response, error) { + return r.ApiService.GetSegmentsExecute(r) +} + +/* +GetSegments List segments + +Get a list of all segments in the given project. + +Segments can be rule-based, list-based, or synced. Big segments include larger list-based segments and synced segments. Some fields in the response only apply to big segments. + +### Filtering segments + +The `filter` parameter supports the following operators: `equals`, `anyOf`, and `exists`. + +You can also combine filters in the following ways: + +- Use a comma (`,`) as an AND operator +- Use a vertical bar (`|`) as an OR operator +- Use parentheses (`()`) to group filters + +#### Supported fields and operators + +You can only filter certain fields in segments when using the `filter` parameter. Additionally, you can only filter some fields with certain operators. + +When you search for segments, the `filter` parameter supports the following fields and operators: + +|
Field
|Description |Supported operators | +|---|---|---| +| `excludedKeys` | The segment keys of segments to exclude from the results. | `anyOf` | +| `external` | Whether the segment is a synced segment. | `exists` | +| `includedKeys` | The segment keys of segments to include in the results. | `anyOf` | +| `query` | A "fuzzy" search across segment key, name, and description. Supply a string or list of strings to the operator. | `equals` | +| `tags` | The segment tags. | `anyOf` | +| `unbounded` | Whether the segment is a standard segment (`false`) or a big segment (`true`). Standard segments include rule-based segments and smaller list-based segments. Big segments include larger list-based segments and synced segments. | `equals` | + +Here are a few examples: + +* The filter `?filter=tags anyOf ["enterprise", "beta"],query equals "toggle"` matches segments with "toggle" in their key, name, or description that also have "enterprise" or "beta" as a tag. +* The filter `?filter=excludedKeys anyOf ["segmentKey1", "segmentKey2"]` excludes the segments with those keys from the results. +* The filter `?filter=unbounded equals true` matches larger list-based segments and synced segments. + +The documented values for `filter` query parameters are prior to URL encoding. For example, the `[` in `?filter=tags anyOf ["enterprise", "beta"]` must be encoded to `%5B`. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetSegmentsRequest +*/ +func (a *SegmentsApiService) GetSegments(ctx context.Context, projectKey string, environmentKey string) ApiGetSegmentsRequest { + return ApiGetSegmentsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return UserSegments +func (a *SegmentsApiService) GetSegmentsExecute(r ApiGetSegmentsRequest) (*UserSegments, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserSegments + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.GetSegments") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExpiringTargetsForSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + patchSegmentExpiringTargetInputRep *PatchSegmentExpiringTargetInputRep +} + +func (r ApiPatchExpiringTargetsForSegmentRequest) PatchSegmentExpiringTargetInputRep(patchSegmentExpiringTargetInputRep PatchSegmentExpiringTargetInputRep) ApiPatchExpiringTargetsForSegmentRequest { + r.patchSegmentExpiringTargetInputRep = &patchSegmentExpiringTargetInputRep + return r +} + +func (r ApiPatchExpiringTargetsForSegmentRequest) Execute() (*ExpiringTargetPatchResponse, *http.Response, error) { + return r.ApiService.PatchExpiringTargetsForSegmentExecute(r) +} + +/* +PatchExpiringTargetsForSegment Update expiring targets for segment + + +Update expiring context targets for a segment. Updating a context target expiration uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +If the request is well-formed but any of its instructions failed to process, this operation returns status code `200`. In this case, the response `errors` array will be non-empty. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring context targets. + +
+Click to expand instructions for updating expiring context targets + +#### addExpiringTarget + +Schedules a date and time when LaunchDarkly will remove a context from segment targeting. The segment must already have the context as an individual target. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. +- `value`: The date when the context should expire from the segment targeting, in Unix milliseconds. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + "value": 1754092860000 + }] +} +``` + +#### updateExpiringTarget + +Updates the date and time when LaunchDarkly will remove a context from segment targeting. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. +- `value`: The new date when the context should expire from the segment targeting, in Unix milliseconds. +- `version`: (Optional) The version of the expiring target to update. If included, update will fail if version doesn't match current version of the expiring target. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + "value": 1754179260000 + }] +} +``` + +#### removeExpiringTarget + +Removes the scheduled expiration for the context in the segment. + +##### Parameters + +- `targetType`: The type of individual target for this context. Must be either `included` or `excluded`. +- `contextKey`: The context key. +- `contextKind`: The kind of context being targeted. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExpiringTarget", + "targetType": "included", + "contextKey": "user-key-123abc", + "contextKind": "user", + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchExpiringTargetsForSegmentRequest +*/ +func (a *SegmentsApiService) PatchExpiringTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchExpiringTargetsForSegmentRequest { + return ApiPatchExpiringTargetsForSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return ExpiringTargetPatchResponse +func (a *SegmentsApiService) PatchExpiringTargetsForSegmentExecute(r ApiPatchExpiringTargetsForSegmentRequest) (*ExpiringTargetPatchResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringTargetPatchResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.PatchExpiringTargetsForSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{segmentKey}/expiring-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchSegmentExpiringTargetInputRep == nil { + return localVarReturnValue, nil, reportError("patchSegmentExpiringTargetInputRep is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchSegmentExpiringTargetInputRep + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExpiringUserTargetsForSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + patchSegmentRequest *PatchSegmentRequest +} + +func (r ApiPatchExpiringUserTargetsForSegmentRequest) PatchSegmentRequest(patchSegmentRequest PatchSegmentRequest) ApiPatchExpiringUserTargetsForSegmentRequest { + r.patchSegmentRequest = &patchSegmentRequest + return r +} + +func (r ApiPatchExpiringUserTargetsForSegmentRequest) Execute() (*ExpiringUserTargetPatchResponse, *http.Response, error) { + return r.ApiService.PatchExpiringUserTargetsForSegmentExecute(r) +} + +/* +PatchExpiringUserTargetsForSegment Update expiring user targets for segment + + +> ### Contexts are now available +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Update expiring targets for segment](https://launchdarkly.com/docs/ld-docs/api/segments/patch-expiring-targets-for-segment) instead of this endpoint. To learn more, read [Contexts](https://launchdarkly.com/docs/home/observability/contexts). + +Update expiring user targets for a segment. Updating a user target expiration uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +If the request is well-formed but any of its instructions failed to process, this operation returns status code `200`. In this case, the response `errors` array will be non-empty. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Schedules a date and time when LaunchDarkly will remove a user from segment targeting. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. +- `value`: The date when the user should expire from the segment targeting, in Unix milliseconds. + +#### updateExpireUserTargetDate + +Updates the date and time when LaunchDarkly will remove a user from segment targeting. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. +- `value`: The new date when the user should expire from the segment targeting, in Unix milliseconds. +- `version`: The segment version. + +#### removeExpireUserTargetDate + +Removes the scheduled expiration for the user in the segment. + +##### Parameters + +- `targetType`: A segment's target type, must be either `included` or `excluded`. +- `userKey`: The user key. + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchExpiringUserTargetsForSegmentRequest +*/ +func (a *SegmentsApiService) PatchExpiringUserTargetsForSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchExpiringUserTargetsForSegmentRequest { + return ApiPatchExpiringUserTargetsForSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetPatchResponse +func (a *SegmentsApiService) PatchExpiringUserTargetsForSegmentExecute(r ApiPatchExpiringUserTargetsForSegmentRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetPatchResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.PatchExpiringUserTargetsForSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{segmentKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchSegmentRequest == nil { + return localVarReturnValue, nil, reportError("patchSegmentRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchSegmentRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + patchWithComment *PatchWithComment +} + +func (r ApiPatchSegmentRequest) PatchWithComment(patchWithComment PatchWithComment) ApiPatchSegmentRequest { + r.patchWithComment = &patchWithComment + return r +} + +func (r ApiPatchSegmentRequest) Execute() (*UserSegment, *http.Response, error) { + return r.ApiService.PatchSegmentExecute(r) +} + +/* +PatchSegment Patch segment + +Update a segment. The request body must be a valid semantic patch, JSON patch, or JSON merge patch. To learn more the different formats, read [Updates](https://launchdarkly.com/docs/api#updates). + +### Using semantic patches on a segment + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +The body of a semantic patch request for updating segments requires an `environmentKey` in addition to `instructions` and an optional `comment`. The body of the request takes the following properties: + +* `comment` (string): (Optional) A description of the update. +* `environmentKey` (string): (Required) The key of the LaunchDarkly environment. +* `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the action requires parameters, you must include those parameters as additional fields in the object. + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating segments. + +
+Click to expand instructions for updating segment details and settings + +#### addTags + +Adds tags to the segment. + +##### Parameters + +- `values`: A list of tags to add. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addTags", + "values": ["tag1", "tag2"] + }] +} +``` + +#### removeTags + +Removes tags from the segment. + +##### Parameters + +- `values`: A list of tags to remove. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeTags", + "values": ["tag1", "tag2"] + }] +} +``` + +#### updateName + +Updates the name of the segment. + +##### Parameters + +- `value`: Name of the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Updated segment name" + }] +} +``` + +
+ +
+Click to expand instructions for updating segment individual targets + +#### addExcludedTargets + +Adds context keys to the individual context targets excluded from the segment for the specified `contextKind`. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `contextKind`: The context kind the targets should be added to. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExcludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addExcludedUsers + +Adds user keys to the individual user targets excluded from the segment. Returns an error if this causes the same user key to be both included and excluded. If you are working with contexts, use `addExcludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addExcludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### addIncludedTargets + +Adds context keys to the individual context targets included in the segment for the specified `contextKind`. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `contextKind`: The context kind the targets should be added to. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addIncludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addIncludedUsers + +Adds user keys to the individual user targets included in the segment. Returns an error if this causes the same user key to be both included and excluded. If you are working with contexts, use `addIncludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addIncludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### removeExcludedTargets + +Removes context keys from the individual context targets excluded from the segment for the specified `contextKind`. + +##### Parameters + +- `contextKind`: The context kind the targets should be removed from. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExcludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeExcludedUsers + +Removes user keys from the individual user targets excluded from the segment. If you are working with contexts, use `removeExcludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeExcludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +#### removeIncludedTargets + +Removes context keys from the individual context targets included in the segment for the specified `contextKind`. + +##### Parameters + +- `contextKind`: The context kind the targets should be removed from. +- `values`: List of keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeIncludedTargets", + "contextKind": "org", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeIncludedUsers + +Removes user keys from the individual user targets included in the segment. If you are working with contexts, use `removeIncludedTargets` instead of this instruction. + +##### Parameters + +- `values`: List of user keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeIncludedUsers", + "values": [ "user-key-123abc", "user-key-456def" ] + }] +} +``` + +
+ +
+Click to expand instructions for updating segment targeting rules + +#### addClauses + +Adds the given clauses to the rule indicated by `ruleId`. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `ruleId`: ID of a rule in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addClauses", + "clauses": [ + { + "attribute": "email", + "negate": false, + "op": "contains", + "values": ["value1"] + } + ], + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + }] +} +``` + +#### addRule + +Adds a new targeting rule to the segment. The rule may contain `clauses`. + +##### Parameters + +- `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. +- `description`: A description of the rule. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addRule", + "clauses": [ + { + "attribute": "email", + "op": "contains", + "negate": false, + "values": ["@launchdarkly.com"] + } + ], + "description": "Targeting rule for LaunchDarkly employees", + }] +} +``` + +#### addValuesToClause + +Adds `values` to the values of the clause that `ruleId` and `clauseId` indicate. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addValuesToClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### removeClauses + +Removes the clauses specified by `clauseIds` from the rule indicated by `ruleId`. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseIds`: Array of IDs of clauses in the rule. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeClauses", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseIds": ["10a58772-3121-400f-846b-b8a04e8944ed", "36a461dc-235e-4b08-97b9-73ce9365873e"] + }] +} +``` + +#### removeRule + +Removes the targeting rule specified by `ruleId`. Does nothing if the rule does not exist. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeRule", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### removeValuesFromClause + +Removes `values` from the values of the clause indicated by `ruleId` and `clauseId`. Does not update the context kind, attribute, or operator. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `values`: Array of strings, case sensitive. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeValuesFromClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed", + "values": ["beta_testers"] + }] +} +``` + +#### reorderRules + +Rearranges the rules to match the order given in `ruleIds`. Returns an error if `ruleIds` does not match the current set of rules in the segment. + +##### Parameters + +- `ruleIds`: Array of IDs of all targeting rules in the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "reorderRules", + "ruleIds": ["a902ef4a-2faf-4eaf-88e1-ecc356708a29", "63c238d1-835d-435e-8f21-c8d5e40b2a3d"] + }] +} +``` + +#### updateClause + +Replaces the clause indicated by `ruleId` and `clauseId` with `clause`. + +##### Parameters + +- `ruleId`: ID of a rule in the segment. +- `clauseId`: ID of a clause in that rule. +- `clause`: New `clause` object, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, if not provided, defaults to `user`. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateClause", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "clauseId": "10c7462a-2062-45ba-a8bb-dfb3de0f8af5", + "clause": { + "contextKind": "user", + "attribute": "country", + "op": "in", + "negate": false, + "values": ["Mexico", "Canada"] + } + }] +} +``` + +#### updateRuleDescription + +Updates the description of the segment targeting rule. + +##### Parameters + +- `description`: The new human-readable description for this rule. +- `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the segment. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateRuleDescription", + "description": "New rule description", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + +#### updateRuleRolloutAndContextKind + +For a rule that includes a percentage of targets, updates the percentage and the context kind of the targets to include. + +##### Parameters + +- `ruleId`: The ID of a targeting rule in the segment that includes a percentage of targets. +- `weight`: The weight, in thousandths of a percent (0-100000). +- `contextKind`: The context kind. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "reorderRules", + "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29", + "weight": "20000", + "contextKind": "device" + }] +} +``` + +
+ +
+Click to expand instructions for working with Big Segments + +A "big segment" is a segment that is either a synced segment, or a list-based segment with more than 15,000 entries that includes only one targeted context kind. LaunchDarkly uses different implementations for different types of segments so that all of your segments have good performance. + +The following semantic patch instructions apply only to these [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments). + +#### addBigSegmentExcludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Adds context keys to the context targets excluded from the segment. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addBigSegmentExcludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### addBigSegmentIncludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Adds context keys to the context targets included in the segment. Returns an error if this causes the same context key to be both included and excluded. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addBigSegmentIncludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### processBigSegmentImport + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Processes a segment import. + +##### Parameters + +- `importId`: The ID of the import. The import ID is returned in the `Location` header as part of the [Create big segment import](https://launchdarkly.com/docs/api/segments/create-big-segment-import) request. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "processBigSegmentImport", + "importId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" + }] +} +``` + + +#### removeBigSegmentExcludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Removes context keys from the context targets excluded from the segment. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeBigSegmentExcludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +#### removeBigSegmentIncludedTargets + +For use with [larger list-based segments](https://launchdarkly.com/docs/home/flags/segments-create#create-larger-list-based-segments) ONLY. Removes context keys from the context targets included in the segment. + +##### Parameters + +- `values`: List of context keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeBigSegmentIncludedTargets", + "values": [ "org-key-123abc", "org-key-456def" ] + }] +} +``` + +
+ +### Using JSON patches on a segment + +If you do not include the header described above, you can use a [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) or [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) representation of the desired changes. + +For example, to update the description for a segment with a JSON patch, use the following request body: + +```json +{ + "patch": [ + { + "op": "replace", + "path": "/description", + "value": "new description" + } + ] +} +``` + +To update fields in the segment that are arrays, set the `path` to the name of the field and then append `/`. Use `/0` to add the new entry to the beginning of the array. Use `/-` to add the new entry to the end of the array. + +For example, to add a rule to a segment, use the following request body: + +```json +{ + "patch":[ + { + "op": "add", + "path": "/rules/0", + "value": { + "clauses": [{ "contextKind": "user", "attribute": "email", "op": "endsWith", "values": [".edu"], "negate": false }] + } + } + ] +} +``` + +To add or remove targets from segments, we recommend using semantic patch. Semantic patch for segments includes specific instructions for adding and removing both included and excluded targets. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiPatchSegmentRequest +*/ +func (a *SegmentsApiService) PatchSegment(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiPatchSegmentRequest { + return ApiPatchSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +// @return UserSegment +func (a *SegmentsApiService) PatchSegmentExecute(r ApiPatchSegmentRequest) (*UserSegment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserSegment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.PatchSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchWithComment == nil { + return localVarReturnValue, nil, reportError("patchWithComment is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchWithComment + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostSegmentRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentBody *SegmentBody +} + +func (r ApiPostSegmentRequest) SegmentBody(segmentBody SegmentBody) ApiPostSegmentRequest { + r.segmentBody = &segmentBody + return r +} + +func (r ApiPostSegmentRequest) Execute() (*UserSegment, *http.Response, error) { + return r.ApiService.PostSegmentExecute(r) +} + +/* +PostSegment Create segment + +Create a new segment. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiPostSegmentRequest +*/ +func (a *SegmentsApiService) PostSegment(ctx context.Context, projectKey string, environmentKey string) ApiPostSegmentRequest { + return ApiPostSegmentRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return UserSegment +func (a *SegmentsApiService) PostSegmentExecute(r ApiPostSegmentRequest) (*UserSegment, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserSegment + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.PostSegment") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.segmentBody == nil { + return localVarReturnValue, nil, reportError("segmentBody is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.segmentBody + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiUpdateBigSegmentContextTargetsRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + segmentUserState *SegmentUserState +} + +func (r ApiUpdateBigSegmentContextTargetsRequest) SegmentUserState(segmentUserState SegmentUserState) ApiUpdateBigSegmentContextTargetsRequest { + r.segmentUserState = &segmentUserState + return r +} + +func (r ApiUpdateBigSegmentContextTargetsRequest) Execute() (*http.Response, error) { + return r.ApiService.UpdateBigSegmentContextTargetsExecute(r) +} + +/* +UpdateBigSegmentContextTargets Update context targets on a big segment + +Update context targets included or excluded in a big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiUpdateBigSegmentContextTargetsRequest +*/ +func (a *SegmentsApiService) UpdateBigSegmentContextTargets(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiUpdateBigSegmentContextTargetsRequest { + return ApiUpdateBigSegmentContextTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +func (a *SegmentsApiService) UpdateBigSegmentContextTargetsExecute(r ApiUpdateBigSegmentContextTargetsRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.UpdateBigSegmentContextTargets") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/contexts" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.segmentUserState == nil { + return nil, reportError("segmentUserState is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.segmentUserState + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiUpdateBigSegmentTargetsRequest struct { + ctx context.Context + ApiService SegmentsApi + projectKey string + environmentKey string + segmentKey string + segmentUserState *SegmentUserState +} + +func (r ApiUpdateBigSegmentTargetsRequest) SegmentUserState(segmentUserState SegmentUserState) ApiUpdateBigSegmentTargetsRequest { + r.segmentUserState = &segmentUserState + return r +} + +func (r ApiUpdateBigSegmentTargetsRequest) Execute() (*http.Response, error) { + return r.ApiService.UpdateBigSegmentTargetsExecute(r) +} + +/* +UpdateBigSegmentTargets Update user context targets on a big segment + +Update user context targets included or excluded in a big segment. Big segments include larger list-based segments and synced segments. This operation does not support standard segments. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param segmentKey The segment key + @return ApiUpdateBigSegmentTargetsRequest +*/ +func (a *SegmentsApiService) UpdateBigSegmentTargets(ctx context.Context, projectKey string, environmentKey string, segmentKey string) ApiUpdateBigSegmentTargetsRequest { + return ApiUpdateBigSegmentTargetsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + segmentKey: segmentKey, + } +} + +// Execute executes the request +func (a *SegmentsApiService) UpdateBigSegmentTargetsExecute(r ApiUpdateBigSegmentTargetsRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SegmentsApiService.UpdateBigSegmentTargets") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/segments/{projectKey}/{environmentKey}/{segmentKey}/users" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"segmentKey"+"}", url.PathEscape(parameterToString(r.segmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.segmentUserState == nil { + return nil, reportError("segmentUserState is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.segmentUserState + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_tags.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_tags.go new file mode 100644 index 00000000..26d3fa17 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_tags.go @@ -0,0 +1,272 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "reflect" +) + + +type TagsApi interface { + + /* + GetTags List tags + + Get a list of tags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTagsRequest + */ + GetTags(ctx context.Context) ApiGetTagsRequest + + // GetTagsExecute executes the request + // @return TagsCollection + GetTagsExecute(r ApiGetTagsRequest) (*TagsCollection, *http.Response, error) +} + +// TagsApiService TagsApi service +type TagsApiService service + +type ApiGetTagsRequest struct { + ctx context.Context + ApiService TagsApi + kind *[]string + pre *string + archived *bool + limit *int32 + offset *int32 + asOf *string +} + +// Fetch tags associated with the specified resource type. Options are `flag`, `project`, `environment`, `segment`, `metric`. Returns all types by default. +func (r ApiGetTagsRequest) Kind(kind []string) ApiGetTagsRequest { + r.kind = &kind + return r +} + +// Return tags with the specified prefix +func (r ApiGetTagsRequest) Pre(pre string) ApiGetTagsRequest { + r.pre = &pre + return r +} + +// Whether or not to return archived flags +func (r ApiGetTagsRequest) Archived(archived bool) ApiGetTagsRequest { + r.archived = &archived + return r +} + +// The number of tags to return. Maximum is 1000. +func (r ApiGetTagsRequest) Limit(limit int32) ApiGetTagsRequest { + r.limit = &limit + return r +} + +// The index of the first tag to return. Default is 0. +func (r ApiGetTagsRequest) Offset(offset int32) ApiGetTagsRequest { + r.offset = &offset + return r +} + +// The time to retrieve tags as of. Default is the current time. +func (r ApiGetTagsRequest) AsOf(asOf string) ApiGetTagsRequest { + r.asOf = &asOf + return r +} + +func (r ApiGetTagsRequest) Execute() (*TagsCollection, *http.Response, error) { + return r.ApiService.GetTagsExecute(r) +} + +/* +GetTags List tags + +Get a list of tags. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTagsRequest +*/ +func (a *TagsApiService) GetTags(ctx context.Context) ApiGetTagsRequest { + return ApiGetTagsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return TagsCollection +func (a *TagsApiService) GetTagsExecute(r ApiGetTagsRequest) (*TagsCollection, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TagsCollection + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TagsApiService.GetTags") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/tags" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.kind != nil { + t := *r.kind + if reflect.TypeOf(t).Kind() == reflect.Slice { + s := reflect.ValueOf(t) + for i := 0; i < s.Len(); i++ { + localVarQueryParams.Add("kind", parameterToString(s.Index(i), "multi")) + } + } else { + localVarQueryParams.Add("kind", parameterToString(t, "multi")) + } + } + if r.pre != nil { + localVarQueryParams.Add("pre", parameterToString(*r.pre, "")) + } + if r.archived != nil { + localVarQueryParams.Add("archived", parameterToString(*r.archived, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.asOf != nil { + localVarQueryParams.Add("asOf", parameterToString(*r.asOf, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_teams.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_teams.go new file mode 100644 index 00000000..0cb10704 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_teams.go @@ -0,0 +1,2345 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "os" +) + + +type TeamsApi interface { + + /* + DeleteTeam Delete team + + Delete a team by key. To learn more, read [Deleting teams](https://launchdarkly.com/docs/home/account/delete-teams). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiDeleteTeamRequest + */ + DeleteTeam(ctx context.Context, teamKey string) ApiDeleteTeamRequest + + // DeleteTeamExecute executes the request + DeleteTeamExecute(r ApiDeleteTeamRequest) (*http.Response, error) + + /* + GetTeam Get team + + Fetch a team by key. + +### Expanding the teams response +LaunchDarkly supports several fields for expanding the "Get team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `roleAttributes` includes a list of the role attributes that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key. + @return ApiGetTeamRequest + */ + GetTeam(ctx context.Context, teamKey string) ApiGetTeamRequest + + // GetTeamExecute executes the request + // @return Team + GetTeamExecute(r ApiGetTeamRequest) (*Team, *http.Response, error) + + /* + GetTeamMaintainers Get team maintainers + + Fetch the maintainers that have been assigned to the team. To learn more, read [Managing team maintainers](https://launchdarkly.com/docs/home/account/team-maintainers). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiGetTeamMaintainersRequest + */ + GetTeamMaintainers(ctx context.Context, teamKey string) ApiGetTeamMaintainersRequest + + // GetTeamMaintainersExecute executes the request + // @return TeamMaintainers + GetTeamMaintainersExecute(r ApiGetTeamMaintainersRequest) (*TeamMaintainers, *http.Response, error) + + /* + GetTeamRoles Get team custom roles + + Fetch the custom roles that have been assigned to the team. To learn more, read [Managing team permissions](https://launchdarkly.com/docs/home/account/team-permissions). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiGetTeamRolesRequest + */ + GetTeamRoles(ctx context.Context, teamKey string) ApiGetTeamRolesRequest + + // GetTeamRolesExecute executes the request + // @return TeamCustomRoles + GetTeamRolesExecute(r ApiGetTeamRolesRequest) (*TeamCustomRoles, *http.Response, error) + + /* + GetTeams List teams + + Return a list of teams. + +By default, this returns the first 20 teams. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering teams + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the teams' names and keys. It is not case-sensitive. + - A request with `query:abc` returns teams with the string `abc` in their name or key. +- `nomembers` is a boolean that filters the list of teams who have 0 members + - A request with `nomembers:true` returns teams that have 0 members + - A request with `nomembers:false` returns teams that have 1 or more members + +### Expanding the teams response +LaunchDarkly supports expanding several fields in the "List teams" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `roleAttributes` includes a list of the role attributes that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,maintainers` includes the `members` and `maintainers` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTeamsRequest + */ + GetTeams(ctx context.Context) ApiGetTeamsRequest + + // GetTeamsExecute executes the request + // @return Teams + GetTeamsExecute(r ApiGetTeamsRequest) (*Teams, *http.Response, error) + + /* + PatchTeam Update team + + Perform a partial update to a team. Updating a team uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating teams. Several of the instructions require one or more member IDs as parameters. The member ID is returned as part of the [List account members](https://launchdarkly.com/docs/ld-docs/api/account-members/get-members) response. It is the `_id` field of each element in the `items` array. + + +
+Click to expand instructions for updating teams + +#### addCustomRoles + +Adds custom roles to the team. Team members will have these custom roles granted to them. + +##### Parameters + +- `values`: List of custom role keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addCustomRoles", + "values": [ "example-custom-role" ] + }] +} +``` + +#### removeCustomRoles + +Removes custom roles from the team. The app will no longer grant these custom roles to the team members. + +##### Parameters + +- `values`: List of custom role keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeCustomRoles", + "values": [ "example-custom-role" ] + }] +} +``` + +#### addRoleAttribute + +Adds a role attribute to a team. Team members will have these role attribute values scoped for all custom roles granted to them. + +##### Parameters + +- `key`: The role attribute key to add. +- `values`: List of role attribute values for that key. + +Here's an example: + +```json +{ + "instructions": [ + { + "kind": "addRoleAttribute", + "key": "testAttribute", + "values": ["someNewValue", "someOtherNewValue"] + } + ] +} +``` +#### updateRoleAttribute + +Updates a role attribute on the team. Any existing values for the given key will be replaced with the new values. Team members will have these role attribute values scoped for all custom roles granted to them. + +##### Parameters + +- `key`: The role attribute key to update. +- `values`: List of role attribute values for that key. + +Here's an example: +```json +{ + "instructions": [ + { + "kind": "updateRoleAttribute", + "key": "testAttribute", + "values": ["someNewValue", "someOtherNewValue"] + } + ] +} +``` +#### removeRoleAttribute + +Removes a role attribute from the team. + +##### Parameters + +- `key`: The role attribute key to remove. + +Here's an example: +```json +{ + "instructions": [ + { + "kind": "removeRoleAttribute", + "key": "testAttribute" + } + ] +} +``` + +#### addMembers + +Adds members to the team. + +##### Parameters + +- `values`: List of member IDs to add. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### removeMembers + +Removes members from the team. + +##### Parameters + +- `values`: List of member IDs to remove. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### replaceMembers + +Replaces the existing members of the team with the new members. + +##### Parameters + +- `values`: List of member IDs of the new members. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### addPermissionGrants + +Adds permission grants to members for the team. For example, a permission grant could allow a member to act as a team maintainer. A permission grant may have either an `actionSet` or a list of `actions` but not both at the same time. The members do not have to be team members to have a permission grant for the team. + +##### Parameters + +- `actionSet`: Name of the action set. +- `actions`: List of actions. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addPermissionGrants", + "actions": [ "updateTeamName", "updateTeamDescription" ], + "memberIDs": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### removePermissionGrants + +Removes permission grants from members for the team. A permission grant may have either an `actionSet` or a list of `actions` but not both at the same time. The `actionSet` and `actions` must match an existing permission grant. + +##### Parameters + +- `actionSet`: Name of the action set. +- `actions`: List of actions. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removePermissionGrants", + "actions": [ "updateTeamName", "updateTeamDescription" ], + "memberIDs": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### updateDescription + +Updates the description of the team. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "value": "Updated team description" + }] +} +``` + +#### updateName + +Updates the name of the team. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Updated team name" + }] +} +``` + +
+ +### Expanding the teams response +LaunchDarkly supports four fields for expanding the "Update team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiPatchTeamRequest + */ + PatchTeam(ctx context.Context, teamKey string) ApiPatchTeamRequest + + // PatchTeamExecute executes the request + // @return Team + PatchTeamExecute(r ApiPatchTeamRequest) (*Team, *http.Response, error) + + /* + PostTeam Create team + + Create a team. To learn more, read [Creating a team](https://launchdarkly.com/docs/home/account/create-teams). + +### Expanding the teams response +LaunchDarkly supports four fields for expanding the "Create team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostTeamRequest + */ + PostTeam(ctx context.Context) ApiPostTeamRequest + + // PostTeamExecute executes the request + // @return Team + PostTeamExecute(r ApiPostTeamRequest) (*Team, *http.Response, error) + + /* + PostTeamMembers Add multiple members to team + + Add multiple members to an existing team by uploading a CSV file of member email addresses. Your CSV file must include email addresses in the first column. You can include data in additional columns, but LaunchDarkly ignores all data outside the first column. Headers are optional. To learn more, read [Manage team members](https://launchdarkly.com/docs/home/account/manage-teams#manage-team-members). + +**Members are only added on a `201` response.** A `207` indicates the CSV file contains a combination of valid and invalid entries. A `207` results in no members being added to the team. + +On a `207` response, if an entry contains bad input, the `message` field contains the row number as well as the reason for the error. The `message` field is omitted if the entry is valid. + +Example `207` response: +```json +{ + "items": [ + { + "status": "success", + "value": "new-team-member@acme.com" + }, + { + "message": "Line 2: empty row", + "status": "error", + "value": "" + }, + { + "message": "Line 3: email already exists in the specified team", + "status": "error", + "value": "existing-team-member@acme.com" + }, + { + "message": "Line 4: invalid email formatting", + "status": "error", + "value": "invalid email format" + } + ] +} +``` + +Message | Resolution +--- | --- +Empty row | This line is blank. Add an email address and try again. +Duplicate entry | This email address appears in the file twice. Remove the email from the file and try again. +Email already exists in the specified team | This member is already on your team. Remove the email from the file and try again. +Invalid formatting | This email address is not formatted correctly. Fix the formatting and try again. +Email does not belong to a LaunchDarkly member | The email address doesn't belong to a LaunchDarkly account member. Invite them to LaunchDarkly, then re-add them to the team. + +On a `400` response, the `message` field may contain errors specific to this endpoint. + +Example `400` response: +```json +{ + "code": "invalid_request", + "message": "Unable to process file" +} +``` + +Message | Resolution +--- | --- +Unable to process file | LaunchDarkly could not process the file for an unspecified reason. Review your file for errors and try again. +File exceeds 25mb | Break up your file into multiple files of less than 25mbs each. +All emails have invalid formatting | None of the email addresses in the file are in the correct format. Fix the formatting and try again. +All emails belong to existing team members | All listed members are already on this team. Populate the file with member emails that do not belong to the team and try again. +File is empty | The CSV file does not contain any email addresses. Populate the file and try again. +No emails belong to members of your LaunchDarkly organization | None of the email addresses belong to members of your LaunchDarkly account. Invite these members to LaunchDarkly, then re-add them to the team. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiPostTeamMembersRequest + */ + PostTeamMembers(ctx context.Context, teamKey string) ApiPostTeamMembersRequest + + // PostTeamMembersExecute executes the request + // @return TeamImportsRep + PostTeamMembersExecute(r ApiPostTeamMembersRequest) (*TeamImportsRep, *http.Response, error) +} + +// TeamsApiService TeamsApi service +type TeamsApiService service + +type ApiDeleteTeamRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string +} + +func (r ApiDeleteTeamRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteTeamExecute(r) +} + +/* +DeleteTeam Delete team + +Delete a team by key. To learn more, read [Deleting teams](https://launchdarkly.com/docs/home/account/delete-teams). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiDeleteTeamRequest +*/ +func (a *TeamsApiService) DeleteTeam(ctx context.Context, teamKey string) ApiDeleteTeamRequest { + return ApiDeleteTeamRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +func (a *TeamsApiService) DeleteTeamExecute(r ApiDeleteTeamRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.DeleteTeam") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetTeamRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string + expand *string +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetTeamRequest) Expand(expand string) ApiGetTeamRequest { + r.expand = &expand + return r +} + +func (r ApiGetTeamRequest) Execute() (*Team, *http.Response, error) { + return r.ApiService.GetTeamExecute(r) +} + +/* +GetTeam Get team + +Fetch a team by key. + +### Expanding the teams response +LaunchDarkly supports several fields for expanding the "Get team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `roleAttributes` includes a list of the role attributes that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key. + @return ApiGetTeamRequest +*/ +func (a *TeamsApiService) GetTeam(ctx context.Context, teamKey string) ApiGetTeamRequest { + return ApiGetTeamRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +// @return Team +func (a *TeamsApiService) GetTeamExecute(r ApiGetTeamRequest) (*Team, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Team + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.GetTeam") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetTeamMaintainersRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string + limit *int64 + offset *int64 +} + +// The number of maintainers to return in the response. Defaults to 20. +func (r ApiGetTeamMaintainersRequest) Limit(limit int64) ApiGetTeamMaintainersRequest { + r.limit = &limit + return r +} + +// Where to start in the list. This is for use with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetTeamMaintainersRequest) Offset(offset int64) ApiGetTeamMaintainersRequest { + r.offset = &offset + return r +} + +func (r ApiGetTeamMaintainersRequest) Execute() (*TeamMaintainers, *http.Response, error) { + return r.ApiService.GetTeamMaintainersExecute(r) +} + +/* +GetTeamMaintainers Get team maintainers + +Fetch the maintainers that have been assigned to the team. To learn more, read [Managing team maintainers](https://launchdarkly.com/docs/home/account/team-maintainers). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiGetTeamMaintainersRequest +*/ +func (a *TeamsApiService) GetTeamMaintainers(ctx context.Context, teamKey string) ApiGetTeamMaintainersRequest { + return ApiGetTeamMaintainersRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +// @return TeamMaintainers +func (a *TeamsApiService) GetTeamMaintainersExecute(r ApiGetTeamMaintainersRequest) (*TeamMaintainers, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TeamMaintainers + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.GetTeamMaintainers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}/maintainers" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetTeamRolesRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string + limit *int64 + offset *int64 +} + +// The number of roles to return in the response. Defaults to 20. +func (r ApiGetTeamRolesRequest) Limit(limit int64) ApiGetTeamRolesRequest { + r.limit = &limit + return r +} + +// Where to start in the list. This is for use with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetTeamRolesRequest) Offset(offset int64) ApiGetTeamRolesRequest { + r.offset = &offset + return r +} + +func (r ApiGetTeamRolesRequest) Execute() (*TeamCustomRoles, *http.Response, error) { + return r.ApiService.GetTeamRolesExecute(r) +} + +/* +GetTeamRoles Get team custom roles + +Fetch the custom roles that have been assigned to the team. To learn more, read [Managing team permissions](https://launchdarkly.com/docs/home/account/team-permissions). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiGetTeamRolesRequest +*/ +func (a *TeamsApiService) GetTeamRoles(ctx context.Context, teamKey string) ApiGetTeamRolesRequest { + return ApiGetTeamRolesRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +// @return TeamCustomRoles +func (a *TeamsApiService) GetTeamRolesExecute(r ApiGetTeamRolesRequest) (*TeamCustomRoles, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TeamCustomRoles + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.GetTeamRoles") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}/roles" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetTeamsRequest struct { + ctx context.Context + ApiService TeamsApi + limit *int64 + offset *int64 + filter *string + expand *string +} + +// The number of teams to return in the response. Defaults to 20. +func (r ApiGetTeamsRequest) Limit(limit int64) ApiGetTeamsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Use this with pagination. For example, an offset of 10 skips the first ten items and returns the next `limit` items. +func (r ApiGetTeamsRequest) Offset(offset int64) ApiGetTeamsRequest { + r.offset = &offset + return r +} + +// A comma-separated list of filters. Each filter is constructed as `field:value`. +func (r ApiGetTeamsRequest) Filter(filter string) ApiGetTeamsRequest { + r.filter = &filter + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. +func (r ApiGetTeamsRequest) Expand(expand string) ApiGetTeamsRequest { + r.expand = &expand + return r +} + +func (r ApiGetTeamsRequest) Execute() (*Teams, *http.Response, error) { + return r.ApiService.GetTeamsExecute(r) +} + +/* +GetTeams List teams + +Return a list of teams. + +By default, this returns the first 20 teams. Page through this list with the `limit` parameter and by following the `first`, `prev`, `next`, and `last` links in the `_links` field that returns. If those links do not appear, the pages they refer to don't exist. For example, the `first` and `prev` links will be missing from the response on the first page, because there is no previous page and you cannot return to the first page when you are already on the first page. + +### Filtering teams + +LaunchDarkly supports the following fields for filters: + +- `query` is a string that matches against the teams' names and keys. It is not case-sensitive. + - A request with `query:abc` returns teams with the string `abc` in their name or key. +- `nomembers` is a boolean that filters the list of teams who have 0 members + - A request with `nomembers:true` returns teams that have 0 members + - A request with `nomembers:false` returns teams that have 1 or more members + +### Expanding the teams response +LaunchDarkly supports expanding several fields in the "List teams" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `roleAttributes` includes a list of the role attributes that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,maintainers` includes the `members` and `maintainers` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTeamsRequest +*/ +func (a *TeamsApiService) GetTeams(ctx context.Context) ApiGetTeamsRequest { + return ApiGetTeamsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Teams +func (a *TeamsApiService) GetTeamsExecute(r ApiGetTeamsRequest) (*Teams, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Teams + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.GetTeams") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchTeamRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string + teamPatchInput *TeamPatchInput + expand *string +} + +func (r ApiPatchTeamRequest) TeamPatchInput(teamPatchInput TeamPatchInput) ApiPatchTeamRequest { + r.teamPatchInput = &teamPatchInput + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. Supported fields are explained above. +func (r ApiPatchTeamRequest) Expand(expand string) ApiPatchTeamRequest { + r.expand = &expand + return r +} + +func (r ApiPatchTeamRequest) Execute() (*Team, *http.Response, error) { + return r.ApiService.PatchTeamExecute(r) +} + +/* +PatchTeam Update team + +Perform a partial update to a team. Updating a team uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating teams. Several of the instructions require one or more member IDs as parameters. The member ID is returned as part of the [List account members](https://launchdarkly.com/docs/ld-docs/api/account-members/get-members) response. It is the `_id` field of each element in the `items` array. + + +
+Click to expand instructions for updating teams + +#### addCustomRoles + +Adds custom roles to the team. Team members will have these custom roles granted to them. + +##### Parameters + +- `values`: List of custom role keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addCustomRoles", + "values": [ "example-custom-role" ] + }] +} +``` + +#### removeCustomRoles + +Removes custom roles from the team. The app will no longer grant these custom roles to the team members. + +##### Parameters + +- `values`: List of custom role keys. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeCustomRoles", + "values": [ "example-custom-role" ] + }] +} +``` + +#### addRoleAttribute + +Adds a role attribute to a team. Team members will have these role attribute values scoped for all custom roles granted to them. + +##### Parameters + +- `key`: The role attribute key to add. +- `values`: List of role attribute values for that key. + +Here's an example: + +```json +{ + "instructions": [ + { + "kind": "addRoleAttribute", + "key": "testAttribute", + "values": ["someNewValue", "someOtherNewValue"] + } + ] +} +``` +#### updateRoleAttribute + +Updates a role attribute on the team. Any existing values for the given key will be replaced with the new values. Team members will have these role attribute values scoped for all custom roles granted to them. + +##### Parameters + +- `key`: The role attribute key to update. +- `values`: List of role attribute values for that key. + +Here's an example: +```json +{ + "instructions": [ + { + "kind": "updateRoleAttribute", + "key": "testAttribute", + "values": ["someNewValue", "someOtherNewValue"] + } + ] +} +``` +#### removeRoleAttribute + +Removes a role attribute from the team. + +##### Parameters + +- `key`: The role attribute key to remove. + +Here's an example: +```json +{ + "instructions": [ + { + "kind": "removeRoleAttribute", + "key": "testAttribute" + } + ] +} +``` + +#### addMembers + +Adds members to the team. + +##### Parameters + +- `values`: List of member IDs to add. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### removeMembers + +Removes members from the team. + +##### Parameters + +- `values`: List of member IDs to remove. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removeMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### replaceMembers + +Replaces the existing members of the team with the new members. + +##### Parameters + +- `values`: List of member IDs of the new members. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "replaceMembers", + "values": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### addPermissionGrants + +Adds permission grants to members for the team. For example, a permission grant could allow a member to act as a team maintainer. A permission grant may have either an `actionSet` or a list of `actions` but not both at the same time. The members do not have to be team members to have a permission grant for the team. + +##### Parameters + +- `actionSet`: Name of the action set. +- `actions`: List of actions. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addPermissionGrants", + "actions": [ "updateTeamName", "updateTeamDescription" ], + "memberIDs": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### removePermissionGrants + +Removes permission grants from members for the team. A permission grant may have either an `actionSet` or a list of `actions` but not both at the same time. The `actionSet` and `actions` must match an existing permission grant. + +##### Parameters + +- `actionSet`: Name of the action set. +- `actions`: List of actions. +- `memberIDs`: List of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "removePermissionGrants", + "actions": [ "updateTeamName", "updateTeamDescription" ], + "memberIDs": [ "1234a56b7c89d012345e678f", "507f1f77bcf86cd799439011" ] + }] +} +``` + +#### updateDescription + +Updates the description of the team. + +##### Parameters + +- `value`: The new description. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateDescription", + "value": "Updated team description" + }] +} +``` + +#### updateName + +Updates the name of the team. + +##### Parameters + +- `value`: The new name. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "updateName", + "value": "Updated team name" + }] +} +``` + +
+ +### Expanding the teams response +LaunchDarkly supports four fields for expanding the "Update team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiPatchTeamRequest +*/ +func (a *TeamsApiService) PatchTeam(ctx context.Context, teamKey string) ApiPatchTeamRequest { + return ApiPatchTeamRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +// @return Team +func (a *TeamsApiService) PatchTeamExecute(r ApiPatchTeamRequest) (*Team, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Team + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.PatchTeam") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.teamPatchInput == nil { + return localVarReturnValue, nil, reportError("teamPatchInput is required and must be specified") + } + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.teamPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostTeamRequest struct { + ctx context.Context + ApiService TeamsApi + teamPostInput *TeamPostInput + expand *string +} + +func (r ApiPostTeamRequest) TeamPostInput(teamPostInput TeamPostInput) ApiPostTeamRequest { + r.teamPostInput = &teamPostInput + return r +} + +// A comma-separated list of properties that can reveal additional information in the response. Supported fields are explained above. +func (r ApiPostTeamRequest) Expand(expand string) ApiPostTeamRequest { + r.expand = &expand + return r +} + +func (r ApiPostTeamRequest) Execute() (*Team, *http.Response, error) { + return r.ApiService.PostTeamExecute(r) +} + +/* +PostTeam Create team + +Create a team. To learn more, read [Creating a team](https://launchdarkly.com/docs/home/account/create-teams). + +### Expanding the teams response +LaunchDarkly supports four fields for expanding the "Create team" response. By default, these fields are **not** included in the response. + +To expand the response, append the `expand` query parameter and add a comma-separated list with any of the following fields: + +* `members` includes the total count of members that belong to the team. +* `roles` includes a paginated list of the custom roles that you have assigned to the team. +* `projects` includes a paginated list of the projects that the team has any write access to. +* `maintainers` includes a paginated list of the maintainers that you have assigned to the team. + +For example, `expand=members,roles` includes the `members` and `roles` fields in the response. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostTeamRequest +*/ +func (a *TeamsApiService) PostTeam(ctx context.Context) ApiPostTeamRequest { + return ApiPostTeamRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Team +func (a *TeamsApiService) PostTeamExecute(r ApiPostTeamRequest) (*Team, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Team + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.PostTeam") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.teamPostInput == nil { + return localVarReturnValue, nil, reportError("teamPostInput is required and must be specified") + } + + if r.expand != nil { + localVarQueryParams.Add("expand", parameterToString(*r.expand, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.teamPostInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostTeamMembersRequest struct { + ctx context.Context + ApiService TeamsApi + teamKey string + file **os.File +} + +// CSV file containing email addresses +func (r ApiPostTeamMembersRequest) File(file *os.File) ApiPostTeamMembersRequest { + r.file = &file + return r +} + +func (r ApiPostTeamMembersRequest) Execute() (*TeamImportsRep, *http.Response, error) { + return r.ApiService.PostTeamMembersExecute(r) +} + +/* +PostTeamMembers Add multiple members to team + +Add multiple members to an existing team by uploading a CSV file of member email addresses. Your CSV file must include email addresses in the first column. You can include data in additional columns, but LaunchDarkly ignores all data outside the first column. Headers are optional. To learn more, read [Manage team members](https://launchdarkly.com/docs/home/account/manage-teams#manage-team-members). + +**Members are only added on a `201` response.** A `207` indicates the CSV file contains a combination of valid and invalid entries. A `207` results in no members being added to the team. + +On a `207` response, if an entry contains bad input, the `message` field contains the row number as well as the reason for the error. The `message` field is omitted if the entry is valid. + +Example `207` response: +```json +{ + "items": [ + { + "status": "success", + "value": "new-team-member@acme.com" + }, + { + "message": "Line 2: empty row", + "status": "error", + "value": "" + }, + { + "message": "Line 3: email already exists in the specified team", + "status": "error", + "value": "existing-team-member@acme.com" + }, + { + "message": "Line 4: invalid email formatting", + "status": "error", + "value": "invalid email format" + } + ] +} +``` + +Message | Resolution +--- | --- +Empty row | This line is blank. Add an email address and try again. +Duplicate entry | This email address appears in the file twice. Remove the email from the file and try again. +Email already exists in the specified team | This member is already on your team. Remove the email from the file and try again. +Invalid formatting | This email address is not formatted correctly. Fix the formatting and try again. +Email does not belong to a LaunchDarkly member | The email address doesn't belong to a LaunchDarkly account member. Invite them to LaunchDarkly, then re-add them to the team. + +On a `400` response, the `message` field may contain errors specific to this endpoint. + +Example `400` response: +```json +{ + "code": "invalid_request", + "message": "Unable to process file" +} +``` + +Message | Resolution +--- | --- +Unable to process file | LaunchDarkly could not process the file for an unspecified reason. Review your file for errors and try again. +File exceeds 25mb | Break up your file into multiple files of less than 25mbs each. +All emails have invalid formatting | None of the email addresses in the file are in the correct format. Fix the formatting and try again. +All emails belong to existing team members | All listed members are already on this team. Populate the file with member emails that do not belong to the team and try again. +File is empty | The CSV file does not contain any email addresses. Populate the file and try again. +No emails belong to members of your LaunchDarkly organization | None of the email addresses belong to members of your LaunchDarkly account. Invite these members to LaunchDarkly, then re-add them to the team. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param teamKey The team key + @return ApiPostTeamMembersRequest +*/ +func (a *TeamsApiService) PostTeamMembers(ctx context.Context, teamKey string) ApiPostTeamMembersRequest { + return ApiPostTeamMembersRequest{ + ApiService: a, + ctx: ctx, + teamKey: teamKey, + } +} + +// Execute executes the request +// @return TeamImportsRep +func (a *TeamsApiService) PostTeamMembersExecute(r ApiPostTeamMembersRequest) (*TeamImportsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *TeamImportsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsApiService.PostTeamMembers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams/{teamKey}/members" + localVarPath = strings.Replace(localVarPath, "{"+"teamKey"+"}", url.PathEscape(parameterToString(r.teamKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"multipart/form-data"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + var fileLocalVarFormFileName string + var fileLocalVarFileName string + var fileLocalVarFileBytes []byte + + fileLocalVarFormFileName = "file" + + var fileLocalVarFile *os.File + if r.file != nil { + fileLocalVarFile = *r.file + } + if fileLocalVarFile != nil { + fbs, _ := ioutil.ReadAll(fileLocalVarFile) + fileLocalVarFileBytes = fbs + fileLocalVarFileName = fileLocalVarFile.Name() + fileLocalVarFile.Close() + } + formFiles = append(formFiles, formFile{fileBytes: fileLocalVarFileBytes, fileName: fileLocalVarFileName, formFileName: fileLocalVarFormFileName}) + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 405 { + var v MethodNotAllowedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_teams_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_teams_beta.go new file mode 100644 index 00000000..6aeb347f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_teams_beta.go @@ -0,0 +1,352 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" +) + + +type TeamsBetaApi interface { + + /* + PatchTeams Update teams + + Perform a partial update to multiple teams. Updating teams uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating teams. + +
+Click to expand instructions for updating teams + +#### addMembersToTeams + +Add the members to teams. + +##### Parameters + +- `memberIDs`: List of member IDs to add. +- `teamKeys`: List of teams to update. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addMembersToTeams", + "memberIDs": [ + "1234a56b7c89d012345e678f" + ], + "teamKeys": [ + "example-team-1", + "example-team-2" + ] + }] +} +``` + +#### addAllMembersToTeams + +Add all members to the team. Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `teamKeys`: List of teams to update. +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addAllMembersToTeams", + "teamKeys": [ + "example-team-1", + "example-team-2" + ], + "filterLastSeen": { "never": true } + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPatchTeamsRequest + */ + PatchTeams(ctx context.Context) ApiPatchTeamsRequest + + // PatchTeamsExecute executes the request + // @return BulkEditTeamsRep + PatchTeamsExecute(r ApiPatchTeamsRequest) (*BulkEditTeamsRep, *http.Response, error) +} + +// TeamsBetaApiService TeamsBetaApi service +type TeamsBetaApiService service + +type ApiPatchTeamsRequest struct { + ctx context.Context + ApiService TeamsBetaApi + teamsPatchInput *TeamsPatchInput +} + +func (r ApiPatchTeamsRequest) TeamsPatchInput(teamsPatchInput TeamsPatchInput) ApiPatchTeamsRequest { + r.teamsPatchInput = &teamsPatchInput + return r +} + +func (r ApiPatchTeamsRequest) Execute() (*BulkEditTeamsRep, *http.Response, error) { + return r.ApiService.PatchTeamsExecute(r) +} + +/* +PatchTeams Update teams + +Perform a partial update to multiple teams. Updating teams uses the semantic patch format. + +To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating teams. + +
+Click to expand instructions for updating teams + +#### addMembersToTeams + +Add the members to teams. + +##### Parameters + +- `memberIDs`: List of member IDs to add. +- `teamKeys`: List of teams to update. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addMembersToTeams", + "memberIDs": [ + "1234a56b7c89d012345e678f" + ], + "teamKeys": [ + "example-team-1", + "example-team-2" + ] + }] +} +``` + +#### addAllMembersToTeams + +Add all members to the team. Members that match any of the filters are **excluded** from the update. + +##### Parameters + +- `teamKeys`: List of teams to update. +- `filterLastSeen`: (Optional) A JSON object with one of the following formats: + - `{"never": true}` - Members that have never been active, such as those who have not accepted their invitation to LaunchDarkly, or have not logged in after being provisioned via SCIM. + - `{"noData": true}` - Members that have not been active since LaunchDarkly began recording last seen timestamps. + - `{"before": 1608672063611}` - Members that have not been active since the provided value, which should be a timestamp in Unix epoch milliseconds. +- `filterQuery`: (Optional) A string that matches against the members' emails and names. It is not case sensitive. +- `filterRoles`: (Optional) A `|` separated list of roles and custom roles. For the purposes of this filtering, `Owner` counts as `Admin`. +- `filterTeamKey`: (Optional) A string that matches against the key of the team the members belong to. It is not case sensitive. +- `ignoredMemberIDs`: (Optional) A list of member IDs. + +Here's an example: + +```json +{ + "instructions": [{ + "kind": "addAllMembersToTeams", + "teamKeys": [ + "example-team-1", + "example-team-2" + ], + "filterLastSeen": { "never": true } + }] +} +``` + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPatchTeamsRequest +*/ +func (a *TeamsBetaApiService) PatchTeams(ctx context.Context) ApiPatchTeamsRequest { + return ApiPatchTeamsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return BulkEditTeamsRep +func (a *TeamsBetaApiService) PatchTeamsExecute(r ApiPatchTeamsRequest) (*BulkEditTeamsRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *BulkEditTeamsRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "TeamsBetaApiService.PatchTeams") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/teams" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.teamsPatchInput == nil { + return localVarReturnValue, nil, reportError("teamsPatchInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.teamsPatchInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_user_settings.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_user_settings.go new file mode 100644 index 00000000..0ef945e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_user_settings.go @@ -0,0 +1,1121 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type UserSettingsApi interface { + + /* + GetExpiringFlagsForUser Get expiring dates on flags for user + + Get a list of flags for which the given user is scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param userKey The user key + @param environmentKey The environment key + @return ApiGetExpiringFlagsForUserRequest + + Deprecated + */ + GetExpiringFlagsForUser(ctx context.Context, projectKey string, userKey string, environmentKey string) ApiGetExpiringFlagsForUserRequest + + // GetExpiringFlagsForUserExecute executes the request + // @return ExpiringUserTargetGetResponse + // Deprecated + GetExpiringFlagsForUserExecute(r ApiGetExpiringFlagsForUserRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) + + /* + GetUserFlagSetting Get flag setting for user + + Get a single flag setting for a user by flag key.

The `_value` is the flag variation that the user receives. The `setting` indicates whether you've explicitly targeted a user to receive a particular variation. For example, if you have turned off a feature flag for a user, this setting will be `false`. The example response indicates that the user `Abbie_Braun` has the `sort.order` flag enabled. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @param featureFlagKey The feature flag key + @return ApiGetUserFlagSettingRequest + + Deprecated + */ + GetUserFlagSetting(ctx context.Context, projectKey string, environmentKey string, userKey string, featureFlagKey string) ApiGetUserFlagSettingRequest + + // GetUserFlagSettingExecute executes the request + // @return UserFlagSetting + // Deprecated + GetUserFlagSettingExecute(r ApiGetUserFlagSettingRequest) (*UserFlagSetting, *http.Response, error) + + /* + GetUserFlagSettings List flag settings for user + + Get the current flag settings for a given user.

The `_value` is the flag variation that the user receives. The `setting` indicates whether you've explicitly targeted a user to receive a particular variation. For example, if you have turned off a feature flag for a user, this setting will be `false`. The example response indicates that the user `Abbie_Braun` has the `sort.order` flag enabled and the `alternate.page` flag disabled, and that the user has not been explicitly targeted to receive a particular variation. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiGetUserFlagSettingsRequest + + Deprecated + */ + GetUserFlagSettings(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiGetUserFlagSettingsRequest + + // GetUserFlagSettingsExecute executes the request + // @return UserFlagSettings + // Deprecated + GetUserFlagSettingsExecute(r ApiGetUserFlagSettingsRequest) (*UserFlagSettings, *http.Response, error) + + /* + PatchExpiringFlagsForUser Update expiring user target for flags + + Schedule the specified user for removal from individual targeting on one or more flags. The user must already be individually targeted for each flag. + +You can add, update, or remove a scheduled removal date. You can only schedule a user for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Adds a date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag. + +#### updateExpireUserTargetDate + +Updates the date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag. +* `version`: The version of the expiring user target to update. If included, update will fail if version doesn't match current version of the expiring user target. + +#### removeExpireUserTargetDate + +Removes the scheduled removal of the user from the flag's individual targeting. The user will remain part of the flag's individual targeting until explicitly removed, or until another removal is scheduled. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param userKey The user key + @param environmentKey The environment key + @return ApiPatchExpiringFlagsForUserRequest + + Deprecated + */ + PatchExpiringFlagsForUser(ctx context.Context, projectKey string, userKey string, environmentKey string) ApiPatchExpiringFlagsForUserRequest + + // PatchExpiringFlagsForUserExecute executes the request + // @return ExpiringUserTargetPatchResponse + // Deprecated + PatchExpiringFlagsForUserExecute(r ApiPatchExpiringFlagsForUserRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) + + /* + PutFlagSetting Update flag settings for user + + Enable or disable a feature flag for a user based on their key. + +Omitting the `setting` attribute from the request body, or including a `setting` of `null`, erases the current setting for a user. + +If you previously patched the flag, and the patch included the user's data, LaunchDarkly continues to use that data. If LaunchDarkly has never encountered the user's key before, it calculates the flag values based on the user key alone. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @param featureFlagKey The feature flag key + @return ApiPutFlagSettingRequest + + Deprecated + */ + PutFlagSetting(ctx context.Context, projectKey string, environmentKey string, userKey string, featureFlagKey string) ApiPutFlagSettingRequest + + // PutFlagSettingExecute executes the request + // Deprecated + PutFlagSettingExecute(r ApiPutFlagSettingRequest) (*http.Response, error) +} + +// UserSettingsApiService UserSettingsApi service +type UserSettingsApiService service + +type ApiGetExpiringFlagsForUserRequest struct { + ctx context.Context + ApiService UserSettingsApi + projectKey string + userKey string + environmentKey string +} + +func (r ApiGetExpiringFlagsForUserRequest) Execute() (*ExpiringUserTargetGetResponse, *http.Response, error) { + return r.ApiService.GetExpiringFlagsForUserExecute(r) +} + +/* +GetExpiringFlagsForUser Get expiring dates on flags for user + +Get a list of flags for which the given user is scheduled for removal. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param userKey The user key + @param environmentKey The environment key + @return ApiGetExpiringFlagsForUserRequest + +Deprecated +*/ +func (a *UserSettingsApiService) GetExpiringFlagsForUser(ctx context.Context, projectKey string, userKey string, environmentKey string) ApiGetExpiringFlagsForUserRequest { + return ApiGetExpiringFlagsForUserRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + userKey: userKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetGetResponse +// Deprecated +func (a *UserSettingsApiService) GetExpiringFlagsForUserExecute(r ApiGetExpiringFlagsForUserRequest) (*ExpiringUserTargetGetResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetGetResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UserSettingsApiService.GetExpiringFlagsForUser") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{userKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetUserFlagSettingRequest struct { + ctx context.Context + ApiService UserSettingsApi + projectKey string + environmentKey string + userKey string + featureFlagKey string +} + +func (r ApiGetUserFlagSettingRequest) Execute() (*UserFlagSetting, *http.Response, error) { + return r.ApiService.GetUserFlagSettingExecute(r) +} + +/* +GetUserFlagSetting Get flag setting for user + +Get a single flag setting for a user by flag key.

The `_value` is the flag variation that the user receives. The `setting` indicates whether you've explicitly targeted a user to receive a particular variation. For example, if you have turned off a feature flag for a user, this setting will be `false`. The example response indicates that the user `Abbie_Braun` has the `sort.order` flag enabled. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @param featureFlagKey The feature flag key + @return ApiGetUserFlagSettingRequest + +Deprecated +*/ +func (a *UserSettingsApiService) GetUserFlagSetting(ctx context.Context, projectKey string, environmentKey string, userKey string, featureFlagKey string) ApiGetUserFlagSettingRequest { + return ApiGetUserFlagSettingRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + userKey: userKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// @return UserFlagSetting +// Deprecated +func (a *UserSettingsApiService) GetUserFlagSettingExecute(r ApiGetUserFlagSettingRequest) (*UserFlagSetting, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserFlagSetting + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UserSettingsApiService.GetUserFlagSetting") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetUserFlagSettingsRequest struct { + ctx context.Context + ApiService UserSettingsApi + projectKey string + environmentKey string + userKey string +} + +func (r ApiGetUserFlagSettingsRequest) Execute() (*UserFlagSettings, *http.Response, error) { + return r.ApiService.GetUserFlagSettingsExecute(r) +} + +/* +GetUserFlagSettings List flag settings for user + +Get the current flag settings for a given user.

The `_value` is the flag variation that the user receives. The `setting` indicates whether you've explicitly targeted a user to receive a particular variation. For example, if you have turned off a feature flag for a user, this setting will be `false`. The example response indicates that the user `Abbie_Braun` has the `sort.order` flag enabled and the `alternate.page` flag disabled, and that the user has not been explicitly targeted to receive a particular variation. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiGetUserFlagSettingsRequest + +Deprecated +*/ +func (a *UserSettingsApiService) GetUserFlagSettings(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiGetUserFlagSettingsRequest { + return ApiGetUserFlagSettingsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + userKey: userKey, + } +} + +// Execute executes the request +// @return UserFlagSettings +// Deprecated +func (a *UserSettingsApiService) GetUserFlagSettingsExecute(r ApiGetUserFlagSettingsRequest) (*UserFlagSettings, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserFlagSettings + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UserSettingsApiService.GetUserFlagSettings") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchExpiringFlagsForUserRequest struct { + ctx context.Context + ApiService UserSettingsApi + projectKey string + userKey string + environmentKey string + patchUsersRequest *PatchUsersRequest +} + +func (r ApiPatchExpiringFlagsForUserRequest) PatchUsersRequest(patchUsersRequest PatchUsersRequest) ApiPatchExpiringFlagsForUserRequest { + r.patchUsersRequest = &patchUsersRequest + return r +} + +func (r ApiPatchExpiringFlagsForUserRequest) Execute() (*ExpiringUserTargetPatchResponse, *http.Response, error) { + return r.ApiService.PatchExpiringFlagsForUserExecute(r) +} + +/* +PatchExpiringFlagsForUser Update expiring user target for flags + +Schedule the specified user for removal from individual targeting on one or more flags. The user must already be individually targeted for each flag. + +You can add, update, or remove a scheduled removal date. You can only schedule a user for removal on a single variation per flag. + +Updating an expiring target uses the semantic patch format. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch). + +### Instructions + +Semantic patch requests support the following `kind` instructions for updating expiring user targets. + +
+Click to expand instructions for updating expiring user targets + +#### addExpireUserTargetDate + +Adds a date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag. + +#### updateExpireUserTargetDate + +Updates the date and time that LaunchDarkly will remove the user from the flag's individual targeting. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag +* `value`: The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag. +* `version`: The version of the expiring user target to update. If included, update will fail if version doesn't match current version of the expiring user target. + +#### removeExpireUserTargetDate + +Removes the scheduled removal of the user from the flag's individual targeting. The user will remain part of the flag's individual targeting until explicitly removed, or until another removal is scheduled. + +##### Parameters + +* `flagKey`: The flag key +* `variationId`: ID of a variation on the flag + +
+ + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param userKey The user key + @param environmentKey The environment key + @return ApiPatchExpiringFlagsForUserRequest + +Deprecated +*/ +func (a *UserSettingsApiService) PatchExpiringFlagsForUser(ctx context.Context, projectKey string, userKey string, environmentKey string) ApiPatchExpiringFlagsForUserRequest { + return ApiPatchExpiringFlagsForUserRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + userKey: userKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return ExpiringUserTargetPatchResponse +// Deprecated +func (a *UserSettingsApiService) PatchExpiringFlagsForUserExecute(r ApiPatchExpiringFlagsForUserRequest) (*ExpiringUserTargetPatchResponse, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *ExpiringUserTargetPatchResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UserSettingsApiService.PatchExpiringFlagsForUser") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{userKey}/expiring-user-targets/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchUsersRequest == nil { + return localVarReturnValue, nil, reportError("patchUsersRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchUsersRequest + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPutFlagSettingRequest struct { + ctx context.Context + ApiService UserSettingsApi + projectKey string + environmentKey string + userKey string + featureFlagKey string + valuePut *ValuePut +} + +func (r ApiPutFlagSettingRequest) ValuePut(valuePut ValuePut) ApiPutFlagSettingRequest { + r.valuePut = &valuePut + return r +} + +func (r ApiPutFlagSettingRequest) Execute() (*http.Response, error) { + return r.ApiService.PutFlagSettingExecute(r) +} + +/* +PutFlagSetting Update flag settings for user + +Enable or disable a feature flag for a user based on their key. + +Omitting the `setting` attribute from the request body, or including a `setting` of `null`, erases the current setting for a user. + +If you previously patched the flag, and the patch included the user's data, LaunchDarkly continues to use that data. If LaunchDarkly has never encountered the user's key before, it calculates the flag values based on the user key alone. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @param featureFlagKey The feature flag key + @return ApiPutFlagSettingRequest + +Deprecated +*/ +func (a *UserSettingsApiService) PutFlagSetting(ctx context.Context, projectKey string, environmentKey string, userKey string, featureFlagKey string) ApiPutFlagSettingRequest { + return ApiPutFlagSettingRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + userKey: userKey, + featureFlagKey: featureFlagKey, + } +} + +// Execute executes the request +// Deprecated +func (a *UserSettingsApiService) PutFlagSettingExecute(r ApiPutFlagSettingRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPut + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UserSettingsApiService.PutFlagSetting") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}/{userKey}/flags/{featureFlagKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.valuePut == nil { + return nil, reportError("valuePut is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.valuePut + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_users.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_users.go new file mode 100644 index 00000000..e3c22c3d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_users.go @@ -0,0 +1,937 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type UsersApi interface { + + /* + DeleteUser Delete user + + > ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Delete context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/delete-context-instances) instead of this endpoint. + +Delete a user by key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiDeleteUserRequest + + Deprecated + */ + DeleteUser(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiDeleteUserRequest + + // DeleteUserExecute executes the request + // Deprecated + DeleteUserExecute(r ApiDeleteUserRequest) (*http.Response, error) + + /* + GetSearchUsers Find users + + > ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Search for context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/search-context-instances) instead of this endpoint. + +Search users in LaunchDarkly based on their last active date, a user attribute filter set, or a search query. + +An example user attribute filter set is `filter=firstName:Anna,activeTrial:false`. This matches users that have the user attribute `firstName` set to `Anna`, that also have the attribute `activeTrial` set to `false`. + +To paginate through results, follow the `next` link in the `_links` object. To learn more, read [Representations](https://launchdarkly.com/docs/ld-docs/api#representations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetSearchUsersRequest + + Deprecated + */ + GetSearchUsers(ctx context.Context, projectKey string, environmentKey string) ApiGetSearchUsersRequest + + // GetSearchUsersExecute executes the request + // @return Users + // Deprecated + GetSearchUsersExecute(r ApiGetSearchUsersRequest) (*Users, *http.Response, error) + + /* + GetUser Get user + + > ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/get-context-instances) instead of this endpoint. + +Get a user by key. The `user` object contains all attributes sent in `variation` calls for that key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiGetUserRequest + + Deprecated + */ + GetUser(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiGetUserRequest + + // GetUserExecute executes the request + // @return UserRecord + // Deprecated + GetUserExecute(r ApiGetUserRequest) (*UserRecord, *http.Response, error) + + /* + GetUsers List users + + > ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Search for contexts](https://launchdarkly.com/docs/ld-docs/api/contexts/search-contexts) instead of this endpoint. + +List all users in the environment. Includes the total count of users. This is useful for exporting all users in the system for further analysis. + +Each page displays users up to a set `limit`. The default is 20. To page through, follow the `next` link in the `_links` object. To learn more, read [Representations](https://launchdarkly.com/docs/ld-docs/api#representations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetUsersRequest + + Deprecated + */ + GetUsers(ctx context.Context, projectKey string, environmentKey string) ApiGetUsersRequest + + // GetUsersExecute executes the request + // @return UsersRep + // Deprecated + GetUsersExecute(r ApiGetUsersRequest) (*UsersRep, *http.Response, error) +} + +// UsersApiService UsersApi service +type UsersApiService service + +type ApiDeleteUserRequest struct { + ctx context.Context + ApiService UsersApi + projectKey string + environmentKey string + userKey string +} + +func (r ApiDeleteUserRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteUserExecute(r) +} + +/* +DeleteUser Delete user + +> ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Delete context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/delete-context-instances) instead of this endpoint. + +Delete a user by key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiDeleteUserRequest + +Deprecated +*/ +func (a *UsersApiService) DeleteUser(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiDeleteUserRequest { + return ApiDeleteUserRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + userKey: userKey, + } +} + +// Execute executes the request +// Deprecated +func (a *UsersApiService) DeleteUserExecute(r ApiDeleteUserRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.DeleteUser") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}/{userKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 409 { + var v StatusConflictErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetSearchUsersRequest struct { + ctx context.Context + ApiService UsersApi + projectKey string + environmentKey string + q *string + limit *int64 + offset *int64 + after *int64 + sort *string + searchAfter *string + filter *string +} + +// Full-text search for users based on name, first name, last name, e-mail address, or key +func (r ApiGetSearchUsersRequest) Q(q string) ApiGetSearchUsersRequest { + r.q = &q + return r +} + +// Specifies the maximum number of items in the collection to return (max: 50, default: 20) +func (r ApiGetSearchUsersRequest) Limit(limit int64) ApiGetSearchUsersRequest { + r.limit = &limit + return r +} + +// Deprecated, use `searchAfter` instead. Specifies the first item to return in the collection. +// Deprecated +func (r ApiGetSearchUsersRequest) Offset(offset int64) ApiGetSearchUsersRequest { + r.offset = &offset + return r +} + +// A Unix epoch time in milliseconds specifying the maximum last time a user requested a feature flag from LaunchDarkly +func (r ApiGetSearchUsersRequest) After(after int64) ApiGetSearchUsersRequest { + r.after = &after + return r +} + +// Specifies a field by which to sort. LaunchDarkly supports the `userKey` and `lastSeen` fields. Fields prefixed by a dash ( - ) sort in descending order. +func (r ApiGetSearchUsersRequest) Sort(sort string) ApiGetSearchUsersRequest { + r.sort = &sort + return r +} + +// Limits results to users with sort values after the value you specify. You can use this for pagination, but we recommend using the `next` link we provide instead. +func (r ApiGetSearchUsersRequest) SearchAfter(searchAfter string) ApiGetSearchUsersRequest { + r.searchAfter = &searchAfter + return r +} + +// A comma-separated list of user attribute filters. Each filter is in the form of attributeKey:attributeValue +func (r ApiGetSearchUsersRequest) Filter(filter string) ApiGetSearchUsersRequest { + r.filter = &filter + return r +} + +func (r ApiGetSearchUsersRequest) Execute() (*Users, *http.Response, error) { + return r.ApiService.GetSearchUsersExecute(r) +} + +/* +GetSearchUsers Find users + +> ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Search for context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/search-context-instances) instead of this endpoint. + +Search users in LaunchDarkly based on their last active date, a user attribute filter set, or a search query. + +An example user attribute filter set is `filter=firstName:Anna,activeTrial:false`. This matches users that have the user attribute `firstName` set to `Anna`, that also have the attribute `activeTrial` set to `false`. + +To paginate through results, follow the `next` link in the `_links` object. To learn more, read [Representations](https://launchdarkly.com/docs/ld-docs/api#representations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetSearchUsersRequest + +Deprecated +*/ +func (a *UsersApiService) GetSearchUsers(ctx context.Context, projectKey string, environmentKey string) ApiGetSearchUsersRequest { + return ApiGetSearchUsersRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return Users +// Deprecated +func (a *UsersApiService) GetSearchUsersExecute(r ApiGetSearchUsersRequest) (*Users, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Users + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.GetSearchUsers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/user-search/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.q != nil { + localVarQueryParams.Add("q", parameterToString(*r.q, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.searchAfter != nil { + localVarQueryParams.Add("searchAfter", parameterToString(*r.searchAfter, "")) + } + if r.filter != nil { + localVarQueryParams.Add("filter", parameterToString(*r.filter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetUserRequest struct { + ctx context.Context + ApiService UsersApi + projectKey string + environmentKey string + userKey string +} + +func (r ApiGetUserRequest) Execute() (*UserRecord, *http.Response, error) { + return r.ApiService.GetUserExecute(r) +} + +/* +GetUser Get user + +> ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get context instances](https://launchdarkly.com/docs/ld-docs/api/contexts/get-context-instances) instead of this endpoint. + +Get a user by key. The `user` object contains all attributes sent in `variation` calls for that key. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @param userKey The user key + @return ApiGetUserRequest + +Deprecated +*/ +func (a *UsersApiService) GetUser(ctx context.Context, projectKey string, environmentKey string, userKey string) ApiGetUserRequest { + return ApiGetUserRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + userKey: userKey, + } +} + +// Execute executes the request +// @return UserRecord +// Deprecated +func (a *UsersApiService) GetUserExecute(r ApiGetUserRequest) (*UserRecord, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserRecord + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.GetUser") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}/{userKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"userKey"+"}", url.PathEscape(parameterToString(r.userKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetUsersRequest struct { + ctx context.Context + ApiService UsersApi + projectKey string + environmentKey string + limit *int64 + searchAfter *string +} + +// The number of elements to return per page +func (r ApiGetUsersRequest) Limit(limit int64) ApiGetUsersRequest { + r.limit = &limit + return r +} + +// Limits results to users with sort values after the value you specify. You can use this for pagination, but we recommend using the `next` link we provide instead. +func (r ApiGetUsersRequest) SearchAfter(searchAfter string) ApiGetUsersRequest { + r.searchAfter = &searchAfter + return r +} + +func (r ApiGetUsersRequest) Execute() (*UsersRep, *http.Response, error) { + return r.ApiService.GetUsersExecute(r) +} + +/* +GetUsers List users + +> ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Search for contexts](https://launchdarkly.com/docs/ld-docs/api/contexts/search-contexts) instead of this endpoint. + +List all users in the environment. Includes the total count of users. This is useful for exporting all users in the system for further analysis. + +Each page displays users up to a set `limit`. The default is 20. To page through, follow the `next` link in the `_links` object. To learn more, read [Representations](https://launchdarkly.com/docs/ld-docs/api#representations). + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetUsersRequest + +Deprecated +*/ +func (a *UsersApiService) GetUsers(ctx context.Context, projectKey string, environmentKey string) ApiGetUsersRequest { + return ApiGetUsersRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return UsersRep +// Deprecated +func (a *UsersApiService) GetUsersExecute(r ApiGetUsersRequest) (*UsersRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UsersRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.GetUsers") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/users/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.searchAfter != nil { + localVarQueryParams.Add("searchAfter", parameterToString(*r.searchAfter, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_users_beta.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_users_beta.go new file mode 100644 index 00000000..9c453d39 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_users_beta.go @@ -0,0 +1,222 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type UsersBetaApi interface { + + /* + GetUserAttributeNames Get user attribute names + + > ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get context attribute names +](https://launchdarkly.com/docs/ld-docs/api/contexts/get-context-attribute-names) instead of this endpoint. + +Get all in-use user attributes in the specified environment. The set of in-use attributes typically consists of all attributes seen within the past 30 days. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetUserAttributeNamesRequest + + Deprecated + */ + GetUserAttributeNames(ctx context.Context, projectKey string, environmentKey string) ApiGetUserAttributeNamesRequest + + // GetUserAttributeNamesExecute executes the request + // @return UserAttributeNamesRep + // Deprecated + GetUserAttributeNamesExecute(r ApiGetUserAttributeNamesRequest) (*UserAttributeNamesRep, *http.Response, error) +} + +// UsersBetaApiService UsersBetaApi service +type UsersBetaApiService service + +type ApiGetUserAttributeNamesRequest struct { + ctx context.Context + ApiService UsersBetaApi + projectKey string + environmentKey string +} + +func (r ApiGetUserAttributeNamesRequest) Execute() (*UserAttributeNamesRep, *http.Response, error) { + return r.ApiService.GetUserAttributeNamesExecute(r) +} + +/* +GetUserAttributeNames Get user attribute names + +> ### Use contexts instead +> +> After you have upgraded your LaunchDarkly SDK to use contexts instead of users, you should use [Get context attribute names +](https://launchdarkly.com/docs/ld-docs/api/contexts/get-context-attribute-names) instead of this endpoint. + +Get all in-use user attributes in the specified environment. The set of in-use attributes typically consists of all attributes seen within the past 30 days. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param environmentKey The environment key + @return ApiGetUserAttributeNamesRequest + +Deprecated +*/ +func (a *UsersBetaApiService) GetUserAttributeNames(ctx context.Context, projectKey string, environmentKey string) ApiGetUserAttributeNamesRequest { + return ApiGetUserAttributeNamesRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return UserAttributeNamesRep +// Deprecated +func (a *UsersBetaApiService) GetUserAttributeNamesExecute(r ApiGetUserAttributeNamesRequest) (*UserAttributeNamesRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *UserAttributeNamesRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersBetaApiService.GetUserAttributeNames") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/user-attributes/{projectKey}/{environmentKey}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_webhooks.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_webhooks.go new file mode 100644 index 00000000..01752440 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_webhooks.go @@ -0,0 +1,883 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type WebhooksApi interface { + + /* + DeleteWebhook Delete webhook + + Delete a webhook by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook to delete + @return ApiDeleteWebhookRequest + */ + DeleteWebhook(ctx context.Context, id string) ApiDeleteWebhookRequest + + // DeleteWebhookExecute executes the request + DeleteWebhookExecute(r ApiDeleteWebhookRequest) (*http.Response, error) + + /* + GetAllWebhooks List webhooks + + Fetch a list of all webhooks. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAllWebhooksRequest + */ + GetAllWebhooks(ctx context.Context) ApiGetAllWebhooksRequest + + // GetAllWebhooksExecute executes the request + // @return Webhooks + GetAllWebhooksExecute(r ApiGetAllWebhooksRequest) (*Webhooks, *http.Response, error) + + /* + GetWebhook Get webhook + + Get a single webhook by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook + @return ApiGetWebhookRequest + */ + GetWebhook(ctx context.Context, id string) ApiGetWebhookRequest + + // GetWebhookExecute executes the request + // @return Webhook + GetWebhookExecute(r ApiGetWebhookRequest) (*Webhook, *http.Response, error) + + /* + PatchWebhook Update webhook + + Update a webhook's settings. Updating webhook settings uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook to update + @return ApiPatchWebhookRequest + */ + PatchWebhook(ctx context.Context, id string) ApiPatchWebhookRequest + + // PatchWebhookExecute executes the request + // @return Webhook + PatchWebhookExecute(r ApiPatchWebhookRequest) (*Webhook, *http.Response, error) + + /* + PostWebhook Creates a webhook + + Create a new webhook. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostWebhookRequest + */ + PostWebhook(ctx context.Context) ApiPostWebhookRequest + + // PostWebhookExecute executes the request + // @return Webhook + PostWebhookExecute(r ApiPostWebhookRequest) (*Webhook, *http.Response, error) +} + +// WebhooksApiService WebhooksApi service +type WebhooksApiService service + +type ApiDeleteWebhookRequest struct { + ctx context.Context + ApiService WebhooksApi + id string +} + +func (r ApiDeleteWebhookRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteWebhookExecute(r) +} + +/* +DeleteWebhook Delete webhook + +Delete a webhook by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook to delete + @return ApiDeleteWebhookRequest +*/ +func (a *WebhooksApiService) DeleteWebhook(ctx context.Context, id string) ApiDeleteWebhookRequest { + return ApiDeleteWebhookRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +func (a *WebhooksApiService) DeleteWebhookExecute(r ApiDeleteWebhookRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WebhooksApiService.DeleteWebhook") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/webhooks/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetAllWebhooksRequest struct { + ctx context.Context + ApiService WebhooksApi +} + +func (r ApiGetAllWebhooksRequest) Execute() (*Webhooks, *http.Response, error) { + return r.ApiService.GetAllWebhooksExecute(r) +} + +/* +GetAllWebhooks List webhooks + +Fetch a list of all webhooks. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetAllWebhooksRequest +*/ +func (a *WebhooksApiService) GetAllWebhooks(ctx context.Context) ApiGetAllWebhooksRequest { + return ApiGetAllWebhooksRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Webhooks +func (a *WebhooksApiService) GetAllWebhooksExecute(r ApiGetAllWebhooksRequest) (*Webhooks, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Webhooks + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WebhooksApiService.GetAllWebhooks") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/webhooks" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetWebhookRequest struct { + ctx context.Context + ApiService WebhooksApi + id string +} + +func (r ApiGetWebhookRequest) Execute() (*Webhook, *http.Response, error) { + return r.ApiService.GetWebhookExecute(r) +} + +/* +GetWebhook Get webhook + +Get a single webhook by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook + @return ApiGetWebhookRequest +*/ +func (a *WebhooksApiService) GetWebhook(ctx context.Context, id string) ApiGetWebhookRequest { + return ApiGetWebhookRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Webhook +func (a *WebhooksApiService) GetWebhookExecute(r ApiGetWebhookRequest) (*Webhook, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Webhook + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WebhooksApiService.GetWebhook") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/webhooks/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchWebhookRequest struct { + ctx context.Context + ApiService WebhooksApi + id string + patchOperation *[]PatchOperation +} + +func (r ApiPatchWebhookRequest) PatchOperation(patchOperation []PatchOperation) ApiPatchWebhookRequest { + r.patchOperation = &patchOperation + return r +} + +func (r ApiPatchWebhookRequest) Execute() (*Webhook, *http.Response, error) { + return r.ApiService.PatchWebhookExecute(r) +} + +/* +PatchWebhook Update webhook + +Update a webhook's settings. Updating webhook settings uses a [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) representation of the desired changes. To learn more, read [Updates](https://launchdarkly.com/docs/api#updates). + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param id The ID of the webhook to update + @return ApiPatchWebhookRequest +*/ +func (a *WebhooksApiService) PatchWebhook(ctx context.Context, id string) ApiPatchWebhookRequest { + return ApiPatchWebhookRequest{ + ApiService: a, + ctx: ctx, + id: id, + } +} + +// Execute executes the request +// @return Webhook +func (a *WebhooksApiService) PatchWebhookExecute(r ApiPatchWebhookRequest) (*Webhook, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPatch + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Webhook + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WebhooksApiService.PatchWebhook") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/webhooks/{id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterToString(r.id, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.patchOperation == nil { + return localVarReturnValue, nil, reportError("patchOperation is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.patchOperation + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostWebhookRequest struct { + ctx context.Context + ApiService WebhooksApi + webhookPost *WebhookPost +} + +func (r ApiPostWebhookRequest) WebhookPost(webhookPost WebhookPost) ApiPostWebhookRequest { + r.webhookPost = &webhookPost + return r +} + +func (r ApiPostWebhookRequest) Execute() (*Webhook, *http.Response, error) { + return r.ApiService.PostWebhookExecute(r) +} + +/* +PostWebhook Creates a webhook + +Create a new webhook. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiPostWebhookRequest +*/ +func (a *WebhooksApiService) PostWebhook(ctx context.Context) ApiPostWebhookRequest { + return ApiPostWebhookRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Webhook +func (a *WebhooksApiService) PostWebhookExecute(r ApiPostWebhookRequest) (*Webhook, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Webhook + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WebhooksApiService.PostWebhook") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/webhooks" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.webhookPost == nil { + return localVarReturnValue, nil, reportError("webhookPost is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.webhookPost + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_workflow_templates.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_workflow_templates.go new file mode 100644 index 00000000..1a242493 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_workflow_templates.go @@ -0,0 +1,550 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type WorkflowTemplatesApi interface { + + /* + CreateWorkflowTemplate Create workflow template + + Create a template for a feature flag workflow + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateWorkflowTemplateRequest + */ + CreateWorkflowTemplate(ctx context.Context) ApiCreateWorkflowTemplateRequest + + // CreateWorkflowTemplateExecute executes the request + // @return WorkflowTemplateOutput + CreateWorkflowTemplateExecute(r ApiCreateWorkflowTemplateRequest) (*WorkflowTemplateOutput, *http.Response, error) + + /* + DeleteWorkflowTemplate Delete workflow template + + Delete a workflow template + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param templateKey The template key + @return ApiDeleteWorkflowTemplateRequest + */ + DeleteWorkflowTemplate(ctx context.Context, templateKey string) ApiDeleteWorkflowTemplateRequest + + // DeleteWorkflowTemplateExecute executes the request + DeleteWorkflowTemplateExecute(r ApiDeleteWorkflowTemplateRequest) (*http.Response, error) + + /* + GetWorkflowTemplates Get workflow templates + + Get workflow templates belonging to an account, or can optionally return templates_endpoints.workflowTemplateSummariesListingOutputRep when summary query param is true + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetWorkflowTemplatesRequest + */ + GetWorkflowTemplates(ctx context.Context) ApiGetWorkflowTemplatesRequest + + // GetWorkflowTemplatesExecute executes the request + // @return WorkflowTemplatesListingOutputRep + GetWorkflowTemplatesExecute(r ApiGetWorkflowTemplatesRequest) (*WorkflowTemplatesListingOutputRep, *http.Response, error) +} + +// WorkflowTemplatesApiService WorkflowTemplatesApi service +type WorkflowTemplatesApiService service + +type ApiCreateWorkflowTemplateRequest struct { + ctx context.Context + ApiService WorkflowTemplatesApi + createWorkflowTemplateInput *CreateWorkflowTemplateInput +} + +func (r ApiCreateWorkflowTemplateRequest) CreateWorkflowTemplateInput(createWorkflowTemplateInput CreateWorkflowTemplateInput) ApiCreateWorkflowTemplateRequest { + r.createWorkflowTemplateInput = &createWorkflowTemplateInput + return r +} + +func (r ApiCreateWorkflowTemplateRequest) Execute() (*WorkflowTemplateOutput, *http.Response, error) { + return r.ApiService.CreateWorkflowTemplateExecute(r) +} + +/* +CreateWorkflowTemplate Create workflow template + +Create a template for a feature flag workflow + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateWorkflowTemplateRequest +*/ +func (a *WorkflowTemplatesApiService) CreateWorkflowTemplate(ctx context.Context) ApiCreateWorkflowTemplateRequest { + return ApiCreateWorkflowTemplateRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return WorkflowTemplateOutput +func (a *WorkflowTemplatesApiService) CreateWorkflowTemplateExecute(r ApiCreateWorkflowTemplateRequest) (*WorkflowTemplateOutput, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *WorkflowTemplateOutput + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowTemplatesApiService.CreateWorkflowTemplate") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/templates" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.createWorkflowTemplateInput == nil { + return localVarReturnValue, nil, reportError("createWorkflowTemplateInput is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.createWorkflowTemplateInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiDeleteWorkflowTemplateRequest struct { + ctx context.Context + ApiService WorkflowTemplatesApi + templateKey string +} + +func (r ApiDeleteWorkflowTemplateRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteWorkflowTemplateExecute(r) +} + +/* +DeleteWorkflowTemplate Delete workflow template + +Delete a workflow template + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param templateKey The template key + @return ApiDeleteWorkflowTemplateRequest +*/ +func (a *WorkflowTemplatesApiService) DeleteWorkflowTemplate(ctx context.Context, templateKey string) ApiDeleteWorkflowTemplateRequest { + return ApiDeleteWorkflowTemplateRequest{ + ApiService: a, + ctx: ctx, + templateKey: templateKey, + } +} + +// Execute executes the request +func (a *WorkflowTemplatesApiService) DeleteWorkflowTemplateExecute(r ApiDeleteWorkflowTemplateRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowTemplatesApiService.DeleteWorkflowTemplate") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/templates/{templateKey}" + localVarPath = strings.Replace(localVarPath, "{"+"templateKey"+"}", url.PathEscape(parameterToString(r.templateKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetWorkflowTemplatesRequest struct { + ctx context.Context + ApiService WorkflowTemplatesApi + summary *bool + search *string +} + +// Whether the entire template object or just a summary should be returned +func (r ApiGetWorkflowTemplatesRequest) Summary(summary bool) ApiGetWorkflowTemplatesRequest { + r.summary = &summary + return r +} + +// The substring in either the name or description of a template +func (r ApiGetWorkflowTemplatesRequest) Search(search string) ApiGetWorkflowTemplatesRequest { + r.search = &search + return r +} + +func (r ApiGetWorkflowTemplatesRequest) Execute() (*WorkflowTemplatesListingOutputRep, *http.Response, error) { + return r.ApiService.GetWorkflowTemplatesExecute(r) +} + +/* +GetWorkflowTemplates Get workflow templates + +Get workflow templates belonging to an account, or can optionally return templates_endpoints.workflowTemplateSummariesListingOutputRep when summary query param is true + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetWorkflowTemplatesRequest +*/ +func (a *WorkflowTemplatesApiService) GetWorkflowTemplates(ctx context.Context) ApiGetWorkflowTemplatesRequest { + return ApiGetWorkflowTemplatesRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return WorkflowTemplatesListingOutputRep +func (a *WorkflowTemplatesApiService) GetWorkflowTemplatesExecute(r ApiGetWorkflowTemplatesRequest) (*WorkflowTemplatesListingOutputRep, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *WorkflowTemplatesListingOutputRep + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowTemplatesApiService.GetWorkflowTemplates") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/templates" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.summary != nil { + localVarQueryParams.Add("summary", parameterToString(*r.summary, "")) + } + if r.search != nil { + localVarQueryParams.Add("search", parameterToString(*r.search, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/api_workflows.go b/vendor/github.com/launchdarkly/api-client-go/v17/api_workflows.go new file mode 100644 index 00000000..04d5de30 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/api_workflows.go @@ -0,0 +1,1031 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + + +type WorkflowsApi interface { + + /* + DeleteWorkflow Delete workflow + + Delete a workflow from a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param workflowId The workflow id + @return ApiDeleteWorkflowRequest + */ + DeleteWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, workflowId string) ApiDeleteWorkflowRequest + + // DeleteWorkflowExecute executes the request + DeleteWorkflowExecute(r ApiDeleteWorkflowRequest) (*http.Response, error) + + /* + GetCustomWorkflow Get custom workflow + + Get a specific workflow by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param workflowId The workflow ID + @return ApiGetCustomWorkflowRequest + */ + GetCustomWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, workflowId string) ApiGetCustomWorkflowRequest + + // GetCustomWorkflowExecute executes the request + // @return CustomWorkflowOutput + GetCustomWorkflowExecute(r ApiGetCustomWorkflowRequest) (*CustomWorkflowOutput, *http.Response, error) + + /* + GetWorkflows Get workflows + + Display workflows associated with a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetWorkflowsRequest + */ + GetWorkflows(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetWorkflowsRequest + + // GetWorkflowsExecute executes the request + // @return CustomWorkflowsListingOutput + GetWorkflowsExecute(r ApiGetWorkflowsRequest) (*CustomWorkflowsListingOutput, *http.Response, error) + + /* + PostWorkflow Create workflow + + Create a workflow for a feature flag. You can create a workflow directly, or you can apply a template to create a new workflow. + +### Creating a workflow + +You can use the create workflow endpoint to create a workflow directly by adding a `stages` array to the request body. + +For each stage, define the `name`, `conditions` when the stage should be executed, and `action` that describes the stage. + +
+Click to expand example + +_Example request body_ +```json +{ + "name": "Progressive rollout starting in two days", + "description": "Turn flag targeting on and increase feature rollout in 10% increments each day", + "stages": [ + { + "name": "10% rollout on day 1", + "conditions": [ + { + "kind": "schedule", + "scheduleKind": "relative", // or "absolute" + // If "scheduleKind" is "absolute", set "executionDate"; + // "waitDuration" and "waitDurationUnit" will be ignored + "waitDuration": 2, + "waitDurationUnit": "calendarDay" + }, + { + "kind": "ld-approval", + "notifyMemberIds": [ "507f1f77bcf86cd799439011" ], + "notifyTeamKeys": [ "team-key-123abc" ] + } + ], + "action": { + "instructions": [ + { + "kind": "turnFlagOn" + }, + { + "kind": "updateFallthroughVariationOrRollout", + "rolloutWeights": { + "452f5fb5-7320-4ba3-81a1-8f4324f79d49": 90000, + "fc15f6a4-05d3-4aa4-a997-446be461345d": 10000 + } + } + ] + } + } + ] +} +``` +
+ +### Creating a workflow by applying a workflow template + +You can also create a workflow by applying a workflow template. If you pass a valid workflow template key as the `templateKey` query parameter with the request, the API will attempt to create a new workflow with the stages defined in the workflow template with the corresponding key. + +#### Applicability of stages +Templates are created in the context of a particular flag in a particular environment in a particular project. However, because workflows created from a template can be applied to any project, environment, and flag, some steps of the workflow may need to be updated in order to be applicable for the target resource. + +You can pass a `dryRun` query parameter to tell the API to return a report of which steps of the workflow template are applicable in the target project/environment/flag, and which will need to be updated. When the `dryRun` query parameter is present the response body includes a `meta` property that holds a list of parameters that could potentially be inapplicable for the target resource. Each of these parameters will include a `valid` field. You will need to update any invalid parameters in order to create the new workflow. You can do this using the `parameters` property, which overrides the workflow template parameters. + +#### Overriding template parameters +You can use the `parameters` property in the request body to tell the API to override the specified workflow template parameters with new values that are specific to your target project/environment/flag. + +
+Click to expand example + +_Example request body_ +```json +{ + "name": "workflow created from my-template", + "description": "description of my workflow", + "parameters": [ + { + "_id": "62cf2bc4cadbeb7697943f3b", + "path": "/clauses/0/values", + "default": { + "value": ["updated-segment"] + } + }, + { + "_id": "62cf2bc4cadbeb7697943f3d", + "path": "/variationId", + "default": { + "value": "abcd1234-abcd-1234-abcd-1234abcd12" + } + } + ] +} +``` +
+ +If there are any steps in the template that are not applicable to the target resource, the workflow will not be created, and the `meta` property will be included in the response body detailing which parameters need to be updated. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostWorkflowRequest + */ + PostWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostWorkflowRequest + + // PostWorkflowExecute executes the request + // @return CustomWorkflowOutput + PostWorkflowExecute(r ApiPostWorkflowRequest) (*CustomWorkflowOutput, *http.Response, error) +} + +// WorkflowsApiService WorkflowsApi service +type WorkflowsApiService service + +type ApiDeleteWorkflowRequest struct { + ctx context.Context + ApiService WorkflowsApi + projectKey string + featureFlagKey string + environmentKey string + workflowId string +} + +func (r ApiDeleteWorkflowRequest) Execute() (*http.Response, error) { + return r.ApiService.DeleteWorkflowExecute(r) +} + +/* +DeleteWorkflow Delete workflow + +Delete a workflow from a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param workflowId The workflow id + @return ApiDeleteWorkflowRequest +*/ +func (a *WorkflowsApiService) DeleteWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, workflowId string) ApiDeleteWorkflowRequest { + return ApiDeleteWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + workflowId: workflowId, + } +} + +// Execute executes the request +func (a *WorkflowsApiService) DeleteWorkflowExecute(r ApiDeleteWorkflowRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowsApiService.DeleteWorkflow") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows/{workflowId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"workflowId"+"}", url.PathEscape(parameterToString(r.workflowId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetCustomWorkflowRequest struct { + ctx context.Context + ApiService WorkflowsApi + projectKey string + featureFlagKey string + environmentKey string + workflowId string +} + +func (r ApiGetCustomWorkflowRequest) Execute() (*CustomWorkflowOutput, *http.Response, error) { + return r.ApiService.GetCustomWorkflowExecute(r) +} + +/* +GetCustomWorkflow Get custom workflow + +Get a specific workflow by ID. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @param workflowId The workflow ID + @return ApiGetCustomWorkflowRequest +*/ +func (a *WorkflowsApiService) GetCustomWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string, workflowId string) ApiGetCustomWorkflowRequest { + return ApiGetCustomWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + workflowId: workflowId, + } +} + +// Execute executes the request +// @return CustomWorkflowOutput +func (a *WorkflowsApiService) GetCustomWorkflowExecute(r ApiGetCustomWorkflowRequest) (*CustomWorkflowOutput, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomWorkflowOutput + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowsApiService.GetCustomWorkflow") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows/{workflowId}" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"workflowId"+"}", url.PathEscape(parameterToString(r.workflowId, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetWorkflowsRequest struct { + ctx context.Context + ApiService WorkflowsApi + projectKey string + featureFlagKey string + environmentKey string + status *string + sort *string + limit *int64 + offset *int64 +} + +// Filter results by workflow status. Valid status filters are `active`, `completed`, and `failed`. +func (r ApiGetWorkflowsRequest) Status(status string) ApiGetWorkflowsRequest { + r.status = &status + return r +} + +// A field to sort the items by. Prefix field by a dash ( - ) to sort in descending order. This endpoint supports sorting by `creationDate` or `stopDate`. +func (r ApiGetWorkflowsRequest) Sort(sort string) ApiGetWorkflowsRequest { + r.sort = &sort + return r +} + +// The maximum number of workflows to return. Defaults to 20. +func (r ApiGetWorkflowsRequest) Limit(limit int64) ApiGetWorkflowsRequest { + r.limit = &limit + return r +} + +// Where to start in the list. Defaults to 0. Use this with pagination. For example, an offset of 10 skips the first ten items and then returns the next items in the list, up to the query `limit`. +func (r ApiGetWorkflowsRequest) Offset(offset int64) ApiGetWorkflowsRequest { + r.offset = &offset + return r +} + +func (r ApiGetWorkflowsRequest) Execute() (*CustomWorkflowsListingOutput, *http.Response, error) { + return r.ApiService.GetWorkflowsExecute(r) +} + +/* +GetWorkflows Get workflows + +Display workflows associated with a feature flag. + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiGetWorkflowsRequest +*/ +func (a *WorkflowsApiService) GetWorkflows(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiGetWorkflowsRequest { + return ApiGetWorkflowsRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return CustomWorkflowsListingOutput +func (a *WorkflowsApiService) GetWorkflowsExecute(r ApiGetWorkflowsRequest) (*CustomWorkflowsListingOutput, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomWorkflowsListingOutput + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowsApiService.GetWorkflows") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if r.status != nil { + localVarQueryParams.Add("status", parameterToString(*r.status, "")) + } + if r.sort != nil { + localVarQueryParams.Add("sort", parameterToString(*r.sort, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostWorkflowRequest struct { + ctx context.Context + ApiService WorkflowsApi + projectKey string + featureFlagKey string + environmentKey string + customWorkflowInput *CustomWorkflowInput + templateKey *string + dryRun *bool +} + +func (r ApiPostWorkflowRequest) CustomWorkflowInput(customWorkflowInput CustomWorkflowInput) ApiPostWorkflowRequest { + r.customWorkflowInput = &customWorkflowInput + return r +} + +// The template key to apply as a starting point for the new workflow +func (r ApiPostWorkflowRequest) TemplateKey(templateKey string) ApiPostWorkflowRequest { + r.templateKey = &templateKey + return r +} + +// Whether to call the endpoint in dry-run mode +func (r ApiPostWorkflowRequest) DryRun(dryRun bool) ApiPostWorkflowRequest { + r.dryRun = &dryRun + return r +} + +func (r ApiPostWorkflowRequest) Execute() (*CustomWorkflowOutput, *http.Response, error) { + return r.ApiService.PostWorkflowExecute(r) +} + +/* +PostWorkflow Create workflow + +Create a workflow for a feature flag. You can create a workflow directly, or you can apply a template to create a new workflow. + +### Creating a workflow + +You can use the create workflow endpoint to create a workflow directly by adding a `stages` array to the request body. + +For each stage, define the `name`, `conditions` when the stage should be executed, and `action` that describes the stage. + +
+Click to expand example + +_Example request body_ +```json +{ + "name": "Progressive rollout starting in two days", + "description": "Turn flag targeting on and increase feature rollout in 10% increments each day", + "stages": [ + { + "name": "10% rollout on day 1", + "conditions": [ + { + "kind": "schedule", + "scheduleKind": "relative", // or "absolute" + // If "scheduleKind" is "absolute", set "executionDate"; + // "waitDuration" and "waitDurationUnit" will be ignored + "waitDuration": 2, + "waitDurationUnit": "calendarDay" + }, + { + "kind": "ld-approval", + "notifyMemberIds": [ "507f1f77bcf86cd799439011" ], + "notifyTeamKeys": [ "team-key-123abc" ] + } + ], + "action": { + "instructions": [ + { + "kind": "turnFlagOn" + }, + { + "kind": "updateFallthroughVariationOrRollout", + "rolloutWeights": { + "452f5fb5-7320-4ba3-81a1-8f4324f79d49": 90000, + "fc15f6a4-05d3-4aa4-a997-446be461345d": 10000 + } + } + ] + } + } + ] +} +``` +
+ +### Creating a workflow by applying a workflow template + +You can also create a workflow by applying a workflow template. If you pass a valid workflow template key as the `templateKey` query parameter with the request, the API will attempt to create a new workflow with the stages defined in the workflow template with the corresponding key. + +#### Applicability of stages +Templates are created in the context of a particular flag in a particular environment in a particular project. However, because workflows created from a template can be applied to any project, environment, and flag, some steps of the workflow may need to be updated in order to be applicable for the target resource. + +You can pass a `dryRun` query parameter to tell the API to return a report of which steps of the workflow template are applicable in the target project/environment/flag, and which will need to be updated. When the `dryRun` query parameter is present the response body includes a `meta` property that holds a list of parameters that could potentially be inapplicable for the target resource. Each of these parameters will include a `valid` field. You will need to update any invalid parameters in order to create the new workflow. You can do this using the `parameters` property, which overrides the workflow template parameters. + +#### Overriding template parameters +You can use the `parameters` property in the request body to tell the API to override the specified workflow template parameters with new values that are specific to your target project/environment/flag. + +
+Click to expand example + +_Example request body_ +```json +{ + "name": "workflow created from my-template", + "description": "description of my workflow", + "parameters": [ + { + "_id": "62cf2bc4cadbeb7697943f3b", + "path": "/clauses/0/values", + "default": { + "value": ["updated-segment"] + } + }, + { + "_id": "62cf2bc4cadbeb7697943f3d", + "path": "/variationId", + "default": { + "value": "abcd1234-abcd-1234-abcd-1234abcd12" + } + } + ] +} +``` +
+ +If there are any steps in the template that are not applicable to the target resource, the workflow will not be created, and the `meta` property will be included in the response body detailing which parameters need to be updated. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param projectKey The project key + @param featureFlagKey The feature flag key + @param environmentKey The environment key + @return ApiPostWorkflowRequest +*/ +func (a *WorkflowsApiService) PostWorkflow(ctx context.Context, projectKey string, featureFlagKey string, environmentKey string) ApiPostWorkflowRequest { + return ApiPostWorkflowRequest{ + ApiService: a, + ctx: ctx, + projectKey: projectKey, + featureFlagKey: featureFlagKey, + environmentKey: environmentKey, + } +} + +// Execute executes the request +// @return CustomWorkflowOutput +func (a *WorkflowsApiService) PostWorkflowExecute(r ApiPostWorkflowRequest) (*CustomWorkflowOutput, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CustomWorkflowOutput + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "WorkflowsApiService.PostWorkflow") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/api/v2/projects/{projectKey}/flags/{featureFlagKey}/environments/{environmentKey}/workflows" + localVarPath = strings.Replace(localVarPath, "{"+"projectKey"+"}", url.PathEscape(parameterToString(r.projectKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"featureFlagKey"+"}", url.PathEscape(parameterToString(r.featureFlagKey, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"environmentKey"+"}", url.PathEscape(parameterToString(r.environmentKey, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + if r.customWorkflowInput == nil { + return localVarReturnValue, nil, reportError("customWorkflowInput is required and must be specified") + } + + if r.templateKey != nil { + localVarQueryParams.Add("templateKey", parameterToString(*r.templateKey, "")) + } + if r.dryRun != nil { + localVarQueryParams.Add("dryRun", parameterToString(*r.dryRun, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.customWorkflowInput + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["ApiKey"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v InvalidRequestErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v UnauthorizedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v ForbiddenErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v NotFoundErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 429 { + var v RateLimitedErrorRep + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/client.go b/vendor/github.com/launchdarkly/api-client-go/v17/client.go new file mode 100644 index 00000000..1b285e96 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/client.go @@ -0,0 +1,720 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "mime/multipart" + "net/http" + "net/http/httputil" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + "golang.org/x/oauth2" +) + +var ( + jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`) + xmlCheck = regexp.MustCompile(`(?i:(?:application|text)/xml)`) +) + +// APIClient manages communication with the LaunchDarkly REST API API v2.0 +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + cfg *Configuration + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // API Services + + AIConfigsBetaApi AIConfigsBetaApi + + AccessTokensApi AccessTokensApi + + AccountMembersApi AccountMembersApi + + AccountMembersBetaApi AccountMembersBetaApi + + AccountUsageBetaApi AccountUsageBetaApi + + AnnouncementsApi AnnouncementsApi + + ApplicationsBetaApi ApplicationsBetaApi + + ApprovalsApi ApprovalsApi + + ApprovalsBetaApi ApprovalsBetaApi + + AuditLogApi AuditLogApi + + CodeReferencesApi CodeReferencesApi + + ContextSettingsApi ContextSettingsApi + + ContextsApi ContextsApi + + CustomRolesApi CustomRolesApi + + DataExportDestinationsApi DataExportDestinationsApi + + EnvironmentsApi EnvironmentsApi + + ExperimentsApi ExperimentsApi + + FeatureFlagsApi FeatureFlagsApi + + FeatureFlagsBetaApi FeatureFlagsBetaApi + + FlagImportConfigurationsBetaApi FlagImportConfigurationsBetaApi + + FlagLinksBetaApi FlagLinksBetaApi + + FlagTriggersApi FlagTriggersApi + + FollowFlagsApi FollowFlagsApi + + HoldoutsBetaApi HoldoutsBetaApi + + InsightsChartsBetaApi InsightsChartsBetaApi + + InsightsDeploymentsBetaApi InsightsDeploymentsBetaApi + + InsightsFlagEventsBetaApi InsightsFlagEventsBetaApi + + InsightsPullRequestsBetaApi InsightsPullRequestsBetaApi + + InsightsRepositoriesBetaApi InsightsRepositoriesBetaApi + + InsightsScoresBetaApi InsightsScoresBetaApi + + IntegrationAuditLogSubscriptionsApi IntegrationAuditLogSubscriptionsApi + + IntegrationDeliveryConfigurationsBetaApi IntegrationDeliveryConfigurationsBetaApi + + IntegrationsBetaApi IntegrationsBetaApi + + LayersApi LayersApi + + MetricsApi MetricsApi + + MetricsBetaApi MetricsBetaApi + + OAuth2ClientsApi OAuth2ClientsApi + + OtherApi OtherApi + + PersistentStoreIntegrationsBetaApi PersistentStoreIntegrationsBetaApi + + ProjectsApi ProjectsApi + + RelayProxyConfigurationsApi RelayProxyConfigurationsApi + + ReleasePipelinesBetaApi ReleasePipelinesBetaApi + + ReleasesBetaApi ReleasesBetaApi + + ScheduledChangesApi ScheduledChangesApi + + SegmentsApi SegmentsApi + + TagsApi TagsApi + + TeamsApi TeamsApi + + TeamsBetaApi TeamsBetaApi + + UserSettingsApi UserSettingsApi + + UsersApi UsersApi + + UsersBetaApi UsersBetaApi + + WebhooksApi WebhooksApi + + WorkflowTemplatesApi WorkflowTemplatesApi + + WorkflowsApi WorkflowsApi +} + +type service struct { + client *APIClient +} + +// NewAPIClient creates a new API client. Requires a userAgent string describing your application. +// optionally a custom http.Client to allow for advanced features such as caching. +func NewAPIClient(cfg *Configuration) *APIClient { + if cfg.HTTPClient == nil { + cfg.HTTPClient = http.DefaultClient + } + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + + // API Services + c.AIConfigsBetaApi = (*AIConfigsBetaApiService)(&c.common) + c.AccessTokensApi = (*AccessTokensApiService)(&c.common) + c.AccountMembersApi = (*AccountMembersApiService)(&c.common) + c.AccountMembersBetaApi = (*AccountMembersBetaApiService)(&c.common) + c.AccountUsageBetaApi = (*AccountUsageBetaApiService)(&c.common) + c.AnnouncementsApi = (*AnnouncementsApiService)(&c.common) + c.ApplicationsBetaApi = (*ApplicationsBetaApiService)(&c.common) + c.ApprovalsApi = (*ApprovalsApiService)(&c.common) + c.ApprovalsBetaApi = (*ApprovalsBetaApiService)(&c.common) + c.AuditLogApi = (*AuditLogApiService)(&c.common) + c.CodeReferencesApi = (*CodeReferencesApiService)(&c.common) + c.ContextSettingsApi = (*ContextSettingsApiService)(&c.common) + c.ContextsApi = (*ContextsApiService)(&c.common) + c.CustomRolesApi = (*CustomRolesApiService)(&c.common) + c.DataExportDestinationsApi = (*DataExportDestinationsApiService)(&c.common) + c.EnvironmentsApi = (*EnvironmentsApiService)(&c.common) + c.ExperimentsApi = (*ExperimentsApiService)(&c.common) + c.FeatureFlagsApi = (*FeatureFlagsApiService)(&c.common) + c.FeatureFlagsBetaApi = (*FeatureFlagsBetaApiService)(&c.common) + c.FlagImportConfigurationsBetaApi = (*FlagImportConfigurationsBetaApiService)(&c.common) + c.FlagLinksBetaApi = (*FlagLinksBetaApiService)(&c.common) + c.FlagTriggersApi = (*FlagTriggersApiService)(&c.common) + c.FollowFlagsApi = (*FollowFlagsApiService)(&c.common) + c.HoldoutsBetaApi = (*HoldoutsBetaApiService)(&c.common) + c.InsightsChartsBetaApi = (*InsightsChartsBetaApiService)(&c.common) + c.InsightsDeploymentsBetaApi = (*InsightsDeploymentsBetaApiService)(&c.common) + c.InsightsFlagEventsBetaApi = (*InsightsFlagEventsBetaApiService)(&c.common) + c.InsightsPullRequestsBetaApi = (*InsightsPullRequestsBetaApiService)(&c.common) + c.InsightsRepositoriesBetaApi = (*InsightsRepositoriesBetaApiService)(&c.common) + c.InsightsScoresBetaApi = (*InsightsScoresBetaApiService)(&c.common) + c.IntegrationAuditLogSubscriptionsApi = (*IntegrationAuditLogSubscriptionsApiService)(&c.common) + c.IntegrationDeliveryConfigurationsBetaApi = (*IntegrationDeliveryConfigurationsBetaApiService)(&c.common) + c.IntegrationsBetaApi = (*IntegrationsBetaApiService)(&c.common) + c.LayersApi = (*LayersApiService)(&c.common) + c.MetricsApi = (*MetricsApiService)(&c.common) + c.MetricsBetaApi = (*MetricsBetaApiService)(&c.common) + c.OAuth2ClientsApi = (*OAuth2ClientsApiService)(&c.common) + c.OtherApi = (*OtherApiService)(&c.common) + c.PersistentStoreIntegrationsBetaApi = (*PersistentStoreIntegrationsBetaApiService)(&c.common) + c.ProjectsApi = (*ProjectsApiService)(&c.common) + c.RelayProxyConfigurationsApi = (*RelayProxyConfigurationsApiService)(&c.common) + c.ReleasePipelinesBetaApi = (*ReleasePipelinesBetaApiService)(&c.common) + c.ReleasesBetaApi = (*ReleasesBetaApiService)(&c.common) + c.ScheduledChangesApi = (*ScheduledChangesApiService)(&c.common) + c.SegmentsApi = (*SegmentsApiService)(&c.common) + c.TagsApi = (*TagsApiService)(&c.common) + c.TeamsApi = (*TeamsApiService)(&c.common) + c.TeamsBetaApi = (*TeamsBetaApiService)(&c.common) + c.UserSettingsApi = (*UserSettingsApiService)(&c.common) + c.UsersApi = (*UsersApiService)(&c.common) + c.UsersBetaApi = (*UsersBetaApiService)(&c.common) + c.WebhooksApi = (*WebhooksApiService)(&c.common) + c.WorkflowTemplatesApi = (*WorkflowTemplatesApiService)(&c.common) + c.WorkflowsApi = (*WorkflowsApiService)(&c.common) + + return c +} + +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insensitive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.ToLower(a) == strings.ToLower(needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +// parameterToString convert interface{} parameters to string, using a delimiter if format is provided. +func parameterToString(obj interface{}, collectionFormat string) string { + var delimiter string + + switch collectionFormat { + case "pipes": + delimiter = "|" + case "ssv": + delimiter = " " + case "tsv": + delimiter = "\t" + case "csv": + delimiter = "," + } + + if reflect.TypeOf(obj).Kind() == reflect.Slice { + return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]") + } else if t, ok := obj.(time.Time); ok { + return t.Format(time.RFC3339) + } + + return fmt.Sprintf("%v", obj) +} + +// helper for converting interface{} parameters to json strings +func parameterToJson(obj interface{}) (string, error) { + jsonBuf, err := json.Marshal(obj) + if err != nil { + return "", err + } + return string(jsonBuf), err +} + +// callAPI do the request. +func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { + if c.cfg.Debug { + dump, err := httputil.DumpRequestOut(request, true) + if err != nil { + return nil, err + } + log.Printf("\n%s\n", string(dump)) + } + + resp, err := c.cfg.HTTPClient.Do(request) + if err != nil { + return resp, err + } + + if c.cfg.Debug { + dump, err := httputil.DumpResponse(resp, true) + if err != nil { + return resp, err + } + log.Printf("\n%s\n", string(dump)) + } + return resp, err +} + +// Allow modification of underlying config for alternate implementations and testing +// Caution: modifying the configuration while live can cause data races and potentially unwanted behavior +func (c *APIClient) GetConfig() *Configuration { + return c.cfg +} + +type formFile struct { + fileBytes []byte + fileName string + formFileName string +} + +// prepareRequest build the request +func (c *APIClient) prepareRequest( + ctx context.Context, + path string, method string, + postBody interface{}, + headerParams map[string]string, + queryParams url.Values, + formParams url.Values, + formFiles []formFile) (localVarRequest *http.Request, err error) { + + var body *bytes.Buffer + + // Detect postBody type and post. + if postBody != nil { + contentType := headerParams["Content-Type"] + if contentType == "" { + contentType = detectContentType(postBody) + headerParams["Content-Type"] = contentType + } + + body, err = setBody(postBody, contentType) + if err != nil { + return nil, err + } + } + + // add form parameters and file if available. + if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(formFiles) > 0) { + if body != nil { + return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + } + body = &bytes.Buffer{} + w := multipart.NewWriter(body) + + for k, v := range formParams { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return nil, err + } + } else { // form value + w.WriteField(k, iv) + } + } + } + for _, formFile := range formFiles { + if len(formFile.fileBytes) > 0 && formFile.fileName != "" { + w.Boundary() + part, err := w.CreateFormFile(formFile.formFileName, filepath.Base(formFile.fileName)) + if err != nil { + return nil, err + } + _, err = part.Write(formFile.fileBytes) + if err != nil { + return nil, err + } + } + } + + // Set the Boundary in the Content-Type + headerParams["Content-Type"] = w.FormDataContentType() + + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + w.Close() + } + + if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { + if body != nil { + return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + } + body = &bytes.Buffer{} + body.WriteString(formParams.Encode()) + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Override request host, if applicable + if c.cfg.Host != "" { + url.Host = c.cfg.Host + } + + // Override request scheme, if applicable + if c.cfg.Scheme != "" { + url.Scheme = c.cfg.Scheme + } + + // Adding Query Param + query := url.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + url.RawQuery = query.Encode() + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, url.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers[h] = []string{v} + } + localVarRequest.Header = headers + } + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent) + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + + // Walk through any authentication. + + // OAuth2 authentication + if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok { + // We were able to grab an oauth2 token from the context + var latestToken *oauth2.Token + if latestToken, err = tok.Token(); err != nil { + return nil, err + } + + latestToken.SetAuthHeader(localVarRequest) + } + + // Basic HTTP Authentication + if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok { + localVarRequest.SetBasicAuth(auth.UserName, auth.Password) + } + + // AccessToken Authentication + if auth, ok := ctx.Value(ContextAccessToken).(string); ok { + localVarRequest.Header.Add("Authorization", "Bearer "+auth) + } + + } + + for header, value := range c.cfg.DefaultHeader { + localVarRequest.Header.Add(header, value) + } + return localVarRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if len(b) == 0 { + return nil + } + if s, ok := v.(*string); ok { + *s = string(b) + return nil + } + if f, ok := v.(**os.File); ok { + *f, err = ioutil.TempFile("", "HttpClientFile") + if err != nil { + return + } + _, err = (*f).Write(b) + if err != nil { + return + } + _, err = (*f).Seek(0, io.SeekStart) + return + } + if xmlCheck.MatchString(contentType) { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } + if jsonCheck.MatchString(contentType) { + if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas + if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined + if err = unmarshalObj.UnmarshalJSON(b); err != nil { + return err + } + } else { + return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") + } + } else if err = json.Unmarshal(b, v); err != nil { // simple model + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Prevent trying to import "fmt" +func reportError(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} + +// A wrapper for strict JSON decoding +func newStrictDecoder(data []byte) *json.Decoder { + dec := json.NewDecoder(bytes.NewBuffer(data)) + dec.DisallowUnknownFields() + return dec +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if fp, ok := body.(**os.File); ok { + _, err = bodyBuf.ReadFrom(*fp) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if jsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if xmlCheck.MatchString(contentType) { + err = xml.NewEncoder(bodyBuf).Encode(body) + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("Invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } else { + expires = now.Add(lifetime) + } + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericOpenAPIError Provides access to the body, error and model on returned errors. +type GenericOpenAPIError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericOpenAPIError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericOpenAPIError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericOpenAPIError) Model() interface{} { + return e.model +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/configuration.go b/vendor/github.com/launchdarkly/api-client-go/v17/configuration.go new file mode 100644 index 00000000..ee532fa1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/configuration.go @@ -0,0 +1,235 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "context" + "fmt" + "net/http" + "strings" +) + +// contextKeys are used to identify the type of value in the context. +// Since these are string, it is possible to get a short description of the +// context key for logging and debugging using key.String(). + +type contextKey string + +func (c contextKey) String() string { + return "auth " + string(c) +} + +var ( + // ContextOAuth2 takes an oauth2.TokenSource as authentication for the request. + ContextOAuth2 = contextKey("token") + + // ContextBasicAuth takes BasicAuth as authentication for the request. + ContextBasicAuth = contextKey("basic") + + // ContextAccessToken takes a string oauth2 access token as authentication for the request. + ContextAccessToken = contextKey("accesstoken") + + // ContextAPIKeys takes a string apikey as authentication for the request + ContextAPIKeys = contextKey("apiKeys") + + // ContextHttpSignatureAuth takes HttpSignatureAuth as authentication for the request. + ContextHttpSignatureAuth = contextKey("httpsignature") + + // ContextServerIndex uses a server configuration from the index. + ContextServerIndex = contextKey("serverIndex") + + // ContextOperationServerIndices uses a server configuration from the index mapping. + ContextOperationServerIndices = contextKey("serverOperationIndices") + + // ContextServerVariables overrides a server configuration variables. + ContextServerVariables = contextKey("serverVariables") + + // ContextOperationServerVariables overrides a server configuration variables using operation specific values. + ContextOperationServerVariables = contextKey("serverOperationVariables") +) + +// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth +type BasicAuth struct { + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` +} + +// APIKey provides API key based authentication to a request passed via context using ContextAPIKey +type APIKey struct { + Key string + Prefix string +} + +// ServerVariable stores the information about a server variable +type ServerVariable struct { + Description string + DefaultValue string + EnumValues []string +} + +// ServerConfiguration stores the information about a server +type ServerConfiguration struct { + URL string + Description string + Variables map[string]ServerVariable +} + +// ServerConfigurations stores multiple ServerConfiguration items +type ServerConfigurations []ServerConfiguration + +// Configuration stores the configuration of the API client +type Configuration struct { + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + Debug bool `json:"debug,omitempty"` + Servers ServerConfigurations + OperationServers map[string]ServerConfigurations + HTTPClient *http.Client +} + +// NewConfiguration returns a new Configuration object +func NewConfiguration() *Configuration { + cfg := &Configuration{ + DefaultHeader: make(map[string]string), + UserAgent: "OpenAPI-Generator/17/go", + Debug: false, + Servers: ServerConfigurations{ + { + URL: "https://app.launchdarkly.com", + Description: " Default", + }, + { + URL: "https://app.launchdarkly.us", + Description: " Federal", + }, + }, + OperationServers: map[string]ServerConfigurations{ + }, + } + return cfg +} + +// AddDefaultHeader adds a new HTTP header to the default header in the request +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} + +// URL formats template on a index using given variables +func (sc ServerConfigurations) URL(index int, variables map[string]string) (string, error) { + if index < 0 || len(sc) <= index { + return "", fmt.Errorf("Index %v out of range %v", index, len(sc)-1) + } + server := sc[index] + url := server.URL + + // go through variables and replace placeholders + for name, variable := range server.Variables { + if value, ok := variables[name]; ok { + found := bool(len(variable.EnumValues) == 0) + for _, enumValue := range variable.EnumValues { + if value == enumValue { + found = true + } + } + if !found { + return "", fmt.Errorf("The variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues) + } + url = strings.Replace(url, "{"+name+"}", value, -1) + } else { + url = strings.Replace(url, "{"+name+"}", variable.DefaultValue, -1) + } + } + return url, nil +} + +// ServerURL returns URL based on server settings +func (c *Configuration) ServerURL(index int, variables map[string]string) (string, error) { + return c.Servers.URL(index, variables) +} + +func getServerIndex(ctx context.Context) (int, error) { + si := ctx.Value(ContextServerIndex) + if si != nil { + if index, ok := si.(int); ok { + return index, nil + } + return 0, reportError("Invalid type %T should be int", si) + } + return 0, nil +} + +func getServerOperationIndex(ctx context.Context, endpoint string) (int, error) { + osi := ctx.Value(ContextOperationServerIndices) + if osi != nil { + if operationIndices, ok := osi.(map[string]int); !ok { + return 0, reportError("Invalid type %T should be map[string]int", osi) + } else { + index, ok := operationIndices[endpoint] + if ok { + return index, nil + } + } + } + return getServerIndex(ctx) +} + +func getServerVariables(ctx context.Context) (map[string]string, error) { + sv := ctx.Value(ContextServerVariables) + if sv != nil { + if variables, ok := sv.(map[string]string); ok { + return variables, nil + } + return nil, reportError("ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv) + } + return nil, nil +} + +func getServerOperationVariables(ctx context.Context, endpoint string) (map[string]string, error) { + osv := ctx.Value(ContextOperationServerVariables) + if osv != nil { + if operationVariables, ok := osv.(map[string]map[string]string); !ok { + return nil, reportError("ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string", osv) + } else { + variables, ok := operationVariables[endpoint] + if ok { + return variables, nil + } + } + } + return getServerVariables(ctx) +} + +// ServerURLWithContext returns a new server URL given an endpoint +func (c *Configuration) ServerURLWithContext(ctx context.Context, endpoint string) (string, error) { + sc, ok := c.OperationServers[endpoint] + if !ok { + sc = c.Servers + } + + if ctx == nil { + return sc.URL(0, nil) + } + + index, err := getServerOperationIndex(ctx, endpoint) + if err != nil { + return "", err + } + + variables, err := getServerOperationVariables(ctx, endpoint) + if err != nil { + return "", err + } + + return sc.URL(index, variables) +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/git_push.sh b/vendor/github.com/launchdarkly/api-client-go/v17/git_push.sh new file mode 100644 index 00000000..8afd2ecd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="launchdarkly" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="api-client-go" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access.go new file mode 100644 index 00000000..9581901e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Access struct for Access +type Access struct { + Denied []AccessDenied `json:"denied"` + Allowed []AccessAllowedRep `json:"allowed"` +} + +// NewAccess instantiates a new Access object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccess(denied []AccessDenied, allowed []AccessAllowedRep) *Access { + this := Access{} + this.Denied = denied + this.Allowed = allowed + return &this +} + +// NewAccessWithDefaults instantiates a new Access object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessWithDefaults() *Access { + this := Access{} + return &this +} + +// GetDenied returns the Denied field value +func (o *Access) GetDenied() []AccessDenied { + if o == nil { + var ret []AccessDenied + return ret + } + + return o.Denied +} + +// GetDeniedOk returns a tuple with the Denied field value +// and a boolean to check if the value has been set. +func (o *Access) GetDeniedOk() ([]AccessDenied, bool) { + if o == nil { + return nil, false + } + return o.Denied, true +} + +// SetDenied sets field value +func (o *Access) SetDenied(v []AccessDenied) { + o.Denied = v +} + +// GetAllowed returns the Allowed field value +func (o *Access) GetAllowed() []AccessAllowedRep { + if o == nil { + var ret []AccessAllowedRep + return ret + } + + return o.Allowed +} + +// GetAllowedOk returns a tuple with the Allowed field value +// and a boolean to check if the value has been set. +func (o *Access) GetAllowedOk() ([]AccessAllowedRep, bool) { + if o == nil { + return nil, false + } + return o.Allowed, true +} + +// SetAllowed sets field value +func (o *Access) SetAllowed(v []AccessAllowedRep) { + o.Allowed = v +} + +func (o Access) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["denied"] = o.Denied + } + if true { + toSerialize["allowed"] = o.Allowed + } + return json.Marshal(toSerialize) +} + +type NullableAccess struct { + value *Access + isSet bool +} + +func (v NullableAccess) Get() *Access { + return v.value +} + +func (v *NullableAccess) Set(val *Access) { + v.value = val + v.isSet = true +} + +func (v NullableAccess) IsSet() bool { + return v.isSet +} + +func (v *NullableAccess) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccess(val *Access) *NullableAccess { + return &NullableAccess{value: val, isSet: true} +} + +func (v NullableAccess) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccess) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_reason.go new file mode 100644 index 00000000..eac09306 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AccessAllowedReason struct for AccessAllowedReason +type AccessAllowedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAccessAllowedReason instantiates a new AccessAllowedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccessAllowedReason(effect string) *AccessAllowedReason { + this := AccessAllowedReason{} + this.Effect = effect + return &this +} + +// NewAccessAllowedReasonWithDefaults instantiates a new AccessAllowedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessAllowedReasonWithDefaults() *AccessAllowedReason { + this := AccessAllowedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AccessAllowedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AccessAllowedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AccessAllowedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AccessAllowedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AccessAllowedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AccessAllowedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AccessAllowedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AccessAllowedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AccessAllowedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AccessAllowedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AccessAllowedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AccessAllowedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AccessAllowedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AccessAllowedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AccessAllowedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessAllowedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AccessAllowedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AccessAllowedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AccessAllowedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAccessAllowedReason struct { + value *AccessAllowedReason + isSet bool +} + +func (v NullableAccessAllowedReason) Get() *AccessAllowedReason { + return v.value +} + +func (v *NullableAccessAllowedReason) Set(val *AccessAllowedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAccessAllowedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAccessAllowedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccessAllowedReason(val *AccessAllowedReason) *NullableAccessAllowedReason { + return &NullableAccessAllowedReason{value: val, isSet: true} +} + +func (v NullableAccessAllowedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccessAllowedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_rep.go new file mode 100644 index 00000000..f9cf7d0b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_allowed_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AccessAllowedRep struct for AccessAllowedRep +type AccessAllowedRep struct { + Action string `json:"action"` + Reason AccessAllowedReason `json:"reason"` +} + +// NewAccessAllowedRep instantiates a new AccessAllowedRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccessAllowedRep(action string, reason AccessAllowedReason) *AccessAllowedRep { + this := AccessAllowedRep{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAccessAllowedRepWithDefaults instantiates a new AccessAllowedRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessAllowedRepWithDefaults() *AccessAllowedRep { + this := AccessAllowedRep{} + return &this +} + +// GetAction returns the Action field value +func (o *AccessAllowedRep) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AccessAllowedRep) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AccessAllowedRep) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AccessAllowedRep) GetReason() AccessAllowedReason { + if o == nil { + var ret AccessAllowedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AccessAllowedRep) GetReasonOk() (*AccessAllowedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AccessAllowedRep) SetReason(v AccessAllowedReason) { + o.Reason = v +} + +func (o AccessAllowedRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAccessAllowedRep struct { + value *AccessAllowedRep + isSet bool +} + +func (v NullableAccessAllowedRep) Get() *AccessAllowedRep { + return v.value +} + +func (v *NullableAccessAllowedRep) Set(val *AccessAllowedRep) { + v.value = val + v.isSet = true +} + +func (v NullableAccessAllowedRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAccessAllowedRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccessAllowedRep(val *AccessAllowedRep) *NullableAccessAllowedRep { + return &NullableAccessAllowedRep{value: val, isSet: true} +} + +func (v NullableAccessAllowedRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccessAllowedRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied.go new file mode 100644 index 00000000..0b7cfea2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AccessDenied struct for AccessDenied +type AccessDenied struct { + Action string `json:"action"` + Reason AccessDeniedReason `json:"reason"` +} + +// NewAccessDenied instantiates a new AccessDenied object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccessDenied(action string, reason AccessDeniedReason) *AccessDenied { + this := AccessDenied{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAccessDeniedWithDefaults instantiates a new AccessDenied object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessDeniedWithDefaults() *AccessDenied { + this := AccessDenied{} + return &this +} + +// GetAction returns the Action field value +func (o *AccessDenied) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AccessDenied) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AccessDenied) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AccessDenied) GetReason() AccessDeniedReason { + if o == nil { + var ret AccessDeniedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AccessDenied) GetReasonOk() (*AccessDeniedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AccessDenied) SetReason(v AccessDeniedReason) { + o.Reason = v +} + +func (o AccessDenied) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAccessDenied struct { + value *AccessDenied + isSet bool +} + +func (v NullableAccessDenied) Get() *AccessDenied { + return v.value +} + +func (v *NullableAccessDenied) Set(val *AccessDenied) { + v.value = val + v.isSet = true +} + +func (v NullableAccessDenied) IsSet() bool { + return v.isSet +} + +func (v *NullableAccessDenied) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccessDenied(val *AccessDenied) *NullableAccessDenied { + return &NullableAccessDenied{value: val, isSet: true} +} + +func (v NullableAccessDenied) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccessDenied) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied_reason.go new file mode 100644 index 00000000..a22fa5ca --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_denied_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AccessDeniedReason struct for AccessDeniedReason +type AccessDeniedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAccessDeniedReason instantiates a new AccessDeniedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccessDeniedReason(effect string) *AccessDeniedReason { + this := AccessDeniedReason{} + this.Effect = effect + return &this +} + +// NewAccessDeniedReasonWithDefaults instantiates a new AccessDeniedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessDeniedReasonWithDefaults() *AccessDeniedReason { + this := AccessDeniedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AccessDeniedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AccessDeniedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AccessDeniedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AccessDeniedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AccessDeniedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AccessDeniedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AccessDeniedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AccessDeniedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AccessDeniedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AccessDeniedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AccessDeniedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AccessDeniedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AccessDeniedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AccessDeniedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AccessDeniedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessDeniedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AccessDeniedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AccessDeniedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AccessDeniedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAccessDeniedReason struct { + value *AccessDeniedReason + isSet bool +} + +func (v NullableAccessDeniedReason) Get() *AccessDeniedReason { + return v.value +} + +func (v *NullableAccessDeniedReason) Set(val *AccessDeniedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAccessDeniedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAccessDeniedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccessDeniedReason(val *AccessDeniedReason) *NullableAccessDeniedReason { + return &NullableAccessDeniedReason{value: val, isSet: true} +} + +func (v NullableAccessDeniedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccessDeniedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_access_token_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_token_post.go new file mode 100644 index 00000000..0e5f3f0d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_access_token_post.go @@ -0,0 +1,339 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AccessTokenPost struct for AccessTokenPost +type AccessTokenPost struct { + // A human-friendly name for the access token + Name *string `json:"name,omitempty"` + // A description for the access token + Description *string `json:"description,omitempty"` + // Built-in role for the token + Role *string `json:"role,omitempty"` + // A list of custom role IDs to use as access limits for the access token + CustomRoleIds []string `json:"customRoleIds,omitempty"` + // A JSON array of statements represented as JSON objects with three attributes: effect, resources, actions. May be used in place of a built-in or custom role. + InlineRole []StatementPost `json:"inlineRole,omitempty"` + // Whether the token is a service token + ServiceToken *bool `json:"serviceToken,omitempty"` + // The default API version for this token + DefaultApiVersion *int32 `json:"defaultApiVersion,omitempty"` +} + +// NewAccessTokenPost instantiates a new AccessTokenPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAccessTokenPost() *AccessTokenPost { + this := AccessTokenPost{} + return &this +} + +// NewAccessTokenPostWithDefaults instantiates a new AccessTokenPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAccessTokenPostWithDefaults() *AccessTokenPost { + this := AccessTokenPost{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *AccessTokenPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *AccessTokenPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *AccessTokenPost) SetName(v string) { + o.Name = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *AccessTokenPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *AccessTokenPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *AccessTokenPost) SetDescription(v string) { + o.Description = &v +} + +// GetRole returns the Role field value if set, zero value otherwise. +func (o *AccessTokenPost) GetRole() string { + if o == nil || o.Role == nil { + var ret string + return ret + } + return *o.Role +} + +// GetRoleOk returns a tuple with the Role field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetRoleOk() (*string, bool) { + if o == nil || o.Role == nil { + return nil, false + } + return o.Role, true +} + +// HasRole returns a boolean if a field has been set. +func (o *AccessTokenPost) HasRole() bool { + if o != nil && o.Role != nil { + return true + } + + return false +} + +// SetRole gets a reference to the given string and assigns it to the Role field. +func (o *AccessTokenPost) SetRole(v string) { + o.Role = &v +} + +// GetCustomRoleIds returns the CustomRoleIds field value if set, zero value otherwise. +func (o *AccessTokenPost) GetCustomRoleIds() []string { + if o == nil || o.CustomRoleIds == nil { + var ret []string + return ret + } + return o.CustomRoleIds +} + +// GetCustomRoleIdsOk returns a tuple with the CustomRoleIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetCustomRoleIdsOk() ([]string, bool) { + if o == nil || o.CustomRoleIds == nil { + return nil, false + } + return o.CustomRoleIds, true +} + +// HasCustomRoleIds returns a boolean if a field has been set. +func (o *AccessTokenPost) HasCustomRoleIds() bool { + if o != nil && o.CustomRoleIds != nil { + return true + } + + return false +} + +// SetCustomRoleIds gets a reference to the given []string and assigns it to the CustomRoleIds field. +func (o *AccessTokenPost) SetCustomRoleIds(v []string) { + o.CustomRoleIds = v +} + +// GetInlineRole returns the InlineRole field value if set, zero value otherwise. +func (o *AccessTokenPost) GetInlineRole() []StatementPost { + if o == nil || o.InlineRole == nil { + var ret []StatementPost + return ret + } + return o.InlineRole +} + +// GetInlineRoleOk returns a tuple with the InlineRole field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetInlineRoleOk() ([]StatementPost, bool) { + if o == nil || o.InlineRole == nil { + return nil, false + } + return o.InlineRole, true +} + +// HasInlineRole returns a boolean if a field has been set. +func (o *AccessTokenPost) HasInlineRole() bool { + if o != nil && o.InlineRole != nil { + return true + } + + return false +} + +// SetInlineRole gets a reference to the given []StatementPost and assigns it to the InlineRole field. +func (o *AccessTokenPost) SetInlineRole(v []StatementPost) { + o.InlineRole = v +} + +// GetServiceToken returns the ServiceToken field value if set, zero value otherwise. +func (o *AccessTokenPost) GetServiceToken() bool { + if o == nil || o.ServiceToken == nil { + var ret bool + return ret + } + return *o.ServiceToken +} + +// GetServiceTokenOk returns a tuple with the ServiceToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetServiceTokenOk() (*bool, bool) { + if o == nil || o.ServiceToken == nil { + return nil, false + } + return o.ServiceToken, true +} + +// HasServiceToken returns a boolean if a field has been set. +func (o *AccessTokenPost) HasServiceToken() bool { + if o != nil && o.ServiceToken != nil { + return true + } + + return false +} + +// SetServiceToken gets a reference to the given bool and assigns it to the ServiceToken field. +func (o *AccessTokenPost) SetServiceToken(v bool) { + o.ServiceToken = &v +} + +// GetDefaultApiVersion returns the DefaultApiVersion field value if set, zero value otherwise. +func (o *AccessTokenPost) GetDefaultApiVersion() int32 { + if o == nil || o.DefaultApiVersion == nil { + var ret int32 + return ret + } + return *o.DefaultApiVersion +} + +// GetDefaultApiVersionOk returns a tuple with the DefaultApiVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AccessTokenPost) GetDefaultApiVersionOk() (*int32, bool) { + if o == nil || o.DefaultApiVersion == nil { + return nil, false + } + return o.DefaultApiVersion, true +} + +// HasDefaultApiVersion returns a boolean if a field has been set. +func (o *AccessTokenPost) HasDefaultApiVersion() bool { + if o != nil && o.DefaultApiVersion != nil { + return true + } + + return false +} + +// SetDefaultApiVersion gets a reference to the given int32 and assigns it to the DefaultApiVersion field. +func (o *AccessTokenPost) SetDefaultApiVersion(v int32) { + o.DefaultApiVersion = &v +} + +func (o AccessTokenPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Role != nil { + toSerialize["role"] = o.Role + } + if o.CustomRoleIds != nil { + toSerialize["customRoleIds"] = o.CustomRoleIds + } + if o.InlineRole != nil { + toSerialize["inlineRole"] = o.InlineRole + } + if o.ServiceToken != nil { + toSerialize["serviceToken"] = o.ServiceToken + } + if o.DefaultApiVersion != nil { + toSerialize["defaultApiVersion"] = o.DefaultApiVersion + } + return json.Marshal(toSerialize) +} + +type NullableAccessTokenPost struct { + value *AccessTokenPost + isSet bool +} + +func (v NullableAccessTokenPost) Get() *AccessTokenPost { + return v.value +} + +func (v *NullableAccessTokenPost) Set(val *AccessTokenPost) { + v.value = val + v.isSet = true +} + +func (v NullableAccessTokenPost) IsSet() bool { + return v.isSet +} + +func (v *NullableAccessTokenPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAccessTokenPost(val *AccessTokenPost) *NullableAccessTokenPost { + return &NullableAccessTokenPost{value: val, isSet: true} +} + +func (v NullableAccessTokenPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAccessTokenPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_action_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_action_input.go new file mode 100644 index 00000000..b7542ad4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_action_input.go @@ -0,0 +1,118 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ActionInput struct for ActionInput +type ActionInput struct { + // An array of instructions for the stage. Each object in the array uses the semantic patch format for updating a feature flag. + Instructions interface{} `json:"instructions,omitempty"` +} + +// NewActionInput instantiates a new ActionInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewActionInput() *ActionInput { + this := ActionInput{} + return &this +} + +// NewActionInputWithDefaults instantiates a new ActionInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewActionInputWithDefaults() *ActionInput { + this := ActionInput{} + return &this +} + +// GetInstructions returns the Instructions field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *ActionInput) GetInstructions() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ActionInput) GetInstructionsOk() (*interface{}, bool) { + if o == nil || o.Instructions == nil { + return nil, false + } + return &o.Instructions, true +} + +// HasInstructions returns a boolean if a field has been set. +func (o *ActionInput) HasInstructions() bool { + if o != nil && o.Instructions != nil { + return true + } + + return false +} + +// SetInstructions gets a reference to the given interface{} and assigns it to the Instructions field. +func (o *ActionInput) SetInstructions(v interface{}) { + o.Instructions = v +} + +func (o ActionInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Instructions != nil { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableActionInput struct { + value *ActionInput + isSet bool +} + +func (v NullableActionInput) Get() *ActionInput { + return v.value +} + +func (v *NullableActionInput) Set(val *ActionInput) { + v.value = val + v.isSet = true +} + +func (v NullableActionInput) IsSet() bool { + return v.isSet +} + +func (v *NullableActionInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableActionInput(val *ActionInput) *NullableActionInput { + return &NullableActionInput{value: val, isSet: true} +} + +func (v NullableActionInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableActionInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_action_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_action_output.go new file mode 100644 index 00000000..07a8fac4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_action_output.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ActionOutput struct for ActionOutput +type ActionOutput struct { + // The type of action for this stage + Kind string `json:"kind"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewActionOutput instantiates a new ActionOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewActionOutput(kind string, instructions []map[string]interface{}) *ActionOutput { + this := ActionOutput{} + this.Kind = kind + this.Instructions = instructions + return &this +} + +// NewActionOutputWithDefaults instantiates a new ActionOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewActionOutputWithDefaults() *ActionOutput { + this := ActionOutput{} + return &this +} + +// GetKind returns the Kind field value +func (o *ActionOutput) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ActionOutput) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ActionOutput) SetKind(v string) { + o.Kind = v +} + +// GetInstructions returns the Instructions field value +func (o *ActionOutput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *ActionOutput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *ActionOutput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o ActionOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableActionOutput struct { + value *ActionOutput + isSet bool +} + +func (v NullableActionOutput) Get() *ActionOutput { + return v.value +} + +func (v *NullableActionOutput) Set(val *ActionOutput) { + v.value = val + v.isSet = true +} + +func (v NullableActionOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableActionOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableActionOutput(val *ActionOutput) *NullableActionOutput { + return &NullableActionOutput{value: val, isSet: true} +} + +func (v NullableActionOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableActionOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config.go new file mode 100644 index 00000000..4a3b5bcd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config.go @@ -0,0 +1,420 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfig struct for AIConfig +type AIConfig struct { + Access *AiConfigsAccess `json:"_access,omitempty"` + Links *ParentAndSelfLinks `json:"_links,omitempty"` + Description string `json:"description"` + Key string `json:"key"` + Maintainer *AIConfigMaintainer `json:"_maintainer,omitempty"` + Name string `json:"name"` + Tags []string `json:"tags"` + Version int32 `json:"version"` + Variations []AIConfigVariation `json:"variations"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` +} + +// NewAIConfig instantiates a new AIConfig object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfig(description string, key string, name string, tags []string, version int32, variations []AIConfigVariation, createdAt int64, updatedAt int64) *AIConfig { + this := AIConfig{} + this.Description = description + this.Key = key + this.Name = name + this.Tags = tags + this.Version = version + this.Variations = variations + this.CreatedAt = createdAt + this.UpdatedAt = updatedAt + return &this +} + +// NewAIConfigWithDefaults instantiates a new AIConfig object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigWithDefaults() *AIConfig { + this := AIConfig{} + return &this +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *AIConfig) GetAccess() AiConfigsAccess { + if o == nil || o.Access == nil { + var ret AiConfigsAccess + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfig) GetAccessOk() (*AiConfigsAccess, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *AIConfig) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given AiConfigsAccess and assigns it to the Access field. +func (o *AIConfig) SetAccess(v AiConfigsAccess) { + o.Access = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *AIConfig) GetLinks() ParentAndSelfLinks { + if o == nil || o.Links == nil { + var ret ParentAndSelfLinks + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfig) GetLinksOk() (*ParentAndSelfLinks, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *AIConfig) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given ParentAndSelfLinks and assigns it to the Links field. +func (o *AIConfig) SetLinks(v ParentAndSelfLinks) { + o.Links = &v +} + +// GetDescription returns the Description field value +func (o *AIConfig) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *AIConfig) SetDescription(v string) { + o.Description = v +} + +// GetKey returns the Key field value +func (o *AIConfig) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *AIConfig) SetKey(v string) { + o.Key = v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *AIConfig) GetMaintainer() AIConfigMaintainer { + if o == nil || o.Maintainer == nil { + var ret AIConfigMaintainer + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfig) GetMaintainerOk() (*AIConfigMaintainer, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *AIConfig) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given AIConfigMaintainer and assigns it to the Maintainer field. +func (o *AIConfig) SetMaintainer(v AIConfigMaintainer) { + o.Maintainer = &v +} + +// GetName returns the Name field value +func (o *AIConfig) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AIConfig) SetName(v string) { + o.Name = v +} + +// GetTags returns the Tags field value +func (o *AIConfig) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *AIConfig) SetTags(v []string) { + o.Tags = v +} + +// GetVersion returns the Version field value +func (o *AIConfig) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *AIConfig) SetVersion(v int32) { + o.Version = v +} + +// GetVariations returns the Variations field value +func (o *AIConfig) GetVariations() []AIConfigVariation { + if o == nil { + var ret []AIConfigVariation + return ret + } + + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetVariationsOk() ([]AIConfigVariation, bool) { + if o == nil { + return nil, false + } + return o.Variations, true +} + +// SetVariations sets field value +func (o *AIConfig) SetVariations(v []AIConfigVariation) { + o.Variations = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *AIConfig) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *AIConfig) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetUpdatedAt returns the UpdatedAt field value +func (o *AIConfig) GetUpdatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.UpdatedAt +} + +// GetUpdatedAtOk returns a tuple with the UpdatedAt field value +// and a boolean to check if the value has been set. +func (o *AIConfig) GetUpdatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.UpdatedAt, true +} + +// SetUpdatedAt sets field value +func (o *AIConfig) SetUpdatedAt(v int64) { + o.UpdatedAt = v +} + +func (o AIConfig) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["version"] = o.Version + } + if true { + toSerialize["variations"] = o.Variations + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if true { + toSerialize["updatedAt"] = o.UpdatedAt + } + return json.Marshal(toSerialize) +} + +type NullableAIConfig struct { + value *AIConfig + isSet bool +} + +func (v NullableAIConfig) Get() *AIConfig { + return v.value +} + +func (v *NullableAIConfig) Set(val *AIConfig) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfig) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfig) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfig(val *AIConfig) *NullableAIConfig { + return &NullableAIConfig{value: val, isSet: true} +} + +func (v NullableAIConfig) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfig) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config__maintainer.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config__maintainer.go new file mode 100644 index 00000000..4c661ee4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config__maintainer.go @@ -0,0 +1,149 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "fmt" +) + +// AIConfigMaintainer - struct for AIConfigMaintainer +type AIConfigMaintainer struct { + AiConfigsMaintainerTeam *AiConfigsMaintainerTeam + MaintainerMember *MaintainerMember +} + +// AiConfigsMaintainerTeamAsAIConfigMaintainer is a convenience function that returns AiConfigsMaintainerTeam wrapped in AIConfigMaintainer +func AiConfigsMaintainerTeamAsAIConfigMaintainer(v *AiConfigsMaintainerTeam) AIConfigMaintainer { + return AIConfigMaintainer{ + AiConfigsMaintainerTeam: v, + } +} + +// MaintainerMemberAsAIConfigMaintainer is a convenience function that returns MaintainerMember wrapped in AIConfigMaintainer +func MaintainerMemberAsAIConfigMaintainer(v *MaintainerMember) AIConfigMaintainer { + return AIConfigMaintainer{ + MaintainerMember: v, + } +} + + +// Unmarshal JSON data into one of the pointers in the struct +func (dst *AIConfigMaintainer) UnmarshalJSON(data []byte) error { + var err error + match := 0 + // try to unmarshal data into AiConfigsMaintainerTeam + err = newStrictDecoder(data).Decode(&dst.AiConfigsMaintainerTeam) + if err == nil { + jsonAiConfigsMaintainerTeam, _ := json.Marshal(dst.AiConfigsMaintainerTeam) + if string(jsonAiConfigsMaintainerTeam) == "{}" { // empty struct + dst.AiConfigsMaintainerTeam = nil + } else { + match++ + } + } else { + dst.AiConfigsMaintainerTeam = nil + } + + // try to unmarshal data into MaintainerMember + err = newStrictDecoder(data).Decode(&dst.MaintainerMember) + if err == nil { + jsonMaintainerMember, _ := json.Marshal(dst.MaintainerMember) + if string(jsonMaintainerMember) == "{}" { // empty struct + dst.MaintainerMember = nil + } else { + match++ + } + } else { + dst.MaintainerMember = nil + } + + if match > 1 { // more than 1 match + // reset to nil + dst.AiConfigsMaintainerTeam = nil + dst.MaintainerMember = nil + + return fmt.Errorf("Data matches more than one schema in oneOf(AIConfigMaintainer)") + } else if match == 1 { + return nil // exactly one match + } else { // no match + return fmt.Errorf("Data failed to match schemas in oneOf(AIConfigMaintainer)") + } +} + +// Marshal data from the first non-nil pointers in the struct to JSON +func (src AIConfigMaintainer) MarshalJSON() ([]byte, error) { + if src.AiConfigsMaintainerTeam != nil { + return json.Marshal(&src.AiConfigsMaintainerTeam) + } + + if src.MaintainerMember != nil { + return json.Marshal(&src.MaintainerMember) + } + + return nil, nil // no data in oneOf schemas +} + +// Get the actual instance +func (obj *AIConfigMaintainer) GetActualInstance() (interface{}) { + if obj == nil { + return nil + } + if obj.AiConfigsMaintainerTeam != nil { + return obj.AiConfigsMaintainerTeam + } + + if obj.MaintainerMember != nil { + return obj.MaintainerMember + } + + // all schemas are nil + return nil +} + +type NullableAIConfigMaintainer struct { + value *AIConfigMaintainer + isSet bool +} + +func (v NullableAIConfigMaintainer) Get() *AIConfigMaintainer { + return v.value +} + +func (v *NullableAIConfigMaintainer) Set(val *AIConfigMaintainer) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigMaintainer) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigMaintainer) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigMaintainer(val *AIConfigMaintainer) *NullableAIConfigMaintainer { + return &NullableAIConfigMaintainer{value: val, isSet: true} +} + +func (v NullableAIConfigMaintainer) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigMaintainer) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_patch.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_patch.go new file mode 100644 index 00000000..a4ba75a4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_patch.go @@ -0,0 +1,260 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigPatch struct for AIConfigPatch +type AIConfigPatch struct { + Description *string `json:"description,omitempty"` + MaintainerId *string `json:"maintainerId,omitempty"` + MaintainerTeamKey *string `json:"maintainerTeamKey,omitempty"` + Name *string `json:"name,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +// NewAIConfigPatch instantiates a new AIConfigPatch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigPatch() *AIConfigPatch { + this := AIConfigPatch{} + return &this +} + +// NewAIConfigPatchWithDefaults instantiates a new AIConfigPatch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigPatchWithDefaults() *AIConfigPatch { + this := AIConfigPatch{} + return &this +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *AIConfigPatch) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPatch) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *AIConfigPatch) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *AIConfigPatch) SetDescription(v string) { + o.Description = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *AIConfigPatch) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPatch) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *AIConfigPatch) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *AIConfigPatch) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainerTeamKey returns the MaintainerTeamKey field value if set, zero value otherwise. +func (o *AIConfigPatch) GetMaintainerTeamKey() string { + if o == nil || o.MaintainerTeamKey == nil { + var ret string + return ret + } + return *o.MaintainerTeamKey +} + +// GetMaintainerTeamKeyOk returns a tuple with the MaintainerTeamKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPatch) GetMaintainerTeamKeyOk() (*string, bool) { + if o == nil || o.MaintainerTeamKey == nil { + return nil, false + } + return o.MaintainerTeamKey, true +} + +// HasMaintainerTeamKey returns a boolean if a field has been set. +func (o *AIConfigPatch) HasMaintainerTeamKey() bool { + if o != nil && o.MaintainerTeamKey != nil { + return true + } + + return false +} + +// SetMaintainerTeamKey gets a reference to the given string and assigns it to the MaintainerTeamKey field. +func (o *AIConfigPatch) SetMaintainerTeamKey(v string) { + o.MaintainerTeamKey = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *AIConfigPatch) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPatch) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *AIConfigPatch) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *AIConfigPatch) SetName(v string) { + o.Name = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *AIConfigPatch) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPatch) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *AIConfigPatch) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *AIConfigPatch) SetTags(v []string) { + o.Tags = v +} + +func (o AIConfigPatch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.MaintainerTeamKey != nil { + toSerialize["maintainerTeamKey"] = o.MaintainerTeamKey + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigPatch struct { + value *AIConfigPatch + isSet bool +} + +func (v NullableAIConfigPatch) Get() *AIConfigPatch { + return v.value +} + +func (v *NullableAIConfigPatch) Set(val *AIConfigPatch) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigPatch) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigPatch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigPatch(val *AIConfigPatch) *NullableAIConfigPatch { + return &NullableAIConfigPatch{value: val, isSet: true} +} + +func (v NullableAIConfigPatch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigPatch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_post.go new file mode 100644 index 00000000..a9e1f20d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_post.go @@ -0,0 +1,286 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigPost struct for AIConfigPost +type AIConfigPost struct { + Description *string `json:"description,omitempty"` + Key string `json:"key"` + MaintainerId *string `json:"maintainerId,omitempty"` + MaintainerTeamKey *string `json:"maintainerTeamKey,omitempty"` + Name string `json:"name"` + Tags []string `json:"tags,omitempty"` +} + +// NewAIConfigPost instantiates a new AIConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigPost(key string, name string) *AIConfigPost { + this := AIConfigPost{} + var description string = "" + this.Description = &description + this.Key = key + this.Name = name + return &this +} + +// NewAIConfigPostWithDefaults instantiates a new AIConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigPostWithDefaults() *AIConfigPost { + this := AIConfigPost{} + var description string = "" + this.Description = &description + return &this +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *AIConfigPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *AIConfigPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *AIConfigPost) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *AIConfigPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *AIConfigPost) SetKey(v string) { + o.Key = v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *AIConfigPost) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *AIConfigPost) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *AIConfigPost) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainerTeamKey returns the MaintainerTeamKey field value if set, zero value otherwise. +func (o *AIConfigPost) GetMaintainerTeamKey() string { + if o == nil || o.MaintainerTeamKey == nil { + var ret string + return ret + } + return *o.MaintainerTeamKey +} + +// GetMaintainerTeamKeyOk returns a tuple with the MaintainerTeamKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetMaintainerTeamKeyOk() (*string, bool) { + if o == nil || o.MaintainerTeamKey == nil { + return nil, false + } + return o.MaintainerTeamKey, true +} + +// HasMaintainerTeamKey returns a boolean if a field has been set. +func (o *AIConfigPost) HasMaintainerTeamKey() bool { + if o != nil && o.MaintainerTeamKey != nil { + return true + } + + return false +} + +// SetMaintainerTeamKey gets a reference to the given string and assigns it to the MaintainerTeamKey field. +func (o *AIConfigPost) SetMaintainerTeamKey(v string) { + o.MaintainerTeamKey = &v +} + +// GetName returns the Name field value +func (o *AIConfigPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AIConfigPost) SetName(v string) { + o.Name = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *AIConfigPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *AIConfigPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *AIConfigPost) SetTags(v []string) { + o.Tags = v +} + +func (o AIConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.MaintainerTeamKey != nil { + toSerialize["maintainerTeamKey"] = o.MaintainerTeamKey + } + if true { + toSerialize["name"] = o.Name + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigPost struct { + value *AIConfigPost + isSet bool +} + +func (v NullableAIConfigPost) Get() *AIConfigPost { + return v.value +} + +func (v *NullableAIConfigPost) Set(val *AIConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigPost(val *AIConfigPost) *NullableAIConfigPost { + return &NullableAIConfigPost{value: val, isSet: true} +} + +func (v NullableAIConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation.go new file mode 100644 index 00000000..556d8f48 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation.go @@ -0,0 +1,434 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigVariation struct for AIConfigVariation +type AIConfigVariation struct { + Links *ParentLink `json:"_links,omitempty"` + Key string `json:"key"` + Messages []Message `json:"messages"` + Model map[string]interface{} `json:"model"` + ModelConfigKey *string `json:"modelConfigKey,omitempty"` + Name string `json:"name"` + CreatedAt int64 `json:"createdAt"` + Version int32 `json:"version"` + State *string `json:"state,omitempty"` + ArchivedAt *int64 `json:"_archivedAt,omitempty"` + PublishedAt *int64 `json:"_publishedAt,omitempty"` +} + +// NewAIConfigVariation instantiates a new AIConfigVariation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigVariation(key string, messages []Message, model map[string]interface{}, name string, createdAt int64, version int32) *AIConfigVariation { + this := AIConfigVariation{} + this.Key = key + this.Messages = messages + this.Model = model + this.Name = name + this.CreatedAt = createdAt + this.Version = version + return &this +} + +// NewAIConfigVariationWithDefaults instantiates a new AIConfigVariation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigVariationWithDefaults() *AIConfigVariation { + this := AIConfigVariation{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *AIConfigVariation) GetLinks() ParentLink { + if o == nil || o.Links == nil { + var ret ParentLink + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetLinksOk() (*ParentLink, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *AIConfigVariation) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given ParentLink and assigns it to the Links field. +func (o *AIConfigVariation) SetLinks(v ParentLink) { + o.Links = &v +} + +// GetKey returns the Key field value +func (o *AIConfigVariation) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *AIConfigVariation) SetKey(v string) { + o.Key = v +} + +// GetMessages returns the Messages field value +func (o *AIConfigVariation) GetMessages() []Message { + if o == nil { + var ret []Message + return ret + } + + return o.Messages +} + +// GetMessagesOk returns a tuple with the Messages field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetMessagesOk() ([]Message, bool) { + if o == nil { + return nil, false + } + return o.Messages, true +} + +// SetMessages sets field value +func (o *AIConfigVariation) SetMessages(v []Message) { + o.Messages = v +} + +// GetModel returns the Model field value +func (o *AIConfigVariation) GetModel() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Model +} + +// GetModelOk returns a tuple with the Model field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetModelOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Model, true +} + +// SetModel sets field value +func (o *AIConfigVariation) SetModel(v map[string]interface{}) { + o.Model = v +} + +// GetModelConfigKey returns the ModelConfigKey field value if set, zero value otherwise. +func (o *AIConfigVariation) GetModelConfigKey() string { + if o == nil || o.ModelConfigKey == nil { + var ret string + return ret + } + return *o.ModelConfigKey +} + +// GetModelConfigKeyOk returns a tuple with the ModelConfigKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetModelConfigKeyOk() (*string, bool) { + if o == nil || o.ModelConfigKey == nil { + return nil, false + } + return o.ModelConfigKey, true +} + +// HasModelConfigKey returns a boolean if a field has been set. +func (o *AIConfigVariation) HasModelConfigKey() bool { + if o != nil && o.ModelConfigKey != nil { + return true + } + + return false +} + +// SetModelConfigKey gets a reference to the given string and assigns it to the ModelConfigKey field. +func (o *AIConfigVariation) SetModelConfigKey(v string) { + o.ModelConfigKey = &v +} + +// GetName returns the Name field value +func (o *AIConfigVariation) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AIConfigVariation) SetName(v string) { + o.Name = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *AIConfigVariation) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *AIConfigVariation) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetVersion returns the Version field value +func (o *AIConfigVariation) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *AIConfigVariation) SetVersion(v int32) { + o.Version = v +} + +// GetState returns the State field value if set, zero value otherwise. +func (o *AIConfigVariation) GetState() string { + if o == nil || o.State == nil { + var ret string + return ret + } + return *o.State +} + +// GetStateOk returns a tuple with the State field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetStateOk() (*string, bool) { + if o == nil || o.State == nil { + return nil, false + } + return o.State, true +} + +// HasState returns a boolean if a field has been set. +func (o *AIConfigVariation) HasState() bool { + if o != nil && o.State != nil { + return true + } + + return false +} + +// SetState gets a reference to the given string and assigns it to the State field. +func (o *AIConfigVariation) SetState(v string) { + o.State = &v +} + +// GetArchivedAt returns the ArchivedAt field value if set, zero value otherwise. +func (o *AIConfigVariation) GetArchivedAt() int64 { + if o == nil || o.ArchivedAt == nil { + var ret int64 + return ret + } + return *o.ArchivedAt +} + +// GetArchivedAtOk returns a tuple with the ArchivedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetArchivedAtOk() (*int64, bool) { + if o == nil || o.ArchivedAt == nil { + return nil, false + } + return o.ArchivedAt, true +} + +// HasArchivedAt returns a boolean if a field has been set. +func (o *AIConfigVariation) HasArchivedAt() bool { + if o != nil && o.ArchivedAt != nil { + return true + } + + return false +} + +// SetArchivedAt gets a reference to the given int64 and assigns it to the ArchivedAt field. +func (o *AIConfigVariation) SetArchivedAt(v int64) { + o.ArchivedAt = &v +} + +// GetPublishedAt returns the PublishedAt field value if set, zero value otherwise. +func (o *AIConfigVariation) GetPublishedAt() int64 { + if o == nil || o.PublishedAt == nil { + var ret int64 + return ret + } + return *o.PublishedAt +} + +// GetPublishedAtOk returns a tuple with the PublishedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariation) GetPublishedAtOk() (*int64, bool) { + if o == nil || o.PublishedAt == nil { + return nil, false + } + return o.PublishedAt, true +} + +// HasPublishedAt returns a boolean if a field has been set. +func (o *AIConfigVariation) HasPublishedAt() bool { + if o != nil && o.PublishedAt != nil { + return true + } + + return false +} + +// SetPublishedAt gets a reference to the given int64 and assigns it to the PublishedAt field. +func (o *AIConfigVariation) SetPublishedAt(v int64) { + o.PublishedAt = &v +} + +func (o AIConfigVariation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["messages"] = o.Messages + } + if true { + toSerialize["model"] = o.Model + } + if o.ModelConfigKey != nil { + toSerialize["modelConfigKey"] = o.ModelConfigKey + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if true { + toSerialize["version"] = o.Version + } + if o.State != nil { + toSerialize["state"] = o.State + } + if o.ArchivedAt != nil { + toSerialize["_archivedAt"] = o.ArchivedAt + } + if o.PublishedAt != nil { + toSerialize["_publishedAt"] = o.PublishedAt + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigVariation struct { + value *AIConfigVariation + isSet bool +} + +func (v NullableAIConfigVariation) Get() *AIConfigVariation { + return v.value +} + +func (v *NullableAIConfigVariation) Set(val *AIConfigVariation) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigVariation) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigVariation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigVariation(val *AIConfigVariation) *NullableAIConfigVariation { + return &NullableAIConfigVariation{value: val, isSet: true} +} + +func (v NullableAIConfigVariation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigVariation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_patch.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_patch.go new file mode 100644 index 00000000..8879b0fc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_patch.go @@ -0,0 +1,297 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigVariationPatch struct for AIConfigVariationPatch +type AIConfigVariationPatch struct { + Messages []Message `json:"messages,omitempty"` + Model map[string]interface{} `json:"model,omitempty"` + ModelConfigKey *string `json:"modelConfigKey,omitempty"` + Name *string `json:"name,omitempty"` + Published *bool `json:"published,omitempty"` + // One of 'archived', 'published' + State *string `json:"state,omitempty"` +} + +// NewAIConfigVariationPatch instantiates a new AIConfigVariationPatch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigVariationPatch() *AIConfigVariationPatch { + this := AIConfigVariationPatch{} + return &this +} + +// NewAIConfigVariationPatchWithDefaults instantiates a new AIConfigVariationPatch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigVariationPatchWithDefaults() *AIConfigVariationPatch { + this := AIConfigVariationPatch{} + return &this +} + +// GetMessages returns the Messages field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetMessages() []Message { + if o == nil || o.Messages == nil { + var ret []Message + return ret + } + return o.Messages +} + +// GetMessagesOk returns a tuple with the Messages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetMessagesOk() ([]Message, bool) { + if o == nil || o.Messages == nil { + return nil, false + } + return o.Messages, true +} + +// HasMessages returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasMessages() bool { + if o != nil && o.Messages != nil { + return true + } + + return false +} + +// SetMessages gets a reference to the given []Message and assigns it to the Messages field. +func (o *AIConfigVariationPatch) SetMessages(v []Message) { + o.Messages = v +} + +// GetModel returns the Model field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetModel() map[string]interface{} { + if o == nil || o.Model == nil { + var ret map[string]interface{} + return ret + } + return o.Model +} + +// GetModelOk returns a tuple with the Model field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetModelOk() (map[string]interface{}, bool) { + if o == nil || o.Model == nil { + return nil, false + } + return o.Model, true +} + +// HasModel returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasModel() bool { + if o != nil && o.Model != nil { + return true + } + + return false +} + +// SetModel gets a reference to the given map[string]interface{} and assigns it to the Model field. +func (o *AIConfigVariationPatch) SetModel(v map[string]interface{}) { + o.Model = v +} + +// GetModelConfigKey returns the ModelConfigKey field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetModelConfigKey() string { + if o == nil || o.ModelConfigKey == nil { + var ret string + return ret + } + return *o.ModelConfigKey +} + +// GetModelConfigKeyOk returns a tuple with the ModelConfigKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetModelConfigKeyOk() (*string, bool) { + if o == nil || o.ModelConfigKey == nil { + return nil, false + } + return o.ModelConfigKey, true +} + +// HasModelConfigKey returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasModelConfigKey() bool { + if o != nil && o.ModelConfigKey != nil { + return true + } + + return false +} + +// SetModelConfigKey gets a reference to the given string and assigns it to the ModelConfigKey field. +func (o *AIConfigVariationPatch) SetModelConfigKey(v string) { + o.ModelConfigKey = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *AIConfigVariationPatch) SetName(v string) { + o.Name = &v +} + +// GetPublished returns the Published field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetPublished() bool { + if o == nil || o.Published == nil { + var ret bool + return ret + } + return *o.Published +} + +// GetPublishedOk returns a tuple with the Published field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetPublishedOk() (*bool, bool) { + if o == nil || o.Published == nil { + return nil, false + } + return o.Published, true +} + +// HasPublished returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasPublished() bool { + if o != nil && o.Published != nil { + return true + } + + return false +} + +// SetPublished gets a reference to the given bool and assigns it to the Published field. +func (o *AIConfigVariationPatch) SetPublished(v bool) { + o.Published = &v +} + +// GetState returns the State field value if set, zero value otherwise. +func (o *AIConfigVariationPatch) GetState() string { + if o == nil || o.State == nil { + var ret string + return ret + } + return *o.State +} + +// GetStateOk returns a tuple with the State field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPatch) GetStateOk() (*string, bool) { + if o == nil || o.State == nil { + return nil, false + } + return o.State, true +} + +// HasState returns a boolean if a field has been set. +func (o *AIConfigVariationPatch) HasState() bool { + if o != nil && o.State != nil { + return true + } + + return false +} + +// SetState gets a reference to the given string and assigns it to the State field. +func (o *AIConfigVariationPatch) SetState(v string) { + o.State = &v +} + +func (o AIConfigVariationPatch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Messages != nil { + toSerialize["messages"] = o.Messages + } + if o.Model != nil { + toSerialize["model"] = o.Model + } + if o.ModelConfigKey != nil { + toSerialize["modelConfigKey"] = o.ModelConfigKey + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Published != nil { + toSerialize["published"] = o.Published + } + if o.State != nil { + toSerialize["state"] = o.State + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigVariationPatch struct { + value *AIConfigVariationPatch + isSet bool +} + +func (v NullableAIConfigVariationPatch) Get() *AIConfigVariationPatch { + return v.value +} + +func (v *NullableAIConfigVariationPatch) Set(val *AIConfigVariationPatch) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigVariationPatch) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigVariationPatch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigVariationPatch(val *AIConfigVariationPatch) *NullableAIConfigVariationPatch { + return &NullableAIConfigVariationPatch{value: val, isSet: true} +} + +func (v NullableAIConfigVariationPatch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigVariationPatch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_post.go new file mode 100644 index 00000000..715b3883 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variation_post.go @@ -0,0 +1,232 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigVariationPost struct for AIConfigVariationPost +type AIConfigVariationPost struct { + Key string `json:"key"` + Messages []Message `json:"messages"` + Model map[string]interface{} `json:"model"` + Name string `json:"name"` + ModelConfigKey *string `json:"modelConfigKey,omitempty"` +} + +// NewAIConfigVariationPost instantiates a new AIConfigVariationPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigVariationPost(key string, messages []Message, model map[string]interface{}, name string) *AIConfigVariationPost { + this := AIConfigVariationPost{} + this.Key = key + this.Messages = messages + this.Model = model + this.Name = name + return &this +} + +// NewAIConfigVariationPostWithDefaults instantiates a new AIConfigVariationPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigVariationPostWithDefaults() *AIConfigVariationPost { + this := AIConfigVariationPost{} + return &this +} + +// GetKey returns the Key field value +func (o *AIConfigVariationPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *AIConfigVariationPost) SetKey(v string) { + o.Key = v +} + +// GetMessages returns the Messages field value +func (o *AIConfigVariationPost) GetMessages() []Message { + if o == nil { + var ret []Message + return ret + } + + return o.Messages +} + +// GetMessagesOk returns a tuple with the Messages field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPost) GetMessagesOk() ([]Message, bool) { + if o == nil { + return nil, false + } + return o.Messages, true +} + +// SetMessages sets field value +func (o *AIConfigVariationPost) SetMessages(v []Message) { + o.Messages = v +} + +// GetModel returns the Model field value +func (o *AIConfigVariationPost) GetModel() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Model +} + +// GetModelOk returns a tuple with the Model field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPost) GetModelOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Model, true +} + +// SetModel sets field value +func (o *AIConfigVariationPost) SetModel(v map[string]interface{}) { + o.Model = v +} + +// GetName returns the Name field value +func (o *AIConfigVariationPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AIConfigVariationPost) SetName(v string) { + o.Name = v +} + +// GetModelConfigKey returns the ModelConfigKey field value if set, zero value otherwise. +func (o *AIConfigVariationPost) GetModelConfigKey() string { + if o == nil || o.ModelConfigKey == nil { + var ret string + return ret + } + return *o.ModelConfigKey +} + +// GetModelConfigKeyOk returns a tuple with the ModelConfigKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigVariationPost) GetModelConfigKeyOk() (*string, bool) { + if o == nil || o.ModelConfigKey == nil { + return nil, false + } + return o.ModelConfigKey, true +} + +// HasModelConfigKey returns a boolean if a field has been set. +func (o *AIConfigVariationPost) HasModelConfigKey() bool { + if o != nil && o.ModelConfigKey != nil { + return true + } + + return false +} + +// SetModelConfigKey gets a reference to the given string and assigns it to the ModelConfigKey field. +func (o *AIConfigVariationPost) SetModelConfigKey(v string) { + o.ModelConfigKey = &v +} + +func (o AIConfigVariationPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["messages"] = o.Messages + } + if true { + toSerialize["model"] = o.Model + } + if true { + toSerialize["name"] = o.Name + } + if o.ModelConfigKey != nil { + toSerialize["modelConfigKey"] = o.ModelConfigKey + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigVariationPost struct { + value *AIConfigVariationPost + isSet bool +} + +func (v NullableAIConfigVariationPost) Get() *AIConfigVariationPost { + return v.value +} + +func (v *NullableAIConfigVariationPost) Set(val *AIConfigVariationPost) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigVariationPost) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigVariationPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigVariationPost(val *AIConfigVariationPost) *NullableAIConfigVariationPost { + return &NullableAIConfigVariationPost{value: val, isSet: true} +} + +func (v NullableAIConfigVariationPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigVariationPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variations_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variations_response.go new file mode 100644 index 00000000..a9a6e657 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_config_variations_response.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigVariationsResponse struct for AIConfigVariationsResponse +type AIConfigVariationsResponse struct { + Items []AIConfigVariation `json:"items"` + TotalCount int32 `json:"totalCount"` +} + +// NewAIConfigVariationsResponse instantiates a new AIConfigVariationsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigVariationsResponse(items []AIConfigVariation, totalCount int32) *AIConfigVariationsResponse { + this := AIConfigVariationsResponse{} + this.Items = items + this.TotalCount = totalCount + return &this +} + +// NewAIConfigVariationsResponseWithDefaults instantiates a new AIConfigVariationsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigVariationsResponseWithDefaults() *AIConfigVariationsResponse { + this := AIConfigVariationsResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *AIConfigVariationsResponse) GetItems() []AIConfigVariation { + if o == nil { + var ret []AIConfigVariation + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationsResponse) GetItemsOk() ([]AIConfigVariation, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *AIConfigVariationsResponse) SetItems(v []AIConfigVariation) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *AIConfigVariationsResponse) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *AIConfigVariationsResponse) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *AIConfigVariationsResponse) SetTotalCount(v int32) { + o.TotalCount = v +} + +func (o AIConfigVariationsResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigVariationsResponse struct { + value *AIConfigVariationsResponse + isSet bool +} + +func (v NullableAIConfigVariationsResponse) Get() *AIConfigVariationsResponse { + return v.value +} + +func (v *NullableAIConfigVariationsResponse) Set(val *AIConfigVariationsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigVariationsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigVariationsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigVariationsResponse(val *AIConfigVariationsResponse) *NullableAIConfigVariationsResponse { + return &NullableAIConfigVariationsResponse{value: val, isSet: true} +} + +func (v NullableAIConfigVariationsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigVariationsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs.go new file mode 100644 index 00000000..47d11559 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs.go @@ -0,0 +1,174 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AIConfigs struct for AIConfigs +type AIConfigs struct { + Links *PaginatedLinks `json:"_links,omitempty"` + Items []AIConfig `json:"items"` + TotalCount int32 `json:"totalCount"` +} + +// NewAIConfigs instantiates a new AIConfigs object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAIConfigs(items []AIConfig, totalCount int32) *AIConfigs { + this := AIConfigs{} + this.Items = items + this.TotalCount = totalCount + return &this +} + +// NewAIConfigsWithDefaults instantiates a new AIConfigs object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAIConfigsWithDefaults() *AIConfigs { + this := AIConfigs{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *AIConfigs) GetLinks() PaginatedLinks { + if o == nil || o.Links == nil { + var ret PaginatedLinks + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AIConfigs) GetLinksOk() (*PaginatedLinks, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *AIConfigs) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given PaginatedLinks and assigns it to the Links field. +func (o *AIConfigs) SetLinks(v PaginatedLinks) { + o.Links = &v +} + +// GetItems returns the Items field value +func (o *AIConfigs) GetItems() []AIConfig { + if o == nil { + var ret []AIConfig + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *AIConfigs) GetItemsOk() ([]AIConfig, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *AIConfigs) SetItems(v []AIConfig) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *AIConfigs) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *AIConfigs) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *AIConfigs) SetTotalCount(v int32) { + o.TotalCount = v +} + +func (o AIConfigs) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableAIConfigs struct { + value *AIConfigs + isSet bool +} + +func (v NullableAIConfigs) Get() *AIConfigs { + return v.value +} + +func (v *NullableAIConfigs) Set(val *AIConfigs) { + v.value = val + v.isSet = true +} + +func (v NullableAIConfigs) IsSet() bool { + return v.isSet +} + +func (v *NullableAIConfigs) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAIConfigs(val *AIConfigs) *NullableAIConfigs { + return &NullableAIConfigs{value: val, isSet: true} +} + +func (v NullableAIConfigs) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAIConfigs) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access.go new file mode 100644 index 00000000..750bc68b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsAccess struct for AiConfigsAccess +type AiConfigsAccess struct { + Denied []AiConfigsAccessDenied `json:"denied"` + Allowed []AiConfigsAccessAllowedRep `json:"allowed"` +} + +// NewAiConfigsAccess instantiates a new AiConfigsAccess object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsAccess(denied []AiConfigsAccessDenied, allowed []AiConfigsAccessAllowedRep) *AiConfigsAccess { + this := AiConfigsAccess{} + this.Denied = denied + this.Allowed = allowed + return &this +} + +// NewAiConfigsAccessWithDefaults instantiates a new AiConfigsAccess object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsAccessWithDefaults() *AiConfigsAccess { + this := AiConfigsAccess{} + return &this +} + +// GetDenied returns the Denied field value +func (o *AiConfigsAccess) GetDenied() []AiConfigsAccessDenied { + if o == nil { + var ret []AiConfigsAccessDenied + return ret + } + + return o.Denied +} + +// GetDeniedOk returns a tuple with the Denied field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccess) GetDeniedOk() ([]AiConfigsAccessDenied, bool) { + if o == nil { + return nil, false + } + return o.Denied, true +} + +// SetDenied sets field value +func (o *AiConfigsAccess) SetDenied(v []AiConfigsAccessDenied) { + o.Denied = v +} + +// GetAllowed returns the Allowed field value +func (o *AiConfigsAccess) GetAllowed() []AiConfigsAccessAllowedRep { + if o == nil { + var ret []AiConfigsAccessAllowedRep + return ret + } + + return o.Allowed +} + +// GetAllowedOk returns a tuple with the Allowed field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccess) GetAllowedOk() ([]AiConfigsAccessAllowedRep, bool) { + if o == nil { + return nil, false + } + return o.Allowed, true +} + +// SetAllowed sets field value +func (o *AiConfigsAccess) SetAllowed(v []AiConfigsAccessAllowedRep) { + o.Allowed = v +} + +func (o AiConfigsAccess) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["denied"] = o.Denied + } + if true { + toSerialize["allowed"] = o.Allowed + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsAccess struct { + value *AiConfigsAccess + isSet bool +} + +func (v NullableAiConfigsAccess) Get() *AiConfigsAccess { + return v.value +} + +func (v *NullableAiConfigsAccess) Set(val *AiConfigsAccess) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsAccess) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsAccess) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsAccess(val *AiConfigsAccess) *NullableAiConfigsAccess { + return &NullableAiConfigsAccess{value: val, isSet: true} +} + +func (v NullableAiConfigsAccess) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsAccess) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_reason.go new file mode 100644 index 00000000..10c86193 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsAccessAllowedReason struct for AiConfigsAccessAllowedReason +type AiConfigsAccessAllowedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAiConfigsAccessAllowedReason instantiates a new AiConfigsAccessAllowedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsAccessAllowedReason(effect string) *AiConfigsAccessAllowedReason { + this := AiConfigsAccessAllowedReason{} + this.Effect = effect + return &this +} + +// NewAiConfigsAccessAllowedReasonWithDefaults instantiates a new AiConfigsAccessAllowedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsAccessAllowedReasonWithDefaults() *AiConfigsAccessAllowedReason { + this := AiConfigsAccessAllowedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AiConfigsAccessAllowedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AiConfigsAccessAllowedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AiConfigsAccessAllowedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AiConfigsAccessAllowedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AiConfigsAccessAllowedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AiConfigsAccessAllowedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AiConfigsAccessAllowedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AiConfigsAccessAllowedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AiConfigsAccessAllowedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AiConfigsAccessAllowedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AiConfigsAccessAllowedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AiConfigsAccessAllowedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AiConfigsAccessAllowedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AiConfigsAccessAllowedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AiConfigsAccessAllowedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AiConfigsAccessAllowedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AiConfigsAccessAllowedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AiConfigsAccessAllowedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsAccessAllowedReason struct { + value *AiConfigsAccessAllowedReason + isSet bool +} + +func (v NullableAiConfigsAccessAllowedReason) Get() *AiConfigsAccessAllowedReason { + return v.value +} + +func (v *NullableAiConfigsAccessAllowedReason) Set(val *AiConfigsAccessAllowedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsAccessAllowedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsAccessAllowedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsAccessAllowedReason(val *AiConfigsAccessAllowedReason) *NullableAiConfigsAccessAllowedReason { + return &NullableAiConfigsAccessAllowedReason{value: val, isSet: true} +} + +func (v NullableAiConfigsAccessAllowedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsAccessAllowedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_rep.go new file mode 100644 index 00000000..1f7968a6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_allowed_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsAccessAllowedRep struct for AiConfigsAccessAllowedRep +type AiConfigsAccessAllowedRep struct { + Action string `json:"action"` + Reason AiConfigsAccessAllowedReason `json:"reason"` +} + +// NewAiConfigsAccessAllowedRep instantiates a new AiConfigsAccessAllowedRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsAccessAllowedRep(action string, reason AiConfigsAccessAllowedReason) *AiConfigsAccessAllowedRep { + this := AiConfigsAccessAllowedRep{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAiConfigsAccessAllowedRepWithDefaults instantiates a new AiConfigsAccessAllowedRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsAccessAllowedRepWithDefaults() *AiConfigsAccessAllowedRep { + this := AiConfigsAccessAllowedRep{} + return &this +} + +// GetAction returns the Action field value +func (o *AiConfigsAccessAllowedRep) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedRep) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AiConfigsAccessAllowedRep) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AiConfigsAccessAllowedRep) GetReason() AiConfigsAccessAllowedReason { + if o == nil { + var ret AiConfigsAccessAllowedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessAllowedRep) GetReasonOk() (*AiConfigsAccessAllowedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AiConfigsAccessAllowedRep) SetReason(v AiConfigsAccessAllowedReason) { + o.Reason = v +} + +func (o AiConfigsAccessAllowedRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsAccessAllowedRep struct { + value *AiConfigsAccessAllowedRep + isSet bool +} + +func (v NullableAiConfigsAccessAllowedRep) Get() *AiConfigsAccessAllowedRep { + return v.value +} + +func (v *NullableAiConfigsAccessAllowedRep) Set(val *AiConfigsAccessAllowedRep) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsAccessAllowedRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsAccessAllowedRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsAccessAllowedRep(val *AiConfigsAccessAllowedRep) *NullableAiConfigsAccessAllowedRep { + return &NullableAiConfigsAccessAllowedRep{value: val, isSet: true} +} + +func (v NullableAiConfigsAccessAllowedRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsAccessAllowedRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied.go new file mode 100644 index 00000000..aea26841 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsAccessDenied struct for AiConfigsAccessDenied +type AiConfigsAccessDenied struct { + Action string `json:"action"` + Reason AiConfigsAccessDeniedReason `json:"reason"` +} + +// NewAiConfigsAccessDenied instantiates a new AiConfigsAccessDenied object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsAccessDenied(action string, reason AiConfigsAccessDeniedReason) *AiConfigsAccessDenied { + this := AiConfigsAccessDenied{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAiConfigsAccessDeniedWithDefaults instantiates a new AiConfigsAccessDenied object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsAccessDeniedWithDefaults() *AiConfigsAccessDenied { + this := AiConfigsAccessDenied{} + return &this +} + +// GetAction returns the Action field value +func (o *AiConfigsAccessDenied) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDenied) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AiConfigsAccessDenied) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AiConfigsAccessDenied) GetReason() AiConfigsAccessDeniedReason { + if o == nil { + var ret AiConfigsAccessDeniedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDenied) GetReasonOk() (*AiConfigsAccessDeniedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AiConfigsAccessDenied) SetReason(v AiConfigsAccessDeniedReason) { + o.Reason = v +} + +func (o AiConfigsAccessDenied) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsAccessDenied struct { + value *AiConfigsAccessDenied + isSet bool +} + +func (v NullableAiConfigsAccessDenied) Get() *AiConfigsAccessDenied { + return v.value +} + +func (v *NullableAiConfigsAccessDenied) Set(val *AiConfigsAccessDenied) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsAccessDenied) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsAccessDenied) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsAccessDenied(val *AiConfigsAccessDenied) *NullableAiConfigsAccessDenied { + return &NullableAiConfigsAccessDenied{value: val, isSet: true} +} + +func (v NullableAiConfigsAccessDenied) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsAccessDenied) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied_reason.go new file mode 100644 index 00000000..a9415f93 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_access_denied_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsAccessDeniedReason struct for AiConfigsAccessDeniedReason +type AiConfigsAccessDeniedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAiConfigsAccessDeniedReason instantiates a new AiConfigsAccessDeniedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsAccessDeniedReason(effect string) *AiConfigsAccessDeniedReason { + this := AiConfigsAccessDeniedReason{} + this.Effect = effect + return &this +} + +// NewAiConfigsAccessDeniedReasonWithDefaults instantiates a new AiConfigsAccessDeniedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsAccessDeniedReasonWithDefaults() *AiConfigsAccessDeniedReason { + this := AiConfigsAccessDeniedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AiConfigsAccessDeniedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AiConfigsAccessDeniedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AiConfigsAccessDeniedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AiConfigsAccessDeniedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AiConfigsAccessDeniedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AiConfigsAccessDeniedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AiConfigsAccessDeniedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AiConfigsAccessDeniedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AiConfigsAccessDeniedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AiConfigsAccessDeniedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AiConfigsAccessDeniedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AiConfigsAccessDeniedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AiConfigsAccessDeniedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AiConfigsAccessDeniedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AiConfigsAccessDeniedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsAccessDeniedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AiConfigsAccessDeniedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AiConfigsAccessDeniedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AiConfigsAccessDeniedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsAccessDeniedReason struct { + value *AiConfigsAccessDeniedReason + isSet bool +} + +func (v NullableAiConfigsAccessDeniedReason) Get() *AiConfigsAccessDeniedReason { + return v.value +} + +func (v *NullableAiConfigsAccessDeniedReason) Set(val *AiConfigsAccessDeniedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsAccessDeniedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsAccessDeniedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsAccessDeniedReason(val *AiConfigsAccessDeniedReason) *NullableAiConfigsAccessDeniedReason { + return &NullableAiConfigsAccessDeniedReason{value: val, isSet: true} +} + +func (v NullableAiConfigsAccessDeniedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsAccessDeniedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_link.go new file mode 100644 index 00000000..9646aa61 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_link.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsLink struct for AiConfigsLink +type AiConfigsLink struct { + Href *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NewAiConfigsLink instantiates a new AiConfigsLink object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsLink() *AiConfigsLink { + this := AiConfigsLink{} + return &this +} + +// NewAiConfigsLinkWithDefaults instantiates a new AiConfigsLink object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsLinkWithDefaults() *AiConfigsLink { + this := AiConfigsLink{} + return &this +} + +// GetHref returns the Href field value if set, zero value otherwise. +func (o *AiConfigsLink) GetHref() string { + if o == nil || o.Href == nil { + var ret string + return ret + } + return *o.Href +} + +// GetHrefOk returns a tuple with the Href field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsLink) GetHrefOk() (*string, bool) { + if o == nil || o.Href == nil { + return nil, false + } + return o.Href, true +} + +// HasHref returns a boolean if a field has been set. +func (o *AiConfigsLink) HasHref() bool { + if o != nil && o.Href != nil { + return true + } + + return false +} + +// SetHref gets a reference to the given string and assigns it to the Href field. +func (o *AiConfigsLink) SetHref(v string) { + o.Href = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *AiConfigsLink) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AiConfigsLink) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *AiConfigsLink) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *AiConfigsLink) SetType(v string) { + o.Type = &v +} + +func (o AiConfigsLink) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Href != nil { + toSerialize["href"] = o.Href + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsLink struct { + value *AiConfigsLink + isSet bool +} + +func (v NullableAiConfigsLink) Get() *AiConfigsLink { + return v.value +} + +func (v *NullableAiConfigsLink) Set(val *AiConfigsLink) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsLink) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsLink(val *AiConfigsLink) *NullableAiConfigsLink { + return &NullableAiConfigsLink{value: val, isSet: true} +} + +func (v NullableAiConfigsLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_maintainer_team.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_maintainer_team.go new file mode 100644 index 00000000..233b41c7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ai_configs_maintainer_team.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AiConfigsMaintainerTeam struct for AiConfigsMaintainerTeam +type AiConfigsMaintainerTeam struct { + Key string `json:"key"` + Name string `json:"name"` +} + +// NewAiConfigsMaintainerTeam instantiates a new AiConfigsMaintainerTeam object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAiConfigsMaintainerTeam(key string, name string) *AiConfigsMaintainerTeam { + this := AiConfigsMaintainerTeam{} + this.Key = key + this.Name = name + return &this +} + +// NewAiConfigsMaintainerTeamWithDefaults instantiates a new AiConfigsMaintainerTeam object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAiConfigsMaintainerTeamWithDefaults() *AiConfigsMaintainerTeam { + this := AiConfigsMaintainerTeam{} + return &this +} + +// GetKey returns the Key field value +func (o *AiConfigsMaintainerTeam) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *AiConfigsMaintainerTeam) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *AiConfigsMaintainerTeam) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *AiConfigsMaintainerTeam) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AiConfigsMaintainerTeam) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AiConfigsMaintainerTeam) SetName(v string) { + o.Name = v +} + +func (o AiConfigsMaintainerTeam) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableAiConfigsMaintainerTeam struct { + value *AiConfigsMaintainerTeam + isSet bool +} + +func (v NullableAiConfigsMaintainerTeam) Get() *AiConfigsMaintainerTeam { + return v.value +} + +func (v *NullableAiConfigsMaintainerTeam) Set(val *AiConfigsMaintainerTeam) { + v.value = val + v.isSet = true +} + +func (v NullableAiConfigsMaintainerTeam) IsSet() bool { + return v.isSet +} + +func (v *NullableAiConfigsMaintainerTeam) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAiConfigsMaintainerTeam(val *AiConfigsMaintainerTeam) *NullableAiConfigsMaintainerTeam { + return &NullableAiConfigsMaintainerTeam{value: val, isSet: true} +} + +func (v NullableAiConfigsMaintainerTeam) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAiConfigsMaintainerTeam) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access.go new file mode 100644 index 00000000..967b738b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccess struct for AnnouncementAccess +type AnnouncementAccess struct { + Denied []AnnouncementAccessDenied `json:"denied"` + Allowed []AnnouncementAccessAllowedRep `json:"allowed"` +} + +// NewAnnouncementAccess instantiates a new AnnouncementAccess object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccess(denied []AnnouncementAccessDenied, allowed []AnnouncementAccessAllowedRep) *AnnouncementAccess { + this := AnnouncementAccess{} + this.Denied = denied + this.Allowed = allowed + return &this +} + +// NewAnnouncementAccessWithDefaults instantiates a new AnnouncementAccess object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessWithDefaults() *AnnouncementAccess { + this := AnnouncementAccess{} + return &this +} + +// GetDenied returns the Denied field value +func (o *AnnouncementAccess) GetDenied() []AnnouncementAccessDenied { + if o == nil { + var ret []AnnouncementAccessDenied + return ret + } + + return o.Denied +} + +// GetDeniedOk returns a tuple with the Denied field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccess) GetDeniedOk() ([]AnnouncementAccessDenied, bool) { + if o == nil { + return nil, false + } + return o.Denied, true +} + +// SetDenied sets field value +func (o *AnnouncementAccess) SetDenied(v []AnnouncementAccessDenied) { + o.Denied = v +} + +// GetAllowed returns the Allowed field value +func (o *AnnouncementAccess) GetAllowed() []AnnouncementAccessAllowedRep { + if o == nil { + var ret []AnnouncementAccessAllowedRep + return ret + } + + return o.Allowed +} + +// GetAllowedOk returns a tuple with the Allowed field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccess) GetAllowedOk() ([]AnnouncementAccessAllowedRep, bool) { + if o == nil { + return nil, false + } + return o.Allowed, true +} + +// SetAllowed sets field value +func (o *AnnouncementAccess) SetAllowed(v []AnnouncementAccessAllowedRep) { + o.Allowed = v +} + +func (o AnnouncementAccess) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["denied"] = o.Denied + } + if true { + toSerialize["allowed"] = o.Allowed + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccess struct { + value *AnnouncementAccess + isSet bool +} + +func (v NullableAnnouncementAccess) Get() *AnnouncementAccess { + return v.value +} + +func (v *NullableAnnouncementAccess) Set(val *AnnouncementAccess) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccess) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccess) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccess(val *AnnouncementAccess) *NullableAnnouncementAccess { + return &NullableAnnouncementAccess{value: val, isSet: true} +} + +func (v NullableAnnouncementAccess) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccess) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_reason.go new file mode 100644 index 00000000..9e0b2a9f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccessAllowedReason struct for AnnouncementAccessAllowedReason +type AnnouncementAccessAllowedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAnnouncementAccessAllowedReason instantiates a new AnnouncementAccessAllowedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccessAllowedReason(effect string) *AnnouncementAccessAllowedReason { + this := AnnouncementAccessAllowedReason{} + this.Effect = effect + return &this +} + +// NewAnnouncementAccessAllowedReasonWithDefaults instantiates a new AnnouncementAccessAllowedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessAllowedReasonWithDefaults() *AnnouncementAccessAllowedReason { + this := AnnouncementAccessAllowedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AnnouncementAccessAllowedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AnnouncementAccessAllowedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AnnouncementAccessAllowedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AnnouncementAccessAllowedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AnnouncementAccessAllowedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AnnouncementAccessAllowedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AnnouncementAccessAllowedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AnnouncementAccessAllowedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AnnouncementAccessAllowedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AnnouncementAccessAllowedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AnnouncementAccessAllowedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AnnouncementAccessAllowedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AnnouncementAccessAllowedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AnnouncementAccessAllowedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AnnouncementAccessAllowedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AnnouncementAccessAllowedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AnnouncementAccessAllowedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AnnouncementAccessAllowedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccessAllowedReason struct { + value *AnnouncementAccessAllowedReason + isSet bool +} + +func (v NullableAnnouncementAccessAllowedReason) Get() *AnnouncementAccessAllowedReason { + return v.value +} + +func (v *NullableAnnouncementAccessAllowedReason) Set(val *AnnouncementAccessAllowedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccessAllowedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccessAllowedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccessAllowedReason(val *AnnouncementAccessAllowedReason) *NullableAnnouncementAccessAllowedReason { + return &NullableAnnouncementAccessAllowedReason{value: val, isSet: true} +} + +func (v NullableAnnouncementAccessAllowedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccessAllowedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_rep.go new file mode 100644 index 00000000..542b9bc1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_allowed_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccessAllowedRep struct for AnnouncementAccessAllowedRep +type AnnouncementAccessAllowedRep struct { + Action string `json:"action"` + Reason AnnouncementAccessAllowedReason `json:"reason"` +} + +// NewAnnouncementAccessAllowedRep instantiates a new AnnouncementAccessAllowedRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccessAllowedRep(action string, reason AnnouncementAccessAllowedReason) *AnnouncementAccessAllowedRep { + this := AnnouncementAccessAllowedRep{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAnnouncementAccessAllowedRepWithDefaults instantiates a new AnnouncementAccessAllowedRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessAllowedRepWithDefaults() *AnnouncementAccessAllowedRep { + this := AnnouncementAccessAllowedRep{} + return &this +} + +// GetAction returns the Action field value +func (o *AnnouncementAccessAllowedRep) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedRep) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AnnouncementAccessAllowedRep) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AnnouncementAccessAllowedRep) GetReason() AnnouncementAccessAllowedReason { + if o == nil { + var ret AnnouncementAccessAllowedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessAllowedRep) GetReasonOk() (*AnnouncementAccessAllowedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AnnouncementAccessAllowedRep) SetReason(v AnnouncementAccessAllowedReason) { + o.Reason = v +} + +func (o AnnouncementAccessAllowedRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccessAllowedRep struct { + value *AnnouncementAccessAllowedRep + isSet bool +} + +func (v NullableAnnouncementAccessAllowedRep) Get() *AnnouncementAccessAllowedRep { + return v.value +} + +func (v *NullableAnnouncementAccessAllowedRep) Set(val *AnnouncementAccessAllowedRep) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccessAllowedRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccessAllowedRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccessAllowedRep(val *AnnouncementAccessAllowedRep) *NullableAnnouncementAccessAllowedRep { + return &NullableAnnouncementAccessAllowedRep{value: val, isSet: true} +} + +func (v NullableAnnouncementAccessAllowedRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccessAllowedRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied.go new file mode 100644 index 00000000..12be7328 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccessDenied struct for AnnouncementAccessDenied +type AnnouncementAccessDenied struct { + Action string `json:"action"` + Reason AnnouncementAccessDeniedReason `json:"reason"` +} + +// NewAnnouncementAccessDenied instantiates a new AnnouncementAccessDenied object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccessDenied(action string, reason AnnouncementAccessDeniedReason) *AnnouncementAccessDenied { + this := AnnouncementAccessDenied{} + this.Action = action + this.Reason = reason + return &this +} + +// NewAnnouncementAccessDeniedWithDefaults instantiates a new AnnouncementAccessDenied object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessDeniedWithDefaults() *AnnouncementAccessDenied { + this := AnnouncementAccessDenied{} + return &this +} + +// GetAction returns the Action field value +func (o *AnnouncementAccessDenied) GetAction() string { + if o == nil { + var ret string + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDenied) GetActionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *AnnouncementAccessDenied) SetAction(v string) { + o.Action = v +} + +// GetReason returns the Reason field value +func (o *AnnouncementAccessDenied) GetReason() AnnouncementAccessDeniedReason { + if o == nil { + var ret AnnouncementAccessDeniedReason + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDenied) GetReasonOk() (*AnnouncementAccessDeniedReason, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *AnnouncementAccessDenied) SetReason(v AnnouncementAccessDeniedReason) { + o.Reason = v +} + +func (o AnnouncementAccessDenied) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccessDenied struct { + value *AnnouncementAccessDenied + isSet bool +} + +func (v NullableAnnouncementAccessDenied) Get() *AnnouncementAccessDenied { + return v.value +} + +func (v *NullableAnnouncementAccessDenied) Set(val *AnnouncementAccessDenied) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccessDenied) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccessDenied) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccessDenied(val *AnnouncementAccessDenied) *NullableAnnouncementAccessDenied { + return &NullableAnnouncementAccessDenied{value: val, isSet: true} +} + +func (v NullableAnnouncementAccessDenied) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccessDenied) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied_reason.go new file mode 100644 index 00000000..635c8df5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_denied_reason.go @@ -0,0 +1,294 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccessDeniedReason struct for AnnouncementAccessDeniedReason +type AnnouncementAccessDeniedReason struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` + RoleName *string `json:"role_name,omitempty"` +} + +// NewAnnouncementAccessDeniedReason instantiates a new AnnouncementAccessDeniedReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccessDeniedReason(effect string) *AnnouncementAccessDeniedReason { + this := AnnouncementAccessDeniedReason{} + this.Effect = effect + return &this +} + +// NewAnnouncementAccessDeniedReasonWithDefaults instantiates a new AnnouncementAccessDeniedReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessDeniedReasonWithDefaults() *AnnouncementAccessDeniedReason { + this := AnnouncementAccessDeniedReason{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *AnnouncementAccessDeniedReason) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *AnnouncementAccessDeniedReason) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *AnnouncementAccessDeniedReason) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *AnnouncementAccessDeniedReason) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *AnnouncementAccessDeniedReason) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *AnnouncementAccessDeniedReason) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *AnnouncementAccessDeniedReason) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *AnnouncementAccessDeniedReason) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *AnnouncementAccessDeniedReason) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *AnnouncementAccessDeniedReason) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *AnnouncementAccessDeniedReason) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *AnnouncementAccessDeniedReason) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *AnnouncementAccessDeniedReason) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *AnnouncementAccessDeniedReason) SetEffect(v string) { + o.Effect = v +} + +// GetRoleName returns the RoleName field value if set, zero value otherwise. +func (o *AnnouncementAccessDeniedReason) GetRoleName() string { + if o == nil || o.RoleName == nil { + var ret string + return ret + } + return *o.RoleName +} + +// GetRoleNameOk returns a tuple with the RoleName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessDeniedReason) GetRoleNameOk() (*string, bool) { + if o == nil || o.RoleName == nil { + return nil, false + } + return o.RoleName, true +} + +// HasRoleName returns a boolean if a field has been set. +func (o *AnnouncementAccessDeniedReason) HasRoleName() bool { + if o != nil && o.RoleName != nil { + return true + } + + return false +} + +// SetRoleName gets a reference to the given string and assigns it to the RoleName field. +func (o *AnnouncementAccessDeniedReason) SetRoleName(v string) { + o.RoleName = &v +} + +func (o AnnouncementAccessDeniedReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + if o.RoleName != nil { + toSerialize["role_name"] = o.RoleName + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccessDeniedReason struct { + value *AnnouncementAccessDeniedReason + isSet bool +} + +func (v NullableAnnouncementAccessDeniedReason) Get() *AnnouncementAccessDeniedReason { + return v.value +} + +func (v *NullableAnnouncementAccessDeniedReason) Set(val *AnnouncementAccessDeniedReason) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccessDeniedReason) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccessDeniedReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccessDeniedReason(val *AnnouncementAccessDeniedReason) *NullableAnnouncementAccessDeniedReason { + return &NullableAnnouncementAccessDeniedReason{value: val, isSet: true} +} + +func (v NullableAnnouncementAccessDeniedReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccessDeniedReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_rep.go new file mode 100644 index 00000000..cb485e70 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_access_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementAccessRep struct for AnnouncementAccessRep +type AnnouncementAccessRep struct { + Denied []AnnouncementAccessDenied `json:"denied"` + Allowed []AnnouncementAccessAllowedRep `json:"allowed"` +} + +// NewAnnouncementAccessRep instantiates a new AnnouncementAccessRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementAccessRep(denied []AnnouncementAccessDenied, allowed []AnnouncementAccessAllowedRep) *AnnouncementAccessRep { + this := AnnouncementAccessRep{} + this.Denied = denied + this.Allowed = allowed + return &this +} + +// NewAnnouncementAccessRepWithDefaults instantiates a new AnnouncementAccessRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementAccessRepWithDefaults() *AnnouncementAccessRep { + this := AnnouncementAccessRep{} + return &this +} + +// GetDenied returns the Denied field value +func (o *AnnouncementAccessRep) GetDenied() []AnnouncementAccessDenied { + if o == nil { + var ret []AnnouncementAccessDenied + return ret + } + + return o.Denied +} + +// GetDeniedOk returns a tuple with the Denied field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessRep) GetDeniedOk() ([]AnnouncementAccessDenied, bool) { + if o == nil { + return nil, false + } + return o.Denied, true +} + +// SetDenied sets field value +func (o *AnnouncementAccessRep) SetDenied(v []AnnouncementAccessDenied) { + o.Denied = v +} + +// GetAllowed returns the Allowed field value +func (o *AnnouncementAccessRep) GetAllowed() []AnnouncementAccessAllowedRep { + if o == nil { + var ret []AnnouncementAccessAllowedRep + return ret + } + + return o.Allowed +} + +// GetAllowedOk returns a tuple with the Allowed field value +// and a boolean to check if the value has been set. +func (o *AnnouncementAccessRep) GetAllowedOk() ([]AnnouncementAccessAllowedRep, bool) { + if o == nil { + return nil, false + } + return o.Allowed, true +} + +// SetAllowed sets field value +func (o *AnnouncementAccessRep) SetAllowed(v []AnnouncementAccessAllowedRep) { + o.Allowed = v +} + +func (o AnnouncementAccessRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["denied"] = o.Denied + } + if true { + toSerialize["allowed"] = o.Allowed + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementAccessRep struct { + value *AnnouncementAccessRep + isSet bool +} + +func (v NullableAnnouncementAccessRep) Get() *AnnouncementAccessRep { + return v.value +} + +func (v *NullableAnnouncementAccessRep) Set(val *AnnouncementAccessRep) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementAccessRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementAccessRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementAccessRep(val *AnnouncementAccessRep) *NullableAnnouncementAccessRep { + return &NullableAnnouncementAccessRep{value: val, isSet: true} +} + +func (v NullableAnnouncementAccessRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementAccessRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_link.go new file mode 100644 index 00000000..08206dd5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_link.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementLink struct for AnnouncementLink +type AnnouncementLink struct { + Href *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NewAnnouncementLink instantiates a new AnnouncementLink object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementLink() *AnnouncementLink { + this := AnnouncementLink{} + return &this +} + +// NewAnnouncementLinkWithDefaults instantiates a new AnnouncementLink object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementLinkWithDefaults() *AnnouncementLink { + this := AnnouncementLink{} + return &this +} + +// GetHref returns the Href field value if set, zero value otherwise. +func (o *AnnouncementLink) GetHref() string { + if o == nil || o.Href == nil { + var ret string + return ret + } + return *o.Href +} + +// GetHrefOk returns a tuple with the Href field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementLink) GetHrefOk() (*string, bool) { + if o == nil || o.Href == nil { + return nil, false + } + return o.Href, true +} + +// HasHref returns a boolean if a field has been set. +func (o *AnnouncementLink) HasHref() bool { + if o != nil && o.Href != nil { + return true + } + + return false +} + +// SetHref gets a reference to the given string and assigns it to the Href field. +func (o *AnnouncementLink) SetHref(v string) { + o.Href = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *AnnouncementLink) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementLink) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *AnnouncementLink) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *AnnouncementLink) SetType(v string) { + o.Type = &v +} + +func (o AnnouncementLink) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Href != nil { + toSerialize["href"] = o.Href + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementLink struct { + value *AnnouncementLink + isSet bool +} + +func (v NullableAnnouncementLink) Get() *AnnouncementLink { + return v.value +} + +func (v *NullableAnnouncementLink) Set(val *AnnouncementLink) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementLink) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementLink(val *AnnouncementLink) *NullableAnnouncementLink { + return &NullableAnnouncementLink{value: val, isSet: true} +} + +func (v NullableAnnouncementLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_paginated_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_paginated_links.go new file mode 100644 index 00000000..43383862 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_paginated_links.go @@ -0,0 +1,253 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementPaginatedLinks struct for AnnouncementPaginatedLinks +type AnnouncementPaginatedLinks struct { + First *AnnouncementLink `json:"first,omitempty"` + Last *AnnouncementLink `json:"last,omitempty"` + Next *AnnouncementLink `json:"next,omitempty"` + Prev *AnnouncementLink `json:"prev,omitempty"` + Self AnnouncementLink `json:"self"` +} + +// NewAnnouncementPaginatedLinks instantiates a new AnnouncementPaginatedLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementPaginatedLinks(self AnnouncementLink) *AnnouncementPaginatedLinks { + this := AnnouncementPaginatedLinks{} + this.Self = self + return &this +} + +// NewAnnouncementPaginatedLinksWithDefaults instantiates a new AnnouncementPaginatedLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementPaginatedLinksWithDefaults() *AnnouncementPaginatedLinks { + this := AnnouncementPaginatedLinks{} + return &this +} + +// GetFirst returns the First field value if set, zero value otherwise. +func (o *AnnouncementPaginatedLinks) GetFirst() AnnouncementLink { + if o == nil || o.First == nil { + var ret AnnouncementLink + return ret + } + return *o.First +} + +// GetFirstOk returns a tuple with the First field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementPaginatedLinks) GetFirstOk() (*AnnouncementLink, bool) { + if o == nil || o.First == nil { + return nil, false + } + return o.First, true +} + +// HasFirst returns a boolean if a field has been set. +func (o *AnnouncementPaginatedLinks) HasFirst() bool { + if o != nil && o.First != nil { + return true + } + + return false +} + +// SetFirst gets a reference to the given AnnouncementLink and assigns it to the First field. +func (o *AnnouncementPaginatedLinks) SetFirst(v AnnouncementLink) { + o.First = &v +} + +// GetLast returns the Last field value if set, zero value otherwise. +func (o *AnnouncementPaginatedLinks) GetLast() AnnouncementLink { + if o == nil || o.Last == nil { + var ret AnnouncementLink + return ret + } + return *o.Last +} + +// GetLastOk returns a tuple with the Last field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementPaginatedLinks) GetLastOk() (*AnnouncementLink, bool) { + if o == nil || o.Last == nil { + return nil, false + } + return o.Last, true +} + +// HasLast returns a boolean if a field has been set. +func (o *AnnouncementPaginatedLinks) HasLast() bool { + if o != nil && o.Last != nil { + return true + } + + return false +} + +// SetLast gets a reference to the given AnnouncementLink and assigns it to the Last field. +func (o *AnnouncementPaginatedLinks) SetLast(v AnnouncementLink) { + o.Last = &v +} + +// GetNext returns the Next field value if set, zero value otherwise. +func (o *AnnouncementPaginatedLinks) GetNext() AnnouncementLink { + if o == nil || o.Next == nil { + var ret AnnouncementLink + return ret + } + return *o.Next +} + +// GetNextOk returns a tuple with the Next field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementPaginatedLinks) GetNextOk() (*AnnouncementLink, bool) { + if o == nil || o.Next == nil { + return nil, false + } + return o.Next, true +} + +// HasNext returns a boolean if a field has been set. +func (o *AnnouncementPaginatedLinks) HasNext() bool { + if o != nil && o.Next != nil { + return true + } + + return false +} + +// SetNext gets a reference to the given AnnouncementLink and assigns it to the Next field. +func (o *AnnouncementPaginatedLinks) SetNext(v AnnouncementLink) { + o.Next = &v +} + +// GetPrev returns the Prev field value if set, zero value otherwise. +func (o *AnnouncementPaginatedLinks) GetPrev() AnnouncementLink { + if o == nil || o.Prev == nil { + var ret AnnouncementLink + return ret + } + return *o.Prev +} + +// GetPrevOk returns a tuple with the Prev field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementPaginatedLinks) GetPrevOk() (*AnnouncementLink, bool) { + if o == nil || o.Prev == nil { + return nil, false + } + return o.Prev, true +} + +// HasPrev returns a boolean if a field has been set. +func (o *AnnouncementPaginatedLinks) HasPrev() bool { + if o != nil && o.Prev != nil { + return true + } + + return false +} + +// SetPrev gets a reference to the given AnnouncementLink and assigns it to the Prev field. +func (o *AnnouncementPaginatedLinks) SetPrev(v AnnouncementLink) { + o.Prev = &v +} + +// GetSelf returns the Self field value +func (o *AnnouncementPaginatedLinks) GetSelf() AnnouncementLink { + if o == nil { + var ret AnnouncementLink + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *AnnouncementPaginatedLinks) GetSelfOk() (*AnnouncementLink, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *AnnouncementPaginatedLinks) SetSelf(v AnnouncementLink) { + o.Self = v +} + +func (o AnnouncementPaginatedLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.First != nil { + toSerialize["first"] = o.First + } + if o.Last != nil { + toSerialize["last"] = o.Last + } + if o.Next != nil { + toSerialize["next"] = o.Next + } + if o.Prev != nil { + toSerialize["prev"] = o.Prev + } + if true { + toSerialize["self"] = o.Self + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementPaginatedLinks struct { + value *AnnouncementPaginatedLinks + isSet bool +} + +func (v NullableAnnouncementPaginatedLinks) Get() *AnnouncementPaginatedLinks { + return v.value +} + +func (v *NullableAnnouncementPaginatedLinks) Set(val *AnnouncementPaginatedLinks) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementPaginatedLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementPaginatedLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementPaginatedLinks(val *AnnouncementPaginatedLinks) *NullableAnnouncementPaginatedLinks { + return &NullableAnnouncementPaginatedLinks{value: val, isSet: true} +} + +func (v NullableAnnouncementPaginatedLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementPaginatedLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_patch_operation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_patch_operation.go new file mode 100644 index 00000000..b2621950 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_patch_operation.go @@ -0,0 +1,178 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementPatchOperation struct for AnnouncementPatchOperation +type AnnouncementPatchOperation struct { + // The type of operation to perform + Op string `json:"op"` + // A JSON Pointer string specifying the part of the document to operate on + Path string `json:"path"` + // A JSON value used in \"add\", \"replace\", and \"test\" operations + Value interface{} `json:"value,omitempty"` +} + +// NewAnnouncementPatchOperation instantiates a new AnnouncementPatchOperation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementPatchOperation(op string, path string) *AnnouncementPatchOperation { + this := AnnouncementPatchOperation{} + this.Op = op + this.Path = path + return &this +} + +// NewAnnouncementPatchOperationWithDefaults instantiates a new AnnouncementPatchOperation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementPatchOperationWithDefaults() *AnnouncementPatchOperation { + this := AnnouncementPatchOperation{} + return &this +} + +// GetOp returns the Op field value +func (o *AnnouncementPatchOperation) GetOp() string { + if o == nil { + var ret string + return ret + } + + return o.Op +} + +// GetOpOk returns a tuple with the Op field value +// and a boolean to check if the value has been set. +func (o *AnnouncementPatchOperation) GetOpOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Op, true +} + +// SetOp sets field value +func (o *AnnouncementPatchOperation) SetOp(v string) { + o.Op = v +} + +// GetPath returns the Path field value +func (o *AnnouncementPatchOperation) GetPath() string { + if o == nil { + var ret string + return ret + } + + return o.Path +} + +// GetPathOk returns a tuple with the Path field value +// and a boolean to check if the value has been set. +func (o *AnnouncementPatchOperation) GetPathOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Path, true +} + +// SetPath sets field value +func (o *AnnouncementPatchOperation) SetPath(v string) { + o.Path = v +} + +// GetValue returns the Value field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AnnouncementPatchOperation) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AnnouncementPatchOperation) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *AnnouncementPatchOperation) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given interface{} and assigns it to the Value field. +func (o *AnnouncementPatchOperation) SetValue(v interface{}) { + o.Value = v +} + +func (o AnnouncementPatchOperation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["op"] = o.Op + } + if true { + toSerialize["path"] = o.Path + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementPatchOperation struct { + value *AnnouncementPatchOperation + isSet bool +} + +func (v NullableAnnouncementPatchOperation) Get() *AnnouncementPatchOperation { + return v.value +} + +func (v *NullableAnnouncementPatchOperation) Set(val *AnnouncementPatchOperation) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementPatchOperation) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementPatchOperation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementPatchOperation(val *AnnouncementPatchOperation) *NullableAnnouncementPatchOperation { + return &NullableAnnouncementPatchOperation{value: val, isSet: true} +} + +func (v NullableAnnouncementPatchOperation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementPatchOperation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response.go new file mode 100644 index 00000000..6cff9f92 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response.go @@ -0,0 +1,392 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementResponse Announcement response +type AnnouncementResponse struct { + // The ID of the announcement + Id string `json:"_id"` + // true if the announcement is dismissible + IsDismissible bool `json:"isDismissible"` + // The title of the announcement + Title string `json:"title"` + // The message of the announcement + Message string `json:"message"` + // The start time of the announcement. This is a Unix timestamp in milliseconds. + StartTime int64 `json:"startTime"` + // The end time of the announcement. This is a Unix timestamp in milliseconds. + EndTime *int64 `json:"endTime,omitempty"` + // The severity of the announcement + Severity string `json:"severity"` + // The status of the announcement + Status string `json:"_status"` + Access *AnnouncementAccessRep `json:"_access,omitempty"` + Links AnnouncementResponseLinks `json:"_links"` +} + +// NewAnnouncementResponse instantiates a new AnnouncementResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementResponse(id string, isDismissible bool, title string, message string, startTime int64, severity string, status string, links AnnouncementResponseLinks) *AnnouncementResponse { + this := AnnouncementResponse{} + this.Id = id + this.IsDismissible = isDismissible + this.Title = title + this.Message = message + this.StartTime = startTime + this.Severity = severity + this.Status = status + this.Links = links + return &this +} + +// NewAnnouncementResponseWithDefaults instantiates a new AnnouncementResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementResponseWithDefaults() *AnnouncementResponse { + this := AnnouncementResponse{} + return &this +} + +// GetId returns the Id field value +func (o *AnnouncementResponse) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *AnnouncementResponse) SetId(v string) { + o.Id = v +} + +// GetIsDismissible returns the IsDismissible field value +func (o *AnnouncementResponse) GetIsDismissible() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsDismissible +} + +// GetIsDismissibleOk returns a tuple with the IsDismissible field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetIsDismissibleOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsDismissible, true +} + +// SetIsDismissible sets field value +func (o *AnnouncementResponse) SetIsDismissible(v bool) { + o.IsDismissible = v +} + +// GetTitle returns the Title field value +func (o *AnnouncementResponse) GetTitle() string { + if o == nil { + var ret string + return ret + } + + return o.Title +} + +// GetTitleOk returns a tuple with the Title field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetTitleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Title, true +} + +// SetTitle sets field value +func (o *AnnouncementResponse) SetTitle(v string) { + o.Title = v +} + +// GetMessage returns the Message field value +func (o *AnnouncementResponse) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *AnnouncementResponse) SetMessage(v string) { + o.Message = v +} + +// GetStartTime returns the StartTime field value +func (o *AnnouncementResponse) GetStartTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.StartTime +} + +// GetStartTimeOk returns a tuple with the StartTime field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetStartTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.StartTime, true +} + +// SetStartTime sets field value +func (o *AnnouncementResponse) SetStartTime(v int64) { + o.StartTime = v +} + +// GetEndTime returns the EndTime field value if set, zero value otherwise. +func (o *AnnouncementResponse) GetEndTime() int64 { + if o == nil || o.EndTime == nil { + var ret int64 + return ret + } + return *o.EndTime +} + +// GetEndTimeOk returns a tuple with the EndTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetEndTimeOk() (*int64, bool) { + if o == nil || o.EndTime == nil { + return nil, false + } + return o.EndTime, true +} + +// HasEndTime returns a boolean if a field has been set. +func (o *AnnouncementResponse) HasEndTime() bool { + if o != nil && o.EndTime != nil { + return true + } + + return false +} + +// SetEndTime gets a reference to the given int64 and assigns it to the EndTime field. +func (o *AnnouncementResponse) SetEndTime(v int64) { + o.EndTime = &v +} + +// GetSeverity returns the Severity field value +func (o *AnnouncementResponse) GetSeverity() string { + if o == nil { + var ret string + return ret + } + + return o.Severity +} + +// GetSeverityOk returns a tuple with the Severity field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetSeverityOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Severity, true +} + +// SetSeverity sets field value +func (o *AnnouncementResponse) SetSeverity(v string) { + o.Severity = v +} + +// GetStatus returns the Status field value +func (o *AnnouncementResponse) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *AnnouncementResponse) SetStatus(v string) { + o.Status = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *AnnouncementResponse) GetAccess() AnnouncementAccessRep { + if o == nil || o.Access == nil { + var ret AnnouncementAccessRep + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetAccessOk() (*AnnouncementAccessRep, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *AnnouncementResponse) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given AnnouncementAccessRep and assigns it to the Access field. +func (o *AnnouncementResponse) SetAccess(v AnnouncementAccessRep) { + o.Access = &v +} + +// GetLinks returns the Links field value +func (o *AnnouncementResponse) GetLinks() AnnouncementResponseLinks { + if o == nil { + var ret AnnouncementResponseLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponse) GetLinksOk() (*AnnouncementResponseLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *AnnouncementResponse) SetLinks(v AnnouncementResponseLinks) { + o.Links = v +} + +func (o AnnouncementResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["isDismissible"] = o.IsDismissible + } + if true { + toSerialize["title"] = o.Title + } + if true { + toSerialize["message"] = o.Message + } + if true { + toSerialize["startTime"] = o.StartTime + } + if o.EndTime != nil { + toSerialize["endTime"] = o.EndTime + } + if true { + toSerialize["severity"] = o.Severity + } + if true { + toSerialize["_status"] = o.Status + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementResponse struct { + value *AnnouncementResponse + isSet bool +} + +func (v NullableAnnouncementResponse) Get() *AnnouncementResponse { + return v.value +} + +func (v *NullableAnnouncementResponse) Set(val *AnnouncementResponse) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementResponse(val *AnnouncementResponse) *NullableAnnouncementResponse { + return &NullableAnnouncementResponse{value: val, isSet: true} +} + +func (v NullableAnnouncementResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response__links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response__links.go new file mode 100644 index 00000000..84a085e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_announcement_response__links.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AnnouncementResponseLinks struct for AnnouncementResponseLinks +type AnnouncementResponseLinks struct { + Parent AnnouncementLink `json:"parent"` +} + +// NewAnnouncementResponseLinks instantiates a new AnnouncementResponseLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAnnouncementResponseLinks(parent AnnouncementLink) *AnnouncementResponseLinks { + this := AnnouncementResponseLinks{} + this.Parent = parent + return &this +} + +// NewAnnouncementResponseLinksWithDefaults instantiates a new AnnouncementResponseLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAnnouncementResponseLinksWithDefaults() *AnnouncementResponseLinks { + this := AnnouncementResponseLinks{} + return &this +} + +// GetParent returns the Parent field value +func (o *AnnouncementResponseLinks) GetParent() AnnouncementLink { + if o == nil { + var ret AnnouncementLink + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *AnnouncementResponseLinks) GetParentOk() (*AnnouncementLink, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *AnnouncementResponseLinks) SetParent(v AnnouncementLink) { + o.Parent = v +} + +func (o AnnouncementResponseLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableAnnouncementResponseLinks struct { + value *AnnouncementResponseLinks + isSet bool +} + +func (v NullableAnnouncementResponseLinks) Get() *AnnouncementResponseLinks { + return v.value +} + +func (v *NullableAnnouncementResponseLinks) Set(val *AnnouncementResponseLinks) { + v.value = val + v.isSet = true +} + +func (v NullableAnnouncementResponseLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableAnnouncementResponseLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAnnouncementResponseLinks(val *AnnouncementResponseLinks) *NullableAnnouncementResponseLinks { + return &NullableAnnouncementResponseLinks{value: val, isSet: true} +} + +func (v NullableAnnouncementResponseLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAnnouncementResponseLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_application_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_collection_rep.go new file mode 100644 index 00000000..ec5f1ab3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_collection_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApplicationCollectionRep struct for ApplicationCollectionRep +type ApplicationCollectionRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // A list of applications + Items []ApplicationRep `json:"items,omitempty"` + // The number of applications + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewApplicationCollectionRep instantiates a new ApplicationCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApplicationCollectionRep() *ApplicationCollectionRep { + this := ApplicationCollectionRep{} + return &this +} + +// NewApplicationCollectionRepWithDefaults instantiates a new ApplicationCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApplicationCollectionRepWithDefaults() *ApplicationCollectionRep { + this := ApplicationCollectionRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ApplicationCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ApplicationCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ApplicationCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *ApplicationCollectionRep) GetItems() []ApplicationRep { + if o == nil || o.Items == nil { + var ret []ApplicationRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationCollectionRep) GetItemsOk() ([]ApplicationRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *ApplicationCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []ApplicationRep and assigns it to the Items field. +func (o *ApplicationCollectionRep) SetItems(v []ApplicationRep) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ApplicationCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ApplicationCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ApplicationCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o ApplicationCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableApplicationCollectionRep struct { + value *ApplicationCollectionRep + isSet bool +} + +func (v NullableApplicationCollectionRep) Get() *ApplicationCollectionRep { + return v.value +} + +func (v *NullableApplicationCollectionRep) Set(val *ApplicationCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableApplicationCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableApplicationCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApplicationCollectionRep(val *ApplicationCollectionRep) *NullableApplicationCollectionRep { + return &NullableApplicationCollectionRep{value: val, isSet: true} +} + +func (v NullableApplicationCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApplicationCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_application_flag_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_flag_collection_rep.go new file mode 100644 index 00000000..b130a6ff --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_flag_collection_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApplicationFlagCollectionRep struct for ApplicationFlagCollectionRep +type ApplicationFlagCollectionRep struct { + // A list of the flags that have been evaluated by the application + Items []FlagListingRep `json:"items,omitempty"` + // The number of flags that have been evaluated by the application + TotalCount *int32 `json:"totalCount,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewApplicationFlagCollectionRep instantiates a new ApplicationFlagCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApplicationFlagCollectionRep() *ApplicationFlagCollectionRep { + this := ApplicationFlagCollectionRep{} + return &this +} + +// NewApplicationFlagCollectionRepWithDefaults instantiates a new ApplicationFlagCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApplicationFlagCollectionRepWithDefaults() *ApplicationFlagCollectionRep { + this := ApplicationFlagCollectionRep{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *ApplicationFlagCollectionRep) GetItems() []FlagListingRep { + if o == nil || o.Items == nil { + var ret []FlagListingRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationFlagCollectionRep) GetItemsOk() ([]FlagListingRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *ApplicationFlagCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []FlagListingRep and assigns it to the Items field. +func (o *ApplicationFlagCollectionRep) SetItems(v []FlagListingRep) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ApplicationFlagCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationFlagCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ApplicationFlagCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ApplicationFlagCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ApplicationFlagCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationFlagCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ApplicationFlagCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ApplicationFlagCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ApplicationFlagCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableApplicationFlagCollectionRep struct { + value *ApplicationFlagCollectionRep + isSet bool +} + +func (v NullableApplicationFlagCollectionRep) Get() *ApplicationFlagCollectionRep { + return v.value +} + +func (v *NullableApplicationFlagCollectionRep) Set(val *ApplicationFlagCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableApplicationFlagCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableApplicationFlagCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApplicationFlagCollectionRep(val *ApplicationFlagCollectionRep) *NullableApplicationFlagCollectionRep { + return &NullableApplicationFlagCollectionRep{value: val, isSet: true} +} + +func (v NullableApplicationFlagCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApplicationFlagCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_application_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_rep.go new file mode 100644 index 00000000..5be3ee3e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_rep.go @@ -0,0 +1,455 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApplicationRep struct for ApplicationRep +type ApplicationRep struct { + Flags *ApplicationFlagCollectionRep `json:"flags,omitempty"` + Access *Access `json:"_access,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // Version of the application + Version *int32 `json:"_version,omitempty"` + // Whether the application was automatically created because it was included in a context when a LaunchDarkly SDK evaluated a feature flag, or was created through the LaunchDarkly UI or REST API. + AutoAdded bool `json:"autoAdded"` + CreationDate *int64 `json:"creationDate,omitempty"` + // The application description + Description *string `json:"description,omitempty"` + // The unique identifier of this application + Key string `json:"key"` + // To distinguish the kind of application + Kind string `json:"kind"` + Maintainer *MaintainerRep `json:"_maintainer,omitempty"` + // The name of the application + Name string `json:"name"` +} + +// NewApplicationRep instantiates a new ApplicationRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApplicationRep(autoAdded bool, key string, kind string, name string) *ApplicationRep { + this := ApplicationRep{} + this.AutoAdded = autoAdded + this.Key = key + this.Kind = kind + this.Name = name + return &this +} + +// NewApplicationRepWithDefaults instantiates a new ApplicationRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApplicationRepWithDefaults() *ApplicationRep { + this := ApplicationRep{} + return &this +} + +// GetFlags returns the Flags field value if set, zero value otherwise. +func (o *ApplicationRep) GetFlags() ApplicationFlagCollectionRep { + if o == nil || o.Flags == nil { + var ret ApplicationFlagCollectionRep + return ret + } + return *o.Flags +} + +// GetFlagsOk returns a tuple with the Flags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetFlagsOk() (*ApplicationFlagCollectionRep, bool) { + if o == nil || o.Flags == nil { + return nil, false + } + return o.Flags, true +} + +// HasFlags returns a boolean if a field has been set. +func (o *ApplicationRep) HasFlags() bool { + if o != nil && o.Flags != nil { + return true + } + + return false +} + +// SetFlags gets a reference to the given ApplicationFlagCollectionRep and assigns it to the Flags field. +func (o *ApplicationRep) SetFlags(v ApplicationFlagCollectionRep) { + o.Flags = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ApplicationRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ApplicationRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ApplicationRep) SetAccess(v Access) { + o.Access = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ApplicationRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ApplicationRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ApplicationRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *ApplicationRep) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *ApplicationRep) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *ApplicationRep) SetVersion(v int32) { + o.Version = &v +} + +// GetAutoAdded returns the AutoAdded field value +func (o *ApplicationRep) GetAutoAdded() bool { + if o == nil { + var ret bool + return ret + } + + return o.AutoAdded +} + +// GetAutoAddedOk returns a tuple with the AutoAdded field value +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetAutoAddedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.AutoAdded, true +} + +// SetAutoAdded sets field value +func (o *ApplicationRep) SetAutoAdded(v bool) { + o.AutoAdded = v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *ApplicationRep) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *ApplicationRep) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *ApplicationRep) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ApplicationRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ApplicationRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ApplicationRep) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *ApplicationRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ApplicationRep) SetKey(v string) { + o.Key = v +} + +// GetKind returns the Kind field value +func (o *ApplicationRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ApplicationRep) SetKind(v string) { + o.Kind = v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *ApplicationRep) GetMaintainer() MaintainerRep { + if o == nil || o.Maintainer == nil { + var ret MaintainerRep + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetMaintainerOk() (*MaintainerRep, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *ApplicationRep) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MaintainerRep and assigns it to the Maintainer field. +func (o *ApplicationRep) SetMaintainer(v MaintainerRep) { + o.Maintainer = &v +} + +// GetName returns the Name field value +func (o *ApplicationRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ApplicationRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ApplicationRep) SetName(v string) { + o.Name = v +} + +func (o ApplicationRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Flags != nil { + toSerialize["flags"] = o.Flags + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["autoAdded"] = o.AutoAdded + } + if o.CreationDate != nil { + toSerialize["creationDate"] = o.CreationDate + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if true { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableApplicationRep struct { + value *ApplicationRep + isSet bool +} + +func (v NullableApplicationRep) Get() *ApplicationRep { + return v.value +} + +func (v *NullableApplicationRep) Set(val *ApplicationRep) { + v.value = val + v.isSet = true +} + +func (v NullableApplicationRep) IsSet() bool { + return v.isSet +} + +func (v *NullableApplicationRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApplicationRep(val *ApplicationRep) *NullableApplicationRep { + return &NullableApplicationRep{value: val, isSet: true} +} + +func (v NullableApplicationRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApplicationRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_application_version_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_version_rep.go new file mode 100644 index 00000000..dfbf29af --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_version_rep.go @@ -0,0 +1,353 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApplicationVersionRep struct for ApplicationVersionRep +type ApplicationVersionRep struct { + Access *Access `json:"_access,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // Version of the application version + Version *int32 `json:"_version,omitempty"` + // Whether the application version was automatically created, because it was included in a context when a LaunchDarkly SDK evaluated a feature flag, or if the application version was created through the LaunchDarkly UI or REST API. + AutoAdded bool `json:"autoAdded"` + CreationDate *int64 `json:"creationDate,omitempty"` + // The unique identifier of this application version + Key string `json:"key"` + // The name of this version + Name string `json:"name"` + // Whether this version is supported. Only applicable if the application kind is mobile. + Supported *bool `json:"supported,omitempty"` +} + +// NewApplicationVersionRep instantiates a new ApplicationVersionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApplicationVersionRep(autoAdded bool, key string, name string) *ApplicationVersionRep { + this := ApplicationVersionRep{} + this.AutoAdded = autoAdded + this.Key = key + this.Name = name + return &this +} + +// NewApplicationVersionRepWithDefaults instantiates a new ApplicationVersionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApplicationVersionRepWithDefaults() *ApplicationVersionRep { + this := ApplicationVersionRep{} + return &this +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ApplicationVersionRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ApplicationVersionRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ApplicationVersionRep) SetAccess(v Access) { + o.Access = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ApplicationVersionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ApplicationVersionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ApplicationVersionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *ApplicationVersionRep) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *ApplicationVersionRep) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *ApplicationVersionRep) SetVersion(v int32) { + o.Version = &v +} + +// GetAutoAdded returns the AutoAdded field value +func (o *ApplicationVersionRep) GetAutoAdded() bool { + if o == nil { + var ret bool + return ret + } + + return o.AutoAdded +} + +// GetAutoAddedOk returns a tuple with the AutoAdded field value +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetAutoAddedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.AutoAdded, true +} + +// SetAutoAdded sets field value +func (o *ApplicationVersionRep) SetAutoAdded(v bool) { + o.AutoAdded = v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *ApplicationVersionRep) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *ApplicationVersionRep) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *ApplicationVersionRep) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetKey returns the Key field value +func (o *ApplicationVersionRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ApplicationVersionRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *ApplicationVersionRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ApplicationVersionRep) SetName(v string) { + o.Name = v +} + +// GetSupported returns the Supported field value if set, zero value otherwise. +func (o *ApplicationVersionRep) GetSupported() bool { + if o == nil || o.Supported == nil { + var ret bool + return ret + } + return *o.Supported +} + +// GetSupportedOk returns a tuple with the Supported field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionRep) GetSupportedOk() (*bool, bool) { + if o == nil || o.Supported == nil { + return nil, false + } + return o.Supported, true +} + +// HasSupported returns a boolean if a field has been set. +func (o *ApplicationVersionRep) HasSupported() bool { + if o != nil && o.Supported != nil { + return true + } + + return false +} + +// SetSupported gets a reference to the given bool and assigns it to the Supported field. +func (o *ApplicationVersionRep) SetSupported(v bool) { + o.Supported = &v +} + +func (o ApplicationVersionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["autoAdded"] = o.AutoAdded + } + if o.CreationDate != nil { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if o.Supported != nil { + toSerialize["supported"] = o.Supported + } + return json.Marshal(toSerialize) +} + +type NullableApplicationVersionRep struct { + value *ApplicationVersionRep + isSet bool +} + +func (v NullableApplicationVersionRep) Get() *ApplicationVersionRep { + return v.value +} + +func (v *NullableApplicationVersionRep) Set(val *ApplicationVersionRep) { + v.value = val + v.isSet = true +} + +func (v NullableApplicationVersionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableApplicationVersionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApplicationVersionRep(val *ApplicationVersionRep) *NullableApplicationVersionRep { + return &NullableApplicationVersionRep{value: val, isSet: true} +} + +func (v NullableApplicationVersionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApplicationVersionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_application_versions_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_versions_collection_rep.go new file mode 100644 index 00000000..2fcbdd02 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_application_versions_collection_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApplicationVersionsCollectionRep struct for ApplicationVersionsCollectionRep +type ApplicationVersionsCollectionRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // A list of the versions for this application + Items []ApplicationVersionRep `json:"items,omitempty"` + // The number of versions for this application + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewApplicationVersionsCollectionRep instantiates a new ApplicationVersionsCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApplicationVersionsCollectionRep() *ApplicationVersionsCollectionRep { + this := ApplicationVersionsCollectionRep{} + return &this +} + +// NewApplicationVersionsCollectionRepWithDefaults instantiates a new ApplicationVersionsCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApplicationVersionsCollectionRepWithDefaults() *ApplicationVersionsCollectionRep { + this := ApplicationVersionsCollectionRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ApplicationVersionsCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionsCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ApplicationVersionsCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ApplicationVersionsCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *ApplicationVersionsCollectionRep) GetItems() []ApplicationVersionRep { + if o == nil || o.Items == nil { + var ret []ApplicationVersionRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionsCollectionRep) GetItemsOk() ([]ApplicationVersionRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *ApplicationVersionsCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []ApplicationVersionRep and assigns it to the Items field. +func (o *ApplicationVersionsCollectionRep) SetItems(v []ApplicationVersionRep) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ApplicationVersionsCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApplicationVersionsCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ApplicationVersionsCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ApplicationVersionsCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o ApplicationVersionsCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableApplicationVersionsCollectionRep struct { + value *ApplicationVersionsCollectionRep + isSet bool +} + +func (v NullableApplicationVersionsCollectionRep) Get() *ApplicationVersionsCollectionRep { + return v.value +} + +func (v *NullableApplicationVersionsCollectionRep) Set(val *ApplicationVersionsCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableApplicationVersionsCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableApplicationVersionsCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApplicationVersionsCollectionRep(val *ApplicationVersionsCollectionRep) *NullableApplicationVersionsCollectionRep { + return &NullableApplicationVersionsCollectionRep{value: val, isSet: true} +} + +func (v NullableApplicationVersionsCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApplicationVersionsCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_request_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_request_response.go new file mode 100644 index 00000000..e0a4e197 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_request_response.go @@ -0,0 +1,845 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApprovalRequestResponse struct for ApprovalRequestResponse +type ApprovalRequestResponse struct { + // The ID of this approval request + Id string `json:"_id"` + // Version of the approval request + Version int32 `json:"_version"` + CreationDate int64 `json:"creationDate"` + ServiceKind string `json:"serviceKind"` + // The ID of the member who requested the approval + RequestorId *string `json:"requestorId,omitempty"` + // A human-friendly name for the approval request + Description *string `json:"description,omitempty"` + // Current status of the review of this approval request + ReviewStatus string `json:"reviewStatus"` + // An array of individual reviews of this approval request + AllReviews []ReviewResponse `json:"allReviews"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds"` + AppliedDate *int64 `json:"appliedDate,omitempty"` + // The member ID of the member who applied the approval request + AppliedByMemberId *string `json:"appliedByMemberId,omitempty"` + // The service token ID of the service token which applied the approval request + AppliedByServiceTokenId *string `json:"appliedByServiceTokenId,omitempty"` + // Current status of the approval request + Status string `json:"status"` + Instructions []map[string]interface{} `json:"instructions"` + // Details on any conflicting approval requests + Conflicts []Conflict `json:"conflicts"` + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + // ID of scheduled change to edit or delete + OperatingOnId *string `json:"operatingOnId,omitempty"` + IntegrationMetadata *IntegrationMetadata `json:"integrationMetadata,omitempty"` + Source *CopiedFromEnv `json:"source,omitempty"` + CustomWorkflowMetadata *CustomWorkflowMeta `json:"customWorkflowMetadata,omitempty"` + // String representation of a resource + ResourceId *string `json:"resourceId,omitempty"` + ApprovalSettings *ApprovalSettings `json:"approvalSettings,omitempty"` +} + +// NewApprovalRequestResponse instantiates a new ApprovalRequestResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApprovalRequestResponse(id string, version int32, creationDate int64, serviceKind string, reviewStatus string, allReviews []ReviewResponse, notifyMemberIds []string, status string, instructions []map[string]interface{}, conflicts []Conflict, links map[string]interface{}) *ApprovalRequestResponse { + this := ApprovalRequestResponse{} + this.Id = id + this.Version = version + this.CreationDate = creationDate + this.ServiceKind = serviceKind + this.ReviewStatus = reviewStatus + this.AllReviews = allReviews + this.NotifyMemberIds = notifyMemberIds + this.Status = status + this.Instructions = instructions + this.Conflicts = conflicts + this.Links = links + return &this +} + +// NewApprovalRequestResponseWithDefaults instantiates a new ApprovalRequestResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApprovalRequestResponseWithDefaults() *ApprovalRequestResponse { + this := ApprovalRequestResponse{} + return &this +} + +// GetId returns the Id field value +func (o *ApprovalRequestResponse) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ApprovalRequestResponse) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *ApprovalRequestResponse) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ApprovalRequestResponse) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *ApprovalRequestResponse) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *ApprovalRequestResponse) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetServiceKind returns the ServiceKind field value +func (o *ApprovalRequestResponse) GetServiceKind() string { + if o == nil { + var ret string + return ret + } + + return o.ServiceKind +} + +// GetServiceKindOk returns a tuple with the ServiceKind field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetServiceKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ServiceKind, true +} + +// SetServiceKind sets field value +func (o *ApprovalRequestResponse) SetServiceKind(v string) { + o.ServiceKind = v +} + +// GetRequestorId returns the RequestorId field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetRequestorId() string { + if o == nil || o.RequestorId == nil { + var ret string + return ret + } + return *o.RequestorId +} + +// GetRequestorIdOk returns a tuple with the RequestorId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetRequestorIdOk() (*string, bool) { + if o == nil || o.RequestorId == nil { + return nil, false + } + return o.RequestorId, true +} + +// HasRequestorId returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasRequestorId() bool { + if o != nil && o.RequestorId != nil { + return true + } + + return false +} + +// SetRequestorId gets a reference to the given string and assigns it to the RequestorId field. +func (o *ApprovalRequestResponse) SetRequestorId(v string) { + o.RequestorId = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ApprovalRequestResponse) SetDescription(v string) { + o.Description = &v +} + +// GetReviewStatus returns the ReviewStatus field value +func (o *ApprovalRequestResponse) GetReviewStatus() string { + if o == nil { + var ret string + return ret + } + + return o.ReviewStatus +} + +// GetReviewStatusOk returns a tuple with the ReviewStatus field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetReviewStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReviewStatus, true +} + +// SetReviewStatus sets field value +func (o *ApprovalRequestResponse) SetReviewStatus(v string) { + o.ReviewStatus = v +} + +// GetAllReviews returns the AllReviews field value +func (o *ApprovalRequestResponse) GetAllReviews() []ReviewResponse { + if o == nil { + var ret []ReviewResponse + return ret + } + + return o.AllReviews +} + +// GetAllReviewsOk returns a tuple with the AllReviews field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetAllReviewsOk() ([]ReviewResponse, bool) { + if o == nil { + return nil, false + } + return o.AllReviews, true +} + +// SetAllReviews sets field value +func (o *ApprovalRequestResponse) SetAllReviews(v []ReviewResponse) { + o.AllReviews = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value +func (o *ApprovalRequestResponse) GetNotifyMemberIds() []string { + if o == nil { + var ret []string + return ret + } + + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// SetNotifyMemberIds sets field value +func (o *ApprovalRequestResponse) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetAppliedDate returns the AppliedDate field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetAppliedDate() int64 { + if o == nil || o.AppliedDate == nil { + var ret int64 + return ret + } + return *o.AppliedDate +} + +// GetAppliedDateOk returns a tuple with the AppliedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetAppliedDateOk() (*int64, bool) { + if o == nil || o.AppliedDate == nil { + return nil, false + } + return o.AppliedDate, true +} + +// HasAppliedDate returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasAppliedDate() bool { + if o != nil && o.AppliedDate != nil { + return true + } + + return false +} + +// SetAppliedDate gets a reference to the given int64 and assigns it to the AppliedDate field. +func (o *ApprovalRequestResponse) SetAppliedDate(v int64) { + o.AppliedDate = &v +} + +// GetAppliedByMemberId returns the AppliedByMemberId field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetAppliedByMemberId() string { + if o == nil || o.AppliedByMemberId == nil { + var ret string + return ret + } + return *o.AppliedByMemberId +} + +// GetAppliedByMemberIdOk returns a tuple with the AppliedByMemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetAppliedByMemberIdOk() (*string, bool) { + if o == nil || o.AppliedByMemberId == nil { + return nil, false + } + return o.AppliedByMemberId, true +} + +// HasAppliedByMemberId returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasAppliedByMemberId() bool { + if o != nil && o.AppliedByMemberId != nil { + return true + } + + return false +} + +// SetAppliedByMemberId gets a reference to the given string and assigns it to the AppliedByMemberId field. +func (o *ApprovalRequestResponse) SetAppliedByMemberId(v string) { + o.AppliedByMemberId = &v +} + +// GetAppliedByServiceTokenId returns the AppliedByServiceTokenId field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetAppliedByServiceTokenId() string { + if o == nil || o.AppliedByServiceTokenId == nil { + var ret string + return ret + } + return *o.AppliedByServiceTokenId +} + +// GetAppliedByServiceTokenIdOk returns a tuple with the AppliedByServiceTokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetAppliedByServiceTokenIdOk() (*string, bool) { + if o == nil || o.AppliedByServiceTokenId == nil { + return nil, false + } + return o.AppliedByServiceTokenId, true +} + +// HasAppliedByServiceTokenId returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasAppliedByServiceTokenId() bool { + if o != nil && o.AppliedByServiceTokenId != nil { + return true + } + + return false +} + +// SetAppliedByServiceTokenId gets a reference to the given string and assigns it to the AppliedByServiceTokenId field. +func (o *ApprovalRequestResponse) SetAppliedByServiceTokenId(v string) { + o.AppliedByServiceTokenId = &v +} + +// GetStatus returns the Status field value +func (o *ApprovalRequestResponse) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *ApprovalRequestResponse) SetStatus(v string) { + o.Status = v +} + +// GetInstructions returns the Instructions field value +func (o *ApprovalRequestResponse) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *ApprovalRequestResponse) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetConflicts returns the Conflicts field value +func (o *ApprovalRequestResponse) GetConflicts() []Conflict { + if o == nil { + var ret []Conflict + return ret + } + + return o.Conflicts +} + +// GetConflictsOk returns a tuple with the Conflicts field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetConflictsOk() ([]Conflict, bool) { + if o == nil { + return nil, false + } + return o.Conflicts, true +} + +// SetConflicts sets field value +func (o *ApprovalRequestResponse) SetConflicts(v []Conflict) { + o.Conflicts = v +} + +// GetLinks returns the Links field value +func (o *ApprovalRequestResponse) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *ApprovalRequestResponse) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *ApprovalRequestResponse) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetOperatingOnId returns the OperatingOnId field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetOperatingOnId() string { + if o == nil || o.OperatingOnId == nil { + var ret string + return ret + } + return *o.OperatingOnId +} + +// GetOperatingOnIdOk returns a tuple with the OperatingOnId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetOperatingOnIdOk() (*string, bool) { + if o == nil || o.OperatingOnId == nil { + return nil, false + } + return o.OperatingOnId, true +} + +// HasOperatingOnId returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasOperatingOnId() bool { + if o != nil && o.OperatingOnId != nil { + return true + } + + return false +} + +// SetOperatingOnId gets a reference to the given string and assigns it to the OperatingOnId field. +func (o *ApprovalRequestResponse) SetOperatingOnId(v string) { + o.OperatingOnId = &v +} + +// GetIntegrationMetadata returns the IntegrationMetadata field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetIntegrationMetadata() IntegrationMetadata { + if o == nil || o.IntegrationMetadata == nil { + var ret IntegrationMetadata + return ret + } + return *o.IntegrationMetadata +} + +// GetIntegrationMetadataOk returns a tuple with the IntegrationMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetIntegrationMetadataOk() (*IntegrationMetadata, bool) { + if o == nil || o.IntegrationMetadata == nil { + return nil, false + } + return o.IntegrationMetadata, true +} + +// HasIntegrationMetadata returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasIntegrationMetadata() bool { + if o != nil && o.IntegrationMetadata != nil { + return true + } + + return false +} + +// SetIntegrationMetadata gets a reference to the given IntegrationMetadata and assigns it to the IntegrationMetadata field. +func (o *ApprovalRequestResponse) SetIntegrationMetadata(v IntegrationMetadata) { + o.IntegrationMetadata = &v +} + +// GetSource returns the Source field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetSource() CopiedFromEnv { + if o == nil || o.Source == nil { + var ret CopiedFromEnv + return ret + } + return *o.Source +} + +// GetSourceOk returns a tuple with the Source field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetSourceOk() (*CopiedFromEnv, bool) { + if o == nil || o.Source == nil { + return nil, false + } + return o.Source, true +} + +// HasSource returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasSource() bool { + if o != nil && o.Source != nil { + return true + } + + return false +} + +// SetSource gets a reference to the given CopiedFromEnv and assigns it to the Source field. +func (o *ApprovalRequestResponse) SetSource(v CopiedFromEnv) { + o.Source = &v +} + +// GetCustomWorkflowMetadata returns the CustomWorkflowMetadata field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetCustomWorkflowMetadata() CustomWorkflowMeta { + if o == nil || o.CustomWorkflowMetadata == nil { + var ret CustomWorkflowMeta + return ret + } + return *o.CustomWorkflowMetadata +} + +// GetCustomWorkflowMetadataOk returns a tuple with the CustomWorkflowMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetCustomWorkflowMetadataOk() (*CustomWorkflowMeta, bool) { + if o == nil || o.CustomWorkflowMetadata == nil { + return nil, false + } + return o.CustomWorkflowMetadata, true +} + +// HasCustomWorkflowMetadata returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasCustomWorkflowMetadata() bool { + if o != nil && o.CustomWorkflowMetadata != nil { + return true + } + + return false +} + +// SetCustomWorkflowMetadata gets a reference to the given CustomWorkflowMeta and assigns it to the CustomWorkflowMetadata field. +func (o *ApprovalRequestResponse) SetCustomWorkflowMetadata(v CustomWorkflowMeta) { + o.CustomWorkflowMetadata = &v +} + +// GetResourceId returns the ResourceId field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetResourceId() string { + if o == nil || o.ResourceId == nil { + var ret string + return ret + } + return *o.ResourceId +} + +// GetResourceIdOk returns a tuple with the ResourceId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetResourceIdOk() (*string, bool) { + if o == nil || o.ResourceId == nil { + return nil, false + } + return o.ResourceId, true +} + +// HasResourceId returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasResourceId() bool { + if o != nil && o.ResourceId != nil { + return true + } + + return false +} + +// SetResourceId gets a reference to the given string and assigns it to the ResourceId field. +func (o *ApprovalRequestResponse) SetResourceId(v string) { + o.ResourceId = &v +} + +// GetApprovalSettings returns the ApprovalSettings field value if set, zero value otherwise. +func (o *ApprovalRequestResponse) GetApprovalSettings() ApprovalSettings { + if o == nil || o.ApprovalSettings == nil { + var ret ApprovalSettings + return ret + } + return *o.ApprovalSettings +} + +// GetApprovalSettingsOk returns a tuple with the ApprovalSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalRequestResponse) GetApprovalSettingsOk() (*ApprovalSettings, bool) { + if o == nil || o.ApprovalSettings == nil { + return nil, false + } + return o.ApprovalSettings, true +} + +// HasApprovalSettings returns a boolean if a field has been set. +func (o *ApprovalRequestResponse) HasApprovalSettings() bool { + if o != nil && o.ApprovalSettings != nil { + return true + } + + return false +} + +// SetApprovalSettings gets a reference to the given ApprovalSettings and assigns it to the ApprovalSettings field. +func (o *ApprovalRequestResponse) SetApprovalSettings(v ApprovalSettings) { + o.ApprovalSettings = &v +} + +func (o ApprovalRequestResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["serviceKind"] = o.ServiceKind + } + if o.RequestorId != nil { + toSerialize["requestorId"] = o.RequestorId + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["reviewStatus"] = o.ReviewStatus + } + if true { + toSerialize["allReviews"] = o.AllReviews + } + if true { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.AppliedDate != nil { + toSerialize["appliedDate"] = o.AppliedDate + } + if o.AppliedByMemberId != nil { + toSerialize["appliedByMemberId"] = o.AppliedByMemberId + } + if o.AppliedByServiceTokenId != nil { + toSerialize["appliedByServiceTokenId"] = o.AppliedByServiceTokenId + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["instructions"] = o.Instructions + } + if true { + toSerialize["conflicts"] = o.Conflicts + } + if true { + toSerialize["_links"] = o.Links + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.OperatingOnId != nil { + toSerialize["operatingOnId"] = o.OperatingOnId + } + if o.IntegrationMetadata != nil { + toSerialize["integrationMetadata"] = o.IntegrationMetadata + } + if o.Source != nil { + toSerialize["source"] = o.Source + } + if o.CustomWorkflowMetadata != nil { + toSerialize["customWorkflowMetadata"] = o.CustomWorkflowMetadata + } + if o.ResourceId != nil { + toSerialize["resourceId"] = o.ResourceId + } + if o.ApprovalSettings != nil { + toSerialize["approvalSettings"] = o.ApprovalSettings + } + return json.Marshal(toSerialize) +} + +type NullableApprovalRequestResponse struct { + value *ApprovalRequestResponse + isSet bool +} + +func (v NullableApprovalRequestResponse) Get() *ApprovalRequestResponse { + return v.value +} + +func (v *NullableApprovalRequestResponse) Set(val *ApprovalRequestResponse) { + v.value = val + v.isSet = true +} + +func (v NullableApprovalRequestResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableApprovalRequestResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApprovalRequestResponse(val *ApprovalRequestResponse) *NullableApprovalRequestResponse { + return &NullableApprovalRequestResponse{value: val, isSet: true} +} + +func (v NullableApprovalRequestResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApprovalRequestResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_settings.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_settings.go new file mode 100644 index 00000000..8b343f4e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_approval_settings.go @@ -0,0 +1,430 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApprovalSettings struct for ApprovalSettings +type ApprovalSettings struct { + // If approvals are required for this environment + Required bool `json:"required"` + // Whether to skip approvals for pending changes + BypassApprovalsForPendingChanges bool `json:"bypassApprovalsForPendingChanges"` + // Sets the amount of approvals required before a member can apply a change. The minimum is one and the maximum is five. + MinNumApprovals int32 `json:"minNumApprovals"` + // Allow someone who makes an approval request to apply their own change + CanReviewOwnRequest bool `json:"canReviewOwnRequest"` + // Allow applying the change as long as at least one person has approved + CanApplyDeclinedChanges bool `json:"canApplyDeclinedChanges"` + // Automatically apply changes that have been approved by all reviewers. This field is only applicable for approval services other than LaunchDarkly. + AutoApplyApprovedChanges *bool `json:"autoApplyApprovedChanges,omitempty"` + // Which service to use for managing approvals + ServiceKind string `json:"serviceKind"` + ServiceConfig map[string]interface{} `json:"serviceConfig"` + // Require approval only on flags with the provided tags. Otherwise all flags will require approval. + RequiredApprovalTags []string `json:"requiredApprovalTags"` + // Optional field for integration configuration ID of a custom approval integration. This is an Enterprise-only feature. + ServiceKindConfigurationId *string `json:"serviceKindConfigurationId,omitempty"` + // The kind of resource for which the approval settings apply, for example, flag or segment + ResourceKind *string `json:"resourceKind,omitempty"` +} + +// NewApprovalSettings instantiates a new ApprovalSettings object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApprovalSettings(required bool, bypassApprovalsForPendingChanges bool, minNumApprovals int32, canReviewOwnRequest bool, canApplyDeclinedChanges bool, serviceKind string, serviceConfig map[string]interface{}, requiredApprovalTags []string) *ApprovalSettings { + this := ApprovalSettings{} + this.Required = required + this.BypassApprovalsForPendingChanges = bypassApprovalsForPendingChanges + this.MinNumApprovals = minNumApprovals + this.CanReviewOwnRequest = canReviewOwnRequest + this.CanApplyDeclinedChanges = canApplyDeclinedChanges + this.ServiceKind = serviceKind + this.ServiceConfig = serviceConfig + this.RequiredApprovalTags = requiredApprovalTags + return &this +} + +// NewApprovalSettingsWithDefaults instantiates a new ApprovalSettings object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApprovalSettingsWithDefaults() *ApprovalSettings { + this := ApprovalSettings{} + return &this +} + +// GetRequired returns the Required field value +func (o *ApprovalSettings) GetRequired() bool { + if o == nil { + var ret bool + return ret + } + + return o.Required +} + +// GetRequiredOk returns a tuple with the Required field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetRequiredOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Required, true +} + +// SetRequired sets field value +func (o *ApprovalSettings) SetRequired(v bool) { + o.Required = v +} + +// GetBypassApprovalsForPendingChanges returns the BypassApprovalsForPendingChanges field value +func (o *ApprovalSettings) GetBypassApprovalsForPendingChanges() bool { + if o == nil { + var ret bool + return ret + } + + return o.BypassApprovalsForPendingChanges +} + +// GetBypassApprovalsForPendingChangesOk returns a tuple with the BypassApprovalsForPendingChanges field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetBypassApprovalsForPendingChangesOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.BypassApprovalsForPendingChanges, true +} + +// SetBypassApprovalsForPendingChanges sets field value +func (o *ApprovalSettings) SetBypassApprovalsForPendingChanges(v bool) { + o.BypassApprovalsForPendingChanges = v +} + +// GetMinNumApprovals returns the MinNumApprovals field value +func (o *ApprovalSettings) GetMinNumApprovals() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.MinNumApprovals +} + +// GetMinNumApprovalsOk returns a tuple with the MinNumApprovals field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetMinNumApprovalsOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.MinNumApprovals, true +} + +// SetMinNumApprovals sets field value +func (o *ApprovalSettings) SetMinNumApprovals(v int32) { + o.MinNumApprovals = v +} + +// GetCanReviewOwnRequest returns the CanReviewOwnRequest field value +func (o *ApprovalSettings) GetCanReviewOwnRequest() bool { + if o == nil { + var ret bool + return ret + } + + return o.CanReviewOwnRequest +} + +// GetCanReviewOwnRequestOk returns a tuple with the CanReviewOwnRequest field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetCanReviewOwnRequestOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.CanReviewOwnRequest, true +} + +// SetCanReviewOwnRequest sets field value +func (o *ApprovalSettings) SetCanReviewOwnRequest(v bool) { + o.CanReviewOwnRequest = v +} + +// GetCanApplyDeclinedChanges returns the CanApplyDeclinedChanges field value +func (o *ApprovalSettings) GetCanApplyDeclinedChanges() bool { + if o == nil { + var ret bool + return ret + } + + return o.CanApplyDeclinedChanges +} + +// GetCanApplyDeclinedChangesOk returns a tuple with the CanApplyDeclinedChanges field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetCanApplyDeclinedChangesOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.CanApplyDeclinedChanges, true +} + +// SetCanApplyDeclinedChanges sets field value +func (o *ApprovalSettings) SetCanApplyDeclinedChanges(v bool) { + o.CanApplyDeclinedChanges = v +} + +// GetAutoApplyApprovedChanges returns the AutoApplyApprovedChanges field value if set, zero value otherwise. +func (o *ApprovalSettings) GetAutoApplyApprovedChanges() bool { + if o == nil || o.AutoApplyApprovedChanges == nil { + var ret bool + return ret + } + return *o.AutoApplyApprovedChanges +} + +// GetAutoApplyApprovedChangesOk returns a tuple with the AutoApplyApprovedChanges field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetAutoApplyApprovedChangesOk() (*bool, bool) { + if o == nil || o.AutoApplyApprovedChanges == nil { + return nil, false + } + return o.AutoApplyApprovedChanges, true +} + +// HasAutoApplyApprovedChanges returns a boolean if a field has been set. +func (o *ApprovalSettings) HasAutoApplyApprovedChanges() bool { + if o != nil && o.AutoApplyApprovedChanges != nil { + return true + } + + return false +} + +// SetAutoApplyApprovedChanges gets a reference to the given bool and assigns it to the AutoApplyApprovedChanges field. +func (o *ApprovalSettings) SetAutoApplyApprovedChanges(v bool) { + o.AutoApplyApprovedChanges = &v +} + +// GetServiceKind returns the ServiceKind field value +func (o *ApprovalSettings) GetServiceKind() string { + if o == nil { + var ret string + return ret + } + + return o.ServiceKind +} + +// GetServiceKindOk returns a tuple with the ServiceKind field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetServiceKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ServiceKind, true +} + +// SetServiceKind sets field value +func (o *ApprovalSettings) SetServiceKind(v string) { + o.ServiceKind = v +} + +// GetServiceConfig returns the ServiceConfig field value +func (o *ApprovalSettings) GetServiceConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.ServiceConfig +} + +// GetServiceConfigOk returns a tuple with the ServiceConfig field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetServiceConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.ServiceConfig, true +} + +// SetServiceConfig sets field value +func (o *ApprovalSettings) SetServiceConfig(v map[string]interface{}) { + o.ServiceConfig = v +} + +// GetRequiredApprovalTags returns the RequiredApprovalTags field value +func (o *ApprovalSettings) GetRequiredApprovalTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.RequiredApprovalTags +} + +// GetRequiredApprovalTagsOk returns a tuple with the RequiredApprovalTags field value +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetRequiredApprovalTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.RequiredApprovalTags, true +} + +// SetRequiredApprovalTags sets field value +func (o *ApprovalSettings) SetRequiredApprovalTags(v []string) { + o.RequiredApprovalTags = v +} + +// GetServiceKindConfigurationId returns the ServiceKindConfigurationId field value if set, zero value otherwise. +func (o *ApprovalSettings) GetServiceKindConfigurationId() string { + if o == nil || o.ServiceKindConfigurationId == nil { + var ret string + return ret + } + return *o.ServiceKindConfigurationId +} + +// GetServiceKindConfigurationIdOk returns a tuple with the ServiceKindConfigurationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetServiceKindConfigurationIdOk() (*string, bool) { + if o == nil || o.ServiceKindConfigurationId == nil { + return nil, false + } + return o.ServiceKindConfigurationId, true +} + +// HasServiceKindConfigurationId returns a boolean if a field has been set. +func (o *ApprovalSettings) HasServiceKindConfigurationId() bool { + if o != nil && o.ServiceKindConfigurationId != nil { + return true + } + + return false +} + +// SetServiceKindConfigurationId gets a reference to the given string and assigns it to the ServiceKindConfigurationId field. +func (o *ApprovalSettings) SetServiceKindConfigurationId(v string) { + o.ServiceKindConfigurationId = &v +} + +// GetResourceKind returns the ResourceKind field value if set, zero value otherwise. +func (o *ApprovalSettings) GetResourceKind() string { + if o == nil || o.ResourceKind == nil { + var ret string + return ret + } + return *o.ResourceKind +} + +// GetResourceKindOk returns a tuple with the ResourceKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalSettings) GetResourceKindOk() (*string, bool) { + if o == nil || o.ResourceKind == nil { + return nil, false + } + return o.ResourceKind, true +} + +// HasResourceKind returns a boolean if a field has been set. +func (o *ApprovalSettings) HasResourceKind() bool { + if o != nil && o.ResourceKind != nil { + return true + } + + return false +} + +// SetResourceKind gets a reference to the given string and assigns it to the ResourceKind field. +func (o *ApprovalSettings) SetResourceKind(v string) { + o.ResourceKind = &v +} + +func (o ApprovalSettings) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["required"] = o.Required + } + if true { + toSerialize["bypassApprovalsForPendingChanges"] = o.BypassApprovalsForPendingChanges + } + if true { + toSerialize["minNumApprovals"] = o.MinNumApprovals + } + if true { + toSerialize["canReviewOwnRequest"] = o.CanReviewOwnRequest + } + if true { + toSerialize["canApplyDeclinedChanges"] = o.CanApplyDeclinedChanges + } + if o.AutoApplyApprovedChanges != nil { + toSerialize["autoApplyApprovedChanges"] = o.AutoApplyApprovedChanges + } + if true { + toSerialize["serviceKind"] = o.ServiceKind + } + if true { + toSerialize["serviceConfig"] = o.ServiceConfig + } + if true { + toSerialize["requiredApprovalTags"] = o.RequiredApprovalTags + } + if o.ServiceKindConfigurationId != nil { + toSerialize["serviceKindConfigurationId"] = o.ServiceKindConfigurationId + } + if o.ResourceKind != nil { + toSerialize["resourceKind"] = o.ResourceKind + } + return json.Marshal(toSerialize) +} + +type NullableApprovalSettings struct { + value *ApprovalSettings + isSet bool +} + +func (v NullableApprovalSettings) Get() *ApprovalSettings { + return v.value +} + +func (v *NullableApprovalSettings) Set(val *ApprovalSettings) { + v.value = val + v.isSet = true +} + +func (v NullableApprovalSettings) IsSet() bool { + return v.isSet +} + +func (v *NullableApprovalSettings) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApprovalSettings(val *ApprovalSettings) *NullableApprovalSettings { + return &NullableApprovalSettings{value: val, isSet: true} +} + +func (v NullableApprovalSettings) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApprovalSettings) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_approvals_capability_config.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_approvals_capability_config.go new file mode 100644 index 00000000..45c4e490 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_approvals_capability_config.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ApprovalsCapabilityConfig struct for ApprovalsCapabilityConfig +type ApprovalsCapabilityConfig struct { + // The additional form variables for the approvals capability + AdditionalFormVariables []FormVariable `json:"additionalFormVariables,omitempty"` +} + +// NewApprovalsCapabilityConfig instantiates a new ApprovalsCapabilityConfig object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewApprovalsCapabilityConfig() *ApprovalsCapabilityConfig { + this := ApprovalsCapabilityConfig{} + return &this +} + +// NewApprovalsCapabilityConfigWithDefaults instantiates a new ApprovalsCapabilityConfig object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewApprovalsCapabilityConfigWithDefaults() *ApprovalsCapabilityConfig { + this := ApprovalsCapabilityConfig{} + return &this +} + +// GetAdditionalFormVariables returns the AdditionalFormVariables field value if set, zero value otherwise. +func (o *ApprovalsCapabilityConfig) GetAdditionalFormVariables() []FormVariable { + if o == nil || o.AdditionalFormVariables == nil { + var ret []FormVariable + return ret + } + return o.AdditionalFormVariables +} + +// GetAdditionalFormVariablesOk returns a tuple with the AdditionalFormVariables field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ApprovalsCapabilityConfig) GetAdditionalFormVariablesOk() ([]FormVariable, bool) { + if o == nil || o.AdditionalFormVariables == nil { + return nil, false + } + return o.AdditionalFormVariables, true +} + +// HasAdditionalFormVariables returns a boolean if a field has been set. +func (o *ApprovalsCapabilityConfig) HasAdditionalFormVariables() bool { + if o != nil && o.AdditionalFormVariables != nil { + return true + } + + return false +} + +// SetAdditionalFormVariables gets a reference to the given []FormVariable and assigns it to the AdditionalFormVariables field. +func (o *ApprovalsCapabilityConfig) SetAdditionalFormVariables(v []FormVariable) { + o.AdditionalFormVariables = v +} + +func (o ApprovalsCapabilityConfig) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.AdditionalFormVariables != nil { + toSerialize["additionalFormVariables"] = o.AdditionalFormVariables + } + return json.Marshal(toSerialize) +} + +type NullableApprovalsCapabilityConfig struct { + value *ApprovalsCapabilityConfig + isSet bool +} + +func (v NullableApprovalsCapabilityConfig) Get() *ApprovalsCapabilityConfig { + return v.value +} + +func (v *NullableApprovalsCapabilityConfig) Set(val *ApprovalsCapabilityConfig) { + v.value = val + v.isSet = true +} + +func (v NullableApprovalsCapabilityConfig) IsSet() bool { + return v.isSet +} + +func (v *NullableApprovalsCapabilityConfig) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableApprovalsCapabilityConfig(val *ApprovalsCapabilityConfig) *NullableApprovalsCapabilityConfig { + return &NullableApprovalsCapabilityConfig{value: val, isSet: true} +} + +func (v NullableApprovalsCapabilityConfig) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableApprovalsCapabilityConfig) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_assigned_to_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_assigned_to_rep.go new file mode 100644 index 00000000..1a157875 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_assigned_to_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AssignedToRep struct for AssignedToRep +type AssignedToRep struct { + // The number of individual members this role is assigned to + MembersCount *int32 `json:"membersCount,omitempty"` + // The number of teams this role is assigned to + TeamsCount *int32 `json:"teamsCount,omitempty"` +} + +// NewAssignedToRep instantiates a new AssignedToRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAssignedToRep() *AssignedToRep { + this := AssignedToRep{} + return &this +} + +// NewAssignedToRepWithDefaults instantiates a new AssignedToRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAssignedToRepWithDefaults() *AssignedToRep { + this := AssignedToRep{} + return &this +} + +// GetMembersCount returns the MembersCount field value if set, zero value otherwise. +func (o *AssignedToRep) GetMembersCount() int32 { + if o == nil || o.MembersCount == nil { + var ret int32 + return ret + } + return *o.MembersCount +} + +// GetMembersCountOk returns a tuple with the MembersCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AssignedToRep) GetMembersCountOk() (*int32, bool) { + if o == nil || o.MembersCount == nil { + return nil, false + } + return o.MembersCount, true +} + +// HasMembersCount returns a boolean if a field has been set. +func (o *AssignedToRep) HasMembersCount() bool { + if o != nil && o.MembersCount != nil { + return true + } + + return false +} + +// SetMembersCount gets a reference to the given int32 and assigns it to the MembersCount field. +func (o *AssignedToRep) SetMembersCount(v int32) { + o.MembersCount = &v +} + +// GetTeamsCount returns the TeamsCount field value if set, zero value otherwise. +func (o *AssignedToRep) GetTeamsCount() int32 { + if o == nil || o.TeamsCount == nil { + var ret int32 + return ret + } + return *o.TeamsCount +} + +// GetTeamsCountOk returns a tuple with the TeamsCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AssignedToRep) GetTeamsCountOk() (*int32, bool) { + if o == nil || o.TeamsCount == nil { + return nil, false + } + return o.TeamsCount, true +} + +// HasTeamsCount returns a boolean if a field has been set. +func (o *AssignedToRep) HasTeamsCount() bool { + if o != nil && o.TeamsCount != nil { + return true + } + + return false +} + +// SetTeamsCount gets a reference to the given int32 and assigns it to the TeamsCount field. +func (o *AssignedToRep) SetTeamsCount(v int32) { + o.TeamsCount = &v +} + +func (o AssignedToRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.MembersCount != nil { + toSerialize["membersCount"] = o.MembersCount + } + if o.TeamsCount != nil { + toSerialize["teamsCount"] = o.TeamsCount + } + return json.Marshal(toSerialize) +} + +type NullableAssignedToRep struct { + value *AssignedToRep + isSet bool +} + +func (v NullableAssignedToRep) Get() *AssignedToRep { + return v.value +} + +func (v *NullableAssignedToRep) Set(val *AssignedToRep) { + v.value = val + v.isSet = true +} + +func (v NullableAssignedToRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAssignedToRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAssignedToRep(val *AssignedToRep) *NullableAssignedToRep { + return &NullableAssignedToRep{value: val, isSet: true} +} + +func (v NullableAssignedToRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAssignedToRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audience.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience.go new file mode 100644 index 00000000..a5405aff --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience.go @@ -0,0 +1,219 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Audience struct for Audience +type Audience struct { + Environment *EnvironmentSummary `json:"environment,omitempty"` + // The release phase name + Name string `json:"name"` + Configuration *AudienceConfiguration `json:"configuration,omitempty"` + // A list of segment keys + SegmentKeys []string `json:"segmentKeys,omitempty"` +} + +// NewAudience instantiates a new Audience object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAudience(name string) *Audience { + this := Audience{} + this.Name = name + return &this +} + +// NewAudienceWithDefaults instantiates a new Audience object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAudienceWithDefaults() *Audience { + this := Audience{} + return &this +} + +// GetEnvironment returns the Environment field value if set, zero value otherwise. +func (o *Audience) GetEnvironment() EnvironmentSummary { + if o == nil || o.Environment == nil { + var ret EnvironmentSummary + return ret + } + return *o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Audience) GetEnvironmentOk() (*EnvironmentSummary, bool) { + if o == nil || o.Environment == nil { + return nil, false + } + return o.Environment, true +} + +// HasEnvironment returns a boolean if a field has been set. +func (o *Audience) HasEnvironment() bool { + if o != nil && o.Environment != nil { + return true + } + + return false +} + +// SetEnvironment gets a reference to the given EnvironmentSummary and assigns it to the Environment field. +func (o *Audience) SetEnvironment(v EnvironmentSummary) { + o.Environment = &v +} + +// GetName returns the Name field value +func (o *Audience) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Audience) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Audience) SetName(v string) { + o.Name = v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *Audience) GetConfiguration() AudienceConfiguration { + if o == nil || o.Configuration == nil { + var ret AudienceConfiguration + return ret + } + return *o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Audience) GetConfigurationOk() (*AudienceConfiguration, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *Audience) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given AudienceConfiguration and assigns it to the Configuration field. +func (o *Audience) SetConfiguration(v AudienceConfiguration) { + o.Configuration = &v +} + +// GetSegmentKeys returns the SegmentKeys field value if set, zero value otherwise. +func (o *Audience) GetSegmentKeys() []string { + if o == nil || o.SegmentKeys == nil { + var ret []string + return ret + } + return o.SegmentKeys +} + +// GetSegmentKeysOk returns a tuple with the SegmentKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Audience) GetSegmentKeysOk() ([]string, bool) { + if o == nil || o.SegmentKeys == nil { + return nil, false + } + return o.SegmentKeys, true +} + +// HasSegmentKeys returns a boolean if a field has been set. +func (o *Audience) HasSegmentKeys() bool { + if o != nil && o.SegmentKeys != nil { + return true + } + + return false +} + +// SetSegmentKeys gets a reference to the given []string and assigns it to the SegmentKeys field. +func (o *Audience) SetSegmentKeys(v []string) { + o.SegmentKeys = v +} + +func (o Audience) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Environment != nil { + toSerialize["environment"] = o.Environment + } + if true { + toSerialize["name"] = o.Name + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + if o.SegmentKeys != nil { + toSerialize["segmentKeys"] = o.SegmentKeys + } + return json.Marshal(toSerialize) +} + +type NullableAudience struct { + value *Audience + isSet bool +} + +func (v NullableAudience) Get() *Audience { + return v.value +} + +func (v *NullableAudience) Set(val *Audience) { + v.value = val + v.isSet = true +} + +func (v NullableAudience) IsSet() bool { + return v.isSet +} + +func (v *NullableAudience) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAudience(val *Audience) *NullableAudience { + return &NullableAudience{value: val, isSet: true} +} + +func (v NullableAudience) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAudience) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_configuration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_configuration.go new file mode 100644 index 00000000..7d2bdb4a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_configuration.go @@ -0,0 +1,249 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AudienceConfiguration struct for AudienceConfiguration +type AudienceConfiguration struct { + ReleaseStrategy string `json:"releaseStrategy"` + // Whether or not the audience requires approval + RequireApproval bool `json:"requireApproval"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // An array of team keys. The members of these teams are notified to review the approval request. + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` + ReleaseGuardianConfiguration *ReleaseGuardianConfiguration `json:"releaseGuardianConfiguration,omitempty"` +} + +// NewAudienceConfiguration instantiates a new AudienceConfiguration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAudienceConfiguration(releaseStrategy string, requireApproval bool) *AudienceConfiguration { + this := AudienceConfiguration{} + this.ReleaseStrategy = releaseStrategy + this.RequireApproval = requireApproval + return &this +} + +// NewAudienceConfigurationWithDefaults instantiates a new AudienceConfiguration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAudienceConfigurationWithDefaults() *AudienceConfiguration { + this := AudienceConfiguration{} + return &this +} + +// GetReleaseStrategy returns the ReleaseStrategy field value +func (o *AudienceConfiguration) GetReleaseStrategy() string { + if o == nil { + var ret string + return ret + } + + return o.ReleaseStrategy +} + +// GetReleaseStrategyOk returns a tuple with the ReleaseStrategy field value +// and a boolean to check if the value has been set. +func (o *AudienceConfiguration) GetReleaseStrategyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReleaseStrategy, true +} + +// SetReleaseStrategy sets field value +func (o *AudienceConfiguration) SetReleaseStrategy(v string) { + o.ReleaseStrategy = v +} + +// GetRequireApproval returns the RequireApproval field value +func (o *AudienceConfiguration) GetRequireApproval() bool { + if o == nil { + var ret bool + return ret + } + + return o.RequireApproval +} + +// GetRequireApprovalOk returns a tuple with the RequireApproval field value +// and a boolean to check if the value has been set. +func (o *AudienceConfiguration) GetRequireApprovalOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.RequireApproval, true +} + +// SetRequireApproval sets field value +func (o *AudienceConfiguration) SetRequireApproval(v bool) { + o.RequireApproval = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *AudienceConfiguration) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AudienceConfiguration) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *AudienceConfiguration) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *AudienceConfiguration) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *AudienceConfiguration) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AudienceConfiguration) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *AudienceConfiguration) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *AudienceConfiguration) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +// GetReleaseGuardianConfiguration returns the ReleaseGuardianConfiguration field value if set, zero value otherwise. +func (o *AudienceConfiguration) GetReleaseGuardianConfiguration() ReleaseGuardianConfiguration { + if o == nil || o.ReleaseGuardianConfiguration == nil { + var ret ReleaseGuardianConfiguration + return ret + } + return *o.ReleaseGuardianConfiguration +} + +// GetReleaseGuardianConfigurationOk returns a tuple with the ReleaseGuardianConfiguration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AudienceConfiguration) GetReleaseGuardianConfigurationOk() (*ReleaseGuardianConfiguration, bool) { + if o == nil || o.ReleaseGuardianConfiguration == nil { + return nil, false + } + return o.ReleaseGuardianConfiguration, true +} + +// HasReleaseGuardianConfiguration returns a boolean if a field has been set. +func (o *AudienceConfiguration) HasReleaseGuardianConfiguration() bool { + if o != nil && o.ReleaseGuardianConfiguration != nil { + return true + } + + return false +} + +// SetReleaseGuardianConfiguration gets a reference to the given ReleaseGuardianConfiguration and assigns it to the ReleaseGuardianConfiguration field. +func (o *AudienceConfiguration) SetReleaseGuardianConfiguration(v ReleaseGuardianConfiguration) { + o.ReleaseGuardianConfiguration = &v +} + +func (o AudienceConfiguration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["releaseStrategy"] = o.ReleaseStrategy + } + if true { + toSerialize["requireApproval"] = o.RequireApproval + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + if o.ReleaseGuardianConfiguration != nil { + toSerialize["releaseGuardianConfiguration"] = o.ReleaseGuardianConfiguration + } + return json.Marshal(toSerialize) +} + +type NullableAudienceConfiguration struct { + value *AudienceConfiguration + isSet bool +} + +func (v NullableAudienceConfiguration) Get() *AudienceConfiguration { + return v.value +} + +func (v *NullableAudienceConfiguration) Set(val *AudienceConfiguration) { + v.value = val + v.isSet = true +} + +func (v NullableAudienceConfiguration) IsSet() bool { + return v.isSet +} + +func (v *NullableAudienceConfiguration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAudienceConfiguration(val *AudienceConfiguration) *NullableAudienceConfiguration { + return &NullableAudienceConfiguration{value: val, isSet: true} +} + +func (v NullableAudienceConfiguration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAudienceConfiguration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_post.go new file mode 100644 index 00000000..46458fe3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audience_post.go @@ -0,0 +1,213 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AudiencePost struct for AudiencePost +type AudiencePost struct { + // A project-unique key for the environment. + EnvironmentKey string `json:"environmentKey"` + // The audience name + Name string `json:"name"` + // Segments targeted by this audience. + SegmentKeys []string `json:"segmentKeys,omitempty"` + Configuration *AudienceConfiguration `json:"configuration,omitempty"` +} + +// NewAudiencePost instantiates a new AudiencePost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAudiencePost(environmentKey string, name string) *AudiencePost { + this := AudiencePost{} + this.EnvironmentKey = environmentKey + this.Name = name + return &this +} + +// NewAudiencePostWithDefaults instantiates a new AudiencePost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAudiencePostWithDefaults() *AudiencePost { + this := AudiencePost{} + return &this +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *AudiencePost) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *AudiencePost) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *AudiencePost) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetName returns the Name field value +func (o *AudiencePost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AudiencePost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AudiencePost) SetName(v string) { + o.Name = v +} + +// GetSegmentKeys returns the SegmentKeys field value if set, zero value otherwise. +func (o *AudiencePost) GetSegmentKeys() []string { + if o == nil || o.SegmentKeys == nil { + var ret []string + return ret + } + return o.SegmentKeys +} + +// GetSegmentKeysOk returns a tuple with the SegmentKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AudiencePost) GetSegmentKeysOk() ([]string, bool) { + if o == nil || o.SegmentKeys == nil { + return nil, false + } + return o.SegmentKeys, true +} + +// HasSegmentKeys returns a boolean if a field has been set. +func (o *AudiencePost) HasSegmentKeys() bool { + if o != nil && o.SegmentKeys != nil { + return true + } + + return false +} + +// SetSegmentKeys gets a reference to the given []string and assigns it to the SegmentKeys field. +func (o *AudiencePost) SetSegmentKeys(v []string) { + o.SegmentKeys = v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *AudiencePost) GetConfiguration() AudienceConfiguration { + if o == nil || o.Configuration == nil { + var ret AudienceConfiguration + return ret + } + return *o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AudiencePost) GetConfigurationOk() (*AudienceConfiguration, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *AudiencePost) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given AudienceConfiguration and assigns it to the Configuration field. +func (o *AudiencePost) SetConfiguration(v AudienceConfiguration) { + o.Configuration = &v +} + +func (o AudiencePost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["name"] = o.Name + } + if o.SegmentKeys != nil { + toSerialize["segmentKeys"] = o.SegmentKeys + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + return json.Marshal(toSerialize) +} + +type NullableAudiencePost struct { + value *AudiencePost + isSet bool +} + +func (v NullableAudiencePost) Get() *AudiencePost { + return v.value +} + +func (v *NullableAudiencePost) Set(val *AudiencePost) { + v.value = val + v.isSet = true +} + +func (v NullableAudiencePost) IsSet() bool { + return v.isSet +} + +func (v *NullableAudiencePost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAudiencePost(val *AudiencePost) *NullableAudiencePost { + return &NullableAudiencePost{value: val, isSet: true} +} + +func (v NullableAudiencePost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAudiencePost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep.go new file mode 100644 index 00000000..1bd3ab52 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep.go @@ -0,0 +1,675 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuditLogEntryListingRep struct for AuditLogEntryListingRep +type AuditLogEntryListingRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of the audit log entry + Id string `json:"_id"` + // The ID of the account to which this audit log entry belongs + AccountId string `json:"_accountId"` + Date int64 `json:"date"` + // Details on the actions performed and resources acted on in this audit log entry + Accesses []ResourceAccess `json:"accesses"` + Kind string `json:"kind"` + // The name of the resource this audit log entry refers to + Name string `json:"name"` + // Description of the change recorded in the audit log entry + Description string `json:"description"` + // Shorter version of the change recorded in the audit log entry + ShortDescription string `json:"shortDescription"` + // Optional comment for the audit log entry + Comment *string `json:"comment,omitempty"` + Subject *SubjectDataRep `json:"subject,omitempty"` + Member *MemberDataRep `json:"member,omitempty"` + Token *TokenSummary `json:"token,omitempty"` + App *AuthorizedAppDataRep `json:"app,omitempty"` + // The action and resource recorded in this audit log entry + TitleVerb *string `json:"titleVerb,omitempty"` + // A description of what occurred, in the format member titleVerb target + Title *string `json:"title,omitempty"` + Target *TargetResourceRep `json:"target,omitempty"` + Parent *ParentResourceRep `json:"parent,omitempty"` +} + +// NewAuditLogEntryListingRep instantiates a new AuditLogEntryListingRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuditLogEntryListingRep(links map[string]Link, id string, accountId string, date int64, accesses []ResourceAccess, kind string, name string, description string, shortDescription string) *AuditLogEntryListingRep { + this := AuditLogEntryListingRep{} + this.Links = links + this.Id = id + this.AccountId = accountId + this.Date = date + this.Accesses = accesses + this.Kind = kind + this.Name = name + this.Description = description + this.ShortDescription = shortDescription + return &this +} + +// NewAuditLogEntryListingRepWithDefaults instantiates a new AuditLogEntryListingRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuditLogEntryListingRepWithDefaults() *AuditLogEntryListingRep { + this := AuditLogEntryListingRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *AuditLogEntryListingRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *AuditLogEntryListingRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *AuditLogEntryListingRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *AuditLogEntryListingRep) SetId(v string) { + o.Id = v +} + +// GetAccountId returns the AccountId field value +func (o *AuditLogEntryListingRep) GetAccountId() string { + if o == nil { + var ret string + return ret + } + + return o.AccountId +} + +// GetAccountIdOk returns a tuple with the AccountId field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetAccountIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.AccountId, true +} + +// SetAccountId sets field value +func (o *AuditLogEntryListingRep) SetAccountId(v string) { + o.AccountId = v +} + +// GetDate returns the Date field value +func (o *AuditLogEntryListingRep) GetDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Date +} + +// GetDateOk returns a tuple with the Date field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Date, true +} + +// SetDate sets field value +func (o *AuditLogEntryListingRep) SetDate(v int64) { + o.Date = v +} + +// GetAccesses returns the Accesses field value +func (o *AuditLogEntryListingRep) GetAccesses() []ResourceAccess { + if o == nil { + var ret []ResourceAccess + return ret + } + + return o.Accesses +} + +// GetAccessesOk returns a tuple with the Accesses field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetAccessesOk() ([]ResourceAccess, bool) { + if o == nil { + return nil, false + } + return o.Accesses, true +} + +// SetAccesses sets field value +func (o *AuditLogEntryListingRep) SetAccesses(v []ResourceAccess) { + o.Accesses = v +} + +// GetKind returns the Kind field value +func (o *AuditLogEntryListingRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *AuditLogEntryListingRep) SetKind(v string) { + o.Kind = v +} + +// GetName returns the Name field value +func (o *AuditLogEntryListingRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AuditLogEntryListingRep) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value +func (o *AuditLogEntryListingRep) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *AuditLogEntryListingRep) SetDescription(v string) { + o.Description = v +} + +// GetShortDescription returns the ShortDescription field value +func (o *AuditLogEntryListingRep) GetShortDescription() string { + if o == nil { + var ret string + return ret + } + + return o.ShortDescription +} + +// GetShortDescriptionOk returns a tuple with the ShortDescription field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetShortDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ShortDescription, true +} + +// SetShortDescription sets field value +func (o *AuditLogEntryListingRep) SetShortDescription(v string) { + o.ShortDescription = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *AuditLogEntryListingRep) SetComment(v string) { + o.Comment = &v +} + +// GetSubject returns the Subject field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetSubject() SubjectDataRep { + if o == nil || o.Subject == nil { + var ret SubjectDataRep + return ret + } + return *o.Subject +} + +// GetSubjectOk returns a tuple with the Subject field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetSubjectOk() (*SubjectDataRep, bool) { + if o == nil || o.Subject == nil { + return nil, false + } + return o.Subject, true +} + +// HasSubject returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasSubject() bool { + if o != nil && o.Subject != nil { + return true + } + + return false +} + +// SetSubject gets a reference to the given SubjectDataRep and assigns it to the Subject field. +func (o *AuditLogEntryListingRep) SetSubject(v SubjectDataRep) { + o.Subject = &v +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetMember() MemberDataRep { + if o == nil || o.Member == nil { + var ret MemberDataRep + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetMemberOk() (*MemberDataRep, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given MemberDataRep and assigns it to the Member field. +func (o *AuditLogEntryListingRep) SetMember(v MemberDataRep) { + o.Member = &v +} + +// GetToken returns the Token field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetToken() TokenSummary { + if o == nil || o.Token == nil { + var ret TokenSummary + return ret + } + return *o.Token +} + +// GetTokenOk returns a tuple with the Token field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetTokenOk() (*TokenSummary, bool) { + if o == nil || o.Token == nil { + return nil, false + } + return o.Token, true +} + +// HasToken returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasToken() bool { + if o != nil && o.Token != nil { + return true + } + + return false +} + +// SetToken gets a reference to the given TokenSummary and assigns it to the Token field. +func (o *AuditLogEntryListingRep) SetToken(v TokenSummary) { + o.Token = &v +} + +// GetApp returns the App field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetApp() AuthorizedAppDataRep { + if o == nil || o.App == nil { + var ret AuthorizedAppDataRep + return ret + } + return *o.App +} + +// GetAppOk returns a tuple with the App field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetAppOk() (*AuthorizedAppDataRep, bool) { + if o == nil || o.App == nil { + return nil, false + } + return o.App, true +} + +// HasApp returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasApp() bool { + if o != nil && o.App != nil { + return true + } + + return false +} + +// SetApp gets a reference to the given AuthorizedAppDataRep and assigns it to the App field. +func (o *AuditLogEntryListingRep) SetApp(v AuthorizedAppDataRep) { + o.App = &v +} + +// GetTitleVerb returns the TitleVerb field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetTitleVerb() string { + if o == nil || o.TitleVerb == nil { + var ret string + return ret + } + return *o.TitleVerb +} + +// GetTitleVerbOk returns a tuple with the TitleVerb field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetTitleVerbOk() (*string, bool) { + if o == nil || o.TitleVerb == nil { + return nil, false + } + return o.TitleVerb, true +} + +// HasTitleVerb returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasTitleVerb() bool { + if o != nil && o.TitleVerb != nil { + return true + } + + return false +} + +// SetTitleVerb gets a reference to the given string and assigns it to the TitleVerb field. +func (o *AuditLogEntryListingRep) SetTitleVerb(v string) { + o.TitleVerb = &v +} + +// GetTitle returns the Title field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetTitle() string { + if o == nil || o.Title == nil { + var ret string + return ret + } + return *o.Title +} + +// GetTitleOk returns a tuple with the Title field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetTitleOk() (*string, bool) { + if o == nil || o.Title == nil { + return nil, false + } + return o.Title, true +} + +// HasTitle returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasTitle() bool { + if o != nil && o.Title != nil { + return true + } + + return false +} + +// SetTitle gets a reference to the given string and assigns it to the Title field. +func (o *AuditLogEntryListingRep) SetTitle(v string) { + o.Title = &v +} + +// GetTarget returns the Target field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetTarget() TargetResourceRep { + if o == nil || o.Target == nil { + var ret TargetResourceRep + return ret + } + return *o.Target +} + +// GetTargetOk returns a tuple with the Target field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetTargetOk() (*TargetResourceRep, bool) { + if o == nil || o.Target == nil { + return nil, false + } + return o.Target, true +} + +// HasTarget returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasTarget() bool { + if o != nil && o.Target != nil { + return true + } + + return false +} + +// SetTarget gets a reference to the given TargetResourceRep and assigns it to the Target field. +func (o *AuditLogEntryListingRep) SetTarget(v TargetResourceRep) { + o.Target = &v +} + +// GetParent returns the Parent field value if set, zero value otherwise. +func (o *AuditLogEntryListingRep) GetParent() ParentResourceRep { + if o == nil || o.Parent == nil { + var ret ParentResourceRep + return ret + } + return *o.Parent +} + +// GetParentOk returns a tuple with the Parent field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRep) GetParentOk() (*ParentResourceRep, bool) { + if o == nil || o.Parent == nil { + return nil, false + } + return o.Parent, true +} + +// HasParent returns a boolean if a field has been set. +func (o *AuditLogEntryListingRep) HasParent() bool { + if o != nil && o.Parent != nil { + return true + } + + return false +} + +// SetParent gets a reference to the given ParentResourceRep and assigns it to the Parent field. +func (o *AuditLogEntryListingRep) SetParent(v ParentResourceRep) { + o.Parent = &v +} + +func (o AuditLogEntryListingRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_accountId"] = o.AccountId + } + if true { + toSerialize["date"] = o.Date + } + if true { + toSerialize["accesses"] = o.Accesses + } + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["shortDescription"] = o.ShortDescription + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.Subject != nil { + toSerialize["subject"] = o.Subject + } + if o.Member != nil { + toSerialize["member"] = o.Member + } + if o.Token != nil { + toSerialize["token"] = o.Token + } + if o.App != nil { + toSerialize["app"] = o.App + } + if o.TitleVerb != nil { + toSerialize["titleVerb"] = o.TitleVerb + } + if o.Title != nil { + toSerialize["title"] = o.Title + } + if o.Target != nil { + toSerialize["target"] = o.Target + } + if o.Parent != nil { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableAuditLogEntryListingRep struct { + value *AuditLogEntryListingRep + isSet bool +} + +func (v NullableAuditLogEntryListingRep) Get() *AuditLogEntryListingRep { + return v.value +} + +func (v *NullableAuditLogEntryListingRep) Set(val *AuditLogEntryListingRep) { + v.value = val + v.isSet = true +} + +func (v NullableAuditLogEntryListingRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAuditLogEntryListingRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuditLogEntryListingRep(val *AuditLogEntryListingRep) *NullableAuditLogEntryListingRep { + return &NullableAuditLogEntryListingRep{value: val, isSet: true} +} + +func (v NullableAuditLogEntryListingRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuditLogEntryListingRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep_collection.go new file mode 100644 index 00000000..93027c65 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_listing_rep_collection.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuditLogEntryListingRepCollection struct for AuditLogEntryListingRepCollection +type AuditLogEntryListingRepCollection struct { + // An array of audit log entries + Items []AuditLogEntryListingRep `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewAuditLogEntryListingRepCollection instantiates a new AuditLogEntryListingRepCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuditLogEntryListingRepCollection(items []AuditLogEntryListingRep, links map[string]Link) *AuditLogEntryListingRepCollection { + this := AuditLogEntryListingRepCollection{} + this.Items = items + this.Links = links + return &this +} + +// NewAuditLogEntryListingRepCollectionWithDefaults instantiates a new AuditLogEntryListingRepCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuditLogEntryListingRepCollectionWithDefaults() *AuditLogEntryListingRepCollection { + this := AuditLogEntryListingRepCollection{} + return &this +} + +// GetItems returns the Items field value +func (o *AuditLogEntryListingRepCollection) GetItems() []AuditLogEntryListingRep { + if o == nil { + var ret []AuditLogEntryListingRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRepCollection) GetItemsOk() ([]AuditLogEntryListingRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *AuditLogEntryListingRepCollection) SetItems(v []AuditLogEntryListingRep) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *AuditLogEntryListingRepCollection) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryListingRepCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *AuditLogEntryListingRepCollection) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o AuditLogEntryListingRepCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableAuditLogEntryListingRepCollection struct { + value *AuditLogEntryListingRepCollection + isSet bool +} + +func (v NullableAuditLogEntryListingRepCollection) Get() *AuditLogEntryListingRepCollection { + return v.value +} + +func (v *NullableAuditLogEntryListingRepCollection) Set(val *AuditLogEntryListingRepCollection) { + v.value = val + v.isSet = true +} + +func (v NullableAuditLogEntryListingRepCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableAuditLogEntryListingRepCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuditLogEntryListingRepCollection(val *AuditLogEntryListingRepCollection) *NullableAuditLogEntryListingRepCollection { + return &NullableAuditLogEntryListingRepCollection{value: val, isSet: true} +} + +func (v NullableAuditLogEntryListingRepCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuditLogEntryListingRepCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_rep.go new file mode 100644 index 00000000..2e3986b5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_entry_rep.go @@ -0,0 +1,901 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuditLogEntryRep struct for AuditLogEntryRep +type AuditLogEntryRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of the audit log entry + Id string `json:"_id"` + // The ID of the account to which this audit log entry belongs + AccountId string `json:"_accountId"` + Date int64 `json:"date"` + // Details on the actions performed and resources acted on in this audit log entry + Accesses []ResourceAccess `json:"accesses"` + Kind string `json:"kind"` + // The name of the resource this audit log entry refers to + Name string `json:"name"` + // Description of the change recorded in the audit log entry + Description string `json:"description"` + // Shorter version of the change recorded in the audit log entry + ShortDescription string `json:"shortDescription"` + // Optional comment for the audit log entry + Comment *string `json:"comment,omitempty"` + Subject *SubjectDataRep `json:"subject,omitempty"` + Member *MemberDataRep `json:"member,omitempty"` + Token *TokenSummary `json:"token,omitempty"` + App *AuthorizedAppDataRep `json:"app,omitempty"` + // The action and resource recorded in this audit log entry + TitleVerb *string `json:"titleVerb,omitempty"` + // A description of what occurred, in the format member titleVerb target + Title *string `json:"title,omitempty"` + Target *TargetResourceRep `json:"target,omitempty"` + Parent *ParentResourceRep `json:"parent,omitempty"` + // If the audit log entry has been updated, this is the JSON patch body that was used in the request to update the entity + Delta interface{} `json:"delta,omitempty"` + // A JSON representation of the external trigger for this audit log entry, if any + TriggerBody interface{} `json:"triggerBody,omitempty"` + // A JSON representation of the merge information for this audit log entry, if any + Merge interface{} `json:"merge,omitempty"` + // If the audit log entry has been updated, this is a JSON representation of the previous version of the entity + PreviousVersion interface{} `json:"previousVersion,omitempty"` + // If the audit log entry has been updated, this is a JSON representation of the current version of the entity + CurrentVersion interface{} `json:"currentVersion,omitempty"` + Subentries []AuditLogEntryListingRep `json:"subentries,omitempty"` +} + +// NewAuditLogEntryRep instantiates a new AuditLogEntryRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuditLogEntryRep(links map[string]Link, id string, accountId string, date int64, accesses []ResourceAccess, kind string, name string, description string, shortDescription string) *AuditLogEntryRep { + this := AuditLogEntryRep{} + this.Links = links + this.Id = id + this.AccountId = accountId + this.Date = date + this.Accesses = accesses + this.Kind = kind + this.Name = name + this.Description = description + this.ShortDescription = shortDescription + return &this +} + +// NewAuditLogEntryRepWithDefaults instantiates a new AuditLogEntryRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuditLogEntryRepWithDefaults() *AuditLogEntryRep { + this := AuditLogEntryRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *AuditLogEntryRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *AuditLogEntryRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *AuditLogEntryRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *AuditLogEntryRep) SetId(v string) { + o.Id = v +} + +// GetAccountId returns the AccountId field value +func (o *AuditLogEntryRep) GetAccountId() string { + if o == nil { + var ret string + return ret + } + + return o.AccountId +} + +// GetAccountIdOk returns a tuple with the AccountId field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetAccountIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.AccountId, true +} + +// SetAccountId sets field value +func (o *AuditLogEntryRep) SetAccountId(v string) { + o.AccountId = v +} + +// GetDate returns the Date field value +func (o *AuditLogEntryRep) GetDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Date +} + +// GetDateOk returns a tuple with the Date field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Date, true +} + +// SetDate sets field value +func (o *AuditLogEntryRep) SetDate(v int64) { + o.Date = v +} + +// GetAccesses returns the Accesses field value +func (o *AuditLogEntryRep) GetAccesses() []ResourceAccess { + if o == nil { + var ret []ResourceAccess + return ret + } + + return o.Accesses +} + +// GetAccessesOk returns a tuple with the Accesses field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetAccessesOk() ([]ResourceAccess, bool) { + if o == nil { + return nil, false + } + return o.Accesses, true +} + +// SetAccesses sets field value +func (o *AuditLogEntryRep) SetAccesses(v []ResourceAccess) { + o.Accesses = v +} + +// GetKind returns the Kind field value +func (o *AuditLogEntryRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *AuditLogEntryRep) SetKind(v string) { + o.Kind = v +} + +// GetName returns the Name field value +func (o *AuditLogEntryRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *AuditLogEntryRep) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value +func (o *AuditLogEntryRep) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *AuditLogEntryRep) SetDescription(v string) { + o.Description = v +} + +// GetShortDescription returns the ShortDescription field value +func (o *AuditLogEntryRep) GetShortDescription() string { + if o == nil { + var ret string + return ret + } + + return o.ShortDescription +} + +// GetShortDescriptionOk returns a tuple with the ShortDescription field value +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetShortDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ShortDescription, true +} + +// SetShortDescription sets field value +func (o *AuditLogEntryRep) SetShortDescription(v string) { + o.ShortDescription = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *AuditLogEntryRep) SetComment(v string) { + o.Comment = &v +} + +// GetSubject returns the Subject field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetSubject() SubjectDataRep { + if o == nil || o.Subject == nil { + var ret SubjectDataRep + return ret + } + return *o.Subject +} + +// GetSubjectOk returns a tuple with the Subject field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetSubjectOk() (*SubjectDataRep, bool) { + if o == nil || o.Subject == nil { + return nil, false + } + return o.Subject, true +} + +// HasSubject returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasSubject() bool { + if o != nil && o.Subject != nil { + return true + } + + return false +} + +// SetSubject gets a reference to the given SubjectDataRep and assigns it to the Subject field. +func (o *AuditLogEntryRep) SetSubject(v SubjectDataRep) { + o.Subject = &v +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetMember() MemberDataRep { + if o == nil || o.Member == nil { + var ret MemberDataRep + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetMemberOk() (*MemberDataRep, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given MemberDataRep and assigns it to the Member field. +func (o *AuditLogEntryRep) SetMember(v MemberDataRep) { + o.Member = &v +} + +// GetToken returns the Token field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetToken() TokenSummary { + if o == nil || o.Token == nil { + var ret TokenSummary + return ret + } + return *o.Token +} + +// GetTokenOk returns a tuple with the Token field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetTokenOk() (*TokenSummary, bool) { + if o == nil || o.Token == nil { + return nil, false + } + return o.Token, true +} + +// HasToken returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasToken() bool { + if o != nil && o.Token != nil { + return true + } + + return false +} + +// SetToken gets a reference to the given TokenSummary and assigns it to the Token field. +func (o *AuditLogEntryRep) SetToken(v TokenSummary) { + o.Token = &v +} + +// GetApp returns the App field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetApp() AuthorizedAppDataRep { + if o == nil || o.App == nil { + var ret AuthorizedAppDataRep + return ret + } + return *o.App +} + +// GetAppOk returns a tuple with the App field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetAppOk() (*AuthorizedAppDataRep, bool) { + if o == nil || o.App == nil { + return nil, false + } + return o.App, true +} + +// HasApp returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasApp() bool { + if o != nil && o.App != nil { + return true + } + + return false +} + +// SetApp gets a reference to the given AuthorizedAppDataRep and assigns it to the App field. +func (o *AuditLogEntryRep) SetApp(v AuthorizedAppDataRep) { + o.App = &v +} + +// GetTitleVerb returns the TitleVerb field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetTitleVerb() string { + if o == nil || o.TitleVerb == nil { + var ret string + return ret + } + return *o.TitleVerb +} + +// GetTitleVerbOk returns a tuple with the TitleVerb field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetTitleVerbOk() (*string, bool) { + if o == nil || o.TitleVerb == nil { + return nil, false + } + return o.TitleVerb, true +} + +// HasTitleVerb returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasTitleVerb() bool { + if o != nil && o.TitleVerb != nil { + return true + } + + return false +} + +// SetTitleVerb gets a reference to the given string and assigns it to the TitleVerb field. +func (o *AuditLogEntryRep) SetTitleVerb(v string) { + o.TitleVerb = &v +} + +// GetTitle returns the Title field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetTitle() string { + if o == nil || o.Title == nil { + var ret string + return ret + } + return *o.Title +} + +// GetTitleOk returns a tuple with the Title field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetTitleOk() (*string, bool) { + if o == nil || o.Title == nil { + return nil, false + } + return o.Title, true +} + +// HasTitle returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasTitle() bool { + if o != nil && o.Title != nil { + return true + } + + return false +} + +// SetTitle gets a reference to the given string and assigns it to the Title field. +func (o *AuditLogEntryRep) SetTitle(v string) { + o.Title = &v +} + +// GetTarget returns the Target field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetTarget() TargetResourceRep { + if o == nil || o.Target == nil { + var ret TargetResourceRep + return ret + } + return *o.Target +} + +// GetTargetOk returns a tuple with the Target field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetTargetOk() (*TargetResourceRep, bool) { + if o == nil || o.Target == nil { + return nil, false + } + return o.Target, true +} + +// HasTarget returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasTarget() bool { + if o != nil && o.Target != nil { + return true + } + + return false +} + +// SetTarget gets a reference to the given TargetResourceRep and assigns it to the Target field. +func (o *AuditLogEntryRep) SetTarget(v TargetResourceRep) { + o.Target = &v +} + +// GetParent returns the Parent field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetParent() ParentResourceRep { + if o == nil || o.Parent == nil { + var ret ParentResourceRep + return ret + } + return *o.Parent +} + +// GetParentOk returns a tuple with the Parent field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetParentOk() (*ParentResourceRep, bool) { + if o == nil || o.Parent == nil { + return nil, false + } + return o.Parent, true +} + +// HasParent returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasParent() bool { + if o != nil && o.Parent != nil { + return true + } + + return false +} + +// SetParent gets a reference to the given ParentResourceRep and assigns it to the Parent field. +func (o *AuditLogEntryRep) SetParent(v ParentResourceRep) { + o.Parent = &v +} + +// GetDelta returns the Delta field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AuditLogEntryRep) GetDelta() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Delta +} + +// GetDeltaOk returns a tuple with the Delta field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AuditLogEntryRep) GetDeltaOk() (*interface{}, bool) { + if o == nil || o.Delta == nil { + return nil, false + } + return &o.Delta, true +} + +// HasDelta returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasDelta() bool { + if o != nil && o.Delta != nil { + return true + } + + return false +} + +// SetDelta gets a reference to the given interface{} and assigns it to the Delta field. +func (o *AuditLogEntryRep) SetDelta(v interface{}) { + o.Delta = v +} + +// GetTriggerBody returns the TriggerBody field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AuditLogEntryRep) GetTriggerBody() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.TriggerBody +} + +// GetTriggerBodyOk returns a tuple with the TriggerBody field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AuditLogEntryRep) GetTriggerBodyOk() (*interface{}, bool) { + if o == nil || o.TriggerBody == nil { + return nil, false + } + return &o.TriggerBody, true +} + +// HasTriggerBody returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasTriggerBody() bool { + if o != nil && o.TriggerBody != nil { + return true + } + + return false +} + +// SetTriggerBody gets a reference to the given interface{} and assigns it to the TriggerBody field. +func (o *AuditLogEntryRep) SetTriggerBody(v interface{}) { + o.TriggerBody = v +} + +// GetMerge returns the Merge field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AuditLogEntryRep) GetMerge() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Merge +} + +// GetMergeOk returns a tuple with the Merge field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AuditLogEntryRep) GetMergeOk() (*interface{}, bool) { + if o == nil || o.Merge == nil { + return nil, false + } + return &o.Merge, true +} + +// HasMerge returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasMerge() bool { + if o != nil && o.Merge != nil { + return true + } + + return false +} + +// SetMerge gets a reference to the given interface{} and assigns it to the Merge field. +func (o *AuditLogEntryRep) SetMerge(v interface{}) { + o.Merge = v +} + +// GetPreviousVersion returns the PreviousVersion field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AuditLogEntryRep) GetPreviousVersion() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.PreviousVersion +} + +// GetPreviousVersionOk returns a tuple with the PreviousVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AuditLogEntryRep) GetPreviousVersionOk() (*interface{}, bool) { + if o == nil || o.PreviousVersion == nil { + return nil, false + } + return &o.PreviousVersion, true +} + +// HasPreviousVersion returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasPreviousVersion() bool { + if o != nil && o.PreviousVersion != nil { + return true + } + + return false +} + +// SetPreviousVersion gets a reference to the given interface{} and assigns it to the PreviousVersion field. +func (o *AuditLogEntryRep) SetPreviousVersion(v interface{}) { + o.PreviousVersion = v +} + +// GetCurrentVersion returns the CurrentVersion field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *AuditLogEntryRep) GetCurrentVersion() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.CurrentVersion +} + +// GetCurrentVersionOk returns a tuple with the CurrentVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *AuditLogEntryRep) GetCurrentVersionOk() (*interface{}, bool) { + if o == nil || o.CurrentVersion == nil { + return nil, false + } + return &o.CurrentVersion, true +} + +// HasCurrentVersion returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasCurrentVersion() bool { + if o != nil && o.CurrentVersion != nil { + return true + } + + return false +} + +// SetCurrentVersion gets a reference to the given interface{} and assigns it to the CurrentVersion field. +func (o *AuditLogEntryRep) SetCurrentVersion(v interface{}) { + o.CurrentVersion = v +} + +// GetSubentries returns the Subentries field value if set, zero value otherwise. +func (o *AuditLogEntryRep) GetSubentries() []AuditLogEntryListingRep { + if o == nil || o.Subentries == nil { + var ret []AuditLogEntryListingRep + return ret + } + return o.Subentries +} + +// GetSubentriesOk returns a tuple with the Subentries field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEntryRep) GetSubentriesOk() ([]AuditLogEntryListingRep, bool) { + if o == nil || o.Subentries == nil { + return nil, false + } + return o.Subentries, true +} + +// HasSubentries returns a boolean if a field has been set. +func (o *AuditLogEntryRep) HasSubentries() bool { + if o != nil && o.Subentries != nil { + return true + } + + return false +} + +// SetSubentries gets a reference to the given []AuditLogEntryListingRep and assigns it to the Subentries field. +func (o *AuditLogEntryRep) SetSubentries(v []AuditLogEntryListingRep) { + o.Subentries = v +} + +func (o AuditLogEntryRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_accountId"] = o.AccountId + } + if true { + toSerialize["date"] = o.Date + } + if true { + toSerialize["accesses"] = o.Accesses + } + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["shortDescription"] = o.ShortDescription + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.Subject != nil { + toSerialize["subject"] = o.Subject + } + if o.Member != nil { + toSerialize["member"] = o.Member + } + if o.Token != nil { + toSerialize["token"] = o.Token + } + if o.App != nil { + toSerialize["app"] = o.App + } + if o.TitleVerb != nil { + toSerialize["titleVerb"] = o.TitleVerb + } + if o.Title != nil { + toSerialize["title"] = o.Title + } + if o.Target != nil { + toSerialize["target"] = o.Target + } + if o.Parent != nil { + toSerialize["parent"] = o.Parent + } + if o.Delta != nil { + toSerialize["delta"] = o.Delta + } + if o.TriggerBody != nil { + toSerialize["triggerBody"] = o.TriggerBody + } + if o.Merge != nil { + toSerialize["merge"] = o.Merge + } + if o.PreviousVersion != nil { + toSerialize["previousVersion"] = o.PreviousVersion + } + if o.CurrentVersion != nil { + toSerialize["currentVersion"] = o.CurrentVersion + } + if o.Subentries != nil { + toSerialize["subentries"] = o.Subentries + } + return json.Marshal(toSerialize) +} + +type NullableAuditLogEntryRep struct { + value *AuditLogEntryRep + isSet bool +} + +func (v NullableAuditLogEntryRep) Get() *AuditLogEntryRep { + return v.value +} + +func (v *NullableAuditLogEntryRep) Set(val *AuditLogEntryRep) { + v.value = val + v.isSet = true +} + +func (v NullableAuditLogEntryRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAuditLogEntryRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuditLogEntryRep(val *AuditLogEntryRep) *NullableAuditLogEntryRep { + return &NullableAuditLogEntryRep{value: val, isSet: true} +} + +func (v NullableAuditLogEntryRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuditLogEntryRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_post.go new file mode 100644 index 00000000..46b67306 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_post.go @@ -0,0 +1,116 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuditLogEventsHookCapabilityConfigPost struct for AuditLogEventsHookCapabilityConfigPost +type AuditLogEventsHookCapabilityConfigPost struct { + Statements []StatementPost `json:"statements,omitempty"` +} + +// NewAuditLogEventsHookCapabilityConfigPost instantiates a new AuditLogEventsHookCapabilityConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuditLogEventsHookCapabilityConfigPost() *AuditLogEventsHookCapabilityConfigPost { + this := AuditLogEventsHookCapabilityConfigPost{} + return &this +} + +// NewAuditLogEventsHookCapabilityConfigPostWithDefaults instantiates a new AuditLogEventsHookCapabilityConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuditLogEventsHookCapabilityConfigPostWithDefaults() *AuditLogEventsHookCapabilityConfigPost { + this := AuditLogEventsHookCapabilityConfigPost{} + return &this +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *AuditLogEventsHookCapabilityConfigPost) GetStatements() []StatementPost { + if o == nil || o.Statements == nil { + var ret []StatementPost + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEventsHookCapabilityConfigPost) GetStatementsOk() ([]StatementPost, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *AuditLogEventsHookCapabilityConfigPost) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []StatementPost and assigns it to the Statements field. +func (o *AuditLogEventsHookCapabilityConfigPost) SetStatements(v []StatementPost) { + o.Statements = v +} + +func (o AuditLogEventsHookCapabilityConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + return json.Marshal(toSerialize) +} + +type NullableAuditLogEventsHookCapabilityConfigPost struct { + value *AuditLogEventsHookCapabilityConfigPost + isSet bool +} + +func (v NullableAuditLogEventsHookCapabilityConfigPost) Get() *AuditLogEventsHookCapabilityConfigPost { + return v.value +} + +func (v *NullableAuditLogEventsHookCapabilityConfigPost) Set(val *AuditLogEventsHookCapabilityConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableAuditLogEventsHookCapabilityConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableAuditLogEventsHookCapabilityConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuditLogEventsHookCapabilityConfigPost(val *AuditLogEventsHookCapabilityConfigPost) *NullableAuditLogEventsHookCapabilityConfigPost { + return &NullableAuditLogEventsHookCapabilityConfigPost{value: val, isSet: true} +} + +func (v NullableAuditLogEventsHookCapabilityConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuditLogEventsHookCapabilityConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_rep.go new file mode 100644 index 00000000..4bdb94f0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_audit_log_events_hook_capability_config_rep.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuditLogEventsHookCapabilityConfigRep struct for AuditLogEventsHookCapabilityConfigRep +type AuditLogEventsHookCapabilityConfigRep struct { + // The set of resources you wish to subscribe to audit log notifications for. + Statements []Statement `json:"statements,omitempty"` +} + +// NewAuditLogEventsHookCapabilityConfigRep instantiates a new AuditLogEventsHookCapabilityConfigRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuditLogEventsHookCapabilityConfigRep() *AuditLogEventsHookCapabilityConfigRep { + this := AuditLogEventsHookCapabilityConfigRep{} + return &this +} + +// NewAuditLogEventsHookCapabilityConfigRepWithDefaults instantiates a new AuditLogEventsHookCapabilityConfigRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuditLogEventsHookCapabilityConfigRepWithDefaults() *AuditLogEventsHookCapabilityConfigRep { + this := AuditLogEventsHookCapabilityConfigRep{} + return &this +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *AuditLogEventsHookCapabilityConfigRep) GetStatements() []Statement { + if o == nil || o.Statements == nil { + var ret []Statement + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuditLogEventsHookCapabilityConfigRep) GetStatementsOk() ([]Statement, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *AuditLogEventsHookCapabilityConfigRep) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []Statement and assigns it to the Statements field. +func (o *AuditLogEventsHookCapabilityConfigRep) SetStatements(v []Statement) { + o.Statements = v +} + +func (o AuditLogEventsHookCapabilityConfigRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + return json.Marshal(toSerialize) +} + +type NullableAuditLogEventsHookCapabilityConfigRep struct { + value *AuditLogEventsHookCapabilityConfigRep + isSet bool +} + +func (v NullableAuditLogEventsHookCapabilityConfigRep) Get() *AuditLogEventsHookCapabilityConfigRep { + return v.value +} + +func (v *NullableAuditLogEventsHookCapabilityConfigRep) Set(val *AuditLogEventsHookCapabilityConfigRep) { + v.value = val + v.isSet = true +} + +func (v NullableAuditLogEventsHookCapabilityConfigRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAuditLogEventsHookCapabilityConfigRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuditLogEventsHookCapabilityConfigRep(val *AuditLogEventsHookCapabilityConfigRep) *NullableAuditLogEventsHookCapabilityConfigRep { + return &NullableAuditLogEventsHookCapabilityConfigRep{value: val, isSet: true} +} + +func (v NullableAuditLogEventsHookCapabilityConfigRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuditLogEventsHookCapabilityConfigRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_authorized_app_data_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_authorized_app_data_rep.go new file mode 100644 index 00000000..2e5b9901 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_authorized_app_data_rep.go @@ -0,0 +1,264 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// AuthorizedAppDataRep struct for AuthorizedAppDataRep +type AuthorizedAppDataRep struct { + Links *map[string]Link `json:"_links,omitempty"` + // The ID of the authorized application + Id *string `json:"_id,omitempty"` + // Whether the application is authorized through SCIM + IsScim *bool `json:"isScim,omitempty"` + // The authorized application name + Name *string `json:"name,omitempty"` + // The name of the maintainer for this authorized application + MaintainerName *string `json:"maintainerName,omitempty"` +} + +// NewAuthorizedAppDataRep instantiates a new AuthorizedAppDataRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewAuthorizedAppDataRep() *AuthorizedAppDataRep { + this := AuthorizedAppDataRep{} + return &this +} + +// NewAuthorizedAppDataRepWithDefaults instantiates a new AuthorizedAppDataRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewAuthorizedAppDataRepWithDefaults() *AuthorizedAppDataRep { + this := AuthorizedAppDataRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *AuthorizedAppDataRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuthorizedAppDataRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *AuthorizedAppDataRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *AuthorizedAppDataRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *AuthorizedAppDataRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuthorizedAppDataRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *AuthorizedAppDataRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *AuthorizedAppDataRep) SetId(v string) { + o.Id = &v +} + +// GetIsScim returns the IsScim field value if set, zero value otherwise. +func (o *AuthorizedAppDataRep) GetIsScim() bool { + if o == nil || o.IsScim == nil { + var ret bool + return ret + } + return *o.IsScim +} + +// GetIsScimOk returns a tuple with the IsScim field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuthorizedAppDataRep) GetIsScimOk() (*bool, bool) { + if o == nil || o.IsScim == nil { + return nil, false + } + return o.IsScim, true +} + +// HasIsScim returns a boolean if a field has been set. +func (o *AuthorizedAppDataRep) HasIsScim() bool { + if o != nil && o.IsScim != nil { + return true + } + + return false +} + +// SetIsScim gets a reference to the given bool and assigns it to the IsScim field. +func (o *AuthorizedAppDataRep) SetIsScim(v bool) { + o.IsScim = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *AuthorizedAppDataRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuthorizedAppDataRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *AuthorizedAppDataRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *AuthorizedAppDataRep) SetName(v string) { + o.Name = &v +} + +// GetMaintainerName returns the MaintainerName field value if set, zero value otherwise. +func (o *AuthorizedAppDataRep) GetMaintainerName() string { + if o == nil || o.MaintainerName == nil { + var ret string + return ret + } + return *o.MaintainerName +} + +// GetMaintainerNameOk returns a tuple with the MaintainerName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AuthorizedAppDataRep) GetMaintainerNameOk() (*string, bool) { + if o == nil || o.MaintainerName == nil { + return nil, false + } + return o.MaintainerName, true +} + +// HasMaintainerName returns a boolean if a field has been set. +func (o *AuthorizedAppDataRep) HasMaintainerName() bool { + if o != nil && o.MaintainerName != nil { + return true + } + + return false +} + +// SetMaintainerName gets a reference to the given string and assigns it to the MaintainerName field. +func (o *AuthorizedAppDataRep) SetMaintainerName(v string) { + o.MaintainerName = &v +} + +func (o AuthorizedAppDataRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.IsScim != nil { + toSerialize["isScim"] = o.IsScim + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.MaintainerName != nil { + toSerialize["maintainerName"] = o.MaintainerName + } + return json.Marshal(toSerialize) +} + +type NullableAuthorizedAppDataRep struct { + value *AuthorizedAppDataRep + isSet bool +} + +func (v NullableAuthorizedAppDataRep) Get() *AuthorizedAppDataRep { + return v.value +} + +func (v *NullableAuthorizedAppDataRep) Set(val *AuthorizedAppDataRep) { + v.value = val + v.isSet = true +} + +func (v NullableAuthorizedAppDataRep) IsSet() bool { + return v.isSet +} + +func (v *NullableAuthorizedAppDataRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAuthorizedAppDataRep(val *AuthorizedAppDataRep) *NullableAuthorizedAppDataRep { + return &NullableAuthorizedAppDataRep{value: val, isSet: true} +} + +func (v NullableAuthorizedAppDataRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAuthorizedAppDataRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_beta_binomial_stats_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_beta_binomial_stats_rep.go new file mode 100644 index 00000000..0f0b93ea --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_beta_binomial_stats_rep.go @@ -0,0 +1,228 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BayesianBetaBinomialStatsRep struct for BayesianBetaBinomialStatsRep +type BayesianBetaBinomialStatsRep struct { + // Sum of converted pseudo-units for prior distribution + PriorAlpha *float32 `json:"priorAlpha,omitempty"` + // Sum of non-converted pseudo-units for prior distribution + PriorBeta *float32 `json:"priorBeta,omitempty"` + // Mean of the prior distribution + PriorMean *float32 `json:"priorMean,omitempty"` + // The precision weight of the data mean + DataWeight *float32 `json:"dataWeight,omitempty"` +} + +// NewBayesianBetaBinomialStatsRep instantiates a new BayesianBetaBinomialStatsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBayesianBetaBinomialStatsRep() *BayesianBetaBinomialStatsRep { + this := BayesianBetaBinomialStatsRep{} + return &this +} + +// NewBayesianBetaBinomialStatsRepWithDefaults instantiates a new BayesianBetaBinomialStatsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBayesianBetaBinomialStatsRepWithDefaults() *BayesianBetaBinomialStatsRep { + this := BayesianBetaBinomialStatsRep{} + return &this +} + +// GetPriorAlpha returns the PriorAlpha field value if set, zero value otherwise. +func (o *BayesianBetaBinomialStatsRep) GetPriorAlpha() float32 { + if o == nil || o.PriorAlpha == nil { + var ret float32 + return ret + } + return *o.PriorAlpha +} + +// GetPriorAlphaOk returns a tuple with the PriorAlpha field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianBetaBinomialStatsRep) GetPriorAlphaOk() (*float32, bool) { + if o == nil || o.PriorAlpha == nil { + return nil, false + } + return o.PriorAlpha, true +} + +// HasPriorAlpha returns a boolean if a field has been set. +func (o *BayesianBetaBinomialStatsRep) HasPriorAlpha() bool { + if o != nil && o.PriorAlpha != nil { + return true + } + + return false +} + +// SetPriorAlpha gets a reference to the given float32 and assigns it to the PriorAlpha field. +func (o *BayesianBetaBinomialStatsRep) SetPriorAlpha(v float32) { + o.PriorAlpha = &v +} + +// GetPriorBeta returns the PriorBeta field value if set, zero value otherwise. +func (o *BayesianBetaBinomialStatsRep) GetPriorBeta() float32 { + if o == nil || o.PriorBeta == nil { + var ret float32 + return ret + } + return *o.PriorBeta +} + +// GetPriorBetaOk returns a tuple with the PriorBeta field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianBetaBinomialStatsRep) GetPriorBetaOk() (*float32, bool) { + if o == nil || o.PriorBeta == nil { + return nil, false + } + return o.PriorBeta, true +} + +// HasPriorBeta returns a boolean if a field has been set. +func (o *BayesianBetaBinomialStatsRep) HasPriorBeta() bool { + if o != nil && o.PriorBeta != nil { + return true + } + + return false +} + +// SetPriorBeta gets a reference to the given float32 and assigns it to the PriorBeta field. +func (o *BayesianBetaBinomialStatsRep) SetPriorBeta(v float32) { + o.PriorBeta = &v +} + +// GetPriorMean returns the PriorMean field value if set, zero value otherwise. +func (o *BayesianBetaBinomialStatsRep) GetPriorMean() float32 { + if o == nil || o.PriorMean == nil { + var ret float32 + return ret + } + return *o.PriorMean +} + +// GetPriorMeanOk returns a tuple with the PriorMean field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianBetaBinomialStatsRep) GetPriorMeanOk() (*float32, bool) { + if o == nil || o.PriorMean == nil { + return nil, false + } + return o.PriorMean, true +} + +// HasPriorMean returns a boolean if a field has been set. +func (o *BayesianBetaBinomialStatsRep) HasPriorMean() bool { + if o != nil && o.PriorMean != nil { + return true + } + + return false +} + +// SetPriorMean gets a reference to the given float32 and assigns it to the PriorMean field. +func (o *BayesianBetaBinomialStatsRep) SetPriorMean(v float32) { + o.PriorMean = &v +} + +// GetDataWeight returns the DataWeight field value if set, zero value otherwise. +func (o *BayesianBetaBinomialStatsRep) GetDataWeight() float32 { + if o == nil || o.DataWeight == nil { + var ret float32 + return ret + } + return *o.DataWeight +} + +// GetDataWeightOk returns a tuple with the DataWeight field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianBetaBinomialStatsRep) GetDataWeightOk() (*float32, bool) { + if o == nil || o.DataWeight == nil { + return nil, false + } + return o.DataWeight, true +} + +// HasDataWeight returns a boolean if a field has been set. +func (o *BayesianBetaBinomialStatsRep) HasDataWeight() bool { + if o != nil && o.DataWeight != nil { + return true + } + + return false +} + +// SetDataWeight gets a reference to the given float32 and assigns it to the DataWeight field. +func (o *BayesianBetaBinomialStatsRep) SetDataWeight(v float32) { + o.DataWeight = &v +} + +func (o BayesianBetaBinomialStatsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.PriorAlpha != nil { + toSerialize["priorAlpha"] = o.PriorAlpha + } + if o.PriorBeta != nil { + toSerialize["priorBeta"] = o.PriorBeta + } + if o.PriorMean != nil { + toSerialize["priorMean"] = o.PriorMean + } + if o.DataWeight != nil { + toSerialize["dataWeight"] = o.DataWeight + } + return json.Marshal(toSerialize) +} + +type NullableBayesianBetaBinomialStatsRep struct { + value *BayesianBetaBinomialStatsRep + isSet bool +} + +func (v NullableBayesianBetaBinomialStatsRep) Get() *BayesianBetaBinomialStatsRep { + return v.value +} + +func (v *NullableBayesianBetaBinomialStatsRep) Set(val *BayesianBetaBinomialStatsRep) { + v.value = val + v.isSet = true +} + +func (v NullableBayesianBetaBinomialStatsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBayesianBetaBinomialStatsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBayesianBetaBinomialStatsRep(val *BayesianBetaBinomialStatsRep) *NullableBayesianBetaBinomialStatsRep { + return &NullableBayesianBetaBinomialStatsRep{value: val, isSet: true} +} + +func (v NullableBayesianBetaBinomialStatsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBayesianBetaBinomialStatsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_normal_stats_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_normal_stats_rep.go new file mode 100644 index 00000000..246cebde --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_bayesian_normal_stats_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BayesianNormalStatsRep struct for BayesianNormalStatsRep +type BayesianNormalStatsRep struct { + // The precision weight of the data mean + DataWeight *float32 `json:"dataWeight,omitempty"` + // Mean of the prior distribution + PriorMean *float32 `json:"priorMean,omitempty"` +} + +// NewBayesianNormalStatsRep instantiates a new BayesianNormalStatsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBayesianNormalStatsRep() *BayesianNormalStatsRep { + this := BayesianNormalStatsRep{} + return &this +} + +// NewBayesianNormalStatsRepWithDefaults instantiates a new BayesianNormalStatsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBayesianNormalStatsRepWithDefaults() *BayesianNormalStatsRep { + this := BayesianNormalStatsRep{} + return &this +} + +// GetDataWeight returns the DataWeight field value if set, zero value otherwise. +func (o *BayesianNormalStatsRep) GetDataWeight() float32 { + if o == nil || o.DataWeight == nil { + var ret float32 + return ret + } + return *o.DataWeight +} + +// GetDataWeightOk returns a tuple with the DataWeight field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianNormalStatsRep) GetDataWeightOk() (*float32, bool) { + if o == nil || o.DataWeight == nil { + return nil, false + } + return o.DataWeight, true +} + +// HasDataWeight returns a boolean if a field has been set. +func (o *BayesianNormalStatsRep) HasDataWeight() bool { + if o != nil && o.DataWeight != nil { + return true + } + + return false +} + +// SetDataWeight gets a reference to the given float32 and assigns it to the DataWeight field. +func (o *BayesianNormalStatsRep) SetDataWeight(v float32) { + o.DataWeight = &v +} + +// GetPriorMean returns the PriorMean field value if set, zero value otherwise. +func (o *BayesianNormalStatsRep) GetPriorMean() float32 { + if o == nil || o.PriorMean == nil { + var ret float32 + return ret + } + return *o.PriorMean +} + +// GetPriorMeanOk returns a tuple with the PriorMean field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BayesianNormalStatsRep) GetPriorMeanOk() (*float32, bool) { + if o == nil || o.PriorMean == nil { + return nil, false + } + return o.PriorMean, true +} + +// HasPriorMean returns a boolean if a field has been set. +func (o *BayesianNormalStatsRep) HasPriorMean() bool { + if o != nil && o.PriorMean != nil { + return true + } + + return false +} + +// SetPriorMean gets a reference to the given float32 and assigns it to the PriorMean field. +func (o *BayesianNormalStatsRep) SetPriorMean(v float32) { + o.PriorMean = &v +} + +func (o BayesianNormalStatsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.DataWeight != nil { + toSerialize["dataWeight"] = o.DataWeight + } + if o.PriorMean != nil { + toSerialize["priorMean"] = o.PriorMean + } + return json.Marshal(toSerialize) +} + +type NullableBayesianNormalStatsRep struct { + value *BayesianNormalStatsRep + isSet bool +} + +func (v NullableBayesianNormalStatsRep) Get() *BayesianNormalStatsRep { + return v.value +} + +func (v *NullableBayesianNormalStatsRep) Set(val *BayesianNormalStatsRep) { + v.value = val + v.isSet = true +} + +func (v NullableBayesianNormalStatsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBayesianNormalStatsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBayesianNormalStatsRep(val *BayesianNormalStatsRep) *NullableBayesianNormalStatsRep { + return &NullableBayesianNormalStatsRep{value: val, isSet: true} +} + +func (v NullableBayesianNormalStatsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBayesianNormalStatsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration.go new file mode 100644 index 00000000..ef95c5e4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration.go @@ -0,0 +1,443 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentStoreIntegration struct for BigSegmentStoreIntegration +type BigSegmentStoreIntegration struct { + Links BigSegmentStoreIntegrationLinks `json:"_links"` + // The integration ID + Id string `json:"_id"` + // The integration key + IntegrationKey string `json:"integrationKey"` + // The project key + ProjectKey string `json:"projectKey"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + Config map[string]interface{} `json:"config"` + // Whether the configuration is turned on + On bool `json:"on"` + // List of tags for this configuration + Tags []string `json:"tags"` + // Name of the configuration + Name string `json:"name"` + // Version of the current configuration + Version int32 `json:"version"` + Access *Access `json:"_access,omitempty"` + Status BigSegmentStoreStatus `json:"_status"` +} + +// NewBigSegmentStoreIntegration instantiates a new BigSegmentStoreIntegration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentStoreIntegration(links BigSegmentStoreIntegrationLinks, id string, integrationKey string, projectKey string, environmentKey string, config map[string]interface{}, on bool, tags []string, name string, version int32, status BigSegmentStoreStatus) *BigSegmentStoreIntegration { + this := BigSegmentStoreIntegration{} + this.Links = links + this.Id = id + this.IntegrationKey = integrationKey + this.ProjectKey = projectKey + this.EnvironmentKey = environmentKey + this.Config = config + this.On = on + this.Tags = tags + this.Name = name + this.Version = version + this.Status = status + return &this +} + +// NewBigSegmentStoreIntegrationWithDefaults instantiates a new BigSegmentStoreIntegration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentStoreIntegrationWithDefaults() *BigSegmentStoreIntegration { + this := BigSegmentStoreIntegration{} + return &this +} + +// GetLinks returns the Links field value +func (o *BigSegmentStoreIntegration) GetLinks() BigSegmentStoreIntegrationLinks { + if o == nil { + var ret BigSegmentStoreIntegrationLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetLinksOk() (*BigSegmentStoreIntegrationLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *BigSegmentStoreIntegration) SetLinks(v BigSegmentStoreIntegrationLinks) { + o.Links = v +} + +// GetId returns the Id field value +func (o *BigSegmentStoreIntegration) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *BigSegmentStoreIntegration) SetId(v string) { + o.Id = v +} + +// GetIntegrationKey returns the IntegrationKey field value +func (o *BigSegmentStoreIntegration) GetIntegrationKey() string { + if o == nil { + var ret string + return ret + } + + return o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetIntegrationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.IntegrationKey, true +} + +// SetIntegrationKey sets field value +func (o *BigSegmentStoreIntegration) SetIntegrationKey(v string) { + o.IntegrationKey = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *BigSegmentStoreIntegration) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *BigSegmentStoreIntegration) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *BigSegmentStoreIntegration) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *BigSegmentStoreIntegration) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetConfig returns the Config field value +func (o *BigSegmentStoreIntegration) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *BigSegmentStoreIntegration) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetOn returns the On field value +func (o *BigSegmentStoreIntegration) GetOn() bool { + if o == nil { + var ret bool + return ret + } + + return o.On +} + +// GetOnOk returns a tuple with the On field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetOnOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.On, true +} + +// SetOn sets field value +func (o *BigSegmentStoreIntegration) SetOn(v bool) { + o.On = v +} + +// GetTags returns the Tags field value +func (o *BigSegmentStoreIntegration) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *BigSegmentStoreIntegration) SetTags(v []string) { + o.Tags = v +} + +// GetName returns the Name field value +func (o *BigSegmentStoreIntegration) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *BigSegmentStoreIntegration) SetName(v string) { + o.Name = v +} + +// GetVersion returns the Version field value +func (o *BigSegmentStoreIntegration) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *BigSegmentStoreIntegration) SetVersion(v int32) { + o.Version = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *BigSegmentStoreIntegration) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *BigSegmentStoreIntegration) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *BigSegmentStoreIntegration) SetAccess(v Access) { + o.Access = &v +} + +// GetStatus returns the Status field value +func (o *BigSegmentStoreIntegration) GetStatus() BigSegmentStoreStatus { + if o == nil { + var ret BigSegmentStoreStatus + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegration) GetStatusOk() (*BigSegmentStoreStatus, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *BigSegmentStoreIntegration) SetStatus(v BigSegmentStoreStatus) { + o.Status = v +} + +func (o BigSegmentStoreIntegration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["integrationKey"] = o.IntegrationKey + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["config"] = o.Config + } + if true { + toSerialize["on"] = o.On + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["version"] = o.Version + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["_status"] = o.Status + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentStoreIntegration struct { + value *BigSegmentStoreIntegration + isSet bool +} + +func (v NullableBigSegmentStoreIntegration) Get() *BigSegmentStoreIntegration { + return v.value +} + +func (v *NullableBigSegmentStoreIntegration) Set(val *BigSegmentStoreIntegration) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentStoreIntegration) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentStoreIntegration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentStoreIntegration(val *BigSegmentStoreIntegration) *NullableBigSegmentStoreIntegration { + return &NullableBigSegmentStoreIntegration{value: val, isSet: true} +} + +func (v NullableBigSegmentStoreIntegration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentStoreIntegration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection.go new file mode 100644 index 00000000..a9325afa --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentStoreIntegrationCollection struct for BigSegmentStoreIntegrationCollection +type BigSegmentStoreIntegrationCollection struct { + Links BigSegmentStoreIntegrationCollectionLinks `json:"_links"` + // An array of persistent store integration configurations + Items []BigSegmentStoreIntegration `json:"items"` +} + +// NewBigSegmentStoreIntegrationCollection instantiates a new BigSegmentStoreIntegrationCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentStoreIntegrationCollection(links BigSegmentStoreIntegrationCollectionLinks, items []BigSegmentStoreIntegration) *BigSegmentStoreIntegrationCollection { + this := BigSegmentStoreIntegrationCollection{} + this.Links = links + this.Items = items + return &this +} + +// NewBigSegmentStoreIntegrationCollectionWithDefaults instantiates a new BigSegmentStoreIntegrationCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentStoreIntegrationCollectionWithDefaults() *BigSegmentStoreIntegrationCollection { + this := BigSegmentStoreIntegrationCollection{} + return &this +} + +// GetLinks returns the Links field value +func (o *BigSegmentStoreIntegrationCollection) GetLinks() BigSegmentStoreIntegrationCollectionLinks { + if o == nil { + var ret BigSegmentStoreIntegrationCollectionLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationCollection) GetLinksOk() (*BigSegmentStoreIntegrationCollectionLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *BigSegmentStoreIntegrationCollection) SetLinks(v BigSegmentStoreIntegrationCollectionLinks) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *BigSegmentStoreIntegrationCollection) GetItems() []BigSegmentStoreIntegration { + if o == nil { + var ret []BigSegmentStoreIntegration + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationCollection) GetItemsOk() ([]BigSegmentStoreIntegration, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *BigSegmentStoreIntegrationCollection) SetItems(v []BigSegmentStoreIntegration) { + o.Items = v +} + +func (o BigSegmentStoreIntegrationCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentStoreIntegrationCollection struct { + value *BigSegmentStoreIntegrationCollection + isSet bool +} + +func (v NullableBigSegmentStoreIntegrationCollection) Get() *BigSegmentStoreIntegrationCollection { + return v.value +} + +func (v *NullableBigSegmentStoreIntegrationCollection) Set(val *BigSegmentStoreIntegrationCollection) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentStoreIntegrationCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentStoreIntegrationCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentStoreIntegrationCollection(val *BigSegmentStoreIntegrationCollection) *NullableBigSegmentStoreIntegrationCollection { + return &NullableBigSegmentStoreIntegrationCollection{value: val, isSet: true} +} + +func (v NullableBigSegmentStoreIntegrationCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentStoreIntegrationCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection_links.go new file mode 100644 index 00000000..262c3e6f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_collection_links.go @@ -0,0 +1,145 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentStoreIntegrationCollectionLinks struct for BigSegmentStoreIntegrationCollectionLinks +type BigSegmentStoreIntegrationCollectionLinks struct { + Self Link `json:"self"` + Parent *Link `json:"parent,omitempty"` +} + +// NewBigSegmentStoreIntegrationCollectionLinks instantiates a new BigSegmentStoreIntegrationCollectionLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentStoreIntegrationCollectionLinks(self Link) *BigSegmentStoreIntegrationCollectionLinks { + this := BigSegmentStoreIntegrationCollectionLinks{} + this.Self = self + return &this +} + +// NewBigSegmentStoreIntegrationCollectionLinksWithDefaults instantiates a new BigSegmentStoreIntegrationCollectionLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentStoreIntegrationCollectionLinksWithDefaults() *BigSegmentStoreIntegrationCollectionLinks { + this := BigSegmentStoreIntegrationCollectionLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *BigSegmentStoreIntegrationCollectionLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationCollectionLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *BigSegmentStoreIntegrationCollectionLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value if set, zero value otherwise. +func (o *BigSegmentStoreIntegrationCollectionLinks) GetParent() Link { + if o == nil || o.Parent == nil { + var ret Link + return ret + } + return *o.Parent +} + +// GetParentOk returns a tuple with the Parent field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationCollectionLinks) GetParentOk() (*Link, bool) { + if o == nil || o.Parent == nil { + return nil, false + } + return o.Parent, true +} + +// HasParent returns a boolean if a field has been set. +func (o *BigSegmentStoreIntegrationCollectionLinks) HasParent() bool { + if o != nil && o.Parent != nil { + return true + } + + return false +} + +// SetParent gets a reference to the given Link and assigns it to the Parent field. +func (o *BigSegmentStoreIntegrationCollectionLinks) SetParent(v Link) { + o.Parent = &v +} + +func (o BigSegmentStoreIntegrationCollectionLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if o.Parent != nil { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentStoreIntegrationCollectionLinks struct { + value *BigSegmentStoreIntegrationCollectionLinks + isSet bool +} + +func (v NullableBigSegmentStoreIntegrationCollectionLinks) Get() *BigSegmentStoreIntegrationCollectionLinks { + return v.value +} + +func (v *NullableBigSegmentStoreIntegrationCollectionLinks) Set(val *BigSegmentStoreIntegrationCollectionLinks) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentStoreIntegrationCollectionLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentStoreIntegrationCollectionLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentStoreIntegrationCollectionLinks(val *BigSegmentStoreIntegrationCollectionLinks) *NullableBigSegmentStoreIntegrationCollectionLinks { + return &NullableBigSegmentStoreIntegrationCollectionLinks{value: val, isSet: true} +} + +func (v NullableBigSegmentStoreIntegrationCollectionLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentStoreIntegrationCollectionLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_links.go new file mode 100644 index 00000000..9fc4a58f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_integration_links.go @@ -0,0 +1,196 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentStoreIntegrationLinks struct for BigSegmentStoreIntegrationLinks +type BigSegmentStoreIntegrationLinks struct { + Self Link `json:"self"` + Parent Link `json:"parent"` + Project Link `json:"project"` + Environment Link `json:"environment"` +} + +// NewBigSegmentStoreIntegrationLinks instantiates a new BigSegmentStoreIntegrationLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentStoreIntegrationLinks(self Link, parent Link, project Link, environment Link) *BigSegmentStoreIntegrationLinks { + this := BigSegmentStoreIntegrationLinks{} + this.Self = self + this.Parent = parent + this.Project = project + this.Environment = environment + return &this +} + +// NewBigSegmentStoreIntegrationLinksWithDefaults instantiates a new BigSegmentStoreIntegrationLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentStoreIntegrationLinksWithDefaults() *BigSegmentStoreIntegrationLinks { + this := BigSegmentStoreIntegrationLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *BigSegmentStoreIntegrationLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *BigSegmentStoreIntegrationLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value +func (o *BigSegmentStoreIntegrationLinks) GetParent() Link { + if o == nil { + var ret Link + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationLinks) GetParentOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *BigSegmentStoreIntegrationLinks) SetParent(v Link) { + o.Parent = v +} + +// GetProject returns the Project field value +func (o *BigSegmentStoreIntegrationLinks) GetProject() Link { + if o == nil { + var ret Link + return ret + } + + return o.Project +} + +// GetProjectOk returns a tuple with the Project field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationLinks) GetProjectOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Project, true +} + +// SetProject sets field value +func (o *BigSegmentStoreIntegrationLinks) SetProject(v Link) { + o.Project = v +} + +// GetEnvironment returns the Environment field value +func (o *BigSegmentStoreIntegrationLinks) GetEnvironment() Link { + if o == nil { + var ret Link + return ret + } + + return o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreIntegrationLinks) GetEnvironmentOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Environment, true +} + +// SetEnvironment sets field value +func (o *BigSegmentStoreIntegrationLinks) SetEnvironment(v Link) { + o.Environment = v +} + +func (o BigSegmentStoreIntegrationLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if true { + toSerialize["parent"] = o.Parent + } + if true { + toSerialize["project"] = o.Project + } + if true { + toSerialize["environment"] = o.Environment + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentStoreIntegrationLinks struct { + value *BigSegmentStoreIntegrationLinks + isSet bool +} + +func (v NullableBigSegmentStoreIntegrationLinks) Get() *BigSegmentStoreIntegrationLinks { + return v.value +} + +func (v *NullableBigSegmentStoreIntegrationLinks) Set(val *BigSegmentStoreIntegrationLinks) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentStoreIntegrationLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentStoreIntegrationLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentStoreIntegrationLinks(val *BigSegmentStoreIntegrationLinks) *NullableBigSegmentStoreIntegrationLinks { + return &NullableBigSegmentStoreIntegrationLinks{value: val, isSet: true} +} + +func (v NullableBigSegmentStoreIntegrationLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentStoreIntegrationLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_status.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_status.go new file mode 100644 index 00000000..26030933 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_store_status.go @@ -0,0 +1,262 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentStoreStatus struct for BigSegmentStoreStatus +type BigSegmentStoreStatus struct { + // Whether the persistent store integration is fully synchronized with the LaunchDarkly environment, and the lastSync occurred within a few minutes + Available *bool `json:"available,omitempty"` + // Whether the persistent store integration may not be fully synchronized with the LaunchDarkly environment. true if the integration could be stale. + PotentiallyStale *bool `json:"potentiallyStale,omitempty"` + LastSync *int64 `json:"lastSync,omitempty"` + LastError *int64 `json:"lastError,omitempty"` + Errors []StoreIntegrationError `json:"errors,omitempty"` +} + +// NewBigSegmentStoreStatus instantiates a new BigSegmentStoreStatus object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentStoreStatus() *BigSegmentStoreStatus { + this := BigSegmentStoreStatus{} + return &this +} + +// NewBigSegmentStoreStatusWithDefaults instantiates a new BigSegmentStoreStatus object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentStoreStatusWithDefaults() *BigSegmentStoreStatus { + this := BigSegmentStoreStatus{} + return &this +} + +// GetAvailable returns the Available field value if set, zero value otherwise. +func (o *BigSegmentStoreStatus) GetAvailable() bool { + if o == nil || o.Available == nil { + var ret bool + return ret + } + return *o.Available +} + +// GetAvailableOk returns a tuple with the Available field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreStatus) GetAvailableOk() (*bool, bool) { + if o == nil || o.Available == nil { + return nil, false + } + return o.Available, true +} + +// HasAvailable returns a boolean if a field has been set. +func (o *BigSegmentStoreStatus) HasAvailable() bool { + if o != nil && o.Available != nil { + return true + } + + return false +} + +// SetAvailable gets a reference to the given bool and assigns it to the Available field. +func (o *BigSegmentStoreStatus) SetAvailable(v bool) { + o.Available = &v +} + +// GetPotentiallyStale returns the PotentiallyStale field value if set, zero value otherwise. +func (o *BigSegmentStoreStatus) GetPotentiallyStale() bool { + if o == nil || o.PotentiallyStale == nil { + var ret bool + return ret + } + return *o.PotentiallyStale +} + +// GetPotentiallyStaleOk returns a tuple with the PotentiallyStale field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreStatus) GetPotentiallyStaleOk() (*bool, bool) { + if o == nil || o.PotentiallyStale == nil { + return nil, false + } + return o.PotentiallyStale, true +} + +// HasPotentiallyStale returns a boolean if a field has been set. +func (o *BigSegmentStoreStatus) HasPotentiallyStale() bool { + if o != nil && o.PotentiallyStale != nil { + return true + } + + return false +} + +// SetPotentiallyStale gets a reference to the given bool and assigns it to the PotentiallyStale field. +func (o *BigSegmentStoreStatus) SetPotentiallyStale(v bool) { + o.PotentiallyStale = &v +} + +// GetLastSync returns the LastSync field value if set, zero value otherwise. +func (o *BigSegmentStoreStatus) GetLastSync() int64 { + if o == nil || o.LastSync == nil { + var ret int64 + return ret + } + return *o.LastSync +} + +// GetLastSyncOk returns a tuple with the LastSync field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreStatus) GetLastSyncOk() (*int64, bool) { + if o == nil || o.LastSync == nil { + return nil, false + } + return o.LastSync, true +} + +// HasLastSync returns a boolean if a field has been set. +func (o *BigSegmentStoreStatus) HasLastSync() bool { + if o != nil && o.LastSync != nil { + return true + } + + return false +} + +// SetLastSync gets a reference to the given int64 and assigns it to the LastSync field. +func (o *BigSegmentStoreStatus) SetLastSync(v int64) { + o.LastSync = &v +} + +// GetLastError returns the LastError field value if set, zero value otherwise. +func (o *BigSegmentStoreStatus) GetLastError() int64 { + if o == nil || o.LastError == nil { + var ret int64 + return ret + } + return *o.LastError +} + +// GetLastErrorOk returns a tuple with the LastError field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreStatus) GetLastErrorOk() (*int64, bool) { + if o == nil || o.LastError == nil { + return nil, false + } + return o.LastError, true +} + +// HasLastError returns a boolean if a field has been set. +func (o *BigSegmentStoreStatus) HasLastError() bool { + if o != nil && o.LastError != nil { + return true + } + + return false +} + +// SetLastError gets a reference to the given int64 and assigns it to the LastError field. +func (o *BigSegmentStoreStatus) SetLastError(v int64) { + o.LastError = &v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *BigSegmentStoreStatus) GetErrors() []StoreIntegrationError { + if o == nil || o.Errors == nil { + var ret []StoreIntegrationError + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BigSegmentStoreStatus) GetErrorsOk() ([]StoreIntegrationError, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *BigSegmentStoreStatus) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []StoreIntegrationError and assigns it to the Errors field. +func (o *BigSegmentStoreStatus) SetErrors(v []StoreIntegrationError) { + o.Errors = v +} + +func (o BigSegmentStoreStatus) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Available != nil { + toSerialize["available"] = o.Available + } + if o.PotentiallyStale != nil { + toSerialize["potentiallyStale"] = o.PotentiallyStale + } + if o.LastSync != nil { + toSerialize["lastSync"] = o.LastSync + } + if o.LastError != nil { + toSerialize["lastError"] = o.LastError + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentStoreStatus struct { + value *BigSegmentStoreStatus + isSet bool +} + +func (v NullableBigSegmentStoreStatus) Get() *BigSegmentStoreStatus { + return v.value +} + +func (v *NullableBigSegmentStoreStatus) Set(val *BigSegmentStoreStatus) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentStoreStatus) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentStoreStatus) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentStoreStatus(val *BigSegmentStoreStatus) *NullableBigSegmentStoreStatus { + return &NullableBigSegmentStoreStatus{value: val, isSet: true} +} + +func (v NullableBigSegmentStoreStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentStoreStatus) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_target.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_target.go new file mode 100644 index 00000000..1869b5e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_big_segment_target.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BigSegmentTarget struct for BigSegmentTarget +type BigSegmentTarget struct { + // The target key + UserKey string `json:"userKey"` + // Indicates whether the target is included.
Included targets are always segment members, regardless of segment rules. + Included bool `json:"included"` + // Indicates whether the target is excluded.
Segment rules bypass excluded targets, so they will never be included based on rules. Excluded targets may still be included explicitly. + Excluded bool `json:"excluded"` +} + +// NewBigSegmentTarget instantiates a new BigSegmentTarget object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBigSegmentTarget(userKey string, included bool, excluded bool) *BigSegmentTarget { + this := BigSegmentTarget{} + this.UserKey = userKey + this.Included = included + this.Excluded = excluded + return &this +} + +// NewBigSegmentTargetWithDefaults instantiates a new BigSegmentTarget object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBigSegmentTargetWithDefaults() *BigSegmentTarget { + this := BigSegmentTarget{} + return &this +} + +// GetUserKey returns the UserKey field value +func (o *BigSegmentTarget) GetUserKey() string { + if o == nil { + var ret string + return ret + } + + return o.UserKey +} + +// GetUserKeyOk returns a tuple with the UserKey field value +// and a boolean to check if the value has been set. +func (o *BigSegmentTarget) GetUserKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.UserKey, true +} + +// SetUserKey sets field value +func (o *BigSegmentTarget) SetUserKey(v string) { + o.UserKey = v +} + +// GetIncluded returns the Included field value +func (o *BigSegmentTarget) GetIncluded() bool { + if o == nil { + var ret bool + return ret + } + + return o.Included +} + +// GetIncludedOk returns a tuple with the Included field value +// and a boolean to check if the value has been set. +func (o *BigSegmentTarget) GetIncludedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Included, true +} + +// SetIncluded sets field value +func (o *BigSegmentTarget) SetIncluded(v bool) { + o.Included = v +} + +// GetExcluded returns the Excluded field value +func (o *BigSegmentTarget) GetExcluded() bool { + if o == nil { + var ret bool + return ret + } + + return o.Excluded +} + +// GetExcludedOk returns a tuple with the Excluded field value +// and a boolean to check if the value has been set. +func (o *BigSegmentTarget) GetExcludedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Excluded, true +} + +// SetExcluded sets field value +func (o *BigSegmentTarget) SetExcluded(v bool) { + o.Excluded = v +} + +func (o BigSegmentTarget) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["userKey"] = o.UserKey + } + if true { + toSerialize["included"] = o.Included + } + if true { + toSerialize["excluded"] = o.Excluded + } + return json.Marshal(toSerialize) +} + +type NullableBigSegmentTarget struct { + value *BigSegmentTarget + isSet bool +} + +func (v NullableBigSegmentTarget) Get() *BigSegmentTarget { + return v.value +} + +func (v *NullableBigSegmentTarget) Set(val *BigSegmentTarget) { + v.value = val + v.isSet = true +} + +func (v NullableBigSegmentTarget) IsSet() bool { + return v.isSet +} + +func (v *NullableBigSegmentTarget) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBigSegmentTarget(val *BigSegmentTarget) *NullableBigSegmentTarget { + return &NullableBigSegmentTarget{value: val, isSet: true} +} + +func (v NullableBigSegmentTarget) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBigSegmentTarget) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_defaults.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_defaults.go new file mode 100644 index 00000000..02299549 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_defaults.go @@ -0,0 +1,302 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BooleanDefaults struct for BooleanDefaults +type BooleanDefaults struct { + // The display name for the true variation, displayed in the LaunchDarkly user interface + TrueDisplayName *string `json:"trueDisplayName,omitempty"` + // The display name for the false variation, displayed in the LaunchDarkly user interface + FalseDisplayName *string `json:"falseDisplayName,omitempty"` + // The description for the true variation + TrueDescription *string `json:"trueDescription,omitempty"` + // The description for the false variation + FalseDescription *string `json:"falseDescription,omitempty"` + // The variation index of the flag variation to use for the default targeting behavior when a flag's targeting is on and the target did not match any rules + OnVariation *int32 `json:"onVariation,omitempty"` + // The variation index of the flag variation to use for the default targeting behavior when a flag's targeting is off + OffVariation *int32 `json:"offVariation,omitempty"` +} + +// NewBooleanDefaults instantiates a new BooleanDefaults object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBooleanDefaults() *BooleanDefaults { + this := BooleanDefaults{} + return &this +} + +// NewBooleanDefaultsWithDefaults instantiates a new BooleanDefaults object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBooleanDefaultsWithDefaults() *BooleanDefaults { + this := BooleanDefaults{} + return &this +} + +// GetTrueDisplayName returns the TrueDisplayName field value if set, zero value otherwise. +func (o *BooleanDefaults) GetTrueDisplayName() string { + if o == nil || o.TrueDisplayName == nil { + var ret string + return ret + } + return *o.TrueDisplayName +} + +// GetTrueDisplayNameOk returns a tuple with the TrueDisplayName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetTrueDisplayNameOk() (*string, bool) { + if o == nil || o.TrueDisplayName == nil { + return nil, false + } + return o.TrueDisplayName, true +} + +// HasTrueDisplayName returns a boolean if a field has been set. +func (o *BooleanDefaults) HasTrueDisplayName() bool { + if o != nil && o.TrueDisplayName != nil { + return true + } + + return false +} + +// SetTrueDisplayName gets a reference to the given string and assigns it to the TrueDisplayName field. +func (o *BooleanDefaults) SetTrueDisplayName(v string) { + o.TrueDisplayName = &v +} + +// GetFalseDisplayName returns the FalseDisplayName field value if set, zero value otherwise. +func (o *BooleanDefaults) GetFalseDisplayName() string { + if o == nil || o.FalseDisplayName == nil { + var ret string + return ret + } + return *o.FalseDisplayName +} + +// GetFalseDisplayNameOk returns a tuple with the FalseDisplayName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetFalseDisplayNameOk() (*string, bool) { + if o == nil || o.FalseDisplayName == nil { + return nil, false + } + return o.FalseDisplayName, true +} + +// HasFalseDisplayName returns a boolean if a field has been set. +func (o *BooleanDefaults) HasFalseDisplayName() bool { + if o != nil && o.FalseDisplayName != nil { + return true + } + + return false +} + +// SetFalseDisplayName gets a reference to the given string and assigns it to the FalseDisplayName field. +func (o *BooleanDefaults) SetFalseDisplayName(v string) { + o.FalseDisplayName = &v +} + +// GetTrueDescription returns the TrueDescription field value if set, zero value otherwise. +func (o *BooleanDefaults) GetTrueDescription() string { + if o == nil || o.TrueDescription == nil { + var ret string + return ret + } + return *o.TrueDescription +} + +// GetTrueDescriptionOk returns a tuple with the TrueDescription field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetTrueDescriptionOk() (*string, bool) { + if o == nil || o.TrueDescription == nil { + return nil, false + } + return o.TrueDescription, true +} + +// HasTrueDescription returns a boolean if a field has been set. +func (o *BooleanDefaults) HasTrueDescription() bool { + if o != nil && o.TrueDescription != nil { + return true + } + + return false +} + +// SetTrueDescription gets a reference to the given string and assigns it to the TrueDescription field. +func (o *BooleanDefaults) SetTrueDescription(v string) { + o.TrueDescription = &v +} + +// GetFalseDescription returns the FalseDescription field value if set, zero value otherwise. +func (o *BooleanDefaults) GetFalseDescription() string { + if o == nil || o.FalseDescription == nil { + var ret string + return ret + } + return *o.FalseDescription +} + +// GetFalseDescriptionOk returns a tuple with the FalseDescription field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetFalseDescriptionOk() (*string, bool) { + if o == nil || o.FalseDescription == nil { + return nil, false + } + return o.FalseDescription, true +} + +// HasFalseDescription returns a boolean if a field has been set. +func (o *BooleanDefaults) HasFalseDescription() bool { + if o != nil && o.FalseDescription != nil { + return true + } + + return false +} + +// SetFalseDescription gets a reference to the given string and assigns it to the FalseDescription field. +func (o *BooleanDefaults) SetFalseDescription(v string) { + o.FalseDescription = &v +} + +// GetOnVariation returns the OnVariation field value if set, zero value otherwise. +func (o *BooleanDefaults) GetOnVariation() int32 { + if o == nil || o.OnVariation == nil { + var ret int32 + return ret + } + return *o.OnVariation +} + +// GetOnVariationOk returns a tuple with the OnVariation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetOnVariationOk() (*int32, bool) { + if o == nil || o.OnVariation == nil { + return nil, false + } + return o.OnVariation, true +} + +// HasOnVariation returns a boolean if a field has been set. +func (o *BooleanDefaults) HasOnVariation() bool { + if o != nil && o.OnVariation != nil { + return true + } + + return false +} + +// SetOnVariation gets a reference to the given int32 and assigns it to the OnVariation field. +func (o *BooleanDefaults) SetOnVariation(v int32) { + o.OnVariation = &v +} + +// GetOffVariation returns the OffVariation field value if set, zero value otherwise. +func (o *BooleanDefaults) GetOffVariation() int32 { + if o == nil || o.OffVariation == nil { + var ret int32 + return ret + } + return *o.OffVariation +} + +// GetOffVariationOk returns a tuple with the OffVariation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BooleanDefaults) GetOffVariationOk() (*int32, bool) { + if o == nil || o.OffVariation == nil { + return nil, false + } + return o.OffVariation, true +} + +// HasOffVariation returns a boolean if a field has been set. +func (o *BooleanDefaults) HasOffVariation() bool { + if o != nil && o.OffVariation != nil { + return true + } + + return false +} + +// SetOffVariation gets a reference to the given int32 and assigns it to the OffVariation field. +func (o *BooleanDefaults) SetOffVariation(v int32) { + o.OffVariation = &v +} + +func (o BooleanDefaults) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TrueDisplayName != nil { + toSerialize["trueDisplayName"] = o.TrueDisplayName + } + if o.FalseDisplayName != nil { + toSerialize["falseDisplayName"] = o.FalseDisplayName + } + if o.TrueDescription != nil { + toSerialize["trueDescription"] = o.TrueDescription + } + if o.FalseDescription != nil { + toSerialize["falseDescription"] = o.FalseDescription + } + if o.OnVariation != nil { + toSerialize["onVariation"] = o.OnVariation + } + if o.OffVariation != nil { + toSerialize["offVariation"] = o.OffVariation + } + return json.Marshal(toSerialize) +} + +type NullableBooleanDefaults struct { + value *BooleanDefaults + isSet bool +} + +func (v NullableBooleanDefaults) Get() *BooleanDefaults { + return v.value +} + +func (v *NullableBooleanDefaults) Set(val *BooleanDefaults) { + v.value = val + v.isSet = true +} + +func (v NullableBooleanDefaults) IsSet() bool { + return v.isSet +} + +func (v *NullableBooleanDefaults) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBooleanDefaults(val *BooleanDefaults) *NullableBooleanDefaults { + return &NullableBooleanDefaults{value: val, isSet: true} +} + +func (v NullableBooleanDefaults) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBooleanDefaults) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_flag_defaults.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_flag_defaults.go new file mode 100644 index 00000000..90f1a67d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_boolean_flag_defaults.go @@ -0,0 +1,260 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BooleanFlagDefaults struct for BooleanFlagDefaults +type BooleanFlagDefaults struct { + // The display name for the true variation, displayed in the LaunchDarkly user interface + TrueDisplayName string `json:"trueDisplayName"` + // The display name for the false variation, displayed in the LaunchDarkly user interface + FalseDisplayName string `json:"falseDisplayName"` + // The description for the true variation + TrueDescription string `json:"trueDescription"` + // The description for the false variation + FalseDescription string `json:"falseDescription"` + // The variation index of the flag variation to use for the default targeting behavior when a flag's targeting is on and the target did not match any rules + OnVariation int32 `json:"onVariation"` + // The variation index of the flag variation to use for the default targeting behavior when a flag's targeting is off + OffVariation int32 `json:"offVariation"` +} + +// NewBooleanFlagDefaults instantiates a new BooleanFlagDefaults object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBooleanFlagDefaults(trueDisplayName string, falseDisplayName string, trueDescription string, falseDescription string, onVariation int32, offVariation int32) *BooleanFlagDefaults { + this := BooleanFlagDefaults{} + this.TrueDisplayName = trueDisplayName + this.FalseDisplayName = falseDisplayName + this.TrueDescription = trueDescription + this.FalseDescription = falseDescription + this.OnVariation = onVariation + this.OffVariation = offVariation + return &this +} + +// NewBooleanFlagDefaultsWithDefaults instantiates a new BooleanFlagDefaults object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBooleanFlagDefaultsWithDefaults() *BooleanFlagDefaults { + this := BooleanFlagDefaults{} + return &this +} + +// GetTrueDisplayName returns the TrueDisplayName field value +func (o *BooleanFlagDefaults) GetTrueDisplayName() string { + if o == nil { + var ret string + return ret + } + + return o.TrueDisplayName +} + +// GetTrueDisplayNameOk returns a tuple with the TrueDisplayName field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetTrueDisplayNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.TrueDisplayName, true +} + +// SetTrueDisplayName sets field value +func (o *BooleanFlagDefaults) SetTrueDisplayName(v string) { + o.TrueDisplayName = v +} + +// GetFalseDisplayName returns the FalseDisplayName field value +func (o *BooleanFlagDefaults) GetFalseDisplayName() string { + if o == nil { + var ret string + return ret + } + + return o.FalseDisplayName +} + +// GetFalseDisplayNameOk returns a tuple with the FalseDisplayName field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetFalseDisplayNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FalseDisplayName, true +} + +// SetFalseDisplayName sets field value +func (o *BooleanFlagDefaults) SetFalseDisplayName(v string) { + o.FalseDisplayName = v +} + +// GetTrueDescription returns the TrueDescription field value +func (o *BooleanFlagDefaults) GetTrueDescription() string { + if o == nil { + var ret string + return ret + } + + return o.TrueDescription +} + +// GetTrueDescriptionOk returns a tuple with the TrueDescription field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetTrueDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.TrueDescription, true +} + +// SetTrueDescription sets field value +func (o *BooleanFlagDefaults) SetTrueDescription(v string) { + o.TrueDescription = v +} + +// GetFalseDescription returns the FalseDescription field value +func (o *BooleanFlagDefaults) GetFalseDescription() string { + if o == nil { + var ret string + return ret + } + + return o.FalseDescription +} + +// GetFalseDescriptionOk returns a tuple with the FalseDescription field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetFalseDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FalseDescription, true +} + +// SetFalseDescription sets field value +func (o *BooleanFlagDefaults) SetFalseDescription(v string) { + o.FalseDescription = v +} + +// GetOnVariation returns the OnVariation field value +func (o *BooleanFlagDefaults) GetOnVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.OnVariation +} + +// GetOnVariationOk returns a tuple with the OnVariation field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetOnVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.OnVariation, true +} + +// SetOnVariation sets field value +func (o *BooleanFlagDefaults) SetOnVariation(v int32) { + o.OnVariation = v +} + +// GetOffVariation returns the OffVariation field value +func (o *BooleanFlagDefaults) GetOffVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.OffVariation +} + +// GetOffVariationOk returns a tuple with the OffVariation field value +// and a boolean to check if the value has been set. +func (o *BooleanFlagDefaults) GetOffVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.OffVariation, true +} + +// SetOffVariation sets field value +func (o *BooleanFlagDefaults) SetOffVariation(v int32) { + o.OffVariation = v +} + +func (o BooleanFlagDefaults) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["trueDisplayName"] = o.TrueDisplayName + } + if true { + toSerialize["falseDisplayName"] = o.FalseDisplayName + } + if true { + toSerialize["trueDescription"] = o.TrueDescription + } + if true { + toSerialize["falseDescription"] = o.FalseDescription + } + if true { + toSerialize["onVariation"] = o.OnVariation + } + if true { + toSerialize["offVariation"] = o.OffVariation + } + return json.Marshal(toSerialize) +} + +type NullableBooleanFlagDefaults struct { + value *BooleanFlagDefaults + isSet bool +} + +func (v NullableBooleanFlagDefaults) Get() *BooleanFlagDefaults { + return v.value +} + +func (v *NullableBooleanFlagDefaults) Set(val *BooleanFlagDefaults) { + v.value = val + v.isSet = true +} + +func (v NullableBooleanFlagDefaults) IsSet() bool { + return v.isSet +} + +func (v *NullableBooleanFlagDefaults) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBooleanFlagDefaults(val *BooleanFlagDefaults) *NullableBooleanFlagDefaults { + return &NullableBooleanFlagDefaults{value: val, isSet: true} +} + +func (v NullableBooleanFlagDefaults) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBooleanFlagDefaults) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_collection_rep.go new file mode 100644 index 00000000..2f415f62 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BranchCollectionRep struct for BranchCollectionRep +type BranchCollectionRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of branches + Items []BranchRep `json:"items"` +} + +// NewBranchCollectionRep instantiates a new BranchCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBranchCollectionRep(links map[string]Link, items []BranchRep) *BranchCollectionRep { + this := BranchCollectionRep{} + this.Links = links + this.Items = items + return &this +} + +// NewBranchCollectionRepWithDefaults instantiates a new BranchCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBranchCollectionRepWithDefaults() *BranchCollectionRep { + this := BranchCollectionRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *BranchCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *BranchCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *BranchCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *BranchCollectionRep) GetItems() []BranchRep { + if o == nil { + var ret []BranchRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *BranchCollectionRep) GetItemsOk() ([]BranchRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *BranchCollectionRep) SetItems(v []BranchRep) { + o.Items = v +} + +func (o BranchCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableBranchCollectionRep struct { + value *BranchCollectionRep + isSet bool +} + +func (v NullableBranchCollectionRep) Get() *BranchCollectionRep { + return v.value +} + +func (v *NullableBranchCollectionRep) Set(val *BranchCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableBranchCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBranchCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBranchCollectionRep(val *BranchCollectionRep) *NullableBranchCollectionRep { + return &NullableBranchCollectionRep{value: val, isSet: true} +} + +func (v NullableBranchCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBranchCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_rep.go new file mode 100644 index 00000000..653dd8ae --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_branch_rep.go @@ -0,0 +1,273 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BranchRep struct for BranchRep +type BranchRep struct { + // The branch name + Name string `json:"name"` + // An ID representing the branch HEAD. For example, a commit SHA. + Head string `json:"head"` + // An optional ID used to prevent older data from overwriting newer data + UpdateSequenceId *int64 `json:"updateSequenceId,omitempty"` + SyncTime int64 `json:"syncTime"` + // An array of flag references found on the branch + References []ReferenceRep `json:"references,omitempty"` + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` +} + +// NewBranchRep instantiates a new BranchRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBranchRep(name string, head string, syncTime int64, links map[string]interface{}) *BranchRep { + this := BranchRep{} + this.Name = name + this.Head = head + this.SyncTime = syncTime + this.Links = links + return &this +} + +// NewBranchRepWithDefaults instantiates a new BranchRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBranchRepWithDefaults() *BranchRep { + this := BranchRep{} + return &this +} + +// GetName returns the Name field value +func (o *BranchRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *BranchRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *BranchRep) SetName(v string) { + o.Name = v +} + +// GetHead returns the Head field value +func (o *BranchRep) GetHead() string { + if o == nil { + var ret string + return ret + } + + return o.Head +} + +// GetHeadOk returns a tuple with the Head field value +// and a boolean to check if the value has been set. +func (o *BranchRep) GetHeadOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Head, true +} + +// SetHead sets field value +func (o *BranchRep) SetHead(v string) { + o.Head = v +} + +// GetUpdateSequenceId returns the UpdateSequenceId field value if set, zero value otherwise. +func (o *BranchRep) GetUpdateSequenceId() int64 { + if o == nil || o.UpdateSequenceId == nil { + var ret int64 + return ret + } + return *o.UpdateSequenceId +} + +// GetUpdateSequenceIdOk returns a tuple with the UpdateSequenceId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BranchRep) GetUpdateSequenceIdOk() (*int64, bool) { + if o == nil || o.UpdateSequenceId == nil { + return nil, false + } + return o.UpdateSequenceId, true +} + +// HasUpdateSequenceId returns a boolean if a field has been set. +func (o *BranchRep) HasUpdateSequenceId() bool { + if o != nil && o.UpdateSequenceId != nil { + return true + } + + return false +} + +// SetUpdateSequenceId gets a reference to the given int64 and assigns it to the UpdateSequenceId field. +func (o *BranchRep) SetUpdateSequenceId(v int64) { + o.UpdateSequenceId = &v +} + +// GetSyncTime returns the SyncTime field value +func (o *BranchRep) GetSyncTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.SyncTime +} + +// GetSyncTimeOk returns a tuple with the SyncTime field value +// and a boolean to check if the value has been set. +func (o *BranchRep) GetSyncTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.SyncTime, true +} + +// SetSyncTime sets field value +func (o *BranchRep) SetSyncTime(v int64) { + o.SyncTime = v +} + +// GetReferences returns the References field value if set, zero value otherwise. +func (o *BranchRep) GetReferences() []ReferenceRep { + if o == nil || o.References == nil { + var ret []ReferenceRep + return ret + } + return o.References +} + +// GetReferencesOk returns a tuple with the References field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BranchRep) GetReferencesOk() ([]ReferenceRep, bool) { + if o == nil || o.References == nil { + return nil, false + } + return o.References, true +} + +// HasReferences returns a boolean if a field has been set. +func (o *BranchRep) HasReferences() bool { + if o != nil && o.References != nil { + return true + } + + return false +} + +// SetReferences gets a reference to the given []ReferenceRep and assigns it to the References field. +func (o *BranchRep) SetReferences(v []ReferenceRep) { + o.References = v +} + +// GetLinks returns the Links field value +func (o *BranchRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *BranchRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *BranchRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +func (o BranchRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["head"] = o.Head + } + if o.UpdateSequenceId != nil { + toSerialize["updateSequenceId"] = o.UpdateSequenceId + } + if true { + toSerialize["syncTime"] = o.SyncTime + } + if o.References != nil { + toSerialize["references"] = o.References + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableBranchRep struct { + value *BranchRep + isSet bool +} + +func (v NullableBranchRep) Get() *BranchRep { + return v.value +} + +func (v *NullableBranchRep) Set(val *BranchRep) { + v.value = val + v.isSet = true +} + +func (v NullableBranchRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBranchRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBranchRep(val *BranchRep) *NullableBranchRep { + return &NullableBranchRep{value: val, isSet: true} +} + +func (v NullableBranchRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBranchRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_members_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_members_rep.go new file mode 100644 index 00000000..7f691832 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_members_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BulkEditMembersRep struct for BulkEditMembersRep +type BulkEditMembersRep struct { + // A list of members IDs of the members who were successfully updated. + Members []string `json:"members,omitempty"` + // A list of member IDs and errors for the members whose updates failed. + Errors []map[string]string `json:"errors,omitempty"` +} + +// NewBulkEditMembersRep instantiates a new BulkEditMembersRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBulkEditMembersRep() *BulkEditMembersRep { + this := BulkEditMembersRep{} + return &this +} + +// NewBulkEditMembersRepWithDefaults instantiates a new BulkEditMembersRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBulkEditMembersRepWithDefaults() *BulkEditMembersRep { + this := BulkEditMembersRep{} + return &this +} + +// GetMembers returns the Members field value if set, zero value otherwise. +func (o *BulkEditMembersRep) GetMembers() []string { + if o == nil || o.Members == nil { + var ret []string + return ret + } + return o.Members +} + +// GetMembersOk returns a tuple with the Members field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BulkEditMembersRep) GetMembersOk() ([]string, bool) { + if o == nil || o.Members == nil { + return nil, false + } + return o.Members, true +} + +// HasMembers returns a boolean if a field has been set. +func (o *BulkEditMembersRep) HasMembers() bool { + if o != nil && o.Members != nil { + return true + } + + return false +} + +// SetMembers gets a reference to the given []string and assigns it to the Members field. +func (o *BulkEditMembersRep) SetMembers(v []string) { + o.Members = v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *BulkEditMembersRep) GetErrors() []map[string]string { + if o == nil || o.Errors == nil { + var ret []map[string]string + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BulkEditMembersRep) GetErrorsOk() ([]map[string]string, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *BulkEditMembersRep) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []map[string]string and assigns it to the Errors field. +func (o *BulkEditMembersRep) SetErrors(v []map[string]string) { + o.Errors = v +} + +func (o BulkEditMembersRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Members != nil { + toSerialize["members"] = o.Members + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableBulkEditMembersRep struct { + value *BulkEditMembersRep + isSet bool +} + +func (v NullableBulkEditMembersRep) Get() *BulkEditMembersRep { + return v.value +} + +func (v *NullableBulkEditMembersRep) Set(val *BulkEditMembersRep) { + v.value = val + v.isSet = true +} + +func (v NullableBulkEditMembersRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBulkEditMembersRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBulkEditMembersRep(val *BulkEditMembersRep) *NullableBulkEditMembersRep { + return &NullableBulkEditMembersRep{value: val, isSet: true} +} + +func (v NullableBulkEditMembersRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBulkEditMembersRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_teams_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_teams_rep.go new file mode 100644 index 00000000..1e556808 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_bulk_edit_teams_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// BulkEditTeamsRep struct for BulkEditTeamsRep +type BulkEditTeamsRep struct { + // A list of member IDs of the members who were added to the teams. + MemberIDs []string `json:"memberIDs,omitempty"` + // A list of team keys of the teams that were successfully updated. + TeamKeys []string `json:"teamKeys,omitempty"` + // A list of team keys and errors for the teams whose updates failed. + Errors []map[string]string `json:"errors,omitempty"` +} + +// NewBulkEditTeamsRep instantiates a new BulkEditTeamsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBulkEditTeamsRep() *BulkEditTeamsRep { + this := BulkEditTeamsRep{} + return &this +} + +// NewBulkEditTeamsRepWithDefaults instantiates a new BulkEditTeamsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBulkEditTeamsRepWithDefaults() *BulkEditTeamsRep { + this := BulkEditTeamsRep{} + return &this +} + +// GetMemberIDs returns the MemberIDs field value if set, zero value otherwise. +func (o *BulkEditTeamsRep) GetMemberIDs() []string { + if o == nil || o.MemberIDs == nil { + var ret []string + return ret + } + return o.MemberIDs +} + +// GetMemberIDsOk returns a tuple with the MemberIDs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BulkEditTeamsRep) GetMemberIDsOk() ([]string, bool) { + if o == nil || o.MemberIDs == nil { + return nil, false + } + return o.MemberIDs, true +} + +// HasMemberIDs returns a boolean if a field has been set. +func (o *BulkEditTeamsRep) HasMemberIDs() bool { + if o != nil && o.MemberIDs != nil { + return true + } + + return false +} + +// SetMemberIDs gets a reference to the given []string and assigns it to the MemberIDs field. +func (o *BulkEditTeamsRep) SetMemberIDs(v []string) { + o.MemberIDs = v +} + +// GetTeamKeys returns the TeamKeys field value if set, zero value otherwise. +func (o *BulkEditTeamsRep) GetTeamKeys() []string { + if o == nil || o.TeamKeys == nil { + var ret []string + return ret + } + return o.TeamKeys +} + +// GetTeamKeysOk returns a tuple with the TeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BulkEditTeamsRep) GetTeamKeysOk() ([]string, bool) { + if o == nil || o.TeamKeys == nil { + return nil, false + } + return o.TeamKeys, true +} + +// HasTeamKeys returns a boolean if a field has been set. +func (o *BulkEditTeamsRep) HasTeamKeys() bool { + if o != nil && o.TeamKeys != nil { + return true + } + + return false +} + +// SetTeamKeys gets a reference to the given []string and assigns it to the TeamKeys field. +func (o *BulkEditTeamsRep) SetTeamKeys(v []string) { + o.TeamKeys = v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *BulkEditTeamsRep) GetErrors() []map[string]string { + if o == nil || o.Errors == nil { + var ret []map[string]string + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BulkEditTeamsRep) GetErrorsOk() ([]map[string]string, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *BulkEditTeamsRep) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []map[string]string and assigns it to the Errors field. +func (o *BulkEditTeamsRep) SetErrors(v []map[string]string) { + o.Errors = v +} + +func (o BulkEditTeamsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.MemberIDs != nil { + toSerialize["memberIDs"] = o.MemberIDs + } + if o.TeamKeys != nil { + toSerialize["teamKeys"] = o.TeamKeys + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableBulkEditTeamsRep struct { + value *BulkEditTeamsRep + isSet bool +} + +func (v NullableBulkEditTeamsRep) Get() *BulkEditTeamsRep { + return v.value +} + +func (v *NullableBulkEditTeamsRep) Set(val *BulkEditTeamsRep) { + v.value = val + v.isSet = true +} + +func (v NullableBulkEditTeamsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableBulkEditTeamsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBulkEditTeamsRep(val *BulkEditTeamsRep) *NullableBulkEditTeamsRep { + return &NullableBulkEditTeamsRep{value: val, isSet: true} +} + +func (v NullableBulkEditTeamsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBulkEditTeamsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_caller_identity_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_caller_identity_rep.go new file mode 100644 index 00000000..9904d876 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_caller_identity_rep.go @@ -0,0 +1,512 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CallerIdentityRep struct for CallerIdentityRep +type CallerIdentityRep struct { + AccountId *string `json:"accountId,omitempty"` + EnvironmentId *string `json:"environmentId,omitempty"` + ProjectId *string `json:"projectId,omitempty"` + EnvironmentName *string `json:"environmentName,omitempty"` + ProjectName *string `json:"projectName,omitempty"` + AuthKind *string `json:"authKind,omitempty"` + TokenKind *string `json:"tokenKind,omitempty"` + ClientId *string `json:"clientId,omitempty"` + TokenName *string `json:"tokenName,omitempty"` + TokenId *string `json:"tokenId,omitempty"` + MemberId *string `json:"memberId,omitempty"` + ServiceToken *bool `json:"serviceToken,omitempty"` +} + +// NewCallerIdentityRep instantiates a new CallerIdentityRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCallerIdentityRep() *CallerIdentityRep { + this := CallerIdentityRep{} + return &this +} + +// NewCallerIdentityRepWithDefaults instantiates a new CallerIdentityRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCallerIdentityRepWithDefaults() *CallerIdentityRep { + this := CallerIdentityRep{} + return &this +} + +// GetAccountId returns the AccountId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetAccountId() string { + if o == nil || o.AccountId == nil { + var ret string + return ret + } + return *o.AccountId +} + +// GetAccountIdOk returns a tuple with the AccountId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetAccountIdOk() (*string, bool) { + if o == nil || o.AccountId == nil { + return nil, false + } + return o.AccountId, true +} + +// HasAccountId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasAccountId() bool { + if o != nil && o.AccountId != nil { + return true + } + + return false +} + +// SetAccountId gets a reference to the given string and assigns it to the AccountId field. +func (o *CallerIdentityRep) SetAccountId(v string) { + o.AccountId = &v +} + +// GetEnvironmentId returns the EnvironmentId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetEnvironmentId() string { + if o == nil || o.EnvironmentId == nil { + var ret string + return ret + } + return *o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetEnvironmentIdOk() (*string, bool) { + if o == nil || o.EnvironmentId == nil { + return nil, false + } + return o.EnvironmentId, true +} + +// HasEnvironmentId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasEnvironmentId() bool { + if o != nil && o.EnvironmentId != nil { + return true + } + + return false +} + +// SetEnvironmentId gets a reference to the given string and assigns it to the EnvironmentId field. +func (o *CallerIdentityRep) SetEnvironmentId(v string) { + o.EnvironmentId = &v +} + +// GetProjectId returns the ProjectId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetProjectId() string { + if o == nil || o.ProjectId == nil { + var ret string + return ret + } + return *o.ProjectId +} + +// GetProjectIdOk returns a tuple with the ProjectId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetProjectIdOk() (*string, bool) { + if o == nil || o.ProjectId == nil { + return nil, false + } + return o.ProjectId, true +} + +// HasProjectId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasProjectId() bool { + if o != nil && o.ProjectId != nil { + return true + } + + return false +} + +// SetProjectId gets a reference to the given string and assigns it to the ProjectId field. +func (o *CallerIdentityRep) SetProjectId(v string) { + o.ProjectId = &v +} + +// GetEnvironmentName returns the EnvironmentName field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetEnvironmentName() string { + if o == nil || o.EnvironmentName == nil { + var ret string + return ret + } + return *o.EnvironmentName +} + +// GetEnvironmentNameOk returns a tuple with the EnvironmentName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetEnvironmentNameOk() (*string, bool) { + if o == nil || o.EnvironmentName == nil { + return nil, false + } + return o.EnvironmentName, true +} + +// HasEnvironmentName returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasEnvironmentName() bool { + if o != nil && o.EnvironmentName != nil { + return true + } + + return false +} + +// SetEnvironmentName gets a reference to the given string and assigns it to the EnvironmentName field. +func (o *CallerIdentityRep) SetEnvironmentName(v string) { + o.EnvironmentName = &v +} + +// GetProjectName returns the ProjectName field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetProjectName() string { + if o == nil || o.ProjectName == nil { + var ret string + return ret + } + return *o.ProjectName +} + +// GetProjectNameOk returns a tuple with the ProjectName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetProjectNameOk() (*string, bool) { + if o == nil || o.ProjectName == nil { + return nil, false + } + return o.ProjectName, true +} + +// HasProjectName returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasProjectName() bool { + if o != nil && o.ProjectName != nil { + return true + } + + return false +} + +// SetProjectName gets a reference to the given string and assigns it to the ProjectName field. +func (o *CallerIdentityRep) SetProjectName(v string) { + o.ProjectName = &v +} + +// GetAuthKind returns the AuthKind field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetAuthKind() string { + if o == nil || o.AuthKind == nil { + var ret string + return ret + } + return *o.AuthKind +} + +// GetAuthKindOk returns a tuple with the AuthKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetAuthKindOk() (*string, bool) { + if o == nil || o.AuthKind == nil { + return nil, false + } + return o.AuthKind, true +} + +// HasAuthKind returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasAuthKind() bool { + if o != nil && o.AuthKind != nil { + return true + } + + return false +} + +// SetAuthKind gets a reference to the given string and assigns it to the AuthKind field. +func (o *CallerIdentityRep) SetAuthKind(v string) { + o.AuthKind = &v +} + +// GetTokenKind returns the TokenKind field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetTokenKind() string { + if o == nil || o.TokenKind == nil { + var ret string + return ret + } + return *o.TokenKind +} + +// GetTokenKindOk returns a tuple with the TokenKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetTokenKindOk() (*string, bool) { + if o == nil || o.TokenKind == nil { + return nil, false + } + return o.TokenKind, true +} + +// HasTokenKind returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasTokenKind() bool { + if o != nil && o.TokenKind != nil { + return true + } + + return false +} + +// SetTokenKind gets a reference to the given string and assigns it to the TokenKind field. +func (o *CallerIdentityRep) SetTokenKind(v string) { + o.TokenKind = &v +} + +// GetClientId returns the ClientId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetClientId() string { + if o == nil || o.ClientId == nil { + var ret string + return ret + } + return *o.ClientId +} + +// GetClientIdOk returns a tuple with the ClientId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetClientIdOk() (*string, bool) { + if o == nil || o.ClientId == nil { + return nil, false + } + return o.ClientId, true +} + +// HasClientId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasClientId() bool { + if o != nil && o.ClientId != nil { + return true + } + + return false +} + +// SetClientId gets a reference to the given string and assigns it to the ClientId field. +func (o *CallerIdentityRep) SetClientId(v string) { + o.ClientId = &v +} + +// GetTokenName returns the TokenName field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetTokenName() string { + if o == nil || o.TokenName == nil { + var ret string + return ret + } + return *o.TokenName +} + +// GetTokenNameOk returns a tuple with the TokenName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetTokenNameOk() (*string, bool) { + if o == nil || o.TokenName == nil { + return nil, false + } + return o.TokenName, true +} + +// HasTokenName returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasTokenName() bool { + if o != nil && o.TokenName != nil { + return true + } + + return false +} + +// SetTokenName gets a reference to the given string and assigns it to the TokenName field. +func (o *CallerIdentityRep) SetTokenName(v string) { + o.TokenName = &v +} + +// GetTokenId returns the TokenId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetTokenId() string { + if o == nil || o.TokenId == nil { + var ret string + return ret + } + return *o.TokenId +} + +// GetTokenIdOk returns a tuple with the TokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetTokenIdOk() (*string, bool) { + if o == nil || o.TokenId == nil { + return nil, false + } + return o.TokenId, true +} + +// HasTokenId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasTokenId() bool { + if o != nil && o.TokenId != nil { + return true + } + + return false +} + +// SetTokenId gets a reference to the given string and assigns it to the TokenId field. +func (o *CallerIdentityRep) SetTokenId(v string) { + o.TokenId = &v +} + +// GetMemberId returns the MemberId field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetMemberId() string { + if o == nil || o.MemberId == nil { + var ret string + return ret + } + return *o.MemberId +} + +// GetMemberIdOk returns a tuple with the MemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetMemberIdOk() (*string, bool) { + if o == nil || o.MemberId == nil { + return nil, false + } + return o.MemberId, true +} + +// HasMemberId returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasMemberId() bool { + if o != nil && o.MemberId != nil { + return true + } + + return false +} + +// SetMemberId gets a reference to the given string and assigns it to the MemberId field. +func (o *CallerIdentityRep) SetMemberId(v string) { + o.MemberId = &v +} + +// GetServiceToken returns the ServiceToken field value if set, zero value otherwise. +func (o *CallerIdentityRep) GetServiceToken() bool { + if o == nil || o.ServiceToken == nil { + var ret bool + return ret + } + return *o.ServiceToken +} + +// GetServiceTokenOk returns a tuple with the ServiceToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CallerIdentityRep) GetServiceTokenOk() (*bool, bool) { + if o == nil || o.ServiceToken == nil { + return nil, false + } + return o.ServiceToken, true +} + +// HasServiceToken returns a boolean if a field has been set. +func (o *CallerIdentityRep) HasServiceToken() bool { + if o != nil && o.ServiceToken != nil { + return true + } + + return false +} + +// SetServiceToken gets a reference to the given bool and assigns it to the ServiceToken field. +func (o *CallerIdentityRep) SetServiceToken(v bool) { + o.ServiceToken = &v +} + +func (o CallerIdentityRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.AccountId != nil { + toSerialize["accountId"] = o.AccountId + } + if o.EnvironmentId != nil { + toSerialize["environmentId"] = o.EnvironmentId + } + if o.ProjectId != nil { + toSerialize["projectId"] = o.ProjectId + } + if o.EnvironmentName != nil { + toSerialize["environmentName"] = o.EnvironmentName + } + if o.ProjectName != nil { + toSerialize["projectName"] = o.ProjectName + } + if o.AuthKind != nil { + toSerialize["authKind"] = o.AuthKind + } + if o.TokenKind != nil { + toSerialize["tokenKind"] = o.TokenKind + } + if o.ClientId != nil { + toSerialize["clientId"] = o.ClientId + } + if o.TokenName != nil { + toSerialize["tokenName"] = o.TokenName + } + if o.TokenId != nil { + toSerialize["tokenId"] = o.TokenId + } + if o.MemberId != nil { + toSerialize["memberId"] = o.MemberId + } + if o.ServiceToken != nil { + toSerialize["serviceToken"] = o.ServiceToken + } + return json.Marshal(toSerialize) +} + +type NullableCallerIdentityRep struct { + value *CallerIdentityRep + isSet bool +} + +func (v NullableCallerIdentityRep) Get() *CallerIdentityRep { + return v.value +} + +func (v *NullableCallerIdentityRep) Set(val *CallerIdentityRep) { + v.value = val + v.isSet = true +} + +func (v NullableCallerIdentityRep) IsSet() bool { + return v.isSet +} + +func (v *NullableCallerIdentityRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCallerIdentityRep(val *CallerIdentityRep) *NullableCallerIdentityRep { + return &NullableCallerIdentityRep{value: val, isSet: true} +} + +func (v NullableCallerIdentityRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCallerIdentityRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_post.go new file mode 100644 index 00000000..76b711e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_post.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CapabilityConfigPost struct for CapabilityConfigPost +type CapabilityConfigPost struct { + Approvals *ApprovalsCapabilityConfig `json:"approvals,omitempty"` + AuditLogEventsHook *AuditLogEventsHookCapabilityConfigPost `json:"auditLogEventsHook,omitempty"` +} + +// NewCapabilityConfigPost instantiates a new CapabilityConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCapabilityConfigPost() *CapabilityConfigPost { + this := CapabilityConfigPost{} + return &this +} + +// NewCapabilityConfigPostWithDefaults instantiates a new CapabilityConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCapabilityConfigPostWithDefaults() *CapabilityConfigPost { + this := CapabilityConfigPost{} + return &this +} + +// GetApprovals returns the Approvals field value if set, zero value otherwise. +func (o *CapabilityConfigPost) GetApprovals() ApprovalsCapabilityConfig { + if o == nil || o.Approvals == nil { + var ret ApprovalsCapabilityConfig + return ret + } + return *o.Approvals +} + +// GetApprovalsOk returns a tuple with the Approvals field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CapabilityConfigPost) GetApprovalsOk() (*ApprovalsCapabilityConfig, bool) { + if o == nil || o.Approvals == nil { + return nil, false + } + return o.Approvals, true +} + +// HasApprovals returns a boolean if a field has been set. +func (o *CapabilityConfigPost) HasApprovals() bool { + if o != nil && o.Approvals != nil { + return true + } + + return false +} + +// SetApprovals gets a reference to the given ApprovalsCapabilityConfig and assigns it to the Approvals field. +func (o *CapabilityConfigPost) SetApprovals(v ApprovalsCapabilityConfig) { + o.Approvals = &v +} + +// GetAuditLogEventsHook returns the AuditLogEventsHook field value if set, zero value otherwise. +func (o *CapabilityConfigPost) GetAuditLogEventsHook() AuditLogEventsHookCapabilityConfigPost { + if o == nil || o.AuditLogEventsHook == nil { + var ret AuditLogEventsHookCapabilityConfigPost + return ret + } + return *o.AuditLogEventsHook +} + +// GetAuditLogEventsHookOk returns a tuple with the AuditLogEventsHook field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CapabilityConfigPost) GetAuditLogEventsHookOk() (*AuditLogEventsHookCapabilityConfigPost, bool) { + if o == nil || o.AuditLogEventsHook == nil { + return nil, false + } + return o.AuditLogEventsHook, true +} + +// HasAuditLogEventsHook returns a boolean if a field has been set. +func (o *CapabilityConfigPost) HasAuditLogEventsHook() bool { + if o != nil && o.AuditLogEventsHook != nil { + return true + } + + return false +} + +// SetAuditLogEventsHook gets a reference to the given AuditLogEventsHookCapabilityConfigPost and assigns it to the AuditLogEventsHook field. +func (o *CapabilityConfigPost) SetAuditLogEventsHook(v AuditLogEventsHookCapabilityConfigPost) { + o.AuditLogEventsHook = &v +} + +func (o CapabilityConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Approvals != nil { + toSerialize["approvals"] = o.Approvals + } + if o.AuditLogEventsHook != nil { + toSerialize["auditLogEventsHook"] = o.AuditLogEventsHook + } + return json.Marshal(toSerialize) +} + +type NullableCapabilityConfigPost struct { + value *CapabilityConfigPost + isSet bool +} + +func (v NullableCapabilityConfigPost) Get() *CapabilityConfigPost { + return v.value +} + +func (v *NullableCapabilityConfigPost) Set(val *CapabilityConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableCapabilityConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableCapabilityConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCapabilityConfigPost(val *CapabilityConfigPost) *NullableCapabilityConfigPost { + return &NullableCapabilityConfigPost{value: val, isSet: true} +} + +func (v NullableCapabilityConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCapabilityConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_rep.go new file mode 100644 index 00000000..8d238f5c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_capability_config_rep.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CapabilityConfigRep struct for CapabilityConfigRep +type CapabilityConfigRep struct { + Approvals *ApprovalsCapabilityConfig `json:"approvals,omitempty"` + AuditLogEventsHook *AuditLogEventsHookCapabilityConfigRep `json:"auditLogEventsHook,omitempty"` +} + +// NewCapabilityConfigRep instantiates a new CapabilityConfigRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCapabilityConfigRep() *CapabilityConfigRep { + this := CapabilityConfigRep{} + return &this +} + +// NewCapabilityConfigRepWithDefaults instantiates a new CapabilityConfigRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCapabilityConfigRepWithDefaults() *CapabilityConfigRep { + this := CapabilityConfigRep{} + return &this +} + +// GetApprovals returns the Approvals field value if set, zero value otherwise. +func (o *CapabilityConfigRep) GetApprovals() ApprovalsCapabilityConfig { + if o == nil || o.Approvals == nil { + var ret ApprovalsCapabilityConfig + return ret + } + return *o.Approvals +} + +// GetApprovalsOk returns a tuple with the Approvals field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CapabilityConfigRep) GetApprovalsOk() (*ApprovalsCapabilityConfig, bool) { + if o == nil || o.Approvals == nil { + return nil, false + } + return o.Approvals, true +} + +// HasApprovals returns a boolean if a field has been set. +func (o *CapabilityConfigRep) HasApprovals() bool { + if o != nil && o.Approvals != nil { + return true + } + + return false +} + +// SetApprovals gets a reference to the given ApprovalsCapabilityConfig and assigns it to the Approvals field. +func (o *CapabilityConfigRep) SetApprovals(v ApprovalsCapabilityConfig) { + o.Approvals = &v +} + +// GetAuditLogEventsHook returns the AuditLogEventsHook field value if set, zero value otherwise. +func (o *CapabilityConfigRep) GetAuditLogEventsHook() AuditLogEventsHookCapabilityConfigRep { + if o == nil || o.AuditLogEventsHook == nil { + var ret AuditLogEventsHookCapabilityConfigRep + return ret + } + return *o.AuditLogEventsHook +} + +// GetAuditLogEventsHookOk returns a tuple with the AuditLogEventsHook field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CapabilityConfigRep) GetAuditLogEventsHookOk() (*AuditLogEventsHookCapabilityConfigRep, bool) { + if o == nil || o.AuditLogEventsHook == nil { + return nil, false + } + return o.AuditLogEventsHook, true +} + +// HasAuditLogEventsHook returns a boolean if a field has been set. +func (o *CapabilityConfigRep) HasAuditLogEventsHook() bool { + if o != nil && o.AuditLogEventsHook != nil { + return true + } + + return false +} + +// SetAuditLogEventsHook gets a reference to the given AuditLogEventsHookCapabilityConfigRep and assigns it to the AuditLogEventsHook field. +func (o *CapabilityConfigRep) SetAuditLogEventsHook(v AuditLogEventsHookCapabilityConfigRep) { + o.AuditLogEventsHook = &v +} + +func (o CapabilityConfigRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Approvals != nil { + toSerialize["approvals"] = o.Approvals + } + if o.AuditLogEventsHook != nil { + toSerialize["auditLogEventsHook"] = o.AuditLogEventsHook + } + return json.Marshal(toSerialize) +} + +type NullableCapabilityConfigRep struct { + value *CapabilityConfigRep + isSet bool +} + +func (v NullableCapabilityConfigRep) Get() *CapabilityConfigRep { + return v.value +} + +func (v *NullableCapabilityConfigRep) Set(val *CapabilityConfigRep) { + v.value = val + v.isSet = true +} + +func (v NullableCapabilityConfigRep) IsSet() bool { + return v.isSet +} + +func (v *NullableCapabilityConfigRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCapabilityConfigRep(val *CapabilityConfigRep) *NullableCapabilityConfigRep { + return &NullableCapabilityConfigRep{value: val, isSet: true} +} + +func (v NullableCapabilityConfigRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCapabilityConfigRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_clause.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_clause.go new file mode 100644 index 00000000..535d0e16 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_clause.go @@ -0,0 +1,268 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Clause struct for Clause +type Clause struct { + Id *string `json:"_id,omitempty"` + Attribute string `json:"attribute"` + Op string `json:"op"` + Values []interface{} `json:"values"` + ContextKind *string `json:"contextKind,omitempty"` + Negate bool `json:"negate"` +} + +// NewClause instantiates a new Clause object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewClause(attribute string, op string, values []interface{}, negate bool) *Clause { + this := Clause{} + this.Attribute = attribute + this.Op = op + this.Values = values + this.Negate = negate + return &this +} + +// NewClauseWithDefaults instantiates a new Clause object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewClauseWithDefaults() *Clause { + this := Clause{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Clause) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Clause) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Clause) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Clause) SetId(v string) { + o.Id = &v +} + +// GetAttribute returns the Attribute field value +func (o *Clause) GetAttribute() string { + if o == nil { + var ret string + return ret + } + + return o.Attribute +} + +// GetAttributeOk returns a tuple with the Attribute field value +// and a boolean to check if the value has been set. +func (o *Clause) GetAttributeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Attribute, true +} + +// SetAttribute sets field value +func (o *Clause) SetAttribute(v string) { + o.Attribute = v +} + +// GetOp returns the Op field value +func (o *Clause) GetOp() string { + if o == nil { + var ret string + return ret + } + + return o.Op +} + +// GetOpOk returns a tuple with the Op field value +// and a boolean to check if the value has been set. +func (o *Clause) GetOpOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Op, true +} + +// SetOp sets field value +func (o *Clause) SetOp(v string) { + o.Op = v +} + +// GetValues returns the Values field value +func (o *Clause) GetValues() []interface{} { + if o == nil { + var ret []interface{} + return ret + } + + return o.Values +} + +// GetValuesOk returns a tuple with the Values field value +// and a boolean to check if the value has been set. +func (o *Clause) GetValuesOk() ([]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Values, true +} + +// SetValues sets field value +func (o *Clause) SetValues(v []interface{}) { + o.Values = v +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *Clause) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Clause) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *Clause) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *Clause) SetContextKind(v string) { + o.ContextKind = &v +} + +// GetNegate returns the Negate field value +func (o *Clause) GetNegate() bool { + if o == nil { + var ret bool + return ret + } + + return o.Negate +} + +// GetNegateOk returns a tuple with the Negate field value +// and a boolean to check if the value has been set. +func (o *Clause) GetNegateOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Negate, true +} + +// SetNegate sets field value +func (o *Clause) SetNegate(v bool) { + o.Negate = v +} + +func (o Clause) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["attribute"] = o.Attribute + } + if true { + toSerialize["op"] = o.Op + } + if true { + toSerialize["values"] = o.Values + } + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + if true { + toSerialize["negate"] = o.Negate + } + return json.Marshal(toSerialize) +} + +type NullableClause struct { + value *Clause + isSet bool +} + +func (v NullableClause) Get() *Clause { + return v.value +} + +func (v *NullableClause) Set(val *Clause) { + v.value = val + v.isSet = true +} + +func (v NullableClause) IsSet() bool { + return v.isSet +} + +func (v *NullableClause) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableClause(val *Clause) *NullableClause { + return &NullableClause{value: val, isSet: true} +} + +func (v NullableClause) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableClause) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_client.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_client.go new file mode 100644 index 00000000..83833122 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_client.go @@ -0,0 +1,333 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Client struct for Client +type Client struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // Client name + Name string `json:"name"` + // Client description + Description *string `json:"description,omitempty"` + // The account ID the client is registered under + AccountId string `json:"_accountId"` + // The client's unique ID + ClientId string `json:"_clientId"` + // The client secret. This will only be shown upon creation. + ClientSecret *string `json:"_clientSecret,omitempty"` + // The client's redirect URI + RedirectUri string `json:"redirectUri"` + CreationDate int64 `json:"_creationDate"` +} + +// NewClient instantiates a new Client object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewClient(links map[string]Link, name string, accountId string, clientId string, redirectUri string, creationDate int64) *Client { + this := Client{} + this.Links = links + this.Name = name + this.AccountId = accountId + this.ClientId = clientId + this.RedirectUri = redirectUri + this.CreationDate = creationDate + return &this +} + +// NewClientWithDefaults instantiates a new Client object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewClientWithDefaults() *Client { + this := Client{} + return &this +} + +// GetLinks returns the Links field value +func (o *Client) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Client) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Client) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetName returns the Name field value +func (o *Client) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Client) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Client) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Client) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Client) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Client) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Client) SetDescription(v string) { + o.Description = &v +} + +// GetAccountId returns the AccountId field value +func (o *Client) GetAccountId() string { + if o == nil { + var ret string + return ret + } + + return o.AccountId +} + +// GetAccountIdOk returns a tuple with the AccountId field value +// and a boolean to check if the value has been set. +func (o *Client) GetAccountIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.AccountId, true +} + +// SetAccountId sets field value +func (o *Client) SetAccountId(v string) { + o.AccountId = v +} + +// GetClientId returns the ClientId field value +func (o *Client) GetClientId() string { + if o == nil { + var ret string + return ret + } + + return o.ClientId +} + +// GetClientIdOk returns a tuple with the ClientId field value +// and a boolean to check if the value has been set. +func (o *Client) GetClientIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ClientId, true +} + +// SetClientId sets field value +func (o *Client) SetClientId(v string) { + o.ClientId = v +} + +// GetClientSecret returns the ClientSecret field value if set, zero value otherwise. +func (o *Client) GetClientSecret() string { + if o == nil || o.ClientSecret == nil { + var ret string + return ret + } + return *o.ClientSecret +} + +// GetClientSecretOk returns a tuple with the ClientSecret field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Client) GetClientSecretOk() (*string, bool) { + if o == nil || o.ClientSecret == nil { + return nil, false + } + return o.ClientSecret, true +} + +// HasClientSecret returns a boolean if a field has been set. +func (o *Client) HasClientSecret() bool { + if o != nil && o.ClientSecret != nil { + return true + } + + return false +} + +// SetClientSecret gets a reference to the given string and assigns it to the ClientSecret field. +func (o *Client) SetClientSecret(v string) { + o.ClientSecret = &v +} + +// GetRedirectUri returns the RedirectUri field value +func (o *Client) GetRedirectUri() string { + if o == nil { + var ret string + return ret + } + + return o.RedirectUri +} + +// GetRedirectUriOk returns a tuple with the RedirectUri field value +// and a boolean to check if the value has been set. +func (o *Client) GetRedirectUriOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.RedirectUri, true +} + +// SetRedirectUri sets field value +func (o *Client) SetRedirectUri(v string) { + o.RedirectUri = v +} + +// GetCreationDate returns the CreationDate field value +func (o *Client) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *Client) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *Client) SetCreationDate(v int64) { + o.CreationDate = v +} + +func (o Client) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["_accountId"] = o.AccountId + } + if true { + toSerialize["_clientId"] = o.ClientId + } + if o.ClientSecret != nil { + toSerialize["_clientSecret"] = o.ClientSecret + } + if true { + toSerialize["redirectUri"] = o.RedirectUri + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + return json.Marshal(toSerialize) +} + +type NullableClient struct { + value *Client + isSet bool +} + +func (v NullableClient) Get() *Client { + return v.value +} + +func (v *NullableClient) Set(val *Client) { + v.value = val + v.isSet = true +} + +func (v NullableClient) IsSet() bool { + return v.isSet +} + +func (v *NullableClient) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableClient(val *Client) *NullableClient { + return &NullableClient{value: val, isSet: true} +} + +func (v NullableClient) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableClient) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_client_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_collection.go new file mode 100644 index 00000000..f8986085 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_collection.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ClientCollection struct for ClientCollection +type ClientCollection struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // List of client objects + Items []Client `json:"items"` +} + +// NewClientCollection instantiates a new ClientCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewClientCollection(links map[string]Link, items []Client) *ClientCollection { + this := ClientCollection{} + this.Links = links + this.Items = items + return &this +} + +// NewClientCollectionWithDefaults instantiates a new ClientCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewClientCollectionWithDefaults() *ClientCollection { + this := ClientCollection{} + return &this +} + +// GetLinks returns the Links field value +func (o *ClientCollection) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ClientCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ClientCollection) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *ClientCollection) GetItems() []Client { + if o == nil { + var ret []Client + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ClientCollection) GetItemsOk() ([]Client, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ClientCollection) SetItems(v []Client) { + o.Items = v +} + +func (o ClientCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableClientCollection struct { + value *ClientCollection + isSet bool +} + +func (v NullableClientCollection) Get() *ClientCollection { + return v.value +} + +func (v *NullableClientCollection) Set(val *ClientCollection) { + v.value = val + v.isSet = true +} + +func (v NullableClientCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableClientCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableClientCollection(val *ClientCollection) *NullableClientCollection { + return &NullableClientCollection{value: val, isSet: true} +} + +func (v NullableClientCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableClientCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability.go new file mode 100644 index 00000000..c1f4c092 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ClientSideAvailability struct for ClientSideAvailability +type ClientSideAvailability struct { + UsingMobileKey *bool `json:"usingMobileKey,omitempty"` + UsingEnvironmentId *bool `json:"usingEnvironmentId,omitempty"` +} + +// NewClientSideAvailability instantiates a new ClientSideAvailability object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewClientSideAvailability() *ClientSideAvailability { + this := ClientSideAvailability{} + return &this +} + +// NewClientSideAvailabilityWithDefaults instantiates a new ClientSideAvailability object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewClientSideAvailabilityWithDefaults() *ClientSideAvailability { + this := ClientSideAvailability{} + return &this +} + +// GetUsingMobileKey returns the UsingMobileKey field value if set, zero value otherwise. +func (o *ClientSideAvailability) GetUsingMobileKey() bool { + if o == nil || o.UsingMobileKey == nil { + var ret bool + return ret + } + return *o.UsingMobileKey +} + +// GetUsingMobileKeyOk returns a tuple with the UsingMobileKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ClientSideAvailability) GetUsingMobileKeyOk() (*bool, bool) { + if o == nil || o.UsingMobileKey == nil { + return nil, false + } + return o.UsingMobileKey, true +} + +// HasUsingMobileKey returns a boolean if a field has been set. +func (o *ClientSideAvailability) HasUsingMobileKey() bool { + if o != nil && o.UsingMobileKey != nil { + return true + } + + return false +} + +// SetUsingMobileKey gets a reference to the given bool and assigns it to the UsingMobileKey field. +func (o *ClientSideAvailability) SetUsingMobileKey(v bool) { + o.UsingMobileKey = &v +} + +// GetUsingEnvironmentId returns the UsingEnvironmentId field value if set, zero value otherwise. +func (o *ClientSideAvailability) GetUsingEnvironmentId() bool { + if o == nil || o.UsingEnvironmentId == nil { + var ret bool + return ret + } + return *o.UsingEnvironmentId +} + +// GetUsingEnvironmentIdOk returns a tuple with the UsingEnvironmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ClientSideAvailability) GetUsingEnvironmentIdOk() (*bool, bool) { + if o == nil || o.UsingEnvironmentId == nil { + return nil, false + } + return o.UsingEnvironmentId, true +} + +// HasUsingEnvironmentId returns a boolean if a field has been set. +func (o *ClientSideAvailability) HasUsingEnvironmentId() bool { + if o != nil && o.UsingEnvironmentId != nil { + return true + } + + return false +} + +// SetUsingEnvironmentId gets a reference to the given bool and assigns it to the UsingEnvironmentId field. +func (o *ClientSideAvailability) SetUsingEnvironmentId(v bool) { + o.UsingEnvironmentId = &v +} + +func (o ClientSideAvailability) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UsingMobileKey != nil { + toSerialize["usingMobileKey"] = o.UsingMobileKey + } + if o.UsingEnvironmentId != nil { + toSerialize["usingEnvironmentId"] = o.UsingEnvironmentId + } + return json.Marshal(toSerialize) +} + +type NullableClientSideAvailability struct { + value *ClientSideAvailability + isSet bool +} + +func (v NullableClientSideAvailability) Get() *ClientSideAvailability { + return v.value +} + +func (v *NullableClientSideAvailability) Set(val *ClientSideAvailability) { + v.value = val + v.isSet = true +} + +func (v NullableClientSideAvailability) IsSet() bool { + return v.isSet +} + +func (v *NullableClientSideAvailability) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableClientSideAvailability(val *ClientSideAvailability) *NullableClientSideAvailability { + return &NullableClientSideAvailability{value: val, isSet: true} +} + +func (v NullableClientSideAvailability) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableClientSideAvailability) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability_post.go new file mode 100644 index 00000000..4e26c5a8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_client_side_availability_post.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ClientSideAvailabilityPost struct for ClientSideAvailabilityPost +type ClientSideAvailabilityPost struct { + // Whether to enable availability for client-side SDKs. Defaults to false. + UsingEnvironmentId bool `json:"usingEnvironmentId"` + // Whether to enable availability for mobile SDKs. Defaults to true. + UsingMobileKey bool `json:"usingMobileKey"` +} + +// NewClientSideAvailabilityPost instantiates a new ClientSideAvailabilityPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewClientSideAvailabilityPost(usingEnvironmentId bool, usingMobileKey bool) *ClientSideAvailabilityPost { + this := ClientSideAvailabilityPost{} + this.UsingEnvironmentId = usingEnvironmentId + this.UsingMobileKey = usingMobileKey + return &this +} + +// NewClientSideAvailabilityPostWithDefaults instantiates a new ClientSideAvailabilityPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewClientSideAvailabilityPostWithDefaults() *ClientSideAvailabilityPost { + this := ClientSideAvailabilityPost{} + return &this +} + +// GetUsingEnvironmentId returns the UsingEnvironmentId field value +func (o *ClientSideAvailabilityPost) GetUsingEnvironmentId() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingEnvironmentId +} + +// GetUsingEnvironmentIdOk returns a tuple with the UsingEnvironmentId field value +// and a boolean to check if the value has been set. +func (o *ClientSideAvailabilityPost) GetUsingEnvironmentIdOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingEnvironmentId, true +} + +// SetUsingEnvironmentId sets field value +func (o *ClientSideAvailabilityPost) SetUsingEnvironmentId(v bool) { + o.UsingEnvironmentId = v +} + +// GetUsingMobileKey returns the UsingMobileKey field value +func (o *ClientSideAvailabilityPost) GetUsingMobileKey() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingMobileKey +} + +// GetUsingMobileKeyOk returns a tuple with the UsingMobileKey field value +// and a boolean to check if the value has been set. +func (o *ClientSideAvailabilityPost) GetUsingMobileKeyOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingMobileKey, true +} + +// SetUsingMobileKey sets field value +func (o *ClientSideAvailabilityPost) SetUsingMobileKey(v bool) { + o.UsingMobileKey = v +} + +func (o ClientSideAvailabilityPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["usingEnvironmentId"] = o.UsingEnvironmentId + } + if true { + toSerialize["usingMobileKey"] = o.UsingMobileKey + } + return json.Marshal(toSerialize) +} + +type NullableClientSideAvailabilityPost struct { + value *ClientSideAvailabilityPost + isSet bool +} + +func (v NullableClientSideAvailabilityPost) Get() *ClientSideAvailabilityPost { + return v.value +} + +func (v *NullableClientSideAvailabilityPost) Set(val *ClientSideAvailabilityPost) { + v.value = val + v.isSet = true +} + +func (v NullableClientSideAvailabilityPost) IsSet() bool { + return v.isSet +} + +func (v *NullableClientSideAvailabilityPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableClientSideAvailabilityPost(val *ClientSideAvailabilityPost) *NullableClientSideAvailabilityPost { + return &NullableClientSideAvailabilityPost{value: val, isSet: true} +} + +func (v NullableClientSideAvailabilityPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableClientSideAvailabilityPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_completed_by.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_completed_by.go new file mode 100644 index 00000000..017dbb2f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_completed_by.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CompletedBy struct for CompletedBy +type CompletedBy struct { + Member *MemberSummary `json:"member,omitempty"` + Token *TokenSummary `json:"token,omitempty"` +} + +// NewCompletedBy instantiates a new CompletedBy object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCompletedBy() *CompletedBy { + this := CompletedBy{} + return &this +} + +// NewCompletedByWithDefaults instantiates a new CompletedBy object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCompletedByWithDefaults() *CompletedBy { + this := CompletedBy{} + return &this +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *CompletedBy) GetMember() MemberSummary { + if o == nil || o.Member == nil { + var ret MemberSummary + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CompletedBy) GetMemberOk() (*MemberSummary, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *CompletedBy) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given MemberSummary and assigns it to the Member field. +func (o *CompletedBy) SetMember(v MemberSummary) { + o.Member = &v +} + +// GetToken returns the Token field value if set, zero value otherwise. +func (o *CompletedBy) GetToken() TokenSummary { + if o == nil || o.Token == nil { + var ret TokenSummary + return ret + } + return *o.Token +} + +// GetTokenOk returns a tuple with the Token field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CompletedBy) GetTokenOk() (*TokenSummary, bool) { + if o == nil || o.Token == nil { + return nil, false + } + return o.Token, true +} + +// HasToken returns a boolean if a field has been set. +func (o *CompletedBy) HasToken() bool { + if o != nil && o.Token != nil { + return true + } + + return false +} + +// SetToken gets a reference to the given TokenSummary and assigns it to the Token field. +func (o *CompletedBy) SetToken(v TokenSummary) { + o.Token = &v +} + +func (o CompletedBy) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Member != nil { + toSerialize["member"] = o.Member + } + if o.Token != nil { + toSerialize["token"] = o.Token + } + return json.Marshal(toSerialize) +} + +type NullableCompletedBy struct { + value *CompletedBy + isSet bool +} + +func (v NullableCompletedBy) Get() *CompletedBy { + return v.value +} + +func (v *NullableCompletedBy) Set(val *CompletedBy) { + v.value = val + v.isSet = true +} + +func (v NullableCompletedBy) IsSet() bool { + return v.isSet +} + +func (v *NullableCompletedBy) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCompletedBy(val *CompletedBy) *NullableCompletedBy { + return &NullableCompletedBy{value: val, isSet: true} +} + +func (v NullableCompletedBy) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCompletedBy) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_input.go new file mode 100644 index 00000000..262baa39 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_input.go @@ -0,0 +1,409 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ConditionInput struct for ConditionInput +type ConditionInput struct { + ScheduleKind *string `json:"scheduleKind,omitempty"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + // For workflow stages whose scheduled execution is relative, how far in the future the stage should start. + WaitDuration *int32 `json:"waitDuration,omitempty"` + WaitDurationUnit *string `json:"waitDurationUnit,omitempty"` + // Whether the workflow stage should be executed immediately + ExecuteNow *bool `json:"executeNow,omitempty"` + // A description of the approval required for this stage + Description *string `json:"description,omitempty"` + // A list of member IDs for the members to request approval from for this stage + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // A list of team keys for the teams to request approval from for this stage + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` + Kind *string `json:"kind,omitempty"` +} + +// NewConditionInput instantiates a new ConditionInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewConditionInput() *ConditionInput { + this := ConditionInput{} + return &this +} + +// NewConditionInputWithDefaults instantiates a new ConditionInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewConditionInputWithDefaults() *ConditionInput { + this := ConditionInput{} + return &this +} + +// GetScheduleKind returns the ScheduleKind field value if set, zero value otherwise. +func (o *ConditionInput) GetScheduleKind() string { + if o == nil || o.ScheduleKind == nil { + var ret string + return ret + } + return *o.ScheduleKind +} + +// GetScheduleKindOk returns a tuple with the ScheduleKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetScheduleKindOk() (*string, bool) { + if o == nil || o.ScheduleKind == nil { + return nil, false + } + return o.ScheduleKind, true +} + +// HasScheduleKind returns a boolean if a field has been set. +func (o *ConditionInput) HasScheduleKind() bool { + if o != nil && o.ScheduleKind != nil { + return true + } + + return false +} + +// SetScheduleKind gets a reference to the given string and assigns it to the ScheduleKind field. +func (o *ConditionInput) SetScheduleKind(v string) { + o.ScheduleKind = &v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *ConditionInput) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *ConditionInput) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *ConditionInput) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetWaitDuration returns the WaitDuration field value if set, zero value otherwise. +func (o *ConditionInput) GetWaitDuration() int32 { + if o == nil || o.WaitDuration == nil { + var ret int32 + return ret + } + return *o.WaitDuration +} + +// GetWaitDurationOk returns a tuple with the WaitDuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetWaitDurationOk() (*int32, bool) { + if o == nil || o.WaitDuration == nil { + return nil, false + } + return o.WaitDuration, true +} + +// HasWaitDuration returns a boolean if a field has been set. +func (o *ConditionInput) HasWaitDuration() bool { + if o != nil && o.WaitDuration != nil { + return true + } + + return false +} + +// SetWaitDuration gets a reference to the given int32 and assigns it to the WaitDuration field. +func (o *ConditionInput) SetWaitDuration(v int32) { + o.WaitDuration = &v +} + +// GetWaitDurationUnit returns the WaitDurationUnit field value if set, zero value otherwise. +func (o *ConditionInput) GetWaitDurationUnit() string { + if o == nil || o.WaitDurationUnit == nil { + var ret string + return ret + } + return *o.WaitDurationUnit +} + +// GetWaitDurationUnitOk returns a tuple with the WaitDurationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetWaitDurationUnitOk() (*string, bool) { + if o == nil || o.WaitDurationUnit == nil { + return nil, false + } + return o.WaitDurationUnit, true +} + +// HasWaitDurationUnit returns a boolean if a field has been set. +func (o *ConditionInput) HasWaitDurationUnit() bool { + if o != nil && o.WaitDurationUnit != nil { + return true + } + + return false +} + +// SetWaitDurationUnit gets a reference to the given string and assigns it to the WaitDurationUnit field. +func (o *ConditionInput) SetWaitDurationUnit(v string) { + o.WaitDurationUnit = &v +} + +// GetExecuteNow returns the ExecuteNow field value if set, zero value otherwise. +func (o *ConditionInput) GetExecuteNow() bool { + if o == nil || o.ExecuteNow == nil { + var ret bool + return ret + } + return *o.ExecuteNow +} + +// GetExecuteNowOk returns a tuple with the ExecuteNow field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetExecuteNowOk() (*bool, bool) { + if o == nil || o.ExecuteNow == nil { + return nil, false + } + return o.ExecuteNow, true +} + +// HasExecuteNow returns a boolean if a field has been set. +func (o *ConditionInput) HasExecuteNow() bool { + if o != nil && o.ExecuteNow != nil { + return true + } + + return false +} + +// SetExecuteNow gets a reference to the given bool and assigns it to the ExecuteNow field. +func (o *ConditionInput) SetExecuteNow(v bool) { + o.ExecuteNow = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ConditionInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ConditionInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ConditionInput) SetDescription(v string) { + o.Description = &v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *ConditionInput) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *ConditionInput) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *ConditionInput) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *ConditionInput) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *ConditionInput) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *ConditionInput) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *ConditionInput) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionInput) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *ConditionInput) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *ConditionInput) SetKind(v string) { + o.Kind = &v +} + +func (o ConditionInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ScheduleKind != nil { + toSerialize["scheduleKind"] = o.ScheduleKind + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.WaitDuration != nil { + toSerialize["waitDuration"] = o.WaitDuration + } + if o.WaitDurationUnit != nil { + toSerialize["waitDurationUnit"] = o.WaitDurationUnit + } + if o.ExecuteNow != nil { + toSerialize["executeNow"] = o.ExecuteNow + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + return json.Marshal(toSerialize) +} + +type NullableConditionInput struct { + value *ConditionInput + isSet bool +} + +func (v NullableConditionInput) Get() *ConditionInput { + return v.value +} + +func (v *NullableConditionInput) Set(val *ConditionInput) { + v.value = val + v.isSet = true +} + +func (v NullableConditionInput) IsSet() bool { + return v.isSet +} + +func (v *NullableConditionInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableConditionInput(val *ConditionInput) *NullableConditionInput { + return &NullableConditionInput{value: val, isSet: true} +} + +func (v NullableConditionInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableConditionInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_output.go new file mode 100644 index 00000000..76bb4aef --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_condition_output.go @@ -0,0 +1,470 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ConditionOutput struct for ConditionOutput +type ConditionOutput struct { + Id string `json:"_id"` + Kind *string `json:"kind,omitempty"` + Execution ExecutionOutput `json:"_execution"` + ScheduleKind *string `json:"scheduleKind,omitempty"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + WaitDuration *int32 `json:"waitDuration,omitempty"` + WaitDurationUnit *string `json:"waitDurationUnit,omitempty"` + Description string `json:"description"` + NotifyMemberIds []string `json:"notifyMemberIds"` + AllReviews []ReviewOutput `json:"allReviews"` + ReviewStatus string `json:"reviewStatus"` + AppliedDate *int64 `json:"appliedDate,omitempty"` +} + +// NewConditionOutput instantiates a new ConditionOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewConditionOutput(id string, execution ExecutionOutput, description string, notifyMemberIds []string, allReviews []ReviewOutput, reviewStatus string) *ConditionOutput { + this := ConditionOutput{} + this.Id = id + this.Execution = execution + this.Description = description + this.NotifyMemberIds = notifyMemberIds + this.AllReviews = allReviews + this.ReviewStatus = reviewStatus + return &this +} + +// NewConditionOutputWithDefaults instantiates a new ConditionOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewConditionOutputWithDefaults() *ConditionOutput { + this := ConditionOutput{} + return &this +} + +// GetId returns the Id field value +func (o *ConditionOutput) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ConditionOutput) SetId(v string) { + o.Id = v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *ConditionOutput) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *ConditionOutput) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *ConditionOutput) SetKind(v string) { + o.Kind = &v +} + +// GetExecution returns the Execution field value +func (o *ConditionOutput) GetExecution() ExecutionOutput { + if o == nil { + var ret ExecutionOutput + return ret + } + + return o.Execution +} + +// GetExecutionOk returns a tuple with the Execution field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetExecutionOk() (*ExecutionOutput, bool) { + if o == nil { + return nil, false + } + return &o.Execution, true +} + +// SetExecution sets field value +func (o *ConditionOutput) SetExecution(v ExecutionOutput) { + o.Execution = v +} + +// GetScheduleKind returns the ScheduleKind field value if set, zero value otherwise. +func (o *ConditionOutput) GetScheduleKind() string { + if o == nil || o.ScheduleKind == nil { + var ret string + return ret + } + return *o.ScheduleKind +} + +// GetScheduleKindOk returns a tuple with the ScheduleKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetScheduleKindOk() (*string, bool) { + if o == nil || o.ScheduleKind == nil { + return nil, false + } + return o.ScheduleKind, true +} + +// HasScheduleKind returns a boolean if a field has been set. +func (o *ConditionOutput) HasScheduleKind() bool { + if o != nil && o.ScheduleKind != nil { + return true + } + + return false +} + +// SetScheduleKind gets a reference to the given string and assigns it to the ScheduleKind field. +func (o *ConditionOutput) SetScheduleKind(v string) { + o.ScheduleKind = &v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *ConditionOutput) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *ConditionOutput) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *ConditionOutput) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetWaitDuration returns the WaitDuration field value if set, zero value otherwise. +func (o *ConditionOutput) GetWaitDuration() int32 { + if o == nil || o.WaitDuration == nil { + var ret int32 + return ret + } + return *o.WaitDuration +} + +// GetWaitDurationOk returns a tuple with the WaitDuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetWaitDurationOk() (*int32, bool) { + if o == nil || o.WaitDuration == nil { + return nil, false + } + return o.WaitDuration, true +} + +// HasWaitDuration returns a boolean if a field has been set. +func (o *ConditionOutput) HasWaitDuration() bool { + if o != nil && o.WaitDuration != nil { + return true + } + + return false +} + +// SetWaitDuration gets a reference to the given int32 and assigns it to the WaitDuration field. +func (o *ConditionOutput) SetWaitDuration(v int32) { + o.WaitDuration = &v +} + +// GetWaitDurationUnit returns the WaitDurationUnit field value if set, zero value otherwise. +func (o *ConditionOutput) GetWaitDurationUnit() string { + if o == nil || o.WaitDurationUnit == nil { + var ret string + return ret + } + return *o.WaitDurationUnit +} + +// GetWaitDurationUnitOk returns a tuple with the WaitDurationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetWaitDurationUnitOk() (*string, bool) { + if o == nil || o.WaitDurationUnit == nil { + return nil, false + } + return o.WaitDurationUnit, true +} + +// HasWaitDurationUnit returns a boolean if a field has been set. +func (o *ConditionOutput) HasWaitDurationUnit() bool { + if o != nil && o.WaitDurationUnit != nil { + return true + } + + return false +} + +// SetWaitDurationUnit gets a reference to the given string and assigns it to the WaitDurationUnit field. +func (o *ConditionOutput) SetWaitDurationUnit(v string) { + o.WaitDurationUnit = &v +} + +// GetDescription returns the Description field value +func (o *ConditionOutput) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *ConditionOutput) SetDescription(v string) { + o.Description = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value +func (o *ConditionOutput) GetNotifyMemberIds() []string { + if o == nil { + var ret []string + return ret + } + + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// SetNotifyMemberIds sets field value +func (o *ConditionOutput) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetAllReviews returns the AllReviews field value +func (o *ConditionOutput) GetAllReviews() []ReviewOutput { + if o == nil { + var ret []ReviewOutput + return ret + } + + return o.AllReviews +} + +// GetAllReviewsOk returns a tuple with the AllReviews field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetAllReviewsOk() ([]ReviewOutput, bool) { + if o == nil { + return nil, false + } + return o.AllReviews, true +} + +// SetAllReviews sets field value +func (o *ConditionOutput) SetAllReviews(v []ReviewOutput) { + o.AllReviews = v +} + +// GetReviewStatus returns the ReviewStatus field value +func (o *ConditionOutput) GetReviewStatus() string { + if o == nil { + var ret string + return ret + } + + return o.ReviewStatus +} + +// GetReviewStatusOk returns a tuple with the ReviewStatus field value +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetReviewStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReviewStatus, true +} + +// SetReviewStatus sets field value +func (o *ConditionOutput) SetReviewStatus(v string) { + o.ReviewStatus = v +} + +// GetAppliedDate returns the AppliedDate field value if set, zero value otherwise. +func (o *ConditionOutput) GetAppliedDate() int64 { + if o == nil || o.AppliedDate == nil { + var ret int64 + return ret + } + return *o.AppliedDate +} + +// GetAppliedDateOk returns a tuple with the AppliedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ConditionOutput) GetAppliedDateOk() (*int64, bool) { + if o == nil || o.AppliedDate == nil { + return nil, false + } + return o.AppliedDate, true +} + +// HasAppliedDate returns a boolean if a field has been set. +func (o *ConditionOutput) HasAppliedDate() bool { + if o != nil && o.AppliedDate != nil { + return true + } + + return false +} + +// SetAppliedDate gets a reference to the given int64 and assigns it to the AppliedDate field. +func (o *ConditionOutput) SetAppliedDate(v int64) { + o.AppliedDate = &v +} + +func (o ConditionOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["_execution"] = o.Execution + } + if o.ScheduleKind != nil { + toSerialize["scheduleKind"] = o.ScheduleKind + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.WaitDuration != nil { + toSerialize["waitDuration"] = o.WaitDuration + } + if o.WaitDurationUnit != nil { + toSerialize["waitDurationUnit"] = o.WaitDurationUnit + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if true { + toSerialize["allReviews"] = o.AllReviews + } + if true { + toSerialize["reviewStatus"] = o.ReviewStatus + } + if o.AppliedDate != nil { + toSerialize["appliedDate"] = o.AppliedDate + } + return json.Marshal(toSerialize) +} + +type NullableConditionOutput struct { + value *ConditionOutput + isSet bool +} + +func (v NullableConditionOutput) Get() *ConditionOutput { + return v.value +} + +func (v *NullableConditionOutput) Set(val *ConditionOutput) { + v.value = val + v.isSet = true +} + +func (v NullableConditionOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableConditionOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableConditionOutput(val *ConditionOutput) *NullableConditionOutput { + return &NullableConditionOutput{value: val, isSet: true} +} + +func (v NullableConditionOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableConditionOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict.go new file mode 100644 index 00000000..c498950c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Conflict struct for Conflict +type Conflict struct { + Instruction map[string]interface{} `json:"instruction,omitempty"` + // Reason why the conflict exists + Reason *string `json:"reason,omitempty"` +} + +// NewConflict instantiates a new Conflict object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewConflict() *Conflict { + this := Conflict{} + return &this +} + +// NewConflictWithDefaults instantiates a new Conflict object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewConflictWithDefaults() *Conflict { + this := Conflict{} + return &this +} + +// GetInstruction returns the Instruction field value if set, zero value otherwise. +func (o *Conflict) GetInstruction() map[string]interface{} { + if o == nil || o.Instruction == nil { + var ret map[string]interface{} + return ret + } + return o.Instruction +} + +// GetInstructionOk returns a tuple with the Instruction field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Conflict) GetInstructionOk() (map[string]interface{}, bool) { + if o == nil || o.Instruction == nil { + return nil, false + } + return o.Instruction, true +} + +// HasInstruction returns a boolean if a field has been set. +func (o *Conflict) HasInstruction() bool { + if o != nil && o.Instruction != nil { + return true + } + + return false +} + +// SetInstruction gets a reference to the given map[string]interface{} and assigns it to the Instruction field. +func (o *Conflict) SetInstruction(v map[string]interface{}) { + o.Instruction = v +} + +// GetReason returns the Reason field value if set, zero value otherwise. +func (o *Conflict) GetReason() string { + if o == nil || o.Reason == nil { + var ret string + return ret + } + return *o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Conflict) GetReasonOk() (*string, bool) { + if o == nil || o.Reason == nil { + return nil, false + } + return o.Reason, true +} + +// HasReason returns a boolean if a field has been set. +func (o *Conflict) HasReason() bool { + if o != nil && o.Reason != nil { + return true + } + + return false +} + +// SetReason gets a reference to the given string and assigns it to the Reason field. +func (o *Conflict) SetReason(v string) { + o.Reason = &v +} + +func (o Conflict) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Instruction != nil { + toSerialize["instruction"] = o.Instruction + } + if o.Reason != nil { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableConflict struct { + value *Conflict + isSet bool +} + +func (v NullableConflict) Get() *Conflict { + return v.value +} + +func (v *NullableConflict) Set(val *Conflict) { + v.value = val + v.isSet = true +} + +func (v NullableConflict) IsSet() bool { + return v.isSet +} + +func (v *NullableConflict) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableConflict(val *Conflict) *NullableConflict { + return &NullableConflict{value: val, isSet: true} +} + +func (v NullableConflict) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableConflict) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict_output.go new file mode 100644 index 00000000..5d370951 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_conflict_output.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ConflictOutput struct for ConflictOutput +type ConflictOutput struct { + // The stage ID + StageId string `json:"stageId"` + // Message about the conflict + Message string `json:"message"` +} + +// NewConflictOutput instantiates a new ConflictOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewConflictOutput(stageId string, message string) *ConflictOutput { + this := ConflictOutput{} + this.StageId = stageId + this.Message = message + return &this +} + +// NewConflictOutputWithDefaults instantiates a new ConflictOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewConflictOutputWithDefaults() *ConflictOutput { + this := ConflictOutput{} + return &this +} + +// GetStageId returns the StageId field value +func (o *ConflictOutput) GetStageId() string { + if o == nil { + var ret string + return ret + } + + return o.StageId +} + +// GetStageIdOk returns a tuple with the StageId field value +// and a boolean to check if the value has been set. +func (o *ConflictOutput) GetStageIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.StageId, true +} + +// SetStageId sets field value +func (o *ConflictOutput) SetStageId(v string) { + o.StageId = v +} + +// GetMessage returns the Message field value +func (o *ConflictOutput) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *ConflictOutput) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *ConflictOutput) SetMessage(v string) { + o.Message = v +} + +func (o ConflictOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["stageId"] = o.StageId + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableConflictOutput struct { + value *ConflictOutput + isSet bool +} + +func (v NullableConflictOutput) Get() *ConflictOutput { + return v.value +} + +func (v *NullableConflictOutput) Set(val *ConflictOutput) { + v.value = val + v.isSet = true +} + +func (v NullableConflictOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableConflictOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableConflictOutput(val *ConflictOutput) *NullableConflictOutput { + return &NullableConflictOutput{value: val, isSet: true} +} + +func (v NullableConflictOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableConflictOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_name.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_name.go new file mode 100644 index 00000000..e616242d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_name.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeName struct for ContextAttributeName +type ContextAttributeName struct { + // A context attribute's name. + Name string `json:"name"` + // A relative estimate of the number of contexts seen recently that have an attribute with the associated name. + Weight int32 `json:"weight"` + // Whether or not the attribute has one or more redacted values. + Redacted *bool `json:"redacted,omitempty"` +} + +// NewContextAttributeName instantiates a new ContextAttributeName object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeName(name string, weight int32) *ContextAttributeName { + this := ContextAttributeName{} + this.Name = name + this.Weight = weight + return &this +} + +// NewContextAttributeNameWithDefaults instantiates a new ContextAttributeName object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeNameWithDefaults() *ContextAttributeName { + this := ContextAttributeName{} + return &this +} + +// GetName returns the Name field value +func (o *ContextAttributeName) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeName) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ContextAttributeName) SetName(v string) { + o.Name = v +} + +// GetWeight returns the Weight field value +func (o *ContextAttributeName) GetWeight() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Weight +} + +// GetWeightOk returns a tuple with the Weight field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeName) GetWeightOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Weight, true +} + +// SetWeight sets field value +func (o *ContextAttributeName) SetWeight(v int32) { + o.Weight = v +} + +// GetRedacted returns the Redacted field value if set, zero value otherwise. +func (o *ContextAttributeName) GetRedacted() bool { + if o == nil || o.Redacted == nil { + var ret bool + return ret + } + return *o.Redacted +} + +// GetRedactedOk returns a tuple with the Redacted field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextAttributeName) GetRedactedOk() (*bool, bool) { + if o == nil || o.Redacted == nil { + return nil, false + } + return o.Redacted, true +} + +// HasRedacted returns a boolean if a field has been set. +func (o *ContextAttributeName) HasRedacted() bool { + if o != nil && o.Redacted != nil { + return true + } + + return false +} + +// SetRedacted gets a reference to the given bool and assigns it to the Redacted field. +func (o *ContextAttributeName) SetRedacted(v bool) { + o.Redacted = &v +} + +func (o ContextAttributeName) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["weight"] = o.Weight + } + if o.Redacted != nil { + toSerialize["redacted"] = o.Redacted + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeName struct { + value *ContextAttributeName + isSet bool +} + +func (v NullableContextAttributeName) Get() *ContextAttributeName { + return v.value +} + +func (v *NullableContextAttributeName) Set(val *ContextAttributeName) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeName) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeName) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeName(val *ContextAttributeName) *NullableContextAttributeName { + return &NullableContextAttributeName{value: val, isSet: true} +} + +func (v NullableContextAttributeName) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeName) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names.go new file mode 100644 index 00000000..5f225afe --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeNames struct for ContextAttributeNames +type ContextAttributeNames struct { + // The kind associated with this collection of context attribute names. + Kind string `json:"kind"` + // A collection of context attribute names. + Names []ContextAttributeName `json:"names"` +} + +// NewContextAttributeNames instantiates a new ContextAttributeNames object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeNames(kind string, names []ContextAttributeName) *ContextAttributeNames { + this := ContextAttributeNames{} + this.Kind = kind + this.Names = names + return &this +} + +// NewContextAttributeNamesWithDefaults instantiates a new ContextAttributeNames object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeNamesWithDefaults() *ContextAttributeNames { + this := ContextAttributeNames{} + return &this +} + +// GetKind returns the Kind field value +func (o *ContextAttributeNames) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeNames) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ContextAttributeNames) SetKind(v string) { + o.Kind = v +} + +// GetNames returns the Names field value +func (o *ContextAttributeNames) GetNames() []ContextAttributeName { + if o == nil { + var ret []ContextAttributeName + return ret + } + + return o.Names +} + +// GetNamesOk returns a tuple with the Names field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeNames) GetNamesOk() ([]ContextAttributeName, bool) { + if o == nil { + return nil, false + } + return o.Names, true +} + +// SetNames sets field value +func (o *ContextAttributeNames) SetNames(v []ContextAttributeName) { + o.Names = v +} + +func (o ContextAttributeNames) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["names"] = o.Names + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeNames struct { + value *ContextAttributeNames + isSet bool +} + +func (v NullableContextAttributeNames) Get() *ContextAttributeNames { + return v.value +} + +func (v *NullableContextAttributeNames) Set(val *ContextAttributeNames) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeNames) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeNames) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeNames(val *ContextAttributeNames) *NullableContextAttributeNames { + return &NullableContextAttributeNames{value: val, isSet: true} +} + +func (v NullableContextAttributeNames) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeNames) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names_collection.go new file mode 100644 index 00000000..73e44201 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_names_collection.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeNamesCollection struct for ContextAttributeNamesCollection +type ContextAttributeNamesCollection struct { + // A collection of context attribute name data grouped by kind. + Items []ContextAttributeNames `json:"items"` +} + +// NewContextAttributeNamesCollection instantiates a new ContextAttributeNamesCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeNamesCollection(items []ContextAttributeNames) *ContextAttributeNamesCollection { + this := ContextAttributeNamesCollection{} + this.Items = items + return &this +} + +// NewContextAttributeNamesCollectionWithDefaults instantiates a new ContextAttributeNamesCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeNamesCollectionWithDefaults() *ContextAttributeNamesCollection { + this := ContextAttributeNamesCollection{} + return &this +} + +// GetItems returns the Items field value +func (o *ContextAttributeNamesCollection) GetItems() []ContextAttributeNames { + if o == nil { + var ret []ContextAttributeNames + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeNamesCollection) GetItemsOk() ([]ContextAttributeNames, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextAttributeNamesCollection) SetItems(v []ContextAttributeNames) { + o.Items = v +} + +func (o ContextAttributeNamesCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeNamesCollection struct { + value *ContextAttributeNamesCollection + isSet bool +} + +func (v NullableContextAttributeNamesCollection) Get() *ContextAttributeNamesCollection { + return v.value +} + +func (v *NullableContextAttributeNamesCollection) Set(val *ContextAttributeNamesCollection) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeNamesCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeNamesCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeNamesCollection(val *ContextAttributeNamesCollection) *NullableContextAttributeNamesCollection { + return &NullableContextAttributeNamesCollection{value: val, isSet: true} +} + +func (v NullableContextAttributeNamesCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeNamesCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_value.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_value.go new file mode 100644 index 00000000..3b381761 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_value.go @@ -0,0 +1,142 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeValue struct for ContextAttributeValue +type ContextAttributeValue struct { + // A value for a context attribute. + Name interface{} `json:"name"` + // A relative estimate of the number of contexts seen recently that have a matching value for a given attribute. + Weight int32 `json:"weight"` +} + +// NewContextAttributeValue instantiates a new ContextAttributeValue object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeValue(name interface{}, weight int32) *ContextAttributeValue { + this := ContextAttributeValue{} + this.Name = name + this.Weight = weight + return &this +} + +// NewContextAttributeValueWithDefaults instantiates a new ContextAttributeValue object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeValueWithDefaults() *ContextAttributeValue { + this := ContextAttributeValue{} + return &this +} + +// GetName returns the Name field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *ContextAttributeValue) GetName() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ContextAttributeValue) GetNameOk() (*interface{}, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ContextAttributeValue) SetName(v interface{}) { + o.Name = v +} + +// GetWeight returns the Weight field value +func (o *ContextAttributeValue) GetWeight() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Weight +} + +// GetWeightOk returns a tuple with the Weight field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeValue) GetWeightOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Weight, true +} + +// SetWeight sets field value +func (o *ContextAttributeValue) SetWeight(v int32) { + o.Weight = v +} + +func (o ContextAttributeValue) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["weight"] = o.Weight + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeValue struct { + value *ContextAttributeValue + isSet bool +} + +func (v NullableContextAttributeValue) Get() *ContextAttributeValue { + return v.value +} + +func (v *NullableContextAttributeValue) Set(val *ContextAttributeValue) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeValue) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeValue) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeValue(val *ContextAttributeValue) *NullableContextAttributeValue { + return &NullableContextAttributeValue{value: val, isSet: true} +} + +func (v NullableContextAttributeValue) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeValue) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values.go new file mode 100644 index 00000000..22b345ef --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeValues struct for ContextAttributeValues +type ContextAttributeValues struct { + // The kind associated with this collection of context attribute values. + Kind string `json:"kind"` + // A collection of context attribute values. + Values []ContextAttributeValue `json:"values"` +} + +// NewContextAttributeValues instantiates a new ContextAttributeValues object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeValues(kind string, values []ContextAttributeValue) *ContextAttributeValues { + this := ContextAttributeValues{} + this.Kind = kind + this.Values = values + return &this +} + +// NewContextAttributeValuesWithDefaults instantiates a new ContextAttributeValues object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeValuesWithDefaults() *ContextAttributeValues { + this := ContextAttributeValues{} + return &this +} + +// GetKind returns the Kind field value +func (o *ContextAttributeValues) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeValues) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ContextAttributeValues) SetKind(v string) { + o.Kind = v +} + +// GetValues returns the Values field value +func (o *ContextAttributeValues) GetValues() []ContextAttributeValue { + if o == nil { + var ret []ContextAttributeValue + return ret + } + + return o.Values +} + +// GetValuesOk returns a tuple with the Values field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeValues) GetValuesOk() ([]ContextAttributeValue, bool) { + if o == nil { + return nil, false + } + return o.Values, true +} + +// SetValues sets field value +func (o *ContextAttributeValues) SetValues(v []ContextAttributeValue) { + o.Values = v +} + +func (o ContextAttributeValues) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["values"] = o.Values + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeValues struct { + value *ContextAttributeValues + isSet bool +} + +func (v NullableContextAttributeValues) Get() *ContextAttributeValues { + return v.value +} + +func (v *NullableContextAttributeValues) Set(val *ContextAttributeValues) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeValues) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeValues) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeValues(val *ContextAttributeValues) *NullableContextAttributeValues { + return &NullableContextAttributeValues{value: val, isSet: true} +} + +func (v NullableContextAttributeValues) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeValues) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values_collection.go new file mode 100644 index 00000000..9496869f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_attribute_values_collection.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextAttributeValuesCollection struct for ContextAttributeValuesCollection +type ContextAttributeValuesCollection struct { + // A collection of context attribute value data grouped by kind. + Items []ContextAttributeValues `json:"items"` +} + +// NewContextAttributeValuesCollection instantiates a new ContextAttributeValuesCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextAttributeValuesCollection(items []ContextAttributeValues) *ContextAttributeValuesCollection { + this := ContextAttributeValuesCollection{} + this.Items = items + return &this +} + +// NewContextAttributeValuesCollectionWithDefaults instantiates a new ContextAttributeValuesCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextAttributeValuesCollectionWithDefaults() *ContextAttributeValuesCollection { + this := ContextAttributeValuesCollection{} + return &this +} + +// GetItems returns the Items field value +func (o *ContextAttributeValuesCollection) GetItems() []ContextAttributeValues { + if o == nil { + var ret []ContextAttributeValues + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextAttributeValuesCollection) GetItemsOk() ([]ContextAttributeValues, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextAttributeValuesCollection) SetItems(v []ContextAttributeValues) { + o.Items = v +} + +func (o ContextAttributeValuesCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableContextAttributeValuesCollection struct { + value *ContextAttributeValuesCollection + isSet bool +} + +func (v NullableContextAttributeValuesCollection) Get() *ContextAttributeValuesCollection { + return v.value +} + +func (v *NullableContextAttributeValuesCollection) Set(val *ContextAttributeValuesCollection) { + v.value = val + v.isSet = true +} + +func (v NullableContextAttributeValuesCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableContextAttributeValuesCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextAttributeValuesCollection(val *ContextAttributeValuesCollection) *NullableContextAttributeValuesCollection { + return &NullableContextAttributeValuesCollection{value: val, isSet: true} +} + +func (v NullableContextAttributeValuesCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextAttributeValuesCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation.go new file mode 100644 index 00000000..d06b93d3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation.go @@ -0,0 +1,238 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceEvaluation struct for ContextInstanceEvaluation +type ContextInstanceEvaluation struct { + // Name of the flag. + Name string `json:"name"` + // Key of the flag. + Key string `json:"key"` + // The value of the flag variation that the context receives. If there is no defined default rule, this is null. + Value interface{} `json:"_value"` + Reason *ContextInstanceEvaluationReason `json:"reason,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewContextInstanceEvaluation instantiates a new ContextInstanceEvaluation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceEvaluation(name string, key string, value interface{}, links map[string]Link) *ContextInstanceEvaluation { + this := ContextInstanceEvaluation{} + this.Name = name + this.Key = key + this.Value = value + this.Links = links + return &this +} + +// NewContextInstanceEvaluationWithDefaults instantiates a new ContextInstanceEvaluation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceEvaluationWithDefaults() *ContextInstanceEvaluation { + this := ContextInstanceEvaluation{} + return &this +} + +// GetName returns the Name field value +func (o *ContextInstanceEvaluation) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluation) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ContextInstanceEvaluation) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *ContextInstanceEvaluation) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluation) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ContextInstanceEvaluation) SetKey(v string) { + o.Key = v +} + +// GetValue returns the Value field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *ContextInstanceEvaluation) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ContextInstanceEvaluation) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *ContextInstanceEvaluation) SetValue(v interface{}) { + o.Value = v +} + +// GetReason returns the Reason field value if set, zero value otherwise. +func (o *ContextInstanceEvaluation) GetReason() ContextInstanceEvaluationReason { + if o == nil || o.Reason == nil { + var ret ContextInstanceEvaluationReason + return ret + } + return *o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluation) GetReasonOk() (*ContextInstanceEvaluationReason, bool) { + if o == nil || o.Reason == nil { + return nil, false + } + return o.Reason, true +} + +// HasReason returns a boolean if a field has been set. +func (o *ContextInstanceEvaluation) HasReason() bool { + if o != nil && o.Reason != nil { + return true + } + + return false +} + +// SetReason gets a reference to the given ContextInstanceEvaluationReason and assigns it to the Reason field. +func (o *ContextInstanceEvaluation) SetReason(v ContextInstanceEvaluationReason) { + o.Reason = &v +} + +// GetLinks returns the Links field value +func (o *ContextInstanceEvaluation) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluation) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ContextInstanceEvaluation) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ContextInstanceEvaluation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.Value != nil { + toSerialize["_value"] = o.Value + } + if o.Reason != nil { + toSerialize["reason"] = o.Reason + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceEvaluation struct { + value *ContextInstanceEvaluation + isSet bool +} + +func (v NullableContextInstanceEvaluation) Get() *ContextInstanceEvaluation { + return v.value +} + +func (v *NullableContextInstanceEvaluation) Set(val *ContextInstanceEvaluation) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceEvaluation) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceEvaluation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceEvaluation(val *ContextInstanceEvaluation) *NullableContextInstanceEvaluation { + return &NullableContextInstanceEvaluation{value: val, isSet: true} +} + +func (v NullableContextInstanceEvaluation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceEvaluation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation_reason.go new file mode 100644 index 00000000..a5311dd0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluation_reason.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceEvaluationReason struct for ContextInstanceEvaluationReason +type ContextInstanceEvaluationReason struct { + // Describes the general reason that LaunchDarkly selected this variation. + Kind string `json:"kind"` + // The positional index of the matching rule if the kind is 'RULE_MATCH'. The index is 0-based. + RuleIndex *int32 `json:"ruleIndex,omitempty"` + // The unique identifier of the matching rule if the kind is 'RULE_MATCH'. + RuleID *string `json:"ruleID,omitempty"` + // The key of the flag that failed if the kind is 'PREREQUISITE_FAILED'. + PrerequisiteKey *string `json:"prerequisiteKey,omitempty"` + // Indicates whether the context was evaluated as part of an experiment. + InExperiment *bool `json:"inExperiment,omitempty"` + // The specific error type if the kind is 'ERROR'. + ErrorKind *string `json:"errorKind,omitempty"` +} + +// NewContextInstanceEvaluationReason instantiates a new ContextInstanceEvaluationReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceEvaluationReason(kind string) *ContextInstanceEvaluationReason { + this := ContextInstanceEvaluationReason{} + this.Kind = kind + return &this +} + +// NewContextInstanceEvaluationReasonWithDefaults instantiates a new ContextInstanceEvaluationReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceEvaluationReasonWithDefaults() *ContextInstanceEvaluationReason { + this := ContextInstanceEvaluationReason{} + return &this +} + +// GetKind returns the Kind field value +func (o *ContextInstanceEvaluationReason) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ContextInstanceEvaluationReason) SetKind(v string) { + o.Kind = v +} + +// GetRuleIndex returns the RuleIndex field value if set, zero value otherwise. +func (o *ContextInstanceEvaluationReason) GetRuleIndex() int32 { + if o == nil || o.RuleIndex == nil { + var ret int32 + return ret + } + return *o.RuleIndex +} + +// GetRuleIndexOk returns a tuple with the RuleIndex field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetRuleIndexOk() (*int32, bool) { + if o == nil || o.RuleIndex == nil { + return nil, false + } + return o.RuleIndex, true +} + +// HasRuleIndex returns a boolean if a field has been set. +func (o *ContextInstanceEvaluationReason) HasRuleIndex() bool { + if o != nil && o.RuleIndex != nil { + return true + } + + return false +} + +// SetRuleIndex gets a reference to the given int32 and assigns it to the RuleIndex field. +func (o *ContextInstanceEvaluationReason) SetRuleIndex(v int32) { + o.RuleIndex = &v +} + +// GetRuleID returns the RuleID field value if set, zero value otherwise. +func (o *ContextInstanceEvaluationReason) GetRuleID() string { + if o == nil || o.RuleID == nil { + var ret string + return ret + } + return *o.RuleID +} + +// GetRuleIDOk returns a tuple with the RuleID field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetRuleIDOk() (*string, bool) { + if o == nil || o.RuleID == nil { + return nil, false + } + return o.RuleID, true +} + +// HasRuleID returns a boolean if a field has been set. +func (o *ContextInstanceEvaluationReason) HasRuleID() bool { + if o != nil && o.RuleID != nil { + return true + } + + return false +} + +// SetRuleID gets a reference to the given string and assigns it to the RuleID field. +func (o *ContextInstanceEvaluationReason) SetRuleID(v string) { + o.RuleID = &v +} + +// GetPrerequisiteKey returns the PrerequisiteKey field value if set, zero value otherwise. +func (o *ContextInstanceEvaluationReason) GetPrerequisiteKey() string { + if o == nil || o.PrerequisiteKey == nil { + var ret string + return ret + } + return *o.PrerequisiteKey +} + +// GetPrerequisiteKeyOk returns a tuple with the PrerequisiteKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetPrerequisiteKeyOk() (*string, bool) { + if o == nil || o.PrerequisiteKey == nil { + return nil, false + } + return o.PrerequisiteKey, true +} + +// HasPrerequisiteKey returns a boolean if a field has been set. +func (o *ContextInstanceEvaluationReason) HasPrerequisiteKey() bool { + if o != nil && o.PrerequisiteKey != nil { + return true + } + + return false +} + +// SetPrerequisiteKey gets a reference to the given string and assigns it to the PrerequisiteKey field. +func (o *ContextInstanceEvaluationReason) SetPrerequisiteKey(v string) { + o.PrerequisiteKey = &v +} + +// GetInExperiment returns the InExperiment field value if set, zero value otherwise. +func (o *ContextInstanceEvaluationReason) GetInExperiment() bool { + if o == nil || o.InExperiment == nil { + var ret bool + return ret + } + return *o.InExperiment +} + +// GetInExperimentOk returns a tuple with the InExperiment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetInExperimentOk() (*bool, bool) { + if o == nil || o.InExperiment == nil { + return nil, false + } + return o.InExperiment, true +} + +// HasInExperiment returns a boolean if a field has been set. +func (o *ContextInstanceEvaluationReason) HasInExperiment() bool { + if o != nil && o.InExperiment != nil { + return true + } + + return false +} + +// SetInExperiment gets a reference to the given bool and assigns it to the InExperiment field. +func (o *ContextInstanceEvaluationReason) SetInExperiment(v bool) { + o.InExperiment = &v +} + +// GetErrorKind returns the ErrorKind field value if set, zero value otherwise. +func (o *ContextInstanceEvaluationReason) GetErrorKind() string { + if o == nil || o.ErrorKind == nil { + var ret string + return ret + } + return *o.ErrorKind +} + +// GetErrorKindOk returns a tuple with the ErrorKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluationReason) GetErrorKindOk() (*string, bool) { + if o == nil || o.ErrorKind == nil { + return nil, false + } + return o.ErrorKind, true +} + +// HasErrorKind returns a boolean if a field has been set. +func (o *ContextInstanceEvaluationReason) HasErrorKind() bool { + if o != nil && o.ErrorKind != nil { + return true + } + + return false +} + +// SetErrorKind gets a reference to the given string and assigns it to the ErrorKind field. +func (o *ContextInstanceEvaluationReason) SetErrorKind(v string) { + o.ErrorKind = &v +} + +func (o ContextInstanceEvaluationReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if o.RuleIndex != nil { + toSerialize["ruleIndex"] = o.RuleIndex + } + if o.RuleID != nil { + toSerialize["ruleID"] = o.RuleID + } + if o.PrerequisiteKey != nil { + toSerialize["prerequisiteKey"] = o.PrerequisiteKey + } + if o.InExperiment != nil { + toSerialize["inExperiment"] = o.InExperiment + } + if o.ErrorKind != nil { + toSerialize["errorKind"] = o.ErrorKind + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceEvaluationReason struct { + value *ContextInstanceEvaluationReason + isSet bool +} + +func (v NullableContextInstanceEvaluationReason) Get() *ContextInstanceEvaluationReason { + return v.value +} + +func (v *NullableContextInstanceEvaluationReason) Set(val *ContextInstanceEvaluationReason) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceEvaluationReason) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceEvaluationReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceEvaluationReason(val *ContextInstanceEvaluationReason) *NullableContextInstanceEvaluationReason { + return &NullableContextInstanceEvaluationReason{value: val, isSet: true} +} + +func (v NullableContextInstanceEvaluationReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceEvaluationReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluations.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluations.go new file mode 100644 index 00000000..e327b9aa --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_evaluations.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceEvaluations struct for ContextInstanceEvaluations +type ContextInstanceEvaluations struct { + // Details on the flag evaluations for this context instance + Items []ContextInstanceEvaluation `json:"items"` + // The number of flags + TotalCount *int32 `json:"totalCount,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewContextInstanceEvaluations instantiates a new ContextInstanceEvaluations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceEvaluations(items []ContextInstanceEvaluation, links map[string]Link) *ContextInstanceEvaluations { + this := ContextInstanceEvaluations{} + this.Items = items + this.Links = links + return &this +} + +// NewContextInstanceEvaluationsWithDefaults instantiates a new ContextInstanceEvaluations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceEvaluationsWithDefaults() *ContextInstanceEvaluations { + this := ContextInstanceEvaluations{} + return &this +} + +// GetItems returns the Items field value +func (o *ContextInstanceEvaluations) GetItems() []ContextInstanceEvaluation { + if o == nil { + var ret []ContextInstanceEvaluation + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluations) GetItemsOk() ([]ContextInstanceEvaluation, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextInstanceEvaluations) SetItems(v []ContextInstanceEvaluation) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ContextInstanceEvaluations) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluations) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ContextInstanceEvaluations) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ContextInstanceEvaluations) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetLinks returns the Links field value +func (o *ContextInstanceEvaluations) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceEvaluations) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ContextInstanceEvaluations) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ContextInstanceEvaluations) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceEvaluations struct { + value *ContextInstanceEvaluations + isSet bool +} + +func (v NullableContextInstanceEvaluations) Get() *ContextInstanceEvaluations { + return v.value +} + +func (v *NullableContextInstanceEvaluations) Set(val *ContextInstanceEvaluations) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceEvaluations) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceEvaluations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceEvaluations(val *ContextInstanceEvaluations) *NullableContextInstanceEvaluations { + return &NullableContextInstanceEvaluations{value: val, isSet: true} +} + +func (v NullableContextInstanceEvaluations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceEvaluations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_record.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_record.go new file mode 100644 index 00000000..139ae46c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_record.go @@ -0,0 +1,327 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// ContextInstanceRecord struct for ContextInstanceRecord +type ContextInstanceRecord struct { + // Timestamp of the last time an evaluation occurred for this context instance + LastSeen *time.Time `json:"lastSeen,omitempty"` + // The context instance ID + Id string `json:"id"` + // An identifier representing the application where the LaunchDarkly SDK is running + ApplicationId *string `json:"applicationId,omitempty"` + // A list of the context kinds this context was associated with that the SDK removed because they were marked as anonymous at flag evaluation + AnonymousKinds []string `json:"anonymousKinds,omitempty"` + // The context, including its kind and attributes + Context interface{} `json:"context"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + Access *Access `json:"_access,omitempty"` +} + +// NewContextInstanceRecord instantiates a new ContextInstanceRecord object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceRecord(id string, context interface{}) *ContextInstanceRecord { + this := ContextInstanceRecord{} + this.Id = id + this.Context = context + return &this +} + +// NewContextInstanceRecordWithDefaults instantiates a new ContextInstanceRecord object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceRecordWithDefaults() *ContextInstanceRecord { + this := ContextInstanceRecord{} + return &this +} + +// GetLastSeen returns the LastSeen field value if set, zero value otherwise. +func (o *ContextInstanceRecord) GetLastSeen() time.Time { + if o == nil || o.LastSeen == nil { + var ret time.Time + return ret + } + return *o.LastSeen +} + +// GetLastSeenOk returns a tuple with the LastSeen field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetLastSeenOk() (*time.Time, bool) { + if o == nil || o.LastSeen == nil { + return nil, false + } + return o.LastSeen, true +} + +// HasLastSeen returns a boolean if a field has been set. +func (o *ContextInstanceRecord) HasLastSeen() bool { + if o != nil && o.LastSeen != nil { + return true + } + + return false +} + +// SetLastSeen gets a reference to the given time.Time and assigns it to the LastSeen field. +func (o *ContextInstanceRecord) SetLastSeen(v time.Time) { + o.LastSeen = &v +} + +// GetId returns the Id field value +func (o *ContextInstanceRecord) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ContextInstanceRecord) SetId(v string) { + o.Id = v +} + +// GetApplicationId returns the ApplicationId field value if set, zero value otherwise. +func (o *ContextInstanceRecord) GetApplicationId() string { + if o == nil || o.ApplicationId == nil { + var ret string + return ret + } + return *o.ApplicationId +} + +// GetApplicationIdOk returns a tuple with the ApplicationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetApplicationIdOk() (*string, bool) { + if o == nil || o.ApplicationId == nil { + return nil, false + } + return o.ApplicationId, true +} + +// HasApplicationId returns a boolean if a field has been set. +func (o *ContextInstanceRecord) HasApplicationId() bool { + if o != nil && o.ApplicationId != nil { + return true + } + + return false +} + +// SetApplicationId gets a reference to the given string and assigns it to the ApplicationId field. +func (o *ContextInstanceRecord) SetApplicationId(v string) { + o.ApplicationId = &v +} + +// GetAnonymousKinds returns the AnonymousKinds field value if set, zero value otherwise. +func (o *ContextInstanceRecord) GetAnonymousKinds() []string { + if o == nil || o.AnonymousKinds == nil { + var ret []string + return ret + } + return o.AnonymousKinds +} + +// GetAnonymousKindsOk returns a tuple with the AnonymousKinds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetAnonymousKindsOk() ([]string, bool) { + if o == nil || o.AnonymousKinds == nil { + return nil, false + } + return o.AnonymousKinds, true +} + +// HasAnonymousKinds returns a boolean if a field has been set. +func (o *ContextInstanceRecord) HasAnonymousKinds() bool { + if o != nil && o.AnonymousKinds != nil { + return true + } + + return false +} + +// SetAnonymousKinds gets a reference to the given []string and assigns it to the AnonymousKinds field. +func (o *ContextInstanceRecord) SetAnonymousKinds(v []string) { + o.AnonymousKinds = v +} + +// GetContext returns the Context field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *ContextInstanceRecord) GetContext() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Context +} + +// GetContextOk returns a tuple with the Context field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ContextInstanceRecord) GetContextOk() (*interface{}, bool) { + if o == nil || o.Context == nil { + return nil, false + } + return &o.Context, true +} + +// SetContext sets field value +func (o *ContextInstanceRecord) SetContext(v interface{}) { + o.Context = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ContextInstanceRecord) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ContextInstanceRecord) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ContextInstanceRecord) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ContextInstanceRecord) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceRecord) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ContextInstanceRecord) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ContextInstanceRecord) SetAccess(v Access) { + o.Access = &v +} + +func (o ContextInstanceRecord) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.LastSeen != nil { + toSerialize["lastSeen"] = o.LastSeen + } + if true { + toSerialize["id"] = o.Id + } + if o.ApplicationId != nil { + toSerialize["applicationId"] = o.ApplicationId + } + if o.AnonymousKinds != nil { + toSerialize["anonymousKinds"] = o.AnonymousKinds + } + if o.Context != nil { + toSerialize["context"] = o.Context + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceRecord struct { + value *ContextInstanceRecord + isSet bool +} + +func (v NullableContextInstanceRecord) Get() *ContextInstanceRecord { + return v.value +} + +func (v *NullableContextInstanceRecord) Set(val *ContextInstanceRecord) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceRecord) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceRecord) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceRecord(val *ContextInstanceRecord) *NullableContextInstanceRecord { + return &NullableContextInstanceRecord{value: val, isSet: true} +} + +func (v NullableContextInstanceRecord) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceRecord) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_search.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_search.go new file mode 100644 index 00000000..2a7a7f37 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_search.go @@ -0,0 +1,228 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceSearch struct for ContextInstanceSearch +type ContextInstanceSearch struct { + // A collection of context instance filters + Filter *string `json:"filter,omitempty"` + // Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying ts for this value, or descending order by specifying -ts. + Sort *string `json:"sort,omitempty"` + // Specifies the maximum number of items in the collection to return (max: 50, default: 20) + Limit *int32 `json:"limit,omitempty"` + // Limits results to context instances with sort values after the value specified. You can use this for pagination, however, we recommend using the next link instead, because this value is an obfuscated string. + ContinuationToken *string `json:"continuationToken,omitempty"` +} + +// NewContextInstanceSearch instantiates a new ContextInstanceSearch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceSearch() *ContextInstanceSearch { + this := ContextInstanceSearch{} + return &this +} + +// NewContextInstanceSearchWithDefaults instantiates a new ContextInstanceSearch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceSearchWithDefaults() *ContextInstanceSearch { + this := ContextInstanceSearch{} + return &this +} + +// GetFilter returns the Filter field value if set, zero value otherwise. +func (o *ContextInstanceSearch) GetFilter() string { + if o == nil || o.Filter == nil { + var ret string + return ret + } + return *o.Filter +} + +// GetFilterOk returns a tuple with the Filter field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceSearch) GetFilterOk() (*string, bool) { + if o == nil || o.Filter == nil { + return nil, false + } + return o.Filter, true +} + +// HasFilter returns a boolean if a field has been set. +func (o *ContextInstanceSearch) HasFilter() bool { + if o != nil && o.Filter != nil { + return true + } + + return false +} + +// SetFilter gets a reference to the given string and assigns it to the Filter field. +func (o *ContextInstanceSearch) SetFilter(v string) { + o.Filter = &v +} + +// GetSort returns the Sort field value if set, zero value otherwise. +func (o *ContextInstanceSearch) GetSort() string { + if o == nil || o.Sort == nil { + var ret string + return ret + } + return *o.Sort +} + +// GetSortOk returns a tuple with the Sort field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceSearch) GetSortOk() (*string, bool) { + if o == nil || o.Sort == nil { + return nil, false + } + return o.Sort, true +} + +// HasSort returns a boolean if a field has been set. +func (o *ContextInstanceSearch) HasSort() bool { + if o != nil && o.Sort != nil { + return true + } + + return false +} + +// SetSort gets a reference to the given string and assigns it to the Sort field. +func (o *ContextInstanceSearch) SetSort(v string) { + o.Sort = &v +} + +// GetLimit returns the Limit field value if set, zero value otherwise. +func (o *ContextInstanceSearch) GetLimit() int32 { + if o == nil || o.Limit == nil { + var ret int32 + return ret + } + return *o.Limit +} + +// GetLimitOk returns a tuple with the Limit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceSearch) GetLimitOk() (*int32, bool) { + if o == nil || o.Limit == nil { + return nil, false + } + return o.Limit, true +} + +// HasLimit returns a boolean if a field has been set. +func (o *ContextInstanceSearch) HasLimit() bool { + if o != nil && o.Limit != nil { + return true + } + + return false +} + +// SetLimit gets a reference to the given int32 and assigns it to the Limit field. +func (o *ContextInstanceSearch) SetLimit(v int32) { + o.Limit = &v +} + +// GetContinuationToken returns the ContinuationToken field value if set, zero value otherwise. +func (o *ContextInstanceSearch) GetContinuationToken() string { + if o == nil || o.ContinuationToken == nil { + var ret string + return ret + } + return *o.ContinuationToken +} + +// GetContinuationTokenOk returns a tuple with the ContinuationToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstanceSearch) GetContinuationTokenOk() (*string, bool) { + if o == nil || o.ContinuationToken == nil { + return nil, false + } + return o.ContinuationToken, true +} + +// HasContinuationToken returns a boolean if a field has been set. +func (o *ContextInstanceSearch) HasContinuationToken() bool { + if o != nil && o.ContinuationToken != nil { + return true + } + + return false +} + +// SetContinuationToken gets a reference to the given string and assigns it to the ContinuationToken field. +func (o *ContextInstanceSearch) SetContinuationToken(v string) { + o.ContinuationToken = &v +} + +func (o ContextInstanceSearch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Filter != nil { + toSerialize["filter"] = o.Filter + } + if o.Sort != nil { + toSerialize["sort"] = o.Sort + } + if o.Limit != nil { + toSerialize["limit"] = o.Limit + } + if o.ContinuationToken != nil { + toSerialize["continuationToken"] = o.ContinuationToken + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceSearch struct { + value *ContextInstanceSearch + isSet bool +} + +func (v NullableContextInstanceSearch) Get() *ContextInstanceSearch { + return v.value +} + +func (v *NullableContextInstanceSearch) Set(val *ContextInstanceSearch) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceSearch) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceSearch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceSearch(val *ContextInstanceSearch) *NullableContextInstanceSearch { + return &NullableContextInstanceSearch{value: val, isSet: true} +} + +func (v NullableContextInstanceSearch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceSearch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_membership.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_membership.go new file mode 100644 index 00000000..f61fbd2b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_membership.go @@ -0,0 +1,350 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceSegmentMembership struct for ContextInstanceSegmentMembership +type ContextInstanceSegmentMembership struct { + // A human-friendly name for the segment + Name string `json:"name"` + // A unique key used to reference the segment + Key string `json:"key"` + // A description of the segment's purpose + Description string `json:"description"` + // Whether this is an unbounded segment. Unbounded segments, also called big segments, may be list-based segments with more than 15,000 entries, or synced segments. + Unbounded bool `json:"unbounded"` + // If the segment is a synced segment, the name of the external source + External string `json:"external"` + // Whether the context is a member of this segment, either by explicit inclusion or by rule matching + IsMember bool `json:"isMember"` + // Whether the context is explicitly included in this segment + IsIndividuallyTargeted bool `json:"isIndividuallyTargeted"` + // Whether the context is captured by this segment's rules. The value of this field is undefined if the context is also explicitly included (isIndividuallyTargeted is true). + IsRuleTargeted bool `json:"isRuleTargeted"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewContextInstanceSegmentMembership instantiates a new ContextInstanceSegmentMembership object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceSegmentMembership(name string, key string, description string, unbounded bool, external string, isMember bool, isIndividuallyTargeted bool, isRuleTargeted bool, links map[string]Link) *ContextInstanceSegmentMembership { + this := ContextInstanceSegmentMembership{} + this.Name = name + this.Key = key + this.Description = description + this.Unbounded = unbounded + this.External = external + this.IsMember = isMember + this.IsIndividuallyTargeted = isIndividuallyTargeted + this.IsRuleTargeted = isRuleTargeted + this.Links = links + return &this +} + +// NewContextInstanceSegmentMembershipWithDefaults instantiates a new ContextInstanceSegmentMembership object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceSegmentMembershipWithDefaults() *ContextInstanceSegmentMembership { + this := ContextInstanceSegmentMembership{} + return &this +} + +// GetName returns the Name field value +func (o *ContextInstanceSegmentMembership) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ContextInstanceSegmentMembership) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *ContextInstanceSegmentMembership) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ContextInstanceSegmentMembership) SetKey(v string) { + o.Key = v +} + +// GetDescription returns the Description field value +func (o *ContextInstanceSegmentMembership) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *ContextInstanceSegmentMembership) SetDescription(v string) { + o.Description = v +} + +// GetUnbounded returns the Unbounded field value +func (o *ContextInstanceSegmentMembership) GetUnbounded() bool { + if o == nil { + var ret bool + return ret + } + + return o.Unbounded +} + +// GetUnboundedOk returns a tuple with the Unbounded field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetUnboundedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Unbounded, true +} + +// SetUnbounded sets field value +func (o *ContextInstanceSegmentMembership) SetUnbounded(v bool) { + o.Unbounded = v +} + +// GetExternal returns the External field value +func (o *ContextInstanceSegmentMembership) GetExternal() string { + if o == nil { + var ret string + return ret + } + + return o.External +} + +// GetExternalOk returns a tuple with the External field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetExternalOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.External, true +} + +// SetExternal sets field value +func (o *ContextInstanceSegmentMembership) SetExternal(v string) { + o.External = v +} + +// GetIsMember returns the IsMember field value +func (o *ContextInstanceSegmentMembership) GetIsMember() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsMember +} + +// GetIsMemberOk returns a tuple with the IsMember field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetIsMemberOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsMember, true +} + +// SetIsMember sets field value +func (o *ContextInstanceSegmentMembership) SetIsMember(v bool) { + o.IsMember = v +} + +// GetIsIndividuallyTargeted returns the IsIndividuallyTargeted field value +func (o *ContextInstanceSegmentMembership) GetIsIndividuallyTargeted() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsIndividuallyTargeted +} + +// GetIsIndividuallyTargetedOk returns a tuple with the IsIndividuallyTargeted field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetIsIndividuallyTargetedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsIndividuallyTargeted, true +} + +// SetIsIndividuallyTargeted sets field value +func (o *ContextInstanceSegmentMembership) SetIsIndividuallyTargeted(v bool) { + o.IsIndividuallyTargeted = v +} + +// GetIsRuleTargeted returns the IsRuleTargeted field value +func (o *ContextInstanceSegmentMembership) GetIsRuleTargeted() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsRuleTargeted +} + +// GetIsRuleTargetedOk returns a tuple with the IsRuleTargeted field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetIsRuleTargetedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsRuleTargeted, true +} + +// SetIsRuleTargeted sets field value +func (o *ContextInstanceSegmentMembership) SetIsRuleTargeted(v bool) { + o.IsRuleTargeted = v +} + +// GetLinks returns the Links field value +func (o *ContextInstanceSegmentMembership) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMembership) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ContextInstanceSegmentMembership) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ContextInstanceSegmentMembership) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["unbounded"] = o.Unbounded + } + if true { + toSerialize["external"] = o.External + } + if true { + toSerialize["isMember"] = o.IsMember + } + if true { + toSerialize["isIndividuallyTargeted"] = o.IsIndividuallyTargeted + } + if true { + toSerialize["isRuleTargeted"] = o.IsRuleTargeted + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceSegmentMembership struct { + value *ContextInstanceSegmentMembership + isSet bool +} + +func (v NullableContextInstanceSegmentMembership) Get() *ContextInstanceSegmentMembership { + return v.value +} + +func (v *NullableContextInstanceSegmentMembership) Set(val *ContextInstanceSegmentMembership) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceSegmentMembership) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceSegmentMembership) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceSegmentMembership(val *ContextInstanceSegmentMembership) *NullableContextInstanceSegmentMembership { + return &NullableContextInstanceSegmentMembership{value: val, isSet: true} +} + +func (v NullableContextInstanceSegmentMembership) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceSegmentMembership) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_memberships.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_memberships.go new file mode 100644 index 00000000..a5eeec7b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instance_segment_memberships.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstanceSegmentMemberships struct for ContextInstanceSegmentMemberships +type ContextInstanceSegmentMemberships struct { + Items []ContextInstanceSegmentMembership `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewContextInstanceSegmentMemberships instantiates a new ContextInstanceSegmentMemberships object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstanceSegmentMemberships(items []ContextInstanceSegmentMembership, links map[string]Link) *ContextInstanceSegmentMemberships { + this := ContextInstanceSegmentMemberships{} + this.Items = items + this.Links = links + return &this +} + +// NewContextInstanceSegmentMembershipsWithDefaults instantiates a new ContextInstanceSegmentMemberships object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstanceSegmentMembershipsWithDefaults() *ContextInstanceSegmentMemberships { + this := ContextInstanceSegmentMemberships{} + return &this +} + +// GetItems returns the Items field value +func (o *ContextInstanceSegmentMemberships) GetItems() []ContextInstanceSegmentMembership { + if o == nil { + var ret []ContextInstanceSegmentMembership + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMemberships) GetItemsOk() ([]ContextInstanceSegmentMembership, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextInstanceSegmentMemberships) SetItems(v []ContextInstanceSegmentMembership) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *ContextInstanceSegmentMemberships) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ContextInstanceSegmentMemberships) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ContextInstanceSegmentMemberships) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ContextInstanceSegmentMemberships) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextInstanceSegmentMemberships struct { + value *ContextInstanceSegmentMemberships + isSet bool +} + +func (v NullableContextInstanceSegmentMemberships) Get() *ContextInstanceSegmentMemberships { + return v.value +} + +func (v *NullableContextInstanceSegmentMemberships) Set(val *ContextInstanceSegmentMemberships) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstanceSegmentMemberships) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstanceSegmentMemberships) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstanceSegmentMemberships(val *ContextInstanceSegmentMemberships) *NullableContextInstanceSegmentMemberships { + return &NullableContextInstanceSegmentMemberships{value: val, isSet: true} +} + +func (v NullableContextInstanceSegmentMemberships) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstanceSegmentMemberships) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instances.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instances.go new file mode 100644 index 00000000..04c8ff1b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_instances.go @@ -0,0 +1,251 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextInstances struct for ContextInstances +type ContextInstances struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The number of unique context instances + TotalCount *int32 `json:"totalCount,omitempty"` + // The environment ID + EnvironmentId string `json:"_environmentId"` + // An obfuscated string that references the last context instance on the previous page of results. You can use this for pagination, however, we recommend using the next link instead. + ContinuationToken *string `json:"continuationToken,omitempty"` + // A collection of context instances. Can include multiple versions of context instances that have the same id, but different applicationIds. + Items []ContextInstanceRecord `json:"items"` +} + +// NewContextInstances instantiates a new ContextInstances object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextInstances(environmentId string, items []ContextInstanceRecord) *ContextInstances { + this := ContextInstances{} + this.EnvironmentId = environmentId + this.Items = items + return &this +} + +// NewContextInstancesWithDefaults instantiates a new ContextInstances object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextInstancesWithDefaults() *ContextInstances { + this := ContextInstances{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ContextInstances) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstances) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ContextInstances) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ContextInstances) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ContextInstances) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstances) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ContextInstances) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ContextInstances) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetEnvironmentId returns the EnvironmentId field value +func (o *ContextInstances) GetEnvironmentId() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value +// and a boolean to check if the value has been set. +func (o *ContextInstances) GetEnvironmentIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentId, true +} + +// SetEnvironmentId sets field value +func (o *ContextInstances) SetEnvironmentId(v string) { + o.EnvironmentId = v +} + +// GetContinuationToken returns the ContinuationToken field value if set, zero value otherwise. +func (o *ContextInstances) GetContinuationToken() string { + if o == nil || o.ContinuationToken == nil { + var ret string + return ret + } + return *o.ContinuationToken +} + +// GetContinuationTokenOk returns a tuple with the ContinuationToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextInstances) GetContinuationTokenOk() (*string, bool) { + if o == nil || o.ContinuationToken == nil { + return nil, false + } + return o.ContinuationToken, true +} + +// HasContinuationToken returns a boolean if a field has been set. +func (o *ContextInstances) HasContinuationToken() bool { + if o != nil && o.ContinuationToken != nil { + return true + } + + return false +} + +// SetContinuationToken gets a reference to the given string and assigns it to the ContinuationToken field. +func (o *ContextInstances) SetContinuationToken(v string) { + o.ContinuationToken = &v +} + +// GetItems returns the Items field value +func (o *ContextInstances) GetItems() []ContextInstanceRecord { + if o == nil { + var ret []ContextInstanceRecord + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextInstances) GetItemsOk() ([]ContextInstanceRecord, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextInstances) SetItems(v []ContextInstanceRecord) { + o.Items = v +} + +func (o ContextInstances) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_environmentId"] = o.EnvironmentId + } + if o.ContinuationToken != nil { + toSerialize["continuationToken"] = o.ContinuationToken + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableContextInstances struct { + value *ContextInstances + isSet bool +} + +func (v NullableContextInstances) Get() *ContextInstances { + return v.value +} + +func (v *NullableContextInstances) Set(val *ContextInstances) { + v.value = val + v.isSet = true +} + +func (v NullableContextInstances) IsSet() bool { + return v.isSet +} + +func (v *NullableContextInstances) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextInstances(val *ContextInstances) *NullableContextInstances { + return &NullableContextInstances{value: val, isSet: true} +} + +func (v NullableContextInstances) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextInstances) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kind_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kind_rep.go new file mode 100644 index 00000000..580c1b3c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kind_rep.go @@ -0,0 +1,434 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextKindRep struct for ContextKindRep +type ContextKindRep struct { + // The context kind key + Key string `json:"key"` + // The context kind name + Name string `json:"name"` + // The context kind description + Description string `json:"description"` + // The context kind version + Version int32 `json:"version"` + CreationDate int64 `json:"creationDate"` + LastModified int64 `json:"lastModified"` + LastSeen *int64 `json:"lastSeen,omitempty"` + CreatedFrom string `json:"createdFrom"` + // Alias for archived. + HideInTargeting *bool `json:"hideInTargeting,omitempty"` + // Whether the context kind is archived. Archived context kinds are unavailable for targeting. + Archived *bool `json:"archived,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewContextKindRep instantiates a new ContextKindRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextKindRep(key string, name string, description string, version int32, creationDate int64, lastModified int64, createdFrom string) *ContextKindRep { + this := ContextKindRep{} + this.Key = key + this.Name = name + this.Description = description + this.Version = version + this.CreationDate = creationDate + this.LastModified = lastModified + this.CreatedFrom = createdFrom + return &this +} + +// NewContextKindRepWithDefaults instantiates a new ContextKindRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextKindRepWithDefaults() *ContextKindRep { + this := ContextKindRep{} + return &this +} + +// GetKey returns the Key field value +func (o *ContextKindRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ContextKindRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *ContextKindRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ContextKindRep) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value +func (o *ContextKindRep) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *ContextKindRep) SetDescription(v string) { + o.Description = v +} + +// GetVersion returns the Version field value +func (o *ContextKindRep) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ContextKindRep) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *ContextKindRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *ContextKindRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value +func (o *ContextKindRep) GetLastModified() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetLastModifiedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModified, true +} + +// SetLastModified sets field value +func (o *ContextKindRep) SetLastModified(v int64) { + o.LastModified = v +} + +// GetLastSeen returns the LastSeen field value if set, zero value otherwise. +func (o *ContextKindRep) GetLastSeen() int64 { + if o == nil || o.LastSeen == nil { + var ret int64 + return ret + } + return *o.LastSeen +} + +// GetLastSeenOk returns a tuple with the LastSeen field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetLastSeenOk() (*int64, bool) { + if o == nil || o.LastSeen == nil { + return nil, false + } + return o.LastSeen, true +} + +// HasLastSeen returns a boolean if a field has been set. +func (o *ContextKindRep) HasLastSeen() bool { + if o != nil && o.LastSeen != nil { + return true + } + + return false +} + +// SetLastSeen gets a reference to the given int64 and assigns it to the LastSeen field. +func (o *ContextKindRep) SetLastSeen(v int64) { + o.LastSeen = &v +} + +// GetCreatedFrom returns the CreatedFrom field value +func (o *ContextKindRep) GetCreatedFrom() string { + if o == nil { + var ret string + return ret + } + + return o.CreatedFrom +} + +// GetCreatedFromOk returns a tuple with the CreatedFrom field value +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetCreatedFromOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.CreatedFrom, true +} + +// SetCreatedFrom sets field value +func (o *ContextKindRep) SetCreatedFrom(v string) { + o.CreatedFrom = v +} + +// GetHideInTargeting returns the HideInTargeting field value if set, zero value otherwise. +func (o *ContextKindRep) GetHideInTargeting() bool { + if o == nil || o.HideInTargeting == nil { + var ret bool + return ret + } + return *o.HideInTargeting +} + +// GetHideInTargetingOk returns a tuple with the HideInTargeting field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetHideInTargetingOk() (*bool, bool) { + if o == nil || o.HideInTargeting == nil { + return nil, false + } + return o.HideInTargeting, true +} + +// HasHideInTargeting returns a boolean if a field has been set. +func (o *ContextKindRep) HasHideInTargeting() bool { + if o != nil && o.HideInTargeting != nil { + return true + } + + return false +} + +// SetHideInTargeting gets a reference to the given bool and assigns it to the HideInTargeting field. +func (o *ContextKindRep) SetHideInTargeting(v bool) { + o.HideInTargeting = &v +} + +// GetArchived returns the Archived field value if set, zero value otherwise. +func (o *ContextKindRep) GetArchived() bool { + if o == nil || o.Archived == nil { + var ret bool + return ret + } + return *o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetArchivedOk() (*bool, bool) { + if o == nil || o.Archived == nil { + return nil, false + } + return o.Archived, true +} + +// HasArchived returns a boolean if a field has been set. +func (o *ContextKindRep) HasArchived() bool { + if o != nil && o.Archived != nil { + return true + } + + return false +} + +// SetArchived gets a reference to the given bool and assigns it to the Archived field. +func (o *ContextKindRep) SetArchived(v bool) { + o.Archived = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ContextKindRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextKindRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ContextKindRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ContextKindRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ContextKindRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["lastModified"] = o.LastModified + } + if o.LastSeen != nil { + toSerialize["lastSeen"] = o.LastSeen + } + if true { + toSerialize["createdFrom"] = o.CreatedFrom + } + if o.HideInTargeting != nil { + toSerialize["hideInTargeting"] = o.HideInTargeting + } + if o.Archived != nil { + toSerialize["archived"] = o.Archived + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextKindRep struct { + value *ContextKindRep + isSet bool +} + +func (v NullableContextKindRep) Get() *ContextKindRep { + return v.value +} + +func (v *NullableContextKindRep) Set(val *ContextKindRep) { + v.value = val + v.isSet = true +} + +func (v NullableContextKindRep) IsSet() bool { + return v.isSet +} + +func (v *NullableContextKindRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextKindRep(val *ContextKindRep) *NullableContextKindRep { + return &NullableContextKindRep{value: val, isSet: true} +} + +func (v NullableContextKindRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextKindRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kinds_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kinds_collection_rep.go new file mode 100644 index 00000000..fa0c9964 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_kinds_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextKindsCollectionRep struct for ContextKindsCollectionRep +type ContextKindsCollectionRep struct { + // An array of context kinds + Items []ContextKindRep `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewContextKindsCollectionRep instantiates a new ContextKindsCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextKindsCollectionRep(items []ContextKindRep, links map[string]Link) *ContextKindsCollectionRep { + this := ContextKindsCollectionRep{} + this.Items = items + this.Links = links + return &this +} + +// NewContextKindsCollectionRepWithDefaults instantiates a new ContextKindsCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextKindsCollectionRepWithDefaults() *ContextKindsCollectionRep { + this := ContextKindsCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *ContextKindsCollectionRep) GetItems() []ContextKindRep { + if o == nil { + var ret []ContextKindRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ContextKindsCollectionRep) GetItemsOk() ([]ContextKindRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ContextKindsCollectionRep) SetItems(v []ContextKindRep) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *ContextKindsCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ContextKindsCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ContextKindsCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ContextKindsCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableContextKindsCollectionRep struct { + value *ContextKindsCollectionRep + isSet bool +} + +func (v NullableContextKindsCollectionRep) Get() *ContextKindsCollectionRep { + return v.value +} + +func (v *NullableContextKindsCollectionRep) Set(val *ContextKindsCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableContextKindsCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableContextKindsCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextKindsCollectionRep(val *ContextKindsCollectionRep) *NullableContextKindsCollectionRep { + return &NullableContextKindsCollectionRep{value: val, isSet: true} +} + +func (v NullableContextKindsCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextKindsCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_record.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_record.go new file mode 100644 index 00000000..7d3685d4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_record.go @@ -0,0 +1,297 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// ContextRecord struct for ContextRecord +type ContextRecord struct { + // Timestamp of the last time an evaluation occurred for this context + LastSeen *time.Time `json:"lastSeen,omitempty"` + // An identifier representing the application where the LaunchDarkly SDK is running + ApplicationId *string `json:"applicationId,omitempty"` + // The context, including its kind and attributes + Context interface{} `json:"context"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + Access *Access `json:"_access,omitempty"` + // The total number of associated contexts. Associated contexts are contexts that have appeared in the same context instance, that is, they were part of the same flag evaluation. + AssociatedContexts *int32 `json:"associatedContexts,omitempty"` +} + +// NewContextRecord instantiates a new ContextRecord object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextRecord(context interface{}) *ContextRecord { + this := ContextRecord{} + this.Context = context + return &this +} + +// NewContextRecordWithDefaults instantiates a new ContextRecord object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextRecordWithDefaults() *ContextRecord { + this := ContextRecord{} + return &this +} + +// GetLastSeen returns the LastSeen field value if set, zero value otherwise. +func (o *ContextRecord) GetLastSeen() time.Time { + if o == nil || o.LastSeen == nil { + var ret time.Time + return ret + } + return *o.LastSeen +} + +// GetLastSeenOk returns a tuple with the LastSeen field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextRecord) GetLastSeenOk() (*time.Time, bool) { + if o == nil || o.LastSeen == nil { + return nil, false + } + return o.LastSeen, true +} + +// HasLastSeen returns a boolean if a field has been set. +func (o *ContextRecord) HasLastSeen() bool { + if o != nil && o.LastSeen != nil { + return true + } + + return false +} + +// SetLastSeen gets a reference to the given time.Time and assigns it to the LastSeen field. +func (o *ContextRecord) SetLastSeen(v time.Time) { + o.LastSeen = &v +} + +// GetApplicationId returns the ApplicationId field value if set, zero value otherwise. +func (o *ContextRecord) GetApplicationId() string { + if o == nil || o.ApplicationId == nil { + var ret string + return ret + } + return *o.ApplicationId +} + +// GetApplicationIdOk returns a tuple with the ApplicationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextRecord) GetApplicationIdOk() (*string, bool) { + if o == nil || o.ApplicationId == nil { + return nil, false + } + return o.ApplicationId, true +} + +// HasApplicationId returns a boolean if a field has been set. +func (o *ContextRecord) HasApplicationId() bool { + if o != nil && o.ApplicationId != nil { + return true + } + + return false +} + +// SetApplicationId gets a reference to the given string and assigns it to the ApplicationId field. +func (o *ContextRecord) SetApplicationId(v string) { + o.ApplicationId = &v +} + +// GetContext returns the Context field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *ContextRecord) GetContext() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Context +} + +// GetContextOk returns a tuple with the Context field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ContextRecord) GetContextOk() (*interface{}, bool) { + if o == nil || o.Context == nil { + return nil, false + } + return &o.Context, true +} + +// SetContext sets field value +func (o *ContextRecord) SetContext(v interface{}) { + o.Context = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ContextRecord) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextRecord) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ContextRecord) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ContextRecord) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ContextRecord) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextRecord) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ContextRecord) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ContextRecord) SetAccess(v Access) { + o.Access = &v +} + +// GetAssociatedContexts returns the AssociatedContexts field value if set, zero value otherwise. +func (o *ContextRecord) GetAssociatedContexts() int32 { + if o == nil || o.AssociatedContexts == nil { + var ret int32 + return ret + } + return *o.AssociatedContexts +} + +// GetAssociatedContextsOk returns a tuple with the AssociatedContexts field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextRecord) GetAssociatedContextsOk() (*int32, bool) { + if o == nil || o.AssociatedContexts == nil { + return nil, false + } + return o.AssociatedContexts, true +} + +// HasAssociatedContexts returns a boolean if a field has been set. +func (o *ContextRecord) HasAssociatedContexts() bool { + if o != nil && o.AssociatedContexts != nil { + return true + } + + return false +} + +// SetAssociatedContexts gets a reference to the given int32 and assigns it to the AssociatedContexts field. +func (o *ContextRecord) SetAssociatedContexts(v int32) { + o.AssociatedContexts = &v +} + +func (o ContextRecord) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.LastSeen != nil { + toSerialize["lastSeen"] = o.LastSeen + } + if o.ApplicationId != nil { + toSerialize["applicationId"] = o.ApplicationId + } + if o.Context != nil { + toSerialize["context"] = o.Context + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.AssociatedContexts != nil { + toSerialize["associatedContexts"] = o.AssociatedContexts + } + return json.Marshal(toSerialize) +} + +type NullableContextRecord struct { + value *ContextRecord + isSet bool +} + +func (v NullableContextRecord) Get() *ContextRecord { + return v.value +} + +func (v *NullableContextRecord) Set(val *ContextRecord) { + v.value = val + v.isSet = true +} + +func (v NullableContextRecord) IsSet() bool { + return v.isSet +} + +func (v *NullableContextRecord) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextRecord(val *ContextRecord) *NullableContextRecord { + return &NullableContextRecord{value: val, isSet: true} +} + +func (v NullableContextRecord) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextRecord) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_context_search.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_search.go new file mode 100644 index 00000000..0aa554cf --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_context_search.go @@ -0,0 +1,228 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ContextSearch struct for ContextSearch +type ContextSearch struct { + // A collection of context filters + Filter *string `json:"filter,omitempty"` + // Specifies a field by which to sort. LaunchDarkly supports sorting by timestamp in ascending order by specifying ts for this value, or descending order by specifying -ts. + Sort *string `json:"sort,omitempty"` + // Specifies the maximum number of items in the collection to return (max: 50, default: 20) + Limit *int32 `json:"limit,omitempty"` + // Limits results to contexts with sort values after the value specified. You can use this for pagination, however, we recommend using the next link instead, because this value is an obfuscated string. + ContinuationToken *string `json:"continuationToken,omitempty"` +} + +// NewContextSearch instantiates a new ContextSearch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContextSearch() *ContextSearch { + this := ContextSearch{} + return &this +} + +// NewContextSearchWithDefaults instantiates a new ContextSearch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextSearchWithDefaults() *ContextSearch { + this := ContextSearch{} + return &this +} + +// GetFilter returns the Filter field value if set, zero value otherwise. +func (o *ContextSearch) GetFilter() string { + if o == nil || o.Filter == nil { + var ret string + return ret + } + return *o.Filter +} + +// GetFilterOk returns a tuple with the Filter field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextSearch) GetFilterOk() (*string, bool) { + if o == nil || o.Filter == nil { + return nil, false + } + return o.Filter, true +} + +// HasFilter returns a boolean if a field has been set. +func (o *ContextSearch) HasFilter() bool { + if o != nil && o.Filter != nil { + return true + } + + return false +} + +// SetFilter gets a reference to the given string and assigns it to the Filter field. +func (o *ContextSearch) SetFilter(v string) { + o.Filter = &v +} + +// GetSort returns the Sort field value if set, zero value otherwise. +func (o *ContextSearch) GetSort() string { + if o == nil || o.Sort == nil { + var ret string + return ret + } + return *o.Sort +} + +// GetSortOk returns a tuple with the Sort field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextSearch) GetSortOk() (*string, bool) { + if o == nil || o.Sort == nil { + return nil, false + } + return o.Sort, true +} + +// HasSort returns a boolean if a field has been set. +func (o *ContextSearch) HasSort() bool { + if o != nil && o.Sort != nil { + return true + } + + return false +} + +// SetSort gets a reference to the given string and assigns it to the Sort field. +func (o *ContextSearch) SetSort(v string) { + o.Sort = &v +} + +// GetLimit returns the Limit field value if set, zero value otherwise. +func (o *ContextSearch) GetLimit() int32 { + if o == nil || o.Limit == nil { + var ret int32 + return ret + } + return *o.Limit +} + +// GetLimitOk returns a tuple with the Limit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextSearch) GetLimitOk() (*int32, bool) { + if o == nil || o.Limit == nil { + return nil, false + } + return o.Limit, true +} + +// HasLimit returns a boolean if a field has been set. +func (o *ContextSearch) HasLimit() bool { + if o != nil && o.Limit != nil { + return true + } + + return false +} + +// SetLimit gets a reference to the given int32 and assigns it to the Limit field. +func (o *ContextSearch) SetLimit(v int32) { + o.Limit = &v +} + +// GetContinuationToken returns the ContinuationToken field value if set, zero value otherwise. +func (o *ContextSearch) GetContinuationToken() string { + if o == nil || o.ContinuationToken == nil { + var ret string + return ret + } + return *o.ContinuationToken +} + +// GetContinuationTokenOk returns a tuple with the ContinuationToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ContextSearch) GetContinuationTokenOk() (*string, bool) { + if o == nil || o.ContinuationToken == nil { + return nil, false + } + return o.ContinuationToken, true +} + +// HasContinuationToken returns a boolean if a field has been set. +func (o *ContextSearch) HasContinuationToken() bool { + if o != nil && o.ContinuationToken != nil { + return true + } + + return false +} + +// SetContinuationToken gets a reference to the given string and assigns it to the ContinuationToken field. +func (o *ContextSearch) SetContinuationToken(v string) { + o.ContinuationToken = &v +} + +func (o ContextSearch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Filter != nil { + toSerialize["filter"] = o.Filter + } + if o.Sort != nil { + toSerialize["sort"] = o.Sort + } + if o.Limit != nil { + toSerialize["limit"] = o.Limit + } + if o.ContinuationToken != nil { + toSerialize["continuationToken"] = o.ContinuationToken + } + return json.Marshal(toSerialize) +} + +type NullableContextSearch struct { + value *ContextSearch + isSet bool +} + +func (v NullableContextSearch) Get() *ContextSearch { + return v.value +} + +func (v *NullableContextSearch) Set(val *ContextSearch) { + v.value = val + v.isSet = true +} + +func (v NullableContextSearch) IsSet() bool { + return v.isSet +} + +func (v *NullableContextSearch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContextSearch(val *ContextSearch) *NullableContextSearch { + return &NullableContextSearch{value: val, isSet: true} +} + +func (v NullableContextSearch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContextSearch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_contexts.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_contexts.go new file mode 100644 index 00000000..18e8cae6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_contexts.go @@ -0,0 +1,251 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Contexts struct for Contexts +type Contexts struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The number of contexts + TotalCount *int32 `json:"totalCount,omitempty"` + // The environment ID where the context was evaluated + EnvironmentId string `json:"_environmentId"` + // An obfuscated string that references the last context instance on the previous page of results. You can use this for pagination, however, we recommend using the next link instead. + ContinuationToken *string `json:"continuationToken,omitempty"` + // A collection of contexts. Can include multiple versions of contexts that have the same kind and key, but different applicationIds. + Items []ContextRecord `json:"items"` +} + +// NewContexts instantiates a new Contexts object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewContexts(environmentId string, items []ContextRecord) *Contexts { + this := Contexts{} + this.EnvironmentId = environmentId + this.Items = items + return &this +} + +// NewContextsWithDefaults instantiates a new Contexts object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewContextsWithDefaults() *Contexts { + this := Contexts{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Contexts) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Contexts) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Contexts) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Contexts) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Contexts) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Contexts) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Contexts) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Contexts) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetEnvironmentId returns the EnvironmentId field value +func (o *Contexts) GetEnvironmentId() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value +// and a boolean to check if the value has been set. +func (o *Contexts) GetEnvironmentIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentId, true +} + +// SetEnvironmentId sets field value +func (o *Contexts) SetEnvironmentId(v string) { + o.EnvironmentId = v +} + +// GetContinuationToken returns the ContinuationToken field value if set, zero value otherwise. +func (o *Contexts) GetContinuationToken() string { + if o == nil || o.ContinuationToken == nil { + var ret string + return ret + } + return *o.ContinuationToken +} + +// GetContinuationTokenOk returns a tuple with the ContinuationToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Contexts) GetContinuationTokenOk() (*string, bool) { + if o == nil || o.ContinuationToken == nil { + return nil, false + } + return o.ContinuationToken, true +} + +// HasContinuationToken returns a boolean if a field has been set. +func (o *Contexts) HasContinuationToken() bool { + if o != nil && o.ContinuationToken != nil { + return true + } + + return false +} + +// SetContinuationToken gets a reference to the given string and assigns it to the ContinuationToken field. +func (o *Contexts) SetContinuationToken(v string) { + o.ContinuationToken = &v +} + +// GetItems returns the Items field value +func (o *Contexts) GetItems() []ContextRecord { + if o == nil { + var ret []ContextRecord + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Contexts) GetItemsOk() ([]ContextRecord, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Contexts) SetItems(v []ContextRecord) { + o.Items = v +} + +func (o Contexts) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_environmentId"] = o.EnvironmentId + } + if o.ContinuationToken != nil { + toSerialize["continuationToken"] = o.ContinuationToken + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableContexts struct { + value *Contexts + isSet bool +} + +func (v NullableContexts) Get() *Contexts { + return v.value +} + +func (v *NullableContexts) Set(val *Contexts) { + v.value = val + v.isSet = true +} + +func (v NullableContexts) IsSet() bool { + return v.isSet +} + +func (v *NullableContexts) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableContexts(val *Contexts) *NullableContexts { + return &NullableContexts{value: val, isSet: true} +} + +func (v NullableContexts) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableContexts) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_copied_from_env.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_copied_from_env.go new file mode 100644 index 00000000..2c81c65b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_copied_from_env.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CopiedFromEnv struct for CopiedFromEnv +type CopiedFromEnv struct { + // Key of feature flag copied + Key string `json:"key"` + // Version of feature flag copied + Version *int32 `json:"version,omitempty"` +} + +// NewCopiedFromEnv instantiates a new CopiedFromEnv object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCopiedFromEnv(key string) *CopiedFromEnv { + this := CopiedFromEnv{} + this.Key = key + return &this +} + +// NewCopiedFromEnvWithDefaults instantiates a new CopiedFromEnv object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCopiedFromEnvWithDefaults() *CopiedFromEnv { + this := CopiedFromEnv{} + return &this +} + +// GetKey returns the Key field value +func (o *CopiedFromEnv) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *CopiedFromEnv) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *CopiedFromEnv) SetKey(v string) { + o.Key = v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *CopiedFromEnv) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CopiedFromEnv) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *CopiedFromEnv) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *CopiedFromEnv) SetVersion(v int32) { + o.Version = &v +} + +func (o CopiedFromEnv) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableCopiedFromEnv struct { + value *CopiedFromEnv + isSet bool +} + +func (v NullableCopiedFromEnv) Get() *CopiedFromEnv { + return v.value +} + +func (v *NullableCopiedFromEnv) Set(val *CopiedFromEnv) { + v.value = val + v.isSet = true +} + +func (v NullableCopiedFromEnv) IsSet() bool { + return v.isSet +} + +func (v *NullableCopiedFromEnv) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCopiedFromEnv(val *CopiedFromEnv) *NullableCopiedFromEnv { + return &NullableCopiedFromEnv{value: val, isSet: true} +} + +func (v NullableCopiedFromEnv) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCopiedFromEnv) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_core_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_core_link.go new file mode 100644 index 00000000..7fa87723 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_core_link.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CoreLink struct for CoreLink +type CoreLink struct { + Href string `json:"href"` + Type string `json:"type"` +} + +// NewCoreLink instantiates a new CoreLink object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCoreLink(href string, type_ string) *CoreLink { + this := CoreLink{} + this.Href = href + this.Type = type_ + return &this +} + +// NewCoreLinkWithDefaults instantiates a new CoreLink object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCoreLinkWithDefaults() *CoreLink { + this := CoreLink{} + return &this +} + +// GetHref returns the Href field value +func (o *CoreLink) GetHref() string { + if o == nil { + var ret string + return ret + } + + return o.Href +} + +// GetHrefOk returns a tuple with the Href field value +// and a boolean to check if the value has been set. +func (o *CoreLink) GetHrefOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Href, true +} + +// SetHref sets field value +func (o *CoreLink) SetHref(v string) { + o.Href = v +} + +// GetType returns the Type field value +func (o *CoreLink) GetType() string { + if o == nil { + var ret string + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *CoreLink) GetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *CoreLink) SetType(v string) { + o.Type = v +} + +func (o CoreLink) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["href"] = o.Href + } + if true { + toSerialize["type"] = o.Type + } + return json.Marshal(toSerialize) +} + +type NullableCoreLink struct { + value *CoreLink + isSet bool +} + +func (v NullableCoreLink) Get() *CoreLink { + return v.value +} + +func (v *NullableCoreLink) Set(val *CoreLink) { + v.value = val + v.isSet = true +} + +func (v NullableCoreLink) IsSet() bool { + return v.isSet +} + +func (v *NullableCoreLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCoreLink(val *CoreLink) *NullableCoreLink { + return &NullableCoreLink{value: val, isSet: true} +} + +func (v NullableCoreLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCoreLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_announcement_body.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_announcement_body.go new file mode 100644 index 00000000..bb573bb4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_announcement_body.go @@ -0,0 +1,267 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateAnnouncementBody Create announcement request body +type CreateAnnouncementBody struct { + // true if the announcement is dismissible + IsDismissible bool `json:"isDismissible"` + // The title of the announcement + Title string `json:"title"` + // The message of the announcement + Message string `json:"message"` + // The start time of the announcement. This is a Unix timestamp in milliseconds. + StartTime int64 `json:"startTime"` + // The end time of the announcement. This is a Unix timestamp in milliseconds. + EndTime *int64 `json:"endTime,omitempty"` + // The severity of the announcement + Severity string `json:"severity"` +} + +// NewCreateAnnouncementBody instantiates a new CreateAnnouncementBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateAnnouncementBody(isDismissible bool, title string, message string, startTime int64, severity string) *CreateAnnouncementBody { + this := CreateAnnouncementBody{} + this.IsDismissible = isDismissible + this.Title = title + this.Message = message + this.StartTime = startTime + this.Severity = severity + return &this +} + +// NewCreateAnnouncementBodyWithDefaults instantiates a new CreateAnnouncementBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateAnnouncementBodyWithDefaults() *CreateAnnouncementBody { + this := CreateAnnouncementBody{} + return &this +} + +// GetIsDismissible returns the IsDismissible field value +func (o *CreateAnnouncementBody) GetIsDismissible() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsDismissible +} + +// GetIsDismissibleOk returns a tuple with the IsDismissible field value +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetIsDismissibleOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsDismissible, true +} + +// SetIsDismissible sets field value +func (o *CreateAnnouncementBody) SetIsDismissible(v bool) { + o.IsDismissible = v +} + +// GetTitle returns the Title field value +func (o *CreateAnnouncementBody) GetTitle() string { + if o == nil { + var ret string + return ret + } + + return o.Title +} + +// GetTitleOk returns a tuple with the Title field value +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetTitleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Title, true +} + +// SetTitle sets field value +func (o *CreateAnnouncementBody) SetTitle(v string) { + o.Title = v +} + +// GetMessage returns the Message field value +func (o *CreateAnnouncementBody) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *CreateAnnouncementBody) SetMessage(v string) { + o.Message = v +} + +// GetStartTime returns the StartTime field value +func (o *CreateAnnouncementBody) GetStartTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.StartTime +} + +// GetStartTimeOk returns a tuple with the StartTime field value +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetStartTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.StartTime, true +} + +// SetStartTime sets field value +func (o *CreateAnnouncementBody) SetStartTime(v int64) { + o.StartTime = v +} + +// GetEndTime returns the EndTime field value if set, zero value otherwise. +func (o *CreateAnnouncementBody) GetEndTime() int64 { + if o == nil || o.EndTime == nil { + var ret int64 + return ret + } + return *o.EndTime +} + +// GetEndTimeOk returns a tuple with the EndTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetEndTimeOk() (*int64, bool) { + if o == nil || o.EndTime == nil { + return nil, false + } + return o.EndTime, true +} + +// HasEndTime returns a boolean if a field has been set. +func (o *CreateAnnouncementBody) HasEndTime() bool { + if o != nil && o.EndTime != nil { + return true + } + + return false +} + +// SetEndTime gets a reference to the given int64 and assigns it to the EndTime field. +func (o *CreateAnnouncementBody) SetEndTime(v int64) { + o.EndTime = &v +} + +// GetSeverity returns the Severity field value +func (o *CreateAnnouncementBody) GetSeverity() string { + if o == nil { + var ret string + return ret + } + + return o.Severity +} + +// GetSeverityOk returns a tuple with the Severity field value +// and a boolean to check if the value has been set. +func (o *CreateAnnouncementBody) GetSeverityOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Severity, true +} + +// SetSeverity sets field value +func (o *CreateAnnouncementBody) SetSeverity(v string) { + o.Severity = v +} + +func (o CreateAnnouncementBody) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["isDismissible"] = o.IsDismissible + } + if true { + toSerialize["title"] = o.Title + } + if true { + toSerialize["message"] = o.Message + } + if true { + toSerialize["startTime"] = o.StartTime + } + if o.EndTime != nil { + toSerialize["endTime"] = o.EndTime + } + if true { + toSerialize["severity"] = o.Severity + } + return json.Marshal(toSerialize) +} + +type NullableCreateAnnouncementBody struct { + value *CreateAnnouncementBody + isSet bool +} + +func (v NullableCreateAnnouncementBody) Get() *CreateAnnouncementBody { + return v.value +} + +func (v *NullableCreateAnnouncementBody) Set(val *CreateAnnouncementBody) { + v.value = val + v.isSet = true +} + +func (v NullableCreateAnnouncementBody) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateAnnouncementBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateAnnouncementBody(val *CreateAnnouncementBody) *NullableCreateAnnouncementBody { + return &NullableCreateAnnouncementBody{value: val, isSet: true} +} + +func (v NullableCreateAnnouncementBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateAnnouncementBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_approval_request_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_approval_request_request.go new file mode 100644 index 00000000..e91ecee4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_approval_request_request.go @@ -0,0 +1,316 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateApprovalRequestRequest struct for CreateApprovalRequestRequest +type CreateApprovalRequestRequest struct { + // String representation of the resource specifier + ResourceId string `json:"resourceId"` + // Optional comment describing the approval request + Comment *string `json:"comment,omitempty"` + // A brief description of the changes you're requesting + Description string `json:"description"` + Instructions []map[string]interface{} `json:"instructions"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // An array of team keys. The members of these teams are notified to review the approval request. + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` + IntegrationConfig map[string]interface{} `json:"integrationConfig,omitempty"` +} + +// NewCreateApprovalRequestRequest instantiates a new CreateApprovalRequestRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateApprovalRequestRequest(resourceId string, description string, instructions []map[string]interface{}) *CreateApprovalRequestRequest { + this := CreateApprovalRequestRequest{} + this.ResourceId = resourceId + this.Description = description + this.Instructions = instructions + return &this +} + +// NewCreateApprovalRequestRequestWithDefaults instantiates a new CreateApprovalRequestRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateApprovalRequestRequestWithDefaults() *CreateApprovalRequestRequest { + this := CreateApprovalRequestRequest{} + return &this +} + +// GetResourceId returns the ResourceId field value +func (o *CreateApprovalRequestRequest) GetResourceId() string { + if o == nil { + var ret string + return ret + } + + return o.ResourceId +} + +// GetResourceIdOk returns a tuple with the ResourceId field value +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetResourceIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ResourceId, true +} + +// SetResourceId sets field value +func (o *CreateApprovalRequestRequest) SetResourceId(v string) { + o.ResourceId = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *CreateApprovalRequestRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *CreateApprovalRequestRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *CreateApprovalRequestRequest) SetComment(v string) { + o.Comment = &v +} + +// GetDescription returns the Description field value +func (o *CreateApprovalRequestRequest) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *CreateApprovalRequestRequest) SetDescription(v string) { + o.Description = v +} + +// GetInstructions returns the Instructions field value +func (o *CreateApprovalRequestRequest) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *CreateApprovalRequestRequest) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *CreateApprovalRequestRequest) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *CreateApprovalRequestRequest) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *CreateApprovalRequestRequest) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *CreateApprovalRequestRequest) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *CreateApprovalRequestRequest) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *CreateApprovalRequestRequest) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +// GetIntegrationConfig returns the IntegrationConfig field value if set, zero value otherwise. +func (o *CreateApprovalRequestRequest) GetIntegrationConfig() map[string]interface{} { + if o == nil || o.IntegrationConfig == nil { + var ret map[string]interface{} + return ret + } + return o.IntegrationConfig +} + +// GetIntegrationConfigOk returns a tuple with the IntegrationConfig field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateApprovalRequestRequest) GetIntegrationConfigOk() (map[string]interface{}, bool) { + if o == nil || o.IntegrationConfig == nil { + return nil, false + } + return o.IntegrationConfig, true +} + +// HasIntegrationConfig returns a boolean if a field has been set. +func (o *CreateApprovalRequestRequest) HasIntegrationConfig() bool { + if o != nil && o.IntegrationConfig != nil { + return true + } + + return false +} + +// SetIntegrationConfig gets a reference to the given map[string]interface{} and assigns it to the IntegrationConfig field. +func (o *CreateApprovalRequestRequest) SetIntegrationConfig(v map[string]interface{}) { + o.IntegrationConfig = v +} + +func (o CreateApprovalRequestRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["resourceId"] = o.ResourceId + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["instructions"] = o.Instructions + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + if o.IntegrationConfig != nil { + toSerialize["integrationConfig"] = o.IntegrationConfig + } + return json.Marshal(toSerialize) +} + +type NullableCreateApprovalRequestRequest struct { + value *CreateApprovalRequestRequest + isSet bool +} + +func (v NullableCreateApprovalRequestRequest) Get() *CreateApprovalRequestRequest { + return v.value +} + +func (v *NullableCreateApprovalRequestRequest) Set(val *CreateApprovalRequestRequest) { + v.value = val + v.isSet = true +} + +func (v NullableCreateApprovalRequestRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateApprovalRequestRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateApprovalRequestRequest(val *CreateApprovalRequestRequest) *NullableCreateApprovalRequestRequest { + return &NullableCreateApprovalRequestRequest{value: val, isSet: true} +} + +func (v NullableCreateApprovalRequestRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateApprovalRequestRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_copy_flag_config_approval_request_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_copy_flag_config_approval_request_request.go new file mode 100644 index 00000000..08e662a6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_copy_flag_config_approval_request_request.go @@ -0,0 +1,324 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateCopyFlagConfigApprovalRequestRequest struct for CreateCopyFlagConfigApprovalRequestRequest +type CreateCopyFlagConfigApprovalRequestRequest struct { + // Optional comment describing the approval request + Comment *string `json:"comment,omitempty"` + // A brief description of your changes + Description string `json:"description"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // An array of team keys. The members of these teams are notified to review the approval request. + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` + Source SourceFlag `json:"source"` + // Optional list of the flag changes to copy from the source environment to the target environment. You may include either includedActions or excludedActions, but not both. If neither are included, then all flag changes will be copied. + IncludedActions []string `json:"includedActions,omitempty"` + // Optional list of the flag changes NOT to copy from the source environment to the target environment. You may include either includedActions or excludedActions, but not both. If neither are included, then all flag changes will be copied. + ExcludedActions []string `json:"excludedActions,omitempty"` +} + +// NewCreateCopyFlagConfigApprovalRequestRequest instantiates a new CreateCopyFlagConfigApprovalRequestRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateCopyFlagConfigApprovalRequestRequest(description string, source SourceFlag) *CreateCopyFlagConfigApprovalRequestRequest { + this := CreateCopyFlagConfigApprovalRequestRequest{} + this.Description = description + this.Source = source + return &this +} + +// NewCreateCopyFlagConfigApprovalRequestRequestWithDefaults instantiates a new CreateCopyFlagConfigApprovalRequestRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateCopyFlagConfigApprovalRequestRequestWithDefaults() *CreateCopyFlagConfigApprovalRequestRequest { + this := CreateCopyFlagConfigApprovalRequestRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetComment(v string) { + o.Comment = &v +} + +// GetDescription returns the Description field value +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetDescription(v string) { + o.Description = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +// GetSource returns the Source field value +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetSource() SourceFlag { + if o == nil { + var ret SourceFlag + return ret + } + + return o.Source +} + +// GetSourceOk returns a tuple with the Source field value +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetSourceOk() (*SourceFlag, bool) { + if o == nil { + return nil, false + } + return &o.Source, true +} + +// SetSource sets field value +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetSource(v SourceFlag) { + o.Source = v +} + +// GetIncludedActions returns the IncludedActions field value if set, zero value otherwise. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetIncludedActions() []string { + if o == nil || o.IncludedActions == nil { + var ret []string + return ret + } + return o.IncludedActions +} + +// GetIncludedActionsOk returns a tuple with the IncludedActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetIncludedActionsOk() ([]string, bool) { + if o == nil || o.IncludedActions == nil { + return nil, false + } + return o.IncludedActions, true +} + +// HasIncludedActions returns a boolean if a field has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) HasIncludedActions() bool { + if o != nil && o.IncludedActions != nil { + return true + } + + return false +} + +// SetIncludedActions gets a reference to the given []string and assigns it to the IncludedActions field. +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetIncludedActions(v []string) { + o.IncludedActions = v +} + +// GetExcludedActions returns the ExcludedActions field value if set, zero value otherwise. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetExcludedActions() []string { + if o == nil || o.ExcludedActions == nil { + var ret []string + return ret + } + return o.ExcludedActions +} + +// GetExcludedActionsOk returns a tuple with the ExcludedActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) GetExcludedActionsOk() ([]string, bool) { + if o == nil || o.ExcludedActions == nil { + return nil, false + } + return o.ExcludedActions, true +} + +// HasExcludedActions returns a boolean if a field has been set. +func (o *CreateCopyFlagConfigApprovalRequestRequest) HasExcludedActions() bool { + if o != nil && o.ExcludedActions != nil { + return true + } + + return false +} + +// SetExcludedActions gets a reference to the given []string and assigns it to the ExcludedActions field. +func (o *CreateCopyFlagConfigApprovalRequestRequest) SetExcludedActions(v []string) { + o.ExcludedActions = v +} + +func (o CreateCopyFlagConfigApprovalRequestRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["description"] = o.Description + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + if true { + toSerialize["source"] = o.Source + } + if o.IncludedActions != nil { + toSerialize["includedActions"] = o.IncludedActions + } + if o.ExcludedActions != nil { + toSerialize["excludedActions"] = o.ExcludedActions + } + return json.Marshal(toSerialize) +} + +type NullableCreateCopyFlagConfigApprovalRequestRequest struct { + value *CreateCopyFlagConfigApprovalRequestRequest + isSet bool +} + +func (v NullableCreateCopyFlagConfigApprovalRequestRequest) Get() *CreateCopyFlagConfigApprovalRequestRequest { + return v.value +} + +func (v *NullableCreateCopyFlagConfigApprovalRequestRequest) Set(val *CreateCopyFlagConfigApprovalRequestRequest) { + v.value = val + v.isSet = true +} + +func (v NullableCreateCopyFlagConfigApprovalRequestRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateCopyFlagConfigApprovalRequestRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateCopyFlagConfigApprovalRequestRequest(val *CreateCopyFlagConfigApprovalRequestRequest) *NullableCreateCopyFlagConfigApprovalRequestRequest { + return &NullableCreateCopyFlagConfigApprovalRequestRequest{value: val, isSet: true} +} + +func (v NullableCreateCopyFlagConfigApprovalRequestRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateCopyFlagConfigApprovalRequestRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_flag_config_approval_request_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_flag_config_approval_request_request.go new file mode 100644 index 00000000..ab781bd6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_flag_config_approval_request_request.go @@ -0,0 +1,359 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateFlagConfigApprovalRequestRequest struct for CreateFlagConfigApprovalRequestRequest +type CreateFlagConfigApprovalRequestRequest struct { + // Optional comment describing the approval request + Comment *string `json:"comment,omitempty"` + // A brief description of the changes you're requesting + Description string `json:"description"` + Instructions []map[string]interface{} `json:"instructions"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // An array of team keys. The members of these teams are notified to review the approval request. + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + // The ID of a scheduled change. Include this if your instructions include editing or deleting a scheduled change. + OperatingOnId *string `json:"operatingOnId,omitempty"` + IntegrationConfig map[string]interface{} `json:"integrationConfig,omitempty"` +} + +// NewCreateFlagConfigApprovalRequestRequest instantiates a new CreateFlagConfigApprovalRequestRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateFlagConfigApprovalRequestRequest(description string, instructions []map[string]interface{}) *CreateFlagConfigApprovalRequestRequest { + this := CreateFlagConfigApprovalRequestRequest{} + this.Description = description + this.Instructions = instructions + return &this +} + +// NewCreateFlagConfigApprovalRequestRequestWithDefaults instantiates a new CreateFlagConfigApprovalRequestRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateFlagConfigApprovalRequestRequestWithDefaults() *CreateFlagConfigApprovalRequestRequest { + this := CreateFlagConfigApprovalRequestRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *CreateFlagConfigApprovalRequestRequest) SetComment(v string) { + o.Comment = &v +} + +// GetDescription returns the Description field value +func (o *CreateFlagConfigApprovalRequestRequest) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *CreateFlagConfigApprovalRequestRequest) SetDescription(v string) { + o.Description = v +} + +// GetInstructions returns the Instructions field value +func (o *CreateFlagConfigApprovalRequestRequest) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *CreateFlagConfigApprovalRequestRequest) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *CreateFlagConfigApprovalRequestRequest) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *CreateFlagConfigApprovalRequestRequest) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *CreateFlagConfigApprovalRequestRequest) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetOperatingOnId returns the OperatingOnId field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetOperatingOnId() string { + if o == nil || o.OperatingOnId == nil { + var ret string + return ret + } + return *o.OperatingOnId +} + +// GetOperatingOnIdOk returns a tuple with the OperatingOnId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetOperatingOnIdOk() (*string, bool) { + if o == nil || o.OperatingOnId == nil { + return nil, false + } + return o.OperatingOnId, true +} + +// HasOperatingOnId returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasOperatingOnId() bool { + if o != nil && o.OperatingOnId != nil { + return true + } + + return false +} + +// SetOperatingOnId gets a reference to the given string and assigns it to the OperatingOnId field. +func (o *CreateFlagConfigApprovalRequestRequest) SetOperatingOnId(v string) { + o.OperatingOnId = &v +} + +// GetIntegrationConfig returns the IntegrationConfig field value if set, zero value otherwise. +func (o *CreateFlagConfigApprovalRequestRequest) GetIntegrationConfig() map[string]interface{} { + if o == nil || o.IntegrationConfig == nil { + var ret map[string]interface{} + return ret + } + return o.IntegrationConfig +} + +// GetIntegrationConfigOk returns a tuple with the IntegrationConfig field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateFlagConfigApprovalRequestRequest) GetIntegrationConfigOk() (map[string]interface{}, bool) { + if o == nil || o.IntegrationConfig == nil { + return nil, false + } + return o.IntegrationConfig, true +} + +// HasIntegrationConfig returns a boolean if a field has been set. +func (o *CreateFlagConfigApprovalRequestRequest) HasIntegrationConfig() bool { + if o != nil && o.IntegrationConfig != nil { + return true + } + + return false +} + +// SetIntegrationConfig gets a reference to the given map[string]interface{} and assigns it to the IntegrationConfig field. +func (o *CreateFlagConfigApprovalRequestRequest) SetIntegrationConfig(v map[string]interface{}) { + o.IntegrationConfig = v +} + +func (o CreateFlagConfigApprovalRequestRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["instructions"] = o.Instructions + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.OperatingOnId != nil { + toSerialize["operatingOnId"] = o.OperatingOnId + } + if o.IntegrationConfig != nil { + toSerialize["integrationConfig"] = o.IntegrationConfig + } + return json.Marshal(toSerialize) +} + +type NullableCreateFlagConfigApprovalRequestRequest struct { + value *CreateFlagConfigApprovalRequestRequest + isSet bool +} + +func (v NullableCreateFlagConfigApprovalRequestRequest) Get() *CreateFlagConfigApprovalRequestRequest { + return v.value +} + +func (v *NullableCreateFlagConfigApprovalRequestRequest) Set(val *CreateFlagConfigApprovalRequestRequest) { + v.value = val + v.isSet = true +} + +func (v NullableCreateFlagConfigApprovalRequestRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateFlagConfigApprovalRequestRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateFlagConfigApprovalRequestRequest(val *CreateFlagConfigApprovalRequestRequest) *NullableCreateFlagConfigApprovalRequestRequest { + return &NullableCreateFlagConfigApprovalRequestRequest{value: val, isSet: true} +} + +func (v NullableCreateFlagConfigApprovalRequestRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateFlagConfigApprovalRequestRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_phase_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_phase_input.go new file mode 100644 index 00000000..92c6971f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_phase_input.go @@ -0,0 +1,176 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreatePhaseInput struct for CreatePhaseInput +type CreatePhaseInput struct { + // An ordered list of the audiences for this release phase. Each audience corresponds to a LaunchDarkly environment. + Audiences []AudiencePost `json:"audiences"` + // The release phase name + Name string `json:"name"` + Configuration map[string]interface{} `json:"configuration,omitempty"` +} + +// NewCreatePhaseInput instantiates a new CreatePhaseInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreatePhaseInput(audiences []AudiencePost, name string) *CreatePhaseInput { + this := CreatePhaseInput{} + this.Audiences = audiences + this.Name = name + return &this +} + +// NewCreatePhaseInputWithDefaults instantiates a new CreatePhaseInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreatePhaseInputWithDefaults() *CreatePhaseInput { + this := CreatePhaseInput{} + return &this +} + +// GetAudiences returns the Audiences field value +func (o *CreatePhaseInput) GetAudiences() []AudiencePost { + if o == nil { + var ret []AudiencePost + return ret + } + + return o.Audiences +} + +// GetAudiencesOk returns a tuple with the Audiences field value +// and a boolean to check if the value has been set. +func (o *CreatePhaseInput) GetAudiencesOk() ([]AudiencePost, bool) { + if o == nil { + return nil, false + } + return o.Audiences, true +} + +// SetAudiences sets field value +func (o *CreatePhaseInput) SetAudiences(v []AudiencePost) { + o.Audiences = v +} + +// GetName returns the Name field value +func (o *CreatePhaseInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CreatePhaseInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CreatePhaseInput) SetName(v string) { + o.Name = v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *CreatePhaseInput) GetConfiguration() map[string]interface{} { + if o == nil || o.Configuration == nil { + var ret map[string]interface{} + return ret + } + return o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreatePhaseInput) GetConfigurationOk() (map[string]interface{}, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *CreatePhaseInput) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given map[string]interface{} and assigns it to the Configuration field. +func (o *CreatePhaseInput) SetConfiguration(v map[string]interface{}) { + o.Configuration = v +} + +func (o CreatePhaseInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["audiences"] = o.Audiences + } + if true { + toSerialize["name"] = o.Name + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + return json.Marshal(toSerialize) +} + +type NullableCreatePhaseInput struct { + value *CreatePhaseInput + isSet bool +} + +func (v NullableCreatePhaseInput) Get() *CreatePhaseInput { + return v.value +} + +func (v *NullableCreatePhaseInput) Set(val *CreatePhaseInput) { + v.value = val + v.isSet = true +} + +func (v NullableCreatePhaseInput) IsSet() bool { + return v.isSet +} + +func (v *NullableCreatePhaseInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreatePhaseInput(val *CreatePhaseInput) *NullableCreatePhaseInput { + return &NullableCreatePhaseInput{value: val, isSet: true} +} + +func (v NullableCreatePhaseInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreatePhaseInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_input.go new file mode 100644 index 00000000..6c6cbd91 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_input.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateReleaseInput struct for CreateReleaseInput +type CreateReleaseInput struct { + // The variation id to release to across all phases + ReleaseVariationId *string `json:"releaseVariationId,omitempty"` + // The key of the release pipeline to attach the flag to + ReleasePipelineKey string `json:"releasePipelineKey"` +} + +// NewCreateReleaseInput instantiates a new CreateReleaseInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateReleaseInput(releasePipelineKey string) *CreateReleaseInput { + this := CreateReleaseInput{} + this.ReleasePipelineKey = releasePipelineKey + return &this +} + +// NewCreateReleaseInputWithDefaults instantiates a new CreateReleaseInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateReleaseInputWithDefaults() *CreateReleaseInput { + this := CreateReleaseInput{} + return &this +} + +// GetReleaseVariationId returns the ReleaseVariationId field value if set, zero value otherwise. +func (o *CreateReleaseInput) GetReleaseVariationId() string { + if o == nil || o.ReleaseVariationId == nil { + var ret string + return ret + } + return *o.ReleaseVariationId +} + +// GetReleaseVariationIdOk returns a tuple with the ReleaseVariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateReleaseInput) GetReleaseVariationIdOk() (*string, bool) { + if o == nil || o.ReleaseVariationId == nil { + return nil, false + } + return o.ReleaseVariationId, true +} + +// HasReleaseVariationId returns a boolean if a field has been set. +func (o *CreateReleaseInput) HasReleaseVariationId() bool { + if o != nil && o.ReleaseVariationId != nil { + return true + } + + return false +} + +// SetReleaseVariationId gets a reference to the given string and assigns it to the ReleaseVariationId field. +func (o *CreateReleaseInput) SetReleaseVariationId(v string) { + o.ReleaseVariationId = &v +} + +// GetReleasePipelineKey returns the ReleasePipelineKey field value +func (o *CreateReleaseInput) GetReleasePipelineKey() string { + if o == nil { + var ret string + return ret + } + + return o.ReleasePipelineKey +} + +// GetReleasePipelineKeyOk returns a tuple with the ReleasePipelineKey field value +// and a boolean to check if the value has been set. +func (o *CreateReleaseInput) GetReleasePipelineKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReleasePipelineKey, true +} + +// SetReleasePipelineKey sets field value +func (o *CreateReleaseInput) SetReleasePipelineKey(v string) { + o.ReleasePipelineKey = v +} + +func (o CreateReleaseInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ReleaseVariationId != nil { + toSerialize["releaseVariationId"] = o.ReleaseVariationId + } + if true { + toSerialize["releasePipelineKey"] = o.ReleasePipelineKey + } + return json.Marshal(toSerialize) +} + +type NullableCreateReleaseInput struct { + value *CreateReleaseInput + isSet bool +} + +func (v NullableCreateReleaseInput) Get() *CreateReleaseInput { + return v.value +} + +func (v *NullableCreateReleaseInput) Set(val *CreateReleaseInput) { + v.value = val + v.isSet = true +} + +func (v NullableCreateReleaseInput) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateReleaseInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateReleaseInput(val *CreateReleaseInput) *NullableCreateReleaseInput { + return &NullableCreateReleaseInput{value: val, isSet: true} +} + +func (v NullableCreateReleaseInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateReleaseInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_pipeline_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_pipeline_input.go new file mode 100644 index 00000000..3315807f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_release_pipeline_input.go @@ -0,0 +1,318 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateReleasePipelineInput struct for CreateReleasePipelineInput +type CreateReleasePipelineInput struct { + // The release pipeline description + Description *string `json:"description,omitempty"` + // The unique identifier of this release pipeline + Key string `json:"key"` + // The name of the release pipeline + Name string `json:"name"` + // A logical grouping of one or more environments that share attributes for rolling out changes + Phases []CreatePhaseInput `json:"phases"` + // A list of tags for this release pipeline + Tags []string `json:"tags,omitempty"` + // Whether or not the newly created pipeline should be set as the default pipeline for this project + IsProjectDefault *bool `json:"isProjectDefault,omitempty"` + // Whether or not the pipeline is enabled for Release Automation. + IsLegacy *bool `json:"isLegacy,omitempty"` +} + +// NewCreateReleasePipelineInput instantiates a new CreateReleasePipelineInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateReleasePipelineInput(key string, name string, phases []CreatePhaseInput) *CreateReleasePipelineInput { + this := CreateReleasePipelineInput{} + this.Key = key + this.Name = name + this.Phases = phases + return &this +} + +// NewCreateReleasePipelineInputWithDefaults instantiates a new CreateReleasePipelineInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateReleasePipelineInputWithDefaults() *CreateReleasePipelineInput { + this := CreateReleasePipelineInput{} + return &this +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CreateReleasePipelineInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CreateReleasePipelineInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CreateReleasePipelineInput) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *CreateReleasePipelineInput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *CreateReleasePipelineInput) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *CreateReleasePipelineInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CreateReleasePipelineInput) SetName(v string) { + o.Name = v +} + +// GetPhases returns the Phases field value +func (o *CreateReleasePipelineInput) GetPhases() []CreatePhaseInput { + if o == nil { + var ret []CreatePhaseInput + return ret + } + + return o.Phases +} + +// GetPhasesOk returns a tuple with the Phases field value +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetPhasesOk() ([]CreatePhaseInput, bool) { + if o == nil { + return nil, false + } + return o.Phases, true +} + +// SetPhases sets field value +func (o *CreateReleasePipelineInput) SetPhases(v []CreatePhaseInput) { + o.Phases = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *CreateReleasePipelineInput) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *CreateReleasePipelineInput) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *CreateReleasePipelineInput) SetTags(v []string) { + o.Tags = v +} + +// GetIsProjectDefault returns the IsProjectDefault field value if set, zero value otherwise. +func (o *CreateReleasePipelineInput) GetIsProjectDefault() bool { + if o == nil || o.IsProjectDefault == nil { + var ret bool + return ret + } + return *o.IsProjectDefault +} + +// GetIsProjectDefaultOk returns a tuple with the IsProjectDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetIsProjectDefaultOk() (*bool, bool) { + if o == nil || o.IsProjectDefault == nil { + return nil, false + } + return o.IsProjectDefault, true +} + +// HasIsProjectDefault returns a boolean if a field has been set. +func (o *CreateReleasePipelineInput) HasIsProjectDefault() bool { + if o != nil && o.IsProjectDefault != nil { + return true + } + + return false +} + +// SetIsProjectDefault gets a reference to the given bool and assigns it to the IsProjectDefault field. +func (o *CreateReleasePipelineInput) SetIsProjectDefault(v bool) { + o.IsProjectDefault = &v +} + +// GetIsLegacy returns the IsLegacy field value if set, zero value otherwise. +func (o *CreateReleasePipelineInput) GetIsLegacy() bool { + if o == nil || o.IsLegacy == nil { + var ret bool + return ret + } + return *o.IsLegacy +} + +// GetIsLegacyOk returns a tuple with the IsLegacy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateReleasePipelineInput) GetIsLegacyOk() (*bool, bool) { + if o == nil || o.IsLegacy == nil { + return nil, false + } + return o.IsLegacy, true +} + +// HasIsLegacy returns a boolean if a field has been set. +func (o *CreateReleasePipelineInput) HasIsLegacy() bool { + if o != nil && o.IsLegacy != nil { + return true + } + + return false +} + +// SetIsLegacy gets a reference to the given bool and assigns it to the IsLegacy field. +func (o *CreateReleasePipelineInput) SetIsLegacy(v bool) { + o.IsLegacy = &v +} + +func (o CreateReleasePipelineInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["phases"] = o.Phases + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.IsProjectDefault != nil { + toSerialize["isProjectDefault"] = o.IsProjectDefault + } + if o.IsLegacy != nil { + toSerialize["isLegacy"] = o.IsLegacy + } + return json.Marshal(toSerialize) +} + +type NullableCreateReleasePipelineInput struct { + value *CreateReleasePipelineInput + isSet bool +} + +func (v NullableCreateReleasePipelineInput) Get() *CreateReleasePipelineInput { + return v.value +} + +func (v *NullableCreateReleasePipelineInput) Set(val *CreateReleasePipelineInput) { + v.value = val + v.isSet = true +} + +func (v NullableCreateReleasePipelineInput) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateReleasePipelineInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateReleasePipelineInput(val *CreateReleasePipelineInput) *NullableCreateReleasePipelineInput { + return &NullableCreateReleasePipelineInput{value: val, isSet: true} +} + +func (v NullableCreateReleasePipelineInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateReleasePipelineInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_create_workflow_template_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_workflow_template_input.go new file mode 100644 index 00000000..998e5726 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_create_workflow_template_input.go @@ -0,0 +1,361 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CreateWorkflowTemplateInput struct for CreateWorkflowTemplateInput +type CreateWorkflowTemplateInput struct { + Key string `json:"key"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + WorkflowId *string `json:"workflowId,omitempty"` + Stages []StageInput `json:"stages,omitempty"` + ProjectKey *string `json:"projectKey,omitempty"` + EnvironmentKey *string `json:"environmentKey,omitempty"` + FlagKey *string `json:"flagKey,omitempty"` +} + +// NewCreateWorkflowTemplateInput instantiates a new CreateWorkflowTemplateInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCreateWorkflowTemplateInput(key string) *CreateWorkflowTemplateInput { + this := CreateWorkflowTemplateInput{} + this.Key = key + return &this +} + +// NewCreateWorkflowTemplateInputWithDefaults instantiates a new CreateWorkflowTemplateInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCreateWorkflowTemplateInputWithDefaults() *CreateWorkflowTemplateInput { + this := CreateWorkflowTemplateInput{} + return &this +} + +// GetKey returns the Key field value +func (o *CreateWorkflowTemplateInput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *CreateWorkflowTemplateInput) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *CreateWorkflowTemplateInput) SetName(v string) { + o.Name = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CreateWorkflowTemplateInput) SetDescription(v string) { + o.Description = &v +} + +// GetWorkflowId returns the WorkflowId field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetWorkflowId() string { + if o == nil || o.WorkflowId == nil { + var ret string + return ret + } + return *o.WorkflowId +} + +// GetWorkflowIdOk returns a tuple with the WorkflowId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetWorkflowIdOk() (*string, bool) { + if o == nil || o.WorkflowId == nil { + return nil, false + } + return o.WorkflowId, true +} + +// HasWorkflowId returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasWorkflowId() bool { + if o != nil && o.WorkflowId != nil { + return true + } + + return false +} + +// SetWorkflowId gets a reference to the given string and assigns it to the WorkflowId field. +func (o *CreateWorkflowTemplateInput) SetWorkflowId(v string) { + o.WorkflowId = &v +} + +// GetStages returns the Stages field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetStages() []StageInput { + if o == nil || o.Stages == nil { + var ret []StageInput + return ret + } + return o.Stages +} + +// GetStagesOk returns a tuple with the Stages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetStagesOk() ([]StageInput, bool) { + if o == nil || o.Stages == nil { + return nil, false + } + return o.Stages, true +} + +// HasStages returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasStages() bool { + if o != nil && o.Stages != nil { + return true + } + + return false +} + +// SetStages gets a reference to the given []StageInput and assigns it to the Stages field. +func (o *CreateWorkflowTemplateInput) SetStages(v []StageInput) { + o.Stages = v +} + +// GetProjectKey returns the ProjectKey field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetProjectKey() string { + if o == nil || o.ProjectKey == nil { + var ret string + return ret + } + return *o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetProjectKeyOk() (*string, bool) { + if o == nil || o.ProjectKey == nil { + return nil, false + } + return o.ProjectKey, true +} + +// HasProjectKey returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasProjectKey() bool { + if o != nil && o.ProjectKey != nil { + return true + } + + return false +} + +// SetProjectKey gets a reference to the given string and assigns it to the ProjectKey field. +func (o *CreateWorkflowTemplateInput) SetProjectKey(v string) { + o.ProjectKey = &v +} + +// GetEnvironmentKey returns the EnvironmentKey field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetEnvironmentKey() string { + if o == nil || o.EnvironmentKey == nil { + var ret string + return ret + } + return *o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetEnvironmentKeyOk() (*string, bool) { + if o == nil || o.EnvironmentKey == nil { + return nil, false + } + return o.EnvironmentKey, true +} + +// HasEnvironmentKey returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasEnvironmentKey() bool { + if o != nil && o.EnvironmentKey != nil { + return true + } + + return false +} + +// SetEnvironmentKey gets a reference to the given string and assigns it to the EnvironmentKey field. +func (o *CreateWorkflowTemplateInput) SetEnvironmentKey(v string) { + o.EnvironmentKey = &v +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +func (o *CreateWorkflowTemplateInput) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CreateWorkflowTemplateInput) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *CreateWorkflowTemplateInput) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +func (o *CreateWorkflowTemplateInput) SetFlagKey(v string) { + o.FlagKey = &v +} + +func (o CreateWorkflowTemplateInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.WorkflowId != nil { + toSerialize["workflowId"] = o.WorkflowId + } + if o.Stages != nil { + toSerialize["stages"] = o.Stages + } + if o.ProjectKey != nil { + toSerialize["projectKey"] = o.ProjectKey + } + if o.EnvironmentKey != nil { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + return json.Marshal(toSerialize) +} + +type NullableCreateWorkflowTemplateInput struct { + value *CreateWorkflowTemplateInput + isSet bool +} + +func (v NullableCreateWorkflowTemplateInput) Get() *CreateWorkflowTemplateInput { + return v.value +} + +func (v *NullableCreateWorkflowTemplateInput) Set(val *CreateWorkflowTemplateInput) { + v.value = val + v.isSet = true +} + +func (v NullableCreateWorkflowTemplateInput) IsSet() bool { + return v.isSet +} + +func (v *NullableCreateWorkflowTemplateInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCreateWorkflowTemplateInput(val *CreateWorkflowTemplateInput) *NullableCreateWorkflowTemplateInput { + return &NullableCreateWorkflowTemplateInput{value: val, isSet: true} +} + +func (v NullableCreateWorkflowTemplateInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCreateWorkflowTemplateInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_credible_interval_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_credible_interval_rep.go new file mode 100644 index 00000000..33e8cc3e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_credible_interval_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CredibleIntervalRep struct for CredibleIntervalRep +type CredibleIntervalRep struct { + // The upper bound + Upper *float32 `json:"upper,omitempty"` + // The lower bound + Lower *float32 `json:"lower,omitempty"` +} + +// NewCredibleIntervalRep instantiates a new CredibleIntervalRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCredibleIntervalRep() *CredibleIntervalRep { + this := CredibleIntervalRep{} + return &this +} + +// NewCredibleIntervalRepWithDefaults instantiates a new CredibleIntervalRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCredibleIntervalRepWithDefaults() *CredibleIntervalRep { + this := CredibleIntervalRep{} + return &this +} + +// GetUpper returns the Upper field value if set, zero value otherwise. +func (o *CredibleIntervalRep) GetUpper() float32 { + if o == nil || o.Upper == nil { + var ret float32 + return ret + } + return *o.Upper +} + +// GetUpperOk returns a tuple with the Upper field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CredibleIntervalRep) GetUpperOk() (*float32, bool) { + if o == nil || o.Upper == nil { + return nil, false + } + return o.Upper, true +} + +// HasUpper returns a boolean if a field has been set. +func (o *CredibleIntervalRep) HasUpper() bool { + if o != nil && o.Upper != nil { + return true + } + + return false +} + +// SetUpper gets a reference to the given float32 and assigns it to the Upper field. +func (o *CredibleIntervalRep) SetUpper(v float32) { + o.Upper = &v +} + +// GetLower returns the Lower field value if set, zero value otherwise. +func (o *CredibleIntervalRep) GetLower() float32 { + if o == nil || o.Lower == nil { + var ret float32 + return ret + } + return *o.Lower +} + +// GetLowerOk returns a tuple with the Lower field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CredibleIntervalRep) GetLowerOk() (*float32, bool) { + if o == nil || o.Lower == nil { + return nil, false + } + return o.Lower, true +} + +// HasLower returns a boolean if a field has been set. +func (o *CredibleIntervalRep) HasLower() bool { + if o != nil && o.Lower != nil { + return true + } + + return false +} + +// SetLower gets a reference to the given float32 and assigns it to the Lower field. +func (o *CredibleIntervalRep) SetLower(v float32) { + o.Lower = &v +} + +func (o CredibleIntervalRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Upper != nil { + toSerialize["upper"] = o.Upper + } + if o.Lower != nil { + toSerialize["lower"] = o.Lower + } + return json.Marshal(toSerialize) +} + +type NullableCredibleIntervalRep struct { + value *CredibleIntervalRep + isSet bool +} + +func (v NullableCredibleIntervalRep) Get() *CredibleIntervalRep { + return v.value +} + +func (v *NullableCredibleIntervalRep) Set(val *CredibleIntervalRep) { + v.value = val + v.isSet = true +} + +func (v NullableCredibleIntervalRep) IsSet() bool { + return v.isSet +} + +func (v *NullableCredibleIntervalRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCredibleIntervalRep(val *CredibleIntervalRep) *NullableCredibleIntervalRep { + return &NullableCredibleIntervalRep{value: val, isSet: true} +} + +func (v NullableCredibleIntervalRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCredibleIntervalRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_property.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_property.go new file mode 100644 index 00000000..509fae2a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_property.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomProperty struct for CustomProperty +type CustomProperty struct { + // The name of the custom property of this type. + Name string `json:"name"` + // An array of values for the custom property data to associate with this flag. + Value []string `json:"value"` +} + +// NewCustomProperty instantiates a new CustomProperty object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomProperty(name string, value []string) *CustomProperty { + this := CustomProperty{} + this.Name = name + this.Value = value + return &this +} + +// NewCustomPropertyWithDefaults instantiates a new CustomProperty object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomPropertyWithDefaults() *CustomProperty { + this := CustomProperty{} + return &this +} + +// GetName returns the Name field value +func (o *CustomProperty) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CustomProperty) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CustomProperty) SetName(v string) { + o.Name = v +} + +// GetValue returns the Value field value +func (o *CustomProperty) GetValue() []string { + if o == nil { + var ret []string + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *CustomProperty) GetValueOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Value, true +} + +// SetValue sets field value +func (o *CustomProperty) SetValue(v []string) { + o.Value = v +} + +func (o CustomProperty) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableCustomProperty struct { + value *CustomProperty + isSet bool +} + +func (v NullableCustomProperty) Get() *CustomProperty { + return v.value +} + +func (v *NullableCustomProperty) Set(val *CustomProperty) { + v.value = val + v.isSet = true +} + +func (v NullableCustomProperty) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomProperty) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomProperty(val *CustomProperty) *NullableCustomProperty { + return &NullableCustomProperty{value: val, isSet: true} +} + +func (v NullableCustomProperty) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomProperty) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role.go new file mode 100644 index 00000000..bc3609bd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role.go @@ -0,0 +1,485 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomRole struct for CustomRole +type CustomRole struct { + // The ID of the custom role + Id string `json:"_id"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Access *Access `json:"_access,omitempty"` + // The description of the custom role + Description *string `json:"description,omitempty"` + // The key of the custom role + Key string `json:"key"` + // The name of the custom role + Name string `json:"name"` + // An array of the policies that comprise this custom role + Policy []Statement `json:"policy"` + BasePermissions *string `json:"basePermissions,omitempty"` + ResourceCategory *string `json:"resourceCategory,omitempty"` + AssignedTo *AssignedToRep `json:"assignedTo,omitempty"` + // If created from a preset, the preset bundle version + PresetBundleVersion *int32 `json:"_presetBundleVersion,omitempty"` + // If created from a preset, the read-only statements copied from the preset + PresetStatements []Statement `json:"_presetStatements,omitempty"` +} + +// NewCustomRole instantiates a new CustomRole object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomRole(id string, links map[string]Link, key string, name string, policy []Statement) *CustomRole { + this := CustomRole{} + this.Id = id + this.Links = links + this.Key = key + this.Name = name + this.Policy = policy + return &this +} + +// NewCustomRoleWithDefaults instantiates a new CustomRole object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomRoleWithDefaults() *CustomRole { + this := CustomRole{} + return &this +} + +// GetId returns the Id field value +func (o *CustomRole) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *CustomRole) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *CustomRole) SetId(v string) { + o.Id = v +} + +// GetLinks returns the Links field value +func (o *CustomRole) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *CustomRole) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *CustomRole) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *CustomRole) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *CustomRole) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *CustomRole) SetAccess(v Access) { + o.Access = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CustomRole) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CustomRole) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CustomRole) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *CustomRole) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *CustomRole) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *CustomRole) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *CustomRole) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CustomRole) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CustomRole) SetName(v string) { + o.Name = v +} + +// GetPolicy returns the Policy field value +func (o *CustomRole) GetPolicy() []Statement { + if o == nil { + var ret []Statement + return ret + } + + return o.Policy +} + +// GetPolicyOk returns a tuple with the Policy field value +// and a boolean to check if the value has been set. +func (o *CustomRole) GetPolicyOk() ([]Statement, bool) { + if o == nil { + return nil, false + } + return o.Policy, true +} + +// SetPolicy sets field value +func (o *CustomRole) SetPolicy(v []Statement) { + o.Policy = v +} + +// GetBasePermissions returns the BasePermissions field value if set, zero value otherwise. +func (o *CustomRole) GetBasePermissions() string { + if o == nil || o.BasePermissions == nil { + var ret string + return ret + } + return *o.BasePermissions +} + +// GetBasePermissionsOk returns a tuple with the BasePermissions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetBasePermissionsOk() (*string, bool) { + if o == nil || o.BasePermissions == nil { + return nil, false + } + return o.BasePermissions, true +} + +// HasBasePermissions returns a boolean if a field has been set. +func (o *CustomRole) HasBasePermissions() bool { + if o != nil && o.BasePermissions != nil { + return true + } + + return false +} + +// SetBasePermissions gets a reference to the given string and assigns it to the BasePermissions field. +func (o *CustomRole) SetBasePermissions(v string) { + o.BasePermissions = &v +} + +// GetResourceCategory returns the ResourceCategory field value if set, zero value otherwise. +func (o *CustomRole) GetResourceCategory() string { + if o == nil || o.ResourceCategory == nil { + var ret string + return ret + } + return *o.ResourceCategory +} + +// GetResourceCategoryOk returns a tuple with the ResourceCategory field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetResourceCategoryOk() (*string, bool) { + if o == nil || o.ResourceCategory == nil { + return nil, false + } + return o.ResourceCategory, true +} + +// HasResourceCategory returns a boolean if a field has been set. +func (o *CustomRole) HasResourceCategory() bool { + if o != nil && o.ResourceCategory != nil { + return true + } + + return false +} + +// SetResourceCategory gets a reference to the given string and assigns it to the ResourceCategory field. +func (o *CustomRole) SetResourceCategory(v string) { + o.ResourceCategory = &v +} + +// GetAssignedTo returns the AssignedTo field value if set, zero value otherwise. +func (o *CustomRole) GetAssignedTo() AssignedToRep { + if o == nil || o.AssignedTo == nil { + var ret AssignedToRep + return ret + } + return *o.AssignedTo +} + +// GetAssignedToOk returns a tuple with the AssignedTo field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetAssignedToOk() (*AssignedToRep, bool) { + if o == nil || o.AssignedTo == nil { + return nil, false + } + return o.AssignedTo, true +} + +// HasAssignedTo returns a boolean if a field has been set. +func (o *CustomRole) HasAssignedTo() bool { + if o != nil && o.AssignedTo != nil { + return true + } + + return false +} + +// SetAssignedTo gets a reference to the given AssignedToRep and assigns it to the AssignedTo field. +func (o *CustomRole) SetAssignedTo(v AssignedToRep) { + o.AssignedTo = &v +} + +// GetPresetBundleVersion returns the PresetBundleVersion field value if set, zero value otherwise. +func (o *CustomRole) GetPresetBundleVersion() int32 { + if o == nil || o.PresetBundleVersion == nil { + var ret int32 + return ret + } + return *o.PresetBundleVersion +} + +// GetPresetBundleVersionOk returns a tuple with the PresetBundleVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetPresetBundleVersionOk() (*int32, bool) { + if o == nil || o.PresetBundleVersion == nil { + return nil, false + } + return o.PresetBundleVersion, true +} + +// HasPresetBundleVersion returns a boolean if a field has been set. +func (o *CustomRole) HasPresetBundleVersion() bool { + if o != nil && o.PresetBundleVersion != nil { + return true + } + + return false +} + +// SetPresetBundleVersion gets a reference to the given int32 and assigns it to the PresetBundleVersion field. +func (o *CustomRole) SetPresetBundleVersion(v int32) { + o.PresetBundleVersion = &v +} + +// GetPresetStatements returns the PresetStatements field value if set, zero value otherwise. +func (o *CustomRole) GetPresetStatements() []Statement { + if o == nil || o.PresetStatements == nil { + var ret []Statement + return ret + } + return o.PresetStatements +} + +// GetPresetStatementsOk returns a tuple with the PresetStatements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRole) GetPresetStatementsOk() ([]Statement, bool) { + if o == nil || o.PresetStatements == nil { + return nil, false + } + return o.PresetStatements, true +} + +// HasPresetStatements returns a boolean if a field has been set. +func (o *CustomRole) HasPresetStatements() bool { + if o != nil && o.PresetStatements != nil { + return true + } + + return false +} + +// SetPresetStatements gets a reference to the given []Statement and assigns it to the PresetStatements field. +func (o *CustomRole) SetPresetStatements(v []Statement) { + o.PresetStatements = v +} + +func (o CustomRole) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["policy"] = o.Policy + } + if o.BasePermissions != nil { + toSerialize["basePermissions"] = o.BasePermissions + } + if o.ResourceCategory != nil { + toSerialize["resourceCategory"] = o.ResourceCategory + } + if o.AssignedTo != nil { + toSerialize["assignedTo"] = o.AssignedTo + } + if o.PresetBundleVersion != nil { + toSerialize["_presetBundleVersion"] = o.PresetBundleVersion + } + if o.PresetStatements != nil { + toSerialize["_presetStatements"] = o.PresetStatements + } + return json.Marshal(toSerialize) +} + +type NullableCustomRole struct { + value *CustomRole + isSet bool +} + +func (v NullableCustomRole) Get() *CustomRole { + return v.value +} + +func (v *NullableCustomRole) Set(val *CustomRole) { + v.value = val + v.isSet = true +} + +func (v NullableCustomRole) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomRole) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomRole(val *CustomRole) *NullableCustomRole { + return &NullableCustomRole{value: val, isSet: true} +} + +func (v NullableCustomRole) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomRole) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role_post.go new file mode 100644 index 00000000..0068288a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_role_post.go @@ -0,0 +1,278 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomRolePost struct for CustomRolePost +type CustomRolePost struct { + // A human-friendly name for the custom role + Name string `json:"name"` + // The custom role key + Key string `json:"key"` + // Description of custom role + Description *string `json:"description,omitempty"` + Policy []StatementPost `json:"policy"` + BasePermissions *string `json:"basePermissions,omitempty"` + ResourceCategory *string `json:"resourceCategory,omitempty"` +} + +// NewCustomRolePost instantiates a new CustomRolePost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomRolePost(name string, key string, policy []StatementPost) *CustomRolePost { + this := CustomRolePost{} + this.Name = name + this.Key = key + this.Policy = policy + return &this +} + +// NewCustomRolePostWithDefaults instantiates a new CustomRolePost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomRolePostWithDefaults() *CustomRolePost { + this := CustomRolePost{} + return &this +} + +// GetName returns the Name field value +func (o *CustomRolePost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CustomRolePost) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *CustomRolePost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *CustomRolePost) SetKey(v string) { + o.Key = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CustomRolePost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CustomRolePost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CustomRolePost) SetDescription(v string) { + o.Description = &v +} + +// GetPolicy returns the Policy field value +func (o *CustomRolePost) GetPolicy() []StatementPost { + if o == nil { + var ret []StatementPost + return ret + } + + return o.Policy +} + +// GetPolicyOk returns a tuple with the Policy field value +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetPolicyOk() ([]StatementPost, bool) { + if o == nil { + return nil, false + } + return o.Policy, true +} + +// SetPolicy sets field value +func (o *CustomRolePost) SetPolicy(v []StatementPost) { + o.Policy = v +} + +// GetBasePermissions returns the BasePermissions field value if set, zero value otherwise. +func (o *CustomRolePost) GetBasePermissions() string { + if o == nil || o.BasePermissions == nil { + var ret string + return ret + } + return *o.BasePermissions +} + +// GetBasePermissionsOk returns a tuple with the BasePermissions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetBasePermissionsOk() (*string, bool) { + if o == nil || o.BasePermissions == nil { + return nil, false + } + return o.BasePermissions, true +} + +// HasBasePermissions returns a boolean if a field has been set. +func (o *CustomRolePost) HasBasePermissions() bool { + if o != nil && o.BasePermissions != nil { + return true + } + + return false +} + +// SetBasePermissions gets a reference to the given string and assigns it to the BasePermissions field. +func (o *CustomRolePost) SetBasePermissions(v string) { + o.BasePermissions = &v +} + +// GetResourceCategory returns the ResourceCategory field value if set, zero value otherwise. +func (o *CustomRolePost) GetResourceCategory() string { + if o == nil || o.ResourceCategory == nil { + var ret string + return ret + } + return *o.ResourceCategory +} + +// GetResourceCategoryOk returns a tuple with the ResourceCategory field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRolePost) GetResourceCategoryOk() (*string, bool) { + if o == nil || o.ResourceCategory == nil { + return nil, false + } + return o.ResourceCategory, true +} + +// HasResourceCategory returns a boolean if a field has been set. +func (o *CustomRolePost) HasResourceCategory() bool { + if o != nil && o.ResourceCategory != nil { + return true + } + + return false +} + +// SetResourceCategory gets a reference to the given string and assigns it to the ResourceCategory field. +func (o *CustomRolePost) SetResourceCategory(v string) { + o.ResourceCategory = &v +} + +func (o CustomRolePost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["policy"] = o.Policy + } + if o.BasePermissions != nil { + toSerialize["basePermissions"] = o.BasePermissions + } + if o.ResourceCategory != nil { + toSerialize["resourceCategory"] = o.ResourceCategory + } + return json.Marshal(toSerialize) +} + +type NullableCustomRolePost struct { + value *CustomRolePost + isSet bool +} + +func (v NullableCustomRolePost) Get() *CustomRolePost { + return v.value +} + +func (v *NullableCustomRolePost) Set(val *CustomRolePost) { + v.value = val + v.isSet = true +} + +func (v NullableCustomRolePost) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomRolePost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomRolePost(val *CustomRolePost) *NullableCustomRolePost { + return &NullableCustomRolePost{value: val, isSet: true} +} + +func (v NullableCustomRolePost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomRolePost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_roles.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_roles.go new file mode 100644 index 00000000..9a0d89b4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_roles.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomRoles struct for CustomRoles +type CustomRoles struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // An array of custom roles + Items []CustomRole `json:"items"` + // The total number of custom roles + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewCustomRoles instantiates a new CustomRoles object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomRoles(items []CustomRole) *CustomRoles { + this := CustomRoles{} + this.Items = items + return &this +} + +// NewCustomRolesWithDefaults instantiates a new CustomRoles object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomRolesWithDefaults() *CustomRoles { + this := CustomRoles{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *CustomRoles) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRoles) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *CustomRoles) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *CustomRoles) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetItems returns the Items field value +func (o *CustomRoles) GetItems() []CustomRole { + if o == nil { + var ret []CustomRole + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *CustomRoles) GetItemsOk() ([]CustomRole, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *CustomRoles) SetItems(v []CustomRole) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *CustomRoles) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomRoles) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *CustomRoles) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *CustomRoles) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o CustomRoles) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableCustomRoles struct { + value *CustomRoles + isSet bool +} + +func (v NullableCustomRoles) Get() *CustomRoles { + return v.value +} + +func (v *NullableCustomRoles) Set(val *CustomRoles) { + v.value = val + v.isSet = true +} + +func (v NullableCustomRoles) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomRoles) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomRoles(val *CustomRoles) *NullableCustomRoles { + return &NullableCustomRoles{value: val, isSet: true} +} + +func (v NullableCustomRoles) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomRoles) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_input.go new file mode 100644 index 00000000..ed730c07 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_input.go @@ -0,0 +1,257 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomWorkflowInput struct for CustomWorkflowInput +type CustomWorkflowInput struct { + MaintainerId *string `json:"maintainerId,omitempty"` + // The workflow name + Name string `json:"name"` + // The workflow description + Description *string `json:"description,omitempty"` + // A list of the workflow stages + Stages []StageInput `json:"stages,omitempty"` + // The template key + TemplateKey *string `json:"templateKey,omitempty"` +} + +// NewCustomWorkflowInput instantiates a new CustomWorkflowInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomWorkflowInput(name string) *CustomWorkflowInput { + this := CustomWorkflowInput{} + this.Name = name + return &this +} + +// NewCustomWorkflowInputWithDefaults instantiates a new CustomWorkflowInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomWorkflowInputWithDefaults() *CustomWorkflowInput { + this := CustomWorkflowInput{} + return &this +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *CustomWorkflowInput) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowInput) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *CustomWorkflowInput) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *CustomWorkflowInput) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetName returns the Name field value +func (o *CustomWorkflowInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CustomWorkflowInput) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CustomWorkflowInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CustomWorkflowInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CustomWorkflowInput) SetDescription(v string) { + o.Description = &v +} + +// GetStages returns the Stages field value if set, zero value otherwise. +func (o *CustomWorkflowInput) GetStages() []StageInput { + if o == nil || o.Stages == nil { + var ret []StageInput + return ret + } + return o.Stages +} + +// GetStagesOk returns a tuple with the Stages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowInput) GetStagesOk() ([]StageInput, bool) { + if o == nil || o.Stages == nil { + return nil, false + } + return o.Stages, true +} + +// HasStages returns a boolean if a field has been set. +func (o *CustomWorkflowInput) HasStages() bool { + if o != nil && o.Stages != nil { + return true + } + + return false +} + +// SetStages gets a reference to the given []StageInput and assigns it to the Stages field. +func (o *CustomWorkflowInput) SetStages(v []StageInput) { + o.Stages = v +} + +// GetTemplateKey returns the TemplateKey field value if set, zero value otherwise. +func (o *CustomWorkflowInput) GetTemplateKey() string { + if o == nil || o.TemplateKey == nil { + var ret string + return ret + } + return *o.TemplateKey +} + +// GetTemplateKeyOk returns a tuple with the TemplateKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowInput) GetTemplateKeyOk() (*string, bool) { + if o == nil || o.TemplateKey == nil { + return nil, false + } + return o.TemplateKey, true +} + +// HasTemplateKey returns a boolean if a field has been set. +func (o *CustomWorkflowInput) HasTemplateKey() bool { + if o != nil && o.TemplateKey != nil { + return true + } + + return false +} + +// SetTemplateKey gets a reference to the given string and assigns it to the TemplateKey field. +func (o *CustomWorkflowInput) SetTemplateKey(v string) { + o.TemplateKey = &v +} + +func (o CustomWorkflowInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Stages != nil { + toSerialize["stages"] = o.Stages + } + if o.TemplateKey != nil { + toSerialize["templateKey"] = o.TemplateKey + } + return json.Marshal(toSerialize) +} + +type NullableCustomWorkflowInput struct { + value *CustomWorkflowInput + isSet bool +} + +func (v NullableCustomWorkflowInput) Get() *CustomWorkflowInput { + return v.value +} + +func (v *NullableCustomWorkflowInput) Set(val *CustomWorkflowInput) { + v.value = val + v.isSet = true +} + +func (v NullableCustomWorkflowInput) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomWorkflowInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomWorkflowInput(val *CustomWorkflowInput) *NullableCustomWorkflowInput { + return &NullableCustomWorkflowInput{value: val, isSet: true} +} + +func (v NullableCustomWorkflowInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomWorkflowInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_meta.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_meta.go new file mode 100644 index 00000000..48b84263 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_meta.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomWorkflowMeta struct for CustomWorkflowMeta +type CustomWorkflowMeta struct { + // The name of the workflow stage that required this approval request + Name *string `json:"name,omitempty"` + Stage *CustomWorkflowStageMeta `json:"stage,omitempty"` +} + +// NewCustomWorkflowMeta instantiates a new CustomWorkflowMeta object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomWorkflowMeta() *CustomWorkflowMeta { + this := CustomWorkflowMeta{} + return &this +} + +// NewCustomWorkflowMetaWithDefaults instantiates a new CustomWorkflowMeta object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomWorkflowMetaWithDefaults() *CustomWorkflowMeta { + this := CustomWorkflowMeta{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *CustomWorkflowMeta) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowMeta) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *CustomWorkflowMeta) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *CustomWorkflowMeta) SetName(v string) { + o.Name = &v +} + +// GetStage returns the Stage field value if set, zero value otherwise. +func (o *CustomWorkflowMeta) GetStage() CustomWorkflowStageMeta { + if o == nil || o.Stage == nil { + var ret CustomWorkflowStageMeta + return ret + } + return *o.Stage +} + +// GetStageOk returns a tuple with the Stage field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowMeta) GetStageOk() (*CustomWorkflowStageMeta, bool) { + if o == nil || o.Stage == nil { + return nil, false + } + return o.Stage, true +} + +// HasStage returns a boolean if a field has been set. +func (o *CustomWorkflowMeta) HasStage() bool { + if o != nil && o.Stage != nil { + return true + } + + return false +} + +// SetStage gets a reference to the given CustomWorkflowStageMeta and assigns it to the Stage field. +func (o *CustomWorkflowMeta) SetStage(v CustomWorkflowStageMeta) { + o.Stage = &v +} + +func (o CustomWorkflowMeta) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Stage != nil { + toSerialize["stage"] = o.Stage + } + return json.Marshal(toSerialize) +} + +type NullableCustomWorkflowMeta struct { + value *CustomWorkflowMeta + isSet bool +} + +func (v NullableCustomWorkflowMeta) Get() *CustomWorkflowMeta { + return v.value +} + +func (v *NullableCustomWorkflowMeta) Set(val *CustomWorkflowMeta) { + v.value = val + v.isSet = true +} + +func (v NullableCustomWorkflowMeta) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomWorkflowMeta) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomWorkflowMeta(val *CustomWorkflowMeta) *NullableCustomWorkflowMeta { + return &NullableCustomWorkflowMeta{value: val, isSet: true} +} + +func (v NullableCustomWorkflowMeta) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomWorkflowMeta) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_output.go new file mode 100644 index 00000000..989aa790 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_output.go @@ -0,0 +1,502 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomWorkflowOutput struct for CustomWorkflowOutput +type CustomWorkflowOutput struct { + // The ID of the workflow + Id string `json:"_id"` + // The version of the workflow + Version int32 `json:"_version"` + // Any conflicts that are present in the workflow stages + Conflicts []ConflictOutput `json:"_conflicts"` + CreationDate int64 `json:"_creationDate"` + // The member ID of the maintainer of the workflow. Defaults to the workflow creator. + MaintainerId string `json:"_maintainerId"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The name of the workflow + Name string `json:"name"` + // A brief description of the workflow + Description *string `json:"description,omitempty"` + // The kind of workflow + Kind *string `json:"kind,omitempty"` + // The stages that make up the workflow. Each stage contains conditions and actions. + Stages []StageOutput `json:"stages,omitempty"` + Execution ExecutionOutput `json:"_execution"` + Meta *WorkflowTemplateMetadata `json:"meta,omitempty"` + // For workflows being created from a workflow template, this value is the template's key + TemplateKey *string `json:"templateKey,omitempty"` +} + +// NewCustomWorkflowOutput instantiates a new CustomWorkflowOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomWorkflowOutput(id string, version int32, conflicts []ConflictOutput, creationDate int64, maintainerId string, links map[string]Link, name string, execution ExecutionOutput) *CustomWorkflowOutput { + this := CustomWorkflowOutput{} + this.Id = id + this.Version = version + this.Conflicts = conflicts + this.CreationDate = creationDate + this.MaintainerId = maintainerId + this.Links = links + this.Name = name + this.Execution = execution + return &this +} + +// NewCustomWorkflowOutputWithDefaults instantiates a new CustomWorkflowOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomWorkflowOutputWithDefaults() *CustomWorkflowOutput { + this := CustomWorkflowOutput{} + return &this +} + +// GetId returns the Id field value +func (o *CustomWorkflowOutput) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *CustomWorkflowOutput) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *CustomWorkflowOutput) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *CustomWorkflowOutput) SetVersion(v int32) { + o.Version = v +} + +// GetConflicts returns the Conflicts field value +func (o *CustomWorkflowOutput) GetConflicts() []ConflictOutput { + if o == nil { + var ret []ConflictOutput + return ret + } + + return o.Conflicts +} + +// GetConflictsOk returns a tuple with the Conflicts field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetConflictsOk() ([]ConflictOutput, bool) { + if o == nil { + return nil, false + } + return o.Conflicts, true +} + +// SetConflicts sets field value +func (o *CustomWorkflowOutput) SetConflicts(v []ConflictOutput) { + o.Conflicts = v +} + +// GetCreationDate returns the CreationDate field value +func (o *CustomWorkflowOutput) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *CustomWorkflowOutput) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetMaintainerId returns the MaintainerId field value +func (o *CustomWorkflowOutput) GetMaintainerId() string { + if o == nil { + var ret string + return ret + } + + return o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetMaintainerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MaintainerId, true +} + +// SetMaintainerId sets field value +func (o *CustomWorkflowOutput) SetMaintainerId(v string) { + o.MaintainerId = v +} + +// GetLinks returns the Links field value +func (o *CustomWorkflowOutput) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *CustomWorkflowOutput) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetName returns the Name field value +func (o *CustomWorkflowOutput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *CustomWorkflowOutput) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *CustomWorkflowOutput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *CustomWorkflowOutput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *CustomWorkflowOutput) SetDescription(v string) { + o.Description = &v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *CustomWorkflowOutput) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *CustomWorkflowOutput) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *CustomWorkflowOutput) SetKind(v string) { + o.Kind = &v +} + +// GetStages returns the Stages field value if set, zero value otherwise. +func (o *CustomWorkflowOutput) GetStages() []StageOutput { + if o == nil || o.Stages == nil { + var ret []StageOutput + return ret + } + return o.Stages +} + +// GetStagesOk returns a tuple with the Stages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetStagesOk() ([]StageOutput, bool) { + if o == nil || o.Stages == nil { + return nil, false + } + return o.Stages, true +} + +// HasStages returns a boolean if a field has been set. +func (o *CustomWorkflowOutput) HasStages() bool { + if o != nil && o.Stages != nil { + return true + } + + return false +} + +// SetStages gets a reference to the given []StageOutput and assigns it to the Stages field. +func (o *CustomWorkflowOutput) SetStages(v []StageOutput) { + o.Stages = v +} + +// GetExecution returns the Execution field value +func (o *CustomWorkflowOutput) GetExecution() ExecutionOutput { + if o == nil { + var ret ExecutionOutput + return ret + } + + return o.Execution +} + +// GetExecutionOk returns a tuple with the Execution field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetExecutionOk() (*ExecutionOutput, bool) { + if o == nil { + return nil, false + } + return &o.Execution, true +} + +// SetExecution sets field value +func (o *CustomWorkflowOutput) SetExecution(v ExecutionOutput) { + o.Execution = v +} + +// GetMeta returns the Meta field value if set, zero value otherwise. +func (o *CustomWorkflowOutput) GetMeta() WorkflowTemplateMetadata { + if o == nil || o.Meta == nil { + var ret WorkflowTemplateMetadata + return ret + } + return *o.Meta +} + +// GetMetaOk returns a tuple with the Meta field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetMetaOk() (*WorkflowTemplateMetadata, bool) { + if o == nil || o.Meta == nil { + return nil, false + } + return o.Meta, true +} + +// HasMeta returns a boolean if a field has been set. +func (o *CustomWorkflowOutput) HasMeta() bool { + if o != nil && o.Meta != nil { + return true + } + + return false +} + +// SetMeta gets a reference to the given WorkflowTemplateMetadata and assigns it to the Meta field. +func (o *CustomWorkflowOutput) SetMeta(v WorkflowTemplateMetadata) { + o.Meta = &v +} + +// GetTemplateKey returns the TemplateKey field value if set, zero value otherwise. +func (o *CustomWorkflowOutput) GetTemplateKey() string { + if o == nil || o.TemplateKey == nil { + var ret string + return ret + } + return *o.TemplateKey +} + +// GetTemplateKeyOk returns a tuple with the TemplateKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowOutput) GetTemplateKeyOk() (*string, bool) { + if o == nil || o.TemplateKey == nil { + return nil, false + } + return o.TemplateKey, true +} + +// HasTemplateKey returns a boolean if a field has been set. +func (o *CustomWorkflowOutput) HasTemplateKey() bool { + if o != nil && o.TemplateKey != nil { + return true + } + + return false +} + +// SetTemplateKey gets a reference to the given string and assigns it to the TemplateKey field. +func (o *CustomWorkflowOutput) SetTemplateKey(v string) { + o.TemplateKey = &v +} + +func (o CustomWorkflowOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["_conflicts"] = o.Conflicts + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if true { + toSerialize["_maintainerId"] = o.MaintainerId + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Stages != nil { + toSerialize["stages"] = o.Stages + } + if true { + toSerialize["_execution"] = o.Execution + } + if o.Meta != nil { + toSerialize["meta"] = o.Meta + } + if o.TemplateKey != nil { + toSerialize["templateKey"] = o.TemplateKey + } + return json.Marshal(toSerialize) +} + +type NullableCustomWorkflowOutput struct { + value *CustomWorkflowOutput + isSet bool +} + +func (v NullableCustomWorkflowOutput) Get() *CustomWorkflowOutput { + return v.value +} + +func (v *NullableCustomWorkflowOutput) Set(val *CustomWorkflowOutput) { + v.value = val + v.isSet = true +} + +func (v NullableCustomWorkflowOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomWorkflowOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomWorkflowOutput(val *CustomWorkflowOutput) *NullableCustomWorkflowOutput { + return &NullableCustomWorkflowOutput{value: val, isSet: true} +} + +func (v NullableCustomWorkflowOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomWorkflowOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_stage_meta.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_stage_meta.go new file mode 100644 index 00000000..832d5af5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflow_stage_meta.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomWorkflowStageMeta struct for CustomWorkflowStageMeta +type CustomWorkflowStageMeta struct { + // The zero-based index of the workflow stage + Index *int32 `json:"index,omitempty"` + // The name of the workflow stage + Name *string `json:"name,omitempty"` +} + +// NewCustomWorkflowStageMeta instantiates a new CustomWorkflowStageMeta object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomWorkflowStageMeta() *CustomWorkflowStageMeta { + this := CustomWorkflowStageMeta{} + return &this +} + +// NewCustomWorkflowStageMetaWithDefaults instantiates a new CustomWorkflowStageMeta object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomWorkflowStageMetaWithDefaults() *CustomWorkflowStageMeta { + this := CustomWorkflowStageMeta{} + return &this +} + +// GetIndex returns the Index field value if set, zero value otherwise. +func (o *CustomWorkflowStageMeta) GetIndex() int32 { + if o == nil || o.Index == nil { + var ret int32 + return ret + } + return *o.Index +} + +// GetIndexOk returns a tuple with the Index field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowStageMeta) GetIndexOk() (*int32, bool) { + if o == nil || o.Index == nil { + return nil, false + } + return o.Index, true +} + +// HasIndex returns a boolean if a field has been set. +func (o *CustomWorkflowStageMeta) HasIndex() bool { + if o != nil && o.Index != nil { + return true + } + + return false +} + +// SetIndex gets a reference to the given int32 and assigns it to the Index field. +func (o *CustomWorkflowStageMeta) SetIndex(v int32) { + o.Index = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *CustomWorkflowStageMeta) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CustomWorkflowStageMeta) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *CustomWorkflowStageMeta) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *CustomWorkflowStageMeta) SetName(v string) { + o.Name = &v +} + +func (o CustomWorkflowStageMeta) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Index != nil { + toSerialize["index"] = o.Index + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableCustomWorkflowStageMeta struct { + value *CustomWorkflowStageMeta + isSet bool +} + +func (v NullableCustomWorkflowStageMeta) Get() *CustomWorkflowStageMeta { + return v.value +} + +func (v *NullableCustomWorkflowStageMeta) Set(val *CustomWorkflowStageMeta) { + v.value = val + v.isSet = true +} + +func (v NullableCustomWorkflowStageMeta) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomWorkflowStageMeta) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomWorkflowStageMeta(val *CustomWorkflowStageMeta) *NullableCustomWorkflowStageMeta { + return &NullableCustomWorkflowStageMeta{value: val, isSet: true} +} + +func (v NullableCustomWorkflowStageMeta) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomWorkflowStageMeta) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflows_listing_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflows_listing_output.go new file mode 100644 index 00000000..3e9f326e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_custom_workflows_listing_output.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// CustomWorkflowsListingOutput struct for CustomWorkflowsListingOutput +type CustomWorkflowsListingOutput struct { + // An array of workflows + Items []CustomWorkflowOutput `json:"items"` + // Total number of workflows + TotalCount int32 `json:"totalCount"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewCustomWorkflowsListingOutput instantiates a new CustomWorkflowsListingOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCustomWorkflowsListingOutput(items []CustomWorkflowOutput, totalCount int32, links map[string]Link) *CustomWorkflowsListingOutput { + this := CustomWorkflowsListingOutput{} + this.Items = items + this.TotalCount = totalCount + this.Links = links + return &this +} + +// NewCustomWorkflowsListingOutputWithDefaults instantiates a new CustomWorkflowsListingOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCustomWorkflowsListingOutputWithDefaults() *CustomWorkflowsListingOutput { + this := CustomWorkflowsListingOutput{} + return &this +} + +// GetItems returns the Items field value +func (o *CustomWorkflowsListingOutput) GetItems() []CustomWorkflowOutput { + if o == nil { + var ret []CustomWorkflowOutput + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowsListingOutput) GetItemsOk() ([]CustomWorkflowOutput, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *CustomWorkflowsListingOutput) SetItems(v []CustomWorkflowOutput) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *CustomWorkflowsListingOutput) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowsListingOutput) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *CustomWorkflowsListingOutput) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetLinks returns the Links field value +func (o *CustomWorkflowsListingOutput) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *CustomWorkflowsListingOutput) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *CustomWorkflowsListingOutput) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o CustomWorkflowsListingOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableCustomWorkflowsListingOutput struct { + value *CustomWorkflowsListingOutput + isSet bool +} + +func (v NullableCustomWorkflowsListingOutput) Get() *CustomWorkflowsListingOutput { + return v.value +} + +func (v *NullableCustomWorkflowsListingOutput) Set(val *CustomWorkflowsListingOutput) { + v.value = val + v.isSet = true +} + +func (v NullableCustomWorkflowsListingOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableCustomWorkflowsListingOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCustomWorkflowsListingOutput(val *CustomWorkflowsListingOutput) *NullableCustomWorkflowsListingOutput { + return &NullableCustomWorkflowsListingOutput{value: val, isSet: true} +} + +func (v NullableCustomWorkflowsListingOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCustomWorkflowsListingOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability.go new file mode 100644 index 00000000..9795f793 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DefaultClientSideAvailability struct for DefaultClientSideAvailability +type DefaultClientSideAvailability struct { + // Whether to enable availability for mobile SDKs + UsingMobileKey bool `json:"usingMobileKey"` + // Whether to enable availability for client-side SDKs + UsingEnvironmentId bool `json:"usingEnvironmentId"` +} + +// NewDefaultClientSideAvailability instantiates a new DefaultClientSideAvailability object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDefaultClientSideAvailability(usingMobileKey bool, usingEnvironmentId bool) *DefaultClientSideAvailability { + this := DefaultClientSideAvailability{} + this.UsingMobileKey = usingMobileKey + this.UsingEnvironmentId = usingEnvironmentId + return &this +} + +// NewDefaultClientSideAvailabilityWithDefaults instantiates a new DefaultClientSideAvailability object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDefaultClientSideAvailabilityWithDefaults() *DefaultClientSideAvailability { + this := DefaultClientSideAvailability{} + return &this +} + +// GetUsingMobileKey returns the UsingMobileKey field value +func (o *DefaultClientSideAvailability) GetUsingMobileKey() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingMobileKey +} + +// GetUsingMobileKeyOk returns a tuple with the UsingMobileKey field value +// and a boolean to check if the value has been set. +func (o *DefaultClientSideAvailability) GetUsingMobileKeyOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingMobileKey, true +} + +// SetUsingMobileKey sets field value +func (o *DefaultClientSideAvailability) SetUsingMobileKey(v bool) { + o.UsingMobileKey = v +} + +// GetUsingEnvironmentId returns the UsingEnvironmentId field value +func (o *DefaultClientSideAvailability) GetUsingEnvironmentId() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingEnvironmentId +} + +// GetUsingEnvironmentIdOk returns a tuple with the UsingEnvironmentId field value +// and a boolean to check if the value has been set. +func (o *DefaultClientSideAvailability) GetUsingEnvironmentIdOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingEnvironmentId, true +} + +// SetUsingEnvironmentId sets field value +func (o *DefaultClientSideAvailability) SetUsingEnvironmentId(v bool) { + o.UsingEnvironmentId = v +} + +func (o DefaultClientSideAvailability) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["usingMobileKey"] = o.UsingMobileKey + } + if true { + toSerialize["usingEnvironmentId"] = o.UsingEnvironmentId + } + return json.Marshal(toSerialize) +} + +type NullableDefaultClientSideAvailability struct { + value *DefaultClientSideAvailability + isSet bool +} + +func (v NullableDefaultClientSideAvailability) Get() *DefaultClientSideAvailability { + return v.value +} + +func (v *NullableDefaultClientSideAvailability) Set(val *DefaultClientSideAvailability) { + v.value = val + v.isSet = true +} + +func (v NullableDefaultClientSideAvailability) IsSet() bool { + return v.isSet +} + +func (v *NullableDefaultClientSideAvailability) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDefaultClientSideAvailability(val *DefaultClientSideAvailability) *NullableDefaultClientSideAvailability { + return &NullableDefaultClientSideAvailability{value: val, isSet: true} +} + +func (v NullableDefaultClientSideAvailability) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDefaultClientSideAvailability) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability_post.go new file mode 100644 index 00000000..adfa893e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_default_client_side_availability_post.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DefaultClientSideAvailabilityPost struct for DefaultClientSideAvailabilityPost +type DefaultClientSideAvailabilityPost struct { + // Whether to enable availability for client-side SDKs. + UsingEnvironmentId bool `json:"usingEnvironmentId"` + // Whether to enable availability for mobile SDKs. + UsingMobileKey bool `json:"usingMobileKey"` +} + +// NewDefaultClientSideAvailabilityPost instantiates a new DefaultClientSideAvailabilityPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDefaultClientSideAvailabilityPost(usingEnvironmentId bool, usingMobileKey bool) *DefaultClientSideAvailabilityPost { + this := DefaultClientSideAvailabilityPost{} + this.UsingEnvironmentId = usingEnvironmentId + this.UsingMobileKey = usingMobileKey + return &this +} + +// NewDefaultClientSideAvailabilityPostWithDefaults instantiates a new DefaultClientSideAvailabilityPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDefaultClientSideAvailabilityPostWithDefaults() *DefaultClientSideAvailabilityPost { + this := DefaultClientSideAvailabilityPost{} + return &this +} + +// GetUsingEnvironmentId returns the UsingEnvironmentId field value +func (o *DefaultClientSideAvailabilityPost) GetUsingEnvironmentId() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingEnvironmentId +} + +// GetUsingEnvironmentIdOk returns a tuple with the UsingEnvironmentId field value +// and a boolean to check if the value has been set. +func (o *DefaultClientSideAvailabilityPost) GetUsingEnvironmentIdOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingEnvironmentId, true +} + +// SetUsingEnvironmentId sets field value +func (o *DefaultClientSideAvailabilityPost) SetUsingEnvironmentId(v bool) { + o.UsingEnvironmentId = v +} + +// GetUsingMobileKey returns the UsingMobileKey field value +func (o *DefaultClientSideAvailabilityPost) GetUsingMobileKey() bool { + if o == nil { + var ret bool + return ret + } + + return o.UsingMobileKey +} + +// GetUsingMobileKeyOk returns a tuple with the UsingMobileKey field value +// and a boolean to check if the value has been set. +func (o *DefaultClientSideAvailabilityPost) GetUsingMobileKeyOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.UsingMobileKey, true +} + +// SetUsingMobileKey sets field value +func (o *DefaultClientSideAvailabilityPost) SetUsingMobileKey(v bool) { + o.UsingMobileKey = v +} + +func (o DefaultClientSideAvailabilityPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["usingEnvironmentId"] = o.UsingEnvironmentId + } + if true { + toSerialize["usingMobileKey"] = o.UsingMobileKey + } + return json.Marshal(toSerialize) +} + +type NullableDefaultClientSideAvailabilityPost struct { + value *DefaultClientSideAvailabilityPost + isSet bool +} + +func (v NullableDefaultClientSideAvailabilityPost) Get() *DefaultClientSideAvailabilityPost { + return v.value +} + +func (v *NullableDefaultClientSideAvailabilityPost) Set(val *DefaultClientSideAvailabilityPost) { + v.value = val + v.isSet = true +} + +func (v NullableDefaultClientSideAvailabilityPost) IsSet() bool { + return v.isSet +} + +func (v *NullableDefaultClientSideAvailabilityPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDefaultClientSideAvailabilityPost(val *DefaultClientSideAvailabilityPost) *NullableDefaultClientSideAvailabilityPost { + return &NullableDefaultClientSideAvailabilityPost{value: val, isSet: true} +} + +func (v NullableDefaultClientSideAvailabilityPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDefaultClientSideAvailabilityPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_defaults.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_defaults.go new file mode 100644 index 00000000..bbc0867a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_defaults.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Defaults struct for Defaults +type Defaults struct { + // The index, from the array of variations for this flag, of the variation to serve by default when targeting is on. + OnVariation int32 `json:"onVariation"` + // The index, from the array of variations for this flag, of the variation to serve by default when targeting is off. + OffVariation int32 `json:"offVariation"` +} + +// NewDefaults instantiates a new Defaults object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDefaults(onVariation int32, offVariation int32) *Defaults { + this := Defaults{} + this.OnVariation = onVariation + this.OffVariation = offVariation + return &this +} + +// NewDefaultsWithDefaults instantiates a new Defaults object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDefaultsWithDefaults() *Defaults { + this := Defaults{} + return &this +} + +// GetOnVariation returns the OnVariation field value +func (o *Defaults) GetOnVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.OnVariation +} + +// GetOnVariationOk returns a tuple with the OnVariation field value +// and a boolean to check if the value has been set. +func (o *Defaults) GetOnVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.OnVariation, true +} + +// SetOnVariation sets field value +func (o *Defaults) SetOnVariation(v int32) { + o.OnVariation = v +} + +// GetOffVariation returns the OffVariation field value +func (o *Defaults) GetOffVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.OffVariation +} + +// GetOffVariationOk returns a tuple with the OffVariation field value +// and a boolean to check if the value has been set. +func (o *Defaults) GetOffVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.OffVariation, true +} + +// SetOffVariation sets field value +func (o *Defaults) SetOffVariation(v int32) { + o.OffVariation = v +} + +func (o Defaults) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["onVariation"] = o.OnVariation + } + if true { + toSerialize["offVariation"] = o.OffVariation + } + return json.Marshal(toSerialize) +} + +type NullableDefaults struct { + value *Defaults + isSet bool +} + +func (v NullableDefaults) Get() *Defaults { + return v.value +} + +func (v *NullableDefaults) Set(val *Defaults) { + v.value = val + v.isSet = true +} + +func (v NullableDefaults) IsSet() bool { + return v.isSet +} + +func (v *NullableDefaults) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDefaults(val *Defaults) *NullableDefaults { + return &NullableDefaults{value: val, isSet: true} +} + +func (v NullableDefaults) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDefaults) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_experiment_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_experiment_rep.go new file mode 100644 index 00000000..f87d3214 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_experiment_rep.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentExperimentRep struct for DependentExperimentRep +type DependentExperimentRep struct { + // The experiment key + Key string `json:"key"` + // The experiment name + Name string `json:"name"` + // The environment ID + EnvironmentId string `json:"environmentId"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + CreationDate int64 `json:"creationDate"` + ArchivedDate *int64 `json:"archivedDate,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewDependentExperimentRep instantiates a new DependentExperimentRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentExperimentRep(key string, name string, environmentId string, environmentKey string, creationDate int64, links map[string]Link) *DependentExperimentRep { + this := DependentExperimentRep{} + this.Key = key + this.Name = name + this.EnvironmentId = environmentId + this.EnvironmentKey = environmentKey + this.CreationDate = creationDate + this.Links = links + return &this +} + +// NewDependentExperimentRepWithDefaults instantiates a new DependentExperimentRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentExperimentRepWithDefaults() *DependentExperimentRep { + this := DependentExperimentRep{} + return &this +} + +// GetKey returns the Key field value +func (o *DependentExperimentRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentExperimentRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *DependentExperimentRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *DependentExperimentRep) SetName(v string) { + o.Name = v +} + +// GetEnvironmentId returns the EnvironmentId field value +func (o *DependentExperimentRep) GetEnvironmentId() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetEnvironmentIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentId, true +} + +// SetEnvironmentId sets field value +func (o *DependentExperimentRep) SetEnvironmentId(v string) { + o.EnvironmentId = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *DependentExperimentRep) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *DependentExperimentRep) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetCreationDate returns the CreationDate field value +func (o *DependentExperimentRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *DependentExperimentRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetArchivedDate returns the ArchivedDate field value if set, zero value otherwise. +func (o *DependentExperimentRep) GetArchivedDate() int64 { + if o == nil || o.ArchivedDate == nil { + var ret int64 + return ret + } + return *o.ArchivedDate +} + +// GetArchivedDateOk returns a tuple with the ArchivedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetArchivedDateOk() (*int64, bool) { + if o == nil || o.ArchivedDate == nil { + return nil, false + } + return o.ArchivedDate, true +} + +// HasArchivedDate returns a boolean if a field has been set. +func (o *DependentExperimentRep) HasArchivedDate() bool { + if o != nil && o.ArchivedDate != nil { + return true + } + + return false +} + +// SetArchivedDate gets a reference to the given int64 and assigns it to the ArchivedDate field. +func (o *DependentExperimentRep) SetArchivedDate(v int64) { + o.ArchivedDate = &v +} + +// GetLinks returns the Links field value +func (o *DependentExperimentRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentExperimentRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentExperimentRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o DependentExperimentRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["environmentId"] = o.EnvironmentId + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if o.ArchivedDate != nil { + toSerialize["archivedDate"] = o.ArchivedDate + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableDependentExperimentRep struct { + value *DependentExperimentRep + isSet bool +} + +func (v NullableDependentExperimentRep) Get() *DependentExperimentRep { + return v.value +} + +func (v *NullableDependentExperimentRep) Set(val *DependentExperimentRep) { + v.value = val + v.isSet = true +} + +func (v NullableDependentExperimentRep) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentExperimentRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentExperimentRep(val *DependentExperimentRep) *NullableDependentExperimentRep { + return &NullableDependentExperimentRep{value: val, isSet: true} +} + +func (v NullableDependentExperimentRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentExperimentRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag.go new file mode 100644 index 00000000..35c28dec --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag.go @@ -0,0 +1,206 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentFlag struct for DependentFlag +type DependentFlag struct { + // The flag name + Name *string `json:"name,omitempty"` + // The flag key + Key string `json:"key"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site Link `json:"_site"` +} + +// NewDependentFlag instantiates a new DependentFlag object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentFlag(key string, links map[string]Link, site Link) *DependentFlag { + this := DependentFlag{} + this.Key = key + this.Links = links + this.Site = site + return &this +} + +// NewDependentFlagWithDefaults instantiates a new DependentFlag object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentFlagWithDefaults() *DependentFlag { + this := DependentFlag{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *DependentFlag) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentFlag) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *DependentFlag) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *DependentFlag) SetName(v string) { + o.Name = &v +} + +// GetKey returns the Key field value +func (o *DependentFlag) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentFlag) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentFlag) SetKey(v string) { + o.Key = v +} + +// GetLinks returns the Links field value +func (o *DependentFlag) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentFlag) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentFlag) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value +func (o *DependentFlag) GetSite() Link { + if o == nil { + var ret Link + return ret + } + + return o.Site +} + +// GetSiteOk returns a tuple with the Site field value +// and a boolean to check if the value has been set. +func (o *DependentFlag) GetSiteOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Site, true +} + +// SetSite sets field value +func (o *DependentFlag) SetSite(v Link) { + o.Site = v +} + +func (o DependentFlag) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_site"] = o.Site + } + return json.Marshal(toSerialize) +} + +type NullableDependentFlag struct { + value *DependentFlag + isSet bool +} + +func (v NullableDependentFlag) Get() *DependentFlag { + return v.value +} + +func (v *NullableDependentFlag) Set(val *DependentFlag) { + v.value = val + v.isSet = true +} + +func (v NullableDependentFlag) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentFlag) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentFlag(val *DependentFlag) *NullableDependentFlag { + return &NullableDependentFlag{value: val, isSet: true} +} + +func (v NullableDependentFlag) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentFlag) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag_environment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag_environment.go new file mode 100644 index 00000000..f4f5712c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flag_environment.go @@ -0,0 +1,206 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentFlagEnvironment struct for DependentFlagEnvironment +type DependentFlagEnvironment struct { + // The environment name + Name *string `json:"name,omitempty"` + // The environment key + Key string `json:"key"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site Link `json:"_site"` +} + +// NewDependentFlagEnvironment instantiates a new DependentFlagEnvironment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentFlagEnvironment(key string, links map[string]Link, site Link) *DependentFlagEnvironment { + this := DependentFlagEnvironment{} + this.Key = key + this.Links = links + this.Site = site + return &this +} + +// NewDependentFlagEnvironmentWithDefaults instantiates a new DependentFlagEnvironment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentFlagEnvironmentWithDefaults() *DependentFlagEnvironment { + this := DependentFlagEnvironment{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *DependentFlagEnvironment) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentFlagEnvironment) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *DependentFlagEnvironment) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *DependentFlagEnvironment) SetName(v string) { + o.Name = &v +} + +// GetKey returns the Key field value +func (o *DependentFlagEnvironment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentFlagEnvironment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentFlagEnvironment) SetKey(v string) { + o.Key = v +} + +// GetLinks returns the Links field value +func (o *DependentFlagEnvironment) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentFlagEnvironment) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentFlagEnvironment) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value +func (o *DependentFlagEnvironment) GetSite() Link { + if o == nil { + var ret Link + return ret + } + + return o.Site +} + +// GetSiteOk returns a tuple with the Site field value +// and a boolean to check if the value has been set. +func (o *DependentFlagEnvironment) GetSiteOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Site, true +} + +// SetSite sets field value +func (o *DependentFlagEnvironment) SetSite(v Link) { + o.Site = v +} + +func (o DependentFlagEnvironment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_site"] = o.Site + } + return json.Marshal(toSerialize) +} + +type NullableDependentFlagEnvironment struct { + value *DependentFlagEnvironment + isSet bool +} + +func (v NullableDependentFlagEnvironment) Get() *DependentFlagEnvironment { + return v.value +} + +func (v *NullableDependentFlagEnvironment) Set(val *DependentFlagEnvironment) { + v.value = val + v.isSet = true +} + +func (v NullableDependentFlagEnvironment) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentFlagEnvironment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentFlagEnvironment(val *DependentFlagEnvironment) *NullableDependentFlagEnvironment { + return &NullableDependentFlagEnvironment{value: val, isSet: true} +} + +func (v NullableDependentFlagEnvironment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentFlagEnvironment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flags_by_environment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flags_by_environment.go new file mode 100644 index 00000000..faf3626a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_flags_by_environment.go @@ -0,0 +1,169 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentFlagsByEnvironment struct for DependentFlagsByEnvironment +type DependentFlagsByEnvironment struct { + // A list of dependent flags, which are flags that use the requested flag as a prerequisite + Items []DependentFlag `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site Link `json:"_site"` +} + +// NewDependentFlagsByEnvironment instantiates a new DependentFlagsByEnvironment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentFlagsByEnvironment(items []DependentFlag, links map[string]Link, site Link) *DependentFlagsByEnvironment { + this := DependentFlagsByEnvironment{} + this.Items = items + this.Links = links + this.Site = site + return &this +} + +// NewDependentFlagsByEnvironmentWithDefaults instantiates a new DependentFlagsByEnvironment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentFlagsByEnvironmentWithDefaults() *DependentFlagsByEnvironment { + this := DependentFlagsByEnvironment{} + return &this +} + +// GetItems returns the Items field value +func (o *DependentFlagsByEnvironment) GetItems() []DependentFlag { + if o == nil { + var ret []DependentFlag + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *DependentFlagsByEnvironment) GetItemsOk() ([]DependentFlag, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *DependentFlagsByEnvironment) SetItems(v []DependentFlag) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *DependentFlagsByEnvironment) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentFlagsByEnvironment) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentFlagsByEnvironment) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value +func (o *DependentFlagsByEnvironment) GetSite() Link { + if o == nil { + var ret Link + return ret + } + + return o.Site +} + +// GetSiteOk returns a tuple with the Site field value +// and a boolean to check if the value has been set. +func (o *DependentFlagsByEnvironment) GetSiteOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Site, true +} + +// SetSite sets field value +func (o *DependentFlagsByEnvironment) SetSite(v Link) { + o.Site = v +} + +func (o DependentFlagsByEnvironment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_site"] = o.Site + } + return json.Marshal(toSerialize) +} + +type NullableDependentFlagsByEnvironment struct { + value *DependentFlagsByEnvironment + isSet bool +} + +func (v NullableDependentFlagsByEnvironment) Get() *DependentFlagsByEnvironment { + return v.value +} + +func (v *NullableDependentFlagsByEnvironment) Set(val *DependentFlagsByEnvironment) { + v.value = val + v.isSet = true +} + +func (v NullableDependentFlagsByEnvironment) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentFlagsByEnvironment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentFlagsByEnvironment(val *DependentFlagsByEnvironment) *NullableDependentFlagsByEnvironment { + return &NullableDependentFlagsByEnvironment{value: val, isSet: true} +} + +func (v NullableDependentFlagsByEnvironment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentFlagsByEnvironment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep.go new file mode 100644 index 00000000..5f607b9c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentMetricGroupRep struct for DependentMetricGroupRep +type DependentMetricGroupRep struct { + // A unique key to reference the metric group + Key string `json:"key"` + // A human-friendly name for the metric group + Name string `json:"name"` + // The type of the metric group + Kind string `json:"kind"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewDependentMetricGroupRep instantiates a new DependentMetricGroupRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentMetricGroupRep(key string, name string, kind string, links map[string]Link) *DependentMetricGroupRep { + this := DependentMetricGroupRep{} + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + return &this +} + +// NewDependentMetricGroupRepWithDefaults instantiates a new DependentMetricGroupRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentMetricGroupRepWithDefaults() *DependentMetricGroupRep { + this := DependentMetricGroupRep{} + return &this +} + +// GetKey returns the Key field value +func (o *DependentMetricGroupRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentMetricGroupRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *DependentMetricGroupRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *DependentMetricGroupRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *DependentMetricGroupRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *DependentMetricGroupRep) SetKind(v string) { + o.Kind = v +} + +// GetLinks returns the Links field value +func (o *DependentMetricGroupRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentMetricGroupRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o DependentMetricGroupRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableDependentMetricGroupRep struct { + value *DependentMetricGroupRep + isSet bool +} + +func (v NullableDependentMetricGroupRep) Get() *DependentMetricGroupRep { + return v.value +} + +func (v *NullableDependentMetricGroupRep) Set(val *DependentMetricGroupRep) { + v.value = val + v.isSet = true +} + +func (v NullableDependentMetricGroupRep) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentMetricGroupRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentMetricGroupRep(val *DependentMetricGroupRep) *NullableDependentMetricGroupRep { + return &NullableDependentMetricGroupRep{value: val, isSet: true} +} + +func (v NullableDependentMetricGroupRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentMetricGroupRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep_with_metrics.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep_with_metrics.go new file mode 100644 index 00000000..be70962b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_group_rep_with_metrics.go @@ -0,0 +1,237 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentMetricGroupRepWithMetrics struct for DependentMetricGroupRepWithMetrics +type DependentMetricGroupRepWithMetrics struct { + // A unique key to reference the metric group + Key string `json:"key"` + // A human-friendly name for the metric group + Name string `json:"name"` + // The type of the metric group + Kind string `json:"kind"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The metrics in the metric group + Metrics []MetricInGroupRep `json:"metrics,omitempty"` +} + +// NewDependentMetricGroupRepWithMetrics instantiates a new DependentMetricGroupRepWithMetrics object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentMetricGroupRepWithMetrics(key string, name string, kind string, links map[string]Link) *DependentMetricGroupRepWithMetrics { + this := DependentMetricGroupRepWithMetrics{} + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + return &this +} + +// NewDependentMetricGroupRepWithMetricsWithDefaults instantiates a new DependentMetricGroupRepWithMetrics object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentMetricGroupRepWithMetricsWithDefaults() *DependentMetricGroupRepWithMetrics { + this := DependentMetricGroupRepWithMetrics{} + return &this +} + +// GetKey returns the Key field value +func (o *DependentMetricGroupRepWithMetrics) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRepWithMetrics) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentMetricGroupRepWithMetrics) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *DependentMetricGroupRepWithMetrics) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRepWithMetrics) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *DependentMetricGroupRepWithMetrics) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *DependentMetricGroupRepWithMetrics) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRepWithMetrics) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *DependentMetricGroupRepWithMetrics) SetKind(v string) { + o.Kind = v +} + +// GetLinks returns the Links field value +func (o *DependentMetricGroupRepWithMetrics) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRepWithMetrics) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentMetricGroupRepWithMetrics) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *DependentMetricGroupRepWithMetrics) GetMetrics() []MetricInGroupRep { + if o == nil || o.Metrics == nil { + var ret []MetricInGroupRep + return ret + } + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentMetricGroupRepWithMetrics) GetMetricsOk() ([]MetricInGroupRep, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *DependentMetricGroupRepWithMetrics) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given []MetricInGroupRep and assigns it to the Metrics field. +func (o *DependentMetricGroupRepWithMetrics) SetMetrics(v []MetricInGroupRep) { + o.Metrics = v +} + +func (o DependentMetricGroupRepWithMetrics) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["_links"] = o.Links + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + return json.Marshal(toSerialize) +} + +type NullableDependentMetricGroupRepWithMetrics struct { + value *DependentMetricGroupRepWithMetrics + isSet bool +} + +func (v NullableDependentMetricGroupRepWithMetrics) Get() *DependentMetricGroupRepWithMetrics { + return v.value +} + +func (v *NullableDependentMetricGroupRepWithMetrics) Set(val *DependentMetricGroupRepWithMetrics) { + v.value = val + v.isSet = true +} + +func (v NullableDependentMetricGroupRepWithMetrics) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentMetricGroupRepWithMetrics) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentMetricGroupRepWithMetrics(val *DependentMetricGroupRepWithMetrics) *NullableDependentMetricGroupRepWithMetrics { + return &NullableDependentMetricGroupRepWithMetrics{value: val, isSet: true} +} + +func (v NullableDependentMetricGroupRepWithMetrics) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentMetricGroupRepWithMetrics) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_or_metric_group_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_or_metric_group_rep.go new file mode 100644 index 00000000..002ea97b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dependent_metric_or_metric_group_rep.go @@ -0,0 +1,334 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DependentMetricOrMetricGroupRep struct for DependentMetricOrMetricGroupRep +type DependentMetricOrMetricGroupRep struct { + // A unique key to reference the metric or metric group + Key string `json:"key"` + // The version ID of the metric or metric group + VersionId string `json:"_versionId"` + // A human-friendly name for the metric or metric group + Name string `json:"name"` + // If this is a metric, then it represents the kind of event the metric tracks. If this is a metric group, then it represents the group type + Kind string `json:"kind"` + // For custom metrics, whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). + IsNumeric *bool `json:"isNumeric,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // Whether this is a metric group or a metric + IsGroup bool `json:"isGroup"` + // An ordered list of the metrics in this metric group + Metrics []MetricInGroupRep `json:"metrics,omitempty"` +} + +// NewDependentMetricOrMetricGroupRep instantiates a new DependentMetricOrMetricGroupRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDependentMetricOrMetricGroupRep(key string, versionId string, name string, kind string, links map[string]Link, isGroup bool) *DependentMetricOrMetricGroupRep { + this := DependentMetricOrMetricGroupRep{} + this.Key = key + this.VersionId = versionId + this.Name = name + this.Kind = kind + this.Links = links + this.IsGroup = isGroup + return &this +} + +// NewDependentMetricOrMetricGroupRepWithDefaults instantiates a new DependentMetricOrMetricGroupRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDependentMetricOrMetricGroupRepWithDefaults() *DependentMetricOrMetricGroupRep { + this := DependentMetricOrMetricGroupRep{} + return &this +} + +// GetKey returns the Key field value +func (o *DependentMetricOrMetricGroupRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *DependentMetricOrMetricGroupRep) SetKey(v string) { + o.Key = v +} + +// GetVersionId returns the VersionId field value +func (o *DependentMetricOrMetricGroupRep) GetVersionId() string { + if o == nil { + var ret string + return ret + } + + return o.VersionId +} + +// GetVersionIdOk returns a tuple with the VersionId field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetVersionIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VersionId, true +} + +// SetVersionId sets field value +func (o *DependentMetricOrMetricGroupRep) SetVersionId(v string) { + o.VersionId = v +} + +// GetName returns the Name field value +func (o *DependentMetricOrMetricGroupRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *DependentMetricOrMetricGroupRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *DependentMetricOrMetricGroupRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *DependentMetricOrMetricGroupRep) SetKind(v string) { + o.Kind = v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *DependentMetricOrMetricGroupRep) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *DependentMetricOrMetricGroupRep) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *DependentMetricOrMetricGroupRep) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetLinks returns the Links field value +func (o *DependentMetricOrMetricGroupRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *DependentMetricOrMetricGroupRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetIsGroup returns the IsGroup field value +func (o *DependentMetricOrMetricGroupRep) GetIsGroup() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsGroup +} + +// GetIsGroupOk returns a tuple with the IsGroup field value +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetIsGroupOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsGroup, true +} + +// SetIsGroup sets field value +func (o *DependentMetricOrMetricGroupRep) SetIsGroup(v bool) { + o.IsGroup = v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *DependentMetricOrMetricGroupRep) GetMetrics() []MetricInGroupRep { + if o == nil || o.Metrics == nil { + var ret []MetricInGroupRep + return ret + } + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DependentMetricOrMetricGroupRep) GetMetricsOk() ([]MetricInGroupRep, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *DependentMetricOrMetricGroupRep) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given []MetricInGroupRep and assigns it to the Metrics field. +func (o *DependentMetricOrMetricGroupRep) SetMetrics(v []MetricInGroupRep) { + o.Metrics = v +} + +func (o DependentMetricOrMetricGroupRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_versionId"] = o.VersionId + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["isGroup"] = o.IsGroup + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + return json.Marshal(toSerialize) +} + +type NullableDependentMetricOrMetricGroupRep struct { + value *DependentMetricOrMetricGroupRep + isSet bool +} + +func (v NullableDependentMetricOrMetricGroupRep) Get() *DependentMetricOrMetricGroupRep { + return v.value +} + +func (v *NullableDependentMetricOrMetricGroupRep) Set(val *DependentMetricOrMetricGroupRep) { + v.value = val + v.isSet = true +} + +func (v NullableDependentMetricOrMetricGroupRep) IsSet() bool { + return v.isSet +} + +func (v *NullableDependentMetricOrMetricGroupRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDependentMetricOrMetricGroupRep(val *DependentMetricOrMetricGroupRep) *NullableDependentMetricOrMetricGroupRep { + return &NullableDependentMetricOrMetricGroupRep{value: val, isSet: true} +} + +func (v NullableDependentMetricOrMetricGroupRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDependentMetricOrMetricGroupRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_collection_rep.go new file mode 100644 index 00000000..23f944ea --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_collection_rep.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DeploymentCollectionRep struct for DeploymentCollectionRep +type DeploymentCollectionRep struct { + // The total number of deployments + TotalCount int32 `json:"totalCount"` + // A list of deployments + Items []DeploymentRep `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewDeploymentCollectionRep instantiates a new DeploymentCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDeploymentCollectionRep(totalCount int32, items []DeploymentRep) *DeploymentCollectionRep { + this := DeploymentCollectionRep{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewDeploymentCollectionRepWithDefaults instantiates a new DeploymentCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDeploymentCollectionRepWithDefaults() *DeploymentCollectionRep { + this := DeploymentCollectionRep{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *DeploymentCollectionRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *DeploymentCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *DeploymentCollectionRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *DeploymentCollectionRep) GetItems() []DeploymentRep { + if o == nil { + var ret []DeploymentRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *DeploymentCollectionRep) GetItemsOk() ([]DeploymentRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *DeploymentCollectionRep) SetItems(v []DeploymentRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *DeploymentCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *DeploymentCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *DeploymentCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o DeploymentCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableDeploymentCollectionRep struct { + value *DeploymentCollectionRep + isSet bool +} + +func (v NullableDeploymentCollectionRep) Get() *DeploymentCollectionRep { + return v.value +} + +func (v *NullableDeploymentCollectionRep) Set(val *DeploymentCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableDeploymentCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableDeploymentCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDeploymentCollectionRep(val *DeploymentCollectionRep) *NullableDeploymentCollectionRep { + return &NullableDeploymentCollectionRep{value: val, isSet: true} +} + +func (v NullableDeploymentCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDeploymentCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_rep.go new file mode 100644 index 00000000..72ddf395 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_deployment_rep.go @@ -0,0 +1,715 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DeploymentRep struct for DeploymentRep +type DeploymentRep struct { + // The deployment ID + Id string `json:"id"` + // The application key + ApplicationKey string `json:"applicationKey"` + // The application version + ApplicationVersion string `json:"applicationVersion"` + StartedAt int64 `json:"startedAt"` + EndedAt *int64 `json:"endedAt,omitempty"` + // The duration of the deployment in milliseconds + DurationMs *int64 `json:"durationMs,omitempty"` + Status string `json:"status"` + Kind string `json:"kind"` + // Whether the deployment is active + Active bool `json:"active"` + // The metadata associated with the deployment + Metadata map[string]interface{} `json:"metadata,omitempty"` + // Whether the deployment is archived + Archived bool `json:"archived"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + // The number of contributors + NumberOfContributors int32 `json:"numberOfContributors"` + // The number of pull requests + NumberOfPullRequests int32 `json:"numberOfPullRequests"` + // The number of lines added + LinesAdded int64 `json:"linesAdded"` + // The number of lines deleted + LinesDeleted int64 `json:"linesDeleted"` + // The total lead time from first commit to deployment end in milliseconds + LeadTime int64 `json:"leadTime"` + PullRequests *PullRequestCollectionRep `json:"pullRequests,omitempty"` + FlagReferences *FlagReferenceCollectionRep `json:"flagReferences,omitempty"` + LeadTimeStages *LeadTimeStagesRep `json:"leadTimeStages,omitempty"` +} + +// NewDeploymentRep instantiates a new DeploymentRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDeploymentRep(id string, applicationKey string, applicationVersion string, startedAt int64, status string, kind string, active bool, archived bool, environmentKey string, numberOfContributors int32, numberOfPullRequests int32, linesAdded int64, linesDeleted int64, leadTime int64) *DeploymentRep { + this := DeploymentRep{} + this.Id = id + this.ApplicationKey = applicationKey + this.ApplicationVersion = applicationVersion + this.StartedAt = startedAt + this.Status = status + this.Kind = kind + this.Active = active + this.Archived = archived + this.EnvironmentKey = environmentKey + this.NumberOfContributors = numberOfContributors + this.NumberOfPullRequests = numberOfPullRequests + this.LinesAdded = linesAdded + this.LinesDeleted = linesDeleted + this.LeadTime = leadTime + return &this +} + +// NewDeploymentRepWithDefaults instantiates a new DeploymentRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDeploymentRepWithDefaults() *DeploymentRep { + this := DeploymentRep{} + return &this +} + +// GetId returns the Id field value +func (o *DeploymentRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *DeploymentRep) SetId(v string) { + o.Id = v +} + +// GetApplicationKey returns the ApplicationKey field value +func (o *DeploymentRep) GetApplicationKey() string { + if o == nil { + var ret string + return ret + } + + return o.ApplicationKey +} + +// GetApplicationKeyOk returns a tuple with the ApplicationKey field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetApplicationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ApplicationKey, true +} + +// SetApplicationKey sets field value +func (o *DeploymentRep) SetApplicationKey(v string) { + o.ApplicationKey = v +} + +// GetApplicationVersion returns the ApplicationVersion field value +func (o *DeploymentRep) GetApplicationVersion() string { + if o == nil { + var ret string + return ret + } + + return o.ApplicationVersion +} + +// GetApplicationVersionOk returns a tuple with the ApplicationVersion field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetApplicationVersionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ApplicationVersion, true +} + +// SetApplicationVersion sets field value +func (o *DeploymentRep) SetApplicationVersion(v string) { + o.ApplicationVersion = v +} + +// GetStartedAt returns the StartedAt field value +func (o *DeploymentRep) GetStartedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.StartedAt +} + +// GetStartedAtOk returns a tuple with the StartedAt field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetStartedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.StartedAt, true +} + +// SetStartedAt sets field value +func (o *DeploymentRep) SetStartedAt(v int64) { + o.StartedAt = v +} + +// GetEndedAt returns the EndedAt field value if set, zero value otherwise. +func (o *DeploymentRep) GetEndedAt() int64 { + if o == nil || o.EndedAt == nil { + var ret int64 + return ret + } + return *o.EndedAt +} + +// GetEndedAtOk returns a tuple with the EndedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetEndedAtOk() (*int64, bool) { + if o == nil || o.EndedAt == nil { + return nil, false + } + return o.EndedAt, true +} + +// HasEndedAt returns a boolean if a field has been set. +func (o *DeploymentRep) HasEndedAt() bool { + if o != nil && o.EndedAt != nil { + return true + } + + return false +} + +// SetEndedAt gets a reference to the given int64 and assigns it to the EndedAt field. +func (o *DeploymentRep) SetEndedAt(v int64) { + o.EndedAt = &v +} + +// GetDurationMs returns the DurationMs field value if set, zero value otherwise. +func (o *DeploymentRep) GetDurationMs() int64 { + if o == nil || o.DurationMs == nil { + var ret int64 + return ret + } + return *o.DurationMs +} + +// GetDurationMsOk returns a tuple with the DurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetDurationMsOk() (*int64, bool) { + if o == nil || o.DurationMs == nil { + return nil, false + } + return o.DurationMs, true +} + +// HasDurationMs returns a boolean if a field has been set. +func (o *DeploymentRep) HasDurationMs() bool { + if o != nil && o.DurationMs != nil { + return true + } + + return false +} + +// SetDurationMs gets a reference to the given int64 and assigns it to the DurationMs field. +func (o *DeploymentRep) SetDurationMs(v int64) { + o.DurationMs = &v +} + +// GetStatus returns the Status field value +func (o *DeploymentRep) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *DeploymentRep) SetStatus(v string) { + o.Status = v +} + +// GetKind returns the Kind field value +func (o *DeploymentRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *DeploymentRep) SetKind(v string) { + o.Kind = v +} + +// GetActive returns the Active field value +func (o *DeploymentRep) GetActive() bool { + if o == nil { + var ret bool + return ret + } + + return o.Active +} + +// GetActiveOk returns a tuple with the Active field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetActiveOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Active, true +} + +// SetActive sets field value +func (o *DeploymentRep) SetActive(v bool) { + o.Active = v +} + +// GetMetadata returns the Metadata field value if set, zero value otherwise. +func (o *DeploymentRep) GetMetadata() map[string]interface{} { + if o == nil || o.Metadata == nil { + var ret map[string]interface{} + return ret + } + return o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetMetadataOk() (map[string]interface{}, bool) { + if o == nil || o.Metadata == nil { + return nil, false + } + return o.Metadata, true +} + +// HasMetadata returns a boolean if a field has been set. +func (o *DeploymentRep) HasMetadata() bool { + if o != nil && o.Metadata != nil { + return true + } + + return false +} + +// SetMetadata gets a reference to the given map[string]interface{} and assigns it to the Metadata field. +func (o *DeploymentRep) SetMetadata(v map[string]interface{}) { + o.Metadata = v +} + +// GetArchived returns the Archived field value +func (o *DeploymentRep) GetArchived() bool { + if o == nil { + var ret bool + return ret + } + + return o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetArchivedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Archived, true +} + +// SetArchived sets field value +func (o *DeploymentRep) SetArchived(v bool) { + o.Archived = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *DeploymentRep) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *DeploymentRep) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetNumberOfContributors returns the NumberOfContributors field value +func (o *DeploymentRep) GetNumberOfContributors() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.NumberOfContributors +} + +// GetNumberOfContributorsOk returns a tuple with the NumberOfContributors field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetNumberOfContributorsOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.NumberOfContributors, true +} + +// SetNumberOfContributors sets field value +func (o *DeploymentRep) SetNumberOfContributors(v int32) { + o.NumberOfContributors = v +} + +// GetNumberOfPullRequests returns the NumberOfPullRequests field value +func (o *DeploymentRep) GetNumberOfPullRequests() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.NumberOfPullRequests +} + +// GetNumberOfPullRequestsOk returns a tuple with the NumberOfPullRequests field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetNumberOfPullRequestsOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.NumberOfPullRequests, true +} + +// SetNumberOfPullRequests sets field value +func (o *DeploymentRep) SetNumberOfPullRequests(v int32) { + o.NumberOfPullRequests = v +} + +// GetLinesAdded returns the LinesAdded field value +func (o *DeploymentRep) GetLinesAdded() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LinesAdded +} + +// GetLinesAddedOk returns a tuple with the LinesAdded field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetLinesAddedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LinesAdded, true +} + +// SetLinesAdded sets field value +func (o *DeploymentRep) SetLinesAdded(v int64) { + o.LinesAdded = v +} + +// GetLinesDeleted returns the LinesDeleted field value +func (o *DeploymentRep) GetLinesDeleted() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LinesDeleted +} + +// GetLinesDeletedOk returns a tuple with the LinesDeleted field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetLinesDeletedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LinesDeleted, true +} + +// SetLinesDeleted sets field value +func (o *DeploymentRep) SetLinesDeleted(v int64) { + o.LinesDeleted = v +} + +// GetLeadTime returns the LeadTime field value +func (o *DeploymentRep) GetLeadTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LeadTime +} + +// GetLeadTimeOk returns a tuple with the LeadTime field value +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetLeadTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LeadTime, true +} + +// SetLeadTime sets field value +func (o *DeploymentRep) SetLeadTime(v int64) { + o.LeadTime = v +} + +// GetPullRequests returns the PullRequests field value if set, zero value otherwise. +func (o *DeploymentRep) GetPullRequests() PullRequestCollectionRep { + if o == nil || o.PullRequests == nil { + var ret PullRequestCollectionRep + return ret + } + return *o.PullRequests +} + +// GetPullRequestsOk returns a tuple with the PullRequests field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetPullRequestsOk() (*PullRequestCollectionRep, bool) { + if o == nil || o.PullRequests == nil { + return nil, false + } + return o.PullRequests, true +} + +// HasPullRequests returns a boolean if a field has been set. +func (o *DeploymentRep) HasPullRequests() bool { + if o != nil && o.PullRequests != nil { + return true + } + + return false +} + +// SetPullRequests gets a reference to the given PullRequestCollectionRep and assigns it to the PullRequests field. +func (o *DeploymentRep) SetPullRequests(v PullRequestCollectionRep) { + o.PullRequests = &v +} + +// GetFlagReferences returns the FlagReferences field value if set, zero value otherwise. +func (o *DeploymentRep) GetFlagReferences() FlagReferenceCollectionRep { + if o == nil || o.FlagReferences == nil { + var ret FlagReferenceCollectionRep + return ret + } + return *o.FlagReferences +} + +// GetFlagReferencesOk returns a tuple with the FlagReferences field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetFlagReferencesOk() (*FlagReferenceCollectionRep, bool) { + if o == nil || o.FlagReferences == nil { + return nil, false + } + return o.FlagReferences, true +} + +// HasFlagReferences returns a boolean if a field has been set. +func (o *DeploymentRep) HasFlagReferences() bool { + if o != nil && o.FlagReferences != nil { + return true + } + + return false +} + +// SetFlagReferences gets a reference to the given FlagReferenceCollectionRep and assigns it to the FlagReferences field. +func (o *DeploymentRep) SetFlagReferences(v FlagReferenceCollectionRep) { + o.FlagReferences = &v +} + +// GetLeadTimeStages returns the LeadTimeStages field value if set, zero value otherwise. +func (o *DeploymentRep) GetLeadTimeStages() LeadTimeStagesRep { + if o == nil || o.LeadTimeStages == nil { + var ret LeadTimeStagesRep + return ret + } + return *o.LeadTimeStages +} + +// GetLeadTimeStagesOk returns a tuple with the LeadTimeStages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DeploymentRep) GetLeadTimeStagesOk() (*LeadTimeStagesRep, bool) { + if o == nil || o.LeadTimeStages == nil { + return nil, false + } + return o.LeadTimeStages, true +} + +// HasLeadTimeStages returns a boolean if a field has been set. +func (o *DeploymentRep) HasLeadTimeStages() bool { + if o != nil && o.LeadTimeStages != nil { + return true + } + + return false +} + +// SetLeadTimeStages gets a reference to the given LeadTimeStagesRep and assigns it to the LeadTimeStages field. +func (o *DeploymentRep) SetLeadTimeStages(v LeadTimeStagesRep) { + o.LeadTimeStages = &v +} + +func (o DeploymentRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["applicationKey"] = o.ApplicationKey + } + if true { + toSerialize["applicationVersion"] = o.ApplicationVersion + } + if true { + toSerialize["startedAt"] = o.StartedAt + } + if o.EndedAt != nil { + toSerialize["endedAt"] = o.EndedAt + } + if o.DurationMs != nil { + toSerialize["durationMs"] = o.DurationMs + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["active"] = o.Active + } + if o.Metadata != nil { + toSerialize["metadata"] = o.Metadata + } + if true { + toSerialize["archived"] = o.Archived + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["numberOfContributors"] = o.NumberOfContributors + } + if true { + toSerialize["numberOfPullRequests"] = o.NumberOfPullRequests + } + if true { + toSerialize["linesAdded"] = o.LinesAdded + } + if true { + toSerialize["linesDeleted"] = o.LinesDeleted + } + if true { + toSerialize["leadTime"] = o.LeadTime + } + if o.PullRequests != nil { + toSerialize["pullRequests"] = o.PullRequests + } + if o.FlagReferences != nil { + toSerialize["flagReferences"] = o.FlagReferences + } + if o.LeadTimeStages != nil { + toSerialize["leadTimeStages"] = o.LeadTimeStages + } + return json.Marshal(toSerialize) +} + +type NullableDeploymentRep struct { + value *DeploymentRep + isSet bool +} + +func (v NullableDeploymentRep) Get() *DeploymentRep { + return v.value +} + +func (v *NullableDeploymentRep) Set(val *DeploymentRep) { + v.value = val + v.isSet = true +} + +func (v NullableDeploymentRep) IsSet() bool { + return v.isSet +} + +func (v *NullableDeploymentRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDeploymentRep(val *DeploymentRep) *NullableDeploymentRep { + return &NullableDeploymentRep{value: val, isSet: true} +} + +func (v NullableDeploymentRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDeploymentRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_destination.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_destination.go new file mode 100644 index 00000000..b6a7e8e7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_destination.go @@ -0,0 +1,375 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Destination struct for Destination +type Destination struct { + // The ID of this Data Export destination + Id *string `json:"_id,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // A human-readable name for your Data Export destination + Name *string `json:"name,omitempty"` + // The type of Data Export destination + Kind *string `json:"kind,omitempty"` + Version *float32 `json:"version,omitempty"` + // An object with the configuration parameters required for the destination type + Config interface{} `json:"config,omitempty"` + // Whether the export is on, that is, the status of the integration + On *bool `json:"on,omitempty"` + Access *Access `json:"_access,omitempty"` +} + +// NewDestination instantiates a new Destination object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDestination() *Destination { + this := Destination{} + return &this +} + +// NewDestinationWithDefaults instantiates a new Destination object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDestinationWithDefaults() *Destination { + this := Destination{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Destination) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Destination) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Destination) SetId(v string) { + o.Id = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Destination) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Destination) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Destination) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Destination) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Destination) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Destination) SetName(v string) { + o.Name = &v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *Destination) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *Destination) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *Destination) SetKind(v string) { + o.Kind = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *Destination) GetVersion() float32 { + if o == nil || o.Version == nil { + var ret float32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetVersionOk() (*float32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *Destination) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given float32 and assigns it to the Version field. +func (o *Destination) SetVersion(v float32) { + o.Version = &v +} + +// GetConfig returns the Config field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *Destination) GetConfig() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *Destination) GetConfigOk() (*interface{}, bool) { + if o == nil || o.Config == nil { + return nil, false + } + return &o.Config, true +} + +// HasConfig returns a boolean if a field has been set. +func (o *Destination) HasConfig() bool { + if o != nil && o.Config != nil { + return true + } + + return false +} + +// SetConfig gets a reference to the given interface{} and assigns it to the Config field. +func (o *Destination) SetConfig(v interface{}) { + o.Config = v +} + +// GetOn returns the On field value if set, zero value otherwise. +func (o *Destination) GetOn() bool { + if o == nil || o.On == nil { + var ret bool + return ret + } + return *o.On +} + +// GetOnOk returns a tuple with the On field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetOnOk() (*bool, bool) { + if o == nil || o.On == nil { + return nil, false + } + return o.On, true +} + +// HasOn returns a boolean if a field has been set. +func (o *Destination) HasOn() bool { + if o != nil && o.On != nil { + return true + } + + return false +} + +// SetOn gets a reference to the given bool and assigns it to the On field. +func (o *Destination) SetOn(v bool) { + o.On = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *Destination) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destination) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *Destination) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *Destination) SetAccess(v Access) { + o.Access = &v +} + +func (o Destination) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + if o.Config != nil { + toSerialize["config"] = o.Config + } + if o.On != nil { + toSerialize["on"] = o.On + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableDestination struct { + value *Destination + isSet bool +} + +func (v NullableDestination) Get() *Destination { + return v.value +} + +func (v *NullableDestination) Set(val *Destination) { + v.value = val + v.isSet = true +} + +func (v NullableDestination) IsSet() bool { + return v.isSet +} + +func (v *NullableDestination) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDestination(val *Destination) *NullableDestination { + return &NullableDestination{value: val, isSet: true} +} + +func (v NullableDestination) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDestination) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_destination_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_destination_post.go new file mode 100644 index 00000000..82ab11f6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_destination_post.go @@ -0,0 +1,229 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DestinationPost struct for DestinationPost +type DestinationPost struct { + // A human-readable name for your Data Export destination + Name *string `json:"name,omitempty"` + // The type of Data Export destination + Kind *string `json:"kind,omitempty"` + // An object with the configuration parameters required for the destination type + Config interface{} `json:"config,omitempty"` + // Whether the export is on. Displayed as the integration status in the LaunchDarkly UI. + On *bool `json:"on,omitempty"` +} + +// NewDestinationPost instantiates a new DestinationPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDestinationPost() *DestinationPost { + this := DestinationPost{} + return &this +} + +// NewDestinationPostWithDefaults instantiates a new DestinationPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDestinationPostWithDefaults() *DestinationPost { + this := DestinationPost{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *DestinationPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DestinationPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *DestinationPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *DestinationPost) SetName(v string) { + o.Name = &v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *DestinationPost) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DestinationPost) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *DestinationPost) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *DestinationPost) SetKind(v string) { + o.Kind = &v +} + +// GetConfig returns the Config field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *DestinationPost) GetConfig() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *DestinationPost) GetConfigOk() (*interface{}, bool) { + if o == nil || o.Config == nil { + return nil, false + } + return &o.Config, true +} + +// HasConfig returns a boolean if a field has been set. +func (o *DestinationPost) HasConfig() bool { + if o != nil && o.Config != nil { + return true + } + + return false +} + +// SetConfig gets a reference to the given interface{} and assigns it to the Config field. +func (o *DestinationPost) SetConfig(v interface{}) { + o.Config = v +} + +// GetOn returns the On field value if set, zero value otherwise. +func (o *DestinationPost) GetOn() bool { + if o == nil || o.On == nil { + var ret bool + return ret + } + return *o.On +} + +// GetOnOk returns a tuple with the On field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DestinationPost) GetOnOk() (*bool, bool) { + if o == nil || o.On == nil { + return nil, false + } + return o.On, true +} + +// HasOn returns a boolean if a field has been set. +func (o *DestinationPost) HasOn() bool { + if o != nil && o.On != nil { + return true + } + + return false +} + +// SetOn gets a reference to the given bool and assigns it to the On field. +func (o *DestinationPost) SetOn(v bool) { + o.On = &v +} + +func (o DestinationPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Config != nil { + toSerialize["config"] = o.Config + } + if o.On != nil { + toSerialize["on"] = o.On + } + return json.Marshal(toSerialize) +} + +type NullableDestinationPost struct { + value *DestinationPost + isSet bool +} + +func (v NullableDestinationPost) Get() *DestinationPost { + return v.value +} + +func (v *NullableDestinationPost) Set(val *DestinationPost) { + v.value = val + v.isSet = true +} + +func (v NullableDestinationPost) IsSet() bool { + return v.isSet +} + +func (v *NullableDestinationPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDestinationPost(val *DestinationPost) *NullableDestinationPost { + return &NullableDestinationPost{value: val, isSet: true} +} + +func (v NullableDestinationPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDestinationPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_destinations.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_destinations.go new file mode 100644 index 00000000..e5a96f8e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_destinations.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Destinations struct for Destinations +type Destinations struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // An array of Data Export destinations + Items []Destination `json:"items,omitempty"` +} + +// NewDestinations instantiates a new Destinations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDestinations() *Destinations { + this := Destinations{} + return &this +} + +// NewDestinationsWithDefaults instantiates a new Destinations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDestinationsWithDefaults() *Destinations { + this := Destinations{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Destinations) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destinations) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Destinations) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Destinations) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *Destinations) GetItems() []Destination { + if o == nil || o.Items == nil { + var ret []Destination + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Destinations) GetItemsOk() ([]Destination, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *Destinations) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []Destination and assigns it to the Items field. +func (o *Destinations) SetItems(v []Destination) { + o.Items = v +} + +func (o Destinations) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableDestinations struct { + value *Destinations + isSet bool +} + +func (v NullableDestinations) Get() *Destinations { + return v.value +} + +func (v *NullableDestinations) Set(val *Destinations) { + v.value = val + v.isSet = true +} + +func (v NullableDestinations) IsSet() bool { + return v.isSet +} + +func (v *NullableDestinations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDestinations(val *Destinations) *NullableDestinations { + return &NullableDestinations{value: val, isSet: true} +} + +func (v NullableDestinations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDestinations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_distribution.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_distribution.go new file mode 100644 index 00000000..d9781cd8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_distribution.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Distribution struct for Distribution +type Distribution struct { + // The type of distribution. + Kind *string `json:"kind,omitempty"` + // The parameters of the distribution. The parameters are different for each distribution type. When kind is normal, the parameters of the distribution are 'mu' and 'sigma'. When kind is beta, the parameters of the distribution are 'alpha' and 'beta.' + Parameters *map[string]float32 `json:"parameters,omitempty"` +} + +// NewDistribution instantiates a new Distribution object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDistribution() *Distribution { + this := Distribution{} + return &this +} + +// NewDistributionWithDefaults instantiates a new Distribution object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDistributionWithDefaults() *Distribution { + this := Distribution{} + return &this +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *Distribution) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Distribution) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *Distribution) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *Distribution) SetKind(v string) { + o.Kind = &v +} + +// GetParameters returns the Parameters field value if set, zero value otherwise. +func (o *Distribution) GetParameters() map[string]float32 { + if o == nil || o.Parameters == nil { + var ret map[string]float32 + return ret + } + return *o.Parameters +} + +// GetParametersOk returns a tuple with the Parameters field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Distribution) GetParametersOk() (*map[string]float32, bool) { + if o == nil || o.Parameters == nil { + return nil, false + } + return o.Parameters, true +} + +// HasParameters returns a boolean if a field has been set. +func (o *Distribution) HasParameters() bool { + if o != nil && o.Parameters != nil { + return true + } + + return false +} + +// SetParameters gets a reference to the given map[string]float32 and assigns it to the Parameters field. +func (o *Distribution) SetParameters(v map[string]float32) { + o.Parameters = &v +} + +func (o Distribution) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Parameters != nil { + toSerialize["parameters"] = o.Parameters + } + return json.Marshal(toSerialize) +} + +type NullableDistribution struct { + value *Distribution + isSet bool +} + +func (v NullableDistribution) Get() *Distribution { + return v.value +} + +func (v *NullableDistribution) Set(val *Distribution) { + v.value = val + v.isSet = true +} + +func (v NullableDistribution) IsSet() bool { + return v.isSet +} + +func (v *NullableDistribution) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDistribution(val *Distribution) *NullableDistribution { + return &NullableDistribution{value: val, isSet: true} +} + +func (v NullableDistribution) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDistribution) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options.go new file mode 100644 index 00000000..f80b2aed --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DynamicOptions struct for DynamicOptions +type DynamicOptions struct { + Endpoint *Endpoint `json:"endpoint,omitempty"` + Parser *DynamicOptionsParser `json:"parser,omitempty"` +} + +// NewDynamicOptions instantiates a new DynamicOptions object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDynamicOptions() *DynamicOptions { + this := DynamicOptions{} + return &this +} + +// NewDynamicOptionsWithDefaults instantiates a new DynamicOptions object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDynamicOptionsWithDefaults() *DynamicOptions { + this := DynamicOptions{} + return &this +} + +// GetEndpoint returns the Endpoint field value if set, zero value otherwise. +func (o *DynamicOptions) GetEndpoint() Endpoint { + if o == nil || o.Endpoint == nil { + var ret Endpoint + return ret + } + return *o.Endpoint +} + +// GetEndpointOk returns a tuple with the Endpoint field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DynamicOptions) GetEndpointOk() (*Endpoint, bool) { + if o == nil || o.Endpoint == nil { + return nil, false + } + return o.Endpoint, true +} + +// HasEndpoint returns a boolean if a field has been set. +func (o *DynamicOptions) HasEndpoint() bool { + if o != nil && o.Endpoint != nil { + return true + } + + return false +} + +// SetEndpoint gets a reference to the given Endpoint and assigns it to the Endpoint field. +func (o *DynamicOptions) SetEndpoint(v Endpoint) { + o.Endpoint = &v +} + +// GetParser returns the Parser field value if set, zero value otherwise. +func (o *DynamicOptions) GetParser() DynamicOptionsParser { + if o == nil || o.Parser == nil { + var ret DynamicOptionsParser + return ret + } + return *o.Parser +} + +// GetParserOk returns a tuple with the Parser field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DynamicOptions) GetParserOk() (*DynamicOptionsParser, bool) { + if o == nil || o.Parser == nil { + return nil, false + } + return o.Parser, true +} + +// HasParser returns a boolean if a field has been set. +func (o *DynamicOptions) HasParser() bool { + if o != nil && o.Parser != nil { + return true + } + + return false +} + +// SetParser gets a reference to the given DynamicOptionsParser and assigns it to the Parser field. +func (o *DynamicOptions) SetParser(v DynamicOptionsParser) { + o.Parser = &v +} + +func (o DynamicOptions) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Endpoint != nil { + toSerialize["endpoint"] = o.Endpoint + } + if o.Parser != nil { + toSerialize["parser"] = o.Parser + } + return json.Marshal(toSerialize) +} + +type NullableDynamicOptions struct { + value *DynamicOptions + isSet bool +} + +func (v NullableDynamicOptions) Get() *DynamicOptions { + return v.value +} + +func (v *NullableDynamicOptions) Set(val *DynamicOptions) { + v.value = val + v.isSet = true +} + +func (v NullableDynamicOptions) IsSet() bool { + return v.isSet +} + +func (v *NullableDynamicOptions) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDynamicOptions(val *DynamicOptions) *NullableDynamicOptions { + return &NullableDynamicOptions{value: val, isSet: true} +} + +func (v NullableDynamicOptions) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDynamicOptions) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options_parser.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options_parser.go new file mode 100644 index 00000000..07844963 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_dynamic_options_parser.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// DynamicOptionsParser struct for DynamicOptionsParser +type DynamicOptionsParser struct { + OptionsItems *OptionsArray `json:"optionsItems,omitempty"` + OptionsPath *string `json:"optionsPath,omitempty"` +} + +// NewDynamicOptionsParser instantiates a new DynamicOptionsParser object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewDynamicOptionsParser() *DynamicOptionsParser { + this := DynamicOptionsParser{} + return &this +} + +// NewDynamicOptionsParserWithDefaults instantiates a new DynamicOptionsParser object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewDynamicOptionsParserWithDefaults() *DynamicOptionsParser { + this := DynamicOptionsParser{} + return &this +} + +// GetOptionsItems returns the OptionsItems field value if set, zero value otherwise. +func (o *DynamicOptionsParser) GetOptionsItems() OptionsArray { + if o == nil || o.OptionsItems == nil { + var ret OptionsArray + return ret + } + return *o.OptionsItems +} + +// GetOptionsItemsOk returns a tuple with the OptionsItems field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DynamicOptionsParser) GetOptionsItemsOk() (*OptionsArray, bool) { + if o == nil || o.OptionsItems == nil { + return nil, false + } + return o.OptionsItems, true +} + +// HasOptionsItems returns a boolean if a field has been set. +func (o *DynamicOptionsParser) HasOptionsItems() bool { + if o != nil && o.OptionsItems != nil { + return true + } + + return false +} + +// SetOptionsItems gets a reference to the given OptionsArray and assigns it to the OptionsItems field. +func (o *DynamicOptionsParser) SetOptionsItems(v OptionsArray) { + o.OptionsItems = &v +} + +// GetOptionsPath returns the OptionsPath field value if set, zero value otherwise. +func (o *DynamicOptionsParser) GetOptionsPath() string { + if o == nil || o.OptionsPath == nil { + var ret string + return ret + } + return *o.OptionsPath +} + +// GetOptionsPathOk returns a tuple with the OptionsPath field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DynamicOptionsParser) GetOptionsPathOk() (*string, bool) { + if o == nil || o.OptionsPath == nil { + return nil, false + } + return o.OptionsPath, true +} + +// HasOptionsPath returns a boolean if a field has been set. +func (o *DynamicOptionsParser) HasOptionsPath() bool { + if o != nil && o.OptionsPath != nil { + return true + } + + return false +} + +// SetOptionsPath gets a reference to the given string and assigns it to the OptionsPath field. +func (o *DynamicOptionsParser) SetOptionsPath(v string) { + o.OptionsPath = &v +} + +func (o DynamicOptionsParser) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.OptionsItems != nil { + toSerialize["optionsItems"] = o.OptionsItems + } + if o.OptionsPath != nil { + toSerialize["optionsPath"] = o.OptionsPath + } + return json.Marshal(toSerialize) +} + +type NullableDynamicOptionsParser struct { + value *DynamicOptionsParser + isSet bool +} + +func (v NullableDynamicOptionsParser) Get() *DynamicOptionsParser { + return v.value +} + +func (v *NullableDynamicOptionsParser) Set(val *DynamicOptionsParser) { + v.value = val + v.isSet = true +} + +func (v NullableDynamicOptionsParser) IsSet() bool { + return v.isSet +} + +func (v *NullableDynamicOptionsParser) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableDynamicOptionsParser(val *DynamicOptionsParser) *NullableDynamicOptionsParser { + return &NullableDynamicOptionsParser{value: val, isSet: true} +} + +func (v NullableDynamicOptionsParser) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableDynamicOptionsParser) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_endpoint.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_endpoint.go new file mode 100644 index 00000000..cdf96dd2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_endpoint.go @@ -0,0 +1,224 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Endpoint struct for Endpoint +type Endpoint struct { + Headers []HeaderItems `json:"headers,omitempty"` + HmacSignature *HMACSignature `json:"hmacSignature,omitempty"` + Method *string `json:"method,omitempty"` + Url *string `json:"url,omitempty"` +} + +// NewEndpoint instantiates a new Endpoint object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEndpoint() *Endpoint { + this := Endpoint{} + return &this +} + +// NewEndpointWithDefaults instantiates a new Endpoint object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEndpointWithDefaults() *Endpoint { + this := Endpoint{} + return &this +} + +// GetHeaders returns the Headers field value if set, zero value otherwise. +func (o *Endpoint) GetHeaders() []HeaderItems { + if o == nil || o.Headers == nil { + var ret []HeaderItems + return ret + } + return o.Headers +} + +// GetHeadersOk returns a tuple with the Headers field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Endpoint) GetHeadersOk() ([]HeaderItems, bool) { + if o == nil || o.Headers == nil { + return nil, false + } + return o.Headers, true +} + +// HasHeaders returns a boolean if a field has been set. +func (o *Endpoint) HasHeaders() bool { + if o != nil && o.Headers != nil { + return true + } + + return false +} + +// SetHeaders gets a reference to the given []HeaderItems and assigns it to the Headers field. +func (o *Endpoint) SetHeaders(v []HeaderItems) { + o.Headers = v +} + +// GetHmacSignature returns the HmacSignature field value if set, zero value otherwise. +func (o *Endpoint) GetHmacSignature() HMACSignature { + if o == nil || o.HmacSignature == nil { + var ret HMACSignature + return ret + } + return *o.HmacSignature +} + +// GetHmacSignatureOk returns a tuple with the HmacSignature field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Endpoint) GetHmacSignatureOk() (*HMACSignature, bool) { + if o == nil || o.HmacSignature == nil { + return nil, false + } + return o.HmacSignature, true +} + +// HasHmacSignature returns a boolean if a field has been set. +func (o *Endpoint) HasHmacSignature() bool { + if o != nil && o.HmacSignature != nil { + return true + } + + return false +} + +// SetHmacSignature gets a reference to the given HMACSignature and assigns it to the HmacSignature field. +func (o *Endpoint) SetHmacSignature(v HMACSignature) { + o.HmacSignature = &v +} + +// GetMethod returns the Method field value if set, zero value otherwise. +func (o *Endpoint) GetMethod() string { + if o == nil || o.Method == nil { + var ret string + return ret + } + return *o.Method +} + +// GetMethodOk returns a tuple with the Method field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Endpoint) GetMethodOk() (*string, bool) { + if o == nil || o.Method == nil { + return nil, false + } + return o.Method, true +} + +// HasMethod returns a boolean if a field has been set. +func (o *Endpoint) HasMethod() bool { + if o != nil && o.Method != nil { + return true + } + + return false +} + +// SetMethod gets a reference to the given string and assigns it to the Method field. +func (o *Endpoint) SetMethod(v string) { + o.Method = &v +} + +// GetUrl returns the Url field value if set, zero value otherwise. +func (o *Endpoint) GetUrl() string { + if o == nil || o.Url == nil { + var ret string + return ret + } + return *o.Url +} + +// GetUrlOk returns a tuple with the Url field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Endpoint) GetUrlOk() (*string, bool) { + if o == nil || o.Url == nil { + return nil, false + } + return o.Url, true +} + +// HasUrl returns a boolean if a field has been set. +func (o *Endpoint) HasUrl() bool { + if o != nil && o.Url != nil { + return true + } + + return false +} + +// SetUrl gets a reference to the given string and assigns it to the Url field. +func (o *Endpoint) SetUrl(v string) { + o.Url = &v +} + +func (o Endpoint) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Headers != nil { + toSerialize["headers"] = o.Headers + } + if o.HmacSignature != nil { + toSerialize["hmacSignature"] = o.HmacSignature + } + if o.Method != nil { + toSerialize["method"] = o.Method + } + if o.Url != nil { + toSerialize["url"] = o.Url + } + return json.Marshal(toSerialize) +} + +type NullableEndpoint struct { + value *Endpoint + isSet bool +} + +func (v NullableEndpoint) Get() *Endpoint { + return v.value +} + +func (v *NullableEndpoint) Set(val *Endpoint) { + v.value = val + v.isSet = true +} + +func (v NullableEndpoint) IsSet() bool { + return v.isSet +} + +func (v *NullableEndpoint) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEndpoint(val *Endpoint) *NullableEndpoint { + return &NullableEndpoint{value: val, isSet: true} +} + +func (v NullableEndpoint) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEndpoint) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_environment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment.go new file mode 100644 index 00000000..e4d8cef1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment.go @@ -0,0 +1,573 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Environment struct for Environment +type Environment struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID for the environment. Use this as the client-side ID for authorization in some client-side SDKs, and to associate LaunchDarkly environments with CDN integrations in edge SDKs. + Id string `json:"_id"` + // A project-unique key for the new environment + Key string `json:"key"` + // A human-friendly name for the new environment + Name string `json:"name"` + // The SDK key for the environment. Use this for authorization in server-side SDKs. + ApiKey string `json:"apiKey"` + // The mobile key for the environment. Use this for authorization in mobile SDKs. + MobileKey string `json:"mobileKey"` + // The color used to indicate this environment in the UI + Color string `json:"color"` + // The default time (in minutes) that the PHP SDK can cache feature flag rules locally + DefaultTtl int32 `json:"defaultTtl"` + // Ensures that one end user of the client-side SDK cannot inspect the variations for another end user + SecureMode bool `json:"secureMode"` + // Enables tracking detailed information for new flags by default + DefaultTrackEvents bool `json:"defaultTrackEvents"` + // Whether members who modify flags and segments through the LaunchDarkly user interface are required to add a comment + RequireComments bool `json:"requireComments"` + // Whether members who modify flags and segments through the LaunchDarkly user interface are required to confirm those changes + ConfirmChanges bool `json:"confirmChanges"` + // A list of tags for this environment + Tags []string `json:"tags"` + ApprovalSettings *ApprovalSettings `json:"approvalSettings,omitempty"` + // Details on the approval settings for this environment for each resource kind + ResourceApprovalSettings *map[string]ApprovalSettings `json:"resourceApprovalSettings,omitempty"` + // Whether the environment is critical + Critical bool `json:"critical"` +} + +// NewEnvironment instantiates a new Environment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEnvironment(links map[string]Link, id string, key string, name string, apiKey string, mobileKey string, color string, defaultTtl int32, secureMode bool, defaultTrackEvents bool, requireComments bool, confirmChanges bool, tags []string, critical bool) *Environment { + this := Environment{} + this.Links = links + this.Id = id + this.Key = key + this.Name = name + this.ApiKey = apiKey + this.MobileKey = mobileKey + this.Color = color + this.DefaultTtl = defaultTtl + this.SecureMode = secureMode + this.DefaultTrackEvents = defaultTrackEvents + this.RequireComments = requireComments + this.ConfirmChanges = confirmChanges + this.Tags = tags + this.Critical = critical + return &this +} + +// NewEnvironmentWithDefaults instantiates a new Environment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEnvironmentWithDefaults() *Environment { + this := Environment{} + return &this +} + +// GetLinks returns the Links field value +func (o *Environment) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Environment) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Environment) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *Environment) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Environment) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Environment) SetId(v string) { + o.Id = v +} + +// GetKey returns the Key field value +func (o *Environment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *Environment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *Environment) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *Environment) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Environment) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Environment) SetName(v string) { + o.Name = v +} + +// GetApiKey returns the ApiKey field value +func (o *Environment) GetApiKey() string { + if o == nil { + var ret string + return ret + } + + return o.ApiKey +} + +// GetApiKeyOk returns a tuple with the ApiKey field value +// and a boolean to check if the value has been set. +func (o *Environment) GetApiKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ApiKey, true +} + +// SetApiKey sets field value +func (o *Environment) SetApiKey(v string) { + o.ApiKey = v +} + +// GetMobileKey returns the MobileKey field value +func (o *Environment) GetMobileKey() string { + if o == nil { + var ret string + return ret + } + + return o.MobileKey +} + +// GetMobileKeyOk returns a tuple with the MobileKey field value +// and a boolean to check if the value has been set. +func (o *Environment) GetMobileKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MobileKey, true +} + +// SetMobileKey sets field value +func (o *Environment) SetMobileKey(v string) { + o.MobileKey = v +} + +// GetColor returns the Color field value +func (o *Environment) GetColor() string { + if o == nil { + var ret string + return ret + } + + return o.Color +} + +// GetColorOk returns a tuple with the Color field value +// and a boolean to check if the value has been set. +func (o *Environment) GetColorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Color, true +} + +// SetColor sets field value +func (o *Environment) SetColor(v string) { + o.Color = v +} + +// GetDefaultTtl returns the DefaultTtl field value +func (o *Environment) GetDefaultTtl() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.DefaultTtl +} + +// GetDefaultTtlOk returns a tuple with the DefaultTtl field value +// and a boolean to check if the value has been set. +func (o *Environment) GetDefaultTtlOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.DefaultTtl, true +} + +// SetDefaultTtl sets field value +func (o *Environment) SetDefaultTtl(v int32) { + o.DefaultTtl = v +} + +// GetSecureMode returns the SecureMode field value +func (o *Environment) GetSecureMode() bool { + if o == nil { + var ret bool + return ret + } + + return o.SecureMode +} + +// GetSecureModeOk returns a tuple with the SecureMode field value +// and a boolean to check if the value has been set. +func (o *Environment) GetSecureModeOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.SecureMode, true +} + +// SetSecureMode sets field value +func (o *Environment) SetSecureMode(v bool) { + o.SecureMode = v +} + +// GetDefaultTrackEvents returns the DefaultTrackEvents field value +func (o *Environment) GetDefaultTrackEvents() bool { + if o == nil { + var ret bool + return ret + } + + return o.DefaultTrackEvents +} + +// GetDefaultTrackEventsOk returns a tuple with the DefaultTrackEvents field value +// and a boolean to check if the value has been set. +func (o *Environment) GetDefaultTrackEventsOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.DefaultTrackEvents, true +} + +// SetDefaultTrackEvents sets field value +func (o *Environment) SetDefaultTrackEvents(v bool) { + o.DefaultTrackEvents = v +} + +// GetRequireComments returns the RequireComments field value +func (o *Environment) GetRequireComments() bool { + if o == nil { + var ret bool + return ret + } + + return o.RequireComments +} + +// GetRequireCommentsOk returns a tuple with the RequireComments field value +// and a boolean to check if the value has been set. +func (o *Environment) GetRequireCommentsOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.RequireComments, true +} + +// SetRequireComments sets field value +func (o *Environment) SetRequireComments(v bool) { + o.RequireComments = v +} + +// GetConfirmChanges returns the ConfirmChanges field value +func (o *Environment) GetConfirmChanges() bool { + if o == nil { + var ret bool + return ret + } + + return o.ConfirmChanges +} + +// GetConfirmChangesOk returns a tuple with the ConfirmChanges field value +// and a boolean to check if the value has been set. +func (o *Environment) GetConfirmChangesOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.ConfirmChanges, true +} + +// SetConfirmChanges sets field value +func (o *Environment) SetConfirmChanges(v bool) { + o.ConfirmChanges = v +} + +// GetTags returns the Tags field value +func (o *Environment) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *Environment) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *Environment) SetTags(v []string) { + o.Tags = v +} + +// GetApprovalSettings returns the ApprovalSettings field value if set, zero value otherwise. +func (o *Environment) GetApprovalSettings() ApprovalSettings { + if o == nil || o.ApprovalSettings == nil { + var ret ApprovalSettings + return ret + } + return *o.ApprovalSettings +} + +// GetApprovalSettingsOk returns a tuple with the ApprovalSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Environment) GetApprovalSettingsOk() (*ApprovalSettings, bool) { + if o == nil || o.ApprovalSettings == nil { + return nil, false + } + return o.ApprovalSettings, true +} + +// HasApprovalSettings returns a boolean if a field has been set. +func (o *Environment) HasApprovalSettings() bool { + if o != nil && o.ApprovalSettings != nil { + return true + } + + return false +} + +// SetApprovalSettings gets a reference to the given ApprovalSettings and assigns it to the ApprovalSettings field. +func (o *Environment) SetApprovalSettings(v ApprovalSettings) { + o.ApprovalSettings = &v +} + +// GetResourceApprovalSettings returns the ResourceApprovalSettings field value if set, zero value otherwise. +func (o *Environment) GetResourceApprovalSettings() map[string]ApprovalSettings { + if o == nil || o.ResourceApprovalSettings == nil { + var ret map[string]ApprovalSettings + return ret + } + return *o.ResourceApprovalSettings +} + +// GetResourceApprovalSettingsOk returns a tuple with the ResourceApprovalSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Environment) GetResourceApprovalSettingsOk() (*map[string]ApprovalSettings, bool) { + if o == nil || o.ResourceApprovalSettings == nil { + return nil, false + } + return o.ResourceApprovalSettings, true +} + +// HasResourceApprovalSettings returns a boolean if a field has been set. +func (o *Environment) HasResourceApprovalSettings() bool { + if o != nil && o.ResourceApprovalSettings != nil { + return true + } + + return false +} + +// SetResourceApprovalSettings gets a reference to the given map[string]ApprovalSettings and assigns it to the ResourceApprovalSettings field. +func (o *Environment) SetResourceApprovalSettings(v map[string]ApprovalSettings) { + o.ResourceApprovalSettings = &v +} + +// GetCritical returns the Critical field value +func (o *Environment) GetCritical() bool { + if o == nil { + var ret bool + return ret + } + + return o.Critical +} + +// GetCriticalOk returns a tuple with the Critical field value +// and a boolean to check if the value has been set. +func (o *Environment) GetCriticalOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Critical, true +} + +// SetCritical sets field value +func (o *Environment) SetCritical(v bool) { + o.Critical = v +} + +func (o Environment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["apiKey"] = o.ApiKey + } + if true { + toSerialize["mobileKey"] = o.MobileKey + } + if true { + toSerialize["color"] = o.Color + } + if true { + toSerialize["defaultTtl"] = o.DefaultTtl + } + if true { + toSerialize["secureMode"] = o.SecureMode + } + if true { + toSerialize["defaultTrackEvents"] = o.DefaultTrackEvents + } + if true { + toSerialize["requireComments"] = o.RequireComments + } + if true { + toSerialize["confirmChanges"] = o.ConfirmChanges + } + if true { + toSerialize["tags"] = o.Tags + } + if o.ApprovalSettings != nil { + toSerialize["approvalSettings"] = o.ApprovalSettings + } + if o.ResourceApprovalSettings != nil { + toSerialize["resourceApprovalSettings"] = o.ResourceApprovalSettings + } + if true { + toSerialize["critical"] = o.Critical + } + return json.Marshal(toSerialize) +} + +type NullableEnvironment struct { + value *Environment + isSet bool +} + +func (v NullableEnvironment) Get() *Environment { + return v.value +} + +func (v *NullableEnvironment) Set(val *Environment) { + v.value = val + v.isSet = true +} + +func (v NullableEnvironment) IsSet() bool { + return v.isSet +} + +func (v *NullableEnvironment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEnvironment(val *Environment) *NullableEnvironment { + return &NullableEnvironment{value: val, isSet: true} +} + +func (v NullableEnvironment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEnvironment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_post.go new file mode 100644 index 00000000..4eb6112b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_post.go @@ -0,0 +1,465 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// EnvironmentPost struct for EnvironmentPost +type EnvironmentPost struct { + // A human-friendly name for the new environment + Name string `json:"name"` + // A project-unique key for the new environment + Key string `json:"key"` + // A color to indicate this environment in the UI + Color string `json:"color"` + // The default time (in minutes) that the PHP SDK can cache feature flag rules locally + DefaultTtl *int32 `json:"defaultTtl,omitempty"` + // Ensures that one end user of the client-side SDK cannot inspect the variations for another end user + SecureMode *bool `json:"secureMode,omitempty"` + // Enables tracking detailed information for new flags by default + DefaultTrackEvents *bool `json:"defaultTrackEvents,omitempty"` + // Requires confirmation for all flag and segment changes via the UI in this environment + ConfirmChanges *bool `json:"confirmChanges,omitempty"` + // Requires comments for all flag and segment changes via the UI in this environment + RequireComments *bool `json:"requireComments,omitempty"` + // Tags to apply to the new environment + Tags []string `json:"tags,omitempty"` + Source *SourceEnv `json:"source,omitempty"` + // Whether the environment is critical + Critical *bool `json:"critical,omitempty"` +} + +// NewEnvironmentPost instantiates a new EnvironmentPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEnvironmentPost(name string, key string, color string) *EnvironmentPost { + this := EnvironmentPost{} + this.Name = name + this.Key = key + this.Color = color + return &this +} + +// NewEnvironmentPostWithDefaults instantiates a new EnvironmentPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEnvironmentPostWithDefaults() *EnvironmentPost { + this := EnvironmentPost{} + return &this +} + +// GetName returns the Name field value +func (o *EnvironmentPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *EnvironmentPost) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *EnvironmentPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *EnvironmentPost) SetKey(v string) { + o.Key = v +} + +// GetColor returns the Color field value +func (o *EnvironmentPost) GetColor() string { + if o == nil { + var ret string + return ret + } + + return o.Color +} + +// GetColorOk returns a tuple with the Color field value +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetColorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Color, true +} + +// SetColor sets field value +func (o *EnvironmentPost) SetColor(v string) { + o.Color = v +} + +// GetDefaultTtl returns the DefaultTtl field value if set, zero value otherwise. +func (o *EnvironmentPost) GetDefaultTtl() int32 { + if o == nil || o.DefaultTtl == nil { + var ret int32 + return ret + } + return *o.DefaultTtl +} + +// GetDefaultTtlOk returns a tuple with the DefaultTtl field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetDefaultTtlOk() (*int32, bool) { + if o == nil || o.DefaultTtl == nil { + return nil, false + } + return o.DefaultTtl, true +} + +// HasDefaultTtl returns a boolean if a field has been set. +func (o *EnvironmentPost) HasDefaultTtl() bool { + if o != nil && o.DefaultTtl != nil { + return true + } + + return false +} + +// SetDefaultTtl gets a reference to the given int32 and assigns it to the DefaultTtl field. +func (o *EnvironmentPost) SetDefaultTtl(v int32) { + o.DefaultTtl = &v +} + +// GetSecureMode returns the SecureMode field value if set, zero value otherwise. +func (o *EnvironmentPost) GetSecureMode() bool { + if o == nil || o.SecureMode == nil { + var ret bool + return ret + } + return *o.SecureMode +} + +// GetSecureModeOk returns a tuple with the SecureMode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetSecureModeOk() (*bool, bool) { + if o == nil || o.SecureMode == nil { + return nil, false + } + return o.SecureMode, true +} + +// HasSecureMode returns a boolean if a field has been set. +func (o *EnvironmentPost) HasSecureMode() bool { + if o != nil && o.SecureMode != nil { + return true + } + + return false +} + +// SetSecureMode gets a reference to the given bool and assigns it to the SecureMode field. +func (o *EnvironmentPost) SetSecureMode(v bool) { + o.SecureMode = &v +} + +// GetDefaultTrackEvents returns the DefaultTrackEvents field value if set, zero value otherwise. +func (o *EnvironmentPost) GetDefaultTrackEvents() bool { + if o == nil || o.DefaultTrackEvents == nil { + var ret bool + return ret + } + return *o.DefaultTrackEvents +} + +// GetDefaultTrackEventsOk returns a tuple with the DefaultTrackEvents field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetDefaultTrackEventsOk() (*bool, bool) { + if o == nil || o.DefaultTrackEvents == nil { + return nil, false + } + return o.DefaultTrackEvents, true +} + +// HasDefaultTrackEvents returns a boolean if a field has been set. +func (o *EnvironmentPost) HasDefaultTrackEvents() bool { + if o != nil && o.DefaultTrackEvents != nil { + return true + } + + return false +} + +// SetDefaultTrackEvents gets a reference to the given bool and assigns it to the DefaultTrackEvents field. +func (o *EnvironmentPost) SetDefaultTrackEvents(v bool) { + o.DefaultTrackEvents = &v +} + +// GetConfirmChanges returns the ConfirmChanges field value if set, zero value otherwise. +func (o *EnvironmentPost) GetConfirmChanges() bool { + if o == nil || o.ConfirmChanges == nil { + var ret bool + return ret + } + return *o.ConfirmChanges +} + +// GetConfirmChangesOk returns a tuple with the ConfirmChanges field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetConfirmChangesOk() (*bool, bool) { + if o == nil || o.ConfirmChanges == nil { + return nil, false + } + return o.ConfirmChanges, true +} + +// HasConfirmChanges returns a boolean if a field has been set. +func (o *EnvironmentPost) HasConfirmChanges() bool { + if o != nil && o.ConfirmChanges != nil { + return true + } + + return false +} + +// SetConfirmChanges gets a reference to the given bool and assigns it to the ConfirmChanges field. +func (o *EnvironmentPost) SetConfirmChanges(v bool) { + o.ConfirmChanges = &v +} + +// GetRequireComments returns the RequireComments field value if set, zero value otherwise. +func (o *EnvironmentPost) GetRequireComments() bool { + if o == nil || o.RequireComments == nil { + var ret bool + return ret + } + return *o.RequireComments +} + +// GetRequireCommentsOk returns a tuple with the RequireComments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetRequireCommentsOk() (*bool, bool) { + if o == nil || o.RequireComments == nil { + return nil, false + } + return o.RequireComments, true +} + +// HasRequireComments returns a boolean if a field has been set. +func (o *EnvironmentPost) HasRequireComments() bool { + if o != nil && o.RequireComments != nil { + return true + } + + return false +} + +// SetRequireComments gets a reference to the given bool and assigns it to the RequireComments field. +func (o *EnvironmentPost) SetRequireComments(v bool) { + o.RequireComments = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *EnvironmentPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *EnvironmentPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *EnvironmentPost) SetTags(v []string) { + o.Tags = v +} + +// GetSource returns the Source field value if set, zero value otherwise. +func (o *EnvironmentPost) GetSource() SourceEnv { + if o == nil || o.Source == nil { + var ret SourceEnv + return ret + } + return *o.Source +} + +// GetSourceOk returns a tuple with the Source field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetSourceOk() (*SourceEnv, bool) { + if o == nil || o.Source == nil { + return nil, false + } + return o.Source, true +} + +// HasSource returns a boolean if a field has been set. +func (o *EnvironmentPost) HasSource() bool { + if o != nil && o.Source != nil { + return true + } + + return false +} + +// SetSource gets a reference to the given SourceEnv and assigns it to the Source field. +func (o *EnvironmentPost) SetSource(v SourceEnv) { + o.Source = &v +} + +// GetCritical returns the Critical field value if set, zero value otherwise. +func (o *EnvironmentPost) GetCritical() bool { + if o == nil || o.Critical == nil { + var ret bool + return ret + } + return *o.Critical +} + +// GetCriticalOk returns a tuple with the Critical field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EnvironmentPost) GetCriticalOk() (*bool, bool) { + if o == nil || o.Critical == nil { + return nil, false + } + return o.Critical, true +} + +// HasCritical returns a boolean if a field has been set. +func (o *EnvironmentPost) HasCritical() bool { + if o != nil && o.Critical != nil { + return true + } + + return false +} + +// SetCritical gets a reference to the given bool and assigns it to the Critical field. +func (o *EnvironmentPost) SetCritical(v bool) { + o.Critical = &v +} + +func (o EnvironmentPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["color"] = o.Color + } + if o.DefaultTtl != nil { + toSerialize["defaultTtl"] = o.DefaultTtl + } + if o.SecureMode != nil { + toSerialize["secureMode"] = o.SecureMode + } + if o.DefaultTrackEvents != nil { + toSerialize["defaultTrackEvents"] = o.DefaultTrackEvents + } + if o.ConfirmChanges != nil { + toSerialize["confirmChanges"] = o.ConfirmChanges + } + if o.RequireComments != nil { + toSerialize["requireComments"] = o.RequireComments + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Source != nil { + toSerialize["source"] = o.Source + } + if o.Critical != nil { + toSerialize["critical"] = o.Critical + } + return json.Marshal(toSerialize) +} + +type NullableEnvironmentPost struct { + value *EnvironmentPost + isSet bool +} + +func (v NullableEnvironmentPost) Get() *EnvironmentPost { + return v.value +} + +func (v *NullableEnvironmentPost) Set(val *EnvironmentPost) { + v.value = val + v.isSet = true +} + +func (v NullableEnvironmentPost) IsSet() bool { + return v.isSet +} + +func (v *NullableEnvironmentPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEnvironmentPost(val *EnvironmentPost) *NullableEnvironmentPost { + return &NullableEnvironmentPost{value: val, isSet: true} +} + +func (v NullableEnvironmentPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEnvironmentPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_summary.go new file mode 100644 index 00000000..a5ab968a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_environment_summary.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// EnvironmentSummary struct for EnvironmentSummary +type EnvironmentSummary struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // A project-unique key for the environment + Key string `json:"key"` + // A human-friendly name for the environment + Name string `json:"name"` + // The color used to indicate this environment in the UI + Color string `json:"color"` +} + +// NewEnvironmentSummary instantiates a new EnvironmentSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEnvironmentSummary(links map[string]Link, key string, name string, color string) *EnvironmentSummary { + this := EnvironmentSummary{} + this.Links = links + this.Key = key + this.Name = name + this.Color = color + return &this +} + +// NewEnvironmentSummaryWithDefaults instantiates a new EnvironmentSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEnvironmentSummaryWithDefaults() *EnvironmentSummary { + this := EnvironmentSummary{} + return &this +} + +// GetLinks returns the Links field value +func (o *EnvironmentSummary) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *EnvironmentSummary) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *EnvironmentSummary) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetKey returns the Key field value +func (o *EnvironmentSummary) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *EnvironmentSummary) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *EnvironmentSummary) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *EnvironmentSummary) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *EnvironmentSummary) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *EnvironmentSummary) SetName(v string) { + o.Name = v +} + +// GetColor returns the Color field value +func (o *EnvironmentSummary) GetColor() string { + if o == nil { + var ret string + return ret + } + + return o.Color +} + +// GetColorOk returns a tuple with the Color field value +// and a boolean to check if the value has been set. +func (o *EnvironmentSummary) GetColorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Color, true +} + +// SetColor sets field value +func (o *EnvironmentSummary) SetColor(v string) { + o.Color = v +} + +func (o EnvironmentSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["color"] = o.Color + } + return json.Marshal(toSerialize) +} + +type NullableEnvironmentSummary struct { + value *EnvironmentSummary + isSet bool +} + +func (v NullableEnvironmentSummary) Get() *EnvironmentSummary { + return v.value +} + +func (v *NullableEnvironmentSummary) Set(val *EnvironmentSummary) { + v.value = val + v.isSet = true +} + +func (v NullableEnvironmentSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableEnvironmentSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEnvironmentSummary(val *EnvironmentSummary) *NullableEnvironmentSummary { + return &NullableEnvironmentSummary{value: val, isSet: true} +} + +func (v NullableEnvironmentSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEnvironmentSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_environments.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_environments.go new file mode 100644 index 00000000..286c4a62 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_environments.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Environments struct for Environments +type Environments struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The number of environments returned + TotalCount *int32 `json:"totalCount,omitempty"` + // An array of environments + Items []Environment `json:"items"` +} + +// NewEnvironments instantiates a new Environments object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEnvironments(items []Environment) *Environments { + this := Environments{} + this.Items = items + return &this +} + +// NewEnvironmentsWithDefaults instantiates a new Environments object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEnvironmentsWithDefaults() *Environments { + this := Environments{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Environments) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Environments) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Environments) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Environments) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Environments) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Environments) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Environments) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Environments) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetItems returns the Items field value +func (o *Environments) GetItems() []Environment { + if o == nil { + var ret []Environment + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Environments) GetItemsOk() ([]Environment, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Environments) SetItems(v []Environment) { + o.Items = v +} + +func (o Environments) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableEnvironments struct { + value *Environments + isSet bool +} + +func (v NullableEnvironments) Get() *Environments { + return v.value +} + +func (v *NullableEnvironments) Set(val *Environments) { + v.value = val + v.isSet = true +} + +func (v NullableEnvironments) IsSet() bool { + return v.isSet +} + +func (v *NullableEnvironments) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEnvironments(val *Environments) *NullableEnvironments { + return &NullableEnvironments{value: val, isSet: true} +} + +func (v NullableEnvironments) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEnvironments) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_error.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_error.go new file mode 100644 index 00000000..fb68b8bf --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_error.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Error struct for Error +type Error struct { + Message string `json:"message"` + Code string `json:"code"` +} + +// NewError instantiates a new Error object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewError(message string, code string) *Error { + this := Error{} + this.Message = message + this.Code = code + return &this +} + +// NewErrorWithDefaults instantiates a new Error object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewErrorWithDefaults() *Error { + this := Error{} + return &this +} + +// GetMessage returns the Message field value +func (o *Error) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *Error) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *Error) SetMessage(v string) { + o.Message = v +} + +// GetCode returns the Code field value +func (o *Error) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *Error) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *Error) SetCode(v string) { + o.Code = v +} + +func (o Error) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["message"] = o.Message + } + if true { + toSerialize["code"] = o.Code + } + return json.Marshal(toSerialize) +} + +type NullableError struct { + value *Error + isSet bool +} + +func (v NullableError) Get() *Error { + return v.value +} + +func (v *NullableError) Set(val *Error) { + v.value = val + v.isSet = true +} + +func (v NullableError) IsSet() bool { + return v.isSet +} + +func (v *NullableError) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableError(val *Error) *NullableError { + return &NullableError{value: val, isSet: true} +} + +func (v NullableError) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableError) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluation_reason.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluation_reason.go new file mode 100644 index 00000000..4fa85df0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluation_reason.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// EvaluationReason struct for EvaluationReason +type EvaluationReason struct { + // Describes the general reason that LaunchDarkly selected this variation. + Kind string `json:"kind"` + // The positional index of the matching rule if the kind is 'RULE_MATCH'. The index is 0-based. + RuleIndex *int32 `json:"ruleIndex,omitempty"` + // The unique identifier of the matching rule if the kind is 'RULE_MATCH'. + RuleID *string `json:"ruleID,omitempty"` + // The key of the flag that failed if the kind is 'PREREQUISITE_FAILED'. + PrerequisiteKey *string `json:"prerequisiteKey,omitempty"` + // Indicates whether the evaluation occurred as part of an experiment. + InExperiment *bool `json:"inExperiment,omitempty"` + // The specific error type if the kind is 'ERROR'. + ErrorKind *string `json:"errorKind,omitempty"` +} + +// NewEvaluationReason instantiates a new EvaluationReason object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEvaluationReason(kind string) *EvaluationReason { + this := EvaluationReason{} + this.Kind = kind + return &this +} + +// NewEvaluationReasonWithDefaults instantiates a new EvaluationReason object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEvaluationReasonWithDefaults() *EvaluationReason { + this := EvaluationReason{} + return &this +} + +// GetKind returns the Kind field value +func (o *EvaluationReason) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *EvaluationReason) SetKind(v string) { + o.Kind = v +} + +// GetRuleIndex returns the RuleIndex field value if set, zero value otherwise. +func (o *EvaluationReason) GetRuleIndex() int32 { + if o == nil || o.RuleIndex == nil { + var ret int32 + return ret + } + return *o.RuleIndex +} + +// GetRuleIndexOk returns a tuple with the RuleIndex field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetRuleIndexOk() (*int32, bool) { + if o == nil || o.RuleIndex == nil { + return nil, false + } + return o.RuleIndex, true +} + +// HasRuleIndex returns a boolean if a field has been set. +func (o *EvaluationReason) HasRuleIndex() bool { + if o != nil && o.RuleIndex != nil { + return true + } + + return false +} + +// SetRuleIndex gets a reference to the given int32 and assigns it to the RuleIndex field. +func (o *EvaluationReason) SetRuleIndex(v int32) { + o.RuleIndex = &v +} + +// GetRuleID returns the RuleID field value if set, zero value otherwise. +func (o *EvaluationReason) GetRuleID() string { + if o == nil || o.RuleID == nil { + var ret string + return ret + } + return *o.RuleID +} + +// GetRuleIDOk returns a tuple with the RuleID field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetRuleIDOk() (*string, bool) { + if o == nil || o.RuleID == nil { + return nil, false + } + return o.RuleID, true +} + +// HasRuleID returns a boolean if a field has been set. +func (o *EvaluationReason) HasRuleID() bool { + if o != nil && o.RuleID != nil { + return true + } + + return false +} + +// SetRuleID gets a reference to the given string and assigns it to the RuleID field. +func (o *EvaluationReason) SetRuleID(v string) { + o.RuleID = &v +} + +// GetPrerequisiteKey returns the PrerequisiteKey field value if set, zero value otherwise. +func (o *EvaluationReason) GetPrerequisiteKey() string { + if o == nil || o.PrerequisiteKey == nil { + var ret string + return ret + } + return *o.PrerequisiteKey +} + +// GetPrerequisiteKeyOk returns a tuple with the PrerequisiteKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetPrerequisiteKeyOk() (*string, bool) { + if o == nil || o.PrerequisiteKey == nil { + return nil, false + } + return o.PrerequisiteKey, true +} + +// HasPrerequisiteKey returns a boolean if a field has been set. +func (o *EvaluationReason) HasPrerequisiteKey() bool { + if o != nil && o.PrerequisiteKey != nil { + return true + } + + return false +} + +// SetPrerequisiteKey gets a reference to the given string and assigns it to the PrerequisiteKey field. +func (o *EvaluationReason) SetPrerequisiteKey(v string) { + o.PrerequisiteKey = &v +} + +// GetInExperiment returns the InExperiment field value if set, zero value otherwise. +func (o *EvaluationReason) GetInExperiment() bool { + if o == nil || o.InExperiment == nil { + var ret bool + return ret + } + return *o.InExperiment +} + +// GetInExperimentOk returns a tuple with the InExperiment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetInExperimentOk() (*bool, bool) { + if o == nil || o.InExperiment == nil { + return nil, false + } + return o.InExperiment, true +} + +// HasInExperiment returns a boolean if a field has been set. +func (o *EvaluationReason) HasInExperiment() bool { + if o != nil && o.InExperiment != nil { + return true + } + + return false +} + +// SetInExperiment gets a reference to the given bool and assigns it to the InExperiment field. +func (o *EvaluationReason) SetInExperiment(v bool) { + o.InExperiment = &v +} + +// GetErrorKind returns the ErrorKind field value if set, zero value otherwise. +func (o *EvaluationReason) GetErrorKind() string { + if o == nil || o.ErrorKind == nil { + var ret string + return ret + } + return *o.ErrorKind +} + +// GetErrorKindOk returns a tuple with the ErrorKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationReason) GetErrorKindOk() (*string, bool) { + if o == nil || o.ErrorKind == nil { + return nil, false + } + return o.ErrorKind, true +} + +// HasErrorKind returns a boolean if a field has been set. +func (o *EvaluationReason) HasErrorKind() bool { + if o != nil && o.ErrorKind != nil { + return true + } + + return false +} + +// SetErrorKind gets a reference to the given string and assigns it to the ErrorKind field. +func (o *EvaluationReason) SetErrorKind(v string) { + o.ErrorKind = &v +} + +func (o EvaluationReason) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if o.RuleIndex != nil { + toSerialize["ruleIndex"] = o.RuleIndex + } + if o.RuleID != nil { + toSerialize["ruleID"] = o.RuleID + } + if o.PrerequisiteKey != nil { + toSerialize["prerequisiteKey"] = o.PrerequisiteKey + } + if o.InExperiment != nil { + toSerialize["inExperiment"] = o.InExperiment + } + if o.ErrorKind != nil { + toSerialize["errorKind"] = o.ErrorKind + } + return json.Marshal(toSerialize) +} + +type NullableEvaluationReason struct { + value *EvaluationReason + isSet bool +} + +func (v NullableEvaluationReason) Get() *EvaluationReason { + return v.value +} + +func (v *NullableEvaluationReason) Set(val *EvaluationReason) { + v.value = val + v.isSet = true +} + +func (v NullableEvaluationReason) IsSet() bool { + return v.isSet +} + +func (v *NullableEvaluationReason) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEvaluationReason(val *EvaluationReason) *NullableEvaluationReason { + return &NullableEvaluationReason{value: val, isSet: true} +} + +func (v NullableEvaluationReason) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEvaluationReason) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluations_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluations_summary.go new file mode 100644 index 00000000..294c49b3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_evaluations_summary.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// EvaluationsSummary struct for EvaluationsSummary +type EvaluationsSummary struct { + // A list of variation evaluations + Variations []VariationEvalSummary `json:"variations,omitempty"` +} + +// NewEvaluationsSummary instantiates a new EvaluationsSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEvaluationsSummary() *EvaluationsSummary { + this := EvaluationsSummary{} + return &this +} + +// NewEvaluationsSummaryWithDefaults instantiates a new EvaluationsSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEvaluationsSummaryWithDefaults() *EvaluationsSummary { + this := EvaluationsSummary{} + return &this +} + +// GetVariations returns the Variations field value if set, zero value otherwise. +func (o *EvaluationsSummary) GetVariations() []VariationEvalSummary { + if o == nil || o.Variations == nil { + var ret []VariationEvalSummary + return ret + } + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EvaluationsSummary) GetVariationsOk() ([]VariationEvalSummary, bool) { + if o == nil || o.Variations == nil { + return nil, false + } + return o.Variations, true +} + +// HasVariations returns a boolean if a field has been set. +func (o *EvaluationsSummary) HasVariations() bool { + if o != nil && o.Variations != nil { + return true + } + + return false +} + +// SetVariations gets a reference to the given []VariationEvalSummary and assigns it to the Variations field. +func (o *EvaluationsSummary) SetVariations(v []VariationEvalSummary) { + o.Variations = v +} + +func (o EvaluationsSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Variations != nil { + toSerialize["variations"] = o.Variations + } + return json.Marshal(toSerialize) +} + +type NullableEvaluationsSummary struct { + value *EvaluationsSummary + isSet bool +} + +func (v NullableEvaluationsSummary) Get() *EvaluationsSummary { + return v.value +} + +func (v *NullableEvaluationsSummary) Set(val *EvaluationsSummary) { + v.value = val + v.isSet = true +} + +func (v NullableEvaluationsSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableEvaluationsSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEvaluationsSummary(val *EvaluationsSummary) *NullableEvaluationsSummary { + return &NullableEvaluationsSummary{value: val, isSet: true} +} + +func (v NullableEvaluationsSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEvaluationsSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_execution_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_execution_output.go new file mode 100644 index 00000000..66b3ef83 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_execution_output.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExecutionOutput struct for ExecutionOutput +type ExecutionOutput struct { + // The status of the execution of this workflow stage + Status string `json:"status"` + StopDate *int64 `json:"stopDate,omitempty"` +} + +// NewExecutionOutput instantiates a new ExecutionOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExecutionOutput(status string) *ExecutionOutput { + this := ExecutionOutput{} + this.Status = status + return &this +} + +// NewExecutionOutputWithDefaults instantiates a new ExecutionOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExecutionOutputWithDefaults() *ExecutionOutput { + this := ExecutionOutput{} + return &this +} + +// GetStatus returns the Status field value +func (o *ExecutionOutput) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *ExecutionOutput) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *ExecutionOutput) SetStatus(v string) { + o.Status = v +} + +// GetStopDate returns the StopDate field value if set, zero value otherwise. +func (o *ExecutionOutput) GetStopDate() int64 { + if o == nil || o.StopDate == nil { + var ret int64 + return ret + } + return *o.StopDate +} + +// GetStopDateOk returns a tuple with the StopDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExecutionOutput) GetStopDateOk() (*int64, bool) { + if o == nil || o.StopDate == nil { + return nil, false + } + return o.StopDate, true +} + +// HasStopDate returns a boolean if a field has been set. +func (o *ExecutionOutput) HasStopDate() bool { + if o != nil && o.StopDate != nil { + return true + } + + return false +} + +// SetStopDate gets a reference to the given int64 and assigns it to the StopDate field. +func (o *ExecutionOutput) SetStopDate(v int64) { + o.StopDate = &v +} + +func (o ExecutionOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["status"] = o.Status + } + if o.StopDate != nil { + toSerialize["stopDate"] = o.StopDate + } + return json.Marshal(toSerialize) +} + +type NullableExecutionOutput struct { + value *ExecutionOutput + isSet bool +} + +func (v NullableExecutionOutput) Get() *ExecutionOutput { + return v.value +} + +func (v *NullableExecutionOutput) Set(val *ExecutionOutput) { + v.value = val + v.isSet = true +} + +func (v NullableExecutionOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableExecutionOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExecutionOutput(val *ExecutionOutput) *NullableExecutionOutput { + return &NullableExecutionOutput{value: val, isSet: true} +} + +func (v NullableExecutionOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExecutionOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_request_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_request_response.go new file mode 100644 index 00000000..bfd7e1f0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_request_response.go @@ -0,0 +1,990 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpandableApprovalRequestResponse struct for ExpandableApprovalRequestResponse +type ExpandableApprovalRequestResponse struct { + // The ID of this approval request + Id string `json:"_id"` + // Version of the approval request + Version int32 `json:"_version"` + CreationDate int64 `json:"creationDate"` + ServiceKind string `json:"serviceKind"` + // The ID of the member who requested the approval + RequestorId *string `json:"requestorId,omitempty"` + // A human-friendly name for the approval request + Description *string `json:"description,omitempty"` + // Current status of the review of this approval request + ReviewStatus string `json:"reviewStatus"` + // An array of individual reviews of this approval request + AllReviews []ReviewResponse `json:"allReviews"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds"` + AppliedDate *int64 `json:"appliedDate,omitempty"` + // The member ID of the member who applied the approval request + AppliedByMemberId *string `json:"appliedByMemberId,omitempty"` + // The service token ID of the service token which applied the approval request + AppliedByServiceTokenId *string `json:"appliedByServiceTokenId,omitempty"` + // Current status of the approval request + Status string `json:"status"` + Instructions []map[string]interface{} `json:"instructions"` + // Details on any conflicting approval requests + Conflicts []Conflict `json:"conflicts"` + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + // ID of scheduled change to edit or delete + OperatingOnId *string `json:"operatingOnId,omitempty"` + IntegrationMetadata *IntegrationMetadata `json:"integrationMetadata,omitempty"` + Source *CopiedFromEnv `json:"source,omitempty"` + CustomWorkflowMetadata *CustomWorkflowMeta `json:"customWorkflowMetadata,omitempty"` + // String representation of a resource + ResourceId *string `json:"resourceId,omitempty"` + ApprovalSettings *ApprovalSettings `json:"approvalSettings,omitempty"` + Project *Project `json:"project,omitempty"` + // List of environments the approval impacts + Environments []Environment `json:"environments,omitempty"` + Flag *ExpandedFlagRep `json:"flag,omitempty"` + Resource *ExpandedResourceRep `json:"resource,omitempty"` +} + +// NewExpandableApprovalRequestResponse instantiates a new ExpandableApprovalRequestResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpandableApprovalRequestResponse(id string, version int32, creationDate int64, serviceKind string, reviewStatus string, allReviews []ReviewResponse, notifyMemberIds []string, status string, instructions []map[string]interface{}, conflicts []Conflict, links map[string]interface{}) *ExpandableApprovalRequestResponse { + this := ExpandableApprovalRequestResponse{} + this.Id = id + this.Version = version + this.CreationDate = creationDate + this.ServiceKind = serviceKind + this.ReviewStatus = reviewStatus + this.AllReviews = allReviews + this.NotifyMemberIds = notifyMemberIds + this.Status = status + this.Instructions = instructions + this.Conflicts = conflicts + this.Links = links + return &this +} + +// NewExpandableApprovalRequestResponseWithDefaults instantiates a new ExpandableApprovalRequestResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpandableApprovalRequestResponseWithDefaults() *ExpandableApprovalRequestResponse { + this := ExpandableApprovalRequestResponse{} + return &this +} + +// GetId returns the Id field value +func (o *ExpandableApprovalRequestResponse) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ExpandableApprovalRequestResponse) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *ExpandableApprovalRequestResponse) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ExpandableApprovalRequestResponse) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *ExpandableApprovalRequestResponse) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *ExpandableApprovalRequestResponse) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetServiceKind returns the ServiceKind field value +func (o *ExpandableApprovalRequestResponse) GetServiceKind() string { + if o == nil { + var ret string + return ret + } + + return o.ServiceKind +} + +// GetServiceKindOk returns a tuple with the ServiceKind field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetServiceKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ServiceKind, true +} + +// SetServiceKind sets field value +func (o *ExpandableApprovalRequestResponse) SetServiceKind(v string) { + o.ServiceKind = v +} + +// GetRequestorId returns the RequestorId field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetRequestorId() string { + if o == nil || o.RequestorId == nil { + var ret string + return ret + } + return *o.RequestorId +} + +// GetRequestorIdOk returns a tuple with the RequestorId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetRequestorIdOk() (*string, bool) { + if o == nil || o.RequestorId == nil { + return nil, false + } + return o.RequestorId, true +} + +// HasRequestorId returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasRequestorId() bool { + if o != nil && o.RequestorId != nil { + return true + } + + return false +} + +// SetRequestorId gets a reference to the given string and assigns it to the RequestorId field. +func (o *ExpandableApprovalRequestResponse) SetRequestorId(v string) { + o.RequestorId = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ExpandableApprovalRequestResponse) SetDescription(v string) { + o.Description = &v +} + +// GetReviewStatus returns the ReviewStatus field value +func (o *ExpandableApprovalRequestResponse) GetReviewStatus() string { + if o == nil { + var ret string + return ret + } + + return o.ReviewStatus +} + +// GetReviewStatusOk returns a tuple with the ReviewStatus field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetReviewStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReviewStatus, true +} + +// SetReviewStatus sets field value +func (o *ExpandableApprovalRequestResponse) SetReviewStatus(v string) { + o.ReviewStatus = v +} + +// GetAllReviews returns the AllReviews field value +func (o *ExpandableApprovalRequestResponse) GetAllReviews() []ReviewResponse { + if o == nil { + var ret []ReviewResponse + return ret + } + + return o.AllReviews +} + +// GetAllReviewsOk returns a tuple with the AllReviews field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetAllReviewsOk() ([]ReviewResponse, bool) { + if o == nil { + return nil, false + } + return o.AllReviews, true +} + +// SetAllReviews sets field value +func (o *ExpandableApprovalRequestResponse) SetAllReviews(v []ReviewResponse) { + o.AllReviews = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value +func (o *ExpandableApprovalRequestResponse) GetNotifyMemberIds() []string { + if o == nil { + var ret []string + return ret + } + + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// SetNotifyMemberIds sets field value +func (o *ExpandableApprovalRequestResponse) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetAppliedDate returns the AppliedDate field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetAppliedDate() int64 { + if o == nil || o.AppliedDate == nil { + var ret int64 + return ret + } + return *o.AppliedDate +} + +// GetAppliedDateOk returns a tuple with the AppliedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetAppliedDateOk() (*int64, bool) { + if o == nil || o.AppliedDate == nil { + return nil, false + } + return o.AppliedDate, true +} + +// HasAppliedDate returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasAppliedDate() bool { + if o != nil && o.AppliedDate != nil { + return true + } + + return false +} + +// SetAppliedDate gets a reference to the given int64 and assigns it to the AppliedDate field. +func (o *ExpandableApprovalRequestResponse) SetAppliedDate(v int64) { + o.AppliedDate = &v +} + +// GetAppliedByMemberId returns the AppliedByMemberId field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetAppliedByMemberId() string { + if o == nil || o.AppliedByMemberId == nil { + var ret string + return ret + } + return *o.AppliedByMemberId +} + +// GetAppliedByMemberIdOk returns a tuple with the AppliedByMemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetAppliedByMemberIdOk() (*string, bool) { + if o == nil || o.AppliedByMemberId == nil { + return nil, false + } + return o.AppliedByMemberId, true +} + +// HasAppliedByMemberId returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasAppliedByMemberId() bool { + if o != nil && o.AppliedByMemberId != nil { + return true + } + + return false +} + +// SetAppliedByMemberId gets a reference to the given string and assigns it to the AppliedByMemberId field. +func (o *ExpandableApprovalRequestResponse) SetAppliedByMemberId(v string) { + o.AppliedByMemberId = &v +} + +// GetAppliedByServiceTokenId returns the AppliedByServiceTokenId field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetAppliedByServiceTokenId() string { + if o == nil || o.AppliedByServiceTokenId == nil { + var ret string + return ret + } + return *o.AppliedByServiceTokenId +} + +// GetAppliedByServiceTokenIdOk returns a tuple with the AppliedByServiceTokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetAppliedByServiceTokenIdOk() (*string, bool) { + if o == nil || o.AppliedByServiceTokenId == nil { + return nil, false + } + return o.AppliedByServiceTokenId, true +} + +// HasAppliedByServiceTokenId returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasAppliedByServiceTokenId() bool { + if o != nil && o.AppliedByServiceTokenId != nil { + return true + } + + return false +} + +// SetAppliedByServiceTokenId gets a reference to the given string and assigns it to the AppliedByServiceTokenId field. +func (o *ExpandableApprovalRequestResponse) SetAppliedByServiceTokenId(v string) { + o.AppliedByServiceTokenId = &v +} + +// GetStatus returns the Status field value +func (o *ExpandableApprovalRequestResponse) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *ExpandableApprovalRequestResponse) SetStatus(v string) { + o.Status = v +} + +// GetInstructions returns the Instructions field value +func (o *ExpandableApprovalRequestResponse) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *ExpandableApprovalRequestResponse) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetConflicts returns the Conflicts field value +func (o *ExpandableApprovalRequestResponse) GetConflicts() []Conflict { + if o == nil { + var ret []Conflict + return ret + } + + return o.Conflicts +} + +// GetConflictsOk returns a tuple with the Conflicts field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetConflictsOk() ([]Conflict, bool) { + if o == nil { + return nil, false + } + return o.Conflicts, true +} + +// SetConflicts sets field value +func (o *ExpandableApprovalRequestResponse) SetConflicts(v []Conflict) { + o.Conflicts = v +} + +// GetLinks returns the Links field value +func (o *ExpandableApprovalRequestResponse) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *ExpandableApprovalRequestResponse) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *ExpandableApprovalRequestResponse) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetOperatingOnId returns the OperatingOnId field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetOperatingOnId() string { + if o == nil || o.OperatingOnId == nil { + var ret string + return ret + } + return *o.OperatingOnId +} + +// GetOperatingOnIdOk returns a tuple with the OperatingOnId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetOperatingOnIdOk() (*string, bool) { + if o == nil || o.OperatingOnId == nil { + return nil, false + } + return o.OperatingOnId, true +} + +// HasOperatingOnId returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasOperatingOnId() bool { + if o != nil && o.OperatingOnId != nil { + return true + } + + return false +} + +// SetOperatingOnId gets a reference to the given string and assigns it to the OperatingOnId field. +func (o *ExpandableApprovalRequestResponse) SetOperatingOnId(v string) { + o.OperatingOnId = &v +} + +// GetIntegrationMetadata returns the IntegrationMetadata field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetIntegrationMetadata() IntegrationMetadata { + if o == nil || o.IntegrationMetadata == nil { + var ret IntegrationMetadata + return ret + } + return *o.IntegrationMetadata +} + +// GetIntegrationMetadataOk returns a tuple with the IntegrationMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetIntegrationMetadataOk() (*IntegrationMetadata, bool) { + if o == nil || o.IntegrationMetadata == nil { + return nil, false + } + return o.IntegrationMetadata, true +} + +// HasIntegrationMetadata returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasIntegrationMetadata() bool { + if o != nil && o.IntegrationMetadata != nil { + return true + } + + return false +} + +// SetIntegrationMetadata gets a reference to the given IntegrationMetadata and assigns it to the IntegrationMetadata field. +func (o *ExpandableApprovalRequestResponse) SetIntegrationMetadata(v IntegrationMetadata) { + o.IntegrationMetadata = &v +} + +// GetSource returns the Source field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetSource() CopiedFromEnv { + if o == nil || o.Source == nil { + var ret CopiedFromEnv + return ret + } + return *o.Source +} + +// GetSourceOk returns a tuple with the Source field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetSourceOk() (*CopiedFromEnv, bool) { + if o == nil || o.Source == nil { + return nil, false + } + return o.Source, true +} + +// HasSource returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasSource() bool { + if o != nil && o.Source != nil { + return true + } + + return false +} + +// SetSource gets a reference to the given CopiedFromEnv and assigns it to the Source field. +func (o *ExpandableApprovalRequestResponse) SetSource(v CopiedFromEnv) { + o.Source = &v +} + +// GetCustomWorkflowMetadata returns the CustomWorkflowMetadata field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetCustomWorkflowMetadata() CustomWorkflowMeta { + if o == nil || o.CustomWorkflowMetadata == nil { + var ret CustomWorkflowMeta + return ret + } + return *o.CustomWorkflowMetadata +} + +// GetCustomWorkflowMetadataOk returns a tuple with the CustomWorkflowMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetCustomWorkflowMetadataOk() (*CustomWorkflowMeta, bool) { + if o == nil || o.CustomWorkflowMetadata == nil { + return nil, false + } + return o.CustomWorkflowMetadata, true +} + +// HasCustomWorkflowMetadata returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasCustomWorkflowMetadata() bool { + if o != nil && o.CustomWorkflowMetadata != nil { + return true + } + + return false +} + +// SetCustomWorkflowMetadata gets a reference to the given CustomWorkflowMeta and assigns it to the CustomWorkflowMetadata field. +func (o *ExpandableApprovalRequestResponse) SetCustomWorkflowMetadata(v CustomWorkflowMeta) { + o.CustomWorkflowMetadata = &v +} + +// GetResourceId returns the ResourceId field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetResourceId() string { + if o == nil || o.ResourceId == nil { + var ret string + return ret + } + return *o.ResourceId +} + +// GetResourceIdOk returns a tuple with the ResourceId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetResourceIdOk() (*string, bool) { + if o == nil || o.ResourceId == nil { + return nil, false + } + return o.ResourceId, true +} + +// HasResourceId returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasResourceId() bool { + if o != nil && o.ResourceId != nil { + return true + } + + return false +} + +// SetResourceId gets a reference to the given string and assigns it to the ResourceId field. +func (o *ExpandableApprovalRequestResponse) SetResourceId(v string) { + o.ResourceId = &v +} + +// GetApprovalSettings returns the ApprovalSettings field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetApprovalSettings() ApprovalSettings { + if o == nil || o.ApprovalSettings == nil { + var ret ApprovalSettings + return ret + } + return *o.ApprovalSettings +} + +// GetApprovalSettingsOk returns a tuple with the ApprovalSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetApprovalSettingsOk() (*ApprovalSettings, bool) { + if o == nil || o.ApprovalSettings == nil { + return nil, false + } + return o.ApprovalSettings, true +} + +// HasApprovalSettings returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasApprovalSettings() bool { + if o != nil && o.ApprovalSettings != nil { + return true + } + + return false +} + +// SetApprovalSettings gets a reference to the given ApprovalSettings and assigns it to the ApprovalSettings field. +func (o *ExpandableApprovalRequestResponse) SetApprovalSettings(v ApprovalSettings) { + o.ApprovalSettings = &v +} + +// GetProject returns the Project field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetProject() Project { + if o == nil || o.Project == nil { + var ret Project + return ret + } + return *o.Project +} + +// GetProjectOk returns a tuple with the Project field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetProjectOk() (*Project, bool) { + if o == nil || o.Project == nil { + return nil, false + } + return o.Project, true +} + +// HasProject returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasProject() bool { + if o != nil && o.Project != nil { + return true + } + + return false +} + +// SetProject gets a reference to the given Project and assigns it to the Project field. +func (o *ExpandableApprovalRequestResponse) SetProject(v Project) { + o.Project = &v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetEnvironments() []Environment { + if o == nil || o.Environments == nil { + var ret []Environment + return ret + } + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetEnvironmentsOk() ([]Environment, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given []Environment and assigns it to the Environments field. +func (o *ExpandableApprovalRequestResponse) SetEnvironments(v []Environment) { + o.Environments = v +} + +// GetFlag returns the Flag field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetFlag() ExpandedFlagRep { + if o == nil || o.Flag == nil { + var ret ExpandedFlagRep + return ret + } + return *o.Flag +} + +// GetFlagOk returns a tuple with the Flag field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetFlagOk() (*ExpandedFlagRep, bool) { + if o == nil || o.Flag == nil { + return nil, false + } + return o.Flag, true +} + +// HasFlag returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasFlag() bool { + if o != nil && o.Flag != nil { + return true + } + + return false +} + +// SetFlag gets a reference to the given ExpandedFlagRep and assigns it to the Flag field. +func (o *ExpandableApprovalRequestResponse) SetFlag(v ExpandedFlagRep) { + o.Flag = &v +} + +// GetResource returns the Resource field value if set, zero value otherwise. +func (o *ExpandableApprovalRequestResponse) GetResource() ExpandedResourceRep { + if o == nil || o.Resource == nil { + var ret ExpandedResourceRep + return ret + } + return *o.Resource +} + +// GetResourceOk returns a tuple with the Resource field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestResponse) GetResourceOk() (*ExpandedResourceRep, bool) { + if o == nil || o.Resource == nil { + return nil, false + } + return o.Resource, true +} + +// HasResource returns a boolean if a field has been set. +func (o *ExpandableApprovalRequestResponse) HasResource() bool { + if o != nil && o.Resource != nil { + return true + } + + return false +} + +// SetResource gets a reference to the given ExpandedResourceRep and assigns it to the Resource field. +func (o *ExpandableApprovalRequestResponse) SetResource(v ExpandedResourceRep) { + o.Resource = &v +} + +func (o ExpandableApprovalRequestResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["serviceKind"] = o.ServiceKind + } + if o.RequestorId != nil { + toSerialize["requestorId"] = o.RequestorId + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["reviewStatus"] = o.ReviewStatus + } + if true { + toSerialize["allReviews"] = o.AllReviews + } + if true { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.AppliedDate != nil { + toSerialize["appliedDate"] = o.AppliedDate + } + if o.AppliedByMemberId != nil { + toSerialize["appliedByMemberId"] = o.AppliedByMemberId + } + if o.AppliedByServiceTokenId != nil { + toSerialize["appliedByServiceTokenId"] = o.AppliedByServiceTokenId + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["instructions"] = o.Instructions + } + if true { + toSerialize["conflicts"] = o.Conflicts + } + if true { + toSerialize["_links"] = o.Links + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.OperatingOnId != nil { + toSerialize["operatingOnId"] = o.OperatingOnId + } + if o.IntegrationMetadata != nil { + toSerialize["integrationMetadata"] = o.IntegrationMetadata + } + if o.Source != nil { + toSerialize["source"] = o.Source + } + if o.CustomWorkflowMetadata != nil { + toSerialize["customWorkflowMetadata"] = o.CustomWorkflowMetadata + } + if o.ResourceId != nil { + toSerialize["resourceId"] = o.ResourceId + } + if o.ApprovalSettings != nil { + toSerialize["approvalSettings"] = o.ApprovalSettings + } + if o.Project != nil { + toSerialize["project"] = o.Project + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + if o.Flag != nil { + toSerialize["flag"] = o.Flag + } + if o.Resource != nil { + toSerialize["resource"] = o.Resource + } + return json.Marshal(toSerialize) +} + +type NullableExpandableApprovalRequestResponse struct { + value *ExpandableApprovalRequestResponse + isSet bool +} + +func (v NullableExpandableApprovalRequestResponse) Get() *ExpandableApprovalRequestResponse { + return v.value +} + +func (v *NullableExpandableApprovalRequestResponse) Set(val *ExpandableApprovalRequestResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpandableApprovalRequestResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpandableApprovalRequestResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpandableApprovalRequestResponse(val *ExpandableApprovalRequestResponse) *NullableExpandableApprovalRequestResponse { + return &NullableExpandableApprovalRequestResponse{value: val, isSet: true} +} + +func (v NullableExpandableApprovalRequestResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpandableApprovalRequestResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_requests_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_requests_response.go new file mode 100644 index 00000000..f0da5a44 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expandable_approval_requests_response.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpandableApprovalRequestsResponse struct for ExpandableApprovalRequestsResponse +type ExpandableApprovalRequestsResponse struct { + // An array of approval requests + Items []ExpandableApprovalRequestResponse `json:"items"` + // Total number of approval requests + TotalCount int32 `json:"totalCount"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewExpandableApprovalRequestsResponse instantiates a new ExpandableApprovalRequestsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpandableApprovalRequestsResponse(items []ExpandableApprovalRequestResponse, totalCount int32, links map[string]Link) *ExpandableApprovalRequestsResponse { + this := ExpandableApprovalRequestsResponse{} + this.Items = items + this.TotalCount = totalCount + this.Links = links + return &this +} + +// NewExpandableApprovalRequestsResponseWithDefaults instantiates a new ExpandableApprovalRequestsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpandableApprovalRequestsResponseWithDefaults() *ExpandableApprovalRequestsResponse { + this := ExpandableApprovalRequestsResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *ExpandableApprovalRequestsResponse) GetItems() []ExpandableApprovalRequestResponse { + if o == nil { + var ret []ExpandableApprovalRequestResponse + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestsResponse) GetItemsOk() ([]ExpandableApprovalRequestResponse, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExpandableApprovalRequestsResponse) SetItems(v []ExpandableApprovalRequestResponse) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *ExpandableApprovalRequestsResponse) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestsResponse) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *ExpandableApprovalRequestsResponse) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetLinks returns the Links field value +func (o *ExpandableApprovalRequestsResponse) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ExpandableApprovalRequestsResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ExpandableApprovalRequestsResponse) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ExpandableApprovalRequestsResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableExpandableApprovalRequestsResponse struct { + value *ExpandableApprovalRequestsResponse + isSet bool +} + +func (v NullableExpandableApprovalRequestsResponse) Get() *ExpandableApprovalRequestsResponse { + return v.value +} + +func (v *NullableExpandableApprovalRequestsResponse) Set(val *ExpandableApprovalRequestsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpandableApprovalRequestsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpandableApprovalRequestsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpandableApprovalRequestsResponse(val *ExpandableApprovalRequestsResponse) *NullableExpandableApprovalRequestsResponse { + return &NullableExpandableApprovalRequestsResponse{value: val, isSet: true} +} + +func (v NullableExpandableApprovalRequestsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpandableApprovalRequestsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_flag_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_flag_rep.go new file mode 100644 index 00000000..795524ba --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_flag_rep.go @@ -0,0 +1,667 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpandedFlagRep struct for ExpandedFlagRep +type ExpandedFlagRep struct { + // A human-friendly name for the feature flag + Name string `json:"name"` + // Kind of feature flag + Kind string `json:"kind"` + // Description of the feature flag + Description *string `json:"description,omitempty"` + // A unique key used to reference the flag in your code + Key string `json:"key"` + // Version of the feature flag + Version int32 `json:"_version"` + CreationDate int64 `json:"creationDate"` + // Deprecated, use clientSideAvailability. Whether this flag should be made available to the client-side JavaScript SDK + // Deprecated + IncludeInSnippet *bool `json:"includeInSnippet,omitempty"` + ClientSideAvailability *ClientSideAvailability `json:"clientSideAvailability,omitempty"` + // An array of possible variations for the flag + Variations []Variation `json:"variations"` + // Whether the flag is a temporary flag + Temporary bool `json:"temporary"` + // Tags for the feature flag + Tags []string `json:"tags"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of the member who maintains the flag + MaintainerId *string `json:"maintainerId,omitempty"` + Maintainer *MemberSummary `json:"_maintainer,omitempty"` + CustomProperties map[string]CustomProperty `json:"customProperties"` + // Boolean indicating if the feature flag is archived + Archived bool `json:"archived"` + ArchivedDate *int64 `json:"archivedDate,omitempty"` + Defaults *Defaults `json:"defaults,omitempty"` +} + +// NewExpandedFlagRep instantiates a new ExpandedFlagRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpandedFlagRep(name string, kind string, key string, version int32, creationDate int64, variations []Variation, temporary bool, tags []string, links map[string]Link, customProperties map[string]CustomProperty, archived bool) *ExpandedFlagRep { + this := ExpandedFlagRep{} + this.Name = name + this.Kind = kind + this.Key = key + this.Version = version + this.CreationDate = creationDate + this.Variations = variations + this.Temporary = temporary + this.Tags = tags + this.Links = links + this.CustomProperties = customProperties + this.Archived = archived + return &this +} + +// NewExpandedFlagRepWithDefaults instantiates a new ExpandedFlagRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpandedFlagRepWithDefaults() *ExpandedFlagRep { + this := ExpandedFlagRep{} + return &this +} + +// GetName returns the Name field value +func (o *ExpandedFlagRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ExpandedFlagRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *ExpandedFlagRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ExpandedFlagRep) SetKind(v string) { + o.Kind = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ExpandedFlagRep) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *ExpandedFlagRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ExpandedFlagRep) SetKey(v string) { + o.Key = v +} + +// GetVersion returns the Version field value +func (o *ExpandedFlagRep) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ExpandedFlagRep) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *ExpandedFlagRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *ExpandedFlagRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetIncludeInSnippet returns the IncludeInSnippet field value if set, zero value otherwise. +// Deprecated +func (o *ExpandedFlagRep) GetIncludeInSnippet() bool { + if o == nil || o.IncludeInSnippet == nil { + var ret bool + return ret + } + return *o.IncludeInSnippet +} + +// GetIncludeInSnippetOk returns a tuple with the IncludeInSnippet field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *ExpandedFlagRep) GetIncludeInSnippetOk() (*bool, bool) { + if o == nil || o.IncludeInSnippet == nil { + return nil, false + } + return o.IncludeInSnippet, true +} + +// HasIncludeInSnippet returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasIncludeInSnippet() bool { + if o != nil && o.IncludeInSnippet != nil { + return true + } + + return false +} + +// SetIncludeInSnippet gets a reference to the given bool and assigns it to the IncludeInSnippet field. +// Deprecated +func (o *ExpandedFlagRep) SetIncludeInSnippet(v bool) { + o.IncludeInSnippet = &v +} + +// GetClientSideAvailability returns the ClientSideAvailability field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetClientSideAvailability() ClientSideAvailability { + if o == nil || o.ClientSideAvailability == nil { + var ret ClientSideAvailability + return ret + } + return *o.ClientSideAvailability +} + +// GetClientSideAvailabilityOk returns a tuple with the ClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetClientSideAvailabilityOk() (*ClientSideAvailability, bool) { + if o == nil || o.ClientSideAvailability == nil { + return nil, false + } + return o.ClientSideAvailability, true +} + +// HasClientSideAvailability returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasClientSideAvailability() bool { + if o != nil && o.ClientSideAvailability != nil { + return true + } + + return false +} + +// SetClientSideAvailability gets a reference to the given ClientSideAvailability and assigns it to the ClientSideAvailability field. +func (o *ExpandedFlagRep) SetClientSideAvailability(v ClientSideAvailability) { + o.ClientSideAvailability = &v +} + +// GetVariations returns the Variations field value +func (o *ExpandedFlagRep) GetVariations() []Variation { + if o == nil { + var ret []Variation + return ret + } + + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetVariationsOk() ([]Variation, bool) { + if o == nil { + return nil, false + } + return o.Variations, true +} + +// SetVariations sets field value +func (o *ExpandedFlagRep) SetVariations(v []Variation) { + o.Variations = v +} + +// GetTemporary returns the Temporary field value +func (o *ExpandedFlagRep) GetTemporary() bool { + if o == nil { + var ret bool + return ret + } + + return o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetTemporaryOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Temporary, true +} + +// SetTemporary sets field value +func (o *ExpandedFlagRep) SetTemporary(v bool) { + o.Temporary = v +} + +// GetTags returns the Tags field value +func (o *ExpandedFlagRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *ExpandedFlagRep) SetTags(v []string) { + o.Tags = v +} + +// GetLinks returns the Links field value +func (o *ExpandedFlagRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ExpandedFlagRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *ExpandedFlagRep) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetMaintainer() MemberSummary { + if o == nil || o.Maintainer == nil { + var ret MemberSummary + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetMaintainerOk() (*MemberSummary, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MemberSummary and assigns it to the Maintainer field. +func (o *ExpandedFlagRep) SetMaintainer(v MemberSummary) { + o.Maintainer = &v +} + +// GetCustomProperties returns the CustomProperties field value +func (o *ExpandedFlagRep) GetCustomProperties() map[string]CustomProperty { + if o == nil { + var ret map[string]CustomProperty + return ret + } + + return o.CustomProperties +} + +// GetCustomPropertiesOk returns a tuple with the CustomProperties field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetCustomPropertiesOk() (*map[string]CustomProperty, bool) { + if o == nil { + return nil, false + } + return &o.CustomProperties, true +} + +// SetCustomProperties sets field value +func (o *ExpandedFlagRep) SetCustomProperties(v map[string]CustomProperty) { + o.CustomProperties = v +} + +// GetArchived returns the Archived field value +func (o *ExpandedFlagRep) GetArchived() bool { + if o == nil { + var ret bool + return ret + } + + return o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetArchivedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Archived, true +} + +// SetArchived sets field value +func (o *ExpandedFlagRep) SetArchived(v bool) { + o.Archived = v +} + +// GetArchivedDate returns the ArchivedDate field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetArchivedDate() int64 { + if o == nil || o.ArchivedDate == nil { + var ret int64 + return ret + } + return *o.ArchivedDate +} + +// GetArchivedDateOk returns a tuple with the ArchivedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetArchivedDateOk() (*int64, bool) { + if o == nil || o.ArchivedDate == nil { + return nil, false + } + return o.ArchivedDate, true +} + +// HasArchivedDate returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasArchivedDate() bool { + if o != nil && o.ArchivedDate != nil { + return true + } + + return false +} + +// SetArchivedDate gets a reference to the given int64 and assigns it to the ArchivedDate field. +func (o *ExpandedFlagRep) SetArchivedDate(v int64) { + o.ArchivedDate = &v +} + +// GetDefaults returns the Defaults field value if set, zero value otherwise. +func (o *ExpandedFlagRep) GetDefaults() Defaults { + if o == nil || o.Defaults == nil { + var ret Defaults + return ret + } + return *o.Defaults +} + +// GetDefaultsOk returns a tuple with the Defaults field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedFlagRep) GetDefaultsOk() (*Defaults, bool) { + if o == nil || o.Defaults == nil { + return nil, false + } + return o.Defaults, true +} + +// HasDefaults returns a boolean if a field has been set. +func (o *ExpandedFlagRep) HasDefaults() bool { + if o != nil && o.Defaults != nil { + return true + } + + return false +} + +// SetDefaults gets a reference to the given Defaults and assigns it to the Defaults field. +func (o *ExpandedFlagRep) SetDefaults(v Defaults) { + o.Defaults = &v +} + +func (o ExpandedFlagRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if o.IncludeInSnippet != nil { + toSerialize["includeInSnippet"] = o.IncludeInSnippet + } + if o.ClientSideAvailability != nil { + toSerialize["clientSideAvailability"] = o.ClientSideAvailability + } + if true { + toSerialize["variations"] = o.Variations + } + if true { + toSerialize["temporary"] = o.Temporary + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["_links"] = o.Links + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if true { + toSerialize["customProperties"] = o.CustomProperties + } + if true { + toSerialize["archived"] = o.Archived + } + if o.ArchivedDate != nil { + toSerialize["archivedDate"] = o.ArchivedDate + } + if o.Defaults != nil { + toSerialize["defaults"] = o.Defaults + } + return json.Marshal(toSerialize) +} + +type NullableExpandedFlagRep struct { + value *ExpandedFlagRep + isSet bool +} + +func (v NullableExpandedFlagRep) Get() *ExpandedFlagRep { + return v.value +} + +func (v *NullableExpandedFlagRep) Set(val *ExpandedFlagRep) { + v.value = val + v.isSet = true +} + +func (v NullableExpandedFlagRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExpandedFlagRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpandedFlagRep(val *ExpandedFlagRep) *NullableExpandedFlagRep { + return &NullableExpandedFlagRep{value: val, isSet: true} +} + +func (v NullableExpandedFlagRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpandedFlagRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_resource_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_resource_rep.go new file mode 100644 index 00000000..ab8dda67 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expanded_resource_rep.go @@ -0,0 +1,182 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpandedResourceRep struct for ExpandedResourceRep +type ExpandedResourceRep struct { + // The type of resource + Kind string `json:"kind"` + Flag *ExpandedFlagRep `json:"flag,omitempty"` + Segment *UserSegment `json:"segment,omitempty"` +} + +// NewExpandedResourceRep instantiates a new ExpandedResourceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpandedResourceRep(kind string) *ExpandedResourceRep { + this := ExpandedResourceRep{} + this.Kind = kind + return &this +} + +// NewExpandedResourceRepWithDefaults instantiates a new ExpandedResourceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpandedResourceRepWithDefaults() *ExpandedResourceRep { + this := ExpandedResourceRep{} + return &this +} + +// GetKind returns the Kind field value +func (o *ExpandedResourceRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ExpandedResourceRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ExpandedResourceRep) SetKind(v string) { + o.Kind = v +} + +// GetFlag returns the Flag field value if set, zero value otherwise. +func (o *ExpandedResourceRep) GetFlag() ExpandedFlagRep { + if o == nil || o.Flag == nil { + var ret ExpandedFlagRep + return ret + } + return *o.Flag +} + +// GetFlagOk returns a tuple with the Flag field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedResourceRep) GetFlagOk() (*ExpandedFlagRep, bool) { + if o == nil || o.Flag == nil { + return nil, false + } + return o.Flag, true +} + +// HasFlag returns a boolean if a field has been set. +func (o *ExpandedResourceRep) HasFlag() bool { + if o != nil && o.Flag != nil { + return true + } + + return false +} + +// SetFlag gets a reference to the given ExpandedFlagRep and assigns it to the Flag field. +func (o *ExpandedResourceRep) SetFlag(v ExpandedFlagRep) { + o.Flag = &v +} + +// GetSegment returns the Segment field value if set, zero value otherwise. +func (o *ExpandedResourceRep) GetSegment() UserSegment { + if o == nil || o.Segment == nil { + var ret UserSegment + return ret + } + return *o.Segment +} + +// GetSegmentOk returns a tuple with the Segment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpandedResourceRep) GetSegmentOk() (*UserSegment, bool) { + if o == nil || o.Segment == nil { + return nil, false + } + return o.Segment, true +} + +// HasSegment returns a boolean if a field has been set. +func (o *ExpandedResourceRep) HasSegment() bool { + if o != nil && o.Segment != nil { + return true + } + + return false +} + +// SetSegment gets a reference to the given UserSegment and assigns it to the Segment field. +func (o *ExpandedResourceRep) SetSegment(v UserSegment) { + o.Segment = &v +} + +func (o ExpandedResourceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if o.Flag != nil { + toSerialize["flag"] = o.Flag + } + if o.Segment != nil { + toSerialize["segment"] = o.Segment + } + return json.Marshal(toSerialize) +} + +type NullableExpandedResourceRep struct { + value *ExpandedResourceRep + isSet bool +} + +func (v NullableExpandedResourceRep) Get() *ExpandedResourceRep { + return v.value +} + +func (v *NullableExpandedResourceRep) Set(val *ExpandedResourceRep) { + v.value = val + v.isSet = true +} + +func (v NullableExpandedResourceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExpandedResourceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpandedResourceRep(val *ExpandedResourceRep) *NullableExpandedResourceRep { + return &NullableExpandedResourceRep{value: val, isSet: true} +} + +func (v NullableExpandedResourceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpandedResourceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment.go new file mode 100644 index 00000000..31b1880e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment.go @@ -0,0 +1,514 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Experiment struct for Experiment +type Experiment struct { + // The experiment ID + Id *string `json:"_id,omitempty"` + // The experiment key + Key string `json:"key"` + // The experiment name + Name string `json:"name"` + // The experiment description + Description *string `json:"description,omitempty"` + // The ID of the member who maintains this experiment. + MaintainerId string `json:"_maintainerId"` + CreationDate int64 `json:"_creationDate"` + EnvironmentKey string `json:"environmentKey"` + ArchivedDate *int64 `json:"archivedDate,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The holdout ID + HoldoutId *string `json:"holdoutId,omitempty"` + CurrentIteration *IterationRep `json:"currentIteration,omitempty"` + DraftIteration *IterationRep `json:"draftIteration,omitempty"` + // Details on the previous iterations for this experiment. + PreviousIterations []IterationRep `json:"previousIterations,omitempty"` +} + +// NewExperiment instantiates a new Experiment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperiment(key string, name string, maintainerId string, creationDate int64, environmentKey string, links map[string]Link) *Experiment { + this := Experiment{} + this.Key = key + this.Name = name + this.MaintainerId = maintainerId + this.CreationDate = creationDate + this.EnvironmentKey = environmentKey + this.Links = links + return &this +} + +// NewExperimentWithDefaults instantiates a new Experiment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentWithDefaults() *Experiment { + this := Experiment{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Experiment) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Experiment) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Experiment) SetId(v string) { + o.Id = &v +} + +// GetKey returns the Key field value +func (o *Experiment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *Experiment) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *Experiment) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Experiment) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Experiment) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Experiment) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Experiment) SetDescription(v string) { + o.Description = &v +} + +// GetMaintainerId returns the MaintainerId field value +func (o *Experiment) GetMaintainerId() string { + if o == nil { + var ret string + return ret + } + + return o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetMaintainerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MaintainerId, true +} + +// SetMaintainerId sets field value +func (o *Experiment) SetMaintainerId(v string) { + o.MaintainerId = v +} + +// GetCreationDate returns the CreationDate field value +func (o *Experiment) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *Experiment) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *Experiment) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *Experiment) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetArchivedDate returns the ArchivedDate field value if set, zero value otherwise. +func (o *Experiment) GetArchivedDate() int64 { + if o == nil || o.ArchivedDate == nil { + var ret int64 + return ret + } + return *o.ArchivedDate +} + +// GetArchivedDateOk returns a tuple with the ArchivedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetArchivedDateOk() (*int64, bool) { + if o == nil || o.ArchivedDate == nil { + return nil, false + } + return o.ArchivedDate, true +} + +// HasArchivedDate returns a boolean if a field has been set. +func (o *Experiment) HasArchivedDate() bool { + if o != nil && o.ArchivedDate != nil { + return true + } + + return false +} + +// SetArchivedDate gets a reference to the given int64 and assigns it to the ArchivedDate field. +func (o *Experiment) SetArchivedDate(v int64) { + o.ArchivedDate = &v +} + +// GetLinks returns the Links field value +func (o *Experiment) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Experiment) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Experiment) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetHoldoutId returns the HoldoutId field value if set, zero value otherwise. +func (o *Experiment) GetHoldoutId() string { + if o == nil || o.HoldoutId == nil { + var ret string + return ret + } + return *o.HoldoutId +} + +// GetHoldoutIdOk returns a tuple with the HoldoutId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetHoldoutIdOk() (*string, bool) { + if o == nil || o.HoldoutId == nil { + return nil, false + } + return o.HoldoutId, true +} + +// HasHoldoutId returns a boolean if a field has been set. +func (o *Experiment) HasHoldoutId() bool { + if o != nil && o.HoldoutId != nil { + return true + } + + return false +} + +// SetHoldoutId gets a reference to the given string and assigns it to the HoldoutId field. +func (o *Experiment) SetHoldoutId(v string) { + o.HoldoutId = &v +} + +// GetCurrentIteration returns the CurrentIteration field value if set, zero value otherwise. +func (o *Experiment) GetCurrentIteration() IterationRep { + if o == nil || o.CurrentIteration == nil { + var ret IterationRep + return ret + } + return *o.CurrentIteration +} + +// GetCurrentIterationOk returns a tuple with the CurrentIteration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetCurrentIterationOk() (*IterationRep, bool) { + if o == nil || o.CurrentIteration == nil { + return nil, false + } + return o.CurrentIteration, true +} + +// HasCurrentIteration returns a boolean if a field has been set. +func (o *Experiment) HasCurrentIteration() bool { + if o != nil && o.CurrentIteration != nil { + return true + } + + return false +} + +// SetCurrentIteration gets a reference to the given IterationRep and assigns it to the CurrentIteration field. +func (o *Experiment) SetCurrentIteration(v IterationRep) { + o.CurrentIteration = &v +} + +// GetDraftIteration returns the DraftIteration field value if set, zero value otherwise. +func (o *Experiment) GetDraftIteration() IterationRep { + if o == nil || o.DraftIteration == nil { + var ret IterationRep + return ret + } + return *o.DraftIteration +} + +// GetDraftIterationOk returns a tuple with the DraftIteration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetDraftIterationOk() (*IterationRep, bool) { + if o == nil || o.DraftIteration == nil { + return nil, false + } + return o.DraftIteration, true +} + +// HasDraftIteration returns a boolean if a field has been set. +func (o *Experiment) HasDraftIteration() bool { + if o != nil && o.DraftIteration != nil { + return true + } + + return false +} + +// SetDraftIteration gets a reference to the given IterationRep and assigns it to the DraftIteration field. +func (o *Experiment) SetDraftIteration(v IterationRep) { + o.DraftIteration = &v +} + +// GetPreviousIterations returns the PreviousIterations field value if set, zero value otherwise. +func (o *Experiment) GetPreviousIterations() []IterationRep { + if o == nil || o.PreviousIterations == nil { + var ret []IterationRep + return ret + } + return o.PreviousIterations +} + +// GetPreviousIterationsOk returns a tuple with the PreviousIterations field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Experiment) GetPreviousIterationsOk() ([]IterationRep, bool) { + if o == nil || o.PreviousIterations == nil { + return nil, false + } + return o.PreviousIterations, true +} + +// HasPreviousIterations returns a boolean if a field has been set. +func (o *Experiment) HasPreviousIterations() bool { + if o != nil && o.PreviousIterations != nil { + return true + } + + return false +} + +// SetPreviousIterations gets a reference to the given []IterationRep and assigns it to the PreviousIterations field. +func (o *Experiment) SetPreviousIterations(v []IterationRep) { + o.PreviousIterations = v +} + +func (o Experiment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["_maintainerId"] = o.MaintainerId + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.ArchivedDate != nil { + toSerialize["archivedDate"] = o.ArchivedDate + } + if true { + toSerialize["_links"] = o.Links + } + if o.HoldoutId != nil { + toSerialize["holdoutId"] = o.HoldoutId + } + if o.CurrentIteration != nil { + toSerialize["currentIteration"] = o.CurrentIteration + } + if o.DraftIteration != nil { + toSerialize["draftIteration"] = o.DraftIteration + } + if o.PreviousIterations != nil { + toSerialize["previousIterations"] = o.PreviousIterations + } + return json.Marshal(toSerialize) +} + +type NullableExperiment struct { + value *Experiment + isSet bool +} + +func (v NullableExperiment) Get() *Experiment { + return v.value +} + +func (v *NullableExperiment) Set(val *Experiment) { + v.value = val + v.isSet = true +} + +func (v NullableExperiment) IsSet() bool { + return v.isSet +} + +func (v *NullableExperiment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperiment(val *Experiment) *NullableExperiment { + return &NullableExperiment{value: val, isSet: true} +} + +func (v NullableExperiment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperiment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_allocation_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_allocation_rep.go new file mode 100644 index 00000000..d856743c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_allocation_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentAllocationRep struct for ExperimentAllocationRep +type ExperimentAllocationRep struct { + DefaultVariation int32 `json:"defaultVariation"` + CanReshuffle bool `json:"canReshuffle"` +} + +// NewExperimentAllocationRep instantiates a new ExperimentAllocationRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentAllocationRep(defaultVariation int32, canReshuffle bool) *ExperimentAllocationRep { + this := ExperimentAllocationRep{} + this.DefaultVariation = defaultVariation + this.CanReshuffle = canReshuffle + return &this +} + +// NewExperimentAllocationRepWithDefaults instantiates a new ExperimentAllocationRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentAllocationRepWithDefaults() *ExperimentAllocationRep { + this := ExperimentAllocationRep{} + return &this +} + +// GetDefaultVariation returns the DefaultVariation field value +func (o *ExperimentAllocationRep) GetDefaultVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.DefaultVariation +} + +// GetDefaultVariationOk returns a tuple with the DefaultVariation field value +// and a boolean to check if the value has been set. +func (o *ExperimentAllocationRep) GetDefaultVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.DefaultVariation, true +} + +// SetDefaultVariation sets field value +func (o *ExperimentAllocationRep) SetDefaultVariation(v int32) { + o.DefaultVariation = v +} + +// GetCanReshuffle returns the CanReshuffle field value +func (o *ExperimentAllocationRep) GetCanReshuffle() bool { + if o == nil { + var ret bool + return ret + } + + return o.CanReshuffle +} + +// GetCanReshuffleOk returns a tuple with the CanReshuffle field value +// and a boolean to check if the value has been set. +func (o *ExperimentAllocationRep) GetCanReshuffleOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.CanReshuffle, true +} + +// SetCanReshuffle sets field value +func (o *ExperimentAllocationRep) SetCanReshuffle(v bool) { + o.CanReshuffle = v +} + +func (o ExperimentAllocationRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["defaultVariation"] = o.DefaultVariation + } + if true { + toSerialize["canReshuffle"] = o.CanReshuffle + } + return json.Marshal(toSerialize) +} + +type NullableExperimentAllocationRep struct { + value *ExperimentAllocationRep + isSet bool +} + +func (v NullableExperimentAllocationRep) Get() *ExperimentAllocationRep { + return v.value +} + +func (v *NullableExperimentAllocationRep) Set(val *ExperimentAllocationRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentAllocationRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentAllocationRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentAllocationRep(val *ExperimentAllocationRep) *NullableExperimentAllocationRep { + return &NullableExperimentAllocationRep{value: val, isSet: true} +} + +func (v NullableExperimentAllocationRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentAllocationRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_bayesian_results_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_bayesian_results_rep.go new file mode 100644 index 00000000..63ab45d3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_bayesian_results_rep.go @@ -0,0 +1,268 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentBayesianResultsRep struct for ExperimentBayesianResultsRep +type ExperimentBayesianResultsRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // Deprecated, use results instead. Only populated when response does not contain results sliced by multiple attributes. + // Deprecated + TreatmentResults []TreatmentResultRep `json:"treatmentResults,omitempty"` + MetricSeen *MetricSeen `json:"metricSeen,omitempty"` + // The probability of a Sample Ratio Mismatch + ProbabilityOfMismatch *float32 `json:"probabilityOfMismatch,omitempty"` + // A list of attribute values and their corresponding treatment results + Results []SlicedResultsRep `json:"results,omitempty"` +} + +// NewExperimentBayesianResultsRep instantiates a new ExperimentBayesianResultsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentBayesianResultsRep() *ExperimentBayesianResultsRep { + this := ExperimentBayesianResultsRep{} + return &this +} + +// NewExperimentBayesianResultsRepWithDefaults instantiates a new ExperimentBayesianResultsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentBayesianResultsRepWithDefaults() *ExperimentBayesianResultsRep { + this := ExperimentBayesianResultsRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExperimentBayesianResultsRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentBayesianResultsRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExperimentBayesianResultsRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExperimentBayesianResultsRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTreatmentResults returns the TreatmentResults field value if set, zero value otherwise. +// Deprecated +func (o *ExperimentBayesianResultsRep) GetTreatmentResults() []TreatmentResultRep { + if o == nil || o.TreatmentResults == nil { + var ret []TreatmentResultRep + return ret + } + return o.TreatmentResults +} + +// GetTreatmentResultsOk returns a tuple with the TreatmentResults field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *ExperimentBayesianResultsRep) GetTreatmentResultsOk() ([]TreatmentResultRep, bool) { + if o == nil || o.TreatmentResults == nil { + return nil, false + } + return o.TreatmentResults, true +} + +// HasTreatmentResults returns a boolean if a field has been set. +func (o *ExperimentBayesianResultsRep) HasTreatmentResults() bool { + if o != nil && o.TreatmentResults != nil { + return true + } + + return false +} + +// SetTreatmentResults gets a reference to the given []TreatmentResultRep and assigns it to the TreatmentResults field. +// Deprecated +func (o *ExperimentBayesianResultsRep) SetTreatmentResults(v []TreatmentResultRep) { + o.TreatmentResults = v +} + +// GetMetricSeen returns the MetricSeen field value if set, zero value otherwise. +func (o *ExperimentBayesianResultsRep) GetMetricSeen() MetricSeen { + if o == nil || o.MetricSeen == nil { + var ret MetricSeen + return ret + } + return *o.MetricSeen +} + +// GetMetricSeenOk returns a tuple with the MetricSeen field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentBayesianResultsRep) GetMetricSeenOk() (*MetricSeen, bool) { + if o == nil || o.MetricSeen == nil { + return nil, false + } + return o.MetricSeen, true +} + +// HasMetricSeen returns a boolean if a field has been set. +func (o *ExperimentBayesianResultsRep) HasMetricSeen() bool { + if o != nil && o.MetricSeen != nil { + return true + } + + return false +} + +// SetMetricSeen gets a reference to the given MetricSeen and assigns it to the MetricSeen field. +func (o *ExperimentBayesianResultsRep) SetMetricSeen(v MetricSeen) { + o.MetricSeen = &v +} + +// GetProbabilityOfMismatch returns the ProbabilityOfMismatch field value if set, zero value otherwise. +func (o *ExperimentBayesianResultsRep) GetProbabilityOfMismatch() float32 { + if o == nil || o.ProbabilityOfMismatch == nil { + var ret float32 + return ret + } + return *o.ProbabilityOfMismatch +} + +// GetProbabilityOfMismatchOk returns a tuple with the ProbabilityOfMismatch field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentBayesianResultsRep) GetProbabilityOfMismatchOk() (*float32, bool) { + if o == nil || o.ProbabilityOfMismatch == nil { + return nil, false + } + return o.ProbabilityOfMismatch, true +} + +// HasProbabilityOfMismatch returns a boolean if a field has been set. +func (o *ExperimentBayesianResultsRep) HasProbabilityOfMismatch() bool { + if o != nil && o.ProbabilityOfMismatch != nil { + return true + } + + return false +} + +// SetProbabilityOfMismatch gets a reference to the given float32 and assigns it to the ProbabilityOfMismatch field. +func (o *ExperimentBayesianResultsRep) SetProbabilityOfMismatch(v float32) { + o.ProbabilityOfMismatch = &v +} + +// GetResults returns the Results field value if set, zero value otherwise. +func (o *ExperimentBayesianResultsRep) GetResults() []SlicedResultsRep { + if o == nil || o.Results == nil { + var ret []SlicedResultsRep + return ret + } + return o.Results +} + +// GetResultsOk returns a tuple with the Results field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentBayesianResultsRep) GetResultsOk() ([]SlicedResultsRep, bool) { + if o == nil || o.Results == nil { + return nil, false + } + return o.Results, true +} + +// HasResults returns a boolean if a field has been set. +func (o *ExperimentBayesianResultsRep) HasResults() bool { + if o != nil && o.Results != nil { + return true + } + + return false +} + +// SetResults gets a reference to the given []SlicedResultsRep and assigns it to the Results field. +func (o *ExperimentBayesianResultsRep) SetResults(v []SlicedResultsRep) { + o.Results = v +} + +func (o ExperimentBayesianResultsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TreatmentResults != nil { + toSerialize["treatmentResults"] = o.TreatmentResults + } + if o.MetricSeen != nil { + toSerialize["metricSeen"] = o.MetricSeen + } + if o.ProbabilityOfMismatch != nil { + toSerialize["probabilityOfMismatch"] = o.ProbabilityOfMismatch + } + if o.Results != nil { + toSerialize["results"] = o.Results + } + return json.Marshal(toSerialize) +} + +type NullableExperimentBayesianResultsRep struct { + value *ExperimentBayesianResultsRep + isSet bool +} + +func (v NullableExperimentBayesianResultsRep) Get() *ExperimentBayesianResultsRep { + return v.value +} + +func (v *NullableExperimentBayesianResultsRep) Set(val *ExperimentBayesianResultsRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentBayesianResultsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentBayesianResultsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentBayesianResultsRep(val *ExperimentBayesianResultsRep) *NullableExperimentBayesianResultsRep { + return &NullableExperimentBayesianResultsRep{value: val, isSet: true} +} + +func (v NullableExperimentBayesianResultsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentBayesianResultsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_collection_rep.go new file mode 100644 index 00000000..148625e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_collection_rep.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentCollectionRep struct for ExperimentCollectionRep +type ExperimentCollectionRep struct { + // An array of experiments + Items []Experiment `json:"items"` + // The total number of experiments in this project and environment. Does not include legacy experiments. + TotalCount *int32 `json:"total_count,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewExperimentCollectionRep instantiates a new ExperimentCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentCollectionRep(items []Experiment) *ExperimentCollectionRep { + this := ExperimentCollectionRep{} + this.Items = items + return &this +} + +// NewExperimentCollectionRepWithDefaults instantiates a new ExperimentCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentCollectionRepWithDefaults() *ExperimentCollectionRep { + this := ExperimentCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *ExperimentCollectionRep) GetItems() []Experiment { + if o == nil { + var ret []Experiment + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExperimentCollectionRep) GetItemsOk() ([]Experiment, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExperimentCollectionRep) SetItems(v []Experiment) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *ExperimentCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *ExperimentCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *ExperimentCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExperimentCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExperimentCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExperimentCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ExperimentCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["total_count"] = o.TotalCount + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableExperimentCollectionRep struct { + value *ExperimentCollectionRep + isSet bool +} + +func (v NullableExperimentCollectionRep) Get() *ExperimentCollectionRep { + return v.value +} + +func (v *NullableExperimentCollectionRep) Set(val *ExperimentCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentCollectionRep(val *ExperimentCollectionRep) *NullableExperimentCollectionRep { + return &NullableExperimentCollectionRep{value: val, isSet: true} +} + +func (v NullableExperimentCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_enabled_period_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_enabled_period_rep.go new file mode 100644 index 00000000..3cfdda9e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_enabled_period_rep.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentEnabledPeriodRep struct for ExperimentEnabledPeriodRep +type ExperimentEnabledPeriodRep struct { + StartDate *int64 `json:"startDate,omitempty"` + StopDate *int64 `json:"stopDate,omitempty"` +} + +// NewExperimentEnabledPeriodRep instantiates a new ExperimentEnabledPeriodRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentEnabledPeriodRep() *ExperimentEnabledPeriodRep { + this := ExperimentEnabledPeriodRep{} + return &this +} + +// NewExperimentEnabledPeriodRepWithDefaults instantiates a new ExperimentEnabledPeriodRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentEnabledPeriodRepWithDefaults() *ExperimentEnabledPeriodRep { + this := ExperimentEnabledPeriodRep{} + return &this +} + +// GetStartDate returns the StartDate field value if set, zero value otherwise. +func (o *ExperimentEnabledPeriodRep) GetStartDate() int64 { + if o == nil || o.StartDate == nil { + var ret int64 + return ret + } + return *o.StartDate +} + +// GetStartDateOk returns a tuple with the StartDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentEnabledPeriodRep) GetStartDateOk() (*int64, bool) { + if o == nil || o.StartDate == nil { + return nil, false + } + return o.StartDate, true +} + +// HasStartDate returns a boolean if a field has been set. +func (o *ExperimentEnabledPeriodRep) HasStartDate() bool { + if o != nil && o.StartDate != nil { + return true + } + + return false +} + +// SetStartDate gets a reference to the given int64 and assigns it to the StartDate field. +func (o *ExperimentEnabledPeriodRep) SetStartDate(v int64) { + o.StartDate = &v +} + +// GetStopDate returns the StopDate field value if set, zero value otherwise. +func (o *ExperimentEnabledPeriodRep) GetStopDate() int64 { + if o == nil || o.StopDate == nil { + var ret int64 + return ret + } + return *o.StopDate +} + +// GetStopDateOk returns a tuple with the StopDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentEnabledPeriodRep) GetStopDateOk() (*int64, bool) { + if o == nil || o.StopDate == nil { + return nil, false + } + return o.StopDate, true +} + +// HasStopDate returns a boolean if a field has been set. +func (o *ExperimentEnabledPeriodRep) HasStopDate() bool { + if o != nil && o.StopDate != nil { + return true + } + + return false +} + +// SetStopDate gets a reference to the given int64 and assigns it to the StopDate field. +func (o *ExperimentEnabledPeriodRep) SetStopDate(v int64) { + o.StopDate = &v +} + +func (o ExperimentEnabledPeriodRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.StartDate != nil { + toSerialize["startDate"] = o.StartDate + } + if o.StopDate != nil { + toSerialize["stopDate"] = o.StopDate + } + return json.Marshal(toSerialize) +} + +type NullableExperimentEnabledPeriodRep struct { + value *ExperimentEnabledPeriodRep + isSet bool +} + +func (v NullableExperimentEnabledPeriodRep) Get() *ExperimentEnabledPeriodRep { + return v.value +} + +func (v *NullableExperimentEnabledPeriodRep) Set(val *ExperimentEnabledPeriodRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentEnabledPeriodRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentEnabledPeriodRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentEnabledPeriodRep(val *ExperimentEnabledPeriodRep) *NullableExperimentEnabledPeriodRep { + return &NullableExperimentEnabledPeriodRep{value: val, isSet: true} +} + +func (v NullableExperimentEnabledPeriodRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentEnabledPeriodRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_environment_setting_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_environment_setting_rep.go new file mode 100644 index 00000000..67b17ee2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_environment_setting_rep.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentEnvironmentSettingRep struct for ExperimentEnvironmentSettingRep +type ExperimentEnvironmentSettingRep struct { + StartDate *int64 `json:"startDate,omitempty"` + StopDate *int64 `json:"stopDate,omitempty"` + EnabledPeriods []ExperimentEnabledPeriodRep `json:"enabledPeriods,omitempty"` +} + +// NewExperimentEnvironmentSettingRep instantiates a new ExperimentEnvironmentSettingRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentEnvironmentSettingRep() *ExperimentEnvironmentSettingRep { + this := ExperimentEnvironmentSettingRep{} + return &this +} + +// NewExperimentEnvironmentSettingRepWithDefaults instantiates a new ExperimentEnvironmentSettingRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentEnvironmentSettingRepWithDefaults() *ExperimentEnvironmentSettingRep { + this := ExperimentEnvironmentSettingRep{} + return &this +} + +// GetStartDate returns the StartDate field value if set, zero value otherwise. +func (o *ExperimentEnvironmentSettingRep) GetStartDate() int64 { + if o == nil || o.StartDate == nil { + var ret int64 + return ret + } + return *o.StartDate +} + +// GetStartDateOk returns a tuple with the StartDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentEnvironmentSettingRep) GetStartDateOk() (*int64, bool) { + if o == nil || o.StartDate == nil { + return nil, false + } + return o.StartDate, true +} + +// HasStartDate returns a boolean if a field has been set. +func (o *ExperimentEnvironmentSettingRep) HasStartDate() bool { + if o != nil && o.StartDate != nil { + return true + } + + return false +} + +// SetStartDate gets a reference to the given int64 and assigns it to the StartDate field. +func (o *ExperimentEnvironmentSettingRep) SetStartDate(v int64) { + o.StartDate = &v +} + +// GetStopDate returns the StopDate field value if set, zero value otherwise. +func (o *ExperimentEnvironmentSettingRep) GetStopDate() int64 { + if o == nil || o.StopDate == nil { + var ret int64 + return ret + } + return *o.StopDate +} + +// GetStopDateOk returns a tuple with the StopDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentEnvironmentSettingRep) GetStopDateOk() (*int64, bool) { + if o == nil || o.StopDate == nil { + return nil, false + } + return o.StopDate, true +} + +// HasStopDate returns a boolean if a field has been set. +func (o *ExperimentEnvironmentSettingRep) HasStopDate() bool { + if o != nil && o.StopDate != nil { + return true + } + + return false +} + +// SetStopDate gets a reference to the given int64 and assigns it to the StopDate field. +func (o *ExperimentEnvironmentSettingRep) SetStopDate(v int64) { + o.StopDate = &v +} + +// GetEnabledPeriods returns the EnabledPeriods field value if set, zero value otherwise. +func (o *ExperimentEnvironmentSettingRep) GetEnabledPeriods() []ExperimentEnabledPeriodRep { + if o == nil || o.EnabledPeriods == nil { + var ret []ExperimentEnabledPeriodRep + return ret + } + return o.EnabledPeriods +} + +// GetEnabledPeriodsOk returns a tuple with the EnabledPeriods field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentEnvironmentSettingRep) GetEnabledPeriodsOk() ([]ExperimentEnabledPeriodRep, bool) { + if o == nil || o.EnabledPeriods == nil { + return nil, false + } + return o.EnabledPeriods, true +} + +// HasEnabledPeriods returns a boolean if a field has been set. +func (o *ExperimentEnvironmentSettingRep) HasEnabledPeriods() bool { + if o != nil && o.EnabledPeriods != nil { + return true + } + + return false +} + +// SetEnabledPeriods gets a reference to the given []ExperimentEnabledPeriodRep and assigns it to the EnabledPeriods field. +func (o *ExperimentEnvironmentSettingRep) SetEnabledPeriods(v []ExperimentEnabledPeriodRep) { + o.EnabledPeriods = v +} + +func (o ExperimentEnvironmentSettingRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.StartDate != nil { + toSerialize["startDate"] = o.StartDate + } + if o.StopDate != nil { + toSerialize["stopDate"] = o.StopDate + } + if o.EnabledPeriods != nil { + toSerialize["enabledPeriods"] = o.EnabledPeriods + } + return json.Marshal(toSerialize) +} + +type NullableExperimentEnvironmentSettingRep struct { + value *ExperimentEnvironmentSettingRep + isSet bool +} + +func (v NullableExperimentEnvironmentSettingRep) Get() *ExperimentEnvironmentSettingRep { + return v.value +} + +func (v *NullableExperimentEnvironmentSettingRep) Set(val *ExperimentEnvironmentSettingRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentEnvironmentSettingRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentEnvironmentSettingRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentEnvironmentSettingRep(val *ExperimentEnvironmentSettingRep) *NullableExperimentEnvironmentSettingRep { + return &NullableExperimentEnvironmentSettingRep{value: val, isSet: true} +} + +func (v NullableExperimentEnvironmentSettingRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentEnvironmentSettingRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_info_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_info_rep.go new file mode 100644 index 00000000..fba4e8a3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_info_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentInfoRep struct for ExperimentInfoRep +type ExperimentInfoRep struct { + BaselineIdx int32 `json:"baselineIdx"` + Items []LegacyExperimentRep `json:"items"` +} + +// NewExperimentInfoRep instantiates a new ExperimentInfoRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentInfoRep(baselineIdx int32, items []LegacyExperimentRep) *ExperimentInfoRep { + this := ExperimentInfoRep{} + this.BaselineIdx = baselineIdx + this.Items = items + return &this +} + +// NewExperimentInfoRepWithDefaults instantiates a new ExperimentInfoRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentInfoRepWithDefaults() *ExperimentInfoRep { + this := ExperimentInfoRep{} + return &this +} + +// GetBaselineIdx returns the BaselineIdx field value +func (o *ExperimentInfoRep) GetBaselineIdx() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.BaselineIdx +} + +// GetBaselineIdxOk returns a tuple with the BaselineIdx field value +// and a boolean to check if the value has been set. +func (o *ExperimentInfoRep) GetBaselineIdxOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.BaselineIdx, true +} + +// SetBaselineIdx sets field value +func (o *ExperimentInfoRep) SetBaselineIdx(v int32) { + o.BaselineIdx = v +} + +// GetItems returns the Items field value +func (o *ExperimentInfoRep) GetItems() []LegacyExperimentRep { + if o == nil { + var ret []LegacyExperimentRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExperimentInfoRep) GetItemsOk() ([]LegacyExperimentRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExperimentInfoRep) SetItems(v []LegacyExperimentRep) { + o.Items = v +} + +func (o ExperimentInfoRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["baselineIdx"] = o.BaselineIdx + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableExperimentInfoRep struct { + value *ExperimentInfoRep + isSet bool +} + +func (v NullableExperimentInfoRep) Get() *ExperimentInfoRep { + return v.value +} + +func (v *NullableExperimentInfoRep) Set(val *ExperimentInfoRep) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentInfoRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentInfoRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentInfoRep(val *ExperimentInfoRep) *NullableExperimentInfoRep { + return &NullableExperimentInfoRep{value: val, isSet: true} +} + +func (v NullableExperimentInfoRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentInfoRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_patch_input.go new file mode 100644 index 00000000..d0d601e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_patch_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentPatchInput struct for ExperimentPatchInput +type ExperimentPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewExperimentPatchInput instantiates a new ExperimentPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentPatchInput(instructions []map[string]interface{}) *ExperimentPatchInput { + this := ExperimentPatchInput{} + this.Instructions = instructions + return &this +} + +// NewExperimentPatchInputWithDefaults instantiates a new ExperimentPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentPatchInputWithDefaults() *ExperimentPatchInput { + this := ExperimentPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *ExperimentPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *ExperimentPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *ExperimentPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *ExperimentPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *ExperimentPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *ExperimentPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o ExperimentPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableExperimentPatchInput struct { + value *ExperimentPatchInput + isSet bool +} + +func (v NullableExperimentPatchInput) Get() *ExperimentPatchInput { + return v.value +} + +func (v *NullableExperimentPatchInput) Set(val *ExperimentPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentPatchInput(val *ExperimentPatchInput) *NullableExperimentPatchInput { + return &NullableExperimentPatchInput{value: val, isSet: true} +} + +func (v NullableExperimentPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_post.go new file mode 100644 index 00000000..63994637 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_experiment_post.go @@ -0,0 +1,280 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExperimentPost struct for ExperimentPost +type ExperimentPost struct { + // The experiment name + Name string `json:"name"` + // The experiment description + Description *string `json:"description,omitempty"` + // The ID of the member who maintains this experiment + MaintainerId *string `json:"maintainerId,omitempty"` + // The experiment key + Key string `json:"key"` + Iteration IterationInput `json:"iteration"` + // The ID of the holdout + HoldoutId *string `json:"holdoutId,omitempty"` +} + +// NewExperimentPost instantiates a new ExperimentPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExperimentPost(name string, key string, iteration IterationInput) *ExperimentPost { + this := ExperimentPost{} + this.Name = name + this.Key = key + this.Iteration = iteration + return &this +} + +// NewExperimentPostWithDefaults instantiates a new ExperimentPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExperimentPostWithDefaults() *ExperimentPost { + this := ExperimentPost{} + return &this +} + +// GetName returns the Name field value +func (o *ExperimentPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ExperimentPost) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ExperimentPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ExperimentPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ExperimentPost) SetDescription(v string) { + o.Description = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *ExperimentPost) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *ExperimentPost) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *ExperimentPost) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetKey returns the Key field value +func (o *ExperimentPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ExperimentPost) SetKey(v string) { + o.Key = v +} + +// GetIteration returns the Iteration field value +func (o *ExperimentPost) GetIteration() IterationInput { + if o == nil { + var ret IterationInput + return ret + } + + return o.Iteration +} + +// GetIterationOk returns a tuple with the Iteration field value +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetIterationOk() (*IterationInput, bool) { + if o == nil { + return nil, false + } + return &o.Iteration, true +} + +// SetIteration sets field value +func (o *ExperimentPost) SetIteration(v IterationInput) { + o.Iteration = v +} + +// GetHoldoutId returns the HoldoutId field value if set, zero value otherwise. +func (o *ExperimentPost) GetHoldoutId() string { + if o == nil || o.HoldoutId == nil { + var ret string + return ret + } + return *o.HoldoutId +} + +// GetHoldoutIdOk returns a tuple with the HoldoutId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExperimentPost) GetHoldoutIdOk() (*string, bool) { + if o == nil || o.HoldoutId == nil { + return nil, false + } + return o.HoldoutId, true +} + +// HasHoldoutId returns a boolean if a field has been set. +func (o *ExperimentPost) HasHoldoutId() bool { + if o != nil && o.HoldoutId != nil { + return true + } + + return false +} + +// SetHoldoutId gets a reference to the given string and assigns it to the HoldoutId field. +func (o *ExperimentPost) SetHoldoutId(v string) { + o.HoldoutId = &v +} + +func (o ExperimentPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["iteration"] = o.Iteration + } + if o.HoldoutId != nil { + toSerialize["holdoutId"] = o.HoldoutId + } + return json.Marshal(toSerialize) +} + +type NullableExperimentPost struct { + value *ExperimentPost + isSet bool +} + +func (v NullableExperimentPost) Get() *ExperimentPost { + return v.value +} + +func (v *NullableExperimentPost) Set(val *ExperimentPost) { + v.value = val + v.isSet = true +} + +func (v NullableExperimentPost) IsSet() bool { + return v.isSet +} + +func (v *NullableExperimentPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExperimentPost(val *ExperimentPost) *NullableExperimentPost { + return &NullableExperimentPost{value: val, isSet: true} +} + +func (v NullableExperimentPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExperimentPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target.go new file mode 100644 index 00000000..d616ba60 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target.go @@ -0,0 +1,332 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringTarget struct for ExpiringTarget +type ExpiringTarget struct { + // The ID of this expiring target + Id string `json:"_id"` + // The version of this expiring target + Version int32 `json:"_version"` + ExpirationDate int64 `json:"expirationDate"` + // The context kind of the context to be removed + ContextKind string `json:"contextKind"` + // A unique key used to represent the context to be removed + ContextKey string `json:"contextKey"` + // A segment's target type, included or excluded. Included when expiring targets are updated on a segment. + TargetType *string `json:"targetType,omitempty"` + // A unique ID used to represent the flag variation. Included when expiring targets are updated on a feature flag. + VariationId *string `json:"variationId,omitempty"` + ResourceId ResourceId `json:"_resourceId"` +} + +// NewExpiringTarget instantiates a new ExpiringTarget object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringTarget(id string, version int32, expirationDate int64, contextKind string, contextKey string, resourceId ResourceId) *ExpiringTarget { + this := ExpiringTarget{} + this.Id = id + this.Version = version + this.ExpirationDate = expirationDate + this.ContextKind = contextKind + this.ContextKey = contextKey + this.ResourceId = resourceId + return &this +} + +// NewExpiringTargetWithDefaults instantiates a new ExpiringTarget object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringTargetWithDefaults() *ExpiringTarget { + this := ExpiringTarget{} + return &this +} + +// GetId returns the Id field value +func (o *ExpiringTarget) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ExpiringTarget) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *ExpiringTarget) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ExpiringTarget) SetVersion(v int32) { + o.Version = v +} + +// GetExpirationDate returns the ExpirationDate field value +func (o *ExpiringTarget) GetExpirationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.ExpirationDate +} + +// GetExpirationDateOk returns a tuple with the ExpirationDate field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetExpirationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.ExpirationDate, true +} + +// SetExpirationDate sets field value +func (o *ExpiringTarget) SetExpirationDate(v int64) { + o.ExpirationDate = v +} + +// GetContextKind returns the ContextKind field value +func (o *ExpiringTarget) GetContextKind() string { + if o == nil { + var ret string + return ret + } + + return o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetContextKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ContextKind, true +} + +// SetContextKind sets field value +func (o *ExpiringTarget) SetContextKind(v string) { + o.ContextKind = v +} + +// GetContextKey returns the ContextKey field value +func (o *ExpiringTarget) GetContextKey() string { + if o == nil { + var ret string + return ret + } + + return o.ContextKey +} + +// GetContextKeyOk returns a tuple with the ContextKey field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetContextKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ContextKey, true +} + +// SetContextKey sets field value +func (o *ExpiringTarget) SetContextKey(v string) { + o.ContextKey = v +} + +// GetTargetType returns the TargetType field value if set, zero value otherwise. +func (o *ExpiringTarget) GetTargetType() string { + if o == nil || o.TargetType == nil { + var ret string + return ret + } + return *o.TargetType +} + +// GetTargetTypeOk returns a tuple with the TargetType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetTargetTypeOk() (*string, bool) { + if o == nil || o.TargetType == nil { + return nil, false + } + return o.TargetType, true +} + +// HasTargetType returns a boolean if a field has been set. +func (o *ExpiringTarget) HasTargetType() bool { + if o != nil && o.TargetType != nil { + return true + } + + return false +} + +// SetTargetType gets a reference to the given string and assigns it to the TargetType field. +func (o *ExpiringTarget) SetTargetType(v string) { + o.TargetType = &v +} + +// GetVariationId returns the VariationId field value if set, zero value otherwise. +func (o *ExpiringTarget) GetVariationId() string { + if o == nil || o.VariationId == nil { + var ret string + return ret + } + return *o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetVariationIdOk() (*string, bool) { + if o == nil || o.VariationId == nil { + return nil, false + } + return o.VariationId, true +} + +// HasVariationId returns a boolean if a field has been set. +func (o *ExpiringTarget) HasVariationId() bool { + if o != nil && o.VariationId != nil { + return true + } + + return false +} + +// SetVariationId gets a reference to the given string and assigns it to the VariationId field. +func (o *ExpiringTarget) SetVariationId(v string) { + o.VariationId = &v +} + +// GetResourceId returns the ResourceId field value +func (o *ExpiringTarget) GetResourceId() ResourceId { + if o == nil { + var ret ResourceId + return ret + } + + return o.ResourceId +} + +// GetResourceIdOk returns a tuple with the ResourceId field value +// and a boolean to check if the value has been set. +func (o *ExpiringTarget) GetResourceIdOk() (*ResourceId, bool) { + if o == nil { + return nil, false + } + return &o.ResourceId, true +} + +// SetResourceId sets field value +func (o *ExpiringTarget) SetResourceId(v ResourceId) { + o.ResourceId = v +} + +func (o ExpiringTarget) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["expirationDate"] = o.ExpirationDate + } + if true { + toSerialize["contextKind"] = o.ContextKind + } + if true { + toSerialize["contextKey"] = o.ContextKey + } + if o.TargetType != nil { + toSerialize["targetType"] = o.TargetType + } + if o.VariationId != nil { + toSerialize["variationId"] = o.VariationId + } + if true { + toSerialize["_resourceId"] = o.ResourceId + } + return json.Marshal(toSerialize) +} + +type NullableExpiringTarget struct { + value *ExpiringTarget + isSet bool +} + +func (v NullableExpiringTarget) Get() *ExpiringTarget { + return v.value +} + +func (v *NullableExpiringTarget) Set(val *ExpiringTarget) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringTarget) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringTarget) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringTarget(val *ExpiringTarget) *NullableExpiringTarget { + return &NullableExpiringTarget{value: val, isSet: true} +} + +func (v NullableExpiringTarget) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringTarget) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_error.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_error.go new file mode 100644 index 00000000..37c1d949 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_error.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringTargetError struct for ExpiringTargetError +type ExpiringTargetError struct { + // The index of the PATCH instruction where the error occurred + InstructionIndex int32 `json:"instructionIndex"` + // The error message related to a failed PATCH instruction + Message string `json:"message"` +} + +// NewExpiringTargetError instantiates a new ExpiringTargetError object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringTargetError(instructionIndex int32, message string) *ExpiringTargetError { + this := ExpiringTargetError{} + this.InstructionIndex = instructionIndex + this.Message = message + return &this +} + +// NewExpiringTargetErrorWithDefaults instantiates a new ExpiringTargetError object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringTargetErrorWithDefaults() *ExpiringTargetError { + this := ExpiringTargetError{} + return &this +} + +// GetInstructionIndex returns the InstructionIndex field value +func (o *ExpiringTargetError) GetInstructionIndex() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.InstructionIndex +} + +// GetInstructionIndexOk returns a tuple with the InstructionIndex field value +// and a boolean to check if the value has been set. +func (o *ExpiringTargetError) GetInstructionIndexOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.InstructionIndex, true +} + +// SetInstructionIndex sets field value +func (o *ExpiringTargetError) SetInstructionIndex(v int32) { + o.InstructionIndex = v +} + +// GetMessage returns the Message field value +func (o *ExpiringTargetError) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *ExpiringTargetError) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *ExpiringTargetError) SetMessage(v string) { + o.Message = v +} + +func (o ExpiringTargetError) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["instructionIndex"] = o.InstructionIndex + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableExpiringTargetError struct { + value *ExpiringTargetError + isSet bool +} + +func (v NullableExpiringTargetError) Get() *ExpiringTargetError { + return v.value +} + +func (v *NullableExpiringTargetError) Set(val *ExpiringTargetError) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringTargetError) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringTargetError) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringTargetError(val *ExpiringTargetError) *NullableExpiringTargetError { + return &NullableExpiringTargetError{value: val, isSet: true} +} + +func (v NullableExpiringTargetError) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringTargetError) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_get_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_get_response.go new file mode 100644 index 00000000..94b8c460 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_get_response.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringTargetGetResponse struct for ExpiringTargetGetResponse +type ExpiringTargetGetResponse struct { + // A list of expiring targets + Items []ExpiringTarget `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewExpiringTargetGetResponse instantiates a new ExpiringTargetGetResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringTargetGetResponse(items []ExpiringTarget) *ExpiringTargetGetResponse { + this := ExpiringTargetGetResponse{} + this.Items = items + return &this +} + +// NewExpiringTargetGetResponseWithDefaults instantiates a new ExpiringTargetGetResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringTargetGetResponseWithDefaults() *ExpiringTargetGetResponse { + this := ExpiringTargetGetResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *ExpiringTargetGetResponse) GetItems() []ExpiringTarget { + if o == nil { + var ret []ExpiringTarget + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExpiringTargetGetResponse) GetItemsOk() ([]ExpiringTarget, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExpiringTargetGetResponse) SetItems(v []ExpiringTarget) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExpiringTargetGetResponse) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetGetResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExpiringTargetGetResponse) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExpiringTargetGetResponse) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ExpiringTargetGetResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableExpiringTargetGetResponse struct { + value *ExpiringTargetGetResponse + isSet bool +} + +func (v NullableExpiringTargetGetResponse) Get() *ExpiringTargetGetResponse { + return v.value +} + +func (v *NullableExpiringTargetGetResponse) Set(val *ExpiringTargetGetResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringTargetGetResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringTargetGetResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringTargetGetResponse(val *ExpiringTargetGetResponse) *NullableExpiringTargetGetResponse { + return &NullableExpiringTargetGetResponse{value: val, isSet: true} +} + +func (v NullableExpiringTargetGetResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringTargetGetResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_patch_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_patch_response.go new file mode 100644 index 00000000..b90f002c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_target_patch_response.go @@ -0,0 +1,291 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringTargetPatchResponse struct for ExpiringTargetPatchResponse +type ExpiringTargetPatchResponse struct { + // A list of the results from each instruction + Items []ExpiringTarget `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + TotalInstructions *int32 `json:"totalInstructions,omitempty"` + SuccessfulInstructions *int32 `json:"successfulInstructions,omitempty"` + FailedInstructions *int32 `json:"failedInstructions,omitempty"` + Errors []ExpiringTargetError `json:"errors,omitempty"` +} + +// NewExpiringTargetPatchResponse instantiates a new ExpiringTargetPatchResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringTargetPatchResponse(items []ExpiringTarget) *ExpiringTargetPatchResponse { + this := ExpiringTargetPatchResponse{} + this.Items = items + return &this +} + +// NewExpiringTargetPatchResponseWithDefaults instantiates a new ExpiringTargetPatchResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringTargetPatchResponseWithDefaults() *ExpiringTargetPatchResponse { + this := ExpiringTargetPatchResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *ExpiringTargetPatchResponse) GetItems() []ExpiringTarget { + if o == nil { + var ret []ExpiringTarget + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetItemsOk() ([]ExpiringTarget, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExpiringTargetPatchResponse) SetItems(v []ExpiringTarget) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExpiringTargetPatchResponse) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExpiringTargetPatchResponse) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExpiringTargetPatchResponse) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalInstructions returns the TotalInstructions field value if set, zero value otherwise. +func (o *ExpiringTargetPatchResponse) GetTotalInstructions() int32 { + if o == nil || o.TotalInstructions == nil { + var ret int32 + return ret + } + return *o.TotalInstructions +} + +// GetTotalInstructionsOk returns a tuple with the TotalInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetTotalInstructionsOk() (*int32, bool) { + if o == nil || o.TotalInstructions == nil { + return nil, false + } + return o.TotalInstructions, true +} + +// HasTotalInstructions returns a boolean if a field has been set. +func (o *ExpiringTargetPatchResponse) HasTotalInstructions() bool { + if o != nil && o.TotalInstructions != nil { + return true + } + + return false +} + +// SetTotalInstructions gets a reference to the given int32 and assigns it to the TotalInstructions field. +func (o *ExpiringTargetPatchResponse) SetTotalInstructions(v int32) { + o.TotalInstructions = &v +} + +// GetSuccessfulInstructions returns the SuccessfulInstructions field value if set, zero value otherwise. +func (o *ExpiringTargetPatchResponse) GetSuccessfulInstructions() int32 { + if o == nil || o.SuccessfulInstructions == nil { + var ret int32 + return ret + } + return *o.SuccessfulInstructions +} + +// GetSuccessfulInstructionsOk returns a tuple with the SuccessfulInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetSuccessfulInstructionsOk() (*int32, bool) { + if o == nil || o.SuccessfulInstructions == nil { + return nil, false + } + return o.SuccessfulInstructions, true +} + +// HasSuccessfulInstructions returns a boolean if a field has been set. +func (o *ExpiringTargetPatchResponse) HasSuccessfulInstructions() bool { + if o != nil && o.SuccessfulInstructions != nil { + return true + } + + return false +} + +// SetSuccessfulInstructions gets a reference to the given int32 and assigns it to the SuccessfulInstructions field. +func (o *ExpiringTargetPatchResponse) SetSuccessfulInstructions(v int32) { + o.SuccessfulInstructions = &v +} + +// GetFailedInstructions returns the FailedInstructions field value if set, zero value otherwise. +func (o *ExpiringTargetPatchResponse) GetFailedInstructions() int32 { + if o == nil || o.FailedInstructions == nil { + var ret int32 + return ret + } + return *o.FailedInstructions +} + +// GetFailedInstructionsOk returns a tuple with the FailedInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetFailedInstructionsOk() (*int32, bool) { + if o == nil || o.FailedInstructions == nil { + return nil, false + } + return o.FailedInstructions, true +} + +// HasFailedInstructions returns a boolean if a field has been set. +func (o *ExpiringTargetPatchResponse) HasFailedInstructions() bool { + if o != nil && o.FailedInstructions != nil { + return true + } + + return false +} + +// SetFailedInstructions gets a reference to the given int32 and assigns it to the FailedInstructions field. +func (o *ExpiringTargetPatchResponse) SetFailedInstructions(v int32) { + o.FailedInstructions = &v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *ExpiringTargetPatchResponse) GetErrors() []ExpiringTargetError { + if o == nil || o.Errors == nil { + var ret []ExpiringTargetError + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringTargetPatchResponse) GetErrorsOk() ([]ExpiringTargetError, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *ExpiringTargetPatchResponse) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []ExpiringTargetError and assigns it to the Errors field. +func (o *ExpiringTargetPatchResponse) SetErrors(v []ExpiringTargetError) { + o.Errors = v +} + +func (o ExpiringTargetPatchResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalInstructions != nil { + toSerialize["totalInstructions"] = o.TotalInstructions + } + if o.SuccessfulInstructions != nil { + toSerialize["successfulInstructions"] = o.SuccessfulInstructions + } + if o.FailedInstructions != nil { + toSerialize["failedInstructions"] = o.FailedInstructions + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableExpiringTargetPatchResponse struct { + value *ExpiringTargetPatchResponse + isSet bool +} + +func (v NullableExpiringTargetPatchResponse) Get() *ExpiringTargetPatchResponse { + return v.value +} + +func (v *NullableExpiringTargetPatchResponse) Set(val *ExpiringTargetPatchResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringTargetPatchResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringTargetPatchResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringTargetPatchResponse(val *ExpiringTargetPatchResponse) *NullableExpiringTargetPatchResponse { + return &NullableExpiringTargetPatchResponse{value: val, isSet: true} +} + +func (v NullableExpiringTargetPatchResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringTargetPatchResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_get_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_get_response.go new file mode 100644 index 00000000..7af50771 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_get_response.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringUserTargetGetResponse struct for ExpiringUserTargetGetResponse +type ExpiringUserTargetGetResponse struct { + // An array of expiring user targets + Items []ExpiringUserTargetItem `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewExpiringUserTargetGetResponse instantiates a new ExpiringUserTargetGetResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringUserTargetGetResponse(items []ExpiringUserTargetItem) *ExpiringUserTargetGetResponse { + this := ExpiringUserTargetGetResponse{} + this.Items = items + return &this +} + +// NewExpiringUserTargetGetResponseWithDefaults instantiates a new ExpiringUserTargetGetResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringUserTargetGetResponseWithDefaults() *ExpiringUserTargetGetResponse { + this := ExpiringUserTargetGetResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *ExpiringUserTargetGetResponse) GetItems() []ExpiringUserTargetItem { + if o == nil { + var ret []ExpiringUserTargetItem + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetGetResponse) GetItemsOk() ([]ExpiringUserTargetItem, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExpiringUserTargetGetResponse) SetItems(v []ExpiringUserTargetItem) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExpiringUserTargetGetResponse) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetGetResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExpiringUserTargetGetResponse) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExpiringUserTargetGetResponse) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ExpiringUserTargetGetResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableExpiringUserTargetGetResponse struct { + value *ExpiringUserTargetGetResponse + isSet bool +} + +func (v NullableExpiringUserTargetGetResponse) Get() *ExpiringUserTargetGetResponse { + return v.value +} + +func (v *NullableExpiringUserTargetGetResponse) Set(val *ExpiringUserTargetGetResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringUserTargetGetResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringUserTargetGetResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringUserTargetGetResponse(val *ExpiringUserTargetGetResponse) *NullableExpiringUserTargetGetResponse { + return &NullableExpiringUserTargetGetResponse{value: val, isSet: true} +} + +func (v NullableExpiringUserTargetGetResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringUserTargetGetResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_item.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_item.go new file mode 100644 index 00000000..8aecfab6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_item.go @@ -0,0 +1,302 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringUserTargetItem struct for ExpiringUserTargetItem +type ExpiringUserTargetItem struct { + // The ID of this expiring user target + Id string `json:"_id"` + // The version of this expiring user target + Version int32 `json:"_version"` + ExpirationDate int64 `json:"expirationDate"` + // A unique key used to represent the user + UserKey string `json:"userKey"` + // A segment's target type. Included when expiring user targets are updated on a segment. + TargetType *string `json:"targetType,omitempty"` + // A unique key used to represent the flag variation. Included when expiring user targets are updated on a feature flag. + VariationId *string `json:"variationId,omitempty"` + ResourceId ResourceIDResponse `json:"_resourceId"` +} + +// NewExpiringUserTargetItem instantiates a new ExpiringUserTargetItem object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringUserTargetItem(id string, version int32, expirationDate int64, userKey string, resourceId ResourceIDResponse) *ExpiringUserTargetItem { + this := ExpiringUserTargetItem{} + this.Id = id + this.Version = version + this.ExpirationDate = expirationDate + this.UserKey = userKey + this.ResourceId = resourceId + return &this +} + +// NewExpiringUserTargetItemWithDefaults instantiates a new ExpiringUserTargetItem object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringUserTargetItemWithDefaults() *ExpiringUserTargetItem { + this := ExpiringUserTargetItem{} + return &this +} + +// GetId returns the Id field value +func (o *ExpiringUserTargetItem) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ExpiringUserTargetItem) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *ExpiringUserTargetItem) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ExpiringUserTargetItem) SetVersion(v int32) { + o.Version = v +} + +// GetExpirationDate returns the ExpirationDate field value +func (o *ExpiringUserTargetItem) GetExpirationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.ExpirationDate +} + +// GetExpirationDateOk returns a tuple with the ExpirationDate field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetExpirationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.ExpirationDate, true +} + +// SetExpirationDate sets field value +func (o *ExpiringUserTargetItem) SetExpirationDate(v int64) { + o.ExpirationDate = v +} + +// GetUserKey returns the UserKey field value +func (o *ExpiringUserTargetItem) GetUserKey() string { + if o == nil { + var ret string + return ret + } + + return o.UserKey +} + +// GetUserKeyOk returns a tuple with the UserKey field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetUserKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.UserKey, true +} + +// SetUserKey sets field value +func (o *ExpiringUserTargetItem) SetUserKey(v string) { + o.UserKey = v +} + +// GetTargetType returns the TargetType field value if set, zero value otherwise. +func (o *ExpiringUserTargetItem) GetTargetType() string { + if o == nil || o.TargetType == nil { + var ret string + return ret + } + return *o.TargetType +} + +// GetTargetTypeOk returns a tuple with the TargetType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetTargetTypeOk() (*string, bool) { + if o == nil || o.TargetType == nil { + return nil, false + } + return o.TargetType, true +} + +// HasTargetType returns a boolean if a field has been set. +func (o *ExpiringUserTargetItem) HasTargetType() bool { + if o != nil && o.TargetType != nil { + return true + } + + return false +} + +// SetTargetType gets a reference to the given string and assigns it to the TargetType field. +func (o *ExpiringUserTargetItem) SetTargetType(v string) { + o.TargetType = &v +} + +// GetVariationId returns the VariationId field value if set, zero value otherwise. +func (o *ExpiringUserTargetItem) GetVariationId() string { + if o == nil || o.VariationId == nil { + var ret string + return ret + } + return *o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetVariationIdOk() (*string, bool) { + if o == nil || o.VariationId == nil { + return nil, false + } + return o.VariationId, true +} + +// HasVariationId returns a boolean if a field has been set. +func (o *ExpiringUserTargetItem) HasVariationId() bool { + if o != nil && o.VariationId != nil { + return true + } + + return false +} + +// SetVariationId gets a reference to the given string and assigns it to the VariationId field. +func (o *ExpiringUserTargetItem) SetVariationId(v string) { + o.VariationId = &v +} + +// GetResourceId returns the ResourceId field value +func (o *ExpiringUserTargetItem) GetResourceId() ResourceIDResponse { + if o == nil { + var ret ResourceIDResponse + return ret + } + + return o.ResourceId +} + +// GetResourceIdOk returns a tuple with the ResourceId field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetItem) GetResourceIdOk() (*ResourceIDResponse, bool) { + if o == nil { + return nil, false + } + return &o.ResourceId, true +} + +// SetResourceId sets field value +func (o *ExpiringUserTargetItem) SetResourceId(v ResourceIDResponse) { + o.ResourceId = v +} + +func (o ExpiringUserTargetItem) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["expirationDate"] = o.ExpirationDate + } + if true { + toSerialize["userKey"] = o.UserKey + } + if o.TargetType != nil { + toSerialize["targetType"] = o.TargetType + } + if o.VariationId != nil { + toSerialize["variationId"] = o.VariationId + } + if true { + toSerialize["_resourceId"] = o.ResourceId + } + return json.Marshal(toSerialize) +} + +type NullableExpiringUserTargetItem struct { + value *ExpiringUserTargetItem + isSet bool +} + +func (v NullableExpiringUserTargetItem) Get() *ExpiringUserTargetItem { + return v.value +} + +func (v *NullableExpiringUserTargetItem) Set(val *ExpiringUserTargetItem) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringUserTargetItem) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringUserTargetItem) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringUserTargetItem(val *ExpiringUserTargetItem) *NullableExpiringUserTargetItem { + return &NullableExpiringUserTargetItem{value: val, isSet: true} +} + +func (v NullableExpiringUserTargetItem) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringUserTargetItem) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_patch_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_patch_response.go new file mode 100644 index 00000000..0c6e07f7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_expiring_user_target_patch_response.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExpiringUserTargetPatchResponse struct for ExpiringUserTargetPatchResponse +type ExpiringUserTargetPatchResponse struct { + // An array of expiring user targets + Items []ExpiringUserTargetItem `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The total count of instructions sent in the PATCH request + TotalInstructions *int32 `json:"totalInstructions,omitempty"` + // The total count of successful instructions sent in the PATCH request + SuccessfulInstructions *int32 `json:"successfulInstructions,omitempty"` + // The total count of the failed instructions sent in the PATCH request + FailedInstructions *int32 `json:"failedInstructions,omitempty"` + // An array of error messages for the failed instructions + Errors []ExpiringTargetError `json:"errors,omitempty"` +} + +// NewExpiringUserTargetPatchResponse instantiates a new ExpiringUserTargetPatchResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExpiringUserTargetPatchResponse(items []ExpiringUserTargetItem) *ExpiringUserTargetPatchResponse { + this := ExpiringUserTargetPatchResponse{} + this.Items = items + return &this +} + +// NewExpiringUserTargetPatchResponseWithDefaults instantiates a new ExpiringUserTargetPatchResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExpiringUserTargetPatchResponseWithDefaults() *ExpiringUserTargetPatchResponse { + this := ExpiringUserTargetPatchResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *ExpiringUserTargetPatchResponse) GetItems() []ExpiringUserTargetItem { + if o == nil { + var ret []ExpiringUserTargetItem + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetItemsOk() ([]ExpiringUserTargetItem, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ExpiringUserTargetPatchResponse) SetItems(v []ExpiringUserTargetItem) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ExpiringUserTargetPatchResponse) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ExpiringUserTargetPatchResponse) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ExpiringUserTargetPatchResponse) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalInstructions returns the TotalInstructions field value if set, zero value otherwise. +func (o *ExpiringUserTargetPatchResponse) GetTotalInstructions() int32 { + if o == nil || o.TotalInstructions == nil { + var ret int32 + return ret + } + return *o.TotalInstructions +} + +// GetTotalInstructionsOk returns a tuple with the TotalInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetTotalInstructionsOk() (*int32, bool) { + if o == nil || o.TotalInstructions == nil { + return nil, false + } + return o.TotalInstructions, true +} + +// HasTotalInstructions returns a boolean if a field has been set. +func (o *ExpiringUserTargetPatchResponse) HasTotalInstructions() bool { + if o != nil && o.TotalInstructions != nil { + return true + } + + return false +} + +// SetTotalInstructions gets a reference to the given int32 and assigns it to the TotalInstructions field. +func (o *ExpiringUserTargetPatchResponse) SetTotalInstructions(v int32) { + o.TotalInstructions = &v +} + +// GetSuccessfulInstructions returns the SuccessfulInstructions field value if set, zero value otherwise. +func (o *ExpiringUserTargetPatchResponse) GetSuccessfulInstructions() int32 { + if o == nil || o.SuccessfulInstructions == nil { + var ret int32 + return ret + } + return *o.SuccessfulInstructions +} + +// GetSuccessfulInstructionsOk returns a tuple with the SuccessfulInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetSuccessfulInstructionsOk() (*int32, bool) { + if o == nil || o.SuccessfulInstructions == nil { + return nil, false + } + return o.SuccessfulInstructions, true +} + +// HasSuccessfulInstructions returns a boolean if a field has been set. +func (o *ExpiringUserTargetPatchResponse) HasSuccessfulInstructions() bool { + if o != nil && o.SuccessfulInstructions != nil { + return true + } + + return false +} + +// SetSuccessfulInstructions gets a reference to the given int32 and assigns it to the SuccessfulInstructions field. +func (o *ExpiringUserTargetPatchResponse) SetSuccessfulInstructions(v int32) { + o.SuccessfulInstructions = &v +} + +// GetFailedInstructions returns the FailedInstructions field value if set, zero value otherwise. +func (o *ExpiringUserTargetPatchResponse) GetFailedInstructions() int32 { + if o == nil || o.FailedInstructions == nil { + var ret int32 + return ret + } + return *o.FailedInstructions +} + +// GetFailedInstructionsOk returns a tuple with the FailedInstructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetFailedInstructionsOk() (*int32, bool) { + if o == nil || o.FailedInstructions == nil { + return nil, false + } + return o.FailedInstructions, true +} + +// HasFailedInstructions returns a boolean if a field has been set. +func (o *ExpiringUserTargetPatchResponse) HasFailedInstructions() bool { + if o != nil && o.FailedInstructions != nil { + return true + } + + return false +} + +// SetFailedInstructions gets a reference to the given int32 and assigns it to the FailedInstructions field. +func (o *ExpiringUserTargetPatchResponse) SetFailedInstructions(v int32) { + o.FailedInstructions = &v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *ExpiringUserTargetPatchResponse) GetErrors() []ExpiringTargetError { + if o == nil || o.Errors == nil { + var ret []ExpiringTargetError + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ExpiringUserTargetPatchResponse) GetErrorsOk() ([]ExpiringTargetError, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *ExpiringUserTargetPatchResponse) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []ExpiringTargetError and assigns it to the Errors field. +func (o *ExpiringUserTargetPatchResponse) SetErrors(v []ExpiringTargetError) { + o.Errors = v +} + +func (o ExpiringUserTargetPatchResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalInstructions != nil { + toSerialize["totalInstructions"] = o.TotalInstructions + } + if o.SuccessfulInstructions != nil { + toSerialize["successfulInstructions"] = o.SuccessfulInstructions + } + if o.FailedInstructions != nil { + toSerialize["failedInstructions"] = o.FailedInstructions + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableExpiringUserTargetPatchResponse struct { + value *ExpiringUserTargetPatchResponse + isSet bool +} + +func (v NullableExpiringUserTargetPatchResponse) Get() *ExpiringUserTargetPatchResponse { + return v.value +} + +func (v *NullableExpiringUserTargetPatchResponse) Set(val *ExpiringUserTargetPatchResponse) { + v.value = val + v.isSet = true +} + +func (v NullableExpiringUserTargetPatchResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableExpiringUserTargetPatchResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExpiringUserTargetPatchResponse(val *ExpiringUserTargetPatchResponse) *NullableExpiringUserTargetPatchResponse { + return &NullableExpiringUserTargetPatchResponse{value: val, isSet: true} +} + +func (v NullableExpiringUserTargetPatchResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExpiringUserTargetPatchResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_export.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_export.go new file mode 100644 index 00000000..fe43e126 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_export.go @@ -0,0 +1,318 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Export struct for Export +type Export struct { + // The export ID + Id string `json:"id"` + // The segment key + SegmentKey string `json:"segmentKey"` + CreationTime int64 `json:"creationTime"` + // The export status + Status string `json:"status"` + // The export size, in bytes + SizeBytes int64 `json:"sizeBytes"` + // The export size, with units + Size string `json:"size"` + Initiator InitiatorRep `json:"initiator"` + // The location and content type of related resources, including the location of the exported file + Links map[string]Link `json:"_links"` +} + +// NewExport instantiates a new Export object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExport(id string, segmentKey string, creationTime int64, status string, sizeBytes int64, size string, initiator InitiatorRep, links map[string]Link) *Export { + this := Export{} + this.Id = id + this.SegmentKey = segmentKey + this.CreationTime = creationTime + this.Status = status + this.SizeBytes = sizeBytes + this.Size = size + this.Initiator = initiator + this.Links = links + return &this +} + +// NewExportWithDefaults instantiates a new Export object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExportWithDefaults() *Export { + this := Export{} + return &this +} + +// GetId returns the Id field value +func (o *Export) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Export) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Export) SetId(v string) { + o.Id = v +} + +// GetSegmentKey returns the SegmentKey field value +func (o *Export) GetSegmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.SegmentKey +} + +// GetSegmentKeyOk returns a tuple with the SegmentKey field value +// and a boolean to check if the value has been set. +func (o *Export) GetSegmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.SegmentKey, true +} + +// SetSegmentKey sets field value +func (o *Export) SetSegmentKey(v string) { + o.SegmentKey = v +} + +// GetCreationTime returns the CreationTime field value +func (o *Export) GetCreationTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationTime +} + +// GetCreationTimeOk returns a tuple with the CreationTime field value +// and a boolean to check if the value has been set. +func (o *Export) GetCreationTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationTime, true +} + +// SetCreationTime sets field value +func (o *Export) SetCreationTime(v int64) { + o.CreationTime = v +} + +// GetStatus returns the Status field value +func (o *Export) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *Export) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *Export) SetStatus(v string) { + o.Status = v +} + +// GetSizeBytes returns the SizeBytes field value +func (o *Export) GetSizeBytes() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.SizeBytes +} + +// GetSizeBytesOk returns a tuple with the SizeBytes field value +// and a boolean to check if the value has been set. +func (o *Export) GetSizeBytesOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.SizeBytes, true +} + +// SetSizeBytes sets field value +func (o *Export) SetSizeBytes(v int64) { + o.SizeBytes = v +} + +// GetSize returns the Size field value +func (o *Export) GetSize() string { + if o == nil { + var ret string + return ret + } + + return o.Size +} + +// GetSizeOk returns a tuple with the Size field value +// and a boolean to check if the value has been set. +func (o *Export) GetSizeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Size, true +} + +// SetSize sets field value +func (o *Export) SetSize(v string) { + o.Size = v +} + +// GetInitiator returns the Initiator field value +func (o *Export) GetInitiator() InitiatorRep { + if o == nil { + var ret InitiatorRep + return ret + } + + return o.Initiator +} + +// GetInitiatorOk returns a tuple with the Initiator field value +// and a boolean to check if the value has been set. +func (o *Export) GetInitiatorOk() (*InitiatorRep, bool) { + if o == nil { + return nil, false + } + return &o.Initiator, true +} + +// SetInitiator sets field value +func (o *Export) SetInitiator(v InitiatorRep) { + o.Initiator = v +} + +// GetLinks returns the Links field value +func (o *Export) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Export) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Export) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o Export) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["segmentKey"] = o.SegmentKey + } + if true { + toSerialize["creationTime"] = o.CreationTime + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["sizeBytes"] = o.SizeBytes + } + if true { + toSerialize["size"] = o.Size + } + if true { + toSerialize["initiator"] = o.Initiator + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableExport struct { + value *Export + isSet bool +} + +func (v NullableExport) Get() *Export { + return v.value +} + +func (v *NullableExport) Set(val *Export) { + v.value = val + v.isSet = true +} + +func (v NullableExport) IsSet() bool { + return v.isSet +} + +func (v *NullableExport) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExport(val *Export) *NullableExport { + return &NullableExport{value: val, isSet: true} +} + +func (v NullableExport) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExport) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction.go new file mode 100644 index 00000000..75434ba2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction.go @@ -0,0 +1,229 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Extinction struct for Extinction +type Extinction struct { + // The identifier for the revision where flag became extinct. For example, a commit SHA. + Revision string `json:"revision"` + // Description of the extinction. For example, the commit message for the revision. + Message string `json:"message"` + Time int64 `json:"time"` + // The feature flag key + FlagKey string `json:"flagKey"` + // The project key + ProjKey string `json:"projKey"` +} + +// NewExtinction instantiates a new Extinction object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExtinction(revision string, message string, time int64, flagKey string, projKey string) *Extinction { + this := Extinction{} + this.Revision = revision + this.Message = message + this.Time = time + this.FlagKey = flagKey + this.ProjKey = projKey + return &this +} + +// NewExtinctionWithDefaults instantiates a new Extinction object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExtinctionWithDefaults() *Extinction { + this := Extinction{} + return &this +} + +// GetRevision returns the Revision field value +func (o *Extinction) GetRevision() string { + if o == nil { + var ret string + return ret + } + + return o.Revision +} + +// GetRevisionOk returns a tuple with the Revision field value +// and a boolean to check if the value has been set. +func (o *Extinction) GetRevisionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Revision, true +} + +// SetRevision sets field value +func (o *Extinction) SetRevision(v string) { + o.Revision = v +} + +// GetMessage returns the Message field value +func (o *Extinction) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *Extinction) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *Extinction) SetMessage(v string) { + o.Message = v +} + +// GetTime returns the Time field value +func (o *Extinction) GetTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Time +} + +// GetTimeOk returns a tuple with the Time field value +// and a boolean to check if the value has been set. +func (o *Extinction) GetTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Time, true +} + +// SetTime sets field value +func (o *Extinction) SetTime(v int64) { + o.Time = v +} + +// GetFlagKey returns the FlagKey field value +func (o *Extinction) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *Extinction) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *Extinction) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetProjKey returns the ProjKey field value +func (o *Extinction) GetProjKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjKey +} + +// GetProjKeyOk returns a tuple with the ProjKey field value +// and a boolean to check if the value has been set. +func (o *Extinction) GetProjKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjKey, true +} + +// SetProjKey sets field value +func (o *Extinction) SetProjKey(v string) { + o.ProjKey = v +} + +func (o Extinction) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["revision"] = o.Revision + } + if true { + toSerialize["message"] = o.Message + } + if true { + toSerialize["time"] = o.Time + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["projKey"] = o.ProjKey + } + return json.Marshal(toSerialize) +} + +type NullableExtinction struct { + value *Extinction + isSet bool +} + +func (v NullableExtinction) Get() *Extinction { + return v.value +} + +func (v *NullableExtinction) Set(val *Extinction) { + v.value = val + v.isSet = true +} + +func (v NullableExtinction) IsSet() bool { + return v.isSet +} + +func (v *NullableExtinction) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExtinction(val *Extinction) *NullableExtinction { + return &NullableExtinction{value: val, isSet: true} +} + +func (v NullableExtinction) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExtinction) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction_collection_rep.go new file mode 100644 index 00000000..f2f0eae5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_extinction_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ExtinctionCollectionRep struct for ExtinctionCollectionRep +type ExtinctionCollectionRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of extinction events + Items map[string][]Extinction `json:"items"` +} + +// NewExtinctionCollectionRep instantiates a new ExtinctionCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewExtinctionCollectionRep(links map[string]Link, items map[string][]Extinction) *ExtinctionCollectionRep { + this := ExtinctionCollectionRep{} + this.Links = links + this.Items = items + return &this +} + +// NewExtinctionCollectionRepWithDefaults instantiates a new ExtinctionCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewExtinctionCollectionRepWithDefaults() *ExtinctionCollectionRep { + this := ExtinctionCollectionRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *ExtinctionCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ExtinctionCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ExtinctionCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *ExtinctionCollectionRep) GetItems() map[string][]Extinction { + if o == nil { + var ret map[string][]Extinction + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ExtinctionCollectionRep) GetItemsOk() (*map[string][]Extinction, bool) { + if o == nil { + return nil, false + } + return &o.Items, true +} + +// SetItems sets field value +func (o *ExtinctionCollectionRep) SetItems(v map[string][]Extinction) { + o.Items = v +} + +func (o ExtinctionCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableExtinctionCollectionRep struct { + value *ExtinctionCollectionRep + isSet bool +} + +func (v NullableExtinctionCollectionRep) Get() *ExtinctionCollectionRep { + return v.value +} + +func (v *NullableExtinctionCollectionRep) Set(val *ExtinctionCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableExtinctionCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableExtinctionCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableExtinctionCollectionRep(val *ExtinctionCollectionRep) *NullableExtinctionCollectionRep { + return &NullableExtinctionCollectionRep{value: val, isSet: true} +} + +func (v NullableExtinctionCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableExtinctionCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_failure_reason_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_failure_reason_rep.go new file mode 100644 index 00000000..adeaa818 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_failure_reason_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FailureReasonRep struct for FailureReasonRep +type FailureReasonRep struct { + // The attribute that failed validation + Attribute string `json:"attribute"` + // The reason the attribute failed validation + Reason string `json:"reason"` +} + +// NewFailureReasonRep instantiates a new FailureReasonRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFailureReasonRep(attribute string, reason string) *FailureReasonRep { + this := FailureReasonRep{} + this.Attribute = attribute + this.Reason = reason + return &this +} + +// NewFailureReasonRepWithDefaults instantiates a new FailureReasonRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFailureReasonRepWithDefaults() *FailureReasonRep { + this := FailureReasonRep{} + return &this +} + +// GetAttribute returns the Attribute field value +func (o *FailureReasonRep) GetAttribute() string { + if o == nil { + var ret string + return ret + } + + return o.Attribute +} + +// GetAttributeOk returns a tuple with the Attribute field value +// and a boolean to check if the value has been set. +func (o *FailureReasonRep) GetAttributeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Attribute, true +} + +// SetAttribute sets field value +func (o *FailureReasonRep) SetAttribute(v string) { + o.Attribute = v +} + +// GetReason returns the Reason field value +func (o *FailureReasonRep) GetReason() string { + if o == nil { + var ret string + return ret + } + + return o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value +// and a boolean to check if the value has been set. +func (o *FailureReasonRep) GetReasonOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Reason, true +} + +// SetReason sets field value +func (o *FailureReasonRep) SetReason(v string) { + o.Reason = v +} + +func (o FailureReasonRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["attribute"] = o.Attribute + } + if true { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableFailureReasonRep struct { + value *FailureReasonRep + isSet bool +} + +func (v NullableFailureReasonRep) Get() *FailureReasonRep { + return v.value +} + +func (v *NullableFailureReasonRep) Set(val *FailureReasonRep) { + v.value = val + v.isSet = true +} + +func (v NullableFailureReasonRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFailureReasonRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFailureReasonRep(val *FailureReasonRep) *NullableFailureReasonRep { + return &NullableFailureReasonRep{value: val, isSet: true} +} + +func (v NullableFailureReasonRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFailureReasonRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag.go new file mode 100644 index 00000000..ff53a4a6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag.go @@ -0,0 +1,992 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlag struct for FeatureFlag +type FeatureFlag struct { + // A human-friendly name for the feature flag + Name string `json:"name"` + // Kind of feature flag + Kind string `json:"kind"` + // Description of the feature flag + Description *string `json:"description,omitempty"` + // A unique key used to reference the flag in your code + Key string `json:"key"` + // Version of the feature flag + Version int32 `json:"_version"` + CreationDate int64 `json:"creationDate"` + // Deprecated, use clientSideAvailability. Whether this flag should be made available to the client-side JavaScript SDK + // Deprecated + IncludeInSnippet *bool `json:"includeInSnippet,omitempty"` + ClientSideAvailability *ClientSideAvailability `json:"clientSideAvailability,omitempty"` + // An array of possible variations for the flag + Variations []Variation `json:"variations"` + // Whether the flag is a temporary flag + Temporary bool `json:"temporary"` + // Tags for the feature flag + Tags []string `json:"tags"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // Associated maintainerId for the feature flag + MaintainerId *string `json:"maintainerId,omitempty"` + Maintainer *MemberSummary `json:"_maintainer,omitempty"` + // The key of the associated team that maintains this feature flag + MaintainerTeamKey *string `json:"maintainerTeamKey,omitempty"` + MaintainerTeam *MaintainerTeam `json:"_maintainerTeam,omitempty"` + // Deprecated, use experiments instead + // Deprecated + GoalIds []string `json:"goalIds,omitempty"` + Experiments ExperimentInfoRep `json:"experiments"` + CustomProperties map[string]CustomProperty `json:"customProperties"` + // Boolean indicating if the feature flag is archived + Archived bool `json:"archived"` + ArchivedDate *int64 `json:"archivedDate,omitempty"` + // Boolean indicating if the feature flag is deprecated + Deprecated *bool `json:"deprecated,omitempty"` + DeprecatedDate *int64 `json:"deprecatedDate,omitempty"` + Defaults *Defaults `json:"defaults,omitempty"` + Purpose *string `json:"_purpose,omitempty"` + MigrationSettings *FlagMigrationSettingsRep `json:"migrationSettings,omitempty"` + // Details on the environments for this flag. Only returned if the request is filtered by environment, using the filterEnv query parameter. + Environments *map[string]FeatureFlagConfig `json:"environments,omitempty"` +} + +// NewFeatureFlag instantiates a new FeatureFlag object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlag(name string, kind string, key string, version int32, creationDate int64, variations []Variation, temporary bool, tags []string, links map[string]Link, experiments ExperimentInfoRep, customProperties map[string]CustomProperty, archived bool) *FeatureFlag { + this := FeatureFlag{} + this.Name = name + this.Kind = kind + this.Key = key + this.Version = version + this.CreationDate = creationDate + this.Variations = variations + this.Temporary = temporary + this.Tags = tags + this.Links = links + this.Experiments = experiments + this.CustomProperties = customProperties + this.Archived = archived + return &this +} + +// NewFeatureFlagWithDefaults instantiates a new FeatureFlag object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagWithDefaults() *FeatureFlag { + this := FeatureFlag{} + return &this +} + +// GetName returns the Name field value +func (o *FeatureFlag) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FeatureFlag) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *FeatureFlag) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *FeatureFlag) SetKind(v string) { + o.Kind = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FeatureFlag) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FeatureFlag) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FeatureFlag) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *FeatureFlag) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FeatureFlag) SetKey(v string) { + o.Key = v +} + +// GetVersion returns the Version field value +func (o *FeatureFlag) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *FeatureFlag) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *FeatureFlag) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *FeatureFlag) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetIncludeInSnippet returns the IncludeInSnippet field value if set, zero value otherwise. +// Deprecated +func (o *FeatureFlag) GetIncludeInSnippet() bool { + if o == nil || o.IncludeInSnippet == nil { + var ret bool + return ret + } + return *o.IncludeInSnippet +} + +// GetIncludeInSnippetOk returns a tuple with the IncludeInSnippet field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *FeatureFlag) GetIncludeInSnippetOk() (*bool, bool) { + if o == nil || o.IncludeInSnippet == nil { + return nil, false + } + return o.IncludeInSnippet, true +} + +// HasIncludeInSnippet returns a boolean if a field has been set. +func (o *FeatureFlag) HasIncludeInSnippet() bool { + if o != nil && o.IncludeInSnippet != nil { + return true + } + + return false +} + +// SetIncludeInSnippet gets a reference to the given bool and assigns it to the IncludeInSnippet field. +// Deprecated +func (o *FeatureFlag) SetIncludeInSnippet(v bool) { + o.IncludeInSnippet = &v +} + +// GetClientSideAvailability returns the ClientSideAvailability field value if set, zero value otherwise. +func (o *FeatureFlag) GetClientSideAvailability() ClientSideAvailability { + if o == nil || o.ClientSideAvailability == nil { + var ret ClientSideAvailability + return ret + } + return *o.ClientSideAvailability +} + +// GetClientSideAvailabilityOk returns a tuple with the ClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetClientSideAvailabilityOk() (*ClientSideAvailability, bool) { + if o == nil || o.ClientSideAvailability == nil { + return nil, false + } + return o.ClientSideAvailability, true +} + +// HasClientSideAvailability returns a boolean if a field has been set. +func (o *FeatureFlag) HasClientSideAvailability() bool { + if o != nil && o.ClientSideAvailability != nil { + return true + } + + return false +} + +// SetClientSideAvailability gets a reference to the given ClientSideAvailability and assigns it to the ClientSideAvailability field. +func (o *FeatureFlag) SetClientSideAvailability(v ClientSideAvailability) { + o.ClientSideAvailability = &v +} + +// GetVariations returns the Variations field value +func (o *FeatureFlag) GetVariations() []Variation { + if o == nil { + var ret []Variation + return ret + } + + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetVariationsOk() ([]Variation, bool) { + if o == nil { + return nil, false + } + return o.Variations, true +} + +// SetVariations sets field value +func (o *FeatureFlag) SetVariations(v []Variation) { + o.Variations = v +} + +// GetTemporary returns the Temporary field value +func (o *FeatureFlag) GetTemporary() bool { + if o == nil { + var ret bool + return ret + } + + return o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetTemporaryOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Temporary, true +} + +// SetTemporary sets field value +func (o *FeatureFlag) SetTemporary(v bool) { + o.Temporary = v +} + +// GetTags returns the Tags field value +func (o *FeatureFlag) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *FeatureFlag) SetTags(v []string) { + o.Tags = v +} + +// GetLinks returns the Links field value +func (o *FeatureFlag) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FeatureFlag) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *FeatureFlag) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *FeatureFlag) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *FeatureFlag) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *FeatureFlag) GetMaintainer() MemberSummary { + if o == nil || o.Maintainer == nil { + var ret MemberSummary + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetMaintainerOk() (*MemberSummary, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *FeatureFlag) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MemberSummary and assigns it to the Maintainer field. +func (o *FeatureFlag) SetMaintainer(v MemberSummary) { + o.Maintainer = &v +} + +// GetMaintainerTeamKey returns the MaintainerTeamKey field value if set, zero value otherwise. +func (o *FeatureFlag) GetMaintainerTeamKey() string { + if o == nil || o.MaintainerTeamKey == nil { + var ret string + return ret + } + return *o.MaintainerTeamKey +} + +// GetMaintainerTeamKeyOk returns a tuple with the MaintainerTeamKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetMaintainerTeamKeyOk() (*string, bool) { + if o == nil || o.MaintainerTeamKey == nil { + return nil, false + } + return o.MaintainerTeamKey, true +} + +// HasMaintainerTeamKey returns a boolean if a field has been set. +func (o *FeatureFlag) HasMaintainerTeamKey() bool { + if o != nil && o.MaintainerTeamKey != nil { + return true + } + + return false +} + +// SetMaintainerTeamKey gets a reference to the given string and assigns it to the MaintainerTeamKey field. +func (o *FeatureFlag) SetMaintainerTeamKey(v string) { + o.MaintainerTeamKey = &v +} + +// GetMaintainerTeam returns the MaintainerTeam field value if set, zero value otherwise. +func (o *FeatureFlag) GetMaintainerTeam() MaintainerTeam { + if o == nil || o.MaintainerTeam == nil { + var ret MaintainerTeam + return ret + } + return *o.MaintainerTeam +} + +// GetMaintainerTeamOk returns a tuple with the MaintainerTeam field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetMaintainerTeamOk() (*MaintainerTeam, bool) { + if o == nil || o.MaintainerTeam == nil { + return nil, false + } + return o.MaintainerTeam, true +} + +// HasMaintainerTeam returns a boolean if a field has been set. +func (o *FeatureFlag) HasMaintainerTeam() bool { + if o != nil && o.MaintainerTeam != nil { + return true + } + + return false +} + +// SetMaintainerTeam gets a reference to the given MaintainerTeam and assigns it to the MaintainerTeam field. +func (o *FeatureFlag) SetMaintainerTeam(v MaintainerTeam) { + o.MaintainerTeam = &v +} + +// GetGoalIds returns the GoalIds field value if set, zero value otherwise. +// Deprecated +func (o *FeatureFlag) GetGoalIds() []string { + if o == nil || o.GoalIds == nil { + var ret []string + return ret + } + return o.GoalIds +} + +// GetGoalIdsOk returns a tuple with the GoalIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *FeatureFlag) GetGoalIdsOk() ([]string, bool) { + if o == nil || o.GoalIds == nil { + return nil, false + } + return o.GoalIds, true +} + +// HasGoalIds returns a boolean if a field has been set. +func (o *FeatureFlag) HasGoalIds() bool { + if o != nil && o.GoalIds != nil { + return true + } + + return false +} + +// SetGoalIds gets a reference to the given []string and assigns it to the GoalIds field. +// Deprecated +func (o *FeatureFlag) SetGoalIds(v []string) { + o.GoalIds = v +} + +// GetExperiments returns the Experiments field value +func (o *FeatureFlag) GetExperiments() ExperimentInfoRep { + if o == nil { + var ret ExperimentInfoRep + return ret + } + + return o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetExperimentsOk() (*ExperimentInfoRep, bool) { + if o == nil { + return nil, false + } + return &o.Experiments, true +} + +// SetExperiments sets field value +func (o *FeatureFlag) SetExperiments(v ExperimentInfoRep) { + o.Experiments = v +} + +// GetCustomProperties returns the CustomProperties field value +func (o *FeatureFlag) GetCustomProperties() map[string]CustomProperty { + if o == nil { + var ret map[string]CustomProperty + return ret + } + + return o.CustomProperties +} + +// GetCustomPropertiesOk returns a tuple with the CustomProperties field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetCustomPropertiesOk() (*map[string]CustomProperty, bool) { + if o == nil { + return nil, false + } + return &o.CustomProperties, true +} + +// SetCustomProperties sets field value +func (o *FeatureFlag) SetCustomProperties(v map[string]CustomProperty) { + o.CustomProperties = v +} + +// GetArchived returns the Archived field value +func (o *FeatureFlag) GetArchived() bool { + if o == nil { + var ret bool + return ret + } + + return o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetArchivedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Archived, true +} + +// SetArchived sets field value +func (o *FeatureFlag) SetArchived(v bool) { + o.Archived = v +} + +// GetArchivedDate returns the ArchivedDate field value if set, zero value otherwise. +func (o *FeatureFlag) GetArchivedDate() int64 { + if o == nil || o.ArchivedDate == nil { + var ret int64 + return ret + } + return *o.ArchivedDate +} + +// GetArchivedDateOk returns a tuple with the ArchivedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetArchivedDateOk() (*int64, bool) { + if o == nil || o.ArchivedDate == nil { + return nil, false + } + return o.ArchivedDate, true +} + +// HasArchivedDate returns a boolean if a field has been set. +func (o *FeatureFlag) HasArchivedDate() bool { + if o != nil && o.ArchivedDate != nil { + return true + } + + return false +} + +// SetArchivedDate gets a reference to the given int64 and assigns it to the ArchivedDate field. +func (o *FeatureFlag) SetArchivedDate(v int64) { + o.ArchivedDate = &v +} + +// GetDeprecated returns the Deprecated field value if set, zero value otherwise. +func (o *FeatureFlag) GetDeprecated() bool { + if o == nil || o.Deprecated == nil { + var ret bool + return ret + } + return *o.Deprecated +} + +// GetDeprecatedOk returns a tuple with the Deprecated field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetDeprecatedOk() (*bool, bool) { + if o == nil || o.Deprecated == nil { + return nil, false + } + return o.Deprecated, true +} + +// HasDeprecated returns a boolean if a field has been set. +func (o *FeatureFlag) HasDeprecated() bool { + if o != nil && o.Deprecated != nil { + return true + } + + return false +} + +// SetDeprecated gets a reference to the given bool and assigns it to the Deprecated field. +func (o *FeatureFlag) SetDeprecated(v bool) { + o.Deprecated = &v +} + +// GetDeprecatedDate returns the DeprecatedDate field value if set, zero value otherwise. +func (o *FeatureFlag) GetDeprecatedDate() int64 { + if o == nil || o.DeprecatedDate == nil { + var ret int64 + return ret + } + return *o.DeprecatedDate +} + +// GetDeprecatedDateOk returns a tuple with the DeprecatedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetDeprecatedDateOk() (*int64, bool) { + if o == nil || o.DeprecatedDate == nil { + return nil, false + } + return o.DeprecatedDate, true +} + +// HasDeprecatedDate returns a boolean if a field has been set. +func (o *FeatureFlag) HasDeprecatedDate() bool { + if o != nil && o.DeprecatedDate != nil { + return true + } + + return false +} + +// SetDeprecatedDate gets a reference to the given int64 and assigns it to the DeprecatedDate field. +func (o *FeatureFlag) SetDeprecatedDate(v int64) { + o.DeprecatedDate = &v +} + +// GetDefaults returns the Defaults field value if set, zero value otherwise. +func (o *FeatureFlag) GetDefaults() Defaults { + if o == nil || o.Defaults == nil { + var ret Defaults + return ret + } + return *o.Defaults +} + +// GetDefaultsOk returns a tuple with the Defaults field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetDefaultsOk() (*Defaults, bool) { + if o == nil || o.Defaults == nil { + return nil, false + } + return o.Defaults, true +} + +// HasDefaults returns a boolean if a field has been set. +func (o *FeatureFlag) HasDefaults() bool { + if o != nil && o.Defaults != nil { + return true + } + + return false +} + +// SetDefaults gets a reference to the given Defaults and assigns it to the Defaults field. +func (o *FeatureFlag) SetDefaults(v Defaults) { + o.Defaults = &v +} + +// GetPurpose returns the Purpose field value if set, zero value otherwise. +func (o *FeatureFlag) GetPurpose() string { + if o == nil || o.Purpose == nil { + var ret string + return ret + } + return *o.Purpose +} + +// GetPurposeOk returns a tuple with the Purpose field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetPurposeOk() (*string, bool) { + if o == nil || o.Purpose == nil { + return nil, false + } + return o.Purpose, true +} + +// HasPurpose returns a boolean if a field has been set. +func (o *FeatureFlag) HasPurpose() bool { + if o != nil && o.Purpose != nil { + return true + } + + return false +} + +// SetPurpose gets a reference to the given string and assigns it to the Purpose field. +func (o *FeatureFlag) SetPurpose(v string) { + o.Purpose = &v +} + +// GetMigrationSettings returns the MigrationSettings field value if set, zero value otherwise. +func (o *FeatureFlag) GetMigrationSettings() FlagMigrationSettingsRep { + if o == nil || o.MigrationSettings == nil { + var ret FlagMigrationSettingsRep + return ret + } + return *o.MigrationSettings +} + +// GetMigrationSettingsOk returns a tuple with the MigrationSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetMigrationSettingsOk() (*FlagMigrationSettingsRep, bool) { + if o == nil || o.MigrationSettings == nil { + return nil, false + } + return o.MigrationSettings, true +} + +// HasMigrationSettings returns a boolean if a field has been set. +func (o *FeatureFlag) HasMigrationSettings() bool { + if o != nil && o.MigrationSettings != nil { + return true + } + + return false +} + +// SetMigrationSettings gets a reference to the given FlagMigrationSettingsRep and assigns it to the MigrationSettings field. +func (o *FeatureFlag) SetMigrationSettings(v FlagMigrationSettingsRep) { + o.MigrationSettings = &v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *FeatureFlag) GetEnvironments() map[string]FeatureFlagConfig { + if o == nil || o.Environments == nil { + var ret map[string]FeatureFlagConfig + return ret + } + return *o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlag) GetEnvironmentsOk() (*map[string]FeatureFlagConfig, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *FeatureFlag) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given map[string]FeatureFlagConfig and assigns it to the Environments field. +func (o *FeatureFlag) SetEnvironments(v map[string]FeatureFlagConfig) { + o.Environments = &v +} + +func (o FeatureFlag) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if o.IncludeInSnippet != nil { + toSerialize["includeInSnippet"] = o.IncludeInSnippet + } + if o.ClientSideAvailability != nil { + toSerialize["clientSideAvailability"] = o.ClientSideAvailability + } + if true { + toSerialize["variations"] = o.Variations + } + if true { + toSerialize["temporary"] = o.Temporary + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["_links"] = o.Links + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if o.MaintainerTeamKey != nil { + toSerialize["maintainerTeamKey"] = o.MaintainerTeamKey + } + if o.MaintainerTeam != nil { + toSerialize["_maintainerTeam"] = o.MaintainerTeam + } + if o.GoalIds != nil { + toSerialize["goalIds"] = o.GoalIds + } + if true { + toSerialize["experiments"] = o.Experiments + } + if true { + toSerialize["customProperties"] = o.CustomProperties + } + if true { + toSerialize["archived"] = o.Archived + } + if o.ArchivedDate != nil { + toSerialize["archivedDate"] = o.ArchivedDate + } + if o.Deprecated != nil { + toSerialize["deprecated"] = o.Deprecated + } + if o.DeprecatedDate != nil { + toSerialize["deprecatedDate"] = o.DeprecatedDate + } + if o.Defaults != nil { + toSerialize["defaults"] = o.Defaults + } + if o.Purpose != nil { + toSerialize["_purpose"] = o.Purpose + } + if o.MigrationSettings != nil { + toSerialize["migrationSettings"] = o.MigrationSettings + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlag struct { + value *FeatureFlag + isSet bool +} + +func (v NullableFeatureFlag) Get() *FeatureFlag { + return v.value +} + +func (v *NullableFeatureFlag) Set(val *FeatureFlag) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlag) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlag) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlag(val *FeatureFlag) *NullableFeatureFlag { + return &NullableFeatureFlag{value: val, isSet: true} +} + +func (v NullableFeatureFlag) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlag) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_body.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_body.go new file mode 100644 index 00000000..e46f46f7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_body.go @@ -0,0 +1,621 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagBody struct for FeatureFlagBody +type FeatureFlagBody struct { + // A human-friendly name for the feature flag + Name string `json:"name"` + // A unique key used to reference the flag in your code + Key string `json:"key"` + // Description of the feature flag. Defaults to an empty string. + Description *string `json:"description,omitempty"` + // Deprecated, use clientSideAvailability. Whether this flag should be made available to the client-side JavaScript SDK. Defaults to false. + // Deprecated + IncludeInSnippet *bool `json:"includeInSnippet,omitempty"` + ClientSideAvailability *ClientSideAvailabilityPost `json:"clientSideAvailability,omitempty"` + // An array of possible variations for the flag. The variation values must be unique. If omitted, two boolean variations of true and false will be used. + Variations []Variation `json:"variations,omitempty"` + // Whether the flag is a temporary flag. Defaults to true. + Temporary *bool `json:"temporary,omitempty"` + // Tags for the feature flag. Defaults to an empty array. + Tags []string `json:"tags,omitempty"` + CustomProperties *map[string]CustomProperty `json:"customProperties,omitempty"` + Defaults *Defaults `json:"defaults,omitempty"` + // Purpose of the flag + Purpose *string `json:"purpose,omitempty"` + MigrationSettings *MigrationSettingsPost `json:"migrationSettings,omitempty"` + // The ID of the member who maintains this feature flag + MaintainerId *string `json:"maintainerId,omitempty"` + // The key of the team that maintains this feature flag + MaintainerTeamKey *string `json:"maintainerTeamKey,omitempty"` + // Initial set of prerequisite flags for all environments + InitialPrerequisites []FlagPrerequisitePost `json:"initialPrerequisites,omitempty"` +} + +// NewFeatureFlagBody instantiates a new FeatureFlagBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagBody(name string, key string) *FeatureFlagBody { + this := FeatureFlagBody{} + this.Name = name + this.Key = key + return &this +} + +// NewFeatureFlagBodyWithDefaults instantiates a new FeatureFlagBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagBodyWithDefaults() *FeatureFlagBody { + this := FeatureFlagBody{} + return &this +} + +// GetName returns the Name field value +func (o *FeatureFlagBody) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FeatureFlagBody) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *FeatureFlagBody) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FeatureFlagBody) SetKey(v string) { + o.Key = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FeatureFlagBody) SetDescription(v string) { + o.Description = &v +} + +// GetIncludeInSnippet returns the IncludeInSnippet field value if set, zero value otherwise. +// Deprecated +func (o *FeatureFlagBody) GetIncludeInSnippet() bool { + if o == nil || o.IncludeInSnippet == nil { + var ret bool + return ret + } + return *o.IncludeInSnippet +} + +// GetIncludeInSnippetOk returns a tuple with the IncludeInSnippet field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *FeatureFlagBody) GetIncludeInSnippetOk() (*bool, bool) { + if o == nil || o.IncludeInSnippet == nil { + return nil, false + } + return o.IncludeInSnippet, true +} + +// HasIncludeInSnippet returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasIncludeInSnippet() bool { + if o != nil && o.IncludeInSnippet != nil { + return true + } + + return false +} + +// SetIncludeInSnippet gets a reference to the given bool and assigns it to the IncludeInSnippet field. +// Deprecated +func (o *FeatureFlagBody) SetIncludeInSnippet(v bool) { + o.IncludeInSnippet = &v +} + +// GetClientSideAvailability returns the ClientSideAvailability field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetClientSideAvailability() ClientSideAvailabilityPost { + if o == nil || o.ClientSideAvailability == nil { + var ret ClientSideAvailabilityPost + return ret + } + return *o.ClientSideAvailability +} + +// GetClientSideAvailabilityOk returns a tuple with the ClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetClientSideAvailabilityOk() (*ClientSideAvailabilityPost, bool) { + if o == nil || o.ClientSideAvailability == nil { + return nil, false + } + return o.ClientSideAvailability, true +} + +// HasClientSideAvailability returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasClientSideAvailability() bool { + if o != nil && o.ClientSideAvailability != nil { + return true + } + + return false +} + +// SetClientSideAvailability gets a reference to the given ClientSideAvailabilityPost and assigns it to the ClientSideAvailability field. +func (o *FeatureFlagBody) SetClientSideAvailability(v ClientSideAvailabilityPost) { + o.ClientSideAvailability = &v +} + +// GetVariations returns the Variations field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetVariations() []Variation { + if o == nil || o.Variations == nil { + var ret []Variation + return ret + } + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetVariationsOk() ([]Variation, bool) { + if o == nil || o.Variations == nil { + return nil, false + } + return o.Variations, true +} + +// HasVariations returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasVariations() bool { + if o != nil && o.Variations != nil { + return true + } + + return false +} + +// SetVariations gets a reference to the given []Variation and assigns it to the Variations field. +func (o *FeatureFlagBody) SetVariations(v []Variation) { + o.Variations = v +} + +// GetTemporary returns the Temporary field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetTemporary() bool { + if o == nil || o.Temporary == nil { + var ret bool + return ret + } + return *o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetTemporaryOk() (*bool, bool) { + if o == nil || o.Temporary == nil { + return nil, false + } + return o.Temporary, true +} + +// HasTemporary returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasTemporary() bool { + if o != nil && o.Temporary != nil { + return true + } + + return false +} + +// SetTemporary gets a reference to the given bool and assigns it to the Temporary field. +func (o *FeatureFlagBody) SetTemporary(v bool) { + o.Temporary = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *FeatureFlagBody) SetTags(v []string) { + o.Tags = v +} + +// GetCustomProperties returns the CustomProperties field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetCustomProperties() map[string]CustomProperty { + if o == nil || o.CustomProperties == nil { + var ret map[string]CustomProperty + return ret + } + return *o.CustomProperties +} + +// GetCustomPropertiesOk returns a tuple with the CustomProperties field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetCustomPropertiesOk() (*map[string]CustomProperty, bool) { + if o == nil || o.CustomProperties == nil { + return nil, false + } + return o.CustomProperties, true +} + +// HasCustomProperties returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasCustomProperties() bool { + if o != nil && o.CustomProperties != nil { + return true + } + + return false +} + +// SetCustomProperties gets a reference to the given map[string]CustomProperty and assigns it to the CustomProperties field. +func (o *FeatureFlagBody) SetCustomProperties(v map[string]CustomProperty) { + o.CustomProperties = &v +} + +// GetDefaults returns the Defaults field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetDefaults() Defaults { + if o == nil || o.Defaults == nil { + var ret Defaults + return ret + } + return *o.Defaults +} + +// GetDefaultsOk returns a tuple with the Defaults field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetDefaultsOk() (*Defaults, bool) { + if o == nil || o.Defaults == nil { + return nil, false + } + return o.Defaults, true +} + +// HasDefaults returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasDefaults() bool { + if o != nil && o.Defaults != nil { + return true + } + + return false +} + +// SetDefaults gets a reference to the given Defaults and assigns it to the Defaults field. +func (o *FeatureFlagBody) SetDefaults(v Defaults) { + o.Defaults = &v +} + +// GetPurpose returns the Purpose field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetPurpose() string { + if o == nil || o.Purpose == nil { + var ret string + return ret + } + return *o.Purpose +} + +// GetPurposeOk returns a tuple with the Purpose field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetPurposeOk() (*string, bool) { + if o == nil || o.Purpose == nil { + return nil, false + } + return o.Purpose, true +} + +// HasPurpose returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasPurpose() bool { + if o != nil && o.Purpose != nil { + return true + } + + return false +} + +// SetPurpose gets a reference to the given string and assigns it to the Purpose field. +func (o *FeatureFlagBody) SetPurpose(v string) { + o.Purpose = &v +} + +// GetMigrationSettings returns the MigrationSettings field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetMigrationSettings() MigrationSettingsPost { + if o == nil || o.MigrationSettings == nil { + var ret MigrationSettingsPost + return ret + } + return *o.MigrationSettings +} + +// GetMigrationSettingsOk returns a tuple with the MigrationSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetMigrationSettingsOk() (*MigrationSettingsPost, bool) { + if o == nil || o.MigrationSettings == nil { + return nil, false + } + return o.MigrationSettings, true +} + +// HasMigrationSettings returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasMigrationSettings() bool { + if o != nil && o.MigrationSettings != nil { + return true + } + + return false +} + +// SetMigrationSettings gets a reference to the given MigrationSettingsPost and assigns it to the MigrationSettings field. +func (o *FeatureFlagBody) SetMigrationSettings(v MigrationSettingsPost) { + o.MigrationSettings = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *FeatureFlagBody) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainerTeamKey returns the MaintainerTeamKey field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetMaintainerTeamKey() string { + if o == nil || o.MaintainerTeamKey == nil { + var ret string + return ret + } + return *o.MaintainerTeamKey +} + +// GetMaintainerTeamKeyOk returns a tuple with the MaintainerTeamKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetMaintainerTeamKeyOk() (*string, bool) { + if o == nil || o.MaintainerTeamKey == nil { + return nil, false + } + return o.MaintainerTeamKey, true +} + +// HasMaintainerTeamKey returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasMaintainerTeamKey() bool { + if o != nil && o.MaintainerTeamKey != nil { + return true + } + + return false +} + +// SetMaintainerTeamKey gets a reference to the given string and assigns it to the MaintainerTeamKey field. +func (o *FeatureFlagBody) SetMaintainerTeamKey(v string) { + o.MaintainerTeamKey = &v +} + +// GetInitialPrerequisites returns the InitialPrerequisites field value if set, zero value otherwise. +func (o *FeatureFlagBody) GetInitialPrerequisites() []FlagPrerequisitePost { + if o == nil || o.InitialPrerequisites == nil { + var ret []FlagPrerequisitePost + return ret + } + return o.InitialPrerequisites +} + +// GetInitialPrerequisitesOk returns a tuple with the InitialPrerequisites field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagBody) GetInitialPrerequisitesOk() ([]FlagPrerequisitePost, bool) { + if o == nil || o.InitialPrerequisites == nil { + return nil, false + } + return o.InitialPrerequisites, true +} + +// HasInitialPrerequisites returns a boolean if a field has been set. +func (o *FeatureFlagBody) HasInitialPrerequisites() bool { + if o != nil && o.InitialPrerequisites != nil { + return true + } + + return false +} + +// SetInitialPrerequisites gets a reference to the given []FlagPrerequisitePost and assigns it to the InitialPrerequisites field. +func (o *FeatureFlagBody) SetInitialPrerequisites(v []FlagPrerequisitePost) { + o.InitialPrerequisites = v +} + +func (o FeatureFlagBody) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.IncludeInSnippet != nil { + toSerialize["includeInSnippet"] = o.IncludeInSnippet + } + if o.ClientSideAvailability != nil { + toSerialize["clientSideAvailability"] = o.ClientSideAvailability + } + if o.Variations != nil { + toSerialize["variations"] = o.Variations + } + if o.Temporary != nil { + toSerialize["temporary"] = o.Temporary + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.CustomProperties != nil { + toSerialize["customProperties"] = o.CustomProperties + } + if o.Defaults != nil { + toSerialize["defaults"] = o.Defaults + } + if o.Purpose != nil { + toSerialize["purpose"] = o.Purpose + } + if o.MigrationSettings != nil { + toSerialize["migrationSettings"] = o.MigrationSettings + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.MaintainerTeamKey != nil { + toSerialize["maintainerTeamKey"] = o.MaintainerTeamKey + } + if o.InitialPrerequisites != nil { + toSerialize["initialPrerequisites"] = o.InitialPrerequisites + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagBody struct { + value *FeatureFlagBody + isSet bool +} + +func (v NullableFeatureFlagBody) Get() *FeatureFlagBody { + return v.value +} + +func (v *NullableFeatureFlagBody) Set(val *FeatureFlagBody) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagBody) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagBody(val *FeatureFlagBody) *NullableFeatureFlagBody { + return &NullableFeatureFlagBody{value: val, isSet: true} +} + +func (v NullableFeatureFlagBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_config.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_config.go new file mode 100644 index 00000000..45ef0434 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_config.go @@ -0,0 +1,777 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagConfig struct for FeatureFlagConfig +type FeatureFlagConfig struct { + // Whether the flag is on + On bool `json:"on"` + // Boolean indicating if the feature flag is archived + Archived bool `json:"archived"` + Salt string `json:"salt"` + Sel string `json:"sel"` + LastModified int64 `json:"lastModified"` + // Version of the feature flag + Version int32 `json:"version"` + // An array of the individual targets that will receive a specific variation based on their key. Individual targets with a context kind of 'user' are included here. + Targets []Target `json:"targets,omitempty"` + // An array of the individual targets that will receive a specific variation based on their key. Individual targets with context kinds other than 'user' are included here. + ContextTargets []Target `json:"contextTargets,omitempty"` + // An array of the rules for how to serve a variation to specific targets based on their attributes + Rules []Rule `json:"rules,omitempty"` + Fallthrough *VariationOrRolloutRep `json:"fallthrough,omitempty"` + // The ID of the variation to serve when the flag is off + OffVariation *int32 `json:"offVariation,omitempty"` + // An array of the prerequisite flags and their variations that are required before this flag takes effect + Prerequisites []Prerequisite `json:"prerequisites,omitempty"` + Site Link `json:"_site"` + Access *Access `json:"_access,omitempty"` + // The environment name + EnvironmentName string `json:"_environmentName"` + // Whether LaunchDarkly tracks events for the feature flag, for all rules + TrackEvents bool `json:"trackEvents"` + // Whether LaunchDarkly tracks events for the feature flag, for the default rule + TrackEventsFallthrough bool `json:"trackEventsFallthrough"` + DebugEventsUntilDate *int64 `json:"_debugEventsUntilDate,omitempty"` + Summary *FlagSummary `json:"_summary,omitempty"` + Evaluation *FlagConfigEvaluation `json:"evaluation,omitempty"` + MigrationSettings *FlagConfigMigrationSettingsRep `json:"migrationSettings,omitempty"` +} + +// NewFeatureFlagConfig instantiates a new FeatureFlagConfig object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagConfig(on bool, archived bool, salt string, sel string, lastModified int64, version int32, site Link, environmentName string, trackEvents bool, trackEventsFallthrough bool) *FeatureFlagConfig { + this := FeatureFlagConfig{} + this.On = on + this.Archived = archived + this.Salt = salt + this.Sel = sel + this.LastModified = lastModified + this.Version = version + this.Site = site + this.EnvironmentName = environmentName + this.TrackEvents = trackEvents + this.TrackEventsFallthrough = trackEventsFallthrough + return &this +} + +// NewFeatureFlagConfigWithDefaults instantiates a new FeatureFlagConfig object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagConfigWithDefaults() *FeatureFlagConfig { + this := FeatureFlagConfig{} + return &this +} + +// GetOn returns the On field value +func (o *FeatureFlagConfig) GetOn() bool { + if o == nil { + var ret bool + return ret + } + + return o.On +} + +// GetOnOk returns a tuple with the On field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetOnOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.On, true +} + +// SetOn sets field value +func (o *FeatureFlagConfig) SetOn(v bool) { + o.On = v +} + +// GetArchived returns the Archived field value +func (o *FeatureFlagConfig) GetArchived() bool { + if o == nil { + var ret bool + return ret + } + + return o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetArchivedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Archived, true +} + +// SetArchived sets field value +func (o *FeatureFlagConfig) SetArchived(v bool) { + o.Archived = v +} + +// GetSalt returns the Salt field value +func (o *FeatureFlagConfig) GetSalt() string { + if o == nil { + var ret string + return ret + } + + return o.Salt +} + +// GetSaltOk returns a tuple with the Salt field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetSaltOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Salt, true +} + +// SetSalt sets field value +func (o *FeatureFlagConfig) SetSalt(v string) { + o.Salt = v +} + +// GetSel returns the Sel field value +func (o *FeatureFlagConfig) GetSel() string { + if o == nil { + var ret string + return ret + } + + return o.Sel +} + +// GetSelOk returns a tuple with the Sel field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetSelOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Sel, true +} + +// SetSel sets field value +func (o *FeatureFlagConfig) SetSel(v string) { + o.Sel = v +} + +// GetLastModified returns the LastModified field value +func (o *FeatureFlagConfig) GetLastModified() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetLastModifiedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModified, true +} + +// SetLastModified sets field value +func (o *FeatureFlagConfig) SetLastModified(v int64) { + o.LastModified = v +} + +// GetVersion returns the Version field value +func (o *FeatureFlagConfig) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *FeatureFlagConfig) SetVersion(v int32) { + o.Version = v +} + +// GetTargets returns the Targets field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetTargets() []Target { + if o == nil || o.Targets == nil { + var ret []Target + return ret + } + return o.Targets +} + +// GetTargetsOk returns a tuple with the Targets field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetTargetsOk() ([]Target, bool) { + if o == nil || o.Targets == nil { + return nil, false + } + return o.Targets, true +} + +// HasTargets returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasTargets() bool { + if o != nil && o.Targets != nil { + return true + } + + return false +} + +// SetTargets gets a reference to the given []Target and assigns it to the Targets field. +func (o *FeatureFlagConfig) SetTargets(v []Target) { + o.Targets = v +} + +// GetContextTargets returns the ContextTargets field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetContextTargets() []Target { + if o == nil || o.ContextTargets == nil { + var ret []Target + return ret + } + return o.ContextTargets +} + +// GetContextTargetsOk returns a tuple with the ContextTargets field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetContextTargetsOk() ([]Target, bool) { + if o == nil || o.ContextTargets == nil { + return nil, false + } + return o.ContextTargets, true +} + +// HasContextTargets returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasContextTargets() bool { + if o != nil && o.ContextTargets != nil { + return true + } + + return false +} + +// SetContextTargets gets a reference to the given []Target and assigns it to the ContextTargets field. +func (o *FeatureFlagConfig) SetContextTargets(v []Target) { + o.ContextTargets = v +} + +// GetRules returns the Rules field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetRules() []Rule { + if o == nil || o.Rules == nil { + var ret []Rule + return ret + } + return o.Rules +} + +// GetRulesOk returns a tuple with the Rules field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetRulesOk() ([]Rule, bool) { + if o == nil || o.Rules == nil { + return nil, false + } + return o.Rules, true +} + +// HasRules returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasRules() bool { + if o != nil && o.Rules != nil { + return true + } + + return false +} + +// SetRules gets a reference to the given []Rule and assigns it to the Rules field. +func (o *FeatureFlagConfig) SetRules(v []Rule) { + o.Rules = v +} + +// GetFallthrough returns the Fallthrough field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetFallthrough() VariationOrRolloutRep { + if o == nil || o.Fallthrough == nil { + var ret VariationOrRolloutRep + return ret + } + return *o.Fallthrough +} + +// GetFallthroughOk returns a tuple with the Fallthrough field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetFallthroughOk() (*VariationOrRolloutRep, bool) { + if o == nil || o.Fallthrough == nil { + return nil, false + } + return o.Fallthrough, true +} + +// HasFallthrough returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasFallthrough() bool { + if o != nil && o.Fallthrough != nil { + return true + } + + return false +} + +// SetFallthrough gets a reference to the given VariationOrRolloutRep and assigns it to the Fallthrough field. +func (o *FeatureFlagConfig) SetFallthrough(v VariationOrRolloutRep) { + o.Fallthrough = &v +} + +// GetOffVariation returns the OffVariation field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetOffVariation() int32 { + if o == nil || o.OffVariation == nil { + var ret int32 + return ret + } + return *o.OffVariation +} + +// GetOffVariationOk returns a tuple with the OffVariation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetOffVariationOk() (*int32, bool) { + if o == nil || o.OffVariation == nil { + return nil, false + } + return o.OffVariation, true +} + +// HasOffVariation returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasOffVariation() bool { + if o != nil && o.OffVariation != nil { + return true + } + + return false +} + +// SetOffVariation gets a reference to the given int32 and assigns it to the OffVariation field. +func (o *FeatureFlagConfig) SetOffVariation(v int32) { + o.OffVariation = &v +} + +// GetPrerequisites returns the Prerequisites field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetPrerequisites() []Prerequisite { + if o == nil || o.Prerequisites == nil { + var ret []Prerequisite + return ret + } + return o.Prerequisites +} + +// GetPrerequisitesOk returns a tuple with the Prerequisites field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetPrerequisitesOk() ([]Prerequisite, bool) { + if o == nil || o.Prerequisites == nil { + return nil, false + } + return o.Prerequisites, true +} + +// HasPrerequisites returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasPrerequisites() bool { + if o != nil && o.Prerequisites != nil { + return true + } + + return false +} + +// SetPrerequisites gets a reference to the given []Prerequisite and assigns it to the Prerequisites field. +func (o *FeatureFlagConfig) SetPrerequisites(v []Prerequisite) { + o.Prerequisites = v +} + +// GetSite returns the Site field value +func (o *FeatureFlagConfig) GetSite() Link { + if o == nil { + var ret Link + return ret + } + + return o.Site +} + +// GetSiteOk returns a tuple with the Site field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetSiteOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Site, true +} + +// SetSite sets field value +func (o *FeatureFlagConfig) SetSite(v Link) { + o.Site = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *FeatureFlagConfig) SetAccess(v Access) { + o.Access = &v +} + +// GetEnvironmentName returns the EnvironmentName field value +func (o *FeatureFlagConfig) GetEnvironmentName() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentName +} + +// GetEnvironmentNameOk returns a tuple with the EnvironmentName field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetEnvironmentNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentName, true +} + +// SetEnvironmentName sets field value +func (o *FeatureFlagConfig) SetEnvironmentName(v string) { + o.EnvironmentName = v +} + +// GetTrackEvents returns the TrackEvents field value +func (o *FeatureFlagConfig) GetTrackEvents() bool { + if o == nil { + var ret bool + return ret + } + + return o.TrackEvents +} + +// GetTrackEventsOk returns a tuple with the TrackEvents field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetTrackEventsOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.TrackEvents, true +} + +// SetTrackEvents sets field value +func (o *FeatureFlagConfig) SetTrackEvents(v bool) { + o.TrackEvents = v +} + +// GetTrackEventsFallthrough returns the TrackEventsFallthrough field value +func (o *FeatureFlagConfig) GetTrackEventsFallthrough() bool { + if o == nil { + var ret bool + return ret + } + + return o.TrackEventsFallthrough +} + +// GetTrackEventsFallthroughOk returns a tuple with the TrackEventsFallthrough field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetTrackEventsFallthroughOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.TrackEventsFallthrough, true +} + +// SetTrackEventsFallthrough sets field value +func (o *FeatureFlagConfig) SetTrackEventsFallthrough(v bool) { + o.TrackEventsFallthrough = v +} + +// GetDebugEventsUntilDate returns the DebugEventsUntilDate field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetDebugEventsUntilDate() int64 { + if o == nil || o.DebugEventsUntilDate == nil { + var ret int64 + return ret + } + return *o.DebugEventsUntilDate +} + +// GetDebugEventsUntilDateOk returns a tuple with the DebugEventsUntilDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetDebugEventsUntilDateOk() (*int64, bool) { + if o == nil || o.DebugEventsUntilDate == nil { + return nil, false + } + return o.DebugEventsUntilDate, true +} + +// HasDebugEventsUntilDate returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasDebugEventsUntilDate() bool { + if o != nil && o.DebugEventsUntilDate != nil { + return true + } + + return false +} + +// SetDebugEventsUntilDate gets a reference to the given int64 and assigns it to the DebugEventsUntilDate field. +func (o *FeatureFlagConfig) SetDebugEventsUntilDate(v int64) { + o.DebugEventsUntilDate = &v +} + +// GetSummary returns the Summary field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetSummary() FlagSummary { + if o == nil || o.Summary == nil { + var ret FlagSummary + return ret + } + return *o.Summary +} + +// GetSummaryOk returns a tuple with the Summary field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetSummaryOk() (*FlagSummary, bool) { + if o == nil || o.Summary == nil { + return nil, false + } + return o.Summary, true +} + +// HasSummary returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasSummary() bool { + if o != nil && o.Summary != nil { + return true + } + + return false +} + +// SetSummary gets a reference to the given FlagSummary and assigns it to the Summary field. +func (o *FeatureFlagConfig) SetSummary(v FlagSummary) { + o.Summary = &v +} + +// GetEvaluation returns the Evaluation field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetEvaluation() FlagConfigEvaluation { + if o == nil || o.Evaluation == nil { + var ret FlagConfigEvaluation + return ret + } + return *o.Evaluation +} + +// GetEvaluationOk returns a tuple with the Evaluation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetEvaluationOk() (*FlagConfigEvaluation, bool) { + if o == nil || o.Evaluation == nil { + return nil, false + } + return o.Evaluation, true +} + +// HasEvaluation returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasEvaluation() bool { + if o != nil && o.Evaluation != nil { + return true + } + + return false +} + +// SetEvaluation gets a reference to the given FlagConfigEvaluation and assigns it to the Evaluation field. +func (o *FeatureFlagConfig) SetEvaluation(v FlagConfigEvaluation) { + o.Evaluation = &v +} + +// GetMigrationSettings returns the MigrationSettings field value if set, zero value otherwise. +func (o *FeatureFlagConfig) GetMigrationSettings() FlagConfigMigrationSettingsRep { + if o == nil || o.MigrationSettings == nil { + var ret FlagConfigMigrationSettingsRep + return ret + } + return *o.MigrationSettings +} + +// GetMigrationSettingsOk returns a tuple with the MigrationSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagConfig) GetMigrationSettingsOk() (*FlagConfigMigrationSettingsRep, bool) { + if o == nil || o.MigrationSettings == nil { + return nil, false + } + return o.MigrationSettings, true +} + +// HasMigrationSettings returns a boolean if a field has been set. +func (o *FeatureFlagConfig) HasMigrationSettings() bool { + if o != nil && o.MigrationSettings != nil { + return true + } + + return false +} + +// SetMigrationSettings gets a reference to the given FlagConfigMigrationSettingsRep and assigns it to the MigrationSettings field. +func (o *FeatureFlagConfig) SetMigrationSettings(v FlagConfigMigrationSettingsRep) { + o.MigrationSettings = &v +} + +func (o FeatureFlagConfig) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["on"] = o.On + } + if true { + toSerialize["archived"] = o.Archived + } + if true { + toSerialize["salt"] = o.Salt + } + if true { + toSerialize["sel"] = o.Sel + } + if true { + toSerialize["lastModified"] = o.LastModified + } + if true { + toSerialize["version"] = o.Version + } + if o.Targets != nil { + toSerialize["targets"] = o.Targets + } + if o.ContextTargets != nil { + toSerialize["contextTargets"] = o.ContextTargets + } + if o.Rules != nil { + toSerialize["rules"] = o.Rules + } + if o.Fallthrough != nil { + toSerialize["fallthrough"] = o.Fallthrough + } + if o.OffVariation != nil { + toSerialize["offVariation"] = o.OffVariation + } + if o.Prerequisites != nil { + toSerialize["prerequisites"] = o.Prerequisites + } + if true { + toSerialize["_site"] = o.Site + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["_environmentName"] = o.EnvironmentName + } + if true { + toSerialize["trackEvents"] = o.TrackEvents + } + if true { + toSerialize["trackEventsFallthrough"] = o.TrackEventsFallthrough + } + if o.DebugEventsUntilDate != nil { + toSerialize["_debugEventsUntilDate"] = o.DebugEventsUntilDate + } + if o.Summary != nil { + toSerialize["_summary"] = o.Summary + } + if o.Evaluation != nil { + toSerialize["evaluation"] = o.Evaluation + } + if o.MigrationSettings != nil { + toSerialize["migrationSettings"] = o.MigrationSettings + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagConfig struct { + value *FeatureFlagConfig + isSet bool +} + +func (v NullableFeatureFlagConfig) Get() *FeatureFlagConfig { + return v.value +} + +func (v *NullableFeatureFlagConfig) Set(val *FeatureFlagConfig) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagConfig) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagConfig) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagConfig(val *FeatureFlagConfig) *NullableFeatureFlagConfig { + return &NullableFeatureFlagConfig{value: val, isSet: true} +} + +func (v NullableFeatureFlagConfig) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagConfig) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_change.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_change.go new file mode 100644 index 00000000..b34d9166 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_change.go @@ -0,0 +1,331 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagScheduledChange struct for FeatureFlagScheduledChange +type FeatureFlagScheduledChange struct { + Id string `json:"_id"` + CreationDate int64 `json:"_creationDate"` + // The ID of the scheduled change maintainer + MaintainerId string `json:"_maintainerId"` + // Version of the scheduled change + Version int32 `json:"_version"` + ExecutionDate int64 `json:"executionDate"` + Instructions []map[string]interface{} `json:"instructions"` + // Details on any conflicting scheduled changes + Conflicts interface{} `json:"conflicts,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewFeatureFlagScheduledChange instantiates a new FeatureFlagScheduledChange object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagScheduledChange(id string, creationDate int64, maintainerId string, version int32, executionDate int64, instructions []map[string]interface{}) *FeatureFlagScheduledChange { + this := FeatureFlagScheduledChange{} + this.Id = id + this.CreationDate = creationDate + this.MaintainerId = maintainerId + this.Version = version + this.ExecutionDate = executionDate + this.Instructions = instructions + return &this +} + +// NewFeatureFlagScheduledChangeWithDefaults instantiates a new FeatureFlagScheduledChange object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagScheduledChangeWithDefaults() *FeatureFlagScheduledChange { + this := FeatureFlagScheduledChange{} + return &this +} + +// GetId returns the Id field value +func (o *FeatureFlagScheduledChange) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FeatureFlagScheduledChange) SetId(v string) { + o.Id = v +} + +// GetCreationDate returns the CreationDate field value +func (o *FeatureFlagScheduledChange) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *FeatureFlagScheduledChange) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetMaintainerId returns the MaintainerId field value +func (o *FeatureFlagScheduledChange) GetMaintainerId() string { + if o == nil { + var ret string + return ret + } + + return o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetMaintainerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MaintainerId, true +} + +// SetMaintainerId sets field value +func (o *FeatureFlagScheduledChange) SetMaintainerId(v string) { + o.MaintainerId = v +} + +// GetVersion returns the Version field value +func (o *FeatureFlagScheduledChange) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *FeatureFlagScheduledChange) SetVersion(v int32) { + o.Version = v +} + +// GetExecutionDate returns the ExecutionDate field value +func (o *FeatureFlagScheduledChange) GetExecutionDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetExecutionDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.ExecutionDate, true +} + +// SetExecutionDate sets field value +func (o *FeatureFlagScheduledChange) SetExecutionDate(v int64) { + o.ExecutionDate = v +} + +// GetInstructions returns the Instructions field value +func (o *FeatureFlagScheduledChange) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *FeatureFlagScheduledChange) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetConflicts returns the Conflicts field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *FeatureFlagScheduledChange) GetConflicts() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Conflicts +} + +// GetConflictsOk returns a tuple with the Conflicts field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *FeatureFlagScheduledChange) GetConflictsOk() (*interface{}, bool) { + if o == nil || o.Conflicts == nil { + return nil, false + } + return &o.Conflicts, true +} + +// HasConflicts returns a boolean if a field has been set. +func (o *FeatureFlagScheduledChange) HasConflicts() bool { + if o != nil && o.Conflicts != nil { + return true + } + + return false +} + +// SetConflicts gets a reference to the given interface{} and assigns it to the Conflicts field. +func (o *FeatureFlagScheduledChange) SetConflicts(v interface{}) { + o.Conflicts = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FeatureFlagScheduledChange) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChange) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FeatureFlagScheduledChange) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FeatureFlagScheduledChange) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o FeatureFlagScheduledChange) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if true { + toSerialize["_maintainerId"] = o.MaintainerId + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["executionDate"] = o.ExecutionDate + } + if true { + toSerialize["instructions"] = o.Instructions + } + if o.Conflicts != nil { + toSerialize["conflicts"] = o.Conflicts + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagScheduledChange struct { + value *FeatureFlagScheduledChange + isSet bool +} + +func (v NullableFeatureFlagScheduledChange) Get() *FeatureFlagScheduledChange { + return v.value +} + +func (v *NullableFeatureFlagScheduledChange) Set(val *FeatureFlagScheduledChange) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagScheduledChange) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagScheduledChange) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagScheduledChange(val *FeatureFlagScheduledChange) *NullableFeatureFlagScheduledChange { + return &NullableFeatureFlagScheduledChange{value: val, isSet: true} +} + +func (v NullableFeatureFlagScheduledChange) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagScheduledChange) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_changes.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_changes.go new file mode 100644 index 00000000..d00e3c53 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_scheduled_changes.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagScheduledChanges struct for FeatureFlagScheduledChanges +type FeatureFlagScheduledChanges struct { + // Array of scheduled changes + Items []FeatureFlagScheduledChange `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewFeatureFlagScheduledChanges instantiates a new FeatureFlagScheduledChanges object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagScheduledChanges(items []FeatureFlagScheduledChange) *FeatureFlagScheduledChanges { + this := FeatureFlagScheduledChanges{} + this.Items = items + return &this +} + +// NewFeatureFlagScheduledChangesWithDefaults instantiates a new FeatureFlagScheduledChanges object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagScheduledChangesWithDefaults() *FeatureFlagScheduledChanges { + this := FeatureFlagScheduledChanges{} + return &this +} + +// GetItems returns the Items field value +func (o *FeatureFlagScheduledChanges) GetItems() []FeatureFlagScheduledChange { + if o == nil { + var ret []FeatureFlagScheduledChange + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChanges) GetItemsOk() ([]FeatureFlagScheduledChange, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FeatureFlagScheduledChanges) SetItems(v []FeatureFlagScheduledChange) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FeatureFlagScheduledChanges) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagScheduledChanges) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FeatureFlagScheduledChanges) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FeatureFlagScheduledChanges) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o FeatureFlagScheduledChanges) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagScheduledChanges struct { + value *FeatureFlagScheduledChanges + isSet bool +} + +func (v NullableFeatureFlagScheduledChanges) Get() *FeatureFlagScheduledChanges { + return v.value +} + +func (v *NullableFeatureFlagScheduledChanges) Set(val *FeatureFlagScheduledChanges) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagScheduledChanges) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagScheduledChanges) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagScheduledChanges(val *FeatureFlagScheduledChanges) *NullableFeatureFlagScheduledChanges { + return &NullableFeatureFlagScheduledChanges{value: val, isSet: true} +} + +func (v NullableFeatureFlagScheduledChanges) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagScheduledChanges) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status.go new file mode 100644 index 00000000..ea9a5ff6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status.go @@ -0,0 +1,186 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// FeatureFlagStatus struct for FeatureFlagStatus +type FeatureFlagStatus struct { + // Status of the flag + Name string `json:"name"` + // Timestamp of last time flag was requested + LastRequested *time.Time `json:"lastRequested,omitempty"` + // Default value seen from code + Default interface{} `json:"default,omitempty"` +} + +// NewFeatureFlagStatus instantiates a new FeatureFlagStatus object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagStatus(name string) *FeatureFlagStatus { + this := FeatureFlagStatus{} + this.Name = name + return &this +} + +// NewFeatureFlagStatusWithDefaults instantiates a new FeatureFlagStatus object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagStatusWithDefaults() *FeatureFlagStatus { + this := FeatureFlagStatus{} + return &this +} + +// GetName returns the Name field value +func (o *FeatureFlagStatus) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatus) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FeatureFlagStatus) SetName(v string) { + o.Name = v +} + +// GetLastRequested returns the LastRequested field value if set, zero value otherwise. +func (o *FeatureFlagStatus) GetLastRequested() time.Time { + if o == nil || o.LastRequested == nil { + var ret time.Time + return ret + } + return *o.LastRequested +} + +// GetLastRequestedOk returns a tuple with the LastRequested field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatus) GetLastRequestedOk() (*time.Time, bool) { + if o == nil || o.LastRequested == nil { + return nil, false + } + return o.LastRequested, true +} + +// HasLastRequested returns a boolean if a field has been set. +func (o *FeatureFlagStatus) HasLastRequested() bool { + if o != nil && o.LastRequested != nil { + return true + } + + return false +} + +// SetLastRequested gets a reference to the given time.Time and assigns it to the LastRequested field. +func (o *FeatureFlagStatus) SetLastRequested(v time.Time) { + o.LastRequested = &v +} + +// GetDefault returns the Default field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *FeatureFlagStatus) GetDefault() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Default +} + +// GetDefaultOk returns a tuple with the Default field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *FeatureFlagStatus) GetDefaultOk() (*interface{}, bool) { + if o == nil || o.Default == nil { + return nil, false + } + return &o.Default, true +} + +// HasDefault returns a boolean if a field has been set. +func (o *FeatureFlagStatus) HasDefault() bool { + if o != nil && o.Default != nil { + return true + } + + return false +} + +// SetDefault gets a reference to the given interface{} and assigns it to the Default field. +func (o *FeatureFlagStatus) SetDefault(v interface{}) { + o.Default = v +} + +func (o FeatureFlagStatus) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.LastRequested != nil { + toSerialize["lastRequested"] = o.LastRequested + } + if o.Default != nil { + toSerialize["default"] = o.Default + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagStatus struct { + value *FeatureFlagStatus + isSet bool +} + +func (v NullableFeatureFlagStatus) Get() *FeatureFlagStatus { + return v.value +} + +func (v *NullableFeatureFlagStatus) Set(val *FeatureFlagStatus) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagStatus) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagStatus) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagStatus(val *FeatureFlagStatus) *NullableFeatureFlagStatus { + return &NullableFeatureFlagStatus{value: val, isSet: true} +} + +func (v NullableFeatureFlagStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagStatus) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status_across_environments.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status_across_environments.go new file mode 100644 index 00000000..33e7a3eb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_status_across_environments.go @@ -0,0 +1,169 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagStatusAcrossEnvironments struct for FeatureFlagStatusAcrossEnvironments +type FeatureFlagStatusAcrossEnvironments struct { + // Flag status for environment. + Environments map[string]FeatureFlagStatus `json:"environments"` + // feature flag key + Key string `json:"key"` + Links map[string]Link `json:"_links"` +} + +// NewFeatureFlagStatusAcrossEnvironments instantiates a new FeatureFlagStatusAcrossEnvironments object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagStatusAcrossEnvironments(environments map[string]FeatureFlagStatus, key string, links map[string]Link) *FeatureFlagStatusAcrossEnvironments { + this := FeatureFlagStatusAcrossEnvironments{} + this.Environments = environments + this.Key = key + this.Links = links + return &this +} + +// NewFeatureFlagStatusAcrossEnvironmentsWithDefaults instantiates a new FeatureFlagStatusAcrossEnvironments object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagStatusAcrossEnvironmentsWithDefaults() *FeatureFlagStatusAcrossEnvironments { + this := FeatureFlagStatusAcrossEnvironments{} + return &this +} + +// GetEnvironments returns the Environments field value +func (o *FeatureFlagStatusAcrossEnvironments) GetEnvironments() map[string]FeatureFlagStatus { + if o == nil { + var ret map[string]FeatureFlagStatus + return ret + } + + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatusAcrossEnvironments) GetEnvironmentsOk() (*map[string]FeatureFlagStatus, bool) { + if o == nil { + return nil, false + } + return &o.Environments, true +} + +// SetEnvironments sets field value +func (o *FeatureFlagStatusAcrossEnvironments) SetEnvironments(v map[string]FeatureFlagStatus) { + o.Environments = v +} + +// GetKey returns the Key field value +func (o *FeatureFlagStatusAcrossEnvironments) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatusAcrossEnvironments) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FeatureFlagStatusAcrossEnvironments) SetKey(v string) { + o.Key = v +} + +// GetLinks returns the Links field value +func (o *FeatureFlagStatusAcrossEnvironments) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatusAcrossEnvironments) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FeatureFlagStatusAcrossEnvironments) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o FeatureFlagStatusAcrossEnvironments) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["environments"] = o.Environments + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagStatusAcrossEnvironments struct { + value *FeatureFlagStatusAcrossEnvironments + isSet bool +} + +func (v NullableFeatureFlagStatusAcrossEnvironments) Get() *FeatureFlagStatusAcrossEnvironments { + return v.value +} + +func (v *NullableFeatureFlagStatusAcrossEnvironments) Set(val *FeatureFlagStatusAcrossEnvironments) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagStatusAcrossEnvironments) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagStatusAcrossEnvironments) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagStatusAcrossEnvironments(val *FeatureFlagStatusAcrossEnvironments) *NullableFeatureFlagStatusAcrossEnvironments { + return &NullableFeatureFlagStatusAcrossEnvironments{value: val, isSet: true} +} + +func (v NullableFeatureFlagStatusAcrossEnvironments) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagStatusAcrossEnvironments) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_statuses.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_statuses.go new file mode 100644 index 00000000..4a05981b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flag_statuses.go @@ -0,0 +1,145 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlagStatuses struct for FeatureFlagStatuses +type FeatureFlagStatuses struct { + Links map[string]Link `json:"_links"` + Items []FlagStatusRep `json:"items,omitempty"` +} + +// NewFeatureFlagStatuses instantiates a new FeatureFlagStatuses object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlagStatuses(links map[string]Link) *FeatureFlagStatuses { + this := FeatureFlagStatuses{} + this.Links = links + return &this +} + +// NewFeatureFlagStatusesWithDefaults instantiates a new FeatureFlagStatuses object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagStatusesWithDefaults() *FeatureFlagStatuses { + this := FeatureFlagStatuses{} + return &this +} + +// GetLinks returns the Links field value +func (o *FeatureFlagStatuses) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatuses) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FeatureFlagStatuses) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *FeatureFlagStatuses) GetItems() []FlagStatusRep { + if o == nil || o.Items == nil { + var ret []FlagStatusRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlagStatuses) GetItemsOk() ([]FlagStatusRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *FeatureFlagStatuses) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []FlagStatusRep and assigns it to the Items field. +func (o *FeatureFlagStatuses) SetItems(v []FlagStatusRep) { + o.Items = v +} + +func (o FeatureFlagStatuses) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlagStatuses struct { + value *FeatureFlagStatuses + isSet bool +} + +func (v NullableFeatureFlagStatuses) Get() *FeatureFlagStatuses { + return v.value +} + +func (v *NullableFeatureFlagStatuses) Set(val *FeatureFlagStatuses) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlagStatuses) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlagStatuses) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlagStatuses(val *FeatureFlagStatuses) *NullableFeatureFlagStatuses { + return &NullableFeatureFlagStatuses{value: val, isSet: true} +} + +func (v NullableFeatureFlagStatuses) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlagStatuses) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flags.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flags.go new file mode 100644 index 00000000..8d23907a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_feature_flags.go @@ -0,0 +1,214 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FeatureFlags struct for FeatureFlags +type FeatureFlags struct { + // An array of feature flags + Items []FeatureFlag `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The total number of flags + TotalCount *int32 `json:"totalCount,omitempty"` + // The number of flags that have differences between environments. Only shown when query parameter compare is true. + TotalCountWithDifferences *int32 `json:"totalCountWithDifferences,omitempty"` +} + +// NewFeatureFlags instantiates a new FeatureFlags object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFeatureFlags(items []FeatureFlag, links map[string]Link) *FeatureFlags { + this := FeatureFlags{} + this.Items = items + this.Links = links + return &this +} + +// NewFeatureFlagsWithDefaults instantiates a new FeatureFlags object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFeatureFlagsWithDefaults() *FeatureFlags { + this := FeatureFlags{} + return &this +} + +// GetItems returns the Items field value +func (o *FeatureFlags) GetItems() []FeatureFlag { + if o == nil { + var ret []FeatureFlag + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FeatureFlags) GetItemsOk() ([]FeatureFlag, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FeatureFlags) SetItems(v []FeatureFlag) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *FeatureFlags) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FeatureFlags) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FeatureFlags) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *FeatureFlags) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlags) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *FeatureFlags) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *FeatureFlags) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetTotalCountWithDifferences returns the TotalCountWithDifferences field value if set, zero value otherwise. +func (o *FeatureFlags) GetTotalCountWithDifferences() int32 { + if o == nil || o.TotalCountWithDifferences == nil { + var ret int32 + return ret + } + return *o.TotalCountWithDifferences +} + +// GetTotalCountWithDifferencesOk returns a tuple with the TotalCountWithDifferences field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FeatureFlags) GetTotalCountWithDifferencesOk() (*int32, bool) { + if o == nil || o.TotalCountWithDifferences == nil { + return nil, false + } + return o.TotalCountWithDifferences, true +} + +// HasTotalCountWithDifferences returns a boolean if a field has been set. +func (o *FeatureFlags) HasTotalCountWithDifferences() bool { + if o != nil && o.TotalCountWithDifferences != nil { + return true + } + + return false +} + +// SetTotalCountWithDifferences gets a reference to the given int32 and assigns it to the TotalCountWithDifferences field. +func (o *FeatureFlags) SetTotalCountWithDifferences(v int32) { + o.TotalCountWithDifferences = &v +} + +func (o FeatureFlags) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if o.TotalCountWithDifferences != nil { + toSerialize["totalCountWithDifferences"] = o.TotalCountWithDifferences + } + return json.Marshal(toSerialize) +} + +type NullableFeatureFlags struct { + value *FeatureFlags + isSet bool +} + +func (v NullableFeatureFlags) Get() *FeatureFlags { + return v.value +} + +func (v *NullableFeatureFlags) Set(val *FeatureFlags) { + v.value = val + v.isSet = true +} + +func (v NullableFeatureFlags) IsSet() bool { + return v.isSet +} + +func (v *NullableFeatureFlags) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFeatureFlags(val *FeatureFlags) *NullableFeatureFlags { + return &NullableFeatureFlags{value: val, isSet: true} +} + +func (v NullableFeatureFlags) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFeatureFlags) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_file_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_file_rep.go new file mode 100644 index 00000000..aedca76e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_file_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FileRep struct for FileRep +type FileRep struct { + // The imported file name, including the extension + Filename *string `json:"filename,omitempty"` + // The imported file status + Status *string `json:"status,omitempty"` +} + +// NewFileRep instantiates a new FileRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFileRep() *FileRep { + this := FileRep{} + return &this +} + +// NewFileRepWithDefaults instantiates a new FileRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFileRepWithDefaults() *FileRep { + this := FileRep{} + return &this +} + +// GetFilename returns the Filename field value if set, zero value otherwise. +func (o *FileRep) GetFilename() string { + if o == nil || o.Filename == nil { + var ret string + return ret + } + return *o.Filename +} + +// GetFilenameOk returns a tuple with the Filename field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FileRep) GetFilenameOk() (*string, bool) { + if o == nil || o.Filename == nil { + return nil, false + } + return o.Filename, true +} + +// HasFilename returns a boolean if a field has been set. +func (o *FileRep) HasFilename() bool { + if o != nil && o.Filename != nil { + return true + } + + return false +} + +// SetFilename gets a reference to the given string and assigns it to the Filename field. +func (o *FileRep) SetFilename(v string) { + o.Filename = &v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *FileRep) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FileRep) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *FileRep) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *FileRep) SetStatus(v string) { + o.Status = &v +} + +func (o FileRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Filename != nil { + toSerialize["filename"] = o.Filename + } + if o.Status != nil { + toSerialize["status"] = o.Status + } + return json.Marshal(toSerialize) +} + +type NullableFileRep struct { + value *FileRep + isSet bool +} + +func (v NullableFileRep) Get() *FileRep { + return v.value +} + +func (v *NullableFileRep) Set(val *FileRep) { + v.value = val + v.isSet = true +} + +func (v NullableFileRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFileRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFileRep(val *FileRep) *NullableFileRep { + return &NullableFileRep{value: val, isSet: true} +} + +func (v NullableFileRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFileRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_request_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_request_response.go new file mode 100644 index 00000000..31535b68 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_request_response.go @@ -0,0 +1,772 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagConfigApprovalRequestResponse struct for FlagConfigApprovalRequestResponse +type FlagConfigApprovalRequestResponse struct { + // The ID of this approval request + Id string `json:"_id"` + // Version of the approval request + Version int32 `json:"_version"` + CreationDate int64 `json:"creationDate"` + ServiceKind string `json:"serviceKind"` + // The ID of the member who requested the approval + RequestorId *string `json:"requestorId,omitempty"` + // A human-friendly name for the approval request + Description *string `json:"description,omitempty"` + // Current status of the review of this approval request + ReviewStatus string `json:"reviewStatus"` + // An array of individual reviews of this approval request + AllReviews []ReviewResponse `json:"allReviews"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds"` + AppliedDate *int64 `json:"appliedDate,omitempty"` + // The member ID of the member who applied the approval request + AppliedByMemberId *string `json:"appliedByMemberId,omitempty"` + // The service token ID of the service token which applied the approval request + AppliedByServiceTokenId *string `json:"appliedByServiceTokenId,omitempty"` + // Current status of the approval request + Status string `json:"status"` + Instructions []map[string]interface{} `json:"instructions"` + // Details on any conflicting approval requests + Conflicts []Conflict `json:"conflicts"` + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + ExecutionDate *int64 `json:"executionDate,omitempty"` + // ID of scheduled change to edit or delete + OperatingOnId *string `json:"operatingOnId,omitempty"` + IntegrationMetadata *IntegrationMetadata `json:"integrationMetadata,omitempty"` + Source *CopiedFromEnv `json:"source,omitempty"` + CustomWorkflowMetadata *CustomWorkflowMeta `json:"customWorkflowMetadata,omitempty"` +} + +// NewFlagConfigApprovalRequestResponse instantiates a new FlagConfigApprovalRequestResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagConfigApprovalRequestResponse(id string, version int32, creationDate int64, serviceKind string, reviewStatus string, allReviews []ReviewResponse, notifyMemberIds []string, status string, instructions []map[string]interface{}, conflicts []Conflict, links map[string]interface{}) *FlagConfigApprovalRequestResponse { + this := FlagConfigApprovalRequestResponse{} + this.Id = id + this.Version = version + this.CreationDate = creationDate + this.ServiceKind = serviceKind + this.ReviewStatus = reviewStatus + this.AllReviews = allReviews + this.NotifyMemberIds = notifyMemberIds + this.Status = status + this.Instructions = instructions + this.Conflicts = conflicts + this.Links = links + return &this +} + +// NewFlagConfigApprovalRequestResponseWithDefaults instantiates a new FlagConfigApprovalRequestResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagConfigApprovalRequestResponseWithDefaults() *FlagConfigApprovalRequestResponse { + this := FlagConfigApprovalRequestResponse{} + return &this +} + +// GetId returns the Id field value +func (o *FlagConfigApprovalRequestResponse) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagConfigApprovalRequestResponse) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *FlagConfigApprovalRequestResponse) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *FlagConfigApprovalRequestResponse) SetVersion(v int32) { + o.Version = v +} + +// GetCreationDate returns the CreationDate field value +func (o *FlagConfigApprovalRequestResponse) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *FlagConfigApprovalRequestResponse) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetServiceKind returns the ServiceKind field value +func (o *FlagConfigApprovalRequestResponse) GetServiceKind() string { + if o == nil { + var ret string + return ret + } + + return o.ServiceKind +} + +// GetServiceKindOk returns a tuple with the ServiceKind field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetServiceKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ServiceKind, true +} + +// SetServiceKind sets field value +func (o *FlagConfigApprovalRequestResponse) SetServiceKind(v string) { + o.ServiceKind = v +} + +// GetRequestorId returns the RequestorId field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetRequestorId() string { + if o == nil || o.RequestorId == nil { + var ret string + return ret + } + return *o.RequestorId +} + +// GetRequestorIdOk returns a tuple with the RequestorId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetRequestorIdOk() (*string, bool) { + if o == nil || o.RequestorId == nil { + return nil, false + } + return o.RequestorId, true +} + +// HasRequestorId returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasRequestorId() bool { + if o != nil && o.RequestorId != nil { + return true + } + + return false +} + +// SetRequestorId gets a reference to the given string and assigns it to the RequestorId field. +func (o *FlagConfigApprovalRequestResponse) SetRequestorId(v string) { + o.RequestorId = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FlagConfigApprovalRequestResponse) SetDescription(v string) { + o.Description = &v +} + +// GetReviewStatus returns the ReviewStatus field value +func (o *FlagConfigApprovalRequestResponse) GetReviewStatus() string { + if o == nil { + var ret string + return ret + } + + return o.ReviewStatus +} + +// GetReviewStatusOk returns a tuple with the ReviewStatus field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetReviewStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReviewStatus, true +} + +// SetReviewStatus sets field value +func (o *FlagConfigApprovalRequestResponse) SetReviewStatus(v string) { + o.ReviewStatus = v +} + +// GetAllReviews returns the AllReviews field value +func (o *FlagConfigApprovalRequestResponse) GetAllReviews() []ReviewResponse { + if o == nil { + var ret []ReviewResponse + return ret + } + + return o.AllReviews +} + +// GetAllReviewsOk returns a tuple with the AllReviews field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetAllReviewsOk() ([]ReviewResponse, bool) { + if o == nil { + return nil, false + } + return o.AllReviews, true +} + +// SetAllReviews sets field value +func (o *FlagConfigApprovalRequestResponse) SetAllReviews(v []ReviewResponse) { + o.AllReviews = v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value +func (o *FlagConfigApprovalRequestResponse) GetNotifyMemberIds() []string { + if o == nil { + var ret []string + return ret + } + + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// SetNotifyMemberIds sets field value +func (o *FlagConfigApprovalRequestResponse) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetAppliedDate returns the AppliedDate field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetAppliedDate() int64 { + if o == nil || o.AppliedDate == nil { + var ret int64 + return ret + } + return *o.AppliedDate +} + +// GetAppliedDateOk returns a tuple with the AppliedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetAppliedDateOk() (*int64, bool) { + if o == nil || o.AppliedDate == nil { + return nil, false + } + return o.AppliedDate, true +} + +// HasAppliedDate returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasAppliedDate() bool { + if o != nil && o.AppliedDate != nil { + return true + } + + return false +} + +// SetAppliedDate gets a reference to the given int64 and assigns it to the AppliedDate field. +func (o *FlagConfigApprovalRequestResponse) SetAppliedDate(v int64) { + o.AppliedDate = &v +} + +// GetAppliedByMemberId returns the AppliedByMemberId field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetAppliedByMemberId() string { + if o == nil || o.AppliedByMemberId == nil { + var ret string + return ret + } + return *o.AppliedByMemberId +} + +// GetAppliedByMemberIdOk returns a tuple with the AppliedByMemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetAppliedByMemberIdOk() (*string, bool) { + if o == nil || o.AppliedByMemberId == nil { + return nil, false + } + return o.AppliedByMemberId, true +} + +// HasAppliedByMemberId returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasAppliedByMemberId() bool { + if o != nil && o.AppliedByMemberId != nil { + return true + } + + return false +} + +// SetAppliedByMemberId gets a reference to the given string and assigns it to the AppliedByMemberId field. +func (o *FlagConfigApprovalRequestResponse) SetAppliedByMemberId(v string) { + o.AppliedByMemberId = &v +} + +// GetAppliedByServiceTokenId returns the AppliedByServiceTokenId field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetAppliedByServiceTokenId() string { + if o == nil || o.AppliedByServiceTokenId == nil { + var ret string + return ret + } + return *o.AppliedByServiceTokenId +} + +// GetAppliedByServiceTokenIdOk returns a tuple with the AppliedByServiceTokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetAppliedByServiceTokenIdOk() (*string, bool) { + if o == nil || o.AppliedByServiceTokenId == nil { + return nil, false + } + return o.AppliedByServiceTokenId, true +} + +// HasAppliedByServiceTokenId returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasAppliedByServiceTokenId() bool { + if o != nil && o.AppliedByServiceTokenId != nil { + return true + } + + return false +} + +// SetAppliedByServiceTokenId gets a reference to the given string and assigns it to the AppliedByServiceTokenId field. +func (o *FlagConfigApprovalRequestResponse) SetAppliedByServiceTokenId(v string) { + o.AppliedByServiceTokenId = &v +} + +// GetStatus returns the Status field value +func (o *FlagConfigApprovalRequestResponse) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *FlagConfigApprovalRequestResponse) SetStatus(v string) { + o.Status = v +} + +// GetInstructions returns the Instructions field value +func (o *FlagConfigApprovalRequestResponse) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *FlagConfigApprovalRequestResponse) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetConflicts returns the Conflicts field value +func (o *FlagConfigApprovalRequestResponse) GetConflicts() []Conflict { + if o == nil { + var ret []Conflict + return ret + } + + return o.Conflicts +} + +// GetConflictsOk returns a tuple with the Conflicts field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetConflictsOk() ([]Conflict, bool) { + if o == nil { + return nil, false + } + return o.Conflicts, true +} + +// SetConflicts sets field value +func (o *FlagConfigApprovalRequestResponse) SetConflicts(v []Conflict) { + o.Conflicts = v +} + +// GetLinks returns the Links field value +func (o *FlagConfigApprovalRequestResponse) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *FlagConfigApprovalRequestResponse) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetExecutionDate returns the ExecutionDate field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetExecutionDate() int64 { + if o == nil || o.ExecutionDate == nil { + var ret int64 + return ret + } + return *o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetExecutionDateOk() (*int64, bool) { + if o == nil || o.ExecutionDate == nil { + return nil, false + } + return o.ExecutionDate, true +} + +// HasExecutionDate returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasExecutionDate() bool { + if o != nil && o.ExecutionDate != nil { + return true + } + + return false +} + +// SetExecutionDate gets a reference to the given int64 and assigns it to the ExecutionDate field. +func (o *FlagConfigApprovalRequestResponse) SetExecutionDate(v int64) { + o.ExecutionDate = &v +} + +// GetOperatingOnId returns the OperatingOnId field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetOperatingOnId() string { + if o == nil || o.OperatingOnId == nil { + var ret string + return ret + } + return *o.OperatingOnId +} + +// GetOperatingOnIdOk returns a tuple with the OperatingOnId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetOperatingOnIdOk() (*string, bool) { + if o == nil || o.OperatingOnId == nil { + return nil, false + } + return o.OperatingOnId, true +} + +// HasOperatingOnId returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasOperatingOnId() bool { + if o != nil && o.OperatingOnId != nil { + return true + } + + return false +} + +// SetOperatingOnId gets a reference to the given string and assigns it to the OperatingOnId field. +func (o *FlagConfigApprovalRequestResponse) SetOperatingOnId(v string) { + o.OperatingOnId = &v +} + +// GetIntegrationMetadata returns the IntegrationMetadata field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetIntegrationMetadata() IntegrationMetadata { + if o == nil || o.IntegrationMetadata == nil { + var ret IntegrationMetadata + return ret + } + return *o.IntegrationMetadata +} + +// GetIntegrationMetadataOk returns a tuple with the IntegrationMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetIntegrationMetadataOk() (*IntegrationMetadata, bool) { + if o == nil || o.IntegrationMetadata == nil { + return nil, false + } + return o.IntegrationMetadata, true +} + +// HasIntegrationMetadata returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasIntegrationMetadata() bool { + if o != nil && o.IntegrationMetadata != nil { + return true + } + + return false +} + +// SetIntegrationMetadata gets a reference to the given IntegrationMetadata and assigns it to the IntegrationMetadata field. +func (o *FlagConfigApprovalRequestResponse) SetIntegrationMetadata(v IntegrationMetadata) { + o.IntegrationMetadata = &v +} + +// GetSource returns the Source field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetSource() CopiedFromEnv { + if o == nil || o.Source == nil { + var ret CopiedFromEnv + return ret + } + return *o.Source +} + +// GetSourceOk returns a tuple with the Source field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetSourceOk() (*CopiedFromEnv, bool) { + if o == nil || o.Source == nil { + return nil, false + } + return o.Source, true +} + +// HasSource returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasSource() bool { + if o != nil && o.Source != nil { + return true + } + + return false +} + +// SetSource gets a reference to the given CopiedFromEnv and assigns it to the Source field. +func (o *FlagConfigApprovalRequestResponse) SetSource(v CopiedFromEnv) { + o.Source = &v +} + +// GetCustomWorkflowMetadata returns the CustomWorkflowMetadata field value if set, zero value otherwise. +func (o *FlagConfigApprovalRequestResponse) GetCustomWorkflowMetadata() CustomWorkflowMeta { + if o == nil || o.CustomWorkflowMetadata == nil { + var ret CustomWorkflowMeta + return ret + } + return *o.CustomWorkflowMetadata +} + +// GetCustomWorkflowMetadataOk returns a tuple with the CustomWorkflowMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestResponse) GetCustomWorkflowMetadataOk() (*CustomWorkflowMeta, bool) { + if o == nil || o.CustomWorkflowMetadata == nil { + return nil, false + } + return o.CustomWorkflowMetadata, true +} + +// HasCustomWorkflowMetadata returns a boolean if a field has been set. +func (o *FlagConfigApprovalRequestResponse) HasCustomWorkflowMetadata() bool { + if o != nil && o.CustomWorkflowMetadata != nil { + return true + } + + return false +} + +// SetCustomWorkflowMetadata gets a reference to the given CustomWorkflowMeta and assigns it to the CustomWorkflowMetadata field. +func (o *FlagConfigApprovalRequestResponse) SetCustomWorkflowMetadata(v CustomWorkflowMeta) { + o.CustomWorkflowMetadata = &v +} + +func (o FlagConfigApprovalRequestResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_version"] = o.Version + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["serviceKind"] = o.ServiceKind + } + if o.RequestorId != nil { + toSerialize["requestorId"] = o.RequestorId + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["reviewStatus"] = o.ReviewStatus + } + if true { + toSerialize["allReviews"] = o.AllReviews + } + if true { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.AppliedDate != nil { + toSerialize["appliedDate"] = o.AppliedDate + } + if o.AppliedByMemberId != nil { + toSerialize["appliedByMemberId"] = o.AppliedByMemberId + } + if o.AppliedByServiceTokenId != nil { + toSerialize["appliedByServiceTokenId"] = o.AppliedByServiceTokenId + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["instructions"] = o.Instructions + } + if true { + toSerialize["conflicts"] = o.Conflicts + } + if true { + toSerialize["_links"] = o.Links + } + if o.ExecutionDate != nil { + toSerialize["executionDate"] = o.ExecutionDate + } + if o.OperatingOnId != nil { + toSerialize["operatingOnId"] = o.OperatingOnId + } + if o.IntegrationMetadata != nil { + toSerialize["integrationMetadata"] = o.IntegrationMetadata + } + if o.Source != nil { + toSerialize["source"] = o.Source + } + if o.CustomWorkflowMetadata != nil { + toSerialize["customWorkflowMetadata"] = o.CustomWorkflowMetadata + } + return json.Marshal(toSerialize) +} + +type NullableFlagConfigApprovalRequestResponse struct { + value *FlagConfigApprovalRequestResponse + isSet bool +} + +func (v NullableFlagConfigApprovalRequestResponse) Get() *FlagConfigApprovalRequestResponse { + return v.value +} + +func (v *NullableFlagConfigApprovalRequestResponse) Set(val *FlagConfigApprovalRequestResponse) { + v.value = val + v.isSet = true +} + +func (v NullableFlagConfigApprovalRequestResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagConfigApprovalRequestResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagConfigApprovalRequestResponse(val *FlagConfigApprovalRequestResponse) *NullableFlagConfigApprovalRequestResponse { + return &NullableFlagConfigApprovalRequestResponse{value: val, isSet: true} +} + +func (v NullableFlagConfigApprovalRequestResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagConfigApprovalRequestResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_requests_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_requests_response.go new file mode 100644 index 00000000..2ca937cc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_approval_requests_response.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagConfigApprovalRequestsResponse struct for FlagConfigApprovalRequestsResponse +type FlagConfigApprovalRequestsResponse struct { + // An array of approval requests + Items []FlagConfigApprovalRequestResponse `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewFlagConfigApprovalRequestsResponse instantiates a new FlagConfigApprovalRequestsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagConfigApprovalRequestsResponse(items []FlagConfigApprovalRequestResponse, links map[string]Link) *FlagConfigApprovalRequestsResponse { + this := FlagConfigApprovalRequestsResponse{} + this.Items = items + this.Links = links + return &this +} + +// NewFlagConfigApprovalRequestsResponseWithDefaults instantiates a new FlagConfigApprovalRequestsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagConfigApprovalRequestsResponseWithDefaults() *FlagConfigApprovalRequestsResponse { + this := FlagConfigApprovalRequestsResponse{} + return &this +} + +// GetItems returns the Items field value +func (o *FlagConfigApprovalRequestsResponse) GetItems() []FlagConfigApprovalRequestResponse { + if o == nil { + var ret []FlagConfigApprovalRequestResponse + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestsResponse) GetItemsOk() ([]FlagConfigApprovalRequestResponse, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagConfigApprovalRequestsResponse) SetItems(v []FlagConfigApprovalRequestResponse) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *FlagConfigApprovalRequestsResponse) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagConfigApprovalRequestsResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagConfigApprovalRequestsResponse) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o FlagConfigApprovalRequestsResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagConfigApprovalRequestsResponse struct { + value *FlagConfigApprovalRequestsResponse + isSet bool +} + +func (v NullableFlagConfigApprovalRequestsResponse) Get() *FlagConfigApprovalRequestsResponse { + return v.value +} + +func (v *NullableFlagConfigApprovalRequestsResponse) Set(val *FlagConfigApprovalRequestsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableFlagConfigApprovalRequestsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagConfigApprovalRequestsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagConfigApprovalRequestsResponse(val *FlagConfigApprovalRequestsResponse) *NullableFlagConfigApprovalRequestsResponse { + return &NullableFlagConfigApprovalRequestsResponse{value: val, isSet: true} +} + +func (v NullableFlagConfigApprovalRequestsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagConfigApprovalRequestsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_evaluation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_evaluation.go new file mode 100644 index 00000000..3ade11e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_evaluation.go @@ -0,0 +1,116 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagConfigEvaluation struct for FlagConfigEvaluation +type FlagConfigEvaluation struct { + ContextKinds []string `json:"contextKinds,omitempty"` +} + +// NewFlagConfigEvaluation instantiates a new FlagConfigEvaluation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagConfigEvaluation() *FlagConfigEvaluation { + this := FlagConfigEvaluation{} + return &this +} + +// NewFlagConfigEvaluationWithDefaults instantiates a new FlagConfigEvaluation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagConfigEvaluationWithDefaults() *FlagConfigEvaluation { + this := FlagConfigEvaluation{} + return &this +} + +// GetContextKinds returns the ContextKinds field value if set, zero value otherwise. +func (o *FlagConfigEvaluation) GetContextKinds() []string { + if o == nil || o.ContextKinds == nil { + var ret []string + return ret + } + return o.ContextKinds +} + +// GetContextKindsOk returns a tuple with the ContextKinds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigEvaluation) GetContextKindsOk() ([]string, bool) { + if o == nil || o.ContextKinds == nil { + return nil, false + } + return o.ContextKinds, true +} + +// HasContextKinds returns a boolean if a field has been set. +func (o *FlagConfigEvaluation) HasContextKinds() bool { + if o != nil && o.ContextKinds != nil { + return true + } + + return false +} + +// SetContextKinds gets a reference to the given []string and assigns it to the ContextKinds field. +func (o *FlagConfigEvaluation) SetContextKinds(v []string) { + o.ContextKinds = v +} + +func (o FlagConfigEvaluation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ContextKinds != nil { + toSerialize["contextKinds"] = o.ContextKinds + } + return json.Marshal(toSerialize) +} + +type NullableFlagConfigEvaluation struct { + value *FlagConfigEvaluation + isSet bool +} + +func (v NullableFlagConfigEvaluation) Get() *FlagConfigEvaluation { + return v.value +} + +func (v *NullableFlagConfigEvaluation) Set(val *FlagConfigEvaluation) { + v.value = val + v.isSet = true +} + +func (v NullableFlagConfigEvaluation) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagConfigEvaluation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagConfigEvaluation(val *FlagConfigEvaluation) *NullableFlagConfigEvaluation { + return &NullableFlagConfigEvaluation{value: val, isSet: true} +} + +func (v NullableFlagConfigEvaluation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagConfigEvaluation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_migration_settings_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_migration_settings_rep.go new file mode 100644 index 00000000..7b1dcf79 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_config_migration_settings_rep.go @@ -0,0 +1,116 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagConfigMigrationSettingsRep struct for FlagConfigMigrationSettingsRep +type FlagConfigMigrationSettingsRep struct { + CheckRatio *int32 `json:"checkRatio,omitempty"` +} + +// NewFlagConfigMigrationSettingsRep instantiates a new FlagConfigMigrationSettingsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagConfigMigrationSettingsRep() *FlagConfigMigrationSettingsRep { + this := FlagConfigMigrationSettingsRep{} + return &this +} + +// NewFlagConfigMigrationSettingsRepWithDefaults instantiates a new FlagConfigMigrationSettingsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagConfigMigrationSettingsRepWithDefaults() *FlagConfigMigrationSettingsRep { + this := FlagConfigMigrationSettingsRep{} + return &this +} + +// GetCheckRatio returns the CheckRatio field value if set, zero value otherwise. +func (o *FlagConfigMigrationSettingsRep) GetCheckRatio() int32 { + if o == nil || o.CheckRatio == nil { + var ret int32 + return ret + } + return *o.CheckRatio +} + +// GetCheckRatioOk returns a tuple with the CheckRatio field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagConfigMigrationSettingsRep) GetCheckRatioOk() (*int32, bool) { + if o == nil || o.CheckRatio == nil { + return nil, false + } + return o.CheckRatio, true +} + +// HasCheckRatio returns a boolean if a field has been set. +func (o *FlagConfigMigrationSettingsRep) HasCheckRatio() bool { + if o != nil && o.CheckRatio != nil { + return true + } + + return false +} + +// SetCheckRatio gets a reference to the given int32 and assigns it to the CheckRatio field. +func (o *FlagConfigMigrationSettingsRep) SetCheckRatio(v int32) { + o.CheckRatio = &v +} + +func (o FlagConfigMigrationSettingsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.CheckRatio != nil { + toSerialize["checkRatio"] = o.CheckRatio + } + return json.Marshal(toSerialize) +} + +type NullableFlagConfigMigrationSettingsRep struct { + value *FlagConfigMigrationSettingsRep + isSet bool +} + +func (v NullableFlagConfigMigrationSettingsRep) Get() *FlagConfigMigrationSettingsRep { + return v.value +} + +func (v *NullableFlagConfigMigrationSettingsRep) Set(val *FlagConfigMigrationSettingsRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagConfigMigrationSettingsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagConfigMigrationSettingsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagConfigMigrationSettingsRep(val *FlagConfigMigrationSettingsRep) *NullableFlagConfigMigrationSettingsRep { + return &NullableFlagConfigMigrationSettingsRep{value: val, isSet: true} +} + +func (v NullableFlagConfigMigrationSettingsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagConfigMigrationSettingsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_environment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_environment.go new file mode 100644 index 00000000..7e4a9a23 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_environment.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagCopyConfigEnvironment struct for FlagCopyConfigEnvironment +type FlagCopyConfigEnvironment struct { + // The environment key + Key string `json:"key"` + // Optional flag version. If you include this, the operation only succeeds if the current flag version in the environment matches this version. + CurrentVersion *int32 `json:"currentVersion,omitempty"` +} + +// NewFlagCopyConfigEnvironment instantiates a new FlagCopyConfigEnvironment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagCopyConfigEnvironment(key string) *FlagCopyConfigEnvironment { + this := FlagCopyConfigEnvironment{} + this.Key = key + return &this +} + +// NewFlagCopyConfigEnvironmentWithDefaults instantiates a new FlagCopyConfigEnvironment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagCopyConfigEnvironmentWithDefaults() *FlagCopyConfigEnvironment { + this := FlagCopyConfigEnvironment{} + return &this +} + +// GetKey returns the Key field value +func (o *FlagCopyConfigEnvironment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigEnvironment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FlagCopyConfigEnvironment) SetKey(v string) { + o.Key = v +} + +// GetCurrentVersion returns the CurrentVersion field value if set, zero value otherwise. +func (o *FlagCopyConfigEnvironment) GetCurrentVersion() int32 { + if o == nil || o.CurrentVersion == nil { + var ret int32 + return ret + } + return *o.CurrentVersion +} + +// GetCurrentVersionOk returns a tuple with the CurrentVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigEnvironment) GetCurrentVersionOk() (*int32, bool) { + if o == nil || o.CurrentVersion == nil { + return nil, false + } + return o.CurrentVersion, true +} + +// HasCurrentVersion returns a boolean if a field has been set. +func (o *FlagCopyConfigEnvironment) HasCurrentVersion() bool { + if o != nil && o.CurrentVersion != nil { + return true + } + + return false +} + +// SetCurrentVersion gets a reference to the given int32 and assigns it to the CurrentVersion field. +func (o *FlagCopyConfigEnvironment) SetCurrentVersion(v int32) { + o.CurrentVersion = &v +} + +func (o FlagCopyConfigEnvironment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.CurrentVersion != nil { + toSerialize["currentVersion"] = o.CurrentVersion + } + return json.Marshal(toSerialize) +} + +type NullableFlagCopyConfigEnvironment struct { + value *FlagCopyConfigEnvironment + isSet bool +} + +func (v NullableFlagCopyConfigEnvironment) Get() *FlagCopyConfigEnvironment { + return v.value +} + +func (v *NullableFlagCopyConfigEnvironment) Set(val *FlagCopyConfigEnvironment) { + v.value = val + v.isSet = true +} + +func (v NullableFlagCopyConfigEnvironment) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagCopyConfigEnvironment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagCopyConfigEnvironment(val *FlagCopyConfigEnvironment) *NullableFlagCopyConfigEnvironment { + return &NullableFlagCopyConfigEnvironment{value: val, isSet: true} +} + +func (v NullableFlagCopyConfigEnvironment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagCopyConfigEnvironment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_post.go new file mode 100644 index 00000000..96c3091d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_copy_config_post.go @@ -0,0 +1,249 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagCopyConfigPost struct for FlagCopyConfigPost +type FlagCopyConfigPost struct { + Source FlagCopyConfigEnvironment `json:"source"` + Target FlagCopyConfigEnvironment `json:"target"` + // Optional comment + Comment *string `json:"comment,omitempty"` + // Optional list of the flag changes to copy from the source environment to the target environment. You may include either includedActions or excludedActions, but not both. If you include neither, then all flag changes will be copied. + IncludedActions []string `json:"includedActions,omitempty"` + // Optional list of the flag changes NOT to copy from the source environment to the target environment. You may include either includedActions or excludedActions, but not both. If you include neither, then all flag changes will be copied. + ExcludedActions []string `json:"excludedActions,omitempty"` +} + +// NewFlagCopyConfigPost instantiates a new FlagCopyConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagCopyConfigPost(source FlagCopyConfigEnvironment, target FlagCopyConfigEnvironment) *FlagCopyConfigPost { + this := FlagCopyConfigPost{} + this.Source = source + this.Target = target + return &this +} + +// NewFlagCopyConfigPostWithDefaults instantiates a new FlagCopyConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagCopyConfigPostWithDefaults() *FlagCopyConfigPost { + this := FlagCopyConfigPost{} + return &this +} + +// GetSource returns the Source field value +func (o *FlagCopyConfigPost) GetSource() FlagCopyConfigEnvironment { + if o == nil { + var ret FlagCopyConfigEnvironment + return ret + } + + return o.Source +} + +// GetSourceOk returns a tuple with the Source field value +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigPost) GetSourceOk() (*FlagCopyConfigEnvironment, bool) { + if o == nil { + return nil, false + } + return &o.Source, true +} + +// SetSource sets field value +func (o *FlagCopyConfigPost) SetSource(v FlagCopyConfigEnvironment) { + o.Source = v +} + +// GetTarget returns the Target field value +func (o *FlagCopyConfigPost) GetTarget() FlagCopyConfigEnvironment { + if o == nil { + var ret FlagCopyConfigEnvironment + return ret + } + + return o.Target +} + +// GetTargetOk returns a tuple with the Target field value +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigPost) GetTargetOk() (*FlagCopyConfigEnvironment, bool) { + if o == nil { + return nil, false + } + return &o.Target, true +} + +// SetTarget sets field value +func (o *FlagCopyConfigPost) SetTarget(v FlagCopyConfigEnvironment) { + o.Target = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *FlagCopyConfigPost) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigPost) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *FlagCopyConfigPost) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *FlagCopyConfigPost) SetComment(v string) { + o.Comment = &v +} + +// GetIncludedActions returns the IncludedActions field value if set, zero value otherwise. +func (o *FlagCopyConfigPost) GetIncludedActions() []string { + if o == nil || o.IncludedActions == nil { + var ret []string + return ret + } + return o.IncludedActions +} + +// GetIncludedActionsOk returns a tuple with the IncludedActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigPost) GetIncludedActionsOk() ([]string, bool) { + if o == nil || o.IncludedActions == nil { + return nil, false + } + return o.IncludedActions, true +} + +// HasIncludedActions returns a boolean if a field has been set. +func (o *FlagCopyConfigPost) HasIncludedActions() bool { + if o != nil && o.IncludedActions != nil { + return true + } + + return false +} + +// SetIncludedActions gets a reference to the given []string and assigns it to the IncludedActions field. +func (o *FlagCopyConfigPost) SetIncludedActions(v []string) { + o.IncludedActions = v +} + +// GetExcludedActions returns the ExcludedActions field value if set, zero value otherwise. +func (o *FlagCopyConfigPost) GetExcludedActions() []string { + if o == nil || o.ExcludedActions == nil { + var ret []string + return ret + } + return o.ExcludedActions +} + +// GetExcludedActionsOk returns a tuple with the ExcludedActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagCopyConfigPost) GetExcludedActionsOk() ([]string, bool) { + if o == nil || o.ExcludedActions == nil { + return nil, false + } + return o.ExcludedActions, true +} + +// HasExcludedActions returns a boolean if a field has been set. +func (o *FlagCopyConfigPost) HasExcludedActions() bool { + if o != nil && o.ExcludedActions != nil { + return true + } + + return false +} + +// SetExcludedActions gets a reference to the given []string and assigns it to the ExcludedActions field. +func (o *FlagCopyConfigPost) SetExcludedActions(v []string) { + o.ExcludedActions = v +} + +func (o FlagCopyConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["source"] = o.Source + } + if true { + toSerialize["target"] = o.Target + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.IncludedActions != nil { + toSerialize["includedActions"] = o.IncludedActions + } + if o.ExcludedActions != nil { + toSerialize["excludedActions"] = o.ExcludedActions + } + return json.Marshal(toSerialize) +} + +type NullableFlagCopyConfigPost struct { + value *FlagCopyConfigPost + isSet bool +} + +func (v NullableFlagCopyConfigPost) Get() *FlagCopyConfigPost { + return v.value +} + +func (v *NullableFlagCopyConfigPost) Set(val *FlagCopyConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableFlagCopyConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagCopyConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagCopyConfigPost(val *FlagCopyConfigPost) *NullableFlagCopyConfigPost { + return &NullableFlagCopyConfigPost{value: val, isSet: true} +} + +func (v NullableFlagCopyConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagCopyConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_defaults_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_defaults_rep.go new file mode 100644 index 00000000..994a2d96 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_defaults_rep.go @@ -0,0 +1,300 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagDefaultsRep struct for FlagDefaultsRep +type FlagDefaultsRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // A unique key for the flag default + Key *string `json:"key,omitempty"` + // A list of default tags for each flag + Tags []string `json:"tags,omitempty"` + // Whether the flag should be temporary by default + Temporary *bool `json:"temporary,omitempty"` + DefaultClientSideAvailability *ClientSideAvailability `json:"defaultClientSideAvailability,omitempty"` + BooleanDefaults *BooleanDefaults `json:"booleanDefaults,omitempty"` +} + +// NewFlagDefaultsRep instantiates a new FlagDefaultsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagDefaultsRep() *FlagDefaultsRep { + this := FlagDefaultsRep{} + return &this +} + +// NewFlagDefaultsRepWithDefaults instantiates a new FlagDefaultsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagDefaultsRepWithDefaults() *FlagDefaultsRep { + this := FlagDefaultsRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FlagDefaultsRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *FlagDefaultsRep) SetKey(v string) { + o.Key = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *FlagDefaultsRep) SetTags(v []string) { + o.Tags = v +} + +// GetTemporary returns the Temporary field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetTemporary() bool { + if o == nil || o.Temporary == nil { + var ret bool + return ret + } + return *o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetTemporaryOk() (*bool, bool) { + if o == nil || o.Temporary == nil { + return nil, false + } + return o.Temporary, true +} + +// HasTemporary returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasTemporary() bool { + if o != nil && o.Temporary != nil { + return true + } + + return false +} + +// SetTemporary gets a reference to the given bool and assigns it to the Temporary field. +func (o *FlagDefaultsRep) SetTemporary(v bool) { + o.Temporary = &v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetDefaultClientSideAvailability() ClientSideAvailability { + if o == nil || o.DefaultClientSideAvailability == nil { + var ret ClientSideAvailability + return ret + } + return *o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetDefaultClientSideAvailabilityOk() (*ClientSideAvailability, bool) { + if o == nil || o.DefaultClientSideAvailability == nil { + return nil, false + } + return o.DefaultClientSideAvailability, true +} + +// HasDefaultClientSideAvailability returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasDefaultClientSideAvailability() bool { + if o != nil && o.DefaultClientSideAvailability != nil { + return true + } + + return false +} + +// SetDefaultClientSideAvailability gets a reference to the given ClientSideAvailability and assigns it to the DefaultClientSideAvailability field. +func (o *FlagDefaultsRep) SetDefaultClientSideAvailability(v ClientSideAvailability) { + o.DefaultClientSideAvailability = &v +} + +// GetBooleanDefaults returns the BooleanDefaults field value if set, zero value otherwise. +func (o *FlagDefaultsRep) GetBooleanDefaults() BooleanDefaults { + if o == nil || o.BooleanDefaults == nil { + var ret BooleanDefaults + return ret + } + return *o.BooleanDefaults +} + +// GetBooleanDefaultsOk returns a tuple with the BooleanDefaults field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagDefaultsRep) GetBooleanDefaultsOk() (*BooleanDefaults, bool) { + if o == nil || o.BooleanDefaults == nil { + return nil, false + } + return o.BooleanDefaults, true +} + +// HasBooleanDefaults returns a boolean if a field has been set. +func (o *FlagDefaultsRep) HasBooleanDefaults() bool { + if o != nil && o.BooleanDefaults != nil { + return true + } + + return false +} + +// SetBooleanDefaults gets a reference to the given BooleanDefaults and assigns it to the BooleanDefaults field. +func (o *FlagDefaultsRep) SetBooleanDefaults(v BooleanDefaults) { + o.BooleanDefaults = &v +} + +func (o FlagDefaultsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Temporary != nil { + toSerialize["temporary"] = o.Temporary + } + if o.DefaultClientSideAvailability != nil { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + if o.BooleanDefaults != nil { + toSerialize["booleanDefaults"] = o.BooleanDefaults + } + return json.Marshal(toSerialize) +} + +type NullableFlagDefaultsRep struct { + value *FlagDefaultsRep + isSet bool +} + +func (v NullableFlagDefaultsRep) Get() *FlagDefaultsRep { + return v.value +} + +func (v *NullableFlagDefaultsRep) Set(val *FlagDefaultsRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagDefaultsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagDefaultsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagDefaultsRep(val *FlagDefaultsRep) *NullableFlagDefaultsRep { + return &NullableFlagDefaultsRep{value: val, isSet: true} +} + +func (v NullableFlagDefaultsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagDefaultsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_collection_rep.go new file mode 100644 index 00000000..eac829bc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_collection_rep.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventCollectionRep struct for FlagEventCollectionRep +type FlagEventCollectionRep struct { + // The total number of flag events + TotalCount int32 `json:"totalCount"` + // A list of flag events + Items []FlagEventRep `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewFlagEventCollectionRep instantiates a new FlagEventCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventCollectionRep(totalCount int32, items []FlagEventRep) *FlagEventCollectionRep { + this := FlagEventCollectionRep{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewFlagEventCollectionRepWithDefaults instantiates a new FlagEventCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventCollectionRepWithDefaults() *FlagEventCollectionRep { + this := FlagEventCollectionRep{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *FlagEventCollectionRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *FlagEventCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *FlagEventCollectionRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *FlagEventCollectionRep) GetItems() []FlagEventRep { + if o == nil { + var ret []FlagEventRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagEventCollectionRep) GetItemsOk() ([]FlagEventRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagEventCollectionRep) SetItems(v []FlagEventRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FlagEventCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FlagEventCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FlagEventCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o FlagEventCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventCollectionRep struct { + value *FlagEventCollectionRep + isSet bool +} + +func (v NullableFlagEventCollectionRep) Get() *FlagEventCollectionRep { + return v.value +} + +func (v *NullableFlagEventCollectionRep) Set(val *FlagEventCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventCollectionRep(val *FlagEventCollectionRep) *NullableFlagEventCollectionRep { + return &NullableFlagEventCollectionRep{value: val, isSet: true} +} + +func (v NullableFlagEventCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment.go new file mode 100644 index 00000000..bc28206a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment.go @@ -0,0 +1,206 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventExperiment struct for FlagEventExperiment +type FlagEventExperiment struct { + // The experiment key + Key string `json:"key"` + // The experiment name + Name string `json:"name"` + Iteration FlagEventExperimentIteration `json:"iteration"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewFlagEventExperiment instantiates a new FlagEventExperiment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventExperiment(key string, name string, iteration FlagEventExperimentIteration) *FlagEventExperiment { + this := FlagEventExperiment{} + this.Key = key + this.Name = name + this.Iteration = iteration + return &this +} + +// NewFlagEventExperimentWithDefaults instantiates a new FlagEventExperiment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventExperimentWithDefaults() *FlagEventExperiment { + this := FlagEventExperiment{} + return &this +} + +// GetKey returns the Key field value +func (o *FlagEventExperiment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperiment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FlagEventExperiment) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *FlagEventExperiment) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperiment) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FlagEventExperiment) SetName(v string) { + o.Name = v +} + +// GetIteration returns the Iteration field value +func (o *FlagEventExperiment) GetIteration() FlagEventExperimentIteration { + if o == nil { + var ret FlagEventExperimentIteration + return ret + } + + return o.Iteration +} + +// GetIterationOk returns a tuple with the Iteration field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperiment) GetIterationOk() (*FlagEventExperimentIteration, bool) { + if o == nil { + return nil, false + } + return &o.Iteration, true +} + +// SetIteration sets field value +func (o *FlagEventExperiment) SetIteration(v FlagEventExperimentIteration) { + o.Iteration = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FlagEventExperiment) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventExperiment) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FlagEventExperiment) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FlagEventExperiment) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o FlagEventExperiment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["iteration"] = o.Iteration + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventExperiment struct { + value *FlagEventExperiment + isSet bool +} + +func (v NullableFlagEventExperiment) Get() *FlagEventExperiment { + return v.value +} + +func (v *NullableFlagEventExperiment) Set(val *FlagEventExperiment) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventExperiment) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventExperiment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventExperiment(val *FlagEventExperiment) *NullableFlagEventExperiment { + return &NullableFlagEventExperiment{value: val, isSet: true} +} + +func (v NullableFlagEventExperiment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventExperiment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_collection.go new file mode 100644 index 00000000..cc792f37 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_collection.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventExperimentCollection struct for FlagEventExperimentCollection +type FlagEventExperimentCollection struct { + // The total number of experiments + TotalCount int32 `json:"totalCount"` + // A list of experiments + Items []FlagEventExperiment `json:"items"` +} + +// NewFlagEventExperimentCollection instantiates a new FlagEventExperimentCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventExperimentCollection(totalCount int32, items []FlagEventExperiment) *FlagEventExperimentCollection { + this := FlagEventExperimentCollection{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewFlagEventExperimentCollectionWithDefaults instantiates a new FlagEventExperimentCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventExperimentCollectionWithDefaults() *FlagEventExperimentCollection { + this := FlagEventExperimentCollection{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *FlagEventExperimentCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *FlagEventExperimentCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *FlagEventExperimentCollection) GetItems() []FlagEventExperiment { + if o == nil { + var ret []FlagEventExperiment + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentCollection) GetItemsOk() ([]FlagEventExperiment, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagEventExperimentCollection) SetItems(v []FlagEventExperiment) { + o.Items = v +} + +func (o FlagEventExperimentCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventExperimentCollection struct { + value *FlagEventExperimentCollection + isSet bool +} + +func (v NullableFlagEventExperimentCollection) Get() *FlagEventExperimentCollection { + return v.value +} + +func (v *NullableFlagEventExperimentCollection) Set(val *FlagEventExperimentCollection) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventExperimentCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventExperimentCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventExperimentCollection(val *FlagEventExperimentCollection) *NullableFlagEventExperimentCollection { + return &NullableFlagEventExperimentCollection{value: val, isSet: true} +} + +func (v NullableFlagEventExperimentCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventExperimentCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_iteration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_iteration.go new file mode 100644 index 00000000..f7045aa5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_experiment_iteration.go @@ -0,0 +1,241 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventExperimentIteration struct for FlagEventExperimentIteration +type FlagEventExperimentIteration struct { + // The experiment iteration ID + Id string `json:"id"` + Status string `json:"status"` + StartedAt int64 `json:"startedAt"` + EndedAt *int64 `json:"endedAt,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewFlagEventExperimentIteration instantiates a new FlagEventExperimentIteration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventExperimentIteration(id string, status string, startedAt int64) *FlagEventExperimentIteration { + this := FlagEventExperimentIteration{} + this.Id = id + this.Status = status + this.StartedAt = startedAt + return &this +} + +// NewFlagEventExperimentIterationWithDefaults instantiates a new FlagEventExperimentIteration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventExperimentIterationWithDefaults() *FlagEventExperimentIteration { + this := FlagEventExperimentIteration{} + return &this +} + +// GetId returns the Id field value +func (o *FlagEventExperimentIteration) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentIteration) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagEventExperimentIteration) SetId(v string) { + o.Id = v +} + +// GetStatus returns the Status field value +func (o *FlagEventExperimentIteration) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentIteration) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *FlagEventExperimentIteration) SetStatus(v string) { + o.Status = v +} + +// GetStartedAt returns the StartedAt field value +func (o *FlagEventExperimentIteration) GetStartedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.StartedAt +} + +// GetStartedAtOk returns a tuple with the StartedAt field value +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentIteration) GetStartedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.StartedAt, true +} + +// SetStartedAt sets field value +func (o *FlagEventExperimentIteration) SetStartedAt(v int64) { + o.StartedAt = v +} + +// GetEndedAt returns the EndedAt field value if set, zero value otherwise. +func (o *FlagEventExperimentIteration) GetEndedAt() int64 { + if o == nil || o.EndedAt == nil { + var ret int64 + return ret + } + return *o.EndedAt +} + +// GetEndedAtOk returns a tuple with the EndedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentIteration) GetEndedAtOk() (*int64, bool) { + if o == nil || o.EndedAt == nil { + return nil, false + } + return o.EndedAt, true +} + +// HasEndedAt returns a boolean if a field has been set. +func (o *FlagEventExperimentIteration) HasEndedAt() bool { + if o != nil && o.EndedAt != nil { + return true + } + + return false +} + +// SetEndedAt gets a reference to the given int64 and assigns it to the EndedAt field. +func (o *FlagEventExperimentIteration) SetEndedAt(v int64) { + o.EndedAt = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FlagEventExperimentIteration) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventExperimentIteration) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FlagEventExperimentIteration) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FlagEventExperimentIteration) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o FlagEventExperimentIteration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["startedAt"] = o.StartedAt + } + if o.EndedAt != nil { + toSerialize["endedAt"] = o.EndedAt + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventExperimentIteration struct { + value *FlagEventExperimentIteration + isSet bool +} + +func (v NullableFlagEventExperimentIteration) Get() *FlagEventExperimentIteration { + return v.value +} + +func (v *NullableFlagEventExperimentIteration) Set(val *FlagEventExperimentIteration) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventExperimentIteration) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventExperimentIteration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventExperimentIteration(val *FlagEventExperimentIteration) *NullableFlagEventExperimentIteration { + return &NullableFlagEventExperimentIteration{value: val, isSet: true} +} + +func (v NullableFlagEventExperimentIteration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventExperimentIteration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_impact_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_impact_rep.go new file mode 100644 index 00000000..e15933a2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_impact_rep.go @@ -0,0 +1,226 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventImpactRep struct for FlagEventImpactRep +type FlagEventImpactRep struct { + // The size of the flag event impact. Sizes are defined as: none (0%), small (0-20%), medium (20-80%), large (>80%) + Size *string `json:"size,omitempty"` + // The percentage of the flag event impact + Percentage *float32 `json:"percentage,omitempty"` + Reason *string `json:"reason,omitempty"` + EvaluationsSummary *EvaluationsSummary `json:"evaluationsSummary,omitempty"` +} + +// NewFlagEventImpactRep instantiates a new FlagEventImpactRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventImpactRep() *FlagEventImpactRep { + this := FlagEventImpactRep{} + return &this +} + +// NewFlagEventImpactRepWithDefaults instantiates a new FlagEventImpactRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventImpactRepWithDefaults() *FlagEventImpactRep { + this := FlagEventImpactRep{} + return &this +} + +// GetSize returns the Size field value if set, zero value otherwise. +func (o *FlagEventImpactRep) GetSize() string { + if o == nil || o.Size == nil { + var ret string + return ret + } + return *o.Size +} + +// GetSizeOk returns a tuple with the Size field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventImpactRep) GetSizeOk() (*string, bool) { + if o == nil || o.Size == nil { + return nil, false + } + return o.Size, true +} + +// HasSize returns a boolean if a field has been set. +func (o *FlagEventImpactRep) HasSize() bool { + if o != nil && o.Size != nil { + return true + } + + return false +} + +// SetSize gets a reference to the given string and assigns it to the Size field. +func (o *FlagEventImpactRep) SetSize(v string) { + o.Size = &v +} + +// GetPercentage returns the Percentage field value if set, zero value otherwise. +func (o *FlagEventImpactRep) GetPercentage() float32 { + if o == nil || o.Percentage == nil { + var ret float32 + return ret + } + return *o.Percentage +} + +// GetPercentageOk returns a tuple with the Percentage field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventImpactRep) GetPercentageOk() (*float32, bool) { + if o == nil || o.Percentage == nil { + return nil, false + } + return o.Percentage, true +} + +// HasPercentage returns a boolean if a field has been set. +func (o *FlagEventImpactRep) HasPercentage() bool { + if o != nil && o.Percentage != nil { + return true + } + + return false +} + +// SetPercentage gets a reference to the given float32 and assigns it to the Percentage field. +func (o *FlagEventImpactRep) SetPercentage(v float32) { + o.Percentage = &v +} + +// GetReason returns the Reason field value if set, zero value otherwise. +func (o *FlagEventImpactRep) GetReason() string { + if o == nil || o.Reason == nil { + var ret string + return ret + } + return *o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventImpactRep) GetReasonOk() (*string, bool) { + if o == nil || o.Reason == nil { + return nil, false + } + return o.Reason, true +} + +// HasReason returns a boolean if a field has been set. +func (o *FlagEventImpactRep) HasReason() bool { + if o != nil && o.Reason != nil { + return true + } + + return false +} + +// SetReason gets a reference to the given string and assigns it to the Reason field. +func (o *FlagEventImpactRep) SetReason(v string) { + o.Reason = &v +} + +// GetEvaluationsSummary returns the EvaluationsSummary field value if set, zero value otherwise. +func (o *FlagEventImpactRep) GetEvaluationsSummary() EvaluationsSummary { + if o == nil || o.EvaluationsSummary == nil { + var ret EvaluationsSummary + return ret + } + return *o.EvaluationsSummary +} + +// GetEvaluationsSummaryOk returns a tuple with the EvaluationsSummary field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventImpactRep) GetEvaluationsSummaryOk() (*EvaluationsSummary, bool) { + if o == nil || o.EvaluationsSummary == nil { + return nil, false + } + return o.EvaluationsSummary, true +} + +// HasEvaluationsSummary returns a boolean if a field has been set. +func (o *FlagEventImpactRep) HasEvaluationsSummary() bool { + if o != nil && o.EvaluationsSummary != nil { + return true + } + + return false +} + +// SetEvaluationsSummary gets a reference to the given EvaluationsSummary and assigns it to the EvaluationsSummary field. +func (o *FlagEventImpactRep) SetEvaluationsSummary(v EvaluationsSummary) { + o.EvaluationsSummary = &v +} + +func (o FlagEventImpactRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Size != nil { + toSerialize["size"] = o.Size + } + if o.Percentage != nil { + toSerialize["percentage"] = o.Percentage + } + if o.Reason != nil { + toSerialize["reason"] = o.Reason + } + if o.EvaluationsSummary != nil { + toSerialize["evaluationsSummary"] = o.EvaluationsSummary + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventImpactRep struct { + value *FlagEventImpactRep + isSet bool +} + +func (v NullableFlagEventImpactRep) Get() *FlagEventImpactRep { + return v.value +} + +func (v *NullableFlagEventImpactRep) Set(val *FlagEventImpactRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventImpactRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventImpactRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventImpactRep(val *FlagEventImpactRep) *NullableFlagEventImpactRep { + return &NullableFlagEventImpactRep{value: val, isSet: true} +} + +func (v NullableFlagEventImpactRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventImpactRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_member_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_member_rep.go new file mode 100644 index 00000000..cd9d0293 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_member_rep.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventMemberRep struct for FlagEventMemberRep +type FlagEventMemberRep struct { + // The member ID + Id string `json:"id"` + // The member email + Email string `json:"email"` + // The member first name + FirstName string `json:"firstName"` + // The member last name + LastName string `json:"lastName"` +} + +// NewFlagEventMemberRep instantiates a new FlagEventMemberRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventMemberRep(id string, email string, firstName string, lastName string) *FlagEventMemberRep { + this := FlagEventMemberRep{} + this.Id = id + this.Email = email + this.FirstName = firstName + this.LastName = lastName + return &this +} + +// NewFlagEventMemberRepWithDefaults instantiates a new FlagEventMemberRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventMemberRepWithDefaults() *FlagEventMemberRep { + this := FlagEventMemberRep{} + return &this +} + +// GetId returns the Id field value +func (o *FlagEventMemberRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagEventMemberRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagEventMemberRep) SetId(v string) { + o.Id = v +} + +// GetEmail returns the Email field value +func (o *FlagEventMemberRep) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *FlagEventMemberRep) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *FlagEventMemberRep) SetEmail(v string) { + o.Email = v +} + +// GetFirstName returns the FirstName field value +func (o *FlagEventMemberRep) GetFirstName() string { + if o == nil { + var ret string + return ret + } + + return o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value +// and a boolean to check if the value has been set. +func (o *FlagEventMemberRep) GetFirstNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FirstName, true +} + +// SetFirstName sets field value +func (o *FlagEventMemberRep) SetFirstName(v string) { + o.FirstName = v +} + +// GetLastName returns the LastName field value +func (o *FlagEventMemberRep) GetLastName() string { + if o == nil { + var ret string + return ret + } + + return o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value +// and a boolean to check if the value has been set. +func (o *FlagEventMemberRep) GetLastNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.LastName, true +} + +// SetLastName sets field value +func (o *FlagEventMemberRep) SetLastName(v string) { + o.LastName = v +} + +func (o FlagEventMemberRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["email"] = o.Email + } + if true { + toSerialize["firstName"] = o.FirstName + } + if true { + toSerialize["lastName"] = o.LastName + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventMemberRep struct { + value *FlagEventMemberRep + isSet bool +} + +func (v NullableFlagEventMemberRep) Get() *FlagEventMemberRep { + return v.value +} + +func (v *NullableFlagEventMemberRep) Set(val *FlagEventMemberRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventMemberRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventMemberRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventMemberRep(val *FlagEventMemberRep) *NullableFlagEventMemberRep { + return &NullableFlagEventMemberRep{value: val, isSet: true} +} + +func (v NullableFlagEventMemberRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventMemberRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_rep.go new file mode 100644 index 00000000..fc192008 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_event_rep.go @@ -0,0 +1,537 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagEventRep struct for FlagEventRep +type FlagEventRep struct { + // The flag event ID + Id string `json:"id"` + // The project ID + ProjectId string `json:"projectId"` + // The project key + ProjectKey string `json:"projectKey"` + // The environment ID + EnvironmentId *string `json:"environmentId,omitempty"` + // The environment key + EnvironmentKey *string `json:"environmentKey,omitempty"` + // The flag key + FlagKey string `json:"flagKey"` + EventType string `json:"eventType"` + EventTime int64 `json:"eventTime"` + // The event description + Description string `json:"description"` + // The audit log entry ID + AuditLogEntryId *string `json:"auditLogEntryId,omitempty"` + Member *FlagEventMemberRep `json:"member,omitempty"` + // The resource actions + Actions []string `json:"actions,omitempty"` + Impact FlagEventImpactRep `json:"impact"` + Experiments *FlagEventExperimentCollection `json:"experiments,omitempty"` +} + +// NewFlagEventRep instantiates a new FlagEventRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagEventRep(id string, projectId string, projectKey string, flagKey string, eventType string, eventTime int64, description string, impact FlagEventImpactRep) *FlagEventRep { + this := FlagEventRep{} + this.Id = id + this.ProjectId = projectId + this.ProjectKey = projectKey + this.FlagKey = flagKey + this.EventType = eventType + this.EventTime = eventTime + this.Description = description + this.Impact = impact + return &this +} + +// NewFlagEventRepWithDefaults instantiates a new FlagEventRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagEventRepWithDefaults() *FlagEventRep { + this := FlagEventRep{} + return &this +} + +// GetId returns the Id field value +func (o *FlagEventRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagEventRep) SetId(v string) { + o.Id = v +} + +// GetProjectId returns the ProjectId field value +func (o *FlagEventRep) GetProjectId() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectId +} + +// GetProjectIdOk returns a tuple with the ProjectId field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetProjectIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectId, true +} + +// SetProjectId sets field value +func (o *FlagEventRep) SetProjectId(v string) { + o.ProjectId = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *FlagEventRep) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *FlagEventRep) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentId returns the EnvironmentId field value if set, zero value otherwise. +func (o *FlagEventRep) GetEnvironmentId() string { + if o == nil || o.EnvironmentId == nil { + var ret string + return ret + } + return *o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetEnvironmentIdOk() (*string, bool) { + if o == nil || o.EnvironmentId == nil { + return nil, false + } + return o.EnvironmentId, true +} + +// HasEnvironmentId returns a boolean if a field has been set. +func (o *FlagEventRep) HasEnvironmentId() bool { + if o != nil && o.EnvironmentId != nil { + return true + } + + return false +} + +// SetEnvironmentId gets a reference to the given string and assigns it to the EnvironmentId field. +func (o *FlagEventRep) SetEnvironmentId(v string) { + o.EnvironmentId = &v +} + +// GetEnvironmentKey returns the EnvironmentKey field value if set, zero value otherwise. +func (o *FlagEventRep) GetEnvironmentKey() string { + if o == nil || o.EnvironmentKey == nil { + var ret string + return ret + } + return *o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetEnvironmentKeyOk() (*string, bool) { + if o == nil || o.EnvironmentKey == nil { + return nil, false + } + return o.EnvironmentKey, true +} + +// HasEnvironmentKey returns a boolean if a field has been set. +func (o *FlagEventRep) HasEnvironmentKey() bool { + if o != nil && o.EnvironmentKey != nil { + return true + } + + return false +} + +// SetEnvironmentKey gets a reference to the given string and assigns it to the EnvironmentKey field. +func (o *FlagEventRep) SetEnvironmentKey(v string) { + o.EnvironmentKey = &v +} + +// GetFlagKey returns the FlagKey field value +func (o *FlagEventRep) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *FlagEventRep) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetEventType returns the EventType field value +func (o *FlagEventRep) GetEventType() string { + if o == nil { + var ret string + return ret + } + + return o.EventType +} + +// GetEventTypeOk returns a tuple with the EventType field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetEventTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EventType, true +} + +// SetEventType sets field value +func (o *FlagEventRep) SetEventType(v string) { + o.EventType = v +} + +// GetEventTime returns the EventTime field value +func (o *FlagEventRep) GetEventTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.EventTime +} + +// GetEventTimeOk returns a tuple with the EventTime field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetEventTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.EventTime, true +} + +// SetEventTime sets field value +func (o *FlagEventRep) SetEventTime(v int64) { + o.EventTime = v +} + +// GetDescription returns the Description field value +func (o *FlagEventRep) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *FlagEventRep) SetDescription(v string) { + o.Description = v +} + +// GetAuditLogEntryId returns the AuditLogEntryId field value if set, zero value otherwise. +func (o *FlagEventRep) GetAuditLogEntryId() string { + if o == nil || o.AuditLogEntryId == nil { + var ret string + return ret + } + return *o.AuditLogEntryId +} + +// GetAuditLogEntryIdOk returns a tuple with the AuditLogEntryId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetAuditLogEntryIdOk() (*string, bool) { + if o == nil || o.AuditLogEntryId == nil { + return nil, false + } + return o.AuditLogEntryId, true +} + +// HasAuditLogEntryId returns a boolean if a field has been set. +func (o *FlagEventRep) HasAuditLogEntryId() bool { + if o != nil && o.AuditLogEntryId != nil { + return true + } + + return false +} + +// SetAuditLogEntryId gets a reference to the given string and assigns it to the AuditLogEntryId field. +func (o *FlagEventRep) SetAuditLogEntryId(v string) { + o.AuditLogEntryId = &v +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *FlagEventRep) GetMember() FlagEventMemberRep { + if o == nil || o.Member == nil { + var ret FlagEventMemberRep + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetMemberOk() (*FlagEventMemberRep, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *FlagEventRep) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given FlagEventMemberRep and assigns it to the Member field. +func (o *FlagEventRep) SetMember(v FlagEventMemberRep) { + o.Member = &v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *FlagEventRep) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *FlagEventRep) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *FlagEventRep) SetActions(v []string) { + o.Actions = v +} + +// GetImpact returns the Impact field value +func (o *FlagEventRep) GetImpact() FlagEventImpactRep { + if o == nil { + var ret FlagEventImpactRep + return ret + } + + return o.Impact +} + +// GetImpactOk returns a tuple with the Impact field value +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetImpactOk() (*FlagEventImpactRep, bool) { + if o == nil { + return nil, false + } + return &o.Impact, true +} + +// SetImpact sets field value +func (o *FlagEventRep) SetImpact(v FlagEventImpactRep) { + o.Impact = v +} + +// GetExperiments returns the Experiments field value if set, zero value otherwise. +func (o *FlagEventRep) GetExperiments() FlagEventExperimentCollection { + if o == nil || o.Experiments == nil { + var ret FlagEventExperimentCollection + return ret + } + return *o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagEventRep) GetExperimentsOk() (*FlagEventExperimentCollection, bool) { + if o == nil || o.Experiments == nil { + return nil, false + } + return o.Experiments, true +} + +// HasExperiments returns a boolean if a field has been set. +func (o *FlagEventRep) HasExperiments() bool { + if o != nil && o.Experiments != nil { + return true + } + + return false +} + +// SetExperiments gets a reference to the given FlagEventExperimentCollection and assigns it to the Experiments field. +func (o *FlagEventRep) SetExperiments(v FlagEventExperimentCollection) { + o.Experiments = &v +} + +func (o FlagEventRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["projectId"] = o.ProjectId + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if o.EnvironmentId != nil { + toSerialize["environmentId"] = o.EnvironmentId + } + if o.EnvironmentKey != nil { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["eventType"] = o.EventType + } + if true { + toSerialize["eventTime"] = o.EventTime + } + if true { + toSerialize["description"] = o.Description + } + if o.AuditLogEntryId != nil { + toSerialize["auditLogEntryId"] = o.AuditLogEntryId + } + if o.Member != nil { + toSerialize["member"] = o.Member + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if true { + toSerialize["impact"] = o.Impact + } + if o.Experiments != nil { + toSerialize["experiments"] = o.Experiments + } + return json.Marshal(toSerialize) +} + +type NullableFlagEventRep struct { + value *FlagEventRep + isSet bool +} + +func (v NullableFlagEventRep) Get() *FlagEventRep { + return v.value +} + +func (v *NullableFlagEventRep) Set(val *FlagEventRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagEventRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagEventRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagEventRep(val *FlagEventRep) *NullableFlagEventRep { + return &NullableFlagEventRep{value: val, isSet: true} +} + +func (v NullableFlagEventRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagEventRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_by_proj_env_get_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_by_proj_env_get_rep.go new file mode 100644 index 00000000..fdb931ad --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_by_proj_env_get_rep.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagFollowersByProjEnvGetRep struct for FlagFollowersByProjEnvGetRep +type FlagFollowersByProjEnvGetRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of flags and their followers + Items []FollowersPerFlag `json:"items,omitempty"` +} + +// NewFlagFollowersByProjEnvGetRep instantiates a new FlagFollowersByProjEnvGetRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagFollowersByProjEnvGetRep(links map[string]Link) *FlagFollowersByProjEnvGetRep { + this := FlagFollowersByProjEnvGetRep{} + this.Links = links + return &this +} + +// NewFlagFollowersByProjEnvGetRepWithDefaults instantiates a new FlagFollowersByProjEnvGetRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagFollowersByProjEnvGetRepWithDefaults() *FlagFollowersByProjEnvGetRep { + this := FlagFollowersByProjEnvGetRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagFollowersByProjEnvGetRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagFollowersByProjEnvGetRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagFollowersByProjEnvGetRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *FlagFollowersByProjEnvGetRep) GetItems() []FollowersPerFlag { + if o == nil || o.Items == nil { + var ret []FollowersPerFlag + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagFollowersByProjEnvGetRep) GetItemsOk() ([]FollowersPerFlag, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *FlagFollowersByProjEnvGetRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []FollowersPerFlag and assigns it to the Items field. +func (o *FlagFollowersByProjEnvGetRep) SetItems(v []FollowersPerFlag) { + o.Items = v +} + +func (o FlagFollowersByProjEnvGetRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFlagFollowersByProjEnvGetRep struct { + value *FlagFollowersByProjEnvGetRep + isSet bool +} + +func (v NullableFlagFollowersByProjEnvGetRep) Get() *FlagFollowersByProjEnvGetRep { + return v.value +} + +func (v *NullableFlagFollowersByProjEnvGetRep) Set(val *FlagFollowersByProjEnvGetRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagFollowersByProjEnvGetRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagFollowersByProjEnvGetRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagFollowersByProjEnvGetRep(val *FlagFollowersByProjEnvGetRep) *NullableFlagFollowersByProjEnvGetRep { + return &NullableFlagFollowersByProjEnvGetRep{value: val, isSet: true} +} + +func (v NullableFlagFollowersByProjEnvGetRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagFollowersByProjEnvGetRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_get_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_get_rep.go new file mode 100644 index 00000000..4f01125c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_followers_get_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagFollowersGetRep struct for FlagFollowersGetRep +type FlagFollowersGetRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of members who are following this flag + Items []FollowFlagMember `json:"items"` +} + +// NewFlagFollowersGetRep instantiates a new FlagFollowersGetRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagFollowersGetRep(links map[string]Link, items []FollowFlagMember) *FlagFollowersGetRep { + this := FlagFollowersGetRep{} + this.Links = links + this.Items = items + return &this +} + +// NewFlagFollowersGetRepWithDefaults instantiates a new FlagFollowersGetRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagFollowersGetRepWithDefaults() *FlagFollowersGetRep { + this := FlagFollowersGetRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagFollowersGetRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagFollowersGetRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagFollowersGetRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *FlagFollowersGetRep) GetItems() []FollowFlagMember { + if o == nil { + var ret []FollowFlagMember + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagFollowersGetRep) GetItemsOk() ([]FollowFlagMember, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagFollowersGetRep) SetItems(v []FollowFlagMember) { + o.Items = v +} + +func (o FlagFollowersGetRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFlagFollowersGetRep struct { + value *FlagFollowersGetRep + isSet bool +} + +func (v NullableFlagFollowersGetRep) Get() *FlagFollowersGetRep { + return v.value +} + +func (v *NullableFlagFollowersGetRep) Set(val *FlagFollowersGetRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagFollowersGetRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagFollowersGetRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagFollowersGetRep(val *FlagFollowersGetRep) *NullableFlagFollowersGetRep { + return &NullableFlagFollowersGetRep{value: val, isSet: true} +} + +func (v NullableFlagFollowersGetRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagFollowersGetRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_configuration_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_configuration_post.go new file mode 100644 index 00000000..cfb9828f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_configuration_post.go @@ -0,0 +1,183 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportConfigurationPost struct for FlagImportConfigurationPost +type FlagImportConfigurationPost struct { + Config map[string]interface{} `json:"config"` + // Tags to associate with the configuration + Tags []string `json:"tags,omitempty"` + // Name to identify the configuration + Name *string `json:"name,omitempty"` +} + +// NewFlagImportConfigurationPost instantiates a new FlagImportConfigurationPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportConfigurationPost(config map[string]interface{}) *FlagImportConfigurationPost { + this := FlagImportConfigurationPost{} + this.Config = config + return &this +} + +// NewFlagImportConfigurationPostWithDefaults instantiates a new FlagImportConfigurationPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportConfigurationPostWithDefaults() *FlagImportConfigurationPost { + this := FlagImportConfigurationPost{} + return &this +} + +// GetConfig returns the Config field value +func (o *FlagImportConfigurationPost) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *FlagImportConfigurationPost) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *FlagImportConfigurationPost) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *FlagImportConfigurationPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportConfigurationPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *FlagImportConfigurationPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *FlagImportConfigurationPost) SetTags(v []string) { + o.Tags = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *FlagImportConfigurationPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportConfigurationPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *FlagImportConfigurationPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *FlagImportConfigurationPost) SetName(v string) { + o.Name = &v +} + +func (o FlagImportConfigurationPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["config"] = o.Config + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportConfigurationPost struct { + value *FlagImportConfigurationPost + isSet bool +} + +func (v NullableFlagImportConfigurationPost) Get() *FlagImportConfigurationPost { + return v.value +} + +func (v *NullableFlagImportConfigurationPost) Set(val *FlagImportConfigurationPost) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportConfigurationPost) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportConfigurationPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportConfigurationPost(val *FlagImportConfigurationPost) *NullableFlagImportConfigurationPost { + return &NullableFlagImportConfigurationPost{value: val, isSet: true} +} + +func (v NullableFlagImportConfigurationPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportConfigurationPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration.go new file mode 100644 index 00000000..ed2a5bce --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration.go @@ -0,0 +1,383 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportIntegration struct for FlagImportIntegration +type FlagImportIntegration struct { + Links FlagImportIntegrationLinks `json:"_links"` + // The integration ID + Id string `json:"_id"` + // The integration key + IntegrationKey string `json:"integrationKey"` + // The project key + ProjectKey string `json:"projectKey"` + Config map[string]interface{} `json:"config"` + // List of tags for this configuration + Tags []string `json:"tags"` + // Name of the configuration + Name string `json:"name"` + // Version of the current configuration + Version int32 `json:"version"` + Access *Access `json:"_access,omitempty"` + Status FlagImportStatus `json:"_status"` +} + +// NewFlagImportIntegration instantiates a new FlagImportIntegration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportIntegration(links FlagImportIntegrationLinks, id string, integrationKey string, projectKey string, config map[string]interface{}, tags []string, name string, version int32, status FlagImportStatus) *FlagImportIntegration { + this := FlagImportIntegration{} + this.Links = links + this.Id = id + this.IntegrationKey = integrationKey + this.ProjectKey = projectKey + this.Config = config + this.Tags = tags + this.Name = name + this.Version = version + this.Status = status + return &this +} + +// NewFlagImportIntegrationWithDefaults instantiates a new FlagImportIntegration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportIntegrationWithDefaults() *FlagImportIntegration { + this := FlagImportIntegration{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagImportIntegration) GetLinks() FlagImportIntegrationLinks { + if o == nil { + var ret FlagImportIntegrationLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetLinksOk() (*FlagImportIntegrationLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagImportIntegration) SetLinks(v FlagImportIntegrationLinks) { + o.Links = v +} + +// GetId returns the Id field value +func (o *FlagImportIntegration) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagImportIntegration) SetId(v string) { + o.Id = v +} + +// GetIntegrationKey returns the IntegrationKey field value +func (o *FlagImportIntegration) GetIntegrationKey() string { + if o == nil { + var ret string + return ret + } + + return o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetIntegrationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.IntegrationKey, true +} + +// SetIntegrationKey sets field value +func (o *FlagImportIntegration) SetIntegrationKey(v string) { + o.IntegrationKey = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *FlagImportIntegration) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *FlagImportIntegration) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetConfig returns the Config field value +func (o *FlagImportIntegration) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *FlagImportIntegration) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetTags returns the Tags field value +func (o *FlagImportIntegration) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *FlagImportIntegration) SetTags(v []string) { + o.Tags = v +} + +// GetName returns the Name field value +func (o *FlagImportIntegration) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FlagImportIntegration) SetName(v string) { + o.Name = v +} + +// GetVersion returns the Version field value +func (o *FlagImportIntegration) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *FlagImportIntegration) SetVersion(v int32) { + o.Version = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *FlagImportIntegration) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *FlagImportIntegration) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *FlagImportIntegration) SetAccess(v Access) { + o.Access = &v +} + +// GetStatus returns the Status field value +func (o *FlagImportIntegration) GetStatus() FlagImportStatus { + if o == nil { + var ret FlagImportStatus + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegration) GetStatusOk() (*FlagImportStatus, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *FlagImportIntegration) SetStatus(v FlagImportStatus) { + o.Status = v +} + +func (o FlagImportIntegration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["integrationKey"] = o.IntegrationKey + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["config"] = o.Config + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["version"] = o.Version + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["_status"] = o.Status + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportIntegration struct { + value *FlagImportIntegration + isSet bool +} + +func (v NullableFlagImportIntegration) Get() *FlagImportIntegration { + return v.value +} + +func (v *NullableFlagImportIntegration) Set(val *FlagImportIntegration) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportIntegration) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportIntegration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportIntegration(val *FlagImportIntegration) *NullableFlagImportIntegration { + return &NullableFlagImportIntegration{value: val, isSet: true} +} + +func (v NullableFlagImportIntegration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportIntegration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection.go new file mode 100644 index 00000000..1d37f206 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportIntegrationCollection struct for FlagImportIntegrationCollection +type FlagImportIntegrationCollection struct { + Links FlagImportIntegrationCollectionLinks `json:"_links"` + // An array of flag import configurations + Items []FlagImportIntegration `json:"items"` +} + +// NewFlagImportIntegrationCollection instantiates a new FlagImportIntegrationCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportIntegrationCollection(links FlagImportIntegrationCollectionLinks, items []FlagImportIntegration) *FlagImportIntegrationCollection { + this := FlagImportIntegrationCollection{} + this.Links = links + this.Items = items + return &this +} + +// NewFlagImportIntegrationCollectionWithDefaults instantiates a new FlagImportIntegrationCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportIntegrationCollectionWithDefaults() *FlagImportIntegrationCollection { + this := FlagImportIntegrationCollection{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagImportIntegrationCollection) GetLinks() FlagImportIntegrationCollectionLinks { + if o == nil { + var ret FlagImportIntegrationCollectionLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationCollection) GetLinksOk() (*FlagImportIntegrationCollectionLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagImportIntegrationCollection) SetLinks(v FlagImportIntegrationCollectionLinks) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *FlagImportIntegrationCollection) GetItems() []FlagImportIntegration { + if o == nil { + var ret []FlagImportIntegration + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationCollection) GetItemsOk() ([]FlagImportIntegration, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagImportIntegrationCollection) SetItems(v []FlagImportIntegration) { + o.Items = v +} + +func (o FlagImportIntegrationCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportIntegrationCollection struct { + value *FlagImportIntegrationCollection + isSet bool +} + +func (v NullableFlagImportIntegrationCollection) Get() *FlagImportIntegrationCollection { + return v.value +} + +func (v *NullableFlagImportIntegrationCollection) Set(val *FlagImportIntegrationCollection) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportIntegrationCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportIntegrationCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportIntegrationCollection(val *FlagImportIntegrationCollection) *NullableFlagImportIntegrationCollection { + return &NullableFlagImportIntegrationCollection{value: val, isSet: true} +} + +func (v NullableFlagImportIntegrationCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportIntegrationCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection_links.go new file mode 100644 index 00000000..bab393bf --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_collection_links.go @@ -0,0 +1,145 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportIntegrationCollectionLinks struct for FlagImportIntegrationCollectionLinks +type FlagImportIntegrationCollectionLinks struct { + Self Link `json:"self"` + Parent *Link `json:"parent,omitempty"` +} + +// NewFlagImportIntegrationCollectionLinks instantiates a new FlagImportIntegrationCollectionLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportIntegrationCollectionLinks(self Link) *FlagImportIntegrationCollectionLinks { + this := FlagImportIntegrationCollectionLinks{} + this.Self = self + return &this +} + +// NewFlagImportIntegrationCollectionLinksWithDefaults instantiates a new FlagImportIntegrationCollectionLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportIntegrationCollectionLinksWithDefaults() *FlagImportIntegrationCollectionLinks { + this := FlagImportIntegrationCollectionLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *FlagImportIntegrationCollectionLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationCollectionLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *FlagImportIntegrationCollectionLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value if set, zero value otherwise. +func (o *FlagImportIntegrationCollectionLinks) GetParent() Link { + if o == nil || o.Parent == nil { + var ret Link + return ret + } + return *o.Parent +} + +// GetParentOk returns a tuple with the Parent field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationCollectionLinks) GetParentOk() (*Link, bool) { + if o == nil || o.Parent == nil { + return nil, false + } + return o.Parent, true +} + +// HasParent returns a boolean if a field has been set. +func (o *FlagImportIntegrationCollectionLinks) HasParent() bool { + if o != nil && o.Parent != nil { + return true + } + + return false +} + +// SetParent gets a reference to the given Link and assigns it to the Parent field. +func (o *FlagImportIntegrationCollectionLinks) SetParent(v Link) { + o.Parent = &v +} + +func (o FlagImportIntegrationCollectionLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if o.Parent != nil { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportIntegrationCollectionLinks struct { + value *FlagImportIntegrationCollectionLinks + isSet bool +} + +func (v NullableFlagImportIntegrationCollectionLinks) Get() *FlagImportIntegrationCollectionLinks { + return v.value +} + +func (v *NullableFlagImportIntegrationCollectionLinks) Set(val *FlagImportIntegrationCollectionLinks) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportIntegrationCollectionLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportIntegrationCollectionLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportIntegrationCollectionLinks(val *FlagImportIntegrationCollectionLinks) *NullableFlagImportIntegrationCollectionLinks { + return &NullableFlagImportIntegrationCollectionLinks{value: val, isSet: true} +} + +func (v NullableFlagImportIntegrationCollectionLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportIntegrationCollectionLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_links.go new file mode 100644 index 00000000..64c36ffa --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_integration_links.go @@ -0,0 +1,167 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportIntegrationLinks struct for FlagImportIntegrationLinks +type FlagImportIntegrationLinks struct { + Self Link `json:"self"` + Parent Link `json:"parent"` + Project Link `json:"project"` +} + +// NewFlagImportIntegrationLinks instantiates a new FlagImportIntegrationLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportIntegrationLinks(self Link, parent Link, project Link) *FlagImportIntegrationLinks { + this := FlagImportIntegrationLinks{} + this.Self = self + this.Parent = parent + this.Project = project + return &this +} + +// NewFlagImportIntegrationLinksWithDefaults instantiates a new FlagImportIntegrationLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportIntegrationLinksWithDefaults() *FlagImportIntegrationLinks { + this := FlagImportIntegrationLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *FlagImportIntegrationLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *FlagImportIntegrationLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value +func (o *FlagImportIntegrationLinks) GetParent() Link { + if o == nil { + var ret Link + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationLinks) GetParentOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *FlagImportIntegrationLinks) SetParent(v Link) { + o.Parent = v +} + +// GetProject returns the Project field value +func (o *FlagImportIntegrationLinks) GetProject() Link { + if o == nil { + var ret Link + return ret + } + + return o.Project +} + +// GetProjectOk returns a tuple with the Project field value +// and a boolean to check if the value has been set. +func (o *FlagImportIntegrationLinks) GetProjectOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Project, true +} + +// SetProject sets field value +func (o *FlagImportIntegrationLinks) SetProject(v Link) { + o.Project = v +} + +func (o FlagImportIntegrationLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if true { + toSerialize["parent"] = o.Parent + } + if true { + toSerialize["project"] = o.Project + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportIntegrationLinks struct { + value *FlagImportIntegrationLinks + isSet bool +} + +func (v NullableFlagImportIntegrationLinks) Get() *FlagImportIntegrationLinks { + return v.value +} + +func (v *NullableFlagImportIntegrationLinks) Set(val *FlagImportIntegrationLinks) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportIntegrationLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportIntegrationLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportIntegrationLinks(val *FlagImportIntegrationLinks) *NullableFlagImportIntegrationLinks { + return &NullableFlagImportIntegrationLinks{value: val, isSet: true} +} + +func (v NullableFlagImportIntegrationLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportIntegrationLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_status.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_status.go new file mode 100644 index 00000000..c481b4ec --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_import_status.go @@ -0,0 +1,225 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagImportStatus struct for FlagImportStatus +type FlagImportStatus struct { + // The current status of the import integrations related import job + Status *string `json:"status,omitempty"` + LastImport *int64 `json:"lastImport,omitempty"` + LastError *int64 `json:"lastError,omitempty"` + Errors []StatusResponse `json:"errors,omitempty"` +} + +// NewFlagImportStatus instantiates a new FlagImportStatus object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagImportStatus() *FlagImportStatus { + this := FlagImportStatus{} + return &this +} + +// NewFlagImportStatusWithDefaults instantiates a new FlagImportStatus object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagImportStatusWithDefaults() *FlagImportStatus { + this := FlagImportStatus{} + return &this +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *FlagImportStatus) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportStatus) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *FlagImportStatus) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *FlagImportStatus) SetStatus(v string) { + o.Status = &v +} + +// GetLastImport returns the LastImport field value if set, zero value otherwise. +func (o *FlagImportStatus) GetLastImport() int64 { + if o == nil || o.LastImport == nil { + var ret int64 + return ret + } + return *o.LastImport +} + +// GetLastImportOk returns a tuple with the LastImport field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportStatus) GetLastImportOk() (*int64, bool) { + if o == nil || o.LastImport == nil { + return nil, false + } + return o.LastImport, true +} + +// HasLastImport returns a boolean if a field has been set. +func (o *FlagImportStatus) HasLastImport() bool { + if o != nil && o.LastImport != nil { + return true + } + + return false +} + +// SetLastImport gets a reference to the given int64 and assigns it to the LastImport field. +func (o *FlagImportStatus) SetLastImport(v int64) { + o.LastImport = &v +} + +// GetLastError returns the LastError field value if set, zero value otherwise. +func (o *FlagImportStatus) GetLastError() int64 { + if o == nil || o.LastError == nil { + var ret int64 + return ret + } + return *o.LastError +} + +// GetLastErrorOk returns a tuple with the LastError field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportStatus) GetLastErrorOk() (*int64, bool) { + if o == nil || o.LastError == nil { + return nil, false + } + return o.LastError, true +} + +// HasLastError returns a boolean if a field has been set. +func (o *FlagImportStatus) HasLastError() bool { + if o != nil && o.LastError != nil { + return true + } + + return false +} + +// SetLastError gets a reference to the given int64 and assigns it to the LastError field. +func (o *FlagImportStatus) SetLastError(v int64) { + o.LastError = &v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *FlagImportStatus) GetErrors() []StatusResponse { + if o == nil || o.Errors == nil { + var ret []StatusResponse + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagImportStatus) GetErrorsOk() ([]StatusResponse, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *FlagImportStatus) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []StatusResponse and assigns it to the Errors field. +func (o *FlagImportStatus) SetErrors(v []StatusResponse) { + o.Errors = v +} + +func (o FlagImportStatus) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.LastImport != nil { + toSerialize["lastImport"] = o.LastImport + } + if o.LastError != nil { + toSerialize["lastError"] = o.LastError + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableFlagImportStatus struct { + value *FlagImportStatus + isSet bool +} + +func (v NullableFlagImportStatus) Get() *FlagImportStatus { + return v.value +} + +func (v *NullableFlagImportStatus) Set(val *FlagImportStatus) { + v.value = val + v.isSet = true +} + +func (v NullableFlagImportStatus) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagImportStatus) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagImportStatus(val *FlagImportStatus) *NullableFlagImportStatus { + return &NullableFlagImportStatus{value: val, isSet: true} +} + +func (v NullableFlagImportStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagImportStatus) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_input.go new file mode 100644 index 00000000..b3a7a612 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_input.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagInput struct for FlagInput +type FlagInput struct { + // The ID of the variation or rollout of the flag to use. Use \"fallthrough\" for the default targeting behavior when the flag is on. + RuleId string `json:"ruleId"` + // The flag version + FlagConfigVersion int32 `json:"flagConfigVersion"` + // The ID of the variation to route traffic not part of the experiment analysis to. Defaults to variation ID of baseline treatment, if set. + NotInExperimentVariationId *string `json:"notInExperimentVariationId,omitempty"` +} + +// NewFlagInput instantiates a new FlagInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagInput(ruleId string, flagConfigVersion int32) *FlagInput { + this := FlagInput{} + this.RuleId = ruleId + this.FlagConfigVersion = flagConfigVersion + return &this +} + +// NewFlagInputWithDefaults instantiates a new FlagInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagInputWithDefaults() *FlagInput { + this := FlagInput{} + return &this +} + +// GetRuleId returns the RuleId field value +func (o *FlagInput) GetRuleId() string { + if o == nil { + var ret string + return ret + } + + return o.RuleId +} + +// GetRuleIdOk returns a tuple with the RuleId field value +// and a boolean to check if the value has been set. +func (o *FlagInput) GetRuleIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.RuleId, true +} + +// SetRuleId sets field value +func (o *FlagInput) SetRuleId(v string) { + o.RuleId = v +} + +// GetFlagConfigVersion returns the FlagConfigVersion field value +func (o *FlagInput) GetFlagConfigVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.FlagConfigVersion +} + +// GetFlagConfigVersionOk returns a tuple with the FlagConfigVersion field value +// and a boolean to check if the value has been set. +func (o *FlagInput) GetFlagConfigVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.FlagConfigVersion, true +} + +// SetFlagConfigVersion sets field value +func (o *FlagInput) SetFlagConfigVersion(v int32) { + o.FlagConfigVersion = v +} + +// GetNotInExperimentVariationId returns the NotInExperimentVariationId field value if set, zero value otherwise. +func (o *FlagInput) GetNotInExperimentVariationId() string { + if o == nil || o.NotInExperimentVariationId == nil { + var ret string + return ret + } + return *o.NotInExperimentVariationId +} + +// GetNotInExperimentVariationIdOk returns a tuple with the NotInExperimentVariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagInput) GetNotInExperimentVariationIdOk() (*string, bool) { + if o == nil || o.NotInExperimentVariationId == nil { + return nil, false + } + return o.NotInExperimentVariationId, true +} + +// HasNotInExperimentVariationId returns a boolean if a field has been set. +func (o *FlagInput) HasNotInExperimentVariationId() bool { + if o != nil && o.NotInExperimentVariationId != nil { + return true + } + + return false +} + +// SetNotInExperimentVariationId gets a reference to the given string and assigns it to the NotInExperimentVariationId field. +func (o *FlagInput) SetNotInExperimentVariationId(v string) { + o.NotInExperimentVariationId = &v +} + +func (o FlagInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["ruleId"] = o.RuleId + } + if true { + toSerialize["flagConfigVersion"] = o.FlagConfigVersion + } + if o.NotInExperimentVariationId != nil { + toSerialize["notInExperimentVariationId"] = o.NotInExperimentVariationId + } + return json.Marshal(toSerialize) +} + +type NullableFlagInput struct { + value *FlagInput + isSet bool +} + +func (v NullableFlagInput) Get() *FlagInput { + return v.value +} + +func (v *NullableFlagInput) Set(val *FlagInput) { + v.value = val + v.isSet = true +} + +func (v NullableFlagInput) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagInput(val *FlagInput) *NullableFlagInput { + return &NullableFlagInput{value: val, isSet: true} +} + +func (v NullableFlagInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_collection_rep.go new file mode 100644 index 00000000..26b13ef3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagLinkCollectionRep struct for FlagLinkCollectionRep +type FlagLinkCollectionRep struct { + // An array of flag links + Items []FlagLinkRep `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewFlagLinkCollectionRep instantiates a new FlagLinkCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagLinkCollectionRep(items []FlagLinkRep, links map[string]Link) *FlagLinkCollectionRep { + this := FlagLinkCollectionRep{} + this.Items = items + this.Links = links + return &this +} + +// NewFlagLinkCollectionRepWithDefaults instantiates a new FlagLinkCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagLinkCollectionRepWithDefaults() *FlagLinkCollectionRep { + this := FlagLinkCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *FlagLinkCollectionRep) GetItems() []FlagLinkRep { + if o == nil { + var ret []FlagLinkRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagLinkCollectionRep) GetItemsOk() ([]FlagLinkRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagLinkCollectionRep) SetItems(v []FlagLinkRep) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *FlagLinkCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagLinkCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagLinkCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o FlagLinkCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagLinkCollectionRep struct { + value *FlagLinkCollectionRep + isSet bool +} + +func (v NullableFlagLinkCollectionRep) Get() *FlagLinkCollectionRep { + return v.value +} + +func (v *NullableFlagLinkCollectionRep) Set(val *FlagLinkCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagLinkCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagLinkCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagLinkCollectionRep(val *FlagLinkCollectionRep) *NullableFlagLinkCollectionRep { + return &NullableFlagLinkCollectionRep{value: val, isSet: true} +} + +func (v NullableFlagLinkCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagLinkCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_member.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_member.go new file mode 100644 index 00000000..c2f0adec --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_member.go @@ -0,0 +1,210 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagLinkMember struct for FlagLinkMember +type FlagLinkMember struct { + Links map[string]Link `json:"_links"` + Id string `json:"_id"` + FirstName *string `json:"firstName,omitempty"` + LastName *string `json:"lastName,omitempty"` +} + +// NewFlagLinkMember instantiates a new FlagLinkMember object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagLinkMember(links map[string]Link, id string) *FlagLinkMember { + this := FlagLinkMember{} + this.Links = links + this.Id = id + return &this +} + +// NewFlagLinkMemberWithDefaults instantiates a new FlagLinkMember object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagLinkMemberWithDefaults() *FlagLinkMember { + this := FlagLinkMember{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagLinkMember) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagLinkMember) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagLinkMember) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *FlagLinkMember) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagLinkMember) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagLinkMember) SetId(v string) { + o.Id = v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *FlagLinkMember) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkMember) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *FlagLinkMember) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *FlagLinkMember) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *FlagLinkMember) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkMember) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *FlagLinkMember) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *FlagLinkMember) SetLastName(v string) { + o.LastName = &v +} + +func (o FlagLinkMember) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + return json.Marshal(toSerialize) +} + +type NullableFlagLinkMember struct { + value *FlagLinkMember + isSet bool +} + +func (v NullableFlagLinkMember) Get() *FlagLinkMember { + return v.value +} + +func (v *NullableFlagLinkMember) Set(val *FlagLinkMember) { + v.value = val + v.isSet = true +} + +func (v NullableFlagLinkMember) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagLinkMember) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagLinkMember(val *FlagLinkMember) *NullableFlagLinkMember { + return &NullableFlagLinkMember{value: val, isSet: true} +} + +func (v NullableFlagLinkMember) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagLinkMember) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_post.go new file mode 100644 index 00000000..888f26bb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_post.go @@ -0,0 +1,338 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagLinkPost struct for FlagLinkPost +type FlagLinkPost struct { + // The flag link key + Key *string `json:"key,omitempty"` + // The integration key for an integration whose manifest.json includes the flagLink capability, if this is a flag link for an existing integration. Do not include for URL flag links. + IntegrationKey *string `json:"integrationKey,omitempty"` + Timestamp *int64 `json:"timestamp,omitempty"` + // The URL for the external resource you are linking the flag to + DeepLink *string `json:"deepLink,omitempty"` + // The title of the flag link + Title *string `json:"title,omitempty"` + // The description of the flag link + Description *string `json:"description,omitempty"` + // The metadata required by this integration in order to create a flag link, if this is a flag link for an existing integration. Defined in the integration's manifest.json file under flagLink. + Metadata *map[string]string `json:"metadata,omitempty"` +} + +// NewFlagLinkPost instantiates a new FlagLinkPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagLinkPost() *FlagLinkPost { + this := FlagLinkPost{} + return &this +} + +// NewFlagLinkPostWithDefaults instantiates a new FlagLinkPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagLinkPostWithDefaults() *FlagLinkPost { + this := FlagLinkPost{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *FlagLinkPost) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *FlagLinkPost) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *FlagLinkPost) SetKey(v string) { + o.Key = &v +} + +// GetIntegrationKey returns the IntegrationKey field value if set, zero value otherwise. +func (o *FlagLinkPost) GetIntegrationKey() string { + if o == nil || o.IntegrationKey == nil { + var ret string + return ret + } + return *o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetIntegrationKeyOk() (*string, bool) { + if o == nil || o.IntegrationKey == nil { + return nil, false + } + return o.IntegrationKey, true +} + +// HasIntegrationKey returns a boolean if a field has been set. +func (o *FlagLinkPost) HasIntegrationKey() bool { + if o != nil && o.IntegrationKey != nil { + return true + } + + return false +} + +// SetIntegrationKey gets a reference to the given string and assigns it to the IntegrationKey field. +func (o *FlagLinkPost) SetIntegrationKey(v string) { + o.IntegrationKey = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *FlagLinkPost) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *FlagLinkPost) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *FlagLinkPost) SetTimestamp(v int64) { + o.Timestamp = &v +} + +// GetDeepLink returns the DeepLink field value if set, zero value otherwise. +func (o *FlagLinkPost) GetDeepLink() string { + if o == nil || o.DeepLink == nil { + var ret string + return ret + } + return *o.DeepLink +} + +// GetDeepLinkOk returns a tuple with the DeepLink field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetDeepLinkOk() (*string, bool) { + if o == nil || o.DeepLink == nil { + return nil, false + } + return o.DeepLink, true +} + +// HasDeepLink returns a boolean if a field has been set. +func (o *FlagLinkPost) HasDeepLink() bool { + if o != nil && o.DeepLink != nil { + return true + } + + return false +} + +// SetDeepLink gets a reference to the given string and assigns it to the DeepLink field. +func (o *FlagLinkPost) SetDeepLink(v string) { + o.DeepLink = &v +} + +// GetTitle returns the Title field value if set, zero value otherwise. +func (o *FlagLinkPost) GetTitle() string { + if o == nil || o.Title == nil { + var ret string + return ret + } + return *o.Title +} + +// GetTitleOk returns a tuple with the Title field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetTitleOk() (*string, bool) { + if o == nil || o.Title == nil { + return nil, false + } + return o.Title, true +} + +// HasTitle returns a boolean if a field has been set. +func (o *FlagLinkPost) HasTitle() bool { + if o != nil && o.Title != nil { + return true + } + + return false +} + +// SetTitle gets a reference to the given string and assigns it to the Title field. +func (o *FlagLinkPost) SetTitle(v string) { + o.Title = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FlagLinkPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FlagLinkPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FlagLinkPost) SetDescription(v string) { + o.Description = &v +} + +// GetMetadata returns the Metadata field value if set, zero value otherwise. +func (o *FlagLinkPost) GetMetadata() map[string]string { + if o == nil || o.Metadata == nil { + var ret map[string]string + return ret + } + return *o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkPost) GetMetadataOk() (*map[string]string, bool) { + if o == nil || o.Metadata == nil { + return nil, false + } + return o.Metadata, true +} + +// HasMetadata returns a boolean if a field has been set. +func (o *FlagLinkPost) HasMetadata() bool { + if o != nil && o.Metadata != nil { + return true + } + + return false +} + +// SetMetadata gets a reference to the given map[string]string and assigns it to the Metadata field. +func (o *FlagLinkPost) SetMetadata(v map[string]string) { + o.Metadata = &v +} + +func (o FlagLinkPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.IntegrationKey != nil { + toSerialize["integrationKey"] = o.IntegrationKey + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + if o.DeepLink != nil { + toSerialize["deepLink"] = o.DeepLink + } + if o.Title != nil { + toSerialize["title"] = o.Title + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Metadata != nil { + toSerialize["metadata"] = o.Metadata + } + return json.Marshal(toSerialize) +} + +type NullableFlagLinkPost struct { + value *FlagLinkPost + isSet bool +} + +func (v NullableFlagLinkPost) Get() *FlagLinkPost { + return v.value +} + +func (v *NullableFlagLinkPost) Set(val *FlagLinkPost) { + v.value = val + v.isSet = true +} + +func (v NullableFlagLinkPost) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagLinkPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagLinkPost(val *FlagLinkPost) *NullableFlagLinkPost { + return &NullableFlagLinkPost{value: val, isSet: true} +} + +func (v NullableFlagLinkPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagLinkPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_rep.go new file mode 100644 index 00000000..f0f3960a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_link_rep.go @@ -0,0 +1,449 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagLinkRep struct for FlagLinkRep +type FlagLinkRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The flag link key + Key *string `json:"_key,omitempty"` + // The integration key for an integration whose manifest.json includes the flagLink capability, if this is a flag link for an existing integration + IntegrationKey *string `json:"_integrationKey,omitempty"` + // The ID of this flag link + Id string `json:"_id"` + // The URL for the external resource the flag is linked to + DeepLink string `json:"_deepLink"` + Timestamp TimestampRep `json:"_timestamp"` + // The title of the flag link + Title *string `json:"title,omitempty"` + // The description of the flag link + Description *string `json:"description,omitempty"` + // The metadata required by this integration in order to create a flag link, if this is a flag link for an existing integration. Defined in the integration's manifest.json file under flagLink. + Metadata *map[string]string `json:"_metadata,omitempty"` + CreatedAt int64 `json:"_createdAt"` + Member *FlagLinkMember `json:"_member,omitempty"` +} + +// NewFlagLinkRep instantiates a new FlagLinkRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagLinkRep(links map[string]Link, id string, deepLink string, timestamp TimestampRep, createdAt int64) *FlagLinkRep { + this := FlagLinkRep{} + this.Links = links + this.Id = id + this.DeepLink = deepLink + this.Timestamp = timestamp + this.CreatedAt = createdAt + return &this +} + +// NewFlagLinkRepWithDefaults instantiates a new FlagLinkRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagLinkRepWithDefaults() *FlagLinkRep { + this := FlagLinkRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *FlagLinkRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagLinkRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *FlagLinkRep) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *FlagLinkRep) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *FlagLinkRep) SetKey(v string) { + o.Key = &v +} + +// GetIntegrationKey returns the IntegrationKey field value if set, zero value otherwise. +func (o *FlagLinkRep) GetIntegrationKey() string { + if o == nil || o.IntegrationKey == nil { + var ret string + return ret + } + return *o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetIntegrationKeyOk() (*string, bool) { + if o == nil || o.IntegrationKey == nil { + return nil, false + } + return o.IntegrationKey, true +} + +// HasIntegrationKey returns a boolean if a field has been set. +func (o *FlagLinkRep) HasIntegrationKey() bool { + if o != nil && o.IntegrationKey != nil { + return true + } + + return false +} + +// SetIntegrationKey gets a reference to the given string and assigns it to the IntegrationKey field. +func (o *FlagLinkRep) SetIntegrationKey(v string) { + o.IntegrationKey = &v +} + +// GetId returns the Id field value +func (o *FlagLinkRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FlagLinkRep) SetId(v string) { + o.Id = v +} + +// GetDeepLink returns the DeepLink field value +func (o *FlagLinkRep) GetDeepLink() string { + if o == nil { + var ret string + return ret + } + + return o.DeepLink +} + +// GetDeepLinkOk returns a tuple with the DeepLink field value +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetDeepLinkOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.DeepLink, true +} + +// SetDeepLink sets field value +func (o *FlagLinkRep) SetDeepLink(v string) { + o.DeepLink = v +} + +// GetTimestamp returns the Timestamp field value +func (o *FlagLinkRep) GetTimestamp() TimestampRep { + if o == nil { + var ret TimestampRep + return ret + } + + return o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetTimestampOk() (*TimestampRep, bool) { + if o == nil { + return nil, false + } + return &o.Timestamp, true +} + +// SetTimestamp sets field value +func (o *FlagLinkRep) SetTimestamp(v TimestampRep) { + o.Timestamp = v +} + +// GetTitle returns the Title field value if set, zero value otherwise. +func (o *FlagLinkRep) GetTitle() string { + if o == nil || o.Title == nil { + var ret string + return ret + } + return *o.Title +} + +// GetTitleOk returns a tuple with the Title field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetTitleOk() (*string, bool) { + if o == nil || o.Title == nil { + return nil, false + } + return o.Title, true +} + +// HasTitle returns a boolean if a field has been set. +func (o *FlagLinkRep) HasTitle() bool { + if o != nil && o.Title != nil { + return true + } + + return false +} + +// SetTitle gets a reference to the given string and assigns it to the Title field. +func (o *FlagLinkRep) SetTitle(v string) { + o.Title = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FlagLinkRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FlagLinkRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FlagLinkRep) SetDescription(v string) { + o.Description = &v +} + +// GetMetadata returns the Metadata field value if set, zero value otherwise. +func (o *FlagLinkRep) GetMetadata() map[string]string { + if o == nil || o.Metadata == nil { + var ret map[string]string + return ret + } + return *o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetMetadataOk() (*map[string]string, bool) { + if o == nil || o.Metadata == nil { + return nil, false + } + return o.Metadata, true +} + +// HasMetadata returns a boolean if a field has been set. +func (o *FlagLinkRep) HasMetadata() bool { + if o != nil && o.Metadata != nil { + return true + } + + return false +} + +// SetMetadata gets a reference to the given map[string]string and assigns it to the Metadata field. +func (o *FlagLinkRep) SetMetadata(v map[string]string) { + o.Metadata = &v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *FlagLinkRep) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *FlagLinkRep) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *FlagLinkRep) GetMember() FlagLinkMember { + if o == nil || o.Member == nil { + var ret FlagLinkMember + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagLinkRep) GetMemberOk() (*FlagLinkMember, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *FlagLinkRep) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given FlagLinkMember and assigns it to the Member field. +func (o *FlagLinkRep) SetMember(v FlagLinkMember) { + o.Member = &v +} + +func (o FlagLinkRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if o.Key != nil { + toSerialize["_key"] = o.Key + } + if o.IntegrationKey != nil { + toSerialize["_integrationKey"] = o.IntegrationKey + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_deepLink"] = o.DeepLink + } + if true { + toSerialize["_timestamp"] = o.Timestamp + } + if o.Title != nil { + toSerialize["title"] = o.Title + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Metadata != nil { + toSerialize["_metadata"] = o.Metadata + } + if true { + toSerialize["_createdAt"] = o.CreatedAt + } + if o.Member != nil { + toSerialize["_member"] = o.Member + } + return json.Marshal(toSerialize) +} + +type NullableFlagLinkRep struct { + value *FlagLinkRep + isSet bool +} + +func (v NullableFlagLinkRep) Get() *FlagLinkRep { + return v.value +} + +func (v *NullableFlagLinkRep) Set(val *FlagLinkRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagLinkRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagLinkRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagLinkRep(val *FlagLinkRep) *NullableFlagLinkRep { + return &NullableFlagLinkRep{value: val, isSet: true} +} + +func (v NullableFlagLinkRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagLinkRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_listing_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_listing_rep.go new file mode 100644 index 00000000..03b2d84b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_listing_rep.go @@ -0,0 +1,212 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagListingRep struct for FlagListingRep +type FlagListingRep struct { + // The flag name + Name string `json:"name"` + // The flag key + Key string `json:"key"` + Links *map[string]Link `json:"_links,omitempty"` + Site *Link `json:"_site,omitempty"` +} + +// NewFlagListingRep instantiates a new FlagListingRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagListingRep(name string, key string) *FlagListingRep { + this := FlagListingRep{} + this.Name = name + this.Key = key + return &this +} + +// NewFlagListingRepWithDefaults instantiates a new FlagListingRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagListingRepWithDefaults() *FlagListingRep { + this := FlagListingRep{} + return &this +} + +// GetName returns the Name field value +func (o *FlagListingRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FlagListingRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FlagListingRep) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *FlagListingRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FlagListingRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FlagListingRep) SetKey(v string) { + o.Key = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *FlagListingRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagListingRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *FlagListingRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *FlagListingRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetSite returns the Site field value if set, zero value otherwise. +func (o *FlagListingRep) GetSite() Link { + if o == nil || o.Site == nil { + var ret Link + return ret + } + return *o.Site +} + +// GetSiteOk returns a tuple with the Site field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagListingRep) GetSiteOk() (*Link, bool) { + if o == nil || o.Site == nil { + return nil, false + } + return o.Site, true +} + +// HasSite returns a boolean if a field has been set. +func (o *FlagListingRep) HasSite() bool { + if o != nil && o.Site != nil { + return true + } + + return false +} + +// SetSite gets a reference to the given Link and assigns it to the Site field. +func (o *FlagListingRep) SetSite(v Link) { + o.Site = &v +} + +func (o FlagListingRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Site != nil { + toSerialize["_site"] = o.Site + } + return json.Marshal(toSerialize) +} + +type NullableFlagListingRep struct { + value *FlagListingRep + isSet bool +} + +func (v NullableFlagListingRep) Get() *FlagListingRep { + return v.value +} + +func (v *NullableFlagListingRep) Set(val *FlagListingRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagListingRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagListingRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagListingRep(val *FlagListingRep) *NullableFlagListingRep { + return &NullableFlagListingRep{value: val, isSet: true} +} + +func (v NullableFlagListingRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagListingRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_migration_settings_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_migration_settings_rep.go new file mode 100644 index 00000000..675f7edc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_migration_settings_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagMigrationSettingsRep struct for FlagMigrationSettingsRep +type FlagMigrationSettingsRep struct { + // The context kind targeted by this migration flag. Only applicable for six-stage migrations. + ContextKind *string `json:"contextKind,omitempty"` + // The number of stages for this migration flag + StageCount *int32 `json:"stageCount,omitempty"` +} + +// NewFlagMigrationSettingsRep instantiates a new FlagMigrationSettingsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagMigrationSettingsRep() *FlagMigrationSettingsRep { + this := FlagMigrationSettingsRep{} + return &this +} + +// NewFlagMigrationSettingsRepWithDefaults instantiates a new FlagMigrationSettingsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagMigrationSettingsRepWithDefaults() *FlagMigrationSettingsRep { + this := FlagMigrationSettingsRep{} + return &this +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *FlagMigrationSettingsRep) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagMigrationSettingsRep) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *FlagMigrationSettingsRep) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *FlagMigrationSettingsRep) SetContextKind(v string) { + o.ContextKind = &v +} + +// GetStageCount returns the StageCount field value if set, zero value otherwise. +func (o *FlagMigrationSettingsRep) GetStageCount() int32 { + if o == nil || o.StageCount == nil { + var ret int32 + return ret + } + return *o.StageCount +} + +// GetStageCountOk returns a tuple with the StageCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagMigrationSettingsRep) GetStageCountOk() (*int32, bool) { + if o == nil || o.StageCount == nil { + return nil, false + } + return o.StageCount, true +} + +// HasStageCount returns a boolean if a field has been set. +func (o *FlagMigrationSettingsRep) HasStageCount() bool { + if o != nil && o.StageCount != nil { + return true + } + + return false +} + +// SetStageCount gets a reference to the given int32 and assigns it to the StageCount field. +func (o *FlagMigrationSettingsRep) SetStageCount(v int32) { + o.StageCount = &v +} + +func (o FlagMigrationSettingsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + if o.StageCount != nil { + toSerialize["stageCount"] = o.StageCount + } + return json.Marshal(toSerialize) +} + +type NullableFlagMigrationSettingsRep struct { + value *FlagMigrationSettingsRep + isSet bool +} + +func (v NullableFlagMigrationSettingsRep) Get() *FlagMigrationSettingsRep { + return v.value +} + +func (v *NullableFlagMigrationSettingsRep) Set(val *FlagMigrationSettingsRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagMigrationSettingsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagMigrationSettingsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagMigrationSettingsRep(val *FlagMigrationSettingsRep) *NullableFlagMigrationSettingsRep { + return &NullableFlagMigrationSettingsRep{value: val, isSet: true} +} + +func (v NullableFlagMigrationSettingsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagMigrationSettingsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_prerequisite_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_prerequisite_post.go new file mode 100644 index 00000000..6471a4e3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_prerequisite_post.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagPrerequisitePost struct for FlagPrerequisitePost +type FlagPrerequisitePost struct { + // Flag key of the prerequisite flag + Key string `json:"key"` + // ID of a variation of the prerequisite flag + VariationId string `json:"variationId"` +} + +// NewFlagPrerequisitePost instantiates a new FlagPrerequisitePost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagPrerequisitePost(key string, variationId string) *FlagPrerequisitePost { + this := FlagPrerequisitePost{} + this.Key = key + this.VariationId = variationId + return &this +} + +// NewFlagPrerequisitePostWithDefaults instantiates a new FlagPrerequisitePost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagPrerequisitePostWithDefaults() *FlagPrerequisitePost { + this := FlagPrerequisitePost{} + return &this +} + +// GetKey returns the Key field value +func (o *FlagPrerequisitePost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *FlagPrerequisitePost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *FlagPrerequisitePost) SetKey(v string) { + o.Key = v +} + +// GetVariationId returns the VariationId field value +func (o *FlagPrerequisitePost) GetVariationId() string { + if o == nil { + var ret string + return ret + } + + return o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value +// and a boolean to check if the value has been set. +func (o *FlagPrerequisitePost) GetVariationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VariationId, true +} + +// SetVariationId sets field value +func (o *FlagPrerequisitePost) SetVariationId(v string) { + o.VariationId = v +} + +func (o FlagPrerequisitePost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["variationId"] = o.VariationId + } + return json.Marshal(toSerialize) +} + +type NullableFlagPrerequisitePost struct { + value *FlagPrerequisitePost + isSet bool +} + +func (v NullableFlagPrerequisitePost) Get() *FlagPrerequisitePost { + return v.value +} + +func (v *NullableFlagPrerequisitePost) Set(val *FlagPrerequisitePost) { + v.value = val + v.isSet = true +} + +func (v NullableFlagPrerequisitePost) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagPrerequisitePost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagPrerequisitePost(val *FlagPrerequisitePost) *NullableFlagPrerequisitePost { + return &NullableFlagPrerequisitePost{value: val, isSet: true} +} + +func (v NullableFlagPrerequisitePost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagPrerequisitePost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_collection_rep.go new file mode 100644 index 00000000..bda34d11 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagReferenceCollectionRep struct for FlagReferenceCollectionRep +type FlagReferenceCollectionRep struct { + // The total number of flag references + TotalCount int32 `json:"totalCount"` + // A list of flag references + Items []FlagReferenceRep `json:"items"` +} + +// NewFlagReferenceCollectionRep instantiates a new FlagReferenceCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagReferenceCollectionRep(totalCount int32, items []FlagReferenceRep) *FlagReferenceCollectionRep { + this := FlagReferenceCollectionRep{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewFlagReferenceCollectionRepWithDefaults instantiates a new FlagReferenceCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagReferenceCollectionRepWithDefaults() *FlagReferenceCollectionRep { + this := FlagReferenceCollectionRep{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *FlagReferenceCollectionRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *FlagReferenceCollectionRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *FlagReferenceCollectionRep) GetItems() []FlagReferenceRep { + if o == nil { + var ret []FlagReferenceRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceCollectionRep) GetItemsOk() ([]FlagReferenceRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *FlagReferenceCollectionRep) SetItems(v []FlagReferenceRep) { + o.Items = v +} + +func (o FlagReferenceCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableFlagReferenceCollectionRep struct { + value *FlagReferenceCollectionRep + isSet bool +} + +func (v NullableFlagReferenceCollectionRep) Get() *FlagReferenceCollectionRep { + return v.value +} + +func (v *NullableFlagReferenceCollectionRep) Set(val *FlagReferenceCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagReferenceCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagReferenceCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagReferenceCollectionRep(val *FlagReferenceCollectionRep) *NullableFlagReferenceCollectionRep { + return &NullableFlagReferenceCollectionRep{value: val, isSet: true} +} + +func (v NullableFlagReferenceCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagReferenceCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_rep.go new file mode 100644 index 00000000..ba414a7a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_reference_rep.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagReferenceRep struct for FlagReferenceRep +type FlagReferenceRep struct { + // The project key + ProjectKey string `json:"projectKey"` + // The flag key + FlagKey string `json:"flagKey"` + // The number of references added + ReferencesAdded int32 `json:"referencesAdded"` + // The number of references removed + ReferencesRemoved int32 `json:"referencesRemoved"` +} + +// NewFlagReferenceRep instantiates a new FlagReferenceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagReferenceRep(projectKey string, flagKey string, referencesAdded int32, referencesRemoved int32) *FlagReferenceRep { + this := FlagReferenceRep{} + this.ProjectKey = projectKey + this.FlagKey = flagKey + this.ReferencesAdded = referencesAdded + this.ReferencesRemoved = referencesRemoved + return &this +} + +// NewFlagReferenceRepWithDefaults instantiates a new FlagReferenceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagReferenceRepWithDefaults() *FlagReferenceRep { + this := FlagReferenceRep{} + return &this +} + +// GetProjectKey returns the ProjectKey field value +func (o *FlagReferenceRep) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceRep) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *FlagReferenceRep) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetFlagKey returns the FlagKey field value +func (o *FlagReferenceRep) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceRep) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *FlagReferenceRep) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetReferencesAdded returns the ReferencesAdded field value +func (o *FlagReferenceRep) GetReferencesAdded() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ReferencesAdded +} + +// GetReferencesAddedOk returns a tuple with the ReferencesAdded field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceRep) GetReferencesAddedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ReferencesAdded, true +} + +// SetReferencesAdded sets field value +func (o *FlagReferenceRep) SetReferencesAdded(v int32) { + o.ReferencesAdded = v +} + +// GetReferencesRemoved returns the ReferencesRemoved field value +func (o *FlagReferenceRep) GetReferencesRemoved() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ReferencesRemoved +} + +// GetReferencesRemovedOk returns a tuple with the ReferencesRemoved field value +// and a boolean to check if the value has been set. +func (o *FlagReferenceRep) GetReferencesRemovedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ReferencesRemoved, true +} + +// SetReferencesRemoved sets field value +func (o *FlagReferenceRep) SetReferencesRemoved(v int32) { + o.ReferencesRemoved = v +} + +func (o FlagReferenceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["referencesAdded"] = o.ReferencesAdded + } + if true { + toSerialize["referencesRemoved"] = o.ReferencesRemoved + } + return json.Marshal(toSerialize) +} + +type NullableFlagReferenceRep struct { + value *FlagReferenceRep + isSet bool +} + +func (v NullableFlagReferenceRep) Get() *FlagReferenceRep { + return v.value +} + +func (v *NullableFlagReferenceRep) Set(val *FlagReferenceRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagReferenceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagReferenceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagReferenceRep(val *FlagReferenceRep) *NullableFlagReferenceRep { + return &NullableFlagReferenceRep{value: val, isSet: true} +} + +func (v NullableFlagReferenceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagReferenceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_rep.go new file mode 100644 index 00000000..c4276e9f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_rep.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagRep struct for FlagRep +type FlagRep struct { + // The targeting rule + TargetingRule *string `json:"targetingRule,omitempty"` + // The rule description + TargetingRuleDescription *string `json:"targetingRuleDescription,omitempty"` + // An array of clauses used for individual targeting based on attributes + TargetingRuleClauses []interface{} `json:"targetingRuleClauses,omitempty"` + // The flag version + FlagConfigVersion *int32 `json:"flagConfigVersion,omitempty"` + // The ID of the variation to route traffic not part of the experiment analysis to + NotInExperimentVariationId *string `json:"notInExperimentVariationId,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewFlagRep instantiates a new FlagRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagRep(links map[string]Link) *FlagRep { + this := FlagRep{} + this.Links = links + return &this +} + +// NewFlagRepWithDefaults instantiates a new FlagRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagRepWithDefaults() *FlagRep { + this := FlagRep{} + return &this +} + +// GetTargetingRule returns the TargetingRule field value if set, zero value otherwise. +func (o *FlagRep) GetTargetingRule() string { + if o == nil || o.TargetingRule == nil { + var ret string + return ret + } + return *o.TargetingRule +} + +// GetTargetingRuleOk returns a tuple with the TargetingRule field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagRep) GetTargetingRuleOk() (*string, bool) { + if o == nil || o.TargetingRule == nil { + return nil, false + } + return o.TargetingRule, true +} + +// HasTargetingRule returns a boolean if a field has been set. +func (o *FlagRep) HasTargetingRule() bool { + if o != nil && o.TargetingRule != nil { + return true + } + + return false +} + +// SetTargetingRule gets a reference to the given string and assigns it to the TargetingRule field. +func (o *FlagRep) SetTargetingRule(v string) { + o.TargetingRule = &v +} + +// GetTargetingRuleDescription returns the TargetingRuleDescription field value if set, zero value otherwise. +func (o *FlagRep) GetTargetingRuleDescription() string { + if o == nil || o.TargetingRuleDescription == nil { + var ret string + return ret + } + return *o.TargetingRuleDescription +} + +// GetTargetingRuleDescriptionOk returns a tuple with the TargetingRuleDescription field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagRep) GetTargetingRuleDescriptionOk() (*string, bool) { + if o == nil || o.TargetingRuleDescription == nil { + return nil, false + } + return o.TargetingRuleDescription, true +} + +// HasTargetingRuleDescription returns a boolean if a field has been set. +func (o *FlagRep) HasTargetingRuleDescription() bool { + if o != nil && o.TargetingRuleDescription != nil { + return true + } + + return false +} + +// SetTargetingRuleDescription gets a reference to the given string and assigns it to the TargetingRuleDescription field. +func (o *FlagRep) SetTargetingRuleDescription(v string) { + o.TargetingRuleDescription = &v +} + +// GetTargetingRuleClauses returns the TargetingRuleClauses field value if set, zero value otherwise. +func (o *FlagRep) GetTargetingRuleClauses() []interface{} { + if o == nil || o.TargetingRuleClauses == nil { + var ret []interface{} + return ret + } + return o.TargetingRuleClauses +} + +// GetTargetingRuleClausesOk returns a tuple with the TargetingRuleClauses field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagRep) GetTargetingRuleClausesOk() ([]interface{}, bool) { + if o == nil || o.TargetingRuleClauses == nil { + return nil, false + } + return o.TargetingRuleClauses, true +} + +// HasTargetingRuleClauses returns a boolean if a field has been set. +func (o *FlagRep) HasTargetingRuleClauses() bool { + if o != nil && o.TargetingRuleClauses != nil { + return true + } + + return false +} + +// SetTargetingRuleClauses gets a reference to the given []interface{} and assigns it to the TargetingRuleClauses field. +func (o *FlagRep) SetTargetingRuleClauses(v []interface{}) { + o.TargetingRuleClauses = v +} + +// GetFlagConfigVersion returns the FlagConfigVersion field value if set, zero value otherwise. +func (o *FlagRep) GetFlagConfigVersion() int32 { + if o == nil || o.FlagConfigVersion == nil { + var ret int32 + return ret + } + return *o.FlagConfigVersion +} + +// GetFlagConfigVersionOk returns a tuple with the FlagConfigVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagRep) GetFlagConfigVersionOk() (*int32, bool) { + if o == nil || o.FlagConfigVersion == nil { + return nil, false + } + return o.FlagConfigVersion, true +} + +// HasFlagConfigVersion returns a boolean if a field has been set. +func (o *FlagRep) HasFlagConfigVersion() bool { + if o != nil && o.FlagConfigVersion != nil { + return true + } + + return false +} + +// SetFlagConfigVersion gets a reference to the given int32 and assigns it to the FlagConfigVersion field. +func (o *FlagRep) SetFlagConfigVersion(v int32) { + o.FlagConfigVersion = &v +} + +// GetNotInExperimentVariationId returns the NotInExperimentVariationId field value if set, zero value otherwise. +func (o *FlagRep) GetNotInExperimentVariationId() string { + if o == nil || o.NotInExperimentVariationId == nil { + var ret string + return ret + } + return *o.NotInExperimentVariationId +} + +// GetNotInExperimentVariationIdOk returns a tuple with the NotInExperimentVariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagRep) GetNotInExperimentVariationIdOk() (*string, bool) { + if o == nil || o.NotInExperimentVariationId == nil { + return nil, false + } + return o.NotInExperimentVariationId, true +} + +// HasNotInExperimentVariationId returns a boolean if a field has been set. +func (o *FlagRep) HasNotInExperimentVariationId() bool { + if o != nil && o.NotInExperimentVariationId != nil { + return true + } + + return false +} + +// SetNotInExperimentVariationId gets a reference to the given string and assigns it to the NotInExperimentVariationId field. +func (o *FlagRep) SetNotInExperimentVariationId(v string) { + o.NotInExperimentVariationId = &v +} + +// GetLinks returns the Links field value +func (o *FlagRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o FlagRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TargetingRule != nil { + toSerialize["targetingRule"] = o.TargetingRule + } + if o.TargetingRuleDescription != nil { + toSerialize["targetingRuleDescription"] = o.TargetingRuleDescription + } + if o.TargetingRuleClauses != nil { + toSerialize["targetingRuleClauses"] = o.TargetingRuleClauses + } + if o.FlagConfigVersion != nil { + toSerialize["flagConfigVersion"] = o.FlagConfigVersion + } + if o.NotInExperimentVariationId != nil { + toSerialize["notInExperimentVariationId"] = o.NotInExperimentVariationId + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagRep struct { + value *FlagRep + isSet bool +} + +func (v NullableFlagRep) Get() *FlagRep { + return v.value +} + +func (v *NullableFlagRep) Set(val *FlagRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagRep(val *FlagRep) *NullableFlagRep { + return &NullableFlagRep{value: val, isSet: true} +} + +func (v NullableFlagRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_scheduled_changes_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_scheduled_changes_input.go new file mode 100644 index 00000000..0db6c351 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_scheduled_changes_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagScheduledChangesInput struct for FlagScheduledChangesInput +type FlagScheduledChangesInput struct { + // Optional comment describing the update to the scheduled changes + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewFlagScheduledChangesInput instantiates a new FlagScheduledChangesInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagScheduledChangesInput(instructions []map[string]interface{}) *FlagScheduledChangesInput { + this := FlagScheduledChangesInput{} + this.Instructions = instructions + return &this +} + +// NewFlagScheduledChangesInputWithDefaults instantiates a new FlagScheduledChangesInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagScheduledChangesInputWithDefaults() *FlagScheduledChangesInput { + this := FlagScheduledChangesInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *FlagScheduledChangesInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagScheduledChangesInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *FlagScheduledChangesInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *FlagScheduledChangesInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *FlagScheduledChangesInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *FlagScheduledChangesInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *FlagScheduledChangesInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o FlagScheduledChangesInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableFlagScheduledChangesInput struct { + value *FlagScheduledChangesInput + isSet bool +} + +func (v NullableFlagScheduledChangesInput) Get() *FlagScheduledChangesInput { + return v.value +} + +func (v *NullableFlagScheduledChangesInput) Set(val *FlagScheduledChangesInput) { + v.value = val + v.isSet = true +} + +func (v NullableFlagScheduledChangesInput) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagScheduledChangesInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagScheduledChangesInput(val *FlagScheduledChangesInput) *NullableFlagScheduledChangesInput { + return &NullableFlagScheduledChangesInput{value: val, isSet: true} +} + +func (v NullableFlagScheduledChangesInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagScheduledChangesInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_sempatch.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_sempatch.go new file mode 100644 index 00000000..101b8c1b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_sempatch.go @@ -0,0 +1,145 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagSempatch struct for FlagSempatch +type FlagSempatch struct { + Instructions []map[string]interface{} `json:"instructions"` + Comment *string `json:"comment,omitempty"` +} + +// NewFlagSempatch instantiates a new FlagSempatch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagSempatch(instructions []map[string]interface{}) *FlagSempatch { + this := FlagSempatch{} + this.Instructions = instructions + return &this +} + +// NewFlagSempatchWithDefaults instantiates a new FlagSempatch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagSempatchWithDefaults() *FlagSempatch { + this := FlagSempatch{} + return &this +} + +// GetInstructions returns the Instructions field value +func (o *FlagSempatch) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *FlagSempatch) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *FlagSempatch) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *FlagSempatch) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagSempatch) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *FlagSempatch) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *FlagSempatch) SetComment(v string) { + o.Comment = &v +} + +func (o FlagSempatch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["instructions"] = o.Instructions + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + return json.Marshal(toSerialize) +} + +type NullableFlagSempatch struct { + value *FlagSempatch + isSet bool +} + +func (v NullableFlagSempatch) Get() *FlagSempatch { + return v.value +} + +func (v *NullableFlagSempatch) Set(val *FlagSempatch) { + v.value = val + v.isSet = true +} + +func (v NullableFlagSempatch) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagSempatch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagSempatch(val *FlagSempatch) *NullableFlagSempatch { + return &NullableFlagSempatch{value: val, isSet: true} +} + +func (v NullableFlagSempatch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagSempatch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_status_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_status_rep.go new file mode 100644 index 00000000..be4cf60c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_status_rep.go @@ -0,0 +1,215 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// FlagStatusRep struct for FlagStatusRep +type FlagStatusRep struct { + // Status of the flag + Name string `json:"name"` + // Timestamp of last time flag was requested + LastRequested *time.Time `json:"lastRequested,omitempty"` + // Default value seen from code + Default interface{} `json:"default,omitempty"` + Links map[string]Link `json:"_links"` +} + +// NewFlagStatusRep instantiates a new FlagStatusRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagStatusRep(name string, links map[string]Link) *FlagStatusRep { + this := FlagStatusRep{} + this.Name = name + this.Links = links + return &this +} + +// NewFlagStatusRepWithDefaults instantiates a new FlagStatusRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagStatusRepWithDefaults() *FlagStatusRep { + this := FlagStatusRep{} + return &this +} + +// GetName returns the Name field value +func (o *FlagStatusRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *FlagStatusRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *FlagStatusRep) SetName(v string) { + o.Name = v +} + +// GetLastRequested returns the LastRequested field value if set, zero value otherwise. +func (o *FlagStatusRep) GetLastRequested() time.Time { + if o == nil || o.LastRequested == nil { + var ret time.Time + return ret + } + return *o.LastRequested +} + +// GetLastRequestedOk returns a tuple with the LastRequested field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagStatusRep) GetLastRequestedOk() (*time.Time, bool) { + if o == nil || o.LastRequested == nil { + return nil, false + } + return o.LastRequested, true +} + +// HasLastRequested returns a boolean if a field has been set. +func (o *FlagStatusRep) HasLastRequested() bool { + if o != nil && o.LastRequested != nil { + return true + } + + return false +} + +// SetLastRequested gets a reference to the given time.Time and assigns it to the LastRequested field. +func (o *FlagStatusRep) SetLastRequested(v time.Time) { + o.LastRequested = &v +} + +// GetDefault returns the Default field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *FlagStatusRep) GetDefault() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Default +} + +// GetDefaultOk returns a tuple with the Default field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *FlagStatusRep) GetDefaultOk() (*interface{}, bool) { + if o == nil || o.Default == nil { + return nil, false + } + return &o.Default, true +} + +// HasDefault returns a boolean if a field has been set. +func (o *FlagStatusRep) HasDefault() bool { + if o != nil && o.Default != nil { + return true + } + + return false +} + +// SetDefault gets a reference to the given interface{} and assigns it to the Default field. +func (o *FlagStatusRep) SetDefault(v interface{}) { + o.Default = v +} + +// GetLinks returns the Links field value +func (o *FlagStatusRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FlagStatusRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FlagStatusRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o FlagStatusRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.LastRequested != nil { + toSerialize["lastRequested"] = o.LastRequested + } + if o.Default != nil { + toSerialize["default"] = o.Default + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableFlagStatusRep struct { + value *FlagStatusRep + isSet bool +} + +func (v NullableFlagStatusRep) Get() *FlagStatusRep { + return v.value +} + +func (v *NullableFlagStatusRep) Set(val *FlagStatusRep) { + v.value = val + v.isSet = true +} + +func (v NullableFlagStatusRep) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagStatusRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagStatusRep(val *FlagStatusRep) *NullableFlagStatusRep { + return &NullableFlagStatusRep{value: val, isSet: true} +} + +func (v NullableFlagStatusRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagStatusRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_summary.go new file mode 100644 index 00000000..0e3d2541 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_summary.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagSummary struct for FlagSummary +type FlagSummary struct { + Variations map[string]VariationSummary `json:"variations"` + // The number of prerequisites for this flag + Prerequisites int32 `json:"prerequisites"` +} + +// NewFlagSummary instantiates a new FlagSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagSummary(variations map[string]VariationSummary, prerequisites int32) *FlagSummary { + this := FlagSummary{} + this.Variations = variations + this.Prerequisites = prerequisites + return &this +} + +// NewFlagSummaryWithDefaults instantiates a new FlagSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagSummaryWithDefaults() *FlagSummary { + this := FlagSummary{} + return &this +} + +// GetVariations returns the Variations field value +func (o *FlagSummary) GetVariations() map[string]VariationSummary { + if o == nil { + var ret map[string]VariationSummary + return ret + } + + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value +// and a boolean to check if the value has been set. +func (o *FlagSummary) GetVariationsOk() (*map[string]VariationSummary, bool) { + if o == nil { + return nil, false + } + return &o.Variations, true +} + +// SetVariations sets field value +func (o *FlagSummary) SetVariations(v map[string]VariationSummary) { + o.Variations = v +} + +// GetPrerequisites returns the Prerequisites field value +func (o *FlagSummary) GetPrerequisites() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Prerequisites +} + +// GetPrerequisitesOk returns a tuple with the Prerequisites field value +// and a boolean to check if the value has been set. +func (o *FlagSummary) GetPrerequisitesOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Prerequisites, true +} + +// SetPrerequisites sets field value +func (o *FlagSummary) SetPrerequisites(v int32) { + o.Prerequisites = v +} + +func (o FlagSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["variations"] = o.Variations + } + if true { + toSerialize["prerequisites"] = o.Prerequisites + } + return json.Marshal(toSerialize) +} + +type NullableFlagSummary struct { + value *FlagSummary + isSet bool +} + +func (v NullableFlagSummary) Get() *FlagSummary { + return v.value +} + +func (v *NullableFlagSummary) Set(val *FlagSummary) { + v.value = val + v.isSet = true +} + +func (v NullableFlagSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagSummary(val *FlagSummary) *NullableFlagSummary { + return &NullableFlagSummary{value: val, isSet: true} +} + +func (v NullableFlagSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_trigger_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_trigger_input.go new file mode 100644 index 00000000..c68085f1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_flag_trigger_input.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FlagTriggerInput struct for FlagTriggerInput +type FlagTriggerInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + // The instructions to perform when updating. This should be an array with objects that look like {\"kind\": \"trigger_action\"}. + Instructions []map[string]interface{} `json:"instructions,omitempty"` +} + +// NewFlagTriggerInput instantiates a new FlagTriggerInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFlagTriggerInput() *FlagTriggerInput { + this := FlagTriggerInput{} + return &this +} + +// NewFlagTriggerInputWithDefaults instantiates a new FlagTriggerInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFlagTriggerInputWithDefaults() *FlagTriggerInput { + this := FlagTriggerInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *FlagTriggerInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagTriggerInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *FlagTriggerInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *FlagTriggerInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value if set, zero value otherwise. +func (o *FlagTriggerInput) GetInstructions() []map[string]interface{} { + if o == nil || o.Instructions == nil { + var ret []map[string]interface{} + return ret + } + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FlagTriggerInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil || o.Instructions == nil { + return nil, false + } + return o.Instructions, true +} + +// HasInstructions returns a boolean if a field has been set. +func (o *FlagTriggerInput) HasInstructions() bool { + if o != nil && o.Instructions != nil { + return true + } + + return false +} + +// SetInstructions gets a reference to the given []map[string]interface{} and assigns it to the Instructions field. +func (o *FlagTriggerInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o FlagTriggerInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.Instructions != nil { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableFlagTriggerInput struct { + value *FlagTriggerInput + isSet bool +} + +func (v NullableFlagTriggerInput) Get() *FlagTriggerInput { + return v.value +} + +func (v *NullableFlagTriggerInput) Set(val *FlagTriggerInput) { + v.value = val + v.isSet = true +} + +func (v NullableFlagTriggerInput) IsSet() bool { + return v.isSet +} + +func (v *NullableFlagTriggerInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFlagTriggerInput(val *FlagTriggerInput) *NullableFlagTriggerInput { + return &NullableFlagTriggerInput{value: val, isSet: true} +} + +func (v NullableFlagTriggerInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFlagTriggerInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_follow_flag_member.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_follow_flag_member.go new file mode 100644 index 00000000..4ddbd5e4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_follow_flag_member.go @@ -0,0 +1,274 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FollowFlagMember struct for FollowFlagMember +type FollowFlagMember struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The member's ID + Id string `json:"_id"` + // The member's first name + FirstName *string `json:"firstName,omitempty"` + // The member's last name + LastName *string `json:"lastName,omitempty"` + // The member's built-in role. If the member has no custom roles, this role will be in effect. + Role string `json:"role"` + // The member's email address + Email string `json:"email"` +} + +// NewFollowFlagMember instantiates a new FollowFlagMember object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFollowFlagMember(links map[string]Link, id string, role string, email string) *FollowFlagMember { + this := FollowFlagMember{} + this.Links = links + this.Id = id + this.Role = role + this.Email = email + return &this +} + +// NewFollowFlagMemberWithDefaults instantiates a new FollowFlagMember object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFollowFlagMemberWithDefaults() *FollowFlagMember { + this := FollowFlagMember{} + return &this +} + +// GetLinks returns the Links field value +func (o *FollowFlagMember) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *FollowFlagMember) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *FollowFlagMember) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *FollowFlagMember) SetId(v string) { + o.Id = v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *FollowFlagMember) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *FollowFlagMember) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *FollowFlagMember) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *FollowFlagMember) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *FollowFlagMember) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *FollowFlagMember) SetLastName(v string) { + o.LastName = &v +} + +// GetRole returns the Role field value +func (o *FollowFlagMember) GetRole() string { + if o == nil { + var ret string + return ret + } + + return o.Role +} + +// GetRoleOk returns a tuple with the Role field value +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetRoleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Role, true +} + +// SetRole sets field value +func (o *FollowFlagMember) SetRole(v string) { + o.Role = v +} + +// GetEmail returns the Email field value +func (o *FollowFlagMember) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *FollowFlagMember) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *FollowFlagMember) SetEmail(v string) { + o.Email = v +} + +func (o FollowFlagMember) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if true { + toSerialize["role"] = o.Role + } + if true { + toSerialize["email"] = o.Email + } + return json.Marshal(toSerialize) +} + +type NullableFollowFlagMember struct { + value *FollowFlagMember + isSet bool +} + +func (v NullableFollowFlagMember) Get() *FollowFlagMember { + return v.value +} + +func (v *NullableFollowFlagMember) Set(val *FollowFlagMember) { + v.value = val + v.isSet = true +} + +func (v NullableFollowFlagMember) IsSet() bool { + return v.isSet +} + +func (v *NullableFollowFlagMember) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFollowFlagMember(val *FollowFlagMember) *NullableFollowFlagMember { + return &NullableFollowFlagMember{value: val, isSet: true} +} + +func (v NullableFollowFlagMember) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFollowFlagMember) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_followers_per_flag.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_followers_per_flag.go new file mode 100644 index 00000000..0bb89c72 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_followers_per_flag.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FollowersPerFlag struct for FollowersPerFlag +type FollowersPerFlag struct { + // The flag key + FlagKey *string `json:"flagKey,omitempty"` + // A list of members who are following this flag + Followers []FollowFlagMember `json:"followers,omitempty"` +} + +// NewFollowersPerFlag instantiates a new FollowersPerFlag object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFollowersPerFlag() *FollowersPerFlag { + this := FollowersPerFlag{} + return &this +} + +// NewFollowersPerFlagWithDefaults instantiates a new FollowersPerFlag object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFollowersPerFlagWithDefaults() *FollowersPerFlag { + this := FollowersPerFlag{} + return &this +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +func (o *FollowersPerFlag) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FollowersPerFlag) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *FollowersPerFlag) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +func (o *FollowersPerFlag) SetFlagKey(v string) { + o.FlagKey = &v +} + +// GetFollowers returns the Followers field value if set, zero value otherwise. +func (o *FollowersPerFlag) GetFollowers() []FollowFlagMember { + if o == nil || o.Followers == nil { + var ret []FollowFlagMember + return ret + } + return o.Followers +} + +// GetFollowersOk returns a tuple with the Followers field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FollowersPerFlag) GetFollowersOk() ([]FollowFlagMember, bool) { + if o == nil || o.Followers == nil { + return nil, false + } + return o.Followers, true +} + +// HasFollowers returns a boolean if a field has been set. +func (o *FollowersPerFlag) HasFollowers() bool { + if o != nil && o.Followers != nil { + return true + } + + return false +} + +// SetFollowers gets a reference to the given []FollowFlagMember and assigns it to the Followers field. +func (o *FollowersPerFlag) SetFollowers(v []FollowFlagMember) { + o.Followers = v +} + +func (o FollowersPerFlag) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + if o.Followers != nil { + toSerialize["followers"] = o.Followers + } + return json.Marshal(toSerialize) +} + +type NullableFollowersPerFlag struct { + value *FollowersPerFlag + isSet bool +} + +func (v NullableFollowersPerFlag) Get() *FollowersPerFlag { + return v.value +} + +func (v *NullableFollowersPerFlag) Set(val *FollowersPerFlag) { + v.value = val + v.isSet = true +} + +func (v NullableFollowersPerFlag) IsSet() bool { + return v.isSet +} + +func (v *NullableFollowersPerFlag) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFollowersPerFlag(val *FollowersPerFlag) *NullableFollowersPerFlag { + return &NullableFollowersPerFlag{value: val, isSet: true} +} + +func (v NullableFollowersPerFlag) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFollowersPerFlag) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_forbidden_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_forbidden_error_rep.go new file mode 100644 index 00000000..4541c357 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_forbidden_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ForbiddenErrorRep struct for ForbiddenErrorRep +type ForbiddenErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewForbiddenErrorRep instantiates a new ForbiddenErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewForbiddenErrorRep(code string, message string) *ForbiddenErrorRep { + this := ForbiddenErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewForbiddenErrorRepWithDefaults instantiates a new ForbiddenErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewForbiddenErrorRepWithDefaults() *ForbiddenErrorRep { + this := ForbiddenErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *ForbiddenErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *ForbiddenErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *ForbiddenErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *ForbiddenErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *ForbiddenErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *ForbiddenErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o ForbiddenErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableForbiddenErrorRep struct { + value *ForbiddenErrorRep + isSet bool +} + +func (v NullableForbiddenErrorRep) Get() *ForbiddenErrorRep { + return v.value +} + +func (v *NullableForbiddenErrorRep) Set(val *ForbiddenErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableForbiddenErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableForbiddenErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableForbiddenErrorRep(val *ForbiddenErrorRep) *NullableForbiddenErrorRep { + return &NullableForbiddenErrorRep{value: val, isSet: true} +} + +func (v NullableForbiddenErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableForbiddenErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_form_variable.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_form_variable.go new file mode 100644 index 00000000..b1aebb58 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_form_variable.go @@ -0,0 +1,405 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// FormVariable struct for FormVariable +type FormVariable struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + Description *string `json:"description,omitempty"` + Placeholder *string `json:"placeholder,omitempty"` + IsOptional *bool `json:"isOptional,omitempty"` + DefaultValue interface{} `json:"defaultValue,omitempty"` + AllowedValues []string `json:"allowedValues,omitempty"` + DynamicOptions *DynamicOptions `json:"dynamicOptions,omitempty"` +} + +// NewFormVariable instantiates a new FormVariable object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewFormVariable() *FormVariable { + this := FormVariable{} + return &this +} + +// NewFormVariableWithDefaults instantiates a new FormVariable object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewFormVariableWithDefaults() *FormVariable { + this := FormVariable{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *FormVariable) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *FormVariable) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *FormVariable) SetKey(v string) { + o.Key = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *FormVariable) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *FormVariable) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *FormVariable) SetName(v string) { + o.Name = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *FormVariable) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *FormVariable) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *FormVariable) SetType(v string) { + o.Type = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *FormVariable) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *FormVariable) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *FormVariable) SetDescription(v string) { + o.Description = &v +} + +// GetPlaceholder returns the Placeholder field value if set, zero value otherwise. +func (o *FormVariable) GetPlaceholder() string { + if o == nil || o.Placeholder == nil { + var ret string + return ret + } + return *o.Placeholder +} + +// GetPlaceholderOk returns a tuple with the Placeholder field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetPlaceholderOk() (*string, bool) { + if o == nil || o.Placeholder == nil { + return nil, false + } + return o.Placeholder, true +} + +// HasPlaceholder returns a boolean if a field has been set. +func (o *FormVariable) HasPlaceholder() bool { + if o != nil && o.Placeholder != nil { + return true + } + + return false +} + +// SetPlaceholder gets a reference to the given string and assigns it to the Placeholder field. +func (o *FormVariable) SetPlaceholder(v string) { + o.Placeholder = &v +} + +// GetIsOptional returns the IsOptional field value if set, zero value otherwise. +func (o *FormVariable) GetIsOptional() bool { + if o == nil || o.IsOptional == nil { + var ret bool + return ret + } + return *o.IsOptional +} + +// GetIsOptionalOk returns a tuple with the IsOptional field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetIsOptionalOk() (*bool, bool) { + if o == nil || o.IsOptional == nil { + return nil, false + } + return o.IsOptional, true +} + +// HasIsOptional returns a boolean if a field has been set. +func (o *FormVariable) HasIsOptional() bool { + if o != nil && o.IsOptional != nil { + return true + } + + return false +} + +// SetIsOptional gets a reference to the given bool and assigns it to the IsOptional field. +func (o *FormVariable) SetIsOptional(v bool) { + o.IsOptional = &v +} + +// GetDefaultValue returns the DefaultValue field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *FormVariable) GetDefaultValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.DefaultValue +} + +// GetDefaultValueOk returns a tuple with the DefaultValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *FormVariable) GetDefaultValueOk() (*interface{}, bool) { + if o == nil || o.DefaultValue == nil { + return nil, false + } + return &o.DefaultValue, true +} + +// HasDefaultValue returns a boolean if a field has been set. +func (o *FormVariable) HasDefaultValue() bool { + if o != nil && o.DefaultValue != nil { + return true + } + + return false +} + +// SetDefaultValue gets a reference to the given interface{} and assigns it to the DefaultValue field. +func (o *FormVariable) SetDefaultValue(v interface{}) { + o.DefaultValue = v +} + +// GetAllowedValues returns the AllowedValues field value if set, zero value otherwise. +func (o *FormVariable) GetAllowedValues() []string { + if o == nil || o.AllowedValues == nil { + var ret []string + return ret + } + return o.AllowedValues +} + +// GetAllowedValuesOk returns a tuple with the AllowedValues field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetAllowedValuesOk() ([]string, bool) { + if o == nil || o.AllowedValues == nil { + return nil, false + } + return o.AllowedValues, true +} + +// HasAllowedValues returns a boolean if a field has been set. +func (o *FormVariable) HasAllowedValues() bool { + if o != nil && o.AllowedValues != nil { + return true + } + + return false +} + +// SetAllowedValues gets a reference to the given []string and assigns it to the AllowedValues field. +func (o *FormVariable) SetAllowedValues(v []string) { + o.AllowedValues = v +} + +// GetDynamicOptions returns the DynamicOptions field value if set, zero value otherwise. +func (o *FormVariable) GetDynamicOptions() DynamicOptions { + if o == nil || o.DynamicOptions == nil { + var ret DynamicOptions + return ret + } + return *o.DynamicOptions +} + +// GetDynamicOptionsOk returns a tuple with the DynamicOptions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *FormVariable) GetDynamicOptionsOk() (*DynamicOptions, bool) { + if o == nil || o.DynamicOptions == nil { + return nil, false + } + return o.DynamicOptions, true +} + +// HasDynamicOptions returns a boolean if a field has been set. +func (o *FormVariable) HasDynamicOptions() bool { + if o != nil && o.DynamicOptions != nil { + return true + } + + return false +} + +// SetDynamicOptions gets a reference to the given DynamicOptions and assigns it to the DynamicOptions field. +func (o *FormVariable) SetDynamicOptions(v DynamicOptions) { + o.DynamicOptions = &v +} + +func (o FormVariable) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Placeholder != nil { + toSerialize["placeholder"] = o.Placeholder + } + if o.IsOptional != nil { + toSerialize["isOptional"] = o.IsOptional + } + if o.DefaultValue != nil { + toSerialize["defaultValue"] = o.DefaultValue + } + if o.AllowedValues != nil { + toSerialize["allowedValues"] = o.AllowedValues + } + if o.DynamicOptions != nil { + toSerialize["dynamicOptions"] = o.DynamicOptions + } + return json.Marshal(toSerialize) +} + +type NullableFormVariable struct { + value *FormVariable + isSet bool +} + +func (v NullableFormVariable) Get() *FormVariable { + return v.value +} + +func (v *NullableFormVariable) Set(val *FormVariable) { + v.value = val + v.isSet = true +} + +func (v NullableFormVariable) IsSet() bool { + return v.isSet +} + +func (v *NullableFormVariable) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFormVariable(val *FormVariable) *NullableFormVariable { + return &NullableFormVariable{value: val, isSet: true} +} + +func (v NullableFormVariable) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFormVariable) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_generate_warehouse_destination_key_pair_post_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_generate_warehouse_destination_key_pair_post_rep.go new file mode 100644 index 00000000..65e35b8e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_generate_warehouse_destination_key_pair_post_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// GenerateWarehouseDestinationKeyPairPostRep struct for GenerateWarehouseDestinationKeyPairPostRep +type GenerateWarehouseDestinationKeyPairPostRep struct { + // The public key used by LaunchDarkly + PublicKey *string `json:"public_key,omitempty"` + // The public key to assign in your Snowflake worksheet + PublicKeyPkcs8 *string `json:"public_key_pkcs8,omitempty"` +} + +// NewGenerateWarehouseDestinationKeyPairPostRep instantiates a new GenerateWarehouseDestinationKeyPairPostRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewGenerateWarehouseDestinationKeyPairPostRep() *GenerateWarehouseDestinationKeyPairPostRep { + this := GenerateWarehouseDestinationKeyPairPostRep{} + return &this +} + +// NewGenerateWarehouseDestinationKeyPairPostRepWithDefaults instantiates a new GenerateWarehouseDestinationKeyPairPostRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewGenerateWarehouseDestinationKeyPairPostRepWithDefaults() *GenerateWarehouseDestinationKeyPairPostRep { + this := GenerateWarehouseDestinationKeyPairPostRep{} + return &this +} + +// GetPublicKey returns the PublicKey field value if set, zero value otherwise. +func (o *GenerateWarehouseDestinationKeyPairPostRep) GetPublicKey() string { + if o == nil || o.PublicKey == nil { + var ret string + return ret + } + return *o.PublicKey +} + +// GetPublicKeyOk returns a tuple with the PublicKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *GenerateWarehouseDestinationKeyPairPostRep) GetPublicKeyOk() (*string, bool) { + if o == nil || o.PublicKey == nil { + return nil, false + } + return o.PublicKey, true +} + +// HasPublicKey returns a boolean if a field has been set. +func (o *GenerateWarehouseDestinationKeyPairPostRep) HasPublicKey() bool { + if o != nil && o.PublicKey != nil { + return true + } + + return false +} + +// SetPublicKey gets a reference to the given string and assigns it to the PublicKey field. +func (o *GenerateWarehouseDestinationKeyPairPostRep) SetPublicKey(v string) { + o.PublicKey = &v +} + +// GetPublicKeyPkcs8 returns the PublicKeyPkcs8 field value if set, zero value otherwise. +func (o *GenerateWarehouseDestinationKeyPairPostRep) GetPublicKeyPkcs8() string { + if o == nil || o.PublicKeyPkcs8 == nil { + var ret string + return ret + } + return *o.PublicKeyPkcs8 +} + +// GetPublicKeyPkcs8Ok returns a tuple with the PublicKeyPkcs8 field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *GenerateWarehouseDestinationKeyPairPostRep) GetPublicKeyPkcs8Ok() (*string, bool) { + if o == nil || o.PublicKeyPkcs8 == nil { + return nil, false + } + return o.PublicKeyPkcs8, true +} + +// HasPublicKeyPkcs8 returns a boolean if a field has been set. +func (o *GenerateWarehouseDestinationKeyPairPostRep) HasPublicKeyPkcs8() bool { + if o != nil && o.PublicKeyPkcs8 != nil { + return true + } + + return false +} + +// SetPublicKeyPkcs8 gets a reference to the given string and assigns it to the PublicKeyPkcs8 field. +func (o *GenerateWarehouseDestinationKeyPairPostRep) SetPublicKeyPkcs8(v string) { + o.PublicKeyPkcs8 = &v +} + +func (o GenerateWarehouseDestinationKeyPairPostRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.PublicKey != nil { + toSerialize["public_key"] = o.PublicKey + } + if o.PublicKeyPkcs8 != nil { + toSerialize["public_key_pkcs8"] = o.PublicKeyPkcs8 + } + return json.Marshal(toSerialize) +} + +type NullableGenerateWarehouseDestinationKeyPairPostRep struct { + value *GenerateWarehouseDestinationKeyPairPostRep + isSet bool +} + +func (v NullableGenerateWarehouseDestinationKeyPairPostRep) Get() *GenerateWarehouseDestinationKeyPairPostRep { + return v.value +} + +func (v *NullableGenerateWarehouseDestinationKeyPairPostRep) Set(val *GenerateWarehouseDestinationKeyPairPostRep) { + v.value = val + v.isSet = true +} + +func (v NullableGenerateWarehouseDestinationKeyPairPostRep) IsSet() bool { + return v.isSet +} + +func (v *NullableGenerateWarehouseDestinationKeyPairPostRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableGenerateWarehouseDestinationKeyPairPostRep(val *GenerateWarehouseDestinationKeyPairPostRep) *NullableGenerateWarehouseDestinationKeyPairPostRep { + return &NullableGenerateWarehouseDestinationKeyPairPostRep{value: val, isSet: true} +} + +func (v NullableGenerateWarehouseDestinationKeyPairPostRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableGenerateWarehouseDestinationKeyPairPostRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_get_announcements_public_200_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_get_announcements_public_200_response.go new file mode 100644 index 00000000..dcf055ab --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_get_announcements_public_200_response.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// GetAnnouncementsPublic200Response struct for GetAnnouncementsPublic200Response +type GetAnnouncementsPublic200Response struct { + Items []AnnouncementResponse `json:"items"` + Links AnnouncementPaginatedLinks `json:"_links"` +} + +// NewGetAnnouncementsPublic200Response instantiates a new GetAnnouncementsPublic200Response object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewGetAnnouncementsPublic200Response(items []AnnouncementResponse, links AnnouncementPaginatedLinks) *GetAnnouncementsPublic200Response { + this := GetAnnouncementsPublic200Response{} + this.Items = items + this.Links = links + return &this +} + +// NewGetAnnouncementsPublic200ResponseWithDefaults instantiates a new GetAnnouncementsPublic200Response object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewGetAnnouncementsPublic200ResponseWithDefaults() *GetAnnouncementsPublic200Response { + this := GetAnnouncementsPublic200Response{} + return &this +} + +// GetItems returns the Items field value +func (o *GetAnnouncementsPublic200Response) GetItems() []AnnouncementResponse { + if o == nil { + var ret []AnnouncementResponse + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *GetAnnouncementsPublic200Response) GetItemsOk() ([]AnnouncementResponse, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *GetAnnouncementsPublic200Response) SetItems(v []AnnouncementResponse) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *GetAnnouncementsPublic200Response) GetLinks() AnnouncementPaginatedLinks { + if o == nil { + var ret AnnouncementPaginatedLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *GetAnnouncementsPublic200Response) GetLinksOk() (*AnnouncementPaginatedLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *GetAnnouncementsPublic200Response) SetLinks(v AnnouncementPaginatedLinks) { + o.Links = v +} + +func (o GetAnnouncementsPublic200Response) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableGetAnnouncementsPublic200Response struct { + value *GetAnnouncementsPublic200Response + isSet bool +} + +func (v NullableGetAnnouncementsPublic200Response) Get() *GetAnnouncementsPublic200Response { + return v.value +} + +func (v *NullableGetAnnouncementsPublic200Response) Set(val *GetAnnouncementsPublic200Response) { + v.value = val + v.isSet = true +} + +func (v NullableGetAnnouncementsPublic200Response) IsSet() bool { + return v.isSet +} + +func (v *NullableGetAnnouncementsPublic200Response) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableGetAnnouncementsPublic200Response(val *GetAnnouncementsPublic200Response) *NullableGetAnnouncementsPublic200Response { + return &NullableGetAnnouncementsPublic200Response{value: val, isSet: true} +} + +func (v NullableGetAnnouncementsPublic200Response) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableGetAnnouncementsPublic200Response) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_header_items.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_header_items.go new file mode 100644 index 00000000..e06679e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_header_items.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HeaderItems struct for HeaderItems +type HeaderItems struct { + Name *string `json:"name,omitempty"` + Value *string `json:"value,omitempty"` +} + +// NewHeaderItems instantiates a new HeaderItems object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHeaderItems() *HeaderItems { + this := HeaderItems{} + return &this +} + +// NewHeaderItemsWithDefaults instantiates a new HeaderItems object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHeaderItemsWithDefaults() *HeaderItems { + this := HeaderItems{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *HeaderItems) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HeaderItems) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *HeaderItems) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *HeaderItems) SetName(v string) { + o.Name = &v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *HeaderItems) GetValue() string { + if o == nil || o.Value == nil { + var ret string + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HeaderItems) GetValueOk() (*string, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *HeaderItems) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given string and assigns it to the Value field. +func (o *HeaderItems) SetValue(v string) { + o.Value = &v +} + +func (o HeaderItems) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableHeaderItems struct { + value *HeaderItems + isSet bool +} + +func (v NullableHeaderItems) Get() *HeaderItems { + return v.value +} + +func (v *NullableHeaderItems) Set(val *HeaderItems) { + v.value = val + v.isSet = true +} + +func (v NullableHeaderItems) IsSet() bool { + return v.isSet +} + +func (v *NullableHeaderItems) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHeaderItems(val *HeaderItems) *NullableHeaderItems { + return &NullableHeaderItems{value: val, isSet: true} +} + +func (v NullableHeaderItems) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHeaderItems) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_hmac_signature.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_hmac_signature.go new file mode 100644 index 00000000..eba3f1bc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_hmac_signature.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HMACSignature struct for HMACSignature +type HMACSignature struct { + HeaderName *string `json:"headerName,omitempty"` + HmacSecretFormVariableKey *string `json:"hmacSecretFormVariableKey,omitempty"` +} + +// NewHMACSignature instantiates a new HMACSignature object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHMACSignature() *HMACSignature { + this := HMACSignature{} + return &this +} + +// NewHMACSignatureWithDefaults instantiates a new HMACSignature object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHMACSignatureWithDefaults() *HMACSignature { + this := HMACSignature{} + return &this +} + +// GetHeaderName returns the HeaderName field value if set, zero value otherwise. +func (o *HMACSignature) GetHeaderName() string { + if o == nil || o.HeaderName == nil { + var ret string + return ret + } + return *o.HeaderName +} + +// GetHeaderNameOk returns a tuple with the HeaderName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HMACSignature) GetHeaderNameOk() (*string, bool) { + if o == nil || o.HeaderName == nil { + return nil, false + } + return o.HeaderName, true +} + +// HasHeaderName returns a boolean if a field has been set. +func (o *HMACSignature) HasHeaderName() bool { + if o != nil && o.HeaderName != nil { + return true + } + + return false +} + +// SetHeaderName gets a reference to the given string and assigns it to the HeaderName field. +func (o *HMACSignature) SetHeaderName(v string) { + o.HeaderName = &v +} + +// GetHmacSecretFormVariableKey returns the HmacSecretFormVariableKey field value if set, zero value otherwise. +func (o *HMACSignature) GetHmacSecretFormVariableKey() string { + if o == nil || o.HmacSecretFormVariableKey == nil { + var ret string + return ret + } + return *o.HmacSecretFormVariableKey +} + +// GetHmacSecretFormVariableKeyOk returns a tuple with the HmacSecretFormVariableKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HMACSignature) GetHmacSecretFormVariableKeyOk() (*string, bool) { + if o == nil || o.HmacSecretFormVariableKey == nil { + return nil, false + } + return o.HmacSecretFormVariableKey, true +} + +// HasHmacSecretFormVariableKey returns a boolean if a field has been set. +func (o *HMACSignature) HasHmacSecretFormVariableKey() bool { + if o != nil && o.HmacSecretFormVariableKey != nil { + return true + } + + return false +} + +// SetHmacSecretFormVariableKey gets a reference to the given string and assigns it to the HmacSecretFormVariableKey field. +func (o *HMACSignature) SetHmacSecretFormVariableKey(v string) { + o.HmacSecretFormVariableKey = &v +} + +func (o HMACSignature) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.HeaderName != nil { + toSerialize["headerName"] = o.HeaderName + } + if o.HmacSecretFormVariableKey != nil { + toSerialize["hmacSecretFormVariableKey"] = o.HmacSecretFormVariableKey + } + return json.Marshal(toSerialize) +} + +type NullableHMACSignature struct { + value *HMACSignature + isSet bool +} + +func (v NullableHMACSignature) Get() *HMACSignature { + return v.value +} + +func (v *NullableHMACSignature) Set(val *HMACSignature) { + v.value = val + v.isSet = true +} + +func (v NullableHMACSignature) IsSet() bool { + return v.isSet +} + +func (v *NullableHMACSignature) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHMACSignature(val *HMACSignature) *NullableHMACSignature { + return &NullableHMACSignature{value: val, isSet: true} +} + +func (v NullableHMACSignature) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHMACSignature) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_detail_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_detail_rep.go new file mode 100644 index 00000000..6033d90d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_detail_rep.go @@ -0,0 +1,364 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HoldoutDetailRep struct for HoldoutDetailRep +type HoldoutDetailRep struct { + Id string `json:"_id"` + Status string `json:"status"` + Description *string `json:"description,omitempty"` + // The percentage of traffic allocated to this holdout. + HoldoutAmount string `json:"holdoutAmount"` + // Indicates if the holdout experiment is running and if any related experiments are running. + IsDirty *bool `json:"isDirty,omitempty"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` + BaseExperiment Experiment `json:"baseExperiment"` + RelatedExperiments []Experiment `json:"relatedExperiments,omitempty"` +} + +// NewHoldoutDetailRep instantiates a new HoldoutDetailRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHoldoutDetailRep(id string, status string, holdoutAmount string, createdAt int64, updatedAt int64, baseExperiment Experiment) *HoldoutDetailRep { + this := HoldoutDetailRep{} + this.Id = id + this.Status = status + this.HoldoutAmount = holdoutAmount + this.CreatedAt = createdAt + this.UpdatedAt = updatedAt + this.BaseExperiment = baseExperiment + return &this +} + +// NewHoldoutDetailRepWithDefaults instantiates a new HoldoutDetailRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHoldoutDetailRepWithDefaults() *HoldoutDetailRep { + this := HoldoutDetailRep{} + return &this +} + +// GetId returns the Id field value +func (o *HoldoutDetailRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *HoldoutDetailRep) SetId(v string) { + o.Id = v +} + +// GetStatus returns the Status field value +func (o *HoldoutDetailRep) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *HoldoutDetailRep) SetStatus(v string) { + o.Status = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *HoldoutDetailRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *HoldoutDetailRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *HoldoutDetailRep) SetDescription(v string) { + o.Description = &v +} + +// GetHoldoutAmount returns the HoldoutAmount field value +func (o *HoldoutDetailRep) GetHoldoutAmount() string { + if o == nil { + var ret string + return ret + } + + return o.HoldoutAmount +} + +// GetHoldoutAmountOk returns a tuple with the HoldoutAmount field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetHoldoutAmountOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.HoldoutAmount, true +} + +// SetHoldoutAmount sets field value +func (o *HoldoutDetailRep) SetHoldoutAmount(v string) { + o.HoldoutAmount = v +} + +// GetIsDirty returns the IsDirty field value if set, zero value otherwise. +func (o *HoldoutDetailRep) GetIsDirty() bool { + if o == nil || o.IsDirty == nil { + var ret bool + return ret + } + return *o.IsDirty +} + +// GetIsDirtyOk returns a tuple with the IsDirty field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetIsDirtyOk() (*bool, bool) { + if o == nil || o.IsDirty == nil { + return nil, false + } + return o.IsDirty, true +} + +// HasIsDirty returns a boolean if a field has been set. +func (o *HoldoutDetailRep) HasIsDirty() bool { + if o != nil && o.IsDirty != nil { + return true + } + + return false +} + +// SetIsDirty gets a reference to the given bool and assigns it to the IsDirty field. +func (o *HoldoutDetailRep) SetIsDirty(v bool) { + o.IsDirty = &v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *HoldoutDetailRep) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *HoldoutDetailRep) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetUpdatedAt returns the UpdatedAt field value +func (o *HoldoutDetailRep) GetUpdatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.UpdatedAt +} + +// GetUpdatedAtOk returns a tuple with the UpdatedAt field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetUpdatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.UpdatedAt, true +} + +// SetUpdatedAt sets field value +func (o *HoldoutDetailRep) SetUpdatedAt(v int64) { + o.UpdatedAt = v +} + +// GetBaseExperiment returns the BaseExperiment field value +func (o *HoldoutDetailRep) GetBaseExperiment() Experiment { + if o == nil { + var ret Experiment + return ret + } + + return o.BaseExperiment +} + +// GetBaseExperimentOk returns a tuple with the BaseExperiment field value +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetBaseExperimentOk() (*Experiment, bool) { + if o == nil { + return nil, false + } + return &o.BaseExperiment, true +} + +// SetBaseExperiment sets field value +func (o *HoldoutDetailRep) SetBaseExperiment(v Experiment) { + o.BaseExperiment = v +} + +// GetRelatedExperiments returns the RelatedExperiments field value if set, zero value otherwise. +func (o *HoldoutDetailRep) GetRelatedExperiments() []Experiment { + if o == nil || o.RelatedExperiments == nil { + var ret []Experiment + return ret + } + return o.RelatedExperiments +} + +// GetRelatedExperimentsOk returns a tuple with the RelatedExperiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutDetailRep) GetRelatedExperimentsOk() ([]Experiment, bool) { + if o == nil || o.RelatedExperiments == nil { + return nil, false + } + return o.RelatedExperiments, true +} + +// HasRelatedExperiments returns a boolean if a field has been set. +func (o *HoldoutDetailRep) HasRelatedExperiments() bool { + if o != nil && o.RelatedExperiments != nil { + return true + } + + return false +} + +// SetRelatedExperiments gets a reference to the given []Experiment and assigns it to the RelatedExperiments field. +func (o *HoldoutDetailRep) SetRelatedExperiments(v []Experiment) { + o.RelatedExperiments = v +} + +func (o HoldoutDetailRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["status"] = o.Status + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["holdoutAmount"] = o.HoldoutAmount + } + if o.IsDirty != nil { + toSerialize["isDirty"] = o.IsDirty + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if true { + toSerialize["updatedAt"] = o.UpdatedAt + } + if true { + toSerialize["baseExperiment"] = o.BaseExperiment + } + if o.RelatedExperiments != nil { + toSerialize["relatedExperiments"] = o.RelatedExperiments + } + return json.Marshal(toSerialize) +} + +type NullableHoldoutDetailRep struct { + value *HoldoutDetailRep + isSet bool +} + +func (v NullableHoldoutDetailRep) Get() *HoldoutDetailRep { + return v.value +} + +func (v *NullableHoldoutDetailRep) Set(val *HoldoutDetailRep) { + v.value = val + v.isSet = true +} + +func (v NullableHoldoutDetailRep) IsSet() bool { + return v.isSet +} + +func (v *NullableHoldoutDetailRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHoldoutDetailRep(val *HoldoutDetailRep) *NullableHoldoutDetailRep { + return &NullableHoldoutDetailRep{value: val, isSet: true} +} + +func (v NullableHoldoutDetailRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHoldoutDetailRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_patch_input.go new file mode 100644 index 00000000..5123208c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_patch_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HoldoutPatchInput struct for HoldoutPatchInput +type HoldoutPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewHoldoutPatchInput instantiates a new HoldoutPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHoldoutPatchInput(instructions []map[string]interface{}) *HoldoutPatchInput { + this := HoldoutPatchInput{} + this.Instructions = instructions + return &this +} + +// NewHoldoutPatchInputWithDefaults instantiates a new HoldoutPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHoldoutPatchInputWithDefaults() *HoldoutPatchInput { + this := HoldoutPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *HoldoutPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *HoldoutPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *HoldoutPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *HoldoutPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *HoldoutPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *HoldoutPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o HoldoutPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableHoldoutPatchInput struct { + value *HoldoutPatchInput + isSet bool +} + +func (v NullableHoldoutPatchInput) Get() *HoldoutPatchInput { + return v.value +} + +func (v *NullableHoldoutPatchInput) Set(val *HoldoutPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableHoldoutPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableHoldoutPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHoldoutPatchInput(val *HoldoutPatchInput) *NullableHoldoutPatchInput { + return &NullableHoldoutPatchInput{value: val, isSet: true} +} + +func (v NullableHoldoutPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHoldoutPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_post_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_post_request.go new file mode 100644 index 00000000..223b0f71 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_post_request.go @@ -0,0 +1,450 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HoldoutPostRequest struct for HoldoutPostRequest +type HoldoutPostRequest struct { + // A human-friendly name for the holdout + Name *string `json:"name,omitempty"` + // A key that identifies the holdout + Key *string `json:"key,omitempty"` + // Description of the holdout + Description *string `json:"description,omitempty"` + // The chosen randomization unit for the holdout base experiment + Randomizationunit *string `json:"randomizationunit,omitempty"` + // The attributes that the holdout iteration's results can be sliced by + Attributes []string `json:"attributes,omitempty"` + // Audience allocation for the holdout + Holdoutamount *string `json:"holdoutamount,omitempty"` + // The key of the primary metric for this holdout + Primarymetrickey *string `json:"primarymetrickey,omitempty"` + // Details on the metrics for this experiment + Metrics []MetricInput `json:"metrics,omitempty"` + // The key of the flag that the holdout is dependent on + Prerequisiteflagkey *string `json:"prerequisiteflagkey,omitempty"` + // Maintainer id + MaintainerId *string `json:"maintainerId,omitempty"` +} + +// NewHoldoutPostRequest instantiates a new HoldoutPostRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHoldoutPostRequest() *HoldoutPostRequest { + this := HoldoutPostRequest{} + return &this +} + +// NewHoldoutPostRequestWithDefaults instantiates a new HoldoutPostRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHoldoutPostRequestWithDefaults() *HoldoutPostRequest { + this := HoldoutPostRequest{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *HoldoutPostRequest) SetName(v string) { + o.Name = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *HoldoutPostRequest) SetKey(v string) { + o.Key = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *HoldoutPostRequest) SetDescription(v string) { + o.Description = &v +} + +// GetRandomizationunit returns the Randomizationunit field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetRandomizationunit() string { + if o == nil || o.Randomizationunit == nil { + var ret string + return ret + } + return *o.Randomizationunit +} + +// GetRandomizationunitOk returns a tuple with the Randomizationunit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetRandomizationunitOk() (*string, bool) { + if o == nil || o.Randomizationunit == nil { + return nil, false + } + return o.Randomizationunit, true +} + +// HasRandomizationunit returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasRandomizationunit() bool { + if o != nil && o.Randomizationunit != nil { + return true + } + + return false +} + +// SetRandomizationunit gets a reference to the given string and assigns it to the Randomizationunit field. +func (o *HoldoutPostRequest) SetRandomizationunit(v string) { + o.Randomizationunit = &v +} + +// GetAttributes returns the Attributes field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetAttributes() []string { + if o == nil || o.Attributes == nil { + var ret []string + return ret + } + return o.Attributes +} + +// GetAttributesOk returns a tuple with the Attributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetAttributesOk() ([]string, bool) { + if o == nil || o.Attributes == nil { + return nil, false + } + return o.Attributes, true +} + +// HasAttributes returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasAttributes() bool { + if o != nil && o.Attributes != nil { + return true + } + + return false +} + +// SetAttributes gets a reference to the given []string and assigns it to the Attributes field. +func (o *HoldoutPostRequest) SetAttributes(v []string) { + o.Attributes = v +} + +// GetHoldoutamount returns the Holdoutamount field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetHoldoutamount() string { + if o == nil || o.Holdoutamount == nil { + var ret string + return ret + } + return *o.Holdoutamount +} + +// GetHoldoutamountOk returns a tuple with the Holdoutamount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetHoldoutamountOk() (*string, bool) { + if o == nil || o.Holdoutamount == nil { + return nil, false + } + return o.Holdoutamount, true +} + +// HasHoldoutamount returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasHoldoutamount() bool { + if o != nil && o.Holdoutamount != nil { + return true + } + + return false +} + +// SetHoldoutamount gets a reference to the given string and assigns it to the Holdoutamount field. +func (o *HoldoutPostRequest) SetHoldoutamount(v string) { + o.Holdoutamount = &v +} + +// GetPrimarymetrickey returns the Primarymetrickey field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetPrimarymetrickey() string { + if o == nil || o.Primarymetrickey == nil { + var ret string + return ret + } + return *o.Primarymetrickey +} + +// GetPrimarymetrickeyOk returns a tuple with the Primarymetrickey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetPrimarymetrickeyOk() (*string, bool) { + if o == nil || o.Primarymetrickey == nil { + return nil, false + } + return o.Primarymetrickey, true +} + +// HasPrimarymetrickey returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasPrimarymetrickey() bool { + if o != nil && o.Primarymetrickey != nil { + return true + } + + return false +} + +// SetPrimarymetrickey gets a reference to the given string and assigns it to the Primarymetrickey field. +func (o *HoldoutPostRequest) SetPrimarymetrickey(v string) { + o.Primarymetrickey = &v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetMetrics() []MetricInput { + if o == nil || o.Metrics == nil { + var ret []MetricInput + return ret + } + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetMetricsOk() ([]MetricInput, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given []MetricInput and assigns it to the Metrics field. +func (o *HoldoutPostRequest) SetMetrics(v []MetricInput) { + o.Metrics = v +} + +// GetPrerequisiteflagkey returns the Prerequisiteflagkey field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetPrerequisiteflagkey() string { + if o == nil || o.Prerequisiteflagkey == nil { + var ret string + return ret + } + return *o.Prerequisiteflagkey +} + +// GetPrerequisiteflagkeyOk returns a tuple with the Prerequisiteflagkey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetPrerequisiteflagkeyOk() (*string, bool) { + if o == nil || o.Prerequisiteflagkey == nil { + return nil, false + } + return o.Prerequisiteflagkey, true +} + +// HasPrerequisiteflagkey returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasPrerequisiteflagkey() bool { + if o != nil && o.Prerequisiteflagkey != nil { + return true + } + + return false +} + +// SetPrerequisiteflagkey gets a reference to the given string and assigns it to the Prerequisiteflagkey field. +func (o *HoldoutPostRequest) SetPrerequisiteflagkey(v string) { + o.Prerequisiteflagkey = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *HoldoutPostRequest) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutPostRequest) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *HoldoutPostRequest) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *HoldoutPostRequest) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +func (o HoldoutPostRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Randomizationunit != nil { + toSerialize["randomizationunit"] = o.Randomizationunit + } + if o.Attributes != nil { + toSerialize["attributes"] = o.Attributes + } + if o.Holdoutamount != nil { + toSerialize["holdoutamount"] = o.Holdoutamount + } + if o.Primarymetrickey != nil { + toSerialize["primarymetrickey"] = o.Primarymetrickey + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + if o.Prerequisiteflagkey != nil { + toSerialize["prerequisiteflagkey"] = o.Prerequisiteflagkey + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + return json.Marshal(toSerialize) +} + +type NullableHoldoutPostRequest struct { + value *HoldoutPostRequest + isSet bool +} + +func (v NullableHoldoutPostRequest) Get() *HoldoutPostRequest { + return v.value +} + +func (v *NullableHoldoutPostRequest) Set(val *HoldoutPostRequest) { + v.value = val + v.isSet = true +} + +func (v NullableHoldoutPostRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableHoldoutPostRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHoldoutPostRequest(val *HoldoutPostRequest) *NullableHoldoutPostRequest { + return &NullableHoldoutPostRequest{value: val, isSet: true} +} + +func (v NullableHoldoutPostRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHoldoutPostRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_rep.go new file mode 100644 index 00000000..5e020ad9 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdout_rep.go @@ -0,0 +1,327 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HoldoutRep struct for HoldoutRep +type HoldoutRep struct { + Id string `json:"_id"` + Status string `json:"status"` + Description *string `json:"description,omitempty"` + // The percentage of traffic allocated to this holdout. + HoldoutAmount string `json:"holdoutAmount"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` + BaseExperiment Experiment `json:"baseExperiment"` + Experiments []RelatedExperimentRep `json:"experiments,omitempty"` +} + +// NewHoldoutRep instantiates a new HoldoutRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHoldoutRep(id string, status string, holdoutAmount string, createdAt int64, updatedAt int64, baseExperiment Experiment) *HoldoutRep { + this := HoldoutRep{} + this.Id = id + this.Status = status + this.HoldoutAmount = holdoutAmount + this.CreatedAt = createdAt + this.UpdatedAt = updatedAt + this.BaseExperiment = baseExperiment + return &this +} + +// NewHoldoutRepWithDefaults instantiates a new HoldoutRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHoldoutRepWithDefaults() *HoldoutRep { + this := HoldoutRep{} + return &this +} + +// GetId returns the Id field value +func (o *HoldoutRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *HoldoutRep) SetId(v string) { + o.Id = v +} + +// GetStatus returns the Status field value +func (o *HoldoutRep) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *HoldoutRep) SetStatus(v string) { + o.Status = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *HoldoutRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *HoldoutRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *HoldoutRep) SetDescription(v string) { + o.Description = &v +} + +// GetHoldoutAmount returns the HoldoutAmount field value +func (o *HoldoutRep) GetHoldoutAmount() string { + if o == nil { + var ret string + return ret + } + + return o.HoldoutAmount +} + +// GetHoldoutAmountOk returns a tuple with the HoldoutAmount field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetHoldoutAmountOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.HoldoutAmount, true +} + +// SetHoldoutAmount sets field value +func (o *HoldoutRep) SetHoldoutAmount(v string) { + o.HoldoutAmount = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *HoldoutRep) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *HoldoutRep) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetUpdatedAt returns the UpdatedAt field value +func (o *HoldoutRep) GetUpdatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.UpdatedAt +} + +// GetUpdatedAtOk returns a tuple with the UpdatedAt field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetUpdatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.UpdatedAt, true +} + +// SetUpdatedAt sets field value +func (o *HoldoutRep) SetUpdatedAt(v int64) { + o.UpdatedAt = v +} + +// GetBaseExperiment returns the BaseExperiment field value +func (o *HoldoutRep) GetBaseExperiment() Experiment { + if o == nil { + var ret Experiment + return ret + } + + return o.BaseExperiment +} + +// GetBaseExperimentOk returns a tuple with the BaseExperiment field value +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetBaseExperimentOk() (*Experiment, bool) { + if o == nil { + return nil, false + } + return &o.BaseExperiment, true +} + +// SetBaseExperiment sets field value +func (o *HoldoutRep) SetBaseExperiment(v Experiment) { + o.BaseExperiment = v +} + +// GetExperiments returns the Experiments field value if set, zero value otherwise. +func (o *HoldoutRep) GetExperiments() []RelatedExperimentRep { + if o == nil || o.Experiments == nil { + var ret []RelatedExperimentRep + return ret + } + return o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutRep) GetExperimentsOk() ([]RelatedExperimentRep, bool) { + if o == nil || o.Experiments == nil { + return nil, false + } + return o.Experiments, true +} + +// HasExperiments returns a boolean if a field has been set. +func (o *HoldoutRep) HasExperiments() bool { + if o != nil && o.Experiments != nil { + return true + } + + return false +} + +// SetExperiments gets a reference to the given []RelatedExperimentRep and assigns it to the Experiments field. +func (o *HoldoutRep) SetExperiments(v []RelatedExperimentRep) { + o.Experiments = v +} + +func (o HoldoutRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["status"] = o.Status + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["holdoutAmount"] = o.HoldoutAmount + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if true { + toSerialize["updatedAt"] = o.UpdatedAt + } + if true { + toSerialize["baseExperiment"] = o.BaseExperiment + } + if o.Experiments != nil { + toSerialize["experiments"] = o.Experiments + } + return json.Marshal(toSerialize) +} + +type NullableHoldoutRep struct { + value *HoldoutRep + isSet bool +} + +func (v NullableHoldoutRep) Get() *HoldoutRep { + return v.value +} + +func (v *NullableHoldoutRep) Set(val *HoldoutRep) { + v.value = val + v.isSet = true +} + +func (v NullableHoldoutRep) IsSet() bool { + return v.isSet +} + +func (v *NullableHoldoutRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHoldoutRep(val *HoldoutRep) *NullableHoldoutRep { + return &NullableHoldoutRep{value: val, isSet: true} +} + +func (v NullableHoldoutRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHoldoutRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_holdouts_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdouts_collection_rep.go new file mode 100644 index 00000000..1d398160 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_holdouts_collection_rep.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HoldoutsCollectionRep struct for HoldoutsCollectionRep +type HoldoutsCollectionRep struct { + Items []SimpleHoldoutRep `json:"items,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The total number of holdouts in this project and environment. + TotalCount *int32 `json:"total_count,omitempty"` +} + +// NewHoldoutsCollectionRep instantiates a new HoldoutsCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHoldoutsCollectionRep() *HoldoutsCollectionRep { + this := HoldoutsCollectionRep{} + return &this +} + +// NewHoldoutsCollectionRepWithDefaults instantiates a new HoldoutsCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHoldoutsCollectionRepWithDefaults() *HoldoutsCollectionRep { + this := HoldoutsCollectionRep{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *HoldoutsCollectionRep) GetItems() []SimpleHoldoutRep { + if o == nil || o.Items == nil { + var ret []SimpleHoldoutRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutsCollectionRep) GetItemsOk() ([]SimpleHoldoutRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *HoldoutsCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []SimpleHoldoutRep and assigns it to the Items field. +func (o *HoldoutsCollectionRep) SetItems(v []SimpleHoldoutRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *HoldoutsCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutsCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *HoldoutsCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *HoldoutsCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *HoldoutsCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HoldoutsCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *HoldoutsCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *HoldoutsCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o HoldoutsCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["total_count"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableHoldoutsCollectionRep struct { + value *HoldoutsCollectionRep + isSet bool +} + +func (v NullableHoldoutsCollectionRep) Get() *HoldoutsCollectionRep { + return v.value +} + +func (v *NullableHoldoutsCollectionRep) Set(val *HoldoutsCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableHoldoutsCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableHoldoutsCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHoldoutsCollectionRep(val *HoldoutsCollectionRep) *NullableHoldoutsCollectionRep { + return &NullableHoldoutsCollectionRep{value: val, isSet: true} +} + +func (v NullableHoldoutsCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHoldoutsCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_hunk_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_hunk_rep.go new file mode 100644 index 00000000..f8b6f732 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_hunk_rep.go @@ -0,0 +1,258 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// HunkRep struct for HunkRep +type HunkRep struct { + // Line number of beginning of code reference hunk + StartingLineNumber int32 `json:"startingLineNumber"` + // Contextual lines of code that include the referenced feature flag + Lines *string `json:"lines,omitempty"` + // The project key + ProjKey *string `json:"projKey,omitempty"` + // The feature flag key + FlagKey *string `json:"flagKey,omitempty"` + // An array of flag key aliases + Aliases []string `json:"aliases,omitempty"` +} + +// NewHunkRep instantiates a new HunkRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewHunkRep(startingLineNumber int32) *HunkRep { + this := HunkRep{} + this.StartingLineNumber = startingLineNumber + return &this +} + +// NewHunkRepWithDefaults instantiates a new HunkRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewHunkRepWithDefaults() *HunkRep { + this := HunkRep{} + return &this +} + +// GetStartingLineNumber returns the StartingLineNumber field value +func (o *HunkRep) GetStartingLineNumber() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.StartingLineNumber +} + +// GetStartingLineNumberOk returns a tuple with the StartingLineNumber field value +// and a boolean to check if the value has been set. +func (o *HunkRep) GetStartingLineNumberOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.StartingLineNumber, true +} + +// SetStartingLineNumber sets field value +func (o *HunkRep) SetStartingLineNumber(v int32) { + o.StartingLineNumber = v +} + +// GetLines returns the Lines field value if set, zero value otherwise. +func (o *HunkRep) GetLines() string { + if o == nil || o.Lines == nil { + var ret string + return ret + } + return *o.Lines +} + +// GetLinesOk returns a tuple with the Lines field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HunkRep) GetLinesOk() (*string, bool) { + if o == nil || o.Lines == nil { + return nil, false + } + return o.Lines, true +} + +// HasLines returns a boolean if a field has been set. +func (o *HunkRep) HasLines() bool { + if o != nil && o.Lines != nil { + return true + } + + return false +} + +// SetLines gets a reference to the given string and assigns it to the Lines field. +func (o *HunkRep) SetLines(v string) { + o.Lines = &v +} + +// GetProjKey returns the ProjKey field value if set, zero value otherwise. +func (o *HunkRep) GetProjKey() string { + if o == nil || o.ProjKey == nil { + var ret string + return ret + } + return *o.ProjKey +} + +// GetProjKeyOk returns a tuple with the ProjKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HunkRep) GetProjKeyOk() (*string, bool) { + if o == nil || o.ProjKey == nil { + return nil, false + } + return o.ProjKey, true +} + +// HasProjKey returns a boolean if a field has been set. +func (o *HunkRep) HasProjKey() bool { + if o != nil && o.ProjKey != nil { + return true + } + + return false +} + +// SetProjKey gets a reference to the given string and assigns it to the ProjKey field. +func (o *HunkRep) SetProjKey(v string) { + o.ProjKey = &v +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +func (o *HunkRep) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HunkRep) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *HunkRep) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +func (o *HunkRep) SetFlagKey(v string) { + o.FlagKey = &v +} + +// GetAliases returns the Aliases field value if set, zero value otherwise. +func (o *HunkRep) GetAliases() []string { + if o == nil || o.Aliases == nil { + var ret []string + return ret + } + return o.Aliases +} + +// GetAliasesOk returns a tuple with the Aliases field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HunkRep) GetAliasesOk() ([]string, bool) { + if o == nil || o.Aliases == nil { + return nil, false + } + return o.Aliases, true +} + +// HasAliases returns a boolean if a field has been set. +func (o *HunkRep) HasAliases() bool { + if o != nil && o.Aliases != nil { + return true + } + + return false +} + +// SetAliases gets a reference to the given []string and assigns it to the Aliases field. +func (o *HunkRep) SetAliases(v []string) { + o.Aliases = v +} + +func (o HunkRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["startingLineNumber"] = o.StartingLineNumber + } + if o.Lines != nil { + toSerialize["lines"] = o.Lines + } + if o.ProjKey != nil { + toSerialize["projKey"] = o.ProjKey + } + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + if o.Aliases != nil { + toSerialize["aliases"] = o.Aliases + } + return json.Marshal(toSerialize) +} + +type NullableHunkRep struct { + value *HunkRep + isSet bool +} + +func (v NullableHunkRep) Get() *HunkRep { + return v.value +} + +func (v *NullableHunkRep) Set(val *HunkRep) { + v.value = val + v.isSet = true +} + +func (v NullableHunkRep) IsSet() bool { + return v.isSet +} + +func (v *NullableHunkRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableHunkRep(val *HunkRep) *NullableHunkRep { + return &NullableHunkRep{value: val, isSet: true} +} + +func (v NullableHunkRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableHunkRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_import.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_import.go new file mode 100644 index 00000000..78a46ea8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_import.go @@ -0,0 +1,296 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Import struct for Import +type Import struct { + // The import ID + Id string `json:"id"` + // The segment key + SegmentKey string `json:"segmentKey"` + CreationTime int64 `json:"creationTime"` + // The import mode used, either merge or replace + Mode string `json:"mode"` + // The import status + Status string `json:"status"` + // The imported files and their status + Files []FileRep `json:"files,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewImport instantiates a new Import object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewImport(id string, segmentKey string, creationTime int64, mode string, status string, links map[string]Link) *Import { + this := Import{} + this.Id = id + this.SegmentKey = segmentKey + this.CreationTime = creationTime + this.Mode = mode + this.Status = status + this.Links = links + return &this +} + +// NewImportWithDefaults instantiates a new Import object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewImportWithDefaults() *Import { + this := Import{} + return &this +} + +// GetId returns the Id field value +func (o *Import) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Import) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Import) SetId(v string) { + o.Id = v +} + +// GetSegmentKey returns the SegmentKey field value +func (o *Import) GetSegmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.SegmentKey +} + +// GetSegmentKeyOk returns a tuple with the SegmentKey field value +// and a boolean to check if the value has been set. +func (o *Import) GetSegmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.SegmentKey, true +} + +// SetSegmentKey sets field value +func (o *Import) SetSegmentKey(v string) { + o.SegmentKey = v +} + +// GetCreationTime returns the CreationTime field value +func (o *Import) GetCreationTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationTime +} + +// GetCreationTimeOk returns a tuple with the CreationTime field value +// and a boolean to check if the value has been set. +func (o *Import) GetCreationTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationTime, true +} + +// SetCreationTime sets field value +func (o *Import) SetCreationTime(v int64) { + o.CreationTime = v +} + +// GetMode returns the Mode field value +func (o *Import) GetMode() string { + if o == nil { + var ret string + return ret + } + + return o.Mode +} + +// GetModeOk returns a tuple with the Mode field value +// and a boolean to check if the value has been set. +func (o *Import) GetModeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Mode, true +} + +// SetMode sets field value +func (o *Import) SetMode(v string) { + o.Mode = v +} + +// GetStatus returns the Status field value +func (o *Import) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *Import) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *Import) SetStatus(v string) { + o.Status = v +} + +// GetFiles returns the Files field value if set, zero value otherwise. +func (o *Import) GetFiles() []FileRep { + if o == nil || o.Files == nil { + var ret []FileRep + return ret + } + return o.Files +} + +// GetFilesOk returns a tuple with the Files field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Import) GetFilesOk() ([]FileRep, bool) { + if o == nil || o.Files == nil { + return nil, false + } + return o.Files, true +} + +// HasFiles returns a boolean if a field has been set. +func (o *Import) HasFiles() bool { + if o != nil && o.Files != nil { + return true + } + + return false +} + +// SetFiles gets a reference to the given []FileRep and assigns it to the Files field. +func (o *Import) SetFiles(v []FileRep) { + o.Files = v +} + +// GetLinks returns the Links field value +func (o *Import) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Import) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Import) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o Import) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["segmentKey"] = o.SegmentKey + } + if true { + toSerialize["creationTime"] = o.CreationTime + } + if true { + toSerialize["mode"] = o.Mode + } + if true { + toSerialize["status"] = o.Status + } + if o.Files != nil { + toSerialize["files"] = o.Files + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableImport struct { + value *Import + isSet bool +} + +func (v NullableImport) Get() *Import { + return v.value +} + +func (v *NullableImport) Set(val *Import) { + v.value = val + v.isSet = true +} + +func (v NullableImport) IsSet() bool { + return v.isSet +} + +func (v *NullableImport) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableImport(val *Import) *NullableImport { + return &NullableImport{value: val, isSet: true} +} + +func (v NullableImport) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableImport) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_initiator_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_initiator_rep.go new file mode 100644 index 00000000..b777f5d8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_initiator_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InitiatorRep struct for InitiatorRep +type InitiatorRep struct { + // The name of the member who initiated the export + Name *string `json:"name,omitempty"` + // The email address of the member who initiated the export + Email *string `json:"email,omitempty"` +} + +// NewInitiatorRep instantiates a new InitiatorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInitiatorRep() *InitiatorRep { + this := InitiatorRep{} + return &this +} + +// NewInitiatorRepWithDefaults instantiates a new InitiatorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInitiatorRepWithDefaults() *InitiatorRep { + this := InitiatorRep{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *InitiatorRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InitiatorRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *InitiatorRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *InitiatorRep) SetName(v string) { + o.Name = &v +} + +// GetEmail returns the Email field value if set, zero value otherwise. +func (o *InitiatorRep) GetEmail() string { + if o == nil || o.Email == nil { + var ret string + return ret + } + return *o.Email +} + +// GetEmailOk returns a tuple with the Email field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InitiatorRep) GetEmailOk() (*string, bool) { + if o == nil || o.Email == nil { + return nil, false + } + return o.Email, true +} + +// HasEmail returns a boolean if a field has been set. +func (o *InitiatorRep) HasEmail() bool { + if o != nil && o.Email != nil { + return true + } + + return false +} + +// SetEmail gets a reference to the given string and assigns it to the Email field. +func (o *InitiatorRep) SetEmail(v string) { + o.Email = &v +} + +func (o InitiatorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Email != nil { + toSerialize["email"] = o.Email + } + return json.Marshal(toSerialize) +} + +type NullableInitiatorRep struct { + value *InitiatorRep + isSet bool +} + +func (v NullableInitiatorRep) Get() *InitiatorRep { + return v.value +} + +func (v *NullableInitiatorRep) Set(val *InitiatorRep) { + v.value = val + v.isSet = true +} + +func (v NullableInitiatorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableInitiatorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInitiatorRep(val *InitiatorRep) *NullableInitiatorRep { + return &NullableInitiatorRep{value: val, isSet: true} +} + +func (v NullableInitiatorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInitiatorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group.go new file mode 100644 index 00000000..83fca46f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group.go @@ -0,0 +1,374 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroup struct for InsightGroup +type InsightGroup struct { + Environment *Environment `json:"environment,omitempty"` + Scores *InsightGroupScores `json:"scores,omitempty"` + ScoreMetadata *InsightGroupCollectionScoreMetadata `json:"scoreMetadata,omitempty"` + // The insight group key + Key string `json:"key"` + // The insight group name + Name string `json:"name"` + // The project key + ProjectKey string `json:"projectKey"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + // The application keys + ApplicationKeys []string `json:"applicationKeys,omitempty"` + CreatedAt int64 `json:"createdAt"` +} + +// NewInsightGroup instantiates a new InsightGroup object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroup(key string, name string, projectKey string, environmentKey string, createdAt int64) *InsightGroup { + this := InsightGroup{} + this.Key = key + this.Name = name + this.ProjectKey = projectKey + this.EnvironmentKey = environmentKey + this.CreatedAt = createdAt + return &this +} + +// NewInsightGroupWithDefaults instantiates a new InsightGroup object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupWithDefaults() *InsightGroup { + this := InsightGroup{} + return &this +} + +// GetEnvironment returns the Environment field value if set, zero value otherwise. +func (o *InsightGroup) GetEnvironment() Environment { + if o == nil || o.Environment == nil { + var ret Environment + return ret + } + return *o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetEnvironmentOk() (*Environment, bool) { + if o == nil || o.Environment == nil { + return nil, false + } + return o.Environment, true +} + +// HasEnvironment returns a boolean if a field has been set. +func (o *InsightGroup) HasEnvironment() bool { + if o != nil && o.Environment != nil { + return true + } + + return false +} + +// SetEnvironment gets a reference to the given Environment and assigns it to the Environment field. +func (o *InsightGroup) SetEnvironment(v Environment) { + o.Environment = &v +} + +// GetScores returns the Scores field value if set, zero value otherwise. +func (o *InsightGroup) GetScores() InsightGroupScores { + if o == nil || o.Scores == nil { + var ret InsightGroupScores + return ret + } + return *o.Scores +} + +// GetScoresOk returns a tuple with the Scores field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetScoresOk() (*InsightGroupScores, bool) { + if o == nil || o.Scores == nil { + return nil, false + } + return o.Scores, true +} + +// HasScores returns a boolean if a field has been set. +func (o *InsightGroup) HasScores() bool { + if o != nil && o.Scores != nil { + return true + } + + return false +} + +// SetScores gets a reference to the given InsightGroupScores and assigns it to the Scores field. +func (o *InsightGroup) SetScores(v InsightGroupScores) { + o.Scores = &v +} + +// GetScoreMetadata returns the ScoreMetadata field value if set, zero value otherwise. +func (o *InsightGroup) GetScoreMetadata() InsightGroupCollectionScoreMetadata { + if o == nil || o.ScoreMetadata == nil { + var ret InsightGroupCollectionScoreMetadata + return ret + } + return *o.ScoreMetadata +} + +// GetScoreMetadataOk returns a tuple with the ScoreMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetScoreMetadataOk() (*InsightGroupCollectionScoreMetadata, bool) { + if o == nil || o.ScoreMetadata == nil { + return nil, false + } + return o.ScoreMetadata, true +} + +// HasScoreMetadata returns a boolean if a field has been set. +func (o *InsightGroup) HasScoreMetadata() bool { + if o != nil && o.ScoreMetadata != nil { + return true + } + + return false +} + +// SetScoreMetadata gets a reference to the given InsightGroupCollectionScoreMetadata and assigns it to the ScoreMetadata field. +func (o *InsightGroup) SetScoreMetadata(v InsightGroupCollectionScoreMetadata) { + o.ScoreMetadata = &v +} + +// GetKey returns the Key field value +func (o *InsightGroup) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *InsightGroup) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *InsightGroup) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *InsightGroup) SetName(v string) { + o.Name = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *InsightGroup) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *InsightGroup) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *InsightGroup) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *InsightGroup) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetApplicationKeys returns the ApplicationKeys field value if set, zero value otherwise. +func (o *InsightGroup) GetApplicationKeys() []string { + if o == nil || o.ApplicationKeys == nil { + var ret []string + return ret + } + return o.ApplicationKeys +} + +// GetApplicationKeysOk returns a tuple with the ApplicationKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetApplicationKeysOk() ([]string, bool) { + if o == nil || o.ApplicationKeys == nil { + return nil, false + } + return o.ApplicationKeys, true +} + +// HasApplicationKeys returns a boolean if a field has been set. +func (o *InsightGroup) HasApplicationKeys() bool { + if o != nil && o.ApplicationKeys != nil { + return true + } + + return false +} + +// SetApplicationKeys gets a reference to the given []string and assigns it to the ApplicationKeys field. +func (o *InsightGroup) SetApplicationKeys(v []string) { + o.ApplicationKeys = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *InsightGroup) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *InsightGroup) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *InsightGroup) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +func (o InsightGroup) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Environment != nil { + toSerialize["environment"] = o.Environment + } + if o.Scores != nil { + toSerialize["scores"] = o.Scores + } + if o.ScoreMetadata != nil { + toSerialize["scoreMetadata"] = o.ScoreMetadata + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.ApplicationKeys != nil { + toSerialize["applicationKeys"] = o.ApplicationKeys + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroup struct { + value *InsightGroup + isSet bool +} + +func (v NullableInsightGroup) Get() *InsightGroup { + return v.value +} + +func (v *NullableInsightGroup) Set(val *InsightGroup) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroup) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroup) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroup(val *InsightGroup) *NullableInsightGroup { + return &NullableInsightGroup{value: val, isSet: true} +} + +func (v NullableInsightGroup) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroup) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection.go new file mode 100644 index 00000000..4c5bec1e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection.go @@ -0,0 +1,249 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroupCollection struct for InsightGroupCollection +type InsightGroupCollection struct { + // The total number of insight groups + TotalCount int32 `json:"totalCount"` + // A list of insight groups + Items []InsightGroup `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + Metadata *InsightGroupCollectionMetadata `json:"metadata,omitempty"` + ScoreMetadata *InsightGroupCollectionScoreMetadata `json:"scoreMetadata,omitempty"` +} + +// NewInsightGroupCollection instantiates a new InsightGroupCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroupCollection(totalCount int32, items []InsightGroup) *InsightGroupCollection { + this := InsightGroupCollection{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewInsightGroupCollectionWithDefaults instantiates a new InsightGroupCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupCollectionWithDefaults() *InsightGroupCollection { + this := InsightGroupCollection{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *InsightGroupCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *InsightGroupCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *InsightGroupCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *InsightGroupCollection) GetItems() []InsightGroup { + if o == nil { + var ret []InsightGroup + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *InsightGroupCollection) GetItemsOk() ([]InsightGroup, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *InsightGroupCollection) SetItems(v []InsightGroup) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *InsightGroupCollection) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroupCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *InsightGroupCollection) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *InsightGroupCollection) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetMetadata returns the Metadata field value if set, zero value otherwise. +func (o *InsightGroupCollection) GetMetadata() InsightGroupCollectionMetadata { + if o == nil || o.Metadata == nil { + var ret InsightGroupCollectionMetadata + return ret + } + return *o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroupCollection) GetMetadataOk() (*InsightGroupCollectionMetadata, bool) { + if o == nil || o.Metadata == nil { + return nil, false + } + return o.Metadata, true +} + +// HasMetadata returns a boolean if a field has been set. +func (o *InsightGroupCollection) HasMetadata() bool { + if o != nil && o.Metadata != nil { + return true + } + + return false +} + +// SetMetadata gets a reference to the given InsightGroupCollectionMetadata and assigns it to the Metadata field. +func (o *InsightGroupCollection) SetMetadata(v InsightGroupCollectionMetadata) { + o.Metadata = &v +} + +// GetScoreMetadata returns the ScoreMetadata field value if set, zero value otherwise. +func (o *InsightGroupCollection) GetScoreMetadata() InsightGroupCollectionScoreMetadata { + if o == nil || o.ScoreMetadata == nil { + var ret InsightGroupCollectionScoreMetadata + return ret + } + return *o.ScoreMetadata +} + +// GetScoreMetadataOk returns a tuple with the ScoreMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroupCollection) GetScoreMetadataOk() (*InsightGroupCollectionScoreMetadata, bool) { + if o == nil || o.ScoreMetadata == nil { + return nil, false + } + return o.ScoreMetadata, true +} + +// HasScoreMetadata returns a boolean if a field has been set. +func (o *InsightGroupCollection) HasScoreMetadata() bool { + if o != nil && o.ScoreMetadata != nil { + return true + } + + return false +} + +// SetScoreMetadata gets a reference to the given InsightGroupCollectionScoreMetadata and assigns it to the ScoreMetadata field. +func (o *InsightGroupCollection) SetScoreMetadata(v InsightGroupCollectionScoreMetadata) { + o.ScoreMetadata = &v +} + +func (o InsightGroupCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Metadata != nil { + toSerialize["metadata"] = o.Metadata + } + if o.ScoreMetadata != nil { + toSerialize["scoreMetadata"] = o.ScoreMetadata + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroupCollection struct { + value *InsightGroupCollection + isSet bool +} + +func (v NullableInsightGroupCollection) Get() *InsightGroupCollection { + return v.value +} + +func (v *NullableInsightGroupCollection) Set(val *InsightGroupCollection) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroupCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroupCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroupCollection(val *InsightGroupCollection) *NullableInsightGroupCollection { + return &NullableInsightGroupCollection{value: val, isSet: true} +} + +func (v NullableInsightGroupCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroupCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_metadata.go new file mode 100644 index 00000000..d43e7885 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_metadata.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroupCollectionMetadata struct for InsightGroupCollectionMetadata +type InsightGroupCollectionMetadata struct { + CountByIndicator InsightGroupsCountByIndicator `json:"countByIndicator"` +} + +// NewInsightGroupCollectionMetadata instantiates a new InsightGroupCollectionMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroupCollectionMetadata(countByIndicator InsightGroupsCountByIndicator) *InsightGroupCollectionMetadata { + this := InsightGroupCollectionMetadata{} + this.CountByIndicator = countByIndicator + return &this +} + +// NewInsightGroupCollectionMetadataWithDefaults instantiates a new InsightGroupCollectionMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupCollectionMetadataWithDefaults() *InsightGroupCollectionMetadata { + this := InsightGroupCollectionMetadata{} + return &this +} + +// GetCountByIndicator returns the CountByIndicator field value +func (o *InsightGroupCollectionMetadata) GetCountByIndicator() InsightGroupsCountByIndicator { + if o == nil { + var ret InsightGroupsCountByIndicator + return ret + } + + return o.CountByIndicator +} + +// GetCountByIndicatorOk returns a tuple with the CountByIndicator field value +// and a boolean to check if the value has been set. +func (o *InsightGroupCollectionMetadata) GetCountByIndicatorOk() (*InsightGroupsCountByIndicator, bool) { + if o == nil { + return nil, false + } + return &o.CountByIndicator, true +} + +// SetCountByIndicator sets field value +func (o *InsightGroupCollectionMetadata) SetCountByIndicator(v InsightGroupsCountByIndicator) { + o.CountByIndicator = v +} + +func (o InsightGroupCollectionMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["countByIndicator"] = o.CountByIndicator + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroupCollectionMetadata struct { + value *InsightGroupCollectionMetadata + isSet bool +} + +func (v NullableInsightGroupCollectionMetadata) Get() *InsightGroupCollectionMetadata { + return v.value +} + +func (v *NullableInsightGroupCollectionMetadata) Set(val *InsightGroupCollectionMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroupCollectionMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroupCollectionMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroupCollectionMetadata(val *InsightGroupCollectionMetadata) *NullableInsightGroupCollectionMetadata { + return &NullableInsightGroupCollectionMetadata{value: val, isSet: true} +} + +func (v NullableInsightGroupCollectionMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroupCollectionMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_score_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_score_metadata.go new file mode 100644 index 00000000..56ad0fa3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_collection_score_metadata.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroupCollectionScoreMetadata struct for InsightGroupCollectionScoreMetadata +type InsightGroupCollectionScoreMetadata struct { + Period InsightPeriod `json:"period"` + LastPeriod InsightPeriod `json:"lastPeriod"` +} + +// NewInsightGroupCollectionScoreMetadata instantiates a new InsightGroupCollectionScoreMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroupCollectionScoreMetadata(period InsightPeriod, lastPeriod InsightPeriod) *InsightGroupCollectionScoreMetadata { + this := InsightGroupCollectionScoreMetadata{} + this.Period = period + this.LastPeriod = lastPeriod + return &this +} + +// NewInsightGroupCollectionScoreMetadataWithDefaults instantiates a new InsightGroupCollectionScoreMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupCollectionScoreMetadataWithDefaults() *InsightGroupCollectionScoreMetadata { + this := InsightGroupCollectionScoreMetadata{} + return &this +} + +// GetPeriod returns the Period field value +func (o *InsightGroupCollectionScoreMetadata) GetPeriod() InsightPeriod { + if o == nil { + var ret InsightPeriod + return ret + } + + return o.Period +} + +// GetPeriodOk returns a tuple with the Period field value +// and a boolean to check if the value has been set. +func (o *InsightGroupCollectionScoreMetadata) GetPeriodOk() (*InsightPeriod, bool) { + if o == nil { + return nil, false + } + return &o.Period, true +} + +// SetPeriod sets field value +func (o *InsightGroupCollectionScoreMetadata) SetPeriod(v InsightPeriod) { + o.Period = v +} + +// GetLastPeriod returns the LastPeriod field value +func (o *InsightGroupCollectionScoreMetadata) GetLastPeriod() InsightPeriod { + if o == nil { + var ret InsightPeriod + return ret + } + + return o.LastPeriod +} + +// GetLastPeriodOk returns a tuple with the LastPeriod field value +// and a boolean to check if the value has been set. +func (o *InsightGroupCollectionScoreMetadata) GetLastPeriodOk() (*InsightPeriod, bool) { + if o == nil { + return nil, false + } + return &o.LastPeriod, true +} + +// SetLastPeriod sets field value +func (o *InsightGroupCollectionScoreMetadata) SetLastPeriod(v InsightPeriod) { + o.LastPeriod = v +} + +func (o InsightGroupCollectionScoreMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["period"] = o.Period + } + if true { + toSerialize["lastPeriod"] = o.LastPeriod + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroupCollectionScoreMetadata struct { + value *InsightGroupCollectionScoreMetadata + isSet bool +} + +func (v NullableInsightGroupCollectionScoreMetadata) Get() *InsightGroupCollectionScoreMetadata { + return v.value +} + +func (v *NullableInsightGroupCollectionScoreMetadata) Set(val *InsightGroupCollectionScoreMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroupCollectionScoreMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroupCollectionScoreMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroupCollectionScoreMetadata(val *InsightGroupCollectionScoreMetadata) *NullableInsightGroupCollectionScoreMetadata { + return &NullableInsightGroupCollectionScoreMetadata{value: val, isSet: true} +} + +func (v NullableInsightGroupCollectionScoreMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroupCollectionScoreMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_scores.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_scores.go new file mode 100644 index 00000000..d0465623 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_group_scores.go @@ -0,0 +1,406 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroupScores struct for InsightGroupScores +type InsightGroupScores struct { + Overall InsightsMetricScore `json:"overall"` + DeploymentFrequency InsightsMetricScore `json:"deploymentFrequency"` + DeploymentFailureRate InsightsMetricScore `json:"deploymentFailureRate"` + LeadTime InsightsMetricScore `json:"leadTime"` + ImpactSize InsightsMetricScore `json:"impactSize"` + ExperimentationCoverage InsightsMetricScore `json:"experimentationCoverage"` + FlagHealth InsightsMetricScore `json:"flagHealth"` + Velocity InsightsMetricScore `json:"velocity"` + Risk InsightsMetricScore `json:"risk"` + Efficiency InsightsMetricScore `json:"efficiency"` + CreationRatio *InsightsMetricScore `json:"creationRatio,omitempty"` +} + +// NewInsightGroupScores instantiates a new InsightGroupScores object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroupScores(overall InsightsMetricScore, deploymentFrequency InsightsMetricScore, deploymentFailureRate InsightsMetricScore, leadTime InsightsMetricScore, impactSize InsightsMetricScore, experimentationCoverage InsightsMetricScore, flagHealth InsightsMetricScore, velocity InsightsMetricScore, risk InsightsMetricScore, efficiency InsightsMetricScore) *InsightGroupScores { + this := InsightGroupScores{} + this.Overall = overall + this.DeploymentFrequency = deploymentFrequency + this.DeploymentFailureRate = deploymentFailureRate + this.LeadTime = leadTime + this.ImpactSize = impactSize + this.ExperimentationCoverage = experimentationCoverage + this.FlagHealth = flagHealth + this.Velocity = velocity + this.Risk = risk + this.Efficiency = efficiency + return &this +} + +// NewInsightGroupScoresWithDefaults instantiates a new InsightGroupScores object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupScoresWithDefaults() *InsightGroupScores { + this := InsightGroupScores{} + return &this +} + +// GetOverall returns the Overall field value +func (o *InsightGroupScores) GetOverall() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.Overall +} + +// GetOverallOk returns a tuple with the Overall field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetOverallOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.Overall, true +} + +// SetOverall sets field value +func (o *InsightGroupScores) SetOverall(v InsightsMetricScore) { + o.Overall = v +} + +// GetDeploymentFrequency returns the DeploymentFrequency field value +func (o *InsightGroupScores) GetDeploymentFrequency() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.DeploymentFrequency +} + +// GetDeploymentFrequencyOk returns a tuple with the DeploymentFrequency field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetDeploymentFrequencyOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.DeploymentFrequency, true +} + +// SetDeploymentFrequency sets field value +func (o *InsightGroupScores) SetDeploymentFrequency(v InsightsMetricScore) { + o.DeploymentFrequency = v +} + +// GetDeploymentFailureRate returns the DeploymentFailureRate field value +func (o *InsightGroupScores) GetDeploymentFailureRate() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.DeploymentFailureRate +} + +// GetDeploymentFailureRateOk returns a tuple with the DeploymentFailureRate field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetDeploymentFailureRateOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.DeploymentFailureRate, true +} + +// SetDeploymentFailureRate sets field value +func (o *InsightGroupScores) SetDeploymentFailureRate(v InsightsMetricScore) { + o.DeploymentFailureRate = v +} + +// GetLeadTime returns the LeadTime field value +func (o *InsightGroupScores) GetLeadTime() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.LeadTime +} + +// GetLeadTimeOk returns a tuple with the LeadTime field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetLeadTimeOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.LeadTime, true +} + +// SetLeadTime sets field value +func (o *InsightGroupScores) SetLeadTime(v InsightsMetricScore) { + o.LeadTime = v +} + +// GetImpactSize returns the ImpactSize field value +func (o *InsightGroupScores) GetImpactSize() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.ImpactSize +} + +// GetImpactSizeOk returns a tuple with the ImpactSize field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetImpactSizeOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.ImpactSize, true +} + +// SetImpactSize sets field value +func (o *InsightGroupScores) SetImpactSize(v InsightsMetricScore) { + o.ImpactSize = v +} + +// GetExperimentationCoverage returns the ExperimentationCoverage field value +func (o *InsightGroupScores) GetExperimentationCoverage() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.ExperimentationCoverage +} + +// GetExperimentationCoverageOk returns a tuple with the ExperimentationCoverage field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetExperimentationCoverageOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.ExperimentationCoverage, true +} + +// SetExperimentationCoverage sets field value +func (o *InsightGroupScores) SetExperimentationCoverage(v InsightsMetricScore) { + o.ExperimentationCoverage = v +} + +// GetFlagHealth returns the FlagHealth field value +func (o *InsightGroupScores) GetFlagHealth() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.FlagHealth +} + +// GetFlagHealthOk returns a tuple with the FlagHealth field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetFlagHealthOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.FlagHealth, true +} + +// SetFlagHealth sets field value +func (o *InsightGroupScores) SetFlagHealth(v InsightsMetricScore) { + o.FlagHealth = v +} + +// GetVelocity returns the Velocity field value +func (o *InsightGroupScores) GetVelocity() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.Velocity +} + +// GetVelocityOk returns a tuple with the Velocity field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetVelocityOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.Velocity, true +} + +// SetVelocity sets field value +func (o *InsightGroupScores) SetVelocity(v InsightsMetricScore) { + o.Velocity = v +} + +// GetRisk returns the Risk field value +func (o *InsightGroupScores) GetRisk() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.Risk +} + +// GetRiskOk returns a tuple with the Risk field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetRiskOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.Risk, true +} + +// SetRisk sets field value +func (o *InsightGroupScores) SetRisk(v InsightsMetricScore) { + o.Risk = v +} + +// GetEfficiency returns the Efficiency field value +func (o *InsightGroupScores) GetEfficiency() InsightsMetricScore { + if o == nil { + var ret InsightsMetricScore + return ret + } + + return o.Efficiency +} + +// GetEfficiencyOk returns a tuple with the Efficiency field value +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetEfficiencyOk() (*InsightsMetricScore, bool) { + if o == nil { + return nil, false + } + return &o.Efficiency, true +} + +// SetEfficiency sets field value +func (o *InsightGroupScores) SetEfficiency(v InsightsMetricScore) { + o.Efficiency = v +} + +// GetCreationRatio returns the CreationRatio field value if set, zero value otherwise. +func (o *InsightGroupScores) GetCreationRatio() InsightsMetricScore { + if o == nil || o.CreationRatio == nil { + var ret InsightsMetricScore + return ret + } + return *o.CreationRatio +} + +// GetCreationRatioOk returns a tuple with the CreationRatio field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightGroupScores) GetCreationRatioOk() (*InsightsMetricScore, bool) { + if o == nil || o.CreationRatio == nil { + return nil, false + } + return o.CreationRatio, true +} + +// HasCreationRatio returns a boolean if a field has been set. +func (o *InsightGroupScores) HasCreationRatio() bool { + if o != nil && o.CreationRatio != nil { + return true + } + + return false +} + +// SetCreationRatio gets a reference to the given InsightsMetricScore and assigns it to the CreationRatio field. +func (o *InsightGroupScores) SetCreationRatio(v InsightsMetricScore) { + o.CreationRatio = &v +} + +func (o InsightGroupScores) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["overall"] = o.Overall + } + if true { + toSerialize["deploymentFrequency"] = o.DeploymentFrequency + } + if true { + toSerialize["deploymentFailureRate"] = o.DeploymentFailureRate + } + if true { + toSerialize["leadTime"] = o.LeadTime + } + if true { + toSerialize["impactSize"] = o.ImpactSize + } + if true { + toSerialize["experimentationCoverage"] = o.ExperimentationCoverage + } + if true { + toSerialize["flagHealth"] = o.FlagHealth + } + if true { + toSerialize["velocity"] = o.Velocity + } + if true { + toSerialize["risk"] = o.Risk + } + if true { + toSerialize["efficiency"] = o.Efficiency + } + if o.CreationRatio != nil { + toSerialize["creationRatio"] = o.CreationRatio + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroupScores struct { + value *InsightGroupScores + isSet bool +} + +func (v NullableInsightGroupScores) Get() *InsightGroupScores { + return v.value +} + +func (v *NullableInsightGroupScores) Set(val *InsightGroupScores) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroupScores) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroupScores) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroupScores(val *InsightGroupScores) *NullableInsightGroupScores { + return &NullableInsightGroupScores{value: val, isSet: true} +} + +func (v NullableInsightGroupScores) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroupScores) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_groups_count_by_indicator.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_groups_count_by_indicator.go new file mode 100644 index 00000000..6bbfbbd4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_groups_count_by_indicator.go @@ -0,0 +1,290 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightGroupsCountByIndicator struct for InsightGroupsCountByIndicator +type InsightGroupsCountByIndicator struct { + // The number of insight groups with an excellent indicator + Excellent int32 `json:"excellent"` + // The number of insight groups with a good indicator + Good int32 `json:"good"` + // The number of insight groups with a fair indicator + Fair int32 `json:"fair"` + // The number of insight groups with a needs attention indicator + NeedsAttention int32 `json:"needsAttention"` + // The number of insight groups with a not calculated indicator + NotCalculated int32 `json:"notCalculated"` + // The number of insight groups with an unknown indicator + Unknown int32 `json:"unknown"` + // The total number of insight groups + Total int32 `json:"total"` +} + +// NewInsightGroupsCountByIndicator instantiates a new InsightGroupsCountByIndicator object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightGroupsCountByIndicator(excellent int32, good int32, fair int32, needsAttention int32, notCalculated int32, unknown int32, total int32) *InsightGroupsCountByIndicator { + this := InsightGroupsCountByIndicator{} + this.Excellent = excellent + this.Good = good + this.Fair = fair + this.NeedsAttention = needsAttention + this.NotCalculated = notCalculated + this.Unknown = unknown + this.Total = total + return &this +} + +// NewInsightGroupsCountByIndicatorWithDefaults instantiates a new InsightGroupsCountByIndicator object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightGroupsCountByIndicatorWithDefaults() *InsightGroupsCountByIndicator { + this := InsightGroupsCountByIndicator{} + return &this +} + +// GetExcellent returns the Excellent field value +func (o *InsightGroupsCountByIndicator) GetExcellent() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Excellent +} + +// GetExcellentOk returns a tuple with the Excellent field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetExcellentOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Excellent, true +} + +// SetExcellent sets field value +func (o *InsightGroupsCountByIndicator) SetExcellent(v int32) { + o.Excellent = v +} + +// GetGood returns the Good field value +func (o *InsightGroupsCountByIndicator) GetGood() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Good +} + +// GetGoodOk returns a tuple with the Good field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetGoodOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Good, true +} + +// SetGood sets field value +func (o *InsightGroupsCountByIndicator) SetGood(v int32) { + o.Good = v +} + +// GetFair returns the Fair field value +func (o *InsightGroupsCountByIndicator) GetFair() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Fair +} + +// GetFairOk returns a tuple with the Fair field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetFairOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Fair, true +} + +// SetFair sets field value +func (o *InsightGroupsCountByIndicator) SetFair(v int32) { + o.Fair = v +} + +// GetNeedsAttention returns the NeedsAttention field value +func (o *InsightGroupsCountByIndicator) GetNeedsAttention() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.NeedsAttention +} + +// GetNeedsAttentionOk returns a tuple with the NeedsAttention field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetNeedsAttentionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.NeedsAttention, true +} + +// SetNeedsAttention sets field value +func (o *InsightGroupsCountByIndicator) SetNeedsAttention(v int32) { + o.NeedsAttention = v +} + +// GetNotCalculated returns the NotCalculated field value +func (o *InsightGroupsCountByIndicator) GetNotCalculated() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.NotCalculated +} + +// GetNotCalculatedOk returns a tuple with the NotCalculated field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetNotCalculatedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.NotCalculated, true +} + +// SetNotCalculated sets field value +func (o *InsightGroupsCountByIndicator) SetNotCalculated(v int32) { + o.NotCalculated = v +} + +// GetUnknown returns the Unknown field value +func (o *InsightGroupsCountByIndicator) GetUnknown() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Unknown +} + +// GetUnknownOk returns a tuple with the Unknown field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetUnknownOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Unknown, true +} + +// SetUnknown sets field value +func (o *InsightGroupsCountByIndicator) SetUnknown(v int32) { + o.Unknown = v +} + +// GetTotal returns the Total field value +func (o *InsightGroupsCountByIndicator) GetTotal() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Total +} + +// GetTotalOk returns a tuple with the Total field value +// and a boolean to check if the value has been set. +func (o *InsightGroupsCountByIndicator) GetTotalOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Total, true +} + +// SetTotal sets field value +func (o *InsightGroupsCountByIndicator) SetTotal(v int32) { + o.Total = v +} + +func (o InsightGroupsCountByIndicator) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["excellent"] = o.Excellent + } + if true { + toSerialize["good"] = o.Good + } + if true { + toSerialize["fair"] = o.Fair + } + if true { + toSerialize["needsAttention"] = o.NeedsAttention + } + if true { + toSerialize["notCalculated"] = o.NotCalculated + } + if true { + toSerialize["unknown"] = o.Unknown + } + if true { + toSerialize["total"] = o.Total + } + return json.Marshal(toSerialize) +} + +type NullableInsightGroupsCountByIndicator struct { + value *InsightGroupsCountByIndicator + isSet bool +} + +func (v NullableInsightGroupsCountByIndicator) Get() *InsightGroupsCountByIndicator { + return v.value +} + +func (v *NullableInsightGroupsCountByIndicator) Set(val *InsightGroupsCountByIndicator) { + v.value = val + v.isSet = true +} + +func (v NullableInsightGroupsCountByIndicator) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightGroupsCountByIndicator) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightGroupsCountByIndicator(val *InsightGroupsCountByIndicator) *NullableInsightGroupsCountByIndicator { + return &NullableInsightGroupsCountByIndicator{value: val, isSet: true} +} + +func (v NullableInsightGroupsCountByIndicator) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightGroupsCountByIndicator) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_period.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_period.go new file mode 100644 index 00000000..d21d2d01 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_period.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightPeriod struct for InsightPeriod +type InsightPeriod struct { + StartTime int64 `json:"startTime"` + EndTime int64 `json:"endTime"` +} + +// NewInsightPeriod instantiates a new InsightPeriod object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightPeriod(startTime int64, endTime int64) *InsightPeriod { + this := InsightPeriod{} + this.StartTime = startTime + this.EndTime = endTime + return &this +} + +// NewInsightPeriodWithDefaults instantiates a new InsightPeriod object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightPeriodWithDefaults() *InsightPeriod { + this := InsightPeriod{} + return &this +} + +// GetStartTime returns the StartTime field value +func (o *InsightPeriod) GetStartTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.StartTime +} + +// GetStartTimeOk returns a tuple with the StartTime field value +// and a boolean to check if the value has been set. +func (o *InsightPeriod) GetStartTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.StartTime, true +} + +// SetStartTime sets field value +func (o *InsightPeriod) SetStartTime(v int64) { + o.StartTime = v +} + +// GetEndTime returns the EndTime field value +func (o *InsightPeriod) GetEndTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.EndTime +} + +// GetEndTimeOk returns a tuple with the EndTime field value +// and a boolean to check if the value has been set. +func (o *InsightPeriod) GetEndTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.EndTime, true +} + +// SetEndTime sets field value +func (o *InsightPeriod) SetEndTime(v int64) { + o.EndTime = v +} + +func (o InsightPeriod) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["startTime"] = o.StartTime + } + if true { + toSerialize["endTime"] = o.EndTime + } + return json.Marshal(toSerialize) +} + +type NullableInsightPeriod struct { + value *InsightPeriod + isSet bool +} + +func (v NullableInsightPeriod) Get() *InsightPeriod { + return v.value +} + +func (v *NullableInsightPeriod) Set(val *InsightPeriod) { + v.value = val + v.isSet = true +} + +func (v NullableInsightPeriod) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightPeriod) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightPeriod(val *InsightPeriod) *NullableInsightPeriod { + return &NullableInsightPeriod{value: val, isSet: true} +} + +func (v NullableInsightPeriod) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightPeriod) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_scores.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_scores.go new file mode 100644 index 00000000..bb370d96 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insight_scores.go @@ -0,0 +1,204 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightScores struct for InsightScores +type InsightScores struct { + Period InsightPeriod `json:"period"` + LastPeriod InsightPeriod `json:"lastPeriod"` + Scores InsightGroupScores `json:"scores"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewInsightScores instantiates a new InsightScores object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightScores(period InsightPeriod, lastPeriod InsightPeriod, scores InsightGroupScores) *InsightScores { + this := InsightScores{} + this.Period = period + this.LastPeriod = lastPeriod + this.Scores = scores + return &this +} + +// NewInsightScoresWithDefaults instantiates a new InsightScores object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightScoresWithDefaults() *InsightScores { + this := InsightScores{} + return &this +} + +// GetPeriod returns the Period field value +func (o *InsightScores) GetPeriod() InsightPeriod { + if o == nil { + var ret InsightPeriod + return ret + } + + return o.Period +} + +// GetPeriodOk returns a tuple with the Period field value +// and a boolean to check if the value has been set. +func (o *InsightScores) GetPeriodOk() (*InsightPeriod, bool) { + if o == nil { + return nil, false + } + return &o.Period, true +} + +// SetPeriod sets field value +func (o *InsightScores) SetPeriod(v InsightPeriod) { + o.Period = v +} + +// GetLastPeriod returns the LastPeriod field value +func (o *InsightScores) GetLastPeriod() InsightPeriod { + if o == nil { + var ret InsightPeriod + return ret + } + + return o.LastPeriod +} + +// GetLastPeriodOk returns a tuple with the LastPeriod field value +// and a boolean to check if the value has been set. +func (o *InsightScores) GetLastPeriodOk() (*InsightPeriod, bool) { + if o == nil { + return nil, false + } + return &o.LastPeriod, true +} + +// SetLastPeriod sets field value +func (o *InsightScores) SetLastPeriod(v InsightPeriod) { + o.LastPeriod = v +} + +// GetScores returns the Scores field value +func (o *InsightScores) GetScores() InsightGroupScores { + if o == nil { + var ret InsightGroupScores + return ret + } + + return o.Scores +} + +// GetScoresOk returns a tuple with the Scores field value +// and a boolean to check if the value has been set. +func (o *InsightScores) GetScoresOk() (*InsightGroupScores, bool) { + if o == nil { + return nil, false + } + return &o.Scores, true +} + +// SetScores sets field value +func (o *InsightScores) SetScores(v InsightGroupScores) { + o.Scores = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *InsightScores) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightScores) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *InsightScores) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *InsightScores) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o InsightScores) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["period"] = o.Period + } + if true { + toSerialize["lastPeriod"] = o.LastPeriod + } + if true { + toSerialize["scores"] = o.Scores + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableInsightScores struct { + value *InsightScores + isSet bool +} + +func (v NullableInsightScores) Get() *InsightScores { + return v.value +} + +func (v *NullableInsightScores) Set(val *InsightScores) { + v.value = val + v.isSet = true +} + +func (v NullableInsightScores) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightScores) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightScores(val *InsightScores) *NullableInsightScores { + return &NullableInsightScores{value: val, isSet: true} +} + +func (v NullableInsightScores) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightScores) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart.go new file mode 100644 index 00000000..bc15493c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChart struct for InsightsChart +type InsightsChart struct { + Metadata InsightsChartMetadata `json:"metadata"` + // Series data for the chart + Series []InsightsChartSeries `json:"series"` +} + +// NewInsightsChart instantiates a new InsightsChart object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChart(metadata InsightsChartMetadata, series []InsightsChartSeries) *InsightsChart { + this := InsightsChart{} + this.Metadata = metadata + this.Series = series + return &this +} + +// NewInsightsChartWithDefaults instantiates a new InsightsChart object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartWithDefaults() *InsightsChart { + this := InsightsChart{} + return &this +} + +// GetMetadata returns the Metadata field value +func (o *InsightsChart) GetMetadata() InsightsChartMetadata { + if o == nil { + var ret InsightsChartMetadata + return ret + } + + return o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value +// and a boolean to check if the value has been set. +func (o *InsightsChart) GetMetadataOk() (*InsightsChartMetadata, bool) { + if o == nil { + return nil, false + } + return &o.Metadata, true +} + +// SetMetadata sets field value +func (o *InsightsChart) SetMetadata(v InsightsChartMetadata) { + o.Metadata = v +} + +// GetSeries returns the Series field value +func (o *InsightsChart) GetSeries() []InsightsChartSeries { + if o == nil { + var ret []InsightsChartSeries + return ret + } + + return o.Series +} + +// GetSeriesOk returns a tuple with the Series field value +// and a boolean to check if the value has been set. +func (o *InsightsChart) GetSeriesOk() ([]InsightsChartSeries, bool) { + if o == nil { + return nil, false + } + return o.Series, true +} + +// SetSeries sets field value +func (o *InsightsChart) SetSeries(v []InsightsChartSeries) { + o.Series = v +} + +func (o InsightsChart) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["metadata"] = o.Metadata + } + if true { + toSerialize["series"] = o.Series + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChart struct { + value *InsightsChart + isSet bool +} + +func (v NullableInsightsChart) Get() *InsightsChart { + return v.value +} + +func (v *NullableInsightsChart) Set(val *InsightsChart) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChart) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChart) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChart(val *InsightsChart) *NullableInsightsChart { + return &NullableInsightsChart{value: val, isSet: true} +} + +func (v NullableInsightsChart) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChart) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_bounds.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_bounds.go new file mode 100644 index 00000000..339c0cae --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_bounds.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartBounds struct for InsightsChartBounds +type InsightsChartBounds struct { + // Name of the bound + Name string `json:"name"` + // Value of the bound + Value int64 `json:"value"` +} + +// NewInsightsChartBounds instantiates a new InsightsChartBounds object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartBounds(name string, value int64) *InsightsChartBounds { + this := InsightsChartBounds{} + this.Name = name + this.Value = value + return &this +} + +// NewInsightsChartBoundsWithDefaults instantiates a new InsightsChartBounds object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartBoundsWithDefaults() *InsightsChartBounds { + this := InsightsChartBounds{} + return &this +} + +// GetName returns the Name field value +func (o *InsightsChartBounds) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *InsightsChartBounds) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *InsightsChartBounds) SetName(v string) { + o.Name = v +} + +// GetValue returns the Value field value +func (o *InsightsChartBounds) GetValue() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *InsightsChartBounds) GetValueOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *InsightsChartBounds) SetValue(v int64) { + o.Value = v +} + +func (o InsightsChartBounds) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartBounds struct { + value *InsightsChartBounds + isSet bool +} + +func (v NullableInsightsChartBounds) Get() *InsightsChartBounds { + return v.value +} + +func (v *NullableInsightsChartBounds) Set(val *InsightsChartBounds) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartBounds) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartBounds) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartBounds(val *InsightsChartBounds) *NullableInsightsChartBounds { + return &NullableInsightsChartBounds{value: val, isSet: true} +} + +func (v NullableInsightsChartBounds) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartBounds) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metadata.go new file mode 100644 index 00000000..df7c0f87 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metadata.go @@ -0,0 +1,240 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartMetadata struct for InsightsChartMetadata +type InsightsChartMetadata struct { + Summary map[string]interface{} `json:"summary"` + // Name of the chart + Name *string `json:"name,omitempty"` + Metrics *map[string]InsightsChartMetric `json:"metrics,omitempty"` + XAxis InsightsChartSeriesMetadataAxis `json:"xAxis"` + YAxis InsightsChartSeriesMetadataAxis `json:"yAxis"` +} + +// NewInsightsChartMetadata instantiates a new InsightsChartMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartMetadata(summary map[string]interface{}, xAxis InsightsChartSeriesMetadataAxis, yAxis InsightsChartSeriesMetadataAxis) *InsightsChartMetadata { + this := InsightsChartMetadata{} + this.Summary = summary + this.XAxis = xAxis + this.YAxis = yAxis + return &this +} + +// NewInsightsChartMetadataWithDefaults instantiates a new InsightsChartMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartMetadataWithDefaults() *InsightsChartMetadata { + this := InsightsChartMetadata{} + return &this +} + +// GetSummary returns the Summary field value +func (o *InsightsChartMetadata) GetSummary() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Summary +} + +// GetSummaryOk returns a tuple with the Summary field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetadata) GetSummaryOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Summary, true +} + +// SetSummary sets field value +func (o *InsightsChartMetadata) SetSummary(v map[string]interface{}) { + o.Summary = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *InsightsChartMetadata) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsChartMetadata) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *InsightsChartMetadata) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *InsightsChartMetadata) SetName(v string) { + o.Name = &v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *InsightsChartMetadata) GetMetrics() map[string]InsightsChartMetric { + if o == nil || o.Metrics == nil { + var ret map[string]InsightsChartMetric + return ret + } + return *o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsChartMetadata) GetMetricsOk() (*map[string]InsightsChartMetric, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *InsightsChartMetadata) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given map[string]InsightsChartMetric and assigns it to the Metrics field. +func (o *InsightsChartMetadata) SetMetrics(v map[string]InsightsChartMetric) { + o.Metrics = &v +} + +// GetXAxis returns the XAxis field value +func (o *InsightsChartMetadata) GetXAxis() InsightsChartSeriesMetadataAxis { + if o == nil { + var ret InsightsChartSeriesMetadataAxis + return ret + } + + return o.XAxis +} + +// GetXAxisOk returns a tuple with the XAxis field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetadata) GetXAxisOk() (*InsightsChartSeriesMetadataAxis, bool) { + if o == nil { + return nil, false + } + return &o.XAxis, true +} + +// SetXAxis sets field value +func (o *InsightsChartMetadata) SetXAxis(v InsightsChartSeriesMetadataAxis) { + o.XAxis = v +} + +// GetYAxis returns the YAxis field value +func (o *InsightsChartMetadata) GetYAxis() InsightsChartSeriesMetadataAxis { + if o == nil { + var ret InsightsChartSeriesMetadataAxis + return ret + } + + return o.YAxis +} + +// GetYAxisOk returns a tuple with the YAxis field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetadata) GetYAxisOk() (*InsightsChartSeriesMetadataAxis, bool) { + if o == nil { + return nil, false + } + return &o.YAxis, true +} + +// SetYAxis sets field value +func (o *InsightsChartMetadata) SetYAxis(v InsightsChartSeriesMetadataAxis) { + o.YAxis = v +} + +func (o InsightsChartMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["summary"] = o.Summary + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + if true { + toSerialize["xAxis"] = o.XAxis + } + if true { + toSerialize["yAxis"] = o.YAxis + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartMetadata struct { + value *InsightsChartMetadata + isSet bool +} + +func (v NullableInsightsChartMetadata) Get() *InsightsChartMetadata { + return v.value +} + +func (v *NullableInsightsChartMetadata) Set(val *InsightsChartMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartMetadata(val *InsightsChartMetadata) *NullableInsightsChartMetadata { + return &NullableInsightsChartMetadata{value: val, isSet: true} +} + +func (v NullableInsightsChartMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metric.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metric.go new file mode 100644 index 00000000..fd56be53 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_metric.go @@ -0,0 +1,230 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartMetric struct for InsightsChartMetric +type InsightsChartMetric struct { + // Metric indicator tier + Indicator string `json:"indicator"` + // Metric value + Value float32 `json:"value"` + // Metric unit + Unit string `json:"unit"` + // Metric modifier + Modifier string `json:"modifier"` + // Metric indicator tiers + Tiers []InsightsMetricTierDefinition `json:"tiers"` +} + +// NewInsightsChartMetric instantiates a new InsightsChartMetric object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartMetric(indicator string, value float32, unit string, modifier string, tiers []InsightsMetricTierDefinition) *InsightsChartMetric { + this := InsightsChartMetric{} + this.Indicator = indicator + this.Value = value + this.Unit = unit + this.Modifier = modifier + this.Tiers = tiers + return &this +} + +// NewInsightsChartMetricWithDefaults instantiates a new InsightsChartMetric object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartMetricWithDefaults() *InsightsChartMetric { + this := InsightsChartMetric{} + return &this +} + +// GetIndicator returns the Indicator field value +func (o *InsightsChartMetric) GetIndicator() string { + if o == nil { + var ret string + return ret + } + + return o.Indicator +} + +// GetIndicatorOk returns a tuple with the Indicator field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetric) GetIndicatorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Indicator, true +} + +// SetIndicator sets field value +func (o *InsightsChartMetric) SetIndicator(v string) { + o.Indicator = v +} + +// GetValue returns the Value field value +func (o *InsightsChartMetric) GetValue() float32 { + if o == nil { + var ret float32 + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetric) GetValueOk() (*float32, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *InsightsChartMetric) SetValue(v float32) { + o.Value = v +} + +// GetUnit returns the Unit field value +func (o *InsightsChartMetric) GetUnit() string { + if o == nil { + var ret string + return ret + } + + return o.Unit +} + +// GetUnitOk returns a tuple with the Unit field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetric) GetUnitOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Unit, true +} + +// SetUnit sets field value +func (o *InsightsChartMetric) SetUnit(v string) { + o.Unit = v +} + +// GetModifier returns the Modifier field value +func (o *InsightsChartMetric) GetModifier() string { + if o == nil { + var ret string + return ret + } + + return o.Modifier +} + +// GetModifierOk returns a tuple with the Modifier field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetric) GetModifierOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Modifier, true +} + +// SetModifier sets field value +func (o *InsightsChartMetric) SetModifier(v string) { + o.Modifier = v +} + +// GetTiers returns the Tiers field value +func (o *InsightsChartMetric) GetTiers() []InsightsMetricTierDefinition { + if o == nil { + var ret []InsightsMetricTierDefinition + return ret + } + + return o.Tiers +} + +// GetTiersOk returns a tuple with the Tiers field value +// and a boolean to check if the value has been set. +func (o *InsightsChartMetric) GetTiersOk() ([]InsightsMetricTierDefinition, bool) { + if o == nil { + return nil, false + } + return o.Tiers, true +} + +// SetTiers sets field value +func (o *InsightsChartMetric) SetTiers(v []InsightsMetricTierDefinition) { + o.Tiers = v +} + +func (o InsightsChartMetric) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["indicator"] = o.Indicator + } + if true { + toSerialize["value"] = o.Value + } + if true { + toSerialize["unit"] = o.Unit + } + if true { + toSerialize["modifier"] = o.Modifier + } + if true { + toSerialize["tiers"] = o.Tiers + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartMetric struct { + value *InsightsChartMetric + isSet bool +} + +func (v NullableInsightsChartMetric) Get() *InsightsChartMetric { + return v.value +} + +func (v *NullableInsightsChartMetric) Set(val *InsightsChartMetric) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartMetric) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartMetric) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartMetric(val *InsightsChartMetric) *NullableInsightsChartMetric { + return &NullableInsightsChartMetric{value: val, isSet: true} +} + +func (v NullableInsightsChartMetric) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartMetric) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series.go new file mode 100644 index 00000000..68ab8439 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartSeries struct for InsightsChartSeries +type InsightsChartSeries struct { + Metadata InsightsChartSeriesMetadata `json:"metadata"` + // Data points for the series + Data []InsightsChartSeriesDataPoint `json:"data"` +} + +// NewInsightsChartSeries instantiates a new InsightsChartSeries object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartSeries(metadata InsightsChartSeriesMetadata, data []InsightsChartSeriesDataPoint) *InsightsChartSeries { + this := InsightsChartSeries{} + this.Metadata = metadata + this.Data = data + return &this +} + +// NewInsightsChartSeriesWithDefaults instantiates a new InsightsChartSeries object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartSeriesWithDefaults() *InsightsChartSeries { + this := InsightsChartSeries{} + return &this +} + +// GetMetadata returns the Metadata field value +func (o *InsightsChartSeries) GetMetadata() InsightsChartSeriesMetadata { + if o == nil { + var ret InsightsChartSeriesMetadata + return ret + } + + return o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeries) GetMetadataOk() (*InsightsChartSeriesMetadata, bool) { + if o == nil { + return nil, false + } + return &o.Metadata, true +} + +// SetMetadata sets field value +func (o *InsightsChartSeries) SetMetadata(v InsightsChartSeriesMetadata) { + o.Metadata = v +} + +// GetData returns the Data field value +func (o *InsightsChartSeries) GetData() []InsightsChartSeriesDataPoint { + if o == nil { + var ret []InsightsChartSeriesDataPoint + return ret + } + + return o.Data +} + +// GetDataOk returns a tuple with the Data field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeries) GetDataOk() ([]InsightsChartSeriesDataPoint, bool) { + if o == nil { + return nil, false + } + return o.Data, true +} + +// SetData sets field value +func (o *InsightsChartSeries) SetData(v []InsightsChartSeriesDataPoint) { + o.Data = v +} + +func (o InsightsChartSeries) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["metadata"] = o.Metadata + } + if true { + toSerialize["data"] = o.Data + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartSeries struct { + value *InsightsChartSeries + isSet bool +} + +func (v NullableInsightsChartSeries) Get() *InsightsChartSeries { + return v.value +} + +func (v *NullableInsightsChartSeries) Set(val *InsightsChartSeries) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartSeries) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartSeries) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartSeries(val *InsightsChartSeries) *NullableInsightsChartSeries { + return &NullableInsightsChartSeries{value: val, isSet: true} +} + +func (v NullableInsightsChartSeries) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartSeries) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_data_point.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_data_point.go new file mode 100644 index 00000000..db5b06a6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_data_point.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartSeriesDataPoint struct for InsightsChartSeriesDataPoint +type InsightsChartSeriesDataPoint struct { + // X-axis value + X int64 `json:"x"` + // Y-axis value + Y int64 `json:"y"` + // Additional values for the data point + Values map[string]interface{} `json:"values,omitempty"` +} + +// NewInsightsChartSeriesDataPoint instantiates a new InsightsChartSeriesDataPoint object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartSeriesDataPoint(x int64, y int64) *InsightsChartSeriesDataPoint { + this := InsightsChartSeriesDataPoint{} + this.X = x + this.Y = y + return &this +} + +// NewInsightsChartSeriesDataPointWithDefaults instantiates a new InsightsChartSeriesDataPoint object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartSeriesDataPointWithDefaults() *InsightsChartSeriesDataPoint { + this := InsightsChartSeriesDataPoint{} + return &this +} + +// GetX returns the X field value +func (o *InsightsChartSeriesDataPoint) GetX() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.X +} + +// GetXOk returns a tuple with the X field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesDataPoint) GetXOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.X, true +} + +// SetX sets field value +func (o *InsightsChartSeriesDataPoint) SetX(v int64) { + o.X = v +} + +// GetY returns the Y field value +func (o *InsightsChartSeriesDataPoint) GetY() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Y +} + +// GetYOk returns a tuple with the Y field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesDataPoint) GetYOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Y, true +} + +// SetY sets field value +func (o *InsightsChartSeriesDataPoint) SetY(v int64) { + o.Y = v +} + +// GetValues returns the Values field value if set, zero value otherwise. +func (o *InsightsChartSeriesDataPoint) GetValues() map[string]interface{} { + if o == nil || o.Values == nil { + var ret map[string]interface{} + return ret + } + return o.Values +} + +// GetValuesOk returns a tuple with the Values field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesDataPoint) GetValuesOk() (map[string]interface{}, bool) { + if o == nil || o.Values == nil { + return nil, false + } + return o.Values, true +} + +// HasValues returns a boolean if a field has been set. +func (o *InsightsChartSeriesDataPoint) HasValues() bool { + if o != nil && o.Values != nil { + return true + } + + return false +} + +// SetValues gets a reference to the given map[string]interface{} and assigns it to the Values field. +func (o *InsightsChartSeriesDataPoint) SetValues(v map[string]interface{}) { + o.Values = v +} + +func (o InsightsChartSeriesDataPoint) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["x"] = o.X + } + if true { + toSerialize["y"] = o.Y + } + if o.Values != nil { + toSerialize["values"] = o.Values + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartSeriesDataPoint struct { + value *InsightsChartSeriesDataPoint + isSet bool +} + +func (v NullableInsightsChartSeriesDataPoint) Get() *InsightsChartSeriesDataPoint { + return v.value +} + +func (v *NullableInsightsChartSeriesDataPoint) Set(val *InsightsChartSeriesDataPoint) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartSeriesDataPoint) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartSeriesDataPoint) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartSeriesDataPoint(val *InsightsChartSeriesDataPoint) *NullableInsightsChartSeriesDataPoint { + return &NullableInsightsChartSeriesDataPoint{value: val, isSet: true} +} + +func (v NullableInsightsChartSeriesDataPoint) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartSeriesDataPoint) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata.go new file mode 100644 index 00000000..ee3ea3e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartSeriesMetadata struct for InsightsChartSeriesMetadata +type InsightsChartSeriesMetadata struct { + // Name of the series + Name string `json:"name"` + // Aggregate count of the series values + Count *int64 `json:"count,omitempty"` + // Bounds for the series data + Bounds []InsightsChartBounds `json:"bounds,omitempty"` +} + +// NewInsightsChartSeriesMetadata instantiates a new InsightsChartSeriesMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartSeriesMetadata(name string) *InsightsChartSeriesMetadata { + this := InsightsChartSeriesMetadata{} + this.Name = name + return &this +} + +// NewInsightsChartSeriesMetadataWithDefaults instantiates a new InsightsChartSeriesMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartSeriesMetadataWithDefaults() *InsightsChartSeriesMetadata { + this := InsightsChartSeriesMetadata{} + return &this +} + +// GetName returns the Name field value +func (o *InsightsChartSeriesMetadata) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesMetadata) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *InsightsChartSeriesMetadata) SetName(v string) { + o.Name = v +} + +// GetCount returns the Count field value if set, zero value otherwise. +func (o *InsightsChartSeriesMetadata) GetCount() int64 { + if o == nil || o.Count == nil { + var ret int64 + return ret + } + return *o.Count +} + +// GetCountOk returns a tuple with the Count field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesMetadata) GetCountOk() (*int64, bool) { + if o == nil || o.Count == nil { + return nil, false + } + return o.Count, true +} + +// HasCount returns a boolean if a field has been set. +func (o *InsightsChartSeriesMetadata) HasCount() bool { + if o != nil && o.Count != nil { + return true + } + + return false +} + +// SetCount gets a reference to the given int64 and assigns it to the Count field. +func (o *InsightsChartSeriesMetadata) SetCount(v int64) { + o.Count = &v +} + +// GetBounds returns the Bounds field value if set, zero value otherwise. +func (o *InsightsChartSeriesMetadata) GetBounds() []InsightsChartBounds { + if o == nil || o.Bounds == nil { + var ret []InsightsChartBounds + return ret + } + return o.Bounds +} + +// GetBoundsOk returns a tuple with the Bounds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesMetadata) GetBoundsOk() ([]InsightsChartBounds, bool) { + if o == nil || o.Bounds == nil { + return nil, false + } + return o.Bounds, true +} + +// HasBounds returns a boolean if a field has been set. +func (o *InsightsChartSeriesMetadata) HasBounds() bool { + if o != nil && o.Bounds != nil { + return true + } + + return false +} + +// SetBounds gets a reference to the given []InsightsChartBounds and assigns it to the Bounds field. +func (o *InsightsChartSeriesMetadata) SetBounds(v []InsightsChartBounds) { + o.Bounds = v +} + +func (o InsightsChartSeriesMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Count != nil { + toSerialize["count"] = o.Count + } + if o.Bounds != nil { + toSerialize["bounds"] = o.Bounds + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartSeriesMetadata struct { + value *InsightsChartSeriesMetadata + isSet bool +} + +func (v NullableInsightsChartSeriesMetadata) Get() *InsightsChartSeriesMetadata { + return v.value +} + +func (v *NullableInsightsChartSeriesMetadata) Set(val *InsightsChartSeriesMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartSeriesMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartSeriesMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartSeriesMetadata(val *InsightsChartSeriesMetadata) *NullableInsightsChartSeriesMetadata { + return &NullableInsightsChartSeriesMetadata{value: val, isSet: true} +} + +func (v NullableInsightsChartSeriesMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartSeriesMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata_axis.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata_axis.go new file mode 100644 index 00000000..d971af8a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_chart_series_metadata_axis.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsChartSeriesMetadataAxis struct for InsightsChartSeriesMetadataAxis +type InsightsChartSeriesMetadataAxis struct { + // Unit of the axis + Unit string `json:"unit"` +} + +// NewInsightsChartSeriesMetadataAxis instantiates a new InsightsChartSeriesMetadataAxis object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsChartSeriesMetadataAxis(unit string) *InsightsChartSeriesMetadataAxis { + this := InsightsChartSeriesMetadataAxis{} + this.Unit = unit + return &this +} + +// NewInsightsChartSeriesMetadataAxisWithDefaults instantiates a new InsightsChartSeriesMetadataAxis object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsChartSeriesMetadataAxisWithDefaults() *InsightsChartSeriesMetadataAxis { + this := InsightsChartSeriesMetadataAxis{} + return &this +} + +// GetUnit returns the Unit field value +func (o *InsightsChartSeriesMetadataAxis) GetUnit() string { + if o == nil { + var ret string + return ret + } + + return o.Unit +} + +// GetUnitOk returns a tuple with the Unit field value +// and a boolean to check if the value has been set. +func (o *InsightsChartSeriesMetadataAxis) GetUnitOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Unit, true +} + +// SetUnit sets field value +func (o *InsightsChartSeriesMetadataAxis) SetUnit(v string) { + o.Unit = v +} + +func (o InsightsChartSeriesMetadataAxis) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["unit"] = o.Unit + } + return json.Marshal(toSerialize) +} + +type NullableInsightsChartSeriesMetadataAxis struct { + value *InsightsChartSeriesMetadataAxis + isSet bool +} + +func (v NullableInsightsChartSeriesMetadataAxis) Get() *InsightsChartSeriesMetadataAxis { + return v.value +} + +func (v *NullableInsightsChartSeriesMetadataAxis) Set(val *InsightsChartSeriesMetadataAxis) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsChartSeriesMetadataAxis) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsChartSeriesMetadataAxis) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsChartSeriesMetadataAxis(val *InsightsChartSeriesMetadataAxis) *NullableInsightsChartSeriesMetadataAxis { + return &NullableInsightsChartSeriesMetadataAxis{value: val, isSet: true} +} + +func (v NullableInsightsChartSeriesMetadataAxis) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsChartSeriesMetadataAxis) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_indicator_range.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_indicator_range.go new file mode 100644 index 00000000..941bf08b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_indicator_range.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsMetricIndicatorRange struct for InsightsMetricIndicatorRange +type InsightsMetricIndicatorRange struct { + // The minimum value for the indicator range + Min int32 `json:"min"` + // The maximum value for the indicator range + Max int32 `json:"max"` +} + +// NewInsightsMetricIndicatorRange instantiates a new InsightsMetricIndicatorRange object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsMetricIndicatorRange(min int32, max int32) *InsightsMetricIndicatorRange { + this := InsightsMetricIndicatorRange{} + this.Min = min + this.Max = max + return &this +} + +// NewInsightsMetricIndicatorRangeWithDefaults instantiates a new InsightsMetricIndicatorRange object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsMetricIndicatorRangeWithDefaults() *InsightsMetricIndicatorRange { + this := InsightsMetricIndicatorRange{} + return &this +} + +// GetMin returns the Min field value +func (o *InsightsMetricIndicatorRange) GetMin() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Min +} + +// GetMinOk returns a tuple with the Min field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricIndicatorRange) GetMinOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Min, true +} + +// SetMin sets field value +func (o *InsightsMetricIndicatorRange) SetMin(v int32) { + o.Min = v +} + +// GetMax returns the Max field value +func (o *InsightsMetricIndicatorRange) GetMax() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Max +} + +// GetMaxOk returns a tuple with the Max field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricIndicatorRange) GetMaxOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Max, true +} + +// SetMax sets field value +func (o *InsightsMetricIndicatorRange) SetMax(v int32) { + o.Max = v +} + +func (o InsightsMetricIndicatorRange) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["min"] = o.Min + } + if true { + toSerialize["max"] = o.Max + } + return json.Marshal(toSerialize) +} + +type NullableInsightsMetricIndicatorRange struct { + value *InsightsMetricIndicatorRange + isSet bool +} + +func (v NullableInsightsMetricIndicatorRange) Get() *InsightsMetricIndicatorRange { + return v.value +} + +func (v *NullableInsightsMetricIndicatorRange) Set(val *InsightsMetricIndicatorRange) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsMetricIndicatorRange) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsMetricIndicatorRange) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsMetricIndicatorRange(val *InsightsMetricIndicatorRange) *NullableInsightsMetricIndicatorRange { + return &NullableInsightsMetricIndicatorRange{value: val, isSet: true} +} + +func (v NullableInsightsMetricIndicatorRange) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsMetricIndicatorRange) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_score.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_score.go new file mode 100644 index 00000000..c00284df --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_score.go @@ -0,0 +1,277 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsMetricScore struct for InsightsMetricScore +type InsightsMetricScore struct { + // The score for the metric + Score int32 `json:"score"` + // The keys of the metrics that were aggregated to calculate this score + AggregateOf []string `json:"aggregateOf,omitempty"` + DiffVsLastPeriod *int32 `json:"diffVsLastPeriod,omitempty"` + Indicator string `json:"indicator"` + IndicatorRange InsightsMetricIndicatorRange `json:"indicatorRange"` + LastPeriod *InsightsMetricScore `json:"lastPeriod,omitempty"` +} + +// NewInsightsMetricScore instantiates a new InsightsMetricScore object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsMetricScore(score int32, indicator string, indicatorRange InsightsMetricIndicatorRange) *InsightsMetricScore { + this := InsightsMetricScore{} + this.Score = score + this.Indicator = indicator + this.IndicatorRange = indicatorRange + return &this +} + +// NewInsightsMetricScoreWithDefaults instantiates a new InsightsMetricScore object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsMetricScoreWithDefaults() *InsightsMetricScore { + this := InsightsMetricScore{} + return &this +} + +// GetScore returns the Score field value +func (o *InsightsMetricScore) GetScore() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Score +} + +// GetScoreOk returns a tuple with the Score field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetScoreOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Score, true +} + +// SetScore sets field value +func (o *InsightsMetricScore) SetScore(v int32) { + o.Score = v +} + +// GetAggregateOf returns the AggregateOf field value if set, zero value otherwise. +func (o *InsightsMetricScore) GetAggregateOf() []string { + if o == nil || o.AggregateOf == nil { + var ret []string + return ret + } + return o.AggregateOf +} + +// GetAggregateOfOk returns a tuple with the AggregateOf field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetAggregateOfOk() ([]string, bool) { + if o == nil || o.AggregateOf == nil { + return nil, false + } + return o.AggregateOf, true +} + +// HasAggregateOf returns a boolean if a field has been set. +func (o *InsightsMetricScore) HasAggregateOf() bool { + if o != nil && o.AggregateOf != nil { + return true + } + + return false +} + +// SetAggregateOf gets a reference to the given []string and assigns it to the AggregateOf field. +func (o *InsightsMetricScore) SetAggregateOf(v []string) { + o.AggregateOf = v +} + +// GetDiffVsLastPeriod returns the DiffVsLastPeriod field value if set, zero value otherwise. +func (o *InsightsMetricScore) GetDiffVsLastPeriod() int32 { + if o == nil || o.DiffVsLastPeriod == nil { + var ret int32 + return ret + } + return *o.DiffVsLastPeriod +} + +// GetDiffVsLastPeriodOk returns a tuple with the DiffVsLastPeriod field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetDiffVsLastPeriodOk() (*int32, bool) { + if o == nil || o.DiffVsLastPeriod == nil { + return nil, false + } + return o.DiffVsLastPeriod, true +} + +// HasDiffVsLastPeriod returns a boolean if a field has been set. +func (o *InsightsMetricScore) HasDiffVsLastPeriod() bool { + if o != nil && o.DiffVsLastPeriod != nil { + return true + } + + return false +} + +// SetDiffVsLastPeriod gets a reference to the given int32 and assigns it to the DiffVsLastPeriod field. +func (o *InsightsMetricScore) SetDiffVsLastPeriod(v int32) { + o.DiffVsLastPeriod = &v +} + +// GetIndicator returns the Indicator field value +func (o *InsightsMetricScore) GetIndicator() string { + if o == nil { + var ret string + return ret + } + + return o.Indicator +} + +// GetIndicatorOk returns a tuple with the Indicator field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetIndicatorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Indicator, true +} + +// SetIndicator sets field value +func (o *InsightsMetricScore) SetIndicator(v string) { + o.Indicator = v +} + +// GetIndicatorRange returns the IndicatorRange field value +func (o *InsightsMetricScore) GetIndicatorRange() InsightsMetricIndicatorRange { + if o == nil { + var ret InsightsMetricIndicatorRange + return ret + } + + return o.IndicatorRange +} + +// GetIndicatorRangeOk returns a tuple with the IndicatorRange field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetIndicatorRangeOk() (*InsightsMetricIndicatorRange, bool) { + if o == nil { + return nil, false + } + return &o.IndicatorRange, true +} + +// SetIndicatorRange sets field value +func (o *InsightsMetricScore) SetIndicatorRange(v InsightsMetricIndicatorRange) { + o.IndicatorRange = v +} + +// GetLastPeriod returns the LastPeriod field value if set, zero value otherwise. +func (o *InsightsMetricScore) GetLastPeriod() InsightsMetricScore { + if o == nil || o.LastPeriod == nil { + var ret InsightsMetricScore + return ret + } + return *o.LastPeriod +} + +// GetLastPeriodOk returns a tuple with the LastPeriod field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsMetricScore) GetLastPeriodOk() (*InsightsMetricScore, bool) { + if o == nil || o.LastPeriod == nil { + return nil, false + } + return o.LastPeriod, true +} + +// HasLastPeriod returns a boolean if a field has been set. +func (o *InsightsMetricScore) HasLastPeriod() bool { + if o != nil && o.LastPeriod != nil { + return true + } + + return false +} + +// SetLastPeriod gets a reference to the given InsightsMetricScore and assigns it to the LastPeriod field. +func (o *InsightsMetricScore) SetLastPeriod(v InsightsMetricScore) { + o.LastPeriod = &v +} + +func (o InsightsMetricScore) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["score"] = o.Score + } + if o.AggregateOf != nil { + toSerialize["aggregateOf"] = o.AggregateOf + } + if o.DiffVsLastPeriod != nil { + toSerialize["diffVsLastPeriod"] = o.DiffVsLastPeriod + } + if true { + toSerialize["indicator"] = o.Indicator + } + if true { + toSerialize["indicatorRange"] = o.IndicatorRange + } + if o.LastPeriod != nil { + toSerialize["lastPeriod"] = o.LastPeriod + } + return json.Marshal(toSerialize) +} + +type NullableInsightsMetricScore struct { + value *InsightsMetricScore + isSet bool +} + +func (v NullableInsightsMetricScore) Get() *InsightsMetricScore { + return v.value +} + +func (v *NullableInsightsMetricScore) Set(val *InsightsMetricScore) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsMetricScore) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsMetricScore) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsMetricScore(val *InsightsMetricScore) *NullableInsightsMetricScore { + return &NullableInsightsMetricScore{value: val, isSet: true} +} + +func (v NullableInsightsMetricScore) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsMetricScore) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_tier_definition.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_tier_definition.go new file mode 100644 index 00000000..ee960afd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_metric_tier_definition.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsMetricTierDefinition struct for InsightsMetricTierDefinition +type InsightsMetricTierDefinition struct { + // Metric indicator tier + Indicator string `json:"indicator"` + // Metric indicator description + Description string `json:"description"` +} + +// NewInsightsMetricTierDefinition instantiates a new InsightsMetricTierDefinition object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsMetricTierDefinition(indicator string, description string) *InsightsMetricTierDefinition { + this := InsightsMetricTierDefinition{} + this.Indicator = indicator + this.Description = description + return &this +} + +// NewInsightsMetricTierDefinitionWithDefaults instantiates a new InsightsMetricTierDefinition object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsMetricTierDefinitionWithDefaults() *InsightsMetricTierDefinition { + this := InsightsMetricTierDefinition{} + return &this +} + +// GetIndicator returns the Indicator field value +func (o *InsightsMetricTierDefinition) GetIndicator() string { + if o == nil { + var ret string + return ret + } + + return o.Indicator +} + +// GetIndicatorOk returns a tuple with the Indicator field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricTierDefinition) GetIndicatorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Indicator, true +} + +// SetIndicator sets field value +func (o *InsightsMetricTierDefinition) SetIndicator(v string) { + o.Indicator = v +} + +// GetDescription returns the Description field value +func (o *InsightsMetricTierDefinition) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *InsightsMetricTierDefinition) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *InsightsMetricTierDefinition) SetDescription(v string) { + o.Description = v +} + +func (o InsightsMetricTierDefinition) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["indicator"] = o.Indicator + } + if true { + toSerialize["description"] = o.Description + } + return json.Marshal(toSerialize) +} + +type NullableInsightsMetricTierDefinition struct { + value *InsightsMetricTierDefinition + isSet bool +} + +func (v NullableInsightsMetricTierDefinition) Get() *InsightsMetricTierDefinition { + return v.value +} + +func (v *NullableInsightsMetricTierDefinition) Set(val *InsightsMetricTierDefinition) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsMetricTierDefinition) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsMetricTierDefinition) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsMetricTierDefinition(val *InsightsMetricTierDefinition) *NullableInsightsMetricTierDefinition { + return &NullableInsightsMetricTierDefinition{value: val, isSet: true} +} + +func (v NullableInsightsMetricTierDefinition) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsMetricTierDefinition) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository.go new file mode 100644 index 00000000..05428117 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository.go @@ -0,0 +1,296 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsRepository struct for InsightsRepository +type InsightsRepository struct { + // The repository ID + Id string `json:"_id"` + // The repository version + Version int32 `json:"version"` + // The repository key + Key string `json:"key"` + // The repository type + Type string `json:"type"` + // The repository URL + Url string `json:"url"` + // The repository main branch + MainBranch string `json:"mainBranch"` + Projects *ProjectSummaryCollection `json:"projects,omitempty"` +} + +// NewInsightsRepository instantiates a new InsightsRepository object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsRepository(id string, version int32, key string, type_ string, url string, mainBranch string) *InsightsRepository { + this := InsightsRepository{} + this.Id = id + this.Version = version + this.Key = key + this.Type = type_ + this.Url = url + this.MainBranch = mainBranch + return &this +} + +// NewInsightsRepositoryWithDefaults instantiates a new InsightsRepository object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsRepositoryWithDefaults() *InsightsRepository { + this := InsightsRepository{} + return &this +} + +// GetId returns the Id field value +func (o *InsightsRepository) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *InsightsRepository) SetId(v string) { + o.Id = v +} + +// GetVersion returns the Version field value +func (o *InsightsRepository) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *InsightsRepository) SetVersion(v int32) { + o.Version = v +} + +// GetKey returns the Key field value +func (o *InsightsRepository) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *InsightsRepository) SetKey(v string) { + o.Key = v +} + +// GetType returns the Type field value +func (o *InsightsRepository) GetType() string { + if o == nil { + var ret string + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *InsightsRepository) SetType(v string) { + o.Type = v +} + +// GetUrl returns the Url field value +func (o *InsightsRepository) GetUrl() string { + if o == nil { + var ret string + return ret + } + + return o.Url +} + +// GetUrlOk returns a tuple with the Url field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Url, true +} + +// SetUrl sets field value +func (o *InsightsRepository) SetUrl(v string) { + o.Url = v +} + +// GetMainBranch returns the MainBranch field value +func (o *InsightsRepository) GetMainBranch() string { + if o == nil { + var ret string + return ret + } + + return o.MainBranch +} + +// GetMainBranchOk returns a tuple with the MainBranch field value +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetMainBranchOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MainBranch, true +} + +// SetMainBranch sets field value +func (o *InsightsRepository) SetMainBranch(v string) { + o.MainBranch = v +} + +// GetProjects returns the Projects field value if set, zero value otherwise. +func (o *InsightsRepository) GetProjects() ProjectSummaryCollection { + if o == nil || o.Projects == nil { + var ret ProjectSummaryCollection + return ret + } + return *o.Projects +} + +// GetProjectsOk returns a tuple with the Projects field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsRepository) GetProjectsOk() (*ProjectSummaryCollection, bool) { + if o == nil || o.Projects == nil { + return nil, false + } + return o.Projects, true +} + +// HasProjects returns a boolean if a field has been set. +func (o *InsightsRepository) HasProjects() bool { + if o != nil && o.Projects != nil { + return true + } + + return false +} + +// SetProjects gets a reference to the given ProjectSummaryCollection and assigns it to the Projects field. +func (o *InsightsRepository) SetProjects(v ProjectSummaryCollection) { + o.Projects = &v +} + +func (o InsightsRepository) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["version"] = o.Version + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["type"] = o.Type + } + if true { + toSerialize["url"] = o.Url + } + if true { + toSerialize["mainBranch"] = o.MainBranch + } + if o.Projects != nil { + toSerialize["projects"] = o.Projects + } + return json.Marshal(toSerialize) +} + +type NullableInsightsRepository struct { + value *InsightsRepository + isSet bool +} + +func (v NullableInsightsRepository) Get() *InsightsRepository { + return v.value +} + +func (v *NullableInsightsRepository) Set(val *InsightsRepository) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsRepository) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsRepository) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsRepository(val *InsightsRepository) *NullableInsightsRepository { + return &NullableInsightsRepository{value: val, isSet: true} +} + +func (v NullableInsightsRepository) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsRepository) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_collection.go new file mode 100644 index 00000000..92a23989 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_collection.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsRepositoryCollection struct for InsightsRepositoryCollection +type InsightsRepositoryCollection struct { + // Total number of repositories + TotalCount int32 `json:"totalCount"` + // List of repositories + Items []InsightsRepository `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewInsightsRepositoryCollection instantiates a new InsightsRepositoryCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsRepositoryCollection(totalCount int32, items []InsightsRepository) *InsightsRepositoryCollection { + this := InsightsRepositoryCollection{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewInsightsRepositoryCollectionWithDefaults instantiates a new InsightsRepositoryCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsRepositoryCollectionWithDefaults() *InsightsRepositoryCollection { + this := InsightsRepositoryCollection{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *InsightsRepositoryCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *InsightsRepositoryCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *InsightsRepositoryCollection) GetItems() []InsightsRepository { + if o == nil { + var ret []InsightsRepository + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryCollection) GetItemsOk() ([]InsightsRepository, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *InsightsRepositoryCollection) SetItems(v []InsightsRepository) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *InsightsRepositoryCollection) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *InsightsRepositoryCollection) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *InsightsRepositoryCollection) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o InsightsRepositoryCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableInsightsRepositoryCollection struct { + value *InsightsRepositoryCollection + isSet bool +} + +func (v NullableInsightsRepositoryCollection) Get() *InsightsRepositoryCollection { + return v.value +} + +func (v *NullableInsightsRepositoryCollection) Set(val *InsightsRepositoryCollection) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsRepositoryCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsRepositoryCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsRepositoryCollection(val *InsightsRepositoryCollection) *NullableInsightsRepositoryCollection { + return &NullableInsightsRepositoryCollection{value: val, isSet: true} +} + +func (v NullableInsightsRepositoryCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsRepositoryCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project.go new file mode 100644 index 00000000..6934d914 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsRepositoryProject struct for InsightsRepositoryProject +type InsightsRepositoryProject struct { + // The repository key + RepositoryKey string `json:"repositoryKey"` + // The project key + ProjectKey string `json:"projectKey"` +} + +// NewInsightsRepositoryProject instantiates a new InsightsRepositoryProject object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsRepositoryProject(repositoryKey string, projectKey string) *InsightsRepositoryProject { + this := InsightsRepositoryProject{} + this.RepositoryKey = repositoryKey + this.ProjectKey = projectKey + return &this +} + +// NewInsightsRepositoryProjectWithDefaults instantiates a new InsightsRepositoryProject object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsRepositoryProjectWithDefaults() *InsightsRepositoryProject { + this := InsightsRepositoryProject{} + return &this +} + +// GetRepositoryKey returns the RepositoryKey field value +func (o *InsightsRepositoryProject) GetRepositoryKey() string { + if o == nil { + var ret string + return ret + } + + return o.RepositoryKey +} + +// GetRepositoryKeyOk returns a tuple with the RepositoryKey field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProject) GetRepositoryKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.RepositoryKey, true +} + +// SetRepositoryKey sets field value +func (o *InsightsRepositoryProject) SetRepositoryKey(v string) { + o.RepositoryKey = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *InsightsRepositoryProject) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProject) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *InsightsRepositoryProject) SetProjectKey(v string) { + o.ProjectKey = v +} + +func (o InsightsRepositoryProject) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["repositoryKey"] = o.RepositoryKey + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + return json.Marshal(toSerialize) +} + +type NullableInsightsRepositoryProject struct { + value *InsightsRepositoryProject + isSet bool +} + +func (v NullableInsightsRepositoryProject) Get() *InsightsRepositoryProject { + return v.value +} + +func (v *NullableInsightsRepositoryProject) Set(val *InsightsRepositoryProject) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsRepositoryProject) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsRepositoryProject) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsRepositoryProject(val *InsightsRepositoryProject) *NullableInsightsRepositoryProject { + return &NullableInsightsRepositoryProject{value: val, isSet: true} +} + +func (v NullableInsightsRepositoryProject) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsRepositoryProject) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_collection.go new file mode 100644 index 00000000..150ae32b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_collection.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsRepositoryProjectCollection struct for InsightsRepositoryProjectCollection +type InsightsRepositoryProjectCollection struct { + // Total number of repository project associations + TotalCount int32 `json:"totalCount"` + // List of repository project associations + Items []InsightsRepositoryProject `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewInsightsRepositoryProjectCollection instantiates a new InsightsRepositoryProjectCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsRepositoryProjectCollection(totalCount int32, items []InsightsRepositoryProject) *InsightsRepositoryProjectCollection { + this := InsightsRepositoryProjectCollection{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewInsightsRepositoryProjectCollectionWithDefaults instantiates a new InsightsRepositoryProjectCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsRepositoryProjectCollectionWithDefaults() *InsightsRepositoryProjectCollection { + this := InsightsRepositoryProjectCollection{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *InsightsRepositoryProjectCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProjectCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *InsightsRepositoryProjectCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *InsightsRepositoryProjectCollection) GetItems() []InsightsRepositoryProject { + if o == nil { + var ret []InsightsRepositoryProject + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProjectCollection) GetItemsOk() ([]InsightsRepositoryProject, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *InsightsRepositoryProjectCollection) SetItems(v []InsightsRepositoryProject) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *InsightsRepositoryProjectCollection) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProjectCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *InsightsRepositoryProjectCollection) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *InsightsRepositoryProjectCollection) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o InsightsRepositoryProjectCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableInsightsRepositoryProjectCollection struct { + value *InsightsRepositoryProjectCollection + isSet bool +} + +func (v NullableInsightsRepositoryProjectCollection) Get() *InsightsRepositoryProjectCollection { + return v.value +} + +func (v *NullableInsightsRepositoryProjectCollection) Set(val *InsightsRepositoryProjectCollection) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsRepositoryProjectCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsRepositoryProjectCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsRepositoryProjectCollection(val *InsightsRepositoryProjectCollection) *NullableInsightsRepositoryProjectCollection { + return &NullableInsightsRepositoryProjectCollection{value: val, isSet: true} +} + +func (v NullableInsightsRepositoryProjectCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsRepositoryProjectCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_mappings.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_mappings.go new file mode 100644 index 00000000..4adcac9c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_insights_repository_project_mappings.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InsightsRepositoryProjectMappings struct for InsightsRepositoryProjectMappings +type InsightsRepositoryProjectMappings struct { + Mappings []InsightsRepositoryProject `json:"mappings"` +} + +// NewInsightsRepositoryProjectMappings instantiates a new InsightsRepositoryProjectMappings object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInsightsRepositoryProjectMappings(mappings []InsightsRepositoryProject) *InsightsRepositoryProjectMappings { + this := InsightsRepositoryProjectMappings{} + this.Mappings = mappings + return &this +} + +// NewInsightsRepositoryProjectMappingsWithDefaults instantiates a new InsightsRepositoryProjectMappings object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInsightsRepositoryProjectMappingsWithDefaults() *InsightsRepositoryProjectMappings { + this := InsightsRepositoryProjectMappings{} + return &this +} + +// GetMappings returns the Mappings field value +func (o *InsightsRepositoryProjectMappings) GetMappings() []InsightsRepositoryProject { + if o == nil { + var ret []InsightsRepositoryProject + return ret + } + + return o.Mappings +} + +// GetMappingsOk returns a tuple with the Mappings field value +// and a boolean to check if the value has been set. +func (o *InsightsRepositoryProjectMappings) GetMappingsOk() ([]InsightsRepositoryProject, bool) { + if o == nil { + return nil, false + } + return o.Mappings, true +} + +// SetMappings sets field value +func (o *InsightsRepositoryProjectMappings) SetMappings(v []InsightsRepositoryProject) { + o.Mappings = v +} + +func (o InsightsRepositoryProjectMappings) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["mappings"] = o.Mappings + } + return json.Marshal(toSerialize) +} + +type NullableInsightsRepositoryProjectMappings struct { + value *InsightsRepositoryProjectMappings + isSet bool +} + +func (v NullableInsightsRepositoryProjectMappings) Get() *InsightsRepositoryProjectMappings { + return v.value +} + +func (v *NullableInsightsRepositoryProjectMappings) Set(val *InsightsRepositoryProjectMappings) { + v.value = val + v.isSet = true +} + +func (v NullableInsightsRepositoryProjectMappings) IsSet() bool { + return v.isSet +} + +func (v *NullableInsightsRepositoryProjectMappings) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInsightsRepositoryProjectMappings(val *InsightsRepositoryProjectMappings) *NullableInsightsRepositoryProjectMappings { + return &NullableInsightsRepositoryProjectMappings{value: val, isSet: true} +} + +func (v NullableInsightsRepositoryProjectMappings) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInsightsRepositoryProjectMappings) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_instruction_user_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_instruction_user_request.go new file mode 100644 index 00000000..2162ef3b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_instruction_user_request.go @@ -0,0 +1,244 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InstructionUserRequest struct for InstructionUserRequest +type InstructionUserRequest struct { + // The type of change to make to the removal date for this user from individual targeting for this flag. + Kind string `json:"kind"` + // The flag key + FlagKey string `json:"flagKey"` + // ID of a variation on the flag + VariationId string `json:"variationId"` + // The time, in Unix milliseconds, when LaunchDarkly should remove the user from individual targeting for this flag. Required if kind is addExpireUserTargetDate or updateExpireUserTargetDate. + Value *int32 `json:"value,omitempty"` + // The version of the expiring user target to update. Optional and only used if kind is updateExpireUserTargetDate. If included, update will fail if version doesn't match current version of the expiring user target. + Version *int32 `json:"version,omitempty"` +} + +// NewInstructionUserRequest instantiates a new InstructionUserRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInstructionUserRequest(kind string, flagKey string, variationId string) *InstructionUserRequest { + this := InstructionUserRequest{} + this.Kind = kind + this.FlagKey = flagKey + this.VariationId = variationId + return &this +} + +// NewInstructionUserRequestWithDefaults instantiates a new InstructionUserRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInstructionUserRequestWithDefaults() *InstructionUserRequest { + this := InstructionUserRequest{} + return &this +} + +// GetKind returns the Kind field value +func (o *InstructionUserRequest) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *InstructionUserRequest) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *InstructionUserRequest) SetKind(v string) { + o.Kind = v +} + +// GetFlagKey returns the FlagKey field value +func (o *InstructionUserRequest) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *InstructionUserRequest) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *InstructionUserRequest) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetVariationId returns the VariationId field value +func (o *InstructionUserRequest) GetVariationId() string { + if o == nil { + var ret string + return ret + } + + return o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value +// and a boolean to check if the value has been set. +func (o *InstructionUserRequest) GetVariationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VariationId, true +} + +// SetVariationId sets field value +func (o *InstructionUserRequest) SetVariationId(v string) { + o.VariationId = v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *InstructionUserRequest) GetValue() int32 { + if o == nil || o.Value == nil { + var ret int32 + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstructionUserRequest) GetValueOk() (*int32, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *InstructionUserRequest) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given int32 and assigns it to the Value field. +func (o *InstructionUserRequest) SetValue(v int32) { + o.Value = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *InstructionUserRequest) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstructionUserRequest) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *InstructionUserRequest) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *InstructionUserRequest) SetVersion(v int32) { + o.Version = &v +} + +func (o InstructionUserRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["variationId"] = o.VariationId + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableInstructionUserRequest struct { + value *InstructionUserRequest + isSet bool +} + +func (v NullableInstructionUserRequest) Get() *InstructionUserRequest { + return v.value +} + +func (v *NullableInstructionUserRequest) Set(val *InstructionUserRequest) { + v.value = val + v.isSet = true +} + +func (v NullableInstructionUserRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableInstructionUserRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInstructionUserRequest(val *InstructionUserRequest) *NullableInstructionUserRequest { + return &NullableInstructionUserRequest{value: val, isSet: true} +} + +func (v NullableInstructionUserRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInstructionUserRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration.go new file mode 100644 index 00000000..2a9e1ed6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration.go @@ -0,0 +1,522 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Integration struct for Integration +type Integration struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The ID for this integration audit log subscription + Id *string `json:"_id,omitempty"` + // The type of integration + Kind *string `json:"kind,omitempty"` + // A human-friendly name for the integration + Name *string `json:"name,omitempty"` + // Details on configuration for an integration of this type. Refer to the formVariables field in the corresponding manifest.json for a full list of fields for each integration. + Config map[string]interface{} `json:"config,omitempty"` + // Represents a Custom role policy, defining a resource kinds filter the integration audit log subscription responds to. + Statements []Statement `json:"statements,omitempty"` + // Whether the integration is currently active + On *bool `json:"on,omitempty"` + // An array of tags for this integration + Tags []string `json:"tags,omitempty"` + Access *Access `json:"_access,omitempty"` + Status *IntegrationSubscriptionStatusRep `json:"_status,omitempty"` + // Slack webhook receiver URL. Only used for legacy Slack webhook integrations. + Url *string `json:"url,omitempty"` + // Datadog API key. Only used for legacy Datadog webhook integrations. + ApiKey *string `json:"apiKey,omitempty"` +} + +// NewIntegration instantiates a new Integration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegration() *Integration { + this := Integration{} + return &this +} + +// NewIntegrationWithDefaults instantiates a new Integration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationWithDefaults() *Integration { + this := Integration{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Integration) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Integration) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Integration) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Integration) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Integration) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Integration) SetId(v string) { + o.Id = &v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *Integration) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *Integration) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *Integration) SetKind(v string) { + o.Kind = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Integration) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Integration) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Integration) SetName(v string) { + o.Name = &v +} + +// GetConfig returns the Config field value if set, zero value otherwise. +func (o *Integration) GetConfig() map[string]interface{} { + if o == nil || o.Config == nil { + var ret map[string]interface{} + return ret + } + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetConfigOk() (map[string]interface{}, bool) { + if o == nil || o.Config == nil { + return nil, false + } + return o.Config, true +} + +// HasConfig returns a boolean if a field has been set. +func (o *Integration) HasConfig() bool { + if o != nil && o.Config != nil { + return true + } + + return false +} + +// SetConfig gets a reference to the given map[string]interface{} and assigns it to the Config field. +func (o *Integration) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *Integration) GetStatements() []Statement { + if o == nil || o.Statements == nil { + var ret []Statement + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetStatementsOk() ([]Statement, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *Integration) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []Statement and assigns it to the Statements field. +func (o *Integration) SetStatements(v []Statement) { + o.Statements = v +} + +// GetOn returns the On field value if set, zero value otherwise. +func (o *Integration) GetOn() bool { + if o == nil || o.On == nil { + var ret bool + return ret + } + return *o.On +} + +// GetOnOk returns a tuple with the On field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetOnOk() (*bool, bool) { + if o == nil || o.On == nil { + return nil, false + } + return o.On, true +} + +// HasOn returns a boolean if a field has been set. +func (o *Integration) HasOn() bool { + if o != nil && o.On != nil { + return true + } + + return false +} + +// SetOn gets a reference to the given bool and assigns it to the On field. +func (o *Integration) SetOn(v bool) { + o.On = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *Integration) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *Integration) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *Integration) SetTags(v []string) { + o.Tags = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *Integration) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *Integration) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *Integration) SetAccess(v Access) { + o.Access = &v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *Integration) GetStatus() IntegrationSubscriptionStatusRep { + if o == nil || o.Status == nil { + var ret IntegrationSubscriptionStatusRep + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetStatusOk() (*IntegrationSubscriptionStatusRep, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *Integration) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given IntegrationSubscriptionStatusRep and assigns it to the Status field. +func (o *Integration) SetStatus(v IntegrationSubscriptionStatusRep) { + o.Status = &v +} + +// GetUrl returns the Url field value if set, zero value otherwise. +func (o *Integration) GetUrl() string { + if o == nil || o.Url == nil { + var ret string + return ret + } + return *o.Url +} + +// GetUrlOk returns a tuple with the Url field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetUrlOk() (*string, bool) { + if o == nil || o.Url == nil { + return nil, false + } + return o.Url, true +} + +// HasUrl returns a boolean if a field has been set. +func (o *Integration) HasUrl() bool { + if o != nil && o.Url != nil { + return true + } + + return false +} + +// SetUrl gets a reference to the given string and assigns it to the Url field. +func (o *Integration) SetUrl(v string) { + o.Url = &v +} + +// GetApiKey returns the ApiKey field value if set, zero value otherwise. +func (o *Integration) GetApiKey() string { + if o == nil || o.ApiKey == nil { + var ret string + return ret + } + return *o.ApiKey +} + +// GetApiKeyOk returns a tuple with the ApiKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integration) GetApiKeyOk() (*string, bool) { + if o == nil || o.ApiKey == nil { + return nil, false + } + return o.ApiKey, true +} + +// HasApiKey returns a boolean if a field has been set. +func (o *Integration) HasApiKey() bool { + if o != nil && o.ApiKey != nil { + return true + } + + return false +} + +// SetApiKey gets a reference to the given string and assigns it to the ApiKey field. +func (o *Integration) SetApiKey(v string) { + o.ApiKey = &v +} + +func (o Integration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Config != nil { + toSerialize["config"] = o.Config + } + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + if o.On != nil { + toSerialize["on"] = o.On + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Status != nil { + toSerialize["_status"] = o.Status + } + if o.Url != nil { + toSerialize["url"] = o.Url + } + if o.ApiKey != nil { + toSerialize["apiKey"] = o.ApiKey + } + return json.Marshal(toSerialize) +} + +type NullableIntegration struct { + value *Integration + isSet bool +} + +func (v NullableIntegration) Get() *Integration { + return v.value +} + +func (v *NullableIntegration) Set(val *Integration) { + v.value = val + v.isSet = true +} + +func (v NullableIntegration) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegration(val *Integration) *NullableIntegration { + return &NullableIntegration{value: val, isSet: true} +} + +func (v NullableIntegration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_collection_rep.go new file mode 100644 index 00000000..9fd6be49 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationConfigurationCollectionRep struct for IntegrationConfigurationCollectionRep +type IntegrationConfigurationCollectionRep struct { + // An array of integration configurations + Items []IntegrationConfigurationsRep `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewIntegrationConfigurationCollectionRep instantiates a new IntegrationConfigurationCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationConfigurationCollectionRep(items []IntegrationConfigurationsRep, links map[string]Link) *IntegrationConfigurationCollectionRep { + this := IntegrationConfigurationCollectionRep{} + this.Items = items + this.Links = links + return &this +} + +// NewIntegrationConfigurationCollectionRepWithDefaults instantiates a new IntegrationConfigurationCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationConfigurationCollectionRepWithDefaults() *IntegrationConfigurationCollectionRep { + this := IntegrationConfigurationCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *IntegrationConfigurationCollectionRep) GetItems() []IntegrationConfigurationsRep { + if o == nil { + var ret []IntegrationConfigurationsRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationCollectionRep) GetItemsOk() ([]IntegrationConfigurationsRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *IntegrationConfigurationCollectionRep) SetItems(v []IntegrationConfigurationsRep) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *IntegrationConfigurationCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *IntegrationConfigurationCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o IntegrationConfigurationCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationConfigurationCollectionRep struct { + value *IntegrationConfigurationCollectionRep + isSet bool +} + +func (v NullableIntegrationConfigurationCollectionRep) Get() *IntegrationConfigurationCollectionRep { + return v.value +} + +func (v *NullableIntegrationConfigurationCollectionRep) Set(val *IntegrationConfigurationCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationConfigurationCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationConfigurationCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationConfigurationCollectionRep(val *IntegrationConfigurationCollectionRep) *NullableIntegrationConfigurationCollectionRep { + return &NullableIntegrationConfigurationCollectionRep{value: val, isSet: true} +} + +func (v NullableIntegrationConfigurationCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationConfigurationCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_post.go new file mode 100644 index 00000000..a101a529 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configuration_post.go @@ -0,0 +1,250 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationConfigurationPost struct for IntegrationConfigurationPost +type IntegrationConfigurationPost struct { + // The name of the integration configuration + Name string `json:"name"` + // Whether the integration configuration is enabled. If omitted, defaults to true + Enabled *bool `json:"enabled,omitempty"` + // Tags for the integration + Tags []string `json:"tags,omitempty"` + // The unique set of fields required to configure the integration. Refer to the formVariables field in the corresponding manifest.json at https://github.com/launchdarkly/integration-framework/tree/main/integrations for a full list of fields for the integration you wish to configure. + ConfigValues map[string]interface{} `json:"configValues"` + CapabilityConfig *CapabilityConfigPost `json:"capabilityConfig,omitempty"` +} + +// NewIntegrationConfigurationPost instantiates a new IntegrationConfigurationPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationConfigurationPost(name string, configValues map[string]interface{}) *IntegrationConfigurationPost { + this := IntegrationConfigurationPost{} + this.Name = name + this.ConfigValues = configValues + return &this +} + +// NewIntegrationConfigurationPostWithDefaults instantiates a new IntegrationConfigurationPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationConfigurationPostWithDefaults() *IntegrationConfigurationPost { + this := IntegrationConfigurationPost{} + return &this +} + +// GetName returns the Name field value +func (o *IntegrationConfigurationPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *IntegrationConfigurationPost) SetName(v string) { + o.Name = v +} + +// GetEnabled returns the Enabled field value if set, zero value otherwise. +func (o *IntegrationConfigurationPost) GetEnabled() bool { + if o == nil || o.Enabled == nil { + var ret bool + return ret + } + return *o.Enabled +} + +// GetEnabledOk returns a tuple with the Enabled field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationPost) GetEnabledOk() (*bool, bool) { + if o == nil || o.Enabled == nil { + return nil, false + } + return o.Enabled, true +} + +// HasEnabled returns a boolean if a field has been set. +func (o *IntegrationConfigurationPost) HasEnabled() bool { + if o != nil && o.Enabled != nil { + return true + } + + return false +} + +// SetEnabled gets a reference to the given bool and assigns it to the Enabled field. +func (o *IntegrationConfigurationPost) SetEnabled(v bool) { + o.Enabled = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *IntegrationConfigurationPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *IntegrationConfigurationPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *IntegrationConfigurationPost) SetTags(v []string) { + o.Tags = v +} + +// GetConfigValues returns the ConfigValues field value +func (o *IntegrationConfigurationPost) GetConfigValues() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.ConfigValues +} + +// GetConfigValuesOk returns a tuple with the ConfigValues field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationPost) GetConfigValuesOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.ConfigValues, true +} + +// SetConfigValues sets field value +func (o *IntegrationConfigurationPost) SetConfigValues(v map[string]interface{}) { + o.ConfigValues = v +} + +// GetCapabilityConfig returns the CapabilityConfig field value if set, zero value otherwise. +func (o *IntegrationConfigurationPost) GetCapabilityConfig() CapabilityConfigPost { + if o == nil || o.CapabilityConfig == nil { + var ret CapabilityConfigPost + return ret + } + return *o.CapabilityConfig +} + +// GetCapabilityConfigOk returns a tuple with the CapabilityConfig field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationPost) GetCapabilityConfigOk() (*CapabilityConfigPost, bool) { + if o == nil || o.CapabilityConfig == nil { + return nil, false + } + return o.CapabilityConfig, true +} + +// HasCapabilityConfig returns a boolean if a field has been set. +func (o *IntegrationConfigurationPost) HasCapabilityConfig() bool { + if o != nil && o.CapabilityConfig != nil { + return true + } + + return false +} + +// SetCapabilityConfig gets a reference to the given CapabilityConfigPost and assigns it to the CapabilityConfig field. +func (o *IntegrationConfigurationPost) SetCapabilityConfig(v CapabilityConfigPost) { + o.CapabilityConfig = &v +} + +func (o IntegrationConfigurationPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Enabled != nil { + toSerialize["enabled"] = o.Enabled + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["configValues"] = o.ConfigValues + } + if o.CapabilityConfig != nil { + toSerialize["capabilityConfig"] = o.CapabilityConfig + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationConfigurationPost struct { + value *IntegrationConfigurationPost + isSet bool +} + +func (v NullableIntegrationConfigurationPost) Get() *IntegrationConfigurationPost { + return v.value +} + +func (v *NullableIntegrationConfigurationPost) Set(val *IntegrationConfigurationPost) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationConfigurationPost) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationConfigurationPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationConfigurationPost(val *IntegrationConfigurationPost) *NullableIntegrationConfigurationPost { + return &NullableIntegrationConfigurationPost{value: val, isSet: true} +} + +func (v NullableIntegrationConfigurationPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationConfigurationPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configurations_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configurations_rep.go new file mode 100644 index 00000000..11a2a070 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_configurations_rep.go @@ -0,0 +1,426 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationConfigurationsRep struct for IntegrationConfigurationsRep +type IntegrationConfigurationsRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The unique identifier for this integration configuration + Id string `json:"_id"` + // A human-friendly name for the integration + Name string `json:"name"` + CreatedAt *int64 `json:"_createdAt,omitempty"` + // The type of integration + IntegrationKey *string `json:"_integrationKey,omitempty"` + // An array of tags for this integration + Tags []string `json:"tags,omitempty"` + // Whether the integration is currently active + Enabled *bool `json:"enabled,omitempty"` + Access *Access `json:"_access,omitempty"` + // Details on configuration for an integration of this type. Refer to the formVariables field in the corresponding manifest.json for a full list of fields for each integration. + ConfigValues map[string]interface{} `json:"configValues,omitempty"` + CapabilityConfig *CapabilityConfigRep `json:"capabilityConfig,omitempty"` +} + +// NewIntegrationConfigurationsRep instantiates a new IntegrationConfigurationsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationConfigurationsRep(links map[string]Link, id string, name string) *IntegrationConfigurationsRep { + this := IntegrationConfigurationsRep{} + this.Links = links + this.Id = id + this.Name = name + return &this +} + +// NewIntegrationConfigurationsRepWithDefaults instantiates a new IntegrationConfigurationsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationConfigurationsRepWithDefaults() *IntegrationConfigurationsRep { + this := IntegrationConfigurationsRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *IntegrationConfigurationsRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *IntegrationConfigurationsRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *IntegrationConfigurationsRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *IntegrationConfigurationsRep) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value +func (o *IntegrationConfigurationsRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *IntegrationConfigurationsRep) SetName(v string) { + o.Name = v +} + +// GetCreatedAt returns the CreatedAt field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetCreatedAt() int64 { + if o == nil || o.CreatedAt == nil { + var ret int64 + return ret + } + return *o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetCreatedAtOk() (*int64, bool) { + if o == nil || o.CreatedAt == nil { + return nil, false + } + return o.CreatedAt, true +} + +// HasCreatedAt returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasCreatedAt() bool { + if o != nil && o.CreatedAt != nil { + return true + } + + return false +} + +// SetCreatedAt gets a reference to the given int64 and assigns it to the CreatedAt field. +func (o *IntegrationConfigurationsRep) SetCreatedAt(v int64) { + o.CreatedAt = &v +} + +// GetIntegrationKey returns the IntegrationKey field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetIntegrationKey() string { + if o == nil || o.IntegrationKey == nil { + var ret string + return ret + } + return *o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetIntegrationKeyOk() (*string, bool) { + if o == nil || o.IntegrationKey == nil { + return nil, false + } + return o.IntegrationKey, true +} + +// HasIntegrationKey returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasIntegrationKey() bool { + if o != nil && o.IntegrationKey != nil { + return true + } + + return false +} + +// SetIntegrationKey gets a reference to the given string and assigns it to the IntegrationKey field. +func (o *IntegrationConfigurationsRep) SetIntegrationKey(v string) { + o.IntegrationKey = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *IntegrationConfigurationsRep) SetTags(v []string) { + o.Tags = v +} + +// GetEnabled returns the Enabled field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetEnabled() bool { + if o == nil || o.Enabled == nil { + var ret bool + return ret + } + return *o.Enabled +} + +// GetEnabledOk returns a tuple with the Enabled field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetEnabledOk() (*bool, bool) { + if o == nil || o.Enabled == nil { + return nil, false + } + return o.Enabled, true +} + +// HasEnabled returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasEnabled() bool { + if o != nil && o.Enabled != nil { + return true + } + + return false +} + +// SetEnabled gets a reference to the given bool and assigns it to the Enabled field. +func (o *IntegrationConfigurationsRep) SetEnabled(v bool) { + o.Enabled = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *IntegrationConfigurationsRep) SetAccess(v Access) { + o.Access = &v +} + +// GetConfigValues returns the ConfigValues field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetConfigValues() map[string]interface{} { + if o == nil || o.ConfigValues == nil { + var ret map[string]interface{} + return ret + } + return o.ConfigValues +} + +// GetConfigValuesOk returns a tuple with the ConfigValues field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetConfigValuesOk() (map[string]interface{}, bool) { + if o == nil || o.ConfigValues == nil { + return nil, false + } + return o.ConfigValues, true +} + +// HasConfigValues returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasConfigValues() bool { + if o != nil && o.ConfigValues != nil { + return true + } + + return false +} + +// SetConfigValues gets a reference to the given map[string]interface{} and assigns it to the ConfigValues field. +func (o *IntegrationConfigurationsRep) SetConfigValues(v map[string]interface{}) { + o.ConfigValues = v +} + +// GetCapabilityConfig returns the CapabilityConfig field value if set, zero value otherwise. +func (o *IntegrationConfigurationsRep) GetCapabilityConfig() CapabilityConfigRep { + if o == nil || o.CapabilityConfig == nil { + var ret CapabilityConfigRep + return ret + } + return *o.CapabilityConfig +} + +// GetCapabilityConfigOk returns a tuple with the CapabilityConfig field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationConfigurationsRep) GetCapabilityConfigOk() (*CapabilityConfigRep, bool) { + if o == nil || o.CapabilityConfig == nil { + return nil, false + } + return o.CapabilityConfig, true +} + +// HasCapabilityConfig returns a boolean if a field has been set. +func (o *IntegrationConfigurationsRep) HasCapabilityConfig() bool { + if o != nil && o.CapabilityConfig != nil { + return true + } + + return false +} + +// SetCapabilityConfig gets a reference to the given CapabilityConfigRep and assigns it to the CapabilityConfig field. +func (o *IntegrationConfigurationsRep) SetCapabilityConfig(v CapabilityConfigRep) { + o.CapabilityConfig = &v +} + +func (o IntegrationConfigurationsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["name"] = o.Name + } + if o.CreatedAt != nil { + toSerialize["_createdAt"] = o.CreatedAt + } + if o.IntegrationKey != nil { + toSerialize["_integrationKey"] = o.IntegrationKey + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Enabled != nil { + toSerialize["enabled"] = o.Enabled + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.ConfigValues != nil { + toSerialize["configValues"] = o.ConfigValues + } + if o.CapabilityConfig != nil { + toSerialize["capabilityConfig"] = o.CapabilityConfig + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationConfigurationsRep struct { + value *IntegrationConfigurationsRep + isSet bool +} + +func (v NullableIntegrationConfigurationsRep) Get() *IntegrationConfigurationsRep { + return v.value +} + +func (v *NullableIntegrationConfigurationsRep) Set(val *IntegrationConfigurationsRep) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationConfigurationsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationConfigurationsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationConfigurationsRep(val *IntegrationConfigurationsRep) *NullableIntegrationConfigurationsRep { + return &NullableIntegrationConfigurationsRep{value: val, isSet: true} +} + +func (v NullableIntegrationConfigurationsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationConfigurationsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration.go new file mode 100644 index 00000000..e40dc041 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration.go @@ -0,0 +1,414 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfiguration struct for IntegrationDeliveryConfiguration +type IntegrationDeliveryConfiguration struct { + Links IntegrationDeliveryConfigurationLinks `json:"_links"` + // The integration ID + Id string `json:"_id"` + // The integration key + IntegrationKey string `json:"integrationKey"` + // The project key + ProjectKey string `json:"projectKey"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + Config map[string]interface{} `json:"config"` + // Whether the configuration is turned on + On bool `json:"on"` + // List of tags for this configuration + Tags []string `json:"tags"` + // Name of the configuration + Name string `json:"name"` + // Version of the current configuration + Version int32 `json:"version"` + Access *Access `json:"_access,omitempty"` +} + +// NewIntegrationDeliveryConfiguration instantiates a new IntegrationDeliveryConfiguration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfiguration(links IntegrationDeliveryConfigurationLinks, id string, integrationKey string, projectKey string, environmentKey string, config map[string]interface{}, on bool, tags []string, name string, version int32) *IntegrationDeliveryConfiguration { + this := IntegrationDeliveryConfiguration{} + this.Links = links + this.Id = id + this.IntegrationKey = integrationKey + this.ProjectKey = projectKey + this.EnvironmentKey = environmentKey + this.Config = config + this.On = on + this.Tags = tags + this.Name = name + this.Version = version + return &this +} + +// NewIntegrationDeliveryConfigurationWithDefaults instantiates a new IntegrationDeliveryConfiguration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationWithDefaults() *IntegrationDeliveryConfiguration { + this := IntegrationDeliveryConfiguration{} + return &this +} + +// GetLinks returns the Links field value +func (o *IntegrationDeliveryConfiguration) GetLinks() IntegrationDeliveryConfigurationLinks { + if o == nil { + var ret IntegrationDeliveryConfigurationLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetLinksOk() (*IntegrationDeliveryConfigurationLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *IntegrationDeliveryConfiguration) SetLinks(v IntegrationDeliveryConfigurationLinks) { + o.Links = v +} + +// GetId returns the Id field value +func (o *IntegrationDeliveryConfiguration) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *IntegrationDeliveryConfiguration) SetId(v string) { + o.Id = v +} + +// GetIntegrationKey returns the IntegrationKey field value +func (o *IntegrationDeliveryConfiguration) GetIntegrationKey() string { + if o == nil { + var ret string + return ret + } + + return o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetIntegrationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.IntegrationKey, true +} + +// SetIntegrationKey sets field value +func (o *IntegrationDeliveryConfiguration) SetIntegrationKey(v string) { + o.IntegrationKey = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *IntegrationDeliveryConfiguration) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *IntegrationDeliveryConfiguration) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *IntegrationDeliveryConfiguration) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *IntegrationDeliveryConfiguration) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetConfig returns the Config field value +func (o *IntegrationDeliveryConfiguration) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *IntegrationDeliveryConfiguration) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetOn returns the On field value +func (o *IntegrationDeliveryConfiguration) GetOn() bool { + if o == nil { + var ret bool + return ret + } + + return o.On +} + +// GetOnOk returns a tuple with the On field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetOnOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.On, true +} + +// SetOn sets field value +func (o *IntegrationDeliveryConfiguration) SetOn(v bool) { + o.On = v +} + +// GetTags returns the Tags field value +func (o *IntegrationDeliveryConfiguration) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *IntegrationDeliveryConfiguration) SetTags(v []string) { + o.Tags = v +} + +// GetName returns the Name field value +func (o *IntegrationDeliveryConfiguration) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *IntegrationDeliveryConfiguration) SetName(v string) { + o.Name = v +} + +// GetVersion returns the Version field value +func (o *IntegrationDeliveryConfiguration) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *IntegrationDeliveryConfiguration) SetVersion(v int32) { + o.Version = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfiguration) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfiguration) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfiguration) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *IntegrationDeliveryConfiguration) SetAccess(v Access) { + o.Access = &v +} + +func (o IntegrationDeliveryConfiguration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["integrationKey"] = o.IntegrationKey + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["config"] = o.Config + } + if true { + toSerialize["on"] = o.On + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["version"] = o.Version + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfiguration struct { + value *IntegrationDeliveryConfiguration + isSet bool +} + +func (v NullableIntegrationDeliveryConfiguration) Get() *IntegrationDeliveryConfiguration { + return v.value +} + +func (v *NullableIntegrationDeliveryConfiguration) Set(val *IntegrationDeliveryConfiguration) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfiguration) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfiguration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfiguration(val *IntegrationDeliveryConfiguration) *NullableIntegrationDeliveryConfiguration { + return &NullableIntegrationDeliveryConfiguration{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfiguration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfiguration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection.go new file mode 100644 index 00000000..f493aa96 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfigurationCollection struct for IntegrationDeliveryConfigurationCollection +type IntegrationDeliveryConfigurationCollection struct { + Links IntegrationDeliveryConfigurationCollectionLinks `json:"_links"` + // An array of integration delivery configurations + Items []IntegrationDeliveryConfiguration `json:"items"` +} + +// NewIntegrationDeliveryConfigurationCollection instantiates a new IntegrationDeliveryConfigurationCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfigurationCollection(links IntegrationDeliveryConfigurationCollectionLinks, items []IntegrationDeliveryConfiguration) *IntegrationDeliveryConfigurationCollection { + this := IntegrationDeliveryConfigurationCollection{} + this.Links = links + this.Items = items + return &this +} + +// NewIntegrationDeliveryConfigurationCollectionWithDefaults instantiates a new IntegrationDeliveryConfigurationCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationCollectionWithDefaults() *IntegrationDeliveryConfigurationCollection { + this := IntegrationDeliveryConfigurationCollection{} + return &this +} + +// GetLinks returns the Links field value +func (o *IntegrationDeliveryConfigurationCollection) GetLinks() IntegrationDeliveryConfigurationCollectionLinks { + if o == nil { + var ret IntegrationDeliveryConfigurationCollectionLinks + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationCollection) GetLinksOk() (*IntegrationDeliveryConfigurationCollectionLinks, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *IntegrationDeliveryConfigurationCollection) SetLinks(v IntegrationDeliveryConfigurationCollectionLinks) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *IntegrationDeliveryConfigurationCollection) GetItems() []IntegrationDeliveryConfiguration { + if o == nil { + var ret []IntegrationDeliveryConfiguration + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationCollection) GetItemsOk() ([]IntegrationDeliveryConfiguration, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *IntegrationDeliveryConfigurationCollection) SetItems(v []IntegrationDeliveryConfiguration) { + o.Items = v +} + +func (o IntegrationDeliveryConfigurationCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfigurationCollection struct { + value *IntegrationDeliveryConfigurationCollection + isSet bool +} + +func (v NullableIntegrationDeliveryConfigurationCollection) Get() *IntegrationDeliveryConfigurationCollection { + return v.value +} + +func (v *NullableIntegrationDeliveryConfigurationCollection) Set(val *IntegrationDeliveryConfigurationCollection) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfigurationCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfigurationCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfigurationCollection(val *IntegrationDeliveryConfigurationCollection) *NullableIntegrationDeliveryConfigurationCollection { + return &NullableIntegrationDeliveryConfigurationCollection{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfigurationCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfigurationCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection_links.go new file mode 100644 index 00000000..82334b83 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_collection_links.go @@ -0,0 +1,145 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfigurationCollectionLinks struct for IntegrationDeliveryConfigurationCollectionLinks +type IntegrationDeliveryConfigurationCollectionLinks struct { + Self Link `json:"self"` + Parent *Link `json:"parent,omitempty"` +} + +// NewIntegrationDeliveryConfigurationCollectionLinks instantiates a new IntegrationDeliveryConfigurationCollectionLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfigurationCollectionLinks(self Link) *IntegrationDeliveryConfigurationCollectionLinks { + this := IntegrationDeliveryConfigurationCollectionLinks{} + this.Self = self + return &this +} + +// NewIntegrationDeliveryConfigurationCollectionLinksWithDefaults instantiates a new IntegrationDeliveryConfigurationCollectionLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationCollectionLinksWithDefaults() *IntegrationDeliveryConfigurationCollectionLinks { + this := IntegrationDeliveryConfigurationCollectionLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *IntegrationDeliveryConfigurationCollectionLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationCollectionLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *IntegrationDeliveryConfigurationCollectionLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationCollectionLinks) GetParent() Link { + if o == nil || o.Parent == nil { + var ret Link + return ret + } + return *o.Parent +} + +// GetParentOk returns a tuple with the Parent field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationCollectionLinks) GetParentOk() (*Link, bool) { + if o == nil || o.Parent == nil { + return nil, false + } + return o.Parent, true +} + +// HasParent returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationCollectionLinks) HasParent() bool { + if o != nil && o.Parent != nil { + return true + } + + return false +} + +// SetParent gets a reference to the given Link and assigns it to the Parent field. +func (o *IntegrationDeliveryConfigurationCollectionLinks) SetParent(v Link) { + o.Parent = &v +} + +func (o IntegrationDeliveryConfigurationCollectionLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if o.Parent != nil { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfigurationCollectionLinks struct { + value *IntegrationDeliveryConfigurationCollectionLinks + isSet bool +} + +func (v NullableIntegrationDeliveryConfigurationCollectionLinks) Get() *IntegrationDeliveryConfigurationCollectionLinks { + return v.value +} + +func (v *NullableIntegrationDeliveryConfigurationCollectionLinks) Set(val *IntegrationDeliveryConfigurationCollectionLinks) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfigurationCollectionLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfigurationCollectionLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfigurationCollectionLinks(val *IntegrationDeliveryConfigurationCollectionLinks) *NullableIntegrationDeliveryConfigurationCollectionLinks { + return &NullableIntegrationDeliveryConfigurationCollectionLinks{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfigurationCollectionLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfigurationCollectionLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_links.go new file mode 100644 index 00000000..b19e056e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_links.go @@ -0,0 +1,196 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfigurationLinks struct for IntegrationDeliveryConfigurationLinks +type IntegrationDeliveryConfigurationLinks struct { + Self Link `json:"self"` + Parent Link `json:"parent"` + Project Link `json:"project"` + Environment Link `json:"environment"` +} + +// NewIntegrationDeliveryConfigurationLinks instantiates a new IntegrationDeliveryConfigurationLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfigurationLinks(self Link, parent Link, project Link, environment Link) *IntegrationDeliveryConfigurationLinks { + this := IntegrationDeliveryConfigurationLinks{} + this.Self = self + this.Parent = parent + this.Project = project + this.Environment = environment + return &this +} + +// NewIntegrationDeliveryConfigurationLinksWithDefaults instantiates a new IntegrationDeliveryConfigurationLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationLinksWithDefaults() *IntegrationDeliveryConfigurationLinks { + this := IntegrationDeliveryConfigurationLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *IntegrationDeliveryConfigurationLinks) GetSelf() Link { + if o == nil { + var ret Link + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationLinks) GetSelfOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *IntegrationDeliveryConfigurationLinks) SetSelf(v Link) { + o.Self = v +} + +// GetParent returns the Parent field value +func (o *IntegrationDeliveryConfigurationLinks) GetParent() Link { + if o == nil { + var ret Link + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationLinks) GetParentOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *IntegrationDeliveryConfigurationLinks) SetParent(v Link) { + o.Parent = v +} + +// GetProject returns the Project field value +func (o *IntegrationDeliveryConfigurationLinks) GetProject() Link { + if o == nil { + var ret Link + return ret + } + + return o.Project +} + +// GetProjectOk returns a tuple with the Project field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationLinks) GetProjectOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Project, true +} + +// SetProject sets field value +func (o *IntegrationDeliveryConfigurationLinks) SetProject(v Link) { + o.Project = v +} + +// GetEnvironment returns the Environment field value +func (o *IntegrationDeliveryConfigurationLinks) GetEnvironment() Link { + if o == nil { + var ret Link + return ret + } + + return o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationLinks) GetEnvironmentOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Environment, true +} + +// SetEnvironment sets field value +func (o *IntegrationDeliveryConfigurationLinks) SetEnvironment(v Link) { + o.Environment = v +} + +func (o IntegrationDeliveryConfigurationLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if true { + toSerialize["parent"] = o.Parent + } + if true { + toSerialize["project"] = o.Project + } + if true { + toSerialize["environment"] = o.Environment + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfigurationLinks struct { + value *IntegrationDeliveryConfigurationLinks + isSet bool +} + +func (v NullableIntegrationDeliveryConfigurationLinks) Get() *IntegrationDeliveryConfigurationLinks { + return v.value +} + +func (v *NullableIntegrationDeliveryConfigurationLinks) Set(val *IntegrationDeliveryConfigurationLinks) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfigurationLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfigurationLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfigurationLinks(val *IntegrationDeliveryConfigurationLinks) *NullableIntegrationDeliveryConfigurationLinks { + return &NullableIntegrationDeliveryConfigurationLinks{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfigurationLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfigurationLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_post.go new file mode 100644 index 00000000..df68ea08 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_post.go @@ -0,0 +1,220 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfigurationPost struct for IntegrationDeliveryConfigurationPost +type IntegrationDeliveryConfigurationPost struct { + // Whether the integration configuration is active. Default value is false. + On *bool `json:"on,omitempty"` + Config map[string]interface{} `json:"config"` + // Tags to associate with the integration + Tags []string `json:"tags,omitempty"` + // Name to identify the integration + Name *string `json:"name,omitempty"` +} + +// NewIntegrationDeliveryConfigurationPost instantiates a new IntegrationDeliveryConfigurationPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfigurationPost(config map[string]interface{}) *IntegrationDeliveryConfigurationPost { + this := IntegrationDeliveryConfigurationPost{} + this.Config = config + return &this +} + +// NewIntegrationDeliveryConfigurationPostWithDefaults instantiates a new IntegrationDeliveryConfigurationPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationPostWithDefaults() *IntegrationDeliveryConfigurationPost { + this := IntegrationDeliveryConfigurationPost{} + return &this +} + +// GetOn returns the On field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationPost) GetOn() bool { + if o == nil || o.On == nil { + var ret bool + return ret + } + return *o.On +} + +// GetOnOk returns a tuple with the On field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationPost) GetOnOk() (*bool, bool) { + if o == nil || o.On == nil { + return nil, false + } + return o.On, true +} + +// HasOn returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationPost) HasOn() bool { + if o != nil && o.On != nil { + return true + } + + return false +} + +// SetOn gets a reference to the given bool and assigns it to the On field. +func (o *IntegrationDeliveryConfigurationPost) SetOn(v bool) { + o.On = &v +} + +// GetConfig returns the Config field value +func (o *IntegrationDeliveryConfigurationPost) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationPost) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *IntegrationDeliveryConfigurationPost) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *IntegrationDeliveryConfigurationPost) SetTags(v []string) { + o.Tags = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *IntegrationDeliveryConfigurationPost) SetName(v string) { + o.Name = &v +} + +func (o IntegrationDeliveryConfigurationPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.On != nil { + toSerialize["on"] = o.On + } + if true { + toSerialize["config"] = o.Config + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfigurationPost struct { + value *IntegrationDeliveryConfigurationPost + isSet bool +} + +func (v NullableIntegrationDeliveryConfigurationPost) Get() *IntegrationDeliveryConfigurationPost { + return v.value +} + +func (v *NullableIntegrationDeliveryConfigurationPost) Set(val *IntegrationDeliveryConfigurationPost) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfigurationPost) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfigurationPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfigurationPost(val *IntegrationDeliveryConfigurationPost) *NullableIntegrationDeliveryConfigurationPost { + return &NullableIntegrationDeliveryConfigurationPost{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfigurationPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfigurationPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_response.go new file mode 100644 index 00000000..366f7477 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_delivery_configuration_response.go @@ -0,0 +1,226 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationDeliveryConfigurationResponse struct for IntegrationDeliveryConfigurationResponse +type IntegrationDeliveryConfigurationResponse struct { + // The status code returned by the validation + StatusCode *int32 `json:"statusCode,omitempty"` + Error *string `json:"error,omitempty"` + Timestamp *int64 `json:"timestamp,omitempty"` + // JSON response to the validation request + ResponseBody *string `json:"responseBody,omitempty"` +} + +// NewIntegrationDeliveryConfigurationResponse instantiates a new IntegrationDeliveryConfigurationResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationDeliveryConfigurationResponse() *IntegrationDeliveryConfigurationResponse { + this := IntegrationDeliveryConfigurationResponse{} + return &this +} + +// NewIntegrationDeliveryConfigurationResponseWithDefaults instantiates a new IntegrationDeliveryConfigurationResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationDeliveryConfigurationResponseWithDefaults() *IntegrationDeliveryConfigurationResponse { + this := IntegrationDeliveryConfigurationResponse{} + return &this +} + +// GetStatusCode returns the StatusCode field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationResponse) GetStatusCode() int32 { + if o == nil || o.StatusCode == nil { + var ret int32 + return ret + } + return *o.StatusCode +} + +// GetStatusCodeOk returns a tuple with the StatusCode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationResponse) GetStatusCodeOk() (*int32, bool) { + if o == nil || o.StatusCode == nil { + return nil, false + } + return o.StatusCode, true +} + +// HasStatusCode returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationResponse) HasStatusCode() bool { + if o != nil && o.StatusCode != nil { + return true + } + + return false +} + +// SetStatusCode gets a reference to the given int32 and assigns it to the StatusCode field. +func (o *IntegrationDeliveryConfigurationResponse) SetStatusCode(v int32) { + o.StatusCode = &v +} + +// GetError returns the Error field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationResponse) GetError() string { + if o == nil || o.Error == nil { + var ret string + return ret + } + return *o.Error +} + +// GetErrorOk returns a tuple with the Error field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationResponse) GetErrorOk() (*string, bool) { + if o == nil || o.Error == nil { + return nil, false + } + return o.Error, true +} + +// HasError returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationResponse) HasError() bool { + if o != nil && o.Error != nil { + return true + } + + return false +} + +// SetError gets a reference to the given string and assigns it to the Error field. +func (o *IntegrationDeliveryConfigurationResponse) SetError(v string) { + o.Error = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationResponse) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationResponse) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationResponse) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *IntegrationDeliveryConfigurationResponse) SetTimestamp(v int64) { + o.Timestamp = &v +} + +// GetResponseBody returns the ResponseBody field value if set, zero value otherwise. +func (o *IntegrationDeliveryConfigurationResponse) GetResponseBody() string { + if o == nil || o.ResponseBody == nil { + var ret string + return ret + } + return *o.ResponseBody +} + +// GetResponseBodyOk returns a tuple with the ResponseBody field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationDeliveryConfigurationResponse) GetResponseBodyOk() (*string, bool) { + if o == nil || o.ResponseBody == nil { + return nil, false + } + return o.ResponseBody, true +} + +// HasResponseBody returns a boolean if a field has been set. +func (o *IntegrationDeliveryConfigurationResponse) HasResponseBody() bool { + if o != nil && o.ResponseBody != nil { + return true + } + + return false +} + +// SetResponseBody gets a reference to the given string and assigns it to the ResponseBody field. +func (o *IntegrationDeliveryConfigurationResponse) SetResponseBody(v string) { + o.ResponseBody = &v +} + +func (o IntegrationDeliveryConfigurationResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.StatusCode != nil { + toSerialize["statusCode"] = o.StatusCode + } + if o.Error != nil { + toSerialize["error"] = o.Error + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + if o.ResponseBody != nil { + toSerialize["responseBody"] = o.ResponseBody + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationDeliveryConfigurationResponse struct { + value *IntegrationDeliveryConfigurationResponse + isSet bool +} + +func (v NullableIntegrationDeliveryConfigurationResponse) Get() *IntegrationDeliveryConfigurationResponse { + return v.value +} + +func (v *NullableIntegrationDeliveryConfigurationResponse) Set(val *IntegrationDeliveryConfigurationResponse) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationDeliveryConfigurationResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationDeliveryConfigurationResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationDeliveryConfigurationResponse(val *IntegrationDeliveryConfigurationResponse) *NullableIntegrationDeliveryConfigurationResponse { + return &NullableIntegrationDeliveryConfigurationResponse{value: val, isSet: true} +} + +func (v NullableIntegrationDeliveryConfigurationResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationDeliveryConfigurationResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_metadata.go new file mode 100644 index 00000000..f9347ea8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_metadata.go @@ -0,0 +1,196 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationMetadata struct for IntegrationMetadata +type IntegrationMetadata struct { + ExternalId string `json:"externalId"` + ExternalStatus IntegrationStatus `json:"externalStatus"` + ExternalUrl string `json:"externalUrl"` + LastChecked int64 `json:"lastChecked"` +} + +// NewIntegrationMetadata instantiates a new IntegrationMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationMetadata(externalId string, externalStatus IntegrationStatus, externalUrl string, lastChecked int64) *IntegrationMetadata { + this := IntegrationMetadata{} + this.ExternalId = externalId + this.ExternalStatus = externalStatus + this.ExternalUrl = externalUrl + this.LastChecked = lastChecked + return &this +} + +// NewIntegrationMetadataWithDefaults instantiates a new IntegrationMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationMetadataWithDefaults() *IntegrationMetadata { + this := IntegrationMetadata{} + return &this +} + +// GetExternalId returns the ExternalId field value +func (o *IntegrationMetadata) GetExternalId() string { + if o == nil { + var ret string + return ret + } + + return o.ExternalId +} + +// GetExternalIdOk returns a tuple with the ExternalId field value +// and a boolean to check if the value has been set. +func (o *IntegrationMetadata) GetExternalIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ExternalId, true +} + +// SetExternalId sets field value +func (o *IntegrationMetadata) SetExternalId(v string) { + o.ExternalId = v +} + +// GetExternalStatus returns the ExternalStatus field value +func (o *IntegrationMetadata) GetExternalStatus() IntegrationStatus { + if o == nil { + var ret IntegrationStatus + return ret + } + + return o.ExternalStatus +} + +// GetExternalStatusOk returns a tuple with the ExternalStatus field value +// and a boolean to check if the value has been set. +func (o *IntegrationMetadata) GetExternalStatusOk() (*IntegrationStatus, bool) { + if o == nil { + return nil, false + } + return &o.ExternalStatus, true +} + +// SetExternalStatus sets field value +func (o *IntegrationMetadata) SetExternalStatus(v IntegrationStatus) { + o.ExternalStatus = v +} + +// GetExternalUrl returns the ExternalUrl field value +func (o *IntegrationMetadata) GetExternalUrl() string { + if o == nil { + var ret string + return ret + } + + return o.ExternalUrl +} + +// GetExternalUrlOk returns a tuple with the ExternalUrl field value +// and a boolean to check if the value has been set. +func (o *IntegrationMetadata) GetExternalUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ExternalUrl, true +} + +// SetExternalUrl sets field value +func (o *IntegrationMetadata) SetExternalUrl(v string) { + o.ExternalUrl = v +} + +// GetLastChecked returns the LastChecked field value +func (o *IntegrationMetadata) GetLastChecked() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastChecked +} + +// GetLastCheckedOk returns a tuple with the LastChecked field value +// and a boolean to check if the value has been set. +func (o *IntegrationMetadata) GetLastCheckedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastChecked, true +} + +// SetLastChecked sets field value +func (o *IntegrationMetadata) SetLastChecked(v int64) { + o.LastChecked = v +} + +func (o IntegrationMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["externalId"] = o.ExternalId + } + if true { + toSerialize["externalStatus"] = o.ExternalStatus + } + if true { + toSerialize["externalUrl"] = o.ExternalUrl + } + if true { + toSerialize["lastChecked"] = o.LastChecked + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationMetadata struct { + value *IntegrationMetadata + isSet bool +} + +func (v NullableIntegrationMetadata) Get() *IntegrationMetadata { + return v.value +} + +func (v *NullableIntegrationMetadata) Set(val *IntegrationMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationMetadata(val *IntegrationMetadata) *NullableIntegrationMetadata { + return &NullableIntegrationMetadata{value: val, isSet: true} +} + +func (v NullableIntegrationMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status.go new file mode 100644 index 00000000..289128ba --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationStatus struct for IntegrationStatus +type IntegrationStatus struct { + Display string `json:"display"` + Value string `json:"value"` +} + +// NewIntegrationStatus instantiates a new IntegrationStatus object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationStatus(display string, value string) *IntegrationStatus { + this := IntegrationStatus{} + this.Display = display + this.Value = value + return &this +} + +// NewIntegrationStatusWithDefaults instantiates a new IntegrationStatus object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationStatusWithDefaults() *IntegrationStatus { + this := IntegrationStatus{} + return &this +} + +// GetDisplay returns the Display field value +func (o *IntegrationStatus) GetDisplay() string { + if o == nil { + var ret string + return ret + } + + return o.Display +} + +// GetDisplayOk returns a tuple with the Display field value +// and a boolean to check if the value has been set. +func (o *IntegrationStatus) GetDisplayOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Display, true +} + +// SetDisplay sets field value +func (o *IntegrationStatus) SetDisplay(v string) { + o.Display = v +} + +// GetValue returns the Value field value +func (o *IntegrationStatus) GetValue() string { + if o == nil { + var ret string + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *IntegrationStatus) GetValueOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *IntegrationStatus) SetValue(v string) { + o.Value = v +} + +func (o IntegrationStatus) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["display"] = o.Display + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationStatus struct { + value *IntegrationStatus + isSet bool +} + +func (v NullableIntegrationStatus) Get() *IntegrationStatus { + return v.value +} + +func (v *NullableIntegrationStatus) Set(val *IntegrationStatus) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationStatus) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationStatus) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationStatus(val *IntegrationStatus) *NullableIntegrationStatus { + return &NullableIntegrationStatus{value: val, isSet: true} +} + +func (v NullableIntegrationStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationStatus) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status_rep.go new file mode 100644 index 00000000..c07e3fb5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_status_rep.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationStatusRep struct for IntegrationStatusRep +type IntegrationStatusRep struct { + StatusCode *int32 `json:"statusCode,omitempty"` + ResponseBody *string `json:"responseBody,omitempty"` + Timestamp *int64 `json:"timestamp,omitempty"` +} + +// NewIntegrationStatusRep instantiates a new IntegrationStatusRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationStatusRep() *IntegrationStatusRep { + this := IntegrationStatusRep{} + return &this +} + +// NewIntegrationStatusRepWithDefaults instantiates a new IntegrationStatusRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationStatusRepWithDefaults() *IntegrationStatusRep { + this := IntegrationStatusRep{} + return &this +} + +// GetStatusCode returns the StatusCode field value if set, zero value otherwise. +func (o *IntegrationStatusRep) GetStatusCode() int32 { + if o == nil || o.StatusCode == nil { + var ret int32 + return ret + } + return *o.StatusCode +} + +// GetStatusCodeOk returns a tuple with the StatusCode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationStatusRep) GetStatusCodeOk() (*int32, bool) { + if o == nil || o.StatusCode == nil { + return nil, false + } + return o.StatusCode, true +} + +// HasStatusCode returns a boolean if a field has been set. +func (o *IntegrationStatusRep) HasStatusCode() bool { + if o != nil && o.StatusCode != nil { + return true + } + + return false +} + +// SetStatusCode gets a reference to the given int32 and assigns it to the StatusCode field. +func (o *IntegrationStatusRep) SetStatusCode(v int32) { + o.StatusCode = &v +} + +// GetResponseBody returns the ResponseBody field value if set, zero value otherwise. +func (o *IntegrationStatusRep) GetResponseBody() string { + if o == nil || o.ResponseBody == nil { + var ret string + return ret + } + return *o.ResponseBody +} + +// GetResponseBodyOk returns a tuple with the ResponseBody field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationStatusRep) GetResponseBodyOk() (*string, bool) { + if o == nil || o.ResponseBody == nil { + return nil, false + } + return o.ResponseBody, true +} + +// HasResponseBody returns a boolean if a field has been set. +func (o *IntegrationStatusRep) HasResponseBody() bool { + if o != nil && o.ResponseBody != nil { + return true + } + + return false +} + +// SetResponseBody gets a reference to the given string and assigns it to the ResponseBody field. +func (o *IntegrationStatusRep) SetResponseBody(v string) { + o.ResponseBody = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *IntegrationStatusRep) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationStatusRep) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *IntegrationStatusRep) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *IntegrationStatusRep) SetTimestamp(v int64) { + o.Timestamp = &v +} + +func (o IntegrationStatusRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.StatusCode != nil { + toSerialize["statusCode"] = o.StatusCode + } + if o.ResponseBody != nil { + toSerialize["responseBody"] = o.ResponseBody + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationStatusRep struct { + value *IntegrationStatusRep + isSet bool +} + +func (v NullableIntegrationStatusRep) Get() *IntegrationStatusRep { + return v.value +} + +func (v *NullableIntegrationStatusRep) Set(val *IntegrationStatusRep) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationStatusRep) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationStatusRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationStatusRep(val *IntegrationStatusRep) *NullableIntegrationStatusRep { + return &NullableIntegrationStatusRep{value: val, isSet: true} +} + +func (v NullableIntegrationStatusRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationStatusRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_subscription_status_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_subscription_status_rep.go new file mode 100644 index 00000000..aa90fdf5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integration_subscription_status_rep.go @@ -0,0 +1,260 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IntegrationSubscriptionStatusRep struct for IntegrationSubscriptionStatusRep +type IntegrationSubscriptionStatusRep struct { + SuccessCount *int32 `json:"successCount,omitempty"` + LastSuccess *int64 `json:"lastSuccess,omitempty"` + LastError *int64 `json:"lastError,omitempty"` + ErrorCount *int32 `json:"errorCount,omitempty"` + Errors []IntegrationStatusRep `json:"errors,omitempty"` +} + +// NewIntegrationSubscriptionStatusRep instantiates a new IntegrationSubscriptionStatusRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrationSubscriptionStatusRep() *IntegrationSubscriptionStatusRep { + this := IntegrationSubscriptionStatusRep{} + return &this +} + +// NewIntegrationSubscriptionStatusRepWithDefaults instantiates a new IntegrationSubscriptionStatusRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationSubscriptionStatusRepWithDefaults() *IntegrationSubscriptionStatusRep { + this := IntegrationSubscriptionStatusRep{} + return &this +} + +// GetSuccessCount returns the SuccessCount field value if set, zero value otherwise. +func (o *IntegrationSubscriptionStatusRep) GetSuccessCount() int32 { + if o == nil || o.SuccessCount == nil { + var ret int32 + return ret + } + return *o.SuccessCount +} + +// GetSuccessCountOk returns a tuple with the SuccessCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationSubscriptionStatusRep) GetSuccessCountOk() (*int32, bool) { + if o == nil || o.SuccessCount == nil { + return nil, false + } + return o.SuccessCount, true +} + +// HasSuccessCount returns a boolean if a field has been set. +func (o *IntegrationSubscriptionStatusRep) HasSuccessCount() bool { + if o != nil && o.SuccessCount != nil { + return true + } + + return false +} + +// SetSuccessCount gets a reference to the given int32 and assigns it to the SuccessCount field. +func (o *IntegrationSubscriptionStatusRep) SetSuccessCount(v int32) { + o.SuccessCount = &v +} + +// GetLastSuccess returns the LastSuccess field value if set, zero value otherwise. +func (o *IntegrationSubscriptionStatusRep) GetLastSuccess() int64 { + if o == nil || o.LastSuccess == nil { + var ret int64 + return ret + } + return *o.LastSuccess +} + +// GetLastSuccessOk returns a tuple with the LastSuccess field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationSubscriptionStatusRep) GetLastSuccessOk() (*int64, bool) { + if o == nil || o.LastSuccess == nil { + return nil, false + } + return o.LastSuccess, true +} + +// HasLastSuccess returns a boolean if a field has been set. +func (o *IntegrationSubscriptionStatusRep) HasLastSuccess() bool { + if o != nil && o.LastSuccess != nil { + return true + } + + return false +} + +// SetLastSuccess gets a reference to the given int64 and assigns it to the LastSuccess field. +func (o *IntegrationSubscriptionStatusRep) SetLastSuccess(v int64) { + o.LastSuccess = &v +} + +// GetLastError returns the LastError field value if set, zero value otherwise. +func (o *IntegrationSubscriptionStatusRep) GetLastError() int64 { + if o == nil || o.LastError == nil { + var ret int64 + return ret + } + return *o.LastError +} + +// GetLastErrorOk returns a tuple with the LastError field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationSubscriptionStatusRep) GetLastErrorOk() (*int64, bool) { + if o == nil || o.LastError == nil { + return nil, false + } + return o.LastError, true +} + +// HasLastError returns a boolean if a field has been set. +func (o *IntegrationSubscriptionStatusRep) HasLastError() bool { + if o != nil && o.LastError != nil { + return true + } + + return false +} + +// SetLastError gets a reference to the given int64 and assigns it to the LastError field. +func (o *IntegrationSubscriptionStatusRep) SetLastError(v int64) { + o.LastError = &v +} + +// GetErrorCount returns the ErrorCount field value if set, zero value otherwise. +func (o *IntegrationSubscriptionStatusRep) GetErrorCount() int32 { + if o == nil || o.ErrorCount == nil { + var ret int32 + return ret + } + return *o.ErrorCount +} + +// GetErrorCountOk returns a tuple with the ErrorCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationSubscriptionStatusRep) GetErrorCountOk() (*int32, bool) { + if o == nil || o.ErrorCount == nil { + return nil, false + } + return o.ErrorCount, true +} + +// HasErrorCount returns a boolean if a field has been set. +func (o *IntegrationSubscriptionStatusRep) HasErrorCount() bool { + if o != nil && o.ErrorCount != nil { + return true + } + + return false +} + +// SetErrorCount gets a reference to the given int32 and assigns it to the ErrorCount field. +func (o *IntegrationSubscriptionStatusRep) SetErrorCount(v int32) { + o.ErrorCount = &v +} + +// GetErrors returns the Errors field value if set, zero value otherwise. +func (o *IntegrationSubscriptionStatusRep) GetErrors() []IntegrationStatusRep { + if o == nil || o.Errors == nil { + var ret []IntegrationStatusRep + return ret + } + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IntegrationSubscriptionStatusRep) GetErrorsOk() ([]IntegrationStatusRep, bool) { + if o == nil || o.Errors == nil { + return nil, false + } + return o.Errors, true +} + +// HasErrors returns a boolean if a field has been set. +func (o *IntegrationSubscriptionStatusRep) HasErrors() bool { + if o != nil && o.Errors != nil { + return true + } + + return false +} + +// SetErrors gets a reference to the given []IntegrationStatusRep and assigns it to the Errors field. +func (o *IntegrationSubscriptionStatusRep) SetErrors(v []IntegrationStatusRep) { + o.Errors = v +} + +func (o IntegrationSubscriptionStatusRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.SuccessCount != nil { + toSerialize["successCount"] = o.SuccessCount + } + if o.LastSuccess != nil { + toSerialize["lastSuccess"] = o.LastSuccess + } + if o.LastError != nil { + toSerialize["lastError"] = o.LastError + } + if o.ErrorCount != nil { + toSerialize["errorCount"] = o.ErrorCount + } + if o.Errors != nil { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableIntegrationSubscriptionStatusRep struct { + value *IntegrationSubscriptionStatusRep + isSet bool +} + +func (v NullableIntegrationSubscriptionStatusRep) Get() *IntegrationSubscriptionStatusRep { + return v.value +} + +func (v *NullableIntegrationSubscriptionStatusRep) Set(val *IntegrationSubscriptionStatusRep) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrationSubscriptionStatusRep) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrationSubscriptionStatusRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrationSubscriptionStatusRep(val *IntegrationSubscriptionStatusRep) *NullableIntegrationSubscriptionStatusRep { + return &NullableIntegrationSubscriptionStatusRep{value: val, isSet: true} +} + +func (v NullableIntegrationSubscriptionStatusRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrationSubscriptionStatusRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_integrations.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_integrations.go new file mode 100644 index 00000000..a2b189a7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_integrations.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Integrations struct for Integrations +type Integrations struct { + Links *map[string]Link `json:"_links,omitempty"` + Items []Integration `json:"items,omitempty"` + Key *string `json:"key,omitempty"` +} + +// NewIntegrations instantiates a new Integrations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIntegrations() *Integrations { + this := Integrations{} + return &this +} + +// NewIntegrationsWithDefaults instantiates a new Integrations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIntegrationsWithDefaults() *Integrations { + this := Integrations{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Integrations) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integrations) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Integrations) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Integrations) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *Integrations) GetItems() []Integration { + if o == nil || o.Items == nil { + var ret []Integration + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integrations) GetItemsOk() ([]Integration, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *Integrations) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []Integration and assigns it to the Items field. +func (o *Integrations) SetItems(v []Integration) { + o.Items = v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *Integrations) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Integrations) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *Integrations) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *Integrations) SetKey(v string) { + o.Key = &v +} + +func (o Integrations) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + return json.Marshal(toSerialize) +} + +type NullableIntegrations struct { + value *Integrations + isSet bool +} + +func (v NullableIntegrations) Get() *Integrations { + return v.value +} + +func (v *NullableIntegrations) Set(val *Integrations) { + v.value = val + v.isSet = true +} + +func (v NullableIntegrations) IsSet() bool { + return v.isSet +} + +func (v *NullableIntegrations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIntegrations(val *Integrations) *NullableIntegrations { + return &NullableIntegrations{value: val, isSet: true} +} + +func (v NullableIntegrations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIntegrations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_invalid_request_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_invalid_request_error_rep.go new file mode 100644 index 00000000..98b907a0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_invalid_request_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// InvalidRequestErrorRep struct for InvalidRequestErrorRep +type InvalidRequestErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewInvalidRequestErrorRep instantiates a new InvalidRequestErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInvalidRequestErrorRep(code string, message string) *InvalidRequestErrorRep { + this := InvalidRequestErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewInvalidRequestErrorRepWithDefaults instantiates a new InvalidRequestErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInvalidRequestErrorRepWithDefaults() *InvalidRequestErrorRep { + this := InvalidRequestErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *InvalidRequestErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *InvalidRequestErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *InvalidRequestErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *InvalidRequestErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *InvalidRequestErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *InvalidRequestErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o InvalidRequestErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableInvalidRequestErrorRep struct { + value *InvalidRequestErrorRep + isSet bool +} + +func (v NullableInvalidRequestErrorRep) Get() *InvalidRequestErrorRep { + return v.value +} + +func (v *NullableInvalidRequestErrorRep) Set(val *InvalidRequestErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableInvalidRequestErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableInvalidRequestErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInvalidRequestErrorRep(val *InvalidRequestErrorRep) *NullableInvalidRequestErrorRep { + return &NullableInvalidRequestErrorRep{value: val, isSet: true} +} + +func (v NullableInvalidRequestErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInvalidRequestErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_ip_list.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_ip_list.go new file mode 100644 index 00000000..04875a0b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_ip_list.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IpList struct for IpList +type IpList struct { + // A list of the IP addresses LaunchDarkly's service uses + Addresses []string `json:"addresses"` + // A list of the IP addresses outgoing webhook notifications use + OutboundAddresses []string `json:"outboundAddresses"` +} + +// NewIpList instantiates a new IpList object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIpList(addresses []string, outboundAddresses []string) *IpList { + this := IpList{} + this.Addresses = addresses + this.OutboundAddresses = outboundAddresses + return &this +} + +// NewIpListWithDefaults instantiates a new IpList object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIpListWithDefaults() *IpList { + this := IpList{} + return &this +} + +// GetAddresses returns the Addresses field value +func (o *IpList) GetAddresses() []string { + if o == nil { + var ret []string + return ret + } + + return o.Addresses +} + +// GetAddressesOk returns a tuple with the Addresses field value +// and a boolean to check if the value has been set. +func (o *IpList) GetAddressesOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Addresses, true +} + +// SetAddresses sets field value +func (o *IpList) SetAddresses(v []string) { + o.Addresses = v +} + +// GetOutboundAddresses returns the OutboundAddresses field value +func (o *IpList) GetOutboundAddresses() []string { + if o == nil { + var ret []string + return ret + } + + return o.OutboundAddresses +} + +// GetOutboundAddressesOk returns a tuple with the OutboundAddresses field value +// and a boolean to check if the value has been set. +func (o *IpList) GetOutboundAddressesOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.OutboundAddresses, true +} + +// SetOutboundAddresses sets field value +func (o *IpList) SetOutboundAddresses(v []string) { + o.OutboundAddresses = v +} + +func (o IpList) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["addresses"] = o.Addresses + } + if true { + toSerialize["outboundAddresses"] = o.OutboundAddresses + } + return json.Marshal(toSerialize) +} + +type NullableIpList struct { + value *IpList + isSet bool +} + +func (v NullableIpList) Get() *IpList { + return v.value +} + +func (v *NullableIpList) Set(val *IpList) { + v.value = val + v.isSet = true +} + +func (v NullableIpList) IsSet() bool { + return v.isSet +} + +func (v *NullableIpList) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIpList(val *IpList) *NullableIpList { + return &NullableIpList{value: val, isSet: true} +} + +func (v NullableIpList) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIpList) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_input.go new file mode 100644 index 00000000..26d7977e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_input.go @@ -0,0 +1,382 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IterationInput struct for IterationInput +type IterationInput struct { + // The expected outcome of this experiment + Hypothesis string `json:"hypothesis"` + // Whether to allow the experiment to reassign traffic to different variations when you increase or decrease the traffic in your experiment audience (true) or keep all traffic assigned to its initial variation (false). Defaults to true. + CanReshuffleTraffic *bool `json:"canReshuffleTraffic,omitempty"` + Metrics []MetricInput `json:"metrics"` + // The key of the primary metric for this experiment. Either primarySingleMetricKey or primaryFunnelKey must be present. + PrimarySingleMetricKey *string `json:"primarySingleMetricKey,omitempty"` + // The key of the primary funnel group for this experiment. Either primarySingleMetricKey or primaryFunnelKey must be present. + PrimaryFunnelKey *string `json:"primaryFunnelKey,omitempty"` + Treatments []TreatmentInput `json:"treatments"` + Flags map[string]FlagInput `json:"flags"` + // The unit of randomization for this iteration. Defaults to user. + RandomizationUnit *string `json:"randomizationUnit,omitempty"` + // The attributes that this iteration's results can be sliced by + Attributes []string `json:"attributes,omitempty"` +} + +// NewIterationInput instantiates a new IterationInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIterationInput(hypothesis string, metrics []MetricInput, treatments []TreatmentInput, flags map[string]FlagInput) *IterationInput { + this := IterationInput{} + this.Hypothesis = hypothesis + this.Metrics = metrics + this.Treatments = treatments + this.Flags = flags + return &this +} + +// NewIterationInputWithDefaults instantiates a new IterationInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIterationInputWithDefaults() *IterationInput { + this := IterationInput{} + return &this +} + +// GetHypothesis returns the Hypothesis field value +func (o *IterationInput) GetHypothesis() string { + if o == nil { + var ret string + return ret + } + + return o.Hypothesis +} + +// GetHypothesisOk returns a tuple with the Hypothesis field value +// and a boolean to check if the value has been set. +func (o *IterationInput) GetHypothesisOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Hypothesis, true +} + +// SetHypothesis sets field value +func (o *IterationInput) SetHypothesis(v string) { + o.Hypothesis = v +} + +// GetCanReshuffleTraffic returns the CanReshuffleTraffic field value if set, zero value otherwise. +func (o *IterationInput) GetCanReshuffleTraffic() bool { + if o == nil || o.CanReshuffleTraffic == nil { + var ret bool + return ret + } + return *o.CanReshuffleTraffic +} + +// GetCanReshuffleTrafficOk returns a tuple with the CanReshuffleTraffic field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationInput) GetCanReshuffleTrafficOk() (*bool, bool) { + if o == nil || o.CanReshuffleTraffic == nil { + return nil, false + } + return o.CanReshuffleTraffic, true +} + +// HasCanReshuffleTraffic returns a boolean if a field has been set. +func (o *IterationInput) HasCanReshuffleTraffic() bool { + if o != nil && o.CanReshuffleTraffic != nil { + return true + } + + return false +} + +// SetCanReshuffleTraffic gets a reference to the given bool and assigns it to the CanReshuffleTraffic field. +func (o *IterationInput) SetCanReshuffleTraffic(v bool) { + o.CanReshuffleTraffic = &v +} + +// GetMetrics returns the Metrics field value +func (o *IterationInput) GetMetrics() []MetricInput { + if o == nil { + var ret []MetricInput + return ret + } + + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value +// and a boolean to check if the value has been set. +func (o *IterationInput) GetMetricsOk() ([]MetricInput, bool) { + if o == nil { + return nil, false + } + return o.Metrics, true +} + +// SetMetrics sets field value +func (o *IterationInput) SetMetrics(v []MetricInput) { + o.Metrics = v +} + +// GetPrimarySingleMetricKey returns the PrimarySingleMetricKey field value if set, zero value otherwise. +func (o *IterationInput) GetPrimarySingleMetricKey() string { + if o == nil || o.PrimarySingleMetricKey == nil { + var ret string + return ret + } + return *o.PrimarySingleMetricKey +} + +// GetPrimarySingleMetricKeyOk returns a tuple with the PrimarySingleMetricKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationInput) GetPrimarySingleMetricKeyOk() (*string, bool) { + if o == nil || o.PrimarySingleMetricKey == nil { + return nil, false + } + return o.PrimarySingleMetricKey, true +} + +// HasPrimarySingleMetricKey returns a boolean if a field has been set. +func (o *IterationInput) HasPrimarySingleMetricKey() bool { + if o != nil && o.PrimarySingleMetricKey != nil { + return true + } + + return false +} + +// SetPrimarySingleMetricKey gets a reference to the given string and assigns it to the PrimarySingleMetricKey field. +func (o *IterationInput) SetPrimarySingleMetricKey(v string) { + o.PrimarySingleMetricKey = &v +} + +// GetPrimaryFunnelKey returns the PrimaryFunnelKey field value if set, zero value otherwise. +func (o *IterationInput) GetPrimaryFunnelKey() string { + if o == nil || o.PrimaryFunnelKey == nil { + var ret string + return ret + } + return *o.PrimaryFunnelKey +} + +// GetPrimaryFunnelKeyOk returns a tuple with the PrimaryFunnelKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationInput) GetPrimaryFunnelKeyOk() (*string, bool) { + if o == nil || o.PrimaryFunnelKey == nil { + return nil, false + } + return o.PrimaryFunnelKey, true +} + +// HasPrimaryFunnelKey returns a boolean if a field has been set. +func (o *IterationInput) HasPrimaryFunnelKey() bool { + if o != nil && o.PrimaryFunnelKey != nil { + return true + } + + return false +} + +// SetPrimaryFunnelKey gets a reference to the given string and assigns it to the PrimaryFunnelKey field. +func (o *IterationInput) SetPrimaryFunnelKey(v string) { + o.PrimaryFunnelKey = &v +} + +// GetTreatments returns the Treatments field value +func (o *IterationInput) GetTreatments() []TreatmentInput { + if o == nil { + var ret []TreatmentInput + return ret + } + + return o.Treatments +} + +// GetTreatmentsOk returns a tuple with the Treatments field value +// and a boolean to check if the value has been set. +func (o *IterationInput) GetTreatmentsOk() ([]TreatmentInput, bool) { + if o == nil { + return nil, false + } + return o.Treatments, true +} + +// SetTreatments sets field value +func (o *IterationInput) SetTreatments(v []TreatmentInput) { + o.Treatments = v +} + +// GetFlags returns the Flags field value +func (o *IterationInput) GetFlags() map[string]FlagInput { + if o == nil { + var ret map[string]FlagInput + return ret + } + + return o.Flags +} + +// GetFlagsOk returns a tuple with the Flags field value +// and a boolean to check if the value has been set. +func (o *IterationInput) GetFlagsOk() (*map[string]FlagInput, bool) { + if o == nil { + return nil, false + } + return &o.Flags, true +} + +// SetFlags sets field value +func (o *IterationInput) SetFlags(v map[string]FlagInput) { + o.Flags = v +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *IterationInput) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationInput) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *IterationInput) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *IterationInput) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +// GetAttributes returns the Attributes field value if set, zero value otherwise. +func (o *IterationInput) GetAttributes() []string { + if o == nil || o.Attributes == nil { + var ret []string + return ret + } + return o.Attributes +} + +// GetAttributesOk returns a tuple with the Attributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationInput) GetAttributesOk() ([]string, bool) { + if o == nil || o.Attributes == nil { + return nil, false + } + return o.Attributes, true +} + +// HasAttributes returns a boolean if a field has been set. +func (o *IterationInput) HasAttributes() bool { + if o != nil && o.Attributes != nil { + return true + } + + return false +} + +// SetAttributes gets a reference to the given []string and assigns it to the Attributes field. +func (o *IterationInput) SetAttributes(v []string) { + o.Attributes = v +} + +func (o IterationInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["hypothesis"] = o.Hypothesis + } + if o.CanReshuffleTraffic != nil { + toSerialize["canReshuffleTraffic"] = o.CanReshuffleTraffic + } + if true { + toSerialize["metrics"] = o.Metrics + } + if o.PrimarySingleMetricKey != nil { + toSerialize["primarySingleMetricKey"] = o.PrimarySingleMetricKey + } + if o.PrimaryFunnelKey != nil { + toSerialize["primaryFunnelKey"] = o.PrimaryFunnelKey + } + if true { + toSerialize["treatments"] = o.Treatments + } + if true { + toSerialize["flags"] = o.Flags + } + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + if o.Attributes != nil { + toSerialize["attributes"] = o.Attributes + } + return json.Marshal(toSerialize) +} + +type NullableIterationInput struct { + value *IterationInput + isSet bool +} + +func (v NullableIterationInput) Get() *IterationInput { + return v.value +} + +func (v *NullableIterationInput) Set(val *IterationInput) { + v.value = val + v.isSet = true +} + +func (v NullableIterationInput) IsSet() bool { + return v.isSet +} + +func (v *NullableIterationInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIterationInput(val *IterationInput) *NullableIterationInput { + return &NullableIterationInput{value: val, isSet: true} +} + +func (v NullableIterationInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIterationInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_rep.go new file mode 100644 index 00000000..4b28f7ca --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_iteration_rep.go @@ -0,0 +1,759 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// IterationRep struct for IterationRep +type IterationRep struct { + // The iteration ID + Id *string `json:"_id,omitempty"` + // The expected outcome of this experiment + Hypothesis string `json:"hypothesis"` + // The status of the iteration: not_started, running, stopped + Status string `json:"status"` + CreatedAt int64 `json:"createdAt"` + StartedAt *int64 `json:"startedAt,omitempty"` + EndedAt *int64 `json:"endedAt,omitempty"` + // The ID of the treatment chosen when the experiment stopped + WinningTreatmentId *string `json:"winningTreatmentId,omitempty"` + // The reason you stopped the experiment + WinningReason *string `json:"winningReason,omitempty"` + // Whether the experiment may reassign traffic to different variations when the experiment audience changes (true) or must keep all traffic assigned to its initial variation (false). + CanReshuffleTraffic *bool `json:"canReshuffleTraffic,omitempty"` + // Details on the flag used in this experiment + Flags *map[string]FlagRep `json:"flags,omitempty"` + PrimaryMetric *DependentMetricOrMetricGroupRep `json:"primaryMetric,omitempty"` + PrimarySingleMetric *MetricV2Rep `json:"primarySingleMetric,omitempty"` + PrimaryFunnel *DependentMetricGroupRepWithMetrics `json:"primaryFunnel,omitempty"` + // The unit of randomization for this iteration + RandomizationUnit *string `json:"randomizationUnit,omitempty"` + // The available attribute filters for this iteration + Attributes []string `json:"attributes,omitempty"` + // Details on the variations you are testing in the experiment + Treatments []TreatmentRep `json:"treatments,omitempty"` + // Deprecated, use metrics instead. Details on the secondary metrics for this experiment. + // Deprecated + SecondaryMetrics []MetricV2Rep `json:"secondaryMetrics,omitempty"` + // Details on the metrics for this experiment + Metrics []DependentMetricOrMetricGroupRep `json:"metrics,omitempty"` + LayerSnapshot *LayerSnapshotRep `json:"layerSnapshot,omitempty"` +} + +// NewIterationRep instantiates a new IterationRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewIterationRep(hypothesis string, status string, createdAt int64) *IterationRep { + this := IterationRep{} + this.Hypothesis = hypothesis + this.Status = status + this.CreatedAt = createdAt + return &this +} + +// NewIterationRepWithDefaults instantiates a new IterationRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewIterationRepWithDefaults() *IterationRep { + this := IterationRep{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *IterationRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *IterationRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *IterationRep) SetId(v string) { + o.Id = &v +} + +// GetHypothesis returns the Hypothesis field value +func (o *IterationRep) GetHypothesis() string { + if o == nil { + var ret string + return ret + } + + return o.Hypothesis +} + +// GetHypothesisOk returns a tuple with the Hypothesis field value +// and a boolean to check if the value has been set. +func (o *IterationRep) GetHypothesisOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Hypothesis, true +} + +// SetHypothesis sets field value +func (o *IterationRep) SetHypothesis(v string) { + o.Hypothesis = v +} + +// GetStatus returns the Status field value +func (o *IterationRep) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *IterationRep) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *IterationRep) SetStatus(v string) { + o.Status = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *IterationRep) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *IterationRep) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *IterationRep) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetStartedAt returns the StartedAt field value if set, zero value otherwise. +func (o *IterationRep) GetStartedAt() int64 { + if o == nil || o.StartedAt == nil { + var ret int64 + return ret + } + return *o.StartedAt +} + +// GetStartedAtOk returns a tuple with the StartedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetStartedAtOk() (*int64, bool) { + if o == nil || o.StartedAt == nil { + return nil, false + } + return o.StartedAt, true +} + +// HasStartedAt returns a boolean if a field has been set. +func (o *IterationRep) HasStartedAt() bool { + if o != nil && o.StartedAt != nil { + return true + } + + return false +} + +// SetStartedAt gets a reference to the given int64 and assigns it to the StartedAt field. +func (o *IterationRep) SetStartedAt(v int64) { + o.StartedAt = &v +} + +// GetEndedAt returns the EndedAt field value if set, zero value otherwise. +func (o *IterationRep) GetEndedAt() int64 { + if o == nil || o.EndedAt == nil { + var ret int64 + return ret + } + return *o.EndedAt +} + +// GetEndedAtOk returns a tuple with the EndedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetEndedAtOk() (*int64, bool) { + if o == nil || o.EndedAt == nil { + return nil, false + } + return o.EndedAt, true +} + +// HasEndedAt returns a boolean if a field has been set. +func (o *IterationRep) HasEndedAt() bool { + if o != nil && o.EndedAt != nil { + return true + } + + return false +} + +// SetEndedAt gets a reference to the given int64 and assigns it to the EndedAt field. +func (o *IterationRep) SetEndedAt(v int64) { + o.EndedAt = &v +} + +// GetWinningTreatmentId returns the WinningTreatmentId field value if set, zero value otherwise. +func (o *IterationRep) GetWinningTreatmentId() string { + if o == nil || o.WinningTreatmentId == nil { + var ret string + return ret + } + return *o.WinningTreatmentId +} + +// GetWinningTreatmentIdOk returns a tuple with the WinningTreatmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetWinningTreatmentIdOk() (*string, bool) { + if o == nil || o.WinningTreatmentId == nil { + return nil, false + } + return o.WinningTreatmentId, true +} + +// HasWinningTreatmentId returns a boolean if a field has been set. +func (o *IterationRep) HasWinningTreatmentId() bool { + if o != nil && o.WinningTreatmentId != nil { + return true + } + + return false +} + +// SetWinningTreatmentId gets a reference to the given string and assigns it to the WinningTreatmentId field. +func (o *IterationRep) SetWinningTreatmentId(v string) { + o.WinningTreatmentId = &v +} + +// GetWinningReason returns the WinningReason field value if set, zero value otherwise. +func (o *IterationRep) GetWinningReason() string { + if o == nil || o.WinningReason == nil { + var ret string + return ret + } + return *o.WinningReason +} + +// GetWinningReasonOk returns a tuple with the WinningReason field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetWinningReasonOk() (*string, bool) { + if o == nil || o.WinningReason == nil { + return nil, false + } + return o.WinningReason, true +} + +// HasWinningReason returns a boolean if a field has been set. +func (o *IterationRep) HasWinningReason() bool { + if o != nil && o.WinningReason != nil { + return true + } + + return false +} + +// SetWinningReason gets a reference to the given string and assigns it to the WinningReason field. +func (o *IterationRep) SetWinningReason(v string) { + o.WinningReason = &v +} + +// GetCanReshuffleTraffic returns the CanReshuffleTraffic field value if set, zero value otherwise. +func (o *IterationRep) GetCanReshuffleTraffic() bool { + if o == nil || o.CanReshuffleTraffic == nil { + var ret bool + return ret + } + return *o.CanReshuffleTraffic +} + +// GetCanReshuffleTrafficOk returns a tuple with the CanReshuffleTraffic field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetCanReshuffleTrafficOk() (*bool, bool) { + if o == nil || o.CanReshuffleTraffic == nil { + return nil, false + } + return o.CanReshuffleTraffic, true +} + +// HasCanReshuffleTraffic returns a boolean if a field has been set. +func (o *IterationRep) HasCanReshuffleTraffic() bool { + if o != nil && o.CanReshuffleTraffic != nil { + return true + } + + return false +} + +// SetCanReshuffleTraffic gets a reference to the given bool and assigns it to the CanReshuffleTraffic field. +func (o *IterationRep) SetCanReshuffleTraffic(v bool) { + o.CanReshuffleTraffic = &v +} + +// GetFlags returns the Flags field value if set, zero value otherwise. +func (o *IterationRep) GetFlags() map[string]FlagRep { + if o == nil || o.Flags == nil { + var ret map[string]FlagRep + return ret + } + return *o.Flags +} + +// GetFlagsOk returns a tuple with the Flags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetFlagsOk() (*map[string]FlagRep, bool) { + if o == nil || o.Flags == nil { + return nil, false + } + return o.Flags, true +} + +// HasFlags returns a boolean if a field has been set. +func (o *IterationRep) HasFlags() bool { + if o != nil && o.Flags != nil { + return true + } + + return false +} + +// SetFlags gets a reference to the given map[string]FlagRep and assigns it to the Flags field. +func (o *IterationRep) SetFlags(v map[string]FlagRep) { + o.Flags = &v +} + +// GetPrimaryMetric returns the PrimaryMetric field value if set, zero value otherwise. +func (o *IterationRep) GetPrimaryMetric() DependentMetricOrMetricGroupRep { + if o == nil || o.PrimaryMetric == nil { + var ret DependentMetricOrMetricGroupRep + return ret + } + return *o.PrimaryMetric +} + +// GetPrimaryMetricOk returns a tuple with the PrimaryMetric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetPrimaryMetricOk() (*DependentMetricOrMetricGroupRep, bool) { + if o == nil || o.PrimaryMetric == nil { + return nil, false + } + return o.PrimaryMetric, true +} + +// HasPrimaryMetric returns a boolean if a field has been set. +func (o *IterationRep) HasPrimaryMetric() bool { + if o != nil && o.PrimaryMetric != nil { + return true + } + + return false +} + +// SetPrimaryMetric gets a reference to the given DependentMetricOrMetricGroupRep and assigns it to the PrimaryMetric field. +func (o *IterationRep) SetPrimaryMetric(v DependentMetricOrMetricGroupRep) { + o.PrimaryMetric = &v +} + +// GetPrimarySingleMetric returns the PrimarySingleMetric field value if set, zero value otherwise. +func (o *IterationRep) GetPrimarySingleMetric() MetricV2Rep { + if o == nil || o.PrimarySingleMetric == nil { + var ret MetricV2Rep + return ret + } + return *o.PrimarySingleMetric +} + +// GetPrimarySingleMetricOk returns a tuple with the PrimarySingleMetric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetPrimarySingleMetricOk() (*MetricV2Rep, bool) { + if o == nil || o.PrimarySingleMetric == nil { + return nil, false + } + return o.PrimarySingleMetric, true +} + +// HasPrimarySingleMetric returns a boolean if a field has been set. +func (o *IterationRep) HasPrimarySingleMetric() bool { + if o != nil && o.PrimarySingleMetric != nil { + return true + } + + return false +} + +// SetPrimarySingleMetric gets a reference to the given MetricV2Rep and assigns it to the PrimarySingleMetric field. +func (o *IterationRep) SetPrimarySingleMetric(v MetricV2Rep) { + o.PrimarySingleMetric = &v +} + +// GetPrimaryFunnel returns the PrimaryFunnel field value if set, zero value otherwise. +func (o *IterationRep) GetPrimaryFunnel() DependentMetricGroupRepWithMetrics { + if o == nil || o.PrimaryFunnel == nil { + var ret DependentMetricGroupRepWithMetrics + return ret + } + return *o.PrimaryFunnel +} + +// GetPrimaryFunnelOk returns a tuple with the PrimaryFunnel field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetPrimaryFunnelOk() (*DependentMetricGroupRepWithMetrics, bool) { + if o == nil || o.PrimaryFunnel == nil { + return nil, false + } + return o.PrimaryFunnel, true +} + +// HasPrimaryFunnel returns a boolean if a field has been set. +func (o *IterationRep) HasPrimaryFunnel() bool { + if o != nil && o.PrimaryFunnel != nil { + return true + } + + return false +} + +// SetPrimaryFunnel gets a reference to the given DependentMetricGroupRepWithMetrics and assigns it to the PrimaryFunnel field. +func (o *IterationRep) SetPrimaryFunnel(v DependentMetricGroupRepWithMetrics) { + o.PrimaryFunnel = &v +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *IterationRep) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *IterationRep) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *IterationRep) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +// GetAttributes returns the Attributes field value if set, zero value otherwise. +func (o *IterationRep) GetAttributes() []string { + if o == nil || o.Attributes == nil { + var ret []string + return ret + } + return o.Attributes +} + +// GetAttributesOk returns a tuple with the Attributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetAttributesOk() ([]string, bool) { + if o == nil || o.Attributes == nil { + return nil, false + } + return o.Attributes, true +} + +// HasAttributes returns a boolean if a field has been set. +func (o *IterationRep) HasAttributes() bool { + if o != nil && o.Attributes != nil { + return true + } + + return false +} + +// SetAttributes gets a reference to the given []string and assigns it to the Attributes field. +func (o *IterationRep) SetAttributes(v []string) { + o.Attributes = v +} + +// GetTreatments returns the Treatments field value if set, zero value otherwise. +func (o *IterationRep) GetTreatments() []TreatmentRep { + if o == nil || o.Treatments == nil { + var ret []TreatmentRep + return ret + } + return o.Treatments +} + +// GetTreatmentsOk returns a tuple with the Treatments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetTreatmentsOk() ([]TreatmentRep, bool) { + if o == nil || o.Treatments == nil { + return nil, false + } + return o.Treatments, true +} + +// HasTreatments returns a boolean if a field has been set. +func (o *IterationRep) HasTreatments() bool { + if o != nil && o.Treatments != nil { + return true + } + + return false +} + +// SetTreatments gets a reference to the given []TreatmentRep and assigns it to the Treatments field. +func (o *IterationRep) SetTreatments(v []TreatmentRep) { + o.Treatments = v +} + +// GetSecondaryMetrics returns the SecondaryMetrics field value if set, zero value otherwise. +// Deprecated +func (o *IterationRep) GetSecondaryMetrics() []MetricV2Rep { + if o == nil || o.SecondaryMetrics == nil { + var ret []MetricV2Rep + return ret + } + return o.SecondaryMetrics +} + +// GetSecondaryMetricsOk returns a tuple with the SecondaryMetrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *IterationRep) GetSecondaryMetricsOk() ([]MetricV2Rep, bool) { + if o == nil || o.SecondaryMetrics == nil { + return nil, false + } + return o.SecondaryMetrics, true +} + +// HasSecondaryMetrics returns a boolean if a field has been set. +func (o *IterationRep) HasSecondaryMetrics() bool { + if o != nil && o.SecondaryMetrics != nil { + return true + } + + return false +} + +// SetSecondaryMetrics gets a reference to the given []MetricV2Rep and assigns it to the SecondaryMetrics field. +// Deprecated +func (o *IterationRep) SetSecondaryMetrics(v []MetricV2Rep) { + o.SecondaryMetrics = v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *IterationRep) GetMetrics() []DependentMetricOrMetricGroupRep { + if o == nil || o.Metrics == nil { + var ret []DependentMetricOrMetricGroupRep + return ret + } + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetMetricsOk() ([]DependentMetricOrMetricGroupRep, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *IterationRep) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given []DependentMetricOrMetricGroupRep and assigns it to the Metrics field. +func (o *IterationRep) SetMetrics(v []DependentMetricOrMetricGroupRep) { + o.Metrics = v +} + +// GetLayerSnapshot returns the LayerSnapshot field value if set, zero value otherwise. +func (o *IterationRep) GetLayerSnapshot() LayerSnapshotRep { + if o == nil || o.LayerSnapshot == nil { + var ret LayerSnapshotRep + return ret + } + return *o.LayerSnapshot +} + +// GetLayerSnapshotOk returns a tuple with the LayerSnapshot field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IterationRep) GetLayerSnapshotOk() (*LayerSnapshotRep, bool) { + if o == nil || o.LayerSnapshot == nil { + return nil, false + } + return o.LayerSnapshot, true +} + +// HasLayerSnapshot returns a boolean if a field has been set. +func (o *IterationRep) HasLayerSnapshot() bool { + if o != nil && o.LayerSnapshot != nil { + return true + } + + return false +} + +// SetLayerSnapshot gets a reference to the given LayerSnapshotRep and assigns it to the LayerSnapshot field. +func (o *IterationRep) SetLayerSnapshot(v LayerSnapshotRep) { + o.LayerSnapshot = &v +} + +func (o IterationRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["hypothesis"] = o.Hypothesis + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if o.StartedAt != nil { + toSerialize["startedAt"] = o.StartedAt + } + if o.EndedAt != nil { + toSerialize["endedAt"] = o.EndedAt + } + if o.WinningTreatmentId != nil { + toSerialize["winningTreatmentId"] = o.WinningTreatmentId + } + if o.WinningReason != nil { + toSerialize["winningReason"] = o.WinningReason + } + if o.CanReshuffleTraffic != nil { + toSerialize["canReshuffleTraffic"] = o.CanReshuffleTraffic + } + if o.Flags != nil { + toSerialize["flags"] = o.Flags + } + if o.PrimaryMetric != nil { + toSerialize["primaryMetric"] = o.PrimaryMetric + } + if o.PrimarySingleMetric != nil { + toSerialize["primarySingleMetric"] = o.PrimarySingleMetric + } + if o.PrimaryFunnel != nil { + toSerialize["primaryFunnel"] = o.PrimaryFunnel + } + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + if o.Attributes != nil { + toSerialize["attributes"] = o.Attributes + } + if o.Treatments != nil { + toSerialize["treatments"] = o.Treatments + } + if o.SecondaryMetrics != nil { + toSerialize["secondaryMetrics"] = o.SecondaryMetrics + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + if o.LayerSnapshot != nil { + toSerialize["layerSnapshot"] = o.LayerSnapshot + } + return json.Marshal(toSerialize) +} + +type NullableIterationRep struct { + value *IterationRep + isSet bool +} + +func (v NullableIterationRep) Get() *IterationRep { + return v.value +} + +func (v *NullableIterationRep) Set(val *IterationRep) { + v.value = val + v.isSet = true +} + +func (v NullableIterationRep) IsSet() bool { + return v.isSet +} + +func (v *NullableIterationRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableIterationRep(val *IterationRep) *NullableIterationRep { + return &NullableIterationRep{value: val, isSet: true} +} + +func (v NullableIterationRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableIterationRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_last_seen_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_last_seen_metadata.go new file mode 100644 index 00000000..85169841 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_last_seen_metadata.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LastSeenMetadata struct for LastSeenMetadata +type LastSeenMetadata struct { + // The ID of the token used in the member's last session + TokenId *string `json:"tokenId,omitempty"` +} + +// NewLastSeenMetadata instantiates a new LastSeenMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLastSeenMetadata() *LastSeenMetadata { + this := LastSeenMetadata{} + return &this +} + +// NewLastSeenMetadataWithDefaults instantiates a new LastSeenMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLastSeenMetadataWithDefaults() *LastSeenMetadata { + this := LastSeenMetadata{} + return &this +} + +// GetTokenId returns the TokenId field value if set, zero value otherwise. +func (o *LastSeenMetadata) GetTokenId() string { + if o == nil || o.TokenId == nil { + var ret string + return ret + } + return *o.TokenId +} + +// GetTokenIdOk returns a tuple with the TokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LastSeenMetadata) GetTokenIdOk() (*string, bool) { + if o == nil || o.TokenId == nil { + return nil, false + } + return o.TokenId, true +} + +// HasTokenId returns a boolean if a field has been set. +func (o *LastSeenMetadata) HasTokenId() bool { + if o != nil && o.TokenId != nil { + return true + } + + return false +} + +// SetTokenId gets a reference to the given string and assigns it to the TokenId field. +func (o *LastSeenMetadata) SetTokenId(v string) { + o.TokenId = &v +} + +func (o LastSeenMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TokenId != nil { + toSerialize["tokenId"] = o.TokenId + } + return json.Marshal(toSerialize) +} + +type NullableLastSeenMetadata struct { + value *LastSeenMetadata + isSet bool +} + +func (v NullableLastSeenMetadata) Get() *LastSeenMetadata { + return v.value +} + +func (v *NullableLastSeenMetadata) Set(val *LastSeenMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableLastSeenMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableLastSeenMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLastSeenMetadata(val *LastSeenMetadata) *NullableLastSeenMetadata { + return &NullableLastSeenMetadata{value: val, isSet: true} +} + +func (v NullableLastSeenMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLastSeenMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_collection_rep.go new file mode 100644 index 00000000..950376b5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_collection_rep.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerCollectionRep struct for LayerCollectionRep +type LayerCollectionRep struct { + // The layers in the project + Items []LayerRep `json:"items"` + // The total number of layers in the project + TotalCount int32 `json:"totalCount"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewLayerCollectionRep instantiates a new LayerCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerCollectionRep(items []LayerRep, totalCount int32, links map[string]Link) *LayerCollectionRep { + this := LayerCollectionRep{} + this.Items = items + this.TotalCount = totalCount + this.Links = links + return &this +} + +// NewLayerCollectionRepWithDefaults instantiates a new LayerCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerCollectionRepWithDefaults() *LayerCollectionRep { + this := LayerCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *LayerCollectionRep) GetItems() []LayerRep { + if o == nil { + var ret []LayerRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *LayerCollectionRep) GetItemsOk() ([]LayerRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *LayerCollectionRep) SetItems(v []LayerRep) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *LayerCollectionRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *LayerCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *LayerCollectionRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetLinks returns the Links field value +func (o *LayerCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *LayerCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *LayerCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o LayerCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableLayerCollectionRep struct { + value *LayerCollectionRep + isSet bool +} + +func (v NullableLayerCollectionRep) Get() *LayerCollectionRep { + return v.value +} + +func (v *NullableLayerCollectionRep) Set(val *LayerCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableLayerCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerCollectionRep(val *LayerCollectionRep) *NullableLayerCollectionRep { + return &NullableLayerCollectionRep{value: val, isSet: true} +} + +func (v NullableLayerCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_configuration_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_configuration_rep.go new file mode 100644 index 00000000..a8f0bbab --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_configuration_rep.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerConfigurationRep struct for LayerConfigurationRep +type LayerConfigurationRep struct { + // The experiment reservations for the layer + Reservations []LayerReservationRep `json:"reservations"` +} + +// NewLayerConfigurationRep instantiates a new LayerConfigurationRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerConfigurationRep(reservations []LayerReservationRep) *LayerConfigurationRep { + this := LayerConfigurationRep{} + this.Reservations = reservations + return &this +} + +// NewLayerConfigurationRepWithDefaults instantiates a new LayerConfigurationRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerConfigurationRepWithDefaults() *LayerConfigurationRep { + this := LayerConfigurationRep{} + return &this +} + +// GetReservations returns the Reservations field value +func (o *LayerConfigurationRep) GetReservations() []LayerReservationRep { + if o == nil { + var ret []LayerReservationRep + return ret + } + + return o.Reservations +} + +// GetReservationsOk returns a tuple with the Reservations field value +// and a boolean to check if the value has been set. +func (o *LayerConfigurationRep) GetReservationsOk() ([]LayerReservationRep, bool) { + if o == nil { + return nil, false + } + return o.Reservations, true +} + +// SetReservations sets field value +func (o *LayerConfigurationRep) SetReservations(v []LayerReservationRep) { + o.Reservations = v +} + +func (o LayerConfigurationRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["reservations"] = o.Reservations + } + return json.Marshal(toSerialize) +} + +type NullableLayerConfigurationRep struct { + value *LayerConfigurationRep + isSet bool +} + +func (v NullableLayerConfigurationRep) Get() *LayerConfigurationRep { + return v.value +} + +func (v *NullableLayerConfigurationRep) Set(val *LayerConfigurationRep) { + v.value = val + v.isSet = true +} + +func (v NullableLayerConfigurationRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerConfigurationRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerConfigurationRep(val *LayerConfigurationRep) *NullableLayerConfigurationRep { + return &NullableLayerConfigurationRep{value: val, isSet: true} +} + +func (v NullableLayerConfigurationRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerConfigurationRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_patch_input.go new file mode 100644 index 00000000..edd37543 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_patch_input.go @@ -0,0 +1,183 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerPatchInput struct for LayerPatchInput +type LayerPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + // The environment key used for making environment specific updates. For example, updating the reservation of an experiment + EnvironmentKey *string `json:"environmentKey,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewLayerPatchInput instantiates a new LayerPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerPatchInput(instructions []map[string]interface{}) *LayerPatchInput { + this := LayerPatchInput{} + this.Instructions = instructions + return &this +} + +// NewLayerPatchInputWithDefaults instantiates a new LayerPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerPatchInputWithDefaults() *LayerPatchInput { + this := LayerPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *LayerPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LayerPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *LayerPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *LayerPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetEnvironmentKey returns the EnvironmentKey field value if set, zero value otherwise. +func (o *LayerPatchInput) GetEnvironmentKey() string { + if o == nil || o.EnvironmentKey == nil { + var ret string + return ret + } + return *o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LayerPatchInput) GetEnvironmentKeyOk() (*string, bool) { + if o == nil || o.EnvironmentKey == nil { + return nil, false + } + return o.EnvironmentKey, true +} + +// HasEnvironmentKey returns a boolean if a field has been set. +func (o *LayerPatchInput) HasEnvironmentKey() bool { + if o != nil && o.EnvironmentKey != nil { + return true + } + + return false +} + +// SetEnvironmentKey gets a reference to the given string and assigns it to the EnvironmentKey field. +func (o *LayerPatchInput) SetEnvironmentKey(v string) { + o.EnvironmentKey = &v +} + +// GetInstructions returns the Instructions field value +func (o *LayerPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *LayerPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *LayerPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o LayerPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.EnvironmentKey != nil { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableLayerPatchInput struct { + value *LayerPatchInput + isSet bool +} + +func (v NullableLayerPatchInput) Get() *LayerPatchInput { + return v.value +} + +func (v *NullableLayerPatchInput) Set(val *LayerPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableLayerPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerPatchInput(val *LayerPatchInput) *NullableLayerPatchInput { + return &NullableLayerPatchInput{value: val, isSet: true} +} + +func (v NullableLayerPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_post.go new file mode 100644 index 00000000..6674ddff --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_post.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerPost struct for LayerPost +type LayerPost struct { + // Unique identifier for the layer + Key string `json:"key"` + // Layer name + Name string `json:"name"` + // The checkout flow for the application + Description string `json:"description"` +} + +// NewLayerPost instantiates a new LayerPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerPost(key string, name string, description string) *LayerPost { + this := LayerPost{} + this.Key = key + this.Name = name + this.Description = description + return &this +} + +// NewLayerPostWithDefaults instantiates a new LayerPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerPostWithDefaults() *LayerPost { + this := LayerPost{} + return &this +} + +// GetKey returns the Key field value +func (o *LayerPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *LayerPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *LayerPost) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *LayerPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *LayerPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *LayerPost) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value +func (o *LayerPost) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *LayerPost) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *LayerPost) SetDescription(v string) { + o.Description = v +} + +func (o LayerPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["description"] = o.Description + } + return json.Marshal(toSerialize) +} + +type NullableLayerPost struct { + value *LayerPost + isSet bool +} + +func (v NullableLayerPost) Get() *LayerPost { + return v.value +} + +func (v *NullableLayerPost) Set(val *LayerPost) { + v.value = val + v.isSet = true +} + +func (v NullableLayerPost) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerPost(val *LayerPost) *NullableLayerPost { + return &NullableLayerPost{value: val, isSet: true} +} + +func (v NullableLayerPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_rep.go new file mode 100644 index 00000000..97f7e5f5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_rep.go @@ -0,0 +1,273 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerRep struct for LayerRep +type LayerRep struct { + // The key of the layer + Key string `json:"key"` + // The name of the layer + Name string `json:"name"` + // The description of the layer + Description string `json:"description"` + CreatedAt int64 `json:"createdAt"` + // The unit of randomization for the layer + RandomizationUnit *string `json:"randomizationUnit,omitempty"` + // The layer configurations for each requested environment + Environments *map[string]LayerConfigurationRep `json:"environments,omitempty"` +} + +// NewLayerRep instantiates a new LayerRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerRep(key string, name string, description string, createdAt int64) *LayerRep { + this := LayerRep{} + this.Key = key + this.Name = name + this.Description = description + this.CreatedAt = createdAt + return &this +} + +// NewLayerRepWithDefaults instantiates a new LayerRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerRepWithDefaults() *LayerRep { + this := LayerRep{} + return &this +} + +// GetKey returns the Key field value +func (o *LayerRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *LayerRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *LayerRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *LayerRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *LayerRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *LayerRep) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value +func (o *LayerRep) GetDescription() string { + if o == nil { + var ret string + return ret + } + + return o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value +// and a boolean to check if the value has been set. +func (o *LayerRep) GetDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Description, true +} + +// SetDescription sets field value +func (o *LayerRep) SetDescription(v string) { + o.Description = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *LayerRep) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *LayerRep) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *LayerRep) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *LayerRep) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LayerRep) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *LayerRep) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *LayerRep) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *LayerRep) GetEnvironments() map[string]LayerConfigurationRep { + if o == nil || o.Environments == nil { + var ret map[string]LayerConfigurationRep + return ret + } + return *o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LayerRep) GetEnvironmentsOk() (*map[string]LayerConfigurationRep, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *LayerRep) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given map[string]LayerConfigurationRep and assigns it to the Environments field. +func (o *LayerRep) SetEnvironments(v map[string]LayerConfigurationRep) { + o.Environments = &v +} + +func (o LayerRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["description"] = o.Description + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + return json.Marshal(toSerialize) +} + +type NullableLayerRep struct { + value *LayerRep + isSet bool +} + +func (v NullableLayerRep) Get() *LayerRep { + return v.value +} + +func (v *NullableLayerRep) Set(val *LayerRep) { + v.value = val + v.isSet = true +} + +func (v NullableLayerRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerRep(val *LayerRep) *NullableLayerRep { + return &NullableLayerRep{value: val, isSet: true} +} + +func (v NullableLayerRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_reservation_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_reservation_rep.go new file mode 100644 index 00000000..db00a141 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_reservation_rep.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerReservationRep struct for LayerReservationRep +type LayerReservationRep struct { + // The key of the experiment + ExperimentKey string `json:"experimentKey"` + // The key of the flag + FlagKey string `json:"flagKey"` + // The percentage of traffic reserved for the experiment + ReservationPercent int32 `json:"reservationPercent"` +} + +// NewLayerReservationRep instantiates a new LayerReservationRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerReservationRep(experimentKey string, flagKey string, reservationPercent int32) *LayerReservationRep { + this := LayerReservationRep{} + this.ExperimentKey = experimentKey + this.FlagKey = flagKey + this.ReservationPercent = reservationPercent + return &this +} + +// NewLayerReservationRepWithDefaults instantiates a new LayerReservationRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerReservationRepWithDefaults() *LayerReservationRep { + this := LayerReservationRep{} + return &this +} + +// GetExperimentKey returns the ExperimentKey field value +func (o *LayerReservationRep) GetExperimentKey() string { + if o == nil { + var ret string + return ret + } + + return o.ExperimentKey +} + +// GetExperimentKeyOk returns a tuple with the ExperimentKey field value +// and a boolean to check if the value has been set. +func (o *LayerReservationRep) GetExperimentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ExperimentKey, true +} + +// SetExperimentKey sets field value +func (o *LayerReservationRep) SetExperimentKey(v string) { + o.ExperimentKey = v +} + +// GetFlagKey returns the FlagKey field value +func (o *LayerReservationRep) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *LayerReservationRep) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *LayerReservationRep) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetReservationPercent returns the ReservationPercent field value +func (o *LayerReservationRep) GetReservationPercent() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ReservationPercent +} + +// GetReservationPercentOk returns a tuple with the ReservationPercent field value +// and a boolean to check if the value has been set. +func (o *LayerReservationRep) GetReservationPercentOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ReservationPercent, true +} + +// SetReservationPercent sets field value +func (o *LayerReservationRep) SetReservationPercent(v int32) { + o.ReservationPercent = v +} + +func (o LayerReservationRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["experimentKey"] = o.ExperimentKey + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["reservationPercent"] = o.ReservationPercent + } + return json.Marshal(toSerialize) +} + +type NullableLayerReservationRep struct { + value *LayerReservationRep + isSet bool +} + +func (v NullableLayerReservationRep) Get() *LayerReservationRep { + return v.value +} + +func (v *NullableLayerReservationRep) Set(val *LayerReservationRep) { + v.value = val + v.isSet = true +} + +func (v NullableLayerReservationRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerReservationRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerReservationRep(val *LayerReservationRep) *NullableLayerReservationRep { + return &NullableLayerReservationRep{value: val, isSet: true} +} + +func (v NullableLayerReservationRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerReservationRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_snapshot_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_snapshot_rep.go new file mode 100644 index 00000000..104fc767 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_layer_snapshot_rep.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LayerSnapshotRep struct for LayerSnapshotRep +type LayerSnapshotRep struct { + // Key of the layer the experiment was part of + Key string `json:"key"` + // Layer name at the time this experiment iteration was stopped + Name string `json:"name"` + // Percent of layer traffic that was reserved in the layer for this experiment iteration + ReservationPercent int32 `json:"reservationPercent"` + // Percent of layer traffic that was reserved for other experiments in the same environment, when this experiment iteration was stopped + OtherReservationPercent int32 `json:"otherReservationPercent"` +} + +// NewLayerSnapshotRep instantiates a new LayerSnapshotRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLayerSnapshotRep(key string, name string, reservationPercent int32, otherReservationPercent int32) *LayerSnapshotRep { + this := LayerSnapshotRep{} + this.Key = key + this.Name = name + this.ReservationPercent = reservationPercent + this.OtherReservationPercent = otherReservationPercent + return &this +} + +// NewLayerSnapshotRepWithDefaults instantiates a new LayerSnapshotRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLayerSnapshotRepWithDefaults() *LayerSnapshotRep { + this := LayerSnapshotRep{} + return &this +} + +// GetKey returns the Key field value +func (o *LayerSnapshotRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *LayerSnapshotRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *LayerSnapshotRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *LayerSnapshotRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *LayerSnapshotRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *LayerSnapshotRep) SetName(v string) { + o.Name = v +} + +// GetReservationPercent returns the ReservationPercent field value +func (o *LayerSnapshotRep) GetReservationPercent() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ReservationPercent +} + +// GetReservationPercentOk returns a tuple with the ReservationPercent field value +// and a boolean to check if the value has been set. +func (o *LayerSnapshotRep) GetReservationPercentOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ReservationPercent, true +} + +// SetReservationPercent sets field value +func (o *LayerSnapshotRep) SetReservationPercent(v int32) { + o.ReservationPercent = v +} + +// GetOtherReservationPercent returns the OtherReservationPercent field value +func (o *LayerSnapshotRep) GetOtherReservationPercent() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.OtherReservationPercent +} + +// GetOtherReservationPercentOk returns a tuple with the OtherReservationPercent field value +// and a boolean to check if the value has been set. +func (o *LayerSnapshotRep) GetOtherReservationPercentOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.OtherReservationPercent, true +} + +// SetOtherReservationPercent sets field value +func (o *LayerSnapshotRep) SetOtherReservationPercent(v int32) { + o.OtherReservationPercent = v +} + +func (o LayerSnapshotRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["reservationPercent"] = o.ReservationPercent + } + if true { + toSerialize["otherReservationPercent"] = o.OtherReservationPercent + } + return json.Marshal(toSerialize) +} + +type NullableLayerSnapshotRep struct { + value *LayerSnapshotRep + isSet bool +} + +func (v NullableLayerSnapshotRep) Get() *LayerSnapshotRep { + return v.value +} + +func (v *NullableLayerSnapshotRep) Set(val *LayerSnapshotRep) { + v.value = val + v.isSet = true +} + +func (v NullableLayerSnapshotRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLayerSnapshotRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLayerSnapshotRep(val *LayerSnapshotRep) *NullableLayerSnapshotRep { + return &NullableLayerSnapshotRep{value: val, isSet: true} +} + +func (v NullableLayerSnapshotRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLayerSnapshotRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_lead_time_stages_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_lead_time_stages_rep.go new file mode 100644 index 00000000..ebe8b898 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_lead_time_stages_rep.go @@ -0,0 +1,258 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LeadTimeStagesRep struct for LeadTimeStagesRep +type LeadTimeStagesRep struct { + // The coding duration in milliseconds + CodingDurationMs int64 `json:"codingDurationMs"` + // The review duration in milliseconds + ReviewDurationMs *int64 `json:"reviewDurationMs,omitempty"` + // The wait duration between merge time and deploy start time in milliseconds + WaitDurationMs *int64 `json:"waitDurationMs,omitempty"` + // The deploy duration in milliseconds + DeployDurationMs *int64 `json:"deployDurationMs,omitempty"` + // The total lead time in milliseconds + TotalLeadTimeMs *int64 `json:"totalLeadTimeMs,omitempty"` +} + +// NewLeadTimeStagesRep instantiates a new LeadTimeStagesRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLeadTimeStagesRep(codingDurationMs int64) *LeadTimeStagesRep { + this := LeadTimeStagesRep{} + this.CodingDurationMs = codingDurationMs + return &this +} + +// NewLeadTimeStagesRepWithDefaults instantiates a new LeadTimeStagesRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLeadTimeStagesRepWithDefaults() *LeadTimeStagesRep { + this := LeadTimeStagesRep{} + return &this +} + +// GetCodingDurationMs returns the CodingDurationMs field value +func (o *LeadTimeStagesRep) GetCodingDurationMs() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CodingDurationMs +} + +// GetCodingDurationMsOk returns a tuple with the CodingDurationMs field value +// and a boolean to check if the value has been set. +func (o *LeadTimeStagesRep) GetCodingDurationMsOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CodingDurationMs, true +} + +// SetCodingDurationMs sets field value +func (o *LeadTimeStagesRep) SetCodingDurationMs(v int64) { + o.CodingDurationMs = v +} + +// GetReviewDurationMs returns the ReviewDurationMs field value if set, zero value otherwise. +func (o *LeadTimeStagesRep) GetReviewDurationMs() int64 { + if o == nil || o.ReviewDurationMs == nil { + var ret int64 + return ret + } + return *o.ReviewDurationMs +} + +// GetReviewDurationMsOk returns a tuple with the ReviewDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LeadTimeStagesRep) GetReviewDurationMsOk() (*int64, bool) { + if o == nil || o.ReviewDurationMs == nil { + return nil, false + } + return o.ReviewDurationMs, true +} + +// HasReviewDurationMs returns a boolean if a field has been set. +func (o *LeadTimeStagesRep) HasReviewDurationMs() bool { + if o != nil && o.ReviewDurationMs != nil { + return true + } + + return false +} + +// SetReviewDurationMs gets a reference to the given int64 and assigns it to the ReviewDurationMs field. +func (o *LeadTimeStagesRep) SetReviewDurationMs(v int64) { + o.ReviewDurationMs = &v +} + +// GetWaitDurationMs returns the WaitDurationMs field value if set, zero value otherwise. +func (o *LeadTimeStagesRep) GetWaitDurationMs() int64 { + if o == nil || o.WaitDurationMs == nil { + var ret int64 + return ret + } + return *o.WaitDurationMs +} + +// GetWaitDurationMsOk returns a tuple with the WaitDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LeadTimeStagesRep) GetWaitDurationMsOk() (*int64, bool) { + if o == nil || o.WaitDurationMs == nil { + return nil, false + } + return o.WaitDurationMs, true +} + +// HasWaitDurationMs returns a boolean if a field has been set. +func (o *LeadTimeStagesRep) HasWaitDurationMs() bool { + if o != nil && o.WaitDurationMs != nil { + return true + } + + return false +} + +// SetWaitDurationMs gets a reference to the given int64 and assigns it to the WaitDurationMs field. +func (o *LeadTimeStagesRep) SetWaitDurationMs(v int64) { + o.WaitDurationMs = &v +} + +// GetDeployDurationMs returns the DeployDurationMs field value if set, zero value otherwise. +func (o *LeadTimeStagesRep) GetDeployDurationMs() int64 { + if o == nil || o.DeployDurationMs == nil { + var ret int64 + return ret + } + return *o.DeployDurationMs +} + +// GetDeployDurationMsOk returns a tuple with the DeployDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LeadTimeStagesRep) GetDeployDurationMsOk() (*int64, bool) { + if o == nil || o.DeployDurationMs == nil { + return nil, false + } + return o.DeployDurationMs, true +} + +// HasDeployDurationMs returns a boolean if a field has been set. +func (o *LeadTimeStagesRep) HasDeployDurationMs() bool { + if o != nil && o.DeployDurationMs != nil { + return true + } + + return false +} + +// SetDeployDurationMs gets a reference to the given int64 and assigns it to the DeployDurationMs field. +func (o *LeadTimeStagesRep) SetDeployDurationMs(v int64) { + o.DeployDurationMs = &v +} + +// GetTotalLeadTimeMs returns the TotalLeadTimeMs field value if set, zero value otherwise. +func (o *LeadTimeStagesRep) GetTotalLeadTimeMs() int64 { + if o == nil || o.TotalLeadTimeMs == nil { + var ret int64 + return ret + } + return *o.TotalLeadTimeMs +} + +// GetTotalLeadTimeMsOk returns a tuple with the TotalLeadTimeMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LeadTimeStagesRep) GetTotalLeadTimeMsOk() (*int64, bool) { + if o == nil || o.TotalLeadTimeMs == nil { + return nil, false + } + return o.TotalLeadTimeMs, true +} + +// HasTotalLeadTimeMs returns a boolean if a field has been set. +func (o *LeadTimeStagesRep) HasTotalLeadTimeMs() bool { + if o != nil && o.TotalLeadTimeMs != nil { + return true + } + + return false +} + +// SetTotalLeadTimeMs gets a reference to the given int64 and assigns it to the TotalLeadTimeMs field. +func (o *LeadTimeStagesRep) SetTotalLeadTimeMs(v int64) { + o.TotalLeadTimeMs = &v +} + +func (o LeadTimeStagesRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["codingDurationMs"] = o.CodingDurationMs + } + if o.ReviewDurationMs != nil { + toSerialize["reviewDurationMs"] = o.ReviewDurationMs + } + if o.WaitDurationMs != nil { + toSerialize["waitDurationMs"] = o.WaitDurationMs + } + if o.DeployDurationMs != nil { + toSerialize["deployDurationMs"] = o.DeployDurationMs + } + if o.TotalLeadTimeMs != nil { + toSerialize["totalLeadTimeMs"] = o.TotalLeadTimeMs + } + return json.Marshal(toSerialize) +} + +type NullableLeadTimeStagesRep struct { + value *LeadTimeStagesRep + isSet bool +} + +func (v NullableLeadTimeStagesRep) Get() *LeadTimeStagesRep { + return v.value +} + +func (v *NullableLeadTimeStagesRep) Set(val *LeadTimeStagesRep) { + v.value = val + v.isSet = true +} + +func (v NullableLeadTimeStagesRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLeadTimeStagesRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLeadTimeStagesRep(val *LeadTimeStagesRep) *NullableLeadTimeStagesRep { + return &NullableLeadTimeStagesRep{value: val, isSet: true} +} + +func (v NullableLeadTimeStagesRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLeadTimeStagesRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_legacy_experiment_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_legacy_experiment_rep.go new file mode 100644 index 00000000..28a341ad --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_legacy_experiment_rep.go @@ -0,0 +1,224 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// LegacyExperimentRep struct for LegacyExperimentRep +type LegacyExperimentRep struct { + MetricKey *string `json:"metricKey,omitempty"` + Metric *MetricListingRep `json:"_metric,omitempty"` + Environments []string `json:"environments,omitempty"` + EnvironmentSettings *map[string]ExperimentEnvironmentSettingRep `json:"_environmentSettings,omitempty"` +} + +// NewLegacyExperimentRep instantiates a new LegacyExperimentRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLegacyExperimentRep() *LegacyExperimentRep { + this := LegacyExperimentRep{} + return &this +} + +// NewLegacyExperimentRepWithDefaults instantiates a new LegacyExperimentRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLegacyExperimentRepWithDefaults() *LegacyExperimentRep { + this := LegacyExperimentRep{} + return &this +} + +// GetMetricKey returns the MetricKey field value if set, zero value otherwise. +func (o *LegacyExperimentRep) GetMetricKey() string { + if o == nil || o.MetricKey == nil { + var ret string + return ret + } + return *o.MetricKey +} + +// GetMetricKeyOk returns a tuple with the MetricKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LegacyExperimentRep) GetMetricKeyOk() (*string, bool) { + if o == nil || o.MetricKey == nil { + return nil, false + } + return o.MetricKey, true +} + +// HasMetricKey returns a boolean if a field has been set. +func (o *LegacyExperimentRep) HasMetricKey() bool { + if o != nil && o.MetricKey != nil { + return true + } + + return false +} + +// SetMetricKey gets a reference to the given string and assigns it to the MetricKey field. +func (o *LegacyExperimentRep) SetMetricKey(v string) { + o.MetricKey = &v +} + +// GetMetric returns the Metric field value if set, zero value otherwise. +func (o *LegacyExperimentRep) GetMetric() MetricListingRep { + if o == nil || o.Metric == nil { + var ret MetricListingRep + return ret + } + return *o.Metric +} + +// GetMetricOk returns a tuple with the Metric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LegacyExperimentRep) GetMetricOk() (*MetricListingRep, bool) { + if o == nil || o.Metric == nil { + return nil, false + } + return o.Metric, true +} + +// HasMetric returns a boolean if a field has been set. +func (o *LegacyExperimentRep) HasMetric() bool { + if o != nil && o.Metric != nil { + return true + } + + return false +} + +// SetMetric gets a reference to the given MetricListingRep and assigns it to the Metric field. +func (o *LegacyExperimentRep) SetMetric(v MetricListingRep) { + o.Metric = &v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *LegacyExperimentRep) GetEnvironments() []string { + if o == nil || o.Environments == nil { + var ret []string + return ret + } + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LegacyExperimentRep) GetEnvironmentsOk() ([]string, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *LegacyExperimentRep) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given []string and assigns it to the Environments field. +func (o *LegacyExperimentRep) SetEnvironments(v []string) { + o.Environments = v +} + +// GetEnvironmentSettings returns the EnvironmentSettings field value if set, zero value otherwise. +func (o *LegacyExperimentRep) GetEnvironmentSettings() map[string]ExperimentEnvironmentSettingRep { + if o == nil || o.EnvironmentSettings == nil { + var ret map[string]ExperimentEnvironmentSettingRep + return ret + } + return *o.EnvironmentSettings +} + +// GetEnvironmentSettingsOk returns a tuple with the EnvironmentSettings field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *LegacyExperimentRep) GetEnvironmentSettingsOk() (*map[string]ExperimentEnvironmentSettingRep, bool) { + if o == nil || o.EnvironmentSettings == nil { + return nil, false + } + return o.EnvironmentSettings, true +} + +// HasEnvironmentSettings returns a boolean if a field has been set. +func (o *LegacyExperimentRep) HasEnvironmentSettings() bool { + if o != nil && o.EnvironmentSettings != nil { + return true + } + + return false +} + +// SetEnvironmentSettings gets a reference to the given map[string]ExperimentEnvironmentSettingRep and assigns it to the EnvironmentSettings field. +func (o *LegacyExperimentRep) SetEnvironmentSettings(v map[string]ExperimentEnvironmentSettingRep) { + o.EnvironmentSettings = &v +} + +func (o LegacyExperimentRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.MetricKey != nil { + toSerialize["metricKey"] = o.MetricKey + } + if o.Metric != nil { + toSerialize["_metric"] = o.Metric + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + if o.EnvironmentSettings != nil { + toSerialize["_environmentSettings"] = o.EnvironmentSettings + } + return json.Marshal(toSerialize) +} + +type NullableLegacyExperimentRep struct { + value *LegacyExperimentRep + isSet bool +} + +func (v NullableLegacyExperimentRep) Get() *LegacyExperimentRep { + return v.value +} + +func (v *NullableLegacyExperimentRep) Set(val *LegacyExperimentRep) { + v.value = val + v.isSet = true +} + +func (v NullableLegacyExperimentRep) IsSet() bool { + return v.isSet +} + +func (v *NullableLegacyExperimentRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLegacyExperimentRep(val *LegacyExperimentRep) *NullableLegacyExperimentRep { + return &NullableLegacyExperimentRep{value: val, isSet: true} +} + +func (v NullableLegacyExperimentRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLegacyExperimentRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_link.go new file mode 100644 index 00000000..dc5f0cb4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_link.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Link struct for Link +type Link struct { + Href *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NewLink instantiates a new Link object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLink() *Link { + this := Link{} + return &this +} + +// NewLinkWithDefaults instantiates a new Link object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLinkWithDefaults() *Link { + this := Link{} + return &this +} + +// GetHref returns the Href field value if set, zero value otherwise. +func (o *Link) GetHref() string { + if o == nil || o.Href == nil { + var ret string + return ret + } + return *o.Href +} + +// GetHrefOk returns a tuple with the Href field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Link) GetHrefOk() (*string, bool) { + if o == nil || o.Href == nil { + return nil, false + } + return o.Href, true +} + +// HasHref returns a boolean if a field has been set. +func (o *Link) HasHref() bool { + if o != nil && o.Href != nil { + return true + } + + return false +} + +// SetHref gets a reference to the given string and assigns it to the Href field. +func (o *Link) SetHref(v string) { + o.Href = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *Link) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Link) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *Link) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *Link) SetType(v string) { + o.Type = &v +} + +func (o Link) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Href != nil { + toSerialize["href"] = o.Href + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + return json.Marshal(toSerialize) +} + +type NullableLink struct { + value *Link + isSet bool +} + +func (v NullableLink) Get() *Link { + return v.value +} + +func (v *NullableLink) Set(val *Link) { + v.value = val + v.isSet = true +} + +func (v NullableLink) IsSet() bool { + return v.isSet +} + +func (v *NullableLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLink(val *Link) *NullableLink { + return &NullableLink{value: val, isSet: true} +} + +func (v NullableLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_member.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_member.go new file mode 100644 index 00000000..d520ed9e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_member.go @@ -0,0 +1,239 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MaintainerMember struct for MaintainerMember +type MaintainerMember struct { + Id string `json:"_id"` + Email string `json:"email"` + FirstName *string `json:"firstName,omitempty"` + LastName *string `json:"lastName,omitempty"` + Role string `json:"role"` +} + +// NewMaintainerMember instantiates a new MaintainerMember object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMaintainerMember(id string, email string, role string) *MaintainerMember { + this := MaintainerMember{} + this.Id = id + this.Email = email + this.Role = role + return &this +} + +// NewMaintainerMemberWithDefaults instantiates a new MaintainerMember object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMaintainerMemberWithDefaults() *MaintainerMember { + this := MaintainerMember{} + return &this +} + +// GetId returns the Id field value +func (o *MaintainerMember) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MaintainerMember) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MaintainerMember) SetId(v string) { + o.Id = v +} + +// GetEmail returns the Email field value +func (o *MaintainerMember) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *MaintainerMember) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *MaintainerMember) SetEmail(v string) { + o.Email = v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *MaintainerMember) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MaintainerMember) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *MaintainerMember) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *MaintainerMember) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *MaintainerMember) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MaintainerMember) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *MaintainerMember) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *MaintainerMember) SetLastName(v string) { + o.LastName = &v +} + +// GetRole returns the Role field value +func (o *MaintainerMember) GetRole() string { + if o == nil { + var ret string + return ret + } + + return o.Role +} + +// GetRoleOk returns a tuple with the Role field value +// and a boolean to check if the value has been set. +func (o *MaintainerMember) GetRoleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Role, true +} + +// SetRole sets field value +func (o *MaintainerMember) SetRole(v string) { + o.Role = v +} + +func (o MaintainerMember) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["email"] = o.Email + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if true { + toSerialize["role"] = o.Role + } + return json.Marshal(toSerialize) +} + +type NullableMaintainerMember struct { + value *MaintainerMember + isSet bool +} + +func (v NullableMaintainerMember) Get() *MaintainerMember { + return v.value +} + +func (v *NullableMaintainerMember) Set(val *MaintainerMember) { + v.value = val + v.isSet = true +} + +func (v NullableMaintainerMember) IsSet() bool { + return v.isSet +} + +func (v *NullableMaintainerMember) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMaintainerMember(val *MaintainerMember) *NullableMaintainerMember { + return &NullableMaintainerMember{value: val, isSet: true} +} + +func (v NullableMaintainerMember) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMaintainerMember) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_rep.go new file mode 100644 index 00000000..d25ed539 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_rep.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MaintainerRep struct for MaintainerRep +type MaintainerRep struct { + Member *MemberSummary `json:"member,omitempty"` + Team *MemberTeamSummaryRep `json:"team,omitempty"` +} + +// NewMaintainerRep instantiates a new MaintainerRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMaintainerRep() *MaintainerRep { + this := MaintainerRep{} + return &this +} + +// NewMaintainerRepWithDefaults instantiates a new MaintainerRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMaintainerRepWithDefaults() *MaintainerRep { + this := MaintainerRep{} + return &this +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *MaintainerRep) GetMember() MemberSummary { + if o == nil || o.Member == nil { + var ret MemberSummary + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MaintainerRep) GetMemberOk() (*MemberSummary, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *MaintainerRep) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given MemberSummary and assigns it to the Member field. +func (o *MaintainerRep) SetMember(v MemberSummary) { + o.Member = &v +} + +// GetTeam returns the Team field value if set, zero value otherwise. +func (o *MaintainerRep) GetTeam() MemberTeamSummaryRep { + if o == nil || o.Team == nil { + var ret MemberTeamSummaryRep + return ret + } + return *o.Team +} + +// GetTeamOk returns a tuple with the Team field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MaintainerRep) GetTeamOk() (*MemberTeamSummaryRep, bool) { + if o == nil || o.Team == nil { + return nil, false + } + return o.Team, true +} + +// HasTeam returns a boolean if a field has been set. +func (o *MaintainerRep) HasTeam() bool { + if o != nil && o.Team != nil { + return true + } + + return false +} + +// SetTeam gets a reference to the given MemberTeamSummaryRep and assigns it to the Team field. +func (o *MaintainerRep) SetTeam(v MemberTeamSummaryRep) { + o.Team = &v +} + +func (o MaintainerRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Member != nil { + toSerialize["member"] = o.Member + } + if o.Team != nil { + toSerialize["team"] = o.Team + } + return json.Marshal(toSerialize) +} + +type NullableMaintainerRep struct { + value *MaintainerRep + isSet bool +} + +func (v NullableMaintainerRep) Get() *MaintainerRep { + return v.value +} + +func (v *NullableMaintainerRep) Set(val *MaintainerRep) { + v.value = val + v.isSet = true +} + +func (v NullableMaintainerRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMaintainerRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMaintainerRep(val *MaintainerRep) *NullableMaintainerRep { + return &NullableMaintainerRep{value: val, isSet: true} +} + +func (v NullableMaintainerRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMaintainerRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_team.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_team.go new file mode 100644 index 00000000..65e991bb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_maintainer_team.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MaintainerTeam struct for MaintainerTeam +type MaintainerTeam struct { + // The key of the maintainer team + Key string `json:"key"` + // A human-friendly name for the maintainer team + Name string `json:"name"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewMaintainerTeam instantiates a new MaintainerTeam object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMaintainerTeam(key string, name string) *MaintainerTeam { + this := MaintainerTeam{} + this.Key = key + this.Name = name + return &this +} + +// NewMaintainerTeamWithDefaults instantiates a new MaintainerTeam object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMaintainerTeamWithDefaults() *MaintainerTeam { + this := MaintainerTeam{} + return &this +} + +// GetKey returns the Key field value +func (o *MaintainerTeam) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MaintainerTeam) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MaintainerTeam) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *MaintainerTeam) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MaintainerTeam) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MaintainerTeam) SetName(v string) { + o.Name = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *MaintainerTeam) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MaintainerTeam) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *MaintainerTeam) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *MaintainerTeam) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o MaintainerTeam) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableMaintainerTeam struct { + value *MaintainerTeam + isSet bool +} + +func (v NullableMaintainerTeam) Get() *MaintainerTeam { + return v.value +} + +func (v *NullableMaintainerTeam) Set(val *MaintainerTeam) { + v.value = val + v.isSet = true +} + +func (v NullableMaintainerTeam) IsSet() bool { + return v.isSet +} + +func (v *NullableMaintainerTeam) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMaintainerTeam(val *MaintainerTeam) *NullableMaintainerTeam { + return &NullableMaintainerTeam{value: val, isSet: true} +} + +func (v NullableMaintainerTeam) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMaintainerTeam) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member.go new file mode 100644 index 00000000..b766afbc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member.go @@ -0,0 +1,782 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Member struct for Member +type Member struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The member's ID + Id string `json:"_id"` + // The member's first name + FirstName *string `json:"firstName,omitempty"` + // The member's last name + LastName *string `json:"lastName,omitempty"` + // The member's built-in role. If the member has no custom roles, this role will be in effect. + Role string `json:"role"` + // The member's email address + Email string `json:"email"` + // Whether the member has a pending invitation + PendingInvite bool `json:"_pendingInvite"` + // Whether the member's email address has been verified + Verified bool `json:"_verified"` + // The member's email address before it has been verified, for accounts where email verification is required + PendingEmail *string `json:"_pendingEmail,omitempty"` + // The set of custom roles (as keys) assigned to the member + CustomRoles []string `json:"customRoles"` + // Whether multi-factor authentication is enabled for this member + Mfa string `json:"mfa"` + // Default dashboards that the member has chosen to ignore + ExcludedDashboards []string `json:"excludedDashboards,omitempty"` + LastSeen int64 `json:"_lastSeen"` + LastSeenMetadata *LastSeenMetadata `json:"_lastSeenMetadata,omitempty"` + IntegrationMetadata *IntegrationMetadata `json:"_integrationMetadata,omitempty"` + // Details on the teams this member is assigned to + Teams []MemberTeamSummaryRep `json:"teams,omitempty"` + // A list of permission grants. Permission grants allow a member to have access to a specific action, without having to create or update a custom role. + PermissionGrants []MemberPermissionGrantSummaryRep `json:"permissionGrants,omitempty"` + CreationDate int64 `json:"creationDate"` + // A list of OAuth providers + OauthProviders []string `json:"oauthProviders,omitempty"` + // Version of the current configuration + Version *int32 `json:"version,omitempty"` + RoleAttributes *map[string][]string `json:"roleAttributes,omitempty"` +} + +// NewMember instantiates a new Member object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMember(links map[string]Link, id string, role string, email string, pendingInvite bool, verified bool, customRoles []string, mfa string, lastSeen int64, creationDate int64) *Member { + this := Member{} + this.Links = links + this.Id = id + this.Role = role + this.Email = email + this.PendingInvite = pendingInvite + this.Verified = verified + this.CustomRoles = customRoles + this.Mfa = mfa + this.LastSeen = lastSeen + this.CreationDate = creationDate + return &this +} + +// NewMemberWithDefaults instantiates a new Member object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberWithDefaults() *Member { + this := Member{} + return &this +} + +// GetLinks returns the Links field value +func (o *Member) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Member) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Member) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *Member) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Member) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Member) SetId(v string) { + o.Id = v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *Member) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *Member) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *Member) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *Member) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *Member) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *Member) SetLastName(v string) { + o.LastName = &v +} + +// GetRole returns the Role field value +func (o *Member) GetRole() string { + if o == nil { + var ret string + return ret + } + + return o.Role +} + +// GetRoleOk returns a tuple with the Role field value +// and a boolean to check if the value has been set. +func (o *Member) GetRoleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Role, true +} + +// SetRole sets field value +func (o *Member) SetRole(v string) { + o.Role = v +} + +// GetEmail returns the Email field value +func (o *Member) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *Member) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *Member) SetEmail(v string) { + o.Email = v +} + +// GetPendingInvite returns the PendingInvite field value +func (o *Member) GetPendingInvite() bool { + if o == nil { + var ret bool + return ret + } + + return o.PendingInvite +} + +// GetPendingInviteOk returns a tuple with the PendingInvite field value +// and a boolean to check if the value has been set. +func (o *Member) GetPendingInviteOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.PendingInvite, true +} + +// SetPendingInvite sets field value +func (o *Member) SetPendingInvite(v bool) { + o.PendingInvite = v +} + +// GetVerified returns the Verified field value +func (o *Member) GetVerified() bool { + if o == nil { + var ret bool + return ret + } + + return o.Verified +} + +// GetVerifiedOk returns a tuple with the Verified field value +// and a boolean to check if the value has been set. +func (o *Member) GetVerifiedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Verified, true +} + +// SetVerified sets field value +func (o *Member) SetVerified(v bool) { + o.Verified = v +} + +// GetPendingEmail returns the PendingEmail field value if set, zero value otherwise. +func (o *Member) GetPendingEmail() string { + if o == nil || o.PendingEmail == nil { + var ret string + return ret + } + return *o.PendingEmail +} + +// GetPendingEmailOk returns a tuple with the PendingEmail field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetPendingEmailOk() (*string, bool) { + if o == nil || o.PendingEmail == nil { + return nil, false + } + return o.PendingEmail, true +} + +// HasPendingEmail returns a boolean if a field has been set. +func (o *Member) HasPendingEmail() bool { + if o != nil && o.PendingEmail != nil { + return true + } + + return false +} + +// SetPendingEmail gets a reference to the given string and assigns it to the PendingEmail field. +func (o *Member) SetPendingEmail(v string) { + o.PendingEmail = &v +} + +// GetCustomRoles returns the CustomRoles field value +func (o *Member) GetCustomRoles() []string { + if o == nil { + var ret []string + return ret + } + + return o.CustomRoles +} + +// GetCustomRolesOk returns a tuple with the CustomRoles field value +// and a boolean to check if the value has been set. +func (o *Member) GetCustomRolesOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.CustomRoles, true +} + +// SetCustomRoles sets field value +func (o *Member) SetCustomRoles(v []string) { + o.CustomRoles = v +} + +// GetMfa returns the Mfa field value +func (o *Member) GetMfa() string { + if o == nil { + var ret string + return ret + } + + return o.Mfa +} + +// GetMfaOk returns a tuple with the Mfa field value +// and a boolean to check if the value has been set. +func (o *Member) GetMfaOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Mfa, true +} + +// SetMfa sets field value +func (o *Member) SetMfa(v string) { + o.Mfa = v +} + +// GetExcludedDashboards returns the ExcludedDashboards field value if set, zero value otherwise. +func (o *Member) GetExcludedDashboards() []string { + if o == nil || o.ExcludedDashboards == nil { + var ret []string + return ret + } + return o.ExcludedDashboards +} + +// GetExcludedDashboardsOk returns a tuple with the ExcludedDashboards field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetExcludedDashboardsOk() ([]string, bool) { + if o == nil || o.ExcludedDashboards == nil { + return nil, false + } + return o.ExcludedDashboards, true +} + +// HasExcludedDashboards returns a boolean if a field has been set. +func (o *Member) HasExcludedDashboards() bool { + if o != nil && o.ExcludedDashboards != nil { + return true + } + + return false +} + +// SetExcludedDashboards gets a reference to the given []string and assigns it to the ExcludedDashboards field. +func (o *Member) SetExcludedDashboards(v []string) { + o.ExcludedDashboards = v +} + +// GetLastSeen returns the LastSeen field value +func (o *Member) GetLastSeen() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastSeen +} + +// GetLastSeenOk returns a tuple with the LastSeen field value +// and a boolean to check if the value has been set. +func (o *Member) GetLastSeenOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastSeen, true +} + +// SetLastSeen sets field value +func (o *Member) SetLastSeen(v int64) { + o.LastSeen = v +} + +// GetLastSeenMetadata returns the LastSeenMetadata field value if set, zero value otherwise. +func (o *Member) GetLastSeenMetadata() LastSeenMetadata { + if o == nil || o.LastSeenMetadata == nil { + var ret LastSeenMetadata + return ret + } + return *o.LastSeenMetadata +} + +// GetLastSeenMetadataOk returns a tuple with the LastSeenMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetLastSeenMetadataOk() (*LastSeenMetadata, bool) { + if o == nil || o.LastSeenMetadata == nil { + return nil, false + } + return o.LastSeenMetadata, true +} + +// HasLastSeenMetadata returns a boolean if a field has been set. +func (o *Member) HasLastSeenMetadata() bool { + if o != nil && o.LastSeenMetadata != nil { + return true + } + + return false +} + +// SetLastSeenMetadata gets a reference to the given LastSeenMetadata and assigns it to the LastSeenMetadata field. +func (o *Member) SetLastSeenMetadata(v LastSeenMetadata) { + o.LastSeenMetadata = &v +} + +// GetIntegrationMetadata returns the IntegrationMetadata field value if set, zero value otherwise. +func (o *Member) GetIntegrationMetadata() IntegrationMetadata { + if o == nil || o.IntegrationMetadata == nil { + var ret IntegrationMetadata + return ret + } + return *o.IntegrationMetadata +} + +// GetIntegrationMetadataOk returns a tuple with the IntegrationMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetIntegrationMetadataOk() (*IntegrationMetadata, bool) { + if o == nil || o.IntegrationMetadata == nil { + return nil, false + } + return o.IntegrationMetadata, true +} + +// HasIntegrationMetadata returns a boolean if a field has been set. +func (o *Member) HasIntegrationMetadata() bool { + if o != nil && o.IntegrationMetadata != nil { + return true + } + + return false +} + +// SetIntegrationMetadata gets a reference to the given IntegrationMetadata and assigns it to the IntegrationMetadata field. +func (o *Member) SetIntegrationMetadata(v IntegrationMetadata) { + o.IntegrationMetadata = &v +} + +// GetTeams returns the Teams field value if set, zero value otherwise. +func (o *Member) GetTeams() []MemberTeamSummaryRep { + if o == nil || o.Teams == nil { + var ret []MemberTeamSummaryRep + return ret + } + return o.Teams +} + +// GetTeamsOk returns a tuple with the Teams field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetTeamsOk() ([]MemberTeamSummaryRep, bool) { + if o == nil || o.Teams == nil { + return nil, false + } + return o.Teams, true +} + +// HasTeams returns a boolean if a field has been set. +func (o *Member) HasTeams() bool { + if o != nil && o.Teams != nil { + return true + } + + return false +} + +// SetTeams gets a reference to the given []MemberTeamSummaryRep and assigns it to the Teams field. +func (o *Member) SetTeams(v []MemberTeamSummaryRep) { + o.Teams = v +} + +// GetPermissionGrants returns the PermissionGrants field value if set, zero value otherwise. +func (o *Member) GetPermissionGrants() []MemberPermissionGrantSummaryRep { + if o == nil || o.PermissionGrants == nil { + var ret []MemberPermissionGrantSummaryRep + return ret + } + return o.PermissionGrants +} + +// GetPermissionGrantsOk returns a tuple with the PermissionGrants field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetPermissionGrantsOk() ([]MemberPermissionGrantSummaryRep, bool) { + if o == nil || o.PermissionGrants == nil { + return nil, false + } + return o.PermissionGrants, true +} + +// HasPermissionGrants returns a boolean if a field has been set. +func (o *Member) HasPermissionGrants() bool { + if o != nil && o.PermissionGrants != nil { + return true + } + + return false +} + +// SetPermissionGrants gets a reference to the given []MemberPermissionGrantSummaryRep and assigns it to the PermissionGrants field. +func (o *Member) SetPermissionGrants(v []MemberPermissionGrantSummaryRep) { + o.PermissionGrants = v +} + +// GetCreationDate returns the CreationDate field value +func (o *Member) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *Member) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *Member) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetOauthProviders returns the OauthProviders field value if set, zero value otherwise. +func (o *Member) GetOauthProviders() []string { + if o == nil || o.OauthProviders == nil { + var ret []string + return ret + } + return o.OauthProviders +} + +// GetOauthProvidersOk returns a tuple with the OauthProviders field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetOauthProvidersOk() ([]string, bool) { + if o == nil || o.OauthProviders == nil { + return nil, false + } + return o.OauthProviders, true +} + +// HasOauthProviders returns a boolean if a field has been set. +func (o *Member) HasOauthProviders() bool { + if o != nil && o.OauthProviders != nil { + return true + } + + return false +} + +// SetOauthProviders gets a reference to the given []string and assigns it to the OauthProviders field. +func (o *Member) SetOauthProviders(v []string) { + o.OauthProviders = v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *Member) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *Member) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *Member) SetVersion(v int32) { + o.Version = &v +} + +// GetRoleAttributes returns the RoleAttributes field value if set, zero value otherwise. +func (o *Member) GetRoleAttributes() map[string][]string { + if o == nil || o.RoleAttributes == nil { + var ret map[string][]string + return ret + } + return *o.RoleAttributes +} + +// GetRoleAttributesOk returns a tuple with the RoleAttributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Member) GetRoleAttributesOk() (*map[string][]string, bool) { + if o == nil || o.RoleAttributes == nil { + return nil, false + } + return o.RoleAttributes, true +} + +// HasRoleAttributes returns a boolean if a field has been set. +func (o *Member) HasRoleAttributes() bool { + if o != nil && o.RoleAttributes != nil { + return true + } + + return false +} + +// SetRoleAttributes gets a reference to the given map[string][]string and assigns it to the RoleAttributes field. +func (o *Member) SetRoleAttributes(v map[string][]string) { + o.RoleAttributes = &v +} + +func (o Member) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if true { + toSerialize["role"] = o.Role + } + if true { + toSerialize["email"] = o.Email + } + if true { + toSerialize["_pendingInvite"] = o.PendingInvite + } + if true { + toSerialize["_verified"] = o.Verified + } + if o.PendingEmail != nil { + toSerialize["_pendingEmail"] = o.PendingEmail + } + if true { + toSerialize["customRoles"] = o.CustomRoles + } + if true { + toSerialize["mfa"] = o.Mfa + } + if o.ExcludedDashboards != nil { + toSerialize["excludedDashboards"] = o.ExcludedDashboards + } + if true { + toSerialize["_lastSeen"] = o.LastSeen + } + if o.LastSeenMetadata != nil { + toSerialize["_lastSeenMetadata"] = o.LastSeenMetadata + } + if o.IntegrationMetadata != nil { + toSerialize["_integrationMetadata"] = o.IntegrationMetadata + } + if o.Teams != nil { + toSerialize["teams"] = o.Teams + } + if o.PermissionGrants != nil { + toSerialize["permissionGrants"] = o.PermissionGrants + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if o.OauthProviders != nil { + toSerialize["oauthProviders"] = o.OauthProviders + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + if o.RoleAttributes != nil { + toSerialize["roleAttributes"] = o.RoleAttributes + } + return json.Marshal(toSerialize) +} + +type NullableMember struct { + value *Member + isSet bool +} + +func (v NullableMember) Get() *Member { + return v.value +} + +func (v *NullableMember) Set(val *Member) { + v.value = val + v.isSet = true +} + +func (v NullableMember) IsSet() bool { + return v.isSet +} + +func (v *NullableMember) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMember(val *Member) *NullableMember { + return &NullableMember{value: val, isSet: true} +} + +func (v NullableMember) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMember) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_data_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_data_rep.go new file mode 100644 index 00000000..e08f3288 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_data_rep.go @@ -0,0 +1,264 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberDataRep struct for MemberDataRep +type MemberDataRep struct { + Links *map[string]Link `json:"_links,omitempty"` + // The member ID + Id *string `json:"_id,omitempty"` + // The member email + Email *string `json:"email,omitempty"` + // The member first name + FirstName *string `json:"firstName,omitempty"` + // The member last name + LastName *string `json:"lastName,omitempty"` +} + +// NewMemberDataRep instantiates a new MemberDataRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberDataRep() *MemberDataRep { + this := MemberDataRep{} + return &this +} + +// NewMemberDataRepWithDefaults instantiates a new MemberDataRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberDataRepWithDefaults() *MemberDataRep { + this := MemberDataRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *MemberDataRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberDataRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *MemberDataRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *MemberDataRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *MemberDataRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberDataRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *MemberDataRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *MemberDataRep) SetId(v string) { + o.Id = &v +} + +// GetEmail returns the Email field value if set, zero value otherwise. +func (o *MemberDataRep) GetEmail() string { + if o == nil || o.Email == nil { + var ret string + return ret + } + return *o.Email +} + +// GetEmailOk returns a tuple with the Email field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberDataRep) GetEmailOk() (*string, bool) { + if o == nil || o.Email == nil { + return nil, false + } + return o.Email, true +} + +// HasEmail returns a boolean if a field has been set. +func (o *MemberDataRep) HasEmail() bool { + if o != nil && o.Email != nil { + return true + } + + return false +} + +// SetEmail gets a reference to the given string and assigns it to the Email field. +func (o *MemberDataRep) SetEmail(v string) { + o.Email = &v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *MemberDataRep) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberDataRep) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *MemberDataRep) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *MemberDataRep) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *MemberDataRep) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberDataRep) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *MemberDataRep) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *MemberDataRep) SetLastName(v string) { + o.LastName = &v +} + +func (o MemberDataRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Email != nil { + toSerialize["email"] = o.Email + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + return json.Marshal(toSerialize) +} + +type NullableMemberDataRep struct { + value *MemberDataRep + isSet bool +} + +func (v NullableMemberDataRep) Get() *MemberDataRep { + return v.value +} + +func (v *NullableMemberDataRep) Set(val *MemberDataRep) { + v.value = val + v.isSet = true +} + +func (v NullableMemberDataRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberDataRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberDataRep(val *MemberDataRep) *NullableMemberDataRep { + return &NullableMemberDataRep{value: val, isSet: true} +} + +func (v NullableMemberDataRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberDataRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_import_item.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_import_item.go new file mode 100644 index 00000000..bd217d0c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_import_item.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberImportItem struct for MemberImportItem +type MemberImportItem struct { + // An error message, including CSV line number, if the status is error + Message *string `json:"message,omitempty"` + // Whether this member can be successfully imported (success) or not (error). Even if the status is success, members are only added to a team on a 201 response. + Status string `json:"status"` + // The email address for the member requested to be added to this team. May be blank or an error, such as 'invalid email format', if the email address cannot be found or parsed. + Value string `json:"value"` +} + +// NewMemberImportItem instantiates a new MemberImportItem object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberImportItem(status string, value string) *MemberImportItem { + this := MemberImportItem{} + this.Status = status + this.Value = value + return &this +} + +// NewMemberImportItemWithDefaults instantiates a new MemberImportItem object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberImportItemWithDefaults() *MemberImportItem { + this := MemberImportItem{} + return &this +} + +// GetMessage returns the Message field value if set, zero value otherwise. +func (o *MemberImportItem) GetMessage() string { + if o == nil || o.Message == nil { + var ret string + return ret + } + return *o.Message +} + +// GetMessageOk returns a tuple with the Message field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberImportItem) GetMessageOk() (*string, bool) { + if o == nil || o.Message == nil { + return nil, false + } + return o.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (o *MemberImportItem) HasMessage() bool { + if o != nil && o.Message != nil { + return true + } + + return false +} + +// SetMessage gets a reference to the given string and assigns it to the Message field. +func (o *MemberImportItem) SetMessage(v string) { + o.Message = &v +} + +// GetStatus returns the Status field value +func (o *MemberImportItem) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *MemberImportItem) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *MemberImportItem) SetStatus(v string) { + o.Status = v +} + +// GetValue returns the Value field value +func (o *MemberImportItem) GetValue() string { + if o == nil { + var ret string + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *MemberImportItem) GetValueOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *MemberImportItem) SetValue(v string) { + o.Value = v +} + +func (o MemberImportItem) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Message != nil { + toSerialize["message"] = o.Message + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableMemberImportItem struct { + value *MemberImportItem + isSet bool +} + +func (v NullableMemberImportItem) Get() *MemberImportItem { + return v.value +} + +func (v *NullableMemberImportItem) Set(val *MemberImportItem) { + v.value = val + v.isSet = true +} + +func (v NullableMemberImportItem) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberImportItem) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberImportItem(val *MemberImportItem) *NullableMemberImportItem { + return &NullableMemberImportItem{value: val, isSet: true} +} + +func (v NullableMemberImportItem) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberImportItem) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_permission_grant_summary_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_permission_grant_summary_rep.go new file mode 100644 index 00000000..281d47b5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_permission_grant_summary_rep.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberPermissionGrantSummaryRep struct for MemberPermissionGrantSummaryRep +type MemberPermissionGrantSummaryRep struct { + // The name of the group of related actions to allow. A permission grant may have either an actionSet or a list of actions but not both at the same time. + ActionSet *string `json:"actionSet,omitempty"` + // A list of actions to allow. A permission grant may have either an actionSet or a list of actions but not both at the same time. + Actions []string `json:"actions,omitempty"` + // The resource for which the actions are allowed + Resource string `json:"resource"` +} + +// NewMemberPermissionGrantSummaryRep instantiates a new MemberPermissionGrantSummaryRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberPermissionGrantSummaryRep(resource string) *MemberPermissionGrantSummaryRep { + this := MemberPermissionGrantSummaryRep{} + this.Resource = resource + return &this +} + +// NewMemberPermissionGrantSummaryRepWithDefaults instantiates a new MemberPermissionGrantSummaryRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberPermissionGrantSummaryRepWithDefaults() *MemberPermissionGrantSummaryRep { + this := MemberPermissionGrantSummaryRep{} + return &this +} + +// GetActionSet returns the ActionSet field value if set, zero value otherwise. +func (o *MemberPermissionGrantSummaryRep) GetActionSet() string { + if o == nil || o.ActionSet == nil { + var ret string + return ret + } + return *o.ActionSet +} + +// GetActionSetOk returns a tuple with the ActionSet field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberPermissionGrantSummaryRep) GetActionSetOk() (*string, bool) { + if o == nil || o.ActionSet == nil { + return nil, false + } + return o.ActionSet, true +} + +// HasActionSet returns a boolean if a field has been set. +func (o *MemberPermissionGrantSummaryRep) HasActionSet() bool { + if o != nil && o.ActionSet != nil { + return true + } + + return false +} + +// SetActionSet gets a reference to the given string and assigns it to the ActionSet field. +func (o *MemberPermissionGrantSummaryRep) SetActionSet(v string) { + o.ActionSet = &v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *MemberPermissionGrantSummaryRep) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberPermissionGrantSummaryRep) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *MemberPermissionGrantSummaryRep) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *MemberPermissionGrantSummaryRep) SetActions(v []string) { + o.Actions = v +} + +// GetResource returns the Resource field value +func (o *MemberPermissionGrantSummaryRep) GetResource() string { + if o == nil { + var ret string + return ret + } + + return o.Resource +} + +// GetResourceOk returns a tuple with the Resource field value +// and a boolean to check if the value has been set. +func (o *MemberPermissionGrantSummaryRep) GetResourceOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Resource, true +} + +// SetResource sets field value +func (o *MemberPermissionGrantSummaryRep) SetResource(v string) { + o.Resource = v +} + +func (o MemberPermissionGrantSummaryRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ActionSet != nil { + toSerialize["actionSet"] = o.ActionSet + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if true { + toSerialize["resource"] = o.Resource + } + return json.Marshal(toSerialize) +} + +type NullableMemberPermissionGrantSummaryRep struct { + value *MemberPermissionGrantSummaryRep + isSet bool +} + +func (v NullableMemberPermissionGrantSummaryRep) Get() *MemberPermissionGrantSummaryRep { + return v.value +} + +func (v *NullableMemberPermissionGrantSummaryRep) Set(val *MemberPermissionGrantSummaryRep) { + v.value = val + v.isSet = true +} + +func (v NullableMemberPermissionGrantSummaryRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberPermissionGrantSummaryRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberPermissionGrantSummaryRep(val *MemberPermissionGrantSummaryRep) *NullableMemberPermissionGrantSummaryRep { + return &NullableMemberPermissionGrantSummaryRep{value: val, isSet: true} +} + +func (v NullableMemberPermissionGrantSummaryRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberPermissionGrantSummaryRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_summary.go new file mode 100644 index 00000000..26fa567d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_summary.go @@ -0,0 +1,274 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberSummary struct for MemberSummary +type MemberSummary struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The member's ID + Id string `json:"_id"` + // The member's first name + FirstName *string `json:"firstName,omitempty"` + // The member's last name + LastName *string `json:"lastName,omitempty"` + // The member's built-in role. If the member has no custom roles, this role will be in effect. + Role string `json:"role"` + // The member's email address + Email string `json:"email"` +} + +// NewMemberSummary instantiates a new MemberSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberSummary(links map[string]Link, id string, role string, email string) *MemberSummary { + this := MemberSummary{} + this.Links = links + this.Id = id + this.Role = role + this.Email = email + return &this +} + +// NewMemberSummaryWithDefaults instantiates a new MemberSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberSummaryWithDefaults() *MemberSummary { + this := MemberSummary{} + return &this +} + +// GetLinks returns the Links field value +func (o *MemberSummary) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MemberSummary) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *MemberSummary) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MemberSummary) SetId(v string) { + o.Id = v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *MemberSummary) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *MemberSummary) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *MemberSummary) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *MemberSummary) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *MemberSummary) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *MemberSummary) SetLastName(v string) { + o.LastName = &v +} + +// GetRole returns the Role field value +func (o *MemberSummary) GetRole() string { + if o == nil { + var ret string + return ret + } + + return o.Role +} + +// GetRoleOk returns a tuple with the Role field value +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetRoleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Role, true +} + +// SetRole sets field value +func (o *MemberSummary) SetRole(v string) { + o.Role = v +} + +// GetEmail returns the Email field value +func (o *MemberSummary) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *MemberSummary) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *MemberSummary) SetEmail(v string) { + o.Email = v +} + +func (o MemberSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if true { + toSerialize["role"] = o.Role + } + if true { + toSerialize["email"] = o.Email + } + return json.Marshal(toSerialize) +} + +type NullableMemberSummary struct { + value *MemberSummary + isSet bool +} + +func (v NullableMemberSummary) Get() *MemberSummary { + return v.value +} + +func (v *NullableMemberSummary) Set(val *MemberSummary) { + v.value = val + v.isSet = true +} + +func (v NullableMemberSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberSummary(val *MemberSummary) *NullableMemberSummary { + return &NullableMemberSummary{value: val, isSet: true} +} + +func (v NullableMemberSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_team_summary_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_team_summary_rep.go new file mode 100644 index 00000000..87e9e3e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_team_summary_rep.go @@ -0,0 +1,206 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberTeamSummaryRep struct for MemberTeamSummaryRep +type MemberTeamSummaryRep struct { + // A list of keys of the custom roles this team has access to + CustomRoleKeys []string `json:"customRoleKeys"` + // The team key + Key string `json:"key"` + Links *map[string]Link `json:"_links,omitempty"` + // The team name + Name string `json:"name"` +} + +// NewMemberTeamSummaryRep instantiates a new MemberTeamSummaryRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberTeamSummaryRep(customRoleKeys []string, key string, name string) *MemberTeamSummaryRep { + this := MemberTeamSummaryRep{} + this.CustomRoleKeys = customRoleKeys + this.Key = key + this.Name = name + return &this +} + +// NewMemberTeamSummaryRepWithDefaults instantiates a new MemberTeamSummaryRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberTeamSummaryRepWithDefaults() *MemberTeamSummaryRep { + this := MemberTeamSummaryRep{} + return &this +} + +// GetCustomRoleKeys returns the CustomRoleKeys field value +func (o *MemberTeamSummaryRep) GetCustomRoleKeys() []string { + if o == nil { + var ret []string + return ret + } + + return o.CustomRoleKeys +} + +// GetCustomRoleKeysOk returns a tuple with the CustomRoleKeys field value +// and a boolean to check if the value has been set. +func (o *MemberTeamSummaryRep) GetCustomRoleKeysOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.CustomRoleKeys, true +} + +// SetCustomRoleKeys sets field value +func (o *MemberTeamSummaryRep) SetCustomRoleKeys(v []string) { + o.CustomRoleKeys = v +} + +// GetKey returns the Key field value +func (o *MemberTeamSummaryRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MemberTeamSummaryRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MemberTeamSummaryRep) SetKey(v string) { + o.Key = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *MemberTeamSummaryRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MemberTeamSummaryRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *MemberTeamSummaryRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *MemberTeamSummaryRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value +func (o *MemberTeamSummaryRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MemberTeamSummaryRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MemberTeamSummaryRep) SetName(v string) { + o.Name = v +} + +func (o MemberTeamSummaryRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["customRoleKeys"] = o.CustomRoleKeys + } + if true { + toSerialize["key"] = o.Key + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableMemberTeamSummaryRep struct { + value *MemberTeamSummaryRep + isSet bool +} + +func (v NullableMemberTeamSummaryRep) Get() *MemberTeamSummaryRep { + return v.value +} + +func (v *NullableMemberTeamSummaryRep) Set(val *MemberTeamSummaryRep) { + v.value = val + v.isSet = true +} + +func (v NullableMemberTeamSummaryRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberTeamSummaryRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberTeamSummaryRep(val *MemberTeamSummaryRep) *NullableMemberTeamSummaryRep { + return &NullableMemberTeamSummaryRep{value: val, isSet: true} +} + +func (v NullableMemberTeamSummaryRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberTeamSummaryRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_member_teams_post_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_teams_post_input.go new file mode 100644 index 00000000..2b7123b1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_member_teams_post_input.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MemberTeamsPostInput struct for MemberTeamsPostInput +type MemberTeamsPostInput struct { + // List of team keys + TeamKeys []string `json:"teamKeys"` +} + +// NewMemberTeamsPostInput instantiates a new MemberTeamsPostInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMemberTeamsPostInput(teamKeys []string) *MemberTeamsPostInput { + this := MemberTeamsPostInput{} + this.TeamKeys = teamKeys + return &this +} + +// NewMemberTeamsPostInputWithDefaults instantiates a new MemberTeamsPostInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMemberTeamsPostInputWithDefaults() *MemberTeamsPostInput { + this := MemberTeamsPostInput{} + return &this +} + +// GetTeamKeys returns the TeamKeys field value +func (o *MemberTeamsPostInput) GetTeamKeys() []string { + if o == nil { + var ret []string + return ret + } + + return o.TeamKeys +} + +// GetTeamKeysOk returns a tuple with the TeamKeys field value +// and a boolean to check if the value has been set. +func (o *MemberTeamsPostInput) GetTeamKeysOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.TeamKeys, true +} + +// SetTeamKeys sets field value +func (o *MemberTeamsPostInput) SetTeamKeys(v []string) { + o.TeamKeys = v +} + +func (o MemberTeamsPostInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["teamKeys"] = o.TeamKeys + } + return json.Marshal(toSerialize) +} + +type NullableMemberTeamsPostInput struct { + value *MemberTeamsPostInput + isSet bool +} + +func (v NullableMemberTeamsPostInput) Get() *MemberTeamsPostInput { + return v.value +} + +func (v *NullableMemberTeamsPostInput) Set(val *MemberTeamsPostInput) { + v.value = val + v.isSet = true +} + +func (v NullableMemberTeamsPostInput) IsSet() bool { + return v.isSet +} + +func (v *NullableMemberTeamsPostInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMemberTeamsPostInput(val *MemberTeamsPostInput) *NullableMemberTeamsPostInput { + return &NullableMemberTeamsPostInput{value: val, isSet: true} +} + +func (v NullableMemberTeamsPostInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMemberTeamsPostInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_members.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_members.go new file mode 100644 index 00000000..aec13699 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_members.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Members struct for Members +type Members struct { + // An array of members + Items []Member `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The number of members returned + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewMembers instantiates a new Members object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMembers(items []Member, links map[string]Link) *Members { + this := Members{} + this.Items = items + this.Links = links + return &this +} + +// NewMembersWithDefaults instantiates a new Members object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMembersWithDefaults() *Members { + this := Members{} + return &this +} + +// GetItems returns the Items field value +func (o *Members) GetItems() []Member { + if o == nil { + var ret []Member + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Members) GetItemsOk() ([]Member, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Members) SetItems(v []Member) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *Members) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Members) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Members) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Members) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Members) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Members) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Members) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o Members) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableMembers struct { + value *Members + isSet bool +} + +func (v NullableMembers) Get() *Members { + return v.value +} + +func (v *NullableMembers) Set(val *Members) { + v.value = val + v.isSet = true +} + +func (v NullableMembers) IsSet() bool { + return v.isSet +} + +func (v *NullableMembers) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMembers(val *Members) *NullableMembers { + return &NullableMembers{value: val, isSet: true} +} + +func (v NullableMembers) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMembers) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_members_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_members_patch_input.go new file mode 100644 index 00000000..e9138433 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_members_patch_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MembersPatchInput struct for MembersPatchInput +type MembersPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewMembersPatchInput instantiates a new MembersPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMembersPatchInput(instructions []map[string]interface{}) *MembersPatchInput { + this := MembersPatchInput{} + this.Instructions = instructions + return &this +} + +// NewMembersPatchInputWithDefaults instantiates a new MembersPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMembersPatchInputWithDefaults() *MembersPatchInput { + this := MembersPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *MembersPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MembersPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *MembersPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *MembersPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *MembersPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *MembersPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *MembersPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o MembersPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableMembersPatchInput struct { + value *MembersPatchInput + isSet bool +} + +func (v NullableMembersPatchInput) Get() *MembersPatchInput { + return v.value +} + +func (v *NullableMembersPatchInput) Set(val *MembersPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableMembersPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableMembersPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMembersPatchInput(val *MembersPatchInput) *NullableMembersPatchInput { + return &NullableMembersPatchInput{value: val, isSet: true} +} + +func (v NullableMembersPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMembersPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_message.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_message.go new file mode 100644 index 00000000..27cc9c1e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_message.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Message struct for Message +type Message struct { + Content string `json:"content"` + Role string `json:"role"` +} + +// NewMessage instantiates a new Message object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMessage(content string, role string) *Message { + this := Message{} + this.Content = content + this.Role = role + return &this +} + +// NewMessageWithDefaults instantiates a new Message object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMessageWithDefaults() *Message { + this := Message{} + return &this +} + +// GetContent returns the Content field value +func (o *Message) GetContent() string { + if o == nil { + var ret string + return ret + } + + return o.Content +} + +// GetContentOk returns a tuple with the Content field value +// and a boolean to check if the value has been set. +func (o *Message) GetContentOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Content, true +} + +// SetContent sets field value +func (o *Message) SetContent(v string) { + o.Content = v +} + +// GetRole returns the Role field value +func (o *Message) GetRole() string { + if o == nil { + var ret string + return ret + } + + return o.Role +} + +// GetRoleOk returns a tuple with the Role field value +// and a boolean to check if the value has been set. +func (o *Message) GetRoleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Role, true +} + +// SetRole sets field value +func (o *Message) SetRole(v string) { + o.Role = v +} + +func (o Message) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["content"] = o.Content + } + if true { + toSerialize["role"] = o.Role + } + return json.Marshal(toSerialize) +} + +type NullableMessage struct { + value *Message + isSet bool +} + +func (v NullableMessage) Get() *Message { + return v.value +} + +func (v *NullableMessage) Set(val *Message) { + v.value = val + v.isSet = true +} + +func (v NullableMessage) IsSet() bool { + return v.isSet +} + +func (v *NullableMessage) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMessage(val *Message) *NullableMessage { + return &NullableMessage{value: val, isSet: true} +} + +func (v NullableMessage) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMessage) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_method_not_allowed_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_method_not_allowed_error_rep.go new file mode 100644 index 00000000..869e0539 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_method_not_allowed_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MethodNotAllowedErrorRep struct for MethodNotAllowedErrorRep +type MethodNotAllowedErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewMethodNotAllowedErrorRep instantiates a new MethodNotAllowedErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMethodNotAllowedErrorRep(code string, message string) *MethodNotAllowedErrorRep { + this := MethodNotAllowedErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewMethodNotAllowedErrorRepWithDefaults instantiates a new MethodNotAllowedErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMethodNotAllowedErrorRepWithDefaults() *MethodNotAllowedErrorRep { + this := MethodNotAllowedErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *MethodNotAllowedErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *MethodNotAllowedErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *MethodNotAllowedErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *MethodNotAllowedErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *MethodNotAllowedErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *MethodNotAllowedErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o MethodNotAllowedErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableMethodNotAllowedErrorRep struct { + value *MethodNotAllowedErrorRep + isSet bool +} + +func (v NullableMethodNotAllowedErrorRep) Get() *MethodNotAllowedErrorRep { + return v.value +} + +func (v *NullableMethodNotAllowedErrorRep) Set(val *MethodNotAllowedErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableMethodNotAllowedErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMethodNotAllowedErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMethodNotAllowedErrorRep(val *MethodNotAllowedErrorRep) *NullableMethodNotAllowedErrorRep { + return &NullableMethodNotAllowedErrorRep{value: val, isSet: true} +} + +func (v NullableMethodNotAllowedErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMethodNotAllowedErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_by_variation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_by_variation.go new file mode 100644 index 00000000..6c3a4736 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_by_variation.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricByVariation struct for MetricByVariation +type MetricByVariation struct { + VariationKey *string `json:"variationKey,omitempty"` + Metrics *Metrics `json:"metrics,omitempty"` +} + +// NewMetricByVariation instantiates a new MetricByVariation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricByVariation() *MetricByVariation { + this := MetricByVariation{} + return &this +} + +// NewMetricByVariationWithDefaults instantiates a new MetricByVariation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricByVariationWithDefaults() *MetricByVariation { + this := MetricByVariation{} + return &this +} + +// GetVariationKey returns the VariationKey field value if set, zero value otherwise. +func (o *MetricByVariation) GetVariationKey() string { + if o == nil || o.VariationKey == nil { + var ret string + return ret + } + return *o.VariationKey +} + +// GetVariationKeyOk returns a tuple with the VariationKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricByVariation) GetVariationKeyOk() (*string, bool) { + if o == nil || o.VariationKey == nil { + return nil, false + } + return o.VariationKey, true +} + +// HasVariationKey returns a boolean if a field has been set. +func (o *MetricByVariation) HasVariationKey() bool { + if o != nil && o.VariationKey != nil { + return true + } + + return false +} + +// SetVariationKey gets a reference to the given string and assigns it to the VariationKey field. +func (o *MetricByVariation) SetVariationKey(v string) { + o.VariationKey = &v +} + +// GetMetrics returns the Metrics field value if set, zero value otherwise. +func (o *MetricByVariation) GetMetrics() Metrics { + if o == nil || o.Metrics == nil { + var ret Metrics + return ret + } + return *o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricByVariation) GetMetricsOk() (*Metrics, bool) { + if o == nil || o.Metrics == nil { + return nil, false + } + return o.Metrics, true +} + +// HasMetrics returns a boolean if a field has been set. +func (o *MetricByVariation) HasMetrics() bool { + if o != nil && o.Metrics != nil { + return true + } + + return false +} + +// SetMetrics gets a reference to the given Metrics and assigns it to the Metrics field. +func (o *MetricByVariation) SetMetrics(v Metrics) { + o.Metrics = &v +} + +func (o MetricByVariation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.VariationKey != nil { + toSerialize["variationKey"] = o.VariationKey + } + if o.Metrics != nil { + toSerialize["metrics"] = o.Metrics + } + return json.Marshal(toSerialize) +} + +type NullableMetricByVariation struct { + value *MetricByVariation + isSet bool +} + +func (v NullableMetricByVariation) Get() *MetricByVariation { + return v.value +} + +func (v *NullableMetricByVariation) Set(val *MetricByVariation) { + v.value = val + v.isSet = true +} + +func (v NullableMetricByVariation) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricByVariation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricByVariation(val *MetricByVariation) *NullableMetricByVariation { + return &NullableMetricByVariation{value: val, isSet: true} +} + +func (v NullableMetricByVariation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricByVariation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_collection_rep.go new file mode 100644 index 00000000..15c716c4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_collection_rep.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricCollectionRep struct for MetricCollectionRep +type MetricCollectionRep struct { + // An array of metrics + Items []MetricListingRep `json:"items,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewMetricCollectionRep instantiates a new MetricCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricCollectionRep() *MetricCollectionRep { + this := MetricCollectionRep{} + return &this +} + +// NewMetricCollectionRepWithDefaults instantiates a new MetricCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricCollectionRepWithDefaults() *MetricCollectionRep { + this := MetricCollectionRep{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *MetricCollectionRep) GetItems() []MetricListingRep { + if o == nil || o.Items == nil { + var ret []MetricListingRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricCollectionRep) GetItemsOk() ([]MetricListingRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *MetricCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []MetricListingRep and assigns it to the Items field. +func (o *MetricCollectionRep) SetItems(v []MetricListingRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *MetricCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *MetricCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *MetricCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *MetricCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *MetricCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *MetricCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o MetricCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableMetricCollectionRep struct { + value *MetricCollectionRep + isSet bool +} + +func (v NullableMetricCollectionRep) Get() *MetricCollectionRep { + return v.value +} + +func (v *NullableMetricCollectionRep) Set(val *MetricCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricCollectionRep(val *MetricCollectionRep) *NullableMetricCollectionRep { + return &NullableMetricCollectionRep{value: val, isSet: true} +} + +func (v NullableMetricCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_event_default_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_event_default_rep.go new file mode 100644 index 00000000..9b5d151f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_event_default_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricEventDefaultRep struct for MetricEventDefaultRep +type MetricEventDefaultRep struct { + // Whether to disable defaulting missing unit events when calculating results. Defaults to false + Disabled *bool `json:"disabled,omitempty"` + // The default value applied to missing unit events. Set to 0 when disabled is false. No other values are currently supported. + Value *float32 `json:"value,omitempty"` +} + +// NewMetricEventDefaultRep instantiates a new MetricEventDefaultRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricEventDefaultRep() *MetricEventDefaultRep { + this := MetricEventDefaultRep{} + return &this +} + +// NewMetricEventDefaultRepWithDefaults instantiates a new MetricEventDefaultRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricEventDefaultRepWithDefaults() *MetricEventDefaultRep { + this := MetricEventDefaultRep{} + return &this +} + +// GetDisabled returns the Disabled field value if set, zero value otherwise. +func (o *MetricEventDefaultRep) GetDisabled() bool { + if o == nil || o.Disabled == nil { + var ret bool + return ret + } + return *o.Disabled +} + +// GetDisabledOk returns a tuple with the Disabled field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricEventDefaultRep) GetDisabledOk() (*bool, bool) { + if o == nil || o.Disabled == nil { + return nil, false + } + return o.Disabled, true +} + +// HasDisabled returns a boolean if a field has been set. +func (o *MetricEventDefaultRep) HasDisabled() bool { + if o != nil && o.Disabled != nil { + return true + } + + return false +} + +// SetDisabled gets a reference to the given bool and assigns it to the Disabled field. +func (o *MetricEventDefaultRep) SetDisabled(v bool) { + o.Disabled = &v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *MetricEventDefaultRep) GetValue() float32 { + if o == nil || o.Value == nil { + var ret float32 + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricEventDefaultRep) GetValueOk() (*float32, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *MetricEventDefaultRep) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given float32 and assigns it to the Value field. +func (o *MetricEventDefaultRep) SetValue(v float32) { + o.Value = &v +} + +func (o MetricEventDefaultRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Disabled != nil { + toSerialize["disabled"] = o.Disabled + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableMetricEventDefaultRep struct { + value *MetricEventDefaultRep + isSet bool +} + +func (v NullableMetricEventDefaultRep) Get() *MetricEventDefaultRep { + return v.value +} + +func (v *NullableMetricEventDefaultRep) Set(val *MetricEventDefaultRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricEventDefaultRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricEventDefaultRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricEventDefaultRep(val *MetricEventDefaultRep) *NullableMetricEventDefaultRep { + return &NullableMetricEventDefaultRep{value: val, isSet: true} +} + +func (v NullableMetricEventDefaultRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricEventDefaultRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_collection_rep.go new file mode 100644 index 00000000..7a729eee --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_collection_rep.go @@ -0,0 +1,183 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricGroupCollectionRep struct for MetricGroupCollectionRep +type MetricGroupCollectionRep struct { + // An array of metric groups + Items []MetricGroupRep `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewMetricGroupCollectionRep instantiates a new MetricGroupCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricGroupCollectionRep(items []MetricGroupRep) *MetricGroupCollectionRep { + this := MetricGroupCollectionRep{} + this.Items = items + return &this +} + +// NewMetricGroupCollectionRepWithDefaults instantiates a new MetricGroupCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricGroupCollectionRepWithDefaults() *MetricGroupCollectionRep { + this := MetricGroupCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *MetricGroupCollectionRep) GetItems() []MetricGroupRep { + if o == nil { + var ret []MetricGroupRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *MetricGroupCollectionRep) GetItemsOk() ([]MetricGroupRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *MetricGroupCollectionRep) SetItems(v []MetricGroupRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *MetricGroupCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *MetricGroupCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *MetricGroupCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *MetricGroupCollectionRep) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *MetricGroupCollectionRep) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *MetricGroupCollectionRep) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o MetricGroupCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableMetricGroupCollectionRep struct { + value *MetricGroupCollectionRep + isSet bool +} + +func (v NullableMetricGroupCollectionRep) Get() *MetricGroupCollectionRep { + return v.value +} + +func (v *NullableMetricGroupCollectionRep) Set(val *MetricGroupCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricGroupCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricGroupCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricGroupCollectionRep(val *MetricGroupCollectionRep) *NullableMetricGroupCollectionRep { + return &NullableMetricGroupCollectionRep{value: val, isSet: true} +} + +func (v NullableMetricGroupCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricGroupCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_post.go new file mode 100644 index 00000000..a8debe5d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_post.go @@ -0,0 +1,297 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricGroupPost struct for MetricGroupPost +type MetricGroupPost struct { + // A unique key to reference the metric group + Key string `json:"key"` + // A human-friendly name for the metric group + Name string `json:"name"` + // The type of the metric group + Kind string `json:"kind"` + // Description of the metric group + Description *string `json:"description,omitempty"` + // The ID of the member who maintains this metric group + MaintainerId string `json:"maintainerId"` + // Tags for the metric group + Tags []string `json:"tags"` + // An ordered list of the metrics in this metric group + Metrics []MetricInMetricGroupInput `json:"metrics"` +} + +// NewMetricGroupPost instantiates a new MetricGroupPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricGroupPost(key string, name string, kind string, maintainerId string, tags []string, metrics []MetricInMetricGroupInput) *MetricGroupPost { + this := MetricGroupPost{} + this.Key = key + this.Name = name + this.Kind = kind + this.MaintainerId = maintainerId + this.Tags = tags + this.Metrics = metrics + return &this +} + +// NewMetricGroupPostWithDefaults instantiates a new MetricGroupPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricGroupPostWithDefaults() *MetricGroupPost { + this := MetricGroupPost{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricGroupPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricGroupPost) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *MetricGroupPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricGroupPost) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricGroupPost) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricGroupPost) SetKind(v string) { + o.Kind = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *MetricGroupPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *MetricGroupPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *MetricGroupPost) SetDescription(v string) { + o.Description = &v +} + +// GetMaintainerId returns the MaintainerId field value +func (o *MetricGroupPost) GetMaintainerId() string { + if o == nil { + var ret string + return ret + } + + return o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetMaintainerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MaintainerId, true +} + +// SetMaintainerId sets field value +func (o *MetricGroupPost) SetMaintainerId(v string) { + o.MaintainerId = v +} + +// GetTags returns the Tags field value +func (o *MetricGroupPost) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *MetricGroupPost) SetTags(v []string) { + o.Tags = v +} + +// GetMetrics returns the Metrics field value +func (o *MetricGroupPost) GetMetrics() []MetricInMetricGroupInput { + if o == nil { + var ret []MetricInMetricGroupInput + return ret + } + + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value +// and a boolean to check if the value has been set. +func (o *MetricGroupPost) GetMetricsOk() ([]MetricInMetricGroupInput, bool) { + if o == nil { + return nil, false + } + return o.Metrics, true +} + +// SetMetrics sets field value +func (o *MetricGroupPost) SetMetrics(v []MetricInMetricGroupInput) { + o.Metrics = v +} + +func (o MetricGroupPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["maintainerId"] = o.MaintainerId + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["metrics"] = o.Metrics + } + return json.Marshal(toSerialize) +} + +type NullableMetricGroupPost struct { + value *MetricGroupPost + isSet bool +} + +func (v NullableMetricGroupPost) Get() *MetricGroupPost { + return v.value +} + +func (v *NullableMetricGroupPost) Set(val *MetricGroupPost) { + v.value = val + v.isSet = true +} + +func (v NullableMetricGroupPost) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricGroupPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricGroupPost(val *MetricGroupPost) *NullableMetricGroupPost { + return &NullableMetricGroupPost{value: val, isSet: true} +} + +func (v NullableMetricGroupPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricGroupPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_rep.go new file mode 100644 index 00000000..056ce0c5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_rep.go @@ -0,0 +1,553 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricGroupRep struct for MetricGroupRep +type MetricGroupRep struct { + // The ID of this metric group + Id string `json:"_id"` + // A unique key to reference the metric group + Key string `json:"key"` + // A human-friendly name for the metric group + Name string `json:"name"` + // The type of the metric group + Kind string `json:"kind"` + // Description of the metric group + Description *string `json:"description,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Access *Access `json:"_access,omitempty"` + // Tags for the metric group + Tags []string `json:"tags"` + CreationDate int64 `json:"_creationDate"` + LastModified int64 `json:"_lastModified"` + Maintainer MaintainerRep `json:"maintainer"` + // An ordered list of the metrics in this metric group + Metrics []MetricInGroupRep `json:"metrics"` + // The version of this metric group + Version int32 `json:"_version"` + Experiments []DependentExperimentRep `json:"experiments,omitempty"` + // The number of experiments using this metric group + ExperimentCount *int32 `json:"experimentCount,omitempty"` +} + +// NewMetricGroupRep instantiates a new MetricGroupRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricGroupRep(id string, key string, name string, kind string, links map[string]Link, tags []string, creationDate int64, lastModified int64, maintainer MaintainerRep, metrics []MetricInGroupRep, version int32) *MetricGroupRep { + this := MetricGroupRep{} + this.Id = id + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + this.Tags = tags + this.CreationDate = creationDate + this.LastModified = lastModified + this.Maintainer = maintainer + this.Metrics = metrics + this.Version = version + return &this +} + +// NewMetricGroupRepWithDefaults instantiates a new MetricGroupRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricGroupRepWithDefaults() *MetricGroupRep { + this := MetricGroupRep{} + return &this +} + +// GetId returns the Id field value +func (o *MetricGroupRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MetricGroupRep) SetId(v string) { + o.Id = v +} + +// GetKey returns the Key field value +func (o *MetricGroupRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricGroupRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *MetricGroupRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricGroupRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricGroupRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricGroupRep) SetKind(v string) { + o.Kind = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *MetricGroupRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *MetricGroupRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *MetricGroupRep) SetDescription(v string) { + o.Description = &v +} + +// GetLinks returns the Links field value +func (o *MetricGroupRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricGroupRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *MetricGroupRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *MetricGroupRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *MetricGroupRep) SetAccess(v Access) { + o.Access = &v +} + +// GetTags returns the Tags field value +func (o *MetricGroupRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *MetricGroupRep) SetTags(v []string) { + o.Tags = v +} + +// GetCreationDate returns the CreationDate field value +func (o *MetricGroupRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *MetricGroupRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value +func (o *MetricGroupRep) GetLastModified() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetLastModifiedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModified, true +} + +// SetLastModified sets field value +func (o *MetricGroupRep) SetLastModified(v int64) { + o.LastModified = v +} + +// GetMaintainer returns the Maintainer field value +func (o *MetricGroupRep) GetMaintainer() MaintainerRep { + if o == nil { + var ret MaintainerRep + return ret + } + + return o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetMaintainerOk() (*MaintainerRep, bool) { + if o == nil { + return nil, false + } + return &o.Maintainer, true +} + +// SetMaintainer sets field value +func (o *MetricGroupRep) SetMaintainer(v MaintainerRep) { + o.Maintainer = v +} + +// GetMetrics returns the Metrics field value +func (o *MetricGroupRep) GetMetrics() []MetricInGroupRep { + if o == nil { + var ret []MetricInGroupRep + return ret + } + + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetMetricsOk() ([]MetricInGroupRep, bool) { + if o == nil { + return nil, false + } + return o.Metrics, true +} + +// SetMetrics sets field value +func (o *MetricGroupRep) SetMetrics(v []MetricInGroupRep) { + o.Metrics = v +} + +// GetVersion returns the Version field value +func (o *MetricGroupRep) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *MetricGroupRep) SetVersion(v int32) { + o.Version = v +} + +// GetExperiments returns the Experiments field value if set, zero value otherwise. +func (o *MetricGroupRep) GetExperiments() []DependentExperimentRep { + if o == nil || o.Experiments == nil { + var ret []DependentExperimentRep + return ret + } + return o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetExperimentsOk() ([]DependentExperimentRep, bool) { + if o == nil || o.Experiments == nil { + return nil, false + } + return o.Experiments, true +} + +// HasExperiments returns a boolean if a field has been set. +func (o *MetricGroupRep) HasExperiments() bool { + if o != nil && o.Experiments != nil { + return true + } + + return false +} + +// SetExperiments gets a reference to the given []DependentExperimentRep and assigns it to the Experiments field. +func (o *MetricGroupRep) SetExperiments(v []DependentExperimentRep) { + o.Experiments = v +} + +// GetExperimentCount returns the ExperimentCount field value if set, zero value otherwise. +func (o *MetricGroupRep) GetExperimentCount() int32 { + if o == nil || o.ExperimentCount == nil { + var ret int32 + return ret + } + return *o.ExperimentCount +} + +// GetExperimentCountOk returns a tuple with the ExperimentCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricGroupRep) GetExperimentCountOk() (*int32, bool) { + if o == nil || o.ExperimentCount == nil { + return nil, false + } + return o.ExperimentCount, true +} + +// HasExperimentCount returns a boolean if a field has been set. +func (o *MetricGroupRep) HasExperimentCount() bool { + if o != nil && o.ExperimentCount != nil { + return true + } + + return false +} + +// SetExperimentCount gets a reference to the given int32 and assigns it to the ExperimentCount field. +func (o *MetricGroupRep) SetExperimentCount(v int32) { + o.ExperimentCount = &v +} + +func (o MetricGroupRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if true { + toSerialize["_lastModified"] = o.LastModified + } + if true { + toSerialize["maintainer"] = o.Maintainer + } + if true { + toSerialize["metrics"] = o.Metrics + } + if true { + toSerialize["_version"] = o.Version + } + if o.Experiments != nil { + toSerialize["experiments"] = o.Experiments + } + if o.ExperimentCount != nil { + toSerialize["experimentCount"] = o.ExperimentCount + } + return json.Marshal(toSerialize) +} + +type NullableMetricGroupRep struct { + value *MetricGroupRep + isSet bool +} + +func (v NullableMetricGroupRep) Get() *MetricGroupRep { + return v.value +} + +func (v *NullableMetricGroupRep) Set(val *MetricGroupRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricGroupRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricGroupRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricGroupRep(val *MetricGroupRep) *NullableMetricGroupRep { + return &NullableMetricGroupRep{value: val, isSet: true} +} + +func (v NullableMetricGroupRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricGroupRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_results_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_results_rep.go new file mode 100644 index 00000000..e974196b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_group_results_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricGroupResultsRep struct for MetricGroupResultsRep +type MetricGroupResultsRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An ordered list of the metrics in this metric group, and each of their results + Metrics []MetricInGroupResultsRep `json:"metrics"` +} + +// NewMetricGroupResultsRep instantiates a new MetricGroupResultsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricGroupResultsRep(links map[string]Link, metrics []MetricInGroupResultsRep) *MetricGroupResultsRep { + this := MetricGroupResultsRep{} + this.Links = links + this.Metrics = metrics + return &this +} + +// NewMetricGroupResultsRepWithDefaults instantiates a new MetricGroupResultsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricGroupResultsRepWithDefaults() *MetricGroupResultsRep { + this := MetricGroupResultsRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *MetricGroupResultsRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricGroupResultsRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricGroupResultsRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetMetrics returns the Metrics field value +func (o *MetricGroupResultsRep) GetMetrics() []MetricInGroupResultsRep { + if o == nil { + var ret []MetricInGroupResultsRep + return ret + } + + return o.Metrics +} + +// GetMetricsOk returns a tuple with the Metrics field value +// and a boolean to check if the value has been set. +func (o *MetricGroupResultsRep) GetMetricsOk() ([]MetricInGroupResultsRep, bool) { + if o == nil { + return nil, false + } + return o.Metrics, true +} + +// SetMetrics sets field value +func (o *MetricGroupResultsRep) SetMetrics(v []MetricInGroupResultsRep) { + o.Metrics = v +} + +func (o MetricGroupResultsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["metrics"] = o.Metrics + } + return json.Marshal(toSerialize) +} + +type NullableMetricGroupResultsRep struct { + value *MetricGroupResultsRep + isSet bool +} + +func (v NullableMetricGroupResultsRep) Get() *MetricGroupResultsRep { + return v.value +} + +func (v *NullableMetricGroupResultsRep) Set(val *MetricGroupResultsRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricGroupResultsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricGroupResultsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricGroupResultsRep(val *MetricGroupResultsRep) *NullableMetricGroupResultsRep { + return &NullableMetricGroupResultsRep{value: val, isSet: true} +} + +func (v NullableMetricGroupResultsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricGroupResultsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_rep.go new file mode 100644 index 00000000..c9c4061f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_rep.go @@ -0,0 +1,385 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricInGroupRep struct for MetricInGroupRep +type MetricInGroupRep struct { + // The metric key + Key string `json:"key"` + // The version ID of the metric + VersionId *string `json:"_versionId,omitempty"` + // The metric name + Name string `json:"name"` + // The kind of event the metric tracks + Kind string `json:"kind"` + // For custom metrics, whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). + IsNumeric *bool `json:"isNumeric,omitempty"` + // The type of unit aggregation to use for the metric + UnitAggregationType *string `json:"unitAggregationType,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // Name of the metric when used within the associated metric group. Can be different from the original name of the metric. Required if and only if the metric group is a funnel. + NameInGroup *string `json:"nameInGroup,omitempty"` + // The randomization units for the metric + RandomizationUnits []string `json:"randomizationUnits,omitempty"` +} + +// NewMetricInGroupRep instantiates a new MetricInGroupRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricInGroupRep(key string, name string, kind string, links map[string]Link) *MetricInGroupRep { + this := MetricInGroupRep{} + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + return &this +} + +// NewMetricInGroupRepWithDefaults instantiates a new MetricInGroupRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricInGroupRepWithDefaults() *MetricInGroupRep { + this := MetricInGroupRep{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricInGroupRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricInGroupRep) SetKey(v string) { + o.Key = v +} + +// GetVersionId returns the VersionId field value if set, zero value otherwise. +func (o *MetricInGroupRep) GetVersionId() string { + if o == nil || o.VersionId == nil { + var ret string + return ret + } + return *o.VersionId +} + +// GetVersionIdOk returns a tuple with the VersionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetVersionIdOk() (*string, bool) { + if o == nil || o.VersionId == nil { + return nil, false + } + return o.VersionId, true +} + +// HasVersionId returns a boolean if a field has been set. +func (o *MetricInGroupRep) HasVersionId() bool { + if o != nil && o.VersionId != nil { + return true + } + + return false +} + +// SetVersionId gets a reference to the given string and assigns it to the VersionId field. +func (o *MetricInGroupRep) SetVersionId(v string) { + o.VersionId = &v +} + +// GetName returns the Name field value +func (o *MetricInGroupRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricInGroupRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricInGroupRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricInGroupRep) SetKind(v string) { + o.Kind = v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *MetricInGroupRep) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *MetricInGroupRep) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *MetricInGroupRep) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetUnitAggregationType returns the UnitAggregationType field value if set, zero value otherwise. +func (o *MetricInGroupRep) GetUnitAggregationType() string { + if o == nil || o.UnitAggregationType == nil { + var ret string + return ret + } + return *o.UnitAggregationType +} + +// GetUnitAggregationTypeOk returns a tuple with the UnitAggregationType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetUnitAggregationTypeOk() (*string, bool) { + if o == nil || o.UnitAggregationType == nil { + return nil, false + } + return o.UnitAggregationType, true +} + +// HasUnitAggregationType returns a boolean if a field has been set. +func (o *MetricInGroupRep) HasUnitAggregationType() bool { + if o != nil && o.UnitAggregationType != nil { + return true + } + + return false +} + +// SetUnitAggregationType gets a reference to the given string and assigns it to the UnitAggregationType field. +func (o *MetricInGroupRep) SetUnitAggregationType(v string) { + o.UnitAggregationType = &v +} + +// GetLinks returns the Links field value +func (o *MetricInGroupRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricInGroupRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetNameInGroup returns the NameInGroup field value if set, zero value otherwise. +func (o *MetricInGroupRep) GetNameInGroup() string { + if o == nil || o.NameInGroup == nil { + var ret string + return ret + } + return *o.NameInGroup +} + +// GetNameInGroupOk returns a tuple with the NameInGroup field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetNameInGroupOk() (*string, bool) { + if o == nil || o.NameInGroup == nil { + return nil, false + } + return o.NameInGroup, true +} + +// HasNameInGroup returns a boolean if a field has been set. +func (o *MetricInGroupRep) HasNameInGroup() bool { + if o != nil && o.NameInGroup != nil { + return true + } + + return false +} + +// SetNameInGroup gets a reference to the given string and assigns it to the NameInGroup field. +func (o *MetricInGroupRep) SetNameInGroup(v string) { + o.NameInGroup = &v +} + +// GetRandomizationUnits returns the RandomizationUnits field value if set, zero value otherwise. +func (o *MetricInGroupRep) GetRandomizationUnits() []string { + if o == nil || o.RandomizationUnits == nil { + var ret []string + return ret + } + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInGroupRep) GetRandomizationUnitsOk() ([]string, bool) { + if o == nil || o.RandomizationUnits == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// HasRandomizationUnits returns a boolean if a field has been set. +func (o *MetricInGroupRep) HasRandomizationUnits() bool { + if o != nil && o.RandomizationUnits != nil { + return true + } + + return false +} + +// SetRandomizationUnits gets a reference to the given []string and assigns it to the RandomizationUnits field. +func (o *MetricInGroupRep) SetRandomizationUnits(v []string) { + o.RandomizationUnits = v +} + +func (o MetricInGroupRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.VersionId != nil { + toSerialize["_versionId"] = o.VersionId + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if o.UnitAggregationType != nil { + toSerialize["unitAggregationType"] = o.UnitAggregationType + } + if true { + toSerialize["_links"] = o.Links + } + if o.NameInGroup != nil { + toSerialize["nameInGroup"] = o.NameInGroup + } + if o.RandomizationUnits != nil { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + return json.Marshal(toSerialize) +} + +type NullableMetricInGroupRep struct { + value *MetricInGroupRep + isSet bool +} + +func (v NullableMetricInGroupRep) Get() *MetricInGroupRep { + return v.value +} + +func (v *NullableMetricInGroupRep) Set(val *MetricInGroupRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricInGroupRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricInGroupRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricInGroupRep(val *MetricInGroupRep) *NullableMetricInGroupRep { + return &NullableMetricInGroupRep{value: val, isSet: true} +} + +func (v NullableMetricInGroupRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricInGroupRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_results_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_results_rep.go new file mode 100644 index 00000000..67410fc3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_group_results_rep.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricInGroupResultsRep struct for MetricInGroupResultsRep +type MetricInGroupResultsRep struct { + Metric MetricInGroupRep `json:"metric"` + Results ExperimentBayesianResultsRep `json:"results"` +} + +// NewMetricInGroupResultsRep instantiates a new MetricInGroupResultsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricInGroupResultsRep(metric MetricInGroupRep, results ExperimentBayesianResultsRep) *MetricInGroupResultsRep { + this := MetricInGroupResultsRep{} + this.Metric = metric + this.Results = results + return &this +} + +// NewMetricInGroupResultsRepWithDefaults instantiates a new MetricInGroupResultsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricInGroupResultsRepWithDefaults() *MetricInGroupResultsRep { + this := MetricInGroupResultsRep{} + return &this +} + +// GetMetric returns the Metric field value +func (o *MetricInGroupResultsRep) GetMetric() MetricInGroupRep { + if o == nil { + var ret MetricInGroupRep + return ret + } + + return o.Metric +} + +// GetMetricOk returns a tuple with the Metric field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupResultsRep) GetMetricOk() (*MetricInGroupRep, bool) { + if o == nil { + return nil, false + } + return &o.Metric, true +} + +// SetMetric sets field value +func (o *MetricInGroupResultsRep) SetMetric(v MetricInGroupRep) { + o.Metric = v +} + +// GetResults returns the Results field value +func (o *MetricInGroupResultsRep) GetResults() ExperimentBayesianResultsRep { + if o == nil { + var ret ExperimentBayesianResultsRep + return ret + } + + return o.Results +} + +// GetResultsOk returns a tuple with the Results field value +// and a boolean to check if the value has been set. +func (o *MetricInGroupResultsRep) GetResultsOk() (*ExperimentBayesianResultsRep, bool) { + if o == nil { + return nil, false + } + return &o.Results, true +} + +// SetResults sets field value +func (o *MetricInGroupResultsRep) SetResults(v ExperimentBayesianResultsRep) { + o.Results = v +} + +func (o MetricInGroupResultsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["metric"] = o.Metric + } + if true { + toSerialize["results"] = o.Results + } + return json.Marshal(toSerialize) +} + +type NullableMetricInGroupResultsRep struct { + value *MetricInGroupResultsRep + isSet bool +} + +func (v NullableMetricInGroupResultsRep) Get() *MetricInGroupResultsRep { + return v.value +} + +func (v *NullableMetricInGroupResultsRep) Set(val *MetricInGroupResultsRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricInGroupResultsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricInGroupResultsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricInGroupResultsRep(val *MetricInGroupResultsRep) *NullableMetricInGroupResultsRep { + return &NullableMetricInGroupResultsRep{value: val, isSet: true} +} + +func (v NullableMetricInGroupResultsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricInGroupResultsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_metric_group_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_metric_group_input.go new file mode 100644 index 00000000..6f1be94c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_in_metric_group_input.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricInMetricGroupInput struct for MetricInMetricGroupInput +type MetricInMetricGroupInput struct { + // The metric key + Key string `json:"key"` + // Name of the metric when used within the associated metric group. Can be different from the original name of the metric + NameInGroup string `json:"nameInGroup"` +} + +// NewMetricInMetricGroupInput instantiates a new MetricInMetricGroupInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricInMetricGroupInput(key string, nameInGroup string) *MetricInMetricGroupInput { + this := MetricInMetricGroupInput{} + this.Key = key + this.NameInGroup = nameInGroup + return &this +} + +// NewMetricInMetricGroupInputWithDefaults instantiates a new MetricInMetricGroupInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricInMetricGroupInputWithDefaults() *MetricInMetricGroupInput { + this := MetricInMetricGroupInput{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricInMetricGroupInput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricInMetricGroupInput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricInMetricGroupInput) SetKey(v string) { + o.Key = v +} + +// GetNameInGroup returns the NameInGroup field value +func (o *MetricInMetricGroupInput) GetNameInGroup() string { + if o == nil { + var ret string + return ret + } + + return o.NameInGroup +} + +// GetNameInGroupOk returns a tuple with the NameInGroup field value +// and a boolean to check if the value has been set. +func (o *MetricInMetricGroupInput) GetNameInGroupOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.NameInGroup, true +} + +// SetNameInGroup sets field value +func (o *MetricInMetricGroupInput) SetNameInGroup(v string) { + o.NameInGroup = v +} + +func (o MetricInMetricGroupInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["nameInGroup"] = o.NameInGroup + } + return json.Marshal(toSerialize) +} + +type NullableMetricInMetricGroupInput struct { + value *MetricInMetricGroupInput + isSet bool +} + +func (v NullableMetricInMetricGroupInput) Get() *MetricInMetricGroupInput { + return v.value +} + +func (v *NullableMetricInMetricGroupInput) Set(val *MetricInMetricGroupInput) { + v.value = val + v.isSet = true +} + +func (v NullableMetricInMetricGroupInput) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricInMetricGroupInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricInMetricGroupInput(val *MetricInMetricGroupInput) *NullableMetricInMetricGroupInput { + return &NullableMetricInMetricGroupInput{value: val, isSet: true} +} + +func (v NullableMetricInMetricGroupInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricInMetricGroupInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_input.go new file mode 100644 index 00000000..76caeb23 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_input.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricInput struct for MetricInput +type MetricInput struct { + // The metric key + Key string `json:"key"` + // Whether this is a metric group (true) or a metric (false). Defaults to false + IsGroup *bool `json:"isGroup,omitempty"` + // Deprecated, use primarySingleMetricKey and primaryFunnelKey. Whether this is a primary metric (true) or a secondary metric (false) + // Deprecated + Primary *bool `json:"primary,omitempty"` +} + +// NewMetricInput instantiates a new MetricInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricInput(key string) *MetricInput { + this := MetricInput{} + this.Key = key + return &this +} + +// NewMetricInputWithDefaults instantiates a new MetricInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricInputWithDefaults() *MetricInput { + this := MetricInput{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricInput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricInput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricInput) SetKey(v string) { + o.Key = v +} + +// GetIsGroup returns the IsGroup field value if set, zero value otherwise. +func (o *MetricInput) GetIsGroup() bool { + if o == nil || o.IsGroup == nil { + var ret bool + return ret + } + return *o.IsGroup +} + +// GetIsGroupOk returns a tuple with the IsGroup field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricInput) GetIsGroupOk() (*bool, bool) { + if o == nil || o.IsGroup == nil { + return nil, false + } + return o.IsGroup, true +} + +// HasIsGroup returns a boolean if a field has been set. +func (o *MetricInput) HasIsGroup() bool { + if o != nil && o.IsGroup != nil { + return true + } + + return false +} + +// SetIsGroup gets a reference to the given bool and assigns it to the IsGroup field. +func (o *MetricInput) SetIsGroup(v bool) { + o.IsGroup = &v +} + +// GetPrimary returns the Primary field value if set, zero value otherwise. +// Deprecated +func (o *MetricInput) GetPrimary() bool { + if o == nil || o.Primary == nil { + var ret bool + return ret + } + return *o.Primary +} + +// GetPrimaryOk returns a tuple with the Primary field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *MetricInput) GetPrimaryOk() (*bool, bool) { + if o == nil || o.Primary == nil { + return nil, false + } + return o.Primary, true +} + +// HasPrimary returns a boolean if a field has been set. +func (o *MetricInput) HasPrimary() bool { + if o != nil && o.Primary != nil { + return true + } + + return false +} + +// SetPrimary gets a reference to the given bool and assigns it to the Primary field. +// Deprecated +func (o *MetricInput) SetPrimary(v bool) { + o.Primary = &v +} + +func (o MetricInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.IsGroup != nil { + toSerialize["isGroup"] = o.IsGroup + } + if o.Primary != nil { + toSerialize["primary"] = o.Primary + } + return json.Marshal(toSerialize) +} + +type NullableMetricInput struct { + value *MetricInput + isSet bool +} + +func (v NullableMetricInput) Get() *MetricInput { + return v.value +} + +func (v *NullableMetricInput) Set(val *MetricInput) { + v.value = val + v.isSet = true +} + +func (v NullableMetricInput) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricInput(val *MetricInput) *NullableMetricInput { + return &NullableMetricInput{value: val, isSet: true} +} + +func (v NullableMetricInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_listing_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_listing_rep.go new file mode 100644 index 00000000..3463b97a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_listing_rep.go @@ -0,0 +1,1017 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricListingRep struct for MetricListingRep +type MetricListingRep struct { + // The number of experiments using this metric + ExperimentCount *int32 `json:"experimentCount,omitempty"` + // The number of metric groups using this metric + MetricGroupCount *int32 `json:"metricGroupCount,omitempty"` + // The ID of this metric + Id string `json:"_id"` + // The version ID of the metric + VersionId string `json:"_versionId"` + // A unique key to reference the metric + Key string `json:"key"` + // A human-friendly name for the metric + Name string `json:"name"` + // The kind of event the metric tracks + Kind string `json:"kind"` + // The number of feature flags currently attached to this metric + AttachedFlagCount *int32 `json:"_attachedFlagCount,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site *Link `json:"_site,omitempty"` + Access *Access `json:"_access,omitempty"` + // Tags for the metric + Tags []string `json:"tags"` + CreationDate int64 `json:"_creationDate"` + LastModified *Modification `json:"lastModified,omitempty"` + // The ID of the member who maintains this metric + MaintainerId *string `json:"maintainerId,omitempty"` + Maintainer *MemberSummary `json:"_maintainer,omitempty"` + // Description of the metric + Description *string `json:"description,omitempty"` + // The category of the metric + Category *string `json:"category,omitempty"` + // For custom metrics, whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). + IsNumeric *bool `json:"isNumeric,omitempty"` + // For custom metrics, the success criteria + SuccessCriteria *string `json:"successCriteria,omitempty"` + // For numeric custom metrics, the unit of measure + Unit *string `json:"unit,omitempty"` + // For custom metrics, the event key to use in your code + EventKey *string `json:"eventKey,omitempty"` + // An array of randomization units allowed for this metric + RandomizationUnits []string `json:"randomizationUnits,omitempty"` + // The method by which multiple unit event values are aggregated + UnitAggregationType *string `json:"unitAggregationType,omitempty"` + // The method for analyzing metric events + AnalysisType *string `json:"analysisType,omitempty"` + // The percentile for the analysis method. An integer denoting the target percentile between 0 and 100. Required when analysisType is percentile. + PercentileValue *int32 `json:"percentileValue,omitempty"` + EventDefault *MetricEventDefaultRep `json:"eventDefault,omitempty"` +} + +// NewMetricListingRep instantiates a new MetricListingRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricListingRep(id string, versionId string, key string, name string, kind string, links map[string]Link, tags []string, creationDate int64) *MetricListingRep { + this := MetricListingRep{} + this.Id = id + this.VersionId = versionId + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + this.Tags = tags + this.CreationDate = creationDate + return &this +} + +// NewMetricListingRepWithDefaults instantiates a new MetricListingRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricListingRepWithDefaults() *MetricListingRep { + this := MetricListingRep{} + return &this +} + +// GetExperimentCount returns the ExperimentCount field value if set, zero value otherwise. +func (o *MetricListingRep) GetExperimentCount() int32 { + if o == nil || o.ExperimentCount == nil { + var ret int32 + return ret + } + return *o.ExperimentCount +} + +// GetExperimentCountOk returns a tuple with the ExperimentCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetExperimentCountOk() (*int32, bool) { + if o == nil || o.ExperimentCount == nil { + return nil, false + } + return o.ExperimentCount, true +} + +// HasExperimentCount returns a boolean if a field has been set. +func (o *MetricListingRep) HasExperimentCount() bool { + if o != nil && o.ExperimentCount != nil { + return true + } + + return false +} + +// SetExperimentCount gets a reference to the given int32 and assigns it to the ExperimentCount field. +func (o *MetricListingRep) SetExperimentCount(v int32) { + o.ExperimentCount = &v +} + +// GetMetricGroupCount returns the MetricGroupCount field value if set, zero value otherwise. +func (o *MetricListingRep) GetMetricGroupCount() int32 { + if o == nil || o.MetricGroupCount == nil { + var ret int32 + return ret + } + return *o.MetricGroupCount +} + +// GetMetricGroupCountOk returns a tuple with the MetricGroupCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetMetricGroupCountOk() (*int32, bool) { + if o == nil || o.MetricGroupCount == nil { + return nil, false + } + return o.MetricGroupCount, true +} + +// HasMetricGroupCount returns a boolean if a field has been set. +func (o *MetricListingRep) HasMetricGroupCount() bool { + if o != nil && o.MetricGroupCount != nil { + return true + } + + return false +} + +// SetMetricGroupCount gets a reference to the given int32 and assigns it to the MetricGroupCount field. +func (o *MetricListingRep) SetMetricGroupCount(v int32) { + o.MetricGroupCount = &v +} + +// GetId returns the Id field value +func (o *MetricListingRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MetricListingRep) SetId(v string) { + o.Id = v +} + +// GetVersionId returns the VersionId field value +func (o *MetricListingRep) GetVersionId() string { + if o == nil { + var ret string + return ret + } + + return o.VersionId +} + +// GetVersionIdOk returns a tuple with the VersionId field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetVersionIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VersionId, true +} + +// SetVersionId sets field value +func (o *MetricListingRep) SetVersionId(v string) { + o.VersionId = v +} + +// GetKey returns the Key field value +func (o *MetricListingRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricListingRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *MetricListingRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricListingRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricListingRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricListingRep) SetKind(v string) { + o.Kind = v +} + +// GetAttachedFlagCount returns the AttachedFlagCount field value if set, zero value otherwise. +func (o *MetricListingRep) GetAttachedFlagCount() int32 { + if o == nil || o.AttachedFlagCount == nil { + var ret int32 + return ret + } + return *o.AttachedFlagCount +} + +// GetAttachedFlagCountOk returns a tuple with the AttachedFlagCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetAttachedFlagCountOk() (*int32, bool) { + if o == nil || o.AttachedFlagCount == nil { + return nil, false + } + return o.AttachedFlagCount, true +} + +// HasAttachedFlagCount returns a boolean if a field has been set. +func (o *MetricListingRep) HasAttachedFlagCount() bool { + if o != nil && o.AttachedFlagCount != nil { + return true + } + + return false +} + +// SetAttachedFlagCount gets a reference to the given int32 and assigns it to the AttachedFlagCount field. +func (o *MetricListingRep) SetAttachedFlagCount(v int32) { + o.AttachedFlagCount = &v +} + +// GetLinks returns the Links field value +func (o *MetricListingRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricListingRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value if set, zero value otherwise. +func (o *MetricListingRep) GetSite() Link { + if o == nil || o.Site == nil { + var ret Link + return ret + } + return *o.Site +} + +// GetSiteOk returns a tuple with the Site field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetSiteOk() (*Link, bool) { + if o == nil || o.Site == nil { + return nil, false + } + return o.Site, true +} + +// HasSite returns a boolean if a field has been set. +func (o *MetricListingRep) HasSite() bool { + if o != nil && o.Site != nil { + return true + } + + return false +} + +// SetSite gets a reference to the given Link and assigns it to the Site field. +func (o *MetricListingRep) SetSite(v Link) { + o.Site = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *MetricListingRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *MetricListingRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *MetricListingRep) SetAccess(v Access) { + o.Access = &v +} + +// GetTags returns the Tags field value +func (o *MetricListingRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *MetricListingRep) SetTags(v []string) { + o.Tags = v +} + +// GetCreationDate returns the CreationDate field value +func (o *MetricListingRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *MetricListingRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value if set, zero value otherwise. +func (o *MetricListingRep) GetLastModified() Modification { + if o == nil || o.LastModified == nil { + var ret Modification + return ret + } + return *o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetLastModifiedOk() (*Modification, bool) { + if o == nil || o.LastModified == nil { + return nil, false + } + return o.LastModified, true +} + +// HasLastModified returns a boolean if a field has been set. +func (o *MetricListingRep) HasLastModified() bool { + if o != nil && o.LastModified != nil { + return true + } + + return false +} + +// SetLastModified gets a reference to the given Modification and assigns it to the LastModified field. +func (o *MetricListingRep) SetLastModified(v Modification) { + o.LastModified = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *MetricListingRep) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *MetricListingRep) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *MetricListingRep) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *MetricListingRep) GetMaintainer() MemberSummary { + if o == nil || o.Maintainer == nil { + var ret MemberSummary + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetMaintainerOk() (*MemberSummary, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *MetricListingRep) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MemberSummary and assigns it to the Maintainer field. +func (o *MetricListingRep) SetMaintainer(v MemberSummary) { + o.Maintainer = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *MetricListingRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *MetricListingRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *MetricListingRep) SetDescription(v string) { + o.Description = &v +} + +// GetCategory returns the Category field value if set, zero value otherwise. +func (o *MetricListingRep) GetCategory() string { + if o == nil || o.Category == nil { + var ret string + return ret + } + return *o.Category +} + +// GetCategoryOk returns a tuple with the Category field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetCategoryOk() (*string, bool) { + if o == nil || o.Category == nil { + return nil, false + } + return o.Category, true +} + +// HasCategory returns a boolean if a field has been set. +func (o *MetricListingRep) HasCategory() bool { + if o != nil && o.Category != nil { + return true + } + + return false +} + +// SetCategory gets a reference to the given string and assigns it to the Category field. +func (o *MetricListingRep) SetCategory(v string) { + o.Category = &v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *MetricListingRep) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *MetricListingRep) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *MetricListingRep) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetSuccessCriteria returns the SuccessCriteria field value if set, zero value otherwise. +func (o *MetricListingRep) GetSuccessCriteria() string { + if o == nil || o.SuccessCriteria == nil { + var ret string + return ret + } + return *o.SuccessCriteria +} + +// GetSuccessCriteriaOk returns a tuple with the SuccessCriteria field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetSuccessCriteriaOk() (*string, bool) { + if o == nil || o.SuccessCriteria == nil { + return nil, false + } + return o.SuccessCriteria, true +} + +// HasSuccessCriteria returns a boolean if a field has been set. +func (o *MetricListingRep) HasSuccessCriteria() bool { + if o != nil && o.SuccessCriteria != nil { + return true + } + + return false +} + +// SetSuccessCriteria gets a reference to the given string and assigns it to the SuccessCriteria field. +func (o *MetricListingRep) SetSuccessCriteria(v string) { + o.SuccessCriteria = &v +} + +// GetUnit returns the Unit field value if set, zero value otherwise. +func (o *MetricListingRep) GetUnit() string { + if o == nil || o.Unit == nil { + var ret string + return ret + } + return *o.Unit +} + +// GetUnitOk returns a tuple with the Unit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetUnitOk() (*string, bool) { + if o == nil || o.Unit == nil { + return nil, false + } + return o.Unit, true +} + +// HasUnit returns a boolean if a field has been set. +func (o *MetricListingRep) HasUnit() bool { + if o != nil && o.Unit != nil { + return true + } + + return false +} + +// SetUnit gets a reference to the given string and assigns it to the Unit field. +func (o *MetricListingRep) SetUnit(v string) { + o.Unit = &v +} + +// GetEventKey returns the EventKey field value if set, zero value otherwise. +func (o *MetricListingRep) GetEventKey() string { + if o == nil || o.EventKey == nil { + var ret string + return ret + } + return *o.EventKey +} + +// GetEventKeyOk returns a tuple with the EventKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetEventKeyOk() (*string, bool) { + if o == nil || o.EventKey == nil { + return nil, false + } + return o.EventKey, true +} + +// HasEventKey returns a boolean if a field has been set. +func (o *MetricListingRep) HasEventKey() bool { + if o != nil && o.EventKey != nil { + return true + } + + return false +} + +// SetEventKey gets a reference to the given string and assigns it to the EventKey field. +func (o *MetricListingRep) SetEventKey(v string) { + o.EventKey = &v +} + +// GetRandomizationUnits returns the RandomizationUnits field value if set, zero value otherwise. +func (o *MetricListingRep) GetRandomizationUnits() []string { + if o == nil || o.RandomizationUnits == nil { + var ret []string + return ret + } + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetRandomizationUnitsOk() ([]string, bool) { + if o == nil || o.RandomizationUnits == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// HasRandomizationUnits returns a boolean if a field has been set. +func (o *MetricListingRep) HasRandomizationUnits() bool { + if o != nil && o.RandomizationUnits != nil { + return true + } + + return false +} + +// SetRandomizationUnits gets a reference to the given []string and assigns it to the RandomizationUnits field. +func (o *MetricListingRep) SetRandomizationUnits(v []string) { + o.RandomizationUnits = v +} + +// GetUnitAggregationType returns the UnitAggregationType field value if set, zero value otherwise. +func (o *MetricListingRep) GetUnitAggregationType() string { + if o == nil || o.UnitAggregationType == nil { + var ret string + return ret + } + return *o.UnitAggregationType +} + +// GetUnitAggregationTypeOk returns a tuple with the UnitAggregationType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetUnitAggregationTypeOk() (*string, bool) { + if o == nil || o.UnitAggregationType == nil { + return nil, false + } + return o.UnitAggregationType, true +} + +// HasUnitAggregationType returns a boolean if a field has been set. +func (o *MetricListingRep) HasUnitAggregationType() bool { + if o != nil && o.UnitAggregationType != nil { + return true + } + + return false +} + +// SetUnitAggregationType gets a reference to the given string and assigns it to the UnitAggregationType field. +func (o *MetricListingRep) SetUnitAggregationType(v string) { + o.UnitAggregationType = &v +} + +// GetAnalysisType returns the AnalysisType field value if set, zero value otherwise. +func (o *MetricListingRep) GetAnalysisType() string { + if o == nil || o.AnalysisType == nil { + var ret string + return ret + } + return *o.AnalysisType +} + +// GetAnalysisTypeOk returns a tuple with the AnalysisType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetAnalysisTypeOk() (*string, bool) { + if o == nil || o.AnalysisType == nil { + return nil, false + } + return o.AnalysisType, true +} + +// HasAnalysisType returns a boolean if a field has been set. +func (o *MetricListingRep) HasAnalysisType() bool { + if o != nil && o.AnalysisType != nil { + return true + } + + return false +} + +// SetAnalysisType gets a reference to the given string and assigns it to the AnalysisType field. +func (o *MetricListingRep) SetAnalysisType(v string) { + o.AnalysisType = &v +} + +// GetPercentileValue returns the PercentileValue field value if set, zero value otherwise. +func (o *MetricListingRep) GetPercentileValue() int32 { + if o == nil || o.PercentileValue == nil { + var ret int32 + return ret + } + return *o.PercentileValue +} + +// GetPercentileValueOk returns a tuple with the PercentileValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetPercentileValueOk() (*int32, bool) { + if o == nil || o.PercentileValue == nil { + return nil, false + } + return o.PercentileValue, true +} + +// HasPercentileValue returns a boolean if a field has been set. +func (o *MetricListingRep) HasPercentileValue() bool { + if o != nil && o.PercentileValue != nil { + return true + } + + return false +} + +// SetPercentileValue gets a reference to the given int32 and assigns it to the PercentileValue field. +func (o *MetricListingRep) SetPercentileValue(v int32) { + o.PercentileValue = &v +} + +// GetEventDefault returns the EventDefault field value if set, zero value otherwise. +func (o *MetricListingRep) GetEventDefault() MetricEventDefaultRep { + if o == nil || o.EventDefault == nil { + var ret MetricEventDefaultRep + return ret + } + return *o.EventDefault +} + +// GetEventDefaultOk returns a tuple with the EventDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricListingRep) GetEventDefaultOk() (*MetricEventDefaultRep, bool) { + if o == nil || o.EventDefault == nil { + return nil, false + } + return o.EventDefault, true +} + +// HasEventDefault returns a boolean if a field has been set. +func (o *MetricListingRep) HasEventDefault() bool { + if o != nil && o.EventDefault != nil { + return true + } + + return false +} + +// SetEventDefault gets a reference to the given MetricEventDefaultRep and assigns it to the EventDefault field. +func (o *MetricListingRep) SetEventDefault(v MetricEventDefaultRep) { + o.EventDefault = &v +} + +func (o MetricListingRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ExperimentCount != nil { + toSerialize["experimentCount"] = o.ExperimentCount + } + if o.MetricGroupCount != nil { + toSerialize["metricGroupCount"] = o.MetricGroupCount + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_versionId"] = o.VersionId + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.AttachedFlagCount != nil { + toSerialize["_attachedFlagCount"] = o.AttachedFlagCount + } + if true { + toSerialize["_links"] = o.Links + } + if o.Site != nil { + toSerialize["_site"] = o.Site + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if o.LastModified != nil { + toSerialize["lastModified"] = o.LastModified + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Category != nil { + toSerialize["category"] = o.Category + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if o.SuccessCriteria != nil { + toSerialize["successCriteria"] = o.SuccessCriteria + } + if o.Unit != nil { + toSerialize["unit"] = o.Unit + } + if o.EventKey != nil { + toSerialize["eventKey"] = o.EventKey + } + if o.RandomizationUnits != nil { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + if o.UnitAggregationType != nil { + toSerialize["unitAggregationType"] = o.UnitAggregationType + } + if o.AnalysisType != nil { + toSerialize["analysisType"] = o.AnalysisType + } + if o.PercentileValue != nil { + toSerialize["percentileValue"] = o.PercentileValue + } + if o.EventDefault != nil { + toSerialize["eventDefault"] = o.EventDefault + } + return json.Marshal(toSerialize) +} + +type NullableMetricListingRep struct { + value *MetricListingRep + isSet bool +} + +func (v NullableMetricListingRep) Get() *MetricListingRep { + return v.value +} + +func (v *NullableMetricListingRep) Set(val *MetricListingRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricListingRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricListingRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricListingRep(val *MetricListingRep) *NullableMetricListingRep { + return &NullableMetricListingRep{value: val, isSet: true} +} + +func (v NullableMetricListingRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricListingRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_post.go new file mode 100644 index 00000000..f8e938b9 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_post.go @@ -0,0 +1,694 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricPost struct for MetricPost +type MetricPost struct { + // A unique key to reference the metric + Key string `json:"key"` + // A human-friendly name for the metric + Name *string `json:"name,omitempty"` + // Description of the metric + Description *string `json:"description,omitempty"` + // The kind of event your metric will track + Kind string `json:"kind"` + // One or more CSS selectors. Required for click metrics only. + Selector *string `json:"selector,omitempty"` + // One or more target URLs. Required for click and pageview metrics only. + Urls []UrlPost `json:"urls,omitempty"` + // Whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). Required for custom metrics only. + IsNumeric *bool `json:"isNumeric,omitempty"` + // The unit of measure. Applicable for numeric custom metrics only. + Unit *string `json:"unit,omitempty"` + // The event key to use in your code. Required for custom conversion/binary and custom numeric metrics only. + EventKey *string `json:"eventKey,omitempty"` + // Success criteria. Required for custom numeric metrics, optional for custom conversion metrics. + SuccessCriteria *string `json:"successCriteria,omitempty"` + // Tags for the metric + Tags []string `json:"tags,omitempty"` + // An array of randomization units allowed for this metric + RandomizationUnits []string `json:"randomizationUnits,omitempty"` + // The ID of the member who maintains this metric + MaintainerId *string `json:"maintainerId,omitempty"` + // The method by which multiple unit event values are aggregated + UnitAggregationType *string `json:"unitAggregationType,omitempty"` + // The method for analyzing metric events + AnalysisType *string `json:"analysisType,omitempty"` + // The percentile for the analysis method. An integer denoting the target percentile between 0 and 100. Required when analysisType is percentile. + PercentileValue *int32 `json:"percentileValue,omitempty"` + EventDefault *MetricEventDefaultRep `json:"eventDefault,omitempty"` +} + +// NewMetricPost instantiates a new MetricPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricPost(key string, kind string) *MetricPost { + this := MetricPost{} + this.Key = key + this.Kind = kind + return &this +} + +// NewMetricPostWithDefaults instantiates a new MetricPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricPostWithDefaults() *MetricPost { + this := MetricPost{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricPost) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *MetricPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *MetricPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *MetricPost) SetName(v string) { + o.Name = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *MetricPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *MetricPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *MetricPost) SetDescription(v string) { + o.Description = &v +} + +// GetKind returns the Kind field value +func (o *MetricPost) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricPost) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricPost) SetKind(v string) { + o.Kind = v +} + +// GetSelector returns the Selector field value if set, zero value otherwise. +func (o *MetricPost) GetSelector() string { + if o == nil || o.Selector == nil { + var ret string + return ret + } + return *o.Selector +} + +// GetSelectorOk returns a tuple with the Selector field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetSelectorOk() (*string, bool) { + if o == nil || o.Selector == nil { + return nil, false + } + return o.Selector, true +} + +// HasSelector returns a boolean if a field has been set. +func (o *MetricPost) HasSelector() bool { + if o != nil && o.Selector != nil { + return true + } + + return false +} + +// SetSelector gets a reference to the given string and assigns it to the Selector field. +func (o *MetricPost) SetSelector(v string) { + o.Selector = &v +} + +// GetUrls returns the Urls field value if set, zero value otherwise. +func (o *MetricPost) GetUrls() []UrlPost { + if o == nil || o.Urls == nil { + var ret []UrlPost + return ret + } + return o.Urls +} + +// GetUrlsOk returns a tuple with the Urls field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetUrlsOk() ([]UrlPost, bool) { + if o == nil || o.Urls == nil { + return nil, false + } + return o.Urls, true +} + +// HasUrls returns a boolean if a field has been set. +func (o *MetricPost) HasUrls() bool { + if o != nil && o.Urls != nil { + return true + } + + return false +} + +// SetUrls gets a reference to the given []UrlPost and assigns it to the Urls field. +func (o *MetricPost) SetUrls(v []UrlPost) { + o.Urls = v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *MetricPost) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *MetricPost) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *MetricPost) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetUnit returns the Unit field value if set, zero value otherwise. +func (o *MetricPost) GetUnit() string { + if o == nil || o.Unit == nil { + var ret string + return ret + } + return *o.Unit +} + +// GetUnitOk returns a tuple with the Unit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetUnitOk() (*string, bool) { + if o == nil || o.Unit == nil { + return nil, false + } + return o.Unit, true +} + +// HasUnit returns a boolean if a field has been set. +func (o *MetricPost) HasUnit() bool { + if o != nil && o.Unit != nil { + return true + } + + return false +} + +// SetUnit gets a reference to the given string and assigns it to the Unit field. +func (o *MetricPost) SetUnit(v string) { + o.Unit = &v +} + +// GetEventKey returns the EventKey field value if set, zero value otherwise. +func (o *MetricPost) GetEventKey() string { + if o == nil || o.EventKey == nil { + var ret string + return ret + } + return *o.EventKey +} + +// GetEventKeyOk returns a tuple with the EventKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetEventKeyOk() (*string, bool) { + if o == nil || o.EventKey == nil { + return nil, false + } + return o.EventKey, true +} + +// HasEventKey returns a boolean if a field has been set. +func (o *MetricPost) HasEventKey() bool { + if o != nil && o.EventKey != nil { + return true + } + + return false +} + +// SetEventKey gets a reference to the given string and assigns it to the EventKey field. +func (o *MetricPost) SetEventKey(v string) { + o.EventKey = &v +} + +// GetSuccessCriteria returns the SuccessCriteria field value if set, zero value otherwise. +func (o *MetricPost) GetSuccessCriteria() string { + if o == nil || o.SuccessCriteria == nil { + var ret string + return ret + } + return *o.SuccessCriteria +} + +// GetSuccessCriteriaOk returns a tuple with the SuccessCriteria field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetSuccessCriteriaOk() (*string, bool) { + if o == nil || o.SuccessCriteria == nil { + return nil, false + } + return o.SuccessCriteria, true +} + +// HasSuccessCriteria returns a boolean if a field has been set. +func (o *MetricPost) HasSuccessCriteria() bool { + if o != nil && o.SuccessCriteria != nil { + return true + } + + return false +} + +// SetSuccessCriteria gets a reference to the given string and assigns it to the SuccessCriteria field. +func (o *MetricPost) SetSuccessCriteria(v string) { + o.SuccessCriteria = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *MetricPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *MetricPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *MetricPost) SetTags(v []string) { + o.Tags = v +} + +// GetRandomizationUnits returns the RandomizationUnits field value if set, zero value otherwise. +func (o *MetricPost) GetRandomizationUnits() []string { + if o == nil || o.RandomizationUnits == nil { + var ret []string + return ret + } + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetRandomizationUnitsOk() ([]string, bool) { + if o == nil || o.RandomizationUnits == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// HasRandomizationUnits returns a boolean if a field has been set. +func (o *MetricPost) HasRandomizationUnits() bool { + if o != nil && o.RandomizationUnits != nil { + return true + } + + return false +} + +// SetRandomizationUnits gets a reference to the given []string and assigns it to the RandomizationUnits field. +func (o *MetricPost) SetRandomizationUnits(v []string) { + o.RandomizationUnits = v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *MetricPost) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *MetricPost) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *MetricPost) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetUnitAggregationType returns the UnitAggregationType field value if set, zero value otherwise. +func (o *MetricPost) GetUnitAggregationType() string { + if o == nil || o.UnitAggregationType == nil { + var ret string + return ret + } + return *o.UnitAggregationType +} + +// GetUnitAggregationTypeOk returns a tuple with the UnitAggregationType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetUnitAggregationTypeOk() (*string, bool) { + if o == nil || o.UnitAggregationType == nil { + return nil, false + } + return o.UnitAggregationType, true +} + +// HasUnitAggregationType returns a boolean if a field has been set. +func (o *MetricPost) HasUnitAggregationType() bool { + if o != nil && o.UnitAggregationType != nil { + return true + } + + return false +} + +// SetUnitAggregationType gets a reference to the given string and assigns it to the UnitAggregationType field. +func (o *MetricPost) SetUnitAggregationType(v string) { + o.UnitAggregationType = &v +} + +// GetAnalysisType returns the AnalysisType field value if set, zero value otherwise. +func (o *MetricPost) GetAnalysisType() string { + if o == nil || o.AnalysisType == nil { + var ret string + return ret + } + return *o.AnalysisType +} + +// GetAnalysisTypeOk returns a tuple with the AnalysisType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetAnalysisTypeOk() (*string, bool) { + if o == nil || o.AnalysisType == nil { + return nil, false + } + return o.AnalysisType, true +} + +// HasAnalysisType returns a boolean if a field has been set. +func (o *MetricPost) HasAnalysisType() bool { + if o != nil && o.AnalysisType != nil { + return true + } + + return false +} + +// SetAnalysisType gets a reference to the given string and assigns it to the AnalysisType field. +func (o *MetricPost) SetAnalysisType(v string) { + o.AnalysisType = &v +} + +// GetPercentileValue returns the PercentileValue field value if set, zero value otherwise. +func (o *MetricPost) GetPercentileValue() int32 { + if o == nil || o.PercentileValue == nil { + var ret int32 + return ret + } + return *o.PercentileValue +} + +// GetPercentileValueOk returns a tuple with the PercentileValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetPercentileValueOk() (*int32, bool) { + if o == nil || o.PercentileValue == nil { + return nil, false + } + return o.PercentileValue, true +} + +// HasPercentileValue returns a boolean if a field has been set. +func (o *MetricPost) HasPercentileValue() bool { + if o != nil && o.PercentileValue != nil { + return true + } + + return false +} + +// SetPercentileValue gets a reference to the given int32 and assigns it to the PercentileValue field. +func (o *MetricPost) SetPercentileValue(v int32) { + o.PercentileValue = &v +} + +// GetEventDefault returns the EventDefault field value if set, zero value otherwise. +func (o *MetricPost) GetEventDefault() MetricEventDefaultRep { + if o == nil || o.EventDefault == nil { + var ret MetricEventDefaultRep + return ret + } + return *o.EventDefault +} + +// GetEventDefaultOk returns a tuple with the EventDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricPost) GetEventDefaultOk() (*MetricEventDefaultRep, bool) { + if o == nil || o.EventDefault == nil { + return nil, false + } + return o.EventDefault, true +} + +// HasEventDefault returns a boolean if a field has been set. +func (o *MetricPost) HasEventDefault() bool { + if o != nil && o.EventDefault != nil { + return true + } + + return false +} + +// SetEventDefault gets a reference to the given MetricEventDefaultRep and assigns it to the EventDefault field. +func (o *MetricPost) SetEventDefault(v MetricEventDefaultRep) { + o.EventDefault = &v +} + +func (o MetricPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["kind"] = o.Kind + } + if o.Selector != nil { + toSerialize["selector"] = o.Selector + } + if o.Urls != nil { + toSerialize["urls"] = o.Urls + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if o.Unit != nil { + toSerialize["unit"] = o.Unit + } + if o.EventKey != nil { + toSerialize["eventKey"] = o.EventKey + } + if o.SuccessCriteria != nil { + toSerialize["successCriteria"] = o.SuccessCriteria + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.RandomizationUnits != nil { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.UnitAggregationType != nil { + toSerialize["unitAggregationType"] = o.UnitAggregationType + } + if o.AnalysisType != nil { + toSerialize["analysisType"] = o.AnalysisType + } + if o.PercentileValue != nil { + toSerialize["percentileValue"] = o.PercentileValue + } + if o.EventDefault != nil { + toSerialize["eventDefault"] = o.EventDefault + } + return json.Marshal(toSerialize) +} + +type NullableMetricPost struct { + value *MetricPost + isSet bool +} + +func (v NullableMetricPost) Get() *MetricPost { + return v.value +} + +func (v *NullableMetricPost) Set(val *MetricPost) { + v.value = val + v.isSet = true +} + +func (v NullableMetricPost) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricPost(val *MetricPost) *NullableMetricPost { + return &NullableMetricPost{value: val, isSet: true} +} + +func (v NullableMetricPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_rep.go new file mode 100644 index 00000000..897d34f0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_rep.go @@ -0,0 +1,1274 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricRep struct for MetricRep +type MetricRep struct { + // The number of experiments using this metric + ExperimentCount *int32 `json:"experimentCount,omitempty"` + // The number of metric groups using this metric + MetricGroupCount *int32 `json:"metricGroupCount,omitempty"` + // The ID of this metric + Id string `json:"_id"` + // The version ID of the metric + VersionId string `json:"_versionId"` + // A unique key to reference the metric + Key string `json:"key"` + // A human-friendly name for the metric + Name string `json:"name"` + // The kind of event the metric tracks + Kind string `json:"kind"` + // The number of feature flags currently attached to this metric + AttachedFlagCount *int32 `json:"_attachedFlagCount,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site *Link `json:"_site,omitempty"` + Access *Access `json:"_access,omitempty"` + // Tags for the metric + Tags []string `json:"tags"` + CreationDate int64 `json:"_creationDate"` + LastModified *Modification `json:"lastModified,omitempty"` + // The ID of the member who maintains this metric + MaintainerId *string `json:"maintainerId,omitempty"` + Maintainer *MemberSummary `json:"_maintainer,omitempty"` + // Description of the metric + Description *string `json:"description,omitempty"` + // The category of the metric + Category *string `json:"category,omitempty"` + // For custom metrics, whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). + IsNumeric *bool `json:"isNumeric,omitempty"` + // For custom metrics, the success criteria + SuccessCriteria *string `json:"successCriteria,omitempty"` + // For numeric custom metrics, the unit of measure + Unit *string `json:"unit,omitempty"` + // For custom metrics, the event key to use in your code + EventKey *string `json:"eventKey,omitempty"` + // An array of randomization units allowed for this metric + RandomizationUnits []string `json:"randomizationUnits,omitempty"` + // The method by which multiple unit event values are aggregated + UnitAggregationType *string `json:"unitAggregationType,omitempty"` + // The method for analyzing metric events + AnalysisType *string `json:"analysisType,omitempty"` + // The percentile for the analysis method. An integer denoting the target percentile between 0 and 100. Required when analysisType is percentile. + PercentileValue *int32 `json:"percentileValue,omitempty"` + EventDefault *MetricEventDefaultRep `json:"eventDefault,omitempty"` + Experiments []DependentExperimentRep `json:"experiments,omitempty"` + // Metric groups that use this metric + MetricGroups []DependentMetricGroupRep `json:"metricGroups,omitempty"` + // Whether the metric is active + IsActive *bool `json:"isActive,omitempty"` + // Details on the flags attached to this metric + AttachedFeatures []FlagListingRep `json:"_attachedFeatures,omitempty"` + // Version of the metric + Version *int32 `json:"_version,omitempty"` + // For click metrics, the CSS selectors + Selector *string `json:"selector,omitempty"` + Urls []map[string]interface{} `json:"urls,omitempty"` +} + +// NewMetricRep instantiates a new MetricRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricRep(id string, versionId string, key string, name string, kind string, links map[string]Link, tags []string, creationDate int64) *MetricRep { + this := MetricRep{} + this.Id = id + this.VersionId = versionId + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + this.Tags = tags + this.CreationDate = creationDate + return &this +} + +// NewMetricRepWithDefaults instantiates a new MetricRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricRepWithDefaults() *MetricRep { + this := MetricRep{} + return &this +} + +// GetExperimentCount returns the ExperimentCount field value if set, zero value otherwise. +func (o *MetricRep) GetExperimentCount() int32 { + if o == nil || o.ExperimentCount == nil { + var ret int32 + return ret + } + return *o.ExperimentCount +} + +// GetExperimentCountOk returns a tuple with the ExperimentCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetExperimentCountOk() (*int32, bool) { + if o == nil || o.ExperimentCount == nil { + return nil, false + } + return o.ExperimentCount, true +} + +// HasExperimentCount returns a boolean if a field has been set. +func (o *MetricRep) HasExperimentCount() bool { + if o != nil && o.ExperimentCount != nil { + return true + } + + return false +} + +// SetExperimentCount gets a reference to the given int32 and assigns it to the ExperimentCount field. +func (o *MetricRep) SetExperimentCount(v int32) { + o.ExperimentCount = &v +} + +// GetMetricGroupCount returns the MetricGroupCount field value if set, zero value otherwise. +func (o *MetricRep) GetMetricGroupCount() int32 { + if o == nil || o.MetricGroupCount == nil { + var ret int32 + return ret + } + return *o.MetricGroupCount +} + +// GetMetricGroupCountOk returns a tuple with the MetricGroupCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetMetricGroupCountOk() (*int32, bool) { + if o == nil || o.MetricGroupCount == nil { + return nil, false + } + return o.MetricGroupCount, true +} + +// HasMetricGroupCount returns a boolean if a field has been set. +func (o *MetricRep) HasMetricGroupCount() bool { + if o != nil && o.MetricGroupCount != nil { + return true + } + + return false +} + +// SetMetricGroupCount gets a reference to the given int32 and assigns it to the MetricGroupCount field. +func (o *MetricRep) SetMetricGroupCount(v int32) { + o.MetricGroupCount = &v +} + +// GetId returns the Id field value +func (o *MetricRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MetricRep) SetId(v string) { + o.Id = v +} + +// GetVersionId returns the VersionId field value +func (o *MetricRep) GetVersionId() string { + if o == nil { + var ret string + return ret + } + + return o.VersionId +} + +// GetVersionIdOk returns a tuple with the VersionId field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetVersionIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VersionId, true +} + +// SetVersionId sets field value +func (o *MetricRep) SetVersionId(v string) { + o.VersionId = v +} + +// GetKey returns the Key field value +func (o *MetricRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricRep) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *MetricRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricRep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricRep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricRep) SetKind(v string) { + o.Kind = v +} + +// GetAttachedFlagCount returns the AttachedFlagCount field value if set, zero value otherwise. +func (o *MetricRep) GetAttachedFlagCount() int32 { + if o == nil || o.AttachedFlagCount == nil { + var ret int32 + return ret + } + return *o.AttachedFlagCount +} + +// GetAttachedFlagCountOk returns a tuple with the AttachedFlagCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetAttachedFlagCountOk() (*int32, bool) { + if o == nil || o.AttachedFlagCount == nil { + return nil, false + } + return o.AttachedFlagCount, true +} + +// HasAttachedFlagCount returns a boolean if a field has been set. +func (o *MetricRep) HasAttachedFlagCount() bool { + if o != nil && o.AttachedFlagCount != nil { + return true + } + + return false +} + +// SetAttachedFlagCount gets a reference to the given int32 and assigns it to the AttachedFlagCount field. +func (o *MetricRep) SetAttachedFlagCount(v int32) { + o.AttachedFlagCount = &v +} + +// GetLinks returns the Links field value +func (o *MetricRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value if set, zero value otherwise. +func (o *MetricRep) GetSite() Link { + if o == nil || o.Site == nil { + var ret Link + return ret + } + return *o.Site +} + +// GetSiteOk returns a tuple with the Site field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetSiteOk() (*Link, bool) { + if o == nil || o.Site == nil { + return nil, false + } + return o.Site, true +} + +// HasSite returns a boolean if a field has been set. +func (o *MetricRep) HasSite() bool { + if o != nil && o.Site != nil { + return true + } + + return false +} + +// SetSite gets a reference to the given Link and assigns it to the Site field. +func (o *MetricRep) SetSite(v Link) { + o.Site = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *MetricRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *MetricRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *MetricRep) SetAccess(v Access) { + o.Access = &v +} + +// GetTags returns the Tags field value +func (o *MetricRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *MetricRep) SetTags(v []string) { + o.Tags = v +} + +// GetCreationDate returns the CreationDate field value +func (o *MetricRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *MetricRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *MetricRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value if set, zero value otherwise. +func (o *MetricRep) GetLastModified() Modification { + if o == nil || o.LastModified == nil { + var ret Modification + return ret + } + return *o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetLastModifiedOk() (*Modification, bool) { + if o == nil || o.LastModified == nil { + return nil, false + } + return o.LastModified, true +} + +// HasLastModified returns a boolean if a field has been set. +func (o *MetricRep) HasLastModified() bool { + if o != nil && o.LastModified != nil { + return true + } + + return false +} + +// SetLastModified gets a reference to the given Modification and assigns it to the LastModified field. +func (o *MetricRep) SetLastModified(v Modification) { + o.LastModified = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *MetricRep) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *MetricRep) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *MetricRep) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *MetricRep) GetMaintainer() MemberSummary { + if o == nil || o.Maintainer == nil { + var ret MemberSummary + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetMaintainerOk() (*MemberSummary, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *MetricRep) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MemberSummary and assigns it to the Maintainer field. +func (o *MetricRep) SetMaintainer(v MemberSummary) { + o.Maintainer = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *MetricRep) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *MetricRep) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *MetricRep) SetDescription(v string) { + o.Description = &v +} + +// GetCategory returns the Category field value if set, zero value otherwise. +func (o *MetricRep) GetCategory() string { + if o == nil || o.Category == nil { + var ret string + return ret + } + return *o.Category +} + +// GetCategoryOk returns a tuple with the Category field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetCategoryOk() (*string, bool) { + if o == nil || o.Category == nil { + return nil, false + } + return o.Category, true +} + +// HasCategory returns a boolean if a field has been set. +func (o *MetricRep) HasCategory() bool { + if o != nil && o.Category != nil { + return true + } + + return false +} + +// SetCategory gets a reference to the given string and assigns it to the Category field. +func (o *MetricRep) SetCategory(v string) { + o.Category = &v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *MetricRep) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *MetricRep) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *MetricRep) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetSuccessCriteria returns the SuccessCriteria field value if set, zero value otherwise. +func (o *MetricRep) GetSuccessCriteria() string { + if o == nil || o.SuccessCriteria == nil { + var ret string + return ret + } + return *o.SuccessCriteria +} + +// GetSuccessCriteriaOk returns a tuple with the SuccessCriteria field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetSuccessCriteriaOk() (*string, bool) { + if o == nil || o.SuccessCriteria == nil { + return nil, false + } + return o.SuccessCriteria, true +} + +// HasSuccessCriteria returns a boolean if a field has been set. +func (o *MetricRep) HasSuccessCriteria() bool { + if o != nil && o.SuccessCriteria != nil { + return true + } + + return false +} + +// SetSuccessCriteria gets a reference to the given string and assigns it to the SuccessCriteria field. +func (o *MetricRep) SetSuccessCriteria(v string) { + o.SuccessCriteria = &v +} + +// GetUnit returns the Unit field value if set, zero value otherwise. +func (o *MetricRep) GetUnit() string { + if o == nil || o.Unit == nil { + var ret string + return ret + } + return *o.Unit +} + +// GetUnitOk returns a tuple with the Unit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetUnitOk() (*string, bool) { + if o == nil || o.Unit == nil { + return nil, false + } + return o.Unit, true +} + +// HasUnit returns a boolean if a field has been set. +func (o *MetricRep) HasUnit() bool { + if o != nil && o.Unit != nil { + return true + } + + return false +} + +// SetUnit gets a reference to the given string and assigns it to the Unit field. +func (o *MetricRep) SetUnit(v string) { + o.Unit = &v +} + +// GetEventKey returns the EventKey field value if set, zero value otherwise. +func (o *MetricRep) GetEventKey() string { + if o == nil || o.EventKey == nil { + var ret string + return ret + } + return *o.EventKey +} + +// GetEventKeyOk returns a tuple with the EventKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetEventKeyOk() (*string, bool) { + if o == nil || o.EventKey == nil { + return nil, false + } + return o.EventKey, true +} + +// HasEventKey returns a boolean if a field has been set. +func (o *MetricRep) HasEventKey() bool { + if o != nil && o.EventKey != nil { + return true + } + + return false +} + +// SetEventKey gets a reference to the given string and assigns it to the EventKey field. +func (o *MetricRep) SetEventKey(v string) { + o.EventKey = &v +} + +// GetRandomizationUnits returns the RandomizationUnits field value if set, zero value otherwise. +func (o *MetricRep) GetRandomizationUnits() []string { + if o == nil || o.RandomizationUnits == nil { + var ret []string + return ret + } + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetRandomizationUnitsOk() ([]string, bool) { + if o == nil || o.RandomizationUnits == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// HasRandomizationUnits returns a boolean if a field has been set. +func (o *MetricRep) HasRandomizationUnits() bool { + if o != nil && o.RandomizationUnits != nil { + return true + } + + return false +} + +// SetRandomizationUnits gets a reference to the given []string and assigns it to the RandomizationUnits field. +func (o *MetricRep) SetRandomizationUnits(v []string) { + o.RandomizationUnits = v +} + +// GetUnitAggregationType returns the UnitAggregationType field value if set, zero value otherwise. +func (o *MetricRep) GetUnitAggregationType() string { + if o == nil || o.UnitAggregationType == nil { + var ret string + return ret + } + return *o.UnitAggregationType +} + +// GetUnitAggregationTypeOk returns a tuple with the UnitAggregationType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetUnitAggregationTypeOk() (*string, bool) { + if o == nil || o.UnitAggregationType == nil { + return nil, false + } + return o.UnitAggregationType, true +} + +// HasUnitAggregationType returns a boolean if a field has been set. +func (o *MetricRep) HasUnitAggregationType() bool { + if o != nil && o.UnitAggregationType != nil { + return true + } + + return false +} + +// SetUnitAggregationType gets a reference to the given string and assigns it to the UnitAggregationType field. +func (o *MetricRep) SetUnitAggregationType(v string) { + o.UnitAggregationType = &v +} + +// GetAnalysisType returns the AnalysisType field value if set, zero value otherwise. +func (o *MetricRep) GetAnalysisType() string { + if o == nil || o.AnalysisType == nil { + var ret string + return ret + } + return *o.AnalysisType +} + +// GetAnalysisTypeOk returns a tuple with the AnalysisType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetAnalysisTypeOk() (*string, bool) { + if o == nil || o.AnalysisType == nil { + return nil, false + } + return o.AnalysisType, true +} + +// HasAnalysisType returns a boolean if a field has been set. +func (o *MetricRep) HasAnalysisType() bool { + if o != nil && o.AnalysisType != nil { + return true + } + + return false +} + +// SetAnalysisType gets a reference to the given string and assigns it to the AnalysisType field. +func (o *MetricRep) SetAnalysisType(v string) { + o.AnalysisType = &v +} + +// GetPercentileValue returns the PercentileValue field value if set, zero value otherwise. +func (o *MetricRep) GetPercentileValue() int32 { + if o == nil || o.PercentileValue == nil { + var ret int32 + return ret + } + return *o.PercentileValue +} + +// GetPercentileValueOk returns a tuple with the PercentileValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetPercentileValueOk() (*int32, bool) { + if o == nil || o.PercentileValue == nil { + return nil, false + } + return o.PercentileValue, true +} + +// HasPercentileValue returns a boolean if a field has been set. +func (o *MetricRep) HasPercentileValue() bool { + if o != nil && o.PercentileValue != nil { + return true + } + + return false +} + +// SetPercentileValue gets a reference to the given int32 and assigns it to the PercentileValue field. +func (o *MetricRep) SetPercentileValue(v int32) { + o.PercentileValue = &v +} + +// GetEventDefault returns the EventDefault field value if set, zero value otherwise. +func (o *MetricRep) GetEventDefault() MetricEventDefaultRep { + if o == nil || o.EventDefault == nil { + var ret MetricEventDefaultRep + return ret + } + return *o.EventDefault +} + +// GetEventDefaultOk returns a tuple with the EventDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetEventDefaultOk() (*MetricEventDefaultRep, bool) { + if o == nil || o.EventDefault == nil { + return nil, false + } + return o.EventDefault, true +} + +// HasEventDefault returns a boolean if a field has been set. +func (o *MetricRep) HasEventDefault() bool { + if o != nil && o.EventDefault != nil { + return true + } + + return false +} + +// SetEventDefault gets a reference to the given MetricEventDefaultRep and assigns it to the EventDefault field. +func (o *MetricRep) SetEventDefault(v MetricEventDefaultRep) { + o.EventDefault = &v +} + +// GetExperiments returns the Experiments field value if set, zero value otherwise. +func (o *MetricRep) GetExperiments() []DependentExperimentRep { + if o == nil || o.Experiments == nil { + var ret []DependentExperimentRep + return ret + } + return o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetExperimentsOk() ([]DependentExperimentRep, bool) { + if o == nil || o.Experiments == nil { + return nil, false + } + return o.Experiments, true +} + +// HasExperiments returns a boolean if a field has been set. +func (o *MetricRep) HasExperiments() bool { + if o != nil && o.Experiments != nil { + return true + } + + return false +} + +// SetExperiments gets a reference to the given []DependentExperimentRep and assigns it to the Experiments field. +func (o *MetricRep) SetExperiments(v []DependentExperimentRep) { + o.Experiments = v +} + +// GetMetricGroups returns the MetricGroups field value if set, zero value otherwise. +func (o *MetricRep) GetMetricGroups() []DependentMetricGroupRep { + if o == nil || o.MetricGroups == nil { + var ret []DependentMetricGroupRep + return ret + } + return o.MetricGroups +} + +// GetMetricGroupsOk returns a tuple with the MetricGroups field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetMetricGroupsOk() ([]DependentMetricGroupRep, bool) { + if o == nil || o.MetricGroups == nil { + return nil, false + } + return o.MetricGroups, true +} + +// HasMetricGroups returns a boolean if a field has been set. +func (o *MetricRep) HasMetricGroups() bool { + if o != nil && o.MetricGroups != nil { + return true + } + + return false +} + +// SetMetricGroups gets a reference to the given []DependentMetricGroupRep and assigns it to the MetricGroups field. +func (o *MetricRep) SetMetricGroups(v []DependentMetricGroupRep) { + o.MetricGroups = v +} + +// GetIsActive returns the IsActive field value if set, zero value otherwise. +func (o *MetricRep) GetIsActive() bool { + if o == nil || o.IsActive == nil { + var ret bool + return ret + } + return *o.IsActive +} + +// GetIsActiveOk returns a tuple with the IsActive field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetIsActiveOk() (*bool, bool) { + if o == nil || o.IsActive == nil { + return nil, false + } + return o.IsActive, true +} + +// HasIsActive returns a boolean if a field has been set. +func (o *MetricRep) HasIsActive() bool { + if o != nil && o.IsActive != nil { + return true + } + + return false +} + +// SetIsActive gets a reference to the given bool and assigns it to the IsActive field. +func (o *MetricRep) SetIsActive(v bool) { + o.IsActive = &v +} + +// GetAttachedFeatures returns the AttachedFeatures field value if set, zero value otherwise. +func (o *MetricRep) GetAttachedFeatures() []FlagListingRep { + if o == nil || o.AttachedFeatures == nil { + var ret []FlagListingRep + return ret + } + return o.AttachedFeatures +} + +// GetAttachedFeaturesOk returns a tuple with the AttachedFeatures field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetAttachedFeaturesOk() ([]FlagListingRep, bool) { + if o == nil || o.AttachedFeatures == nil { + return nil, false + } + return o.AttachedFeatures, true +} + +// HasAttachedFeatures returns a boolean if a field has been set. +func (o *MetricRep) HasAttachedFeatures() bool { + if o != nil && o.AttachedFeatures != nil { + return true + } + + return false +} + +// SetAttachedFeatures gets a reference to the given []FlagListingRep and assigns it to the AttachedFeatures field. +func (o *MetricRep) SetAttachedFeatures(v []FlagListingRep) { + o.AttachedFeatures = v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *MetricRep) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *MetricRep) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *MetricRep) SetVersion(v int32) { + o.Version = &v +} + +// GetSelector returns the Selector field value if set, zero value otherwise. +func (o *MetricRep) GetSelector() string { + if o == nil || o.Selector == nil { + var ret string + return ret + } + return *o.Selector +} + +// GetSelectorOk returns a tuple with the Selector field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetSelectorOk() (*string, bool) { + if o == nil || o.Selector == nil { + return nil, false + } + return o.Selector, true +} + +// HasSelector returns a boolean if a field has been set. +func (o *MetricRep) HasSelector() bool { + if o != nil && o.Selector != nil { + return true + } + + return false +} + +// SetSelector gets a reference to the given string and assigns it to the Selector field. +func (o *MetricRep) SetSelector(v string) { + o.Selector = &v +} + +// GetUrls returns the Urls field value if set, zero value otherwise. +func (o *MetricRep) GetUrls() []map[string]interface{} { + if o == nil || o.Urls == nil { + var ret []map[string]interface{} + return ret + } + return o.Urls +} + +// GetUrlsOk returns a tuple with the Urls field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricRep) GetUrlsOk() ([]map[string]interface{}, bool) { + if o == nil || o.Urls == nil { + return nil, false + } + return o.Urls, true +} + +// HasUrls returns a boolean if a field has been set. +func (o *MetricRep) HasUrls() bool { + if o != nil && o.Urls != nil { + return true + } + + return false +} + +// SetUrls gets a reference to the given []map[string]interface{} and assigns it to the Urls field. +func (o *MetricRep) SetUrls(v []map[string]interface{}) { + o.Urls = v +} + +func (o MetricRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ExperimentCount != nil { + toSerialize["experimentCount"] = o.ExperimentCount + } + if o.MetricGroupCount != nil { + toSerialize["metricGroupCount"] = o.MetricGroupCount + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_versionId"] = o.VersionId + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.AttachedFlagCount != nil { + toSerialize["_attachedFlagCount"] = o.AttachedFlagCount + } + if true { + toSerialize["_links"] = o.Links + } + if o.Site != nil { + toSerialize["_site"] = o.Site + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if o.LastModified != nil { + toSerialize["lastModified"] = o.LastModified + } + if o.MaintainerId != nil { + toSerialize["maintainerId"] = o.MaintainerId + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Category != nil { + toSerialize["category"] = o.Category + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if o.SuccessCriteria != nil { + toSerialize["successCriteria"] = o.SuccessCriteria + } + if o.Unit != nil { + toSerialize["unit"] = o.Unit + } + if o.EventKey != nil { + toSerialize["eventKey"] = o.EventKey + } + if o.RandomizationUnits != nil { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + if o.UnitAggregationType != nil { + toSerialize["unitAggregationType"] = o.UnitAggregationType + } + if o.AnalysisType != nil { + toSerialize["analysisType"] = o.AnalysisType + } + if o.PercentileValue != nil { + toSerialize["percentileValue"] = o.PercentileValue + } + if o.EventDefault != nil { + toSerialize["eventDefault"] = o.EventDefault + } + if o.Experiments != nil { + toSerialize["experiments"] = o.Experiments + } + if o.MetricGroups != nil { + toSerialize["metricGroups"] = o.MetricGroups + } + if o.IsActive != nil { + toSerialize["isActive"] = o.IsActive + } + if o.AttachedFeatures != nil { + toSerialize["_attachedFeatures"] = o.AttachedFeatures + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if o.Selector != nil { + toSerialize["selector"] = o.Selector + } + if o.Urls != nil { + toSerialize["urls"] = o.Urls + } + return json.Marshal(toSerialize) +} + +type NullableMetricRep struct { + value *MetricRep + isSet bool +} + +func (v NullableMetricRep) Get() *MetricRep { + return v.value +} + +func (v *NullableMetricRep) Set(val *MetricRep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricRep(val *MetricRep) *NullableMetricRep { + return &NullableMetricRep{value: val, isSet: true} +} + +func (v NullableMetricRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_seen.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_seen.go new file mode 100644 index 00000000..55cccaeb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_seen.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricSeen struct for MetricSeen +type MetricSeen struct { + // Whether the metric has received an event for this iteration + Ever *bool `json:"ever,omitempty"` + // Timestamp of when the metric most recently received an event for this iteration + Timestamp *int64 `json:"timestamp,omitempty"` +} + +// NewMetricSeen instantiates a new MetricSeen object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricSeen() *MetricSeen { + this := MetricSeen{} + return &this +} + +// NewMetricSeenWithDefaults instantiates a new MetricSeen object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricSeenWithDefaults() *MetricSeen { + this := MetricSeen{} + return &this +} + +// GetEver returns the Ever field value if set, zero value otherwise. +func (o *MetricSeen) GetEver() bool { + if o == nil || o.Ever == nil { + var ret bool + return ret + } + return *o.Ever +} + +// GetEverOk returns a tuple with the Ever field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricSeen) GetEverOk() (*bool, bool) { + if o == nil || o.Ever == nil { + return nil, false + } + return o.Ever, true +} + +// HasEver returns a boolean if a field has been set. +func (o *MetricSeen) HasEver() bool { + if o != nil && o.Ever != nil { + return true + } + + return false +} + +// SetEver gets a reference to the given bool and assigns it to the Ever field. +func (o *MetricSeen) SetEver(v bool) { + o.Ever = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *MetricSeen) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricSeen) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *MetricSeen) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *MetricSeen) SetTimestamp(v int64) { + o.Timestamp = &v +} + +func (o MetricSeen) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Ever != nil { + toSerialize["ever"] = o.Ever + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + return json.Marshal(toSerialize) +} + +type NullableMetricSeen struct { + value *MetricSeen + isSet bool +} + +func (v NullableMetricSeen) Get() *MetricSeen { + return v.value +} + +func (v *NullableMetricSeen) Set(val *MetricSeen) { + v.value = val + v.isSet = true +} + +func (v NullableMetricSeen) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricSeen) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricSeen(val *MetricSeen) *NullableMetricSeen { + return &NullableMetricSeen{value: val, isSet: true} +} + +func (v NullableMetricSeen) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricSeen) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_v2_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_v2_rep.go new file mode 100644 index 00000000..0c1d9ba0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metric_v2_rep.go @@ -0,0 +1,311 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MetricV2Rep struct for MetricV2Rep +type MetricV2Rep struct { + // The metric key + Key string `json:"key"` + // The version ID of the metric + VersionId *string `json:"_versionId,omitempty"` + // The metric name + Name string `json:"name"` + // The kind of event the metric tracks + Kind string `json:"kind"` + // For custom metrics, whether to track numeric changes in value against a baseline (true) or to track a conversion when an end user takes an action (false). + IsNumeric *bool `json:"isNumeric,omitempty"` + // The type of unit aggregation to use for the metric + UnitAggregationType *string `json:"unitAggregationType,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewMetricV2Rep instantiates a new MetricV2Rep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetricV2Rep(key string, name string, kind string, links map[string]Link) *MetricV2Rep { + this := MetricV2Rep{} + this.Key = key + this.Name = name + this.Kind = kind + this.Links = links + return &this +} + +// NewMetricV2RepWithDefaults instantiates a new MetricV2Rep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricV2RepWithDefaults() *MetricV2Rep { + this := MetricV2Rep{} + return &this +} + +// GetKey returns the Key field value +func (o *MetricV2Rep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MetricV2Rep) SetKey(v string) { + o.Key = v +} + +// GetVersionId returns the VersionId field value if set, zero value otherwise. +func (o *MetricV2Rep) GetVersionId() string { + if o == nil || o.VersionId == nil { + var ret string + return ret + } + return *o.VersionId +} + +// GetVersionIdOk returns a tuple with the VersionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetVersionIdOk() (*string, bool) { + if o == nil || o.VersionId == nil { + return nil, false + } + return o.VersionId, true +} + +// HasVersionId returns a boolean if a field has been set. +func (o *MetricV2Rep) HasVersionId() bool { + if o != nil && o.VersionId != nil { + return true + } + + return false +} + +// SetVersionId gets a reference to the given string and assigns it to the VersionId field. +func (o *MetricV2Rep) SetVersionId(v string) { + o.VersionId = &v +} + +// GetName returns the Name field value +func (o *MetricV2Rep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MetricV2Rep) SetName(v string) { + o.Name = v +} + +// GetKind returns the Kind field value +func (o *MetricV2Rep) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *MetricV2Rep) SetKind(v string) { + o.Kind = v +} + +// GetIsNumeric returns the IsNumeric field value if set, zero value otherwise. +func (o *MetricV2Rep) GetIsNumeric() bool { + if o == nil || o.IsNumeric == nil { + var ret bool + return ret + } + return *o.IsNumeric +} + +// GetIsNumericOk returns a tuple with the IsNumeric field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetIsNumericOk() (*bool, bool) { + if o == nil || o.IsNumeric == nil { + return nil, false + } + return o.IsNumeric, true +} + +// HasIsNumeric returns a boolean if a field has been set. +func (o *MetricV2Rep) HasIsNumeric() bool { + if o != nil && o.IsNumeric != nil { + return true + } + + return false +} + +// SetIsNumeric gets a reference to the given bool and assigns it to the IsNumeric field. +func (o *MetricV2Rep) SetIsNumeric(v bool) { + o.IsNumeric = &v +} + +// GetUnitAggregationType returns the UnitAggregationType field value if set, zero value otherwise. +func (o *MetricV2Rep) GetUnitAggregationType() string { + if o == nil || o.UnitAggregationType == nil { + var ret string + return ret + } + return *o.UnitAggregationType +} + +// GetUnitAggregationTypeOk returns a tuple with the UnitAggregationType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetUnitAggregationTypeOk() (*string, bool) { + if o == nil || o.UnitAggregationType == nil { + return nil, false + } + return o.UnitAggregationType, true +} + +// HasUnitAggregationType returns a boolean if a field has been set. +func (o *MetricV2Rep) HasUnitAggregationType() bool { + if o != nil && o.UnitAggregationType != nil { + return true + } + + return false +} + +// SetUnitAggregationType gets a reference to the given string and assigns it to the UnitAggregationType field. +func (o *MetricV2Rep) SetUnitAggregationType(v string) { + o.UnitAggregationType = &v +} + +// GetLinks returns the Links field value +func (o *MetricV2Rep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MetricV2Rep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MetricV2Rep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o MetricV2Rep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.VersionId != nil { + toSerialize["_versionId"] = o.VersionId + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["kind"] = o.Kind + } + if o.IsNumeric != nil { + toSerialize["isNumeric"] = o.IsNumeric + } + if o.UnitAggregationType != nil { + toSerialize["unitAggregationType"] = o.UnitAggregationType + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableMetricV2Rep struct { + value *MetricV2Rep + isSet bool +} + +func (v NullableMetricV2Rep) Get() *MetricV2Rep { + return v.value +} + +func (v *NullableMetricV2Rep) Set(val *MetricV2Rep) { + v.value = val + v.isSet = true +} + +func (v NullableMetricV2Rep) IsSet() bool { + return v.isSet +} + +func (v *NullableMetricV2Rep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetricV2Rep(val *MetricV2Rep) *NullableMetricV2Rep { + return &NullableMetricV2Rep{value: val, isSet: true} +} + +func (v NullableMetricV2Rep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetricV2Rep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_metrics.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_metrics.go new file mode 100644 index 00000000..d158dc51 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_metrics.go @@ -0,0 +1,558 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Metrics struct for Metrics +type Metrics struct { + InputTokens *int32 `json:"inputTokens,omitempty"` + OutputTokens *int32 `json:"outputTokens,omitempty"` + TotalTokens *int32 `json:"totalTokens,omitempty"` + // Number of attempted generations + // Deprecated + GenerationCount *int32 `json:"generationCount,omitempty"` + // Number of successful generations + GenerationSuccessCount *int32 `json:"generationSuccessCount,omitempty"` + // Number of generations with errors + GenerationErrorCount *int32 `json:"generationErrorCount,omitempty"` + ThumbsUp *int32 `json:"thumbsUp,omitempty"` + ThumbsDown *int32 `json:"thumbsDown,omitempty"` + DurationMs *int32 `json:"durationMs,omitempty"` + TimeToFirstTokenMs *int32 `json:"timeToFirstTokenMs,omitempty"` + // A value between 0 and 1 representing satisfaction rating + SatisfactionRating *float32 `json:"satisfactionRating,omitempty"` + // Cost of input tokens in USD + InputCost *float64 `json:"inputCost,omitempty"` + // Cost of output tokens in USD + OutputCost *float64 `json:"outputCost,omitempty"` +} + +// NewMetrics instantiates a new Metrics object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMetrics() *Metrics { + this := Metrics{} + return &this +} + +// NewMetricsWithDefaults instantiates a new Metrics object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMetricsWithDefaults() *Metrics { + this := Metrics{} + return &this +} + +// GetInputTokens returns the InputTokens field value if set, zero value otherwise. +func (o *Metrics) GetInputTokens() int32 { + if o == nil || o.InputTokens == nil { + var ret int32 + return ret + } + return *o.InputTokens +} + +// GetInputTokensOk returns a tuple with the InputTokens field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetInputTokensOk() (*int32, bool) { + if o == nil || o.InputTokens == nil { + return nil, false + } + return o.InputTokens, true +} + +// HasInputTokens returns a boolean if a field has been set. +func (o *Metrics) HasInputTokens() bool { + if o != nil && o.InputTokens != nil { + return true + } + + return false +} + +// SetInputTokens gets a reference to the given int32 and assigns it to the InputTokens field. +func (o *Metrics) SetInputTokens(v int32) { + o.InputTokens = &v +} + +// GetOutputTokens returns the OutputTokens field value if set, zero value otherwise. +func (o *Metrics) GetOutputTokens() int32 { + if o == nil || o.OutputTokens == nil { + var ret int32 + return ret + } + return *o.OutputTokens +} + +// GetOutputTokensOk returns a tuple with the OutputTokens field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetOutputTokensOk() (*int32, bool) { + if o == nil || o.OutputTokens == nil { + return nil, false + } + return o.OutputTokens, true +} + +// HasOutputTokens returns a boolean if a field has been set. +func (o *Metrics) HasOutputTokens() bool { + if o != nil && o.OutputTokens != nil { + return true + } + + return false +} + +// SetOutputTokens gets a reference to the given int32 and assigns it to the OutputTokens field. +func (o *Metrics) SetOutputTokens(v int32) { + o.OutputTokens = &v +} + +// GetTotalTokens returns the TotalTokens field value if set, zero value otherwise. +func (o *Metrics) GetTotalTokens() int32 { + if o == nil || o.TotalTokens == nil { + var ret int32 + return ret + } + return *o.TotalTokens +} + +// GetTotalTokensOk returns a tuple with the TotalTokens field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetTotalTokensOk() (*int32, bool) { + if o == nil || o.TotalTokens == nil { + return nil, false + } + return o.TotalTokens, true +} + +// HasTotalTokens returns a boolean if a field has been set. +func (o *Metrics) HasTotalTokens() bool { + if o != nil && o.TotalTokens != nil { + return true + } + + return false +} + +// SetTotalTokens gets a reference to the given int32 and assigns it to the TotalTokens field. +func (o *Metrics) SetTotalTokens(v int32) { + o.TotalTokens = &v +} + +// GetGenerationCount returns the GenerationCount field value if set, zero value otherwise. +// Deprecated +func (o *Metrics) GetGenerationCount() int32 { + if o == nil || o.GenerationCount == nil { + var ret int32 + return ret + } + return *o.GenerationCount +} + +// GetGenerationCountOk returns a tuple with the GenerationCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *Metrics) GetGenerationCountOk() (*int32, bool) { + if o == nil || o.GenerationCount == nil { + return nil, false + } + return o.GenerationCount, true +} + +// HasGenerationCount returns a boolean if a field has been set. +func (o *Metrics) HasGenerationCount() bool { + if o != nil && o.GenerationCount != nil { + return true + } + + return false +} + +// SetGenerationCount gets a reference to the given int32 and assigns it to the GenerationCount field. +// Deprecated +func (o *Metrics) SetGenerationCount(v int32) { + o.GenerationCount = &v +} + +// GetGenerationSuccessCount returns the GenerationSuccessCount field value if set, zero value otherwise. +func (o *Metrics) GetGenerationSuccessCount() int32 { + if o == nil || o.GenerationSuccessCount == nil { + var ret int32 + return ret + } + return *o.GenerationSuccessCount +} + +// GetGenerationSuccessCountOk returns a tuple with the GenerationSuccessCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetGenerationSuccessCountOk() (*int32, bool) { + if o == nil || o.GenerationSuccessCount == nil { + return nil, false + } + return o.GenerationSuccessCount, true +} + +// HasGenerationSuccessCount returns a boolean if a field has been set. +func (o *Metrics) HasGenerationSuccessCount() bool { + if o != nil && o.GenerationSuccessCount != nil { + return true + } + + return false +} + +// SetGenerationSuccessCount gets a reference to the given int32 and assigns it to the GenerationSuccessCount field. +func (o *Metrics) SetGenerationSuccessCount(v int32) { + o.GenerationSuccessCount = &v +} + +// GetGenerationErrorCount returns the GenerationErrorCount field value if set, zero value otherwise. +func (o *Metrics) GetGenerationErrorCount() int32 { + if o == nil || o.GenerationErrorCount == nil { + var ret int32 + return ret + } + return *o.GenerationErrorCount +} + +// GetGenerationErrorCountOk returns a tuple with the GenerationErrorCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetGenerationErrorCountOk() (*int32, bool) { + if o == nil || o.GenerationErrorCount == nil { + return nil, false + } + return o.GenerationErrorCount, true +} + +// HasGenerationErrorCount returns a boolean if a field has been set. +func (o *Metrics) HasGenerationErrorCount() bool { + if o != nil && o.GenerationErrorCount != nil { + return true + } + + return false +} + +// SetGenerationErrorCount gets a reference to the given int32 and assigns it to the GenerationErrorCount field. +func (o *Metrics) SetGenerationErrorCount(v int32) { + o.GenerationErrorCount = &v +} + +// GetThumbsUp returns the ThumbsUp field value if set, zero value otherwise. +func (o *Metrics) GetThumbsUp() int32 { + if o == nil || o.ThumbsUp == nil { + var ret int32 + return ret + } + return *o.ThumbsUp +} + +// GetThumbsUpOk returns a tuple with the ThumbsUp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetThumbsUpOk() (*int32, bool) { + if o == nil || o.ThumbsUp == nil { + return nil, false + } + return o.ThumbsUp, true +} + +// HasThumbsUp returns a boolean if a field has been set. +func (o *Metrics) HasThumbsUp() bool { + if o != nil && o.ThumbsUp != nil { + return true + } + + return false +} + +// SetThumbsUp gets a reference to the given int32 and assigns it to the ThumbsUp field. +func (o *Metrics) SetThumbsUp(v int32) { + o.ThumbsUp = &v +} + +// GetThumbsDown returns the ThumbsDown field value if set, zero value otherwise. +func (o *Metrics) GetThumbsDown() int32 { + if o == nil || o.ThumbsDown == nil { + var ret int32 + return ret + } + return *o.ThumbsDown +} + +// GetThumbsDownOk returns a tuple with the ThumbsDown field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetThumbsDownOk() (*int32, bool) { + if o == nil || o.ThumbsDown == nil { + return nil, false + } + return o.ThumbsDown, true +} + +// HasThumbsDown returns a boolean if a field has been set. +func (o *Metrics) HasThumbsDown() bool { + if o != nil && o.ThumbsDown != nil { + return true + } + + return false +} + +// SetThumbsDown gets a reference to the given int32 and assigns it to the ThumbsDown field. +func (o *Metrics) SetThumbsDown(v int32) { + o.ThumbsDown = &v +} + +// GetDurationMs returns the DurationMs field value if set, zero value otherwise. +func (o *Metrics) GetDurationMs() int32 { + if o == nil || o.DurationMs == nil { + var ret int32 + return ret + } + return *o.DurationMs +} + +// GetDurationMsOk returns a tuple with the DurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetDurationMsOk() (*int32, bool) { + if o == nil || o.DurationMs == nil { + return nil, false + } + return o.DurationMs, true +} + +// HasDurationMs returns a boolean if a field has been set. +func (o *Metrics) HasDurationMs() bool { + if o != nil && o.DurationMs != nil { + return true + } + + return false +} + +// SetDurationMs gets a reference to the given int32 and assigns it to the DurationMs field. +func (o *Metrics) SetDurationMs(v int32) { + o.DurationMs = &v +} + +// GetTimeToFirstTokenMs returns the TimeToFirstTokenMs field value if set, zero value otherwise. +func (o *Metrics) GetTimeToFirstTokenMs() int32 { + if o == nil || o.TimeToFirstTokenMs == nil { + var ret int32 + return ret + } + return *o.TimeToFirstTokenMs +} + +// GetTimeToFirstTokenMsOk returns a tuple with the TimeToFirstTokenMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetTimeToFirstTokenMsOk() (*int32, bool) { + if o == nil || o.TimeToFirstTokenMs == nil { + return nil, false + } + return o.TimeToFirstTokenMs, true +} + +// HasTimeToFirstTokenMs returns a boolean if a field has been set. +func (o *Metrics) HasTimeToFirstTokenMs() bool { + if o != nil && o.TimeToFirstTokenMs != nil { + return true + } + + return false +} + +// SetTimeToFirstTokenMs gets a reference to the given int32 and assigns it to the TimeToFirstTokenMs field. +func (o *Metrics) SetTimeToFirstTokenMs(v int32) { + o.TimeToFirstTokenMs = &v +} + +// GetSatisfactionRating returns the SatisfactionRating field value if set, zero value otherwise. +func (o *Metrics) GetSatisfactionRating() float32 { + if o == nil || o.SatisfactionRating == nil { + var ret float32 + return ret + } + return *o.SatisfactionRating +} + +// GetSatisfactionRatingOk returns a tuple with the SatisfactionRating field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetSatisfactionRatingOk() (*float32, bool) { + if o == nil || o.SatisfactionRating == nil { + return nil, false + } + return o.SatisfactionRating, true +} + +// HasSatisfactionRating returns a boolean if a field has been set. +func (o *Metrics) HasSatisfactionRating() bool { + if o != nil && o.SatisfactionRating != nil { + return true + } + + return false +} + +// SetSatisfactionRating gets a reference to the given float32 and assigns it to the SatisfactionRating field. +func (o *Metrics) SetSatisfactionRating(v float32) { + o.SatisfactionRating = &v +} + +// GetInputCost returns the InputCost field value if set, zero value otherwise. +func (o *Metrics) GetInputCost() float64 { + if o == nil || o.InputCost == nil { + var ret float64 + return ret + } + return *o.InputCost +} + +// GetInputCostOk returns a tuple with the InputCost field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetInputCostOk() (*float64, bool) { + if o == nil || o.InputCost == nil { + return nil, false + } + return o.InputCost, true +} + +// HasInputCost returns a boolean if a field has been set. +func (o *Metrics) HasInputCost() bool { + if o != nil && o.InputCost != nil { + return true + } + + return false +} + +// SetInputCost gets a reference to the given float64 and assigns it to the InputCost field. +func (o *Metrics) SetInputCost(v float64) { + o.InputCost = &v +} + +// GetOutputCost returns the OutputCost field value if set, zero value otherwise. +func (o *Metrics) GetOutputCost() float64 { + if o == nil || o.OutputCost == nil { + var ret float64 + return ret + } + return *o.OutputCost +} + +// GetOutputCostOk returns a tuple with the OutputCost field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Metrics) GetOutputCostOk() (*float64, bool) { + if o == nil || o.OutputCost == nil { + return nil, false + } + return o.OutputCost, true +} + +// HasOutputCost returns a boolean if a field has been set. +func (o *Metrics) HasOutputCost() bool { + if o != nil && o.OutputCost != nil { + return true + } + + return false +} + +// SetOutputCost gets a reference to the given float64 and assigns it to the OutputCost field. +func (o *Metrics) SetOutputCost(v float64) { + o.OutputCost = &v +} + +func (o Metrics) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.InputTokens != nil { + toSerialize["inputTokens"] = o.InputTokens + } + if o.OutputTokens != nil { + toSerialize["outputTokens"] = o.OutputTokens + } + if o.TotalTokens != nil { + toSerialize["totalTokens"] = o.TotalTokens + } + if o.GenerationCount != nil { + toSerialize["generationCount"] = o.GenerationCount + } + if o.GenerationSuccessCount != nil { + toSerialize["generationSuccessCount"] = o.GenerationSuccessCount + } + if o.GenerationErrorCount != nil { + toSerialize["generationErrorCount"] = o.GenerationErrorCount + } + if o.ThumbsUp != nil { + toSerialize["thumbsUp"] = o.ThumbsUp + } + if o.ThumbsDown != nil { + toSerialize["thumbsDown"] = o.ThumbsDown + } + if o.DurationMs != nil { + toSerialize["durationMs"] = o.DurationMs + } + if o.TimeToFirstTokenMs != nil { + toSerialize["timeToFirstTokenMs"] = o.TimeToFirstTokenMs + } + if o.SatisfactionRating != nil { + toSerialize["satisfactionRating"] = o.SatisfactionRating + } + if o.InputCost != nil { + toSerialize["inputCost"] = o.InputCost + } + if o.OutputCost != nil { + toSerialize["outputCost"] = o.OutputCost + } + return json.Marshal(toSerialize) +} + +type NullableMetrics struct { + value *Metrics + isSet bool +} + +func (v NullableMetrics) Get() *Metrics { + return v.value +} + +func (v *NullableMetrics) Set(val *Metrics) { + v.value = val + v.isSet = true +} + +func (v NullableMetrics) IsSet() bool { + return v.isSet +} + +func (v *NullableMetrics) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMetrics(val *Metrics) *NullableMetrics { + return &NullableMetrics{value: val, isSet: true} +} + +func (v NullableMetrics) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMetrics) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_safety_issue_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_safety_issue_rep.go new file mode 100644 index 00000000..3cc77e7d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_safety_issue_rep.go @@ -0,0 +1,228 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MigrationSafetyIssueRep struct for MigrationSafetyIssueRep +type MigrationSafetyIssueRep struct { + // The ID of the rule which caused this issue + CausingRuleId *string `json:"causingRuleId,omitempty"` + // A list of the IDs of the rules which are affected by this issue. fallthrough is a sentinel value for the default rule. + AffectedRuleIds []string `json:"affectedRuleIds,omitempty"` + // A description of the issue that causingRuleId has caused for affectedRuleIds. + Issue *string `json:"issue,omitempty"` + // Whether the changes caused by causingRuleId bring inconsistency to the old system + OldSystemAffected *bool `json:"oldSystemAffected,omitempty"` +} + +// NewMigrationSafetyIssueRep instantiates a new MigrationSafetyIssueRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMigrationSafetyIssueRep() *MigrationSafetyIssueRep { + this := MigrationSafetyIssueRep{} + return &this +} + +// NewMigrationSafetyIssueRepWithDefaults instantiates a new MigrationSafetyIssueRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMigrationSafetyIssueRepWithDefaults() *MigrationSafetyIssueRep { + this := MigrationSafetyIssueRep{} + return &this +} + +// GetCausingRuleId returns the CausingRuleId field value if set, zero value otherwise. +func (o *MigrationSafetyIssueRep) GetCausingRuleId() string { + if o == nil || o.CausingRuleId == nil { + var ret string + return ret + } + return *o.CausingRuleId +} + +// GetCausingRuleIdOk returns a tuple with the CausingRuleId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MigrationSafetyIssueRep) GetCausingRuleIdOk() (*string, bool) { + if o == nil || o.CausingRuleId == nil { + return nil, false + } + return o.CausingRuleId, true +} + +// HasCausingRuleId returns a boolean if a field has been set. +func (o *MigrationSafetyIssueRep) HasCausingRuleId() bool { + if o != nil && o.CausingRuleId != nil { + return true + } + + return false +} + +// SetCausingRuleId gets a reference to the given string and assigns it to the CausingRuleId field. +func (o *MigrationSafetyIssueRep) SetCausingRuleId(v string) { + o.CausingRuleId = &v +} + +// GetAffectedRuleIds returns the AffectedRuleIds field value if set, zero value otherwise. +func (o *MigrationSafetyIssueRep) GetAffectedRuleIds() []string { + if o == nil || o.AffectedRuleIds == nil { + var ret []string + return ret + } + return o.AffectedRuleIds +} + +// GetAffectedRuleIdsOk returns a tuple with the AffectedRuleIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MigrationSafetyIssueRep) GetAffectedRuleIdsOk() ([]string, bool) { + if o == nil || o.AffectedRuleIds == nil { + return nil, false + } + return o.AffectedRuleIds, true +} + +// HasAffectedRuleIds returns a boolean if a field has been set. +func (o *MigrationSafetyIssueRep) HasAffectedRuleIds() bool { + if o != nil && o.AffectedRuleIds != nil { + return true + } + + return false +} + +// SetAffectedRuleIds gets a reference to the given []string and assigns it to the AffectedRuleIds field. +func (o *MigrationSafetyIssueRep) SetAffectedRuleIds(v []string) { + o.AffectedRuleIds = v +} + +// GetIssue returns the Issue field value if set, zero value otherwise. +func (o *MigrationSafetyIssueRep) GetIssue() string { + if o == nil || o.Issue == nil { + var ret string + return ret + } + return *o.Issue +} + +// GetIssueOk returns a tuple with the Issue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MigrationSafetyIssueRep) GetIssueOk() (*string, bool) { + if o == nil || o.Issue == nil { + return nil, false + } + return o.Issue, true +} + +// HasIssue returns a boolean if a field has been set. +func (o *MigrationSafetyIssueRep) HasIssue() bool { + if o != nil && o.Issue != nil { + return true + } + + return false +} + +// SetIssue gets a reference to the given string and assigns it to the Issue field. +func (o *MigrationSafetyIssueRep) SetIssue(v string) { + o.Issue = &v +} + +// GetOldSystemAffected returns the OldSystemAffected field value if set, zero value otherwise. +func (o *MigrationSafetyIssueRep) GetOldSystemAffected() bool { + if o == nil || o.OldSystemAffected == nil { + var ret bool + return ret + } + return *o.OldSystemAffected +} + +// GetOldSystemAffectedOk returns a tuple with the OldSystemAffected field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MigrationSafetyIssueRep) GetOldSystemAffectedOk() (*bool, bool) { + if o == nil || o.OldSystemAffected == nil { + return nil, false + } + return o.OldSystemAffected, true +} + +// HasOldSystemAffected returns a boolean if a field has been set. +func (o *MigrationSafetyIssueRep) HasOldSystemAffected() bool { + if o != nil && o.OldSystemAffected != nil { + return true + } + + return false +} + +// SetOldSystemAffected gets a reference to the given bool and assigns it to the OldSystemAffected field. +func (o *MigrationSafetyIssueRep) SetOldSystemAffected(v bool) { + o.OldSystemAffected = &v +} + +func (o MigrationSafetyIssueRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.CausingRuleId != nil { + toSerialize["causingRuleId"] = o.CausingRuleId + } + if o.AffectedRuleIds != nil { + toSerialize["affectedRuleIds"] = o.AffectedRuleIds + } + if o.Issue != nil { + toSerialize["issue"] = o.Issue + } + if o.OldSystemAffected != nil { + toSerialize["oldSystemAffected"] = o.OldSystemAffected + } + return json.Marshal(toSerialize) +} + +type NullableMigrationSafetyIssueRep struct { + value *MigrationSafetyIssueRep + isSet bool +} + +func (v NullableMigrationSafetyIssueRep) Get() *MigrationSafetyIssueRep { + return v.value +} + +func (v *NullableMigrationSafetyIssueRep) Set(val *MigrationSafetyIssueRep) { + v.value = val + v.isSet = true +} + +func (v NullableMigrationSafetyIssueRep) IsSet() bool { + return v.isSet +} + +func (v *NullableMigrationSafetyIssueRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMigrationSafetyIssueRep(val *MigrationSafetyIssueRep) *NullableMigrationSafetyIssueRep { + return &NullableMigrationSafetyIssueRep{value: val, isSet: true} +} + +func (v NullableMigrationSafetyIssueRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMigrationSafetyIssueRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_settings_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_settings_post.go new file mode 100644 index 00000000..ab805891 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_migration_settings_post.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MigrationSettingsPost struct for MigrationSettingsPost +type MigrationSettingsPost struct { + // Context kind for a migration with 6 stages, where data is being moved + ContextKind *string `json:"contextKind,omitempty"` + StageCount int32 `json:"stageCount"` +} + +// NewMigrationSettingsPost instantiates a new MigrationSettingsPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMigrationSettingsPost(stageCount int32) *MigrationSettingsPost { + this := MigrationSettingsPost{} + this.StageCount = stageCount + return &this +} + +// NewMigrationSettingsPostWithDefaults instantiates a new MigrationSettingsPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMigrationSettingsPostWithDefaults() *MigrationSettingsPost { + this := MigrationSettingsPost{} + return &this +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *MigrationSettingsPost) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MigrationSettingsPost) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *MigrationSettingsPost) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *MigrationSettingsPost) SetContextKind(v string) { + o.ContextKind = &v +} + +// GetStageCount returns the StageCount field value +func (o *MigrationSettingsPost) GetStageCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.StageCount +} + +// GetStageCountOk returns a tuple with the StageCount field value +// and a boolean to check if the value has been set. +func (o *MigrationSettingsPost) GetStageCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.StageCount, true +} + +// SetStageCount sets field value +func (o *MigrationSettingsPost) SetStageCount(v int32) { + o.StageCount = v +} + +func (o MigrationSettingsPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + if true { + toSerialize["stageCount"] = o.StageCount + } + return json.Marshal(toSerialize) +} + +type NullableMigrationSettingsPost struct { + value *MigrationSettingsPost + isSet bool +} + +func (v NullableMigrationSettingsPost) Get() *MigrationSettingsPost { + return v.value +} + +func (v *NullableMigrationSettingsPost) Set(val *MigrationSettingsPost) { + v.value = val + v.isSet = true +} + +func (v NullableMigrationSettingsPost) IsSet() bool { + return v.isSet +} + +func (v *NullableMigrationSettingsPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMigrationSettingsPost(val *MigrationSettingsPost) *NullableMigrationSettingsPost { + return &NullableMigrationSettingsPost{value: val, isSet: true} +} + +func (v NullableMigrationSettingsPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMigrationSettingsPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config.go new file mode 100644 index 00000000..16f35024 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config.go @@ -0,0 +1,514 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ModelConfig struct for ModelConfig +type ModelConfig struct { + Access *AiConfigsAccess `json:"_access,omitempty"` + // Human readable name of the model + Name string `json:"name"` + // Unique key for the model + Key string `json:"key"` + // Identifier for the model, for use with third party providers + Id string `json:"id"` + // Icon for the model + Icon *string `json:"icon,omitempty"` + // Provider for the model + Provider *string `json:"provider,omitempty"` + // Whether the model is global + Global bool `json:"global"` + Params map[string]interface{} `json:"params,omitempty"` + CustomParams map[string]interface{} `json:"customParams,omitempty"` + Tags []string `json:"tags"` + Version int32 `json:"version"` + // Cost per input token in USD + CostPerInputToken *float64 `json:"costPerInputToken,omitempty"` + // Cost per output token in USD + CostPerOutputToken *float64 `json:"costPerOutputToken,omitempty"` +} + +// NewModelConfig instantiates a new ModelConfig object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewModelConfig(name string, key string, id string, global bool, tags []string, version int32) *ModelConfig { + this := ModelConfig{} + this.Name = name + this.Key = key + this.Id = id + this.Global = global + this.Tags = tags + this.Version = version + return &this +} + +// NewModelConfigWithDefaults instantiates a new ModelConfig object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewModelConfigWithDefaults() *ModelConfig { + this := ModelConfig{} + return &this +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ModelConfig) GetAccess() AiConfigsAccess { + if o == nil || o.Access == nil { + var ret AiConfigsAccess + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetAccessOk() (*AiConfigsAccess, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ModelConfig) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given AiConfigsAccess and assigns it to the Access field. +func (o *ModelConfig) SetAccess(v AiConfigsAccess) { + o.Access = &v +} + +// GetName returns the Name field value +func (o *ModelConfig) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ModelConfig) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *ModelConfig) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ModelConfig) SetKey(v string) { + o.Key = v +} + +// GetId returns the Id field value +func (o *ModelConfig) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ModelConfig) SetId(v string) { + o.Id = v +} + +// GetIcon returns the Icon field value if set, zero value otherwise. +func (o *ModelConfig) GetIcon() string { + if o == nil || o.Icon == nil { + var ret string + return ret + } + return *o.Icon +} + +// GetIconOk returns a tuple with the Icon field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetIconOk() (*string, bool) { + if o == nil || o.Icon == nil { + return nil, false + } + return o.Icon, true +} + +// HasIcon returns a boolean if a field has been set. +func (o *ModelConfig) HasIcon() bool { + if o != nil && o.Icon != nil { + return true + } + + return false +} + +// SetIcon gets a reference to the given string and assigns it to the Icon field. +func (o *ModelConfig) SetIcon(v string) { + o.Icon = &v +} + +// GetProvider returns the Provider field value if set, zero value otherwise. +func (o *ModelConfig) GetProvider() string { + if o == nil || o.Provider == nil { + var ret string + return ret + } + return *o.Provider +} + +// GetProviderOk returns a tuple with the Provider field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetProviderOk() (*string, bool) { + if o == nil || o.Provider == nil { + return nil, false + } + return o.Provider, true +} + +// HasProvider returns a boolean if a field has been set. +func (o *ModelConfig) HasProvider() bool { + if o != nil && o.Provider != nil { + return true + } + + return false +} + +// SetProvider gets a reference to the given string and assigns it to the Provider field. +func (o *ModelConfig) SetProvider(v string) { + o.Provider = &v +} + +// GetGlobal returns the Global field value +func (o *ModelConfig) GetGlobal() bool { + if o == nil { + var ret bool + return ret + } + + return o.Global +} + +// GetGlobalOk returns a tuple with the Global field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetGlobalOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Global, true +} + +// SetGlobal sets field value +func (o *ModelConfig) SetGlobal(v bool) { + o.Global = v +} + +// GetParams returns the Params field value if set, zero value otherwise. +func (o *ModelConfig) GetParams() map[string]interface{} { + if o == nil || o.Params == nil { + var ret map[string]interface{} + return ret + } + return o.Params +} + +// GetParamsOk returns a tuple with the Params field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetParamsOk() (map[string]interface{}, bool) { + if o == nil || o.Params == nil { + return nil, false + } + return o.Params, true +} + +// HasParams returns a boolean if a field has been set. +func (o *ModelConfig) HasParams() bool { + if o != nil && o.Params != nil { + return true + } + + return false +} + +// SetParams gets a reference to the given map[string]interface{} and assigns it to the Params field. +func (o *ModelConfig) SetParams(v map[string]interface{}) { + o.Params = v +} + +// GetCustomParams returns the CustomParams field value if set, zero value otherwise. +func (o *ModelConfig) GetCustomParams() map[string]interface{} { + if o == nil || o.CustomParams == nil { + var ret map[string]interface{} + return ret + } + return o.CustomParams +} + +// GetCustomParamsOk returns a tuple with the CustomParams field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetCustomParamsOk() (map[string]interface{}, bool) { + if o == nil || o.CustomParams == nil { + return nil, false + } + return o.CustomParams, true +} + +// HasCustomParams returns a boolean if a field has been set. +func (o *ModelConfig) HasCustomParams() bool { + if o != nil && o.CustomParams != nil { + return true + } + + return false +} + +// SetCustomParams gets a reference to the given map[string]interface{} and assigns it to the CustomParams field. +func (o *ModelConfig) SetCustomParams(v map[string]interface{}) { + o.CustomParams = v +} + +// GetTags returns the Tags field value +func (o *ModelConfig) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *ModelConfig) SetTags(v []string) { + o.Tags = v +} + +// GetVersion returns the Version field value +func (o *ModelConfig) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *ModelConfig) SetVersion(v int32) { + o.Version = v +} + +// GetCostPerInputToken returns the CostPerInputToken field value if set, zero value otherwise. +func (o *ModelConfig) GetCostPerInputToken() float64 { + if o == nil || o.CostPerInputToken == nil { + var ret float64 + return ret + } + return *o.CostPerInputToken +} + +// GetCostPerInputTokenOk returns a tuple with the CostPerInputToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetCostPerInputTokenOk() (*float64, bool) { + if o == nil || o.CostPerInputToken == nil { + return nil, false + } + return o.CostPerInputToken, true +} + +// HasCostPerInputToken returns a boolean if a field has been set. +func (o *ModelConfig) HasCostPerInputToken() bool { + if o != nil && o.CostPerInputToken != nil { + return true + } + + return false +} + +// SetCostPerInputToken gets a reference to the given float64 and assigns it to the CostPerInputToken field. +func (o *ModelConfig) SetCostPerInputToken(v float64) { + o.CostPerInputToken = &v +} + +// GetCostPerOutputToken returns the CostPerOutputToken field value if set, zero value otherwise. +func (o *ModelConfig) GetCostPerOutputToken() float64 { + if o == nil || o.CostPerOutputToken == nil { + var ret float64 + return ret + } + return *o.CostPerOutputToken +} + +// GetCostPerOutputTokenOk returns a tuple with the CostPerOutputToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfig) GetCostPerOutputTokenOk() (*float64, bool) { + if o == nil || o.CostPerOutputToken == nil { + return nil, false + } + return o.CostPerOutputToken, true +} + +// HasCostPerOutputToken returns a boolean if a field has been set. +func (o *ModelConfig) HasCostPerOutputToken() bool { + if o != nil && o.CostPerOutputToken != nil { + return true + } + + return false +} + +// SetCostPerOutputToken gets a reference to the given float64 and assigns it to the CostPerOutputToken field. +func (o *ModelConfig) SetCostPerOutputToken(v float64) { + o.CostPerOutputToken = &v +} + +func (o ModelConfig) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["id"] = o.Id + } + if o.Icon != nil { + toSerialize["icon"] = o.Icon + } + if o.Provider != nil { + toSerialize["provider"] = o.Provider + } + if true { + toSerialize["global"] = o.Global + } + if o.Params != nil { + toSerialize["params"] = o.Params + } + if o.CustomParams != nil { + toSerialize["customParams"] = o.CustomParams + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["version"] = o.Version + } + if o.CostPerInputToken != nil { + toSerialize["costPerInputToken"] = o.CostPerInputToken + } + if o.CostPerOutputToken != nil { + toSerialize["costPerOutputToken"] = o.CostPerOutputToken + } + return json.Marshal(toSerialize) +} + +type NullableModelConfig struct { + value *ModelConfig + isSet bool +} + +func (v NullableModelConfig) Get() *ModelConfig { + return v.value +} + +func (v *NullableModelConfig) Set(val *ModelConfig) { + v.value = val + v.isSet = true +} + +func (v NullableModelConfig) IsSet() bool { + return v.isSet +} + +func (v *NullableModelConfig) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableModelConfig(val *ModelConfig) *NullableModelConfig { + return &NullableModelConfig{value: val, isSet: true} +} + +func (v NullableModelConfig) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableModelConfig) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config_post.go new file mode 100644 index 00000000..07e18126 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_model_config_post.go @@ -0,0 +1,426 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ModelConfigPost struct for ModelConfigPost +type ModelConfigPost struct { + // Human readable name of the model + Name string `json:"name"` + // Unique key for the model + Key string `json:"key"` + // Identifier for the model, for use with third party providers + Id string `json:"id"` + // Icon for the model + Icon *string `json:"icon,omitempty"` + // Provider for the model + Provider *string `json:"provider,omitempty"` + Params map[string]interface{} `json:"params,omitempty"` + CustomParams map[string]interface{} `json:"customParams,omitempty"` + Tags []string `json:"tags,omitempty"` + // Cost per input token in USD + CostPerInputToken *float64 `json:"costPerInputToken,omitempty"` + // Cost per output token in USD + CostPerOutputToken *float64 `json:"costPerOutputToken,omitempty"` +} + +// NewModelConfigPost instantiates a new ModelConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewModelConfigPost(name string, key string, id string) *ModelConfigPost { + this := ModelConfigPost{} + this.Name = name + this.Key = key + this.Id = id + return &this +} + +// NewModelConfigPostWithDefaults instantiates a new ModelConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewModelConfigPostWithDefaults() *ModelConfigPost { + this := ModelConfigPost{} + return &this +} + +// GetName returns the Name field value +func (o *ModelConfigPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ModelConfigPost) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *ModelConfigPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ModelConfigPost) SetKey(v string) { + o.Key = v +} + +// GetId returns the Id field value +func (o *ModelConfigPost) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ModelConfigPost) SetId(v string) { + o.Id = v +} + +// GetIcon returns the Icon field value if set, zero value otherwise. +func (o *ModelConfigPost) GetIcon() string { + if o == nil || o.Icon == nil { + var ret string + return ret + } + return *o.Icon +} + +// GetIconOk returns a tuple with the Icon field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetIconOk() (*string, bool) { + if o == nil || o.Icon == nil { + return nil, false + } + return o.Icon, true +} + +// HasIcon returns a boolean if a field has been set. +func (o *ModelConfigPost) HasIcon() bool { + if o != nil && o.Icon != nil { + return true + } + + return false +} + +// SetIcon gets a reference to the given string and assigns it to the Icon field. +func (o *ModelConfigPost) SetIcon(v string) { + o.Icon = &v +} + +// GetProvider returns the Provider field value if set, zero value otherwise. +func (o *ModelConfigPost) GetProvider() string { + if o == nil || o.Provider == nil { + var ret string + return ret + } + return *o.Provider +} + +// GetProviderOk returns a tuple with the Provider field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetProviderOk() (*string, bool) { + if o == nil || o.Provider == nil { + return nil, false + } + return o.Provider, true +} + +// HasProvider returns a boolean if a field has been set. +func (o *ModelConfigPost) HasProvider() bool { + if o != nil && o.Provider != nil { + return true + } + + return false +} + +// SetProvider gets a reference to the given string and assigns it to the Provider field. +func (o *ModelConfigPost) SetProvider(v string) { + o.Provider = &v +} + +// GetParams returns the Params field value if set, zero value otherwise. +func (o *ModelConfigPost) GetParams() map[string]interface{} { + if o == nil || o.Params == nil { + var ret map[string]interface{} + return ret + } + return o.Params +} + +// GetParamsOk returns a tuple with the Params field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetParamsOk() (map[string]interface{}, bool) { + if o == nil || o.Params == nil { + return nil, false + } + return o.Params, true +} + +// HasParams returns a boolean if a field has been set. +func (o *ModelConfigPost) HasParams() bool { + if o != nil && o.Params != nil { + return true + } + + return false +} + +// SetParams gets a reference to the given map[string]interface{} and assigns it to the Params field. +func (o *ModelConfigPost) SetParams(v map[string]interface{}) { + o.Params = v +} + +// GetCustomParams returns the CustomParams field value if set, zero value otherwise. +func (o *ModelConfigPost) GetCustomParams() map[string]interface{} { + if o == nil || o.CustomParams == nil { + var ret map[string]interface{} + return ret + } + return o.CustomParams +} + +// GetCustomParamsOk returns a tuple with the CustomParams field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetCustomParamsOk() (map[string]interface{}, bool) { + if o == nil || o.CustomParams == nil { + return nil, false + } + return o.CustomParams, true +} + +// HasCustomParams returns a boolean if a field has been set. +func (o *ModelConfigPost) HasCustomParams() bool { + if o != nil && o.CustomParams != nil { + return true + } + + return false +} + +// SetCustomParams gets a reference to the given map[string]interface{} and assigns it to the CustomParams field. +func (o *ModelConfigPost) SetCustomParams(v map[string]interface{}) { + o.CustomParams = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *ModelConfigPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *ModelConfigPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *ModelConfigPost) SetTags(v []string) { + o.Tags = v +} + +// GetCostPerInputToken returns the CostPerInputToken field value if set, zero value otherwise. +func (o *ModelConfigPost) GetCostPerInputToken() float64 { + if o == nil || o.CostPerInputToken == nil { + var ret float64 + return ret + } + return *o.CostPerInputToken +} + +// GetCostPerInputTokenOk returns a tuple with the CostPerInputToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetCostPerInputTokenOk() (*float64, bool) { + if o == nil || o.CostPerInputToken == nil { + return nil, false + } + return o.CostPerInputToken, true +} + +// HasCostPerInputToken returns a boolean if a field has been set. +func (o *ModelConfigPost) HasCostPerInputToken() bool { + if o != nil && o.CostPerInputToken != nil { + return true + } + + return false +} + +// SetCostPerInputToken gets a reference to the given float64 and assigns it to the CostPerInputToken field. +func (o *ModelConfigPost) SetCostPerInputToken(v float64) { + o.CostPerInputToken = &v +} + +// GetCostPerOutputToken returns the CostPerOutputToken field value if set, zero value otherwise. +func (o *ModelConfigPost) GetCostPerOutputToken() float64 { + if o == nil || o.CostPerOutputToken == nil { + var ret float64 + return ret + } + return *o.CostPerOutputToken +} + +// GetCostPerOutputTokenOk returns a tuple with the CostPerOutputToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ModelConfigPost) GetCostPerOutputTokenOk() (*float64, bool) { + if o == nil || o.CostPerOutputToken == nil { + return nil, false + } + return o.CostPerOutputToken, true +} + +// HasCostPerOutputToken returns a boolean if a field has been set. +func (o *ModelConfigPost) HasCostPerOutputToken() bool { + if o != nil && o.CostPerOutputToken != nil { + return true + } + + return false +} + +// SetCostPerOutputToken gets a reference to the given float64 and assigns it to the CostPerOutputToken field. +func (o *ModelConfigPost) SetCostPerOutputToken(v float64) { + o.CostPerOutputToken = &v +} + +func (o ModelConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["id"] = o.Id + } + if o.Icon != nil { + toSerialize["icon"] = o.Icon + } + if o.Provider != nil { + toSerialize["provider"] = o.Provider + } + if o.Params != nil { + toSerialize["params"] = o.Params + } + if o.CustomParams != nil { + toSerialize["customParams"] = o.CustomParams + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.CostPerInputToken != nil { + toSerialize["costPerInputToken"] = o.CostPerInputToken + } + if o.CostPerOutputToken != nil { + toSerialize["costPerOutputToken"] = o.CostPerOutputToken + } + return json.Marshal(toSerialize) +} + +type NullableModelConfigPost struct { + value *ModelConfigPost + isSet bool +} + +func (v NullableModelConfigPost) Get() *ModelConfigPost { + return v.value +} + +func (v *NullableModelConfigPost) Set(val *ModelConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableModelConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableModelConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableModelConfigPost(val *ModelConfigPost) *NullableModelConfigPost { + return &NullableModelConfigPost{value: val, isSet: true} +} + +func (v NullableModelConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableModelConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_modification.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_modification.go new file mode 100644 index 00000000..e23706e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_modification.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// Modification struct for Modification +type Modification struct { + Date *time.Time `json:"date,omitempty"` +} + +// NewModification instantiates a new Modification object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewModification() *Modification { + this := Modification{} + return &this +} + +// NewModificationWithDefaults instantiates a new Modification object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewModificationWithDefaults() *Modification { + this := Modification{} + return &this +} + +// GetDate returns the Date field value if set, zero value otherwise. +func (o *Modification) GetDate() time.Time { + if o == nil || o.Date == nil { + var ret time.Time + return ret + } + return *o.Date +} + +// GetDateOk returns a tuple with the Date field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Modification) GetDateOk() (*time.Time, bool) { + if o == nil || o.Date == nil { + return nil, false + } + return o.Date, true +} + +// HasDate returns a boolean if a field has been set. +func (o *Modification) HasDate() bool { + if o != nil && o.Date != nil { + return true + } + + return false +} + +// SetDate gets a reference to the given time.Time and assigns it to the Date field. +func (o *Modification) SetDate(v time.Time) { + o.Date = &v +} + +func (o Modification) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Date != nil { + toSerialize["date"] = o.Date + } + return json.Marshal(toSerialize) +} + +type NullableModification struct { + value *Modification + isSet bool +} + +func (v NullableModification) Get() *Modification { + return v.value +} + +func (v *NullableModification) Set(val *Modification) { + v.value = val + v.isSet = true +} + +func (v NullableModification) IsSet() bool { + return v.isSet +} + +func (v *NullableModification) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableModification(val *Modification) *NullableModification { + return &NullableModification{value: val, isSet: true} +} + +func (v NullableModification) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableModification) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flag.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flag.go new file mode 100644 index 00000000..771f6b20 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flag.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MultiEnvironmentDependentFlag struct for MultiEnvironmentDependentFlag +type MultiEnvironmentDependentFlag struct { + // The flag name + Name *string `json:"name,omitempty"` + // The flag key + Key string `json:"key"` + // A list of environments in which the dependent flag appears + Environments []DependentFlagEnvironment `json:"environments"` +} + +// NewMultiEnvironmentDependentFlag instantiates a new MultiEnvironmentDependentFlag object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMultiEnvironmentDependentFlag(key string, environments []DependentFlagEnvironment) *MultiEnvironmentDependentFlag { + this := MultiEnvironmentDependentFlag{} + this.Key = key + this.Environments = environments + return &this +} + +// NewMultiEnvironmentDependentFlagWithDefaults instantiates a new MultiEnvironmentDependentFlag object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMultiEnvironmentDependentFlagWithDefaults() *MultiEnvironmentDependentFlag { + this := MultiEnvironmentDependentFlag{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *MultiEnvironmentDependentFlag) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlag) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *MultiEnvironmentDependentFlag) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *MultiEnvironmentDependentFlag) SetName(v string) { + o.Name = &v +} + +// GetKey returns the Key field value +func (o *MultiEnvironmentDependentFlag) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlag) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *MultiEnvironmentDependentFlag) SetKey(v string) { + o.Key = v +} + +// GetEnvironments returns the Environments field value +func (o *MultiEnvironmentDependentFlag) GetEnvironments() []DependentFlagEnvironment { + if o == nil { + var ret []DependentFlagEnvironment + return ret + } + + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlag) GetEnvironmentsOk() ([]DependentFlagEnvironment, bool) { + if o == nil { + return nil, false + } + return o.Environments, true +} + +// SetEnvironments sets field value +func (o *MultiEnvironmentDependentFlag) SetEnvironments(v []DependentFlagEnvironment) { + o.Environments = v +} + +func (o MultiEnvironmentDependentFlag) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["environments"] = o.Environments + } + return json.Marshal(toSerialize) +} + +type NullableMultiEnvironmentDependentFlag struct { + value *MultiEnvironmentDependentFlag + isSet bool +} + +func (v NullableMultiEnvironmentDependentFlag) Get() *MultiEnvironmentDependentFlag { + return v.value +} + +func (v *NullableMultiEnvironmentDependentFlag) Set(val *MultiEnvironmentDependentFlag) { + v.value = val + v.isSet = true +} + +func (v NullableMultiEnvironmentDependentFlag) IsSet() bool { + return v.isSet +} + +func (v *NullableMultiEnvironmentDependentFlag) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMultiEnvironmentDependentFlag(val *MultiEnvironmentDependentFlag) *NullableMultiEnvironmentDependentFlag { + return &NullableMultiEnvironmentDependentFlag{value: val, isSet: true} +} + +func (v NullableMultiEnvironmentDependentFlag) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMultiEnvironmentDependentFlag) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flags.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flags.go new file mode 100644 index 00000000..4b836a34 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_multi_environment_dependent_flags.go @@ -0,0 +1,169 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// MultiEnvironmentDependentFlags struct for MultiEnvironmentDependentFlags +type MultiEnvironmentDependentFlags struct { + // An array of dependent flags with their environment information + Items []MultiEnvironmentDependentFlag `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + Site Link `json:"_site"` +} + +// NewMultiEnvironmentDependentFlags instantiates a new MultiEnvironmentDependentFlags object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMultiEnvironmentDependentFlags(items []MultiEnvironmentDependentFlag, links map[string]Link, site Link) *MultiEnvironmentDependentFlags { + this := MultiEnvironmentDependentFlags{} + this.Items = items + this.Links = links + this.Site = site + return &this +} + +// NewMultiEnvironmentDependentFlagsWithDefaults instantiates a new MultiEnvironmentDependentFlags object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMultiEnvironmentDependentFlagsWithDefaults() *MultiEnvironmentDependentFlags { + this := MultiEnvironmentDependentFlags{} + return &this +} + +// GetItems returns the Items field value +func (o *MultiEnvironmentDependentFlags) GetItems() []MultiEnvironmentDependentFlag { + if o == nil { + var ret []MultiEnvironmentDependentFlag + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlags) GetItemsOk() ([]MultiEnvironmentDependentFlag, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *MultiEnvironmentDependentFlags) SetItems(v []MultiEnvironmentDependentFlag) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *MultiEnvironmentDependentFlags) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlags) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *MultiEnvironmentDependentFlags) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetSite returns the Site field value +func (o *MultiEnvironmentDependentFlags) GetSite() Link { + if o == nil { + var ret Link + return ret + } + + return o.Site +} + +// GetSiteOk returns a tuple with the Site field value +// and a boolean to check if the value has been set. +func (o *MultiEnvironmentDependentFlags) GetSiteOk() (*Link, bool) { + if o == nil { + return nil, false + } + return &o.Site, true +} + +// SetSite sets field value +func (o *MultiEnvironmentDependentFlags) SetSite(v Link) { + o.Site = v +} + +func (o MultiEnvironmentDependentFlags) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_site"] = o.Site + } + return json.Marshal(toSerialize) +} + +type NullableMultiEnvironmentDependentFlags struct { + value *MultiEnvironmentDependentFlags + isSet bool +} + +func (v NullableMultiEnvironmentDependentFlags) Get() *MultiEnvironmentDependentFlags { + return v.value +} + +func (v *NullableMultiEnvironmentDependentFlags) Set(val *MultiEnvironmentDependentFlags) { + v.value = val + v.isSet = true +} + +func (v NullableMultiEnvironmentDependentFlags) IsSet() bool { + return v.isSet +} + +func (v *NullableMultiEnvironmentDependentFlags) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMultiEnvironmentDependentFlags(val *MultiEnvironmentDependentFlags) *NullableMultiEnvironmentDependentFlags { + return &NullableMultiEnvironmentDependentFlags{value: val, isSet: true} +} + +func (v NullableMultiEnvironmentDependentFlags) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMultiEnvironmentDependentFlags) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_naming_convention.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_naming_convention.go new file mode 100644 index 00000000..861d3d83 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_naming_convention.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// NamingConvention struct for NamingConvention +type NamingConvention struct { + // The casing convention to enforce for new flag keys in this project + Case *string `json:"case,omitempty"` + // The prefix to enforce for new flag keys in this project + Prefix *string `json:"prefix,omitempty"` +} + +// NewNamingConvention instantiates a new NamingConvention object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewNamingConvention() *NamingConvention { + this := NamingConvention{} + return &this +} + +// NewNamingConventionWithDefaults instantiates a new NamingConvention object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewNamingConventionWithDefaults() *NamingConvention { + this := NamingConvention{} + return &this +} + +// GetCase returns the Case field value if set, zero value otherwise. +func (o *NamingConvention) GetCase() string { + if o == nil || o.Case == nil { + var ret string + return ret + } + return *o.Case +} + +// GetCaseOk returns a tuple with the Case field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NamingConvention) GetCaseOk() (*string, bool) { + if o == nil || o.Case == nil { + return nil, false + } + return o.Case, true +} + +// HasCase returns a boolean if a field has been set. +func (o *NamingConvention) HasCase() bool { + if o != nil && o.Case != nil { + return true + } + + return false +} + +// SetCase gets a reference to the given string and assigns it to the Case field. +func (o *NamingConvention) SetCase(v string) { + o.Case = &v +} + +// GetPrefix returns the Prefix field value if set, zero value otherwise. +func (o *NamingConvention) GetPrefix() string { + if o == nil || o.Prefix == nil { + var ret string + return ret + } + return *o.Prefix +} + +// GetPrefixOk returns a tuple with the Prefix field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NamingConvention) GetPrefixOk() (*string, bool) { + if o == nil || o.Prefix == nil { + return nil, false + } + return o.Prefix, true +} + +// HasPrefix returns a boolean if a field has been set. +func (o *NamingConvention) HasPrefix() bool { + if o != nil && o.Prefix != nil { + return true + } + + return false +} + +// SetPrefix gets a reference to the given string and assigns it to the Prefix field. +func (o *NamingConvention) SetPrefix(v string) { + o.Prefix = &v +} + +func (o NamingConvention) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Case != nil { + toSerialize["case"] = o.Case + } + if o.Prefix != nil { + toSerialize["prefix"] = o.Prefix + } + return json.Marshal(toSerialize) +} + +type NullableNamingConvention struct { + value *NamingConvention + isSet bool +} + +func (v NullableNamingConvention) Get() *NamingConvention { + return v.value +} + +func (v *NullableNamingConvention) Set(val *NamingConvention) { + v.value = val + v.isSet = true +} + +func (v NullableNamingConvention) IsSet() bool { + return v.isSet +} + +func (v *NullableNamingConvention) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableNamingConvention(val *NamingConvention) *NullableNamingConvention { + return &NullableNamingConvention{value: val, isSet: true} +} + +func (v NullableNamingConvention) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableNamingConvention) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_new_member_form.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_new_member_form.go new file mode 100644 index 00000000..066921b3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_new_member_form.go @@ -0,0 +1,368 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// NewMemberForm struct for NewMemberForm +type NewMemberForm struct { + // The member's email + Email string `json:"email"` + // The member's password + Password *string `json:"password,omitempty"` + // The member's first name + FirstName *string `json:"firstName,omitempty"` + // The member's last name + LastName *string `json:"lastName,omitempty"` + // The member's built-in role + Role *string `json:"role,omitempty"` + // An array of the member's custom roles + CustomRoles []string `json:"customRoles,omitempty"` + // An array of the member's teams + TeamKeys []string `json:"teamKeys,omitempty"` + RoleAttributes *map[string][]string `json:"roleAttributes,omitempty"` +} + +// NewNewMemberForm instantiates a new NewMemberForm object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewNewMemberForm(email string) *NewMemberForm { + this := NewMemberForm{} + this.Email = email + return &this +} + +// NewNewMemberFormWithDefaults instantiates a new NewMemberForm object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewNewMemberFormWithDefaults() *NewMemberForm { + this := NewMemberForm{} + return &this +} + +// GetEmail returns the Email field value +func (o *NewMemberForm) GetEmail() string { + if o == nil { + var ret string + return ret + } + + return o.Email +} + +// GetEmailOk returns a tuple with the Email field value +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetEmailOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Email, true +} + +// SetEmail sets field value +func (o *NewMemberForm) SetEmail(v string) { + o.Email = v +} + +// GetPassword returns the Password field value if set, zero value otherwise. +func (o *NewMemberForm) GetPassword() string { + if o == nil || o.Password == nil { + var ret string + return ret + } + return *o.Password +} + +// GetPasswordOk returns a tuple with the Password field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetPasswordOk() (*string, bool) { + if o == nil || o.Password == nil { + return nil, false + } + return o.Password, true +} + +// HasPassword returns a boolean if a field has been set. +func (o *NewMemberForm) HasPassword() bool { + if o != nil && o.Password != nil { + return true + } + + return false +} + +// SetPassword gets a reference to the given string and assigns it to the Password field. +func (o *NewMemberForm) SetPassword(v string) { + o.Password = &v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *NewMemberForm) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *NewMemberForm) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *NewMemberForm) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *NewMemberForm) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *NewMemberForm) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *NewMemberForm) SetLastName(v string) { + o.LastName = &v +} + +// GetRole returns the Role field value if set, zero value otherwise. +func (o *NewMemberForm) GetRole() string { + if o == nil || o.Role == nil { + var ret string + return ret + } + return *o.Role +} + +// GetRoleOk returns a tuple with the Role field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetRoleOk() (*string, bool) { + if o == nil || o.Role == nil { + return nil, false + } + return o.Role, true +} + +// HasRole returns a boolean if a field has been set. +func (o *NewMemberForm) HasRole() bool { + if o != nil && o.Role != nil { + return true + } + + return false +} + +// SetRole gets a reference to the given string and assigns it to the Role field. +func (o *NewMemberForm) SetRole(v string) { + o.Role = &v +} + +// GetCustomRoles returns the CustomRoles field value if set, zero value otherwise. +func (o *NewMemberForm) GetCustomRoles() []string { + if o == nil || o.CustomRoles == nil { + var ret []string + return ret + } + return o.CustomRoles +} + +// GetCustomRolesOk returns a tuple with the CustomRoles field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetCustomRolesOk() ([]string, bool) { + if o == nil || o.CustomRoles == nil { + return nil, false + } + return o.CustomRoles, true +} + +// HasCustomRoles returns a boolean if a field has been set. +func (o *NewMemberForm) HasCustomRoles() bool { + if o != nil && o.CustomRoles != nil { + return true + } + + return false +} + +// SetCustomRoles gets a reference to the given []string and assigns it to the CustomRoles field. +func (o *NewMemberForm) SetCustomRoles(v []string) { + o.CustomRoles = v +} + +// GetTeamKeys returns the TeamKeys field value if set, zero value otherwise. +func (o *NewMemberForm) GetTeamKeys() []string { + if o == nil || o.TeamKeys == nil { + var ret []string + return ret + } + return o.TeamKeys +} + +// GetTeamKeysOk returns a tuple with the TeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetTeamKeysOk() ([]string, bool) { + if o == nil || o.TeamKeys == nil { + return nil, false + } + return o.TeamKeys, true +} + +// HasTeamKeys returns a boolean if a field has been set. +func (o *NewMemberForm) HasTeamKeys() bool { + if o != nil && o.TeamKeys != nil { + return true + } + + return false +} + +// SetTeamKeys gets a reference to the given []string and assigns it to the TeamKeys field. +func (o *NewMemberForm) SetTeamKeys(v []string) { + o.TeamKeys = v +} + +// GetRoleAttributes returns the RoleAttributes field value if set, zero value otherwise. +func (o *NewMemberForm) GetRoleAttributes() map[string][]string { + if o == nil || o.RoleAttributes == nil { + var ret map[string][]string + return ret + } + return *o.RoleAttributes +} + +// GetRoleAttributesOk returns a tuple with the RoleAttributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *NewMemberForm) GetRoleAttributesOk() (*map[string][]string, bool) { + if o == nil || o.RoleAttributes == nil { + return nil, false + } + return o.RoleAttributes, true +} + +// HasRoleAttributes returns a boolean if a field has been set. +func (o *NewMemberForm) HasRoleAttributes() bool { + if o != nil && o.RoleAttributes != nil { + return true + } + + return false +} + +// SetRoleAttributes gets a reference to the given map[string][]string and assigns it to the RoleAttributes field. +func (o *NewMemberForm) SetRoleAttributes(v map[string][]string) { + o.RoleAttributes = &v +} + +func (o NewMemberForm) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["email"] = o.Email + } + if o.Password != nil { + toSerialize["password"] = o.Password + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if o.Role != nil { + toSerialize["role"] = o.Role + } + if o.CustomRoles != nil { + toSerialize["customRoles"] = o.CustomRoles + } + if o.TeamKeys != nil { + toSerialize["teamKeys"] = o.TeamKeys + } + if o.RoleAttributes != nil { + toSerialize["roleAttributes"] = o.RoleAttributes + } + return json.Marshal(toSerialize) +} + +type NullableNewMemberForm struct { + value *NewMemberForm + isSet bool +} + +func (v NullableNewMemberForm) Get() *NewMemberForm { + return v.value +} + +func (v *NullableNewMemberForm) Set(val *NewMemberForm) { + v.value = val + v.isSet = true +} + +func (v NullableNewMemberForm) IsSet() bool { + return v.isSet +} + +func (v *NullableNewMemberForm) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableNewMemberForm(val *NewMemberForm) *NullableNewMemberForm { + return &NullableNewMemberForm{value: val, isSet: true} +} + +func (v NullableNewMemberForm) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableNewMemberForm) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_not_found_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_not_found_error_rep.go new file mode 100644 index 00000000..8bd43bc4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_not_found_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// NotFoundErrorRep struct for NotFoundErrorRep +type NotFoundErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewNotFoundErrorRep instantiates a new NotFoundErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewNotFoundErrorRep(code string, message string) *NotFoundErrorRep { + this := NotFoundErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewNotFoundErrorRepWithDefaults instantiates a new NotFoundErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewNotFoundErrorRepWithDefaults() *NotFoundErrorRep { + this := NotFoundErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *NotFoundErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *NotFoundErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *NotFoundErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *NotFoundErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *NotFoundErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *NotFoundErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o NotFoundErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableNotFoundErrorRep struct { + value *NotFoundErrorRep + isSet bool +} + +func (v NullableNotFoundErrorRep) Get() *NotFoundErrorRep { + return v.value +} + +func (v *NullableNotFoundErrorRep) Set(val *NotFoundErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableNotFoundErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableNotFoundErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableNotFoundErrorRep(val *NotFoundErrorRep) *NullableNotFoundErrorRep { + return &NullableNotFoundErrorRep{value: val, isSet: true} +} + +func (v NullableNotFoundErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableNotFoundErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_oauth_client_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_oauth_client_post.go new file mode 100644 index 00000000..e5095df5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_oauth_client_post.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// OauthClientPost struct for OauthClientPost +type OauthClientPost struct { + // The name of your new LaunchDarkly OAuth 2.0 client. + Name *string `json:"name,omitempty"` + // The redirect URI for your new OAuth 2.0 application. This should be an absolute URL conforming with the standard HTTPS protocol. + RedirectUri *string `json:"redirectUri,omitempty"` + // Description of your OAuth 2.0 client. + Description *string `json:"description,omitempty"` +} + +// NewOauthClientPost instantiates a new OauthClientPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewOauthClientPost() *OauthClientPost { + this := OauthClientPost{} + return &this +} + +// NewOauthClientPostWithDefaults instantiates a new OauthClientPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewOauthClientPostWithDefaults() *OauthClientPost { + this := OauthClientPost{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *OauthClientPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *OauthClientPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *OauthClientPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *OauthClientPost) SetName(v string) { + o.Name = &v +} + +// GetRedirectUri returns the RedirectUri field value if set, zero value otherwise. +func (o *OauthClientPost) GetRedirectUri() string { + if o == nil || o.RedirectUri == nil { + var ret string + return ret + } + return *o.RedirectUri +} + +// GetRedirectUriOk returns a tuple with the RedirectUri field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *OauthClientPost) GetRedirectUriOk() (*string, bool) { + if o == nil || o.RedirectUri == nil { + return nil, false + } + return o.RedirectUri, true +} + +// HasRedirectUri returns a boolean if a field has been set. +func (o *OauthClientPost) HasRedirectUri() bool { + if o != nil && o.RedirectUri != nil { + return true + } + + return false +} + +// SetRedirectUri gets a reference to the given string and assigns it to the RedirectUri field. +func (o *OauthClientPost) SetRedirectUri(v string) { + o.RedirectUri = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *OauthClientPost) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *OauthClientPost) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *OauthClientPost) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *OauthClientPost) SetDescription(v string) { + o.Description = &v +} + +func (o OauthClientPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.RedirectUri != nil { + toSerialize["redirectUri"] = o.RedirectUri + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + return json.Marshal(toSerialize) +} + +type NullableOauthClientPost struct { + value *OauthClientPost + isSet bool +} + +func (v NullableOauthClientPost) Get() *OauthClientPost { + return v.value +} + +func (v *NullableOauthClientPost) Set(val *OauthClientPost) { + v.value = val + v.isSet = true +} + +func (v NullableOauthClientPost) IsSet() bool { + return v.isSet +} + +func (v *NullableOauthClientPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableOauthClientPost(val *OauthClientPost) *NullableOauthClientPost { + return &NullableOauthClientPost{value: val, isSet: true} +} + +func (v NullableOauthClientPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableOauthClientPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_options_array.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_options_array.go new file mode 100644 index 00000000..043b9378 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_options_array.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// OptionsArray struct for OptionsArray +type OptionsArray struct { + Label *string `json:"label,omitempty"` + Value *string `json:"value,omitempty"` +} + +// NewOptionsArray instantiates a new OptionsArray object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewOptionsArray() *OptionsArray { + this := OptionsArray{} + return &this +} + +// NewOptionsArrayWithDefaults instantiates a new OptionsArray object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewOptionsArrayWithDefaults() *OptionsArray { + this := OptionsArray{} + return &this +} + +// GetLabel returns the Label field value if set, zero value otherwise. +func (o *OptionsArray) GetLabel() string { + if o == nil || o.Label == nil { + var ret string + return ret + } + return *o.Label +} + +// GetLabelOk returns a tuple with the Label field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *OptionsArray) GetLabelOk() (*string, bool) { + if o == nil || o.Label == nil { + return nil, false + } + return o.Label, true +} + +// HasLabel returns a boolean if a field has been set. +func (o *OptionsArray) HasLabel() bool { + if o != nil && o.Label != nil { + return true + } + + return false +} + +// SetLabel gets a reference to the given string and assigns it to the Label field. +func (o *OptionsArray) SetLabel(v string) { + o.Label = &v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *OptionsArray) GetValue() string { + if o == nil || o.Value == nil { + var ret string + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *OptionsArray) GetValueOk() (*string, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *OptionsArray) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given string and assigns it to the Value field. +func (o *OptionsArray) SetValue(v string) { + o.Value = &v +} + +func (o OptionsArray) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Label != nil { + toSerialize["label"] = o.Label + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableOptionsArray struct { + value *OptionsArray + isSet bool +} + +func (v NullableOptionsArray) Get() *OptionsArray { + return v.value +} + +func (v *NullableOptionsArray) Set(val *OptionsArray) { + v.value = val + v.isSet = true +} + +func (v NullableOptionsArray) IsSet() bool { + return v.isSet +} + +func (v *NullableOptionsArray) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableOptionsArray(val *OptionsArray) *NullableOptionsArray { + return &NullableOptionsArray{value: val, isSet: true} +} + +func (v NullableOptionsArray) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableOptionsArray) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_paginated_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_paginated_links.go new file mode 100644 index 00000000..04ca5597 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_paginated_links.go @@ -0,0 +1,253 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PaginatedLinks struct for PaginatedLinks +type PaginatedLinks struct { + First *AiConfigsLink `json:"first,omitempty"` + Last *AiConfigsLink `json:"last,omitempty"` + Next *AiConfigsLink `json:"next,omitempty"` + Prev *AiConfigsLink `json:"prev,omitempty"` + Self AiConfigsLink `json:"self"` +} + +// NewPaginatedLinks instantiates a new PaginatedLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPaginatedLinks(self AiConfigsLink) *PaginatedLinks { + this := PaginatedLinks{} + this.Self = self + return &this +} + +// NewPaginatedLinksWithDefaults instantiates a new PaginatedLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPaginatedLinksWithDefaults() *PaginatedLinks { + this := PaginatedLinks{} + return &this +} + +// GetFirst returns the First field value if set, zero value otherwise. +func (o *PaginatedLinks) GetFirst() AiConfigsLink { + if o == nil || o.First == nil { + var ret AiConfigsLink + return ret + } + return *o.First +} + +// GetFirstOk returns a tuple with the First field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PaginatedLinks) GetFirstOk() (*AiConfigsLink, bool) { + if o == nil || o.First == nil { + return nil, false + } + return o.First, true +} + +// HasFirst returns a boolean if a field has been set. +func (o *PaginatedLinks) HasFirst() bool { + if o != nil && o.First != nil { + return true + } + + return false +} + +// SetFirst gets a reference to the given AiConfigsLink and assigns it to the First field. +func (o *PaginatedLinks) SetFirst(v AiConfigsLink) { + o.First = &v +} + +// GetLast returns the Last field value if set, zero value otherwise. +func (o *PaginatedLinks) GetLast() AiConfigsLink { + if o == nil || o.Last == nil { + var ret AiConfigsLink + return ret + } + return *o.Last +} + +// GetLastOk returns a tuple with the Last field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PaginatedLinks) GetLastOk() (*AiConfigsLink, bool) { + if o == nil || o.Last == nil { + return nil, false + } + return o.Last, true +} + +// HasLast returns a boolean if a field has been set. +func (o *PaginatedLinks) HasLast() bool { + if o != nil && o.Last != nil { + return true + } + + return false +} + +// SetLast gets a reference to the given AiConfigsLink and assigns it to the Last field. +func (o *PaginatedLinks) SetLast(v AiConfigsLink) { + o.Last = &v +} + +// GetNext returns the Next field value if set, zero value otherwise. +func (o *PaginatedLinks) GetNext() AiConfigsLink { + if o == nil || o.Next == nil { + var ret AiConfigsLink + return ret + } + return *o.Next +} + +// GetNextOk returns a tuple with the Next field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PaginatedLinks) GetNextOk() (*AiConfigsLink, bool) { + if o == nil || o.Next == nil { + return nil, false + } + return o.Next, true +} + +// HasNext returns a boolean if a field has been set. +func (o *PaginatedLinks) HasNext() bool { + if o != nil && o.Next != nil { + return true + } + + return false +} + +// SetNext gets a reference to the given AiConfigsLink and assigns it to the Next field. +func (o *PaginatedLinks) SetNext(v AiConfigsLink) { + o.Next = &v +} + +// GetPrev returns the Prev field value if set, zero value otherwise. +func (o *PaginatedLinks) GetPrev() AiConfigsLink { + if o == nil || o.Prev == nil { + var ret AiConfigsLink + return ret + } + return *o.Prev +} + +// GetPrevOk returns a tuple with the Prev field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PaginatedLinks) GetPrevOk() (*AiConfigsLink, bool) { + if o == nil || o.Prev == nil { + return nil, false + } + return o.Prev, true +} + +// HasPrev returns a boolean if a field has been set. +func (o *PaginatedLinks) HasPrev() bool { + if o != nil && o.Prev != nil { + return true + } + + return false +} + +// SetPrev gets a reference to the given AiConfigsLink and assigns it to the Prev field. +func (o *PaginatedLinks) SetPrev(v AiConfigsLink) { + o.Prev = &v +} + +// GetSelf returns the Self field value +func (o *PaginatedLinks) GetSelf() AiConfigsLink { + if o == nil { + var ret AiConfigsLink + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *PaginatedLinks) GetSelfOk() (*AiConfigsLink, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *PaginatedLinks) SetSelf(v AiConfigsLink) { + o.Self = v +} + +func (o PaginatedLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.First != nil { + toSerialize["first"] = o.First + } + if o.Last != nil { + toSerialize["last"] = o.Last + } + if o.Next != nil { + toSerialize["next"] = o.Next + } + if o.Prev != nil { + toSerialize["prev"] = o.Prev + } + if true { + toSerialize["self"] = o.Self + } + return json.Marshal(toSerialize) +} + +type NullablePaginatedLinks struct { + value *PaginatedLinks + isSet bool +} + +func (v NullablePaginatedLinks) Get() *PaginatedLinks { + return v.value +} + +func (v *NullablePaginatedLinks) Set(val *PaginatedLinks) { + v.value = val + v.isSet = true +} + +func (v NullablePaginatedLinks) IsSet() bool { + return v.isSet +} + +func (v *NullablePaginatedLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePaginatedLinks(val *PaginatedLinks) *NullablePaginatedLinks { + return &NullablePaginatedLinks{value: val, isSet: true} +} + +func (v NullablePaginatedLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePaginatedLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_default.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_default.go new file mode 100644 index 00000000..ef6eea3a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_default.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ParameterDefault struct for ParameterDefault +type ParameterDefault struct { + // The default value for the given parameter + Value interface{} `json:"value,omitempty"` + // Variation value for boolean flags. Not applicable for non-boolean flags. + BooleanVariationValue *bool `json:"booleanVariationValue,omitempty"` + RuleClause *RuleClause `json:"ruleClause,omitempty"` +} + +// NewParameterDefault instantiates a new ParameterDefault object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewParameterDefault() *ParameterDefault { + this := ParameterDefault{} + return &this +} + +// NewParameterDefaultWithDefaults instantiates a new ParameterDefault object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewParameterDefaultWithDefaults() *ParameterDefault { + this := ParameterDefault{} + return &this +} + +// GetValue returns the Value field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *ParameterDefault) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ParameterDefault) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *ParameterDefault) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given interface{} and assigns it to the Value field. +func (o *ParameterDefault) SetValue(v interface{}) { + o.Value = v +} + +// GetBooleanVariationValue returns the BooleanVariationValue field value if set, zero value otherwise. +func (o *ParameterDefault) GetBooleanVariationValue() bool { + if o == nil || o.BooleanVariationValue == nil { + var ret bool + return ret + } + return *o.BooleanVariationValue +} + +// GetBooleanVariationValueOk returns a tuple with the BooleanVariationValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParameterDefault) GetBooleanVariationValueOk() (*bool, bool) { + if o == nil || o.BooleanVariationValue == nil { + return nil, false + } + return o.BooleanVariationValue, true +} + +// HasBooleanVariationValue returns a boolean if a field has been set. +func (o *ParameterDefault) HasBooleanVariationValue() bool { + if o != nil && o.BooleanVariationValue != nil { + return true + } + + return false +} + +// SetBooleanVariationValue gets a reference to the given bool and assigns it to the BooleanVariationValue field. +func (o *ParameterDefault) SetBooleanVariationValue(v bool) { + o.BooleanVariationValue = &v +} + +// GetRuleClause returns the RuleClause field value if set, zero value otherwise. +func (o *ParameterDefault) GetRuleClause() RuleClause { + if o == nil || o.RuleClause == nil { + var ret RuleClause + return ret + } + return *o.RuleClause +} + +// GetRuleClauseOk returns a tuple with the RuleClause field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParameterDefault) GetRuleClauseOk() (*RuleClause, bool) { + if o == nil || o.RuleClause == nil { + return nil, false + } + return o.RuleClause, true +} + +// HasRuleClause returns a boolean if a field has been set. +func (o *ParameterDefault) HasRuleClause() bool { + if o != nil && o.RuleClause != nil { + return true + } + + return false +} + +// SetRuleClause gets a reference to the given RuleClause and assigns it to the RuleClause field. +func (o *ParameterDefault) SetRuleClause(v RuleClause) { + o.RuleClause = &v +} + +func (o ParameterDefault) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.BooleanVariationValue != nil { + toSerialize["booleanVariationValue"] = o.BooleanVariationValue + } + if o.RuleClause != nil { + toSerialize["ruleClause"] = o.RuleClause + } + return json.Marshal(toSerialize) +} + +type NullableParameterDefault struct { + value *ParameterDefault + isSet bool +} + +func (v NullableParameterDefault) Get() *ParameterDefault { + return v.value +} + +func (v *NullableParameterDefault) Set(val *ParameterDefault) { + v.value = val + v.isSet = true +} + +func (v NullableParameterDefault) IsSet() bool { + return v.isSet +} + +func (v *NullableParameterDefault) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableParameterDefault(val *ParameterDefault) *NullableParameterDefault { + return &NullableParameterDefault{value: val, isSet: true} +} + +func (v NullableParameterDefault) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableParameterDefault) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_rep.go new file mode 100644 index 00000000..c2e40c05 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_parameter_rep.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ParameterRep struct for ParameterRep +type ParameterRep struct { + VariationId *string `json:"variationId,omitempty"` + FlagKey *string `json:"flagKey,omitempty"` +} + +// NewParameterRep instantiates a new ParameterRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewParameterRep() *ParameterRep { + this := ParameterRep{} + return &this +} + +// NewParameterRepWithDefaults instantiates a new ParameterRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewParameterRepWithDefaults() *ParameterRep { + this := ParameterRep{} + return &this +} + +// GetVariationId returns the VariationId field value if set, zero value otherwise. +func (o *ParameterRep) GetVariationId() string { + if o == nil || o.VariationId == nil { + var ret string + return ret + } + return *o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParameterRep) GetVariationIdOk() (*string, bool) { + if o == nil || o.VariationId == nil { + return nil, false + } + return o.VariationId, true +} + +// HasVariationId returns a boolean if a field has been set. +func (o *ParameterRep) HasVariationId() bool { + if o != nil && o.VariationId != nil { + return true + } + + return false +} + +// SetVariationId gets a reference to the given string and assigns it to the VariationId field. +func (o *ParameterRep) SetVariationId(v string) { + o.VariationId = &v +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +func (o *ParameterRep) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParameterRep) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *ParameterRep) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +func (o *ParameterRep) SetFlagKey(v string) { + o.FlagKey = &v +} + +func (o ParameterRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.VariationId != nil { + toSerialize["variationId"] = o.VariationId + } + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + return json.Marshal(toSerialize) +} + +type NullableParameterRep struct { + value *ParameterRep + isSet bool +} + +func (v NullableParameterRep) Get() *ParameterRep { + return v.value +} + +func (v *NullableParameterRep) Set(val *ParameterRep) { + v.value = val + v.isSet = true +} + +func (v NullableParameterRep) IsSet() bool { + return v.isSet +} + +func (v *NullableParameterRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableParameterRep(val *ParameterRep) *NullableParameterRep { + return &NullableParameterRep{value: val, isSet: true} +} + +func (v NullableParameterRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableParameterRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_and_self_links.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_and_self_links.go new file mode 100644 index 00000000..4c296d6c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_and_self_links.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ParentAndSelfLinks The location and content type of related resources +type ParentAndSelfLinks struct { + Self CoreLink `json:"self"` + Parent CoreLink `json:"parent"` +} + +// NewParentAndSelfLinks instantiates a new ParentAndSelfLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewParentAndSelfLinks(self CoreLink, parent CoreLink) *ParentAndSelfLinks { + this := ParentAndSelfLinks{} + this.Self = self + this.Parent = parent + return &this +} + +// NewParentAndSelfLinksWithDefaults instantiates a new ParentAndSelfLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewParentAndSelfLinksWithDefaults() *ParentAndSelfLinks { + this := ParentAndSelfLinks{} + return &this +} + +// GetSelf returns the Self field value +func (o *ParentAndSelfLinks) GetSelf() CoreLink { + if o == nil { + var ret CoreLink + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *ParentAndSelfLinks) GetSelfOk() (*CoreLink, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *ParentAndSelfLinks) SetSelf(v CoreLink) { + o.Self = v +} + +// GetParent returns the Parent field value +func (o *ParentAndSelfLinks) GetParent() CoreLink { + if o == nil { + var ret CoreLink + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *ParentAndSelfLinks) GetParentOk() (*CoreLink, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *ParentAndSelfLinks) SetParent(v CoreLink) { + o.Parent = v +} + +func (o ParentAndSelfLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["self"] = o.Self + } + if true { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableParentAndSelfLinks struct { + value *ParentAndSelfLinks + isSet bool +} + +func (v NullableParentAndSelfLinks) Get() *ParentAndSelfLinks { + return v.value +} + +func (v *NullableParentAndSelfLinks) Set(val *ParentAndSelfLinks) { + v.value = val + v.isSet = true +} + +func (v NullableParentAndSelfLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableParentAndSelfLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableParentAndSelfLinks(val *ParentAndSelfLinks) *NullableParentAndSelfLinks { + return &NullableParentAndSelfLinks{value: val, isSet: true} +} + +func (v NullableParentAndSelfLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableParentAndSelfLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_link.go new file mode 100644 index 00000000..3edd7ecf --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_link.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ParentLink struct for ParentLink +type ParentLink struct { + Parent CoreLink `json:"parent"` +} + +// NewParentLink instantiates a new ParentLink object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewParentLink(parent CoreLink) *ParentLink { + this := ParentLink{} + this.Parent = parent + return &this +} + +// NewParentLinkWithDefaults instantiates a new ParentLink object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewParentLinkWithDefaults() *ParentLink { + this := ParentLink{} + return &this +} + +// GetParent returns the Parent field value +func (o *ParentLink) GetParent() CoreLink { + if o == nil { + var ret CoreLink + return ret + } + + return o.Parent +} + +// GetParentOk returns a tuple with the Parent field value +// and a boolean to check if the value has been set. +func (o *ParentLink) GetParentOk() (*CoreLink, bool) { + if o == nil { + return nil, false + } + return &o.Parent, true +} + +// SetParent sets field value +func (o *ParentLink) SetParent(v CoreLink) { + o.Parent = v +} + +func (o ParentLink) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["parent"] = o.Parent + } + return json.Marshal(toSerialize) +} + +type NullableParentLink struct { + value *ParentLink + isSet bool +} + +func (v NullableParentLink) Get() *ParentLink { + return v.value +} + +func (v *NullableParentLink) Set(val *ParentLink) { + v.value = val + v.isSet = true +} + +func (v NullableParentLink) IsSet() bool { + return v.isSet +} + +func (v *NullableParentLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableParentLink(val *ParentLink) *NullableParentLink { + return &NullableParentLink{value: val, isSet: true} +} + +func (v NullableParentLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableParentLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_resource_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_resource_rep.go new file mode 100644 index 00000000..704bb3fc --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_parent_resource_rep.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ParentResourceRep struct for ParentResourceRep +type ParentResourceRep struct { + Links *map[string]Link `json:"_links,omitempty"` + // The name of the parent resource + Name *string `json:"name,omitempty"` + // The parent's resource specifier + Resource *string `json:"resource,omitempty"` +} + +// NewParentResourceRep instantiates a new ParentResourceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewParentResourceRep() *ParentResourceRep { + this := ParentResourceRep{} + return &this +} + +// NewParentResourceRepWithDefaults instantiates a new ParentResourceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewParentResourceRepWithDefaults() *ParentResourceRep { + this := ParentResourceRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ParentResourceRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParentResourceRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ParentResourceRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ParentResourceRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *ParentResourceRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParentResourceRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *ParentResourceRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *ParentResourceRep) SetName(v string) { + o.Name = &v +} + +// GetResource returns the Resource field value if set, zero value otherwise. +func (o *ParentResourceRep) GetResource() string { + if o == nil || o.Resource == nil { + var ret string + return ret + } + return *o.Resource +} + +// GetResourceOk returns a tuple with the Resource field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ParentResourceRep) GetResourceOk() (*string, bool) { + if o == nil || o.Resource == nil { + return nil, false + } + return o.Resource, true +} + +// HasResource returns a boolean if a field has been set. +func (o *ParentResourceRep) HasResource() bool { + if o != nil && o.Resource != nil { + return true + } + + return false +} + +// SetResource gets a reference to the given string and assigns it to the Resource field. +func (o *ParentResourceRep) SetResource(v string) { + o.Resource = &v +} + +func (o ParentResourceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Resource != nil { + toSerialize["resource"] = o.Resource + } + return json.Marshal(toSerialize) +} + +type NullableParentResourceRep struct { + value *ParentResourceRep + isSet bool +} + +func (v NullableParentResourceRep) Get() *ParentResourceRep { + return v.value +} + +func (v *NullableParentResourceRep) Set(val *ParentResourceRep) { + v.value = val + v.isSet = true +} + +func (v NullableParentResourceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableParentResourceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableParentResourceRep(val *ParentResourceRep) *NullableParentResourceRep { + return &NullableParentResourceRep{value: val, isSet: true} +} + +func (v NullableParentResourceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableParentResourceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_failed_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_failed_error_rep.go new file mode 100644 index 00000000..52ad8f28 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_failed_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchFailedErrorRep struct for PatchFailedErrorRep +type PatchFailedErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewPatchFailedErrorRep instantiates a new PatchFailedErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchFailedErrorRep(code string, message string) *PatchFailedErrorRep { + this := PatchFailedErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewPatchFailedErrorRepWithDefaults instantiates a new PatchFailedErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchFailedErrorRepWithDefaults() *PatchFailedErrorRep { + this := PatchFailedErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *PatchFailedErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *PatchFailedErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *PatchFailedErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *PatchFailedErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *PatchFailedErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *PatchFailedErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o PatchFailedErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullablePatchFailedErrorRep struct { + value *PatchFailedErrorRep + isSet bool +} + +func (v NullablePatchFailedErrorRep) Get() *PatchFailedErrorRep { + return v.value +} + +func (v *NullablePatchFailedErrorRep) Set(val *PatchFailedErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullablePatchFailedErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchFailedErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchFailedErrorRep(val *PatchFailedErrorRep) *NullablePatchFailedErrorRep { + return &NullablePatchFailedErrorRep{value: val, isSet: true} +} + +func (v NullablePatchFailedErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchFailedErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_flags_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_flags_request.go new file mode 100644 index 00000000..3d079d1c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_flags_request.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchFlagsRequest struct for PatchFlagsRequest +type PatchFlagsRequest struct { + // Optional comment describing the change + Comment *string `json:"comment,omitempty"` + // The instructions to perform when updating + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewPatchFlagsRequest instantiates a new PatchFlagsRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchFlagsRequest(instructions []map[string]interface{}) *PatchFlagsRequest { + this := PatchFlagsRequest{} + this.Instructions = instructions + return &this +} + +// NewPatchFlagsRequestWithDefaults instantiates a new PatchFlagsRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchFlagsRequestWithDefaults() *PatchFlagsRequest { + this := PatchFlagsRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PatchFlagsRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchFlagsRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PatchFlagsRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PatchFlagsRequest) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *PatchFlagsRequest) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *PatchFlagsRequest) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *PatchFlagsRequest) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o PatchFlagsRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullablePatchFlagsRequest struct { + value *PatchFlagsRequest + isSet bool +} + +func (v NullablePatchFlagsRequest) Get() *PatchFlagsRequest { + return v.value +} + +func (v *NullablePatchFlagsRequest) Set(val *PatchFlagsRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePatchFlagsRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchFlagsRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchFlagsRequest(val *PatchFlagsRequest) *NullablePatchFlagsRequest { + return &NullablePatchFlagsRequest{value: val, isSet: true} +} + +func (v NullablePatchFlagsRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchFlagsRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_operation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_operation.go new file mode 100644 index 00000000..f3420a4d --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_operation.go @@ -0,0 +1,178 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchOperation struct for PatchOperation +type PatchOperation struct { + // The type of operation to perform + Op string `json:"op"` + // A JSON Pointer string specifying the part of the document to operate on + Path string `json:"path"` + // A JSON value used in \"add\", \"replace\", and \"test\" operations + Value interface{} `json:"value,omitempty"` +} + +// NewPatchOperation instantiates a new PatchOperation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchOperation(op string, path string) *PatchOperation { + this := PatchOperation{} + this.Op = op + this.Path = path + return &this +} + +// NewPatchOperationWithDefaults instantiates a new PatchOperation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchOperationWithDefaults() *PatchOperation { + this := PatchOperation{} + return &this +} + +// GetOp returns the Op field value +func (o *PatchOperation) GetOp() string { + if o == nil { + var ret string + return ret + } + + return o.Op +} + +// GetOpOk returns a tuple with the Op field value +// and a boolean to check if the value has been set. +func (o *PatchOperation) GetOpOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Op, true +} + +// SetOp sets field value +func (o *PatchOperation) SetOp(v string) { + o.Op = v +} + +// GetPath returns the Path field value +func (o *PatchOperation) GetPath() string { + if o == nil { + var ret string + return ret + } + + return o.Path +} + +// GetPathOk returns a tuple with the Path field value +// and a boolean to check if the value has been set. +func (o *PatchOperation) GetPathOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Path, true +} + +// SetPath sets field value +func (o *PatchOperation) SetPath(v string) { + o.Path = v +} + +// GetValue returns the Value field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *PatchOperation) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *PatchOperation) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *PatchOperation) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given interface{} and assigns it to the Value field. +func (o *PatchOperation) SetValue(v interface{}) { + o.Value = v +} + +func (o PatchOperation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["op"] = o.Op + } + if true { + toSerialize["path"] = o.Path + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullablePatchOperation struct { + value *PatchOperation + isSet bool +} + +func (v NullablePatchOperation) Get() *PatchOperation { + return v.value +} + +func (v *NullablePatchOperation) Set(val *PatchOperation) { + v.value = val + v.isSet = true +} + +func (v NullablePatchOperation) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchOperation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchOperation(val *PatchOperation) *NullablePatchOperation { + return &NullablePatchOperation{value: val, isSet: true} +} + +func (v NullablePatchOperation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchOperation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_input_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_input_rep.go new file mode 100644 index 00000000..38ead3f6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_input_rep.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchSegmentExpiringTargetInputRep struct for PatchSegmentExpiringTargetInputRep +type PatchSegmentExpiringTargetInputRep struct { + // Optional description of changes + Comment *string `json:"comment,omitempty"` + // Semantic patch instructions for the desired changes to the resource + Instructions []PatchSegmentExpiringTargetInstruction `json:"instructions"` +} + +// NewPatchSegmentExpiringTargetInputRep instantiates a new PatchSegmentExpiringTargetInputRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchSegmentExpiringTargetInputRep(instructions []PatchSegmentExpiringTargetInstruction) *PatchSegmentExpiringTargetInputRep { + this := PatchSegmentExpiringTargetInputRep{} + this.Instructions = instructions + return &this +} + +// NewPatchSegmentExpiringTargetInputRepWithDefaults instantiates a new PatchSegmentExpiringTargetInputRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchSegmentExpiringTargetInputRepWithDefaults() *PatchSegmentExpiringTargetInputRep { + this := PatchSegmentExpiringTargetInputRep{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PatchSegmentExpiringTargetInputRep) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInputRep) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PatchSegmentExpiringTargetInputRep) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PatchSegmentExpiringTargetInputRep) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *PatchSegmentExpiringTargetInputRep) GetInstructions() []PatchSegmentExpiringTargetInstruction { + if o == nil { + var ret []PatchSegmentExpiringTargetInstruction + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInputRep) GetInstructionsOk() ([]PatchSegmentExpiringTargetInstruction, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *PatchSegmentExpiringTargetInputRep) SetInstructions(v []PatchSegmentExpiringTargetInstruction) { + o.Instructions = v +} + +func (o PatchSegmentExpiringTargetInputRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullablePatchSegmentExpiringTargetInputRep struct { + value *PatchSegmentExpiringTargetInputRep + isSet bool +} + +func (v NullablePatchSegmentExpiringTargetInputRep) Get() *PatchSegmentExpiringTargetInputRep { + return v.value +} + +func (v *NullablePatchSegmentExpiringTargetInputRep) Set(val *PatchSegmentExpiringTargetInputRep) { + v.value = val + v.isSet = true +} + +func (v NullablePatchSegmentExpiringTargetInputRep) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchSegmentExpiringTargetInputRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchSegmentExpiringTargetInputRep(val *PatchSegmentExpiringTargetInputRep) *NullablePatchSegmentExpiringTargetInputRep { + return &NullablePatchSegmentExpiringTargetInputRep{value: val, isSet: true} +} + +func (v NullablePatchSegmentExpiringTargetInputRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchSegmentExpiringTargetInputRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_instruction.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_instruction.go new file mode 100644 index 00000000..a6de8804 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_expiring_target_instruction.go @@ -0,0 +1,274 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchSegmentExpiringTargetInstruction struct for PatchSegmentExpiringTargetInstruction +type PatchSegmentExpiringTargetInstruction struct { + // The type of change to make to the context's removal date from this segment + Kind string `json:"kind"` + // A unique key used to represent the context + ContextKey string `json:"contextKey"` + // The kind of context + ContextKind string `json:"contextKind"` + // The segment's target type + TargetType string `json:"targetType"` + // The time, in Unix milliseconds, when the context should be removed from this segment. Required if kind is addExpiringTarget or updateExpiringTarget. + Value *int64 `json:"value,omitempty"` + // The version of the expiring target to update. Optional and only used if kind is updateExpiringTarget. If included, update will fail if version doesn't match current version of the expiring target. + Version *int32 `json:"version,omitempty"` +} + +// NewPatchSegmentExpiringTargetInstruction instantiates a new PatchSegmentExpiringTargetInstruction object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchSegmentExpiringTargetInstruction(kind string, contextKey string, contextKind string, targetType string) *PatchSegmentExpiringTargetInstruction { + this := PatchSegmentExpiringTargetInstruction{} + this.Kind = kind + this.ContextKey = contextKey + this.ContextKind = contextKind + this.TargetType = targetType + return &this +} + +// NewPatchSegmentExpiringTargetInstructionWithDefaults instantiates a new PatchSegmentExpiringTargetInstruction object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchSegmentExpiringTargetInstructionWithDefaults() *PatchSegmentExpiringTargetInstruction { + this := PatchSegmentExpiringTargetInstruction{} + return &this +} + +// GetKind returns the Kind field value +func (o *PatchSegmentExpiringTargetInstruction) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *PatchSegmentExpiringTargetInstruction) SetKind(v string) { + o.Kind = v +} + +// GetContextKey returns the ContextKey field value +func (o *PatchSegmentExpiringTargetInstruction) GetContextKey() string { + if o == nil { + var ret string + return ret + } + + return o.ContextKey +} + +// GetContextKeyOk returns a tuple with the ContextKey field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetContextKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ContextKey, true +} + +// SetContextKey sets field value +func (o *PatchSegmentExpiringTargetInstruction) SetContextKey(v string) { + o.ContextKey = v +} + +// GetContextKind returns the ContextKind field value +func (o *PatchSegmentExpiringTargetInstruction) GetContextKind() string { + if o == nil { + var ret string + return ret + } + + return o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetContextKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ContextKind, true +} + +// SetContextKind sets field value +func (o *PatchSegmentExpiringTargetInstruction) SetContextKind(v string) { + o.ContextKind = v +} + +// GetTargetType returns the TargetType field value +func (o *PatchSegmentExpiringTargetInstruction) GetTargetType() string { + if o == nil { + var ret string + return ret + } + + return o.TargetType +} + +// GetTargetTypeOk returns a tuple with the TargetType field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetTargetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.TargetType, true +} + +// SetTargetType sets field value +func (o *PatchSegmentExpiringTargetInstruction) SetTargetType(v string) { + o.TargetType = v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *PatchSegmentExpiringTargetInstruction) GetValue() int64 { + if o == nil || o.Value == nil { + var ret int64 + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetValueOk() (*int64, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *PatchSegmentExpiringTargetInstruction) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given int64 and assigns it to the Value field. +func (o *PatchSegmentExpiringTargetInstruction) SetValue(v int64) { + o.Value = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *PatchSegmentExpiringTargetInstruction) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentExpiringTargetInstruction) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *PatchSegmentExpiringTargetInstruction) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *PatchSegmentExpiringTargetInstruction) SetVersion(v int32) { + o.Version = &v +} + +func (o PatchSegmentExpiringTargetInstruction) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["contextKey"] = o.ContextKey + } + if true { + toSerialize["contextKind"] = o.ContextKind + } + if true { + toSerialize["targetType"] = o.TargetType + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullablePatchSegmentExpiringTargetInstruction struct { + value *PatchSegmentExpiringTargetInstruction + isSet bool +} + +func (v NullablePatchSegmentExpiringTargetInstruction) Get() *PatchSegmentExpiringTargetInstruction { + return v.value +} + +func (v *NullablePatchSegmentExpiringTargetInstruction) Set(val *PatchSegmentExpiringTargetInstruction) { + v.value = val + v.isSet = true +} + +func (v NullablePatchSegmentExpiringTargetInstruction) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchSegmentExpiringTargetInstruction) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchSegmentExpiringTargetInstruction(val *PatchSegmentExpiringTargetInstruction) *NullablePatchSegmentExpiringTargetInstruction { + return &NullablePatchSegmentExpiringTargetInstruction{value: val, isSet: true} +} + +func (v NullablePatchSegmentExpiringTargetInstruction) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchSegmentExpiringTargetInstruction) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_instruction.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_instruction.go new file mode 100644 index 00000000..ca814208 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_instruction.go @@ -0,0 +1,244 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchSegmentInstruction struct for PatchSegmentInstruction +type PatchSegmentInstruction struct { + // The type of change to make to the user's removal date from this segment + Kind string `json:"kind"` + // A unique key used to represent the user + UserKey string `json:"userKey"` + // The segment's target type + TargetType string `json:"targetType"` + // The time, in Unix milliseconds, when the user should be removed from this segment. Required if kind is addExpireUserTargetDate or updateExpireUserTargetDate. + Value *int32 `json:"value,omitempty"` + // The version of the segment to update. Required if kind is updateExpireUserTargetDate. + Version *int32 `json:"version,omitempty"` +} + +// NewPatchSegmentInstruction instantiates a new PatchSegmentInstruction object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchSegmentInstruction(kind string, userKey string, targetType string) *PatchSegmentInstruction { + this := PatchSegmentInstruction{} + this.Kind = kind + this.UserKey = userKey + this.TargetType = targetType + return &this +} + +// NewPatchSegmentInstructionWithDefaults instantiates a new PatchSegmentInstruction object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchSegmentInstructionWithDefaults() *PatchSegmentInstruction { + this := PatchSegmentInstruction{} + return &this +} + +// GetKind returns the Kind field value +func (o *PatchSegmentInstruction) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentInstruction) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *PatchSegmentInstruction) SetKind(v string) { + o.Kind = v +} + +// GetUserKey returns the UserKey field value +func (o *PatchSegmentInstruction) GetUserKey() string { + if o == nil { + var ret string + return ret + } + + return o.UserKey +} + +// GetUserKeyOk returns a tuple with the UserKey field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentInstruction) GetUserKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.UserKey, true +} + +// SetUserKey sets field value +func (o *PatchSegmentInstruction) SetUserKey(v string) { + o.UserKey = v +} + +// GetTargetType returns the TargetType field value +func (o *PatchSegmentInstruction) GetTargetType() string { + if o == nil { + var ret string + return ret + } + + return o.TargetType +} + +// GetTargetTypeOk returns a tuple with the TargetType field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentInstruction) GetTargetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.TargetType, true +} + +// SetTargetType sets field value +func (o *PatchSegmentInstruction) SetTargetType(v string) { + o.TargetType = v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *PatchSegmentInstruction) GetValue() int32 { + if o == nil || o.Value == nil { + var ret int32 + return ret + } + return *o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentInstruction) GetValueOk() (*int32, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *PatchSegmentInstruction) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given int32 and assigns it to the Value field. +func (o *PatchSegmentInstruction) SetValue(v int32) { + o.Value = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *PatchSegmentInstruction) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentInstruction) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *PatchSegmentInstruction) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *PatchSegmentInstruction) SetVersion(v int32) { + o.Version = &v +} + +func (o PatchSegmentInstruction) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["kind"] = o.Kind + } + if true { + toSerialize["userKey"] = o.UserKey + } + if true { + toSerialize["targetType"] = o.TargetType + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullablePatchSegmentInstruction struct { + value *PatchSegmentInstruction + isSet bool +} + +func (v NullablePatchSegmentInstruction) Get() *PatchSegmentInstruction { + return v.value +} + +func (v *NullablePatchSegmentInstruction) Set(val *PatchSegmentInstruction) { + v.value = val + v.isSet = true +} + +func (v NullablePatchSegmentInstruction) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchSegmentInstruction) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchSegmentInstruction(val *PatchSegmentInstruction) *NullablePatchSegmentInstruction { + return &NullablePatchSegmentInstruction{value: val, isSet: true} +} + +func (v NullablePatchSegmentInstruction) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchSegmentInstruction) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_request.go new file mode 100644 index 00000000..09de8f1c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_segment_request.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchSegmentRequest struct for PatchSegmentRequest +type PatchSegmentRequest struct { + // Optional description of changes + Comment *string `json:"comment,omitempty"` + // Semantic patch instructions for the desired changes to the resource + Instructions []PatchSegmentInstruction `json:"instructions"` +} + +// NewPatchSegmentRequest instantiates a new PatchSegmentRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchSegmentRequest(instructions []PatchSegmentInstruction) *PatchSegmentRequest { + this := PatchSegmentRequest{} + this.Instructions = instructions + return &this +} + +// NewPatchSegmentRequestWithDefaults instantiates a new PatchSegmentRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchSegmentRequestWithDefaults() *PatchSegmentRequest { + this := PatchSegmentRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PatchSegmentRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchSegmentRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PatchSegmentRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PatchSegmentRequest) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *PatchSegmentRequest) GetInstructions() []PatchSegmentInstruction { + if o == nil { + var ret []PatchSegmentInstruction + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *PatchSegmentRequest) GetInstructionsOk() ([]PatchSegmentInstruction, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *PatchSegmentRequest) SetInstructions(v []PatchSegmentInstruction) { + o.Instructions = v +} + +func (o PatchSegmentRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullablePatchSegmentRequest struct { + value *PatchSegmentRequest + isSet bool +} + +func (v NullablePatchSegmentRequest) Get() *PatchSegmentRequest { + return v.value +} + +func (v *NullablePatchSegmentRequest) Set(val *PatchSegmentRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePatchSegmentRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchSegmentRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchSegmentRequest(val *PatchSegmentRequest) *NullablePatchSegmentRequest { + return &NullablePatchSegmentRequest{value: val, isSet: true} +} + +func (v NullablePatchSegmentRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchSegmentRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_users_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_users_request.go new file mode 100644 index 00000000..a5730795 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_users_request.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchUsersRequest struct for PatchUsersRequest +type PatchUsersRequest struct { + // Optional comment describing the change + Comment *string `json:"comment,omitempty"` + // The instructions to perform when updating + Instructions []InstructionUserRequest `json:"instructions"` +} + +// NewPatchUsersRequest instantiates a new PatchUsersRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchUsersRequest(instructions []InstructionUserRequest) *PatchUsersRequest { + this := PatchUsersRequest{} + this.Instructions = instructions + return &this +} + +// NewPatchUsersRequestWithDefaults instantiates a new PatchUsersRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchUsersRequestWithDefaults() *PatchUsersRequest { + this := PatchUsersRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PatchUsersRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchUsersRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PatchUsersRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PatchUsersRequest) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *PatchUsersRequest) GetInstructions() []InstructionUserRequest { + if o == nil { + var ret []InstructionUserRequest + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *PatchUsersRequest) GetInstructionsOk() ([]InstructionUserRequest, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *PatchUsersRequest) SetInstructions(v []InstructionUserRequest) { + o.Instructions = v +} + +func (o PatchUsersRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullablePatchUsersRequest struct { + value *PatchUsersRequest + isSet bool +} + +func (v NullablePatchUsersRequest) Get() *PatchUsersRequest { + return v.value +} + +func (v *NullablePatchUsersRequest) Set(val *PatchUsersRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePatchUsersRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchUsersRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchUsersRequest(val *PatchUsersRequest) *NullablePatchUsersRequest { + return &NullablePatchUsersRequest{value: val, isSet: true} +} + +func (v NullablePatchUsersRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchUsersRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_with_comment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_with_comment.go new file mode 100644 index 00000000..8635aa17 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_patch_with_comment.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PatchWithComment struct for PatchWithComment +type PatchWithComment struct { + Patch []PatchOperation `json:"patch"` + // Optional comment + Comment *string `json:"comment,omitempty"` +} + +// NewPatchWithComment instantiates a new PatchWithComment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchWithComment(patch []PatchOperation) *PatchWithComment { + this := PatchWithComment{} + this.Patch = patch + return &this +} + +// NewPatchWithCommentWithDefaults instantiates a new PatchWithComment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchWithCommentWithDefaults() *PatchWithComment { + this := PatchWithComment{} + return &this +} + +// GetPatch returns the Patch field value +func (o *PatchWithComment) GetPatch() []PatchOperation { + if o == nil { + var ret []PatchOperation + return ret + } + + return o.Patch +} + +// GetPatchOk returns a tuple with the Patch field value +// and a boolean to check if the value has been set. +func (o *PatchWithComment) GetPatchOk() ([]PatchOperation, bool) { + if o == nil { + return nil, false + } + return o.Patch, true +} + +// SetPatch sets field value +func (o *PatchWithComment) SetPatch(v []PatchOperation) { + o.Patch = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PatchWithComment) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchWithComment) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PatchWithComment) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PatchWithComment) SetComment(v string) { + o.Comment = &v +} + +func (o PatchWithComment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["patch"] = o.Patch + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + return json.Marshal(toSerialize) +} + +type NullablePatchWithComment struct { + value *PatchWithComment + isSet bool +} + +func (v NullablePatchWithComment) Get() *PatchWithComment { + return v.value +} + +func (v *NullablePatchWithComment) Set(val *PatchWithComment) { + v.value = val + v.isSet = true +} + +func (v NullablePatchWithComment) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchWithComment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchWithComment(val *PatchWithComment) *NullablePatchWithComment { + return &NullablePatchWithComment{value: val, isSet: true} +} + +func (v NullablePatchWithComment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchWithComment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_permission_grant_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_permission_grant_input.go new file mode 100644 index 00000000..02f8f102 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_permission_grant_input.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PermissionGrantInput struct for PermissionGrantInput +type PermissionGrantInput struct { + // A group of related actions to allow. Specify either actionSet or actions. Use maintainTeam to add team maintainers. + ActionSet *string `json:"actionSet,omitempty"` + // A list of actions to allow. Specify either actionSet or actions. To learn more, read [Role actions](https://launchdarkly.com/docs/ld-docs/home/account/role-actions). + Actions []string `json:"actions,omitempty"` + // A list of member IDs who receive the permission grant. + MemberIDs []string `json:"memberIDs,omitempty"` +} + +// NewPermissionGrantInput instantiates a new PermissionGrantInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPermissionGrantInput() *PermissionGrantInput { + this := PermissionGrantInput{} + return &this +} + +// NewPermissionGrantInputWithDefaults instantiates a new PermissionGrantInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPermissionGrantInputWithDefaults() *PermissionGrantInput { + this := PermissionGrantInput{} + return &this +} + +// GetActionSet returns the ActionSet field value if set, zero value otherwise. +func (o *PermissionGrantInput) GetActionSet() string { + if o == nil || o.ActionSet == nil { + var ret string + return ret + } + return *o.ActionSet +} + +// GetActionSetOk returns a tuple with the ActionSet field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PermissionGrantInput) GetActionSetOk() (*string, bool) { + if o == nil || o.ActionSet == nil { + return nil, false + } + return o.ActionSet, true +} + +// HasActionSet returns a boolean if a field has been set. +func (o *PermissionGrantInput) HasActionSet() bool { + if o != nil && o.ActionSet != nil { + return true + } + + return false +} + +// SetActionSet gets a reference to the given string and assigns it to the ActionSet field. +func (o *PermissionGrantInput) SetActionSet(v string) { + o.ActionSet = &v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *PermissionGrantInput) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PermissionGrantInput) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *PermissionGrantInput) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *PermissionGrantInput) SetActions(v []string) { + o.Actions = v +} + +// GetMemberIDs returns the MemberIDs field value if set, zero value otherwise. +func (o *PermissionGrantInput) GetMemberIDs() []string { + if o == nil || o.MemberIDs == nil { + var ret []string + return ret + } + return o.MemberIDs +} + +// GetMemberIDsOk returns a tuple with the MemberIDs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PermissionGrantInput) GetMemberIDsOk() ([]string, bool) { + if o == nil || o.MemberIDs == nil { + return nil, false + } + return o.MemberIDs, true +} + +// HasMemberIDs returns a boolean if a field has been set. +func (o *PermissionGrantInput) HasMemberIDs() bool { + if o != nil && o.MemberIDs != nil { + return true + } + + return false +} + +// SetMemberIDs gets a reference to the given []string and assigns it to the MemberIDs field. +func (o *PermissionGrantInput) SetMemberIDs(v []string) { + o.MemberIDs = v +} + +func (o PermissionGrantInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ActionSet != nil { + toSerialize["actionSet"] = o.ActionSet + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.MemberIDs != nil { + toSerialize["memberIDs"] = o.MemberIDs + } + return json.Marshal(toSerialize) +} + +type NullablePermissionGrantInput struct { + value *PermissionGrantInput + isSet bool +} + +func (v NullablePermissionGrantInput) Get() *PermissionGrantInput { + return v.value +} + +func (v *NullablePermissionGrantInput) Set(val *PermissionGrantInput) { + v.value = val + v.isSet = true +} + +func (v NullablePermissionGrantInput) IsSet() bool { + return v.isSet +} + +func (v *NullablePermissionGrantInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePermissionGrantInput(val *PermissionGrantInput) *NullablePermissionGrantInput { + return &NullablePermissionGrantInput{value: val, isSet: true} +} + +func (v NullablePermissionGrantInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePermissionGrantInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_phase.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_phase.go new file mode 100644 index 00000000..d16d7532 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_phase.go @@ -0,0 +1,205 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Phase struct for Phase +type Phase struct { + // The phase ID + Id string `json:"id"` + Audiences []Audience `json:"audiences"` + // The release phase name + Name string `json:"name"` + Configuration map[string]interface{} `json:"configuration,omitempty"` +} + +// NewPhase instantiates a new Phase object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPhase(id string, audiences []Audience, name string) *Phase { + this := Phase{} + this.Id = id + this.Audiences = audiences + this.Name = name + return &this +} + +// NewPhaseWithDefaults instantiates a new Phase object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPhaseWithDefaults() *Phase { + this := Phase{} + return &this +} + +// GetId returns the Id field value +func (o *Phase) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Phase) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Phase) SetId(v string) { + o.Id = v +} + +// GetAudiences returns the Audiences field value +func (o *Phase) GetAudiences() []Audience { + if o == nil { + var ret []Audience + return ret + } + + return o.Audiences +} + +// GetAudiencesOk returns a tuple with the Audiences field value +// and a boolean to check if the value has been set. +func (o *Phase) GetAudiencesOk() ([]Audience, bool) { + if o == nil { + return nil, false + } + return o.Audiences, true +} + +// SetAudiences sets field value +func (o *Phase) SetAudiences(v []Audience) { + o.Audiences = v +} + +// GetName returns the Name field value +func (o *Phase) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Phase) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Phase) SetName(v string) { + o.Name = v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *Phase) GetConfiguration() map[string]interface{} { + if o == nil || o.Configuration == nil { + var ret map[string]interface{} + return ret + } + return o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Phase) GetConfigurationOk() (map[string]interface{}, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *Phase) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given map[string]interface{} and assigns it to the Configuration field. +func (o *Phase) SetConfiguration(v map[string]interface{}) { + o.Configuration = v +} + +func (o Phase) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["audiences"] = o.Audiences + } + if true { + toSerialize["name"] = o.Name + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + return json.Marshal(toSerialize) +} + +type NullablePhase struct { + value *Phase + isSet bool +} + +func (v NullablePhase) Get() *Phase { + return v.value +} + +func (v *NullablePhase) Set(val *Phase) { + v.value = val + v.isSet = true +} + +func (v NullablePhase) IsSet() bool { + return v.isSet +} + +func (v *NullablePhase) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePhase(val *Phase) *NullablePhase { + return &NullablePhase{value: val, isSet: true} +} + +func (v NullablePhase) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePhase) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_phase_info.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_phase_info.go new file mode 100644 index 00000000..62b234f1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_phase_info.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PhaseInfo struct for PhaseInfo +type PhaseInfo struct { + // The phase ID + Id string `json:"_id"` + // The release phase name + Name string `json:"name"` + // The number of active releases in this phase + ReleaseCount int32 `json:"releaseCount"` +} + +// NewPhaseInfo instantiates a new PhaseInfo object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPhaseInfo(id string, name string, releaseCount int32) *PhaseInfo { + this := PhaseInfo{} + this.Id = id + this.Name = name + this.ReleaseCount = releaseCount + return &this +} + +// NewPhaseInfoWithDefaults instantiates a new PhaseInfo object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPhaseInfoWithDefaults() *PhaseInfo { + this := PhaseInfo{} + return &this +} + +// GetId returns the Id field value +func (o *PhaseInfo) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *PhaseInfo) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *PhaseInfo) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value +func (o *PhaseInfo) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *PhaseInfo) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *PhaseInfo) SetName(v string) { + o.Name = v +} + +// GetReleaseCount returns the ReleaseCount field value +func (o *PhaseInfo) GetReleaseCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ReleaseCount +} + +// GetReleaseCountOk returns a tuple with the ReleaseCount field value +// and a boolean to check if the value has been set. +func (o *PhaseInfo) GetReleaseCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ReleaseCount, true +} + +// SetReleaseCount sets field value +func (o *PhaseInfo) SetReleaseCount(v int32) { + o.ReleaseCount = v +} + +func (o PhaseInfo) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["releaseCount"] = o.ReleaseCount + } + return json.Marshal(toSerialize) +} + +type NullablePhaseInfo struct { + value *PhaseInfo + isSet bool +} + +func (v NullablePhaseInfo) Get() *PhaseInfo { + return v.value +} + +func (v *NullablePhaseInfo) Set(val *PhaseInfo) { + v.value = val + v.isSet = true +} + +func (v NullablePhaseInfo) IsSet() bool { + return v.isSet +} + +func (v *NullablePhaseInfo) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePhaseInfo(val *PhaseInfo) *NullablePhaseInfo { + return &NullablePhaseInfo{value: val, isSet: true} +} + +func (v NullablePhaseInfo) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePhaseInfo) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_apply_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_apply_request.go new file mode 100644 index 00000000..76b62215 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_apply_request.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PostApprovalRequestApplyRequest struct for PostApprovalRequestApplyRequest +type PostApprovalRequestApplyRequest struct { + // Optional comment about the approval request + Comment *string `json:"comment,omitempty"` +} + +// NewPostApprovalRequestApplyRequest instantiates a new PostApprovalRequestApplyRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostApprovalRequestApplyRequest() *PostApprovalRequestApplyRequest { + this := PostApprovalRequestApplyRequest{} + return &this +} + +// NewPostApprovalRequestApplyRequestWithDefaults instantiates a new PostApprovalRequestApplyRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostApprovalRequestApplyRequestWithDefaults() *PostApprovalRequestApplyRequest { + this := PostApprovalRequestApplyRequest{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PostApprovalRequestApplyRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostApprovalRequestApplyRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PostApprovalRequestApplyRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PostApprovalRequestApplyRequest) SetComment(v string) { + o.Comment = &v +} + +func (o PostApprovalRequestApplyRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + return json.Marshal(toSerialize) +} + +type NullablePostApprovalRequestApplyRequest struct { + value *PostApprovalRequestApplyRequest + isSet bool +} + +func (v NullablePostApprovalRequestApplyRequest) Get() *PostApprovalRequestApplyRequest { + return v.value +} + +func (v *NullablePostApprovalRequestApplyRequest) Set(val *PostApprovalRequestApplyRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePostApprovalRequestApplyRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePostApprovalRequestApplyRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostApprovalRequestApplyRequest(val *PostApprovalRequestApplyRequest) *NullablePostApprovalRequestApplyRequest { + return &NullablePostApprovalRequestApplyRequest{value: val, isSet: true} +} + +func (v NullablePostApprovalRequestApplyRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostApprovalRequestApplyRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_review_request.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_review_request.go new file mode 100644 index 00000000..b57a047a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_approval_request_review_request.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PostApprovalRequestReviewRequest struct for PostApprovalRequestReviewRequest +type PostApprovalRequestReviewRequest struct { + // The type of review for this approval request + Kind *string `json:"kind,omitempty"` + // Optional comment about the approval request + Comment *string `json:"comment,omitempty"` +} + +// NewPostApprovalRequestReviewRequest instantiates a new PostApprovalRequestReviewRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostApprovalRequestReviewRequest() *PostApprovalRequestReviewRequest { + this := PostApprovalRequestReviewRequest{} + return &this +} + +// NewPostApprovalRequestReviewRequestWithDefaults instantiates a new PostApprovalRequestReviewRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostApprovalRequestReviewRequestWithDefaults() *PostApprovalRequestReviewRequest { + this := PostApprovalRequestReviewRequest{} + return &this +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *PostApprovalRequestReviewRequest) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostApprovalRequestReviewRequest) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *PostApprovalRequestReviewRequest) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *PostApprovalRequestReviewRequest) SetKind(v string) { + o.Kind = &v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PostApprovalRequestReviewRequest) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostApprovalRequestReviewRequest) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PostApprovalRequestReviewRequest) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PostApprovalRequestReviewRequest) SetComment(v string) { + o.Comment = &v +} + +func (o PostApprovalRequestReviewRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + return json.Marshal(toSerialize) +} + +type NullablePostApprovalRequestReviewRequest struct { + value *PostApprovalRequestReviewRequest + isSet bool +} + +func (v NullablePostApprovalRequestReviewRequest) Get() *PostApprovalRequestReviewRequest { + return v.value +} + +func (v *NullablePostApprovalRequestReviewRequest) Set(val *PostApprovalRequestReviewRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePostApprovalRequestReviewRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePostApprovalRequestReviewRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostApprovalRequestReviewRequest(val *PostApprovalRequestReviewRequest) *NullablePostApprovalRequestReviewRequest { + return &NullablePostApprovalRequestReviewRequest{value: val, isSet: true} +} + +func (v NullablePostApprovalRequestReviewRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostApprovalRequestReviewRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_post_deployment_event_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_deployment_event_input.go new file mode 100644 index 00000000..252da439 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_deployment_event_input.go @@ -0,0 +1,451 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PostDeploymentEventInput struct for PostDeploymentEventInput +type PostDeploymentEventInput struct { + // The project key + ProjectKey string `json:"projectKey"` + // The environment key + EnvironmentKey string `json:"environmentKey"` + // The application key. This defines the granularity at which you want to view your insights metrics. Typically it is the name of one of the GitHub repositories that you use in this project.

LaunchDarkly automatically creates a new application each time you send a unique application key. + ApplicationKey string `json:"applicationKey"` + // The application name. This defines how the application is displayed + ApplicationName *string `json:"applicationName,omitempty"` + // The kind of application. Default: server + ApplicationKind *string `json:"applicationKind,omitempty"` + // The application version. You can set the application version to any string that includes only letters, numbers, periods (.), hyphens (-), or underscores (_).

We recommend setting the application version to at least the first seven characters of the SHA or to the tag of the GitHub commit for this deployment. + Version string `json:"version"` + // The version name. This defines how the version is displayed + VersionName *string `json:"versionName,omitempty"` + // The event type + EventType string `json:"eventType"` + EventTime *int64 `json:"eventTime,omitempty"` + // A JSON object containing metadata about the event + EventMetadata map[string]interface{} `json:"eventMetadata,omitempty"` + // A JSON object containing metadata about the deployment + DeploymentMetadata map[string]interface{} `json:"deploymentMetadata,omitempty"` +} + +// NewPostDeploymentEventInput instantiates a new PostDeploymentEventInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostDeploymentEventInput(projectKey string, environmentKey string, applicationKey string, version string, eventType string) *PostDeploymentEventInput { + this := PostDeploymentEventInput{} + this.ProjectKey = projectKey + this.EnvironmentKey = environmentKey + this.ApplicationKey = applicationKey + this.Version = version + this.EventType = eventType + return &this +} + +// NewPostDeploymentEventInputWithDefaults instantiates a new PostDeploymentEventInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostDeploymentEventInputWithDefaults() *PostDeploymentEventInput { + this := PostDeploymentEventInput{} + return &this +} + +// GetProjectKey returns the ProjectKey field value +func (o *PostDeploymentEventInput) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *PostDeploymentEventInput) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *PostDeploymentEventInput) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *PostDeploymentEventInput) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetApplicationKey returns the ApplicationKey field value +func (o *PostDeploymentEventInput) GetApplicationKey() string { + if o == nil { + var ret string + return ret + } + + return o.ApplicationKey +} + +// GetApplicationKeyOk returns a tuple with the ApplicationKey field value +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetApplicationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ApplicationKey, true +} + +// SetApplicationKey sets field value +func (o *PostDeploymentEventInput) SetApplicationKey(v string) { + o.ApplicationKey = v +} + +// GetApplicationName returns the ApplicationName field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetApplicationName() string { + if o == nil || o.ApplicationName == nil { + var ret string + return ret + } + return *o.ApplicationName +} + +// GetApplicationNameOk returns a tuple with the ApplicationName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetApplicationNameOk() (*string, bool) { + if o == nil || o.ApplicationName == nil { + return nil, false + } + return o.ApplicationName, true +} + +// HasApplicationName returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasApplicationName() bool { + if o != nil && o.ApplicationName != nil { + return true + } + + return false +} + +// SetApplicationName gets a reference to the given string and assigns it to the ApplicationName field. +func (o *PostDeploymentEventInput) SetApplicationName(v string) { + o.ApplicationName = &v +} + +// GetApplicationKind returns the ApplicationKind field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetApplicationKind() string { + if o == nil || o.ApplicationKind == nil { + var ret string + return ret + } + return *o.ApplicationKind +} + +// GetApplicationKindOk returns a tuple with the ApplicationKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetApplicationKindOk() (*string, bool) { + if o == nil || o.ApplicationKind == nil { + return nil, false + } + return o.ApplicationKind, true +} + +// HasApplicationKind returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasApplicationKind() bool { + if o != nil && o.ApplicationKind != nil { + return true + } + + return false +} + +// SetApplicationKind gets a reference to the given string and assigns it to the ApplicationKind field. +func (o *PostDeploymentEventInput) SetApplicationKind(v string) { + o.ApplicationKind = &v +} + +// GetVersion returns the Version field value +func (o *PostDeploymentEventInput) GetVersion() string { + if o == nil { + var ret string + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetVersionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *PostDeploymentEventInput) SetVersion(v string) { + o.Version = v +} + +// GetVersionName returns the VersionName field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetVersionName() string { + if o == nil || o.VersionName == nil { + var ret string + return ret + } + return *o.VersionName +} + +// GetVersionNameOk returns a tuple with the VersionName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetVersionNameOk() (*string, bool) { + if o == nil || o.VersionName == nil { + return nil, false + } + return o.VersionName, true +} + +// HasVersionName returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasVersionName() bool { + if o != nil && o.VersionName != nil { + return true + } + + return false +} + +// SetVersionName gets a reference to the given string and assigns it to the VersionName field. +func (o *PostDeploymentEventInput) SetVersionName(v string) { + o.VersionName = &v +} + +// GetEventType returns the EventType field value +func (o *PostDeploymentEventInput) GetEventType() string { + if o == nil { + var ret string + return ret + } + + return o.EventType +} + +// GetEventTypeOk returns a tuple with the EventType field value +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetEventTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EventType, true +} + +// SetEventType sets field value +func (o *PostDeploymentEventInput) SetEventType(v string) { + o.EventType = v +} + +// GetEventTime returns the EventTime field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetEventTime() int64 { + if o == nil || o.EventTime == nil { + var ret int64 + return ret + } + return *o.EventTime +} + +// GetEventTimeOk returns a tuple with the EventTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetEventTimeOk() (*int64, bool) { + if o == nil || o.EventTime == nil { + return nil, false + } + return o.EventTime, true +} + +// HasEventTime returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasEventTime() bool { + if o != nil && o.EventTime != nil { + return true + } + + return false +} + +// SetEventTime gets a reference to the given int64 and assigns it to the EventTime field. +func (o *PostDeploymentEventInput) SetEventTime(v int64) { + o.EventTime = &v +} + +// GetEventMetadata returns the EventMetadata field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetEventMetadata() map[string]interface{} { + if o == nil || o.EventMetadata == nil { + var ret map[string]interface{} + return ret + } + return o.EventMetadata +} + +// GetEventMetadataOk returns a tuple with the EventMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetEventMetadataOk() (map[string]interface{}, bool) { + if o == nil || o.EventMetadata == nil { + return nil, false + } + return o.EventMetadata, true +} + +// HasEventMetadata returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasEventMetadata() bool { + if o != nil && o.EventMetadata != nil { + return true + } + + return false +} + +// SetEventMetadata gets a reference to the given map[string]interface{} and assigns it to the EventMetadata field. +func (o *PostDeploymentEventInput) SetEventMetadata(v map[string]interface{}) { + o.EventMetadata = v +} + +// GetDeploymentMetadata returns the DeploymentMetadata field value if set, zero value otherwise. +func (o *PostDeploymentEventInput) GetDeploymentMetadata() map[string]interface{} { + if o == nil || o.DeploymentMetadata == nil { + var ret map[string]interface{} + return ret + } + return o.DeploymentMetadata +} + +// GetDeploymentMetadataOk returns a tuple with the DeploymentMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostDeploymentEventInput) GetDeploymentMetadataOk() (map[string]interface{}, bool) { + if o == nil || o.DeploymentMetadata == nil { + return nil, false + } + return o.DeploymentMetadata, true +} + +// HasDeploymentMetadata returns a boolean if a field has been set. +func (o *PostDeploymentEventInput) HasDeploymentMetadata() bool { + if o != nil && o.DeploymentMetadata != nil { + return true + } + + return false +} + +// SetDeploymentMetadata gets a reference to the given map[string]interface{} and assigns it to the DeploymentMetadata field. +func (o *PostDeploymentEventInput) SetDeploymentMetadata(v map[string]interface{}) { + o.DeploymentMetadata = v +} + +func (o PostDeploymentEventInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if true { + toSerialize["applicationKey"] = o.ApplicationKey + } + if o.ApplicationName != nil { + toSerialize["applicationName"] = o.ApplicationName + } + if o.ApplicationKind != nil { + toSerialize["applicationKind"] = o.ApplicationKind + } + if true { + toSerialize["version"] = o.Version + } + if o.VersionName != nil { + toSerialize["versionName"] = o.VersionName + } + if true { + toSerialize["eventType"] = o.EventType + } + if o.EventTime != nil { + toSerialize["eventTime"] = o.EventTime + } + if o.EventMetadata != nil { + toSerialize["eventMetadata"] = o.EventMetadata + } + if o.DeploymentMetadata != nil { + toSerialize["deploymentMetadata"] = o.DeploymentMetadata + } + return json.Marshal(toSerialize) +} + +type NullablePostDeploymentEventInput struct { + value *PostDeploymentEventInput + isSet bool +} + +func (v NullablePostDeploymentEventInput) Get() *PostDeploymentEventInput { + return v.value +} + +func (v *NullablePostDeploymentEventInput) Set(val *PostDeploymentEventInput) { + v.value = val + v.isSet = true +} + +func (v NullablePostDeploymentEventInput) IsSet() bool { + return v.isSet +} + +func (v *NullablePostDeploymentEventInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostDeploymentEventInput(val *PostDeploymentEventInput) *NullablePostDeploymentEventInput { + return &NullablePostDeploymentEventInput{value: val, isSet: true} +} + +func (v NullablePostDeploymentEventInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostDeploymentEventInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_post_flag_scheduled_changes_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_flag_scheduled_changes_input.go new file mode 100644 index 00000000..cff3bbea --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_flag_scheduled_changes_input.go @@ -0,0 +1,175 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PostFlagScheduledChangesInput struct for PostFlagScheduledChangesInput +type PostFlagScheduledChangesInput struct { + // Optional comment describing the scheduled changes + Comment *string `json:"comment,omitempty"` + ExecutionDate int64 `json:"executionDate"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewPostFlagScheduledChangesInput instantiates a new PostFlagScheduledChangesInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostFlagScheduledChangesInput(executionDate int64, instructions []map[string]interface{}) *PostFlagScheduledChangesInput { + this := PostFlagScheduledChangesInput{} + this.ExecutionDate = executionDate + this.Instructions = instructions + return &this +} + +// NewPostFlagScheduledChangesInputWithDefaults instantiates a new PostFlagScheduledChangesInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostFlagScheduledChangesInputWithDefaults() *PostFlagScheduledChangesInput { + this := PostFlagScheduledChangesInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *PostFlagScheduledChangesInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostFlagScheduledChangesInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *PostFlagScheduledChangesInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *PostFlagScheduledChangesInput) SetComment(v string) { + o.Comment = &v +} + +// GetExecutionDate returns the ExecutionDate field value +func (o *PostFlagScheduledChangesInput) GetExecutionDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.ExecutionDate +} + +// GetExecutionDateOk returns a tuple with the ExecutionDate field value +// and a boolean to check if the value has been set. +func (o *PostFlagScheduledChangesInput) GetExecutionDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.ExecutionDate, true +} + +// SetExecutionDate sets field value +func (o *PostFlagScheduledChangesInput) SetExecutionDate(v int64) { + o.ExecutionDate = v +} + +// GetInstructions returns the Instructions field value +func (o *PostFlagScheduledChangesInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *PostFlagScheduledChangesInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *PostFlagScheduledChangesInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o PostFlagScheduledChangesInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["executionDate"] = o.ExecutionDate + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullablePostFlagScheduledChangesInput struct { + value *PostFlagScheduledChangesInput + isSet bool +} + +func (v NullablePostFlagScheduledChangesInput) Get() *PostFlagScheduledChangesInput { + return v.value +} + +func (v *NullablePostFlagScheduledChangesInput) Set(val *PostFlagScheduledChangesInput) { + v.value = val + v.isSet = true +} + +func (v NullablePostFlagScheduledChangesInput) IsSet() bool { + return v.isSet +} + +func (v *NullablePostFlagScheduledChangesInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostFlagScheduledChangesInput(val *PostFlagScheduledChangesInput) *NullablePostFlagScheduledChangesInput { + return &NullablePostFlagScheduledChangesInput{value: val, isSet: true} +} + +func (v NullablePostFlagScheduledChangesInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostFlagScheduledChangesInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_post_insight_group_params.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_insight_group_params.go new file mode 100644 index 00000000..58e26aa2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_post_insight_group_params.go @@ -0,0 +1,237 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PostInsightGroupParams struct for PostInsightGroupParams +type PostInsightGroupParams struct { + // The name of the insight group + Name string `json:"name"` + // The key of the insight group + Key string `json:"key"` + // The projectKey to be associated with the insight group + ProjectKey string `json:"projectKey"` + // The environmentKey to be associated with the insight group + EnvironmentKey string `json:"environmentKey"` + // The application keys to associate with the insight group. If not provided, the insight group will include data from all applications. + ApplicationKeys []string `json:"applicationKeys,omitempty"` +} + +// NewPostInsightGroupParams instantiates a new PostInsightGroupParams object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostInsightGroupParams(name string, key string, projectKey string, environmentKey string) *PostInsightGroupParams { + this := PostInsightGroupParams{} + this.Name = name + this.Key = key + this.ProjectKey = projectKey + this.EnvironmentKey = environmentKey + return &this +} + +// NewPostInsightGroupParamsWithDefaults instantiates a new PostInsightGroupParams object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostInsightGroupParamsWithDefaults() *PostInsightGroupParams { + this := PostInsightGroupParams{} + return &this +} + +// GetName returns the Name field value +func (o *PostInsightGroupParams) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *PostInsightGroupParams) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *PostInsightGroupParams) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *PostInsightGroupParams) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *PostInsightGroupParams) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *PostInsightGroupParams) SetKey(v string) { + o.Key = v +} + +// GetProjectKey returns the ProjectKey field value +func (o *PostInsightGroupParams) GetProjectKey() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value +// and a boolean to check if the value has been set. +func (o *PostInsightGroupParams) GetProjectKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectKey, true +} + +// SetProjectKey sets field value +func (o *PostInsightGroupParams) SetProjectKey(v string) { + o.ProjectKey = v +} + +// GetEnvironmentKey returns the EnvironmentKey field value +func (o *PostInsightGroupParams) GetEnvironmentKey() string { + if o == nil { + var ret string + return ret + } + + return o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value +// and a boolean to check if the value has been set. +func (o *PostInsightGroupParams) GetEnvironmentKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.EnvironmentKey, true +} + +// SetEnvironmentKey sets field value +func (o *PostInsightGroupParams) SetEnvironmentKey(v string) { + o.EnvironmentKey = v +} + +// GetApplicationKeys returns the ApplicationKeys field value if set, zero value otherwise. +func (o *PostInsightGroupParams) GetApplicationKeys() []string { + if o == nil || o.ApplicationKeys == nil { + var ret []string + return ret + } + return o.ApplicationKeys +} + +// GetApplicationKeysOk returns a tuple with the ApplicationKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostInsightGroupParams) GetApplicationKeysOk() ([]string, bool) { + if o == nil || o.ApplicationKeys == nil { + return nil, false + } + return o.ApplicationKeys, true +} + +// HasApplicationKeys returns a boolean if a field has been set. +func (o *PostInsightGroupParams) HasApplicationKeys() bool { + if o != nil && o.ApplicationKeys != nil { + return true + } + + return false +} + +// SetApplicationKeys gets a reference to the given []string and assigns it to the ApplicationKeys field. +func (o *PostInsightGroupParams) SetApplicationKeys(v []string) { + o.ApplicationKeys = v +} + +func (o PostInsightGroupParams) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["projectKey"] = o.ProjectKey + } + if true { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.ApplicationKeys != nil { + toSerialize["applicationKeys"] = o.ApplicationKeys + } + return json.Marshal(toSerialize) +} + +type NullablePostInsightGroupParams struct { + value *PostInsightGroupParams + isSet bool +} + +func (v NullablePostInsightGroupParams) Get() *PostInsightGroupParams { + return v.value +} + +func (v *NullablePostInsightGroupParams) Set(val *PostInsightGroupParams) { + v.value = val + v.isSet = true +} + +func (v NullablePostInsightGroupParams) IsSet() bool { + return v.isSet +} + +func (v *NullablePostInsightGroupParams) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostInsightGroupParams(val *PostInsightGroupParams) *NullablePostInsightGroupParams { + return &NullablePostInsightGroupParams{value: val, isSet: true} +} + +func (v NullablePostInsightGroupParams) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostInsightGroupParams) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_prerequisite.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_prerequisite.go new file mode 100644 index 00000000..6a275104 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_prerequisite.go @@ -0,0 +1,138 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Prerequisite struct for Prerequisite +type Prerequisite struct { + Key string `json:"key"` + Variation int32 `json:"variation"` +} + +// NewPrerequisite instantiates a new Prerequisite object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPrerequisite(key string, variation int32) *Prerequisite { + this := Prerequisite{} + this.Key = key + this.Variation = variation + return &this +} + +// NewPrerequisiteWithDefaults instantiates a new Prerequisite object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPrerequisiteWithDefaults() *Prerequisite { + this := Prerequisite{} + return &this +} + +// GetKey returns the Key field value +func (o *Prerequisite) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *Prerequisite) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *Prerequisite) SetKey(v string) { + o.Key = v +} + +// GetVariation returns the Variation field value +func (o *Prerequisite) GetVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Variation +} + +// GetVariationOk returns a tuple with the Variation field value +// and a boolean to check if the value has been set. +func (o *Prerequisite) GetVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Variation, true +} + +// SetVariation sets field value +func (o *Prerequisite) SetVariation(v int32) { + o.Variation = v +} + +func (o Prerequisite) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["variation"] = o.Variation + } + return json.Marshal(toSerialize) +} + +type NullablePrerequisite struct { + value *Prerequisite + isSet bool +} + +func (v NullablePrerequisite) Get() *Prerequisite { + return v.value +} + +func (v *NullablePrerequisite) Set(val *Prerequisite) { + v.value = val + v.isSet = true +} + +func (v NullablePrerequisite) IsSet() bool { + return v.isSet +} + +func (v *NullablePrerequisite) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePrerequisite(val *Prerequisite) *NullablePrerequisite { + return &NullablePrerequisite{value: val, isSet: true} +} + +func (v NullablePrerequisite) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePrerequisite) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_project.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_project.go new file mode 100644 index 00000000..09f12dd3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_project.go @@ -0,0 +1,405 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Project struct for Project +type Project struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of this project + Id string `json:"_id"` + // The key of this project + Key string `json:"key"` + // Whether or not flags created in this project are made available to the client-side JavaScript SDK by default + IncludeInSnippetByDefault bool `json:"includeInSnippetByDefault"` + DefaultClientSideAvailability *ClientSideAvailability `json:"defaultClientSideAvailability,omitempty"` + // A human-friendly name for the project + Name string `json:"name"` + Access *Access `json:"_access,omitempty"` + // A list of tags for the project + Tags []string `json:"tags"` + // The key of the default release pipeline for this project + DefaultReleasePipelineKey *string `json:"defaultReleasePipelineKey,omitempty"` + Environments *Environments `json:"environments,omitempty"` +} + +// NewProject instantiates a new Project object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProject(links map[string]Link, id string, key string, includeInSnippetByDefault bool, name string, tags []string) *Project { + this := Project{} + this.Links = links + this.Id = id + this.Key = key + this.IncludeInSnippetByDefault = includeInSnippetByDefault + this.Name = name + this.Tags = tags + return &this +} + +// NewProjectWithDefaults instantiates a new Project object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectWithDefaults() *Project { + this := Project{} + return &this +} + +// GetLinks returns the Links field value +func (o *Project) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Project) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Project) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *Project) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Project) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Project) SetId(v string) { + o.Id = v +} + +// GetKey returns the Key field value +func (o *Project) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *Project) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *Project) SetKey(v string) { + o.Key = v +} + +// GetIncludeInSnippetByDefault returns the IncludeInSnippetByDefault field value +func (o *Project) GetIncludeInSnippetByDefault() bool { + if o == nil { + var ret bool + return ret + } + + return o.IncludeInSnippetByDefault +} + +// GetIncludeInSnippetByDefaultOk returns a tuple with the IncludeInSnippetByDefault field value +// and a boolean to check if the value has been set. +func (o *Project) GetIncludeInSnippetByDefaultOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IncludeInSnippetByDefault, true +} + +// SetIncludeInSnippetByDefault sets field value +func (o *Project) SetIncludeInSnippetByDefault(v bool) { + o.IncludeInSnippetByDefault = v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value if set, zero value otherwise. +func (o *Project) GetDefaultClientSideAvailability() ClientSideAvailability { + if o == nil || o.DefaultClientSideAvailability == nil { + var ret ClientSideAvailability + return ret + } + return *o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Project) GetDefaultClientSideAvailabilityOk() (*ClientSideAvailability, bool) { + if o == nil || o.DefaultClientSideAvailability == nil { + return nil, false + } + return o.DefaultClientSideAvailability, true +} + +// HasDefaultClientSideAvailability returns a boolean if a field has been set. +func (o *Project) HasDefaultClientSideAvailability() bool { + if o != nil && o.DefaultClientSideAvailability != nil { + return true + } + + return false +} + +// SetDefaultClientSideAvailability gets a reference to the given ClientSideAvailability and assigns it to the DefaultClientSideAvailability field. +func (o *Project) SetDefaultClientSideAvailability(v ClientSideAvailability) { + o.DefaultClientSideAvailability = &v +} + +// GetName returns the Name field value +func (o *Project) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Project) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Project) SetName(v string) { + o.Name = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *Project) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Project) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *Project) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *Project) SetAccess(v Access) { + o.Access = &v +} + +// GetTags returns the Tags field value +func (o *Project) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *Project) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *Project) SetTags(v []string) { + o.Tags = v +} + +// GetDefaultReleasePipelineKey returns the DefaultReleasePipelineKey field value if set, zero value otherwise. +func (o *Project) GetDefaultReleasePipelineKey() string { + if o == nil || o.DefaultReleasePipelineKey == nil { + var ret string + return ret + } + return *o.DefaultReleasePipelineKey +} + +// GetDefaultReleasePipelineKeyOk returns a tuple with the DefaultReleasePipelineKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Project) GetDefaultReleasePipelineKeyOk() (*string, bool) { + if o == nil || o.DefaultReleasePipelineKey == nil { + return nil, false + } + return o.DefaultReleasePipelineKey, true +} + +// HasDefaultReleasePipelineKey returns a boolean if a field has been set. +func (o *Project) HasDefaultReleasePipelineKey() bool { + if o != nil && o.DefaultReleasePipelineKey != nil { + return true + } + + return false +} + +// SetDefaultReleasePipelineKey gets a reference to the given string and assigns it to the DefaultReleasePipelineKey field. +func (o *Project) SetDefaultReleasePipelineKey(v string) { + o.DefaultReleasePipelineKey = &v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *Project) GetEnvironments() Environments { + if o == nil || o.Environments == nil { + var ret Environments + return ret + } + return *o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Project) GetEnvironmentsOk() (*Environments, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *Project) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given Environments and assigns it to the Environments field. +func (o *Project) SetEnvironments(v Environments) { + o.Environments = &v +} + +func (o Project) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["includeInSnippetByDefault"] = o.IncludeInSnippetByDefault + } + if o.DefaultClientSideAvailability != nil { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + if true { + toSerialize["name"] = o.Name + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["tags"] = o.Tags + } + if o.DefaultReleasePipelineKey != nil { + toSerialize["defaultReleasePipelineKey"] = o.DefaultReleasePipelineKey + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + return json.Marshal(toSerialize) +} + +type NullableProject struct { + value *Project + isSet bool +} + +func (v NullableProject) Get() *Project { + return v.value +} + +func (v *NullableProject) Set(val *Project) { + v.value = val + v.isSet = true +} + +func (v NullableProject) IsSet() bool { + return v.isSet +} + +func (v *NullableProject) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProject(val *Project) *NullableProject { + return &NullableProject{value: val, isSet: true} +} + +func (v NullableProject) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProject) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_project_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_post.go new file mode 100644 index 00000000..992fb900 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_post.go @@ -0,0 +1,323 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ProjectPost struct for ProjectPost +type ProjectPost struct { + // A human-friendly name for the project. + Name string `json:"name"` + // A unique key used to reference the project in your code. + Key string `json:"key"` + // Whether or not flags created in this project are made available to the client-side JavaScript SDK by default. + IncludeInSnippetByDefault *bool `json:"includeInSnippetByDefault,omitempty"` + DefaultClientSideAvailability *DefaultClientSideAvailabilityPost `json:"defaultClientSideAvailability,omitempty"` + // Tags for the project + Tags []string `json:"tags,omitempty"` + // Creates the provided environments for this project. If omitted default environments will be created instead. + Environments []EnvironmentPost `json:"environments,omitempty"` + NamingConvention *NamingConvention `json:"namingConvention,omitempty"` +} + +// NewProjectPost instantiates a new ProjectPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProjectPost(name string, key string) *ProjectPost { + this := ProjectPost{} + this.Name = name + this.Key = key + return &this +} + +// NewProjectPostWithDefaults instantiates a new ProjectPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectPostWithDefaults() *ProjectPost { + this := ProjectPost{} + return &this +} + +// GetName returns the Name field value +func (o *ProjectPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ProjectPost) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *ProjectPost) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ProjectPost) SetKey(v string) { + o.Key = v +} + +// GetIncludeInSnippetByDefault returns the IncludeInSnippetByDefault field value if set, zero value otherwise. +func (o *ProjectPost) GetIncludeInSnippetByDefault() bool { + if o == nil || o.IncludeInSnippetByDefault == nil { + var ret bool + return ret + } + return *o.IncludeInSnippetByDefault +} + +// GetIncludeInSnippetByDefaultOk returns a tuple with the IncludeInSnippetByDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetIncludeInSnippetByDefaultOk() (*bool, bool) { + if o == nil || o.IncludeInSnippetByDefault == nil { + return nil, false + } + return o.IncludeInSnippetByDefault, true +} + +// HasIncludeInSnippetByDefault returns a boolean if a field has been set. +func (o *ProjectPost) HasIncludeInSnippetByDefault() bool { + if o != nil && o.IncludeInSnippetByDefault != nil { + return true + } + + return false +} + +// SetIncludeInSnippetByDefault gets a reference to the given bool and assigns it to the IncludeInSnippetByDefault field. +func (o *ProjectPost) SetIncludeInSnippetByDefault(v bool) { + o.IncludeInSnippetByDefault = &v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value if set, zero value otherwise. +func (o *ProjectPost) GetDefaultClientSideAvailability() DefaultClientSideAvailabilityPost { + if o == nil || o.DefaultClientSideAvailability == nil { + var ret DefaultClientSideAvailabilityPost + return ret + } + return *o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetDefaultClientSideAvailabilityOk() (*DefaultClientSideAvailabilityPost, bool) { + if o == nil || o.DefaultClientSideAvailability == nil { + return nil, false + } + return o.DefaultClientSideAvailability, true +} + +// HasDefaultClientSideAvailability returns a boolean if a field has been set. +func (o *ProjectPost) HasDefaultClientSideAvailability() bool { + if o != nil && o.DefaultClientSideAvailability != nil { + return true + } + + return false +} + +// SetDefaultClientSideAvailability gets a reference to the given DefaultClientSideAvailabilityPost and assigns it to the DefaultClientSideAvailability field. +func (o *ProjectPost) SetDefaultClientSideAvailability(v DefaultClientSideAvailabilityPost) { + o.DefaultClientSideAvailability = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *ProjectPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *ProjectPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *ProjectPost) SetTags(v []string) { + o.Tags = v +} + +// GetEnvironments returns the Environments field value if set, zero value otherwise. +func (o *ProjectPost) GetEnvironments() []EnvironmentPost { + if o == nil || o.Environments == nil { + var ret []EnvironmentPost + return ret + } + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetEnvironmentsOk() ([]EnvironmentPost, bool) { + if o == nil || o.Environments == nil { + return nil, false + } + return o.Environments, true +} + +// HasEnvironments returns a boolean if a field has been set. +func (o *ProjectPost) HasEnvironments() bool { + if o != nil && o.Environments != nil { + return true + } + + return false +} + +// SetEnvironments gets a reference to the given []EnvironmentPost and assigns it to the Environments field. +func (o *ProjectPost) SetEnvironments(v []EnvironmentPost) { + o.Environments = v +} + +// GetNamingConvention returns the NamingConvention field value if set, zero value otherwise. +func (o *ProjectPost) GetNamingConvention() NamingConvention { + if o == nil || o.NamingConvention == nil { + var ret NamingConvention + return ret + } + return *o.NamingConvention +} + +// GetNamingConventionOk returns a tuple with the NamingConvention field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectPost) GetNamingConventionOk() (*NamingConvention, bool) { + if o == nil || o.NamingConvention == nil { + return nil, false + } + return o.NamingConvention, true +} + +// HasNamingConvention returns a boolean if a field has been set. +func (o *ProjectPost) HasNamingConvention() bool { + if o != nil && o.NamingConvention != nil { + return true + } + + return false +} + +// SetNamingConvention gets a reference to the given NamingConvention and assigns it to the NamingConvention field. +func (o *ProjectPost) SetNamingConvention(v NamingConvention) { + o.NamingConvention = &v +} + +func (o ProjectPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.IncludeInSnippetByDefault != nil { + toSerialize["includeInSnippetByDefault"] = o.IncludeInSnippetByDefault + } + if o.DefaultClientSideAvailability != nil { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Environments != nil { + toSerialize["environments"] = o.Environments + } + if o.NamingConvention != nil { + toSerialize["namingConvention"] = o.NamingConvention + } + return json.Marshal(toSerialize) +} + +type NullableProjectPost struct { + value *ProjectPost + isSet bool +} + +func (v NullableProjectPost) Get() *ProjectPost { + return v.value +} + +func (v *NullableProjectPost) Set(val *ProjectPost) { + v.value = val + v.isSet = true +} + +func (v NullableProjectPost) IsSet() bool { + return v.isSet +} + +func (v *NullableProjectPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProjectPost(val *ProjectPost) *NullableProjectPost { + return &NullableProjectPost{value: val, isSet: true} +} + +func (v NullableProjectPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProjectPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_project_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_rep.go new file mode 100644 index 00000000..93f4923a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_rep.go @@ -0,0 +1,399 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ProjectRep struct for ProjectRep +type ProjectRep struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of this project + Id string `json:"_id"` + // The key of this project + Key string `json:"key"` + // Whether or not flags created in this project are made available to the client-side JavaScript SDK by default + IncludeInSnippetByDefault bool `json:"includeInSnippetByDefault"` + DefaultClientSideAvailability *ClientSideAvailability `json:"defaultClientSideAvailability,omitempty"` + // A human-friendly name for the project + Name string `json:"name"` + Access *Access `json:"_access,omitempty"` + // A list of tags for the project + Tags []string `json:"tags"` + // The key of the default release pipeline for this project + DefaultReleasePipelineKey *string `json:"defaultReleasePipelineKey,omitempty"` + // A list of environments for the project + Environments []Environment `json:"environments"` +} + +// NewProjectRep instantiates a new ProjectRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProjectRep(links map[string]Link, id string, key string, includeInSnippetByDefault bool, name string, tags []string, environments []Environment) *ProjectRep { + this := ProjectRep{} + this.Links = links + this.Id = id + this.Key = key + this.IncludeInSnippetByDefault = includeInSnippetByDefault + this.Name = name + this.Tags = tags + this.Environments = environments + return &this +} + +// NewProjectRepWithDefaults instantiates a new ProjectRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectRepWithDefaults() *ProjectRep { + this := ProjectRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *ProjectRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ProjectRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *ProjectRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ProjectRep) SetId(v string) { + o.Id = v +} + +// GetKey returns the Key field value +func (o *ProjectRep) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ProjectRep) SetKey(v string) { + o.Key = v +} + +// GetIncludeInSnippetByDefault returns the IncludeInSnippetByDefault field value +func (o *ProjectRep) GetIncludeInSnippetByDefault() bool { + if o == nil { + var ret bool + return ret + } + + return o.IncludeInSnippetByDefault +} + +// GetIncludeInSnippetByDefaultOk returns a tuple with the IncludeInSnippetByDefault field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetIncludeInSnippetByDefaultOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IncludeInSnippetByDefault, true +} + +// SetIncludeInSnippetByDefault sets field value +func (o *ProjectRep) SetIncludeInSnippetByDefault(v bool) { + o.IncludeInSnippetByDefault = v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value if set, zero value otherwise. +func (o *ProjectRep) GetDefaultClientSideAvailability() ClientSideAvailability { + if o == nil || o.DefaultClientSideAvailability == nil { + var ret ClientSideAvailability + return ret + } + return *o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetDefaultClientSideAvailabilityOk() (*ClientSideAvailability, bool) { + if o == nil || o.DefaultClientSideAvailability == nil { + return nil, false + } + return o.DefaultClientSideAvailability, true +} + +// HasDefaultClientSideAvailability returns a boolean if a field has been set. +func (o *ProjectRep) HasDefaultClientSideAvailability() bool { + if o != nil && o.DefaultClientSideAvailability != nil { + return true + } + + return false +} + +// SetDefaultClientSideAvailability gets a reference to the given ClientSideAvailability and assigns it to the DefaultClientSideAvailability field. +func (o *ProjectRep) SetDefaultClientSideAvailability(v ClientSideAvailability) { + o.DefaultClientSideAvailability = &v +} + +// GetName returns the Name field value +func (o *ProjectRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ProjectRep) SetName(v string) { + o.Name = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ProjectRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ProjectRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ProjectRep) SetAccess(v Access) { + o.Access = &v +} + +// GetTags returns the Tags field value +func (o *ProjectRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *ProjectRep) SetTags(v []string) { + o.Tags = v +} + +// GetDefaultReleasePipelineKey returns the DefaultReleasePipelineKey field value if set, zero value otherwise. +func (o *ProjectRep) GetDefaultReleasePipelineKey() string { + if o == nil || o.DefaultReleasePipelineKey == nil { + var ret string + return ret + } + return *o.DefaultReleasePipelineKey +} + +// GetDefaultReleasePipelineKeyOk returns a tuple with the DefaultReleasePipelineKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetDefaultReleasePipelineKeyOk() (*string, bool) { + if o == nil || o.DefaultReleasePipelineKey == nil { + return nil, false + } + return o.DefaultReleasePipelineKey, true +} + +// HasDefaultReleasePipelineKey returns a boolean if a field has been set. +func (o *ProjectRep) HasDefaultReleasePipelineKey() bool { + if o != nil && o.DefaultReleasePipelineKey != nil { + return true + } + + return false +} + +// SetDefaultReleasePipelineKey gets a reference to the given string and assigns it to the DefaultReleasePipelineKey field. +func (o *ProjectRep) SetDefaultReleasePipelineKey(v string) { + o.DefaultReleasePipelineKey = &v +} + +// GetEnvironments returns the Environments field value +func (o *ProjectRep) GetEnvironments() []Environment { + if o == nil { + var ret []Environment + return ret + } + + return o.Environments +} + +// GetEnvironmentsOk returns a tuple with the Environments field value +// and a boolean to check if the value has been set. +func (o *ProjectRep) GetEnvironmentsOk() ([]Environment, bool) { + if o == nil { + return nil, false + } + return o.Environments, true +} + +// SetEnvironments sets field value +func (o *ProjectRep) SetEnvironments(v []Environment) { + o.Environments = v +} + +func (o ProjectRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["includeInSnippetByDefault"] = o.IncludeInSnippetByDefault + } + if o.DefaultClientSideAvailability != nil { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + if true { + toSerialize["name"] = o.Name + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["tags"] = o.Tags + } + if o.DefaultReleasePipelineKey != nil { + toSerialize["defaultReleasePipelineKey"] = o.DefaultReleasePipelineKey + } + if true { + toSerialize["environments"] = o.Environments + } + return json.Marshal(toSerialize) +} + +type NullableProjectRep struct { + value *ProjectRep + isSet bool +} + +func (v NullableProjectRep) Get() *ProjectRep { + return v.value +} + +func (v *NullableProjectRep) Set(val *ProjectRep) { + v.value = val + v.isSet = true +} + +func (v NullableProjectRep) IsSet() bool { + return v.isSet +} + +func (v *NullableProjectRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProjectRep(val *ProjectRep) *NullableProjectRep { + return &NullableProjectRep{value: val, isSet: true} +} + +func (v NullableProjectRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProjectRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary.go new file mode 100644 index 00000000..bc5f71c2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ProjectSummary struct for ProjectSummary +type ProjectSummary struct { + // The ID of this project + Id string `json:"_id"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The project key + Key string `json:"key"` + // The project name + Name string `json:"name"` +} + +// NewProjectSummary instantiates a new ProjectSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProjectSummary(id string, links map[string]Link, key string, name string) *ProjectSummary { + this := ProjectSummary{} + this.Id = id + this.Links = links + this.Key = key + this.Name = name + return &this +} + +// NewProjectSummaryWithDefaults instantiates a new ProjectSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectSummaryWithDefaults() *ProjectSummary { + this := ProjectSummary{} + return &this +} + +// GetId returns the Id field value +func (o *ProjectSummary) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ProjectSummary) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ProjectSummary) SetId(v string) { + o.Id = v +} + +// GetLinks returns the Links field value +func (o *ProjectSummary) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ProjectSummary) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ProjectSummary) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetKey returns the Key field value +func (o *ProjectSummary) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ProjectSummary) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ProjectSummary) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *ProjectSummary) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ProjectSummary) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ProjectSummary) SetName(v string) { + o.Name = v +} + +func (o ProjectSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableProjectSummary struct { + value *ProjectSummary + isSet bool +} + +func (v NullableProjectSummary) Get() *ProjectSummary { + return v.value +} + +func (v *NullableProjectSummary) Set(val *ProjectSummary) { + v.value = val + v.isSet = true +} + +func (v NullableProjectSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableProjectSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProjectSummary(val *ProjectSummary) *NullableProjectSummary { + return &NullableProjectSummary{value: val, isSet: true} +} + +func (v NullableProjectSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProjectSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary_collection.go new file mode 100644 index 00000000..511673a3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_project_summary_collection.go @@ -0,0 +1,174 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ProjectSummaryCollection struct for ProjectSummaryCollection +type ProjectSummaryCollection struct { + TotalCount int32 `json:"totalCount"` + Items []ProjectSummary `json:"items"` + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewProjectSummaryCollection instantiates a new ProjectSummaryCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProjectSummaryCollection(totalCount int32, items []ProjectSummary) *ProjectSummaryCollection { + this := ProjectSummaryCollection{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewProjectSummaryCollectionWithDefaults instantiates a new ProjectSummaryCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectSummaryCollectionWithDefaults() *ProjectSummaryCollection { + this := ProjectSummaryCollection{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *ProjectSummaryCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *ProjectSummaryCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *ProjectSummaryCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *ProjectSummaryCollection) GetItems() []ProjectSummary { + if o == nil { + var ret []ProjectSummary + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ProjectSummaryCollection) GetItemsOk() ([]ProjectSummary, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ProjectSummaryCollection) SetItems(v []ProjectSummary) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ProjectSummaryCollection) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ProjectSummaryCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ProjectSummaryCollection) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ProjectSummaryCollection) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o ProjectSummaryCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableProjectSummaryCollection struct { + value *ProjectSummaryCollection + isSet bool +} + +func (v NullableProjectSummaryCollection) Get() *ProjectSummaryCollection { + return v.value +} + +func (v *NullableProjectSummaryCollection) Set(val *ProjectSummaryCollection) { + v.value = val + v.isSet = true +} + +func (v NullableProjectSummaryCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableProjectSummaryCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProjectSummaryCollection(val *ProjectSummaryCollection) *NullableProjectSummaryCollection { + return &NullableProjectSummaryCollection{value: val, isSet: true} +} + +func (v NullableProjectSummaryCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProjectSummaryCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_projects.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_projects.go new file mode 100644 index 00000000..49f5ea91 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_projects.go @@ -0,0 +1,176 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Projects struct for Projects +type Projects struct { + // A link to this resource. + Links map[string]Link `json:"_links"` + // List of projects. + Items []Project `json:"items"` + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewProjects instantiates a new Projects object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewProjects(links map[string]Link, items []Project) *Projects { + this := Projects{} + this.Links = links + this.Items = items + return &this +} + +// NewProjectsWithDefaults instantiates a new Projects object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewProjectsWithDefaults() *Projects { + this := Projects{} + return &this +} + +// GetLinks returns the Links field value +func (o *Projects) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Projects) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Projects) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *Projects) GetItems() []Project { + if o == nil { + var ret []Project + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Projects) GetItemsOk() ([]Project, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Projects) SetItems(v []Project) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Projects) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Projects) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Projects) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Projects) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o Projects) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableProjects struct { + value *Projects + isSet bool +} + +func (v NullableProjects) Get() *Projects { + return v.value +} + +func (v *NullableProjects) Set(val *Projects) { + v.value = val + v.isSet = true +} + +func (v NullableProjects) IsSet() bool { + return v.isSet +} + +func (v *NullableProjects) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableProjects(val *Projects) *NullableProjects { + return &NullableProjects{value: val, isSet: true} +} + +func (v NullableProjects) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableProjects) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_collection_rep.go new file mode 100644 index 00000000..0ea4d9da --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_collection_rep.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PullRequestCollectionRep struct for PullRequestCollectionRep +type PullRequestCollectionRep struct { + // The total number of pull requests + TotalCount int32 `json:"totalCount"` + // A list of pull requests + Items []PullRequestRep `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewPullRequestCollectionRep instantiates a new PullRequestCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPullRequestCollectionRep(totalCount int32, items []PullRequestRep) *PullRequestCollectionRep { + this := PullRequestCollectionRep{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewPullRequestCollectionRepWithDefaults instantiates a new PullRequestCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPullRequestCollectionRepWithDefaults() *PullRequestCollectionRep { + this := PullRequestCollectionRep{} + return &this +} + +// GetTotalCount returns the TotalCount field value +func (o *PullRequestCollectionRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *PullRequestCollectionRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *PullRequestCollectionRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *PullRequestCollectionRep) GetItems() []PullRequestRep { + if o == nil { + var ret []PullRequestRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *PullRequestCollectionRep) GetItemsOk() ([]PullRequestRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *PullRequestCollectionRep) SetItems(v []PullRequestRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *PullRequestCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *PullRequestCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *PullRequestCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o PullRequestCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullablePullRequestCollectionRep struct { + value *PullRequestCollectionRep + isSet bool +} + +func (v NullablePullRequestCollectionRep) Get() *PullRequestCollectionRep { + return v.value +} + +func (v *NullablePullRequestCollectionRep) Set(val *PullRequestCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullablePullRequestCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullablePullRequestCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePullRequestCollectionRep(val *PullRequestCollectionRep) *NullablePullRequestCollectionRep { + return &NullablePullRequestCollectionRep{value: val, isSet: true} +} + +func (v NullablePullRequestCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePullRequestCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_lead_time_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_lead_time_rep.go new file mode 100644 index 00000000..724816b2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_lead_time_rep.go @@ -0,0 +1,369 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PullRequestLeadTimeRep struct for PullRequestLeadTimeRep +type PullRequestLeadTimeRep struct { + // The coding duration in milliseconds + CodingDurationMs int64 `json:"codingDurationMs"` + // The review duration in milliseconds + ReviewDurationMs *int64 `json:"reviewDurationMs,omitempty"` + // The max wait duration between merge time and deploy start time in milliseconds + MaxWaitDurationMs *int64 `json:"maxWaitDurationMs,omitempty"` + // The average wait duration between merge time and deploy start time in milliseconds + AvgWaitDurationMs *int64 `json:"avgWaitDurationMs,omitempty"` + // The max deploy duration in milliseconds + MaxDeployDurationMs *int64 `json:"maxDeployDurationMs,omitempty"` + // The average deploy duration in milliseconds + AvgDeployDurationMs *int64 `json:"avgDeployDurationMs,omitempty"` + // The max total lead time in milliseconds + MaxTotalLeadTimeMs *int64 `json:"maxTotalLeadTimeMs,omitempty"` + // The average total lead time in milliseconds + AvgTotalLeadTimeMs *int64 `json:"avgTotalLeadTimeMs,omitempty"` +} + +// NewPullRequestLeadTimeRep instantiates a new PullRequestLeadTimeRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPullRequestLeadTimeRep(codingDurationMs int64) *PullRequestLeadTimeRep { + this := PullRequestLeadTimeRep{} + this.CodingDurationMs = codingDurationMs + return &this +} + +// NewPullRequestLeadTimeRepWithDefaults instantiates a new PullRequestLeadTimeRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPullRequestLeadTimeRepWithDefaults() *PullRequestLeadTimeRep { + this := PullRequestLeadTimeRep{} + return &this +} + +// GetCodingDurationMs returns the CodingDurationMs field value +func (o *PullRequestLeadTimeRep) GetCodingDurationMs() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CodingDurationMs +} + +// GetCodingDurationMsOk returns a tuple with the CodingDurationMs field value +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetCodingDurationMsOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CodingDurationMs, true +} + +// SetCodingDurationMs sets field value +func (o *PullRequestLeadTimeRep) SetCodingDurationMs(v int64) { + o.CodingDurationMs = v +} + +// GetReviewDurationMs returns the ReviewDurationMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetReviewDurationMs() int64 { + if o == nil || o.ReviewDurationMs == nil { + var ret int64 + return ret + } + return *o.ReviewDurationMs +} + +// GetReviewDurationMsOk returns a tuple with the ReviewDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetReviewDurationMsOk() (*int64, bool) { + if o == nil || o.ReviewDurationMs == nil { + return nil, false + } + return o.ReviewDurationMs, true +} + +// HasReviewDurationMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasReviewDurationMs() bool { + if o != nil && o.ReviewDurationMs != nil { + return true + } + + return false +} + +// SetReviewDurationMs gets a reference to the given int64 and assigns it to the ReviewDurationMs field. +func (o *PullRequestLeadTimeRep) SetReviewDurationMs(v int64) { + o.ReviewDurationMs = &v +} + +// GetMaxWaitDurationMs returns the MaxWaitDurationMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetMaxWaitDurationMs() int64 { + if o == nil || o.MaxWaitDurationMs == nil { + var ret int64 + return ret + } + return *o.MaxWaitDurationMs +} + +// GetMaxWaitDurationMsOk returns a tuple with the MaxWaitDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetMaxWaitDurationMsOk() (*int64, bool) { + if o == nil || o.MaxWaitDurationMs == nil { + return nil, false + } + return o.MaxWaitDurationMs, true +} + +// HasMaxWaitDurationMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasMaxWaitDurationMs() bool { + if o != nil && o.MaxWaitDurationMs != nil { + return true + } + + return false +} + +// SetMaxWaitDurationMs gets a reference to the given int64 and assigns it to the MaxWaitDurationMs field. +func (o *PullRequestLeadTimeRep) SetMaxWaitDurationMs(v int64) { + o.MaxWaitDurationMs = &v +} + +// GetAvgWaitDurationMs returns the AvgWaitDurationMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetAvgWaitDurationMs() int64 { + if o == nil || o.AvgWaitDurationMs == nil { + var ret int64 + return ret + } + return *o.AvgWaitDurationMs +} + +// GetAvgWaitDurationMsOk returns a tuple with the AvgWaitDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetAvgWaitDurationMsOk() (*int64, bool) { + if o == nil || o.AvgWaitDurationMs == nil { + return nil, false + } + return o.AvgWaitDurationMs, true +} + +// HasAvgWaitDurationMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasAvgWaitDurationMs() bool { + if o != nil && o.AvgWaitDurationMs != nil { + return true + } + + return false +} + +// SetAvgWaitDurationMs gets a reference to the given int64 and assigns it to the AvgWaitDurationMs field. +func (o *PullRequestLeadTimeRep) SetAvgWaitDurationMs(v int64) { + o.AvgWaitDurationMs = &v +} + +// GetMaxDeployDurationMs returns the MaxDeployDurationMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetMaxDeployDurationMs() int64 { + if o == nil || o.MaxDeployDurationMs == nil { + var ret int64 + return ret + } + return *o.MaxDeployDurationMs +} + +// GetMaxDeployDurationMsOk returns a tuple with the MaxDeployDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetMaxDeployDurationMsOk() (*int64, bool) { + if o == nil || o.MaxDeployDurationMs == nil { + return nil, false + } + return o.MaxDeployDurationMs, true +} + +// HasMaxDeployDurationMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasMaxDeployDurationMs() bool { + if o != nil && o.MaxDeployDurationMs != nil { + return true + } + + return false +} + +// SetMaxDeployDurationMs gets a reference to the given int64 and assigns it to the MaxDeployDurationMs field. +func (o *PullRequestLeadTimeRep) SetMaxDeployDurationMs(v int64) { + o.MaxDeployDurationMs = &v +} + +// GetAvgDeployDurationMs returns the AvgDeployDurationMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetAvgDeployDurationMs() int64 { + if o == nil || o.AvgDeployDurationMs == nil { + var ret int64 + return ret + } + return *o.AvgDeployDurationMs +} + +// GetAvgDeployDurationMsOk returns a tuple with the AvgDeployDurationMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetAvgDeployDurationMsOk() (*int64, bool) { + if o == nil || o.AvgDeployDurationMs == nil { + return nil, false + } + return o.AvgDeployDurationMs, true +} + +// HasAvgDeployDurationMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasAvgDeployDurationMs() bool { + if o != nil && o.AvgDeployDurationMs != nil { + return true + } + + return false +} + +// SetAvgDeployDurationMs gets a reference to the given int64 and assigns it to the AvgDeployDurationMs field. +func (o *PullRequestLeadTimeRep) SetAvgDeployDurationMs(v int64) { + o.AvgDeployDurationMs = &v +} + +// GetMaxTotalLeadTimeMs returns the MaxTotalLeadTimeMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetMaxTotalLeadTimeMs() int64 { + if o == nil || o.MaxTotalLeadTimeMs == nil { + var ret int64 + return ret + } + return *o.MaxTotalLeadTimeMs +} + +// GetMaxTotalLeadTimeMsOk returns a tuple with the MaxTotalLeadTimeMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetMaxTotalLeadTimeMsOk() (*int64, bool) { + if o == nil || o.MaxTotalLeadTimeMs == nil { + return nil, false + } + return o.MaxTotalLeadTimeMs, true +} + +// HasMaxTotalLeadTimeMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasMaxTotalLeadTimeMs() bool { + if o != nil && o.MaxTotalLeadTimeMs != nil { + return true + } + + return false +} + +// SetMaxTotalLeadTimeMs gets a reference to the given int64 and assigns it to the MaxTotalLeadTimeMs field. +func (o *PullRequestLeadTimeRep) SetMaxTotalLeadTimeMs(v int64) { + o.MaxTotalLeadTimeMs = &v +} + +// GetAvgTotalLeadTimeMs returns the AvgTotalLeadTimeMs field value if set, zero value otherwise. +func (o *PullRequestLeadTimeRep) GetAvgTotalLeadTimeMs() int64 { + if o == nil || o.AvgTotalLeadTimeMs == nil { + var ret int64 + return ret + } + return *o.AvgTotalLeadTimeMs +} + +// GetAvgTotalLeadTimeMsOk returns a tuple with the AvgTotalLeadTimeMs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestLeadTimeRep) GetAvgTotalLeadTimeMsOk() (*int64, bool) { + if o == nil || o.AvgTotalLeadTimeMs == nil { + return nil, false + } + return o.AvgTotalLeadTimeMs, true +} + +// HasAvgTotalLeadTimeMs returns a boolean if a field has been set. +func (o *PullRequestLeadTimeRep) HasAvgTotalLeadTimeMs() bool { + if o != nil && o.AvgTotalLeadTimeMs != nil { + return true + } + + return false +} + +// SetAvgTotalLeadTimeMs gets a reference to the given int64 and assigns it to the AvgTotalLeadTimeMs field. +func (o *PullRequestLeadTimeRep) SetAvgTotalLeadTimeMs(v int64) { + o.AvgTotalLeadTimeMs = &v +} + +func (o PullRequestLeadTimeRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["codingDurationMs"] = o.CodingDurationMs + } + if o.ReviewDurationMs != nil { + toSerialize["reviewDurationMs"] = o.ReviewDurationMs + } + if o.MaxWaitDurationMs != nil { + toSerialize["maxWaitDurationMs"] = o.MaxWaitDurationMs + } + if o.AvgWaitDurationMs != nil { + toSerialize["avgWaitDurationMs"] = o.AvgWaitDurationMs + } + if o.MaxDeployDurationMs != nil { + toSerialize["maxDeployDurationMs"] = o.MaxDeployDurationMs + } + if o.AvgDeployDurationMs != nil { + toSerialize["avgDeployDurationMs"] = o.AvgDeployDurationMs + } + if o.MaxTotalLeadTimeMs != nil { + toSerialize["maxTotalLeadTimeMs"] = o.MaxTotalLeadTimeMs + } + if o.AvgTotalLeadTimeMs != nil { + toSerialize["avgTotalLeadTimeMs"] = o.AvgTotalLeadTimeMs + } + return json.Marshal(toSerialize) +} + +type NullablePullRequestLeadTimeRep struct { + value *PullRequestLeadTimeRep + isSet bool +} + +func (v NullablePullRequestLeadTimeRep) Get() *PullRequestLeadTimeRep { + return v.value +} + +func (v *NullablePullRequestLeadTimeRep) Set(val *PullRequestLeadTimeRep) { + v.value = val + v.isSet = true +} + +func (v NullablePullRequestLeadTimeRep) IsSet() bool { + return v.isSet +} + +func (v *NullablePullRequestLeadTimeRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePullRequestLeadTimeRep(val *PullRequestLeadTimeRep) *NullablePullRequestLeadTimeRep { + return &NullablePullRequestLeadTimeRep{value: val, isSet: true} +} + +func (v NullablePullRequestLeadTimeRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePullRequestLeadTimeRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_rep.go new file mode 100644 index 00000000..5d2446cf --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_pull_request_rep.go @@ -0,0 +1,620 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PullRequestRep struct for PullRequestRep +type PullRequestRep struct { + // The pull request internal ID + Id string `json:"id"` + // The pull request number + ExternalId string `json:"externalId"` + // The pull request title + Title string `json:"title"` + // The pull request status + Status string `json:"status"` + // The pull request author + Author string `json:"author"` + CreateTime int64 `json:"createTime"` + MergeTime *int64 `json:"mergeTime,omitempty"` + // The pull request merge commit key + MergeCommitKey *string `json:"mergeCommitKey,omitempty"` + // The pull request base commit key + BaseCommitKey string `json:"baseCommitKey"` + // The pull request head commit key + HeadCommitKey string `json:"headCommitKey"` + // The number of files changed + FilesChanged int32 `json:"filesChanged"` + // The number of lines added + LinesAdded int32 `json:"linesAdded"` + // The number of lines deleted + LinesDeleted int32 `json:"linesDeleted"` + // The pull request URL + Url string `json:"url"` + Deployments *DeploymentCollectionRep `json:"deployments,omitempty"` + FlagReferences *FlagReferenceCollectionRep `json:"flagReferences,omitempty"` + LeadTime *PullRequestLeadTimeRep `json:"leadTime,omitempty"` +} + +// NewPullRequestRep instantiates a new PullRequestRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPullRequestRep(id string, externalId string, title string, status string, author string, createTime int64, baseCommitKey string, headCommitKey string, filesChanged int32, linesAdded int32, linesDeleted int32, url string) *PullRequestRep { + this := PullRequestRep{} + this.Id = id + this.ExternalId = externalId + this.Title = title + this.Status = status + this.Author = author + this.CreateTime = createTime + this.BaseCommitKey = baseCommitKey + this.HeadCommitKey = headCommitKey + this.FilesChanged = filesChanged + this.LinesAdded = linesAdded + this.LinesDeleted = linesDeleted + this.Url = url + return &this +} + +// NewPullRequestRepWithDefaults instantiates a new PullRequestRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPullRequestRepWithDefaults() *PullRequestRep { + this := PullRequestRep{} + return &this +} + +// GetId returns the Id field value +func (o *PullRequestRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *PullRequestRep) SetId(v string) { + o.Id = v +} + +// GetExternalId returns the ExternalId field value +func (o *PullRequestRep) GetExternalId() string { + if o == nil { + var ret string + return ret + } + + return o.ExternalId +} + +// GetExternalIdOk returns a tuple with the ExternalId field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetExternalIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ExternalId, true +} + +// SetExternalId sets field value +func (o *PullRequestRep) SetExternalId(v string) { + o.ExternalId = v +} + +// GetTitle returns the Title field value +func (o *PullRequestRep) GetTitle() string { + if o == nil { + var ret string + return ret + } + + return o.Title +} + +// GetTitleOk returns a tuple with the Title field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetTitleOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Title, true +} + +// SetTitle sets field value +func (o *PullRequestRep) SetTitle(v string) { + o.Title = v +} + +// GetStatus returns the Status field value +func (o *PullRequestRep) GetStatus() string { + if o == nil { + var ret string + return ret + } + + return o.Status +} + +// GetStatusOk returns a tuple with the Status field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetStatusOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Status, true +} + +// SetStatus sets field value +func (o *PullRequestRep) SetStatus(v string) { + o.Status = v +} + +// GetAuthor returns the Author field value +func (o *PullRequestRep) GetAuthor() string { + if o == nil { + var ret string + return ret + } + + return o.Author +} + +// GetAuthorOk returns a tuple with the Author field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetAuthorOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Author, true +} + +// SetAuthor sets field value +func (o *PullRequestRep) SetAuthor(v string) { + o.Author = v +} + +// GetCreateTime returns the CreateTime field value +func (o *PullRequestRep) GetCreateTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreateTime +} + +// GetCreateTimeOk returns a tuple with the CreateTime field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetCreateTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreateTime, true +} + +// SetCreateTime sets field value +func (o *PullRequestRep) SetCreateTime(v int64) { + o.CreateTime = v +} + +// GetMergeTime returns the MergeTime field value if set, zero value otherwise. +func (o *PullRequestRep) GetMergeTime() int64 { + if o == nil || o.MergeTime == nil { + var ret int64 + return ret + } + return *o.MergeTime +} + +// GetMergeTimeOk returns a tuple with the MergeTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetMergeTimeOk() (*int64, bool) { + if o == nil || o.MergeTime == nil { + return nil, false + } + return o.MergeTime, true +} + +// HasMergeTime returns a boolean if a field has been set. +func (o *PullRequestRep) HasMergeTime() bool { + if o != nil && o.MergeTime != nil { + return true + } + + return false +} + +// SetMergeTime gets a reference to the given int64 and assigns it to the MergeTime field. +func (o *PullRequestRep) SetMergeTime(v int64) { + o.MergeTime = &v +} + +// GetMergeCommitKey returns the MergeCommitKey field value if set, zero value otherwise. +func (o *PullRequestRep) GetMergeCommitKey() string { + if o == nil || o.MergeCommitKey == nil { + var ret string + return ret + } + return *o.MergeCommitKey +} + +// GetMergeCommitKeyOk returns a tuple with the MergeCommitKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetMergeCommitKeyOk() (*string, bool) { + if o == nil || o.MergeCommitKey == nil { + return nil, false + } + return o.MergeCommitKey, true +} + +// HasMergeCommitKey returns a boolean if a field has been set. +func (o *PullRequestRep) HasMergeCommitKey() bool { + if o != nil && o.MergeCommitKey != nil { + return true + } + + return false +} + +// SetMergeCommitKey gets a reference to the given string and assigns it to the MergeCommitKey field. +func (o *PullRequestRep) SetMergeCommitKey(v string) { + o.MergeCommitKey = &v +} + +// GetBaseCommitKey returns the BaseCommitKey field value +func (o *PullRequestRep) GetBaseCommitKey() string { + if o == nil { + var ret string + return ret + } + + return o.BaseCommitKey +} + +// GetBaseCommitKeyOk returns a tuple with the BaseCommitKey field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetBaseCommitKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.BaseCommitKey, true +} + +// SetBaseCommitKey sets field value +func (o *PullRequestRep) SetBaseCommitKey(v string) { + o.BaseCommitKey = v +} + +// GetHeadCommitKey returns the HeadCommitKey field value +func (o *PullRequestRep) GetHeadCommitKey() string { + if o == nil { + var ret string + return ret + } + + return o.HeadCommitKey +} + +// GetHeadCommitKeyOk returns a tuple with the HeadCommitKey field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetHeadCommitKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.HeadCommitKey, true +} + +// SetHeadCommitKey sets field value +func (o *PullRequestRep) SetHeadCommitKey(v string) { + o.HeadCommitKey = v +} + +// GetFilesChanged returns the FilesChanged field value +func (o *PullRequestRep) GetFilesChanged() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.FilesChanged +} + +// GetFilesChangedOk returns a tuple with the FilesChanged field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetFilesChangedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.FilesChanged, true +} + +// SetFilesChanged sets field value +func (o *PullRequestRep) SetFilesChanged(v int32) { + o.FilesChanged = v +} + +// GetLinesAdded returns the LinesAdded field value +func (o *PullRequestRep) GetLinesAdded() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.LinesAdded +} + +// GetLinesAddedOk returns a tuple with the LinesAdded field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetLinesAddedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.LinesAdded, true +} + +// SetLinesAdded sets field value +func (o *PullRequestRep) SetLinesAdded(v int32) { + o.LinesAdded = v +} + +// GetLinesDeleted returns the LinesDeleted field value +func (o *PullRequestRep) GetLinesDeleted() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.LinesDeleted +} + +// GetLinesDeletedOk returns a tuple with the LinesDeleted field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetLinesDeletedOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.LinesDeleted, true +} + +// SetLinesDeleted sets field value +func (o *PullRequestRep) SetLinesDeleted(v int32) { + o.LinesDeleted = v +} + +// GetUrl returns the Url field value +func (o *PullRequestRep) GetUrl() string { + if o == nil { + var ret string + return ret + } + + return o.Url +} + +// GetUrlOk returns a tuple with the Url field value +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Url, true +} + +// SetUrl sets field value +func (o *PullRequestRep) SetUrl(v string) { + o.Url = v +} + +// GetDeployments returns the Deployments field value if set, zero value otherwise. +func (o *PullRequestRep) GetDeployments() DeploymentCollectionRep { + if o == nil || o.Deployments == nil { + var ret DeploymentCollectionRep + return ret + } + return *o.Deployments +} + +// GetDeploymentsOk returns a tuple with the Deployments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetDeploymentsOk() (*DeploymentCollectionRep, bool) { + if o == nil || o.Deployments == nil { + return nil, false + } + return o.Deployments, true +} + +// HasDeployments returns a boolean if a field has been set. +func (o *PullRequestRep) HasDeployments() bool { + if o != nil && o.Deployments != nil { + return true + } + + return false +} + +// SetDeployments gets a reference to the given DeploymentCollectionRep and assigns it to the Deployments field. +func (o *PullRequestRep) SetDeployments(v DeploymentCollectionRep) { + o.Deployments = &v +} + +// GetFlagReferences returns the FlagReferences field value if set, zero value otherwise. +func (o *PullRequestRep) GetFlagReferences() FlagReferenceCollectionRep { + if o == nil || o.FlagReferences == nil { + var ret FlagReferenceCollectionRep + return ret + } + return *o.FlagReferences +} + +// GetFlagReferencesOk returns a tuple with the FlagReferences field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetFlagReferencesOk() (*FlagReferenceCollectionRep, bool) { + if o == nil || o.FlagReferences == nil { + return nil, false + } + return o.FlagReferences, true +} + +// HasFlagReferences returns a boolean if a field has been set. +func (o *PullRequestRep) HasFlagReferences() bool { + if o != nil && o.FlagReferences != nil { + return true + } + + return false +} + +// SetFlagReferences gets a reference to the given FlagReferenceCollectionRep and assigns it to the FlagReferences field. +func (o *PullRequestRep) SetFlagReferences(v FlagReferenceCollectionRep) { + o.FlagReferences = &v +} + +// GetLeadTime returns the LeadTime field value if set, zero value otherwise. +func (o *PullRequestRep) GetLeadTime() PullRequestLeadTimeRep { + if o == nil || o.LeadTime == nil { + var ret PullRequestLeadTimeRep + return ret + } + return *o.LeadTime +} + +// GetLeadTimeOk returns a tuple with the LeadTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PullRequestRep) GetLeadTimeOk() (*PullRequestLeadTimeRep, bool) { + if o == nil || o.LeadTime == nil { + return nil, false + } + return o.LeadTime, true +} + +// HasLeadTime returns a boolean if a field has been set. +func (o *PullRequestRep) HasLeadTime() bool { + if o != nil && o.LeadTime != nil { + return true + } + + return false +} + +// SetLeadTime gets a reference to the given PullRequestLeadTimeRep and assigns it to the LeadTime field. +func (o *PullRequestRep) SetLeadTime(v PullRequestLeadTimeRep) { + o.LeadTime = &v +} + +func (o PullRequestRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["externalId"] = o.ExternalId + } + if true { + toSerialize["title"] = o.Title + } + if true { + toSerialize["status"] = o.Status + } + if true { + toSerialize["author"] = o.Author + } + if true { + toSerialize["createTime"] = o.CreateTime + } + if o.MergeTime != nil { + toSerialize["mergeTime"] = o.MergeTime + } + if o.MergeCommitKey != nil { + toSerialize["mergeCommitKey"] = o.MergeCommitKey + } + if true { + toSerialize["baseCommitKey"] = o.BaseCommitKey + } + if true { + toSerialize["headCommitKey"] = o.HeadCommitKey + } + if true { + toSerialize["filesChanged"] = o.FilesChanged + } + if true { + toSerialize["linesAdded"] = o.LinesAdded + } + if true { + toSerialize["linesDeleted"] = o.LinesDeleted + } + if true { + toSerialize["url"] = o.Url + } + if o.Deployments != nil { + toSerialize["deployments"] = o.Deployments + } + if o.FlagReferences != nil { + toSerialize["flagReferences"] = o.FlagReferences + } + if o.LeadTime != nil { + toSerialize["leadTime"] = o.LeadTime + } + return json.Marshal(toSerialize) +} + +type NullablePullRequestRep struct { + value *PullRequestRep + isSet bool +} + +func (v NullablePullRequestRep) Get() *PullRequestRep { + return v.value +} + +func (v *NullablePullRequestRep) Set(val *PullRequestRep) { + v.value = val + v.isSet = true +} + +func (v NullablePullRequestRep) IsSet() bool { + return v.isSet +} + +func (v *NullablePullRequestRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePullRequestRep(val *PullRequestRep) *NullablePullRequestRep { + return &NullablePullRequestRep{value: val, isSet: true} +} + +func (v NullablePullRequestRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePullRequestRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_put_branch.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_put_branch.go new file mode 100644 index 00000000..d2fbac3c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_put_branch.go @@ -0,0 +1,279 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// PutBranch struct for PutBranch +type PutBranch struct { + // The branch name + Name string `json:"name"` + // An ID representing the branch HEAD. For example, a commit SHA. + Head string `json:"head"` + // An optional ID used to prevent older data from overwriting newer data. If no sequence ID is included, the newly submitted data will always be saved. + UpdateSequenceId *int64 `json:"updateSequenceId,omitempty"` + SyncTime int64 `json:"syncTime"` + // An array of flag references found on the branch + References []ReferenceRep `json:"references,omitempty"` + CommitTime *int64 `json:"commitTime,omitempty"` +} + +// NewPutBranch instantiates a new PutBranch object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPutBranch(name string, head string, syncTime int64) *PutBranch { + this := PutBranch{} + this.Name = name + this.Head = head + this.SyncTime = syncTime + return &this +} + +// NewPutBranchWithDefaults instantiates a new PutBranch object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPutBranchWithDefaults() *PutBranch { + this := PutBranch{} + return &this +} + +// GetName returns the Name field value +func (o *PutBranch) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *PutBranch) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *PutBranch) SetName(v string) { + o.Name = v +} + +// GetHead returns the Head field value +func (o *PutBranch) GetHead() string { + if o == nil { + var ret string + return ret + } + + return o.Head +} + +// GetHeadOk returns a tuple with the Head field value +// and a boolean to check if the value has been set. +func (o *PutBranch) GetHeadOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Head, true +} + +// SetHead sets field value +func (o *PutBranch) SetHead(v string) { + o.Head = v +} + +// GetUpdateSequenceId returns the UpdateSequenceId field value if set, zero value otherwise. +func (o *PutBranch) GetUpdateSequenceId() int64 { + if o == nil || o.UpdateSequenceId == nil { + var ret int64 + return ret + } + return *o.UpdateSequenceId +} + +// GetUpdateSequenceIdOk returns a tuple with the UpdateSequenceId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PutBranch) GetUpdateSequenceIdOk() (*int64, bool) { + if o == nil || o.UpdateSequenceId == nil { + return nil, false + } + return o.UpdateSequenceId, true +} + +// HasUpdateSequenceId returns a boolean if a field has been set. +func (o *PutBranch) HasUpdateSequenceId() bool { + if o != nil && o.UpdateSequenceId != nil { + return true + } + + return false +} + +// SetUpdateSequenceId gets a reference to the given int64 and assigns it to the UpdateSequenceId field. +func (o *PutBranch) SetUpdateSequenceId(v int64) { + o.UpdateSequenceId = &v +} + +// GetSyncTime returns the SyncTime field value +func (o *PutBranch) GetSyncTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.SyncTime +} + +// GetSyncTimeOk returns a tuple with the SyncTime field value +// and a boolean to check if the value has been set. +func (o *PutBranch) GetSyncTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.SyncTime, true +} + +// SetSyncTime sets field value +func (o *PutBranch) SetSyncTime(v int64) { + o.SyncTime = v +} + +// GetReferences returns the References field value if set, zero value otherwise. +func (o *PutBranch) GetReferences() []ReferenceRep { + if o == nil || o.References == nil { + var ret []ReferenceRep + return ret + } + return o.References +} + +// GetReferencesOk returns a tuple with the References field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PutBranch) GetReferencesOk() ([]ReferenceRep, bool) { + if o == nil || o.References == nil { + return nil, false + } + return o.References, true +} + +// HasReferences returns a boolean if a field has been set. +func (o *PutBranch) HasReferences() bool { + if o != nil && o.References != nil { + return true + } + + return false +} + +// SetReferences gets a reference to the given []ReferenceRep and assigns it to the References field. +func (o *PutBranch) SetReferences(v []ReferenceRep) { + o.References = v +} + +// GetCommitTime returns the CommitTime field value if set, zero value otherwise. +func (o *PutBranch) GetCommitTime() int64 { + if o == nil || o.CommitTime == nil { + var ret int64 + return ret + } + return *o.CommitTime +} + +// GetCommitTimeOk returns a tuple with the CommitTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PutBranch) GetCommitTimeOk() (*int64, bool) { + if o == nil || o.CommitTime == nil { + return nil, false + } + return o.CommitTime, true +} + +// HasCommitTime returns a boolean if a field has been set. +func (o *PutBranch) HasCommitTime() bool { + if o != nil && o.CommitTime != nil { + return true + } + + return false +} + +// SetCommitTime gets a reference to the given int64 and assigns it to the CommitTime field. +func (o *PutBranch) SetCommitTime(v int64) { + o.CommitTime = &v +} + +func (o PutBranch) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["head"] = o.Head + } + if o.UpdateSequenceId != nil { + toSerialize["updateSequenceId"] = o.UpdateSequenceId + } + if true { + toSerialize["syncTime"] = o.SyncTime + } + if o.References != nil { + toSerialize["references"] = o.References + } + if o.CommitTime != nil { + toSerialize["commitTime"] = o.CommitTime + } + return json.Marshal(toSerialize) +} + +type NullablePutBranch struct { + value *PutBranch + isSet bool +} + +func (v NullablePutBranch) Get() *PutBranch { + return v.value +} + +func (v *NullablePutBranch) Set(val *PutBranch) { + v.value = val + v.isSet = true +} + +func (v NullablePutBranch) IsSet() bool { + return v.isSet +} + +func (v *NullablePutBranch) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePutBranch(val *PutBranch) *NullablePutBranch { + return &NullablePutBranch{value: val, isSet: true} +} + +func (v NullablePutBranch) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePutBranch) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_put.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_put.go new file mode 100644 index 00000000..99305b3c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_put.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RandomizationSettingsPut struct for RandomizationSettingsPut +type RandomizationSettingsPut struct { + // An array of randomization units allowed for this project. + RandomizationUnits []RandomizationUnitInput `json:"randomizationUnits"` +} + +// NewRandomizationSettingsPut instantiates a new RandomizationSettingsPut object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRandomizationSettingsPut(randomizationUnits []RandomizationUnitInput) *RandomizationSettingsPut { + this := RandomizationSettingsPut{} + this.RandomizationUnits = randomizationUnits + return &this +} + +// NewRandomizationSettingsPutWithDefaults instantiates a new RandomizationSettingsPut object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRandomizationSettingsPutWithDefaults() *RandomizationSettingsPut { + this := RandomizationSettingsPut{} + return &this +} + +// GetRandomizationUnits returns the RandomizationUnits field value +func (o *RandomizationSettingsPut) GetRandomizationUnits() []RandomizationUnitInput { + if o == nil { + var ret []RandomizationUnitInput + return ret + } + + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsPut) GetRandomizationUnitsOk() ([]RandomizationUnitInput, bool) { + if o == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// SetRandomizationUnits sets field value +func (o *RandomizationSettingsPut) SetRandomizationUnits(v []RandomizationUnitInput) { + o.RandomizationUnits = v +} + +func (o RandomizationSettingsPut) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + return json.Marshal(toSerialize) +} + +type NullableRandomizationSettingsPut struct { + value *RandomizationSettingsPut + isSet bool +} + +func (v NullableRandomizationSettingsPut) Get() *RandomizationSettingsPut { + return v.value +} + +func (v *NullableRandomizationSettingsPut) Set(val *RandomizationSettingsPut) { + v.value = val + v.isSet = true +} + +func (v NullableRandomizationSettingsPut) IsSet() bool { + return v.isSet +} + +func (v *NullableRandomizationSettingsPut) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRandomizationSettingsPut(val *RandomizationSettingsPut) *NullableRandomizationSettingsPut { + return &NullableRandomizationSettingsPut{value: val, isSet: true} +} + +func (v NullableRandomizationSettingsPut) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRandomizationSettingsPut) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_rep.go new file mode 100644 index 00000000..789eedff --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_settings_rep.go @@ -0,0 +1,264 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RandomizationSettingsRep struct for RandomizationSettingsRep +type RandomizationSettingsRep struct { + // The project ID + ProjectId *string `json:"_projectId,omitempty"` + // The project key + ProjectKey *string `json:"_projectKey,omitempty"` + // An array of the randomization units in this project + RandomizationUnits []RandomizationUnitRep `json:"randomizationUnits,omitempty"` + CreationDate *int64 `json:"_creationDate,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewRandomizationSettingsRep instantiates a new RandomizationSettingsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRandomizationSettingsRep() *RandomizationSettingsRep { + this := RandomizationSettingsRep{} + return &this +} + +// NewRandomizationSettingsRepWithDefaults instantiates a new RandomizationSettingsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRandomizationSettingsRepWithDefaults() *RandomizationSettingsRep { + this := RandomizationSettingsRep{} + return &this +} + +// GetProjectId returns the ProjectId field value if set, zero value otherwise. +func (o *RandomizationSettingsRep) GetProjectId() string { + if o == nil || o.ProjectId == nil { + var ret string + return ret + } + return *o.ProjectId +} + +// GetProjectIdOk returns a tuple with the ProjectId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsRep) GetProjectIdOk() (*string, bool) { + if o == nil || o.ProjectId == nil { + return nil, false + } + return o.ProjectId, true +} + +// HasProjectId returns a boolean if a field has been set. +func (o *RandomizationSettingsRep) HasProjectId() bool { + if o != nil && o.ProjectId != nil { + return true + } + + return false +} + +// SetProjectId gets a reference to the given string and assigns it to the ProjectId field. +func (o *RandomizationSettingsRep) SetProjectId(v string) { + o.ProjectId = &v +} + +// GetProjectKey returns the ProjectKey field value if set, zero value otherwise. +func (o *RandomizationSettingsRep) GetProjectKey() string { + if o == nil || o.ProjectKey == nil { + var ret string + return ret + } + return *o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsRep) GetProjectKeyOk() (*string, bool) { + if o == nil || o.ProjectKey == nil { + return nil, false + } + return o.ProjectKey, true +} + +// HasProjectKey returns a boolean if a field has been set. +func (o *RandomizationSettingsRep) HasProjectKey() bool { + if o != nil && o.ProjectKey != nil { + return true + } + + return false +} + +// SetProjectKey gets a reference to the given string and assigns it to the ProjectKey field. +func (o *RandomizationSettingsRep) SetProjectKey(v string) { + o.ProjectKey = &v +} + +// GetRandomizationUnits returns the RandomizationUnits field value if set, zero value otherwise. +func (o *RandomizationSettingsRep) GetRandomizationUnits() []RandomizationUnitRep { + if o == nil || o.RandomizationUnits == nil { + var ret []RandomizationUnitRep + return ret + } + return o.RandomizationUnits +} + +// GetRandomizationUnitsOk returns a tuple with the RandomizationUnits field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsRep) GetRandomizationUnitsOk() ([]RandomizationUnitRep, bool) { + if o == nil || o.RandomizationUnits == nil { + return nil, false + } + return o.RandomizationUnits, true +} + +// HasRandomizationUnits returns a boolean if a field has been set. +func (o *RandomizationSettingsRep) HasRandomizationUnits() bool { + if o != nil && o.RandomizationUnits != nil { + return true + } + + return false +} + +// SetRandomizationUnits gets a reference to the given []RandomizationUnitRep and assigns it to the RandomizationUnits field. +func (o *RandomizationSettingsRep) SetRandomizationUnits(v []RandomizationUnitRep) { + o.RandomizationUnits = v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *RandomizationSettingsRep) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsRep) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *RandomizationSettingsRep) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *RandomizationSettingsRep) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *RandomizationSettingsRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationSettingsRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *RandomizationSettingsRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *RandomizationSettingsRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o RandomizationSettingsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ProjectId != nil { + toSerialize["_projectId"] = o.ProjectId + } + if o.ProjectKey != nil { + toSerialize["_projectKey"] = o.ProjectKey + } + if o.RandomizationUnits != nil { + toSerialize["randomizationUnits"] = o.RandomizationUnits + } + if o.CreationDate != nil { + toSerialize["_creationDate"] = o.CreationDate + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableRandomizationSettingsRep struct { + value *RandomizationSettingsRep + isSet bool +} + +func (v NullableRandomizationSettingsRep) Get() *RandomizationSettingsRep { + return v.value +} + +func (v *NullableRandomizationSettingsRep) Set(val *RandomizationSettingsRep) { + v.value = val + v.isSet = true +} + +func (v NullableRandomizationSettingsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRandomizationSettingsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRandomizationSettingsRep(val *RandomizationSettingsRep) *NullableRandomizationSettingsRep { + return &NullableRandomizationSettingsRep{value: val, isSet: true} +} + +func (v NullableRandomizationSettingsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRandomizationSettingsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_input.go new file mode 100644 index 00000000..2837b6bd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_input.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RandomizationUnitInput struct for RandomizationUnitInput +type RandomizationUnitInput struct { + // The unit of randomization. Must match the key of an existing context kind in this project. + RandomizationUnit string `json:"randomizationUnit"` + // If true, any experiment iterations created within this project will default to using this randomization unit. A project can only have one default randomization unit. + Default *bool `json:"default,omitempty"` + // One of LaunchDarkly's fixed set of standard randomization units. + StandardRandomizationUnit string `json:"standardRandomizationUnit"` +} + +// NewRandomizationUnitInput instantiates a new RandomizationUnitInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRandomizationUnitInput(randomizationUnit string, standardRandomizationUnit string) *RandomizationUnitInput { + this := RandomizationUnitInput{} + this.RandomizationUnit = randomizationUnit + this.StandardRandomizationUnit = standardRandomizationUnit + return &this +} + +// NewRandomizationUnitInputWithDefaults instantiates a new RandomizationUnitInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRandomizationUnitInputWithDefaults() *RandomizationUnitInput { + this := RandomizationUnitInput{} + return &this +} + +// GetRandomizationUnit returns the RandomizationUnit field value +func (o *RandomizationUnitInput) GetRandomizationUnit() string { + if o == nil { + var ret string + return ret + } + + return o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value +// and a boolean to check if the value has been set. +func (o *RandomizationUnitInput) GetRandomizationUnitOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.RandomizationUnit, true +} + +// SetRandomizationUnit sets field value +func (o *RandomizationUnitInput) SetRandomizationUnit(v string) { + o.RandomizationUnit = v +} + +// GetDefault returns the Default field value if set, zero value otherwise. +func (o *RandomizationUnitInput) GetDefault() bool { + if o == nil || o.Default == nil { + var ret bool + return ret + } + return *o.Default +} + +// GetDefaultOk returns a tuple with the Default field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitInput) GetDefaultOk() (*bool, bool) { + if o == nil || o.Default == nil { + return nil, false + } + return o.Default, true +} + +// HasDefault returns a boolean if a field has been set. +func (o *RandomizationUnitInput) HasDefault() bool { + if o != nil && o.Default != nil { + return true + } + + return false +} + +// SetDefault gets a reference to the given bool and assigns it to the Default field. +func (o *RandomizationUnitInput) SetDefault(v bool) { + o.Default = &v +} + +// GetStandardRandomizationUnit returns the StandardRandomizationUnit field value +func (o *RandomizationUnitInput) GetStandardRandomizationUnit() string { + if o == nil { + var ret string + return ret + } + + return o.StandardRandomizationUnit +} + +// GetStandardRandomizationUnitOk returns a tuple with the StandardRandomizationUnit field value +// and a boolean to check if the value has been set. +func (o *RandomizationUnitInput) GetStandardRandomizationUnitOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.StandardRandomizationUnit, true +} + +// SetStandardRandomizationUnit sets field value +func (o *RandomizationUnitInput) SetStandardRandomizationUnit(v string) { + o.StandardRandomizationUnit = v +} + +func (o RandomizationUnitInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + if o.Default != nil { + toSerialize["default"] = o.Default + } + if true { + toSerialize["standardRandomizationUnit"] = o.StandardRandomizationUnit + } + return json.Marshal(toSerialize) +} + +type NullableRandomizationUnitInput struct { + value *RandomizationUnitInput + isSet bool +} + +func (v NullableRandomizationUnitInput) Get() *RandomizationUnitInput { + return v.value +} + +func (v *NullableRandomizationUnitInput) Set(val *RandomizationUnitInput) { + v.value = val + v.isSet = true +} + +func (v NullableRandomizationUnitInput) IsSet() bool { + return v.isSet +} + +func (v *NullableRandomizationUnitInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRandomizationUnitInput(val *RandomizationUnitInput) *NullableRandomizationUnitInput { + return &NullableRandomizationUnitInput{value: val, isSet: true} +} + +func (v NullableRandomizationUnitInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRandomizationUnitInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_rep.go new file mode 100644 index 00000000..21db1ede --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_randomization_unit_rep.go @@ -0,0 +1,264 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RandomizationUnitRep struct for RandomizationUnitRep +type RandomizationUnitRep struct { + // The unit of randomization. Defaults to user. + RandomizationUnit *string `json:"randomizationUnit,omitempty"` + // One of LaunchDarkly's fixed set of standard randomization units. + StandardRandomizationUnit *string `json:"standardRandomizationUnit,omitempty"` + // Whether this randomization unit is the default for experiments + Default *bool `json:"default,omitempty"` + Hidden *bool `json:"_hidden,omitempty"` + // The display name for the randomization unit, displayed in the LaunchDarkly user interface. + DisplayName *string `json:"_displayName,omitempty"` +} + +// NewRandomizationUnitRep instantiates a new RandomizationUnitRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRandomizationUnitRep() *RandomizationUnitRep { + this := RandomizationUnitRep{} + return &this +} + +// NewRandomizationUnitRepWithDefaults instantiates a new RandomizationUnitRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRandomizationUnitRepWithDefaults() *RandomizationUnitRep { + this := RandomizationUnitRep{} + return &this +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *RandomizationUnitRep) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitRep) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *RandomizationUnitRep) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *RandomizationUnitRep) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +// GetStandardRandomizationUnit returns the StandardRandomizationUnit field value if set, zero value otherwise. +func (o *RandomizationUnitRep) GetStandardRandomizationUnit() string { + if o == nil || o.StandardRandomizationUnit == nil { + var ret string + return ret + } + return *o.StandardRandomizationUnit +} + +// GetStandardRandomizationUnitOk returns a tuple with the StandardRandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitRep) GetStandardRandomizationUnitOk() (*string, bool) { + if o == nil || o.StandardRandomizationUnit == nil { + return nil, false + } + return o.StandardRandomizationUnit, true +} + +// HasStandardRandomizationUnit returns a boolean if a field has been set. +func (o *RandomizationUnitRep) HasStandardRandomizationUnit() bool { + if o != nil && o.StandardRandomizationUnit != nil { + return true + } + + return false +} + +// SetStandardRandomizationUnit gets a reference to the given string and assigns it to the StandardRandomizationUnit field. +func (o *RandomizationUnitRep) SetStandardRandomizationUnit(v string) { + o.StandardRandomizationUnit = &v +} + +// GetDefault returns the Default field value if set, zero value otherwise. +func (o *RandomizationUnitRep) GetDefault() bool { + if o == nil || o.Default == nil { + var ret bool + return ret + } + return *o.Default +} + +// GetDefaultOk returns a tuple with the Default field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitRep) GetDefaultOk() (*bool, bool) { + if o == nil || o.Default == nil { + return nil, false + } + return o.Default, true +} + +// HasDefault returns a boolean if a field has been set. +func (o *RandomizationUnitRep) HasDefault() bool { + if o != nil && o.Default != nil { + return true + } + + return false +} + +// SetDefault gets a reference to the given bool and assigns it to the Default field. +func (o *RandomizationUnitRep) SetDefault(v bool) { + o.Default = &v +} + +// GetHidden returns the Hidden field value if set, zero value otherwise. +func (o *RandomizationUnitRep) GetHidden() bool { + if o == nil || o.Hidden == nil { + var ret bool + return ret + } + return *o.Hidden +} + +// GetHiddenOk returns a tuple with the Hidden field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitRep) GetHiddenOk() (*bool, bool) { + if o == nil || o.Hidden == nil { + return nil, false + } + return o.Hidden, true +} + +// HasHidden returns a boolean if a field has been set. +func (o *RandomizationUnitRep) HasHidden() bool { + if o != nil && o.Hidden != nil { + return true + } + + return false +} + +// SetHidden gets a reference to the given bool and assigns it to the Hidden field. +func (o *RandomizationUnitRep) SetHidden(v bool) { + o.Hidden = &v +} + +// GetDisplayName returns the DisplayName field value if set, zero value otherwise. +func (o *RandomizationUnitRep) GetDisplayName() string { + if o == nil || o.DisplayName == nil { + var ret string + return ret + } + return *o.DisplayName +} + +// GetDisplayNameOk returns a tuple with the DisplayName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RandomizationUnitRep) GetDisplayNameOk() (*string, bool) { + if o == nil || o.DisplayName == nil { + return nil, false + } + return o.DisplayName, true +} + +// HasDisplayName returns a boolean if a field has been set. +func (o *RandomizationUnitRep) HasDisplayName() bool { + if o != nil && o.DisplayName != nil { + return true + } + + return false +} + +// SetDisplayName gets a reference to the given string and assigns it to the DisplayName field. +func (o *RandomizationUnitRep) SetDisplayName(v string) { + o.DisplayName = &v +} + +func (o RandomizationUnitRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + if o.StandardRandomizationUnit != nil { + toSerialize["standardRandomizationUnit"] = o.StandardRandomizationUnit + } + if o.Default != nil { + toSerialize["default"] = o.Default + } + if o.Hidden != nil { + toSerialize["_hidden"] = o.Hidden + } + if o.DisplayName != nil { + toSerialize["_displayName"] = o.DisplayName + } + return json.Marshal(toSerialize) +} + +type NullableRandomizationUnitRep struct { + value *RandomizationUnitRep + isSet bool +} + +func (v NullableRandomizationUnitRep) Get() *RandomizationUnitRep { + return v.value +} + +func (v *NullableRandomizationUnitRep) Set(val *RandomizationUnitRep) { + v.value = val + v.isSet = true +} + +func (v NullableRandomizationUnitRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRandomizationUnitRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRandomizationUnitRep(val *RandomizationUnitRep) *NullableRandomizationUnitRep { + return &NullableRandomizationUnitRep{value: val, isSet: true} +} + +func (v NullableRandomizationUnitRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRandomizationUnitRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_rate_limited_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_rate_limited_error_rep.go new file mode 100644 index 00000000..a5422a61 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_rate_limited_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RateLimitedErrorRep struct for RateLimitedErrorRep +type RateLimitedErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewRateLimitedErrorRep instantiates a new RateLimitedErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRateLimitedErrorRep(code string, message string) *RateLimitedErrorRep { + this := RateLimitedErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewRateLimitedErrorRepWithDefaults instantiates a new RateLimitedErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRateLimitedErrorRepWithDefaults() *RateLimitedErrorRep { + this := RateLimitedErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *RateLimitedErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *RateLimitedErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *RateLimitedErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *RateLimitedErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *RateLimitedErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *RateLimitedErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o RateLimitedErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableRateLimitedErrorRep struct { + value *RateLimitedErrorRep + isSet bool +} + +func (v NullableRateLimitedErrorRep) Get() *RateLimitedErrorRep { + return v.value +} + +func (v *NullableRateLimitedErrorRep) Set(val *RateLimitedErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableRateLimitedErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRateLimitedErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRateLimitedErrorRep(val *RateLimitedErrorRep) *NullableRateLimitedErrorRep { + return &NullableRateLimitedErrorRep{value: val, isSet: true} +} + +func (v NullableRateLimitedErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRateLimitedErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_recent_trigger_body.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_recent_trigger_body.go new file mode 100644 index 00000000..fd78ed5f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_recent_trigger_body.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RecentTriggerBody struct for RecentTriggerBody +type RecentTriggerBody struct { + Timestamp *int64 `json:"timestamp,omitempty"` + // The marshalled JSON request body for the incoming trigger webhook. If this is empty or contains invalid JSON, the timestamp is recorded but this field will be empty. + JsonBody map[string]interface{} `json:"jsonBody,omitempty"` +} + +// NewRecentTriggerBody instantiates a new RecentTriggerBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRecentTriggerBody() *RecentTriggerBody { + this := RecentTriggerBody{} + return &this +} + +// NewRecentTriggerBodyWithDefaults instantiates a new RecentTriggerBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRecentTriggerBodyWithDefaults() *RecentTriggerBody { + this := RecentTriggerBody{} + return &this +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *RecentTriggerBody) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RecentTriggerBody) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *RecentTriggerBody) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *RecentTriggerBody) SetTimestamp(v int64) { + o.Timestamp = &v +} + +// GetJsonBody returns the JsonBody field value if set, zero value otherwise. +func (o *RecentTriggerBody) GetJsonBody() map[string]interface{} { + if o == nil || o.JsonBody == nil { + var ret map[string]interface{} + return ret + } + return o.JsonBody +} + +// GetJsonBodyOk returns a tuple with the JsonBody field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RecentTriggerBody) GetJsonBodyOk() (map[string]interface{}, bool) { + if o == nil || o.JsonBody == nil { + return nil, false + } + return o.JsonBody, true +} + +// HasJsonBody returns a boolean if a field has been set. +func (o *RecentTriggerBody) HasJsonBody() bool { + if o != nil && o.JsonBody != nil { + return true + } + + return false +} + +// SetJsonBody gets a reference to the given map[string]interface{} and assigns it to the JsonBody field. +func (o *RecentTriggerBody) SetJsonBody(v map[string]interface{}) { + o.JsonBody = v +} + +func (o RecentTriggerBody) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + if o.JsonBody != nil { + toSerialize["jsonBody"] = o.JsonBody + } + return json.Marshal(toSerialize) +} + +type NullableRecentTriggerBody struct { + value *RecentTriggerBody + isSet bool +} + +func (v NullableRecentTriggerBody) Get() *RecentTriggerBody { + return v.value +} + +func (v *NullableRecentTriggerBody) Set(val *RecentTriggerBody) { + v.value = val + v.isSet = true +} + +func (v NullableRecentTriggerBody) IsSet() bool { + return v.isSet +} + +func (v *NullableRecentTriggerBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRecentTriggerBody(val *RecentTriggerBody) *NullableRecentTriggerBody { + return &NullableRecentTriggerBody{value: val, isSet: true} +} + +func (v NullableRecentTriggerBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRecentTriggerBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_reference_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_reference_rep.go new file mode 100644 index 00000000..60eb0932 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_reference_rep.go @@ -0,0 +1,176 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReferenceRep struct for ReferenceRep +type ReferenceRep struct { + // File path of the reference + Path string `json:"path"` + // Programming language used in the file + Hint *string `json:"hint,omitempty"` + Hunks []HunkRep `json:"hunks"` +} + +// NewReferenceRep instantiates a new ReferenceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReferenceRep(path string, hunks []HunkRep) *ReferenceRep { + this := ReferenceRep{} + this.Path = path + this.Hunks = hunks + return &this +} + +// NewReferenceRepWithDefaults instantiates a new ReferenceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReferenceRepWithDefaults() *ReferenceRep { + this := ReferenceRep{} + return &this +} + +// GetPath returns the Path field value +func (o *ReferenceRep) GetPath() string { + if o == nil { + var ret string + return ret + } + + return o.Path +} + +// GetPathOk returns a tuple with the Path field value +// and a boolean to check if the value has been set. +func (o *ReferenceRep) GetPathOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Path, true +} + +// SetPath sets field value +func (o *ReferenceRep) SetPath(v string) { + o.Path = v +} + +// GetHint returns the Hint field value if set, zero value otherwise. +func (o *ReferenceRep) GetHint() string { + if o == nil || o.Hint == nil { + var ret string + return ret + } + return *o.Hint +} + +// GetHintOk returns a tuple with the Hint field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReferenceRep) GetHintOk() (*string, bool) { + if o == nil || o.Hint == nil { + return nil, false + } + return o.Hint, true +} + +// HasHint returns a boolean if a field has been set. +func (o *ReferenceRep) HasHint() bool { + if o != nil && o.Hint != nil { + return true + } + + return false +} + +// SetHint gets a reference to the given string and assigns it to the Hint field. +func (o *ReferenceRep) SetHint(v string) { + o.Hint = &v +} + +// GetHunks returns the Hunks field value +func (o *ReferenceRep) GetHunks() []HunkRep { + if o == nil { + var ret []HunkRep + return ret + } + + return o.Hunks +} + +// GetHunksOk returns a tuple with the Hunks field value +// and a boolean to check if the value has been set. +func (o *ReferenceRep) GetHunksOk() ([]HunkRep, bool) { + if o == nil { + return nil, false + } + return o.Hunks, true +} + +// SetHunks sets field value +func (o *ReferenceRep) SetHunks(v []HunkRep) { + o.Hunks = v +} + +func (o ReferenceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["path"] = o.Path + } + if o.Hint != nil { + toSerialize["hint"] = o.Hint + } + if true { + toSerialize["hunks"] = o.Hunks + } + return json.Marshal(toSerialize) +} + +type NullableReferenceRep struct { + value *ReferenceRep + isSet bool +} + +func (v NullableReferenceRep) Get() *ReferenceRep { + return v.value +} + +func (v *NullableReferenceRep) Set(val *ReferenceRep) { + v.value = val + v.isSet = true +} + +func (v NullableReferenceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableReferenceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReferenceRep(val *ReferenceRep) *NullableReferenceRep { + return &NullableReferenceRep{value: val, isSet: true} +} + +func (v NullableReferenceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReferenceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_related_experiment_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_related_experiment_rep.go new file mode 100644 index 00000000..f618c2ad --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_related_experiment_rep.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RelatedExperimentRep struct for RelatedExperimentRep +type RelatedExperimentRep struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + Environment *string `json:"environment,omitempty"` +} + +// NewRelatedExperimentRep instantiates a new RelatedExperimentRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelatedExperimentRep() *RelatedExperimentRep { + this := RelatedExperimentRep{} + return &this +} + +// NewRelatedExperimentRepWithDefaults instantiates a new RelatedExperimentRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRelatedExperimentRepWithDefaults() *RelatedExperimentRep { + this := RelatedExperimentRep{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *RelatedExperimentRep) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelatedExperimentRep) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *RelatedExperimentRep) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *RelatedExperimentRep) SetKey(v string) { + o.Key = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *RelatedExperimentRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelatedExperimentRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *RelatedExperimentRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *RelatedExperimentRep) SetName(v string) { + o.Name = &v +} + +// GetEnvironment returns the Environment field value if set, zero value otherwise. +func (o *RelatedExperimentRep) GetEnvironment() string { + if o == nil || o.Environment == nil { + var ret string + return ret + } + return *o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelatedExperimentRep) GetEnvironmentOk() (*string, bool) { + if o == nil || o.Environment == nil { + return nil, false + } + return o.Environment, true +} + +// HasEnvironment returns a boolean if a field has been set. +func (o *RelatedExperimentRep) HasEnvironment() bool { + if o != nil && o.Environment != nil { + return true + } + + return false +} + +// SetEnvironment gets a reference to the given string and assigns it to the Environment field. +func (o *RelatedExperimentRep) SetEnvironment(v string) { + o.Environment = &v +} + +func (o RelatedExperimentRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Environment != nil { + toSerialize["environment"] = o.Environment + } + return json.Marshal(toSerialize) +} + +type NullableRelatedExperimentRep struct { + value *RelatedExperimentRep + isSet bool +} + +func (v NullableRelatedExperimentRep) Get() *RelatedExperimentRep { + return v.value +} + +func (v *NullableRelatedExperimentRep) Set(val *RelatedExperimentRep) { + v.value = val + v.isSet = true +} + +func (v NullableRelatedExperimentRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRelatedExperimentRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelatedExperimentRep(val *RelatedExperimentRep) *NullableRelatedExperimentRep { + return &NullableRelatedExperimentRep{value: val, isSet: true} +} + +func (v NullableRelatedExperimentRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelatedExperimentRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_relative_difference_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_relative_difference_rep.go new file mode 100644 index 00000000..7ab747e0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_relative_difference_rep.go @@ -0,0 +1,265 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RelativeDifferenceRep struct for RelativeDifferenceRep +type RelativeDifferenceRep struct { + // An upper bound of the relative difference between the treatment and the fromTreatmentId + Upper *float32 `json:"upper,omitempty"` + // A lower bound of the relative difference between the treatment and the fromTreatmentId + Lower *float32 `json:"lower,omitempty"` + // The treatment ID of the treatment against which the relative difference is calculated + FromTreatmentId *string `json:"fromTreatmentId,omitempty"` + // Variance of the relative difference + Variance *float32 `json:"variance,omitempty"` + // The reduction in variance resulting from CUPED + VarianceReduction *float32 `json:"varianceReduction,omitempty"` +} + +// NewRelativeDifferenceRep instantiates a new RelativeDifferenceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelativeDifferenceRep() *RelativeDifferenceRep { + this := RelativeDifferenceRep{} + return &this +} + +// NewRelativeDifferenceRepWithDefaults instantiates a new RelativeDifferenceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRelativeDifferenceRepWithDefaults() *RelativeDifferenceRep { + this := RelativeDifferenceRep{} + return &this +} + +// GetUpper returns the Upper field value if set, zero value otherwise. +func (o *RelativeDifferenceRep) GetUpper() float32 { + if o == nil || o.Upper == nil { + var ret float32 + return ret + } + return *o.Upper +} + +// GetUpperOk returns a tuple with the Upper field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelativeDifferenceRep) GetUpperOk() (*float32, bool) { + if o == nil || o.Upper == nil { + return nil, false + } + return o.Upper, true +} + +// HasUpper returns a boolean if a field has been set. +func (o *RelativeDifferenceRep) HasUpper() bool { + if o != nil && o.Upper != nil { + return true + } + + return false +} + +// SetUpper gets a reference to the given float32 and assigns it to the Upper field. +func (o *RelativeDifferenceRep) SetUpper(v float32) { + o.Upper = &v +} + +// GetLower returns the Lower field value if set, zero value otherwise. +func (o *RelativeDifferenceRep) GetLower() float32 { + if o == nil || o.Lower == nil { + var ret float32 + return ret + } + return *o.Lower +} + +// GetLowerOk returns a tuple with the Lower field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelativeDifferenceRep) GetLowerOk() (*float32, bool) { + if o == nil || o.Lower == nil { + return nil, false + } + return o.Lower, true +} + +// HasLower returns a boolean if a field has been set. +func (o *RelativeDifferenceRep) HasLower() bool { + if o != nil && o.Lower != nil { + return true + } + + return false +} + +// SetLower gets a reference to the given float32 and assigns it to the Lower field. +func (o *RelativeDifferenceRep) SetLower(v float32) { + o.Lower = &v +} + +// GetFromTreatmentId returns the FromTreatmentId field value if set, zero value otherwise. +func (o *RelativeDifferenceRep) GetFromTreatmentId() string { + if o == nil || o.FromTreatmentId == nil { + var ret string + return ret + } + return *o.FromTreatmentId +} + +// GetFromTreatmentIdOk returns a tuple with the FromTreatmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelativeDifferenceRep) GetFromTreatmentIdOk() (*string, bool) { + if o == nil || o.FromTreatmentId == nil { + return nil, false + } + return o.FromTreatmentId, true +} + +// HasFromTreatmentId returns a boolean if a field has been set. +func (o *RelativeDifferenceRep) HasFromTreatmentId() bool { + if o != nil && o.FromTreatmentId != nil { + return true + } + + return false +} + +// SetFromTreatmentId gets a reference to the given string and assigns it to the FromTreatmentId field. +func (o *RelativeDifferenceRep) SetFromTreatmentId(v string) { + o.FromTreatmentId = &v +} + +// GetVariance returns the Variance field value if set, zero value otherwise. +func (o *RelativeDifferenceRep) GetVariance() float32 { + if o == nil || o.Variance == nil { + var ret float32 + return ret + } + return *o.Variance +} + +// GetVarianceOk returns a tuple with the Variance field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelativeDifferenceRep) GetVarianceOk() (*float32, bool) { + if o == nil || o.Variance == nil { + return nil, false + } + return o.Variance, true +} + +// HasVariance returns a boolean if a field has been set. +func (o *RelativeDifferenceRep) HasVariance() bool { + if o != nil && o.Variance != nil { + return true + } + + return false +} + +// SetVariance gets a reference to the given float32 and assigns it to the Variance field. +func (o *RelativeDifferenceRep) SetVariance(v float32) { + o.Variance = &v +} + +// GetVarianceReduction returns the VarianceReduction field value if set, zero value otherwise. +func (o *RelativeDifferenceRep) GetVarianceReduction() float32 { + if o == nil || o.VarianceReduction == nil { + var ret float32 + return ret + } + return *o.VarianceReduction +} + +// GetVarianceReductionOk returns a tuple with the VarianceReduction field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelativeDifferenceRep) GetVarianceReductionOk() (*float32, bool) { + if o == nil || o.VarianceReduction == nil { + return nil, false + } + return o.VarianceReduction, true +} + +// HasVarianceReduction returns a boolean if a field has been set. +func (o *RelativeDifferenceRep) HasVarianceReduction() bool { + if o != nil && o.VarianceReduction != nil { + return true + } + + return false +} + +// SetVarianceReduction gets a reference to the given float32 and assigns it to the VarianceReduction field. +func (o *RelativeDifferenceRep) SetVarianceReduction(v float32) { + o.VarianceReduction = &v +} + +func (o RelativeDifferenceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Upper != nil { + toSerialize["upper"] = o.Upper + } + if o.Lower != nil { + toSerialize["lower"] = o.Lower + } + if o.FromTreatmentId != nil { + toSerialize["fromTreatmentId"] = o.FromTreatmentId + } + if o.Variance != nil { + toSerialize["variance"] = o.Variance + } + if o.VarianceReduction != nil { + toSerialize["varianceReduction"] = o.VarianceReduction + } + return json.Marshal(toSerialize) +} + +type NullableRelativeDifferenceRep struct { + value *RelativeDifferenceRep + isSet bool +} + +func (v NullableRelativeDifferenceRep) Get() *RelativeDifferenceRep { + return v.value +} + +func (v *NullableRelativeDifferenceRep) Set(val *RelativeDifferenceRep) { + v.value = val + v.isSet = true +} + +func (v NullableRelativeDifferenceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRelativeDifferenceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelativeDifferenceRep(val *RelativeDifferenceRep) *NullableRelativeDifferenceRep { + return &NullableRelativeDifferenceRep{value: val, isSet: true} +} + +func (v NullableRelativeDifferenceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelativeDifferenceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_collection_rep.go new file mode 100644 index 00000000..bddc72b2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_collection_rep.go @@ -0,0 +1,110 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RelayAutoConfigCollectionRep struct for RelayAutoConfigCollectionRep +type RelayAutoConfigCollectionRep struct { + // An array of Relay Proxy configurations + Items []RelayAutoConfigRep `json:"items"` +} + +// NewRelayAutoConfigCollectionRep instantiates a new RelayAutoConfigCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelayAutoConfigCollectionRep(items []RelayAutoConfigRep) *RelayAutoConfigCollectionRep { + this := RelayAutoConfigCollectionRep{} + this.Items = items + return &this +} + +// NewRelayAutoConfigCollectionRepWithDefaults instantiates a new RelayAutoConfigCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRelayAutoConfigCollectionRepWithDefaults() *RelayAutoConfigCollectionRep { + this := RelayAutoConfigCollectionRep{} + return &this +} + +// GetItems returns the Items field value +func (o *RelayAutoConfigCollectionRep) GetItems() []RelayAutoConfigRep { + if o == nil { + var ret []RelayAutoConfigRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigCollectionRep) GetItemsOk() ([]RelayAutoConfigRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *RelayAutoConfigCollectionRep) SetItems(v []RelayAutoConfigRep) { + o.Items = v +} + +func (o RelayAutoConfigCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableRelayAutoConfigCollectionRep struct { + value *RelayAutoConfigCollectionRep + isSet bool +} + +func (v NullableRelayAutoConfigCollectionRep) Get() *RelayAutoConfigCollectionRep { + return v.value +} + +func (v *NullableRelayAutoConfigCollectionRep) Set(val *RelayAutoConfigCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableRelayAutoConfigCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRelayAutoConfigCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelayAutoConfigCollectionRep(val *RelayAutoConfigCollectionRep) *NullableRelayAutoConfigCollectionRep { + return &NullableRelayAutoConfigCollectionRep{value: val, isSet: true} +} + +func (v NullableRelayAutoConfigCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelayAutoConfigCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_post.go new file mode 100644 index 00000000..a25c6f89 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_post.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RelayAutoConfigPost struct for RelayAutoConfigPost +type RelayAutoConfigPost struct { + // A human-friendly name for the Relay Proxy configuration + Name string `json:"name"` + // A description of what environments and projects the Relay Proxy should include or exclude. To learn more, read [Write an inline policy](https://launchdarkly.com/docs/sdk/relay-proxy/automatic-configuration#write-an-inline-policy). + Policy []Statement `json:"policy"` +} + +// NewRelayAutoConfigPost instantiates a new RelayAutoConfigPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelayAutoConfigPost(name string, policy []Statement) *RelayAutoConfigPost { + this := RelayAutoConfigPost{} + this.Name = name + this.Policy = policy + return &this +} + +// NewRelayAutoConfigPostWithDefaults instantiates a new RelayAutoConfigPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRelayAutoConfigPostWithDefaults() *RelayAutoConfigPost { + this := RelayAutoConfigPost{} + return &this +} + +// GetName returns the Name field value +func (o *RelayAutoConfigPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *RelayAutoConfigPost) SetName(v string) { + o.Name = v +} + +// GetPolicy returns the Policy field value +func (o *RelayAutoConfigPost) GetPolicy() []Statement { + if o == nil { + var ret []Statement + return ret + } + + return o.Policy +} + +// GetPolicyOk returns a tuple with the Policy field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigPost) GetPolicyOk() ([]Statement, bool) { + if o == nil { + return nil, false + } + return o.Policy, true +} + +// SetPolicy sets field value +func (o *RelayAutoConfigPost) SetPolicy(v []Statement) { + o.Policy = v +} + +func (o RelayAutoConfigPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["policy"] = o.Policy + } + return json.Marshal(toSerialize) +} + +type NullableRelayAutoConfigPost struct { + value *RelayAutoConfigPost + isSet bool +} + +func (v NullableRelayAutoConfigPost) Get() *RelayAutoConfigPost { + return v.value +} + +func (v *NullableRelayAutoConfigPost) Set(val *RelayAutoConfigPost) { + v.value = val + v.isSet = true +} + +func (v NullableRelayAutoConfigPost) IsSet() bool { + return v.isSet +} + +func (v *NullableRelayAutoConfigPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelayAutoConfigPost(val *RelayAutoConfigPost) *NullableRelayAutoConfigPost { + return &NullableRelayAutoConfigPost{value: val, isSet: true} +} + +func (v NullableRelayAutoConfigPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelayAutoConfigPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_rep.go new file mode 100644 index 00000000..60119a5e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_relay_auto_config_rep.go @@ -0,0 +1,359 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RelayAutoConfigRep struct for RelayAutoConfigRep +type RelayAutoConfigRep struct { + Id string `json:"_id"` + Creator *MemberSummary `json:"_creator,omitempty"` + Access *Access `json:"_access,omitempty"` + // A human-friendly name for the Relay Proxy configuration + Name string `json:"name"` + // A description of what environments and projects the Relay Proxy should include or exclude + Policy []Statement `json:"policy"` + // The Relay Proxy configuration key + FullKey string `json:"fullKey"` + // The last few characters of the Relay Proxy configuration key, displayed in the LaunchDarkly UI + DisplayKey string `json:"displayKey"` + CreationDate int64 `json:"creationDate"` + LastModified int64 `json:"lastModified"` +} + +// NewRelayAutoConfigRep instantiates a new RelayAutoConfigRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelayAutoConfigRep(id string, name string, policy []Statement, fullKey string, displayKey string, creationDate int64, lastModified int64) *RelayAutoConfigRep { + this := RelayAutoConfigRep{} + this.Id = id + this.Name = name + this.Policy = policy + this.FullKey = fullKey + this.DisplayKey = displayKey + this.CreationDate = creationDate + this.LastModified = lastModified + return &this +} + +// NewRelayAutoConfigRepWithDefaults instantiates a new RelayAutoConfigRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRelayAutoConfigRepWithDefaults() *RelayAutoConfigRep { + this := RelayAutoConfigRep{} + return &this +} + +// GetId returns the Id field value +func (o *RelayAutoConfigRep) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *RelayAutoConfigRep) SetId(v string) { + o.Id = v +} + +// GetCreator returns the Creator field value if set, zero value otherwise. +func (o *RelayAutoConfigRep) GetCreator() MemberSummary { + if o == nil || o.Creator == nil { + var ret MemberSummary + return ret + } + return *o.Creator +} + +// GetCreatorOk returns a tuple with the Creator field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetCreatorOk() (*MemberSummary, bool) { + if o == nil || o.Creator == nil { + return nil, false + } + return o.Creator, true +} + +// HasCreator returns a boolean if a field has been set. +func (o *RelayAutoConfigRep) HasCreator() bool { + if o != nil && o.Creator != nil { + return true + } + + return false +} + +// SetCreator gets a reference to the given MemberSummary and assigns it to the Creator field. +func (o *RelayAutoConfigRep) SetCreator(v MemberSummary) { + o.Creator = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *RelayAutoConfigRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *RelayAutoConfigRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *RelayAutoConfigRep) SetAccess(v Access) { + o.Access = &v +} + +// GetName returns the Name field value +func (o *RelayAutoConfigRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *RelayAutoConfigRep) SetName(v string) { + o.Name = v +} + +// GetPolicy returns the Policy field value +func (o *RelayAutoConfigRep) GetPolicy() []Statement { + if o == nil { + var ret []Statement + return ret + } + + return o.Policy +} + +// GetPolicyOk returns a tuple with the Policy field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetPolicyOk() ([]Statement, bool) { + if o == nil { + return nil, false + } + return o.Policy, true +} + +// SetPolicy sets field value +func (o *RelayAutoConfigRep) SetPolicy(v []Statement) { + o.Policy = v +} + +// GetFullKey returns the FullKey field value +func (o *RelayAutoConfigRep) GetFullKey() string { + if o == nil { + var ret string + return ret + } + + return o.FullKey +} + +// GetFullKeyOk returns a tuple with the FullKey field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetFullKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FullKey, true +} + +// SetFullKey sets field value +func (o *RelayAutoConfigRep) SetFullKey(v string) { + o.FullKey = v +} + +// GetDisplayKey returns the DisplayKey field value +func (o *RelayAutoConfigRep) GetDisplayKey() string { + if o == nil { + var ret string + return ret + } + + return o.DisplayKey +} + +// GetDisplayKeyOk returns a tuple with the DisplayKey field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetDisplayKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.DisplayKey, true +} + +// SetDisplayKey sets field value +func (o *RelayAutoConfigRep) SetDisplayKey(v string) { + o.DisplayKey = v +} + +// GetCreationDate returns the CreationDate field value +func (o *RelayAutoConfigRep) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *RelayAutoConfigRep) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value +func (o *RelayAutoConfigRep) GetLastModified() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value +// and a boolean to check if the value has been set. +func (o *RelayAutoConfigRep) GetLastModifiedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModified, true +} + +// SetLastModified sets field value +func (o *RelayAutoConfigRep) SetLastModified(v int64) { + o.LastModified = v +} + +func (o RelayAutoConfigRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if o.Creator != nil { + toSerialize["_creator"] = o.Creator + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["policy"] = o.Policy + } + if true { + toSerialize["fullKey"] = o.FullKey + } + if true { + toSerialize["displayKey"] = o.DisplayKey + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["lastModified"] = o.LastModified + } + return json.Marshal(toSerialize) +} + +type NullableRelayAutoConfigRep struct { + value *RelayAutoConfigRep + isSet bool +} + +func (v NullableRelayAutoConfigRep) Get() *RelayAutoConfigRep { + return v.value +} + +func (v *NullableRelayAutoConfigRep) Set(val *RelayAutoConfigRep) { + v.value = val + v.isSet = true +} + +func (v NullableRelayAutoConfigRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRelayAutoConfigRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelayAutoConfigRep(val *RelayAutoConfigRep) *NullableRelayAutoConfigRep { + return &NullableRelayAutoConfigRep{value: val, isSet: true} +} + +func (v NullableRelayAutoConfigRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelayAutoConfigRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release.go new file mode 100644 index 00000000..84efb5a0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release.go @@ -0,0 +1,340 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Release struct for Release +type Release struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The release pipeline name + Name string `json:"name"` + // The release pipeline key + ReleasePipelineKey string `json:"releasePipelineKey"` + // The release pipeline description + ReleasePipelineDescription string `json:"releasePipelineDescription"` + // An ordered list of the release pipeline phases + Phases []ReleasePhase `json:"phases"` + // The release version + Version int32 `json:"_version"` + // The chosen release variation ID to use across all phases of a release + ReleaseVariationId *string `json:"_releaseVariationId,omitempty"` + CanceledAt *int64 `json:"_canceledAt,omitempty"` +} + +// NewRelease instantiates a new Release object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRelease(name string, releasePipelineKey string, releasePipelineDescription string, phases []ReleasePhase, version int32) *Release { + this := Release{} + this.Name = name + this.ReleasePipelineKey = releasePipelineKey + this.ReleasePipelineDescription = releasePipelineDescription + this.Phases = phases + this.Version = version + return &this +} + +// NewReleaseWithDefaults instantiates a new Release object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseWithDefaults() *Release { + this := Release{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Release) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Release) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Release) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Release) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value +func (o *Release) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *Release) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *Release) SetName(v string) { + o.Name = v +} + +// GetReleasePipelineKey returns the ReleasePipelineKey field value +func (o *Release) GetReleasePipelineKey() string { + if o == nil { + var ret string + return ret + } + + return o.ReleasePipelineKey +} + +// GetReleasePipelineKeyOk returns a tuple with the ReleasePipelineKey field value +// and a boolean to check if the value has been set. +func (o *Release) GetReleasePipelineKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReleasePipelineKey, true +} + +// SetReleasePipelineKey sets field value +func (o *Release) SetReleasePipelineKey(v string) { + o.ReleasePipelineKey = v +} + +// GetReleasePipelineDescription returns the ReleasePipelineDescription field value +func (o *Release) GetReleasePipelineDescription() string { + if o == nil { + var ret string + return ret + } + + return o.ReleasePipelineDescription +} + +// GetReleasePipelineDescriptionOk returns a tuple with the ReleasePipelineDescription field value +// and a boolean to check if the value has been set. +func (o *Release) GetReleasePipelineDescriptionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ReleasePipelineDescription, true +} + +// SetReleasePipelineDescription sets field value +func (o *Release) SetReleasePipelineDescription(v string) { + o.ReleasePipelineDescription = v +} + +// GetPhases returns the Phases field value +func (o *Release) GetPhases() []ReleasePhase { + if o == nil { + var ret []ReleasePhase + return ret + } + + return o.Phases +} + +// GetPhasesOk returns a tuple with the Phases field value +// and a boolean to check if the value has been set. +func (o *Release) GetPhasesOk() ([]ReleasePhase, bool) { + if o == nil { + return nil, false + } + return o.Phases, true +} + +// SetPhases sets field value +func (o *Release) SetPhases(v []ReleasePhase) { + o.Phases = v +} + +// GetVersion returns the Version field value +func (o *Release) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *Release) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *Release) SetVersion(v int32) { + o.Version = v +} + +// GetReleaseVariationId returns the ReleaseVariationId field value if set, zero value otherwise. +func (o *Release) GetReleaseVariationId() string { + if o == nil || o.ReleaseVariationId == nil { + var ret string + return ret + } + return *o.ReleaseVariationId +} + +// GetReleaseVariationIdOk returns a tuple with the ReleaseVariationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Release) GetReleaseVariationIdOk() (*string, bool) { + if o == nil || o.ReleaseVariationId == nil { + return nil, false + } + return o.ReleaseVariationId, true +} + +// HasReleaseVariationId returns a boolean if a field has been set. +func (o *Release) HasReleaseVariationId() bool { + if o != nil && o.ReleaseVariationId != nil { + return true + } + + return false +} + +// SetReleaseVariationId gets a reference to the given string and assigns it to the ReleaseVariationId field. +func (o *Release) SetReleaseVariationId(v string) { + o.ReleaseVariationId = &v +} + +// GetCanceledAt returns the CanceledAt field value if set, zero value otherwise. +func (o *Release) GetCanceledAt() int64 { + if o == nil || o.CanceledAt == nil { + var ret int64 + return ret + } + return *o.CanceledAt +} + +// GetCanceledAtOk returns a tuple with the CanceledAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Release) GetCanceledAtOk() (*int64, bool) { + if o == nil || o.CanceledAt == nil { + return nil, false + } + return o.CanceledAt, true +} + +// HasCanceledAt returns a boolean if a field has been set. +func (o *Release) HasCanceledAt() bool { + if o != nil && o.CanceledAt != nil { + return true + } + + return false +} + +// SetCanceledAt gets a reference to the given int64 and assigns it to the CanceledAt field. +func (o *Release) SetCanceledAt(v int64) { + o.CanceledAt = &v +} + +func (o Release) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["releasePipelineKey"] = o.ReleasePipelineKey + } + if true { + toSerialize["releasePipelineDescription"] = o.ReleasePipelineDescription + } + if true { + toSerialize["phases"] = o.Phases + } + if true { + toSerialize["_version"] = o.Version + } + if o.ReleaseVariationId != nil { + toSerialize["_releaseVariationId"] = o.ReleaseVariationId + } + if o.CanceledAt != nil { + toSerialize["_canceledAt"] = o.CanceledAt + } + return json.Marshal(toSerialize) +} + +type NullableRelease struct { + value *Release + isSet bool +} + +func (v NullableRelease) Get() *Release { + return v.value +} + +func (v *NullableRelease) Set(val *Release) { + v.value = val + v.isSet = true +} + +func (v NullableRelease) IsSet() bool { + return v.isSet +} + +func (v *NullableRelease) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRelease(val *Release) *NullableRelease { + return &NullableRelease{value: val, isSet: true} +} + +func (v NullableRelease) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRelease) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_audience.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_audience.go new file mode 100644 index 00000000..48526e33 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_audience.go @@ -0,0 +1,359 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaseAudience struct for ReleaseAudience +type ReleaseAudience struct { + // The audience ID + Id string `json:"_id"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + Environment *EnvironmentSummary `json:"environment,omitempty"` + // The release phase name + Name string `json:"name"` + Configuration *AudienceConfiguration `json:"configuration,omitempty"` + // A list of segment keys + SegmentKeys []string `json:"segmentKeys,omitempty"` + Status *string `json:"status,omitempty"` + // The rules IDs added or updated by this audience + RuleIds []string `json:"_ruleIds,omitempty"` +} + +// NewReleaseAudience instantiates a new ReleaseAudience object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseAudience(id string, name string) *ReleaseAudience { + this := ReleaseAudience{} + this.Id = id + this.Name = name + return &this +} + +// NewReleaseAudienceWithDefaults instantiates a new ReleaseAudience object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseAudienceWithDefaults() *ReleaseAudience { + this := ReleaseAudience{} + return &this +} + +// GetId returns the Id field value +func (o *ReleaseAudience) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ReleaseAudience) SetId(v string) { + o.Id = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *ReleaseAudience) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *ReleaseAudience) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *ReleaseAudience) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetEnvironment returns the Environment field value if set, zero value otherwise. +func (o *ReleaseAudience) GetEnvironment() EnvironmentSummary { + if o == nil || o.Environment == nil { + var ret EnvironmentSummary + return ret + } + return *o.Environment +} + +// GetEnvironmentOk returns a tuple with the Environment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetEnvironmentOk() (*EnvironmentSummary, bool) { + if o == nil || o.Environment == nil { + return nil, false + } + return o.Environment, true +} + +// HasEnvironment returns a boolean if a field has been set. +func (o *ReleaseAudience) HasEnvironment() bool { + if o != nil && o.Environment != nil { + return true + } + + return false +} + +// SetEnvironment gets a reference to the given EnvironmentSummary and assigns it to the Environment field. +func (o *ReleaseAudience) SetEnvironment(v EnvironmentSummary) { + o.Environment = &v +} + +// GetName returns the Name field value +func (o *ReleaseAudience) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ReleaseAudience) SetName(v string) { + o.Name = v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *ReleaseAudience) GetConfiguration() AudienceConfiguration { + if o == nil || o.Configuration == nil { + var ret AudienceConfiguration + return ret + } + return *o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetConfigurationOk() (*AudienceConfiguration, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *ReleaseAudience) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given AudienceConfiguration and assigns it to the Configuration field. +func (o *ReleaseAudience) SetConfiguration(v AudienceConfiguration) { + o.Configuration = &v +} + +// GetSegmentKeys returns the SegmentKeys field value if set, zero value otherwise. +func (o *ReleaseAudience) GetSegmentKeys() []string { + if o == nil || o.SegmentKeys == nil { + var ret []string + return ret + } + return o.SegmentKeys +} + +// GetSegmentKeysOk returns a tuple with the SegmentKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetSegmentKeysOk() ([]string, bool) { + if o == nil || o.SegmentKeys == nil { + return nil, false + } + return o.SegmentKeys, true +} + +// HasSegmentKeys returns a boolean if a field has been set. +func (o *ReleaseAudience) HasSegmentKeys() bool { + if o != nil && o.SegmentKeys != nil { + return true + } + + return false +} + +// SetSegmentKeys gets a reference to the given []string and assigns it to the SegmentKeys field. +func (o *ReleaseAudience) SetSegmentKeys(v []string) { + o.SegmentKeys = v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *ReleaseAudience) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *ReleaseAudience) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *ReleaseAudience) SetStatus(v string) { + o.Status = &v +} + +// GetRuleIds returns the RuleIds field value if set, zero value otherwise. +func (o *ReleaseAudience) GetRuleIds() []string { + if o == nil || o.RuleIds == nil { + var ret []string + return ret + } + return o.RuleIds +} + +// GetRuleIdsOk returns a tuple with the RuleIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAudience) GetRuleIdsOk() ([]string, bool) { + if o == nil || o.RuleIds == nil { + return nil, false + } + return o.RuleIds, true +} + +// HasRuleIds returns a boolean if a field has been set. +func (o *ReleaseAudience) HasRuleIds() bool { + if o != nil && o.RuleIds != nil { + return true + } + + return false +} + +// SetRuleIds gets a reference to the given []string and assigns it to the RuleIds field. +func (o *ReleaseAudience) SetRuleIds(v []string) { + o.RuleIds = v +} + +func (o ReleaseAudience) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Environment != nil { + toSerialize["environment"] = o.Environment + } + if true { + toSerialize["name"] = o.Name + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + if o.SegmentKeys != nil { + toSerialize["segmentKeys"] = o.SegmentKeys + } + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.RuleIds != nil { + toSerialize["_ruleIds"] = o.RuleIds + } + return json.Marshal(toSerialize) +} + +type NullableReleaseAudience struct { + value *ReleaseAudience + isSet bool +} + +func (v NullableReleaseAudience) Get() *ReleaseAudience { + return v.value +} + +func (v *NullableReleaseAudience) Set(val *ReleaseAudience) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseAudience) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseAudience) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseAudience(val *ReleaseAudience) *NullableReleaseAudience { + return &NullableReleaseAudience{value: val, isSet: true} +} + +func (v NullableReleaseAudience) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseAudience) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration.go new file mode 100644 index 00000000..fc611f07 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration.go @@ -0,0 +1,207 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaseGuardianConfiguration struct for ReleaseGuardianConfiguration +type ReleaseGuardianConfiguration struct { + // The monitoring window in milliseconds + MonitoringWindowMilliseconds int64 `json:"monitoringWindowMilliseconds"` + // The rollout weight percentage + RolloutWeight int32 `json:"rolloutWeight"` + // Whether or not to roll back on regression + RollbackOnRegression bool `json:"rollbackOnRegression"` + // The randomization unit for the measured rollout + RandomizationUnit *string `json:"randomizationUnit,omitempty"` +} + +// NewReleaseGuardianConfiguration instantiates a new ReleaseGuardianConfiguration object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseGuardianConfiguration(monitoringWindowMilliseconds int64, rolloutWeight int32, rollbackOnRegression bool) *ReleaseGuardianConfiguration { + this := ReleaseGuardianConfiguration{} + this.MonitoringWindowMilliseconds = monitoringWindowMilliseconds + this.RolloutWeight = rolloutWeight + this.RollbackOnRegression = rollbackOnRegression + return &this +} + +// NewReleaseGuardianConfigurationWithDefaults instantiates a new ReleaseGuardianConfiguration object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseGuardianConfigurationWithDefaults() *ReleaseGuardianConfiguration { + this := ReleaseGuardianConfiguration{} + return &this +} + +// GetMonitoringWindowMilliseconds returns the MonitoringWindowMilliseconds field value +func (o *ReleaseGuardianConfiguration) GetMonitoringWindowMilliseconds() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.MonitoringWindowMilliseconds +} + +// GetMonitoringWindowMillisecondsOk returns a tuple with the MonitoringWindowMilliseconds field value +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfiguration) GetMonitoringWindowMillisecondsOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.MonitoringWindowMilliseconds, true +} + +// SetMonitoringWindowMilliseconds sets field value +func (o *ReleaseGuardianConfiguration) SetMonitoringWindowMilliseconds(v int64) { + o.MonitoringWindowMilliseconds = v +} + +// GetRolloutWeight returns the RolloutWeight field value +func (o *ReleaseGuardianConfiguration) GetRolloutWeight() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.RolloutWeight +} + +// GetRolloutWeightOk returns a tuple with the RolloutWeight field value +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfiguration) GetRolloutWeightOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.RolloutWeight, true +} + +// SetRolloutWeight sets field value +func (o *ReleaseGuardianConfiguration) SetRolloutWeight(v int32) { + o.RolloutWeight = v +} + +// GetRollbackOnRegression returns the RollbackOnRegression field value +func (o *ReleaseGuardianConfiguration) GetRollbackOnRegression() bool { + if o == nil { + var ret bool + return ret + } + + return o.RollbackOnRegression +} + +// GetRollbackOnRegressionOk returns a tuple with the RollbackOnRegression field value +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfiguration) GetRollbackOnRegressionOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.RollbackOnRegression, true +} + +// SetRollbackOnRegression sets field value +func (o *ReleaseGuardianConfiguration) SetRollbackOnRegression(v bool) { + o.RollbackOnRegression = v +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *ReleaseGuardianConfiguration) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfiguration) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *ReleaseGuardianConfiguration) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *ReleaseGuardianConfiguration) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +func (o ReleaseGuardianConfiguration) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["monitoringWindowMilliseconds"] = o.MonitoringWindowMilliseconds + } + if true { + toSerialize["rolloutWeight"] = o.RolloutWeight + } + if true { + toSerialize["rollbackOnRegression"] = o.RollbackOnRegression + } + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + return json.Marshal(toSerialize) +} + +type NullableReleaseGuardianConfiguration struct { + value *ReleaseGuardianConfiguration + isSet bool +} + +func (v NullableReleaseGuardianConfiguration) Get() *ReleaseGuardianConfiguration { + return v.value +} + +func (v *NullableReleaseGuardianConfiguration) Set(val *ReleaseGuardianConfiguration) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseGuardianConfiguration) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseGuardianConfiguration) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseGuardianConfiguration(val *ReleaseGuardianConfiguration) *NullableReleaseGuardianConfiguration { + return &NullableReleaseGuardianConfiguration{value: val, isSet: true} +} + +func (v NullableReleaseGuardianConfiguration) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseGuardianConfiguration) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration_input.go new file mode 100644 index 00000000..9e436131 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_guardian_configuration_input.go @@ -0,0 +1,228 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaseGuardianConfigurationInput struct for ReleaseGuardianConfigurationInput +type ReleaseGuardianConfigurationInput struct { + // The monitoring window in milliseconds + MonitoringWindowMilliseconds *int64 `json:"monitoringWindowMilliseconds,omitempty"` + // The rollout weight + RolloutWeight *int32 `json:"rolloutWeight,omitempty"` + // Whether or not to rollback on regression + RollbackOnRegression *bool `json:"rollbackOnRegression,omitempty"` + // The randomization unit for the measured rollout + RandomizationUnit *string `json:"randomizationUnit,omitempty"` +} + +// NewReleaseGuardianConfigurationInput instantiates a new ReleaseGuardianConfigurationInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseGuardianConfigurationInput() *ReleaseGuardianConfigurationInput { + this := ReleaseGuardianConfigurationInput{} + return &this +} + +// NewReleaseGuardianConfigurationInputWithDefaults instantiates a new ReleaseGuardianConfigurationInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseGuardianConfigurationInputWithDefaults() *ReleaseGuardianConfigurationInput { + this := ReleaseGuardianConfigurationInput{} + return &this +} + +// GetMonitoringWindowMilliseconds returns the MonitoringWindowMilliseconds field value if set, zero value otherwise. +func (o *ReleaseGuardianConfigurationInput) GetMonitoringWindowMilliseconds() int64 { + if o == nil || o.MonitoringWindowMilliseconds == nil { + var ret int64 + return ret + } + return *o.MonitoringWindowMilliseconds +} + +// GetMonitoringWindowMillisecondsOk returns a tuple with the MonitoringWindowMilliseconds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfigurationInput) GetMonitoringWindowMillisecondsOk() (*int64, bool) { + if o == nil || o.MonitoringWindowMilliseconds == nil { + return nil, false + } + return o.MonitoringWindowMilliseconds, true +} + +// HasMonitoringWindowMilliseconds returns a boolean if a field has been set. +func (o *ReleaseGuardianConfigurationInput) HasMonitoringWindowMilliseconds() bool { + if o != nil && o.MonitoringWindowMilliseconds != nil { + return true + } + + return false +} + +// SetMonitoringWindowMilliseconds gets a reference to the given int64 and assigns it to the MonitoringWindowMilliseconds field. +func (o *ReleaseGuardianConfigurationInput) SetMonitoringWindowMilliseconds(v int64) { + o.MonitoringWindowMilliseconds = &v +} + +// GetRolloutWeight returns the RolloutWeight field value if set, zero value otherwise. +func (o *ReleaseGuardianConfigurationInput) GetRolloutWeight() int32 { + if o == nil || o.RolloutWeight == nil { + var ret int32 + return ret + } + return *o.RolloutWeight +} + +// GetRolloutWeightOk returns a tuple with the RolloutWeight field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfigurationInput) GetRolloutWeightOk() (*int32, bool) { + if o == nil || o.RolloutWeight == nil { + return nil, false + } + return o.RolloutWeight, true +} + +// HasRolloutWeight returns a boolean if a field has been set. +func (o *ReleaseGuardianConfigurationInput) HasRolloutWeight() bool { + if o != nil && o.RolloutWeight != nil { + return true + } + + return false +} + +// SetRolloutWeight gets a reference to the given int32 and assigns it to the RolloutWeight field. +func (o *ReleaseGuardianConfigurationInput) SetRolloutWeight(v int32) { + o.RolloutWeight = &v +} + +// GetRollbackOnRegression returns the RollbackOnRegression field value if set, zero value otherwise. +func (o *ReleaseGuardianConfigurationInput) GetRollbackOnRegression() bool { + if o == nil || o.RollbackOnRegression == nil { + var ret bool + return ret + } + return *o.RollbackOnRegression +} + +// GetRollbackOnRegressionOk returns a tuple with the RollbackOnRegression field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfigurationInput) GetRollbackOnRegressionOk() (*bool, bool) { + if o == nil || o.RollbackOnRegression == nil { + return nil, false + } + return o.RollbackOnRegression, true +} + +// HasRollbackOnRegression returns a boolean if a field has been set. +func (o *ReleaseGuardianConfigurationInput) HasRollbackOnRegression() bool { + if o != nil && o.RollbackOnRegression != nil { + return true + } + + return false +} + +// SetRollbackOnRegression gets a reference to the given bool and assigns it to the RollbackOnRegression field. +func (o *ReleaseGuardianConfigurationInput) SetRollbackOnRegression(v bool) { + o.RollbackOnRegression = &v +} + +// GetRandomizationUnit returns the RandomizationUnit field value if set, zero value otherwise. +func (o *ReleaseGuardianConfigurationInput) GetRandomizationUnit() string { + if o == nil || o.RandomizationUnit == nil { + var ret string + return ret + } + return *o.RandomizationUnit +} + +// GetRandomizationUnitOk returns a tuple with the RandomizationUnit field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseGuardianConfigurationInput) GetRandomizationUnitOk() (*string, bool) { + if o == nil || o.RandomizationUnit == nil { + return nil, false + } + return o.RandomizationUnit, true +} + +// HasRandomizationUnit returns a boolean if a field has been set. +func (o *ReleaseGuardianConfigurationInput) HasRandomizationUnit() bool { + if o != nil && o.RandomizationUnit != nil { + return true + } + + return false +} + +// SetRandomizationUnit gets a reference to the given string and assigns it to the RandomizationUnit field. +func (o *ReleaseGuardianConfigurationInput) SetRandomizationUnit(v string) { + o.RandomizationUnit = &v +} + +func (o ReleaseGuardianConfigurationInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.MonitoringWindowMilliseconds != nil { + toSerialize["monitoringWindowMilliseconds"] = o.MonitoringWindowMilliseconds + } + if o.RolloutWeight != nil { + toSerialize["rolloutWeight"] = o.RolloutWeight + } + if o.RollbackOnRegression != nil { + toSerialize["rollbackOnRegression"] = o.RollbackOnRegression + } + if o.RandomizationUnit != nil { + toSerialize["randomizationUnit"] = o.RandomizationUnit + } + return json.Marshal(toSerialize) +} + +type NullableReleaseGuardianConfigurationInput struct { + value *ReleaseGuardianConfigurationInput + isSet bool +} + +func (v NullableReleaseGuardianConfigurationInput) Get() *ReleaseGuardianConfigurationInput { + return v.value +} + +func (v *NullableReleaseGuardianConfigurationInput) Set(val *ReleaseGuardianConfigurationInput) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseGuardianConfigurationInput) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseGuardianConfigurationInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseGuardianConfigurationInput(val *ReleaseGuardianConfigurationInput) *NullableReleaseGuardianConfigurationInput { + return &NullableReleaseGuardianConfigurationInput{value: val, isSet: true} +} + +func (v NullableReleaseGuardianConfigurationInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseGuardianConfigurationInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_phase.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_phase.go new file mode 100644 index 00000000..1e5d64ea --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_phase.go @@ -0,0 +1,446 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleasePhase struct for ReleasePhase +type ReleasePhase struct { + // The phase ID + Id string `json:"_id"` + // The release phase name + Name string `json:"_name"` + // Whether this phase is complete + Complete bool `json:"complete"` + CreationDate int64 `json:"_creationDate"` + CompletionDate *int64 `json:"_completionDate,omitempty"` + CompletedBy *CompletedBy `json:"_completedBy,omitempty"` + // A logical grouping of one or more environments that share attributes for rolling out changes + Audiences []ReleaseAudience `json:"_audiences"` + Status *string `json:"status,omitempty"` + // Whether or not this phase has started + Started *bool `json:"started,omitempty"` + StartedDate *int64 `json:"_startedDate,omitempty"` + Configuration map[string]interface{} `json:"configuration,omitempty"` +} + +// NewReleasePhase instantiates a new ReleasePhase object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleasePhase(id string, name string, complete bool, creationDate int64, audiences []ReleaseAudience) *ReleasePhase { + this := ReleasePhase{} + this.Id = id + this.Name = name + this.Complete = complete + this.CreationDate = creationDate + this.Audiences = audiences + return &this +} + +// NewReleasePhaseWithDefaults instantiates a new ReleasePhase object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleasePhaseWithDefaults() *ReleasePhase { + this := ReleasePhase{} + return &this +} + +// GetId returns the Id field value +func (o *ReleasePhase) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ReleasePhase) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value +func (o *ReleasePhase) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ReleasePhase) SetName(v string) { + o.Name = v +} + +// GetComplete returns the Complete field value +func (o *ReleasePhase) GetComplete() bool { + if o == nil { + var ret bool + return ret + } + + return o.Complete +} + +// GetCompleteOk returns a tuple with the Complete field value +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetCompleteOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Complete, true +} + +// SetComplete sets field value +func (o *ReleasePhase) SetComplete(v bool) { + o.Complete = v +} + +// GetCreationDate returns the CreationDate field value +func (o *ReleasePhase) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *ReleasePhase) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetCompletionDate returns the CompletionDate field value if set, zero value otherwise. +func (o *ReleasePhase) GetCompletionDate() int64 { + if o == nil || o.CompletionDate == nil { + var ret int64 + return ret + } + return *o.CompletionDate +} + +// GetCompletionDateOk returns a tuple with the CompletionDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetCompletionDateOk() (*int64, bool) { + if o == nil || o.CompletionDate == nil { + return nil, false + } + return o.CompletionDate, true +} + +// HasCompletionDate returns a boolean if a field has been set. +func (o *ReleasePhase) HasCompletionDate() bool { + if o != nil && o.CompletionDate != nil { + return true + } + + return false +} + +// SetCompletionDate gets a reference to the given int64 and assigns it to the CompletionDate field. +func (o *ReleasePhase) SetCompletionDate(v int64) { + o.CompletionDate = &v +} + +// GetCompletedBy returns the CompletedBy field value if set, zero value otherwise. +func (o *ReleasePhase) GetCompletedBy() CompletedBy { + if o == nil || o.CompletedBy == nil { + var ret CompletedBy + return ret + } + return *o.CompletedBy +} + +// GetCompletedByOk returns a tuple with the CompletedBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetCompletedByOk() (*CompletedBy, bool) { + if o == nil || o.CompletedBy == nil { + return nil, false + } + return o.CompletedBy, true +} + +// HasCompletedBy returns a boolean if a field has been set. +func (o *ReleasePhase) HasCompletedBy() bool { + if o != nil && o.CompletedBy != nil { + return true + } + + return false +} + +// SetCompletedBy gets a reference to the given CompletedBy and assigns it to the CompletedBy field. +func (o *ReleasePhase) SetCompletedBy(v CompletedBy) { + o.CompletedBy = &v +} + +// GetAudiences returns the Audiences field value +func (o *ReleasePhase) GetAudiences() []ReleaseAudience { + if o == nil { + var ret []ReleaseAudience + return ret + } + + return o.Audiences +} + +// GetAudiencesOk returns a tuple with the Audiences field value +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetAudiencesOk() ([]ReleaseAudience, bool) { + if o == nil { + return nil, false + } + return o.Audiences, true +} + +// SetAudiences sets field value +func (o *ReleasePhase) SetAudiences(v []ReleaseAudience) { + o.Audiences = v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *ReleasePhase) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *ReleasePhase) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *ReleasePhase) SetStatus(v string) { + o.Status = &v +} + +// GetStarted returns the Started field value if set, zero value otherwise. +func (o *ReleasePhase) GetStarted() bool { + if o == nil || o.Started == nil { + var ret bool + return ret + } + return *o.Started +} + +// GetStartedOk returns a tuple with the Started field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetStartedOk() (*bool, bool) { + if o == nil || o.Started == nil { + return nil, false + } + return o.Started, true +} + +// HasStarted returns a boolean if a field has been set. +func (o *ReleasePhase) HasStarted() bool { + if o != nil && o.Started != nil { + return true + } + + return false +} + +// SetStarted gets a reference to the given bool and assigns it to the Started field. +func (o *ReleasePhase) SetStarted(v bool) { + o.Started = &v +} + +// GetStartedDate returns the StartedDate field value if set, zero value otherwise. +func (o *ReleasePhase) GetStartedDate() int64 { + if o == nil || o.StartedDate == nil { + var ret int64 + return ret + } + return *o.StartedDate +} + +// GetStartedDateOk returns a tuple with the StartedDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetStartedDateOk() (*int64, bool) { + if o == nil || o.StartedDate == nil { + return nil, false + } + return o.StartedDate, true +} + +// HasStartedDate returns a boolean if a field has been set. +func (o *ReleasePhase) HasStartedDate() bool { + if o != nil && o.StartedDate != nil { + return true + } + + return false +} + +// SetStartedDate gets a reference to the given int64 and assigns it to the StartedDate field. +func (o *ReleasePhase) SetStartedDate(v int64) { + o.StartedDate = &v +} + +// GetConfiguration returns the Configuration field value if set, zero value otherwise. +func (o *ReleasePhase) GetConfiguration() map[string]interface{} { + if o == nil || o.Configuration == nil { + var ret map[string]interface{} + return ret + } + return o.Configuration +} + +// GetConfigurationOk returns a tuple with the Configuration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePhase) GetConfigurationOk() (map[string]interface{}, bool) { + if o == nil || o.Configuration == nil { + return nil, false + } + return o.Configuration, true +} + +// HasConfiguration returns a boolean if a field has been set. +func (o *ReleasePhase) HasConfiguration() bool { + if o != nil && o.Configuration != nil { + return true + } + + return false +} + +// SetConfiguration gets a reference to the given map[string]interface{} and assigns it to the Configuration field. +func (o *ReleasePhase) SetConfiguration(v map[string]interface{}) { + o.Configuration = v +} + +func (o ReleasePhase) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_name"] = o.Name + } + if true { + toSerialize["complete"] = o.Complete + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if o.CompletionDate != nil { + toSerialize["_completionDate"] = o.CompletionDate + } + if o.CompletedBy != nil { + toSerialize["_completedBy"] = o.CompletedBy + } + if true { + toSerialize["_audiences"] = o.Audiences + } + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.Started != nil { + toSerialize["started"] = o.Started + } + if o.StartedDate != nil { + toSerialize["_startedDate"] = o.StartedDate + } + if o.Configuration != nil { + toSerialize["configuration"] = o.Configuration + } + return json.Marshal(toSerialize) +} + +type NullableReleasePhase struct { + value *ReleasePhase + isSet bool +} + +func (v NullableReleasePhase) Get() *ReleasePhase { + return v.value +} + +func (v *NullableReleasePhase) Set(val *ReleasePhase) { + v.value = val + v.isSet = true +} + +func (v NullableReleasePhase) IsSet() bool { + return v.isSet +} + +func (v *NullableReleasePhase) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleasePhase(val *ReleasePhase) *NullableReleasePhase { + return &NullableReleasePhase{value: val, isSet: true} +} + +func (v NullableReleasePhase) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleasePhase) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline.go new file mode 100644 index 00000000..a626ef31 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline.go @@ -0,0 +1,422 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// ReleasePipeline struct for ReleasePipeline +type ReleasePipeline struct { + // Timestamp of when the release pipeline was created + CreatedAt time.Time `json:"createdAt"` + // The release pipeline description + Description *string `json:"description,omitempty"` + // The release pipeline key + Key string `json:"key"` + // The release pipeline name + Name string `json:"name"` + // An ordered list of the release pipeline phases. Each phase is a logical grouping of one or more environments that share attributes for rolling out changes. + Phases []Phase `json:"phases"` + // A list of the release pipeline's tags + Tags []string `json:"tags,omitempty"` + // The release pipeline version + Version *int32 `json:"_version,omitempty"` + Access *Access `json:"_access,omitempty"` + // Whether this release pipeline is the default pipeline for the project + IsProjectDefault *bool `json:"isProjectDefault,omitempty"` + // Whether this release pipeline is a legacy pipeline + IsLegacy *bool `json:"_isLegacy,omitempty"` +} + +// NewReleasePipeline instantiates a new ReleasePipeline object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleasePipeline(createdAt time.Time, key string, name string, phases []Phase) *ReleasePipeline { + this := ReleasePipeline{} + this.CreatedAt = createdAt + this.Key = key + this.Name = name + this.Phases = phases + return &this +} + +// NewReleasePipelineWithDefaults instantiates a new ReleasePipeline object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleasePipelineWithDefaults() *ReleasePipeline { + this := ReleasePipeline{} + return &this +} + +// GetCreatedAt returns the CreatedAt field value +func (o *ReleasePipeline) GetCreatedAt() time.Time { + if o == nil { + var ret time.Time + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetCreatedAtOk() (*time.Time, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *ReleasePipeline) SetCreatedAt(v time.Time) { + o.CreatedAt = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *ReleasePipeline) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *ReleasePipeline) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *ReleasePipeline) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *ReleasePipeline) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *ReleasePipeline) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value +func (o *ReleasePipeline) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *ReleasePipeline) SetName(v string) { + o.Name = v +} + +// GetPhases returns the Phases field value +func (o *ReleasePipeline) GetPhases() []Phase { + if o == nil { + var ret []Phase + return ret + } + + return o.Phases +} + +// GetPhasesOk returns a tuple with the Phases field value +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetPhasesOk() ([]Phase, bool) { + if o == nil { + return nil, false + } + return o.Phases, true +} + +// SetPhases sets field value +func (o *ReleasePipeline) SetPhases(v []Phase) { + o.Phases = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *ReleasePipeline) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *ReleasePipeline) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *ReleasePipeline) SetTags(v []string) { + o.Tags = v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *ReleasePipeline) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *ReleasePipeline) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *ReleasePipeline) SetVersion(v int32) { + o.Version = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *ReleasePipeline) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *ReleasePipeline) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *ReleasePipeline) SetAccess(v Access) { + o.Access = &v +} + +// GetIsProjectDefault returns the IsProjectDefault field value if set, zero value otherwise. +func (o *ReleasePipeline) GetIsProjectDefault() bool { + if o == nil || o.IsProjectDefault == nil { + var ret bool + return ret + } + return *o.IsProjectDefault +} + +// GetIsProjectDefaultOk returns a tuple with the IsProjectDefault field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetIsProjectDefaultOk() (*bool, bool) { + if o == nil || o.IsProjectDefault == nil { + return nil, false + } + return o.IsProjectDefault, true +} + +// HasIsProjectDefault returns a boolean if a field has been set. +func (o *ReleasePipeline) HasIsProjectDefault() bool { + if o != nil && o.IsProjectDefault != nil { + return true + } + + return false +} + +// SetIsProjectDefault gets a reference to the given bool and assigns it to the IsProjectDefault field. +func (o *ReleasePipeline) SetIsProjectDefault(v bool) { + o.IsProjectDefault = &v +} + +// GetIsLegacy returns the IsLegacy field value if set, zero value otherwise. +func (o *ReleasePipeline) GetIsLegacy() bool { + if o == nil || o.IsLegacy == nil { + var ret bool + return ret + } + return *o.IsLegacy +} + +// GetIsLegacyOk returns a tuple with the IsLegacy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleasePipeline) GetIsLegacyOk() (*bool, bool) { + if o == nil || o.IsLegacy == nil { + return nil, false + } + return o.IsLegacy, true +} + +// HasIsLegacy returns a boolean if a field has been set. +func (o *ReleasePipeline) HasIsLegacy() bool { + if o != nil && o.IsLegacy != nil { + return true + } + + return false +} + +// SetIsLegacy gets a reference to the given bool and assigns it to the IsLegacy field. +func (o *ReleasePipeline) SetIsLegacy(v bool) { + o.IsLegacy = &v +} + +func (o ReleasePipeline) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["phases"] = o.Phases + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.IsProjectDefault != nil { + toSerialize["isProjectDefault"] = o.IsProjectDefault + } + if o.IsLegacy != nil { + toSerialize["_isLegacy"] = o.IsLegacy + } + return json.Marshal(toSerialize) +} + +type NullableReleasePipeline struct { + value *ReleasePipeline + isSet bool +} + +func (v NullableReleasePipeline) Get() *ReleasePipeline { + return v.value +} + +func (v *NullableReleasePipeline) Set(val *ReleasePipeline) { + v.value = val + v.isSet = true +} + +func (v NullableReleasePipeline) IsSet() bool { + return v.isSet +} + +func (v *NullableReleasePipeline) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleasePipeline(val *ReleasePipeline) *NullableReleasePipeline { + return &NullableReleasePipeline{value: val, isSet: true} +} + +func (v NullableReleasePipeline) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleasePipeline) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline_collection.go new file mode 100644 index 00000000..893ca12f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_pipeline_collection.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleasePipelineCollection struct for ReleasePipelineCollection +type ReleasePipelineCollection struct { + // An array of release pipelines + Items []ReleasePipeline `json:"items"` + // Total number of release pipelines + TotalCount int32 `json:"totalCount"` +} + +// NewReleasePipelineCollection instantiates a new ReleasePipelineCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleasePipelineCollection(items []ReleasePipeline, totalCount int32) *ReleasePipelineCollection { + this := ReleasePipelineCollection{} + this.Items = items + this.TotalCount = totalCount + return &this +} + +// NewReleasePipelineCollectionWithDefaults instantiates a new ReleasePipelineCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleasePipelineCollectionWithDefaults() *ReleasePipelineCollection { + this := ReleasePipelineCollection{} + return &this +} + +// GetItems returns the Items field value +func (o *ReleasePipelineCollection) GetItems() []ReleasePipeline { + if o == nil { + var ret []ReleasePipeline + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ReleasePipelineCollection) GetItemsOk() ([]ReleasePipeline, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ReleasePipelineCollection) SetItems(v []ReleasePipeline) { + o.Items = v +} + +// GetTotalCount returns the TotalCount field value +func (o *ReleasePipelineCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *ReleasePipelineCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *ReleasePipelineCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +func (o ReleasePipelineCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableReleasePipelineCollection struct { + value *ReleasePipelineCollection + isSet bool +} + +func (v NullableReleasePipelineCollection) Get() *ReleasePipelineCollection { + return v.value +} + +func (v *NullableReleasePipelineCollection) Set(val *ReleasePipelineCollection) { + v.value = val + v.isSet = true +} + +func (v NullableReleasePipelineCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableReleasePipelineCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleasePipelineCollection(val *ReleasePipelineCollection) *NullableReleasePipelineCollection { + return &NullableReleasePipelineCollection{value: val, isSet: true} +} + +func (v NullableReleasePipelineCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleasePipelineCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression.go new file mode 100644 index 00000000..6149d67a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression.go @@ -0,0 +1,242 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaseProgression struct for ReleaseProgression +type ReleaseProgression struct { + CreatedAt int64 `json:"_createdAt"` + CompletedAt *int64 `json:"_completedAt,omitempty"` + // The flag key + FlagKey string `json:"flagKey"` + // The ID of the currently active release phase + ActivePhaseId *string `json:"activePhaseId,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewReleaseProgression instantiates a new ReleaseProgression object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseProgression(createdAt int64, flagKey string, links map[string]Link) *ReleaseProgression { + this := ReleaseProgression{} + this.CreatedAt = createdAt + this.FlagKey = flagKey + this.Links = links + return &this +} + +// NewReleaseProgressionWithDefaults instantiates a new ReleaseProgression object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseProgressionWithDefaults() *ReleaseProgression { + this := ReleaseProgression{} + return &this +} + +// GetCreatedAt returns the CreatedAt field value +func (o *ReleaseProgression) GetCreatedAt() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgression) GetCreatedAtOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *ReleaseProgression) SetCreatedAt(v int64) { + o.CreatedAt = v +} + +// GetCompletedAt returns the CompletedAt field value if set, zero value otherwise. +func (o *ReleaseProgression) GetCompletedAt() int64 { + if o == nil || o.CompletedAt == nil { + var ret int64 + return ret + } + return *o.CompletedAt +} + +// GetCompletedAtOk returns a tuple with the CompletedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseProgression) GetCompletedAtOk() (*int64, bool) { + if o == nil || o.CompletedAt == nil { + return nil, false + } + return o.CompletedAt, true +} + +// HasCompletedAt returns a boolean if a field has been set. +func (o *ReleaseProgression) HasCompletedAt() bool { + if o != nil && o.CompletedAt != nil { + return true + } + + return false +} + +// SetCompletedAt gets a reference to the given int64 and assigns it to the CompletedAt field. +func (o *ReleaseProgression) SetCompletedAt(v int64) { + o.CompletedAt = &v +} + +// GetFlagKey returns the FlagKey field value +func (o *ReleaseProgression) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgression) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *ReleaseProgression) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetActivePhaseId returns the ActivePhaseId field value if set, zero value otherwise. +func (o *ReleaseProgression) GetActivePhaseId() string { + if o == nil || o.ActivePhaseId == nil { + var ret string + return ret + } + return *o.ActivePhaseId +} + +// GetActivePhaseIdOk returns a tuple with the ActivePhaseId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseProgression) GetActivePhaseIdOk() (*string, bool) { + if o == nil || o.ActivePhaseId == nil { + return nil, false + } + return o.ActivePhaseId, true +} + +// HasActivePhaseId returns a boolean if a field has been set. +func (o *ReleaseProgression) HasActivePhaseId() bool { + if o != nil && o.ActivePhaseId != nil { + return true + } + + return false +} + +// SetActivePhaseId gets a reference to the given string and assigns it to the ActivePhaseId field. +func (o *ReleaseProgression) SetActivePhaseId(v string) { + o.ActivePhaseId = &v +} + +// GetLinks returns the Links field value +func (o *ReleaseProgression) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgression) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ReleaseProgression) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ReleaseProgression) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_createdAt"] = o.CreatedAt + } + if o.CompletedAt != nil { + toSerialize["_completedAt"] = o.CompletedAt + } + if true { + toSerialize["flagKey"] = o.FlagKey + } + if o.ActivePhaseId != nil { + toSerialize["activePhaseId"] = o.ActivePhaseId + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableReleaseProgression struct { + value *ReleaseProgression + isSet bool +} + +func (v NullableReleaseProgression) Get() *ReleaseProgression { + return v.value +} + +func (v *NullableReleaseProgression) Set(val *ReleaseProgression) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseProgression) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseProgression) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseProgression(val *ReleaseProgression) *NullableReleaseProgression { + return &NullableReleaseProgression{value: val, isSet: true} +} + +func (v NullableReleaseProgression) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseProgression) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression_collection.go new file mode 100644 index 00000000..be73bd30 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_release_progression_collection.go @@ -0,0 +1,260 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaseProgressionCollection struct for ReleaseProgressionCollection +type ReleaseProgressionCollection struct { + // The number of active releases + ActiveCount int32 `json:"activeCount"` + // The number of completed releases + CompletedCount int32 `json:"completedCount"` + // A list of details for each release, across all flags, for this release pipeline + Items []ReleaseProgression `json:"items"` + // A list of details for each phase, across all releases, for this release pipeline + Phases []PhaseInfo `json:"phases"` + // The total number of releases for this release pipeline + TotalCount int32 `json:"totalCount"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewReleaseProgressionCollection instantiates a new ReleaseProgressionCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseProgressionCollection(activeCount int32, completedCount int32, items []ReleaseProgression, phases []PhaseInfo, totalCount int32, links map[string]Link) *ReleaseProgressionCollection { + this := ReleaseProgressionCollection{} + this.ActiveCount = activeCount + this.CompletedCount = completedCount + this.Items = items + this.Phases = phases + this.TotalCount = totalCount + this.Links = links + return &this +} + +// NewReleaseProgressionCollectionWithDefaults instantiates a new ReleaseProgressionCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseProgressionCollectionWithDefaults() *ReleaseProgressionCollection { + this := ReleaseProgressionCollection{} + return &this +} + +// GetActiveCount returns the ActiveCount field value +func (o *ReleaseProgressionCollection) GetActiveCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ActiveCount +} + +// GetActiveCountOk returns a tuple with the ActiveCount field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetActiveCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ActiveCount, true +} + +// SetActiveCount sets field value +func (o *ReleaseProgressionCollection) SetActiveCount(v int32) { + o.ActiveCount = v +} + +// GetCompletedCount returns the CompletedCount field value +func (o *ReleaseProgressionCollection) GetCompletedCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.CompletedCount +} + +// GetCompletedCountOk returns a tuple with the CompletedCount field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetCompletedCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.CompletedCount, true +} + +// SetCompletedCount sets field value +func (o *ReleaseProgressionCollection) SetCompletedCount(v int32) { + o.CompletedCount = v +} + +// GetItems returns the Items field value +func (o *ReleaseProgressionCollection) GetItems() []ReleaseProgression { + if o == nil { + var ret []ReleaseProgression + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetItemsOk() ([]ReleaseProgression, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *ReleaseProgressionCollection) SetItems(v []ReleaseProgression) { + o.Items = v +} + +// GetPhases returns the Phases field value +func (o *ReleaseProgressionCollection) GetPhases() []PhaseInfo { + if o == nil { + var ret []PhaseInfo + return ret + } + + return o.Phases +} + +// GetPhasesOk returns a tuple with the Phases field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetPhasesOk() ([]PhaseInfo, bool) { + if o == nil { + return nil, false + } + return o.Phases, true +} + +// SetPhases sets field value +func (o *ReleaseProgressionCollection) SetPhases(v []PhaseInfo) { + o.Phases = v +} + +// GetTotalCount returns the TotalCount field value +func (o *ReleaseProgressionCollection) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *ReleaseProgressionCollection) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetLinks returns the Links field value +func (o *ReleaseProgressionCollection) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *ReleaseProgressionCollection) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *ReleaseProgressionCollection) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o ReleaseProgressionCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["activeCount"] = o.ActiveCount + } + if true { + toSerialize["completedCount"] = o.CompletedCount + } + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["phases"] = o.Phases + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableReleaseProgressionCollection struct { + value *ReleaseProgressionCollection + isSet bool +} + +func (v NullableReleaseProgressionCollection) Get() *ReleaseProgressionCollection { + return v.value +} + +func (v *NullableReleaseProgressionCollection) Set(val *ReleaseProgressionCollection) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseProgressionCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseProgressionCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseProgressionCollection(val *ReleaseProgressionCollection) *NullableReleaseProgressionCollection { + return &NullableReleaseProgressionCollection{value: val, isSet: true} +} + +func (v NullableReleaseProgressionCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseProgressionCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_releaser_audience_config_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_releaser_audience_config_input.go new file mode 100644 index 00000000..a7c09d06 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_releaser_audience_config_input.go @@ -0,0 +1,227 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReleaserAudienceConfigInput struct for ReleaserAudienceConfigInput +type ReleaserAudienceConfigInput struct { + // UUID of the audience. + AudienceId *string `json:"audienceId,omitempty"` + ReleaseGuardianConfiguration *ReleaseGuardianConfigurationInput `json:"releaseGuardianConfiguration,omitempty"` + // An array of member IDs. These members are notified to review the approval request. + NotifyMemberIds []string `json:"notifyMemberIds,omitempty"` + // An array of team keys. The members of these teams are notified to review the approval request. + NotifyTeamKeys []string `json:"notifyTeamKeys,omitempty"` +} + +// NewReleaserAudienceConfigInput instantiates a new ReleaserAudienceConfigInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaserAudienceConfigInput() *ReleaserAudienceConfigInput { + this := ReleaserAudienceConfigInput{} + return &this +} + +// NewReleaserAudienceConfigInputWithDefaults instantiates a new ReleaserAudienceConfigInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaserAudienceConfigInputWithDefaults() *ReleaserAudienceConfigInput { + this := ReleaserAudienceConfigInput{} + return &this +} + +// GetAudienceId returns the AudienceId field value if set, zero value otherwise. +func (o *ReleaserAudienceConfigInput) GetAudienceId() string { + if o == nil || o.AudienceId == nil { + var ret string + return ret + } + return *o.AudienceId +} + +// GetAudienceIdOk returns a tuple with the AudienceId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaserAudienceConfigInput) GetAudienceIdOk() (*string, bool) { + if o == nil || o.AudienceId == nil { + return nil, false + } + return o.AudienceId, true +} + +// HasAudienceId returns a boolean if a field has been set. +func (o *ReleaserAudienceConfigInput) HasAudienceId() bool { + if o != nil && o.AudienceId != nil { + return true + } + + return false +} + +// SetAudienceId gets a reference to the given string and assigns it to the AudienceId field. +func (o *ReleaserAudienceConfigInput) SetAudienceId(v string) { + o.AudienceId = &v +} + +// GetReleaseGuardianConfiguration returns the ReleaseGuardianConfiguration field value if set, zero value otherwise. +func (o *ReleaserAudienceConfigInput) GetReleaseGuardianConfiguration() ReleaseGuardianConfigurationInput { + if o == nil || o.ReleaseGuardianConfiguration == nil { + var ret ReleaseGuardianConfigurationInput + return ret + } + return *o.ReleaseGuardianConfiguration +} + +// GetReleaseGuardianConfigurationOk returns a tuple with the ReleaseGuardianConfiguration field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaserAudienceConfigInput) GetReleaseGuardianConfigurationOk() (*ReleaseGuardianConfigurationInput, bool) { + if o == nil || o.ReleaseGuardianConfiguration == nil { + return nil, false + } + return o.ReleaseGuardianConfiguration, true +} + +// HasReleaseGuardianConfiguration returns a boolean if a field has been set. +func (o *ReleaserAudienceConfigInput) HasReleaseGuardianConfiguration() bool { + if o != nil && o.ReleaseGuardianConfiguration != nil { + return true + } + + return false +} + +// SetReleaseGuardianConfiguration gets a reference to the given ReleaseGuardianConfigurationInput and assigns it to the ReleaseGuardianConfiguration field. +func (o *ReleaserAudienceConfigInput) SetReleaseGuardianConfiguration(v ReleaseGuardianConfigurationInput) { + o.ReleaseGuardianConfiguration = &v +} + +// GetNotifyMemberIds returns the NotifyMemberIds field value if set, zero value otherwise. +func (o *ReleaserAudienceConfigInput) GetNotifyMemberIds() []string { + if o == nil || o.NotifyMemberIds == nil { + var ret []string + return ret + } + return o.NotifyMemberIds +} + +// GetNotifyMemberIdsOk returns a tuple with the NotifyMemberIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaserAudienceConfigInput) GetNotifyMemberIdsOk() ([]string, bool) { + if o == nil || o.NotifyMemberIds == nil { + return nil, false + } + return o.NotifyMemberIds, true +} + +// HasNotifyMemberIds returns a boolean if a field has been set. +func (o *ReleaserAudienceConfigInput) HasNotifyMemberIds() bool { + if o != nil && o.NotifyMemberIds != nil { + return true + } + + return false +} + +// SetNotifyMemberIds gets a reference to the given []string and assigns it to the NotifyMemberIds field. +func (o *ReleaserAudienceConfigInput) SetNotifyMemberIds(v []string) { + o.NotifyMemberIds = v +} + +// GetNotifyTeamKeys returns the NotifyTeamKeys field value if set, zero value otherwise. +func (o *ReleaserAudienceConfigInput) GetNotifyTeamKeys() []string { + if o == nil || o.NotifyTeamKeys == nil { + var ret []string + return ret + } + return o.NotifyTeamKeys +} + +// GetNotifyTeamKeysOk returns a tuple with the NotifyTeamKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaserAudienceConfigInput) GetNotifyTeamKeysOk() ([]string, bool) { + if o == nil || o.NotifyTeamKeys == nil { + return nil, false + } + return o.NotifyTeamKeys, true +} + +// HasNotifyTeamKeys returns a boolean if a field has been set. +func (o *ReleaserAudienceConfigInput) HasNotifyTeamKeys() bool { + if o != nil && o.NotifyTeamKeys != nil { + return true + } + + return false +} + +// SetNotifyTeamKeys gets a reference to the given []string and assigns it to the NotifyTeamKeys field. +func (o *ReleaserAudienceConfigInput) SetNotifyTeamKeys(v []string) { + o.NotifyTeamKeys = v +} + +func (o ReleaserAudienceConfigInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.AudienceId != nil { + toSerialize["audienceId"] = o.AudienceId + } + if o.ReleaseGuardianConfiguration != nil { + toSerialize["releaseGuardianConfiguration"] = o.ReleaseGuardianConfiguration + } + if o.NotifyMemberIds != nil { + toSerialize["notifyMemberIds"] = o.NotifyMemberIds + } + if o.NotifyTeamKeys != nil { + toSerialize["notifyTeamKeys"] = o.NotifyTeamKeys + } + return json.Marshal(toSerialize) +} + +type NullableReleaserAudienceConfigInput struct { + value *ReleaserAudienceConfigInput + isSet bool +} + +func (v NullableReleaserAudienceConfigInput) Get() *ReleaserAudienceConfigInput { + return v.value +} + +func (v *NullableReleaserAudienceConfigInput) Set(val *ReleaserAudienceConfigInput) { + v.value = val + v.isSet = true +} + +func (v NullableReleaserAudienceConfigInput) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaserAudienceConfigInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaserAudienceConfigInput(val *ReleaserAudienceConfigInput) *NullableReleaserAudienceConfigInput { + return &NullableReleaserAudienceConfigInput{value: val, isSet: true} +} + +func (v NullableReleaserAudienceConfigInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaserAudienceConfigInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_collection_rep.go new file mode 100644 index 00000000..2e6031af --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_collection_rep.go @@ -0,0 +1,139 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RepositoryCollectionRep struct for RepositoryCollectionRep +type RepositoryCollectionRep struct { + Links map[string]Link `json:"_links"` + // An array of repositories + Items []RepositoryRep `json:"items"` +} + +// NewRepositoryCollectionRep instantiates a new RepositoryCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRepositoryCollectionRep(links map[string]Link, items []RepositoryRep) *RepositoryCollectionRep { + this := RepositoryCollectionRep{} + this.Links = links + this.Items = items + return &this +} + +// NewRepositoryCollectionRepWithDefaults instantiates a new RepositoryCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRepositoryCollectionRepWithDefaults() *RepositoryCollectionRep { + this := RepositoryCollectionRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *RepositoryCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *RepositoryCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *RepositoryCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *RepositoryCollectionRep) GetItems() []RepositoryRep { + if o == nil { + var ret []RepositoryRep + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *RepositoryCollectionRep) GetItemsOk() ([]RepositoryRep, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *RepositoryCollectionRep) SetItems(v []RepositoryRep) { + o.Items = v +} + +func (o RepositoryCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableRepositoryCollectionRep struct { + value *RepositoryCollectionRep + isSet bool +} + +func (v NullableRepositoryCollectionRep) Get() *RepositoryCollectionRep { + return v.value +} + +func (v *NullableRepositoryCollectionRep) Set(val *RepositoryCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableRepositoryCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRepositoryCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRepositoryCollectionRep(val *RepositoryCollectionRep) *NullableRepositoryCollectionRep { + return &NullableRepositoryCollectionRep{value: val, isSet: true} +} + +func (v NullableRepositoryCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRepositoryCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_post.go new file mode 100644 index 00000000..12db4523 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_post.go @@ -0,0 +1,295 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RepositoryPost struct for RepositoryPost +type RepositoryPost struct { + // The repository name + Name string `json:"name"` + // A URL to access the repository + SourceLink *string `json:"sourceLink,omitempty"` + // A template for constructing a valid URL to view the commit + CommitUrlTemplate *string `json:"commitUrlTemplate,omitempty"` + // A template for constructing a valid URL to view the hunk + HunkUrlTemplate *string `json:"hunkUrlTemplate,omitempty"` + // The type of repository. If not specified, the default value is custom. + Type *string `json:"type,omitempty"` + // The repository's default branch. If not specified, the default value is main. + DefaultBranch *string `json:"defaultBranch,omitempty"` +} + +// NewRepositoryPost instantiates a new RepositoryPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRepositoryPost(name string) *RepositoryPost { + this := RepositoryPost{} + this.Name = name + return &this +} + +// NewRepositoryPostWithDefaults instantiates a new RepositoryPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRepositoryPostWithDefaults() *RepositoryPost { + this := RepositoryPost{} + return &this +} + +// GetName returns the Name field value +func (o *RepositoryPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *RepositoryPost) SetName(v string) { + o.Name = v +} + +// GetSourceLink returns the SourceLink field value if set, zero value otherwise. +func (o *RepositoryPost) GetSourceLink() string { + if o == nil || o.SourceLink == nil { + var ret string + return ret + } + return *o.SourceLink +} + +// GetSourceLinkOk returns a tuple with the SourceLink field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetSourceLinkOk() (*string, bool) { + if o == nil || o.SourceLink == nil { + return nil, false + } + return o.SourceLink, true +} + +// HasSourceLink returns a boolean if a field has been set. +func (o *RepositoryPost) HasSourceLink() bool { + if o != nil && o.SourceLink != nil { + return true + } + + return false +} + +// SetSourceLink gets a reference to the given string and assigns it to the SourceLink field. +func (o *RepositoryPost) SetSourceLink(v string) { + o.SourceLink = &v +} + +// GetCommitUrlTemplate returns the CommitUrlTemplate field value if set, zero value otherwise. +func (o *RepositoryPost) GetCommitUrlTemplate() string { + if o == nil || o.CommitUrlTemplate == nil { + var ret string + return ret + } + return *o.CommitUrlTemplate +} + +// GetCommitUrlTemplateOk returns a tuple with the CommitUrlTemplate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetCommitUrlTemplateOk() (*string, bool) { + if o == nil || o.CommitUrlTemplate == nil { + return nil, false + } + return o.CommitUrlTemplate, true +} + +// HasCommitUrlTemplate returns a boolean if a field has been set. +func (o *RepositoryPost) HasCommitUrlTemplate() bool { + if o != nil && o.CommitUrlTemplate != nil { + return true + } + + return false +} + +// SetCommitUrlTemplate gets a reference to the given string and assigns it to the CommitUrlTemplate field. +func (o *RepositoryPost) SetCommitUrlTemplate(v string) { + o.CommitUrlTemplate = &v +} + +// GetHunkUrlTemplate returns the HunkUrlTemplate field value if set, zero value otherwise. +func (o *RepositoryPost) GetHunkUrlTemplate() string { + if o == nil || o.HunkUrlTemplate == nil { + var ret string + return ret + } + return *o.HunkUrlTemplate +} + +// GetHunkUrlTemplateOk returns a tuple with the HunkUrlTemplate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetHunkUrlTemplateOk() (*string, bool) { + if o == nil || o.HunkUrlTemplate == nil { + return nil, false + } + return o.HunkUrlTemplate, true +} + +// HasHunkUrlTemplate returns a boolean if a field has been set. +func (o *RepositoryPost) HasHunkUrlTemplate() bool { + if o != nil && o.HunkUrlTemplate != nil { + return true + } + + return false +} + +// SetHunkUrlTemplate gets a reference to the given string and assigns it to the HunkUrlTemplate field. +func (o *RepositoryPost) SetHunkUrlTemplate(v string) { + o.HunkUrlTemplate = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *RepositoryPost) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *RepositoryPost) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *RepositoryPost) SetType(v string) { + o.Type = &v +} + +// GetDefaultBranch returns the DefaultBranch field value if set, zero value otherwise. +func (o *RepositoryPost) GetDefaultBranch() string { + if o == nil || o.DefaultBranch == nil { + var ret string + return ret + } + return *o.DefaultBranch +} + +// GetDefaultBranchOk returns a tuple with the DefaultBranch field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryPost) GetDefaultBranchOk() (*string, bool) { + if o == nil || o.DefaultBranch == nil { + return nil, false + } + return o.DefaultBranch, true +} + +// HasDefaultBranch returns a boolean if a field has been set. +func (o *RepositoryPost) HasDefaultBranch() bool { + if o != nil && o.DefaultBranch != nil { + return true + } + + return false +} + +// SetDefaultBranch gets a reference to the given string and assigns it to the DefaultBranch field. +func (o *RepositoryPost) SetDefaultBranch(v string) { + o.DefaultBranch = &v +} + +func (o RepositoryPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.SourceLink != nil { + toSerialize["sourceLink"] = o.SourceLink + } + if o.CommitUrlTemplate != nil { + toSerialize["commitUrlTemplate"] = o.CommitUrlTemplate + } + if o.HunkUrlTemplate != nil { + toSerialize["hunkUrlTemplate"] = o.HunkUrlTemplate + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + if o.DefaultBranch != nil { + toSerialize["defaultBranch"] = o.DefaultBranch + } + return json.Marshal(toSerialize) +} + +type NullableRepositoryPost struct { + value *RepositoryPost + isSet bool +} + +func (v NullableRepositoryPost) Get() *RepositoryPost { + return v.value +} + +func (v *NullableRepositoryPost) Set(val *RepositoryPost) { + v.value = val + v.isSet = true +} + +func (v NullableRepositoryPost) IsSet() bool { + return v.isSet +} + +func (v *NullableRepositoryPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRepositoryPost(val *RepositoryPost) *NullableRepositoryPost { + return &NullableRepositoryPost{value: val, isSet: true} +} + +func (v NullableRepositoryPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRepositoryPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_rep.go new file mode 100644 index 00000000..2da9bf4c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_repository_rep.go @@ -0,0 +1,443 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RepositoryRep struct for RepositoryRep +type RepositoryRep struct { + // The repository name + Name string `json:"name"` + // A URL to access the repository + SourceLink *string `json:"sourceLink,omitempty"` + // A template for constructing a valid URL to view the commit + CommitUrlTemplate *string `json:"commitUrlTemplate,omitempty"` + // A template for constructing a valid URL to view the hunk + HunkUrlTemplate *string `json:"hunkUrlTemplate,omitempty"` + // The type of repository + Type string `json:"type"` + // The repository's default branch + DefaultBranch string `json:"defaultBranch"` + // Whether or not a repository is enabled for code reference scanning + Enabled bool `json:"enabled"` + // The version of the repository's saved information + Version int32 `json:"version"` + // An array of the repository's branches that have been scanned for code references + Branches []BranchRep `json:"branches,omitempty"` + Links map[string]interface{} `json:"_links"` + Access *Access `json:"_access,omitempty"` +} + +// NewRepositoryRep instantiates a new RepositoryRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRepositoryRep(name string, type_ string, defaultBranch string, enabled bool, version int32, links map[string]interface{}) *RepositoryRep { + this := RepositoryRep{} + this.Name = name + this.Type = type_ + this.DefaultBranch = defaultBranch + this.Enabled = enabled + this.Version = version + this.Links = links + return &this +} + +// NewRepositoryRepWithDefaults instantiates a new RepositoryRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRepositoryRepWithDefaults() *RepositoryRep { + this := RepositoryRep{} + return &this +} + +// GetName returns the Name field value +func (o *RepositoryRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *RepositoryRep) SetName(v string) { + o.Name = v +} + +// GetSourceLink returns the SourceLink field value if set, zero value otherwise. +func (o *RepositoryRep) GetSourceLink() string { + if o == nil || o.SourceLink == nil { + var ret string + return ret + } + return *o.SourceLink +} + +// GetSourceLinkOk returns a tuple with the SourceLink field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetSourceLinkOk() (*string, bool) { + if o == nil || o.SourceLink == nil { + return nil, false + } + return o.SourceLink, true +} + +// HasSourceLink returns a boolean if a field has been set. +func (o *RepositoryRep) HasSourceLink() bool { + if o != nil && o.SourceLink != nil { + return true + } + + return false +} + +// SetSourceLink gets a reference to the given string and assigns it to the SourceLink field. +func (o *RepositoryRep) SetSourceLink(v string) { + o.SourceLink = &v +} + +// GetCommitUrlTemplate returns the CommitUrlTemplate field value if set, zero value otherwise. +func (o *RepositoryRep) GetCommitUrlTemplate() string { + if o == nil || o.CommitUrlTemplate == nil { + var ret string + return ret + } + return *o.CommitUrlTemplate +} + +// GetCommitUrlTemplateOk returns a tuple with the CommitUrlTemplate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetCommitUrlTemplateOk() (*string, bool) { + if o == nil || o.CommitUrlTemplate == nil { + return nil, false + } + return o.CommitUrlTemplate, true +} + +// HasCommitUrlTemplate returns a boolean if a field has been set. +func (o *RepositoryRep) HasCommitUrlTemplate() bool { + if o != nil && o.CommitUrlTemplate != nil { + return true + } + + return false +} + +// SetCommitUrlTemplate gets a reference to the given string and assigns it to the CommitUrlTemplate field. +func (o *RepositoryRep) SetCommitUrlTemplate(v string) { + o.CommitUrlTemplate = &v +} + +// GetHunkUrlTemplate returns the HunkUrlTemplate field value if set, zero value otherwise. +func (o *RepositoryRep) GetHunkUrlTemplate() string { + if o == nil || o.HunkUrlTemplate == nil { + var ret string + return ret + } + return *o.HunkUrlTemplate +} + +// GetHunkUrlTemplateOk returns a tuple with the HunkUrlTemplate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetHunkUrlTemplateOk() (*string, bool) { + if o == nil || o.HunkUrlTemplate == nil { + return nil, false + } + return o.HunkUrlTemplate, true +} + +// HasHunkUrlTemplate returns a boolean if a field has been set. +func (o *RepositoryRep) HasHunkUrlTemplate() bool { + if o != nil && o.HunkUrlTemplate != nil { + return true + } + + return false +} + +// SetHunkUrlTemplate gets a reference to the given string and assigns it to the HunkUrlTemplate field. +func (o *RepositoryRep) SetHunkUrlTemplate(v string) { + o.HunkUrlTemplate = &v +} + +// GetType returns the Type field value +func (o *RepositoryRep) GetType() string { + if o == nil { + var ret string + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *RepositoryRep) SetType(v string) { + o.Type = v +} + +// GetDefaultBranch returns the DefaultBranch field value +func (o *RepositoryRep) GetDefaultBranch() string { + if o == nil { + var ret string + return ret + } + + return o.DefaultBranch +} + +// GetDefaultBranchOk returns a tuple with the DefaultBranch field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetDefaultBranchOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.DefaultBranch, true +} + +// SetDefaultBranch sets field value +func (o *RepositoryRep) SetDefaultBranch(v string) { + o.DefaultBranch = v +} + +// GetEnabled returns the Enabled field value +func (o *RepositoryRep) GetEnabled() bool { + if o == nil { + var ret bool + return ret + } + + return o.Enabled +} + +// GetEnabledOk returns a tuple with the Enabled field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetEnabledOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Enabled, true +} + +// SetEnabled sets field value +func (o *RepositoryRep) SetEnabled(v bool) { + o.Enabled = v +} + +// GetVersion returns the Version field value +func (o *RepositoryRep) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *RepositoryRep) SetVersion(v int32) { + o.Version = v +} + +// GetBranches returns the Branches field value if set, zero value otherwise. +func (o *RepositoryRep) GetBranches() []BranchRep { + if o == nil || o.Branches == nil { + var ret []BranchRep + return ret + } + return o.Branches +} + +// GetBranchesOk returns a tuple with the Branches field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetBranchesOk() ([]BranchRep, bool) { + if o == nil || o.Branches == nil { + return nil, false + } + return o.Branches, true +} + +// HasBranches returns a boolean if a field has been set. +func (o *RepositoryRep) HasBranches() bool { + if o != nil && o.Branches != nil { + return true + } + + return false +} + +// SetBranches gets a reference to the given []BranchRep and assigns it to the Branches field. +func (o *RepositoryRep) SetBranches(v []BranchRep) { + o.Branches = v +} + +// GetLinks returns the Links field value +func (o *RepositoryRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *RepositoryRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *RepositoryRep) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RepositoryRep) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *RepositoryRep) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *RepositoryRep) SetAccess(v Access) { + o.Access = &v +} + +func (o RepositoryRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.SourceLink != nil { + toSerialize["sourceLink"] = o.SourceLink + } + if o.CommitUrlTemplate != nil { + toSerialize["commitUrlTemplate"] = o.CommitUrlTemplate + } + if o.HunkUrlTemplate != nil { + toSerialize["hunkUrlTemplate"] = o.HunkUrlTemplate + } + if true { + toSerialize["type"] = o.Type + } + if true { + toSerialize["defaultBranch"] = o.DefaultBranch + } + if true { + toSerialize["enabled"] = o.Enabled + } + if true { + toSerialize["version"] = o.Version + } + if o.Branches != nil { + toSerialize["branches"] = o.Branches + } + if true { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableRepositoryRep struct { + value *RepositoryRep + isSet bool +} + +func (v NullableRepositoryRep) Get() *RepositoryRep { + return v.value +} + +func (v *NullableRepositoryRep) Set(val *RepositoryRep) { + v.value = val + v.isSet = true +} + +func (v NullableRepositoryRep) IsSet() bool { + return v.isSet +} + +func (v *NullableRepositoryRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRepositoryRep(val *RepositoryRep) *NullableRepositoryRep { + return &NullableRepositoryRep{value: val, isSet: true} +} + +func (v NullableRepositoryRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRepositoryRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_access.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_access.go new file mode 100644 index 00000000..835328fe --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_access.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ResourceAccess struct for ResourceAccess +type ResourceAccess struct { + Action *string `json:"action,omitempty"` + Resource *string `json:"resource,omitempty"` +} + +// NewResourceAccess instantiates a new ResourceAccess object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewResourceAccess() *ResourceAccess { + this := ResourceAccess{} + return &this +} + +// NewResourceAccessWithDefaults instantiates a new ResourceAccess object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewResourceAccessWithDefaults() *ResourceAccess { + this := ResourceAccess{} + return &this +} + +// GetAction returns the Action field value if set, zero value otherwise. +func (o *ResourceAccess) GetAction() string { + if o == nil || o.Action == nil { + var ret string + return ret + } + return *o.Action +} + +// GetActionOk returns a tuple with the Action field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceAccess) GetActionOk() (*string, bool) { + if o == nil || o.Action == nil { + return nil, false + } + return o.Action, true +} + +// HasAction returns a boolean if a field has been set. +func (o *ResourceAccess) HasAction() bool { + if o != nil && o.Action != nil { + return true + } + + return false +} + +// SetAction gets a reference to the given string and assigns it to the Action field. +func (o *ResourceAccess) SetAction(v string) { + o.Action = &v +} + +// GetResource returns the Resource field value if set, zero value otherwise. +func (o *ResourceAccess) GetResource() string { + if o == nil || o.Resource == nil { + var ret string + return ret + } + return *o.Resource +} + +// GetResourceOk returns a tuple with the Resource field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceAccess) GetResourceOk() (*string, bool) { + if o == nil || o.Resource == nil { + return nil, false + } + return o.Resource, true +} + +// HasResource returns a boolean if a field has been set. +func (o *ResourceAccess) HasResource() bool { + if o != nil && o.Resource != nil { + return true + } + + return false +} + +// SetResource gets a reference to the given string and assigns it to the Resource field. +func (o *ResourceAccess) SetResource(v string) { + o.Resource = &v +} + +func (o ResourceAccess) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Action != nil { + toSerialize["action"] = o.Action + } + if o.Resource != nil { + toSerialize["resource"] = o.Resource + } + return json.Marshal(toSerialize) +} + +type NullableResourceAccess struct { + value *ResourceAccess + isSet bool +} + +func (v NullableResourceAccess) Get() *ResourceAccess { + return v.value +} + +func (v *NullableResourceAccess) Set(val *ResourceAccess) { + v.value = val + v.isSet = true +} + +func (v NullableResourceAccess) IsSet() bool { + return v.isSet +} + +func (v *NullableResourceAccess) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableResourceAccess(val *ResourceAccess) *NullableResourceAccess { + return &NullableResourceAccess{value: val, isSet: true} +} + +func (v NullableResourceAccess) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableResourceAccess) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id.go new file mode 100644 index 00000000..d8a6ee55 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id.go @@ -0,0 +1,268 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ResourceId struct for ResourceId +type ResourceId struct { + // The environment key + EnvironmentKey *string `json:"environmentKey,omitempty"` + // Deprecated, use key instead + // Deprecated + FlagKey *string `json:"flagKey,omitempty"` + // The key of the flag or segment + Key *string `json:"key,omitempty"` + Kind *string `json:"kind,omitempty"` + // The project key + ProjectKey *string `json:"projectKey,omitempty"` +} + +// NewResourceId instantiates a new ResourceId object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewResourceId() *ResourceId { + this := ResourceId{} + return &this +} + +// NewResourceIdWithDefaults instantiates a new ResourceId object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewResourceIdWithDefaults() *ResourceId { + this := ResourceId{} + return &this +} + +// GetEnvironmentKey returns the EnvironmentKey field value if set, zero value otherwise. +func (o *ResourceId) GetEnvironmentKey() string { + if o == nil || o.EnvironmentKey == nil { + var ret string + return ret + } + return *o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceId) GetEnvironmentKeyOk() (*string, bool) { + if o == nil || o.EnvironmentKey == nil { + return nil, false + } + return o.EnvironmentKey, true +} + +// HasEnvironmentKey returns a boolean if a field has been set. +func (o *ResourceId) HasEnvironmentKey() bool { + if o != nil && o.EnvironmentKey != nil { + return true + } + + return false +} + +// SetEnvironmentKey gets a reference to the given string and assigns it to the EnvironmentKey field. +func (o *ResourceId) SetEnvironmentKey(v string) { + o.EnvironmentKey = &v +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +// Deprecated +func (o *ResourceId) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +// Deprecated +func (o *ResourceId) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *ResourceId) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +// Deprecated +func (o *ResourceId) SetFlagKey(v string) { + o.FlagKey = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *ResourceId) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceId) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *ResourceId) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *ResourceId) SetKey(v string) { + o.Key = &v +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *ResourceId) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceId) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *ResourceId) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *ResourceId) SetKind(v string) { + o.Kind = &v +} + +// GetProjectKey returns the ProjectKey field value if set, zero value otherwise. +func (o *ResourceId) GetProjectKey() string { + if o == nil || o.ProjectKey == nil { + var ret string + return ret + } + return *o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceId) GetProjectKeyOk() (*string, bool) { + if o == nil || o.ProjectKey == nil { + return nil, false + } + return o.ProjectKey, true +} + +// HasProjectKey returns a boolean if a field has been set. +func (o *ResourceId) HasProjectKey() bool { + if o != nil && o.ProjectKey != nil { + return true + } + + return false +} + +// SetProjectKey gets a reference to the given string and assigns it to the ProjectKey field. +func (o *ResourceId) SetProjectKey(v string) { + o.ProjectKey = &v +} + +func (o ResourceId) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.EnvironmentKey != nil { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.ProjectKey != nil { + toSerialize["projectKey"] = o.ProjectKey + } + return json.Marshal(toSerialize) +} + +type NullableResourceId struct { + value *ResourceId + isSet bool +} + +func (v NullableResourceId) Get() *ResourceId { + return v.value +} + +func (v *NullableResourceId) Set(val *ResourceId) { + v.value = val + v.isSet = true +} + +func (v NullableResourceId) IsSet() bool { + return v.isSet +} + +func (v *NullableResourceId) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableResourceId(val *ResourceId) *NullableResourceId { + return &NullableResourceId{value: val, isSet: true} +} + +func (v NullableResourceId) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableResourceId) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id_response.go new file mode 100644 index 00000000..a7d95716 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_resource_id_response.go @@ -0,0 +1,260 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ResourceIDResponse struct for ResourceIDResponse +type ResourceIDResponse struct { + Kind *string `json:"kind,omitempty"` + ProjectKey *string `json:"projectKey,omitempty"` + EnvironmentKey *string `json:"environmentKey,omitempty"` + FlagKey *string `json:"flagKey,omitempty"` + Key *string `json:"key,omitempty"` +} + +// NewResourceIDResponse instantiates a new ResourceIDResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewResourceIDResponse() *ResourceIDResponse { + this := ResourceIDResponse{} + return &this +} + +// NewResourceIDResponseWithDefaults instantiates a new ResourceIDResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewResourceIDResponseWithDefaults() *ResourceIDResponse { + this := ResourceIDResponse{} + return &this +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *ResourceIDResponse) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceIDResponse) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *ResourceIDResponse) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *ResourceIDResponse) SetKind(v string) { + o.Kind = &v +} + +// GetProjectKey returns the ProjectKey field value if set, zero value otherwise. +func (o *ResourceIDResponse) GetProjectKey() string { + if o == nil || o.ProjectKey == nil { + var ret string + return ret + } + return *o.ProjectKey +} + +// GetProjectKeyOk returns a tuple with the ProjectKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceIDResponse) GetProjectKeyOk() (*string, bool) { + if o == nil || o.ProjectKey == nil { + return nil, false + } + return o.ProjectKey, true +} + +// HasProjectKey returns a boolean if a field has been set. +func (o *ResourceIDResponse) HasProjectKey() bool { + if o != nil && o.ProjectKey != nil { + return true + } + + return false +} + +// SetProjectKey gets a reference to the given string and assigns it to the ProjectKey field. +func (o *ResourceIDResponse) SetProjectKey(v string) { + o.ProjectKey = &v +} + +// GetEnvironmentKey returns the EnvironmentKey field value if set, zero value otherwise. +func (o *ResourceIDResponse) GetEnvironmentKey() string { + if o == nil || o.EnvironmentKey == nil { + var ret string + return ret + } + return *o.EnvironmentKey +} + +// GetEnvironmentKeyOk returns a tuple with the EnvironmentKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceIDResponse) GetEnvironmentKeyOk() (*string, bool) { + if o == nil || o.EnvironmentKey == nil { + return nil, false + } + return o.EnvironmentKey, true +} + +// HasEnvironmentKey returns a boolean if a field has been set. +func (o *ResourceIDResponse) HasEnvironmentKey() bool { + if o != nil && o.EnvironmentKey != nil { + return true + } + + return false +} + +// SetEnvironmentKey gets a reference to the given string and assigns it to the EnvironmentKey field. +func (o *ResourceIDResponse) SetEnvironmentKey(v string) { + o.EnvironmentKey = &v +} + +// GetFlagKey returns the FlagKey field value if set, zero value otherwise. +func (o *ResourceIDResponse) GetFlagKey() string { + if o == nil || o.FlagKey == nil { + var ret string + return ret + } + return *o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceIDResponse) GetFlagKeyOk() (*string, bool) { + if o == nil || o.FlagKey == nil { + return nil, false + } + return o.FlagKey, true +} + +// HasFlagKey returns a boolean if a field has been set. +func (o *ResourceIDResponse) HasFlagKey() bool { + if o != nil && o.FlagKey != nil { + return true + } + + return false +} + +// SetFlagKey gets a reference to the given string and assigns it to the FlagKey field. +func (o *ResourceIDResponse) SetFlagKey(v string) { + o.FlagKey = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *ResourceIDResponse) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceIDResponse) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *ResourceIDResponse) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *ResourceIDResponse) SetKey(v string) { + o.Key = &v +} + +func (o ResourceIDResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.ProjectKey != nil { + toSerialize["projectKey"] = o.ProjectKey + } + if o.EnvironmentKey != nil { + toSerialize["environmentKey"] = o.EnvironmentKey + } + if o.FlagKey != nil { + toSerialize["flagKey"] = o.FlagKey + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + return json.Marshal(toSerialize) +} + +type NullableResourceIDResponse struct { + value *ResourceIDResponse + isSet bool +} + +func (v NullableResourceIDResponse) Get() *ResourceIDResponse { + return v.value +} + +func (v *NullableResourceIDResponse) Set(val *ResourceIDResponse) { + v.value = val + v.isSet = true +} + +func (v NullableResourceIDResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableResourceIDResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableResourceIDResponse(val *ResourceIDResponse) *NullableResourceIDResponse { + return &NullableResourceIDResponse{value: val, isSet: true} +} + +func (v NullableResourceIDResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableResourceIDResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_review_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_review_output.go new file mode 100644 index 00000000..b80e4ed9 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_review_output.go @@ -0,0 +1,282 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReviewOutput struct for ReviewOutput +type ReviewOutput struct { + Id string `json:"_id"` + Kind string `json:"kind"` + CreationDate *int64 `json:"creationDate,omitempty"` + Comment *string `json:"comment,omitempty"` + MemberId *string `json:"memberId,omitempty"` + ServiceTokenId *string `json:"serviceTokenId,omitempty"` +} + +// NewReviewOutput instantiates a new ReviewOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReviewOutput(id string, kind string) *ReviewOutput { + this := ReviewOutput{} + this.Id = id + this.Kind = kind + return &this +} + +// NewReviewOutputWithDefaults instantiates a new ReviewOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReviewOutputWithDefaults() *ReviewOutput { + this := ReviewOutput{} + return &this +} + +// GetId returns the Id field value +func (o *ReviewOutput) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ReviewOutput) SetId(v string) { + o.Id = v +} + +// GetKind returns the Kind field value +func (o *ReviewOutput) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ReviewOutput) SetKind(v string) { + o.Kind = v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *ReviewOutput) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *ReviewOutput) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *ReviewOutput) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *ReviewOutput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *ReviewOutput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *ReviewOutput) SetComment(v string) { + o.Comment = &v +} + +// GetMemberId returns the MemberId field value if set, zero value otherwise. +func (o *ReviewOutput) GetMemberId() string { + if o == nil || o.MemberId == nil { + var ret string + return ret + } + return *o.MemberId +} + +// GetMemberIdOk returns a tuple with the MemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetMemberIdOk() (*string, bool) { + if o == nil || o.MemberId == nil { + return nil, false + } + return o.MemberId, true +} + +// HasMemberId returns a boolean if a field has been set. +func (o *ReviewOutput) HasMemberId() bool { + if o != nil && o.MemberId != nil { + return true + } + + return false +} + +// SetMemberId gets a reference to the given string and assigns it to the MemberId field. +func (o *ReviewOutput) SetMemberId(v string) { + o.MemberId = &v +} + +// GetServiceTokenId returns the ServiceTokenId field value if set, zero value otherwise. +func (o *ReviewOutput) GetServiceTokenId() string { + if o == nil || o.ServiceTokenId == nil { + var ret string + return ret + } + return *o.ServiceTokenId +} + +// GetServiceTokenIdOk returns a tuple with the ServiceTokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewOutput) GetServiceTokenIdOk() (*string, bool) { + if o == nil || o.ServiceTokenId == nil { + return nil, false + } + return o.ServiceTokenId, true +} + +// HasServiceTokenId returns a boolean if a field has been set. +func (o *ReviewOutput) HasServiceTokenId() bool { + if o != nil && o.ServiceTokenId != nil { + return true + } + + return false +} + +// SetServiceTokenId gets a reference to the given string and assigns it to the ServiceTokenId field. +func (o *ReviewOutput) SetServiceTokenId(v string) { + o.ServiceTokenId = &v +} + +func (o ReviewOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["kind"] = o.Kind + } + if o.CreationDate != nil { + toSerialize["creationDate"] = o.CreationDate + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.MemberId != nil { + toSerialize["memberId"] = o.MemberId + } + if o.ServiceTokenId != nil { + toSerialize["serviceTokenId"] = o.ServiceTokenId + } + return json.Marshal(toSerialize) +} + +type NullableReviewOutput struct { + value *ReviewOutput + isSet bool +} + +func (v NullableReviewOutput) Get() *ReviewOutput { + return v.value +} + +func (v *NullableReviewOutput) Set(val *ReviewOutput) { + v.value = val + v.isSet = true +} + +func (v NullableReviewOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableReviewOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReviewOutput(val *ReviewOutput) *NullableReviewOutput { + return &NullableReviewOutput{value: val, isSet: true} +} + +func (v NullableReviewOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReviewOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_review_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_review_response.go new file mode 100644 index 00000000..6bc5ec27 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_review_response.go @@ -0,0 +1,287 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ReviewResponse struct for ReviewResponse +type ReviewResponse struct { + // The approval request ID + Id string `json:"_id"` + // The type of review action to take + Kind string `json:"kind"` + CreationDate *int64 `json:"creationDate,omitempty"` + // A comment describing the approval response + Comment *string `json:"comment,omitempty"` + // ID of account member that reviewed request + MemberId *string `json:"memberId,omitempty"` + // ID of account service token that reviewed request + ServiceTokenId *string `json:"serviceTokenId,omitempty"` +} + +// NewReviewResponse instantiates a new ReviewResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReviewResponse(id string, kind string) *ReviewResponse { + this := ReviewResponse{} + this.Id = id + this.Kind = kind + return &this +} + +// NewReviewResponseWithDefaults instantiates a new ReviewResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReviewResponseWithDefaults() *ReviewResponse { + this := ReviewResponse{} + return &this +} + +// GetId returns the Id field value +func (o *ReviewResponse) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *ReviewResponse) SetId(v string) { + o.Id = v +} + +// GetKind returns the Kind field value +func (o *ReviewResponse) GetKind() string { + if o == nil { + var ret string + return ret + } + + return o.Kind +} + +// GetKindOk returns a tuple with the Kind field value +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetKindOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Kind, true +} + +// SetKind sets field value +func (o *ReviewResponse) SetKind(v string) { + o.Kind = v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *ReviewResponse) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *ReviewResponse) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *ReviewResponse) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *ReviewResponse) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *ReviewResponse) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *ReviewResponse) SetComment(v string) { + o.Comment = &v +} + +// GetMemberId returns the MemberId field value if set, zero value otherwise. +func (o *ReviewResponse) GetMemberId() string { + if o == nil || o.MemberId == nil { + var ret string + return ret + } + return *o.MemberId +} + +// GetMemberIdOk returns a tuple with the MemberId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetMemberIdOk() (*string, bool) { + if o == nil || o.MemberId == nil { + return nil, false + } + return o.MemberId, true +} + +// HasMemberId returns a boolean if a field has been set. +func (o *ReviewResponse) HasMemberId() bool { + if o != nil && o.MemberId != nil { + return true + } + + return false +} + +// SetMemberId gets a reference to the given string and assigns it to the MemberId field. +func (o *ReviewResponse) SetMemberId(v string) { + o.MemberId = &v +} + +// GetServiceTokenId returns the ServiceTokenId field value if set, zero value otherwise. +func (o *ReviewResponse) GetServiceTokenId() string { + if o == nil || o.ServiceTokenId == nil { + var ret string + return ret + } + return *o.ServiceTokenId +} + +// GetServiceTokenIdOk returns a tuple with the ServiceTokenId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReviewResponse) GetServiceTokenIdOk() (*string, bool) { + if o == nil || o.ServiceTokenId == nil { + return nil, false + } + return o.ServiceTokenId, true +} + +// HasServiceTokenId returns a boolean if a field has been set. +func (o *ReviewResponse) HasServiceTokenId() bool { + if o != nil && o.ServiceTokenId != nil { + return true + } + + return false +} + +// SetServiceTokenId gets a reference to the given string and assigns it to the ServiceTokenId field. +func (o *ReviewResponse) SetServiceTokenId(v string) { + o.ServiceTokenId = &v +} + +func (o ReviewResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["kind"] = o.Kind + } + if o.CreationDate != nil { + toSerialize["creationDate"] = o.CreationDate + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.MemberId != nil { + toSerialize["memberId"] = o.MemberId + } + if o.ServiceTokenId != nil { + toSerialize["serviceTokenId"] = o.ServiceTokenId + } + return json.Marshal(toSerialize) +} + +type NullableReviewResponse struct { + value *ReviewResponse + isSet bool +} + +func (v NullableReviewResponse) Get() *ReviewResponse { + return v.value +} + +func (v *NullableReviewResponse) Set(val *ReviewResponse) { + v.value = val + v.isSet = true +} + +func (v NullableReviewResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableReviewResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReviewResponse(val *ReviewResponse) *NullableReviewResponse { + return &NullableReviewResponse{value: val, isSet: true} +} + +func (v NullableReviewResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReviewResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_rollout.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_rollout.go new file mode 100644 index 00000000..277a9a07 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_rollout.go @@ -0,0 +1,253 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Rollout struct for Rollout +type Rollout struct { + Variations []WeightedVariation `json:"variations"` + ExperimentAllocation *ExperimentAllocationRep `json:"experimentAllocation,omitempty"` + Seed *int32 `json:"seed,omitempty"` + BucketBy *string `json:"bucketBy,omitempty"` + ContextKind *string `json:"contextKind,omitempty"` +} + +// NewRollout instantiates a new Rollout object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRollout(variations []WeightedVariation) *Rollout { + this := Rollout{} + this.Variations = variations + return &this +} + +// NewRolloutWithDefaults instantiates a new Rollout object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRolloutWithDefaults() *Rollout { + this := Rollout{} + return &this +} + +// GetVariations returns the Variations field value +func (o *Rollout) GetVariations() []WeightedVariation { + if o == nil { + var ret []WeightedVariation + return ret + } + + return o.Variations +} + +// GetVariationsOk returns a tuple with the Variations field value +// and a boolean to check if the value has been set. +func (o *Rollout) GetVariationsOk() ([]WeightedVariation, bool) { + if o == nil { + return nil, false + } + return o.Variations, true +} + +// SetVariations sets field value +func (o *Rollout) SetVariations(v []WeightedVariation) { + o.Variations = v +} + +// GetExperimentAllocation returns the ExperimentAllocation field value if set, zero value otherwise. +func (o *Rollout) GetExperimentAllocation() ExperimentAllocationRep { + if o == nil || o.ExperimentAllocation == nil { + var ret ExperimentAllocationRep + return ret + } + return *o.ExperimentAllocation +} + +// GetExperimentAllocationOk returns a tuple with the ExperimentAllocation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rollout) GetExperimentAllocationOk() (*ExperimentAllocationRep, bool) { + if o == nil || o.ExperimentAllocation == nil { + return nil, false + } + return o.ExperimentAllocation, true +} + +// HasExperimentAllocation returns a boolean if a field has been set. +func (o *Rollout) HasExperimentAllocation() bool { + if o != nil && o.ExperimentAllocation != nil { + return true + } + + return false +} + +// SetExperimentAllocation gets a reference to the given ExperimentAllocationRep and assigns it to the ExperimentAllocation field. +func (o *Rollout) SetExperimentAllocation(v ExperimentAllocationRep) { + o.ExperimentAllocation = &v +} + +// GetSeed returns the Seed field value if set, zero value otherwise. +func (o *Rollout) GetSeed() int32 { + if o == nil || o.Seed == nil { + var ret int32 + return ret + } + return *o.Seed +} + +// GetSeedOk returns a tuple with the Seed field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rollout) GetSeedOk() (*int32, bool) { + if o == nil || o.Seed == nil { + return nil, false + } + return o.Seed, true +} + +// HasSeed returns a boolean if a field has been set. +func (o *Rollout) HasSeed() bool { + if o != nil && o.Seed != nil { + return true + } + + return false +} + +// SetSeed gets a reference to the given int32 and assigns it to the Seed field. +func (o *Rollout) SetSeed(v int32) { + o.Seed = &v +} + +// GetBucketBy returns the BucketBy field value if set, zero value otherwise. +func (o *Rollout) GetBucketBy() string { + if o == nil || o.BucketBy == nil { + var ret string + return ret + } + return *o.BucketBy +} + +// GetBucketByOk returns a tuple with the BucketBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rollout) GetBucketByOk() (*string, bool) { + if o == nil || o.BucketBy == nil { + return nil, false + } + return o.BucketBy, true +} + +// HasBucketBy returns a boolean if a field has been set. +func (o *Rollout) HasBucketBy() bool { + if o != nil && o.BucketBy != nil { + return true + } + + return false +} + +// SetBucketBy gets a reference to the given string and assigns it to the BucketBy field. +func (o *Rollout) SetBucketBy(v string) { + o.BucketBy = &v +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *Rollout) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rollout) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *Rollout) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *Rollout) SetContextKind(v string) { + o.ContextKind = &v +} + +func (o Rollout) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["variations"] = o.Variations + } + if o.ExperimentAllocation != nil { + toSerialize["experimentAllocation"] = o.ExperimentAllocation + } + if o.Seed != nil { + toSerialize["seed"] = o.Seed + } + if o.BucketBy != nil { + toSerialize["bucketBy"] = o.BucketBy + } + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + return json.Marshal(toSerialize) +} + +type NullableRollout struct { + value *Rollout + isSet bool +} + +func (v NullableRollout) Get() *Rollout { + return v.value +} + +func (v *NullableRollout) Set(val *Rollout) { + v.value = val + v.isSet = true +} + +func (v NullableRollout) IsSet() bool { + return v.isSet +} + +func (v *NullableRollout) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRollout(val *Rollout) *NullableRollout { + return &NullableRollout{value: val, isSet: true} +} + +func (v NullableRollout) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRollout) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_root_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_root_response.go new file mode 100644 index 00000000..2221fb0a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_root_response.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RootResponse struct for RootResponse +type RootResponse struct { + Links map[string]Link `json:"links"` +} + +// NewRootResponse instantiates a new RootResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRootResponse(links map[string]Link) *RootResponse { + this := RootResponse{} + this.Links = links + return &this +} + +// NewRootResponseWithDefaults instantiates a new RootResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRootResponseWithDefaults() *RootResponse { + this := RootResponse{} + return &this +} + +// GetLinks returns the Links field value +func (o *RootResponse) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *RootResponse) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *RootResponse) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o RootResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableRootResponse struct { + value *RootResponse + isSet bool +} + +func (v NullableRootResponse) Get() *RootResponse { + return v.value +} + +func (v *NullableRootResponse) Set(val *RootResponse) { + v.value = val + v.isSet = true +} + +func (v NullableRootResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableRootResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRootResponse(val *RootResponse) *NullableRootResponse { + return &NullableRootResponse{value: val, isSet: true} +} + +func (v NullableRootResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRootResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_rule.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_rule.go new file mode 100644 index 00000000..eccdd5d4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_rule.go @@ -0,0 +1,323 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Rule struct for Rule +type Rule struct { + // The flag rule ID + Id *string `json:"_id,omitempty"` + // The index of the variation, from the array of variations for this flag + Variation *int32 `json:"variation,omitempty"` + Rollout *Rollout `json:"rollout,omitempty"` + // An array of clauses used for individual targeting based on attributes + Clauses []Clause `json:"clauses"` + // Whether LaunchDarkly tracks events for this rule + TrackEvents bool `json:"trackEvents"` + // The rule description + Description *string `json:"description,omitempty"` + Ref *string `json:"ref,omitempty"` +} + +// NewRule instantiates a new Rule object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRule(clauses []Clause, trackEvents bool) *Rule { + this := Rule{} + this.Clauses = clauses + this.TrackEvents = trackEvents + return &this +} + +// NewRuleWithDefaults instantiates a new Rule object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRuleWithDefaults() *Rule { + this := Rule{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Rule) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rule) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Rule) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Rule) SetId(v string) { + o.Id = &v +} + +// GetVariation returns the Variation field value if set, zero value otherwise. +func (o *Rule) GetVariation() int32 { + if o == nil || o.Variation == nil { + var ret int32 + return ret + } + return *o.Variation +} + +// GetVariationOk returns a tuple with the Variation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rule) GetVariationOk() (*int32, bool) { + if o == nil || o.Variation == nil { + return nil, false + } + return o.Variation, true +} + +// HasVariation returns a boolean if a field has been set. +func (o *Rule) HasVariation() bool { + if o != nil && o.Variation != nil { + return true + } + + return false +} + +// SetVariation gets a reference to the given int32 and assigns it to the Variation field. +func (o *Rule) SetVariation(v int32) { + o.Variation = &v +} + +// GetRollout returns the Rollout field value if set, zero value otherwise. +func (o *Rule) GetRollout() Rollout { + if o == nil || o.Rollout == nil { + var ret Rollout + return ret + } + return *o.Rollout +} + +// GetRolloutOk returns a tuple with the Rollout field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rule) GetRolloutOk() (*Rollout, bool) { + if o == nil || o.Rollout == nil { + return nil, false + } + return o.Rollout, true +} + +// HasRollout returns a boolean if a field has been set. +func (o *Rule) HasRollout() bool { + if o != nil && o.Rollout != nil { + return true + } + + return false +} + +// SetRollout gets a reference to the given Rollout and assigns it to the Rollout field. +func (o *Rule) SetRollout(v Rollout) { + o.Rollout = &v +} + +// GetClauses returns the Clauses field value +func (o *Rule) GetClauses() []Clause { + if o == nil { + var ret []Clause + return ret + } + + return o.Clauses +} + +// GetClausesOk returns a tuple with the Clauses field value +// and a boolean to check if the value has been set. +func (o *Rule) GetClausesOk() ([]Clause, bool) { + if o == nil { + return nil, false + } + return o.Clauses, true +} + +// SetClauses sets field value +func (o *Rule) SetClauses(v []Clause) { + o.Clauses = v +} + +// GetTrackEvents returns the TrackEvents field value +func (o *Rule) GetTrackEvents() bool { + if o == nil { + var ret bool + return ret + } + + return o.TrackEvents +} + +// GetTrackEventsOk returns a tuple with the TrackEvents field value +// and a boolean to check if the value has been set. +func (o *Rule) GetTrackEventsOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.TrackEvents, true +} + +// SetTrackEvents sets field value +func (o *Rule) SetTrackEvents(v bool) { + o.TrackEvents = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Rule) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rule) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Rule) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Rule) SetDescription(v string) { + o.Description = &v +} + +// GetRef returns the Ref field value if set, zero value otherwise. +func (o *Rule) GetRef() string { + if o == nil || o.Ref == nil { + var ret string + return ret + } + return *o.Ref +} + +// GetRefOk returns a tuple with the Ref field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Rule) GetRefOk() (*string, bool) { + if o == nil || o.Ref == nil { + return nil, false + } + return o.Ref, true +} + +// HasRef returns a boolean if a field has been set. +func (o *Rule) HasRef() bool { + if o != nil && o.Ref != nil { + return true + } + + return false +} + +// SetRef gets a reference to the given string and assigns it to the Ref field. +func (o *Rule) SetRef(v string) { + o.Ref = &v +} + +func (o Rule) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Variation != nil { + toSerialize["variation"] = o.Variation + } + if o.Rollout != nil { + toSerialize["rollout"] = o.Rollout + } + if true { + toSerialize["clauses"] = o.Clauses + } + if true { + toSerialize["trackEvents"] = o.TrackEvents + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Ref != nil { + toSerialize["ref"] = o.Ref + } + return json.Marshal(toSerialize) +} + +type NullableRule struct { + value *Rule + isSet bool +} + +func (v NullableRule) Get() *Rule { + return v.value +} + +func (v *NullableRule) Set(val *Rule) { + v.value = val + v.isSet = true +} + +func (v NullableRule) IsSet() bool { + return v.isSet +} + +func (v *NullableRule) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRule(val *Rule) *NullableRule { + return &NullableRule{value: val, isSet: true} +} + +func (v NullableRule) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRule) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_rule_clause.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_rule_clause.go new file mode 100644 index 00000000..e4d987c2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_rule_clause.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// RuleClause struct for RuleClause +type RuleClause struct { + // The attribute the rule applies to, for example, last name or email address + Attribute *string `json:"attribute,omitempty"` + // The operator to apply to the given attribute + Op *string `json:"op,omitempty"` + // Whether the operator should be negated + Negate *bool `json:"negate,omitempty"` +} + +// NewRuleClause instantiates a new RuleClause object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRuleClause() *RuleClause { + this := RuleClause{} + return &this +} + +// NewRuleClauseWithDefaults instantiates a new RuleClause object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRuleClauseWithDefaults() *RuleClause { + this := RuleClause{} + return &this +} + +// GetAttribute returns the Attribute field value if set, zero value otherwise. +func (o *RuleClause) GetAttribute() string { + if o == nil || o.Attribute == nil { + var ret string + return ret + } + return *o.Attribute +} + +// GetAttributeOk returns a tuple with the Attribute field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RuleClause) GetAttributeOk() (*string, bool) { + if o == nil || o.Attribute == nil { + return nil, false + } + return o.Attribute, true +} + +// HasAttribute returns a boolean if a field has been set. +func (o *RuleClause) HasAttribute() bool { + if o != nil && o.Attribute != nil { + return true + } + + return false +} + +// SetAttribute gets a reference to the given string and assigns it to the Attribute field. +func (o *RuleClause) SetAttribute(v string) { + o.Attribute = &v +} + +// GetOp returns the Op field value if set, zero value otherwise. +func (o *RuleClause) GetOp() string { + if o == nil || o.Op == nil { + var ret string + return ret + } + return *o.Op +} + +// GetOpOk returns a tuple with the Op field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RuleClause) GetOpOk() (*string, bool) { + if o == nil || o.Op == nil { + return nil, false + } + return o.Op, true +} + +// HasOp returns a boolean if a field has been set. +func (o *RuleClause) HasOp() bool { + if o != nil && o.Op != nil { + return true + } + + return false +} + +// SetOp gets a reference to the given string and assigns it to the Op field. +func (o *RuleClause) SetOp(v string) { + o.Op = &v +} + +// GetNegate returns the Negate field value if set, zero value otherwise. +func (o *RuleClause) GetNegate() bool { + if o == nil || o.Negate == nil { + var ret bool + return ret + } + return *o.Negate +} + +// GetNegateOk returns a tuple with the Negate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RuleClause) GetNegateOk() (*bool, bool) { + if o == nil || o.Negate == nil { + return nil, false + } + return o.Negate, true +} + +// HasNegate returns a boolean if a field has been set. +func (o *RuleClause) HasNegate() bool { + if o != nil && o.Negate != nil { + return true + } + + return false +} + +// SetNegate gets a reference to the given bool and assigns it to the Negate field. +func (o *RuleClause) SetNegate(v bool) { + o.Negate = &v +} + +func (o RuleClause) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Attribute != nil { + toSerialize["attribute"] = o.Attribute + } + if o.Op != nil { + toSerialize["op"] = o.Op + } + if o.Negate != nil { + toSerialize["negate"] = o.Negate + } + return json.Marshal(toSerialize) +} + +type NullableRuleClause struct { + value *RuleClause + isSet bool +} + +func (v NullableRuleClause) Get() *RuleClause { + return v.value +} + +func (v *NullableRuleClause) Set(val *RuleClause) { + v.value = val + v.isSet = true +} + +func (v NullableRuleClause) IsSet() bool { + return v.isSet +} + +func (v *NullableRuleClause) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRuleClause(val *RuleClause) *NullableRuleClause { + return &NullableRuleClause{value: val, isSet: true} +} + +func (v NullableRuleClause) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRuleClause) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_list_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_list_rep.go new file mode 100644 index 00000000..997de066 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_list_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SdkListRep struct for SdkListRep +type SdkListRep struct { + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + // The list of SDK names + Sdks []string `json:"sdks"` +} + +// NewSdkListRep instantiates a new SdkListRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSdkListRep(links map[string]interface{}, sdks []string) *SdkListRep { + this := SdkListRep{} + this.Links = links + this.Sdks = sdks + return &this +} + +// NewSdkListRepWithDefaults instantiates a new SdkListRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSdkListRepWithDefaults() *SdkListRep { + this := SdkListRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *SdkListRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *SdkListRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *SdkListRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetSdks returns the Sdks field value +func (o *SdkListRep) GetSdks() []string { + if o == nil { + var ret []string + return ret + } + + return o.Sdks +} + +// GetSdksOk returns a tuple with the Sdks field value +// and a boolean to check if the value has been set. +func (o *SdkListRep) GetSdksOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Sdks, true +} + +// SetSdks sets field value +func (o *SdkListRep) SetSdks(v []string) { + o.Sdks = v +} + +func (o SdkListRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["sdks"] = o.Sdks + } + return json.Marshal(toSerialize) +} + +type NullableSdkListRep struct { + value *SdkListRep + isSet bool +} + +func (v NullableSdkListRep) Get() *SdkListRep { + return v.value +} + +func (v *NullableSdkListRep) Set(val *SdkListRep) { + v.value = val + v.isSet = true +} + +func (v NullableSdkListRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSdkListRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSdkListRep(val *SdkListRep) *NullableSdkListRep { + return &NullableSdkListRep{value: val, isSet: true} +} + +func (v NullableSdkListRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSdkListRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_list_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_list_rep.go new file mode 100644 index 00000000..27522a3a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_list_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SdkVersionListRep struct for SdkVersionListRep +type SdkVersionListRep struct { + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + // The list of SDK names and versions + SdkVersions []SdkVersionRep `json:"sdkVersions"` +} + +// NewSdkVersionListRep instantiates a new SdkVersionListRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSdkVersionListRep(links map[string]interface{}, sdkVersions []SdkVersionRep) *SdkVersionListRep { + this := SdkVersionListRep{} + this.Links = links + this.SdkVersions = sdkVersions + return &this +} + +// NewSdkVersionListRepWithDefaults instantiates a new SdkVersionListRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSdkVersionListRepWithDefaults() *SdkVersionListRep { + this := SdkVersionListRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *SdkVersionListRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *SdkVersionListRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *SdkVersionListRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetSdkVersions returns the SdkVersions field value +func (o *SdkVersionListRep) GetSdkVersions() []SdkVersionRep { + if o == nil { + var ret []SdkVersionRep + return ret + } + + return o.SdkVersions +} + +// GetSdkVersionsOk returns a tuple with the SdkVersions field value +// and a boolean to check if the value has been set. +func (o *SdkVersionListRep) GetSdkVersionsOk() ([]SdkVersionRep, bool) { + if o == nil { + return nil, false + } + return o.SdkVersions, true +} + +// SetSdkVersions sets field value +func (o *SdkVersionListRep) SetSdkVersions(v []SdkVersionRep) { + o.SdkVersions = v +} + +func (o SdkVersionListRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["sdkVersions"] = o.SdkVersions + } + return json.Marshal(toSerialize) +} + +type NullableSdkVersionListRep struct { + value *SdkVersionListRep + isSet bool +} + +func (v NullableSdkVersionListRep) Get() *SdkVersionListRep { + return v.value +} + +func (v *NullableSdkVersionListRep) Set(val *SdkVersionListRep) { + v.value = val + v.isSet = true +} + +func (v NullableSdkVersionListRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSdkVersionListRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSdkVersionListRep(val *SdkVersionListRep) *NullableSdkVersionListRep { + return &NullableSdkVersionListRep{value: val, isSet: true} +} + +func (v NullableSdkVersionListRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSdkVersionListRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_rep.go new file mode 100644 index 00000000..44315772 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_sdk_version_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SdkVersionRep struct for SdkVersionRep +type SdkVersionRep struct { + // The SDK name, or \"Unknown\" + Sdk string `json:"sdk"` + // The version number, or \"Unknown\" + Version string `json:"version"` +} + +// NewSdkVersionRep instantiates a new SdkVersionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSdkVersionRep(sdk string, version string) *SdkVersionRep { + this := SdkVersionRep{} + this.Sdk = sdk + this.Version = version + return &this +} + +// NewSdkVersionRepWithDefaults instantiates a new SdkVersionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSdkVersionRepWithDefaults() *SdkVersionRep { + this := SdkVersionRep{} + return &this +} + +// GetSdk returns the Sdk field value +func (o *SdkVersionRep) GetSdk() string { + if o == nil { + var ret string + return ret + } + + return o.Sdk +} + +// GetSdkOk returns a tuple with the Sdk field value +// and a boolean to check if the value has been set. +func (o *SdkVersionRep) GetSdkOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Sdk, true +} + +// SetSdk sets field value +func (o *SdkVersionRep) SetSdk(v string) { + o.Sdk = v +} + +// GetVersion returns the Version field value +func (o *SdkVersionRep) GetVersion() string { + if o == nil { + var ret string + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *SdkVersionRep) GetVersionOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *SdkVersionRep) SetVersion(v string) { + o.Version = v +} + +func (o SdkVersionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["sdk"] = o.Sdk + } + if true { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableSdkVersionRep struct { + value *SdkVersionRep + isSet bool +} + +func (v NullableSdkVersionRep) Get() *SdkVersionRep { + return v.value +} + +func (v *NullableSdkVersionRep) Set(val *SdkVersionRep) { + v.value = val + v.isSet = true +} + +func (v NullableSdkVersionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSdkVersionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSdkVersionRep(val *SdkVersionRep) *NullableSdkVersionRep { + return &NullableSdkVersionRep{value: val, isSet: true} +} + +func (v NullableSdkVersionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSdkVersionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_body.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_body.go new file mode 100644 index 00000000..549bf203 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_body.go @@ -0,0 +1,288 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SegmentBody struct for SegmentBody +type SegmentBody struct { + // A human-friendly name for the segment + Name string `json:"name"` + // A unique key used to reference the segment + Key string `json:"key"` + // A description of the segment's purpose + Description *string `json:"description,omitempty"` + // Tags for the segment + Tags []string `json:"tags,omitempty"` + // Whether to create a standard segment (false) or a big segment (true). Standard segments include rule-based and smaller list-based segments. Big segments include larger list-based segments and synced segments. Only use a big segment if you need to add more than 15,000 individual targets. + Unbounded *bool `json:"unbounded,omitempty"` + // For big segments, the targeted context kind. + UnboundedContextKind *string `json:"unboundedContextKind,omitempty"` +} + +// NewSegmentBody instantiates a new SegmentBody object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSegmentBody(name string, key string) *SegmentBody { + this := SegmentBody{} + this.Name = name + this.Key = key + return &this +} + +// NewSegmentBodyWithDefaults instantiates a new SegmentBody object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSegmentBodyWithDefaults() *SegmentBody { + this := SegmentBody{} + return &this +} + +// GetName returns the Name field value +func (o *SegmentBody) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *SegmentBody) SetName(v string) { + o.Name = v +} + +// GetKey returns the Key field value +func (o *SegmentBody) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *SegmentBody) SetKey(v string) { + o.Key = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *SegmentBody) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *SegmentBody) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *SegmentBody) SetDescription(v string) { + o.Description = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *SegmentBody) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *SegmentBody) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *SegmentBody) SetTags(v []string) { + o.Tags = v +} + +// GetUnbounded returns the Unbounded field value if set, zero value otherwise. +func (o *SegmentBody) GetUnbounded() bool { + if o == nil || o.Unbounded == nil { + var ret bool + return ret + } + return *o.Unbounded +} + +// GetUnboundedOk returns a tuple with the Unbounded field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetUnboundedOk() (*bool, bool) { + if o == nil || o.Unbounded == nil { + return nil, false + } + return o.Unbounded, true +} + +// HasUnbounded returns a boolean if a field has been set. +func (o *SegmentBody) HasUnbounded() bool { + if o != nil && o.Unbounded != nil { + return true + } + + return false +} + +// SetUnbounded gets a reference to the given bool and assigns it to the Unbounded field. +func (o *SegmentBody) SetUnbounded(v bool) { + o.Unbounded = &v +} + +// GetUnboundedContextKind returns the UnboundedContextKind field value if set, zero value otherwise. +func (o *SegmentBody) GetUnboundedContextKind() string { + if o == nil || o.UnboundedContextKind == nil { + var ret string + return ret + } + return *o.UnboundedContextKind +} + +// GetUnboundedContextKindOk returns a tuple with the UnboundedContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentBody) GetUnboundedContextKindOk() (*string, bool) { + if o == nil || o.UnboundedContextKind == nil { + return nil, false + } + return o.UnboundedContextKind, true +} + +// HasUnboundedContextKind returns a boolean if a field has been set. +func (o *SegmentBody) HasUnboundedContextKind() bool { + if o != nil && o.UnboundedContextKind != nil { + return true + } + + return false +} + +// SetUnboundedContextKind gets a reference to the given string and assigns it to the UnboundedContextKind field. +func (o *SegmentBody) SetUnboundedContextKind(v string) { + o.UnboundedContextKind = &v +} + +func (o SegmentBody) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["key"] = o.Key + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if o.Unbounded != nil { + toSerialize["unbounded"] = o.Unbounded + } + if o.UnboundedContextKind != nil { + toSerialize["unboundedContextKind"] = o.UnboundedContextKind + } + return json.Marshal(toSerialize) +} + +type NullableSegmentBody struct { + value *SegmentBody + isSet bool +} + +func (v NullableSegmentBody) Get() *SegmentBody { + return v.value +} + +func (v *NullableSegmentBody) Set(val *SegmentBody) { + v.value = val + v.isSet = true +} + +func (v NullableSegmentBody) IsSet() bool { + return v.isSet +} + +func (v *NullableSegmentBody) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSegmentBody(val *SegmentBody) *NullableSegmentBody { + return &NullableSegmentBody{value: val, isSet: true} +} + +func (v NullableSegmentBody) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSegmentBody) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_metadata.go new file mode 100644 index 00000000..6ad78ab1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_metadata.go @@ -0,0 +1,332 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SegmentMetadata struct for SegmentMetadata +type SegmentMetadata struct { + EnvId *string `json:"envId,omitempty"` + SegmentId *string `json:"segmentId,omitempty"` + Version *int32 `json:"version,omitempty"` + IncludedCount *int32 `json:"includedCount,omitempty"` + ExcludedCount *int32 `json:"excludedCount,omitempty"` + LastModified *int64 `json:"lastModified,omitempty"` + Deleted *bool `json:"deleted,omitempty"` +} + +// NewSegmentMetadata instantiates a new SegmentMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSegmentMetadata() *SegmentMetadata { + this := SegmentMetadata{} + return &this +} + +// NewSegmentMetadataWithDefaults instantiates a new SegmentMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSegmentMetadataWithDefaults() *SegmentMetadata { + this := SegmentMetadata{} + return &this +} + +// GetEnvId returns the EnvId field value if set, zero value otherwise. +func (o *SegmentMetadata) GetEnvId() string { + if o == nil || o.EnvId == nil { + var ret string + return ret + } + return *o.EnvId +} + +// GetEnvIdOk returns a tuple with the EnvId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetEnvIdOk() (*string, bool) { + if o == nil || o.EnvId == nil { + return nil, false + } + return o.EnvId, true +} + +// HasEnvId returns a boolean if a field has been set. +func (o *SegmentMetadata) HasEnvId() bool { + if o != nil && o.EnvId != nil { + return true + } + + return false +} + +// SetEnvId gets a reference to the given string and assigns it to the EnvId field. +func (o *SegmentMetadata) SetEnvId(v string) { + o.EnvId = &v +} + +// GetSegmentId returns the SegmentId field value if set, zero value otherwise. +func (o *SegmentMetadata) GetSegmentId() string { + if o == nil || o.SegmentId == nil { + var ret string + return ret + } + return *o.SegmentId +} + +// GetSegmentIdOk returns a tuple with the SegmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetSegmentIdOk() (*string, bool) { + if o == nil || o.SegmentId == nil { + return nil, false + } + return o.SegmentId, true +} + +// HasSegmentId returns a boolean if a field has been set. +func (o *SegmentMetadata) HasSegmentId() bool { + if o != nil && o.SegmentId != nil { + return true + } + + return false +} + +// SetSegmentId gets a reference to the given string and assigns it to the SegmentId field. +func (o *SegmentMetadata) SetSegmentId(v string) { + o.SegmentId = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *SegmentMetadata) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *SegmentMetadata) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *SegmentMetadata) SetVersion(v int32) { + o.Version = &v +} + +// GetIncludedCount returns the IncludedCount field value if set, zero value otherwise. +func (o *SegmentMetadata) GetIncludedCount() int32 { + if o == nil || o.IncludedCount == nil { + var ret int32 + return ret + } + return *o.IncludedCount +} + +// GetIncludedCountOk returns a tuple with the IncludedCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetIncludedCountOk() (*int32, bool) { + if o == nil || o.IncludedCount == nil { + return nil, false + } + return o.IncludedCount, true +} + +// HasIncludedCount returns a boolean if a field has been set. +func (o *SegmentMetadata) HasIncludedCount() bool { + if o != nil && o.IncludedCount != nil { + return true + } + + return false +} + +// SetIncludedCount gets a reference to the given int32 and assigns it to the IncludedCount field. +func (o *SegmentMetadata) SetIncludedCount(v int32) { + o.IncludedCount = &v +} + +// GetExcludedCount returns the ExcludedCount field value if set, zero value otherwise. +func (o *SegmentMetadata) GetExcludedCount() int32 { + if o == nil || o.ExcludedCount == nil { + var ret int32 + return ret + } + return *o.ExcludedCount +} + +// GetExcludedCountOk returns a tuple with the ExcludedCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetExcludedCountOk() (*int32, bool) { + if o == nil || o.ExcludedCount == nil { + return nil, false + } + return o.ExcludedCount, true +} + +// HasExcludedCount returns a boolean if a field has been set. +func (o *SegmentMetadata) HasExcludedCount() bool { + if o != nil && o.ExcludedCount != nil { + return true + } + + return false +} + +// SetExcludedCount gets a reference to the given int32 and assigns it to the ExcludedCount field. +func (o *SegmentMetadata) SetExcludedCount(v int32) { + o.ExcludedCount = &v +} + +// GetLastModified returns the LastModified field value if set, zero value otherwise. +func (o *SegmentMetadata) GetLastModified() int64 { + if o == nil || o.LastModified == nil { + var ret int64 + return ret + } + return *o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetLastModifiedOk() (*int64, bool) { + if o == nil || o.LastModified == nil { + return nil, false + } + return o.LastModified, true +} + +// HasLastModified returns a boolean if a field has been set. +func (o *SegmentMetadata) HasLastModified() bool { + if o != nil && o.LastModified != nil { + return true + } + + return false +} + +// SetLastModified gets a reference to the given int64 and assigns it to the LastModified field. +func (o *SegmentMetadata) SetLastModified(v int64) { + o.LastModified = &v +} + +// GetDeleted returns the Deleted field value if set, zero value otherwise. +func (o *SegmentMetadata) GetDeleted() bool { + if o == nil || o.Deleted == nil { + var ret bool + return ret + } + return *o.Deleted +} + +// GetDeletedOk returns a tuple with the Deleted field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentMetadata) GetDeletedOk() (*bool, bool) { + if o == nil || o.Deleted == nil { + return nil, false + } + return o.Deleted, true +} + +// HasDeleted returns a boolean if a field has been set. +func (o *SegmentMetadata) HasDeleted() bool { + if o != nil && o.Deleted != nil { + return true + } + + return false +} + +// SetDeleted gets a reference to the given bool and assigns it to the Deleted field. +func (o *SegmentMetadata) SetDeleted(v bool) { + o.Deleted = &v +} + +func (o SegmentMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.EnvId != nil { + toSerialize["envId"] = o.EnvId + } + if o.SegmentId != nil { + toSerialize["segmentId"] = o.SegmentId + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + if o.IncludedCount != nil { + toSerialize["includedCount"] = o.IncludedCount + } + if o.ExcludedCount != nil { + toSerialize["excludedCount"] = o.ExcludedCount + } + if o.LastModified != nil { + toSerialize["lastModified"] = o.LastModified + } + if o.Deleted != nil { + toSerialize["deleted"] = o.Deleted + } + return json.Marshal(toSerialize) +} + +type NullableSegmentMetadata struct { + value *SegmentMetadata + isSet bool +} + +func (v NullableSegmentMetadata) Get() *SegmentMetadata { + return v.value +} + +func (v *NullableSegmentMetadata) Set(val *SegmentMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableSegmentMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableSegmentMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSegmentMetadata(val *SegmentMetadata) *NullableSegmentMetadata { + return &NullableSegmentMetadata{value: val, isSet: true} +} + +func (v NullableSegmentMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSegmentMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_target.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_target.go new file mode 100644 index 00000000..3506d3b7 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_target.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SegmentTarget struct for SegmentTarget +type SegmentTarget struct { + Values []string `json:"values,omitempty"` + ContextKind *string `json:"contextKind,omitempty"` +} + +// NewSegmentTarget instantiates a new SegmentTarget object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSegmentTarget() *SegmentTarget { + this := SegmentTarget{} + return &this +} + +// NewSegmentTargetWithDefaults instantiates a new SegmentTarget object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSegmentTargetWithDefaults() *SegmentTarget { + this := SegmentTarget{} + return &this +} + +// GetValues returns the Values field value if set, zero value otherwise. +func (o *SegmentTarget) GetValues() []string { + if o == nil || o.Values == nil { + var ret []string + return ret + } + return o.Values +} + +// GetValuesOk returns a tuple with the Values field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentTarget) GetValuesOk() ([]string, bool) { + if o == nil || o.Values == nil { + return nil, false + } + return o.Values, true +} + +// HasValues returns a boolean if a field has been set. +func (o *SegmentTarget) HasValues() bool { + if o != nil && o.Values != nil { + return true + } + + return false +} + +// SetValues gets a reference to the given []string and assigns it to the Values field. +func (o *SegmentTarget) SetValues(v []string) { + o.Values = v +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *SegmentTarget) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentTarget) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *SegmentTarget) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *SegmentTarget) SetContextKind(v string) { + o.ContextKind = &v +} + +func (o SegmentTarget) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Values != nil { + toSerialize["values"] = o.Values + } + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + return json.Marshal(toSerialize) +} + +type NullableSegmentTarget struct { + value *SegmentTarget + isSet bool +} + +func (v NullableSegmentTarget) Get() *SegmentTarget { + return v.value +} + +func (v *NullableSegmentTarget) Set(val *SegmentTarget) { + v.value = val + v.isSet = true +} + +func (v NullableSegmentTarget) IsSet() bool { + return v.isSet +} + +func (v *NullableSegmentTarget) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSegmentTarget(val *SegmentTarget) *NullableSegmentTarget { + return &NullableSegmentTarget{value: val, isSet: true} +} + +func (v NullableSegmentTarget) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSegmentTarget) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_list.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_list.go new file mode 100644 index 00000000..48d56387 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_list.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SegmentUserList struct for SegmentUserList +type SegmentUserList struct { + Add []string `json:"add,omitempty"` + Remove []string `json:"remove,omitempty"` +} + +// NewSegmentUserList instantiates a new SegmentUserList object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSegmentUserList() *SegmentUserList { + this := SegmentUserList{} + return &this +} + +// NewSegmentUserListWithDefaults instantiates a new SegmentUserList object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSegmentUserListWithDefaults() *SegmentUserList { + this := SegmentUserList{} + return &this +} + +// GetAdd returns the Add field value if set, zero value otherwise. +func (o *SegmentUserList) GetAdd() []string { + if o == nil || o.Add == nil { + var ret []string + return ret + } + return o.Add +} + +// GetAddOk returns a tuple with the Add field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentUserList) GetAddOk() ([]string, bool) { + if o == nil || o.Add == nil { + return nil, false + } + return o.Add, true +} + +// HasAdd returns a boolean if a field has been set. +func (o *SegmentUserList) HasAdd() bool { + if o != nil && o.Add != nil { + return true + } + + return false +} + +// SetAdd gets a reference to the given []string and assigns it to the Add field. +func (o *SegmentUserList) SetAdd(v []string) { + o.Add = v +} + +// GetRemove returns the Remove field value if set, zero value otherwise. +func (o *SegmentUserList) GetRemove() []string { + if o == nil || o.Remove == nil { + var ret []string + return ret + } + return o.Remove +} + +// GetRemoveOk returns a tuple with the Remove field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentUserList) GetRemoveOk() ([]string, bool) { + if o == nil || o.Remove == nil { + return nil, false + } + return o.Remove, true +} + +// HasRemove returns a boolean if a field has been set. +func (o *SegmentUserList) HasRemove() bool { + if o != nil && o.Remove != nil { + return true + } + + return false +} + +// SetRemove gets a reference to the given []string and assigns it to the Remove field. +func (o *SegmentUserList) SetRemove(v []string) { + o.Remove = v +} + +func (o SegmentUserList) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Add != nil { + toSerialize["add"] = o.Add + } + if o.Remove != nil { + toSerialize["remove"] = o.Remove + } + return json.Marshal(toSerialize) +} + +type NullableSegmentUserList struct { + value *SegmentUserList + isSet bool +} + +func (v NullableSegmentUserList) Get() *SegmentUserList { + return v.value +} + +func (v *NullableSegmentUserList) Set(val *SegmentUserList) { + v.value = val + v.isSet = true +} + +func (v NullableSegmentUserList) IsSet() bool { + return v.isSet +} + +func (v *NullableSegmentUserList) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSegmentUserList(val *SegmentUserList) *NullableSegmentUserList { + return &NullableSegmentUserList{value: val, isSet: true} +} + +func (v NullableSegmentUserList) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSegmentUserList) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_state.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_state.go new file mode 100644 index 00000000..17947b45 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_segment_user_state.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SegmentUserState struct for SegmentUserState +type SegmentUserState struct { + Included *SegmentUserList `json:"included,omitempty"` + Excluded *SegmentUserList `json:"excluded,omitempty"` +} + +// NewSegmentUserState instantiates a new SegmentUserState object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSegmentUserState() *SegmentUserState { + this := SegmentUserState{} + return &this +} + +// NewSegmentUserStateWithDefaults instantiates a new SegmentUserState object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSegmentUserStateWithDefaults() *SegmentUserState { + this := SegmentUserState{} + return &this +} + +// GetIncluded returns the Included field value if set, zero value otherwise. +func (o *SegmentUserState) GetIncluded() SegmentUserList { + if o == nil || o.Included == nil { + var ret SegmentUserList + return ret + } + return *o.Included +} + +// GetIncludedOk returns a tuple with the Included field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentUserState) GetIncludedOk() (*SegmentUserList, bool) { + if o == nil || o.Included == nil { + return nil, false + } + return o.Included, true +} + +// HasIncluded returns a boolean if a field has been set. +func (o *SegmentUserState) HasIncluded() bool { + if o != nil && o.Included != nil { + return true + } + + return false +} + +// SetIncluded gets a reference to the given SegmentUserList and assigns it to the Included field. +func (o *SegmentUserState) SetIncluded(v SegmentUserList) { + o.Included = &v +} + +// GetExcluded returns the Excluded field value if set, zero value otherwise. +func (o *SegmentUserState) GetExcluded() SegmentUserList { + if o == nil || o.Excluded == nil { + var ret SegmentUserList + return ret + } + return *o.Excluded +} + +// GetExcludedOk returns a tuple with the Excluded field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SegmentUserState) GetExcludedOk() (*SegmentUserList, bool) { + if o == nil || o.Excluded == nil { + return nil, false + } + return o.Excluded, true +} + +// HasExcluded returns a boolean if a field has been set. +func (o *SegmentUserState) HasExcluded() bool { + if o != nil && o.Excluded != nil { + return true + } + + return false +} + +// SetExcluded gets a reference to the given SegmentUserList and assigns it to the Excluded field. +func (o *SegmentUserState) SetExcluded(v SegmentUserList) { + o.Excluded = &v +} + +func (o SegmentUserState) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Included != nil { + toSerialize["included"] = o.Included + } + if o.Excluded != nil { + toSerialize["excluded"] = o.Excluded + } + return json.Marshal(toSerialize) +} + +type NullableSegmentUserState struct { + value *SegmentUserState + isSet bool +} + +func (v NullableSegmentUserState) Get() *SegmentUserState { + return v.value +} + +func (v *NullableSegmentUserState) Set(val *SegmentUserState) { + v.value = val + v.isSet = true +} + +func (v NullableSegmentUserState) IsSet() bool { + return v.isSet +} + +func (v *NullableSegmentUserState) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSegmentUserState(val *SegmentUserState) *NullableSegmentUserState { + return &NullableSegmentUserState{value: val, isSet: true} +} + +func (v NullableSegmentUserState) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSegmentUserState) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_series.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_series.go new file mode 100644 index 00000000..2cc55ab4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_series.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Series struct for Series +type Series struct { + // The timestamp + Time int64 `json:"time"` + // The value for the given timestamp + Value float32 `json:"value"` +} + +// NewSeries instantiates a new Series object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSeries(time int64, value float32) *Series { + this := Series{} + this.Time = time + this.Value = value + return &this +} + +// NewSeriesWithDefaults instantiates a new Series object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSeriesWithDefaults() *Series { + this := Series{} + return &this +} + +// GetTime returns the Time field value +func (o *Series) GetTime() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.Time +} + +// GetTimeOk returns a tuple with the Time field value +// and a boolean to check if the value has been set. +func (o *Series) GetTimeOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.Time, true +} + +// SetTime sets field value +func (o *Series) SetTime(v int64) { + o.Time = v +} + +// GetValue returns the Value field value +func (o *Series) GetValue() float32 { + if o == nil { + var ret float32 + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *Series) GetValueOk() (*float32, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *Series) SetValue(v float32) { + o.Value = v +} + +func (o Series) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["time"] = o.Time + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullableSeries struct { + value *Series + isSet bool +} + +func (v NullableSeries) Get() *Series { + return v.value +} + +func (v *NullableSeries) Set(val *Series) { + v.value = val + v.isSet = true +} + +func (v NullableSeries) IsSet() bool { + return v.isSet +} + +func (v *NullableSeries) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSeries(val *Series) *NullableSeries { + return &NullableSeries{value: val, isSet: true} +} + +func (v NullableSeries) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSeries) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_series_intervals_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_series_intervals_rep.go new file mode 100644 index 00000000..1bd9cc27 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_series_intervals_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SeriesIntervalsRep struct for SeriesIntervalsRep +type SeriesIntervalsRep struct { + // An array of timestamps and values for a given meter + Series []Series `json:"series"` + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` +} + +// NewSeriesIntervalsRep instantiates a new SeriesIntervalsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSeriesIntervalsRep(series []Series, links map[string]interface{}) *SeriesIntervalsRep { + this := SeriesIntervalsRep{} + this.Series = series + this.Links = links + return &this +} + +// NewSeriesIntervalsRepWithDefaults instantiates a new SeriesIntervalsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSeriesIntervalsRepWithDefaults() *SeriesIntervalsRep { + this := SeriesIntervalsRep{} + return &this +} + +// GetSeries returns the Series field value +func (o *SeriesIntervalsRep) GetSeries() []Series { + if o == nil { + var ret []Series + return ret + } + + return o.Series +} + +// GetSeriesOk returns a tuple with the Series field value +// and a boolean to check if the value has been set. +func (o *SeriesIntervalsRep) GetSeriesOk() ([]Series, bool) { + if o == nil { + return nil, false + } + return o.Series, true +} + +// SetSeries sets field value +func (o *SeriesIntervalsRep) SetSeries(v []Series) { + o.Series = v +} + +// GetLinks returns the Links field value +func (o *SeriesIntervalsRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *SeriesIntervalsRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *SeriesIntervalsRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +func (o SeriesIntervalsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["series"] = o.Series + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableSeriesIntervalsRep struct { + value *SeriesIntervalsRep + isSet bool +} + +func (v NullableSeriesIntervalsRep) Get() *SeriesIntervalsRep { + return v.value +} + +func (v *NullableSeriesIntervalsRep) Set(val *SeriesIntervalsRep) { + v.value = val + v.isSet = true +} + +func (v NullableSeriesIntervalsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSeriesIntervalsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSeriesIntervalsRep(val *SeriesIntervalsRep) *NullableSeriesIntervalsRep { + return &NullableSeriesIntervalsRep{value: val, isSet: true} +} + +func (v NullableSeriesIntervalsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSeriesIntervalsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_series_list_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_series_list_rep.go new file mode 100644 index 00000000..f588b554 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_series_list_rep.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SeriesListRep struct for SeriesListRep +type SeriesListRep struct { + // The location and content type of related resources + Links map[string]interface{} `json:"_links"` + // Metadata about each series + Metadata []map[string]interface{} `json:"metadata"` + // An array of data points with timestamps. Each element of the array is an object with a 'time' field, whose value is the timestamp, and one or more key fields. If there are multiple key fields, they are labeled '0', '1', and so on, and are explained in the metadata. + Series []map[string]int32 `json:"series"` +} + +// NewSeriesListRep instantiates a new SeriesListRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSeriesListRep(links map[string]interface{}, metadata []map[string]interface{}, series []map[string]int32) *SeriesListRep { + this := SeriesListRep{} + this.Links = links + this.Metadata = metadata + this.Series = series + return &this +} + +// NewSeriesListRepWithDefaults instantiates a new SeriesListRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSeriesListRepWithDefaults() *SeriesListRep { + this := SeriesListRep{} + return &this +} + +// GetLinks returns the Links field value +func (o *SeriesListRep) GetLinks() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *SeriesListRep) GetLinksOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Links, true +} + +// SetLinks sets field value +func (o *SeriesListRep) SetLinks(v map[string]interface{}) { + o.Links = v +} + +// GetMetadata returns the Metadata field value +func (o *SeriesListRep) GetMetadata() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Metadata +} + +// GetMetadataOk returns a tuple with the Metadata field value +// and a boolean to check if the value has been set. +func (o *SeriesListRep) GetMetadataOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Metadata, true +} + +// SetMetadata sets field value +func (o *SeriesListRep) SetMetadata(v []map[string]interface{}) { + o.Metadata = v +} + +// GetSeries returns the Series field value +func (o *SeriesListRep) GetSeries() []map[string]int32 { + if o == nil { + var ret []map[string]int32 + return ret + } + + return o.Series +} + +// GetSeriesOk returns a tuple with the Series field value +// and a boolean to check if the value has been set. +func (o *SeriesListRep) GetSeriesOk() ([]map[string]int32, bool) { + if o == nil { + return nil, false + } + return o.Series, true +} + +// SetSeries sets field value +func (o *SeriesListRep) SetSeries(v []map[string]int32) { + o.Series = v +} + +func (o SeriesListRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["metadata"] = o.Metadata + } + if true { + toSerialize["series"] = o.Series + } + return json.Marshal(toSerialize) +} + +type NullableSeriesListRep struct { + value *SeriesListRep + isSet bool +} + +func (v NullableSeriesListRep) Get() *SeriesListRep { + return v.value +} + +func (v *NullableSeriesListRep) Set(val *SeriesListRep) { + v.value = val + v.isSet = true +} + +func (v NullableSeriesListRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSeriesListRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSeriesListRep(val *SeriesListRep) *NullableSeriesListRep { + return &NullableSeriesListRep{value: val, isSet: true} +} + +func (v NullableSeriesListRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSeriesListRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_simple_holdout_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_simple_holdout_rep.go new file mode 100644 index 00000000..c124934f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_simple_holdout_rep.go @@ -0,0 +1,332 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SimpleHoldoutRep struct for SimpleHoldoutRep +type SimpleHoldoutRep struct { + Id *string `json:"_id,omitempty"` + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + CreatedAt *int64 `json:"createdAt,omitempty"` + UpdatedAt *int64 `json:"updatedAt,omitempty"` + Experiments []RelatedExperimentRep `json:"experiments,omitempty"` +} + +// NewSimpleHoldoutRep instantiates a new SimpleHoldoutRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSimpleHoldoutRep() *SimpleHoldoutRep { + this := SimpleHoldoutRep{} + return &this +} + +// NewSimpleHoldoutRepWithDefaults instantiates a new SimpleHoldoutRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSimpleHoldoutRepWithDefaults() *SimpleHoldoutRep { + this := SimpleHoldoutRep{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *SimpleHoldoutRep) SetId(v string) { + o.Id = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *SimpleHoldoutRep) SetKey(v string) { + o.Key = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *SimpleHoldoutRep) SetName(v string) { + o.Name = &v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *SimpleHoldoutRep) SetStatus(v string) { + o.Status = &v +} + +// GetCreatedAt returns the CreatedAt field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetCreatedAt() int64 { + if o == nil || o.CreatedAt == nil { + var ret int64 + return ret + } + return *o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetCreatedAtOk() (*int64, bool) { + if o == nil || o.CreatedAt == nil { + return nil, false + } + return o.CreatedAt, true +} + +// HasCreatedAt returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasCreatedAt() bool { + if o != nil && o.CreatedAt != nil { + return true + } + + return false +} + +// SetCreatedAt gets a reference to the given int64 and assigns it to the CreatedAt field. +func (o *SimpleHoldoutRep) SetCreatedAt(v int64) { + o.CreatedAt = &v +} + +// GetUpdatedAt returns the UpdatedAt field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetUpdatedAt() int64 { + if o == nil || o.UpdatedAt == nil { + var ret int64 + return ret + } + return *o.UpdatedAt +} + +// GetUpdatedAtOk returns a tuple with the UpdatedAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetUpdatedAtOk() (*int64, bool) { + if o == nil || o.UpdatedAt == nil { + return nil, false + } + return o.UpdatedAt, true +} + +// HasUpdatedAt returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasUpdatedAt() bool { + if o != nil && o.UpdatedAt != nil { + return true + } + + return false +} + +// SetUpdatedAt gets a reference to the given int64 and assigns it to the UpdatedAt field. +func (o *SimpleHoldoutRep) SetUpdatedAt(v int64) { + o.UpdatedAt = &v +} + +// GetExperiments returns the Experiments field value if set, zero value otherwise. +func (o *SimpleHoldoutRep) GetExperiments() []RelatedExperimentRep { + if o == nil || o.Experiments == nil { + var ret []RelatedExperimentRep + return ret + } + return o.Experiments +} + +// GetExperimentsOk returns a tuple with the Experiments field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SimpleHoldoutRep) GetExperimentsOk() ([]RelatedExperimentRep, bool) { + if o == nil || o.Experiments == nil { + return nil, false + } + return o.Experiments, true +} + +// HasExperiments returns a boolean if a field has been set. +func (o *SimpleHoldoutRep) HasExperiments() bool { + if o != nil && o.Experiments != nil { + return true + } + + return false +} + +// SetExperiments gets a reference to the given []RelatedExperimentRep and assigns it to the Experiments field. +func (o *SimpleHoldoutRep) SetExperiments(v []RelatedExperimentRep) { + o.Experiments = v +} + +func (o SimpleHoldoutRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.CreatedAt != nil { + toSerialize["createdAt"] = o.CreatedAt + } + if o.UpdatedAt != nil { + toSerialize["updatedAt"] = o.UpdatedAt + } + if o.Experiments != nil { + toSerialize["experiments"] = o.Experiments + } + return json.Marshal(toSerialize) +} + +type NullableSimpleHoldoutRep struct { + value *SimpleHoldoutRep + isSet bool +} + +func (v NullableSimpleHoldoutRep) Get() *SimpleHoldoutRep { + return v.value +} + +func (v *NullableSimpleHoldoutRep) Set(val *SimpleHoldoutRep) { + v.value = val + v.isSet = true +} + +func (v NullableSimpleHoldoutRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSimpleHoldoutRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSimpleHoldoutRep(val *SimpleHoldoutRep) *NullableSimpleHoldoutRep { + return &NullableSimpleHoldoutRep{value: val, isSet: true} +} + +func (v NullableSimpleHoldoutRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSimpleHoldoutRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_sliced_results_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_sliced_results_rep.go new file mode 100644 index 00000000..e4c116ac --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_sliced_results_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SlicedResultsRep struct for SlicedResultsRep +type SlicedResultsRep struct { + // An attribute that results are sliced by + Attribute *string `json:"attribute,omitempty"` + // Attribute Value for 'attribute' + AttributeValue *string `json:"attributeValue,omitempty"` + // A list of the results for each treatment + TreatmentResults []TreatmentResultRep `json:"treatmentResults,omitempty"` +} + +// NewSlicedResultsRep instantiates a new SlicedResultsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSlicedResultsRep() *SlicedResultsRep { + this := SlicedResultsRep{} + return &this +} + +// NewSlicedResultsRepWithDefaults instantiates a new SlicedResultsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSlicedResultsRepWithDefaults() *SlicedResultsRep { + this := SlicedResultsRep{} + return &this +} + +// GetAttribute returns the Attribute field value if set, zero value otherwise. +func (o *SlicedResultsRep) GetAttribute() string { + if o == nil || o.Attribute == nil { + var ret string + return ret + } + return *o.Attribute +} + +// GetAttributeOk returns a tuple with the Attribute field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SlicedResultsRep) GetAttributeOk() (*string, bool) { + if o == nil || o.Attribute == nil { + return nil, false + } + return o.Attribute, true +} + +// HasAttribute returns a boolean if a field has been set. +func (o *SlicedResultsRep) HasAttribute() bool { + if o != nil && o.Attribute != nil { + return true + } + + return false +} + +// SetAttribute gets a reference to the given string and assigns it to the Attribute field. +func (o *SlicedResultsRep) SetAttribute(v string) { + o.Attribute = &v +} + +// GetAttributeValue returns the AttributeValue field value if set, zero value otherwise. +func (o *SlicedResultsRep) GetAttributeValue() string { + if o == nil || o.AttributeValue == nil { + var ret string + return ret + } + return *o.AttributeValue +} + +// GetAttributeValueOk returns a tuple with the AttributeValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SlicedResultsRep) GetAttributeValueOk() (*string, bool) { + if o == nil || o.AttributeValue == nil { + return nil, false + } + return o.AttributeValue, true +} + +// HasAttributeValue returns a boolean if a field has been set. +func (o *SlicedResultsRep) HasAttributeValue() bool { + if o != nil && o.AttributeValue != nil { + return true + } + + return false +} + +// SetAttributeValue gets a reference to the given string and assigns it to the AttributeValue field. +func (o *SlicedResultsRep) SetAttributeValue(v string) { + o.AttributeValue = &v +} + +// GetTreatmentResults returns the TreatmentResults field value if set, zero value otherwise. +func (o *SlicedResultsRep) GetTreatmentResults() []TreatmentResultRep { + if o == nil || o.TreatmentResults == nil { + var ret []TreatmentResultRep + return ret + } + return o.TreatmentResults +} + +// GetTreatmentResultsOk returns a tuple with the TreatmentResults field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SlicedResultsRep) GetTreatmentResultsOk() ([]TreatmentResultRep, bool) { + if o == nil || o.TreatmentResults == nil { + return nil, false + } + return o.TreatmentResults, true +} + +// HasTreatmentResults returns a boolean if a field has been set. +func (o *SlicedResultsRep) HasTreatmentResults() bool { + if o != nil && o.TreatmentResults != nil { + return true + } + + return false +} + +// SetTreatmentResults gets a reference to the given []TreatmentResultRep and assigns it to the TreatmentResults field. +func (o *SlicedResultsRep) SetTreatmentResults(v []TreatmentResultRep) { + o.TreatmentResults = v +} + +func (o SlicedResultsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Attribute != nil { + toSerialize["attribute"] = o.Attribute + } + if o.AttributeValue != nil { + toSerialize["attributeValue"] = o.AttributeValue + } + if o.TreatmentResults != nil { + toSerialize["treatmentResults"] = o.TreatmentResults + } + return json.Marshal(toSerialize) +} + +type NullableSlicedResultsRep struct { + value *SlicedResultsRep + isSet bool +} + +func (v NullableSlicedResultsRep) Get() *SlicedResultsRep { + return v.value +} + +func (v *NullableSlicedResultsRep) Set(val *SlicedResultsRep) { + v.value = val + v.isSet = true +} + +func (v NullableSlicedResultsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSlicedResultsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSlicedResultsRep(val *SlicedResultsRep) *NullableSlicedResultsRep { + return &NullableSlicedResultsRep{value: val, isSet: true} +} + +func (v NullableSlicedResultsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSlicedResultsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_source_env.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_source_env.go new file mode 100644 index 00000000..7c2687b3 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_source_env.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SourceEnv struct for SourceEnv +type SourceEnv struct { + // The key of the source environment to clone from + Key *string `json:"key,omitempty"` + // (Optional) The version number of the source environment to clone from. Used for optimistic locking + Version *int32 `json:"version,omitempty"` +} + +// NewSourceEnv instantiates a new SourceEnv object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSourceEnv() *SourceEnv { + this := SourceEnv{} + return &this +} + +// NewSourceEnvWithDefaults instantiates a new SourceEnv object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSourceEnvWithDefaults() *SourceEnv { + this := SourceEnv{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *SourceEnv) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SourceEnv) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *SourceEnv) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *SourceEnv) SetKey(v string) { + o.Key = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *SourceEnv) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SourceEnv) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *SourceEnv) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *SourceEnv) SetVersion(v int32) { + o.Version = &v +} + +func (o SourceEnv) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableSourceEnv struct { + value *SourceEnv + isSet bool +} + +func (v NullableSourceEnv) Get() *SourceEnv { + return v.value +} + +func (v *NullableSourceEnv) Set(val *SourceEnv) { + v.value = val + v.isSet = true +} + +func (v NullableSourceEnv) IsSet() bool { + return v.isSet +} + +func (v *NullableSourceEnv) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSourceEnv(val *SourceEnv) *NullableSourceEnv { + return &NullableSourceEnv{value: val, isSet: true} +} + +func (v NullableSourceEnv) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSourceEnv) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_source_flag.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_source_flag.go new file mode 100644 index 00000000..db00ca6e --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_source_flag.go @@ -0,0 +1,147 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SourceFlag struct for SourceFlag +type SourceFlag struct { + // The environment key for the source environment + Key string `json:"key"` + // The version of the source flag from which to copy + Version *int32 `json:"version,omitempty"` +} + +// NewSourceFlag instantiates a new SourceFlag object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSourceFlag(key string) *SourceFlag { + this := SourceFlag{} + this.Key = key + return &this +} + +// NewSourceFlagWithDefaults instantiates a new SourceFlag object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSourceFlagWithDefaults() *SourceFlag { + this := SourceFlag{} + return &this +} + +// GetKey returns the Key field value +func (o *SourceFlag) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *SourceFlag) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *SourceFlag) SetKey(v string) { + o.Key = v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *SourceFlag) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SourceFlag) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *SourceFlag) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *SourceFlag) SetVersion(v int32) { + o.Version = &v +} + +func (o SourceFlag) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["key"] = o.Key + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableSourceFlag struct { + value *SourceFlag + isSet bool +} + +func (v NullableSourceFlag) Get() *SourceFlag { + return v.value +} + +func (v *NullableSourceFlag) Set(val *SourceFlag) { + v.value = val + v.isSet = true +} + +func (v NullableSourceFlag) IsSet() bool { + return v.isSet +} + +func (v *NullableSourceFlag) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSourceFlag(val *SourceFlag) *NullableSourceFlag { + return &NullableSourceFlag{value: val, isSet: true} +} + +func (v NullableSourceFlag) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSourceFlag) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_input.go new file mode 100644 index 00000000..eeb4fa83 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_input.go @@ -0,0 +1,227 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StageInput struct for StageInput +type StageInput struct { + // The stage name + Name *string `json:"name,omitempty"` + // Whether to execute the conditions in sequence for the given stage + ExecuteConditionsInSequence *bool `json:"executeConditionsInSequence,omitempty"` + // An array of conditions for the stage + Conditions []ConditionInput `json:"conditions,omitempty"` + Action *ActionInput `json:"action,omitempty"` +} + +// NewStageInput instantiates a new StageInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStageInput() *StageInput { + this := StageInput{} + return &this +} + +// NewStageInputWithDefaults instantiates a new StageInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStageInputWithDefaults() *StageInput { + this := StageInput{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *StageInput) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StageInput) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *StageInput) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *StageInput) SetName(v string) { + o.Name = &v +} + +// GetExecuteConditionsInSequence returns the ExecuteConditionsInSequence field value if set, zero value otherwise. +func (o *StageInput) GetExecuteConditionsInSequence() bool { + if o == nil || o.ExecuteConditionsInSequence == nil { + var ret bool + return ret + } + return *o.ExecuteConditionsInSequence +} + +// GetExecuteConditionsInSequenceOk returns a tuple with the ExecuteConditionsInSequence field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StageInput) GetExecuteConditionsInSequenceOk() (*bool, bool) { + if o == nil || o.ExecuteConditionsInSequence == nil { + return nil, false + } + return o.ExecuteConditionsInSequence, true +} + +// HasExecuteConditionsInSequence returns a boolean if a field has been set. +func (o *StageInput) HasExecuteConditionsInSequence() bool { + if o != nil && o.ExecuteConditionsInSequence != nil { + return true + } + + return false +} + +// SetExecuteConditionsInSequence gets a reference to the given bool and assigns it to the ExecuteConditionsInSequence field. +func (o *StageInput) SetExecuteConditionsInSequence(v bool) { + o.ExecuteConditionsInSequence = &v +} + +// GetConditions returns the Conditions field value if set, zero value otherwise. +func (o *StageInput) GetConditions() []ConditionInput { + if o == nil || o.Conditions == nil { + var ret []ConditionInput + return ret + } + return o.Conditions +} + +// GetConditionsOk returns a tuple with the Conditions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StageInput) GetConditionsOk() ([]ConditionInput, bool) { + if o == nil || o.Conditions == nil { + return nil, false + } + return o.Conditions, true +} + +// HasConditions returns a boolean if a field has been set. +func (o *StageInput) HasConditions() bool { + if o != nil && o.Conditions != nil { + return true + } + + return false +} + +// SetConditions gets a reference to the given []ConditionInput and assigns it to the Conditions field. +func (o *StageInput) SetConditions(v []ConditionInput) { + o.Conditions = v +} + +// GetAction returns the Action field value if set, zero value otherwise. +func (o *StageInput) GetAction() ActionInput { + if o == nil || o.Action == nil { + var ret ActionInput + return ret + } + return *o.Action +} + +// GetActionOk returns a tuple with the Action field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StageInput) GetActionOk() (*ActionInput, bool) { + if o == nil || o.Action == nil { + return nil, false + } + return o.Action, true +} + +// HasAction returns a boolean if a field has been set. +func (o *StageInput) HasAction() bool { + if o != nil && o.Action != nil { + return true + } + + return false +} + +// SetAction gets a reference to the given ActionInput and assigns it to the Action field. +func (o *StageInput) SetAction(v ActionInput) { + o.Action = &v +} + +func (o StageInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.ExecuteConditionsInSequence != nil { + toSerialize["executeConditionsInSequence"] = o.ExecuteConditionsInSequence + } + if o.Conditions != nil { + toSerialize["conditions"] = o.Conditions + } + if o.Action != nil { + toSerialize["action"] = o.Action + } + return json.Marshal(toSerialize) +} + +type NullableStageInput struct { + value *StageInput + isSet bool +} + +func (v NullableStageInput) Get() *StageInput { + return v.value +} + +func (v *NullableStageInput) Set(val *StageInput) { + v.value = val + v.isSet = true +} + +func (v NullableStageInput) IsSet() bool { + return v.isSet +} + +func (v *NullableStageInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStageInput(val *StageInput) *NullableStageInput { + return &NullableStageInput{value: val, isSet: true} +} + +func (v NullableStageInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStageInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_output.go new file mode 100644 index 00000000..e24d00e8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_stage_output.go @@ -0,0 +1,235 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StageOutput struct for StageOutput +type StageOutput struct { + // The ID of this stage + Id string `json:"_id"` + // The stage name + Name *string `json:"name,omitempty"` + // An array of conditions for the stage + Conditions []ConditionOutput `json:"conditions"` + Action ActionOutput `json:"action"` + Execution ExecutionOutput `json:"_execution"` +} + +// NewStageOutput instantiates a new StageOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStageOutput(id string, conditions []ConditionOutput, action ActionOutput, execution ExecutionOutput) *StageOutput { + this := StageOutput{} + this.Id = id + this.Conditions = conditions + this.Action = action + this.Execution = execution + return &this +} + +// NewStageOutputWithDefaults instantiates a new StageOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStageOutputWithDefaults() *StageOutput { + this := StageOutput{} + return &this +} + +// GetId returns the Id field value +func (o *StageOutput) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *StageOutput) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *StageOutput) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *StageOutput) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StageOutput) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *StageOutput) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *StageOutput) SetName(v string) { + o.Name = &v +} + +// GetConditions returns the Conditions field value +func (o *StageOutput) GetConditions() []ConditionOutput { + if o == nil { + var ret []ConditionOutput + return ret + } + + return o.Conditions +} + +// GetConditionsOk returns a tuple with the Conditions field value +// and a boolean to check if the value has been set. +func (o *StageOutput) GetConditionsOk() ([]ConditionOutput, bool) { + if o == nil { + return nil, false + } + return o.Conditions, true +} + +// SetConditions sets field value +func (o *StageOutput) SetConditions(v []ConditionOutput) { + o.Conditions = v +} + +// GetAction returns the Action field value +func (o *StageOutput) GetAction() ActionOutput { + if o == nil { + var ret ActionOutput + return ret + } + + return o.Action +} + +// GetActionOk returns a tuple with the Action field value +// and a boolean to check if the value has been set. +func (o *StageOutput) GetActionOk() (*ActionOutput, bool) { + if o == nil { + return nil, false + } + return &o.Action, true +} + +// SetAction sets field value +func (o *StageOutput) SetAction(v ActionOutput) { + o.Action = v +} + +// GetExecution returns the Execution field value +func (o *StageOutput) GetExecution() ExecutionOutput { + if o == nil { + var ret ExecutionOutput + return ret + } + + return o.Execution +} + +// GetExecutionOk returns a tuple with the Execution field value +// and a boolean to check if the value has been set. +func (o *StageOutput) GetExecutionOk() (*ExecutionOutput, bool) { + if o == nil { + return nil, false + } + return &o.Execution, true +} + +// SetExecution sets field value +func (o *StageOutput) SetExecution(v ExecutionOutput) { + o.Execution = v +} + +func (o StageOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["conditions"] = o.Conditions + } + if true { + toSerialize["action"] = o.Action + } + if true { + toSerialize["_execution"] = o.Execution + } + return json.Marshal(toSerialize) +} + +type NullableStageOutput struct { + value *StageOutput + isSet bool +} + +func (v NullableStageOutput) Get() *StageOutput { + return v.value +} + +func (v *NullableStageOutput) Set(val *StageOutput) { + v.value = val + v.isSet = true +} + +func (v NullableStageOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableStageOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStageOutput(val *StageOutput) *NullableStageOutput { + return &NullableStageOutput{value: val, isSet: true} +} + +func (v NullableStageOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStageOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_statement.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_statement.go new file mode 100644 index 00000000..0e66fde8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_statement.go @@ -0,0 +1,258 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Statement struct for Statement +type Statement struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources and notActions fields must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions and notResources fields must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` +} + +// NewStatement instantiates a new Statement object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatement(effect string) *Statement { + this := Statement{} + this.Effect = effect + return &this +} + +// NewStatementWithDefaults instantiates a new Statement object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatementWithDefaults() *Statement { + this := Statement{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *Statement) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Statement) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *Statement) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *Statement) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *Statement) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Statement) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *Statement) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *Statement) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *Statement) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Statement) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *Statement) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *Statement) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *Statement) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Statement) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *Statement) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *Statement) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *Statement) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *Statement) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *Statement) SetEffect(v string) { + o.Effect = v +} + +func (o Statement) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + return json.Marshal(toSerialize) +} + +type NullableStatement struct { + value *Statement + isSet bool +} + +func (v NullableStatement) Get() *Statement { + return v.value +} + +func (v *NullableStatement) Set(val *Statement) { + v.value = val + v.isSet = true +} + +func (v NullableStatement) IsSet() bool { + return v.isSet +} + +func (v *NullableStatement) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatement(val *Statement) *NullableStatement { + return &NullableStatement{value: val, isSet: true} +} + +func (v NullableStatement) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatement) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_statement_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_statement_post.go new file mode 100644 index 00000000..4c0f631c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_statement_post.go @@ -0,0 +1,258 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatementPost struct for StatementPost +type StatementPost struct { + // Resource specifier strings + Resources []string `json:"resources,omitempty"` + // Targeted resources are the resources NOT in this list. The resources field must be empty to use this field. + NotResources []string `json:"notResources,omitempty"` + // Actions to perform on a resource + Actions []string `json:"actions,omitempty"` + // Targeted actions are the actions NOT in this list. The actions field must be empty to use this field. + NotActions []string `json:"notActions,omitempty"` + // Whether this statement should allow or deny actions on the resources. + Effect string `json:"effect"` +} + +// NewStatementPost instantiates a new StatementPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatementPost(effect string) *StatementPost { + this := StatementPost{} + this.Effect = effect + return &this +} + +// NewStatementPostWithDefaults instantiates a new StatementPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatementPostWithDefaults() *StatementPost { + this := StatementPost{} + return &this +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *StatementPost) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatementPost) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *StatementPost) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *StatementPost) SetResources(v []string) { + o.Resources = v +} + +// GetNotResources returns the NotResources field value if set, zero value otherwise. +func (o *StatementPost) GetNotResources() []string { + if o == nil || o.NotResources == nil { + var ret []string + return ret + } + return o.NotResources +} + +// GetNotResourcesOk returns a tuple with the NotResources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatementPost) GetNotResourcesOk() ([]string, bool) { + if o == nil || o.NotResources == nil { + return nil, false + } + return o.NotResources, true +} + +// HasNotResources returns a boolean if a field has been set. +func (o *StatementPost) HasNotResources() bool { + if o != nil && o.NotResources != nil { + return true + } + + return false +} + +// SetNotResources gets a reference to the given []string and assigns it to the NotResources field. +func (o *StatementPost) SetNotResources(v []string) { + o.NotResources = v +} + +// GetActions returns the Actions field value if set, zero value otherwise. +func (o *StatementPost) GetActions() []string { + if o == nil || o.Actions == nil { + var ret []string + return ret + } + return o.Actions +} + +// GetActionsOk returns a tuple with the Actions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatementPost) GetActionsOk() ([]string, bool) { + if o == nil || o.Actions == nil { + return nil, false + } + return o.Actions, true +} + +// HasActions returns a boolean if a field has been set. +func (o *StatementPost) HasActions() bool { + if o != nil && o.Actions != nil { + return true + } + + return false +} + +// SetActions gets a reference to the given []string and assigns it to the Actions field. +func (o *StatementPost) SetActions(v []string) { + o.Actions = v +} + +// GetNotActions returns the NotActions field value if set, zero value otherwise. +func (o *StatementPost) GetNotActions() []string { + if o == nil || o.NotActions == nil { + var ret []string + return ret + } + return o.NotActions +} + +// GetNotActionsOk returns a tuple with the NotActions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatementPost) GetNotActionsOk() ([]string, bool) { + if o == nil || o.NotActions == nil { + return nil, false + } + return o.NotActions, true +} + +// HasNotActions returns a boolean if a field has been set. +func (o *StatementPost) HasNotActions() bool { + if o != nil && o.NotActions != nil { + return true + } + + return false +} + +// SetNotActions gets a reference to the given []string and assigns it to the NotActions field. +func (o *StatementPost) SetNotActions(v []string) { + o.NotActions = v +} + +// GetEffect returns the Effect field value +func (o *StatementPost) GetEffect() string { + if o == nil { + var ret string + return ret + } + + return o.Effect +} + +// GetEffectOk returns a tuple with the Effect field value +// and a boolean to check if the value has been set. +func (o *StatementPost) GetEffectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Effect, true +} + +// SetEffect sets field value +func (o *StatementPost) SetEffect(v string) { + o.Effect = v +} + +func (o StatementPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + if o.NotResources != nil { + toSerialize["notResources"] = o.NotResources + } + if o.Actions != nil { + toSerialize["actions"] = o.Actions + } + if o.NotActions != nil { + toSerialize["notActions"] = o.NotActions + } + if true { + toSerialize["effect"] = o.Effect + } + return json.Marshal(toSerialize) +} + +type NullableStatementPost struct { + value *StatementPost + isSet bool +} + +func (v NullableStatementPost) Get() *StatementPost { + return v.value +} + +func (v *NullableStatementPost) Set(val *StatementPost) { + v.value = val + v.isSet = true +} + +func (v NullableStatementPost) IsSet() bool { + return v.isSet +} + +func (v *NullableStatementPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatementPost(val *StatementPost) *NullableStatementPost { + return &NullableStatementPost{value: val, isSet: true} +} + +func (v NullableStatementPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatementPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_collection_rep.go new file mode 100644 index 00000000..d23c8578 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_collection_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatisticCollectionRep struct for StatisticCollectionRep +type StatisticCollectionRep struct { + // A map of flag keys to a list of code reference statistics for each code repository in which the flag key appears + Flags map[string][]StatisticRep `json:"flags"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewStatisticCollectionRep instantiates a new StatisticCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatisticCollectionRep(flags map[string][]StatisticRep, links map[string]Link) *StatisticCollectionRep { + this := StatisticCollectionRep{} + this.Flags = flags + this.Links = links + return &this +} + +// NewStatisticCollectionRepWithDefaults instantiates a new StatisticCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatisticCollectionRepWithDefaults() *StatisticCollectionRep { + this := StatisticCollectionRep{} + return &this +} + +// GetFlags returns the Flags field value +func (o *StatisticCollectionRep) GetFlags() map[string][]StatisticRep { + if o == nil { + var ret map[string][]StatisticRep + return ret + } + + return o.Flags +} + +// GetFlagsOk returns a tuple with the Flags field value +// and a boolean to check if the value has been set. +func (o *StatisticCollectionRep) GetFlagsOk() (*map[string][]StatisticRep, bool) { + if o == nil { + return nil, false + } + return &o.Flags, true +} + +// SetFlags sets field value +func (o *StatisticCollectionRep) SetFlags(v map[string][]StatisticRep) { + o.Flags = v +} + +// GetLinks returns the Links field value +func (o *StatisticCollectionRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *StatisticCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *StatisticCollectionRep) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o StatisticCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["flags"] = o.Flags + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableStatisticCollectionRep struct { + value *StatisticCollectionRep + isSet bool +} + +func (v NullableStatisticCollectionRep) Get() *StatisticCollectionRep { + return v.value +} + +func (v *NullableStatisticCollectionRep) Set(val *StatisticCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableStatisticCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableStatisticCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatisticCollectionRep(val *StatisticCollectionRep) *NullableStatisticCollectionRep { + return &NullableStatisticCollectionRep{value: val, isSet: true} +} + +func (v NullableStatisticCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatisticCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_rep.go new file mode 100644 index 00000000..5d6119e6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistic_rep.go @@ -0,0 +1,386 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatisticRep struct for StatisticRep +type StatisticRep struct { + // The repository name + Name string `json:"name"` + // The type of repository + Type string `json:"type"` + // A URL to access the repository + SourceLink string `json:"sourceLink"` + // The repository's default branch + DefaultBranch string `json:"defaultBranch"` + // Whether or not a repository is enabled for code reference scanning + Enabled bool `json:"enabled"` + // The version of the repository's saved information + Version int32 `json:"version"` + // The number of code reference hunks in which the flag appears in this repository + HunkCount int32 `json:"hunkCount"` + // The number of files in which the flag appears in this repository + FileCount int32 `json:"fileCount"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + LatestCommitTime *int64 `json:"latestCommitTime,omitempty"` +} + +// NewStatisticRep instantiates a new StatisticRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatisticRep(name string, type_ string, sourceLink string, defaultBranch string, enabled bool, version int32, hunkCount int32, fileCount int32, links map[string]Link) *StatisticRep { + this := StatisticRep{} + this.Name = name + this.Type = type_ + this.SourceLink = sourceLink + this.DefaultBranch = defaultBranch + this.Enabled = enabled + this.Version = version + this.HunkCount = hunkCount + this.FileCount = fileCount + this.Links = links + return &this +} + +// NewStatisticRepWithDefaults instantiates a new StatisticRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatisticRepWithDefaults() *StatisticRep { + this := StatisticRep{} + return &this +} + +// GetName returns the Name field value +func (o *StatisticRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *StatisticRep) SetName(v string) { + o.Name = v +} + +// GetType returns the Type field value +func (o *StatisticRep) GetType() string { + if o == nil { + var ret string + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *StatisticRep) SetType(v string) { + o.Type = v +} + +// GetSourceLink returns the SourceLink field value +func (o *StatisticRep) GetSourceLink() string { + if o == nil { + var ret string + return ret + } + + return o.SourceLink +} + +// GetSourceLinkOk returns a tuple with the SourceLink field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetSourceLinkOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.SourceLink, true +} + +// SetSourceLink sets field value +func (o *StatisticRep) SetSourceLink(v string) { + o.SourceLink = v +} + +// GetDefaultBranch returns the DefaultBranch field value +func (o *StatisticRep) GetDefaultBranch() string { + if o == nil { + var ret string + return ret + } + + return o.DefaultBranch +} + +// GetDefaultBranchOk returns a tuple with the DefaultBranch field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetDefaultBranchOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.DefaultBranch, true +} + +// SetDefaultBranch sets field value +func (o *StatisticRep) SetDefaultBranch(v string) { + o.DefaultBranch = v +} + +// GetEnabled returns the Enabled field value +func (o *StatisticRep) GetEnabled() bool { + if o == nil { + var ret bool + return ret + } + + return o.Enabled +} + +// GetEnabledOk returns a tuple with the Enabled field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetEnabledOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Enabled, true +} + +// SetEnabled sets field value +func (o *StatisticRep) SetEnabled(v bool) { + o.Enabled = v +} + +// GetVersion returns the Version field value +func (o *StatisticRep) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *StatisticRep) SetVersion(v int32) { + o.Version = v +} + +// GetHunkCount returns the HunkCount field value +func (o *StatisticRep) GetHunkCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.HunkCount +} + +// GetHunkCountOk returns a tuple with the HunkCount field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetHunkCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.HunkCount, true +} + +// SetHunkCount sets field value +func (o *StatisticRep) SetHunkCount(v int32) { + o.HunkCount = v +} + +// GetFileCount returns the FileCount field value +func (o *StatisticRep) GetFileCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.FileCount +} + +// GetFileCountOk returns a tuple with the FileCount field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetFileCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.FileCount, true +} + +// SetFileCount sets field value +func (o *StatisticRep) SetFileCount(v int32) { + o.FileCount = v +} + +// GetLinks returns the Links field value +func (o *StatisticRep) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *StatisticRep) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetLatestCommitTime returns the LatestCommitTime field value if set, zero value otherwise. +func (o *StatisticRep) GetLatestCommitTime() int64 { + if o == nil || o.LatestCommitTime == nil { + var ret int64 + return ret + } + return *o.LatestCommitTime +} + +// GetLatestCommitTimeOk returns a tuple with the LatestCommitTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatisticRep) GetLatestCommitTimeOk() (*int64, bool) { + if o == nil || o.LatestCommitTime == nil { + return nil, false + } + return o.LatestCommitTime, true +} + +// HasLatestCommitTime returns a boolean if a field has been set. +func (o *StatisticRep) HasLatestCommitTime() bool { + if o != nil && o.LatestCommitTime != nil { + return true + } + + return false +} + +// SetLatestCommitTime gets a reference to the given int64 and assigns it to the LatestCommitTime field. +func (o *StatisticRep) SetLatestCommitTime(v int64) { + o.LatestCommitTime = &v +} + +func (o StatisticRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["type"] = o.Type + } + if true { + toSerialize["sourceLink"] = o.SourceLink + } + if true { + toSerialize["defaultBranch"] = o.DefaultBranch + } + if true { + toSerialize["enabled"] = o.Enabled + } + if true { + toSerialize["version"] = o.Version + } + if true { + toSerialize["hunkCount"] = o.HunkCount + } + if true { + toSerialize["fileCount"] = o.FileCount + } + if true { + toSerialize["_links"] = o.Links + } + if o.LatestCommitTime != nil { + toSerialize["latestCommitTime"] = o.LatestCommitTime + } + return json.Marshal(toSerialize) +} + +type NullableStatisticRep struct { + value *StatisticRep + isSet bool +} + +func (v NullableStatisticRep) Get() *StatisticRep { + return v.value +} + +func (v *NullableStatisticRep) Set(val *StatisticRep) { + v.value = val + v.isSet = true +} + +func (v NullableStatisticRep) IsSet() bool { + return v.isSet +} + +func (v *NullableStatisticRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatisticRep(val *StatisticRep) *NullableStatisticRep { + return &NullableStatisticRep{value: val, isSet: true} +} + +func (v NullableStatisticRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatisticRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_statistics_root.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistics_root.go new file mode 100644 index 00000000..68e5b995 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_statistics_root.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatisticsRoot struct for StatisticsRoot +type StatisticsRoot struct { + // The location and content type of all projects that have code references + Projects []Link `json:"projects,omitempty"` + Self *Link `json:"self,omitempty"` +} + +// NewStatisticsRoot instantiates a new StatisticsRoot object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatisticsRoot() *StatisticsRoot { + this := StatisticsRoot{} + return &this +} + +// NewStatisticsRootWithDefaults instantiates a new StatisticsRoot object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatisticsRootWithDefaults() *StatisticsRoot { + this := StatisticsRoot{} + return &this +} + +// GetProjects returns the Projects field value if set, zero value otherwise. +func (o *StatisticsRoot) GetProjects() []Link { + if o == nil || o.Projects == nil { + var ret []Link + return ret + } + return o.Projects +} + +// GetProjectsOk returns a tuple with the Projects field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatisticsRoot) GetProjectsOk() ([]Link, bool) { + if o == nil || o.Projects == nil { + return nil, false + } + return o.Projects, true +} + +// HasProjects returns a boolean if a field has been set. +func (o *StatisticsRoot) HasProjects() bool { + if o != nil && o.Projects != nil { + return true + } + + return false +} + +// SetProjects gets a reference to the given []Link and assigns it to the Projects field. +func (o *StatisticsRoot) SetProjects(v []Link) { + o.Projects = v +} + +// GetSelf returns the Self field value if set, zero value otherwise. +func (o *StatisticsRoot) GetSelf() Link { + if o == nil || o.Self == nil { + var ret Link + return ret + } + return *o.Self +} + +// GetSelfOk returns a tuple with the Self field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatisticsRoot) GetSelfOk() (*Link, bool) { + if o == nil || o.Self == nil { + return nil, false + } + return o.Self, true +} + +// HasSelf returns a boolean if a field has been set. +func (o *StatisticsRoot) HasSelf() bool { + if o != nil && o.Self != nil { + return true + } + + return false +} + +// SetSelf gets a reference to the given Link and assigns it to the Self field. +func (o *StatisticsRoot) SetSelf(v Link) { + o.Self = &v +} + +func (o StatisticsRoot) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Projects != nil { + toSerialize["projects"] = o.Projects + } + if o.Self != nil { + toSerialize["self"] = o.Self + } + return json.Marshal(toSerialize) +} + +type NullableStatisticsRoot struct { + value *StatisticsRoot + isSet bool +} + +func (v NullableStatisticsRoot) Get() *StatisticsRoot { + return v.value +} + +func (v *NullableStatisticsRoot) Set(val *StatisticsRoot) { + v.value = val + v.isSet = true +} + +func (v NullableStatisticsRoot) IsSet() bool { + return v.isSet +} + +func (v *NullableStatisticsRoot) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatisticsRoot(val *StatisticsRoot) *NullableStatisticsRoot { + return &NullableStatisticsRoot{value: val, isSet: true} +} + +func (v NullableStatisticsRoot) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatisticsRoot) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_status_conflict_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_conflict_error_rep.go new file mode 100644 index 00000000..bb380ce4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_conflict_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatusConflictErrorRep struct for StatusConflictErrorRep +type StatusConflictErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewStatusConflictErrorRep instantiates a new StatusConflictErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatusConflictErrorRep(code string, message string) *StatusConflictErrorRep { + this := StatusConflictErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewStatusConflictErrorRepWithDefaults instantiates a new StatusConflictErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatusConflictErrorRepWithDefaults() *StatusConflictErrorRep { + this := StatusConflictErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *StatusConflictErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *StatusConflictErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *StatusConflictErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *StatusConflictErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *StatusConflictErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *StatusConflictErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o StatusConflictErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableStatusConflictErrorRep struct { + value *StatusConflictErrorRep + isSet bool +} + +func (v NullableStatusConflictErrorRep) Get() *StatusConflictErrorRep { + return v.value +} + +func (v *NullableStatusConflictErrorRep) Set(val *StatusConflictErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableStatusConflictErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableStatusConflictErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatusConflictErrorRep(val *StatusConflictErrorRep) *NullableStatusConflictErrorRep { + return &NullableStatusConflictErrorRep{value: val, isSet: true} +} + +func (v NullableStatusConflictErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatusConflictErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_status_response.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_response.go new file mode 100644 index 00000000..af068a56 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_response.go @@ -0,0 +1,224 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatusResponse struct for StatusResponse +type StatusResponse struct { + IntegrationId *string `json:"integrationId,omitempty"` + Message *string `json:"message,omitempty"` + StatusCode *int32 `json:"statusCode,omitempty"` + Timestamp *int64 `json:"timestamp,omitempty"` +} + +// NewStatusResponse instantiates a new StatusResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatusResponse() *StatusResponse { + this := StatusResponse{} + return &this +} + +// NewStatusResponseWithDefaults instantiates a new StatusResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatusResponseWithDefaults() *StatusResponse { + this := StatusResponse{} + return &this +} + +// GetIntegrationId returns the IntegrationId field value if set, zero value otherwise. +func (o *StatusResponse) GetIntegrationId() string { + if o == nil || o.IntegrationId == nil { + var ret string + return ret + } + return *o.IntegrationId +} + +// GetIntegrationIdOk returns a tuple with the IntegrationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatusResponse) GetIntegrationIdOk() (*string, bool) { + if o == nil || o.IntegrationId == nil { + return nil, false + } + return o.IntegrationId, true +} + +// HasIntegrationId returns a boolean if a field has been set. +func (o *StatusResponse) HasIntegrationId() bool { + if o != nil && o.IntegrationId != nil { + return true + } + + return false +} + +// SetIntegrationId gets a reference to the given string and assigns it to the IntegrationId field. +func (o *StatusResponse) SetIntegrationId(v string) { + o.IntegrationId = &v +} + +// GetMessage returns the Message field value if set, zero value otherwise. +func (o *StatusResponse) GetMessage() string { + if o == nil || o.Message == nil { + var ret string + return ret + } + return *o.Message +} + +// GetMessageOk returns a tuple with the Message field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatusResponse) GetMessageOk() (*string, bool) { + if o == nil || o.Message == nil { + return nil, false + } + return o.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (o *StatusResponse) HasMessage() bool { + if o != nil && o.Message != nil { + return true + } + + return false +} + +// SetMessage gets a reference to the given string and assigns it to the Message field. +func (o *StatusResponse) SetMessage(v string) { + o.Message = &v +} + +// GetStatusCode returns the StatusCode field value if set, zero value otherwise. +func (o *StatusResponse) GetStatusCode() int32 { + if o == nil || o.StatusCode == nil { + var ret int32 + return ret + } + return *o.StatusCode +} + +// GetStatusCodeOk returns a tuple with the StatusCode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatusResponse) GetStatusCodeOk() (*int32, bool) { + if o == nil || o.StatusCode == nil { + return nil, false + } + return o.StatusCode, true +} + +// HasStatusCode returns a boolean if a field has been set. +func (o *StatusResponse) HasStatusCode() bool { + if o != nil && o.StatusCode != nil { + return true + } + + return false +} + +// SetStatusCode gets a reference to the given int32 and assigns it to the StatusCode field. +func (o *StatusResponse) SetStatusCode(v int32) { + o.StatusCode = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *StatusResponse) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StatusResponse) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *StatusResponse) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *StatusResponse) SetTimestamp(v int64) { + o.Timestamp = &v +} + +func (o StatusResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.IntegrationId != nil { + toSerialize["integrationId"] = o.IntegrationId + } + if o.Message != nil { + toSerialize["message"] = o.Message + } + if o.StatusCode != nil { + toSerialize["statusCode"] = o.StatusCode + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + return json.Marshal(toSerialize) +} + +type NullableStatusResponse struct { + value *StatusResponse + isSet bool +} + +func (v NullableStatusResponse) Get() *StatusResponse { + return v.value +} + +func (v *NullableStatusResponse) Set(val *StatusResponse) { + v.value = val + v.isSet = true +} + +func (v NullableStatusResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableStatusResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatusResponse(val *StatusResponse) *NullableStatusResponse { + return &NullableStatusResponse{value: val, isSet: true} +} + +func (v NullableStatusResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatusResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_status_service_unavailable.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_service_unavailable.go new file mode 100644 index 00000000..3026d329 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_status_service_unavailable.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StatusServiceUnavailable struct for StatusServiceUnavailable +type StatusServiceUnavailable struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewStatusServiceUnavailable instantiates a new StatusServiceUnavailable object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStatusServiceUnavailable(code string, message string) *StatusServiceUnavailable { + this := StatusServiceUnavailable{} + this.Code = code + this.Message = message + return &this +} + +// NewStatusServiceUnavailableWithDefaults instantiates a new StatusServiceUnavailable object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStatusServiceUnavailableWithDefaults() *StatusServiceUnavailable { + this := StatusServiceUnavailable{} + return &this +} + +// GetCode returns the Code field value +func (o *StatusServiceUnavailable) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *StatusServiceUnavailable) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *StatusServiceUnavailable) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *StatusServiceUnavailable) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *StatusServiceUnavailable) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *StatusServiceUnavailable) SetMessage(v string) { + o.Message = v +} + +func (o StatusServiceUnavailable) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableStatusServiceUnavailable struct { + value *StatusServiceUnavailable + isSet bool +} + +func (v NullableStatusServiceUnavailable) Get() *StatusServiceUnavailable { + return v.value +} + +func (v *NullableStatusServiceUnavailable) Set(val *StatusServiceUnavailable) { + v.value = val + v.isSet = true +} + +func (v NullableStatusServiceUnavailable) IsSet() bool { + return v.isSet +} + +func (v *NullableStatusServiceUnavailable) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStatusServiceUnavailable(val *StatusServiceUnavailable) *NullableStatusServiceUnavailable { + return &NullableStatusServiceUnavailable{value: val, isSet: true} +} + +func (v NullableStatusServiceUnavailable) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStatusServiceUnavailable) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_store_integration_error.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_store_integration_error.go new file mode 100644 index 00000000..9b3f4d19 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_store_integration_error.go @@ -0,0 +1,188 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// StoreIntegrationError struct for StoreIntegrationError +type StoreIntegrationError struct { + StatusCode *int32 `json:"statusCode,omitempty"` + Message *string `json:"message,omitempty"` + Timestamp *int64 `json:"timestamp,omitempty"` +} + +// NewStoreIntegrationError instantiates a new StoreIntegrationError object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStoreIntegrationError() *StoreIntegrationError { + this := StoreIntegrationError{} + return &this +} + +// NewStoreIntegrationErrorWithDefaults instantiates a new StoreIntegrationError object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStoreIntegrationErrorWithDefaults() *StoreIntegrationError { + this := StoreIntegrationError{} + return &this +} + +// GetStatusCode returns the StatusCode field value if set, zero value otherwise. +func (o *StoreIntegrationError) GetStatusCode() int32 { + if o == nil || o.StatusCode == nil { + var ret int32 + return ret + } + return *o.StatusCode +} + +// GetStatusCodeOk returns a tuple with the StatusCode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StoreIntegrationError) GetStatusCodeOk() (*int32, bool) { + if o == nil || o.StatusCode == nil { + return nil, false + } + return o.StatusCode, true +} + +// HasStatusCode returns a boolean if a field has been set. +func (o *StoreIntegrationError) HasStatusCode() bool { + if o != nil && o.StatusCode != nil { + return true + } + + return false +} + +// SetStatusCode gets a reference to the given int32 and assigns it to the StatusCode field. +func (o *StoreIntegrationError) SetStatusCode(v int32) { + o.StatusCode = &v +} + +// GetMessage returns the Message field value if set, zero value otherwise. +func (o *StoreIntegrationError) GetMessage() string { + if o == nil || o.Message == nil { + var ret string + return ret + } + return *o.Message +} + +// GetMessageOk returns a tuple with the Message field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StoreIntegrationError) GetMessageOk() (*string, bool) { + if o == nil || o.Message == nil { + return nil, false + } + return o.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (o *StoreIntegrationError) HasMessage() bool { + if o != nil && o.Message != nil { + return true + } + + return false +} + +// SetMessage gets a reference to the given string and assigns it to the Message field. +func (o *StoreIntegrationError) SetMessage(v string) { + o.Message = &v +} + +// GetTimestamp returns the Timestamp field value if set, zero value otherwise. +func (o *StoreIntegrationError) GetTimestamp() int64 { + if o == nil || o.Timestamp == nil { + var ret int64 + return ret + } + return *o.Timestamp +} + +// GetTimestampOk returns a tuple with the Timestamp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StoreIntegrationError) GetTimestampOk() (*int64, bool) { + if o == nil || o.Timestamp == nil { + return nil, false + } + return o.Timestamp, true +} + +// HasTimestamp returns a boolean if a field has been set. +func (o *StoreIntegrationError) HasTimestamp() bool { + if o != nil && o.Timestamp != nil { + return true + } + + return false +} + +// SetTimestamp gets a reference to the given int64 and assigns it to the Timestamp field. +func (o *StoreIntegrationError) SetTimestamp(v int64) { + o.Timestamp = &v +} + +func (o StoreIntegrationError) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.StatusCode != nil { + toSerialize["statusCode"] = o.StatusCode + } + if o.Message != nil { + toSerialize["message"] = o.Message + } + if o.Timestamp != nil { + toSerialize["timestamp"] = o.Timestamp + } + return json.Marshal(toSerialize) +} + +type NullableStoreIntegrationError struct { + value *StoreIntegrationError + isSet bool +} + +func (v NullableStoreIntegrationError) Get() *StoreIntegrationError { + return v.value +} + +func (v *NullableStoreIntegrationError) Set(val *StoreIntegrationError) { + v.value = val + v.isSet = true +} + +func (v NullableStoreIntegrationError) IsSet() bool { + return v.isSet +} + +func (v *NullableStoreIntegrationError) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStoreIntegrationError(val *StoreIntegrationError) *NullableStoreIntegrationError { + return &NullableStoreIntegrationError{value: val, isSet: true} +} + +func (v NullableStoreIntegrationError) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStoreIntegrationError) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_subject_data_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_subject_data_rep.go new file mode 100644 index 00000000..404a179c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_subject_data_rep.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SubjectDataRep struct for SubjectDataRep +type SubjectDataRep struct { + Links *map[string]Link `json:"_links,omitempty"` + // The subject's name + Name *string `json:"name,omitempty"` + // The subject's avatar + AvatarUrl *string `json:"avatarUrl,omitempty"` +} + +// NewSubjectDataRep instantiates a new SubjectDataRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSubjectDataRep() *SubjectDataRep { + this := SubjectDataRep{} + return &this +} + +// NewSubjectDataRepWithDefaults instantiates a new SubjectDataRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSubjectDataRepWithDefaults() *SubjectDataRep { + this := SubjectDataRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *SubjectDataRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubjectDataRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *SubjectDataRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *SubjectDataRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *SubjectDataRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubjectDataRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *SubjectDataRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *SubjectDataRep) SetName(v string) { + o.Name = &v +} + +// GetAvatarUrl returns the AvatarUrl field value if set, zero value otherwise. +func (o *SubjectDataRep) GetAvatarUrl() string { + if o == nil || o.AvatarUrl == nil { + var ret string + return ret + } + return *o.AvatarUrl +} + +// GetAvatarUrlOk returns a tuple with the AvatarUrl field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubjectDataRep) GetAvatarUrlOk() (*string, bool) { + if o == nil || o.AvatarUrl == nil { + return nil, false + } + return o.AvatarUrl, true +} + +// HasAvatarUrl returns a boolean if a field has been set. +func (o *SubjectDataRep) HasAvatarUrl() bool { + if o != nil && o.AvatarUrl != nil { + return true + } + + return false +} + +// SetAvatarUrl gets a reference to the given string and assigns it to the AvatarUrl field. +func (o *SubjectDataRep) SetAvatarUrl(v string) { + o.AvatarUrl = &v +} + +func (o SubjectDataRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.AvatarUrl != nil { + toSerialize["avatarUrl"] = o.AvatarUrl + } + return json.Marshal(toSerialize) +} + +type NullableSubjectDataRep struct { + value *SubjectDataRep + isSet bool +} + +func (v NullableSubjectDataRep) Get() *SubjectDataRep { + return v.value +} + +func (v *NullableSubjectDataRep) Set(val *SubjectDataRep) { + v.value = val + v.isSet = true +} + +func (v NullableSubjectDataRep) IsSet() bool { + return v.isSet +} + +func (v *NullableSubjectDataRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSubjectDataRep(val *SubjectDataRep) *NullableSubjectDataRep { + return &NullableSubjectDataRep{value: val, isSet: true} +} + +func (v NullableSubjectDataRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSubjectDataRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_subscription_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_subscription_post.go new file mode 100644 index 00000000..1f40d61a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_subscription_post.go @@ -0,0 +1,324 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// SubscriptionPost struct for SubscriptionPost +type SubscriptionPost struct { + // A human-friendly name for your audit log subscription. + Name string `json:"name"` + Statements []StatementPost `json:"statements,omitempty"` + // Whether or not you want your subscription to actively send events. + On *bool `json:"on,omitempty"` + // An array of tags for this subscription. + Tags []string `json:"tags,omitempty"` + // The unique set of fields required to configure an audit log subscription integration of this type. Refer to the formVariables field in the corresponding manifest.json at https://github.com/launchdarkly/integration-framework/tree/main/integrations for a full list of fields for the integration you wish to configure. + Config map[string]interface{} `json:"config"` + // Slack webhook receiver URL. Only necessary for legacy Slack webhook integrations. + Url *string `json:"url,omitempty"` + // Datadog API key. Only necessary for legacy Datadog webhook integrations. + ApiKey *string `json:"apiKey,omitempty"` +} + +// NewSubscriptionPost instantiates a new SubscriptionPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewSubscriptionPost(name string, config map[string]interface{}) *SubscriptionPost { + this := SubscriptionPost{} + this.Name = name + this.Config = config + return &this +} + +// NewSubscriptionPostWithDefaults instantiates a new SubscriptionPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewSubscriptionPostWithDefaults() *SubscriptionPost { + this := SubscriptionPost{} + return &this +} + +// GetName returns the Name field value +func (o *SubscriptionPost) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *SubscriptionPost) SetName(v string) { + o.Name = v +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *SubscriptionPost) GetStatements() []StatementPost { + if o == nil || o.Statements == nil { + var ret []StatementPost + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetStatementsOk() ([]StatementPost, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *SubscriptionPost) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []StatementPost and assigns it to the Statements field. +func (o *SubscriptionPost) SetStatements(v []StatementPost) { + o.Statements = v +} + +// GetOn returns the On field value if set, zero value otherwise. +func (o *SubscriptionPost) GetOn() bool { + if o == nil || o.On == nil { + var ret bool + return ret + } + return *o.On +} + +// GetOnOk returns a tuple with the On field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetOnOk() (*bool, bool) { + if o == nil || o.On == nil { + return nil, false + } + return o.On, true +} + +// HasOn returns a boolean if a field has been set. +func (o *SubscriptionPost) HasOn() bool { + if o != nil && o.On != nil { + return true + } + + return false +} + +// SetOn gets a reference to the given bool and assigns it to the On field. +func (o *SubscriptionPost) SetOn(v bool) { + o.On = &v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *SubscriptionPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *SubscriptionPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *SubscriptionPost) SetTags(v []string) { + o.Tags = v +} + +// GetConfig returns the Config field value +func (o *SubscriptionPost) GetConfig() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + + return o.Config +} + +// GetConfigOk returns a tuple with the Config field value +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetConfigOk() (map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Config, true +} + +// SetConfig sets field value +func (o *SubscriptionPost) SetConfig(v map[string]interface{}) { + o.Config = v +} + +// GetUrl returns the Url field value if set, zero value otherwise. +func (o *SubscriptionPost) GetUrl() string { + if o == nil || o.Url == nil { + var ret string + return ret + } + return *o.Url +} + +// GetUrlOk returns a tuple with the Url field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetUrlOk() (*string, bool) { + if o == nil || o.Url == nil { + return nil, false + } + return o.Url, true +} + +// HasUrl returns a boolean if a field has been set. +func (o *SubscriptionPost) HasUrl() bool { + if o != nil && o.Url != nil { + return true + } + + return false +} + +// SetUrl gets a reference to the given string and assigns it to the Url field. +func (o *SubscriptionPost) SetUrl(v string) { + o.Url = &v +} + +// GetApiKey returns the ApiKey field value if set, zero value otherwise. +func (o *SubscriptionPost) GetApiKey() string { + if o == nil || o.ApiKey == nil { + var ret string + return ret + } + return *o.ApiKey +} + +// GetApiKeyOk returns a tuple with the ApiKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SubscriptionPost) GetApiKeyOk() (*string, bool) { + if o == nil || o.ApiKey == nil { + return nil, false + } + return o.ApiKey, true +} + +// HasApiKey returns a boolean if a field has been set. +func (o *SubscriptionPost) HasApiKey() bool { + if o != nil && o.ApiKey != nil { + return true + } + + return false +} + +// SetApiKey gets a reference to the given string and assigns it to the ApiKey field. +func (o *SubscriptionPost) SetApiKey(v string) { + o.ApiKey = &v +} + +func (o SubscriptionPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + if o.On != nil { + toSerialize["on"] = o.On + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["config"] = o.Config + } + if o.Url != nil { + toSerialize["url"] = o.Url + } + if o.ApiKey != nil { + toSerialize["apiKey"] = o.ApiKey + } + return json.Marshal(toSerialize) +} + +type NullableSubscriptionPost struct { + value *SubscriptionPost + isSet bool +} + +func (v NullableSubscriptionPost) Get() *SubscriptionPost { + return v.value +} + +func (v *NullableSubscriptionPost) Set(val *SubscriptionPost) { + v.value = val + v.isSet = true +} + +func (v NullableSubscriptionPost) IsSet() bool { + return v.isSet +} + +func (v *NullableSubscriptionPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSubscriptionPost(val *SubscriptionPost) *NullableSubscriptionPost { + return &NullableSubscriptionPost{value: val, isSet: true} +} + +func (v NullableSubscriptionPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSubscriptionPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_collection.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_collection.go new file mode 100644 index 00000000..4fba3b36 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_collection.go @@ -0,0 +1,176 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TagsCollection struct for TagsCollection +type TagsCollection struct { + // List of tags + Items []string `json:"items"` + Links map[string]TagsLink `json:"_links"` + // The total number of tags + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewTagsCollection instantiates a new TagsCollection object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTagsCollection(items []string, links map[string]TagsLink) *TagsCollection { + this := TagsCollection{} + this.Items = items + this.Links = links + return &this +} + +// NewTagsCollectionWithDefaults instantiates a new TagsCollection object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTagsCollectionWithDefaults() *TagsCollection { + this := TagsCollection{} + return &this +} + +// GetItems returns the Items field value +func (o *TagsCollection) GetItems() []string { + if o == nil { + var ret []string + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *TagsCollection) GetItemsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *TagsCollection) SetItems(v []string) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *TagsCollection) GetLinks() map[string]TagsLink { + if o == nil { + var ret map[string]TagsLink + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *TagsCollection) GetLinksOk() (*map[string]TagsLink, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *TagsCollection) SetLinks(v map[string]TagsLink) { + o.Links = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *TagsCollection) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TagsCollection) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *TagsCollection) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *TagsCollection) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o TagsCollection) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableTagsCollection struct { + value *TagsCollection + isSet bool +} + +func (v NullableTagsCollection) Get() *TagsCollection { + return v.value +} + +func (v *NullableTagsCollection) Set(val *TagsCollection) { + v.value = val + v.isSet = true +} + +func (v NullableTagsCollection) IsSet() bool { + return v.isSet +} + +func (v *NullableTagsCollection) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTagsCollection(val *TagsCollection) *NullableTagsCollection { + return &NullableTagsCollection{value: val, isSet: true} +} + +func (v NullableTagsCollection) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTagsCollection) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_link.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_link.go new file mode 100644 index 00000000..690d39d5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_tags_link.go @@ -0,0 +1,152 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TagsLink struct for TagsLink +type TagsLink struct { + Href *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NewTagsLink instantiates a new TagsLink object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTagsLink() *TagsLink { + this := TagsLink{} + return &this +} + +// NewTagsLinkWithDefaults instantiates a new TagsLink object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTagsLinkWithDefaults() *TagsLink { + this := TagsLink{} + return &this +} + +// GetHref returns the Href field value if set, zero value otherwise. +func (o *TagsLink) GetHref() string { + if o == nil || o.Href == nil { + var ret string + return ret + } + return *o.Href +} + +// GetHrefOk returns a tuple with the Href field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TagsLink) GetHrefOk() (*string, bool) { + if o == nil || o.Href == nil { + return nil, false + } + return o.Href, true +} + +// HasHref returns a boolean if a field has been set. +func (o *TagsLink) HasHref() bool { + if o != nil && o.Href != nil { + return true + } + + return false +} + +// SetHref gets a reference to the given string and assigns it to the Href field. +func (o *TagsLink) SetHref(v string) { + o.Href = &v +} + +// GetType returns the Type field value if set, zero value otherwise. +func (o *TagsLink) GetType() string { + if o == nil || o.Type == nil { + var ret string + return ret + } + return *o.Type +} + +// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TagsLink) GetTypeOk() (*string, bool) { + if o == nil || o.Type == nil { + return nil, false + } + return o.Type, true +} + +// HasType returns a boolean if a field has been set. +func (o *TagsLink) HasType() bool { + if o != nil && o.Type != nil { + return true + } + + return false +} + +// SetType gets a reference to the given string and assigns it to the Type field. +func (o *TagsLink) SetType(v string) { + o.Type = &v +} + +func (o TagsLink) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Href != nil { + toSerialize["href"] = o.Href + } + if o.Type != nil { + toSerialize["type"] = o.Type + } + return json.Marshal(toSerialize) +} + +type NullableTagsLink struct { + value *TagsLink + isSet bool +} + +func (v NullableTagsLink) Get() *TagsLink { + return v.value +} + +func (v *NullableTagsLink) Set(val *TagsLink) { + v.value = val + v.isSet = true +} + +func (v NullableTagsLink) IsSet() bool { + return v.isSet +} + +func (v *NullableTagsLink) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTagsLink(val *TagsLink) *NullableTagsLink { + return &NullableTagsLink{value: val, isSet: true} +} + +func (v NullableTagsLink) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTagsLink) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_target.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_target.go new file mode 100644 index 00000000..54c77992 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_target.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Target struct for Target +type Target struct { + // A list of the keys for targets that will receive this variation because of individual targeting + Values []string `json:"values"` + // The index, from the array of variations for this flag, of the variation to serve this list of targets + Variation int32 `json:"variation"` + // The context kind of the individual target + ContextKind *string `json:"contextKind,omitempty"` +} + +// NewTarget instantiates a new Target object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTarget(values []string, variation int32) *Target { + this := Target{} + this.Values = values + this.Variation = variation + return &this +} + +// NewTargetWithDefaults instantiates a new Target object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTargetWithDefaults() *Target { + this := Target{} + return &this +} + +// GetValues returns the Values field value +func (o *Target) GetValues() []string { + if o == nil { + var ret []string + return ret + } + + return o.Values +} + +// GetValuesOk returns a tuple with the Values field value +// and a boolean to check if the value has been set. +func (o *Target) GetValuesOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Values, true +} + +// SetValues sets field value +func (o *Target) SetValues(v []string) { + o.Values = v +} + +// GetVariation returns the Variation field value +func (o *Target) GetVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Variation +} + +// GetVariationOk returns a tuple with the Variation field value +// and a boolean to check if the value has been set. +func (o *Target) GetVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Variation, true +} + +// SetVariation sets field value +func (o *Target) SetVariation(v int32) { + o.Variation = v +} + +// GetContextKind returns the ContextKind field value if set, zero value otherwise. +func (o *Target) GetContextKind() string { + if o == nil || o.ContextKind == nil { + var ret string + return ret + } + return *o.ContextKind +} + +// GetContextKindOk returns a tuple with the ContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Target) GetContextKindOk() (*string, bool) { + if o == nil || o.ContextKind == nil { + return nil, false + } + return o.ContextKind, true +} + +// HasContextKind returns a boolean if a field has been set. +func (o *Target) HasContextKind() bool { + if o != nil && o.ContextKind != nil { + return true + } + + return false +} + +// SetContextKind gets a reference to the given string and assigns it to the ContextKind field. +func (o *Target) SetContextKind(v string) { + o.ContextKind = &v +} + +func (o Target) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["values"] = o.Values + } + if true { + toSerialize["variation"] = o.Variation + } + if o.ContextKind != nil { + toSerialize["contextKind"] = o.ContextKind + } + return json.Marshal(toSerialize) +} + +type NullableTarget struct { + value *Target + isSet bool +} + +func (v NullableTarget) Get() *Target { + return v.value +} + +func (v *NullableTarget) Set(val *Target) { + v.value = val + v.isSet = true +} + +func (v NullableTarget) IsSet() bool { + return v.isSet +} + +func (v *NullableTarget) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTarget(val *Target) *NullableTarget { + return &NullableTarget{value: val, isSet: true} +} + +func (v NullableTarget) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTarget) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_target_resource_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_target_resource_rep.go new file mode 100644 index 00000000..5ce81815 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_target_resource_rep.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TargetResourceRep struct for TargetResourceRep +type TargetResourceRep struct { + Links *map[string]Link `json:"_links,omitempty"` + // The name of the resource + Name *string `json:"name,omitempty"` + // The resource specifier + Resources []string `json:"resources,omitempty"` +} + +// NewTargetResourceRep instantiates a new TargetResourceRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTargetResourceRep() *TargetResourceRep { + this := TargetResourceRep{} + return &this +} + +// NewTargetResourceRepWithDefaults instantiates a new TargetResourceRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTargetResourceRepWithDefaults() *TargetResourceRep { + this := TargetResourceRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TargetResourceRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TargetResourceRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TargetResourceRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TargetResourceRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *TargetResourceRep) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TargetResourceRep) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *TargetResourceRep) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *TargetResourceRep) SetName(v string) { + o.Name = &v +} + +// GetResources returns the Resources field value if set, zero value otherwise. +func (o *TargetResourceRep) GetResources() []string { + if o == nil || o.Resources == nil { + var ret []string + return ret + } + return o.Resources +} + +// GetResourcesOk returns a tuple with the Resources field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TargetResourceRep) GetResourcesOk() ([]string, bool) { + if o == nil || o.Resources == nil { + return nil, false + } + return o.Resources, true +} + +// HasResources returns a boolean if a field has been set. +func (o *TargetResourceRep) HasResources() bool { + if o != nil && o.Resources != nil { + return true + } + + return false +} + +// SetResources gets a reference to the given []string and assigns it to the Resources field. +func (o *TargetResourceRep) SetResources(v []string) { + o.Resources = v +} + +func (o TargetResourceRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Resources != nil { + toSerialize["resources"] = o.Resources + } + return json.Marshal(toSerialize) +} + +type NullableTargetResourceRep struct { + value *TargetResourceRep + isSet bool +} + +func (v NullableTargetResourceRep) Get() *TargetResourceRep { + return v.value +} + +func (v *NullableTargetResourceRep) Set(val *TargetResourceRep) { + v.value = val + v.isSet = true +} + +func (v NullableTargetResourceRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTargetResourceRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTargetResourceRep(val *TargetResourceRep) *NullableTargetResourceRep { + return &NullableTargetResourceRep{value: val, isSet: true} +} + +func (v NullableTargetResourceRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTargetResourceRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team.go new file mode 100644 index 00000000..0643d388 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team.go @@ -0,0 +1,590 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Team struct for Team +type Team struct { + // A description of the team + Description *string `json:"description,omitempty"` + // The team key + Key *string `json:"key,omitempty"` + // A human-friendly name for the team + Name *string `json:"name,omitempty"` + Access *Access `json:"_access,omitempty"` + CreationDate *int64 `json:"_creationDate,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + LastModified *int64 `json:"_lastModified,omitempty"` + // The team version + Version *int32 `json:"_version,omitempty"` + // Whether the team has been synced with an external identity provider (IdP). Team sync is available to customers on an Enterprise plan. + IdpSynced *bool `json:"_idpSynced,omitempty"` + RoleAttributes *map[string][]string `json:"roleAttributes,omitempty"` + Roles *TeamCustomRoles `json:"roles,omitempty"` + Members *TeamMembers `json:"members,omitempty"` + Projects *TeamProjects `json:"projects,omitempty"` + Maintainers *TeamMaintainers `json:"maintainers,omitempty"` +} + +// NewTeam instantiates a new Team object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeam() *Team { + this := Team{} + return &this +} + +// NewTeamWithDefaults instantiates a new Team object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamWithDefaults() *Team { + this := Team{} + return &this +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Team) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Team) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Team) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *Team) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *Team) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *Team) SetKey(v string) { + o.Key = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Team) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Team) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Team) SetName(v string) { + o.Name = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *Team) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *Team) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *Team) SetAccess(v Access) { + o.Access = &v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *Team) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *Team) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *Team) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Team) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Team) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Team) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetLastModified returns the LastModified field value if set, zero value otherwise. +func (o *Team) GetLastModified() int64 { + if o == nil || o.LastModified == nil { + var ret int64 + return ret + } + return *o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetLastModifiedOk() (*int64, bool) { + if o == nil || o.LastModified == nil { + return nil, false + } + return o.LastModified, true +} + +// HasLastModified returns a boolean if a field has been set. +func (o *Team) HasLastModified() bool { + if o != nil && o.LastModified != nil { + return true + } + + return false +} + +// SetLastModified gets a reference to the given int64 and assigns it to the LastModified field. +func (o *Team) SetLastModified(v int64) { + o.LastModified = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *Team) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *Team) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *Team) SetVersion(v int32) { + o.Version = &v +} + +// GetIdpSynced returns the IdpSynced field value if set, zero value otherwise. +func (o *Team) GetIdpSynced() bool { + if o == nil || o.IdpSynced == nil { + var ret bool + return ret + } + return *o.IdpSynced +} + +// GetIdpSyncedOk returns a tuple with the IdpSynced field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetIdpSyncedOk() (*bool, bool) { + if o == nil || o.IdpSynced == nil { + return nil, false + } + return o.IdpSynced, true +} + +// HasIdpSynced returns a boolean if a field has been set. +func (o *Team) HasIdpSynced() bool { + if o != nil && o.IdpSynced != nil { + return true + } + + return false +} + +// SetIdpSynced gets a reference to the given bool and assigns it to the IdpSynced field. +func (o *Team) SetIdpSynced(v bool) { + o.IdpSynced = &v +} + +// GetRoleAttributes returns the RoleAttributes field value if set, zero value otherwise. +func (o *Team) GetRoleAttributes() map[string][]string { + if o == nil || o.RoleAttributes == nil { + var ret map[string][]string + return ret + } + return *o.RoleAttributes +} + +// GetRoleAttributesOk returns a tuple with the RoleAttributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetRoleAttributesOk() (*map[string][]string, bool) { + if o == nil || o.RoleAttributes == nil { + return nil, false + } + return o.RoleAttributes, true +} + +// HasRoleAttributes returns a boolean if a field has been set. +func (o *Team) HasRoleAttributes() bool { + if o != nil && o.RoleAttributes != nil { + return true + } + + return false +} + +// SetRoleAttributes gets a reference to the given map[string][]string and assigns it to the RoleAttributes field. +func (o *Team) SetRoleAttributes(v map[string][]string) { + o.RoleAttributes = &v +} + +// GetRoles returns the Roles field value if set, zero value otherwise. +func (o *Team) GetRoles() TeamCustomRoles { + if o == nil || o.Roles == nil { + var ret TeamCustomRoles + return ret + } + return *o.Roles +} + +// GetRolesOk returns a tuple with the Roles field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetRolesOk() (*TeamCustomRoles, bool) { + if o == nil || o.Roles == nil { + return nil, false + } + return o.Roles, true +} + +// HasRoles returns a boolean if a field has been set. +func (o *Team) HasRoles() bool { + if o != nil && o.Roles != nil { + return true + } + + return false +} + +// SetRoles gets a reference to the given TeamCustomRoles and assigns it to the Roles field. +func (o *Team) SetRoles(v TeamCustomRoles) { + o.Roles = &v +} + +// GetMembers returns the Members field value if set, zero value otherwise. +func (o *Team) GetMembers() TeamMembers { + if o == nil || o.Members == nil { + var ret TeamMembers + return ret + } + return *o.Members +} + +// GetMembersOk returns a tuple with the Members field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetMembersOk() (*TeamMembers, bool) { + if o == nil || o.Members == nil { + return nil, false + } + return o.Members, true +} + +// HasMembers returns a boolean if a field has been set. +func (o *Team) HasMembers() bool { + if o != nil && o.Members != nil { + return true + } + + return false +} + +// SetMembers gets a reference to the given TeamMembers and assigns it to the Members field. +func (o *Team) SetMembers(v TeamMembers) { + o.Members = &v +} + +// GetProjects returns the Projects field value if set, zero value otherwise. +func (o *Team) GetProjects() TeamProjects { + if o == nil || o.Projects == nil { + var ret TeamProjects + return ret + } + return *o.Projects +} + +// GetProjectsOk returns a tuple with the Projects field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetProjectsOk() (*TeamProjects, bool) { + if o == nil || o.Projects == nil { + return nil, false + } + return o.Projects, true +} + +// HasProjects returns a boolean if a field has been set. +func (o *Team) HasProjects() bool { + if o != nil && o.Projects != nil { + return true + } + + return false +} + +// SetProjects gets a reference to the given TeamProjects and assigns it to the Projects field. +func (o *Team) SetProjects(v TeamProjects) { + o.Projects = &v +} + +// GetMaintainers returns the Maintainers field value if set, zero value otherwise. +func (o *Team) GetMaintainers() TeamMaintainers { + if o == nil || o.Maintainers == nil { + var ret TeamMaintainers + return ret + } + return *o.Maintainers +} + +// GetMaintainersOk returns a tuple with the Maintainers field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Team) GetMaintainersOk() (*TeamMaintainers, bool) { + if o == nil || o.Maintainers == nil { + return nil, false + } + return o.Maintainers, true +} + +// HasMaintainers returns a boolean if a field has been set. +func (o *Team) HasMaintainers() bool { + if o != nil && o.Maintainers != nil { + return true + } + + return false +} + +// SetMaintainers gets a reference to the given TeamMaintainers and assigns it to the Maintainers field. +func (o *Team) SetMaintainers(v TeamMaintainers) { + o.Maintainers = &v +} + +func (o Team) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.CreationDate != nil { + toSerialize["_creationDate"] = o.CreationDate + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.LastModified != nil { + toSerialize["_lastModified"] = o.LastModified + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if o.IdpSynced != nil { + toSerialize["_idpSynced"] = o.IdpSynced + } + if o.RoleAttributes != nil { + toSerialize["roleAttributes"] = o.RoleAttributes + } + if o.Roles != nil { + toSerialize["roles"] = o.Roles + } + if o.Members != nil { + toSerialize["members"] = o.Members + } + if o.Projects != nil { + toSerialize["projects"] = o.Projects + } + if o.Maintainers != nil { + toSerialize["maintainers"] = o.Maintainers + } + return json.Marshal(toSerialize) +} + +type NullableTeam struct { + value *Team + isSet bool +} + +func (v NullableTeam) Get() *Team { + return v.value +} + +func (v *NullableTeam) Set(val *Team) { + v.value = val + v.isSet = true +} + +func (v NullableTeam) IsSet() bool { + return v.isSet +} + +func (v *NullableTeam) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeam(val *Team) *NullableTeam { + return &NullableTeam{value: val, isSet: true} +} + +func (v NullableTeam) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeam) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_role.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_role.go new file mode 100644 index 00000000..c60671c4 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_role.go @@ -0,0 +1,226 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamCustomRole struct for TeamCustomRole +type TeamCustomRole struct { + // The key of the custom role + Key *string `json:"key,omitempty"` + // The name of the custom role + Name *string `json:"name,omitempty"` + Projects *TeamProjects `json:"projects,omitempty"` + AppliedOn *int64 `json:"appliedOn,omitempty"` +} + +// NewTeamCustomRole instantiates a new TeamCustomRole object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamCustomRole() *TeamCustomRole { + this := TeamCustomRole{} + return &this +} + +// NewTeamCustomRoleWithDefaults instantiates a new TeamCustomRole object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamCustomRoleWithDefaults() *TeamCustomRole { + this := TeamCustomRole{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *TeamCustomRole) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRole) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *TeamCustomRole) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *TeamCustomRole) SetKey(v string) { + o.Key = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *TeamCustomRole) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRole) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *TeamCustomRole) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *TeamCustomRole) SetName(v string) { + o.Name = &v +} + +// GetProjects returns the Projects field value if set, zero value otherwise. +func (o *TeamCustomRole) GetProjects() TeamProjects { + if o == nil || o.Projects == nil { + var ret TeamProjects + return ret + } + return *o.Projects +} + +// GetProjectsOk returns a tuple with the Projects field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRole) GetProjectsOk() (*TeamProjects, bool) { + if o == nil || o.Projects == nil { + return nil, false + } + return o.Projects, true +} + +// HasProjects returns a boolean if a field has been set. +func (o *TeamCustomRole) HasProjects() bool { + if o != nil && o.Projects != nil { + return true + } + + return false +} + +// SetProjects gets a reference to the given TeamProjects and assigns it to the Projects field. +func (o *TeamCustomRole) SetProjects(v TeamProjects) { + o.Projects = &v +} + +// GetAppliedOn returns the AppliedOn field value if set, zero value otherwise. +func (o *TeamCustomRole) GetAppliedOn() int64 { + if o == nil || o.AppliedOn == nil { + var ret int64 + return ret + } + return *o.AppliedOn +} + +// GetAppliedOnOk returns a tuple with the AppliedOn field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRole) GetAppliedOnOk() (*int64, bool) { + if o == nil || o.AppliedOn == nil { + return nil, false + } + return o.AppliedOn, true +} + +// HasAppliedOn returns a boolean if a field has been set. +func (o *TeamCustomRole) HasAppliedOn() bool { + if o != nil && o.AppliedOn != nil { + return true + } + + return false +} + +// SetAppliedOn gets a reference to the given int64 and assigns it to the AppliedOn field. +func (o *TeamCustomRole) SetAppliedOn(v int64) { + o.AppliedOn = &v +} + +func (o TeamCustomRole) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Projects != nil { + toSerialize["projects"] = o.Projects + } + if o.AppliedOn != nil { + toSerialize["appliedOn"] = o.AppliedOn + } + return json.Marshal(toSerialize) +} + +type NullableTeamCustomRole struct { + value *TeamCustomRole + isSet bool +} + +func (v NullableTeamCustomRole) Get() *TeamCustomRole { + return v.value +} + +func (v *NullableTeamCustomRole) Set(val *TeamCustomRole) { + v.value = val + v.isSet = true +} + +func (v NullableTeamCustomRole) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamCustomRole) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamCustomRole(val *TeamCustomRole) *NullableTeamCustomRole { + return &NullableTeamCustomRole{value: val, isSet: true} +} + +func (v NullableTeamCustomRole) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamCustomRole) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_roles.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_roles.go new file mode 100644 index 00000000..477c0d42 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_custom_roles.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamCustomRoles struct for TeamCustomRoles +type TeamCustomRoles struct { + // The number of custom roles assigned to this team + TotalCount *int32 `json:"totalCount,omitempty"` + // An array of the custom roles that have been assigned to this team + Items []TeamCustomRole `json:"items,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewTeamCustomRoles instantiates a new TeamCustomRoles object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamCustomRoles() *TeamCustomRoles { + this := TeamCustomRoles{} + return &this +} + +// NewTeamCustomRolesWithDefaults instantiates a new TeamCustomRoles object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamCustomRolesWithDefaults() *TeamCustomRoles { + this := TeamCustomRoles{} + return &this +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *TeamCustomRoles) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRoles) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *TeamCustomRoles) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *TeamCustomRoles) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *TeamCustomRoles) GetItems() []TeamCustomRole { + if o == nil || o.Items == nil { + var ret []TeamCustomRole + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRoles) GetItemsOk() ([]TeamCustomRole, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *TeamCustomRoles) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []TeamCustomRole and assigns it to the Items field. +func (o *TeamCustomRoles) SetItems(v []TeamCustomRole) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TeamCustomRoles) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamCustomRoles) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TeamCustomRoles) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TeamCustomRoles) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o TeamCustomRoles) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableTeamCustomRoles struct { + value *TeamCustomRoles + isSet bool +} + +func (v NullableTeamCustomRoles) Get() *TeamCustomRoles { + return v.value +} + +func (v *NullableTeamCustomRoles) Set(val *TeamCustomRoles) { + v.value = val + v.isSet = true +} + +func (v NullableTeamCustomRoles) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamCustomRoles) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamCustomRoles(val *TeamCustomRoles) *NullableTeamCustomRoles { + return &NullableTeamCustomRoles{value: val, isSet: true} +} + +func (v NullableTeamCustomRoles) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamCustomRoles) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_imports_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_imports_rep.go new file mode 100644 index 00000000..66e49e97 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_imports_rep.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamImportsRep struct for TeamImportsRep +type TeamImportsRep struct { + // An array of details about the members requested to be added to this team + Items []MemberImportItem `json:"items,omitempty"` +} + +// NewTeamImportsRep instantiates a new TeamImportsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamImportsRep() *TeamImportsRep { + this := TeamImportsRep{} + return &this +} + +// NewTeamImportsRepWithDefaults instantiates a new TeamImportsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamImportsRepWithDefaults() *TeamImportsRep { + this := TeamImportsRep{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *TeamImportsRep) GetItems() []MemberImportItem { + if o == nil || o.Items == nil { + var ret []MemberImportItem + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamImportsRep) GetItemsOk() ([]MemberImportItem, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *TeamImportsRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []MemberImportItem and assigns it to the Items field. +func (o *TeamImportsRep) SetItems(v []MemberImportItem) { + o.Items = v +} + +func (o TeamImportsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableTeamImportsRep struct { + value *TeamImportsRep + isSet bool +} + +func (v NullableTeamImportsRep) Get() *TeamImportsRep { + return v.value +} + +func (v *NullableTeamImportsRep) Set(val *TeamImportsRep) { + v.value = val + v.isSet = true +} + +func (v NullableTeamImportsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamImportsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamImportsRep(val *TeamImportsRep) *NullableTeamImportsRep { + return &NullableTeamImportsRep{value: val, isSet: true} +} + +func (v NullableTeamImportsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamImportsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_maintainers.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_maintainers.go new file mode 100644 index 00000000..d1ce34ca --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_maintainers.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamMaintainers struct for TeamMaintainers +type TeamMaintainers struct { + // The number of maintainers of the team + TotalCount *int32 `json:"totalCount,omitempty"` + // Details on the members that have been assigned as maintainers of the team + Items []MemberSummary `json:"items,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewTeamMaintainers instantiates a new TeamMaintainers object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamMaintainers() *TeamMaintainers { + this := TeamMaintainers{} + return &this +} + +// NewTeamMaintainersWithDefaults instantiates a new TeamMaintainers object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamMaintainersWithDefaults() *TeamMaintainers { + this := TeamMaintainers{} + return &this +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *TeamMaintainers) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamMaintainers) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *TeamMaintainers) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *TeamMaintainers) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *TeamMaintainers) GetItems() []MemberSummary { + if o == nil || o.Items == nil { + var ret []MemberSummary + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamMaintainers) GetItemsOk() ([]MemberSummary, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *TeamMaintainers) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []MemberSummary and assigns it to the Items field. +func (o *TeamMaintainers) SetItems(v []MemberSummary) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TeamMaintainers) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamMaintainers) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TeamMaintainers) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TeamMaintainers) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o TeamMaintainers) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableTeamMaintainers struct { + value *TeamMaintainers + isSet bool +} + +func (v NullableTeamMaintainers) Get() *TeamMaintainers { + return v.value +} + +func (v *NullableTeamMaintainers) Set(val *TeamMaintainers) { + v.value = val + v.isSet = true +} + +func (v NullableTeamMaintainers) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamMaintainers) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamMaintainers(val *TeamMaintainers) *NullableTeamMaintainers { + return &NullableTeamMaintainers{value: val, isSet: true} +} + +func (v NullableTeamMaintainers) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamMaintainers) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_members.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_members.go new file mode 100644 index 00000000..bea554d9 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_members.go @@ -0,0 +1,117 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamMembers struct for TeamMembers +type TeamMembers struct { + // The total count of members that belong to the team + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewTeamMembers instantiates a new TeamMembers object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamMembers() *TeamMembers { + this := TeamMembers{} + return &this +} + +// NewTeamMembersWithDefaults instantiates a new TeamMembers object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamMembersWithDefaults() *TeamMembers { + this := TeamMembers{} + return &this +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *TeamMembers) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamMembers) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *TeamMembers) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *TeamMembers) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o TeamMembers) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableTeamMembers struct { + value *TeamMembers + isSet bool +} + +func (v NullableTeamMembers) Get() *TeamMembers { + return v.value +} + +func (v *NullableTeamMembers) Set(val *TeamMembers) { + v.value = val + v.isSet = true +} + +func (v NullableTeamMembers) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamMembers) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamMembers(val *TeamMembers) *NullableTeamMembers { + return &NullableTeamMembers{value: val, isSet: true} +} + +func (v NullableTeamMembers) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamMembers) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_patch_input.go new file mode 100644 index 00000000..efe74486 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_patch_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamPatchInput struct for TeamPatchInput +type TeamPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewTeamPatchInput instantiates a new TeamPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamPatchInput(instructions []map[string]interface{}) *TeamPatchInput { + this := TeamPatchInput{} + this.Instructions = instructions + return &this +} + +// NewTeamPatchInputWithDefaults instantiates a new TeamPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamPatchInputWithDefaults() *TeamPatchInput { + this := TeamPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *TeamPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *TeamPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *TeamPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *TeamPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *TeamPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *TeamPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o TeamPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableTeamPatchInput struct { + value *TeamPatchInput + isSet bool +} + +func (v NullableTeamPatchInput) Get() *TeamPatchInput { + return v.value +} + +func (v *NullableTeamPatchInput) Set(val *TeamPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableTeamPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamPatchInput(val *TeamPatchInput) *NullableTeamPatchInput { + return &NullableTeamPatchInput{value: val, isSet: true} +} + +func (v NullableTeamPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_post_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_post_input.go new file mode 100644 index 00000000..959455dd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_post_input.go @@ -0,0 +1,324 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamPostInput struct for TeamPostInput +type TeamPostInput struct { + // List of custom role keys the team will access + CustomRoleKeys []string `json:"customRoleKeys,omitempty"` + // A description of the team + Description *string `json:"description,omitempty"` + // The team key + Key string `json:"key"` + // A list of member IDs who belong to the team + MemberIDs []string `json:"memberIDs,omitempty"` + // A human-friendly name for the team + Name string `json:"name"` + // A list of permission grants. Permission grants allow access to a specific action, without having to create or update a custom role. + PermissionGrants []PermissionGrantInput `json:"permissionGrants,omitempty"` + RoleAttributes *map[string][]string `json:"roleAttributes,omitempty"` +} + +// NewTeamPostInput instantiates a new TeamPostInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamPostInput(key string, name string) *TeamPostInput { + this := TeamPostInput{} + this.Key = key + this.Name = name + return &this +} + +// NewTeamPostInputWithDefaults instantiates a new TeamPostInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamPostInputWithDefaults() *TeamPostInput { + this := TeamPostInput{} + return &this +} + +// GetCustomRoleKeys returns the CustomRoleKeys field value if set, zero value otherwise. +func (o *TeamPostInput) GetCustomRoleKeys() []string { + if o == nil || o.CustomRoleKeys == nil { + var ret []string + return ret + } + return o.CustomRoleKeys +} + +// GetCustomRoleKeysOk returns a tuple with the CustomRoleKeys field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetCustomRoleKeysOk() ([]string, bool) { + if o == nil || o.CustomRoleKeys == nil { + return nil, false + } + return o.CustomRoleKeys, true +} + +// HasCustomRoleKeys returns a boolean if a field has been set. +func (o *TeamPostInput) HasCustomRoleKeys() bool { + if o != nil && o.CustomRoleKeys != nil { + return true + } + + return false +} + +// SetCustomRoleKeys gets a reference to the given []string and assigns it to the CustomRoleKeys field. +func (o *TeamPostInput) SetCustomRoleKeys(v []string) { + o.CustomRoleKeys = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *TeamPostInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *TeamPostInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *TeamPostInput) SetDescription(v string) { + o.Description = &v +} + +// GetKey returns the Key field value +func (o *TeamPostInput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *TeamPostInput) SetKey(v string) { + o.Key = v +} + +// GetMemberIDs returns the MemberIDs field value if set, zero value otherwise. +func (o *TeamPostInput) GetMemberIDs() []string { + if o == nil || o.MemberIDs == nil { + var ret []string + return ret + } + return o.MemberIDs +} + +// GetMemberIDsOk returns a tuple with the MemberIDs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetMemberIDsOk() ([]string, bool) { + if o == nil || o.MemberIDs == nil { + return nil, false + } + return o.MemberIDs, true +} + +// HasMemberIDs returns a boolean if a field has been set. +func (o *TeamPostInput) HasMemberIDs() bool { + if o != nil && o.MemberIDs != nil { + return true + } + + return false +} + +// SetMemberIDs gets a reference to the given []string and assigns it to the MemberIDs field. +func (o *TeamPostInput) SetMemberIDs(v []string) { + o.MemberIDs = v +} + +// GetName returns the Name field value +func (o *TeamPostInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *TeamPostInput) SetName(v string) { + o.Name = v +} + +// GetPermissionGrants returns the PermissionGrants field value if set, zero value otherwise. +func (o *TeamPostInput) GetPermissionGrants() []PermissionGrantInput { + if o == nil || o.PermissionGrants == nil { + var ret []PermissionGrantInput + return ret + } + return o.PermissionGrants +} + +// GetPermissionGrantsOk returns a tuple with the PermissionGrants field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetPermissionGrantsOk() ([]PermissionGrantInput, bool) { + if o == nil || o.PermissionGrants == nil { + return nil, false + } + return o.PermissionGrants, true +} + +// HasPermissionGrants returns a boolean if a field has been set. +func (o *TeamPostInput) HasPermissionGrants() bool { + if o != nil && o.PermissionGrants != nil { + return true + } + + return false +} + +// SetPermissionGrants gets a reference to the given []PermissionGrantInput and assigns it to the PermissionGrants field. +func (o *TeamPostInput) SetPermissionGrants(v []PermissionGrantInput) { + o.PermissionGrants = v +} + +// GetRoleAttributes returns the RoleAttributes field value if set, zero value otherwise. +func (o *TeamPostInput) GetRoleAttributes() map[string][]string { + if o == nil || o.RoleAttributes == nil { + var ret map[string][]string + return ret + } + return *o.RoleAttributes +} + +// GetRoleAttributesOk returns a tuple with the RoleAttributes field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamPostInput) GetRoleAttributesOk() (*map[string][]string, bool) { + if o == nil || o.RoleAttributes == nil { + return nil, false + } + return o.RoleAttributes, true +} + +// HasRoleAttributes returns a boolean if a field has been set. +func (o *TeamPostInput) HasRoleAttributes() bool { + if o != nil && o.RoleAttributes != nil { + return true + } + + return false +} + +// SetRoleAttributes gets a reference to the given map[string][]string and assigns it to the RoleAttributes field. +func (o *TeamPostInput) SetRoleAttributes(v map[string][]string) { + o.RoleAttributes = &v +} + +func (o TeamPostInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.CustomRoleKeys != nil { + toSerialize["customRoleKeys"] = o.CustomRoleKeys + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["key"] = o.Key + } + if o.MemberIDs != nil { + toSerialize["memberIDs"] = o.MemberIDs + } + if true { + toSerialize["name"] = o.Name + } + if o.PermissionGrants != nil { + toSerialize["permissionGrants"] = o.PermissionGrants + } + if o.RoleAttributes != nil { + toSerialize["roleAttributes"] = o.RoleAttributes + } + return json.Marshal(toSerialize) +} + +type NullableTeamPostInput struct { + value *TeamPostInput + isSet bool +} + +func (v NullableTeamPostInput) Get() *TeamPostInput { + return v.value +} + +func (v *NullableTeamPostInput) Set(val *TeamPostInput) { + v.value = val + v.isSet = true +} + +func (v NullableTeamPostInput) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamPostInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamPostInput(val *TeamPostInput) *NullableTeamPostInput { + return &NullableTeamPostInput{value: val, isSet: true} +} + +func (v NullableTeamPostInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamPostInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_team_projects.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_projects.go new file mode 100644 index 00000000..2ad21d02 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_team_projects.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamProjects struct for TeamProjects +type TeamProjects struct { + TotalCount *int32 `json:"totalCount,omitempty"` + // Details on each project where team members have write privileges on at least one resource type (e.g. flags) + Items []ProjectSummary `json:"items,omitempty"` +} + +// NewTeamProjects instantiates a new TeamProjects object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamProjects() *TeamProjects { + this := TeamProjects{} + return &this +} + +// NewTeamProjectsWithDefaults instantiates a new TeamProjects object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamProjectsWithDefaults() *TeamProjects { + this := TeamProjects{} + return &this +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *TeamProjects) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamProjects) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *TeamProjects) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *TeamProjects) SetTotalCount(v int32) { + o.TotalCount = &v +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *TeamProjects) GetItems() []ProjectSummary { + if o == nil || o.Items == nil { + var ret []ProjectSummary + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamProjects) GetItemsOk() ([]ProjectSummary, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *TeamProjects) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []ProjectSummary and assigns it to the Items field. +func (o *TeamProjects) SetItems(v []ProjectSummary) { + o.Items = v +} + +func (o TeamProjects) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + if o.Items != nil { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableTeamProjects struct { + value *TeamProjects + isSet bool +} + +func (v NullableTeamProjects) Get() *TeamProjects { + return v.value +} + +func (v *NullableTeamProjects) Set(val *TeamProjects) { + v.value = val + v.isSet = true +} + +func (v NullableTeamProjects) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamProjects) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamProjects(val *TeamProjects) *NullableTeamProjects { + return &NullableTeamProjects{value: val, isSet: true} +} + +func (v NullableTeamProjects) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamProjects) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_teams.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_teams.go new file mode 100644 index 00000000..7432627c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_teams.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Teams struct for Teams +type Teams struct { + // An array of teams + Items []Team `json:"items"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The number of teams + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewTeams instantiates a new Teams object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeams(items []Team) *Teams { + this := Teams{} + this.Items = items + return &this +} + +// NewTeamsWithDefaults instantiates a new Teams object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamsWithDefaults() *Teams { + this := Teams{} + return &this +} + +// GetItems returns the Items field value +func (o *Teams) GetItems() []Team { + if o == nil { + var ret []Team + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Teams) GetItemsOk() ([]Team, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Teams) SetItems(v []Team) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Teams) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Teams) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Teams) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Teams) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Teams) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Teams) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Teams) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Teams) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o Teams) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableTeams struct { + value *Teams + isSet bool +} + +func (v NullableTeams) Get() *Teams { + return v.value +} + +func (v *NullableTeams) Set(val *Teams) { + v.value = val + v.isSet = true +} + +func (v NullableTeams) IsSet() bool { + return v.isSet +} + +func (v *NullableTeams) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeams(val *Teams) *NullableTeams { + return &NullableTeams{value: val, isSet: true} +} + +func (v NullableTeams) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeams) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_teams_patch_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_teams_patch_input.go new file mode 100644 index 00000000..309ef00b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_teams_patch_input.go @@ -0,0 +1,146 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TeamsPatchInput struct for TeamsPatchInput +type TeamsPatchInput struct { + // Optional comment describing the update + Comment *string `json:"comment,omitempty"` + Instructions []map[string]interface{} `json:"instructions"` +} + +// NewTeamsPatchInput instantiates a new TeamsPatchInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTeamsPatchInput(instructions []map[string]interface{}) *TeamsPatchInput { + this := TeamsPatchInput{} + this.Instructions = instructions + return &this +} + +// NewTeamsPatchInputWithDefaults instantiates a new TeamsPatchInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTeamsPatchInputWithDefaults() *TeamsPatchInput { + this := TeamsPatchInput{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *TeamsPatchInput) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TeamsPatchInput) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *TeamsPatchInput) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *TeamsPatchInput) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value +func (o *TeamsPatchInput) GetInstructions() []map[string]interface{} { + if o == nil { + var ret []map[string]interface{} + return ret + } + + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value +// and a boolean to check if the value has been set. +func (o *TeamsPatchInput) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil { + return nil, false + } + return o.Instructions, true +} + +// SetInstructions sets field value +func (o *TeamsPatchInput) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +func (o TeamsPatchInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if true { + toSerialize["instructions"] = o.Instructions + } + return json.Marshal(toSerialize) +} + +type NullableTeamsPatchInput struct { + value *TeamsPatchInput + isSet bool +} + +func (v NullableTeamsPatchInput) Get() *TeamsPatchInput { + return v.value +} + +func (v *NullableTeamsPatchInput) Set(val *TeamsPatchInput) { + v.value = val + v.isSet = true +} + +func (v NullableTeamsPatchInput) IsSet() bool { + return v.isSet +} + +func (v *NullableTeamsPatchInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTeamsPatchInput(val *TeamsPatchInput) *NullableTeamsPatchInput { + return &NullableTeamsPatchInput{value: val, isSet: true} +} + +func (v NullableTeamsPatchInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTeamsPatchInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_timestamp_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_timestamp_rep.go new file mode 100644 index 00000000..576b8be6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_timestamp_rep.go @@ -0,0 +1,224 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TimestampRep struct for TimestampRep +type TimestampRep struct { + Milliseconds *int64 `json:"milliseconds,omitempty"` + Seconds *int64 `json:"seconds,omitempty"` + Rfc3339 *string `json:"rfc3339,omitempty"` + Simple *string `json:"simple,omitempty"` +} + +// NewTimestampRep instantiates a new TimestampRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTimestampRep() *TimestampRep { + this := TimestampRep{} + return &this +} + +// NewTimestampRepWithDefaults instantiates a new TimestampRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTimestampRepWithDefaults() *TimestampRep { + this := TimestampRep{} + return &this +} + +// GetMilliseconds returns the Milliseconds field value if set, zero value otherwise. +func (o *TimestampRep) GetMilliseconds() int64 { + if o == nil || o.Milliseconds == nil { + var ret int64 + return ret + } + return *o.Milliseconds +} + +// GetMillisecondsOk returns a tuple with the Milliseconds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TimestampRep) GetMillisecondsOk() (*int64, bool) { + if o == nil || o.Milliseconds == nil { + return nil, false + } + return o.Milliseconds, true +} + +// HasMilliseconds returns a boolean if a field has been set. +func (o *TimestampRep) HasMilliseconds() bool { + if o != nil && o.Milliseconds != nil { + return true + } + + return false +} + +// SetMilliseconds gets a reference to the given int64 and assigns it to the Milliseconds field. +func (o *TimestampRep) SetMilliseconds(v int64) { + o.Milliseconds = &v +} + +// GetSeconds returns the Seconds field value if set, zero value otherwise. +func (o *TimestampRep) GetSeconds() int64 { + if o == nil || o.Seconds == nil { + var ret int64 + return ret + } + return *o.Seconds +} + +// GetSecondsOk returns a tuple with the Seconds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TimestampRep) GetSecondsOk() (*int64, bool) { + if o == nil || o.Seconds == nil { + return nil, false + } + return o.Seconds, true +} + +// HasSeconds returns a boolean if a field has been set. +func (o *TimestampRep) HasSeconds() bool { + if o != nil && o.Seconds != nil { + return true + } + + return false +} + +// SetSeconds gets a reference to the given int64 and assigns it to the Seconds field. +func (o *TimestampRep) SetSeconds(v int64) { + o.Seconds = &v +} + +// GetRfc3339 returns the Rfc3339 field value if set, zero value otherwise. +func (o *TimestampRep) GetRfc3339() string { + if o == nil || o.Rfc3339 == nil { + var ret string + return ret + } + return *o.Rfc3339 +} + +// GetRfc3339Ok returns a tuple with the Rfc3339 field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TimestampRep) GetRfc3339Ok() (*string, bool) { + if o == nil || o.Rfc3339 == nil { + return nil, false + } + return o.Rfc3339, true +} + +// HasRfc3339 returns a boolean if a field has been set. +func (o *TimestampRep) HasRfc3339() bool { + if o != nil && o.Rfc3339 != nil { + return true + } + + return false +} + +// SetRfc3339 gets a reference to the given string and assigns it to the Rfc3339 field. +func (o *TimestampRep) SetRfc3339(v string) { + o.Rfc3339 = &v +} + +// GetSimple returns the Simple field value if set, zero value otherwise. +func (o *TimestampRep) GetSimple() string { + if o == nil || o.Simple == nil { + var ret string + return ret + } + return *o.Simple +} + +// GetSimpleOk returns a tuple with the Simple field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TimestampRep) GetSimpleOk() (*string, bool) { + if o == nil || o.Simple == nil { + return nil, false + } + return o.Simple, true +} + +// HasSimple returns a boolean if a field has been set. +func (o *TimestampRep) HasSimple() bool { + if o != nil && o.Simple != nil { + return true + } + + return false +} + +// SetSimple gets a reference to the given string and assigns it to the Simple field. +func (o *TimestampRep) SetSimple(v string) { + o.Simple = &v +} + +func (o TimestampRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Milliseconds != nil { + toSerialize["milliseconds"] = o.Milliseconds + } + if o.Seconds != nil { + toSerialize["seconds"] = o.Seconds + } + if o.Rfc3339 != nil { + toSerialize["rfc3339"] = o.Rfc3339 + } + if o.Simple != nil { + toSerialize["simple"] = o.Simple + } + return json.Marshal(toSerialize) +} + +type NullableTimestampRep struct { + value *TimestampRep + isSet bool +} + +func (v NullableTimestampRep) Get() *TimestampRep { + return v.value +} + +func (v *NullableTimestampRep) Set(val *TimestampRep) { + v.value = val + v.isSet = true +} + +func (v NullableTimestampRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTimestampRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTimestampRep(val *TimestampRep) *NullableTimestampRep { + return &NullableTimestampRep{value: val, isSet: true} +} + +func (v NullableTimestampRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTimestampRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_token.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_token.go new file mode 100644 index 00000000..7a9a0ce8 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_token.go @@ -0,0 +1,623 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Token struct for Token +type Token struct { + Id string `json:"_id"` + OwnerId string `json:"ownerId"` + MemberId string `json:"memberId"` + Member *MemberSummary `json:"_member,omitempty"` + // A human-friendly name for the access token + Name *string `json:"name,omitempty"` + // A description for the access token + Description *string `json:"description,omitempty"` + CreationDate int64 `json:"creationDate"` + LastModified int64 `json:"lastModified"` + // A list of custom role IDs to use as access limits for the access token + CustomRoleIds []string `json:"customRoleIds,omitempty"` + // An array of policy statements, with three attributes: effect, resources, actions. May be used in place of a built-in or custom role. + InlineRole []Statement `json:"inlineRole,omitempty"` + // Built-in role for the token + Role *string `json:"role,omitempty"` + // The token value. When creating or resetting, contains the entire token value. Otherwise, contains the last four characters. + Token *string `json:"token,omitempty"` + // Whether this is a service token or a personal token + ServiceToken *bool `json:"serviceToken,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The default API version for this token + DefaultApiVersion *int32 `json:"defaultApiVersion,omitempty"` + LastUsed *int64 `json:"lastUsed,omitempty"` +} + +// NewToken instantiates a new Token object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewToken(id string, ownerId string, memberId string, creationDate int64, lastModified int64, links map[string]Link) *Token { + this := Token{} + this.Id = id + this.OwnerId = ownerId + this.MemberId = memberId + this.CreationDate = creationDate + this.LastModified = lastModified + this.Links = links + return &this +} + +// NewTokenWithDefaults instantiates a new Token object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTokenWithDefaults() *Token { + this := Token{} + return &this +} + +// GetId returns the Id field value +func (o *Token) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Token) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Token) SetId(v string) { + o.Id = v +} + +// GetOwnerId returns the OwnerId field value +func (o *Token) GetOwnerId() string { + if o == nil { + var ret string + return ret + } + + return o.OwnerId +} + +// GetOwnerIdOk returns a tuple with the OwnerId field value +// and a boolean to check if the value has been set. +func (o *Token) GetOwnerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.OwnerId, true +} + +// SetOwnerId sets field value +func (o *Token) SetOwnerId(v string) { + o.OwnerId = v +} + +// GetMemberId returns the MemberId field value +func (o *Token) GetMemberId() string { + if o == nil { + var ret string + return ret + } + + return o.MemberId +} + +// GetMemberIdOk returns a tuple with the MemberId field value +// and a boolean to check if the value has been set. +func (o *Token) GetMemberIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MemberId, true +} + +// SetMemberId sets field value +func (o *Token) SetMemberId(v string) { + o.MemberId = v +} + +// GetMember returns the Member field value if set, zero value otherwise. +func (o *Token) GetMember() MemberSummary { + if o == nil || o.Member == nil { + var ret MemberSummary + return ret + } + return *o.Member +} + +// GetMemberOk returns a tuple with the Member field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetMemberOk() (*MemberSummary, bool) { + if o == nil || o.Member == nil { + return nil, false + } + return o.Member, true +} + +// HasMember returns a boolean if a field has been set. +func (o *Token) HasMember() bool { + if o != nil && o.Member != nil { + return true + } + + return false +} + +// SetMember gets a reference to the given MemberSummary and assigns it to the Member field. +func (o *Token) SetMember(v MemberSummary) { + o.Member = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Token) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Token) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Token) SetName(v string) { + o.Name = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Token) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Token) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Token) SetDescription(v string) { + o.Description = &v +} + +// GetCreationDate returns the CreationDate field value +func (o *Token) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *Token) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *Token) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModified returns the LastModified field value +func (o *Token) GetLastModified() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModified +} + +// GetLastModifiedOk returns a tuple with the LastModified field value +// and a boolean to check if the value has been set. +func (o *Token) GetLastModifiedOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModified, true +} + +// SetLastModified sets field value +func (o *Token) SetLastModified(v int64) { + o.LastModified = v +} + +// GetCustomRoleIds returns the CustomRoleIds field value if set, zero value otherwise. +func (o *Token) GetCustomRoleIds() []string { + if o == nil || o.CustomRoleIds == nil { + var ret []string + return ret + } + return o.CustomRoleIds +} + +// GetCustomRoleIdsOk returns a tuple with the CustomRoleIds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetCustomRoleIdsOk() ([]string, bool) { + if o == nil || o.CustomRoleIds == nil { + return nil, false + } + return o.CustomRoleIds, true +} + +// HasCustomRoleIds returns a boolean if a field has been set. +func (o *Token) HasCustomRoleIds() bool { + if o != nil && o.CustomRoleIds != nil { + return true + } + + return false +} + +// SetCustomRoleIds gets a reference to the given []string and assigns it to the CustomRoleIds field. +func (o *Token) SetCustomRoleIds(v []string) { + o.CustomRoleIds = v +} + +// GetInlineRole returns the InlineRole field value if set, zero value otherwise. +func (o *Token) GetInlineRole() []Statement { + if o == nil || o.InlineRole == nil { + var ret []Statement + return ret + } + return o.InlineRole +} + +// GetInlineRoleOk returns a tuple with the InlineRole field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetInlineRoleOk() ([]Statement, bool) { + if o == nil || o.InlineRole == nil { + return nil, false + } + return o.InlineRole, true +} + +// HasInlineRole returns a boolean if a field has been set. +func (o *Token) HasInlineRole() bool { + if o != nil && o.InlineRole != nil { + return true + } + + return false +} + +// SetInlineRole gets a reference to the given []Statement and assigns it to the InlineRole field. +func (o *Token) SetInlineRole(v []Statement) { + o.InlineRole = v +} + +// GetRole returns the Role field value if set, zero value otherwise. +func (o *Token) GetRole() string { + if o == nil || o.Role == nil { + var ret string + return ret + } + return *o.Role +} + +// GetRoleOk returns a tuple with the Role field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetRoleOk() (*string, bool) { + if o == nil || o.Role == nil { + return nil, false + } + return o.Role, true +} + +// HasRole returns a boolean if a field has been set. +func (o *Token) HasRole() bool { + if o != nil && o.Role != nil { + return true + } + + return false +} + +// SetRole gets a reference to the given string and assigns it to the Role field. +func (o *Token) SetRole(v string) { + o.Role = &v +} + +// GetToken returns the Token field value if set, zero value otherwise. +func (o *Token) GetToken() string { + if o == nil || o.Token == nil { + var ret string + return ret + } + return *o.Token +} + +// GetTokenOk returns a tuple with the Token field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetTokenOk() (*string, bool) { + if o == nil || o.Token == nil { + return nil, false + } + return o.Token, true +} + +// HasToken returns a boolean if a field has been set. +func (o *Token) HasToken() bool { + if o != nil && o.Token != nil { + return true + } + + return false +} + +// SetToken gets a reference to the given string and assigns it to the Token field. +func (o *Token) SetToken(v string) { + o.Token = &v +} + +// GetServiceToken returns the ServiceToken field value if set, zero value otherwise. +func (o *Token) GetServiceToken() bool { + if o == nil || o.ServiceToken == nil { + var ret bool + return ret + } + return *o.ServiceToken +} + +// GetServiceTokenOk returns a tuple with the ServiceToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetServiceTokenOk() (*bool, bool) { + if o == nil || o.ServiceToken == nil { + return nil, false + } + return o.ServiceToken, true +} + +// HasServiceToken returns a boolean if a field has been set. +func (o *Token) HasServiceToken() bool { + if o != nil && o.ServiceToken != nil { + return true + } + + return false +} + +// SetServiceToken gets a reference to the given bool and assigns it to the ServiceToken field. +func (o *Token) SetServiceToken(v bool) { + o.ServiceToken = &v +} + +// GetLinks returns the Links field value +func (o *Token) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Token) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Token) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetDefaultApiVersion returns the DefaultApiVersion field value if set, zero value otherwise. +func (o *Token) GetDefaultApiVersion() int32 { + if o == nil || o.DefaultApiVersion == nil { + var ret int32 + return ret + } + return *o.DefaultApiVersion +} + +// GetDefaultApiVersionOk returns a tuple with the DefaultApiVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetDefaultApiVersionOk() (*int32, bool) { + if o == nil || o.DefaultApiVersion == nil { + return nil, false + } + return o.DefaultApiVersion, true +} + +// HasDefaultApiVersion returns a boolean if a field has been set. +func (o *Token) HasDefaultApiVersion() bool { + if o != nil && o.DefaultApiVersion != nil { + return true + } + + return false +} + +// SetDefaultApiVersion gets a reference to the given int32 and assigns it to the DefaultApiVersion field. +func (o *Token) SetDefaultApiVersion(v int32) { + o.DefaultApiVersion = &v +} + +// GetLastUsed returns the LastUsed field value if set, zero value otherwise. +func (o *Token) GetLastUsed() int64 { + if o == nil || o.LastUsed == nil { + var ret int64 + return ret + } + return *o.LastUsed +} + +// GetLastUsedOk returns a tuple with the LastUsed field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Token) GetLastUsedOk() (*int64, bool) { + if o == nil || o.LastUsed == nil { + return nil, false + } + return o.LastUsed, true +} + +// HasLastUsed returns a boolean if a field has been set. +func (o *Token) HasLastUsed() bool { + if o != nil && o.LastUsed != nil { + return true + } + + return false +} + +// SetLastUsed gets a reference to the given int64 and assigns it to the LastUsed field. +func (o *Token) SetLastUsed(v int64) { + o.LastUsed = &v +} + +func (o Token) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["ownerId"] = o.OwnerId + } + if true { + toSerialize["memberId"] = o.MemberId + } + if o.Member != nil { + toSerialize["_member"] = o.Member + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["lastModified"] = o.LastModified + } + if o.CustomRoleIds != nil { + toSerialize["customRoleIds"] = o.CustomRoleIds + } + if o.InlineRole != nil { + toSerialize["inlineRole"] = o.InlineRole + } + if o.Role != nil { + toSerialize["role"] = o.Role + } + if o.Token != nil { + toSerialize["token"] = o.Token + } + if o.ServiceToken != nil { + toSerialize["serviceToken"] = o.ServiceToken + } + if true { + toSerialize["_links"] = o.Links + } + if o.DefaultApiVersion != nil { + toSerialize["defaultApiVersion"] = o.DefaultApiVersion + } + if o.LastUsed != nil { + toSerialize["lastUsed"] = o.LastUsed + } + return json.Marshal(toSerialize) +} + +type NullableToken struct { + value *Token + isSet bool +} + +func (v NullableToken) Get() *Token { + return v.value +} + +func (v *NullableToken) Set(val *Token) { + v.value = val + v.isSet = true +} + +func (v NullableToken) IsSet() bool { + return v.isSet +} + +func (v *NullableToken) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableToken(val *Token) *NullableToken { + return &NullableToken{value: val, isSet: true} +} + +func (v NullableToken) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableToken) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_token_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_token_summary.go new file mode 100644 index 00000000..7bef6993 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_token_summary.go @@ -0,0 +1,263 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TokenSummary struct for TokenSummary +type TokenSummary struct { + Links *map[string]Link `json:"_links,omitempty"` + Id *string `json:"_id,omitempty"` + // The name of the token + Name *string `json:"name,omitempty"` + // The last few characters of the token + Ending *string `json:"ending,omitempty"` + // Whether this is a service token + ServiceToken *bool `json:"serviceToken,omitempty"` +} + +// NewTokenSummary instantiates a new TokenSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTokenSummary() *TokenSummary { + this := TokenSummary{} + return &this +} + +// NewTokenSummaryWithDefaults instantiates a new TokenSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTokenSummaryWithDefaults() *TokenSummary { + this := TokenSummary{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TokenSummary) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TokenSummary) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TokenSummary) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TokenSummary) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *TokenSummary) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TokenSummary) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *TokenSummary) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *TokenSummary) SetId(v string) { + o.Id = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *TokenSummary) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TokenSummary) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *TokenSummary) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *TokenSummary) SetName(v string) { + o.Name = &v +} + +// GetEnding returns the Ending field value if set, zero value otherwise. +func (o *TokenSummary) GetEnding() string { + if o == nil || o.Ending == nil { + var ret string + return ret + } + return *o.Ending +} + +// GetEndingOk returns a tuple with the Ending field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TokenSummary) GetEndingOk() (*string, bool) { + if o == nil || o.Ending == nil { + return nil, false + } + return o.Ending, true +} + +// HasEnding returns a boolean if a field has been set. +func (o *TokenSummary) HasEnding() bool { + if o != nil && o.Ending != nil { + return true + } + + return false +} + +// SetEnding gets a reference to the given string and assigns it to the Ending field. +func (o *TokenSummary) SetEnding(v string) { + o.Ending = &v +} + +// GetServiceToken returns the ServiceToken field value if set, zero value otherwise. +func (o *TokenSummary) GetServiceToken() bool { + if o == nil || o.ServiceToken == nil { + var ret bool + return ret + } + return *o.ServiceToken +} + +// GetServiceTokenOk returns a tuple with the ServiceToken field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TokenSummary) GetServiceTokenOk() (*bool, bool) { + if o == nil || o.ServiceToken == nil { + return nil, false + } + return o.ServiceToken, true +} + +// HasServiceToken returns a boolean if a field has been set. +func (o *TokenSummary) HasServiceToken() bool { + if o != nil && o.ServiceToken != nil { + return true + } + + return false +} + +// SetServiceToken gets a reference to the given bool and assigns it to the ServiceToken field. +func (o *TokenSummary) SetServiceToken(v bool) { + o.ServiceToken = &v +} + +func (o TokenSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Ending != nil { + toSerialize["ending"] = o.Ending + } + if o.ServiceToken != nil { + toSerialize["serviceToken"] = o.ServiceToken + } + return json.Marshal(toSerialize) +} + +type NullableTokenSummary struct { + value *TokenSummary + isSet bool +} + +func (v NullableTokenSummary) Get() *TokenSummary { + return v.value +} + +func (v *NullableTokenSummary) Set(val *TokenSummary) { + v.value = val + v.isSet = true +} + +func (v NullableTokenSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableTokenSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTokenSummary(val *TokenSummary) *NullableTokenSummary { + return &NullableTokenSummary{value: val, isSet: true} +} + +func (v NullableTokenSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTokenSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_tokens.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_tokens.go new file mode 100644 index 00000000..3d8d5fed --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_tokens.go @@ -0,0 +1,190 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Tokens struct for Tokens +type Tokens struct { + // An array of access tokens + Items []Token `json:"items,omitempty"` + Links *map[string]Link `json:"_links,omitempty"` + // The number of access tokens returned + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewTokens instantiates a new Tokens object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTokens() *Tokens { + this := Tokens{} + return &this +} + +// NewTokensWithDefaults instantiates a new Tokens object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTokensWithDefaults() *Tokens { + this := Tokens{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *Tokens) GetItems() []Token { + if o == nil || o.Items == nil { + var ret []Token + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Tokens) GetItemsOk() ([]Token, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *Tokens) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []Token and assigns it to the Items field. +func (o *Tokens) SetItems(v []Token) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Tokens) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Tokens) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Tokens) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Tokens) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *Tokens) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Tokens) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *Tokens) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *Tokens) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o Tokens) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableTokens struct { + value *Tokens + isSet bool +} + +func (v NullableTokens) Get() *Tokens { + return v.value +} + +func (v *NullableTokens) Set(val *Tokens) { + v.value = val + v.isSet = true +} + +func (v NullableTokens) IsSet() bool { + return v.isSet +} + +func (v *NullableTokens) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTokens(val *Tokens) *NullableTokens { + return &NullableTokens{value: val, isSet: true} +} + +func (v NullableTokens) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTokens) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_input.go new file mode 100644 index 00000000..ee3033ec --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_input.go @@ -0,0 +1,200 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TreatmentInput struct for TreatmentInput +type TreatmentInput struct { + // The treatment name + Name string `json:"name"` + // Whether this treatment is the baseline to compare other treatments against + Baseline bool `json:"baseline"` + // The percentage of traffic allocated to this treatment during the iteration + AllocationPercent string `json:"allocationPercent"` + // Details on the flag and variation to use for this treatment + Parameters []TreatmentParameterInput `json:"parameters"` +} + +// NewTreatmentInput instantiates a new TreatmentInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTreatmentInput(name string, baseline bool, allocationPercent string, parameters []TreatmentParameterInput) *TreatmentInput { + this := TreatmentInput{} + this.Name = name + this.Baseline = baseline + this.AllocationPercent = allocationPercent + this.Parameters = parameters + return &this +} + +// NewTreatmentInputWithDefaults instantiates a new TreatmentInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTreatmentInputWithDefaults() *TreatmentInput { + this := TreatmentInput{} + return &this +} + +// GetName returns the Name field value +func (o *TreatmentInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *TreatmentInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *TreatmentInput) SetName(v string) { + o.Name = v +} + +// GetBaseline returns the Baseline field value +func (o *TreatmentInput) GetBaseline() bool { + if o == nil { + var ret bool + return ret + } + + return o.Baseline +} + +// GetBaselineOk returns a tuple with the Baseline field value +// and a boolean to check if the value has been set. +func (o *TreatmentInput) GetBaselineOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Baseline, true +} + +// SetBaseline sets field value +func (o *TreatmentInput) SetBaseline(v bool) { + o.Baseline = v +} + +// GetAllocationPercent returns the AllocationPercent field value +func (o *TreatmentInput) GetAllocationPercent() string { + if o == nil { + var ret string + return ret + } + + return o.AllocationPercent +} + +// GetAllocationPercentOk returns a tuple with the AllocationPercent field value +// and a boolean to check if the value has been set. +func (o *TreatmentInput) GetAllocationPercentOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.AllocationPercent, true +} + +// SetAllocationPercent sets field value +func (o *TreatmentInput) SetAllocationPercent(v string) { + o.AllocationPercent = v +} + +// GetParameters returns the Parameters field value +func (o *TreatmentInput) GetParameters() []TreatmentParameterInput { + if o == nil { + var ret []TreatmentParameterInput + return ret + } + + return o.Parameters +} + +// GetParametersOk returns a tuple with the Parameters field value +// and a boolean to check if the value has been set. +func (o *TreatmentInput) GetParametersOk() ([]TreatmentParameterInput, bool) { + if o == nil { + return nil, false + } + return o.Parameters, true +} + +// SetParameters sets field value +func (o *TreatmentInput) SetParameters(v []TreatmentParameterInput) { + o.Parameters = v +} + +func (o TreatmentInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["baseline"] = o.Baseline + } + if true { + toSerialize["allocationPercent"] = o.AllocationPercent + } + if true { + toSerialize["parameters"] = o.Parameters + } + return json.Marshal(toSerialize) +} + +type NullableTreatmentInput struct { + value *TreatmentInput + isSet bool +} + +func (v NullableTreatmentInput) Get() *TreatmentInput { + return v.value +} + +func (v *NullableTreatmentInput) Set(val *TreatmentInput) { + v.value = val + v.isSet = true +} + +func (v NullableTreatmentInput) IsSet() bool { + return v.isSet +} + +func (v *NullableTreatmentInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTreatmentInput(val *TreatmentInput) *NullableTreatmentInput { + return &NullableTreatmentInput{value: val, isSet: true} +} + +func (v NullableTreatmentInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTreatmentInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_parameter_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_parameter_input.go new file mode 100644 index 00000000..2a8c8ac0 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_parameter_input.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TreatmentParameterInput struct for TreatmentParameterInput +type TreatmentParameterInput struct { + // The flag key + FlagKey string `json:"flagKey"` + // The ID of the flag variation + VariationId string `json:"variationId"` +} + +// NewTreatmentParameterInput instantiates a new TreatmentParameterInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTreatmentParameterInput(flagKey string, variationId string) *TreatmentParameterInput { + this := TreatmentParameterInput{} + this.FlagKey = flagKey + this.VariationId = variationId + return &this +} + +// NewTreatmentParameterInputWithDefaults instantiates a new TreatmentParameterInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTreatmentParameterInputWithDefaults() *TreatmentParameterInput { + this := TreatmentParameterInput{} + return &this +} + +// GetFlagKey returns the FlagKey field value +func (o *TreatmentParameterInput) GetFlagKey() string { + if o == nil { + var ret string + return ret + } + + return o.FlagKey +} + +// GetFlagKeyOk returns a tuple with the FlagKey field value +// and a boolean to check if the value has been set. +func (o *TreatmentParameterInput) GetFlagKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.FlagKey, true +} + +// SetFlagKey sets field value +func (o *TreatmentParameterInput) SetFlagKey(v string) { + o.FlagKey = v +} + +// GetVariationId returns the VariationId field value +func (o *TreatmentParameterInput) GetVariationId() string { + if o == nil { + var ret string + return ret + } + + return o.VariationId +} + +// GetVariationIdOk returns a tuple with the VariationId field value +// and a boolean to check if the value has been set. +func (o *TreatmentParameterInput) GetVariationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.VariationId, true +} + +// SetVariationId sets field value +func (o *TreatmentParameterInput) SetVariationId(v string) { + o.VariationId = v +} + +func (o TreatmentParameterInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["flagKey"] = o.FlagKey + } + if true { + toSerialize["variationId"] = o.VariationId + } + return json.Marshal(toSerialize) +} + +type NullableTreatmentParameterInput struct { + value *TreatmentParameterInput + isSet bool +} + +func (v NullableTreatmentParameterInput) Get() *TreatmentParameterInput { + return v.value +} + +func (v *NullableTreatmentParameterInput) Set(val *TreatmentParameterInput) { + v.value = val + v.isSet = true +} + +func (v NullableTreatmentParameterInput) IsSet() bool { + return v.isSet +} + +func (v *NullableTreatmentParameterInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTreatmentParameterInput(val *TreatmentParameterInput) *NullableTreatmentParameterInput { + return &NullableTreatmentParameterInput{value: val, isSet: true} +} + +func (v NullableTreatmentParameterInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTreatmentParameterInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_rep.go new file mode 100644 index 00000000..f0247eeb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_rep.go @@ -0,0 +1,251 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TreatmentRep struct for TreatmentRep +type TreatmentRep struct { + // The treatment ID. This is the variation ID from the flag. + Id *string `json:"_id,omitempty"` + // The treatment name. This is the variation name from the flag. + Name string `json:"name"` + // The percentage of traffic allocated to this treatment during the iteration + AllocationPercent string `json:"allocationPercent"` + // Whether this treatment is the baseline to compare other treatments against + Baseline *bool `json:"baseline,omitempty"` + // Details on the flag and variation used for this treatment + Parameters []ParameterRep `json:"parameters,omitempty"` +} + +// NewTreatmentRep instantiates a new TreatmentRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTreatmentRep(name string, allocationPercent string) *TreatmentRep { + this := TreatmentRep{} + this.Name = name + this.AllocationPercent = allocationPercent + return &this +} + +// NewTreatmentRepWithDefaults instantiates a new TreatmentRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTreatmentRepWithDefaults() *TreatmentRep { + this := TreatmentRep{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *TreatmentRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *TreatmentRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *TreatmentRep) SetId(v string) { + o.Id = &v +} + +// GetName returns the Name field value +func (o *TreatmentRep) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *TreatmentRep) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *TreatmentRep) SetName(v string) { + o.Name = v +} + +// GetAllocationPercent returns the AllocationPercent field value +func (o *TreatmentRep) GetAllocationPercent() string { + if o == nil { + var ret string + return ret + } + + return o.AllocationPercent +} + +// GetAllocationPercentOk returns a tuple with the AllocationPercent field value +// and a boolean to check if the value has been set. +func (o *TreatmentRep) GetAllocationPercentOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.AllocationPercent, true +} + +// SetAllocationPercent sets field value +func (o *TreatmentRep) SetAllocationPercent(v string) { + o.AllocationPercent = v +} + +// GetBaseline returns the Baseline field value if set, zero value otherwise. +func (o *TreatmentRep) GetBaseline() bool { + if o == nil || o.Baseline == nil { + var ret bool + return ret + } + return *o.Baseline +} + +// GetBaselineOk returns a tuple with the Baseline field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentRep) GetBaselineOk() (*bool, bool) { + if o == nil || o.Baseline == nil { + return nil, false + } + return o.Baseline, true +} + +// HasBaseline returns a boolean if a field has been set. +func (o *TreatmentRep) HasBaseline() bool { + if o != nil && o.Baseline != nil { + return true + } + + return false +} + +// SetBaseline gets a reference to the given bool and assigns it to the Baseline field. +func (o *TreatmentRep) SetBaseline(v bool) { + o.Baseline = &v +} + +// GetParameters returns the Parameters field value if set, zero value otherwise. +func (o *TreatmentRep) GetParameters() []ParameterRep { + if o == nil || o.Parameters == nil { + var ret []ParameterRep + return ret + } + return o.Parameters +} + +// GetParametersOk returns a tuple with the Parameters field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentRep) GetParametersOk() ([]ParameterRep, bool) { + if o == nil || o.Parameters == nil { + return nil, false + } + return o.Parameters, true +} + +// HasParameters returns a boolean if a field has been set. +func (o *TreatmentRep) HasParameters() bool { + if o != nil && o.Parameters != nil { + return true + } + + return false +} + +// SetParameters gets a reference to the given []ParameterRep and assigns it to the Parameters field. +func (o *TreatmentRep) SetParameters(v []ParameterRep) { + o.Parameters = v +} + +func (o TreatmentRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["allocationPercent"] = o.AllocationPercent + } + if o.Baseline != nil { + toSerialize["baseline"] = o.Baseline + } + if o.Parameters != nil { + toSerialize["parameters"] = o.Parameters + } + return json.Marshal(toSerialize) +} + +type NullableTreatmentRep struct { + value *TreatmentRep + isSet bool +} + +func (v NullableTreatmentRep) Get() *TreatmentRep { + return v.value +} + +func (v *NullableTreatmentRep) Set(val *TreatmentRep) { + v.value = val + v.isSet = true +} + +func (v NullableTreatmentRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTreatmentRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTreatmentRep(val *TreatmentRep) *NullableTreatmentRep { + return &NullableTreatmentRep{value: val, isSet: true} +} + +func (v NullableTreatmentRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTreatmentRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_result_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_result_rep.go new file mode 100644 index 00000000..7be5ef1f --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_treatment_result_rep.go @@ -0,0 +1,779 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TreatmentResultRep struct for TreatmentResultRep +type TreatmentResultRep struct { + // The ID of the treatment + TreatmentId *string `json:"treatmentId,omitempty"` + // The name of the treatment + TreatmentName *string `json:"treatmentName,omitempty"` + // The average value of the variation in this sample. It doesn’t capture the uncertainty in the measurement, so it should not be the only measurement you use to make decisions. + Mean *float32 `json:"mean,omitempty"` + // The mean of the data, with no priors effecting the result. + DataMean *float32 `json:"dataMean,omitempty"` + // The standard deviation of the data, with no priors effecting the result. + DataStdDev *float32 `json:"dataStdDev,omitempty"` + CredibleInterval *CredibleIntervalRep `json:"credibleInterval,omitempty"` + // The likelihood that this variation has the biggest effect on the primary metric. The variation with the highest probability is likely the best of the variations you're testing + PBest *float32 `json:"pBest,omitempty"` + // Estimates of the relative difference between this treatment's mean and the mean of each other treatment + RelativeDifferences []RelativeDifferenceRep `json:"relativeDifferences,omitempty"` + // The number of units exposed to this treatment that have event values, including those that are configured to default to 0 + Units *int64 `json:"units,omitempty"` + // The number of units exposed to this treatment. + Traffic *int64 `json:"traffic,omitempty"` + // The sum of the event values for the units exposed to this treatment. + EventValuesSum *float32 `json:"eventValuesSum,omitempty"` + Distribution *Distribution `json:"distribution,omitempty"` + // The outcome-covariate correlation + Correlation *float32 `json:"correlation,omitempty"` + // The ratio of the outcome SD to covariate SD + StandardDeviationRatio *float32 `json:"standardDeviationRatio,omitempty"` + // The imbalance between the covariate mean for the arm and the covariate mean for the experiment + CovariateImbalance *float32 `json:"covariateImbalance,omitempty"` + // The reduction in variance resulting from CUPED + VarianceReduction *float32 `json:"varianceReduction,omitempty"` + // The model used to calculate the results. Parameters specific to this model will be defined under the field under the same name + Model *string `json:"model,omitempty"` + BayesianNormal *BayesianNormalStatsRep `json:"bayesianNormal,omitempty"` + BayesianBeta *BayesianBetaBinomialStatsRep `json:"bayesianBeta,omitempty"` +} + +// NewTreatmentResultRep instantiates a new TreatmentResultRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTreatmentResultRep() *TreatmentResultRep { + this := TreatmentResultRep{} + return &this +} + +// NewTreatmentResultRepWithDefaults instantiates a new TreatmentResultRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTreatmentResultRepWithDefaults() *TreatmentResultRep { + this := TreatmentResultRep{} + return &this +} + +// GetTreatmentId returns the TreatmentId field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetTreatmentId() string { + if o == nil || o.TreatmentId == nil { + var ret string + return ret + } + return *o.TreatmentId +} + +// GetTreatmentIdOk returns a tuple with the TreatmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetTreatmentIdOk() (*string, bool) { + if o == nil || o.TreatmentId == nil { + return nil, false + } + return o.TreatmentId, true +} + +// HasTreatmentId returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasTreatmentId() bool { + if o != nil && o.TreatmentId != nil { + return true + } + + return false +} + +// SetTreatmentId gets a reference to the given string and assigns it to the TreatmentId field. +func (o *TreatmentResultRep) SetTreatmentId(v string) { + o.TreatmentId = &v +} + +// GetTreatmentName returns the TreatmentName field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetTreatmentName() string { + if o == nil || o.TreatmentName == nil { + var ret string + return ret + } + return *o.TreatmentName +} + +// GetTreatmentNameOk returns a tuple with the TreatmentName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetTreatmentNameOk() (*string, bool) { + if o == nil || o.TreatmentName == nil { + return nil, false + } + return o.TreatmentName, true +} + +// HasTreatmentName returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasTreatmentName() bool { + if o != nil && o.TreatmentName != nil { + return true + } + + return false +} + +// SetTreatmentName gets a reference to the given string and assigns it to the TreatmentName field. +func (o *TreatmentResultRep) SetTreatmentName(v string) { + o.TreatmentName = &v +} + +// GetMean returns the Mean field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetMean() float32 { + if o == nil || o.Mean == nil { + var ret float32 + return ret + } + return *o.Mean +} + +// GetMeanOk returns a tuple with the Mean field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetMeanOk() (*float32, bool) { + if o == nil || o.Mean == nil { + return nil, false + } + return o.Mean, true +} + +// HasMean returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasMean() bool { + if o != nil && o.Mean != nil { + return true + } + + return false +} + +// SetMean gets a reference to the given float32 and assigns it to the Mean field. +func (o *TreatmentResultRep) SetMean(v float32) { + o.Mean = &v +} + +// GetDataMean returns the DataMean field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetDataMean() float32 { + if o == nil || o.DataMean == nil { + var ret float32 + return ret + } + return *o.DataMean +} + +// GetDataMeanOk returns a tuple with the DataMean field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetDataMeanOk() (*float32, bool) { + if o == nil || o.DataMean == nil { + return nil, false + } + return o.DataMean, true +} + +// HasDataMean returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasDataMean() bool { + if o != nil && o.DataMean != nil { + return true + } + + return false +} + +// SetDataMean gets a reference to the given float32 and assigns it to the DataMean field. +func (o *TreatmentResultRep) SetDataMean(v float32) { + o.DataMean = &v +} + +// GetDataStdDev returns the DataStdDev field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetDataStdDev() float32 { + if o == nil || o.DataStdDev == nil { + var ret float32 + return ret + } + return *o.DataStdDev +} + +// GetDataStdDevOk returns a tuple with the DataStdDev field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetDataStdDevOk() (*float32, bool) { + if o == nil || o.DataStdDev == nil { + return nil, false + } + return o.DataStdDev, true +} + +// HasDataStdDev returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasDataStdDev() bool { + if o != nil && o.DataStdDev != nil { + return true + } + + return false +} + +// SetDataStdDev gets a reference to the given float32 and assigns it to the DataStdDev field. +func (o *TreatmentResultRep) SetDataStdDev(v float32) { + o.DataStdDev = &v +} + +// GetCredibleInterval returns the CredibleInterval field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetCredibleInterval() CredibleIntervalRep { + if o == nil || o.CredibleInterval == nil { + var ret CredibleIntervalRep + return ret + } + return *o.CredibleInterval +} + +// GetCredibleIntervalOk returns a tuple with the CredibleInterval field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetCredibleIntervalOk() (*CredibleIntervalRep, bool) { + if o == nil || o.CredibleInterval == nil { + return nil, false + } + return o.CredibleInterval, true +} + +// HasCredibleInterval returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasCredibleInterval() bool { + if o != nil && o.CredibleInterval != nil { + return true + } + + return false +} + +// SetCredibleInterval gets a reference to the given CredibleIntervalRep and assigns it to the CredibleInterval field. +func (o *TreatmentResultRep) SetCredibleInterval(v CredibleIntervalRep) { + o.CredibleInterval = &v +} + +// GetPBest returns the PBest field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetPBest() float32 { + if o == nil || o.PBest == nil { + var ret float32 + return ret + } + return *o.PBest +} + +// GetPBestOk returns a tuple with the PBest field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetPBestOk() (*float32, bool) { + if o == nil || o.PBest == nil { + return nil, false + } + return o.PBest, true +} + +// HasPBest returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasPBest() bool { + if o != nil && o.PBest != nil { + return true + } + + return false +} + +// SetPBest gets a reference to the given float32 and assigns it to the PBest field. +func (o *TreatmentResultRep) SetPBest(v float32) { + o.PBest = &v +} + +// GetRelativeDifferences returns the RelativeDifferences field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetRelativeDifferences() []RelativeDifferenceRep { + if o == nil || o.RelativeDifferences == nil { + var ret []RelativeDifferenceRep + return ret + } + return o.RelativeDifferences +} + +// GetRelativeDifferencesOk returns a tuple with the RelativeDifferences field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetRelativeDifferencesOk() ([]RelativeDifferenceRep, bool) { + if o == nil || o.RelativeDifferences == nil { + return nil, false + } + return o.RelativeDifferences, true +} + +// HasRelativeDifferences returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasRelativeDifferences() bool { + if o != nil && o.RelativeDifferences != nil { + return true + } + + return false +} + +// SetRelativeDifferences gets a reference to the given []RelativeDifferenceRep and assigns it to the RelativeDifferences field. +func (o *TreatmentResultRep) SetRelativeDifferences(v []RelativeDifferenceRep) { + o.RelativeDifferences = v +} + +// GetUnits returns the Units field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetUnits() int64 { + if o == nil || o.Units == nil { + var ret int64 + return ret + } + return *o.Units +} + +// GetUnitsOk returns a tuple with the Units field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetUnitsOk() (*int64, bool) { + if o == nil || o.Units == nil { + return nil, false + } + return o.Units, true +} + +// HasUnits returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasUnits() bool { + if o != nil && o.Units != nil { + return true + } + + return false +} + +// SetUnits gets a reference to the given int64 and assigns it to the Units field. +func (o *TreatmentResultRep) SetUnits(v int64) { + o.Units = &v +} + +// GetTraffic returns the Traffic field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetTraffic() int64 { + if o == nil || o.Traffic == nil { + var ret int64 + return ret + } + return *o.Traffic +} + +// GetTrafficOk returns a tuple with the Traffic field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetTrafficOk() (*int64, bool) { + if o == nil || o.Traffic == nil { + return nil, false + } + return o.Traffic, true +} + +// HasTraffic returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasTraffic() bool { + if o != nil && o.Traffic != nil { + return true + } + + return false +} + +// SetTraffic gets a reference to the given int64 and assigns it to the Traffic field. +func (o *TreatmentResultRep) SetTraffic(v int64) { + o.Traffic = &v +} + +// GetEventValuesSum returns the EventValuesSum field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetEventValuesSum() float32 { + if o == nil || o.EventValuesSum == nil { + var ret float32 + return ret + } + return *o.EventValuesSum +} + +// GetEventValuesSumOk returns a tuple with the EventValuesSum field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetEventValuesSumOk() (*float32, bool) { + if o == nil || o.EventValuesSum == nil { + return nil, false + } + return o.EventValuesSum, true +} + +// HasEventValuesSum returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasEventValuesSum() bool { + if o != nil && o.EventValuesSum != nil { + return true + } + + return false +} + +// SetEventValuesSum gets a reference to the given float32 and assigns it to the EventValuesSum field. +func (o *TreatmentResultRep) SetEventValuesSum(v float32) { + o.EventValuesSum = &v +} + +// GetDistribution returns the Distribution field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetDistribution() Distribution { + if o == nil || o.Distribution == nil { + var ret Distribution + return ret + } + return *o.Distribution +} + +// GetDistributionOk returns a tuple with the Distribution field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetDistributionOk() (*Distribution, bool) { + if o == nil || o.Distribution == nil { + return nil, false + } + return o.Distribution, true +} + +// HasDistribution returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasDistribution() bool { + if o != nil && o.Distribution != nil { + return true + } + + return false +} + +// SetDistribution gets a reference to the given Distribution and assigns it to the Distribution field. +func (o *TreatmentResultRep) SetDistribution(v Distribution) { + o.Distribution = &v +} + +// GetCorrelation returns the Correlation field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetCorrelation() float32 { + if o == nil || o.Correlation == nil { + var ret float32 + return ret + } + return *o.Correlation +} + +// GetCorrelationOk returns a tuple with the Correlation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetCorrelationOk() (*float32, bool) { + if o == nil || o.Correlation == nil { + return nil, false + } + return o.Correlation, true +} + +// HasCorrelation returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasCorrelation() bool { + if o != nil && o.Correlation != nil { + return true + } + + return false +} + +// SetCorrelation gets a reference to the given float32 and assigns it to the Correlation field. +func (o *TreatmentResultRep) SetCorrelation(v float32) { + o.Correlation = &v +} + +// GetStandardDeviationRatio returns the StandardDeviationRatio field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetStandardDeviationRatio() float32 { + if o == nil || o.StandardDeviationRatio == nil { + var ret float32 + return ret + } + return *o.StandardDeviationRatio +} + +// GetStandardDeviationRatioOk returns a tuple with the StandardDeviationRatio field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetStandardDeviationRatioOk() (*float32, bool) { + if o == nil || o.StandardDeviationRatio == nil { + return nil, false + } + return o.StandardDeviationRatio, true +} + +// HasStandardDeviationRatio returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasStandardDeviationRatio() bool { + if o != nil && o.StandardDeviationRatio != nil { + return true + } + + return false +} + +// SetStandardDeviationRatio gets a reference to the given float32 and assigns it to the StandardDeviationRatio field. +func (o *TreatmentResultRep) SetStandardDeviationRatio(v float32) { + o.StandardDeviationRatio = &v +} + +// GetCovariateImbalance returns the CovariateImbalance field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetCovariateImbalance() float32 { + if o == nil || o.CovariateImbalance == nil { + var ret float32 + return ret + } + return *o.CovariateImbalance +} + +// GetCovariateImbalanceOk returns a tuple with the CovariateImbalance field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetCovariateImbalanceOk() (*float32, bool) { + if o == nil || o.CovariateImbalance == nil { + return nil, false + } + return o.CovariateImbalance, true +} + +// HasCovariateImbalance returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasCovariateImbalance() bool { + if o != nil && o.CovariateImbalance != nil { + return true + } + + return false +} + +// SetCovariateImbalance gets a reference to the given float32 and assigns it to the CovariateImbalance field. +func (o *TreatmentResultRep) SetCovariateImbalance(v float32) { + o.CovariateImbalance = &v +} + +// GetVarianceReduction returns the VarianceReduction field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetVarianceReduction() float32 { + if o == nil || o.VarianceReduction == nil { + var ret float32 + return ret + } + return *o.VarianceReduction +} + +// GetVarianceReductionOk returns a tuple with the VarianceReduction field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetVarianceReductionOk() (*float32, bool) { + if o == nil || o.VarianceReduction == nil { + return nil, false + } + return o.VarianceReduction, true +} + +// HasVarianceReduction returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasVarianceReduction() bool { + if o != nil && o.VarianceReduction != nil { + return true + } + + return false +} + +// SetVarianceReduction gets a reference to the given float32 and assigns it to the VarianceReduction field. +func (o *TreatmentResultRep) SetVarianceReduction(v float32) { + o.VarianceReduction = &v +} + +// GetModel returns the Model field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetModel() string { + if o == nil || o.Model == nil { + var ret string + return ret + } + return *o.Model +} + +// GetModelOk returns a tuple with the Model field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetModelOk() (*string, bool) { + if o == nil || o.Model == nil { + return nil, false + } + return o.Model, true +} + +// HasModel returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasModel() bool { + if o != nil && o.Model != nil { + return true + } + + return false +} + +// SetModel gets a reference to the given string and assigns it to the Model field. +func (o *TreatmentResultRep) SetModel(v string) { + o.Model = &v +} + +// GetBayesianNormal returns the BayesianNormal field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetBayesianNormal() BayesianNormalStatsRep { + if o == nil || o.BayesianNormal == nil { + var ret BayesianNormalStatsRep + return ret + } + return *o.BayesianNormal +} + +// GetBayesianNormalOk returns a tuple with the BayesianNormal field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetBayesianNormalOk() (*BayesianNormalStatsRep, bool) { + if o == nil || o.BayesianNormal == nil { + return nil, false + } + return o.BayesianNormal, true +} + +// HasBayesianNormal returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasBayesianNormal() bool { + if o != nil && o.BayesianNormal != nil { + return true + } + + return false +} + +// SetBayesianNormal gets a reference to the given BayesianNormalStatsRep and assigns it to the BayesianNormal field. +func (o *TreatmentResultRep) SetBayesianNormal(v BayesianNormalStatsRep) { + o.BayesianNormal = &v +} + +// GetBayesianBeta returns the BayesianBeta field value if set, zero value otherwise. +func (o *TreatmentResultRep) GetBayesianBeta() BayesianBetaBinomialStatsRep { + if o == nil || o.BayesianBeta == nil { + var ret BayesianBetaBinomialStatsRep + return ret + } + return *o.BayesianBeta +} + +// GetBayesianBetaOk returns a tuple with the BayesianBeta field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TreatmentResultRep) GetBayesianBetaOk() (*BayesianBetaBinomialStatsRep, bool) { + if o == nil || o.BayesianBeta == nil { + return nil, false + } + return o.BayesianBeta, true +} + +// HasBayesianBeta returns a boolean if a field has been set. +func (o *TreatmentResultRep) HasBayesianBeta() bool { + if o != nil && o.BayesianBeta != nil { + return true + } + + return false +} + +// SetBayesianBeta gets a reference to the given BayesianBetaBinomialStatsRep and assigns it to the BayesianBeta field. +func (o *TreatmentResultRep) SetBayesianBeta(v BayesianBetaBinomialStatsRep) { + o.BayesianBeta = &v +} + +func (o TreatmentResultRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.TreatmentId != nil { + toSerialize["treatmentId"] = o.TreatmentId + } + if o.TreatmentName != nil { + toSerialize["treatmentName"] = o.TreatmentName + } + if o.Mean != nil { + toSerialize["mean"] = o.Mean + } + if o.DataMean != nil { + toSerialize["dataMean"] = o.DataMean + } + if o.DataStdDev != nil { + toSerialize["dataStdDev"] = o.DataStdDev + } + if o.CredibleInterval != nil { + toSerialize["credibleInterval"] = o.CredibleInterval + } + if o.PBest != nil { + toSerialize["pBest"] = o.PBest + } + if o.RelativeDifferences != nil { + toSerialize["relativeDifferences"] = o.RelativeDifferences + } + if o.Units != nil { + toSerialize["units"] = o.Units + } + if o.Traffic != nil { + toSerialize["traffic"] = o.Traffic + } + if o.EventValuesSum != nil { + toSerialize["eventValuesSum"] = o.EventValuesSum + } + if o.Distribution != nil { + toSerialize["distribution"] = o.Distribution + } + if o.Correlation != nil { + toSerialize["correlation"] = o.Correlation + } + if o.StandardDeviationRatio != nil { + toSerialize["standardDeviationRatio"] = o.StandardDeviationRatio + } + if o.CovariateImbalance != nil { + toSerialize["covariateImbalance"] = o.CovariateImbalance + } + if o.VarianceReduction != nil { + toSerialize["varianceReduction"] = o.VarianceReduction + } + if o.Model != nil { + toSerialize["model"] = o.Model + } + if o.BayesianNormal != nil { + toSerialize["bayesianNormal"] = o.BayesianNormal + } + if o.BayesianBeta != nil { + toSerialize["bayesianBeta"] = o.BayesianBeta + } + return json.Marshal(toSerialize) +} + +type NullableTreatmentResultRep struct { + value *TreatmentResultRep + isSet bool +} + +func (v NullableTreatmentResultRep) Get() *TreatmentResultRep { + return v.value +} + +func (v *NullableTreatmentResultRep) Set(val *TreatmentResultRep) { + v.value = val + v.isSet = true +} + +func (v NullableTreatmentResultRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTreatmentResultRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTreatmentResultRep(val *TreatmentResultRep) *NullableTreatmentResultRep { + return &NullableTreatmentResultRep{value: val, isSet: true} +} + +func (v NullableTreatmentResultRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTreatmentResultRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_post.go new file mode 100644 index 00000000..3210c8e6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_post.go @@ -0,0 +1,184 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TriggerPost struct for TriggerPost +type TriggerPost struct { + // Optional comment describing the trigger + Comment *string `json:"comment,omitempty"` + // The action to perform when triggering. This should be an array with a single object that looks like {\"kind\": \"flag_action\"}. Supported flag actions are turnFlagOn and turnFlagOff. + Instructions []map[string]interface{} `json:"instructions,omitempty"` + // The unique identifier of the integration for your trigger. Use generic-trigger for integrations not explicitly supported. + IntegrationKey string `json:"integrationKey"` +} + +// NewTriggerPost instantiates a new TriggerPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTriggerPost(integrationKey string) *TriggerPost { + this := TriggerPost{} + this.IntegrationKey = integrationKey + return &this +} + +// NewTriggerPostWithDefaults instantiates a new TriggerPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTriggerPostWithDefaults() *TriggerPost { + this := TriggerPost{} + return &this +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *TriggerPost) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerPost) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *TriggerPost) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *TriggerPost) SetComment(v string) { + o.Comment = &v +} + +// GetInstructions returns the Instructions field value if set, zero value otherwise. +func (o *TriggerPost) GetInstructions() []map[string]interface{} { + if o == nil || o.Instructions == nil { + var ret []map[string]interface{} + return ret + } + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerPost) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil || o.Instructions == nil { + return nil, false + } + return o.Instructions, true +} + +// HasInstructions returns a boolean if a field has been set. +func (o *TriggerPost) HasInstructions() bool { + if o != nil && o.Instructions != nil { + return true + } + + return false +} + +// SetInstructions gets a reference to the given []map[string]interface{} and assigns it to the Instructions field. +func (o *TriggerPost) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetIntegrationKey returns the IntegrationKey field value +func (o *TriggerPost) GetIntegrationKey() string { + if o == nil { + var ret string + return ret + } + + return o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value +// and a boolean to check if the value has been set. +func (o *TriggerPost) GetIntegrationKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.IntegrationKey, true +} + +// SetIntegrationKey sets field value +func (o *TriggerPost) SetIntegrationKey(v string) { + o.IntegrationKey = v +} + +func (o TriggerPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + if o.Instructions != nil { + toSerialize["instructions"] = o.Instructions + } + if true { + toSerialize["integrationKey"] = o.IntegrationKey + } + return json.Marshal(toSerialize) +} + +type NullableTriggerPost struct { + value *TriggerPost + isSet bool +} + +func (v NullableTriggerPost) Get() *TriggerPost { + return v.value +} + +func (v *NullableTriggerPost) Set(val *TriggerPost) { + v.value = val + v.isSet = true +} + +func (v NullableTriggerPost) IsSet() bool { + return v.isSet +} + +func (v *NullableTriggerPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTriggerPost(val *TriggerPost) *NullableTriggerPost { + return &NullableTriggerPost{value: val, isSet: true} +} + +func (v NullableTriggerPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTriggerPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_collection_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_collection_rep.go new file mode 100644 index 00000000..2ff3b666 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_collection_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TriggerWorkflowCollectionRep struct for TriggerWorkflowCollectionRep +type TriggerWorkflowCollectionRep struct { + // An array of flag triggers + Items []TriggerWorkflowRep `json:"items,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewTriggerWorkflowCollectionRep instantiates a new TriggerWorkflowCollectionRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTriggerWorkflowCollectionRep() *TriggerWorkflowCollectionRep { + this := TriggerWorkflowCollectionRep{} + return &this +} + +// NewTriggerWorkflowCollectionRepWithDefaults instantiates a new TriggerWorkflowCollectionRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTriggerWorkflowCollectionRepWithDefaults() *TriggerWorkflowCollectionRep { + this := TriggerWorkflowCollectionRep{} + return &this +} + +// GetItems returns the Items field value if set, zero value otherwise. +func (o *TriggerWorkflowCollectionRep) GetItems() []TriggerWorkflowRep { + if o == nil || o.Items == nil { + var ret []TriggerWorkflowRep + return ret + } + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowCollectionRep) GetItemsOk() ([]TriggerWorkflowRep, bool) { + if o == nil || o.Items == nil { + return nil, false + } + return o.Items, true +} + +// HasItems returns a boolean if a field has been set. +func (o *TriggerWorkflowCollectionRep) HasItems() bool { + if o != nil && o.Items != nil { + return true + } + + return false +} + +// SetItems gets a reference to the given []TriggerWorkflowRep and assigns it to the Items field. +func (o *TriggerWorkflowCollectionRep) SetItems(v []TriggerWorkflowRep) { + o.Items = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TriggerWorkflowCollectionRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowCollectionRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TriggerWorkflowCollectionRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TriggerWorkflowCollectionRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o TriggerWorkflowCollectionRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Items != nil { + toSerialize["items"] = o.Items + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableTriggerWorkflowCollectionRep struct { + value *TriggerWorkflowCollectionRep + isSet bool +} + +func (v NullableTriggerWorkflowCollectionRep) Get() *TriggerWorkflowCollectionRep { + return v.value +} + +func (v *NullableTriggerWorkflowCollectionRep) Set(val *TriggerWorkflowCollectionRep) { + v.value = val + v.isSet = true +} + +func (v NullableTriggerWorkflowCollectionRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTriggerWorkflowCollectionRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTriggerWorkflowCollectionRep(val *TriggerWorkflowCollectionRep) *NullableTriggerWorkflowCollectionRep { + return &NullableTriggerWorkflowCollectionRep{value: val, isSet: true} +} + +func (v NullableTriggerWorkflowCollectionRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTriggerWorkflowCollectionRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_rep.go new file mode 100644 index 00000000..1dd0e636 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_trigger_workflow_rep.go @@ -0,0 +1,556 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// TriggerWorkflowRep struct for TriggerWorkflowRep +type TriggerWorkflowRep struct { + Id *string `json:"_id,omitempty"` + // The flag trigger version + Version *int32 `json:"_version,omitempty"` + CreationDate *int64 `json:"_creationDate,omitempty"` + // The ID of the flag trigger maintainer + MaintainerId *string `json:"_maintainerId,omitempty"` + Maintainer *MemberSummary `json:"_maintainer,omitempty"` + // Whether the flag trigger is currently enabled + Enabled *bool `json:"enabled,omitempty"` + // The unique identifier of the integration for your trigger + IntegrationKey *string `json:"_integrationKey,omitempty"` + Instructions []map[string]interface{} `json:"instructions,omitempty"` + LastTriggeredAt *int64 `json:"_lastTriggeredAt,omitempty"` + // Details on recent flag trigger requests. + RecentTriggerBodies []RecentTriggerBody `json:"_recentTriggerBodies,omitempty"` + // Number of times the trigger has been executed + TriggerCount *int32 `json:"_triggerCount,omitempty"` + // The unguessable URL for this flag trigger + TriggerURL *string `json:"triggerURL,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewTriggerWorkflowRep instantiates a new TriggerWorkflowRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTriggerWorkflowRep() *TriggerWorkflowRep { + this := TriggerWorkflowRep{} + return &this +} + +// NewTriggerWorkflowRepWithDefaults instantiates a new TriggerWorkflowRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTriggerWorkflowRepWithDefaults() *TriggerWorkflowRep { + this := TriggerWorkflowRep{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *TriggerWorkflowRep) SetId(v string) { + o.Id = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *TriggerWorkflowRep) SetVersion(v int32) { + o.Version = &v +} + +// GetCreationDate returns the CreationDate field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetCreationDate() int64 { + if o == nil || o.CreationDate == nil { + var ret int64 + return ret + } + return *o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetCreationDateOk() (*int64, bool) { + if o == nil || o.CreationDate == nil { + return nil, false + } + return o.CreationDate, true +} + +// HasCreationDate returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasCreationDate() bool { + if o != nil && o.CreationDate != nil { + return true + } + + return false +} + +// SetCreationDate gets a reference to the given int64 and assigns it to the CreationDate field. +func (o *TriggerWorkflowRep) SetCreationDate(v int64) { + o.CreationDate = &v +} + +// GetMaintainerId returns the MaintainerId field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetMaintainerId() string { + if o == nil || o.MaintainerId == nil { + var ret string + return ret + } + return *o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetMaintainerIdOk() (*string, bool) { + if o == nil || o.MaintainerId == nil { + return nil, false + } + return o.MaintainerId, true +} + +// HasMaintainerId returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasMaintainerId() bool { + if o != nil && o.MaintainerId != nil { + return true + } + + return false +} + +// SetMaintainerId gets a reference to the given string and assigns it to the MaintainerId field. +func (o *TriggerWorkflowRep) SetMaintainerId(v string) { + o.MaintainerId = &v +} + +// GetMaintainer returns the Maintainer field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetMaintainer() MemberSummary { + if o == nil || o.Maintainer == nil { + var ret MemberSummary + return ret + } + return *o.Maintainer +} + +// GetMaintainerOk returns a tuple with the Maintainer field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetMaintainerOk() (*MemberSummary, bool) { + if o == nil || o.Maintainer == nil { + return nil, false + } + return o.Maintainer, true +} + +// HasMaintainer returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasMaintainer() bool { + if o != nil && o.Maintainer != nil { + return true + } + + return false +} + +// SetMaintainer gets a reference to the given MemberSummary and assigns it to the Maintainer field. +func (o *TriggerWorkflowRep) SetMaintainer(v MemberSummary) { + o.Maintainer = &v +} + +// GetEnabled returns the Enabled field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetEnabled() bool { + if o == nil || o.Enabled == nil { + var ret bool + return ret + } + return *o.Enabled +} + +// GetEnabledOk returns a tuple with the Enabled field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetEnabledOk() (*bool, bool) { + if o == nil || o.Enabled == nil { + return nil, false + } + return o.Enabled, true +} + +// HasEnabled returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasEnabled() bool { + if o != nil && o.Enabled != nil { + return true + } + + return false +} + +// SetEnabled gets a reference to the given bool and assigns it to the Enabled field. +func (o *TriggerWorkflowRep) SetEnabled(v bool) { + o.Enabled = &v +} + +// GetIntegrationKey returns the IntegrationKey field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetIntegrationKey() string { + if o == nil || o.IntegrationKey == nil { + var ret string + return ret + } + return *o.IntegrationKey +} + +// GetIntegrationKeyOk returns a tuple with the IntegrationKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetIntegrationKeyOk() (*string, bool) { + if o == nil || o.IntegrationKey == nil { + return nil, false + } + return o.IntegrationKey, true +} + +// HasIntegrationKey returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasIntegrationKey() bool { + if o != nil && o.IntegrationKey != nil { + return true + } + + return false +} + +// SetIntegrationKey gets a reference to the given string and assigns it to the IntegrationKey field. +func (o *TriggerWorkflowRep) SetIntegrationKey(v string) { + o.IntegrationKey = &v +} + +// GetInstructions returns the Instructions field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetInstructions() []map[string]interface{} { + if o == nil || o.Instructions == nil { + var ret []map[string]interface{} + return ret + } + return o.Instructions +} + +// GetInstructionsOk returns a tuple with the Instructions field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetInstructionsOk() ([]map[string]interface{}, bool) { + if o == nil || o.Instructions == nil { + return nil, false + } + return o.Instructions, true +} + +// HasInstructions returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasInstructions() bool { + if o != nil && o.Instructions != nil { + return true + } + + return false +} + +// SetInstructions gets a reference to the given []map[string]interface{} and assigns it to the Instructions field. +func (o *TriggerWorkflowRep) SetInstructions(v []map[string]interface{}) { + o.Instructions = v +} + +// GetLastTriggeredAt returns the LastTriggeredAt field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetLastTriggeredAt() int64 { + if o == nil || o.LastTriggeredAt == nil { + var ret int64 + return ret + } + return *o.LastTriggeredAt +} + +// GetLastTriggeredAtOk returns a tuple with the LastTriggeredAt field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetLastTriggeredAtOk() (*int64, bool) { + if o == nil || o.LastTriggeredAt == nil { + return nil, false + } + return o.LastTriggeredAt, true +} + +// HasLastTriggeredAt returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasLastTriggeredAt() bool { + if o != nil && o.LastTriggeredAt != nil { + return true + } + + return false +} + +// SetLastTriggeredAt gets a reference to the given int64 and assigns it to the LastTriggeredAt field. +func (o *TriggerWorkflowRep) SetLastTriggeredAt(v int64) { + o.LastTriggeredAt = &v +} + +// GetRecentTriggerBodies returns the RecentTriggerBodies field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetRecentTriggerBodies() []RecentTriggerBody { + if o == nil || o.RecentTriggerBodies == nil { + var ret []RecentTriggerBody + return ret + } + return o.RecentTriggerBodies +} + +// GetRecentTriggerBodiesOk returns a tuple with the RecentTriggerBodies field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetRecentTriggerBodiesOk() ([]RecentTriggerBody, bool) { + if o == nil || o.RecentTriggerBodies == nil { + return nil, false + } + return o.RecentTriggerBodies, true +} + +// HasRecentTriggerBodies returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasRecentTriggerBodies() bool { + if o != nil && o.RecentTriggerBodies != nil { + return true + } + + return false +} + +// SetRecentTriggerBodies gets a reference to the given []RecentTriggerBody and assigns it to the RecentTriggerBodies field. +func (o *TriggerWorkflowRep) SetRecentTriggerBodies(v []RecentTriggerBody) { + o.RecentTriggerBodies = v +} + +// GetTriggerCount returns the TriggerCount field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetTriggerCount() int32 { + if o == nil || o.TriggerCount == nil { + var ret int32 + return ret + } + return *o.TriggerCount +} + +// GetTriggerCountOk returns a tuple with the TriggerCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetTriggerCountOk() (*int32, bool) { + if o == nil || o.TriggerCount == nil { + return nil, false + } + return o.TriggerCount, true +} + +// HasTriggerCount returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasTriggerCount() bool { + if o != nil && o.TriggerCount != nil { + return true + } + + return false +} + +// SetTriggerCount gets a reference to the given int32 and assigns it to the TriggerCount field. +func (o *TriggerWorkflowRep) SetTriggerCount(v int32) { + o.TriggerCount = &v +} + +// GetTriggerURL returns the TriggerURL field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetTriggerURL() string { + if o == nil || o.TriggerURL == nil { + var ret string + return ret + } + return *o.TriggerURL +} + +// GetTriggerURLOk returns a tuple with the TriggerURL field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetTriggerURLOk() (*string, bool) { + if o == nil || o.TriggerURL == nil { + return nil, false + } + return o.TriggerURL, true +} + +// HasTriggerURL returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasTriggerURL() bool { + if o != nil && o.TriggerURL != nil { + return true + } + + return false +} + +// SetTriggerURL gets a reference to the given string and assigns it to the TriggerURL field. +func (o *TriggerWorkflowRep) SetTriggerURL(v string) { + o.TriggerURL = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *TriggerWorkflowRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TriggerWorkflowRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *TriggerWorkflowRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *TriggerWorkflowRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o TriggerWorkflowRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Version != nil { + toSerialize["_version"] = o.Version + } + if o.CreationDate != nil { + toSerialize["_creationDate"] = o.CreationDate + } + if o.MaintainerId != nil { + toSerialize["_maintainerId"] = o.MaintainerId + } + if o.Maintainer != nil { + toSerialize["_maintainer"] = o.Maintainer + } + if o.Enabled != nil { + toSerialize["enabled"] = o.Enabled + } + if o.IntegrationKey != nil { + toSerialize["_integrationKey"] = o.IntegrationKey + } + if o.Instructions != nil { + toSerialize["instructions"] = o.Instructions + } + if o.LastTriggeredAt != nil { + toSerialize["_lastTriggeredAt"] = o.LastTriggeredAt + } + if o.RecentTriggerBodies != nil { + toSerialize["_recentTriggerBodies"] = o.RecentTriggerBodies + } + if o.TriggerCount != nil { + toSerialize["_triggerCount"] = o.TriggerCount + } + if o.TriggerURL != nil { + toSerialize["triggerURL"] = o.TriggerURL + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableTriggerWorkflowRep struct { + value *TriggerWorkflowRep + isSet bool +} + +func (v NullableTriggerWorkflowRep) Get() *TriggerWorkflowRep { + return v.value +} + +func (v *NullableTriggerWorkflowRep) Set(val *TriggerWorkflowRep) { + v.value = val + v.isSet = true +} + +func (v NullableTriggerWorkflowRep) IsSet() bool { + return v.isSet +} + +func (v *NullableTriggerWorkflowRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTriggerWorkflowRep(val *TriggerWorkflowRep) *NullableTriggerWorkflowRep { + return &NullableTriggerWorkflowRep{value: val, isSet: true} +} + +func (v NullableTriggerWorkflowRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTriggerWorkflowRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_unauthorized_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_unauthorized_error_rep.go new file mode 100644 index 00000000..238df441 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_unauthorized_error_rep.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UnauthorizedErrorRep struct for UnauthorizedErrorRep +type UnauthorizedErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` +} + +// NewUnauthorizedErrorRep instantiates a new UnauthorizedErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUnauthorizedErrorRep(code string, message string) *UnauthorizedErrorRep { + this := UnauthorizedErrorRep{} + this.Code = code + this.Message = message + return &this +} + +// NewUnauthorizedErrorRepWithDefaults instantiates a new UnauthorizedErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUnauthorizedErrorRepWithDefaults() *UnauthorizedErrorRep { + this := UnauthorizedErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *UnauthorizedErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *UnauthorizedErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *UnauthorizedErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *UnauthorizedErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *UnauthorizedErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *UnauthorizedErrorRep) SetMessage(v string) { + o.Message = v +} + +func (o UnauthorizedErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + return json.Marshal(toSerialize) +} + +type NullableUnauthorizedErrorRep struct { + value *UnauthorizedErrorRep + isSet bool +} + +func (v NullableUnauthorizedErrorRep) Get() *UnauthorizedErrorRep { + return v.value +} + +func (v *NullableUnauthorizedErrorRep) Set(val *UnauthorizedErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableUnauthorizedErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableUnauthorizedErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUnauthorizedErrorRep(val *UnauthorizedErrorRep) *NullableUnauthorizedErrorRep { + return &NullableUnauthorizedErrorRep{value: val, isSet: true} +} + +func (v NullableUnauthorizedErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUnauthorizedErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_update_phase_status_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_update_phase_status_input.go new file mode 100644 index 00000000..511e8e09 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_update_phase_status_input.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpdatePhaseStatusInput struct for UpdatePhaseStatusInput +type UpdatePhaseStatusInput struct { + Status *string `json:"status,omitempty"` + // Extra configuration for audiences required upon phase initialization. + Audiences []ReleaserAudienceConfigInput `json:"audiences,omitempty"` +} + +// NewUpdatePhaseStatusInput instantiates a new UpdatePhaseStatusInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpdatePhaseStatusInput() *UpdatePhaseStatusInput { + this := UpdatePhaseStatusInput{} + return &this +} + +// NewUpdatePhaseStatusInputWithDefaults instantiates a new UpdatePhaseStatusInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpdatePhaseStatusInputWithDefaults() *UpdatePhaseStatusInput { + this := UpdatePhaseStatusInput{} + return &this +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *UpdatePhaseStatusInput) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdatePhaseStatusInput) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *UpdatePhaseStatusInput) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *UpdatePhaseStatusInput) SetStatus(v string) { + o.Status = &v +} + +// GetAudiences returns the Audiences field value if set, zero value otherwise. +func (o *UpdatePhaseStatusInput) GetAudiences() []ReleaserAudienceConfigInput { + if o == nil || o.Audiences == nil { + var ret []ReleaserAudienceConfigInput + return ret + } + return o.Audiences +} + +// GetAudiencesOk returns a tuple with the Audiences field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdatePhaseStatusInput) GetAudiencesOk() ([]ReleaserAudienceConfigInput, bool) { + if o == nil || o.Audiences == nil { + return nil, false + } + return o.Audiences, true +} + +// HasAudiences returns a boolean if a field has been set. +func (o *UpdatePhaseStatusInput) HasAudiences() bool { + if o != nil && o.Audiences != nil { + return true + } + + return false +} + +// SetAudiences gets a reference to the given []ReleaserAudienceConfigInput and assigns it to the Audiences field. +func (o *UpdatePhaseStatusInput) SetAudiences(v []ReleaserAudienceConfigInput) { + o.Audiences = v +} + +func (o UpdatePhaseStatusInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.Audiences != nil { + toSerialize["audiences"] = o.Audiences + } + return json.Marshal(toSerialize) +} + +type NullableUpdatePhaseStatusInput struct { + value *UpdatePhaseStatusInput + isSet bool +} + +func (v NullableUpdatePhaseStatusInput) Get() *UpdatePhaseStatusInput { + return v.value +} + +func (v *NullableUpdatePhaseStatusInput) Set(val *UpdatePhaseStatusInput) { + v.value = val + v.isSet = true +} + +func (v NullableUpdatePhaseStatusInput) IsSet() bool { + return v.isSet +} + +func (v *NullableUpdatePhaseStatusInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpdatePhaseStatusInput(val *UpdatePhaseStatusInput) *NullableUpdatePhaseStatusInput { + return &NullableUpdatePhaseStatusInput{value: val, isSet: true} +} + +func (v NullableUpdatePhaseStatusInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpdatePhaseStatusInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_update_release_pipeline_input.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_update_release_pipeline_input.go new file mode 100644 index 00000000..78622103 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_update_release_pipeline_input.go @@ -0,0 +1,214 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpdateReleasePipelineInput struct for UpdateReleasePipelineInput +type UpdateReleasePipelineInput struct { + // The release pipeline description + Description *string `json:"description,omitempty"` + // The name of the release pipeline + Name string `json:"name"` + // A logical grouping of one or more environments that share attributes for rolling out changes + Phases []CreatePhaseInput `json:"phases"` + // A list of tags for this release pipeline + Tags []string `json:"tags,omitempty"` +} + +// NewUpdateReleasePipelineInput instantiates a new UpdateReleasePipelineInput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpdateReleasePipelineInput(name string, phases []CreatePhaseInput) *UpdateReleasePipelineInput { + this := UpdateReleasePipelineInput{} + this.Name = name + this.Phases = phases + return &this +} + +// NewUpdateReleasePipelineInputWithDefaults instantiates a new UpdateReleasePipelineInput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpdateReleasePipelineInputWithDefaults() *UpdateReleasePipelineInput { + this := UpdateReleasePipelineInput{} + return &this +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *UpdateReleasePipelineInput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleasePipelineInput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *UpdateReleasePipelineInput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *UpdateReleasePipelineInput) SetDescription(v string) { + o.Description = &v +} + +// GetName returns the Name field value +func (o *UpdateReleasePipelineInput) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *UpdateReleasePipelineInput) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *UpdateReleasePipelineInput) SetName(v string) { + o.Name = v +} + +// GetPhases returns the Phases field value +func (o *UpdateReleasePipelineInput) GetPhases() []CreatePhaseInput { + if o == nil { + var ret []CreatePhaseInput + return ret + } + + return o.Phases +} + +// GetPhasesOk returns a tuple with the Phases field value +// and a boolean to check if the value has been set. +func (o *UpdateReleasePipelineInput) GetPhasesOk() ([]CreatePhaseInput, bool) { + if o == nil { + return nil, false + } + return o.Phases, true +} + +// SetPhases sets field value +func (o *UpdateReleasePipelineInput) SetPhases(v []CreatePhaseInput) { + o.Phases = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *UpdateReleasePipelineInput) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleasePipelineInput) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *UpdateReleasePipelineInput) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *UpdateReleasePipelineInput) SetTags(v []string) { + o.Tags = v +} + +func (o UpdateReleasePipelineInput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["phases"] = o.Phases + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + return json.Marshal(toSerialize) +} + +type NullableUpdateReleasePipelineInput struct { + value *UpdateReleasePipelineInput + isSet bool +} + +func (v NullableUpdateReleasePipelineInput) Get() *UpdateReleasePipelineInput { + return v.value +} + +func (v *NullableUpdateReleasePipelineInput) Set(val *UpdateReleasePipelineInput) { + v.value = val + v.isSet = true +} + +func (v NullableUpdateReleasePipelineInput) IsSet() bool { + return v.isSet +} + +func (v *NullableUpdateReleasePipelineInput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpdateReleasePipelineInput(val *UpdateReleasePipelineInput) *NullableUpdateReleasePipelineInput { + return &NullableUpdateReleasePipelineInput{value: val, isSet: true} +} + +func (v NullableUpdateReleasePipelineInput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpdateReleasePipelineInput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_context_kind_payload.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_context_kind_payload.go new file mode 100644 index 00000000..9a406cee --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_context_kind_payload.go @@ -0,0 +1,258 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpsertContextKindPayload struct for UpsertContextKindPayload +type UpsertContextKindPayload struct { + // The context kind name + Name string `json:"name"` + // The context kind description + Description *string `json:"description,omitempty"` + // Alias for archived. + HideInTargeting *bool `json:"hideInTargeting,omitempty"` + // Whether the context kind is archived. Archived context kinds are unavailable for targeting. + Archived *bool `json:"archived,omitempty"` + // The context kind version. If not specified when the context kind is created, defaults to 1. + Version *int32 `json:"version,omitempty"` +} + +// NewUpsertContextKindPayload instantiates a new UpsertContextKindPayload object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpsertContextKindPayload(name string) *UpsertContextKindPayload { + this := UpsertContextKindPayload{} + this.Name = name + return &this +} + +// NewUpsertContextKindPayloadWithDefaults instantiates a new UpsertContextKindPayload object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpsertContextKindPayloadWithDefaults() *UpsertContextKindPayload { + this := UpsertContextKindPayload{} + return &this +} + +// GetName returns the Name field value +func (o *UpsertContextKindPayload) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *UpsertContextKindPayload) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *UpsertContextKindPayload) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *UpsertContextKindPayload) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertContextKindPayload) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *UpsertContextKindPayload) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *UpsertContextKindPayload) SetDescription(v string) { + o.Description = &v +} + +// GetHideInTargeting returns the HideInTargeting field value if set, zero value otherwise. +func (o *UpsertContextKindPayload) GetHideInTargeting() bool { + if o == nil || o.HideInTargeting == nil { + var ret bool + return ret + } + return *o.HideInTargeting +} + +// GetHideInTargetingOk returns a tuple with the HideInTargeting field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertContextKindPayload) GetHideInTargetingOk() (*bool, bool) { + if o == nil || o.HideInTargeting == nil { + return nil, false + } + return o.HideInTargeting, true +} + +// HasHideInTargeting returns a boolean if a field has been set. +func (o *UpsertContextKindPayload) HasHideInTargeting() bool { + if o != nil && o.HideInTargeting != nil { + return true + } + + return false +} + +// SetHideInTargeting gets a reference to the given bool and assigns it to the HideInTargeting field. +func (o *UpsertContextKindPayload) SetHideInTargeting(v bool) { + o.HideInTargeting = &v +} + +// GetArchived returns the Archived field value if set, zero value otherwise. +func (o *UpsertContextKindPayload) GetArchived() bool { + if o == nil || o.Archived == nil { + var ret bool + return ret + } + return *o.Archived +} + +// GetArchivedOk returns a tuple with the Archived field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertContextKindPayload) GetArchivedOk() (*bool, bool) { + if o == nil || o.Archived == nil { + return nil, false + } + return o.Archived, true +} + +// HasArchived returns a boolean if a field has been set. +func (o *UpsertContextKindPayload) HasArchived() bool { + if o != nil && o.Archived != nil { + return true + } + + return false +} + +// SetArchived gets a reference to the given bool and assigns it to the Archived field. +func (o *UpsertContextKindPayload) SetArchived(v bool) { + o.Archived = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *UpsertContextKindPayload) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertContextKindPayload) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *UpsertContextKindPayload) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *UpsertContextKindPayload) SetVersion(v int32) { + o.Version = &v +} + +func (o UpsertContextKindPayload) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.HideInTargeting != nil { + toSerialize["hideInTargeting"] = o.HideInTargeting + } + if o.Archived != nil { + toSerialize["archived"] = o.Archived + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableUpsertContextKindPayload struct { + value *UpsertContextKindPayload + isSet bool +} + +func (v NullableUpsertContextKindPayload) Get() *UpsertContextKindPayload { + return v.value +} + +func (v *NullableUpsertContextKindPayload) Set(val *UpsertContextKindPayload) { + v.value = val + v.isSet = true +} + +func (v NullableUpsertContextKindPayload) IsSet() bool { + return v.isSet +} + +func (v *NullableUpsertContextKindPayload) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpsertContextKindPayload(val *UpsertContextKindPayload) *NullableUpsertContextKindPayload { + return &NullableUpsertContextKindPayload{value: val, isSet: true} +} + +func (v NullableUpsertContextKindPayload) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpsertContextKindPayload) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_flag_defaults_payload.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_flag_defaults_payload.go new file mode 100644 index 00000000..27ef7100 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_flag_defaults_payload.go @@ -0,0 +1,198 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpsertFlagDefaultsPayload struct for UpsertFlagDefaultsPayload +type UpsertFlagDefaultsPayload struct { + // A list of default tags for each flag + Tags []string `json:"tags"` + // Whether the flag should be temporary by default + Temporary bool `json:"temporary"` + BooleanDefaults BooleanFlagDefaults `json:"booleanDefaults"` + DefaultClientSideAvailability DefaultClientSideAvailability `json:"defaultClientSideAvailability"` +} + +// NewUpsertFlagDefaultsPayload instantiates a new UpsertFlagDefaultsPayload object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpsertFlagDefaultsPayload(tags []string, temporary bool, booleanDefaults BooleanFlagDefaults, defaultClientSideAvailability DefaultClientSideAvailability) *UpsertFlagDefaultsPayload { + this := UpsertFlagDefaultsPayload{} + this.Tags = tags + this.Temporary = temporary + this.BooleanDefaults = booleanDefaults + this.DefaultClientSideAvailability = defaultClientSideAvailability + return &this +} + +// NewUpsertFlagDefaultsPayloadWithDefaults instantiates a new UpsertFlagDefaultsPayload object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpsertFlagDefaultsPayloadWithDefaults() *UpsertFlagDefaultsPayload { + this := UpsertFlagDefaultsPayload{} + return &this +} + +// GetTags returns the Tags field value +func (o *UpsertFlagDefaultsPayload) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *UpsertFlagDefaultsPayload) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *UpsertFlagDefaultsPayload) SetTags(v []string) { + o.Tags = v +} + +// GetTemporary returns the Temporary field value +func (o *UpsertFlagDefaultsPayload) GetTemporary() bool { + if o == nil { + var ret bool + return ret + } + + return o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value +// and a boolean to check if the value has been set. +func (o *UpsertFlagDefaultsPayload) GetTemporaryOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Temporary, true +} + +// SetTemporary sets field value +func (o *UpsertFlagDefaultsPayload) SetTemporary(v bool) { + o.Temporary = v +} + +// GetBooleanDefaults returns the BooleanDefaults field value +func (o *UpsertFlagDefaultsPayload) GetBooleanDefaults() BooleanFlagDefaults { + if o == nil { + var ret BooleanFlagDefaults + return ret + } + + return o.BooleanDefaults +} + +// GetBooleanDefaultsOk returns a tuple with the BooleanDefaults field value +// and a boolean to check if the value has been set. +func (o *UpsertFlagDefaultsPayload) GetBooleanDefaultsOk() (*BooleanFlagDefaults, bool) { + if o == nil { + return nil, false + } + return &o.BooleanDefaults, true +} + +// SetBooleanDefaults sets field value +func (o *UpsertFlagDefaultsPayload) SetBooleanDefaults(v BooleanFlagDefaults) { + o.BooleanDefaults = v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value +func (o *UpsertFlagDefaultsPayload) GetDefaultClientSideAvailability() DefaultClientSideAvailability { + if o == nil { + var ret DefaultClientSideAvailability + return ret + } + + return o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value +// and a boolean to check if the value has been set. +func (o *UpsertFlagDefaultsPayload) GetDefaultClientSideAvailabilityOk() (*DefaultClientSideAvailability, bool) { + if o == nil { + return nil, false + } + return &o.DefaultClientSideAvailability, true +} + +// SetDefaultClientSideAvailability sets field value +func (o *UpsertFlagDefaultsPayload) SetDefaultClientSideAvailability(v DefaultClientSideAvailability) { + o.DefaultClientSideAvailability = v +} + +func (o UpsertFlagDefaultsPayload) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["temporary"] = o.Temporary + } + if true { + toSerialize["booleanDefaults"] = o.BooleanDefaults + } + if true { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + return json.Marshal(toSerialize) +} + +type NullableUpsertFlagDefaultsPayload struct { + value *UpsertFlagDefaultsPayload + isSet bool +} + +func (v NullableUpsertFlagDefaultsPayload) Get() *UpsertFlagDefaultsPayload { + return v.value +} + +func (v *NullableUpsertFlagDefaultsPayload) Set(val *UpsertFlagDefaultsPayload) { + v.value = val + v.isSet = true +} + +func (v NullableUpsertFlagDefaultsPayload) IsSet() bool { + return v.isSet +} + +func (v *NullableUpsertFlagDefaultsPayload) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpsertFlagDefaultsPayload(val *UpsertFlagDefaultsPayload) *NullableUpsertFlagDefaultsPayload { + return &NullableUpsertFlagDefaultsPayload{value: val, isSet: true} +} + +func (v NullableUpsertFlagDefaultsPayload) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpsertFlagDefaultsPayload) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_payload_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_payload_rep.go new file mode 100644 index 00000000..c38b1242 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_payload_rep.go @@ -0,0 +1,235 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpsertPayloadRep struct for UpsertPayloadRep +type UpsertPayloadRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // A list of default tags for each flag + Tags []string `json:"tags"` + // Whether the flag should be temporary by default + Temporary bool `json:"temporary"` + BooleanDefaults BooleanFlagDefaults `json:"booleanDefaults"` + DefaultClientSideAvailability DefaultClientSideAvailability `json:"defaultClientSideAvailability"` +} + +// NewUpsertPayloadRep instantiates a new UpsertPayloadRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpsertPayloadRep(tags []string, temporary bool, booleanDefaults BooleanFlagDefaults, defaultClientSideAvailability DefaultClientSideAvailability) *UpsertPayloadRep { + this := UpsertPayloadRep{} + this.Tags = tags + this.Temporary = temporary + this.BooleanDefaults = booleanDefaults + this.DefaultClientSideAvailability = defaultClientSideAvailability + return &this +} + +// NewUpsertPayloadRepWithDefaults instantiates a new UpsertPayloadRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpsertPayloadRepWithDefaults() *UpsertPayloadRep { + this := UpsertPayloadRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *UpsertPayloadRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertPayloadRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *UpsertPayloadRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *UpsertPayloadRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTags returns the Tags field value +func (o *UpsertPayloadRep) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *UpsertPayloadRep) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *UpsertPayloadRep) SetTags(v []string) { + o.Tags = v +} + +// GetTemporary returns the Temporary field value +func (o *UpsertPayloadRep) GetTemporary() bool { + if o == nil { + var ret bool + return ret + } + + return o.Temporary +} + +// GetTemporaryOk returns a tuple with the Temporary field value +// and a boolean to check if the value has been set. +func (o *UpsertPayloadRep) GetTemporaryOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Temporary, true +} + +// SetTemporary sets field value +func (o *UpsertPayloadRep) SetTemporary(v bool) { + o.Temporary = v +} + +// GetBooleanDefaults returns the BooleanDefaults field value +func (o *UpsertPayloadRep) GetBooleanDefaults() BooleanFlagDefaults { + if o == nil { + var ret BooleanFlagDefaults + return ret + } + + return o.BooleanDefaults +} + +// GetBooleanDefaultsOk returns a tuple with the BooleanDefaults field value +// and a boolean to check if the value has been set. +func (o *UpsertPayloadRep) GetBooleanDefaultsOk() (*BooleanFlagDefaults, bool) { + if o == nil { + return nil, false + } + return &o.BooleanDefaults, true +} + +// SetBooleanDefaults sets field value +func (o *UpsertPayloadRep) SetBooleanDefaults(v BooleanFlagDefaults) { + o.BooleanDefaults = v +} + +// GetDefaultClientSideAvailability returns the DefaultClientSideAvailability field value +func (o *UpsertPayloadRep) GetDefaultClientSideAvailability() DefaultClientSideAvailability { + if o == nil { + var ret DefaultClientSideAvailability + return ret + } + + return o.DefaultClientSideAvailability +} + +// GetDefaultClientSideAvailabilityOk returns a tuple with the DefaultClientSideAvailability field value +// and a boolean to check if the value has been set. +func (o *UpsertPayloadRep) GetDefaultClientSideAvailabilityOk() (*DefaultClientSideAvailability, bool) { + if o == nil { + return nil, false + } + return &o.DefaultClientSideAvailability, true +} + +// SetDefaultClientSideAvailability sets field value +func (o *UpsertPayloadRep) SetDefaultClientSideAvailability(v DefaultClientSideAvailability) { + o.DefaultClientSideAvailability = v +} + +func (o UpsertPayloadRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["temporary"] = o.Temporary + } + if true { + toSerialize["booleanDefaults"] = o.BooleanDefaults + } + if true { + toSerialize["defaultClientSideAvailability"] = o.DefaultClientSideAvailability + } + return json.Marshal(toSerialize) +} + +type NullableUpsertPayloadRep struct { + value *UpsertPayloadRep + isSet bool +} + +func (v NullableUpsertPayloadRep) Get() *UpsertPayloadRep { + return v.value +} + +func (v *NullableUpsertPayloadRep) Set(val *UpsertPayloadRep) { + v.value = val + v.isSet = true +} + +func (v NullableUpsertPayloadRep) IsSet() bool { + return v.isSet +} + +func (v *NullableUpsertPayloadRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpsertPayloadRep(val *UpsertPayloadRep) *NullableUpsertPayloadRep { + return &NullableUpsertPayloadRep{value: val, isSet: true} +} + +func (v NullableUpsertPayloadRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpsertPayloadRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_response_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_response_rep.go new file mode 100644 index 00000000..6549820c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_upsert_response_rep.go @@ -0,0 +1,154 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UpsertResponseRep struct for UpsertResponseRep +type UpsertResponseRep struct { + // The status of the create or update operation + Status *string `json:"status,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` +} + +// NewUpsertResponseRep instantiates a new UpsertResponseRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpsertResponseRep() *UpsertResponseRep { + this := UpsertResponseRep{} + return &this +} + +// NewUpsertResponseRepWithDefaults instantiates a new UpsertResponseRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpsertResponseRepWithDefaults() *UpsertResponseRep { + this := UpsertResponseRep{} + return &this +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *UpsertResponseRep) GetStatus() string { + if o == nil || o.Status == nil { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertResponseRep) GetStatusOk() (*string, bool) { + if o == nil || o.Status == nil { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *UpsertResponseRep) HasStatus() bool { + if o != nil && o.Status != nil { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *UpsertResponseRep) SetStatus(v string) { + o.Status = &v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *UpsertResponseRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpsertResponseRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *UpsertResponseRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *UpsertResponseRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +func (o UpsertResponseRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Status != nil { + toSerialize["status"] = o.Status + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableUpsertResponseRep struct { + value *UpsertResponseRep + isSet bool +} + +func (v NullableUpsertResponseRep) Get() *UpsertResponseRep { + return v.value +} + +func (v *NullableUpsertResponseRep) Set(val *UpsertResponseRep) { + v.value = val + v.isSet = true +} + +func (v NullableUpsertResponseRep) IsSet() bool { + return v.isSet +} + +func (v *NullableUpsertResponseRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpsertResponseRep(val *UpsertResponseRep) *NullableUpsertResponseRep { + return &NullableUpsertResponseRep{value: val, isSet: true} +} + +func (v NullableUpsertResponseRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpsertResponseRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_url_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_url_post.go new file mode 100644 index 00000000..312ce381 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_url_post.go @@ -0,0 +1,224 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UrlPost struct for UrlPost +type UrlPost struct { + Kind *string `json:"kind,omitempty"` + Url *string `json:"url,omitempty"` + Substring *string `json:"substring,omitempty"` + Pattern *string `json:"pattern,omitempty"` +} + +// NewUrlPost instantiates a new UrlPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUrlPost() *UrlPost { + this := UrlPost{} + return &this +} + +// NewUrlPostWithDefaults instantiates a new UrlPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUrlPostWithDefaults() *UrlPost { + this := UrlPost{} + return &this +} + +// GetKind returns the Kind field value if set, zero value otherwise. +func (o *UrlPost) GetKind() string { + if o == nil || o.Kind == nil { + var ret string + return ret + } + return *o.Kind +} + +// GetKindOk returns a tuple with the Kind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UrlPost) GetKindOk() (*string, bool) { + if o == nil || o.Kind == nil { + return nil, false + } + return o.Kind, true +} + +// HasKind returns a boolean if a field has been set. +func (o *UrlPost) HasKind() bool { + if o != nil && o.Kind != nil { + return true + } + + return false +} + +// SetKind gets a reference to the given string and assigns it to the Kind field. +func (o *UrlPost) SetKind(v string) { + o.Kind = &v +} + +// GetUrl returns the Url field value if set, zero value otherwise. +func (o *UrlPost) GetUrl() string { + if o == nil || o.Url == nil { + var ret string + return ret + } + return *o.Url +} + +// GetUrlOk returns a tuple with the Url field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UrlPost) GetUrlOk() (*string, bool) { + if o == nil || o.Url == nil { + return nil, false + } + return o.Url, true +} + +// HasUrl returns a boolean if a field has been set. +func (o *UrlPost) HasUrl() bool { + if o != nil && o.Url != nil { + return true + } + + return false +} + +// SetUrl gets a reference to the given string and assigns it to the Url field. +func (o *UrlPost) SetUrl(v string) { + o.Url = &v +} + +// GetSubstring returns the Substring field value if set, zero value otherwise. +func (o *UrlPost) GetSubstring() string { + if o == nil || o.Substring == nil { + var ret string + return ret + } + return *o.Substring +} + +// GetSubstringOk returns a tuple with the Substring field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UrlPost) GetSubstringOk() (*string, bool) { + if o == nil || o.Substring == nil { + return nil, false + } + return o.Substring, true +} + +// HasSubstring returns a boolean if a field has been set. +func (o *UrlPost) HasSubstring() bool { + if o != nil && o.Substring != nil { + return true + } + + return false +} + +// SetSubstring gets a reference to the given string and assigns it to the Substring field. +func (o *UrlPost) SetSubstring(v string) { + o.Substring = &v +} + +// GetPattern returns the Pattern field value if set, zero value otherwise. +func (o *UrlPost) GetPattern() string { + if o == nil || o.Pattern == nil { + var ret string + return ret + } + return *o.Pattern +} + +// GetPatternOk returns a tuple with the Pattern field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UrlPost) GetPatternOk() (*string, bool) { + if o == nil || o.Pattern == nil { + return nil, false + } + return o.Pattern, true +} + +// HasPattern returns a boolean if a field has been set. +func (o *UrlPost) HasPattern() bool { + if o != nil && o.Pattern != nil { + return true + } + + return false +} + +// SetPattern gets a reference to the given string and assigns it to the Pattern field. +func (o *UrlPost) SetPattern(v string) { + o.Pattern = &v +} + +func (o UrlPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Kind != nil { + toSerialize["kind"] = o.Kind + } + if o.Url != nil { + toSerialize["url"] = o.Url + } + if o.Substring != nil { + toSerialize["substring"] = o.Substring + } + if o.Pattern != nil { + toSerialize["pattern"] = o.Pattern + } + return json.Marshal(toSerialize) +} + +type NullableUrlPost struct { + value *UrlPost + isSet bool +} + +func (v NullableUrlPost) Get() *UrlPost { + return v.value +} + +func (v *NullableUrlPost) Set(val *UrlPost) { + v.value = val + v.isSet = true +} + +func (v NullableUrlPost) IsSet() bool { + return v.isSet +} + +func (v *NullableUrlPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUrlPost(val *UrlPost) *NullableUrlPost { + return &NullableUrlPost{value: val, isSet: true} +} + +func (v NullableUrlPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUrlPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user.go new file mode 100644 index 00000000..2e160c72 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user.go @@ -0,0 +1,524 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// User struct for User +type User struct { + // The user key. This is the only mandatory user attribute. + Key *string `json:"key,omitempty"` + // If provided, used with the user key to generate a variation in percentage rollouts + Secondary *string `json:"secondary,omitempty"` + // The user's IP address + Ip *string `json:"ip,omitempty"` + // The user's country + Country *string `json:"country,omitempty"` + // The user's email + Email *string `json:"email,omitempty"` + // The user's first name + FirstName *string `json:"firstName,omitempty"` + // The user's last name + LastName *string `json:"lastName,omitempty"` + // An absolute URL to an avatar image. + Avatar *string `json:"avatar,omitempty"` + // The user's full name + Name *string `json:"name,omitempty"` + // Whether the user is anonymous. If true, this user does not appear on the Contexts list in the LaunchDarkly user interface. + Anonymous *bool `json:"anonymous,omitempty"` + // Any other custom attributes for this user. Custom attributes contain any other user data that you would like to use to conditionally target your users. + Custom map[string]interface{} `json:"custom,omitempty"` + // A list of attribute names that are marked as private. You can use these attributes in targeting rules and segments. If you are using a server-side SDK, the SDK will not send the private attribute back to LaunchDarkly. If you are using a client-side SDK, the SDK will send the private attribute back to LaunchDarkly for evaluation. However, the SDK won't send the attribute to LaunchDarkly in events data, LaunchDarkly won't store the private attribute, and the private attribute will not appear on the Contexts list. + PrivateAttrs []string `json:"privateAttrs,omitempty"` +} + +// NewUser instantiates a new User object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUser() *User { + this := User{} + return &this +} + +// NewUserWithDefaults instantiates a new User object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserWithDefaults() *User { + this := User{} + return &this +} + +// GetKey returns the Key field value if set, zero value otherwise. +func (o *User) GetKey() string { + if o == nil || o.Key == nil { + var ret string + return ret + } + return *o.Key +} + +// GetKeyOk returns a tuple with the Key field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetKeyOk() (*string, bool) { + if o == nil || o.Key == nil { + return nil, false + } + return o.Key, true +} + +// HasKey returns a boolean if a field has been set. +func (o *User) HasKey() bool { + if o != nil && o.Key != nil { + return true + } + + return false +} + +// SetKey gets a reference to the given string and assigns it to the Key field. +func (o *User) SetKey(v string) { + o.Key = &v +} + +// GetSecondary returns the Secondary field value if set, zero value otherwise. +func (o *User) GetSecondary() string { + if o == nil || o.Secondary == nil { + var ret string + return ret + } + return *o.Secondary +} + +// GetSecondaryOk returns a tuple with the Secondary field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetSecondaryOk() (*string, bool) { + if o == nil || o.Secondary == nil { + return nil, false + } + return o.Secondary, true +} + +// HasSecondary returns a boolean if a field has been set. +func (o *User) HasSecondary() bool { + if o != nil && o.Secondary != nil { + return true + } + + return false +} + +// SetSecondary gets a reference to the given string and assigns it to the Secondary field. +func (o *User) SetSecondary(v string) { + o.Secondary = &v +} + +// GetIp returns the Ip field value if set, zero value otherwise. +func (o *User) GetIp() string { + if o == nil || o.Ip == nil { + var ret string + return ret + } + return *o.Ip +} + +// GetIpOk returns a tuple with the Ip field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetIpOk() (*string, bool) { + if o == nil || o.Ip == nil { + return nil, false + } + return o.Ip, true +} + +// HasIp returns a boolean if a field has been set. +func (o *User) HasIp() bool { + if o != nil && o.Ip != nil { + return true + } + + return false +} + +// SetIp gets a reference to the given string and assigns it to the Ip field. +func (o *User) SetIp(v string) { + o.Ip = &v +} + +// GetCountry returns the Country field value if set, zero value otherwise. +func (o *User) GetCountry() string { + if o == nil || o.Country == nil { + var ret string + return ret + } + return *o.Country +} + +// GetCountryOk returns a tuple with the Country field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetCountryOk() (*string, bool) { + if o == nil || o.Country == nil { + return nil, false + } + return o.Country, true +} + +// HasCountry returns a boolean if a field has been set. +func (o *User) HasCountry() bool { + if o != nil && o.Country != nil { + return true + } + + return false +} + +// SetCountry gets a reference to the given string and assigns it to the Country field. +func (o *User) SetCountry(v string) { + o.Country = &v +} + +// GetEmail returns the Email field value if set, zero value otherwise. +func (o *User) GetEmail() string { + if o == nil || o.Email == nil { + var ret string + return ret + } + return *o.Email +} + +// GetEmailOk returns a tuple with the Email field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetEmailOk() (*string, bool) { + if o == nil || o.Email == nil { + return nil, false + } + return o.Email, true +} + +// HasEmail returns a boolean if a field has been set. +func (o *User) HasEmail() bool { + if o != nil && o.Email != nil { + return true + } + + return false +} + +// SetEmail gets a reference to the given string and assigns it to the Email field. +func (o *User) SetEmail(v string) { + o.Email = &v +} + +// GetFirstName returns the FirstName field value if set, zero value otherwise. +func (o *User) GetFirstName() string { + if o == nil || o.FirstName == nil { + var ret string + return ret + } + return *o.FirstName +} + +// GetFirstNameOk returns a tuple with the FirstName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetFirstNameOk() (*string, bool) { + if o == nil || o.FirstName == nil { + return nil, false + } + return o.FirstName, true +} + +// HasFirstName returns a boolean if a field has been set. +func (o *User) HasFirstName() bool { + if o != nil && o.FirstName != nil { + return true + } + + return false +} + +// SetFirstName gets a reference to the given string and assigns it to the FirstName field. +func (o *User) SetFirstName(v string) { + o.FirstName = &v +} + +// GetLastName returns the LastName field value if set, zero value otherwise. +func (o *User) GetLastName() string { + if o == nil || o.LastName == nil { + var ret string + return ret + } + return *o.LastName +} + +// GetLastNameOk returns a tuple with the LastName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetLastNameOk() (*string, bool) { + if o == nil || o.LastName == nil { + return nil, false + } + return o.LastName, true +} + +// HasLastName returns a boolean if a field has been set. +func (o *User) HasLastName() bool { + if o != nil && o.LastName != nil { + return true + } + + return false +} + +// SetLastName gets a reference to the given string and assigns it to the LastName field. +func (o *User) SetLastName(v string) { + o.LastName = &v +} + +// GetAvatar returns the Avatar field value if set, zero value otherwise. +func (o *User) GetAvatar() string { + if o == nil || o.Avatar == nil { + var ret string + return ret + } + return *o.Avatar +} + +// GetAvatarOk returns a tuple with the Avatar field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetAvatarOk() (*string, bool) { + if o == nil || o.Avatar == nil { + return nil, false + } + return o.Avatar, true +} + +// HasAvatar returns a boolean if a field has been set. +func (o *User) HasAvatar() bool { + if o != nil && o.Avatar != nil { + return true + } + + return false +} + +// SetAvatar gets a reference to the given string and assigns it to the Avatar field. +func (o *User) SetAvatar(v string) { + o.Avatar = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *User) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *User) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *User) SetName(v string) { + o.Name = &v +} + +// GetAnonymous returns the Anonymous field value if set, zero value otherwise. +func (o *User) GetAnonymous() bool { + if o == nil || o.Anonymous == nil { + var ret bool + return ret + } + return *o.Anonymous +} + +// GetAnonymousOk returns a tuple with the Anonymous field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetAnonymousOk() (*bool, bool) { + if o == nil || o.Anonymous == nil { + return nil, false + } + return o.Anonymous, true +} + +// HasAnonymous returns a boolean if a field has been set. +func (o *User) HasAnonymous() bool { + if o != nil && o.Anonymous != nil { + return true + } + + return false +} + +// SetAnonymous gets a reference to the given bool and assigns it to the Anonymous field. +func (o *User) SetAnonymous(v bool) { + o.Anonymous = &v +} + +// GetCustom returns the Custom field value if set, zero value otherwise. +func (o *User) GetCustom() map[string]interface{} { + if o == nil || o.Custom == nil { + var ret map[string]interface{} + return ret + } + return o.Custom +} + +// GetCustomOk returns a tuple with the Custom field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetCustomOk() (map[string]interface{}, bool) { + if o == nil || o.Custom == nil { + return nil, false + } + return o.Custom, true +} + +// HasCustom returns a boolean if a field has been set. +func (o *User) HasCustom() bool { + if o != nil && o.Custom != nil { + return true + } + + return false +} + +// SetCustom gets a reference to the given map[string]interface{} and assigns it to the Custom field. +func (o *User) SetCustom(v map[string]interface{}) { + o.Custom = v +} + +// GetPrivateAttrs returns the PrivateAttrs field value if set, zero value otherwise. +func (o *User) GetPrivateAttrs() []string { + if o == nil || o.PrivateAttrs == nil { + var ret []string + return ret + } + return o.PrivateAttrs +} + +// GetPrivateAttrsOk returns a tuple with the PrivateAttrs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetPrivateAttrsOk() ([]string, bool) { + if o == nil || o.PrivateAttrs == nil { + return nil, false + } + return o.PrivateAttrs, true +} + +// HasPrivateAttrs returns a boolean if a field has been set. +func (o *User) HasPrivateAttrs() bool { + if o != nil && o.PrivateAttrs != nil { + return true + } + + return false +} + +// SetPrivateAttrs gets a reference to the given []string and assigns it to the PrivateAttrs field. +func (o *User) SetPrivateAttrs(v []string) { + o.PrivateAttrs = v +} + +func (o User) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Key != nil { + toSerialize["key"] = o.Key + } + if o.Secondary != nil { + toSerialize["secondary"] = o.Secondary + } + if o.Ip != nil { + toSerialize["ip"] = o.Ip + } + if o.Country != nil { + toSerialize["country"] = o.Country + } + if o.Email != nil { + toSerialize["email"] = o.Email + } + if o.FirstName != nil { + toSerialize["firstName"] = o.FirstName + } + if o.LastName != nil { + toSerialize["lastName"] = o.LastName + } + if o.Avatar != nil { + toSerialize["avatar"] = o.Avatar + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Anonymous != nil { + toSerialize["anonymous"] = o.Anonymous + } + if o.Custom != nil { + toSerialize["custom"] = o.Custom + } + if o.PrivateAttrs != nil { + toSerialize["privateAttrs"] = o.PrivateAttrs + } + return json.Marshal(toSerialize) +} + +type NullableUser struct { + value *User + isSet bool +} + +func (v NullableUser) Get() *User { + return v.value +} + +func (v *NullableUser) Set(val *User) { + v.value = val + v.isSet = true +} + +func (v NullableUser) IsSet() bool { + return v.isSet +} + +func (v *NullableUser) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUser(val *User) *NullableUser { + return &NullableUser{value: val, isSet: true} +} + +func (v NullableUser) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUser) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_attribute_names_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_attribute_names_rep.go new file mode 100644 index 00000000..aa38a4cb --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_attribute_names_rep.go @@ -0,0 +1,191 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserAttributeNamesRep struct for UserAttributeNamesRep +type UserAttributeNamesRep struct { + // private attributes + Private []string `json:"private,omitempty"` + // custom attributes + Custom []string `json:"custom,omitempty"` + // standard attributes + Standard []string `json:"standard,omitempty"` +} + +// NewUserAttributeNamesRep instantiates a new UserAttributeNamesRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserAttributeNamesRep() *UserAttributeNamesRep { + this := UserAttributeNamesRep{} + return &this +} + +// NewUserAttributeNamesRepWithDefaults instantiates a new UserAttributeNamesRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserAttributeNamesRepWithDefaults() *UserAttributeNamesRep { + this := UserAttributeNamesRep{} + return &this +} + +// GetPrivate returns the Private field value if set, zero value otherwise. +func (o *UserAttributeNamesRep) GetPrivate() []string { + if o == nil || o.Private == nil { + var ret []string + return ret + } + return o.Private +} + +// GetPrivateOk returns a tuple with the Private field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserAttributeNamesRep) GetPrivateOk() ([]string, bool) { + if o == nil || o.Private == nil { + return nil, false + } + return o.Private, true +} + +// HasPrivate returns a boolean if a field has been set. +func (o *UserAttributeNamesRep) HasPrivate() bool { + if o != nil && o.Private != nil { + return true + } + + return false +} + +// SetPrivate gets a reference to the given []string and assigns it to the Private field. +func (o *UserAttributeNamesRep) SetPrivate(v []string) { + o.Private = v +} + +// GetCustom returns the Custom field value if set, zero value otherwise. +func (o *UserAttributeNamesRep) GetCustom() []string { + if o == nil || o.Custom == nil { + var ret []string + return ret + } + return o.Custom +} + +// GetCustomOk returns a tuple with the Custom field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserAttributeNamesRep) GetCustomOk() ([]string, bool) { + if o == nil || o.Custom == nil { + return nil, false + } + return o.Custom, true +} + +// HasCustom returns a boolean if a field has been set. +func (o *UserAttributeNamesRep) HasCustom() bool { + if o != nil && o.Custom != nil { + return true + } + + return false +} + +// SetCustom gets a reference to the given []string and assigns it to the Custom field. +func (o *UserAttributeNamesRep) SetCustom(v []string) { + o.Custom = v +} + +// GetStandard returns the Standard field value if set, zero value otherwise. +func (o *UserAttributeNamesRep) GetStandard() []string { + if o == nil || o.Standard == nil { + var ret []string + return ret + } + return o.Standard +} + +// GetStandardOk returns a tuple with the Standard field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserAttributeNamesRep) GetStandardOk() ([]string, bool) { + if o == nil || o.Standard == nil { + return nil, false + } + return o.Standard, true +} + +// HasStandard returns a boolean if a field has been set. +func (o *UserAttributeNamesRep) HasStandard() bool { + if o != nil && o.Standard != nil { + return true + } + + return false +} + +// SetStandard gets a reference to the given []string and assigns it to the Standard field. +func (o *UserAttributeNamesRep) SetStandard(v []string) { + o.Standard = v +} + +func (o UserAttributeNamesRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Private != nil { + toSerialize["private"] = o.Private + } + if o.Custom != nil { + toSerialize["custom"] = o.Custom + } + if o.Standard != nil { + toSerialize["standard"] = o.Standard + } + return json.Marshal(toSerialize) +} + +type NullableUserAttributeNamesRep struct { + value *UserAttributeNamesRep + isSet bool +} + +func (v NullableUserAttributeNamesRep) Get() *UserAttributeNamesRep { + return v.value +} + +func (v *NullableUserAttributeNamesRep) Set(val *UserAttributeNamesRep) { + v.value = val + v.isSet = true +} + +func (v NullableUserAttributeNamesRep) IsSet() bool { + return v.isSet +} + +func (v *NullableUserAttributeNamesRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserAttributeNamesRep(val *UserAttributeNamesRep) *NullableUserAttributeNamesRep { + return &NullableUserAttributeNamesRep{value: val, isSet: true} +} + +func (v NullableUserAttributeNamesRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserAttributeNamesRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_setting.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_setting.go new file mode 100644 index 00000000..53325b64 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_setting.go @@ -0,0 +1,210 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserFlagSetting struct for UserFlagSetting +type UserFlagSetting struct { + // The location and content type of related resources. + Links map[string]Link `json:"_links"` + // The value of the flag variation that the user receives. If there is no defined default rule, this is null. + Value interface{} `json:"_value"` + // Whether the user is explicitly targeted to receive a particular variation. The setting is false if you have turned off a feature flag for a user. It is null if you haven't assigned that user to a specific variation. + Setting interface{} `json:"setting"` + Reason *EvaluationReason `json:"reason,omitempty"` +} + +// NewUserFlagSetting instantiates a new UserFlagSetting object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserFlagSetting(links map[string]Link, value interface{}, setting interface{}) *UserFlagSetting { + this := UserFlagSetting{} + this.Links = links + this.Value = value + this.Setting = setting + return &this +} + +// NewUserFlagSettingWithDefaults instantiates a new UserFlagSetting object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserFlagSettingWithDefaults() *UserFlagSetting { + this := UserFlagSetting{} + return &this +} + +// GetLinks returns the Links field value +func (o *UserFlagSetting) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *UserFlagSetting) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *UserFlagSetting) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetValue returns the Value field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *UserFlagSetting) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *UserFlagSetting) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *UserFlagSetting) SetValue(v interface{}) { + o.Value = v +} + +// GetSetting returns the Setting field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *UserFlagSetting) GetSetting() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Setting +} + +// GetSettingOk returns a tuple with the Setting field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *UserFlagSetting) GetSettingOk() (*interface{}, bool) { + if o == nil || o.Setting == nil { + return nil, false + } + return &o.Setting, true +} + +// SetSetting sets field value +func (o *UserFlagSetting) SetSetting(v interface{}) { + o.Setting = v +} + +// GetReason returns the Reason field value if set, zero value otherwise. +func (o *UserFlagSetting) GetReason() EvaluationReason { + if o == nil || o.Reason == nil { + var ret EvaluationReason + return ret + } + return *o.Reason +} + +// GetReasonOk returns a tuple with the Reason field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserFlagSetting) GetReasonOk() (*EvaluationReason, bool) { + if o == nil || o.Reason == nil { + return nil, false + } + return o.Reason, true +} + +// HasReason returns a boolean if a field has been set. +func (o *UserFlagSetting) HasReason() bool { + if o != nil && o.Reason != nil { + return true + } + + return false +} + +// SetReason gets a reference to the given EvaluationReason and assigns it to the Reason field. +func (o *UserFlagSetting) SetReason(v EvaluationReason) { + o.Reason = &v +} + +func (o UserFlagSetting) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if o.Value != nil { + toSerialize["_value"] = o.Value + } + if o.Setting != nil { + toSerialize["setting"] = o.Setting + } + if o.Reason != nil { + toSerialize["reason"] = o.Reason + } + return json.Marshal(toSerialize) +} + +type NullableUserFlagSetting struct { + value *UserFlagSetting + isSet bool +} + +func (v NullableUserFlagSetting) Get() *UserFlagSetting { + return v.value +} + +func (v *NullableUserFlagSetting) Set(val *UserFlagSetting) { + v.value = val + v.isSet = true +} + +func (v NullableUserFlagSetting) IsSet() bool { + return v.isSet +} + +func (v *NullableUserFlagSetting) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserFlagSetting(val *UserFlagSetting) *NullableUserFlagSetting { + return &NullableUserFlagSetting{value: val, isSet: true} +} + +func (v NullableUserFlagSetting) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserFlagSetting) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_settings.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_settings.go new file mode 100644 index 00000000..8c0558d1 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_flag_settings.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserFlagSettings struct for UserFlagSettings +type UserFlagSettings struct { + // An array of flag settings for the user + Items map[string]UserFlagSetting `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` +} + +// NewUserFlagSettings instantiates a new UserFlagSettings object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserFlagSettings(items map[string]UserFlagSetting, links map[string]Link) *UserFlagSettings { + this := UserFlagSettings{} + this.Items = items + this.Links = links + return &this +} + +// NewUserFlagSettingsWithDefaults instantiates a new UserFlagSettings object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserFlagSettingsWithDefaults() *UserFlagSettings { + this := UserFlagSettings{} + return &this +} + +// GetItems returns the Items field value +func (o *UserFlagSettings) GetItems() map[string]UserFlagSetting { + if o == nil { + var ret map[string]UserFlagSetting + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *UserFlagSettings) GetItemsOk() (*map[string]UserFlagSetting, bool) { + if o == nil { + return nil, false + } + return &o.Items, true +} + +// SetItems sets field value +func (o *UserFlagSettings) SetItems(v map[string]UserFlagSetting) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *UserFlagSettings) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *UserFlagSettings) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *UserFlagSettings) SetLinks(v map[string]Link) { + o.Links = v +} + +func (o UserFlagSettings) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + return json.Marshal(toSerialize) +} + +type NullableUserFlagSettings struct { + value *UserFlagSettings + isSet bool +} + +func (v NullableUserFlagSettings) Get() *UserFlagSettings { + return v.value +} + +func (v *NullableUserFlagSettings) Set(val *UserFlagSettings) { + v.value = val + v.isSet = true +} + +func (v NullableUserFlagSettings) IsSet() bool { + return v.isSet +} + +func (v *NullableUserFlagSettings) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserFlagSettings(val *UserFlagSettings) *NullableUserFlagSettings { + return &NullableUserFlagSettings{value: val, isSet: true} +} + +func (v NullableUserFlagSettings) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserFlagSettings) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_record.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_record.go new file mode 100644 index 00000000..d4cf62aa --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_record.go @@ -0,0 +1,337 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// UserRecord struct for UserRecord +type UserRecord struct { + // Timestamp of the last time this user was seen + LastPing *time.Time `json:"lastPing,omitempty"` + EnvironmentId *string `json:"environmentId,omitempty"` + OwnerId *string `json:"ownerId,omitempty"` + User *User `json:"user,omitempty"` + // If this record is returned as part of a list, the value used to sort the list. This is only included when the sort query parameter is specified. It is a time, in Unix milliseconds, if the sort is by lastSeen. It is a user key if the sort is by userKey. + SortValue interface{} `json:"sortValue,omitempty"` + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + Access *Access `json:"_access,omitempty"` +} + +// NewUserRecord instantiates a new UserRecord object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserRecord() *UserRecord { + this := UserRecord{} + return &this +} + +// NewUserRecordWithDefaults instantiates a new UserRecord object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserRecordWithDefaults() *UserRecord { + this := UserRecord{} + return &this +} + +// GetLastPing returns the LastPing field value if set, zero value otherwise. +func (o *UserRecord) GetLastPing() time.Time { + if o == nil || o.LastPing == nil { + var ret time.Time + return ret + } + return *o.LastPing +} + +// GetLastPingOk returns a tuple with the LastPing field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetLastPingOk() (*time.Time, bool) { + if o == nil || o.LastPing == nil { + return nil, false + } + return o.LastPing, true +} + +// HasLastPing returns a boolean if a field has been set. +func (o *UserRecord) HasLastPing() bool { + if o != nil && o.LastPing != nil { + return true + } + + return false +} + +// SetLastPing gets a reference to the given time.Time and assigns it to the LastPing field. +func (o *UserRecord) SetLastPing(v time.Time) { + o.LastPing = &v +} + +// GetEnvironmentId returns the EnvironmentId field value if set, zero value otherwise. +func (o *UserRecord) GetEnvironmentId() string { + if o == nil || o.EnvironmentId == nil { + var ret string + return ret + } + return *o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetEnvironmentIdOk() (*string, bool) { + if o == nil || o.EnvironmentId == nil { + return nil, false + } + return o.EnvironmentId, true +} + +// HasEnvironmentId returns a boolean if a field has been set. +func (o *UserRecord) HasEnvironmentId() bool { + if o != nil && o.EnvironmentId != nil { + return true + } + + return false +} + +// SetEnvironmentId gets a reference to the given string and assigns it to the EnvironmentId field. +func (o *UserRecord) SetEnvironmentId(v string) { + o.EnvironmentId = &v +} + +// GetOwnerId returns the OwnerId field value if set, zero value otherwise. +func (o *UserRecord) GetOwnerId() string { + if o == nil || o.OwnerId == nil { + var ret string + return ret + } + return *o.OwnerId +} + +// GetOwnerIdOk returns a tuple with the OwnerId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetOwnerIdOk() (*string, bool) { + if o == nil || o.OwnerId == nil { + return nil, false + } + return o.OwnerId, true +} + +// HasOwnerId returns a boolean if a field has been set. +func (o *UserRecord) HasOwnerId() bool { + if o != nil && o.OwnerId != nil { + return true + } + + return false +} + +// SetOwnerId gets a reference to the given string and assigns it to the OwnerId field. +func (o *UserRecord) SetOwnerId(v string) { + o.OwnerId = &v +} + +// GetUser returns the User field value if set, zero value otherwise. +func (o *UserRecord) GetUser() User { + if o == nil || o.User == nil { + var ret User + return ret + } + return *o.User +} + +// GetUserOk returns a tuple with the User field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetUserOk() (*User, bool) { + if o == nil || o.User == nil { + return nil, false + } + return o.User, true +} + +// HasUser returns a boolean if a field has been set. +func (o *UserRecord) HasUser() bool { + if o != nil && o.User != nil { + return true + } + + return false +} + +// SetUser gets a reference to the given User and assigns it to the User field. +func (o *UserRecord) SetUser(v User) { + o.User = &v +} + +// GetSortValue returns the SortValue field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *UserRecord) GetSortValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.SortValue +} + +// GetSortValueOk returns a tuple with the SortValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *UserRecord) GetSortValueOk() (*interface{}, bool) { + if o == nil || o.SortValue == nil { + return nil, false + } + return &o.SortValue, true +} + +// HasSortValue returns a boolean if a field has been set. +func (o *UserRecord) HasSortValue() bool { + if o != nil && o.SortValue != nil { + return true + } + + return false +} + +// SetSortValue gets a reference to the given interface{} and assigns it to the SortValue field. +func (o *UserRecord) SetSortValue(v interface{}) { + o.SortValue = v +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *UserRecord) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *UserRecord) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *UserRecord) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *UserRecord) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserRecord) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *UserRecord) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *UserRecord) SetAccess(v Access) { + o.Access = &v +} + +func (o UserRecord) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.LastPing != nil { + toSerialize["lastPing"] = o.LastPing + } + if o.EnvironmentId != nil { + toSerialize["environmentId"] = o.EnvironmentId + } + if o.OwnerId != nil { + toSerialize["ownerId"] = o.OwnerId + } + if o.User != nil { + toSerialize["user"] = o.User + } + if o.SortValue != nil { + toSerialize["sortValue"] = o.SortValue + } + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableUserRecord struct { + value *UserRecord + isSet bool +} + +func (v NullableUserRecord) Get() *UserRecord { + return v.value +} + +func (v *NullableUserRecord) Set(val *UserRecord) { + v.value = val + v.isSet = true +} + +func (v NullableUserRecord) IsSet() bool { + return v.isSet +} + +func (v *NullableUserRecord) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserRecord(val *UserRecord) *NullableUserRecord { + return &NullableUserRecord{value: val, isSet: true} +} + +func (v NullableUserRecord) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserRecord) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment.go new file mode 100644 index 00000000..f36ec474 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment.go @@ -0,0 +1,855 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserSegment struct for UserSegment +type UserSegment struct { + // A human-friendly name for the segment. + Name string `json:"name"` + // A description of the segment's purpose. Defaults to null and is omitted in the response if not provided. + Description *string `json:"description,omitempty"` + // Tags for the segment. Defaults to an empty array. + Tags []string `json:"tags"` + CreationDate int64 `json:"creationDate"` + LastModifiedDate int64 `json:"lastModifiedDate"` + // A unique key used to reference the segment + Key string `json:"key"` + // An array of keys for included targets. Included individual targets are always segment members, regardless of segment rules. For list-based segments over 15,000 entries, also called big segments, this array is either empty or omitted. + Included []string `json:"included,omitempty"` + // An array of keys for excluded targets. Segment rules bypass individual excluded targets, so they will never be included based on rules. Excluded targets may still be included explicitly. This value is omitted for list-based segments over 15,000 entries, also called big segments. + Excluded []string `json:"excluded,omitempty"` + IncludedContexts []SegmentTarget `json:"includedContexts,omitempty"` + ExcludedContexts []SegmentTarget `json:"excludedContexts,omitempty"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of the targeting rules for this segment. + Rules []UserSegmentRule `json:"rules"` + // Version of the segment + Version int32 `json:"version"` + // Whether the segment has been deleted + Deleted bool `json:"deleted"` + Access *Access `json:"_access,omitempty"` + // A list of flags targeting this segment. Only included when getting a single segment, using the getSegment endpoint. + Flags []FlagListingRep `json:"_flags,omitempty"` + // Whether this is a standard segment (false) or a big segment (true). Standard segments include rule-based segments and smaller list-based segments. Big segments include larger list-based segments and synced segments. If omitted, the segment is a standard segment. + Unbounded *bool `json:"unbounded,omitempty"` + // For big segments, the targeted context kind. + UnboundedContextKind *string `json:"unboundedContextKind,omitempty"` + // For big segments, how many times this segment has been created. + Generation int32 `json:"generation"` + UnboundedMetadata *SegmentMetadata `json:"_unboundedMetadata,omitempty"` + // The external data store backing this segment. Only applies to synced segments. + External *string `json:"_external,omitempty"` + // The URL for the external data store backing this segment. Only applies to synced segments. + ExternalLink *string `json:"_externalLink,omitempty"` + // Whether an import is currently in progress for the specified segment. Only applies to big segments. + ImportInProgress *bool `json:"_importInProgress,omitempty"` +} + +// NewUserSegment instantiates a new UserSegment object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserSegment(name string, tags []string, creationDate int64, lastModifiedDate int64, key string, links map[string]Link, rules []UserSegmentRule, version int32, deleted bool, generation int32) *UserSegment { + this := UserSegment{} + this.Name = name + this.Tags = tags + this.CreationDate = creationDate + this.LastModifiedDate = lastModifiedDate + this.Key = key + this.Links = links + this.Rules = rules + this.Version = version + this.Deleted = deleted + this.Generation = generation + return &this +} + +// NewUserSegmentWithDefaults instantiates a new UserSegment object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserSegmentWithDefaults() *UserSegment { + this := UserSegment{} + return &this +} + +// GetName returns the Name field value +func (o *UserSegment) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *UserSegment) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *UserSegment) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *UserSegment) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *UserSegment) SetDescription(v string) { + o.Description = &v +} + +// GetTags returns the Tags field value +func (o *UserSegment) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *UserSegment) SetTags(v []string) { + o.Tags = v +} + +// GetCreationDate returns the CreationDate field value +func (o *UserSegment) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *UserSegment) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetLastModifiedDate returns the LastModifiedDate field value +func (o *UserSegment) GetLastModifiedDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.LastModifiedDate +} + +// GetLastModifiedDateOk returns a tuple with the LastModifiedDate field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetLastModifiedDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.LastModifiedDate, true +} + +// SetLastModifiedDate sets field value +func (o *UserSegment) SetLastModifiedDate(v int64) { + o.LastModifiedDate = v +} + +// GetKey returns the Key field value +func (o *UserSegment) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *UserSegment) SetKey(v string) { + o.Key = v +} + +// GetIncluded returns the Included field value if set, zero value otherwise. +func (o *UserSegment) GetIncluded() []string { + if o == nil || o.Included == nil { + var ret []string + return ret + } + return o.Included +} + +// GetIncludedOk returns a tuple with the Included field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetIncludedOk() ([]string, bool) { + if o == nil || o.Included == nil { + return nil, false + } + return o.Included, true +} + +// HasIncluded returns a boolean if a field has been set. +func (o *UserSegment) HasIncluded() bool { + if o != nil && o.Included != nil { + return true + } + + return false +} + +// SetIncluded gets a reference to the given []string and assigns it to the Included field. +func (o *UserSegment) SetIncluded(v []string) { + o.Included = v +} + +// GetExcluded returns the Excluded field value if set, zero value otherwise. +func (o *UserSegment) GetExcluded() []string { + if o == nil || o.Excluded == nil { + var ret []string + return ret + } + return o.Excluded +} + +// GetExcludedOk returns a tuple with the Excluded field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetExcludedOk() ([]string, bool) { + if o == nil || o.Excluded == nil { + return nil, false + } + return o.Excluded, true +} + +// HasExcluded returns a boolean if a field has been set. +func (o *UserSegment) HasExcluded() bool { + if o != nil && o.Excluded != nil { + return true + } + + return false +} + +// SetExcluded gets a reference to the given []string and assigns it to the Excluded field. +func (o *UserSegment) SetExcluded(v []string) { + o.Excluded = v +} + +// GetIncludedContexts returns the IncludedContexts field value if set, zero value otherwise. +func (o *UserSegment) GetIncludedContexts() []SegmentTarget { + if o == nil || o.IncludedContexts == nil { + var ret []SegmentTarget + return ret + } + return o.IncludedContexts +} + +// GetIncludedContextsOk returns a tuple with the IncludedContexts field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetIncludedContextsOk() ([]SegmentTarget, bool) { + if o == nil || o.IncludedContexts == nil { + return nil, false + } + return o.IncludedContexts, true +} + +// HasIncludedContexts returns a boolean if a field has been set. +func (o *UserSegment) HasIncludedContexts() bool { + if o != nil && o.IncludedContexts != nil { + return true + } + + return false +} + +// SetIncludedContexts gets a reference to the given []SegmentTarget and assigns it to the IncludedContexts field. +func (o *UserSegment) SetIncludedContexts(v []SegmentTarget) { + o.IncludedContexts = v +} + +// GetExcludedContexts returns the ExcludedContexts field value if set, zero value otherwise. +func (o *UserSegment) GetExcludedContexts() []SegmentTarget { + if o == nil || o.ExcludedContexts == nil { + var ret []SegmentTarget + return ret + } + return o.ExcludedContexts +} + +// GetExcludedContextsOk returns a tuple with the ExcludedContexts field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetExcludedContextsOk() ([]SegmentTarget, bool) { + if o == nil || o.ExcludedContexts == nil { + return nil, false + } + return o.ExcludedContexts, true +} + +// HasExcludedContexts returns a boolean if a field has been set. +func (o *UserSegment) HasExcludedContexts() bool { + if o != nil && o.ExcludedContexts != nil { + return true + } + + return false +} + +// SetExcludedContexts gets a reference to the given []SegmentTarget and assigns it to the ExcludedContexts field. +func (o *UserSegment) SetExcludedContexts(v []SegmentTarget) { + o.ExcludedContexts = v +} + +// GetLinks returns the Links field value +func (o *UserSegment) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *UserSegment) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetRules returns the Rules field value +func (o *UserSegment) GetRules() []UserSegmentRule { + if o == nil { + var ret []UserSegmentRule + return ret + } + + return o.Rules +} + +// GetRulesOk returns a tuple with the Rules field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetRulesOk() ([]UserSegmentRule, bool) { + if o == nil { + return nil, false + } + return o.Rules, true +} + +// SetRules sets field value +func (o *UserSegment) SetRules(v []UserSegmentRule) { + o.Rules = v +} + +// GetVersion returns the Version field value +func (o *UserSegment) GetVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Version +} + +// GetVersionOk returns a tuple with the Version field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Version, true +} + +// SetVersion sets field value +func (o *UserSegment) SetVersion(v int32) { + o.Version = v +} + +// GetDeleted returns the Deleted field value +func (o *UserSegment) GetDeleted() bool { + if o == nil { + var ret bool + return ret + } + + return o.Deleted +} + +// GetDeletedOk returns a tuple with the Deleted field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetDeletedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Deleted, true +} + +// SetDeleted sets field value +func (o *UserSegment) SetDeleted(v bool) { + o.Deleted = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *UserSegment) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *UserSegment) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *UserSegment) SetAccess(v Access) { + o.Access = &v +} + +// GetFlags returns the Flags field value if set, zero value otherwise. +func (o *UserSegment) GetFlags() []FlagListingRep { + if o == nil || o.Flags == nil { + var ret []FlagListingRep + return ret + } + return o.Flags +} + +// GetFlagsOk returns a tuple with the Flags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetFlagsOk() ([]FlagListingRep, bool) { + if o == nil || o.Flags == nil { + return nil, false + } + return o.Flags, true +} + +// HasFlags returns a boolean if a field has been set. +func (o *UserSegment) HasFlags() bool { + if o != nil && o.Flags != nil { + return true + } + + return false +} + +// SetFlags gets a reference to the given []FlagListingRep and assigns it to the Flags field. +func (o *UserSegment) SetFlags(v []FlagListingRep) { + o.Flags = v +} + +// GetUnbounded returns the Unbounded field value if set, zero value otherwise. +func (o *UserSegment) GetUnbounded() bool { + if o == nil || o.Unbounded == nil { + var ret bool + return ret + } + return *o.Unbounded +} + +// GetUnboundedOk returns a tuple with the Unbounded field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetUnboundedOk() (*bool, bool) { + if o == nil || o.Unbounded == nil { + return nil, false + } + return o.Unbounded, true +} + +// HasUnbounded returns a boolean if a field has been set. +func (o *UserSegment) HasUnbounded() bool { + if o != nil && o.Unbounded != nil { + return true + } + + return false +} + +// SetUnbounded gets a reference to the given bool and assigns it to the Unbounded field. +func (o *UserSegment) SetUnbounded(v bool) { + o.Unbounded = &v +} + +// GetUnboundedContextKind returns the UnboundedContextKind field value if set, zero value otherwise. +func (o *UserSegment) GetUnboundedContextKind() string { + if o == nil || o.UnboundedContextKind == nil { + var ret string + return ret + } + return *o.UnboundedContextKind +} + +// GetUnboundedContextKindOk returns a tuple with the UnboundedContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetUnboundedContextKindOk() (*string, bool) { + if o == nil || o.UnboundedContextKind == nil { + return nil, false + } + return o.UnboundedContextKind, true +} + +// HasUnboundedContextKind returns a boolean if a field has been set. +func (o *UserSegment) HasUnboundedContextKind() bool { + if o != nil && o.UnboundedContextKind != nil { + return true + } + + return false +} + +// SetUnboundedContextKind gets a reference to the given string and assigns it to the UnboundedContextKind field. +func (o *UserSegment) SetUnboundedContextKind(v string) { + o.UnboundedContextKind = &v +} + +// GetGeneration returns the Generation field value +func (o *UserSegment) GetGeneration() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Generation +} + +// GetGenerationOk returns a tuple with the Generation field value +// and a boolean to check if the value has been set. +func (o *UserSegment) GetGenerationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Generation, true +} + +// SetGeneration sets field value +func (o *UserSegment) SetGeneration(v int32) { + o.Generation = v +} + +// GetUnboundedMetadata returns the UnboundedMetadata field value if set, zero value otherwise. +func (o *UserSegment) GetUnboundedMetadata() SegmentMetadata { + if o == nil || o.UnboundedMetadata == nil { + var ret SegmentMetadata + return ret + } + return *o.UnboundedMetadata +} + +// GetUnboundedMetadataOk returns a tuple with the UnboundedMetadata field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetUnboundedMetadataOk() (*SegmentMetadata, bool) { + if o == nil || o.UnboundedMetadata == nil { + return nil, false + } + return o.UnboundedMetadata, true +} + +// HasUnboundedMetadata returns a boolean if a field has been set. +func (o *UserSegment) HasUnboundedMetadata() bool { + if o != nil && o.UnboundedMetadata != nil { + return true + } + + return false +} + +// SetUnboundedMetadata gets a reference to the given SegmentMetadata and assigns it to the UnboundedMetadata field. +func (o *UserSegment) SetUnboundedMetadata(v SegmentMetadata) { + o.UnboundedMetadata = &v +} + +// GetExternal returns the External field value if set, zero value otherwise. +func (o *UserSegment) GetExternal() string { + if o == nil || o.External == nil { + var ret string + return ret + } + return *o.External +} + +// GetExternalOk returns a tuple with the External field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetExternalOk() (*string, bool) { + if o == nil || o.External == nil { + return nil, false + } + return o.External, true +} + +// HasExternal returns a boolean if a field has been set. +func (o *UserSegment) HasExternal() bool { + if o != nil && o.External != nil { + return true + } + + return false +} + +// SetExternal gets a reference to the given string and assigns it to the External field. +func (o *UserSegment) SetExternal(v string) { + o.External = &v +} + +// GetExternalLink returns the ExternalLink field value if set, zero value otherwise. +func (o *UserSegment) GetExternalLink() string { + if o == nil || o.ExternalLink == nil { + var ret string + return ret + } + return *o.ExternalLink +} + +// GetExternalLinkOk returns a tuple with the ExternalLink field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetExternalLinkOk() (*string, bool) { + if o == nil || o.ExternalLink == nil { + return nil, false + } + return o.ExternalLink, true +} + +// HasExternalLink returns a boolean if a field has been set. +func (o *UserSegment) HasExternalLink() bool { + if o != nil && o.ExternalLink != nil { + return true + } + + return false +} + +// SetExternalLink gets a reference to the given string and assigns it to the ExternalLink field. +func (o *UserSegment) SetExternalLink(v string) { + o.ExternalLink = &v +} + +// GetImportInProgress returns the ImportInProgress field value if set, zero value otherwise. +func (o *UserSegment) GetImportInProgress() bool { + if o == nil || o.ImportInProgress == nil { + var ret bool + return ret + } + return *o.ImportInProgress +} + +// GetImportInProgressOk returns a tuple with the ImportInProgress field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegment) GetImportInProgressOk() (*bool, bool) { + if o == nil || o.ImportInProgress == nil { + return nil, false + } + return o.ImportInProgress, true +} + +// HasImportInProgress returns a boolean if a field has been set. +func (o *UserSegment) HasImportInProgress() bool { + if o != nil && o.ImportInProgress != nil { + return true + } + + return false +} + +// SetImportInProgress gets a reference to the given bool and assigns it to the ImportInProgress field. +func (o *UserSegment) SetImportInProgress(v bool) { + o.ImportInProgress = &v +} + +func (o UserSegment) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if true { + toSerialize["tags"] = o.Tags + } + if true { + toSerialize["creationDate"] = o.CreationDate + } + if true { + toSerialize["lastModifiedDate"] = o.LastModifiedDate + } + if true { + toSerialize["key"] = o.Key + } + if o.Included != nil { + toSerialize["included"] = o.Included + } + if o.Excluded != nil { + toSerialize["excluded"] = o.Excluded + } + if o.IncludedContexts != nil { + toSerialize["includedContexts"] = o.IncludedContexts + } + if o.ExcludedContexts != nil { + toSerialize["excludedContexts"] = o.ExcludedContexts + } + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["rules"] = o.Rules + } + if true { + toSerialize["version"] = o.Version + } + if true { + toSerialize["deleted"] = o.Deleted + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + if o.Flags != nil { + toSerialize["_flags"] = o.Flags + } + if o.Unbounded != nil { + toSerialize["unbounded"] = o.Unbounded + } + if o.UnboundedContextKind != nil { + toSerialize["unboundedContextKind"] = o.UnboundedContextKind + } + if true { + toSerialize["generation"] = o.Generation + } + if o.UnboundedMetadata != nil { + toSerialize["_unboundedMetadata"] = o.UnboundedMetadata + } + if o.External != nil { + toSerialize["_external"] = o.External + } + if o.ExternalLink != nil { + toSerialize["_externalLink"] = o.ExternalLink + } + if o.ImportInProgress != nil { + toSerialize["_importInProgress"] = o.ImportInProgress + } + return json.Marshal(toSerialize) +} + +type NullableUserSegment struct { + value *UserSegment + isSet bool +} + +func (v NullableUserSegment) Get() *UserSegment { + return v.value +} + +func (v *NullableUserSegment) Set(val *UserSegment) { + v.value = val + v.isSet = true +} + +func (v NullableUserSegment) IsSet() bool { + return v.isSet +} + +func (v *NullableUserSegment) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserSegment(val *UserSegment) *NullableUserSegment { + return &NullableUserSegment{value: val, isSet: true} +} + +func (v NullableUserSegment) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserSegment) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment_rule.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment_rule.go new file mode 100644 index 00000000..b3399c1a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segment_rule.go @@ -0,0 +1,289 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserSegmentRule struct for UserSegmentRule +type UserSegmentRule struct { + Id *string `json:"_id,omitempty"` + Clauses []Clause `json:"clauses"` + Weight *int32 `json:"weight,omitempty"` + RolloutContextKind *string `json:"rolloutContextKind,omitempty"` + BucketBy *string `json:"bucketBy,omitempty"` + Description *string `json:"description,omitempty"` +} + +// NewUserSegmentRule instantiates a new UserSegmentRule object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserSegmentRule(clauses []Clause) *UserSegmentRule { + this := UserSegmentRule{} + this.Clauses = clauses + return &this +} + +// NewUserSegmentRuleWithDefaults instantiates a new UserSegmentRule object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserSegmentRuleWithDefaults() *UserSegmentRule { + this := UserSegmentRule{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *UserSegmentRule) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *UserSegmentRule) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *UserSegmentRule) SetId(v string) { + o.Id = &v +} + +// GetClauses returns the Clauses field value +func (o *UserSegmentRule) GetClauses() []Clause { + if o == nil { + var ret []Clause + return ret + } + + return o.Clauses +} + +// GetClausesOk returns a tuple with the Clauses field value +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetClausesOk() ([]Clause, bool) { + if o == nil { + return nil, false + } + return o.Clauses, true +} + +// SetClauses sets field value +func (o *UserSegmentRule) SetClauses(v []Clause) { + o.Clauses = v +} + +// GetWeight returns the Weight field value if set, zero value otherwise. +func (o *UserSegmentRule) GetWeight() int32 { + if o == nil || o.Weight == nil { + var ret int32 + return ret + } + return *o.Weight +} + +// GetWeightOk returns a tuple with the Weight field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetWeightOk() (*int32, bool) { + if o == nil || o.Weight == nil { + return nil, false + } + return o.Weight, true +} + +// HasWeight returns a boolean if a field has been set. +func (o *UserSegmentRule) HasWeight() bool { + if o != nil && o.Weight != nil { + return true + } + + return false +} + +// SetWeight gets a reference to the given int32 and assigns it to the Weight field. +func (o *UserSegmentRule) SetWeight(v int32) { + o.Weight = &v +} + +// GetRolloutContextKind returns the RolloutContextKind field value if set, zero value otherwise. +func (o *UserSegmentRule) GetRolloutContextKind() string { + if o == nil || o.RolloutContextKind == nil { + var ret string + return ret + } + return *o.RolloutContextKind +} + +// GetRolloutContextKindOk returns a tuple with the RolloutContextKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetRolloutContextKindOk() (*string, bool) { + if o == nil || o.RolloutContextKind == nil { + return nil, false + } + return o.RolloutContextKind, true +} + +// HasRolloutContextKind returns a boolean if a field has been set. +func (o *UserSegmentRule) HasRolloutContextKind() bool { + if o != nil && o.RolloutContextKind != nil { + return true + } + + return false +} + +// SetRolloutContextKind gets a reference to the given string and assigns it to the RolloutContextKind field. +func (o *UserSegmentRule) SetRolloutContextKind(v string) { + o.RolloutContextKind = &v +} + +// GetBucketBy returns the BucketBy field value if set, zero value otherwise. +func (o *UserSegmentRule) GetBucketBy() string { + if o == nil || o.BucketBy == nil { + var ret string + return ret + } + return *o.BucketBy +} + +// GetBucketByOk returns a tuple with the BucketBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetBucketByOk() (*string, bool) { + if o == nil || o.BucketBy == nil { + return nil, false + } + return o.BucketBy, true +} + +// HasBucketBy returns a boolean if a field has been set. +func (o *UserSegmentRule) HasBucketBy() bool { + if o != nil && o.BucketBy != nil { + return true + } + + return false +} + +// SetBucketBy gets a reference to the given string and assigns it to the BucketBy field. +func (o *UserSegmentRule) SetBucketBy(v string) { + o.BucketBy = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *UserSegmentRule) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegmentRule) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *UserSegmentRule) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *UserSegmentRule) SetDescription(v string) { + o.Description = &v +} + +func (o UserSegmentRule) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["clauses"] = o.Clauses + } + if o.Weight != nil { + toSerialize["weight"] = o.Weight + } + if o.RolloutContextKind != nil { + toSerialize["rolloutContextKind"] = o.RolloutContextKind + } + if o.BucketBy != nil { + toSerialize["bucketBy"] = o.BucketBy + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + return json.Marshal(toSerialize) +} + +type NullableUserSegmentRule struct { + value *UserSegmentRule + isSet bool +} + +func (v NullableUserSegmentRule) Get() *UserSegmentRule { + return v.value +} + +func (v *NullableUserSegmentRule) Set(val *UserSegmentRule) { + v.value = val + v.isSet = true +} + +func (v NullableUserSegmentRule) IsSet() bool { + return v.isSet +} + +func (v *NullableUserSegmentRule) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserSegmentRule(val *UserSegmentRule) *NullableUserSegmentRule { + return &NullableUserSegmentRule{value: val, isSet: true} +} + +func (v NullableUserSegmentRule) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserSegmentRule) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segments.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segments.go new file mode 100644 index 00000000..609c78ea --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_user_segments.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UserSegments struct for UserSegments +type UserSegments struct { + // An array of segments + Items []UserSegment `json:"items"` + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The total number of segments + TotalCount *int32 `json:"totalCount,omitempty"` +} + +// NewUserSegments instantiates a new UserSegments object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUserSegments(items []UserSegment, links map[string]Link) *UserSegments { + this := UserSegments{} + this.Items = items + this.Links = links + return &this +} + +// NewUserSegmentsWithDefaults instantiates a new UserSegments object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUserSegmentsWithDefaults() *UserSegments { + this := UserSegments{} + return &this +} + +// GetItems returns the Items field value +func (o *UserSegments) GetItems() []UserSegment { + if o == nil { + var ret []UserSegment + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *UserSegments) GetItemsOk() ([]UserSegment, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *UserSegments) SetItems(v []UserSegment) { + o.Items = v +} + +// GetLinks returns the Links field value +func (o *UserSegments) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *UserSegments) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *UserSegments) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetTotalCount returns the TotalCount field value if set, zero value otherwise. +func (o *UserSegments) GetTotalCount() int32 { + if o == nil || o.TotalCount == nil { + var ret int32 + return ret + } + return *o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UserSegments) GetTotalCountOk() (*int32, bool) { + if o == nil || o.TotalCount == nil { + return nil, false + } + return o.TotalCount, true +} + +// HasTotalCount returns a boolean if a field has been set. +func (o *UserSegments) HasTotalCount() bool { + if o != nil && o.TotalCount != nil { + return true + } + + return false +} + +// SetTotalCount gets a reference to the given int32 and assigns it to the TotalCount field. +func (o *UserSegments) SetTotalCount(v int32) { + o.TotalCount = &v +} + +func (o UserSegments) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + if true { + toSerialize["_links"] = o.Links + } + if o.TotalCount != nil { + toSerialize["totalCount"] = o.TotalCount + } + return json.Marshal(toSerialize) +} + +type NullableUserSegments struct { + value *UserSegments + isSet bool +} + +func (v NullableUserSegments) Get() *UserSegments { + return v.value +} + +func (v *NullableUserSegments) Set(val *UserSegments) { + v.value = val + v.isSet = true +} + +func (v NullableUserSegments) IsSet() bool { + return v.isSet +} + +func (v *NullableUserSegments) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUserSegments(val *UserSegments) *NullableUserSegments { + return &NullableUserSegments{value: val, isSet: true} +} + +func (v NullableUserSegments) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUserSegments) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_users.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_users.go new file mode 100644 index 00000000..10c19bc2 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_users.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Users struct for Users +type Users struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The total number of users in the environment + TotalCount int32 `json:"totalCount"` + // Details on the users + Items []UserRecord `json:"items"` +} + +// NewUsers instantiates a new Users object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUsers(totalCount int32, items []UserRecord) *Users { + this := Users{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewUsersWithDefaults instantiates a new Users object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUsersWithDefaults() *Users { + this := Users{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Users) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Users) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Users) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *Users) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value +func (o *Users) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *Users) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *Users) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *Users) GetItems() []UserRecord { + if o == nil { + var ret []UserRecord + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Users) GetItemsOk() ([]UserRecord, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Users) SetItems(v []UserRecord) { + o.Items = v +} + +func (o Users) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableUsers struct { + value *Users + isSet bool +} + +func (v NullableUsers) Get() *Users { + return v.value +} + +func (v *NullableUsers) Set(val *Users) { + v.value = val + v.isSet = true +} + +func (v NullableUsers) IsSet() bool { + return v.isSet +} + +func (v *NullableUsers) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUsers(val *Users) *NullableUsers { + return &NullableUsers{value: val, isSet: true} +} + +func (v NullableUsers) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUsers) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_users_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_users_rep.go new file mode 100644 index 00000000..4d71c279 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_users_rep.go @@ -0,0 +1,177 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// UsersRep struct for UsersRep +type UsersRep struct { + // The location and content type of related resources + Links *map[string]Link `json:"_links,omitempty"` + // The total number of users in the environment + TotalCount int32 `json:"totalCount"` + // Details on the users + Items []UserRecord `json:"items"` +} + +// NewUsersRep instantiates a new UsersRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUsersRep(totalCount int32, items []UserRecord) *UsersRep { + this := UsersRep{} + this.TotalCount = totalCount + this.Items = items + return &this +} + +// NewUsersRepWithDefaults instantiates a new UsersRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUsersRepWithDefaults() *UsersRep { + this := UsersRep{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *UsersRep) GetLinks() map[string]Link { + if o == nil || o.Links == nil { + var ret map[string]Link + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UsersRep) GetLinksOk() (*map[string]Link, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *UsersRep) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given map[string]Link and assigns it to the Links field. +func (o *UsersRep) SetLinks(v map[string]Link) { + o.Links = &v +} + +// GetTotalCount returns the TotalCount field value +func (o *UsersRep) GetTotalCount() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.TotalCount +} + +// GetTotalCountOk returns a tuple with the TotalCount field value +// and a boolean to check if the value has been set. +func (o *UsersRep) GetTotalCountOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.TotalCount, true +} + +// SetTotalCount sets field value +func (o *UsersRep) SetTotalCount(v int32) { + o.TotalCount = v +} + +// GetItems returns the Items field value +func (o *UsersRep) GetItems() []UserRecord { + if o == nil { + var ret []UserRecord + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *UsersRep) GetItemsOk() ([]UserRecord, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *UsersRep) SetItems(v []UserRecord) { + o.Items = v +} + +func (o UsersRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["totalCount"] = o.TotalCount + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableUsersRep struct { + value *UsersRep + isSet bool +} + +func (v NullableUsersRep) Get() *UsersRep { + return v.value +} + +func (v *NullableUsersRep) Set(val *UsersRep) { + v.value = val + v.isSet = true +} + +func (v NullableUsersRep) IsSet() bool { + return v.isSet +} + +func (v *NullableUsersRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUsersRep(val *UsersRep) *NullableUsersRep { + return &NullableUsersRep{value: val, isSet: true} +} + +func (v NullableUsersRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUsersRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_validation_failed_error_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_validation_failed_error_rep.go new file mode 100644 index 00000000..05636ddd --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_validation_failed_error_rep.go @@ -0,0 +1,170 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ValidationFailedErrorRep struct for ValidationFailedErrorRep +type ValidationFailedErrorRep struct { + // Specific error code encountered + Code string `json:"code"` + // Description of the error + Message string `json:"message"` + // List of validation errors + Errors []FailureReasonRep `json:"errors"` +} + +// NewValidationFailedErrorRep instantiates a new ValidationFailedErrorRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewValidationFailedErrorRep(code string, message string, errors []FailureReasonRep) *ValidationFailedErrorRep { + this := ValidationFailedErrorRep{} + this.Code = code + this.Message = message + this.Errors = errors + return &this +} + +// NewValidationFailedErrorRepWithDefaults instantiates a new ValidationFailedErrorRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewValidationFailedErrorRepWithDefaults() *ValidationFailedErrorRep { + this := ValidationFailedErrorRep{} + return &this +} + +// GetCode returns the Code field value +func (o *ValidationFailedErrorRep) GetCode() string { + if o == nil { + var ret string + return ret + } + + return o.Code +} + +// GetCodeOk returns a tuple with the Code field value +// and a boolean to check if the value has been set. +func (o *ValidationFailedErrorRep) GetCodeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Code, true +} + +// SetCode sets field value +func (o *ValidationFailedErrorRep) SetCode(v string) { + o.Code = v +} + +// GetMessage returns the Message field value +func (o *ValidationFailedErrorRep) GetMessage() string { + if o == nil { + var ret string + return ret + } + + return o.Message +} + +// GetMessageOk returns a tuple with the Message field value +// and a boolean to check if the value has been set. +func (o *ValidationFailedErrorRep) GetMessageOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Message, true +} + +// SetMessage sets field value +func (o *ValidationFailedErrorRep) SetMessage(v string) { + o.Message = v +} + +// GetErrors returns the Errors field value +func (o *ValidationFailedErrorRep) GetErrors() []FailureReasonRep { + if o == nil { + var ret []FailureReasonRep + return ret + } + + return o.Errors +} + +// GetErrorsOk returns a tuple with the Errors field value +// and a boolean to check if the value has been set. +func (o *ValidationFailedErrorRep) GetErrorsOk() ([]FailureReasonRep, bool) { + if o == nil { + return nil, false + } + return o.Errors, true +} + +// SetErrors sets field value +func (o *ValidationFailedErrorRep) SetErrors(v []FailureReasonRep) { + o.Errors = v +} + +func (o ValidationFailedErrorRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["code"] = o.Code + } + if true { + toSerialize["message"] = o.Message + } + if true { + toSerialize["errors"] = o.Errors + } + return json.Marshal(toSerialize) +} + +type NullableValidationFailedErrorRep struct { + value *ValidationFailedErrorRep + isSet bool +} + +func (v NullableValidationFailedErrorRep) Get() *ValidationFailedErrorRep { + return v.value +} + +func (v *NullableValidationFailedErrorRep) Set(val *ValidationFailedErrorRep) { + v.value = val + v.isSet = true +} + +func (v NullableValidationFailedErrorRep) IsSet() bool { + return v.isSet +} + +func (v *NullableValidationFailedErrorRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableValidationFailedErrorRep(val *ValidationFailedErrorRep) *NullableValidationFailedErrorRep { + return &NullableValidationFailedErrorRep{value: val, isSet: true} +} + +func (v NullableValidationFailedErrorRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableValidationFailedErrorRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_value_put.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_value_put.go new file mode 100644 index 00000000..d76c7101 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_value_put.go @@ -0,0 +1,155 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// ValuePut struct for ValuePut +type ValuePut struct { + // The variation value to set for the context. Must match the flag's variation type. + Setting interface{} `json:"setting,omitempty"` + // Optional comment describing the change + Comment *string `json:"comment,omitempty"` +} + +// NewValuePut instantiates a new ValuePut object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewValuePut() *ValuePut { + this := ValuePut{} + return &this +} + +// NewValuePutWithDefaults instantiates a new ValuePut object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewValuePutWithDefaults() *ValuePut { + this := ValuePut{} + return &this +} + +// GetSetting returns the Setting field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *ValuePut) GetSetting() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Setting +} + +// GetSettingOk returns a tuple with the Setting field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *ValuePut) GetSettingOk() (*interface{}, bool) { + if o == nil || o.Setting == nil { + return nil, false + } + return &o.Setting, true +} + +// HasSetting returns a boolean if a field has been set. +func (o *ValuePut) HasSetting() bool { + if o != nil && o.Setting != nil { + return true + } + + return false +} + +// SetSetting gets a reference to the given interface{} and assigns it to the Setting field. +func (o *ValuePut) SetSetting(v interface{}) { + o.Setting = v +} + +// GetComment returns the Comment field value if set, zero value otherwise. +func (o *ValuePut) GetComment() string { + if o == nil || o.Comment == nil { + var ret string + return ret + } + return *o.Comment +} + +// GetCommentOk returns a tuple with the Comment field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ValuePut) GetCommentOk() (*string, bool) { + if o == nil || o.Comment == nil { + return nil, false + } + return o.Comment, true +} + +// HasComment returns a boolean if a field has been set. +func (o *ValuePut) HasComment() bool { + if o != nil && o.Comment != nil { + return true + } + + return false +} + +// SetComment gets a reference to the given string and assigns it to the Comment field. +func (o *ValuePut) SetComment(v string) { + o.Comment = &v +} + +func (o ValuePut) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Setting != nil { + toSerialize["setting"] = o.Setting + } + if o.Comment != nil { + toSerialize["comment"] = o.Comment + } + return json.Marshal(toSerialize) +} + +type NullableValuePut struct { + value *ValuePut + isSet bool +} + +func (v NullableValuePut) Get() *ValuePut { + return v.value +} + +func (v *NullableValuePut) Set(val *ValuePut) { + v.value = val + v.isSet = true +} + +func (v NullableValuePut) IsSet() bool { + return v.isSet +} + +func (v *NullableValuePut) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableValuePut(val *ValuePut) *NullableValuePut { + return &NullableValuePut{value: val, isSet: true} +} + +func (v NullableValuePut) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableValuePut) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_variation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation.go new file mode 100644 index 00000000..be747500 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation.go @@ -0,0 +1,223 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Variation struct for Variation +type Variation struct { + // The ID of the variation. Leave empty when you are creating a flag. + Id *string `json:"_id,omitempty"` + // The value of the variation. For boolean flags, this must be true or false. For multivariate flags, this may be a string, number, or JSON object. + Value interface{} `json:"value"` + // Description of the variation. Defaults to an empty string, but is omitted from the response if not set. + Description *string `json:"description,omitempty"` + // A human-friendly name for the variation. Defaults to an empty string, but is omitted from the response if not set. + Name *string `json:"name,omitempty"` +} + +// NewVariation instantiates a new Variation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewVariation(value interface{}) *Variation { + this := Variation{} + this.Value = value + return &this +} + +// NewVariationWithDefaults instantiates a new Variation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewVariationWithDefaults() *Variation { + this := Variation{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *Variation) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Variation) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *Variation) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *Variation) SetId(v string) { + o.Id = &v +} + +// GetValue returns the Value field value +// If the value is explicit nil, the zero value for interface{} will be returned +func (o *Variation) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *Variation) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *Variation) SetValue(v interface{}) { + o.Value = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *Variation) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Variation) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *Variation) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *Variation) SetDescription(v string) { + o.Description = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Variation) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Variation) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Variation) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Variation) SetName(v string) { + o.Name = &v +} + +func (o Variation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + return json.Marshal(toSerialize) +} + +type NullableVariation struct { + value *Variation + isSet bool +} + +func (v NullableVariation) Get() *Variation { + return v.value +} + +func (v *NullableVariation) Set(val *Variation) { + v.value = val + v.isSet = true +} + +func (v NullableVariation) IsSet() bool { + return v.isSet +} + +func (v *NullableVariation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableVariation(val *Variation) *NullableVariation { + return &NullableVariation{value: val, isSet: true} +} + +func (v NullableVariation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableVariation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_eval_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_eval_summary.go new file mode 100644 index 00000000..2e85cc4b --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_eval_summary.go @@ -0,0 +1,192 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// VariationEvalSummary struct for VariationEvalSummary +type VariationEvalSummary struct { + // The variation value + Value interface{} `json:"value,omitempty"` + // The number of evaluations in the ten minutes before the flag event + Before *int64 `json:"before,omitempty"` + // The number of evaluations in the ten minutes after the flag event + After *int64 `json:"after,omitempty"` +} + +// NewVariationEvalSummary instantiates a new VariationEvalSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewVariationEvalSummary() *VariationEvalSummary { + this := VariationEvalSummary{} + return &this +} + +// NewVariationEvalSummaryWithDefaults instantiates a new VariationEvalSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewVariationEvalSummaryWithDefaults() *VariationEvalSummary { + this := VariationEvalSummary{} + return &this +} + +// GetValue returns the Value field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *VariationEvalSummary) GetValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *VariationEvalSummary) GetValueOk() (*interface{}, bool) { + if o == nil || o.Value == nil { + return nil, false + } + return &o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *VariationEvalSummary) HasValue() bool { + if o != nil && o.Value != nil { + return true + } + + return false +} + +// SetValue gets a reference to the given interface{} and assigns it to the Value field. +func (o *VariationEvalSummary) SetValue(v interface{}) { + o.Value = v +} + +// GetBefore returns the Before field value if set, zero value otherwise. +func (o *VariationEvalSummary) GetBefore() int64 { + if o == nil || o.Before == nil { + var ret int64 + return ret + } + return *o.Before +} + +// GetBeforeOk returns a tuple with the Before field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationEvalSummary) GetBeforeOk() (*int64, bool) { + if o == nil || o.Before == nil { + return nil, false + } + return o.Before, true +} + +// HasBefore returns a boolean if a field has been set. +func (o *VariationEvalSummary) HasBefore() bool { + if o != nil && o.Before != nil { + return true + } + + return false +} + +// SetBefore gets a reference to the given int64 and assigns it to the Before field. +func (o *VariationEvalSummary) SetBefore(v int64) { + o.Before = &v +} + +// GetAfter returns the After field value if set, zero value otherwise. +func (o *VariationEvalSummary) GetAfter() int64 { + if o == nil || o.After == nil { + var ret int64 + return ret + } + return *o.After +} + +// GetAfterOk returns a tuple with the After field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationEvalSummary) GetAfterOk() (*int64, bool) { + if o == nil || o.After == nil { + return nil, false + } + return o.After, true +} + +// HasAfter returns a boolean if a field has been set. +func (o *VariationEvalSummary) HasAfter() bool { + if o != nil && o.After != nil { + return true + } + + return false +} + +// SetAfter gets a reference to the given int64 and assigns it to the After field. +func (o *VariationEvalSummary) SetAfter(v int64) { + o.After = &v +} + +func (o VariationEvalSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Value != nil { + toSerialize["value"] = o.Value + } + if o.Before != nil { + toSerialize["before"] = o.Before + } + if o.After != nil { + toSerialize["after"] = o.After + } + return json.Marshal(toSerialize) +} + +type NullableVariationEvalSummary struct { + value *VariationEvalSummary + isSet bool +} + +func (v NullableVariationEvalSummary) Get() *VariationEvalSummary { + return v.value +} + +func (v *NullableVariationEvalSummary) Set(val *VariationEvalSummary) { + v.value = val + v.isSet = true +} + +func (v NullableVariationEvalSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableVariationEvalSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableVariationEvalSummary(val *VariationEvalSummary) *NullableVariationEvalSummary { + return &NullableVariationEvalSummary{value: val, isSet: true} +} + +func (v NullableVariationEvalSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableVariationEvalSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_or_rollout_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_or_rollout_rep.go new file mode 100644 index 00000000..ed3920e6 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_or_rollout_rep.go @@ -0,0 +1,153 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// VariationOrRolloutRep struct for VariationOrRolloutRep +type VariationOrRolloutRep struct { + // The index of the variation, from the array of variations for this flag + Variation *int32 `json:"variation,omitempty"` + Rollout *Rollout `json:"rollout,omitempty"` +} + +// NewVariationOrRolloutRep instantiates a new VariationOrRolloutRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewVariationOrRolloutRep() *VariationOrRolloutRep { + this := VariationOrRolloutRep{} + return &this +} + +// NewVariationOrRolloutRepWithDefaults instantiates a new VariationOrRolloutRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewVariationOrRolloutRepWithDefaults() *VariationOrRolloutRep { + this := VariationOrRolloutRep{} + return &this +} + +// GetVariation returns the Variation field value if set, zero value otherwise. +func (o *VariationOrRolloutRep) GetVariation() int32 { + if o == nil || o.Variation == nil { + var ret int32 + return ret + } + return *o.Variation +} + +// GetVariationOk returns a tuple with the Variation field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationOrRolloutRep) GetVariationOk() (*int32, bool) { + if o == nil || o.Variation == nil { + return nil, false + } + return o.Variation, true +} + +// HasVariation returns a boolean if a field has been set. +func (o *VariationOrRolloutRep) HasVariation() bool { + if o != nil && o.Variation != nil { + return true + } + + return false +} + +// SetVariation gets a reference to the given int32 and assigns it to the Variation field. +func (o *VariationOrRolloutRep) SetVariation(v int32) { + o.Variation = &v +} + +// GetRollout returns the Rollout field value if set, zero value otherwise. +func (o *VariationOrRolloutRep) GetRollout() Rollout { + if o == nil || o.Rollout == nil { + var ret Rollout + return ret + } + return *o.Rollout +} + +// GetRolloutOk returns a tuple with the Rollout field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationOrRolloutRep) GetRolloutOk() (*Rollout, bool) { + if o == nil || o.Rollout == nil { + return nil, false + } + return o.Rollout, true +} + +// HasRollout returns a boolean if a field has been set. +func (o *VariationOrRolloutRep) HasRollout() bool { + if o != nil && o.Rollout != nil { + return true + } + + return false +} + +// SetRollout gets a reference to the given Rollout and assigns it to the Rollout field. +func (o *VariationOrRolloutRep) SetRollout(v Rollout) { + o.Rollout = &v +} + +func (o VariationOrRolloutRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Variation != nil { + toSerialize["variation"] = o.Variation + } + if o.Rollout != nil { + toSerialize["rollout"] = o.Rollout + } + return json.Marshal(toSerialize) +} + +type NullableVariationOrRolloutRep struct { + value *VariationOrRolloutRep + isSet bool +} + +func (v NullableVariationOrRolloutRep) Get() *VariationOrRolloutRep { + return v.value +} + +func (v *NullableVariationOrRolloutRep) Set(val *VariationOrRolloutRep) { + v.value = val + v.isSet = true +} + +func (v NullableVariationOrRolloutRep) IsSet() bool { + return v.isSet +} + +func (v *NullableVariationOrRolloutRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableVariationOrRolloutRep(val *VariationOrRolloutRep) *NullableVariationOrRolloutRep { + return &NullableVariationOrRolloutRep{value: val, isSet: true} +} + +func (v NullableVariationOrRolloutRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableVariationOrRolloutRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_summary.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_summary.go new file mode 100644 index 00000000..5ade6b4c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_variation_summary.go @@ -0,0 +1,340 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// VariationSummary struct for VariationSummary +type VariationSummary struct { + Rules int32 `json:"rules"` + NullRules int32 `json:"nullRules"` + Targets int32 `json:"targets"` + ContextTargets int32 `json:"contextTargets"` + IsFallthrough *bool `json:"isFallthrough,omitempty"` + IsOff *bool `json:"isOff,omitempty"` + Rollout *int32 `json:"rollout,omitempty"` + BucketBy *string `json:"bucketBy,omitempty"` +} + +// NewVariationSummary instantiates a new VariationSummary object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewVariationSummary(rules int32, nullRules int32, targets int32, contextTargets int32) *VariationSummary { + this := VariationSummary{} + this.Rules = rules + this.NullRules = nullRules + this.Targets = targets + this.ContextTargets = contextTargets + return &this +} + +// NewVariationSummaryWithDefaults instantiates a new VariationSummary object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewVariationSummaryWithDefaults() *VariationSummary { + this := VariationSummary{} + return &this +} + +// GetRules returns the Rules field value +func (o *VariationSummary) GetRules() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Rules +} + +// GetRulesOk returns a tuple with the Rules field value +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetRulesOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Rules, true +} + +// SetRules sets field value +func (o *VariationSummary) SetRules(v int32) { + o.Rules = v +} + +// GetNullRules returns the NullRules field value +func (o *VariationSummary) GetNullRules() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.NullRules +} + +// GetNullRulesOk returns a tuple with the NullRules field value +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetNullRulesOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.NullRules, true +} + +// SetNullRules sets field value +func (o *VariationSummary) SetNullRules(v int32) { + o.NullRules = v +} + +// GetTargets returns the Targets field value +func (o *VariationSummary) GetTargets() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Targets +} + +// GetTargetsOk returns a tuple with the Targets field value +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetTargetsOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Targets, true +} + +// SetTargets sets field value +func (o *VariationSummary) SetTargets(v int32) { + o.Targets = v +} + +// GetContextTargets returns the ContextTargets field value +func (o *VariationSummary) GetContextTargets() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.ContextTargets +} + +// GetContextTargetsOk returns a tuple with the ContextTargets field value +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetContextTargetsOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.ContextTargets, true +} + +// SetContextTargets sets field value +func (o *VariationSummary) SetContextTargets(v int32) { + o.ContextTargets = v +} + +// GetIsFallthrough returns the IsFallthrough field value if set, zero value otherwise. +func (o *VariationSummary) GetIsFallthrough() bool { + if o == nil || o.IsFallthrough == nil { + var ret bool + return ret + } + return *o.IsFallthrough +} + +// GetIsFallthroughOk returns a tuple with the IsFallthrough field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetIsFallthroughOk() (*bool, bool) { + if o == nil || o.IsFallthrough == nil { + return nil, false + } + return o.IsFallthrough, true +} + +// HasIsFallthrough returns a boolean if a field has been set. +func (o *VariationSummary) HasIsFallthrough() bool { + if o != nil && o.IsFallthrough != nil { + return true + } + + return false +} + +// SetIsFallthrough gets a reference to the given bool and assigns it to the IsFallthrough field. +func (o *VariationSummary) SetIsFallthrough(v bool) { + o.IsFallthrough = &v +} + +// GetIsOff returns the IsOff field value if set, zero value otherwise. +func (o *VariationSummary) GetIsOff() bool { + if o == nil || o.IsOff == nil { + var ret bool + return ret + } + return *o.IsOff +} + +// GetIsOffOk returns a tuple with the IsOff field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetIsOffOk() (*bool, bool) { + if o == nil || o.IsOff == nil { + return nil, false + } + return o.IsOff, true +} + +// HasIsOff returns a boolean if a field has been set. +func (o *VariationSummary) HasIsOff() bool { + if o != nil && o.IsOff != nil { + return true + } + + return false +} + +// SetIsOff gets a reference to the given bool and assigns it to the IsOff field. +func (o *VariationSummary) SetIsOff(v bool) { + o.IsOff = &v +} + +// GetRollout returns the Rollout field value if set, zero value otherwise. +func (o *VariationSummary) GetRollout() int32 { + if o == nil || o.Rollout == nil { + var ret int32 + return ret + } + return *o.Rollout +} + +// GetRolloutOk returns a tuple with the Rollout field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetRolloutOk() (*int32, bool) { + if o == nil || o.Rollout == nil { + return nil, false + } + return o.Rollout, true +} + +// HasRollout returns a boolean if a field has been set. +func (o *VariationSummary) HasRollout() bool { + if o != nil && o.Rollout != nil { + return true + } + + return false +} + +// SetRollout gets a reference to the given int32 and assigns it to the Rollout field. +func (o *VariationSummary) SetRollout(v int32) { + o.Rollout = &v +} + +// GetBucketBy returns the BucketBy field value if set, zero value otherwise. +func (o *VariationSummary) GetBucketBy() string { + if o == nil || o.BucketBy == nil { + var ret string + return ret + } + return *o.BucketBy +} + +// GetBucketByOk returns a tuple with the BucketBy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VariationSummary) GetBucketByOk() (*string, bool) { + if o == nil || o.BucketBy == nil { + return nil, false + } + return o.BucketBy, true +} + +// HasBucketBy returns a boolean if a field has been set. +func (o *VariationSummary) HasBucketBy() bool { + if o != nil && o.BucketBy != nil { + return true + } + + return false +} + +// SetBucketBy gets a reference to the given string and assigns it to the BucketBy field. +func (o *VariationSummary) SetBucketBy(v string) { + o.BucketBy = &v +} + +func (o VariationSummary) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["rules"] = o.Rules + } + if true { + toSerialize["nullRules"] = o.NullRules + } + if true { + toSerialize["targets"] = o.Targets + } + if true { + toSerialize["contextTargets"] = o.ContextTargets + } + if o.IsFallthrough != nil { + toSerialize["isFallthrough"] = o.IsFallthrough + } + if o.IsOff != nil { + toSerialize["isOff"] = o.IsOff + } + if o.Rollout != nil { + toSerialize["rollout"] = o.Rollout + } + if o.BucketBy != nil { + toSerialize["bucketBy"] = o.BucketBy + } + return json.Marshal(toSerialize) +} + +type NullableVariationSummary struct { + value *VariationSummary + isSet bool +} + +func (v NullableVariationSummary) Get() *VariationSummary { + return v.value +} + +func (v *NullableVariationSummary) Set(val *VariationSummary) { + v.value = val + v.isSet = true +} + +func (v NullableVariationSummary) IsSet() bool { + return v.isSet +} + +func (v *NullableVariationSummary) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableVariationSummary(val *VariationSummary) *NullableVariationSummary { + return &NullableVariationSummary{value: val, isSet: true} +} + +func (v NullableVariationSummary) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableVariationSummary) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_versions_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_versions_rep.go new file mode 100644 index 00000000..2b9953f5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_versions_rep.go @@ -0,0 +1,205 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// VersionsRep struct for VersionsRep +type VersionsRep struct { + // A list of all valid API versions. To learn more about our versioning, read [Versioning](https://launchdarkly.com/docs/api#versioning). + ValidVersions []int32 `json:"validVersions"` + LatestVersion int32 `json:"latestVersion"` + CurrentVersion int32 `json:"currentVersion"` + // Whether the version of the API currently is use is a beta version. This is always true if you add the LD-API-Version: beta header to your request. + Beta *bool `json:"beta,omitempty"` +} + +// NewVersionsRep instantiates a new VersionsRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewVersionsRep(validVersions []int32, latestVersion int32, currentVersion int32) *VersionsRep { + this := VersionsRep{} + this.ValidVersions = validVersions + this.LatestVersion = latestVersion + this.CurrentVersion = currentVersion + return &this +} + +// NewVersionsRepWithDefaults instantiates a new VersionsRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewVersionsRepWithDefaults() *VersionsRep { + this := VersionsRep{} + return &this +} + +// GetValidVersions returns the ValidVersions field value +func (o *VersionsRep) GetValidVersions() []int32 { + if o == nil { + var ret []int32 + return ret + } + + return o.ValidVersions +} + +// GetValidVersionsOk returns a tuple with the ValidVersions field value +// and a boolean to check if the value has been set. +func (o *VersionsRep) GetValidVersionsOk() ([]int32, bool) { + if o == nil { + return nil, false + } + return o.ValidVersions, true +} + +// SetValidVersions sets field value +func (o *VersionsRep) SetValidVersions(v []int32) { + o.ValidVersions = v +} + +// GetLatestVersion returns the LatestVersion field value +func (o *VersionsRep) GetLatestVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.LatestVersion +} + +// GetLatestVersionOk returns a tuple with the LatestVersion field value +// and a boolean to check if the value has been set. +func (o *VersionsRep) GetLatestVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.LatestVersion, true +} + +// SetLatestVersion sets field value +func (o *VersionsRep) SetLatestVersion(v int32) { + o.LatestVersion = v +} + +// GetCurrentVersion returns the CurrentVersion field value +func (o *VersionsRep) GetCurrentVersion() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.CurrentVersion +} + +// GetCurrentVersionOk returns a tuple with the CurrentVersion field value +// and a boolean to check if the value has been set. +func (o *VersionsRep) GetCurrentVersionOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.CurrentVersion, true +} + +// SetCurrentVersion sets field value +func (o *VersionsRep) SetCurrentVersion(v int32) { + o.CurrentVersion = v +} + +// GetBeta returns the Beta field value if set, zero value otherwise. +func (o *VersionsRep) GetBeta() bool { + if o == nil || o.Beta == nil { + var ret bool + return ret + } + return *o.Beta +} + +// GetBetaOk returns a tuple with the Beta field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *VersionsRep) GetBetaOk() (*bool, bool) { + if o == nil || o.Beta == nil { + return nil, false + } + return o.Beta, true +} + +// HasBeta returns a boolean if a field has been set. +func (o *VersionsRep) HasBeta() bool { + if o != nil && o.Beta != nil { + return true + } + + return false +} + +// SetBeta gets a reference to the given bool and assigns it to the Beta field. +func (o *VersionsRep) SetBeta(v bool) { + o.Beta = &v +} + +func (o VersionsRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["validVersions"] = o.ValidVersions + } + if true { + toSerialize["latestVersion"] = o.LatestVersion + } + if true { + toSerialize["currentVersion"] = o.CurrentVersion + } + if o.Beta != nil { + toSerialize["beta"] = o.Beta + } + return json.Marshal(toSerialize) +} + +type NullableVersionsRep struct { + value *VersionsRep + isSet bool +} + +func (v NullableVersionsRep) Get() *VersionsRep { + return v.value +} + +func (v *NullableVersionsRep) Set(val *VersionsRep) { + v.value = val + v.isSet = true +} + +func (v NullableVersionsRep) IsSet() bool { + return v.isSet +} + +func (v *NullableVersionsRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableVersionsRep(val *VersionsRep) *NullableVersionsRep { + return &NullableVersionsRep{value: val, isSet: true} +} + +func (v NullableVersionsRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableVersionsRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook.go new file mode 100644 index 00000000..8dfcf6e5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook.go @@ -0,0 +1,377 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Webhook struct for Webhook +type Webhook struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // The ID of this webhook + Id string `json:"_id"` + // A human-readable name for this webhook + Name *string `json:"name,omitempty"` + // The URL to which LaunchDarkly sends an HTTP POST payload for this webhook + Url string `json:"url"` + // The secret for this webhook + Secret *string `json:"secret,omitempty"` + // Represents a Custom role policy, defining a resource kinds filter the webhook responds to. + Statements []Statement `json:"statements,omitempty"` + // Whether or not this webhook is enabled + On bool `json:"on"` + // List of tags for this webhook + Tags []string `json:"tags"` + Access *Access `json:"_access,omitempty"` +} + +// NewWebhook instantiates a new Webhook object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWebhook(links map[string]Link, id string, url string, on bool, tags []string) *Webhook { + this := Webhook{} + this.Links = links + this.Id = id + this.Url = url + this.On = on + this.Tags = tags + return &this +} + +// NewWebhookWithDefaults instantiates a new Webhook object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWebhookWithDefaults() *Webhook { + this := Webhook{} + return &this +} + +// GetLinks returns the Links field value +func (o *Webhook) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Webhook) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Webhook) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetId returns the Id field value +func (o *Webhook) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *Webhook) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *Webhook) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *Webhook) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Webhook) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *Webhook) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *Webhook) SetName(v string) { + o.Name = &v +} + +// GetUrl returns the Url field value +func (o *Webhook) GetUrl() string { + if o == nil { + var ret string + return ret + } + + return o.Url +} + +// GetUrlOk returns a tuple with the Url field value +// and a boolean to check if the value has been set. +func (o *Webhook) GetUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Url, true +} + +// SetUrl sets field value +func (o *Webhook) SetUrl(v string) { + o.Url = v +} + +// GetSecret returns the Secret field value if set, zero value otherwise. +func (o *Webhook) GetSecret() string { + if o == nil || o.Secret == nil { + var ret string + return ret + } + return *o.Secret +} + +// GetSecretOk returns a tuple with the Secret field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Webhook) GetSecretOk() (*string, bool) { + if o == nil || o.Secret == nil { + return nil, false + } + return o.Secret, true +} + +// HasSecret returns a boolean if a field has been set. +func (o *Webhook) HasSecret() bool { + if o != nil && o.Secret != nil { + return true + } + + return false +} + +// SetSecret gets a reference to the given string and assigns it to the Secret field. +func (o *Webhook) SetSecret(v string) { + o.Secret = &v +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *Webhook) GetStatements() []Statement { + if o == nil || o.Statements == nil { + var ret []Statement + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Webhook) GetStatementsOk() ([]Statement, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *Webhook) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []Statement and assigns it to the Statements field. +func (o *Webhook) SetStatements(v []Statement) { + o.Statements = v +} + +// GetOn returns the On field value +func (o *Webhook) GetOn() bool { + if o == nil { + var ret bool + return ret + } + + return o.On +} + +// GetOnOk returns a tuple with the On field value +// and a boolean to check if the value has been set. +func (o *Webhook) GetOnOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.On, true +} + +// SetOn sets field value +func (o *Webhook) SetOn(v bool) { + o.On = v +} + +// GetTags returns the Tags field value +func (o *Webhook) GetTags() []string { + if o == nil { + var ret []string + return ret + } + + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value +// and a boolean to check if the value has been set. +func (o *Webhook) GetTagsOk() ([]string, bool) { + if o == nil { + return nil, false + } + return o.Tags, true +} + +// SetTags sets field value +func (o *Webhook) SetTags(v []string) { + o.Tags = v +} + +// GetAccess returns the Access field value if set, zero value otherwise. +func (o *Webhook) GetAccess() Access { + if o == nil || o.Access == nil { + var ret Access + return ret + } + return *o.Access +} + +// GetAccessOk returns a tuple with the Access field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Webhook) GetAccessOk() (*Access, bool) { + if o == nil || o.Access == nil { + return nil, false + } + return o.Access, true +} + +// HasAccess returns a boolean if a field has been set. +func (o *Webhook) HasAccess() bool { + if o != nil && o.Access != nil { + return true + } + + return false +} + +// SetAccess gets a reference to the given Access and assigns it to the Access field. +func (o *Webhook) SetAccess(v Access) { + o.Access = &v +} + +func (o Webhook) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["_id"] = o.Id + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["url"] = o.Url + } + if o.Secret != nil { + toSerialize["secret"] = o.Secret + } + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + if true { + toSerialize["on"] = o.On + } + if true { + toSerialize["tags"] = o.Tags + } + if o.Access != nil { + toSerialize["_access"] = o.Access + } + return json.Marshal(toSerialize) +} + +type NullableWebhook struct { + value *Webhook + isSet bool +} + +func (v NullableWebhook) Get() *Webhook { + return v.value +} + +func (v *NullableWebhook) Set(val *Webhook) { + v.value = val + v.isSet = true +} + +func (v NullableWebhook) IsSet() bool { + return v.isSet +} + +func (v *NullableWebhook) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWebhook(val *Webhook) *NullableWebhook { + return &NullableWebhook{value: val, isSet: true} +} + +func (v NullableWebhook) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWebhook) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook_post.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook_post.go new file mode 100644 index 00000000..3c0ff183 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhook_post.go @@ -0,0 +1,317 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WebhookPost struct for WebhookPost +type WebhookPost struct { + // A human-readable name for your webhook + Name *string `json:"name,omitempty"` + // The URL of the remote webhook + Url string `json:"url"` + // If sign is true, and the secret attribute is omitted, LaunchDarkly automatically generates a secret for you. + Secret *string `json:"secret,omitempty"` + Statements []StatementPost `json:"statements,omitempty"` + // If sign is false, the webhook does not include a signature header, and the secret can be omitted. + Sign bool `json:"sign"` + // Whether or not this webhook is enabled. + On bool `json:"on"` + // List of tags for this webhook + Tags []string `json:"tags,omitempty"` +} + +// NewWebhookPost instantiates a new WebhookPost object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWebhookPost(url string, sign bool, on bool) *WebhookPost { + this := WebhookPost{} + this.Url = url + this.Sign = sign + this.On = on + return &this +} + +// NewWebhookPostWithDefaults instantiates a new WebhookPost object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWebhookPostWithDefaults() *WebhookPost { + this := WebhookPost{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *WebhookPost) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *WebhookPost) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *WebhookPost) SetName(v string) { + o.Name = &v +} + +// GetUrl returns the Url field value +func (o *WebhookPost) GetUrl() string { + if o == nil { + var ret string + return ret + } + + return o.Url +} + +// GetUrlOk returns a tuple with the Url field value +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Url, true +} + +// SetUrl sets field value +func (o *WebhookPost) SetUrl(v string) { + o.Url = v +} + +// GetSecret returns the Secret field value if set, zero value otherwise. +func (o *WebhookPost) GetSecret() string { + if o == nil || o.Secret == nil { + var ret string + return ret + } + return *o.Secret +} + +// GetSecretOk returns a tuple with the Secret field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetSecretOk() (*string, bool) { + if o == nil || o.Secret == nil { + return nil, false + } + return o.Secret, true +} + +// HasSecret returns a boolean if a field has been set. +func (o *WebhookPost) HasSecret() bool { + if o != nil && o.Secret != nil { + return true + } + + return false +} + +// SetSecret gets a reference to the given string and assigns it to the Secret field. +func (o *WebhookPost) SetSecret(v string) { + o.Secret = &v +} + +// GetStatements returns the Statements field value if set, zero value otherwise. +func (o *WebhookPost) GetStatements() []StatementPost { + if o == nil || o.Statements == nil { + var ret []StatementPost + return ret + } + return o.Statements +} + +// GetStatementsOk returns a tuple with the Statements field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetStatementsOk() ([]StatementPost, bool) { + if o == nil || o.Statements == nil { + return nil, false + } + return o.Statements, true +} + +// HasStatements returns a boolean if a field has been set. +func (o *WebhookPost) HasStatements() bool { + if o != nil && o.Statements != nil { + return true + } + + return false +} + +// SetStatements gets a reference to the given []StatementPost and assigns it to the Statements field. +func (o *WebhookPost) SetStatements(v []StatementPost) { + o.Statements = v +} + +// GetSign returns the Sign field value +func (o *WebhookPost) GetSign() bool { + if o == nil { + var ret bool + return ret + } + + return o.Sign +} + +// GetSignOk returns a tuple with the Sign field value +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetSignOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.Sign, true +} + +// SetSign sets field value +func (o *WebhookPost) SetSign(v bool) { + o.Sign = v +} + +// GetOn returns the On field value +func (o *WebhookPost) GetOn() bool { + if o == nil { + var ret bool + return ret + } + + return o.On +} + +// GetOnOk returns a tuple with the On field value +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetOnOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.On, true +} + +// SetOn sets field value +func (o *WebhookPost) SetOn(v bool) { + o.On = v +} + +// GetTags returns the Tags field value if set, zero value otherwise. +func (o *WebhookPost) GetTags() []string { + if o == nil || o.Tags == nil { + var ret []string + return ret + } + return o.Tags +} + +// GetTagsOk returns a tuple with the Tags field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WebhookPost) GetTagsOk() ([]string, bool) { + if o == nil || o.Tags == nil { + return nil, false + } + return o.Tags, true +} + +// HasTags returns a boolean if a field has been set. +func (o *WebhookPost) HasTags() bool { + if o != nil && o.Tags != nil { + return true + } + + return false +} + +// SetTags gets a reference to the given []string and assigns it to the Tags field. +func (o *WebhookPost) SetTags(v []string) { + o.Tags = v +} + +func (o WebhookPost) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["url"] = o.Url + } + if o.Secret != nil { + toSerialize["secret"] = o.Secret + } + if o.Statements != nil { + toSerialize["statements"] = o.Statements + } + if true { + toSerialize["sign"] = o.Sign + } + if true { + toSerialize["on"] = o.On + } + if o.Tags != nil { + toSerialize["tags"] = o.Tags + } + return json.Marshal(toSerialize) +} + +type NullableWebhookPost struct { + value *WebhookPost + isSet bool +} + +func (v NullableWebhookPost) Get() *WebhookPost { + return v.value +} + +func (v *NullableWebhookPost) Set(val *WebhookPost) { + v.value = val + v.isSet = true +} + +func (v NullableWebhookPost) IsSet() bool { + return v.isSet +} + +func (v *NullableWebhookPost) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWebhookPost(val *WebhookPost) *NullableWebhookPost { + return &NullableWebhookPost{value: val, isSet: true} +} + +func (v NullableWebhookPost) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWebhookPost) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_webhooks.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhooks.go new file mode 100644 index 00000000..5ae9ab80 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_webhooks.go @@ -0,0 +1,140 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// Webhooks struct for Webhooks +type Webhooks struct { + // The location and content type of related resources + Links map[string]Link `json:"_links"` + // An array of webhooks + Items []Webhook `json:"items"` +} + +// NewWebhooks instantiates a new Webhooks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWebhooks(links map[string]Link, items []Webhook) *Webhooks { + this := Webhooks{} + this.Links = links + this.Items = items + return &this +} + +// NewWebhooksWithDefaults instantiates a new Webhooks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWebhooksWithDefaults() *Webhooks { + this := Webhooks{} + return &this +} + +// GetLinks returns the Links field value +func (o *Webhooks) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *Webhooks) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *Webhooks) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetItems returns the Items field value +func (o *Webhooks) GetItems() []Webhook { + if o == nil { + var ret []Webhook + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *Webhooks) GetItemsOk() ([]Webhook, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *Webhooks) SetItems(v []Webhook) { + o.Items = v +} + +func (o Webhooks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_links"] = o.Links + } + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableWebhooks struct { + value *Webhooks + isSet bool +} + +func (v NullableWebhooks) Get() *Webhooks { + return v.value +} + +func (v *NullableWebhooks) Set(val *Webhooks) { + v.value = val + v.isSet = true +} + +func (v NullableWebhooks) IsSet() bool { + return v.isSet +} + +func (v *NullableWebhooks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWebhooks(val *Webhooks) *NullableWebhooks { + return &NullableWebhooks{value: val, isSet: true} +} + +func (v NullableWebhooks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWebhooks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_weighted_variation.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_weighted_variation.go new file mode 100644 index 00000000..02959e9c --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_weighted_variation.go @@ -0,0 +1,174 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WeightedVariation struct for WeightedVariation +type WeightedVariation struct { + Variation int32 `json:"variation"` + Weight int32 `json:"weight"` + Untracked *bool `json:"_untracked,omitempty"` +} + +// NewWeightedVariation instantiates a new WeightedVariation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWeightedVariation(variation int32, weight int32) *WeightedVariation { + this := WeightedVariation{} + this.Variation = variation + this.Weight = weight + return &this +} + +// NewWeightedVariationWithDefaults instantiates a new WeightedVariation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWeightedVariationWithDefaults() *WeightedVariation { + this := WeightedVariation{} + return &this +} + +// GetVariation returns the Variation field value +func (o *WeightedVariation) GetVariation() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Variation +} + +// GetVariationOk returns a tuple with the Variation field value +// and a boolean to check if the value has been set. +func (o *WeightedVariation) GetVariationOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Variation, true +} + +// SetVariation sets field value +func (o *WeightedVariation) SetVariation(v int32) { + o.Variation = v +} + +// GetWeight returns the Weight field value +func (o *WeightedVariation) GetWeight() int32 { + if o == nil { + var ret int32 + return ret + } + + return o.Weight +} + +// GetWeightOk returns a tuple with the Weight field value +// and a boolean to check if the value has been set. +func (o *WeightedVariation) GetWeightOk() (*int32, bool) { + if o == nil { + return nil, false + } + return &o.Weight, true +} + +// SetWeight sets field value +func (o *WeightedVariation) SetWeight(v int32) { + o.Weight = v +} + +// GetUntracked returns the Untracked field value if set, zero value otherwise. +func (o *WeightedVariation) GetUntracked() bool { + if o == nil || o.Untracked == nil { + var ret bool + return ret + } + return *o.Untracked +} + +// GetUntrackedOk returns a tuple with the Untracked field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WeightedVariation) GetUntrackedOk() (*bool, bool) { + if o == nil || o.Untracked == nil { + return nil, false + } + return o.Untracked, true +} + +// HasUntracked returns a boolean if a field has been set. +func (o *WeightedVariation) HasUntracked() bool { + if o != nil && o.Untracked != nil { + return true + } + + return false +} + +// SetUntracked gets a reference to the given bool and assigns it to the Untracked field. +func (o *WeightedVariation) SetUntracked(v bool) { + o.Untracked = &v +} + +func (o WeightedVariation) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["variation"] = o.Variation + } + if true { + toSerialize["weight"] = o.Weight + } + if o.Untracked != nil { + toSerialize["_untracked"] = o.Untracked + } + return json.Marshal(toSerialize) +} + +type NullableWeightedVariation struct { + value *WeightedVariation + isSet bool +} + +func (v NullableWeightedVariation) Get() *WeightedVariation { + return v.value +} + +func (v *NullableWeightedVariation) Set(val *WeightedVariation) { + v.value = val + v.isSet = true +} + +func (v NullableWeightedVariation) IsSet() bool { + return v.isSet +} + +func (v *NullableWeightedVariation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWeightedVariation(val *WeightedVariation) *NullableWeightedVariation { + return &NullableWeightedVariation{value: val, isSet: true} +} + +func (v NullableWeightedVariation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWeightedVariation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_metadata.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_metadata.go new file mode 100644 index 00000000..0ccea931 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_metadata.go @@ -0,0 +1,116 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WorkflowTemplateMetadata struct for WorkflowTemplateMetadata +type WorkflowTemplateMetadata struct { + Parameters []WorkflowTemplateParameter `json:"parameters,omitempty"` +} + +// NewWorkflowTemplateMetadata instantiates a new WorkflowTemplateMetadata object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWorkflowTemplateMetadata() *WorkflowTemplateMetadata { + this := WorkflowTemplateMetadata{} + return &this +} + +// NewWorkflowTemplateMetadataWithDefaults instantiates a new WorkflowTemplateMetadata object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWorkflowTemplateMetadataWithDefaults() *WorkflowTemplateMetadata { + this := WorkflowTemplateMetadata{} + return &this +} + +// GetParameters returns the Parameters field value if set, zero value otherwise. +func (o *WorkflowTemplateMetadata) GetParameters() []WorkflowTemplateParameter { + if o == nil || o.Parameters == nil { + var ret []WorkflowTemplateParameter + return ret + } + return o.Parameters +} + +// GetParametersOk returns a tuple with the Parameters field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateMetadata) GetParametersOk() ([]WorkflowTemplateParameter, bool) { + if o == nil || o.Parameters == nil { + return nil, false + } + return o.Parameters, true +} + +// HasParameters returns a boolean if a field has been set. +func (o *WorkflowTemplateMetadata) HasParameters() bool { + if o != nil && o.Parameters != nil { + return true + } + + return false +} + +// SetParameters gets a reference to the given []WorkflowTemplateParameter and assigns it to the Parameters field. +func (o *WorkflowTemplateMetadata) SetParameters(v []WorkflowTemplateParameter) { + o.Parameters = v +} + +func (o WorkflowTemplateMetadata) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Parameters != nil { + toSerialize["parameters"] = o.Parameters + } + return json.Marshal(toSerialize) +} + +type NullableWorkflowTemplateMetadata struct { + value *WorkflowTemplateMetadata + isSet bool +} + +func (v NullableWorkflowTemplateMetadata) Get() *WorkflowTemplateMetadata { + return v.value +} + +func (v *NullableWorkflowTemplateMetadata) Set(val *WorkflowTemplateMetadata) { + v.value = val + v.isSet = true +} + +func (v NullableWorkflowTemplateMetadata) IsSet() bool { + return v.isSet +} + +func (v *NullableWorkflowTemplateMetadata) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWorkflowTemplateMetadata(val *WorkflowTemplateMetadata) *NullableWorkflowTemplateMetadata { + return &NullableWorkflowTemplateMetadata{value: val, isSet: true} +} + +func (v NullableWorkflowTemplateMetadata) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWorkflowTemplateMetadata) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_output.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_output.go new file mode 100644 index 00000000..150f581a --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_output.go @@ -0,0 +1,362 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WorkflowTemplateOutput struct for WorkflowTemplateOutput +type WorkflowTemplateOutput struct { + Id string `json:"_id"` + Key string `json:"_key"` + Name *string `json:"name,omitempty"` + CreationDate int64 `json:"_creationDate"` + OwnerId string `json:"_ownerId"` + MaintainerId string `json:"_maintainerId"` + Links map[string]Link `json:"_links"` + Description *string `json:"description,omitempty"` + Stages []StageOutput `json:"stages,omitempty"` +} + +// NewWorkflowTemplateOutput instantiates a new WorkflowTemplateOutput object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWorkflowTemplateOutput(id string, key string, creationDate int64, ownerId string, maintainerId string, links map[string]Link) *WorkflowTemplateOutput { + this := WorkflowTemplateOutput{} + this.Id = id + this.Key = key + this.CreationDate = creationDate + this.OwnerId = ownerId + this.MaintainerId = maintainerId + this.Links = links + return &this +} + +// NewWorkflowTemplateOutputWithDefaults instantiates a new WorkflowTemplateOutput object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWorkflowTemplateOutputWithDefaults() *WorkflowTemplateOutput { + this := WorkflowTemplateOutput{} + return &this +} + +// GetId returns the Id field value +func (o *WorkflowTemplateOutput) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *WorkflowTemplateOutput) SetId(v string) { + o.Id = v +} + +// GetKey returns the Key field value +func (o *WorkflowTemplateOutput) GetKey() string { + if o == nil { + var ret string + return ret + } + + return o.Key +} + +// GetKeyOk returns a tuple with the Key field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetKeyOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Key, true +} + +// SetKey sets field value +func (o *WorkflowTemplateOutput) SetKey(v string) { + o.Key = v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *WorkflowTemplateOutput) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *WorkflowTemplateOutput) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *WorkflowTemplateOutput) SetName(v string) { + o.Name = &v +} + +// GetCreationDate returns the CreationDate field value +func (o *WorkflowTemplateOutput) GetCreationDate() int64 { + if o == nil { + var ret int64 + return ret + } + + return o.CreationDate +} + +// GetCreationDateOk returns a tuple with the CreationDate field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetCreationDateOk() (*int64, bool) { + if o == nil { + return nil, false + } + return &o.CreationDate, true +} + +// SetCreationDate sets field value +func (o *WorkflowTemplateOutput) SetCreationDate(v int64) { + o.CreationDate = v +} + +// GetOwnerId returns the OwnerId field value +func (o *WorkflowTemplateOutput) GetOwnerId() string { + if o == nil { + var ret string + return ret + } + + return o.OwnerId +} + +// GetOwnerIdOk returns a tuple with the OwnerId field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetOwnerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.OwnerId, true +} + +// SetOwnerId sets field value +func (o *WorkflowTemplateOutput) SetOwnerId(v string) { + o.OwnerId = v +} + +// GetMaintainerId returns the MaintainerId field value +func (o *WorkflowTemplateOutput) GetMaintainerId() string { + if o == nil { + var ret string + return ret + } + + return o.MaintainerId +} + +// GetMaintainerIdOk returns a tuple with the MaintainerId field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetMaintainerIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.MaintainerId, true +} + +// SetMaintainerId sets field value +func (o *WorkflowTemplateOutput) SetMaintainerId(v string) { + o.MaintainerId = v +} + +// GetLinks returns the Links field value +func (o *WorkflowTemplateOutput) GetLinks() map[string]Link { + if o == nil { + var ret map[string]Link + return ret + } + + return o.Links +} + +// GetLinksOk returns a tuple with the Links field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetLinksOk() (*map[string]Link, bool) { + if o == nil { + return nil, false + } + return &o.Links, true +} + +// SetLinks sets field value +func (o *WorkflowTemplateOutput) SetLinks(v map[string]Link) { + o.Links = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *WorkflowTemplateOutput) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *WorkflowTemplateOutput) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *WorkflowTemplateOutput) SetDescription(v string) { + o.Description = &v +} + +// GetStages returns the Stages field value if set, zero value otherwise. +func (o *WorkflowTemplateOutput) GetStages() []StageOutput { + if o == nil || o.Stages == nil { + var ret []StageOutput + return ret + } + return o.Stages +} + +// GetStagesOk returns a tuple with the Stages field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateOutput) GetStagesOk() ([]StageOutput, bool) { + if o == nil || o.Stages == nil { + return nil, false + } + return o.Stages, true +} + +// HasStages returns a boolean if a field has been set. +func (o *WorkflowTemplateOutput) HasStages() bool { + if o != nil && o.Stages != nil { + return true + } + + return false +} + +// SetStages gets a reference to the given []StageOutput and assigns it to the Stages field. +func (o *WorkflowTemplateOutput) SetStages(v []StageOutput) { + o.Stages = v +} + +func (o WorkflowTemplateOutput) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["_id"] = o.Id + } + if true { + toSerialize["_key"] = o.Key + } + if o.Name != nil { + toSerialize["name"] = o.Name + } + if true { + toSerialize["_creationDate"] = o.CreationDate + } + if true { + toSerialize["_ownerId"] = o.OwnerId + } + if true { + toSerialize["_maintainerId"] = o.MaintainerId + } + if true { + toSerialize["_links"] = o.Links + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Stages != nil { + toSerialize["stages"] = o.Stages + } + return json.Marshal(toSerialize) +} + +type NullableWorkflowTemplateOutput struct { + value *WorkflowTemplateOutput + isSet bool +} + +func (v NullableWorkflowTemplateOutput) Get() *WorkflowTemplateOutput { + return v.value +} + +func (v *NullableWorkflowTemplateOutput) Set(val *WorkflowTemplateOutput) { + v.value = val + v.isSet = true +} + +func (v NullableWorkflowTemplateOutput) IsSet() bool { + return v.isSet +} + +func (v *NullableWorkflowTemplateOutput) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWorkflowTemplateOutput(val *WorkflowTemplateOutput) *NullableWorkflowTemplateOutput { + return &NullableWorkflowTemplateOutput{value: val, isSet: true} +} + +func (v NullableWorkflowTemplateOutput) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWorkflowTemplateOutput) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_parameter.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_parameter.go new file mode 100644 index 00000000..9e8b2325 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_template_parameter.go @@ -0,0 +1,226 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WorkflowTemplateParameter struct for WorkflowTemplateParameter +type WorkflowTemplateParameter struct { + Id *string `json:"_id,omitempty"` + // The path of the property to parameterize, relative to its parent condition or instruction + Path *string `json:"path,omitempty"` + Default *ParameterDefault `json:"default,omitempty"` + // Whether the default value is valid for the target flag and environment + Valid *bool `json:"valid,omitempty"` +} + +// NewWorkflowTemplateParameter instantiates a new WorkflowTemplateParameter object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWorkflowTemplateParameter() *WorkflowTemplateParameter { + this := WorkflowTemplateParameter{} + return &this +} + +// NewWorkflowTemplateParameterWithDefaults instantiates a new WorkflowTemplateParameter object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWorkflowTemplateParameterWithDefaults() *WorkflowTemplateParameter { + this := WorkflowTemplateParameter{} + return &this +} + +// GetId returns the Id field value if set, zero value otherwise. +func (o *WorkflowTemplateParameter) GetId() string { + if o == nil || o.Id == nil { + var ret string + return ret + } + return *o.Id +} + +// GetIdOk returns a tuple with the Id field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateParameter) GetIdOk() (*string, bool) { + if o == nil || o.Id == nil { + return nil, false + } + return o.Id, true +} + +// HasId returns a boolean if a field has been set. +func (o *WorkflowTemplateParameter) HasId() bool { + if o != nil && o.Id != nil { + return true + } + + return false +} + +// SetId gets a reference to the given string and assigns it to the Id field. +func (o *WorkflowTemplateParameter) SetId(v string) { + o.Id = &v +} + +// GetPath returns the Path field value if set, zero value otherwise. +func (o *WorkflowTemplateParameter) GetPath() string { + if o == nil || o.Path == nil { + var ret string + return ret + } + return *o.Path +} + +// GetPathOk returns a tuple with the Path field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateParameter) GetPathOk() (*string, bool) { + if o == nil || o.Path == nil { + return nil, false + } + return o.Path, true +} + +// HasPath returns a boolean if a field has been set. +func (o *WorkflowTemplateParameter) HasPath() bool { + if o != nil && o.Path != nil { + return true + } + + return false +} + +// SetPath gets a reference to the given string and assigns it to the Path field. +func (o *WorkflowTemplateParameter) SetPath(v string) { + o.Path = &v +} + +// GetDefault returns the Default field value if set, zero value otherwise. +func (o *WorkflowTemplateParameter) GetDefault() ParameterDefault { + if o == nil || o.Default == nil { + var ret ParameterDefault + return ret + } + return *o.Default +} + +// GetDefaultOk returns a tuple with the Default field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateParameter) GetDefaultOk() (*ParameterDefault, bool) { + if o == nil || o.Default == nil { + return nil, false + } + return o.Default, true +} + +// HasDefault returns a boolean if a field has been set. +func (o *WorkflowTemplateParameter) HasDefault() bool { + if o != nil && o.Default != nil { + return true + } + + return false +} + +// SetDefault gets a reference to the given ParameterDefault and assigns it to the Default field. +func (o *WorkflowTemplateParameter) SetDefault(v ParameterDefault) { + o.Default = &v +} + +// GetValid returns the Valid field value if set, zero value otherwise. +func (o *WorkflowTemplateParameter) GetValid() bool { + if o == nil || o.Valid == nil { + var ret bool + return ret + } + return *o.Valid +} + +// GetValidOk returns a tuple with the Valid field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *WorkflowTemplateParameter) GetValidOk() (*bool, bool) { + if o == nil || o.Valid == nil { + return nil, false + } + return o.Valid, true +} + +// HasValid returns a boolean if a field has been set. +func (o *WorkflowTemplateParameter) HasValid() bool { + if o != nil && o.Valid != nil { + return true + } + + return false +} + +// SetValid gets a reference to the given bool and assigns it to the Valid field. +func (o *WorkflowTemplateParameter) SetValid(v bool) { + o.Valid = &v +} + +func (o WorkflowTemplateParameter) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Id != nil { + toSerialize["_id"] = o.Id + } + if o.Path != nil { + toSerialize["path"] = o.Path + } + if o.Default != nil { + toSerialize["default"] = o.Default + } + if o.Valid != nil { + toSerialize["valid"] = o.Valid + } + return json.Marshal(toSerialize) +} + +type NullableWorkflowTemplateParameter struct { + value *WorkflowTemplateParameter + isSet bool +} + +func (v NullableWorkflowTemplateParameter) Get() *WorkflowTemplateParameter { + return v.value +} + +func (v *NullableWorkflowTemplateParameter) Set(val *WorkflowTemplateParameter) { + v.value = val + v.isSet = true +} + +func (v NullableWorkflowTemplateParameter) IsSet() bool { + return v.isSet +} + +func (v *NullableWorkflowTemplateParameter) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWorkflowTemplateParameter(val *WorkflowTemplateParameter) *NullableWorkflowTemplateParameter { + return &NullableWorkflowTemplateParameter{value: val, isSet: true} +} + +func (v NullableWorkflowTemplateParameter) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWorkflowTemplateParameter) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_templates_listing_output_rep.go b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_templates_listing_output_rep.go new file mode 100644 index 00000000..a740c046 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/model_workflow_templates_listing_output_rep.go @@ -0,0 +1,109 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" +) + +// WorkflowTemplatesListingOutputRep struct for WorkflowTemplatesListingOutputRep +type WorkflowTemplatesListingOutputRep struct { + Items []WorkflowTemplateOutput `json:"items"` +} + +// NewWorkflowTemplatesListingOutputRep instantiates a new WorkflowTemplatesListingOutputRep object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewWorkflowTemplatesListingOutputRep(items []WorkflowTemplateOutput) *WorkflowTemplatesListingOutputRep { + this := WorkflowTemplatesListingOutputRep{} + this.Items = items + return &this +} + +// NewWorkflowTemplatesListingOutputRepWithDefaults instantiates a new WorkflowTemplatesListingOutputRep object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewWorkflowTemplatesListingOutputRepWithDefaults() *WorkflowTemplatesListingOutputRep { + this := WorkflowTemplatesListingOutputRep{} + return &this +} + +// GetItems returns the Items field value +func (o *WorkflowTemplatesListingOutputRep) GetItems() []WorkflowTemplateOutput { + if o == nil { + var ret []WorkflowTemplateOutput + return ret + } + + return o.Items +} + +// GetItemsOk returns a tuple with the Items field value +// and a boolean to check if the value has been set. +func (o *WorkflowTemplatesListingOutputRep) GetItemsOk() ([]WorkflowTemplateOutput, bool) { + if o == nil { + return nil, false + } + return o.Items, true +} + +// SetItems sets field value +func (o *WorkflowTemplatesListingOutputRep) SetItems(v []WorkflowTemplateOutput) { + o.Items = v +} + +func (o WorkflowTemplatesListingOutputRep) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["items"] = o.Items + } + return json.Marshal(toSerialize) +} + +type NullableWorkflowTemplatesListingOutputRep struct { + value *WorkflowTemplatesListingOutputRep + isSet bool +} + +func (v NullableWorkflowTemplatesListingOutputRep) Get() *WorkflowTemplatesListingOutputRep { + return v.value +} + +func (v *NullableWorkflowTemplatesListingOutputRep) Set(val *WorkflowTemplatesListingOutputRep) { + v.value = val + v.isSet = true +} + +func (v NullableWorkflowTemplatesListingOutputRep) IsSet() bool { + return v.isSet +} + +func (v *NullableWorkflowTemplatesListingOutputRep) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableWorkflowTemplatesListingOutputRep(val *WorkflowTemplatesListingOutputRep) *NullableWorkflowTemplatesListingOutputRep { + return &NullableWorkflowTemplatesListingOutputRep{value: val, isSet: true} +} + +func (v NullableWorkflowTemplatesListingOutputRep) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableWorkflowTemplatesListingOutputRep) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/response.go b/vendor/github.com/launchdarkly/api-client-go/v17/response.go new file mode 100644 index 00000000..077647f5 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/response.go @@ -0,0 +1,48 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "net/http" +) + +// APIResponse stores the API response returned by the server. +type APIResponse struct { + *http.Response `json:"-"` + Message string `json:"message,omitempty"` + // Operation is the name of the OpenAPI operation. + Operation string `json:"operation,omitempty"` + // RequestURL is the request URL. This value is always available, even if the + // embedded *http.Response is nil. + RequestURL string `json:"url,omitempty"` + // Method is the HTTP method used for the request. This value is always + // available, even if the embedded *http.Response is nil. + Method string `json:"method,omitempty"` + // Payload holds the contents of the response body (which may be nil or empty). + // This is provided here as the raw response.Body() reader will have already + // been drained. + Payload []byte `json:"-"` +} + +// NewAPIResponse returns a new APIResponse object. +func NewAPIResponse(r *http.Response) *APIResponse { + + response := &APIResponse{Response: r} + return response +} + +// NewAPIResponseWithError returns a new APIResponse object with the provided error message. +func NewAPIResponseWithError(errorMessage string) *APIResponse { + + response := &APIResponse{Message: errorMessage} + return response +} diff --git a/vendor/github.com/launchdarkly/api-client-go/v17/utils.go b/vendor/github.com/launchdarkly/api-client-go/v17/utils.go new file mode 100644 index 00000000..59c4b898 --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/v17/utils.go @@ -0,0 +1,329 @@ +/* +LaunchDarkly REST API + +This documentation describes LaunchDarkly's REST API. To access the complete OpenAPI spec directly, use [Get OpenAPI spec](https://launchdarkly.com/docs/api/other/get-openapi-spec). ## Authentication LaunchDarkly's REST API uses the HTTPS protocol with a minimum TLS version of 1.2. All REST API resources are authenticated with either [personal or service access tokens](https://launchdarkly.com/docs/home/account/api), or session cookies. Other authentication mechanisms are not supported. You can manage personal access tokens on your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page in the LaunchDarkly UI. LaunchDarkly also has SDK keys, mobile keys, and client-side IDs that are used by our server-side SDKs, mobile SDKs, and JavaScript-based SDKs, respectively. **These keys cannot be used to access our REST API**. These keys are environment-specific, and can only perform read-only operations such as fetching feature flag settings. | Auth mechanism | Allowed resources | Use cases | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | [Personal or service access tokens](https://launchdarkly.com/docs/home/account/api) | Can be customized on a per-token basis | Building scripts, custom integrations, data export. | | SDK keys | Can only access read-only resources specific to server-side SDKs. Restricted to a single environment. | Server-side SDKs | | Mobile keys | Can only access read-only resources specific to mobile SDKs, and only for flags marked available to mobile keys. Restricted to a single environment. | Mobile SDKs | | Client-side ID | Can only access read-only resources specific to JavaScript-based client-side SDKs, and only for flags marked available to client-side. Restricted to a single environment. | Client-side JavaScript | > #### Keep your access tokens and SDK keys private > > Access tokens should _never_ be exposed in untrusted contexts. Never put an access token in client-side JavaScript, or embed it in a mobile application. LaunchDarkly has special mobile keys that you can embed in mobile apps. If you accidentally expose an access token or SDK key, you can reset it from your [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. > > The client-side ID is safe to embed in untrusted contexts. It's designed for use in client-side JavaScript. ### Authentication using request header The preferred way to authenticate with the API is by adding an `Authorization` header containing your access token to your requests. The value of the `Authorization` header must be your access token. Manage personal access tokens from the [**Authorization**](https://app.launchdarkly.com/settings/authorization) page. ### Authentication using session cookie For testing purposes, you can make API calls directly from your web browser. If you are logged in to the LaunchDarkly application, the API will use your existing session to authenticate calls. If you have a [role](https://launchdarkly.com/docs/home/account/built-in-roles) other than Admin, or have a [custom role](https://launchdarkly.com/docs/home/account/custom-roles) defined, you may not have permission to perform some API calls. You will receive a `401` response code in that case. > ### Modifying the Origin header causes an error > > LaunchDarkly validates that the Origin header for any API request authenticated by a session cookie matches the expected Origin header. The expected Origin header is `https://app.launchdarkly.com`. > > If the Origin header does not match what's expected, LaunchDarkly returns an error. This error can prevent the LaunchDarkly app from working correctly. > > Any browser extension that intentionally changes the Origin header can cause this problem. For example, the `Allow-Control-Allow-Origin: *` Chrome extension changes the Origin header to `http://evil.com` and causes the app to fail. > > To prevent this error, do not modify your Origin header. > > LaunchDarkly does not require origin matching when authenticating with an access token, so this issue does not affect normal API usage. ## Representations All resources expect and return JSON response bodies. Error responses also send a JSON body. To learn more about the error format of the API, read [Errors](https://launchdarkly.com/docs/api#errors). In practice this means that you always get a response with a `Content-Type` header set to `application/json`. In addition, request bodies for `PATCH`, `POST`, and `PUT` requests must be encoded as JSON with a `Content-Type` header set to `application/json`. ### Summary and detailed representations When you fetch a list of resources, the response includes only the most important attributes of each resource. This is a _summary representation_ of the resource. When you fetch an individual resource, such as a single feature flag, you receive a _detailed representation_ of the resource. The best way to find a detailed representation is to follow links. Every summary representation includes a link to its detailed representation. ### Expanding responses Sometimes the detailed representation of a resource does not include all of the attributes of the resource by default. If this is the case, the request method will clearly document this and describe which attributes you can include in an expanded response. To include the additional attributes, append the `expand` request parameter to your request and add a comma-separated list of the attributes to include. For example, when you append `?expand=members,maintainers` to the [Get team](https://launchdarkly.com/docs/api/teams/get-team) endpoint, the expanded response includes both of these attributes. ### Links and addressability The best way to navigate the API is by following links. These are attributes in representations that link to other resources. The API always uses the same format for links: - Links to other resources within the API are encapsulated in a `_links` object - If the resource has a corresponding link to HTML content on the site, it is stored in a special `_site` link Each link has two attributes: - An `href`, which contains the URL - A `type`, which describes the content type For example, a feature resource might return the following: ```json { \"_links\": { \"parent\": { \"href\": \"/api/features\", \"type\": \"application/json\" }, \"self\": { \"href\": \"/api/features/sort.order\", \"type\": \"application/json\" } }, \"_site\": { \"href\": \"/features/sort.order\", \"type\": \"text/html\" } } ``` From this, you can navigate to the parent collection of features by following the `parent` link, or navigate to the site page for the feature by following the `_site` link. Collections are always represented as a JSON object with an `items` attribute containing an array of representations. Like all other representations, collections have `_links` defined at the top level. Paginated collections include `first`, `last`, `next`, and `prev` links containing a URL with the respective set of elements in the collection. ## Updates Resources that accept partial updates use the `PATCH` verb. Most resources support the [JSON patch](https://launchdarkly.com/docs/api#updates-using-json-patch) format. Some resources also support the [JSON merge patch](https://launchdarkly.com/docs/api#updates-using-json-merge-patch) format, and some resources support the [semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch) format, which is a way to specify the modifications to perform as a set of executable instructions. Each resource supports optional [comments](https://launchdarkly.com/docs/api#updates-with-comments) that you can submit with updates. Comments appear in outgoing webhooks, the audit log, and other integrations. When a resource supports both JSON patch and semantic patch, we document both in the request method. However, the specific request body fields and descriptions included in our documentation only match one type of patch or the other. ### Updates using JSON patch [JSON patch](https://datatracker.ietf.org/doc/html/rfc6902) is a way to specify the modifications to perform on a resource. JSON patch uses paths and a limited set of operations to describe how to transform the current state of the resource into a new state. JSON patch documents are always arrays, where each element contains an operation, a path to the field to update, and the new value. For example, in this feature flag representation: ```json { \"name\": \"New recommendations engine\", \"key\": \"engine.enable\", \"description\": \"This is the description\", ... } ``` You can change the feature flag's description with the following patch document: ```json [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"This is the new description\" }] ``` You can specify multiple modifications to perform in a single request. You can also test that certain preconditions are met before applying the patch: ```json [ { \"op\": \"test\", \"path\": \"/version\", \"value\": 10 }, { \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" } ] ``` The above patch request tests whether the feature flag's `version` is `10`, and if so, changes the feature flag's description. Attributes that are not editable, such as a resource's `_links`, have names that start with an underscore. ### Updates using JSON merge patch [JSON merge patch](https://datatracker.ietf.org/doc/html/rfc7386) is another format for specifying the modifications to perform on a resource. JSON merge patch is less expressive than JSON patch. However, in many cases it is simpler to construct a merge patch document. For example, you can change a feature flag's description with the following merge patch document: ```json { \"description\": \"New flag description\" } ``` ### Updates using semantic patch Some resources support the semantic patch format. A semantic patch is a way to specify the modifications to perform on a resource as a set of executable instructions. Semantic patch allows you to be explicit about intent using precise, custom instructions. In many cases, you can define semantic patch instructions independently of the current state of the resource. This can be useful when defining a change that may be applied at a future date. To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. Here's how: ``` Content-Type: application/json; domain-model=launchdarkly.semanticpatch ``` If you call a semantic patch resource without this header, you will receive a `400` response because your semantic patch will be interpreted as a JSON patch. The body of a semantic patch request takes the following properties: * `comment` (string): (Optional) A description of the update. * `environmentKey` (string): (Required for some resources only) The environment key. * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the instruction requires parameters, you must include those parameters as additional fields in the object. The documentation for each resource that supports semantic patch includes the available instructions and any additional parameters. For example: ```json { \"comment\": \"optional comment\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` Semantic patches are not applied partially; either all of the instructions are applied or none of them are. If **any** instruction is invalid, the endpoint returns an error and will not change the resource. If all instructions are valid, the request succeeds and the resources are updated if necessary, or left unchanged if they are already in the state you request. ### Updates with comments You can submit optional comments with `PATCH` changes. To submit a comment along with a JSON patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"patch\": [{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"The new description\" }] } ``` To submit a comment along with a JSON merge patch document, use the following format: ```json { \"comment\": \"This is a comment string\", \"merge\": { \"description\": \"New flag description\" } } ``` To submit a comment along with a semantic patch, use the following format: ```json { \"comment\": \"This is a comment string\", \"instructions\": [ {\"kind\": \"turnFlagOn\"} ] } ``` ## Errors The API always returns errors in a common format. Here's an example: ```json { \"code\": \"invalid_request\", \"message\": \"A feature with that key already exists\", \"id\": \"30ce6058-87da-11e4-b116-123b93f75cba\" } ``` The `code` indicates the general class of error. The `message` is a human-readable explanation of what went wrong. The `id` is a unique identifier. Use it when you're working with LaunchDarkly Support to debug a problem with a specific API call. ### HTTP status error response codes | Code | Definition | Description | Possible Solution | | ---- | ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | 400 | Invalid request | The request cannot be understood. | Ensure JSON syntax in request body is correct. | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call. | Ensure your API access token is valid and has the appropriate permissions. | | 403 | Forbidden | Requestor does not have access to this resource. | Ensure that the account member or access token has proper permissions set. | | 404 | Invalid resource identifier | The requested resource is not valid. | Ensure that the resource is correctly identified by ID or key. | | 405 | Method not allowed | The request method is not allowed on this resource. | Ensure that the HTTP verb is correct. | | 409 | Conflict | The API request can not be completed because it conflicts with a concurrent API request. | Retry your request. | | 422 | Unprocessable entity | The API request can not be completed because the update description can not be understood. | Ensure that the request body is correct for the type of patch you are using, either JSON patch or semantic patch. | 429 | Too many requests | Read [Rate limiting](https://launchdarkly.com/docs/api#rate-limiting). | Wait and try again later. | ## CORS The LaunchDarkly API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. If an `Origin` header is given in a request, it will be echoed as an explicitly allowed origin. Otherwise the request returns a wildcard, `Access-Control-Allow-Origin: *`. For more information on CORS, read the [CORS W3C Recommendation](http://www.w3.org/TR/cors). Example CORS headers might look like: ```http Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, Authorization Access-Control-Allow-Methods: OPTIONS, GET, DELETE, PATCH Access-Control-Allow-Origin: * Access-Control-Max-Age: 300 ``` You can make authenticated CORS calls just as you would make same-origin calls, using either [token or session-based authentication](https://launchdarkly.com/docs/api#authentication). If you are using session authentication, you should set the `withCredentials` property for your `xhr` request to `true`. You should never expose your access tokens to untrusted entities. ## Rate limiting We use several rate limiting strategies to ensure the availability of our APIs. Rate-limited calls to our APIs return a `429` status code. Calls to our APIs include headers indicating the current rate limit status. The specific headers returned depend on the API route being called. The limits differ based on the route, authentication mechanism, and other factors. Routes that are not rate limited may not contain any of the headers described below. > ### Rate limiting and SDKs > > LaunchDarkly SDKs are never rate limited and do not use the API endpoints defined here. LaunchDarkly uses a different set of approaches, including streaming/server-sent events and a global CDN, to ensure availability to the routes used by LaunchDarkly SDKs. ### Global rate limits Authenticated requests are subject to a global limit. This is the maximum number of calls that your account can make to the API per ten seconds. All service and personal access tokens on the account share this limit, so exceeding the limit with one access token will impact other tokens. Calls that are subject to global rate limits may return the headers below: | Header name | Description | | ------------------------------ | -------------------------------------------------------------------------------- | | `X-Ratelimit-Global-Remaining` | The maximum number of requests the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | We do not publicly document the specific number of calls that can be made globally. This limit may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limit. ### Route-level rate limits Some authenticated routes have custom rate limits. These also reset every ten seconds. Any service or personal access tokens hitting the same route share this limit, so exceeding the limit with one access token may impact other tokens. Calls that are subject to route-level rate limits return the headers below: | Header name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------- | | `X-Ratelimit-Route-Remaining` | The maximum number of requests to the current route the account is permitted to make per ten seconds. | | `X-Ratelimit-Reset` | The time at which the current rate limit window resets in epoch milliseconds. | A _route_ represents a specific URL pattern and verb. For example, the [Delete environment](https://launchdarkly.com/docs/api/environments/delete-environment) endpoint is considered a single route, and each call to delete an environment counts against your route-level rate limit for that route. We do not publicly document the specific number of calls that an account can make to each endpoint per ten seconds. These limits may change, and we encourage clients to program against the specification, relying on the two headers defined above, rather than hardcoding to the current limits. ### IP-based rate limiting We also employ IP-based rate limiting on some API routes. If you hit an IP-based rate limit, your API response will include a `Retry-After` header indicating how long to wait before re-trying the call. Clients must wait at least `Retry-After` seconds before making additional calls to our API, and should employ jitter and backoff strategies to avoid triggering rate limits again. ## OpenAPI (Swagger) and client libraries We have a [complete OpenAPI (Swagger) specification](https://app.launchdarkly.com/api/v2/openapi.json) for our API. We auto-generate multiple client libraries based on our OpenAPI specification. To learn more, visit the [collection of client libraries on GitHub](https://github.com/search?q=topic%3Alaunchdarkly-api+org%3Alaunchdarkly&type=Repositories). You can also use this specification to generate client libraries to interact with our REST API in your language of choice. Our OpenAPI specification is supported by several API-based tools such as Postman and Insomnia. In many cases, you can directly import our specification to explore our APIs. ## Method overriding Some firewalls and HTTP clients restrict the use of verbs other than `GET` and `POST`. In those environments, our API endpoints that use `DELETE`, `PATCH`, and `PUT` verbs are inaccessible. To avoid this issue, our API supports the `X-HTTP-Method-Override` header, allowing clients to \"tunnel\" `DELETE`, `PATCH`, and `PUT` requests using a `POST` request. For example, to call a `PATCH` endpoint using a `POST` request, you can include `X-HTTP-Method-Override:PATCH` as a header. ## Beta resources We sometimes release new API resources in **beta** status before we release them with general availability. Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. We try to promote resources into general availability as quickly as possible. This happens after sufficient testing and when we're satisfied that we no longer need to make backwards-incompatible changes. We mark beta resources with a \"Beta\" callout in our documentation, pictured below: > ### This feature is in beta > > To use this feature, pass in a header including the `LD-API-Version` key with value set to `beta`. Use this header with each call. To learn more, read [Beta resources](https://launchdarkly.com/docs/api#beta-resources). > > Resources that are in beta are still undergoing testing and development. They may change without notice, including becoming backwards incompatible. ### Using beta resources To use a beta resource, you must include a header in the request. If you call a beta resource without this header, you receive a `403` response. Use this header: ``` LD-API-Version: beta ``` ## Federal environments The version of LaunchDarkly that is available on domains controlled by the United States government is different from the version of LaunchDarkly available to the general public. If you are an employee or contractor for a United States federal agency and use LaunchDarkly in your work, you likely use the federal instance of LaunchDarkly. If you are working in the federal instance of LaunchDarkly, the base URI for each request is `https://app.launchdarkly.us`. To learn more, read [LaunchDarkly in federal environments](https://launchdarkly.com/docs/home/infrastructure/federal). ## Versioning We try hard to keep our REST API backwards compatible, but we occasionally have to make backwards-incompatible changes in the process of shipping new features. These breaking changes can cause unexpected behavior if you don't prepare for them accordingly. Updates to our REST API include support for the latest features in LaunchDarkly. We also release a new version of our REST API every time we make a breaking change. We provide simultaneous support for multiple API versions so you can migrate from your current API version to a new version at your own pace. ### Setting the API version per request You can set the API version on a specific request by sending an `LD-API-Version` header, as shown in the example below: ``` LD-API-Version: 20240415 ``` The header value is the version number of the API version you would like to request. The number for each version corresponds to the date the version was released in `yyyymmdd` format. In the example above the version `20240415` corresponds to April 15, 2024. ### Setting the API version per access token When you create an access token, you must specify a specific version of the API to use. This ensures that integrations using this token cannot be broken by version changes. Tokens created before versioning was released have their version set to `20160426`, which is the version of the API that existed before the current versioning scheme, so that they continue working the same way they did before versioning. If you would like to upgrade your integration to use a new API version, you can explicitly set the header described above. > ### Best practice: Set the header for every client or integration > > We recommend that you set the API version header explicitly in any client or integration you build. > > Only rely on the access token API version during manual testing. ### API version changelog
Version Changes End of life (EOL)
`20240415`
  • Changed several endpoints from unpaginated to paginated. Use the `limit` and `offset` query parameters to page through the results.
  • Changed the [list access tokens](https://launchdarkly.com/docs/api/access-tokens/get-tokens) endpoint:
    • Response is now paginated with a default limit of `25`
  • Changed the [list account members](https://launchdarkly.com/docs/api/account-members/get-members) endpoint:
    • The `accessCheck` filter is no longer available
  • Changed the [list custom roles](https://launchdarkly.com/docs/api/custom-roles/get-custom-roles) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `environments` field is now only returned if the request is filtered by environment, using the `filterEnv` query parameter
    • The `followerId`, `hasDataExport`, `status`, `contextKindTargeted`, and `segmentTargeted` filters are no longer available
    • The `compare` query parameter is no longer available
  • Changed the [list segments](https://launchdarkly.com/docs/api/segments/get-segments) endpoint:
    • Response is now paginated with a default limit of `20`
  • Changed the [list teams](https://launchdarkly.com/docs/api/teams/get-teams) endpoint:
    • The `expand` parameter no longer supports including `projects` or `roles`
    • In paginated results, the maximum page size is now 100
  • Changed the [get workflows](https://launchdarkly.com/docs/api/workflows/get-workflows) endpoint:
    • Response is now paginated with a default limit of `20`
    • The `_conflicts` field in the response is no longer available
Current
`20220603`
  • Changed the [list projects](https://launchdarkly.com/docs/api/projects/get-projects) return value:
    • Response is now paginated with a default limit of `20`.
    • Added support for filter and sort.
    • The project `environments` field is now expandable. This field is omitted by default.
  • Changed the [get project](https://launchdarkly.com/docs/api/projects/get-project) return value:
    • The `environments` field is now expandable. This field is omitted by default.
2025-04-15
`20210729`
  • Changed the [create approval request](https://launchdarkly.com/docs/api/approvals/post-approval-request) return value. It now returns HTTP Status Code `201` instead of `200`.
  • Changed the [get user](https://launchdarkly.com/docs/api/users/get-user) return value. It now returns a user record, not a user.
  • Added additional optional fields to environment, segments, flags, members, and segments, including the ability to create big segments.
  • Added default values for flag variations when new environments are created.
  • Added filtering and pagination for getting flags and members, including `limit`, `number`, `filter`, and `sort` query parameters.
  • Added endpoints for expiring user targets for flags and segments, scheduled changes, access tokens, Relay Proxy configuration, integrations and subscriptions, and approvals.
2023-06-03
`20191212`
  • [List feature flags](https://launchdarkly.com/docs/api/feature-flags/get-feature-flags) now defaults to sending summaries of feature flag configurations, equivalent to setting the query parameter `summary=true`. Summaries omit flag targeting rules and individual user targets from the payload.
  • Added endpoints for flags, flag status, projects, environments, audit logs, members, users, custom roles, segments, usage, streams, events, and data export.
2022-07-29
`20160426`
  • Initial versioning of API. Tokens created before versioning have their version set to this.
2020-12-12
To learn more about how EOL is determined, read LaunchDarkly's [End of Life (EOL) Policy](https://launchdarkly.com/policies/end-of-life-policy/). + +API version: 2.0 +Contact: support@launchdarkly.com +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package ldapi + +import ( + "encoding/json" + "time" +) + +// PtrBool is a helper routine that returns a pointer to given boolean value. +func PtrBool(v bool) *bool { return &v } + +// PtrInt is a helper routine that returns a pointer to given integer value. +func PtrInt(v int) *int { return &v } + +// PtrInt32 is a helper routine that returns a pointer to given integer value. +func PtrInt32(v int32) *int32 { return &v } + +// PtrInt64 is a helper routine that returns a pointer to given integer value. +func PtrInt64(v int64) *int64 { return &v } + +// PtrFloat32 is a helper routine that returns a pointer to given float value. +func PtrFloat32(v float32) *float32 { return &v } + +// PtrFloat64 is a helper routine that returns a pointer to given float value. +func PtrFloat64(v float64) *float64 { return &v } + +// PtrString is a helper routine that returns a pointer to given string value. +func PtrString(v string) *string { return &v } + +// PtrTime is helper routine that returns a pointer to given Time value. +func PtrTime(v time.Time) *time.Time { return &v } + +type NullableBool struct { + value *bool + isSet bool +} + +func (v NullableBool) Get() *bool { + return v.value +} + +func (v *NullableBool) Set(val *bool) { + v.value = val + v.isSet = true +} + +func (v NullableBool) IsSet() bool { + return v.isSet +} + +func (v *NullableBool) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBool(val *bool) *NullableBool { + return &NullableBool{value: val, isSet: true} +} + +func (v NullableBool) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBool) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt struct { + value *int + isSet bool +} + +func (v NullableInt) Get() *int { + return v.value +} + +func (v *NullableInt) Set(val *int) { + v.value = val + v.isSet = true +} + +func (v NullableInt) IsSet() bool { + return v.isSet +} + +func (v *NullableInt) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt(val *int) *NullableInt { + return &NullableInt{value: val, isSet: true} +} + +func (v NullableInt) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt32 struct { + value *int32 + isSet bool +} + +func (v NullableInt32) Get() *int32 { + return v.value +} + +func (v *NullableInt32) Set(val *int32) { + v.value = val + v.isSet = true +} + +func (v NullableInt32) IsSet() bool { + return v.isSet +} + +func (v *NullableInt32) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt32(val *int32) *NullableInt32 { + return &NullableInt32{value: val, isSet: true} +} + +func (v NullableInt32) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt32) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableInt64 struct { + value *int64 + isSet bool +} + +func (v NullableInt64) Get() *int64 { + return v.value +} + +func (v *NullableInt64) Set(val *int64) { + v.value = val + v.isSet = true +} + +func (v NullableInt64) IsSet() bool { + return v.isSet +} + +func (v *NullableInt64) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInt64(val *int64) *NullableInt64 { + return &NullableInt64{value: val, isSet: true} +} + +func (v NullableInt64) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInt64) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableFloat32 struct { + value *float32 + isSet bool +} + +func (v NullableFloat32) Get() *float32 { + return v.value +} + +func (v *NullableFloat32) Set(val *float32) { + v.value = val + v.isSet = true +} + +func (v NullableFloat32) IsSet() bool { + return v.isSet +} + +func (v *NullableFloat32) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFloat32(val *float32) *NullableFloat32 { + return &NullableFloat32{value: val, isSet: true} +} + +func (v NullableFloat32) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFloat32) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableFloat64 struct { + value *float64 + isSet bool +} + +func (v NullableFloat64) Get() *float64 { + return v.value +} + +func (v *NullableFloat64) Set(val *float64) { + v.value = val + v.isSet = true +} + +func (v NullableFloat64) IsSet() bool { + return v.isSet +} + +func (v *NullableFloat64) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableFloat64(val *float64) *NullableFloat64 { + return &NullableFloat64{value: val, isSet: true} +} + +func (v NullableFloat64) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableFloat64) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableString struct { + value *string + isSet bool +} + +func (v NullableString) Get() *string { + return v.value +} + +func (v *NullableString) Set(val *string) { + v.value = val + v.isSet = true +} + +func (v NullableString) IsSet() bool { + return v.isSet +} + +func (v *NullableString) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableString(val *string) *NullableString { + return &NullableString{value: val, isSet: true} +} + +func (v NullableString) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableString) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + +type NullableTime struct { + value *time.Time + isSet bool +} + +func (v NullableTime) Get() *time.Time { + return v.value +} + +func (v *NullableTime) Set(val *time.Time) { + v.value = val + v.isSet = true +} + +func (v NullableTime) IsSet() bool { + return v.isSet +} + +func (v *NullableTime) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTime(val *time.Time) *NullableTime { + return &NullableTime{value: val, isSet: true} +} + +func (v NullableTime) MarshalJSON() ([]byte, error) { + return v.value.MarshalJSON() +} + +func (v *NullableTime) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go index 38317437..6cd3b3f9 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/aliases/alias.go @@ -7,13 +7,13 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strconv" "strings" "time" "github.com/bmatcuk/doublestar/v4" "github.com/iancoleman/strcase" + regexp "github.com/wasilibs/go-re2" "github.com/launchdarkly/ld-find-code-refs/v2/internal/helpers" "github.com/launchdarkly/ld-find-code-refs/v2/internal/log" @@ -21,6 +21,9 @@ import ( "github.com/launchdarkly/ld-find-code-refs/v2/options" ) +var globCache = make(map[string][]string) +var regexCache = make(map[string]*regexp.Regexp) + // GenerateAliases returns a map of flag keys to aliases based on config. func GenerateAliases(flags []string, aliases []options.Alias, dir string) (map[string][]string, error) { allFileContents, err := processFileContent(aliases, dir) @@ -88,10 +91,9 @@ func GenerateAliasesFromFilePattern(a options.Alias, flag, dir string, allFileCo // Concatenate the contents of all files into a single byte array to be matched by specified patterns fileContents := []byte{} for _, path := range a.Paths { - absGlob := filepath.Join(dir, path) - matches, err := doublestar.FilepathGlob(absGlob) + matches, err := cacheFilepathGlob(dir, path) if err != nil { - return nil, fmt.Errorf("filepattern '%s': could not process path glob '%s'", a.Name, absGlob) + return nil, fmt.Errorf("filepattern '%s': could not process path glob '%s'", a.Name, path) } for _, match := range matches { if pathFileContents := allFileContents[match]; len(pathFileContents) > 0 { @@ -101,7 +103,12 @@ func GenerateAliasesFromFilePattern(a options.Alias, flag, dir string, allFileCo } for _, p := range a.Patterns { - pattern := regexp.MustCompile(strings.ReplaceAll(p, "FLAG_KEY", flag)) + patternStr := strings.ReplaceAll(p, "FLAG_KEY", flag) + pattern, ok := regexCache[patternStr] + if !ok { + pattern = regexp.MustCompile(patternStr) + regexCache[patternStr] = pattern + } results := pattern.FindAllStringSubmatch(string(fileContents), -1) for _, res := range results { if len(res) > 1 { @@ -157,13 +164,12 @@ func processFileContent(aliases []options.Alias, dir string) (FileContentsMap, e paths := []string{} for _, glob := range a.Paths { - absGlob := filepath.Join(dir, glob) - matches, err := doublestar.FilepathGlob(absGlob) + matches, err := cacheFilepathGlob(dir, glob) if err != nil { - return nil, fmt.Errorf("filepattern '%s': could not process path glob '%s'", aliasId, absGlob) + return nil, fmt.Errorf("filepattern '%s': could not process path glob '%s'", aliasId, glob) } if matches == nil { - log.Info.Printf("filepattern '%s': no matching files found for alias path glob '%s'", aliasId, absGlob) + log.Info.Printf("filepattern '%s': no matching files found for alias path glob '%s'", aliasId, glob) } paths = append(paths, matches...) } @@ -188,3 +194,15 @@ func processFileContent(aliases []options.Alias, dir string) (FileContentsMap, e } return allFileContents, nil } + +func cacheFilepathGlob(dir, glob string) ([]string, error) { + absGlob := filepath.Join(dir, glob) + if cachedMatches, ok := globCache[absGlob]; ok { + return cachedMatches, nil + } + + matches, err := doublestar.FilepathGlob(absGlob) + globCache[absGlob] = matches + + return matches, err +} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/flags/flags.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/flags/flags.go index 82eeda38..c76a9552 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/flags/flags.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/flags/flags.go @@ -27,7 +27,7 @@ func GetFlagKeys(opts options.Options, repoParams ld.RepoParams) map[string][]st flagKeys := make(map[string][]string) for _, proj := range opts.Projects { - flags, err := getFlags(ldApi, proj.Key) + flags, err := getFlags(ldApi, proj.Key, opts.SkipArchivedFlags) if err != nil { helpers.FatalServiceError(fmt.Errorf("could not retrieve flag keys from LaunchDarkly for project `%s`: %w", proj.Key, err), ignoreServiceErrors) } @@ -63,8 +63,8 @@ func addFlagKeys(flagKeys map[string][]string, flags []string, projKey string) { flagKeys[projKey] = filteredFlags } -func getFlags(ldApi ld.ApiClient, projKey string) ([]string, error) { - flags, err := ldApi.GetFlagKeyList(projKey) +func getFlags(ldApi ld.ApiClient, projKey string, skipArchivedFlags bool) ([]string, error) { + flags, err := ldApi.GetFlagKeyList(projKey, skipArchivedFlags) if err != nil { return nil, err } diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go index 13a98de0..59942c27 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/ld/ld.go @@ -20,7 +20,7 @@ import ( h "github.com/hashicorp/go-retryablehttp" "github.com/olekukonko/tablewriter" - ldapi "github.com/launchdarkly/api-client-go/v15" + ldapi "github.com/launchdarkly/api-client-go/v17" jsonpatch "github.com/launchdarkly/json-patch" "github.com/launchdarkly/ld-find-code-refs/v2/internal/log" "github.com/launchdarkly/ld-find-code-refs/v2/internal/validation" @@ -40,10 +40,11 @@ type ApiOptions struct { } const ( - apiVersion = "20220603" + apiVersion = "20240415" apiVersionHeader = "LD-API-Version" v2ApiPath = "/api/v2" reposPath = "/code-refs/repositories" + shortShaLength = 7 // Descriptive constant for SHA length ) type ConfigurationError struct { @@ -76,8 +77,8 @@ func IsTransient(err error) bool { // Fallback to default backoff if header can't be parsed // https://apidocs.launchdarkly.com/#section/Overview/Rate-limiting // Method is curried in order to avoid stubbing the time package and fallback Backoff in unit tests -func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(time.Duration, time.Duration, int, *http.Response) time.Duration { - return func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { +func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(minDuration, _ time.Duration, attemptNum int, resp *http.Response) time.Duration { + return func(minDuration, max2 time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil { if resp.StatusCode == http.StatusTooManyRequests { if s, ok := resp.Header["X-Ratelimit-Reset"]; ok { @@ -95,7 +96,7 @@ func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(time } } - return fallbackBackoff(min, max, attemptNum, resp) + return fallbackBackoff(minDuration, max2, attemptNum, resp) } } @@ -108,7 +109,7 @@ func InitApiClient(options ApiOptions) ApiClient { if options.RetryMax != nil && *options.RetryMax >= 0 { client.RetryMax = *options.RetryMax } - client.Backoff = RateLimitBackoff(time.Now, h.LinearJitterBackoff) + client.Backoff = RateLimitBackoff(time.Now, h.LinearJitterBackoff) //nolint:bodyclose return ApiClient{ httpClient: client, @@ -121,7 +122,11 @@ func (c ApiClient) getPath(path string) string { return fmt.Sprintf("%s%s%s", c.Options.BaseUri, v2ApiPath, path) } -func (c ApiClient) GetFlagKeyList(projKey string) ([]string, error) { +func (c ApiClient) getPathFromLink(path string) string { + return fmt.Sprintf("%s%s", c.Options.BaseUri, path) +} + +func (c ApiClient) GetFlagKeyList(projKey string, skipArchivedFlags bool) ([]string, error) { env, err := c.getProjectEnvironment(projKey) if err != nil { return nil, err @@ -136,6 +141,15 @@ func (c ApiClient) GetFlagKeyList(projKey string) ([]string, error) { return nil, err } + // If we only want live flags, return them now + if skipArchivedFlags { + flagKeys := make([]string, 0, len(activeFlags)) + for _, flag := range activeFlags { + flagKeys = append(flagKeys, flag.Key) + } + return flagKeys, nil + } + params.Add("filter", "state:archived") archivedFlags, err := c.getFlags(projKey, params) if err != nil { @@ -192,32 +206,53 @@ func (c ApiClient) getProjectEnvironment(projKey string) (*ldapi.Environment, er } func (c ApiClient) getFlags(projKey string, params url.Values) ([]ldapi.FeatureFlag, error) { - url := c.getPath(fmt.Sprintf("/flags/%s", projKey)) - req, err := h.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, err + // If no limit is set, use the maximum allowed + if params.Get("limit") == "" { + params.Set("limit", "100") } - req.URL.RawQuery = params.Encode() - res, err := c.do(req) - if err != nil { - return nil, err - } + var allFlags []ldapi.FeatureFlag + nextUrl := c.getPath(fmt.Sprintf("/flags/%s", projKey)) //nolint:perfsprint + for nextUrl != "" { + req, err := h.NewRequest(http.MethodGet, nextUrl, nil) + if err != nil { + return nil, err + } - resBytes, err := io.ReadAll(res.Body) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } + if nextUrl == c.getPath(fmt.Sprintf("/flags/%s", projKey)) { //nolint:perfsprint + req.URL.RawQuery = params.Encode() + } - var flags ldapi.FeatureFlags - if err := json.Unmarshal(resBytes, &flags); err != nil { - return nil, err + log.Info.Printf("Requesting flags from %s", nextUrl) + res, err := c.do(req) + if err != nil { + return nil, err + } + + resBytes, err := io.ReadAll(res.Body) + if res != nil { + defer res.Body.Close() + } + if err != nil { + return nil, err + } + var flagsPage ldapi.FeatureFlags + if err := json.Unmarshal(resBytes, &flagsPage); err != nil { + return nil, err + } + + allFlags = append(allFlags, flagsPage.Items...) + if flagsPage.TotalCount != nil && len(allFlags) >= int(*flagsPage.TotalCount) { + break + } + + nextLink, ok := flagsPage.Links["next"] + if ok { + nextUrl = c.getPathFromLink(*nextLink.Href) + } } - return flags.Items, nil + return allFlags, nil } func (c ApiClient) patchCodeReferenceRepository(currentRepo, repo RepoParams) error { @@ -441,7 +476,7 @@ type ldErrorResponse struct { func (c ApiClient) do(req *h.Request) (*http.Response, error) { req.Header.Set("Authorization", c.Options.ApiKey) - req.Header.Set(apiVersionHeader, apiVersion) + req.Header.Set(apiVersionHeader, apiVersion) //nolint:canonicalheader req.Header.Set("User-Agent", c.Options.UserAgent) req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Length", strconv.FormatInt(req.ContentLength, 10)) @@ -550,8 +585,8 @@ func (b BranchRep) TotalHunkCount() int { func (b BranchRep) WriteToCSV(outDir, projKey, repo, sha string) (path string, err error) { // Try to create a filename with a shortened sha, but if the sha is too short for some unexpected reason, use the branch name instead var tag string - if len(sha) >= 7 { - tag = sha[:7] + if len(sha) >= shortShaLength { + tag = sha[:shortShaLength] } else { tag = b.Name } @@ -577,7 +612,7 @@ func (b BranchRep) WriteToCSV(outDir, projKey, repo, sha string) (path string, e // sort csv by flag key sort.Slice(records, func(i, j int) bool { // sort by flagKey -> path -> startingLineNumber - for k := 0; k < 3; k++ { + for k := range [3]int{} { if records[i][k] != records[j][k] { return records[i][k] < records[j][k] } @@ -697,8 +732,7 @@ func (b BranchRep) PrintReferenceCountTable() { truncatedData = append(truncatedData, []string{"Other flags", strconv.FormatInt(additionalRefCount, 10)}) table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Flag", "# References"}) - table.SetBorder(false) - table.AppendBulk(truncatedData) + table.Header([]string{"Flag", "# References"}) + table.Bulk(truncatedData) table.Render() } diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/version/version.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/version/version.go index 59ce345f..89c58ec7 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/version/version.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/internal/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.13.0" +const Version = "2.14.0" diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/flags.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/flags.go index c3d1a1be..cd48a85b 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/flags.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/flags.go @@ -45,7 +45,7 @@ Allowed template variables: 'branchName', 'sha'. If "commitUrlTemplate" is not p { name: "contextLines", short: "C", - defaultValue: 2, + defaultValue: 2, //nolint:mnd usage: `The number of context lines to send to LaunchDarkly. If < 0, no source code will be sent to LaunchDarkly. If 0, only the lines containing flag references will be sent. If > 0, will send that number of context @@ -94,7 +94,7 @@ LaunchDarkly API is unreachable or returns an unexpected response.`, { name: "lookback", short: "l", - defaultValue: 10, + defaultValue: 10, //nolint:mnd usage: `Sets the number of git commits to search in history for whether a feature flag was removed from code. May be set to 0 to disabled this feature. Setting this option to a high value will increase search time.`, }, @@ -142,6 +142,11 @@ LaunchDarkly UI. Acceptable values: bitbucket|custom|github|gitlab.`, defaultValue: "", usage: `Use this option to scan non-git codebases. The current revision of the repository to be scanned. If set, the version string for the scanned repository will not be inferred, and branch garbage collection will be disabled. The "branch" option is required when "revision" is set.`, }, + { + name: "skipArchivedFlags", + defaultValue: false, + usage: `If enabled, archived feature flags will not be fetched from the LaunchDarkly API as input to the tool.`, + }, { name: "subdirectory", defaultValue: "", diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/options.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/options.go index cad15126..0a9a266e 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/options.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/options/options.go @@ -67,6 +67,7 @@ type Options struct { DryRun bool `mapstructure:"dryRun"` IgnoreServiceErrors bool `mapstructure:"ignoreServiceErrors"` Prune bool `mapstructure:"prune"` + SkipArchivedFlags bool `mapstructure:"skipArchivedFlags"` // The following options can only be configured via YAML configuration @@ -195,7 +196,7 @@ func (o Options) ValidateRequired() error { } if len(o.ProjKey) > 0 && len(o.Projects) > 0 { - return fmt.Errorf("`--projKey` cannot be combined with `projects` in configuration") + return errors.New("`--projKey` cannot be combined with `projects` in configuration") } if len(o.ProjKey) > maxProjKeyLength { @@ -263,7 +264,7 @@ func (o Options) Validate() error { } if o.Revision != "" && o.Branch == "" { - return fmt.Errorf(`"branch" option is required when "revision" option is set`) + return errors.New(`"branch" option is required when "revision" option is set`) } if len(o.Projects) > 0 { diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/files.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/files.go index c5c19714..9d415107 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/files.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/files.go @@ -64,7 +64,7 @@ func readFileLines(path string) ([]string, error) { return lines, nil } -func readFiles(ctx context.Context, files chan<- file, workspace string) error { +func readFiles(ctx context.Context, files chan<- file, workspace, subdirectory string) error { defer close(files) ignoreFiles := []string{".gitignore", ".ignore", ".ldignore"} allIgnores := newIgnore(workspace, ignoreFiles) @@ -108,9 +108,20 @@ func readFiles(ctx context.Context, files chan<- file, workspace string) error { return nil } - files <- file{path: strings.TrimPrefix(path, workspace+"/"), lines: lines} + resolvedPath := resolvePath(path, workspace, subdirectory) + + files <- file{path: resolvedPath, lines: lines} return nil } return filepath.Walk(workspace, readFile) } + +func resolvePath(path, workspace, subdirectory string) string { + dir := workspace + if subdirectory != "" { + dir = strings.TrimSuffix(workspace, "/"+subdirectory) + } + + return strings.TrimPrefix(path, dir+"/") +} diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go index 765fb13a..76b0a9f0 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/matcher.go @@ -83,7 +83,7 @@ func buildElementPatterns(flags []string, delimiters string) map[string][]string for _, left := range delimiters { for _, right := range delimiters { var sb strings.Builder - sb.Grow(len(flag) + 2) + sb.Grow(len(flag) + 2) //nolint:mnd sb.WriteRune(left) sb.WriteString(flag) sb.WriteRune(right) diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go index 165e7886..ea349f8f 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/scan.go @@ -19,7 +19,7 @@ func Scan(opts options.Options, repoParams ld.RepoParams, dir string) (Matcher, searchDir = filepath.Join(dir, opts.Subdirectory) } - refs, err := SearchForRefs(searchDir, matcher) + refs, err := SearchForRefs(searchDir, opts.Subdirectory, matcher) if err != nil { log.Error.Fatalf("error searching for flag key references: %s", err) } diff --git a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/search.go b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/search.go index c63ec279..a8d33023 100644 --- a/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/search.go +++ b/vendor/github.com/launchdarkly/ld-find-code-refs/v2/search/search.go @@ -104,6 +104,7 @@ func (f file) aggregateHunksForFlag(projKey, flagKey string, matcher Matcher, li func (f file) toHunks(matcher Matcher) *ld.ReferenceHunksRep { hunks := make([]ld.HunkRep, 0) filteredMatchers := make([]ElementMatcher, 0) + for _, elementSearch := range matcher.Elements { if elementSearch.Dir != "" { matchDir := strings.HasPrefix(f.path, elementSearch.Dir) @@ -192,7 +193,7 @@ func processFiles(ctx context.Context, files <-chan file, references chan<- ld.R w.Wait() } -func SearchForRefs(directory string, matcher Matcher) ([]ld.ReferenceHunksRep, error) { +func SearchForRefs(directory, subdirectory string, matcher Matcher) ([]ld.ReferenceHunksRep, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() files := make(chan file) @@ -200,7 +201,7 @@ func SearchForRefs(directory string, matcher Matcher) ([]ld.ReferenceHunksRep, e // Start workers to process files asynchronously as they are written to the files channel go processFiles(ctx, files, references, matcher) - err := readFiles(ctx, files, directory) + err := readFiles(ctx, files, directory, subdirectory) if err != nil { return nil, err } diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE new file mode 100644 index 00000000..91b5cef3 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md new file mode 100644 index 00000000..ca048371 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -0,0 +1,48 @@ +# go-colorable + +[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest) +[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) +[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) +[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) + +Colorable writer for windows. + +For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) +This package is possible to handle escape sequence for ansi color on windows. + +## Too Bad! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) + + +## So Good! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) + +## Usage + +```go +logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) +logrus.SetOutput(colorable.NewColorableStdout()) + +logrus.Info("succeeded") +logrus.Warn("not correct") +logrus.Error("something error") +logrus.Fatal("panic") +``` + +You can compile above code on non-windows OSs. + +## Installation + +``` +$ go get github.com/mattn/go-colorable +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go new file mode 100644 index 00000000..416d1bbb --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -0,0 +1,38 @@ +//go:build appengine +// +build appengine + +package colorable + +import ( + "io" + "os" + + _ "github.com/mattn/go-isatty" +) + +// NewColorable returns new instance of Writer which handles escape sequence. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return os.Stdout +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return os.Stderr +} + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go new file mode 100644 index 00000000..766d9460 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -0,0 +1,38 @@ +//go:build !windows && !appengine +// +build !windows,!appengine + +package colorable + +import ( + "io" + "os" + + _ "github.com/mattn/go-isatty" +) + +// NewColorable returns new instance of Writer which handles escape sequence. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return os.Stdout +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return os.Stderr +} + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go new file mode 100644 index 00000000..1846ad5a --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -0,0 +1,1047 @@ +//go:build windows && !appengine +// +build windows,!appengine + +package colorable + +import ( + "bytes" + "io" + "math" + "os" + "strconv" + "strings" + "sync" + "syscall" + "unsafe" + + "github.com/mattn/go-isatty" +) + +const ( + foregroundBlue = 0x1 + foregroundGreen = 0x2 + foregroundRed = 0x4 + foregroundIntensity = 0x8 + foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity) + backgroundBlue = 0x10 + backgroundGreen = 0x20 + backgroundRed = 0x40 + backgroundIntensity = 0x80 + backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) + commonLvbUnderscore = 0x8000 + + cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 +) + +const ( + genericRead = 0x80000000 + genericWrite = 0x40000000 +) + +const ( + consoleTextmodeBuffer = 0x1 +) + +type wchar uint16 +type short int16 +type dword uint32 +type word uint16 + +type coord struct { + x short + y short +} + +type smallRect struct { + left short + top short + right short + bottom short +} + +type consoleScreenBufferInfo struct { + size coord + cursorPosition coord + attributes word + window smallRect + maximumWindowSize coord +} + +type consoleCursorInfo struct { + size dword + visible int32 +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") + procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") + procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") + procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") + procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") + procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") + procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") + procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer") +) + +// Writer provides colorable Writer to the console +type Writer struct { + out io.Writer + handle syscall.Handle + althandle syscall.Handle + oldattr word + oldpos coord + rest bytes.Buffer + mutex sync.Mutex +} + +// NewColorable returns new instance of Writer which handles escape sequence from File. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + if isatty.IsTerminal(file.Fd()) { + var mode uint32 + if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { + return file + } + var csbi consoleScreenBufferInfo + handle := syscall.Handle(file.Fd()) + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}} + } + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return NewColorable(os.Stdout) +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return NewColorable(os.Stderr) +} + +var color256 = map[int]int{ + 0: 0x000000, + 1: 0x800000, + 2: 0x008000, + 3: 0x808000, + 4: 0x000080, + 5: 0x800080, + 6: 0x008080, + 7: 0xc0c0c0, + 8: 0x808080, + 9: 0xff0000, + 10: 0x00ff00, + 11: 0xffff00, + 12: 0x0000ff, + 13: 0xff00ff, + 14: 0x00ffff, + 15: 0xffffff, + 16: 0x000000, + 17: 0x00005f, + 18: 0x000087, + 19: 0x0000af, + 20: 0x0000d7, + 21: 0x0000ff, + 22: 0x005f00, + 23: 0x005f5f, + 24: 0x005f87, + 25: 0x005faf, + 26: 0x005fd7, + 27: 0x005fff, + 28: 0x008700, + 29: 0x00875f, + 30: 0x008787, + 31: 0x0087af, + 32: 0x0087d7, + 33: 0x0087ff, + 34: 0x00af00, + 35: 0x00af5f, + 36: 0x00af87, + 37: 0x00afaf, + 38: 0x00afd7, + 39: 0x00afff, + 40: 0x00d700, + 41: 0x00d75f, + 42: 0x00d787, + 43: 0x00d7af, + 44: 0x00d7d7, + 45: 0x00d7ff, + 46: 0x00ff00, + 47: 0x00ff5f, + 48: 0x00ff87, + 49: 0x00ffaf, + 50: 0x00ffd7, + 51: 0x00ffff, + 52: 0x5f0000, + 53: 0x5f005f, + 54: 0x5f0087, + 55: 0x5f00af, + 56: 0x5f00d7, + 57: 0x5f00ff, + 58: 0x5f5f00, + 59: 0x5f5f5f, + 60: 0x5f5f87, + 61: 0x5f5faf, + 62: 0x5f5fd7, + 63: 0x5f5fff, + 64: 0x5f8700, + 65: 0x5f875f, + 66: 0x5f8787, + 67: 0x5f87af, + 68: 0x5f87d7, + 69: 0x5f87ff, + 70: 0x5faf00, + 71: 0x5faf5f, + 72: 0x5faf87, + 73: 0x5fafaf, + 74: 0x5fafd7, + 75: 0x5fafff, + 76: 0x5fd700, + 77: 0x5fd75f, + 78: 0x5fd787, + 79: 0x5fd7af, + 80: 0x5fd7d7, + 81: 0x5fd7ff, + 82: 0x5fff00, + 83: 0x5fff5f, + 84: 0x5fff87, + 85: 0x5fffaf, + 86: 0x5fffd7, + 87: 0x5fffff, + 88: 0x870000, + 89: 0x87005f, + 90: 0x870087, + 91: 0x8700af, + 92: 0x8700d7, + 93: 0x8700ff, + 94: 0x875f00, + 95: 0x875f5f, + 96: 0x875f87, + 97: 0x875faf, + 98: 0x875fd7, + 99: 0x875fff, + 100: 0x878700, + 101: 0x87875f, + 102: 0x878787, + 103: 0x8787af, + 104: 0x8787d7, + 105: 0x8787ff, + 106: 0x87af00, + 107: 0x87af5f, + 108: 0x87af87, + 109: 0x87afaf, + 110: 0x87afd7, + 111: 0x87afff, + 112: 0x87d700, + 113: 0x87d75f, + 114: 0x87d787, + 115: 0x87d7af, + 116: 0x87d7d7, + 117: 0x87d7ff, + 118: 0x87ff00, + 119: 0x87ff5f, + 120: 0x87ff87, + 121: 0x87ffaf, + 122: 0x87ffd7, + 123: 0x87ffff, + 124: 0xaf0000, + 125: 0xaf005f, + 126: 0xaf0087, + 127: 0xaf00af, + 128: 0xaf00d7, + 129: 0xaf00ff, + 130: 0xaf5f00, + 131: 0xaf5f5f, + 132: 0xaf5f87, + 133: 0xaf5faf, + 134: 0xaf5fd7, + 135: 0xaf5fff, + 136: 0xaf8700, + 137: 0xaf875f, + 138: 0xaf8787, + 139: 0xaf87af, + 140: 0xaf87d7, + 141: 0xaf87ff, + 142: 0xafaf00, + 143: 0xafaf5f, + 144: 0xafaf87, + 145: 0xafafaf, + 146: 0xafafd7, + 147: 0xafafff, + 148: 0xafd700, + 149: 0xafd75f, + 150: 0xafd787, + 151: 0xafd7af, + 152: 0xafd7d7, + 153: 0xafd7ff, + 154: 0xafff00, + 155: 0xafff5f, + 156: 0xafff87, + 157: 0xafffaf, + 158: 0xafffd7, + 159: 0xafffff, + 160: 0xd70000, + 161: 0xd7005f, + 162: 0xd70087, + 163: 0xd700af, + 164: 0xd700d7, + 165: 0xd700ff, + 166: 0xd75f00, + 167: 0xd75f5f, + 168: 0xd75f87, + 169: 0xd75faf, + 170: 0xd75fd7, + 171: 0xd75fff, + 172: 0xd78700, + 173: 0xd7875f, + 174: 0xd78787, + 175: 0xd787af, + 176: 0xd787d7, + 177: 0xd787ff, + 178: 0xd7af00, + 179: 0xd7af5f, + 180: 0xd7af87, + 181: 0xd7afaf, + 182: 0xd7afd7, + 183: 0xd7afff, + 184: 0xd7d700, + 185: 0xd7d75f, + 186: 0xd7d787, + 187: 0xd7d7af, + 188: 0xd7d7d7, + 189: 0xd7d7ff, + 190: 0xd7ff00, + 191: 0xd7ff5f, + 192: 0xd7ff87, + 193: 0xd7ffaf, + 194: 0xd7ffd7, + 195: 0xd7ffff, + 196: 0xff0000, + 197: 0xff005f, + 198: 0xff0087, + 199: 0xff00af, + 200: 0xff00d7, + 201: 0xff00ff, + 202: 0xff5f00, + 203: 0xff5f5f, + 204: 0xff5f87, + 205: 0xff5faf, + 206: 0xff5fd7, + 207: 0xff5fff, + 208: 0xff8700, + 209: 0xff875f, + 210: 0xff8787, + 211: 0xff87af, + 212: 0xff87d7, + 213: 0xff87ff, + 214: 0xffaf00, + 215: 0xffaf5f, + 216: 0xffaf87, + 217: 0xffafaf, + 218: 0xffafd7, + 219: 0xffafff, + 220: 0xffd700, + 221: 0xffd75f, + 222: 0xffd787, + 223: 0xffd7af, + 224: 0xffd7d7, + 225: 0xffd7ff, + 226: 0xffff00, + 227: 0xffff5f, + 228: 0xffff87, + 229: 0xffffaf, + 230: 0xffffd7, + 231: 0xffffff, + 232: 0x080808, + 233: 0x121212, + 234: 0x1c1c1c, + 235: 0x262626, + 236: 0x303030, + 237: 0x3a3a3a, + 238: 0x444444, + 239: 0x4e4e4e, + 240: 0x585858, + 241: 0x626262, + 242: 0x6c6c6c, + 243: 0x767676, + 244: 0x808080, + 245: 0x8a8a8a, + 246: 0x949494, + 247: 0x9e9e9e, + 248: 0xa8a8a8, + 249: 0xb2b2b2, + 250: 0xbcbcbc, + 251: 0xc6c6c6, + 252: 0xd0d0d0, + 253: 0xdadada, + 254: 0xe4e4e4, + 255: 0xeeeeee, +} + +// `\033]0;TITLESTR\007` +func doTitleSequence(er *bytes.Reader) error { + var c byte + var err error + + c, err = er.ReadByte() + if err != nil { + return err + } + if c != '0' && c != '2' { + return nil + } + c, err = er.ReadByte() + if err != nil { + return err + } + if c != ';' { + return nil + } + title := make([]byte, 0, 80) + for { + c, err = er.ReadByte() + if err != nil { + return err + } + if c == 0x07 || c == '\n' { + break + } + title = append(title, c) + } + if len(title) > 0 { + title8, err := syscall.UTF16PtrFromString(string(title)) + if err == nil { + procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8))) + } + } + return nil +} + +// returns Atoi(s) unless s == "" in which case it returns def +func atoiWithDefault(s string, def int) (int, error) { + if s == "" { + return def, nil + } + return strconv.Atoi(s) +} + +// Write writes data on console +func (w *Writer) Write(data []byte) (n int, err error) { + w.mutex.Lock() + defer w.mutex.Unlock() + var csbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + + handle := w.handle + + var er *bytes.Reader + if w.rest.Len() > 0 { + var rest bytes.Buffer + w.rest.WriteTo(&rest) + w.rest.Reset() + rest.Write(data) + er = bytes.NewReader(rest.Bytes()) + } else { + er = bytes.NewReader(data) + } + var plaintext bytes.Buffer +loop: + for { + c1, err := er.ReadByte() + if err != nil { + plaintext.WriteTo(w.out) + break loop + } + if c1 != 0x1b { + plaintext.WriteByte(c1) + continue + } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } + c2, err := er.ReadByte() + if err != nil { + break loop + } + + switch c2 { + case '>': + continue + case ']': + w.rest.WriteByte(c1) + w.rest.WriteByte(c2) + er.WriteTo(&w.rest) + if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 { + break loop + } + er = bytes.NewReader(w.rest.Bytes()[2:]) + err := doTitleSequence(er) + if err != nil { + break loop + } + w.rest.Reset() + continue + // https://github.com/mattn/go-colorable/issues/27 + case '7': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + w.oldpos = csbi.cursorPosition + continue + case '8': + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + continue + case 0x5b: + // execute part after switch + default: + continue + } + + w.rest.WriteByte(c1) + w.rest.WriteByte(c2) + er.WriteTo(&w.rest) + + var buf bytes.Buffer + var m byte + for i, c := range w.rest.Bytes()[2:] { + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { + m = c + er = bytes.NewReader(w.rest.Bytes()[2+i+1:]) + w.rest.Reset() + break + } + buf.Write([]byte(string(c))) + } + if m == 0 { + break loop + } + + switch m { + case 'A': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'B': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'C': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'D': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x -= short(n) + if csbi.cursorPosition.x < 0 { + csbi.cursorPosition.x = 0 + } + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'E': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'F': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'G': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + if n < 1 { + n = 1 + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = short(n - 1) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'H', 'f': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + if buf.Len() > 0 { + token := strings.Split(buf.String(), ";") + switch len(token) { + case 1: + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + csbi.cursorPosition.y = short(n1 - 1) + case 2: + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + n2, err := strconv.Atoi(token[1]) + if err != nil { + continue + } + csbi.cursorPosition.x = short(n2 - 1) + csbi.cursorPosition.y = short(n1 - 1) + } + } else { + csbi.cursorPosition.y = 0 + } + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'J': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + var count, written dword + var cursor coord + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) + case 1: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x) + case 2: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) + } + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'K': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + var cursor coord + var count, written dword + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + count = dword(csbi.size.x - csbi.cursorPosition.x) + case 1: + cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} + count = dword(csbi.size.x - csbi.cursorPosition.x) + case 2: + cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} + count = dword(csbi.size.x) + } + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'X': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + var cursor coord + var written dword + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'm': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + attr := csbi.attributes + cs := buf.String() + if cs == "" { + procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr)) + continue + } + token := strings.Split(cs, ";") + for i := 0; i < len(token); i++ { + ns := token[i] + if n, err = strconv.Atoi(ns); err == nil { + switch { + case n == 0 || n == 100: + attr = w.oldattr + case n == 4: + attr |= commonLvbUnderscore + case (1 <= n && n <= 3) || n == 5: + attr |= foregroundIntensity + case n == 7 || n == 27: + attr = + (attr &^ (foregroundMask | backgroundMask)) | + ((attr & foregroundMask) << 4) | + ((attr & backgroundMask) >> 4) + case n == 22: + attr &^= foregroundIntensity + case n == 24: + attr &^= commonLvbUnderscore + case 30 <= n && n <= 37: + attr &= backgroundMask + if (n-30)&1 != 0 { + attr |= foregroundRed + } + if (n-30)&2 != 0 { + attr |= foregroundGreen + } + if (n-30)&4 != 0 { + attr |= foregroundBlue + } + case n == 38: // set foreground color. + if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256foreAttr == nil { + n256setup() + } + attr &= backgroundMask + attr |= n256foreAttr[n256%len(n256foreAttr)] + i += 2 + } + } else if len(token) == 5 && token[i+1] == "2" { + var r, g, b int + r, _ = strconv.Atoi(token[i+2]) + g, _ = strconv.Atoi(token[i+3]) + b, _ = strconv.Atoi(token[i+4]) + i += 4 + if r > 127 { + attr |= foregroundRed + } + if g > 127 { + attr |= foregroundGreen + } + if b > 127 { + attr |= foregroundBlue + } + } else { + attr = attr & (w.oldattr & backgroundMask) + } + case n == 39: // reset foreground color. + attr &= backgroundMask + attr |= w.oldattr & foregroundMask + case 40 <= n && n <= 47: + attr &= foregroundMask + if (n-40)&1 != 0 { + attr |= backgroundRed + } + if (n-40)&2 != 0 { + attr |= backgroundGreen + } + if (n-40)&4 != 0 { + attr |= backgroundBlue + } + case n == 48: // set background color. + if i < len(token)-2 && token[i+1] == "5" { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256backAttr == nil { + n256setup() + } + attr &= foregroundMask + attr |= n256backAttr[n256%len(n256backAttr)] + i += 2 + } + } else if len(token) == 5 && token[i+1] == "2" { + var r, g, b int + r, _ = strconv.Atoi(token[i+2]) + g, _ = strconv.Atoi(token[i+3]) + b, _ = strconv.Atoi(token[i+4]) + i += 4 + if r > 127 { + attr |= backgroundRed + } + if g > 127 { + attr |= backgroundGreen + } + if b > 127 { + attr |= backgroundBlue + } + } else { + attr = attr & (w.oldattr & foregroundMask) + } + case n == 49: // reset foreground color. + attr &= foregroundMask + attr |= w.oldattr & backgroundMask + case 90 <= n && n <= 97: + attr = (attr & backgroundMask) + attr |= foregroundIntensity + if (n-90)&1 != 0 { + attr |= foregroundRed + } + if (n-90)&2 != 0 { + attr |= foregroundGreen + } + if (n-90)&4 != 0 { + attr |= foregroundBlue + } + case 100 <= n && n <= 107: + attr = (attr & foregroundMask) + attr |= backgroundIntensity + if (n-100)&1 != 0 { + attr |= backgroundRed + } + if (n-100)&2 != 0 { + attr |= backgroundGreen + } + if (n-100)&4 != 0 { + attr |= backgroundBlue + } + } + procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr)) + } + } + case 'h': + var ci consoleCursorInfo + cs := buf.String() + if cs == "5>" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 0 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?25" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 1 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?1049" { + if w.althandle == 0 { + h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0) + w.althandle = syscall.Handle(h) + if w.althandle != 0 { + handle = w.althandle + } + } + } + case 'l': + var ci consoleCursorInfo + cs := buf.String() + if cs == "5>" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 1 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?25" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 0 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?1049" { + if w.althandle != 0 { + syscall.CloseHandle(w.althandle) + w.althandle = 0 + handle = w.handle + } + } + case 's': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + w.oldpos = csbi.cursorPosition + case 'u': + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + } + } + + return len(data), nil +} + +type consoleColor struct { + rgb int + red bool + green bool + blue bool + intensity bool +} + +func (c consoleColor) foregroundAttr() (attr word) { + if c.red { + attr |= foregroundRed + } + if c.green { + attr |= foregroundGreen + } + if c.blue { + attr |= foregroundBlue + } + if c.intensity { + attr |= foregroundIntensity + } + return +} + +func (c consoleColor) backgroundAttr() (attr word) { + if c.red { + attr |= backgroundRed + } + if c.green { + attr |= backgroundGreen + } + if c.blue { + attr |= backgroundBlue + } + if c.intensity { + attr |= backgroundIntensity + } + return +} + +var color16 = []consoleColor{ + {0x000000, false, false, false, false}, + {0x000080, false, false, true, false}, + {0x008000, false, true, false, false}, + {0x008080, false, true, true, false}, + {0x800000, true, false, false, false}, + {0x800080, true, false, true, false}, + {0x808000, true, true, false, false}, + {0xc0c0c0, true, true, true, false}, + {0x808080, false, false, false, true}, + {0x0000ff, false, false, true, true}, + {0x00ff00, false, true, false, true}, + {0x00ffff, false, true, true, true}, + {0xff0000, true, false, false, true}, + {0xff00ff, true, false, true, true}, + {0xffff00, true, true, false, true}, + {0xffffff, true, true, true, true}, +} + +type hsv struct { + h, s, v float32 +} + +func (a hsv) dist(b hsv) float32 { + dh := a.h - b.h + switch { + case dh > 0.5: + dh = 1 - dh + case dh < -0.5: + dh = -1 - dh + } + ds := a.s - b.s + dv := a.v - b.v + return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv))) +} + +func toHSV(rgb int) hsv { + r, g, b := float32((rgb&0xFF0000)>>16)/256.0, + float32((rgb&0x00FF00)>>8)/256.0, + float32(rgb&0x0000FF)/256.0 + min, max := minmax3f(r, g, b) + h := max - min + if h > 0 { + if max == r { + h = (g - b) / h + if h < 0 { + h += 6 + } + } else if max == g { + h = 2 + (b-r)/h + } else { + h = 4 + (r-g)/h + } + } + h /= 6.0 + s := max - min + if max != 0 { + s /= max + } + v := max + return hsv{h: h, s: s, v: v} +} + +type hsvTable []hsv + +func toHSVTable(rgbTable []consoleColor) hsvTable { + t := make(hsvTable, len(rgbTable)) + for i, c := range rgbTable { + t[i] = toHSV(c.rgb) + } + return t +} + +func (t hsvTable) find(rgb int) consoleColor { + hsv := toHSV(rgb) + n := 7 + l := float32(5.0) + for i, p := range t { + d := hsv.dist(p) + if d < l { + l, n = d, i + } + } + return color16[n] +} + +func minmax3f(a, b, c float32) (min, max float32) { + if a < b { + if b < c { + return a, c + } else if a < c { + return a, b + } else { + return c, b + } + } else { + if a < c { + return b, c + } else if b < c { + return b, a + } else { + return c, a + } + } +} + +var n256foreAttr []word +var n256backAttr []word + +func n256setup() { + n256foreAttr = make([]word, 256) + n256backAttr = make([]word, 256) + t := toHSVTable(color16) + for i, rgb := range color256 { + c := t.find(rgb) + n256foreAttr[i] = c.foregroundAttr() + n256backAttr[i] = c.backgroundAttr() + } +} + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + var mode uint32 + h := os.Stdout.Fd() + if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 { + if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { + if enabled != nil { + *enabled = true + } + return func() { + procSetConsoleMode.Call(h, uintptr(mode)) + } + } + } + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-runewidth/go.test.sh b/vendor/github.com/mattn/go-colorable/go.test.sh similarity index 100% rename from vendor/github.com/mattn/go-runewidth/go.test.sh rename to vendor/github.com/mattn/go-colorable/go.test.sh diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go new file mode 100644 index 00000000..05d6f74b --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -0,0 +1,57 @@ +package colorable + +import ( + "bytes" + "io" +) + +// NonColorable holds writer but removes escape sequence. +type NonColorable struct { + out io.Writer +} + +// NewNonColorable returns new instance of Writer which removes escape sequence from Writer. +func NewNonColorable(w io.Writer) io.Writer { + return &NonColorable{out: w} +} + +// Write writes data on console +func (w *NonColorable) Write(data []byte) (n int, err error) { + er := bytes.NewReader(data) + var plaintext bytes.Buffer +loop: + for { + c1, err := er.ReadByte() + if err != nil { + plaintext.WriteTo(w.out) + break loop + } + if c1 != 0x1b { + plaintext.WriteByte(c1) + continue + } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } + c2, err := er.ReadByte() + if err != nil { + break loop + } + if c2 != 0x5b { + continue + } + + for { + c, err := er.ReadByte() + if err != nil { + break loop + } + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { + break + } + } + } + + return len(data), nil +} diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml deleted file mode 100644 index 6a21813a..00000000 --- a/vendor/github.com/mattn/go-runewidth/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - go generate - - git diff --cached --exit-code - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-runewidth/README.md b/vendor/github.com/mattn/go-runewidth/README.md index aa56ab96..5e2cfd98 100644 --- a/vendor/github.com/mattn/go-runewidth/README.md +++ b/vendor/github.com/mattn/go-runewidth/README.md @@ -1,7 +1,7 @@ go-runewidth ============ -[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) +[![Build Status](https://github.com/mattn/go-runewidth/workflows/test/badge.svg?branch=master)](https://github.com/mattn/go-runewidth/actions?query=workflow%3Atest) [![Codecov](https://codecov.io/gh/mattn/go-runewidth/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-runewidth) [![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index 19f8e044..7dfbb3be 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -2,6 +2,9 @@ package runewidth import ( "os" + "strings" + + "github.com/rivo/uniseg" ) //go:generate go run script/generate.go @@ -10,11 +13,14 @@ var ( // EastAsianWidth will be set true if the current locale is CJK EastAsianWidth bool - // ZeroWidthJoiner is flag to set to use UTR#51 ZWJ - ZeroWidthJoiner bool + // StrictEmojiNeutral should be set false if handle broken fonts + StrictEmojiNeutral bool = true // DefaultCondition is a condition in current locale - DefaultCondition = &Condition{} + DefaultCondition = &Condition{ + EastAsianWidth: false, + StrictEmojiNeutral: true, + } ) func init() { @@ -29,8 +35,13 @@ func handleEnv() { EastAsianWidth = env == "1" } // update DefaultCondition - DefaultCondition.EastAsianWidth = EastAsianWidth - DefaultCondition.ZeroWidthJoiner = ZeroWidthJoiner + if DefaultCondition.EastAsianWidth != EastAsianWidth { + DefaultCondition.EastAsianWidth = EastAsianWidth + if len(DefaultCondition.combinedLut) > 0 { + DefaultCondition.combinedLut = DefaultCondition.combinedLut[:0] + CreateLUT() + } + } } type interval struct { @@ -85,63 +96,97 @@ var nonprint = table{ // Condition have flag EastAsianWidth whether the current locale is CJK or not. type Condition struct { - EastAsianWidth bool - ZeroWidthJoiner bool + combinedLut []byte + EastAsianWidth bool + StrictEmojiNeutral bool } // NewCondition return new instance of Condition which is current locale. func NewCondition() *Condition { return &Condition{ - EastAsianWidth: EastAsianWidth, - ZeroWidthJoiner: ZeroWidthJoiner, + EastAsianWidth: EastAsianWidth, + StrictEmojiNeutral: StrictEmojiNeutral, } } // RuneWidth returns the number of cells in r. // See http://www.unicode.org/reports/tr11/ func (c *Condition) RuneWidth(r rune) int { - switch { - case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining, notassigned): + if r < 0 || r > 0x10FFFF { return 0 - case (c.EastAsianWidth && IsAmbiguousWidth(r)) || inTables(r, doublewidth): - return 2 - default: - return 1 } -} - -func (c *Condition) stringWidth(s string) (width int) { - for _, r := range []rune(s) { - width += c.RuneWidth(r) + if len(c.combinedLut) > 0 { + return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3 } - return width -} - -func (c *Condition) stringWidthZeroJoiner(s string) (width int) { - r1, r2 := rune(0), rune(0) - for _, r := range []rune(s) { - if r == 0xFE0E || r == 0xFE0F { - continue + // optimized version, verified by TestRuneWidthChecksums() + if !c.EastAsianWidth { + switch { + case r < 0x20: + return 0 + case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint + return 0 + case r < 0x300: + return 1 + case inTable(r, narrow): + return 1 + case inTables(r, nonprint, combining): + return 0 + case inTable(r, doublewidth): + return 2 + default: + return 1 } - w := c.RuneWidth(r) - if r2 == 0x200D && inTables(r, emoji) && inTables(r1, emoji) { - if width < w { - width = w - } - } else { - width += w + } else { + switch { + case inTables(r, nonprint, combining): + return 0 + case inTable(r, narrow): + return 1 + case inTables(r, ambiguous, doublewidth): + return 2 + case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow): + return 2 + default: + return 1 } - r1, r2 = r2, r } - return width +} + +// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation. +// This should not be called concurrently with other operations on c. +// If options in c is changed, CreateLUT should be called again. +func (c *Condition) CreateLUT() { + const max = 0x110000 + lut := c.combinedLut + if len(c.combinedLut) != 0 { + // Remove so we don't use it. + c.combinedLut = nil + } else { + lut = make([]byte, max/2) + } + for i := range lut { + i32 := int32(i * 2) + x0 := c.RuneWidth(i32) + x1 := c.RuneWidth(i32 + 1) + lut[i] = uint8(x0) | uint8(x1)<<4 + } + c.combinedLut = lut } // StringWidth return width as you can see func (c *Condition) StringWidth(s string) (width int) { - if c.ZeroWidthJoiner { - return c.stringWidthZeroJoiner(s) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // Our best guess at this point is to use the width of the first non-zero-width rune. + } + } + width += chWidth } - return c.stringWidth(s) + return } // Truncate return string truncated with w cells @@ -149,27 +194,69 @@ func (c *Condition) Truncate(s string, w int, tail string) string { if c.StringWidth(s) <= w { return s } - r := []rune(s) - tw := c.StringWidth(tail) - w -= tw - width := 0 - i := 0 - for ; i < len(r); i++ { - cw := c.RuneWidth(r[i]) - if width+cw > w { + w -= c.StringWidth(tail) + var width int + pos := len(s) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + if width+chWidth > w { + pos, _ = g.Positions() break } - width += cw + width += chWidth + } + return s[:pos] + tail +} + +// TruncateLeft cuts w cells from the beginning of the `s`. +func (c *Condition) TruncateLeft(s string, w int, prefix string) string { + if c.StringWidth(s) <= w { + return prefix + } + + var width int + pos := len(s) + + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + + if width+chWidth > w { + if width < w { + _, pos = g.Positions() + prefix += strings.Repeat(" ", width+chWidth-w) + } else { + pos, _ = g.Positions() + } + + break + } + + width += chWidth } - return string(r[0:i]) + tail + + return prefix + s[pos:] } // Wrap return string wrapped with w cells func (c *Condition) Wrap(s string, w int) string { width := 0 out := "" - for _, r := range []rune(s) { - cw := RuneWidth(r) + for _, r := range s { + cw := c.RuneWidth(r) if r == '\n' { out += string(r) width = 0 @@ -241,6 +328,11 @@ func Truncate(s string, w int, tail string) string { return DefaultCondition.Truncate(s, w, tail) } +// TruncateLeft cuts w cells from the beginning of the `s`. +func TruncateLeft(s string, w int, prefix string) string { + return DefaultCondition.TruncateLeft(s, w, prefix) +} + // Wrap return string wrapped with w cells func Wrap(s string, w int) string { return DefaultCondition.Wrap(s, w) @@ -255,3 +347,12 @@ func FillLeft(s string, w int) string { func FillRight(s string, w int) string { return DefaultCondition.FillRight(s, w) } + +// CreateLUT will create an in-memory lookup table of 557055 bytes for faster operation. +// This should not be called concurrently with other operations. +func CreateLUT() { + if len(DefaultCondition.combinedLut) > 0 { + return + } + DefaultCondition.CreateLUT() +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go index 7d99f6e5..84b6528d 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go index c5fdf40b..c2abbc2d 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_js.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -1,5 +1,5 @@ -// +build js -// +build !appengine +//go:build js && !appengine +// +build js,!appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go index 480ad748..5a31d738 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -1,6 +1,5 @@ -// +build !windows -// +build !js -// +build !appengine +//go:build !windows && !js && !appengine +// +build !windows,!js,!appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/vendor/github.com/mattn/go-runewidth/runewidth_table.go index b27d77d8..ad025ad5 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_table.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_table.go @@ -4,20 +4,21 @@ package runewidth var combining = table{ {0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3}, - {0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0D00, 0x0D01}, - {0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1AC0}, - {0x1B6B, 0x1B73}, {0x1DC0, 0x1DF9}, {0x1DFB, 0x1DFF}, + {0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0CF3, 0x0CF3}, + {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ACE}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF}, {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF}, {0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A}, - {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x11300, 0x11301}, - {0x1133B, 0x1133C}, {0x11366, 0x1136C}, {0x11370, 0x11374}, - {0x16AF0, 0x16AF4}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, + {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85}, + {0x11300, 0x11301}, {0x1133B, 0x1133C}, {0x11366, 0x1136C}, + {0x11370, 0x11374}, {0x16AF0, 0x16AF4}, {0x1CF00, 0x1CF2D}, + {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, - {0x1E8D0, 0x1E8D6}, + {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6}, } var doublewidth = table{ @@ -33,33 +34,34 @@ var doublewidth = table{ {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, - {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, - {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, - {0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31E3}, - {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x4DBF}, - {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, - {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, - {0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, - {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4}, - {0x16FF0, 0x16FF1}, {0x17000, 0x187F7}, {0x18800, 0x18CD5}, - {0x18D00, 0x18D08}, {0x1B000, 0x1B11E}, {0x1B150, 0x1B152}, - {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, {0x1F004, 0x1F004}, - {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, - {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, - {0x1F250, 0x1F251}, {0x1F260, 0x1F265}, {0x1F300, 0x1F320}, - {0x1F32D, 0x1F335}, {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, - {0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, - {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, - {0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, - {0x1F550, 0x1F567}, {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, - {0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, - {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2}, {0x1F6D5, 0x1F6D7}, - {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, - {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F978}, - {0x1F97A, 0x1F9CB}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA74}, - {0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA86}, {0x1FA90, 0x1FAA8}, - {0x1FAB0, 0x1FAB6}, {0x1FAC0, 0x1FAC2}, {0x1FAD0, 0x1FAD6}, - {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, + {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x303E}, + {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312F}, + {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31EF, 0x321E}, + {0x3220, 0x3247}, {0x3250, 0x4DBF}, {0x4E00, 0xA48C}, + {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4}, {0x16FF0, 0x16FF1}, + {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08}, + {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE}, + {0x1B000, 0x1B122}, {0x1B132, 0x1B132}, {0x1B150, 0x1B152}, + {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, + {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, + {0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F260, 0x1F265}, + {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, + {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, {0x1F57A, 0x1F57A}, + {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F}, + {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2}, + {0x1F6D5, 0x1F6D7}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC}, + {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, {0x1F7F0, 0x1F7F0}, + {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F9FF}, + {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD}, + {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB}, {0x1FAE0, 0x1FAE8}, + {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, } var ambiguous = table{ @@ -124,8 +126,10 @@ var ambiguous = table{ {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, } -var notassigned = table{ - {0x27E6, 0x27ED}, {0x2985, 0x2986}, +var narrow = table{ + {0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6}, + {0x00AC, 0x00AC}, {0x00AF, 0x00AF}, {0x27E6, 0x27ED}, + {0x2985, 0x2986}, } var neutral = table{ @@ -152,43 +156,43 @@ var neutral = table{ {0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x058A}, {0x058D, 0x058F}, {0x0591, 0x05C7}, {0x05D0, 0x05EA}, {0x05EF, 0x05F4}, - {0x0600, 0x061C}, {0x061E, 0x070D}, {0x070F, 0x074A}, - {0x074D, 0x07B1}, {0x07C0, 0x07FA}, {0x07FD, 0x082D}, - {0x0830, 0x083E}, {0x0840, 0x085B}, {0x085E, 0x085E}, - {0x0860, 0x086A}, {0x08A0, 0x08B4}, {0x08B6, 0x08C7}, - {0x08D3, 0x0983}, {0x0985, 0x098C}, {0x098F, 0x0990}, - {0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, - {0x09B6, 0x09B9}, {0x09BC, 0x09C4}, {0x09C7, 0x09C8}, - {0x09CB, 0x09CE}, {0x09D7, 0x09D7}, {0x09DC, 0x09DD}, - {0x09DF, 0x09E3}, {0x09E6, 0x09FE}, {0x0A01, 0x0A03}, - {0x0A05, 0x0A0A}, {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, - {0x0A2A, 0x0A30}, {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, - {0x0A38, 0x0A39}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, - {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, - {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76}, - {0x0A81, 0x0A83}, {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, - {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, - {0x0AB5, 0x0AB9}, {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9}, - {0x0ACB, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3}, - {0x0AE6, 0x0AF1}, {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03}, - {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, - {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B35, 0x0B39}, - {0x0B3C, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, - {0x0B55, 0x0B57}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63}, - {0x0B66, 0x0B77}, {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, - {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, - {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, - {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2}, - {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0}, - {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C}, - {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, - {0x0C3D, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, - {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C63}, + {0x0600, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1}, + {0x07C0, 0x07FA}, {0x07FD, 0x082D}, {0x0830, 0x083E}, + {0x0840, 0x085B}, {0x085E, 0x085E}, {0x0860, 0x086A}, + {0x0870, 0x088E}, {0x0890, 0x0891}, {0x0898, 0x0983}, + {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, + {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, + {0x09BC, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CE}, + {0x09D7, 0x09D7}, {0x09DC, 0x09DD}, {0x09DF, 0x09E3}, + {0x09E6, 0x09FE}, {0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, + {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, + {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, + {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, + {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76}, {0x0A81, 0x0A83}, + {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, + {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, + {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, + {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, + {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, + {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, + {0x0B32, 0x0B33}, {0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, + {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57}, + {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, + {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, + {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, + {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, + {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, + {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10}, + {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44}, + {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, + {0x0C58, 0x0C5A}, {0x0C5D, 0x0C5D}, {0x0C60, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, {0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, - {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3}, - {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D00, 0x0D0C}, + {0x0CD5, 0x0CD6}, {0x0CDD, 0x0CDE}, {0x0CE0, 0x0CE3}, + {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, {0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, @@ -198,7 +202,7 @@ var neutral = table{ {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, {0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4}, - {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, + {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC}, {0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7}, @@ -210,20 +214,19 @@ var neutral = table{ {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8}, - {0x1700, 0x170C}, {0x170E, 0x1714}, {0x1720, 0x1736}, - {0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, - {0x1772, 0x1773}, {0x1780, 0x17DD}, {0x17E0, 0x17E9}, - {0x17F0, 0x17F9}, {0x1800, 0x180E}, {0x1810, 0x1819}, - {0x1820, 0x1878}, {0x1880, 0x18AA}, {0x18B0, 0x18F5}, - {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B}, - {0x1940, 0x1940}, {0x1944, 0x196D}, {0x1970, 0x1974}, - {0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA}, - {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, - {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, - {0x1AB0, 0x1AC0}, {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C}, - {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49}, - {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, - {0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9}, {0x1DFB, 0x1F15}, + {0x1700, 0x1715}, {0x171F, 0x1736}, {0x1740, 0x1753}, + {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1772, 0x1773}, + {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, + {0x1800, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA}, + {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B}, + {0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D}, + {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, + {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, + {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, + {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C}, + {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, + {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, + {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, @@ -235,7 +238,7 @@ var neutral = table{ {0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064}, {0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080}, {0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, - {0x20AA, 0x20AB}, {0x20AD, 0x20BF}, {0x20D0, 0x20F0}, + {0x20AA, 0x20AB}, {0x20AD, 0x20C0}, {0x20D0, 0x20F0}, {0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120}, {0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152}, @@ -273,15 +276,15 @@ var neutral = table{ {0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE}, {0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A}, {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73}, - {0x2B76, 0x2B95}, {0x2B97, 0x2C2E}, {0x2C30, 0x2C5E}, - {0x2C60, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D27, 0x2D27}, - {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D70}, - {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, - {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, - {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, - {0x2DE0, 0x2E52}, {0x303F, 0x303F}, {0x4DC0, 0x4DFF}, - {0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, {0xA700, 0xA7BF}, - {0xA7C2, 0xA7CA}, {0xA7F5, 0xA82C}, {0xA830, 0xA839}, + {0x2B76, 0x2B95}, {0x2B97, 0x2CF3}, {0x2CF9, 0x2D25}, + {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, + {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, + {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, + {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, + {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E5D}, {0x303F, 0x303F}, + {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, + {0xA700, 0xA7CA}, {0xA7D0, 0xA7D1}, {0xA7D3, 0xA7D3}, + {0xA7D5, 0xA7D9}, {0xA7F2, 0xA82C}, {0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36}, @@ -292,8 +295,8 @@ var neutral = table{ {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, - {0xFB43, 0xFB44}, {0xFB46, 0xFBC1}, {0xFBD3, 0xFD3F}, - {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD}, + {0xFB43, 0xFB44}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F}, + {0xFD92, 0xFDC7}, {0xFDCF, 0xFDCF}, {0xFDF0, 0xFDFF}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D}, @@ -305,44 +308,48 @@ var neutral = table{ {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5}, {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, - {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, - {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, - {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, - {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF}, - {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B}, - {0x1091F, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x109B7}, - {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06}, - {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58}, - {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6}, - {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72}, - {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, - {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, - {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10E60, 0x10E7E}, - {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EB0, 0x10EB1}, - {0x10F00, 0x10F27}, {0x10F30, 0x10F59}, {0x10FB0, 0x10FCB}, - {0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x1106F}, - {0x1107F, 0x110C1}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8}, - {0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147}, - {0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4}, - {0x11200, 0x11211}, {0x11213, 0x1123E}, {0x11280, 0x11286}, - {0x11288, 0x11288}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, - {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, - {0x11300, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, - {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, - {0x11335, 0x11339}, {0x1133B, 0x11344}, {0x11347, 0x11348}, - {0x1134B, 0x1134D}, {0x11350, 0x11350}, {0x11357, 0x11357}, - {0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, - {0x11400, 0x1145B}, {0x1145D, 0x11461}, {0x11480, 0x114C7}, - {0x114D0, 0x114D9}, {0x11580, 0x115B5}, {0x115B8, 0x115DD}, - {0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, - {0x11680, 0x116B8}, {0x116C0, 0x116C9}, {0x11700, 0x1171A}, - {0x1171D, 0x1172B}, {0x11730, 0x1173F}, {0x11800, 0x1183B}, - {0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x11909, 0x11909}, - {0x1190C, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x11935}, - {0x11937, 0x11938}, {0x1193B, 0x11946}, {0x11950, 0x11959}, - {0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, - {0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AC0, 0x11AF8}, + {0x1056F, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592}, + {0x10594, 0x10595}, {0x10597, 0x105A1}, {0x105A3, 0x105B1}, + {0x105B3, 0x105B9}, {0x105BB, 0x105BC}, {0x10600, 0x10736}, + {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785}, + {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805}, + {0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838}, + {0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E}, + {0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, + {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F}, + {0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, + {0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, + {0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, + {0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, + {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, + {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, + {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, + {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, + {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, + {0x10EB0, 0x10EB1}, {0x10EFD, 0x10F27}, {0x10F30, 0x10F59}, + {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB}, {0x10FE0, 0x10FF6}, + {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110C2}, + {0x110CD, 0x110CD}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, + {0x11100, 0x11134}, {0x11136, 0x11147}, {0x11150, 0x11176}, + {0x11180, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, + {0x11213, 0x11241}, {0x11280, 0x11286}, {0x11288, 0x11288}, + {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A9}, + {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11303}, + {0x11305, 0x1130C}, {0x1130F, 0x11310}, {0x11313, 0x11328}, + {0x1132A, 0x11330}, {0x11332, 0x11333}, {0x11335, 0x11339}, + {0x1133B, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D}, + {0x11350, 0x11350}, {0x11357, 0x11357}, {0x1135D, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x1145B}, + {0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644}, + {0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9}, + {0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B}, + {0x11730, 0x11746}, {0x11800, 0x1183B}, {0x118A0, 0x118F2}, + {0x118FF, 0x11906}, {0x11909, 0x11909}, {0x1190C, 0x11913}, + {0x11915, 0x11916}, {0x11918, 0x11935}, {0x11937, 0x11938}, + {0x1193B, 0x11946}, {0x11950, 0x11959}, {0x119A0, 0x119A7}, + {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, {0x11A00, 0x11A47}, + {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09}, @@ -350,30 +357,36 @@ var neutral = table{ {0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65}, {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91}, {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8}, + {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F59}, {0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399}, {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, - {0x13000, 0x1342E}, {0x13430, 0x13438}, {0x14400, 0x14646}, + {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, - {0x16A6E, 0x16A6F}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5}, - {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, - {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16E40, 0x16E9A}, - {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F}, - {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, - {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, {0x1D000, 0x1D0F5}, - {0x1D100, 0x1D126}, {0x1D129, 0x1D1E8}, {0x1D200, 0x1D245}, - {0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, - {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, - {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, - {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, - {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, - {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, - {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, - {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, - {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, - {0x1E026, 0x1E02A}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D}, - {0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E2C0, 0x1E2F9}, - {0x1E2FF, 0x1E2FF}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6}, + {0x16A6E, 0x16ABE}, {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED}, + {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, + {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, + {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, + {0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, + {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1CF50, 0x1CFC3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1EA}, + {0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3}, + {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, {0x1D400, 0x1D454}, + {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, + {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, + {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, + {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, + {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, + {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, + {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, + {0x1DAA1, 0x1DAAF}, {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, + {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, + {0x1E08F, 0x1E08F}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D}, + {0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE}, + {0x1E2C0, 0x1E2F9}, {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9}, + {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7ED, 0x1E7EE}, + {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24}, @@ -398,8 +411,8 @@ var neutral = table{ {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4}, - {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, - {0x1F780, 0x1F7D8}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, + {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F776}, + {0x1F77B, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B}, {0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D}, diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go index d6a61777..5f987a31 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package runewidth diff --git a/vendor/github.com/olekukonko/errors/.gitignore b/vendor/github.com/olekukonko/errors/.gitignore new file mode 100644 index 00000000..8a1327cd --- /dev/null +++ b/vendor/github.com/olekukonko/errors/.gitignore @@ -0,0 +1,3 @@ +# Created by .ignore support plugin (hsz.mobi) +.idea/ +tmp/ \ No newline at end of file diff --git a/vendor/github.com/olekukonko/errors/LICENSE b/vendor/github.com/olekukonko/errors/LICENSE new file mode 100644 index 00000000..ca02db8c --- /dev/null +++ b/vendor/github.com/olekukonko/errors/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Oleku Konko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/olekukonko/errors/README.md b/vendor/github.com/olekukonko/errors/README.md new file mode 100644 index 00000000..e99cf999 --- /dev/null +++ b/vendor/github.com/olekukonko/errors/README.md @@ -0,0 +1,1358 @@ +# Enhanced Error Handling for Go with Context, Stack Traces, Monitoring, and More + +[![Go Reference](https://pkg.go.dev/badge/github.com/olekukonko/errors.svg)](https://pkg.go.dev/github.com/olekukonko/errors) +[![Go Report Card](https://goreportcard.com/badge/github.com/olekukonko/errors)](https://goreportcard.com/report/github.com/olekukonko/errors) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Benchmarks](https://img.shields.io/badge/benchmarks-included-success)](README.md#benchmarks) + +A production-grade error handling library for Go, offering zero-cost abstractions, stack traces, multi-error support, retries, and advanced monitoring through two complementary packages: `errors` (core) and `errmgr` (management). + +## Features + +### `errors` Package (Core) +- **Performance Optimized** + - Optional memory pooling (12 ns/op with pooling) + - Lazy stack trace collection (205 ns/op with stack) + - Small context optimization (≤4 items, 40 ns/op) + - Lock-free configuration reads + +- **Debugging Tools** + - Full stack traces with internal frame filtering + - Error wrapping and chaining + - Structured context attachment + - JSON serialization (662 ns/op) + +- **Advanced Utilities** + - Configurable retry mechanism + - Multi-error aggregation with sampling + - HTTP status code support + - Callback triggers for cleanup or side effects + +### `errmgr` Package (Management) +- **Production Monitoring** + - Error occurrence counting + - Threshold-based alerting + - Categorized metrics + - Predefined error templates + +## Installation + +```bash +go get github.com/olekukonko/errors@latest +``` + +## Package Overview + +- **`errors`**: Core error handling with creation, wrapping, context, stack traces, retries, and multi-error support. +- **`errmgr`**: Error management with templates, monitoring, and predefined errors for consistent application use. + +--- + +## Using the `errors` Package + +### Basic Error Creation + +#### Simple Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Fast error with no stack trace + err := errors.New("connection failed") + fmt.Println(err) // "connection failed" + + // Standard error, no allocation, same speed + stdErr := errors.Std("connection failed") + fmt.Println(stdErr) // "connection failed" +} +``` + +#### Formatted Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Formatted error without stack trace + err := errors.Newf("user %s not found", "bob") + fmt.Println(err) // Output: "user bob not found" + + // Standard formatted error, no fmt.Errorf needed + stdErr := errors.Stdf("user %s not found", "bob") + fmt.Println(stdErr) // Output: "user bob not found" +} +``` + +#### Error with Stack Trace +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Create an error with stack trace using Trace + err := errors.Trace("critical issue") + fmt.Println(err) // Output: "critical issue" + fmt.Println(err.Stack()) // Output: e.g., ["main.go:15", "caller.go:42"] + + // Convert basic error to traceable with WithStack + errS := errors.New("critical issue") + errS = errS.WithStack() // Add stack trace and update error + fmt.Println(errS) // Output: "critical issue" + fmt.Println(errS.Stack()) // Output: e.g., ["main.go:19", "caller.go:42"] +} +``` + +#### Named Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Create a named error with stack trace + err := errors.Named("InputError") + fmt.Println(err.Name()) // Output: "InputError" + fmt.Println(err) // Output: "InputError" +} +``` + +### Adding Context + +#### Basic Context +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Create an error with context + err := errors.New("processing failed"). + With("id", "123"). + With("attempt", 3). + With("retryable", true) + fmt.Println("Error:", err) // Output: "processing failed" + fmt.Println("Full context:", errors.Context(err)) // Output: map[id:123 attempt:3 retryable:true] +} +``` + +#### Context with Wrapped Standard Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Wrap a standard error and add context + err := errors.New("processing failed"). + With("id", "123") + wrapped := fmt.Errorf("wrapped: %w", err) + fmt.Println("Wrapped error:", wrapped) // Output: "wrapped: processing failed" + fmt.Println("Direct context:", errors.Context(wrapped)) // Output: nil + + // Convert to access context + e := errors.Convert(wrapped) + fmt.Println("Converted context:", e.Context()) // Output: map[id:123] +} +``` + +#### Adding Context to Standard Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Convert a standard error and add context + stdErr := fmt.Errorf("standard error") + converted := errors.Convert(stdErr). + With("source", "legacy"). + With("severity", "high") + fmt.Println("Message:", converted.Error()) // Output: "standard error" + fmt.Println("Context:", converted.Context()) // Output: map[source:legacy severity:high] +} +``` + +#### Complex Context +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Create an error with complex context + err := errors.New("database operation failed"). + With("query", "SELECT * FROM users"). + With("params", map[string]interface{}{ + "limit": 100, + "offset": 0, + }). + With("duration_ms", 45.2) + fmt.Println("Complex error context:") + for k, v := range errors.Context(err) { + fmt.Printf("%s: %v (%T)\n", k, v, v) + } + // Output: + // query: SELECT * FROM users (string) + // params: map[limit:100 offset:0] (map[string]interface {}) + // duration_ms: 45.2 (float64) +} +``` + +### Stack Traces + +#### Adding Stack to Any Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Add stack trace to a standard error + err := fmt.Errorf("basic error") + enhanced := errors.WithStack(err) + fmt.Println("Error with stack:") + fmt.Println("Message:", enhanced.Error()) // Output: "basic error" + fmt.Println("Stack:", enhanced.Stack()) // Output: e.g., ["main.go:15", ...] +} +``` + +#### Chaining with Stack +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" + "time" +) + +func main() { + // Create an enhanced error and add stack/context + err := errors.New("validation error"). + With("field", "email") + stackErr := errors.WithStack(err). + With("timestamp", time.Now()). + WithCode(500) + fmt.Println("Message:", stackErr.Error()) // Output: "validation error" + fmt.Println("Context:", stackErr.Context()) // Output: map[field:email timestamp:...] + fmt.Println("Stack:") + for _, frame := range stackErr.Stack() { + fmt.Println(frame) + } +} +``` +### Stack Traces with `WithStack()` +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" + "math/rand" + "time" +) + +func basicFunc() error { + return fmt.Errorf("basic error") +} + +func enhancedFunc() *errors.Error { + return errors.New("enhanced error") +} + +func main() { + // 1. Package-level WithStack - works with ANY error type + err1 := basicFunc() + enhanced1 := errors.WithStack(err1) // Handles basic errors + fmt.Println("Package-level WithStack:") + fmt.Println(enhanced1.Stack()) + + // 2. Method-style WithStack - only for *errors.Error + err2 := enhancedFunc() + enhanced2 := err2.WithStack() // More natural chaining + fmt.Println("\nMethod-style WithStack:") + fmt.Println(enhanced2.Stack()) + + // 3. Combined usage in real-world scenario + result := processData() + if result != nil { + // Use package-level when type is unknown + stackErr := errors.WithStack(result) + + // Then use method-style for chaining + finalErr := stackErr. + With("timestamp", time.Now()). + WithCode(500) + + fmt.Println("\nCombined Usage:") + fmt.Println("Message:", finalErr.Error()) + fmt.Println("Context:", finalErr.Context()) + fmt.Println("Stack:") + for _, frame := range finalErr.Stack() { + fmt.Println(frame) + } + } +} + +func processData() error { + // Could return either basic or enhanced error + if rand.Intn(2) == 0 { + return fmt.Errorf("database error") + } + return errors.New("validation error").With("field", "email") +} +``` + +### Error Wrapping and Chaining + +#### Basic Wrapping +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Wrap an error with additional context + lowErr := errors.New("low-level failure") + highErr := errors.Wrapf(lowErr, "high-level operation failed: %s", "details") + fmt.Println(highErr) // Output: "high-level operation failed: details: low-level failure" + fmt.Println(errors.Unwrap(highErr)) // Output: "low-level failure" +} +``` + +#### Walking Error Chain +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Create a chained error + dbErr := errors.New("connection timeout"). + With("server", "db01.prod") + bizErr := errors.New("failed to process user 12345"). + With("user_id", "12345"). + Wrap(dbErr) + apiErr := errors.New("API request failed"). + WithCode(500). + Wrap(bizErr) + + // Walk the error chain + fmt.Println("Error Chain:") + for i, e := range errors.UnwrapAll(apiErr) { + fmt.Printf("%d. %s\n", i+1, e) + } + // Output: + // 1. API request failed + // 2. failed to process user 12345 + // 3. connection timeout +} +``` + +### Type Assertions + +#### Using Is +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Check error type with Is + err := errors.Named("AuthError") + wrapped := errors.Wrapf(err, "login failed") + if errors.Is(wrapped, err) { + fmt.Println("Is an AuthError") // Output: "Is an AuthError" + } +} +``` + +#### Using As +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Extract error type with As + err := errors.Named("AuthError") + wrapped := errors.Wrapf(err, "login failed") + var authErr *errors.Error + if wrapped.As(&authErr) { + fmt.Println("Extracted:", authErr.Name()) // Output: "Extracted: AuthError" + } +} +``` + +### Retry Mechanism + +#### Basic Retry +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" + "math/rand" + "time" +) + +func main() { + // Simulate a flaky operation + attempts := 0 + retry := errors.NewRetry( + errors.WithMaxAttempts(3), + errors.WithDelay(100*time.Millisecond), + ) + err := retry.Execute(func() error { + attempts++ + if rand.Intn(2) == 0 { + return errors.New("temporary failure").WithRetryable() + } + return nil + }) + if err != nil { + fmt.Printf("Failed after %d attempts: %v\n", attempts, err) + } else { + fmt.Printf("Succeeded after %d attempts\n", attempts) + } +} + +``` + +#### Retry with Context Timeout +```go +package main + +import ( + "context" + "fmt" + "github.com/olekukonko/errors" + "time" +) + +func main() { + // Retry with context timeout + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + retry := errors.NewRetry( + errors.WithContext(ctx), + errors.WithMaxAttempts(5), + errors.WithDelay(200*time.Millisecond), + ) + err := retry.Execute(func() error { + return errors.New("operation failed").WithRetryable() + }) + if errors.Is(err, context.DeadlineExceeded) { + fmt.Println("Operation timed out:", err) + } else if err != nil { + fmt.Println("Operation failed:", err) + } +} +``` + + +### Retry Comprehensive + +```go +package main + +import ( + "context" + "fmt" + "github.com/olekukonko/errors" + "math/rand" + "time" +) + +// DatabaseClient simulates a flaky database connection +type DatabaseClient struct { + healthyAfterAttempt int +} + +func (db *DatabaseClient) Query() error { + if db.healthyAfterAttempt > 0 { + db.healthyAfterAttempt-- + return errors.New("database connection failed"). + With("attempt_remaining", db.healthyAfterAttempt). + WithRetryable() // Mark as retryable + } + return nil +} + +// ExternalService simulates an unreliable external API +func ExternalService() error { + if rand.Intn(100) < 30 { // 30% failure rate + return errors.New("service unavailable"). + WithCode(503). + WithRetryable() + } + return nil +} + +func main() { + // Configure retry with exponential backoff and jitter + retry := errors.NewRetry( + errors.WithMaxAttempts(5), + errors.WithDelay(200*time.Millisecond), + errors.WithMaxDelay(2*time.Second), + errors.WithJitter(true), + errors.WithBackoff(errors.ExponentialBackoff{}), + errors.WithOnRetry(func(attempt int, err error) { + // Calculate delay using the same logic as in Execute + baseDelay := 200 * time.Millisecond + maxDelay := 2 * time.Second + delay := errors.ExponentialBackoff{}.Backoff(attempt, baseDelay) + if delay > maxDelay { + delay = maxDelay + } + fmt.Printf("Attempt %d failed: %v (retrying in %v)\n", + attempt, + err.Error(), + delay) + }), + ) + + // Scenario 1: Database connection with known recovery point + db := &DatabaseClient{healthyAfterAttempt: 3} + fmt.Println("Starting database operation...") + err := retry.Execute(func() error { + return db.Query() + }) + if err != nil { + fmt.Printf("Database operation failed after %d attempts: %v\n", retry.Attempts(), err) + } else { + fmt.Println("Database operation succeeded!") + } + + // Scenario 2: External service with random failures + fmt.Println("\nStarting external service call...") + var lastAttempts int + start := time.Now() + + // Using ExecuteReply to demonstrate return values + result, err := errors.ExecuteReply[string](retry, func() (string, error) { + lastAttempts++ + if err := ExternalService(); err != nil { + return "", err + } + return "service response data", nil + }) + + duration := time.Since(start) + + if err != nil { + fmt.Printf("Service call failed after %d attempts (%.2f sec): %v\n", + lastAttempts, + duration.Seconds(), + err) + } else { + fmt.Printf("Service call succeeded after %d attempts (%.2f sec): %s\n", + lastAttempts, + duration.Seconds(), + result) + } + + // Scenario 3: Context cancellation with more visibility + fmt.Println("\nStarting operation with timeout...") + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + timeoutRetry := retry.Transform( + errors.WithContext(ctx), + errors.WithMaxAttempts(10), + errors.WithOnRetry(func(attempt int, err error) { + fmt.Printf("Timeout scenario attempt %d: %v\n", attempt, err) + }), + ) + + startTimeout := time.Now() + err = timeoutRetry.Execute(func() error { + time.Sleep(300 * time.Millisecond) // Simulate long operation + return errors.New("operation timed out") + }) + + if errors.Is(err, context.DeadlineExceeded) { + fmt.Printf("Operation cancelled by timeout after %.2f sec: %v\n", + time.Since(startTimeout).Seconds(), + err) + } else if err != nil { + fmt.Printf("Operation failed: %v\n", err) + } else { + fmt.Println("Operation succeeded (unexpected)") + } +} +``` + +### Multi-Error Aggregation + +#### Form Validation +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Validate a form with multiple errors + multi := errors.NewMultiError() + multi.Add(errors.New("name is required")) + multi.Add(errors.New("email is invalid")) + multi.Add(errors.New("password too short")) + if multi.Has() { + fmt.Println(multi) // Output: "errors(3): name is required; email is invalid; password too short" + fmt.Printf("Total errors: %d\n", multi.Count()) + } +} +``` + +#### Sampling Multi-Errors +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Simulate many errors with sampling + multi := errors.NewMultiError( + errors.WithSampling(10), // 10% sampling + errors.WithLimit(5), + ) + for i := 0; i < 100; i++ { + multi.Add(errors.Newf("error %d", i)) + } + fmt.Println(multi) + fmt.Printf("Captured %d out of 100 errors\n", multi.Count()) +} +``` + +### Additional Examples + +#### Using Callbacks +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Add a callback to an error + err := errors.New("transaction failed"). + Callback(func() { + fmt.Println("Reversing transaction...") + }) + fmt.Println(err) // Output: "transaction failed" + "Reversing transaction..." + err.Free() +} +``` + +#### Copying Errors +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Copy an error and modify the copy + original := errors.New("base error").With("key", "value") + copied := original.Copy().With("extra", "data") + fmt.Println("Original:", original, original.Context()) // Output: "base error" map[key:value] + fmt.Println("Copied:", copied, copied.Context()) // Output: "base error" map[key:value extra:data] +} +``` + +#### Transforming Errors +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Transform an error with additional context + err := errors.New("base error") + transformed := errors.Transform(err, func(e *errors.Error) { + e.With("env", "prod"). + WithCode(500). + WithStack() + }) + fmt.Println(transformed.Error()) // Output: "base error" + fmt.Println(transformed.Context()) // Output: map[env:prod] + fmt.Println(transformed.Code()) // Output: 500 + fmt.Println(len(transformed.Stack()) > 0) // Output: true + transformed.Free() +} +``` + +### Transformation and Enrichment + +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func process() error { + return errors.New("base error") +} + +func main() { + err := process() + transformedErr := errors.Transform(err, func(e *errors.Error) { + e.With("env", "prod"). + WithCode(500). + WithStack() + }) + + // No type assertion needed now + fmt.Println(transformedErr.Error()) // "base error" + fmt.Println(transformedErr.Context()) // map[env:prod] + fmt.Println(transformedErr.Code()) // 500 + fmt.Println(len(transformedErr.Stack()) > 0) // true + transformedErr.Free() // Clean up + + stdErr := process() + convertedErr := errors.Convert(stdErr) // Convert standard error to *Error + convertedErr.With("source", "external"). + WithCode(400). + Callback(func() { + fmt.Println("Converted error processed...") + }) + fmt.Println("Converted Error:", convertedErr.Error()) + fmt.Println("Context:", convertedErr.Context()) + fmt.Println("Code:", convertedErr.Code()) + convertedErr.Free() + +} + +``` + +#### Fast Stack Trace +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Get a lightweight stack trace + err := errors.Trace("lightweight error") + fastStack := err.FastStack() + fmt.Println("Fast Stack:") + for _, frame := range fastStack { + fmt.Println(frame) // Output: e.g., "main.go:15" + } +} +``` + +#### WarmStackPool +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Pre-warm the stack pool + errors.WarmStackPool(10) + err := errors.Trace("pre-warmed error") + fmt.Println("Stack after warming pool:") + for _, frame := range err.Stack() { + fmt.Println(frame) + } +} +``` + +### Multi-Error Aggregation + +```go +package main + +import ( + "fmt" + "net/mail" + "strings" + "time" + + "github.com/olekukonko/errors" +) + +type UserForm struct { + Name string + Email string + Password string + Birthday string +} + +func validateUser(form UserForm) *errors.MultiError { + multi := errors.NewMultiError( + errors.WithLimit(10), + errors.WithFormatter(customFormat), + ) + + // Name validation + if form.Name == "" { + multi.Add(errors.New("name is required")) + } else if len(form.Name) > 50 { + multi.Add(errors.New("name cannot exceed 50 characters")) + } + + // Email validation + if form.Email == "" { + multi.Add(errors.New("email is required")) + } else { + if _, err := mail.ParseAddress(form.Email); err != nil { + multi.Add(errors.New("invalid email format")) + } + if !strings.Contains(form.Email, "@") { + multi.Add(errors.New("email must contain @ symbol")) + } + } + + // Password validation + if len(form.Password) < 8 { + multi.Add(errors.New("password must be at least 8 characters")) + } + if !strings.ContainsAny(form.Password, "0123456789") { + multi.Add(errors.New("password must contain at least one number")) + } + if !strings.ContainsAny(form.Password, "!@#$%^&*") { + multi.Add(errors.New("password must contain at least one special character")) + } + + // Birthday validation + if form.Birthday != "" { + if _, err := time.Parse("2006-01-02", form.Birthday); err != nil { + multi.Add(errors.New("birthday must be in YYYY-MM-DD format")) + } else if bday, _ := time.Parse("2006-01-02", form.Birthday); time.Since(bday).Hours()/24/365 < 13 { + multi.Add(errors.New("must be at least 13 years old")) + } + } + + return multi +} + +func customFormat(errs []error) string { + var sb strings.Builder + sb.WriteString("🚨 Validation Errors:\n") + for i, err := range errs { + sb.WriteString(fmt.Sprintf(" %d. %s\n", i+1, err)) + } + sb.WriteString(fmt.Sprintf("\nTotal issues found: %d\n", len(errs))) + return sb.String() +} + +func main() { + fmt.Println("=== User Registration Validation ===") + + user := UserForm{ + Name: "", // Empty name + Email: "invalid-email", + Password: "weak", + Birthday: "2015-01-01", // Under 13 + } + + // Generate multiple validation errors + validationErrors := validateUser(user) + + if validationErrors.Has() { + fmt.Println(validationErrors) + + // Detailed error analysis + fmt.Println("\n🔍 Error Analysis:") + fmt.Printf("Total errors: %d\n", validationErrors.Count()) + fmt.Printf("First error: %v\n", validationErrors.First()) + fmt.Printf("Last error: %v\n", validationErrors.Last()) + + // Categorized errors with consistent formatting + fmt.Println("\n📋 Error Categories:") + if emailErrors := validationErrors.Filter(contains("email")); emailErrors.Has() { + fmt.Println("Email Issues:") + if emailErrors.Count() == 1 { + fmt.Println(customFormat([]error{emailErrors.First()})) + } else { + fmt.Println(emailErrors) + } + } + if pwErrors := validationErrors.Filter(contains("password")); pwErrors.Has() { + fmt.Println("Password Issues:") + if pwErrors.Count() == 1 { + fmt.Println(customFormat([]error{pwErrors.First()})) + } else { + fmt.Println(pwErrors) + } + } + if ageErrors := validationErrors.Filter(contains("13 years")); ageErrors.Has() { + fmt.Println("Age Restriction:") + if ageErrors.Count() == 1 { + fmt.Println(customFormat([]error{ageErrors.First()})) + } else { + fmt.Println(ageErrors) + } + } + } + + // System Error Aggregation Example + fmt.Println("\n=== System Error Aggregation ===") + systemErrors := errors.NewMultiError( + errors.WithLimit(5), + errors.WithFormatter(systemErrorFormat), + ) + + // Simulate system errors + systemErrors.Add(errors.New("database connection timeout").WithRetryable()) + systemErrors.Add(errors.New("API rate limit exceeded").WithRetryable()) + systemErrors.Add(errors.New("disk space low")) + systemErrors.Add(errors.New("database connection timeout").WithRetryable()) // Duplicate + systemErrors.Add(errors.New("cache miss")) + systemErrors.Add(errors.New("database connection timeout").WithRetryable()) // Over limit + + fmt.Println(systemErrors) + fmt.Printf("\nSystem Status: %d active issues\n", systemErrors.Count()) + + // Filter retryable errors + if retryable := systemErrors.Filter(errors.IsRetryable); retryable.Has() { + fmt.Println("\n🔄 Retryable Errors:") + fmt.Println(retryable) + } +} + +func systemErrorFormat(errs []error) string { + var sb strings.Builder + sb.WriteString("⚠️ System Alerts:\n") + for i, err := range errs { + sb.WriteString(fmt.Sprintf(" %d. %s", i+1, err)) + if errors.IsRetryable(err) { + sb.WriteString(" (retryable)") + } + sb.WriteString("\n") + } + return sb.String() +} + +func contains(substr string) func(error) bool { + return func(err error) bool { + return strings.Contains(err.Error(), substr) + } +} + +``` + +--- + +## Using the `errmgr` Package + +### Predefined Errors + +#### Static Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors/errmgr" +) + +func main() { + // Use a predefined static error + err := errmgr.ErrNotFound + fmt.Println(err) // Output: "not found" + fmt.Println(err.Code()) // Output: 404 +} +``` + +#### Templated Error +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors/errmgr" +) + +func main() { + // Use a templated error with category + err := errmgr.ErrDBQuery("SELECT failed") + fmt.Println(err) // Output: "database query failed: SELECT failed" + fmt.Println(err.Category()) // Output: "database" +} +``` + +### Error Monitoring + +#### Basic Monitoring +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors/errmgr" + "time" +) + +func main() { + // Define and monitor an error + netErr := errmgr.Define("NetError", "network issue: %s") + monitor := errmgr.NewMonitor("NetError") + errmgr.SetThreshold("NetError", 2) + defer monitor.Close() + + go func() { + for alert := range monitor.Alerts() { + fmt.Printf("Alert: %s, count: %d\n", alert.Error(), alert.Count()) + } + }() + + for i := 0; i < 4; i++ { + err := netErr(fmt.Sprintf("attempt %d", i)) + err.Free() + } + time.Sleep(100 * time.Millisecond) +} +``` + +#### Realistic Monitoring +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" + "github.com/olekukonko/errors/errmgr" + "os" + "os/signal" + "syscall" + "time" +) + +func main() { + // Define our error types + netErr := errmgr.Define("NetError", "network connection failed: %s (attempt %d)") + dbErr := errmgr.Define("DBError", "database operation failed: %s") + + // Create monitors with different buffer sizes + netMonitor := errmgr.NewMonitorBuffered("NetError", 10) // Larger buffer for network errors + dbMonitor := errmgr.NewMonitorBuffered("DBError", 5) // Smaller buffer for DB errors + defer netMonitor.Close() + defer dbMonitor.Close() + + // Set different thresholds + errmgr.SetThreshold("NetError", 3) // Alert after 3 network errors + errmgr.SetThreshold("DBError", 2) // Alert after 2 database errors + + // Set up signal handling for graceful shutdown + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + // Alert handler goroutine + done := make(chan struct{}) + go func() { + defer close(done) + for { + select { + case alert, ok := <-netMonitor.Alerts(): + if !ok { + fmt.Println("Network alert channel closed") + return + } + handleAlert("NETWORK", alert) + case alert, ok := <-dbMonitor.Alerts(): + if !ok { + fmt.Println("Database alert channel closed") + return + } + handleAlert("DATABASE", alert) + case <-time.After(2 * time.Second): + // Periodic check for shutdown + continue + } + } + }() + + // Simulate operations with potential failures + go func() { + for i := 1; i <= 15; i++ { + // Simulate different error scenarios + if i%4 == 0 { + // Database error + err := dbErr("connection timeout") + fmt.Printf("DB Operation %d: Failed\n", i) + err.Free() + } else { + // Network error + var errMsg string + switch { + case i%3 == 0: + errMsg = "timeout" + case i%5 == 0: + errMsg = "connection reset" + default: + errMsg = "unknown error" + } + + err := netErr(errMsg, i) + fmt.Printf("Network Operation %d: Failed with %q\n", i, errMsg) + err.Free() + } + + // Random delay between operations + time.Sleep(time.Duration(100+(i%200)) * time.Millisecond) + } + }() + + // Wait for shutdown signal or completion + select { + case <-sigChan: + fmt.Println("\nReceived shutdown signal...") + case <-time.After(5 * time.Second): + fmt.Println("Completion timeout reached...") + } + + // Cleanup + fmt.Println("Initiating shutdown...") + netMonitor.Close() + dbMonitor.Close() + + // Wait for the alert handler to finish + select { + case <-done: + fmt.Println("Alert handler shutdown complete") + case <-time.After(1 * time.Second): + fmt.Println("Alert handler shutdown timeout") + } + + fmt.Println("Application shutdown complete") +} + +func handleAlert(service string, alert *errors.Error) { + if alert == nil { + fmt.Printf("[%s] Received nil alert\n", service) + return + } + + fmt.Printf("[%s ALERT] %s (total occurrences: %d)\n", + service, alert.Error(), alert.Count()) + + if alert.Count() > 5 { + fmt.Printf("[%s CRITICAL] High error rate detected!\n", service) + } +} +``` + +--- + +## Performance Optimization + +### Configuration Tuning +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Tune error package configuration + errors.Configure(errors.Config{ + StackDepth: 32, // Limit stack frames + ContextSize: 4, // Optimize small contexts + DisablePooling: false, // Enable pooling + }) + err := errors.New("configured error") + fmt.Println(err) // Output: "configured error" +} +``` + +### Using `Free()` for Performance +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Use Free() to return error to pool + err := errors.New("temp error") + fmt.Println(err) // Output: "temp error" + err.Free() // Immediate pool return, reduces GC pressure +} +``` + +### Benchmarks +Real performance data (Apple M3 Pro, Go 1.21): +``` +goos: darwin +goarch: arm64 +pkg: github.com/olekukonko/errors +cpu: Apple M3 Pro +BenchmarkBasic_New-12 99810412 12.00 ns/op 0 B/op 0 allocs/op +BenchmarkStack_WithStack-12 5879510 205.6 ns/op 24 B/op 1 allocs/op +BenchmarkContext_Small-12 29600850 40.34 ns/op 16 B/op 1 allocs/op +BenchmarkWrapping_Simple-12 100000000 11.73 ns/op 0 B/op 0 allocs/op +``` +- **New with Pooling**: 12 ns/op, 0 allocations +- **WithStack**: 205 ns/op, minimal allocation +- **Context**: 40 ns/op for small contexts +- Run: `go test -bench=. -benchmem` + +## Migration Guide + +### From Standard Library +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Before: Standard library error + err1 := fmt.Errorf("error: %v", "oops") + fmt.Println(err1) + + // After: Enhanced error with context and stack + err2 := errors.Newf("error: %v", "oops"). + With("source", "api"). + WithStack() + fmt.Println(err2) +} +``` + +### From `pkg/errors` +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Before: pkg/errors (assuming similar API) + // err := pkgerrors.Wrap(err, "context") + + // After: Enhanced wrapping + err := errors.New("low-level"). + Msgf("context: %s", "details"). + WithStack() + fmt.Println(err) +} +``` + +### Compatibility with `errors.Is` and `errors.As` +```go +package main + +import ( + "fmt" + "github.com/olekukonko/errors" +) + +func main() { + // Check compatibility with standard library + err := errors.Named("MyError") + wrapped := errors.Wrapf(err, "outer") + if errors.Is(wrapped, err) { // Stdlib compatible + fmt.Println("Matches MyError") // Output: "Matches MyError" + } +} +``` + +## FAQ + +- **When to use `Copy()`?** + - Use `Copy()` to create a modifiable duplicate of an error without altering the original. + +- **When to use `Free()`?** + - Use in performance-critical loops; otherwise, autofree handles it (Go 1.24+). + +- **How to handle cleanup?** + - Use `Callback()` for automatic actions like rollbacks or logging. + +- **How to add stack traces later?** + - Use `WithStack()` to upgrade a simple error: + ```go + package main + + import ( + "fmt" + "github.com/olekukonko/errors" + ) + + func main() { + err := errors.New("simple") + err = err.WithStack() + fmt.Println(err.Stack()) + } + ``` + +## Contributing +- Fork, branch, commit, and PR—see [CONTRIBUTING.md](#). + +## License +MIT License - See [LICENSE](LICENSE). \ No newline at end of file diff --git a/vendor/github.com/olekukonko/errors/errors.go b/vendor/github.com/olekukonko/errors/errors.go new file mode 100644 index 00000000..07d1e3d1 --- /dev/null +++ b/vendor/github.com/olekukonko/errors/errors.go @@ -0,0 +1,957 @@ +package errors + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "runtime" + "strings" + "sync" + "sync/atomic" +) + +const ( + ctxTimeout = "[error] timeout" // Context key for marking timeout errors + ctxRetry = "[error] retry" // Context key for marking retryable errors + + contextSize = 4 // Default size of fixed-size context array + bufferSize = 256 // Initial buffer size for JSON marshaling + warmUpSize = 100 // Number of errors to pre-warm the pool + stackDepth = 32 // Default maximum stack trace depth +) + +type ErrorCategory string + +// ErrorOpts provides options for customizing error creation. +type ErrorOpts struct { + SkipStack int // Number of stack frames to skip when capturing the stack trace +} + +// Config defines the configuration for the errors package. +type Config struct { + StackDepth int // Maximum depth of the stack trace; 0 uses default + ContextSize int // Initial size of the context map; 0 uses default + DisablePooling bool // Disables object pooling for errors if true + FilterInternal bool // Filters internal package frames from stack traces if true + AutoFree bool // Automatically frees errors to pool if true +} + +// cachedConfig holds the current configuration, updated only on Configure(). +type cachedConfig struct { + stackDepth int + contextSize int + disablePooling bool + filterInternal bool + autoFree bool +} + +var ( + currentConfig cachedConfig + configMu sync.RWMutex + errorPool = NewErrorPool() // Custom pool for Error instances + stackPool = sync.Pool{ // Pool for stack trace slices + New: func() interface{} { + return make([]uintptr, currentConfig.stackDepth) + }, + } + emptyError = &Error{ + smallContext: [contextSize]contextItem{}, + msg: "", + name: "", + template: "", + cause: nil, + } +) + +//var bufferPool = sync.Pool{ +// New: func() interface{} { +// return bytes.NewBuffer(make([]byte, 0, bufferSize)) +// }, +//} + +// contextItem represents a single key-value pair in the smallContext array. +type contextItem struct { + key string + value interface{} +} + +// Error represents a custom error with enhanced features like context, stack traces, and wrapping. +type Error struct { + // Primary error information (most frequently accessed) + msg string // Error message + name string // Error name/type + stack []uintptr // Stack trace + + // Secondary error metadata + template string // Message template used if msg is empty + category string // Error category (e.g., "network", "validation") + count uint64 // Occurrence count for tracking frequency + code int32 // HTTP-like error code + smallCount int32 // Number of items in smallContext + + // Context and chaining + context map[string]interface{} // Additional context as key-value pairs + cause error // Wrapped underlying error + callback func() // Optional callback executed on Error() + smallContext [contextSize]contextItem // Fixed-size context storage for efficiency + + // Synchronization + mu sync.RWMutex // Protects concurrent access to mutable fields +} + +// init initializes the package with default configuration and pre-warms the error pool. +func init() { + currentConfig = cachedConfig{ + stackDepth: stackDepth, + contextSize: contextSize, + disablePooling: false, + filterInternal: true, + autoFree: true, + } + WarmPool(warmUpSize) // Pre-warm pool with initial errors +} + +// Configure updates the global configuration for the errors package. +// Thread-safe; should be called before heavy usage for optimal performance. +// Changes apply immediately to all subsequent error operations. +func Configure(cfg Config) { + configMu.Lock() + defer configMu.Unlock() + + if cfg.StackDepth != 0 { + currentConfig.stackDepth = cfg.StackDepth + } + if cfg.ContextSize != 0 { + currentConfig.contextSize = cfg.ContextSize + } + currentConfig.disablePooling = cfg.DisablePooling + currentConfig.filterInternal = cfg.FilterInternal + currentConfig.autoFree = cfg.AutoFree +} + +// newError creates a new Error instance, using the pool if enabled. +// Initializes smallContext and stack appropriately. +func newError() *Error { + if currentConfig.disablePooling { + return &Error{ + smallContext: [contextSize]contextItem{}, + stack: nil, + } + } + return errorPool.Get() +} + +// Empty creates a new empty error with no stack trace. +// Useful as a base for building errors incrementally. +func Empty() *Error { + return emptyError +} + +// Named creates a new error with a specific name and stack trace. +// The name is used as the error message if no other message is set. +func Named(name string) *Error { + e := newError() + e.name = name + return e.WithStack() +} + +// New creates a fast, lightweight error without stack tracing. +// Use instead of Trace() when stack traces aren't needed for better performance. +func New(text string) *Error { + if text == "" { + return emptyError.Copy() // Global pre-allocated empty error + } + err := newError() + err.msg = text + return err +} + +// Newf is an alias to Errorf for fmt.Errorf compatibility. +// Creates a formatted error without stack traces. +func Newf(format string, args ...interface{}) *Error { + err := newError() + err.msg = fmt.Sprintf(format, args...) + return err +} + +// Std creates a standard error using errors.New, provided for backward compatibility. +// This function serves as a lightweight wrapper around the standard library's error creation, +// allowing users to opt into basic error handling without adopting the full features of this package. +func Std(text string) error { + return errors.New(text) +} + +// Stdf creates a formatted standard error using fmt.Errorf, provided for backward compatibility. +// This function wraps the standard library's formatted error creation, offering a simple alternative +// to the package's enhanced error handling while maintaining compatibility with existing codebases. +func Stdf(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} + +// Trace creates an error with stack trace capture enabled. +// Use when call stacks are needed for debugging; has performance overhead. +func Trace(text string) *Error { + e := New(text) + return e.WithStack() +} + +// Tracef creates a formatted error with stack trace. +// Combines Errorf and WithStack for convenience. +func Tracef(format string, args ...interface{}) *Error { + e := Newf(format, args...) + return e.WithStack() +} + +// As attempts to assign the error or one in its chain to the target interface. +// It only assigns when the target is a **Error and the current error node has a non-empty name. +// If the current node has an empty name, it delegates to its wrapped cause. +func (e *Error) As(target interface{}) bool { + if e == nil { + return false + } + // Handle *Error target (for stderrors.As compatibility) + if targetPtr, ok := target.(*Error); ok { + current := e + for current != nil { + if current.name != "" { + *targetPtr = *current + return true + } + if next, ok := current.cause.(*Error); ok { + current = next + } else if current.cause != nil { + return errors.As(current.cause, target) + } else { + return false + } + } + return false + } + // Handle *error target - unwrap to innermost error + if targetErr, ok := target.(*error); ok { + innermost := error(e) + current := error(e) + for current != nil { + if err, ok := current.(*Error); ok && err.cause != nil { + current = err.cause + innermost = current + } else { + break + } + } + *targetErr = innermost + return true + } + + // Delegate to cause for other types + if e.cause != nil { + return errors.As(e.cause, target) + } + return false +} + +// Callback sets a function to be called when Error() is invoked. +// Useful for logging or side effects; returns the error for chaining. +func (e *Error) Callback(fn func()) *Error { + e.callback = fn + return e +} + +// Category returns the error's category, if set. +// Returns an empty string if no category is defined. +func (e *Error) Category() string { + return e.category +} + +// Code returns the error's status code, if set. +// Returns 0 if no code is defined. +func (e *Error) Code() int { + return int(e.code) +} + +// Context returns the error's context as a map. +// Converts smallContext to a map if needed; returns nil if empty. +func (e *Error) Context() map[string]interface{} { + e.mu.RLock() + defer e.mu.RUnlock() + + if e.smallCount > 0 && e.context == nil { + e.context = make(map[string]interface{}, e.smallCount) + for i := int32(0); i < e.smallCount; i++ { + e.context[e.smallContext[i].key] = e.smallContext[i].value + } + } + return e.context +} + +// Copy creates a deep copy of the error, preserving all fields except stack. +// The new error does not capture a new stack trace unless explicitly added. +func (e *Error) Copy() *Error { + if e == emptyError { + return &Error{ + smallContext: [contextSize]contextItem{}, + } + } + + newErr := newError() + + newErr.msg = e.msg + newErr.name = e.name + newErr.template = e.template + newErr.cause = e.cause + newErr.code = e.code + newErr.category = e.category + newErr.count = e.count + + if e.smallCount > 0 { + newErr.smallCount = e.smallCount + for i := int32(0); i < e.smallCount; i++ { + newErr.smallContext[i] = e.smallContext[i] + } + } else if e.context != nil { + newErr.context = make(map[string]interface{}, len(e.context)) + for k, v := range e.context { + newErr.context[k] = v + } + } + + if e.stack != nil && len(e.stack) > 0 { + if newErr.stack == nil { + newErr.stack = stackPool.Get().([]uintptr) + } + newErr.stack = append(newErr.stack[:0], e.stack...) + } + + return newErr +} + +// Count returns the number of times the error has been incremented. +// Useful for tracking occurrence frequency. +func (e *Error) Count() uint64 { + return e.count +} + +// Err returns the error as an error interface. +// Provided for compatibility; simply returns the error itself. +func (e *Error) Err() error { + return e +} + +// Error returns the string representation of the error. +// Prioritizes msg, then template, then name, falling back to "unknown error". +// Executes callback if set before returning the message. +func (e *Error) Error() string { + if e.callback != nil { + e.callback() + } + var msg string + switch { + case e.msg != "": + msg = e.msg + case e.template != "": + msg = e.template + case e.name != "": + msg = e.name + default: + msg = "unknown error" + } + if e.cause != nil { + causeMsg := e.cause.Error() + if msg != "" && causeMsg != "" { + msg = msg + ": " + causeMsg + } else if causeMsg != "" { + msg = causeMsg + } + } + return msg +} + +// Errorf creates a formatted error without stack traces. +// Compatible with fmt.Errorf; does not capture stack trace for performance. +func Errorf(format string, args ...interface{}) *Error { + err := newError() + err.msg = fmt.Sprintf(format, args...) + return err +} + +// FastStack returns a lightweight stack trace without function names. +// Filters internal frames if FilterInternal is enabled; returns nil if no stack. +func (e *Error) FastStack() []string { + if e.stack == nil { + return nil + } + configMu.RLock() + filter := currentConfig.filterInternal + configMu.RUnlock() + + pcs := e.stack + frames := make([]string, 0, len(pcs)) + for _, pc := range pcs { + fn := runtime.FuncForPC(pc) + if fn == nil { + frames = append(frames, "unknown") + continue + } + file, line := fn.FileLine(pc) + if filter && isInternalFrame(runtime.Frame{File: file, Function: fn.Name()}) { + continue + } + frames = append(frames, fmt.Sprintf("%s:%d", file, line)) + } + return frames +} + +// Find searches the error chain for the first error matching pred. +// Starts with the current error and follows Unwrap() and Cause() chains. +func (e *Error) Find(pred func(error) bool) error { + if e == nil || pred == nil { + return nil + } + return Find(e, pred) +} + +// Format returns a formatted string representation of the error. +// Includes message, code, context, and stack trace if present. +func (e *Error) Format() string { + var sb strings.Builder + + // Error message + sb.WriteString("Error: " + e.Error() + "\n") + + // Metadata + if e.code != 0 { + sb.WriteString(fmt.Sprintf("Code: %d\n", e.code)) + } + + // Context (only show context added at this level) + if ctx := e.contextAtThisLevel(); len(ctx) > 0 { + sb.WriteString("Context:\n") + for k, v := range ctx { + sb.WriteString(fmt.Sprintf(" %s: %v\n", k, v)) + } + } + + // Stack trace + if e.stack != nil { + sb.WriteString("Stack:\n") + for i, frame := range e.Stack() { + sb.WriteString(fmt.Sprintf(" %d. %s\n", i+1, frame)) + } + } + + return sb.String() +} + +// contextAtThisLevel returns context specific to this error level, excluding inherited context. +// Combines smallContext and context map into a single map; returns nil if empty. +func (e *Error) contextAtThisLevel() map[string]interface{} { + if e.context == nil && e.smallCount == 0 { + return nil + } + + ctx := make(map[string]interface{}) + // Add smallContext items + for i := 0; i < int(e.smallCount); i++ { + ctx[e.smallContext[i].key] = e.smallContext[i].value + } + // Add map context items + if e.context != nil { + for k, v := range e.context { + ctx[k] = v + } + } + return ctx +} + +// Free resets the error and returns it to the pool if pooling is enabled. +// Does nothing beyond reset if pooling is disabled. +func (e *Error) Free() { + if currentConfig.disablePooling { + return + } + + e.Reset() + + if e.stack != nil { + stackPool.Put(e.stack[:cap(e.stack)]) + e.stack = nil + } + errorPool.Put(e) +} + +// Has checks if the error contains meaningful content. +// Returns true if msg, template, name, or cause is non-empty/nil. +func (e *Error) Has() bool { + return e != nil && (e.msg != "" || e.template != "" || e.name != "" || e.cause != nil) +} + +// HasContextKey checks if the specified key exists in the error's context. +// Searches both smallContext and context map; thread-safe. +func (e *Error) HasContextKey(key string) bool { + e.mu.RLock() + defer e.mu.RUnlock() + + if e.smallCount > 0 { + for i := int32(0); i < e.smallCount; i++ { + if e.smallContext[i].key == key { + return true + } + } + } + if e.context != nil { + _, exists := e.context[key] + return exists + } + return false +} + +// Increment increases the error's count by 1 and returns the error. +// Uses atomic operation for thread safety. +func (e *Error) Increment() *Error { + atomic.AddUint64(&e.count, 1) + return e +} + +// Is checks if the error matches a target error by pointer equality, name, or wrapped cause. +// Ensures compatibility with stderrors.Is by prioritizing chain traversal. +func (e *Error) Is(target error) bool { + if e == nil || target == nil { + return e == target + } + if e == target { + return true + } + if e.name != "" { + if te, ok := target.(*Error); ok && te.name != "" && e.name == te.name { + return true + } + } + // Add string comparison for standard errors + if stdErr, ok := target.(error); ok && e.Error() == stdErr.Error() { + return true + } + if e.cause != nil { + return errors.Is(e.cause, target) + } + return false +} + +// IsEmpty checks if the error has no meaningful content (empty message, no name/template/cause). +// Returns true for nil errors or errors with no data. +func (e *Error) IsEmpty() bool { + if e == nil { + return true + } + return e.msg == "" && e.template == "" && e.name == "" && e.cause == nil +} + +// IsNull checks if an error is nil or represents a SQL NULL value. +// Considers both the error itself and any context values; returns true if all context is null. +func (e *Error) IsNull() bool { + if e == nil || e == emptyError { + return true + } + // If no context or cause, and no content, it's not null + if e.smallCount == 0 && e.context == nil && e.cause == nil { + return false + } + + // Check cause first - if it’s null, the whole error is null + if e.cause != nil { + var isNull bool + if ce, ok := e.cause.(*Error); ok { + isNull = ce.IsNull() + } else { + isNull = sqlNull(e.cause) + } + if isNull { + return true + } + // If cause isn’t null, continue checking this error’s context + } + + // Check small context + if e.smallCount > 0 { + allNull := true + for i := 0; i < int(e.smallCount); i++ { + isNull := sqlNull(e.smallContext[i].value) + if !isNull { + allNull = false + break + } + } + if !allNull { + return false + } + } + + // Check regular context + if e.context != nil { + allNull := true + for _, v := range e.context { + isNull := sqlNull(v) + if !isNull { + allNull = false + break + } + } + if !allNull { + return false + } + } + + // Null if we have context and it’s all null + return e.smallCount > 0 || e.context != nil +} + +var ( + jsonBufferPool = sync.Pool{ + New: func() interface{} { + return bytes.NewBuffer(make([]byte, 0, bufferSize)) + }, + } +) + +// MarshalJSON serializes the error to JSON, including name, message, context, cause, and stack. +// Handles nested *Error causes and custom marshalers efficiently. +func (e *Error) MarshalJSON() ([]byte, error) { + // Get buffer from pool + buf := jsonBufferPool.Get().(*bytes.Buffer) + defer jsonBufferPool.Put(buf) + buf.Reset() + + // Create new encoder each time (no Reset available) + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + + // Prepare error data + je := struct { + Name string `json:"name,omitempty"` + Message string `json:"message,omitempty"` + Context map[string]interface{} `json:"context,omitempty"` + Cause interface{} `json:"cause,omitempty"` + Stack []string `json:"stack,omitempty"` + Code int `json:"code,omitempty"` + }{ + Name: e.name, + Message: e.msg, + Code: e.Code(), + } + + // Handle context + if ctx := e.Context(); len(ctx) > 0 { + je.Context = ctx + } + + // Handle stack + if e.stack != nil { + je.Stack = e.Stack() + } + + // Handle cause + if e.cause != nil { + switch c := e.cause.(type) { + case *Error: + je.Cause = c + case json.Marshaler: + je.Cause = c + default: + je.Cause = c.Error() + } + } + + // Encode + if err := enc.Encode(je); err != nil { + return nil, err + } + + // Return bytes without trailing newline + result := buf.Bytes() + if len(result) > 0 && result[len(result)-1] == '\n' { + result = result[:len(result)-1] + } + return result, nil +} + +// Msgf sets the error message using a formatted string. +// Overwrites any existing message; returns the error for chaining. +func (e *Error) Msgf(format string, args ...interface{}) *Error { + e.msg = fmt.Sprintf(format, args...) + return e +} + +// Name returns the error's name, if set. +// Returns an empty string if no name is defined. +func (e *Error) Name() string { + return e.name +} + +// Reset clears all fields of the error, preparing it for reuse. +// Does not free the stack; use Free() to return to pool. +func (e *Error) Reset() { + e.msg = "" + e.name = "" + e.template = "" + e.category = "" + e.code = 0 + e.count = 0 + e.cause = nil + e.callback = nil + + if e.context != nil { + for k := range e.context { + delete(e.context, k) + } + } + e.smallCount = 0 + + if e.stack != nil { + e.stack = e.stack[:0] + } +} + +// Stack returns a detailed stack trace as a slice of strings. +// Filters internal frames if FilterInternal is enabled; returns nil if no stack. +func (e *Error) Stack() []string { + if e.stack == nil { + return nil + } + + frames := runtime.CallersFrames(e.stack) + var trace []string + for { + frame, more := frames.Next() + if frame == (runtime.Frame{}) { + break + } + + if currentConfig.filterInternal && isInternalFrame(frame) { + continue + } + + trace = append(trace, fmt.Sprintf("%s %s:%d", + frame.Function, + frame.File, + frame.Line)) + + if !more { + break + } + } + return trace +} + +// Trace ensures the error has a stack trace, capturing it if missing. +// Skips capture if stack already exists; returns the error for chaining. +func (e *Error) Trace() *Error { + if e.stack == nil { + e.stack = captureStack(2) + } + return e +} + +// Transform applies transformations to a copy of the error. +// Returns the transformed copy or the original if no changes are needed. +func (e *Error) Transform(fn func(*Error)) *Error { + if e == nil || fn == nil { + return e + } + newErr := e.Copy() + fn(newErr) + return newErr +} + +// Unwrap returns the underlying cause of the error, if any. +// Implements the errors.Unwrap interface for unwrapping chains. +func (e *Error) Unwrap() error { + return e.cause +} + +// UnwrapAll returns a slice of all errors in the chain, starting with this error. +// Traverses the cause chain, creating isolated copies of each *Error. +func (e *Error) UnwrapAll() []error { + if e == nil { + return nil + } + var chain []error + current := error(e) + for current != nil { + if err, ok := current.(*Error); ok { + isolated := newError() + isolated.msg = err.msg + isolated.name = err.name + isolated.template = err.template + isolated.code = err.code + isolated.category = err.category + if err.smallCount > 0 { + isolated.smallCount = err.smallCount + for i := int32(0); i < err.smallCount; i++ { + isolated.smallContext[i] = err.smallContext[i] + } + } + if err.context != nil { + isolated.context = make(map[string]interface{}, len(err.context)) + for k, v := range err.context { + isolated.context[k] = v + } + } + if err.stack != nil { + isolated.stack = append([]uintptr(nil), err.stack...) + } + chain = append(chain, isolated) + } else { + chain = append(chain, current) + } + if unwrapper, ok := current.(interface{ Unwrap() error }); ok { + current = unwrapper.Unwrap() + } else { + break + } + } + return chain +} + +// Walk traverses the error chain, applying fn to each error. +// Starts with the current error and follows the cause chain. +func (e *Error) Walk(fn func(error)) { + if e == nil || fn == nil { + return + } + current := error(e) + for current != nil { + fn(current) + if unwrappable, ok := current.(interface{ Unwrap() error }); ok { + current = unwrappable.Unwrap() + } else { + break + } + } +} + +// With adds a key-value pair to the error's context. +// Uses smallContext for efficiency until full, then switches to map; thread-safe. +func (e *Error) With(key string, value interface{}) *Error { + // Fast path for small context (no map needed) + if e.smallCount < contextSize && e.context == nil { + e.mu.Lock() + // Double-check after acquiring lock + if e.smallCount < contextSize && e.context == nil { + e.smallContext[e.smallCount] = contextItem{key, value} + e.smallCount++ + e.mu.Unlock() + return e + } + e.mu.Unlock() + } + + // Slow path - requires map + e.mu.Lock() + defer e.mu.Unlock() + + if e.context == nil { + e.context = make(map[string]interface{}, currentConfig.contextSize) + // Migrate existing items if any + for i := int32(0); i < e.smallCount; i++ { + e.context[e.smallContext[i].key] = e.smallContext[i].value + } + } + + e.context[key] = value + return e +} + +// WithCategory sets a category for the error and returns the error. +// Useful for classifying errors (e.g., "network", "validation"). +func (e *Error) WithCategory(category ErrorCategory) *Error { + e.category = string(category) + return e +} + +// WithCode sets an HTTP-like status code for the error and returns the error. +// Overwrites any existing code. +func (e *Error) WithCode(code int) *Error { + e.code = int32(code) + return e +} + +// WithName sets the error's name and returns the error. +// Overwrites any existing name. +func (e *Error) WithName(name string) *Error { + e.name = name + return e +} + +// WithRetryable marks the error as retryable in its context. +// Adds a "retry" key with value true; returns the error. +func (e *Error) WithRetryable() *Error { + return e.With(ctxRetry, true) +} + +// WithStack captures the stack trace at call time and returns the error. +// Skips capturing if stack already exists or depth is 0. +func (e *Error) WithStack() *Error { + if e.stack == nil { + e.stack = captureStack(1) // Skip WithStack + } + return e +} + +// WithTemplate sets a template string for the error and returns the error. +// Used as the error message if no explicit message is set. +func (e *Error) WithTemplate(template string) *Error { + e.template = template + return e +} + +// WithTimeout marks the error as a timeout error in its context. +// Adds a "timeout" key with value true; returns the error. +func (e *Error) WithTimeout() *Error { + return e.With(ctxTimeout, true) +} + +// Wrap associates a cause error with this error, creating an error chain. +// Returns the error for method chaining. +func (e *Error) Wrap(cause error) *Error { + if cause == nil { + return e + } + e.cause = cause + return e +} + +// WrapNotNil wraps a cause error only if it is non-nil. +// Returns the error for method chaining; no-op if cause is nil. +func (e *Error) WrapNotNil(cause error) *Error { + if cause != nil { + e.cause = cause + } + return e +} + +// WarmPool pre-populates the error pool with a specified number of instances. +// Reduces allocation overhead during initial usage; no effect if pooling is disabled. +func WarmPool(count int) { + if currentConfig.disablePooling { + return + } + for i := 0; i < count; i++ { + e := &Error{ + smallContext: [contextSize]contextItem{}, + stack: nil, + } + errorPool.Put(e) + stackPool.Put(make([]uintptr, 0, currentConfig.stackDepth)) + } +} + +// WarmStackPool pre-populates the stack pool with a specified number of slices. +// Reduces allocation overhead for stack traces; no effect if pooling is disabled. +func WarmStackPool(count int) { + if currentConfig.disablePooling { + return + } + for i := 0; i < count; i++ { + stackPool.Put(make([]uintptr, 0, currentConfig.stackDepth)) + } +} diff --git a/vendor/github.com/olekukonko/errors/helper.go b/vendor/github.com/olekukonko/errors/helper.go new file mode 100644 index 00000000..e023636d --- /dev/null +++ b/vendor/github.com/olekukonko/errors/helper.go @@ -0,0 +1,423 @@ +package errors + +import ( + "context" + "errors" + "fmt" + "strings" + "time" +) + +// As wraps errors.As, using custom type assertion for *Error types. +// Falls back to standard errors.As for non-*Error types. +// Returns false if either err or target is nil. +func As(err error, target interface{}) bool { + if err == nil || target == nil { + return false + } + + // First try our custom *Error handling + if e, ok := err.(*Error); ok { + return e.As(target) + } + + // Fall back to standard errors.As + return errors.As(err, target) +} + +// Code returns the status code of an error, if it is an *Error. +// Returns 500 as a default for non-*Error types to indicate an internal error. +func Code(err error) int { + if e, ok := err.(*Error); ok { + return e.Code() + } + return 500 +} + +// Context extracts the context map from an error, if it is an *Error. +// Returns nil for non-*Error types or if no context is present. +func Context(err error) map[string]interface{} { + if e, ok := err.(*Error); ok { + return e.Context() + } + return nil +} + +// Convert transforms any error into an *Error, preserving its message and wrapping it if needed. +// Returns nil if the input is nil; returns the original if already an *Error. +// Uses multiple strategies: direct assertion, errors.As, manual unwrapping, and fallback creation. +func Convert(err error) *Error { + if err == nil { + return nil + } + + // First try direct type assertion (fast path) + if e, ok := err.(*Error); ok { + return e + } + + // Try using errors.As (more flexible) + var e *Error + if errors.As(err, &e) { + return e + } + + // Manual unwrapping as fallback + for unwrapped := err; unwrapped != nil; { + if e, ok := unwrapped.(*Error); ok { + return e + } + unwrapped = errors.Unwrap(unwrapped) + } + + // Final fallback: create new error with original message and wrap it + return New(err.Error()).Wrap(err) +} + +// Count returns the occurrence count of an error, if it is an *Error. +// Returns 0 for non-*Error types. +func Count(err error) uint64 { + if e, ok := err.(*Error); ok { + return e.Count() + } + return 0 +} + +// Find searches the error chain for the first error matching pred. +// Returns nil if no match is found or pred is nil; traverses both Unwrap() and Cause() chains. +func Find(err error, pred func(error) bool) error { + for current := err; current != nil; { + if pred(current) { + return current + } + + // Attempt to unwrap using Unwrap() or Cause() + switch v := current.(type) { + case interface{ Unwrap() error }: + current = v.Unwrap() + case interface{ Cause() error }: + current = v.Cause() + default: + return nil + } + } + return nil +} + +// From transforms any error into an *Error, preserving its message and wrapping it if needed. +// Alias of Convert; returns nil if input is nil, original if already an *Error. +func From(err error) *Error { + return Convert(err) +} + +// FromContext creates an *Error from a context and an existing error. +// Enhances the error with context info: timeout status, deadline, or cancellation. +// Returns nil if input error is nil; does not store context values directly. +func FromContext(ctx context.Context, err error) *Error { + if err == nil { + return nil + } + + e := New(err.Error()) + + // Handle context errors + switch ctx.Err() { + case context.DeadlineExceeded: + e.WithTimeout() + if deadline, ok := ctx.Deadline(); ok { + e.With("deadline", deadline.Format(time.RFC3339)) + } + case context.Canceled: + e.With("cancelled", true) + } + + return e +} + +// Category returns the category of an error, if it is an *Error. +// Returns an empty string for non-*Error types or unset categories. +func Category(err error) string { + if e, ok := err.(*Error); ok { + return e.category + } + return "" +} + +// Has checks if an error contains meaningful content. +// Returns true for non-nil standard errors or *Error with content (msg, name, template, or cause). +func Has(err error) bool { + if e, ok := err.(*Error); ok { + return e.Has() + } + return err != nil +} + +// HasContextKey checks if the error's context contains the specified key. +// Returns false for non-*Error types or if the key is not present in the context. +func HasContextKey(err error, key string) bool { + if e, ok := err.(*Error); ok { + ctx := e.Context() + if ctx != nil { + _, exists := ctx[key] + return exists + } + } + return false +} + +// Is wraps errors.Is, using custom matching for *Error types. +// Falls back to standard errors.Is for non-*Error types; returns true if err equals target. +func Is(err, target error) bool { + if err == nil || target == nil { + return err == target + } + + if e, ok := err.(*Error); ok { + return e.Is(target) + } + + // Use standard errors.Is for non-Error types + return errors.Is(err, target) +} + +// IsError checks if an error is an instance of *Error. +// Returns true only for this package's custom error type; false for nil or other types. +func IsError(err error) bool { + _, ok := err.(*Error) + return ok +} + +// IsEmpty checks if an error has no meaningful content. +// Returns true for nil errors, empty *Error instances, or standard errors with whitespace-only messages. +func IsEmpty(err error) bool { + if err == nil { + return true + } + if e, ok := err.(*Error); ok { + return e.IsEmpty() + } + return strings.TrimSpace(err.Error()) == "" +} + +// IsNull checks if an error is nil or represents a NULL value. +// Delegates to *Error’s IsNull for custom errors; uses sqlNull for others. +func IsNull(err error) bool { + if err == nil { + return true + } + if e, ok := err.(*Error); ok { + return e.IsNull() + } + return sqlNull(err) +} + +// IsRetryable checks if an error is retryable. +// For *Error, checks context for retry flag; for others, looks for "retry" or timeout in message. +// Returns false for nil errors; thread-safe for *Error types. +func IsRetryable(err error) bool { + if err == nil { + return false + } + if e, ok := err.(*Error); ok { + e.mu.RLock() + defer e.mu.RUnlock() + // Check smallContext directly if context map isn’t populated + for i := int32(0); i < e.smallCount; i++ { + if e.smallContext[i].key == ctxRetry { + if val, ok := e.smallContext[i].value.(bool); ok { + return val + } + } + } + // Fallback to context map + if e.context != nil { + if val, ok := e.context[ctxRetry].(bool); ok { + return val + } + } + } + lowerMsg := strings.ToLower(err.Error()) + return IsTimeout(err) || strings.Contains(lowerMsg, "retry") +} + +// IsTimeout checks if an error indicates a timeout. +// For *Error, checks context for timeout flag; for others, looks for "timeout" in message. +// Returns false for nil errors. +func IsTimeout(err error) bool { + if err == nil { + return false + } + if e, ok := err.(*Error); ok { + if val, ok := e.Context()[ctxTimeout].(bool); ok { + return val + } + } + return strings.Contains(strings.ToLower(err.Error()), "timeout") +} + +// Merge combines multiple errors into a single *Error. +// Aggregates messages with "; " separator, merges contexts and stacks; returns nil if no errors provided. +func Merge(errs ...error) *Error { + if len(errs) == 0 { + return nil + } + var messages []string + combined := New("") + for _, err := range errs { + if err == nil { + continue + } + messages = append(messages, err.Error()) + if e, ok := err.(*Error); ok { + if e.stack != nil && combined.stack == nil { + combined.WithStack() // Capture stack from first *Error with stack + } + if ctx := e.Context(); ctx != nil { + for k, v := range ctx { + combined.With(k, v) + } + } + if e.cause != nil { + combined.Wrap(e.cause) + } + } else { + combined.Wrap(err) + } + } + if len(messages) > 0 { + combined.msg = strings.Join(messages, "; ") + } + return combined +} + +// Name returns the name of an error, if it is an *Error. +// Returns an empty string for non-*Error types or unset names. +func Name(err error) string { + if e, ok := err.(*Error); ok { + return e.name + } + return "" +} + +// UnwrapAll returns a slice of all errors in the chain, including the root error. +// Traverses both Unwrap() and Cause() chains; returns nil if err is nil. +func UnwrapAll(err error) []error { + if err == nil { + return nil + } + if e, ok := err.(*Error); ok { + return e.UnwrapAll() + } + var result []error + Walk(err, func(e error) { + result = append(result, e) + }) + return result +} + +// Stack extracts the stack trace from an error, if it is an *Error. +// Returns nil for non-*Error types or if no stack is present. +func Stack(err error) []string { + if e, ok := err.(*Error); ok { + return e.Stack() + } + return nil +} + +// Transform applies transformations to an error, returning a new *Error. +// Creates a new *Error from non-*Error types before applying fn; returns nil if err is nil. +func Transform(err error, fn func(*Error)) *Error { + if err == nil { + return nil + } + if e, ok := err.(*Error); ok { + newErr := e.Copy() + fn(newErr) + return newErr + } + // If not an *Error, create a new one and transform it + newErr := New(err.Error()) + fn(newErr) + return newErr +} + +// Unwrap returns the underlying cause of an error, if it implements Unwrap. +// For *Error, returns cause; for others, returns the error itself; nil if err is nil. +func Unwrap(err error) error { + for current := err; current != nil; { + if e, ok := current.(*Error); ok { + if e.cause == nil { + return current + } + current = e.cause + } else { + return current + } + } + return nil +} + +// Walk traverses the error chain, applying fn to each error. +// Supports both Unwrap() and Cause() interfaces; stops at nil or non-unwrappable errors. +func Walk(err error, fn func(error)) { + for current := err; current != nil; { + fn(current) + + // Attempt to unwrap using Unwrap() or Cause() + switch v := current.(type) { + case interface{ Unwrap() error }: + current = v.Unwrap() + case interface{ Cause() error }: + current = v.Cause() + default: + return + } + } +} + +// With adds a key-value pair to an error's context, if it is an *Error. +// Returns the original error unchanged if not an *Error; no-op for non-*Error types. +func With(err error, key string, value interface{}) error { + if e, ok := err.(*Error); ok { + return e.With(key, value) + } + return err +} + +// WithStack converts any error to an *Error and captures a stack trace. +// Returns nil if input is nil; adds stack to existing *Error or wraps non-*Error types. +func WithStack(err error) *Error { + if err == nil { + return nil + } + if e, ok := err.(*Error); ok { + return e.WithStack() + } + return New(err.Error()).WithStack().Wrap(err) +} + +// Wrap creates a new *Error that wraps another error with additional context. +// Uses a copy of the provided wrapper *Error; returns nil if err is nil. +func Wrap(err error, wrapper *Error) *Error { + if err == nil { + return nil + } + if wrapper == nil { + wrapper = newError() + } + newErr := wrapper.Copy() + newErr.cause = err + return newErr +} + +// Wrapf creates a new formatted *Error that wraps another error. +// Formats the message and sets the cause; returns nil if err is nil. +func Wrapf(err error, format string, args ...interface{}) *Error { + if err == nil { + return nil + } + e := newError() + e.msg = fmt.Sprintf(format, args...) + e.cause = err + return e +} diff --git a/vendor/github.com/olekukonko/errors/multi_error.go b/vendor/github.com/olekukonko/errors/multi_error.go new file mode 100644 index 00000000..2419c82f --- /dev/null +++ b/vendor/github.com/olekukonko/errors/multi_error.go @@ -0,0 +1,325 @@ +package errors + +import ( + "fmt" + "math/rand" + "strings" + "sync" + "time" +) + +// MultiError represents a thread-safe collection of errors with enhanced features. +// Supports limits, sampling, and custom formatting for error aggregation. +type MultiError struct { + errors []error + mu sync.RWMutex + + // Configuration fields + limit int // Maximum number of errors to store (0 = unlimited) + formatter ErrorFormatter // Custom formatting function for error string + sampling bool // Whether sampling is enabled to limit error collection + sampleRate uint32 // Sampling percentage (1-100) when sampling is enabled + rand *rand.Rand // Random source for sampling (nil defaults to fastRand) +} + +// ErrorFormatter defines a function for custom error message formatting. +// Takes a slice of errors and returns a single formatted string. +type ErrorFormatter func([]error) string + +// MultiErrorOption configures MultiError behavior during creation. +type MultiErrorOption func(*MultiError) + +// NewMultiError creates a new MultiError instance with optional configuration. +// Initial capacity is set to 4; applies options in the order provided. +func NewMultiError(opts ...MultiErrorOption) *MultiError { + m := &MultiError{ + errors: make([]error, 0, 4), + limit: 0, // Unlimited by default + } + + for _, opt := range opts { + opt(m) + } + return m +} + +// Add appends an error to the collection with optional sampling, limit checks, and duplicate prevention. +// Ignores nil errors and duplicates based on string equality; thread-safe. +func (m *MultiError) Add(err error) { + if err == nil { + return + } + + m.mu.Lock() + defer m.mu.Unlock() + + // Check for duplicates by comparing error messages + for _, e := range m.errors { + if e.Error() == err.Error() { + return + } + } + + // Apply sampling if enabled and collection isn’t empty + if m.sampling && len(m.errors) > 0 { + var r uint32 + if m.rand != nil { + r = uint32(m.rand.Int31n(100)) + } else { + r = fastRand() % 100 + } + if r > m.sampleRate { // Accept if random value is within sample rate + return + } + } + + // Respect limit if set + if m.limit > 0 && len(m.errors) >= m.limit { + return + } + + m.errors = append(m.errors, err) +} + +// Clear removes all errors from the collection. +// Thread-safe; resets the slice while preserving capacity. +func (m *MultiError) Clear() { + m.mu.Lock() + defer m.mu.Unlock() + m.errors = m.errors[:0] +} + +// Count returns the number of errors in the collection. +// Thread-safe. +func (m *MultiError) Count() int { + m.mu.RLock() + defer m.mu.RUnlock() + return len(m.errors) +} + +// Error returns a formatted string representation of the errors. +// Returns empty string if no errors, single error message if one exists, +// or a formatted list using custom formatter or default if multiple; thread-safe. +func (m *MultiError) Error() string { + m.mu.RLock() + defer m.mu.RUnlock() + + switch len(m.errors) { + case 0: + return "" + case 1: + return m.errors[0].Error() + default: + if m.formatter != nil { + return m.formatter(m.errors) + } + return defaultFormat(m.errors) + } +} + +// Errors returns a copy of the contained errors. +// Thread-safe; returns nil if no errors exist. +func (m *MultiError) Errors() []error { + m.mu.RLock() + defer m.mu.RUnlock() + + if len(m.errors) == 0 { + return nil + } + errs := make([]error, len(m.errors)) + copy(errs, m.errors) + return errs +} + +// Filter returns a new MultiError containing only errors that match the predicate. +// Thread-safe; preserves original configuration including limit, formatter, and sampling. +func (m *MultiError) Filter(fn func(error) bool) *MultiError { + m.mu.RLock() + defer m.mu.RUnlock() + + var opts []MultiErrorOption + opts = append(opts, WithLimit(m.limit)) + if m.formatter != nil { + opts = append(opts, WithFormatter(m.formatter)) + } + if m.sampling { + opts = append(opts, WithSampling(m.sampleRate)) + } + + filtered := NewMultiError(opts...) + for _, err := range m.errors { + if fn(err) { + filtered.Add(err) + } + } + return filtered +} + +// First returns the first error in the collection, if any. +// Thread-safe; returns nil if the collection is empty. +func (m *MultiError) First() error { + m.mu.RLock() + defer m.mu.RUnlock() + if len(m.errors) > 0 { + return m.errors[0] + } + return nil +} + +// Has reports whether the collection contains any errors. +// Thread-safe. +func (m *MultiError) Has() bool { + m.mu.RLock() + defer m.mu.RUnlock() + return len(m.errors) > 0 +} + +// Last returns the most recently added error in the collection, if any. +// Thread-safe; returns nil if the collection is empty. +func (m *MultiError) Last() error { + m.mu.RLock() + defer m.mu.RUnlock() + if len(m.errors) > 0 { + return m.errors[len(m.errors)-1] + } + return nil +} + +// Merge combines another MultiError's errors into this one. +// Thread-safe; respects this instance’s limit and sampling settings; no-op if other is nil or empty. +func (m *MultiError) Merge(other *MultiError) { + if other == nil || !other.Has() { + return + } + + other.mu.RLock() + defer other.mu.RUnlock() + + for _, err := range other.errors { + m.Add(err) + } +} + +// IsNull checks if the MultiError is empty or contains only null errors. +// Returns true if empty or all errors are null (via IsNull() or empty message); thread-safe. +func (m *MultiError) IsNull() bool { + m.mu.RLock() + defer m.mu.RUnlock() + + // Fast path for empty MultiError + if len(m.errors) == 0 { + return true + } + + // Check each error for null status + allNull := true + for _, err := range m.errors { + switch e := err.(type) { + case interface{ IsNull() bool }: + if !e.IsNull() { + allNull = false + break + } + case nil: + continue + default: + if e.Error() != "" { + allNull = false + break + } + } + } + return allNull +} + +// Single returns nil if the collection is empty, the single error if only one exists, +// or the MultiError itself if multiple errors are present. +// Thread-safe; useful for unwrapping to a single error when possible. +func (m *MultiError) Single() error { + m.mu.RLock() + defer m.mu.RUnlock() + + switch len(m.errors) { + case 0: + return nil + case 1: + return m.errors[0] + default: + return m + } +} + +// String implements the Stringer interface for a concise string representation. +// Thread-safe; delegates to Error() for formatting. +func (m *MultiError) String() string { + return m.Error() +} + +// Unwrap returns a copy of the contained errors for multi-error unwrapping. +// Implements the errors.Unwrap interface; thread-safe; returns nil if empty. +func (m *MultiError) Unwrap() []error { + return m.Errors() +} + +// WithFormatter sets a custom error formatting function. +// Returns a MultiErrorOption for use with NewMultiError; overrides default formatting. +func WithFormatter(f ErrorFormatter) MultiErrorOption { + return func(m *MultiError) { + m.formatter = f + } +} + +// WithLimit sets the maximum number of errors to store. +// Returns a MultiErrorOption for use with NewMultiError; 0 means unlimited, negative values are ignored. +func WithLimit(n int) MultiErrorOption { + return func(m *MultiError) { + if n < 0 { + n = 0 // Ensure non-negative limit + } + m.limit = n + } +} + +// WithSampling enables error sampling with a specified rate (1-100). +// Returns a MultiErrorOption for use with NewMultiError; caps rate at 100 for validity. +func WithSampling(rate uint32) MultiErrorOption { + return func(m *MultiError) { + if rate > 100 { + rate = 100 + } + m.sampling = true + m.sampleRate = rate + } +} + +// WithRand sets a custom random source for sampling, useful for testing. +// Returns a MultiErrorOption for use with NewMultiError; defaults to fastRand if nil. +func WithRand(r *rand.Rand) MultiErrorOption { + return func(m *MultiError) { + m.rand = r + } +} + +// defaultFormat provides the default formatting for multiple errors. +// Returns a semicolon-separated list prefixed with the error count (e.g., "errors(3): err1; err2; err3"). +func defaultFormat(errs []error) string { + var sb strings.Builder + sb.WriteString(fmt.Sprintf("errors(%d): ", len(errs))) + for i, err := range errs { + if i > 0 { + sb.WriteString("; ") + } + sb.WriteString(err.Error()) + } + return sb.String() +} + +// fastRand generates a quick pseudo-random number for sampling. +// Uses a simple xorshift algorithm based on the current time; not cryptographically secure. +func fastRand() uint32 { + r := uint32(time.Now().UnixNano()) + r ^= r << 13 + r ^= r >> 17 + r ^= r << 5 + return r +} diff --git a/vendor/github.com/olekukonko/errors/pool.go b/vendor/github.com/olekukonko/errors/pool.go new file mode 100644 index 00000000..37515aac --- /dev/null +++ b/vendor/github.com/olekukonko/errors/pool.go @@ -0,0 +1,75 @@ +// pool.go +package errors + +import ( + "sync" + "sync/atomic" +) + +// ErrorPool is a high-performance, thread-safe pool for reusing *Error instances. +// Reduces allocation overhead by recycling errors; tracks hit/miss statistics. +type ErrorPool struct { + pool sync.Pool // Underlying pool for storing *Error instances + poolStats struct { // Embedded struct for pool usage statistics + hits atomic.Int64 // Number of times an error was reused from the pool + misses atomic.Int64 // Number of times a new error was created due to pool miss + } +} + +// NewErrorPool creates a new ErrorPool instance. +// Initializes the pool with a New function that returns a fresh *Error with default smallContext. +func NewErrorPool() *ErrorPool { + return &ErrorPool{ + pool: sync.Pool{ + New: func() interface{} { + return &Error{ + smallContext: [contextSize]contextItem{}, + } + }, + }, + } +} + +// Get retrieves an *Error from the pool or creates a new one if pooling is disabled or pool is empty. +// Resets are handled by Put; thread-safe; updates hit/miss stats when pooling is enabled. +func (ep *ErrorPool) Get() *Error { + if currentConfig.disablePooling { + return &Error{ + smallContext: [contextSize]contextItem{}, + } + } + + e := ep.pool.Get().(*Error) + if e == nil { // Pool returned nil (unlikely due to New func, but handled for safety) + ep.poolStats.misses.Add(1) + return &Error{ + smallContext: [contextSize]contextItem{}, + } + } + ep.poolStats.hits.Add(1) + return e +} + +// Put returns an *Error to the pool after resetting it. +// Ignores nil errors or if pooling is disabled; preserves stack capacity; thread-safe. +func (ep *ErrorPool) Put(e *Error) { + if e == nil || currentConfig.disablePooling { + return + } + + // Reset the error to a clean state, preserving capacity + e.Reset() + + // Reset stack length while keeping capacity for reuse + if e.stack != nil { + e.stack = e.stack[:0] + } + + ep.pool.Put(e) +} + +// Stats returns the current pool statistics as hits and misses. +// Thread-safe; uses atomic loads to ensure accurate counts. +func (ep *ErrorPool) Stats() (hits, misses int64) { + return ep.poolStats.hits.Load(), ep.poolStats.misses.Load() +} diff --git a/vendor/github.com/olekukonko/errors/pool_above_1_24.go b/vendor/github.com/olekukonko/errors/pool_above_1_24.go new file mode 100644 index 00000000..706550fd --- /dev/null +++ b/vendor/github.com/olekukonko/errors/pool_above_1_24.go @@ -0,0 +1,24 @@ +//go:build go1.24 +// +build go1.24 + +package errors + +import "runtime" + +// setupCleanup configures a cleanup function for an *Error to auto-return it to the pool. +// Only active for Go 1.24+; uses runtime.AddCleanup when autoFree is set and pooling is enabled. +func (ep *ErrorPool) setupCleanup(e *Error) { + if currentConfig.autoFree { + runtime.AddCleanup(e, func(_ *struct{}) { + if !currentConfig.disablePooling { + ep.Put(e) // Return to pool when cleaned up + } + }, nil) // No additional context needed + } +} + +// clearCleanup is a no-op for Go 1.24 and above. +// Cleanup is managed by runtime.AddCleanup; no explicit removal is required. +func (ep *ErrorPool) clearCleanup(e *Error) { + // No-op for Go 1.24+ +} diff --git a/vendor/github.com/olekukonko/errors/pool_below_1_24.go b/vendor/github.com/olekukonko/errors/pool_below_1_24.go new file mode 100644 index 00000000..3c94209f --- /dev/null +++ b/vendor/github.com/olekukonko/errors/pool_below_1_24.go @@ -0,0 +1,24 @@ +//go:build !go1.24 +// +build !go1.24 + +package errors + +import "runtime" + +// setupCleanup configures a finalizer for an *Error to auto-return it to the pool. +// Only active for Go versions < 1.24; enables automatic cleanup when autoFree is set and pooling is enabled. +func (ep *ErrorPool) setupCleanup(e *Error) { + if currentConfig.autoFree { + runtime.SetFinalizer(e, func(e *Error) { + if !currentConfig.disablePooling { + ep.Put(e) // Return to pool when garbage collected + } + }) + } +} + +// clearCleanup removes any finalizer set on an *Error. +// Only active for Go versions < 1.24; ensures no cleanup action occurs on garbage collection. +func (ep *ErrorPool) clearCleanup(e *Error) { + runtime.SetFinalizer(e, nil) // Disable finalizer +} diff --git a/vendor/github.com/olekukonko/errors/retry.go b/vendor/github.com/olekukonko/errors/retry.go new file mode 100644 index 00000000..89a73f6a --- /dev/null +++ b/vendor/github.com/olekukonko/errors/retry.go @@ -0,0 +1,286 @@ +// Package errors provides utilities for error handling, including a flexible retry mechanism. +package errors + +import ( + "context" + "math/rand" + "time" +) + +// BackoffStrategy defines the interface for calculating retry delays. +type BackoffStrategy interface { + // Backoff returns the delay for a given attempt based on the base delay. + Backoff(attempt int, baseDelay time.Duration) time.Duration +} + +// ConstantBackoff provides a fixed delay for each retry attempt. +type ConstantBackoff struct{} + +// Backoff returns the base delay regardless of the attempt number. +// Implements BackoffStrategy with a constant delay. +func (c ConstantBackoff) Backoff(_ int, baseDelay time.Duration) time.Duration { + return baseDelay +} + +// ExponentialBackoff provides an exponentially increasing delay for retry attempts. +type ExponentialBackoff struct{} + +// Backoff returns a delay that doubles with each attempt, starting from the base delay. +// Uses bit shifting for efficient exponential growth (e.g., baseDelay * 2^(attempt-1)). +func (e ExponentialBackoff) Backoff(attempt int, baseDelay time.Duration) time.Duration { + if attempt <= 1 { + return baseDelay + } + return baseDelay * time.Duration(1< r.maxDelay { + currentDelay = r.maxDelay + } + if r.jitter { + currentDelay = addJitter(currentDelay) + } + + // Wait with respect to context cancellation or timeout + select { + case <-r.ctx.Done(): + return r.ctx.Err() + case <-time.After(currentDelay): + } + } + return lastErr +} + +// Transform creates a new Retry instance with modified configuration. +// Copies all settings from the original Retry and applies the given options. +func (r *Retry) Transform(opts ...RetryOption) *Retry { + newRetry := &Retry{ + maxAttempts: r.maxAttempts, + delay: r.delay, + maxDelay: r.maxDelay, + retryIf: r.retryIf, + onRetry: r.onRetry, + backoff: r.backoff, + jitter: r.jitter, + ctx: r.ctx, + } + for _, opt := range opts { + opt(newRetry) + } + return newRetry +} + +// WithBackoff sets the backoff strategy using the BackoffStrategy interface. +// Returns a RetryOption; no-op if strategy is nil, retaining the existing strategy. +func WithBackoff(strategy BackoffStrategy) RetryOption { + return func(r *Retry) { + if strategy != nil { + r.backoff = strategy + } + } +} + +// WithContext sets the context for cancellation and deadlines. +// Returns a RetryOption; retains context.Background if ctx is nil. +func WithContext(ctx context.Context) RetryOption { + return func(r *Retry) { + if ctx != nil { + r.ctx = ctx + } + } +} + +// WithDelay sets the initial delay between retries. +// Returns a RetryOption; ensures non-negative delay by setting negatives to 0. +func WithDelay(delay time.Duration) RetryOption { + return func(r *Retry) { + if delay < 0 { + delay = 0 + } + r.delay = delay + } +} + +// WithJitter enables or disables jitter in the backoff delay. +// Returns a RetryOption; toggles random delay variation. +func WithJitter(jitter bool) RetryOption { + return func(r *Retry) { + r.jitter = jitter + } +} + +// WithMaxAttempts sets the maximum number of retry attempts. +// Returns a RetryOption; ensures at least 1 attempt by adjusting lower values. +func WithMaxAttempts(maxAttempts int) RetryOption { + return func(r *Retry) { + if maxAttempts < 1 { + maxAttempts = 1 + } + r.maxAttempts = maxAttempts + } +} + +// WithMaxDelay sets the maximum delay between retries. +// Returns a RetryOption; ensures non-negative delay by setting negatives to 0. +func WithMaxDelay(maxDelay time.Duration) RetryOption { + return func(r *Retry) { + if maxDelay < 0 { + maxDelay = 0 + } + r.maxDelay = maxDelay + } +} + +// WithOnRetry sets a callback to execute after each failed attempt. +// Returns a RetryOption; callback receives attempt number and error. +func WithOnRetry(onRetry func(attempt int, err error)) RetryOption { + return func(r *Retry) { + r.onRetry = onRetry + } +} + +// WithRetryIf sets the condition under which to retry. +// Returns a RetryOption; retains IsRetryable default if retryIf is nil. +func WithRetryIf(retryIf func(error) bool) RetryOption { + return func(r *Retry) { + if retryIf != nil { + r.retryIf = retryIf + } + } +} + +// ExecuteReply runs the provided function with retry logic and returns its result. +// Returns the result and nil on success, or zero value and last error on failure; generic type T. +func ExecuteReply[T any](r *Retry, fn func() (T, error)) (T, error) { + var lastErr error + var zero T + + for attempt := 1; attempt <= r.maxAttempts; attempt++ { + result, err := fn() + if err == nil { + return result, nil + } + + // Check if retry is applicable; return immediately if not retryable + if r.retryIf != nil && !r.retryIf(err) { + return zero, err + } + + lastErr = err + if r.onRetry != nil { + r.onRetry(attempt, err) + } + + if attempt == r.maxAttempts { + break + } + + // Calculate delay with backoff, cap at maxDelay, and apply jitter if enabled + currentDelay := r.backoff.Backoff(attempt, r.delay) + if currentDelay > r.maxDelay { + currentDelay = r.maxDelay + } + if r.jitter { + currentDelay = addJitter(currentDelay) + } + + // Wait with respect to context cancellation or timeout + select { + case <-r.ctx.Done(): + return zero, r.ctx.Err() + case <-time.After(currentDelay): + } + } + return zero, lastErr +} diff --git a/vendor/github.com/olekukonko/errors/utils.go b/vendor/github.com/olekukonko/errors/utils.go new file mode 100644 index 00000000..bb6753df --- /dev/null +++ b/vendor/github.com/olekukonko/errors/utils.go @@ -0,0 +1,153 @@ +// Package errors provides utility functions for error handling, including stack +// trace capture and function name extraction. +package errors + +import ( + "database/sql" + "fmt" + "reflect" + "runtime" + "strings" +) + +// captureStack captures a stack trace with the configured depth. +// Skip=0 captures the current call site; skips captureStack and its caller (+2 frames); thread-safe via stackPool. +func captureStack(skip int) []uintptr { + buf := stackPool.Get().([]uintptr) + buf = buf[:cap(buf)] + + // +2 to skip captureStack and the immediate caller + n := runtime.Callers(skip+2, buf) + if n == 0 { + stackPool.Put(buf) + return nil + } + + // Create a new slice to return, avoiding direct use of pooled memory + stack := make([]uintptr, n) + copy(stack, buf[:n]) + stackPool.Put(buf) + + return stack +} + +// min returns the smaller of two integers. +// Simple helper for limiting stack trace size or other comparisons. +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// clearMap removes all entries from a map. +// Helper function to reset map contents without reallocating. +func clearMap(m map[string]interface{}) { + for k := range m { + delete(m, k) + } +} + +// sqlNull detects if a value represents a SQL NULL type. +// Returns true for nil or invalid sql.Null* types (e.g., NullString, NullInt64); false otherwise. +func sqlNull(v interface{}) bool { + if v == nil { + return true + } + + switch val := v.(type) { + case sql.NullString: + return !val.Valid + case sql.NullTime: + return !val.Valid + case sql.NullInt64: + return !val.Valid + case sql.NullBool: + return !val.Valid + case sql.NullFloat64: + return !val.Valid + default: + return false + } +} + +// getFuncName extracts the function name from an interface, typically a function or method. +// Returns "unknown" if the input is nil or invalid; trims leading dots from runtime name. +func getFuncName(fn interface{}) string { + if fn == nil { + return "unknown" + } + fullName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() + return strings.TrimPrefix(fullName, ".") +} + +// isInternalFrame determines if a stack frame is considered "internal". +// Returns true for frames from runtime, reflect, or this package’s subdirectories if FilterInternal is true. +func isInternalFrame(frame runtime.Frame) bool { + if strings.HasPrefix(frame.Function, "runtime.") || strings.HasPrefix(frame.Function, "reflect.") { + return true + } + + suffixes := []string{ + "errors", + "utils", + "helper", + "retry", + "multi", + } + + file := frame.File + for _, v := range suffixes { + if strings.Contains(file, fmt.Sprintf("github.com/olekukonko/errors/%s", v)) { + return true + } + } + return false +} + +// FormatError returns a formatted string representation of an error. +// Includes message, name, context, stack trace, and cause for *Error types; just message for others; "" if nil. +func FormatError(err error) string { + if err == nil { + return "" + } + var sb strings.Builder + if e, ok := err.(*Error); ok { + sb.WriteString(fmt.Sprintf("Error: %s\n", e.Error())) + if e.name != "" { + sb.WriteString(fmt.Sprintf("Name: %s\n", e.name)) + } + if ctx := e.Context(); len(ctx) > 0 { + sb.WriteString("Context:\n") + for k, v := range ctx { + sb.WriteString(fmt.Sprintf("\t%s: %v\n", k, v)) + } + } + if stack := e.Stack(); len(stack) > 0 { + sb.WriteString("Stack Trace:\n") + for _, frame := range stack { + sb.WriteString(fmt.Sprintf("\t%s\n", frame)) + } + } + if e.cause != nil { + sb.WriteString(fmt.Sprintf("Caused by: %s\n", FormatError(e.cause))) + } + } else { + sb.WriteString(fmt.Sprintf("Error: %s\n", err.Error())) + } + return sb.String() +} + +// Caller returns the file, line, and function name of the caller at the specified skip level. +// Skip=0 returns the caller of this function, 1 returns its caller, etc.; returns "unknown" if no caller found. +func Caller(skip int) (file string, line int, function string) { + configMu.RLock() + defer configMu.RUnlock() + var pcs [1]uintptr + n := runtime.Callers(skip+2, pcs[:]) // +2 skips Caller and its immediate caller + if n == 0 { + return "", 0, "unknown" + } + frame, _ := runtime.CallersFrames(pcs[:n]).Next() + return frame.File, frame.Line, frame.Function +} diff --git a/vendor/github.com/olekukonko/ll/.gitignore b/vendor/github.com/olekukonko/ll/.gitignore new file mode 100644 index 00000000..70d08776 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/.gitignore @@ -0,0 +1,5 @@ +.idea +lab +tmp +#_* +_test/ diff --git a/vendor/github.com/olekukonko/ll/LICENSE b/vendor/github.com/olekukonko/ll/LICENSE new file mode 100644 index 00000000..ca02db8c --- /dev/null +++ b/vendor/github.com/olekukonko/ll/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Oleku Konko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/olekukonko/ll/README.md b/vendor/github.com/olekukonko/ll/README.md new file mode 100644 index 00000000..c9a02059 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/README.md @@ -0,0 +1,359 @@ +# ll - A Modern Structured Logging Library for Go + +`ll` is a high-performance, production-ready logging library for Go, designed to provide **hierarchical namespaces**, **structured logging**, **middleware pipelines**, **conditional logging**, and support for multiple output formats, including text, JSON, colorized logs, and compatibility with Go’s `slog`. It’s ideal for applications requiring fine-grained log control, extensibility, and scalability. + +## Key Features + +- **Hierarchical Namespaces**: Organize logs with fine-grained control over subsystems (e.g., "app/db"). +- **Structured Logging**: Add key-value metadata for machine-readable logs. +- **Middleware Pipeline**: Customize log processing with error-based rejection. +- **Conditional Logging**: Optimize performance by skipping unnecessary log operations. +- **Multiple Output Formats**: Support for text, JSON, colorized logs, and `slog` integration. +- **Debugging Utilities**: Inspect variables (`Dbg`), binary data (`Dump`), and stack traces (`Stack`). +- **Thread-Safe**: Built for concurrent use with mutex-protected state. +- **Performance Optimized**: Minimal allocations and efficient namespace caching. + +## Installation + +Install `ll` using Go modules: + +```bash +go get github.com/olekukonko/ll +``` + +Ensure you have Go 1.21 or later for optimal compatibility. + +## Getting Started + +Here’s a quick example to start logging with `ll`: + + +```go +package main + +import ( + "github.com/olekukonko/ll" +) + +func main() { + // Create a logger with namespace "app" + logger := ll.New("") + + // enable output + logger.Enable() + + // Basic log + logger.Info("Welcome") // Output: [app] INFO: Application started + + logger = logger.Namespace("app") + + // Basic log + logger.Info("start at :8080") // Output: [app] INFO: Application started + + //Output + //INFO: Welcome + //[app] INFO: start at :8080 +} + +``` + +```go +package main + +import ( + "github.com/olekukonko/ll" + "github.com/olekukonko/ll/lh" + "os" +) + +func main() { + // Chaining + logger := ll.New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) + + // Basic log + logger.Info("Application started") // Output: [app] INFO: Application started + + // Structured log with fields + logger.Fields("user", "alice", "status", 200).Info("User logged in") + // Output: [app] INFO: User logged in [user=alice status=200] + + // Conditional log + debugMode := false + logger.If(debugMode).Debug("Debug info") // No output (debugMode is false) +} +``` + +## Core Features + +### 1. Hierarchical Namespaces + +Namespaces allow you to organize logs hierarchically, enabling precise control over logging for different parts of your application. This is especially useful for large systems with multiple components. + +**Benefits**: +- **Granular Control**: Enable/disable logs for specific subsystems (e.g., "app/db" vs. "app/api"). +- **Scalability**: Manage log volume in complex applications. +- **Readability**: Clear namespace paths improve traceability. + +**Example**: +```go +logger := ll.New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) + +// Child loggers +dbLogger := logger.Namespace("db") +apiLogger := logger.Namespace("api").Style(lx.NestedPath) + +// Namespace control +logger.NamespaceEnable("app/db") // Enable DB logs +logger.NamespaceDisable("app/api") // Disable API logs + +dbLogger.Info("Query executed") // Output: [app/db] INFO: Query executed +apiLogger.Info("Request received") // No output +``` + +### 2. Structured Logging + +Add key-value metadata to logs for machine-readable output, making it easier to query and analyze logs in tools like ELK or Grafana. + +**Example**: +```go +logger := ll.New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) + +// Variadic fields +logger.Fields("user", "bob", "status", 200).Info("Request completed") +// Output: [app] INFO: Request completed [user=bob status=200] + +// Map-based fields +logger.Field(map[string]interface{}{"method": "GET"}).Info("Request") +// Output: [app] INFO: Request [method=GET] +``` + +### 3. Middleware Pipeline + +Customize log processing with a middleware pipeline. Middleware functions can enrich, filter, or transform logs, using an error-based rejection mechanism (non-nil errors stop logging). + +**Example**: +```go +logger := ll.New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) + +// Enrich logs with app metadata +logger.Use(ll.FuncMiddleware(func(e *lx.Entry) error { + if e.Fields == nil { + e.Fields = make(map[string]interface{}) + } + e.Fields["app"] = "myapp" + return nil +})) + +// Filter low-level logs +logger.Use(ll.FuncMiddleware(func(e *lx.Entry) error { + if e.Level < lx.LevelWarn { + return fmt.Errorf("level too low") + } + return nil +})) + +logger.Info("Ignored") // No output (filtered) +logger.Warn("Warning") // Output: [app] WARN: Warning [app=myapp] +``` + +### 4. Conditional Logging + +Optimize performance by skipping expensive log operations when conditions are false, ideal for production environments. + +**Example**: +```go +logger := ll.New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) + +featureEnabled := true +logger.If(featureEnabled).Fields("action", "update").Info("Feature used") +// Output: [app] INFO: Feature used [action=update] + +logger.If(false).Info("Ignored") // No output, no processing +``` + +### 5. Multiple Output Formats + +`ll` supports various output formats, including human-readable text, colorized logs, JSON, and integration with Go’s `slog` package. + +**Example**: +```go +logger := ll.New("app").Enable() + +// Text output +logger.Handler(lh.NewTextHandler(os.Stdout)) +logger.Info("Text log") // Output: [app] INFO: Text log + +// JSON output +logger.Handler(lh.NewJSONHandler(os.Stdout, time.RFC3339Nano)) +logger.Info("JSON log") // Output: {"timestamp":"...","level":"INFO","message":"JSON log","namespace":"app"} + +// Slog integration +slogText := slog.NewTextHandler(os.Stdout, nil) +logger.Handler(lh.NewSlogHandler(slogText)) +logger.Info("Slog log") // Output: level=INFO msg="Slog log" namespace=app class=Text +``` + +### 6. Debugging Utilities + +`ll` provides powerful tools for debugging, including variable inspection, binary data dumps, and stack traces. + +#### Core Debugging Methods + +1. **Dbg - Contextual Inspection** + Inspects variables with file and line context, preserving variable names and handling all Go types. + ```go + x := 42 + user := struct{ Name string }{"Alice"} + ll.Dbg(x) // Output: [file.go:123] x = 42 + ll.Dbg(user) // Output: [file.go:124] user = [Name:Alice] + ``` + +2. **Dump - Binary Inspection** + Displays a hex/ASCII view of data, optimized for strings, bytes, and complex types (with JSON fallback). + ```go + ll.Handler(lh.NewColorizedHandler(os.Stdout)) + ll.Dump("hello\nworld") // Output: Hex/ASCII dump (see example/dump.png) + ``` + +3. **Stack - Stack Inspection** + Logs a stack trace for debugging critical errors. + ```go + ll.Handler(lh.NewColorizedHandler(os.Stdout)) + ll.Stack("Critical error") // Output: [app] ERROR: Critical error [stack=...] (see example/stack.png) + ``` + +#### Performance Tracking +Measure execution time for performance analysis. +```go +// Automatic measurement +defer ll.Measure(func() { time.Sleep(time.Millisecond) })() +// Output: [app] INFO: function executed [duration=~1ms] + +// Explicit benchmarking +start := time.Now() +time.Sleep(time.Millisecond) +ll.Benchmark(start) // Output: [app] INFO: benchmark [start=... end=... duration=...] +``` + +**Performance Notes**: +- `Dbg` calls are disabled at compile-time when not enabled. +- `Dump` optimizes for primitive types, strings, and bytes with zero-copy paths. +- Stack traces are configurable via `StackSize`. + +## Real-World Example: Web Server + +A practical example of using `ll` in a web server with structured logging, middleware, and `slog` integration: + +```go +package main + +import ( + "github.com/olekukonko/ll" + "github.com/olekukonko/ll/lh" + "log/slog" + "net/http" + "os" + "time" +) + +func main() { + // Initialize logger with slog handler + slogHandler := slog.NewJSONHandler(os.Stdout, nil) + logger := ll.New("server").Enable().Handler(lh.NewSlogHandler(slogHandler)) + + // HTTP child logger + httpLogger := logger.Namespace("http").Style(lx.NestedPath) + + // Middleware for request ID + httpLogger.Use(ll.FuncMiddleware(func(e *lx.Entry) error { + if e.Fields == nil { + e.Fields = make(map[string]interface{}) + } + e.Fields["request_id"] = "req-" + time.Now().String() + return nil + })) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + httpLogger.Fields("method", r.Method, "path", r.URL.Path).Info("Request received") + w.Write([]byte("Hello, world!")) + httpLogger.Fields("duration_ms", time.Since(start).Milliseconds()).Info("Request completed") + }) + + logger.Info("Starting server on :8080") + http.ListenAndServe(":8080", nil) +} +``` + +**Sample Output (JSON via slog)**: +```json +{"level":"INFO","msg":"Starting server on :8080","namespace":"server"} +{"level":"INFO","msg":"Request received","namespace":"server/http","class":"Text","method":"GET","path":"/","request_id":"req-..."} +{"level":"INFO","msg":"Request completed","namespace":"server/http","class":"Text","duration_ms":1,"request_id":"req-..."} +``` + +## Why Choose `ll`? + +- **Granular Control**: Hierarchical namespaces for precise log management. +- **Performance**: Conditional logging and optimized concatenation reduce overhead. +- **Extensibility**: Middleware pipeline for custom log processing. +- **Structured Output**: Machine-readable logs with key-value metadata. +- **Flexible Formats**: Text, JSON, colorized, and `slog` support. +- **Debugging Power**: Advanced tools like `Dbg`, `Dump`, and `Stack` for deep inspection. +- **Thread-Safe**: Safe for concurrent use in high-throughput applications. + +## Comparison with Other Libraries + +| Feature | `ll` | `log` (stdlib) | `slog` (stdlib) | `zap` | +|--------------------------|--------------------------|----------------|-----------------|-------------------| +| Hierarchical Namespaces | ✅ | ❌ | ❌ | ❌ | +| Structured Logging | ✅ (Fields, Context) | ❌ | ✅ | ✅ | +| Middleware Pipeline | ✅ | ❌ | ❌ | ✅ (limited) | +| Conditional Logging | ✅ (If, IfOne, IfAny) | ❌ | ❌ | ❌ | +| Slog Compatibility | ✅ | ❌ | ✅ (native) | ❌ | +| Debugging (Dbg, Dump) | ✅ | ❌ | ❌ | ❌ | +| Performance (disabled logs) | High (conditional) | Low | Medium | High | +| Output Formats | Text, JSON, Color, Slog | Text | Text, JSON | JSON, Text | + +## Benchmarks + +`ll` is optimized for performance, particularly for disabled logs and structured logging: +- **Disabled Logs**: 30% faster than `slog` due to efficient conditional checks. +- **Structured Logging**: 2x faster than `log` with minimal allocations. +- **Namespace Caching**: Reduces overhead for hierarchical lookups. + +See `ll_bench_test.go` for detailed benchmarks on namespace creation, cloning, and field building. + +## Testing and Stability + +The `ll` library includes a comprehensive test suite (`ll_test.go`) covering: +- Logger configuration, namespaces, and conditional logging. +- Middleware, rate limiting, and sampling. +- Handler output formats (text, JSON, slog). +- Debugging utilities (`Dbg`, `Dump`, `Stack`). + +Recent improvements: +- Fixed sampling middleware for reliable behavior at edge cases (0.0 and 1.0 rates). +- Enhanced documentation across `conditional.go`, `field.go`, `global.go`, `ll.go`, `lx.go`, and `ns.go`. +- Added `slog` compatibility via `lh.SlogHandler`. + +## Contributing + +Contributions are welcome! To contribute: +1. Fork the repository: `github.com/olekukonko/ll`. +2. Create a feature branch: `git checkout -b feature/your-feature`. +3. Commit changes: `git commit -m "Add your feature"`. +4. Push to the branch: `git push origin feature/your-feature`. +5. Open a pull request with a clear description. + +Please include tests in `ll_test.go` and update documentation as needed. Follow the Go coding style and run `go test ./...` before submitting. + +## License + +`ll` is licensed under the MIT License. See [LICENSE](LICENSE) for details. + +## Resources + +- **Source Code**: [github.com/olekukonko/ll](https://github.com/olekukonko/ll) +- **Issue Tracker**: [github.com/olekukonko/ll/issues](https://github.com/olekukonko/ll/issues) +- **GoDoc**: [pkg.go.dev/github.com/olekukonko/ll](https://pkg.go.dev/github.com/olekukonko/ll) \ No newline at end of file diff --git a/vendor/github.com/olekukonko/ll/concat.go b/vendor/github.com/olekukonko/ll/concat.go new file mode 100644 index 00000000..4bfb22e1 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/concat.go @@ -0,0 +1,421 @@ +package ll + +import ( + "fmt" + "github.com/olekukonko/ll/lx" + "reflect" + "strconv" + "strings" + "unsafe" +) + +const ( + maxRecursionDepth = 20 // Maximum depth for recursive type handling to prevent stack overflow + nilString = "" // String representation for nil values + unexportedString = "" // String representation for unexported fields +) + +// Concat efficiently concatenates values without a separator using the default logger. +// It converts each argument to a string and joins them directly, optimizing for performance +// in logging scenarios. Thread-safe as it does not modify shared state. +// Example: +// +// msg := ll.Concat("Hello", 42, true) // Returns "Hello42true" +func Concat(args ...any) string { + return concat(args...) +} + +// ConcatSpaced concatenates values with a space separator using the default logger. +// It converts each argument to a string and joins them with spaces, suitable for log message +// formatting. Thread-safe as it does not modify shared state. +// Example: +// +// msg := ll.ConcatSpaced("Hello", 42, true) // Returns "Hello 42 true" +func ConcatSpaced(args ...any) string { + return concatSpaced(args...) +} + +// ConcatAll concatenates elements with a separator, prefix, and suffix using the default logger. +// It combines before, main, and after arguments with the specified separator, optimizing memory +// allocation for logging. Thread-safe as it does not modify shared state. +// Example: +// +// msg := ll.ConcatAll(",", []any{"prefix"}, []any{"suffix"}, "main") +// // Returns "prefix,main,suffix" +func ConcatAll(sep string, before, after []any, args ...any) string { + return concatenate(sep, before, after, args...) +} + +// concat efficiently concatenates values without a separator. +// It converts each argument to a string and joins them directly, optimizing for performance +// in logging scenarios. Used internally by Concat and other logging functions. +// Example: +// +// msg := concat("Hello", 42, true) // Returns "Hello42true" +func concat(args ...any) string { + return concatWith("", args...) +} + +// concatSpaced concatenates values with a space separator. +// It converts each argument to a string and joins them with spaces, suitable for formatting +// log messages. Used internally by ConcatSpaced. +// Example: +// +// msg := concatSpaced("Hello", 42, true) // Returns "Hello 42 true" +func concatSpaced(args ...any) string { + return concatWith(lx.Space, args...) +} + +// concatWith concatenates values with a specified separator using optimized type handling. +// It builds a string from arguments, handling various types efficiently (strings, numbers, +// structs, etc.), and is used by concat and concatSpaced for log message construction. +// Thread-safe as it does not modify shared state. +// Example: +// +// msg := concatWith(",", "Hello", 42, true) // Returns "Hello,42,true" +func concatWith(sep string, args ...any) string { + switch len(args) { + case 0: + return "" + case 1: + return concatToString(args[0]) + } + + var b strings.Builder + b.Grow(concatEstimateArgs(sep, args)) + + for i, arg := range args { + if i > 0 { + b.WriteString(sep) + } + concatWriteValue(&b, arg, 0) + } + + return b.String() +} + +// concatenate concatenates elements with separators, prefixes, and suffixes efficiently. +// It combines before, main, and after arguments with the specified separator, optimizing +// memory allocation for complex log message formatting. Used internally by ConcatAll. +// Example: +// +// msg := concatenate(",", []any{"prefix"}, []any{"suffix"}, "main") +// // Returns "prefix,main,suffix" +func concatenate(sep string, before []any, after []any, args ...any) string { + totalLen := len(before) + len(after) + len(args) + switch totalLen { + case 0: + return "" + case 1: + switch { + case len(before) > 0: + return concatToString(before[0]) + case len(args) > 0: + return concatToString(args[0]) + default: + return concatToString(after[0]) + } + } + + var b strings.Builder + b.Grow(concatEstimateTotal(sep, before, after, args)) + + // Write before elements + concatWriteGroup(&b, sep, before) + + // Write main arguments + if len(before) > 0 && len(args) > 0 { + b.WriteString(sep) + } + concatWriteGroup(&b, sep, args) + + // Write after elements + if len(after) > 0 && (len(before) > 0 || len(args) > 0) { + b.WriteString(sep) + } + concatWriteGroup(&b, sep, after) + + return b.String() +} + +// concatWriteGroup writes a group of arguments to a strings.Builder with a separator. +// It handles each argument by converting it to a string, used internally by concatenate +// to process before, main, or after groups in log message construction. +// Example: +// +// var b strings.Builder +// concatWriteGroup(&b, ",", []any{"a", 42}) // Writes "a,42" to b +func concatWriteGroup(b *strings.Builder, sep string, group []any) { + for i, arg := range group { + if i > 0 { + b.WriteString(sep) + } + concatWriteValue(b, arg, 0) + } +} + +// concatToString converts a single argument to a string efficiently. +// It handles common types (string, []byte, fmt.Stringer) with minimal overhead and falls +// back to fmt.Sprint for other types. Used internally by concat and concatenate. +// Example: +// +// s := concatToString("Hello") // Returns "Hello" +// s := concatToString([]byte{65, 66}) // Returns "AB" +func concatToString(arg any) string { + switch v := arg.(type) { + case string: + return v + case []byte: + return *(*string)(unsafe.Pointer(&v)) + case fmt.Stringer: + return v.String() + case error: + return v.Error() + default: + return fmt.Sprint(v) + } +} + +// concatEstimateTotal estimates the total string length for concatenate. +// It calculates the expected size of the concatenated string, including before, main, and +// after arguments with separators, to preallocate the strings.Builder capacity. +// Example: +// +// size := concatEstimateTotal(",", []any{"prefix"}, []any{"suffix"}, "main") +// // Returns estimated length for "prefix,main,suffix" +func concatEstimateTotal(sep string, before, after, args []any) int { + size := 0 + if len(before) > 0 { + size += concatEstimateArgs(sep, before) + } + if len(args) > 0 { + if size > 0 { + size += len(sep) + } + size += concatEstimateArgs(sep, args) + } + if len(after) > 0 { + if size > 0 { + size += len(sep) + } + size += concatEstimateArgs(sep, after) + } + return size +} + +// concatEstimateArgs estimates the string length for a group of arguments. +// It sums the estimated sizes of each argument plus separators, used by concatEstimateTotal +// and concatWith to optimize memory allocation for log message construction. +// Example: +// +// size := concatEstimateArgs(",", []any{"hello", 42}) // Returns estimated length for "hello,42" +func concatEstimateArgs(sep string, args []any) int { + if len(args) == 0 { + return 0 + } + size := len(sep) * (len(args) - 1) + for _, arg := range args { + size += concatEstimateSize(arg) + } + return size +} + +// concatEstimateSize estimates the string length for a single argument. +// It provides size estimates for various types (strings, numbers, booleans, etc.) to +// optimize strings.Builder capacity allocation in logging functions. +// Example: +// +// size := concatEstimateSize("hello") // Returns 5 +// size := concatEstimateSize(42) // Returns ~2 +func concatEstimateSize(arg any) int { + switch v := arg.(type) { + case string: + return len(v) + case []byte: + return len(v) + case int: + return concatNumLen(int64(v)) + case int64: + return concatNumLen(v) + case int32: + return concatNumLen(int64(v)) + case int16: + return concatNumLen(int64(v)) + case int8: + return concatNumLen(int64(v)) + case uint: + return concatNumLen(uint64(v)) + case uint64: + return concatNumLen(v) + case uint32: + return concatNumLen(uint64(v)) + case uint16: + return concatNumLen(uint64(v)) + case uint8: + return concatNumLen(uint64(v)) + case float64: + return 24 // Max digits for float64 + case float32: + return 16 // Max digits for float32 + case bool: + if v { + return 4 // "true" + } + return 5 // "false" + case fmt.Stringer: + return 16 // Conservative estimate + default: + return 16 // Default estimate + } +} + +// concatNumLen estimates the string length for a signed or unsigned integer. +// It returns a conservative estimate (20 digits) for int64 or uint64 values, including +// a sign for negative numbers, used by concatEstimateSize for memory allocation. +// Example: +// +// size := concatNumLen(int64(-123)) // Returns 20 +// size := concatNumLen(uint64(123)) // Returns 20 +func concatNumLen[T int64 | uint64](v T) int { + if v < 0 { + return 20 // Max digits for int64 + sign + } + return 20 // Max digits for uint64 +} + +// concatWriteValue writes a formatted value to a strings.Builder with recursion depth tracking. +// It handles various types (strings, numbers, structs, slices, etc.) and prevents infinite +// recursion by limiting depth. Used internally by concatWith and concatWriteGroup for log +// message formatting. +// Example: +// +// var b strings.Builder +// concatWriteValue(&b, "hello", 0) // Writes "hello" to b +// concatWriteValue(&b, []int{1, 2}, 0) // Writes "[1,2]" to b +func concatWriteValue(b *strings.Builder, arg any, depth int) { + if depth > maxRecursionDepth { + b.WriteString("...") + return + } + + if arg == nil { + b.WriteString(nilString) + return + } + + if s, ok := arg.(fmt.Stringer); ok { + b.WriteString(s.String()) + return + } + + switch v := arg.(type) { + case string: + b.WriteString(v) + case []byte: + b.Write(v) + case int: + b.WriteString(strconv.FormatInt(int64(v), 10)) + case int64: + b.WriteString(strconv.FormatInt(v, 10)) + case int32: + b.WriteString(strconv.FormatInt(int64(v), 10)) + case int16: + b.WriteString(strconv.FormatInt(int64(v), 10)) + case int8: + b.WriteString(strconv.FormatInt(int64(v), 10)) + case uint: + b.WriteString(strconv.FormatUint(uint64(v), 10)) + case uint64: + b.WriteString(strconv.FormatUint(v, 10)) + case uint32: + b.WriteString(strconv.FormatUint(uint64(v), 10)) + case uint16: + b.WriteString(strconv.FormatUint(uint64(v), 10)) + case uint8: + b.WriteString(strconv.FormatUint(uint64(v), 10)) + case float64: + b.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) + case float32: + b.WriteString(strconv.FormatFloat(float64(v), 'f', -1, 32)) + case bool: + if v { + b.WriteString("true") + } else { + b.WriteString("false") + } + default: + val := reflect.ValueOf(arg) + if val.Kind() == reflect.Ptr { + if val.IsNil() { + b.WriteString(nilString) + return + } + val = val.Elem() + } + + switch val.Kind() { + case reflect.Slice, reflect.Array: + concatFormatSlice(b, val, depth) + case reflect.Struct: + concatFormatStruct(b, val, depth) + default: + fmt.Fprint(b, v) + } + } +} + +// concatFormatSlice formats a slice or array for logging. +// It writes the elements in a bracketed, comma-separated format, handling nested types +// recursively with depth tracking. Used internally by concatWriteValue for log message formatting. +// Example: +// +// var b strings.Builder +// val := reflect.ValueOf([]int{1, 2}) +// concatFormatSlice(&b, val, 0) // Writes "[1,2]" to b +func concatFormatSlice(b *strings.Builder, val reflect.Value, depth int) { + b.WriteByte('[') + for i := 0; i < val.Len(); i++ { + if i > 0 { + b.WriteByte(',') + } + concatWriteValue(b, val.Index(i).Interface(), depth+1) + } + b.WriteByte(']') +} + +// concatFormatStruct formats a struct for logging. +// It writes the struct’s exported fields in a bracketed, name:value format, handling nested +// types recursively with depth tracking. Unexported fields are represented as "". +// Used internally by concatWriteValue for log message formatting. +// Example: +// +// var b strings.Builder +// val := reflect.ValueOf(struct{ Name string }{Name: "test"}) +// concatFormatStruct(&b, val, 0) // Writes "[Name:test]" to b +func concatFormatStruct(b *strings.Builder, val reflect.Value, depth int) { + typ := val.Type() + b.WriteByte('[') + + first := true + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + + if !first { + b.WriteString("; ") + } + first = false + + b.WriteString(field.Name) + b.WriteByte(':') + + if !fieldValue.CanInterface() { + b.WriteString(unexportedString) + continue + } + + concatWriteValue(b, fieldValue.Interface(), depth+1) + } + + b.WriteByte(']') +} diff --git a/vendor/github.com/olekukonko/ll/conditional.go b/vendor/github.com/olekukonko/ll/conditional.go new file mode 100644 index 00000000..0ec9e4b8 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/conditional.go @@ -0,0 +1,340 @@ +package ll + +// Conditional enables conditional logging based on a boolean condition. +// It wraps a logger with a condition that determines whether logging operations are executed, +// optimizing performance by skipping expensive operations (e.g., field computation, message formatting) +// when the condition is false. The struct supports fluent chaining for adding fields and logging. +type Conditional struct { + logger *Logger // Associated logger instance for logging operations + condition bool // Whether logging is allowed (true to log, false to skip) +} + +// If creates a conditional logger that logs only if the condition is true. +// It returns a Conditional struct that wraps the logger, enabling conditional logging methods. +// This method is typically called on a Logger instance to start a conditional chain. +// Thread-safe via the underlying logger’s mutex. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Info("Logged") // Output: [app] INFO: Logged +// logger.If(false).Info("Ignored") // No output +func (l *Logger) If(condition bool) *Conditional { + return &Conditional{logger: l, condition: condition} +} + +// IfOne creates a conditional logger that logs only if all conditions are true. +// It evaluates a variadic list of boolean conditions, setting the condition to true only if +// all are true (logical AND). Returns a new Conditional with the result. Thread-safe via the +// underlying logger. +// Example: +// +// logger := New("app").Enable() +// logger.IfOne(true, true).Info("Logged") // Output: [app] INFO: Logged +// logger.IfOne(true, false).Info("Ignored") // No output +func (cl *Conditional) IfOne(conditions ...bool) *Conditional { + result := true + // Check each condition; set result to false if any is false + for _, cond := range conditions { + if !cond { + result = false + break + } + } + return &Conditional{logger: cl.logger, condition: result} +} + +// IfAny creates a conditional logger that logs only if at least one condition is true. +// It evaluates a variadic list of boolean conditions, setting the condition to true if any +// is true (logical OR). Returns a new Conditional with the result. Thread-safe via the +// underlying logger. +// Example: +// +// logger := New("app").Enable() +// logger.IfAny(false, true).Info("Logged") // Output: [app] INFO: Logged +// logger.IfAny(false, false).Info("Ignored") // No output +func (cl *Conditional) IfAny(conditions ...bool) *Conditional { + result := false + // Check each condition; set result to true if any is true + for _, cond := range conditions { + if cond { + result = true + break + } + } + return &Conditional{logger: cl.logger, condition: result} +} + +// Fields starts a fluent chain for adding fields using variadic key-value pairs, if the condition is true. +// It returns a FieldBuilder to attach fields, skipping field processing if the condition is false +// to optimize performance. Thread-safe via the FieldBuilder’s logger. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Fields("user", "alice").Info("Logged") // Output: [app] INFO: Logged [user=alice] +// logger.If(false).Fields("user", "alice").Info("Ignored") // No output, no field processing +func (cl *Conditional) Fields(pairs ...any) *FieldBuilder { + // Skip field processing if condition is false + if !cl.condition { + return &FieldBuilder{logger: cl.logger, fields: nil} + } + // Delegate to logger’s Fields method + return cl.logger.Fields(pairs...) +} + +// Field starts a fluent chain for adding fields from a map, if the condition is true. +// It returns a FieldBuilder to attach fields from a map, skipping processing if the condition +// is false. Thread-safe via the FieldBuilder’s logger. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Field(map[string]interface{}{"user": "alice"}).Info("Logged") // Output: [app] INFO: Logged [user=alice] +// logger.If(false).Field(map[string]interface{}{"user": "alice"}).Info("Ignored") // No output +func (cl *Conditional) Field(fields map[string]interface{}) *FieldBuilder { + // Skip field processing if condition is false + if !cl.condition { + return &FieldBuilder{logger: cl.logger, fields: nil} + } + // Delegate to logger’s Field method + return cl.logger.Field(fields) +} + +// Info logs a message at Info level with variadic arguments if the condition is true. +// It concatenates the arguments with spaces and delegates to the logger’s Info method if the +// condition is true. Skips processing if false, optimizing performance. Thread-safe via the +// logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Info("Action", "started") // Output: [app] INFO: Action started +// logger.If(false).Info("Action", "ignored") // No output +func (cl *Conditional) Info(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Info method + cl.logger.Info(args...) +} + +// Infof logs a message at Info level with a format string if the condition is true. +// It formats the message using the provided format string and arguments, delegating to the +// logger’s Infof method if the condition is true. Skips processing if false, optimizing performance. +// Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Infof("Action %s", "started") // Output: [app] INFO: Action started +// logger.If(false).Infof("Action %s", "ignored") // No output +func (cl *Conditional) Infof(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Infof method + cl.logger.Infof(format, args...) +} + +// Debug logs a message at Debug level with variadic arguments if the condition is true. +// It concatenates the arguments with spaces and delegates to the logger’s Debug method if the +// condition is true. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelDebug) +// logger.If(true).Debug("Debugging", "mode") // Output: [app] DEBUG: Debugging mode +// logger.If(false).Debug("Debugging", "ignored") // No output +func (cl *Conditional) Debug(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Debug method + cl.logger.Debug(args...) +} + +// Debugf logs a message at Debug level with a format string if the condition is true. +// It formats the message and delegates to the logger’s Debugf method if the condition is true. +// Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelDebug) +// logger.If(true).Debugf("Debug %s", "mode") // Output: [app] DEBUG: Debug mode +// logger.If(false).Debugf("Debug %s", "ignored") // No output +func (cl *Conditional) Debugf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Debugf method + cl.logger.Debugf(format, args...) +} + +// Warn logs a message at Warn level with variadic arguments if the condition is true. +// It concatenates the arguments with spaces and delegates to the logger’s Warn method if the +// condition is true. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Warn("Warning", "issued") // Output: [app] WARN: Warning issued +// logger.If(false).Warn("Warning", "ignored") // No output +func (cl *Conditional) Warn(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Warn method + cl.logger.Warn(args...) +} + +// Warnf logs a message at Warn level with a format string if the condition is true. +// It formats the message and delegates to the logger’s Warnf method if the condition is true. +// Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Warnf("Warning %s", "issued") // Output: [app] WARN: Warning issued +// logger.If(false).Warnf("Warning %s", "ignored") // No output +func (cl *Conditional) Warnf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Warnf method + cl.logger.Warnf(format, args...) +} + +// Error logs a message at Error level with variadic arguments if the condition is true. +// It concatenates the arguments with spaces and delegates to the logger’s Error method if the +// condition is true. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Error("Error", "occurred") // Output: [app] ERROR: Error occurred +// logger.If(false).Error("Error", "ignored") // No output +func (cl *Conditional) Error(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Error method + cl.logger.Error(args...) +} + +// Errorf logs a message at Error level with a format string if the condition is true. +// It formats the message and delegates to the logger’s Errorf method if the condition is true. +// Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Errorf("Error %s", "occurred") // Output: [app] ERROR: Error occurred +// logger.If(false).Errorf("Error %s", "ignored") // No output +func (cl *Conditional) Errorf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Errorf method + cl.logger.Errorf(format, args...) +} + +// Stack logs a message at Error level with a stack trace and variadic arguments if the condition is true. +// It concatenates the arguments with spaces and delegates to the logger’s Stack method if the +// condition is true. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Stack("Critical", "error") // Output: [app] ERROR: Critical error [stack=...] +// logger.If(false).Stack("Critical", "ignored") // No output +func (cl *Conditional) Stack(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Stack method + cl.logger.Stack(args...) +} + +// Stackf logs a message at Error level with a stack trace and a format string if the condition is true. +// It formats the message and delegates to the logger’s Stackf method if the condition is true. +// Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Stackf("Critical %s", "error") // Output: [app] ERROR: Critical error [stack=...] +// logger.If(false).Stackf("Critical %s", "ignored") // No output +func (cl *Conditional) Stackf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Stackf method + cl.logger.Stackf(format, args...) +} + +// Fatal logs a message at Error level with a stack trace and variadic arguments if the condition is true, +// then exits. It concatenates the arguments with spaces and delegates to the logger’s Fatal method +// if the condition is true, terminating the program with exit code 1. Skips processing if false. +// Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Fatal("Fatal", "error") // Output: [app] ERROR: Fatal error [stack=...], then exits +// logger.If(false).Fatal("Fatal", "ignored") // No output, no exit +func (cl *Conditional) Fatal(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Fatal method + cl.logger.Fatal(args...) +} + +// Fatalf logs a formatted message at Error level with a stack trace if the condition is true, then exits. +// It formats the message and delegates to the logger’s Fatalf method if the condition is true, +// terminating the program with exit code 1. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Fatalf("Fatal %s", "error") // Output: [app] ERROR: Fatal error [stack=...], then exits +// logger.If(false).Fatalf("Fatal %s", "ignored") // No output, no exit +func (cl *Conditional) Fatalf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Fatalf method + cl.logger.Fatalf(format, args...) +} + +// Panic logs a message at Error level with a stack trace and variadic arguments if the condition is true, +// then panics. It concatenates the arguments with spaces and delegates to the logger’s Panic method +// if the condition is true, triggering a panic. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Panic("Panic", "error") // Output: [app] ERROR: Panic error [stack=...], then panics +// logger.If(false).Panic("Panic", "ignored") // No output, no panic +func (cl *Conditional) Panic(args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Panic method + cl.logger.Panic(args...) +} + +// Panicf logs a formatted message at Error level with a stack trace if the condition is true, then panics. +// It formats the message and delegates to the logger’s Panicf method if the condition is true, +// triggering a panic. Skips processing if false. Thread-safe via the logger’s log method. +// Example: +// +// logger := New("app").Enable() +// logger.If(true).Panicf("Panic %s", "error") // Output: [app] ERROR: Panic error [stack=...], then panics +// logger.If(false).Panicf("Panic %s", "ignored") // No output, no panic +func (cl *Conditional) Panicf(format string, args ...any) { + // Skip logging if condition is false + if !cl.condition { + return + } + // Delegate to logger’s Panicf method + cl.logger.Panicf(format, args...) +} diff --git a/vendor/github.com/olekukonko/ll/field.go b/vendor/github.com/olekukonko/ll/field.go new file mode 100644 index 00000000..9d4ff3c6 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/field.go @@ -0,0 +1,374 @@ +package ll + +import ( + "fmt" + "github.com/olekukonko/ll/lx" + "os" + "strings" +) + +// FieldBuilder enables fluent addition of fields before logging. +// It acts as a builder pattern to attach key-value pairs (fields) to log entries, +// supporting structured logging with metadata. The builder allows chaining to add fields +// and log messages at various levels (Info, Debug, Warn, Error, etc.) in a single expression. +type FieldBuilder struct { + logger *Logger // Associated logger instance for logging operations + fields map[string]interface{} // Fields to include in the log entry as key-value pairs +} + +// Logger creates a new logger with the builder’s fields embedded in its context. +// It clones the parent logger and copies the builder’s fields into the new logger’s context, +// enabling persistent field inclusion in subsequent logs. This method supports fluent chaining +// after Fields or Field calls. +// Example: +// +// logger := New("app").Enable() +// newLogger := logger.Fields("user", "alice").Logger() +// newLogger.Info("Action") // Output: [app] INFO: Action [user=alice] +func (fb *FieldBuilder) Logger() *Logger { + // Clone the parent logger to preserve its configuration + newLogger := fb.logger.Clone() + // Initialize a new context map to avoid modifying the parent’s context + newLogger.context = make(map[string]interface{}) + // Copy builder’s fields into the new logger’s context + for k, v := range fb.fields { + newLogger.context[k] = v + } + return newLogger +} + +// Info logs a message at Info level with the builder’s fields. +// It concatenates the arguments with spaces and delegates to the logger’s log method, +// returning early if fields are nil. This method is used for informational messages. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Info("Action", "started") // Output: [app] INFO: Action started [user=alice] +func (fb *FieldBuilder) Info(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Log at Info level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelInfo, lx.ClassText, concatSpaced(args...), fb.fields, false) +} + +// Infof logs a message at Info level with the builder’s fields. +// It formats the message using the provided format string and arguments, then delegates +// to the logger’s internal log method. If fields are nil, it returns early to avoid logging. +// This method is part of the fluent API, typically called after adding fields. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Infof("Action %s", "started") // Output: [app] INFO: Action started [user=alice] +func (fb *FieldBuilder) Infof(format string, args ...any) { + // Skip logging if fields are nil to prevent invalid log entries + if fb.fields == nil { + return + } + // Format the message using the provided arguments + msg := fmt.Sprintf(format, args...) + // Log at Info level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelInfo, lx.ClassText, msg, fb.fields, false) +} + +// Debug logs a message at Debug level with the builder’s fields. +// It concatenates the arguments with spaces and delegates to the logger’s log method, +// returning early if fields are nil. This method is used for debugging information. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Debug("Debugging", "mode") // Output: [app] DEBUG: Debugging mode [user=alice] +func (fb *FieldBuilder) Debug(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Log at Debug level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelDebug, lx.ClassText, concatSpaced(args...), fb.fields, false) +} + +// Debugf logs a message at Debug level with the builder’s fields. +// It formats the message and delegates to the logger’s log method, returning early if +// fields are nil. This method is used for debugging information that may be disabled in +// production environments. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Debugf("Debug %s", "mode") // Output: [app] DEBUG: Debug mode [user=alice] +func (fb *FieldBuilder) Debugf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message + msg := fmt.Sprintf(format, args...) + // Log at Debug level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelDebug, lx.ClassText, msg, fb.fields, false) +} + +// Warn logs a message at Warn level with the builder’s fields. +// It concatenates the arguments with spaces and delegates to the logger’s log method, +// returning early if fields are nil. This method is used for warning conditions. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Warn("Warning", "issued") // Output: [app] WARN: Warning issued [user=alice] +func (fb *FieldBuilder) Warn(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Log at Warn level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelWarn, lx.ClassText, concatSpaced(args...), fb.fields, false) +} + +// Warnf logs a message at Warn level with the builder’s fields. +// It formats the message and delegates to the logger’s log method, returning early if +// fields are nil. This method is used for warning conditions that do not halt execution. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Warnf("Warning %s", "issued") // Output: [app] WARN: Warning issued [user=alice] +func (fb *FieldBuilder) Warnf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message + msg := fmt.Sprintf(format, args...) + // Log at Warn level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelWarn, lx.ClassText, msg, fb.fields, false) +} + +// Error logs a message at Error level with the builder’s fields. +// It concatenates the arguments with spaces and delegates to the logger’s log method, +// returning early if fields are nil. This method is used for error conditions. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Error("Error", "occurred") // Output: [app] ERROR: Error occurred [user=alice] +func (fb *FieldBuilder) Error(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Log at Error level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelError, lx.ClassText, concatSpaced(args...), fb.fields, false) +} + +// Errorf logs a message at Error level with the builder’s fields. +// It formats the message and delegates to the logger’s log method, returning early if +// fields are nil. This method is used for error conditions that may require attention. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Errorf("Error %s", "occurred") // Output: [app] ERROR: Error occurred [user=alice] +func (fb *FieldBuilder) Errorf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message + msg := fmt.Sprintf(format, args...) + // Log at Error level with the builder’s fields, no stack trace + fb.logger.log(lx.LevelError, lx.ClassText, msg, fb.fields, false) +} + +// Stack logs a message at Error level with a stack trace and the builder’s fields. +// It concatenates the arguments with spaces and delegates to the logger’s log method, +// returning early if fields are nil. This method is useful for debugging critical errors. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Stack("Critical", "error") // Output: [app] ERROR: Critical error [user=alice stack=...] +func (fb *FieldBuilder) Stack(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Log at Error level with the builder’s fields and a stack trace + fb.logger.log(lx.LevelError, lx.ClassText, concatSpaced(args...), fb.fields, true) +} + +// Stackf logs a message at Error level with a stack trace and the builder’s fields. +// It formats the message and delegates to the logger’s log method, returning early if +// fields are nil. This method is useful for debugging critical errors. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Stackf("Critical %s", "error") // Output: [app] ERROR: Critical error [user=alice stack=...] +func (fb *FieldBuilder) Stackf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message + msg := fmt.Sprintf(format, args...) + // Log at Error level with the builder’s fields and a stack trace + fb.logger.log(lx.LevelError, lx.ClassText, msg, fb.fields, true) +} + +// Fatal logs a message at Error level with a stack trace and the builder’s fields, then exits. +// It constructs the message from variadic arguments, logs it with a stack trace, and terminates +// the program with exit code 1. Returns early if fields are nil. This method is used for +// unrecoverable errors. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Fatal("Fatal", "error") // Output: [app] ERROR: Fatal error [user=alice stack=...], then exits +func (fb *FieldBuilder) Fatal(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Build the message by concatenating arguments with spaces + var builder strings.Builder + for i, arg := range args { + if i > 0 { + builder.WriteString(lx.Space) + } + builder.WriteString(fmt.Sprint(arg)) + } + // Log at Error level with the builder’s fields and a stack trace + fb.logger.log(lx.LevelError, lx.ClassText, builder.String(), fb.fields, true) + // Exit the program with status code 1 + os.Exit(1) +} + +// Fatalf logs a formatted message at Error level with a stack trace and the builder’s fields, +// then exits. It delegates to Fatal and returns early if fields are nil. This method is used +// for unrecoverable errors. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Fatalf("Fatal %s", "error") // Output: [app] ERROR: Fatal error [user=alice stack=...], then exits +func (fb *FieldBuilder) Fatalf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message and pass to Fatal + fb.Fatal(fmt.Sprintf(format, args...)) +} + +// Panic logs a message at Error level with a stack trace and the builder’s fields, then panics. +// It constructs the message from variadic arguments, logs it with a stack trace, and triggers +// a panic with the message. Returns early if fields are nil. This method is used for critical +// errors that require immediate program termination with a panic. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Panic("Panic", "error") // Output: [app] ERROR: Panic error [user=alice stack=...], then panics +func (fb *FieldBuilder) Panic(args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Build the message by concatenating arguments with spaces + var builder strings.Builder + for i, arg := range args { + if i > 0 { + builder.WriteString(lx.Space) + } + builder.WriteString(fmt.Sprint(arg)) + } + msg := builder.String() + // Log at Error level with the builder’s fields and a stack trace + fb.logger.log(lx.LevelError, lx.ClassText, msg, fb.fields, true) + // Trigger a panic with the formatted message + panic(msg) +} + +// Panicf logs a formatted message at Error level with a stack trace and the builder’s fields, +// then panics. It delegates to Panic and returns early if fields are nil. This method is used +// for critical errors that require immediate program termination with a panic. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Panicf("Panic %s", "error") // Output: [app] ERROR: Panic error [user=alice stack=...], then panics +func (fb *FieldBuilder) Panicf(format string, args ...any) { + // Skip logging if fields are nil + if fb.fields == nil { + return + } + // Format the message and pass to Panic + fb.Panic(fmt.Sprintf(format, args...)) +} + +// Err adds one or more errors to the FieldBuilder as a field and logs them. +// It stores non-nil errors in the "error" field: a single error if only one is non-nil, +// or a slice of errors if multiple are non-nil. It logs the concatenated string representations +// of non-nil errors (e.g., "failed 1; failed 2") at the Error level. Returns the FieldBuilder +// for chaining, allowing further field additions or logging. Thread-safe via the logger’s mutex. +// Example: +// +// logger := New("app").Enable() +// err1 := errors.New("failed 1") +// err2 := errors.New("failed 2") +// logger.Fields("k", "v").Err(err1, err2).Info("Error occurred") +// // Output: [app] ERROR: failed 1; failed 2 +// // [app] INFO: Error occurred [error=[failed 1 failed 2] k=v] +func (fb *FieldBuilder) Err(errs ...error) *FieldBuilder { + // Initialize fields map if nil + if fb.fields == nil { + fb.fields = make(map[string]interface{}) + } + + // Collect non-nil errors and build log message + var nonNilErrors []error + var builder strings.Builder + count := 0 + for i, err := range errs { + if err != nil { + if i > 0 && count > 0 { + builder.WriteString("; ") + } + builder.WriteString(err.Error()) + nonNilErrors = append(nonNilErrors, err) + count++ + } + } + + // Set error field and log if there are non-nil errors + if count > 0 { + if count == 1 { + // Store single error directly + fb.fields["error"] = nonNilErrors[0] + } else { + // Store slice of errors + fb.fields["error"] = nonNilErrors + } + // Log concatenated error messages at Error level + fb.logger.log(lx.LevelError, lx.ClassText, builder.String(), nil, false) + } + + // Return FieldBuilder for chaining + return fb +} + +// Merge adds additional key-value pairs to the FieldBuilder. +// It processes variadic arguments as key-value pairs, expecting string keys. Non-string keys +// or uneven pairs generate an "error" field with a descriptive message. Returns the FieldBuilder +// for chaining to allow further field additions or logging. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("k1", "v1").Merge("k2", "v2").Info("Action") // Output: [app] INFO: Action [k1=v1 k2=v2] +func (fb *FieldBuilder) Merge(pairs ...any) *FieldBuilder { + // Process pairs as key-value, advancing by 2 + for i := 0; i < len(pairs)-1; i += 2 { + // Ensure the key is a string + if key, ok := pairs[i].(string); ok { + fb.fields[key] = pairs[i+1] + } else { + // Log an error field for non-string keys + fb.fields["error"] = fmt.Errorf("non-string key in Merge: %v", pairs[i]) + } + } + // Check for uneven pairs (missing value) + if len(pairs)%2 != 0 { + fb.fields["error"] = fmt.Errorf("uneven key-value pairs in Merge: [%v]", pairs[len(pairs)-1]) + } + return fb +} diff --git a/vendor/github.com/olekukonko/ll/global.go b/vendor/github.com/olekukonko/ll/global.go new file mode 100644 index 00000000..2ebea73b --- /dev/null +++ b/vendor/github.com/olekukonko/ll/global.go @@ -0,0 +1,659 @@ +package ll + +import ( + "github.com/olekukonko/ll/lh" + "github.com/olekukonko/ll/lx" + "os" + "sync/atomic" + "time" +) + +// defaultLogger is the global logger instance for package-level logging functions. +// It provides a shared logger for convenience, allowing logging without explicitly creating +// a logger instance. The logger is initialized with default settings: enabled, Debug level, +// flat namespace style, and a text handler to os.Stdout. It is thread-safe due to the Logger +// struct’s mutex. +var defaultLogger = &Logger{ + enabled: true, // Initially enabled + level: lx.LevelDebug, // Minimum log level set to Debug + namespaces: defaultStore, // Shared namespace store for enable/disable states + context: make(map[string]interface{}), // Empty context for global fields + style: lx.FlatPath, // Flat namespace style (e.g., [parent/child]) + handler: lh.NewTextHandler(os.Stdout), // Default text handler to os.Stdout + middleware: make([]Middleware, 0), // Empty middleware chain + stackBufferSize: 4096, // Buffer size for stack traces +} + +// Handler sets the handler for the default logger. +// It configures the output destination and format (e.g., text, JSON) for logs emitted by +// defaultLogger. Returns the default logger for method chaining, enabling fluent configuration. +// Example: +// +// ll.Handler(lh.NewJSONHandler(os.Stdout)).Enable() +// ll.Info("Started") // Output: {"level":"INFO","message":"Started"} +func Handler(handler lx.Handler) *Logger { + return defaultLogger.Handler(handler) +} + +// Level sets the minimum log level for the default logger. +// It determines which log messages (Debug, Info, Warn, Error) are emitted. Messages below +// the specified level are ignored. Returns the default logger for method chaining. +// Example: +// +// ll.Level(lx.LevelWarn) +// ll.Info("Ignored") // No output +// ll.Warn("Logged") // Output: [] WARN: Logged +func Level(level lx.LevelType) *Logger { + return defaultLogger.Level(level) +} + +// Style sets the namespace style for the default logger. +// It controls how namespace paths are formatted in logs (FlatPath: [parent/child], +// NestedPath: [parent]→[child]). Returns the default logger for method chaining. +// Example: +// +// ll.Style(lx.NestedPath) +// ll.Info("Test") // Output: []: INFO: Test +func Style(style lx.StyleType) *Logger { + return defaultLogger.Style(style) +} + +// NamespaceEnable enables logging for a namespace and its children using the default logger. +// It activates logging for the specified namespace path (e.g., "app/db") and all its +// descendants. Returns the default logger for method chaining. Thread-safe via the Logger’s mutex. +// Example: +// +// ll.NamespaceEnable("app/db") +// ll.Clone().Namespace("db").Info("Query") // Output: [app/db] INFO: Query +func NamespaceEnable(path string) *Logger { + return defaultLogger.NamespaceEnable(path) +} + +// NamespaceDisable disables logging for a namespace and its children using the default logger. +// It suppresses logging for the specified namespace path and all its descendants. Returns +// the default logger for method chaining. Thread-safe via the Logger’s mutex. +// Example: +// +// ll.NamespaceDisable("app/db") +// ll.Clone().Namespace("db").Info("Query") // No output +func NamespaceDisable(path string) *Logger { + return defaultLogger.NamespaceDisable(path) +} + +// Namespace creates a child logger with a sub-namespace appended to the current path. +// The child inherits the default logger’s configuration but has an independent context. +// Thread-safe with read lock. Returns the new logger for further configuration or logging. +// Example: +// +// logger := ll.Namespace("app") +// logger.Info("Started") // Output: [app] INFO: Started +func Namespace(name string) *Logger { + return defaultLogger.Namespace(name) +} + +// Info logs a message at Info level with variadic arguments using the default logger. +// It concatenates the arguments with spaces and delegates to defaultLogger’s Info method. +// Thread-safe via the Logger’s log method. +// Example: +// +// ll.Info("Service", "started") // Output: [] INFO: Service started +func Info(args ...any) { + defaultLogger.Info(args...) +} + +// Infof logs a message at Info level with a format string using the default logger. +// It formats the message using the provided format string and arguments, then delegates to +// defaultLogger’s Infof method. Thread-safe via the Logger’s log method. +// Example: +// +// ll.Infof("Service %s", "started") // Output: [] INFO: Service started +func Infof(format string, args ...any) { + defaultLogger.Infof(format, args...) +} + +// Debug logs a message at Debug level with variadic arguments using the default logger. +// It concatenates the arguments with spaces and delegates to defaultLogger’s Debug method. +// Used for debugging information, typically disabled in production. Thread-safe. +// Example: +// +// ll.Level(lx.LevelDebug) +// ll.Debug("Debugging", "mode") // Output: [] DEBUG: Debugging mode +func Debug(args ...any) { + defaultLogger.Debug(args...) +} + +// Debugf logs a message at Debug level with a format string using the default logger. +// It formats the message and delegates to defaultLogger’s Debugf method. Used for debugging +// information, typically disabled in production. Thread-safe. +// Example: +// +// ll.Level(lx.LevelDebug) +// ll.Debugf("Debug %s", "mode") // Output: [] DEBUG: Debug mode +func Debugf(format string, args ...any) { + defaultLogger.Debugf(format, args...) +} + +// Warn logs a message at Warn level with variadic arguments using the default logger. +// It concatenates the arguments with spaces and delegates to defaultLogger’s Warn method. +// Used for warning conditions that do not halt execution. Thread-safe. +// Example: +// +// ll.Warn("Low", "memory") // Output: [] WARN: Low memory +func Warn(args ...any) { + defaultLogger.Warn(args...) +} + +// Warnf logs a message at Warn level with a format string using the default logger. +// It formats the message and delegates to defaultLogger’s Warnf method. Used for warning +// conditions that do not halt execution. Thread-safe. +// Example: +// +// ll.Warnf("Low %s", "memory") // Output: [] WARN: Low memory +func Warnf(format string, args ...any) { + defaultLogger.Warnf(format, args...) +} + +// Error logs a message at Error level with variadic arguments using the default logger. +// It concatenates the arguments with spaces and delegates to defaultLogger’s Error method. +// Used for error conditions requiring attention. Thread-safe. +// Example: +// +// ll.Error("Database", "failure") // Output: [] ERROR: Database failure +func Error(args ...any) { + defaultLogger.Error(args...) +} + +// Errorf logs a message at Error level with a format string using the default logger. +// It formats the message and delegates to defaultLogger’s Errorf method. Used for error +// conditions requiring attention. Thread-safe. +// Example: +// +// ll.Errorf("Database %s", "failure") // Output: [] ERROR: Database failure +func Errorf(format string, args ...any) { + defaultLogger.Errorf(format, args...) +} + +// Stack logs a message at Error level with a stack trace and variadic arguments using the default logger. +// It concatenates the arguments with spaces and delegates to defaultLogger’s Stack method. +// Thread-safe. +// Example: +// +// ll.Stack("Critical", "error") // Output: [] ERROR: Critical error [stack=...] +func Stack(args ...any) { + defaultLogger.Stack(args...) +} + +// Stackf logs a message at Error level with a stack trace and a format string using the default logger. +// It formats the message and delegates to defaultLogger’s Stackf method. Thread-safe. +// Example: +// +// ll.Stackf("Critical %s", "error") // Output: [] ERROR: Critical error [stack=...] +func Stackf(format string, args ...any) { + defaultLogger.Stackf(format, args...) +} + +// Fatal logs a message at Error level with a stack trace and variadic arguments using the default logger, +// then exits. It concatenates the arguments with spaces, logs with a stack trace, and terminates +// with exit code 1. Thread-safe. +// Example: +// +// ll.Fatal("Fatal", "error") // Output: [] ERROR: Fatal error [stack=...], then exits +func Fatal(args ...any) { + defaultLogger.Fatal(args...) +} + +// Fatalf logs a formatted message at Error level with a stack trace using the default logger, +// then exits. It formats the message, logs with a stack trace, and terminates with exit code 1. +// Thread-safe. +// Example: +// +// ll.Fatalf("Fatal %s", "error") // Output: [] ERROR: Fatal error [stack=...], then exits +func Fatalf(format string, args ...any) { + defaultLogger.Fatalf(format, args...) +} + +// Panic logs a message at Error level with a stack trace and variadic arguments using the default logger, +// then panics. It concatenates the arguments with spaces, logs with a stack trace, and triggers a panic. +// Thread-safe. +// Example: +// +// ll.Panic("Panic", "error") // Output: [] ERROR: Panic error [stack=...], then panics +func Panic(args ...any) { + defaultLogger.Panic(args...) +} + +// Panicf logs a formatted message at Error level with a stack trace using the default logger, +// then panics. It formats the message, logs with a stack trace, and triggers a panic. Thread-safe. +// Example: +// +// ll.Panicf("Panic %s", "error") // Output: [] ERROR: Panic error [stack=...], then panics +func Panicf(format string, args ...any) { + defaultLogger.Panicf(format, args...) +} + +// If creates a conditional logger that logs only if the condition is true using the default logger. +// It returns a Conditional struct that wraps the default logger, enabling conditional logging methods. +// Thread-safe via the Logger’s mutex. +// Example: +// +// ll.If(true).Info("Logged") // Output: [] INFO: Logged +// ll.If(false).Info("Ignored") // No output +func If(condition bool) *Conditional { + return defaultLogger.If(condition) +} + +// Context creates a new logger with additional contextual fields using the default logger. +// It preserves existing context fields and adds new ones, returning a new logger instance +// to avoid mutating the default logger. Thread-safe with write lock. +// Example: +// +// logger := ll.Context(map[string]interface{}{"user": "alice"}) +// logger.Info("Action") // Output: [] INFO: Action [user=alice] +func Context(fields map[string]interface{}) *Logger { + return defaultLogger.Context(fields) +} + +// AddContext adds a key-value pair to the default logger’s context, modifying it directly. +// It mutates the default logger’s context and is thread-safe using a write lock. +// Example: +// +// ll.AddContext("user", "alice") +// ll.Info("Action") // Output: [] INFO: Action [user=alice] +func AddContext(key string, value interface{}) *Logger { + return defaultLogger.AddContext(key, value) +} + +// GetContext returns the default logger’s context map of persistent key-value fields. +// It provides thread-safe read access to the context using a read lock. +// Example: +// +// ll.AddContext("user", "alice") +// ctx := ll.GetContext() // Returns map[string]interface{}{"user": "alice"} +func GetContext() map[string]interface{} { + return defaultLogger.GetContext() +} + +// GetLevel returns the minimum log level for the default logger. +// It provides thread-safe read access to the level field using a read lock. +// Example: +// +// ll.Level(lx.LevelWarn) +// if ll.GetLevel() == lx.LevelWarn { +// ll.Warn("Warning level set") // Output: [] WARN: Warning level set +// } +func GetLevel() lx.LevelType { + return defaultLogger.GetLevel() +} + +// GetPath returns the default logger’s current namespace path. +// It provides thread-safe read access to the currentPath field using a read lock. +// Example: +// +// logger := ll.Namespace("app") +// path := logger.GetPath() // Returns "app" +func GetPath() string { + return defaultLogger.GetPath() +} + +// GetSeparator returns the default logger’s namespace separator (e.g., "/"). +// It provides thread-safe read access to the separator field using a read lock. +// Example: +// +// ll.Separator(".") +// sep := ll.GetSeparator() // Returns "." +func GetSeparator() string { + return defaultLogger.GetSeparator() +} + +// GetStyle returns the default logger’s namespace formatting style (FlatPath or NestedPath). +// It provides thread-safe read access to the style field using a read lock. +// Example: +// +// ll.Style(lx.NestedPath) +// if ll.GetStyle() == lx.NestedPath { +// ll.Info("Nested style") // Output: []: INFO: Nested style +// } +func GetStyle() lx.StyleType { + return defaultLogger.GetStyle() +} + +// GetHandler returns the default logger’s current handler for customization or inspection. +// The returned handler should not be modified concurrently with logger operations. +// Example: +// +// handler := ll.GetHandler() // Returns the current handler (e.g., TextHandler) +func GetHandler() lx.Handler { + return defaultLogger.GetHandler() +} + +// Separator sets the namespace separator for the default logger (e.g., "/" or "."). +// It updates the separator used in namespace paths. Thread-safe with write lock. +// Returns the default logger for method chaining. +// Example: +// +// ll.Separator(".") +// ll.Namespace("app").Info("Log") // Output: [app] INFO: Log +func Separator(separator string) *Logger { + return defaultLogger.Separator(separator) +} + +// Prefix sets a prefix to be prepended to all log messages of the default logger. +// The prefix is applied before the message in the log output. Thread-safe with write lock. +// Returns the default logger for method chaining. +// Example: +// +// ll.Prefix("APP: ") +// ll.Info("Started") // Output: [] INFO: APP: Started +func Prefix(prefix string) *Logger { + return defaultLogger.Prefix(prefix) +} + +// StackSize sets the buffer size for stack trace capture in the default logger. +// It configures the maximum size for stack traces in Stack, Fatal, and Panic methods. +// Thread-safe with write lock. Returns the default logger for chaining. +// Example: +// +// ll.StackSize(65536) +// ll.Stack("Error") // Captures up to 64KB stack trace +func StackSize(size int) *Logger { + return defaultLogger.StackSize(size) +} + +// Use adds a middleware function to process log entries before they are handled by the default logger. +// It registers the middleware and returns a Middleware handle for removal. Middleware returning +// a non-nil error stops the log. Thread-safe with write lock. +// Example: +// +// mw := ll.Use(ll.FuncMiddleware(func(e *lx.Entry) error { +// if e.Level < lx.LevelWarn { +// return fmt.Errorf("level too low") +// } +// return nil +// })) +// ll.Info("Ignored") // No output +// mw.Remove() +// ll.Info("Logged") // Output: [] INFO: Logged +func Use(fn lx.Handler) *Middleware { + return defaultLogger.Use(fn) +} + +// Remove removes middleware by the reference returned from Use for the default logger. +// It delegates to the Middleware’s Remove method for thread-safe removal. +// Example: +// +// mw := ll.Use(someMiddleware) +// ll.Remove(mw) // Removes middleware +func Remove(m *Middleware) { + defaultLogger.Remove(m) +} + +// Clear removes all middleware functions from the default logger. +// It resets the middleware chain to empty, ensuring no middleware is applied. +// Thread-safe with write lock. Returns the default logger for chaining. +// Example: +// +// ll.Use(someMiddleware) +// ll.Clear() +// ll.Info("No middleware") // Output: [] INFO: No middleware +func Clear() *Logger { + return defaultLogger.Clear() +} + +// CanLog checks if a log at the given level would be emitted by the default logger. +// It considers enablement, log level, namespaces, sampling, and rate limits. +// Thread-safe via the Logger’s shouldLog method. +// Example: +// +// ll.Level(lx.LevelWarn) +// canLog := ll.CanLog(lx.LevelInfo) // false +func CanLog(level lx.LevelType) bool { + return defaultLogger.CanLog(level) +} + +// NamespaceEnabled checks if a namespace is enabled in the default logger. +// It evaluates the namespace hierarchy, considering parent namespaces, and caches the result +// for performance. Thread-safe with read lock. +// Example: +// +// ll.NamespaceDisable("app/db") +// enabled := ll.NamespaceEnabled("app/db") // false +func NamespaceEnabled(path string) bool { + return defaultLogger.NamespaceEnabled(path) +} + +// Print logs a message at Info level without format specifiers using the default logger. +// It concatenates variadic arguments with spaces, minimizing allocations, and delegates +// to defaultLogger’s Print method. Thread-safe via the Logger’s log method. +// Example: +// +// ll.Print("message", "value") // Output: [] INFO: message value +func Print(args ...any) { + defaultLogger.Print(args...) +} + +// Println logs a message at Info level without format specifiers, minimizing allocations +// by concatenating arguments with spaces. It is thread-safe via the log method. +// Example: +// +// ll.Println("message", "value") // Output: [] INFO: message value [New Line] +func Println(args ...any) { + defaultLogger.Println(args...) +} + +// Printf logs a message at Info level with a format string using the default logger. +// It formats the message and delegates to defaultLogger’s Printf method. Thread-safe via +// the Logger’s log method. +// Example: +// +// ll.Printf("Message %s", "value") // Output: [] INFO: Message value +func Printf(format string, args ...any) { + defaultLogger.Printf(format, args...) +} + +// Len returns the total number of log entries sent to the handler by the default logger. +// It provides thread-safe access to the entries counter using atomic operations. +// Example: +// +// ll.Info("Test") +// count := ll.Len() // Returns 1 +func Len() int64 { + return defaultLogger.Len() +} + +// Measure is a benchmarking helper that measures and returns the duration of a function’s execution. +// It logs the duration at Info level with a "duration" field using defaultLogger. The function +// is executed once, and the elapsed time is returned. Thread-safe via the Logger’s mutex. +// Example: +// +// duration := ll.Measure(func() { time.Sleep(time.Millisecond) }) +// // Output: [] INFO: function executed [duration=~1ms] +func Measure(fns ...func()) time.Duration { + start := time.Now() + for _, fn := range fns { + fn() + } + duration := time.Since(start) + defaultLogger.Fields("duration", duration).Infof("function executed") + return duration +} + +// Benchmark logs the duration since a start time at Info level using the default logger. +// It calculates the time elapsed since the provided start time and logs it with "start", +// "end", and "duration" fields. Thread-safe via the Logger’s mutex. +// Example: +// +// start := time.Now() +// time.Sleep(time.Millisecond) +// ll.Benchmark(start) // Output: [] INFO: benchmark [start=... end=... duration=...] +func Benchmark(start time.Time) { + defaultLogger.Fields("start", start, "end", time.Now(), "duration", time.Now().Sub(start)).Infof("benchmark") +} + +// Clone returns a new logger with the same configuration as the default logger. +// It creates a copy of defaultLogger’s settings (level, style, namespaces, etc.) but with +// an independent context, allowing customization without affecting the global logger. +// Thread-safe via the Logger’s Clone method. +// Example: +// +// logger := ll.Clone().Namespace("sub") +// logger.Info("Sub-logger") // Output: [sub] INFO: Sub-logger +func Clone() *Logger { + return defaultLogger.Clone() +} + +// Err adds one or more errors to the default logger’s context and logs them. +// It stores non-nil errors in the "error" context field and logs their concatenated string +// representations (e.g., "failed 1; failed 2") at the Error level. Thread-safe via the Logger’s mutex. +// Example: +// +// err1 := errors.New("failed 1") +// ll.Err(err1) +// ll.Info("Error occurred") // Output: [] ERROR: failed 1 +// // [] INFO: Error occurred [error=failed 1] +func Err(errs ...error) { + defaultLogger.Err(errs...) +} + +// Start activates the global logging system. +// If the system was shut down, this re-enables all logging operations, +// subject to individual logger and namespace configurations. +// Thread-safe via atomic operations. +// Example: +// +// ll.Shutdown() +// ll.Info("Ignored") // No output +// ll.Start() +// ll.Info("Logged") // Output: [] INFO: Logged +func Start() { + atomic.StoreInt32(&systemActive, 1) +} + +// Shutdown deactivates the global logging system. +// All logging operations are skipped, regardless of individual logger or namespace configurations, +// until Start() is called again. Thread-safe via atomic operations. +// Example: +// +// ll.Shutdown() +// ll.Info("Ignored") // No output +func Shutdown() { + atomic.StoreInt32(&systemActive, 0) +} + +// Active returns true if the global logging system is currently active. +// Thread-safe via atomic operations. +// Example: +// +// if ll.Active() { +// ll.Info("System active") // Output: [] INFO: System active +// } +func Active() bool { + return atomic.LoadInt32(&systemActive) == 1 +} + +// Enable activates logging for the default logger. +// It allows logs to be emitted if other conditions (level, namespace) are met. +// Thread-safe with write lock. Returns the default logger for method chaining. +// Example: +// +// ll.Disable() +// ll.Info("Ignored") // No output +// ll.Enable() +// ll.Info("Logged") // Output: [] INFO: Logged +func Enable() *Logger { + return defaultLogger.Enable() +} + +// Disable deactivates logging for the default logger. +// It suppresses all logs, regardless of level or namespace. Thread-safe with write lock. +// Returns the default logger for method chaining. +// Example: +// +// ll.Disable() +// ll.Info("Ignored") // No output +func Disable() *Logger { + return defaultLogger.Disable() +} + +// Dbg logs debug information including the source file, line number, and expression value +// using the default logger. It captures the calling line of code and displays both the +// expression and its value. Useful for debugging without temporary print statements. +// Example: +// +// x := 42 +// ll.Dbg(x) // Output: [file.go:123] x = 42 +func Dbg(any ...interface{}) { + defaultLogger.dbg(2, any...) +} + +// Dump displays a hex and ASCII representation of a value’s binary form using the default logger. +// It serializes the value using gob encoding or direct conversion and shows a hex/ASCII dump. +// Useful for inspecting binary data structures. +// Example: +// +// ll.Dump([]byte{0x41, 0x42}) // Outputs hex/ASCII dump +func Dump(any interface{}) { + defaultLogger.Dump(any) +} + +// Enabled returns whether the default logger is enabled for logging. +// It provides thread-safe read access to the enabled field using a read lock. +// Example: +// +// ll.Enable() +// if ll.Enabled() { +// ll.Info("Logging enabled") // Output: [] INFO: Logging enabled +// } +func Enabled() bool { + return defaultLogger.Enabled() +} + +// Fields starts a fluent chain for adding fields using variadic key-value pairs with the default logger. +// It creates a FieldBuilder to attach fields, handling non-string keys or uneven pairs by +// adding an error field. Thread-safe via the FieldBuilder’s logger. +// Example: +// +// ll.Fields("user", "alice").Info("Action") // Output: [] INFO: Action [user=alice] +func Fields(pairs ...any) *FieldBuilder { + return defaultLogger.Fields(pairs...) +} + +// Field starts a fluent chain for adding fields from a map with the default logger. +// It creates a FieldBuilder to attach fields from a map, supporting type-safe field addition. +// Thread-safe via the FieldBuilder’s logger. +// Example: +// +// ll.Field(map[string]interface{}{"user": "alice"}).Info("Action") // Output: [] INFO: Action [user=alice] +func Field(fields map[string]interface{}) *FieldBuilder { + return defaultLogger.Field(fields) +} + +// Line adds vertical spacing (newlines) to the log output using the default logger. +// If no arguments are provided, it defaults to 1 newline. Multiple values are summed to +// determine the total lines. Useful for visually separating log sections. Thread-safe. +// Example: +// +// ll.Line(2).Info("After two newlines") // Adds 2 blank lines before: [] INFO: After two newlines +func Line(lines ...int) *Logger { + return defaultLogger.Line(lines...) +} + +// Indent sets the indentation level for all log messages of the default logger. +// Each level adds two spaces to the log message, useful for hierarchical output. +// Thread-safe with write lock. Returns the default logger for method chaining. +// Example: +// +// ll.Indent(2) +// ll.Info("Indented") // Output: [] INFO: Indented +func Indent(depth int) *Logger { + return defaultLogger.Indent(depth) +} + +// Mark logs the current file and line number where it's called, without any additional debug information. +// It's useful for tracing execution flow without the verbosity of Dbg. +// Example: +// +// logger.Mark() // *MARK*: [file.go:123] +func Mark(names ...string) { + defaultLogger.mark(2, names...) + +} diff --git a/vendor/github.com/olekukonko/ll/lc.go b/vendor/github.com/olekukonko/ll/lc.go new file mode 100644 index 00000000..11871350 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lc.go @@ -0,0 +1,48 @@ +package ll + +import "github.com/olekukonko/ll/lx" + +// defaultStore is the global namespace store for enable/disable states. +// It is shared across all Logger instances to manage namespace hierarchy consistently. +// Thread-safe via the lx.Namespace struct’s sync.Map. +var defaultStore = &lx.Namespace{} + +// systemActive indicates if the global logging system is active. +// Defaults to true, meaning logging is active unless explicitly shut down. +// Or, default to false and require an explicit ll.Start(). Let's default to true for less surprise. +var systemActive int32 = 1 // 1 for true, 0 for false (for atomic operations) + +// Option defines a functional option for configuring a Logger. +type Option func(*Logger) + +// reverseString reverses the input string by swapping characters from both ends. +// It converts the string to a rune slice to handle Unicode characters correctly, +// ensuring proper reversal for multi-byte characters. +// Used internally for string manipulation, such as in debugging or log formatting. +func reverseString(s string) string { + // Convert string to rune slice to handle Unicode characters + r := []rune(s) + // Iterate over half the slice, swapping characters from start and end + for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { + r[i], r[j] = r[j], r[i] + } + // Convert rune slice back to string and return + return string(r) +} + +// viewString converts a byte slice to a printable string, replacing non-printable +// characters (ASCII < 32 or > 126) with a dot ('.'). +// It ensures safe display of binary data in logs, such as in the Dump method. +// Used for formatting binary data in a human-readable hex/ASCII dump. +func viewString(b []byte) string { + // Convert byte slice to rune slice via string for processing + r := []rune(string(b)) + // Replace non-printable characters with '.' + for i := range r { + if r[i] < 32 || r[i] > 126 { + r[i] = '.' + } + } + // Return the resulting printable string + return string(r) +} diff --git a/vendor/github.com/olekukonko/ll/lh/buffered.go b/vendor/github.com/olekukonko/ll/lh/buffered.go new file mode 100644 index 00000000..0fc8c14d --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/buffered.go @@ -0,0 +1,279 @@ +package lh + +import ( + "fmt" + "io" + "os" + "runtime" + "sync" + "time" + + "github.com/olekukonko/ll/lx" +) + +// Buffering holds configuration for the Buffered handler. +type Buffering struct { + BatchSize int // Flush when this many entries are buffered (default: 100) + FlushInterval time.Duration // Maximum time between flushes (default: 10s) + MaxBuffer int // Maximum buffer size before applying backpressure (default: 1000) + OnOverflow func(int) // Called when buffer reaches MaxBuffer (default: logs warning) +} + +// BufferingOpt configures Buffered handler. +type BufferingOpt func(*Buffering) + +// WithBatchSize sets the batch size for flushing. +// It specifies the number of log entries to buffer before flushing to the underlying handler. +// Example: +// +// handler := NewBuffered(textHandler, WithBatchSize(50)) // Flush every 50 entries +func WithBatchSize(size int) BufferingOpt { + return func(c *Buffering) { + c.BatchSize = size + } +} + +// WithFlushInterval sets the maximum time between flushes. +// It defines the interval at which buffered entries are flushed, even if the batch size is not reached. +// Example: +// +// handler := NewBuffered(textHandler, WithFlushInterval(5*time.Second)) // Flush every 5 seconds +func WithFlushInterval(d time.Duration) BufferingOpt { + return func(c *Buffering) { + c.FlushInterval = d + } +} + +// WithMaxBuffer sets the maximum buffer size before backpressure. +// It limits the number of entries that can be queued in the channel, triggering overflow handling if exceeded. +// Example: +// +// handler := NewBuffered(textHandler, WithMaxBuffer(500)) // Allow up to 500 buffered entries +func WithMaxBuffer(size int) BufferingOpt { + return func(c *Buffering) { + c.MaxBuffer = size + } +} + +// WithOverflowHandler sets the overflow callback. +// It specifies a function to call when the buffer reaches MaxBuffer, typically for logging or metrics. +// Example: +// +// handler := NewBuffered(textHandler, WithOverflowHandler(func(n int) { fmt.Printf("Overflow: %d entries\n", n) })) +func WithOverflowHandler(fn func(int)) BufferingOpt { + return func(c *Buffering) { + c.OnOverflow = fn + } +} + +// Buffered wraps any Handler to provide buffering capabilities. +// It buffers log entries in a channel and flushes them based on batch size, time interval, or explicit flush. +// The generic type H ensures compatibility with any lx.Handler implementation. +// Thread-safe via channels and sync primitives. +type Buffered[H lx.Handler] struct { + handler H // Underlying handler to process log entries + config *Buffering // Configuration for batching and flushing + entries chan *lx.Entry // Channel for buffering log entries + flushSignal chan struct{} // Channel to trigger explicit flushes + shutdown chan struct{} // Channel to signal worker shutdown + shutdownOnce sync.Once // Ensures Close is called only once + wg sync.WaitGroup // Waits for worker goroutine to finish +} + +// NewBuffered creates a new buffered handler that wraps another handler. +// It initializes the handler with default or provided configuration options and starts a worker goroutine. +// Thread-safe via channel operations and finalizer for cleanup. +// Example: +// +// textHandler := lh.NewTextHandler(os.Stdout) +// buffered := NewBuffered(textHandler, WithBatchSize(50)) +func NewBuffered[H lx.Handler](handler H, opts ...BufferingOpt) *Buffered[H] { + // Initialize default configuration + config := &Buffering{ + BatchSize: 100, // Default: flush every 100 entries + FlushInterval: 10 * time.Second, // Default: flush every 10 seconds + MaxBuffer: 1000, // Default: max 1000 entries in buffer + OnOverflow: func(count int) { // Default: log overflow to io.Discard + fmt.Fprintf(io.Discard, "log buffer overflow: %d entries\n", count) + }, + } + + // Apply provided options + for _, opt := range opts { + opt(config) + } + + // Ensure sane configuration values + if config.BatchSize < 1 { + config.BatchSize = 1 // Minimum batch size is 1 + } + if config.MaxBuffer < config.BatchSize { + config.MaxBuffer = config.BatchSize * 10 // Ensure buffer is at least 10x batch size + } + if config.FlushInterval <= 0 { + config.FlushInterval = 10 * time.Second // Minimum flush interval is 10s + } + + // Initialize Buffered handler + b := &Buffered[H]{ + handler: handler, // Set underlying handler + config: config, // Set configuration + entries: make(chan *lx.Entry, config.MaxBuffer), // Create buffered channel + flushSignal: make(chan struct{}, 1), // Create single-slot flush signal channel + shutdown: make(chan struct{}), // Create shutdown signal channel + } + + // Start worker goroutine + b.wg.Add(1) + go b.worker() + + // Set finalizer for cleanup during garbage collection + runtime.SetFinalizer(b, (*Buffered[H]).Final) + return b +} + +// Handle implements the lx.Handler interface. +// It buffers log entries in the entries channel or triggers a flush on overflow. +// Returns an error if the buffer is full and flush cannot be triggered. +// Thread-safe via non-blocking channel operations. +// Example: +// +// buffered.Handle(&lx.Entry{Message: "test"}) // Buffers entry or triggers flush +func (b *Buffered[H]) Handle(e *lx.Entry) error { + select { + case b.entries <- e: // Buffer entry if channel has space + return nil + default: // Handle buffer overflow + if b.config.OnOverflow != nil { + b.config.OnOverflow(len(b.entries)) // Call overflow handler + } + select { + case b.flushSignal <- struct{}{}: // Trigger flush if possible + return fmt.Errorf("log buffer overflow, triggering flush") + default: // Flush already in progress + return fmt.Errorf("log buffer overflow and flush already in progress") + } + } +} + +// Flush triggers an immediate flush of buffered entries. +// It sends a signal to the worker to process all buffered entries. +// If a flush is already pending, it waits briefly and may exit without flushing. +// Thread-safe via non-blocking channel operations. +// Example: +// +// buffered.Flush() // Flushes all buffered entries +func (b *Buffered[H]) Flush() { + select { + case b.flushSignal <- struct{}{}: // Signal worker to flush + case <-time.After(100 * time.Millisecond): // Timeout if flush is pending + // Flush already pending + } +} + +// Close flushes any remaining entries and stops the worker. +// It ensures shutdown is performed only once and waits for the worker to finish. +// Thread-safe via sync.Once and WaitGroup. +// Returns nil as it does not produce errors. +// Example: +// +// buffered.Close() // Flushes entries and stops worker +func (b *Buffered[H]) Close() error { + b.shutdownOnce.Do(func() { + close(b.shutdown) // Signal worker to shut down + b.wg.Wait() // Wait for worker to finish + runtime.SetFinalizer(b, nil) // Remove finalizer + }) + return nil +} + +// Final ensures remaining entries are flushed during garbage collection. +// It calls Close to flush entries and stop the worker. +// Used as a runtime finalizer to prevent log loss. +// Example (internal usage): +// +// runtime.SetFinalizer(buffered, (*Buffered[H]).Final) +func (b *Buffered[H]) Final() { + b.Close() +} + +// Config returns the current configuration of the Buffered handler. +// It provides access to BatchSize, FlushInterval, MaxBuffer, and OnOverflow settings. +// Example: +// +// config := buffered.Config() // Access configuration +func (b *Buffered[H]) Config() *Buffering { + return b.config +} + +// worker processes entries and handles flushing. +// It runs in a goroutine, buffering entries, flushing on batch size, timer, or explicit signal, +// and shutting down cleanly when signaled. +// Thread-safe via channel operations and WaitGroup. +func (b *Buffered[H]) worker() { + defer b.wg.Done() // Signal completion when worker exits + batch := make([]*lx.Entry, 0, b.config.BatchSize) // Buffer for batching entries + ticker := time.NewTicker(b.config.FlushInterval) // Timer for periodic flushes + defer ticker.Stop() // Clean up ticker + for { + select { + case entry := <-b.entries: // Receive new entry + batch = append(batch, entry) + // Flush if batch size is reached + if len(batch) >= b.config.BatchSize { + b.flushBatch(batch) + batch = batch[:0] + } + case <-ticker.C: // Periodic flush + if len(batch) > 0 { + b.flushBatch(batch) + batch = batch[:0] + } + case <-b.flushSignal: // Explicit flush + if len(batch) > 0 { + b.flushBatch(batch) + batch = batch[:0] + } + b.drainRemaining() // Drain all entries from the channel + case <-b.shutdown: // Shutdown signal + if len(batch) > 0 { + b.flushBatch(batch) + } + b.drainRemaining() // Flush remaining entries + return + } + } +} + +// flushBatch processes a batch of entries through the wrapped handler. +// It writes each entry to the underlying handler, logging any errors to stderr. +// Example (internal usage): +// +// b.flushBatch([]*lx.Entry{entry1, entry2}) +func (b *Buffered[H]) flushBatch(batch []*lx.Entry) { + for _, entry := range batch { + // Process each entry through the handler + if err := b.handler.Handle(entry); err != nil { + fmt.Fprintf(os.Stderr, "log flush error: %v\n", err) // Log errors to stderr + } + } +} + +// drainRemaining processes any remaining entries in the channel. +// It flushes all entries from the entries channel to the underlying handler, +// logging any errors to stderr. Used during flush or shutdown. +// Example (internal usage): +// +// b.drainRemaining() // Flushes all pending entries +func (b *Buffered[H]) drainRemaining() { + for { + select { + case entry := <-b.entries: // Process next entry + if err := b.handler.Handle(entry); err != nil { + fmt.Fprintf(os.Stderr, "log drain error: %v\n", err) // Log errors to stderr + } + default: // Exit when channel is empty + return + } + } +} diff --git a/vendor/github.com/olekukonko/ll/lh/colorized.go b/vendor/github.com/olekukonko/ll/lh/colorized.go new file mode 100644 index 00000000..3dbfed30 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/colorized.go @@ -0,0 +1,439 @@ +package lh + +import ( + "fmt" + "github.com/olekukonko/ll/lx" + "io" + "os" + "sort" + "strings" +) + +// Palette defines ANSI color codes for various log components. +// It specifies colors for headers, goroutines, functions, paths, stack traces, and log levels, +// used by ColorizedHandler to format log output with color. +type Palette struct { + Header string // Color for stack trace header and dump separators + Goroutine string // Color for goroutine lines in stack traces + Func string // Color for function names in stack traces + Path string // Color for file paths in stack traces + FileLine string // Color for file line numbers (not used in provided code) + Reset string // Reset code to clear color formatting + Pos string // Color for position in hex dumps + Hex string // Color for hex values in dumps + Ascii string // Color for ASCII values in dumps + Debug string // Color for Debug level messages + Info string // Color for Info level messages + Warn string // Color for Warn level messages + Error string // Color for Error level messages + Title string // Color for dump titles (BEGIN/END separators) +} + +// darkPalette defines colors optimized for dark terminal backgrounds. +// It uses bright, contrasting colors for readability on dark backgrounds. +var darkPalette = Palette{ + Header: "\033[1;31m", // Bold red for headers + Goroutine: "\033[1;36m", // Bold cyan for goroutines + Func: "\033[97m", // Bright white for functions + Path: "\033[38;5;245m", // Light gray for paths + FileLine: "\033[38;5;111m", // Muted light blue (unused) + Reset: "\033[0m", // Reset color formatting + + Title: "\033[38;5;245m", // Light gray for dump titles + Pos: "\033[38;5;117m", // Light blue for dump positions + Hex: "\033[38;5;156m", // Light green for hex values + Ascii: "\033[38;5;224m", // Light pink for ASCII values + + Debug: "\033[36m", // Cyan for Debug level + Info: "\033[32m", // Green for Info level + Warn: "\033[33m", // Yellow for Warn level + Error: "\033[31m", // Red for Error level +} + +// lightPalette defines colors optimized for light terminal backgrounds. +// It uses darker colors for better contrast on light backgrounds. +var lightPalette = Palette{ + Header: "\033[1;31m", // Same red for headers + Goroutine: "\033[34m", // Blue (darker for light bg) + Func: "\033[30m", // Black text for functions + Path: "\033[90m", // Dark gray for paths + FileLine: "\033[94m", // Blue for file lines (unused) + Reset: "\033[0m", // Reset color formatting + + Title: "\033[38;5;245m", // Light gray for dump titles + Pos: "\033[38;5;117m", // Light blue for dump positions + Hex: "\033[38;5;156m", // Light green for hex values + Ascii: "\033[38;5;224m", // Light pink for ASCII values + + Debug: "\033[36m", // Cyan for Debug level + Info: "\033[32m", // Green for Info level + Warn: "\033[33m", // Yellow for Warn level + Error: "\033[31m", // Red for Error level +} + +// ColorizedHandler is a handler that outputs log entries with ANSI color codes. +// It formats log entries with colored namespace, level, message, fields, and stack traces, +// writing the result to the provided writer. +// Thread-safe if the underlying writer is thread-safe. +type ColorizedHandler struct { + w io.Writer // Destination for colored log output + palette Palette // Color scheme for formatting +} + +// ColorOption defines a configuration function for ColorizedHandler. +// It allows customization of the handler, such as setting the color palette. +type ColorOption func(*ColorizedHandler) + +// WithColorPallet sets the color palette for the ColorizedHandler. +// It allows specifying a custom Palette for dark or light terminal backgrounds. +// Example: +// +// handler := NewColorizedHandler(os.Stdout, WithColorPallet(lightPalette)) +func WithColorPallet(pallet Palette) ColorOption { + return func(c *ColorizedHandler) { + c.palette = pallet + } +} + +// NewColorizedHandler creates a new ColorizedHandler writing to the specified writer. +// It initializes the handler with a detected or specified color palette and applies +// optional configuration functions. +// Example: +// +// handler := NewColorizedHandler(os.Stdout) +// logger := ll.New("app").Enable().Handler(handler) +// logger.Info("Test") // Output: [app] : Test +func NewColorizedHandler(w io.Writer, opts ...ColorOption) *ColorizedHandler { + c := &ColorizedHandler{w: w} // Initialize with writer + // Apply configuration options + for _, opt := range opts { + opt(c) + } + // Detect palette if not set + c.palette = c.detectPalette() + return c +} + +// Handle processes a log entry and writes it with ANSI color codes. +// It delegates to specialized methods based on the entry's class (Dump, Raw, or regular). +// Returns an error if writing to the underlying writer fails. +// Thread-safe if the writer is thread-safe. +// Example: +// +// handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes colored output +func (h *ColorizedHandler) Handle(e *lx.Entry) error { + switch e.Class { + case lx.ClassDump: + // Handle hex dump entries + return h.handleDumpOutput(e) + case lx.ClassRaw: + // Write raw entries directly + _, err := h.w.Write([]byte(e.Message)) + return err + default: + // Handle standard log entries + return h.handleRegularOutput(e) + } +} + +// handleRegularOutput handles normal log entries. +// It formats the entry with colored namespace, level, message, fields, and stack trace (if present), +// writing the result to the handler's writer. +// Returns an error if writing fails. +// Example (internal usage): +// +// h.handleRegularOutput(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes colored output +func (h *ColorizedHandler) handleRegularOutput(e *lx.Entry) error { + var builder strings.Builder // Buffer for building formatted output + + // Format namespace with colors + h.formatNamespace(&builder, e) + + // Format level with color based on severity + h.formatLevel(&builder, e) + + // Add message and fields + builder.WriteString(e.Message) + h.formatFields(&builder, e) + + // fmt.Println("------------>", len(e.Stack)) + // Format stack trace if present + if len(e.Stack) > 0 { + h.formatStack(&builder, e.Stack) + } + + // Append newline for non-None levels + if e.Level != lx.LevelNone { + builder.WriteString(lx.Newline) + } + + // Write formatted output to writer + _, err := h.w.Write([]byte(builder.String())) + return err +} + +// formatNamespace formats the namespace with ANSI color codes. +// It supports FlatPath ([parent/child]) and NestedPath ([parent]→[child]) styles. +// Example (internal usage): +// +// h.formatNamespace(&builder, &lx.Entry{Namespace: "parent/child", Style: lx.FlatPath}) // Writes "[parent/child]: " +func (h *ColorizedHandler) formatNamespace(b *strings.Builder, e *lx.Entry) { + if e.Namespace == "" { + return + } + + b.WriteString(lx.LeftBracket) + switch e.Style { + case lx.NestedPath: + // Split namespace and format as [parent]→[child] + parts := strings.Split(e.Namespace, lx.Slash) + for i, part := range parts { + b.WriteString(part) + b.WriteString(lx.RightBracket) + if i < len(parts)-1 { + b.WriteString(lx.Arrow) + b.WriteString(lx.LeftBracket) + } + } + default: // FlatPath + // Format as [parent/child] + b.WriteString(e.Namespace) + b.WriteString(lx.RightBracket) + } + b.WriteString(lx.Colon) + b.WriteString(lx.Space) +} + +// formatLevel formats the log level with ANSI color codes. +// It applies a color based on the level (Debug, Info, Warn, Error) and resets afterward. +// Example (internal usage): +// +// h.formatLevel(&builder, &lx.Entry{Level: lx.LevelInfo}) // Writes "INFO: " +func (h *ColorizedHandler) formatLevel(b *strings.Builder, e *lx.Entry) { + // Map levels to colors + color := map[lx.LevelType]string{ + lx.LevelDebug: h.palette.Debug, // Cyan + lx.LevelInfo: h.palette.Info, // Green + lx.LevelWarn: h.palette.Warn, // Yellow + lx.LevelError: h.palette.Error, // Red + }[e.Level] + + b.WriteString(color) + b.WriteString(e.Level.String()) + b.WriteString(h.palette.Reset) + b.WriteString(lx.Colon) + b.WriteString(lx.Space) +} + +// formatFields formats the log entry's fields in sorted order. +// It writes fields as [key=value key=value], with no additional coloring. +// Example (internal usage): +// +// h.formatFields(&builder, &lx.Entry{Fields: map[string]interface{}{"key": "value"}}) // Writes " [key=value]" +func (h *ColorizedHandler) formatFields(b *strings.Builder, e *lx.Entry) { + if len(e.Fields) == 0 { + return + } + + // Collect and sort field keys + var keys []string + for k := range e.Fields { + keys = append(keys, k) + } + sort.Strings(keys) + + b.WriteString(lx.Space) + b.WriteString(lx.LeftBracket) + // Format fields as key=value + for i, k := range keys { + if i > 0 { + b.WriteString(lx.Space) + } + b.WriteString(k) + b.WriteString("=") + b.WriteString(fmt.Sprint(e.Fields[k])) + } + b.WriteString(lx.RightBracket) +} + +// formatStack formats a stack trace with ANSI color codes. +// It structures the stack trace with colored goroutine, function, and path segments, +// using indentation and separators for readability. +// Example (internal usage): +// +// h.formatStack(&builder, []byte("goroutine 1 [running]:\nmain.main()\n\tmain.go:10")) // Appends colored stack trace +func (h *ColorizedHandler) formatStack(b *strings.Builder, stack []byte) { + b.WriteString("\n") + b.WriteString(h.palette.Header) + b.WriteString("[stack]") + b.WriteString(h.palette.Reset) + b.WriteString("\n") + + lines := strings.Split(string(stack), "\n") + if len(lines) == 0 { + return + } + + // Format goroutine line + b.WriteString(" ┌─ ") + b.WriteString(h.palette.Goroutine) + b.WriteString(lines[0]) + b.WriteString(h.palette.Reset) + b.WriteString("\n") + + // Pair function name and file path lines + for i := 1; i < len(lines)-1; i += 2 { + funcLine := strings.TrimSpace(lines[i]) + pathLine := strings.TrimSpace(lines[i+1]) + + if funcLine != "" { + b.WriteString(" │ ") + b.WriteString(h.palette.Func) + b.WriteString(funcLine) + b.WriteString(h.palette.Reset) + b.WriteString("\n") + } + if pathLine != "" { + b.WriteString(" │ ") + + // Look for last "/" before ".go:" + lastSlash := strings.LastIndex(pathLine, "/") + goIndex := strings.Index(pathLine, ".go:") + + if lastSlash >= 0 && goIndex > lastSlash { + // Prefix path + prefix := pathLine[:lastSlash+1] + // File and line (e.g., ll.go:698 +0x5c) + suffix := pathLine[lastSlash+1:] + + b.WriteString(h.palette.Path) + b.WriteString(prefix) + b.WriteString(h.palette.Reset) + + b.WriteString(h.palette.Path) // Use mainPath color for suffix + b.WriteString(suffix) + b.WriteString(h.palette.Reset) + } else { + // Fallback: whole line is gray + b.WriteString(h.palette.Path) + b.WriteString(pathLine) + b.WriteString(h.palette.Reset) + } + + b.WriteString("\n") + } + } + + // Handle any remaining unpaired line + if len(lines)%2 == 0 && strings.TrimSpace(lines[len(lines)-1]) != "" { + b.WriteString(" │ ") + b.WriteString(h.palette.Func) + b.WriteString(strings.TrimSpace(lines[len(lines)-1])) + b.WriteString(h.palette.Reset) + b.WriteString("\n") + } + + b.WriteString(" └\n") +} + +// handleDumpOutput formats hex dump output with ANSI color codes. +// It applies colors to position, hex, ASCII, and title components of the dump, +// wrapping the output with colored BEGIN/END separators. +// Returns an error if writing fails. +// Example (internal usage): +// +// h.handleDumpOutput(&lx.Entry{Class: lx.ClassDump, Message: "pos 00 hex: 61 62 'ab'"}) // Writes colored dump +func (h *ColorizedHandler) handleDumpOutput(e *lx.Entry) error { + var builder strings.Builder + // Write colored BEGIN separator + builder.WriteString(h.palette.Title) + builder.WriteString("---- BEGIN DUMP ----") + builder.WriteString(h.palette.Reset) + builder.WriteString("\n") + + // Process each line of the dump + lines := strings.Split(e.Message, "\n") + length := len(lines) + for i, line := range lines { + if strings.HasPrefix(line, "pos ") { + // Parse and color position and hex/ASCII parts + parts := strings.SplitN(line, "hex:", 2) + if len(parts) == 2 { + builder.WriteString(h.palette.Pos) + builder.WriteString(parts[0]) + builder.WriteString(h.palette.Reset) + + hexAscii := strings.SplitN(parts[1], "'", 2) + builder.WriteString(h.palette.Hex) + builder.WriteString("hex:") + builder.WriteString(hexAscii[0]) + builder.WriteString(h.palette.Reset) + + if len(hexAscii) > 1 { + builder.WriteString(h.palette.Ascii) + builder.WriteString("'") + builder.WriteString(hexAscii[1]) + builder.WriteString(h.palette.Reset) + } + } + } else if strings.HasPrefix(line, "Dumping value of type:") { + // Color type dump lines + builder.WriteString(h.palette.Header) + builder.WriteString(line) + builder.WriteString(h.palette.Reset) + } else { + // Write non-dump lines as-is + builder.WriteString(line) + } + + // Don't add newline for the last line + if i < length-1 { + builder.WriteString("\n") + } + } + + // Write colored END separator + builder.WriteString(h.palette.Title) + builder.WriteString("---- END DUMP ----") + builder.WriteString(h.palette.Reset) + builder.WriteString("\n") + + // Write formatted output to writer + _, err := h.w.Write([]byte(builder.String())) + return err +} + +// detectPalette selects a color palette based on terminal environment variables. +// It checks TERM_BACKGROUND, COLORFGBG, and AppleInterfaceStyle to determine +// whether a light or dark palette is appropriate, defaulting to darkPalette. +// Example (internal usage): +// +// palette := h.detectPalette() // Returns darkPalette or lightPalette +func (h *ColorizedHandler) detectPalette() Palette { + // Check TERM_BACKGROUND (e.g., iTerm2) + if bg, ok := os.LookupEnv("TERM_BACKGROUND"); ok { + if bg == "light" { + return lightPalette // Use light palette for light background + } + return darkPalette // Use dark palette otherwise + } + + // Check COLORFGBG (traditional xterm) + if fgBg, ok := os.LookupEnv("COLORFGBG"); ok { + parts := strings.Split(fgBg, ";") + if len(parts) >= 2 { + bg := parts[len(parts)-1] // Last part (some terminals add more fields) + if bg == "7" || bg == "15" || bg == "0;15" { // Handle variations + return lightPalette // Use light palette for light background + } + } + } + + // Check macOS dark mode + if style, ok := os.LookupEnv("AppleInterfaceStyle"); ok && strings.EqualFold(style, "dark") { + return darkPalette // Use dark palette for macOS dark mode + } + + // Default: dark (conservative choice for terminals) + return darkPalette +} diff --git a/vendor/github.com/olekukonko/ll/lh/json.go b/vendor/github.com/olekukonko/ll/lh/json.go new file mode 100644 index 00000000..c40576d6 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/json.go @@ -0,0 +1,170 @@ +package lh + +import ( + "encoding/json" + "fmt" + "github.com/olekukonko/ll/lx" + "io" + "os" + "strings" + "sync" + "time" +) + +// JSONHandler is a handler that outputs log entries as JSON objects. +// It formats log entries with timestamp, level, message, namespace, fields, and optional +// stack traces or dump segments, writing the result to the provided writer. +// Thread-safe with a mutex to protect concurrent writes. +type JSONHandler struct { + writer io.Writer // Destination for JSON output + timeFmt string // Format for timestamp (default: RFC3339Nano) + pretty bool // Enable pretty printing with indentation if true + fieldMap map[string]string // Optional mapping for field names (not used in provided code) + mu sync.Mutex // Protects concurrent access to writer +} + +// JsonOutput represents the JSON structure for a log entry. +// It includes all relevant log data, such as timestamp, level, message, and optional +// stack trace or dump segments, serialized as a JSON object. +type JsonOutput struct { + Time string `json:"ts"` // Timestamp in specified format + Level string `json:"lvl"` // Log level (e.g., "INFO") + Class string `json:"class"` // Entry class (e.g., "Text", "Dump") + Msg string `json:"msg"` // Log message + Namespace string `json:"ns"` // Namespace path + Stack []byte `json:"stack"` // Stack trace (if present) + Dump []dumpSegment `json:"dump"` // Hex/ASCII dump segments (for ClassDump) + Fields map[string]interface{} `json:"fields"` // Custom fields +} + +// dumpSegment represents a single segment of a hex/ASCII dump. +// Used for ClassDump entries to structure position, hex values, and ASCII representation. +type dumpSegment struct { + Offset int `json:"offset"` // Starting byte offset of the segment + Hex []string `json:"hex"` // Hexadecimal values of bytes + ASCII string `json:"ascii"` // ASCII representation of bytes +} + +// NewJSONHandler creates a new JSONHandler writing to the specified writer. +// It initializes the handler with a default timestamp format (RFC3339Nano) and optional +// configuration functions to customize settings like pretty printing. +// Example: +// +// handler := NewJSONHandler(os.Stdout) +// logger := ll.New("app").Enable().Handler(handler) +// logger.Info("Test") // Output: {"ts":"...","lvl":"INFO","class":"Text","msg":"Test","ns":"app","stack":null,"dump":null,"fields":null} +func NewJSONHandler(w io.Writer, opts ...func(*JSONHandler)) *JSONHandler { + h := &JSONHandler{ + writer: w, // Set output writer + timeFmt: time.RFC3339Nano, // Default timestamp format + } + // Apply configuration options + for _, opt := range opts { + opt(h) + } + return h +} + +// Handle processes a log entry and writes it as JSON. +// It delegates to specialized methods based on the entry's class (Dump or regular), +// ensuring thread-safety with a mutex. +// Returns an error if JSON encoding or writing fails. +// Example: +// +// handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes JSON object +func (h *JSONHandler) Handle(e *lx.Entry) error { + h.mu.Lock() + defer h.mu.Unlock() + + // Handle dump entries separately + if e.Class == lx.ClassDump { + return h.handleDump(e) + } + // Handle standard log entries + return h.handleRegular(e) +} + +// handleRegular handles standard log entries (non-dump). +// It converts the entry to a JsonOutput struct and encodes it as JSON, +// applying pretty printing if enabled. Logs encoding errors to stderr for debugging. +// Returns an error if encoding or writing fails. +// Example (internal usage): +// +// h.handleRegular(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes JSON object +func (h *JSONHandler) handleRegular(e *lx.Entry) error { + // Create JSON output structure + entry := JsonOutput{ + Time: e.Timestamp.Format(h.timeFmt), // Format timestamp + Level: e.Level.String(), // Convert level to string + Class: e.Class.String(), // Convert class to string + Msg: e.Message, // Set message + Namespace: e.Namespace, // Set namespace + Dump: nil, // No dump for regular entries + Fields: e.Fields, // Copy fields + Stack: e.Stack, // Include stack trace if present + } + // Create JSON encoder + enc := json.NewEncoder(h.writer) + if h.pretty { + // Enable indentation for pretty printing + enc.SetIndent("", " ") + } + // Log encoding attempt for debugging + fmt.Fprintf(os.Stderr, "Encoding JSON entry: %v\n", e.Message) + // Encode and write JSON + err := enc.Encode(entry) + if err != nil { + // Log encoding error for debugging + fmt.Fprintf(os.Stderr, "JSON encode error: %v\n", err) + } + return err +} + +// handleDump processes ClassDump entries, converting hex dump output to JSON segments. +// It parses the dump message into structured segments with offset, hex, and ASCII data, +// encoding them as a JsonOutput struct. +// Returns an error if parsing or encoding fails. +// Example (internal usage): +// +// h.handleDump(&lx.Entry{Class: lx.ClassDump, Message: "pos 00 hex: 61 62 'ab'"}) // Writes JSON with dump segments +func (h *JSONHandler) handleDump(e *lx.Entry) error { + var segments []dumpSegment + lines := strings.Split(e.Message, "\n") + + // Parse each line of the dump message + for _, line := range lines { + if !strings.HasPrefix(line, "pos") { + continue // Skip non-dump lines + } + parts := strings.SplitN(line, "hex:", 2) + if len(parts) != 2 { + continue // Skip invalid lines + } + // Parse position + var offset int + fmt.Sscanf(parts[0], "pos %d", &offset) + + // Parse hex and ASCII + hexAscii := strings.SplitN(parts[1], "'", 2) + hexStr := strings.Fields(strings.TrimSpace(hexAscii[0])) + + // Create dump segment + segments = append(segments, dumpSegment{ + Offset: offset, // Set byte offset + Hex: hexStr, // Set hex values + ASCII: strings.Trim(hexAscii[1], "'"), // Set ASCII representation + }) + } + + // Encode JSON output with dump segments + return json.NewEncoder(h.writer).Encode(JsonOutput{ + Time: e.Timestamp.Format(h.timeFmt), // Format timestamp + Level: e.Level.String(), // Convert level to string + Class: e.Class.String(), // Convert class to string + Msg: "dumping segments", // Fixed message for dumps + Namespace: e.Namespace, // Set namespace + Dump: segments, // Include parsed segments + Fields: e.Fields, // Copy fields + Stack: e.Stack, // Include stack trace if present + }) +} diff --git a/vendor/github.com/olekukonko/ll/lh/memory.go b/vendor/github.com/olekukonko/ll/lh/memory.go new file mode 100644 index 00000000..78ac918a --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/memory.go @@ -0,0 +1,93 @@ +package lh + +import ( + "fmt" + "github.com/olekukonko/ll/lx" + "io" + "sync" +) + +// MemoryHandler is an lx.Handler that stores log entries in memory. +// Useful for testing or buffering logs for later inspection. +// It maintains a thread-safe slice of log entries, protected by a read-write mutex. +type MemoryHandler struct { + mu sync.RWMutex // Protects concurrent access to entries + entries []*lx.Entry // Slice of stored log entries +} + +// NewMemoryHandler creates a new MemoryHandler. +// It initializes an empty slice for storing log entries, ready for use in logging or testing. +// Example: +// +// handler := NewMemoryHandler() +// logger := ll.New("app").Enable().Handler(handler) +// logger.Info("Test") // Stores entry in memory +func NewMemoryHandler() *MemoryHandler { + return &MemoryHandler{ + entries: make([]*lx.Entry, 0), // Initialize empty slice for entries + } +} + +// Handle stores the log entry in memory. +// It appends the provided entry to the entries slice, ensuring thread-safety with a write lock. +// Always returns nil, as it does not perform I/O operations. +// Example: +// +// handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Stores entry +func (h *MemoryHandler) Handle(entry *lx.Entry) error { + h.mu.Lock() + defer h.mu.Unlock() + h.entries = append(h.entries, entry) // Append entry to slice + return nil +} + +// Entries returns a copy of the stored log entries. +// It creates a new slice with copies of all entries, ensuring thread-safety with a read lock. +// The returned slice is safe for external use without affecting the handler's internal state. +// Example: +// +// entries := handler.Entries() // Returns copy of stored entries +func (h *MemoryHandler) Entries() []*lx.Entry { + h.mu.RLock() + defer h.mu.RUnlock() + entries := make([]*lx.Entry, len(h.entries)) // Create new slice for copy + copy(entries, h.entries) // Copy entries to new slice + return entries +} + +// Reset clears all stored entries. +// It truncates the entries slice to zero length, preserving capacity, using a write lock for thread-safety. +// Example: +// +// handler.Reset() // Clears all stored entries +func (h *MemoryHandler) Reset() { + h.mu.Lock() + defer h.mu.Unlock() + h.entries = h.entries[:0] // Truncate slice to zero length +} + +// Dump writes all stored log entries to the provided io.Writer in text format. +// Entries are formatted as they would be by a TextHandler, including namespace, level, +// message, and fields. Thread-safe with read lock. +// Returns an error if writing fails. +// Example: +// +// logger := ll.New("test", ll.WithHandler(NewMemoryHandler())).Enable() +// logger.Info("Test message") +// handler := logger.handler.(*MemoryHandler) +// handler.Dump(os.Stdout) // Output: [test] INFO: Test message +func (h *MemoryHandler) Dump(w io.Writer) error { + h.mu.RLock() + defer h.mu.RUnlock() + + // Create a temporary TextHandler to format entries + tempHandler := NewTextHandler(w) + + // Process each entry through the TextHandler + for _, entry := range h.entries { + if err := tempHandler.Handle(entry); err != nil { + return fmt.Errorf("failed to dump entry: %w", err) // Wrap and return write errors + } + } + return nil +} diff --git a/vendor/github.com/olekukonko/ll/lh/multi.go b/vendor/github.com/olekukonko/ll/lh/multi.go new file mode 100644 index 00000000..8a9d8846 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/multi.go @@ -0,0 +1,51 @@ +package lh + +import ( + "errors" + "fmt" + "github.com/olekukonko/ll/lx" +) + +// MultiHandler combines multiple handlers to process log entries concurrently. +// It holds a list of lx.Handler instances and delegates each log entry to all handlers, +// collecting any errors into a single combined error. +// Thread-safe if the underlying handlers are thread-safe. +type MultiHandler struct { + Handlers []lx.Handler // List of handlers to process each log entry +} + +// NewMultiHandler creates a new MultiHandler with the specified handlers. +// It accepts a variadic list of handlers to be executed in order. +// The returned handler processes log entries by passing them to each handler in sequence. +// Example: +// +// textHandler := NewTextHandler(os.Stdout) +// jsonHandler := NewJSONHandler(os.Stdout) +// multi := NewMultiHandler(textHandler, jsonHandler) +// logger := ll.New("app").Enable().Handler(multi) +// logger.Info("Test") // Processed by both text and JSON handlers +func NewMultiHandler(h ...lx.Handler) *MultiHandler { + return &MultiHandler{ + Handlers: h, // Initialize with provided handlers + } +} + +// Handle implements the Handler interface, calling Handle on each handler in sequence. +// It collects any errors from handlers and combines them into a single error using errors.Join. +// If no errors occur, it returns nil. Thread-safe if the underlying handlers are thread-safe. +// Example: +// +// multi.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Calls Handle on all handlers +func (h *MultiHandler) Handle(e *lx.Entry) error { + var errs []error // Collect errors from handlers + for i, handler := range h.Handlers { + // Process entry with each handler + if err := handler.Handle(e); err != nil { + // fmt.Fprintf(os.Stderr, "MultiHandler error for handler %d: %v\n", i, err) + // Wrap error with handler index for context + errs = append(errs, fmt.Errorf("handler %d: %w", i, err)) + } + } + // Combine errors into a single error, or return nil if no errors + return errors.Join(errs...) +} diff --git a/vendor/github.com/olekukonko/ll/lh/slog.go b/vendor/github.com/olekukonko/ll/lh/slog.go new file mode 100644 index 00000000..77584202 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/slog.go @@ -0,0 +1,89 @@ +package lh + +import ( + "context" + "github.com/olekukonko/ll/lx" + "log/slog" +) + +// SlogHandler adapts a slog.Handler to implement lx.Handler. +// It converts lx.Entry objects to slog.Record objects and delegates to an underlying +// slog.Handler for processing, enabling compatibility with Go's standard slog package. +// Thread-safe if the underlying slog.Handler is thread-safe. +type SlogHandler struct { + slogHandler slog.Handler // Underlying slog.Handler for processing log records +} + +// NewSlogHandler creates a new SlogHandler wrapping the provided slog.Handler. +// It initializes the handler with the given slog.Handler, allowing lx.Entry logs to be +// processed by slog's logging infrastructure. +// Example: +// +// slogText := slog.NewTextHandler(os.Stdout, nil) +// handler := NewSlogHandler(slogText) +// logger := ll.New("app").Enable().Handler(handler) +// logger.Info("Test") // Output: level=INFO msg=Test namespace=app class=Text +func NewSlogHandler(h slog.Handler) *SlogHandler { + return &SlogHandler{slogHandler: h} +} + +// Handle converts an lx.Entry to slog.Record and delegates to the slog.Handler. +// It maps the entry's fields, level, namespace, class, and stack trace to slog attributes, +// passing the resulting record to the underlying slog.Handler. +// Returns an error if the slog.Handler fails to process the record. +// Thread-safe if the underlying slog.Handler is thread-safe. +// Example: +// +// handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Processes as slog record +func (h *SlogHandler) Handle(e *lx.Entry) error { + // Convert lx.LevelType to slog.Level + level := toSlogLevel(e.Level) + + // Create a slog.Record with the entry's data + record := slog.NewRecord( + e.Timestamp, // time.Time for log timestamp + level, // slog.Level for log severity + e.Message, // string for log message + 0, // pc (program counter, optional, not used) + ) + + // Add standard fields as attributes + record.AddAttrs( + slog.String("namespace", e.Namespace), // Add namespace as string attribute + slog.String("class", e.Class.String()), // Add class as string attribute + ) + + // Add stack trace if present + if len(e.Stack) > 0 { + record.AddAttrs(slog.String("stack", string(e.Stack))) // Add stack trace as string + } + + // Add custom fields + for k, v := range e.Fields { + record.AddAttrs(slog.Any(k, v)) // Add each field as a key-value attribute + } + + // Handle the record with the underlying slog.Handler + return h.slogHandler.Handle(context.Background(), record) +} + +// toSlogLevel converts lx.LevelType to slog.Level. +// It maps the logging levels used by the lx package to those used by slog, +// defaulting to slog.LevelInfo for unknown levels. +// Example (internal usage): +// +// level := toSlogLevel(lx.LevelDebug) // Returns slog.LevelDebug +func toSlogLevel(level lx.LevelType) slog.Level { + switch level { + case lx.LevelDebug: + return slog.LevelDebug + case lx.LevelInfo: + return slog.LevelInfo + case lx.LevelWarn: + return slog.LevelWarn + case lx.LevelError: + return slog.LevelError + default: + return slog.LevelInfo // Default for unknown levels + } +} diff --git a/vendor/github.com/olekukonko/ll/lh/text.go b/vendor/github.com/olekukonko/ll/lh/text.go new file mode 100644 index 00000000..3b0a85ce --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lh/text.go @@ -0,0 +1,193 @@ +package lh + +import ( + "fmt" + "github.com/olekukonko/ll/lx" + "io" + "sort" + "strings" +) + +// TextHandler is a handler that outputs log entries as plain text. +// It formats log entries with namespace, level, message, fields, and optional stack traces, +// writing the result to the provided writer. +// Thread-safe if the underlying writer is thread-safe. +type TextHandler struct { + w io.Writer // Destination for formatted log output +} + +// NewTextHandler creates a new TextHandler writing to the specified writer. +// It initializes the handler with the given writer, suitable for outputs like stdout or files. +// Example: +// +// handler := NewTextHandler(os.Stdout) +// logger := ll.New("app").Enable().Handler(handler) +// logger.Info("Test") // Output: [app] INFO: Test +func NewTextHandler(w io.Writer) *TextHandler { + return &TextHandler{w: w} +} + +// Handle processes a log entry and writes it as plain text. +// It delegates to specialized methods based on the entry's class (Dump, Raw, or regular). +// Returns an error if writing to the underlying writer fails. +// Thread-safe if the writer is thread-safe. +// Example: +// +// handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes "INFO: test" +func (h *TextHandler) Handle(e *lx.Entry) error { + // Special handling for dump output + if e.Class == lx.ClassDump { + return h.handleDumpOutput(e) + } + + // Raw entries are written directly without formatting + if e.Class == lx.ClassRaw { + _, err := h.w.Write([]byte(e.Message)) + return err + } + + // Handle standard log entries + return h.handleRegularOutput(e) +} + +// handleRegularOutput handles normal log entries. +// It formats the entry with namespace, level, message, fields, and stack trace (if present), +// writing the result to the handler's writer. +// Returns an error if writing fails. +// Example (internal usage): +// +// h.handleRegularOutput(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes "INFO: test" +func (h *TextHandler) handleRegularOutput(e *lx.Entry) error { + var builder strings.Builder // Buffer for building formatted output + + // Format namespace based on style + switch e.Style { + case lx.NestedPath: + if e.Namespace != "" { + // Split namespace into parts and format as [parent]→[child] + parts := strings.Split(e.Namespace, lx.Slash) + for i, part := range parts { + builder.WriteString(lx.LeftBracket) + builder.WriteString(part) + builder.WriteString(lx.RightBracket) + if i < len(parts)-1 { + builder.WriteString(lx.Arrow) + } + } + builder.WriteString(lx.Colon) + builder.WriteString(lx.Space) + } + default: // FlatPath + if e.Namespace != "" { + // Format namespace as [parent/child] + builder.WriteString(lx.LeftBracket) + builder.WriteString(e.Namespace) + builder.WriteString(lx.RightBracket) + builder.WriteString(lx.Space) + } + } + + // Add level and message + builder.WriteString(e.Level.String()) + builder.WriteString(lx.Colon) + builder.WriteString(lx.Space) + builder.WriteString(e.Message) + + // Add fields in sorted order + if len(e.Fields) > 0 { + var keys []string + for k := range e.Fields { + keys = append(keys, k) + } + // Sort keys for consistent output + sort.Strings(keys) + builder.WriteString(lx.Space) + builder.WriteString(lx.LeftBracket) + for i, k := range keys { + if i > 0 { + builder.WriteString(lx.Space) + } + // Format field as key=value + builder.WriteString(k) + builder.WriteString("=") + builder.WriteString(fmt.Sprint(e.Fields[k])) + } + builder.WriteString(lx.RightBracket) + } + + // Add stack trace if present + if len(e.Stack) > 0 { + h.formatStack(&builder, e.Stack) + } + + // Append newline for non-None levels + if e.Level != lx.LevelNone { + builder.WriteString(lx.Newline) + } + + // Write formatted output to writer + _, err := h.w.Write([]byte(builder.String())) + return err +} + +// handleDumpOutput specially formats hex dump output (plain text version). +// It wraps the dump message with BEGIN/END separators for clarity. +// Returns an error if writing fails. +// Example (internal usage): +// +// h.handleDumpOutput(&lx.Entry{Class: lx.ClassDump, Message: "pos 00 hex: 61"}) // Writes "---- BEGIN DUMP ----\npos 00 hex: 61\n---- END DUMP ----\n" +func (h *TextHandler) handleDumpOutput(e *lx.Entry) error { + // For text handler, we just add a newline before dump output + var builder strings.Builder // Buffer for building formatted output + + // Add separator lines and dump content + builder.WriteString("---- BEGIN DUMP ----\n") + builder.WriteString(e.Message) + builder.WriteString("---- END DUMP ----\n") + + // Write formatted output to writer + _, err := h.w.Write([]byte(builder.String())) + return err +} + +// formatStack formats a stack trace for plain text output. +// It structures the stack trace with indentation and separators for readability, +// including goroutine and function/file details. +// Example (internal usage): +// +// h.formatStack(&builder, []byte("goroutine 1 [running]:\nmain.main()\n\tmain.go:10")) // Appends formatted stack trace +func (h *TextHandler) formatStack(b *strings.Builder, stack []byte) { + lines := strings.Split(string(stack), "\n") + if len(lines) == 0 { + return + } + + // Start stack trace section + b.WriteString("\n[stack]\n") + + // First line: goroutine + b.WriteString(" ┌─ ") + b.WriteString(lines[0]) + b.WriteString("\n") + + // Iterate through remaining lines + for i := 1; i < len(lines); i++ { + line := strings.TrimSpace(lines[i]) + if line == "" { + continue + } + + if strings.Contains(line, ".go") { + // File path lines get extra indent + b.WriteString(" ├ ") + } else { + // Function names + b.WriteString(" │ ") + } + b.WriteString(line) + b.WriteString("\n") + } + + // End stack trace section + b.WriteString(" └\n") +} diff --git a/vendor/github.com/olekukonko/ll/ll.go b/vendor/github.com/olekukonko/ll/ll.go new file mode 100644 index 00000000..3a660b95 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/ll.go @@ -0,0 +1,1412 @@ +package ll + +import ( + "bufio" + "encoding/binary" + "encoding/json" + "fmt" + "github.com/olekukonko/ll/lh" + "github.com/olekukonko/ll/lx" + "io" + "math" + "os" + "reflect" + "runtime" + "strings" + "sync" + "sync/atomic" + "time" +) + +// Logger manages logging configuration and behavior, encapsulating state such as enablement, +// log level, namespaces, context fields, output style, handler, middleware, and formatting. +// It is thread-safe, using a read-write mutex to protect concurrent access to its fields. +type Logger struct { + mu sync.RWMutex // Guards concurrent access to fields + enabled bool // Determines if logging is enabled + suspend bool // uses suspend path for most actions eg. skipping namespace checks + level lx.LevelType // Minimum log level (e.g., Debug, Info, Warn, Error) + namespaces *lx.Namespace // Manages namespace enable/disable states + currentPath string // Current namespace path (e.g., "parent/child") + context map[string]interface{} // Contextual fields included in all logs + style lx.StyleType // Namespace formatting style (FlatPath or NestedPath) + handler lx.Handler // Output handler for logs (e.g., text, JSON) + middleware []Middleware // Middleware functions to process log entries + prefix string // Prefix prepended to log messages + indent int // Number of double spaces for message indentation + stackBufferSize int // Buffer size for capturing stack traces + separator string // Separator for namespace paths (e.g., "/") + entries atomic.Int64 // Tracks total log entries sent to handler +} + +// New creates a new Logger with the given namespace and optional configurations. +// It initializes with defaults: disabled, Debug level, flat namespace style, text handler +// to os.Stdout, and an empty middleware chain. Options (e.g., WithHandler, WithLevel) can +// override defaults. The logger is thread-safe via mutex-protected methods. +// Example: +// +// logger := New("app", WithHandler(lh.NewTextHandler(os.Stdout))).Enable() +// logger.Info("Starting application") // Output: [app] INFO: Starting application +func New(namespace string, opts ...Option) *Logger { + logger := &Logger{ + enabled: lx.DefaultEnabled, // Defaults to disabled (false) + level: lx.LevelDebug, // Default minimum log level + namespaces: defaultStore, // Shared namespace store + currentPath: namespace, // Initial namespace path + context: make(map[string]interface{}), // Empty context for fields + style: lx.FlatPath, // Default namespace style ([parent/child]) + handler: lh.NewTextHandler(os.Stdout), // Default text output to stdout + middleware: make([]Middleware, 0), // Empty middleware chain + stackBufferSize: 4096, // Default stack trace buffer size + separator: lx.Slash, // Default namespace separator ("/") + } + + // Apply provided configuration options + for _, opt := range opts { + opt(logger) + } + + return logger +} + +// AddContext adds a key-value pair to the logger's context, modifying it directly. +// Unlike Context, it mutates the existing context. It is thread-safe using a write lock. +// Example: +// +// logger := New("app").Enable() +// logger.AddContext("user", "alice") +// logger.Info("Action") // Output: [app] INFO: Action [user=alice] +func (l *Logger) AddContext(key string, value interface{}) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + + // Initialize context map if nil + if l.context == nil { + l.context = make(map[string]interface{}) + } + l.context[key] = value + return l +} + +// Benchmark logs the duration since a start time at Info level, including "start", +// "end", and "duration" fields. It is thread-safe via Fields and log methods. +// Example: +// +// logger := New("app").Enable() +// start := time.Now() +// logger.Benchmark(start) // Output: [app] INFO: benchmark [start=... end=... duration=...] +func (l *Logger) Benchmark(start time.Time) time.Duration { + duration := time.Since(start) + l.Fields("start", start, "end", time.Now(), "duration", duration).Infof("benchmark") + return duration +} + +// CanLog checks if a log at the given level would be emitted, considering enablement, +// log level, namespaces, sampling, and rate limits. It is thread-safe via shouldLog. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelWarn) +// canLog := logger.CanLog(lx.LevelInfo) // false +func (l *Logger) CanLog(level lx.LevelType) bool { + return l.shouldLog(level) +} + +// Clear removes all middleware functions, resetting the middleware chain to empty. +// It is thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().Use(someMiddleware) +// logger.Clear() +// logger.Info("No middleware") // Output: [app] INFO: No middleware +func (l *Logger) Clear() *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.middleware = nil + return l +} + +// Clone creates a new logger with the same configuration and namespace as the parent, +// but with a fresh context map to allow independent field additions. It is thread-safe +// using a read lock. +// Example: +// +// logger := New("app").Enable().Context(map[string]interface{}{"k": "v"}) +// clone := logger.Clone() +// clone.Info("Cloned") // Output: [app] INFO: Cloned [k=v] +func (l *Logger) Clone() *Logger { + l.mu.RLock() + defer l.mu.RUnlock() + + return &Logger{ + enabled: l.enabled, // Copy enablement state + level: l.level, // Copy log level + namespaces: l.namespaces, // Share namespace store + currentPath: l.currentPath, // Copy namespace path + context: make(map[string]interface{}), // Fresh context map + style: l.style, // Copy namespace style + handler: l.handler, // Copy output handler + middleware: l.middleware, // Copy middleware chain + prefix: l.prefix, // Copy message prefix + indent: l.indent, // Copy indentation level + stackBufferSize: l.stackBufferSize, // Copy stack trace buffer size + separator: l.separator, // Default separator ("/") + suspend: l.suspend, + } +} + +// Context creates a new logger with additional contextual fields, preserving existing +// fields and adding new ones. It returns a new logger to avoid mutating the parent and +// is thread-safe using a write lock. +// Example: +// +// logger := New("app").Enable() +// logger = logger.Context(map[string]interface{}{"user": "alice"}) +// logger.Info("Action") // Output: [app] INFO: Action [user=alice] +func (l *Logger) Context(fields map[string]interface{}) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + + // Create a new logger with inherited configuration + newLogger := &Logger{ + enabled: l.enabled, + level: l.level, + namespaces: l.namespaces, + currentPath: l.currentPath, + context: make(map[string]interface{}), + style: l.style, + handler: l.handler, + middleware: l.middleware, + prefix: l.prefix, + indent: l.indent, + stackBufferSize: l.stackBufferSize, + separator: l.separator, + suspend: l.suspend, + } + + // Copy parent's context fields + for k, v := range l.context { + newLogger.context[k] = v + } + + // Add new fields + for k, v := range fields { + newLogger.context[k] = v + } + + return newLogger +} + +// Dbg logs debug information, including the source file, line number, and expression +// value, capturing the calling line of code. It is useful for debugging without temporary +// print statements. +// Example: +// +// x := 42 +// logger.Dbg(x) // Output: [file.go:123] x = 42 +func (l *Logger) Dbg(values ...interface{}) { + // Skip logging if Info level is not enabled + if !l.shouldLog(lx.LevelInfo) { + return + } + + l.dbg(2, values...) +} + +// Debug logs a message at Debug level, formatting it and delegating to the internal +// log method. It is thread-safe. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelDebug) +// logger.Debug("Debugging") // Output: [app] DEBUG: Debugging +func (l *Logger) Debug(args ...any) { + // check if suspended + if l.suspend { + return + } + + // Skip logging if Debug level is not enabled + if !l.shouldLog(lx.LevelDebug) { + return + } + + l.log(lx.LevelDebug, lx.ClassText, concatSpaced(args...), nil, false) +} + +// Debugf logs a formatted message at Debug level, delegating to Debug. It is thread-safe. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelDebug) +// logger.Debugf("Debug %s", "message") // Output: [app] DEBUG: Debug message +func (l *Logger) Debugf(format string, args ...any) { + // check if suspended + if l.suspend { + return + } + + l.Debug(fmt.Sprintf(format, args...)) +} + +// Disable deactivates logging, suppressing all logs regardless of level or namespace. +// It is thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().Disable() +// logger.Info("Ignored") // No output +func (l *Logger) Disable() *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.enabled = false + return l +} + +// Dump displays a hex and ASCII representation of a value's binary form, using gob +// encoding or direct conversion. It is useful for inspecting binary data structures. +// Example: +// +// type Data struct { X int; Y string } +// logger.Dump(Data{42, "test"}) // Outputs hex/ASCII dump +func (l *Logger) Dump(values ...interface{}) { + // Iterate over each value to dump + for _, value := range values { + // Log value description and type + l.Infof("Dumping %v (%T)", value, value) + var by []byte + var err error + + // Convert value to byte slice based on type + switch v := value.(type) { + case []byte: + by = v + case string: + by = []byte(v) + case float32: + // Convert float32 to 4-byte big-endian + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, math.Float32bits(v)) + by = buf + case float64: + // Convert float64 to 8-byte big-endian + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, math.Float64bits(v)) + by = buf + case int, int8, int16, int32, int64: + // Convert signed integer to 8-byte big-endian + by = make([]byte, 8) + binary.BigEndian.PutUint64(by, uint64(reflect.ValueOf(v).Int())) + case uint, uint8, uint16, uint32, uint64: + // Convert unsigned integer to 8-byte big-endian + by = make([]byte, 8) + binary.BigEndian.PutUint64(by, reflect.ValueOf(v).Uint()) + case io.Reader: + // Read all bytes from io.Reader + by, err = io.ReadAll(v) + default: + // Fallback to JSON marshaling for complex types + by, err = json.Marshal(v) + } + + // Log error if conversion fails + if err != nil { + l.Errorf("Dump error: %v", err) + continue + } + + // Generate hex/ASCII dump + n := len(by) + rowcount := 0 + stop := (n / 8) * 8 + k := 0 + s := strings.Builder{} + // Process 8-byte rows + for i := 0; i <= stop; i += 8 { + k++ + if i+8 < n { + rowcount = 8 + } else { + rowcount = min(k*8, n) % 8 + } + // Write position and hex prefix + s.WriteString(fmt.Sprintf("pos %02d hex: ", i)) + + // Write hex values + for j := 0; j < rowcount; j++ { + s.WriteString(fmt.Sprintf("%02x ", by[i+j])) + } + // Pad with spaces for alignment + for j := rowcount; j < 8; j++ { + s.WriteString(fmt.Sprintf(" ")) + } + // Write ASCII representation + s.WriteString(fmt.Sprintf(" '%s'\n", viewString(by[i:(i+rowcount)]))) + } + // Log the hex/ASCII dump + l.log(lx.LevelNone, lx.ClassDump, s.String(), nil, false) + } +} + +// Enable activates logging, allowing logs to be emitted if other conditions (e.g., level, +// namespace) are met. It is thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable() +// logger.Info("Started") // Output: [app] INFO: Started +func (l *Logger) Enable() *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.enabled = true + return l +} + +// Enabled checks if the logger is enabled for logging. It is thread-safe using a read lock. +// Example: +// +// logger := New("app").Enable() +// if logger.Enabled() { +// logger.Info("Logging is enabled") // Output: [app] INFO: Logging is enabled +// } +func (l *Logger) Enabled() bool { + l.mu.RLock() + defer l.mu.RUnlock() + return l.enabled +} + +// Err adds one or more errors to the logger’s context and logs them at Error level. +// Non-nil errors are stored in the "error" context field (single error or slice) and +// logged as a concatenated string (e.g., "failed 1; failed 2"). It is thread-safe and +// returns the logger for chaining. +// Example: +// +// logger := New("app").Enable() +// err1 := errors.New("failed 1") +// err2 := errors.New("failed 2") +// logger.Err(err1, err2).Info("Error occurred") +// // Output: [app] ERROR: failed 1; failed 2 +// // [app] INFO: Error occurred [error=[failed 1 failed 2]] +func (l *Logger) Err(errs ...error) { + // Skip logging if Error level is not enabled + if !l.shouldLog(lx.LevelError) { + return + } + + l.mu.Lock() + + // Initialize context map if nil + if l.context == nil { + l.context = make(map[string]interface{}) + } + + // Collect non-nil errors and build log message + var nonNilErrors []error + var builder strings.Builder + count := 0 + for i, err := range errs { + if err != nil { + if i > 0 && count > 0 { + builder.WriteString("; ") + } + builder.WriteString(err.Error()) + nonNilErrors = append(nonNilErrors, err) + count++ + } + } + + if count > 0 { + if count == 1 { + // Store single error directly + l.context["error"] = nonNilErrors[0] + } else { + // Store slice of errors + l.context["error"] = nonNilErrors + } + // Log concatenated error messages + l.log(lx.LevelError, lx.ClassText, builder.String(), nil, false) + } + l.mu.Unlock() +} + +// Error logs a message at Error level, formatting it and delegating to the internal +// log method. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Error("Error occurred") // Output: [app] ERROR: Error occurred +func (l *Logger) Error(args ...any) { + // check if suspended + if l.suspend { + return + } + + // Skip logging if Error level is not enabled + if !l.shouldLog(lx.LevelError) { + return + } + l.log(lx.LevelError, lx.ClassText, concatSpaced(args...), nil, false) +} + +// Errorf logs a formatted message at Error level, delegating to Error. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Errorf("Error %s", "occurred") // Output: [app] ERROR: Error occurred +func (l *Logger) Errorf(format string, args ...any) { + // check if suspended + if l.suspend { + return + } + + l.Error(fmt.Errorf(format, args...)) +} + +// Fatal logs a message at Error level with a stack trace and exits the program with +// exit code 1. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Fatal("Fatal error") // Output: [app] ERROR: Fatal error [stack=...], then exits +func (l *Logger) Fatal(args ...any) { + // check if suspended + if l.suspend { + return + } + + // Exit immediately if Error level is not enabled + if !l.shouldLog(lx.LevelError) { + os.Exit(1) + } + + l.log(lx.LevelError, lx.ClassText, concatSpaced(args...), nil, true) + os.Exit(1) +} + +// Fatalf logs a formatted message at Error level with a stack trace and exits the program. +// It delegates to Fatal and is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Fatalf("Fatal %s", "error") // Output: [app] ERROR: Fatal error [stack=...], then exits +func (l *Logger) Fatalf(format string, args ...any) { + // check if suspended + if l.suspend { + return + } + + l.Fatal(fmt.Sprintf(format, args...)) +} + +// Field starts a fluent chain for adding fields from a map, creating a FieldBuilder +// for type-safe field addition. It is thread-safe via the FieldBuilder’s logger. +// Example: +// +// logger := New("app").Enable() +// logger.Field(map[string]interface{}{"user": "alice"}).Info("Action") // Output: [app] INFO: Action [user=alice] +func (l *Logger) Field(fields map[string]interface{}) *FieldBuilder { + fb := &FieldBuilder{logger: l, fields: make(map[string]interface{})} + + // check if suspended + if l.suspend { + return fb + } + + // Copy fields from input map to FieldBuilder + for k, v := range fields { + fb.fields[k] = v + } + return fb +} + +// Fields starts a fluent chain for adding fields using variadic key-value pairs, +// creating a FieldBuilder. Non-string keys or uneven pairs add an error field. It is +// thread-safe via the FieldBuilder’s logger. +// Example: +// +// logger := New("app").Enable() +// logger.Fields("user", "alice").Info("Action") // Output: [app] INFO: Action [user=alice] +func (l *Logger) Fields(pairs ...any) *FieldBuilder { + fb := &FieldBuilder{logger: l, fields: make(map[string]interface{})} + + if l.suspend { + return fb + } + + // Process key-value pairs + for i := 0; i < len(pairs)-1; i += 2 { + if key, ok := pairs[i].(string); ok { + fb.fields[key] = pairs[i+1] + } else { + // Log error for non-string keys + fb.fields["error"] = fmt.Errorf("non-string key in Fields: %v", pairs[i]) + } + } + // Log error for uneven pairs + if len(pairs)%2 != 0 { + fb.fields["error"] = fmt.Errorf("uneven key-value pairs in Fields: [%v]", pairs[len(pairs)-1]) + } + return fb +} + +// GetContext returns the logger's context map of persistent key-value fields. It is +// thread-safe using a read lock. +// Example: +// +// logger := New("app").AddContext("user", "alice") +// ctx := logger.GetContext() // Returns map[string]interface{}{"user": "alice"} +func (l *Logger) GetContext() map[string]interface{} { + l.mu.RLock() + defer l.mu.RUnlock() + return l.context +} + +// GetHandler returns the logger's current handler for customization or inspection. +// The returned handler should not be modified concurrently with logger operations. +// Example: +// +// logger := New("app") +// handler := logger.GetHandler() // Returns the current handler (e.g., TextHandler) +func (l *Logger) GetHandler() lx.Handler { + return l.handler +} + +// GetLevel returns the minimum log level for the logger. It is thread-safe using a read lock. +// Example: +// +// logger := New("app").Level(lx.LevelWarn) +// if logger.GetLevel() == lx.LevelWarn { +// logger.Warn("Warning level set") // Output: [app] WARN: Warning level set +// } +func (l *Logger) GetLevel() lx.LevelType { + l.mu.RLock() + defer l.mu.RUnlock() + return l.level +} + +// GetPath returns the logger's current namespace path. It is thread-safe using a read lock. +// Example: +// +// logger := New("app").Namespace("sub") +// path := logger.GetPath() // Returns "app/sub" +func (l *Logger) GetPath() string { + l.mu.RLock() + defer l.mu.RUnlock() + return l.currentPath +} + +// GetSeparator returns the logger's namespace separator (e.g., "/"). It is thread-safe +// using a read lock. +// Example: +// +// logger := New("app").Separator(".") +// sep := logger.GetSeparator() // Returns "." +func (l *Logger) GetSeparator() string { + l.mu.RLock() + defer l.mu.RUnlock() + return l.separator +} + +// GetStyle returns the logger's namespace formatting style (FlatPath or NestedPath). +// It is thread-safe using a read lock. +// Example: +// +// logger := New("app").Style(lx.NestedPath) +// if logger.GetStyle() == lx.NestedPath { +// logger.Info("Nested style") // Output: [app]: INFO: Nested style +// } +func (l *Logger) GetStyle() lx.StyleType { + l.mu.RLock() + defer l.mu.RUnlock() + return l.style +} + +// Handler sets the handler for processing log entries, configuring the output destination +// and format (e.g., text, JSON). It is thread-safe using a write lock and returns the +// logger for chaining. +// Example: +// +// logger := New("app").Enable().Handler(lh.NewTextHandler(os.Stdout)) +// logger.Info("Log") // Output: [app] INFO: Log +func (l *Logger) Handler(handler lx.Handler) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.handler = handler + return l +} + +// Indent sets the indentation level for log messages, adding two spaces per level. It is +// thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().Indent(2) +// logger.Info("Indented") // Output: [app] INFO: Indented +func (l *Logger) Indent(depth int) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.indent = depth + return l +} + +// Info logs a message at Info level, formatting it and delegating to the internal log +// method. It is thread-safe. +// Example: +// +// logger := New("app").Enable().Style(lx.NestedPath) +// logger.Info("Started") // Output: [app]: INFO: Started +func (l *Logger) Info(args ...any) { + if l.suspend { + return + } + + if !l.shouldLog(lx.LevelInfo) { + return + } + + l.log(lx.LevelInfo, lx.ClassText, concatSpaced(args...), nil, false) +} + +// Infof logs a formatted message at Info level, delegating to Info. It is thread-safe. +// Example: +// +// logger := New("app").Enable().Style(lx.NestedPath) +// logger.Infof("Started %s", "now") // Output: [app]: INFO: Started now +func (l *Logger) Infof(format string, args ...any) { + if l.suspend { + return + } + + l.Info(fmt.Sprintf(format, args...)) +} + +// Len returns the total number of log entries sent to the handler, using atomic operations +// for thread safety. +// Example: +// +// logger := New("app").Enable() +// logger.Info("Test") +// count := logger.Len() // Returns 1 +func (l *Logger) Len() int64 { + return l.entries.Load() +} + +// Level sets the minimum log level, ignoring messages below it. It is thread-safe using +// a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().Level(lx.LevelWarn) +// logger.Info("Ignored") // No output +// logger.Warn("Logged") // Output: [app] WARN: Logged +func (l *Logger) Level(level lx.LevelType) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.level = level + return l +} + +// Line adds vertical spacing (newlines) to the log output, defaulting to 1 if no arguments +// are provided. Multiple values are summed for total lines. It is thread-safe and returns +// the logger for chaining. +// Example: +// +// logger := New("app").Enable() +// logger.Line(2).Info("After 2 newlines") // Adds 2 blank lines before logging +// logger.Line().Error("After 1 newline") // Defaults to 1 +func (l *Logger) Line(lines ...int) *Logger { + line := 1 // Default to 1 newline + if len(lines) > 0 { + line = 0 + // Sum all provided line counts + for _, n := range lines { + line += n + } + // Ensure at least 1 line + if line < 1 { + line = 1 + } + } + l.log(lx.LevelNone, lx.ClassRaw, strings.Repeat(lx.Newline, line), nil, false) + return l +} + +// Mark logs the current file and line number where it's called, without any additional debug information. +// It's useful for tracing execution flow without the verbosity of Dbg. +// Example: +// +// logger.Mark() // *MARK*: [file.go:123] +func (l *Logger) Mark(name ...string) { + l.mark(2, name...) +} + +func (l *Logger) mark(skip int, names ...string) { + // Skip logging if Info level is not enabled + if !l.shouldLog(lx.LevelInfo) { + return + } + + // Get caller information (file, line) + _, file, line, ok := runtime.Caller(skip) + if !ok { + l.log(lx.LevelError, lx.ClassText, "Mark: Unable to parse runtime caller", nil, false) + return + } + + // Extract just the filename (without full path) + shortFile := file + if idx := strings.LastIndex(file, "/"); idx >= 0 { + shortFile = file[idx+1:] + } + + name := strings.Join(names, l.separator) + if name == "" { + name = "MARK" + } + + // Format as [filename:line] + out := fmt.Sprintf("[*%s*]: [%s:%d]\n", name, shortFile, line) + l.log(lx.LevelInfo, lx.ClassRaw, out, nil, false) +} + +// Measure benchmarks function execution, logging the duration at Info level with a +// "duration" field. It is thread-safe via Fields and log methods. +// Example: +// +// logger := New("app").Enable() +// duration := logger.Measure(func() { time.Sleep(time.Millisecond) }) +// // Output: [app] INFO: function executed [duration=~1ms] +func (l *Logger) Measure(fns ...func()) time.Duration { + start := time.Now() + // Execute all provided functions + for _, fn := range fns { + fn() + } + duration := time.Since(start) + l.Fields("duration", duration).Infof("function executed") + return duration +} + +// Namespace creates a child logger with a sub-namespace appended to the current path, +// inheriting the parent’s configuration but with an independent context. It is thread-safe +// using a read lock. +// Example: +// +// parent := New("parent").Enable() +// child := parent.Namespace("child") +// child.Info("Child log") // Output: [parent/child] INFO: Child log +func (l *Logger) Namespace(name string) *Logger { + if l.suspend { + return l + } + + l.mu.RLock() + defer l.mu.RUnlock() + + // Construct full namespace path + fullPath := name + if l.currentPath != "" { + fullPath = l.currentPath + l.separator + name + } + + // Create child logger with inherited configuration + return &Logger{ + enabled: l.enabled, + level: l.level, + namespaces: l.namespaces, + currentPath: fullPath, + context: make(map[string]interface{}), + style: l.style, + handler: l.handler, + middleware: l.middleware, + prefix: l.prefix, + indent: l.indent, + stackBufferSize: l.stackBufferSize, + separator: l.separator, + suspend: l.suspend, + } +} + +// NamespaceDisable disables logging for a namespace and its children, invalidating the +// namespace cache. It is thread-safe via lx.Namespace’s sync.Map and returns the logger +// for chaining. +// Example: +// +// logger := New("parent").Enable().NamespaceDisable("parent/child") +// logger.Namespace("child").Info("Ignored") // No output +func (l *Logger) NamespaceDisable(relativePath string) *Logger { + l.mu.RLock() + fullPath := l.joinPath(l.currentPath, relativePath) + l.mu.RUnlock() + + // Disable namespace in shared store + l.namespaces.Set(fullPath, false) + return l +} + +// NamespaceEnable enables logging for a namespace and its children, invalidating the +// namespace cache. It is thread-safe via lx.Namespace’s sync.Map and returns the logger +// for chaining. +// Example: +// +// logger := New("parent").Enable().NamespaceEnable("parent/child") +// logger.Namespace("child").Info("Log") // Output: [parent/child] INFO: Log +func (l *Logger) NamespaceEnable(relativePath string) *Logger { + l.mu.RLock() + fullPath := l.joinPath(l.currentPath, relativePath) + l.mu.RUnlock() + + // Enable namespace in shared store + l.namespaces.Set(fullPath, true) + return l +} + +// NamespaceEnabled checks if a namespace is enabled, considering parent namespaces and +// caching results for performance. It is thread-safe using a read lock. +// Example: +// +// logger := New("parent").Enable().NamespaceDisable("parent/child") +// enabled := logger.NamespaceEnabled("parent/child") // false +func (l *Logger) NamespaceEnabled(relativePath string) bool { + l.mu.RLock() + fullPath := l.joinPath(l.currentPath, relativePath) + separator := l.separator + if separator == "" { + separator = lx.Slash + } + instanceEnabled := l.enabled + l.mu.RUnlock() + + // Handle root path case + if fullPath == "" && relativePath == "" { + return instanceEnabled + } + + if fullPath != "" { + // Check namespace rules + isEnabledByNSRule, isDisabledByNSRule := l.namespaces.Enabled(fullPath, separator) + if isDisabledByNSRule { + return false + } + if isEnabledByNSRule { + return true + } + } + // Fall back to logger's enabled state + return instanceEnabled +} + +// Panic logs a message at Error level with a stack trace and triggers a panic. It is +// thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Panic("Panic error") // Output: [app] ERROR: Panic error [stack=...], then panics +func (l *Logger) Panic(args ...any) { + // Build message by concatenating arguments with spaces + msg := concatSpaced(args...) + + if l.suspend { + panic(msg) + } + + // Panic immediately if Error level is not enabled + if !l.shouldLog(lx.LevelError) { + panic(msg) + } + + l.log(lx.LevelError, lx.ClassText, msg, nil, true) + panic(msg) +} + +// Panicf logs a formatted message at Error level with a stack trace and triggers a panic. +// It delegates to Panic and is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Panicf("Panic %s", "error") // Output: [app] ERROR: Panic error [stack=...], then panics +func (l *Logger) Panicf(format string, args ...any) { + l.Panic(fmt.Sprintf(format, args...)) +} + +// Prefix sets a prefix prepended to all log messages. It is thread-safe using a write +// lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().Prefix("APP: ") +// logger.Info("Started") // Output: [app] INFO: APP: Started +func (l *Logger) Prefix(prefix string) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.prefix = prefix + return l +} + +// Print logs a message at Info level without format specifiers, minimizing allocations +// by concatenating arguments with spaces. It is thread-safe via the log method. +// Example: +// +// logger := New("app").Enable() +// logger.Print("message", "value") // Output: [app] INFO: message value +func (l *Logger) Print(args ...any) { + if l.suspend { + return + } + + // Skip logging if Info level is not enabled + if !l.shouldLog(lx.LevelInfo) { + return + } + l.log(lx.LevelNone, lx.ClassRaw, concatSpaced(args...), nil, false) +} + +// Println logs a message at Info level without format specifiers, minimizing allocations +// by concatenating arguments with spaces. It is thread-safe via the log method. +// Example: +// +// logger := New("app").Enable() +// logger.Println("message", "value") // Output: [app] INFO: message value +func (l *Logger) Println(args ...any) { + if l.suspend { + return + } + + // Skip logging if Info level is not enabled + if !l.shouldLog(lx.LevelInfo) { + return + } + l.log(lx.LevelNone, lx.ClassRaw, concatenate(lx.Space, nil, []any{lx.Newline}, args...), nil, false) +} + +// Printf logs a formatted message at Info level, delegating to Print. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Printf("Message %s", "value") // Output: [app] INFO: Message value +func (l *Logger) Printf(format string, args ...any) { + if l.suspend { + return + } + + l.Print(fmt.Sprintf(format, args...)) +} + +// Remove removes middleware by the reference returned from Use, delegating to the +// Middleware’s Remove method for thread-safe removal. +// Example: +// +// logger := New("app").Enable() +// mw := logger.Use(someMiddleware) +// logger.Remove(mw) // Removes middleware +func (l *Logger) Remove(m *Middleware) { + m.Remove() +} + +// Resume reactivates logging for the current logger after it has been suspended. +// It clears the suspend flag, allowing logs to be emitted if other conditions (e.g., level, namespace) +// are met. Thread-safe with a write lock. Returns the logger for method chaining. +// Example: +// +// logger := New("app").Enable().Suspend() +// logger.Resume() +// logger.Info("Resumed") // Output: [app] INFO: Resumed +func (l *Logger) Resume() *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.suspend = false // Clear suspend flag to resume logging + return l +} + +// Separator sets the namespace separator for grouping namespaces and log entries (e.g., "/" or "."). +// It is thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Separator(".") +// logger.Namespace("sub").Info("Log") // Output: [app.sub] INFO: Log +func (l *Logger) Separator(separator string) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.separator = separator + return l +} + +// Suspend temporarily deactivates logging for the current logger. +// It sets the suspend flag, suppressing all logs regardless of level or namespace until resumed. +// Thread-safe with a write lock. Returns the logger for method chaining. +// Example: +// +// logger := New("app").Enable() +// logger.Suspend() +// logger.Info("Ignored") // No output +func (l *Logger) Suspend() *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.suspend = true // Set suspend flag to pause logging + return l +} + +// Suspended returns whether the logger is currently suspended. +// It provides thread-safe read access to the suspend flag using a write lock. +// Example: +// +// logger := New("app").Enable().Suspend() +// if logger.Suspended() { +// fmt.Println("Logging is suspended") // Prints message +// } +func (l *Logger) Suspended() bool { + l.mu.Lock() + defer l.mu.Unlock() + return l.suspend // Return current suspend state +} + +// Stack logs messages at Error level with a stack trace for each provided argument. +// It is thread-safe and skips logging if Debug level is not enabled. +// Example: +// +// logger := New("app").Enable() +// logger.Stack("Critical error") // Output: [app] ERROR: Critical error [stack=...] +func (l *Logger) Stack(args ...any) { + if l.suspend { + return + } + + // Skip logging if Debug level is not enabled + if !l.shouldLog(lx.LevelDebug) { + return + } + + for _, arg := range args { + l.log(lx.LevelError, lx.ClassText, concat(arg), nil, true) + } +} + +// Stackf logs a formatted message at Error level with a stack trace, delegating to Stack. +// It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Stackf("Critical %s", "error") // Output: [app] ERROR: Critical error [stack=...] +func (l *Logger) Stackf(format string, args ...any) { + if l.suspend { + return + } + + l.Stack(fmt.Sprintf(format, args...)) +} + +// StackSize sets the buffer size for stack trace capture in Stack, Fatal, and Panic methods. +// It is thread-safe using a write lock and returns the logger for chaining. +// Example: +// +// logger := New("app").Enable().StackSize(65536) +// logger.Stack("Error") // Captures up to 64KB stack trace +func (l *Logger) StackSize(size int) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + if size > 0 { + l.stackBufferSize = size + } + return l +} + +// Style sets the namespace formatting style (FlatPath or NestedPath). FlatPath uses +// [parent/child], while NestedPath uses [parent]→[child]. It is thread-safe using a write +// lock and returns the logger for chaining. +// Example: +// +// logger := New("parent/child").Enable().Style(lx.NestedPath) +// logger.Info("Log") // Output: [parent]→[child]: INFO: Log +func (l *Logger) Style(style lx.StyleType) *Logger { + l.mu.Lock() + defer l.mu.Unlock() + l.style = style + return l +} + +// Use adds a middleware function to process log entries before they are handled, returning +// a Middleware handle for removal. Middleware returning a non-nil error stops the log. +// It is thread-safe using a write lock. +// Example: +// +// logger := New("app").Enable() +// mw := logger.Use(ll.FuncMiddleware(func(e *lx.Entry) error { +// if e.Level < lx.LevelWarn { +// return fmt.Errorf("level too low") +// } +// return nil +// })) +// logger.Info("Ignored") // No output +// mw.Remove() +// logger.Info("Now logged") // Output: [app] INFO: Now logged +func (l *Logger) Use(fn lx.Handler) *Middleware { + l.mu.Lock() + defer l.mu.Unlock() + + // Assign a unique ID to the middleware + id := len(l.middleware) + 1 + // Append middleware to the chain + l.middleware = append(l.middleware, Middleware{id: id, fn: fn}) + + return &Middleware{ + logger: l, + id: id, + } +} + +// Warn logs a message at Warn level, formatting it and delegating to the internal log +// method. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Warn("Warning") // Output: [app] WARN: Warning +func (l *Logger) Warn(args ...any) { + if l.suspend { + return + } + + // Skip logging if Warn level is not enabled + if !l.shouldLog(lx.LevelWarn) { + return + } + + l.log(lx.LevelWarn, lx.ClassText, concatSpaced(args...), nil, false) +} + +// Warnf logs a formatted message at Warn level, delegating to Warn. It is thread-safe. +// Example: +// +// logger := New("app").Enable() +// logger.Warnf("Warning %s", "issued") // Output: [app] WARN: Warning issued +func (l *Logger) Warnf(format string, args ...any) { + if l.suspend { + return + } + + l.Warn(fmt.Sprintf(format, args...)) +} + +// dbg is an internal helper for Dbg, logging debug information with source file and line +// number, extracting the calling line of code. It is thread-safe via the log method. +// Example (internal usage): +// +// logger.Dbg(x) // Calls dbg(2, x) +func (l *Logger) dbg(skip int, values ...interface{}) { + for _, exp := range values { + // Get caller information (file, line) + _, file, line, ok := runtime.Caller(skip) + if !ok { + l.log(lx.LevelError, lx.ClassText, "Dbg: Unable to parse runtime caller", nil, false) + return + } + + // Open source file + f, err := os.Open(file) + if err != nil { + l.log(lx.LevelError, lx.ClassText, "Dbg: Unable to open expected file", nil, false) + return + } + + // Scan file to find the line + scanner := bufio.NewScanner(f) + scanner.Split(bufio.ScanLines) + var out string + i := 1 + for scanner.Scan() { + if i == line { + // Extract expression between parentheses + v := scanner.Text()[strings.Index(scanner.Text(), "(")+1 : len(scanner.Text())-strings.Index(reverseString(scanner.Text()), ")")-1] + // Format output with file, line, expression, and value + out = fmt.Sprintf("[%s:%d] %s = %+v", file[len(file)-strings.Index(reverseString(file), "/"):], line, v, exp) + break + } + i++ + } + if err := scanner.Err(); err != nil { + l.log(lx.LevelError, lx.ClassText, err.Error(), nil, false) + return + } + // Log based on value type + switch exp.(type) { + case error: + l.log(lx.LevelError, lx.ClassText, out, nil, false) + default: + l.log(lx.LevelInfo, lx.ClassText, out, nil, false) + } + + f.Close() + } +} + +// joinPath joins a base path and a relative path using the logger's separator, handling +// empty base or relative paths. It is used internally for namespace path construction. +// Example (internal usage): +// +// logger.joinPath("parent", "child") // Returns "parent/child" +func (l *Logger) joinPath(base, relative string) string { + if base == "" { + return relative + } + if relative == "" { + return base + } + separator := l.separator + if separator == "" { + separator = lx.Slash // Default separator + } + return base + separator + relative +} + +// log is the internal method for processing a log entry, applying rate limiting, sampling, +// middleware, and context before passing to the handler. Middleware returning a non-nil +// error stops the log. It is thread-safe with read/write locks for configuration and stack +// trace buffer. +// Example (internal usage): +// +// logger := New("app").Enable() +// logger.Info("Test") // Calls log(lx.LevelInfo, "Test", nil, false) +func (l *Logger) log(level lx.LevelType, class lx.ClassType, msg string, fields map[string]interface{}, withStack bool) { + // Skip logging if level is not enabled + if !l.shouldLog(level) { + return + } + + var stack []byte + + // Capture stack trace if requested + if withStack { + l.mu.RLock() + buf := make([]byte, l.stackBufferSize) + l.mu.RUnlock() + n := runtime.Stack(buf, false) + if fields == nil { + fields = make(map[string]interface{}) + } + stack = buf[:n] + } + + l.mu.RLock() + defer l.mu.RUnlock() + + // Apply prefix and indentation to the message + var builder strings.Builder + if l.indent > 0 { + builder.WriteString(strings.Repeat(lx.DoubleSpace, l.indent)) + } + if l.prefix != "" { + builder.WriteString(l.prefix) + } + builder.WriteString(msg) + finalMsg := builder.String() + + // Create log entry + entry := &lx.Entry{ + Timestamp: time.Now(), + Level: level, + Message: finalMsg, + Namespace: l.currentPath, + Fields: fields, + Style: l.style, + Class: class, + Stack: stack, + } + + // Merge context fields, avoiding overwrites + if len(l.context) > 0 { + if entry.Fields == nil { + entry.Fields = make(map[string]interface{}) + } + for k, v := range l.context { + if _, exists := entry.Fields[k]; !exists { + entry.Fields[k] = v + } + } + } + + // Apply middleware, stopping if any returns an error + for _, mw := range l.middleware { + if err := mw.fn.Handle(entry); err != nil { + return + } + } + + // Pass to handler if set + if l.handler != nil { + _ = l.handler.Handle(entry) + l.entries.Add(1) + } +} + +// shouldLog determines if a log should be emitted based on enabled state, level, namespaces, +// sampling, and rate limits, caching namespace results for performance. It is thread-safe +// with a read lock. +// Example (internal usage): +// +// logger := New("app").Enable().Level(lx.LevelWarn) +// if logger.shouldLog(lx.LevelInfo) { // false +// // Log would be skipped +// } +func (l *Logger) shouldLog(level lx.LevelType) bool { + // Skip if global logging system is inactive + if !Active() { + return false + } + + // check for suspend mode + if l.suspend { + return false + } + + // Skip if log level is below minimum + if level > l.level { + return false + } + + separator := l.separator + if separator == "" { + separator = lx.Slash + } + + // Check namespace rules if path is set + if l.currentPath != "" { + isEnabledByNSRule, isDisabledByNSRule := l.namespaces.Enabled(l.currentPath, separator) + if isDisabledByNSRule { + return false + } + if isEnabledByNSRule { + return true + } + } + + // Fall back to logger's enabled state + if !l.enabled { + return false + } + + return true +} + +// WithHandler sets the handler for the logger as a functional option for configuring +// a new logger instance. +// Example: +// +// logger := New("app", WithHandler(lh.NewJSONHandler(os.Stdout))) +func WithHandler(handler lx.Handler) Option { + return func(l *Logger) { + l.handler = handler + } +} + +// WithLevel sets the minimum log level for the logger as a functional option for +// configuring a new logger instance. +// Example: +// +// logger := New("app", WithLevel(lx.LevelWarn)) +func WithLevel(level lx.LevelType) Option { + return func(l *Logger) { + l.level = level + } +} + +// WithStyle sets the namespace formatting style for the logger as a functional option +// for configuring a new logger instance. +// Example: +// +// logger := New("app", WithStyle(lx.NestedPath)) +func WithStyle(style lx.StyleType) Option { + return func(l *Logger) { + l.style = style + } +} diff --git a/vendor/github.com/olekukonko/ll/lx/lx.go b/vendor/github.com/olekukonko/ll/lx/lx.go new file mode 100644 index 00000000..2e404d59 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lx/lx.go @@ -0,0 +1,154 @@ +package lx + +import ( + "time" +) + +// Formatting constants for log output. +// These constants define the characters used to format log messages, ensuring consistency +// across handlers (e.g., text, JSON, colorized). They are used to construct namespace paths, +// level indicators, and field separators in log entries. +const ( + Space = " " // Single space for separating elements (e.g., between level and message) + DoubleSpace = " " // Double space for indentation (e.g., for hierarchical output) + Slash = "/" // Separator for namespace paths (e.g., "parent/child") + Arrow = "→" // Arrow for NestedPath style namespaces (e.g., [parent]→[child]) + LeftBracket = "[" // Opening bracket for namespaces and fields (e.g., [app]) + RightBracket = "]" // Closing bracket for namespaces and fields (e.g., [app]) + Colon = ":" // Separator after namespace or level (e.g., [app]: INFO:) + Dot = "." // Separator for namespace paths (e.g., "parent.child") + Newline = "\n" // Newline for separating log entries or stack trace lines +) + +// DefaultEnabled defines the default logging state (disabled). +// It specifies whether logging is enabled by default for new Logger instances in the ll package. +// Set to false to prevent logging until explicitly enabled. +const ( + DefaultEnabled = false // Default state for new loggers (disabled) +) + +// Log level constants, ordered by increasing severity. +// These constants define the severity levels for log messages, used to filter logs based +// on the logger’s minimum level. They are ordered to allow comparison (e.g., LevelDebug < LevelWarn). +const ( + LevelNone LevelType = iota // Debug level for detailed diagnostic information + LevelInfo // Info level for general operational messages + LevelWarn // Warn level for warning conditions + LevelError // Error level for error conditions requiring attention + LevelDebug // None level for logs without a specific severity (e.g., raw output) +) + +// Log class constants, defining the type of log entry. +// These constants categorize log entries by their content or purpose, influencing how +// handlers process them (e.g., text, JSON, hex dump). +const ( + ClassText ClassType = iota // Text entries for standard log messages + ClassJSON // JSON entries for structured output + ClassDump // Dump entries for hex/ASCII dumps + ClassSpecial // Special entries for custom or non-standard logs + ClassRaw // Raw entries for unformatted output +) + +// Namespace style constants. +// These constants define how namespace paths are formatted in log output, affecting the +// visual representation of hierarchical namespaces. +const ( + FlatPath StyleType = iota // Formats namespaces as [parent/child] + NestedPath // Formats namespaces as [parent]→[child] +) + +// LevelType represents the severity of a log message. +// It is an integer type used to define log levels (Debug, Info, Warn, Error, None), with associated +// string representations for display in log output. +type LevelType int + +// String converts a LevelType to its string representation. +// It maps each level constant to a human-readable string, returning "UNKNOWN" for invalid levels. +// Used by handlers to display the log level in output. +// Example: +// +// var level lx.LevelType = lx.LevelInfo +// fmt.Println(level.String()) // Output: INFO +func (l LevelType) String() string { + switch l { + case LevelDebug: + return "DEBUG" + case LevelInfo: + return "INFO" + case LevelWarn: + return "WARN" + case LevelError: + return "ERROR" + case LevelNone: + return "NONE" + default: + return "UNKNOWN" + } +} + +// StyleType defines how namespace paths are formatted in log output. +// It is an integer type used to select between FlatPath ([parent/child]) and NestedPath +// ([parent]→[child]) styles, affecting how handlers render namespace hierarchies. +type StyleType int + +// Entry represents a single log entry passed to handlers. +// It encapsulates all information about a log message, including its timestamp, severity, +// content, namespace, metadata, and formatting style. Handlers process Entry instances +// to produce formatted output (e.g., text, JSON). The struct is immutable once created, +// ensuring thread-safety in handler processing. +type Entry struct { + Timestamp time.Time // Time the log was created + Level LevelType // Severity level of the log (Debug, Info, Warn, Error, None) + Message string // Log message content + Namespace string // Namespace path (e.g., "parent/child") + Fields map[string]interface{} // Additional key-value metadata (e.g., {"user": "alice"}) + Style StyleType // Namespace formatting style (FlatPath or NestedPath) + Error error // Associated error, if any (e.g., for error logs) + Class ClassType // Type of log entry (Text, JSON, Dump, Special, Raw) + Stack []byte // Stack trace data (if present) + Id int `json:"-"` // Unique ID for the entry, ignored in JSON output +} + +// Handler defines the interface for processing log entries. +// Implementations (e.g., TextHandler, JSONHandler) format and output log entries to various +// destinations (e.g., stdout, files). The Handle method returns an error if processing fails, +// allowing the logger to handle output failures gracefully. +// Example (simplified handler implementation): +// +// type MyHandler struct{} +// func (h *MyHandler) Handle(e *Entry) error { +// fmt.Printf("[%s] %s: %s\n", e.Namespace, e.Level.String(), e.Message) +// return nil +// } +type Handler interface { + Handle(e *Entry) error // Processes a log entry, returning any error +} + +// ClassType represents the type of a log entry. +// It is an integer type used to categorize log entries (Text, JSON, Dump, Special, Raw), +// influencing how handlers process and format them. +type ClassType int + +// String converts a ClassType to its string representation. +// It maps each class constant to a human-readable string, returning "UNKNOWN" for invalid classes. +// Used by handlers to indicate the entry type in output (e.g., JSON fields). +// Example: +// +// var class lx.ClassType = lx.ClassText +// fmt.Println(class.String()) // Output: TEST +func (t ClassType) String() string { + switch t { + case ClassText: + return "TEST" // Note: Likely a typo, should be "TEXT" + case ClassJSON: + return "JSON" + case ClassDump: + return "DUMP" + case ClassSpecial: + return "SPECIAL" + case ClassRaw: + return "RAW" + default: + return "UNKNOWN" + } +} diff --git a/vendor/github.com/olekukonko/ll/lx/ns.go b/vendor/github.com/olekukonko/ll/lx/ns.go new file mode 100644 index 00000000..5d30c939 --- /dev/null +++ b/vendor/github.com/olekukonko/ll/lx/ns.go @@ -0,0 +1,102 @@ +package lx + +import ( + "strings" + "sync" +) + +// namespaceRule stores the cached result of Enabled. +type namespaceRule struct { + isEnabledByRule bool + isDisabledByRule bool +} + +// Namespace manages thread-safe namespace enable/disable states with caching. +// The store holds explicit user-defined rules (path -> bool). +// The cache holds computed effective states for paths (path -> namespaceRule) +// based on hierarchical rules to optimize lookups. +type Namespace struct { + store sync.Map // path (string) -> rule (bool: true=enable, false=disable) + cache sync.Map // path (string) -> namespaceRule +} + +// Set defines an explicit enable/disable rule for a namespace path. +// It clears the cache to ensure subsequent lookups reflect the change. +func (ns *Namespace) Set(path string, enabled bool) { + ns.store.Store(path, enabled) + ns.clearCache() +} + +// Load retrieves an explicit rule from the store for a path. +// Returns the rule (true=enable, false=disable) and whether it exists. +// Does not consider hierarchy or caching. +func (ns *Namespace) Load(path string) (rule interface{}, found bool) { + return ns.store.Load(path) +} + +// Store directly sets a rule in the store, bypassing cache invalidation. +// Intended for internal use or sync.Map parity; prefer Set for standard use. +func (ns *Namespace) Store(path string, rule bool) { + ns.store.Store(path, rule) +} + +// clearCache clears the cache of Enabled results. +// Called by Set to ensure consistency after rule changes. +func (ns *Namespace) clearCache() { + ns.cache.Range(func(key, _ interface{}) bool { + ns.cache.Delete(key) + return true + }) +} + +// Enabled checks if a path is enabled by namespace rules, considering the most +// specific rule (path or closest prefix) in the store. Results are cached. +// Args: +// - path: Absolute namespace path to check. +// - separator: Character delimiting path segments (e.g., "/", "."). +// +// Returns: +// - isEnabledByRule: True if an explicit rule enables the path. +// - isDisabledByRule: True if an explicit rule disables the path. +// +// If both are false, no explicit rule applies to the path or its prefixes. +func (ns *Namespace) Enabled(path string, separator string) (isEnabledByRule bool, isDisabledByRule bool) { + if path == "" { // Root path has no explicit rule + return false, false + } + + // Check cache + if cachedValue, found := ns.cache.Load(path); found { + if state, ok := cachedValue.(namespaceRule); ok { + return state.isEnabledByRule, state.isDisabledByRule + } + ns.cache.Delete(path) // Remove invalid cache entry + } + + // Compute: Most specific rule wins + parts := strings.Split(path, separator) + computedIsEnabled := false + computedIsDisabled := false + + for i := len(parts); i >= 1; i-- { + currentPrefix := strings.Join(parts[:i], separator) + if val, ok := ns.store.Load(currentPrefix); ok { + if rule := val.(bool); rule { + computedIsEnabled = true + computedIsDisabled = false + } else { + computedIsEnabled = false + computedIsDisabled = true + } + break + } + } + + // Cache result, including (false, false) for no rule + ns.cache.Store(path, namespaceRule{ + isEnabledByRule: computedIsEnabled, + isDisabledByRule: computedIsDisabled, + }) + + return computedIsEnabled, computedIsDisabled +} diff --git a/vendor/github.com/olekukonko/ll/middleware.go b/vendor/github.com/olekukonko/ll/middleware.go new file mode 100644 index 00000000..694f75fa --- /dev/null +++ b/vendor/github.com/olekukonko/ll/middleware.go @@ -0,0 +1,124 @@ +package ll + +import ( + "github.com/olekukonko/ll/lx" +) + +// Middleware represents a registered middleware and its operations in the logging pipeline. +// It holds an ID for identification, a reference to the parent logger, and the handler function +// that processes log entries. Middleware is used to transform or filter log entries before they +// are passed to the logger's output handler. +type Middleware struct { + id int // Unique identifier for the middleware + logger *Logger // Parent logger instance for context and logging operations + fn lx.Handler // Handler function that processes log entries +} + +// Remove unregisters the middleware from the logger’s middleware chain. +// It safely removes the middleware by its ID, ensuring thread-safety with a mutex lock. +// If the middleware or logger is nil, it returns early to prevent panics. +// Example usage: +// +// // Using a named middleware function +// mw := logger.Use(authMiddleware) +// defer mw.Remove() +// +// // Using an inline middleware +// mw = logger.Use(ll.Middle(func(e *lx.Entry) error { +// if e.Level < lx.LevelWarn { +// return fmt.Errorf("level too low") +// } +// return nil +// })) +// defer mw.Remove() +func (m *Middleware) Remove() { + // Check for nil middleware or logger to avoid panics + if m == nil || m.logger == nil { + return + } + // Acquire write lock to modify middleware slice + m.logger.mu.Lock() + defer m.logger.mu.Unlock() + // Iterate through middleware slice to find and remove matching ID + for i, entry := range m.logger.middleware { + if entry.id == m.id { + // Remove middleware by slicing out the matching entry + m.logger.middleware = append(m.logger.middleware[:i], m.logger.middleware[i+1:]...) + return + } + } +} + +// Logger returns the parent logger for optional chaining. +// This allows middleware to access the logger for additional operations, such as logging errors +// or creating derived loggers. It is useful for fluent API patterns. +// Example: +// +// mw := logger.Use(authMiddleware) +// mw.Logger().Info("Middleware registered") +func (m *Middleware) Logger() *Logger { + return m.logger +} + +// Error logs an error message at the Error level if the middleware blocks a log entry. +// It uses the parent logger to emit the error and returns the middleware for chaining. +// This is useful for debugging or auditing when middleware rejects a log. +// Example: +// +// mw := logger.Use(ll.Middle(func(e *lx.Entry) error { +// if e.Level < lx.LevelWarn { +// return fmt.Errorf("level too low") +// } +// return nil +// })) +// mw.Error("Rejected low-level log") +func (m *Middleware) Error(args ...any) *Middleware { + m.logger.Error(args...) + return m +} + +// Errorf logs an error message at the Error level if the middleware blocks a log entry. +// It uses the parent logger to emit the error and returns the middleware for chaining. +// This is useful for debugging or auditing when middleware rejects a log. +// Example: +// +// mw := logger.Use(ll.Middle(func(e *lx.Entry) error { +// if e.Level < lx.LevelWarn { +// return fmt.Errorf("level too low") +// } +// return nil +// })) +// mw.Errorf("Rejected low-level log") +func (m *Middleware) Errorf(format string, args ...any) *Middleware { + m.logger.Errorf(format, args...) + return m +} + +// middlewareFunc is a function adapter that implements the lx.Handler interface. +// It allows plain functions with the signature `func(*lx.Entry) error` to be used as middleware. +// The function should return nil to allow the log to proceed or a non-nil error to reject it, +// stopping the log from being emitted by the logger. +type middlewareFunc func(*lx.Entry) error + +// Handle implements the lx.Handler interface for middlewareFunc. +// It calls the underlying function with the log entry and returns its result. +// This enables seamless integration of function-based middleware into the logging pipeline. +func (mf middlewareFunc) Handle(e *lx.Entry) error { + return mf(e) +} + +// Middle creates a middleware handler from a function. +// It wraps a function with the signature `func(*lx.Entry) error` into a middlewareFunc, +// allowing it to be used in the logger’s middleware pipeline. A non-nil error returned by +// the function will stop the log from being emitted, ensuring precise control over logging. +// Example: +// +// logger.Use(ll.Middle(func(e *lx.Entry) error { +// if e.Level == lx.LevelDebug { +// return fmt.Errorf("debug logs disabled") +// } +// return nil +// })) +func Middle(fn func(*lx.Entry) error) lx.Handler { + return middlewareFunc(fn) +} diff --git a/vendor/github.com/olekukonko/tablewriter/.gitignore b/vendor/github.com/olekukonko/tablewriter/.gitignore index b66cec63..f79a2875 100644 --- a/vendor/github.com/olekukonko/tablewriter/.gitignore +++ b/vendor/github.com/olekukonko/tablewriter/.gitignore @@ -1,15 +1,10 @@ -# Created by .ignore support plugin (hsz.mobi) -### Go template -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out +# folders +.idea +.vscode +/tmp +/lab +dev.sh +*csv2table +_test/ diff --git a/vendor/github.com/olekukonko/tablewriter/.travis.yml b/vendor/github.com/olekukonko/tablewriter/.travis.yml deleted file mode 100644 index 366d48a3..00000000 --- a/vendor/github.com/olekukonko/tablewriter/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: go -arch: - - ppc64le - - amd64 -go: - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 - - "1.10" - - tip -jobs: - exclude : - - arch : ppc64le - go : - - 1.3 - - arch : ppc64le - go : - - 1.4 diff --git a/vendor/github.com/olekukonko/tablewriter/MIGRATION.md b/vendor/github.com/olekukonko/tablewriter/MIGRATION.md new file mode 100644 index 00000000..650a195b --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/MIGRATION.md @@ -0,0 +1,3280 @@ +# Migration Guide: tablewriter v0.0.5 to v1.0.x +> **NOTE:** This document is work in progress, use with `caution`. This document is a comprehensive guide. For specific issues or advanced scenarios, please refer to the source code or open an issue. + +The `tablewriter` library has undergone a significant redesign between versions **v0.0.5** and **v1.0.x**, transitioning from a primarily method-driven API to a more robust, modular, and configuration-driven framework. This guide provides a detailed roadmap for migrating your v0.0.5 codebase to v1.0.x. It includes mappings of old methods to new approaches, practical examples, and explanations of new features. + +We believe these changes significantly improve the library's flexibility, maintainability, and power, enabling new features and making complex table configurations more manageable. + +## Why Migrate to v1.0.x? + +The v1.0.x redesign enhances `tablewriter`’s flexibility, maintainability, and feature set: +- **Extensibility**: Decoupled rendering supports diverse output formats (e.g., HTML, Markdown, CSV). +- **Robust Configuration**: Centralized `Config` struct and fluent builders ensure atomic, predictable setups. +- **Streaming Capability**: Dedicated API for row-by-row rendering, ideal for large or real-time datasets. +- **Type Safety**: Specific types (e.g., `tw.State`, `tw.Align`) reduce errors and improve clarity. +- **Consistent API**: Unified interface for intuitive usage across simple and complex use cases. +- **New Features**: Hierarchical merging, granular padding, table captions, and fixed column widths. + +These improvements make v1.0.x more powerful, but they require updating code to leverage the new configuration-driven framework and take advantage of advanced functionalities. + +## Key New Features in v1.0.x + +- **Fluent Configuration Builders**: `NewConfigBuilder()` enables chained, readable setups (`config.go:NewConfigBuilder`). +- **Centralized Configuration**: `Config` struct governs table behavior and data processing (`config.go:Config`). +- **Decoupled Renderer**: `tw.Renderer` interface with `tw.Rendition` for visual styling, allowing custom renderers (`tw/renderer.go`). +- **True Streaming Support**: `Start()`, `Append()`, `Close()` for incremental rendering (`stream.go`). +- **Hierarchical Cell Merging**: `tw.MergeHierarchical` for complex data structures (`tw/tw.go:MergeMode` constant, logic in `zoo.go`). +- **Granular Padding Control**: Per-side (`Top`, `Bottom`, `Left`, `Right`) and per-column padding (`tw/cell.go:CellPadding`, `tw/types.go:Padding`). +- **Enhanced Type System**: `tw.State`, `tw.Align`, `tw.Spot`, and others for clarity and safety (`tw/state.go`, `tw/types.go`). +- **Comprehensive Error Handling**: Methods like `Render()` and `Append()` return errors (`tablewriter.go`, `stream.go`). +- **Fixed Column Width System**: `Config.Widths` for precise column sizing, especially in streaming (`config.go:Config`, `tw/cell.go:CellWidth`). +- **Table Captioning**: Flexible placement and styling with `tw.Caption` (`tw/types.go:Caption`). +- **Advanced Data Processing**: Support for `tw.Formatter`, per-column filters, and stringer caching (`tw/cell.go:CellFilter`, `tablewriter.go:WithStringer`). + +## Core Philosophy Changes in v1.0.x + +Understanding these shifts is essential for a successful migration: + +1. **Configuration-Driven Approach**: + - **Old**: Relied on `table.SetXxx()` methods for incremental, stateful modifications to table properties. + - **New**: Table behavior is defined by a `tablewriter.Config` struct (`config.go:Config`), while visual styling is managed by a `tw.Rendition` struct (`tw/renderer.go:Rendition`). These are typically set at table creation using `NewTable()` with `Option` functions or via a fluent `ConfigBuilder`, ensuring atomic and predictable configuration changes. + +2. **Decoupled Rendering Engine**: + - **Old**: Rendering logic was tightly integrated into the `Table` struct, limiting output flexibility. + - **New**: The `tw.Renderer` interface (`tw/renderer.go:Renderer`) defines rendering logic, with `renderer.NewBlueprint()` as the default text-based renderer. The renderer’s appearance (e.g., borders, symbols) is controlled by `tw.Rendition`, enabling support for alternative formats like HTML or Markdown. + +3. **Unified Section Configuration**: + - **Old**: Headers, rows, and footers had separate, inconsistent configuration methods. + - **New**: `tw.CellConfig` (`tw/cell.go:CellConfig`) standardizes configuration across headers, rows, and footers, encompassing formatting (`tw.CellFormatting`), padding (`tw.CellPadding`), column widths (`tw.CellWidth`), alignments (`tw.CellAlignment`), and filters (`tw.CellFilter`). + +4. **Fluent Configuration Builders**: + - **Old**: Configuration was done via individual setters, often requiring multiple method calls. + - **New**: `tablewriter.NewConfigBuilder()` (`config.go:NewConfigBuilder`) provides a chained, fluent API for constructing `Config` objects, with nested builders for `Header()`, `Row()`, `Footer()`, `Alignment()`, `Behavior()`, and `ForColumn()` to simplify complex setups. + +5. **Explicit Streaming Mode**: + - **Old**: No dedicated streaming support; tables were rendered in batch mode. + - **New**: Streaming for row-by-row rendering is enabled via `Config.Stream.Enable` or `WithStreaming(tw.StreamConfig{Enable: true})` and managed with `Table.Start()`, `Table.Append()` (or `Table.Header()`, `Table.Footer()`), and `Table.Close()` (`stream.go`). This is ideal for large datasets or continuous output. + +6. **Enhanced Error Handling**: + - **Old**: Methods like `Render()` did not return errors, making error detection difficult. + - **New**: Key methods (`Render()`, `Start()`, `Close()`, `Append()`, `Bulk()`) return errors to promote robust error handling and improve application reliability (`tablewriter.go`, `stream.go`). + +7. **Richer Type System & `tw` Package**: + - **Old**: Used integer constants (e.g., `ALIGN_CENTER`) and booleans, leading to potential errors. + - **New**: The `tw` sub-package introduces type-safe constructs like `tw.State` (`tw/state.go`), `tw.Align` (`tw/types.go`), `tw.Position` (`tw/types.go`), and `tw.CellConfig` (`tw/cell.go`), replacing magic constants and enhancing code clarity. + +## Configuration Methods in v1.0.x + +v1.0.x offers four flexible methods to configure tables, catering to different use cases and complexity levels. Each method can be used independently or combined, providing versatility for both simple and advanced setups. + +1. **Using `WithConfig` Option**: + - **Description**: Pass a fully populated `tablewriter.Config` struct during `NewTable` initialization using the `WithConfig` option. + - **Use Case**: Ideal for predefined, reusable configurations that can be serialized or shared across multiple tables. + - **Pros**: Explicit, portable, and suitable for complex setups; allows complete control over all configuration aspects. + - **Cons**: Verbose for simple changes, requiring manual struct population. + - **Example**: + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + cfg := tablewriter.Config{ + Header: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignCenter}, + Formatting: tw.CellFormatting{AutoFormat: tw.On}, + }, + Row: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, + }, + MaxWidth: 80, + Behavior: tw.Behavior{TrimSpace: tw.On}, + } + table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` +**Output**: + ``` +┌───────┬────────┐ +│ NAME │ STATUS │ +├───────┼────────┤ +│ Node1 │ Ready │ +└───────┴────────┘ + ``` + +2. **Using `Table.Configure` method**: + - **Description**: After creating a `Table` instance, use the `Configure` method with a function that modifies the table's `Config` struct. + - **Use Case**: Suitable for quick, ad-hoc tweaks post-initialization, especially for simple or dynamic adjustments. + - **Pros**: Straightforward for minor changes; no need for additional structs or builders if you already have a `Table` instance. + - **Cons**: Less readable for complex configurations compared to a builder; modifications are applied to an existing instance. + - **Example**: +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Configure(func(cfg *tablewriter.Config) { + cfg.Header.Alignment.Global = tw.AlignCenter + cfg.Row.Alignment.Global = tw.AlignLeft + }) + + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` +**Output**: Same as above. + +3. **Standalone `Option` Functions**: + - **Description**: Use `WithXxx` functions (e.g., `WithHeaderAlignment`, `WithDebug`) during `NewTable` initialization or via `table.Options()` to apply targeted settings. + - **Use Case**: Best for simple, specific configuration changes without needing a full `Config` struct. + - **Pros**: Concise, readable, and intuitive for common settings; ideal for minimal setups. + - **Cons**: Limited for complex, multi-faceted configurations; requires multiple options for extensive changes. + - **Example**: +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithHeaderAlignment(tw.AlignCenter), + tablewriter.WithRowAlignment(tw.AlignLeft), + tablewriter.WithDebug(true), + ) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` + **Output**: Same as above. + +4. **Fluent `ConfigBuilder`**: + - **Description**: Use `tablewriter.NewConfigBuilder()` to construct a `Config` struct through a chained, fluent API, then apply it with `WithConfig(builder.Build())`. + - **Use Case**: Optimal for complex, dynamic, or programmatically generated configurations requiring fine-grained control. + - **Pros**: Highly readable, maintainable, and expressive; supports nested builders for sections and columns. + - **Cons**: Slightly verbose; requires understanding builder methods and `Build()` call. + - **Example**: +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + cnfBuilder := tablewriter.NewConfigBuilder() + cnfBuilder.Header().Alignment().WithGlobal(tw.AlignCenter) + // Example of configuring a specific column (less emphasis on this for now) + // cnfBuilder.ForColumn(0).WithAlignment(tw.AlignLeft).Build() // Call Build() to return to ConfigBuilder + + table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cnfBuilder.Build())) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` +**Output**: Same as above. + +**Best Practices**: +- Use `WithConfig` or `ConfigBuilder` for complex setups or reusable configurations. +- Opt for `Option` functions for simple, targeted changes. +- Use `Table.Configure` for direct modifications after table creation, but avoid changes during rendering. +- Combine methods as needed (e.g., `ConfigBuilder` for initial setup, `Option` functions for overrides). + +## Default Parameters in v1.0.x + +The `defaultConfig()` function (`config.go:defaultConfig`) establishes baseline settings for new tables, ensuring predictable behavior unless overridden. Below is a detailed table of default parameters, organized by configuration section, to help you understand the starting point for table behavior and appearance. + +| Section | Parameter | Default Value | Description | +|---------------|-------------------------------|-----------------------------------|-----------------------------------------------------------------------------| +| **Header** | `Alignment.Global` | `tw.AlignCenter` | Centers header text globally unless overridden by `PerColumn`. | +| Header | `Alignment.PerColumn` | `[]tw.Align{}` | Empty; falls back to `Global` unless specified. | +| Header | `Formatting.AutoFormat` | `tw.On` | Applies title case (e.g., "col_one" → "COL ONE") to header content. | +| Header | `Formatting.AutoWrap` | `tw.WrapTruncate` | Truncates long header text with "…" based on width constraints. | +| Header | `Formatting.MergeMode` | `tw.MergeNone` | Disables cell merging in headers by default. | +| Header | `Padding.Global` | `tw.PaddingDefault` (`" "`) | Adds one space on left and right of header cells. | +| Header | `Padding.PerColumn` | `[]tw.Padding{}` | Empty; falls back to `Global` unless specified. | +| Header | `ColMaxWidths.Global` | `0` (unlimited) | No maximum content width for header cells unless set. | +| Header | `ColMaxWidths.PerColumn` | `tw.NewMapper[int, int]()` | Empty map; no per-column content width limits unless specified. | +| Header | `Filter.Global` | `nil` | No global content transformation for header cells. | +| Header | `Filter.PerColumn` | `[]func(string) string{}` | No per-column content transformations unless specified. | +| **Row** | `Alignment.Global` | `tw.AlignLeft` | Left-aligns row text globally unless overridden by `PerColumn`. | +| Row | `Alignment.PerColumn` | `[]tw.Align{}` | Empty; falls back to `Global`. | +| Row | `Formatting.AutoFormat` | `tw.Off` | Disables auto-formatting (e.g., title case) for row content. | +| Row | `Formatting.AutoWrap` | `tw.WrapNormal` | Wraps long row text naturally at word boundaries based on width constraints.| +| Row | `Formatting.MergeMode` | `tw.MergeNone` | Disables cell merging in rows by default. | +| Row | `Padding.Global` | `tw.PaddingDefault` (`" "`) | Adds one space on left and right of row cells. | +| Row | `Padding.PerColumn` | `[]tw.Padding{}` | Empty; falls back to `Global`. | +| Row | `ColMaxWidths.Global` | `0` (unlimited) | No maximum content width for row cells. | +| Row | `ColMaxWidths.PerColumn` | `tw.NewMapper[int, int]()` | Empty map; no per-column content width limits. | +| Row | `Filter.Global` | `nil` | No global content transformation for row cells. | +| Row | `Filter.PerColumn` | `[]func(string) string{}` | No per-column content transformations. | +| **Footer** | `Alignment.Global` | `tw.AlignRight` | Right-aligns footer text globally unless overridden by `PerColumn`. | +| Footer | `Alignment.PerColumn` | `[]tw.Align{}` | Empty; falls back to `Global`. | +| Footer | `Formatting.AutoFormat` | `tw.Off` | Disables auto-formatting for footer content. | +| Footer | `Formatting.AutoWrap` | `tw.WrapNormal` | Wraps long footer text naturally. | +| Footer | `Formatting.MergeMode` | `tw.MergeNone` | Disables cell merging in footers. | +| Footer | `Padding.Global` | `tw.PaddingDefault` (`" "`) | Adds one space on left and right of footer cells. | +| Footer | `Padding.PerColumn` | `[]tw.Padding{}` | Empty; falls back to `Global`. | +| Footer | `ColMaxWidths.Global` | `0` (unlimited) | No maximum content width for footer cells. | +| Footer | `ColMaxWidths.PerColumn` | `tw.NewMapper[int, int]()` | Empty map; no per-column content width limits. | +| Footer | `Filter.Global` | `nil` | No global content transformation for footer cells. | +| Footer | `Filter.PerColumn` | `[]func(string) string{}` | No per-column content transformations. | +| **Global** | `MaxWidth` | `0` (unlimited) | No overall table width limit. | +| Global | `Behavior.AutoHide` | `tw.Off` | Displays empty columns (ignored in streaming). | +| Global | `Behavior.TrimSpace` | `tw.On` | Trims leading/trailing spaces from cell content. | +| Global | `Behavior.Header` | `tw.Control{Hide: tw.Off}` | Shows header if content is provided. | +| Global | `Behavior.Footer` | `tw.Control{Hide: tw.Off}` | Shows footer if content is provided. | +| Global | `Behavior.Compact` | `tw.Compact{Merge: tw.Off}` | No compact width optimization for merged cells. | +| Global | `Debug` | `false` | Disables debug logging. | +| Global | `Stream.Enable` | `false` | Disables streaming mode by default. | +| Global | `Widths.Global` | `0` (unlimited) | No fixed column width unless specified. | +| Global | `Widths.PerColumn` | `tw.NewMapper[int, int]()` | Empty map; no per-column fixed widths unless specified. | + +**Notes**: +- Defaults can be overridden using any configuration method. +- `tw.PaddingDefault` is `{Left: " ", Right: " "}` (`tw/preset.go`). +- Alignment within `tw.CellFormatting` is deprecated; `tw.CellAlignment` is preferred. `tw.AlignDefault` falls back to `Global` or `tw.AlignLeft` (`tw/types.go`). +- Streaming mode uses `Widths` for fixed column sizing (`stream.go`). + +## Renderer Types and Customization + +v1.0.x introduces a flexible rendering system via the `tw.Renderer` interface (`tw/renderer.go:Renderer`), allowing for both default text-based rendering and custom output formats. This decouples rendering logic from table data processing, enabling support for diverse formats like HTML, CSV, or JSON. + +### Default Renderer: `renderer.NewBlueprint` +- **Description**: `renderer.NewBlueprint()` creates a text-based renderer. Its visual styles are configured using `tw.Rendition`. +- **Use Case**: Standard terminal or text output with configurable borders, symbols, and separators. +- **Configuration**: Styled via `tw.Rendition`, which controls: + - `Borders`: Outer table borders (`tw.Border`) with `tw.State` for each side (`tw/renderer.go`). + - `Settings`: Internal lines (`tw.Lines`) and separators (`tw.Separators`) (`tw/renderer.go`). + - `Symbols`: Characters for drawing table lines and junctions (`tw.Symbols`) (`tw/symbols.go`). + - **Example**: +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" // Import the renderer package + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), // Default Blueprint renderer + tablewriter.WithRendition(tw.Rendition{ // Apply custom rendition + Symbols: tw.NewSymbols(tw.StyleRounded), + Borders: tw.Border{Top: tw.On, Bottom: tw.On, Left: tw.On, Right: tw.On}, + Settings: tw.Settings{ + Separators: tw.Separators{BetweenRows: tw.On}, + Lines: tw.Lines{ShowHeaderLine: tw.On}, + }, + }), + ) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` +**Output**: + ``` + ╭───────┬────────╮ + │ Name │ Status │ + ├───────┼────────┤ + │ Node1 │ Ready │ + ╰───────┴────────╯ + ``` + +### Custom Renderer Implementation +- **Description**: Implement the `tw.Renderer` interface to create custom output formats (e.g., HTML, CSV). +- **Use Case**: Non-text outputs, specialized formatting, or integration with other systems. +- **Interface Methods**: + - `Start(w io.Writer) error`: Initializes rendering. + - `Header(headers [][]string, ctx tw.Formatting)`: Renders header rows. + - `Row(row []string, ctx tw.Formatting)`: Renders a data row. + - `Footer(footers [][]string, ctx tw.Formatting)`: Renders footer rows. + - `Line(ctx tw.Formatting)`: Renders separator lines. + - `Close() error`: Finalizes rendering. + - `Config() tw.Rendition`: Returns renderer's current rendition configuration. + - `Logger(logger *ll.Logger)`: Sets logger for debugging. + - **Example (HTML Renderer)**: + +```go +package main + +import ( + "fmt" + "github.com/olekukonko/ll" // For logger type + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "io" + "os" +) + +// BasicHTMLRenderer implements tw.Renderer +type BasicHTMLRenderer struct { + writer io.Writer + config tw.Rendition // Store the rendition + logger *ll.Logger + err error +} + +func (r *BasicHTMLRenderer) Start(w io.Writer) error { + r.writer = w + _, r.err = r.writer.Write([]byte("\n")) + return r.err +} + +// Header expects [][]string for potentially multi-line headers +func (r *BasicHTMLRenderer) Header(headers [][]string, ctx tw.Formatting) { + if r.err != nil { return } + _, r.err = r.writer.Write([]byte(" \n")) + if r.err != nil { return } + // Iterate over cells from the context for the current line + for _, cellCtx := range ctx.Row.Current { + content := fmt.Sprintf(" \n", cellCtx.Data) + _, r.err = r.writer.Write([]byte(content)) + if r.err != nil { return } + } + _, r.err = r.writer.Write([]byte(" \n")) +} + +// Row expects []string for a single line row, but uses ctx for actual data +func (r *BasicHTMLRenderer) Row(row []string, ctx tw.Formatting) { // row param is less relevant here, ctx.Row.Current is key + if r.err != nil { return } + _, r.err = r.writer.Write([]byte(" \n")) + if r.err != nil { return } + for _, cellCtx := range ctx.Row.Current { + content := fmt.Sprintf(" \n", cellCtx.Data) + _, r.err = r.writer.Write([]byte(content)) + if r.err != nil { return } + } + _, r.err = r.writer.Write([]byte(" \n")) +} + +func (r *BasicHTMLRenderer) Footer(footers [][]string, ctx tw.Formatting) { + if r.err != nil { return } + // Similar to Header/Row, using ctx.Row.Current for the footer line data + // The footers [][]string param might be used if the renderer needs multi-line footer logic + r.Row(nil, ctx) // Reusing Row logic, passing nil for the direct row []string as ctx contains the data +} + +func (r *BasicHTMLRenderer) Line(ctx tw.Formatting) { /* No lines in basic HTML */ } + +func (r *BasicHTMLRenderer) Close() error { + if r.err != nil { + return r.err + } + _, r.err = r.writer.Write([]byte("
%s
%s
\n")) + return r.err +} + +func (r *BasicHTMLRenderer) Config() tw.Rendition { return r.config } +func (r *BasicHTMLRenderer) Logger(logger *ll.Logger) { r.logger = logger } + +func main() { + table := tablewriter.NewTable(os.Stdout, tablewriter.WithRenderer(&BasicHTMLRenderer{ + config: tw.Rendition{Symbols: tw.NewSymbols(tw.StyleASCII)}, // Provide a default Rendition + })) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` +**Output**: +```html + + + + + + + + + +
NAMESTATUS
Node1Ready
+``` + + +#### Custom Invoice Renderer + +```go + +package main + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" +) + +// InvoiceRenderer implements tw.Renderer for a basic invoice style. +type InvoiceRenderer struct { + writer io.Writer + logger *ll.Logger + rendition tw.Rendition +} + +func NewInvoiceRenderer() *InvoiceRenderer { + rendition := tw.Rendition{ + Borders: tw.BorderNone, + Symbols: tw.NewSymbols(tw.StyleNone), + Settings: tw.Settings{Separators: tw.SeparatorsNone, Lines: tw.LinesNone}, + Streaming: false, + } + defaultLogger := ll.New("simple-invoice-renderer") + return &InvoiceRenderer{logger: defaultLogger, rendition: rendition} +} + +func (r *InvoiceRenderer) Logger(logger *ll.Logger) { + if logger != nil { + r.logger = logger + } +} + +func (r *InvoiceRenderer) Config() tw.Rendition { + return r.rendition +} + +func (r *InvoiceRenderer) Start(w io.Writer) error { + r.writer = w + r.logger.Debug("InvoiceRenderer: Start") + return nil +} + +func (r *InvoiceRenderer) formatLine(cells []string, widths tw.Mapper[int, int], cellContexts map[int]tw.CellContext) string { + var sb strings.Builder + numCols := 0 + if widths != nil { // Ensure widths is not nil before calling Len + numCols = widths.Len() + } + + for i := 0; i < numCols; i++ { + data := "" + if i < len(cells) { + data = cells[i] + } + + width := 0 + if widths != nil { // Check again before Get + width = widths.Get(i) + } + + align := tw.AlignDefault + if cellContexts != nil { // Check cellContexts + if ctx, ok := cellContexts[i]; ok { + align = ctx.Align + } + } + + paddedCell := tw.Pad(data, " ", width, align) + sb.WriteString(paddedCell) + + if i < numCols-1 { + sb.WriteString(" ") // Column separator + } + } + return sb.String() +} + +func (r *InvoiceRenderer) Header(headers [][]string, ctx tw.Formatting) { + if r.writer == nil { + return + } + r.logger.Debugf("InvoiceRenderer: Header (lines: %d)", len(headers)) + + for _, headerLineCells := range headers { + lineStr := r.formatLine(headerLineCells, ctx.Row.Widths, ctx.Row.Current) + fmt.Fprintln(r.writer, lineStr) + } + + if len(headers) > 0 { + totalWidth := 0 + if ctx.Row.Widths != nil { + ctx.Row.Widths.Each(func(_ int, w int) { totalWidth += w }) + if ctx.Row.Widths.Len() > 1 { + totalWidth += (ctx.Row.Widths.Len() - 1) * 3 // Separator spaces + } + } + if totalWidth > 0 { + fmt.Fprintln(r.writer, strings.Repeat("-", totalWidth)) + } + } +} + +func (r *InvoiceRenderer) Row(row []string, ctx tw.Formatting) { + if r.writer == nil { + return + } + r.logger.Debug("InvoiceRenderer: Row") + lineStr := r.formatLine(row, ctx.Row.Widths, ctx.Row.Current) + fmt.Fprintln(r.writer, lineStr) +} + +func (r *InvoiceRenderer) Footer(footers [][]string, ctx tw.Formatting) { + if r.writer == nil { + return + } + r.logger.Debugf("InvoiceRenderer: Footer (lines: %d)", len(footers)) + + if len(footers) > 0 { + totalWidth := 0 + if ctx.Row.Widths != nil { + ctx.Row.Widths.Each(func(_ int, w int) { totalWidth += w }) + if ctx.Row.Widths.Len() > 1 { + totalWidth += (ctx.Row.Widths.Len() - 1) * 3 + } + } + if totalWidth > 0 { + fmt.Fprintln(r.writer, strings.Repeat("-", totalWidth)) + } + } + + for _, footerLineCells := range footers { + lineStr := r.formatLine(footerLineCells, ctx.Row.Widths, ctx.Row.Current) + fmt.Fprintln(r.writer, lineStr) + } +} + +func (r *InvoiceRenderer) Line(ctx tw.Formatting) { + r.logger.Debug("InvoiceRenderer: Line (no-op)") + // This simple renderer draws its own lines in Header/Footer. +} + +func (r *InvoiceRenderer) Close() error { + r.logger.Debug("InvoiceRenderer: Close") + r.writer = nil + return nil +} + +func main() { + data := [][]string{ + {"Product A", "2", "10.00", "20.00"}, + {"Super Long Product Name B", "1", "125.50", "125.50"}, + {"Item C", "10", "1.99", "19.90"}, + } + + header := []string{"Description", "Qty", "Unit Price", "Total Price"} + footer := []string{"", "", "Subtotal:\nTax (10%):\nGRAND TOTAL:", "165.40\n16.54\n181.94"} + invoiceRenderer := NewInvoiceRenderer() + + // Create table and set custom renderer using Options + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(invoiceRenderer), + tablewriter.WithAlignment([]tw.Align{ + tw.AlignLeft, tw.AlignCenter, tw.AlignRight, tw.AlignRight, + }), + ) + + table.Header(header) + for _, v := range data { + table.Append(v) + } + + // Use the Footer method with strings containing newlines for multi-line cells + table.Footer(footer) + + fmt.Println("Rendering with InvoiceRenderer:") + table.Render() + + // For comparison, render with default Blueprint renderer + // Re-create the table or reset it to use a different renderer + table2 := tablewriter.NewTable(os.Stdout, + tablewriter.WithAlignment([]tw.Align{ + tw.AlignLeft, tw.AlignCenter, tw.AlignRight, tw.AlignRight, + }), + ) + + table2.Header(header) + for _, v := range data { + table2.Append(v) + } + table2.Footer(footer) + fmt.Println("\nRendering with Default Blueprint Renderer (for comparison):") + table2.Render() +} + +``` + + +``` +Rendering with InvoiceRenderer: +DESCRIPTION QTY UNIT PRICE TOTAL PRICE +-------------------------------------------------------------------- +Product A 2 10.00 20.00 +Super Long Product Name B 1 125.50 125.50 +Item C 10 1.99 19.90 +-------------------------------------------------------------------- + Subtotal: 165.40 +-------------------------------------------------------------------- + Tax (10%): 16.54 +-------------------------------------------------------------------- + GRAND TOTAL: 181.94 +``` + + +``` +Rendering with Default Blueprint Renderer (for comparison): +┌───────────────────────────┬─────┬──────────────┬─────────────┐ +│ DESCRIPTION │ QTY │ UNIT PRICE │ TOTAL PRICE │ +├───────────────────────────┼─────┼──────────────┼─────────────┤ +│ Product A │ 2 │ 10.00 │ 20.00 │ +│ Super Long Product Name B │ 1 │ 125.50 │ 125.50 │ +│ Item C │ 10 │ 1.99 │ 19.90 │ +├───────────────────────────┼─────┼──────────────┼─────────────┤ +│ │ │ Subtotal: │ 165.40 │ +│ │ │ Tax (10%): │ 16.54 │ +│ │ │ GRAND TOTAL: │ 181.94 │ +└───────────────────────────┴─────┴──────────────┴─────────────┘ + +``` +**Notes**: +- The `renderer.NewBlueprint()` is sufficient for most text-based use cases. +- Custom renderers require implementing all interface methods to handle table structure correctly. `tw.Formatting` (which includes `tw.RowContext`) provides cell content and metadata. + +## Function Mapping Table (v0.0.5 → v1.0.x) + +The following table maps v0.0.5 methods to their v1.0.x equivalents, ensuring a quick reference for migration. All deprecated methods are retained for compatibility but should be replaced with new APIs. + +| v0.0.5 Method | v1.0.x Equivalent(s) | Notes | +|-----------------------------------|--------------------------------------------------------------------------------------|----------------------------------------------------------------------| +| `NewWriter(w)` | `NewTable(w, opts...)` | `NewWriter` deprecated; wraps `NewTable` (`tablewriter.go`). | +| `SetHeader([]string)` | `Header(...any)` | Variadic or slice; supports any type (`tablewriter.go`). | +| `Append([]string)` | `Append(...any)` | Variadic, slice, or struct (`tablewriter.go`). | +| `AppendBulk([][]string)` | `Bulk([]any)` | Slice of rows; supports any type (`tablewriter.go`). | +| `SetFooter([]string)` | `Footer(...any)` | Variadic or slice; supports any type (`tablewriter.go`). | +| `Render()` | `Render()` (returns `error`) | Batch mode; streaming uses `Start/Close` (`tablewriter.go`). | +| `SetBorder(bool)` | `WithRendition(tw.Rendition{Borders: ...})` or `WithBorders(tw.Border)` (deprecated) | Use `tw.Border` (`deprecated.go`, `tw/renderer.go`). | +| `SetRowLine(bool)` | `WithRendition(tw.Rendition{Settings: {Separators: {BetweenRows: tw.On}}})` | `tw.Separators` (`tw/renderer.go`). | +| `SetHeaderLine(bool)` | `WithRendition(tw.Rendition{Settings: {Lines: {ShowHeaderLine: tw.On}}})` | `tw.Lines` (`tw/renderer.go`). | +| `SetColumnSeparator(string)` | `WithRendition(tw.Rendition{Symbols: ...})` or `WithSymbols(tw.Symbols)` (deprecated)| `tw.NewSymbols` or custom `tw.Symbols` (`tw/symbols.go`). | +| `SetCenterSeparator(string)` | `WithRendition(tw.Rendition{Symbols: ...})` or `WithSymbols(tw.Symbols)` (deprecated)| `tw.Symbols` (`tw/symbols.go`). | +| `SetRowSeparator(string)` | `WithRendition(tw.Rendition{Symbols: ...})` or `WithSymbols(tw.Symbols)` (deprecated)| `tw.Symbols` (`tw/symbols.go`). | +| `SetAlignment(int)` | `WithRowAlignment(tw.Align)` or `Config.Row.Alignment.Global` | `tw.Align` type (`config.go`). | +| `SetHeaderAlignment(int)` | `WithHeaderAlignment(tw.Align)` or `Config.Header.Alignment.Global` | `tw.Align` type (`config.go`). | +| `SetAutoFormatHeaders(bool)` | `WithHeaderAutoFormat(tw.State)` or `Config.Header.Formatting.AutoFormat` | `tw.State` (`config.go`). | +| `SetAutoWrapText(bool)` | `WithRowAutoWrap(int)` or `Config.Row.Formatting.AutoWrap` (uses `tw.Wrap...` const) | `tw.WrapNormal`, `tw.WrapTruncate`, etc. (`config.go`). | +| `SetAutoMergeCells(bool)` | `WithRowMergeMode(int)` or `Config.Row.Formatting.MergeMode` (uses `tw.Merge...` const) | Supports `Vertical`, `Hierarchical` (`config.go`). | +| `SetColMinWidth(col, w)` | `WithColumnWidths(tw.NewMapper[int,int]().Set(col, w))` or `Config.Widths.PerColumn` | `Config.Widths` for fixed widths (`config.go`). | +| `SetTablePadding(string)` | Use `Config.
.Padding.Global` with `tw.Padding` | No direct equivalent; manage via cell padding (`tw/cell.go`). | +| `SetDebug(bool)` | `WithDebug(bool)` or `Config.Debug` | Logs via `table.Debug()` (`config.go`). | +| `Clear()` | `Reset()` | Clears data and state (`tablewriter.go`). | +| `SetNoWhiteSpace(bool)` | `WithTrimSpace(tw.Off)` (if `true`) or `WithPadding(tw.PaddingNone)` | Manage via `Config.Behavior.TrimSpace` or padding (`config.go`). | +| `SetColumnColor(Colors)` | Embed ANSI codes in cell data, use `tw.Formatter`, or `Config.
.Filter` | Colors via data or filters (`tw/cell.go`). | +| `SetHeaderColor(Colors)` | Embed ANSI codes in cell data, use `tw.Formatter`, or `Config.Header.Filter` | Colors via data or filters (`tw/cell.go`). | +| `SetFooterColor(Colors)` | Embed ANSI codes in cell data, use `tw.Formatter`, or `Config.Footer.Filter` | Colors via data or filters (`tw/cell.go`). | + +**Notes**: +- Deprecated methods are in `deprecated.go` but should be replaced. +- `tw` package types (e.g., `tw.Align`, `tw.State`) are required for new APIs. +- Examples for each mapping are provided in the migration steps below. + +## Detailed Migration Steps: Initialization, Data Input, Rendering + +This section provides step-by-step guidance for migrating core table operations, with code examples and explanations to ensure clarity. Each step maps v0.0.5 methods to v1.0.x equivalents, highlighting changes, best practices, and potential pitfalls. + +### 1. Table Initialization +Initialization has shifted from `NewWriter` to `NewTable`, which supports flexible configuration via `Option` functions, `Config` structs, or `ConfigBuilder`. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // ... use table + _ = table // Avoid "declared but not used" +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" // Added for FormattableEntry example + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" // Import renderer + "github.com/olekukonko/tablewriter/tw" + "os" + "strings" // Added for Formatter example +) + +func main() { + // Minimal Setup (Default Configuration) + tableMinimal := tablewriter.NewTable(os.Stdout) + _ = tableMinimal // Avoid "declared but not used" + + // Using Option Functions for Targeted Configuration + tableWithOptions := tablewriter.NewTable(os.Stdout, + tablewriter.WithHeaderAlignment(tw.AlignCenter), // Center header text + tablewriter.WithRowAlignment(tw.AlignLeft), // Left-align row text + tablewriter.WithDebug(true), // Enable debug logging + ) + _ = tableWithOptions // Avoid "declared but not used" + + // Using a Full Config Struct for Comprehensive Control + cfg := tablewriter.Config{ + Header: tw.CellConfig{ + Alignment: tw.CellAlignment{ + Global: tw.AlignCenter, + PerColumn: []tw.Align{tw.AlignLeft, tw.AlignRight}, // Column-specific alignment + }, + Formatting: tw.CellFormatting{AutoFormat: tw.On}, + }, + Row: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, + Formatting: tw.CellFormatting{AutoWrap: tw.WrapNormal}, + }, + Footer: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignRight}, + }, + MaxWidth: 80, // Constrain total table width + Behavior: tw.Behavior{ + AutoHide: tw.Off, // Show empty columns + TrimSpace: tw.On, // Trim cell spaces + }, + Widths: tw.CellWidth{ + Global: 20, // Default fixed column width + PerColumn: tw.NewMapper[int, int]().Set(0, 15), // Column 0 fixed at 15 + }, + } + tableWithConfig := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + _ = tableWithConfig // Avoid "declared but not used" + + // Using ConfigBuilder for Fluent, Complex Configuration + builder := tablewriter.NewConfigBuilder(). + WithMaxWidth(80). + WithAutoHide(tw.Off). + WithTrimSpace(tw.On). + WithDebug(true). // Enable debug logging + Header(). + Alignment(). + WithGlobal(tw.AlignCenter). + Build(). // Returns *ConfigBuilder + Header(). + Formatting(). + WithAutoFormat(tw.On). + WithAutoWrap(tw.WrapTruncate). // Test truncation + WithMergeMode(tw.MergeNone). // Explicit merge mode + Build(). // Returns *HeaderConfigBuilder + Padding(). + WithGlobal(tw.Padding{Left: "[", Right: "]", Overwrite: true}). + Build(). // Returns *HeaderConfigBuilder + Build(). // Returns *ConfigBuilder + Row(). + Formatting(). + WithAutoFormat(tw.On). // Uppercase rows + Build(). // Returns *RowConfigBuilder + Build(). // Returns *ConfigBuilder + Row(). + Alignment(). + WithGlobal(tw.AlignLeft). + Build(). // Returns *ConfigBuilder + Build() // Finalize Config + + tableWithFluent := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(builder)) + _ = tableWithFluent // Avoid "declared but not used" +} +``` + +**Key Changes**: +- **Deprecation**: `NewWriter` is deprecated but retained for compatibility, internally calling `NewTable` (`tablewriter.go:NewWriter`). Transition to `NewTable` for new code. +- **Flexibility**: `NewTable` accepts an `io.Writer` and variadic `Option` functions (`tablewriter.go:NewTable`), enabling configuration via: + - `WithConfig(Config)`: Applies a complete `Config` struct (`config.go:WithConfig`). + - `WithRenderer(tw.Renderer)`: Sets a custom renderer, defaulting to `renderer.NewBlueprint()` (`tablewriter.go:WithRenderer`). + - `WithRendition(tw.Rendition)`: Configures visual styles for the renderer (`tablewriter.go:WithRendition`). + - `WithStreaming(tw.StreamConfig)`: Enables streaming mode (`tablewriter.go:WithStreaming`). + - Other `WithXxx` functions for specific settings (e.g., `WithHeaderAlignment`, `WithDebug`). +- **ConfigBuilder**: Provides a fluent API for complex setups; `Build()` finalizes the `Config` (`config.go:ConfigBuilder`). +- **Method Chaining in Builder**: Remember to call `Build()` on nested builders to return to the parent builder (e.g., `builder.Header().Alignment().WithGlobal(...).Build().Formatting()...`). + +**Migration Tips**: +- Replace `NewWriter` with `NewTable` and specify configurations explicitly. +- Use `ConfigBuilder` for complex setups or when readability is paramount. +- Apply `Option` functions for quick, targeted changes. +- Ensure `tw` package is imported for types like `tw.Align` and `tw.CellConfig`. +- Verify renderer settings if custom styling is needed, as `renderer.NewBlueprint()` is the default. + +**Potential Pitfalls**: +- **Unintended Defaults**: Without explicit configuration, `defaultConfig()` applies (see Default Parameters), which may differ from v0.0.5 behavior (e.g., `Header.Formatting.AutoFormat = tw.On`). +- **Renderer Absence**: If no renderer is set, `NewTable` defaults to `renderer.NewBlueprint()`; explicitly set for custom formats. +- **ConfigBuilder Errors**: Always call `Build()` at the end of a builder chain and on nested builders; omitting it can lead to incomplete configurations or runtime errors. +- **Concurrent Modification**: Avoid modifying `Table.config` (if using the `Configure` method or direct access) in concurrent scenarios or during rendering to prevent race conditions. + +### 2. Data Input +Data input methods in v1.0.x are more flexible, accepting `any` type for headers, rows, and footers, with robust conversion logic to handle strings, structs, and custom types. + +#### 2.1. Setting Headers +Headers define the table’s column labels and are typically the first data added. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + // ... +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.Formatter + "os" + "strings" +) + +// Struct with Formatter +type HeaderData struct { // Renamed to avoid conflict + Label string +} + +func (h HeaderData) Format() string { return strings.ToUpper(h.Label) } // Implements tw.Formatter + +func main() { + table := tablewriter.NewTable(os.Stdout) + + // Variadic Arguments (Preferred for Simplicity) + table.Header("Name", "Sign", "Rating") + + // Slice of Strings + // table.Header([]string{"Name", "Sign", "Rating"}) // Example, comment out if using variadic + + // Slice of Any Type (Flexible) + // table.Header([]any{"Name", "Sign", 123}) // Numbers converted to strings + + // Using Formatter + // table.Header(HeaderData{"name"}, HeaderData{"sign"}, HeaderData{"rating"}) // Outputs "NAME", "SIGN", "RATING" + + table.Append("Example", "Row", "Data") // Add some data to render + table.Render() +} +``` + +**Key Changes**: +- **Method**: `SetHeader([]string)` replaced by `Header(...any)` (`tablewriter.go:Header`). +- **Flexibility**: Accepts variadic arguments or a single slice; supports any type, not just strings. +- **Conversion**: Elements are processed by `processVariadic` (`zoo.go:processVariadic`) and converted to strings via `convertCellsToStrings` (`zoo.go:convertCellsToStrings`), supporting: + - Basic types (e.g., `string`, `int`, `float64`). + - `fmt.Stringer` implementations. + - `tw.Formatter` implementations (custom string conversion). + - Structs (exported fields as cells or single cell if `Stringer`/`Formatter`). +- **Streaming**: In streaming mode, `Header()` renders immediately via `streamRenderHeader` (`stream.go:streamRenderHeader`). +- **Formatting**: Headers are formatted per `Config.Header` settings (e.g., `AutoFormat`, `Alignment`) during rendering (`zoo.go:prepareContent`). + +**Migration Tips**: +- Replace `SetHeader` with `Header`, using variadic arguments for simplicity. +- Use slices for dynamic header lists or when passing from a variable. +- Implement `tw.Formatter` for custom header formatting (e.g., uppercase). +- Ensure header count matches expected columns to avoid width mismatches. +- In streaming mode, call `Header()` before rows, as it fixes column widths (`stream.go`). + +**Potential Pitfalls**: +- **Type Mismatch**: Non-string types are converted to strings; ensure desired formatting (e.g., use `tw.Formatter` for custom types). +- **Streaming Widths**: Headers influence column widths in streaming; set `Config.Widths` explicitly if specific widths are needed (`stream.go:streamCalculateWidths`). +- **Empty Headers**: Missing headers may cause rendering issues; provide placeholders (e.g., `""`) if needed. +- **AutoFormat**: Default `Header.Formatting.AutoFormat = tw.On` applies title case; disable with `WithHeaderAutoFormat(tw.Off)` if unwanted (`config.go`). + +#### 2.2. Appending Rows +Rows represent the table’s data entries, and v1.0.x enhances flexibility with support for varied input types. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"ColA", "ColB", "ColC"}) // Add header for context + table.Append([]string{"A", "The Good", "500"}) + table.Append([]string{"B", "The Very Bad", "288"}) + data := [][]string{ + {"C", "The Ugly", "120"}, + {"D", "The Gopher", "800"}, + } + table.AppendBulk(data) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.Formatter + "log" + "os" +) + +// Struct for examples +type Entry struct { + ID string + Label string + Score int +} + +// Struct with Formatter +type FormattableEntry struct { + ID string + Label string + Score int +} + +func (e FormattableEntry) Format() string { return fmt.Sprintf("%s (%d)", e.Label, e.Score) } // Implements tw.Formatter + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Header("ID", "Description", "Value") // Header for context + + // Variadic Arguments (Single Row) + table.Append("A", "The Good", 500) // Numbers converted to strings + + // Slice of Any Type (Single Row) + table.Append([]any{"B", "The Very Bad", "288"}) + + // Struct with Fields + table.Append(Entry{ID: "C", Label: "The Ugly", Score: 120}) // Fields as cells + + // Struct with Formatter (will produce a single cell for this row based on Format()) + // To make it fit 3 columns, the formatter would need to produce a string that looks like 3 cells, or the table config would need to adapt. + // For this example, let's assume it's meant to be one wide cell, or adjust the header. + // For now, let's simplify and append it to a table with one header. + tableOneCol := tablewriter.NewTable(os.Stdout) + tableOneCol.Header("Formatted Entry") + tableOneCol.Append(FormattableEntry{ID: "D", Label: "The Gopher", Score: 800}) // Single cell "The Gopher (800)" + tableOneCol.Render() + fmt.Println("---") + + + // Re-initialize main table for Bulk example + table = tablewriter.NewTable(os.Stdout) + table.Header("ID", "Description", "Value") + + // Multiple Rows with Bulk + data := []any{ + []any{"E", "The Fast", 300}, + Entry{ID: "F", Label: "The Swift", Score: 400}, // Struct instance + // FormattableEntry{ID: "G", Label: "The Bold", Score: 500}, // Would also be one cell + } + if err := table.Bulk(data); err != nil { + log.Fatalf("Bulk append failed: %v", err) + } + table.Render() +} +``` + +**Key Changes**: +- **Method**: `Append([]string)` replaced by `Append(...any)`; `AppendBulk([][]string)` replaced by `Bulk([]any)` (`tablewriter.go`). +- **Input Flexibility**: `Append` accepts: + - Multiple arguments as cells of a single row. + - A single slice (e.g., `[]string`, `[]any`) as cells of a single row. + - A single struct, processed by `convertItemToCells` (`zoo.go`): + - Uses `tw.Formatter` or `fmt.Stringer` for single-cell output. + - Extracts exported fields as multiple cells otherwise. +- **Bulk Input**: `Bulk` accepts a slice where each element is a row (e.g., `[][]any`, `[]Entry`), processed by `appendSingle` (`zoo.go:appendSingle`). +- **Streaming**: Rows render immediately in streaming mode via `streamAppendRow` (`stream.go:streamAppendRow`). +- **Error Handling**: `Append` and `Bulk` return errors for invalid conversions or streaming issues (`tablewriter.go`). + +**Migration Tips**: +- Replace `Append([]string)` with `Append(...any)` for variadic input. +- Use `Bulk` for multiple rows, ensuring each element is a valid row representation. +- Implement `tw.Formatter` for custom struct formatting to control cell output. +- Match row cell count to headers to avoid alignment issues. +- In streaming mode, append rows after `Start()` and before `Close()` (`stream.go`). + +**Potential Pitfalls**: +- **Cell Count Mismatch**: Uneven row lengths may cause rendering errors; pad with empty strings (e.g., `""`) if needed. +- **Struct Conversion**: Unexported fields are ignored; ensure fields are public or use `Formatter`/`Stringer` (`zoo.go`). +- **Streaming Order**: Rows must be appended after headers in streaming to maintain width consistency (`stream.go`). +- **Error Ignored**: Always check `Bulk` errors, as invalid data can cause failures. + +#### 2.3. Setting Footers +Footers provide summary or closing data for the table, often aligned differently from rows. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"ColA", "ColB", "ColC", "ColD"}) // Add header for context + table.SetFooter([]string{"", "", "Total", "1408"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.Formatter + "os" +) + +// Using Formatter +type FooterSummary struct { // Renamed to avoid conflict + Label string + Value float64 +} + +func (s FooterSummary) Format() string { return fmt.Sprintf("%s: %.2f", s.Label, s.Value) } // Implements tw.Formatter + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Header("ColA", "ColB", "ColC", "ColD") // Header for context + + // Variadic Arguments + table.Footer("", "", "Total", 1408) + + // Slice of Any Type + // table.Footer([]any{"", "", "Total", 1408.50}) + + table.Render() // Render this table + + fmt.Println("--- Another Table with Formatter Footer ---") + table2 := tablewriter.NewTable(os.Stdout) + table2.Header("Summary Info") // Single column header + // Using Formatter for a single cell footer + table2.Footer(FooterSummary{Label: "Grand Total", Value: 1408.50}) // Single cell: "Grand Total: 1408.50" + table2.Render() +} +``` + +**Key Changes**: +- **Method**: `SetFooter([]string)` replaced by `Footer(...any)` (`tablewriter.go:Footer`). +- **Input Flexibility**: Like `Header`, accepts variadic arguments, slices, or structs with `Formatter`/`Stringer` support (`zoo.go:processVariadic`). +- **Streaming**: Footers are buffered via `streamStoreFooter` and rendered during `Close()` (`stream.go:streamStoreFooter`, `stream.go:streamRenderFooter`). +- **Formatting**: Controlled by `Config.Footer` settings (e.g., `Alignment`, `AutoWrap`) (`zoo.go:prepareTableSection`). + +**Migration Tips**: +- Replace `SetFooter` with `Footer`, preferring variadic input for simplicity. +- Use `tw.Formatter` for custom footer formatting (e.g., formatted numbers). +- Ensure footer cell count matches headers/rows to maintain alignment. +- In streaming mode, call `Footer()` before `Close()` to include it in rendering. + +**Potential Pitfalls**: +- **Alignment Differences**: Default `Footer.Alignment.Global = tw.AlignRight` differs from rows (`tw.AlignLeft`); adjust if needed (`config.go`). +- **Streaming Timing**: Footers not rendered until `Close()`; ensure `Close()` is called (`stream.go`). +- **Empty Footers**: Missing footers may affect table appearance; use placeholders if needed. + +### 3. Rendering the Table +Rendering has been overhauled to support both batch and streaming modes, with mandatory error handling for robustness. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Data"}) + table.Append([]string{"Example"}) + table.Render() +} +``` + +**New (v1.0.x) - Batch Mode:** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "log" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Header("Data") + table.Append("Example") + if err := table.Render(); err != nil { + log.Fatalf("Table rendering failed: %v", err) + } +} +``` + +**New (v1.0.x) - Streaming Mode:** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "log" + "os" +) + +func main() { + tableStream := tablewriter.NewTable(os.Stdout, + tablewriter.WithConfig(tablewriter.Config{ + Stream: tw.StreamConfig{Enable: true}, + Widths: tw.CellWidth{ + Global: 12, // Fixed column width for streaming + PerColumn: tw.NewMapper[int, int]().Set(0, 15), // Column 0 at 15 + }, + }), + ) + // Alternative: Using WithStreaming Option + // tableStream := tablewriter.NewTable(os.Stdout, + // tablewriter.WithStreaming(tw.StreamConfig{Enable: true}), + // tablewriter.WithColumnMax(12), // Sets Config.Widths.Global + // ) + + if err := tableStream.Start(); err != nil { + log.Fatalf("Failed to start table stream: %v", err) + } + tableStream.Header("Column 1", "Column 2") + for i := 0; i < 3; i++ { + if err := tableStream.Append(fmt.Sprintf("Data %d-1", i), fmt.Sprintf("Data %d-2", i)); err != nil { + log.Printf("Failed to append row %d: %v", i, err) // Log and continue or handle differently + } + } + tableStream.Footer("End", "Summary") + if err := tableStream.Close(); err != nil { + log.Fatalf("Failed to close table stream: %v", err) + } +} +``` + +**Key Changes**: +- **Batch Mode**: + - `Render()` processes all data (headers, rows, footers) in one go (`tablewriter.go:render`). + - Calculates column widths dynamically based on content, `Config.Widths`, `ColMaxWidths`, and `MaxWidth` (`zoo.go:calculateAndNormalizeWidths`). + - Invokes renderer methods: `Start()`, `Header()`, `Row()`, `Footer()`, `Line()`, `Close()` (`tw/renderer.go`). + - Returns errors for invalid configurations or I/O issues. +- **Streaming Mode**: + - Enabled via `Config.Stream.Enable` or `WithStreaming(tw.StreamConfig{Enable: true})` (`tablewriter.go:WithStreaming`). + - `Start()` initializes the stream, fixing column widths based on `Config.Widths` or first data (header/row) (`stream.go:streamCalculateWidths`). + - `Header()`, `Append()` render immediately (`stream.go:streamRenderHeader`, `stream.go:streamAppendRow`). + - `Footer()` buffers data, rendered by `Close()` (`stream.go:streamStoreFooter`, `stream.go:streamRenderFooter`). + - `Close()` finalizes rendering with footer and borders (`stream.go:Close`). + - All methods return errors for robust handling. +- **Error Handling**: Mandatory error checks replace silent failures, improving reliability. + +**Migration Tips**: +- Replace `Render()` calls with error-checked versions in batch mode. +- For streaming, adopt `Start()`, `Append()`, `Close()` workflow, ensuring `Start()` precedes data input. +- Set `Config.Widths` for consistent column widths in streaming mode (`config.go`). +- Use `WithRendition` to customize visual output, as renderer settings are decoupled (`tablewriter.go`). +- Test rendering with small datasets to verify configuration before scaling. + +**Potential Pitfalls**: +- **Missing Error Checks**: Failing to check errors can miss rendering failures; always use `if err != nil`. +- **Streaming Widths**: Widths are fixed after `Start()`; inconsistent data may cause truncation (`stream.go`). +- **Renderer Misconfiguration**: Ensure `tw.Rendition` matches desired output style (`tw/renderer.go`). +- **Incomplete Streaming**: Forgetting `Close()` in streaming mode omits footer and final borders (`stream.go`). +- **Batch vs. Streaming**: Using `Render()` in streaming mode causes errors; use `Start()`/`Close()` instead (`tablewriter.go`). + + +## Styling and Appearance Configuration + +Styling in v1.0.x is split between `tablewriter.Config` for data processing (e.g., alignment, padding, wrapping) and `tw.Rendition` for visual rendering (e.g., borders, symbols, lines). This section details how to migrate v0.0.5 styling methods to v1.0.x, providing examples, best practices, and migration tips to maintain or enhance table appearance. + +### 4.1. Table Styles +Table styles define the visual structure through border and separator characters. In v0.0.5, styles were set via individual separator methods, whereas v1.0.x uses `tw.Rendition.Symbols` for a cohesive approach, offering predefined styles and custom symbol sets. + +**Available Table Styles**: +The `tw.Symbols` interface (`tw/symbols.go`) supports a variety of predefined styles, each tailored to specific use cases, as well as custom configurations for unique requirements. + +| Style Name | Use Case | Symbols Example | Recommended Context | +|----------------|-----------------------------------|-------------------------------------|-----------------------------------------| +| `StyleASCII` | Simple, terminal-friendly | `+`, `-`, `|` | Basic CLI output, minimal dependencies; ensures compatibility across all terminals, including older or non-Unicode systems. | +| `StyleLight` | Clean, lightweight borders | `┌`, `└`, `─`, `│` | Modern terminals, clean and professional aesthetics; suitable for most CLI applications requiring a modern look. | +| `StyleHeavy` | Thick, prominent borders | `┏`, `┗`, `━`, `┃` | High-visibility reports, dashboards, or logs; emphasizes table structure for critical data presentation. | +| `StyleDouble` | Double-line borders | `╔`, `╚`, `═`, `║` | Formal documents, structured data exports; visually distinct for presentations or printed outputs. | +| `StyleRounded` | Rounded corners, aesthetic | `╭`, `╰`, `─`, `│` | User-friendly CLI applications, reports; enhances visual appeal with smooth, rounded edges. | +| `StyleMarkdown`| Markdown-compatible | `|`, `-`, `:` | Documentation, GitHub READMEs, or Markdown-based platforms; ensures proper rendering in Markdown viewers. | +*Note: `StyleBold` was mentioned but not defined in the symbols code, `StyleHeavy` is similar.* + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetCenterSeparator("*") // Example, actual v0.0.5 method might vary + // table.SetColumnSeparator("!") + // table.SetRowSeparator("=") + // table.SetBorder(true) + table.SetHeader([]string{"Header1", "Header2"}) + table.Append([]string{"Cell1", "Cell2"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Using a Predefined Style (Rounded Corners for Aesthetic Output) + tableStyled := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), // Ensure renderer is set + tablewriter.WithRendition(tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleRounded), // Predefined rounded style + Borders: tw.Border{Top: tw.On, Bottom: tw.On, Left: tw.On, Right: tw.On}, + Settings: tw.Settings{ + Separators: tw.Separators{BetweenRows: tw.On}, // Lines between rows + }, + }), + ) + tableStyled.Header("Name", "Status") + tableStyled.Append("Node1", "Ready") + tableStyled.Render() + + // Using Fully Custom Symbols (Mimicking v0.0.5 Custom Separators) + mySymbols := tw.NewSymbolCustom("my-style"). // Fluent builder for custom symbols + WithCenter("*"). // Junction of lines + WithColumn("!"). // Vertical separator + WithRow("="). // Horizontal separator + WithTopLeft("/"). + WithTopMid("-"). + WithTopRight("\\"). + WithMidLeft("["). + WithMidRight("]"). // Corrected from duplicate WithMidRight("+") + // WithMidMid was not a method in SymbolCustom + WithBottomLeft("\\"). + WithBottomMid("_"). + WithBottomRight("/"). + WithHeaderLeft("("). + WithHeaderMid("-"). + WithHeaderRight(")") // Header-specific + tableCustomSymbols := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), + tablewriter.WithRendition(tw.Rendition{ + Symbols: mySymbols, + Borders: tw.Border{Top: tw.On, Bottom: tw.On, Left: tw.On, Right: tw.On}, + }), + ) + tableCustomSymbols.Header("Name", "Status") + tableCustomSymbols.Append("Node1", "Ready") + tableCustomSymbols.Render() +} +``` + +**Output (Styled, Rounded):** +``` +╭───────┬────────╮ +│ NAME │ STATUS │ +├───────┼────────┤ +│ Node1 │ Ready │ +╰───────┴────────╯ +``` + +**Output (Custom Symbols):** +``` +/=======-========\ +! NAME ! STATUS ! +[=======*========] +! Node1 ! Ready ! +\=======_========/ +``` + +**Key Changes**: +- **Deprecated Methods**: `SetCenterSeparator`, `SetColumnSeparator`, `SetRowSeparator`, and `SetBorder` are deprecated and moved to `deprecated.go`. These are replaced by `tw.Rendition.Symbols` and `tw.Rendition.Borders` for a unified styling approach (`tablewriter.go`). +- **Symbol System**: The `tw.Symbols` interface defines all drawing characters used for table lines, junctions, and corners (`tw/symbols.go:Symbols`). + - `tw.NewSymbols(tw.BorderStyle)` provides predefined styles (e.g., `tw.StyleASCII`, `tw.StyleMarkdown`, `tw.StyleRounded`) for common use cases. (Note: `tw.Style` should be `tw.BorderStyle`) + - `tw.NewSymbolCustom(name string)` enables fully custom symbol sets via a fluent builder, allowing precise control over each character (e.g., `WithCenter`, `WithTopLeft`). +- **Renderer Dependency**: Styling requires a renderer, set via `WithRenderer`; the default is `renderer.NewBlueprint()` if not specified (`tablewriter.go:WithRenderer`). +- **Border Control**: `tw.Rendition.Borders` uses `tw.State` (`tw.On`, `tw.Off`) to enable or disable borders on each side (Top, Bottom, Left, Right) (`tw/renderer.go:Border`). +- **Extensibility**: Custom styles can be combined with custom renderers for non-text outputs, enhancing flexibility (`tw/renderer.go`). + +**Migration Tips**: +- Replace individual separator setters (`SetCenterSeparator`, etc.) with `tw.NewSymbols` for predefined styles or `tw.NewSymbolCustom` for custom designs to maintain or enhance v0.0.5 styling. +- Use `WithRendition` to apply `tw.Rendition` settings, ensuring a renderer is explicitly set to avoid default behavior (`tablewriter.go`). +- Test table styles in your target environment (e.g., terminal, Markdown viewer, or log file) to ensure compatibility with fonts and display capabilities. +- For Markdown-based outputs (e.g., GitHub READMEs), use `tw.StyleMarkdown` to ensure proper rendering in Markdown parsers (`tw/symbols.go`). +- Combine `tw.Rendition.Symbols` with `tw.Rendition.Borders` and `tw.Rendition.Settings` to replicate or improve v0.0.5’s border and line configurations (`tw/renderer.go`). +- Document custom symbol sets in code comments to aid maintenance, as they can be complex (`tw/symbols.go`). + +**Potential Pitfalls**: +- **Missing Renderer**: If `WithRenderer` is omitted, `NewTable` defaults to `renderer.NewBlueprint` with minimal styling, which may not match v0.0.5’s `SetBorder(true)` behavior; always specify for custom styles (`tablewriter.go`). +- **Incomplete Custom Symbols**: When using `tw.NewSymbolCustom`, failing to set all required symbols (e.g., `TopLeft`, `Center`, `HeaderLeft`) can cause rendering errors or inconsistent visuals; ensure all necessary characters are defined (`tw/symbols.go`). +- **Terminal Compatibility Issues**: Advanced styles like `StyleDouble` or `StyleHeavy` may not render correctly in older terminals or non-Unicode environments; use `StyleASCII` for maximum compatibility across platforms (`tw/symbols.go`). +- **Border and Symbol Mismatch**: Inconsistent `tw.Rendition.Borders` and `tw.Symbols` settings (e.g., enabling borders but using minimal symbols) can lead to visual artifacts; test with small tables to verify alignment (`tw/renderer.go`). +- **Markdown Rendering**: Non-Markdown styles (e.g., `StyleRounded`) may not render correctly in Markdown viewers; use `StyleMarkdown` for documentation or web-based outputs (`tw/symbols.go`). + +### 4.2. Borders and Separator Lines +Borders and internal lines define the table’s structural appearance, controlling the visibility of outer edges and internal divisions. In v0.0.5, these were set via specific methods, while v1.0.x uses `tw.Rendition` fields for a more integrated approach. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetBorder(false) // Disable all outer borders + // table.SetRowLine(true) // Enable lines between data rows + // table.SetHeaderLine(true) // Enable line below header + table.SetHeader([]string{"Header1", "Header2"}) + table.Append([]string{"Cell1", "Cell2"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Standard Bordered Table with Internal Lines + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), + tablewriter.WithRendition(tw.Rendition{ + Borders: tw.Border{ // Outer table borders + Left: tw.On, + Right: tw.On, + Top: tw.On, + Bottom: tw.On, + }, + Settings: tw.Settings{ + Lines: tw.Lines{ // Major internal separator lines + ShowHeaderLine: tw.On, // Line after header + ShowFooterLine: tw.On, // Line before footer (if footer exists) + }, + Separators: tw.Separators{ // General row and column separators + BetweenRows: tw.On, // Horizontal lines between data rows + BetweenColumns: tw.On, // Vertical lines between columns + }, + }, + }), + ) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() + + // Borderless Table (kubectl-style, No Lines or Separators) + // Configure the table with a borderless, kubectl-style layout + config := tablewriter.NewConfigBuilder(). + Header(). + Padding(). + WithGlobal(tw.PaddingNone). // No header padding + Build(). + Alignment(). + WithGlobal(tw.AlignLeft). // Left-align header + Build(). + Row(). + Padding(). + WithGlobal(tw.PaddingNone). // No row padding + Build(). + Alignment(). + WithGlobal(tw.AlignLeft). // Left-align rows + Build(). + Footer(). + Padding(). + WithGlobal(tw.PaddingNone). // No footer padding + Build(). + Alignment(). + WithGlobal(tw.AlignLeft). // Left-align footer (if used) + Build(). + WithDebug(true). // Enable debug logging + Build() + + // Create borderless table + tableBorderless := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), // Assumes valid renderer + tablewriter.WithRendition(tw.Rendition{ + Borders: tw.BorderNone, // No borders + Symbols: tw.NewSymbols(tw.StyleNone), // No border symbols + Settings: tw.Settings{ + Lines: tw.LinesNone, // No header/footer lines + Separators: tw.SeparatorsNone, // No row/column separators + }, + }), + tablewriter.WithConfig(config), + ) + + // Set headers and data + tableBorderless.Header("Name", "Status") + tableBorderless.Append("Node1", "Ready") + tableBorderless.Render() +} +``` + +**Output (Standard Bordered):** +``` +┌───────┬────────┐ +│ Name │ Status │ +├───────┼────────┤ +│ Node1 │ Ready │ +└───────┴────────┘ +``` + +**Output (Borderless):** +``` +NAME STATUS +Node1 Ready +``` + +**Key Changes**: +- **Deprecated Methods**: `SetBorder`, `SetRowLine`, and `SetHeaderLine` are deprecated and moved to `deprecated.go`. These are replaced by fields in `tw.Rendition` (`tw/renderer.go`): + - `Borders`: Controls outer table borders (`tw.Border`) with `tw.State` (`tw.On`, `tw.Off`) for each side (Top, Bottom, Left, Right). + - `Settings.Lines`: Manages major internal lines (`ShowHeaderLine` for header, `ShowFooterLine` for footer) (`tw.Lines`). + - `Settings.Separators`: Controls general separators between rows (`BetweenRows`) and columns (`BetweenColumns`) (`tw.Separators`). +- **Presets for Simplicity**: `tw.BorderNone`, `tw.LinesNone`, and `tw.SeparatorsNone` provide quick configurations for minimal or borderless tables (`tw/preset.go`). +- **Renderer Integration**: Border and line settings are applied via `WithRendition`, requiring a renderer to be set (`tablewriter.go:WithRendition`). +- **Granular Control**: Each border side and line type can be independently configured, offering greater flexibility than v0.0.5’s boolean toggles. +- **Dependency on Symbols**: The appearance of borders and lines depends on `tw.Rendition.Symbols`; ensure compatible symbol sets (`tw/symbols.go`). + +**Migration Tips**: +- Replace `SetBorder(false)` with `tw.Rendition.Borders = tw.BorderNone` to disable all outer borders (`tw/preset.go`). +- Use `tw.Rendition.Settings.Separators.BetweenRows = tw.On` to replicate `SetRowLine(true)`, ensuring row separators are visible (`tw/renderer.go`). +- Set `tw.Rendition.Settings.Lines.ShowHeaderLine = tw.On` to mimic `SetHeaderLine(true)` for a line below the header (`tw/renderer.go`). +- For kubectl-style borderless tables, combine `tw.BorderNone`, `tw.LinesNone`, `tw.SeparatorsNone`, and `WithPadding(tw.PaddingNone)` (applied via `ConfigBuilder` or `WithConfig`) to eliminate all lines and spacing (`tw/preset.go`, `config.go`). +- Test border and line configurations with small tables to verify visual consistency, especially when combining with custom `tw.Symbols`. +- Use `WithDebug(true)` to log rendering details if borders or lines appear incorrectly (`config.go`). + +**Potential Pitfalls**: +- **Separator Absence**: If `tw.Rendition.Settings.Separators.BetweenColumns` is `tw.Off` and borders are disabled, columns may lack visual separation; use `tw.CellPadding` or ensure content spacing (`tw/cell.go`). +- **Line and Border Conflicts**: Mismatched settings (e.g., enabling `ShowHeaderLine` but disabling `Borders.Top`) can cause uneven rendering; align `Borders`, `Lines`, and `Separators` settings (`tw/renderer.go`). +- **Renderer Dependency**: Border settings require a renderer; omitting `WithRenderer` defaults to `renderer.NewBlueprint` with minimal styling, which may not match v0.0.5 expectations (`tablewriter.go`). +- **Streaming Limitations**: In streaming mode, separator rendering is fixed after `Start()`; ensure `tw.Rendition` is set correctly before rendering begins (`stream.go`). +- **Symbol Mismatch**: Using minimal `tw.Symbols` (e.g., `StyleASCII`) with complex `Borders` settings may lead to visual artifacts; test with matching symbol sets (`tw/symbols.go`). + +### 4.3. Alignment +Alignment controls the positioning of text within table cells, now configurable per section (Header, Row, Footer) with both global and per-column options for greater precision. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" // Assuming ALIGN_CENTER etc. were constants here + "os" +) + +const ( // Mocking v0.0.5 constants for example completeness + ALIGN_CENTER = 1 // Example values + ALIGN_LEFT = 2 +) + + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetAlignment(ALIGN_CENTER) // Applied to data rows + // table.SetHeaderAlignment(ALIGN_LEFT) // Applied to header + // No specific footer alignment setter + table.SetHeader([]string{"Header1", "Header2"}) + table.Append([]string{"Cell1", "Cell2"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + cfg := tablewriter.Config{ + Header: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, + }, + Row: tw.CellConfig{ + Alignment: tw.CellAlignment{ + Global: tw.AlignCenter, + PerColumn: []tw.Align{tw.AlignLeft, tw.AlignRight}, // Col 0 left, Col 1 right + }, + }, + Footer: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignRight}, + }, + } + table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Footer("", "Active") // Ensure footer has content to show alignment + table.Render() +} +``` + +**Output:** +``` +┌───────┬────────┐ +│ NAME │ STATUS │ +├───────┼────────┤ +│ Node1 │ Ready │ +├───────┼────────┤ +│ │ Active │ +└───────┴────────┘ +``` + +**Key Changes**: +- **Deprecated Methods**: `SetAlignment` and `SetHeaderAlignment` are replaced by `WithRowAlignment`, `WithHeaderAlignment`, `WithFooterAlignment`, or direct `Config` settings (`config.go`). These old methods are retained in `deprecated.go` for compatibility but should be migrated. +- **Alignment Structure**: Alignment is managed within `tw.CellConfig.Alignment` (`tw/cell.go:CellAlignment`), which includes: + - `Global`: A single `tw.Align` value applied to all cells in the section (`tw.AlignLeft`, `tw.AlignCenter`, `tw.AlignRight`, `tw.AlignNone`). + - `PerColumn`: A slice of `tw.Align` values for column-specific alignment, overriding `Global` for specified columns. +- **Footer Alignment**: v1.0.x introduces explicit footer alignment via `WithFooterAlignment` or `Config.Footer.Alignment`, addressing v0.0.5’s lack of footer-specific control (`config.go`). +- **Type Safety**: `tw.Align` string constants replace v0.0.5’s integer constants (e.g., `ALIGN_CENTER`), improving clarity and reducing errors (`tw/types.go`). +- **Builder Support**: `ConfigBuilder` provides `Alignment()` methods for each section. `ForColumn(idx).WithAlignment()` applies alignment to a specific column across all sections (`config.go:ConfigBuilder`, `config.go:ColumnConfigBuilder`). +- **Deprecated Fields**: `tw.CellConfig.ColumnAligns` (slice) and `tw.CellFormatting.Alignment` (single value) are supported for backward compatibility but should be migrated to `tw.CellAlignment.Global` and `tw.CellAlignment.PerColumn` (`tw/cell.go`). + +**Migration Tips**: +- Replace `SetAlignment(ALIGN_X)` with `WithRowAlignment(tw.AlignX)` or `Config.Row.Alignment.Global = tw.AlignX` to set row alignment (`config.go`). +- Use `WithHeaderAlignment(tw.AlignX)` for headers and `WithFooterAlignment(tw.AlignX)` for footers to maintain or adjust v0.0.5 behavior (`config.go`). +- Specify per-column alignments with `ConfigBuilder.Row().Alignment().WithPerColumn([]tw.Align{...})` or by setting `Config.Row.Alignment.PerColumn` for fine-grained control (`config.go`). +- Use `ConfigBuilder.ForColumn(idx).WithAlignment(tw.AlignX)` to apply consistent alignment to a specific column across all sections (Header, Row, Footer) (`config.go`). +- Verify alignment settings against defaults (`Header: tw.AlignCenter`, `Row: tw.AlignLeft`, `Footer: tw.AlignRight`) to ensure expected output (`config.go:defaultConfig`). +- Test alignment with varied cell content lengths to confirm readability, especially when combined with wrapping or padding settings (`zoo.go:prepareContent`). + +**Potential Pitfalls**: +- **Alignment Precedence**: `PerColumn` settings override `Global` within a section; ensure column-specific alignments are intentional (`tw/cell.go:CellAlignment`). +- **Deprecated Fields**: Relying on `ColumnAligns` or `tw.CellFormatting.Alignment` is temporary; migrate to `tw.CellAlignment` to avoid future issues (`tw/cell.go`). +- **Cell Count Mismatch**: Rows or footers with fewer cells than headers can cause alignment errors; pad with empty strings (`""`) to match column count (`zoo.go`). +- **Streaming Width Impact**: In streaming mode, alignment depends on fixed column widths set by `Config.Widths`; narrow widths may truncate content, misaligning text (`stream.go:streamCalculateWidths`). +- **Default Misalignment**: The default `Footer.Alignment.Global = tw.AlignRight` differs from rows (`tw.AlignLeft`); explicitly set `WithFooterAlignment` if consistency is needed (`config.go`). + +### 4.4. Auto-Formatting (Header Title Case) +Auto-formatting applies transformations like title case to cell content, primarily for headers to enhance readability, but it can be enabled for rows or footers in v1.0.x. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetAutoFormatHeaders(true) // Default: true; applies title case to headers + table.SetHeader([]string{"col_one", "status_report"}) + table.Append([]string{"Node1", "Ready"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Using Direct Config Struct to turn OFF default AutoFormat for Header + cfg := tablewriter.Config{ + Header: tw.CellConfig{Formatting: tw.CellFormatting{AutoFormat: tw.Off}}, // Turn OFF title case for headers + Row: tw.CellConfig{Formatting: tw.CellFormatting{AutoFormat: tw.Off}}, // No formatting for rows (default) + Footer: tw.CellConfig{Formatting: tw.CellFormatting{AutoFormat: tw.Off}}, // No formatting for footers (default) + } + tableNoAutoFormat := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + + tableNoAutoFormat.Header("col_one", "status_report") // Stays as "col_one", "status_report" + tableNoAutoFormat.Append("Node1", "Ready") + tableNoAutoFormat.Render() + + // Using Option Function for Headers (default is ON, this makes it explicit) + tableWithAutoFormat := tablewriter.NewTable(os.Stdout, + tablewriter.WithHeaderAutoFormat(tw.On), // Explicitly enable title case (default behavior) + ) + + tableWithAutoFormat.Header("col_one", "status_report") // Becomes "COL ONE", "STATUS REPORT" + tableWithAutoFormat.Append("Node1", "Ready") + tableWithAutoFormat.Render() +} +``` + +**Output:** +``` +┌─────────┬───────────────┐ +│ col_one │ status_report │ +├─────────┼───────────────┤ +│ Node1 │ Ready │ +└─────────┴───────────────┘ +┌─────────┬───────────────┐ +│ COL ONE │ STATUS REPORT │ +├─────────┼───────────────┤ +│ Node1 │ Ready │ +└─────────┴───────────────┘ +``` + +**Key Changes**: +- **Method**: `SetAutoFormatHeaders` is replaced by `Config.Header.Formatting.AutoFormat`, or equivalent builder methods (`config.go`). +- **Extended Scope**: Auto-formatting can now be applied to rows and footers via `Config.Row.Formatting.AutoFormat` and `Config.Footer.Formatting.AutoFormat`, unlike v0.0.5’s header-only support (`tw/cell.go`). +- **Type Safety**: `tw.State` (`tw.On`, `tw.Off`, `tw.Unknown`) controls formatting state, replacing boolean flags (`tw/state.go`). +- **Behavior**: When `tw.On`, the `tw.Title` function converts text to uppercase and replaces underscores and some periods with spaces (e.g., "col_one" → "COL ONE") (`tw/fn.go:Title`, `zoo.go:prepareContent`). +- **Defaults**: `Header.Formatting.AutoFormat = tw.On`, `Row.Formatting.AutoFormat = tw.Off`, `Footer.Formatting.AutoFormat = tw.Off` (`config.go:defaultConfig`). + +**Migration Tips**: +- To maintain v0.0.5’s default header title case behavior, no explicit action is needed as `WithHeaderAutoFormat(tw.On)` is the default. If you were using `SetAutoFormatHeaders(false)`, you'd use `WithHeaderAutoFormat(tw.Off)`. +- Explicitly set `WithRowAutoFormat(tw.Off)` or `WithFooterAutoFormat(tw.Off)` if you want to ensure rows and footers remain unformatted, as v1.0.x allows enabling formatting for these sections (`config.go`). +- Use `ConfigBuilder.Header().Formatting().WithAutoFormat(tw.State)` for precise control over formatting per section (`config.go`). +- Test header output with underscores or periods (e.g., "my_column") to verify title case transformation meets expectations. +- For custom formatting beyond title case (e.g., custom capitalization), use `tw.CellFilter` instead of `AutoFormat` (`tw/cell.go`). + +**Potential Pitfalls**: +- **Default Header Formatting**: `Header.Formatting.AutoFormat = tw.On` by default may unexpectedly alter header text (e.g., "col_one" → "COL ONE"); disable with `WithHeaderAutoFormat(tw.Off)` if raw headers are preferred (`config.go`). +- **Row/Footer Formatting**: Enabling `AutoFormat` for rows or footers (not default) applies title case, which may not suit data content; verify with `tw.Off` unless intended (`tw/cell.go`). +- **Filter Conflicts**: Combining `AutoFormat` with `tw.CellFilter` can lead to overlapping transformations; prioritize filters for complex formatting (`zoo.go:prepareContent`). +- **Performance Overhead**: Auto-formatting large datasets may add minor processing time; disable for performance-critical applications (`zoo.go`). + +### 4.5. Text Wrapping +Text wrapping determines how long cell content is handled within width constraints, offering more options in v1.0.x compared to v0.0.5’s binary toggle. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetAutoWrapText(true) // Enable normal word wrapping + // table.SetAutoWrapText(false) // Disable wrapping + table.SetHeader([]string{"Long Header Text Example", "Status"}) + table.Append([]string{"This is some very long cell content that might wrap", "Ready"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.WrapNormal etc. + "os" +) + +func main() { + // Using Option Functions for Quick Wrapping Settings on a specific section (e.g., Row) + // To actually see wrapping, a MaxWidth for the table or columns is needed. + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRowAutoWrap(tw.WrapNormal), // Set row wrapping + tablewriter.WithHeaderAutoWrap(tw.WrapTruncate), // Header truncates (default) + tablewriter.WithMaxWidth(30), // Force wrapping by setting table max width + ) + table.Header("Long Header Text", "Status") + table.Append("This is a very long cell content", "Ready") + table.Footer("Summary", "Active") + table.Render() + + // For more fine-grained control (e.g., different wrapping for header, row, footer): + cfgBuilder := tablewriter.NewConfigBuilder() + cfgBuilder.Header().Formatting().WithAutoWrap(tw.WrapTruncate) // Header: Truncate + cfgBuilder.Row().Formatting().WithAutoWrap(tw.WrapNormal) // Row: Normal wrap + cfgBuilder.Footer().Formatting().WithAutoWrap(tw.WrapBreak) // Footer: Break words + cfgBuilder.WithMaxWidth(40) // Overall table width constraint + + tableFullCfg := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) + tableFullCfg.Header("Another Very Long Header Example That Will Be Truncated", "Info") + tableFullCfg.Append("This is an example of row content that should wrap normally based on available space.", "Detail") + tableFullCfg.Footer("FinalSummaryInformationThatMightBreakAcrossLines", "End") + tableFullCfg.Render() +} +``` + +**Output (tableOpt):** +``` +┌──────────────┬────────┐ +│ LONG HEADER… │ STATUS │ +├──────────────┼────────┤ +│ This is a │ Ready │ +│ very long │ │ +│ cell content │ │ +├──────────────┼────────┤ +│ Summary │ Active │ +└──────────────┴────────┘ +``` +*(Second table output will vary based on content and width)* + +**Key Changes**: +- **Method**: `SetAutoWrapText` is replaced by `Config.
.Formatting.AutoWrap` or specific `With
AutoWrap` options (`config.go`). +- **Wrapping Modes**: `int` constants for `AutoWrap` (e.g., `tw.WrapNone`, `tw.WrapNormal`, `tw.WrapTruncate`, `tw.WrapBreak`) replace v0.0.5’s binary toggle (`tw/tw.go`). +- **Section-Specific Control**: Wrapping is configurable per section (Header, Row, Footer), unlike v0.0.5’s global setting (`tw/cell.go`). +- **Defaults**: `Header: tw.WrapTruncate`, `Row: tw.WrapNormal`, `Footer: tw.WrapNormal` (`config.go:defaultConfig`). +- **Width Dependency**: Wrapping behavior relies on width constraints set by `Config.Widths` (fixed column widths), `Config.
.ColMaxWidths` (max content width), or `Config.MaxWidth` (total table width) (`zoo.go:calculateContentMaxWidth`, `zoo.go:prepareContent`). + +**Migration Tips**: +- Replace `SetAutoWrapText(true)` with `WithRowAutoWrap(tw.WrapNormal)` to maintain v0.0.5’s default wrapping for rows (`config.go`). +- Use `WithHeaderAutoWrap(tw.WrapTruncate)` to align with v1.0.x’s default header behavior, ensuring long headers are truncated (`config.go`). +- Set `Config.Widths` or `Config.MaxWidth` explicitly to enforce wrapping, as unconstrained widths may prevent wrapping (`config.go`). +- Use `ConfigBuilder.
().Formatting().WithAutoWrap(int_wrap_mode)` for precise control over wrapping per section (`config.go`). +- Test wrapping with varied content lengths (e.g., short and long text) to ensure readability and proper width allocation. +- Consider `tw.WrapNormal` for data rows to preserve content integrity, reserving `tw.WrapTruncate` for headers or footers (`tw/tw.go`). + +**Potential Pitfalls**: +- **Missing Width Constraints**: Without `Config.Widths`, `ColMaxWidths`, or `MaxWidth`, wrapping may not occur, leading to overflow; always define width limits for wrapping (`zoo.go`). +- **Streaming Width Impact**: In streaming mode, wrapping depends on fixed widths set at `Start()`; narrow widths may truncate content excessively (`stream.go:streamCalculateWidths`). +- **Truncation Data Loss**: `tw.WrapTruncate` may obscure critical data in rows; use `tw.WrapNormal` or wider columns to retain content (`tw/tw.go`). +- **Performance Overhead**: Wrapping large datasets with `tw.WrapNormal` or `tw.WrapBreak` can add processing time; optimize widths for performance-critical applications (`zoo.go:prepareContent`). +- **Inconsistent Section Wrapping**: Default wrapping differs (`Header: tw.WrapTruncate`, `Row/Footer: tw.WrapNormal`); align settings if uniform behavior is needed (`config.go`). + +### 4.6. Padding +Padding adds spacing within cells, enhancing readability and affecting cell width calculations. v1.0.x introduces granular, per-side padding, replacing v0.0.5’s single inter-column padding control. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetTablePadding("\t") // Set inter-column space character when borders are off + // Default: single space within cells + table.SetHeader([]string{"Header1"}) + table.Append([]string{"Cell1"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Using Direct Config Struct + cfg := tablewriter.Config{ + Header: tw.CellConfig{ + Padding: tw.CellPadding{ + Global: tw.Padding{Left: "[", Right: "]", Top: "-", Bottom: "-"}, // Padding for all header cells + PerColumn: []tw.Padding{ // Specific padding for header column 0 + {Left: ">>", Right: "<<", Top: "=", Bottom: "="}, // Overrides Global for column 0 + }, + }, + }, + Row: tw.CellConfig{ + Padding: tw.CellPadding{ + Global: tw.PaddingDefault, // One space left/right for all row cells + }, + }, + Footer: tw.CellConfig{ + Padding: tw.CellPadding{ + Global: tw.Padding{Top: "~", Bottom: "~"}, // Top/bottom padding for all footer cells + }, + }, + } + table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + + table.Header("Name", "Status") // Two columns + table.Append("Node1", "Ready") + table.Footer("End", "Active") + table.Render() +} +``` + +**Output:** +``` +┌────────┬────────┐ +│========│[------]│ +│>>NAME<<│[STATUS]│ +│========│[------]│ +├────────┼────────┤ +│ Node1 │ Ready │ +│~~~~~~~~│~~~~~~~~│ +│End │Active │ +│~~~~~~~~│~~~~~~~~│ +└────────┴────────┘ +``` + +**Key Changes**: +- **No Direct Equivalent for `SetTablePadding`**: `SetTablePadding` controlled inter-column spacing when borders were off in v0.0.5; v1.0.x has no direct equivalent for *inter-column* spacing separate from cell padding. Inter-column visual separation is now primarily handled by `tw.Rendition.Settings.Separators.BetweenColumns` and the chosen `tw.Symbols`. +- **Granular Cell Padding**: `tw.CellPadding` (`tw/cell.go:CellPadding`) supports: + - `Global`: A `tw.Padding` struct with `Left`, `Right`, `Top`, `Bottom` strings and an `Overwrite` flag (`tw/types.go:Padding`). This padding is *inside* the cell. + - `PerColumn`: A slice of `tw.Padding` for column-specific padding, overriding `Global` for specified columns. +- **Per-Side Control**: `Top` and `Bottom` padding add extra lines *within* cells, unlike v0.0.5’s left/right-only spacing (`zoo.go:prepareContent`). +- **Defaults**: `tw.PaddingDefault` is `{Left: " ", Right: " "}` for all sections (applied inside cells); `Top` and `Bottom` are empty by default (`tw/preset.go`). +- **Width Impact**: Cell padding contributes to column widths, calculated in `Config.Widths` (`zoo.go:calculateAndNormalizeWidths`). +- **Presets**: `tw.PaddingNone` (`{Left: "", Right: "", Top: "", Bottom: "", Overwrite: true}`) removes padding for tight layouts (`tw/preset.go`). + +**Migration Tips**: +- To achieve spacing similar to `SetTablePadding("\t")` when borders are off, you would set cell padding: `WithPadding(tw.Padding{Left: "\t", Right: "\t"})`. If you truly mean space *between* columns and not *inside* cells, ensure `tw.Rendition.Settings.Separators.BetweenColumns` is `tw.On` and customize `tw.Symbols.Column()` if needed. +- Use `tw.PaddingNone` (e.g., via `ConfigBuilder.
().Padding().WithGlobal(tw.PaddingNone)`) for no cell padding. +- Set `Top` and `Bottom` padding for vertical spacing *within* cells, enhancing readability for multi-line content (`tw/types.go`). +- Use `ConfigBuilder.
().Padding().WithPerColumn` for column-specific padding to differentiate sections or columns (`config.go`). +- Test padding with varied content and widths to ensure proper alignment and spacing, especially with wrapping enabled (`zoo.go`). +- Combine padding with `Config.Widths` or `ColMaxWidths` to control total cell size (`config.go`). + +**Potential Pitfalls**: +- **Inter-Column Spacing vs. Cell Padding**: Be clear whether you want space *between* columns (separators) or *inside* cells (padding). `SetTablePadding` was ambiguous; v1.0.x distinguishes these. +- **Width Inflation**: Cell padding increases column widths, potentially exceeding `Config.MaxWidth` or causing truncation in streaming; adjust `Config.Widths` accordingly (`zoo.go`). +- **Top/Bottom Padding**: Non-empty `Top` or `Bottom` padding adds vertical lines *within* cells, increasing cell height; use sparingly for dense tables (`zoo.go:prepareContent`). +- **Streaming Constraints**: Padding is fixed in streaming mode after `Start()`; ensure `Config.Widths` accommodates padding (`stream.go`). +- **Default Padding**: `tw.PaddingDefault` adds spaces *inside* cells; set `tw.PaddingNone` for no internal cell padding (`tw/preset.go`). + +### 4.7. Column Widths (Fixed Widths and Max Content Widths) +Column width control in v1.0.x is more sophisticated, offering fixed widths, maximum content widths, and overall table width constraints, replacing v0.0.5’s limited `SetColMinWidth`. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetColMinWidth(0, 10) // Set minimum width for column 0 + table.SetHeader([]string{"Header1", "Header2"}) + table.Append([]string{"Cell1-Content", "Cell2-Content"}) + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Direct Config for Width Control + cfg := tablewriter.Config{ + Widths: tw.CellWidth{ // Fixed total column widths (content + padding) + Global: 20, // Default fixed width for all columns + PerColumn: tw.NewMapper[int, int]().Set(0, 15), // Column 0 fixed at 15 + }, + Header: tw.CellConfig{ + ColMaxWidths: tw.CellWidth{ // Max content width (excluding padding) for header cells + Global: 15, // Max content width for all header cells + PerColumn: tw.NewMapper[int, int]().Set(0, 10), // Header Col 0 max content at 10 + }, + // Default header padding is " " on left/right, so content 10 + padding 2 = 12. + // If Widths.PerColumn[0] is 15, there's space. + }, + Row: tw.CellConfig{ + ColMaxWidths: tw.CellWidth{Global: 18}, // Max content width for row cells (18 + default padding 2 = 20) + }, + MaxWidth: 80, // Constrain total table width (optional, columns might shrink) + } + tableWithCfg := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfg)) + tableWithCfg.Header("Very Long Header Name", "Status Information") + tableWithCfg.Append("Some long content for the first column", "Ready") + tableWithCfg.Render() + + // Option Functions for Width Settings + tableWithOpts := tablewriter.NewTable(os.Stdout, + tablewriter.WithColumnMax(20), // Sets Config.Widths.Global (fixed total col width) + tablewriter.WithColumnWidths(tw.NewMapper[int, int]().Set(0, 15)), // Sets Config.Widths.PerColumn for col 0 + tablewriter.WithMaxWidth(80), // Sets Config.MaxWidth + // For max content width per section, you'd use WithHeaderConfig, WithRowConfig, etc. + // e.g., tablewriter.WithRowMaxWidth(18) // Sets Config.Row.ColMaxWidths.Global + ) + tableWithOpts.Header("Long Header", "Status") + tableWithOpts.Append("Long Content", "Ready") + tableWithOpts.Render() +} +``` + +**Output (tableWithCfg - illustrative, exact wrapping depends on content and full config):** +``` +┌───────────┬──────────────────┐ +│ VERY LONG │ STATUS INFORMAT… │ +│ HEADER NA…│ │ +├───────────┼──────────────────┤ +│ Some long │ Ready │ +│ content f…│ │ +└───────────┴──────────────────┘ +``` + +**Key Changes**: +- **Enhanced Width System**: v1.0.x introduces three levels of width control, replacing `SetColMinWidth` (`config.go`): + - **Config.Widths**: Sets fixed total widths (content + padding) for columns, applied globally or per-column (`tw.CellWidth`). + - `Global`: Default fixed width for all columns. + - `PerColumn`: `tw.Mapper[int, int]` for specific column widths. + - **Config.
.ColMaxWidths**: Sets maximum content widths (excluding padding) for a section (Header, Row, Footer) (`tw.CellWidth`). + - `Global`: Max content width for all cells in the section. + - `PerColumn`: `tw.Mapper[int, int]` for specific columns in the section. + - **Config.MaxWidth**: Constrains the total table width, shrinking columns proportionally if needed (`config.go`). +- **Streaming Support**: In streaming mode, `Config.Widths` fixes column widths at `Start()`; `ColMaxWidths` is used only for wrapping/truncation (`stream.go:streamCalculateWidths`). +- **Calculation Logic**: Widths are computed by `calculateAndNormalizeWidths` in batch mode and `streamCalculateWidths` in streaming mode, considering content, padding, and constraints (`zoo.go`, `stream.go`). +- **Deprecated Approach**: `SetColMinWidth` is replaced by `Config.Widths.PerColumn` or `Config.
.ColMaxWidths.PerColumn` for more precise control (`deprecated.go`). + +**Migration Tips**: +- Replace `SetColMinWidth(col, w)` with `WithColumnWidths(tw.NewMapper[int, int]().Set(col, w))` for fixed column widths or `Config.
.ColMaxWidths.PerColumn` for content width limits (`config.go`). +- Use `Config.Widths.Global` or `WithColumnMax(w)` to set a default fixed width for all columns, ensuring consistency (`tablewriter.go`). +- Apply `Config.MaxWidth` to constrain total table width, especially for wide datasets (`config.go`). +- Use `ConfigBuilder.ForColumn(idx).WithMaxWidth(w)` to set per-column content width limits across sections (`config.go`). *(Note: This sets it for Header, Row, and Footer)* +- In streaming mode, set `Config.Widths` before `Start()` to fix widths, avoiding content-based sizing (`stream.go`). +- Test width settings with varied content to ensure wrapping and truncation behave as expected (`zoo.go`). + +**Potential Pitfalls**: +- **Width Precedence**: `Config.Widths.PerColumn` overrides `Widths.Global`; `ColMaxWidths` applies *within* those fixed total widths for content wrapping/truncation (`zoo.go`). +- **Streaming Width Fixing**: Widths are locked after `Start()` in streaming; inconsistent data may cause truncation (`stream.go`). +- **Padding Impact**: Padding adds to total width when considering `Config.Widths`; account for `tw.CellPadding` when setting fixed column widths (`zoo.go`). +- **MaxWidth Shrinkage**: `Config.MaxWidth` may shrink columns unevenly; test with `MaxWidth` to avoid cramped layouts (`zoo.go`). +- **No Width Constraints**: Without `Widths` or `MaxWidth`, columns size to content, potentially causing overflow; define limits (`zoo.go`). + +### 4.8. Colors +Colors in v0.0.5 were applied via specific color-setting methods, while v1.0.x embeds ANSI escape codes in cell content or uses data-driven formatting for greater flexibility. + +**Old (v0.0.5):** +```go +package main +// Assuming tablewriter.Colors and color constants existed in v0.0.5 +// This is a mock representation as the actual v0.0.5 definitions are not provided. +// import "github.com/olekukonko/tablewriter" +// import "os" + +// type Colors []interface{} // Mock +// const ( +// Bold = 1; FgGreenColor = 2; FgRedColor = 3 // Mock constants +// ) + +func main() { + // table := tablewriter.NewWriter(os.Stdout) + // table.SetColumnColor( + // tablewriter.Colors{tablewriter.Bold, tablewriter.FgGreenColor}, // Column 0 + // tablewriter.Colors{tablewriter.FgRedColor}, // Column 1 + // ) + // table.SetHeader([]string{"Name", "Status"}) + // table.Append([]string{"Node1", "Ready"}) + // table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.Formatter + "os" +) + +// Direct ANSI Code Embedding +const ( + Reset = "\033[0m" + Bold = "\033[1m" + FgGreen = "\033[32m" + FgRed = "\033[31m" +) + +// Using tw.Formatter for Custom Types +type Status string + +func (s Status) Format() string { // Implements tw.Formatter + color := FgGreen + if s == "Error" || s == "Inactive" { + color = FgRed + } + return color + string(s) + Reset +} + +func main() { + // Example 1: Direct ANSI embedding + tableDirectANSI := tablewriter.NewTable(os.Stdout, + tablewriter.WithHeaderAutoFormat(tw.Off), // Keep header text as is for coloring + ) + tableDirectANSI.Header(Bold+FgGreen+"Name"+Reset, Bold+FgRed+"Status"+Reset) + tableDirectANSI.Append([]any{"Node1", FgGreen + "Ready" + Reset}) + tableDirectANSI.Append([]any{"Node2", FgRed + "Error" + Reset}) + tableDirectANSI.Render() + + fmt.Println("\n--- Table with Formatter for Colors ---") + + // Example 2: Using tw.Formatter + tableFormatter := tablewriter.NewTable(os.Stdout) + tableFormatter.Header("Name", "Status") // AutoFormat will apply to "NAME", "STATUS" + tableFormatter.Append([]any{"Alice", Status("Active")}) + tableFormatter.Append([]any{"Bob", Status("Inactive")}) + tableFormatter.Render() + + fmt.Println("\n--- Table with CellFilter for Colors ---") + // Example 3: Using CellFilter + tableWithFilters := tablewriter.NewTable(os.Stdout, + tablewriter.WithConfig( + tablewriter.NewConfigBuilder(). + Row(). + Filter(). + WithPerColumn([]func(string) string{ + nil, // No filter for Item column + func(s string) string { // Status column: apply color + if s == "Ready" || s == "Active" { + return FgGreen + s + Reset + } + return FgRed + s + Reset + }, + }). + Build(). // Return to RowConfigBuilder + Build(). // Return to ConfigBuilder + Build(), // Finalize Config + ), + ) + tableWithFilters.Header("Item", "Availability") + tableWithFilters.Append("ItemA", "Ready") + tableWithFilters.Append("ItemB", "Unavailable") + tableWithFilters.Render() +} +``` + +**Output (Text Approximation, Colors Not Shown):** +``` +┌──────┬────────┐ +│ Name │ Status │ +├──────┼────────┤ +│Node1 │ Ready │ +│Node2 │ Error │ +└──────┴────────┘ + +--- Table with Formatter for Colors --- +┌───────┬──────────┐ +│ NAME │ STATUS │ +├───────┼──────────┤ +│ Alice │ Active │ +│ Bob │ Inactive │ +└───────┴──────────┘ + +--- Table with CellFilter for Colors --- +┌───────┬────────────┐ +│ ITEM │ AVAILABILI │ +│ │ TY │ +├───────┼────────────┤ +│ ItemA │ Ready │ +│ ItemB │ Unavailabl │ +│ │ e │ +└───────┴────────────┘ +``` + +**Key Changes**: +- **Removed Color Methods**: `SetColumnColor`, `SetHeaderColor`, and `SetFooterColor` are removed; colors are now applied by embedding ANSI escape codes in cell content or via data-driven mechanisms (`tablewriter.go`). +- **Flexible Coloring Options**: + - **Direct ANSI Codes**: Embed codes (e.g., `\033[32m` for green) in strings for manual control (`zoo.go:convertCellsToStrings`). + - **tw.Formatter**: Implement `Format() string` on custom types to control cell output, including colors (`tw/types.go:Formatter`). + - **tw.CellFilter**: Use `Config.
.Filter.Global` or `PerColumn` to apply transformations like coloring dynamically (`tw/cell.go:CellFilter`). +- **Width Handling**: `twdw.Width()` correctly calculates display width of ANSI-coded strings, ignoring escape sequences (`tw/fn.go:DisplayWidth`). +- **No Built-In Color Presets**: Unlike v0.0.5’s potential `tablewriter.Colors`, v1.0.x requires manual ANSI code management or external libraries for color constants. + +**Migration Tips**: +- Replace `SetColumnColor` with direct ANSI code embedding for simple cases (e.g., `FgGreen+"text"+Reset`) (`zoo.go`). +- Implement `tw.Formatter` on custom types for reusable, semantic color logic (e.g., `Status` type above) (`tw/types.go`). +- Use `ConfigBuilder.
().Filter().WithPerColumn` to apply color filters to specific columns, mimicking v0.0.5’s per-column coloring (`config.go`). +- Define ANSI constants in your codebase or use a library (e.g., `github.com/fatih/color`) to simplify color management. +- Test colored output in your target terminal to ensure ANSI codes render correctly. +- Combine filters with `AutoFormat` or wrapping for consistent styling (`zoo.go:prepareContent`). + +**Potential Pitfalls**: +- **Terminal Support**: Some terminals may not support ANSI codes, causing artifacts; test in your environment or provide a non-colored fallback. +- **Filter Overlap**: Combining `tw.CellFilter` with `AutoFormat` or other transformations can lead to unexpected results; prioritize filters for coloring (`zoo.go`). +- **Width Miscalculation**: Incorrect ANSI code handling (e.g., missing `Reset`) can skew width calculations; use `twdw.Width` (`tw/fn.go`). +- **Streaming Consistency**: In streaming mode, ensure color codes are applied consistently across rows to avoid visual discrepancies (`stream.go`). +- **Performance**: Applying filters to large datasets may add overhead; optimize filter logic for efficiency (`zoo.go`). + +## Advanced Features in v1.0.x + +v1.0.x introduces several advanced features that enhance table functionality beyond v0.0.5’s capabilities. This section covers cell merging, captions, filters, stringers, and performance optimizations, providing migration guidance and examples for leveraging these features. + +### 5. Cell Merging +Cell merging combines adjacent cells with identical content, improving readability for grouped data. v1.0.x expands merging options beyond v0.0.5’s horizontal merging. + +**Old (v0.0.5):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewWriter(os.Stdout) + // table.SetAutoMergeCells(true) // Enable horizontal merging + table.SetHeader([]string{"Category", "Item", "Notes"}) + table.Append([]string{"Fruit", "Apple", "Red"}) + table.Append([]string{"Fruit", "Apple", "Green"}) // "Apple" might merge if SetAutoMergeCells was on + table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Horizontal Merging (Similar to v0.0.5) + tableH := tablewriter.NewTable(os.Stdout, + tablewriter.WithConfig(tablewriter.Config{Row: tw.CellConfig{Formatting: tw.CellFormatting{MergeMode: tw.MergeHorizontal}}}), + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{Symbols: tw.NewSymbols(tw.StyleASCII)})), // Specify renderer for symbols + ) + tableH.Header("Category", "Item", "Item", "Notes") // Note: Two "Item" headers for demo + tableH.Append("Fruit", "Apple", "Apple", "Red") // "Apple" cells merge + tableH.Render() + + // Vertical Merging + tableV := tablewriter.NewTable(os.Stdout, + tablewriter.WithConfig(tablewriter.Config{Row: tw.CellConfig{Formatting: tw.CellFormatting{MergeMode: tw.MergeVertical}}}), + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{Symbols: tw.NewSymbols(tw.StyleASCII)})), + ) + tableV.Header("User", "Permission") + tableV.Append("Alice", "Read") + tableV.Append("Alice", "Write") // "Alice" cells merge vertically + tableV.Append("Bob", "Read") + tableV.Render() + + // Hierarchical Merging + tableHier := tablewriter.NewTable(os.Stdout, + tablewriter.WithConfig(tablewriter.Config{Row: tw.CellConfig{Formatting: tw.CellFormatting{MergeMode: tw.MergeHierarchical}}}), + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{Symbols: tw.NewSymbols(tw.StyleASCII)})), + ) + tableHier.Header("Group", "SubGroup", "Item") + tableHier.Append("Tech", "CPU", "i7") + tableHier.Append("Tech", "CPU", "i9") // "Tech" and "CPU" merge + tableHier.Append("Tech", "RAM", "16GB") // "Tech" merges, "RAM" is new + tableHier.Append("Office", "CPU", "i5") // "Office" is new + tableHier.Render() +} +``` + +**Output (Horizontal):** +``` ++----------+-------+-------+-------+ +| CATEGORY | ITEM | ITEM | NOTES | ++----------+-------+-------+-------+ +| Fruit | Apple | Red | ++----------+---------------+-------+ +``` + +**Output (Vertical):** +``` ++-------+------------+ +| USER | PERMISSION | ++-------+------------+ +| Alice | Read | +| | Write | ++-------+------------+ +| Bob | Read | ++-------+------------+ +``` + +**Output (Hierarchical):** +``` ++---------+----------+------+ +| GROUP | SUBGROUP | ITEM | ++---------+----------+------+ +| Tech | CPU | i7 | +| | | i9 | +| +----------+------+ +| | RAM | 16GB | ++---------+----------+------+ +| Office | CPU | i5 | ++---------+----------+------+ +``` + +**Key Changes**: +- **Method**: `SetAutoMergeCells` is replaced by `WithRowMergeMode(int_merge_mode)` or `Config.Row.Formatting.MergeMode` (`config.go`). Uses `tw.Merge...` constants. +- **Merge Modes**: `tw.MergeMode` constants (`tw.MergeNone`, `tw.MergeHorizontal`, `tw.MergeVertical`, `tw.MergeHierarchical`) define behavior (`tw/tw.go`). +- **Section-Specific**: Merging can be applied to `Header`, `Row`, or `Footer` via `Config.
.Formatting.MergeMode` (`tw/cell.go`). +- **Processing**: Merging is handled during content preparation (`zoo.go:prepareWithMerges`, `zoo.go:applyVerticalMerges`, `zoo.go:applyHierarchicalMerges`). +- **Width Adjustment**: Horizontal merging adjusts column widths (`zoo.go:applyHorizontalMergeWidths`). +- **Renderer Support**: `tw.MergeState` in `tw.CellContext` ensures correct border drawing for merged cells (`tw/cell.go:CellContext`). +- **Streaming Limitation**: Streaming mode supports only simple horizontal merging due to fixed widths (`stream.go:streamAppendRow`). + +**Migration Tips**: +- Replace `SetAutoMergeCells(true)` with `WithRowMergeMode(tw.MergeHorizontal)` to maintain v0.0.5’s horizontal merging behavior (`config.go`). +- Use `tw.MergeVertical` for vertical grouping (e.g., repeated user names) or `tw.MergeHierarchical` for nested data structures (`tw/tw.go`). +- Apply merging to specific sections via `ConfigBuilder.
().Formatting().WithMergeMode(int_merge_mode)` (`config.go`). +- Test merging with sample data to verify visual output, especially for hierarchical merging with complex datasets. +- In streaming mode, ensure `Config.Widths` supports merged cell widths to avoid truncation (`stream.go`). +- Use `WithDebug(true)` to log merge processing for troubleshooting (`config.go`). + +**Potential Pitfalls**: +- **Streaming Restrictions**: Vertical and hierarchical merging are unsupported in streaming mode; use batch mode for these features (`stream.go`). +- **Width Misalignment**: Merged cells may require wider columns; adjust `Config.Widths` or `ColMaxWidths` (`zoo.go`). +- **Data Dependency**: Merging requires identical content; case or whitespace differences prevent merging (`zoo.go`). +- **Renderer Errors**: Incorrect `tw.MergeState` handling in custom renderers can break merged cell borders; test thoroughly (`tw/cell.go`). +- **Performance**: Hierarchical merging with large datasets may slow rendering; optimize data or limit merging (`zoo.go`). + +### 6. Table Captions +Captions add descriptive text above or below the table, a new feature in v1.0.x not present in v0.0.5. + +**Old (v0.0.5):** +```go +package main +// No direct caption support in v0.0.5. Users might have printed text manually. +// import "github.com/olekukonko/tablewriter" +// import "os" +// import "fmt" + +func main() { + // fmt.Println("Movie ratings.") // Manual caption + // table := tablewriter.NewWriter(os.Stdout) + // table.SetHeader([]string{"Name", "Sign", "Rating"}) + // table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Caption(tw.Caption{ // tw/types.go:Caption + Text: "System Status Overview - A Very Long Caption Example To Demonstrate Wrapping Behavior", + Spot: tw.SpotTopCenter, // Placement: TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight + Align: tw.AlignCenter, // Text alignment within caption width + Width: 30, // Fixed width for caption text wrapping; if 0, wraps to table width + }) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Append("SuperLongNodeNameHere", "ActiveNow") + table.Render() +} +``` + +**Output:** +``` + System Status Overview - A Very +Long Caption Example To Demonst… +┌─────────────────────┬──────────┐ +│ NAME │ STATUS │ +├─────────────────────┼──────────┤ +│ Node1 │ Ready │ +│ SuperLongNodeNameHe │ ActiveNo │ +│ re │ w │ +└─────────────────────┴──────────┘ +``` + +**Key Changes**: +- **New Feature**: `Table.Caption(tw.Caption)` introduces captions, absent in v0.0.5 (`tablewriter.go:Caption`). +- **Configuration**: `tw.Caption` (`tw/types.go:Caption`) includes: + - `Text`: Caption content. + - `Spot`: Placement (`tw.SpotTopLeft`, `tw.SpotBottomCenter`, etc.); defaults to `tw.SpotBottomCenter` if `tw.SpotNone`. + - `Align`: Text alignment (`tw.AlignLeft`, `tw.AlignCenter`, `tw.AlignRight`). + - `Width`: Optional fixed width for wrapping; defaults to table width. +- **Rendering**: Captions are rendered by `printTopBottomCaption` before or after the table based on `Spot` (`tablewriter.go:printTopBottomCaption`). +- **Streaming**: Captions are rendered during `Close()` in streaming mode if placed at the bottom (`stream.go`). + +**Migration Tips**: +- Add captions to enhance table context, especially for reports or documentation (`tw/types.go`). +- Use `tw.SpotTopCenter` for prominent placement above the table, aligning with common report formats. +- Set `Align` to match table aesthetics (e.g., `tw.AlignCenter` for balanced appearance). +- Specify `Width` for consistent wrapping, especially with long captions or narrow tables (`tablewriter.go`). +- Test caption placement and alignment with different table sizes to ensure readability. + +**Potential Pitfalls**: +- **Spot Default**: If `Spot` is `tw.SpotNone`, caption defaults to `tw.SpotBottomCenter`, which may surprise users expecting no caption (`tablewriter.go`). +- **Width Overflow**: Without `Width`, captions wrap to table width, potentially causing misalignment; set explicitly for control (`tw/types.go`). +- **Streaming Delay**: Bottom-placed captions in streaming mode appear only at `Close()`; ensure `Close()` is called (`stream.go`). +- **Alignment Confusion**: Caption `Align` is independent of table cell alignment; verify separately (`tw/cell.go`). + +### 7. Filters +Filters allow dynamic transformation of cell content during rendering, a new feature in v1.0.x for tasks like formatting, coloring, or sanitizing data. + +**Old (v0.0.5):** +```go +package main +// No direct support for cell content transformation in v0.0.5. +// Users would typically preprocess data before appending. +// import "github.com/olekukonko/tablewriter" +// import "os" +// import "strings" + +func main() { + // table := tablewriter.NewWriter(os.Stdout) + // table.SetHeader([]string{"Name", "Status"}) + // status := " Ready " + // preprocessedStatus := "Status: " + strings.TrimSpace(status) + // table.Append([]string{"Node1", preprocessedStatus}) + // table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.CellConfig etc. + "os" + "strings" +) + +func main() { + // Per-Column Filter for Specific Transformations + cfgBuilder := tablewriter.NewConfigBuilder() + cfgBuilder.Row().Filter().WithPerColumn([]func(string) string{ + nil, // No filter for Name column + func(s string) string { // Status column: prefix and trim + return "Status: " + strings.TrimSpace(s) + }, + }) + + tableWithFilter := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) + tableWithFilter.Header("Name", "Status") + tableWithFilter.Append("Node1", " Ready ") // Note the extra spaces + tableWithFilter.Append("Node2", "Pending") + tableWithFilter.Render() + + // Global filter example (applied to all cells in the Row section) + cfgGlobalFilter := tablewriter.NewConfigBuilder() + cfgGlobalFilter.Row().Filter().WithGlobal(func(s string) string { + return "[" + s + "]" // Wrap all row cells in brackets + }) + tableGlobalFilter := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgGlobalFilter.Build())) + tableGlobalFilter.Header("Item", "Count") + tableGlobalFilter.Append("Apple", "5") + tableGlobalFilter.Render() +} +``` + +**Output (Per-Column Filter):** +``` +┌───────┬─────────────────┐ +│ NAME │ STATUS │ +├───────┼─────────────────┤ +│ Node1 │ Status: Ready │ +│ Node2 │ Status: Pending │ +└───────┴─────────────────┘ +``` + +**Output (Global Filter):** +``` +┌───────┬─────────┐ +│ ITEM │ COUNT │ +├───────┼─────────┤ +│[Apple]│ [5] │ +└───────┴─────────┘ +``` + +**Key Changes**: +- **New Feature**: `tw.CellFilter` (`tw/cell.go:CellFilter`) introduces: + - `Global`: A `func(s []string) []string` applied to entire rows (all cells in that row) of a section. + - `PerColumn`: A slice of `func(string) string` for column-specific transformations on individual cells. +- **Configuration**: Set via `Config.
.Filter` (`Header`, `Row`, `Footer`) using `ConfigBuilder` or direct `Config` (`config.go`). +- **Processing**: Filters are applied during content preparation, after `AutoFormat` but before rendering (`zoo.go:convertCellsToStrings` calls `prepareContent` which applies some transformations, filters are applied in `convertCellsToStrings` itself). +- **Use Cases**: Formatting (e.g., uppercase, prefixes), coloring (via ANSI codes), sanitization (e.g., removing sensitive data), or data normalization. + +**Migration Tips**: +- Use filters to replace manual content preprocessing in v0.0.5 (e.g., string manipulation before `Append`). +- Apply `Global` filters for uniform transformations across all cells of rows in a section (e.g., uppercasing all row data) (`tw/cell.go`). +- Use `PerColumn` filters for column-specific formatting (e.g., adding prefixes to status columns) (`config.go`). +- Combine filters with `tw.Formatter` for complex types or ANSI coloring for visual enhancements (`tw/cell.go`). +- Test filters with diverse inputs to ensure transformations preserve data integrity (`zoo.go`). + +**Potential Pitfalls**: +- **Filter Order**: Filters apply before some other transformations like padding and alignment; combining can lead to interactions. +- **Performance**: Complex filters on large datasets may slow rendering; optimize logic (`zoo.go`). +- **Nil Filters**: Unset filters (`nil`) are ignored, but incorrect indexing in `PerColumn` can skip columns (`tw/cell.go`). +- **Streaming Consistency**: Filters must be consistent in streaming mode, as widths are fixed at `Start()` (`stream.go`). + +### 8. Stringers and Caching +Stringers allow custom string conversion for data types, with v1.0.x adding caching for performance. + +**Old (v0.0.5):** +```go +package main +// v0.0.5 primarily relied on fmt.Stringer for custom types. +// import "fmt" +// import "github.com/olekukonko/tablewriter" +// import "os" + +// type MyCustomType struct { +// Value string +// } +// func (m MyCustomType) String() string { return "Formatted: " + m.Value } + +func main() { + // table := tablewriter.NewWriter(os.Stdout) + // table.SetHeader([]string{"Custom Data"}) + // table.Append([]string{MyCustomType{"test"}.String()}) // Manual call to String() + // table.Render() +} +``` + +**New (v1.0.x):** +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.Formatter + "os" + "strings" // For Person example +) + +// Example 1: Using WithStringer for general conversion +type CustomInt int + +func main() { + // Table with a general stringer (func(any) []string) + tableWithStringer := tablewriter.NewTable(os.Stdout, + tablewriter.WithStringer(func(v any) []string { // Must return []string + if ci, ok := v.(CustomInt); ok { + return []string{fmt.Sprintf("CustomInt Value: %d!", ci)} + } + return []string{fmt.Sprintf("Value: %v", v)} // Fallback + }), + tablewriter.WithDebug(true), // Enable caching if WithStringerCache() is also used + // tablewriter.WithStringerCache(), // Optional: enable caching + ) + tableWithStringer.Header("Data") + tableWithStringer.Append(123) + tableWithStringer.Append(CustomInt(456)) + tableWithStringer.Render() + + fmt.Println("\n--- Table with Type-Specific Stringer for Structs ---") + + // Example 2: Stringer for a specific struct type + type Person struct { + ID int + Name string + City string + } + + // Stringer for Person to produce 3 cells + personToStrings := func(p Person) []string { + return []string{ + fmt.Sprintf("ID: %d", p.ID), + p.Name, + strings.ToUpper(p.City), + } + } + + tablePersonStringer := tablewriter.NewTable(os.Stdout, + tablewriter.WithStringer(personToStrings), // Pass the type-specific function + ) + tablePersonStringer.Header("User ID", "Full Name", "Location") + tablePersonStringer.Append(Person{1, "Alice", "New York"}) + tablePersonStringer.Append(Person{2, "Bob", "London"}) + tablePersonStringer.Render() + + fmt.Println("\n--- Table with tw.Formatter ---") + // Example 3: Using tw.Formatter for types + type Product struct { + Name string + Price float64 + } + func (p Product) Format() string { // Implements tw.Formatter + return fmt.Sprintf("%s - $%.2f", p.Name, p.Price) + } + tableFormatter := tablewriter.NewTable(os.Stdout) + tableFormatter.Header("Product Details") + tableFormatter.Append(Product{"Laptop", 1200.99}) // Will use Format() + tableFormatter.Render() +} +``` + +**Output (Stringer Examples):** +``` +┌─────────────────────┐ +│ DATA │ +├─────────────────────┤ +│ Value: 123 │ +│ CustomInt Value: 456! │ +└─────────────────────┘ + +--- Table with Type-Specific Stringer for Structs --- +┌─────────┬───────────┬──────────┐ +│ USER ID │ FULL NAME │ LOCATION │ +├─────────┼───────────┼──────────┤ +│ ID: 1 │ Alice │ NEW YORK │ +│ ID: 2 │ Bob │ LONDON │ +└─────────┴───────────┴──────────┘ + +--- Table with tw.Formatter --- +┌─────────────────┐ +│ PRODUCT DETAILS │ +├─────────────────┤ +│ Laptop - $1200… │ +└─────────────────┘ +``` + +**Key Changes**: +- **Stringer Support**: `WithStringer(fn any)` sets a table-wide string conversion function. This function must have a signature like `func(SomeType) []string` or `func(any) []string`. It's used to convert an input item (e.g., a struct) into a slice of strings, where each string is a cell for the row (`tablewriter.go:WithStringer`). +- **Caching**: `WithStringerCache()` enables caching for the function provided via `WithStringer`, improving performance for repeated conversions of the same input type (`tablewriter.go:WithStringerCache`). +- **Formatter**: `tw.Formatter` interface (`Format() string`) allows types to define their own single-string representation for a cell. This is checked before `fmt.Stringer` (`tw/types.go:Formatter`). +- **Priority**: When converting an item to cell(s): + 1. `WithStringer` (if provided and compatible with the item's type). + 2. If not handled by `WithStringer`, or if `WithStringer` is not set: + * If the item is a struct that does *not* implement `tw.Formatter` or `fmt.Stringer`, its exported fields are reflected into multiple cells. + * If the item (or struct) implements `tw.Formatter` (`Format() string`), that's used for a single cell. + * Else, if it implements `fmt.Stringer` (`String() string`), that's used for a single cell. + * Else, default `fmt.Sprintf("%v", ...)` for a single cell. + (`zoo.go:convertCellsToStrings`, `zoo.go:convertItemToCells`) + +**Migration Tips**: +- For types that should produce a single cell with custom formatting, implement `tw.Formatter`. +- For types (especially structs) that should be expanded into multiple cells with custom logic, use `WithStringer` with a function like `func(MyType) []string`. +- If you have a general way to convert *any* type into a set of cells, use `WithStringer(func(any) []string)`. +- Enable `WithStringerCache` for large datasets with repetitive data types if using `WithStringer`. +- Test stringer/formatter output to ensure formatting meets expectations (`zoo.go`). + +**Potential Pitfalls**: +- **Cache Overhead**: `WithStringerCache` may increase memory usage for diverse data; disable for small tables or if not using `WithStringer` (`tablewriter.go`). +- **Stringer Signature**: The function passed to `WithStringer` *must* return `[]string`. A function returning `string` will lead to a warning and fallback behavior. +- **Formatter vs. Stringer Priority**: Be aware of the conversion priority if your types implement multiple interfaces or if you also use `WithStringer`. +- **Streaming**: Stringers/Formatters must produce consistent cell counts in streaming mode to maintain width alignment (`stream.go`). + +## Examples + +This section provides practical examples to demonstrate v1.0.x features, covering common and advanced use cases to aid migration. Each example includes code, output, and notes to illustrate functionality. + +### Example: Minimal Setup +A basic table with default settings, ideal for quick setups. + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Render() +} +``` + +**Output**: +``` +┌───────┬────────┐ +│ NAME │ STATUS │ +├───────┼────────┤ +│ Node1 │ Ready │ +└───────┴────────┘ +``` + +**Notes**: +- Uses default `renderer.NewBlueprint()` and `defaultConfig()` settings (`tablewriter.go`, `config.go`). +- `Header: tw.AlignCenter`, `Row: tw.AlignLeft` (`config.go:defaultConfig`). +- Simple replacement for v0.0.5’s `NewWriter` and `SetHeader`/`Append`. + +### Example: Streaming with Fixed Widths +Demonstrates streaming mode for real-time data output. + +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "log" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithStreaming(tw.StreamConfig{Enable: true}), + tablewriter.WithColumnMax(10), // Sets Config.Widths.Global + ) + if err := table.Start(); err != nil { + log.Fatalf("Start failed: %v", err) + } + table.Header("Name", "Status") + for i := 0; i < 2; i++ { + err := table.Append(fmt.Sprintf("Node%d", i+1), "Ready") + if err != nil { + log.Printf("Append failed: %v", err) + } + } + if err := table.Close(); err != nil { + log.Fatalf("Close failed: %v", err) + } +} +``` + +**Output**: +``` +┌──────────┬──────────┐ +│ NAME │ STATUS │ +├──────────┼──────────┤ +│ Node1 │ Ready │ +│ Node2 │ Ready │ +└──────────┴──────────┘ +``` + +**Notes**: +- Streaming requires `Start()` and `Close()`; `Config.Widths` (here set via `WithColumnMax`) fixes widths (`stream.go`). +- Replaces v0.0.5’s batch rendering for real-time use cases. +- Ensure error handling for `Start()`, `Append()`, and `Close()`. + +### Example: Markdown-Style Table +Creates a Markdown-compatible table for documentation. + +```go +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" // Import renderer + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + // Example 1: Using Blueprint renderer with Markdown symbols + tableBlueprintMarkdown := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), // Use Blueprint + tablewriter.WithRendition(tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleMarkdown), + Borders: tw.Border{Left: tw.On, Right: tw.On}, // Markdown needs left/right borders + }), + tablewriter.WithRowAlignment(tw.AlignLeft), // Common for Markdown + tablewriter.WithHeaderAlignment(tw.AlignCenter), // Center align headers + ) + tableBlueprintMarkdown.Header("Name", "Status") + tableBlueprintMarkdown.Append("Node1", "Ready") + tableBlueprintMarkdown.Append("Node2", "NotReady") + tableBlueprintMarkdown.Render() + + fmt.Println("\n--- Using dedicated Markdown Renderer (if one exists or is built) ---") + // Example 2: Assuming a dedicated Markdown renderer (hypothetical example) + // If a `renderer.NewMarkdown()` existed that directly outputs GitHub Flavored Markdown table syntax: + /* + tableDedicatedMarkdown := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewMarkdown()), // Hypothetical Markdown renderer + ) + tableDedicatedMarkdown.Header("Name", "Status") + tableDedicatedMarkdown.Append("Node1", "Ready") + tableDedicatedMarkdown.Append("Node2", "NotReady") + tableDedicatedMarkdown.Render() + */ + // Since `renderer.NewMarkdown()` isn't shown in the provided code, + // the first example (Blueprint with StyleMarkdown) is the current viable way. +} +``` + +**Output (Blueprint with StyleMarkdown):** +``` +| NAME | STATUS | +|--------|----------| +| Node1 | Ready | +| Node2 | NotReady | +``` + +**Notes**: +- `StyleMarkdown` ensures compatibility with Markdown parsers (`tw/symbols.go`). +- Left alignment for rows and center for headers is common for Markdown readability (`config.go`). +- Ideal for GitHub READMEs or documentation. +- A dedicated Markdown renderer (like the commented-out example) would typically handle alignment syntax (e.g., `|:---:|:---|`). With `Blueprint` and `StyleMarkdown`, alignment is visual within the text rather than Markdown syntax. + +### Example: ASCII-Style Table +Uses `StyleASCII` for maximum terminal compatibility. + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), + tablewriter.WithRendition(tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleASCII), + }), + tablewriter.WithRowAlignment(tw.AlignLeft), + ) + table.Header("ID", "Value") + table.Append("1", "Test") + table.Render() +} +``` + +**Output**: +``` ++----+-------+ +│ ID │ VALUE │ ++----+-------+ +│ 1 │ Test │ ++----+-------+ +``` + +**Notes**: +- `StyleASCII` is robust for all terminals (`tw/symbols.go`). +- Replaces v0.0.5’s default style with explicit configuration. + + +### Example: Kubectl-Style Output +Creates a borderless, minimal table similar to `kubectl` command output, emphasizing simplicity and readability. + +```go +package main + +import ( + "os" + "sync" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" +) + +var wg sync.WaitGroup + +func main() { + data := [][]any{ + {"node1.example.com", "Ready", "compute", "1.11"}, + {"node2.example.com", "Ready", "compute", "1.11"}, + {"node3.example.com", "Ready", "compute", "1.11"}, + {"node4.example.com", "NotReady", "compute", "1.11"}, + } + + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Borders: tw.BorderNone, + Settings: tw.Settings{ + Separators: tw.SeparatorsNone, + Lines: tw.LinesNone, + }, + })), + tablewriter.WithConfig(tablewriter.Config{ + Header: tw.CellConfig{ + Formatting: tw.CellFormatting{Alignment: tw.AlignLeft}, + }, + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{Alignment: tw.AlignLeft}, + Padding: tw.CellPadding{Global: tw.PaddingNone}, + }, + }), + ) + table.Header("Name", "Status", "Role", "Version") + table.Bulk(data) + table.Render() +} +``` + +**Output:** +``` +NAME STATUS ROLE VERSION +node1.example.com Ready compute 1.21.3 +node2.example.com Ready infra 1.21.3 +node3.example.com NotReady compute 1.20.7 +``` + +**Notes**: +- **Configuration**: Uses `tw.BorderNone`, `tw.LinesNone`, `tw.SeparatorsNone`, `tw.NewSymbols(tw.StyleNone)` and specific padding (`Padding{Right:" "}`) for a minimal, borderless layout. +- **Migration from v0.0.5**: Replaces `SetBorder(false)` and manual spacing with `tw.Rendition` and `Config` settings, achieving a cleaner kubectl-like output. +- **Key Features**: + - Left-aligned text for readability (`config.go`). + - `WithTrimSpace(tw.Off)` preserves spacing (`config.go`). + - `Bulk` efficiently adds multiple rows (`tablewriter.go`). + - Padding `Right: " "` is used to create space between columns as separators are off. +- **Best Practices**: Test in terminals to ensure spacing aligns with command-line aesthetics; use `WithDebug(true)` for layout issues (`config.go`). +- **Potential Issues**: Column widths are content-based. For very long content in one column and short in others, it might not look perfectly aligned like fixed-width CLI tools. `Config.Widths` could be used for more control if needed. + +### Example: Hierarchical Merging +Demonstrates hierarchical cell merging for nested data structures, a new feature in v1.0.x. + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + data := [][]string{ + // Header row is separate + {"table\nwriter", "v0.0.1", "legacy"}, + {"table\nwriter", "v0.0.2", "legacy"}, + {"table\nwriter", "v0.0.2", "legacy"}, // Duplicate for testing merge + {"table\nwriter", "v0.0.2", "legacy"}, // Duplicate for testing merge + {"table\nwriter", "v0.0.5", "legacy"}, + {"table\nwriter", "v1.0.6", "latest"}, + } + + rendition := tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleLight), // Use light for clearer merge lines + Settings: tw.Settings{ + Separators: tw.Separators{BetweenRows: tw.On}, + Lines: tw.Lines{ShowHeaderLine: tw.On, ShowFooterLine: tw.On}, // Show header line + }, + Borders: tw.Border{Left:tw.On, Right:tw.On, Top:tw.On, Bottom:tw.On}, + } + + tableHier := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), + tablewriter.WithRendition(rendition), + tablewriter.WithConfig(tablewriter.Config{ + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{ + MergeMode: tw.MergeHierarchical, + // Alignment: tw.AlignCenter, // Default is Left, often better for hierarchical + AutoWrap: tw.WrapNormal, // Allow wrapping for "table\nwriter" + }, + }, + }), + ) + + tableHier.Header("Package", "Version", "Status") // Header + tableHier.Bulk(data) // Bulk data + tableHier.Render() + + // --- Vertical Merging Example for Contrast --- + tableVert := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), + tablewriter.WithRendition(rendition), // Reuse same rendition + tablewriter.WithConfig(tablewriter.Config{ + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{ + MergeMode: tw.MergeVertical, + AutoWrap: tw.WrapNormal, + }, + }, + }), + ) + tableVert.Header("Package", "Version", "Status") + tableVert.Bulk(data) + tableVert.Render() +} +``` + +**Output (Hierarchical):** +``` +┌─────────┬─────────┬────────┐ +│ PACKAGE │ VERSION │ STATUS │ +├─────────┼─────────┼────────┤ +│ table │ v0.0.1 │ legacy │ +│ writer │ │ │ +│ ├─────────┼────────┤ +│ │ v0.0.2 │ legacy │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ├─────────┼────────┤ +│ │ v0.0.5 │ legacy │ +│ ├─────────┼────────┤ +│ │ v1.0.6 │ latest │ +└─────────┴─────────┴────────┘ +``` +**Output (Vertical):** +``` +┌─────────┬─────────┬────────┐ +│ PACKAGE │ VERSION │ STATUS │ +├─────────┼─────────┼────────┤ +│ table │ v0.0.1 │ legacy │ +│ writer │ │ │ +│ ├─────────┤ │ +│ │ v0.0.2 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ├─────────┤ │ +│ │ v0.0.5 │ │ +│ ├─────────┼────────┤ +│ │ v1.0.6 │ latest │ +└─────────┴─────────┴────────┘ +``` + +**Notes**: +- **Configuration**: Uses `tw.MergeHierarchical` to merge cells based on matching values in preceding columns (`tw/tw.go`). +- **Migration from v0.0.5**: Extends `SetAutoMergeCells(true)` (horizontal only) with hierarchical merging for complex data (`tablewriter.go`). +- **Key Features**: + - `StyleLight` for clear visuals (`tw/symbols.go`). + - `Bulk` for efficient data loading (`tablewriter.go`). +- **Best Practices**: Test merging with nested data; use batch mode, as streaming doesn’t support hierarchical merging (`stream.go`). +- **Potential Issues**: Ensure data is sorted appropriately for hierarchical merging to work as expected; mismatches prevent merging (`zoo.go`). `AutoWrap: tw.WrapNormal` helps with multi-line cell content like "table\nwriter". + +### Example: Colorized Table +Applies ANSI colors to highlight status values, replacing v0.0.5’s `SetColumnColor`. + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" // For tw.State, tw.CellConfig etc. + "os" +) + +func main() { + const ( + FgGreen = "\033[32m" + FgRed = "\033[31m" + Reset = "\033[0m" + ) + + cfgBuilder := tablewriter.NewConfigBuilder() + cfgBuilder.Row().Filter().WithPerColumn([]func(string) string{ + nil, // No filter for Name + func(s string) string { // Color Status + if s == "Ready" { + return FgGreen + s + Reset + } + return FgRed + s + Reset + }, + }) + + table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) + table.Header("Name", "Status") + table.Append("Node1", "Ready") + table.Append("Node2", "Error") + table.Render() +} +``` + +**Output (Text Approximation, Colors Not Shown):** +``` +┌───────┬────────┐ +│ NAME │ STATUS │ +├───────┼────────┤ +│ Node1 │ Ready │ +│ Node2 │ Error │ +└───────┴────────┘ +``` + +**Notes**: +- **Configuration**: Uses `tw.CellFilter` for per-column coloring, embedding ANSI codes (`tw/cell.go`). +- **Migration from v0.0.5**: Replaces `SetColumnColor` with dynamic filters (`tablewriter.go`). +- **Key Features**: Flexible color application; `twdw.Width` handles ANSI codes correctly (`tw/fn.go`). +- **Best Practices**: Test in ANSI-compatible terminals; use constants for code clarity. +- **Potential Issues**: Non-ANSI terminals may show artifacts; provide fallbacks (`tw/fn.go`). + +### Example: Vertical Merging +Shows vertical cell merging for repeated values in a column. (This example was very similar to the hierarchical one, so I'll ensure it's distinct by using simpler data). + +```go +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint()), // Default renderer + tablewriter.WithRendition(tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleLight), + Settings: tw.Settings{Separators: tw.Separators{BetweenRows: tw.On}}, + Borders: tw.Border{Left:tw.On, Right:tw.On, Top:tw.On, Bottom:tw.On}, + }), + tablewriter.WithConfig( + tablewriter.NewConfigBuilder(). + Row().Formatting().WithMergeMode(tw.MergeVertical).Build(). // Enable Vertical Merge + Build(), + ), + ) + table.Header("User", "Permission", "Target") + table.Append("Alice", "Read", "FileA") + table.Append("Alice", "Write", "FileA") // Alice and FileA will merge vertically + table.Append("Alice", "Read", "FileB") + table.Append("Bob", "Read", "FileA") + table.Append("Bob", "Read", "FileC") // Bob and Read will merge + table.Render() +} +``` + +**Output:** +``` +┌───────┬────────────┬────────┐ +│ USER │ PERMISSION │ TARGET │ +├───────┼────────────┼────────┤ +│ Alice │ Read │ FileA │ +│ │ │ │ +│ ├────────────┤ │ +│ │ Write │ │ +│ ├────────────┼────────┤ +│ │ Read │ FileB │ +├───────┼────────────┼────────┤ +│ Bob │ Read │ FileA │ +│ │ ├────────┤ +│ │ │ FileC │ +└───────┴────────────┴────────┘ +``` + +**Notes**: +- **Configuration**: `tw.MergeVertical` merges identical cells vertically (`tw/tw.go`). +- **Migration from v0.0.5**: Extends `SetAutoMergeCells` with vertical merging (`tablewriter.go`). +- **Key Features**: Enhances grouped data display; requires batch mode (`stream.go`). +- **Best Practices**: Sort data by the columns you intend to merge for best results; test with `StyleLight` for clarity (`tw/symbols.go`). +- **Potential Issues**: Streaming doesn’t support vertical merging; use batch mode (`stream.go`). + +### Example: Custom Renderer (CSV Output) +Implements a custom renderer for CSV output. + +```go +package main + +import ( + "fmt" + "github.com/olekukonko/ll" // For logger type + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "io" + "os" + "strings" // For CSV escaping +) + +// CSVRenderer implements tw.Renderer +type CSVRenderer struct { + writer io.Writer + config tw.Rendition // Store the rendition + logger *ll.Logger + err error +} + +func (r *CSVRenderer) Start(w io.Writer) error { + r.writer = w + return nil // No initial output for CSV typically +} + +func (r *CSVRenderer) escapeCSVCell(data string) string { + // Basic CSV escaping: double quotes if it contains comma, newline, or quote + if strings.ContainsAny(data, ",\"\n") { + return `"` + strings.ReplaceAll(data, `"`, `""`) + `"` + } + return data +} + +func (r *CSVRenderer) writeLine(cells map[int]tw.CellContext, numCols int) { + if r.err != nil { return } + var lineParts []string + // Need to iterate in column order for CSV + keys := make([]int, 0, len(cells)) + for k := range cells { + keys = append(keys, k) + } + // This simple sort works for int keys 0,1,2... + // For more complex scenarios, a proper sort might be needed if keys aren't sequential. + for i := 0; i < numCols; i++ { // Assume numCols reflects the intended max columns + if cellCtx, ok := cells[i]; ok { + lineParts = append(lineParts, r.escapeCSVCell(cellCtx.Data)) + } else { + lineParts = append(lineParts, "") // Empty cell if not present + } + } + _, r.err = r.writer.Write([]byte(strings.Join(lineParts, ",") + "\n")) +} + + +func (r *CSVRenderer) Header(headers [][]string, ctx tw.Formatting) { + // For CSV, usually only the first line of headers is relevant + // The ctx.Row.Current will contain the cells for the first line of the header being processed + r.writeLine(ctx.Row.Current, len(ctx.Row.Current)) +} + +func (r *CSVRenderer) Row(row []string, ctx tw.Formatting) { + // ctx.Row.Current contains the cells for the current row line + r.writeLine(ctx.Row.Current, len(ctx.Row.Current)) +} + +func (r *CSVRenderer) Footer(footers [][]string, ctx tw.Formatting) { + // Similar to Header/Row, using ctx.Row.Current for the footer line data + r.writeLine(ctx.Row.Current, len(ctx.Row.Current)) +} + +func (r *CSVRenderer) Line(ctx tw.Formatting) { /* No separator lines in CSV */ } + +func (r *CSVRenderer) Close() error { return r.err } + +func (r *CSVRenderer) Config() tw.Rendition { return r.config } +func (r *CSVRenderer) Logger(logger *ll.Logger) { r.logger = logger } + +func main() { + table := tablewriter.NewTable(os.Stdout, tablewriter.WithRenderer(&CSVRenderer{ + // config can be minimal for CSV as symbols/borders aren't used + config: tw.Rendition{}, + })) + table.Header("Name", "Status", "Notes, with comma") + table.Append("Node1", "Ready", "All systems \"go\"!") + table.Append("Node2", "Error", "Needs\nattention") + table.Footer("Summary", "2 Nodes", "Check logs") + table.Render() +} +``` + +**Output:** +```csv +Name,Status,"Notes, with comma" +Node1,Ready,"All systems ""go""!" +Node2,Error,"Needs +attention" +Summary,2 Nodes,Check logs +``` + +**Notes**: +- **Configuration**: Custom `CSVRenderer` implements `tw.Renderer` for CSV output (`tw/renderer.go`). +- **Migration from v0.0.5**: Extends v0.0.5’s text-only output with custom formats (`tablewriter.go`). +- **Key Features**: Handles basic CSV cell escaping; supports streaming if `Append` is called multiple times. `ctx.Row.Current` (map[int]tw.CellContext) is used to access cell data. +- **Best Practices**: Test with complex data (e.g., commas, quotes, newlines); implement all renderer methods. A more robust CSV renderer would use the `encoding/csv` package. +- **Potential Issues**: Custom renderers require careful error handling and correct interpretation of `tw.Formatting` and `tw.RowContext`. This example's `writeLine` assumes columns are 0-indexed and contiguous for simplicity. + +## Troubleshooting and Common Pitfalls + +This section addresses common migration issues with detailed solutions, covering 30+ scenarios to reduce support tickets. + +| Issue | Cause/Solution | +|-------------------------------------------|-------------------------------------------------------------------------------| +| No output from `Render()` | **Cause**: Missing `Start()`/`Close()` in streaming mode or invalid `io.Writer`. **Solution**: Ensure `Start()` and `Close()` are called in streaming; verify `io.Writer` (`stream.go`). | +| Incorrect column widths | **Cause**: Missing `Config.Widths` in streaming or content-based sizing. **Solution**: Set `Config.Widths` before `Start()`; use `WithColumnMax` (`stream.go`). | +| Merging not working | **Cause**: Streaming mode or mismatched data. **Solution**: Use batch mode for vertical/hierarchical merging; ensure identical content (`zoo.go`). | +| Alignment ignored | **Cause**: `PerColumn` overrides `Global`. **Solution**: Check `Config.Section.Alignment.PerColumn` settings or `ConfigBuilder` calls (`tw/cell.go`). | +| Padding affects widths | **Cause**: Padding included in `Config.Widths`. **Solution**: Adjust `Config.Widths` to account for `tw.CellPadding` (`zoo.go`). | +| Colors not rendering | **Cause**: Non-ANSI terminal or incorrect codes. **Solution**: Test in ANSI-compatible terminal; use `twdw.Width` (`tw/fn.go`). | +| Caption missing | **Cause**: `Close()` not called in streaming or incorrect `Spot`. **Solution**: Ensure `Close()`; verify `tw.Caption.Spot` (`tablewriter.go`). | +| Filters not applied | **Cause**: Incorrect `PerColumn` indexing or nil filters. **Solution**: Set filters correctly; test with sample data (`tw/cell.go`). | +| Stringer cache overhead | **Cause**: Large datasets with diverse types. **Solution**: Disable `WithStringerCache` for small tables if not using `WithStringer` or if types vary greatly (`tablewriter.go`). | +| Deprecated methods used | **Cause**: Using `WithBorders`, old `tablewriter.Behavior` constants. **Solution**: Migrate to `WithRendition`, `tw.Behavior` struct (`tablewriter.go`, `deprecated.go`). | +| Streaming footer missing | **Cause**: `Close()` not called. **Solution**: Always call `Close()` (`stream.go`). | +| Hierarchical merging fails | **Cause**: Unsorted data or streaming mode. **Solution**: Sort data; use batch mode (`zoo.go`). | +| Custom renderer errors | **Cause**: Incomplete method implementation or misinterpreting `tw.Formatting`. **Solution**: Implement all `tw.Renderer` methods; test thoroughly (`tw/renderer.go`). | +| Width overflow | **Cause**: No `MaxWidth` or wide content. **Solution**: Set `Config.MaxWidth` (`config.go`). | +| Truncated content | **Cause**: Narrow `Config.Widths` or `tw.WrapTruncate`. **Solution**: Widen columns or use `tw.WrapNormal` (`zoo.go`). | +| Debug logs absent | **Cause**: `Debug = false`. **Solution**: Enable `WithDebug(true)` (`config.go`). | +| Alignment mismatch across sections | **Cause**: Different defaults. **Solution**: Set uniform alignment options (e.g., via `ConfigBuilder.
.Alignment()`) (`config.go`). | +| ANSI code artifacts | **Cause**: Non-ANSI terminal. **Solution**: Provide non-colored fallback (`tw/fn.go`). | +| Slow rendering | **Cause**: Complex filters or merging. **Solution**: Optimize logic; limit merging (`zoo.go`). | +| Uneven cell counts | **Cause**: Mismatched rows/headers. **Solution**: Pad with `""` (`zoo.go`). | +| Border inconsistencies | **Cause**: Mismatched `Borders`/`Symbols`. **Solution**: Align settings (`tw/renderer.go`). | +| Streaming width issues | **Cause**: No `Config.Widths`. **Solution**: Set before `Start()` (`stream.go`). | +| Formatter ignored | **Cause**: `WithStringer` might take precedence if compatible. **Solution**: Review conversion priority; `tw.Formatter` is high-priority for single-item-to-single-cell conversion (`zoo.go`). | +| Caption misalignment | **Cause**: Incorrect `Width` or `Align`. **Solution**: Set `tw.Caption.Width`/`Align` (`tablewriter.go`). | +| Per-column padding errors | **Cause**: Incorrect indexing in `Padding.PerColumn`. **Solution**: Verify indices (`tw/cell.go`). | +| Vertical merging in streaming | **Cause**: Unsupported. **Solution**: Use batch mode (`stream.go`). | +| Filter performance | **Cause**: Complex logic. **Solution**: Simplify filters (`zoo.go`). | +| Custom symbols incomplete | **Cause**: Missing characters. **Solution**: Define all symbols (`tw/symbols.go`). | +| Table too wide | **Cause**: No `MaxWidth`. **Solution**: Set `Config.MaxWidth` (`config.go`). | +| Streaming errors | **Cause**: Missing `Start()`. **Solution**: Call `Start()` before data input (`stream.go`). | + +## Additional Notes + +- **Performance Optimization**: Enable `WithStringerCache` for repetitive data types when using `WithStringer`; optimize filters and merging for large datasets (`tablewriter.go`, `zoo.go`). +- **Debugging**: Use `WithDebug(true)` and `table.Debug()` to log configuration and rendering details; invaluable for troubleshooting (`config.go`). +- **Testing Resources**: The `tests/` directory contains examples of various configurations. +- **Community Support**: For advanced use cases or issues, consult the source code or open an issue on the `tablewriter` repository. +- **Future Considerations**: Deprecated methods in `deprecated.go` (e.g., `WithBorders`) are slated for removal in future releases; migrate promptly to ensure compatibility. + +This guide aims to cover all migration scenarios comprehensively. For highly specific or advanced use cases, refer to the source files (`config.go`, `tablewriter.go`, `stream.go`, `tw/*`) or engage with the `tablewriter` community for support. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index f06530d7..70480d69 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -1,431 +1,1101 @@ -ASCII Table Writer -========= - -[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) -[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter) -[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter) - -Generate ASCII table on the fly ... Installation is simple as - - go get github.com/olekukonko/tablewriter - - -#### Features -- Automatic Padding -- Support Multiple Lines -- Supports Alignment -- Support Custom Separators -- Automatic Alignment of numbers & percentage -- Write directly to http , file etc via `io.Writer` -- Read directly from CSV file -- Optional row line via `SetRowLine` -- Normalise table header -- Make CSV Headers optional -- Enable or disable table border -- Set custom footer support -- Optional identical cells merging -- Set custom caption -- Optional reflowing of paragraphs in multi-line cells. - -#### Example 1 - Basic +# TableWriter for Go + +[![Go](https://github.com/olekukonko/tablewriter/actions/workflows/go.yml/badge.svg)](https://github.com/olekukonko/tablewriter/actions/workflows/go.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/olekukonko/tablewriter.svg)](https://pkg.go.dev/github.com/olekukonko/tablewriter) +[![Go Report Card](https://goreportcard.com/badge/github.com/olekukonko/tablewriter)](https://goreportcard.com/report/github.com/olekukonko/tablewriter) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Benchmarks](https://img.shields.io/badge/benchmarks-included-success)](README.md#benchmarks) + +`tablewriter` is a Go library for generating **rich text-based tables** with support for multiple output formats, including ASCII, Unicode, Markdown, HTML, and colorized terminals. Perfect for CLI tools, logs, and web applications. + +### Key Features +- **Multi-format rendering**: ASCII, Unicode, Markdown, HTML, ANSI-colored +- **Advanced styling**: Cell merging, alignment, padding, borders +- **Flexible input**: CSV, structs, slices, or streaming data +- **High performance**: Minimal allocations, buffer reuse +- **Modern features**: Generics support, hierarchical merging, real-time streaming + +--- + +### Installation + +#### Legacy Version (v0.0.5) +For use with legacy applications: +```bash +go get github.com/olekukonko/tablewriter@v0.0.5 +``` + +#### Latest Version +The latest stable version +```bash +go get github.com/olekukonko/tablewriter@v1.0.7 +``` + +**Warning:** Version `v1.0.0` contains missing functionality and should not be used. + + +> **Version Guidance** +> - Legacy: Use `v0.0.5` (stable) +> - New Features: Use `@latest` (includes generics, super fast streaming APIs) +> - Legacy Docs: See [README_LEGACY.md](README_LEGACY.md) + +--- + +### Why TableWriter? +- **CLI Ready**: Instant compatibility with terminal outputs +- **Database Friendly**: Native support for `sql.Null*` types +- **Secure**: Auto-escaping for HTML/Markdown +- **Extensible**: Custom renderers and formatters + +--- + +### Quick Example ```go -data := [][]string{ - []string{"A", "The Good", "500"}, - []string{"B", "The Very very Bad Man", "288"}, - []string{"C", "The Ugly", "120"}, - []string{"D", "The Gopher", "800"}, -} +package main + +import ( + "github.com/olekukonko/tablewriter" + "os" +) -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Name", "Sign", "Rating"}) +func main() { + data := [][]string{ + {"Package", "Version", "Status"}, + {"tablewriter", "v0.0.5", "legacy"}, + {"tablewriter", "v1.0.7", "latest"}, + } -for _, v := range data { - table.Append(v) + table := tablewriter.NewWriter(os.Stdout) + table.Header(data[0]) + table.Bulk(data[1:]) + table.Render() } -table.Render() // Send output ``` +**Output**: +``` +┌─────────────┬─────────┬────────┐ +│ PACKAGE │ VERSION │ STATUS │ +├─────────────┼─────────┼────────┤ +│ tablewriter │ v0.0.5 │ legacy │ +│ tablewriter │ v1.0.7 │ latest │ +└─────────────┴─────────┴────────┘ +``` + + +## Detailed Usage + +Create a table with `NewTable` or `NewWriter`, configure it using options or a `Config` struct, add data with `Append` or `Bulk`, and render to an `io.Writer`. Use renderers like `Blueprint` (ASCII), `HTML`, `Markdown`, `Colorized`, or `Ocean` (streaming). + +Here's how the API primitives map to the generated ASCII table: -##### Output 1 ``` -+------+-----------------------+--------+ -| NAME | SIGN | RATING | -+------+-----------------------+--------+ -| A | The Good | 500 | -| B | The Very very Bad Man | 288 | -| C | The Ugly | 120 | -| D | The Gopher | 800 | -+------+-----------------------+--------+ +API Call ASCII Table Component +-------- --------------------- + +table.Header([]string{"NAME", "AGE"}) ┌──────┬─────┐ ← Borders.Top + │ NAME │ AGE │ ← Header row + ├──────┼─────┤ ← Lines.ShowTop (header separator) + +table.Append([]string{"Alice", "25"}) │ Alice│ 25 │ ← Data row + ├──────┼─────┤ ← Separators.BetweenRows + +table.Append([]string{"Bob", "30"}) │ Bob │ 30 │ ← Data row + ├──────┼─────┤ ← Lines.ShowBottom (footer separator) + +table.Footer([]string{"Total", "2"}) │ Total│ 2 │ ← Footer row + └──────┴─────┘ ← Borders.Bottom ``` -#### Example 2 - Without Border / Footer / Bulk Append +The core components include: + +- **Renderer** - Implements the core interface for converting table data into output formats. Available renderers include Blueprint (ASCII), HTML, Markdown, Colorized (ASCII with color), Ocean (streaming ASCII), and SVG. + +- **Config** - The root configuration struct that controls all table behavior and appearance + - **Behavior** - Controls high-level rendering behaviors including auto-hiding empty columns, trimming row whitespace, header/footer visibility, and compact mode for optimized merged cell calculations + - **CellConfig** - The comprehensive configuration template used for table sections (header, row, footer). Combines formatting, padding, alignment, filtering, callbacks, and width constraints with global and per-column control + - **StreamConfig** - Configuration for streaming mode including enable/disable state and strict column validation + +- **Rendition** - Defines how a renderer formats tables and contains the complete visual styling configuration + - **Borders** - Control the outer frame visibility (top, bottom, left, right edges) of the table + - **Lines** - Control horizontal boundary lines (above/below headers, above footers) that separate different table sections + - **Separators** - Control the visibility of separators between rows and between columns within the table content + - **Symbols** - Define the characters used for drawing table borders, corners, and junctions + +These components can be configured with various `tablewriter.With*()` functional options when creating a new table. + +## Examples + +### Basic Examples + +#### 1. Simple Tables + +Create a basic table with headers and rows. + + +##### default + ```go -data := [][]string{ - []string{"1/1/2014", "Domain name", "2233", "$10.98"}, - []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, - []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, - []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "os" +) + +type Age int + +func (a Age) String() string { + return fmt.Sprintf("%d yrs", a) } -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) -table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer -table.SetBorder(false) // Set Border to false -table.AppendBulk(data) // Add Bulk Data -table.Render() -``` +func main() { + data := [][]any{ + {"Alice", Age(25), "New York"}, + {"Bob", Age(30), "Boston"}, + } -##### Output 2 + table := tablewriter.NewTable(os.Stdout) + table.Header("Name", "Age", "City") + table.Bulk(data) + table.Render() +} ``` - DATE | DESCRIPTION | CV2 | AMOUNT ------------+--------------------------+-------+---------- - 1/1/2014 | Domain name | 2233 | $10.98 - 1/1/2014 | January Hosting | 2233 | $54.95 - 1/4/2014 | February Hosting | 2233 | $51.00 - 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 ------------+--------------------------+-------+---------- - TOTAL | $146 93 - --------+---------- +**Output**: ``` +┌───────┬────────┬──────────┐ +│ NAME │ AGE │ CITY │ +├───────┼────────┼──────────┤ +│ Alice │ 25 yrs │ New York │ +│ Bob │ 30 yrs │ Boston │ +└───────┴────────┴──────────┘ + +``` + + +##### with customization -#### Example 3 - CSV ```go -table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test_info.csv", true) -table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment -table.Render() +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +type Age int + +func (a Age) String() string { + return fmt.Sprintf("%d yrs", a) +} + +func main() { + data := [][]any{ + {"Alice", Age(25), "New York"}, + {"Bob", Age(30), "Boston"}, + } + + symbols := tw.NewSymbolCustom("Nature"). + WithRow("~"). + WithColumn("|"). + WithTopLeft("🌱"). + WithTopMid("🌿"). + WithTopRight("🌱"). + WithMidLeft("🍃"). + WithCenter("❀"). + WithMidRight("🍃"). + WithBottomLeft("🌻"). + WithBottomMid("🌾"). + WithBottomRight("🌻") + + table := tablewriter.NewTable(os.Stdout, tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{Symbols: symbols}))) + table.Header("Name", "Age", "City") + table.Bulk(data) + table.Render() +} ``` -##### Output 3 ``` -+----------+--------------+------+-----+---------+----------------+ -| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | -+----------+--------------+------+-----+---------+----------------+ -| user_id | smallint(5) | NO | PRI | NULL | auto_increment | -| username | varchar(10) | NO | | NULL | | -| password | varchar(100) | NO | | NULL | | -+----------+--------------+------+-----+---------+----------------+ +🌱~~~~~~❀~~~~~~~~❀~~~~~~~~~🌱 +| NAME | AGE | CITY | +🍃~~~~~~❀~~~~~~~~❀~~~~~~~~~🍃 +| Alice | 25 yrs | New York | +| Bob | 30 yrs | Boston | +🌻~~~~~~❀~~~~~~~~❀~~~~~~~~~🌻 ``` -#### Example 4 - Custom Separator +See [symbols example](https://github.com/olekukonko/tablewriter/blob/master/_example/symbols/main.go) for more + +#### 2. Markdown Table + +Generate a Markdown table for documentation. + ```go -table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test.csv", true) -table.SetRowLine(true) // Enable row line +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "os" + "strings" + "unicode" +) + +type Name struct { + First string + Last string +} + +// this will be ignored since Format() is present +func (n Name) String() string { + return fmt.Sprintf("%s %s", n.First, n.Last) +} + +// Note: Format() overrides String() if both exist. +func (n Name) Format() string { + return fmt.Sprintf("%s %s", n.clean(n.First), n.clean(n.Last)) +} + +// clean ensures the first letter is capitalized and the rest are lowercase +func (n Name) clean(s string) string { + s = strings.TrimSpace(strings.ToLower(s)) + words := strings.Fields(s) + s = strings.Join(words, "") + + if s == "" { + return s + } + // Capitalize the first letter + runes := []rune(s) + runes[0] = unicode.ToUpper(runes[0]) + return string(runes) +} + +type Age int + +// Age int will be ignore and string will be used +func (a Age) String() string { + return fmt.Sprintf("%d yrs", a) +} + +func main() { + data := [][]any{ + {Name{"Al i CE", " Ma SK"}, Age(25), "New York"}, + {Name{"bOb", "mar le y"}, Age(30), "Boston"}, + } -// Change table lines -table.SetCenterSeparator("*") -table.SetColumnSeparator("╪") -table.SetRowSeparator("-") + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewMarkdown()), + ) -table.SetAlignment(tablewriter.ALIGN_LEFT) -table.Render() + table.Header([]string{"Name", "Age", "City"}) + table.Bulk(data) + table.Render() +} ``` -##### Output 4 +**Output**: + ``` -*------------*-----------*---------* -╪ FIRST NAME ╪ LAST NAME ╪ SSN ╪ -*------------*-----------*---------* -╪ John ╪ Barry ╪ 123456 ╪ -*------------*-----------*---------* -╪ Kathy ╪ Smith ╪ 687987 ╪ -*------------*-----------*---------* -╪ Bob ╪ McCornick ╪ 3979870 ╪ -*------------*-----------*---------* +| NAME | AGE | CITY | +|:----------:|:------:|:--------:| +| Alice Mask | 25 yrs | New York | +| Bob Marley | 30 yrs | Boston | + + ``` -#### Example 5 - Markdown Format +#### 3. CSV Input + +Create a table from a CSV file with custom row alignment. + ```go -data := [][]string{ - []string{"1/1/2014", "Domain name", "2233", "$10.98"}, - []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, - []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, - []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, -} +package main -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) -table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) -table.SetCenterSeparator("|") -table.AppendBulk(data) // Add Bulk Data -table.Render() +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "log" + "os" +) + +func main() { + // Assuming "test.csv" contains: "First Name,Last Name,SSN\nJohn,Barry,123456\nKathy,Smith,687987" + table, err := tablewriter.NewCSV(os.Stdout, "test.csv", true) + if err != nil { + log.Fatalf("Error: %v", err) + } + + table.Configure(func(config *tablewriter.Config) { + config.Row.Alignment.Global = tw.AlignLeft + }) + table.Render() +} ``` -##### Output 5 +**Output**: + ``` -| DATE | DESCRIPTION | CV2 | AMOUNT | -|----------|--------------------------|------|--------| -| 1/1/2014 | Domain name | 2233 | $10.98 | -| 1/1/2014 | January Hosting | 2233 | $54.95 | -| 1/4/2014 | February Hosting | 2233 | $51.00 | -| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +┌────────────┬───────────┬─────────┐ +│ FIRST NAME │ LAST NAME │ SSN │ +├────────────┼───────────┼─────────┤ +│ John │ Barry │ 123456 │ +│ Kathy │ Smith │ 687987 │ +└────────────┴───────────┴─────────┘ ``` -#### Example 6 - Identical cells merging +### Advanced Examples + +#### 4. Colorized Table with Long Values + +Create a colorized table with wrapped long values, per-column colors, and a styled footer (inspired by `TestColorizedLongValues` and `TestColorizedCustomColors`). + ```go -data := [][]string{ - []string{"1/1/2014", "Domain name", "1234", "$10.98"}, - []string{"1/1/2014", "January Hosting", "2345", "$54.95"}, - []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, - []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +package main + +import ( + "github.com/fatih/color" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + data := [][]string{ + {"1", "This is a very long description that needs wrapping for readability", "OK"}, + {"2", "Short description", "DONE"}, + {"3", "Another lengthy description requiring truncation or wrapping", "ERROR"}, + } + + // Configure colors: green headers, cyan/magenta rows, yellow footer + colorCfg := renderer.ColorizedConfig{ + Header: renderer.Tint{ + FG: renderer.Colors{color.FgGreen, color.Bold}, // Green bold headers + BG: renderer.Colors{color.BgHiWhite}, + }, + Column: renderer.Tint{ + FG: renderer.Colors{color.FgCyan}, // Default cyan for rows + Columns: []renderer.Tint{ + {FG: renderer.Colors{color.FgMagenta}}, // Magenta for column 0 + {}, // Inherit default (cyan) + {FG: renderer.Colors{color.FgHiRed}}, // High-intensity red for column 2 + }, + }, + Footer: renderer.Tint{ + FG: renderer.Colors{color.FgYellow, color.Bold}, // Yellow bold footer + Columns: []renderer.Tint{ + {}, // Inherit default + {FG: renderer.Colors{color.FgHiYellow}}, // High-intensity yellow for column 1 + {}, // Inherit default + }, + }, + Border: renderer.Tint{FG: renderer.Colors{color.FgWhite}}, // White borders + Separator: renderer.Tint{FG: renderer.Colors{color.FgWhite}}, // White separators + } + + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewColorized(colorCfg)), + tablewriter.WithConfig(tablewriter.Config{ + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{AutoWrap: tw.WrapNormal}, // Wrap long content + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, // Left-align rows + ColMaxWidths: tw.CellWidth{Global: 25}, + }, + Footer: tw.CellConfig{ + Alignment: tw.CellAlignment{Global: tw.AlignRight}, + }, + }), + ) + + table.Header([]string{"ID", "Description", "Status"}) + table.Bulk(data) + table.Footer([]string{"", "Total", "3"}) + table.Render() } +``` + +**Output** (colors visible in ANSI-compatible terminals): + +![Colorized Table with Long Values](_readme/color_1.png "Title") + +#### 5. Streaming Table with Truncation + +Stream a table incrementally with truncation and a footer, simulating a real-time data feed (inspired by `TestOceanStreamTruncation` and `TestOceanStreamSlowOutput`). -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) -table.SetFooter([]string{"", "", "Total", "$146.93"}) -table.SetAutoMergeCells(true) -table.SetRowLine(true) -table.AppendBulk(data) -table.Render() -``` - -##### Output 6 -``` -+----------+--------------------------+-------+---------+ -| DATE | DESCRIPTION | CV2 | AMOUNT | -+----------+--------------------------+-------+---------+ -| 1/1/2014 | Domain name | 1234 | $10.98 | -+ +--------------------------+-------+---------+ -| | January Hosting | 2345 | $54.95 | -+----------+--------------------------+-------+---------+ -| 1/4/2014 | February Hosting | 3456 | $51.00 | -+ +--------------------------+-------+---------+ -| | February Extra Bandwidth | 4567 | $30.00 | -+----------+--------------------------+-------+---------+ -| TOTAL | $146 93 | -+----------+--------------------------+-------+---------+ -``` - -#### Example 7 - Identical cells merging (specify the column index to merge) ```go -data := [][]string{ - []string{"1/1/2014", "Domain name", "1234", "$10.98"}, - []string{"1/1/2014", "January Hosting", "1234", "$10.98"}, - []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, - []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, -} +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "log" + "os" + "time" +) -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) -table.SetFooter([]string{"", "", "Total", "$146.93"}) -table.SetAutoMergeCellsByColumnIndex([]int{2, 3}) -table.SetRowLine(true) -table.AppendBulk(data) -table.Render() +func main() { + table := tablewriter.NewTable(os.Stdout, tablewriter.WithStreaming(tw.StreamConfig{Enable: true})) + + // Start streaming + if err := table.Start(); err != nil { + log.Fatalf("Start failed: %v", err) + } + + defer table.Close() + + // Stream header + table.Header([]string{"ID", "Description", "Status"}) + + // Stream rows with simulated delay + data := [][]string{ + {"1", "This description is too long", "OK"}, + {"2", "Short desc", "DONE"}, + {"3", "Another long description here", "ERROR"}, + } + for _, row := range data { + table.Append(row) + time.Sleep(500 * time.Millisecond) // Simulate real-time data feed + } + + // Stream footer + table.Footer([]string{"", "Total", "3"}) +} ``` -##### Output 7 +**Output** (appears incrementally): + ``` -+----------+--------------------------+-------+---------+ -| DATE | DESCRIPTION | CV2 | AMOUNT | -+----------+--------------------------+-------+---------+ -| 1/1/2014 | Domain name | 1234 | $10.98 | -+----------+--------------------------+ + + -| 1/1/2014 | January Hosting | | | -+----------+--------------------------+-------+---------+ -| 1/4/2014 | February Hosting | 3456 | $51.00 | -+----------+--------------------------+-------+---------+ -| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 | -+----------+--------------------------+-------+---------+ -| TOTAL | $146.93 | -+----------+--------------------------+-------+---------+ +┌────────┬───────────────┬──────────┐ +│ ID │ DESCRIPTION │ STATUS │ +├────────┼───────────────┼──────────┤ +│ 1 │ This │ OK │ +│ │ description │ │ +│ │ is too long │ │ +│ 2 │ Short desc │ DONE │ +│ 3 │ Another long │ ERROR │ +│ │ description │ │ +│ │ here │ │ +├────────┼───────────────┼──────────┤ +│ │ Total │ 3 │ +└────────┴───────────────┴──────────┘ ``` +**Note**: Long descriptions are truncated with `…` due to fixed column widths. The output appears row-by-row, simulating a real-time feed. + +#### 6. Hierarchical Merging for Organizational Data + +Show hierarchical merging for a tree-like structure, such as an organizational hierarchy (inspired by `TestMergeHierarchicalUnicode`). -#### Table with color ```go -data := [][]string{ - []string{"1/1/2014", "Domain name", "2233", "$10.98"}, - []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, - []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, - []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, -} +package main -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) -table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer -table.SetBorder(false) // Set Border to false +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) -table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, - tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, - tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, - tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) +func main() { + data := [][]string{ + {"Engineering", "Backend", "API Team", "Alice"}, + {"Engineering", "Backend", "Database Team", "Bob"}, + {"Engineering", "Frontend", "UI Team", "Charlie"}, + {"Marketing", "Digital", "SEO Team", "Dave"}, + {"Marketing", "Digital", "Content Team", "Eve"}, + } -table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Settings: tw.Settings{Separators: tw.Separators{BetweenRows: tw.On}}, + })), + tablewriter.WithConfig(tablewriter.Config{ + Header: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}}, + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{MergeMode: tw.MergeHierarchical}, + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, + }, + }), + ) + table.Header([]string{"Department", "Division", "Team", "Lead"}) + table.Bulk(data) + table.Render() +} +``` -table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, - tablewriter.Colors{tablewriter.Bold}, - tablewriter.Colors{tablewriter.FgHiRedColor}) +**Output**: -table.AppendBulk(data) -table.Render() +``` +┌────────────┬──────────┬──────────────┬────────┐ +│ DEPARTMENT │ DIVISION │ TEAM │ LEAD │ +├────────────┼──────────┼──────────────┼────────┤ +│ Engineering│ Backend │ API Team │ Alice │ +│ │ ├──────────────┼────────┤ +│ │ │ Database Team│ Bob │ +│ │ Frontend ├──────────────┼────────┤ +│ │ │ UI Team │ Charlie│ +├────────────┼──────────┼──────────────┼────────┤ +│ Marketing │ Digital │ SEO Team │ Dave │ +│ │ ├──────────────┼────────┤ +│ │ │ Content Team │ Eve │ +└────────────┴──────────┴──────────────┴────────┘ ``` -#### Table with color Output -![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) +**Note**: Hierarchical merging groups repeated values (e.g., "Engineering" spans multiple rows, "Backend" spans two teams), creating a tree-like structure. -#### Example - 8 Table Cells with Color +#### 7. Custom Padding with Merging -Individual Cell Colors from `func Rich` take precedence over Column Colors +Showcase custom padding and combined horizontal/vertical merging (inspired by `TestMergeWithPadding` in `merge_test.go`). ```go -data := [][]string{ - []string{"Test1Merge", "HelloCol2 - 1", "HelloCol3 - 1", "HelloCol4 - 1"}, - []string{"Test1Merge", "HelloCol2 - 2", "HelloCol3 - 2", "HelloCol4 - 2"}, - []string{"Test1Merge", "HelloCol2 - 3", "HelloCol3 - 3", "HelloCol4 - 3"}, - []string{"Test2Merge", "HelloCol2 - 4", "HelloCol3 - 4", "HelloCol4 - 4"}, - []string{"Test2Merge", "HelloCol2 - 5", "HelloCol3 - 5", "HelloCol4 - 5"}, - []string{"Test2Merge", "HelloCol2 - 6", "HelloCol3 - 6", "HelloCol4 - 6"}, - []string{"Test2Merge", "HelloCol2 - 7", "HelloCol3 - 7", "HelloCol4 - 7"}, - []string{"Test3Merge", "HelloCol2 - 8", "HelloCol3 - 8", "HelloCol4 - 8"}, - []string{"Test3Merge", "HelloCol2 - 9", "HelloCol3 - 9", "HelloCol4 - 9"}, - []string{"Test3Merge", "HelloCol2 - 10", "HelloCol3 -10", "HelloCol4 - 10"}, +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + data := [][]string{ + {"1/1/2014", "Domain name", "Successful", "Successful"}, + {"1/1/2014", "Domain name", "Pending", "Waiting"}, + {"1/1/2014", "Domain name", "Successful", "Rejected"}, + {"", "", "TOTAL", "$145.93"}, + } + + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Settings: tw.Settings{Separators: tw.Separators{BetweenRows: tw.On}}, + })), + tablewriter.WithConfig(tablewriter.Config{ + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{MergeMode: tw.MergeBoth}, + Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.Skip, tw.Skip, tw.AlignRight, tw.AlignLeft}}, + }, + + Footer: tw.CellConfig{ + Padding: tw.CellPadding{ + Global: tw.Padding{Left: "*", Right: "*"}, + PerColumn: []tw.Padding{{}, {}, {Bottom: "^"}, {Bottom: "^"}}, + }, + Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.Skip, tw.Skip, tw.AlignRight, tw.AlignLeft}}, + }, + }), + ) + table.Header([]string{"Date", "Description", "Status", "Conclusion"}) + table.Bulk(data) + table.Render() } +``` -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Col1", "Col2", "Col3", "Col4"}) -table.SetFooter([]string{"", "", "Footer3", "Footer4"}) -table.SetBorder(false) +**Output**: -table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, - tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, - tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, - tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) +``` +┌──────────┬─────────────┬────────────┬────────────┐ +│ DATE │ DESCRIPTION │ STATUS │ CONCLUSION │ +├──────────┼─────────────┼────────────┴────────────┤ +│ 1/1/2014 │ Domain name │ Successful │ +│ │ ├────────────┬────────────┤ +│ │ │ Pending │ Waiting │ +│ │ ├────────────┼────────────┤ +│ │ │ Successful │ Rejected │ +├──────────┼─────────────┼────────────┼────────────┤ +│ │ │ TOTAL │ $145.93 │ +│ │ │^^^^^^^^^^^^│^^^^^^^^^^^^│ +└──────────┴─────────────┴────────────┴────────────┘ +``` -table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, - tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) +#### 8. Nested Tables -table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, - tablewriter.Colors{tablewriter.Bold}, - tablewriter.Colors{tablewriter.FgHiRedColor}) +Create a table with nested sub-tables for complex layouts (inspired by `TestMasterClass` in `extra_test.go`). + +```go +package main -colorData1 := []string{"TestCOLOR1Merge", "HelloCol2 - COLOR1", "HelloCol3 - COLOR1", "HelloCol4 - COLOR1"} -colorData2 := []string{"TestCOLOR2Merge", "HelloCol2 - COLOR2", "HelloCol3 - COLOR2", "HelloCol4 - COLOR2"} +import ( + "bytes" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) -for i, row := range data { - if i == 4 { - table.Rich(colorData1, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{tablewriter.Normal, tablewriter.FgCyanColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgWhiteColor}, tablewriter.Colors{}}) - table.Rich(colorData2, []tablewriter.Colors{tablewriter.Colors{tablewriter.Normal, tablewriter.FgMagentaColor}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgRedColor}, tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Italic, tablewriter.BgHiCyanColor}}) +func main() { + // Helper to create a sub-table + createSubTable := func(s string) string { + var buf bytes.Buffer + table := tablewriter.NewTable(&buf, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Borders: tw.BorderNone, + Symbols: tw.NewSymbols(tw.StyleASCII), + Settings: tw.Settings{ + Separators: tw.Separators{BetweenRows: tw.On}, + Lines: tw.Lines{ShowFooterLine: tw.On}, + }, + })), + tablewriter.WithConfig(tablewriter.Config{ + MaxWidth: 10, + Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}}, + }), + ) + table.Append([]string{s, s}) + table.Append([]string{s, s}) + table.Render() + return buf.String() } - table.Append(row) + + // Main table + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Borders: tw.BorderNone, + Settings: tw.Settings{Separators: tw.Separators{BetweenColumns: tw.On}}, + })), + tablewriter.WithConfig(tablewriter.Config{ + MaxWidth: 30, + Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignCenter}}, + }), + ) + table.Append([]string{createSubTable("A"), createSubTable("B")}) + table.Append([]string{createSubTable("C"), createSubTable("D")}) + table.Render() } +``` -table.SetAutoMergeCells(true) -table.Render() +**Output**: ``` + A | A │ B | B + ---+--- │ ---+--- + A | A │ B | B + C | C │ D | D + ---+--- │ ---+--- + C | C │ D | D +``` + +#### 9. Structs with Database -##### Table cells with color Output -![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png) +Render a table from a slice of structs, simulating a database query (inspired by `TestStructTableWithDB` in `struct_test.go`). -#### Example 9 - Set table caption ```go -data := [][]string{ - []string{"A", "The Good", "500"}, - []string{"B", "The Very very Bad Man", "288"}, - []string{"C", "The Ugly", "120"}, - []string{"D", "The Gopher", "800"}, +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +type Employee struct { + ID int + Name string + Age int + Department string + Salary float64 } -table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Name", "Sign", "Rating"}) -table.SetCaption(true, "Movie ratings.") +func employeeStringer(e interface{}) []string { + emp, ok := e.(Employee) + if !ok { + return []string{"Error: Invalid type"} + } + return []string{ + fmt.Sprintf("%d", emp.ID), + emp.Name, + fmt.Sprintf("%d", emp.Age), + emp.Department, + fmt.Sprintf("%.2f", emp.Salary), + } +} + +func main() { + employees := []Employee{ + {ID: 1, Name: "Alice Smith", Age: 28, Department: "Engineering", Salary: 75000.50}, + {ID: 2, Name: "Bob Johnson", Age: 34, Department: "Marketing", Salary: 62000.00}, + {ID: 3, Name: "Charlie Brown", Age: 45, Department: "HR", Salary: 80000.75}, + } + + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{ + Symbols: tw.NewSymbols(tw.StyleRounded), + })), + tablewriter.WithStringer(employeeStringer), + tablewriter.WithConfig(tablewriter.Config{ + Header: tw.CellConfig{ + Formatting: tw.CellFormatting{AutoFormat: tw.On}, + Alignment: tw.CellAlignment{Global: tw.AlignCenter}, + }, + Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignLeft}}, + Footer: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignRight}}, + }), + ) + table.Header([]string{"ID", "Name", "Age", "Department", "Salary"}) + + for _, emp := range employees { + table.Append(emp) + } -for _, v := range data { - table.Append(v) + totalSalary := 0.0 + for _, emp := range employees { + totalSalary += emp.Salary + } + table.Footer([]string{"", "", "", "Total", fmt.Sprintf("%.2f", totalSalary)}) + table.Render() } -table.Render() // Send output ``` -Note: Caption text will wrap with total width of rendered table. +**Output**: -##### Output 9 ``` -+------+-----------------------+--------+ -| NAME | SIGN | RATING | -+------+-----------------------+--------+ -| A | The Good | 500 | -| B | The Very very Bad Man | 288 | -| C | The Ugly | 120 | -| D | The Gopher | 800 | -+------+-----------------------+--------+ -Movie ratings. +╭────┬───────────────┬─────┬─────────────┬───────────╮ +│ ID │ NAME │ AGE │ DEPARTMENT │ SALARY │ +├────┼───────────────┼─────┼─────────────┼───────────┤ +│ 1 │ Alice Smith │ 28 │ Engineering │ 75000.50 │ +│ 2 │ Bob Johnson │ 34 │ Marketing │ 62000.00 │ +│ 3 │ Charlie Brown │ 45 │ HR │ 80000.75 │ +├────┼───────────────┼─────┼─────────────┼───────────┤ +│ │ │ │ Total │ 217001.25 │ +╰────┴───────────────┴─────┴─────────────┴───────────╯ ``` -#### Example 10 - Set NoWhiteSpace and TablePadding option + +#### 10. Simple Html Table + + ```go -data := [][]string{ - {"node1.example.com", "Ready", "compute", "1.11"}, - {"node2.example.com", "Ready", "compute", "1.11"}, - {"node3.example.com", "Ready", "compute", "1.11"}, - {"node4.example.com", "NotReady", "compute", "1.11"}, +package main + +import ( + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "os" +) + +func main() { + data := [][]string{ + {"North", "Q1 & Q2", "Q1 & Q2", "$2200.00"}, + {"South", "Q1", "Q1", "$1000.00"}, + {"South", "Q2", "Q2", "$1200.00"}, + } + + // Configure HTML with custom CSS classes and content escaping + htmlCfg := renderer.HTMLConfig{ + TableClass: "sales-table", + HeaderClass: "table-header", + BodyClass: "table-body", + FooterClass: "table-footer", + RowClass: "table-row", + HeaderRowClass: "header-row", + FooterRowClass: "footer-row", + EscapeContent: true, // Escape HTML characters (e.g., "&" to "&") + } + + table := tablewriter.NewTable(os.Stdout, + tablewriter.WithRenderer(renderer.NewHTML(htmlCfg)), + tablewriter.WithConfig(tablewriter.Config{ + Header: tw.CellConfig{ + Formatting: tw.CellFormatting{MergeMode: tw.MergeHorizontal}, // Merge identical header cells + Alignment: tw.CellAlignment{Global: tw.AlignCenter}, + }, + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{MergeMode: tw.MergeHorizontal}, // Merge identical row cells + Alignment: tw.CellAlignment{Global: tw.AlignLeft}, + }, + Footer: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignRight}}, + }), + ) + + table.Header([]string{"Region", "Quarter", "Quarter", "Sales"}) + table.Bulk(data) + table.Footer([]string{"", "", "Total", "$4400.00"}) + table.Render() } +``` + +**Output**: + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
REGIONQUARTERSALES
NorthQ1 & Q2$2200.00
SouthQ1$1000.00
SouthQ2$1200.00
-table := tablewriter.NewWriter(os.Stdout) -table.SetHeader([]string{"Name", "Status", "Role", "Version"}) -table.SetAutoWrapText(false) -table.SetAutoFormatHeaders(true) -table.SetHeaderAlignment(ALIGN_LEFT) -table.SetAlignment(ALIGN_LEFT) -table.SetCenterSeparator("") -table.SetColumnSeparator("") -table.SetRowSeparator("") -table.SetHeaderLine(false) -table.SetBorder(false) -table.SetTablePadding("\t") // pad with tabs -table.SetNoWhiteSpace(true) -table.AppendBulk(data) // Add Bulk Data -table.Render() ``` -##### Output 10 +#### 11. SVG Support +```go +package main + +import ( + "fmt" + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/renderer" + "os" +) + +type Age int + +func (a Age) String() string { + return fmt.Sprintf("%d yrs", a) +} + +func main() { + data := [][]any{ + {"Alice", Age(25), "New York"}, + {"Bob", Age(30), "Boston"}, + } + + file, err := os.OpenFile("out.svg", os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + ll.Fatal(err) + } + defer file.Close() + + table := tablewriter.NewTable(file, tablewriter.WithRenderer(renderer.NewSVG())) + table.Header("Name", "Age", "City") + table.Bulk(data) + table.Render() +} ``` -NAME STATUS ROLE VERSION -node1.example.com Ready compute 1.11 -node2.example.com Ready compute 1.11 -node3.example.com Ready compute 1.11 -node4.example.com NotReady compute 1.11 + +```go + + + + NAME + + AGE + + CITY + + Alice + + 25 yrs + + New York + + Bob + + 30 yrs + + Boston + + + + + + + + + + + + ``` -#### Render table into a string +#### 12 Simple Application -Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example: ```go package main import ( - "strings" - "fmt" + "fmt" + "github.com/olekukonko/tablewriter" + "github.com/olekukonko/tablewriter/tw" + "io/fs" + "os" + "path/filepath" + "strings" + "time" +) - "github.com/olekukonko/tablewriter" +const ( + folder = "📁" + file = "📄" + baseDir = "../" + indentStr = " " ) func main() { - tableString := &strings.Builder{} - table := tablewriter.NewWriter(tableString) + table := tablewriter.NewTable(os.Stdout, tablewriter.WithTrimSpace(tw.Off)) + table.Header([]string{"Tree", "Size", "Permissions", "Modified"}) + err := filepath.WalkDir(baseDir, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.Name() == "." || d.Name() == ".." { + return nil + } + + // Calculate relative path depth + relPath, err := filepath.Rel(baseDir, path) + if err != nil { + return err + } + + depth := 0 + if relPath != "." { + depth = len(strings.Split(relPath, string(filepath.Separator))) - 1 + } + + indent := strings.Repeat(indentStr, depth) + + var name string + if d.IsDir() { + name = fmt.Sprintf("%s%s %s", indent, folder, d.Name()) + } else { + name = fmt.Sprintf("%s%s %s", indent, file, d.Name()) + } + + info, err := d.Info() + if err != nil { + return err + } + + table.Append([]string{ + name, + Size(info.Size()).String(), + info.Mode().String(), + Time(info.ModTime()).Format(), + }) + + return nil + }) + + if err != nil { + fmt.Fprintf(os.Stdout, "Error: %v\n", err) + return + } + + table.Render() +} - /* - * Code to fill the table - */ +const ( + KB = 1024 + MB = KB * 1024 + GB = MB * 1024 + TB = GB * 1024 +) - table.Render() +type Size int64 + +func (s Size) String() string { + switch { + case s < KB: + return fmt.Sprintf("%d B", s) + case s < MB: + return fmt.Sprintf("%.2f KB", float64(s)/KB) + case s < GB: + return fmt.Sprintf("%.2f MB", float64(s)/MB) + case s < TB: + return fmt.Sprintf("%.2f GB", float64(s)/GB) + default: + return fmt.Sprintf("%.2f TB", float64(s)/TB) + } +} - fmt.Println(tableString.String()) +type Time time.Time + +func (t Time) Format() string { + now := time.Now() + diff := now.Sub(time.Time(t)) + + if diff.Seconds() < 60 { + return "just now" + } else if diff.Minutes() < 60 { + return fmt.Sprintf("%d minutes ago", int(diff.Minutes())) + } else if diff.Hours() < 24 { + return fmt.Sprintf("%d hours ago", int(diff.Hours())) + } else if diff.Hours() < 24*7 { + return fmt.Sprintf("%d days ago", int(diff.Hours()/24)) + } else { + return time.Time(t).Format("Jan 2, 2006") + } } + ``` -#### TODO -- ~~Import Directly from CSV~~ - `done` -- ~~Support for `SetFooter`~~ - `done` -- ~~Support for `SetBorder`~~ - `done` -- ~~Support table with uneven rows~~ - `done` -- ~~Support custom alignment~~ -- General Improvement & Optimisation -- `NewHTML` Parse table from HTML +``` +┌──────────────────┬─────────┬─────────────┬──────────────┐ +│ TREE │ SIZE │ PERMISSIONS │ MODIFIED │ +├──────────────────┼─────────┼─────────────┼──────────────┤ +│ 📁 filetable │ 160 B │ drwxr-xr-x │ just now │ +│ 📄 main.go │ 2.19 KB │ -rw-r--r-- │ 22 hours ago │ +│ 📄 out.txt │ 0 B │ -rw-r--r-- │ just now │ +│ 📁 testdata │ 128 B │ drwxr-xr-x │ 1 days ago │ +│ 📄 a.txt │ 11 B │ -rw-r--r-- │ 1 days ago │ +│ 📄 b.txt │ 17 B │ -rw-r--r-- │ 1 days ago │ +│ 📁 symbols │ 128 B │ drwxr-xr-x │ just now │ +│ 📄 main.go │ 4.58 KB │ -rw-r--r-- │ 1 hours ago │ +│ 📄 out.txt │ 8.72 KB │ -rw-r--r-- │ just now │ +└──────────────────┴─────────┴─────────────┴──────────────┘ +``` + + +## Changes + +- `AutoFormat` changes See [#261](https://github.com/olekukonko/tablewriter/issues/261) + + +## Command-Line Tool + +The `csv2table` tool converts CSV files to ASCII tables. See `cmd/csv2table/csv2table.go` for details. + +Example usage: + +```bash +csv2table -f test.csv -h true -a left +``` + +## Contributing + +Contributions are welcome! Submit issues or pull requests to the [GitHub repository](https://github.com/olekukonko/tablewriter). + +## License + +MIT License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/README_LEGACY.md b/vendor/github.com/olekukonko/tablewriter/README_LEGACY.md new file mode 100644 index 00000000..ed9b9c0a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/README_LEGACY.md @@ -0,0 +1,466 @@ +ASCII Table Writer +========= + +[![ci](https://github.com/olekukonko/tablewriter/workflows/ci/badge.svg?branch=master)](https://github.com/olekukonko/tablewriter/actions?query=workflow%3Aci) +[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter) + + +## Important Notice: Modernization in Progress + +The `tablewriter` package is being modernized on the `prototype` branch with generics, streaming support, and a modular design, targeting `v0.2.0`. Until this is released: + +**For Production Use**: Use the stable version `v0.0.5`: +```bash + go get github.com/olekukonko/tablewriter@v0.0.5 +``` + +#### + +For Development Preview: Try the in-progress version (unstable) + +```bash +go get github.com/olekukonko/tablewriter@master +``` + +#### Features + +- Automatic Padding +- Support Multiple Lines +- Supports Alignment +- Support Custom Separators +- Automatic Alignment of numbers & percentage +- Write directly to http , file etc via `io.Writer` +- Read directly from CSV file +- Optional row line via `SetRowLine` +- Normalise table header +- Make CSV Headers optional +- Enable or disable table border +- Set custom footer support +- Optional identical cells merging +- Set custom caption +- Optional reflowing of paragraphs in multi-line cells. + +#### Example 1 - Basic + +```go +data := [][]string{ +[]string{"A", "The Good", "500"}, +[]string{"B", "The Very very Bad Man", "288"}, +[]string{"C", "The Ugly", "120"}, +[]string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) + +for _, v := range data { +table.Append(v) +} +table.Render() // Send output +``` + +##### Output 1 + +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +``` + +#### Example 2 - Without Border / Footer / Bulk Append + +```go +data := [][]string{ +[]string{"1/1/2014", "Domain name", "2233", "$10.98"}, +[]string{"1/1/2014", "January Hosting", "2233", "$54.95"}, +[]string{"1/4/2014", "February Hosting", "2233", "$51.00"}, +[]string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.EnableBorder(false) // Set Border to false +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 2 + +``` + + DATE | DESCRIPTION | CV2 | AMOUNT +-----------+--------------------------+-------+---------- + 1/1/2014 | Domain name | 2233 | $10.98 + 1/1/2014 | January Hosting | 2233 | $54.95 + 1/4/2014 | February Hosting | 2233 | $51.00 + 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 +-----------+--------------------------+-------+---------- + TOTAL | $146 93 + --------+---------- + +``` + +#### Example 3 - CSV + +```go +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test_info.csv", true) +table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment +table.Render() +``` + +##### Output 3 + +``` ++----------+--------------+------+-----+---------+----------------+ +| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | ++----------+--------------+------+-----+---------+----------------+ +| user_id | smallint(5) | NO | PRI | NULL | auto_increment | +| username | varchar(10) | NO | | NULL | | +| password | varchar(100) | NO | | NULL | | ++----------+--------------+------+-----+---------+----------------+ +``` + +#### Example 4 - Custom Separator + +```go +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test.csv", true) +table.SetRowLine(true) // Enable row line + +// Change table lines +table.SetCenterSeparator("*") +table.SetColumnSeparator("╪") +table.SetRowSeparator("-") + +table.SetAlignment(tablewriter.ALIGN_LEFT) +table.Render() +``` + +##### Output 4 + +``` +*------------*-----------*---------* +╪ FIRST NAME ╪ LAST NAME ╪ SSN ╪ +*------------*-----------*---------* +╪ John ╪ Barry ╪ 123456 ╪ +*------------*-----------*---------* +╪ Kathy ╪ Smith ╪ 687987 ╪ +*------------*-----------*---------* +╪ Bob ╪ McCornick ╪ 3979870 ╪ +*------------*-----------*---------* +``` + +#### Example 5 - Markdown Format + +```go +data := [][]string{ +[]string{"1/1/2014", "Domain name", "2233", "$10.98"}, +[]string{"1/1/2014", "January Hosting", "2233", "$54.95"}, +[]string{"1/4/2014", "February Hosting", "2233", "$51.00"}, +[]string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) +table.SetCenterSeparator("|") +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 5 + +``` +| DATE | DESCRIPTION | CV2 | AMOUNT | +|----------|--------------------------|------|--------| +| 1/1/2014 | Domain name | 2233 | $10.98 | +| 1/1/2014 | January Hosting | 2233 | $54.95 | +| 1/4/2014 | February Hosting | 2233 | $51.00 | +| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +``` + +#### Example 6 - Identical cells merging + +```go +data := [][]string{ +[]string{"1/1/2014", "Domain name", "1234", "$10.98"}, +[]string{"1/1/2014", "January Hosting", "2345", "$54.95"}, +[]string{"1/4/2014", "February Hosting", "3456", "$51.00"}, +[]string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCells(true) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 6 + +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++ +--------------------------+-------+---------+ +| | January Hosting | 2345 | $54.95 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++ +--------------------------+-------+---------+ +| | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146 93 | ++----------+--------------------------+-------+---------+ +``` + +#### Example 7 - Identical cells merging (specify the column index to merge) + +```go +data := [][]string{ +[]string{"1/1/2014", "Domain name", "1234", "$10.98"}, +[]string{"1/1/2014", "January Hosting", "1234", "$10.98"}, +[]string{"1/4/2014", "February Hosting", "3456", "$51.00"}, +[]string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCellsByColumnIndex([]int{2, 3}) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 7 + +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++----------+--------------------------+ + + +| 1/1/2014 | January Hosting | | | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146.93 | ++----------+--------------------------+-------+---------+ +``` + +#### Table with color + +```go +data := [][]string{ +[]string{"1/1/2014", "Domain name", "2233", "$10.98"}, +[]string{"1/1/2014", "January Hosting", "2233", "$54.95"}, +[]string{"1/4/2014", "February Hosting", "2233", "$51.00"}, +[]string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.EnableBorder(false) // Set Border to false + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, +tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, +tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, +tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, +tablewriter.Colors{tablewriter.Bold}, +tablewriter.Colors{tablewriter.FgHiRedColor}) + +table.AppendBulk(data) +table.Render() +``` + +#### Table with color Output + +![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) + +#### Example - 8 Table Cells with Color + +Individual Cell Colors from `func Rich` take precedence over Column Colors + +```go +data := [][]string{ +[]string{"Test1Merge", "HelloCol2 - 1", "HelloCol3 - 1", "HelloCol4 - 1"}, +[]string{"Test1Merge", "HelloCol2 - 2", "HelloCol3 - 2", "HelloCol4 - 2"}, +[]string{"Test1Merge", "HelloCol2 - 3", "HelloCol3 - 3", "HelloCol4 - 3"}, +[]string{"Test2Merge", "HelloCol2 - 4", "HelloCol3 - 4", "HelloCol4 - 4"}, +[]string{"Test2Merge", "HelloCol2 - 5", "HelloCol3 - 5", "HelloCol4 - 5"}, +[]string{"Test2Merge", "HelloCol2 - 6", "HelloCol3 - 6", "HelloCol4 - 6"}, +[]string{"Test2Merge", "HelloCol2 - 7", "HelloCol3 - 7", "HelloCol4 - 7"}, +[]string{"Test3Merge", "HelloCol2 - 8", "HelloCol3 - 8", "HelloCol4 - 8"}, +[]string{"Test3Merge", "HelloCol2 - 9", "HelloCol3 - 9", "HelloCol4 - 9"}, +[]string{"Test3Merge", "HelloCol2 - 10", "HelloCol3 -10", "HelloCol4 - 10"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Col1", "Col2", "Col3", "Col4"}) +table.SetFooter([]string{"", "", "Footer3", "Footer4"}) +table.EnableBorder(false) + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, +tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, +tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, +tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, +tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, +tablewriter.Colors{tablewriter.Bold}, +tablewriter.Colors{tablewriter.FgHiRedColor}) + +colorData1 := []string{"TestCOLOR1Merge", "HelloCol2 - COLOR1", "HelloCol3 - COLOR1", "HelloCol4 - COLOR1"} +colorData2 := []string{"TestCOLOR2Merge", "HelloCol2 - COLOR2", "HelloCol3 - COLOR2", "HelloCol4 - COLOR2"} + +for i, row := range data { +if i == 4 { +table.Rich(colorData1, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{tablewriter.Normal, tablewriter.FgCyanColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgWhiteColor}, tablewriter.Colors{}}) +table.Rich(colorData2, []tablewriter.Colors{tablewriter.Colors{tablewriter.Normal, tablewriter.FgMagentaColor}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgRedColor}, tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Italic, tablewriter.BgHiCyanColor}}) +} +table.Append(row) +} + +table.SetAutoMergeCells(true) +table.Render() + +``` + +##### Table cells with color Output + +![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png) + +#### Example 9 - Set table caption + +```go +data := [][]string{ +[]string{"A", "The Good", "500"}, +[]string{"B", "The Very very Bad Man", "288"}, +[]string{"C", "The Ugly", "120"}, +[]string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) +table.SetCaption(true, "Movie ratings.") + +for _, v := range data { +table.Append(v) +} +table.Render() // Send output +``` + +Note: Caption text will wrap with total width of rendered table. + +##### Output 9 + +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +Movie ratings. +``` + +#### Example 10 - Set NoWhiteSpace and TablePadding option + +```go +data := [][]string{ +{"node1.example.com", "Ready", "compute", "1.11"}, +{"node2.example.com", "Ready", "compute", "1.11"}, +{"node3.example.com", "Ready", "compute", "1.11"}, +{"node4.example.com", "NotReady", "compute", "1.11"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Status", "Role", "Version"}) +table.SetAutoWrapText(false) +table.SetAutoFormatHeaders(true) +table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) +table.SetAlignment(tablewriter.ALIGN_LEFT) +table.SetCenterSeparator("") +table.SetColumnSeparator("") +table.SetRowSeparator("") +table.SetHeaderLine(false) +table.EnableBorder(false) +table.SetTablePadding("\t") // pad with tabs +table.SetNoWhiteSpace(true) +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 10 + +``` +NAME STATUS ROLE VERSION +node1.example.com Ready compute 1.11 +node2.example.com Ready compute 1.11 +node3.example.com Ready compute 1.11 +node4.example.com NotReady compute 1.11 +``` + +#### Render table into a string + +Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the +`strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example: + +```go +package main + +import ( + "strings" + "fmt" + + "github.com/olekukonko/tablewriter" +) + +func main() { + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) + + /* + * Code to fill the table + */ + + table.Render() + + fmt.Println(tableString.String()) +} +``` + +#### TODO + +- ~~Import Directly from CSV~~ - `done` +- ~~Support for `SetFooter`~~ - `done` +- ~~Support for `SetBorder`~~ - `done` +- ~~Support table with uneven rows~~ - `done` +- ~~Support custom alignment~~ +- General Improvement & Optimisation +- `NewHTML` Parse table from HTML diff --git a/vendor/github.com/olekukonko/tablewriter/config.go b/vendor/github.com/olekukonko/tablewriter/config.go new file mode 100644 index 00000000..94094f1b --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/config.go @@ -0,0 +1,960 @@ +package tablewriter + +import ( + "github.com/olekukonko/tablewriter/tw" +) + +// Config represents the table configuration +type Config struct { + MaxWidth int + Header tw.CellConfig + Row tw.CellConfig + Footer tw.CellConfig + Debug bool + Stream tw.StreamConfig + Behavior tw.Behavior + Widths tw.CellWidth +} + +// ConfigBuilder provides a fluent interface for building Config +type ConfigBuilder struct { + config Config +} + +// NewConfigBuilder creates a new ConfigBuilder with defaults +func NewConfigBuilder() *ConfigBuilder { + return &ConfigBuilder{ + config: defaultConfig(), + } +} + +// Build returns the built Config +func (b *ConfigBuilder) Build() Config { + return b.config +} + +// Header returns a HeaderConfigBuilder for header configuration +func (b *ConfigBuilder) Header() *HeaderConfigBuilder { + return &HeaderConfigBuilder{ + parent: b, + config: &b.config.Header, + } +} + +// Row returns a RowConfigBuilder for row configuration +func (b *ConfigBuilder) Row() *RowConfigBuilder { + return &RowConfigBuilder{ + parent: b, + config: &b.config.Row, + } +} + +// Footer returns a FooterConfigBuilder for footer configuration +func (b *ConfigBuilder) Footer() *FooterConfigBuilder { + return &FooterConfigBuilder{ + parent: b, + config: &b.config.Footer, + } +} + +// Behavior returns a BehaviorConfigBuilder for behavior configuration +func (b *ConfigBuilder) Behavior() *BehaviorConfigBuilder { + return &BehaviorConfigBuilder{ + parent: b, + config: &b.config.Behavior, + } +} + +// ForColumn returns a ColumnConfigBuilder for column-specific configuration +func (b *ConfigBuilder) ForColumn(col int) *ColumnConfigBuilder { + return &ColumnConfigBuilder{ + parent: b, + col: col, + } +} + +// WithTrimSpace enables or disables automatic trimming of leading/trailing spaces. +// Ignored in streaming mode. +func (b *ConfigBuilder) WithTrimSpace(state tw.State) *ConfigBuilder { + b.config.Behavior.TrimSpace = state + return b +} + +// WithDebug enables/disables debug logging +func (b *ConfigBuilder) WithDebug(debug bool) *ConfigBuilder { + b.config.Debug = debug + return b +} + +// WithAutoHide enables or disables automatic hiding of empty columns (ignored in streaming mode). +func (b *ConfigBuilder) WithAutoHide(state tw.State) *ConfigBuilder { + b.config.Behavior.AutoHide = state + return b +} + +// WithFooterAlignment sets the text alignment for all footer cells. +// Invalid alignments are ignored. +func (b *ConfigBuilder) WithFooterAlignment(align tw.Align) *ConfigBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return b + } + b.config.Footer.Alignment.Global = align + return b +} + +// WithFooterAutoFormat enables or disables automatic formatting (e.g., title case) for footer cells. +func (b *ConfigBuilder) WithFooterAutoFormat(autoFormat tw.State) *ConfigBuilder { + b.config.Footer.Formatting.AutoFormat = autoFormat + return b +} + +// WithFooterAutoWrap sets the wrapping behavior for footer cells (e.g., truncate, normal, break). +// Invalid wrap modes are ignored. +func (b *ConfigBuilder) WithFooterAutoWrap(autoWrap int) *ConfigBuilder { + if autoWrap < tw.WrapNone || autoWrap > tw.WrapBreak { + return b + } + b.config.Footer.Formatting.AutoWrap = autoWrap + return b +} + +// WithFooterGlobalPadding sets the global padding for all footer cells. +func (b *ConfigBuilder) WithFooterGlobalPadding(padding tw.Padding) *ConfigBuilder { + b.config.Footer.Padding.Global = padding + return b +} + +// WithFooterMaxWidth sets the maximum content width for footer cells. +// Negative values are ignored. +func (b *ConfigBuilder) WithFooterMaxWidth(maxWidth int) *ConfigBuilder { + if maxWidth < 0 { + return b + } + b.config.Footer.ColMaxWidths.Global = maxWidth + return b +} + +// WithFooterMergeMode sets the merge behavior for footer cells (e.g., horizontal, hierarchical). +// Invalid merge modes are ignored. +func (b *ConfigBuilder) WithFooterMergeMode(mergeMode int) *ConfigBuilder { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return b + } + b.config.Footer.Formatting.MergeMode = mergeMode + return b +} + +// WithHeaderAlignment sets the text alignment for all header cells. +// Invalid alignments are ignored. +func (b *ConfigBuilder) WithHeaderAlignment(align tw.Align) *ConfigBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return b + } + b.config.Header.Alignment.Global = align + return b +} + +// WithHeaderAutoFormat enables or disables automatic formatting (e.g., title case) for header cells. +func (b *ConfigBuilder) WithHeaderAutoFormat(autoFormat tw.State) *ConfigBuilder { + b.config.Header.Formatting.AutoFormat = autoFormat + return b +} + +// WithHeaderAutoWrap sets the wrapping behavior for header cells (e.g., truncate, normal). +// Invalid wrap modes are ignored. +func (b *ConfigBuilder) WithHeaderAutoWrap(autoWrap int) *ConfigBuilder { + if autoWrap < tw.WrapNone || autoWrap > tw.WrapBreak { + return b + } + b.config.Header.Formatting.AutoWrap = autoWrap + return b +} + +// WithHeaderGlobalPadding sets the global padding for all header cells. +func (b *ConfigBuilder) WithHeaderGlobalPadding(padding tw.Padding) *ConfigBuilder { + b.config.Header.Padding.Global = padding + return b +} + +// WithHeaderMaxWidth sets the maximum content width for header cells. +// Negative values are ignored. +func (b *ConfigBuilder) WithHeaderMaxWidth(maxWidth int) *ConfigBuilder { + if maxWidth < 0 { + return b + } + b.config.Header.ColMaxWidths.Global = maxWidth + return b +} + +// WithHeaderMergeMode sets the merge behavior for header cells (e.g., horizontal, vertical). +// Invalid merge modes are ignored. +func (b *ConfigBuilder) WithHeaderMergeMode(mergeMode int) *ConfigBuilder { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return b + } + b.config.Header.Formatting.MergeMode = mergeMode + return b +} + +// WithMaxWidth sets the maximum width for the entire table (0 means unlimited). +// Negative values are treated as 0. +func (b *ConfigBuilder) WithMaxWidth(width int) *ConfigBuilder { + if width < 0 { + b.config.MaxWidth = 0 + } else { + b.config.MaxWidth = width + } + return b +} + +// WithRowAlignment sets the text alignment for all row cells. +// Invalid alignments are ignored. +func (b *ConfigBuilder) WithRowAlignment(align tw.Align) *ConfigBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return b + } + b.config.Row.Alignment.Global = align + return b +} + +// WithRowAutoFormat enables or disables automatic formatting for row cells. +func (b *ConfigBuilder) WithRowAutoFormat(autoFormat tw.State) *ConfigBuilder { + b.config.Row.Formatting.AutoFormat = autoFormat + return b +} + +// WithRowAutoWrap sets the wrapping behavior for row cells (e.g., truncate, normal). +// Invalid wrap modes are ignored. +func (b *ConfigBuilder) WithRowAutoWrap(autoWrap int) *ConfigBuilder { + if autoWrap < tw.WrapNone || autoWrap > tw.WrapBreak { + return b + } + b.config.Row.Formatting.AutoWrap = autoWrap + return b +} + +// WithRowGlobalPadding sets the global padding for all row cells. +func (b *ConfigBuilder) WithRowGlobalPadding(padding tw.Padding) *ConfigBuilder { + b.config.Row.Padding.Global = padding + return b +} + +// WithRowMaxWidth sets the maximum content width for row cells. +// Negative values are ignored. +func (b *ConfigBuilder) WithRowMaxWidth(maxWidth int) *ConfigBuilder { + if maxWidth < 0 { + return b + } + b.config.Row.ColMaxWidths.Global = maxWidth + return b +} + +// WithRowMergeMode sets the merge behavior for row cells (e.g., horizontal, hierarchical). +// Invalid merge modes are ignored. +func (b *ConfigBuilder) WithRowMergeMode(mergeMode int) *ConfigBuilder { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return b + } + b.config.Row.Formatting.MergeMode = mergeMode + return b +} + +// HeaderConfigBuilder configures header settings +type HeaderConfigBuilder struct { + parent *ConfigBuilder + config *tw.CellConfig +} + +// Build returns the parent ConfigBuilder +func (h *HeaderConfigBuilder) Build() *ConfigBuilder { + return h.parent +} + +// Alignment returns an AlignmentConfigBuilder for header alignment +func (h *HeaderConfigBuilder) Alignment() *AlignmentConfigBuilder { + return &AlignmentConfigBuilder{ + parent: h.parent, + config: &h.config.Alignment, + section: "header", + } +} + +// Formatting returns a HeaderFormattingBuilder for header formatting +func (h *HeaderConfigBuilder) Formatting() *HeaderFormattingBuilder { + return &HeaderFormattingBuilder{ + parent: h, + config: &h.config.Formatting, + section: "header", + } +} + +// Padding returns a HeaderPaddingBuilder for header padding +func (h *HeaderConfigBuilder) Padding() *HeaderPaddingBuilder { + return &HeaderPaddingBuilder{ + parent: h, + config: &h.config.Padding, + section: "header", + } +} + +// Filter returns a HeaderFilterBuilder for header filtering +func (h *HeaderConfigBuilder) Filter() *HeaderFilterBuilder { + return &HeaderFilterBuilder{ + parent: h, + config: &h.config.Filter, + section: "header", + } +} + +// Callbacks returns a HeaderCallbacksBuilder for header callbacks +func (h *HeaderConfigBuilder) Callbacks() *HeaderCallbacksBuilder { + return &HeaderCallbacksBuilder{ + parent: h, + config: &h.config.Callbacks, + section: "header", + } +} + +// RowConfigBuilder configures row settings +type RowConfigBuilder struct { + parent *ConfigBuilder + config *tw.CellConfig +} + +// Build returns the parent ConfigBuilder +func (r *RowConfigBuilder) Build() *ConfigBuilder { + return r.parent +} + +// Alignment returns an AlignmentConfigBuilder for row alignment +func (r *RowConfigBuilder) Alignment() *AlignmentConfigBuilder { + return &AlignmentConfigBuilder{ + parent: r.parent, + config: &r.config.Alignment, + section: "row", + } +} + +// Formatting returns a RowFormattingBuilder for row formatting +func (r *RowConfigBuilder) Formatting() *RowFormattingBuilder { + return &RowFormattingBuilder{ + parent: r, + config: &r.config.Formatting, + section: "row", + } +} + +// Padding returns a RowPaddingBuilder for row padding +func (r *RowConfigBuilder) Padding() *RowPaddingBuilder { + return &RowPaddingBuilder{ + parent: r, + config: &r.config.Padding, + section: "row", + } +} + +// Filter returns a RowFilterBuilder for row filtering +func (r *RowConfigBuilder) Filter() *RowFilterBuilder { + return &RowFilterBuilder{ + parent: r, + config: &r.config.Filter, + section: "row", + } +} + +// Callbacks returns a RowCallbacksBuilder for row callbacks +func (r *RowConfigBuilder) Callbacks() *RowCallbacksBuilder { + return &RowCallbacksBuilder{ + parent: r, + config: &r.config.Callbacks, + section: "row", + } +} + +// FooterConfigBuilder configures footer settings +type FooterConfigBuilder struct { + parent *ConfigBuilder + config *tw.CellConfig +} + +// Build returns the parent ConfigBuilder +func (f *FooterConfigBuilder) Build() *ConfigBuilder { + return f.parent +} + +// Alignment returns an AlignmentConfigBuilder for footer alignment +func (f *FooterConfigBuilder) Alignment() *AlignmentConfigBuilder { + return &AlignmentConfigBuilder{ + parent: f.parent, + config: &f.config.Alignment, + section: "footer", + } +} + +// Formatting returns a FooterFormattingBuilder for footer formatting +func (f *FooterConfigBuilder) Formatting() *FooterFormattingBuilder { + return &FooterFormattingBuilder{ + parent: f, + config: &f.config.Formatting, + section: "footer", + } +} + +// Padding returns a FooterPaddingBuilder for footer padding +func (f *FooterConfigBuilder) Padding() *FooterPaddingBuilder { + return &FooterPaddingBuilder{ + parent: f, + config: &f.config.Padding, + section: "footer", + } +} + +// Filter returns a FooterFilterBuilder for footer filtering +func (f *FooterConfigBuilder) Filter() *FooterFilterBuilder { + return &FooterFilterBuilder{ + parent: f, + config: &f.config.Filter, + section: "footer", + } +} + +// Callbacks returns a FooterCallbacksBuilder for footer callbacks +func (f *FooterConfigBuilder) Callbacks() *FooterCallbacksBuilder { + return &FooterCallbacksBuilder{ + parent: f, + config: &f.config.Callbacks, + section: "footer", + } +} + +// AlignmentConfigBuilder configures alignment settings +type AlignmentConfigBuilder struct { + parent *ConfigBuilder + config *tw.CellAlignment + section string +} + +// Build returns the parent ConfigBuilder +func (a *AlignmentConfigBuilder) Build() *ConfigBuilder { + return a.parent +} + +// WithGlobal sets global alignment +func (a *AlignmentConfigBuilder) WithGlobal(align tw.Align) *AlignmentConfigBuilder { + if err := align.Validate(); err == nil { + a.config.Global = align + } + return a +} + +// WithPerColumn sets per-column alignments +func (a *AlignmentConfigBuilder) WithPerColumn(alignments []tw.Align) *AlignmentConfigBuilder { + if len(alignments) > 0 { + a.config.PerColumn = alignments + } + return a +} + +// HeaderFormattingBuilder configures header formatting +type HeaderFormattingBuilder struct { + parent *HeaderConfigBuilder + config *tw.CellFormatting + section string +} + +// Build returns the parent HeaderConfigBuilder +func (hf *HeaderFormattingBuilder) Build() *HeaderConfigBuilder { + return hf.parent +} + +// WithAutoFormat enables/disables auto formatting +func (hf *HeaderFormattingBuilder) WithAutoFormat(autoFormat tw.State) *HeaderFormattingBuilder { + hf.config.AutoFormat = autoFormat + return hf +} + +// WithAutoWrap sets auto wrap mode +func (hf *HeaderFormattingBuilder) WithAutoWrap(autoWrap int) *HeaderFormattingBuilder { + if autoWrap >= tw.WrapNone && autoWrap <= tw.WrapBreak { + hf.config.AutoWrap = autoWrap + } + return hf +} + +// WithMergeMode sets merge mode +func (hf *HeaderFormattingBuilder) WithMergeMode(mergeMode int) *HeaderFormattingBuilder { + if mergeMode >= tw.MergeNone && mergeMode <= tw.MergeHierarchical { + hf.config.MergeMode = mergeMode + } + return hf +} + +// RowFormattingBuilder configures row formatting +type RowFormattingBuilder struct { + parent *RowConfigBuilder + config *tw.CellFormatting + section string +} + +// Build returns the parent RowConfigBuilder +func (rf *RowFormattingBuilder) Build() *RowConfigBuilder { + return rf.parent +} + +// WithAutoFormat enables/disables auto formatting +func (rf *RowFormattingBuilder) WithAutoFormat(autoFormat tw.State) *RowFormattingBuilder { + rf.config.AutoFormat = autoFormat + return rf +} + +// WithAutoWrap sets auto wrap mode +func (rf *RowFormattingBuilder) WithAutoWrap(autoWrap int) *RowFormattingBuilder { + if autoWrap >= tw.WrapNone && autoWrap <= tw.WrapBreak { + rf.config.AutoWrap = autoWrap + } + return rf +} + +// WithMergeMode sets merge mode +func (rf *RowFormattingBuilder) WithMergeMode(mergeMode int) *RowFormattingBuilder { + if mergeMode >= tw.MergeNone && mergeMode <= tw.MergeHierarchical { + rf.config.MergeMode = mergeMode + } + return rf +} + +// FooterFormattingBuilder configures footer formatting +type FooterFormattingBuilder struct { + parent *FooterConfigBuilder + config *tw.CellFormatting + section string +} + +// Build returns the parent FooterConfigBuilder +func (ff *FooterFormattingBuilder) Build() *FooterConfigBuilder { + return ff.parent +} + +// WithAutoFormat enables/disables auto formatting +func (ff *FooterFormattingBuilder) WithAutoFormat(autoFormat tw.State) *FooterFormattingBuilder { + ff.config.AutoFormat = autoFormat + return ff +} + +// WithAutoWrap sets auto wrap mode +func (ff *FooterFormattingBuilder) WithAutoWrap(autoWrap int) *FooterFormattingBuilder { + if autoWrap >= tw.WrapNone && autoWrap <= tw.WrapBreak { + ff.config.AutoWrap = autoWrap + } + return ff +} + +// WithMergeMode sets merge mode +func (ff *FooterFormattingBuilder) WithMergeMode(mergeMode int) *FooterFormattingBuilder { + if mergeMode >= tw.MergeNone && mergeMode <= tw.MergeHierarchical { + ff.config.MergeMode = mergeMode + } + return ff +} + +// HeaderPaddingBuilder configures header padding +type HeaderPaddingBuilder struct { + parent *HeaderConfigBuilder + config *tw.CellPadding + section string +} + +// Build returns the parent HeaderConfigBuilder +func (hp *HeaderPaddingBuilder) Build() *HeaderConfigBuilder { + return hp.parent +} + +// WithGlobal sets global padding +func (hp *HeaderPaddingBuilder) WithGlobal(padding tw.Padding) *HeaderPaddingBuilder { + hp.config.Global = padding + return hp +} + +// WithPerColumn sets per-column padding +func (hp *HeaderPaddingBuilder) WithPerColumn(padding []tw.Padding) *HeaderPaddingBuilder { + hp.config.PerColumn = padding + return hp +} + +// AddColumnPadding adds padding for a specific column in the header +func (hp *HeaderPaddingBuilder) AddColumnPadding(padding tw.Padding) *HeaderPaddingBuilder { + hp.config.PerColumn = append(hp.config.PerColumn, padding) + return hp +} + +// RowPaddingBuilder configures row padding +type RowPaddingBuilder struct { + parent *RowConfigBuilder + config *tw.CellPadding + section string +} + +// Build returns the parent RowConfigBuilder +func (rp *RowPaddingBuilder) Build() *RowConfigBuilder { + return rp.parent +} + +// WithGlobal sets global padding +func (rp *RowPaddingBuilder) WithGlobal(padding tw.Padding) *RowPaddingBuilder { + rp.config.Global = padding + return rp +} + +// WithPerColumn sets per-column padding +func (rp *RowPaddingBuilder) WithPerColumn(padding []tw.Padding) *RowPaddingBuilder { + rp.config.PerColumn = padding + return rp +} + +// AddColumnPadding adds padding for a specific column in the rows +func (rp *RowPaddingBuilder) AddColumnPadding(padding tw.Padding) *RowPaddingBuilder { + rp.config.PerColumn = append(rp.config.PerColumn, padding) + return rp +} + +// FooterPaddingBuilder configures footer padding +type FooterPaddingBuilder struct { + parent *FooterConfigBuilder + config *tw.CellPadding + section string +} + +// Build returns the parent FooterConfigBuilder +func (fp *FooterPaddingBuilder) Build() *FooterConfigBuilder { + return fp.parent +} + +// WithGlobal sets global padding +func (fp *FooterPaddingBuilder) WithGlobal(padding tw.Padding) *FooterPaddingBuilder { + fp.config.Global = padding + return fp +} + +// WithPerColumn sets per-column padding +func (fp *FooterPaddingBuilder) WithPerColumn(padding []tw.Padding) *FooterPaddingBuilder { + fp.config.PerColumn = padding + return fp +} + +// AddColumnPadding adds padding for a specific column in the footer +func (fp *FooterPaddingBuilder) AddColumnPadding(padding tw.Padding) *FooterPaddingBuilder { + fp.config.PerColumn = append(fp.config.PerColumn, padding) + return fp +} + +// BehaviorConfigBuilder configures behavior settings +type BehaviorConfigBuilder struct { + parent *ConfigBuilder + config *tw.Behavior +} + +// Build returns the parent ConfigBuilder +func (bb *BehaviorConfigBuilder) Build() *ConfigBuilder { + return bb.parent +} + +// WithAutoHide enables/disables auto-hide +func (bb *BehaviorConfigBuilder) WithAutoHide(state tw.State) *BehaviorConfigBuilder { + bb.config.AutoHide = state + return bb +} + +// WithTrimSpace enables/disables trim space +func (bb *BehaviorConfigBuilder) WithTrimSpace(state tw.State) *BehaviorConfigBuilder { + bb.config.TrimSpace = state + return bb +} + +// WithHeaderHide enables/disables header visibility +func (bb *BehaviorConfigBuilder) WithHeaderHide(state tw.State) *BehaviorConfigBuilder { + bb.config.Header.Hide = state + return bb +} + +// WithFooterHide enables/disables footer visibility +func (bb *BehaviorConfigBuilder) WithFooterHide(state tw.State) *BehaviorConfigBuilder { + bb.config.Footer.Hide = state + return bb +} + +// WithCompactMerge enables/disables compact width optimization for merged cells +func (bb *BehaviorConfigBuilder) WithCompactMerge(state tw.State) *BehaviorConfigBuilder { + bb.config.Compact.Merge = state + return bb +} + +// ColumnConfigBuilder configures column-specific settings +type ColumnConfigBuilder struct { + parent *ConfigBuilder + col int +} + +// Build returns the parent ConfigBuilder +func (c *ColumnConfigBuilder) Build() *ConfigBuilder { + return c.parent +} + +// WithAlignment sets alignment for the column +func (c *ColumnConfigBuilder) WithAlignment(align tw.Align) *ColumnConfigBuilder { + if err := align.Validate(); err == nil { + // Ensure slices are large enough + if len(c.parent.config.Header.Alignment.PerColumn) <= c.col { + newAligns := make([]tw.Align, c.col+1) + copy(newAligns, c.parent.config.Header.Alignment.PerColumn) + c.parent.config.Header.Alignment.PerColumn = newAligns + } + c.parent.config.Header.Alignment.PerColumn[c.col] = align + + if len(c.parent.config.Row.Alignment.PerColumn) <= c.col { + newAligns := make([]tw.Align, c.col+1) + copy(newAligns, c.parent.config.Row.Alignment.PerColumn) + c.parent.config.Row.Alignment.PerColumn = newAligns + } + c.parent.config.Row.Alignment.PerColumn[c.col] = align + + if len(c.parent.config.Footer.Alignment.PerColumn) <= c.col { + newAligns := make([]tw.Align, c.col+1) + copy(newAligns, c.parent.config.Footer.Alignment.PerColumn) + c.parent.config.Footer.Alignment.PerColumn = newAligns + } + c.parent.config.Footer.Alignment.PerColumn[c.col] = align + } + return c +} + +// WithMaxWidth sets max width for the column +func (c *ColumnConfigBuilder) WithMaxWidth(width int) *ColumnConfigBuilder { + if width >= 0 { + // Initialize maps if needed + if c.parent.config.Header.ColMaxWidths.PerColumn == nil { + c.parent.config.Header.ColMaxWidths.PerColumn = make(tw.Mapper[int, int]) + c.parent.config.Row.ColMaxWidths.PerColumn = make(tw.Mapper[int, int]) + c.parent.config.Footer.ColMaxWidths.PerColumn = make(tw.Mapper[int, int]) + } + c.parent.config.Header.ColMaxWidths.PerColumn[c.col] = width + c.parent.config.Row.ColMaxWidths.PerColumn[c.col] = width + c.parent.config.Footer.ColMaxWidths.PerColumn[c.col] = width + } + return c +} + +// HeaderFilterBuilder configures header filtering +type HeaderFilterBuilder struct { + parent *HeaderConfigBuilder + config *tw.CellFilter + section string +} + +// Build returns the parent HeaderConfigBuilder +func (hf *HeaderFilterBuilder) Build() *HeaderConfigBuilder { + return hf.parent +} + +// WithGlobal sets the global filter function for the header +func (hf *HeaderFilterBuilder) WithGlobal(filter func([]string) []string) *HeaderFilterBuilder { + if filter != nil { + hf.config.Global = filter + } + return hf +} + +// WithPerColumn sets per-column filter functions for the header +func (hf *HeaderFilterBuilder) WithPerColumn(filters []func(string) string) *HeaderFilterBuilder { + if len(filters) > 0 { + hf.config.PerColumn = filters + } + return hf +} + +// AddColumnFilter adds a filter function for a specific column in the header +func (hf *HeaderFilterBuilder) AddColumnFilter(filter func(string) string) *HeaderFilterBuilder { + if filter != nil { + hf.config.PerColumn = append(hf.config.PerColumn, filter) + } + return hf +} + +// RowFilterBuilder configures row filtering +type RowFilterBuilder struct { + parent *RowConfigBuilder + config *tw.CellFilter + section string +} + +// Build returns the parent RowConfigBuilder +func (rf *RowFilterBuilder) Build() *RowConfigBuilder { + return rf.parent +} + +// WithGlobal sets the global filter function for the rows +func (rf *RowFilterBuilder) WithGlobal(filter func([]string) []string) *RowFilterBuilder { + if filter != nil { + rf.config.Global = filter + } + return rf +} + +// WithPerColumn sets per-column filter functions for the rows +func (rf *RowFilterBuilder) WithPerColumn(filters []func(string) string) *RowFilterBuilder { + if len(filters) > 0 { + rf.config.PerColumn = filters + } + return rf +} + +// AddColumnFilter adds a filter function for a specific column in the rows +func (rf *RowFilterBuilder) AddColumnFilter(filter func(string) string) *RowFilterBuilder { + if filter != nil { + rf.config.PerColumn = append(rf.config.PerColumn, filter) + } + return rf +} + +// FooterFilterBuilder configures footer filtering +type FooterFilterBuilder struct { + parent *FooterConfigBuilder + config *tw.CellFilter + section string +} + +// Build returns the parent FooterConfigBuilder +func (ff *FooterFilterBuilder) Build() *FooterConfigBuilder { + return ff.parent +} + +// WithGlobal sets the global filter function for the footer +func (ff *FooterFilterBuilder) WithGlobal(filter func([]string) []string) *FooterFilterBuilder { + if filter != nil { + ff.config.Global = filter + } + return ff +} + +// WithPerColumn sets per-column filter functions for the footer +func (ff *FooterFilterBuilder) WithPerColumn(filters []func(string) string) *FooterFilterBuilder { + if len(filters) > 0 { + ff.config.PerColumn = filters + } + return ff +} + +// AddColumnFilter adds a filter function for a specific column in the footer +func (ff *FooterFilterBuilder) AddColumnFilter(filter func(string) string) *FooterFilterBuilder { + if filter != nil { + ff.config.PerColumn = append(ff.config.PerColumn, filter) + } + return ff +} + +// HeaderCallbacksBuilder configures header callbacks +type HeaderCallbacksBuilder struct { + parent *HeaderConfigBuilder + config *tw.CellCallbacks + section string +} + +// Build returns the parent HeaderConfigBuilder +func (hc *HeaderCallbacksBuilder) Build() *HeaderConfigBuilder { + return hc.parent +} + +// WithGlobal sets the global callback function for the header +func (hc *HeaderCallbacksBuilder) WithGlobal(callback func()) *HeaderCallbacksBuilder { + if callback != nil { + hc.config.Global = callback + } + return hc +} + +// WithPerColumn sets per-column callback functions for the header +func (hc *HeaderCallbacksBuilder) WithPerColumn(callbacks []func()) *HeaderCallbacksBuilder { + if len(callbacks) > 0 { + hc.config.PerColumn = callbacks + } + return hc +} + +// AddColumnCallback adds a callback function for a specific column in the header +func (hc *HeaderCallbacksBuilder) AddColumnCallback(callback func()) *HeaderCallbacksBuilder { + if callback != nil { + hc.config.PerColumn = append(hc.config.PerColumn, callback) + } + return hc +} + +// RowCallbacksBuilder configures row callbacks +type RowCallbacksBuilder struct { + parent *RowConfigBuilder + config *tw.CellCallbacks + section string +} + +// Build returns the parent RowConfigBuilder +func (rc *RowCallbacksBuilder) Build() *RowConfigBuilder { + return rc.parent +} + +// WithGlobal sets the global callback function for the rows +func (rc *RowCallbacksBuilder) WithGlobal(callback func()) *RowCallbacksBuilder { + if callback != nil { + rc.config.Global = callback + } + return rc +} + +// WithPerColumn sets per-column callback functions for the rows +func (rc *RowCallbacksBuilder) WithPerColumn(callbacks []func()) *RowCallbacksBuilder { + if len(callbacks) > 0 { + rc.config.PerColumn = callbacks + } + return rc +} + +// AddColumnCallback adds a callback function for a specific column in the rows +func (rc *RowCallbacksBuilder) AddColumnCallback(callback func()) *RowCallbacksBuilder { + if callback != nil { + rc.config.PerColumn = append(rc.config.PerColumn, callback) + } + return rc +} + +// FooterCallbacksBuilder configures footer callbacks +type FooterCallbacksBuilder struct { + parent *FooterConfigBuilder + config *tw.CellCallbacks + section string +} + +// Build returns the parent FooterConfigBuilder +func (fc *FooterCallbacksBuilder) Build() *FooterConfigBuilder { + return fc.parent +} + +// WithGlobal sets the global callback function for the footer +func (fc *FooterCallbacksBuilder) WithGlobal(callback func()) *FooterCallbacksBuilder { + if callback != nil { + fc.config.Global = callback + } + return fc +} + +// WithPerColumn sets per-column callback functions for the footer +func (fc *FooterCallbacksBuilder) WithPerColumn(callbacks []func()) *FooterCallbacksBuilder { + if len(callbacks) > 0 { + fc.config.PerColumn = callbacks + } + return fc +} + +// AddColumnCallback adds a callback function for a specific column in the footer +func (fc *FooterCallbacksBuilder) AddColumnCallback(callback func()) *FooterCallbacksBuilder { + if callback != nil { + fc.config.PerColumn = append(fc.config.PerColumn, callback) + } + return fc +} diff --git a/vendor/github.com/olekukonko/tablewriter/csv.go b/vendor/github.com/olekukonko/tablewriter/csv.go index 98878303..04263208 100644 --- a/vendor/github.com/olekukonko/tablewriter/csv.go +++ b/vendor/github.com/olekukonko/tablewriter/csv.go @@ -1,10 +1,3 @@ -// Copyright 2014 Oleku Konko All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. - -// This module is a Table Writer API for the Go Programming Language. -// The protocols were written in pure Go and works on windows and unix systems - package tablewriter import ( @@ -13,40 +6,89 @@ import ( "os" ) -// Start A new table by importing from a CSV file +// NewCSV Start A new table by importing from a CSV file // Takes io.Writer and csv File name -func NewCSV(writer io.Writer, fileName string, hasHeader bool) (*Table, error) { +func NewCSV(writer io.Writer, fileName string, hasHeader bool, opts ...Option) (*Table, error) { + // Open the CSV file file, err := os.Open(fileName) if err != nil { - return &Table{}, err + // Log implicitly handled by NewTable if logger is configured via opts + return nil, err // Return nil *Table on error } - defer file.Close() + defer file.Close() // Ensure file is closed + + // Create a CSV reader csvReader := csv.NewReader(file) - t, err := NewCSVReader(writer, csvReader, hasHeader) - return t, err + + // Delegate to NewCSVReader, passing through the options + return NewCSVReader(writer, csvReader, hasHeader, opts...) } -// Start a New Table Writer with csv.Reader +// NewCSVReader Start a New Table Writer with csv.Reader // This enables customisation such as reader.Comma = ';' // See http://golang.org/src/pkg/encoding/csv/reader.go?s=3213:3671#L94 -func NewCSVReader(writer io.Writer, csvReader *csv.Reader, hasHeader bool) (*Table, error) { - t := NewWriter(writer) +func NewCSVReader(writer io.Writer, csvReader *csv.Reader, hasHeader bool, opts ...Option) (*Table, error) { + // Create a new table instance using the modern API and provided options. + // Options configure the table's appearance and behavior (renderer, borders, etc.). + t := NewTable(writer, opts...) // Logger setup happens here if WithLogger/WithDebug is passed + + // Process header row if specified if hasHeader { - // Read the first row headers, err := csvReader.Read() if err != nil { - return &Table{}, err + // Handle EOF specifically: means the CSV was empty or contained only an empty header line. + if err == io.EOF { + t.logger.Debug("NewCSVReader: CSV empty or only header found (EOF after header read attempt).") + // Return the table configured by opts, but without data/header. + // It's ready for Render() which will likely output nothing or just borders if configured. + return t, nil + } + // Log other read errors + t.logger.Errorf("NewCSVReader: Error reading CSV header: %v", err) + return nil, err // Return nil *Table on critical read error + } + + // Check if the read header is genuinely empty (e.g., a blank line in the CSV) + isEmptyHeader := true + for _, h := range headers { + if h != "" { + isEmptyHeader = false + break + } + } + + if !isEmptyHeader { + t.Header(headers) // Use the Table method to set the header data + t.logger.Debugf("NewCSVReader: Header set from CSV: %v", headers) + } else { + t.logger.Debug("NewCSVReader: Read an empty header line, skipping setting table header.") } - t.SetHeader(headers) } + + // Process data rows + rowCount := 0 for { record, err := csvReader.Read() if err == io.EOF { - break - } else if err != nil { - return &Table{}, err + break // Reached the end of the CSV data + } + if err != nil { + // Log other read errors during data processing + t.logger.Errorf("NewCSVReader: Error reading CSV record: %v", err) + return nil, err // Return nil *Table on critical read error } - t.Append(record) + + // Append the record to the table's internal buffer (for batch rendering). + // The Table.Append method handles conversion and storage. + if appendErr := t.Append(record); appendErr != nil { + t.logger.Errorf("NewCSVReader: Error appending record #%d: %v", rowCount+1, appendErr) + // Decide if append error is fatal. For now, let's treat it as fatal. + return nil, appendErr + } + rowCount++ } + t.logger.Debugf("NewCSVReader: Finished reading CSV. Appended %d data rows.", rowCount) + + // Return the configured and populated table instance, ready for Render() call. return t, nil } diff --git a/vendor/github.com/olekukonko/tablewriter/deprecated.go b/vendor/github.com/olekukonko/tablewriter/deprecated.go new file mode 100644 index 00000000..aa119e48 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/deprecated.go @@ -0,0 +1,220 @@ +package tablewriter + +import ( + "github.com/olekukonko/tablewriter/tw" +) + +// WithBorders configures the table's border settings by updating the renderer's border configuration. +// This function is deprecated and will be removed in a future version. +// +// Deprecated: Use [WithRendition] to configure border settings for renderers that support +// [tw.Renditioning], or update the renderer's [tw.RenderConfig] directly via its Config() method. +// This function has no effect if no renderer is set on the table. +// +// Example migration: +// +// // Old (deprecated) +// table.Options(WithBorders(tw.Border{Top: true, Bottom: true})) +// // New (recommended) +// table.Options(WithRendition(tw.Rendition{Borders: tw.Border{Top: true, Bottom: true}})) +// +// Parameters: +// - borders: The [tw.Border] configuration to apply to the renderer's borders. +// +// Returns: +// +// An [Option] that updates the renderer's border settings if a renderer is set. +// Logs a debug message if debugging is enabled and a renderer is present. +func WithBorders(borders tw.Border) Option { + return func(target *Table) { + if target.renderer != nil { + cfg := target.renderer.Config() + cfg.Borders = borders + if target.logger != nil { + target.logger.Debugf("Option: WithBorders applied to Table: %+v", borders) + } + } + } +} + +// Behavior is an alias for [tw.Behavior] to configure table behavior settings. +// This type is deprecated and will be removed in a future version. +// +// Deprecated: Use [tw.Behavior] directly to configure settings such as auto-hiding empty +// columns, trimming spaces, or controlling header/footer visibility. +// +// Example migration: +// +// // Old (deprecated) +// var b tablewriter.Behavior = tablewriter.Behavior{AutoHide: tw.On} +// // New (recommended) +// var b tw.Behavior = tw.Behavior{AutoHide: tw.On} +type Behavior tw.Behavior + +// Settings is an alias for [tw.Settings] to configure renderer settings. +// This type is deprecated and will be removed in a future version. +// +// Deprecated: Use [tw.Settings] directly to configure renderer settings, such as +// separators and line styles. +// +// Example migration: +// +// // Old (deprecated) +// var s tablewriter.Settings = tablewriter.Settings{Separator: "|"} +// // New (recommended) +// var s tw.Settings = tw.Settings{Separator: "|"} +type Settings tw.Settings + +// WithRendererSettings updates the renderer's settings, such as separators and line styles. +// This function is deprecated and will be removed in a future version. +// +// Deprecated: Use [WithRendition] to update renderer settings for renderers that implement +// [tw.Renditioning], or configure the renderer's [tw.Settings] directly via its +// [tw.Renderer.Config] method. This function has no effect if no renderer is set. +// +// Example migration: +// +// // Old (deprecated) +// table.Options(WithRendererSettings(tw.Settings{Separator: "|"})) +// // New (recommended) +// table.Options(WithRendition(tw.Rendition{Settings: tw.Settings{Separator: "|"}})) +// +// Parameters: +// - settings: The [tw.Settings] configuration to apply to the renderer. +// +// Returns: +// +// An [Option] that updates the renderer's settings if a renderer is set. +// Logs a debug message if debugging is enabled and a renderer is present. +func WithRendererSettings(settings tw.Settings) Option { + return func(target *Table) { + if target.renderer != nil { + cfg := target.renderer.Config() + cfg.Settings = settings + if target.logger != nil { + target.logger.Debugf("Option: WithRendererSettings applied to Table: %+v", settings) + } + } + } +} + +// WithAlignment sets the text alignment for footer cells within the formatting configuration. +// This method is deprecated and will be removed in the next version. +// +// Deprecated: Use [FooterConfigBuilder.Alignment] with [AlignmentConfigBuilder.WithGlobal] +// or [AlignmentConfigBuilder.WithPerColumn] to configure footer alignments. +// Alternatively, apply a complete [tw.CellAlignment] configuration using +// [WithFooterAlignmentConfig]. +// +// Example migration: +// +// // Old (deprecated) +// builder.Footer().Formatting().WithAlignment(tw.AlignRight) +// // New (recommended) +// builder.Footer().Alignment().WithGlobal(tw.AlignRight) +// // Or +// table.Options(WithFooterAlignmentConfig(tw.CellAlignment{Global: tw.AlignRight})) +// +// Parameters: +// - align: The [tw.Align] value to set for footer cells. Valid values are +// [tw.AlignLeft], [tw.AlignRight], [tw.AlignCenter], and [tw.AlignNone]. +// Invalid alignments are ignored. +// +// Returns: +// +// The [FooterFormattingBuilder] instance for method chaining. +func (ff *FooterFormattingBuilder) WithAlignment(align tw.Align) *FooterFormattingBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return ff + } + ff.config.Alignment = align + return ff +} + +// WithAlignment sets the text alignment for header cells within the formatting configuration. +// This method is deprecated and will be removed in the next version. +// +// Deprecated: Use [HeaderConfigBuilder.Alignment] with [AlignmentConfigBuilder.WithGlobal] +// or [AlignmentConfigBuilder.WithPerColumn] to configure header alignments. +// Alternatively, apply a complete [tw.CellAlignment] configuration using +// [WithHeaderAlignmentConfig]. +// +// Example migration: +// +// // Old (deprecated) +// builder.Header().Formatting().WithAlignment(tw.AlignCenter) +// // New (recommended) +// builder.Header().Alignment().WithGlobal(tw.AlignCenter) +// // Or +// table.Options(WithHeaderAlignmentConfig(tw.CellAlignment{Global: tw.AlignCenter})) +// +// Parameters: +// - align: The [tw.Align] value to set for header cells. Valid values are +// [tw.AlignLeft], [tw.AlignRight], [tw.AlignCenter], and [tw.AlignNone]. +// Invalid alignments are ignored. +// +// Returns: +// +// The [HeaderFormattingBuilder] instance for method chaining. +func (hf *HeaderFormattingBuilder) WithAlignment(align tw.Align) *HeaderFormattingBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return hf + } + hf.config.Alignment = align + return hf +} + +// WithAlignment sets the text alignment for row cells within the formatting configuration. +// This method is deprecated and will be removed in the next version. +// +// Deprecated: Use [RowConfigBuilder.Alignment] with [AlignmentConfigBuilder.WithGlobal] +// or [AlignmentConfigBuilder.WithPerColumn] to configure row alignments. +// Alternatively, apply a complete [tw.CellAlignment] configuration using +// [WithRowAlignmentConfig]. +// +// Example migration: +// +// // Old (deprecated) +// builder.Row().Formatting().WithAlignment(tw.AlignLeft) +// // New (recommended) +// builder.Row().Alignment().WithGlobal(tw.AlignLeft) +// // Or +// table.Options(WithRowAlignmentConfig(tw.CellAlignment{Global: tw.AlignLeft})) +// +// Parameters: +// - align: The [tw.Align] value to set for row cells. Valid values are +// [tw.AlignLeft], [tw.AlignRight], [tw.AlignCenter], and [tw.AlignNone]. +// Invalid alignments are ignored. +// +// Returns: +// +// The [RowFormattingBuilder] instance for method chaining. +func (rf *RowFormattingBuilder) WithAlignment(align tw.Align) *RowFormattingBuilder { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return rf + } + rf.config.Alignment = align + return rf +} + +// WithTableMax sets the maximum width of the entire table in characters. +// Negative values are ignored, and the change is logged if debugging is enabled. +// The width constrains the table's rendering, potentially causing text wrapping or truncation +// based on the configuration's wrapping settings (e.g., tw.WrapTruncate). +// If debug logging is enabled via WithDebug(true), the applied width is logged. +// +// Deprecated: Use WithMaxWidth instead, which provides the same functionality with a clearer name +// and consistent naming across the package. For example: +// +// tablewriter.NewTable(os.Stdout, tablewriter.WithMaxWidth(80)) +func WithTableMax(width int) Option { + return func(target *Table) { + if width < 0 { + return + } + target.config.MaxWidth = width + if target.logger != nil { + target.logger.Debugf("Option: WithTableMax applied to Table: %v", width) + } + } +} diff --git a/vendor/github.com/olekukonko/tablewriter/option.go b/vendor/github.com/olekukonko/tablewriter/option.go new file mode 100644 index 00000000..7270b768 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/option.go @@ -0,0 +1,891 @@ +package tablewriter + +import ( + "github.com/mattn/go-runewidth" + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "github.com/olekukonko/tablewriter/tw" + "reflect" +) + +// Option defines a function type for configuring a Table instance. +type Option func(target *Table) + +// WithAutoHide enables or disables automatic hiding of columns with empty data rows. +// Logs the change if debugging is enabled. +func WithAutoHide(state tw.State) Option { + return func(target *Table) { + target.config.Behavior.AutoHide = state + if target.logger != nil { + target.logger.Debugf("Option: WithAutoHide applied to Table: %v", state) + } + } +} + +// WithColumnMax sets a global maximum column width for the table in streaming mode. +// Negative values are ignored, and the change is logged if debugging is enabled. +func WithColumnMax(width int) Option { + return func(target *Table) { + if width < 0 { + return + } + target.config.Widths.Global = width + if target.logger != nil { + target.logger.Debugf("Option: WithColumnMax applied to Table: %v", width) + } + } +} + +// WithMaxWidth sets a global maximum table width for the table. +// Negative values are ignored, and the change is logged if debugging is enabled. +func WithMaxWidth(width int) Option { + return func(target *Table) { + if width < 0 { + return + } + target.config.MaxWidth = width + if target.logger != nil { + target.logger.Debugf("Option: WithTableMax applied to Table: %v", width) + } + } +} + +// WithWidths sets per-column widths for the table. +// Negative widths are removed, and the change is logged if debugging is enabled. +func WithWidths(width tw.CellWidth) Option { + return func(target *Table) { + target.config.Widths = width + if target.logger != nil { + target.logger.Debugf("Option: WithColumnWidths applied to Table: %v", width) + } + } +} + +// WithColumnWidths sets per-column widths for the table. +// Negative widths are removed, and the change is logged if debugging is enabled. +func WithColumnWidths(widths tw.Mapper[int, int]) Option { + return func(target *Table) { + for k, v := range widths { + if v < 0 { + delete(widths, k) + } + } + target.config.Widths.PerColumn = widths + if target.logger != nil { + target.logger.Debugf("Option: WithColumnWidths applied to Table: %v", widths) + } + } +} + +// WithConfig applies a custom configuration to the table by merging it with the default configuration. +func WithConfig(cfg Config) Option { + return func(target *Table) { + target.config = mergeConfig(defaultConfig(), cfg) + } +} + +// WithDebug enables or disables debug logging and adjusts the logger level accordingly. +// Logs the change if debugging is enabled. +func WithDebug(debug bool) Option { + return func(target *Table) { + target.config.Debug = debug + } +} + +// WithFooter sets the table footers by calling the Footer method. +func WithFooter(footers []string) Option { + return func(target *Table) { + target.Footer(footers) + } +} + +// WithFooterConfig applies a full footer configuration to the table. +// Logs the change if debugging is enabled. +func WithFooterConfig(config tw.CellConfig) Option { + return func(target *Table) { + target.config.Footer = config + if target.logger != nil { + target.logger.Debug("Option: WithFooterConfig applied to Table.") + } + } +} + +// WithFooterAlignmentConfig applies a footer alignment configuration to the table. +// Logs the change if debugging is enabled. +func WithFooterAlignmentConfig(alignment tw.CellAlignment) Option { + return func(target *Table) { + target.config.Footer.Alignment = alignment + if target.logger != nil { + target.logger.Debugf("Option: WithFooterAlignmentConfig applied to Table: %+v", alignment) + } + } +} + +// WithFooterMergeMode sets the merge mode for footer cells. +// Invalid merge modes are ignored, and the change is logged if debugging is enabled. +func WithFooterMergeMode(mergeMode int) Option { + return func(target *Table) { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return + } + target.config.Footer.Formatting.MergeMode = mergeMode + if target.logger != nil { + target.logger.Debugf("Option: WithFooterMergeMode applied to Table: %v", mergeMode) + } + } +} + +// WithFooterAutoWrap sets the wrapping behavior for footer cells. +// Invalid wrap modes are ignored, and the change is logged if debugging is enabled. +func WithFooterAutoWrap(wrap int) Option { + return func(target *Table) { + if wrap < tw.WrapNone || wrap > tw.WrapBreak { + return + } + target.config.Footer.Formatting.AutoWrap = wrap + if target.logger != nil { + target.logger.Debugf("Option: WithFooterAutoWrap applied to Table: %v", wrap) + } + } +} + +// WithFooterFilter sets the filter configuration for footer cells. +// Logs the change if debugging is enabled. +func WithFooterFilter(filter tw.CellFilter) Option { + return func(target *Table) { + target.config.Footer.Filter = filter + if target.logger != nil { + target.logger.Debug("Option: WithFooterFilter applied to Table.") + } + } +} + +// WithFooterCallbacks sets the callback configuration for footer cells. +// Logs the change if debugging is enabled. +func WithFooterCallbacks(callbacks tw.CellCallbacks) Option { + return func(target *Table) { + target.config.Footer.Callbacks = callbacks + if target.logger != nil { + target.logger.Debug("Option: WithFooterCallbacks applied to Table.") + } + } +} + +// WithFooterPaddingPerColumn sets per-column padding for footer cells. +// Logs the change if debugging is enabled. +func WithFooterPaddingPerColumn(padding []tw.Padding) Option { + return func(target *Table) { + target.config.Footer.Padding.PerColumn = padding + if target.logger != nil { + target.logger.Debugf("Option: WithFooterPaddingPerColumn applied to Table: %+v", padding) + } + } +} + +// WithFooterMaxWidth sets the maximum content width for footer cells. +// Negative values are ignored, and the change is logged if debugging is enabled. +func WithFooterMaxWidth(maxWidth int) Option { + return func(target *Table) { + if maxWidth < 0 { + return + } + target.config.Footer.ColMaxWidths.Global = maxWidth + if target.logger != nil { + target.logger.Debugf("Option: WithFooterMaxWidth applied to Table: %v", maxWidth) + } + } +} + +// WithHeader sets the table headers by calling the Header method. +func WithHeader(headers []string) Option { + return func(target *Table) { + target.Header(headers) + } +} + +// WithHeaderAlignment sets the text alignment for header cells. +// Invalid alignments are ignored, and the change is logged if debugging is enabled. +func WithHeaderAlignment(align tw.Align) Option { + return func(target *Table) { + if align != tw.AlignLeft && align != tw.AlignRight && align != tw.AlignCenter && align != tw.AlignNone { + return + } + target.config.Header.Alignment.Global = align + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderAlignment applied to Table: %v", align) + } + } +} + +// WithHeaderAutoWrap sets the wrapping behavior for header cells. +// Invalid wrap modes are ignored, and the change is logged if debugging is enabled. +func WithHeaderAutoWrap(wrap int) Option { + return func(target *Table) { + if wrap < tw.WrapNone || wrap > tw.WrapBreak { + return + } + target.config.Header.Formatting.AutoWrap = wrap + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderAutoWrap applied to Table: %v", wrap) + } + } +} + +// WithHeaderMergeMode sets the merge mode for header cells. +// Invalid merge modes are ignored, and the change is logged if debugging is enabled. +func WithHeaderMergeMode(mergeMode int) Option { + return func(target *Table) { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return + } + target.config.Header.Formatting.MergeMode = mergeMode + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderMergeMode applied to Table: %v", mergeMode) + } + } +} + +// WithHeaderFilter sets the filter configuration for header cells. +// Logs the change if debugging is enabled. +func WithHeaderFilter(filter tw.CellFilter) Option { + return func(target *Table) { + target.config.Header.Filter = filter + if target.logger != nil { + target.logger.Debug("Option: WithHeaderFilter applied to Table.") + } + } +} + +// WithHeaderCallbacks sets the callback configuration for header cells. +// Logs the change if debugging is enabled. +func WithHeaderCallbacks(callbacks tw.CellCallbacks) Option { + return func(target *Table) { + target.config.Header.Callbacks = callbacks + if target.logger != nil { + target.logger.Debug("Option: WithHeaderCallbacks applied to Table.") + } + } +} + +// WithHeaderPaddingPerColumn sets per-column padding for header cells. +// Logs the change if debugging is enabled. +func WithHeaderPaddingPerColumn(padding []tw.Padding) Option { + return func(target *Table) { + target.config.Header.Padding.PerColumn = padding + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderPaddingPerColumn applied to Table: %+v", padding) + } + } +} + +// WithHeaderMaxWidth sets the maximum content width for header cells. +// Negative values are ignored, and the change is logged if debugging is enabled. +func WithHeaderMaxWidth(maxWidth int) Option { + return func(target *Table) { + if maxWidth < 0 { + return + } + target.config.Header.ColMaxWidths.Global = maxWidth + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderMaxWidth applied to Table: %v", maxWidth) + } + } +} + +// WithRowAlignment sets the text alignment for row cells. +// Invalid alignments are ignored, and the change is logged if debugging is enabled. +func WithRowAlignment(align tw.Align) Option { + return func(target *Table) { + if err := align.Validate(); err != nil { + return + } + target.config.Row.Alignment.Global = align + if target.logger != nil { + target.logger.Debugf("Option: WithRowAlignment applied to Table: %v", align) + } + } +} + +// WithRowAutoWrap sets the wrapping behavior for row cells. +// Invalid wrap modes are ignored, and the change is logged if debugging is enabled. +func WithRowAutoWrap(wrap int) Option { + return func(target *Table) { + if wrap < tw.WrapNone || wrap > tw.WrapBreak { + return + } + target.config.Row.Formatting.AutoWrap = wrap + if target.logger != nil { + target.logger.Debugf("Option: WithRowAutoWrap applied to Table: %v", wrap) + } + } +} + +// WithRowMergeMode sets the merge mode for row cells. +// Invalid merge modes are ignored, and the change is logged if debugging is enabled. +func WithRowMergeMode(mergeMode int) Option { + return func(target *Table) { + if mergeMode < tw.MergeNone || mergeMode > tw.MergeHierarchical { + return + } + target.config.Row.Formatting.MergeMode = mergeMode + if target.logger != nil { + target.logger.Debugf("Option: WithRowMergeMode applied to Table: %v", mergeMode) + } + } +} + +// WithRowFilter sets the filter configuration for row cells. +// Logs the change if debugging is enabled. +func WithRowFilter(filter tw.CellFilter) Option { + return func(target *Table) { + target.config.Row.Filter = filter + if target.logger != nil { + target.logger.Debug("Option: WithRowFilter applied to Table.") + } + } +} + +// WithRowCallbacks sets the callback configuration for row cells. +// Logs the change if debugging is enabled. +func WithRowCallbacks(callbacks tw.CellCallbacks) Option { + return func(target *Table) { + target.config.Row.Callbacks = callbacks + if target.logger != nil { + target.logger.Debug("Option: WithRowCallbacks applied to Table.") + } + } +} + +// WithRowPaddingPerColumn sets per-column padding for row cells. +// Logs the change if debugging is enabled. +func WithRowPaddingPerColumn(padding []tw.Padding) Option { + return func(target *Table) { + target.config.Row.Padding.PerColumn = padding + if target.logger != nil { + target.logger.Debugf("Option: WithRowPaddingPerColumn applied to Table: %+v", padding) + } + } +} + +// WithHeaderAlignmentConfig applies a header alignment configuration to the table. +// Logs the change if debugging is enabled. +func WithHeaderAlignmentConfig(alignment tw.CellAlignment) Option { + return func(target *Table) { + target.config.Header.Alignment = alignment + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderAlignmentConfig applied to Table: %+v", alignment) + } + } +} + +// WithHeaderConfig applies a full header configuration to the table. +// Logs the change if debugging is enabled. +func WithHeaderConfig(config tw.CellConfig) Option { + return func(target *Table) { + target.config.Header = config + if target.logger != nil { + target.logger.Debug("Option: WithHeaderConfig applied to Table.") + } + } +} + +// WithLogger sets a custom logger for the table and updates the renderer if present. +// Logs the change if debugging is enabled. +func WithLogger(logger *ll.Logger) Option { + return func(target *Table) { + target.logger = logger + if target.logger != nil { + target.logger.Debug("Option: WithLogger applied to Table.") + if target.renderer != nil { + target.renderer.Logger(target.logger) + } + } + } +} + +// WithRenderer sets a custom renderer for the table and attaches the logger if present. +// Logs the change if debugging is enabled. +func WithRenderer(f tw.Renderer) Option { + return func(target *Table) { + target.renderer = f + if target.logger != nil { + target.logger.Debugf("Option: WithRenderer applied to Table: %T", f) + f.Logger(target.logger) + } + } +} + +// WithRowConfig applies a full row configuration to the table. +// Logs the change if debugging is enabled. +func WithRowConfig(config tw.CellConfig) Option { + return func(target *Table) { + target.config.Row = config + if target.logger != nil { + target.logger.Debug("Option: WithRowConfig applied to Table.") + } + } +} + +// WithRowAlignmentConfig applies a row alignment configuration to the table. +// Logs the change if debugging is enabled. +func WithRowAlignmentConfig(alignment tw.CellAlignment) Option { + return func(target *Table) { + target.config.Row.Alignment = alignment + if target.logger != nil { + target.logger.Debugf("Option: WithRowAlignmentConfig applied to Table: %+v", alignment) + } + } +} + +// WithRowMaxWidth sets the maximum content width for row cells. +// Negative values are ignored, and the change is logged if debugging is enabled. +func WithRowMaxWidth(maxWidth int) Option { + return func(target *Table) { + if maxWidth < 0 { + return + } + target.config.Row.ColMaxWidths.Global = maxWidth + if target.logger != nil { + target.logger.Debugf("Option: WithRowMaxWidth applied to Table: %v", maxWidth) + } + } +} + +// WithStreaming applies a streaming configuration to the table by merging it with the existing configuration. +// Logs the change if debugging is enabled. +func WithStreaming(c tw.StreamConfig) Option { + return func(target *Table) { + target.config.Stream = mergeStreamConfig(target.config.Stream, c) + if target.logger != nil { + target.logger.Debug("Option: WithStreaming applied to Table.") + } + } +} + +// WithStringer sets a custom stringer function for converting row data and clears the stringer cache. +// Logs the change if debugging is enabled. +func WithStringer(stringer interface{}) Option { + return func(t *Table) { + t.stringer = stringer + t.stringerCacheMu.Lock() + t.stringerCache = make(map[reflect.Type]reflect.Value) + t.stringerCacheMu.Unlock() + if t.logger != nil { + t.logger.Debug("Stringer updated, cache cleared") + } + } +} + +// WithStringerCache enables caching for the stringer function. +// Logs the change if debugging is enabled. +func WithStringerCache() Option { + return func(t *Table) { + t.stringerCacheEnabled = true + if t.logger != nil { + t.logger.Debug("Option: WithStringerCache enabled") + } + } +} + +// WithTrimSpace sets whether leading and trailing spaces are automatically trimmed. +// Logs the change if debugging is enabled. +func WithTrimSpace(state tw.State) Option { + return func(target *Table) { + target.config.Behavior.TrimSpace = state + if target.logger != nil { + target.logger.Debugf("Option: WithTrimSpace applied to Table: %v", state) + } + } +} + +// WithHeaderAutoFormat enables or disables automatic formatting for header cells. +// Logs the change if debugging is enabled. +func WithHeaderAutoFormat(state tw.State) Option { + return func(target *Table) { + target.config.Header.Formatting.AutoFormat = state + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderAutoFormat applied to Table: %v", state) + } + } +} + +// WithFooterAutoFormat enables or disables automatic formatting for footer cells. +// Logs the change if debugging is enabled. +func WithFooterAutoFormat(state tw.State) Option { + return func(target *Table) { + target.config.Footer.Formatting.AutoFormat = state + if target.logger != nil { + target.logger.Debugf("Option: WithFooterAutoFormat applied to Table: %v", state) + } + } +} + +// WithRowAutoFormat enables or disables automatic formatting for row cells. +// Logs the change if debugging is enabled. +func WithRowAutoFormat(state tw.State) Option { + return func(target *Table) { + target.config.Row.Formatting.AutoFormat = state + if target.logger != nil { + target.logger.Debugf("Option: WithRowAutoFormat applied to Table: %v", state) + } + } +} + +// WithHeaderControl sets the control behavior for the table header. +// Logs the change if debugging is enabled. +func WithHeaderControl(control tw.Control) Option { + return func(target *Table) { + target.config.Behavior.Header = control + if target.logger != nil { + target.logger.Debugf("Option: WithHeaderControl applied to Table: %v", control) + } + } +} + +// WithFooterControl sets the control behavior for the table footer. +// Logs the change if debugging is enabled. +func WithFooterControl(control tw.Control) Option { + return func(target *Table) { + target.config.Behavior.Footer = control + if target.logger != nil { + target.logger.Debugf("Option: WithFooterControl applied to Table: %v", control) + } + } +} + +// WithAlignment sets the default column alignment for the header, rows, and footer. +// Logs the change if debugging is enabled. +func WithAlignment(alignment tw.Alignment) Option { + return func(target *Table) { + target.config.Header.Alignment.PerColumn = alignment + target.config.Row.Alignment.PerColumn = alignment + target.config.Footer.Alignment.PerColumn = alignment + if target.logger != nil { + target.logger.Debugf("Option: WithAlignment applied to Table: %+v", alignment) + } + } +} + +// WithBehavior applies a behavior configuration to the table. +// Logs the change if debugging is enabled. +func WithBehavior(behavior tw.Behavior) Option { + return func(target *Table) { + target.config.Behavior = behavior + if target.logger != nil { + target.logger.Debugf("Option: WithBehavior applied to Table: %+v", behavior) + } + } +} + +// WithPadding sets the global padding for the header, rows, and footer. +// Logs the change if debugging is enabled. +func WithPadding(padding tw.Padding) Option { + return func(target *Table) { + target.config.Header.Padding.Global = padding + target.config.Row.Padding.Global = padding + target.config.Footer.Padding.Global = padding + if target.logger != nil { + target.logger.Debugf("Option: WithPadding applied to Table: %+v", padding) + } + } +} + +// WithRendition allows updating the active renderer's rendition configuration +// by merging the provided rendition. +// If the renderer does not implement tw.Renditioning, a warning is logged. +// Logs the change if debugging is enabled. +func WithRendition(rendition tw.Rendition) Option { + return func(target *Table) { + if target.renderer == nil { + if target.logger != nil { + target.logger.Warn("Option: WithRendition: No renderer set on table.") + } + return + } + if ru, ok := target.renderer.(tw.Renditioning); ok { + ru.Rendition(rendition) + if target.logger != nil { + target.logger.Debugf("Option: WithRendition: Applied to renderer via Renditioning.SetRendition(): %+v", rendition) + } + } else { + if target.logger != nil { + target.logger.Warnf("Option: WithRendition: Current renderer type %T does not implement tw.Renditioning. Rendition may not be applied as expected.", target.renderer) + } + } + } +} + +// WithEastAsian configures the global East Asian width calculation setting. +// - enable=true: Enables East Asian width calculations. CJK and ambiguous characters +// are typically measured as double width. +// - enable=false: Disables East Asian width calculations. Characters are generally +// measured as single width, subject to Unicode standards. +// +// This setting affects all subsequent display width calculations using the twdw package. +func WithEastAsian(enable bool) Option { + return func(target *Table) { + twwidth.SetEastAsian(enable) + } +} + +// WithCondition provides a way to set a custom global runewidth.Condition +// that will be used for all subsequent display width calculations by the twwidth (twdw) package. +// +// The runewidth.Condition object allows for more fine-grained control over how rune widths +// are determined, beyond just toggling EastAsianWidth. This could include settings for +// ambiguous width characters or other future properties of runewidth.Condition. +func WithCondition(condition *runewidth.Condition) Option { + return func(target *Table) { + twwidth.SetCondition(condition) + } +} + +// WithSymbols sets the symbols used for drawing table borders and separators. +// The symbols are applied to the table's renderer configuration, if a renderer is set. +// If no renderer is set (target.renderer is nil), this option has no effect. . +func WithSymbols(symbols tw.Symbols) Option { + return func(target *Table) { + if target.renderer != nil { + cfg := target.renderer.Config() + cfg.Symbols = symbols + + if ru, ok := target.renderer.(tw.Renditioning); ok { + ru.Rendition(cfg) + if target.logger != nil { + target.logger.Debugf("Option: WithRendition: Applied to renderer via Renditioning.SetRendition(): %+v", cfg) + } + } else { + if target.logger != nil { + target.logger.Warnf("Option: WithRendition: Current renderer type %T does not implement tw.Renditioning. Rendition may not be applied as expected.", target.renderer) + } + } + } + } +} + +// defaultConfig returns a default Config with sensible settings for headers, rows, footers, and behavior. +func defaultConfig() Config { + return Config{ + MaxWidth: 0, + Header: tw.CellConfig{ + Formatting: tw.CellFormatting{ + AutoWrap: tw.WrapTruncate, + AutoFormat: tw.On, + MergeMode: tw.MergeNone, + }, + Padding: tw.CellPadding{ + Global: tw.PaddingDefault, + }, + Alignment: tw.CellAlignment{ + Global: tw.AlignCenter, + PerColumn: []tw.Align{}, + }, + }, + Row: tw.CellConfig{ + Formatting: tw.CellFormatting{ + AutoWrap: tw.WrapNormal, + AutoFormat: tw.Off, + MergeMode: tw.MergeNone, + }, + Padding: tw.CellPadding{ + Global: tw.PaddingDefault, + }, + Alignment: tw.CellAlignment{ + Global: tw.AlignLeft, + PerColumn: []tw.Align{}, + }, + }, + Footer: tw.CellConfig{ + Formatting: tw.CellFormatting{ + AutoWrap: tw.WrapNormal, + AutoFormat: tw.Off, + MergeMode: tw.MergeNone, + }, + Padding: tw.CellPadding{ + Global: tw.PaddingDefault, + }, + Alignment: tw.CellAlignment{ + Global: tw.AlignRight, + PerColumn: []tw.Align{}, + }, + }, + Stream: tw.StreamConfig{ + Enable: false, + StrictColumns: false, + }, + Debug: false, + Behavior: tw.Behavior{ + AutoHide: tw.Off, + TrimSpace: tw.On, + }, + } +} + +// mergeCellConfig merges a source CellConfig into a destination CellConfig, prioritizing non-default source values. +// It handles deep merging for complex fields like padding and callbacks. +func mergeCellConfig(dst, src tw.CellConfig) tw.CellConfig { + if src.Formatting.Alignment != tw.Empty { + dst.Formatting.Alignment = src.Formatting.Alignment + } + + if src.Formatting.AutoWrap != 0 { + dst.Formatting.AutoWrap = src.Formatting.AutoWrap + } + if src.ColMaxWidths.Global != 0 { + dst.ColMaxWidths.Global = src.ColMaxWidths.Global + } + if src.Formatting.MergeMode != 0 { + dst.Formatting.MergeMode = src.Formatting.MergeMode + } + + dst.Formatting.AutoFormat = src.Formatting.AutoFormat + + if src.Padding.Global.Paddable() { + dst.Padding.Global = src.Padding.Global + } + + if len(src.Padding.PerColumn) > 0 { + if dst.Padding.PerColumn == nil { + dst.Padding.PerColumn = make([]tw.Padding, len(src.Padding.PerColumn)) + } else if len(src.Padding.PerColumn) > len(dst.Padding.PerColumn) { + dst.Padding.PerColumn = append(dst.Padding.PerColumn, make([]tw.Padding, len(src.Padding.PerColumn)-len(dst.Padding.PerColumn))...) + } + for i, pad := range src.Padding.PerColumn { + if pad.Paddable() { + dst.Padding.PerColumn[i] = pad + } + } + } + if src.Callbacks.Global != nil { + dst.Callbacks.Global = src.Callbacks.Global + } + if len(src.Callbacks.PerColumn) > 0 { + if dst.Callbacks.PerColumn == nil { + dst.Callbacks.PerColumn = make([]func(), len(src.Callbacks.PerColumn)) + } else if len(src.Callbacks.PerColumn) > len(dst.Callbacks.PerColumn) { + dst.Callbacks.PerColumn = append(dst.Callbacks.PerColumn, make([]func(), len(src.Callbacks.PerColumn)-len(dst.Callbacks.PerColumn))...) + } + for i, cb := range src.Callbacks.PerColumn { + if cb != nil { + dst.Callbacks.PerColumn[i] = cb + } + } + } + if src.Filter.Global != nil { + dst.Filter.Global = src.Filter.Global + } + if len(src.Filter.PerColumn) > 0 { + if dst.Filter.PerColumn == nil { + dst.Filter.PerColumn = make([]func(string) string, len(src.Filter.PerColumn)) + } else if len(src.Filter.PerColumn) > len(dst.Filter.PerColumn) { + dst.Filter.PerColumn = append(dst.Filter.PerColumn, make([]func(string) string, len(src.Filter.PerColumn)-len(dst.Filter.PerColumn))...) + } + for i, filter := range src.Filter.PerColumn { + if filter != nil { + dst.Filter.PerColumn[i] = filter + } + } + } + + // Merge Alignment + if src.Alignment.Global != tw.Empty { + dst.Alignment.Global = src.Alignment.Global + } + + if len(src.Alignment.PerColumn) > 0 { + if dst.Alignment.PerColumn == nil { + dst.Alignment.PerColumn = make([]tw.Align, len(src.Alignment.PerColumn)) + } else if len(src.Alignment.PerColumn) > len(dst.Alignment.PerColumn) { + dst.Alignment.PerColumn = append(dst.Alignment.PerColumn, make([]tw.Align, len(src.Alignment.PerColumn)-len(dst.Alignment.PerColumn))...) + } + for i, align := range src.Alignment.PerColumn { + if align != tw.Skip { + dst.Alignment.PerColumn[i] = align + } + } + } + + if len(src.ColumnAligns) > 0 { + if dst.ColumnAligns == nil { + dst.ColumnAligns = make([]tw.Align, len(src.ColumnAligns)) + } else if len(src.ColumnAligns) > len(dst.ColumnAligns) { + dst.ColumnAligns = append(dst.ColumnAligns, make([]tw.Align, len(src.ColumnAligns)-len(dst.ColumnAligns))...) + } + for i, align := range src.ColumnAligns { + if align != tw.Skip { + dst.ColumnAligns[i] = align + } + } + } + + if len(src.ColMaxWidths.PerColumn) > 0 { + if dst.ColMaxWidths.PerColumn == nil { + dst.ColMaxWidths.PerColumn = make(map[int]int) + } + for k, v := range src.ColMaxWidths.PerColumn { + if v != 0 { + dst.ColMaxWidths.PerColumn[k] = v + } + } + } + return dst +} + +// mergeConfig merges a source Config into a destination Config, prioritizing non-default source values. +// It performs deep merging for complex types like Header, Row, Footer, and Stream. +func mergeConfig(dst, src Config) Config { + if src.MaxWidth != 0 { + dst.MaxWidth = src.MaxWidth + } + + dst.Debug = src.Debug || dst.Debug + dst.Behavior.AutoHide = src.Behavior.AutoHide + dst.Behavior.TrimSpace = src.Behavior.TrimSpace + dst.Behavior.Compact = src.Behavior.Compact + dst.Behavior.Header = src.Behavior.Header + dst.Behavior.Footer = src.Behavior.Footer + + if src.Widths.Global != 0 { + dst.Widths.Global = src.Widths.Global + } + if len(src.Widths.PerColumn) > 0 { + if dst.Widths.PerColumn == nil { + dst.Widths.PerColumn = make(map[int]int) + } + for k, v := range src.Widths.PerColumn { + if v != 0 { + dst.Widths.PerColumn[k] = v + } + } + } + + dst.Header = mergeCellConfig(dst.Header, src.Header) + dst.Row = mergeCellConfig(dst.Row, src.Row) + dst.Footer = mergeCellConfig(dst.Footer, src.Footer) + dst.Stream = mergeStreamConfig(dst.Stream, src.Stream) + + return dst +} + +// mergeStreamConfig merges a source StreamConfig into a destination StreamConfig, prioritizing non-default source values. +func mergeStreamConfig(dst, src tw.StreamConfig) tw.StreamConfig { + if src.Enable { + dst.Enable = true + } + + dst.StrictColumns = src.StrictColumns + return dst +} + +// padLine pads a line to the specified column count by appending empty strings as needed. +func padLine(line []string, numCols int) []string { + if len(line) >= numCols { + return line + } + padded := make([]string, numCols) + copy(padded, line) + for i := len(line); i < numCols; i++ { + padded[i] = tw.Empty + } + return padded +} diff --git a/vendor/github.com/olekukonko/tablewriter/pkg/twwarp/wrap.go b/vendor/github.com/olekukonko/tablewriter/pkg/twwarp/wrap.go new file mode 100644 index 00000000..a577c1eb --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/pkg/twwarp/wrap.go @@ -0,0 +1,237 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package twwarp + +import ( + "math" + "strings" + "unicode" + + "github.com/olekukonko/tablewriter/pkg/twwidth" // IMPORT YOUR NEW PACKAGE + "github.com/rivo/uniseg" + // "github.com/mattn/go-runewidth" // This can be removed if all direct uses are gone +) + +const ( + nl = "\n" + sp = " " +) + +const defaultPenalty = 1e5 + +func SplitWords(s string) []string { + words := make([]string, 0, len(s)/5) + var wordBegin int + wordPending := false + for i, c := range s { + if unicode.IsSpace(c) { + if wordPending { + words = append(words, s[wordBegin:i]) + wordPending = false + } + continue + } + if !wordPending { + wordBegin = i + wordPending = true + } + } + if wordPending { + words = append(words, s[wordBegin:]) + } + return words +} + +// WrapString wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapString(s string, lim int) ([]string, int) { + if s == sp { + return []string{sp}, lim + } + words := SplitWords(s) + if len(words) == 0 { + return []string{""}, lim + } + var lines []string + max := 0 + for _, v := range words { + // max = runewidth.StringWidth(v) // OLD + max = twwidth.Width(v) // NEW: Use twdw.Width + if max > lim { + lim = max + } + } + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, strings.Join(line, sp)) + } + return lines, lim +} + +// WrapStringWithSpaces wraps a string into lines of a specified display width while preserving +// leading and trailing spaces. It splits the input string into words, condenses internal multiple +// spaces to a single space, and wraps the content to fit within the given width limit, measured +// using Unicode-aware display width. The function is used in the logging library to format log +// messages for consistent output. It returns the wrapped lines as a slice of strings and the +// adjusted width limit, which may increase if a single word exceeds the input limit. Thread-safe +// as it does not modify shared state. +func WrapStringWithSpaces(s string, lim int) ([]string, int) { + if len(s) == 0 { + return []string{""}, lim + } + if strings.TrimSpace(s) == "" { // All spaces + // if runewidth.StringWidth(s) <= lim { // OLD + if twwidth.Width(s) <= lim { // NEW: Use twdw.Width + // return []string{s}, runewidth.StringWidth(s) // OLD + return []string{s}, twwidth.Width(s) // NEW: Use twdw.Width + } + // For very long all-space strings, "wrap" by truncating to the limit. + if lim > 0 { + substring, _ := stringToDisplayWidth(s, lim) + return []string{substring}, lim + } + return []string{""}, lim + } + + var leadingSpaces, trailingSpaces, coreContent string + firstNonSpace := strings.IndexFunc(s, func(r rune) bool { return !unicode.IsSpace(r) }) + leadingSpaces = s[:firstNonSpace] + lastNonSpace := strings.LastIndexFunc(s, func(r rune) bool { return !unicode.IsSpace(r) }) + trailingSpaces = s[lastNonSpace+1:] + coreContent = s[firstNonSpace : lastNonSpace+1] + + if coreContent == "" { + return []string{leadingSpaces + trailingSpaces}, lim + } + + words := SplitWords(coreContent) + if len(words) == 0 { + return []string{leadingSpaces + trailingSpaces}, lim + } + + var lines []string + currentLim := lim + + maxCoreWordWidth := 0 + for _, v := range words { + // w := runewidth.StringWidth(v) // OLD + w := twwidth.Width(v) // NEW: Use twdw.Width + if w > maxCoreWordWidth { + maxCoreWordWidth = w + } + } + + if maxCoreWordWidth > currentLim { + currentLim = maxCoreWordWidth + } + + wrappedWordLines := WrapWords(words, 1, currentLim, defaultPenalty) + + for i, lineWords := range wrappedWordLines { + joinedLine := strings.Join(lineWords, sp) + finalLine := leadingSpaces + joinedLine + if i == len(wrappedWordLines)-1 { // Last line + finalLine += trailingSpaces + } + lines = append(lines, finalLine) + } + return lines, currentLim +} + +// stringToDisplayWidth returns a substring of s that has a display width +// as close as possible to, but not exceeding, targetWidth. +// It returns the substring and its actual display width. +func stringToDisplayWidth(s string, targetWidth int) (substring string, actualWidth int) { + if targetWidth <= 0 { + return "", 0 + } + + var currentWidth int + var endIndex int // Tracks the byte index in the original string + + g := uniseg.NewGraphemes(s) + for g.Next() { + grapheme := g.Str() + // graphemeWidth := runewidth.StringWidth(grapheme) // OLD + graphemeWidth := twwidth.Width(grapheme) // NEW: Use twdw.Width + + if currentWidth+graphemeWidth > targetWidth { + break + } + + currentWidth += graphemeWidth + _, e := g.Positions() + endIndex = e + } + return s[:endIndex], currentWidth +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, +// WrapString will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each rune as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words []string, spc, lim, pen int) [][]string { + n := len(words) + if n == 0 { + return nil + } + lengths := make([]int, n) + for i := 0; i < n; i++ { + // lengths[i] = runewidth.StringWidth(words[i]) // OLD + lengths[i] = twwidth.Width(words[i]) // NEW: Use twdw.Width + } + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + remainderLen := lengths[n-1] // Uses updated lengths + for i := n - 1; i >= 0; i-- { + if i < n-1 { + remainderLen += spc + lengths[i] + } + if remainderLen <= lim { + cost[i] = 0 + nbrk[i] = n + continue + } + phraseLen := lengths[i] + for j := i + 1; j < n; j++ { + if j > i+1 { + phraseLen += spc + lengths[j-1] + } + d := lim - phraseLen + c := d*d + cost[j] + if phraseLen > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + var lines [][]string + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} + +// getLines decomposes a multiline string into a slice of strings. +func getLines(s string) []string { + return strings.Split(s, nl) +} diff --git a/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go new file mode 100644 index 00000000..d46ce4a8 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/pkg/twwidth/width.go @@ -0,0 +1,321 @@ +package twwidth + +import ( + "bytes" + "github.com/mattn/go-runewidth" + "regexp" + "strings" + "sync" +) + +// condition holds the global runewidth configuration, including East Asian width settings. +var condition *runewidth.Condition + +// mu protects access to condition and widthCache for thread safety. +var mu sync.Mutex + +// ansi is a compiled regular expression for stripping ANSI escape codes from strings. +var ansi = Filter() + +func init() { + condition = runewidth.NewCondition() + widthCache = make(map[cacheKey]int) +} + +// cacheKey is used as a key for memoizing string width results in widthCache. +type cacheKey struct { + str string // Input string + eastAsianWidth bool // East Asian width setting +} + +// widthCache stores memoized results of Width calculations to improve performance. +var widthCache map[cacheKey]int + +// Filter compiles and returns a regular expression for matching ANSI escape sequences, +// including CSI (Control Sequence Introducer) and OSC (Operating System Command) sequences. +// The returned regex can be used to strip ANSI codes from strings. +func Filter() *regexp.Regexp { + var regESC = "\x1b" // ASCII escape character + var regBEL = "\x07" // ASCII bell character + + // ANSI string terminator: either ESC+\ or BEL + var regST = "(" + regexp.QuoteMeta(regESC+"\\") + "|" + regexp.QuoteMeta(regBEL) + ")" + // Control Sequence Introducer (CSI): ESC[ followed by parameters and a final byte + var regCSI = regexp.QuoteMeta(regESC+"[") + "[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]" + // Operating System Command (OSC): ESC] followed by arbitrary content until a terminator + var regOSC = regexp.QuoteMeta(regESC+"]") + ".*?" + regST + + // Combine CSI and OSC patterns into a single regex + return regexp.MustCompile("(" + regCSI + "|" + regOSC + ")") +} + +// SetEastAsian enables or disables East Asian width handling for width calculations. +// When the setting changes, the width cache is cleared to ensure accuracy. +// This function is thread-safe. +// +// Example: +// +// twdw.SetEastAsian(true) // Enable East Asian width handling +func SetEastAsian(enable bool) { + mu.Lock() + defer mu.Unlock() + if condition.EastAsianWidth != enable { + condition.EastAsianWidth = enable + widthCache = make(map[cacheKey]int) // Clear cache on setting change + } +} + +// SetCondition updates the global runewidth.Condition used for width calculations. +// When the condition is changed, the width cache is cleared. +// This function is thread-safe. +// +// Example: +// +// newCond := runewidth.NewCondition() +// newCond.EastAsianWidth = true +// twdw.SetCondition(newCond) +func SetCondition(newCond *runewidth.Condition) { + mu.Lock() + defer mu.Unlock() + condition = newCond + widthCache = make(map[cacheKey]int) // Clear cache on setting change +} + +// Width calculates the visual width of a string, excluding ANSI escape sequences, +// using the go-runewidth package for accurate Unicode handling. It accounts for the +// current East Asian width setting and caches results for performance. +// This function is thread-safe. +// +// Example: +// +// width := twdw.Width("Hello\x1b[31mWorld") // Returns 10 +func Width(str string) int { + mu.Lock() + key := cacheKey{str: str, eastAsianWidth: condition.EastAsianWidth} + if w, found := widthCache[key]; found { + mu.Unlock() + return w + } + mu.Unlock() + + // Use a temporary condition to avoid holding the lock during calculation + tempCond := runewidth.NewCondition() + tempCond.EastAsianWidth = key.eastAsianWidth + + stripped := ansi.ReplaceAllLiteralString(str, "") + calculatedWidth := tempCond.StringWidth(stripped) + + mu.Lock() + widthCache[key] = calculatedWidth + mu.Unlock() + + return calculatedWidth +} + +// WidthNoCache calculates the visual width of a string without using or +// updating the global cache. It uses the current global East Asian width setting. +// This function is intended for internal use (e.g., benchmarking) and is thread-safe. +// +// Example: +// +// width := twdw.WidthNoCache("Hello\x1b[31mWorld") // Returns 10 +func WidthNoCache(str string) int { + mu.Lock() + currentEA := condition.EastAsianWidth + mu.Unlock() + + tempCond := runewidth.NewCondition() + tempCond.EastAsianWidth = currentEA + + stripped := ansi.ReplaceAllLiteralString(str, "") + return tempCond.StringWidth(stripped) +} + +// Display calculates the visual width of a string, excluding ANSI escape sequences, +// using the provided runewidth condition. Unlike Width, it does not use caching +// and is intended for cases where a specific condition is required. +// This function is thread-safe with respect to the provided condition. +// +// Example: +// +// cond := runewidth.NewCondition() +// width := twdw.Display(cond, "Hello\x1b[31mWorld") // Returns 10 +func Display(cond *runewidth.Condition, str string) int { + return cond.StringWidth(ansi.ReplaceAllLiteralString(str, "")) +} + +// Truncate shortens a string to fit within a specified visual width, optionally +// appending a suffix (e.g., "..."). It preserves ANSI escape sequences and adds +// a reset sequence (\x1b[0m) if needed to prevent formatting bleed. The function +// respects the global East Asian width setting and is thread-safe. +// +// If maxWidth is negative, an empty string is returned. If maxWidth is zero and +// a suffix is provided, the suffix is returned. If the string's visual width is +// less than or equal to maxWidth, the string (and suffix, if provided and fits) +// is returned unchanged. +// +// Example: +// +// s := twdw.Truncate("Hello\x1b[31mWorld", 5, "...") // Returns "Hello..." +// s = twdw.Truncate("Hello", 10) // Returns "Hello" +func Truncate(s string, maxWidth int, suffix ...string) string { + if maxWidth < 0 { + return "" + } + + suffixStr := strings.Join(suffix, "") + sDisplayWidth := Width(s) // Uses global cached Width + suffixDisplayWidth := Width(suffixStr) // Uses global cached Width + + // Case 1: Original string is visually empty. + if sDisplayWidth == 0 { + // If suffix is provided and fits within maxWidth (or if maxWidth is generous) + if len(suffixStr) > 0 && suffixDisplayWidth <= maxWidth { + return suffixStr + } + // If s has ANSI codes (len(s)>0) but maxWidth is 0, can't display them. + if maxWidth == 0 && len(s) > 0 { + return "" + } + return s // Returns "" or original ANSI codes + } + + // Case 2: maxWidth is 0, but string has content. Cannot display anything. + if maxWidth == 0 { + return "" + } + + // Case 3: String fits completely or fits with suffix. + // Here, maxWidth is the total budget for the line. + if sDisplayWidth <= maxWidth { + if len(suffixStr) == 0 { // No suffix. + return s + } + // Suffix is provided. Check if s + suffix fits. + if sDisplayWidth+suffixDisplayWidth <= maxWidth { + return s + suffixStr + } + // s fits, but s + suffix is too long. Return s. + return s + } + + // Case 4: String needs truncation (sDisplayWidth > maxWidth). + // maxWidth is the total budget for the final string (content + suffix). + + // Capture the global EastAsianWidth setting once for consistent use + mu.Lock() + currentGlobalEastAsianWidth := condition.EastAsianWidth + mu.Unlock() + + // Special case for EastAsian true: if only suffix fits, return suffix. + // This was derived from previous test behavior. + if len(suffixStr) > 0 && currentGlobalEastAsianWidth { + provisionalContentWidth := maxWidth - suffixDisplayWidth + if provisionalContentWidth == 0 { // Exactly enough space for suffix only + return suffixStr // <<<< MODIFIED: No ANSI reset here + } + } + + // Calculate the budget for the content part, reserving space for the suffix. + targetContentForIteration := maxWidth + if len(suffixStr) > 0 { + targetContentForIteration -= suffixDisplayWidth + } + + // If content budget is negative, means not even suffix fits (or no suffix and no space). + // However, if only suffix fits, it should be handled. + if targetContentForIteration < 0 { + // Can we still fit just the suffix? + if len(suffixStr) > 0 && suffixDisplayWidth <= maxWidth { + if strings.Contains(s, "\x1b[") { + return "\x1b[0m" + suffixStr + } + return suffixStr + } + return "" // Cannot fit anything. + } + // If targetContentForIteration is 0, loop won't run, result will be empty string, then suffix is added. + + var contentBuf bytes.Buffer + var currentContentDisplayWidth int + var ansiSeqBuf bytes.Buffer + inAnsiSequence := false + ansiWrittenToContent := false + + localRunewidthCond := runewidth.NewCondition() + localRunewidthCond.EastAsianWidth = currentGlobalEastAsianWidth + + for _, r := range s { + if r == '\x1b' { + inAnsiSequence = true + ansiSeqBuf.Reset() + ansiSeqBuf.WriteRune(r) + } else if inAnsiSequence { + ansiSeqBuf.WriteRune(r) + seqBytes := ansiSeqBuf.Bytes() + seqLen := len(seqBytes) + terminated := false + if seqLen >= 2 { + introducer := seqBytes[1] + if introducer == '[' { + if seqLen >= 3 && r >= 0x40 && r <= 0x7E { + terminated = true + } + } else if introducer == ']' { + if r == '\x07' { + terminated = true + } else if seqLen > 1 && seqBytes[seqLen-2] == '\x1b' && r == '\\' { // Check for ST: \x1b\ + terminated = true + } + } + } + if terminated { + inAnsiSequence = false + contentBuf.Write(ansiSeqBuf.Bytes()) + ansiWrittenToContent = true + ansiSeqBuf.Reset() + } + } else { // Normal character + runeDisplayWidth := localRunewidthCond.RuneWidth(r) + if targetContentForIteration == 0 { // No budget for content at all + break + } + if currentContentDisplayWidth+runeDisplayWidth > targetContentForIteration { + break + } + contentBuf.WriteRune(r) + currentContentDisplayWidth += runeDisplayWidth + } + } + + result := contentBuf.String() + + // Suffix is added if: + // 1. A suffix string is provided. + // 2. Truncation actually happened (sDisplayWidth > maxWidth originally) + // OR if the content part is empty but a suffix is meant to be shown + // (e.g. targetContentForIteration was 0). + if len(suffixStr) > 0 { + // Add suffix if we are in the truncation path (sDisplayWidth > maxWidth) + // OR if targetContentForIteration was 0 (meaning only suffix should be shown) + // but we must ensure we don't exceed original maxWidth. + // The logic above for targetContentForIteration already ensures space. + + needsReset := false + // Condition for reset: if styling was active in 's' and might affect suffix + if (ansiWrittenToContent || (inAnsiSequence && strings.Contains(s, "\x1b["))) && (currentContentDisplayWidth > 0 || ansiWrittenToContent) { + if !strings.HasSuffix(result, "\x1b[0m") { + needsReset = true + } + } else if currentContentDisplayWidth > 0 && strings.Contains(result, "\x1b[") && !strings.HasSuffix(result, "\x1b[0m") && strings.Contains(s, "\x1b[") { + // If result has content and ANSI, and original had ANSI, and result not already reset + needsReset = true + } + + if needsReset { + result += "\x1b[0m" + } + result += suffixStr + } + return result +} diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/blueprint.go b/vendor/github.com/olekukonko/tablewriter/renderer/blueprint.go new file mode 100644 index 00000000..42966ebc --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/blueprint.go @@ -0,0 +1,581 @@ +package renderer + +import ( + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "io" + "strings" + + "github.com/olekukonko/tablewriter/tw" +) + +// Blueprint implements a primary table rendering engine with customizable borders and alignments. +type Blueprint struct { + config tw.Rendition // Rendering configuration for table borders and symbols + logger *ll.Logger // Logger for debug trace messages + w io.Writer +} + +// NewBlueprint creates a new Blueprint instance with optional custom configurations. +func NewBlueprint(configs ...tw.Rendition) *Blueprint { + // Initialize with default configuration + cfg := defaultBlueprint() + if len(configs) > 0 { + userCfg := configs[0] + // Override default borders if provided + if userCfg.Borders.Left != 0 { + cfg.Borders.Left = userCfg.Borders.Left + } + if userCfg.Borders.Right != 0 { + cfg.Borders.Right = userCfg.Borders.Right + } + if userCfg.Borders.Top != 0 { + cfg.Borders.Top = userCfg.Borders.Top + } + if userCfg.Borders.Bottom != 0 { + cfg.Borders.Bottom = userCfg.Borders.Bottom + } + // Override symbols if provided + if userCfg.Symbols != nil { + cfg.Symbols = userCfg.Symbols + } + + // Merge user settings with default settings + cfg.Settings = mergeSettings(cfg.Settings, userCfg.Settings) + } + return &Blueprint{config: cfg, logger: ll.New("blueprint")} +} + +// Close performs cleanup (no-op in this implementation). +func (f *Blueprint) Close() error { + f.logger.Debug("Blueprint.Close() called (no-op).") + return nil +} + +// Config returns the renderer's current configuration. +func (f *Blueprint) Config() tw.Rendition { + return f.config +} + +// Footer renders the table footer section with configured formatting. +func (f *Blueprint) Footer(footers [][]string, ctx tw.Formatting) { + f.logger.Debugf("Starting Footer render: IsSubRow=%v, Location=%v, Pos=%s", ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position) + // Render the footer line + f.renderLine(ctx) + f.logger.Debug("Completed Footer render") +} + +// Header renders the table header section with configured formatting. +func (f *Blueprint) Header(headers [][]string, ctx tw.Formatting) { + f.logger.Debugf("Starting Header render: IsSubRow=%v, Location=%v, Pos=%s, lines=%d, widths=%v", + ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position, len(ctx.Row.Current), ctx.Row.Widths) + // Render the header line + f.renderLine(ctx) + f.logger.Debug("Completed Header render") +} + +// Line renders a full horizontal row line with junctions and segments. +func (f *Blueprint) Line(ctx tw.Formatting) { + // Initialize junction renderer + jr := NewJunction(JunctionContext{ + Symbols: f.config.Symbols, + Ctx: ctx, + ColIdx: 0, + Logger: f.logger, + BorderTint: Tint{}, + SeparatorTint: Tint{}, + }) + + var line strings.Builder + totalLineWidth := 0 // Track total display width + // Get sorted column indices + sortedKeys := ctx.Row.Widths.SortedKeys() + numCols := 0 + if len(sortedKeys) > 0 { + numCols = sortedKeys[len(sortedKeys)-1] + 1 + } + + // Handle empty row case + if numCols == 0 { + prefix := tw.Empty + suffix := tw.Empty + if f.config.Borders.Left.Enabled() { + prefix = jr.RenderLeft() + } + if f.config.Borders.Right.Enabled() { + suffix = jr.RenderRight(-1) + } + if prefix != tw.Empty || suffix != tw.Empty { + line.WriteString(prefix + suffix + tw.NewLine) + totalLineWidth = twwidth.Width(prefix) + twwidth.Width(suffix) + f.w.Write([]byte(line.String())) + } + f.logger.Debugf("Line: Handled empty row/widths case (total width %d)", totalLineWidth) + return + } + + // Calculate target total width based on data rows + targetTotalWidth := 0 + for _, colIdx := range sortedKeys { + targetTotalWidth += ctx.Row.Widths.Get(colIdx) + } + if f.config.Borders.Left.Enabled() { + targetTotalWidth += twwidth.Width(f.config.Symbols.Column()) + } + if f.config.Borders.Right.Enabled() { + targetTotalWidth += twwidth.Width(f.config.Symbols.Column()) + } + if f.config.Settings.Separators.BetweenColumns.Enabled() && len(sortedKeys) > 1 { + targetTotalWidth += twwidth.Width(f.config.Symbols.Column()) * (len(sortedKeys) - 1) + } + + // Add left border if enabled + leftBorderWidth := 0 + if f.config.Borders.Left.Enabled() { + leftBorder := jr.RenderLeft() + line.WriteString(leftBorder) + leftBorderWidth = twwidth.Width(leftBorder) + totalLineWidth += leftBorderWidth + f.logger.Debugf("Line: Left border='%s' (f.width %d)", leftBorder, leftBorderWidth) + } + + visibleColIndices := make([]int, 0) + // Calculate visible columns + for _, colIdx := range sortedKeys { + colWidth := ctx.Row.Widths.Get(colIdx) + if colWidth > 0 { + visibleColIndices = append(visibleColIndices, colIdx) + } + } + + f.logger.Debugf("Line: sortedKeys=%v, Widths=%v, visibleColIndices=%v, targetTotalWidth=%d", sortedKeys, ctx.Row.Widths, visibleColIndices, targetTotalWidth) + // Render each column segment + for keyIndex, currentColIdx := range visibleColIndices { + jr.colIdx = currentColIdx + segment := jr.GetSegment() + colWidth := ctx.Row.Widths.Get(currentColIdx) + // Adjust colWidth to account for wider borders + adjustedColWidth := colWidth + if f.config.Borders.Left.Enabled() && keyIndex == 0 { + adjustedColWidth -= leftBorderWidth - twwidth.Width(f.config.Symbols.Column()) + } + if f.config.Borders.Right.Enabled() && keyIndex == len(visibleColIndices)-1 { + rightBorderWidth := twwidth.Width(jr.RenderRight(currentColIdx)) + adjustedColWidth -= rightBorderWidth - twwidth.Width(f.config.Symbols.Column()) + } + if adjustedColWidth < 0 { + adjustedColWidth = 0 + } + f.logger.Debugf("Line: colIdx=%d, segment='%s', adjusted colWidth=%d", currentColIdx, segment, adjustedColWidth) + if segment == tw.Empty { + spaces := strings.Repeat(tw.Space, adjustedColWidth) + line.WriteString(spaces) + totalLineWidth += adjustedColWidth + f.logger.Debugf("Line: Rendered spaces='%s' (f.width %d) for col %d", spaces, adjustedColWidth, currentColIdx) + } else { + segmentWidth := twwidth.Width(segment) + if segmentWidth == 0 { + segmentWidth = 1 // Avoid division by zero + f.logger.Warnf("Line: Segment='%s' has zero width, using 1", segment) + } + // Calculate how many full segments fit + repeat := adjustedColWidth / segmentWidth + if repeat < 1 && adjustedColWidth > 0 { + repeat = 1 + } + repeatedSegment := strings.Repeat(segment, repeat) + actualWidth := twwidth.Width(repeatedSegment) + if actualWidth > adjustedColWidth { + // Truncate if too long + repeatedSegment = twwidth.Truncate(repeatedSegment, adjustedColWidth) + actualWidth = twwidth.Width(repeatedSegment) + f.logger.Debugf("Line: Truncated segment='%s' to width %d", repeatedSegment, actualWidth) + } else if actualWidth < adjustedColWidth { + // Pad with segment character to match adjustedColWidth + remainingWidth := adjustedColWidth - actualWidth + for i := 0; i < remainingWidth/segmentWidth; i++ { + repeatedSegment += segment + } + actualWidth = twwidth.Width(repeatedSegment) + if actualWidth < adjustedColWidth { + repeatedSegment = tw.PadRight(repeatedSegment, tw.Space, adjustedColWidth) + actualWidth = adjustedColWidth + f.logger.Debugf("Line: Padded segment with spaces='%s' to width %d", repeatedSegment, actualWidth) + } + f.logger.Debugf("Line: Padded segment='%s' to width %d", repeatedSegment, actualWidth) + } + line.WriteString(repeatedSegment) + totalLineWidth += actualWidth + f.logger.Debugf("Line: Rendered segment='%s' (f.width %d) for col %d", repeatedSegment, actualWidth, currentColIdx) + } + + // Add junction between columns if not the last column + isLast := keyIndex == len(visibleColIndices)-1 + if !isLast && f.config.Settings.Separators.BetweenColumns.Enabled() { + nextColIdx := visibleColIndices[keyIndex+1] + junction := jr.RenderJunction(currentColIdx, nextColIdx) + // Use center symbol (❀) or column separator (|) to match data rows + if twwidth.Width(junction) != twwidth.Width(f.config.Symbols.Column()) { + junction = f.config.Symbols.Center() + if twwidth.Width(junction) != twwidth.Width(f.config.Symbols.Column()) { + junction = f.config.Symbols.Column() + } + } + junctionWidth := twwidth.Width(junction) + line.WriteString(junction) + totalLineWidth += junctionWidth + f.logger.Debugf("Line: Junction between %d and %d: '%s' (f.width %d)", currentColIdx, nextColIdx, junction, junctionWidth) + } + } + + // Add right border + rightBorderWidth := 0 + if f.config.Borders.Right.Enabled() && len(visibleColIndices) > 0 { + lastIdx := visibleColIndices[len(visibleColIndices)-1] + rightBorder := jr.RenderRight(lastIdx) + rightBorderWidth = twwidth.Width(rightBorder) + line.WriteString(rightBorder) + totalLineWidth += rightBorderWidth + f.logger.Debugf("Line: Right border='%s' (f.width %d)", rightBorder, rightBorderWidth) + } + + // Write the final line + line.WriteString(tw.NewLine) + f.w.Write([]byte(line.String())) + f.logger.Debugf("Line rendered: '%s' (total width %d, target %d)", strings.TrimSuffix(line.String(), tw.NewLine), totalLineWidth, targetTotalWidth) +} + +// Logger sets the logger for the Blueprint instance. +func (f *Blueprint) Logger(logger *ll.Logger) { + f.logger = logger.Namespace("blueprint") +} + +// Row renders a table data row with configured formatting. +func (f *Blueprint) Row(row []string, ctx tw.Formatting) { + f.logger.Debugf("Starting Row render: IsSubRow=%v, Location=%v, Pos=%s, hasFooter=%v", + ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position, ctx.HasFooter) + + // Render the row line + f.renderLine(ctx) + f.logger.Debug("Completed Row render") +} + +// Start initializes the rendering process (no-op in this implementation). +func (f *Blueprint) Start(w io.Writer) error { + f.w = w + f.logger.Debug("Blueprint.Start() called (no-op).") + return nil +} + +// formatCell formats a cell's content with specified width, padding, and alignment, returning an empty string if width is non-positive. +func (f *Blueprint) formatCell(content string, width int, padding tw.Padding, align tw.Align) string { + if width <= 0 { + return tw.Empty + } + + f.logger.Debugf("Formatting cell: content='%s', width=%d, align=%s, padding={L:'%s' R:'%s'}", + content, width, align, padding.Left, padding.Right) + + // Calculate display width of content + runeWidth := twwidth.Width(content) + + // Set default padding characters + leftPadChar := padding.Left + rightPadChar := padding.Right + + //if f.config.Settings.Cushion.Enabled() || f.config.Settings.Cushion.Default() { + // if leftPadChar == tw.Empty { + // leftPadChar = tw.Space + // } + // if rightPadChar == tw.Empty { + // rightPadChar = tw.Space + // } + //} + + // Calculate padding widths + padLeftWidth := twwidth.Width(leftPadChar) + padRightWidth := twwidth.Width(rightPadChar) + + // Calculate available width for content + availableContentWidth := width - padLeftWidth - padRightWidth + if availableContentWidth < 0 { + availableContentWidth = 0 + } + f.logger.Debugf("Available content width: %d", availableContentWidth) + + // Truncate content if it exceeds available width + if runeWidth > availableContentWidth { + content = twwidth.Truncate(content, availableContentWidth) + runeWidth = twwidth.Width(content) + f.logger.Debugf("Truncated content to fit %d: '%s' (new width %d)", availableContentWidth, content, runeWidth) + } + + // Calculate total padding needed + totalPaddingWidth := width - runeWidth + if totalPaddingWidth < 0 { + totalPaddingWidth = 0 + } + f.logger.Debugf("Total padding width: %d", totalPaddingWidth) + + var result strings.Builder + var leftPaddingWidth, rightPaddingWidth int + + // Apply alignment and padding + switch align { + case tw.AlignLeft: + result.WriteString(leftPadChar) + result.WriteString(content) + rightPaddingWidth = totalPaddingWidth - padLeftWidth + if rightPaddingWidth > 0 { + result.WriteString(tw.PadRight(tw.Empty, rightPadChar, rightPaddingWidth)) + f.logger.Debugf("Applied right padding: '%s' for %d width", rightPadChar, rightPaddingWidth) + } + case tw.AlignRight: + leftPaddingWidth = totalPaddingWidth - padRightWidth + if leftPaddingWidth > 0 { + result.WriteString(tw.PadLeft(tw.Empty, leftPadChar, leftPaddingWidth)) + f.logger.Debugf("Applied left padding: '%s' for %d width", leftPadChar, leftPaddingWidth) + } + result.WriteString(content) + result.WriteString(rightPadChar) + case tw.AlignCenter: + leftPaddingWidth = (totalPaddingWidth-padLeftWidth-padRightWidth)/2 + padLeftWidth + rightPaddingWidth = totalPaddingWidth - leftPaddingWidth + if leftPaddingWidth > padLeftWidth { + result.WriteString(tw.PadLeft(tw.Empty, leftPadChar, leftPaddingWidth-padLeftWidth)) + f.logger.Debugf("Applied left centering padding: '%s' for %d width", leftPadChar, leftPaddingWidth-padLeftWidth) + } + result.WriteString(leftPadChar) + result.WriteString(content) + result.WriteString(rightPadChar) + if rightPaddingWidth > padRightWidth { + result.WriteString(tw.PadRight(tw.Empty, rightPadChar, rightPaddingWidth-padRightWidth)) + f.logger.Debugf("Applied right centering padding: '%s' for %d width", rightPadChar, rightPaddingWidth-padRightWidth) + } + default: + // Default to left alignment + result.WriteString(leftPadChar) + result.WriteString(content) + rightPaddingWidth = totalPaddingWidth - padLeftWidth + if rightPaddingWidth > 0 { + result.WriteString(tw.PadRight(tw.Empty, rightPadChar, rightPaddingWidth)) + f.logger.Debugf("Applied right padding: '%s' for %d width", rightPadChar, rightPaddingWidth) + } + } + + output := result.String() + finalWidth := twwidth.Width(output) + // Adjust output to match target width + if finalWidth > width { + output = twwidth.Truncate(output, width) + f.logger.Debugf("formatCell: Truncated output to width %d", width) + } else if finalWidth < width { + output = tw.PadRight(output, tw.Space, width) + f.logger.Debugf("formatCell: Padded output to meet width %d", width) + } + + // Log warning if final width doesn't match target + if f.logger.Enabled() && twwidth.Width(output) != width { + f.logger.Debugf("formatCell Warning: Final width %d does not match target %d for result '%s'", + twwidth.Width(output), width, output) + } + + f.logger.Debugf("Formatted cell final result: '%s' (target width %d)", output, width) + return output +} + +// renderLine renders a single line (header, row, or footer) with borders, separators, and merge handling. +func (f *Blueprint) renderLine(ctx tw.Formatting) { + // Get sorted column indices + sortedKeys := ctx.Row.Widths.SortedKeys() + numCols := 0 + if len(sortedKeys) > 0 { + numCols = sortedKeys[len(sortedKeys)-1] + 1 + } + + // Set column separator and borders + columnSeparator := f.config.Symbols.Column() + prefix := tw.Empty + if f.config.Borders.Left.Enabled() { + prefix = columnSeparator + } + suffix := tw.Empty + if f.config.Borders.Right.Enabled() { + suffix = columnSeparator + } + + var output strings.Builder + totalLineWidth := 0 // Track total display width + if prefix != tw.Empty { + output.WriteString(prefix) + totalLineWidth += twwidth.Width(prefix) + f.logger.Debugf("renderLine: Prefix='%s' (f.width %d)", prefix, twwidth.Width(prefix)) + } + + colIndex := 0 + separatorDisplayWidth := 0 + if f.config.Settings.Separators.BetweenColumns.Enabled() { + separatorDisplayWidth = twwidth.Width(columnSeparator) + } + + // Process each column + for colIndex < numCols { + visualWidth := ctx.Row.Widths.Get(colIndex) + cellCtx, ok := ctx.Row.Current[colIndex] + isHMergeStart := ok && cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start + if visualWidth == 0 && !isHMergeStart { + f.logger.Debugf("renderLine: Skipping col %d (zero width, not HMerge start)", colIndex) + colIndex++ + continue + } + + // Determine if a separator is needed + shouldAddSeparator := false + if colIndex > 0 && f.config.Settings.Separators.BetweenColumns.Enabled() { + prevWidth := ctx.Row.Widths.Get(colIndex - 1) + prevCellCtx, prevOk := ctx.Row.Current[colIndex-1] + prevIsHMergeEnd := prevOk && prevCellCtx.Merge.Horizontal.Present && prevCellCtx.Merge.Horizontal.End + if (prevWidth > 0 || prevIsHMergeEnd) && (!ok || !(cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start)) { + shouldAddSeparator = true + } + } + if shouldAddSeparator { + output.WriteString(columnSeparator) + totalLineWidth += separatorDisplayWidth + f.logger.Debugf("renderLine: Added separator '%s' before col %d (f.width %d)", columnSeparator, colIndex, separatorDisplayWidth) + } else if colIndex > 0 { + f.logger.Debugf("renderLine: Skipped separator before col %d due to zero-width prev col or HMerge continuation", colIndex) + } + + // Handle merged cells + span := 1 + if isHMergeStart { + span = cellCtx.Merge.Horizontal.Span + if ctx.Row.Position == tw.Row { + dynamicTotalWidth := 0 + for k := 0; k < span && colIndex+k < numCols; k++ { + normWidth := ctx.NormalizedWidths.Get(colIndex + k) + if normWidth < 0 { + normWidth = 0 + } + dynamicTotalWidth += normWidth + if k > 0 && separatorDisplayWidth > 0 && ctx.NormalizedWidths.Get(colIndex+k) > 0 { + dynamicTotalWidth += separatorDisplayWidth + } + } + visualWidth = dynamicTotalWidth + f.logger.Debugf("renderLine: Row HMerge col %d, span %d, dynamic visualWidth %d", colIndex, span, visualWidth) + } else { + visualWidth = ctx.Row.Widths.Get(colIndex) + f.logger.Debugf("renderLine: H/F HMerge col %d, span %d, pre-adjusted visualWidth %d", colIndex, span, visualWidth) + } + } else { + visualWidth = ctx.Row.Widths.Get(colIndex) + f.logger.Debugf("renderLine: Regular col %d, visualWidth %d", colIndex, visualWidth) + } + if visualWidth < 0 { + visualWidth = 0 + } + + // Skip processing for non-start merged cells + if ok && cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start { + f.logger.Debugf("renderLine: Skipping col %d processing (part of HMerge)", colIndex) + colIndex++ + continue + } + + // Handle empty cell context + if !ok { + if visualWidth > 0 { + spaces := strings.Repeat(tw.Space, visualWidth) + output.WriteString(spaces) + totalLineWidth += visualWidth + f.logger.Debugf("renderLine: No cell context for col %d, writing %d spaces (f.width %d)", colIndex, visualWidth, visualWidth) + } else { + f.logger.Debugf("renderLine: No cell context for col %d, visualWidth is 0, writing nothing", colIndex) + } + colIndex += span + continue + } + + // Set cell padding and alignment + padding := cellCtx.Padding + align := cellCtx.Align + if align == tw.AlignNone { + if ctx.Row.Position == tw.Header { + align = tw.AlignCenter + } else if ctx.Row.Position == tw.Footer { + align = tw.AlignRight + } else { + align = tw.AlignLeft + } + f.logger.Debugf("renderLine: col %d (data: '%s') using renderer default align '%s' for position %s.", colIndex, cellCtx.Data, align, ctx.Row.Position) + } else if align == tw.Skip { + if ctx.Row.Position == tw.Header { + align = tw.AlignCenter + } else if ctx.Row.Position == tw.Footer { + align = tw.AlignRight + } else { + align = tw.AlignLeft + } + f.logger.Debugf("renderLine: col %d (data: '%s') cellCtx.Align was Skip/empty, falling back to basic default '%s'.", colIndex, cellCtx.Data, align) + } + + isTotalPattern := false + + // Override alignment for footer merged cells + if (ctx.Row.Position == tw.Footer && isHMergeStart) || isTotalPattern { + if align != tw.AlignRight { + f.logger.Debugf("renderLine: Applying AlignRight HMerge/TOTAL override for Footer col %d. Original/default align was: %s", colIndex, align) + align = tw.AlignRight + } + } + + // Handle vertical/hierarchical merges + cellData := cellCtx.Data + if (cellCtx.Merge.Vertical.Present && !cellCtx.Merge.Vertical.Start) || + (cellCtx.Merge.Hierarchical.Present && !cellCtx.Merge.Hierarchical.Start) { + cellData = tw.Empty + f.logger.Debugf("renderLine: Blanked data for col %d (non-start V/Hierarchical)", colIndex) + } + + // Format and render the cell + formattedCell := f.formatCell(cellData, visualWidth, padding, align) + if len(formattedCell) > 0 { + output.WriteString(formattedCell) + cellWidth := twwidth.Width(formattedCell) + totalLineWidth += cellWidth + f.logger.Debugf("renderLine: Rendered col %d, formattedCell='%s' (f.width %d), totalLineWidth=%d", colIndex, formattedCell, cellWidth, totalLineWidth) + } + + // Log rendering details + if isHMergeStart { + f.logger.Debugf("renderLine: Rendered HMerge START col %d (span %d, visualWidth %d, align %v): '%s'", + colIndex, span, visualWidth, align, formattedCell) + } else { + f.logger.Debugf("renderLine: Rendered regular col %d (visualWidth %d, align %v): '%s'", + colIndex, visualWidth, align, formattedCell) + } + colIndex += span + } + + // Add suffix and adjust total width + if output.Len() > len(prefix) || f.config.Borders.Right.Enabled() { + output.WriteString(suffix) + totalLineWidth += twwidth.Width(suffix) + f.logger.Debugf("renderLine: Suffix='%s' (f.width %d)", suffix, twwidth.Width(suffix)) + } + output.WriteString(tw.NewLine) + f.w.Write([]byte(output.String())) + f.logger.Debugf("renderLine: Final rendered line: '%s' (total width %d)", strings.TrimSuffix(output.String(), tw.NewLine), totalLineWidth) +} + +// Rendition updates the Blueprint's configuration. +func (f *Blueprint) Rendition(config tw.Rendition) { + f.config = mergeRendition(f.config, config) + f.logger.Debugf("Blueprint.Rendition updated. New config: %+v", f.config) + +} + +// Ensure Blueprint implements tw.Renditioning +var _ tw.Renditioning = (*Blueprint)(nil) diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go b/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go new file mode 100644 index 00000000..5eaa1924 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/colorized.go @@ -0,0 +1,719 @@ +package renderer + +import ( + "github.com/fatih/color" + "github.com/olekukonko/ll" + "github.com/olekukonko/ll/lh" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "io" + "strings" + + "github.com/olekukonko/tablewriter/tw" +) + +// ColorizedConfig holds configuration for the Colorized table renderer. +type ColorizedConfig struct { + Borders tw.Border // Border visibility settings + Settings tw.Settings // Rendering behavior settings (e.g., separators, whitespace) + Header Tint // Colors for header cells + Column Tint // Colors for row cells + Footer Tint // Colors for footer cells + Border Tint // Colors for borders and lines + Separator Tint // Colors for column separators + Symbols tw.Symbols // Symbols for table drawing (e.g., corners, lines) +} + +// Colors is a slice of color attributes for use with fatih/color, such as color.FgWhite or color.Bold. +type Colors []color.Attribute + +// Tint defines foreground and background color settings for table elements, with optional per-column overrides. +type Tint struct { + FG Colors // Foreground color attributes + BG Colors // Background color attributes + Columns []Tint // Per-column color settings +} + +// Apply applies the Tint's foreground and background colors to the given text, returning the text unchanged if no colors are set. +func (t Tint) Apply(text string) string { + if len(t.FG) == 0 && len(t.BG) == 0 { + return text + } + // Combine foreground and background colors + combinedColors := append(t.FG, t.BG...) + // Create a color function and apply it to the text + c := color.New(combinedColors...).SprintFunc() + return c(text) +} + +// Colorized renders colored ASCII tables with customizable borders, colors, and alignments. +type Colorized struct { + config ColorizedConfig // Renderer configuration + trace []string // Debug trace messages + newLine string // Newline character + defaultAlign map[tw.Position]tw.Align // Default alignments for header, row, and footer + logger *ll.Logger // Logger for debug messages + w io.Writer +} + +// NewColorized creates a Colorized renderer with the specified configuration, falling back to defaults if none provided. +// Only the first config is used if multiple are passed. +func NewColorized(configs ...ColorizedConfig) *Colorized { + // Initialize with default configuration + baseCfg := defaultColorized() + + if len(configs) > 0 { + userCfg := configs[0] + + // Override border settings if provided + if userCfg.Borders.Left != 0 { + baseCfg.Borders.Left = userCfg.Borders.Left + } + if userCfg.Borders.Right != 0 { + baseCfg.Borders.Right = userCfg.Borders.Right + } + if userCfg.Borders.Top != 0 { + baseCfg.Borders.Top = userCfg.Borders.Top + } + if userCfg.Borders.Bottom != 0 { + baseCfg.Borders.Bottom = userCfg.Borders.Bottom + } + + // Merge separator and line settings + baseCfg.Settings.Separators = mergeSeparators(baseCfg.Settings.Separators, userCfg.Settings.Separators) + baseCfg.Settings.Lines = mergeLines(baseCfg.Settings.Lines, userCfg.Settings.Lines) + + // Override compact mode if specified + if userCfg.Settings.CompactMode != 0 { + baseCfg.Settings.CompactMode = userCfg.Settings.CompactMode + } + + // Override color settings for various table elements + if len(userCfg.Header.FG) > 0 || len(userCfg.Header.BG) > 0 || userCfg.Header.Columns != nil { + baseCfg.Header = userCfg.Header + } + if len(userCfg.Column.FG) > 0 || len(userCfg.Column.BG) > 0 || userCfg.Column.Columns != nil { + baseCfg.Column = userCfg.Column + } + if len(userCfg.Footer.FG) > 0 || len(userCfg.Footer.BG) > 0 || userCfg.Footer.Columns != nil { + baseCfg.Footer = userCfg.Footer + } + if len(userCfg.Border.FG) > 0 || len(userCfg.Border.BG) > 0 || userCfg.Border.Columns != nil { + baseCfg.Border = userCfg.Border + } + if len(userCfg.Separator.FG) > 0 || len(userCfg.Separator.BG) > 0 || userCfg.Separator.Columns != nil { + baseCfg.Separator = userCfg.Separator + } + + // Override symbols if provided + if userCfg.Symbols != nil { + baseCfg.Symbols = userCfg.Symbols + } + } + + cfg := baseCfg + // Ensure symbols are initialized + if cfg.Symbols == nil { + cfg.Symbols = tw.NewSymbols(tw.StyleLight) + } + + // Initialize the Colorized renderer + f := &Colorized{ + config: cfg, + newLine: tw.NewLine, + defaultAlign: map[tw.Position]tw.Align{ + tw.Header: tw.AlignCenter, + tw.Row: tw.AlignLeft, + tw.Footer: tw.AlignRight, + }, + logger: ll.New("colorized", ll.WithHandler(lh.NewMemoryHandler())), + } + // Log initialization details + f.logger.Debugf("Initialized Colorized renderer with symbols: Center=%q, Row=%q, Column=%q", f.config.Symbols.Center(), f.config.Symbols.Row(), f.config.Symbols.Column()) + f.logger.Debugf("Final ColorizedConfig.Settings.Lines: %+v", f.config.Settings.Lines) + f.logger.Debugf("Final ColorizedConfig.Borders: %+v", f.config.Borders) + return f +} + +// Close performs cleanup (no-op in this implementation). +func (c *Colorized) Close() error { + c.logger.Debug("Colorized.Close() called (no-op).") + return nil +} + +// Config returns the renderer's configuration as a Rendition. +func (c *Colorized) Config() tw.Rendition { + return tw.Rendition{ + Borders: c.config.Borders, + Settings: c.config.Settings, + Symbols: c.config.Symbols, + Streaming: true, + } +} + +// Debug returns the accumulated debug trace messages. +func (c *Colorized) Debug() []string { + return c.trace +} + +// Footer renders the table footer with configured colors and formatting. +func (c *Colorized) Footer(footers [][]string, ctx tw.Formatting) { + c.logger.Debugf("Starting Footer render: IsSubRow=%v, Location=%v, Pos=%s", + ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position) + + // Check if there are footers to render + if len(footers) == 0 || len(footers[0]) == 0 { + c.logger.Debug("Footer: No footers to render") + return + } + + // Render the footer line + c.renderLine(ctx, footers[0], c.config.Footer) + c.logger.Debug("Completed Footer render") +} + +// Header renders the table header with configured colors and formatting. +func (c *Colorized) Header(headers [][]string, ctx tw.Formatting) { + c.logger.Debugf("Starting Header render: IsSubRow=%v, Location=%v, Pos=%s, lines=%d, widths=%v", + ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position, len(headers), ctx.Row.Widths) + + // Check if there are headers to render + if len(headers) == 0 || len(headers[0]) == 0 { + c.logger.Debug("Header: No headers to render") + return + } + + // Render the header line + c.renderLine(ctx, headers[0], c.config.Header) + c.logger.Debug("Completed Header render") +} + +// Line renders a horizontal row line with colored junctions and segments, skipping zero-width columns. +func (c *Colorized) Line(ctx tw.Formatting) { + c.logger.Debugf("Line: Starting with Level=%v, Location=%v, IsSubRow=%v, Widths=%v", ctx.Level, ctx.Row.Location, ctx.IsSubRow, ctx.Row.Widths) + + // Initialize junction renderer + jr := NewJunction(JunctionContext{ + Symbols: c.config.Symbols, + Ctx: ctx, + ColIdx: 0, + BorderTint: c.config.Border, + SeparatorTint: c.config.Separator, + Logger: c.logger, + }) + + var line strings.Builder + + // Get sorted column indices and filter out zero-width columns + allSortedKeys := ctx.Row.Widths.SortedKeys() + effectiveKeys := []int{} + keyWidthMap := make(map[int]int) + + for _, k := range allSortedKeys { + width := ctx.Row.Widths.Get(k) + keyWidthMap[k] = width + if width > 0 { + effectiveKeys = append(effectiveKeys, k) + } + } + c.logger.Debugf("Line: All keys=%v, Effective keys (width>0)=%v", allSortedKeys, effectiveKeys) + + // Handle case with no effective columns + if len(effectiveKeys) == 0 { + prefix := tw.Empty + suffix := tw.Empty + if c.config.Borders.Left.Enabled() { + prefix = jr.RenderLeft() + } + if c.config.Borders.Right.Enabled() { + originalLastColIdx := -1 + if len(allSortedKeys) > 0 { + originalLastColIdx = allSortedKeys[len(allSortedKeys)-1] + } + suffix = jr.RenderRight(originalLastColIdx) + } + if prefix != tw.Empty || suffix != tw.Empty { + line.WriteString(prefix + suffix + tw.NewLine) + c.w.Write([]byte(line.String())) + } + c.logger.Debug("Line: Handled empty row/widths case (no effective keys)") + return + } + + // Add left border if enabled + if c.config.Borders.Left.Enabled() { + line.WriteString(jr.RenderLeft()) + } + + // Render segments for each effective column + for keyIndex, currentColIdx := range effectiveKeys { + jr.colIdx = currentColIdx + segment := jr.GetSegment() + colWidth := keyWidthMap[currentColIdx] + c.logger.Debugf("Line: Drawing segment for Effective colIdx=%d, segment='%s', width=%d", currentColIdx, segment, colWidth) + + if segment == tw.Empty { + line.WriteString(strings.Repeat(tw.Space, colWidth)) + } else { + // Calculate how many times to repeat the segment + segmentWidth := twwidth.Width(segment) + if segmentWidth <= 0 { + segmentWidth = 1 + } + repeat := 0 + if colWidth > 0 && segmentWidth > 0 { + repeat = colWidth / segmentWidth + } + drawnSegment := strings.Repeat(segment, repeat) + line.WriteString(drawnSegment) + + // Adjust for width discrepancies + actualDrawnWidth := twwidth.Width(drawnSegment) + if actualDrawnWidth < colWidth { + missingWidth := colWidth - actualDrawnWidth + spaces := strings.Repeat(tw.Space, missingWidth) + if len(c.config.Border.BG) > 0 { + line.WriteString(Tint{BG: c.config.Border.BG}.Apply(spaces)) + } else { + line.WriteString(spaces) + } + c.logger.Debugf("Line: colIdx=%d corrected segment width, added %d spaces", currentColIdx, missingWidth) + } else if actualDrawnWidth > colWidth { + c.logger.Debugf("Line: WARNING colIdx=%d segment draw width %d > target %d", currentColIdx, actualDrawnWidth, colWidth) + } + } + + // Add junction between columns if not the last visible column + isLastVisible := keyIndex == len(effectiveKeys)-1 + if !isLastVisible && c.config.Settings.Separators.BetweenColumns.Enabled() { + nextVisibleColIdx := effectiveKeys[keyIndex+1] + originalPrecedingCol := -1 + foundCurrent := false + for _, k := range allSortedKeys { + if k == currentColIdx { + foundCurrent = true + } + if foundCurrent && k < nextVisibleColIdx { + originalPrecedingCol = k + } + if k >= nextVisibleColIdx { + break + } + } + + if originalPrecedingCol != -1 { + jr.colIdx = originalPrecedingCol + junction := jr.RenderJunction(originalPrecedingCol, nextVisibleColIdx) + c.logger.Debugf("Line: Junction between visible %d (orig preceding %d) and next visible %d: '%s'", currentColIdx, originalPrecedingCol, nextVisibleColIdx, junction) + line.WriteString(junction) + } else { + c.logger.Debugf("Line: Could not determine original preceding column for junction before visible %d", nextVisibleColIdx) + line.WriteString(c.config.Separator.Apply(jr.sym.Center())) + } + } + } + + // Add right border if enabled + if c.config.Borders.Right.Enabled() { + originalLastColIdx := -1 + if len(allSortedKeys) > 0 { + originalLastColIdx = allSortedKeys[len(allSortedKeys)-1] + } + jr.colIdx = originalLastColIdx + line.WriteString(jr.RenderRight(originalLastColIdx)) + } + + // Write the final line + line.WriteString(c.newLine) + c.w.Write([]byte(line.String())) + c.logger.Debugf("Line rendered: %s", strings.TrimSuffix(line.String(), c.newLine)) +} + +// Logger sets the logger for the Colorized instance. +func (c *Colorized) Logger(logger *ll.Logger) { + c.logger = logger.Namespace("colorized") +} + +// Reset clears the renderer's internal state, including debug traces. +func (c *Colorized) Reset() { + c.trace = nil + c.logger.Debugf("Reset: Cleared debug trace") +} + +// Row renders a table data row with configured colors and formatting. +func (c *Colorized) Row(row []string, ctx tw.Formatting) { + c.logger.Debugf("Starting Row render: IsSubRow=%v, Location=%v, Pos=%s, hasFooter=%v", + ctx.IsSubRow, ctx.Row.Location, ctx.Row.Position, ctx.HasFooter) + + // Check if there is data to render + if len(row) == 0 { + c.logger.Debugf("Row: No data to render") + return + } + + // Render the row line + c.renderLine(ctx, row, c.config.Column) + c.logger.Debugf("Completed Row render") +} + +// Start initializes the rendering process (no-op in this implementation). +func (c *Colorized) Start(w io.Writer) error { + c.w = w + c.logger.Debugf("Colorized.Start() called (no-op).") + return nil +} + +// formatCell formats a cell's content with color, width, padding, and alignment, handling whitespace trimming and truncation. +func (c *Colorized) formatCell(content string, width int, padding tw.Padding, align tw.Align, tint Tint) string { + c.logger.Debugf("Formatting cell: content='%s', width=%d, align=%s, paddingL='%s', paddingR='%s', tintFG=%v, tintBG=%v", + content, width, align, padding.Left, padding.Right, tint.FG, tint.BG) + + // Return empty string if width is non-positive + if width <= 0 { + c.logger.Debugf("formatCell: width %d <= 0, returning empty string", width) + return tw.Empty + } + + // Calculate visual width of content + contentVisualWidth := twwidth.Width(content) + + // Set default padding characters + padLeftCharStr := padding.Left + if padLeftCharStr == tw.Empty { + padLeftCharStr = tw.Space + } + padRightCharStr := padding.Right + if padRightCharStr == tw.Empty { + padRightCharStr = tw.Space + } + + // Calculate padding widths + definedPadLeftWidth := twwidth.Width(padLeftCharStr) + definedPadRightWidth := twwidth.Width(padRightCharStr) + // Calculate available width for content and alignment + availableForContentAndAlign := width - definedPadLeftWidth - definedPadRightWidth + if availableForContentAndAlign < 0 { + availableForContentAndAlign = 0 + } + + // Truncate content if it exceeds available width + if contentVisualWidth > availableForContentAndAlign { + content = twwidth.Truncate(content, availableForContentAndAlign) + contentVisualWidth = twwidth.Width(content) + c.logger.Debugf("Truncated content to fit %d: '%s' (new width %d)", availableForContentAndAlign, content, contentVisualWidth) + } + + // Calculate remaining space for alignment + remainingSpaceForAlignment := availableForContentAndAlign - contentVisualWidth + if remainingSpaceForAlignment < 0 { + remainingSpaceForAlignment = 0 + } + + // Apply alignment padding + leftAlignmentPadSpaces := tw.Empty + rightAlignmentPadSpaces := tw.Empty + switch align { + case tw.AlignLeft: + rightAlignmentPadSpaces = strings.Repeat(tw.Space, remainingSpaceForAlignment) + case tw.AlignRight: + leftAlignmentPadSpaces = strings.Repeat(tw.Space, remainingSpaceForAlignment) + case tw.AlignCenter: + leftSpacesCount := remainingSpaceForAlignment / 2 + rightSpacesCount := remainingSpaceForAlignment - leftSpacesCount + leftAlignmentPadSpaces = strings.Repeat(tw.Space, leftSpacesCount) + rightAlignmentPadSpaces = strings.Repeat(tw.Space, rightSpacesCount) + default: + // Default to left alignment + rightAlignmentPadSpaces = strings.Repeat(tw.Space, remainingSpaceForAlignment) + } + + // Apply colors to content and padding + coloredContent := tint.Apply(content) + coloredPadLeft := padLeftCharStr + coloredPadRight := padRightCharStr + coloredAlignPadLeft := leftAlignmentPadSpaces + coloredAlignPadRight := rightAlignmentPadSpaces + + if len(tint.BG) > 0 { + bgTint := Tint{BG: tint.BG} + // Apply foreground color to non-space padding if foreground is defined + if len(tint.FG) > 0 && padLeftCharStr != tw.Space { + coloredPadLeft = tint.Apply(padLeftCharStr) + } else { + coloredPadLeft = bgTint.Apply(padLeftCharStr) + } + if len(tint.FG) > 0 && padRightCharStr != tw.Space { + coloredPadRight = tint.Apply(padRightCharStr) + } else { + coloredPadRight = bgTint.Apply(padRightCharStr) + } + // Apply background color to alignment padding + if leftAlignmentPadSpaces != tw.Empty { + coloredAlignPadLeft = bgTint.Apply(leftAlignmentPadSpaces) + } + if rightAlignmentPadSpaces != tw.Empty { + coloredAlignPadRight = bgTint.Apply(rightAlignmentPadSpaces) + } + } else if len(tint.FG) > 0 { + // Apply foreground color to non-space padding + if padLeftCharStr != tw.Space { + coloredPadLeft = tint.Apply(padLeftCharStr) + } + if padRightCharStr != tw.Space { + coloredPadRight = tint.Apply(padRightCharStr) + } + } + + // Build final cell string + var sb strings.Builder + sb.WriteString(coloredPadLeft) + sb.WriteString(coloredAlignPadLeft) + sb.WriteString(coloredContent) + sb.WriteString(coloredAlignPadRight) + sb.WriteString(coloredPadRight) + output := sb.String() + + // Adjust output width if necessary + currentVisualWidth := twwidth.Width(output) + if currentVisualWidth != width { + c.logger.Debugf("formatCell MISMATCH: content='%s', target_w=%d. Calculated parts width = %d. String: '%s'", + content, width, currentVisualWidth, output) + if currentVisualWidth > width { + output = twwidth.Truncate(output, width) + } else { + paddingSpacesStr := strings.Repeat(tw.Space, width-currentVisualWidth) + if len(tint.BG) > 0 { + output += Tint{BG: tint.BG}.Apply(paddingSpacesStr) + } else { + output += paddingSpacesStr + } + } + c.logger.Debugf("formatCell Post-Correction: Target %d, New Visual width %d. Output: '%s'", width, twwidth.Width(output), output) + } + + c.logger.Debugf("Formatted cell final result: '%s' (target width %d, display width %d)", output, width, twwidth.Width(output)) + return output +} + +// renderLine renders a single line (header, row, or footer) with colors, handling merges and separators. +func (c *Colorized) renderLine(ctx tw.Formatting, line []string, tint Tint) { + // Determine number of columns + numCols := 0 + if len(ctx.Row.Current) > 0 { + maxKey := -1 + for k := range ctx.Row.Current { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else { + maxKey := -1 + for k := range ctx.Row.Widths { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } + + var output strings.Builder + + // Add left border if enabled + prefix := tw.Empty + if c.config.Borders.Left.Enabled() { + prefix = c.config.Border.Apply(c.config.Symbols.Column()) + } + output.WriteString(prefix) + + // Set up separator + separatorDisplayWidth := 0 + separatorString := tw.Empty + if c.config.Settings.Separators.BetweenColumns.Enabled() { + separatorString = c.config.Separator.Apply(c.config.Symbols.Column()) + separatorDisplayWidth = twwidth.Width(c.config.Symbols.Column()) + } + + // Process each column + for i := 0; i < numCols; { + // Determine if a separator is needed + shouldAddSeparator := false + if i > 0 && c.config.Settings.Separators.BetweenColumns.Enabled() { + cellCtx, ok := ctx.Row.Current[i] + if !ok || !(cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start) { + shouldAddSeparator = true + } + } + if shouldAddSeparator { + output.WriteString(separatorString) + c.logger.Debugf("renderLine: Added separator '%s' before col %d", separatorString, i) + } else if i > 0 { + c.logger.Debugf("renderLine: Skipped separator before col %d due to HMerge continuation", i) + } + + // Get cell context, use default if not present + cellCtx, ok := ctx.Row.Current[i] + if !ok { + cellCtx = tw.CellContext{ + Data: tw.Empty, + Align: c.defaultAlign[ctx.Row.Position], + Padding: tw.Padding{Left: tw.Space, Right: tw.Space}, + Width: ctx.Row.Widths.Get(i), + Merge: tw.MergeState{}, + } + } + + // Handle merged cells + visualWidth := 0 + span := 1 + isHMergeStart := ok && cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start + + if isHMergeStart { + span = cellCtx.Merge.Horizontal.Span + if ctx.Row.Position == tw.Row { + // Calculate dynamic width for row merges + dynamicTotalWidth := 0 + for k := 0; k < span && i+k < numCols; k++ { + colToSum := i + k + normWidth := ctx.NormalizedWidths.Get(colToSum) + if normWidth < 0 { + normWidth = 0 + } + dynamicTotalWidth += normWidth + if k > 0 && separatorDisplayWidth > 0 { + dynamicTotalWidth += separatorDisplayWidth + } + } + visualWidth = dynamicTotalWidth + c.logger.Debugf("renderLine: Row HMerge col %d, span %d, dynamic visualWidth %d", i, span, visualWidth) + } else { + visualWidth = ctx.Row.Widths.Get(i) + c.logger.Debugf("renderLine: H/F HMerge col %d, span %d, pre-adjusted visualWidth %d", i, span, visualWidth) + } + } else { + visualWidth = ctx.Row.Widths.Get(i) + c.logger.Debugf("renderLine: Regular col %d, visualWidth %d", i, visualWidth) + } + if visualWidth < 0 { + visualWidth = 0 + } + + // Skip processing for non-start merged cells + if ok && cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start { + c.logger.Debugf("renderLine: Skipping col %d processing (part of HMerge)", i) + i++ + continue + } + + // Handle empty cell context with non-zero width + if !ok && visualWidth > 0 { + spaces := strings.Repeat(tw.Space, visualWidth) + if len(tint.BG) > 0 { + output.WriteString(Tint{BG: tint.BG}.Apply(spaces)) + } else { + output.WriteString(spaces) + } + c.logger.Debugf("renderLine: No cell context for col %d, writing %d spaces", i, visualWidth) + i += span + continue + } + + // Set cell alignment + padding := cellCtx.Padding + align := cellCtx.Align + if align == tw.AlignNone { + align = c.defaultAlign[ctx.Row.Position] + c.logger.Debugf("renderLine: col %d using default renderer align '%s' for position %s because cellCtx.Align was AlignNone", i, align, ctx.Row.Position) + } + + // Detect and handle TOTAL pattern + isTotalPattern := false + if i == 0 && isHMergeStart && cellCtx.Merge.Horizontal.Span >= 3 && strings.TrimSpace(cellCtx.Data) == "TOTAL" { + isTotalPattern = true + c.logger.Debugf("renderLine: Detected 'TOTAL' HMerge pattern at col 0") + } + // Override alignment for footer merges or TOTAL pattern + if (ctx.Row.Position == tw.Footer && isHMergeStart) || isTotalPattern { + if align != tw.AlignRight { + c.logger.Debugf("renderLine: Applying AlignRight override for Footer HMerge/TOTAL pattern at col %d. Original/default align was: %s", i, align) + align = tw.AlignRight + } + } + + // Handle vertical/hierarchical merges + content := cellCtx.Data + if (cellCtx.Merge.Vertical.Present && !cellCtx.Merge.Vertical.Start) || + (cellCtx.Merge.Hierarchical.Present && !cellCtx.Merge.Hierarchical.Start) { + content = tw.Empty + c.logger.Debugf("renderLine: Blanked data for col %d (non-start V/Hierarchical)", i) + } + + // Apply per-column tint if available + cellTint := tint + if i < len(tint.Columns) { + columnTint := tint.Columns[i] + if len(columnTint.FG) > 0 || len(columnTint.BG) > 0 { + cellTint = columnTint + } + } + + // Format and render the cell + formattedCell := c.formatCell(content, visualWidth, padding, align, cellTint) + if len(formattedCell) > 0 { + output.WriteString(formattedCell) + } else if visualWidth == 0 && isHMergeStart { + c.logger.Debugf("renderLine: Rendered HMerge START col %d resulted in 0 visual width, wrote nothing.", i) + } else if visualWidth == 0 { + c.logger.Debugf("renderLine: Rendered regular col %d resulted in 0 visual width, wrote nothing.", i) + } + + // Log rendering details + if isHMergeStart { + c.logger.Debugf("renderLine: Rendered HMerge START col %d (span %d, visualWidth %d, align %s): '%s'", + i, span, visualWidth, align, formattedCell) + } else { + c.logger.Debugf("renderLine: Rendered regular col %d (visualWidth %d, align %s): '%s'", + i, visualWidth, align, formattedCell) + } + + i += span + } + + // Add right border if enabled + suffix := tw.Empty + if c.config.Borders.Right.Enabled() { + suffix = c.config.Border.Apply(c.config.Symbols.Column()) + } + output.WriteString(suffix) + + // Write the final line + output.WriteString(c.newLine) + c.w.Write([]byte(output.String())) + c.logger.Debugf("renderLine: Final rendered line: %s", strings.TrimSuffix(output.String(), c.newLine)) +} + +// Rendition updates the parts of ColorizedConfig that correspond to tw.Rendition +// by merging the provided newRendition. Color-specific Tints are not modified. +func (c *Colorized) Rendition(newRendition tw.Rendition) { // Method name matches interface + c.logger.Debug("Colorized.Rendition called. Current B/Sym/Set: B:%+v, Sym:%T, S:%+v. Override: %+v", c.config.Borders, c.config.Symbols, c.config.Settings, newRendition) + + currentRenditionPart := tw.Rendition{ + Borders: c.config.Borders, + Symbols: c.config.Symbols, + Settings: c.config.Settings, + } + + mergedRenditionPart := mergeRendition(currentRenditionPart, newRendition) + + c.config.Borders = mergedRenditionPart.Borders + c.config.Symbols = mergedRenditionPart.Symbols + if c.config.Symbols == nil { + c.config.Symbols = tw.NewSymbols(tw.StyleLight) + } + c.config.Settings = mergedRenditionPart.Settings + + c.logger.Debugf("Colorized.Rendition updated. New B/Sym/Set: B:%+v, Sym:%T, S:%+v", + c.config.Borders, c.config.Symbols, c.config.Settings) +} + +// Ensure Colorized implements tw.Renditioning +var _ tw.Renditioning = (*Colorized)(nil) diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/fn.go b/vendor/github.com/olekukonko/tablewriter/renderer/fn.go new file mode 100644 index 00000000..3bda04f4 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/fn.go @@ -0,0 +1,236 @@ +package renderer + +import ( + "fmt" + "github.com/fatih/color" + "github.com/olekukonko/tablewriter/tw" +) + +// defaultBlueprint returns a default Rendition for ASCII table rendering with borders and light symbols. +func defaultBlueprint() tw.Rendition { + return tw.Rendition{ + Borders: tw.Border{ + Left: tw.On, + Right: tw.On, + Top: tw.On, + Bottom: tw.On, + }, + Settings: tw.Settings{ + Separators: tw.Separators{ + ShowHeader: tw.On, + ShowFooter: tw.On, + BetweenRows: tw.Off, + BetweenColumns: tw.On, + }, + Lines: tw.Lines{ + ShowTop: tw.On, + ShowBottom: tw.On, + ShowHeaderLine: tw.On, + ShowFooterLine: tw.On, + }, + CompactMode: tw.Off, + // Cushion: tw.On, + }, + Symbols: tw.NewSymbols(tw.StyleLight), + Streaming: true, + } +} + +// defaultColorized returns a default ColorizedConfig optimized for dark terminal backgrounds with colored headers, rows, and borders. +func defaultColorized() ColorizedConfig { + return ColorizedConfig{ + Borders: tw.Border{Left: tw.On, Right: tw.On, Top: tw.On, Bottom: tw.On}, + Settings: tw.Settings{ + Separators: tw.Separators{ + ShowHeader: tw.On, + ShowFooter: tw.On, + BetweenRows: tw.Off, + BetweenColumns: tw.On, + }, + Lines: tw.Lines{ + ShowTop: tw.On, + ShowBottom: tw.On, + ShowHeaderLine: tw.On, + ShowFooterLine: tw.On, + }, + + CompactMode: tw.Off, + }, + Header: Tint{ + FG: Colors{color.FgWhite, color.Bold}, + BG: Colors{color.BgBlack}, + }, + Column: Tint{ + FG: Colors{color.FgCyan}, + BG: Colors{color.BgBlack}, + }, + Footer: Tint{ + FG: Colors{color.FgYellow}, + BG: Colors{color.BgBlack}, + }, + Border: Tint{ + FG: Colors{color.FgWhite}, + BG: Colors{color.BgBlack}, + }, + Separator: Tint{ + FG: Colors{color.FgWhite}, + BG: Colors{color.BgBlack}, + }, + Symbols: tw.NewSymbols(tw.StyleLight), + } +} + +// defaultOceanRendererConfig returns a base tw.Rendition for the Ocean renderer. +func defaultOceanRendererConfig() tw.Rendition { + + return tw.Rendition{ + Borders: tw.Border{ + Left: tw.On, Right: tw.On, Top: tw.On, Bottom: tw.On, + }, + Settings: tw.Settings{ + Separators: tw.Separators{ + ShowHeader: tw.On, + ShowFooter: tw.Off, + BetweenRows: tw.Off, + BetweenColumns: tw.On, + }, + Lines: tw.Lines{ + ShowTop: tw.On, + ShowBottom: tw.On, + ShowHeaderLine: tw.On, + ShowFooterLine: tw.Off, + }, + + CompactMode: tw.Off, + }, + Symbols: tw.NewSymbols(tw.StyleDefault), + Streaming: true, + } +} + +// getHTMLStyle remains the same +func getHTMLStyle(align tw.Align) string { + styleContent := tw.Empty + switch align { + case tw.AlignRight: + styleContent = "text-align: right;" + case tw.AlignCenter: + styleContent = "text-align: center;" + case tw.AlignLeft: + styleContent = "text-align: left;" + } + if styleContent != tw.Empty { + return fmt.Sprintf(` style="%s"`, styleContent) + } + return tw.Empty +} + +// mergeLines combines default and override line settings, preserving defaults for unset (zero) overrides. +func mergeLines(defaults, overrides tw.Lines) tw.Lines { + if overrides.ShowTop != 0 { + defaults.ShowTop = overrides.ShowTop + } + if overrides.ShowBottom != 0 { + defaults.ShowBottom = overrides.ShowBottom + } + if overrides.ShowHeaderLine != 0 { + defaults.ShowHeaderLine = overrides.ShowHeaderLine + } + if overrides.ShowFooterLine != 0 { + defaults.ShowFooterLine = overrides.ShowFooterLine + } + return defaults +} + +// mergeSeparators combines default and override separator settings, preserving defaults for unset (zero) overrides. +func mergeSeparators(defaults, overrides tw.Separators) tw.Separators { + if overrides.ShowHeader != 0 { + defaults.ShowHeader = overrides.ShowHeader + } + if overrides.ShowFooter != 0 { + defaults.ShowFooter = overrides.ShowFooter + } + if overrides.BetweenRows != 0 { + defaults.BetweenRows = overrides.BetweenRows + } + if overrides.BetweenColumns != 0 { + defaults.BetweenColumns = overrides.BetweenColumns + } + return defaults +} + +// mergeSettings combines default and override settings, preserving defaults for unset (zero) overrides. +func mergeSettings(defaults, overrides tw.Settings) tw.Settings { + if overrides.Separators.ShowHeader != tw.Unknown { + defaults.Separators.ShowHeader = overrides.Separators.ShowHeader + } + if overrides.Separators.ShowFooter != tw.Unknown { + defaults.Separators.ShowFooter = overrides.Separators.ShowFooter + } + if overrides.Separators.BetweenRows != tw.Unknown { + defaults.Separators.BetweenRows = overrides.Separators.BetweenRows + } + if overrides.Separators.BetweenColumns != tw.Unknown { + defaults.Separators.BetweenColumns = overrides.Separators.BetweenColumns + } + if overrides.Lines.ShowTop != tw.Unknown { + defaults.Lines.ShowTop = overrides.Lines.ShowTop + } + if overrides.Lines.ShowBottom != tw.Unknown { + defaults.Lines.ShowBottom = overrides.Lines.ShowBottom + } + if overrides.Lines.ShowHeaderLine != tw.Unknown { + defaults.Lines.ShowHeaderLine = overrides.Lines.ShowHeaderLine + } + if overrides.Lines.ShowFooterLine != tw.Unknown { + defaults.Lines.ShowFooterLine = overrides.Lines.ShowFooterLine + } + + if overrides.CompactMode != tw.Unknown { + defaults.CompactMode = overrides.CompactMode + } + + //if overrides.Cushion != tw.Unknown { + // defaults.Cushion = overrides.Cushion + //} + + return defaults +} + +// MergeRendition merges the 'override' rendition into the 'current' rendition. +// It only updates fields in 'current' if they are explicitly set (non-zero/non-nil) in 'override'. +// This allows for partial updates to a renderer's configuration. +func mergeRendition(current, override tw.Rendition) tw.Rendition { + // Merge Borders: Only update if override border states are explicitly set (not 0). + // A tw.State's zero value is 0, which is distinct from tw.On (1) or tw.Off (-1). + // So, if override.Borders.Left is 0, it means "not specified", so we keep current. + if override.Borders.Left != 0 { + current.Borders.Left = override.Borders.Left + } + if override.Borders.Right != 0 { + current.Borders.Right = override.Borders.Right + } + if override.Borders.Top != 0 { + current.Borders.Top = override.Borders.Top + } + if override.Borders.Bottom != 0 { + current.Borders.Bottom = override.Borders.Bottom + } + + // Merge Symbols: Only update if override.Symbols is not nil. + if override.Symbols != nil { + current.Symbols = override.Symbols + } + + // Merge Settings: Use the existing mergeSettings for granular control. + // mergeSettings already handles preserving defaults for unset (zero) overrides. + current.Settings = mergeSettings(current.Settings, override.Settings) + + // Streaming flag: typically set at renderer creation, but can be overridden if needed. + // For now, let's assume it's not commonly changed post-creation by a generic rendition merge. + // If override provides a different streaming capability, it might indicate a fundamental + // change that a simple merge shouldn't handle without more context. + // current.Streaming = override.Streaming // Or keep current.Streaming + + return current +} diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/html.go b/vendor/github.com/olekukonko/tablewriter/renderer/html.go new file mode 100644 index 00000000..62430a17 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/html.go @@ -0,0 +1,441 @@ +package renderer + +import ( + "errors" + "fmt" + "github.com/olekukonko/ll" + "html" + "io" + "strings" + + "github.com/olekukonko/tablewriter/tw" +) + +// HTMLConfig defines settings for the HTML table renderer. +type HTMLConfig struct { + EscapeContent bool // Whether to escape cell content + AddLinesTag bool // Whether to wrap multiline content in tags + TableClass string // CSS class for + HeaderClass string // CSS class for + BodyClass string // CSS class for + FooterClass string // CSS class for + RowClass string // CSS class for in body + HeaderRowClass string // CSS class for in header + FooterRowClass string // CSS class for in footer +} + +// HTML renders tables in HTML format with customizable classes and content handling. +type HTML struct { + config HTMLConfig // Renderer configuration + w io.Writer // Output w + trace []string // Debug trace messages + debug bool // Enables debug logging + tableStarted bool // Tracks if
tag is open + tbodyStarted bool // Tracks if tag is open + tfootStarted bool // Tracks if tag is open + vMergeTrack map[int]int // Tracks vertical merge spans by column index + logger *ll.Logger +} + +// NewHTML initializes an HTML renderer with the given w, debug setting, and optional configuration. +// It panics if the w is nil and applies defaults for unset config fields. +// Update: see https://github.com/olekukonko/tablewriter/issues/258 +func NewHTML(configs ...HTMLConfig) *HTML { + cfg := HTMLConfig{ + EscapeContent: true, + AddLinesTag: false, + } + if len(configs) > 0 { + userCfg := configs[0] + cfg.EscapeContent = userCfg.EscapeContent + cfg.AddLinesTag = userCfg.AddLinesTag + cfg.TableClass = userCfg.TableClass + cfg.HeaderClass = userCfg.HeaderClass + cfg.BodyClass = userCfg.BodyClass + cfg.FooterClass = userCfg.FooterClass + cfg.RowClass = userCfg.RowClass + cfg.HeaderRowClass = userCfg.HeaderRowClass + cfg.FooterRowClass = userCfg.FooterRowClass + } + return &HTML{ + config: cfg, + vMergeTrack: make(map[int]int), + tableStarted: false, + tbodyStarted: false, + tfootStarted: false, + logger: ll.New("html"), + } +} + +func (h *HTML) Logger(logger *ll.Logger) { + h.logger = logger +} + +// Config returns a Rendition representation of the current configuration. +func (h *HTML) Config() tw.Rendition { + return tw.Rendition{ + Borders: tw.BorderNone, + Symbols: tw.NewSymbols(tw.StyleNone), + Settings: tw.Settings{}, + Streaming: false, + } +} + +// debugLog appends a formatted message to the debug trace if debugging is enabled. +//func (h *HTML) debugLog(format string, a ...interface{}) { +// if h.debug { +// msg := fmt.Sprintf(format, a...) +// h.trace = append(h.trace, fmt.Sprintf("[HTML] %s", msg)) +// } +//} + +// Debug returns the accumulated debug trace messages. +func (h *HTML) Debug() []string { + return h.trace +} + +// Start begins the HTML table rendering by opening the
tag. +func (h *HTML) Start(w io.Writer) error { + h.w = w + h.Reset() + h.logger.Debug("HTML.Start() called.") + + classAttr := tw.Empty + if h.config.TableClass != tw.Empty { + classAttr = fmt.Sprintf(` class="%s"`, h.config.TableClass) + } + h.logger.Debugf("Writing opening tag", classAttr) + _, err := fmt.Fprintf(h.w, "\n", classAttr) + if err != nil { + return err + } + h.tableStarted = true + return nil +} + +// closePreviousSection closes any open or sections. +func (h *HTML) closePreviousSection() { + if h.tbodyStarted { + h.logger.Debug("Closing tag") + fmt.Fprintln(h.w, "") + h.tbodyStarted = false + } + if h.tfootStarted { + h.logger.Debug("Closing tag") + fmt.Fprintln(h.w, "") + h.tfootStarted = false + } +} + +// Header renders the section with header rows, supporting horizontal merges. +func (h *HTML) Header(headers [][]string, ctx tw.Formatting) { + if !h.tableStarted { + h.logger.Debug("WARN: Header called before Start") + return + } + if len(headers) == 0 || len(headers[0]) == 0 { + h.logger.Debug("Header: No headers") + return + } + + h.closePreviousSection() + classAttr := tw.Empty + if h.config.HeaderClass != tw.Empty { + classAttr = fmt.Sprintf(` class="%s"`, h.config.HeaderClass) + } + fmt.Fprintf(h.w, "\n", classAttr) + + headerRow := headers[0] + numCols := 0 + if len(ctx.Row.Current) > 0 { + maxKey := -1 + for k := range ctx.Row.Current { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else if len(headerRow) > 0 { + numCols = len(headerRow) + } + + indent := " " + rowClassAttr := tw.Empty + if h.config.HeaderRowClass != tw.Empty { + rowClassAttr = fmt.Sprintf(` class="%s"`, h.config.HeaderRowClass) + } + fmt.Fprintf(h.w, "%s", indent, rowClassAttr) + + renderedCols := 0 + for colIdx := 0; renderedCols < numCols && colIdx < numCols; { + // Skip columns consumed by vertical merges + if remainingSpan, merging := h.vMergeTrack[colIdx]; merging && remainingSpan > 1 { + h.logger.Debugf("Header: Skipping col %d due to vmerge", colIdx) + h.vMergeTrack[colIdx]-- + if h.vMergeTrack[colIdx] <= 1 { + delete(h.vMergeTrack, colIdx) + } + colIdx++ + continue + } + + // Render cell + cellCtx, ok := ctx.Row.Current[colIdx] + if !ok { + cellCtx = tw.CellContext{Align: tw.AlignCenter} + } + originalContent := tw.Empty + if colIdx < len(headerRow) { + originalContent = headerRow[colIdx] + } + + tag, attributes, processedContent := h.renderRowCell(originalContent, cellCtx, true, colIdx) + fmt.Fprintf(h.w, "<%s%s>%s", tag, attributes, processedContent, tag) + renderedCols++ + + // Handle horizontal merges + hSpan := 1 + if cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start { + hSpan = cellCtx.Merge.Horizontal.Span + renderedCols += (hSpan - 1) + } + colIdx += hSpan + } + fmt.Fprintf(h.w, "\n") + fmt.Fprintln(h.w, "") +} + +// Row renders a element within , supporting horizontal and vertical merges. +func (h *HTML) Row(row []string, ctx tw.Formatting) { + if !h.tableStarted { + h.logger.Debug("WARN: Row called before Start") + return + } + + if !h.tbodyStarted { + h.closePreviousSection() + classAttr := tw.Empty + if h.config.BodyClass != tw.Empty { + classAttr = fmt.Sprintf(` class="%s"`, h.config.BodyClass) + } + h.logger.Debugf("Writing opening tag", classAttr) + fmt.Fprintf(h.w, "\n", classAttr) + h.tbodyStarted = true + } + + h.logger.Debugf("Rendering row data: %v", row) + numCols := 0 + if len(ctx.Row.Current) > 0 { + maxKey := -1 + for k := range ctx.Row.Current { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else if len(row) > 0 { + numCols = len(row) + } + + indent := " " + rowClassAttr := tw.Empty + if h.config.RowClass != tw.Empty { + rowClassAttr = fmt.Sprintf(` class="%s"`, h.config.RowClass) + } + fmt.Fprintf(h.w, "%s", indent, rowClassAttr) + + renderedCols := 0 + for colIdx := 0; renderedCols < numCols && colIdx < numCols; { + // Skip columns consumed by vertical merges + if remainingSpan, merging := h.vMergeTrack[colIdx]; merging && remainingSpan > 1 { + h.logger.Debugf("Row: Skipping render for col %d due to vertical merge (remaining %d)", colIdx, remainingSpan-1) + h.vMergeTrack[colIdx]-- + if h.vMergeTrack[colIdx] <= 1 { + delete(h.vMergeTrack, colIdx) + } + colIdx++ + continue + } + + // Render cell + cellCtx, ok := ctx.Row.Current[colIdx] + if !ok { + cellCtx = tw.CellContext{Align: tw.AlignLeft} + } + originalContent := tw.Empty + if colIdx < len(row) { + originalContent = row[colIdx] + } + + tag, attributes, processedContent := h.renderRowCell(originalContent, cellCtx, false, colIdx) + fmt.Fprintf(h.w, "<%s%s>%s", tag, attributes, processedContent, tag) + renderedCols++ + + // Handle horizontal merges + hSpan := 1 + if cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start { + hSpan = cellCtx.Merge.Horizontal.Span + renderedCols += (hSpan - 1) + } + colIdx += hSpan + } + fmt.Fprintf(h.w, "\n") +} + +// Footer renders the section with footer rows, supporting horizontal merges. +func (h *HTML) Footer(footers [][]string, ctx tw.Formatting) { + if !h.tableStarted { + h.logger.Debug("WARN: Footer called before Start") + return + } + if len(footers) == 0 || len(footers[0]) == 0 { + h.logger.Debug("Footer: No footers") + return + } + + h.closePreviousSection() + classAttr := tw.Empty + if h.config.FooterClass != tw.Empty { + classAttr = fmt.Sprintf(` class="%s"`, h.config.FooterClass) + } + fmt.Fprintf(h.w, "\n", classAttr) + h.tfootStarted = true + + footerRow := footers[0] + numCols := 0 + if len(ctx.Row.Current) > 0 { + maxKey := -1 + for k := range ctx.Row.Current { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else if len(footerRow) > 0 { + numCols = len(footerRow) + } + + indent := " " + rowClassAttr := tw.Empty + if h.config.FooterRowClass != tw.Empty { + rowClassAttr = fmt.Sprintf(` class="%s"`, h.config.FooterRowClass) + } + fmt.Fprintf(h.w, "%s", indent, rowClassAttr) + + renderedCols := 0 + for colIdx := 0; renderedCols < numCols && colIdx < numCols; { + cellCtx, ok := ctx.Row.Current[colIdx] + if !ok { + cellCtx = tw.CellContext{Align: tw.AlignRight} + } + originalContent := tw.Empty + if colIdx < len(footerRow) { + originalContent = footerRow[colIdx] + } + + tag, attributes, processedContent := h.renderRowCell(originalContent, cellCtx, false, colIdx) + fmt.Fprintf(h.w, "<%s%s>%s", tag, attributes, processedContent, tag) + renderedCols++ + + hSpan := 1 + if cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start { + hSpan = cellCtx.Merge.Horizontal.Span + renderedCols += (hSpan - 1) + } + colIdx += hSpan + } + fmt.Fprintf(h.w, "\n") + fmt.Fprintln(h.w, "") + h.tfootStarted = false +} + +// renderRowCell generates HTML for a single cell, handling content escaping, merges, and alignment. +func (h *HTML) renderRowCell(originalContent string, cellCtx tw.CellContext, isHeader bool, colIdx int) (tag, attributes, processedContent string) { + tag = "td" + if isHeader { + tag = "th" + } + + // Process content + processedContent = originalContent + containsNewline := strings.Contains(originalContent, "\n") + + if h.config.EscapeContent { + if containsNewline { + const newlinePlaceholder = "[[--HTML_RENDERER_BR_PLACEHOLDER--]]" + tempContent := strings.ReplaceAll(originalContent, "\n", newlinePlaceholder) + escapedContent := html.EscapeString(tempContent) + processedContent = strings.ReplaceAll(escapedContent, newlinePlaceholder, "
") + } else { + processedContent = html.EscapeString(originalContent) + } + } else if containsNewline { + processedContent = strings.ReplaceAll(originalContent, "\n", "
") + } + + if containsNewline && h.config.AddLinesTag { + processedContent = "" + processedContent + "" + } + + // Build attributes + var attrBuilder strings.Builder + merge := cellCtx.Merge + + if merge.Horizontal.Present && merge.Horizontal.Start && merge.Horizontal.Span > 1 { + fmt.Fprintf(&attrBuilder, ` colspan="%d"`, merge.Horizontal.Span) + } + + vSpan := 0 + if !isHeader { + if merge.Vertical.Present && merge.Vertical.Start { + vSpan = merge.Vertical.Span + } else if merge.Hierarchical.Present && merge.Hierarchical.Start { + vSpan = merge.Hierarchical.Span + } + if vSpan > 1 { + fmt.Fprintf(&attrBuilder, ` rowspan="%d"`, vSpan) + h.vMergeTrack[colIdx] = vSpan + h.logger.Debugf("renderRowCell: Tracking rowspan=%d for col %d", vSpan, colIdx) + } + } + + if style := getHTMLStyle(cellCtx.Align); style != tw.Empty { + attrBuilder.WriteString(style) + } + attributes = attrBuilder.String() + return +} + +// Line is a no-op for HTML rendering, as structural lines are handled by tags. +func (h *HTML) Line(ctx tw.Formatting) {} + +// Reset clears the renderer's internal state, including debug traces and merge tracking. +func (h *HTML) Reset() { + h.logger.Debug("HTML.Reset() called.") + h.tableStarted = false + h.tbodyStarted = false + h.tfootStarted = false + h.vMergeTrack = make(map[int]int) + h.trace = nil +} + +// Close ensures all open HTML tags (
, , ) are properly closed. +func (h *HTML) Close() error { + if h.w == nil { + return errors.New("HTML Renderer Close called on nil internal w") + } + + if h.tableStarted { + h.logger.Debug("HTML.Close() called.") + h.closePreviousSection() + h.logger.Debug("Closing
tag.") + _, err := fmt.Fprintln(h.w, "
") + h.tableStarted = false + h.tbodyStarted = false + h.tfootStarted = false + h.vMergeTrack = make(map[int]int) + return err + } + h.logger.Debug("HTML.Close() called, but table was not started (no-op).") + return nil +} diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/junction.go b/vendor/github.com/olekukonko/tablewriter/renderer/junction.go new file mode 100644 index 00000000..0c684f1a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/junction.go @@ -0,0 +1,273 @@ +package renderer + +import ( + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter/tw" +) + +// Junction handles rendering of table junction points (corners, intersections) with color support. +type Junction struct { + sym tw.Symbols // Symbols used for rendering junctions and lines + ctx tw.Formatting // Current table formatting context + colIdx int // Index of the column being processed + debugging bool // Enables debug logging + borderTint Tint // Colors for border symbols + separatorTint Tint // Colors for separator symbols + logger *ll.Logger +} + +type JunctionContext struct { + Symbols tw.Symbols + Ctx tw.Formatting + ColIdx int + Logger *ll.Logger + BorderTint Tint + SeparatorTint Tint +} + +// NewJunction initializes a Junction with the given symbols, context, and tints. +// If debug is nil, a no-op debug function is used. +func NewJunction(ctx JunctionContext) *Junction { + return &Junction{ + sym: ctx.Symbols, + ctx: ctx.Ctx, + colIdx: ctx.ColIdx, + logger: ctx.Logger.Namespace("junction"), + borderTint: ctx.BorderTint, + separatorTint: ctx.SeparatorTint, + } +} + +// getMergeState retrieves the merge state for a specific column in a row, returning an empty state if not found. +func (jr *Junction) getMergeState(row map[int]tw.CellContext, colIdx int) tw.MergeState { + if row == nil || colIdx < 0 { + return tw.MergeState{} + } + return row[colIdx].Merge +} + +// GetSegment determines whether to render a colored horizontal line or an empty space based on merge states. +func (jr *Junction) GetSegment() string { + currentMerge := jr.getMergeState(jr.ctx.Row.Current, jr.colIdx) + nextMerge := jr.getMergeState(jr.ctx.Row.Next, jr.colIdx) + + vPassThruStrict := (currentMerge.Vertical.Present && nextMerge.Vertical.Present && !currentMerge.Vertical.End && !nextMerge.Vertical.Start) || + (currentMerge.Hierarchical.Present && nextMerge.Hierarchical.Present && !currentMerge.Hierarchical.End && !nextMerge.Hierarchical.Start) + + if vPassThruStrict { + jr.logger.Debugf("GetSegment col %d: VPassThruStrict=%v -> Empty segment", jr.colIdx, vPassThruStrict) + return tw.Empty + } + symbol := jr.sym.Row() + coloredSymbol := jr.borderTint.Apply(symbol) + jr.logger.Debugf("GetSegment col %d: VPassThruStrict=%v -> Colored row symbol '%s'", jr.colIdx, vPassThruStrict, coloredSymbol) + return coloredSymbol +} + +// RenderLeft selects and colors the leftmost junction symbol for the current row line based on position and merges. +func (jr *Junction) RenderLeft() string { + mergeAbove := jr.getMergeState(jr.ctx.Row.Current, 0) + mergeBelow := jr.getMergeState(jr.ctx.Row.Next, 0) + + jr.logger.Debugf("RenderLeft: Level=%v, Location=%v, Previous=%v", jr.ctx.Level, jr.ctx.Row.Location, jr.ctx.Row.Previous) + + isTopBorder := (jr.ctx.Level == tw.LevelHeader && jr.ctx.Row.Location == tw.LocationFirst) || + (jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationFirst && jr.ctx.Row.Previous == nil) + if isTopBorder { + symbol := jr.sym.TopLeft() + return jr.borderTint.Apply(symbol) + } + + isBottom := jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationEnd && !jr.ctx.HasFooter + isFooter := jr.ctx.Level == tw.LevelFooter && jr.ctx.Row.Location == tw.LocationEnd + if isBottom || isFooter { + symbol := jr.sym.BottomLeft() + return jr.borderTint.Apply(symbol) + } + + isVPassThruStrict := (mergeAbove.Vertical.Present && mergeBelow.Vertical.Present && !mergeAbove.Vertical.End && !mergeBelow.Vertical.Start) || + (mergeAbove.Hierarchical.Present && mergeBelow.Hierarchical.Present && !mergeAbove.Hierarchical.End && !mergeBelow.Hierarchical.Start) + if isVPassThruStrict { + symbol := jr.sym.Column() + return jr.separatorTint.Apply(symbol) + } + + symbol := jr.sym.MidLeft() + return jr.borderTint.Apply(symbol) +} + +// RenderRight selects and colors the rightmost junction symbol for the row line based on position, merges, and last column index. +func (jr *Junction) RenderRight(lastColIdx int) string { + jr.logger.Debugf("RenderRight: lastColIdx=%d, Level=%v, Location=%v, Previous=%v", lastColIdx, jr.ctx.Level, jr.ctx.Row.Location, jr.ctx.Row.Previous) + + if lastColIdx < 0 { + switch jr.ctx.Level { + case tw.LevelHeader: + symbol := jr.sym.TopRight() + return jr.borderTint.Apply(symbol) + case tw.LevelFooter: + symbol := jr.sym.BottomRight() + return jr.borderTint.Apply(symbol) + default: + if jr.ctx.Row.Location == tw.LocationFirst { + symbol := jr.sym.TopRight() + return jr.borderTint.Apply(symbol) + } + if jr.ctx.Row.Location == tw.LocationEnd { + symbol := jr.sym.BottomRight() + return jr.borderTint.Apply(symbol) + } + symbol := jr.sym.MidRight() + return jr.borderTint.Apply(symbol) + } + } + + mergeAbove := jr.getMergeState(jr.ctx.Row.Current, lastColIdx) + mergeBelow := jr.getMergeState(jr.ctx.Row.Next, lastColIdx) + + isTopBorder := (jr.ctx.Level == tw.LevelHeader && jr.ctx.Row.Location == tw.LocationFirst) || + (jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationFirst && jr.ctx.Row.Previous == nil) + if isTopBorder { + symbol := jr.sym.TopRight() + return jr.borderTint.Apply(symbol) + } + + isBottom := jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationEnd && !jr.ctx.HasFooter + isFooter := jr.ctx.Level == tw.LevelFooter && jr.ctx.Row.Location == tw.LocationEnd + if isBottom || isFooter { + symbol := jr.sym.BottomRight() + return jr.borderTint.Apply(symbol) + } + + isVPassThruStrict := (mergeAbove.Vertical.Present && mergeBelow.Vertical.Present && !mergeAbove.Vertical.End && !mergeBelow.Vertical.Start) || + (mergeAbove.Hierarchical.Present && mergeBelow.Hierarchical.Present && !mergeAbove.Hierarchical.End && !mergeBelow.Hierarchical.Start) + if isVPassThruStrict { + symbol := jr.sym.Column() + return jr.separatorTint.Apply(symbol) + } + + symbol := jr.sym.MidRight() + return jr.borderTint.Apply(symbol) +} + +// RenderJunction selects and colors the junction symbol between two adjacent columns based on merge states and table position. +func (jr *Junction) RenderJunction(leftColIdx, rightColIdx int) string { + mergeCurrentL := jr.getMergeState(jr.ctx.Row.Current, leftColIdx) + mergeCurrentR := jr.getMergeState(jr.ctx.Row.Current, rightColIdx) + mergeNextL := jr.getMergeState(jr.ctx.Row.Next, leftColIdx) + mergeNextR := jr.getMergeState(jr.ctx.Row.Next, rightColIdx) + + isSpannedCurrent := mergeCurrentL.Horizontal.Present && !mergeCurrentL.Horizontal.End + isSpannedNext := mergeNextL.Horizontal.Present && !mergeNextL.Horizontal.End + + vPassThruLStrict := (mergeCurrentL.Vertical.Present && mergeNextL.Vertical.Present && !mergeCurrentL.Vertical.End && !mergeNextL.Vertical.Start) || + (mergeCurrentL.Hierarchical.Present && mergeNextL.Hierarchical.Present && !mergeCurrentL.Hierarchical.End && !mergeNextL.Hierarchical.Start) + vPassThruRStrict := (mergeCurrentR.Vertical.Present && mergeNextR.Vertical.Present && !mergeCurrentR.Vertical.End && !mergeNextR.Vertical.Start) || + (mergeCurrentR.Hierarchical.Present && mergeNextR.Hierarchical.Present && !mergeCurrentR.Hierarchical.End && !mergeNextR.Hierarchical.Start) + + isTop := (jr.ctx.Level == tw.LevelHeader && jr.ctx.Row.Location == tw.LocationFirst) || + (jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationFirst && len(jr.ctx.Row.Previous) == 0) + isBottom := (jr.ctx.Level == tw.LevelFooter && jr.ctx.Row.Location == tw.LocationEnd) || + (jr.ctx.Level == tw.LevelBody && jr.ctx.Row.Location == tw.LocationEnd && !jr.ctx.HasFooter) + isPreFooter := jr.ctx.Level == tw.LevelFooter && (jr.ctx.Row.Position == tw.Row || jr.ctx.Row.Position == tw.Header) + + if isTop { + if isSpannedNext { + symbol := jr.sym.Row() + return jr.borderTint.Apply(symbol) + } + symbol := jr.sym.TopMid() + return jr.borderTint.Apply(symbol) + } + + if isBottom { + if vPassThruLStrict && vPassThruRStrict { + symbol := jr.sym.Column() + return jr.separatorTint.Apply(symbol) + } + if vPassThruLStrict { + symbol := jr.sym.MidLeft() + return jr.borderTint.Apply(symbol) + } + if vPassThruRStrict { + symbol := jr.sym.MidRight() + return jr.borderTint.Apply(symbol) + } + if isSpannedCurrent { + symbol := jr.sym.Row() + return jr.borderTint.Apply(symbol) + } + symbol := jr.sym.BottomMid() + return jr.borderTint.Apply(symbol) + } + + if isPreFooter { + if vPassThruLStrict && vPassThruRStrict { + symbol := jr.sym.Column() + return jr.separatorTint.Apply(symbol) + } + if vPassThruLStrict { + symbol := jr.sym.MidLeft() + return jr.borderTint.Apply(symbol) + } + if vPassThruRStrict { + symbol := jr.sym.MidRight() + return jr.borderTint.Apply(symbol) + } + if mergeCurrentL.Horizontal.Present { + if !mergeCurrentL.Horizontal.End && mergeCurrentR.Horizontal.Present && !mergeCurrentR.Horizontal.End { + jr.logger.Debugf("Footer separator: H-merge continues from col %d to %d (mid-span), using BottomMid", leftColIdx, rightColIdx) + symbol := jr.sym.BottomMid() + return jr.borderTint.Apply(symbol) + } + if !mergeCurrentL.Horizontal.End && mergeCurrentR.Horizontal.Present && mergeCurrentR.Horizontal.End { + jr.logger.Debugf("Footer separator: H-merge ends at col %d, using BottomMid", rightColIdx) + symbol := jr.sym.BottomMid() + return jr.borderTint.Apply(symbol) + } + if mergeCurrentL.Horizontal.End && !mergeCurrentR.Horizontal.Present { + jr.logger.Debugf("Footer separator: H-merge ends at col %d, next col %d not merged, using Center", leftColIdx, rightColIdx) + symbol := jr.sym.Center() + return jr.borderTint.Apply(symbol) + } + } + if isSpannedNext { + symbol := jr.sym.BottomMid() + return jr.borderTint.Apply(symbol) + } + if isSpannedCurrent { + symbol := jr.sym.TopMid() + return jr.borderTint.Apply(symbol) + } + symbol := jr.sym.Center() + return jr.borderTint.Apply(symbol) + } + + if vPassThruLStrict && vPassThruRStrict { + symbol := jr.sym.Column() + return jr.separatorTint.Apply(symbol) + } + if vPassThruLStrict { + symbol := jr.sym.MidLeft() + return jr.borderTint.Apply(symbol) + } + if vPassThruRStrict { + symbol := jr.sym.MidRight() + return jr.borderTint.Apply(symbol) + } + if isSpannedCurrent && isSpannedNext { + symbol := jr.sym.Row() + return jr.borderTint.Apply(symbol) + } + if isSpannedCurrent { + symbol := jr.sym.TopMid() + return jr.borderTint.Apply(symbol) + } + if isSpannedNext { + symbol := jr.sym.BottomMid() + return jr.borderTint.Apply(symbol) + } + + symbol := jr.sym.Center() + return jr.borderTint.Apply(symbol) +} diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/markdown.go b/vendor/github.com/olekukonko/tablewriter/renderer/markdown.go new file mode 100644 index 00000000..a565cc38 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/markdown.go @@ -0,0 +1,419 @@ +package renderer + +import ( + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "io" + "strings" + + "github.com/olekukonko/tablewriter/tw" +) + +// Markdown renders tables in Markdown format with customizable settings. +type Markdown struct { + config tw.Rendition // Rendering configuration + logger *ll.Logger // Debug trace messages + alignment tw.Alignment // alias of []tw.Align + w io.Writer +} + +// NewMarkdown initializes a Markdown renderer with defaults tailored for Markdown (e.g., pipes, header separator). +// Only the first config is used if multiple are provided. +func NewMarkdown(configs ...tw.Rendition) *Markdown { + cfg := defaultBlueprint() + // Configure Markdown-specific defaults + cfg.Symbols = tw.NewSymbols(tw.StyleMarkdown) + cfg.Borders = tw.Border{Left: tw.On, Right: tw.On, Top: tw.Off, Bottom: tw.Off} + cfg.Settings.Separators.BetweenColumns = tw.On + cfg.Settings.Separators.BetweenRows = tw.Off + cfg.Settings.Lines.ShowHeaderLine = tw.On + cfg.Settings.Lines.ShowTop = tw.Off + cfg.Settings.Lines.ShowBottom = tw.Off + cfg.Settings.Lines.ShowFooterLine = tw.Off + // cfg.Settings.TrimWhitespace = tw.On + + // Apply user overrides + if len(configs) > 0 { + cfg = mergeMarkdownConfig(cfg, configs[0]) + } + return &Markdown{config: cfg, logger: ll.New("markdown")} +} + +// mergeMarkdownConfig combines user-provided config with Markdown defaults, enforcing Markdown-specific settings. +func mergeMarkdownConfig(defaults, overrides tw.Rendition) tw.Rendition { + if overrides.Borders.Left != 0 { + defaults.Borders.Left = overrides.Borders.Left + } + if overrides.Borders.Right != 0 { + defaults.Borders.Right = overrides.Borders.Right + } + if overrides.Symbols != nil { + defaults.Symbols = overrides.Symbols + } + defaults.Settings = mergeSettings(defaults.Settings, overrides.Settings) + // Enforce Markdown requirements + defaults.Settings.Lines.ShowHeaderLine = tw.On + defaults.Settings.Separators.BetweenColumns = tw.On + // defaults.Settings.TrimWhitespace = tw.On + return defaults +} + +func (m *Markdown) Logger(logger *ll.Logger) { + m.logger = logger.Namespace("markdown") +} + +// Config returns the renderer's current configuration. +func (m *Markdown) Config() tw.Rendition { + return m.config +} + +// Header renders the Markdown table header and its separator line. +func (m *Markdown) Header(headers [][]string, ctx tw.Formatting) { + m.resolveAlignment(ctx) + if len(headers) == 0 || len(headers[0]) == 0 { + m.logger.Debug("Header: No headers to render") + return + } + m.logger.Debugf("Rendering header with %d lines, widths=%v, current=%v, next=%v", len(headers), ctx.Row.Widths, ctx.Row.Current, ctx.Row.Next) + + // Render header content + m.renderMarkdownLine(headers[0], ctx, false) + + // Render separator if enabled + if m.config.Settings.Lines.ShowHeaderLine.Enabled() { + sepCtx := ctx + sepCtx.Row.Widths = ctx.Row.Widths + sepCtx.Row.Current = ctx.Row.Current + sepCtx.Row.Previous = ctx.Row.Current + sepCtx.IsSubRow = true + m.renderMarkdownLine(nil, sepCtx, true) + } +} + +// Row renders a Markdown table data row. +func (m *Markdown) Row(row []string, ctx tw.Formatting) { + m.resolveAlignment(ctx) + m.logger.Debugf("Rendering row with data=%v, widths=%v, previous=%v, current=%v, next=%v", row, ctx.Row.Widths, ctx.Row.Previous, ctx.Row.Current, ctx.Row.Next) + m.renderMarkdownLine(row, ctx, false) + +} + +// Footer renders the Markdown table footer. +func (m *Markdown) Footer(footers [][]string, ctx tw.Formatting) { + m.resolveAlignment(ctx) + if len(footers) == 0 || len(footers[0]) == 0 { + m.logger.Debug("Footer: No footers to render") + return + } + m.logger.Debugf("Rendering footer with %d lines, widths=%v, previous=%v, current=%v, next=%v", + len(footers), ctx.Row.Widths, ctx.Row.Previous, ctx.Row.Current, ctx.Row.Next) + m.renderMarkdownLine(footers[0], ctx, false) +} + +// Line is a no-op for Markdown, as only the header separator is rendered (handled by Header). +func (m *Markdown) Line(ctx tw.Formatting) { + m.logger.Debugf("Line: Generic Line call received (pos: %s, loc: %s). Markdown ignores these.", ctx.Row.Position, ctx.Row.Location) +} + +// Reset clears the renderer's internal state, including debug traces. +func (m *Markdown) Reset() { + m.logger.Info("Reset: Cleared debug trace") +} + +func (m *Markdown) Start(w io.Writer) error { + m.w = w + m.logger.Warn("Markdown.Start() called (no-op).") + return nil +} + +func (m *Markdown) Close() error { + m.logger.Warn("Markdown.Close() called (no-op).") + return nil +} + +func (m *Markdown) resolveAlignment(ctx tw.Formatting) tw.Alignment { + if len(m.alignment) != 0 { + return m.alignment + } + + // get total columns + total := len(ctx.Row.Current) + + // build default alignment + for i := 0; i < total; i++ { + m.alignment = append(m.alignment, tw.AlignNone) // Default to AlignNone + } + + // add per column alignment if it exists + for i := 0; i < total; i++ { + m.alignment[i] = ctx.Row.Current[i].Align + } + + m.logger.Debugf(" → Align Resolved %s", m.alignment) + return m.alignment +} + +// formatCell formats a Markdown cell's content with padding and alignment, ensuring at least 3 characters wide. +func (m *Markdown) formatCell(content string, width int, align tw.Align, padding tw.Padding) string { + //if m.config.Settings.TrimWhitespace.Enabled() { + // content = strings.TrimSpace(content) + //} + contentVisualWidth := twwidth.Width(content) + + // Use specified padding characters or default to spaces + padLeftChar := padding.Left + if padLeftChar == tw.Empty { + padLeftChar = tw.Space + } + padRightChar := padding.Right + if padRightChar == tw.Empty { + padRightChar = tw.Space + } + + // Calculate padding widths + padLeftCharWidth := twwidth.Width(padLeftChar) + padRightCharWidth := twwidth.Width(padRightChar) + minWidth := tw.Max(3, contentVisualWidth+padLeftCharWidth+padRightCharWidth) + targetWidth := tw.Max(width, minWidth) + + // Calculate padding + totalPaddingNeeded := targetWidth - contentVisualWidth + if totalPaddingNeeded < 0 { + totalPaddingNeeded = 0 + } + + var leftPadStr, rightPadStr string + switch align { + case tw.AlignRight: + leftPadCount := tw.Max(0, totalPaddingNeeded-padRightCharWidth) + rightPadCount := totalPaddingNeeded - leftPadCount + leftPadStr = strings.Repeat(padLeftChar, leftPadCount) + rightPadStr = strings.Repeat(padRightChar, rightPadCount) + case tw.AlignCenter: + leftPadCount := totalPaddingNeeded / 2 + rightPadCount := totalPaddingNeeded - leftPadCount + if leftPadCount < padLeftCharWidth && totalPaddingNeeded >= padLeftCharWidth+padRightCharWidth { + leftPadCount = padLeftCharWidth + rightPadCount = totalPaddingNeeded - leftPadCount + } + if rightPadCount < padRightCharWidth && totalPaddingNeeded >= padLeftCharWidth+padRightCharWidth { + rightPadCount = padRightCharWidth + leftPadCount = totalPaddingNeeded - rightPadCount + } + leftPadStr = strings.Repeat(padLeftChar, leftPadCount) + rightPadStr = strings.Repeat(padRightChar, rightPadCount) + default: // AlignLeft + rightPadCount := tw.Max(0, totalPaddingNeeded-padLeftCharWidth) + leftPadCount := totalPaddingNeeded - rightPadCount + leftPadStr = strings.Repeat(padLeftChar, leftPadCount) + rightPadStr = strings.Repeat(padRightChar, rightPadCount) + } + + // Build result + result := leftPadStr + content + rightPadStr + + // Adjust width if needed + finalWidth := twwidth.Width(result) + if finalWidth != targetWidth { + m.logger.Debugf("Markdown formatCell MISMATCH: content='%s', target_w=%d, paddingL='%s', paddingR='%s', align=%s -> result='%s', result_w=%d", + content, targetWidth, padding.Left, padding.Right, align, result, finalWidth) + adjNeeded := targetWidth - finalWidth + if adjNeeded > 0 { + adjStr := strings.Repeat(tw.Space, adjNeeded) + if align == tw.AlignRight { + result = adjStr + result + } else if align == tw.AlignCenter { + leftAdj := adjNeeded / 2 + rightAdj := adjNeeded - leftAdj + result = strings.Repeat(tw.Space, leftAdj) + result + strings.Repeat(tw.Space, rightAdj) + } else { + result += adjStr + } + } else { + result = twwidth.Truncate(result, targetWidth) + } + m.logger.Debugf("Markdown formatCell Corrected: target_w=%d, result='%s', new_w=%d", targetWidth, result, twwidth.Width(result)) + } + + m.logger.Debugf("Markdown formatCell: content='%s', width=%d, align=%s, paddingL='%s', paddingR='%s' -> '%s' (target %d)", + content, width, align, padding.Left, padding.Right, result, targetWidth) + return result +} + +// formatSeparator generates a Markdown separator (e.g., `---`, `:--`, `:-:`) with alignment indicators. +func (m *Markdown) formatSeparator(width int, align tw.Align) string { + targetWidth := tw.Max(3, width) + var sb strings.Builder + + switch align { + case tw.AlignLeft: + sb.WriteRune(':') + sb.WriteString(strings.Repeat("-", targetWidth-1)) + case tw.AlignRight: + sb.WriteString(strings.Repeat("-", targetWidth-1)) + sb.WriteRune(':') + case tw.AlignCenter: + sb.WriteRune(':') + sb.WriteString(strings.Repeat("-", targetWidth-2)) + sb.WriteRune(':') + case tw.AlignNone: + sb.WriteString(strings.Repeat("-", targetWidth)) + default: + sb.WriteString(strings.Repeat("-", targetWidth)) // Fallback + } + + result := sb.String() + currentLen := twwidth.Width(result) + if currentLen < targetWidth { + result += strings.Repeat("-", targetWidth-currentLen) + } else if currentLen > targetWidth { + result = twwidth.Truncate(result, targetWidth) + } + + m.logger.Debugf("Markdown formatSeparator: width=%d, align=%s -> '%s'", width, align, result) + return result +} + +// renderMarkdownLine renders a single Markdown line (header, row, footer, or separator) with pipes and alignment. +func (m *Markdown) renderMarkdownLine(line []string, ctx tw.Formatting, isHeaderSep bool) { + numCols := 0 + if len(ctx.Row.Widths) > 0 { + maxKey := -1 + for k := range ctx.Row.Widths { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else if len(ctx.Row.Current) > 0 { + maxKey := -1 + for k := range ctx.Row.Current { + if k > maxKey { + maxKey = k + } + } + numCols = maxKey + 1 + } else if len(line) > 0 && !isHeaderSep { + numCols = len(line) + } + + if numCols == 0 && !isHeaderSep { + m.logger.Debug("renderMarkdownLine: Skipping line with zero columns.") + return + } + + var output strings.Builder + prefix := m.config.Symbols.Column() + if m.config.Borders.Left == tw.Off { + prefix = tw.Empty + } + suffix := m.config.Symbols.Column() + if m.config.Borders.Right == tw.Off { + suffix = tw.Empty + } + separator := m.config.Symbols.Column() + output.WriteString(prefix) + + colIndex := 0 + separatorWidth := twwidth.Width(separator) + + for colIndex < numCols { + cellCtx, ok := ctx.Row.Current[colIndex] + align := m.alignment[colIndex] + + defaultPadding := tw.Padding{Left: tw.Space, Right: tw.Space} + if !ok { + cellCtx = tw.CellContext{ + Data: tw.Empty, Align: align, Padding: defaultPadding, + Width: ctx.Row.Widths.Get(colIndex), Merge: tw.MergeState{}, + } + } else if !cellCtx.Padding.Paddable() { + cellCtx.Padding = defaultPadding + } + + // Add separator + isContinuation := ok && cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start + if colIndex > 0 && !isContinuation { + output.WriteString(separator) + m.logger.Debugf("renderMarkdownLine: Added separator '%s' before col %d", separator, colIndex) + } + + // Calculate width and span + span := 1 + visualWidth := 0 + isHMergeStart := ok && cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start + if isHMergeStart { + span = cellCtx.Merge.Horizontal.Span + totalWidth := 0 + for k := 0; k < span && colIndex+k < numCols; k++ { + colWidth := ctx.NormalizedWidths.Get(colIndex + k) + if colWidth < 0 { + colWidth = 0 + } + totalWidth += colWidth + if k > 0 && separatorWidth > 0 { + totalWidth += separatorWidth + } + } + visualWidth = totalWidth + m.logger.Debugf("renderMarkdownLine: HMerge col %d, span %d, visualWidth %d", colIndex, span, visualWidth) + } else { + visualWidth = ctx.Row.Widths.Get(colIndex) + m.logger.Debugf("renderMarkdownLine: Regular col %d, visualWidth %d", colIndex, visualWidth) + } + if visualWidth < 0 { + visualWidth = 0 + } + + // Render segment + if isContinuation { + m.logger.Debugf("renderMarkdownLine: Skipping col %d (HMerge continuation)", colIndex) + } else { + var formattedSegment string + if isHeaderSep { + // Use header's alignment from ctx.Row.Previous + headerAlign := align + if headerCellCtx, headerOK := ctx.Row.Previous[colIndex]; headerOK { + headerAlign = headerCellCtx.Align + // Preserve tw.AlignNone for separator + if headerAlign != tw.AlignNone && (headerAlign == tw.Empty || headerAlign == tw.Skip) { + headerAlign = tw.AlignCenter + } + } + formattedSegment = m.formatSeparator(visualWidth, headerAlign) + } else { + content := tw.Empty + if colIndex < len(line) { + content = line[colIndex] + } + // For rows, use the header's alignment if specified + rowAlign := align + if headerCellCtx, headerOK := ctx.Row.Previous[colIndex]; headerOK && isHeaderSep == false { + if headerCellCtx.Align != tw.AlignNone && headerCellCtx.Align != tw.Empty { + rowAlign = headerCellCtx.Align + } + } + if rowAlign == tw.AlignNone || rowAlign == tw.Empty { + if ctx.Row.Position == tw.Header { + rowAlign = tw.AlignCenter + } else if ctx.Row.Position == tw.Footer { + rowAlign = tw.AlignRight + } else { + rowAlign = tw.AlignLeft + } + m.logger.Debugf("renderMarkdownLine: Col %d using default align '%s'", colIndex, rowAlign) + } + formattedSegment = m.formatCell(content, visualWidth, rowAlign, cellCtx.Padding) + } + output.WriteString(formattedSegment) + m.logger.Debugf("renderMarkdownLine: Wrote col %d (span %d, width %d): '%s'", colIndex, span, visualWidth, formattedSegment) + } + + colIndex += span + } + + output.WriteString(suffix) + output.WriteString(tw.NewLine) + m.w.Write([]byte(output.String())) + m.logger.Debugf("renderMarkdownLine: Final line: %s", strings.TrimSuffix(output.String(), tw.NewLine)) +} diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/ocean.go b/vendor/github.com/olekukonko/tablewriter/renderer/ocean.go new file mode 100644 index 00000000..7a943e9f --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/ocean.go @@ -0,0 +1,470 @@ +package renderer + +import ( + "github.com/olekukonko/tablewriter/pkg/twwidth" + "io" + "strings" + + "github.com/olekukonko/ll" + "github.com/olekukonko/tablewriter/tw" +) + +// OceanConfig defines configuration specific to the Ocean renderer. +type OceanConfig struct { +} + +// Ocean is a streaming table renderer that writes ASCII tables. +type Ocean struct { + config tw.Rendition + oceanConfig OceanConfig + fixedWidths tw.Mapper[int, int] + widthsFinalized bool + tableOutputStarted bool + headerContentRendered bool // True if actual header *content* has been rendered by Ocean.Header + logger *ll.Logger + w io.Writer +} + +func NewOcean(oceanConfig ...OceanConfig) *Ocean { + cfg := defaultOceanRendererConfig() + oCfg := OceanConfig{} + if len(oceanConfig) > 0 { + // Apply user-provided OceanConfig if necessary + } + r := &Ocean{ + config: cfg, + oceanConfig: oCfg, + fixedWidths: tw.NewMapper[int, int](), + logger: ll.New("ocean"), + } + r.resetState() + return r +} + +func (o *Ocean) resetState() { + o.fixedWidths = tw.NewMapper[int, int]() + o.widthsFinalized = false + o.tableOutputStarted = false + o.headerContentRendered = false + o.logger.Debug("State reset.") +} + +func (o *Ocean) Logger(logger *ll.Logger) { + o.logger = logger.Namespace("ocean") +} + +func (o *Ocean) Config() tw.Rendition { + return o.config +} + +func (o *Ocean) tryFinalizeWidths(ctx tw.Formatting) { + if o.widthsFinalized { + return + } + if ctx.Row.Widths != nil && ctx.Row.Widths.Len() > 0 { + o.fixedWidths = ctx.Row.Widths.Clone() + o.widthsFinalized = true + o.logger.Debugf("Widths finalized from context: %v", o.fixedWidths) + } else { + o.logger.Warn("Attempted to finalize widths, but no width data in context.") + } +} + +func (o *Ocean) Start(w io.Writer) error { + o.w = w + o.logger.Debug("Start() called.") + o.resetState() + // Top border is drawn by the first component (Header or Row) that has widths + // OR by an explicit Line() call from table.go's batch renderer. + return nil +} + +// renderTopBorderIfNeeded is called by Header or Row if it's the first to render +// and tableOutputStarted is false. +func (o *Ocean) renderTopBorderIfNeeded(currentPosition tw.Position, ctx tw.Formatting) { + if !o.tableOutputStarted && o.widthsFinalized { + // This renderer's config for Top border + if o.config.Borders.Top.Enabled() && o.config.Settings.Lines.ShowTop.Enabled() { + o.logger.Debugf("Ocean itself rendering top border (triggered by %s)", currentPosition) + lineCtx := tw.Formatting{ // Construct specific context for this line + Row: tw.RowContext{ + Widths: o.fixedWidths, + Location: tw.LocationFirst, + Position: currentPosition, + Next: ctx.Row.Current, // The actual first content is "Next" to the top border + }, + Level: tw.LevelHeader, + } + o.Line(lineCtx) + o.tableOutputStarted = true + } + } +} + +func (o *Ocean) Header(headers [][]string, ctx tw.Formatting) { + o.logger.Debugf("Ocean.Header called: IsSubRow=%v, Location=%v, NumLines=%d", ctx.IsSubRow, ctx.Row.Location, len(headers)) + + if !o.widthsFinalized { + o.tryFinalizeWidths(ctx) + } + + if !o.widthsFinalized { + o.logger.Error("Ocean.Header: Cannot render content, widths are not finalized.") + return + } + + if len(headers) > 0 && len(headers[0]) > 0 { + for i, headerLineData := range headers { + currentLineCtx := ctx + currentLineCtx.Row.Widths = o.fixedWidths + if i > 0 { + currentLineCtx.IsSubRow = true + } + o.renderContentLine(currentLineCtx, headerLineData) + o.tableOutputStarted = true // Content was written + } + o.headerContentRendered = true + } else { + o.logger.Debug("Ocean.Header: No actual header content lines to render.") + } +} + +func (o *Ocean) Row(row []string, ctx tw.Formatting) { + o.logger.Debugf("Ocean.Row called: IsSubRow=%v, Location=%v, DataItems=%d", ctx.IsSubRow, ctx.Row.Location, len(row)) + + if !o.widthsFinalized { + o.tryFinalizeWidths(ctx) + } + if !o.widthsFinalized { + o.logger.Error("Ocean.Row: Cannot render content, widths are not finalized.") + return + } + + ctx.Row.Widths = o.fixedWidths + o.renderContentLine(ctx, row) + o.tableOutputStarted = true +} + +func (o *Ocean) Footer(footers [][]string, ctx tw.Formatting) { + o.logger.Debugf("Ocean.Footer called: IsSubRow=%v, Location=%v, NumLines=%d", ctx.IsSubRow, ctx.Row.Location, len(footers)) + + if !o.widthsFinalized { + o.tryFinalizeWidths(ctx) + o.logger.Warn("Ocean.Footer: Widths finalized at Footer stage (unusual).") + } + if !o.widthsFinalized { + o.logger.Error("Ocean.Footer: Cannot render content, widths are not finalized.") + return + } + + if len(footers) > 0 && len(footers[0]) > 0 { + for i, footerLineData := range footers { + currentLineCtx := ctx + currentLineCtx.Row.Widths = o.fixedWidths + if i > 0 { + currentLineCtx.IsSubRow = true + } + o.renderContentLine(currentLineCtx, footerLineData) + o.tableOutputStarted = true + } + } else { + o.logger.Debug("Ocean.Footer: No actual footer content lines to render.") + } +} + +func (o *Ocean) Line(ctx tw.Formatting) { + if !o.widthsFinalized { + o.tryFinalizeWidths(ctx) + if !o.widthsFinalized { + o.logger.Error("Ocean.Line: Called but widths could not be finalized. Skipping line rendering.") + return + } + } + + // Ensure Line uses the consistent fixedWidths for drawing + ctx.Row.Widths = o.fixedWidths + o.logger.Debugf("Ocean.Line DRAWING: Level=%v, Loc=%s, Pos=%s, IsSubRow=%t, WidthsLen=%d", ctx.Level, ctx.Row.Location, ctx.Row.Position, ctx.IsSubRow, ctx.Row.Widths.Len()) + + jr := NewJunction(JunctionContext{ + Symbols: o.config.Symbols, + Ctx: ctx, + ColIdx: 0, + Logger: o.logger, + BorderTint: Tint{}, + SeparatorTint: Tint{}, + }) + + var line strings.Builder + sortedColIndices := o.fixedWidths.SortedKeys() + + if len(sortedColIndices) == 0 { + drewEmptyBorders := false + if o.config.Borders.Left.Enabled() { + line.WriteString(jr.RenderLeft()) + drewEmptyBorders = true + } + if o.config.Borders.Right.Enabled() { + line.WriteString(jr.RenderRight(-1)) + drewEmptyBorders = true + } + if drewEmptyBorders { + line.WriteString(tw.NewLine) + o.w.Write([]byte(line.String())) + o.logger.Debug("Line: Drew empty table borders based on Line call.") + } else { + o.logger.Debug("Line: Handled empty table case (no columns, no borders).") + } + o.tableOutputStarted = drewEmptyBorders // A line counts as output + return + } + + if o.config.Borders.Left.Enabled() { + line.WriteString(jr.RenderLeft()) + } + + for i, colIdx := range sortedColIndices { + jr.colIdx = colIdx + segmentChar := jr.GetSegment() + colVisualWidth := o.fixedWidths.Get(colIdx) + + if colVisualWidth <= 0 { + // Still need to consider separators after zero-width columns + } else { + if segmentChar == tw.Empty { + segmentChar = o.config.Symbols.Row() + } + segmentDisplayWidth := twwidth.Width(segmentChar) + if segmentDisplayWidth <= 0 { + segmentDisplayWidth = 1 + } + + repeatCount := 0 + if colVisualWidth > 0 { + repeatCount = colVisualWidth / segmentDisplayWidth + if repeatCount == 0 { + repeatCount = 1 + } + } + line.WriteString(strings.Repeat(segmentChar, repeatCount)) + } + + if i < len(sortedColIndices)-1 && o.config.Settings.Separators.BetweenColumns.Enabled() { + nextColIdx := sortedColIndices[i+1] + line.WriteString(jr.RenderJunction(colIdx, nextColIdx)) + } + } + + if o.config.Borders.Right.Enabled() { + lastColIdx := sortedColIndices[len(sortedColIndices)-1] + line.WriteString(jr.RenderRight(lastColIdx)) + } + + line.WriteString(tw.NewLine) + o.w.Write([]byte(line.String())) + o.tableOutputStarted = true + o.logger.Debugf("Line rendered by explicit call: %s", strings.TrimSuffix(line.String(), tw.NewLine)) +} + +func (o *Ocean) Close() error { + o.logger.Debug("Ocean.Close() called.") + o.resetState() + return nil +} + +func (o *Ocean) renderContentLine(ctx tw.Formatting, lineData []string) { + if !o.widthsFinalized || o.fixedWidths.Len() == 0 { + o.logger.Error("renderContentLine: Cannot render, fixedWidths not set or empty.") + return + } + + var output strings.Builder + if o.config.Borders.Left.Enabled() { + output.WriteString(o.config.Symbols.Column()) + } + + sortedColIndices := o.fixedWidths.SortedKeys() + + for i, colIdx := range sortedColIndices { + cellVisualWidth := o.fixedWidths.Get(colIdx) + cellContent := tw.Empty + align := tw.AlignDefault + padding := tw.Padding{Left: tw.Space, Right: tw.Space} + + switch ctx.Row.Position { + case tw.Header: + align = tw.AlignCenter + case tw.Footer: + align = tw.AlignRight + default: + align = tw.AlignLeft + } + + cellCtx, hasCellCtx := ctx.Row.Current[colIdx] + if hasCellCtx { + cellContent = cellCtx.Data + if cellCtx.Align.Validate() == nil && cellCtx.Align != tw.AlignNone { + align = cellCtx.Align + } + if cellCtx.Padding.Paddable() { + padding = cellCtx.Padding + } + } else if colIdx < len(lineData) { + cellContent = lineData[colIdx] + } + + actualCellWidthToRender := cellVisualWidth + isHMergeContinuation := false + + if hasCellCtx && cellCtx.Merge.Horizontal.Present { + if cellCtx.Merge.Horizontal.Start { + hSpan := cellCtx.Merge.Horizontal.Span + if hSpan <= 0 { + hSpan = 1 + } + + currentMergeTotalRenderWidth := 0 + for k := 0; k < hSpan; k++ { + idxInMergeSpan := colIdx + k + // Check if idxInMergeSpan is a defined column in fixedWidths + foundInFixedWidths := false + for _, sortedCIdx_inner := range sortedColIndices { + if sortedCIdx_inner == idxInMergeSpan { + currentMergeTotalRenderWidth += o.fixedWidths.Get(idxInMergeSpan) + foundInFixedWidths = true + break + } + } + if !foundInFixedWidths && idxInMergeSpan <= sortedColIndices[len(sortedColIndices)-1] { + o.logger.Debugf("Col %d in HMerge span not found in fixedWidths, assuming 0-width contribution.", idxInMergeSpan) + } + + if k < hSpan-1 && o.config.Settings.Separators.BetweenColumns.Enabled() { + currentMergeTotalRenderWidth += twwidth.Width(o.config.Symbols.Column()) + } + } + actualCellWidthToRender = currentMergeTotalRenderWidth + } else { + isHMergeContinuation = true + } + } + + if isHMergeContinuation { + o.logger.Debugf("renderContentLine: Col %d is HMerge continuation, skipping content render.", colIdx) + // The separator logic below needs to handle this correctly. + // If the *previous* column was the start of a merge that spans *this* column, + // then the separator after the previous column should have been suppressed. + } else if actualCellWidthToRender > 0 { + formattedCell := o.formatCellContent(cellContent, actualCellWidthToRender, padding, align) + output.WriteString(formattedCell) + } else { + o.logger.Debugf("renderContentLine: col %d has 0 render width, writing no content.", colIdx) + } + + // Add column separator if: + // 1. It's not the last column in sortedColIndices + // 2. Separators are enabled + // 3. This cell is NOT a horizontal merge start that spans over the next column. + if i < len(sortedColIndices)-1 && o.config.Settings.Separators.BetweenColumns.Enabled() { + shouldAddSeparator := true + if hasCellCtx && cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start { + // If this merge start spans beyond the current colIdx into the next sortedColIndex + if colIdx+cellCtx.Merge.Horizontal.Span > sortedColIndices[i+1] { + shouldAddSeparator = false // Separator is part of the merged cell's width + o.logger.Debugf("renderContentLine: Suppressed separator after HMerge col %d.", colIdx) + } + } + if shouldAddSeparator { + output.WriteString(o.config.Symbols.Column()) + } + } + } + + if o.config.Borders.Right.Enabled() { + output.WriteString(o.config.Symbols.Column()) + } + + output.WriteString(tw.NewLine) + o.w.Write([]byte(output.String())) + o.logger.Debugf("Content line rendered: %s", strings.TrimSuffix(output.String(), tw.NewLine)) +} + +func (o *Ocean) formatCellContent(content string, cellVisualWidth int, padding tw.Padding, align tw.Align) string { + if cellVisualWidth <= 0 { + return tw.Empty + } + + contentDisplayWidth := twwidth.Width(content) + + padLeftChar := padding.Left + if padLeftChar == tw.Empty { + padLeftChar = tw.Space + } + padRightChar := padding.Right + if padRightChar == tw.Empty { + padRightChar = tw.Space + } + + padLeftDisplayWidth := twwidth.Width(padLeftChar) + padRightDisplayWidth := twwidth.Width(padRightChar) + + spaceForContentAndAlignment := cellVisualWidth - padLeftDisplayWidth - padRightDisplayWidth + if spaceForContentAndAlignment < 0 { + spaceForContentAndAlignment = 0 + } + + if contentDisplayWidth > spaceForContentAndAlignment { + content = twwidth.Truncate(content, spaceForContentAndAlignment) + contentDisplayWidth = twwidth.Width(content) + } + + remainingSpace := spaceForContentAndAlignment - contentDisplayWidth + if remainingSpace < 0 { + remainingSpace = 0 + } + + var PL, PR string + switch align { + case tw.AlignRight: + PL = strings.Repeat(tw.Space, remainingSpace) + case tw.AlignCenter: + leftSpaces := remainingSpace / 2 + rightSpaces := remainingSpace - leftSpaces + PL = strings.Repeat(tw.Space, leftSpaces) + PR = strings.Repeat(tw.Space, rightSpaces) + default: + PR = strings.Repeat(tw.Space, remainingSpace) + } + + var sb strings.Builder + sb.WriteString(padLeftChar) + sb.WriteString(PL) + sb.WriteString(content) + sb.WriteString(PR) + sb.WriteString(padRightChar) + + currentFormattedWidth := twwidth.Width(sb.String()) + if currentFormattedWidth < cellVisualWidth { + if align == tw.AlignRight { + prefixSpaces := strings.Repeat(tw.Space, cellVisualWidth-currentFormattedWidth) + finalStr := prefixSpaces + sb.String() + sb.Reset() + sb.WriteString(finalStr) + } else { + sb.WriteString(strings.Repeat(tw.Space, cellVisualWidth-currentFormattedWidth)) + } + } else if currentFormattedWidth > cellVisualWidth { + tempStr := sb.String() + sb.Reset() + sb.WriteString(twwidth.Truncate(tempStr, cellVisualWidth)) + o.logger.Warnf("formatCellContent: Final string '%s' (width %d) exceeded target %d. Force truncated.", tempStr, currentFormattedWidth, cellVisualWidth) + } + return sb.String() +} + +func (o *Ocean) Rendition(config tw.Rendition) { + o.config = mergeRendition(o.config, config) + o.logger.Debugf("Blueprint.Rendition updated. New internal config: %+v", o.config) +} + +// Ensure Blueprint implements tw.Renditioning +var _ tw.Renditioning = (*Ocean)(nil) diff --git a/vendor/github.com/olekukonko/tablewriter/renderer/svg.go b/vendor/github.com/olekukonko/tablewriter/renderer/svg.go new file mode 100644 index 00000000..f49e2d77 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/renderer/svg.go @@ -0,0 +1,703 @@ +package renderer + +import ( + "fmt" + "github.com/olekukonko/ll" + "html" + "io" + "strings" + + "github.com/olekukonko/tablewriter/tw" +) + +// SVGConfig holds configuration for the SVG renderer. +// Fields include font, colors, padding, and merge rendering options. +// Used to customize SVG output appearance and behavior. +type SVGConfig struct { + FontFamily string // e.g., "Arial, sans-serif" + FontSize float64 // Base font size in SVG units + LineHeightFactor float64 // Factor for line height (e.g., 1.2) + Padding float64 // Padding inside cells + StrokeWidth float64 // Line width for borders + StrokeColor string // Color for strokes (e.g., "black") + HeaderBG string // Background color for header + RowBG string // Background color for rows + RowAltBG string // Alternating row background color + FooterBG string // Background color for footer + HeaderColor string // Text color for header + RowColor string // Text color for rows + FooterColor string // Text color for footer + ApproxCharWidthFactor float64 // Char width relative to FontSize + MinColWidth float64 // Minimum column width + RenderTWConfigOverrides bool // Override SVG alignments with tablewriter + Debug bool // Enable debug logging + ScaleFactor float64 // Scaling factor for SVG +} + +// SVG implements tw.Renderer for SVG output. +// Manages SVG element generation and merge tracking. +type SVG struct { + config SVGConfig + trace []string + + allVisualLineData [][][]string // [section][line][cell] + allVisualLineCtx [][]tw.Formatting // [section][line]Formatting + + maxCols int + calculatedColWidths []float64 + svgElements strings.Builder + currentY float64 + dataRowCounter int + vMergeTrack map[int]int // Tracks vertical merge spans + numVisualRowsDrawn int + logger *ll.Logger + w io.Writer +} + +const ( + sectionTypeHeader = 0 + sectionTypeRow = 1 + sectionTypeFooter = 2 +) + +// NewSVG creates a new SVG renderer with configuration. +// Parameter configs provides optional SVGConfig; defaults used if empty. +// Returns a configured SVG instance. +func NewSVG(configs ...SVGConfig) *SVG { + cfg := SVGConfig{ + FontFamily: "sans-serif", + FontSize: 12.0, + LineHeightFactor: 1.4, + Padding: 5.0, + StrokeWidth: 1.0, + StrokeColor: "black", + HeaderBG: "#F0F0F0", + RowBG: "white", + RowAltBG: "#F9F9F9", + FooterBG: "#F0F0F0", + HeaderColor: "black", + RowColor: "black", + FooterColor: "black", + ApproxCharWidthFactor: 0.6, + MinColWidth: 30.0, + ScaleFactor: 1.0, + RenderTWConfigOverrides: true, + Debug: false, + } + if len(configs) > 0 { + userCfg := configs[0] + if userCfg.FontFamily != tw.Empty { + cfg.FontFamily = userCfg.FontFamily + } + if userCfg.FontSize > 0 { + cfg.FontSize = userCfg.FontSize + } + if userCfg.LineHeightFactor > 0 { + cfg.LineHeightFactor = userCfg.LineHeightFactor + } + if userCfg.Padding >= 0 { + cfg.Padding = userCfg.Padding + } + if userCfg.StrokeWidth > 0 { + cfg.StrokeWidth = userCfg.StrokeWidth + } + if userCfg.StrokeColor != tw.Empty { + cfg.StrokeColor = userCfg.StrokeColor + } + if userCfg.HeaderBG != tw.Empty { + cfg.HeaderBG = userCfg.HeaderBG + } + if userCfg.RowBG != tw.Empty { + cfg.RowBG = userCfg.RowBG + } + cfg.RowAltBG = userCfg.RowAltBG + if userCfg.FooterBG != tw.Empty { + cfg.FooterBG = userCfg.FooterBG + } + if userCfg.HeaderColor != tw.Empty { + cfg.HeaderColor = userCfg.HeaderColor + } + if userCfg.RowColor != tw.Empty { + cfg.RowColor = userCfg.RowColor + } + if userCfg.FooterColor != tw.Empty { + cfg.FooterColor = userCfg.FooterColor + } + if userCfg.ApproxCharWidthFactor > 0 { + cfg.ApproxCharWidthFactor = userCfg.ApproxCharWidthFactor + } + if userCfg.MinColWidth >= 0 { + cfg.MinColWidth = userCfg.MinColWidth + } + cfg.RenderTWConfigOverrides = userCfg.RenderTWConfigOverrides + cfg.Debug = userCfg.Debug + } + r := &SVG{ + config: cfg, + trace: make([]string, 0, 50), + allVisualLineData: make([][][]string, 3), + allVisualLineCtx: make([][]tw.Formatting, 3), + vMergeTrack: make(map[int]int), + logger: ll.New("svg"), + } + for i := 0; i < 3; i++ { + r.allVisualLineData[i] = make([][]string, 0) + r.allVisualLineCtx[i] = make([]tw.Formatting, 0) + } + return r +} + +// calculateAllColumnWidths computes column widths based on content and merges. +// Uses content length and merge spans; handles horizontal merges by distributing width. +func (s *SVG) calculateAllColumnWidths() { + s.debug("Calculating column widths") + tempMaxCols := 0 + for sectionIdx := 0; sectionIdx < 3; sectionIdx++ { + for lineIdx, lineCtx := range s.allVisualLineCtx[sectionIdx] { + if lineCtx.Row.Current != nil { + visualColCount := 0 + for colIdx := 0; colIdx < len(lineCtx.Row.Current); { + cellCtx := lineCtx.Row.Current[colIdx] + if cellCtx.Merge.Horizontal.Present && !cellCtx.Merge.Horizontal.Start { + colIdx++ // Skip non-start merged cells + continue + } + visualColCount++ + span := 1 + if cellCtx.Merge.Horizontal.Present && cellCtx.Merge.Horizontal.Start { + span = cellCtx.Merge.Horizontal.Span + if span <= 0 { + span = 1 + } + } + colIdx += span + } + s.debug("Section %d, line %d: Visual columns = %d", sectionIdx, lineIdx, visualColCount) + if visualColCount > tempMaxCols { + tempMaxCols = visualColCount + } + } else if lineIdx < len(s.allVisualLineData[sectionIdx]) { + if rawDataLen := len(s.allVisualLineData[sectionIdx][lineIdx]); rawDataLen > tempMaxCols { + tempMaxCols = rawDataLen + } + } + } + } + s.maxCols = tempMaxCols + s.debug("Max columns: %d", s.maxCols) + if s.maxCols == 0 { + s.calculatedColWidths = []float64{} + return + } + s.calculatedColWidths = make([]float64, s.maxCols) + for i := range s.calculatedColWidths { + s.calculatedColWidths[i] = s.config.MinColWidth + } + + // Structure to track max width for each merge group + type mergeKey struct { + startCol int + span int + } + maxMergeWidths := make(map[mergeKey]float64) + + processSectionForWidth := func(sectionIdx int) { + for lineIdx, visualLineData := range s.allVisualLineData[sectionIdx] { + if lineIdx >= len(s.allVisualLineCtx[sectionIdx]) { + s.debug("Warning: Missing context for section %d line %d", sectionIdx, lineIdx) + continue + } + lineCtx := s.allVisualLineCtx[sectionIdx][lineIdx] + currentTableCol := 0 + currentVisualCol := 0 + for currentVisualCol < len(visualLineData) && currentTableCol < s.maxCols { + cellContent := visualLineData[currentVisualCol] + cellCtx := tw.CellContext{} + if lineCtx.Row.Current != nil { + if c, ok := lineCtx.Row.Current[currentTableCol]; ok { + cellCtx = c + } + } + hSpan := 1 + if cellCtx.Merge.Horizontal.Present { + if cellCtx.Merge.Horizontal.Start { + hSpan = cellCtx.Merge.Horizontal.Span + if hSpan <= 0 { + hSpan = 1 + } + } else { + currentTableCol++ + continue + } + } + textPixelWidth := s.estimateTextWidth(cellContent) + contentAndPaddingWidth := textPixelWidth + (2 * s.config.Padding) + if hSpan == 1 { + if currentTableCol < len(s.calculatedColWidths) && contentAndPaddingWidth > s.calculatedColWidths[currentTableCol] { + s.calculatedColWidths[currentTableCol] = contentAndPaddingWidth + } + } else { + totalMergedWidth := contentAndPaddingWidth + (float64(hSpan-1) * s.config.Padding * 2) + if totalMergedWidth < s.config.MinColWidth*float64(hSpan) { + totalMergedWidth = s.config.MinColWidth * float64(hSpan) + } + if currentTableCol < len(s.calculatedColWidths) { + key := mergeKey{currentTableCol, hSpan} + if currentWidth, ok := maxMergeWidths[key]; ok { + if totalMergedWidth > currentWidth { + maxMergeWidths[key] = totalMergedWidth + } + } else { + maxMergeWidths[key] = totalMergedWidth + } + s.debug("Horizontal merge at col %d, span %d: Total width %.2f", currentTableCol, hSpan, totalMergedWidth) + } + } + currentTableCol += hSpan + currentVisualCol++ + } + } + } + processSectionForWidth(sectionTypeHeader) + processSectionForWidth(sectionTypeRow) + processSectionForWidth(sectionTypeFooter) + + // Apply maximum widths for merged cells + for key, width := range maxMergeWidths { + s.calculatedColWidths[key.startCol] = width + for i := 1; i < key.span && (key.startCol+i) < len(s.calculatedColWidths); i++ { + s.calculatedColWidths[key.startCol+i] = 0 + } + } + + for i := range s.calculatedColWidths { + if s.calculatedColWidths[i] < s.config.MinColWidth && s.calculatedColWidths[i] != 0 { + s.calculatedColWidths[i] = s.config.MinColWidth + } + } + s.debug("Column widths: %v", s.calculatedColWidths) +} + +// Close finalizes SVG rendering and writes output. +// Parameter w is the output w. +// Returns an error if writing fails. +func (s *SVG) Close() error { + s.debug("Finalizing SVG output") + s.calculateAllColumnWidths() + s.renderBufferedData() + if s.numVisualRowsDrawn == 0 && s.maxCols == 0 { + fmt.Fprintf(s.w, ``, s.config.StrokeWidth*2, s.config.StrokeWidth*2) + return nil + } + totalWidth := s.config.StrokeWidth + if len(s.calculatedColWidths) > 0 { + for _, cw := range s.calculatedColWidths { + colWidth := cw + if colWidth <= 0 { + colWidth = s.config.MinColWidth + } + totalWidth += colWidth + s.config.StrokeWidth + } + } else if s.maxCols > 0 { + for i := 0; i < s.maxCols; i++ { + totalWidth += s.config.MinColWidth + s.config.StrokeWidth + } + } else { + totalWidth = s.config.StrokeWidth * 2 + } + totalHeight := s.currentY + singleVisualRowHeight := s.config.FontSize*s.config.LineHeightFactor + (2 * s.config.Padding) + if s.numVisualRowsDrawn == 0 { + if s.maxCols > 0 { + totalHeight = s.config.StrokeWidth + singleVisualRowHeight + s.config.StrokeWidth + } else { + totalHeight = s.config.StrokeWidth * 2 + } + } + fmt.Fprintf(s.w, ``, + totalWidth, totalHeight, html.EscapeString(s.config.FontFamily), s.config.FontSize) + fmt.Fprintln(s.w) + fmt.Fprintln(s.w, "") + if _, err := io.WriteString(s.w, s.svgElements.String()); err != nil { + fmt.Fprintln(s.w, ``) + return fmt.Errorf("failed to write SVG elements: %w", err) + } + if s.maxCols > 0 || s.numVisualRowsDrawn > 0 { + fmt.Fprintf(s.w, ` `, + html.EscapeString(s.config.StrokeColor), s.config.StrokeWidth) + fmt.Fprintln(s.w) + yPos := s.config.StrokeWidth / 2.0 + borderRowsToDraw := s.numVisualRowsDrawn + if borderRowsToDraw == 0 && s.maxCols > 0 { + borderRowsToDraw = 1 + } + lineStartX := s.config.StrokeWidth / 2.0 + lineEndX := s.config.StrokeWidth / 2.0 + for _, width := range s.calculatedColWidths { + lineEndX += width + s.config.StrokeWidth + } + for i := 0; i <= borderRowsToDraw; i++ { + fmt.Fprintf(s.w, ` %s`, + lineStartX, yPos, lineEndX, yPos, "\n") + if i < borderRowsToDraw { + yPos += singleVisualRowHeight + s.config.StrokeWidth + } + } + xPos := s.config.StrokeWidth / 2.0 + borderLineStartY := s.config.StrokeWidth / 2.0 + borderLineEndY := totalHeight - (s.config.StrokeWidth / 2.0) + for visualColIdx := 0; visualColIdx <= s.maxCols; visualColIdx++ { + fmt.Fprintf(s.w, ` %s`, + xPos, borderLineStartY, xPos, borderLineEndY, "\n") + if visualColIdx < s.maxCols { + colWidth := s.config.MinColWidth + if visualColIdx < len(s.calculatedColWidths) && s.calculatedColWidths[visualColIdx] > 0 { + colWidth = s.calculatedColWidths[visualColIdx] + } + xPos += colWidth + s.config.StrokeWidth + } + } + fmt.Fprintln(s.w, " ") + } + fmt.Fprintln(s.w, ``) + return nil +} + +// Config returns the renderer's configuration. +// No parameters are required. +// Returns a Rendition with border and debug settings. +func (s *SVG) Config() tw.Rendition { + return tw.Rendition{ + Borders: tw.Border{Left: tw.On, Right: tw.On, Top: tw.On, Bottom: tw.On}, + Settings: tw.Settings{}, + Streaming: false, + } +} + +// Debug returns the renderer's debug trace. +// No parameters are required. +// Returns a slice of debug messages. +func (s *SVG) Debug() []string { + return s.trace +} + +// estimateTextWidth estimates text width in SVG units. +// Parameter text is the input string to measure. +// Returns the estimated width based on font size and char factor. +func (s *SVG) estimateTextWidth(text string) float64 { + runeCount := float64(len([]rune(text))) + return runeCount * s.config.FontSize * s.config.ApproxCharWidthFactor +} + +// Footer buffers footer lines for SVG rendering. +// Parameters include w (w), footers (lines), and ctx (formatting). +// No return value; stores data for later rendering. +func (s *SVG) Footer(footers [][]string, ctx tw.Formatting) { + s.debug("Buffering %d footer lines", len(footers)) + for i, line := range footers { + currentCtx := ctx + currentCtx.IsSubRow = (i > 0) + s.storeVisualLine(sectionTypeFooter, line, currentCtx) + } +} + +// getSVGAnchorFromTW maps tablewriter alignment to SVG text-anchor. +// Parameter align is the tablewriter alignment setting. +// Returns the corresponding SVG text-anchor value or empty string. +func (s *SVG) getSVGAnchorFromTW(align tw.Align) string { + switch align { + case tw.AlignLeft: + return "start" + case tw.AlignCenter: + return "middle" + case tw.AlignRight: + return "end" + case tw.AlignNone, tw.Skip: + return tw.Empty + } + return tw.Empty +} + +// Header buffers header lines for SVG rendering. +// Parameters include w (w), headers (lines), and ctx (formatting). +// No return value; stores data for later rendering. +func (s *SVG) Header(headers [][]string, ctx tw.Formatting) { + s.debug("Buffering %d header lines", len(headers)) + for i, line := range headers { + currentCtx := ctx + currentCtx.IsSubRow = i > 0 + s.storeVisualLine(sectionTypeHeader, line, currentCtx) + } +} + +// Line handles border rendering (ignored in SVG renderer). +// Parameters include w (w) and ctx (formatting). +// No return value; SVG borders are drawn in Close. +func (s *SVG) Line(ctx tw.Formatting) { + s.debug("Line rendering ignored") +} + +// padLineSVG pads a line to the specified column count. +// Parameters include line (input strings) and numCols (target length). +// Returns the padded line with empty strings as needed. +func padLineSVG(line []string, numCols int) []string { + if numCols <= 0 { + return []string{} + } + currentLen := len(line) + if currentLen == numCols { + return line + } + if currentLen > numCols { + return line[:numCols] + } + padded := make([]string, numCols) + copy(padded, line) + return padded +} + +// renderBufferedData renders all buffered lines to SVG elements. +// No parameters are required. +// No return value; populates svgElements buffer. +func (s *SVG) renderBufferedData() { + s.debug("Rendering buffered data") + s.currentY = s.config.StrokeWidth + s.dataRowCounter = 0 + s.vMergeTrack = make(map[int]int) + s.numVisualRowsDrawn = 0 + renderSection := func(sectionIdx int, position tw.Position) { + for visualLineIdx, visualLineData := range s.allVisualLineData[sectionIdx] { + if visualLineIdx >= len(s.allVisualLineCtx[sectionIdx]) { + s.debug("Error: Missing context for section %d line %d", sectionIdx, visualLineIdx) + continue + } + s.renderVisualLine(visualLineData, s.allVisualLineCtx[sectionIdx][visualLineIdx], position) + } + } + renderSection(sectionTypeHeader, tw.Header) + renderSection(sectionTypeRow, tw.Row) + renderSection(sectionTypeFooter, tw.Footer) +} + +// renderVisualLine renders a single visual line as SVG elements. +// Parameters include lineData (cell content), ctx (formatting), and position (section type). +// No return value; handles horizontal and vertical merges. +func (s *SVG) renderVisualLine(visualLineData []string, ctx tw.Formatting, position tw.Position) { + if s.maxCols == 0 || len(s.calculatedColWidths) == 0 { + s.debug("Skipping line rendering: maxCols=%d, widths=%d", s.maxCols, len(s.calculatedColWidths)) + return + } + s.numVisualRowsDrawn++ + s.debug("Rendering visual row %d", s.numVisualRowsDrawn) + singleVisualRowHeight := s.config.FontSize*s.config.LineHeightFactor + (2 * s.config.Padding) + bgColor := tw.Empty + textColor := tw.Empty + defaultTextAnchor := "start" + switch position { + case tw.Header: + bgColor = s.config.HeaderBG + textColor = s.config.HeaderColor + defaultTextAnchor = "middle" + case tw.Footer: + bgColor = s.config.FooterBG + textColor = s.config.FooterColor + defaultTextAnchor = "end" + default: + textColor = s.config.RowColor + if !ctx.IsSubRow { + if s.config.RowAltBG != tw.Empty && s.dataRowCounter%2 != 0 { + bgColor = s.config.RowAltBG + } else { + bgColor = s.config.RowBG + } + s.dataRowCounter++ + } else { + parentDataRowStripeIndex := s.dataRowCounter - 1 + if parentDataRowStripeIndex < 0 { + parentDataRowStripeIndex = 0 + } + if s.config.RowAltBG != tw.Empty && parentDataRowStripeIndex%2 != 0 { + bgColor = s.config.RowAltBG + } else { + bgColor = s.config.RowBG + } + } + } + currentX := s.config.StrokeWidth + currentVisualCellIdx := 0 + for tableColIdx := 0; tableColIdx < s.maxCols; { + if tableColIdx >= len(s.calculatedColWidths) { + s.debug("Table Col %d out of bounds for widths", tableColIdx) + tableColIdx++ + continue + } + if remainingVSpan, isMerging := s.vMergeTrack[tableColIdx]; isMerging && remainingVSpan > 1 { + s.vMergeTrack[tableColIdx]-- + if s.vMergeTrack[tableColIdx] <= 1 { + delete(s.vMergeTrack, tableColIdx) + } + currentX += s.calculatedColWidths[tableColIdx] + s.config.StrokeWidth + tableColIdx++ + continue + } + cellContentFromVisualLine := tw.Empty + if currentVisualCellIdx < len(visualLineData) { + cellContentFromVisualLine = visualLineData[currentVisualCellIdx] + } + cellCtx := tw.CellContext{} + if ctx.Row.Current != nil { + if c, ok := ctx.Row.Current[tableColIdx]; ok { + cellCtx = c + } + } + textToRender := cellContentFromVisualLine + if cellCtx.Data != tw.Empty { + if !((cellCtx.Merge.Vertical.Present && !cellCtx.Merge.Vertical.Start) || (cellCtx.Merge.Hierarchical.Present && !cellCtx.Merge.Hierarchical.Start)) { + textToRender = cellCtx.Data + } else { + textToRender = tw.Empty + } + } else if (cellCtx.Merge.Vertical.Present && !cellCtx.Merge.Vertical.Start) || (cellCtx.Merge.Hierarchical.Present && !cellCtx.Merge.Hierarchical.Start) { + textToRender = tw.Empty + } + hSpan := 1 + if cellCtx.Merge.Horizontal.Present { + if cellCtx.Merge.Horizontal.Start { + hSpan = cellCtx.Merge.Horizontal.Span + if hSpan <= 0 { + hSpan = 1 + } + } else { + currentX += s.calculatedColWidths[tableColIdx] + s.config.StrokeWidth + tableColIdx++ + continue + } + } + vSpan := 1 + isVSpanStart := false + if cellCtx.Merge.Vertical.Present && cellCtx.Merge.Vertical.Start { + vSpan = cellCtx.Merge.Vertical.Span + isVSpanStart = true + } else if cellCtx.Merge.Hierarchical.Present && cellCtx.Merge.Hierarchical.Start { + vSpan = cellCtx.Merge.Hierarchical.Span + isVSpanStart = true + } + if vSpan <= 0 { + vSpan = 1 + } + rectWidth := 0.0 + for hs := 0; hs < hSpan && (tableColIdx+hs) < s.maxCols; hs++ { + if (tableColIdx + hs) < len(s.calculatedColWidths) { + rectWidth += s.calculatedColWidths[tableColIdx+hs] + } else { + rectWidth += s.config.MinColWidth + } + } + if hSpan > 1 { + rectWidth += float64(hSpan-1) * s.config.StrokeWidth + } + if rectWidth <= 0 { + tableColIdx += hSpan + if hSpan > 0 { + currentVisualCellIdx++ + } + continue + } + rectHeight := singleVisualRowHeight + if isVSpanStart && vSpan > 1 { + rectHeight = float64(vSpan)*singleVisualRowHeight + float64(vSpan-1)*s.config.StrokeWidth + for hs := 0; hs < hSpan && (tableColIdx+hs) < s.maxCols; hs++ { + s.vMergeTrack[tableColIdx+hs] = vSpan + } + s.debug("Vertical merge at col %d, span %d, height %.2f", tableColIdx, vSpan, rectHeight) + } else if remainingVSpan, isMerging := s.vMergeTrack[tableColIdx]; isMerging && remainingVSpan > 1 { + rectHeight = singleVisualRowHeight + textToRender = tw.Empty + } + fmt.Fprintf(&s.svgElements, ` %s`, + currentX, s.currentY, rectWidth, rectHeight, html.EscapeString(bgColor), "\n") + cellTextAnchor := defaultTextAnchor + if s.config.RenderTWConfigOverrides { + if al := s.getSVGAnchorFromTW(cellCtx.Align); al != tw.Empty { + cellTextAnchor = al + } + } + textX := currentX + s.config.Padding + if cellTextAnchor == "middle" { + textX = currentX + s.config.Padding + (rectWidth-2*s.config.Padding)/2.0 + } else if cellTextAnchor == "end" { + textX = currentX + rectWidth - s.config.Padding + } + textY := s.currentY + rectHeight/2.0 + escapedCell := html.EscapeString(textToRender) + fmt.Fprintf(&s.svgElements, ` %s%s`, + textX, textY, html.EscapeString(textColor), cellTextAnchor, escapedCell, "\n") + currentX += rectWidth + s.config.StrokeWidth + tableColIdx += hSpan + currentVisualCellIdx++ + } + s.currentY += singleVisualRowHeight + s.config.StrokeWidth +} + +// Reset clears the renderer's internal state. +// No parameters are required. +// No return value; prepares for new rendering. +func (s *SVG) Reset() { + s.debug("Resetting state") + s.trace = make([]string, 0, 50) + for i := 0; i < 3; i++ { + s.allVisualLineData[i] = s.allVisualLineData[i][:0] + s.allVisualLineCtx[i] = s.allVisualLineCtx[i][:0] + } + s.maxCols = 0 + s.calculatedColWidths = nil + s.svgElements.Reset() + s.currentY = 0 + s.dataRowCounter = 0 + s.vMergeTrack = make(map[int]int) + s.numVisualRowsDrawn = 0 +} + +// Row buffers a row line for SVG rendering. +// Parameters include w (w), rowLine (cells), and ctx (formatting). +// No return value; stores data for later rendering. +func (s *SVG) Row(rowLine []string, ctx tw.Formatting) { + s.debug("Buffering row line, IsSubRow: %v", ctx.IsSubRow) + s.storeVisualLine(sectionTypeRow, rowLine, ctx) +} + +func (s *SVG) Logger(logger *ll.Logger) { + s.logger = logger.Namespace("svg") +} + +// Start initializes SVG rendering. +// Parameter w is the output w. +// Returns nil; prepares internal state. +func (s *SVG) Start(w io.Writer) error { + s.w = w + s.debug("Starting SVG rendering") + s.Reset() + return nil +} + +// debug logs a message if debugging is enabled. +// Parameters include format string and variadic arguments. +// No return value; appends to trace. +func (s *SVG) debug(format string, a ...interface{}) { + if s.config.Debug { + msg := fmt.Sprintf(format, a...) + s.trace = append(s.trace, fmt.Sprintf("[SVG] %s", msg)) + } +} + +// storeVisualLine stores a visual line for rendering. +// Parameters include sectionIdx, lineData (cells), and ctx (formatting). +// No return value; buffers data and context. +func (s *SVG) storeVisualLine(sectionIdx int, lineData []string, ctx tw.Formatting) { + copiedLineData := make([]string, len(lineData)) + copy(copiedLineData, lineData) + s.allVisualLineData[sectionIdx] = append(s.allVisualLineData[sectionIdx], copiedLineData) + s.allVisualLineCtx[sectionIdx] = append(s.allVisualLineCtx[sectionIdx], ctx) + hasCurrent := ctx.Row.Current != nil + s.debug("Stored line in section %d, has context: %v", sectionIdx, hasCurrent) +} diff --git a/vendor/github.com/olekukonko/tablewriter/stream.go b/vendor/github.com/olekukonko/tablewriter/stream.go new file mode 100644 index 00000000..7467e9cb --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/stream.go @@ -0,0 +1,1164 @@ +package tablewriter + +import ( + "fmt" + "github.com/olekukonko/errors" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "github.com/olekukonko/tablewriter/tw" + "math" +) + +// Close finalizes the table stream. +// It requires the stream to be started (by calling NewStreamTable). +// It calls the renderer's Close method to render final elements (like the bottom border) and close the stream. +func (t *Table) Close() error { + t.logger.Debug("Close() called. Finalizing stream.") + + // Ensure stream was actually started and enabled + if !t.config.Stream.Enable || !t.hasPrinted { + t.logger.Warn("Close() called but streaming not enabled or not started. Ignoring Close() actions.") + // If renderer has a Close method that should always be called, consider that. + // For Blueprint, Close is a no-op, so returning early is fine. + // If we always call renderer.Close(), ensure it's safe if renderer.Start() wasn't called. + // Let's only call renderer.Close if stream was started. + if t.hasPrinted && t.renderer != nil { // Check if renderer is not nil for safety + t.renderer.Close() // Still call renderer's close for cleanup + } + t.hasPrinted = false // Reset flag + return nil + } + + // Render stored footer if any + if len(t.streamFooterLines) > 0 { + t.logger.Debug("Close(): Rendering stored footer.") + if err := t.streamRenderFooter(t.streamFooterLines); err != nil { + t.logger.Errorf("Close(): Failed to render stream footer: %v", err) + // Continue to try and close renderer and render bottom border + } + } + + // Render the final table bottom border + t.logger.Debug("Close(): Rendering stream bottom border.") + if err := t.streamRenderBottomBorder(); err != nil { + t.logger.Errorf("Close(): Failed to render stream bottom border: %v", err) + // Continue to try and close renderer + } + + // Call the underlying renderer's Close method + err := t.renderer.Close() + if err != nil { + t.logger.Errorf("Renderer.Close() failed: %v", err) + } + + // Reset streaming state + t.hasPrinted = false + t.headerRendered = false + t.firstRowRendered = false + t.lastRenderedLineContent = nil + t.lastRenderedMergeState = nil + t.lastRenderedPosition = "" + t.streamFooterLines = nil + // t.streamWidths should persist if we want to make multiple Start/Close calls on same config? + // For now, let's assume Start re-evaluates. If widths are from StreamConfig, they'd be reused. + // If derived, they'd be re-derived. Let's clear for true reset. + t.streamWidths = tw.NewMapper[int, int]() + t.streamNumCols = 0 + // t.streamRowCounter = 0 // Removed this field + + t.logger.Debug("Stream ended. hasPrinted = false.") + return err // Return error from renderer.Close or other significant errors +} + +// Start initializes the table stream. +// In this streaming model, renderer.Start() is primarily called in NewStreamTable. +// This method serves as a safeguard or point for adding pre-rendering logic. +// Start initializes the table stream. +// It is the entry point for streaming mode. +// Requires t.config.Stream.Enable to be true. +// Returns an error if streaming is disabled or the renderer does not support streaming, +// or if called multiple times on the same stream. +func (t *Table) Start() error { + t.ensureInitialized() // Ensures basic setup like loggers + + if !t.config.Stream.Enable { + // Start() should only be called when streaming is explicitly enabled. + // Otherwise, the user should call Render() for batch mode. + t.logger.Warn("Start() called but streaming is disabled. Call Render() instead for batch mode.") + return errors.New("start() called but streaming is disabled") + } + + if !t.renderer.Config().Streaming { + // Check if the configured renderer actually supports streaming. + t.logger.Error("Configured renderer does not support streaming.") + return fmt.Errorf("renderer does not support streaming") + } + + //t.renderer.Start(t.writer) + //t.renderer.Logger(t.logger) + + if t.hasPrinted { + // Prevent calling Start() multiple times on the same stream instance. + t.logger.Warn("Start() called multiple times for the same table stream. Ignoring subsequent calls.") + return nil + } + + t.logger.Debug("Starting table stream.") + + // Initialize/reset streaming state flags and buffers + t.headerRendered = false + t.firstRowRendered = false + t.lastRenderedLineContent = nil + t.lastRenderedPosition = "" // Reset last rendered position + t.streamFooterLines = nil // Reset footer buffer + t.streamNumCols = 0 // Reset derived column count + + // Calculate initial fixed widths if provided in StreamConfig.Widths + // These widths will be used for all subsequent rendering in streaming mode. + if t.config.Widths.PerColumn != nil && t.config.Widths.PerColumn.Len() > 0 { + // Use per-column stream widths if set + t.logger.Debugf("Using per-column stream widths from StreamConfig: %v", t.config.Widths.PerColumn) + t.streamWidths = t.config.Widths.PerColumn.Clone() + // Determine numCols from the highest index in PerColumn map + maxColIdx := -1 + t.streamWidths.Each(func(col int, width int) { + if col > maxColIdx { + maxColIdx = col + } + // Ensure configured widths are reasonable (>0 becomes >=1, <0 becomes 0) + if width > 0 && width < 1 { + t.streamWidths.Set(col, 1) + } else if width < 0 { + t.streamWidths.Set(col, 0) // Negative width means hide column + } + }) + if maxColIdx >= 0 { + t.streamNumCols = maxColIdx + 1 + t.logger.Debugf("Derived streamNumCols from PerColumn widths: %d", t.streamNumCols) + } else { + // PerColumn map exists but is empty? Or all negative widths? Assume 0 columns for now. + t.streamNumCols = 0 + t.logger.Debugf("PerColumn widths map is effectively empty or contains only negative values, streamNumCols = 0.") + } + + } else if t.config.Widths.Global > 0 { + // Global width is set, but we don't know the number of columns yet. + // Defer applying global width until the first data (Header or first Row) arrives. + // Store a placeholder or flag indicating global width should be used. + // The simple way for now: Keep streamWidths empty, signal the global width preference. + // The width calculation function called later will need to check StreamConfig.Widths.Global + // if streamWidths is empty. + t.logger.Debugf("Global stream width %d set in StreamConfig. Will derive numCols from first data.", t.config.Widths.Global) + t.streamWidths = tw.NewMapper[int, int]() // Initialize as empty, will be populated later + // Note: No need to store Global width value here, it's available in t.config.Stream.Widths.Global + + } else { + // No explicit stream widths in config. They will be calculated from the first data (Header or first Row). + t.logger.Debug("No explicit stream widths configured in StreamConfig. Will derive from first data.") + t.streamWidths = tw.NewMapper[int, int]() // Initialize as empty, will be populated later + t.streamNumCols = 0 // NumCols will be determined by first data + } + + // Log warnings if incompatible features are enabled in streaming config + // Vertical/Hierarchical merges require processing all rows together. + if t.config.Header.Formatting.MergeMode&(tw.MergeVertical|tw.MergeHierarchical) != 0 { + t.logger.Warnf("Vertical or Hierarchical merge modes enabled on Header config (%d) but are unsupported in streaming mode. Only Horizontal merge will be considered.", t.config.Header.Formatting.MergeMode) + } + if t.config.Row.Formatting.MergeMode&(tw.MergeVertical|tw.MergeHierarchical) != 0 { + t.logger.Warnf("Vertical or Hierarchical merge modes enabled on Row config (%d) but are unsupported in streaming mode. Only Horizontal merge will be considered.", t.config.Row.Formatting.MergeMode) + } + if t.config.Footer.Formatting.MergeMode&(tw.MergeVertical|tw.MergeHierarchical) != 0 { + t.logger.Warnf("Vertical or Hierarchical merge modes enabled on Footer config (%d) but are unsupported in streaming mode. Only Horizontal merge will be considered.", t.config.Footer.Formatting.MergeMode) + } + // AutoHide requires processing all row data to find empty columns. + if t.config.Behavior.AutoHide.Enabled() { + t.logger.Warn("AutoHide is enabled in config but is ignored in streaming mode.") + } + + // Call the renderer's start method for the stream. + err := t.renderer.Start(t.writer) + if err == nil { + t.hasPrinted = true // Mark as started successfully only if renderer.Start works + t.logger.Debug("Renderer.Start() succeeded. Table stream initiated.") + } else { + // Reset state if renderer.Start fails + t.hasPrinted = false + t.headerRendered = false + t.firstRowRendered = false + t.lastRenderedLineContent = nil + t.lastRenderedPosition = "" + t.streamFooterLines = nil + t.streamWidths = tw.NewMapper[int, int]() // Clear any widths that might have been set + t.streamNumCols = 0 + t.logger.Errorf("Renderer.Start() failed: %v. Streaming initialization failed.", err) + } + return err +} + +// streamAppendRow processes and renders a single row in streaming mode. +// It calculates/uses fixed stream widths, processes content, renders separators and lines, +// and updates streaming state. +// It assumes Start() has already been called and t.hasPrinted is true. +func (t *Table) streamAppendRow(row interface{}) error { + t.logger.Debugf("streamAppendRow called with row: %v (type: %T)", row, row) + + if !t.config.Stream.Enable { + return errors.New("streaming mode is disabled") + } + + rawCellsSlice, err := t.convertCellsToStrings(row, t.config.Row) + if err != nil { + t.logger.Errorf("streamAppendRow: Failed to convert row to strings: %v", err) + return fmt.Errorf("failed to convert row to strings: %w", err) + } + + if len(rawCellsSlice) == 0 { + t.logger.Debug("streamAppendRow: No raw cells after conversion, skipping row rendering.") + if !t.firstRowRendered { + t.firstRowRendered = true + t.logger.Debug("streamAppendRow: Marked first row rendered (empty content after processing).") + } + return nil + } + + if err := t.ensureStreamWidthsCalculated(rawCellsSlice, t.config.Row); err != nil { + return fmt.Errorf("failed to establish stream column count/widths: %w", err) + } + + // Now, check for column mismatch if a column count has been established. + if t.streamNumCols > 0 { + if len(rawCellsSlice) != t.streamNumCols { + if t.config.Stream.StrictColumns { + err := errors.Newf("input row column count (%d) does not match established stream column count (%d) and StrictColumns is enabled", len(rawCellsSlice), t.streamNumCols) + t.logger.Error(err.Error()) + return err + } + // If not strict, retain the old lenient behavior (warn and pad/truncate) + t.logger.Warnf("streamAppendRow: Input row column count (%d) != stream column count (%d). Padding/Truncating (StrictColumns is false).", len(rawCellsSlice), t.streamNumCols) + if len(rawCellsSlice) < t.streamNumCols { + paddedCells := make([]string, t.streamNumCols) + copy(paddedCells, rawCellsSlice) + for i := len(rawCellsSlice); i < t.streamNumCols; i++ { + paddedCells[i] = tw.Empty + } + rawCellsSlice = paddedCells + } else { + rawCellsSlice = rawCellsSlice[:t.streamNumCols] + } + } + } else if len(rawCellsSlice) > 0 && t.config.Stream.StrictColumns { + err := errors.Newf("failed to establish stream column count from first data row (%d cells) and StrictColumns is enabled", len(rawCellsSlice)) + t.logger.Error(err.Error()) + return err + } + + if t.streamNumCols == 0 { + t.logger.Warn("streamAppendRow: streamNumCols is 0. Cannot render row.") + return errors.New("cannot render row, column count is zero and could not be determined") + } + + _, rowMerges, _ := t.prepareWithMerges([][]string{rawCellsSlice}, t.config.Row, tw.Row) + processedRowLines := t.prepareContent(rawCellsSlice, t.config.Row) + t.logger.Debugf("streamAppendRow: Processed row lines: %d lines", len(processedRowLines)) + + f := t.renderer + cfg := t.renderer.Config() + + if !t.headerRendered && !t.firstRowRendered && t.lastRenderedPosition == "" { + if cfg.Borders.Top.Enabled() && cfg.Settings.Lines.ShowTop.Enabled() { + t.logger.Debug("streamAppendRow: Rendering table top border (first element is a row).") + var nextCellsCtx map[int]tw.CellContext + if len(processedRowLines) > 0 { + firstRowLineResp := t.streamBuildCellContexts( + tw.Row, 0, 0, processedRowLines, rowMerges, t.config.Row, + ) + nextCellsCtx = firstRowLineResp.cells + } + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Next: nextCellsCtx, + Position: tw.Row, + Location: tw.LocationFirst, + }, + Level: tw.LevelHeader, + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.logger.Debug("streamAppendRow: Top border rendered.") + } + } + + shouldDrawHeaderRowSeparator := t.headerRendered && !t.firstRowRendered && cfg.Settings.Lines.ShowHeaderLine.Enabled() + shouldDrawRowRowSeparator := t.firstRowRendered && cfg.Settings.Separators.BetweenRows.Enabled() + + firstCellForLog := "" + if len(rawCellsSlice) > 0 { + firstCellForLog = rawCellsSlice[0] + } + t.logger.Debugf("streamAppendRow: Separator Pre-Check for row starting with '%s': headerRendered=%v, firstRowRendered=%v, ShowHeaderLine=%v, BetweenRows=%v, lastRenderedPos=%q", + firstCellForLog, t.headerRendered, t.firstRowRendered, cfg.Settings.Lines.ShowHeaderLine.Enabled(), + cfg.Settings.Separators.BetweenRows.Enabled(), t.lastRenderedPosition) + t.logger.Debugf("streamAppendRow: Separator Decision Flags for row starting with '%s': shouldDrawHeaderRowSeparator=%v, shouldDrawRowRowSeparator=%v", + firstCellForLog, shouldDrawHeaderRowSeparator, shouldDrawRowRowSeparator) + + if (shouldDrawHeaderRowSeparator || shouldDrawRowRowSeparator) && t.lastRenderedPosition != tw.Position("separator") { + t.logger.Debugf("streamAppendRow: Rendering separator line for row starting with '%s'.", firstCellForLog) + prevCellsCtx := t.streamRenderedMergeState(t.lastRenderedLineContent, t.lastRenderedMergeState) + var nextCellsCtx map[int]tw.CellContext + if len(processedRowLines) > 0 { + firstRowLineResp := t.streamBuildCellContexts(tw.Row, 0, 0, processedRowLines, rowMerges, t.config.Row) + nextCellsCtx = firstRowLineResp.cells + } + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: prevCellsCtx, + Previous: nil, + Next: nextCellsCtx, + Position: tw.Row, + Location: tw.LocationMiddle, + }, + Level: tw.LevelBody, + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedPosition = tw.Position("separator") + t.lastRenderedLineContent = nil + t.lastRenderedMergeState = nil + t.logger.Debug("streamAppendRow: Separator line rendered. Updated lastRenderedPosition to 'separator'.") + } else { + details := "" + if !(shouldDrawHeaderRowSeparator || shouldDrawRowRowSeparator) { + details = "neither header/row nor row/row separator was flagged true" + } else if t.lastRenderedPosition == tw.Position("separator") { + details = "lastRenderedPosition is already 'separator'" + } else { + details = "an unexpected combination of conditions" + } + t.logger.Debugf("streamAppendRow: Separator not drawn for row '%s' because %s.", firstCellForLog, details) + } + + if len(processedRowLines) == 0 { + t.logger.Debugf("streamAppendRow: No processed row lines to render for row starting with '%s'.", firstCellForLog) + if !t.firstRowRendered { + t.firstRowRendered = true + t.logger.Debugf("streamAppendRow: Marked first row rendered (empty content after processing).") + } + return nil + } + + totalRowLines := len(processedRowLines) + for i := 0; i < totalRowLines; i++ { + resp := t.streamBuildCellContexts(tw.Row, 0, i, processedRowLines, rowMerges, t.config.Row) + t.logger.Debug("streamAppendRow: Rendering row line %d/%d with location %v for row starting with '%s'.", i, totalRowLines, resp.location, firstCellForLog) + f.Row(resp.cellsContent, tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, + Position: tw.Row, + Location: resp.location, + }, + Level: tw.LevelBody, + IsSubRow: i > 0, + + NormalizedWidths: t.streamWidths, + HasFooter: len(t.streamFooterLines) > 0, + }) + t.lastRenderedLineContent = resp.cellsContent + t.lastRenderedMergeState = make(map[int]tw.MergeState) + for colIdx, cellCtx := range resp.cells { + t.lastRenderedMergeState[colIdx] = cellCtx.Merge + } + t.lastRenderedPosition = tw.Row + } + + if !t.firstRowRendered { + t.firstRowRendered = true + t.logger.Debug("streamAppendRow: Marked first row rendered (after processing content).") + } + + t.logger.Debug("streamAppendRow: Row processing completed for row starting with '%s'.", firstCellForLog) + return nil +} + +// streamBuildCellContexts creates CellContext objects for a given line in streaming mode. +// Parameters: +// - position: The section being processed (Header, Row, Footer). +// - rowIdx: The row index within its section (always 0 for Header/Footer, row number for Row). +// - lineIdx: The line index within the processed lines for this block. +// - processedLines: All multi-lines for the current row/header/footer block. +// - sectionMerges: Merge states for the section or row (map[int]tw.MergeState). +// - sectionConfig: The CellConfig for this section (Header, Row, Footer). +// Returns a renderMergeResponse with Current, Previous, Next cells, cellsContent, and the determined Location. +func (t *Table) streamBuildCellContexts( + position tw.Position, + rowIdx, lineIdx int, + processedLines [][]string, + sectionMerges map[int]tw.MergeState, + sectionConfig tw.CellConfig, +) renderMergeResponse { + t.logger.Debug("streamBuildCellContexts: Building contexts for position=%s, rowIdx=%d, lineIdx=%d", position, rowIdx, lineIdx) + resp := renderMergeResponse{ + cells: make(map[int]tw.CellContext), + prevCells: nil, + nextCells: nil, + cellsContent: make([]string, t.streamNumCols), + location: tw.LocationMiddle, + } + + if t.streamWidths == nil || t.streamWidths.Len() == 0 || t.streamNumCols == 0 { + t.logger.Warn("streamBuildCellContexts: streamWidths is not set or streamNumCols is 0. Returning empty contexts.") + return resp + } + + currentLineContent := make([]string, t.streamNumCols) + if lineIdx >= 0 && lineIdx < len(processedLines) { + currentLineContent = padLine(processedLines[lineIdx], t.streamNumCols) + } else { + t.logger.Warnf("streamBuildCellContexts: lineIdx %d out of bounds for processedLines (len %d) at position %s, rowIdx %d. Using empty line.", lineIdx, len(processedLines), position, rowIdx) + for j := range currentLineContent { + currentLineContent[j] = tw.Empty + } + } + resp.cellsContent = currentLineContent + + colAligns := t.buildAligns(sectionConfig) + colPadding := t.buildPadding(sectionConfig.Padding) + resp.cells = t.buildCoreCellContexts(currentLineContent, sectionMerges, t.streamWidths, colAligns, colPadding, t.streamNumCols) + + if t.lastRenderedLineContent != nil && t.lastRenderedPosition.Validate() == nil { + resp.prevCells = t.streamRenderedMergeState(t.lastRenderedLineContent, t.lastRenderedMergeState) + } + + totalLinesInBlock := len(processedLines) + if lineIdx < totalLinesInBlock-1 { + resp.nextCells = make(map[int]tw.CellContext) + nextLineContent := padLine(processedLines[lineIdx+1], t.streamNumCols) + nextCells := t.buildCoreCellContexts(nextLineContent, sectionMerges, t.streamWidths, colAligns, colPadding, t.streamNumCols) + for j := 0; j < t.streamNumCols; j++ { + resp.nextCells[j] = nextCells[j] + } + } + + isFirstLineOfBlock := (lineIdx == 0) + if isFirstLineOfBlock && (t.lastRenderedLineContent == nil || t.lastRenderedPosition != position) { + resp.location = tw.LocationFirst + } + + t.logger.Debug("streamBuildCellContexts: Position %s, Row %d, Line %d/%d. Location: %v. Prev Pos: %v. Has Prev: %v.", + position, rowIdx, lineIdx, totalLinesInBlock, resp.location, t.lastRenderedPosition, t.lastRenderedLineContent != nil) + return resp +} + +// streamCalculateWidths determines the fixed column widths for streaming mode. +// It prioritizes widths from StreamConfig.Widths.PerColumn, then StreamConfig.Widths.Global, +// then derives from the provided sample data lines. +// It populates t.streamWidths and t.streamNumCols if they are currently empty. +// The sampleDataLines should be the *raw* input lines (e.g., []string for Header/Footer, or the first row's []string cells for Row). +// The paddingConfig should be the CellPadding config relevant to the sample data (Header/Row/Footer). +// Returns the determined number of columns. +// This function should only be called when t.streamWidths is currently empty. +func (t *Table) streamCalculateWidths(sampling []string, config tw.CellConfig) int { + if t.streamWidths != nil && t.streamWidths.Len() > 0 { + t.logger.Debug("streamCalculateWidths: Called when streaming widths are already set (%d columns). Reusing existing.", t.streamNumCols) + return t.streamNumCols + } + + t.logger.Debug("streamCalculateWidths: Calculating streaming widths. Sample data cells: %d. Using section config: %+v", len(sampling), config.Formatting) + + determinedNumCols := 0 + if t.config.Widths.PerColumn != nil && t.config.Widths.PerColumn.Len() > 0 { + maxColIdx := -1 + t.config.Widths.PerColumn.Each(func(col int, width int) { + if col > maxColIdx { + maxColIdx = col + } + }) + determinedNumCols = maxColIdx + 1 + t.logger.Debug("streamCalculateWidths: Determined numCols (%d) from StreamConfig.Widths.PerColumn", determinedNumCols) + } else if len(sampling) > 0 { + determinedNumCols = len(sampling) + t.logger.Debug("streamCalculateWidths: Determined numCols (%d) from sample data length", determinedNumCols) + } else { + t.logger.Debug("streamCalculateWidths: Cannot determine numCols (no PerColumn config, no sample data)") + t.streamNumCols = 0 + t.streamWidths = tw.NewMapper[int, int]() + return 0 + } + + t.streamNumCols = determinedNumCols + t.streamWidths = tw.NewMapper[int, int]() + + // Use padding and autowrap from the provided config + paddingForWidthCalc := config.Padding + autoWrapForWidthCalc := config.Formatting.AutoWrap + + if t.config.Widths.PerColumn != nil && t.config.Widths.PerColumn.Len() > 0 { + t.logger.Debug("streamCalculateWidths: Using widths from StreamConfig.Widths.PerColumn") + for i := 0; i < t.streamNumCols; i++ { + width, ok := t.config.Widths.PerColumn.OK(i) + if !ok { + width = 0 + } + if width > 0 && width < 1 { + width = 1 + } else if width < 0 { + width = 0 + } + t.streamWidths.Set(i, width) + } + } else { + // No PerColumn config, derive from sampling intelligently + t.logger.Debug("streamCalculateWidths: Intelligently deriving widths from sample data content and padding.") + tempRequiredWidths := tw.NewMapper[int, int]() // Widths from updateWidths (content + padding) + if len(sampling) > 0 { + // updateWidths calculates: DisplayWidth(content) + padLeft + padRight + t.updateWidths(sampling, tempRequiredWidths, paddingForWidthCalc) + } + + ellipsisWidthBuffer := 0 + if autoWrapForWidthCalc == tw.WrapTruncate { + ellipsisWidthBuffer = twwidth.Width(tw.CharEllipsis) + } + varianceBuffer := 2 // Your suggested variance + minTotalColWidth := tw.MinimumColumnWidth + // Example: if t.config.Stream.MinAutoColumnWidth > 0 { minTotalColWidth = t.config.Stream.MinAutoColumnWidth } + + for i := 0; i < t.streamNumCols; i++ { + // baseCellWidth (content_width + padding_width) comes from tempRequiredWidths.Get(i) + // We need to deconstruct it to apply logic to content_width first. + + sampleContent := "" + if i < len(sampling) { + sampleContent = t.Trimmer(sampling[i]) + } + sampleContentDisplayWidth := twwidth.Width(sampleContent) + + colPad := paddingForWidthCalc.Global + if i < len(paddingForWidthCalc.PerColumn) && paddingForWidthCalc.PerColumn[i].Paddable() { + colPad = paddingForWidthCalc.PerColumn[i] + } + currentPadLWidth := twwidth.Width(colPad.Left) + currentPadRWidth := twwidth.Width(colPad.Right) + currentTotalPaddingWidth := currentPadLWidth + currentPadRWidth + + // Start with the target content width logic + targetContentWidth := sampleContentDisplayWidth + if autoWrapForWidthCalc == tw.WrapTruncate { + // If content is short, ensure it's at least wide enough for an ellipsis + if targetContentWidth < ellipsisWidthBuffer { + targetContentWidth = ellipsisWidthBuffer + } + } + targetContentWidth += varianceBuffer // Add variance + + // Now calculate the total cell width based on this buffered content target + padding + calculatedWidth := targetContentWidth + currentTotalPaddingWidth + + // Apply an absolute minimum total column width + if calculatedWidth > 0 && calculatedWidth < minTotalColWidth { + t.logger.Debug("streamCalculateWidths: Col %d, InitialCalcW=%d (ContentTarget=%d + Pad=%d) is less than MinTotalW=%d. Adjusting to MinTotalW.", + i, calculatedWidth, targetContentWidth, currentTotalPaddingWidth, minTotalColWidth) + calculatedWidth = minTotalColWidth + } else if calculatedWidth <= 0 && sampleContentDisplayWidth > 0 { // If content exists but calc width is 0 (e.g. large negative variance) + // Ensure at least min width or content + padding + buffers + fallbackWidth := sampleContentDisplayWidth + currentTotalPaddingWidth + if autoWrapForWidthCalc == tw.WrapTruncate { + fallbackWidth += ellipsisWidthBuffer + } + fallbackWidth += varianceBuffer + calculatedWidth = tw.Max(minTotalColWidth, fallbackWidth) + if calculatedWidth <= 0 && (currentTotalPaddingWidth+1) > 0 { // last resort if all else is zero + calculatedWidth = currentTotalPaddingWidth + 1 + } else if calculatedWidth <= 0 { + calculatedWidth = 1 // absolute last resort + } + + t.logger.Debug("streamCalculateWidths: Col %d, CalculatedW was <=0 despite content. Adjusted to %d.", i, calculatedWidth) + } else if calculatedWidth <= 0 && sampleContentDisplayWidth == 0 { + // Column is truly empty in sample and buffers didn't make it positive, or minTotalColWidth is 0. + // Keep width 0 (it will be hidden by renderer if all content is empty for this col) + // Or, if we want empty columns to have a minimum presence (even if just padding): + // calculatedWidth = currentTotalPaddingWidth // This would make it just wide enough for padding + // For now, let truly empty sample + no min width result in 0. + calculatedWidth = 0 // Explicitly set to 0 if it ended up non-positive and no content + } + + t.streamWidths.Set(i, calculatedWidth) + t.logger.Debug("streamCalculateWidths: Col %d, SampleContentW=%d, PadW=%d, EllipsisBufIfTruncate=%d, VarianceBuf=%d -> FinalTotalColW=%d", + i, sampleContentDisplayWidth, currentTotalPaddingWidth, ellipsisWidthBuffer, varianceBuffer, calculatedWidth) + } + } + + // Apply Global Constraint (if t.config.Stream.Widths.Global > 0) + if t.config.Widths.Global > 0 && t.streamNumCols > 0 { + t.logger.Debug("streamCalculateWidths: Applying global stream width constraint %d", t.config.Widths.Global) + currentTotalColumnWidthsSum := 0 + t.streamWidths.Each(func(_ int, w int) { + currentTotalColumnWidthsSum += w + }) + + separatorWidth := 0 + if t.renderer != nil { + rendererConfig := t.renderer.Config() + if rendererConfig.Settings.Separators.BetweenColumns.Enabled() { + separatorWidth = twwidth.Width(rendererConfig.Symbols.Column()) + } + } else { + separatorWidth = 1 // Default if renderer not available yet + } + + totalWidthIncludingSeparators := currentTotalColumnWidthsSum + if t.streamNumCols > 1 { + totalWidthIncludingSeparators += (t.streamNumCols - 1) * separatorWidth + } + + if t.config.Widths.Global < totalWidthIncludingSeparators && totalWidthIncludingSeparators > 0 { // Added check for total > 0 + t.logger.Debug("streamCalculateWidths: Total calculated width (%d incl separators) exceeds global stream width (%d). Shrinking.", totalWidthIncludingSeparators, t.config.Widths.Global) + + // Target sum for column widths only (global limit - total separator width) + targetSumForColumnWidths := t.config.Widths.Global + if t.streamNumCols > 1 { + targetSumForColumnWidths -= (t.streamNumCols - 1) * separatorWidth + } + if targetSumForColumnWidths < t.streamNumCols && t.streamNumCols > 0 { // Ensure at least 1 per column if possible + targetSumForColumnWidths = t.streamNumCols + } else if targetSumForColumnWidths < 0 { + targetSumForColumnWidths = 0 + } + + scaleFactor := float64(targetSumForColumnWidths) / float64(currentTotalColumnWidthsSum) + if currentTotalColumnWidthsSum <= 0 { + scaleFactor = 0 + } // Avoid division by zero or negative scale + + adjustedSum := 0 + for i := 0; i < t.streamNumCols; i++ { + originalColWidth := t.streamWidths.Get(i) + if originalColWidth == 0 { + continue + } // Don't scale hidden columns + + scaledWidth := 0 + if scaleFactor > 0 { + scaledWidth = int(math.Round(float64(originalColWidth) * scaleFactor)) + } + + if scaledWidth < 1 && originalColWidth > 0 { // Ensure at least 1 if original had width and scaling made it too small + scaledWidth = 1 + } else if scaledWidth < 0 { // Should not happen with math.Round on positive*positive + scaledWidth = 0 + } + t.streamWidths.Set(i, scaledWidth) + adjustedSum += scaledWidth + } + + // Distribute rounding errors to meet targetSumForColumnWidths + remainingSpace := targetSumForColumnWidths - adjustedSum + t.logger.Debug("streamCalculateWidths: Scaling complete. TargetSum=%d, AchievedSum=%d, RemSpace=%d", targetSumForColumnWidths, adjustedSum, remainingSpace) + // Distribute remainingSpace (positive or negative) among non-zero width columns + if remainingSpace != 0 && t.streamNumCols > 0 { + colsToAdjust := []int{} + t.streamWidths.Each(func(col int, w int) { + if w > 0 { // Only consider columns that currently have width + colsToAdjust = append(colsToAdjust, col) + } + }) + if len(colsToAdjust) > 0 { + for i := 0; i < int(math.Abs(float64(remainingSpace))); i++ { + colIdx := colsToAdjust[i%len(colsToAdjust)] + currentColWidth := t.streamWidths.Get(colIdx) + if remainingSpace > 0 { + t.streamWidths.Set(colIdx, currentColWidth+1) + } else if remainingSpace < 0 && currentColWidth > 1 { // Don't reduce below 1 + t.streamWidths.Set(colIdx, currentColWidth-1) + } + } + } + } + t.logger.Debug("streamCalculateWidths: Widths after scaling and distribution: %v", t.streamWidths) + } else { + t.logger.Debug("streamCalculateWidths: Total calculated width (%d) fits global stream width (%d). No scaling needed.", totalWidthIncludingSeparators, t.config.Widths.Global) + } + } + + // Final sanitization + t.streamWidths.Each(func(col int, width int) { + if width < 0 { + t.streamWidths.Set(col, 0) + } + }) + + t.logger.Debug("streamCalculateWidths: Final derived stream widths after all adjustments (%d columns): %v", t.streamNumCols, t.streamWidths) + return t.streamNumCols +} + +// streamRenderBottomBorder renders the bottom border of the table in streaming mode. +// It uses the fixed streamWidths and the last rendered content to create the border context. +// It assumes Start() has been called and t.hasPrinted is true. +// Returns an error if rendering fails. +func (t *Table) streamRenderBottomBorder() error { + if t.streamWidths == nil || t.streamWidths.Len() == 0 { + t.logger.Debug("streamRenderBottomBorder: No stream widths available, skipping bottom border.") + return nil + } + + cfg := t.renderer.Config() + if !cfg.Borders.Bottom.Enabled() || !cfg.Settings.Lines.ShowBottom.Enabled() { + t.logger.Debug("streamRenderBottomBorder: Bottom border disabled in config, skipping.") + return nil + } + + // The bottom border's "Current" context is the last rendered content line + currentCells := make(map[int]tw.CellContext) + if t.lastRenderedLineContent != nil { + // Use a helper to convert last rendered state to cell contexts + currentCells = t.streamRenderedMergeState(t.lastRenderedLineContent, t.lastRenderedMergeState) + } else { + // No content was ever rendered, but we might still want a bottom border if a top border was drawn. + // Create empty cell contexts. + for i := 0; i < t.streamNumCols; i++ { + currentCells[i] = tw.CellContext{Width: t.streamWidths.Get(i)} + } + t.logger.Debug("streamRenderBottomBorder: No previous content line, creating empty context for bottom border.") + } + + f := t.renderer + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: currentCells, // Context of the line *above* the bottom border + Previous: nil, // No line before this, relative to the border itself (or use lastRendered's previous?) + Next: nil, // No line after the bottom border + Position: t.lastRenderedPosition, // Position of the content above the border (Row or Footer) + Location: tw.LocationEnd, // This is the absolute end + }, + Level: tw.LevelFooter, // Bottom border is LevelFooter + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.logger.Debug("streamRenderBottomBorder: Bottom border rendered.") + return nil +} + +// streamRenderFooter renders the stored footer lines in streaming mode. +// It's called by Close(). It renders the Row/Footer separator line first. +// It assumes Start() has been called and t.hasPrinted is true. +// Returns an error if rendering fails. +func (t *Table) streamRenderFooter(processedFooterLines [][]string) error { + t.logger.Debug("streamRenderFooter: Rendering %d processed footer lines.", len(processedFooterLines)) + + if t.streamWidths == nil || t.streamWidths.Len() == 0 || t.streamNumCols == 0 { + t.logger.Warn("streamRenderFooter: No stream widths or columns defined. Cannot render footer.") + return errors.New("cannot render stream footer without defined column widths") + } + + if len(processedFooterLines) == 0 { + t.logger.Debug("streamRenderFooter: No footer lines to render.") + return nil + } + + f := t.renderer + cfg := t.renderer.Config() + + // Render Row/Footer or Header/Footer Separator Line + // This separator is drawn if ShowFooterLine is enabled AND there was content before the footer. + // The last rendered position (t.lastRenderedPosition) should be Row or Header or "separator". + if (t.lastRenderedPosition == tw.Row || t.lastRenderedPosition == tw.Header || t.lastRenderedPosition == tw.Position("separator")) && + cfg.Settings.Lines.ShowFooterLine.Enabled() { + + t.logger.Debug("streamRenderFooter: Rendering Row/Footer or Header/Footer separator line.") + + // Previous context is the last line rendered before this footer + prevCells := t.streamRenderedMergeState(t.lastRenderedLineContent, t.lastRenderedMergeState) + + // Next context is the first line of this footer + var nextCells map[int]tw.CellContext = nil + if len(processedFooterLines) > 0 { + // Need merge states for the footer section. + // Since footer is processed once and stored, detect merges on its raw input once. + // This requires access to the *original* raw footer strings passed to Footer(). + // For simplicity now, assume no complex horizontal merges in footer for this separator line context. + // A better approach: streamStoreFooter should also calculate and store footerMerges. + // For now, create nextCells without specific merge info for the separator line. + // Or, call prepareWithMerges on the *stored processed* lines, which might be okay for simple cases. + // Let's pass nil for sectionMerges to streamBuildCellContexts for this specific Next context. + // It will result in default (no-merge) states. + + // For now, let's build nextCells manually for the separator line context + nextCells = make(map[int]tw.CellContext) + firstFooterLineContent := padLine(processedFooterLines[0], t.streamNumCols) + // Footer merges should be calculated in streamStoreFooter and stored if needed. + // For now, assume no merges for this 'Next' context. + for j := 0; j < t.streamNumCols; j++ { + nextCells[j] = tw.CellContext{Data: firstFooterLineContent[j], Width: t.streamWidths.Get(j)} + } + } + + separatorLevel := tw.LevelFooter // Line before footer section is LevelFooter + separatorPosition := tw.Footer // Positioned relative to the footer it precedes + separatorLocation := tw.LocationMiddle + + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: prevCells, // Context of line above separator + Previous: nil, // No line before Current in this specific context + Next: nextCells, // Context of line below separator (first footer line) + Position: separatorPosition, + Location: separatorLocation, + }, + Level: separatorLevel, + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedPosition = tw.Position("separator") // Update state + t.lastRenderedLineContent = nil + t.lastRenderedMergeState = nil + t.logger.Debug("streamRenderFooter: Footer separator line rendered.") + } + // End Render Separator Line + + // Detect horizontal merges for the footer section based on its (assumed stored) raw input. + // This is tricky because streamStoreFooter gets []string, but prepareWithMerges expects [][]string. + // For simplicity, if complex merges are needed in footer, streamStoreFooter should + // have received raw data, called prepareWithMerges, and stored those merges. + // For now, assume no complex horizontal merges in footer or pass nil for sectionMerges. + // Let's assume footerMerges were calculated and stored as `t.streamFooterMerges map[int]tw.MergeState` + // by `streamStoreFooter`. For this example, we'll pass nil, meaning no merges. + var footerMerges map[int]tw.MergeState = nil // Placeholder + + totalFooterLines := len(processedFooterLines) + for i := 0; i < totalFooterLines; i++ { + resp := t.streamBuildCellContexts( + tw.Footer, + 0, // Row index within Footer (always 0) + i, // Line index + processedFooterLines, + footerMerges, // Pass footer-specific merges if calculated and stored + t.config.Footer, + ) + + // Special Location logic for the *very last line* of the table if this footer line is it. + // This is complex because bottom border might follow. + // Let streamBuildCellContexts handle LocationFirst/Middle for now. + // streamRenderBottomBorder will handle the final LocationEnd for its line. + // If this footer line is the last content and no bottom border, *it* should be LocationEnd. + + // If this is the last line of the last content block (footer), and no bottom border will be drawn, + // its Location should be End. + isLastLineOfTableContent := (i == totalFooterLines-1) && + !(cfg.Borders.Bottom.Enabled() && cfg.Settings.Lines.ShowBottom.Enabled()) + if isLastLineOfTableContent { + resp.location = tw.LocationEnd + t.logger.Debug("streamRenderFooter: Setting LocationEnd for last footer line as no bottom border will follow.") + } + + f.Footer([][]string{resp.cellsContent}, tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, // Next is nil if last line of footer block + Position: tw.Footer, + Location: resp.location, + }, + Level: tw.LevelFooter, + IsSubRow: (i > 0), + + NormalizedWidths: t.streamWidths, + }) + + t.lastRenderedLineContent = resp.cellsContent + t.lastRenderedMergeState = make(map[int]tw.MergeState) + for colIdx, cellCtx := range resp.cells { + t.lastRenderedMergeState[colIdx] = cellCtx.Merge + } + t.lastRenderedPosition = tw.Footer + } + + t.logger.Debug("streamRenderFooter: Footer content rendering completed.") + return nil +} + +// streamRenderHeader processes and renders the header section in streaming mode. +// It calculates/uses fixed stream widths, processes content, renders borders/lines, +// and updates streaming state. +// It assumes Start() has already been called and t.hasPrinted is true. +func (t *Table) streamRenderHeader(headers []string) error { + t.logger.Debug("streamRenderHeader called with headers: %v", headers) + + if !t.config.Stream.Enable { + return errors.New("streaming mode is disabled") + } + + if t.headerRendered { + t.logger.Warn("streamRenderHeader called but header already rendered. Ignoring.") + return nil + } + + if err := t.ensureStreamWidthsCalculated(headers, t.config.Header); err != nil { + return err + } + + _, headerMerges, _ := t.prepareWithMerges([][]string{headers}, t.config.Header, tw.Header) + processedHeaderLines := t.prepareContent(headers, t.config.Header) + t.logger.Debug("streamRenderHeader: Processed header lines: %d", len(processedHeaderLines)) + + if t.streamNumCols > 0 { + t.headerRendered = true + } + if len(processedHeaderLines) == 0 && t.streamNumCols == 0 { + t.logger.Debug("streamRenderHeader: No header content and no columns determined.") + return nil + } + + f := t.renderer + cfg := t.renderer.Config() + + if t.lastRenderedPosition == "" && cfg.Borders.Top.Enabled() && cfg.Settings.Lines.ShowTop.Enabled() { + t.logger.Debug("streamRenderHeader: Rendering table top border.") + var nextCellsCtx map[int]tw.CellContext + if len(processedHeaderLines) > 0 { + firstHeaderLineResp := t.streamBuildCellContexts( + tw.Header, 0, 0, processedHeaderLines, headerMerges, t.config.Header, + ) + nextCellsCtx = firstHeaderLineResp.cells + } + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Next: nextCellsCtx, + Position: tw.Header, + Location: tw.LocationFirst, + }, + Level: tw.LevelHeader, + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.logger.Debug("streamRenderHeader: Top border rendered.") + } + + hasTopPadding := t.config.Header.Padding.Global.Top != tw.Empty + if hasTopPadding { + resp := t.streamBuildCellContexts(tw.Header, 0, -1, nil, headerMerges, t.config.Header) + resp.cellsContent = t.buildPaddingLineContents(t.config.Header.Padding.Global.Top, t.streamWidths, t.streamNumCols, headerMerges) + resp.location = tw.LocationFirst + t.logger.Debug("streamRenderHeader: Rendering header top padding line: %v (loc: %v)", resp.cellsContent, resp.location) + f.Header([][]string{resp.cellsContent}, tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, + Position: tw.Header, + Location: resp.location, + }, + Level: tw.LevelHeader, + IsSubRow: true, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedLineContent = resp.cellsContent + t.lastRenderedMergeState = make(map[int]tw.MergeState) + for colIdx, cellCtx := range resp.cells { + t.lastRenderedMergeState[colIdx] = cellCtx.Merge + } + t.lastRenderedPosition = tw.Header + } + + totalHeaderLines := len(processedHeaderLines) + for i := 0; i < totalHeaderLines; i++ { + resp := t.streamBuildCellContexts(tw.Header, 0, i, processedHeaderLines, headerMerges, t.config.Header) + t.logger.Debug("streamRenderHeader: Rendering header content line %d/%d with location %v", i, totalHeaderLines, resp.location) + f.Header([][]string{resp.cellsContent}, tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, + Position: tw.Header, + Location: resp.location, + }, + Level: tw.LevelHeader, + IsSubRow: i > 0, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedLineContent = resp.cellsContent + t.lastRenderedMergeState = make(map[int]tw.MergeState) + for colIdx, cellCtx := range resp.cells { + t.lastRenderedMergeState[colIdx] = cellCtx.Merge + } + t.lastRenderedPosition = tw.Header + } + + hasBottomPadding := t.config.Header.Padding.Global.Bottom != tw.Empty + if hasBottomPadding { + resp := t.streamBuildCellContexts(tw.Header, 0, totalHeaderLines, nil, headerMerges, t.config.Header) + resp.cellsContent = t.buildPaddingLineContents(t.config.Header.Padding.Global.Bottom, t.streamWidths, t.streamNumCols, headerMerges) + resp.location = tw.LocationEnd + t.logger.Debug("streamRenderHeader: Rendering header bottom padding line: %v (loc: %v)", resp.cellsContent, resp.location) + f.Header([][]string{resp.cellsContent}, tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, + Position: tw.Header, + Location: resp.location, + }, + Level: tw.LevelHeader, + IsSubRow: true, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedLineContent = resp.cellsContent + t.lastRenderedMergeState = make(map[int]tw.MergeState) + for colIdx, cellCtx := range resp.cells { + t.lastRenderedMergeState[colIdx] = cellCtx.Merge + } + t.lastRenderedPosition = tw.Header + } + + if cfg.Settings.Lines.ShowHeaderLine.Enabled() && (t.firstRowRendered || len(t.streamFooterLines) > 0) { + t.logger.Debug("streamRenderHeader: Rendering header separator line.") + resp := t.streamBuildCellContexts(tw.Header, 0, totalHeaderLines-1, processedHeaderLines, headerMerges, t.config.Header) + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: t.streamWidths, + ColMaxWidths: tw.CellWidth{PerColumn: t.streamWidths}, + Current: resp.cells, + Previous: resp.prevCells, + Next: nil, + Position: tw.Header, + Location: tw.LocationMiddle, + }, + Level: tw.LevelBody, + IsSubRow: false, + + NormalizedWidths: t.streamWidths, + }) + t.lastRenderedPosition = tw.Position("separator") + t.lastRenderedLineContent = nil + t.lastRenderedMergeState = nil + } + + t.logger.Debug("streamRenderHeader: Header content rendering completed.") + return nil +} + +// streamRenderedMergeState converts the stored last rendered line content +// and its merge states into a map of CellContext, suitable for providing +// context (e.g., "Current" or "Previous") to the renderer. +// It uses the fixed streamWidths. +func (t *Table) streamRenderedMergeState( + lineContent []string, + lineMergeStates map[int]tw.MergeState, +) map[int]tw.CellContext { + cells := make(map[int]tw.CellContext) + if t.streamWidths == nil || t.streamWidths.Len() == 0 || t.streamNumCols == 0 { + t.logger.Warn("streamRenderedMergeState: streamWidths not set or streamNumCols is 0. Returning empty cell contexts.") + return cells + } + + // Ensure lineContent is padded to streamNumCols if it's not nil + var paddedLineContent []string + if lineContent != nil { + paddedLineContent = padLine(lineContent, t.streamNumCols) + } else { + // If lineContent is nil (e.g. after a separator), create an empty padded line + paddedLineContent = make([]string, t.streamNumCols) + for i := range paddedLineContent { + paddedLineContent[i] = tw.Empty + } + } + + for j := 0; j < t.streamNumCols; j++ { + cellData := paddedLineContent[j] + colWidth := t.streamWidths.Get(j) + mergeState := tw.MergeState{} // Default to no merge + + if lineMergeStates != nil { + if state, ok := lineMergeStates[j]; ok { + mergeState = state + } + } + + // For context purposes (like Previous or Current for a border line), + // Align and Padding are often less critical than Data, Width, and Merge. + // We can use default/empty Align and Padding here. + cells[j] = tw.CellContext{ + Data: cellData, + Align: tw.AlignDefault, // Or tw.AlignNone if preferred for context-only cells + Padding: tw.Padding{}, // Empty padding + Width: colWidth, + Merge: mergeState, + } + } + return cells +} + +// streamStoreFooter processes the footer content and stores it for later rendering by Close() +// in streaming mode. It ensures stream widths are calculated if not already set. +func (t *Table) streamStoreFooter(footers []string) error { + t.logger.Debug("streamStoreFooter called with footers: %v", footers) + + if !t.config.Stream.Enable { + return errors.New("streaming mode is disabled") + } + + if len(footers) == 0 { + t.logger.Debug("streamStoreFooter: Empty footer cells, storing empty footer lines.") + t.streamFooterLines = [][]string{} + return nil + } + + if err := t.ensureStreamWidthsCalculated(footers, t.config.Footer); err != nil { + t.logger.Warnf("streamStoreFooter: Failed to determine column count from footer data: %v", err) + t.streamFooterLines = [][]string{} + return nil + } + + if t.streamNumCols > 0 && len(footers) != t.streamNumCols { + t.logger.Warnf("streamStoreFooter: Input footer column count (%d) does not match fixed stream column count (%d). Padding/Truncating input footers.", len(footers), t.streamNumCols) + if len(footers) < t.streamNumCols { + paddedFooters := make([]string, t.streamNumCols) + copy(paddedFooters, footers) + for i := len(footers); i < t.streamNumCols; i++ { + paddedFooters[i] = tw.Empty + } + footers = paddedFooters + } else { + footers = footers[:t.streamNumCols] + } + } + + if t.streamNumCols == 0 { + t.logger.Warn("streamStoreFooter: streamNumCols is 0, cannot process/store footer lines meaningfully.") + t.streamFooterLines = [][]string{} + return nil + } + + t.streamFooterLines = t.prepareContent(footers, t.config.Footer) + t.logger.Debug("streamStoreFooter: Processed and stored footer lines: %d lines. Content: %v", len(t.streamFooterLines), t.streamFooterLines) + + return nil +} diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go deleted file mode 100644 index f913149c..00000000 --- a/vendor/github.com/olekukonko/tablewriter/table.go +++ /dev/null @@ -1,967 +0,0 @@ -// Copyright 2014 Oleku Konko All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. - -// This module is a Table Writer API for the Go Programming Language. -// The protocols were written in pure Go and works on windows and unix systems - -// Create & Generate text based table -package tablewriter - -import ( - "bytes" - "fmt" - "io" - "regexp" - "strings" -) - -const ( - MAX_ROW_WIDTH = 30 -) - -const ( - CENTER = "+" - ROW = "-" - COLUMN = "|" - SPACE = " " - NEWLINE = "\n" -) - -const ( - ALIGN_DEFAULT = iota - ALIGN_CENTER - ALIGN_RIGHT - ALIGN_LEFT -) - -var ( - decimal = regexp.MustCompile(`^-?(?:\d{1,3}(?:,\d{3})*|\d+)(?:\.\d+)?$`) - percent = regexp.MustCompile(`^-?\d+\.?\d*$%$`) -) - -type Border struct { - Left bool - Right bool - Top bool - Bottom bool -} - -type Table struct { - out io.Writer - rows [][]string - lines [][][]string - cs map[int]int - rs map[int]int - headers [][]string - footers [][]string - caption bool - captionText string - autoFmt bool - autoWrap bool - reflowText bool - mW int - pCenter string - pRow string - pColumn string - tColumn int - tRow int - hAlign int - fAlign int - align int - newLine string - rowLine bool - autoMergeCells bool - columnsToAutoMergeCells map[int]bool - noWhiteSpace bool - tablePadding string - hdrLine bool - borders Border - colSize int - headerParams []string - columnsParams []string - footerParams []string - columnsAlign []int -} - -// Start New Table -// Take io.Writer Directly -func NewWriter(writer io.Writer) *Table { - t := &Table{ - out: writer, - rows: [][]string{}, - lines: [][][]string{}, - cs: make(map[int]int), - rs: make(map[int]int), - headers: [][]string{}, - footers: [][]string{}, - caption: false, - captionText: "Table caption.", - autoFmt: true, - autoWrap: true, - reflowText: true, - mW: MAX_ROW_WIDTH, - pCenter: CENTER, - pRow: ROW, - pColumn: COLUMN, - tColumn: -1, - tRow: -1, - hAlign: ALIGN_DEFAULT, - fAlign: ALIGN_DEFAULT, - align: ALIGN_DEFAULT, - newLine: NEWLINE, - rowLine: false, - hdrLine: true, - borders: Border{Left: true, Right: true, Bottom: true, Top: true}, - colSize: -1, - headerParams: []string{}, - columnsParams: []string{}, - footerParams: []string{}, - columnsAlign: []int{}} - return t -} - -// Render table output -func (t *Table) Render() { - if t.borders.Top { - t.printLine(true) - } - t.printHeading() - if t.autoMergeCells { - t.printRowsMergeCells() - } else { - t.printRows() - } - if !t.rowLine && t.borders.Bottom { - t.printLine(true) - } - t.printFooter() - - if t.caption { - t.printCaption() - } -} - -const ( - headerRowIdx = -1 - footerRowIdx = -2 -) - -// Set table header -func (t *Table) SetHeader(keys []string) { - t.colSize = len(keys) - for i, v := range keys { - lines := t.parseDimension(v, i, headerRowIdx) - t.headers = append(t.headers, lines) - } -} - -// Set table Footer -func (t *Table) SetFooter(keys []string) { - //t.colSize = len(keys) - for i, v := range keys { - lines := t.parseDimension(v, i, footerRowIdx) - t.footers = append(t.footers, lines) - } -} - -// Set table Caption -func (t *Table) SetCaption(caption bool, captionText ...string) { - t.caption = caption - if len(captionText) == 1 { - t.captionText = captionText[0] - } -} - -// Turn header autoformatting on/off. Default is on (true). -func (t *Table) SetAutoFormatHeaders(auto bool) { - t.autoFmt = auto -} - -// Turn automatic multiline text adjustment on/off. Default is on (true). -func (t *Table) SetAutoWrapText(auto bool) { - t.autoWrap = auto -} - -// Turn automatic reflowing of multiline text when rewrapping. Default is on (true). -func (t *Table) SetReflowDuringAutoWrap(auto bool) { - t.reflowText = auto -} - -// Set the Default column width -func (t *Table) SetColWidth(width int) { - t.mW = width -} - -// Set the minimal width for a column -func (t *Table) SetColMinWidth(column int, width int) { - t.cs[column] = width -} - -// Set the Column Separator -func (t *Table) SetColumnSeparator(sep string) { - t.pColumn = sep -} - -// Set the Row Separator -func (t *Table) SetRowSeparator(sep string) { - t.pRow = sep -} - -// Set the center Separator -func (t *Table) SetCenterSeparator(sep string) { - t.pCenter = sep -} - -// Set Header Alignment -func (t *Table) SetHeaderAlignment(hAlign int) { - t.hAlign = hAlign -} - -// Set Footer Alignment -func (t *Table) SetFooterAlignment(fAlign int) { - t.fAlign = fAlign -} - -// Set Table Alignment -func (t *Table) SetAlignment(align int) { - t.align = align -} - -// Set No White Space -func (t *Table) SetNoWhiteSpace(allow bool) { - t.noWhiteSpace = allow -} - -// Set Table Padding -func (t *Table) SetTablePadding(padding string) { - t.tablePadding = padding -} - -func (t *Table) SetColumnAlignment(keys []int) { - for _, v := range keys { - switch v { - case ALIGN_CENTER: - break - case ALIGN_LEFT: - break - case ALIGN_RIGHT: - break - default: - v = ALIGN_DEFAULT - } - t.columnsAlign = append(t.columnsAlign, v) - } -} - -// Set New Line -func (t *Table) SetNewLine(nl string) { - t.newLine = nl -} - -// Set Header Line -// This would enable / disable a line after the header -func (t *Table) SetHeaderLine(line bool) { - t.hdrLine = line -} - -// Set Row Line -// This would enable / disable a line on each row of the table -func (t *Table) SetRowLine(line bool) { - t.rowLine = line -} - -// Set Auto Merge Cells -// This would enable / disable the merge of cells with identical values -func (t *Table) SetAutoMergeCells(auto bool) { - t.autoMergeCells = auto -} - -// Set Auto Merge Cells By Column Index -// This would enable / disable the merge of cells with identical values for specific columns -// If cols is empty, it is the same as `SetAutoMergeCells(true)`. -func (t *Table) SetAutoMergeCellsByColumnIndex(cols []int) { - t.autoMergeCells = true - - if len(cols) > 0 { - m := make(map[int]bool) - for _, col := range cols { - m[col] = true - } - t.columnsToAutoMergeCells = m - } -} - -// Set Table Border -// This would enable / disable line around the table -func (t *Table) SetBorder(border bool) { - t.SetBorders(Border{border, border, border, border}) -} - -func (t *Table) SetBorders(border Border) { - t.borders = border -} - -// Append row to table -func (t *Table) Append(row []string) { - rowSize := len(t.headers) - if rowSize > t.colSize { - t.colSize = rowSize - } - - n := len(t.lines) - line := [][]string{} - for i, v := range row { - - // Detect string width - // Detect String height - // Break strings into words - out := t.parseDimension(v, i, n) - - // Append broken words - line = append(line, out) - } - t.lines = append(t.lines, line) -} - -// Append row to table with color attributes -func (t *Table) Rich(row []string, colors []Colors) { - rowSize := len(t.headers) - if rowSize > t.colSize { - t.colSize = rowSize - } - - n := len(t.lines) - line := [][]string{} - for i, v := range row { - - // Detect string width - // Detect String height - // Break strings into words - out := t.parseDimension(v, i, n) - - if len(colors) > i { - color := colors[i] - out[0] = format(out[0], color) - } - - // Append broken words - line = append(line, out) - } - t.lines = append(t.lines, line) -} - -// Allow Support for Bulk Append -// Eliminates repeated for loops -func (t *Table) AppendBulk(rows [][]string) { - for _, row := range rows { - t.Append(row) - } -} - -// NumLines to get the number of lines -func (t *Table) NumLines() int { - return len(t.lines) -} - -// Clear rows -func (t *Table) ClearRows() { - t.lines = [][][]string{} -} - -// Clear footer -func (t *Table) ClearFooter() { - t.footers = [][]string{} -} - -// Center based on position and border. -func (t *Table) center(i int) string { - if i == -1 && !t.borders.Left { - return t.pRow - } - - if i == len(t.cs)-1 && !t.borders.Right { - return t.pRow - } - - return t.pCenter -} - -// Print line based on row width -func (t *Table) printLine(nl bool) { - fmt.Fprint(t.out, t.center(-1)) - for i := 0; i < len(t.cs); i++ { - v := t.cs[i] - fmt.Fprintf(t.out, "%s%s%s%s", - t.pRow, - strings.Repeat(string(t.pRow), v), - t.pRow, - t.center(i)) - } - if nl { - fmt.Fprint(t.out, t.newLine) - } -} - -// Print line based on row width with our without cell separator -func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { - fmt.Fprint(t.out, t.pCenter) - for i := 0; i < len(t.cs); i++ { - v := t.cs[i] - if i > len(displayCellSeparator) || displayCellSeparator[i] { - // Display the cell separator - fmt.Fprintf(t.out, "%s%s%s%s", - t.pRow, - strings.Repeat(string(t.pRow), v), - t.pRow, - t.pCenter) - } else { - // Don't display the cell separator for this cell - fmt.Fprintf(t.out, "%s%s", - strings.Repeat(" ", v+2), - t.pCenter) - } - } - if nl { - fmt.Fprint(t.out, t.newLine) - } -} - -// Return the PadRight function if align is left, PadLeft if align is right, -// and Pad by default -func pad(align int) func(string, string, int) string { - padFunc := Pad - switch align { - case ALIGN_LEFT: - padFunc = PadRight - case ALIGN_RIGHT: - padFunc = PadLeft - } - return padFunc -} - -// Print heading information -func (t *Table) printHeading() { - // Check if headers is available - if len(t.headers) < 1 { - return - } - - // Identify last column - end := len(t.cs) - 1 - - // Get pad function - padFunc := pad(t.hAlign) - - // Checking for ANSI escape sequences for header - is_esc_seq := false - if len(t.headerParams) > 0 { - is_esc_seq = true - } - - // Maximum height. - max := t.rs[headerRowIdx] - - // Print Heading - for x := 0; x < max; x++ { - // Check if border is set - // Replace with space if not set - if !t.noWhiteSpace { - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) - } - - for y := 0; y <= end; y++ { - v := t.cs[y] - h := "" - - if y < len(t.headers) && x < len(t.headers[y]) { - h = t.headers[y][x] - } - if t.autoFmt { - h = Title(h) - } - pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn) - if t.noWhiteSpace { - pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding) - } - if is_esc_seq { - if !t.noWhiteSpace { - fmt.Fprintf(t.out, " %s %s", - format(padFunc(h, SPACE, v), - t.headerParams[y]), pad) - } else { - fmt.Fprintf(t.out, "%s %s", - format(padFunc(h, SPACE, v), - t.headerParams[y]), pad) - } - } else { - if !t.noWhiteSpace { - fmt.Fprintf(t.out, " %s %s", - padFunc(h, SPACE, v), - pad) - } else { - // the spaces between breaks the kube formatting - fmt.Fprintf(t.out, "%s%s", - padFunc(h, SPACE, v), - pad) - } - } - } - // Next line - fmt.Fprint(t.out, t.newLine) - } - if t.hdrLine { - t.printLine(true) - } -} - -// Print heading information -func (t *Table) printFooter() { - // Check if headers is available - if len(t.footers) < 1 { - return - } - - // Only print line if border is not set - if !t.borders.Bottom { - t.printLine(true) - } - - // Identify last column - end := len(t.cs) - 1 - - // Get pad function - padFunc := pad(t.fAlign) - - // Checking for ANSI escape sequences for header - is_esc_seq := false - if len(t.footerParams) > 0 { - is_esc_seq = true - } - - // Maximum height. - max := t.rs[footerRowIdx] - - // Print Footer - erasePad := make([]bool, len(t.footers)) - for x := 0; x < max; x++ { - // Check if border is set - // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) - - for y := 0; y <= end; y++ { - v := t.cs[y] - f := "" - if y < len(t.footers) && x < len(t.footers[y]) { - f = t.footers[y][x] - } - if t.autoFmt { - f = Title(f) - } - pad := ConditionString((y == end && !t.borders.Top), SPACE, t.pColumn) - - if erasePad[y] || (x == 0 && len(f) == 0) { - pad = SPACE - erasePad[y] = true - } - - if is_esc_seq { - fmt.Fprintf(t.out, " %s %s", - format(padFunc(f, SPACE, v), - t.footerParams[y]), pad) - } else { - fmt.Fprintf(t.out, " %s %s", - padFunc(f, SPACE, v), - pad) - } - - //fmt.Fprintf(t.out, " %s %s", - // padFunc(f, SPACE, v), - // pad) - } - // Next line - fmt.Fprint(t.out, t.newLine) - //t.printLine(true) - } - - hasPrinted := false - - for i := 0; i <= end; i++ { - v := t.cs[i] - pad := t.pRow - center := t.pCenter - length := len(t.footers[i][0]) - - if length > 0 { - hasPrinted = true - } - - // Set center to be space if length is 0 - if length == 0 && !t.borders.Right { - center = SPACE - } - - // Print first junction - if i == 0 { - if length > 0 && !t.borders.Left { - center = t.pRow - } - fmt.Fprint(t.out, center) - } - - // Pad With space of length is 0 - if length == 0 { - pad = SPACE - } - // Ignore left space as it has printed before - if hasPrinted || t.borders.Left { - pad = t.pRow - center = t.pCenter - } - - // Change Center end position - if center != SPACE { - if i == end && !t.borders.Right { - center = t.pRow - } - } - - // Change Center start position - if center == SPACE { - if i < end && len(t.footers[i+1][0]) != 0 { - if !t.borders.Left { - center = t.pRow - } else { - center = t.pCenter - } - } - } - - // Print the footer - fmt.Fprintf(t.out, "%s%s%s%s", - pad, - strings.Repeat(string(pad), v), - pad, - center) - - } - - fmt.Fprint(t.out, t.newLine) -} - -// Print caption text -func (t Table) printCaption() { - width := t.getTableWidth() - paragraph, _ := WrapString(t.captionText, width) - for linecount := 0; linecount < len(paragraph); linecount++ { - fmt.Fprintln(t.out, paragraph[linecount]) - } -} - -// Calculate the total number of characters in a row -func (t Table) getTableWidth() int { - var chars int - for _, v := range t.cs { - chars += v - } - - // Add chars, spaces, seperators to calculate the total width of the table. - // ncols := t.colSize - // spaces := ncols * 2 - // seps := ncols + 1 - - return (chars + (3 * t.colSize) + 2) -} - -func (t Table) printRows() { - for i, lines := range t.lines { - t.printRow(lines, i) - } -} - -func (t *Table) fillAlignment(num int) { - if len(t.columnsAlign) < num { - t.columnsAlign = make([]int, num) - for i := range t.columnsAlign { - t.columnsAlign[i] = t.align - } - } -} - -// Print Row Information -// Adjust column alignment based on type - -func (t *Table) printRow(columns [][]string, rowIdx int) { - // Get Maximum Height - max := t.rs[rowIdx] - total := len(columns) - - // TODO Fix uneven col size - // if total < t.colSize { - // for n := t.colSize - total; n < t.colSize ; n++ { - // columns = append(columns, []string{SPACE}) - // t.cs[n] = t.mW - // } - //} - - // Pad Each Height - pads := []int{} - - // Checking for ANSI escape sequences for columns - is_esc_seq := false - if len(t.columnsParams) > 0 { - is_esc_seq = true - } - t.fillAlignment(total) - - for i, line := range columns { - length := len(line) - pad := max - length - pads = append(pads, pad) - for n := 0; n < pad; n++ { - columns[i] = append(columns[i], " ") - } - } - //fmt.Println(max, "\n") - for x := 0; x < max; x++ { - for y := 0; y < total; y++ { - - // Check if border is set - if !t.noWhiteSpace { - fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) - fmt.Fprintf(t.out, SPACE) - } - - str := columns[y][x] - - // Embedding escape sequence with column value - if is_esc_seq { - str = format(str, t.columnsParams[y]) - } - - // This would print alignment - // Default alignment would use multiple configuration - switch t.columnsAlign[y] { - case ALIGN_CENTER: // - fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) - case ALIGN_RIGHT: - fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) - case ALIGN_LEFT: - fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) - default: - if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { - fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) - } else { - fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) - - // TODO Custom alignment per column - //if max == 1 || pads[y] > 0 { - // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) - //} else { - // fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) - //} - - } - } - if !t.noWhiteSpace { - fmt.Fprintf(t.out, SPACE) - } else { - fmt.Fprintf(t.out, t.tablePadding) - } - } - // Check if border is set - // Replace with space if not set - if !t.noWhiteSpace { - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) - } - fmt.Fprint(t.out, t.newLine) - } - - if t.rowLine { - t.printLine(true) - } -} - -// Print the rows of the table and merge the cells that are identical -func (t *Table) printRowsMergeCells() { - var previousLine []string - var displayCellBorder []bool - var tmpWriter bytes.Buffer - for i, lines := range t.lines { - // We store the display of the current line in a tmp writer, as we need to know which border needs to be print above - previousLine, displayCellBorder = t.printRowMergeCells(&tmpWriter, lines, i, previousLine) - if i > 0 { //We don't need to print borders above first line - if t.rowLine { - t.printLineOptionalCellSeparators(true, displayCellBorder) - } - } - tmpWriter.WriteTo(t.out) - } - //Print the end of the table - if t.rowLine { - t.printLine(true) - } -} - -// Print Row Information to a writer and merge identical cells. -// Adjust column alignment based on type - -func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx int, previousLine []string) ([]string, []bool) { - // Get Maximum Height - max := t.rs[rowIdx] - total := len(columns) - - // Pad Each Height - pads := []int{} - - // Checking for ANSI escape sequences for columns - is_esc_seq := false - if len(t.columnsParams) > 0 { - is_esc_seq = true - } - for i, line := range columns { - length := len(line) - pad := max - length - pads = append(pads, pad) - for n := 0; n < pad; n++ { - columns[i] = append(columns[i], " ") - } - } - - var displayCellBorder []bool - t.fillAlignment(total) - for x := 0; x < max; x++ { - for y := 0; y < total; y++ { - - // Check if border is set - fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) - - fmt.Fprintf(writer, SPACE) - - str := columns[y][x] - - // Embedding escape sequence with column value - if is_esc_seq { - str = format(str, t.columnsParams[y]) - } - - if t.autoMergeCells { - var mergeCell bool - if t.columnsToAutoMergeCells != nil { - // Check to see if the column index is in columnsToAutoMergeCells. - if t.columnsToAutoMergeCells[y] { - mergeCell = true - } - } else { - // columnsToAutoMergeCells was not set. - mergeCell = true - } - //Store the full line to merge mutli-lines cells - fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") - if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" && mergeCell { - // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. - displayCellBorder = append(displayCellBorder, false) - str = "" - } else { - // First line or different content, keep the content and print the cell border - displayCellBorder = append(displayCellBorder, true) - } - } - - // This would print alignment - // Default alignment would use multiple configuration - switch t.columnsAlign[y] { - case ALIGN_CENTER: // - fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y])) - case ALIGN_RIGHT: - fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) - case ALIGN_LEFT: - fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) - default: - if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { - fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) - } else { - fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) - } - } - fmt.Fprintf(writer, SPACE) - } - // Check if border is set - // Replace with space if not set - fmt.Fprint(writer, ConditionString(t.borders.Left, t.pColumn, SPACE)) - fmt.Fprint(writer, t.newLine) - } - - //The new previous line is the current one - previousLine = make([]string, total) - for y := 0; y < total; y++ { - previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells - } - //Returns the newly added line and wether or not a border should be displayed above. - return previousLine, displayCellBorder -} - -func (t *Table) parseDimension(str string, colKey, rowKey int) []string { - var ( - raw []string - maxWidth int - ) - - raw = getLines(str) - maxWidth = 0 - for _, line := range raw { - if w := DisplayWidth(line); w > maxWidth { - maxWidth = w - } - } - - // If wrapping, ensure that all paragraphs in the cell fit in the - // specified width. - if t.autoWrap { - // If there's a maximum allowed width for wrapping, use that. - if maxWidth > t.mW { - maxWidth = t.mW - } - - // In the process of doing so, we need to recompute maxWidth. This - // is because perhaps a word in the cell is longer than the - // allowed maximum width in t.mW. - newMaxWidth := maxWidth - newRaw := make([]string, 0, len(raw)) - - if t.reflowText { - // Make a single paragraph of everything. - raw = []string{strings.Join(raw, " ")} - } - for i, para := range raw { - paraLines, _ := WrapString(para, maxWidth) - for _, line := range paraLines { - if w := DisplayWidth(line); w > newMaxWidth { - newMaxWidth = w - } - } - if i > 0 { - newRaw = append(newRaw, " ") - } - newRaw = append(newRaw, paraLines...) - } - raw = newRaw - maxWidth = newMaxWidth - } - - // Store the new known maximum width. - v, ok := t.cs[colKey] - if !ok || v < maxWidth || v == 0 { - t.cs[colKey] = maxWidth - } - - // Remember the number of lines for the row printer. - h := len(raw) - v, ok = t.rs[rowKey] - - if !ok || v < h || v == 0 { - t.rs[rowKey] = h - } - //fmt.Printf("Raw %+v %d\n", raw, len(raw)) - return raw -} diff --git a/vendor/github.com/olekukonko/tablewriter/table_with_color.go b/vendor/github.com/olekukonko/tablewriter/table_with_color.go deleted file mode 100644 index ae7a364a..00000000 --- a/vendor/github.com/olekukonko/tablewriter/table_with_color.go +++ /dev/null @@ -1,136 +0,0 @@ -package tablewriter - -import ( - "fmt" - "strconv" - "strings" -) - -const ESC = "\033" -const SEP = ";" - -const ( - BgBlackColor int = iota + 40 - BgRedColor - BgGreenColor - BgYellowColor - BgBlueColor - BgMagentaColor - BgCyanColor - BgWhiteColor -) - -const ( - FgBlackColor int = iota + 30 - FgRedColor - FgGreenColor - FgYellowColor - FgBlueColor - FgMagentaColor - FgCyanColor - FgWhiteColor -) - -const ( - BgHiBlackColor int = iota + 100 - BgHiRedColor - BgHiGreenColor - BgHiYellowColor - BgHiBlueColor - BgHiMagentaColor - BgHiCyanColor - BgHiWhiteColor -) - -const ( - FgHiBlackColor int = iota + 90 - FgHiRedColor - FgHiGreenColor - FgHiYellowColor - FgHiBlueColor - FgHiMagentaColor - FgHiCyanColor - FgHiWhiteColor -) - -const ( - Normal = 0 - Bold = 1 - UnderlineSingle = 4 - Italic -) - -type Colors []int - -func startFormat(seq string) string { - return fmt.Sprintf("%s[%sm", ESC, seq) -} - -func stopFormat() string { - return fmt.Sprintf("%s[%dm", ESC, Normal) -} - -// Making the SGR (Select Graphic Rendition) sequence. -func makeSequence(codes []int) string { - codesInString := []string{} - for _, code := range codes { - codesInString = append(codesInString, strconv.Itoa(code)) - } - return strings.Join(codesInString, SEP) -} - -// Adding ANSI escape sequences before and after string -func format(s string, codes interface{}) string { - var seq string - - switch v := codes.(type) { - - case string: - seq = v - case []int: - seq = makeSequence(v) - case Colors: - seq = makeSequence(v) - default: - return s - } - - if len(seq) == 0 { - return s - } - return startFormat(seq) + s + stopFormat() -} - -// Adding header colors (ANSI codes) -func (t *Table) SetHeaderColor(colors ...Colors) { - if t.colSize != len(colors) { - panic("Number of header colors must be equal to number of headers.") - } - for i := 0; i < len(colors); i++ { - t.headerParams = append(t.headerParams, makeSequence(colors[i])) - } -} - -// Adding column colors (ANSI codes) -func (t *Table) SetColumnColor(colors ...Colors) { - if t.colSize != len(colors) { - panic("Number of column colors must be equal to number of headers.") - } - for i := 0; i < len(colors); i++ { - t.columnsParams = append(t.columnsParams, makeSequence(colors[i])) - } -} - -// Adding column colors (ANSI codes) -func (t *Table) SetFooterColor(colors ...Colors) { - if len(t.footers) != len(colors) { - panic("Number of footer colors must be equal to number of footer.") - } - for i := 0; i < len(colors); i++ { - t.footerParams = append(t.footerParams, makeSequence(colors[i])) - } -} - -func Color(colors ...int) []int { - return colors -} diff --git a/vendor/github.com/olekukonko/tablewriter/tablewriter.go b/vendor/github.com/olekukonko/tablewriter/tablewriter.go new file mode 100644 index 00000000..4aed1a64 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tablewriter.go @@ -0,0 +1,2213 @@ +package tablewriter + +import ( + "bytes" + "fmt" + "github.com/olekukonko/errors" + "github.com/olekukonko/ll" + "github.com/olekukonko/ll/lh" + "github.com/olekukonko/tablewriter/pkg/twwarp" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "github.com/olekukonko/tablewriter/renderer" + "github.com/olekukonko/tablewriter/tw" + "io" + "math" + "os" + "reflect" + "runtime" + "strings" + "sync" +) + +// Table represents a table instance with content and rendering capabilities. +type Table struct { + writer io.Writer // Destination for table output + rows [][][]string // Row data, supporting multi-line cells + headers [][]string // Header content + footers [][]string // Footer content + headerWidths tw.Mapper[int, int] // Computed widths for header columns + rowWidths tw.Mapper[int, int] // Computed widths for row columns + footerWidths tw.Mapper[int, int] // Computed widths for footer columns + renderer tw.Renderer // Engine for rendering the table + config Config // Table configuration settings + stringer any // Function to convert rows to strings + newLine string // Newline character (e.g., "\n") + hasPrinted bool // Indicates if the table has been rendered + logger *ll.Logger // Debug trace log + trace *bytes.Buffer // Debug trace log + + // Caption fields + caption tw.Caption + + // streaming + streamWidths tw.Mapper[int, int] // Fixed column widths for streaming mode, calculated once + streamFooterLines [][]string // Processed footer lines for streaming, stored until Close(). + headerRendered bool // Tracks if header has been rendered in streaming mode + firstRowRendered bool // Tracks if the first data row has been rendered in streaming mode + lastRenderedLineContent []string // Content of the very last line rendered (for Previous context in streaming) + lastRenderedMergeState tw.Mapper[int, tw.MergeState] // Merge state of the very last line rendered (for Previous context in streaming) + lastRenderedPosition tw.Position // Position (Header/Row/Footer/Separator) of the last line rendered (for Previous context in streaming) + streamNumCols int // The derived number of columns in streaming mode + streamRowCounter int // Counter for rows rendered in streaming mode (0-indexed logical rows) + + // cache + stringerCache map[reflect.Type]reflect.Value // Cache for stringer reflection + stringerCacheMu sync.RWMutex // Mutex for thread-safe cache access + stringerCacheEnabled bool // Flag to enable/disable caching + + batchRenderNumCols int + isBatchRenderNumColsSet bool +} + +// renderContext holds the core state for rendering the table. +type renderContext struct { + table *Table // Reference to the table instance + renderer tw.Renderer // Renderer instance + cfg tw.Rendition // Renderer configuration + numCols int // Total number of columns + headerLines [][]string // Processed header lines + rowLines [][][]string // Processed row lines + footerLines [][]string // Processed footer lines + widths tw.Mapper[tw.Position, tw.Mapper[int, int]] // Widths per section + footerPrepared bool // Tracks if footer is prepared + emptyColumns []bool // Tracks which original columns are empty (true if empty) + visibleColCount int // Count of columns that are NOT empty + logger *ll.Logger // Debug trace log +} + +// mergeContext holds state related to cell merging. +type mergeContext struct { + headerMerges map[int]tw.MergeState // Merge states for header columns + rowMerges []map[int]tw.MergeState // Merge states for each row + footerMerges map[int]tw.MergeState // Merge states for footer columns + horzMerges map[tw.Position]map[int]bool // Tracks horizontal merges (unused) +} + +// helperContext holds additional data for rendering helpers. +type helperContext struct { + position tw.Position // Section being processed (Header, Row, Footer) + rowIdx int // Row index within section + lineIdx int // Line index within row + location tw.Location // Boundary location (First, Middle, End) + line []string // Current line content +} + +// renderMergeResponse holds cell context data from rendering operations. +type renderMergeResponse struct { + cells map[int]tw.CellContext // Current line cells + prevCells map[int]tw.CellContext // Previous line cells + nextCells map[int]tw.CellContext // Next line cells + location tw.Location // Determined Location for this line + cellsContent []string +} + +// NewTable creates a new table instance with specified writer and options. +// Parameters include writer for output and optional configuration options. +// Returns a pointer to the initialized Table instance. +func NewTable(w io.Writer, opts ...Option) *Table { + t := &Table{ + writer: w, + headerWidths: tw.NewMapper[int, int](), + rowWidths: tw.NewMapper[int, int](), + footerWidths: tw.NewMapper[int, int](), + renderer: renderer.NewBlueprint(), + config: defaultConfig(), + newLine: tw.NewLine, + trace: &bytes.Buffer{}, + + // Streaming + streamWidths: tw.NewMapper[int, int](), // Initialize empty mapper for streaming widths + lastRenderedMergeState: tw.NewMapper[int, tw.MergeState](), + headerRendered: false, + firstRowRendered: false, + lastRenderedPosition: "", + streamNumCols: 0, + streamRowCounter: 0, + + // Cache + stringerCache: make(map[reflect.Type]reflect.Value), + stringerCacheEnabled: false, // Disabled by default + } + + // set Options + t.Options(opts...) + + t.logger.Infof("Table initialized with %d options", len(opts)) + return t +} + +// NewWriter creates a new table with default settings for backward compatibility. +// It logs the creation if debugging is enabled. +func NewWriter(w io.Writer) *Table { + t := NewTable(w) + if t.logger != nil { + t.logger.Debug("NewWriter created buffered Table") + } + return t +} + +// Caption sets the table caption (legacy method). +// Defaults to BottomCenter alignment, wrapping to table width. +// Use SetCaptionOptions for more control. +func (t *Table) Caption(caption tw.Caption) *Table { // This is the one we modified + originalSpot := caption.Spot + originalAlign := caption.Align + + if caption.Spot == tw.SpotNone { + caption.Spot = tw.SpotBottomCenter + t.logger.Debugf("[Table.Caption] Input Spot was SpotNone, defaulting Spot to SpotBottomCenter (%d)", caption.Spot) + } + + if caption.Align == "" || caption.Align == tw.AlignDefault || caption.Align == tw.AlignNone { + switch caption.Spot { + case tw.SpotTopLeft, tw.SpotBottomLeft: + caption.Align = tw.AlignLeft + case tw.SpotTopRight, tw.SpotBottomRight: + caption.Align = tw.AlignRight + default: + caption.Align = tw.AlignCenter + } + t.logger.Debugf("[Table.Caption] Input Align was empty/default, defaulting Align to %s for Spot %d", caption.Align, caption.Spot) + } + + t.caption = caption // t.caption on the struct is now updated. + t.logger.Debugf("Caption method called: Input(Spot:%v, Align:%q), Final(Spot:%v, Align:%q), Text:'%.20s', MaxWidth:%d", + originalSpot, originalAlign, t.caption.Spot, t.caption.Align, t.caption.Text, t.caption.Width) + return t +} + +// Append adds data to the current row being built for the table. +// This method always contributes to a single logical row in the table. +// To add multiple distinct rows, call Append multiple times (once for each row's data) +// or use the Bulk() method if providing a slice where each element is a row. +func (t *Table) Append(rows ...interface{}) error { // rows is already []interface{} + t.ensureInitialized() + + if t.config.Stream.Enable && t.hasPrinted { + t.logger.Debugf("Append() called in streaming mode with %d items for a single row", len(rows)) + var rowItemForStream interface{} + if len(rows) == 1 { + rowItemForStream = rows[0] + } else { + rowItemForStream = rows // Pass the slice of items if multiple args + } + if err := t.streamAppendRow(rowItemForStream); err != nil { + t.logger.Errorf("Error rendering streaming row: %v", err) + return fmt.Errorf("failed to stream append row: %w", err) + } + return nil + } + + //Batch Mode Logic + t.logger.Debugf("Append (Batch) received %d arguments: %v", len(rows), rows) + + var cellsSource interface{} + if len(rows) == 1 { + cellsSource = rows[0] + t.logger.Debug("Append (Batch): Single argument provided. Treating it as the source for row cells.") + } else { + cellsSource = rows // 'rows' is []interface{} containing all arguments + t.logger.Debug("Append (Batch): Multiple arguments provided. Treating them directly as cells for one row.") + } + + if err := t.appendSingle(cellsSource); err != nil { + t.logger.Errorf("Append (Batch) failed for cellsSource %v: %v", cellsSource, err) + return err + } + + t.logger.Debugf("Append (Batch) completed for one row, total rows in table: %d", len(t.rows)) + return nil +} + +// Bulk adds multiple rows from a slice to the table (legacy method). +// Parameter rows must be a slice compatible with stringer or []string. +// Returns an error if the input is invalid or appending fails. +func (t *Table) Bulk(rows interface{}) error { + t.logger.Debug("Starting Bulk operation") + rv := reflect.ValueOf(rows) + if rv.Kind() != reflect.Slice { + err := errors.Newf("Bulk expects a slice, got %T", rows) + t.logger.Debugf("Bulk error: %v", err) + return err + } + for i := 0; i < rv.Len(); i++ { + row := rv.Index(i).Interface() + t.logger.Debugf("Processing bulk row %d: %v", i, row) + if err := t.appendSingle(row); err != nil { + t.logger.Debugf("Bulk append failed at index %d: %v", i, err) + return err + } + } + t.logger.Debugf("Bulk completed, processed %d rows", rv.Len()) + return nil +} + +// Config returns the current table configuration. +// No parameters are required. +// Returns the Config struct with current settings. +func (t *Table) Config() Config { + return t.config +} + +// Configure updates the table's configuration using a provided function. +// Parameter fn is a function that modifies the Config struct. +// Returns the Table instance for method chaining. +func (t *Table) Configure(fn func(cfg *Config)) *Table { + fn(&t.config) // Let the user modify the config directly + // Handle any immediate side-effects of config changes, e.g., logger state + if t.config.Debug { + t.logger.Enable() + t.logger.Resume() // in case it was suspended + } else { + t.logger.Disable() + t.logger.Suspend() // suspend totally, especially because of tight loops + } + t.logger.Debugf("Configure complete. New t.config: %+v", t.config) + return t +} + +// Debug retrieves the accumulated debug trace logs. +// No parameters are required. +// Returns a slice of debug messages including renderer logs. +func (t *Table) Debug() *bytes.Buffer { + return t.trace +} + +// Header sets the table's header content, padding to match column count. +// Parameter elements is a slice of strings for header content. +// No return value. +// In streaming mode, this processes and renders the header immediately. +func (t *Table) Header(elements ...any) { + t.ensureInitialized() + t.logger.Debugf("Header() method called with raw variadic elements: %v (len %d). Streaming: %v, Started: %v", elements, len(elements), t.config.Stream.Enable, t.hasPrinted) + + // just forget + if t.config.Behavior.Header.Hide.Enabled() { + return + } + + // add come common default + if t.config.Header.Formatting.AutoFormat == tw.Unknown { + t.config.Header.Formatting.AutoFormat = tw.On + } + + if t.config.Stream.Enable && t.hasPrinted { + // Streaming Path + actualCellsToProcess := t.processVariadic(elements) + headersAsStrings, err := t.convertCellsToStrings(actualCellsToProcess, t.config.Header) + if err != nil { + t.logger.Errorf("Header(): Failed to convert header elements to strings for streaming: %v", err) + headersAsStrings = []string{} // Use empty on error + } + errStream := t.streamRenderHeader(headersAsStrings) // streamRenderHeader handles padding to streamNumCols internally + if errStream != nil { + t.logger.Errorf("Error rendering streaming header: %v", errStream) + } + return + } + + // Batch Path + processedElements := t.processVariadic(elements) + t.logger.Debugf("Header() (Batch): Effective cells to process: %v", processedElements) + + headersAsStrings, err := t.convertCellsToStrings(processedElements, t.config.Header) + if err != nil { + t.logger.Errorf("Header() (Batch): Failed to convert to strings: %v", err) + t.headers = [][]string{} // Set to empty on error + return + } + + // prepareContent uses t.config.Header for AutoFormat and MaxWidth constraints. + // It processes based on the number of columns in headersAsStrings. + preparedHeaderLines := t.prepareContent(headersAsStrings, t.config.Header) + t.headers = preparedHeaderLines // Store directly. Padding to t.maxColumns() will happen in prepareContexts. + + t.logger.Debugf("Header set (batch mode), lines stored: %d. First line if exists: %v", len(t.headers), func() []string { + if len(t.headers) > 0 { + return t.headers[0] + } else { + return nil + } + }()) +} + +// Footer sets the table's footer content, padding to match column count. +// Parameter footers is a slice of strings for footer content. +// No return value. +// Footer sets the table's footer content. +// Parameter footers is a slice of strings for footer content. +// In streaming mode, this processes and stores the footer for rendering by Close(). +func (t *Table) Footer(elements ...any) { + t.ensureInitialized() + t.logger.Debugf("Footer() method called with raw variadic elements: %v (len %d). Streaming: %v, Started: %v", elements, len(elements), t.config.Stream.Enable, t.hasPrinted) + + // just forget + if t.config.Behavior.Footer.Hide.Enabled() { + return + } + + if t.config.Stream.Enable && t.hasPrinted { + // Streaming Path + actualCellsToProcess := t.processVariadic(elements) + footersAsStrings, err := t.convertCellsToStrings(actualCellsToProcess, t.config.Footer) + if err != nil { + t.logger.Errorf("Footer(): Failed to convert footer elements to strings for streaming: %v", err) + footersAsStrings = []string{} // Use empty on error + } + errStream := t.streamStoreFooter(footersAsStrings) // streamStoreFooter handles padding to streamNumCols internally + if errStream != nil { + t.logger.Errorf("Error processing streaming footer: %v", errStream) + } + return + } + + // Batch Path + processedElements := t.processVariadic(elements) + t.logger.Debugf("Footer() (Batch): Effective cells to process: %v", processedElements) + + footersAsStrings, err := t.convertCellsToStrings(processedElements, t.config.Footer) + if err != nil { + t.logger.Errorf("Footer() (Batch): Failed to convert to strings: %v", err) + t.footers = [][]string{} // Set to empty on error + return + } + + preparedFooterLines := t.prepareContent(footersAsStrings, t.config.Footer) + t.footers = preparedFooterLines // Store directly. Padding to t.maxColumns() will happen in prepareContexts. + + t.logger.Debugf("Footer set (batch mode), lines stored: %d. First line if exists: %v", + len(t.footers), func() []string { + if len(t.footers) > 0 { + return t.footers[0] + } else { + return nil + } + }()) +} + +// Options updates the table's Options using a provided function. +// Parameter opts is a function that modifies the Table struct. +// Returns the Table instance for method chaining. +func (t *Table) Options(opts ...Option) *Table { + + // add logger + if t.logger == nil { + t.logger = ll.New("table").Handler(lh.NewTextHandler(t.trace)) + } + + // loop through options + for _, opt := range opts { + opt(t) + } + + // force debugging mode if set + // This should be move away form WithDebug + if t.config.Debug == true { + t.logger.Enable() + t.logger.Resume() + } else { + t.logger.Disable() + t.logger.Suspend() + } + + // Get additional system information for debugging + goVersion := runtime.Version() + goOS := runtime.GOOS + goArch := runtime.GOARCH + numCPU := runtime.NumCPU() + + t.logger.Infof("Environment: LC_CTYPE=%s, LANG=%s, TERM=%s", os.Getenv("LC_CTYPE"), os.Getenv("LANG"), os.Getenv("TERM")) + t.logger.Infof("Go Runtime: Version=%s, OS=%s, Arch=%s, CPUs=%d", goVersion, goOS, goArch, numCPU) + + // send logger to renderer + // this will overwrite the default logger + t.renderer.Logger(t.logger) + return t +} + +// Reset clears all data (headers, rows, footers, caption) and rendering state +// from the table, allowing the Table instance to be reused for a new table +// with the same configuration and writer. +// It does NOT reset the configuration itself (set by NewTable options or Configure) +// or the underlying io.Writer. +func (t *Table) Reset() { + t.logger.Debug("Reset() called. Clearing table data and render state.") + + // Clear data slices + t.rows = nil // Or t.rows = make([][][]string, 0) + t.headers = nil // Or t.headers = make([][]string, 0) + t.footers = nil // Or t.footers = make([][]string, 0) + + // Reset width mappers (important for recalculating widths for the new table) + t.headerWidths = tw.NewMapper[int, int]() + t.rowWidths = tw.NewMapper[int, int]() + t.footerWidths = tw.NewMapper[int, int]() + + // Reset caption + t.caption = tw.Caption{} // Reset to zero value + + // Reset rendering state flags + t.hasPrinted = false // Critical for allowing Render() or stream Start() again + + // Reset streaming-specific state + // (Important if the table was used in streaming mode and might be reused in batch or another stream) + t.streamWidths = tw.NewMapper[int, int]() + t.streamFooterLines = nil + t.headerRendered = false + t.firstRowRendered = false + t.lastRenderedLineContent = nil + t.lastRenderedMergeState = tw.NewMapper[int, tw.MergeState]() // Re-initialize + t.lastRenderedPosition = "" + t.streamNumCols = 0 + t.streamRowCounter = 0 + + // The stringer and its cache are part of the table's configuration, + if t.stringerCacheEnabled { + t.stringerCacheMu.Lock() + t.stringerCache = make(map[reflect.Type]reflect.Value) + t.stringerCacheMu.Unlock() + t.logger.Debug("Reset(): Stringer cache cleared.") + } + + // If the renderer has its own state that needs resetting after a table is done, + // this would be the place to call a renderer.Reset() method if it existed. + // Most current renderers are stateless per render call or reset in their Start/Close. + // For instance, HTML and SVG renderers have their own Reset method. + // It might be good practice to call it if available. + if r, ok := t.renderer.(interface{ Reset() }); ok { + t.logger.Debug("Reset(): Calling Reset() on the current renderer.") + r.Reset() + } + + t.logger.Info("Table instance has been reset.") +} + +// Render triggers the table rendering process to the configured writer. +// No parameters are required. +// Returns an error if rendering fails. +func (t *Table) Render() error { + return t.render() +} + +// Trimmer trims whitespace from a string based on the Table’s configuration. +// It conditionally applies strings.TrimSpace to the input string if the TrimSpace behavior +// is enabled in t.config.Behavior, otherwise returning the string unchanged. This method +// is used in the logging library to format strings for tabular output, ensuring consistent +// display in log messages. Thread-safe as it only reads configuration and operates on the +// input string. +func (t *Table) Trimmer(str string) string { + if t.config.Behavior.TrimSpace.Enabled() { + return strings.TrimSpace(str) + } + return str +} + +// appendSingle adds a single row to the table's row data. +// Parameter row is the data to append, converted via stringer if needed. +// Returns an error if conversion or appending fails. +func (t *Table) appendSingle(row interface{}) error { + t.ensureInitialized() // Already here + + if t.config.Stream.Enable && t.hasPrinted { // If streaming is active + t.logger.Debugf("appendSingle: Dispatching to streamAppendRow for row: %v", row) + return t.streamAppendRow(row) // Call the streaming render function + } + // Existing batch logic: + t.logger.Debugf("appendSingle: Processing for batch mode, row: %v", row) + // toStringLines now uses the new convertCellsToStrings internally, then prepareContent. + // This is fine for batch. + lines, err := t.toStringLines(row, t.config.Row) + if err != nil { + t.logger.Debugf("Error in toStringLines (batch mode): %v", err) + return err + } + t.rows = append(t.rows, lines) // Add to batch storage + t.logger.Debugf("Row appended to batch t.rows, total batch rows: %d", len(t.rows)) + return nil +} + +// buildAligns constructs a map of column alignments from configuration. +// Parameter config provides alignment settings for the section. +// Returns a map of column indices to alignment settings. +func (t *Table) buildAligns(config tw.CellConfig) map[int]tw.Align { + // Start with global alignment, preferring deprecated Formatting.Alignment + effectiveGlobalAlign := config.Formatting.Alignment + if effectiveGlobalAlign == tw.Empty || effectiveGlobalAlign == tw.Skip { + effectiveGlobalAlign = config.Alignment.Global + if config.Formatting.Alignment != tw.Empty && config.Formatting.Alignment != tw.Skip { + t.logger.Warnf("Using deprecated CellFormatting.Alignment (%s). Migrate to CellConfig.Alignment.Global.", config.Formatting.Alignment) + } + } + + // Use per-column alignments, preferring deprecated ColumnAligns + effectivePerColumn := config.ColumnAligns + if len(effectivePerColumn) == 0 && len(config.Alignment.PerColumn) > 0 { + effectivePerColumn = make([]tw.Align, len(config.Alignment.PerColumn)) + copy(effectivePerColumn, config.Alignment.PerColumn) + if len(config.ColumnAligns) > 0 { + t.logger.Warnf("Using deprecated CellConfig.ColumnAligns (%v). Migrate to CellConfig.Alignment.PerColumn.", config.ColumnAligns) + } + } + + // Log input for debugging + t.logger.Debugf("buildAligns INPUT: deprecated Formatting.Alignment=%s, deprecated ColumnAligns=%v, config.Alignment.Global=%s, config.Alignment.PerColumn=%v", + config.Formatting.Alignment, config.ColumnAligns, config.Alignment.Global, config.Alignment.PerColumn) + + numColsToUse := t.getNumColsToUse() + colAlignsResult := make(map[int]tw.Align) + for i := 0; i < numColsToUse; i++ { + currentAlign := effectiveGlobalAlign + if i < len(effectivePerColumn) && effectivePerColumn[i] != tw.Empty && effectivePerColumn[i] != tw.Skip { + currentAlign = effectivePerColumn[i] + } + // Skip validation here; rely on rendering to handle invalid alignments + colAlignsResult[i] = currentAlign + } + + t.logger.Debugf("Aligns built: %v (length %d)", colAlignsResult, len(colAlignsResult)) + return colAlignsResult +} + +// buildPadding constructs a map of column padding settings from configuration. +// Parameter padding provides padding settings for the section. +// Returns a map of column indices to padding settings. +func (t *Table) buildPadding(padding tw.CellPadding) map[int]tw.Padding { + numColsToUse := t.getNumColsToUse() + colPadding := make(map[int]tw.Padding) + for i := 0; i < numColsToUse; i++ { + if i < len(padding.PerColumn) && padding.PerColumn[i].Paddable() { + colPadding[i] = padding.PerColumn[i] + } else { + colPadding[i] = padding.Global + } + } + t.logger.Debugf("Padding built: %v (length %d)", colPadding, len(colPadding)) + return colPadding +} + +// ensureInitialized initializes required fields before use. +// No parameters are required. +// No return value. +func (t *Table) ensureInitialized() { + if t.headerWidths == nil { + t.headerWidths = tw.NewMapper[int, int]() + } + if t.rowWidths == nil { + t.rowWidths = tw.NewMapper[int, int]() + } + if t.footerWidths == nil { + t.footerWidths = tw.NewMapper[int, int]() + } + if t.renderer == nil { + t.renderer = renderer.NewBlueprint() + } + t.logger.Debug("ensureInitialized called") +} + +// finalizeHierarchicalMergeBlock sets Span and End for hierarchical merges. +// Parameters include ctx, mctx, col, startRow, and endRow. +// No return value. +func (t *Table) finalizeHierarchicalMergeBlock(ctx *renderContext, mctx *mergeContext, col, startRow, endRow int) { + if endRow < startRow { + ctx.logger.Debugf("Hierarchical merge FINALIZE WARNING: Invalid block col %d, start %d > end %d", col, startRow, endRow) + return + } + if startRow < 0 || endRow < 0 { + ctx.logger.Debugf("Hierarchical merge FINALIZE WARNING: Negative row indices col %d, start %d, end %d", col, startRow, endRow) + return + } + requiredLen := endRow + 1 + if requiredLen > len(mctx.rowMerges) { + ctx.logger.Debugf("Hierarchical merge FINALIZE WARNING: rowMerges slice too short (len %d) for endRow %d", len(mctx.rowMerges), endRow) + return + } + if mctx.rowMerges[startRow] == nil { + mctx.rowMerges[startRow] = make(map[int]tw.MergeState) + } + if mctx.rowMerges[endRow] == nil { + mctx.rowMerges[endRow] = make(map[int]tw.MergeState) + } + + finalSpan := (endRow - startRow) + 1 + ctx.logger.Debugf("Finalizing H-merge block: col=%d, startRow=%d, endRow=%d, span=%d", col, startRow, endRow, finalSpan) + + startState := mctx.rowMerges[startRow][col] + if startState.Hierarchical.Present && startState.Hierarchical.Start { + startState.Hierarchical.Span = finalSpan + startState.Hierarchical.End = finalSpan == 1 + mctx.rowMerges[startRow][col] = startState + ctx.logger.Debugf(" -> Updated start state: %+v", startState.Hierarchical) + } else { + ctx.logger.Debugf("Hierarchical merge FINALIZE WARNING: col %d, startRow %d was not marked as Present/Start? Current state: %+v. Attempting recovery.", col, startRow, startState.Hierarchical) + startState.Hierarchical.Present = true + startState.Hierarchical.Start = true + startState.Hierarchical.Span = finalSpan + startState.Hierarchical.End = finalSpan == 1 + mctx.rowMerges[startRow][col] = startState + } + + if endRow > startRow { + endState := mctx.rowMerges[endRow][col] + if endState.Hierarchical.Present && !endState.Hierarchical.Start { + endState.Hierarchical.End = true + endState.Hierarchical.Span = finalSpan + mctx.rowMerges[endRow][col] = endState + ctx.logger.Debugf(" -> Updated end state: %+v", endState.Hierarchical) + } else { + ctx.logger.Debugf("Hierarchical merge FINALIZE WARNING: col %d, endRow %d was not marked as Present/Continuation? Current state: %+v. Attempting recovery.", col, endRow, endState.Hierarchical) + endState.Hierarchical.Present = true + endState.Hierarchical.Start = false + endState.Hierarchical.End = true + endState.Hierarchical.Span = finalSpan + mctx.rowMerges[endRow][col] = endState + } + } else { + ctx.logger.Debugf(" -> Span is 1, startRow is also endRow.") + } +} + +// getLevel maps a position to its rendering level. +// Parameter position specifies the section (Header, Row, Footer). +// Returns the corresponding tw.Level (Header, Body, Footer). +func (t *Table) getLevel(position tw.Position) tw.Level { + switch position { + case tw.Header: + return tw.LevelHeader + case tw.Row: + return tw.LevelBody + case tw.Footer: + return tw.LevelFooter + default: + return tw.LevelBody + } +} + +// hasFooterElements checks if the footer has renderable elements. +// No parameters are required. +// Returns true if footer has content or padding, false otherwise. +func (t *Table) hasFooterElements() bool { + hasContent := len(t.footers) > 0 + hasTopPadding := t.config.Footer.Padding.Global.Top != tw.Empty + hasBottomPaddingConfig := t.config.Footer.Padding.Global.Bottom != tw.Empty || t.hasPerColumnBottomPadding() + return hasContent || hasTopPadding || hasBottomPaddingConfig +} + +// hasPerColumnBottomPadding checks for per-column bottom padding in footer. +// No parameters are required. +// Returns true if any per-column bottom padding is defined. +func (t *Table) hasPerColumnBottomPadding() bool { + if t.config.Footer.Padding.PerColumn == nil { + return false + } + for _, pad := range t.config.Footer.Padding.PerColumn { + if pad.Bottom != tw.Empty { + return true + } + } + return false +} + +// Logger retrieves the table's logger instance. +// No parameters are required. +// Returns the ll.Logger instance used for debug tracing. +func (t *Table) Logger() *ll.Logger { + return t.logger +} + +// Renderer retrieves the current renderer instance used by the table. +// No parameters are required. +// Returns the tw.Renderer interface instance. +func (t *Table) Renderer() tw.Renderer { + t.logger.Debug("Renderer requested") + return t.renderer +} + +// maxColumns calculates the maximum column count across sections. +// No parameters are required. +// Returns the highest number of columns found. +func (t *Table) maxColumns() int { + m := 0 + if len(t.headers) > 0 && len(t.headers[0]) > m { + m = len(t.headers[0]) + } + for _, row := range t.rows { + if len(row) > 0 && len(row[0]) > m { + m = len(row[0]) + } + } + if len(t.footers) > 0 && len(t.footers[0]) > m { + m = len(t.footers[0]) + } + t.logger.Debugf("Max columns: %d", m) + return m +} + +// printTopBottomCaption prints the table's caption at the specified top or bottom position. +// It wraps the caption text to fit the table width or a user-defined width, aligns it according +// to the specified alignment, and writes it to the provided writer. If the caption text is empty +// or the spot is invalid, it logs the issue and returns without printing. The function handles +// wrapping errors by falling back to splitting on newlines or using the original text. +func (t *Table) printTopBottomCaption(w io.Writer, actualTableWidth int) { + t.logger.Debugf("[printCaption Entry] Text=%q, Spot=%v (type %T), Align=%q, UserWidth=%d, ActualTableWidth=%d", + t.caption.Text, t.caption.Spot, t.caption.Spot, t.caption.Align, t.caption.Width, actualTableWidth) + + currentCaptionSpot := t.caption.Spot + isValidSpot := currentCaptionSpot >= tw.SpotTopLeft && currentCaptionSpot <= tw.SpotBottomRight + if t.caption.Text == "" || !isValidSpot { + t.logger.Debugf("[printCaption] Aborting: Text empty OR Spot invalid...") + return + } + + var captionWrapWidth int + if t.caption.Width > 0 { + captionWrapWidth = t.caption.Width + t.logger.Debugf("[printCaption] Using user-defined caption.Width %d for wrapping.", captionWrapWidth) + } else if actualTableWidth <= 4 { + captionWrapWidth = twwidth.Width(t.caption.Text) + t.logger.Debugf("[printCaption] Empty table, no user caption.Width: Using natural caption width %d.", captionWrapWidth) + } else { + captionWrapWidth = actualTableWidth + t.logger.Debugf("[printCaption] Non-empty table, no user caption.Width: Using actualTableWidth %d for wrapping.", actualTableWidth) + } + + if captionWrapWidth <= 0 { + captionWrapWidth = 10 + t.logger.Warnf("[printCaption] captionWrapWidth was %d (<=0). Setting to minimum %d.", captionWrapWidth, 10) + } + t.logger.Debugf("[printCaption] Final captionWrapWidth to be used by twwarp: %d", captionWrapWidth) + + wrappedCaptionLines, count := twwarp.WrapString(t.caption.Text, captionWrapWidth) + if count == 0 { + t.logger.Errorf("[printCaption] Error from twwarp.WrapString (width %d): %v. Text: %q", captionWrapWidth, count, t.caption.Text) + if strings.Contains(t.caption.Text, "\n") { + wrappedCaptionLines = strings.Split(t.caption.Text, "\n") + } else { + wrappedCaptionLines = []string{t.caption.Text} + } + t.logger.Debugf("[printCaption] Fallback: using %d lines from original text.", len(wrappedCaptionLines)) + } + + if len(wrappedCaptionLines) == 0 && t.caption.Text != "" { + t.logger.Warn("[printCaption] Wrapping resulted in zero lines for non-empty text. Using fallback.") + if strings.Contains(t.caption.Text, "\n") { + wrappedCaptionLines = strings.Split(t.caption.Text, "\n") + } else { + wrappedCaptionLines = []string{t.caption.Text} + } + } else if t.caption.Text != "" { + t.logger.Debugf("[printCaption] Wrapped caption into %d lines: %v", len(wrappedCaptionLines), wrappedCaptionLines) + } + + paddingTargetWidth := actualTableWidth + if t.caption.Width > 0 { + paddingTargetWidth = t.caption.Width + } else if actualTableWidth <= 4 { + paddingTargetWidth = captionWrapWidth + } + t.logger.Debugf("[printCaption] Final paddingTargetWidth for tw.Pad: %d", paddingTargetWidth) + + for i, line := range wrappedCaptionLines { + align := t.caption.Align + if align == "" || align == tw.AlignDefault || align == tw.AlignNone { + switch t.caption.Spot { + case tw.SpotTopLeft, tw.SpotBottomLeft: + align = tw.AlignLeft + case tw.SpotTopRight, tw.SpotBottomRight: + align = tw.AlignRight + default: + align = tw.AlignCenter + } + t.logger.Debugf("[printCaption] Line %d: Alignment defaulted to %s based on Spot %v", i, align, t.caption.Spot) + } + paddedLine := tw.Pad(line, " ", paddingTargetWidth, align) + t.logger.Debugf("[printCaption] Printing line %d: InputLine=%q, Align=%s, PaddingTargetWidth=%d, PaddedLine=%q", + i, line, align, paddingTargetWidth, paddedLine) + w.Write([]byte(paddedLine)) + w.Write([]byte(tw.NewLine)) + } + + t.logger.Debugf("[printCaption] Finished printing all caption lines.") +} + +// prepareContent processes cell content with formatting and wrapping. +// Parameters include cells to process and config for formatting rules. +// Returns a slice of string slices representing processed lines. +func (t *Table) prepareContent(cells []string, config tw.CellConfig) [][]string { + isStreaming := t.config.Stream.Enable && t.hasPrinted + t.logger.Debugf("prepareContent: Processing cells=%v (streaming: %v)", cells, isStreaming) + initialInputCellCount := len(cells) + result := make([][]string, 0) + + effectiveNumCols := initialInputCellCount + if isStreaming { + if t.streamNumCols > 0 { + effectiveNumCols = t.streamNumCols + t.logger.Debugf("prepareContent: Streaming mode, using fixed streamNumCols: %d", effectiveNumCols) + if len(cells) != effectiveNumCols { + t.logger.Warnf("prepareContent: Streaming mode, input cell count (%d) does not match streamNumCols (%d). Input cells will be padded/truncated.", len(cells), effectiveNumCols) + if len(cells) < effectiveNumCols { + paddedCells := make([]string, effectiveNumCols) + copy(paddedCells, cells) + for i := len(cells); i < effectiveNumCols; i++ { + paddedCells[i] = tw.Empty + } + cells = paddedCells + } else if len(cells) > effectiveNumCols { + cells = cells[:effectiveNumCols] + } + } + } else { + t.logger.Warnf("prepareContent: Streaming mode enabled but streamNumCols is 0. Using input cell count %d. Stream widths may not be available.", effectiveNumCols) + } + } + + if t.config.MaxWidth > 0 && !t.config.Widths.Constrained() { + if effectiveNumCols > 0 { + derivedSectionGlobalMaxWidth := int(math.Floor(float64(t.config.MaxWidth) / float64(effectiveNumCols))) + config.ColMaxWidths.Global = derivedSectionGlobalMaxWidth + t.logger.Debugf("prepareContent: Table MaxWidth %d active and t.config.Widths not constrained. "+ + "Derived section ColMaxWidths.Global: %d for %d columns. This will be used by calculateContentMaxWidth if no higher priority constraints exist.", + t.config.MaxWidth, config.ColMaxWidths.Global, effectiveNumCols) + } + } + + for i := 0; i < effectiveNumCols; i++ { + cellContent := "" + if i < len(cells) { + cellContent = cells[i] + } else { + cellContent = tw.Empty + } + + cellContent = t.Trimmer(cellContent) + + colPad := config.Padding.Global + if i < len(config.Padding.PerColumn) && config.Padding.PerColumn[i].Paddable() { + colPad = config.Padding.PerColumn[i] + } + + padLeftWidth := twwidth.Width(colPad.Left) + padRightWidth := twwidth.Width(colPad.Right) + + effectiveContentMaxWidth := t.calculateContentMaxWidth(i, config, padLeftWidth, padRightWidth, isStreaming) + + if config.Formatting.AutoFormat.Enabled() { + cellContent = tw.Title(strings.Join(tw.SplitCamelCase(cellContent), tw.Space)) + } + + lines := strings.Split(cellContent, "\n") + finalLinesForCell := make([]string, 0) + for _, line := range lines { + if effectiveContentMaxWidth > 0 { + switch config.Formatting.AutoWrap { + case tw.WrapNormal: + var wrapped []string + if t.config.Behavior.TrimSpace.Enabled() { + wrapped, _ = twwarp.WrapString(line, effectiveContentMaxWidth) + } else { + wrapped, _ = twwarp.WrapStringWithSpaces(line, effectiveContentMaxWidth) + } + finalLinesForCell = append(finalLinesForCell, wrapped...) + case tw.WrapTruncate: + if twwidth.Width(line) > effectiveContentMaxWidth { + ellipsisWidth := twwidth.Width(tw.CharEllipsis) + if effectiveContentMaxWidth >= ellipsisWidth { + finalLinesForCell = append(finalLinesForCell, twwidth.Truncate(line, effectiveContentMaxWidth-ellipsisWidth, tw.CharEllipsis)) + } else { + finalLinesForCell = append(finalLinesForCell, twwidth.Truncate(line, effectiveContentMaxWidth, "")) + } + } else { + finalLinesForCell = append(finalLinesForCell, line) + } + case tw.WrapBreak: + wrapped := make([]string, 0) + currentLine := line + breakCharWidth := twwidth.Width(tw.CharBreak) + for twwidth.Width(currentLine) > effectiveContentMaxWidth { + targetWidth := effectiveContentMaxWidth - breakCharWidth + if targetWidth < 0 { + targetWidth = 0 + } + breakPoint := tw.BreakPoint(currentLine, targetWidth) + runes := []rune(currentLine) + if breakPoint <= 0 || breakPoint > len(runes) { + t.logger.Warnf("prepareContent: WrapBreak - Invalid BreakPoint %d for line '%s' at width %d. Attempting manual break.", breakPoint, currentLine, targetWidth) + actualBreakRuneCount := 0 + tempWidth := 0 + for charIdx, r := range runes { + runeStr := string(r) + rw := twwidth.Width(runeStr) + if tempWidth+rw > targetWidth && charIdx > 0 { + break + } + tempWidth += rw + actualBreakRuneCount = charIdx + 1 + if tempWidth >= targetWidth && charIdx == 0 { + break + } + } + if actualBreakRuneCount == 0 && len(runes) > 0 { + actualBreakRuneCount = 1 + } + if actualBreakRuneCount > 0 && actualBreakRuneCount <= len(runes) { + wrapped = append(wrapped, string(runes[:actualBreakRuneCount])+tw.CharBreak) + currentLine = string(runes[actualBreakRuneCount:]) + } else { + t.logger.Warnf("prepareContent: WrapBreak - Cannot break line '%s'. Adding as is.", currentLine) + wrapped = append(wrapped, currentLine) + currentLine = "" + break + } + } else { + wrapped = append(wrapped, string(runes[:breakPoint])+tw.CharBreak) + currentLine = string(runes[breakPoint:]) + } + } + if twwidth.Width(currentLine) > 0 { + wrapped = append(wrapped, currentLine) + } + if len(wrapped) == 0 && twwidth.Width(line) > 0 && len(finalLinesForCell) == 0 { + finalLinesForCell = append(finalLinesForCell, line) + } else { + finalLinesForCell = append(finalLinesForCell, wrapped...) + } + default: + finalLinesForCell = append(finalLinesForCell, line) + } + } else { + finalLinesForCell = append(finalLinesForCell, line) + } + } + + for len(result) < len(finalLinesForCell) { + newRow := make([]string, effectiveNumCols) + for j := range newRow { + newRow[j] = tw.Empty + } + result = append(result, newRow) + } + + for j := 0; j < len(result); j++ { + cellLineContent := tw.Empty + if j < len(finalLinesForCell) { + cellLineContent = finalLinesForCell[j] + } + if i < len(result[j]) { + result[j][i] = cellLineContent + } else { + t.logger.Warnf("prepareContent: Column index %d out of bounds (%d) during result matrix population. EffectiveNumCols: %d. This indicates a logic error.", + i, len(result[j]), effectiveNumCols) + } + } + } + + t.logger.Debugf("prepareContent: Content prepared, result %d lines.", len(result)) + return result +} + +// prepareContexts initializes rendering and merge contexts. +// No parameters are required. +// Returns renderContext, mergeContext, and an error if initialization fails. +func (t *Table) prepareContexts() (*renderContext, *mergeContext, error) { + numOriginalCols := t.maxColumns() + t.logger.Debugf("prepareContexts: Original number of columns: %d", numOriginalCols) + + ctx := &renderContext{ + table: t, + renderer: t.renderer, + cfg: t.renderer.Config(), + numCols: numOriginalCols, + widths: map[tw.Position]tw.Mapper[int, int]{ + tw.Header: tw.NewMapper[int, int](), + tw.Row: tw.NewMapper[int, int](), + tw.Footer: tw.NewMapper[int, int](), + }, + logger: t.logger, + } + + isEmpty, visibleCount := t.getEmptyColumnInfo(numOriginalCols) + ctx.emptyColumns = isEmpty + ctx.visibleColCount = visibleCount + + mctx := &mergeContext{ + headerMerges: make(map[int]tw.MergeState), + rowMerges: make([]map[int]tw.MergeState, len(t.rows)), + footerMerges: make(map[int]tw.MergeState), + horzMerges: make(map[tw.Position]map[int]bool), + } + for i := range mctx.rowMerges { + mctx.rowMerges[i] = make(map[int]tw.MergeState) + } + + ctx.headerLines = t.headers + ctx.rowLines = t.rows + ctx.footerLines = t.footers + + if err := t.calculateAndNormalizeWidths(ctx); err != nil { + t.logger.Debugf("Error during initial width calculation: %v", err) + return nil, nil, err + } + t.logger.Debugf("Initial normalized widths (before hiding): H=%v, R=%v, F=%v", + ctx.widths[tw.Header], ctx.widths[tw.Row], ctx.widths[tw.Footer]) + + preparedHeaderLines, headerMerges, _ := t.prepareWithMerges(ctx.headerLines, t.config.Header, tw.Header) + ctx.headerLines = preparedHeaderLines + mctx.headerMerges = headerMerges + + processedRowLines := make([][][]string, len(ctx.rowLines)) + for i, row := range ctx.rowLines { + if mctx.rowMerges[i] == nil { + mctx.rowMerges[i] = make(map[int]tw.MergeState) + } + processedRowLines[i], mctx.rowMerges[i], _ = t.prepareWithMerges(row, t.config.Row, tw.Row) + } + ctx.rowLines = processedRowLines + + t.applyHorizontalMergeWidths(tw.Header, ctx, mctx.headerMerges) + + if t.config.Row.Formatting.MergeMode&tw.MergeVertical != 0 { + t.applyVerticalMerges(ctx, mctx) + } + if t.config.Row.Formatting.MergeMode&tw.MergeHierarchical != 0 { + t.applyHierarchicalMerges(ctx, mctx) + } + + t.prepareFooter(ctx, mctx) + t.logger.Debugf("Footer prepared. Widths before hiding: H=%v, R=%v, F=%v", + ctx.widths[tw.Header], ctx.widths[tw.Row], ctx.widths[tw.Footer]) + + if t.config.Behavior.AutoHide.Enabled() { + t.logger.Debugf("Applying AutoHide: Adjusting widths for empty columns.") + if ctx.emptyColumns == nil { + t.logger.Debugf("Warning: ctx.emptyColumns is nil during width adjustment.") + } else if len(ctx.emptyColumns) != ctx.numCols { + t.logger.Debugf("Warning: Length mismatch between emptyColumns (%d) and numCols (%d). Skipping adjustment.", len(ctx.emptyColumns), ctx.numCols) + } else { + for colIdx := 0; colIdx < ctx.numCols; colIdx++ { + if ctx.emptyColumns[colIdx] { + t.logger.Debugf("AutoHide: Hiding column %d by setting width to 0.", colIdx) + ctx.widths[tw.Header].Set(colIdx, 0) + ctx.widths[tw.Row].Set(colIdx, 0) + ctx.widths[tw.Footer].Set(colIdx, 0) + } + } + t.logger.Debugf("Widths after AutoHide adjustment: H=%v, R=%v, F=%v", + ctx.widths[tw.Header], ctx.widths[tw.Row], ctx.widths[tw.Footer]) + } + } else { + t.logger.Debugf("AutoHide is disabled, skipping width adjustment.") + } + t.logger.Debugf("prepareContexts completed all stages.") + return ctx, mctx, nil +} + +// prepareFooter processes footer content and applies merges. +// Parameters ctx and mctx hold rendering and merge state. +// No return value. +func (t *Table) prepareFooter(ctx *renderContext, mctx *mergeContext) { + if len(t.footers) == 0 { + ctx.logger.Debugf("Skipping footer preparation - no footer data") + if ctx.widths[tw.Footer] == nil { + ctx.widths[tw.Footer] = tw.NewMapper[int, int]() + } + numCols := ctx.numCols + for i := 0; i < numCols; i++ { + ctx.widths[tw.Footer].Set(i, ctx.widths[tw.Row].Get(i)) + } + t.logger.Debug("Initialized empty footer widths based on row widths: %v", ctx.widths[tw.Footer]) + ctx.footerPrepared = true + return + } + + t.logger.Debugf("Preparing footer with merge mode: %d", t.config.Footer.Formatting.MergeMode) + preparedLines, mergeStates, _ := t.prepareWithMerges(t.footers, t.config.Footer, tw.Footer) + t.footers = preparedLines + mctx.footerMerges = mergeStates + ctx.footerLines = t.footers + t.logger.Debugf("Base footer widths (normalized from rows/header): %v", ctx.widths[tw.Footer]) + t.applyHorizontalMergeWidths(tw.Footer, ctx, mctx.footerMerges) + ctx.footerPrepared = true + t.logger.Debugf("Footer preparation completed. Final footer widths: %v", ctx.widths[tw.Footer]) +} + +// prepareWithMerges processes content and detects horizontal merges. +// Parameters include content, config, and position (Header, Row, Footer). +// Returns processed lines, merge states, and horizontal merge map. +func (t *Table) prepareWithMerges(content [][]string, config tw.CellConfig, position tw.Position) ([][]string, map[int]tw.MergeState, map[int]bool) { + t.logger.Debugf("PrepareWithMerges START: position=%s, mergeMode=%d", position, config.Formatting.MergeMode) + if len(content) == 0 { + t.logger.Debugf("PrepareWithMerges END: No content.") + return content, nil, nil + } + + numCols := 0 + if len(content) > 0 && len(content[0]) > 0 { // Assumes content[0] exists and has items + numCols = len(content[0]) + } else { // Fallback if first line is empty or content is empty + for _, line := range content { // Find max columns from any line + if len(line) > numCols { + numCols = len(line) + } + } + if numCols == 0 { // If still 0, try table-wide max (batch mode context) + numCols = t.maxColumns() + } + } + + if numCols == 0 { + t.logger.Debugf("PrepareWithMerges END: numCols is zero.") + return content, nil, nil + } + + horzMergeMap := make(map[int]bool) // Tracks if a column is part of any horizontal merge for this logical row + mergeMap := make(map[int]tw.MergeState) // Final merge states for this logical row + + // Ensure all lines in 'content' are padded to numCols for consistent processing + // This result is what will be modified and returned. + result := make([][]string, len(content)) + for i := range content { + result[i] = padLine(content[i], numCols) + } + + if config.Formatting.MergeMode&tw.MergeHorizontal != 0 { + t.logger.Debugf("Checking for horizontal merges (logical cell comparison) for %d visual lines, %d columns", len(content), numCols) + + // Special handling for footer lead merge (often for "TOTAL" spanning empty cells) + // This logic only applies if it's a footer and typically to the first (often only) visual line. + if position == tw.Footer && len(content) > 0 { + lineIdx := 0 // Assume footer lead merge applies to the first visual line primarily + originalLine := padLine(content[lineIdx], numCols) // Use original content for decision + currentLineResult := result[lineIdx] // Modify the result line + + firstContentIdx := -1 + var firstContent string + for c := 0; c < numCols; c++ { + if c >= len(originalLine) { + break + } + trimmedVal := t.Trimmer(originalLine[c]) + + if trimmedVal != "" && trimmedVal != "-" { // "-" is often a placeholder not to merge over + firstContentIdx = c + firstContent = originalLine[c] // Store the raw content for placement + break + } else if trimmedVal == "-" { // Stop if we hit a hard non-mergeable placeholder + break + } + } + + if firstContentIdx > 0 { // If content starts after the first column + span := firstContentIdx + 1 // Merge from col 0 up to and including firstContentIdx + startCol := 0 + + allEmptyBefore := true + for c := 0; c < firstContentIdx; c++ { + originalLine[c] = t.Trimmer(originalLine[c]) + if c >= len(originalLine) || originalLine[c] != "" { + allEmptyBefore = false + break + } + } + + if allEmptyBefore { + t.logger.Debugf("Footer lead-merge applied line %d: content '%s' from col %d moved to col %d, span %d", + lineIdx, firstContent, firstContentIdx, startCol, span) + + if startCol < len(currentLineResult) { + currentLineResult[startCol] = firstContent // Place the original content + } + for k := startCol + 1; k < startCol+span; k++ { // Clear out other cells in the span + if k < len(currentLineResult) { + currentLineResult[k] = tw.Empty + } + } + + // Update mergeMap for all visual lines of this logical row + for visualLine := 0; visualLine < len(result); visualLine++ { + // Only apply the data move to the line where it was detected, + // but the merge state should apply to the logical cell (all its visual lines). + if visualLine != lineIdx { // For other visual lines, just clear the cells in the span + if startCol < len(result[visualLine]) { + result[visualLine][startCol] = tw.Empty // Typically empty for other lines in a lead merge + } + for k := startCol + 1; k < startCol+span; k++ { + if k < len(result[visualLine]) { + result[visualLine][k] = tw.Empty + } + } + } + } + + // Set merge state for the starting column + startState := mergeMap[startCol] + startState.Horizontal = tw.MergeStateOption{Present: true, Span: span, Start: true, End: (span == 1)} + mergeMap[startCol] = startState + horzMergeMap[startCol] = true // Mark this column as processed by a merge + + // Set merge state for subsequent columns in the span + for k := startCol + 1; k < startCol+span; k++ { + colState := mergeMap[k] + colState.Horizontal = tw.MergeStateOption{Present: true, Span: span, Start: false, End: k == startCol+span-1} + mergeMap[k] = colState + horzMergeMap[k] = true // Mark as processed + } + } + } + } + + // Standard horizontal merge logic based on full logical cell content + col := 0 + for col < numCols { + if horzMergeMap[col] { // If already part of a footer lead-merge, skip + col++ + continue + } + + // Get full content of logical cell 'col' + var currentLogicalCellContentBuilder strings.Builder + for lineIdx := 0; lineIdx < len(content); lineIdx++ { + if col < len(content[lineIdx]) { + currentLogicalCellContentBuilder.WriteString(content[lineIdx][col]) + } + } + + currentLogicalCellTrimmed := t.Trimmer(currentLogicalCellContentBuilder.String()) + if currentLogicalCellTrimmed == "" || currentLogicalCellTrimmed == "-" { + col++ + continue + } + + span := 1 + for nextCol := col + 1; nextCol < numCols; nextCol++ { + if horzMergeMap[nextCol] { // Don't merge into an already merged (e.g. footer lead) column + break + } + var nextLogicalCellContentBuilder strings.Builder + for lineIdx := 0; lineIdx < len(content); lineIdx++ { + if nextCol < len(content[lineIdx]) { + nextLogicalCellContentBuilder.WriteString(content[lineIdx][nextCol]) + } + } + + nextLogicalCellTrimmed := t.Trimmer(nextLogicalCellContentBuilder.String()) + if currentLogicalCellTrimmed == nextLogicalCellTrimmed && nextLogicalCellTrimmed != "-" { + span++ + } else { + break + } + } + + if span > 1 { + t.logger.Debugf("Standard horizontal merge (logical cell): startCol %d, span %d for content '%s'", col, span, currentLogicalCellTrimmed) + startState := mergeMap[col] + startState.Horizontal = tw.MergeStateOption{Present: true, Span: span, Start: true, End: (span == 1)} + mergeMap[col] = startState + horzMergeMap[col] = true + + // For all visual lines, clear out the content of the merged-over cells + for lineIdx := 0; lineIdx < len(result); lineIdx++ { + for k := col + 1; k < col+span; k++ { + if k < len(result[lineIdx]) { + result[lineIdx][k] = tw.Empty + } + } + } + + // Set merge state for subsequent columns in the span + for k := col + 1; k < col+span; k++ { + colState := mergeMap[k] + colState.Horizontal = tw.MergeStateOption{Present: true, Span: span, Start: false, End: k == col+span-1} + mergeMap[k] = colState + horzMergeMap[k] = true + } + col += span + } else { + col++ + } + } + } + + t.logger.Debugf("PrepareWithMerges END: position=%s, lines=%d, mergeMapH: %v", position, len(result), func() map[int]tw.MergeStateOption { + m := make(map[int]tw.MergeStateOption) + for k, v := range mergeMap { + m[k] = v.Horizontal + } + return m + }()) + return result, mergeMap, horzMergeMap +} + +// render generates the table output using the configured renderer. +// No parameters are required. +// Returns an error if rendering fails in any section. +func (t *Table) render() error { + + t.ensureInitialized() + + if t.config.Stream.Enable { + t.logger.Warn("Render() called in streaming mode. Use Start/Append/Close methods instead.") + return errors.New("render called in streaming mode; use Start/Append/Close") + } + + // Calculate and cache numCols for THIS batch render pass + t.batchRenderNumCols = t.maxColumns() // Calculate ONCE + t.isBatchRenderNumColsSet = true // Mark the cache as active for this render pass + t.logger.Debugf("Render(): Set batchRenderNumCols to %d and isBatchRenderNumColsSet to true.", t.batchRenderNumCols) + + defer func() { + t.isBatchRenderNumColsSet = false + // t.batchRenderNumCols = 0; // Optional: reset to 0, or leave as is. + // Since isBatchRenderNumColsSet is false, its value won't be used by getNumColsToUse. + t.logger.Debugf("Render(): Cleared isBatchRenderNumColsSet to false (batchRenderNumCols was %d).", t.batchRenderNumCols) + }() + + hasCaption := t.caption.Text != "" && t.caption.Spot != tw.SpotNone + isTopOrBottomCaption := hasCaption && + (t.caption.Spot >= tw.SpotTopLeft && t.caption.Spot <= tw.SpotBottomRight) + + var tableStringBuffer *strings.Builder + targetWriter := t.writer + originalWriter := t.writer // Save original writer for restoration if needed + + if isTopOrBottomCaption { + tableStringBuffer = &strings.Builder{} + targetWriter = tableStringBuffer + t.logger.Debugf("Top/Bottom caption detected. Rendering table core to buffer first.") + } else { + t.logger.Debugf("No caption detected. Rendering table core directly to writer.") + } + + //Render Table Core + t.writer = targetWriter + ctx, mctx, err := t.prepareContexts() + if err != nil { + t.writer = originalWriter + t.logger.Errorf("prepareContexts failed: %v", err) + return fmt.Errorf("failed to prepare table contexts: %w", err) + } + + if err := ctx.renderer.Start(t.writer); err != nil { + t.writer = originalWriter + t.logger.Errorf("Renderer Start() error: %v", err) + return fmt.Errorf("renderer start failed: %w", err) + } + + renderError := false + var firstRenderErr error + renderFuncs := []func(*renderContext, *mergeContext) error{ + t.renderHeader, + t.renderRow, + t.renderFooter, + } + for i, renderFn := range renderFuncs { + sectionName := []string{"Header", "Row", "Footer"}[i] + if renderErr := renderFn(ctx, mctx); renderErr != nil { + t.logger.Errorf("Renderer section error (%s): %v", sectionName, renderErr) + if !renderError { + firstRenderErr = fmt.Errorf("failed to render %s section: %w", sectionName, renderErr) + } + renderError = true + break + } + } + + if closeErr := ctx.renderer.Close(); closeErr != nil { + t.logger.Errorf("Renderer Close() error: %v", closeErr) + if !renderError { + firstRenderErr = fmt.Errorf("renderer close failed: %w", closeErr) + } + renderError = true + } + + t.writer = originalWriter // Restore original writer + + if renderError { + return firstRenderErr // Return error from core rendering if any + } + + //Caption Handling & Final Output --- + if isTopOrBottomCaption { + renderedTableContent := tableStringBuffer.String() + t.logger.Debugf("[Render] Table core buffer length: %d", len(renderedTableContent)) + + // Check if the buffer is empty AND borders are enabled + shouldHaveBorders := t.renderer != nil && (t.renderer.Config().Borders.Top.Enabled() || t.renderer.Config().Borders.Bottom.Enabled()) + if len(renderedTableContent) == 0 && shouldHaveBorders { + var sb strings.Builder + if t.renderer.Config().Borders.Top.Enabled() { + sb.WriteString("+--+") + sb.WriteString(t.newLine) + } + if t.renderer.Config().Borders.Bottom.Enabled() { + sb.WriteString("+--+") + } + renderedTableContent = sb.String() + t.logger.Warnf("[Render] Table buffer was empty despite enabled borders. Manually generated minimal output: %q", renderedTableContent) + } + + actualTableWidth := 0 + trimmedBuffer := strings.TrimRight(renderedTableContent, "\r\n \t") + for _, line := range strings.Split(trimmedBuffer, "\n") { + w := twwidth.Width(line) + if w > actualTableWidth { + actualTableWidth = w + } + } + t.logger.Debugf("[Render] Calculated actual table width: %d (from content: %q)", actualTableWidth, renderedTableContent) + + isTopCaption := t.caption.Spot >= tw.SpotTopLeft && t.caption.Spot <= tw.SpotTopRight + + if isTopCaption { + t.logger.Debugf("[Render] Printing Top Caption.") + t.printTopBottomCaption(t.writer, actualTableWidth) + } + + if len(renderedTableContent) > 0 { + t.logger.Debugf("[Render] Printing table content (length %d) to final writer.", len(renderedTableContent)) + t.writer.Write([]byte(renderedTableContent)) + if !isTopCaption && t.caption.Text != "" && !strings.HasSuffix(renderedTableContent, t.newLine) { + t.writer.Write([]byte(tw.NewLine)) + t.logger.Debugf("[Render] Added trailing newline after table content before bottom caption.") + } + } else { + t.logger.Debugf("[Render] No table content (original buffer or generated) to print.") + } + + if !isTopCaption { + t.logger.Debugf("[Render] Calling printTopBottomCaption for Bottom Caption. Width: %d", actualTableWidth) + t.printTopBottomCaption(t.writer, actualTableWidth) + t.logger.Debugf("[Render] Returned from printTopBottomCaption for Bottom Caption.") + } + } + + t.hasPrinted = true + t.logger.Info("Render() completed.") + return nil // Success +} + +// renderFooter renders the table's footer section with borders and padding. +// Parameters ctx and mctx hold rendering and merge state. +// Returns an error if rendering fails. +func (t *Table) renderFooter(ctx *renderContext, mctx *mergeContext) error { + if !ctx.footerPrepared { + t.prepareFooter(ctx, mctx) + } + + f := ctx.renderer + cfg := ctx.cfg + + hasContent := len(ctx.footerLines) > 0 + hasTopPadding := t.config.Footer.Padding.Global.Top != tw.Empty + hasBottomPaddingConfig := t.config.Footer.Padding.Global.Bottom != tw.Empty || t.hasPerColumnBottomPadding() + hasAnyFooterElement := hasContent || hasTopPadding || hasBottomPaddingConfig + + if !hasAnyFooterElement { + hasContentAbove := len(ctx.rowLines) > 0 || len(ctx.headerLines) > 0 + if hasContentAbove && cfg.Borders.Bottom.Enabled() && cfg.Settings.Lines.ShowBottom.Enabled() { + ctx.logger.Debugf("Footer is empty, rendering table bottom border based on last row/header") + var lastLineAboveCtx *helperContext + var lastLineAligns map[int]tw.Align + var lastLinePadding map[int]tw.Padding + + if len(ctx.rowLines) > 0 { + lastRowIdx := len(ctx.rowLines) - 1 + lastRowLineIdx := -1 + var lastRowLine []string + if lastRowIdx >= 0 && len(ctx.rowLines[lastRowIdx]) > 0 { + lastRowLineIdx = len(ctx.rowLines[lastRowIdx]) - 1 + lastRowLine = padLine(ctx.rowLines[lastRowIdx][lastRowLineIdx], ctx.numCols) + } else { + lastRowLine = make([]string, ctx.numCols) + } + lastLineAboveCtx = &helperContext{ + position: tw.Row, + rowIdx: lastRowIdx, + lineIdx: lastRowLineIdx, + line: lastRowLine, + location: tw.LocationEnd, + } + lastLineAligns = t.buildAligns(t.config.Row) + lastLinePadding = t.buildPadding(t.config.Row.Padding) + } else { + lastHeaderLineIdx := -1 + var lastHeaderLine []string + if len(ctx.headerLines) > 0 { + lastHeaderLineIdx = len(ctx.headerLines) - 1 + lastHeaderLine = padLine(ctx.headerLines[lastHeaderLineIdx], ctx.numCols) + } else { + lastHeaderLine = make([]string, ctx.numCols) + } + lastLineAboveCtx = &helperContext{ + position: tw.Header, + rowIdx: 0, + lineIdx: lastHeaderLineIdx, + line: lastHeaderLine, + location: tw.LocationEnd, + } + lastLineAligns = t.buildAligns(t.config.Header) + lastLinePadding = t.buildPadding(t.config.Header.Padding) + } + + resp := t.buildCellContexts(ctx, mctx, lastLineAboveCtx, lastLineAligns, lastLinePadding) + ctx.logger.Debugf("Bottom border: Using Widths=%v", ctx.widths[tw.Row]) + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Row], + Current: resp.cells, + Previous: resp.prevCells, + Position: lastLineAboveCtx.position, + Location: tw.LocationEnd, + ColMaxWidths: t.getColMaxWidths(tw.Footer), + }, + Level: tw.LevelFooter, + IsSubRow: false, + }) + } else { + ctx.logger.Debugf("Footer is empty and no content above or borders disabled, skipping footer render") + } + return nil + } + + ctx.logger.Debugf("Rendering footer section (has elements)") + hasContentAbove := len(ctx.rowLines) > 0 || len(ctx.headerLines) > 0 + colAligns := t.buildAligns(t.config.Footer) + colPadding := t.buildPadding(t.config.Footer.Padding) + hctx := &helperContext{position: tw.Footer} + // Declare paddingLineContentForContext with a default value + paddingLineContentForContext := make([]string, ctx.numCols) + + if hasContentAbove && cfg.Settings.Lines.ShowFooterLine.Enabled() && !hasTopPadding && len(ctx.footerLines) > 0 { + ctx.logger.Debugf("Rendering footer separator line") + var lastLineAboveCtx *helperContext + var lastLineAligns map[int]tw.Align + var lastLinePadding map[int]tw.Padding + var lastLinePosition tw.Position + + if len(ctx.rowLines) > 0 { + lastRowIdx := len(ctx.rowLines) - 1 + lastRowLineIdx := -1 + var lastRowLine []string + if lastRowIdx >= 0 && len(ctx.rowLines[lastRowIdx]) > 0 { + lastRowLineIdx = len(ctx.rowLines[lastRowIdx]) - 1 + lastRowLine = padLine(ctx.rowLines[lastRowIdx][lastRowLineIdx], ctx.numCols) + } else { + lastRowLine = make([]string, ctx.numCols) + } + lastLineAboveCtx = &helperContext{ + position: tw.Row, + rowIdx: lastRowIdx, + lineIdx: lastRowLineIdx, + line: lastRowLine, + location: tw.LocationMiddle, + } + lastLineAligns = t.buildAligns(t.config.Row) + lastLinePadding = t.buildPadding(t.config.Row.Padding) + lastLinePosition = tw.Row + } else { + lastHeaderLineIdx := -1 + var lastHeaderLine []string + if len(ctx.headerLines) > 0 { + lastHeaderLineIdx = len(ctx.headerLines) - 1 + lastHeaderLine = padLine(ctx.headerLines[lastHeaderLineIdx], ctx.numCols) + } else { + lastHeaderLine = make([]string, ctx.numCols) + } + lastLineAboveCtx = &helperContext{ + position: tw.Header, + rowIdx: 0, + lineIdx: lastHeaderLineIdx, + line: lastHeaderLine, + location: tw.LocationMiddle, + } + lastLineAligns = t.buildAligns(t.config.Header) + lastLinePadding = t.buildPadding(t.config.Header.Padding) + lastLinePosition = tw.Header + } + + resp := t.buildCellContexts(ctx, mctx, lastLineAboveCtx, lastLineAligns, lastLinePadding) + var nextCells map[int]tw.CellContext + if hasContent { + nextCells = make(map[int]tw.CellContext) + for j, cellData := range padLine(ctx.footerLines[0], ctx.numCols) { + mergeState := tw.MergeState{} + if mctx.footerMerges != nil { + mergeState = mctx.footerMerges[j] + } + nextCells[j] = tw.CellContext{Data: cellData, Merge: mergeState, Width: ctx.widths[tw.Footer].Get(j)} + } + } + ctx.logger.Debugf("Footer separator: Using Widths=%v", ctx.widths[tw.Row]) + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Row], + Current: resp.cells, + Previous: resp.prevCells, + Next: nextCells, + Position: lastLinePosition, + Location: tw.LocationMiddle, + ColMaxWidths: t.getColMaxWidths(tw.Footer), + }, + Level: tw.LevelFooter, + IsSubRow: false, + HasFooter: true, + }) + } + + if hasTopPadding { + hctx.rowIdx = 0 + hctx.lineIdx = -1 + if !(hasContentAbove && cfg.Settings.Lines.ShowFooterLine.Enabled()) { + hctx.location = tw.LocationFirst + } else { + hctx.location = tw.LocationMiddle + } + hctx.line = t.buildPaddingLineContents(t.config.Footer.Padding.Global.Top, ctx.widths[tw.Footer], ctx.numCols, mctx.footerMerges) + ctx.logger.Debugf("Calling renderPadding for Footer Top Padding line: %v (loc: %v)", hctx.line, hctx.location) + if err := t.renderPadding(ctx, mctx, hctx, t.config.Footer.Padding.Global.Top); err != nil { + return err + } + } + + lastRenderedLineIdx := -2 + if hasTopPadding { + lastRenderedLineIdx = -1 + } + for i, line := range ctx.footerLines { + hctx.rowIdx = 0 + hctx.lineIdx = i + hctx.line = padLine(line, ctx.numCols) + isFirstContentLine := i == 0 + isLastContentLine := i == len(ctx.footerLines)-1 + if isFirstContentLine && !hasTopPadding && !(hasContentAbove && cfg.Settings.Lines.ShowFooterLine.Enabled()) { + hctx.location = tw.LocationFirst + } else if isLastContentLine && !hasBottomPaddingConfig { + hctx.location = tw.LocationEnd + } else { + hctx.location = tw.LocationMiddle + } + ctx.logger.Debugf("Rendering footer content line %d with location %v", i, hctx.location) + if err := t.renderLine(ctx, mctx, hctx, colAligns, colPadding); err != nil { + return err + } + lastRenderedLineIdx = i + } + + if hasBottomPaddingConfig { + paddingLineContentForContext = make([]string, ctx.numCols) + formattedPaddingCells := make([]string, ctx.numCols) + var representativePadChar string = " " + ctx.logger.Debugf("Constructing Footer Bottom Padding line content strings") + for j := 0; j < ctx.numCols; j++ { + colWd := ctx.widths[tw.Footer].Get(j) + mergeState := tw.MergeState{} + if mctx.footerMerges != nil { + if state, ok := mctx.footerMerges[j]; ok { + mergeState = state + } + } + if mergeState.Horizontal.Present && !mergeState.Horizontal.Start { + paddingLineContentForContext[j] = "" + formattedPaddingCells[j] = "" + continue + } + padChar := " " + if j < len(t.config.Footer.Padding.PerColumn) && t.config.Footer.Padding.PerColumn[j].Bottom != tw.Empty { + padChar = t.config.Footer.Padding.PerColumn[j].Bottom + } else if t.config.Footer.Padding.Global.Bottom != tw.Empty { + padChar = t.config.Footer.Padding.Global.Bottom + } + paddingLineContentForContext[j] = padChar + if j == 0 || representativePadChar == " " { + representativePadChar = padChar + } + padWidth := twwidth.Width(padChar) + if padWidth < 1 { + padWidth = 1 + } + repeatCount := 0 + if colWd > 0 && padWidth > 0 { + repeatCount = colWd / padWidth + } + if colWd > 0 && repeatCount < 1 && padChar != " " { + repeatCount = 1 + } + if colWd == 0 { + repeatCount = 0 + } + rawPaddingContent := strings.Repeat(padChar, repeatCount) + currentWd := twwidth.Width(rawPaddingContent) + if currentWd < colWd { + rawPaddingContent += strings.Repeat(" ", colWd-currentWd) + } + if currentWd > colWd && colWd > 0 { + rawPaddingContent = twwidth.Truncate(rawPaddingContent, colWd) + } + if colWd == 0 { + rawPaddingContent = "" + } + formattedPaddingCells[j] = rawPaddingContent + } + ctx.logger.Debugf("Manually rendering Footer Bottom Padding line (char like '%s')", representativePadChar) + var paddingLineOutput strings.Builder + if cfg.Borders.Left.Enabled() { + paddingLineOutput.WriteString(cfg.Symbols.Column()) + } + for colIdx := 0; colIdx < ctx.numCols; { + if colIdx > 0 && cfg.Settings.Separators.BetweenColumns.Enabled() { + shouldAddSeparator := true + if prevMergeState, ok := mctx.footerMerges[colIdx-1]; ok { + if prevMergeState.Horizontal.Present && !prevMergeState.Horizontal.End { + shouldAddSeparator = false + } + } + if shouldAddSeparator { + paddingLineOutput.WriteString(cfg.Symbols.Column()) + } + } + if colIdx < len(formattedPaddingCells) { + paddingLineOutput.WriteString(formattedPaddingCells[colIdx]) + } + currentMergeState := tw.MergeState{} + if mctx.footerMerges != nil { + if state, ok := mctx.footerMerges[colIdx]; ok { + currentMergeState = state + } + } + if currentMergeState.Horizontal.Present && currentMergeState.Horizontal.Start { + colIdx += currentMergeState.Horizontal.Span + } else { + colIdx++ + } + } + if cfg.Borders.Right.Enabled() { + paddingLineOutput.WriteString(cfg.Symbols.Column()) + } + paddingLineOutput.WriteString(t.newLine) + t.writer.Write([]byte(paddingLineOutput.String())) + ctx.logger.Debugf("Manually rendered Footer Bottom Padding line: %s", strings.TrimSuffix(paddingLineOutput.String(), t.newLine)) + hctx.rowIdx = 0 + hctx.lineIdx = len(ctx.footerLines) + hctx.line = paddingLineContentForContext + hctx.location = tw.LocationEnd + lastRenderedLineIdx = hctx.lineIdx + } + + if cfg.Borders.Bottom.Enabled() && cfg.Settings.Lines.ShowBottom.Enabled() { + ctx.logger.Debugf("Rendering final table bottom border") + if lastRenderedLineIdx == len(ctx.footerLines) { + hctx.rowIdx = 0 + hctx.lineIdx = lastRenderedLineIdx + hctx.line = paddingLineContentForContext + hctx.location = tw.LocationEnd + ctx.logger.Debugf("Setting border context based on bottom padding line") + } else if lastRenderedLineIdx >= 0 { + hctx.rowIdx = 0 + hctx.lineIdx = lastRenderedLineIdx + hctx.line = padLine(ctx.footerLines[hctx.lineIdx], ctx.numCols) + hctx.location = tw.LocationEnd + ctx.logger.Debugf("Setting border context based on last content line idx %d", hctx.lineIdx) + } else if lastRenderedLineIdx == -1 { + hctx.rowIdx = 0 + hctx.lineIdx = -1 + hctx.line = paddingLineContentForContext + hctx.location = tw.LocationEnd + ctx.logger.Debugf("Setting border context based on top padding line") + } else { + hctx.rowIdx = 0 + hctx.lineIdx = -2 + hctx.line = make([]string, ctx.numCols) + hctx.location = tw.LocationEnd + ctx.logger.Debugf("Warning: Cannot determine context for bottom border") + } + resp := t.buildCellContexts(ctx, mctx, hctx, colAligns, colPadding) + ctx.logger.Debugf("Bottom border: Using Widths=%v", ctx.widths[tw.Row]) + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Row], + Current: resp.cells, + Previous: resp.prevCells, + Position: tw.Footer, + Location: tw.LocationEnd, + ColMaxWidths: t.getColMaxWidths(tw.Footer), + }, + Level: tw.LevelFooter, + IsSubRow: false, + }) + } + + return nil +} + +// renderHeader renders the table's header section with borders and padding. +// Parameters ctx and mctx hold rendering and merge state. +// Returns an error if rendering fails. +func (t *Table) renderHeader(ctx *renderContext, mctx *mergeContext) error { + if len(ctx.headerLines) == 0 { + return nil + } + ctx.logger.Debug("Rendering header section") + + f := ctx.renderer + cfg := ctx.cfg + colAligns := t.buildAligns(t.config.Header) + colPadding := t.buildPadding(t.config.Header.Padding) + hctx := &helperContext{position: tw.Header} + + if cfg.Borders.Top.Enabled() && cfg.Settings.Lines.ShowTop.Enabled() { + ctx.logger.Debug("Rendering table top border") + nextCells := make(map[int]tw.CellContext) + if len(ctx.headerLines) > 0 { + for j, cell := range ctx.headerLines[0] { + nextCells[j] = tw.CellContext{Data: cell, Merge: mctx.headerMerges[j]} + } + } + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Header], + Next: nextCells, + Position: tw.Header, + Location: tw.LocationFirst, + }, + Level: tw.LevelHeader, + IsSubRow: false, + }) + } + + if t.config.Header.Padding.Global.Top != tw.Empty { + hctx.location = tw.LocationFirst + hctx.line = t.buildPaddingLineContents(t.config.Header.Padding.Global.Top, ctx.widths[tw.Header], ctx.numCols, mctx.headerMerges) + if err := t.renderPadding(ctx, mctx, hctx, t.config.Header.Padding.Global.Top); err != nil { + return err + } + } + + for i, line := range ctx.headerLines { + hctx.rowIdx = 0 + hctx.lineIdx = i + hctx.line = padLine(line, ctx.numCols) + hctx.location = t.determineLocation(i, len(ctx.headerLines), t.config.Header.Padding.Global.Top, t.config.Header.Padding.Global.Bottom) + + if t.config.Header.Callbacks.Global != nil { + ctx.logger.Debug("Executing global header callback for line %d", i) + t.config.Header.Callbacks.Global() + } + for colIdx, cb := range t.config.Header.Callbacks.PerColumn { + if colIdx < ctx.numCols && cb != nil { + ctx.logger.Debug("Executing per-column header callback for line %d, col %d", i, colIdx) + cb() + } + } + + if err := t.renderLine(ctx, mctx, hctx, colAligns, colPadding); err != nil { + return err + } + } + + if t.config.Header.Padding.Global.Bottom != tw.Empty { + hctx.location = tw.LocationEnd + hctx.line = t.buildPaddingLineContents(t.config.Header.Padding.Global.Bottom, ctx.widths[tw.Header], ctx.numCols, mctx.headerMerges) + if err := t.renderPadding(ctx, mctx, hctx, t.config.Header.Padding.Global.Bottom); err != nil { + return err + } + } + + if cfg.Settings.Lines.ShowHeaderLine.Enabled() && (len(ctx.rowLines) > 0 || len(ctx.footerLines) > 0) { + ctx.logger.Debug("Rendering header separator line") + resp := t.buildCellContexts(ctx, mctx, hctx, colAligns, colPadding) + + var nextSectionCells map[int]tw.CellContext + var nextSectionWidths tw.Mapper[int, int] + + if len(ctx.rowLines) > 0 { + nextSectionWidths = ctx.widths[tw.Row] + rowColAligns := t.buildAligns(t.config.Row) + rowColPadding := t.buildPadding(t.config.Row.Padding) + firstRowHctx := &helperContext{ + position: tw.Row, + rowIdx: 0, + lineIdx: 0, + } + if len(ctx.rowLines[0]) > 0 { + firstRowHctx.line = padLine(ctx.rowLines[0][0], ctx.numCols) + } else { + firstRowHctx.line = make([]string, ctx.numCols) + } + firstRowResp := t.buildCellContexts(ctx, mctx, firstRowHctx, rowColAligns, rowColPadding) + nextSectionCells = firstRowResp.cells + } else if len(ctx.footerLines) > 0 { + nextSectionWidths = ctx.widths[tw.Row] + footerColAligns := t.buildAligns(t.config.Footer) + footerColPadding := t.buildPadding(t.config.Footer.Padding) + firstFooterHctx := &helperContext{ + position: tw.Footer, + rowIdx: 0, + lineIdx: 0, + } + if len(ctx.footerLines) > 0 { + firstFooterHctx.line = padLine(ctx.footerLines[0], ctx.numCols) + } else { + firstFooterHctx.line = make([]string, ctx.numCols) + } + firstFooterResp := t.buildCellContexts(ctx, mctx, firstFooterHctx, footerColAligns, footerColPadding) + nextSectionCells = firstFooterResp.cells + } else { + nextSectionWidths = ctx.widths[tw.Header] + nextSectionCells = nil + } + + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: nextSectionWidths, + Current: resp.cells, + Previous: resp.prevCells, + Next: nextSectionCells, + Position: tw.Header, + Location: tw.LocationMiddle, + }, + Level: tw.LevelBody, + IsSubRow: false, + }) + } + return nil +} + +// renderLine renders a single line with callbacks and normalized widths. +// Parameters include ctx, mctx, hctx, aligns, and padding for rendering. +// Returns an error if rendering fails. +func (t *Table) renderLine(ctx *renderContext, mctx *mergeContext, hctx *helperContext, aligns map[int]tw.Align, padding map[int]tw.Padding) error { + resp := t.buildCellContexts(ctx, mctx, hctx, aligns, padding) + f := ctx.renderer + + isPaddingLine := false + sectionConfig := t.config.Row + switch hctx.position { + case tw.Header: + sectionConfig = t.config.Header + isPaddingLine = (hctx.lineIdx == -1 && sectionConfig.Padding.Global.Top != tw.Empty) || + (hctx.lineIdx == len(ctx.headerLines) && sectionConfig.Padding.Global.Bottom != tw.Empty) + case tw.Footer: + sectionConfig = t.config.Footer + isPaddingLine = (hctx.lineIdx == -1 && sectionConfig.Padding.Global.Top != tw.Empty) || + (hctx.lineIdx == len(ctx.footerLines) && (sectionConfig.Padding.Global.Bottom != tw.Empty || t.hasPerColumnBottomPadding())) + case tw.Row: + if hctx.rowIdx >= 0 && hctx.rowIdx < len(ctx.rowLines) { + isPaddingLine = (hctx.lineIdx == -1 && sectionConfig.Padding.Global.Top != tw.Empty) || + (hctx.lineIdx == len(ctx.rowLines[hctx.rowIdx]) && sectionConfig.Padding.Global.Bottom != tw.Empty) + } + } + + sectionWidths := ctx.widths[hctx.position] + normalizedWidths := ctx.widths[tw.Row] + + formatting := tw.Formatting{ + Row: tw.RowContext{ + Widths: sectionWidths, + ColMaxWidths: t.getColMaxWidths(hctx.position), + Current: resp.cells, + Previous: resp.prevCells, + Next: resp.nextCells, + Position: hctx.position, + Location: hctx.location, + }, + Level: t.getLevel(hctx.position), + IsSubRow: hctx.lineIdx > 0 || isPaddingLine, + NormalizedWidths: normalizedWidths, + } + + if hctx.position == tw.Row { + formatting.HasFooter = len(ctx.footerLines) > 0 + } + + switch hctx.position { + case tw.Header: + f.Header([][]string{hctx.line}, formatting) + case tw.Row: + f.Row(hctx.line, formatting) + case tw.Footer: + f.Footer([][]string{hctx.line}, formatting) + } + return nil +} + +// renderPadding renders padding lines for a section. +// Parameters include ctx, mctx, hctx, and padChar for padding content. +// Returns an error if rendering fails. +func (t *Table) renderPadding(ctx *renderContext, mctx *mergeContext, hctx *helperContext, padChar string) error { + ctx.logger.Debug("Rendering padding line for %s (using char like '%s')", hctx.position, padChar) + + colAligns := t.buildAligns(t.config.Row) + colPadding := t.buildPadding(t.config.Row.Padding) + + switch hctx.position { + case tw.Header: + colAligns = t.buildAligns(t.config.Header) + colPadding = t.buildPadding(t.config.Header.Padding) + case tw.Footer: + colAligns = t.buildAligns(t.config.Footer) + colPadding = t.buildPadding(t.config.Footer.Padding) + } + + return t.renderLine(ctx, mctx, hctx, colAligns, colPadding) +} + +// renderRow renders the table's row section with borders and padding. +// Parameters ctx and mctx hold rendering and merge state. +// Returns an error if rendering fails. +func (t *Table) renderRow(ctx *renderContext, mctx *mergeContext) error { + if len(ctx.rowLines) == 0 { + return nil + } + ctx.logger.Debugf("Rendering row section (total rows: %d)", len(ctx.rowLines)) + + f := ctx.renderer + cfg := ctx.cfg + colAligns := t.buildAligns(t.config.Row) + colPadding := t.buildPadding(t.config.Row.Padding) + hctx := &helperContext{position: tw.Row} + + footerIsEmptyOrNonExistent := !t.hasFooterElements() + if len(ctx.headerLines) == 0 && footerIsEmptyOrNonExistent && cfg.Borders.Top.Enabled() && cfg.Settings.Lines.ShowTop.Enabled() { + ctx.logger.Debug("Rendering table top border (rows only table)") + nextCells := make(map[int]tw.CellContext) + if len(ctx.rowLines) > 0 && len(ctx.rowLines[0]) > 0 && len(mctx.rowMerges) > 0 { + firstLine := ctx.rowLines[0][0] + firstMerges := mctx.rowMerges[0] + for j, cell := range padLine(firstLine, ctx.numCols) { + mergeState := tw.MergeState{} + if firstMerges != nil { + mergeState = firstMerges[j] + } + nextCells[j] = tw.CellContext{Data: cell, Merge: mergeState, Width: ctx.widths[tw.Row].Get(j)} + } + } + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Row], + Next: nextCells, + Position: tw.Row, + Location: tw.LocationFirst, + }, + Level: tw.LevelHeader, + IsSubRow: false, + }) + } + + for i, lines := range ctx.rowLines { + rowHasTopPadding := t.config.Row.Padding.Global.Top != tw.Empty + if rowHasTopPadding { + hctx.rowIdx = i + hctx.lineIdx = -1 + if i == 0 && len(ctx.headerLines) == 0 { + hctx.location = tw.LocationFirst + } else { + hctx.location = tw.LocationMiddle + } + hctx.line = t.buildPaddingLineContents(t.config.Row.Padding.Global.Top, ctx.widths[tw.Row], ctx.numCols, mctx.rowMerges[i]) + ctx.logger.Debug("Calling renderPadding for Row Top Padding (row %d): %v (loc: %v)", i, hctx.line, hctx.location) + if err := t.renderPadding(ctx, mctx, hctx, t.config.Row.Padding.Global.Top); err != nil { + return err + } + } + + footerExists := t.hasFooterElements() + rowHasBottomPadding := t.config.Row.Padding.Global.Bottom != tw.Empty + isLastRow := i == len(ctx.rowLines)-1 + + for j, visualLineData := range lines { + hctx.rowIdx = i + hctx.lineIdx = j + hctx.line = padLine(visualLineData, ctx.numCols) + + if j > 0 { + visualLineHasActualContent := false + for kCellIdx, cellContentInVisualLine := range hctx.line { + if t.Trimmer(cellContentInVisualLine) != "" { + visualLineHasActualContent = true + ctx.logger.Debug("Visual line [%d][%d] has content in cell %d: '%s'. Not skipping.", i, j, kCellIdx, cellContentInVisualLine) + break + } + } + + if !visualLineHasActualContent { + ctx.logger.Debug("Skipping visual line [%d][%d] as it's entirely blank after trimming. Line: %q", i, j, hctx.line) + continue + } + } + + isFirstRow := i == 0 + isLastLineOfRow := j == len(lines)-1 + + if isFirstRow && j == 0 && !rowHasTopPadding && len(ctx.headerLines) == 0 { + hctx.location = tw.LocationFirst + } else if isLastRow && isLastLineOfRow && !rowHasBottomPadding && !footerExists { + hctx.location = tw.LocationEnd + } else { + hctx.location = tw.LocationMiddle + } + + ctx.logger.Debugf("Rendering row %d line %d with location %v. Content: %q", i, j, hctx.location, hctx.line) + if err := t.renderLine(ctx, mctx, hctx, colAligns, colPadding); err != nil { + return err + } + } + + if rowHasBottomPadding { + hctx.rowIdx = i + hctx.lineIdx = len(lines) + if isLastRow && !footerExists { + hctx.location = tw.LocationEnd + } else { + hctx.location = tw.LocationMiddle + } + hctx.line = t.buildPaddingLineContents(t.config.Row.Padding.Global.Bottom, ctx.widths[tw.Row], ctx.numCols, mctx.rowMerges[i]) + ctx.logger.Debug("Calling renderPadding for Row Bottom Padding (row %d): %v (loc: %v)", i, hctx.line, hctx.location) + if err := t.renderPadding(ctx, mctx, hctx, t.config.Row.Padding.Global.Bottom); err != nil { + return err + } + } + + if cfg.Settings.Separators.BetweenRows.Enabled() && !isLastRow { + ctx.logger.Debug("Rendering between-rows separator after logical row %d", i) + respCurrent := t.buildCellContexts(ctx, mctx, hctx, colAligns, colPadding) + + var nextCellsForSeparator map[int]tw.CellContext = nil + nextRowIdx := i + 1 + if nextRowIdx < len(ctx.rowLines) && nextRowIdx < len(mctx.rowMerges) { + hctxNext := &helperContext{position: tw.Row, rowIdx: nextRowIdx, location: tw.LocationMiddle} + nextRowActualLines := ctx.rowLines[nextRowIdx] + nextRowMerges := mctx.rowMerges[nextRowIdx] + + if t.config.Row.Padding.Global.Top != tw.Empty { + hctxNext.lineIdx = -1 + hctxNext.line = t.buildPaddingLineContents(t.config.Row.Padding.Global.Top, ctx.widths[tw.Row], ctx.numCols, nextRowMerges) + } else if len(nextRowActualLines) > 0 { + hctxNext.lineIdx = 0 + hctxNext.line = padLine(nextRowActualLines[0], ctx.numCols) + } else { + hctxNext.lineIdx = 0 + hctxNext.line = make([]string, ctx.numCols) + } + respNext := t.buildCellContexts(ctx, mctx, hctxNext, colAligns, colPadding) + nextCellsForSeparator = respNext.cells + } else { + ctx.logger.Debug("Separator context: No next logical row for separator after row %d.", i) + } + + f.Line(tw.Formatting{ + Row: tw.RowContext{ + Widths: ctx.widths[tw.Row], + Current: respCurrent.cells, + Previous: respCurrent.prevCells, + Next: nextCellsForSeparator, + Position: tw.Row, + Location: tw.LocationMiddle, + ColMaxWidths: t.getColMaxWidths(tw.Row), + }, + Level: tw.LevelBody, + IsSubRow: false, + HasFooter: footerExists, + }) + } + } + return nil +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/cell.go b/vendor/github.com/olekukonko/tablewriter/tw/cell.go new file mode 100644 index 00000000..0547f01a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/cell.go @@ -0,0 +1,64 @@ +package tw + +// CellFormatting holds formatting options for table cells. +type CellFormatting struct { + AutoWrap int // Wrapping behavior (e.g., WrapTruncate, WrapNormal) + MergeMode int // Bitmask for merge behavior (e.g., MergeHorizontal, MergeVertical) + + // Changed form bool to State + // See https://github.com/olekukonko/tablewriter/issues/261 + AutoFormat State // Enables automatic formatting (e.g., title case for headers) + + // Deprecated: kept for compatibility + // will be removed soon + Alignment Align // Text alignment within the cell (e.g., Left, Right, Center) + +} + +// CellPadding defines padding settings for table cells. +type CellPadding struct { + Global Padding // Default padding applied to all cells + PerColumn []Padding // Column-specific padding overrides +} + +// CellFilter defines filtering functions for cell content. +type CellFilter struct { + Global func([]string) []string // Processes the entire row + PerColumn []func(string) string // Processes individual cells by column +} + +// CellCallbacks holds callback functions for cell processing. +// Note: These are currently placeholders and not fully implemented. +type CellCallbacks struct { + Global func() // Global callback applied to all cells + PerColumn []func() // Column-specific callbacks +} + +// CellAlignment defines alignment settings for table cells. +type CellAlignment struct { + Global Align // Default alignment applied to all cells + PerColumn []Align // Column-specific alignment overrides +} + +// CellConfig combines formatting, padding, and callback settings for a table section. +type CellConfig struct { + Formatting CellFormatting // Cell formatting options + Padding CellPadding // Padding configuration + Callbacks CellCallbacks // Callback functions (unused) + Filter CellFilter // Function to filter cell content (renamed from Filter Filter) + Alignment CellAlignment // Alignment configuration for cells + ColMaxWidths CellWidth // Per-column maximum width overrides + + // Deprecated: use Alignment.PerColumn instead. Will be removed in a future version. + // will be removed soon + ColumnAligns []Align // Per-column alignment overrides +} + +type CellWidth struct { + Global int + PerColumn Mapper[int, int] +} + +func (c CellWidth) Constrained() bool { + return c.Global > 0 || c.PerColumn.Len() > 0 +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/deprecated.go b/vendor/github.com/olekukonko/tablewriter/tw/deprecated.go new file mode 100644 index 00000000..3325765f --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/deprecated.go @@ -0,0 +1,137 @@ +package tw + +// Deprecated: SymbolASCII is deprecated; use Glyphs with StyleASCII instead. +// this will be removed soon +type SymbolASCII struct{} + +// SymbolASCII symbol methods +func (s *SymbolASCII) Name() string { return StyleNameASCII.String() } +func (s *SymbolASCII) Center() string { return "+" } +func (s *SymbolASCII) Row() string { return "-" } +func (s *SymbolASCII) Column() string { return "|" } +func (s *SymbolASCII) TopLeft() string { return "+" } +func (s *SymbolASCII) TopMid() string { return "+" } +func (s *SymbolASCII) TopRight() string { return "+" } +func (s *SymbolASCII) MidLeft() string { return "+" } +func (s *SymbolASCII) MidRight() string { return "+" } +func (s *SymbolASCII) BottomLeft() string { return "+" } +func (s *SymbolASCII) BottomMid() string { return "+" } +func (s *SymbolASCII) BottomRight() string { return "+" } +func (s *SymbolASCII) HeaderLeft() string { return "+" } +func (s *SymbolASCII) HeaderMid() string { return "+" } +func (s *SymbolASCII) HeaderRight() string { return "+" } + +// Deprecated: SymbolUnicode is deprecated; use Glyphs with appropriate styles (e.g., StyleLight, StyleHeavy) instead. +// this will be removed soon +type SymbolUnicode struct { + row string + column string + center string + corners [9]string // [topLeft, topMid, topRight, midLeft, center, midRight, bottomLeft, bottomMid, bottomRight] +} + +// SymbolUnicode symbol methods +func (s *SymbolUnicode) Name() string { return "unicode" } +func (s *SymbolUnicode) Center() string { return s.center } +func (s *SymbolUnicode) Row() string { return s.row } +func (s *SymbolUnicode) Column() string { return s.column } +func (s *SymbolUnicode) TopLeft() string { return s.corners[0] } +func (s *SymbolUnicode) TopMid() string { return s.corners[1] } +func (s *SymbolUnicode) TopRight() string { return s.corners[2] } +func (s *SymbolUnicode) MidLeft() string { return s.corners[3] } +func (s *SymbolUnicode) MidRight() string { return s.corners[5] } +func (s *SymbolUnicode) BottomLeft() string { return s.corners[6] } +func (s *SymbolUnicode) BottomMid() string { return s.corners[7] } +func (s *SymbolUnicode) BottomRight() string { return s.corners[8] } +func (s *SymbolUnicode) HeaderLeft() string { return s.MidLeft() } +func (s *SymbolUnicode) HeaderMid() string { return s.Center() } +func (s *SymbolUnicode) HeaderRight() string { return s.MidRight() } + +// Deprecated: SymbolMarkdown is deprecated; use Glyphs with StyleMarkdown instead. +// this will be removed soon +type SymbolMarkdown struct{} + +// SymbolMarkdown symbol methods +func (s *SymbolMarkdown) Name() string { return StyleNameMarkdown.String() } +func (s *SymbolMarkdown) Center() string { return "|" } +func (s *SymbolMarkdown) Row() string { return "-" } +func (s *SymbolMarkdown) Column() string { return "|" } +func (s *SymbolMarkdown) TopLeft() string { return "" } +func (s *SymbolMarkdown) TopMid() string { return "" } +func (s *SymbolMarkdown) TopRight() string { return "" } +func (s *SymbolMarkdown) MidLeft() string { return "|" } +func (s *SymbolMarkdown) MidRight() string { return "|" } +func (s *SymbolMarkdown) BottomLeft() string { return "" } +func (s *SymbolMarkdown) BottomMid() string { return "" } +func (s *SymbolMarkdown) BottomRight() string { return "" } +func (s *SymbolMarkdown) HeaderLeft() string { return "|" } +func (s *SymbolMarkdown) HeaderMid() string { return "|" } +func (s *SymbolMarkdown) HeaderRight() string { return "|" } + +// Deprecated: SymbolNothing is deprecated; use Glyphs with StyleNone instead. +// this will be removed soon +type SymbolNothing struct{} + +// SymbolNothing symbol methods +func (s *SymbolNothing) Name() string { return StyleNameNothing.String() } +func (s *SymbolNothing) Center() string { return "" } +func (s *SymbolNothing) Row() string { return "" } +func (s *SymbolNothing) Column() string { return "" } +func (s *SymbolNothing) TopLeft() string { return "" } +func (s *SymbolNothing) TopMid() string { return "" } +func (s *SymbolNothing) TopRight() string { return "" } +func (s *SymbolNothing) MidLeft() string { return "" } +func (s *SymbolNothing) MidRight() string { return "" } +func (s *SymbolNothing) BottomLeft() string { return "" } +func (s *SymbolNothing) BottomMid() string { return "" } +func (s *SymbolNothing) BottomRight() string { return "" } +func (s *SymbolNothing) HeaderLeft() string { return "" } +func (s *SymbolNothing) HeaderMid() string { return "" } +func (s *SymbolNothing) HeaderRight() string { return "" } + +// Deprecated: SymbolGraphical is deprecated; use Glyphs with StyleGraphical instead. +// this will be removed soon +type SymbolGraphical struct{} + +// SymbolGraphical symbol methods +func (s *SymbolGraphical) Name() string { return StyleNameGraphical.String() } +func (s *SymbolGraphical) Center() string { return "🟧" } // Orange square (matches mid junctions) +func (s *SymbolGraphical) Row() string { return "🟥" } // Red square (matches corners) +func (s *SymbolGraphical) Column() string { return "🟦" } // Blue square (vertical line) +func (s *SymbolGraphical) TopLeft() string { return "🟥" } // Top-left corner +func (s *SymbolGraphical) TopMid() string { return "🔳" } // Top junction +func (s *SymbolGraphical) TopRight() string { return "🟥" } // Top-right corner +func (s *SymbolGraphical) MidLeft() string { return "🟧" } // Left junction +func (s *SymbolGraphical) MidRight() string { return "🟧" } // Right junction +func (s *SymbolGraphical) BottomLeft() string { return "🟥" } // Bottom-left corner +func (s *SymbolGraphical) BottomMid() string { return "🔳" } // Bottom junction +func (s *SymbolGraphical) BottomRight() string { return "🟥" } // Bottom-right corner +func (s *SymbolGraphical) HeaderLeft() string { return "🟧" } // Header left (matches mid junctions) +func (s *SymbolGraphical) HeaderMid() string { return "🟧" } // Header middle (matches mid junctions) +func (s *SymbolGraphical) HeaderRight() string { return "🟧" } // Header right (matches mid junctions) + +// Deprecated: SymbolMerger is deprecated; use Glyphs with StyleMerger instead. +// this will be removed soon +type SymbolMerger struct { + row string + column string + center string + corners [9]string // [TL, TM, TR, ML, CenterIdx(unused), MR, BL, BM, BR] +} + +// SymbolMerger symbol methods +func (s *SymbolMerger) Name() string { return StyleNameMerger.String() } +func (s *SymbolMerger) Center() string { return s.center } // Main crossing symbol +func (s *SymbolMerger) Row() string { return s.row } +func (s *SymbolMerger) Column() string { return s.column } +func (s *SymbolMerger) TopLeft() string { return s.corners[0] } +func (s *SymbolMerger) TopMid() string { return s.corners[1] } // LevelHeader junction +func (s *SymbolMerger) TopRight() string { return s.corners[2] } +func (s *SymbolMerger) MidLeft() string { return s.corners[3] } // Left junction +func (s *SymbolMerger) MidRight() string { return s.corners[5] } // Right junction +func (s *SymbolMerger) BottomLeft() string { return s.corners[6] } +func (s *SymbolMerger) BottomMid() string { return s.corners[7] } // LevelFooter junction +func (s *SymbolMerger) BottomRight() string { return s.corners[8] } +func (s *SymbolMerger) HeaderLeft() string { return s.MidLeft() } +func (s *SymbolMerger) HeaderMid() string { return s.Center() } +func (s *SymbolMerger) HeaderRight() string { return s.MidRight() } diff --git a/vendor/github.com/olekukonko/tablewriter/tw/fn.go b/vendor/github.com/olekukonko/tablewriter/tw/fn.go new file mode 100644 index 00000000..d962ff8d --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/fn.go @@ -0,0 +1,231 @@ +// Package tw provides utility functions for text formatting, width calculation, and string manipulation +// specifically tailored for table rendering, including handling ANSI escape codes and Unicode text. +package tw + +import ( + "github.com/olekukonko/tablewriter/pkg/twwidth" + "math" // For mathematical operations like ceiling + "strconv" // For string-to-number conversions + "strings" // For string manipulation utilities + "unicode" // For Unicode character classification + "unicode/utf8" // For UTF-8 rune handling +) + +// Title normalizes and uppercases a label string for use in headers. +// It replaces underscores and certain dots with spaces and trims whitespace. +func Title(name string) string { + origLen := len(name) + rs := []rune(name) + for i, r := range rs { + switch r { + case '_': + rs[i] = ' ' // Replace underscores with spaces + case '.': + // Replace dots with spaces unless they are between numeric or space characters + if (i != 0 && !IsIsNumericOrSpace(rs[i-1])) || (i != len(rs)-1 && !IsIsNumericOrSpace(rs[i+1])) { + rs[i] = ' ' + } + } + } + name = string(rs) + name = strings.TrimSpace(name) + // If the input was non-empty but trimmed to empty, return a single space + if len(name) == 0 && origLen > 0 { + name = " " + } + // Convert to uppercase for header formatting + return strings.ToUpper(name) +} + +// PadCenter centers a string within a specified width using a padding character. +// Extra padding is split between left and right, with slight preference to left if uneven. +func PadCenter(s, pad string, width int) string { + gap := width - twwidth.Width(s) + if gap > 0 { + // Calculate left and right padding; ceil ensures left gets extra if gap is odd + gapLeft := int(math.Ceil(float64(gap) / 2)) + gapRight := gap - gapLeft + return strings.Repeat(pad, gapLeft) + s + strings.Repeat(pad, gapRight) + } + // If no padding needed or string is too wide, return as is + return s +} + +// PadRight left-aligns a string within a specified width, filling remaining space on the right with padding. +func PadRight(s, pad string, width int) string { + gap := width - twwidth.Width(s) + if gap > 0 { + // Append padding to the right + return s + strings.Repeat(pad, gap) + } + // If no padding needed or string is too wide, return as is + return s +} + +// PadLeft right-aligns a string within a specified width, filling remaining space on the left with padding. +func PadLeft(s, pad string, width int) string { + gap := width - twwidth.Width(s) + if gap > 0 { + // Prepend padding to the left + return strings.Repeat(pad, gap) + s + } + // If no padding needed or string is too wide, return as is + return s +} + +// Pad aligns a string within a specified width using a padding character. +// It truncates if the string is wider than the target width. +func Pad(s string, padChar string, totalWidth int, alignment Align) string { + sDisplayWidth := twwidth.Width(s) + if sDisplayWidth > totalWidth { + return twwidth.Truncate(s, totalWidth) // Only truncate if necessary + } + switch alignment { + case AlignLeft: + return PadRight(s, padChar, totalWidth) + case AlignRight: + return PadLeft(s, padChar, totalWidth) + case AlignCenter: + return PadCenter(s, padChar, totalWidth) + default: + return PadRight(s, padChar, totalWidth) + } +} + +// IsIsNumericOrSpace checks if a rune is a digit or space character. +// Used in formatting logic to determine safe character replacements. +func IsIsNumericOrSpace(r rune) bool { + return ('0' <= r && r <= '9') || r == ' ' +} + +// IsNumeric checks if a string represents a valid integer or floating-point number. +func IsNumeric(s string) bool { + s = strings.TrimSpace(s) + if s == "" { + return false + } + // Try parsing as integer first + if _, err := strconv.Atoi(s); err == nil { + return true + } + // Then try parsing as float + _, err := strconv.ParseFloat(s, 64) + return err == nil +} + +// SplitCamelCase splits a camelCase or PascalCase or snake_case string into separate words. +// It detects transitions between uppercase, lowercase, digits, and other characters. +func SplitCamelCase(src string) (entries []string) { + // Validate UTF-8 input; return as single entry if invalid + if !utf8.ValidString(src) { + return []string{src} + } + entries = []string{} + var runes [][]rune + lastClass := 0 + class := 0 + // Classify each rune into categories: lowercase (1), uppercase (2), digit (3), other (4) + for _, r := range src { + switch { + case unicode.IsLower(r): + class = 1 + case unicode.IsUpper(r): + class = 2 + case unicode.IsDigit(r): + class = 3 + default: + class = 4 + } + // Group consecutive runes of the same class together + if class == lastClass { + runes[len(runes)-1] = append(runes[len(runes)-1], r) + } else { + runes = append(runes, []rune{r}) + } + lastClass = class + } + // Adjust for cases where an uppercase letter is followed by lowercase (e.g., CamelCase) + for i := 0; i < len(runes)-1; i++ { + if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { + // Move the last uppercase rune to the next group for proper word splitting + runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) + runes[i] = runes[i][:len(runes[i])-1] + } + } + // Convert rune groups to strings, excluding empty, underscore or whitespace-only groups + for _, s := range runes { + str := string(s) + if len(s) > 0 && strings.TrimSpace(str) != "" && str != "_" { + entries = append(entries, str) + } + } + return +} + +// Or provides a ternary-like operation for strings, returning 'valid' if cond is true, else 'inValid'. +func Or(cond bool, valid, inValid string) string { + if cond { + return valid + } + return inValid +} + +// Max returns the greater of two integers. +func Max(a, b int) int { + if a > b { + return a + } + return b +} + +// Min returns the smaller of two integers. +func Min(a, b int) int { + if a < b { + return a + } + return b +} + +// BreakPoint finds the rune index where the display width of a string first exceeds the specified limit. +// It returns the number of runes if the entire string fits, or 0 if nothing fits. +func BreakPoint(s string, limit int) int { + // If limit is 0 or negative, nothing can fit + if limit <= 0 { + return 0 + } + // Empty string has a breakpoint of 0 + if s == "" { + return 0 + } + + currentWidth := 0 + runeCount := 0 + // Iterate over runes, accumulating display width + for _, r := range s { + runeWidth := twwidth.Width(string(r)) // Calculate width of individual rune + if currentWidth+runeWidth > limit { + // Adding this rune would exceed the limit; breakpoint is before this rune + if currentWidth == 0 { + // First rune is too wide; allow breaking after it if limit > 0 + if runeWidth > limit && limit > 0 { + return 1 + } + return 0 + } + return runeCount + } + currentWidth += runeWidth + runeCount++ + } + + // Entire string fits within the limit + return runeCount +} + +func MakeAlign(l int, align Align) Alignment { + aa := make(Alignment, l) + for i := 0; i < l; i++ { + aa[i] = align + } + return aa +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/mapper.go b/vendor/github.com/olekukonko/tablewriter/tw/mapper.go new file mode 100644 index 00000000..8d814447 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/mapper.go @@ -0,0 +1,220 @@ +package tw + +import ( + "fmt" + "sort" +) + +// KeyValuePair represents a single key-value pair from a Mapper. +type KeyValuePair[K comparable, V any] struct { + Key K + Value V +} + +// Mapper is a generic map type with comparable keys and any value type. +// It provides type-safe operations on maps with additional convenience methods. +type Mapper[K comparable, V any] map[K]V + +// NewMapper creates and returns a new initialized Mapper. +func NewMapper[K comparable, V any]() Mapper[K, V] { + return make(Mapper[K, V]) +} + +// Get returns the value associated with the key. +// If the key doesn't exist or the map is nil, it returns the zero value for the value type. +func (m Mapper[K, V]) Get(key K) V { + if m == nil { + var zero V + return zero + } + return m[key] +} + +// OK returns the value associated with the key and a boolean indicating whether the key exists. +func (m Mapper[K, V]) OK(key K) (V, bool) { + if m == nil { + var zero V + return zero, false + } + val, ok := m[key] + return val, ok +} + +// Set sets the value for the specified key. +// Does nothing if the map is nil. +func (m Mapper[K, V]) Set(key K, value V) Mapper[K, V] { + if m != nil { + m[key] = value + } + return m +} + +// Delete removes the specified key from the map. +// Does nothing if the key doesn't exist or the map is nil. +func (m Mapper[K, V]) Delete(key K) Mapper[K, V] { + if m != nil { + delete(m, key) + } + return m +} + +// Has returns true if the key exists in the map, false otherwise. +func (m Mapper[K, V]) Has(key K) bool { + if m == nil { + return false + } + _, exists := m[key] + return exists +} + +// Len returns the number of elements in the map. +// Returns 0 if the map is nil. +func (m Mapper[K, V]) Len() int { + if m == nil { + return 0 + } + return len(m) +} + +// Keys returns a slice containing all keys in the map. +// Returns nil if the map is nil or empty. +func (m Mapper[K, V]) Keys() []K { + if m == nil { + return nil + } + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + return keys +} + +func (m Mapper[K, V]) Clear() { + if m == nil { + return + } + for k := range m { + delete(m, k) + } +} + +// Values returns a slice containing all values in the map. +// Returns nil if the map is nil or empty. +func (m Mapper[K, V]) Values() []V { + if m == nil { + return nil + } + values := make([]V, 0, len(m)) + for _, v := range m { + values = append(values, v) + } + return values +} + +// Each iterates over each key-value pair in the map and calls the provided function. +// Does nothing if the map is nil. +func (m Mapper[K, V]) Each(fn func(K, V)) { + if m != nil { + for k, v := range m { + fn(k, v) + } + } +} + +// Filter returns a new Mapper containing only the key-value pairs that satisfy the predicate. +func (m Mapper[K, V]) Filter(fn func(K, V) bool) Mapper[K, V] { + result := NewMapper[K, V]() + if m != nil { + for k, v := range m { + if fn(k, v) { + result[k] = v + } + } + } + return result +} + +// MapValues returns a new Mapper with the same keys but values transformed by the provided function. +func (m Mapper[K, V]) MapValues(fn func(V) V) Mapper[K, V] { + result := NewMapper[K, V]() + if m != nil { + for k, v := range m { + result[k] = fn(v) + } + } + return result +} + +// Clone returns a shallow copy of the Mapper. +func (m Mapper[K, V]) Clone() Mapper[K, V] { + result := NewMapper[K, V]() + if m != nil { + for k, v := range m { + result[k] = v + } + } + return result +} + +// Slicer converts the Mapper to a Slicer of key-value pairs. +func (m Mapper[K, V]) Slicer() Slicer[KeyValuePair[K, V]] { + if m == nil { + return nil + } + result := make(Slicer[KeyValuePair[K, V]], 0, len(m)) + for k, v := range m { + result = append(result, KeyValuePair[K, V]{Key: k, Value: v}) + } + return result +} + +func (m Mapper[K, V]) SortedKeys() []K { + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + + sort.Slice(keys, func(i, j int) bool { + a, b := any(keys[i]), any(keys[j]) + + switch va := a.(type) { + case int: + if vb, ok := b.(int); ok { + return va < vb + } + case int32: + if vb, ok := b.(int32); ok { + return va < vb + } + case int64: + if vb, ok := b.(int64); ok { + return va < vb + } + case uint: + if vb, ok := b.(uint); ok { + return va < vb + } + case uint64: + if vb, ok := b.(uint64); ok { + return va < vb + } + case float32: + if vb, ok := b.(float32); ok { + return va < vb + } + case float64: + if vb, ok := b.(float64); ok { + return va < vb + } + case string: + if vb, ok := b.(string); ok { + return va < vb + } + } + + // fallback to string comparison + return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) + }) + + return keys +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/preset.go b/vendor/github.com/olekukonko/tablewriter/tw/preset.go new file mode 100644 index 00000000..acadc25c --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/preset.go @@ -0,0 +1,18 @@ +package tw + +// BorderNone defines a border configuration with all sides disabled. +var ( + // PaddingNone represents explicitly empty padding (no spacing on any side) + // Equivalent to Padding{Overwrite: true} + PaddingNone = Padding{Left: Empty, Right: Empty, Top: Empty, Bottom: Empty, Overwrite: true} + BorderNone = Border{Left: Off, Right: Off, Top: Off, Bottom: Off} + LinesNone = Lines{ShowTop: Off, ShowBottom: Off, ShowHeaderLine: Off, ShowFooterLine: Off} + SeparatorsNone = Separators{ShowHeader: Off, ShowFooter: Off, BetweenRows: Off, BetweenColumns: Off} +) + +var ( + + // PaddingDefault represents standard single-space padding on left/right + // Equivalent to Padding{Left: " ", Right: " ", Overwrite: true} + PaddingDefault = Padding{Left: " ", Right: " ", Overwrite: true} +) diff --git a/vendor/github.com/olekukonko/tablewriter/tw/renderer.go b/vendor/github.com/olekukonko/tablewriter/tw/renderer.go new file mode 100644 index 00000000..cf2779b2 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/renderer.go @@ -0,0 +1,132 @@ +package tw + +import ( + "github.com/olekukonko/ll" + "io" +) + +// Renderer defines the interface for rendering tables to an io.Writer. +// Implementations must handle headers, rows, footers, and separator lines. +type Renderer interface { + Start(w io.Writer) error + Header(headers [][]string, ctx Formatting) // Renders table header + Row(row []string, ctx Formatting) // Renders a single row + Footer(footers [][]string, ctx Formatting) // Renders table footer + Line(ctx Formatting) // Renders separator line + Config() Rendition // Returns renderer config + Close() error // Gets Rendition form Blueprint + Logger(logger *ll.Logger) // send logger to renderers +} + +// Rendition holds the configuration for the default renderer. +type Rendition struct { + Borders Border // Border visibility settings + Symbols Symbols // Symbols used for table drawing + Settings Settings // Rendering behavior settings + Streaming bool +} + +// Renditioning has a method to update its rendition. +// Let's define an optional interface for this. +type Renditioning interface { + Rendition(r Rendition) +} + +// Formatting encapsulates the complete formatting context for a table row. +// It provides all necessary information to render a row correctly within the table structure. +type Formatting struct { + Row RowContext // Detailed configuration for the row and its cells + Level Level // Hierarchical level (Header, Body, Footer) affecting line drawing + HasFooter bool // Indicates if the table includes a footer section + IsSubRow bool // Marks this as a continuation or padding line in multi-line rows + NormalizedWidths Mapper[int, int] +} + +// CellContext defines the properties and formatting state of an individual table cell. +type CellContext struct { + Data string // Content to be displayed in the cell, provided by the caller + Align Align // Text alignment within the cell (Left, Right, Center, Skip) + Padding Padding // Padding characters surrounding the cell content + Width int // Suggested width (often overridden by Row.Widths) + Merge MergeState // Details about cell spanning across rows or columns +} + +// MergeState captures how a cell merges across different directions. +type MergeState struct { + Vertical MergeStateOption // Properties for vertical merging (across rows) + Horizontal MergeStateOption // Properties for horizontal merging (across columns) + Hierarchical MergeStateOption // Properties for nested/hierarchical merging +} + +// MergeStateOption represents common attributes for merging in a specific direction. +type MergeStateOption struct { + Present bool // True if this merge direction is active + Span int // Number of cells this merge spans + Start bool // True if this cell is the starting point of the merge + End bool // True if this cell is the ending point of the merge +} + +// RowContext manages layout properties and relationships for a row and its columns. +// It maintains state about the current row and its neighbors for proper rendering. +type RowContext struct { + Position Position // Section of the table (Header, Row, Footer) + Location Location // Boundary position (First, Middle, End) + Current map[int]CellContext // Cells in this row, indexed by column + Previous map[int]CellContext // Cells from the row above; nil if none + Next map[int]CellContext // Cells from the row below; nil if none + Widths Mapper[int, int] // Computed widths for each column + ColMaxWidths CellWidth // Maximum allowed width per column +} + +func (r RowContext) GetCell(col int) CellContext { + return r.Current[col] +} + +// Separators controls the visibility of separators in the table. +type Separators struct { + ShowHeader State // Controls header separator visibility + ShowFooter State // Controls footer separator visibility + BetweenRows State // Determines if lines appear between rows + BetweenColumns State // Determines if separators appear between columns +} + +// Lines manages the visibility of table boundary lines. +type Lines struct { + ShowTop State // Top border visibility + ShowBottom State // Bottom border visibility + ShowHeaderLine State // Header separator line visibility + ShowFooterLine State // Footer separator line visibility +} + +// Settings holds configuration preferences for rendering behavior. +type Settings struct { + Separators Separators // Separator visibility settings + Lines Lines // Line visibility settings + CompactMode State // Reserved for future compact rendering (unused) + // Cushion State +} + +// Border defines the visibility states of table borders. +type Border struct { + Left State // Left border visibility + Right State // Right border visibility + Top State // Top border visibility + Bottom State // Bottom border visibility + Overwrite bool +} + +type StreamConfig struct { + Enable bool + + // StrictColumns, if true, causes Append() to return an error + // in streaming mode if the number of cells in an appended row + // does not match the established number of columns for the stream. + // If false (default), rows with mismatched column counts will be + // padded or truncated with a warning log. + StrictColumns bool + + // Deprecated: Use top-level Config.Widths for streaming width control. + // This field will be removed in a future version. It will be respected if + // Config.Widths is not set and this field is. + Widths CellWidth +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/slicer.go b/vendor/github.com/olekukonko/tablewriter/tw/slicer.go new file mode 100644 index 00000000..34d24632 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/slicer.go @@ -0,0 +1,147 @@ +package tw + +// Slicer is a generic slice type that provides additional methods for slice manipulation. +type Slicer[T any] []T + +// NewSlicer creates and returns a new initialized Slicer. +func NewSlicer[T any]() Slicer[T] { + return make(Slicer[T], 0) +} + +// Get returns the element at the specified index. +// Returns the zero value if the index is out of bounds or the slice is nil. +func (s Slicer[T]) Get(index int) T { + if s == nil || index < 0 || index >= len(s) { + var zero T + return zero + } + return s[index] +} + +// GetOK returns the element at the specified index and a boolean indicating whether the index was valid. +func (s Slicer[T]) GetOK(index int) (T, bool) { + if s == nil || index < 0 || index >= len(s) { + var zero T + return zero, false + } + return s[index], true +} + +// Append appends elements to the slice and returns the new slice. +func (s Slicer[T]) Append(elements ...T) Slicer[T] { + return append(s, elements...) +} + +// Prepend adds elements to the beginning of the slice and returns the new slice. +func (s Slicer[T]) Prepend(elements ...T) Slicer[T] { + return append(elements, s...) +} + +// Len returns the number of elements in the slice. +// Returns 0 if the slice is nil. +func (s Slicer[T]) Len() int { + if s == nil { + return 0 + } + return len(s) +} + +// IsEmpty returns true if the slice is nil or has zero elements. +func (s Slicer[T]) IsEmpty() bool { + return s.Len() == 0 +} + +// Has returns true if the index exists in the slice. +func (s Slicer[T]) Has(index int) bool { + return index >= 0 && index < s.Len() +} + +// First returns the first element of the slice, or the zero value if empty. +func (s Slicer[T]) First() T { + return s.Get(0) +} + +// Last returns the last element of the slice, or the zero value if empty. +func (s Slicer[T]) Last() T { + return s.Get(s.Len() - 1) +} + +// Each iterates over each element in the slice and calls the provided function. +// Does nothing if the slice is nil. +func (s Slicer[T]) Each(fn func(T)) { + if s != nil { + for _, v := range s { + fn(v) + } + } +} + +// Filter returns a new Slicer containing only elements that satisfy the predicate. +func (s Slicer[T]) Filter(fn func(T) bool) Slicer[T] { + result := NewSlicer[T]() + if s != nil { + for _, v := range s { + if fn(v) { + result = result.Append(v) + } + } + } + return result +} + +// Map returns a new Slicer with each element transformed by the provided function. +func (s Slicer[T]) Map(fn func(T) T) Slicer[T] { + result := NewSlicer[T]() + if s != nil { + for _, v := range s { + result = result.Append(fn(v)) + } + } + return result +} + +// Contains returns true if the slice contains an element that satisfies the predicate. +func (s Slicer[T]) Contains(fn func(T) bool) bool { + if s != nil { + for _, v := range s { + if fn(v) { + return true + } + } + } + return false +} + +// Find returns the first element that satisfies the predicate, along with a boolean indicating if it was found. +func (s Slicer[T]) Find(fn func(T) bool) (T, bool) { + if s != nil { + for _, v := range s { + if fn(v) { + return v, true + } + } + } + var zero T + return zero, false +} + +// Clone returns a shallow copy of the Slicer. +func (s Slicer[T]) Clone() Slicer[T] { + result := NewSlicer[T]() + if s != nil { + result = append(result, s...) + } + return result +} + +// SlicerToMapper converts a Slicer of KeyValuePair to a Mapper. +func SlicerToMapper[K comparable, V any](s Slicer[KeyValuePair[K, V]]) Mapper[K, V] { + result := make(Mapper[K, V]) + if s == nil { + return result + } + for _, pair := range s { + result[pair.Key] = pair.Value + } + return result +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/state.go b/vendor/github.com/olekukonko/tablewriter/tw/state.go new file mode 100644 index 00000000..7e485099 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/state.go @@ -0,0 +1,51 @@ +package tw + +// State represents an on/off state +type State int + +// Public: Methods for State type + +// Enabled checks if the state is on +func (o State) Enabled() bool { return o == Success } + +// Default checks if the state is unknown +func (o State) Default() bool { return o == Unknown } + +// Disabled checks if the state is off +func (o State) Disabled() bool { return o == Fail } + +// Toggle switches the state between on and off +func (o State) Toggle() State { + if o == Fail { + return Success + } + return Fail +} + +// Cond executes a condition if the state is enabled +func (o State) Cond(c func() bool) bool { + if o.Enabled() { + return c() + } + return false +} + +// Or returns this state if enabled, else the provided state +func (o State) Or(c State) State { + if o.Enabled() { + return o + } + return c +} + +// String returns the string representation of the state +func (o State) String() string { + if o.Enabled() { + return "on" + } + + if o.Disabled() { + return "off" + } + return "undefined" +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/symbols.go b/vendor/github.com/olekukonko/tablewriter/tw/symbols.go new file mode 100644 index 00000000..3ee87fc9 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/symbols.go @@ -0,0 +1,1012 @@ +package tw + +import "fmt" + +// Symbols defines the interface for table border symbols +type Symbols interface { + // Name returns the style name + Name() string + + // Basic component symbols + Center() string // Junction symbol (where lines cross) + Row() string // Horizontal line symbol + Column() string // Vertical line symbol + + // Corner and junction symbols + TopLeft() string // LevelHeader-left corner + TopMid() string // LevelHeader junction + TopRight() string // LevelHeader-right corner + MidLeft() string // Left junction + MidRight() string // Right junction + BottomLeft() string // LevelFooter-left corner + BottomMid() string // LevelFooter junction + BottomRight() string // LevelFooter-right corner + + // Optional header-specific symbols + HeaderLeft() string + HeaderMid() string + HeaderRight() string +} + +// BorderStyle defines different border styling options +type BorderStyle int + +// Border style constants +const ( + StyleNone BorderStyle = iota + StyleASCII + StyleLight + StyleHeavy + StyleDouble + StyleDoubleLong + StyleLightHeavy + StyleHeavyLight + StyleLightDouble + StyleDoubleLight + StyleRounded + StyleMarkdown + StyleGraphical + StyleMerger + StyleDefault + StyleDotted + StyleArrow + StyleStarry + StyleHearts + StyleCircuit // Renamed from StyleTech + StyleNature + StyleArtistic + Style8Bit + StyleChaos + StyleDots + StyleBlocks + StyleZen + StyleVintage + StyleSketch + StyleArrowDouble + StyleCelestial + StyleCyber + StyleRunic + StyleIndustrial + StyleInk + StyleArcade + StyleBlossom + StyleFrosted + StyleMosaic + StyleUFO + StyleSteampunk + StyleGalaxy + StyleJazz + StylePuzzle + StyleHypno +) + +// StyleName defines names for border styles +type StyleName string + +func (s StyleName) String() string { + return string(s) +} + +const ( + StyleNameNothing StyleName = "nothing" + StyleNameASCII StyleName = "ascii" + StyleNameLight StyleName = "light" + StyleNameHeavy StyleName = "heavy" + StyleNameDouble StyleName = "double" + StyleNameDoubleLong StyleName = "doublelong" + StyleNameLightHeavy StyleName = "lightheavy" + StyleNameHeavyLight StyleName = "heavylight" + StyleNameLightDouble StyleName = "lightdouble" + StyleNameDoubleLight StyleName = "doublelight" + StyleNameRounded StyleName = "rounded" + StyleNameMarkdown StyleName = "markdown" + StyleNameGraphical StyleName = "graphical" + StyleNameMerger StyleName = "merger" + StyleNameDotted StyleName = "dotted" + StyleNameArrow StyleName = "arrow" + StyleNameStarry StyleName = "starry" + StyleNameHearts StyleName = "hearts" + StyleNameCircuit StyleName = "circuit" // Renamed from Tech + StyleNameNature StyleName = "nature" + StyleNameArtistic StyleName = "artistic" + StyleName8Bit StyleName = "8bit" + StyleNameChaos StyleName = "chaos" + StyleNameDots StyleName = "dots" + StyleNameBlocks StyleName = "blocks" + StyleNameZen StyleName = "zen" + StyleNameVintage StyleName = "vintage" + StyleNameSketch StyleName = "sketch" + StyleNameArrowDouble StyleName = "arrowdouble" + StyleNameCelestial StyleName = "celestial" + StyleNameCyber StyleName = "cyber" + StyleNameRunic StyleName = "runic" + StyleNameIndustrial StyleName = "industrial" + StyleNameInk StyleName = "ink" + StyleNameArcade StyleName = "arcade" + StyleNameBlossom StyleName = "blossom" + StyleNameFrosted StyleName = "frosted" + StyleNameMosaic StyleName = "mosaic" + StyleNameUFO StyleName = "ufo" + StyleNameSteampunk StyleName = "steampunk" + StyleNameGalaxy StyleName = "galaxy" + StyleNameJazz StyleName = "jazz" + StyleNamePuzzle StyleName = "puzzle" + StyleNameHypno StyleName = "hypno" +) + +// Styles maps BorderStyle to StyleName +var Styles = map[BorderStyle]StyleName{ + StyleNone: StyleNameNothing, + StyleASCII: StyleNameASCII, + StyleLight: StyleNameLight, + StyleHeavy: StyleNameHeavy, + StyleDouble: StyleNameDouble, + StyleDoubleLong: StyleNameDoubleLong, + StyleLightHeavy: StyleNameLightHeavy, + StyleHeavyLight: StyleNameHeavyLight, + StyleLightDouble: StyleNameLightDouble, + StyleDoubleLight: StyleNameDoubleLight, + StyleRounded: StyleNameRounded, + StyleMarkdown: StyleNameMarkdown, + StyleGraphical: StyleNameGraphical, + StyleMerger: StyleNameMerger, + StyleDefault: StyleNameLight, + StyleDotted: StyleNameDotted, + StyleArrow: StyleNameArrow, + StyleStarry: StyleNameStarry, + StyleHearts: StyleNameHearts, + StyleCircuit: StyleNameCircuit, + StyleNature: StyleNameNature, + StyleArtistic: StyleNameArtistic, + Style8Bit: StyleName8Bit, + StyleChaos: StyleNameChaos, + StyleDots: StyleNameDots, + StyleBlocks: StyleNameBlocks, + StyleZen: StyleNameZen, + StyleVintage: StyleNameVintage, + StyleSketch: StyleNameSketch, + StyleArrowDouble: StyleNameArrowDouble, + StyleCelestial: StyleNameCelestial, + StyleCyber: StyleNameCyber, + StyleRunic: StyleNameRunic, + StyleIndustrial: StyleNameIndustrial, + StyleInk: StyleNameInk, + StyleArcade: StyleNameArcade, + StyleBlossom: StyleNameBlossom, + StyleFrosted: StyleNameFrosted, + StyleMosaic: StyleNameMosaic, + StyleUFO: StyleNameUFO, + StyleSteampunk: StyleNameSteampunk, + StyleGalaxy: StyleNameGalaxy, + StyleJazz: StyleNameJazz, + StylePuzzle: StyleNamePuzzle, + StyleHypno: StyleNameHypno, +} + +// String returns the string representation of a border style +func (s BorderStyle) String() string { + return [...]string{ + "None", + "ASCII", + "Light", + "Heavy", + "Double", + "DoubleLong", + "LightHeavy", + "HeavyLight", + "LightDouble", + "DoubleLight", + "Rounded", + "Markdown", + "Graphical", + "Merger", + "Default", + "Dotted", + "Arrow", + "Starry", + "Hearts", + "Circuit", + "Nature", + "Artistic", + "8Bit", + "Chaos", + "Dots", + "Blocks", + "Zen", + "Vintage", + "Sketch", + "ArrowDouble", + "Celestial", + "Cyber", + "Runic", + "Industrial", + "Ink", + "Arcade", + "Blossom", + "Frosted", + "Mosaic", + "UFO", + "Steampunk", + "Galaxy", + "Jazz", + "Puzzle", + "Hypno", + }[s] +} + +// NewSymbols creates a new Symbols instance with the specified style +func NewSymbols(style BorderStyle) Symbols { + switch style { + case StyleASCII: + return &Glyphs{ + name: StyleNameASCII, + row: "-", + column: "|", + center: "+", + corners: [9]string{ + "+", "+", "+", + "+", "+", "+", + "+", "+", "+", + }, + headerLeft: "+", + headerMid: "+", + headerRight: "+", + } + case StyleLight, StyleDefault: + return &Glyphs{ + name: StyleNameLight, + row: "─", + column: "│", + center: "┼", + corners: [9]string{ + "┌", "┬", "┐", + "├", "┼", "┤", + "└", "┴", "┘", + }, + headerLeft: "├", + headerMid: "┼", + headerRight: "┤", + } + case StyleHeavy: + return &Glyphs{ + name: StyleNameHeavy, + row: "━", + column: "┃", + center: "╋", + corners: [9]string{ + "┏", "┳", "┓", + "┣", "╋", "┫", + "┗", "┻", "┛", + }, + headerLeft: "┣", + headerMid: "╋", + headerRight: "┫", + } + case StyleDouble: + return &Glyphs{ + name: StyleNameDouble, + row: "═", + column: "║", + center: "╬", + corners: [9]string{ + "╔", "╦", "╗", + "╠", "╬", "╣", + "╚", "╩", "╝", + }, + headerLeft: "╠", + headerMid: "╬", + headerRight: "╣", + } + case StyleDoubleLong: + return &Glyphs{ + name: StyleNameDoubleLong, + row: "═╡═", + column: "╞", + center: "╪", + corners: [9]string{ + "╔═╡", "═╤═", "╡═╗", + "╟ ", "╪ ", " ╢", + "╚═╡", "═╧═", "╡═╝", + }, + headerLeft: "╟═╡", + headerMid: "╪═╡", + headerRight: "╡═╢", + } + case StyleLightHeavy: + return &Glyphs{ + name: StyleNameLightHeavy, + row: "─", + column: "┃", + center: "╂", + corners: [9]string{ + "┍", "┯", "┑", + "┝", "╂", "┥", + "┕", "┷", "┙", + }, + headerLeft: "┝", + headerMid: "╂", + headerRight: "┥", + } + case StyleHeavyLight: + return &Glyphs{ + name: StyleNameHeavyLight, + row: "━", + column: "│", + center: "┿", + corners: [9]string{ + "┎", "┰", "┒", + "┠", "┿", "┨", + "┖", "┸", "┚", + }, + headerLeft: "┠", + headerMid: "┿", + headerRight: "┨", + } + case StyleLightDouble: + return &Glyphs{ + name: StyleNameLightDouble, + row: "─", + column: "║", + center: "╫", + corners: [9]string{ + "╓", "╥", "╖", + "╟", "╫", "╢", + "╙", "╨", "╜", + }, + headerLeft: "╟", + headerMid: "╫", + headerRight: "╢", + } + case StyleDoubleLight: + return &Glyphs{ + name: StyleNameDoubleLight, + row: "═", + column: "│", + center: "╪", + corners: [9]string{ + "╒", "╤", "╕", + "╞", "╪", "╡", + "╘", "╧", "╛", + }, + headerLeft: "╞", + headerMid: "╪", + headerRight: "╡", + } + case StyleRounded: + return &Glyphs{ + name: StyleNameRounded, + row: "─", + column: "│", + center: "┼", + corners: [9]string{ + "╭", "┬", "╮", + "├", "┼", "┤", + "╰", "┴", "╯", + }, + headerLeft: "├", + headerMid: "┼", + headerRight: "┤", + } + case StyleMarkdown: + return &Glyphs{ + name: StyleNameMarkdown, + row: "-", + column: "|", + center: "|", + corners: [9]string{ + "", "", "", + "|", "|", "|", + "", "", "", + }, + headerLeft: "|", + headerMid: "|", + headerRight: "|", + } + case StyleGraphical: + return &Glyphs{ + name: StyleNameGraphical, + row: "┄┄", + column: "┆", + center: "╂", + corners: [9]string{ + "┌┄", "┄┄", "┄┐", + "┆ ", "╂ ", " ┆", + "└┄", "┄┄", "┄┘", + }, + headerLeft: "├┄", + headerMid: "╂┄", + headerRight: "┄┤", + } + case StyleMerger: + return &Glyphs{ + name: StyleNameMerger, + row: "─", + column: "│", + center: "+", + corners: [9]string{ + "┌", "┬", "┐", + "├", "┼", "┤", + "└", "┴", "┘", + }, + headerLeft: "├", + headerMid: "+", + headerRight: "┤", + } + case StyleDotted: + return &Glyphs{ + name: StyleNameDotted, + row: "·", + column: ":", + center: "+", + corners: [9]string{ + ".", "·", ".", + ":", "+", ":", + "'", "·", "'", + }, + headerLeft: ":", + headerMid: "+", + headerRight: ":", + } + case StyleArrow: + return &Glyphs{ + name: StyleNameArrow, + row: "→", + column: "↓", + center: "↔", + corners: [9]string{ + "↗", "↑", "↖", + "→", "↔", "←", + "↘", "↓", "↙", + }, + headerLeft: "→", + headerMid: "↔", + headerRight: "←", + } + case StyleStarry: + return &Glyphs{ + name: StyleNameStarry, + row: "★", + column: "☆", + center: "✶", + corners: [9]string{ + "✧", "✯", "✧", + "✦", "✶", "✦", + "✧", "✯", "✧", + }, + headerLeft: "✦", + headerMid: "✶", + headerRight: "✦", + } + case StyleHearts: + return &Glyphs{ + name: StyleNameHearts, + row: "♥", + column: "❤", + center: "✚", + corners: [9]string{ + "❥", "♡", "❥", + "❣", "✚", "❣", + "❦", "♡", "❦", + }, + headerLeft: "❣", + headerMid: "✚", + headerRight: "❣", + } + case StyleCircuit: + return &Glyphs{ + name: StyleNameCircuit, + row: "=", + column: "||", + center: "<>", + corners: [9]string{ + "/*", "##", "*/", + "//", "<>", "\\", + "\\*", "##", "*/", + }, + headerLeft: "//", + headerMid: "<>", + headerRight: "\\", + } + case StyleNature: + return &Glyphs{ + name: StyleNameNature, + row: "~", + column: "|", + center: "❀", + corners: [9]string{ + "🌱", "🌿", "🌱", + "🍃", "❀", "🍃", + "🌻", "🌾", "🌻", + }, + headerLeft: "🍃", + headerMid: "❀", + headerRight: "🍃", + } + case StyleArtistic: + return &Glyphs{ + name: StyleNameArtistic, + row: "▬", + column: "▐", + center: "⬔", + corners: [9]string{ + "◈", "◊", "◈", + "◀", "⬔", "▶", + "◭", "▣", "◮", + }, + headerLeft: "◀", + headerMid: "⬔", + headerRight: "▶", + } + case Style8Bit: + return &Glyphs{ + name: StyleName8Bit, + row: "■", + column: "█", + center: "♦", + corners: [9]string{ + "╔", "▲", "╗", + "◄", "♦", "►", + "╚", "▼", "╝", + }, + headerLeft: "◄", + headerMid: "♦", + headerRight: "►", + } + case StyleChaos: + return &Glyphs{ + name: StyleNameChaos, + row: "≈", + column: "§", + center: "☯", + corners: [9]string{ + "⌘", "∞", "⌥", + "⚡", "☯", "♞", + "⌂", "∆", "◊", + }, + headerLeft: "⚡", + headerMid: "☯", + headerRight: "♞", + } + case StyleDots: + return &Glyphs{ + name: StyleNameDots, + row: "·", + column: " ", + center: "·", + corners: [9]string{ + "·", "·", "·", + " ", "·", " ", + "·", "·", "·", + }, + headerLeft: " ", + headerMid: "·", + headerRight: " ", + } + case StyleBlocks: + return &Glyphs{ + name: StyleNameBlocks, + row: "▀", + column: "█", + center: "█", + corners: [9]string{ + "▛", "▀", "▜", + "▌", "█", "▐", + "▙", "▄", "▟", + }, + headerLeft: "▌", + headerMid: "█", + headerRight: "▐", + } + case StyleZen: + return &Glyphs{ + name: StyleNameZen, + row: "~", + column: " ", + center: "☯", + corners: [9]string{ + " ", "♨", " ", + " ", "☯", " ", + " ", "♨", " ", + }, + headerLeft: " ", + headerMid: "☯", + headerRight: " ", + } + case StyleVintage: + return &Glyphs{ + name: StyleNameVintage, + row: "────", + column: " ⁜ ", + center: " ✠ ", + corners: [9]string{ + "╔══", "══╤", "══╗", + " ⁜ ", " ✠ ", " ⁜ ", + "╚══", "══╧", "══╝", + }, + headerLeft: " ├─", + headerMid: "─✠─", + headerRight: "─┤ ", + } + case StyleSketch: + return &Glyphs{ + name: StyleNameSketch, + row: "~~", + column: "/", + center: "+", + corners: [9]string{ + " .", "~~", ". ", + "/ ", "+ ", " \\", + " '", "~~", "` ", + }, + headerLeft: "/~", + headerMid: "+~", + headerRight: "~\\", + } + case StyleArrowDouble: + return &Glyphs{ + name: StyleNameArrowDouble, + row: "»»", + column: "⫸", + center: "✿", + corners: [9]string{ + "⌜»", "»»", "»⌝", + "⫸ ", "✿ ", " ⫷", + "⌞»", "»»", "»⌟", + }, + headerLeft: "⫸»", + headerMid: "✿»", + headerRight: "»⫷", + } + case StyleCelestial: + return &Glyphs{ + name: StyleNameCelestial, + row: "✦✧", + column: "☽", + center: "☀", + corners: [9]string{ + "✧✦", "✦✧", "✦✧", + "☽ ", "☀ ", " ☾", + "✧✦", "✦✧", "✦✧", + }, + headerLeft: "☽✦", + headerMid: "☀✧", + headerRight: "✦☾", + } + case StyleCyber: + return &Glyphs{ + name: StyleNameCyber, + row: "═╦═", + column: "║", + center: "╬", + corners: [9]string{ + "╔╦═", "╦═╦", "═╦╗", + "║ ", "╬ ", " ║", + "╚╩═", "╩═╩", "═╩╝", + }, + headerLeft: "╠╦═", + headerMid: "╬═╦", + headerRight: "═╦╣", + } + case StyleRunic: + return &Glyphs{ + name: StyleNameRunic, + row: "ᛖᛖᛖ", + column: "ᛟ", + center: "ᛞ", + corners: [9]string{ + "ᛏᛖᛖ", "ᛖᛖᛖ", "ᛖᛖᛏ", + "ᛟ ", "ᛞ ", " ᛟ", + "ᛗᛖᛖ", "ᛖᛖᛖ", "ᛖᛖᛗ", + }, + headerLeft: "ᛟᛖᛖ", + headerMid: "ᛞᛖᛖ", + headerRight: "ᛖᛖᛟ", + } + case StyleIndustrial: + return &Glyphs{ + name: StyleNameIndustrial, + row: "━╋━", + column: "┃", + center: "╋", + corners: [9]string{ + "┏╋━", "╋━╋", "━╋┓", + "┃ ", "╋ ", " ┃", + "┗╋━", "╋━╋", "━╋┛", + }, + headerLeft: "┣╋━", + headerMid: "╋━╋", + headerRight: "━╋┫", + } + case StyleInk: + return &Glyphs{ + name: StyleNameInk, + row: "﹌", + column: "︱", + center: "✒", + corners: [9]string{ + "﹏", "﹌", "﹏", + "︱ ", "✒ ", " ︱", + "﹋", "﹌", "﹋", + }, + headerLeft: "︱﹌", + headerMid: "✒﹌", + headerRight: "﹌︱", + } + case StyleArcade: + return &Glyphs{ + name: StyleNameArcade, + row: "■□", + column: "▐", + center: "◉", + corners: [9]string{ + "▞■", "■□", "□▚", + "▐ ", "◉ ", " ▐", + "▚■", "■□", "□▞", + }, + headerLeft: "▐■", + headerMid: "◉□", + headerRight: "■▐", + } + case StyleBlossom: + return &Glyphs{ + name: StyleNameBlossom, + row: "🌸", + column: "🌿", + center: "✿", + corners: [9]string{ + "🌷", "🌸", "🌷", + "🌿", "✿", "🌿", + "🌱", "🌸", "🌱", + }, + headerLeft: "🌿🌸", + headerMid: "✿🌸", + headerRight: "🌸🌿", + } + case StyleFrosted: + return &Glyphs{ + name: StyleNameFrosted, + row: "░▒░", + column: "▓", + center: "◍", + corners: [9]string{ + "◌░▒", "░▒░", "▒░◌", + "▓ ", "◍ ", " ▓", + "◌░▒", "░▒░", "▒░◌", + }, + headerLeft: "▓░▒", + headerMid: "◍▒░", + headerRight: "░▒▓", + } + case StyleMosaic: + return &Glyphs{ + name: StyleNameMosaic, + row: "▰▱", + column: "⧉", + center: "⬖", + corners: [9]string{ + "⧠▰", "▰▱", "▱⧠", + "⧉ ", "⬖ ", " ⧉", + "⧅▰", "▰▱", "▱⧅", + }, + headerLeft: "⧉▰", + headerMid: "⬖▱", + headerRight: "▰⧉", + } + case StyleUFO: + return &Glyphs{ + name: StyleNameUFO, + row: "⊚⊚", + column: "☽", + center: "☢", + corners: [9]string{ + "⌖⊚", "⊚⊚", "⊚⌖", + "☽ ", "☢ ", " ☽", + "⌗⊚", "⊚⊚", "⊚⌗", + }, + headerLeft: "☽⊚", + headerMid: "☢⊚", + headerRight: "⊚☽", + } + case StyleSteampunk: + return &Glyphs{ + name: StyleNameSteampunk, + row: "═⚙═", + column: "⛓️", + center: "⚔️", + corners: [9]string{ + "🜂⚙═", "═⚙═", "═⚙🜂", + "⛓️ ", "⚔️ ", " ⛓️", + "🜄⚙═", "═⚙═", "═⚙🜄", + }, + headerLeft: "⛓️⚙═", + headerMid: "⚔️═⚙", + headerRight: "═⚙⛓️", + } + case StyleGalaxy: + return &Glyphs{ + name: StyleNameGalaxy, + row: "≋≋", + column: "♆", + center: "☄️", + corners: [9]string{ + "⌇≋", "≋≋", "≋⌇", + "♆ ", "☄️ ", " ♆", + "⌇≋", "≋≋", "≋⌇", + }, + headerLeft: "♆≋", + headerMid: "☄️≋", + headerRight: "≋♆", + } + case StyleJazz: + return &Glyphs{ + name: StyleNameJazz, + row: "♬♬", + column: "▷", + center: "★", + corners: [9]string{ + "♔♬", "♬♬", "♬♔", + "▷ ", "★ ", " ◁", + "♕♬", "♬♬", "♬♕", + }, + headerLeft: "▷♬", + headerMid: "★♬", + headerRight: "♬◁", + } + case StylePuzzle: + return &Glyphs{ + name: StyleNamePuzzle, + row: "▣▣", + column: "◫", + center: "✚", + corners: [9]string{ + "◩▣", "▣▣", "▣◪", + "◫ ", "✚ ", " ◫", + "◧▣", "▣▣", "▣◨", + }, + headerLeft: "◫▣", + headerMid: "✚▣", + headerRight: "▣◫", + } + case StyleHypno: + return &Glyphs{ + name: StyleNameHypno, + row: "◜◝", + column: "꩜", + center: "⃰", + corners: [9]string{ + "◟◜", "◜◝", "◝◞", + "꩜ ", "⃰ ", " ꩜", + "◟◜", "◜◝", "◝◞", + }, + headerLeft: "꩜◜", + headerMid: "⃰◝", + headerRight: "◜꩜", + } + default: + return &Glyphs{ + name: StyleNameNothing, + row: "", + column: "", + center: "", + corners: [9]string{ + "", "", "", + "", "", "", + "", "", "", + }, + headerLeft: "", + headerMid: "", + headerRight: "", + } + } +} + +// SymbolCustom implements the Symbols interface with fully configurable symbols +type SymbolCustom struct { + name string + center string + row string + column string + topLeft string + topMid string + topRight string + midLeft string + midRight string + bottomLeft string + bottomMid string + bottomRight string + headerLeft string + headerMid string + headerRight string +} + +// NewSymbolCustom creates a new customizable border style +func NewSymbolCustom(name string) *SymbolCustom { + return &SymbolCustom{ + name: name, + center: "+", + row: "-", + column: "|", + } +} + +// Implement all Symbols interface methods +func (c *SymbolCustom) Name() string { return c.name } +func (c *SymbolCustom) Center() string { return c.center } +func (c *SymbolCustom) Row() string { return c.row } +func (c *SymbolCustom) Column() string { return c.column } +func (c *SymbolCustom) TopLeft() string { return c.topLeft } +func (c *SymbolCustom) TopMid() string { return c.topMid } +func (c *SymbolCustom) TopRight() string { return c.topRight } +func (c *SymbolCustom) MidLeft() string { return c.midLeft } +func (c *SymbolCustom) MidRight() string { return c.midRight } +func (c *SymbolCustom) BottomLeft() string { return c.bottomLeft } +func (c *SymbolCustom) BottomMid() string { return c.bottomMid } +func (c *SymbolCustom) BottomRight() string { return c.bottomRight } +func (c *SymbolCustom) HeaderLeft() string { return c.headerLeft } +func (c *SymbolCustom) HeaderMid() string { return c.headerMid } +func (c *SymbolCustom) HeaderRight() string { return c.headerRight } + +// Builder methods for fluent configuration +func (c *SymbolCustom) WithCenter(s string) *SymbolCustom { c.center = s; return c } +func (c *SymbolCustom) WithRow(s string) *SymbolCustom { c.row = s; return c } +func (c *SymbolCustom) WithColumn(s string) *SymbolCustom { c.column = s; return c } +func (c *SymbolCustom) WithTopLeft(s string) *SymbolCustom { c.topLeft = s; return c } +func (c *SymbolCustom) WithTopMid(s string) *SymbolCustom { c.topMid = s; return c } +func (c *SymbolCustom) WithTopRight(s string) *SymbolCustom { c.topRight = s; return c } +func (c *SymbolCustom) WithMidLeft(s string) *SymbolCustom { c.midLeft = s; return c } +func (c *SymbolCustom) WithMidRight(s string) *SymbolCustom { c.midRight = s; return c } +func (c *SymbolCustom) WithBottomLeft(s string) *SymbolCustom { c.bottomLeft = s; return c } +func (c *SymbolCustom) WithBottomMid(s string) *SymbolCustom { c.bottomMid = s; return c } +func (c *SymbolCustom) WithBottomRight(s string) *SymbolCustom { c.bottomRight = s; return c } +func (c *SymbolCustom) WithHeaderLeft(s string) *SymbolCustom { c.headerLeft = s; return c } +func (c *SymbolCustom) WithHeaderMid(s string) *SymbolCustom { c.headerMid = s; return c } +func (c *SymbolCustom) WithHeaderRight(s string) *SymbolCustom { c.headerRight = s; return c } + +// Preview renders a small sample table to visualize the border style +func (s *SymbolCustom) Preview() string { + return fmt.Sprintf( + "%s%s%s\n%s %s %s\n%s%s%s", + s.TopLeft(), s.Row(), s.TopRight(), + s.Column(), s.Center(), s.Column(), + s.BottomLeft(), s.Row(), s.BottomRight(), + ) +} + +// Glyphs provides fully independent border symbols with a corners array +type Glyphs struct { + name StyleName + row string + column string + center string + corners [9]string // [TopLeft, TopMid, TopRight, MidLeft, Center, MidRight, BottomLeft, BottomMid, BottomRight] + headerLeft string + headerMid string + headerRight string +} + +// Glyphs symbol methods +func (s *Glyphs) Name() string { return s.name.String() } +func (s *Glyphs) Center() string { return s.center } +func (s *Glyphs) Row() string { return s.row } +func (s *Glyphs) Column() string { return s.column } +func (s *Glyphs) TopLeft() string { return s.corners[0] } +func (s *Glyphs) TopMid() string { return s.corners[1] } +func (s *Glyphs) TopRight() string { return s.corners[2] } +func (s *Glyphs) MidLeft() string { return s.corners[3] } +func (s *Glyphs) MidRight() string { return s.corners[5] } +func (s *Glyphs) BottomLeft() string { return s.corners[6] } +func (s *Glyphs) BottomMid() string { return s.corners[7] } +func (s *Glyphs) BottomRight() string { return s.corners[8] } +func (s *Glyphs) HeaderLeft() string { return s.headerLeft } +func (s *Glyphs) HeaderMid() string { return s.headerMid } +func (s *Glyphs) HeaderRight() string { return s.headerRight } + +// Preview renders a small sample table to visualize the border style +func (s *Glyphs) Preview() string { + return fmt.Sprintf( + "%s%s%s\n%s %s %s\n%s%s%s", + s.TopLeft(), s.Row(), s.TopRight(), + s.Column(), s.Center(), s.Column(), + s.BottomLeft(), s.Row(), s.BottomRight(), + ) +} diff --git a/vendor/github.com/olekukonko/tablewriter/tw/tw.go b/vendor/github.com/olekukonko/tablewriter/tw/tw.go new file mode 100644 index 00000000..f1cbb9e5 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/tw.go @@ -0,0 +1,107 @@ +package tw + +// Operation Status Constants +// Used to indicate the success or failure of operations +const ( + Pending = 0 // Operation failed + Fail = -1 // Operation failed + Success = 1 // Operation succeeded + + MinimumColumnWidth = 8 +) + +const ( + Empty = "" + Skip = "" + Space = " " + NewLine = "\n" + Column = ":" + Dash = "-" +) + +// Feature State Constants +// Represents enabled/disabled states for features +const ( + Unknown State = Pending // Feature is enabled + On State = Success // Feature is enabled + Off State = Fail // Feature is disabled +) + +// Table Alignment Constants +// Defines text alignment options for table content +const ( + AlignNone Align = "none" // Center-aligned text + AlignCenter Align = "center" // Center-aligned text + AlignRight Align = "right" // Right-aligned text + AlignLeft Align = "left" // Left-aligned text + AlignDefault = AlignLeft // Left-aligned text +) + +const ( + Header Position = "header" // Table header section + Row Position = "row" // Table row section + Footer Position = "footer" // Table footer section +) + +const ( + LevelHeader Level = iota // Topmost line position + LevelBody // LevelBody line position + LevelFooter // LevelFooter line position +) + +const ( + LocationFirst Location = "first" // Topmost line position + LocationMiddle Location = "middle" // LevelBody line position + LocationEnd Location = "end" // LevelFooter line position +) + +const ( + SectionHeader = "header" + SectionRow = "row" + SectionFooter = "footer" +) + +// Text Wrapping Constants +// Defines text wrapping behavior in table cells +const ( + WrapNone = iota // No wrapping + WrapNormal // Standard word wrapping + WrapTruncate // Truncate text with ellipsis + WrapBreak // Break words to fit +) + +// Cell Merge Constants +// Specifies cell merging behavior in tables + +const ( + MergeNone = iota // No merging + MergeVertical // Merge cells vertically + MergeHorizontal // Merge cells horizontally + MergeBoth // Merge both vertically and horizontally + MergeHierarchical // Hierarchical merging +) + +// Special Character Constants +// Defines special characters used in formatting +const ( + CharEllipsis = "…" // Ellipsis character for truncation + CharBreak = "↩" // Break character for wrapping +) + +type Spot int + +const ( + SpotNone Spot = iota + SpotTopLeft + SpotTopCenter + SpotTopRight + SpotBottomLeft + SpotBottomCenter // Default for legacy SetCaption + SpotBottomRight + SpotLeftTop + SpotLeftCenter + SpotLeftBottom + SpotRightTop + SpotRightCenter + SpotRIghtBottom +) diff --git a/vendor/github.com/olekukonko/tablewriter/tw/types.go b/vendor/github.com/olekukonko/tablewriter/tw/types.go new file mode 100644 index 00000000..29a1862c --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/tw/types.go @@ -0,0 +1,199 @@ +// Package tw defines types and constants for table formatting and configuration, +// including validation logic for various table properties. +package tw + +import ( + "fmt" + "github.com/olekukonko/errors" + "strings" +) // Custom error handling library + +// Position defines where formatting applies in the table (e.g., header, footer, or rows). +type Position string + +// Validate checks if the Position is one of the allowed values: Header, Footer, or Row. +func (pos Position) Validate() error { + switch pos { + case Header, Footer, Row: + return nil // Valid position + } + // Return an error for any unrecognized position + return errors.New("invalid position") +} + +// Filter defines a function type for processing cell content. +// It takes a slice of strings (representing cell data) and returns a processed slice. +type Filter func([]string) []string + +// Formatter defines an interface for types that can format themselves into a string. +// Used for custom formatting of table cell content. +type Formatter interface { + Format() string // Returns the formatted string representation +} + +// Align specifies the text alignment within a table cell. +type Align string + +// Validate checks if the Align is one of the allowed values: None, Center, Left, or Right. +func (a Align) Validate() error { + switch a { + case AlignNone, AlignCenter, AlignLeft, AlignRight: + return nil // Valid alignment + } + // Return an error for any unrecognized alignment + return errors.New("invalid align") +} + +type Alignment []Align + +func (a Alignment) String() string { + var str strings.Builder + for i, a := range a { + if i > 0 { + str.WriteString("; ") + } + str.WriteString(fmt.Sprint(i)) + str.WriteString("=") + str.WriteString(string(a)) + } + return str.String() +} + +func (a Alignment) Add(aligns ...Align) Alignment { + aa := make(Alignment, len(aligns)) + copy(aa, aligns) + return aa +} + +func (a Alignment) Set(col int, align Align) Alignment { + if col >= 0 && col < len(a) { + a[col] = align + } + return a +} + +// Copy creates a new independent copy of the Alignment +func (a Alignment) Copy() Alignment { + aa := make(Alignment, len(a)) + copy(aa, a) + return aa +} + +// Level indicates the vertical position of a line in the table (e.g., header, body, or footer). +type Level int + +// Validate checks if the Level is one of the allowed values: Header, Body, or Footer. +func (l Level) Validate() error { + switch l { + case LevelHeader, LevelBody, LevelFooter: + return nil // Valid level + } + // Return an error for any unrecognized level + return errors.New("invalid level") +} + +// Location specifies the horizontal position of a cell or column within a table row. +type Location string + +// Validate checks if the Location is one of the allowed values: First, Middle, or End. +func (l Location) Validate() error { + switch l { + case LocationFirst, LocationMiddle, LocationEnd: + return nil // Valid location + } + // Return an error for any unrecognized location + return errors.New("invalid location") +} + +type Caption struct { + Text string + Spot Spot + Align Align + Width int +} + +func (c Caption) WithText(text string) Caption { + c.Text = text + return c +} + +func (c Caption) WithSpot(spot Spot) Caption { + c.Spot = spot + return c +} + +func (c Caption) WithAlign(align Align) Caption { + c.Align = align + return c +} + +func (c Caption) WithWidth(width int) Caption { + c.Width = width + return c +} + +type Control struct { + Hide State +} + +// Compact configures compact width optimization for merged cells. +type Compact struct { + Merge State // Merge enables compact width calculation during cell merging, optimizing space allocation. +} + +// Behavior defines settings that control table rendering behaviors, such as column visibility and content formatting. +type Behavior struct { + AutoHide State // AutoHide determines whether empty columns are hidden. Ignored in streaming mode. + TrimSpace State // TrimSpace enables trimming of leading and trailing spaces from cell content. + + Header Control // Header specifies control settings for the table header. + Footer Control // Footer specifies control settings for the table footer. + + // Compact enables optimized width calculation for merged cells, such as in horizontal merges, + // by systematically determining the most efficient width instead of scaling by the number of columns. + Compact Compact +} + +// Padding defines the spacing characters around cell content in all four directions. +// A zero-value Padding struct will use the table's default padding unless Overwrite is true. +type Padding struct { + Left string + Right string + Top string + Bottom string + + // Overwrite forces tablewriter to use this padding configuration exactly as specified, + // even when empty. When false (default), empty Padding fields will inherit defaults. + // + // For explicit no-padding, use the PaddingNone constant instead of setting Overwrite. + Overwrite bool +} + +// Common padding configurations for convenience + +// Equals reports whether two Padding configurations are identical in all fields. +// This includes comparing the Overwrite flag as part of the equality check. +func (p Padding) Equals(padding Padding) bool { + return p.Left == padding.Left && + p.Right == padding.Right && + p.Top == padding.Top && + p.Bottom == padding.Bottom && + p.Overwrite == padding.Overwrite +} + +// Empty reports whether all padding strings are empty (all fields == ""). +// Note that an Empty padding may still take effect if Overwrite is true. +func (p Padding) Empty() bool { + return p.Left == "" && p.Right == "" && p.Top == "" && p.Bottom == "" +} + +// Paddable reports whether this Padding configuration should override existing padding. +// Returns true if either: +// - Any padding string is non-empty (!p.Empty()) +// - Overwrite flag is true (even with all strings empty) +// +// This is used internally during configuration merging to determine whether to +// apply the padding settings. +func (p Padding) Paddable() bool { + return !p.Empty() || p.Overwrite +} diff --git a/vendor/github.com/olekukonko/tablewriter/util.go b/vendor/github.com/olekukonko/tablewriter/util.go deleted file mode 100644 index 380e7ab3..00000000 --- a/vendor/github.com/olekukonko/tablewriter/util.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 Oleku Konko All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. - -// This module is a Table Writer API for the Go Programming Language. -// The protocols were written in pure Go and works on windows and unix systems - -package tablewriter - -import ( - "math" - "regexp" - "strings" - - "github.com/mattn/go-runewidth" -) - -var ansi = regexp.MustCompile("\033\\[(?:[0-9]{1,3}(?:;[0-9]{1,3})*)?[m|K]") - -func DisplayWidth(str string) int { - return runewidth.StringWidth(ansi.ReplaceAllLiteralString(str, "")) -} - -// Simple Condition for string -// Returns value based on condition -func ConditionString(cond bool, valid, inValid string) string { - if cond { - return valid - } - return inValid -} - -func isNumOrSpace(r rune) bool { - return ('0' <= r && r <= '9') || r == ' ' -} - -// Format Table Header -// Replace _ , . and spaces -func Title(name string) string { - origLen := len(name) - rs := []rune(name) - for i, r := range rs { - switch r { - case '_': - rs[i] = ' ' - case '.': - // ignore floating number 0.0 - if (i != 0 && !isNumOrSpace(rs[i-1])) || (i != len(rs)-1 && !isNumOrSpace(rs[i+1])) { - rs[i] = ' ' - } - } - } - name = string(rs) - name = strings.TrimSpace(name) - if len(name) == 0 && origLen > 0 { - // Keep at least one character. This is important to preserve - // empty lines in multi-line headers/footers. - name = " " - } - return strings.ToUpper(name) -} - -// Pad String -// Attempts to place string in the center -func Pad(s, pad string, width int) string { - gap := width - DisplayWidth(s) - if gap > 0 { - gapLeft := int(math.Ceil(float64(gap / 2))) - gapRight := gap - gapLeft - return strings.Repeat(string(pad), gapLeft) + s + strings.Repeat(string(pad), gapRight) - } - return s -} - -// Pad String Right position -// This would place string at the left side of the screen -func PadRight(s, pad string, width int) string { - gap := width - DisplayWidth(s) - if gap > 0 { - return s + strings.Repeat(string(pad), gap) - } - return s -} - -// Pad String Left position -// This would place string at the right side of the screen -func PadLeft(s, pad string, width int) string { - gap := width - DisplayWidth(s) - if gap > 0 { - return strings.Repeat(string(pad), gap) + s - } - return s -} diff --git a/vendor/github.com/olekukonko/tablewriter/wrap.go b/vendor/github.com/olekukonko/tablewriter/wrap.go deleted file mode 100644 index a092ee1f..00000000 --- a/vendor/github.com/olekukonko/tablewriter/wrap.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 Oleku Konko All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. - -// This module is a Table Writer API for the Go Programming Language. -// The protocols were written in pure Go and works on windows and unix systems - -package tablewriter - -import ( - "math" - "strings" - - "github.com/mattn/go-runewidth" -) - -var ( - nl = "\n" - sp = " " -) - -const defaultPenalty = 1e5 - -// Wrap wraps s into a paragraph of lines of length lim, with minimal -// raggedness. -func WrapString(s string, lim int) ([]string, int) { - words := strings.Split(strings.Replace(s, nl, sp, -1), sp) - var lines []string - max := 0 - for _, v := range words { - max = runewidth.StringWidth(v) - if max > lim { - lim = max - } - } - for _, line := range WrapWords(words, 1, lim, defaultPenalty) { - lines = append(lines, strings.Join(line, sp)) - } - return lines, lim -} - -// WrapWords is the low-level line-breaking algorithm, useful if you need more -// control over the details of the text wrapping process. For most uses, -// WrapString will be sufficient and more convenient. -// -// WrapWords splits a list of words into lines with minimal "raggedness", -// treating each rune as one unit, accounting for spc units between adjacent -// words on each line, and attempting to limit lines to lim units. Raggedness -// is the total error over all lines, where error is the square of the -// difference of the length of the line and lim. Too-long lines (which only -// happen when a single word is longer than lim units) have pen penalty units -// added to the error. -func WrapWords(words []string, spc, lim, pen int) [][]string { - n := len(words) - - length := make([][]int, n) - for i := 0; i < n; i++ { - length[i] = make([]int, n) - length[i][i] = runewidth.StringWidth(words[i]) - for j := i + 1; j < n; j++ { - length[i][j] = length[i][j-1] + spc + runewidth.StringWidth(words[j]) - } - } - nbrk := make([]int, n) - cost := make([]int, n) - for i := range cost { - cost[i] = math.MaxInt32 - } - for i := n - 1; i >= 0; i-- { - if length[i][n-1] <= lim { - cost[i] = 0 - nbrk[i] = n - } else { - for j := i + 1; j < n; j++ { - d := lim - length[i][j-1] - c := d*d + cost[j] - if length[i][j-1] > lim { - c += pen // too-long lines get a worse penalty - } - if c < cost[i] { - cost[i] = c - nbrk[i] = j - } - } - } - } - var lines [][]string - i := 0 - for i < n { - lines = append(lines, words[i:nbrk[i]]) - i = nbrk[i] - } - return lines -} - -// getLines decomposes a multiline string into a slice of strings. -func getLines(s string) []string { - return strings.Split(s, nl) -} diff --git a/vendor/github.com/olekukonko/tablewriter/zoo.go b/vendor/github.com/olekukonko/tablewriter/zoo.go new file mode 100644 index 00000000..b24f230c --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/zoo.go @@ -0,0 +1,1696 @@ +package tablewriter + +import ( + "database/sql" + "fmt" + "github.com/olekukonko/errors" + "github.com/olekukonko/tablewriter/pkg/twwidth" + "github.com/olekukonko/tablewriter/tw" + "io" + "math" + "reflect" + "strconv" + "strings" +) + +// applyHierarchicalMerges applies hierarchical merges to row content. +// Parameters ctx and mctx hold rendering and merge state. +// No return value. +func (t *Table) applyHierarchicalMerges(ctx *renderContext, mctx *mergeContext) { + ctx.logger.Debug("Applying hierarchical merges (left-to-right vertical flow - snapshot comparison)") + if len(ctx.rowLines) <= 1 { + ctx.logger.Debug("Skipping hierarchical merges - less than 2 rows") + return + } + numCols := ctx.numCols + + originalRowLines := make([][][]string, len(ctx.rowLines)) + for i, row := range ctx.rowLines { + originalRowLines[i] = make([][]string, len(row)) + for j, line := range row { + originalRowLines[i][j] = make([]string, len(line)) + copy(originalRowLines[i][j], line) + } + } + ctx.logger.Debug("Created snapshot of original row data for hierarchical merge comparison.") + + hMergeStartRow := make(map[int]int) + + for r := 1; r < len(ctx.rowLines); r++ { + leftCellContinuedHierarchical := false + + for c := 0; c < numCols; c++ { + if mctx.rowMerges[r] == nil { + mctx.rowMerges[r] = make(map[int]tw.MergeState) + } + if mctx.rowMerges[r-1] == nil { + mctx.rowMerges[r-1] = make(map[int]tw.MergeState) + } + + canCompare := r > 0 && + len(originalRowLines[r]) > 0 && + len(originalRowLines[r-1]) > 0 + + if !canCompare { + currentState := mctx.rowMerges[r][c] + currentState.Hierarchical = tw.MergeStateOption{} + mctx.rowMerges[r][c] = currentState + ctx.logger.Debugf("HCompare Skipped: r=%d, c=%d - Insufficient data in snapshot", r, c) + leftCellContinuedHierarchical = false + continue + } + + // Join all lines of the cell for comparison + var currentVal, aboveVal string + for _, line := range originalRowLines[r] { + if c < len(line) { + currentVal += line[c] + } + } + for _, line := range originalRowLines[r-1] { + if c < len(line) { + aboveVal += line[c] + } + } + + currentVal = t.Trimmer(currentVal) + aboveVal = t.Trimmer(aboveVal) + + currentState := mctx.rowMerges[r][c] + prevStateAbove := mctx.rowMerges[r-1][c] + + valuesMatch := currentVal == aboveVal && currentVal != "" && currentVal != "-" + hierarchyAllowed := c == 0 || leftCellContinuedHierarchical + shouldContinue := valuesMatch && hierarchyAllowed + + ctx.logger.Debugf("HCompare: r=%d, c=%d; current='%s', above='%s'; match=%v; leftCont=%v; shouldCont=%v", + r, c, currentVal, aboveVal, valuesMatch, leftCellContinuedHierarchical, shouldContinue) + + if shouldContinue { + currentState.Hierarchical.Present = true + currentState.Hierarchical.Start = false + + if prevStateAbove.Hierarchical.Present && !prevStateAbove.Hierarchical.End { + startRow, ok := hMergeStartRow[c] + if !ok { + ctx.logger.Debugf("Hierarchical merge WARNING: Recovering lost start row at r=%d, c=%d. Assuming r-1 was start.", r, c) + startRow = r - 1 + hMergeStartRow[c] = startRow + startState := mctx.rowMerges[startRow][c] + startState.Hierarchical.Present = true + startState.Hierarchical.Start = true + startState.Hierarchical.End = false + mctx.rowMerges[startRow][c] = startState + } + ctx.logger.Debugf("Hierarchical merge CONTINUED row %d, col %d. Block previously started row %d", r, c, startRow) + } else { + startRow := r - 1 + hMergeStartRow[c] = startRow + startState := mctx.rowMerges[startRow][c] + startState.Hierarchical.Present = true + startState.Hierarchical.Start = true + startState.Hierarchical.End = false + mctx.rowMerges[startRow][c] = startState + ctx.logger.Debugf("Hierarchical merge START detected for block ending at or after row %d, col %d (started at row %d)", r, c, startRow) + } + + for lineIdx := range ctx.rowLines[r] { + if c < len(ctx.rowLines[r][lineIdx]) { + ctx.rowLines[r][lineIdx][c] = tw.Empty + } + } + + leftCellContinuedHierarchical = true + } else { + currentState.Hierarchical = tw.MergeStateOption{} + + if startRow, ok := hMergeStartRow[c]; ok { + t.finalizeHierarchicalMergeBlock(ctx, mctx, c, startRow, r-1) + delete(hMergeStartRow, c) + } + + leftCellContinuedHierarchical = false + } + + mctx.rowMerges[r][c] = currentState + } + } + + lastRowIdx := len(ctx.rowLines) - 1 + if lastRowIdx >= 0 { + for c, startRow := range hMergeStartRow { + t.finalizeHierarchicalMergeBlock(ctx, mctx, c, startRow, lastRowIdx) + } + } + ctx.logger.Debug("Hierarchical merge processing completed") +} + +// applyHorizontalMergeWidths adjusts column widths for horizontal merges. +// Parameters include position, ctx for rendering, and mergeStates for merges. +// No return value. +func (t *Table) applyHorizontalMergeWidths(position tw.Position, ctx *renderContext, mergeStates map[int]tw.MergeState) { + if mergeStates == nil { + t.logger.Debugf("applyHorizontalMergeWidths: Skipping %s - no merge states", position) + return + } + t.logger.Debugf("applyHorizontalMergeWidths: Applying HMerge width recalc for %s", position) + + numCols := ctx.numCols + targetWidthsMap := ctx.widths[position] + originalNormalizedWidths := tw.NewMapper[int, int]() + for i := 0; i < numCols; i++ { + originalNormalizedWidths.Set(i, targetWidthsMap.Get(i)) + } + + separatorWidth := 0 + if t.renderer != nil { + rendererConfig := t.renderer.Config() + if rendererConfig.Settings.Separators.BetweenColumns.Enabled() { + separatorWidth = twwidth.Width(rendererConfig.Symbols.Column()) + } + } + + processedCols := make(map[int]bool) + + for col := 0; col < numCols; col++ { + if processedCols[col] { + continue + } + + state, exists := mergeStates[col] + if !exists { + continue + } + + if state.Horizontal.Present && state.Horizontal.Start { + totalWidth := 0 + span := state.Horizontal.Span + t.logger.Debugf(" -> HMerge detected: startCol=%d, span=%d, separatorWidth=%d", col, span, separatorWidth) + + for i := 0; i < span && (col+i) < numCols; i++ { + currentColIndex := col + i + normalizedWidth := originalNormalizedWidths.Get(currentColIndex) + totalWidth += normalizedWidth + t.logger.Debugf(" -> col %d: adding normalized width %d", currentColIndex, normalizedWidth) + + if i > 0 && separatorWidth > 0 { + totalWidth += separatorWidth + t.logger.Debugf(" -> col %d: adding separator width %d", currentColIndex, separatorWidth) + } + } + + targetWidthsMap.Set(col, totalWidth) + t.logger.Debugf(" -> Set %s col %d width to %d (merged)", position, col, totalWidth) + processedCols[col] = true + + for i := 1; i < span && (col+i) < numCols; i++ { + targetWidthsMap.Set(col+i, 0) + t.logger.Debugf(" -> Set %s col %d width to 0 (part of merge)", position, col+i) + processedCols[col+i] = true + } + } + } + ctx.logger.Debugf("applyHorizontalMergeWidths: Final widths for %s: %v", position, targetWidthsMap) +} + +// applyVerticalMerges applies vertical merges to row content. +// Parameters ctx and mctx hold rendering and merge state. +// No return value. +func (t *Table) applyVerticalMerges(ctx *renderContext, mctx *mergeContext) { + ctx.logger.Debugf("Applying vertical merges across %d rows", len(ctx.rowLines)) + numCols := ctx.numCols + + mergeStartRow := make(map[int]int) + mergeStartContent := make(map[int]string) + + for i := 0; i < len(ctx.rowLines); i++ { + if i >= len(mctx.rowMerges) { + newRowMerges := make([]map[int]tw.MergeState, i+1) + copy(newRowMerges, mctx.rowMerges) + for k := len(mctx.rowMerges); k <= i; k++ { + newRowMerges[k] = make(map[int]tw.MergeState) + } + mctx.rowMerges = newRowMerges + ctx.logger.Debugf("Extended rowMerges to index %d", i) + } else if mctx.rowMerges[i] == nil { + mctx.rowMerges[i] = make(map[int]tw.MergeState) + } + + if len(ctx.rowLines[i]) == 0 { + continue + } + currentLineContent := ctx.rowLines[i] + + for col := 0; col < numCols; col++ { + // Join all lines of the cell to compare full content + var currentVal strings.Builder + for _, line := range currentLineContent { + if col < len(line) { + currentVal.WriteString(line[col]) + } + } + + currentValStr := t.Trimmer(currentVal.String()) + + startRow, ongoingMerge := mergeStartRow[col] + startContent := mergeStartContent[col] + mergeState := mctx.rowMerges[i][col] + + if ongoingMerge && currentValStr == startContent && currentValStr != "" { + mergeState.Vertical = tw.MergeStateOption{ + Present: true, + Span: 0, + Start: false, + End: false, + } + mctx.rowMerges[i][col] = mergeState + for lineIdx := range ctx.rowLines[i] { + if col < len(ctx.rowLines[i][lineIdx]) { + ctx.rowLines[i][lineIdx][col] = tw.Empty + } + } + ctx.logger.Debugf("Vertical merge continued at row %d, col %d", i, col) + } else { + if ongoingMerge { + endedRow := i - 1 + if endedRow >= 0 && endedRow >= startRow { + startState := mctx.rowMerges[startRow][col] + startState.Vertical.Span = (endedRow - startRow) + 1 + startState.Vertical.End = startState.Vertical.Span == 1 + mctx.rowMerges[startRow][col] = startState + + endState := mctx.rowMerges[endedRow][col] + endState.Vertical.End = true + endState.Vertical.Span = startState.Vertical.Span + mctx.rowMerges[endedRow][col] = endState + ctx.logger.Debugf("Vertical merge ended at row %d, col %d, span %d", endedRow, col, startState.Vertical.Span) + } + delete(mergeStartRow, col) + delete(mergeStartContent, col) + } + + if currentValStr != "" { + mergeState.Vertical = tw.MergeStateOption{ + Present: true, + Span: 1, + Start: true, + End: false, + } + mctx.rowMerges[i][col] = mergeState + mergeStartRow[col] = i + mergeStartContent[col] = currentValStr + ctx.logger.Debugf("Vertical merge started at row %d, col %d", i, col) + } else if !mergeState.Horizontal.Present { + mergeState.Vertical = tw.MergeStateOption{} + mctx.rowMerges[i][col] = mergeState + } + } + } + } + + lastRowIdx := len(ctx.rowLines) - 1 + if lastRowIdx >= 0 { + for col, startRow := range mergeStartRow { + startState := mctx.rowMerges[startRow][col] + finalSpan := (lastRowIdx - startRow) + 1 + startState.Vertical.Span = finalSpan + startState.Vertical.End = finalSpan == 1 + mctx.rowMerges[startRow][col] = startState + + endState := mctx.rowMerges[lastRowIdx][col] + endState.Vertical.Present = true + endState.Vertical.End = true + endState.Vertical.Span = finalSpan + if startRow != lastRowIdx { + endState.Vertical.Start = false + } + mctx.rowMerges[lastRowIdx][col] = endState + ctx.logger.Debugf("Vertical merge finalized at row %d, col %d, span %d", lastRowIdx, col, finalSpan) + } + } + ctx.logger.Debug("Vertical merges completed") +} + +// buildAdjacentCells constructs cell contexts for adjacent lines. +// Parameters include ctx, mctx, hctx, and direction (-1 for prev, +1 for next). +// Returns a map of column indices to CellContext for the adjacent line. +func (t *Table) buildAdjacentCells(ctx *renderContext, mctx *mergeContext, hctx *helperContext, direction int) map[int]tw.CellContext { + adjCells := make(map[int]tw.CellContext) + var adjLine []string + var adjMerges map[int]tw.MergeState + found := false + adjPosition := hctx.position // Assume adjacent line is in the same section initially + + switch hctx.position { + case tw.Header: + targetLineIdx := hctx.lineIdx + direction + if direction < 0 { // Previous + if targetLineIdx >= 0 && targetLineIdx < len(ctx.headerLines) { + adjLine = ctx.headerLines[targetLineIdx] + adjMerges = mctx.headerMerges + found = true + } + } else { // Next + if targetLineIdx < len(ctx.headerLines) { + adjLine = ctx.headerLines[targetLineIdx] + adjMerges = mctx.headerMerges + found = true + } else if len(ctx.rowLines) > 0 && len(ctx.rowLines[0]) > 0 && len(mctx.rowMerges) > 0 { + adjLine = ctx.rowLines[0][0] + adjMerges = mctx.rowMerges[0] + adjPosition = tw.Row + found = true + } else if len(ctx.footerLines) > 0 { + adjLine = ctx.footerLines[0] + adjMerges = mctx.footerMerges + adjPosition = tw.Footer + found = true + } + } + case tw.Row: + targetLineIdx := hctx.lineIdx + direction + if hctx.rowIdx < 0 || hctx.rowIdx >= len(ctx.rowLines) || hctx.rowIdx >= len(mctx.rowMerges) { + t.logger.Debugf("Warning: Invalid row index %d in buildAdjacentCells", hctx.rowIdx) + return nil + } + currentRowLines := ctx.rowLines[hctx.rowIdx] + currentMerges := mctx.rowMerges[hctx.rowIdx] + + if direction < 0 { // Previous + if targetLineIdx >= 0 && targetLineIdx < len(currentRowLines) { + adjLine = currentRowLines[targetLineIdx] + adjMerges = currentMerges + found = true + } else if targetLineIdx < 0 { + targetRowIdx := hctx.rowIdx - 1 + if targetRowIdx >= 0 && targetRowIdx < len(ctx.rowLines) && targetRowIdx < len(mctx.rowMerges) { + prevRowLines := ctx.rowLines[targetRowIdx] + if len(prevRowLines) > 0 { + adjLine = prevRowLines[len(prevRowLines)-1] + adjMerges = mctx.rowMerges[targetRowIdx] + found = true + } + } else if len(ctx.headerLines) > 0 { + adjLine = ctx.headerLines[len(ctx.headerLines)-1] + adjMerges = mctx.headerMerges + adjPosition = tw.Header + found = true + } + } + } else { // Next + if targetLineIdx >= 0 && targetLineIdx < len(currentRowLines) { + adjLine = currentRowLines[targetLineIdx] + adjMerges = currentMerges + found = true + } else if targetLineIdx >= len(currentRowLines) { + targetRowIdx := hctx.rowIdx + 1 + if targetRowIdx < len(ctx.rowLines) && targetRowIdx < len(mctx.rowMerges) && len(ctx.rowLines[targetRowIdx]) > 0 { + adjLine = ctx.rowLines[targetRowIdx][0] + adjMerges = mctx.rowMerges[targetRowIdx] + found = true + } else if len(ctx.footerLines) > 0 { + adjLine = ctx.footerLines[0] + adjMerges = mctx.footerMerges + adjPosition = tw.Footer + found = true + } + } + } + case tw.Footer: + targetLineIdx := hctx.lineIdx + direction + if direction < 0 { // Previous + if targetLineIdx >= 0 && targetLineIdx < len(ctx.footerLines) { + adjLine = ctx.footerLines[targetLineIdx] + adjMerges = mctx.footerMerges + found = true + } else if targetLineIdx < 0 { + if len(ctx.rowLines) > 0 { + lastRowIdx := len(ctx.rowLines) - 1 + if lastRowIdx < len(mctx.rowMerges) && len(ctx.rowLines[lastRowIdx]) > 0 { + lastRowLines := ctx.rowLines[lastRowIdx] + adjLine = lastRowLines[len(lastRowLines)-1] + adjMerges = mctx.rowMerges[lastRowIdx] + adjPosition = tw.Row + found = true + } + } else if len(ctx.headerLines) > 0 { + adjLine = ctx.headerLines[len(ctx.headerLines)-1] + adjMerges = mctx.headerMerges + adjPosition = tw.Header + found = true + } + } + } else { // Next + if targetLineIdx >= 0 && targetLineIdx < len(ctx.footerLines) { + adjLine = ctx.footerLines[targetLineIdx] + adjMerges = mctx.footerMerges + found = true + } + } + } + + if !found { + return nil + } + + if adjMerges == nil { + adjMerges = make(map[int]tw.MergeState) + t.logger.Debugf("Warning: adjMerges was nil in buildAdjacentCells despite found=true") + } + + paddedAdjLine := padLine(adjLine, ctx.numCols) + + for j := 0; j < ctx.numCols; j++ { + mergeState := adjMerges[j] + cellData := paddedAdjLine[j] + finalAdjColWidth := ctx.widths[adjPosition].Get(j) + + adjCells[j] = tw.CellContext{ + Data: cellData, + Merge: mergeState, + Width: finalAdjColWidth, + } + } + return adjCells +} + +// buildCellContexts creates CellContext objects for a given line in batch mode. +// Parameters include ctx, mctx, hctx, aligns, and padding for rendering. +// Returns a renderMergeResponse with current, previous, and next cell contexts. +func (t *Table) buildCellContexts(ctx *renderContext, mctx *mergeContext, hctx *helperContext, aligns map[int]tw.Align, padding map[int]tw.Padding) renderMergeResponse { + t.logger.Debugf("buildCellContexts: Building contexts for position=%s, rowIdx=%d, lineIdx=%d", hctx.position, hctx.rowIdx, hctx.lineIdx) + var merges map[int]tw.MergeState + switch hctx.position { + case tw.Header: + merges = mctx.headerMerges + case tw.Row: + if hctx.rowIdx >= 0 && hctx.rowIdx < len(mctx.rowMerges) && mctx.rowMerges[hctx.rowIdx] != nil { + merges = mctx.rowMerges[hctx.rowIdx] + } else { + merges = make(map[int]tw.MergeState) + t.logger.Warnf("buildCellContexts: Invalid row index %d or nil merges for row", hctx.rowIdx) + } + case tw.Footer: + merges = mctx.footerMerges + default: + merges = make(map[int]tw.MergeState) + t.logger.Warnf("buildCellContexts: Invalid position '%s'", hctx.position) + } + + cells := t.buildCoreCellContexts(hctx.line, merges, ctx.widths[hctx.position], aligns, padding, ctx.numCols) + return renderMergeResponse{ + cells: cells, + prevCells: t.buildAdjacentCells(ctx, mctx, hctx, -1), + nextCells: t.buildAdjacentCells(ctx, mctx, hctx, +1), + location: hctx.location, + } +} + +// buildCoreCellContexts constructs CellContext objects for a single line, shared between batch and streaming modes. +// Parameters: +// - line: The content of the current line (padded to numCols). +// - merges: Merge states for the line's columns (map[int]tw.MergeState). +// - widths: Column widths (tw.Mapper[int, int]). +// - aligns: Column alignments (map[int]tw.Align). +// - padding: Column padding settings (map[int]tw.Padding). +// - numCols: Number of columns to process. +// Returns a map of column indices to CellContext for the current line. +func (t *Table) buildCoreCellContexts(line []string, merges map[int]tw.MergeState, widths tw.Mapper[int, int], aligns map[int]tw.Align, padding map[int]tw.Padding, numCols int) map[int]tw.CellContext { + cells := make(map[int]tw.CellContext) + paddedLine := padLine(line, numCols) + for j := 0; j < numCols; j++ { + cellData := paddedLine[j] + mergeState := tw.MergeState{} + if merges != nil { + if state, ok := merges[j]; ok { + mergeState = state + } + } + cells[j] = tw.CellContext{ + Data: cellData, + Align: aligns[j], + Padding: padding[j], + Width: widths.Get(j), + Merge: mergeState, + } + } + t.logger.Debugf("buildCoreCellContexts: Built cell contexts for %d columns", numCols) + return cells +} + +// buildPaddingLineContents constructs a padding line for a given section, respecting column widths and horizontal merges. +// It generates a []string where each element is the padding content for a column, using the specified padChar. +func (t *Table) buildPaddingLineContents(padChar string, widths tw.Mapper[int, int], numCols int, merges map[int]tw.MergeState) []string { + line := make([]string, numCols) + padWidth := twwidth.Width(padChar) + if padWidth < 1 { + padWidth = 1 + } + for j := 0; j < numCols; j++ { + mergeState := tw.MergeState{} + if merges != nil { + if state, ok := merges[j]; ok { + mergeState = state + } + } + if mergeState.Horizontal.Present && !mergeState.Horizontal.Start { + line[j] = tw.Empty + continue + } + colWd := widths.Get(j) + repeatCount := 0 + if colWd > 0 && padWidth > 0 { + repeatCount = colWd / padWidth + } + if colWd > 0 && repeatCount < 1 { + repeatCount = 1 + } + content := strings.Repeat(padChar, repeatCount) + line[j] = content + } + if t.logger.Enabled() { + t.logger.Debugf("Built padding line with char '%s' for %d columns", padChar, numCols) + } + return line +} + +// calculateAndNormalizeWidths computes and normalizes column widths. +// Parameter ctx holds rendering state with width maps. +// Returns an error if width calculation fails. +func (t *Table) calculateAndNormalizeWidths(ctx *renderContext) error { + ctx.logger.Debugf("calculateAndNormalizeWidths: Computing and normalizing widths for %d columns. Compact: %v", + ctx.numCols, t.config.Behavior.Compact.Merge.Enabled()) + + // Initialize width maps + //t.headerWidths = tw.NewMapper[int, int]() + //t.rowWidths = tw.NewMapper[int, int]() + //t.footerWidths = tw.NewMapper[int, int]() + + // Compute content-based widths for each section + for _, lines := range ctx.headerLines { + t.updateWidths(lines, t.headerWidths, t.config.Header.Padding) + } + rowWidthCache := make([]tw.Mapper[int, int], len(ctx.rowLines)) + for i, row := range ctx.rowLines { + rowWidthCache[i] = tw.NewMapper[int, int]() + for _, line := range row { + t.updateWidths(line, rowWidthCache[i], t.config.Row.Padding) + for col, width := range rowWidthCache[i] { + currentMax, _ := t.rowWidths.OK(col) + if width > currentMax { + t.rowWidths.Set(col, width) + } + } + } + } + for _, lines := range ctx.footerLines { + t.updateWidths(lines, t.footerWidths, t.config.Footer.Padding) + } + ctx.logger.Debugf("Content-based widths: header=%v, row=%v, footer=%v", t.headerWidths, t.rowWidths, t.footerWidths) + + // Analyze header merges for optimization + var headerMergeSpans map[int]int + if t.config.Header.Formatting.MergeMode&tw.MergeHorizontal != 0 && len(ctx.headerLines) > 0 { + headerMergeSpans = make(map[int]int) + visitedCols := make(map[int]bool) + firstHeaderLine := ctx.headerLines[0] + if len(firstHeaderLine) > 0 { + for i := 0; i < len(firstHeaderLine); { + if visitedCols[i] { + i++ + continue + } + var currentLogicalCellContentBuilder strings.Builder + for _, hLine := range ctx.headerLines { + if i < len(hLine) { + currentLogicalCellContentBuilder.WriteString(hLine[i]) + } + } + currentHeaderCellContent := t.Trimmer(currentLogicalCellContentBuilder.String()) + span := 1 + for j := i + 1; j < len(firstHeaderLine); j++ { + var nextLogicalCellContentBuilder strings.Builder + for _, hLine := range ctx.headerLines { + if j < len(hLine) { + nextLogicalCellContentBuilder.WriteString(hLine[j]) + } + } + nextHeaderCellContent := t.Trimmer(nextLogicalCellContentBuilder.String()) + if currentHeaderCellContent == nextHeaderCellContent && currentHeaderCellContent != "" && currentHeaderCellContent != "-" { + span++ + } else { + break + } + } + if span > 1 { + headerMergeSpans[i] = span + for k := 0; k < span; k++ { + visitedCols[i+k] = true + } + } + i += span + } + } + if len(headerMergeSpans) > 0 { + ctx.logger.Debugf("Header merge spans: %v", headerMergeSpans) + } + } + + // Determine natural column widths + naturalColumnWidths := tw.NewMapper[int, int]() + for i := 0; i < ctx.numCols; i++ { + width := 0 + if colWidth, ok := t.config.Widths.PerColumn.OK(i); ok && colWidth >= 0 { + width = colWidth + ctx.logger.Debugf("Col %d width from Config.Widths.PerColumn: %d", i, width) + } else { + maxRowFooterWidth := tw.Max(t.rowWidths.Get(i), t.footerWidths.Get(i)) + headerCellOriginalWidth := t.headerWidths.Get(i) + if t.config.Behavior.Compact.Merge.Enabled() && + t.config.Header.Formatting.MergeMode&tw.MergeHorizontal != 0 && + headerMergeSpans != nil { + isColInHeaderMerge := false + for startCol, span := range headerMergeSpans { + if i >= startCol && i < startCol+span { + isColInHeaderMerge = true + break + } + } + if isColInHeaderMerge { + width = maxRowFooterWidth + if width == 0 && headerCellOriginalWidth > 0 { + width = headerCellOriginalWidth + } + ctx.logger.Debugf("Col %d (in merge) width: %d (row/footer: %d, header: %d)", i, width, maxRowFooterWidth, headerCellOriginalWidth) + } else { + width = tw.Max(headerCellOriginalWidth, maxRowFooterWidth) + ctx.logger.Debugf("Col %d (not in merge) width: %d", i, width) + } + } else { + width = tw.Max(tw.Max(headerCellOriginalWidth, t.rowWidths.Get(i)), t.footerWidths.Get(i)) + ctx.logger.Debugf("Col %d width (no merge): %d", i, width) + } + if width == 0 && (headerCellOriginalWidth > 0 || t.rowWidths.Get(i) > 0 || t.footerWidths.Get(i) > 0) { + width = tw.Max(tw.Max(headerCellOriginalWidth, t.rowWidths.Get(i)), t.footerWidths.Get(i)) + } + if width == 0 { + width = 1 + } + } + naturalColumnWidths.Set(i, width) + } + ctx.logger.Debugf("Natural column widths: %v", naturalColumnWidths) + + // Expand columns for merged header content if needed + workingWidths := naturalColumnWidths.Clone() + if t.config.Header.Formatting.MergeMode&tw.MergeHorizontal != 0 && headerMergeSpans != nil { + if span, isOneBigMerge := headerMergeSpans[0]; isOneBigMerge && span == ctx.numCols && ctx.numCols > 0 { + var firstHeaderCellLogicalContentBuilder strings.Builder + for _, hLine := range ctx.headerLines { + if 0 < len(hLine) { + firstHeaderCellLogicalContentBuilder.WriteString(hLine[0]) + } + } + mergedContentString := t.Trimmer(firstHeaderCellLogicalContentBuilder.String()) + headerCellPadding := t.config.Header.Padding.Global + if 0 < len(t.config.Header.Padding.PerColumn) && t.config.Header.Padding.PerColumn[0].Paddable() { + headerCellPadding = t.config.Header.Padding.PerColumn[0] + } + actualMergedHeaderContentPhysicalWidth := twwidth.Width(mergedContentString) + + twwidth.Width(headerCellPadding.Left) + + twwidth.Width(headerCellPadding.Right) + currentSumOfColumnWidths := 0 + workingWidths.Each(func(_ int, w int) { currentSumOfColumnWidths += w }) + numSeparatorsInFullSpan := 0 + if ctx.numCols > 1 { + if t.renderer != nil && t.renderer.Config().Settings.Separators.BetweenColumns.Enabled() { + numSeparatorsInFullSpan = (ctx.numCols - 1) * twwidth.Width(t.renderer.Config().Symbols.Column()) + } + } + totalCurrentSpanPhysicalWidth := currentSumOfColumnWidths + numSeparatorsInFullSpan + if actualMergedHeaderContentPhysicalWidth > totalCurrentSpanPhysicalWidth { + ctx.logger.Debugf("Merged header content '%s' (width %d) exceeds total width %d. Expanding.", + mergedContentString, actualMergedHeaderContentPhysicalWidth, totalCurrentSpanPhysicalWidth) + shortfall := actualMergedHeaderContentPhysicalWidth - totalCurrentSpanPhysicalWidth + numNonZeroCols := 0 + workingWidths.Each(func(_ int, w int) { + if w > 0 { + numNonZeroCols++ + } + }) + if numNonZeroCols == 0 && ctx.numCols > 0 { + numNonZeroCols = ctx.numCols + } + if numNonZeroCols > 0 && shortfall > 0 { + extraPerColumn := int(math.Ceil(float64(shortfall) / float64(numNonZeroCols))) + finalSumAfterExpansion := 0 + workingWidths.Each(func(colIdx int, currentW int) { + if currentW > 0 || (numNonZeroCols == ctx.numCols && ctx.numCols > 0) { + newWidth := currentW + extraPerColumn + workingWidths.Set(colIdx, newWidth) + finalSumAfterExpansion += newWidth + ctx.logger.Debugf("Col %d expanded by %d to %d", colIdx, extraPerColumn, newWidth) + } else { + finalSumAfterExpansion += currentW + } + }) + overDistributed := (finalSumAfterExpansion + numSeparatorsInFullSpan) - actualMergedHeaderContentPhysicalWidth + if overDistributed > 0 { + ctx.logger.Debugf("Correcting over-distribution of %d", overDistributed) + // Sort columns for deterministic reduction + sortedCols := workingWidths.SortedKeys() + for i := 0; i < overDistributed; i++ { + // Reduce from highest-indexed column + for j := len(sortedCols) - 1; j >= 0; j-- { + col := sortedCols[j] + if workingWidths.Get(col) > 1 && naturalColumnWidths.Get(col) < workingWidths.Get(col) { + workingWidths.Set(col, workingWidths.Get(col)-1) + ctx.logger.Debugf("Reduced col %d by 1 to %d", col, workingWidths.Get(col)) + break + } + } + } + } + } + } + } + } + ctx.logger.Debugf("Widths after merged header expansion: %v", workingWidths) + + // Apply global width constraint + finalWidths := workingWidths.Clone() + if t.config.Widths.Global > 0 { + ctx.logger.Debugf("Applying global width constraint: %d", t.config.Widths.Global) + currentSumOfFinalColWidths := 0 + finalWidths.Each(func(_ int, w int) { currentSumOfFinalColWidths += w }) + numSeparators := 0 + if ctx.numCols > 1 && t.renderer != nil && t.renderer.Config().Settings.Separators.BetweenColumns.Enabled() { + numSeparators = (ctx.numCols - 1) * twwidth.Width(t.renderer.Config().Symbols.Column()) + } + totalCurrentTablePhysicalWidth := currentSumOfFinalColWidths + numSeparators + if totalCurrentTablePhysicalWidth > t.config.Widths.Global { + ctx.logger.Debugf("Table width %d exceeds global limit %d. Shrinking.", totalCurrentTablePhysicalWidth, t.config.Widths.Global) + targetTotalColumnContentWidth := t.config.Widths.Global - numSeparators + if targetTotalColumnContentWidth < 0 { + targetTotalColumnContentWidth = 0 + } + if ctx.numCols > 0 && targetTotalColumnContentWidth < ctx.numCols { + targetTotalColumnContentWidth = ctx.numCols + } + hardMinimums := tw.NewMapper[int, int]() + sumOfHardMinimums := 0 + isHeaderContentHardToWrap := !(t.config.Header.Formatting.AutoWrap == tw.WrapNormal || t.config.Header.Formatting.AutoWrap == tw.WrapBreak) + for i := 0; i < ctx.numCols; i++ { + minW := 1 + if isHeaderContentHardToWrap && len(ctx.headerLines) > 0 { + headerColNaturalWidthWithPadding := t.headerWidths.Get(i) + if headerColNaturalWidthWithPadding > minW { + minW = headerColNaturalWidthWithPadding + } + } + hardMinimums.Set(i, minW) + sumOfHardMinimums += minW + } + ctx.logger.Debugf("Hard minimums: %v (sum: %d)", hardMinimums, sumOfHardMinimums) + if targetTotalColumnContentWidth < sumOfHardMinimums && sumOfHardMinimums > 0 { + ctx.logger.Warnf("Target width %d below minimums %d. Scaling.", targetTotalColumnContentWidth, sumOfHardMinimums) + scaleFactorMin := float64(targetTotalColumnContentWidth) / float64(sumOfHardMinimums) + if scaleFactorMin < 0 { + scaleFactorMin = 0 + } + tempSum := 0 + scaledHardMinimums := tw.NewMapper[int, int]() + hardMinimums.Each(func(colIdx int, currentMinW int) { + scaledMinW := int(math.Round(float64(currentMinW) * scaleFactorMin)) + if scaledMinW < 1 && targetTotalColumnContentWidth > 0 { + scaledMinW = 1 + } else if scaledMinW < 0 { + scaledMinW = 0 + } + scaledHardMinimums.Set(colIdx, scaledMinW) + tempSum += scaledMinW + }) + errorDiffMin := targetTotalColumnContentWidth - tempSum + if errorDiffMin != 0 && scaledHardMinimums.Len() > 0 { + sortedKeys := scaledHardMinimums.SortedKeys() + for i := 0; i < int(math.Abs(float64(errorDiffMin))); i++ { + keyToAdjust := sortedKeys[i%len(sortedKeys)] + val := scaledHardMinimums.Get(keyToAdjust) + adj := 1 + if errorDiffMin < 0 { + adj = -1 + } + if val+adj >= 1 || (val+adj == 0 && targetTotalColumnContentWidth == 0) { + scaledHardMinimums.Set(keyToAdjust, val+adj) + } else if adj > 0 { + scaledHardMinimums.Set(keyToAdjust, val+adj) + } + } + } + finalWidths = scaledHardMinimums.Clone() + ctx.logger.Debugf("Scaled minimums: %v", finalWidths) + } else { + finalWidths = hardMinimums.Clone() + widthAllocatedByMinimums := sumOfHardMinimums + remainingWidthToDistribute := targetTotalColumnContentWidth - widthAllocatedByMinimums + ctx.logger.Debugf("Target: %d, minimums: %d, remaining: %d", targetTotalColumnContentWidth, widthAllocatedByMinimums, remainingWidthToDistribute) + if remainingWidthToDistribute > 0 { + sumOfFlexiblePotentialBase := 0 + flexibleColsOriginalWidths := tw.NewMapper[int, int]() + for i := 0; i < ctx.numCols; i++ { + naturalW := workingWidths.Get(i) + minW := hardMinimums.Get(i) + if naturalW > minW { + sumOfFlexiblePotentialBase += (naturalW - minW) + flexibleColsOriginalWidths.Set(i, naturalW) + } + } + ctx.logger.Debugf("Flexible potential: %d, flexible widths: %v", sumOfFlexiblePotentialBase, flexibleColsOriginalWidths) + if sumOfFlexiblePotentialBase > 0 { + distributedExtraSum := 0 + sortedFlexKeys := flexibleColsOriginalWidths.SortedKeys() + for _, colIdx := range sortedFlexKeys { + naturalWOfCol := flexibleColsOriginalWidths.Get(colIdx) + hardMinOfCol := hardMinimums.Get(colIdx) + flexiblePartOfCol := naturalWOfCol - hardMinOfCol + proportion := 0.0 + if sumOfFlexiblePotentialBase > 0 { + proportion = float64(flexiblePartOfCol) / float64(sumOfFlexiblePotentialBase) + } else if len(sortedFlexKeys) > 0 { + proportion = 1.0 / float64(len(sortedFlexKeys)) + } + extraForThisCol := int(math.Round(float64(remainingWidthToDistribute) * proportion)) + currentAssignedW := finalWidths.Get(colIdx) + finalWidths.Set(colIdx, currentAssignedW+extraForThisCol) + distributedExtraSum += extraForThisCol + } + errorInDist := remainingWidthToDistribute - distributedExtraSum + ctx.logger.Debugf("Distributed %d, error: %d", distributedExtraSum, errorInDist) + if errorInDist != 0 && len(sortedFlexKeys) > 0 { + for i := 0; i < int(math.Abs(float64(errorInDist))); i++ { + colToAdjust := sortedFlexKeys[i%len(sortedFlexKeys)] + w := finalWidths.Get(colToAdjust) + adj := 1 + if errorInDist < 0 { + adj = -1 + } + if !(adj < 0 && w+adj < hardMinimums.Get(colToAdjust)) { + finalWidths.Set(colToAdjust, w+adj) + } else if adj > 0 { + finalWidths.Set(colToAdjust, w+adj) + } + } + } + } else { + if ctx.numCols > 0 { + extraPerCol := remainingWidthToDistribute / ctx.numCols + rem := remainingWidthToDistribute % ctx.numCols + for i := 0; i < ctx.numCols; i++ { + currentW := finalWidths.Get(i) + add := extraPerCol + if i < rem { + add++ + } + finalWidths.Set(i, currentW+add) + } + } + } + } + } + finalSumCheck := 0 + finalWidths.Each(func(idx int, w int) { + if w < 1 && targetTotalColumnContentWidth > 0 { + finalWidths.Set(idx, 1) + } else if w < 0 { + finalWidths.Set(idx, 0) + } + finalSumCheck += finalWidths.Get(idx) + }) + ctx.logger.Debugf("Final widths after scaling: %v (sum: %d, target: %d)", finalWidths, finalSumCheck, targetTotalColumnContentWidth) + } + } + + // Assign final widths to context + ctx.widths[tw.Header] = finalWidths.Clone() + ctx.widths[tw.Row] = finalWidths.Clone() + ctx.widths[tw.Footer] = finalWidths.Clone() + ctx.logger.Debugf("Final normalized widths: header=%v, row=%v, footer=%v", ctx.widths[tw.Header], ctx.widths[tw.Row], ctx.widths[tw.Footer]) + return nil +} + +// calculateContentMaxWidth computes the maximum content width for a column, accounting for padding and mode-specific constraints. +// Returns the effective content width (after subtracting padding) for the given column index. +func (t *Table) calculateContentMaxWidth(colIdx int, config tw.CellConfig, padLeftWidth, padRightWidth int, isStreaming bool) int { + var effectiveContentMaxWidth int + + if isStreaming { + // Existing streaming logic remains unchanged + totalColumnWidthFromStream := t.streamWidths.Get(colIdx) + if totalColumnWidthFromStream < 0 { + totalColumnWidthFromStream = 0 + } + effectiveContentMaxWidth = totalColumnWidthFromStream - padLeftWidth - padRightWidth + if effectiveContentMaxWidth < 1 && totalColumnWidthFromStream > (padLeftWidth+padRightWidth) { + effectiveContentMaxWidth = 1 + } else if effectiveContentMaxWidth < 0 { + effectiveContentMaxWidth = 0 + } + if totalColumnWidthFromStream == 0 { + effectiveContentMaxWidth = 0 + } + t.logger.Debugf("calculateContentMaxWidth: Streaming col %d, TotalColWd=%d, PadL=%d, PadR=%d -> ContentMaxWd=%d", colIdx, totalColumnWidthFromStream, padLeftWidth, padRightWidth, effectiveContentMaxWidth) + } else { + // New priority-based width constraint checking + constraintTotalCellWidth := 0 + hasConstraint := false + + // 1. Check new Widths.PerColumn (highest priority) + if t.config.Widths.Constrained() { + + if colWidth, ok := t.config.Widths.PerColumn.OK(colIdx); ok && colWidth > 0 { + constraintTotalCellWidth = colWidth + hasConstraint = true + t.logger.Debugf("calculateContentMaxWidth: Using Widths.PerColumn[%d] = %d", + colIdx, constraintTotalCellWidth) + } + + // 2. Check new Widths.Global + if !hasConstraint && t.config.Widths.Global > 0 { + constraintTotalCellWidth = t.config.Widths.Global + hasConstraint = true + t.logger.Debugf("calculateContentMaxWidth: Using Widths.Global = %d", constraintTotalCellWidth) + } + } + + // 3. Fall back to legacy ColMaxWidths.PerColumn (backward compatibility) + if !hasConstraint && config.ColMaxWidths.PerColumn != nil { + if colMax, ok := config.ColMaxWidths.PerColumn.OK(colIdx); ok && colMax > 0 { + constraintTotalCellWidth = colMax + hasConstraint = true + t.logger.Debugf("calculateContentMaxWidth: Using legacy ColMaxWidths.PerColumn[%d] = %d", + colIdx, constraintTotalCellWidth) + } + } + + // 4. Fall back to legacy ColMaxWidths.Global + if !hasConstraint && config.ColMaxWidths.Global > 0 { + constraintTotalCellWidth = config.ColMaxWidths.Global + hasConstraint = true + t.logger.Debugf("calculateContentMaxWidth: Using legacy ColMaxWidths.Global = %d", + constraintTotalCellWidth) + } + + // 5. Fall back to table MaxWidth if auto-wrapping + if !hasConstraint && t.config.MaxWidth > 0 && config.Formatting.AutoWrap != tw.WrapNone { + constraintTotalCellWidth = t.config.MaxWidth + hasConstraint = true + t.logger.Debugf("calculateContentMaxWidth: Using table MaxWidth = %d (AutoWrap enabled)", + constraintTotalCellWidth) + } + + // Calculate effective width based on found constraint + if hasConstraint { + effectiveContentMaxWidth = constraintTotalCellWidth - padLeftWidth - padRightWidth + if effectiveContentMaxWidth < 1 && constraintTotalCellWidth > (padLeftWidth+padRightWidth) { + effectiveContentMaxWidth = 1 + } else if effectiveContentMaxWidth < 0 { + effectiveContentMaxWidth = 0 + } + t.logger.Debugf("calculateContentMaxWidth: ConstraintTotalCellWidth=%d, PadL=%d, PadR=%d -> EffectiveContentMaxWidth=%d", + constraintTotalCellWidth, padLeftWidth, padRightWidth, effectiveContentMaxWidth) + } else { + effectiveContentMaxWidth = 0 + t.logger.Debugf("calculateContentMaxWidth: No width constraints found for column %d", colIdx) + } + } + + return effectiveContentMaxWidth +} + +// convertToStringer invokes the table's stringer function with optional caching. +func (t *Table) convertToStringer(input interface{}) ([]string, error) { + // This function is now only called if t.stringer is non-nil. + if t.stringer == nil { + return nil, errors.New("internal error: convertToStringer called with nil t.stringer") + } + + t.logger.Debugf("convertToString attempt %v using %v", input, t.stringer) + + inputType := reflect.TypeOf(input) + stringerFuncVal := reflect.ValueOf(t.stringer) + stringerFuncType := stringerFuncVal.Type() + + // Cache lookup (simplified, actual cache logic can be more complex) + if t.stringerCacheEnabled { + t.stringerCacheMu.RLock() + cachedFunc, ok := t.stringerCache[inputType] + t.stringerCacheMu.RUnlock() + if ok { + // Add proper type checking for cachedFunc against input here if necessary + t.logger.Debugf("convertToStringer: Cache hit for type %v", inputType) + results := cachedFunc.Call([]reflect.Value{reflect.ValueOf(input)}) + if len(results) == 1 && results[0].Type() == reflect.TypeOf([]string{}) { + return results[0].Interface().([]string), nil + } + } + } + + // Robust type checking for the stringer function + validSignature := stringerFuncVal.Kind() == reflect.Func && + stringerFuncType.NumIn() == 1 && + stringerFuncType.NumOut() == 1 && + stringerFuncType.Out(0) == reflect.TypeOf([]string{}) + + if !validSignature { + return nil, errors.Newf("table stringer (type %T) does not have signature func(SomeType) []string", t.stringer) + } + + // Check if input is assignable to stringer's parameter type + paramType := stringerFuncType.In(0) + assignable := false + if inputType != nil { // input is not untyped nil + if inputType.AssignableTo(paramType) { + assignable = true + } else if paramType.Kind() == reflect.Interface && inputType.Implements(paramType) { + assignable = true + } else if paramType.Kind() == reflect.Interface && paramType.NumMethod() == 0 { // stringer expects interface{} + assignable = true + } + } else if paramType.Kind() == reflect.Interface || (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() != reflect.Interface) { + // If input is nil, it can be assigned if stringer expects an interface or a pointer type + // (but not a pointer to an interface, which is rare for stringers). + // A nil value for a concrete type parameter would cause a panic on Call. + // So, if paramType is not an interface/pointer, and input is nil, it's an issue. + // This needs careful handling. For now, assume assignable if interface/pointer. + assignable = true + } + + if !assignable { + return nil, errors.Newf("input type %T cannot be passed to table stringer expecting %s", input, paramType) + } + + var callArgs []reflect.Value + if input == nil { + // If input is nil, we must pass a zero value of the stringer's parameter type + // if that type is a pointer or interface. + // Passing reflect.ValueOf(nil) directly will cause issues if paramType is concrete. + callArgs = []reflect.Value{reflect.Zero(paramType)} + } else { + callArgs = []reflect.Value{reflect.ValueOf(input)} + } + + resultValues := stringerFuncVal.Call(callArgs) + + if t.stringerCacheEnabled && inputType != nil { // Only cache if inputType is valid + t.stringerCacheMu.Lock() + t.stringerCache[inputType] = stringerFuncVal + t.stringerCacheMu.Unlock() + } + + return resultValues[0].Interface().([]string), nil +} + +// convertToString converts a value to its string representation. +func (t *Table) convertToString(value interface{}) string { + if value == nil { + return "" + } + switch v := value.(type) { + case tw.Formatter: + return v.Format() + case io.Reader: + const maxReadSize = 512 + var buf strings.Builder + _, err := io.CopyN(&buf, v, maxReadSize) + if err != nil && err != io.EOF { + return fmt.Sprintf("[reader error: %v]", err) // Keep fmt.Sprintf for rare error case + } + if buf.Len() == maxReadSize { + buf.WriteString(tw.CharEllipsis) + } + return buf.String() + case sql.NullString: + if v.Valid { + return v.String + } + return "" + case sql.NullInt64: + if v.Valid { + return strconv.FormatInt(v.Int64, 10) + } + return "" + case sql.NullFloat64: + if v.Valid { + return strconv.FormatFloat(v.Float64, 'f', -1, 64) + } + return "" + case sql.NullBool: + if v.Valid { + return strconv.FormatBool(v.Bool) + } + return "" + case sql.NullTime: + if v.Valid { + return v.Time.String() + } + return "" + case []byte: + return string(v) + case error: + return v.Error() + case fmt.Stringer: + return v.String() + case string: + return v + case int: + return strconv.FormatInt(int64(v), 10) + case int8: + return strconv.FormatInt(int64(v), 10) + case int16: + return strconv.FormatInt(int64(v), 10) + case int32: + return strconv.FormatInt(int64(v), 10) + case int64: + return strconv.FormatInt(v, 10) + case uint: + return strconv.FormatUint(uint64(v), 10) + case uint8: + return strconv.FormatUint(uint64(v), 10) + case uint16: + return strconv.FormatUint(uint64(v), 10) + case uint32: + return strconv.FormatUint(uint64(v), 10) + case uint64: + return strconv.FormatUint(v, 10) + case float32: + return strconv.FormatFloat(float64(v), 'f', -1, 32) + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case bool: + return strconv.FormatBool(v) + default: + t.logger.Debugf("convertToString: Falling back to fmt.Sprintf for type %T", value) + return fmt.Sprintf("%v", value) // Fallback for rare types + } +} + +// convertItemToCells is responsible for converting a single input item (which could be +// a struct, a basic type, or an item implementing Stringer/Formatter) into a slice +// of strings, where each string represents a cell for the table row. +func (t *Table) convertItemToCells(item interface{}) ([]string, error) { + t.logger.Debugf("convertItemToCells: Converting item of type %T", item) + + // 1. User-defined table-wide stringer (t.stringer) takes highest precedence. + if t.stringer != nil { + res, err := t.convertToStringer(item) + if err == nil { + t.logger.Debugf("convertItemToCells: Used custom table stringer (t.stringer) for type %T. Produced %d cells: %v", item, len(res), res) + return res, nil + } + t.logger.Warnf("convertItemToCells: Custom table stringer (t.stringer) was set but incompatible or errored for type %T: %v. Will attempt other conversion methods.", item, err) + } + + // 2. Handle untyped nil directly. + if item == nil { + t.logger.Debugf("convertItemToCells: Item is untyped nil. Returning single empty cell.") + return []string{""}, nil + } + + itemValue := reflect.ValueOf(item) + itemType := itemValue.Type() + + // 3. Handle pointers: Dereference pointers to get to the underlying struct or value. + if itemType.Kind() == reflect.Ptr { + if itemValue.IsNil() { + t.logger.Debugf("convertItemToCells: Item is a nil pointer of type %s. Returning single empty cell.", itemType.String()) + return []string{""}, nil + } + itemValue = itemValue.Elem() + itemType = itemValue.Type() + t.logger.Debugf("convertItemToCells: Dereferenced pointer, now processing type %s.", itemType.String()) + } + + // 4. Special handling for structs: + if itemType.Kind() == reflect.Struct { + // Check if the original item (before potential dereference) implements Formatter or Stringer. + if formatter, ok := item.(tw.Formatter); ok { + t.logger.Debugf("convertItemToCells: Struct item (type %s) is tw.Formatter. Using Format(). Resulting in 1 cell.", itemType.Name()) + return []string{formatter.Format()}, nil + } + if stringer, ok := item.(fmt.Stringer); ok { + t.logger.Debugf("convertItemToCells: Struct item (type %s) is fmt.Stringer. Using String(). Resulting in 1 cell.", itemType.Name()) + return []string{stringer.String()}, nil + } + + t.logger.Debugf("convertItemToCells: Item is a struct (type %s). Attempting generic field reflection to expand into multiple cells.", itemType.Name()) + numFields := itemValue.NumField() + structCells := make([]string, 0, numFields) + hasProcessableFields := false + + for i := 0; i < numFields; i++ { + fieldMeta := itemType.Field(i) + if fieldMeta.PkgPath != "" { + t.logger.Debugf("convertItemToCells: Skipping unexported field %s in struct %s", fieldMeta.Name, itemType.Name()) + continue + } + hasProcessableFields = true // Mark true if we encounter any exported field + + jsonTag := fieldMeta.Tag.Get("json") + if jsonTag == "-" { + t.logger.Debugf("convertItemToCells: Skipping field %s in struct %s due to json:\"-\" tag", fieldMeta.Name, itemType.Name()) + continue + } + + fieldReflectedValue := itemValue.Field(i) + if strings.Contains(jsonTag, ",omitempty") && fieldReflectedValue.IsZero() { + t.logger.Debugf("convertItemToCells: Omitting zero value for field %s in struct %s due to omitempty tag", fieldMeta.Name, itemType.Name()) + structCells = append(structCells, "") + continue + } + structCells = append(structCells, t.convertToString(fieldReflectedValue.Interface())) + } + + // Only return expanded cells if there were processable fields. + // If a struct has no exported fields, or all were skipped via json:"-", + // it should still produce output (e.g. fmt.Sprintf of the struct) rather than an empty row. + if hasProcessableFields { + t.logger.Debugf("convertItemToCells: Struct %s reflected into %d cells: %v", itemType.Name(), len(structCells), structCells) + return structCells, nil + } + + t.logger.Warnf("convertItemToCells: Struct %s has no processable exported fields. Falling back to Sprintf for the whole item (resulting in 1 cell).", itemType.Name()) + return []string{t.convertToString(item)}, nil // 'item' is the original potentially pointer type + } + + // 5. Item is NOT a struct. It might be a basic type or a non-struct type implementing Formatter/Stringer. + // These should all result in a single cell. + if formatter, ok := item.(tw.Formatter); ok { + t.logger.Debugf("convertItemToCells: Item (non-struct, type %T) is tw.Formatter. Using Format(). Resulting in 1 cell.", item) + return []string{formatter.Format()}, nil + } + if stringer, ok := item.(fmt.Stringer); ok { + t.logger.Debugf("convertItemToCells: Item (non-struct, type %T) is fmt.Stringer. Using String(). Resulting in 1 cell.", item) + return []string{stringer.String()}, nil + } + + // 6. Fallback for any other single item (e.g., basic types like int, string, bool): + t.logger.Debugf("convertItemToCells: Item (type %T) is a basic type or unhandled by other mechanisms. Treating as single cell via convertToString.", item) + return []string{t.convertToString(item)}, nil +} + +// convertCellsToStrings converts a row to its raw string representation using specified cell config for filters. +// 'rowInput' can be []string, []any, or a custom type if t.stringer is set. +func (t *Table) convertCellsToStrings(rowInput interface{}, cellCfg tw.CellConfig) ([]string, error) { + t.logger.Debugf("convertCellsToStrings: Converting row: %v (type: %T)", rowInput, rowInput) + + var cells []string + var err error + + switch v := rowInput.(type) { + //Directly supported slice types + case []string: + cells = v + case []interface{}: // Catches variadic simple types grouped by Append + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = t.convertToString(val) + } + case []int: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.Itoa(val) + } + case []int8: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatInt(int64(val), 10) + } + case []int16: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatInt(int64(val), 10) + } + case []int32: // Also rune + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = t.convertToString(val) + } // Use convertToString for potential rune + case []int64: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatInt(val, 10) + } + case []uint: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatUint(uint64(val), 10) + } + case []uint8: // Also byte + cells = make([]string, len(v)) + // If it's truly []byte, convertToString will handle it as a string. + // If it's a slice of small numbers, convertToString will handle them individually. + for i, val := range v { + cells[i] = t.convertToString(val) + } + case []uint16: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatUint(uint64(val), 10) + } + case []uint32: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatUint(uint64(val), 10) + } + case []uint64: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatUint(val, 10) + } + case []float32: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatFloat(float64(val), 'f', -1, 32) + } + case []float64: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatFloat(val, 'f', -1, 64) + } + case []bool: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = strconv.FormatBool(val) + } + case []tw.Formatter: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = val.Format() + } + case []fmt.Stringer: + cells = make([]string, len(v)) + for i, val := range v { + cells[i] = val.String() + } + + //Cases for single items that are NOT slices + // These are now dispatched to convertItemToCells by the default case. + // Keeping direct tw.Formatter and fmt.Stringer here could be a micro-optimization + // if `rowInput` is *exactly* that type (not a struct implementing it), + // but for clarity, `convertItemToCells` can handle these too. + // For this iteration, to match the described flow: + case tw.Formatter: // This handles a single Formatter item + t.logger.Debugf("convertCellsToStrings: Input is a single tw.Formatter. Using Format().") + cells = []string{v.Format()} + case fmt.Stringer: // This handles a single Stringer item + t.logger.Debugf("convertCellsToStrings: Input is a single fmt.Stringer. Using String().") + cells = []string{v.String()} + + default: + // If rowInput is not one of the recognized slice types above, + // or not a single Formatter/Stringer that was directly matched, + // it's treated as a single item that needs to be converted into potentially multiple cells. + // This is where structs (for field expansion) or other single values (for a single cell) are handled. + t.logger.Debugf("convertCellsToStrings: Default case for type %T. Dispatching to convertItemToCells.", rowInput) + cells, err = t.convertItemToCells(rowInput) + if err != nil { + t.logger.Errorf("convertCellsToStrings: Error from convertItemToCells for type %T: %v", rowInput, err) + return nil, err + } + } + + // Apply filters (common logic for all successful conversions) + if err == nil && cells != nil { + if cellCfg.Filter.Global != nil { + t.logger.Debugf("convertCellsToStrings: Applying global filter to cells: %v", cells) + cells = cellCfg.Filter.Global(cells) + } + if len(cellCfg.Filter.PerColumn) > 0 { + t.logger.Debugf("convertCellsToStrings: Applying per-column filters to %d cells", len(cells)) + for i := 0; i < len(cellCfg.Filter.PerColumn); i++ { + if i < len(cells) && cellCfg.Filter.PerColumn[i] != nil { + originalCell := cells[i] + cells[i] = cellCfg.Filter.PerColumn[i](cells[i]) + if cells[i] != originalCell { + t.logger.Debugf(" convertCellsToStrings: Col %d filter applied: '%s' -> '%s'", i, originalCell, cells[i]) + } + } else if i >= len(cells) && cellCfg.Filter.PerColumn[i] != nil { + t.logger.Warnf(" convertCellsToStrings: Per-column filter defined for col %d, but item only produced %d cells. Filter for this column skipped.", i, len(cells)) + } + } + } + } + + if err != nil { + t.logger.Debugf("convertCellsToStrings: Returning with error: %v", err) + return nil, err + } + t.logger.Debugf("convertCellsToStrings: Conversion and filtering completed, raw cells: %v", cells) + return cells, nil +} + +// determineLocation determines the boundary location for a line. +// Parameters include lineIdx, totalLines, topPad, and bottomPad. +// Returns a tw.Location indicating First, Middle, or End. +func (t *Table) determineLocation(lineIdx, totalLines int, topPad, bottomPad string) tw.Location { + if lineIdx == 0 && topPad == tw.Empty { + return tw.LocationFirst + } + if lineIdx == totalLines-1 && bottomPad == tw.Empty { + return tw.LocationEnd + } + return tw.LocationMiddle +} + +// ensureStreamWidthsCalculated ensures that stream widths and column count are initialized for streaming mode. +// It uses sampleData and sectionConfig to calculate widths if not already set. +// Returns an error if the column count cannot be determined. +func (t *Table) ensureStreamWidthsCalculated(sampleData []string, sectionConfig tw.CellConfig) error { + if t.streamWidths != nil && t.streamWidths.Len() > 0 { + t.logger.Debugf("Stream widths already set: %v", t.streamWidths) + return nil + } + t.streamCalculateWidths(sampleData, sectionConfig) + if t.streamNumCols == 0 { + t.logger.Warn("Failed to determine column count from sample data") + return errors.New("failed to determine column count for streaming") + } + for i := 0; i < t.streamNumCols; i++ { + if _, ok := t.streamWidths.OK(i); !ok { + t.streamWidths.Set(i, 0) + } + } + t.logger.Debugf("Initialized stream widths: %v", t.streamWidths) + return nil +} + +// getColMaxWidths retrieves maximum column widths for a section. +// Parameter position specifies the section (Header, Row, Footer). +// Returns a map of column indices to maximum widths. +func (t *Table) getColMaxWidths(position tw.Position) tw.CellWidth { + switch position { + case tw.Header: + return t.config.Header.ColMaxWidths + case tw.Row: + return t.config.Row.ColMaxWidths + case tw.Footer: + return t.config.Footer.ColMaxWidths + default: + return tw.CellWidth{} + } +} + +// getEmptyColumnInfo identifies empty columns in row data. +// Parameter numOriginalCols specifies the total column count. +// Returns a boolean slice (true for empty) and visible column count. +func (t *Table) getEmptyColumnInfo(numOriginalCols int) (isEmpty []bool, visibleColCount int) { + isEmpty = make([]bool, numOriginalCols) + for i := range isEmpty { + isEmpty[i] = true + } + + if t.config.Behavior.AutoHide.Disabled() { + t.logger.Debugf("getEmptyColumnInfo: AutoHide disabled, marking all %d columns as visible.", numOriginalCols) + for i := range isEmpty { + isEmpty[i] = false + } + visibleColCount = numOriginalCols + return isEmpty, visibleColCount + } + + t.logger.Debugf("getEmptyColumnInfo: Checking %d rows for %d columns...", len(t.rows), numOriginalCols) + + for rowIdx, logicalRow := range t.rows { + for lineIdx, visualLine := range logicalRow { + for colIdx, cellContent := range visualLine { + if colIdx >= numOriginalCols { + continue + } + if !isEmpty[colIdx] { + continue + } + + cellContent = t.Trimmer(cellContent) + + if cellContent != "" { + isEmpty[colIdx] = false + t.logger.Debugf("getEmptyColumnInfo: Found content in row %d, line %d, col %d ('%s'). Marked as not empty.", rowIdx, lineIdx, colIdx, cellContent) + } + } + } + } + + visibleColCount = 0 + for _, empty := range isEmpty { + if !empty { + visibleColCount++ + } + } + + t.logger.Debugf("getEmptyColumnInfo: Detection complete. isEmpty: %v, visibleColCount: %d", isEmpty, visibleColCount) + return isEmpty, visibleColCount +} + +// getNumColsToUse determines the number of columns to use for rendering, based on streaming or batch mode. +// Returns the number of columns (streamNumCols for streaming, maxColumns for batch). +func (t *Table) getNumColsToUse() int { + if t.config.Stream.Enable && t.hasPrinted { + t.logger.Debugf("getNumColsToUse: Using streamNumCols: %d", t.streamNumCols) + return t.streamNumCols + } + + // For batch mode: + if t.isBatchRenderNumColsSet { + // If the flag is set, batchRenderNumCols holds the authoritative count + // for the current Render() pass, even if that count is 0. + t.logger.Debugf("getNumColsToUse (batch): Using cached t.batchRenderNumCols: %d (because isBatchRenderNumColsSet is true)", t.batchRenderNumCols) + return t.batchRenderNumCols + } + + // Fallback: If not streaming and cache flag is not set (e.g., called outside a Render pass) + num := t.maxColumns() + t.logger.Debugf("getNumColsToUse (batch): Cache not active, calculated via t.maxColumns(): %d", num) + return num +} + +// prepareTableSection prepares either headers or footers for the table +func (t *Table) prepareTableSection(elements []any, config tw.CellConfig, sectionName string) [][]string { + actualCellsToProcess := t.processVariadic(elements) + t.logger.Debugf("%s(): Effective cells to process: %v", sectionName, actualCellsToProcess) + + stringsResult, err := t.convertCellsToStrings(actualCellsToProcess, config) + if err != nil { + t.logger.Errorf("%s(): Failed to convert elements to strings: %v", sectionName, err) + stringsResult = []string{} + } + + prepared := t.prepareContent(stringsResult, config) + numColsBatch := t.maxColumns() + + if len(prepared) > 0 { + for i := range prepared { + if len(prepared[i]) < numColsBatch { + t.logger.Debugf("Padding %s line %d from %d to %d columns", sectionName, i, len(prepared[i]), numColsBatch) + paddedLine := make([]string, numColsBatch) + copy(paddedLine, prepared[i]) + for j := len(prepared[i]); j < numColsBatch; j++ { + paddedLine[j] = tw.Empty + } + prepared[i] = paddedLine + } else if len(prepared[i]) > numColsBatch { + t.logger.Debugf("Truncating %s line %d from %d to %d columns", sectionName, i, len(prepared[i]), numColsBatch) + prepared[i] = prepared[i][:numColsBatch] + } + } + } + + return prepared +} + +// processVariadic handles the common logic for processing variadic arguments +// that could be either individual elements or a slice of elements +func (t *Table) processVariadic(elements []any) []any { + if len(elements) == 1 { + switch v := elements[0].(type) { + case []string: + t.logger.Debugf("Detected single []string argument. Unpacking it (fast path).") + out := make([]any, len(v)) + for i := range v { + out[i] = v[i] + } + return out + + case []interface{}: + t.logger.Debugf("Detected single []interface{} argument. Unpacking it (fast path).") + out := make([]any, len(v)) + copy(out, v) + return out + } + } + + t.logger.Debugf("Input has multiple elements or single non-slice. Using variadic elements as-is.") + return elements +} + +// toStringLines converts raw cells to formatted lines for table output +func (t *Table) toStringLines(row interface{}, config tw.CellConfig) ([][]string, error) { + cells, err := t.convertCellsToStrings(row, config) + if err != nil { + return nil, err + } + return t.prepareContent(cells, config), nil +} + +// updateWidths updates the width map based on cell content and padding. +// Parameters include row content, widths map, and padding configuration. +// No return value. +func (t *Table) updateWidths(row []string, widths tw.Mapper[int, int], padding tw.CellPadding) { + t.logger.Debugf("Updating widths for row: %v", row) + for i, cell := range row { + colPad := padding.Global + + if i < len(padding.PerColumn) && padding.PerColumn[i].Paddable() { + colPad = padding.PerColumn[i] + t.logger.Debugf(" Col %d: Using per-column padding: L:'%s' R:'%s'", i, colPad.Left, colPad.Right) + } else { + t.logger.Debugf(" Col %d: Using global padding: L:'%s' R:'%s'", i, padding.Global.Left, padding.Global.Right) + } + + padLeftWidth := twwidth.Width(colPad.Left) + padRightWidth := twwidth.Width(colPad.Right) + + // Split cell into lines and find maximum content width + lines := strings.Split(cell, tw.NewLine) + contentWidth := 0 + for _, line := range lines { + lineWidth := twwidth.Width(line) + if t.config.Behavior.TrimSpace.Enabled() { + lineWidth = twwidth.Width(t.Trimmer(line)) + } + if lineWidth > contentWidth { + contentWidth = lineWidth + } + } + + totalWidth := contentWidth + padLeftWidth + padRightWidth + minRequiredPaddingWidth := padLeftWidth + padRightWidth + + if contentWidth == 0 && totalWidth < minRequiredPaddingWidth { + t.logger.Debugf(" Col %d: Empty content, ensuring width >= padding width (%d). Setting totalWidth to %d.", i, minRequiredPaddingWidth, minRequiredPaddingWidth) + totalWidth = minRequiredPaddingWidth + } + + if totalWidth < 1 { + t.logger.Debugf(" Col %d: Calculated totalWidth is zero, setting minimum width to 1.", i) + totalWidth = 1 + } + + currentMax, _ := widths.OK(i) + if totalWidth > currentMax { + widths.Set(i, totalWidth) + t.logger.Debugf(" Col %d: Updated width from %d to %d (content:%d + padL:%d + padR:%d) for cell '%s'", i, currentMax, totalWidth, contentWidth, padLeftWidth, padRightWidth, cell) + } else { + t.logger.Debugf(" Col %d: Width %d not greater than current max %d for cell '%s'", i, totalWidth, currentMax, cell) + } + } +} diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm index 99761296..4230fba0 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:2edf6aab2d57644f3fe7407132a0d1770846867465a39c2083770cf62734b05d +FROM golang:1.23@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 ENV GOOS=linux ENV GOARCH=arm @@ -10,7 +10,6 @@ ENV PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig RUN dpkg --add-architecture armhf \ && apt update \ && apt install -y --no-install-recommends \ - upx \ gcc-arm-linux-gnueabihf \ libc6-dev-armhf-cross \ pkg-config \ diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 index 66bd0947..59928252 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:2edf6aab2d57644f3fe7407132a0d1770846867465a39c2083770cf62734b05d +FROM golang:1.23@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 ENV GOOS=linux ENV GOARCH=arm64 diff --git a/vendor/github.com/pjbgf/sha1cd/LICENSE b/vendor/github.com/pjbgf/sha1cd/LICENSE index 261eeb9e..c8ff622f 100644 --- a/vendor/github.com/pjbgf/sha1cd/LICENSE +++ b/vendor/github.com/pjbgf/sha1cd/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2023 pjbgf Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/pjbgf/sha1cd/Makefile b/vendor/github.com/pjbgf/sha1cd/Makefile index b24f2cba..278a109d 100644 --- a/vendor/github.com/pjbgf/sha1cd/Makefile +++ b/vendor/github.com/pjbgf/sha1cd/Makefile @@ -32,8 +32,7 @@ build-nocgo: cross-build: build-arm build-arm64 build-nocgo generate: - go run sha1cdblock_amd64_asm.go -out sha1cdblock_amd64.s - sed -i 's;&\samd64;&\n// +build !noasm,gc,amd64;g' sha1cdblock_amd64.s + go generate -x ./... verify: generate git diff --exit-code diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cd.go b/vendor/github.com/pjbgf/sha1cd/sha1cd.go index a69e480e..509569f6 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cd.go +++ b/vendor/github.com/pjbgf/sha1cd/sha1cd.go @@ -20,6 +20,8 @@ import ( shared "github.com/pjbgf/sha1cd/internal" ) +//go:generate go run -C asm . -out ../sha1cdblock_amd64.s -pkg $GOPACKAGE + func init() { crypto.RegisterHash(crypto.SHA1, New) } diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s index 86f9821c..e5e213a5 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s @@ -1,7 +1,6 @@ -// Code generated by command: go run sha1cdblock_amd64_asm.go -out sha1cdblock_amd64.s. DO NOT EDIT. +// Code generated by command: go run asm.go -out ../sha1cdblock_amd64.s -pkg sha1cd. DO NOT EDIT. //go:build !noasm && gc && amd64 -// +build !noasm,gc,amd64 #include "textflag.h" diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/doc.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go similarity index 68% rename from vendor/github.com/pjbgf/sha1cd/ubc/doc.go rename to vendor/github.com/pjbgf/sha1cd/ubc/ubc.go index 0090e36b..b0b4d76e 100644 --- a/vendor/github.com/pjbgf/sha1cd/ubc/doc.go +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go @@ -1,3 +1,5 @@ // ubc package provides ways for SHA1 blocks to be checked for // Unavoidable Bit Conditions that arise from crypto analysis attacks. package ubc + +//go:generate go run -C asm . -out ../ubc_amd64.s -pkg $GOPACKAGE diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go new file mode 100644 index 00000000..09159bb5 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go @@ -0,0 +1,14 @@ +//go:build !noasm && gc && amd64 +// +build !noasm,gc,amd64 + +package ubc + +func CalculateDvMaskAMD64(W [80]uint32) uint32 + +// Check takes as input an expanded message block and verifies the unavoidable bitconditions +// for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all +// unavoidable bitconditions for that DV have been met. +// Thus, one needs to do the recompression check for each DV that has its bit set. +func CalculateDvMask(W [80]uint32) uint32 { + return CalculateDvMaskAMD64(W) +} diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s new file mode 100644 index 00000000..c77ea77e --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s @@ -0,0 +1,1897 @@ +// Code generated by command: go run asm.go -out ../ubc_amd64.s -pkg ubc. DO NOT EDIT. + +//go:build !noasm && gc && amd64 + +#include "textflag.h" + +// func CalculateDvMaskAMD64(W [80]uint32) uint32 +TEXT ·CalculateDvMaskAMD64(SB), NOSPLIT, $0-324 + MOVL $0xffffffff, AX + + // (((((W[44] ^ W[45]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)) + MOVL W_44+176(FP), CX + MOVL W_45+180(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xfd7c5f7f, CX + ANDL CX, AX + + // mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) + MOVL W_49+196(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x3d7efff7, CX + ANDL CX, AX + + // mask &= (((((W[48] ^ W[49]) >> 29) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_52_0_bit | DV_II_49_0_bit | DV_II_50_0_bit | DV_II_54_0_bit | DV_II_55_0_bit)) + MOVL W_48+192(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x9f5f7ffb, CX + ANDL CX, AX + + // mask &= ((((W[47] ^ (W[50] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) + MOVL W_47+188(FP), CX + MOVL W_50+200(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0x7dfedddf, CX + ANDL CX, AX + + // mask &= (((((W[47] ^ W[48]) >> 29) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_51_0_bit | DV_II_48_0_bit | DV_II_49_0_bit | DV_II_53_0_bit | DV_II_54_0_bit)) + MOVL W_47+188(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xcfcfdffd, CX + ANDL CX, AX + + // mask &= (((((W[46] >> 4) ^ (W[49] >> 29)) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_50_0_bit | DV_II_55_0_bit)) + MOVL W_46+184(FP), CX + SHRL $0x04, CX + MOVL W_49+196(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xbf7f7777, CX + ANDL CX, AX + + // mask &= (((((W[46] ^ W[47]) >> 29) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_50_0_bit | DV_II_47_0_bit | DV_II_48_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) + MOVL W_46+184(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xe7e7f7fe, CX + ANDL CX, AX + + // mask &= (((((W[45] >> 4) ^ (W[48] >> 29)) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_49_0_bit | DV_II_54_0_bit)) + MOVL W_45+180(FP), CX + SHRL $0x04, CX + MOVL W_48+192(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xdfdfdddb, CX + ANDL CX, AX + + // mask &= (((((W[45] ^ W[46]) >> 29) & 1) - 1) | ^(DV_I_49_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_47_0_bit | DV_II_51_0_bit | DV_II_52_0_bit)) + MOVL W_45+180(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xf5f57dff, CX + ANDL CX, AX + + // mask &= (((((W[44] >> 4) ^ (W[47] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | DV_II_53_0_bit)) + MOVL W_44+176(FP), CX + SHRL $0x04, CX + MOVL W_47+188(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xefeff775, CX + ANDL CX, AX + + // mask &= (((((W[43] >> 4) ^ (W[46] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | DV_II_52_0_bit)) + MOVL W_43+172(FP), CX + SHRL $0x04, CX + MOVL W_46+184(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xf7f7fdda, CX + ANDL CX, AX + + // mask &= (((((W[43] ^ W[44]) >> 29) & 1) - 1) | ^(DV_I_47_0_bit | DV_I_50_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_49_0_bit | DV_II_50_0_bit)) + MOVL W_43+172(FP), CX + MOVL W_44+176(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xff5ed7df, CX + ANDL CX, AX + + // mask &= (((((W[42] >> 4) ^ (W[45] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_51_0_bit)) + MOVL W_42+168(FP), CX + SHRL $0x04, CX + MOVL W_45+180(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xfdfd7f75, CX + ANDL CX, AX + + // mask &= (((((W[41] >> 4) ^ (W[44] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_50_0_bit)) + MOVL W_41+164(FP), CX + SHRL $0x04, CX + MOVL W_44+176(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xff7edfda, CX + ANDL CX, AX + + // mask &= (((((W[40] ^ W[41]) >> 29) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_47_0_bit | DV_I_48_0_bit | DV_II_46_0_bit | DV_II_47_0_bit | DV_II_56_0_bit)) + MOVL W_40+160(FP), CX + MOVL W_41+164(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7ff5ff5d, CX + ANDL CX, AX + + // mask &= (((((W[54] ^ W[55]) >> 29) & 1) - 1) | ^(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_50_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) + MOVL W_54+216(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x3f77dfff, CX + ANDL CX, AX + + // mask &= (((((W[53] ^ W[54]) >> 29) & 1) - 1) | ^(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_49_0_bit | DV_II_54_0_bit | DV_II_55_0_bit)) + MOVL W_53+212(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x9fddf7ff, CX + ANDL CX, AX + + // mask &= (((((W[52] ^ W[53]) >> 29) & 1) - 1) | ^(DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit | DV_II_53_0_bit | DV_II_54_0_bit)) + MOVL W_52+208(FP), CX + MOVL W_53+212(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xcfeefdff, CX + ANDL CX, AX + + // mask &= ((((W[50] ^ (W[53] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_48_0_bit | DV_II_54_0_bit)) + MOVL W_50+200(FP), CX + MOVL W_53+212(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xdfed77ff, CX + ANDL CX, AX + + // mask &= (((((W[50] ^ W[51]) >> 29) & 1) - 1) | ^(DV_I_47_0_bit | DV_II_46_0_bit | DV_II_51_0_bit | DV_II_52_0_bit | DV_II_56_0_bit)) + MOVL W_50+200(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x75fdffdf, CX + ANDL CX, AX + + // mask &= ((((W[49] ^ (W[52] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_47_0_bit | DV_II_53_0_bit)) + MOVL W_49+196(FP), CX + MOVL W_52+208(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xeff6ddff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ (W[51] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_52_0_bit)) + MOVL W_48+192(FP), CX + MOVL W_51+204(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xf7fd777f, CX + ANDL CX, AX + + // mask &= (((((W[42] ^ W[43]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_49_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) + MOVL W_42+168(FP), CX + MOVL W_43+172(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffcff5f7, CX + ANDL CX, AX + + // mask &= (((((W[41] ^ W[42]) >> 29) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_48_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | DV_II_48_0_bit)) + MOVL W_41+164(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffe7fd7b, CX + ANDL CX, AX + + // mask &= (((((W[40] >> 4) ^ (W[43] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_50_0_bit | DV_II_49_0_bit | DV_II_56_0_bit)) + MOVL W_40+160(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7fdff7f5, CX + ANDL CX, AX + + // mask &= (((((W[39] >> 4) ^ (W[42] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_49_0_bit | DV_II_48_0_bit | DV_II_55_0_bit)) + MOVL W_39+156(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xbfeffdfa, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= (((((W[38] >> 4) ^ (W[41] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + // } + TESTL $0xa0080082, AX + JE f1 + MOVL W_38+152(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x5ff7ff7d, CX + ANDL CX, AX + +f1: + // mask &= (((((W[37] >> 4) ^ (W[40] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_47_0_bit | DV_II_46_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) + MOVL W_37+148(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xaffdffde, CX + ANDL CX, AX + + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= (((((W[55] ^ W[56]) >> 29) & 1) - 1) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x82108000, AX + JE f2 + MOVL W_55+220(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7def7fff, CX + ANDL CX, AX + +f2: + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((((W[52] ^ (W[55] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x80908000, AX + JE f3 + MOVL W_52+208(FP), CX + MOVL W_55+220(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0x7f6f7fff, CX + ANDL CX, AX + +f3: + // if (mask & (DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((((W[51] ^ (W[54] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x40282000, AX + JE f4 + MOVL W_51+204(FP), CX + MOVL W_54+216(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xbfd7dfff, CX + ANDL CX, AX + +f4: + // if (mask & (DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= (((((W[51] ^ W[52]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x18080080, AX + JE f5 + MOVL W_51+204(FP), CX + MOVL W_52+208(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xe7f7ff7f, CX + ANDL CX, AX + +f5: + // if (mask & (DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)) != 0 { + // mask &= (((((W[36] >> 4) ^ (W[40] >> 29)) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)) + // } + TESTL $0x00110208, AX + JE f6 + MOVL W_36+144(FP), CX + SHRL $0x04, CX + MOVL W_40+160(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffeefdf7, CX + ANDL CX, AX + +f6: + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) != 0 { + // mask &= ((0 - (((W[53] ^ W[56]) >> 29) & 1)) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) + // } + TESTL $0x00308000, AX + JE f7 + MOVL W_53+212(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffcf7fff, CX + ANDL CX, AX + +f7: + // if (mask & (DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((0 - (((W[51] ^ W[54]) >> 29) & 1)) | ^(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x000a0800, AX + JE f8 + MOVL W_51+204(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfff5f7ff, CX + ANDL CX, AX + +f8: + // if (mask & (DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - (((W[50] ^ W[52]) >> 29) & 1)) | ^(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00012200, AX + JE f9 + MOVL W_50+200(FP), CX + MOVL W_52+208(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffeddff, CX + ANDL CX, AX + +f9: + // if (mask & (DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)) != 0 { + // mask &= ((0 - (((W[49] ^ W[51]) >> 29) & 1)) | ^(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)) + // } + TESTL $0x00008880, AX + JE f10 + MOVL W_49+196(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffff777f, CX + ANDL CX, AX + +f10: + // if (mask & (DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)) != 0 { + // mask &= ((0 - (((W[48] ^ W[50]) >> 29) & 1)) | ^(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)) + // } + TESTL $0x00002220, AX + JE f11 + MOVL W_48+192(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffdddf, CX + ANDL CX, AX + +f11: + // if (mask & (DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)) != 0 { + // mask &= ((0 - (((W[47] ^ W[49]) >> 29) & 1)) | ^(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)) + // } + TESTL $0x00000888, AX + JE f12 + MOVL W_47+188(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffff777, CX + ANDL CX, AX + +f12: + // if (mask & (DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)) != 0 { + // mask &= ((0 - (((W[46] ^ W[48]) >> 29) & 1)) | ^(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)) + // } + TESTL $0x00000224, AX + JE f13 + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffffddb, CX + ANDL CX, AX + +f13: + // mask &= ((((W[45] ^ W[47]) & (1 << 6)) - (1 << 6)) | ^(DV_I_47_2_bit | DV_I_49_2_bit | DV_I_51_2_bit)) + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffbbbf, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)) != 0 { + // mask &= ((0 - (((W[45] ^ W[47]) >> 29) & 1)) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)) + // } + TESTL $0x0000008a, AX + JE f14 + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffff75, CX + ANDL CX, AX + +f14: + // mask &= (((((W[44] ^ W[46]) >> 6) & 1) - 1) | ^(DV_I_46_2_bit | DV_I_48_2_bit | DV_I_50_2_bit)) + MOVL W_44+176(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x06, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffffeeef, CX + ANDL CX, AX + + // if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)) != 0 { + // mask &= ((0 - (((W[44] ^ W[46]) >> 29) & 1)) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)) + // } + TESTL $0x00000025, AX + JE f15 + MOVL W_44+176(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffffda, CX + ANDL CX, AX + +f15: + // mask &= ((0 - ((W[41] ^ (W[42] >> 5)) & (1 << 1))) | ^(DV_I_48_2_bit | DV_II_46_2_bit | DV_II_51_2_bit)) + MOVL W_41+164(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfbfbfeff, CX + ANDL CX, AX + + // mask &= ((0 - ((W[40] ^ (W[41] >> 5)) & (1 << 1))) | ^(DV_I_47_2_bit | DV_I_51_2_bit | DV_II_50_2_bit)) + MOVL W_40+160(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfeffbfbf, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((0 - (((W[40] ^ W[42]) >> 4) & 1)) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x8000000a, AX + JE f16 + MOVL W_40+160(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0x7ffffff5, CX + ANDL CX, AX + +f16: + // mask &= ((0 - ((W[39] ^ (W[40] >> 5)) & (1 << 1))) | ^(DV_I_46_2_bit | DV_I_50_2_bit | DV_II_49_2_bit)) + MOVL W_39+156(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffbfefef, CX + ANDL CX, AX + + // if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((0 - (((W[39] ^ W[41]) >> 4) & 1)) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x40000005, AX + JE f17 + MOVL W_39+156(FP), CX + MOVL W_41+164(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xbffffffa, CX + ANDL CX, AX + +f17: + // if (mask & (DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((0 - (((W[38] ^ W[40]) >> 4) & 1)) | ^(DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + // } + TESTL $0xa0000002, AX + JE f18 + MOVL W_38+152(FP), CX + MOVL W_40+160(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0x5ffffffd, CX + ANDL CX, AX + +f18: + // if (mask & (DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((0 - (((W[37] ^ W[39]) >> 4) & 1)) | ^(DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x50000001, AX + JE f19 + MOVL W_37+148(FP), CX + MOVL W_39+156(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xaffffffe, CX + ANDL CX, AX + +f19: + // mask &= ((0 - ((W[36] ^ (W[37] >> 5)) & (1 << 1))) | ^(DV_I_47_2_bit | DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_36+144(FP), CX + MOVL W_37+148(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffbefbf, CX + ANDL CX, AX + + // if (mask & (DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= (((((W[35] >> 4) ^ (W[39] >> 29)) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00080084, AX + JE f20 + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xfff7ff7b, CX + ANDL CX, AX + +f20: + // if (mask & (DV_I_48_0_bit | DV_II_48_0_bit)) != 0 { + // mask &= ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 0))) | ^(DV_I_48_0_bit | DV_II_48_0_bit)) + // } + TESTL $0x00100080, AX + JE f21 + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffefff7f, CX + ANDL CX, AX + +f21: + // if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 1))) | ^(DV_I_45_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00010004, AX + JE f22 + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffefffb, CX + ANDL CX, AX + +f22: + // if (mask & (DV_I_47_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((0 - ((W[62] ^ (W[63] >> 5)) & (1 << 0))) | ^(DV_I_47_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00080020, AX + JE f23 + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfff7ffdf, CX + ANDL CX, AX + +f23: + // if (mask & (DV_I_46_0_bit | DV_II_46_0_bit)) != 0 { + // mask &= ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 0))) | ^(DV_I_46_0_bit | DV_II_46_0_bit)) + // } + TESTL $0x00020008, AX + JE f24 + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffdfff7, CX + ANDL CX, AX + +f24: + // mask &= ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 2))) | ^(DV_I_46_2_bit | DV_II_46_2_bit)) + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + ORL $0xfffbffef, CX + ANDL CX, AX + + // if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - ((W[60] ^ (W[61] >> 5)) & (1 << 0))) | ^(DV_I_45_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00010004, AX + JE f25 + MOVL W_60+240(FP), CX + MOVL W_61+244(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffefffb, CX + ANDL CX, AX + +f25: + // if (mask & (DV_II_51_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= (((((W[58] ^ W[59]) >> 29) & 1) - 1) | ^(DV_II_51_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x22000000, AX + JE f26 + MOVL W_58+232(FP), CX + MOVL W_59+236(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xddffffff, CX + ANDL CX, AX + +f26: + // if (mask & (DV_II_50_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= (((((W[57] ^ W[58]) >> 29) & 1) - 1) | ^(DV_II_50_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x10800000, AX + JE f27 + MOVL W_57+228(FP), CX + MOVL W_58+232(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xef7fffff, CX + ANDL CX, AX + +f27: + // if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= ((((W[56] ^ (W[59] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_52_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x28000000, AX + JE f28 + MOVL W_56+224(FP), CX + MOVL W_59+236(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xd7ffffff, CX + ANDL CX, AX + +f28: + // if (mask & (DV_II_51_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= ((0 - (((W[56] ^ W[59]) >> 29) & 1)) | ^(DV_II_51_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x0a000000, AX + JE f29 + MOVL W_56+224(FP), CX + MOVL W_59+236(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xf5ffffff, CX + ANDL CX, AX + +f29: + // if (mask & (DV_II_49_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= (((((W[56] ^ W[57]) >> 29) & 1) - 1) | ^(DV_II_49_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x08200000, AX + JE f30 + MOVL W_56+224(FP), CX + MOVL W_57+228(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xf7dfffff, CX + ANDL CX, AX + +f30: + // if (mask & (DV_II_51_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= ((((W[55] ^ (W[58] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_51_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x12000000, AX + JE f31 + MOVL W_55+220(FP), CX + MOVL W_58+232(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xedffffff, CX + ANDL CX, AX + +f31: + // if (mask & (DV_II_50_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= ((((W[54] ^ (W[57] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_50_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x08800000, AX + JE f32 + MOVL W_54+216(FP), CX + MOVL W_57+228(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xf77fffff, CX + ANDL CX, AX + +f32: + // if (mask & (DV_II_49_0_bit | DV_II_51_0_bit)) != 0 { + // mask &= ((((W[53] ^ (W[56] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_49_0_bit | DV_II_51_0_bit)) + // } + TESTL $0x02200000, AX + JE f33 + MOVL W_53+212(FP), CX + MOVL W_56+224(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xfddfffff, CX + ANDL CX, AX + +f33: + // mask &= ((((W[51] ^ (W[50] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_51+204(FP), CX + MOVL W_50+200(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfffbefff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ W[50]) & (1 << 6)) - (1 << 6)) | ^(DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_48+192(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xfffbefff, CX + ANDL CX, AX + + // if (mask & (DV_I_51_0_bit | DV_I_52_0_bit)) != 0 { + // mask &= ((0 - (((W[48] ^ W[55]) >> 29) & 1)) | ^(DV_I_51_0_bit | DV_I_52_0_bit)) + // } + TESTL $0x0000a000, AX + JE f34 + MOVL W_48+192(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffff5fff, CX + ANDL CX, AX + +f34: + // mask &= ((((W[47] ^ W[49]) & (1 << 6)) - (1 << 6)) | ^(DV_I_49_2_bit | DV_I_51_2_bit)) + MOVL W_47+188(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffbbff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ (W[47] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_47_2_bit | DV_II_51_2_bit)) + MOVL W_48+192(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfbffffbf, CX + ANDL CX, AX + + // mask &= ((((W[46] ^ W[48]) & (1 << 6)) - (1 << 6)) | ^(DV_I_48_2_bit | DV_I_50_2_bit)) + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffeeff, CX + ANDL CX, AX + + // mask &= ((((W[47] ^ (W[46] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_46_2_bit | DV_II_50_2_bit)) + MOVL W_47+188(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfeffffef, CX + ANDL CX, AX + + // mask &= ((0 - ((W[44] ^ (W[45] >> 5)) & (1 << 1))) | ^(DV_I_51_2_bit | DV_II_49_2_bit)) + MOVL W_44+176(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffbfbfff, CX + ANDL CX, AX + + // mask &= ((((W[43] ^ W[45]) & (1 << 6)) - (1 << 6)) | ^(DV_I_47_2_bit | DV_I_49_2_bit)) + MOVL W_43+172(FP), CX + MOVL W_45+180(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xfffffbbf, CX + ANDL CX, AX + + // mask &= (((((W[42] ^ W[44]) >> 6) & 1) - 1) | ^(DV_I_46_2_bit | DV_I_48_2_bit)) + MOVL W_42+168(FP), CX + MOVL W_44+176(FP), DX + XORL DX, CX + SHRL $0x06, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xfffffeef, CX + ANDL CX, AX + + // mask &= ((((W[43] ^ (W[42] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_II_46_2_bit | DV_II_51_2_bit)) + MOVL W_43+172(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfbfbffff, CX + ANDL CX, AX + + // mask &= ((((W[42] ^ (W[41] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_51_2_bit | DV_II_50_2_bit)) + MOVL W_42+168(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfeffbfff, CX + ANDL CX, AX + + // mask &= ((((W[41] ^ (W[40] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_50_2_bit | DV_II_49_2_bit)) + MOVL W_41+164(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xffbfefff, CX + ANDL CX, AX + + // if (mask & (DV_I_52_0_bit | DV_II_51_0_bit)) != 0 { + // mask &= ((((W[39] ^ (W[43] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_52_0_bit | DV_II_51_0_bit)) + // } + TESTL $0x02008000, AX + JE f35 + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xfdff7fff, CX + ANDL CX, AX + +f35: + // if (mask & (DV_I_51_0_bit | DV_II_50_0_bit)) != 0 { + // mask &= ((((W[38] ^ (W[42] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_51_0_bit | DV_II_50_0_bit)) + // } + TESTL $0x00802000, AX + JE f36 + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xff7fdfff, CX + ANDL CX, AX + +f36: + // if (mask & (DV_I_48_2_bit | DV_I_51_2_bit)) != 0 { + // mask &= ((0 - ((W[37] ^ (W[38] >> 5)) & (1 << 1))) | ^(DV_I_48_2_bit | DV_I_51_2_bit)) + // } + TESTL $0x00004100, AX + JE f37 + MOVL W_37+148(FP), CX + MOVL W_38+152(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffffbeff, CX + ANDL CX, AX + +f37: + // if (mask & (DV_I_50_0_bit | DV_II_49_0_bit)) != 0 { + // mask &= ((((W[37] ^ (W[41] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_50_0_bit | DV_II_49_0_bit)) + // } + TESTL $0x00200800, AX + JE f38 + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xffdff7ff, CX + ANDL CX, AX + +f38: + // if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= ((0 - ((W[36] ^ W[38]) & (1 << 4))) | ^(DV_II_52_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x28000000, AX + JE f39 + MOVL W_36+144(FP), CX + MOVL W_38+152(FP), DX + XORL DX, CX + ANDL $0x00000010, CX + NEGL CX + ORL $0xd7ffffff, CX + ANDL CX, AX + +f39: + // mask &= ((0 - ((W[35] ^ (W[36] >> 5)) & (1 << 1))) | ^(DV_I_46_2_bit | DV_I_49_2_bit)) + MOVL W_35+140(FP), CX + MOVL W_36+144(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffffbef, CX + ANDL CX, AX + + // if (mask & (DV_I_51_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((((W[35] ^ (W[39] >> 25)) & (1 << 3)) - (1 << 3)) | ^(DV_I_51_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00082000, AX + JE f40 + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + SUBL $0x00000008, CX + ORL $0xfff7dfff, CX + ANDL CX, AX + +f40: + // if mask != 0 + TESTL $0x00000000, AX + JNE end + + // if (mask & DV_I_43_0_bit) != 0 { + // if not((W[61]^(W[62]>>5))&(1<<1)) != 0 || + // not(not((W[59]^(W[63]>>25))&(1<<5))) != 0 || + // not((W[58]^(W[63]>>30))&(1<<0)) != 0 { + // mask &= ^DV_I_43_0_bit + // } + // } + BTL $0x00, AX + JNC f41_skip + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f41_in + MOVL W_59+236(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f41_in + MOVL W_58+232(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f41_in + JMP f41_skip + +f41_in: + ANDL $0xfffffffe, AX + +f41_skip: + // if (mask & DV_I_44_0_bit) != 0 { + // if not((W[62]^(W[63]>>5))&(1<<1)) != 0 || + // not(not((W[60]^(W[64]>>25))&(1<<5))) != 0 || + // not((W[59]^(W[64]>>30))&(1<<0)) != 0 { + // mask &= ^DV_I_44_0_bit + // } + // } + BTL $0x01, AX + JNC f42_skip + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f42_in + MOVL W_60+240(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f42_in + MOVL W_59+236(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f42_in + JMP f42_skip + +f42_in: + ANDL $0xfffffffd, AX + +f42_skip: + // if (mask & DV_I_46_2_bit) != 0 { + // mask &= ((^((W[40] ^ W[42]) >> 2)) | ^DV_I_46_2_bit) + // } + BTL $0x04, AX + JNC f43 + MOVL W_40+160(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x02, CX + NOTL CX + ORL $0xffffffef, CX + ANDL CX, AX + +f43: + // if (mask & DV_I_47_2_bit) != 0 { + // if not((W[62]^(W[63]>>5))&(1<<2)) != 0 || + // not(not((W[41]^W[43])&(1<<6))) != 0 { + // mask &= ^DV_I_47_2_bit + // } + // } + BTL $0x06, AX + JNC f44_skip + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + CMPL CX, $0x00000000 + JE f44_in + MOVL W_41+164(FP), CX + MOVL W_43+172(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f44_in + JMP f44_skip + +f44_in: + ANDL $0xffffffbf, AX + +f44_skip: + // if (mask & DV_I_48_2_bit) != 0 { + // if not((W[63]^(W[64]>>5))&(1<<2)) != 0 || + // not(not((W[48]^(W[49]<<5))&(1<<6))) != 0 { + // mask &= ^DV_I_48_2_bit + // } + // } + BTL $0x08, AX + JNC f45_skip + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + CMPL CX, $0x00000000 + JE f45_in + MOVL W_48+192(FP), CX + MOVL W_49+196(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f45_in + JMP f45_skip + +f45_in: + ANDL $0xfffffeff, AX + +f45_skip: + // if (mask & DV_I_49_2_bit) != 0 { + // if not(not((W[49]^(W[50]<<5))&(1<<6))) != 0 || + // not((W[42]^W[50])&(1<<1)) != 0 || + // not(not((W[39]^(W[40]<<5))&(1<<6))) != 0 || + // not((W[38]^W[40])&(1<<1)) != 0 { + // mask &= ^DV_I_49_2_bit + // } + // } + BTL $0x0a, AX + JNC f46_skip + MOVL W_49+196(FP), CX + MOVL W_50+200(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f46_in + MOVL W_42+168(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JE f46_in + MOVL W_39+156(FP), CX + MOVL W_40+160(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f46_in + MOVL W_38+152(FP), CX + MOVL W_40+160(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JE f46_in + JMP f46_skip + +f46_in: + ANDL $0xfffffbff, AX + +f46_skip: + // if (mask & DV_I_50_0_bit) != 0 { + // mask &= (((W[36] ^ W[37]) << 7) | ^DV_I_50_0_bit) + // } + BTL $0x0b, AX + JNC f47 + MOVL W_36+144(FP), CX + MOVL W_37+148(FP), DX + XORL DX, CX + SHLL $0x07, CX + ORL $0xfffff7ff, CX + ANDL CX, AX + +f47: + // if (mask & DV_I_50_2_bit) != 0 { + // mask &= (((W[43] ^ W[51]) << 11) | ^DV_I_50_2_bit) + // } + BTL $0x0c, AX + JNC f48 + MOVL W_43+172(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHLL $0x0b, CX + ORL $0xffffefff, CX + ANDL CX, AX + +f48: + // if (mask & DV_I_51_0_bit) != 0 { + // mask &= (((W[37] ^ W[38]) << 9) | ^DV_I_51_0_bit) + // } + BTL $0x0d, AX + JNC f49 + MOVL W_37+148(FP), CX + MOVL W_38+152(FP), DX + XORL DX, CX + SHLL $0x09, CX + ORL $0xffffdfff, CX + ANDL CX, AX + +f49: + // if (mask & DV_I_51_2_bit) != 0 { + // if not(not((W[51]^(W[52]<<5))&(1<<6))) != 0 || + // not(not((W[49]^W[51])&(1<<6))) != 0 || + // not(not((W[37]^(W[37]>>5))&(1<<1))) != 0 || + // not(not((W[35]^(W[39]>>25))&(1<<5))) != 0 { + // mask &= ^DV_I_51_2_bit + // } + // } + BTL $0x0e, AX + JNC f50_skip + MOVL W_51+204(FP), CX + MOVL W_52+208(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_49+196(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_37+148(FP), CX + MOVL W_37+148(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f50_in + JMP f50_skip + +f50_in: + ANDL $0xffffbfff, AX + +f50_skip: + // if (mask & DV_I_52_0_bit) != 0 { + // mask &= (((W[38] ^ W[39]) << 11) | ^DV_I_52_0_bit) + // } + BTL $0x0f, AX + JNC f51 + MOVL W_38+152(FP), CX + MOVL W_39+156(FP), DX + XORL DX, CX + SHLL $0x0b, CX + ORL $0xffff7fff, CX + ANDL CX, AX + +f51: + // if (mask & DV_II_46_2_bit) != 0 { + // mask &= (((W[47] ^ W[51]) << 17) | ^DV_II_46_2_bit) + // } + TESTL $0x00040000, AX + BTL $0x12, AX + JNC f52 + MOVL W_47+188(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHLL $0x11, CX + ORL $0xfffbffff, CX + ANDL CX, AX + +f52: + // if (mask & DV_II_48_0_bit) != 0 { + // if not(not((W[36]^(W[40]>>25))&(1<<3))) != 0 || + // not((W[35]^(W[40]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_48_0_bit + // } + // } + BTL $0x14, AX + JNC f53_skip + MOVL W_36+144(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f53_in + MOVL W_35+140(FP), CX + MOVL W_40+160(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + CMPL CX, $0x00000000 + JNE f53_in + JMP f53_skip + +f53_in: + ANDL $0xffefffff, AX + +f53_skip: + // if (mask & DV_II_49_0_bit) != 0 { + // if not(not((W[37]^(W[41]>>25))&(1<<3))) != 0 || + // not((W[36]^(W[41]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_49_0_bit + // } + // } + BTL $0x15, AX + JNC f54_skip + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f54_in + MOVL W_36+144(FP), CX + MOVL W_41+164(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + CMPL CX, $0x00000000 + JNE f54_in + JMP f54_skip + +f54_in: + ANDL $0xffdfffff, AX + +f54_skip: + // if (mask & DV_II_49_2_bit) != 0 { + // if not(not((W[53]^(W[54]<<5))&(1<<6))) != 0 || + // not(not((W[51]^W[53])&(1<<6))) != 0 || + // not((W[50]^W[54])&(1<<1)) != 0 || + // not(not((W[45]^(W[46]<<5))&(1<<6))) != 0 || + // not(not((W[37]^(W[41]>>25))&(1<<5))) != 0 || + // not((W[36]^(W[41]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_49_2_bit + // } + // } + BTL $0x16, AX + JNC f55_skip + MOVL W_53+212(FP), CX + MOVL W_54+216(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_51+204(FP), CX + MOVL W_53+212(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_50+200(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f55_in + MOVL W_45+180(FP), CX + MOVL W_46+184(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_36+144(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f55_in + JMP f55_skip + +f55_in: + ANDL $0xffbfffff, AX + +f55_skip: + // if (mask & DV_II_50_0_bit) != 0 { + // if not((W[55]^W[58])&(1<<29)) != 0 || + // not(not((W[38]^(W[42]>>25))&(1<<3))) != 0 || + // not((W[37]^(W[42]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_50_0_bit + // } + // } + BTL $0x17, AX + JNC f56_skip + MOVL W_55+220(FP), CX + MOVL W_58+232(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f56_in + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f56_in + MOVL W_37+148(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f56_in + JMP f56_skip + +f56_in: + ANDL $0xff7fffff, AX + +f56_skip: + // if (mask & DV_II_50_2_bit) != 0 { + // if not(not((W[54]^(W[55]<<5))&(1<<6))) != 0 || + // not(not((W[52]^W[54])&(1<<6))) != 0 || + // not((W[51]^W[55])&(1<<1)) != 0 || + // not((W[45]^W[47])&(1<<1)) != 0 || + // not(not((W[38]^(W[42]>>25))&(1<<5))) != 0 || + // not((W[37]^(W[42]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_50_2_bit + // } + // } + BTL $0x18, AX + JNC f57_skip + MOVL W_54+216(FP), CX + MOVL W_55+220(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_52+208(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_51+204(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_37+148(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + JMP f57_skip + +f57_in: + ANDL $0xfeffffff, AX + +f57_skip: + // if (mask & DV_II_51_0_bit) != 0 { + // if not(not((W[39]^(W[43]>>25))&(1<<3))) != 0 || + // not((W[38]^(W[43]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_51_0_bit + // } + // } + BTL $0x19, AX + JNC f58_skip + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f58_in + MOVL W_38+152(FP), CX + MOVL W_43+172(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f58_in + JMP f58_skip + +f58_in: + ANDL $0xfdffffff, AX + +f58_skip: + // if (mask & DV_II_51_2_bit) != 0 { + // if not(not((W[55]^(W[56]<<5))&(1<<6))) != 0 || + // not(not((W[53]^W[55])&(1<<6))) != 0 || + // not((W[52]^W[56])&(1<<1)) != 0 || + // not((W[46]^W[48])&(1<<1)) != 0 || + // not(not((W[39]^(W[43]>>25))&(1<<5))) != 0 || + // not((W[38]^(W[43]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_51_2_bit + // } + // } + BTL $0x1a, AX + JNC f59_skip + MOVL W_55+220(FP), CX + MOVL W_56+224(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_53+212(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_52+208(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_38+152(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + JMP f59_skip + +f59_in: + ANDL $0xfbffffff, AX + +f59_skip: + // if (mask & DV_II_52_0_bit) != 0 { + // if not(not((W[59]^W[60])&(1<<29))) != 0 || + // not(not((W[40]^(W[44]>>25))&(1<<3))) != 0 || + // not(not((W[40]^(W[44]>>25))&(1<<4))) != 0 || + // not((W[39]^(W[44]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_52_0_bit + // } + // } + BTL $0x1b, AX + JNC f60_skip + MOVL W_59+236(FP), CX + MOVL W_60+240(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_40+160(FP), CX + MOVL W_44+176(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_40+160(FP), CX + MOVL W_44+176(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_39+156(FP), CX + MOVL W_44+176(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f60_in + JMP f60_skip + +f60_in: + ANDL $0xf7ffffff, AX + +f60_skip: + // if (mask & DV_II_53_0_bit) != 0 { + // if not((W[58]^W[61])&(1<<29)) != 0 || + // not(not((W[57]^(W[61]>>25))&(1<<4))) != 0 || + // not(not((W[41]^(W[45]>>25))&(1<<3))) != 0 || + // not(not((W[41]^(W[45]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_53_0_bit + // } + // } + BTL $0x1c, AX + JNC f61_skip + MOVL W_58+232(FP), CX + MOVL W_61+244(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f61_in + MOVL W_57+228(FP), CX + MOVL W_61+244(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f61_in + MOVL W_41+164(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f61_in + MOVL W_41+164(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f61_in + JMP f61_skip + +f61_in: + ANDL $0xefffffff, AX + +f61_skip: + // if (mask & DV_II_54_0_bit) != 0 { + // if not(not((W[58]^(W[62]>>25))&(1<<4))) != 0 || + // not(not((W[42]^(W[46]>>25))&(1<<3))) != 0 || + // not(not((W[42]^(W[46]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_54_0_bit + // } + // } + BTL $0x1d, AX + JNC f62_skip + MOVL W_58+232(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f62_in + MOVL W_42+168(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f62_in + MOVL W_42+168(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f62_in + JMP f62_skip + +f62_in: + ANDL $0xdfffffff, AX + +f62_skip: + // if (mask & DV_II_55_0_bit) != 0 { + // if not(not((W[59]^(W[63]>>25))&(1<<4))) != 0 || + // not(not((W[57]^(W[59]>>25))&(1<<4))) != 0 || + // not(not((W[43]^(W[47]>>25))&(1<<3))) != 0 || + // not(not((W[43]^(W[47]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_55_0_bit + // } + // } + BTL $0x1e, AX + JNC f63_skip + MOVL W_59+236(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_57+228(FP), CX + MOVL W_59+236(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_43+172(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_43+172(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + JMP f63_skip + +f63_in: + ANDL $0xbfffffff, AX + +f63_skip: + // if (mask & DV_II_56_0_bit) != 0 { + // if not(not((W[60]^(W[64]>>25))&(1<<4))) != 0 || + // not(not((W[44]^(W[48]>>25))&(1<<3))) != 0 || + // not(not((W[44]^(W[48]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_56_0_bit + // } + // } + BTL $0x1f, AX + JNC f64_skip + MOVL W_60+240(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f64_in + MOVL W_44+176(FP), CX + MOVL W_48+192(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f64_in + MOVL W_44+176(FP), CX + MOVL W_48+192(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f64_in + JMP f64_skip + +f64_in: + ANDL $0x7fffffff, AX + +f64_skip: +end: + MOVL AX, ret+320(FP) + RET diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/check.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go similarity index 99% rename from vendor/github.com/pjbgf/sha1cd/ubc/check.go rename to vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go index 167a5558..ee95bd52 100644 --- a/vendor/github.com/pjbgf/sha1cd/ubc/check.go +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go @@ -25,7 +25,7 @@ type DvInfo struct { // for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all // unavoidable bitconditions for that DV have been met. // Thus, one needs to do the recompression check for each DV that has its bit set. -func CalculateDvMask(W [80]uint32) uint32 { +func CalculateDvMaskGeneric(W [80]uint32) uint32 { mask := uint32(0xFFFFFFFF) mask &= (((((W[44] ^ W[45]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)) mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go new file mode 100644 index 00000000..48d6dff1 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go @@ -0,0 +1,12 @@ +//go:build !amd64 || noasm || !gc +// +build !amd64 noasm !gc + +package ubc + +// Check takes as input an expanded message block and verifies the unavoidable bitconditions +// for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all +// unavoidable bitconditions for that DV have been met. +// Thus, one needs to do the recompression check for each DV that has its bit set. +func CalculateDvMask(W [80]uint32) uint32 { + return CalculateDvMaskGeneric(W) +} diff --git a/vendor/github.com/rivo/uniseg/LICENSE.txt b/vendor/github.com/rivo/uniseg/LICENSE.txt new file mode 100644 index 00000000..5040f1ef --- /dev/null +++ b/vendor/github.com/rivo/uniseg/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Oliver Kuederle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/rivo/uniseg/README.md b/vendor/github.com/rivo/uniseg/README.md new file mode 100644 index 00000000..f8da293e --- /dev/null +++ b/vendor/github.com/rivo/uniseg/README.md @@ -0,0 +1,62 @@ +# Unicode Text Segmentation for Go + +[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/rivo/uniseg) +[![Go Report](https://img.shields.io/badge/go%20report-A%2B-brightgreen.svg)](https://goreportcard.com/report/github.com/rivo/uniseg) + +This Go package implements Unicode Text Segmentation according to [Unicode Standard Annex #29](http://unicode.org/reports/tr29/) (Unicode version 12.0.0). + +At this point, only the determination of grapheme cluster boundaries is implemented. + +## Background + +In Go, [strings are read-only slices of bytes](https://blog.golang.org/strings). They can be turned into Unicode code points using the `for` loop or by casting: `[]rune(str)`. However, multiple code points may be combined into one user-perceived character or what the Unicode specification calls "grapheme cluster". Here are some examples: + +|String|Bytes (UTF-8)|Code points (runes)|Grapheme clusters| +|-|-|-|-| +|Käse|6 bytes: `4b 61 cc 88 73 65`|5 code points: `4b 61 308 73 65`|4 clusters: `[4b],[61 308],[73],[65]`| +|🏳️‍🌈|14 bytes: `f0 9f 8f b3 ef b8 8f e2 80 8d f0 9f 8c 88`|4 code points: `1f3f3 fe0f 200d 1f308`|1 cluster: `[1f3f3 fe0f 200d 1f308]`| +|🇩🇪|8 bytes: `f0 9f 87 a9 f0 9f 87 aa`|2 code points: `1f1e9 1f1ea`|1 cluster: `[1f1e9 1f1ea]`| + +This package provides a tool to iterate over these grapheme clusters. This may be used to determine the number of user-perceived characters, to split strings in their intended places, or to extract individual characters which form a unit. + +## Installation + +```bash +go get github.com/rivo/uniseg +``` + +## Basic Example + +```go +package uniseg + +import ( + "fmt" + + "github.com/rivo/uniseg" +) + +func main() { + gr := uniseg.NewGraphemes("👍🏼!") + for gr.Next() { + fmt.Printf("%x ", gr.Runes()) + } + // Output: [1f44d 1f3fc] [21] +} +``` + +## Documentation + +Refer to https://godoc.org/github.com/rivo/uniseg for the package's documentation. + +## Dependencies + +This package does not depend on any packages outside the standard library. + +## Your Feedback + +Add your issue here on GitHub. Feel free to get in touch if you have any questions. + +## Version + +Version tags will be introduced once Golang modules are official. Consider this version 0.1. diff --git a/vendor/github.com/rivo/uniseg/doc.go b/vendor/github.com/rivo/uniseg/doc.go new file mode 100644 index 00000000..60c737d7 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/doc.go @@ -0,0 +1,8 @@ +/* +Package uniseg implements Unicode Text Segmentation according to Unicode +Standard Annex #29 (http://unicode.org/reports/tr29/). + +At this point, only the determination of grapheme cluster boundaries is +implemented. +*/ +package uniseg diff --git a/vendor/github.com/rivo/uniseg/grapheme.go b/vendor/github.com/rivo/uniseg/grapheme.go new file mode 100644 index 00000000..207157f5 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/grapheme.go @@ -0,0 +1,268 @@ +package uniseg + +import "unicode/utf8" + +// The states of the grapheme cluster parser. +const ( + grAny = iota + grCR + grControlLF + grL + grLVV + grLVTT + grPrepend + grExtendedPictographic + grExtendedPictographicZWJ + grRIOdd + grRIEven +) + +// The grapheme cluster parser's breaking instructions. +const ( + grNoBoundary = iota + grBoundary +) + +// The grapheme cluster parser's state transitions. Maps (state, property) to +// (new state, breaking instruction, rule number). The breaking instruction +// always refers to the boundary between the last and next code point. +// +// This map is queried as follows: +// +// 1. Find specific state + specific property. Stop if found. +// 2. Find specific state + any property. +// 3. Find any state + specific property. +// 4. If only (2) or (3) (but not both) was found, stop. +// 5. If both (2) and (3) were found, use state and breaking instruction from +// the transition with the lower rule number, prefer (3) if rule numbers +// are equal. Stop. +// 6. Assume grAny and grBoundary. +var grTransitions = map[[2]int][3]int{ + // GB5 + {grAny, prCR}: {grCR, grBoundary, 50}, + {grAny, prLF}: {grControlLF, grBoundary, 50}, + {grAny, prControl}: {grControlLF, grBoundary, 50}, + + // GB4 + {grCR, prAny}: {grAny, grBoundary, 40}, + {grControlLF, prAny}: {grAny, grBoundary, 40}, + + // GB3. + {grCR, prLF}: {grAny, grNoBoundary, 30}, + + // GB6. + {grAny, prL}: {grL, grBoundary, 9990}, + {grL, prL}: {grL, grNoBoundary, 60}, + {grL, prV}: {grLVV, grNoBoundary, 60}, + {grL, prLV}: {grLVV, grNoBoundary, 60}, + {grL, prLVT}: {grLVTT, grNoBoundary, 60}, + + // GB7. + {grAny, prLV}: {grLVV, grBoundary, 9990}, + {grAny, prV}: {grLVV, grBoundary, 9990}, + {grLVV, prV}: {grLVV, grNoBoundary, 70}, + {grLVV, prT}: {grLVTT, grNoBoundary, 70}, + + // GB8. + {grAny, prLVT}: {grLVTT, grBoundary, 9990}, + {grAny, prT}: {grLVTT, grBoundary, 9990}, + {grLVTT, prT}: {grLVTT, grNoBoundary, 80}, + + // GB9. + {grAny, prExtend}: {grAny, grNoBoundary, 90}, + {grAny, prZWJ}: {grAny, grNoBoundary, 90}, + + // GB9a. + {grAny, prSpacingMark}: {grAny, grNoBoundary, 91}, + + // GB9b. + {grAny, prPreprend}: {grPrepend, grBoundary, 9990}, + {grPrepend, prAny}: {grAny, grNoBoundary, 92}, + + // GB11. + {grAny, prExtendedPictographic}: {grExtendedPictographic, grBoundary, 9990}, + {grExtendedPictographic, prExtend}: {grExtendedPictographic, grNoBoundary, 110}, + {grExtendedPictographic, prZWJ}: {grExtendedPictographicZWJ, grNoBoundary, 110}, + {grExtendedPictographicZWJ, prExtendedPictographic}: {grExtendedPictographic, grNoBoundary, 110}, + + // GB12 / GB13. + {grAny, prRegionalIndicator}: {grRIOdd, grBoundary, 9990}, + {grRIOdd, prRegionalIndicator}: {grRIEven, grNoBoundary, 120}, + {grRIEven, prRegionalIndicator}: {grRIOdd, grBoundary, 120}, +} + +// Graphemes implements an iterator over Unicode extended grapheme clusters, +// specified in the Unicode Standard Annex #29. Grapheme clusters correspond to +// "user-perceived characters". These characters often consist of multiple +// code points (e.g. the "woman kissing woman" emoji consists of 8 code points: +// woman + ZWJ + heavy black heart (2 code points) + ZWJ + kiss mark + ZWJ + +// woman) and the rules described in Annex #29 must be applied to group those +// code points into clusters perceived by the user as one character. +type Graphemes struct { + // The code points over which this class iterates. + codePoints []rune + + // The (byte-based) indices of the code points into the original string plus + // len(original string). Thus, len(indices) = len(codePoints) + 1. + indices []int + + // The current grapheme cluster to be returned. These are indices into + // codePoints/indices. If start == end, we either haven't started iterating + // yet (0) or the iteration has already completed (1). + start, end int + + // The index of the next code point to be parsed. + pos int + + // The current state of the code point parser. + state int +} + +// NewGraphemes returns a new grapheme cluster iterator. +func NewGraphemes(s string) *Graphemes { + l := utf8.RuneCountInString(s) + codePoints := make([]rune, l) + indices := make([]int, l+1) + i := 0 + for pos, r := range s { + codePoints[i] = r + indices[i] = pos + i++ + } + indices[l] = len(s) + g := &Graphemes{ + codePoints: codePoints, + indices: indices, + } + g.Next() // Parse ahead. + return g +} + +// Next advances the iterator by one grapheme cluster and returns false if no +// clusters are left. This function must be called before the first cluster is +// accessed. +func (g *Graphemes) Next() bool { + g.start = g.end + + // The state transition gives us a boundary instruction BEFORE the next code + // point so we always need to stay ahead by one code point. + + // Parse the next code point. + for g.pos <= len(g.codePoints) { + // GB2. + if g.pos == len(g.codePoints) { + g.end = g.pos + g.pos++ + break + } + + // Determine the property of the next character. + nextProperty := property(g.codePoints[g.pos]) + g.pos++ + + // Find the applicable transition. + var boundary bool + transition, ok := grTransitions[[2]int{g.state, nextProperty}] + if ok { + // We have a specific transition. We'll use it. + g.state = transition[0] + boundary = transition[1] == grBoundary + } else { + // No specific transition found. Try the less specific ones. + transAnyProp, okAnyProp := grTransitions[[2]int{g.state, prAny}] + transAnyState, okAnyState := grTransitions[[2]int{grAny, nextProperty}] + if okAnyProp && okAnyState { + // Both apply. We'll use a mix (see comments for grTransitions). + g.state = transAnyState[0] + boundary = transAnyState[1] == grBoundary + if transAnyProp[2] < transAnyState[2] { + g.state = transAnyProp[0] + boundary = transAnyProp[1] == grBoundary + } + } else if okAnyProp { + // We only have a specific state. + g.state = transAnyProp[0] + boundary = transAnyProp[1] == grBoundary + // This branch will probably never be reached because okAnyState will + // always be true given the current transition map. But we keep it here + // for future modifications to the transition map where this may not be + // true anymore. + } else if okAnyState { + // We only have a specific property. + g.state = transAnyState[0] + boundary = transAnyState[1] == grBoundary + } else { + // No known transition. GB999: Any x Any. + g.state = grAny + boundary = true + } + } + + // If we found a cluster boundary, let's stop here. The current cluster will + // be the one that just ended. + if g.pos-1 == 0 /* GB1 */ || boundary { + g.end = g.pos - 1 + break + } + } + + return g.start != g.end +} + +// Runes returns a slice of runes (code points) which corresponds to the current +// grapheme cluster. If the iterator is already past the end or Next() has not +// yet been called, nil is returned. +func (g *Graphemes) Runes() []rune { + if g.start == g.end { + return nil + } + return g.codePoints[g.start:g.end] +} + +// Str returns a substring of the original string which corresponds to the +// current grapheme cluster. If the iterator is already past the end or Next() +// has not yet been called, an empty string is returned. +func (g *Graphemes) Str() string { + if g.start == g.end { + return "" + } + return string(g.codePoints[g.start:g.end]) +} + +// Bytes returns a byte slice which corresponds to the current grapheme cluster. +// If the iterator is already past the end or Next() has not yet been called, +// nil is returned. +func (g *Graphemes) Bytes() []byte { + if g.start == g.end { + return nil + } + return []byte(string(g.codePoints[g.start:g.end])) +} + +// Positions returns the interval of the current grapheme cluster as byte +// positions into the original string. The first returned value "from" indexes +// the first byte and the second returned value "to" indexes the first byte that +// is not included anymore, i.e. str[from:to] is the current grapheme cluster of +// the original string "str". If Next() has not yet been called, both values are +// 0. If the iterator is already past the end, both values are 1. +func (g *Graphemes) Positions() (int, int) { + return g.indices[g.start], g.indices[g.end] +} + +// Reset puts the iterator into its initial state such that the next call to +// Next() sets it to the first grapheme cluster again. +func (g *Graphemes) Reset() { + g.start, g.end, g.pos, g.state = 0, 0, 0, grAny + g.Next() // Parse ahead again. +} + +// GraphemeClusterCount returns the number of user-perceived characters +// (grapheme clusters) for the given string. To calculate this number, it +// iterates through the string using the Graphemes iterator. +func GraphemeClusterCount(s string) (n int) { + g := NewGraphemes(s) + for g.Next() { + n++ + } + return +} diff --git a/vendor/github.com/rivo/uniseg/properties.go b/vendor/github.com/rivo/uniseg/properties.go new file mode 100644 index 00000000..a75ab588 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/properties.go @@ -0,0 +1,1658 @@ +package uniseg + +// The unicode properties. Only the ones needed in the context of this package +// are included. +const ( + prAny = iota + prPreprend + prCR + prLF + prControl + prExtend + prRegionalIndicator + prSpacingMark + prL + prV + prT + prLV + prLVT + prZWJ + prExtendedPictographic +) + +// Maps code point ranges to their properties. In the context of this package, +// any code point that is not contained may map to "prAny". The code point +// ranges in this slice are numerically sorted. +// +// These ranges were taken from +// http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt +// as well as +// https://unicode.org/Public/emoji/latest/emoji-data.txt +// ("Extended_Pictographic" only) on March 11, 2019. See +// https://www.unicode.org/license.html for the Unicode license agreement. +var codePoints = [][3]int{ + {0x0000, 0x0009, prControl}, // Cc [10] .. + {0x000A, 0x000A, prLF}, // Cc + {0x000B, 0x000C, prControl}, // Cc [2] .. + {0x000D, 0x000D, prCR}, // Cc + {0x000E, 0x001F, prControl}, // Cc [18] .. + {0x007F, 0x009F, prControl}, // Cc [33] .. + {0x00A9, 0x00A9, prExtendedPictographic}, // 1.1 [1] (©️) copyright + {0x00AD, 0x00AD, prControl}, // Cf SOFT HYPHEN + {0x00AE, 0x00AE, prExtendedPictographic}, // 1.1 [1] (®️) registered + {0x0300, 0x036F, prExtend}, // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X + {0x0483, 0x0487, prExtend}, // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prExtend}, // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x0591, 0x05BD, prExtend}, // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BF, 0x05BF, prExtend}, // Mn HEBREW POINT RAFE + {0x05C1, 0x05C2, prExtend}, // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C4, 0x05C5, prExtend}, // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C7, 0x05C7, prExtend}, // Mn HEBREW POINT QAMATS QATAN + {0x0600, 0x0605, prPreprend}, // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x0610, 0x061A, prExtend}, // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061C, 0x061C, prControl}, // Cf ARABIC LETTER MARK + {0x064B, 0x065F, prExtend}, // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0670, 0x0670, prExtend}, // Mn ARABIC LETTER SUPERSCRIPT ALEF + {0x06D6, 0x06DC, prExtend}, // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prPreprend}, // Cf ARABIC END OF AYAH + {0x06DF, 0x06E4, prExtend}, // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E7, 0x06E8, prExtend}, // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06EA, 0x06ED, prExtend}, // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x070F, 0x070F, prPreprend}, // Cf SYRIAC ABBREVIATION MARK + {0x0711, 0x0711, prExtend}, // Mn SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0730, 0x074A, prExtend}, // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x07A6, 0x07B0, prExtend}, // Mn [11] THAANA ABAFILI..THAANA SUKUN + {0x07EB, 0x07F3, prExtend}, // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07FD, 0x07FD, prExtend}, // Mn NKO DANTAYALAN + {0x0816, 0x0819, prExtend}, // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081B, 0x0823, prExtend}, // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0825, 0x0827, prExtend}, // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0829, 0x082D, prExtend}, // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0859, 0x085B, prExtend}, // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x08D3, 0x08E1, prExtend}, // Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prPreprend}, // Cf ARABIC DISPUTED END OF AYAH + {0x08E3, 0x0902, prExtend}, // Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prSpacingMark}, // Mc DEVANAGARI SIGN VISARGA + {0x093A, 0x093A, prExtend}, // Mn DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prSpacingMark}, // Mc DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prExtend}, // Mn DEVANAGARI SIGN NUKTA + {0x093E, 0x0940, prSpacingMark}, // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prExtend}, // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prSpacingMark}, // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prExtend}, // Mn DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prSpacingMark}, // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0951, 0x0957, prExtend}, // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0962, 0x0963, prExtend}, // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0981, 0x0981, prExtend}, // Mn BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prSpacingMark}, // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x09BC, 0x09BC, prExtend}, // Mn BENGALI SIGN NUKTA + {0x09BE, 0x09BE, prExtend}, // Mc BENGALI VOWEL SIGN AA + {0x09BF, 0x09C0, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN I..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prExtend}, // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prExtend}, // Mn BENGALI SIGN VIRAMA + {0x09D7, 0x09D7, prExtend}, // Mc BENGALI AU LENGTH MARK + {0x09E2, 0x09E3, prExtend}, // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09FE, 0x09FE, prExtend}, // Mn BENGALI SANDHI MARK + {0x0A01, 0x0A02, prExtend}, // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prSpacingMark}, // Mc GURMUKHI SIGN VISARGA + {0x0A3C, 0x0A3C, prExtend}, // Mn GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prSpacingMark}, // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prExtend}, // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prExtend}, // Mn GURMUKHI SIGN UDAAT + {0x0A70, 0x0A71, prExtend}, // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A75, 0x0A75, prExtend}, // Mn GURMUKHI SIGN YAKASH + {0x0A81, 0x0A82, prExtend}, // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prSpacingMark}, // Mc GUJARATI SIGN VISARGA + {0x0ABC, 0x0ABC, prExtend}, // Mn GUJARATI SIGN NUKTA + {0x0ABE, 0x0AC0, prSpacingMark}, // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prExtend}, // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prExtend}, // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prSpacingMark}, // Mc GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prSpacingMark}, // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prExtend}, // Mn GUJARATI SIGN VIRAMA + {0x0AE2, 0x0AE3, prExtend}, // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AFA, 0x0AFF, prExtend}, // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prExtend}, // Mn ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prSpacingMark}, // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B3C, 0x0B3C, prExtend}, // Mn ORIYA SIGN NUKTA + {0x0B3E, 0x0B3E, prExtend}, // Mc ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prExtend}, // Mn ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prSpacingMark}, // Mc ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prExtend}, // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prSpacingMark}, // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prSpacingMark}, // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prExtend}, // Mn ORIYA SIGN VIRAMA + {0x0B56, 0x0B56, prExtend}, // Mn ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prExtend}, // Mc ORIYA AU LENGTH MARK + {0x0B62, 0x0B63, prExtend}, // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B82, 0x0B82, prExtend}, // Mn TAMIL SIGN ANUSVARA + {0x0BBE, 0x0BBE, prExtend}, // Mc TAMIL VOWEL SIGN AA + {0x0BBF, 0x0BBF, prSpacingMark}, // Mc TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prExtend}, // Mn TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prSpacingMark}, // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prSpacingMark}, // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prSpacingMark}, // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prExtend}, // Mn TAMIL SIGN VIRAMA + {0x0BD7, 0x0BD7, prExtend}, // Mc TAMIL AU LENGTH MARK + {0x0C00, 0x0C00, prExtend}, // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prSpacingMark}, // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prExtend}, // Mn TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C3E, 0x0C40, prExtend}, // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prSpacingMark}, // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prExtend}, // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prExtend}, // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prExtend}, // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C62, 0x0C63, prExtend}, // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C81, 0x0C81, prExtend}, // Mn KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prSpacingMark}, // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0CBC, 0x0CBC, prExtend}, // Mn KANNADA SIGN NUKTA + {0x0CBE, 0x0CBE, prSpacingMark}, // Mc KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prExtend}, // Mn KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC1, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN U + {0x0CC2, 0x0CC2, prExtend}, // Mc KANNADA VOWEL SIGN UU + {0x0CC3, 0x0CC4, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN VOCALIC R..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prExtend}, // Mn KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prExtend}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prExtend}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prSpacingMark}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D3B, 0x0D3C, prExtend}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3E, 0x0D3E, prExtend}, // Mc MALAYALAM VOWEL SIGN AA + {0x0D3F, 0x0D40, prSpacingMark}, // Mc [2] MALAYALAM VOWEL SIGN I..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prExtend}, // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prSpacingMark}, // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prSpacingMark}, // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prExtend}, // Mn MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prPreprend}, // Lo MALAYALAM LETTER DOT REPH + {0x0D57, 0x0D57, prExtend}, // Mc MALAYALAM AU LENGTH MARK + {0x0D62, 0x0D63, prExtend}, // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D82, 0x0D83, prSpacingMark}, // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0DCA, 0x0DCA, prExtend}, // Mn SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DCF, prExtend}, // Mc SINHALA VOWEL SIGN AELA-PILLA + {0x0DD0, 0x0DD1, prSpacingMark}, // Mc [2] SINHALA VOWEL SIGN KETTI AEDA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prExtend}, // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prExtend}, // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDE, prSpacingMark}, // Mc [7] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA + {0x0DDF, 0x0DDF, prExtend}, // Mc SINHALA VOWEL SIGN GAYANUKITTA + {0x0DF2, 0x0DF3, prSpacingMark}, // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0E31, 0x0E31, prExtend}, // Mn THAI CHARACTER MAI HAN-AKAT + {0x0E33, 0x0E33, prSpacingMark}, // Lo THAI CHARACTER SARA AM + {0x0E34, 0x0E3A, prExtend}, // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E47, 0x0E4E, prExtend}, // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN + {0x0EB3, 0x0EB3, prSpacingMark}, // Lo LAO VOWEL SIGN AM + {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EC8, 0x0ECD, prExtend}, // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F35, 0x0F35, prExtend}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F37, 0x0F37, prExtend}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F39, 0x0F39, prExtend}, // Mn TIBETAN MARK TSA -PHRU + {0x0F3E, 0x0F3F, prSpacingMark}, // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F71, 0x0F7E, prExtend}, // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prSpacingMark}, // Mc TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prExtend}, // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F86, 0x0F87, prExtend}, // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F8D, 0x0F97, prExtend}, // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prExtend}, // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FC6, 0x0FC6, prExtend}, // Mn TIBETAN SYMBOL PADMA GDAN + {0x102D, 0x1030, prExtend}, // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prSpacingMark}, // Mc MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prExtend}, // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1039, 0x103A, prExtend}, // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prSpacingMark}, // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prExtend}, // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x1056, 0x1057, prSpacingMark}, // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prExtend}, // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105E, 0x1060, prExtend}, // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1071, 0x1074, prExtend}, // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1082, 0x1082, prExtend}, // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1084, 0x1084, prSpacingMark}, // Mc MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prExtend}, // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x108D, 0x108D, prExtend}, // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x109D, 0x109D, prExtend}, // Mn MYANMAR VOWEL SIGN AITON AI + {0x1100, 0x115F, prL}, // Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER + {0x1160, 0x11A7, prV}, // Lo [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE + {0x11A8, 0x11FF, prT}, // Lo [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN + {0x135D, 0x135F, prExtend}, // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1712, 0x1714, prExtend}, // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1732, 0x1734, prExtend}, // Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD + {0x1752, 0x1753, prExtend}, // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1772, 0x1773, prExtend}, // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x17B4, 0x17B5, prExtend}, // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prSpacingMark}, // Mc KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prExtend}, // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prSpacingMark}, // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prExtend}, // Mn KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prSpacingMark}, // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prExtend}, // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17DD, 0x17DD, prExtend}, // Mn KHMER SIGN ATTHACAN + {0x180B, 0x180D, prExtend}, // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prControl}, // Cf MONGOLIAN VOWEL SEPARATOR + {0x1885, 0x1886, prExtend}, // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x18A9, 0x18A9, prExtend}, // Mn MONGOLIAN LETTER ALI GALI DAGALGA + {0x1920, 0x1922, prExtend}, // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prSpacingMark}, // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prExtend}, // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prSpacingMark}, // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prSpacingMark}, // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prExtend}, // Mn LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prSpacingMark}, // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prExtend}, // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1A17, 0x1A18, prExtend}, // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prSpacingMark}, // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prExtend}, // Mn BUGINESE VOWEL SIGN AE + {0x1A55, 0x1A55, prSpacingMark}, // Mc TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prExtend}, // Mn TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prSpacingMark}, // Mc TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prExtend}, // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prExtend}, // Mn TAI THAM SIGN SAKOT + {0x1A62, 0x1A62, prExtend}, // Mn TAI THAM VOWEL SIGN MAI SAT + {0x1A65, 0x1A6C, prExtend}, // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prSpacingMark}, // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prExtend}, // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prExtend}, // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1AB0, 0x1ABD, prExtend}, // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prExtend}, // Me COMBINING PARENTHESES OVERLAY + {0x1B00, 0x1B03, prExtend}, // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prSpacingMark}, // Mc BALINESE SIGN BISAH + {0x1B34, 0x1B34, prExtend}, // Mn BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prExtend}, // Mc BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prExtend}, // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prSpacingMark}, // Mc BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prExtend}, // Mn BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prSpacingMark}, // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prExtend}, // Mn BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prSpacingMark}, // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B6B, 0x1B73, prExtend}, // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B80, 0x1B81, prExtend}, // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prSpacingMark}, // Mc SUNDANESE SIGN PANGWISAD + {0x1BA1, 0x1BA1, prSpacingMark}, // Mc SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prExtend}, // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prSpacingMark}, // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prExtend}, // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prSpacingMark}, // Mc SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prExtend}, // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BE6, 0x1BE6, prExtend}, // Mn BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prSpacingMark}, // Mc BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prExtend}, // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prSpacingMark}, // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prExtend}, // Mn BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prSpacingMark}, // Mc BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prExtend}, // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prSpacingMark}, // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1C24, 0x1C2B, prSpacingMark}, // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prExtend}, // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prSpacingMark}, // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prExtend}, // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1CD0, 0x1CD2, prExtend}, // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD4, 0x1CE0, prExtend}, // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prSpacingMark}, // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prExtend}, // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CED, 0x1CED, prExtend}, // Mn VEDIC SIGN TIRYAK + {0x1CF4, 0x1CF4, prExtend}, // Mn VEDIC TONE CANDRA ABOVE + {0x1CF7, 0x1CF7, prSpacingMark}, // Mc VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prExtend}, // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1DC0, 0x1DF9, prExtend}, // Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW + {0x1DFB, 0x1DFF, prExtend}, // Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x200B, 0x200B, prControl}, // Cf ZERO WIDTH SPACE + {0x200C, 0x200C, prExtend}, // Cf ZERO WIDTH NON-JOINER + {0x200D, 0x200D, prZWJ}, // Cf ZERO WIDTH JOINER + {0x200E, 0x200F, prControl}, // Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK + {0x2028, 0x2028, prControl}, // Zl LINE SEPARATOR + {0x2029, 0x2029, prControl}, // Zp PARAGRAPH SEPARATOR + {0x202A, 0x202E, prControl}, // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x203C, 0x203C, prExtendedPictographic}, // 1.1 [1] (‼️) double exclamation mark + {0x2049, 0x2049, prExtendedPictographic}, // 3.0 [1] (⁉️) exclamation question mark + {0x2060, 0x2064, prControl}, // Cf [5] WORD JOINER..INVISIBLE PLUS + {0x2065, 0x2065, prControl}, // Cn + {0x2066, 0x206F, prControl}, // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x20D0, 0x20DC, prExtend}, // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prExtend}, // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prExtend}, // Mn COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prExtend}, // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prExtend}, // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2122, 0x2122, prExtendedPictographic}, // 1.1 [1] (™️) trade mark + {0x2139, 0x2139, prExtendedPictographic}, // 3.0 [1] (ℹ️) information + {0x2194, 0x2199, prExtendedPictographic}, // 1.1 [6] (↔️..↙️) left-right arrow..down-left arrow + {0x21A9, 0x21AA, prExtendedPictographic}, // 1.1 [2] (↩️..↪️) right arrow curving left..left arrow curving right + {0x231A, 0x231B, prExtendedPictographic}, // 1.1 [2] (⌚..⌛) watch..hourglass done + {0x2328, 0x2328, prExtendedPictographic}, // 1.1 [1] (⌨️) keyboard + {0x2388, 0x2388, prExtendedPictographic}, // 3.0 [1] (⎈) HELM SYMBOL + {0x23CF, 0x23CF, prExtendedPictographic}, // 4.0 [1] (⏏️) eject button + {0x23E9, 0x23F3, prExtendedPictographic}, // 6.0 [11] (⏩..⏳) fast-forward button..hourglass not done + {0x23F8, 0x23FA, prExtendedPictographic}, // 7.0 [3] (⏸️..⏺️) pause button..record button + {0x24C2, 0x24C2, prExtendedPictographic}, // 1.1 [1] (Ⓜ️) circled M + {0x25AA, 0x25AB, prExtendedPictographic}, // 1.1 [2] (▪️..▫️) black small square..white small square + {0x25B6, 0x25B6, prExtendedPictographic}, // 1.1 [1] (▶️) play button + {0x25C0, 0x25C0, prExtendedPictographic}, // 1.1 [1] (◀️) reverse button + {0x25FB, 0x25FE, prExtendedPictographic}, // 3.2 [4] (◻️..◾) white medium square..black medium-small square + {0x2600, 0x2605, prExtendedPictographic}, // 1.1 [6] (☀️..★) sun..BLACK STAR + {0x2607, 0x2612, prExtendedPictographic}, // 1.1 [12] (☇..☒) LIGHTNING..BALLOT BOX WITH X + {0x2614, 0x2615, prExtendedPictographic}, // 4.0 [2] (☔..☕) umbrella with rain drops..hot beverage + {0x2616, 0x2617, prExtendedPictographic}, // 3.2 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE + {0x2618, 0x2618, prExtendedPictographic}, // 4.1 [1] (☘️) shamrock + {0x2619, 0x2619, prExtendedPictographic}, // 3.0 [1] (☙) REVERSED ROTATED FLORAL HEART BULLET + {0x261A, 0x266F, prExtendedPictographic}, // 1.1 [86] (☚..♯) BLACK LEFT POINTING INDEX..MUSIC SHARP SIGN + {0x2670, 0x2671, prExtendedPictographic}, // 3.0 [2] (♰..♱) WEST SYRIAC CROSS..EAST SYRIAC CROSS + {0x2672, 0x267D, prExtendedPictographic}, // 3.2 [12] (♲..♽) UNIVERSAL RECYCLING SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL + {0x267E, 0x267F, prExtendedPictographic}, // 4.1 [2] (♾️..♿) infinity..wheelchair symbol + {0x2680, 0x2685, prExtendedPictographic}, // 3.2 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6 + {0x2690, 0x2691, prExtendedPictographic}, // 4.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG + {0x2692, 0x269C, prExtendedPictographic}, // 4.1 [11] (⚒️..⚜️) hammer and pick..fleur-de-lis + {0x269D, 0x269D, prExtendedPictographic}, // 5.1 [1] (⚝) OUTLINED WHITE STAR + {0x269E, 0x269F, prExtendedPictographic}, // 5.2 [2] (⚞..⚟) THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT + {0x26A0, 0x26A1, prExtendedPictographic}, // 4.0 [2] (⚠️..⚡) warning..high voltage + {0x26A2, 0x26B1, prExtendedPictographic}, // 4.1 [16] (⚢..⚱️) DOUBLED FEMALE SIGN..funeral urn + {0x26B2, 0x26B2, prExtendedPictographic}, // 5.0 [1] (⚲) NEUTER + {0x26B3, 0x26BC, prExtendedPictographic}, // 5.1 [10] (⚳..⚼) CERES..SESQUIQUADRATE + {0x26BD, 0x26BF, prExtendedPictographic}, // 5.2 [3] (⚽..⚿) soccer ball..SQUARED KEY + {0x26C0, 0x26C3, prExtendedPictographic}, // 5.1 [4] (⛀..⛃) WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING + {0x26C4, 0x26CD, prExtendedPictographic}, // 5.2 [10] (⛄..⛍) snowman without snow..DISABLED CAR + {0x26CE, 0x26CE, prExtendedPictographic}, // 6.0 [1] (⛎) Ophiuchus + {0x26CF, 0x26E1, prExtendedPictographic}, // 5.2 [19] (⛏️..⛡) pick..RESTRICTED LEFT ENTRY-2 + {0x26E2, 0x26E2, prExtendedPictographic}, // 6.0 [1] (⛢) ASTRONOMICAL SYMBOL FOR URANUS + {0x26E3, 0x26E3, prExtendedPictographic}, // 5.2 [1] (⛣) HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE + {0x26E4, 0x26E7, prExtendedPictographic}, // 6.0 [4] (⛤..⛧) PENTAGRAM..INVERTED PENTAGRAM + {0x26E8, 0x26FF, prExtendedPictographic}, // 5.2 [24] (⛨..⛿) BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE + {0x2700, 0x2700, prExtendedPictographic}, // 7.0 [1] (✀) BLACK SAFETY SCISSORS + {0x2701, 0x2704, prExtendedPictographic}, // 1.1 [4] (✁..✄) UPPER BLADE SCISSORS..WHITE SCISSORS + {0x2705, 0x2705, prExtendedPictographic}, // 6.0 [1] (✅) check mark button + {0x2708, 0x2709, prExtendedPictographic}, // 1.1 [2] (✈️..✉️) airplane..envelope + {0x270A, 0x270B, prExtendedPictographic}, // 6.0 [2] (✊..✋) raised fist..raised hand + {0x270C, 0x2712, prExtendedPictographic}, // 1.1 [7] (✌️..✒️) victory hand..black nib + {0x2714, 0x2714, prExtendedPictographic}, // 1.1 [1] (✔️) check mark + {0x2716, 0x2716, prExtendedPictographic}, // 1.1 [1] (✖️) multiplication sign + {0x271D, 0x271D, prExtendedPictographic}, // 1.1 [1] (✝️) latin cross + {0x2721, 0x2721, prExtendedPictographic}, // 1.1 [1] (✡️) star of David + {0x2728, 0x2728, prExtendedPictographic}, // 6.0 [1] (✨) sparkles + {0x2733, 0x2734, prExtendedPictographic}, // 1.1 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star + {0x2744, 0x2744, prExtendedPictographic}, // 1.1 [1] (❄️) snowflake + {0x2747, 0x2747, prExtendedPictographic}, // 1.1 [1] (❇️) sparkle + {0x274C, 0x274C, prExtendedPictographic}, // 6.0 [1] (❌) cross mark + {0x274E, 0x274E, prExtendedPictographic}, // 6.0 [1] (❎) cross mark button + {0x2753, 0x2755, prExtendedPictographic}, // 6.0 [3] (❓..❕) question mark..white exclamation mark + {0x2757, 0x2757, prExtendedPictographic}, // 5.2 [1] (❗) exclamation mark + {0x2763, 0x2767, prExtendedPictographic}, // 1.1 [5] (❣️..❧) heart exclamation..ROTATED FLORAL HEART BULLET + {0x2795, 0x2797, prExtendedPictographic}, // 6.0 [3] (➕..➗) plus sign..division sign + {0x27A1, 0x27A1, prExtendedPictographic}, // 1.1 [1] (➡️) right arrow + {0x27B0, 0x27B0, prExtendedPictographic}, // 6.0 [1] (➰) curly loop + {0x27BF, 0x27BF, prExtendedPictographic}, // 6.0 [1] (➿) double curly loop + {0x2934, 0x2935, prExtendedPictographic}, // 3.2 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down + {0x2B05, 0x2B07, prExtendedPictographic}, // 4.0 [3] (⬅️..⬇️) left arrow..down arrow + {0x2B1B, 0x2B1C, prExtendedPictographic}, // 5.1 [2] (⬛..⬜) black large square..white large square + {0x2B50, 0x2B50, prExtendedPictographic}, // 5.1 [1] (⭐) star + {0x2B55, 0x2B55, prExtendedPictographic}, // 5.2 [1] (⭕) hollow red circle + {0x2CEF, 0x2CF1, prExtend}, // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2D7F, 0x2D7F, prExtend}, // Mn TIFINAGH CONSONANT JOINER + {0x2DE0, 0x2DFF, prExtend}, // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x302A, 0x302D, prExtend}, // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prExtend}, // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3030, 0x3030, prExtendedPictographic}, // 1.1 [1] (〰️) wavy dash + {0x303D, 0x303D, prExtendedPictographic}, // 3.2 [1] (〽️) part alternation mark + {0x3099, 0x309A, prExtend}, // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x3297, 0x3297, prExtendedPictographic}, // 1.1 [1] (㊗️) Japanese “congratulations” button + {0x3299, 0x3299, prExtendedPictographic}, // 1.1 [1] (㊙️) Japanese “secret” button + {0xA66F, 0xA66F, prExtend}, // Mn COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prExtend}, // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA674, 0xA67D, prExtend}, // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA69E, 0xA69F, prExtend}, // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6F0, 0xA6F1, prExtend}, // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA802, 0xA802, prExtend}, // Mn SYLOTI NAGRI SIGN DVISVARA + {0xA806, 0xA806, prExtend}, // Mn SYLOTI NAGRI SIGN HASANTA + {0xA80B, 0xA80B, prExtend}, // Mn SYLOTI NAGRI SIGN ANUSVARA + {0xA823, 0xA824, prSpacingMark}, // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prExtend}, // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prSpacingMark}, // Mc SYLOTI NAGRI VOWEL SIGN OO + {0xA880, 0xA881, prSpacingMark}, // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA8B4, 0xA8C3, prSpacingMark}, // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prExtend}, // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8E0, 0xA8F1, prExtend}, // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8FF, 0xA8FF, prExtend}, // Mn DEVANAGARI VOWEL SIGN AY + {0xA926, 0xA92D, prExtend}, // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA947, 0xA951, prExtend}, // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prSpacingMark}, // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA960, 0xA97C, prL}, // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prExtend}, // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prSpacingMark}, // Mc JAVANESE SIGN WIGNYAN + {0xA9B3, 0xA9B3, prExtend}, // Mn JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prSpacingMark}, // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prExtend}, // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prSpacingMark}, // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prExtend}, // Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prSpacingMark}, // Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9E5, 0xA9E5, prExtend}, // Mn MYANMAR SIGN SHAN SAW + {0xAA29, 0xAA2E, prExtend}, // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prSpacingMark}, // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prExtend}, // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prSpacingMark}, // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prExtend}, // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA43, 0xAA43, prExtend}, // Mn CHAM CONSONANT SIGN FINAL NG + {0xAA4C, 0xAA4C, prExtend}, // Mn CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prSpacingMark}, // Mc CHAM CONSONANT SIGN FINAL H + {0xAA7C, 0xAA7C, prExtend}, // Mn MYANMAR SIGN TAI LAING TONE-2 + {0xAAB0, 0xAAB0, prExtend}, // Mn TAI VIET MAI KANG + {0xAAB2, 0xAAB4, prExtend}, // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB7, 0xAAB8, prExtend}, // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAABE, 0xAABF, prExtend}, // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC1, 0xAAC1, prExtend}, // Mn TAI VIET TONE MAI THO + {0xAAEB, 0xAAEB, prSpacingMark}, // Mc MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prExtend}, // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF5, 0xAAF5, prSpacingMark}, // Mc MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prExtend}, // Mn MEETEI MAYEK VIRAMA + {0xABE3, 0xABE4, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEC, 0xABEC, prSpacingMark}, // Mc MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prExtend}, // Mn MEETEI MAYEK APUN IYEK + {0xAC00, 0xAC00, prLV}, // Lo HANGUL SYLLABLE GA + {0xAC01, 0xAC1B, prLVT}, // Lo [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH + {0xAC1C, 0xAC1C, prLV}, // Lo HANGUL SYLLABLE GAE + {0xAC1D, 0xAC37, prLVT}, // Lo [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH + {0xAC38, 0xAC38, prLV}, // Lo HANGUL SYLLABLE GYA + {0xAC39, 0xAC53, prLVT}, // Lo [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH + {0xAC54, 0xAC54, prLV}, // Lo HANGUL SYLLABLE GYAE + {0xAC55, 0xAC6F, prLVT}, // Lo [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH + {0xAC70, 0xAC70, prLV}, // Lo HANGUL SYLLABLE GEO + {0xAC71, 0xAC8B, prLVT}, // Lo [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH + {0xAC8C, 0xAC8C, prLV}, // Lo HANGUL SYLLABLE GE + {0xAC8D, 0xACA7, prLVT}, // Lo [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH + {0xACA8, 0xACA8, prLV}, // Lo HANGUL SYLLABLE GYEO + {0xACA9, 0xACC3, prLVT}, // Lo [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH + {0xACC4, 0xACC4, prLV}, // Lo HANGUL SYLLABLE GYE + {0xACC5, 0xACDF, prLVT}, // Lo [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH + {0xACE0, 0xACE0, prLV}, // Lo HANGUL SYLLABLE GO + {0xACE1, 0xACFB, prLVT}, // Lo [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH + {0xACFC, 0xACFC, prLV}, // Lo HANGUL SYLLABLE GWA + {0xACFD, 0xAD17, prLVT}, // Lo [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH + {0xAD18, 0xAD18, prLV}, // Lo HANGUL SYLLABLE GWAE + {0xAD19, 0xAD33, prLVT}, // Lo [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH + {0xAD34, 0xAD34, prLV}, // Lo HANGUL SYLLABLE GOE + {0xAD35, 0xAD4F, prLVT}, // Lo [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH + {0xAD50, 0xAD50, prLV}, // Lo HANGUL SYLLABLE GYO + {0xAD51, 0xAD6B, prLVT}, // Lo [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH + {0xAD6C, 0xAD6C, prLV}, // Lo HANGUL SYLLABLE GU + {0xAD6D, 0xAD87, prLVT}, // Lo [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH + {0xAD88, 0xAD88, prLV}, // Lo HANGUL SYLLABLE GWEO + {0xAD89, 0xADA3, prLVT}, // Lo [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH + {0xADA4, 0xADA4, prLV}, // Lo HANGUL SYLLABLE GWE + {0xADA5, 0xADBF, prLVT}, // Lo [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH + {0xADC0, 0xADC0, prLV}, // Lo HANGUL SYLLABLE GWI + {0xADC1, 0xADDB, prLVT}, // Lo [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH + {0xADDC, 0xADDC, prLV}, // Lo HANGUL SYLLABLE GYU + {0xADDD, 0xADF7, prLVT}, // Lo [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH + {0xADF8, 0xADF8, prLV}, // Lo HANGUL SYLLABLE GEU + {0xADF9, 0xAE13, prLVT}, // Lo [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH + {0xAE14, 0xAE14, prLV}, // Lo HANGUL SYLLABLE GYI + {0xAE15, 0xAE2F, prLVT}, // Lo [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH + {0xAE30, 0xAE30, prLV}, // Lo HANGUL SYLLABLE GI + {0xAE31, 0xAE4B, prLVT}, // Lo [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH + {0xAE4C, 0xAE4C, prLV}, // Lo HANGUL SYLLABLE GGA + {0xAE4D, 0xAE67, prLVT}, // Lo [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH + {0xAE68, 0xAE68, prLV}, // Lo HANGUL SYLLABLE GGAE + {0xAE69, 0xAE83, prLVT}, // Lo [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH + {0xAE84, 0xAE84, prLV}, // Lo HANGUL SYLLABLE GGYA + {0xAE85, 0xAE9F, prLVT}, // Lo [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH + {0xAEA0, 0xAEA0, prLV}, // Lo HANGUL SYLLABLE GGYAE + {0xAEA1, 0xAEBB, prLVT}, // Lo [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH + {0xAEBC, 0xAEBC, prLV}, // Lo HANGUL SYLLABLE GGEO + {0xAEBD, 0xAED7, prLVT}, // Lo [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH + {0xAED8, 0xAED8, prLV}, // Lo HANGUL SYLLABLE GGE + {0xAED9, 0xAEF3, prLVT}, // Lo [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH + {0xAEF4, 0xAEF4, prLV}, // Lo HANGUL SYLLABLE GGYEO + {0xAEF5, 0xAF0F, prLVT}, // Lo [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH + {0xAF10, 0xAF10, prLV}, // Lo HANGUL SYLLABLE GGYE + {0xAF11, 0xAF2B, prLVT}, // Lo [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH + {0xAF2C, 0xAF2C, prLV}, // Lo HANGUL SYLLABLE GGO + {0xAF2D, 0xAF47, prLVT}, // Lo [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH + {0xAF48, 0xAF48, prLV}, // Lo HANGUL SYLLABLE GGWA + {0xAF49, 0xAF63, prLVT}, // Lo [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH + {0xAF64, 0xAF64, prLV}, // Lo HANGUL SYLLABLE GGWAE + {0xAF65, 0xAF7F, prLVT}, // Lo [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH + {0xAF80, 0xAF80, prLV}, // Lo HANGUL SYLLABLE GGOE + {0xAF81, 0xAF9B, prLVT}, // Lo [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH + {0xAF9C, 0xAF9C, prLV}, // Lo HANGUL SYLLABLE GGYO + {0xAF9D, 0xAFB7, prLVT}, // Lo [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH + {0xAFB8, 0xAFB8, prLV}, // Lo HANGUL SYLLABLE GGU + {0xAFB9, 0xAFD3, prLVT}, // Lo [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH + {0xAFD4, 0xAFD4, prLV}, // Lo HANGUL SYLLABLE GGWEO + {0xAFD5, 0xAFEF, prLVT}, // Lo [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH + {0xAFF0, 0xAFF0, prLV}, // Lo HANGUL SYLLABLE GGWE + {0xAFF1, 0xB00B, prLVT}, // Lo [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH + {0xB00C, 0xB00C, prLV}, // Lo HANGUL SYLLABLE GGWI + {0xB00D, 0xB027, prLVT}, // Lo [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH + {0xB028, 0xB028, prLV}, // Lo HANGUL SYLLABLE GGYU + {0xB029, 0xB043, prLVT}, // Lo [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH + {0xB044, 0xB044, prLV}, // Lo HANGUL SYLLABLE GGEU + {0xB045, 0xB05F, prLVT}, // Lo [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH + {0xB060, 0xB060, prLV}, // Lo HANGUL SYLLABLE GGYI + {0xB061, 0xB07B, prLVT}, // Lo [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH + {0xB07C, 0xB07C, prLV}, // Lo HANGUL SYLLABLE GGI + {0xB07D, 0xB097, prLVT}, // Lo [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH + {0xB098, 0xB098, prLV}, // Lo HANGUL SYLLABLE NA + {0xB099, 0xB0B3, prLVT}, // Lo [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH + {0xB0B4, 0xB0B4, prLV}, // Lo HANGUL SYLLABLE NAE + {0xB0B5, 0xB0CF, prLVT}, // Lo [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH + {0xB0D0, 0xB0D0, prLV}, // Lo HANGUL SYLLABLE NYA + {0xB0D1, 0xB0EB, prLVT}, // Lo [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH + {0xB0EC, 0xB0EC, prLV}, // Lo HANGUL SYLLABLE NYAE + {0xB0ED, 0xB107, prLVT}, // Lo [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH + {0xB108, 0xB108, prLV}, // Lo HANGUL SYLLABLE NEO + {0xB109, 0xB123, prLVT}, // Lo [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH + {0xB124, 0xB124, prLV}, // Lo HANGUL SYLLABLE NE + {0xB125, 0xB13F, prLVT}, // Lo [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH + {0xB140, 0xB140, prLV}, // Lo HANGUL SYLLABLE NYEO + {0xB141, 0xB15B, prLVT}, // Lo [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH + {0xB15C, 0xB15C, prLV}, // Lo HANGUL SYLLABLE NYE + {0xB15D, 0xB177, prLVT}, // Lo [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH + {0xB178, 0xB178, prLV}, // Lo HANGUL SYLLABLE NO + {0xB179, 0xB193, prLVT}, // Lo [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH + {0xB194, 0xB194, prLV}, // Lo HANGUL SYLLABLE NWA + {0xB195, 0xB1AF, prLVT}, // Lo [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH + {0xB1B0, 0xB1B0, prLV}, // Lo HANGUL SYLLABLE NWAE + {0xB1B1, 0xB1CB, prLVT}, // Lo [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH + {0xB1CC, 0xB1CC, prLV}, // Lo HANGUL SYLLABLE NOE + {0xB1CD, 0xB1E7, prLVT}, // Lo [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH + {0xB1E8, 0xB1E8, prLV}, // Lo HANGUL SYLLABLE NYO + {0xB1E9, 0xB203, prLVT}, // Lo [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH + {0xB204, 0xB204, prLV}, // Lo HANGUL SYLLABLE NU + {0xB205, 0xB21F, prLVT}, // Lo [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH + {0xB220, 0xB220, prLV}, // Lo HANGUL SYLLABLE NWEO + {0xB221, 0xB23B, prLVT}, // Lo [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH + {0xB23C, 0xB23C, prLV}, // Lo HANGUL SYLLABLE NWE + {0xB23D, 0xB257, prLVT}, // Lo [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH + {0xB258, 0xB258, prLV}, // Lo HANGUL SYLLABLE NWI + {0xB259, 0xB273, prLVT}, // Lo [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH + {0xB274, 0xB274, prLV}, // Lo HANGUL SYLLABLE NYU + {0xB275, 0xB28F, prLVT}, // Lo [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH + {0xB290, 0xB290, prLV}, // Lo HANGUL SYLLABLE NEU + {0xB291, 0xB2AB, prLVT}, // Lo [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH + {0xB2AC, 0xB2AC, prLV}, // Lo HANGUL SYLLABLE NYI + {0xB2AD, 0xB2C7, prLVT}, // Lo [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH + {0xB2C8, 0xB2C8, prLV}, // Lo HANGUL SYLLABLE NI + {0xB2C9, 0xB2E3, prLVT}, // Lo [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH + {0xB2E4, 0xB2E4, prLV}, // Lo HANGUL SYLLABLE DA + {0xB2E5, 0xB2FF, prLVT}, // Lo [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH + {0xB300, 0xB300, prLV}, // Lo HANGUL SYLLABLE DAE + {0xB301, 0xB31B, prLVT}, // Lo [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH + {0xB31C, 0xB31C, prLV}, // Lo HANGUL SYLLABLE DYA + {0xB31D, 0xB337, prLVT}, // Lo [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH + {0xB338, 0xB338, prLV}, // Lo HANGUL SYLLABLE DYAE + {0xB339, 0xB353, prLVT}, // Lo [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH + {0xB354, 0xB354, prLV}, // Lo HANGUL SYLLABLE DEO + {0xB355, 0xB36F, prLVT}, // Lo [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH + {0xB370, 0xB370, prLV}, // Lo HANGUL SYLLABLE DE + {0xB371, 0xB38B, prLVT}, // Lo [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH + {0xB38C, 0xB38C, prLV}, // Lo HANGUL SYLLABLE DYEO + {0xB38D, 0xB3A7, prLVT}, // Lo [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH + {0xB3A8, 0xB3A8, prLV}, // Lo HANGUL SYLLABLE DYE + {0xB3A9, 0xB3C3, prLVT}, // Lo [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH + {0xB3C4, 0xB3C4, prLV}, // Lo HANGUL SYLLABLE DO + {0xB3C5, 0xB3DF, prLVT}, // Lo [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH + {0xB3E0, 0xB3E0, prLV}, // Lo HANGUL SYLLABLE DWA + {0xB3E1, 0xB3FB, prLVT}, // Lo [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH + {0xB3FC, 0xB3FC, prLV}, // Lo HANGUL SYLLABLE DWAE + {0xB3FD, 0xB417, prLVT}, // Lo [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH + {0xB418, 0xB418, prLV}, // Lo HANGUL SYLLABLE DOE + {0xB419, 0xB433, prLVT}, // Lo [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH + {0xB434, 0xB434, prLV}, // Lo HANGUL SYLLABLE DYO + {0xB435, 0xB44F, prLVT}, // Lo [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH + {0xB450, 0xB450, prLV}, // Lo HANGUL SYLLABLE DU + {0xB451, 0xB46B, prLVT}, // Lo [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH + {0xB46C, 0xB46C, prLV}, // Lo HANGUL SYLLABLE DWEO + {0xB46D, 0xB487, prLVT}, // Lo [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH + {0xB488, 0xB488, prLV}, // Lo HANGUL SYLLABLE DWE + {0xB489, 0xB4A3, prLVT}, // Lo [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH + {0xB4A4, 0xB4A4, prLV}, // Lo HANGUL SYLLABLE DWI + {0xB4A5, 0xB4BF, prLVT}, // Lo [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH + {0xB4C0, 0xB4C0, prLV}, // Lo HANGUL SYLLABLE DYU + {0xB4C1, 0xB4DB, prLVT}, // Lo [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH + {0xB4DC, 0xB4DC, prLV}, // Lo HANGUL SYLLABLE DEU + {0xB4DD, 0xB4F7, prLVT}, // Lo [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH + {0xB4F8, 0xB4F8, prLV}, // Lo HANGUL SYLLABLE DYI + {0xB4F9, 0xB513, prLVT}, // Lo [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH + {0xB514, 0xB514, prLV}, // Lo HANGUL SYLLABLE DI + {0xB515, 0xB52F, prLVT}, // Lo [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH + {0xB530, 0xB530, prLV}, // Lo HANGUL SYLLABLE DDA + {0xB531, 0xB54B, prLVT}, // Lo [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH + {0xB54C, 0xB54C, prLV}, // Lo HANGUL SYLLABLE DDAE + {0xB54D, 0xB567, prLVT}, // Lo [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH + {0xB568, 0xB568, prLV}, // Lo HANGUL SYLLABLE DDYA + {0xB569, 0xB583, prLVT}, // Lo [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH + {0xB584, 0xB584, prLV}, // Lo HANGUL SYLLABLE DDYAE + {0xB585, 0xB59F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH + {0xB5A0, 0xB5A0, prLV}, // Lo HANGUL SYLLABLE DDEO + {0xB5A1, 0xB5BB, prLVT}, // Lo [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH + {0xB5BC, 0xB5BC, prLV}, // Lo HANGUL SYLLABLE DDE + {0xB5BD, 0xB5D7, prLVT}, // Lo [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH + {0xB5D8, 0xB5D8, prLV}, // Lo HANGUL SYLLABLE DDYEO + {0xB5D9, 0xB5F3, prLVT}, // Lo [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH + {0xB5F4, 0xB5F4, prLV}, // Lo HANGUL SYLLABLE DDYE + {0xB5F5, 0xB60F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH + {0xB610, 0xB610, prLV}, // Lo HANGUL SYLLABLE DDO + {0xB611, 0xB62B, prLVT}, // Lo [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH + {0xB62C, 0xB62C, prLV}, // Lo HANGUL SYLLABLE DDWA + {0xB62D, 0xB647, prLVT}, // Lo [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH + {0xB648, 0xB648, prLV}, // Lo HANGUL SYLLABLE DDWAE + {0xB649, 0xB663, prLVT}, // Lo [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH + {0xB664, 0xB664, prLV}, // Lo HANGUL SYLLABLE DDOE + {0xB665, 0xB67F, prLVT}, // Lo [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH + {0xB680, 0xB680, prLV}, // Lo HANGUL SYLLABLE DDYO + {0xB681, 0xB69B, prLVT}, // Lo [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH + {0xB69C, 0xB69C, prLV}, // Lo HANGUL SYLLABLE DDU + {0xB69D, 0xB6B7, prLVT}, // Lo [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH + {0xB6B8, 0xB6B8, prLV}, // Lo HANGUL SYLLABLE DDWEO + {0xB6B9, 0xB6D3, prLVT}, // Lo [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH + {0xB6D4, 0xB6D4, prLV}, // Lo HANGUL SYLLABLE DDWE + {0xB6D5, 0xB6EF, prLVT}, // Lo [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH + {0xB6F0, 0xB6F0, prLV}, // Lo HANGUL SYLLABLE DDWI + {0xB6F1, 0xB70B, prLVT}, // Lo [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH + {0xB70C, 0xB70C, prLV}, // Lo HANGUL SYLLABLE DDYU + {0xB70D, 0xB727, prLVT}, // Lo [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH + {0xB728, 0xB728, prLV}, // Lo HANGUL SYLLABLE DDEU + {0xB729, 0xB743, prLVT}, // Lo [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH + {0xB744, 0xB744, prLV}, // Lo HANGUL SYLLABLE DDYI + {0xB745, 0xB75F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH + {0xB760, 0xB760, prLV}, // Lo HANGUL SYLLABLE DDI + {0xB761, 0xB77B, prLVT}, // Lo [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH + {0xB77C, 0xB77C, prLV}, // Lo HANGUL SYLLABLE RA + {0xB77D, 0xB797, prLVT}, // Lo [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH + {0xB798, 0xB798, prLV}, // Lo HANGUL SYLLABLE RAE + {0xB799, 0xB7B3, prLVT}, // Lo [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH + {0xB7B4, 0xB7B4, prLV}, // Lo HANGUL SYLLABLE RYA + {0xB7B5, 0xB7CF, prLVT}, // Lo [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH + {0xB7D0, 0xB7D0, prLV}, // Lo HANGUL SYLLABLE RYAE + {0xB7D1, 0xB7EB, prLVT}, // Lo [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH + {0xB7EC, 0xB7EC, prLV}, // Lo HANGUL SYLLABLE REO + {0xB7ED, 0xB807, prLVT}, // Lo [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH + {0xB808, 0xB808, prLV}, // Lo HANGUL SYLLABLE RE + {0xB809, 0xB823, prLVT}, // Lo [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH + {0xB824, 0xB824, prLV}, // Lo HANGUL SYLLABLE RYEO + {0xB825, 0xB83F, prLVT}, // Lo [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH + {0xB840, 0xB840, prLV}, // Lo HANGUL SYLLABLE RYE + {0xB841, 0xB85B, prLVT}, // Lo [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH + {0xB85C, 0xB85C, prLV}, // Lo HANGUL SYLLABLE RO + {0xB85D, 0xB877, prLVT}, // Lo [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH + {0xB878, 0xB878, prLV}, // Lo HANGUL SYLLABLE RWA + {0xB879, 0xB893, prLVT}, // Lo [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH + {0xB894, 0xB894, prLV}, // Lo HANGUL SYLLABLE RWAE + {0xB895, 0xB8AF, prLVT}, // Lo [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH + {0xB8B0, 0xB8B0, prLV}, // Lo HANGUL SYLLABLE ROE + {0xB8B1, 0xB8CB, prLVT}, // Lo [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH + {0xB8CC, 0xB8CC, prLV}, // Lo HANGUL SYLLABLE RYO + {0xB8CD, 0xB8E7, prLVT}, // Lo [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH + {0xB8E8, 0xB8E8, prLV}, // Lo HANGUL SYLLABLE RU + {0xB8E9, 0xB903, prLVT}, // Lo [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH + {0xB904, 0xB904, prLV}, // Lo HANGUL SYLLABLE RWEO + {0xB905, 0xB91F, prLVT}, // Lo [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH + {0xB920, 0xB920, prLV}, // Lo HANGUL SYLLABLE RWE + {0xB921, 0xB93B, prLVT}, // Lo [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH + {0xB93C, 0xB93C, prLV}, // Lo HANGUL SYLLABLE RWI + {0xB93D, 0xB957, prLVT}, // Lo [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH + {0xB958, 0xB958, prLV}, // Lo HANGUL SYLLABLE RYU + {0xB959, 0xB973, prLVT}, // Lo [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH + {0xB974, 0xB974, prLV}, // Lo HANGUL SYLLABLE REU + {0xB975, 0xB98F, prLVT}, // Lo [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH + {0xB990, 0xB990, prLV}, // Lo HANGUL SYLLABLE RYI + {0xB991, 0xB9AB, prLVT}, // Lo [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH + {0xB9AC, 0xB9AC, prLV}, // Lo HANGUL SYLLABLE RI + {0xB9AD, 0xB9C7, prLVT}, // Lo [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH + {0xB9C8, 0xB9C8, prLV}, // Lo HANGUL SYLLABLE MA + {0xB9C9, 0xB9E3, prLVT}, // Lo [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH + {0xB9E4, 0xB9E4, prLV}, // Lo HANGUL SYLLABLE MAE + {0xB9E5, 0xB9FF, prLVT}, // Lo [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH + {0xBA00, 0xBA00, prLV}, // Lo HANGUL SYLLABLE MYA + {0xBA01, 0xBA1B, prLVT}, // Lo [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH + {0xBA1C, 0xBA1C, prLV}, // Lo HANGUL SYLLABLE MYAE + {0xBA1D, 0xBA37, prLVT}, // Lo [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH + {0xBA38, 0xBA38, prLV}, // Lo HANGUL SYLLABLE MEO + {0xBA39, 0xBA53, prLVT}, // Lo [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH + {0xBA54, 0xBA54, prLV}, // Lo HANGUL SYLLABLE ME + {0xBA55, 0xBA6F, prLVT}, // Lo [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH + {0xBA70, 0xBA70, prLV}, // Lo HANGUL SYLLABLE MYEO + {0xBA71, 0xBA8B, prLVT}, // Lo [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH + {0xBA8C, 0xBA8C, prLV}, // Lo HANGUL SYLLABLE MYE + {0xBA8D, 0xBAA7, prLVT}, // Lo [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH + {0xBAA8, 0xBAA8, prLV}, // Lo HANGUL SYLLABLE MO + {0xBAA9, 0xBAC3, prLVT}, // Lo [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH + {0xBAC4, 0xBAC4, prLV}, // Lo HANGUL SYLLABLE MWA + {0xBAC5, 0xBADF, prLVT}, // Lo [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH + {0xBAE0, 0xBAE0, prLV}, // Lo HANGUL SYLLABLE MWAE + {0xBAE1, 0xBAFB, prLVT}, // Lo [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH + {0xBAFC, 0xBAFC, prLV}, // Lo HANGUL SYLLABLE MOE + {0xBAFD, 0xBB17, prLVT}, // Lo [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH + {0xBB18, 0xBB18, prLV}, // Lo HANGUL SYLLABLE MYO + {0xBB19, 0xBB33, prLVT}, // Lo [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH + {0xBB34, 0xBB34, prLV}, // Lo HANGUL SYLLABLE MU + {0xBB35, 0xBB4F, prLVT}, // Lo [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH + {0xBB50, 0xBB50, prLV}, // Lo HANGUL SYLLABLE MWEO + {0xBB51, 0xBB6B, prLVT}, // Lo [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH + {0xBB6C, 0xBB6C, prLV}, // Lo HANGUL SYLLABLE MWE + {0xBB6D, 0xBB87, prLVT}, // Lo [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH + {0xBB88, 0xBB88, prLV}, // Lo HANGUL SYLLABLE MWI + {0xBB89, 0xBBA3, prLVT}, // Lo [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH + {0xBBA4, 0xBBA4, prLV}, // Lo HANGUL SYLLABLE MYU + {0xBBA5, 0xBBBF, prLVT}, // Lo [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH + {0xBBC0, 0xBBC0, prLV}, // Lo HANGUL SYLLABLE MEU + {0xBBC1, 0xBBDB, prLVT}, // Lo [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH + {0xBBDC, 0xBBDC, prLV}, // Lo HANGUL SYLLABLE MYI + {0xBBDD, 0xBBF7, prLVT}, // Lo [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH + {0xBBF8, 0xBBF8, prLV}, // Lo HANGUL SYLLABLE MI + {0xBBF9, 0xBC13, prLVT}, // Lo [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH + {0xBC14, 0xBC14, prLV}, // Lo HANGUL SYLLABLE BA + {0xBC15, 0xBC2F, prLVT}, // Lo [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH + {0xBC30, 0xBC30, prLV}, // Lo HANGUL SYLLABLE BAE + {0xBC31, 0xBC4B, prLVT}, // Lo [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH + {0xBC4C, 0xBC4C, prLV}, // Lo HANGUL SYLLABLE BYA + {0xBC4D, 0xBC67, prLVT}, // Lo [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH + {0xBC68, 0xBC68, prLV}, // Lo HANGUL SYLLABLE BYAE + {0xBC69, 0xBC83, prLVT}, // Lo [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH + {0xBC84, 0xBC84, prLV}, // Lo HANGUL SYLLABLE BEO + {0xBC85, 0xBC9F, prLVT}, // Lo [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH + {0xBCA0, 0xBCA0, prLV}, // Lo HANGUL SYLLABLE BE + {0xBCA1, 0xBCBB, prLVT}, // Lo [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH + {0xBCBC, 0xBCBC, prLV}, // Lo HANGUL SYLLABLE BYEO + {0xBCBD, 0xBCD7, prLVT}, // Lo [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH + {0xBCD8, 0xBCD8, prLV}, // Lo HANGUL SYLLABLE BYE + {0xBCD9, 0xBCF3, prLVT}, // Lo [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH + {0xBCF4, 0xBCF4, prLV}, // Lo HANGUL SYLLABLE BO + {0xBCF5, 0xBD0F, prLVT}, // Lo [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH + {0xBD10, 0xBD10, prLV}, // Lo HANGUL SYLLABLE BWA + {0xBD11, 0xBD2B, prLVT}, // Lo [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH + {0xBD2C, 0xBD2C, prLV}, // Lo HANGUL SYLLABLE BWAE + {0xBD2D, 0xBD47, prLVT}, // Lo [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH + {0xBD48, 0xBD48, prLV}, // Lo HANGUL SYLLABLE BOE + {0xBD49, 0xBD63, prLVT}, // Lo [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH + {0xBD64, 0xBD64, prLV}, // Lo HANGUL SYLLABLE BYO + {0xBD65, 0xBD7F, prLVT}, // Lo [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH + {0xBD80, 0xBD80, prLV}, // Lo HANGUL SYLLABLE BU + {0xBD81, 0xBD9B, prLVT}, // Lo [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH + {0xBD9C, 0xBD9C, prLV}, // Lo HANGUL SYLLABLE BWEO + {0xBD9D, 0xBDB7, prLVT}, // Lo [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH + {0xBDB8, 0xBDB8, prLV}, // Lo HANGUL SYLLABLE BWE + {0xBDB9, 0xBDD3, prLVT}, // Lo [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH + {0xBDD4, 0xBDD4, prLV}, // Lo HANGUL SYLLABLE BWI + {0xBDD5, 0xBDEF, prLVT}, // Lo [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH + {0xBDF0, 0xBDF0, prLV}, // Lo HANGUL SYLLABLE BYU + {0xBDF1, 0xBE0B, prLVT}, // Lo [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH + {0xBE0C, 0xBE0C, prLV}, // Lo HANGUL SYLLABLE BEU + {0xBE0D, 0xBE27, prLVT}, // Lo [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH + {0xBE28, 0xBE28, prLV}, // Lo HANGUL SYLLABLE BYI + {0xBE29, 0xBE43, prLVT}, // Lo [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH + {0xBE44, 0xBE44, prLV}, // Lo HANGUL SYLLABLE BI + {0xBE45, 0xBE5F, prLVT}, // Lo [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH + {0xBE60, 0xBE60, prLV}, // Lo HANGUL SYLLABLE BBA + {0xBE61, 0xBE7B, prLVT}, // Lo [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH + {0xBE7C, 0xBE7C, prLV}, // Lo HANGUL SYLLABLE BBAE + {0xBE7D, 0xBE97, prLVT}, // Lo [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH + {0xBE98, 0xBE98, prLV}, // Lo HANGUL SYLLABLE BBYA + {0xBE99, 0xBEB3, prLVT}, // Lo [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH + {0xBEB4, 0xBEB4, prLV}, // Lo HANGUL SYLLABLE BBYAE + {0xBEB5, 0xBECF, prLVT}, // Lo [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH + {0xBED0, 0xBED0, prLV}, // Lo HANGUL SYLLABLE BBEO + {0xBED1, 0xBEEB, prLVT}, // Lo [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH + {0xBEEC, 0xBEEC, prLV}, // Lo HANGUL SYLLABLE BBE + {0xBEED, 0xBF07, prLVT}, // Lo [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH + {0xBF08, 0xBF08, prLV}, // Lo HANGUL SYLLABLE BBYEO + {0xBF09, 0xBF23, prLVT}, // Lo [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH + {0xBF24, 0xBF24, prLV}, // Lo HANGUL SYLLABLE BBYE + {0xBF25, 0xBF3F, prLVT}, // Lo [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH + {0xBF40, 0xBF40, prLV}, // Lo HANGUL SYLLABLE BBO + {0xBF41, 0xBF5B, prLVT}, // Lo [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH + {0xBF5C, 0xBF5C, prLV}, // Lo HANGUL SYLLABLE BBWA + {0xBF5D, 0xBF77, prLVT}, // Lo [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH + {0xBF78, 0xBF78, prLV}, // Lo HANGUL SYLLABLE BBWAE + {0xBF79, 0xBF93, prLVT}, // Lo [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH + {0xBF94, 0xBF94, prLV}, // Lo HANGUL SYLLABLE BBOE + {0xBF95, 0xBFAF, prLVT}, // Lo [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH + {0xBFB0, 0xBFB0, prLV}, // Lo HANGUL SYLLABLE BBYO + {0xBFB1, 0xBFCB, prLVT}, // Lo [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH + {0xBFCC, 0xBFCC, prLV}, // Lo HANGUL SYLLABLE BBU + {0xBFCD, 0xBFE7, prLVT}, // Lo [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH + {0xBFE8, 0xBFE8, prLV}, // Lo HANGUL SYLLABLE BBWEO + {0xBFE9, 0xC003, prLVT}, // Lo [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH + {0xC004, 0xC004, prLV}, // Lo HANGUL SYLLABLE BBWE + {0xC005, 0xC01F, prLVT}, // Lo [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH + {0xC020, 0xC020, prLV}, // Lo HANGUL SYLLABLE BBWI + {0xC021, 0xC03B, prLVT}, // Lo [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH + {0xC03C, 0xC03C, prLV}, // Lo HANGUL SYLLABLE BBYU + {0xC03D, 0xC057, prLVT}, // Lo [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH + {0xC058, 0xC058, prLV}, // Lo HANGUL SYLLABLE BBEU + {0xC059, 0xC073, prLVT}, // Lo [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH + {0xC074, 0xC074, prLV}, // Lo HANGUL SYLLABLE BBYI + {0xC075, 0xC08F, prLVT}, // Lo [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH + {0xC090, 0xC090, prLV}, // Lo HANGUL SYLLABLE BBI + {0xC091, 0xC0AB, prLVT}, // Lo [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH + {0xC0AC, 0xC0AC, prLV}, // Lo HANGUL SYLLABLE SA + {0xC0AD, 0xC0C7, prLVT}, // Lo [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH + {0xC0C8, 0xC0C8, prLV}, // Lo HANGUL SYLLABLE SAE + {0xC0C9, 0xC0E3, prLVT}, // Lo [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH + {0xC0E4, 0xC0E4, prLV}, // Lo HANGUL SYLLABLE SYA + {0xC0E5, 0xC0FF, prLVT}, // Lo [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH + {0xC100, 0xC100, prLV}, // Lo HANGUL SYLLABLE SYAE + {0xC101, 0xC11B, prLVT}, // Lo [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH + {0xC11C, 0xC11C, prLV}, // Lo HANGUL SYLLABLE SEO + {0xC11D, 0xC137, prLVT}, // Lo [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH + {0xC138, 0xC138, prLV}, // Lo HANGUL SYLLABLE SE + {0xC139, 0xC153, prLVT}, // Lo [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH + {0xC154, 0xC154, prLV}, // Lo HANGUL SYLLABLE SYEO + {0xC155, 0xC16F, prLVT}, // Lo [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH + {0xC170, 0xC170, prLV}, // Lo HANGUL SYLLABLE SYE + {0xC171, 0xC18B, prLVT}, // Lo [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH + {0xC18C, 0xC18C, prLV}, // Lo HANGUL SYLLABLE SO + {0xC18D, 0xC1A7, prLVT}, // Lo [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH + {0xC1A8, 0xC1A8, prLV}, // Lo HANGUL SYLLABLE SWA + {0xC1A9, 0xC1C3, prLVT}, // Lo [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH + {0xC1C4, 0xC1C4, prLV}, // Lo HANGUL SYLLABLE SWAE + {0xC1C5, 0xC1DF, prLVT}, // Lo [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH + {0xC1E0, 0xC1E0, prLV}, // Lo HANGUL SYLLABLE SOE + {0xC1E1, 0xC1FB, prLVT}, // Lo [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH + {0xC1FC, 0xC1FC, prLV}, // Lo HANGUL SYLLABLE SYO + {0xC1FD, 0xC217, prLVT}, // Lo [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH + {0xC218, 0xC218, prLV}, // Lo HANGUL SYLLABLE SU + {0xC219, 0xC233, prLVT}, // Lo [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH + {0xC234, 0xC234, prLV}, // Lo HANGUL SYLLABLE SWEO + {0xC235, 0xC24F, prLVT}, // Lo [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH + {0xC250, 0xC250, prLV}, // Lo HANGUL SYLLABLE SWE + {0xC251, 0xC26B, prLVT}, // Lo [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH + {0xC26C, 0xC26C, prLV}, // Lo HANGUL SYLLABLE SWI + {0xC26D, 0xC287, prLVT}, // Lo [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH + {0xC288, 0xC288, prLV}, // Lo HANGUL SYLLABLE SYU + {0xC289, 0xC2A3, prLVT}, // Lo [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH + {0xC2A4, 0xC2A4, prLV}, // Lo HANGUL SYLLABLE SEU + {0xC2A5, 0xC2BF, prLVT}, // Lo [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH + {0xC2C0, 0xC2C0, prLV}, // Lo HANGUL SYLLABLE SYI + {0xC2C1, 0xC2DB, prLVT}, // Lo [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH + {0xC2DC, 0xC2DC, prLV}, // Lo HANGUL SYLLABLE SI + {0xC2DD, 0xC2F7, prLVT}, // Lo [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH + {0xC2F8, 0xC2F8, prLV}, // Lo HANGUL SYLLABLE SSA + {0xC2F9, 0xC313, prLVT}, // Lo [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH + {0xC314, 0xC314, prLV}, // Lo HANGUL SYLLABLE SSAE + {0xC315, 0xC32F, prLVT}, // Lo [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH + {0xC330, 0xC330, prLV}, // Lo HANGUL SYLLABLE SSYA + {0xC331, 0xC34B, prLVT}, // Lo [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH + {0xC34C, 0xC34C, prLV}, // Lo HANGUL SYLLABLE SSYAE + {0xC34D, 0xC367, prLVT}, // Lo [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH + {0xC368, 0xC368, prLV}, // Lo HANGUL SYLLABLE SSEO + {0xC369, 0xC383, prLVT}, // Lo [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH + {0xC384, 0xC384, prLV}, // Lo HANGUL SYLLABLE SSE + {0xC385, 0xC39F, prLVT}, // Lo [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH + {0xC3A0, 0xC3A0, prLV}, // Lo HANGUL SYLLABLE SSYEO + {0xC3A1, 0xC3BB, prLVT}, // Lo [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH + {0xC3BC, 0xC3BC, prLV}, // Lo HANGUL SYLLABLE SSYE + {0xC3BD, 0xC3D7, prLVT}, // Lo [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH + {0xC3D8, 0xC3D8, prLV}, // Lo HANGUL SYLLABLE SSO + {0xC3D9, 0xC3F3, prLVT}, // Lo [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH + {0xC3F4, 0xC3F4, prLV}, // Lo HANGUL SYLLABLE SSWA + {0xC3F5, 0xC40F, prLVT}, // Lo [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH + {0xC410, 0xC410, prLV}, // Lo HANGUL SYLLABLE SSWAE + {0xC411, 0xC42B, prLVT}, // Lo [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH + {0xC42C, 0xC42C, prLV}, // Lo HANGUL SYLLABLE SSOE + {0xC42D, 0xC447, prLVT}, // Lo [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH + {0xC448, 0xC448, prLV}, // Lo HANGUL SYLLABLE SSYO + {0xC449, 0xC463, prLVT}, // Lo [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH + {0xC464, 0xC464, prLV}, // Lo HANGUL SYLLABLE SSU + {0xC465, 0xC47F, prLVT}, // Lo [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH + {0xC480, 0xC480, prLV}, // Lo HANGUL SYLLABLE SSWEO + {0xC481, 0xC49B, prLVT}, // Lo [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH + {0xC49C, 0xC49C, prLV}, // Lo HANGUL SYLLABLE SSWE + {0xC49D, 0xC4B7, prLVT}, // Lo [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH + {0xC4B8, 0xC4B8, prLV}, // Lo HANGUL SYLLABLE SSWI + {0xC4B9, 0xC4D3, prLVT}, // Lo [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH + {0xC4D4, 0xC4D4, prLV}, // Lo HANGUL SYLLABLE SSYU + {0xC4D5, 0xC4EF, prLVT}, // Lo [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH + {0xC4F0, 0xC4F0, prLV}, // Lo HANGUL SYLLABLE SSEU + {0xC4F1, 0xC50B, prLVT}, // Lo [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH + {0xC50C, 0xC50C, prLV}, // Lo HANGUL SYLLABLE SSYI + {0xC50D, 0xC527, prLVT}, // Lo [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH + {0xC528, 0xC528, prLV}, // Lo HANGUL SYLLABLE SSI + {0xC529, 0xC543, prLVT}, // Lo [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH + {0xC544, 0xC544, prLV}, // Lo HANGUL SYLLABLE A + {0xC545, 0xC55F, prLVT}, // Lo [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH + {0xC560, 0xC560, prLV}, // Lo HANGUL SYLLABLE AE + {0xC561, 0xC57B, prLVT}, // Lo [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH + {0xC57C, 0xC57C, prLV}, // Lo HANGUL SYLLABLE YA + {0xC57D, 0xC597, prLVT}, // Lo [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH + {0xC598, 0xC598, prLV}, // Lo HANGUL SYLLABLE YAE + {0xC599, 0xC5B3, prLVT}, // Lo [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH + {0xC5B4, 0xC5B4, prLV}, // Lo HANGUL SYLLABLE EO + {0xC5B5, 0xC5CF, prLVT}, // Lo [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH + {0xC5D0, 0xC5D0, prLV}, // Lo HANGUL SYLLABLE E + {0xC5D1, 0xC5EB, prLVT}, // Lo [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH + {0xC5EC, 0xC5EC, prLV}, // Lo HANGUL SYLLABLE YEO + {0xC5ED, 0xC607, prLVT}, // Lo [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH + {0xC608, 0xC608, prLV}, // Lo HANGUL SYLLABLE YE + {0xC609, 0xC623, prLVT}, // Lo [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH + {0xC624, 0xC624, prLV}, // Lo HANGUL SYLLABLE O + {0xC625, 0xC63F, prLVT}, // Lo [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH + {0xC640, 0xC640, prLV}, // Lo HANGUL SYLLABLE WA + {0xC641, 0xC65B, prLVT}, // Lo [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH + {0xC65C, 0xC65C, prLV}, // Lo HANGUL SYLLABLE WAE + {0xC65D, 0xC677, prLVT}, // Lo [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH + {0xC678, 0xC678, prLV}, // Lo HANGUL SYLLABLE OE + {0xC679, 0xC693, prLVT}, // Lo [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH + {0xC694, 0xC694, prLV}, // Lo HANGUL SYLLABLE YO + {0xC695, 0xC6AF, prLVT}, // Lo [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH + {0xC6B0, 0xC6B0, prLV}, // Lo HANGUL SYLLABLE U + {0xC6B1, 0xC6CB, prLVT}, // Lo [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH + {0xC6CC, 0xC6CC, prLV}, // Lo HANGUL SYLLABLE WEO + {0xC6CD, 0xC6E7, prLVT}, // Lo [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH + {0xC6E8, 0xC6E8, prLV}, // Lo HANGUL SYLLABLE WE + {0xC6E9, 0xC703, prLVT}, // Lo [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH + {0xC704, 0xC704, prLV}, // Lo HANGUL SYLLABLE WI + {0xC705, 0xC71F, prLVT}, // Lo [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH + {0xC720, 0xC720, prLV}, // Lo HANGUL SYLLABLE YU + {0xC721, 0xC73B, prLVT}, // Lo [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH + {0xC73C, 0xC73C, prLV}, // Lo HANGUL SYLLABLE EU + {0xC73D, 0xC757, prLVT}, // Lo [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH + {0xC758, 0xC758, prLV}, // Lo HANGUL SYLLABLE YI + {0xC759, 0xC773, prLVT}, // Lo [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH + {0xC774, 0xC774, prLV}, // Lo HANGUL SYLLABLE I + {0xC775, 0xC78F, prLVT}, // Lo [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH + {0xC790, 0xC790, prLV}, // Lo HANGUL SYLLABLE JA + {0xC791, 0xC7AB, prLVT}, // Lo [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH + {0xC7AC, 0xC7AC, prLV}, // Lo HANGUL SYLLABLE JAE + {0xC7AD, 0xC7C7, prLVT}, // Lo [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH + {0xC7C8, 0xC7C8, prLV}, // Lo HANGUL SYLLABLE JYA + {0xC7C9, 0xC7E3, prLVT}, // Lo [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH + {0xC7E4, 0xC7E4, prLV}, // Lo HANGUL SYLLABLE JYAE + {0xC7E5, 0xC7FF, prLVT}, // Lo [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH + {0xC800, 0xC800, prLV}, // Lo HANGUL SYLLABLE JEO + {0xC801, 0xC81B, prLVT}, // Lo [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH + {0xC81C, 0xC81C, prLV}, // Lo HANGUL SYLLABLE JE + {0xC81D, 0xC837, prLVT}, // Lo [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH + {0xC838, 0xC838, prLV}, // Lo HANGUL SYLLABLE JYEO + {0xC839, 0xC853, prLVT}, // Lo [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH + {0xC854, 0xC854, prLV}, // Lo HANGUL SYLLABLE JYE + {0xC855, 0xC86F, prLVT}, // Lo [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH + {0xC870, 0xC870, prLV}, // Lo HANGUL SYLLABLE JO + {0xC871, 0xC88B, prLVT}, // Lo [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH + {0xC88C, 0xC88C, prLV}, // Lo HANGUL SYLLABLE JWA + {0xC88D, 0xC8A7, prLVT}, // Lo [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH + {0xC8A8, 0xC8A8, prLV}, // Lo HANGUL SYLLABLE JWAE + {0xC8A9, 0xC8C3, prLVT}, // Lo [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH + {0xC8C4, 0xC8C4, prLV}, // Lo HANGUL SYLLABLE JOE + {0xC8C5, 0xC8DF, prLVT}, // Lo [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH + {0xC8E0, 0xC8E0, prLV}, // Lo HANGUL SYLLABLE JYO + {0xC8E1, 0xC8FB, prLVT}, // Lo [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH + {0xC8FC, 0xC8FC, prLV}, // Lo HANGUL SYLLABLE JU + {0xC8FD, 0xC917, prLVT}, // Lo [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH + {0xC918, 0xC918, prLV}, // Lo HANGUL SYLLABLE JWEO + {0xC919, 0xC933, prLVT}, // Lo [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH + {0xC934, 0xC934, prLV}, // Lo HANGUL SYLLABLE JWE + {0xC935, 0xC94F, prLVT}, // Lo [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH + {0xC950, 0xC950, prLV}, // Lo HANGUL SYLLABLE JWI + {0xC951, 0xC96B, prLVT}, // Lo [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH + {0xC96C, 0xC96C, prLV}, // Lo HANGUL SYLLABLE JYU + {0xC96D, 0xC987, prLVT}, // Lo [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH + {0xC988, 0xC988, prLV}, // Lo HANGUL SYLLABLE JEU + {0xC989, 0xC9A3, prLVT}, // Lo [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH + {0xC9A4, 0xC9A4, prLV}, // Lo HANGUL SYLLABLE JYI + {0xC9A5, 0xC9BF, prLVT}, // Lo [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH + {0xC9C0, 0xC9C0, prLV}, // Lo HANGUL SYLLABLE JI + {0xC9C1, 0xC9DB, prLVT}, // Lo [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH + {0xC9DC, 0xC9DC, prLV}, // Lo HANGUL SYLLABLE JJA + {0xC9DD, 0xC9F7, prLVT}, // Lo [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH + {0xC9F8, 0xC9F8, prLV}, // Lo HANGUL SYLLABLE JJAE + {0xC9F9, 0xCA13, prLVT}, // Lo [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH + {0xCA14, 0xCA14, prLV}, // Lo HANGUL SYLLABLE JJYA + {0xCA15, 0xCA2F, prLVT}, // Lo [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH + {0xCA30, 0xCA30, prLV}, // Lo HANGUL SYLLABLE JJYAE + {0xCA31, 0xCA4B, prLVT}, // Lo [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH + {0xCA4C, 0xCA4C, prLV}, // Lo HANGUL SYLLABLE JJEO + {0xCA4D, 0xCA67, prLVT}, // Lo [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH + {0xCA68, 0xCA68, prLV}, // Lo HANGUL SYLLABLE JJE + {0xCA69, 0xCA83, prLVT}, // Lo [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH + {0xCA84, 0xCA84, prLV}, // Lo HANGUL SYLLABLE JJYEO + {0xCA85, 0xCA9F, prLVT}, // Lo [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH + {0xCAA0, 0xCAA0, prLV}, // Lo HANGUL SYLLABLE JJYE + {0xCAA1, 0xCABB, prLVT}, // Lo [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH + {0xCABC, 0xCABC, prLV}, // Lo HANGUL SYLLABLE JJO + {0xCABD, 0xCAD7, prLVT}, // Lo [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH + {0xCAD8, 0xCAD8, prLV}, // Lo HANGUL SYLLABLE JJWA + {0xCAD9, 0xCAF3, prLVT}, // Lo [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH + {0xCAF4, 0xCAF4, prLV}, // Lo HANGUL SYLLABLE JJWAE + {0xCAF5, 0xCB0F, prLVT}, // Lo [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH + {0xCB10, 0xCB10, prLV}, // Lo HANGUL SYLLABLE JJOE + {0xCB11, 0xCB2B, prLVT}, // Lo [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH + {0xCB2C, 0xCB2C, prLV}, // Lo HANGUL SYLLABLE JJYO + {0xCB2D, 0xCB47, prLVT}, // Lo [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH + {0xCB48, 0xCB48, prLV}, // Lo HANGUL SYLLABLE JJU + {0xCB49, 0xCB63, prLVT}, // Lo [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH + {0xCB64, 0xCB64, prLV}, // Lo HANGUL SYLLABLE JJWEO + {0xCB65, 0xCB7F, prLVT}, // Lo [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH + {0xCB80, 0xCB80, prLV}, // Lo HANGUL SYLLABLE JJWE + {0xCB81, 0xCB9B, prLVT}, // Lo [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH + {0xCB9C, 0xCB9C, prLV}, // Lo HANGUL SYLLABLE JJWI + {0xCB9D, 0xCBB7, prLVT}, // Lo [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH + {0xCBB8, 0xCBB8, prLV}, // Lo HANGUL SYLLABLE JJYU + {0xCBB9, 0xCBD3, prLVT}, // Lo [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH + {0xCBD4, 0xCBD4, prLV}, // Lo HANGUL SYLLABLE JJEU + {0xCBD5, 0xCBEF, prLVT}, // Lo [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH + {0xCBF0, 0xCBF0, prLV}, // Lo HANGUL SYLLABLE JJYI + {0xCBF1, 0xCC0B, prLVT}, // Lo [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH + {0xCC0C, 0xCC0C, prLV}, // Lo HANGUL SYLLABLE JJI + {0xCC0D, 0xCC27, prLVT}, // Lo [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH + {0xCC28, 0xCC28, prLV}, // Lo HANGUL SYLLABLE CA + {0xCC29, 0xCC43, prLVT}, // Lo [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH + {0xCC44, 0xCC44, prLV}, // Lo HANGUL SYLLABLE CAE + {0xCC45, 0xCC5F, prLVT}, // Lo [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH + {0xCC60, 0xCC60, prLV}, // Lo HANGUL SYLLABLE CYA + {0xCC61, 0xCC7B, prLVT}, // Lo [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH + {0xCC7C, 0xCC7C, prLV}, // Lo HANGUL SYLLABLE CYAE + {0xCC7D, 0xCC97, prLVT}, // Lo [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH + {0xCC98, 0xCC98, prLV}, // Lo HANGUL SYLLABLE CEO + {0xCC99, 0xCCB3, prLVT}, // Lo [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH + {0xCCB4, 0xCCB4, prLV}, // Lo HANGUL SYLLABLE CE + {0xCCB5, 0xCCCF, prLVT}, // Lo [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH + {0xCCD0, 0xCCD0, prLV}, // Lo HANGUL SYLLABLE CYEO + {0xCCD1, 0xCCEB, prLVT}, // Lo [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH + {0xCCEC, 0xCCEC, prLV}, // Lo HANGUL SYLLABLE CYE + {0xCCED, 0xCD07, prLVT}, // Lo [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH + {0xCD08, 0xCD08, prLV}, // Lo HANGUL SYLLABLE CO + {0xCD09, 0xCD23, prLVT}, // Lo [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH + {0xCD24, 0xCD24, prLV}, // Lo HANGUL SYLLABLE CWA + {0xCD25, 0xCD3F, prLVT}, // Lo [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH + {0xCD40, 0xCD40, prLV}, // Lo HANGUL SYLLABLE CWAE + {0xCD41, 0xCD5B, prLVT}, // Lo [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH + {0xCD5C, 0xCD5C, prLV}, // Lo HANGUL SYLLABLE COE + {0xCD5D, 0xCD77, prLVT}, // Lo [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH + {0xCD78, 0xCD78, prLV}, // Lo HANGUL SYLLABLE CYO + {0xCD79, 0xCD93, prLVT}, // Lo [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH + {0xCD94, 0xCD94, prLV}, // Lo HANGUL SYLLABLE CU + {0xCD95, 0xCDAF, prLVT}, // Lo [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH + {0xCDB0, 0xCDB0, prLV}, // Lo HANGUL SYLLABLE CWEO + {0xCDB1, 0xCDCB, prLVT}, // Lo [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH + {0xCDCC, 0xCDCC, prLV}, // Lo HANGUL SYLLABLE CWE + {0xCDCD, 0xCDE7, prLVT}, // Lo [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH + {0xCDE8, 0xCDE8, prLV}, // Lo HANGUL SYLLABLE CWI + {0xCDE9, 0xCE03, prLVT}, // Lo [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH + {0xCE04, 0xCE04, prLV}, // Lo HANGUL SYLLABLE CYU + {0xCE05, 0xCE1F, prLVT}, // Lo [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH + {0xCE20, 0xCE20, prLV}, // Lo HANGUL SYLLABLE CEU + {0xCE21, 0xCE3B, prLVT}, // Lo [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH + {0xCE3C, 0xCE3C, prLV}, // Lo HANGUL SYLLABLE CYI + {0xCE3D, 0xCE57, prLVT}, // Lo [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH + {0xCE58, 0xCE58, prLV}, // Lo HANGUL SYLLABLE CI + {0xCE59, 0xCE73, prLVT}, // Lo [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH + {0xCE74, 0xCE74, prLV}, // Lo HANGUL SYLLABLE KA + {0xCE75, 0xCE8F, prLVT}, // Lo [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH + {0xCE90, 0xCE90, prLV}, // Lo HANGUL SYLLABLE KAE + {0xCE91, 0xCEAB, prLVT}, // Lo [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH + {0xCEAC, 0xCEAC, prLV}, // Lo HANGUL SYLLABLE KYA + {0xCEAD, 0xCEC7, prLVT}, // Lo [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH + {0xCEC8, 0xCEC8, prLV}, // Lo HANGUL SYLLABLE KYAE + {0xCEC9, 0xCEE3, prLVT}, // Lo [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH + {0xCEE4, 0xCEE4, prLV}, // Lo HANGUL SYLLABLE KEO + {0xCEE5, 0xCEFF, prLVT}, // Lo [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH + {0xCF00, 0xCF00, prLV}, // Lo HANGUL SYLLABLE KE + {0xCF01, 0xCF1B, prLVT}, // Lo [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH + {0xCF1C, 0xCF1C, prLV}, // Lo HANGUL SYLLABLE KYEO + {0xCF1D, 0xCF37, prLVT}, // Lo [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH + {0xCF38, 0xCF38, prLV}, // Lo HANGUL SYLLABLE KYE + {0xCF39, 0xCF53, prLVT}, // Lo [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH + {0xCF54, 0xCF54, prLV}, // Lo HANGUL SYLLABLE KO + {0xCF55, 0xCF6F, prLVT}, // Lo [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH + {0xCF70, 0xCF70, prLV}, // Lo HANGUL SYLLABLE KWA + {0xCF71, 0xCF8B, prLVT}, // Lo [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH + {0xCF8C, 0xCF8C, prLV}, // Lo HANGUL SYLLABLE KWAE + {0xCF8D, 0xCFA7, prLVT}, // Lo [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH + {0xCFA8, 0xCFA8, prLV}, // Lo HANGUL SYLLABLE KOE + {0xCFA9, 0xCFC3, prLVT}, // Lo [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH + {0xCFC4, 0xCFC4, prLV}, // Lo HANGUL SYLLABLE KYO + {0xCFC5, 0xCFDF, prLVT}, // Lo [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH + {0xCFE0, 0xCFE0, prLV}, // Lo HANGUL SYLLABLE KU + {0xCFE1, 0xCFFB, prLVT}, // Lo [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH + {0xCFFC, 0xCFFC, prLV}, // Lo HANGUL SYLLABLE KWEO + {0xCFFD, 0xD017, prLVT}, // Lo [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH + {0xD018, 0xD018, prLV}, // Lo HANGUL SYLLABLE KWE + {0xD019, 0xD033, prLVT}, // Lo [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH + {0xD034, 0xD034, prLV}, // Lo HANGUL SYLLABLE KWI + {0xD035, 0xD04F, prLVT}, // Lo [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH + {0xD050, 0xD050, prLV}, // Lo HANGUL SYLLABLE KYU + {0xD051, 0xD06B, prLVT}, // Lo [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH + {0xD06C, 0xD06C, prLV}, // Lo HANGUL SYLLABLE KEU + {0xD06D, 0xD087, prLVT}, // Lo [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH + {0xD088, 0xD088, prLV}, // Lo HANGUL SYLLABLE KYI + {0xD089, 0xD0A3, prLVT}, // Lo [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH + {0xD0A4, 0xD0A4, prLV}, // Lo HANGUL SYLLABLE KI + {0xD0A5, 0xD0BF, prLVT}, // Lo [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH + {0xD0C0, 0xD0C0, prLV}, // Lo HANGUL SYLLABLE TA + {0xD0C1, 0xD0DB, prLVT}, // Lo [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH + {0xD0DC, 0xD0DC, prLV}, // Lo HANGUL SYLLABLE TAE + {0xD0DD, 0xD0F7, prLVT}, // Lo [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH + {0xD0F8, 0xD0F8, prLV}, // Lo HANGUL SYLLABLE TYA + {0xD0F9, 0xD113, prLVT}, // Lo [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH + {0xD114, 0xD114, prLV}, // Lo HANGUL SYLLABLE TYAE + {0xD115, 0xD12F, prLVT}, // Lo [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH + {0xD130, 0xD130, prLV}, // Lo HANGUL SYLLABLE TEO + {0xD131, 0xD14B, prLVT}, // Lo [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH + {0xD14C, 0xD14C, prLV}, // Lo HANGUL SYLLABLE TE + {0xD14D, 0xD167, prLVT}, // Lo [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH + {0xD168, 0xD168, prLV}, // Lo HANGUL SYLLABLE TYEO + {0xD169, 0xD183, prLVT}, // Lo [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH + {0xD184, 0xD184, prLV}, // Lo HANGUL SYLLABLE TYE + {0xD185, 0xD19F, prLVT}, // Lo [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH + {0xD1A0, 0xD1A0, prLV}, // Lo HANGUL SYLLABLE TO + {0xD1A1, 0xD1BB, prLVT}, // Lo [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH + {0xD1BC, 0xD1BC, prLV}, // Lo HANGUL SYLLABLE TWA + {0xD1BD, 0xD1D7, prLVT}, // Lo [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH + {0xD1D8, 0xD1D8, prLV}, // Lo HANGUL SYLLABLE TWAE + {0xD1D9, 0xD1F3, prLVT}, // Lo [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH + {0xD1F4, 0xD1F4, prLV}, // Lo HANGUL SYLLABLE TOE + {0xD1F5, 0xD20F, prLVT}, // Lo [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH + {0xD210, 0xD210, prLV}, // Lo HANGUL SYLLABLE TYO + {0xD211, 0xD22B, prLVT}, // Lo [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH + {0xD22C, 0xD22C, prLV}, // Lo HANGUL SYLLABLE TU + {0xD22D, 0xD247, prLVT}, // Lo [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH + {0xD248, 0xD248, prLV}, // Lo HANGUL SYLLABLE TWEO + {0xD249, 0xD263, prLVT}, // Lo [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH + {0xD264, 0xD264, prLV}, // Lo HANGUL SYLLABLE TWE + {0xD265, 0xD27F, prLVT}, // Lo [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH + {0xD280, 0xD280, prLV}, // Lo HANGUL SYLLABLE TWI + {0xD281, 0xD29B, prLVT}, // Lo [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH + {0xD29C, 0xD29C, prLV}, // Lo HANGUL SYLLABLE TYU + {0xD29D, 0xD2B7, prLVT}, // Lo [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH + {0xD2B8, 0xD2B8, prLV}, // Lo HANGUL SYLLABLE TEU + {0xD2B9, 0xD2D3, prLVT}, // Lo [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH + {0xD2D4, 0xD2D4, prLV}, // Lo HANGUL SYLLABLE TYI + {0xD2D5, 0xD2EF, prLVT}, // Lo [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH + {0xD2F0, 0xD2F0, prLV}, // Lo HANGUL SYLLABLE TI + {0xD2F1, 0xD30B, prLVT}, // Lo [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH + {0xD30C, 0xD30C, prLV}, // Lo HANGUL SYLLABLE PA + {0xD30D, 0xD327, prLVT}, // Lo [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH + {0xD328, 0xD328, prLV}, // Lo HANGUL SYLLABLE PAE + {0xD329, 0xD343, prLVT}, // Lo [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH + {0xD344, 0xD344, prLV}, // Lo HANGUL SYLLABLE PYA + {0xD345, 0xD35F, prLVT}, // Lo [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH + {0xD360, 0xD360, prLV}, // Lo HANGUL SYLLABLE PYAE + {0xD361, 0xD37B, prLVT}, // Lo [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH + {0xD37C, 0xD37C, prLV}, // Lo HANGUL SYLLABLE PEO + {0xD37D, 0xD397, prLVT}, // Lo [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH + {0xD398, 0xD398, prLV}, // Lo HANGUL SYLLABLE PE + {0xD399, 0xD3B3, prLVT}, // Lo [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH + {0xD3B4, 0xD3B4, prLV}, // Lo HANGUL SYLLABLE PYEO + {0xD3B5, 0xD3CF, prLVT}, // Lo [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH + {0xD3D0, 0xD3D0, prLV}, // Lo HANGUL SYLLABLE PYE + {0xD3D1, 0xD3EB, prLVT}, // Lo [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH + {0xD3EC, 0xD3EC, prLV}, // Lo HANGUL SYLLABLE PO + {0xD3ED, 0xD407, prLVT}, // Lo [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH + {0xD408, 0xD408, prLV}, // Lo HANGUL SYLLABLE PWA + {0xD409, 0xD423, prLVT}, // Lo [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH + {0xD424, 0xD424, prLV}, // Lo HANGUL SYLLABLE PWAE + {0xD425, 0xD43F, prLVT}, // Lo [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH + {0xD440, 0xD440, prLV}, // Lo HANGUL SYLLABLE POE + {0xD441, 0xD45B, prLVT}, // Lo [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH + {0xD45C, 0xD45C, prLV}, // Lo HANGUL SYLLABLE PYO + {0xD45D, 0xD477, prLVT}, // Lo [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH + {0xD478, 0xD478, prLV}, // Lo HANGUL SYLLABLE PU + {0xD479, 0xD493, prLVT}, // Lo [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH + {0xD494, 0xD494, prLV}, // Lo HANGUL SYLLABLE PWEO + {0xD495, 0xD4AF, prLVT}, // Lo [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH + {0xD4B0, 0xD4B0, prLV}, // Lo HANGUL SYLLABLE PWE + {0xD4B1, 0xD4CB, prLVT}, // Lo [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH + {0xD4CC, 0xD4CC, prLV}, // Lo HANGUL SYLLABLE PWI + {0xD4CD, 0xD4E7, prLVT}, // Lo [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH + {0xD4E8, 0xD4E8, prLV}, // Lo HANGUL SYLLABLE PYU + {0xD4E9, 0xD503, prLVT}, // Lo [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH + {0xD504, 0xD504, prLV}, // Lo HANGUL SYLLABLE PEU + {0xD505, 0xD51F, prLVT}, // Lo [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH + {0xD520, 0xD520, prLV}, // Lo HANGUL SYLLABLE PYI + {0xD521, 0xD53B, prLVT}, // Lo [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH + {0xD53C, 0xD53C, prLV}, // Lo HANGUL SYLLABLE PI + {0xD53D, 0xD557, prLVT}, // Lo [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH + {0xD558, 0xD558, prLV}, // Lo HANGUL SYLLABLE HA + {0xD559, 0xD573, prLVT}, // Lo [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH + {0xD574, 0xD574, prLV}, // Lo HANGUL SYLLABLE HAE + {0xD575, 0xD58F, prLVT}, // Lo [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH + {0xD590, 0xD590, prLV}, // Lo HANGUL SYLLABLE HYA + {0xD591, 0xD5AB, prLVT}, // Lo [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH + {0xD5AC, 0xD5AC, prLV}, // Lo HANGUL SYLLABLE HYAE + {0xD5AD, 0xD5C7, prLVT}, // Lo [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH + {0xD5C8, 0xD5C8, prLV}, // Lo HANGUL SYLLABLE HEO + {0xD5C9, 0xD5E3, prLVT}, // Lo [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH + {0xD5E4, 0xD5E4, prLV}, // Lo HANGUL SYLLABLE HE + {0xD5E5, 0xD5FF, prLVT}, // Lo [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH + {0xD600, 0xD600, prLV}, // Lo HANGUL SYLLABLE HYEO + {0xD601, 0xD61B, prLVT}, // Lo [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH + {0xD61C, 0xD61C, prLV}, // Lo HANGUL SYLLABLE HYE + {0xD61D, 0xD637, prLVT}, // Lo [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH + {0xD638, 0xD638, prLV}, // Lo HANGUL SYLLABLE HO + {0xD639, 0xD653, prLVT}, // Lo [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH + {0xD654, 0xD654, prLV}, // Lo HANGUL SYLLABLE HWA + {0xD655, 0xD66F, prLVT}, // Lo [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH + {0xD670, 0xD670, prLV}, // Lo HANGUL SYLLABLE HWAE + {0xD671, 0xD68B, prLVT}, // Lo [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH + {0xD68C, 0xD68C, prLV}, // Lo HANGUL SYLLABLE HOE + {0xD68D, 0xD6A7, prLVT}, // Lo [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH + {0xD6A8, 0xD6A8, prLV}, // Lo HANGUL SYLLABLE HYO + {0xD6A9, 0xD6C3, prLVT}, // Lo [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH + {0xD6C4, 0xD6C4, prLV}, // Lo HANGUL SYLLABLE HU + {0xD6C5, 0xD6DF, prLVT}, // Lo [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH + {0xD6E0, 0xD6E0, prLV}, // Lo HANGUL SYLLABLE HWEO + {0xD6E1, 0xD6FB, prLVT}, // Lo [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH + {0xD6FC, 0xD6FC, prLV}, // Lo HANGUL SYLLABLE HWE + {0xD6FD, 0xD717, prLVT}, // Lo [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH + {0xD718, 0xD718, prLV}, // Lo HANGUL SYLLABLE HWI + {0xD719, 0xD733, prLVT}, // Lo [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH + {0xD734, 0xD734, prLV}, // Lo HANGUL SYLLABLE HYU + {0xD735, 0xD74F, prLVT}, // Lo [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH + {0xD750, 0xD750, prLV}, // Lo HANGUL SYLLABLE HEU + {0xD751, 0xD76B, prLVT}, // Lo [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH + {0xD76C, 0xD76C, prLV}, // Lo HANGUL SYLLABLE HYI + {0xD76D, 0xD787, prLVT}, // Lo [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH + {0xD788, 0xD788, prLV}, // Lo HANGUL SYLLABLE HI + {0xD789, 0xD7A3, prLVT}, // Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prV}, // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prT}, // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xFB1E, 0xFB1E, prExtend}, // Mn HEBREW POINT JUDEO-SPANISH VARIKA + {0xFE00, 0xFE0F, prExtend}, // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE20, 0xFE2F, prExtend}, // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFEFF, 0xFEFF, prControl}, // Cf ZERO WIDTH NO-BREAK SPACE + {0xFF9E, 0xFF9F, prExtend}, // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFF0, 0xFFF8, prControl}, // Cn [9] .. + {0xFFF9, 0xFFFB, prControl}, // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0x101FD, 0x101FD, prExtend}, // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x102E0, 0x102E0, prExtend}, // Mn COPTIC EPACT THOUSANDS MARK + {0x10376, 0x1037A, prExtend}, // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10A01, 0x10A03, prExtend}, // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prExtend}, // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prExtend}, // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A38, 0x10A3A, prExtend}, // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prExtend}, // Mn KHAROSHTHI VIRAMA + {0x10AE5, 0x10AE6, prExtend}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10D24, 0x10D27, prExtend}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10F46, 0x10F50, prExtend}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x11000, 0x11000, prSpacingMark}, // Mc BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prExtend}, // Mn BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prSpacingMark}, // Mc BRAHMI SIGN VISARGA + {0x11038, 0x11046, prExtend}, // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x1107F, 0x11081, prExtend}, // Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prSpacingMark}, // Mc KAITHI SIGN VISARGA + {0x110B0, 0x110B2, prSpacingMark}, // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prExtend}, // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prSpacingMark}, // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prExtend}, // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BD, 0x110BD, prPreprend}, // Cf KAITHI NUMBER SIGN + {0x110CD, 0x110CD, prPreprend}, // Cf KAITHI NUMBER SIGN ABOVE + {0x11100, 0x11102, prExtend}, // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11127, 0x1112B, prExtend}, // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prSpacingMark}, // Mc CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prExtend}, // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11145, 0x11146, prSpacingMark}, // Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11173, 0x11173, prExtend}, // Mn MAHAJANI SIGN NUKTA + {0x11180, 0x11181, prExtend}, // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prSpacingMark}, // Mc SHARADA SIGN VISARGA + {0x111B3, 0x111B5, prSpacingMark}, // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prExtend}, // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prSpacingMark}, // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C2, 0x111C3, prPreprend}, // Lo [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA + {0x111C9, 0x111CC, prExtend}, // Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x1122C, 0x1122E, prSpacingMark}, // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prExtend}, // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prSpacingMark}, // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prExtend}, // Mn KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prSpacingMark}, // Mc KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x112DF, 0x112DF, prExtend}, // Mn KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prSpacingMark}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prExtend}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x11300, 0x11301, prExtend}, // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prSpacingMark}, // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x1133B, 0x1133C, prExtend}, // Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133E, 0x1133E, prExtend}, // Mc GRANTHA VOWEL SIGN AA + {0x1133F, 0x1133F, prSpacingMark}, // Mc GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prExtend}, // Mn GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prSpacingMark}, // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prSpacingMark}, // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prSpacingMark}, // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11357, 0x11357, prExtend}, // Mc GRANTHA AU LENGTH MARK + {0x11362, 0x11363, prSpacingMark}, // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prExtend}, // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prExtend}, // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11435, 0x11437, prSpacingMark}, // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prExtend}, // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prSpacingMark}, // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prExtend}, // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prSpacingMark}, // Mc NEWA SIGN VISARGA + {0x11446, 0x11446, prExtend}, // Mn NEWA SIGN NUKTA + {0x1145E, 0x1145E, prExtend}, // Mn NEWA SANDHI MARK + {0x114B0, 0x114B0, prExtend}, // Mc TIRHUTA VOWEL SIGN AA + {0x114B1, 0x114B2, prSpacingMark}, // Mc [2] TIRHUTA VOWEL SIGN I..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prExtend}, // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prSpacingMark}, // Mc TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prExtend}, // Mn TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BC, prSpacingMark}, // Mc [2] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN O + {0x114BD, 0x114BD, prExtend}, // Mc TIRHUTA VOWEL SIGN SHORT O + {0x114BE, 0x114BE, prSpacingMark}, // Mc TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prExtend}, // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prSpacingMark}, // Mc TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prExtend}, // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x115AF, 0x115AF, prExtend}, // Mc SIDDHAM VOWEL SIGN AA + {0x115B0, 0x115B1, prSpacingMark}, // Mc [2] SIDDHAM VOWEL SIGN I..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prExtend}, // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prSpacingMark}, // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prExtend}, // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prSpacingMark}, // Mc SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prExtend}, // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115DC, 0x115DD, prExtend}, // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11630, 0x11632, prSpacingMark}, // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prExtend}, // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prSpacingMark}, // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prExtend}, // Mn MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prSpacingMark}, // Mc MODI SIGN VISARGA + {0x1163F, 0x11640, prExtend}, // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x116AB, 0x116AB, prExtend}, // Mn TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prSpacingMark}, // Mc TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prExtend}, // Mn TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prSpacingMark}, // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prExtend}, // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prSpacingMark}, // Mc TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prExtend}, // Mn TAKRI SIGN NUKTA + {0x1171D, 0x1171F, prExtend}, // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11720, 0x11721, prSpacingMark}, // Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA + {0x11722, 0x11725, prExtend}, // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prSpacingMark}, // Mc AHOM VOWEL SIGN E + {0x11727, 0x1172B, prExtend}, // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x1182C, 0x1182E, prSpacingMark}, // Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prExtend}, // Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prSpacingMark}, // Mc DOGRA SIGN VISARGA + {0x11839, 0x1183A, prExtend}, // Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x119D1, 0x119D3, prSpacingMark}, // Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prExtend}, // Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prExtend}, // Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prSpacingMark}, // Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prExtend}, // Mn NANDINAGARI SIGN VIRAMA + {0x119E4, 0x119E4, prSpacingMark}, // Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A01, 0x11A0A, prExtend}, // Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A33, 0x11A38, prExtend}, // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prSpacingMark}, // Mc ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prPreprend}, // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prExtend}, // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A47, 0x11A47, prExtend}, // Mn ZANABAZAR SQUARE SUBJOINER + {0x11A51, 0x11A56, prExtend}, // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prSpacingMark}, // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prExtend}, // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A84, 0x11A89, prPreprend}, // Lo [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prExtend}, // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prSpacingMark}, // Mc SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prExtend}, // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11C2F, 0x11C2F, prSpacingMark}, // Mc BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prExtend}, // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prExtend}, // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prSpacingMark}, // Mc BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prExtend}, // Mn BHAIKSUKI SIGN VIRAMA + {0x11C92, 0x11CA7, prExtend}, // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prSpacingMark}, // Mc MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prExtend}, // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prSpacingMark}, // Mc MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prExtend}, // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prSpacingMark}, // Mc MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prExtend}, // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D31, 0x11D36, prExtend}, // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prExtend}, // Mn MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prExtend}, // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prExtend}, // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prPreprend}, // Lo MASARAM GONDI REPHA + {0x11D47, 0x11D47, prExtend}, // Mn MASARAM GONDI RA-KARA + {0x11D8A, 0x11D8E, prSpacingMark}, // Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prExtend}, // Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prSpacingMark}, // Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prExtend}, // Mn GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prSpacingMark}, // Mc GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prExtend}, // Mn GUNJALA GONDI VIRAMA + {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prSpacingMark}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x13430, 0x13438, prControl}, // Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT + {0x16AF0, 0x16AF4, prExtend}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16B30, 0x16B36, prExtend}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16F4F, 0x16F4F, prExtend}, // Mn MIAO SIGN CONSONANT MODIFIER BAR + {0x16F51, 0x16F87, prSpacingMark}, // Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prExtend}, // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x1BC9D, 0x1BC9E, prExtend}, // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BCA0, 0x1BCA3, prControl}, // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1D165, 0x1D165, prExtend}, // Mc MUSICAL SYMBOL COMBINING STEM + {0x1D166, 0x1D166, prSpacingMark}, // Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prExtend}, // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16D, 0x1D16D, prSpacingMark}, // Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT + {0x1D16E, 0x1D172, prExtend}, // Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prControl}, // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prExtend}, // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D185, 0x1D18B, prExtend}, // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D1AA, 0x1D1AD, prExtend}, // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D242, 0x1D244, prExtend}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1DA00, 0x1DA36, prExtend}, // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA3B, 0x1DA6C, prExtend}, // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA75, 0x1DA75, prExtend}, // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA84, 0x1DA84, prExtend}, // Mn SIGNWRITING LOCATION HEAD NECK + {0x1DA9B, 0x1DA9F, prExtend}, // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prExtend}, // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E8D0, 0x1E8D6, prExtend}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E944, 0x1E94A, prExtend}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1F000, 0x1F02B, prExtendedPictographic}, // 5.1 [44] (🀀..🀫) MAHJONG TILE EAST WIND..MAHJONG TILE BACK + {0x1F02C, 0x1F02F, prExtendedPictographic}, // NA [4] (🀬..🀯) .. + {0x1F030, 0x1F093, prExtendedPictographic}, // 5.1[100] (🀰..🂓) DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06 + {0x1F094, 0x1F09F, prExtendedPictographic}, // NA [12] (🂔..🂟) .. + {0x1F0A0, 0x1F0AE, prExtendedPictographic}, // 6.0 [15] (🂠..🂮) PLAYING CARD BACK..PLAYING CARD KING OF SPADES + {0x1F0AF, 0x1F0B0, prExtendedPictographic}, // NA [2] (🂯..🂰) .. + {0x1F0B1, 0x1F0BE, prExtendedPictographic}, // 6.0 [14] (🂱..🂾) PLAYING CARD ACE OF HEARTS..PLAYING CARD KING OF HEARTS + {0x1F0BF, 0x1F0BF, prExtendedPictographic}, // 7.0 [1] (🂿) PLAYING CARD RED JOKER + {0x1F0C0, 0x1F0C0, prExtendedPictographic}, // NA [1] (🃀) + {0x1F0C1, 0x1F0CF, prExtendedPictographic}, // 6.0 [15] (🃁..🃏) PLAYING CARD ACE OF DIAMONDS..joker + {0x1F0D0, 0x1F0D0, prExtendedPictographic}, // NA [1] (🃐) + {0x1F0D1, 0x1F0DF, prExtendedPictographic}, // 6.0 [15] (🃑..🃟) PLAYING CARD ACE OF CLUBS..PLAYING CARD WHITE JOKER + {0x1F0E0, 0x1F0F5, prExtendedPictographic}, // 7.0 [22] (🃠..🃵) PLAYING CARD FOOL..PLAYING CARD TRUMP-21 + {0x1F0F6, 0x1F0FF, prExtendedPictographic}, // NA [10] (🃶..🃿) .. + {0x1F10D, 0x1F10F, prExtendedPictographic}, // NA [3] (🄍..🄏) .. + {0x1F12F, 0x1F12F, prExtendedPictographic}, // 11.0 [1] (🄯) COPYLEFT SYMBOL + {0x1F16C, 0x1F16C, prExtendedPictographic}, // 12.0 [1] (🅬) RAISED MR SIGN + {0x1F16D, 0x1F16F, prExtendedPictographic}, // NA [3] (🅭..🅯) .. + {0x1F170, 0x1F171, prExtendedPictographic}, // 6.0 [2] (🅰️..🅱️) A button (blood type)..B button (blood type) + {0x1F17E, 0x1F17E, prExtendedPictographic}, // 6.0 [1] (🅾️) O button (blood type) + {0x1F17F, 0x1F17F, prExtendedPictographic}, // 5.2 [1] (🅿️) P button + {0x1F18E, 0x1F18E, prExtendedPictographic}, // 6.0 [1] (🆎) AB button (blood type) + {0x1F191, 0x1F19A, prExtendedPictographic}, // 6.0 [10] (🆑..🆚) CL button..VS button + {0x1F1AD, 0x1F1E5, prExtendedPictographic}, // NA [57] (🆭..🇥) .. + {0x1F1E6, 0x1F1FF, prRegionalIndicator}, // So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + {0x1F201, 0x1F202, prExtendedPictographic}, // 6.0 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button + {0x1F203, 0x1F20F, prExtendedPictographic}, // NA [13] (🈃..🈏) .. + {0x1F21A, 0x1F21A, prExtendedPictographic}, // 5.2 [1] (🈚) Japanese “free of charge” button + {0x1F22F, 0x1F22F, prExtendedPictographic}, // 5.2 [1] (🈯) Japanese “reserved” button + {0x1F232, 0x1F23A, prExtendedPictographic}, // 6.0 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button + {0x1F23C, 0x1F23F, prExtendedPictographic}, // NA [4] (🈼..🈿) .. + {0x1F249, 0x1F24F, prExtendedPictographic}, // NA [7] (🉉..🉏) .. + {0x1F250, 0x1F251, prExtendedPictographic}, // 6.0 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button + {0x1F252, 0x1F25F, prExtendedPictographic}, // NA [14] (🉒..🉟) .. + {0x1F260, 0x1F265, prExtendedPictographic}, // 10.0 [6] (🉠..🉥) ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI + {0x1F266, 0x1F2FF, prExtendedPictographic}, // NA[154] (🉦..🋿) .. + {0x1F300, 0x1F320, prExtendedPictographic}, // 6.0 [33] (🌀..🌠) cyclone..shooting star + {0x1F321, 0x1F32C, prExtendedPictographic}, // 7.0 [12] (🌡️..🌬️) thermometer..wind face + {0x1F32D, 0x1F32F, prExtendedPictographic}, // 8.0 [3] (🌭..🌯) hot dog..burrito + {0x1F330, 0x1F335, prExtendedPictographic}, // 6.0 [6] (🌰..🌵) chestnut..cactus + {0x1F336, 0x1F336, prExtendedPictographic}, // 7.0 [1] (🌶️) hot pepper + {0x1F337, 0x1F37C, prExtendedPictographic}, // 6.0 [70] (🌷..🍼) tulip..baby bottle + {0x1F37D, 0x1F37D, prExtendedPictographic}, // 7.0 [1] (🍽️) fork and knife with plate + {0x1F37E, 0x1F37F, prExtendedPictographic}, // 8.0 [2] (🍾..🍿) bottle with popping cork..popcorn + {0x1F380, 0x1F393, prExtendedPictographic}, // 6.0 [20] (🎀..🎓) ribbon..graduation cap + {0x1F394, 0x1F39F, prExtendedPictographic}, // 7.0 [12] (🎔..🎟️) HEART WITH TIP ON THE LEFT..admission tickets + {0x1F3A0, 0x1F3C4, prExtendedPictographic}, // 6.0 [37] (🎠..🏄) carousel horse..person surfing + {0x1F3C5, 0x1F3C5, prExtendedPictographic}, // 7.0 [1] (🏅) sports medal + {0x1F3C6, 0x1F3CA, prExtendedPictographic}, // 6.0 [5] (🏆..🏊) trophy..person swimming + {0x1F3CB, 0x1F3CE, prExtendedPictographic}, // 7.0 [4] (🏋️..🏎️) person lifting weights..racing car + {0x1F3CF, 0x1F3D3, prExtendedPictographic}, // 8.0 [5] (🏏..🏓) cricket game..ping pong + {0x1F3D4, 0x1F3DF, prExtendedPictographic}, // 7.0 [12] (🏔️..🏟️) snow-capped mountain..stadium + {0x1F3E0, 0x1F3F0, prExtendedPictographic}, // 6.0 [17] (🏠..🏰) house..castle + {0x1F3F1, 0x1F3F7, prExtendedPictographic}, // 7.0 [7] (🏱..🏷️) WHITE PENNANT..label + {0x1F3F8, 0x1F3FA, prExtendedPictographic}, // 8.0 [3] (🏸..🏺) badminton..amphora + {0x1F3FB, 0x1F3FF, prExtend}, // Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 + {0x1F400, 0x1F43E, prExtendedPictographic}, // 6.0 [63] (🐀..🐾) rat..paw prints + {0x1F43F, 0x1F43F, prExtendedPictographic}, // 7.0 [1] (🐿️) chipmunk + {0x1F440, 0x1F440, prExtendedPictographic}, // 6.0 [1] (👀) eyes + {0x1F441, 0x1F441, prExtendedPictographic}, // 7.0 [1] (👁️) eye + {0x1F442, 0x1F4F7, prExtendedPictographic}, // 6.0[182] (👂..📷) ear..camera + {0x1F4F8, 0x1F4F8, prExtendedPictographic}, // 7.0 [1] (📸) camera with flash + {0x1F4F9, 0x1F4FC, prExtendedPictographic}, // 6.0 [4] (📹..📼) video camera..videocassette + {0x1F4FD, 0x1F4FE, prExtendedPictographic}, // 7.0 [2] (📽️..📾) film projector..PORTABLE STEREO + {0x1F4FF, 0x1F4FF, prExtendedPictographic}, // 8.0 [1] (📿) prayer beads + {0x1F500, 0x1F53D, prExtendedPictographic}, // 6.0 [62] (🔀..🔽) shuffle tracks button..downwards button + {0x1F546, 0x1F54A, prExtendedPictographic}, // 7.0 [5] (🕆..🕊️) WHITE LATIN CROSS..dove + {0x1F54B, 0x1F54F, prExtendedPictographic}, // 8.0 [5] (🕋..🕏) kaaba..BOWL OF HYGIEIA + {0x1F550, 0x1F567, prExtendedPictographic}, // 6.0 [24] (🕐..🕧) one o’clock..twelve-thirty + {0x1F568, 0x1F579, prExtendedPictographic}, // 7.0 [18] (🕨..🕹️) RIGHT SPEAKER..joystick + {0x1F57A, 0x1F57A, prExtendedPictographic}, // 9.0 [1] (🕺) man dancing + {0x1F57B, 0x1F5A3, prExtendedPictographic}, // 7.0 [41] (🕻..🖣) LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX + {0x1F5A4, 0x1F5A4, prExtendedPictographic}, // 9.0 [1] (🖤) black heart + {0x1F5A5, 0x1F5FA, prExtendedPictographic}, // 7.0 [86] (🖥️..🗺️) desktop computer..world map + {0x1F5FB, 0x1F5FF, prExtendedPictographic}, // 6.0 [5] (🗻..🗿) mount fuji..moai + {0x1F600, 0x1F600, prExtendedPictographic}, // 6.1 [1] (😀) grinning face + {0x1F601, 0x1F610, prExtendedPictographic}, // 6.0 [16] (😁..😐) beaming face with smiling eyes..neutral face + {0x1F611, 0x1F611, prExtendedPictographic}, // 6.1 [1] (😑) expressionless face + {0x1F612, 0x1F614, prExtendedPictographic}, // 6.0 [3] (😒..😔) unamused face..pensive face + {0x1F615, 0x1F615, prExtendedPictographic}, // 6.1 [1] (😕) confused face + {0x1F616, 0x1F616, prExtendedPictographic}, // 6.0 [1] (😖) confounded face + {0x1F617, 0x1F617, prExtendedPictographic}, // 6.1 [1] (😗) kissing face + {0x1F618, 0x1F618, prExtendedPictographic}, // 6.0 [1] (😘) face blowing a kiss + {0x1F619, 0x1F619, prExtendedPictographic}, // 6.1 [1] (😙) kissing face with smiling eyes + {0x1F61A, 0x1F61A, prExtendedPictographic}, // 6.0 [1] (😚) kissing face with closed eyes + {0x1F61B, 0x1F61B, prExtendedPictographic}, // 6.1 [1] (😛) face with tongue + {0x1F61C, 0x1F61E, prExtendedPictographic}, // 6.0 [3] (😜..😞) winking face with tongue..disappointed face + {0x1F61F, 0x1F61F, prExtendedPictographic}, // 6.1 [1] (😟) worried face + {0x1F620, 0x1F625, prExtendedPictographic}, // 6.0 [6] (😠..😥) angry face..sad but relieved face + {0x1F626, 0x1F627, prExtendedPictographic}, // 6.1 [2] (😦..😧) frowning face with open mouth..anguished face + {0x1F628, 0x1F62B, prExtendedPictographic}, // 6.0 [4] (😨..😫) fearful face..tired face + {0x1F62C, 0x1F62C, prExtendedPictographic}, // 6.1 [1] (😬) grimacing face + {0x1F62D, 0x1F62D, prExtendedPictographic}, // 6.0 [1] (😭) loudly crying face + {0x1F62E, 0x1F62F, prExtendedPictographic}, // 6.1 [2] (😮..😯) face with open mouth..hushed face + {0x1F630, 0x1F633, prExtendedPictographic}, // 6.0 [4] (😰..😳) anxious face with sweat..flushed face + {0x1F634, 0x1F634, prExtendedPictographic}, // 6.1 [1] (😴) sleeping face + {0x1F635, 0x1F640, prExtendedPictographic}, // 6.0 [12] (😵..🙀) dizzy face..weary cat + {0x1F641, 0x1F642, prExtendedPictographic}, // 7.0 [2] (🙁..🙂) slightly frowning face..slightly smiling face + {0x1F643, 0x1F644, prExtendedPictographic}, // 8.0 [2] (🙃..🙄) upside-down face..face with rolling eyes + {0x1F645, 0x1F64F, prExtendedPictographic}, // 6.0 [11] (🙅..🙏) person gesturing NO..folded hands + {0x1F680, 0x1F6C5, prExtendedPictographic}, // 6.0 [70] (🚀..🛅) rocket..left luggage + {0x1F6C6, 0x1F6CF, prExtendedPictographic}, // 7.0 [10] (🛆..🛏️) TRIANGLE WITH ROUNDED CORNERS..bed + {0x1F6D0, 0x1F6D0, prExtendedPictographic}, // 8.0 [1] (🛐) place of worship + {0x1F6D1, 0x1F6D2, prExtendedPictographic}, // 9.0 [2] (🛑..🛒) stop sign..shopping cart + {0x1F6D3, 0x1F6D4, prExtendedPictographic}, // 10.0 [2] (🛓..🛔) STUPA..PAGODA + {0x1F6D5, 0x1F6D5, prExtendedPictographic}, // 12.0 [1] (🛕) hindu temple + {0x1F6D6, 0x1F6DF, prExtendedPictographic}, // NA [10] (🛖..🛟) .. + {0x1F6E0, 0x1F6EC, prExtendedPictographic}, // 7.0 [13] (🛠️..🛬) hammer and wrench..airplane arrival + {0x1F6ED, 0x1F6EF, prExtendedPictographic}, // NA [3] (🛭..🛯) .. + {0x1F6F0, 0x1F6F3, prExtendedPictographic}, // 7.0 [4] (🛰️..🛳️) satellite..passenger ship + {0x1F6F4, 0x1F6F6, prExtendedPictographic}, // 9.0 [3] (🛴..🛶) kick scooter..canoe + {0x1F6F7, 0x1F6F8, prExtendedPictographic}, // 10.0 [2] (🛷..🛸) sled..flying saucer + {0x1F6F9, 0x1F6F9, prExtendedPictographic}, // 11.0 [1] (🛹) skateboard + {0x1F6FA, 0x1F6FA, prExtendedPictographic}, // 12.0 [1] (🛺) auto rickshaw + {0x1F6FB, 0x1F6FF, prExtendedPictographic}, // NA [5] (🛻..🛿) .. + {0x1F774, 0x1F77F, prExtendedPictographic}, // NA [12] (🝴..🝿) .. + {0x1F7D5, 0x1F7D8, prExtendedPictographic}, // 11.0 [4] (🟕..🟘) CIRCLED TRIANGLE..NEGATIVE CIRCLED SQUARE + {0x1F7D9, 0x1F7DF, prExtendedPictographic}, // NA [7] (🟙..🟟) .. + {0x1F7E0, 0x1F7EB, prExtendedPictographic}, // 12.0 [12] (🟠..🟫) orange circle..brown square + {0x1F7EC, 0x1F7FF, prExtendedPictographic}, // NA [20] (🟬..🟿) .. + {0x1F80C, 0x1F80F, prExtendedPictographic}, // NA [4] (🠌..🠏) .. + {0x1F848, 0x1F84F, prExtendedPictographic}, // NA [8] (🡈..🡏) .. + {0x1F85A, 0x1F85F, prExtendedPictographic}, // NA [6] (🡚..🡟) .. + {0x1F888, 0x1F88F, prExtendedPictographic}, // NA [8] (🢈..🢏) .. + {0x1F8AE, 0x1F8FF, prExtendedPictographic}, // NA [82] (🢮..🣿) .. + {0x1F90C, 0x1F90C, prExtendedPictographic}, // NA [1] (🤌) + {0x1F90D, 0x1F90F, prExtendedPictographic}, // 12.0 [3] (🤍..🤏) white heart..pinching hand + {0x1F910, 0x1F918, prExtendedPictographic}, // 8.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns + {0x1F919, 0x1F91E, prExtendedPictographic}, // 9.0 [6] (🤙..🤞) call me hand..crossed fingers + {0x1F91F, 0x1F91F, prExtendedPictographic}, // 10.0 [1] (🤟) love-you gesture + {0x1F920, 0x1F927, prExtendedPictographic}, // 9.0 [8] (🤠..🤧) cowboy hat face..sneezing face + {0x1F928, 0x1F92F, prExtendedPictographic}, // 10.0 [8] (🤨..🤯) face with raised eyebrow..exploding head + {0x1F930, 0x1F930, prExtendedPictographic}, // 9.0 [1] (🤰) pregnant woman + {0x1F931, 0x1F932, prExtendedPictographic}, // 10.0 [2] (🤱..🤲) breast-feeding..palms up together + {0x1F933, 0x1F93A, prExtendedPictographic}, // 9.0 [8] (🤳..🤺) selfie..person fencing + {0x1F93C, 0x1F93E, prExtendedPictographic}, // 9.0 [3] (🤼..🤾) people wrestling..person playing handball + {0x1F93F, 0x1F93F, prExtendedPictographic}, // 12.0 [1] (🤿) diving mask + {0x1F940, 0x1F945, prExtendedPictographic}, // 9.0 [6] (🥀..🥅) wilted flower..goal net + {0x1F947, 0x1F94B, prExtendedPictographic}, // 9.0 [5] (🥇..🥋) 1st place medal..martial arts uniform + {0x1F94C, 0x1F94C, prExtendedPictographic}, // 10.0 [1] (🥌) curling stone + {0x1F94D, 0x1F94F, prExtendedPictographic}, // 11.0 [3] (🥍..🥏) lacrosse..flying disc + {0x1F950, 0x1F95E, prExtendedPictographic}, // 9.0 [15] (🥐..🥞) croissant..pancakes + {0x1F95F, 0x1F96B, prExtendedPictographic}, // 10.0 [13] (🥟..🥫) dumpling..canned food + {0x1F96C, 0x1F970, prExtendedPictographic}, // 11.0 [5] (🥬..🥰) leafy green..smiling face with hearts + {0x1F971, 0x1F971, prExtendedPictographic}, // 12.0 [1] (🥱) yawning face + {0x1F972, 0x1F972, prExtendedPictographic}, // NA [1] (🥲) + {0x1F973, 0x1F976, prExtendedPictographic}, // 11.0 [4] (🥳..🥶) partying face..cold face + {0x1F977, 0x1F979, prExtendedPictographic}, // NA [3] (🥷..🥹) .. + {0x1F97A, 0x1F97A, prExtendedPictographic}, // 11.0 [1] (🥺) pleading face + {0x1F97B, 0x1F97B, prExtendedPictographic}, // 12.0 [1] (🥻) sari + {0x1F97C, 0x1F97F, prExtendedPictographic}, // 11.0 [4] (🥼..🥿) lab coat..flat shoe + {0x1F980, 0x1F984, prExtendedPictographic}, // 8.0 [5] (🦀..🦄) crab..unicorn + {0x1F985, 0x1F991, prExtendedPictographic}, // 9.0 [13] (🦅..🦑) eagle..squid + {0x1F992, 0x1F997, prExtendedPictographic}, // 10.0 [6] (🦒..🦗) giraffe..cricket + {0x1F998, 0x1F9A2, prExtendedPictographic}, // 11.0 [11] (🦘..🦢) kangaroo..swan + {0x1F9A3, 0x1F9A4, prExtendedPictographic}, // NA [2] (🦣..🦤) .. + {0x1F9A5, 0x1F9AA, prExtendedPictographic}, // 12.0 [6] (🦥..🦪) sloth..oyster + {0x1F9AB, 0x1F9AD, prExtendedPictographic}, // NA [3] (🦫..🦭) .. + {0x1F9AE, 0x1F9AF, prExtendedPictographic}, // 12.0 [2] (🦮..🦯) guide dog..probing cane + {0x1F9B0, 0x1F9B9, prExtendedPictographic}, // 11.0 [10] (🦰..🦹) red hair..supervillain + {0x1F9BA, 0x1F9BF, prExtendedPictographic}, // 12.0 [6] (🦺..🦿) safety vest..mechanical leg + {0x1F9C0, 0x1F9C0, prExtendedPictographic}, // 8.0 [1] (🧀) cheese wedge + {0x1F9C1, 0x1F9C2, prExtendedPictographic}, // 11.0 [2] (🧁..🧂) cupcake..salt + {0x1F9C3, 0x1F9CA, prExtendedPictographic}, // 12.0 [8] (🧃..🧊) beverage box..ice cube + {0x1F9CB, 0x1F9CC, prExtendedPictographic}, // NA [2] (🧋..🧌) .. + {0x1F9CD, 0x1F9CF, prExtendedPictographic}, // 12.0 [3] (🧍..🧏) person standing..deaf person + {0x1F9D0, 0x1F9E6, prExtendedPictographic}, // 10.0 [23] (🧐..🧦) face with monocle..socks + {0x1F9E7, 0x1F9FF, prExtendedPictographic}, // 11.0 [25] (🧧..🧿) red envelope..nazar amulet + {0x1FA00, 0x1FA53, prExtendedPictographic}, // 12.0 [84] (🨀..🩓) NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP + {0x1FA54, 0x1FA5F, prExtendedPictographic}, // NA [12] (🩔..🩟) .. + {0x1FA60, 0x1FA6D, prExtendedPictographic}, // 11.0 [14] (🩠..🩭) XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER + {0x1FA6E, 0x1FA6F, prExtendedPictographic}, // NA [2] (🩮..🩯) .. + {0x1FA70, 0x1FA73, prExtendedPictographic}, // 12.0 [4] (🩰..🩳) ballet shoes..shorts + {0x1FA74, 0x1FA77, prExtendedPictographic}, // NA [4] (🩴..🩷) .. + {0x1FA78, 0x1FA7A, prExtendedPictographic}, // 12.0 [3] (🩸..🩺) drop of blood..stethoscope + {0x1FA7B, 0x1FA7F, prExtendedPictographic}, // NA [5] (🩻..🩿) .. + {0x1FA80, 0x1FA82, prExtendedPictographic}, // 12.0 [3] (🪀..🪂) yo-yo..parachute + {0x1FA83, 0x1FA8F, prExtendedPictographic}, // NA [13] (🪃..🪏) .. + {0x1FA90, 0x1FA95, prExtendedPictographic}, // 12.0 [6] (🪐..🪕) ringed planet..banjo + {0x1FA96, 0x1FFFD, prExtendedPictographic}, // NA[1384] (🪖..🿽) .. + {0xE0000, 0xE0000, prControl}, // Cn + {0xE0001, 0xE0001, prControl}, // Cf LANGUAGE TAG + {0xE0002, 0xE001F, prControl}, // Cn [30] .. + {0xE0020, 0xE007F, prExtend}, // Cf [96] TAG SPACE..CANCEL TAG + {0xE0080, 0xE00FF, prControl}, // Cn [128] .. + {0xE0100, 0xE01EF, prExtend}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + {0xE01F0, 0xE0FFF, prControl}, // Cn [3600] .. +} + +// property returns the Unicode property value (see constants above) of the +// given code point. +func property(r rune) int { + // Run a binary search. + from := 0 + to := len(codePoints) + for to > from { + middle := (from + to) / 2 + cpRange := codePoints[middle] + if int(r) < cpRange[0] { + to = middle + continue + } + if int(r) > cpRange[1] { + from = middle + 1 + continue + } + return cpRange[2] + } + return prAny +} diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index 7eacc5bd..388c4e5e 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -284,6 +284,33 @@ func main() { } ``` +### Using pflag with go test +`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`). +For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details. + +For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this: +```bash +go test /your/tests -run ^YourTest -v --your-test-pflags +``` +will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags. +To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package. + +**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()` +```go +import ( + goflag "flag" + flag "github.com/spf13/pflag" +) + +var ip *int = flag.Int("flagname", 1234, "help message for flagname") + +func main() { + flag.CommandLine.AddGoFlagSet(goflag.CommandLine) + flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine) + flag.Parse() +} +``` + ## More info You can see the full reference documentation of the pflag package diff --git a/vendor/github.com/spf13/pflag/bool_func.go b/vendor/github.com/spf13/pflag/bool_func.go new file mode 100644 index 00000000..83d77afa --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_func.go @@ -0,0 +1,40 @@ +package pflag + +// -- func Value +type boolfuncValue func(string) error + +func (f boolfuncValue) Set(s string) error { return f(s) } + +func (f boolfuncValue) Type() string { return "boolfunc" } + +func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package + +func (f boolfuncValue) IsBoolFlag() bool { return true } + +// BoolFunc defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed +// on the command line. +func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) { + f.BoolFuncP(name, "", usage, fn) +} + +// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) { + var val Value = boolfuncValue(fn) + flag := f.VarPF(val, name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// BoolFunc defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed +// on the command line. +func BoolFunc(name string, usage string, fn func(string) error) { + CommandLine.BoolFuncP(name, "", usage, fn) +} + +// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash. +func BoolFuncP(name, shorthand string, usage string, fn func(string) error) { + CommandLine.BoolFuncP(name, shorthand, usage, fn) +} diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go index a0b2679f..d49c0143 100644 --- a/vendor/github.com/spf13/pflag/count.go +++ b/vendor/github.com/spf13/pflag/count.go @@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int { // Count defines a count flag with specified name, default value, and usage string. // The return value is the address of an int variable that stores the value of the flag. -// A count flag will add 1 to its value evey time it is found on the command line +// A count flag will add 1 to its value every time it is found on the command line func Count(name string, usage string) *int { return CommandLine.CountP(name, "", usage) } diff --git a/vendor/github.com/spf13/pflag/errors.go b/vendor/github.com/spf13/pflag/errors.go new file mode 100644 index 00000000..ff11b66b --- /dev/null +++ b/vendor/github.com/spf13/pflag/errors.go @@ -0,0 +1,149 @@ +package pflag + +import "fmt" + +// notExistErrorMessageType specifies which flavor of "flag does not exist" +// is printed by NotExistError. This allows the related errors to be grouped +// under a single NotExistError struct without making a breaking change to +// the error message text. +type notExistErrorMessageType int + +const ( + flagNotExistMessage notExistErrorMessageType = iota + flagNotDefinedMessage + flagNoSuchFlagMessage + flagUnknownFlagMessage + flagUnknownShorthandFlagMessage +) + +// NotExistError is the error returned when trying to access a flag that +// does not exist in the FlagSet. +type NotExistError struct { + name string + specifiedShorthands string + messageType notExistErrorMessageType +} + +// Error implements error. +func (e *NotExistError) Error() string { + switch e.messageType { + case flagNotExistMessage: + return fmt.Sprintf("flag %q does not exist", e.name) + + case flagNotDefinedMessage: + return fmt.Sprintf("flag accessed but not defined: %s", e.name) + + case flagNoSuchFlagMessage: + return fmt.Sprintf("no such flag -%v", e.name) + + case flagUnknownFlagMessage: + return fmt.Sprintf("unknown flag: --%s", e.name) + + case flagUnknownShorthandFlagMessage: + c := rune(e.name[0]) + return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands) + } + + panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType)) +} + +// GetSpecifiedName returns the name of the flag (without dashes) as it +// appeared in the parsed arguments. +func (e *NotExistError) GetSpecifiedName() string { + return e.name +} + +// GetSpecifiedShortnames returns the group of shorthand arguments +// (without dashes) that the flag appeared within. If the flag was not in a +// shorthand group, this will return an empty string. +func (e *NotExistError) GetSpecifiedShortnames() string { + return e.specifiedShorthands +} + +// ValueRequiredError is the error returned when a flag needs an argument but +// no argument was provided. +type ValueRequiredError struct { + flag *Flag + specifiedName string + specifiedShorthands string +} + +// Error implements error. +func (e *ValueRequiredError) Error() string { + if len(e.specifiedShorthands) > 0 { + c := rune(e.specifiedName[0]) + return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands) + } + + return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName) +} + +// GetFlag returns the flag for which the error occurred. +func (e *ValueRequiredError) GetFlag() *Flag { + return e.flag +} + +// GetSpecifiedName returns the name of the flag (without dashes) as it +// appeared in the parsed arguments. +func (e *ValueRequiredError) GetSpecifiedName() string { + return e.specifiedName +} + +// GetSpecifiedShortnames returns the group of shorthand arguments +// (without dashes) that the flag appeared within. If the flag was not in a +// shorthand group, this will return an empty string. +func (e *ValueRequiredError) GetSpecifiedShortnames() string { + return e.specifiedShorthands +} + +// InvalidValueError is the error returned when an invalid value is used +// for a flag. +type InvalidValueError struct { + flag *Flag + value string + cause error +} + +// Error implements error. +func (e *InvalidValueError) Error() string { + flag := e.flag + var flagName string + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) + } else { + flagName = fmt.Sprintf("--%s", flag.Name) + } + return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause) +} + +// Unwrap implements errors.Unwrap. +func (e *InvalidValueError) Unwrap() error { + return e.cause +} + +// GetFlag returns the flag for which the error occurred. +func (e *InvalidValueError) GetFlag() *Flag { + return e.flag +} + +// GetValue returns the invalid value that was provided. +func (e *InvalidValueError) GetValue() string { + return e.value +} + +// InvalidSyntaxError is the error returned when a bad flag name is passed on +// the command line. +type InvalidSyntaxError struct { + specifiedFlag string +} + +// Error implements error. +func (e *InvalidSyntaxError) Error() string { + return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag) +} + +// GetSpecifiedName returns the exact flag (with dashes) as it +// appeared in the parsed arguments. +func (e *InvalidSyntaxError) GetSpecifiedFlag() string { + return e.specifiedFlag +} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 7c058de3..d4dfbc5e 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -27,23 +27,32 @@ unaffected. Define flags using flag.String(), Bool(), Int(), etc. This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + var ip = flag.Int("flagname", 1234, "help message for flagname") + If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") } + Or you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") + For such flags, the default value is just the initial value of the variable. After all flags are defined, call + flag.Parse() + to parse the command line into the defined flags. Flags may then be used directly. If you're using the flags themselves, they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar) @@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1. The pflag package also defines some new functions that are not in flag, that give one-letter shorthands for flags. You can use these by appending 'P' to the name of any function that defines a flag. + var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") } flag.VarP(&flagval, "varname", "v", "help message") + Shorthand letters can be used with single dashes on the command line. Boolean shorthand flags can be combined with other shorthand flags. Command line flag syntax: + --flag // boolean flags only --flag=x Unlike the flag package, a single dash before an option means something different than a double dash. Single dashes signify a series of shorthand letters for flags. All but the last shorthand letter must be boolean flags. + // boolean flags -f -abc @@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag { func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { flag := f.Lookup(name) if flag == nil { - err := fmt.Errorf("flag accessed but not defined: %s", name) + err := &NotExistError{name: name, messageType: flagNotDefinedMessage} return nil, err } @@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int { func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) @@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) @@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro func (f *FlagSet) MarkHidden(name string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } flag.Hidden = true return nil @@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error { normalName := f.normalizeFlagName(name) flag, ok := f.formal[normalName] if !ok { - return fmt.Errorf("no such flag -%v", name) + return &NotExistError{name: name, messageType: flagNoSuchFlagMessage} } err := flag.Value.Set(value) if err != nil { - var flagName string - if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { - flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) - } else { - flagName = fmt.Sprintf("--%s", flag.Name) + return &InvalidValueError{ + flag: flag, + value: value, + cause: err, } - return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) } if !flag.Changed { @@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error { normalName := f.normalizeFlagName(name) flag, ok := f.formal[normalName] if !ok { - return fmt.Errorf("no such flag -%v", name) + return &NotExistError{name: name, messageType: flagNoSuchFlagMessage} } if flag.Annotations == nil { flag.Annotations = map[string][]string{} @@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() { func (f *Flag) defaultIsZeroValue() bool { switch f.Value.(type) { case boolFlag: - return f.DefValue == "false" + return f.DefValue == "false" || f.DefValue == "" case *durationValue: // Beginning in Go 1.7, duration zero values are "0s" return f.DefValue == "0" || f.DefValue == "0s" @@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool { case *intSliceValue, *stringSliceValue, *stringArrayValue: return f.DefValue == "[]" default: - switch f.Value.String() { + switch f.DefValue { case "false": return true case "": @@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { name = flag.Value.Type() switch name { - case "bool": + case "bool", "boolfunc": name = "" + case "func": + name = "value" case "float64": name = "float" case "int64": @@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { switch flag.Value.Type() { case "string": line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) - case "bool": + case "bool", "boolfunc": if flag.NoOptDefVal != "true" { line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) } @@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) { CommandLine.VarP(value, name, shorthand, usage) } -// failf prints to standard error a formatted error and usage message and +// fail prints an error message and usage message to standard error and // returns the error. -func (f *FlagSet) failf(format string, a ...interface{}) error { - err := fmt.Errorf(format, a...) +func (f *FlagSet) fail(err error) error { if f.errorHandling != ContinueOnError { fmt.Fprintln(f.Output(), err) f.usage() @@ -934,9 +946,9 @@ func (f *FlagSet) usage() { } } -//--unknown (args will be empty) -//--unknown --next-flag ... (args will be --next-flag ...) -//--unknown arg ... (args will be arg ...) +// --unknown (args will be empty) +// --unknown --next-flag ... (args will be --next-flag ...) +// --unknown arg ... (args will be arg ...) func stripUnknownFlagValue(args []string) []string { if len(args) == 0 { //--unknown @@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin a = args name := s[2:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { - err = f.failf("bad flag syntax: %s", s) + err = f.fail(&InvalidSyntaxError{specifiedFlag: s}) return } @@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin return stripUnknownFlagValue(a), nil default: - err = f.failf("unknown flag: --%s", name) + err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage}) return } } @@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin a = a[1:] } else { // '--flag' (arg was required) - err = f.failf("flag needs an argument: %s", s) + err = f.fail(&ValueRequiredError{ + flag: flag, + specifiedName: name, + }) return } err = fn(flag, value) if err != nil { - f.failf(err.Error()) + f.fail(err) } return } @@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { outArgs = args - if strings.HasPrefix(shorthands, "test.") { + if isGotestShorthandFlag(shorthands) { return } @@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse outArgs = stripUnknownFlagValue(outArgs) return default: - err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) + err = f.fail(&NotExistError{ + name: string(c), + specifiedShorthands: shorthands, + messageType: flagUnknownShorthandFlagMessage, + }) return } } @@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse outArgs = args[1:] } else { // '-f' (arg was required) - err = f.failf("flag needs an argument: %q in -%s", c, shorthands) + err = f.fail(&ValueRequiredError{ + flag: flag, + specifiedName: string(c), + specifiedShorthands: shorthands, + }) return } @@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse err = fn(flag, value) if err != nil { - f.failf(err.Error()) + f.fail(err) } return } @@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error { } f.parsed = true - if len(arguments) < 0 { + if len(arguments) == 0 { return nil } diff --git a/vendor/github.com/spf13/pflag/func.go b/vendor/github.com/spf13/pflag/func.go new file mode 100644 index 00000000..9f4d88f2 --- /dev/null +++ b/vendor/github.com/spf13/pflag/func.go @@ -0,0 +1,37 @@ +package pflag + +// -- func Value +type funcValue func(string) error + +func (f funcValue) Set(s string) error { return f(s) } + +func (f funcValue) Type() string { return "func" } + +func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package + +// Func defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}={value}" (or equivalent) is +// parsed on the command line, with "{value}" as an argument. +func (f *FlagSet) Func(name string, usage string, fn func(string) error) { + f.FuncP(name, "", usage, fn) +} + +// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) { + var val Value = funcValue(fn) + f.VarP(val, name, shorthand, usage) +} + +// Func defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}={value}" (or equivalent) is +// parsed on the command line, with "{value}" as an argument. +func Func(name string, usage string, fn func(string) error) { + CommandLine.FuncP(name, "", usage, fn) +} + +// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash. +func FuncP(name, shorthand string, usage string, fn func(string) error) { + CommandLine.FuncP(name, shorthand, usage, fn) +} diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go index d3dd72b7..f563907e 100644 --- a/vendor/github.com/spf13/pflag/golangflag.go +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -10,6 +10,15 @@ import ( "strings" ) +// go test flags prefixes +func isGotestFlag(flag string) bool { + return strings.HasPrefix(flag, "-test.") +} + +func isGotestShorthandFlag(flag string) bool { + return strings.HasPrefix(flag, "test.") +} + // flagValueWrapper implements pflag.Value around a flag.Value. The main // difference here is the addition of the Type method that returns a string // name of the type. As this is generally unknown, we approximate that with @@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { } f.addedGoFlagSets = append(f.addedGoFlagSets, newSet) } + +// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(), +// since by default those are skipped by pflag.Parse(). +// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)` +func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error { + var skippedFlags []string + for _, f := range osArgs { + if isGotestFlag(f) { + skippedFlags = append(skippedFlags, f) + } + } + return goFlagSet.Parse(skippedFlags) +} diff --git a/vendor/github.com/spf13/pflag/ipnet_slice.go b/vendor/github.com/spf13/pflag/ipnet_slice.go index 6b541aa8..c6e89da1 100644 --- a/vendor/github.com/spf13/pflag/ipnet_slice.go +++ b/vendor/github.com/spf13/pflag/ipnet_slice.go @@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string { func ipNetSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") - // Emtpy string would cause a slice with one (empty) entry + // Empty string would cause a slice with one (empty) entry if len(val) == 0 { return []net.IPNet{}, nil } diff --git a/vendor/github.com/spf13/pflag/text.go b/vendor/github.com/spf13/pflag/text.go new file mode 100644 index 00000000..886d5a3d --- /dev/null +++ b/vendor/github.com/spf13/pflag/text.go @@ -0,0 +1,81 @@ +package pflag + +import ( + "encoding" + "fmt" + "reflect" +) + +// following is copied from go 1.23.4 flag.go +type textValue struct{ p encoding.TextUnmarshaler } + +func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue { + ptrVal := reflect.ValueOf(p) + if ptrVal.Kind() != reflect.Ptr { + panic("variable value type must be a pointer") + } + defVal := reflect.ValueOf(val) + if defVal.Kind() == reflect.Ptr { + defVal = defVal.Elem() + } + if defVal.Type() != ptrVal.Type().Elem() { + panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem())) + } + ptrVal.Elem().Set(defVal) + return textValue{p} +} + +func (v textValue) Set(s string) error { + return v.p.UnmarshalText([]byte(s)) +} + +func (v textValue) Get() interface{} { + return v.p +} + +func (v textValue) String() string { + if m, ok := v.p.(encoding.TextMarshaler); ok { + if b, err := m.MarshalText(); err == nil { + return string(b) + } + } + return "" +} + +//end of copy + +func (v textValue) Type() string { + return reflect.ValueOf(v.p).Type().Name() +} + +// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name +func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag accessed but not defined: %s", name) + } + if flag.Value.Type() != reflect.TypeOf(out).Name() { + return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type()) + } + return out.UnmarshalText([]byte(flag.Value.String())) +} + +// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p. +func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) { + f.VarP(newTextValue(value, p), name, "", usage) +} + +// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) { + f.VarP(newTextValue(value, p), name, shorthand, usage) +} + +// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p. +func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) { + CommandLine.VarP(newTextValue(value, p), name, "", usage) +} + +// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash. +func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) { + CommandLine.VarP(newTextValue(value, p), name, shorthand, usage) +} diff --git a/vendor/github.com/spf13/pflag/time.go b/vendor/github.com/spf13/pflag/time.go new file mode 100644 index 00000000..dc024807 --- /dev/null +++ b/vendor/github.com/spf13/pflag/time.go @@ -0,0 +1,118 @@ +package pflag + +import ( + "fmt" + "strings" + "time" +) + +// TimeValue adapts time.Time for use as a flag. +type timeValue struct { + *time.Time + formats []string +} + +func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue { + *p = val + return &timeValue{ + Time: p, + formats: formats, + } +} + +// Set time.Time value from string based on accepted formats. +func (d *timeValue) Set(s string) error { + s = strings.TrimSpace(s) + for _, f := range d.formats { + v, err := time.Parse(f, s) + if err != nil { + continue + } + *d.Time = v + return nil + } + + formatsString := "" + for i, f := range d.formats { + if i > 0 { + formatsString += ", " + } + formatsString += fmt.Sprintf("`%s`", f) + } + + return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString) +} + +// Type name for time.Time flags. +func (d *timeValue) Type() string { + return "time" +} + +func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) } + +// GetTime return the time value of a flag with the given name +func (f *FlagSet) GetTime(name string) (time.Time, error) { + flag := f.Lookup(name) + if flag == nil { + err := fmt.Errorf("flag accessed but not defined: %s", name) + return time.Time{}, err + } + + if flag.Value.Type() != "time" { + err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type()) + return time.Time{}, err + } + + val, ok := flag.Value.(*timeValue) + if !ok { + return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value) + } + + return *val.Time, nil +} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) { + f.TimeVarP(p, name, "", value, formats, usage) +} + +// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) { + f.VarP(newTimeValue(value, p, formats), name, shorthand, usage) +} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) { + CommandLine.TimeVarP(p, name, "", value, formats, usage) +} + +// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash. +func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) { + CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage) +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time { + return f.TimeP(name, "", value, formats, usage) +} + +// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time { + p := new(time.Time) + f.TimeVarP(p, name, shorthand, value, formats, usage) + return p +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func Time(name string, value time.Time, formats []string, usage string) *time.Time { + return CommandLine.TimeP(name, "", value, formats, usage) +} + +// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash. +func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time { + return CommandLine.TimeP(name, shorthand, value, formats, usage) +} diff --git a/vendor/github.com/tetratelabs/wazero/.editorconfig b/vendor/github.com/tetratelabs/wazero/.editorconfig new file mode 100644 index 00000000..f999431d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/vendor/github.com/tetratelabs/wazero/.gitattributes b/vendor/github.com/tetratelabs/wazero/.gitattributes new file mode 100644 index 00000000..3a08bc38 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/.gitattributes @@ -0,0 +1,2 @@ +# Improves experience of commands like `make format` on Windows +* text=auto eol=lf diff --git a/vendor/github.com/tetratelabs/wazero/.gitignore b/vendor/github.com/tetratelabs/wazero/.gitignore new file mode 100644 index 00000000..e9dd94b3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/.gitignore @@ -0,0 +1,46 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +/wazero +build +dist + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +# Goland +.idea + +# AssemblyScript +node_modules +package-lock.json + +# codecov.io +/coverage.txt + +.vagrant + +zig-cache/ +.zig-cache/ +zig-out/ + +.DS_Store + +# Ignore compiled stdlib test cases. +/internal/integration_test/stdlibs/testdata +/internal/integration_test/libsodium/testdata diff --git a/vendor/github.com/tetratelabs/wazero/.gitmodules b/vendor/github.com/tetratelabs/wazero/.gitmodules new file mode 100644 index 00000000..410c91f4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/.gitmodules @@ -0,0 +1,3 @@ +[submodule "site/themes/hello-friend"] + path = site/themes/hello-friend + url = https://github.com/panr/hugo-theme-hello-friend.git diff --git a/vendor/github.com/tetratelabs/wazero/CONTRIBUTING.md b/vendor/github.com/tetratelabs/wazero/CONTRIBUTING.md new file mode 100644 index 00000000..8ab866f0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contributing + +We welcome contributions from the community. Please read the following guidelines carefully to maximize the chances of your PR being merged. + +## Coding Style + +- To ensure your change passes format checks, run `make check`. To format your files, you can run `make format`. +- We follow standard Go table-driven tests and use an internal [testing library](./internal/testing/require) to assert correctness. To verify all tests pass, you can run `make test`. + +## DCO + +We require DCO signoff line in every commit to this repo. + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](https://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. +Developer's Certificate of Origin 1.1 +By making a contribution to this project, I certify that: +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. + +## Code Reviews + +* The pull request title should describe what the change does and not embed issue numbers. +The pull request should only be blank when the change is minor. Any feature should include +a description of the change and what motivated it. If the change or design changes through +review, please keep the title and description updated accordingly. +* A single approval is sufficient to merge. If a reviewer asks for +changes in a PR they should be addressed before the PR is merged, +even if another reviewer has already approved the PR. +* During the review, address the comments and commit the changes +_without_ squashing the commits. This facilitates incremental reviews +since the reviewer does not go through all the code again to find out +what has changed since the last review. When a change goes out of sync with main, +please rebase and force push, keeping the original commits where practical. +* Commits are squashed prior to merging a pull request, using the title +as commit message by default. Maintainers may request contributors to +edit the pull request tite to ensure that it remains descriptive as a +commit message. Alternatively, maintainers may change the commit message directly. diff --git a/vendor/github.com/tetratelabs/wazero/LICENSE b/vendor/github.com/tetratelabs/wazero/LICENSE new file mode 100644 index 00000000..e21d6995 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020-2023 wazero authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/tetratelabs/wazero/Makefile b/vendor/github.com/tetratelabs/wazero/Makefile new file mode 100644 index 00000000..b33fdd4e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/Makefile @@ -0,0 +1,364 @@ + +gofumpt := mvdan.cc/gofumpt@v0.6.0 +gosimports := github.com/rinchsan/gosimports/cmd/gosimports@v0.3.8 +golangci_lint := github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 +asmfmt := github.com/klauspost/asmfmt/cmd/asmfmt@v1.3.2 +# sync this with netlify.toml! +hugo := github.com/gohugoio/hugo@v0.115.2 + +# Make 3.81 doesn't support '**' globbing: Set explicitly instead of recursion. +all_sources := $(wildcard *.go */*.go */*/*.go */*/*/*.go */*/*/*.go */*/*/*/*.go) +all_testdata := $(wildcard testdata/* */testdata/* */*/testdata/* */*/testdata/*/* */*/*/testdata/*) +all_testing := $(wildcard internal/testing/* internal/testing/*/* internal/testing/*/*/*) +all_examples := $(wildcard examples/* examples/*/* examples/*/*/* */*/example/* */*/example/*/* */*/example/*/*/*) +all_it := $(wildcard internal/integration_test/* internal/integration_test/*/* internal/integration_test/*/*/*) +# main_sources exclude any test or example related code +main_sources := $(wildcard $(filter-out %_test.go $(all_testdata) $(all_testing) $(all_examples) $(all_it), $(all_sources))) +# main_packages collect the unique main source directories (sort will dedupe). +# Paths need to all start with ./, so we do that manually vs foreach which strips it. +main_packages := $(sort $(foreach f,$(dir $(main_sources)),$(if $(findstring ./,$(f)),./,./$(f)))) + +go_test_options ?= -timeout 300s + +.PHONY: test.examples +test.examples: + @go test $(go_test_options) ./examples/... ./imports/assemblyscript/example/... ./imports/emscripten/... ./imports/wasi_snapshot_preview1/example/... + +.PHONY: build.examples.as +build.examples.as: + @cd ./imports/assemblyscript/example/testdata && npm install && npm run build + +%.wasm: %.zig + @(cd $(@D); zig build -Doptimize=ReleaseSmall) + @mv $(@D)/zig-out/*/$(@F) $(@D) + +.PHONY: build.examples.zig +build.examples.zig: examples/allocation/zig/testdata/greet.wasm imports/wasi_snapshot_preview1/example/testdata/zig/cat.wasm imports/wasi_snapshot_preview1/testdata/zig/wasi.wasm + @cd internal/testing/dwarftestdata/testdata/zig; zig build; mv zig-out/*/main.wasm ./ # Need DWARF custom sections. + +tinygo_reactor_sources_reactor := examples/basic/testdata/add.go examples/allocation/tinygo/testdata/greet.go +.PHONY: build.examples.tinygo_reactor +build.examples.tinygo_reactor: $(tinygo_sources_reactor) + @for f in $^; do \ + tinygo build -o $$(echo $$f | sed -e 's/\.go/\.wasm/') -scheduler=none --no-debug --target=wasip1 -buildmode=c-shared $$f; \ + done + +tinygo_sources_clis := examples/cli/testdata/cli.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go imports/wasi_snapshot_preview1/testdata/tinygo/wasi.go cmd/wazero/testdata/cat/cat.go +.PHONY: build.examples.tinygo_clis +build.examples.tinygo_clis: $(tinygo_sources_clis) + @for f in $^; do \ + tinygo build -o $$(echo $$f | sed -e 's/\.go/\.wasm/') -scheduler=none --no-debug --target=wasip1 $$f; \ + done + @mv cmd/wazero/testdata/cat/cat.wasm cmd/wazero/testdata/cat/cat-tinygo.wasm + +.PHONY: build.examples.tinygo +build.examples.tinygo: build.examples.tinygo_reactor build.examples.tinygo_clis + +# We use zig to build C as it is easy to install and embeds a copy of zig-cc. +# Note: Don't use "-Oz" as that breaks our wasi sock example. +c_sources := imports/wasi_snapshot_preview1/example/testdata/zig-cc/cat.c imports/wasi_snapshot_preview1/testdata/zig-cc/wasi.c internal/testing/dwarftestdata/testdata/zig-cc/main.c +.PHONY: build.examples.zig-cc +build.examples.zig-cc: $(c_sources) + @for f in $^; do \ + zig cc --target=wasm32-wasi -o $$(echo $$f | sed -e 's/\.c/\.wasm/') $$f; \ + done + +# Here are the emcc args we use: +# +# * `-Oz` - most optimization for code size. +# * `--profiling` - adds the name section. +# * `-s STANDALONE_WASM` - ensures wasm is built for a non-js runtime. +# * `-s EXPORTED_FUNCTIONS=_malloc,_free` - export allocation functions so that +# they can be used externally as "malloc" and "free". +# * `-s WARN_ON_UNDEFINED_SYMBOLS=0` - imports not defined in JavaScript error +# otherwise. See https://github.com/emscripten-core/emscripten/issues/13641 +# * `-s TOTAL_STACK=8KB -s TOTAL_MEMORY=64KB` - reduce memory default from 16MB +# to one page (64KB). To do this, we have to reduce the stack size. +# * `-s ALLOW_MEMORY_GROWTH` - allows "memory.grow" instructions to succeed, but +# requires a function import "emscripten_notify_memory_growth". +emscripten_sources := $(wildcard imports/emscripten/testdata/*.cc) +.PHONY: build.examples.emscripten +build.examples.emscripten: $(emscripten_sources) + @for f in $^; do \ + em++ -Oz --profiling \ + -s STANDALONE_WASM \ + -s EXPORTED_FUNCTIONS=_malloc,_free \ + -s WARN_ON_UNDEFINED_SYMBOLS=0 \ + -s TOTAL_STACK=8KB -s TOTAL_MEMORY=64KB \ + -s ALLOW_MEMORY_GROWTH \ + --std=c++17 -o $$(echo $$f | sed -e 's/\.cc/\.wasm/') $$f; \ + done + +%/greet.wasm : cargo_target := wasm32-unknown-unknown +%/cat.wasm : cargo_target := wasm32-wasip1 +%/wasi.wasm : cargo_target := wasm32-wasip1 + +.PHONY: build.examples.rust +build.examples.rust: examples/allocation/rust/testdata/greet.wasm imports/wasi_snapshot_preview1/example/testdata/cargo-wasi/cat.wasm imports/wasi_snapshot_preview1/testdata/cargo-wasi/wasi.wasm internal/testing/dwarftestdata/testdata/rust/main.wasm.xz + +# Normally, we build release because it is smaller. Testing dwarf requires the debug build. +internal/testing/dwarftestdata/testdata/rust/main.wasm.xz: + cd $(@D) && cargo build --target wasm32-wasip1 + mv $(@D)/target/wasm32-wasip1/debug/main.wasm $(@D) + cd $(@D) && xz -k -f ./main.wasm # Rust's DWARF section is huge, so compress it. + +# Builds rust using cargo normally +%.wasm: %.rs + @(cd $(@D); cargo build --target $(cargo_target) --release) + @mv $(@D)/target/$(cargo_target)/release/$(@F) $(@D) + +spectest_base_dir := internal/integration_test/spectest +spectest_v1_dir := $(spectest_base_dir)/v1 +spectest_v1_testdata_dir := $(spectest_v1_dir)/testdata +spec_version_v1 := wg-1.0 +spectest_v2_dir := $(spectest_base_dir)/v2 +spectest_v2_testdata_dir := $(spectest_v2_dir)/testdata +# Latest draft state as of March 12, 2024. +spec_version_v2 := 1c5e5d178bd75c79b7a12881c529098beaee2a05 +spectest_threads_dir := $(spectest_base_dir)/threads +spectest_threads_testdata_dir := $(spectest_threads_dir)/testdata +# From https://github.com/WebAssembly/threads/tree/upstream-rebuild which has not been merged to main yet. +# It will likely be renamed to main in the future - https://github.com/WebAssembly/threads/issues/216. +spec_version_threads := 3635ca51a17e57e106988846c5b0e0cc48ac04fc + +.PHONY: build.spectest +build.spectest: + @$(MAKE) build.spectest.v1 + @$(MAKE) build.spectest.v2 + +.PHONY: build.spectest.v1 +build.spectest.v1: # Note: wabt by default uses >1.0 features, so wast2json flags might drift as they include more. See WebAssembly/wabt#1878 + @rm -rf $(spectest_v1_testdata_dir) + @mkdir -p $(spectest_v1_testdata_dir) + @cd $(spectest_v1_testdata_dir) \ + && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core?ref=$(spec_version_v1)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O + @cd $(spectest_v1_testdata_dir) && for f in `find . -name '*.wast'`; do \ + perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"f32.demote_f64"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f32.const nan:canonical\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"f32.demote_f64"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f32.const nan:arithmetic\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"f64\.promote_f32"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f64.const nan:canonical\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"f64\.promote_f32"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f64.const nan:arithmetic\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\s\([a-z0-9.\s+-:]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\s\([a-z0-9.\s+-:]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ + perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ + wast2json \ + --disable-saturating-float-to-int \ + --disable-sign-extension \ + --disable-simd \ + --disable-multi-value \ + --disable-bulk-memory \ + --disable-reference-types \ + --debug-names $$f; \ + done + +.PHONY: build.spectest.v2 +build.spectest.v2: # Note: SIMD cases are placed in the "simd" subdirectory. + @mkdir -p $(spectest_v2_testdata_dir) + @cd $(spectest_v2_testdata_dir) \ + && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core?ref=$(spec_version_v2)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O + @cd $(spectest_v2_testdata_dir) \ + && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core/simd?ref=$(spec_version_v2)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O + @cd $(spectest_v2_testdata_dir) && for f in `find . -name '*.wast'`; do \ + wast2json --debug-names --no-check $$f || true; \ + done # Ignore the error here as some tests (e.g. comments.wast right now) are not supported by wast2json yet. + +# Note: We currently cannot build the "threads" subdirectory that spawns threads due to missing support in wast2json. +# https://github.com/WebAssembly/wabt/issues/2348#issuecomment-1878003959 +.PHONY: build.spectest.threads +build.spectest.threads: + @mkdir -p $(spectest_threads_testdata_dir) + @cd $(spectest_threads_testdata_dir) \ + && curl -sSL 'https://api.github.com/repos/WebAssembly/threads/contents/test/core?ref=$(spec_version_threads)' | jq -r '.[]| .download_url' | grep -E "atomic.wast" | xargs -Iurl curl -sJL url -O + @cd $(spectest_threads_testdata_dir) && for f in `find . -name '*.wast'`; do \ + wast2json --enable-threads --debug-names $$f; \ + done + +.PHONY: test +test: + @go test $(go_test_options) ./... + @cd internal/version/testdata && go test $(go_test_options) ./... + @cd internal/integration_test/fuzz/wazerolib && CGO_ENABLED=0 WASM_BINARY_PATH=testdata/test.wasm go test ./... + +.PHONY: coverage +# replace spaces with commas +coverpkg = $(shell echo $(main_packages) | tr ' ' ',') +coverage: ## Generate test coverage + @go test -coverprofile=coverage.txt -covermode=atomic --coverpkg=$(coverpkg) $(main_packages) + @go tool cover -func coverage.txt + +golangci_lint_path := $(shell go env GOPATH)/bin/golangci-lint + +$(golangci_lint_path): + @go install $(golangci_lint) + +golangci_lint_goarch ?= $(shell go env GOARCH) + +.PHONY: lint +lint: $(golangci_lint_path) + @GOARCH=$(golangci_lint_goarch) CGO_ENABLED=0 $(golangci_lint_path) run --timeout 5m -E testableexamples + +.PHONY: format +format: + @go run $(gofumpt) -l -w . + @go run $(gosimports) -local github.com/tetratelabs/ -w $(shell find . -name '*.go' -type f) + @go run $(asmfmt) -w $(shell find . -name '*.s' -type f) + +.PHONY: check # Pre-flight check for pull requests +check: +# The following checks help ensure our platform-specific code used for system +# calls safely falls back on a platform unsupported by the compiler engine. +# This makes sure the intepreter can be used. Most often the package that can +# drift here is "platform" or "sysfs": +# +# Ensure we build on plan9. See #1578 + @GOARCH=amd64 GOOS=plan9 go build ./... +# Ensure we build on gojs. See #1526. + @GOARCH=wasm GOOS=js go build ./... +# Ensure we build on wasip1. See #1526. + @GOARCH=wasm GOOS=wasip1 go build ./... +# Ensure we build on aix. See #1723 + @GOARCH=ppc64 GOOS=aix go build ./... +# Ensure we build on windows: + @GOARCH=amd64 GOOS=windows go build ./... +# Ensure we build on an arbitrary operating system: + @GOARCH=amd64 GOOS=dragonfly go build ./... +# Ensure we build on solaris/illumos: + @GOARCH=amd64 GOOS=illumos go build ./... + @GOARCH=amd64 GOOS=solaris go build ./... +# Ensure we build on linux arm for Dapr: +# gh release view -R dapr/dapr --json assets --jq 'first(.assets[] | select(.name = "daprd_linux_arm.tar.gz") | {url, downloadCount})' + @GOARCH=arm GOOS=linux go build ./... +# Ensure we build on linux 386 for Trivy: +# gh release view -R aquasecurity/trivy --json assets --jq 'first(.assets[] | select(.name| test("Linux-32bit.*tar.gz")) | {url, downloadCount})' + @GOARCH=386 GOOS=linux go build ./... +# Ensure we build on FreeBSD amd64 for Trivy: +# gh release view -R aquasecurity/trivy --json assets --jq 'first(.assets[] | select(.name| test("FreeBSD-64bit.*tar.gz")) | {url, downloadCount})' + @GOARCH=amd64 GOOS=freebsd go build ./... + @$(MAKE) lint golangci_lint_goarch=arm64 + @$(MAKE) lint golangci_lint_goarch=amd64 + @$(MAKE) format + @go mod tidy + @if [ ! -z "`git status -s`" ]; then \ + echo "The following differences will fail CI until committed:"; \ + git diff --exit-code; \ + fi + +.PHONY: site +site: ## Serve website content + @git submodule update --init + @cd site && go run $(hugo) server --minify --disableFastRender --baseURL localhost:1313 --cleanDestinationDir -D + +.PHONY: clean +clean: ## Ensure a clean build + @rm -rf dist build coverage.txt + @go clean -testcache + +fuzz_default_flags := --no-trace-compares --sanitizer=none -- -rss_limit_mb=8192 + +fuzz_timeout_seconds ?= 10 +.PHONY: fuzz +fuzz: + @cd internal/integration_test/fuzz && cargo test + @cd internal/integration_test/fuzz && cargo fuzz run logging_no_diff $(fuzz_default_flags) -max_total_time=$(fuzz_timeout_seconds) + @cd internal/integration_test/fuzz && cargo fuzz run no_diff $(fuzz_default_flags) -max_total_time=$(fuzz_timeout_seconds) + @cd internal/integration_test/fuzz && cargo fuzz run memory_no_diff $(fuzz_default_flags) -max_total_time=$(fuzz_timeout_seconds) + @cd internal/integration_test/fuzz && cargo fuzz run validation $(fuzz_default_flags) -max_total_time=$(fuzz_timeout_seconds) + +libsodium: + cd ./internal/integration_test/libsodium/testdata && \ + curl -s "https://api.github.com/repos/jedisct1/webassembly-benchmarks/contents/2022-12/wasm?ref=7e86d68e99e60130899fbe3b3ab6e9dce9187a7c" \ + | jq -r '.[] | .download_url' | xargs -n 1 curl -LO + +#### CLI release related #### + +VERSION ?= dev +# Default to a dummy version 0.0.1.1, which is always lower than a real release. +# Legal version values should look like 'x.x.x.x' where x is an integer from 0 to 65534. +# https://learn.microsoft.com/en-us/windows/win32/msi/productversion?redirectedfrom=MSDN +# https://stackoverflow.com/questions/9312221/msi-version-numbers +MSI_VERSION ?= 0.0.1.1 +non_windows_platforms := darwin_amd64 darwin_arm64 linux_amd64 linux_arm64 +non_windows_archives := $(non_windows_platforms:%=dist/wazero_$(VERSION)_%.tar.gz) +windows_platforms := windows_amd64 # TODO: add arm64 windows once we start testing on it. +windows_archives := $(windows_platforms:%=dist/wazero_$(VERSION)_%.zip) $(windows_platforms:%=dist/wazero_$(VERSION)_%.msi) +checksum_txt := dist/wazero_$(VERSION)_checksums.txt + +# define macros for multi-platform builds. these parse the filename being built +go-arch = $(if $(findstring amd64,$1),amd64,arm64) +go-os = $(if $(findstring .exe,$1),windows,$(if $(findstring linux,$1),linux,darwin)) +# msi-arch is a macro so we can detect it based on the file naming convention +msi-arch = $(if $(findstring amd64,$1),x64,arm64) + +build/wazero_%/wazero: + $(call go-build,$@,$<) + +build/wazero_%/wazero.exe: + $(call go-build,$@,$<) + +dist/wazero_$(VERSION)_%.tar.gz: build/wazero_%/wazero + @echo tar.gz "tarring $@" + @mkdir -p $(@D) +# On Windows, we pass the special flag `--mode='+rx' to ensure that we set the executable flag. +# This is only supported by GNU Tar, so we set it conditionally. + @tar -C $(> $(@F) + +dist: $(non_windows_archives) $(if $(findstring Windows_NT,$(OS)),$(windows_archives),) $(checksum_txt) diff --git a/vendor/github.com/tetratelabs/wazero/NOTICE b/vendor/github.com/tetratelabs/wazero/NOTICE new file mode 100644 index 00000000..2f5ea8eb --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/NOTICE @@ -0,0 +1,2 @@ +wazero +Copyright 2020-2023 wazero authors diff --git a/vendor/github.com/tetratelabs/wazero/RATIONALE.md b/vendor/github.com/tetratelabs/wazero/RATIONALE.md new file mode 100644 index 00000000..8d783cb4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/RATIONALE.md @@ -0,0 +1,1587 @@ +# Notable rationale of wazero + +## Zero dependencies + +Wazero has zero dependencies to differentiate itself from other runtimes which +have heavy impact usually due to CGO. By avoiding CGO, wazero avoids +prerequisites such as shared libraries or libc, and lets users keep features +like cross compilation. + +Avoiding go.mod dependencies reduces interference on Go version support, and +size of a statically compiled binary. However, doing so brings some +responsibility into the project. + +Go's native platform support is good: We don't need platform-specific code to +get monotonic time, nor do we need much work to implement certain features +needed by our compiler such as `mmap`. That said, Go does not support all +common operating systems to the same degree. For example, Go 1.18 includes +`Mprotect` on Linux and Darwin, but not FreeBSD. + +The general tradeoff the project takes from a zero dependency policy is more +explicit support of platforms (in the compiler runtime), as well a larger and +more technically difficult codebase. + +At some point, we may allow extensions to supply their own platform-specific +hooks. Until then, one end user impact/tradeoff is some glitches trying +untested platforms (with the Compiler runtime). + +### Why do we use CGO to implement system calls on darwin? + +wazero is dependency and CGO free by design. In some cases, we have code that +can optionally use CGO, but retain a fallback for when that's disabled. The only +operating system (`GOOS`) we use CGO by default in is `darwin`. + +Unlike other operating systems, regardless of `CGO_ENABLED`, Go always uses +"CGO" mechanisms in the runtime layer of `darwin`. This is explained in +[Statically linked binaries on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html#//apple_ref/doc/uid/DTS10001666): + +> Apple does not support statically linked binaries on Mac OS X. A statically +> linked binary assumes binary compatibility at the kernel system call +> interface, and we do not make any guarantees on that front. Rather, we strive +> to ensure binary compatibility in each dynamically linked system library and +> framework. + +This plays to our advantage for system calls that aren't yet exposed in the Go +standard library, notably `futimens` for nanosecond-precision timestamp +manipulation. + +### Why not x/sys + +Going beyond Go's SDK limitations can be accomplished with their [x/sys library](https://pkg.go.dev/golang.org/x/sys/unix). +For example, this includes `zsyscall_freebsd_amd64.go` missing from the Go SDK. + +However, like all dependencies, x/sys is a source of conflict. For example, +x/sys had to be in order to upgrade to Go 1.18. + +If we depended on x/sys, we could get more precise functionality needed for +features such as clocks or more platform support for the compiler runtime. + +That said, formally supporting an operating system may still require testing as +even use of x/sys can require platform-specifics. For example, [mmap-go](https://github.com/edsrzf/mmap-go) +uses x/sys, but also mentions limitations, some not surmountable with x/sys +alone. + +Regardless, we may at some point introduce a separate go.mod for users to use +x/sys as a platform plugin without forcing all users to maintain that +dependency. + +## Project structure + +wazero uses internal packages extensively to balance API compatibility desires for end users with the need to safely +share internals between compilers. + +End-user packages include `wazero`, with `Config` structs, `api`, with shared types, and the built-in `wasi` library. +Everything else is internal. + +We put the main program for wazero into a directory of the same name to match conventions used in `go install`, +notably the name of the folder becomes the binary name. We chose to use `cmd/wazero` as it is common practice +and less surprising than `wazero/wazero`. + +### Internal packages + +Most code in wazero is internal, and it is acknowledged that this prevents external implementation of facets such as +compilers or decoding. It also prevents splitting this code into separate repositories, resulting in a larger monorepo. +This also adds work as more code needs to be centrally reviewed. + +However, the alternative is neither secure nor viable. To allow external implementation would require exporting symbols +public, such as the `CodeSection`, which can easily create bugs. Moreover, there's a high drift risk for any attempt at +external implementations, compounded not just by wazero's code organization, but also the fast moving Wasm and WASI +specifications. + +For example, implementing a compiler correctly requires expertise in Wasm, Golang and assembly. This requires deep +insight into how internals are meant to be structured and the various tiers of testing required for `wazero` to result +in a high quality experience. Even if someone had these skills, supporting external code would introduce variables which +are constants in the central one. Supporting an external codebase is harder on the project team, and could starve time +from the already large burden on the central codebase. + +The tradeoffs of internal packages are a larger codebase and responsibility to implement all standard features. It also +implies thinking about extension more as forking is not viable for reasons above also. The primary mitigation of these +realities are friendly OSS licensing, high rigor and a collaborative spirit which aim to make contribution in the shared +codebase productive. + +### Avoiding cyclic dependencies + +wazero shares constants and interfaces with internal code by a sharing pattern described below: +* shared interfaces and constants go in one package under root: `api`. +* user APIs and structs depend on `api` and go into the root package `wazero`. + * e.g. `InstantiateModule` -> `/wasm.go` depends on the type `api.Module`. +* implementation code can also depend on `api` in a corresponding package under `/internal`. + * Ex package `wasm` -> `/internal/wasm/*.go` and can depend on the type `api.Module`. + +The above guarantees no cyclic dependencies at the cost of having to re-define symbols that exist in both packages. +For example, if `wasm.Store` is a type the user needs access to, it is narrowed by a cover type in the `wazero`: + +```go +type runtime struct { + s *wasm.Store +} +``` + +This is not as bad as it sounds as mutations are only available via configuration. This means exported functions are +limited to only a few functions. + +### Avoiding security bugs + +In order to avoid security flaws such as code insertion, nothing in the public API is permitted to write directly to any +mutable symbol in the internal package. For example, the package `api` is shared with internal code. To ensure +immutability, the `api` package cannot contain any mutable public symbol, such as a slice or a struct with an exported +field. + +In practice, this means shared functionality like memory mutation need to be implemented by interfaces. + +Here are some examples: +* `api.Memory` protects access by exposing functions like `WriteFloat64Le` instead of exporting a buffer (`[]byte`). +* There is no exported symbol for the `[]byte` representing the `CodeSection` + +Besides security, this practice prevents other bugs and allows centralization of validation logic such as decoding Wasm. + +## API Design + +### Why is `context.Context` inconsistent? + +It may seem strange that only certain API have an initial `context.Context` +parameter. We originally had a `context.Context` for anything that might be +traced, but it turned out to be only useful for lifecycle and host functions. + +For instruction-scoped aspects like memory updates, a context parameter is too +fine-grained and also invisible in practice. For example, most users will use +the compiler engine, and its memory, global or table access will never use go's +context. + +### Why does `api.ValueType` map to uint64? + +WebAssembly allows functions to be defined either by the guest or the host, +with signatures expressed as WebAssembly types. For example, `i32` is a 32-bit +type which might be interpreted as signed. Function signatures can have zero or +more parameters or results even if WebAssembly 1.0 allows up to one result. + +The guest can export functions, so that the host can call it. In the case of +wazero, the host is Go and an exported function can be called via +`api.Function`. `api.Function` allows users to supply parameters and read +results as a slice of uint64. For example, if there are no results, an empty +slice is returned. The user can learn the signature via `FunctionDescription`, +which returns the `api.ValueType` corresponding to each parameter or result. +`api.ValueType` defines the mapping of WebAssembly types to `uint64` values for +reason described in this section. The special case of `v128` is also mentioned +below. + +wazero maps each value type to a uint64 values because it holds the largest +type in WebAssembly 1.0 (i64). A slice allows you to express empty (e.g. a +nullary signature), for example a start function. + +Here's an example of calling a function, noting this syntax works for both a +signature `(param i32 i32) (result i32)` and `(param i64 i64) (result i64)` +```go +x, y := uint64(1), uint64(2) +results, err := mod.ExportedFunction("add").Call(ctx, x, y) +if err != nil { + log.Panicln(err) +} +fmt.Printf("%d + %d = %d\n", x, y, results[0]) +``` + +WebAssembly does not define an encoding strategy for host defined parameters or +results. This means the encoding rules above are defined by wazero instead. To +address this, we clarified mapping both in `api.ValueType` and added helper +functions like `api.EncodeF64`. This allows users conversions typical in Go +programming, and utilities to avoid ambiguity and edge cases around casting. + +Alternatively, we could have defined a byte buffer based approach and a binary +encoding of value types in and out. For example, an empty byte slice would mean +no values, while a non-empty could use a binary encoding for supported values. +This could work, but it is more difficult for the normal case of i32 and i64. +It also shares a struggle with the current approach, which is that value types +were added after WebAssembly 1.0 and not all of them have an encoding. More on +this below. + +In summary, wazero chose an approach for signature mapping because there was +none, and the one we chose biases towards simplicity with integers and handles +the rest with documentation and utilities. + +#### Post 1.0 value types + +Value types added after WebAssembly 1.0 stressed the current model, as some +have no encoding or are larger than 64 bits. While problematic, these value +types are not commonly used in exported (extern) functions. However, some +decisions were made and detailed below. + +For example `externref` has no guest representation. wazero chose to map +references to uint64 as that's the largest value needed to encode a pointer on +supported platforms. While there are two reference types, `externref` and +`functype`, the latter is an internal detail of function tables, and the former +is rarely if ever used in function signatures as of the end of 2022. + +The only value larger than 64 bits is used for SIMD (`v128`). Vectorizing via +host functions is not used as of the end of 2022. Even if it were, it would be +inefficient vs guest vectorization due to host function overhead. In other +words, the `v128` value type is unlikely to be in an exported function +signature. That it requires two uint64 values to encode is an internal detail +and not worth changing the exported function interface `api.Function`, as doing +so would break all users. + +### Interfaces, not structs + +All exported types in public packages, regardless of configuration vs runtime, are interfaces. The primary benefits are +internal flexibility and avoiding people accidentally mis-initializing by instantiating the types on their own vs using +the `NewXxx` constructor functions. In other words, there's less support load when things can't be done incorrectly. + +Here's an example: +```go +rt := &RuntimeConfig{} // not initialized properly (fields are nil which shouldn't be) +rt := RuntimeConfig{} // not initialized properly (should be a pointer) +rt := wazero.NewRuntimeConfig() // initialized properly +``` + +There are a few drawbacks to this, notably some work for maintainers. +* Interfaces are decoupled from the structs implementing them, which means the signature has to be repeated twice. +* Interfaces have to be documented and guarded at time of use, that 3rd party implementations aren't supported. +* As of Golang 1.21, interfaces are still [not well supported](https://github.com/golang/go/issues/5860) in godoc. + +## Config + +wazero configures scopes such as Runtime and Module using `XxxConfig` types. For example, `RuntimeConfig` configures +`Runtime` and `ModuleConfig` configure `Module` (instantiation). In all cases, config types begin defaults and can be +customized by a user, e.g., selecting features or a module name override. + +### Why don't we make each configuration setting return an error? +No config types create resources that would need to be closed, nor do they return errors on use. This helps reduce +resource leaks, and makes chaining easier. It makes it possible to parse configuration (ex by parsing yaml) independent +of validating it. + +Instead of: +``` +cfg, err = cfg.WithFS(fs) +if err != nil { + return err +} +cfg, err = cfg.WithName(name) +if err != nil { + return err +} +mod, err = rt.InstantiateModuleWithConfig(ctx, code, cfg) +if err != nil { + return err +} +``` + +There's only one call site to handle errors: +``` +cfg = cfg.WithFS(fs).WithName(name) +mod, err = rt.InstantiateModuleWithConfig(ctx, code, cfg) +if err != nil { + return err +} +``` + +This allows users one place to look for errors, and also the benefit that if anything internally opens a resource, but +errs, there's nothing they need to close. In other words, users don't need to track which resources need closing on +partial error, as that is handled internally by the only code that can read configuration fields. + +### Why are configuration immutable? +While it seems certain scopes like `Runtime` won't repeat within a process, they do, possibly in different goroutines. +For example, some users create a new runtime for each module, and some re-use the same base module configuration with +only small updates (ex the name) for each instantiation. Making configuration immutable allows them to be safely used in +any goroutine. + +Since config are immutable, changes apply via return val, similar to `append` in a slice. + +For example, both of these are the same sort of error: +```go +append(slice, element) // bug as only the return value has the updated slice. +cfg.WithName(next) // bug as only the return value has the updated name. +``` + +Here's an example of correct use: re-assigning explicitly or via chaining. +```go +cfg = cfg.WithName(name) // explicit + +mod, err = rt.InstantiateModuleWithConfig(ctx, code, cfg.WithName(name)) // implicit +if err != nil { + return err +} +``` + +### Why aren't configuration assigned with option types? +The option pattern is a familiar one in Go. For example, someone defines a type `func (x X) err` and uses it to update +the target. For example, you could imagine wazero could choose to make `ModuleConfig` from options vs chaining fields. + +Ex instead of: +```go +type ModuleConfig interface { + WithName(string) ModuleConfig + WithFS(fs.FS) ModuleConfig +} + +struct moduleConfig { + name string + fs fs.FS +} + +func (c *moduleConfig) WithName(name string) ModuleConfig { + ret := *c // copy + ret.name = name + return &ret +} + +func (c *moduleConfig) WithFS(fs fs.FS) ModuleConfig { + ret := *c // copy + ret.setFS("/", fs) + return &ret +} + +config := r.NewModuleConfig().WithFS(fs) +configDerived := config.WithName("name") +``` + +An option function could be defined, then refactor each config method into an name prefixed option function: +```go +type ModuleConfig interface { +} +struct moduleConfig { + name string + fs fs.FS +} + +type ModuleConfigOption func(c *moduleConfig) + +func ModuleConfigName(name string) ModuleConfigOption { + return func(c *moduleConfig) { + c.name = name + } +} + +func ModuleConfigFS(fs fs.FS) ModuleConfigOption { + return func(c *moduleConfig) { + c.fs = fs + } +} + +func (r *runtime) NewModuleConfig(opts ...ModuleConfigOption) ModuleConfig { + ret := newModuleConfig() // defaults + for _, opt := range opts { + opt(&ret.config) + } + return ret +} + +func (c *moduleConfig) WithOptions(opts ...ModuleConfigOption) ModuleConfig { + ret := *c // copy base config + for _, opt := range opts { + opt(&ret.config) + } + return ret +} + +config := r.NewModuleConfig(ModuleConfigFS(fs)) +configDerived := config.WithOptions(ModuleConfigName("name")) +``` + +wazero took the path of the former design primarily due to: +* interfaces provide natural namespaces for their methods, which is more direct than functions with name prefixes. +* parsing config into function callbacks is more direct vs parsing config into a slice of functions to do the same. +* in either case derived config is needed and the options pattern is more awkward to achieve that. + +There are other reasons such as test and debug being simpler without options: the above list is constrained to conserve +space. It is accepted that the options pattern is common in Go, which is the main reason for documenting this decision. + +### Why aren't config types deeply structured? +wazero's configuration types cover the two main scopes of WebAssembly use: +* `RuntimeConfig`: This is the broadest scope, so applies also to compilation + and instantiation. e.g. This controls the WebAssembly Specification Version. +* `ModuleConfig`: This affects modules instantiated after compilation and what + resources are allowed. e.g. This defines how or if STDOUT is captured. This + also allows sub-configuration of `FSConfig`. + +These default to a flat definition each, with lazy sub-configuration only after +proven to be necessary. A flat structure is easier to work with and is also +easy to discover. Unlike the option pattern described earlier, more +configuration in the interface doesn't taint the package namespace, only +`ModuleConfig`. + +We default to a flat structure to encourage simplicity. If we eagerly broke out +all possible configurations into sub-types (e.g. ClockConfig), it would be hard +to notice configuration sprawl. By keeping the config flat, it is easy to see +the cognitive load we may be adding to our users. + +In other words, discomfort adding more configuration is a feature, not a bug. +We should only add new configuration rarely, and before doing so, ensure it +will be used. In fact, this is why we support using context fields for +experimental configuration. By letting users practice, we can find out if a +configuration was a good idea or not before committing to it, and potentially +sprawling our types. + +In reflection, this approach worked well for the nearly 1.5 year period leading +to version 1.0. We've only had to create a single sub-configuration, `FSConfig`, +and it was well understood why when it occurred. + +## Why does `ModuleConfig.WithStartFunctions` default to `_start`? + +We formerly had functions like `StartWASICommand` that would verify +preconditions and start WASI's `_start` command. However, this caused confusion +because both many languages compiled a WASI dependency, and many did so +inconsistently. + +The conflict is that exported functions need to use features the language +runtime provides, such as garbage collection. There's a "chicken-egg problem" +where `_start` needs to complete in order for exported behavior to work. + +For example, unlike `GOOS=wasip1` in Go 1.21, TinyGo's "wasi" target supports +function exports. So, the only way to use FFI style is via the "wasi" target. +Not explicitly calling `_start` before an ABI such as wapc-go, would crash, due +to setup not happening (e.g. to implement `panic`). Other embedders such as +Envoy also called `_start` for the same reason. To avoid a common problem for +users unaware of WASI, and also to simplify normal use of WASI (e.g. `main`), +we added `_start` to `ModuleConfig.WithStartFunctions`. + +In cases of multiple initializers, such as in wapc-go, users can override this +to add the others *after* `_start`. Users who want to explicitly control +`_start`, such as some of our unit tests, can clear the start functions and +remove it. + +This decision was made in 2022, and holds true in 2023, even with the +introduction of "wasix". It holds because "wasix" is backwards compatible with +"wasip1". In the future, there will be other ways to start applications, and +may not be backwards compatible with "wasip1". + +Most notably WASI "Preview 2" is not implemented in a way compatible with +wasip1. Its start function is likely to be different, and defined in the +wasi-cli "world". When the design settles, and it is implemented by compilers, +wazero will attempt to support "wasip2". However, it won't do so in a way that +breaks existing compilers. + +In other words, we won't remove `_start` if "wasip2" continues a path of an +alternate function name. If we did, we'd break existing users despite our +compatibility promise saying we don't. The most likely case is that when we +build-in something incompatible with "wasip1", that start function will be +added to the start functions list in addition to `_start`. + +See http://wasix.org +See https://github.com/WebAssembly/wasi-cli + +## Runtime == Engine+Store +wazero defines a single user-type which combines the specification concept of `Store` with the unspecified `Engine` +which manages them. + +### Why not multi-store? +Multi-store isn't supported as the extra tier complicates lifecycle and locking. Moreover, in practice it is unusual for +there to be an engine that has multiple stores which have multiple modules. More often, it is the case that there is +either 1 engine with 1 store and multiple modules, or 1 engine with many stores, each having 1 non-host module. In worst +case, a user can use multiple runtimes until "multi-store" is better understood. + +If later, we have demand for multiple stores, that can be accomplished by overload. e.g. `Runtime.InstantiateInStore` or +`Runtime.Store(name) Store`. + +## Exit + +### Why do we only return a `sys.ExitError` on a non-zero exit code? + +It is reasonable to think an exit error should be returned, even if the code is +success (zero). Even on success, the module is no longer functional. For +example, function exports would error later. However, wazero does not. The only +time `sys.ExitError` is on error (non-zero). + +This decision was to improve performance and ergonomics for guests that both +use WASI (have a `_start` function), and also allow custom exports. +Specifically, Rust, TinyGo and normal wasi-libc, don't exit the module during +`_start`. If they did, it would invalidate their function exports. This means +it is unlikely most compilers will change this behavior. + +`GOOS=waspi1` from Go 1.21 does exit during `_start`. However, it doesn't +support other exports besides `_start`, and `_start` is not defined to be +called multiple times anyway. + +Since `sys.ExitError` is not always returned, we added `Module.IsClosed` for +defensive checks. This helps integrators avoid calling functions which will +always fail. + +### Why panic with `sys.ExitError` after a host function exits? + +Currently, the only portable way to stop processing code is via panic. For +example, WebAssembly "trap" instructions, such as divide by zero, are +implemented via panic. This ensures code isn't executed after it. + +When code reaches the WASI `proc_exit` instruction, we need to stop processing. +Regardless of the exit code, any code invoked after exit would be in an +inconsistent state. This is likely why unreachable instructions are sometimes +inserted after exit: https://github.com/emscripten-core/emscripten/issues/12322 + +## WASI + +Unfortunately, (WASI Snapshot Preview 1)[https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md] is not formally defined enough, and has APIs with ambiguous semantics. +This section describes how Wazero interprets and implements the semantics of several WASI APIs that may be interpreted differently by different wasm runtimes. +Those APIs may affect the portability of a WASI application. + +### Why don't we attempt to pass wasi-testsuite on user-defined `fs.FS`? + +While most cases work fine on an `os.File` based implementation, we won't +promise wasi-testsuite compatibility on user defined wrappers of `os.DirFS`. +The only option for real systems is to use our `sysfs.FS`. + +There are a lot of areas where windows behaves differently, despite the +`os.File` abstraction. This goes well beyond file locking concerns (e.g. +`EBUSY` errors on open files). For example, errors like `ACCESS_DENIED` aren't +properly mapped to `EPERM`. There are trickier parts too. `FileInfo.Sys()` +doesn't return enough information to build inodes needed for WASI. To rebuild +them requires the full path to the underlying file, not just its directory +name, and there's no way for us to get that information. At one point we tried, +but in practice things became tangled and functionality such as read-only +wrappers became untenable. Finally, there are version-specific behaviors which +are difficult to maintain even in our own code. For example, go 1.20 opens +files in a different way than versions before it. + +### Why aren't WASI rules enforced? + +The [snapshot-01](https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md) version of WASI has a +number of rules for a "command module", but only the memory export rule is enforced. If a "_start" function exists, it +is enforced to be the correct signature and succeed, but the export itself isn't enforced. It follows that this means +exports are not required to be contained to a "_start" function invocation. Finally, the "__indirect_function_table" +export is also not enforced. + +The reason for the exceptions are that implementations aren't following the rules. For example, TinyGo doesn't export +"__indirect_function_table", so crashing on this would make wazero unable to run TinyGo modules. Similarly, modules +loaded by wapc-go don't always define a "_start" function. Since "snapshot-01" is not a proper version, and certainly +not a W3C recommendation, there's no sense in breaking users over matters like this. + +### Why is I/O configuration not coupled to WASI? + +WebAssembly System Interfaces (WASI) is a formalization of a practice that can be done anyway: Define a host function to +access a system interface, such as writing to STDOUT. WASI stalled at snapshot-01 and as of early 2023, is being +rewritten entirely. + +This instability implies a need to transition between WASI specs, which places wazero in a position that requires +decoupling. For example, if code uses two different functions to call `fd_write`, the underlying configuration must be +centralized and decoupled. Otherwise, calls using the same file descriptor number will end up writing to different +places. + +In short, wazero defined system configuration in `ModuleConfig`, not a WASI type. This allows end-users to switch from +one spec to another with minimal impact. This has other helpful benefits, as centralized resources are simpler to close +coherently (ex via `Module.Close`). + +In reflection, this worked well as more ABI became usable in wazero. + +### Background on `ModuleConfig` design + +WebAssembly 1.0 (20191205) specifies some aspects to control isolation between modules ([sandboxing](https://en.wikipedia.org/wiki/Sandbox_(computer_security))). +For example, `wasm.Memory` has size constraints and each instance of it is isolated from each other. While `wasm.Memory` +can be shared, by exporting it, it is not exported by default. In fact a WebAssembly Module (Wasm) has no memory by +default. + +While memory is defined in WebAssembly 1.0 (20191205), many aspects are not. Let's use an example of `exec.Cmd` as for +example, a WebAssembly System Interfaces (WASI) command is implemented as a module with a `_start` function, and in many +ways acts similar to a process with a `main` function. + +To capture "hello world" written to the console (stdout a.k.a. file descriptor 1) in `exec.Cmd`, you would set the +`Stdout` field accordingly, perhaps to a buffer. In WebAssembly 1.0 (20191205), the only way to perform something like +this is via a host function (ex `HostModuleFunctionBuilder`) and internally copy memory corresponding to that string +to a buffer. + +WASI implements system interfaces with host functions. Concretely, to write to console, a WASI command `Module` imports +"fd_write" from "wasi_snapshot_preview1" and calls it with the `fd` parameter set to 1 (STDOUT). + +The [snapshot-01](https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md) version of WASI has no +means to declare configuration, although its function definitions imply configuration for example if fd 1 should exist, +and if so where should it write. Moreover, snapshot-01 was last updated in late 2020 and the specification is being +completely rewritten as of early 2022. This means WASI as defined by "snapshot-01" will not clarify aspects like which +file descriptors are required. While it is possible a subsequent version may, it is too early to tell as no version of +WASI has reached a stage near W3C recommendation. Even if it did, module authors are not required to only use WASI to +write to console, as they can define their own host functions, such as they did before WASI existed. + +wazero aims to serve Go developers as a primary function, and help them transition between WASI specifications. In +order to do this, we have to allow top-level configuration. To ensure isolation by default, `ModuleConfig` has WithXXX +that override defaults to no-op or empty. One `ModuleConfig` instance is used regardless of how many times the same WASI +functions are imported. The nil defaults allow safe concurrency in these situations, as well lower the cost when they +are never used. Finally, a one-to-one mapping with `Module` allows the module to close the `ModuleConfig` instead of +confusing users with another API to close. + +Naming, defaults and validation rules of aspects like `STDIN` and `Environ` are intentionally similar to other Go +libraries such as `exec.Cmd` or `syscall.SetEnv`, and differences called out where helpful. For example, there's no goal +to emulate any operating system primitive specific to Windows (such as a 'c:\' drive). Moreover, certain defaults +working with real system calls are neither relevant nor safe to inherit: For example, `exec.Cmd` defaults to read STDIN +from a real file descriptor ("/dev/null"). Defaulting to this, vs reading `io.EOF`, would be unsafe as it can exhaust +file descriptors if resources aren't managed properly. In other words, blind copying of defaults isn't wise as it can +violate isolation or endanger the embedding process. In summary, we try to be similar to normal Go code, but often need +act differently and document `ModuleConfig` is more about emulating, not necessarily performing real system calls. + +## File systems + +### Motivation on `sys.FS` + +The `sys.FS` abstraction in wazero was created because of limitations in +`fs.FS`, and `fs.File` in Go. Compilers targeting `wasip1` may access +functionality that writes new files. The ability to overcome this was requested +even before wazero was named this, via issue #21 in March 2021. + +A month later, golang/go#45757 was raised by someone else on the same topic. As +of July 2023, this has not resolved to a writeable file system abstraction. + +Over the next year more use cases accumulated, consolidated in March 2022 into +#390. This closed in January 2023 with a milestone of providing more +functionality, limited to users giving a real directory. This didn't yet expose +a file abstraction for general purpose use. Internally, this used `os.File`. +However, a wasm module instance is a virtual machine. Only supporting `os.File` +breaks sand-boxing use cases. Moreover, `os.File` is not an interface. Even +though this abstracts functionality, it does allow interception use cases. + +Hence, a few days later in January 2023, we had more issues asking to expose an +abstraction, #1013 and later #1532, on use cases like masking access to files. +In other words, the use case requests never stopped, and aren't solved by +exposing only real files. + +In summary, the primary motivation for exposing a replacement for `fs.FS` and +`fs.File` was around repetitive use case requests for years, around +interception and the ability to create new files, both virtual and real files. +While some use cases are solved with real files, not all are. Regardless, an +interface approach is necessary to ensure users can intercept I/O operations. + +### Why doesn't `sys.File` have a `Fd()` method? + +There are many features we could expose. We could make File expose underlying +file descriptors in case they are supported, for integration of system calls +that accept multiple ones, namely `poll` for multiplexing. This special case is +described in a subsequent section. + +As noted above, users have been asking for a file abstraction for over two +years, and a common answer was to wait. Making users wait is a problem, +especially so long. Good reasons to make people wait are stabilization. Edge +case features are not a great reason to hold abstractions from users. + +Another reason is implementation difficulty. Go did not attempt to abstract +file descriptors. For example, unlike `fs.ReadFile` there is no `fs.FdFile` +interface. Most likely, this is because file descriptors are an implementation +detail of common features. Programming languages, including Go, do not require +end users to know about file descriptors. Types such as `fs.File` can be used +without any knowledge of them. Implementations may or may not have file +descriptors. For example, in Go, `os.DirFS` has underlying file descriptors +while `embed.FS` does not. + +Despite this, some may want to expose a non-standard interface because +`os.File` has `Fd() uintptr` to return a file descriptor. Mainly, this is +handy to integrate with `syscall` package functions (on `GOOS` values that +declare them). Notice, though that `uintptr` is unsafe and not an abstraction. +Close inspection will find some `os.File` types internally use `poll.FD` +instead, yet this is not possible to use abstractly because that type is not +exposed. For example, `plan9` uses a different type than `poll.FD`. In other +words, even in real files, `Fd()` is not wholly portable, despite it being +useful on many operating systems with the `syscall` package. + +The reasons above, why Go doesn't abstract `FdFile` interface are a subset of +reasons why `sys.File` does not. If we exposed `File.Fd()` we not only would +have to declare all the edge cases that Go describes including impact of +finalizers, we would have to describe these in terms of virtualized files. +Then, we would have to reason with this value vs our existing virtualized +`sys.FileTable`, mapping whatever type we return to keys in that table, also +in consideration of garbage collection impact. The combination of issues like +this could lead down a path of not implementing a file system abstraction at +all, and instead a weak key mapped abstraction of the `syscall` package. Once +we finished with all the edge cases, we would have lost context of the original +reason why we started.. simply to allow file write access! + +When wazero attempts to do more than what the Go programming language team, it +has to be carefully evaluated, to: +* Be possible to implement at least for `os.File` backed files +* Not be confusing or cognitively hard for virtual file systems and normal use. +* Affordable: custom code is solely the responsible by the core team, a much + smaller group of individuals than who maintain the Go programming language. + +Due to problems well known in Go, consideration of the end users who constantly +ask for basic file system functionality, and the difficulty virtualizing file +descriptors at multiple levels, we don't expose `Fd()` and likely won't ever +expose `Fd()` on `sys.File`. + +### Why does `sys.File` have a `Poll()` method, while `sys.FS` does not? + +wazero exposes `File.Poll` which allows one-at-a-time poll use cases, +requested by multiple users. This not only includes abstract tests such as +Go 1.21 `GOOS=wasip1`, but real use cases including python and container2wasm +repls, as well listen sockets. The main use cases is non-blocking poll on a +single file. Being a single file, this has no risk of problems such as +head-of-line blocking, even when emulated. + +The main use case of multi-poll are bidirectional network services, something +not used in `GOOS=wasip1` standard libraries, but could be in the future. +Moving forward without a multi-poller allows wazero to expose its file system +abstraction instead of continuing to hold back it back for edge cases. We'll +continue discussion below regardless, as rationale was requested. + +You can loop through multiple `sys.File`, using `File.Poll` to see if an event +is ready, but there is a head-of-line blocking problem. If a long timeout is +used, bad luck could have a file that has nothing to read or write before one +that does. This could cause more blocking than necessary, even if you could +poll the others just after with a zero timeout. What's worse than this is if +unlimited blocking was used (`timeout=-1`). The host implementations could use +goroutines to avoid this, but interrupting a "forever" poll is problematic. All +of these are reasons to consider a multi-poll API, but do not require exporting +`File.Fd()`. + +Should multi-poll becomes critical, `sys.FS` could expose a `Poll` function +like below, despite it being the non-portable, complicated if possible to +implement on all platforms and virtual file systems. +```go +ready, errno := fs.Poll([]sys.PollFile{{f1, sys.POLLIN}, {f2, sys.POLLOUT}}, timeoutMillis) +``` + +A real filesystem could handle this by using an approach like the internal +`unix.Poll` function in Go, passing file descriptors on unix platforms, or +returning `sys.ENOSYS` for unsupported operating systems. Implementation for +virtual files could have a strategy around timeout to avoid the worst case of +head-of-line blocking (unlimited timeout). + +Let's remember that when designing abstractions, it is not best to add an +interface for everything. Certainly, Go doesn't, as evidenced by them not +exposing `poll.FD` in `os.File`! Such a multi-poll could be limited to +built-in filesystems in the wazero repository, avoiding complexity of trying to +support and test this abstractly. This would still permit multiplexing for CLI +users, and also permit single file polling as exists now. + +### Why doesn't wazero implement the working directory? + +An early design of wazero's API included a `WithWorkDirFS` which allowed +control over which file a relative path such as "./config.yml" resolved to, +independent of the root file system. This intended to help separate concerns +like mutability of files, but it didn't work and was removed. + +Compilers that target wasm act differently with regard to the working +directory. For example, wasi-libc, used by TinyGo, +tracks working directory changes in compiled wasm instead: initially "/" until +code calls `chdir`. Zig assumes the first pre-opened file descriptor is the +working directory. + +The only place wazero can standardize a layered concern is via a host function. +Since WASI doesn't use host functions to track the working directory, we can't +standardize the storage and initial value of it. + +Meanwhile, code may be able to affect the working directory by compiling +`chdir` into their main function, using an argument or ENV for the initial +value (possibly `PWD`). Those unable to control the compiled code should only +use absolute paths in configuration. + +See +* https://github.com/golang/go/blob/go1.20/src/syscall/fs_js.go#L324 +* https://github.com/WebAssembly/wasi-libc/pull/214#issue-673090117 +* https://github.com/ziglang/zig/blob/53a9ee699a35a3d245ab6d1dac1f0687a4dcb42c/src/main.zig#L32 + +### Why ignore the error returned by io.Reader when n > 1? + +Per https://pkg.go.dev/io#Reader, if we receive an error, any bytes read should +be processed first. At the syscall abstraction (`fd_read`), the caller is the +processor, so we can't process the bytes inline and also return the error (as +`EIO`). + +Let's assume we want to return the bytes read on error to the caller. This +implies we at least temporarily ignore the error alongside them. The choice +remaining is whether to persist the error returned with the read until a +possible next call, or ignore the error. + +If we persist an error returned, it would be coupled to a file descriptor, but +effectively it is boolean as this case coerces to `EIO`. If we track a "last +error" on a file descriptor, it could be complicated for a couple reasons +including whether the error is transient or permanent, or if the error would +apply to any FD operation, or just read. Finally, there may never be a +subsequent read as perhaps the bytes leading up to the error are enough to +satisfy the processor. + +This decision boils down to whether or not to track an error bit per file +descriptor or not. If not, the assumption is that a subsequent operation would +also error, this time without reading any bytes. + +The current opinion is to go with the simplest path, which is to return the +bytes read and ignore the error the there were any. Assume a subsequent +operation will err if it needs to. This helps reduce the complexity of the code +in wazero and also accommodates the scenario where the bytes read are enough to +satisfy its processor. + +### File descriptor allocation strategy + +File descriptor allocation currently uses a strategy similar the one implemented +by unix systems: when opening a file, the lowest unused number is picked. + +The WASI standard documents that programs cannot expect that file descriptor +numbers will be allocated with a lowest-first strategy, and they should instead +assume the values will be random. Since _random_ is a very imprecise concept in +computers, we technically satisfying the implementation with the descriptor +allocation strategy we use in Wazero. We could imagine adding more _randomness_ +to the descriptor selection process, however this should never be used as a +security measure to prevent applications from guessing the next file number so +there are no strong incentives to complicate the logic. + +### Why does `FSConfig.WithDirMount` not match behaviour with `os.DirFS`? + +It may seem that we should require any feature that seems like a standard +library in Go, to behave the same way as the standard library. Doing so would +present least surprise to Go developers. In the case of how we handle +filesystems, we break from that as it is incompatible with the expectations of +WASI, the most commonly implemented filesystem ABI. + +The main reason is that `os.DirFS` is a virtual filesystem abstraction while +WASI is an abstraction over syscalls. For example, the signature of `fs.Open` +does not permit use of flags. This creates conflict on what default behaviors +to take when Go implemented `os.DirFS`. On the other hand, `path_open` can pass +flags, and in fact tests require them to be honored in specific ways. + +This conflict requires us to choose what to be more compatible with, and which +type of user to surprise the least. We assume there will be more developers +compiling code to wasm than developers of custom filesystem plugins, and those +compiling code to wasm will be better served if we are compatible with WASI. +Hence on conflict, we prefer WASI behavior vs the behavior of `os.DirFS`. + +See https://github.com/WebAssembly/wasi-testsuite +See https://github.com/golang/go/issues/58141 + +## Why is our `Readdir` function more like Go's `os.File` than POSIX `readdir`? + +At one point we attempted to move from a bulk `Readdir` function to something +more like the POSIX `DIR` struct, exposing functions like `telldir`, `seekdir` +and `readdir`. However, we chose the design more like `os.File.Readdir`, +because it performs and fits wasip1 better. + +### wasip1/wasix + +`fd_readdir` in wasip1 (and so also wasix) is like `getdents` in Linux, not +`readdir` in POSIX. `getdents` is more like Go's `os.File.Readdir`. + +We currently have an internal type `sys.DirentCache` which only is used by +wasip1 or wasix. When `HostModuleBuilder` adds support for instantiation state, +we could move this to the `wasi_snapshot_preview1` package. Meanwhile, all +filesystem code is internal anyway, so this special-case is acceptable. + +### wasip2 + +`directory-entry-stream` in wasi-filesystem preview2 is defined in component +model, not an ABI, but in wasmtime it is a consuming iterator. A consuming +iterator is easy to support with anything (like `Readdir(1)`), even if it is +inefficient as you can neither bulk read nor skip. The implementation of the +preview1 adapter (uses preview2) confirms this. They use a dirent cache similar +in some ways to our `sysfs.DirentCache`. As there is no seek concept in +preview2, they interpret the cookie as numeric and read on repeat entries when +a cache wasn't available. Note: we currently do not skip-read like this as it +risks buffering large directories, and no user has requested entries before the +cache, yet. + +Regardless, wasip2 is not complete until the end of 2023. We can defer design +discussion until after it is stable and after the reference impl wasmtime +implements it. + +See + * https://github.com/WebAssembly/wasi-filesystem/blob/ef9fc87c07323a6827632edeb6a7388b31266c8e/example-world.md#directory_entry_stream + * https://github.com/bytecodealliance/wasmtime/blob/b741f7c79d72492d17ab8a29c8ffe4687715938e/crates/wasi/src/preview2/preview2/filesystem.rs#L286-L296 + * https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L2131-L2137 + * https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L936 + +### wasip3 + +`directory-entry-stream` is documented to change significantly in wasip3 moving +from synchronous to synchronous streams. This is dramatically different than +POSIX `readdir` which is synchronous. + +Regardless, wasip3 is not complete until after wasip2, which means 2024 or +later. We can defer design discussion until after it is stable and after the +reference impl wasmtime implements it. + +See + * https://github.com/WebAssembly/WASI/blob/ddfe3d1dda5d1473f37ecebc552ae20ce5fd319a/docs/WitInWasi.md#Streams + * https://docs.google.com/presentation/d/1MNVOZ8hdofO3tI0szg_i-Yoy0N2QPU2C--LzVuoGSlE/edit#slide=id.g1270ef7d5b6_0_662 + +### How do we implement `Pread` with an `fs.File`? + +`ReadAt` is the Go equivalent to `pread`: it does not affect, and is not +affected by, the underlying file offset. Unfortunately, `io.ReaderAt` is not +implemented by all `fs.File`. For example, as of Go 1.19, `embed.openFile` does +not. + +The initial implementation of `fd_pread` instead used `Seek`. To avoid a +regression, we fall back to `io.Seeker` when `io.ReaderAt` is not supported. + +This requires obtaining the initial file offset, seeking to the intended read +offset, and resetting the file offset the initial state. If this final seek +fails, the file offset is left in an undefined state. This is not thread-safe. + +While seeking per read seems expensive, the common case of `embed.openFile` is +only accessing a single int64 field, which is cheap. + +### Pre-opened files + +WASI includes `fd_prestat_get` and `fd_prestat_dir_name` functions used to +learn any directory paths for file descriptors open at initialization time. + +For example, `__wasilibc_register_preopened_fd` scans any file descriptors past +STDERR (1) and invokes `fd_prestat_dir_name` to learn any path prefixes they +correspond to. Zig's `preopensAlloc` does similar. These pre-open functions are +not used again after initialization. + +wazero supports stdio pre-opens followed by any mounts e.g `.:/`. The guest +path is a directory and its name, e.g. "/" is returned by `fd_prestat_dir_name` +for file descriptor 3 (STDERR+1). The first longest match wins on multiple +pre-opens, which allows a path like "/tmp" to match regardless of order vs "/". + +See + * https://github.com/WebAssembly/wasi-libc/blob/a02298043ff551ce1157bc2ee7ab74c3bffe7144/libc-bottom-half/sources/preopens.c + * https://github.com/ziglang/zig/blob/9cb06f3b8bf9ea6b5e5307711bc97328762d6a1d/lib/std/fs/wasi.zig#L50-L53 + +### fd_prestat_dir_name + +`fd_prestat_dir_name` is a WASI function to return the path of the pre-opened +directory of a file descriptor. It has the following three parameters, and the +third `path_len` has ambiguous semantics. + +* `fd`: a file descriptor +* `path`: the offset for the result path +* `path_len`: In wazero, `FdPrestatDirName` writes the result path string to + `path` offset for the exact length of `path_len`. + +Wasmer considers `path_len` to be the maximum length instead of the exact +length that should be written. +See https://github.com/wasmerio/wasmer/blob/3463c51268ed551933392a4063bd4f8e7498b0f6/lib/wasi/src/syscalls/mod.rs#L764 + +The semantics in wazero follows that of wasmtime. +See https://github.com/bytecodealliance/wasmtime/blob/2ca01ae9478f199337cf743a6ab543e8c3f3b238/crates/wasi-common/src/snapshots/preview_1.rs#L578-L582 + +Their semantics match when `path_len` == the length of `path`, so in practice +this difference won't matter match. + +## fd_readdir + +### Why does "wasi_snapshot_preview1" require dot entries when POSIX does not? + +In October 2019, WASI project knew requiring dot entries ("." and "..") was not +documented in preview1, not required by POSIX and problematic to synthesize. +For example, Windows runtimes backed by `FindNextFileW` could not return these. +A year later, the tag representing WASI preview 1 (`snapshot-01`) was made. +This did not include the requested change of making dot entries optional. + +The `phases/snapshot/docs.md` document was altered in subsequent years in +significant ways, often in lock-step with wasmtime or wasi-libc. In January +2022, `sock_accept` was added to `phases/snapshot/docs.md`, a document later +renamed to later renamed to `legacy/preview1/docs.md`. + +As a result, the ABI and behavior remained unstable: The `snapshot-01` tag was +not an effective basis of portability. A test suite was requested well before +this tag, in April 2019. Meanwhile, compliance had no meaning. Developers had +to track changes to the latest doc, while clarifying with wasi-libc or wasmtime +behavior. This lack of stability could have permitted a fix to the dot entries +problem, just as it permitted changes desired by other users. + +In November 2022, the wasi-testsuite project began and started solidifying +expectations. This quickly led to changes in runtimes and the spec doc. WASI +began importing tests from wasmtime as required behaviors for all runtimes. +Some changes implied changes to wasi-libc. For example, `readdir` began to +imply inode fan-outs, which caused performance regressions. Most notably a +test merged in January required dot entries. Tests were merged without running +against any runtime, and even when run ad-hoc only against Linux. Hence, +portability issues mentioned over three years earlier did not trigger any +failure until wazero (which tests Windows) noticed. + +In the same month, wazero requested to revert this change primarily because +Go does not return them from `os.ReadDir`, and materializing them is +complicated due to tests also requiring inodes. Moreover, they are discarded by +not just Go, but other common programming languages. This was rejected by the +WASI lead for preview1, but considered for the completely different ABI named +preview2. + +In February 2023, the WASI chair declared that new rule requiring preview1 to +return dot entries "was decided by the subgroup as a whole", citing meeting +notes. According to these notes, the WASI lead stated incorrectly that POSIX +conformance required returning dot entries, something it explicitly says are +optional. In other words, he said filtering them out would make Preview1 +non-conforming, and asked if anyone objects to this. The co-chair was noted to +say "Because there are existing P1 programs, we shouldn’t make changes like +this." No other were recorded to say anything. + +In summary, preview1 was changed retrospectively to require dot entries and +preview2 was changed to require their absence. This rule was reverse engineered +from wasmtime tests, and affirmed on two false premises: + +* POSIX compliance requires dot entries + * POSIX literally says these are optional +* WASI cannot make changes because there are existing P1 programs. + * Changes to Preview 1 happened before and after this topic. + +As of June 2023, wasi-testsuite still only runs on Linux, so compliance of this +rule on Windows is left to runtimes to decide to validate. The preview2 adapter +uses fake cookies zero and one to refer to dot dirents, uses a real inode for +the dot(".") entry and zero inode for dot-dot(".."). + +See https://github.com/WebAssembly/wasi-filesystem/issues/3 +See https://github.com/WebAssembly/WASI/tree/snapshot-01 +See https://github.com/WebAssembly/WASI/issues/9 +See https://github.com/WebAssembly/WASI/pull/458 +See https://github.com/WebAssembly/wasi-testsuite/pull/32 +See https://github.com/WebAssembly/wasi-libc/pull/345 +See https://github.com/WebAssembly/wasi-testsuite/issues/52 +See https://github.com/WebAssembly/WASI/pull/516 +See https://github.com/WebAssembly/meetings/blob/main/wasi/2023/WASI-02-09.md#should-preview1-fd_readdir-filter-out--and- +See https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L1026-L1041 + +### Why are dot (".") and dot-dot ("..") entries problematic? + +When reading a directory, dot (".") and dot-dot ("..") entries are problematic. +For example, Go does not return them from `os.ReadDir`, and materializing them +is complicated (at least dot-dot is). + +A directory entry has stat information in it. The stat information includes +inode which is used for comparing file equivalence. In the simple case of dot, +we could materialize a special entry to expose the same info as stat on the fd +would return. However, doing this and not doing dot-dot would cause confusion, +and dot-dot is far more tricky. To back-fill inode information about a parent +directory would be costly and subtle. For example, the pre-open (mount) of the +directory may be different than its logical parent. This is easy to understand +when considering the common case of mounting "/" and "/tmp" as pre-opens. To +implement ".." from "/tmp" requires information from a separate pre-open, this +includes state to even know the difference. There are easier edge cases as +well, such as the decision to not return ".." from a root path. In any case, +this should start to explain that faking entries when underlying stdlib doesn't +return them is tricky and requires quite a lot of state. + +Another issue is around the `Dirent.Off` value of a directory entry, sometimes +called a "cookie" in Linux man pagers. When the host operating system or +library function does not return dot entries, to support functions such as +`seekdir`, you still need a value for `Dirent.Off`. Naively, you can synthesize +these by choosing sequential offsets zero and one. However, POSIX strictly says +offsets should be treated opaquely. The backing filesystem could use these to +represent real entries. For example, a directory with one entry could use zero +as the `Dirent.Off` value. If you also used zero for the "." dirent, there +would be a clash. This means if you synthesize `Dirent.Off` for any entry, you +need to synthesize this value for all entries. In practice, the simplest way is +using an incrementing number, such as done in the WASI preview2 adapter. + +Working around these issues causes expense to all users of wazero, so we'd +then look to see if that would be justified or not. However, the most common +compilers involved in end user questions, as of early 2023 are TinyGo, Rust and +Zig. All of these compile code which ignores dot and dot-dot entries. In other +words, faking these entries would not only cost our codebase with complexity, +but it would also add unnecessary overhead as the values aren't commonly used. + +The final reason why we might do this, is an end users or a specification +requiring us to. As of early 2023, no end user has raised concern over Go and +by extension wazero not returning dot and dot-dot. The snapshot-01 spec of WASI +does not mention anything on this point. Also, POSIX has the following to say, +which summarizes to "these are optional" + +> The readdir() function shall not return directory entries containing empty names. If entries for dot or dot-dot exist, one entry shall be returned for dot and one entry shall be returned for dot-dot; otherwise, they shall not be returned. + +Unfortunately, as described above, the WASI project decided in early 2023 to +require dot entries in both the spec and the wasi-testsuite. For only this +reason, wazero adds overhead to synthesize dot entries despite it being +unnecessary for most users. + +See https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html +See https://github.com/golang/go/blob/go1.20/src/os/dir_unix.go#L108-L110 +See https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L1026-L1041 + +### Why don't we pre-populate an inode for the dot-dot ("..") entry? + +We only populate an inode for dot (".") because wasi-testsuite requires it, and +we likely already have it (because we cache it). We could attempt to populate +one for dot-dot (".."), but chose not to. + +Firstly, wasi-testsuite does not require the inode of dot-dot, possibly because +the wasip2 adapter doesn't populate it (but we don't really know why). + +The only other reason to populate it would be to avoid wasi-libc's stat fanout +when it is missing. However, wasi-libc explicitly doesn't fan-out to lstat on +the ".." entry on a zero ino. + +Fetching dot-dot's inode despite the above not only doesn't help wasi-libc, but +it also hurts languages that don't use it, such as Go. These languages would +pay a stat syscall penalty even if they don't need the inode. In fact, Go +discards both dot entries! + +In summary, there are no significant upsides in attempting to pre-fetch +dot-dot's inode, and there are downsides to doing it anyway. + +See + * https://github.com/WebAssembly/wasi-libc/blob/bd950eb128bff337153de217b11270f948d04bb4/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c#L87-L94 + * https://github.com/WebAssembly/wasi-testsuite/blob/main/tests/rust/src/bin/fd_readdir.rs#L108 + * https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L1037 + +### Why don't we require inodes to be non-zero? + +We don't require a non-zero value for `Dirent.Ino` because doing so can prevent +a real one from resolving later via `Stat_t.Ino`. + +We define `Ino` like `d_ino` in POSIX which doesn't special-case zero. It can +be zero for a few reasons: + +* The file is not a regular file or directory. +* The underlying filesystem does not support inodes. e.g. embed:fs +* A directory doesn't include inodes, but a later stat can. e.g. Windows +* The backend is based on wasi-filesystem (a.k.a wasip2), which has + `directory_entry.inode` optional, and might remove it entirely. + +There are other downsides to returning a zero inode in widely used compilers: + +* File equivalence utilities, like `os.SameFile` will not work. +* wasi-libc's `wasip1` mode will call `lstat` and attempt to retrieve a + non-zero value (unless the entry is named ".."). + +A new compiler may accidentally skip a `Dirent` with a zero `Ino` if emulating +a non-POSIX function and re-using `Dirent.Ino` for `d_fileno`. + +* Linux `getdents` doesn't define `d_fileno` must be non-zero +* BSD `getdirentries` is implementation specific. For example, OpenBSD will + return dirents with a zero `d_fileno`, but Darwin will skip them. + +The above shouldn't be a problem, even in the case of BSD, because `wasip1` is +defined more in terms of `getdents` than `getdirentries`. The bottom half of +either should treat `wasip1` (or any similar ABI such as wasix or wasip2) as a +different operating system and either use different logic that doesn't skip, or +synthesize a fake non-zero `d_fileno` when `d_ino` is zero. + +However, this has been a problem. Go's `syscall.ParseDirent` utility is shared +for all `GOOS=unix`. For simplicity, this abstracts `direntIno` with data from +`d_fileno` or `d_ino`, and drops if either are zero, even if `d_fileno` is the +only field with zero explicitly defined. This led to a change to special case +`GOOS=wasip1` as otherwise virtual files would be unconditionally skipped. + +In practice, this problem is rather unique due to so many compilers relying on +wasi-libc, which tolerates a zero inode. For example, while issues were +reported about the performance regression when wasi-libc began doing a fan-out +on zero `Dirent.Ino`, no issues were reported about dirents being dropped as a +result. + +In summary, rather than complicating implementation and forcing non-zero inodes +for a rare case, we permit zero. We instead document this topic thoroughly, so +that emerging compilers can re-use the research and reference it on conflict. +We also document that `Ino` should be non-zero, so that users implementing that +field will attempt to get it. + +See + * https://github.com/WebAssembly/wasi-filesystem/pull/81 + * https://github.com/WebAssembly/wasi-libc/blob/bd950eb128bff337153de217b11270f948d04bb4/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c#L87-L94 + * https://linux.die.net/man/3/getdents + * https://www.unix.com/man-page/osx/2/getdirentries/ + * https://man.openbsd.org/OpenBSD-5.4/getdirentries.2 + * https://github.com/golang/go/blob/go1.20/src/syscall/dirent.go#L60-L102 + * https://go-review.googlesource.com/c/go/+/507915 + +## sys.Walltime and Nanotime + +The `sys` package has two function types, `Walltime` and `Nanotime` for real +and monotonic clock exports. The naming matches conventions used in Go. + +```go +func time_now() (sec int64, nsec int32, mono int64) { + sec, nsec = walltime() + return sec, nsec, nanotime() +} +``` + +Splitting functions for wall and clock time allow implementations to choose +whether to implement the clock once (as in Go), or split them out. + +Each can be configured with a `ClockResolution`, although is it usually +incorrect as detailed in a sub-heading below. The only reason for exposing this +is to satisfy WASI: + +See https://github.com/WebAssembly/wasi-clocks + +### Why default to fake time? + +WebAssembly has an implicit design pattern of capabilities based security. By +defaulting to a fake time, we reduce the chance of timing attacks, at the cost +of requiring configuration to opt-into real clocks. + +See https://gruss.cc/files/fantastictimers.pdf for an example attacks. + +### Why does fake time increase on reading? + +Both the fake nanotime and walltime increase by 1ms on reading. Particularly in +the case of nanotime, this prevents spinning. + +### Why not `time.Clock`? + +wazero can't use `time.Clock` as a plugin for clock implementation as it is +only substitutable with build flags (`faketime`) and conflates wall and +monotonic time in the same call. + +Go's `time.Clock` was added monotonic time after the fact. For portability with +prior APIs, a decision was made to combine readings into the same API call. + +See https://go.googlesource.com/proposal/+/master/design/12914-monotonic.md + +WebAssembly time imports do not have the same concern. In fact even Go's +imports for clocks split walltime from nanotime readings. + +See https://github.com/golang/go/blob/go1.20/misc/wasm/wasm_exec.js#L243-L255 + +Finally, Go's clock is not an interface. WebAssembly users who want determinism +or security need to be able to substitute an alternative clock implementation +from the host process one. + +### `ClockResolution` + +A clock's resolution is hardware and OS dependent so requires a system call to retrieve an accurate value. +Go does not provide a function for getting resolution, so without CGO we don't have an easy way to get an actual +value. For now, we return fixed values of 1us for realtime and 1ns for monotonic, assuming that realtime clocks are +often lower precision than monotonic clocks. In the future, this could be improved by having OS+arch specific assembly +to make syscalls. + +For example, Go implements time.Now for linux-amd64 with this [assembly](https://github.com/golang/go/blob/go1.20/src/runtime/time_linux_amd64.s). +Because retrieving resolution is not generally called often, unlike getting time, it could be appropriate to only +implement the fallback logic that does not use VDSO (executing syscalls in user mode). The syscall for clock_getres +is 229 and should be usable. https://pkg.go.dev/syscall#pkg-constants. + +If implementing similar for Windows, [mingw](https://github.com/mirror/mingw-w64/blob/6a0e9165008f731bccadfc41a59719cf7c8efc02/mingw-w64-libraries/winpthreads/src/clock.c#L77 +) is often a good source to find the Windows API calls that correspond +to a POSIX method. + +Writing assembly would allow making syscalls without CGO, but comes with the cost that it will require implementations +across many combinations of OS and architecture. + +## sys.Nanosleep + +All major programming languages have a `sleep` mechanism to block for a +duration. Sleep is typically implemented by a WASI `poll_oneoff` relative clock +subscription. + +For example, the below ends up calling `wasi_snapshot_preview1.poll_oneoff`: + +```zig +const std = @import("std"); +pub fn main() !void { + std.time.sleep(std.time.ns_per_s * 5); +} +``` + +Besides Zig, this is also the case with TinyGo (`-target=wasi`) and Rust +(`--target wasm32-wasi`). + +We decided to expose `sys.Nanosleep` to allow overriding the implementation +used in the common case, even if it isn't used by Go, because this gives an +easy and efficient closure over a common program function. We also documented +`sys.Nanotime` to warn users that some compilers don't optimize sleep. + +## sys.Osyield + +We expose `sys.Osyield`, to allow users to control the behavior of WASI's +`sched_yield` without a new build of wazero. This is mainly for parity with +all other related features which we allow users to implement, including +`sys.Nanosleep`. Unlike others, we don't provide an out-of-box implementation +primarily because it will cause performance problems when accessed. + +For example, the below implementation uses CGO, which might result in a 1us +delay per invocation depending on the platform. + +See https://github.com/golang/go/issues/19409#issuecomment-284788196 +```go +//go:noescape +//go:linkname osyield runtime.osyield +func osyield() +``` + +In practice, a request to customize this is unlikely to happen until other +thread based functions are implemented. That said, as of early 2023, there are +a few signs of implementation interest and cross-referencing: + +See https://github.com/WebAssembly/stack-switching/discussions/38 +See https://github.com/WebAssembly/wasi-threads#what-can-be-skipped +See https://slinkydeveloper.com/Kubernetes-controllers-A-New-Hope/ + +## sys.Stat_t + +We expose `stat` information as `sys.Stat_t`, like `syscall.Stat_t` except +defined without build constraints. For example, you can use `sys.Stat_t` on +`GOOS=windows` which doesn't define `syscall.Stat_t`. + +The first use case of this is to return inodes from `fs.FileInfo` without +relying on platform-specifics. For example, a user could return `*sys.Stat_t` +from `info.Sys()` and define a non-zero inode for a virtual file, or map a +real inode to a virtual one. + +Notable choices per field are listed below, where `sys.Stat_t` is unlike +`syscall.Stat_t` on `GOOS=linux`, or needs clarification. One common issue +not repeated below is that numeric fields are 64-bit when at least one platform +defines it that large. Also, zero values are equivalent to nil or absent. + +* `Dev` and `Ino` (`Inode`) are both defined unsigned as they are defined + opaque, and most `syscall.Stat_t` also defined them unsigned. There are + separate sections in this document discussing the impact of zero in `Ino`. +* `Mode` is defined as a `fs.FileMode` even though that is not defined in POSIX + and will not map to all possible values. This is because the current use is + WASI, which doesn't define any types or features not already supported. By + using `fs.FileMode`, we can re-use routine experience in Go. +* `NLink` is unsigned because it is defined that way in `syscall.Stat_t`: there + can never be less than zero links to a file. We suggest defaulting to 1 in + conversions when information is not knowable because at least that many links + exist. +* `Size` is signed because it is defined that way in `syscall.Stat_t`: while + regular files and directories will always be non-negative, irregular files + are possibly negative or not defined. Notably sparse files are known to + return negative values. +* `Atim`, `Mtim` and `Ctim` are signed because they are defined that way in + `syscall.Stat_t`: Negative values are time before 1970. The resolution is + nanosecond because that's the maximum resolution currently supported in Go. + +### Why do we use `sys.EpochNanos` instead of `time.Time` or similar? + +To simplify documentation, we defined a type alias `sys.EpochNanos` for int64. +`time.Time` is a data structure, and we could have used this for +`syscall.Stat_t` time values. The most important reason we do not is conversion +penalty deriving time from common types. + +The most common ABI used in `wasip2`. This, and compatible ABI such as `wasix`, +encode timestamps in memory as a 64-bit number. If we used `time.Time`, we +would have to convert an underlying type like `syscall.Timespec` to `time.Time` +only to later have to call `.UnixNano()` to convert it back to a 64-bit number. + +In the future, the component model module "wasi-filesystem" may represent stat +timestamps with a type shared with "wasi-clocks", abstractly structured similar +to `time.Time`. However, component model intentionally does not define an ABI. +It is likely that the canonical ABI for timestamp will be in two parts, but it +is not required for it to be intermediately represented this way. A utility +like `syscall.NsecToTimespec` could split an int64 so that it could be written +to memory as 96 bytes (int64, int32), without allocating a struct. + +Finally, some may confuse epoch nanoseconds with 32-bit epoch seconds. While +32-bit epoch seconds has "The year 2038" problem, epoch nanoseconds has +"The Year 2262" problem, which is even less concerning for this library. If +the Go programming language and wazero exist in the 2200's, we can make a major +version increment to adjust the `sys.EpochNanos` approach. Meanwhile, we have +faster code. + +## poll_oneoff + +`poll_oneoff` is a WASI API for waiting for I/O events on multiple handles. +It is conceptually similar to the POSIX `poll(2)` syscall. +The name is not `poll`, because it references [“the fact that this function is not efficient +when used repeatedly with the same large set of handles”][poll_oneoff]. + +We chose to support this API in a handful of cases that work for regular files +and standard input. We currently do not support other types of file descriptors such +as socket handles. + +### Clock Subscriptions + +As detailed above in [sys.Nanosleep](#sysnanosleep), `poll_oneoff` handles +relative clock subscriptions. In our implementation we use `sys.Nanosleep()` +for this purpose in most cases, except when polling for interactive input +from `os.Stdin` (see more details below). + +### FdRead and FdWrite Subscriptions + +When subscribing a file descriptor (except `Stdin`) for reads or writes, +the implementation will generally return immediately with success, unless +the file descriptor is unknown. The file descriptor is not checked further +for new incoming data. Any timeout is cancelled, and the API call is able +to return, unless there are subscriptions to `Stdin`: these are handled +separately. + +### FdRead and FdWrite Subscription to Stdin + +Subscribing `Stdin` for reads (writes make no sense and cause an error), +requires extra care: wazero allows to configure a custom reader for `Stdin`. + +In general, if a custom reader is found, the behavior will be the same +as for regular file descriptors: data is assumed to be present and +a success is written back to the result buffer. + +However, if the reader is detected to read from `os.Stdin`, +a special code path is followed, invoking `sysfs.poll()`. + +`sysfs.poll()` is a wrapper for `poll(2)` on POSIX systems, +and it is emulated on Windows. + +### Poll on POSIX + +On POSIX systems, `poll(2)` allows to wait for incoming data on a file +descriptor, and block until either data becomes available or the timeout +expires. + +Usage of `syfs.poll()` is currently only reserved for standard input, because + +1. it is really only necessary to handle interactive input: otherwise, + there is no way in Go to peek from Standard Input without actually + reading (and thus consuming) from it; + +2. if `Stdin` is connected to a pipe, it is ok in most cases to return + with success immediately; + +3. `syfs.poll()` is currently a blocking call, irrespective of goroutines, + because the underlying syscall is; thus, it is better to limit its usage. + +So, if the subscription is for `os.Stdin` and the handle is detected +to correspond to an interactive session, then `sysfs.poll()` will be +invoked with a the `Stdin` handle *and* the timeout. + +This also means that in this specific case, the timeout is uninterruptible, +unless data becomes available on `Stdin` itself. + +### Select on Windows + +On Windows `sysfs.poll()` cannot be delegated to a single +syscall, because there is no single syscall to handle sockets, +pipes and regular files. + +Instead, we emulate its behavior for the cases that are currently +of interest. + +- For regular files, we _always_ report them as ready, as +[most operating systems do anyway][async-io-windows]. + +- For pipes, we invoke [`PeekNamedPipe`][peeknamedpipe] +for each file handle we detect is a pipe open for reading. +We currently ignore pipes open for writing. + +- Notably, we include also support for sockets using the [WinSock +implementation of `poll`][wsapoll], but instead +of relying on the timeout argument of the `WSAPoll` function, +we set a 0-duration timeout so that it behaves like a peek. + +This way, we can check for regular files all at once, +at the beginning of the function, then we poll pipes and +sockets periodically using a cancellable `time.Tick`, +which plays nicely with the rest of the Go runtime. + +### Impact of blocking + +Because this is a blocking syscall, it will also block the carrier thread of +the goroutine, preventing any means to support context cancellation directly. + +There are ways to obviate this issue. We outline here one idea, that is however +not currently implemented. A common approach to support context cancellation is +to add a signal file descriptor to the set, e.g. the read-end of a pipe or an +eventfd on Linux. When the context is canceled, we may unblock a Select call by +writing to the fd, causing it to return immediately. This however requires to +do a bit of housekeeping to hide the "special" FD from the end-user. + +[poll_oneoff]: https://github.com/WebAssembly/wasi-poll#why-is-the-function-called-poll_oneoff +[async-io-windows]: https://tinyclouds.org/iocp_links +[peeknamedpipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe +[wsapoll]: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll + +## Signed encoding of integer global constant initializers + +wazero treats integer global constant initializers signed as their interpretation is not known at declaration time. For +example, there is no signed integer [value type](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#value-types%E2%91%A0). + +To get at the problem, let's use an example. +``` +(global (export "start_epoch") i64 (i64.const 1620216263544)) +``` + +In both signed and unsigned LEB128 encoding, this value is the same bit pattern. The problem is that some numbers are +not. For example, 16256 is `807f` encoded as unsigned, but `80ff00` encoded as signed. + +While the specification mentions uninterpreted integers are in abstract [unsigned values](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#integers%E2%91%A0), +the binary encoding is clear that they are encoded [signed](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#integers%E2%91%A4). + +For consistency, we go with signed encoding in the special case of global constant initializers. + +## Implementation limitations + +WebAssembly 1.0 (20191205) specification allows runtimes to [limit certain aspects of Wasm module or execution](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#a2-implementation-limitations). + +wazero limitations are imposed pragmatically and described below. + +### Number of functions in a module + +The possible number of function instances in [a module](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#module-instances%E2%91%A0) is not specified in the WebAssembly specifications since [`funcaddr`](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-funcaddr) corresponding to a function instance in a store can be arbitrary number. +wazero limits the maximum function instances to 2^27 as even that number would occupy 1GB in function pointers. + +That is because not only we _believe_ that all use cases are fine with the limitation, but also we have no way to test wazero runtimes under these unusual circumstances. + +### Number of function types in a store + +There's no limitation on the number of function types in [a store](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#store%E2%91%A0) according to the spec. In wazero implementation, we assign each function type to a unique ID, and choose to use `uint32` to represent the IDs. +Therefore the maximum number of function types a store can have is limited to 2^27 as even that number would occupy 512MB just to reference the function types. + +This is due to the same reason for the limitation on the number of functions above. + +### Number of values on the stack in a function + +While the the spec does not clarify a limitation of function stack values, wazero limits this to 2^27 = 134,217,728. +The reason is that we internally represent all the values as 64-bit integers regardless of its types (including f32, f64), and 2^27 values means +1 GiB = (2^30). 1 GiB is the reasonable for most applications [as we see a Goroutine has 250 MB as a limit on the stack for 32-bit arch](https://github.com/golang/go/blob/go1.20/src/runtime/proc.go#L152-L159), considering that WebAssembly is (currently) 32-bit environment. + +All the functions are statically analyzed at module instantiation phase, and if a function can potentially reach this limit, an error is returned. + +### Number of globals in a module + +Theoretically, a module can declare globals (including imports) up to 2^32 times. However, wazero limits this to 2^27(134,217,728) per module. +That is because internally we store globals in a slice with pointer types (meaning 8 bytes on 64-bit platforms), and therefore 2^27 globals +means that we have 1 GiB size of slice which seems large enough for most applications. + +### Number of tables in a module + +While the the spec says that a module can have up to 2^32 tables, wazero limits this to 2^27 = 134,217,728. +One of the reasons is even that number would occupy 1GB in the pointers tables alone. Not only that, we access tables slice by +table index by using 32-bit signed offset in the compiler implementation, which means that the table index of 2^27 can reach 2^27 * 8 (pointer size on 64-bit machines) = 2^30 offsets in bytes. + +We _believe_ that all use cases are fine with the limitation, but also note that we have no way to test wazero runtimes under these unusual circumstances. + +If a module reaches this limit, an error is returned at the compilation phase. + +## Compiler engine implementation + +### Why it's safe to execute runtime-generated machine codes against async Goroutine preemption + +Goroutine preemption is the mechanism of the Go runtime to switch goroutines contexts on an OS thread. +There are two types of preemption: cooperative preemption and async preemption. The former happens, for example, +when making a function call, and it is not an issue for our runtime-generated functions as they do not make +direct function calls to Go-implemented functions. On the other hand, the latter, async preemption, can be problematic +since it tries to interrupt the execution of Goroutine at any point of function, and manipulates CPU register states. + +Fortunately, our runtime-generated machine codes do not need to take the async preemption into account. +All the assembly codes are entered via the trampoline implemented as Go Assembler Function (e.g. [arch_amd64.s](./arch_amd64.s)), +and as of Go 1.20, these assembler functions are considered as _unsafe_ for async preemption: +- https://github.com/golang/go/blob/go1.20rc1/src/runtime/preempt.go#L406-L407 +- https://github.com/golang/go/blob/9f0234214473dfb785a5ad84a8fc62a6a395cbc3/src/runtime/traceback.go#L227 + +From the Go runtime point of view, the execution of runtime-generated machine codes is considered as a part of +that trampoline function. Therefore, runtime-generated machine code is also correctly considered unsafe for async preemption. + +## Why context cancellation is handled in Go code rather than native code + +Since [wazero v1.0.0-pre.9](https://github.com/tetratelabs/wazero/releases/tag/v1.0.0-pre.9), the runtime +supports integration with Go contexts to interrupt execution after a timeout, or in response to explicit cancellation. +This support is internally implemented as a special opcode `builtinFunctionCheckExitCode` that triggers the execution of +a Go function (`ModuleInstance.FailIfClosed`) that atomically checks a sentinel value at strategic points in the code. + +[It _is indeed_ possible to check the sentinel value directly, without leaving the native world][native_check], thus sparing some cycles; +however, because native code never preempts (see section above), this may lead to a state where the other goroutines +never get the chance to run, and thus never get the chance to set the sentinel value; effectively preventing +cancellation from taking place. + +[native_check]: https://github.com/tetratelabs/wazero/issues/1409 + +## Golang patterns + +### Hammer tests +Code that uses concurrency primitives, such as locks or atomics, should include "hammer tests", which run large loops +inside a bounded amount of goroutines, run by half that many `GOMAXPROCS`. These are named consistently "hammer", so +they are easy to find. The name inherits from some existing tests in [golang/go](https://github.com/golang/go/search?q=hammer&type=code). + +Here is an annotated description of the key pieces of a hammer test: +1. `P` declares the count of goroutines to use, defaulting to 8 or 4 if `testing.Short`. + * Half this amount are the cores used, and 4 is less than a modern laptop's CPU. This allows multiple "hammer" tests to run in parallel. +2. `N` declares the scale of work (loop) per goroutine, defaulting to value that finishes in ~0.1s on a modern laptop. + * When in doubt, try 1000 or 100 if `testing.Short` + * Remember, there are multiple hammer tests and CI nodes are slow. Slower tests hurt feedback loops. +3. `defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P/2))` makes goroutines switch cores, testing visibility of shared data. +4. To ensure goroutines execute at the same time, block them with `sync.WaitGroup`, initialized to `Add(P)`. + * `sync.WaitGroup` internally uses `runtime_Semacquire` not available in any other library. + * `sync.WaitGroup.Add` with a negative value can unblock many goroutines at the same time, e.g. without a for loop. +5. Track goroutines progress via `finished := make(chan int)` where each goroutine in `P` defers `finished <- 1`. + 1. Tests use `require.XXX`, so `recover()` into `t.Fail` in a `defer` function before `finished <- 1`. + * This makes it easier to spot larger concurrency problems as you see each failure, not just the first. + 2. After the `defer` function, await unblocked, then run the stateful function `N` times in a normal loop. + * This loop should trigger shared state problems as locks or atomics are contended by `P` goroutines. +6. After all `P` goroutines launch, atomically release all of them with `WaitGroup.Add(-P)`. +7. Block the runner on goroutine completion, by (`<-finished`) for each `P`. +8. When all goroutines complete, `return` if `t.Failed()`, otherwise perform follow-up state checks. + +This is implemented in wazero in [hammer.go](internal/testing/hammer/hammer.go) + +### Lock-free, cross-goroutine observations of updates + +How to achieve cross-goroutine reads of a variable are not explicitly defined in https://go.dev/ref/mem. wazero uses +atomics to implement this following unofficial practice. For example, a `Close` operation can be guarded to happen only +once via compare-and-swap (CAS) against a zero value. When we use this pattern, we consistently use atomics to both +read and update the same numeric field. + +In lieu of formal documentation, we infer this pattern works from other sources (besides tests): + * `sync.WaitGroup` by definition must support calling `Add` from other goroutines. Internally, it uses atomics. + * rsc in golang/go#5045 writes "atomics guarantee sequential consistency among the atomic variables". + +See https://github.com/golang/go/blob/go1.20/src/sync/waitgroup.go#L64 +See https://github.com/golang/go/issues/5045#issuecomment-252730563 +See https://www.youtube.com/watch?v=VmrEG-3bWyM diff --git a/vendor/github.com/tetratelabs/wazero/README.md b/vendor/github.com/tetratelabs/wazero/README.md new file mode 100644 index 00000000..e49fcb8a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/README.md @@ -0,0 +1,139 @@ +# wazero: the zero dependency WebAssembly runtime for Go developers + +[![Go Reference](https://pkg.go.dev/badge/github.com/tetratelabs/wazero.svg)](https://pkg.go.dev/github.com/tetratelabs/wazero) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +WebAssembly is a way to safely run code compiled in other languages. Runtimes +execute WebAssembly Modules (Wasm), which are most often binaries with a `.wasm` +extension. + +wazero is a WebAssembly Core Specification [1.0][1] and [2.0][2] compliant +runtime written in Go. It has *zero dependencies*, and doesn't rely on CGO. +This means you can run applications in other languages and still keep cross +compilation. + +Import wazero and extend your Go application with code written in any language! + +## Example + +The best way to learn wazero is by trying one of our [examples](examples/README.md). The +most [basic example](examples/basic) extends a Go application with an addition +function defined in WebAssembly. + +## Runtime + +There are two runtime configurations supported in wazero: _Compiler_ is default: + +By default, ex `wazero.NewRuntime(ctx)`, the Compiler is used if supported. You +can also force the interpreter like so: +```go +r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter()) +``` + +### Interpreter +Interpreter is a naive interpreter-based implementation of Wasm virtual +machine. Its implementation doesn't have any platform (GOARCH, GOOS) specific +code, therefore _interpreter_ can be used for any compilation target available +for Go (such as `riscv64`). + +### Compiler +Compiler compiles WebAssembly modules into machine code ahead of time (AOT), +during `Runtime.CompileModule`. This means your WebAssembly functions execute +natively at runtime. Compiler is faster than Interpreter, often by order of +magnitude (10x) or more. This is done without host-specific dependencies. + +### Conformance + +Both runtimes pass WebAssembly Core [1.0][7] and [2.0][14] specification tests +on supported platforms: + +| Runtime | Usage | amd64 | arm64 | others | +|:-----------:|:--------------------------------------:|:-----:|:-----:|:------:| +| Interpreter | `wazero.NewRuntimeConfigInterpreter()` | ✅ | ✅ | ✅ | +| Compiler | `wazero.NewRuntimeConfigCompiler()` | ✅ | ✅ | ❌ | + +## Support Policy + +The below support policy focuses on compatibility concerns of those embedding +wazero into their Go applications. + +### wazero + +wazero's [1.0 release][15] happened in March 2023, and is [in use][16] by many +projects and production sites. + +We offer an API stability promise with semantic versioning. In other words, we +promise to not break any exported function signature without incrementing the +major version. This does not mean no innovation: New features and behaviors +happen with a minor version increment, e.g. 1.0.11 to 1.2.0. We also fix bugs +or change internal details with a patch version, e.g. 1.0.0 to 1.0.1. + +You can get the latest version of wazero like this. +```bash +go get github.com/tetratelabs/wazero@latest +``` + +Please give us a [star][17] if you end up using wazero! + +### Go + +wazero has no dependencies except Go, so the only source of conflict in your +project's use of wazero is the Go version. + +wazero follows the same version policy as Go's [Release Policy][10]: two +versions. wazero will ensure these versions work and bugs are valid if there's +an issue with a current Go version. + +Additionally, wazero intentionally delays usage of language or standard library +features one additional version. For example, when Go 1.29 is released, wazero +can use language features or standard libraries added in 1.27. This is a +convenience for embedders who have a slower version policy than Go. However, +only supported Go versions may be used to raise support issues. + +### Platform + +wazero has two runtime modes: Interpreter and Compiler. The only supported operating +systems are ones we test, but that doesn't necessarily mean other operating +system versions won't work. + +We currently test Linux (Ubuntu and scratch), MacOS and Windows as packaged by +[GitHub Actions][11], as well as nested VMs running on Linux for FreeBSD, NetBSD, +OpenBSD, DragonFly BSD, illumos and Solaris. + +We also test cross compilation for many `GOOS` and `GOARCH` combinations. + +* Interpreter + * Linux is tested on amd64 (native) as well arm64 and riscv64 via emulation. + * Windows, FreeBSD, NetBSD, OpenBSD, DragonFly BSD, illumos and Solaris are + tested only on amd64. + * macOS is tested only on arm64. +* Compiler + * Linux is tested on amd64 (native) as well arm64 via emulation. + * Windows, FreeBSD, NetBSD, DragonFly BSD, illumos and Solaris are + tested only on amd64. + * macOS is tested only on arm64. + +wazero has no dependencies and doesn't require CGO. This means it can also be +embedded in an application that doesn't use an operating system. This is a main +differentiator between wazero and alternatives. + +We verify zero dependencies by running tests in Docker's [scratch image][12]. +This approach ensures compatibility with any parent image. + +----- +wazero is a registered trademark of Tetrate.io, Inc. in the United States and/or other countries + +[1]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/ +[2]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/ +[4]: https://github.com/WebAssembly/meetings/blob/main/process/subgroups.md +[5]: https://github.com/WebAssembly/WASI +[6]: https://pkg.go.dev/golang.org/x/sys/unix +[7]: https://github.com/WebAssembly/spec/tree/wg-1.0/test/core +[9]: https://github.com/tetratelabs/wazero/issues/506 +[10]: https://go.dev/doc/devel/release +[11]: https://github.com/actions/virtual-environments +[12]: https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch +[13]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md +[14]: https://github.com/WebAssembly/spec/tree/d39195773112a22b245ffbe864bab6d1182ccb06/test/core +[15]: https://tetrate.io/blog/introducing-wazero-from-tetrate/ +[16]: https://wazero.io/community/users/ +[17]: https://github.com/tetratelabs/wazero/stargazers diff --git a/vendor/github.com/tetratelabs/wazero/api/features.go b/vendor/github.com/tetratelabs/wazero/api/features.go new file mode 100644 index 00000000..c739d3bf --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/api/features.go @@ -0,0 +1,214 @@ +package api + +import ( + "fmt" + "strings" +) + +// CoreFeatures is a bit flag of WebAssembly Core specification features. See +// https://github.com/WebAssembly/proposals for proposals and their status. +// +// Constants define individual features, such as CoreFeatureMultiValue, or +// groups of "finished" features, assigned to a WebAssembly Core Specification +// version, e.g. CoreFeaturesV1 or CoreFeaturesV2. +// +// Note: Numeric values are not intended to be interpreted except as bit flags. +type CoreFeatures uint64 + +// CoreFeaturesV1 are features included in the WebAssembly Core Specification +// 1.0. As of late 2022, this is the only version that is a Web Standard (W3C +// Recommendation). +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/ +const CoreFeaturesV1 = CoreFeatureMutableGlobal + +// CoreFeaturesV2 are features included in the WebAssembly Core Specification +// 2.0 (20220419). As of late 2022, version 2.0 is a W3C working draft, not yet +// a Web Standard (W3C Recommendation). +// +// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#release-1-1 +const CoreFeaturesV2 = CoreFeaturesV1 | + CoreFeatureBulkMemoryOperations | + CoreFeatureMultiValue | + CoreFeatureNonTrappingFloatToIntConversion | + CoreFeatureReferenceTypes | + CoreFeatureSignExtensionOps | + CoreFeatureSIMD + +const ( + // CoreFeatureBulkMemoryOperations adds instructions modify ranges of + // memory or table entries ("bulk-memory-operations"). This is included in + // CoreFeaturesV2, but not CoreFeaturesV1. + // + // Here are the notable effects: + // - Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop` + // instructions. + // - Adds `table.init`, `table.copy` and `elem.drop` instructions. + // - Introduces a "passive" form of element and data segments. + // - Stops checking "active" element and data segment boundaries at + // compile-time, meaning they can error at runtime. + // + // Note: "bulk-memory-operations" is mixed with the "reference-types" + // proposal due to the WebAssembly Working Group merging them + // "mutually dependent". Therefore, enabling this feature requires enabling + // CoreFeatureReferenceTypes, and vice-versa. + // + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and + // https://github.com/WebAssembly/spec/pull/1287 + CoreFeatureBulkMemoryOperations CoreFeatures = 1 << iota + + // CoreFeatureMultiValue enables multiple values ("multi-value"). This is + // included in CoreFeaturesV2, but not CoreFeaturesV1. + // + // Here are the notable effects: + // - Function (`func`) types allow more than one result. + // - Block types (`block`, `loop` and `if`) can be arbitrary function + // types. + // + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md + CoreFeatureMultiValue + + // CoreFeatureMutableGlobal allows globals to be mutable. This is included + // in both CoreFeaturesV1 and CoreFeaturesV2. + // + // When false, an api.Global can never be cast to an api.MutableGlobal, and + // any wasm that includes global vars will fail to parse. + CoreFeatureMutableGlobal + + // CoreFeatureNonTrappingFloatToIntConversion enables non-trapping + // float-to-int conversions ("nontrapping-float-to-int-conversion"). This + // is included in CoreFeaturesV2, but not CoreFeaturesV1. + // + // The only effect of enabling is allowing the following instructions, + // which return 0 on NaN instead of panicking. + // - `i32.trunc_sat_f32_s` + // - `i32.trunc_sat_f32_u` + // - `i32.trunc_sat_f64_s` + // - `i32.trunc_sat_f64_u` + // - `i64.trunc_sat_f32_s` + // - `i64.trunc_sat_f32_u` + // - `i64.trunc_sat_f64_s` + // - `i64.trunc_sat_f64_u` + // + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md + CoreFeatureNonTrappingFloatToIntConversion + + // CoreFeatureReferenceTypes enables various instructions and features + // related to table and new reference types. This is included in + // CoreFeaturesV2, but not CoreFeaturesV1. + // + // - Introduction of new value types: `funcref` and `externref`. + // - Support for the following new instructions: + // - `ref.null` + // - `ref.func` + // - `ref.is_null` + // - `table.fill` + // - `table.get` + // - `table.grow` + // - `table.set` + // - `table.size` + // - Support for multiple tables per module: + // - `call_indirect`, `table.init`, `table.copy` and `elem.drop` + // - Support for instructions can take non-zero table index. + // - Element segments can take non-zero table index. + // + // Note: "reference-types" is mixed with the "bulk-memory-operations" + // proposal due to the WebAssembly Working Group merging them + // "mutually dependent". Therefore, enabling this feature requires enabling + // CoreFeatureBulkMemoryOperations, and vice-versa. + // + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and + // https://github.com/WebAssembly/spec/pull/1287 + CoreFeatureReferenceTypes + + // CoreFeatureSignExtensionOps enables sign extension instructions + // ("sign-extension-ops"). This is included in CoreFeaturesV2, but not + // CoreFeaturesV1. + // + // Adds instructions: + // - `i32.extend8_s` + // - `i32.extend16_s` + // - `i64.extend8_s` + // - `i64.extend16_s` + // - `i64.extend32_s` + // + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md + CoreFeatureSignExtensionOps + + // CoreFeatureSIMD enables the vector value type and vector instructions + // (aka SIMD). This is included in CoreFeaturesV2, but not CoreFeaturesV1. + // + // Note: The instruction list is too long to enumerate in godoc. + // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md + CoreFeatureSIMD + + // Update experimental/features.go when adding elements here. +) + +// SetEnabled enables or disables the feature or group of features. +func (f CoreFeatures) SetEnabled(feature CoreFeatures, val bool) CoreFeatures { + if val { + return f | feature + } + return f &^ feature +} + +// IsEnabled returns true if the feature (or group of features) is enabled. +func (f CoreFeatures) IsEnabled(feature CoreFeatures) bool { + return f&feature != 0 +} + +// RequireEnabled returns an error if the feature (or group of features) is not +// enabled. +func (f CoreFeatures) RequireEnabled(feature CoreFeatures) error { + if f&feature == 0 { + return fmt.Errorf("feature %q is disabled", feature) + } + return nil +} + +// String implements fmt.Stringer by returning each enabled feature. +func (f CoreFeatures) String() string { + var builder strings.Builder + for i := 0; i <= 63; i++ { // cycle through all bits to reduce code and maintenance + target := CoreFeatures(1 << i) + if f.IsEnabled(target) { + if name := featureName(target); name != "" { + if builder.Len() > 0 { + builder.WriteByte('|') + } + builder.WriteString(name) + } + } + } + return builder.String() +} + +func featureName(f CoreFeatures) string { + switch f { + case CoreFeatureMutableGlobal: + // match https://github.com/WebAssembly/mutable-global + return "mutable-global" + case CoreFeatureSignExtensionOps: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md + return "sign-extension-ops" + case CoreFeatureMultiValue: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md + return "multi-value" + case CoreFeatureNonTrappingFloatToIntConversion: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md + return "nontrapping-float-to-int-conversion" + case CoreFeatureBulkMemoryOperations: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md + return "bulk-memory-operations" + case CoreFeatureReferenceTypes: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md + return "reference-types" + case CoreFeatureSIMD: + // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md + return "simd" + } + return "" +} diff --git a/vendor/github.com/tetratelabs/wazero/api/wasm.go b/vendor/github.com/tetratelabs/wazero/api/wasm.go new file mode 100644 index 00000000..d99c1a75 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/api/wasm.go @@ -0,0 +1,766 @@ +// Package api includes constants and interfaces used by both end-users and internal implementations. +package api + +import ( + "context" + "fmt" + "math" + + "github.com/tetratelabs/wazero/internal/internalapi" +) + +// ExternType classifies imports and exports with their respective types. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#external-types%E2%91%A0 +type ExternType = byte + +const ( + ExternTypeFunc ExternType = 0x00 + ExternTypeTable ExternType = 0x01 + ExternTypeMemory ExternType = 0x02 + ExternTypeGlobal ExternType = 0x03 +) + +// The below are exported to consolidate parsing behavior for external types. +const ( + // ExternTypeFuncName is the name of the WebAssembly 1.0 (20191205) Text Format field for ExternTypeFunc. + ExternTypeFuncName = "func" + // ExternTypeTableName is the name of the WebAssembly 1.0 (20191205) Text Format field for ExternTypeTable. + ExternTypeTableName = "table" + // ExternTypeMemoryName is the name of the WebAssembly 1.0 (20191205) Text Format field for ExternTypeMemory. + ExternTypeMemoryName = "memory" + // ExternTypeGlobalName is the name of the WebAssembly 1.0 (20191205) Text Format field for ExternTypeGlobal. + ExternTypeGlobalName = "global" +) + +// ExternTypeName returns the name of the WebAssembly 1.0 (20191205) Text Format field of the given type. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A4 +func ExternTypeName(et ExternType) string { + switch et { + case ExternTypeFunc: + return ExternTypeFuncName + case ExternTypeTable: + return ExternTypeTableName + case ExternTypeMemory: + return ExternTypeMemoryName + case ExternTypeGlobal: + return ExternTypeGlobalName + } + return fmt.Sprintf("%#x", et) +} + +// ValueType describes a parameter or result type mapped to a WebAssembly +// function signature. +// +// The following describes how to convert between Wasm and Golang types: +// +// - ValueTypeI32 - EncodeU32 DecodeU32 for uint32 / EncodeI32 DecodeI32 for int32 +// - ValueTypeI64 - uint64(int64) +// - ValueTypeF32 - EncodeF32 DecodeF32 from float32 +// - ValueTypeF64 - EncodeF64 DecodeF64 from float64 +// - ValueTypeExternref - unintptr(unsafe.Pointer(p)) where p is any pointer +// type in Go (e.g. *string) +// +// e.g. Given a Text Format type use (param i64) (result i64), no conversion is +// necessary. +// +// results, _ := fn(ctx, input) +// result := result[0] +// +// e.g. Given a Text Format type use (param f64) (result f64), conversion is +// necessary. +// +// results, _ := fn(ctx, api.EncodeF64(input)) +// result := api.DecodeF64(result[0]) +// +// Note: This is a type alias as it is easier to encode and decode in the +// binary format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-valtype +type ValueType = byte + +const ( + // ValueTypeI32 is a 32-bit integer. + ValueTypeI32 ValueType = 0x7f + // ValueTypeI64 is a 64-bit integer. + ValueTypeI64 ValueType = 0x7e + // ValueTypeF32 is a 32-bit floating point number. + ValueTypeF32 ValueType = 0x7d + // ValueTypeF64 is a 64-bit floating point number. + ValueTypeF64 ValueType = 0x7c + + // ValueTypeExternref is a externref type. + // + // Note: in wazero, externref type value are opaque raw 64-bit pointers, + // and the ValueTypeExternref type in the signature will be translated as + // uintptr in wazero's API level. + // + // For example, given the import function: + // (func (import "env" "f") (param externref) (result externref)) + // + // This can be defined in Go as: + // r.NewHostModuleBuilder("env"). + // NewFunctionBuilder(). + // WithFunc(func(context.Context, _ uintptr) (_ uintptr) { return }). + // Export("f") + // + // Note: The usage of this type is toggled with api.CoreFeatureBulkMemoryOperations. + ValueTypeExternref ValueType = 0x6f +) + +// ValueTypeName returns the type name of the given ValueType as a string. +// These type names match the names used in the WebAssembly text format. +// +// Note: This returns "unknown", if an undefined ValueType value is passed. +func ValueTypeName(t ValueType) string { + switch t { + case ValueTypeI32: + return "i32" + case ValueTypeI64: + return "i64" + case ValueTypeF32: + return "f32" + case ValueTypeF64: + return "f64" + case ValueTypeExternref: + return "externref" + } + return "unknown" +} + +// Module is a sandboxed, ready to execute Wasm module. This can be used to get exported functions, etc. +// +// In WebAssembly terminology, this corresponds to a "Module Instance", but wazero calls pre-instantiation module as +// "Compiled Module" as in wazero.CompiledModule, therefore we call this post-instantiation module simply "Module". +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#module-instances%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - Closing the wazero.Runtime closes any Module it instantiated. +type Module interface { + fmt.Stringer + + // Name is the name this module was instantiated with. Exported functions can be imported with this name. + Name() string + + // Memory returns a memory defined in this module or nil if there are none wasn't. + Memory() Memory + + // ExportedFunction returns a function exported from this module or nil if it wasn't. + // + // # Notes + // - The default wazero.ModuleConfig attempts to invoke `_start`, which + // in rare cases can close the module. When in doubt, check IsClosed prior + // to invoking a function export after instantiation. + // - The semantics of host functions assumes the existence of an "importing module" because, for example, the host function needs access to + // the memory of the importing module. Therefore, direct use of ExportedFunction is forbidden for host modules. + // Practically speaking, it is usually meaningless to directly call a host function from Go code as it is already somewhere in Go code. + ExportedFunction(name string) Function + + // ExportedFunctionDefinitions returns all the exported function + // definitions in this module, keyed on export name. + ExportedFunctionDefinitions() map[string]FunctionDefinition + + // TODO: Table + + // ExportedMemory returns a memory exported from this module or nil if it wasn't. + // + // WASI modules require exporting a Memory named "memory". This means that a module successfully initialized + // as a WASI Command or Reactor will never return nil for this name. + // + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi + ExportedMemory(name string) Memory + + // ExportedMemoryDefinitions returns all the exported memory definitions + // in this module, keyed on export name. + // + // Note: As of WebAssembly Core Specification 2.0, there can be at most one + // memory. + ExportedMemoryDefinitions() map[string]MemoryDefinition + + // ExportedGlobal a global exported from this module or nil if it wasn't. + ExportedGlobal(name string) Global + + // CloseWithExitCode releases resources allocated for this Module. Use a non-zero exitCode parameter to indicate a + // failure to ExportedFunction callers. + // + // The error returned here, if present, is about resource de-allocation (such as I/O errors). Only the last error is + // returned, so a non-nil return means at least one error happened. Regardless of error, this Module will + // be removed, making its name available again. + // + // Calling this inside a host function is safe, and may cause ExportedFunction callers to receive a sys.ExitError + // with the exitCode. + CloseWithExitCode(ctx context.Context, exitCode uint32) error + + // Closer closes this module by delegating to CloseWithExitCode with an exit code of zero. + Closer + + // IsClosed returns true if the module is closed, so no longer usable. + // + // This can happen for the following reasons: + // - Closer was called directly. + // - A guest function called Closer indirectly, such as `_start` calling + // `proc_exit`, which internally closed the module. + // - wazero.RuntimeConfig `WithCloseOnContextDone` was enabled and a + // context completion closed the module. + // + // Where any of the above are possible, check this value before calling an + // ExportedFunction, even if you didn't formerly receive a sys.ExitError. + // sys.ExitError is only returned on non-zero code, something that closes + // the module successfully will not result it one. + IsClosed() bool + + internalapi.WazeroOnly +} + +// Closer closes a resource. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type Closer interface { + // Close closes the resource. + // + // Note: The context parameter is used for value lookup, such as for + // logging. A canceled or otherwise done context will not prevent Close + // from succeeding. + Close(context.Context) error +} + +// ExportDefinition is a WebAssembly type exported in a module +// (wazero.CompiledModule). +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type ExportDefinition interface { + // ModuleName is the possibly empty name of the module defining this + // export. + // + // Note: This may be different from Module.Name, because a compiled module + // can be instantiated multiple times as different names. + ModuleName() string + + // Index is the position in the module's index, imports first. + Index() uint32 + + // Import returns true with the module and name when this was imported. + // Otherwise, it returns false. + // + // Note: Empty string is valid for both names in the WebAssembly Core + // Specification, so "" "" is possible. + Import() (moduleName, name string, isImport bool) + + // ExportNames include all exported names. + // + // Note: The empty name is allowed in the WebAssembly Core Specification, + // so "" is possible. + ExportNames() []string + + internalapi.WazeroOnly +} + +// MemoryDefinition is a WebAssembly memory exported in a module +// (wazero.CompiledModule). Units are in pages (64KB). +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type MemoryDefinition interface { + ExportDefinition + + // Min returns the possibly zero initial count of 64KB pages. + Min() uint32 + + // Max returns the possibly zero max count of 64KB pages, or false if + // unbounded. + Max() (uint32, bool) + + internalapi.WazeroOnly +} + +// FunctionDefinition is a WebAssembly function exported in a module +// (wazero.CompiledModule). +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type FunctionDefinition interface { + ExportDefinition + + // Name is the module-defined name of the function, which is not necessarily + // the same as its export name. + Name() string + + // DebugName identifies this function based on its Index or Name in the + // module. This is used for errors and stack traces. e.g. "env.abort". + // + // When the function name is empty, a substitute name is generated by + // prefixing '$' to its position in the index. Ex ".$0" is the + // first function (possibly imported) in an unnamed module. + // + // The format is dot-delimited module and function name, but there are no + // restrictions on the module and function name. This means either can be + // empty or include dots. e.g. "x.x.x" could mean module "x" and name "x.x", + // or it could mean module "x.x" and name "x". + // + // Note: This name is stable regardless of import or export. For example, + // if Import returns true, the value is still based on the Name or Index + // and not the imported function name. + DebugName() string + + // GoFunction is non-nil when implemented by the embedder instead of a wasm + // binary, e.g. via wazero.HostModuleBuilder + // + // The expected results are nil, GoFunction or GoModuleFunction. + GoFunction() interface{} + + // ParamTypes are the possibly empty sequence of value types accepted by a + // function with this signature. + // + // See ValueType documentation for encoding rules. + ParamTypes() []ValueType + + // ParamNames are index-correlated with ParamTypes or nil if not available + // for one or more parameters. + ParamNames() []string + + // ResultTypes are the results of the function. + // + // When WebAssembly 1.0 (20191205), there can be at most one result. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#result-types%E2%91%A0 + // + // See ValueType documentation for encoding rules. + ResultTypes() []ValueType + + // ResultNames are index-correlated with ResultTypes or nil if not + // available for one or more results. + ResultNames() []string + + internalapi.WazeroOnly +} + +// Function is a WebAssembly function exported from an instantiated module +// (wazero.Runtime InstantiateModule). +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-func +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type Function interface { + // Definition is metadata about this function from its defining module. + Definition() FunctionDefinition + + // Call invokes the function with the given parameters and returns any + // results or an error for any failure looking up or invoking the function. + // + // Encoding is described in Definition, and supplying an incorrect count of + // parameters vs FunctionDefinition.ParamTypes is an error. + // + // If the exporting Module was closed during this call, the error returned + // may be a sys.ExitError. See Module.CloseWithExitCode for details. + // + // Call is not goroutine-safe, therefore it is recommended to create + // another Function if you want to invoke the same function concurrently. + // On the other hand, sequential invocations of Call is allowed. + // However, this should not be called multiple times until the previous Call returns. + // + // To safely encode/decode params/results expressed as uint64, users are encouraged to + // use api.EncodeXXX or DecodeXXX functions. See the docs on api.ValueType. + // + // When RuntimeConfig.WithCloseOnContextDone is toggled, the invocation of this Call method is ensured to be closed + // whenever one of the three conditions is met. In the event of close, sys.ExitError will be returned and + // the api.Module from which this api.Function is derived will be made closed. See the documentation of + // WithCloseOnContextDone on wazero.RuntimeConfig for detail. See examples in context_done_example_test.go for + // the end-to-end demonstrations of how these terminations can be performed. + Call(ctx context.Context, params ...uint64) ([]uint64, error) + + // CallWithStack is an optimized variation of Call that saves memory + // allocations when the stack slice is reused across calls. + // + // Stack length must be at least the max of parameter or result length. + // The caller adds parameters in order to the stack, and reads any results + // in order from the stack, except in the error case. + // + // For example, the following reuses the same stack slice to call searchFn + // repeatedly saving one allocation per iteration: + // + // stack := make([]uint64, 4) + // for i, search := range searchParams { + // // copy the next params to the stack + // copy(stack, search) + // if err := searchFn.CallWithStack(ctx, stack); err != nil { + // return err + // } else if stack[0] == 1 { // found + // return i // searchParams[i] matched! + // } + // } + // + // # Notes + // + // - This is similar to GoModuleFunction, except for using calling functions + // instead of implementing them. Moreover, this is used regardless of + // whether the callee is a host or wasm defined function. + CallWithStack(ctx context.Context, stack []uint64) error + + internalapi.WazeroOnly +} + +// GoModuleFunction is a Function implemented in Go instead of a wasm binary. +// The Module parameter is the calling module, used to access memory or +// exported functions. See GoModuleFunc for an example. +// +// The stack is includes any parameters encoded according to their ValueType. +// Its length is the max of parameter or result length. When there are results, +// write them in order beginning at index zero. Do not use the stack after the +// function returns. +// +// Here's a typical way to read three parameters and write back one. +// +// // read parameters off the stack in index order +// argv, argvBuf := api.DecodeU32(stack[0]), api.DecodeU32(stack[1]) +// +// // write results back to the stack in index order +// stack[0] = api.EncodeU32(ErrnoSuccess) +// +// This function can be non-deterministic or cause side effects. It also +// has special properties not defined in the WebAssembly Core specification. +// Notably, this uses the caller's memory (via Module.Memory). See +// https://www.w3.org/TR/wasm-core-1/#host-functions%E2%91%A0 +// +// Most end users will not define functions directly with this, as they will +// use reflection or code generators instead. These approaches are more +// idiomatic as they can map go types to ValueType. This type is exposed for +// those willing to trade usability and safety for performance. +// +// To safely decode/encode values from/to the uint64 stack, users are encouraged to use +// api.EncodeXXX or api.DecodeXXX functions. See the docs on api.ValueType. +type GoModuleFunction interface { + Call(ctx context.Context, mod Module, stack []uint64) +} + +// GoModuleFunc is a convenience for defining an inlined function. +// +// For example, the following returns an uint32 value read from parameter zero: +// +// api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { +// offset := api.DecodeU32(stack[0]) // read the parameter from the stack +// +// ret, ok := mod.Memory().ReadUint32Le(offset) +// if !ok { +// panic("out of memory") +// } +// +// stack[0] = api.EncodeU32(ret) // add the result back to the stack. +// }) +type GoModuleFunc func(ctx context.Context, mod Module, stack []uint64) + +// Call implements GoModuleFunction.Call. +func (f GoModuleFunc) Call(ctx context.Context, mod Module, stack []uint64) { + f(ctx, mod, stack) +} + +// GoFunction is an optimized form of GoModuleFunction which doesn't require +// the Module parameter. See GoFunc for an example. +// +// For example, this function does not need to use the importing module's +// memory or exported functions. +type GoFunction interface { + Call(ctx context.Context, stack []uint64) +} + +// GoFunc is a convenience for defining an inlined function. +// +// For example, the following returns the sum of two uint32 parameters: +// +// api.GoFunc(func(ctx context.Context, stack []uint64) { +// x, y := api.DecodeU32(stack[0]), api.DecodeU32(stack[1]) +// stack[0] = api.EncodeU32(x + y) +// }) +type GoFunc func(ctx context.Context, stack []uint64) + +// Call implements GoFunction.Call. +func (f GoFunc) Call(ctx context.Context, stack []uint64) { + f(ctx, stack) +} + +// Global is a WebAssembly 1.0 (20191205) global exported from an instantiated module (wazero.Runtime InstantiateModule). +// +// For example, if the value is not mutable, you can read it once: +// +// offset := module.ExportedGlobal("memory.offset").Get() +// +// Globals are allowed by specification to be mutable. However, this can be disabled by configuration. When in doubt, +// safe cast to find out if the value can change. Here's an example: +// +// offset := module.ExportedGlobal("memory.offset") +// if _, ok := offset.(api.MutableGlobal); ok { +// // value can change +// } else { +// // value is constant +// } +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#globals%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type Global interface { + fmt.Stringer + + // Type describes the numeric type of the global. + Type() ValueType + + // Get returns the last known value of this global. + // + // See Type for how to decode this value to a Go type. + Get() uint64 +} + +// MutableGlobal is a Global whose value can be updated at runtime (variable). +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type MutableGlobal interface { + Global + + // Set updates the value of this global. + // + // See Global.Type for how to encode this value from a Go type. + Set(v uint64) + + internalapi.WazeroOnly +} + +// Memory allows restricted access to a module's memory. Notably, this does not allow growing. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#storage%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - This includes all value types available in WebAssembly 1.0 (20191205) and all are encoded little-endian. +type Memory interface { + // Definition is metadata about this memory from its defining module. + Definition() MemoryDefinition + + // Size returns the memory size in bytes available. + // e.g. If the underlying memory has 1 page: 65536 + // + // # Notes + // + // - This overflows (returns zero) if the memory has the maximum 65536 pages. + // As a workaround until wazero v2 to fix the return type, use Grow(0) to obtain the current pages and + // multiply by 65536. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-memorymathsfmemorysize%E2%91%A0 + Size() uint32 + + // Grow increases memory by the delta in pages (65536 bytes per page). + // The return val is the previous memory size in pages, or false if the + // delta was ignored as it exceeds MemoryDefinition.Max. + // + // # Notes + // + // - This is the same as the "memory.grow" instruction defined in the + // WebAssembly Core Specification, except returns false instead of -1. + // - When this returns true, any shared views via Read must be refreshed. + // + // See MemorySizer Read and https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem + Grow(deltaPages uint32) (previousPages uint32, ok bool) + + // ReadByte reads a single byte from the underlying buffer at the offset or returns false if out of range. + ReadByte(offset uint32) (byte, bool) + + // ReadUint16Le reads a uint16 in little-endian encoding from the underlying buffer at the offset in or returns + // false if out of range. + ReadUint16Le(offset uint32) (uint16, bool) + + // ReadUint32Le reads a uint32 in little-endian encoding from the underlying buffer at the offset in or returns + // false if out of range. + ReadUint32Le(offset uint32) (uint32, bool) + + // ReadFloat32Le reads a float32 from 32 IEEE 754 little-endian encoded bits in the underlying buffer at the offset + // or returns false if out of range. + // See math.Float32bits + ReadFloat32Le(offset uint32) (float32, bool) + + // ReadUint64Le reads a uint64 in little-endian encoding from the underlying buffer at the offset or returns false + // if out of range. + ReadUint64Le(offset uint32) (uint64, bool) + + // ReadFloat64Le reads a float64 from 64 IEEE 754 little-endian encoded bits in the underlying buffer at the offset + // or returns false if out of range. + // + // See math.Float64bits + ReadFloat64Le(offset uint32) (float64, bool) + + // Read reads byteCount bytes from the underlying buffer at the offset or + // returns false if out of range. + // + // For example, to search for a NUL-terminated string: + // buf, _ = memory.Read(offset, byteCount) + // n := bytes.IndexByte(buf, 0) + // if n < 0 { + // // Not found! + // } + // + // Write-through + // + // This returns a view of the underlying memory, not a copy. This means any + // writes to the slice returned are visible to Wasm, and any updates from + // Wasm are visible reading the returned slice. + // + // For example: + // buf, _ = memory.Read(offset, byteCount) + // buf[1] = 'a' // writes through to memory, meaning Wasm code see 'a'. + // + // If you don't intend-write through, make a copy of the returned slice. + // + // When to refresh Read + // + // The returned slice disconnects on any capacity change. For example, + // `buf = append(buf, 'a')` might result in a slice that is no longer + // shared. The same exists Wasm side. For example, if Wasm changes its + // memory capacity, ex via "memory.grow"), the host slice is no longer + // shared. Those who need a stable view must set Wasm memory min=max, or + // use wazero.RuntimeConfig WithMemoryCapacityPages to ensure max is always + // allocated. + Read(offset, byteCount uint32) ([]byte, bool) + + // WriteByte writes a single byte to the underlying buffer at the offset in or returns false if out of range. + WriteByte(offset uint32, v byte) bool + + // WriteUint16Le writes the value in little-endian encoding to the underlying buffer at the offset in or returns + // false if out of range. + WriteUint16Le(offset uint32, v uint16) bool + + // WriteUint32Le writes the value in little-endian encoding to the underlying buffer at the offset in or returns + // false if out of range. + WriteUint32Le(offset, v uint32) bool + + // WriteFloat32Le writes the value in 32 IEEE 754 little-endian encoded bits to the underlying buffer at the offset + // or returns false if out of range. + // + // See math.Float32bits + WriteFloat32Le(offset uint32, v float32) bool + + // WriteUint64Le writes the value in little-endian encoding to the underlying buffer at the offset in or returns + // false if out of range. + WriteUint64Le(offset uint32, v uint64) bool + + // WriteFloat64Le writes the value in 64 IEEE 754 little-endian encoded bits to the underlying buffer at the offset + // or returns false if out of range. + // + // See math.Float64bits + WriteFloat64Le(offset uint32, v float64) bool + + // Write writes the slice to the underlying buffer at the offset or returns false if out of range. + Write(offset uint32, v []byte) bool + + // WriteString writes the string to the underlying buffer at the offset or returns false if out of range. + WriteString(offset uint32, v string) bool + + internalapi.WazeroOnly +} + +// CustomSection contains the name and raw data of a custom section. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type CustomSection interface { + // Name is the name of the custom section + Name() string + // Data is the raw data of the custom section + Data() []byte + + internalapi.WazeroOnly +} + +// EncodeExternref encodes the input as a ValueTypeExternref. +// +// See DecodeExternref +func EncodeExternref(input uintptr) uint64 { + return uint64(input) +} + +// DecodeExternref decodes the input as a ValueTypeExternref. +// +// See EncodeExternref +func DecodeExternref(input uint64) uintptr { + return uintptr(input) +} + +// EncodeI32 encodes the input as a ValueTypeI32. +func EncodeI32(input int32) uint64 { + return uint64(uint32(input)) +} + +// DecodeI32 decodes the input as a ValueTypeI32. +func DecodeI32(input uint64) int32 { + return int32(input) +} + +// EncodeU32 encodes the input as a ValueTypeI32. +func EncodeU32(input uint32) uint64 { + return uint64(input) +} + +// DecodeU32 decodes the input as a ValueTypeI32. +func DecodeU32(input uint64) uint32 { + return uint32(input) +} + +// EncodeI64 encodes the input as a ValueTypeI64. +func EncodeI64(input int64) uint64 { + return uint64(input) +} + +// EncodeF32 encodes the input as a ValueTypeF32. +// +// See DecodeF32 +func EncodeF32(input float32) uint64 { + return uint64(math.Float32bits(input)) +} + +// DecodeF32 decodes the input as a ValueTypeF32. +// +// See EncodeF32 +func DecodeF32(input uint64) float32 { + return math.Float32frombits(uint32(input)) +} + +// EncodeF64 encodes the input as a ValueTypeF64. +// +// See EncodeF32 +func EncodeF64(input float64) uint64 { + return math.Float64bits(input) +} + +// DecodeF64 decodes the input as a ValueTypeF64. +// +// See EncodeF64 +func DecodeF64(input uint64) float64 { + return math.Float64frombits(input) +} diff --git a/vendor/github.com/tetratelabs/wazero/builder.go b/vendor/github.com/tetratelabs/wazero/builder.go new file mode 100644 index 00000000..b60a9e09 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/builder.go @@ -0,0 +1,367 @@ +package wazero + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// HostFunctionBuilder defines a host function (in Go), so that a +// WebAssembly binary (e.g. %.wasm file) can import and use it. +// +// Here's an example of an addition function: +// +// hostModuleBuilder.NewFunctionBuilder(). +// WithFunc(func(cxt context.Context, x, y uint32) uint32 { +// return x + y +// }). +// Export("add") +// +// # Memory +// +// All host functions act on the importing api.Module, including any memory +// exported in its binary (%.wasm file). If you are reading or writing memory, +// it is sand-boxed Wasm memory defined by the guest. +// +// Below, `m` is the importing module, defined in Wasm. `fn` is a host function +// added via Export. This means that `x` was read from memory defined in Wasm, +// not arbitrary memory in the process. +// +// fn := func(ctx context.Context, m api.Module, offset uint32) uint32 { +// x, _ := m.Memory().ReadUint32Le(ctx, offset) +// return x +// } +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type HostFunctionBuilder interface { + // WithGoFunction is an advanced feature for those who need higher + // performance than WithFunc at the cost of more complexity. + // + // Here's an example addition function: + // + // builder.WithGoFunction(api.GoFunc(func(ctx context.Context, stack []uint64) { + // x, y := api.DecodeI32(stack[0]), api.DecodeI32(stack[1]) + // sum := x + y + // stack[0] = api.EncodeI32(sum) + // }), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + // + // As you can see above, defining in this way implies knowledge of which + // WebAssembly api.ValueType is appropriate for each parameter and result. + // + // See WithGoModuleFunction if you also need to access the calling module. + WithGoFunction(fn api.GoFunction, params, results []api.ValueType) HostFunctionBuilder + + // WithGoModuleFunction is an advanced feature for those who need higher + // performance than WithFunc at the cost of more complexity. + // + // Here's an example addition function that loads operands from memory: + // + // builder.WithGoModuleFunction(api.GoModuleFunc(func(ctx context.Context, m api.Module, stack []uint64) { + // mem := m.Memory() + // offset := api.DecodeU32(stack[0]) + // + // x, _ := mem.ReadUint32Le(ctx, offset) + // y, _ := mem.ReadUint32Le(ctx, offset + 4) // 32 bits == 4 bytes! + // sum := x + y + // + // stack[0] = api.EncodeU32(sum) + // }), []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + // + // As you can see above, defining in this way implies knowledge of which + // WebAssembly api.ValueType is appropriate for each parameter and result. + // + // See WithGoFunction if you don't need access to the calling module. + WithGoModuleFunction(fn api.GoModuleFunction, params, results []api.ValueType) HostFunctionBuilder + + // WithFunc uses reflect.Value to map a go `func` to a WebAssembly + // compatible Signature. An input that isn't a `func` will fail to + // instantiate. + // + // Here's an example of an addition function: + // + // builder.WithFunc(func(cxt context.Context, x, y uint32) uint32 { + // return x + y + // }) + // + // # Defining a function + // + // Except for the context.Context and optional api.Module, all parameters + // or result types must map to WebAssembly numeric value types. This means + // uint32, int32, uint64, int64, float32 or float64. + // + // api.Module may be specified as the second parameter, usually to access + // memory. This is important because there are only numeric types in Wasm. + // The only way to share other data is via writing memory and sharing + // offsets. + // + // builder.WithFunc(func(ctx context.Context, m api.Module, offset uint32) uint32 { + // mem := m.Memory() + // x, _ := mem.ReadUint32Le(ctx, offset) + // y, _ := mem.ReadUint32Le(ctx, offset + 4) // 32 bits == 4 bytes! + // return x + y + // }) + // + // This example propagates context properly when calling other functions + // exported in the api.Module: + // + // builder.WithFunc(func(ctx context.Context, m api.Module, offset, byteCount uint32) uint32 { + // fn = m.ExportedFunction("__read") + // results, err := fn(ctx, offset, byteCount) + // --snip-- + WithFunc(interface{}) HostFunctionBuilder + + // WithName defines the optional module-local name of this function, e.g. + // "random_get" + // + // Note: This is not required to match the Export name. + WithName(name string) HostFunctionBuilder + + // WithParameterNames defines optional parameter names of the function + // signature, e.x. "buf", "buf_len" + // + // Note: When defined, names must be provided for all parameters. + WithParameterNames(names ...string) HostFunctionBuilder + + // WithResultNames defines optional result names of the function + // signature, e.x. "errno" + // + // Note: When defined, names must be provided for all results. + WithResultNames(names ...string) HostFunctionBuilder + + // Export exports this to the HostModuleBuilder as the given name, e.g. + // "random_get" + Export(name string) HostModuleBuilder +} + +// HostModuleBuilder is a way to define host functions (in Go), so that a +// WebAssembly binary (e.g. %.wasm file) can import and use them. +// +// Specifically, this implements the host side of an Application Binary +// Interface (ABI) like WASI or AssemblyScript. +// +// For example, this defines and instantiates a module named "env" with one +// function: +// +// ctx := context.Background() +// r := wazero.NewRuntime(ctx) +// defer r.Close(ctx) // This closes everything this Runtime created. +// +// hello := func() { +// println("hello!") +// } +// env, _ := r.NewHostModuleBuilder("env"). +// NewFunctionBuilder().WithFunc(hello).Export("hello"). +// Instantiate(ctx) +// +// If the same module may be instantiated multiple times, it is more efficient +// to separate steps. Here's an example: +// +// compiled, _ := r.NewHostModuleBuilder("env"). +// NewFunctionBuilder().WithFunc(getRandomString).Export("get_random_string"). +// Compile(ctx) +// +// env1, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("env.1")) +// env2, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("env.2")) +// +// See HostFunctionBuilder for valid host function signatures and other details. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - HostModuleBuilder is mutable: each method returns the same instance for +// chaining. +// - methods do not return errors, to allow chaining. Any validation errors +// are deferred until Compile. +// - Functions are indexed in order of calls to NewFunctionBuilder as +// insertion ordering is needed by ABI such as Emscripten (invoke_*). +// - The semantics of host functions assumes the existence of an "importing module" because, for example, the host function needs access to +// the memory of the importing module. Therefore, direct use of ExportedFunction is forbidden for host modules. +// Practically speaking, it is usually meaningless to directly call a host function from Go code as it is already somewhere in Go code. +type HostModuleBuilder interface { + // Note: until golang/go#5860, we can't use example tests to embed code in interface godocs. + + // NewFunctionBuilder begins the definition of a host function. + NewFunctionBuilder() HostFunctionBuilder + + // Compile returns a CompiledModule that can be instantiated by Runtime. + Compile(context.Context) (CompiledModule, error) + + // Instantiate is a convenience that calls Compile, then Runtime.InstantiateModule. + // This can fail for reasons documented on Runtime.InstantiateModule. + // + // Here's an example: + // + // ctx := context.Background() + // r := wazero.NewRuntime(ctx) + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // hello := func() { + // println("hello!") + // } + // env, _ := r.NewHostModuleBuilder("env"). + // NewFunctionBuilder().WithFunc(hello).Export("hello"). + // Instantiate(ctx) + // + // # Notes + // + // - Closing the Runtime has the same effect as closing the result. + // - Fields in the builder are copied during instantiation: Later changes do not affect the instantiated result. + // - To avoid using configuration defaults, use Compile instead. + Instantiate(context.Context) (api.Module, error) +} + +// hostModuleBuilder implements HostModuleBuilder +type hostModuleBuilder struct { + r *runtime + moduleName string + exportNames []string + nameToHostFunc map[string]*wasm.HostFunc +} + +// NewHostModuleBuilder implements Runtime.NewHostModuleBuilder +func (r *runtime) NewHostModuleBuilder(moduleName string) HostModuleBuilder { + return &hostModuleBuilder{ + r: r, + moduleName: moduleName, + nameToHostFunc: map[string]*wasm.HostFunc{}, + } +} + +// hostFunctionBuilder implements HostFunctionBuilder +type hostFunctionBuilder struct { + b *hostModuleBuilder + fn interface{} + name string + paramNames []string + resultNames []string +} + +// WithGoFunction implements HostFunctionBuilder.WithGoFunction +func (h *hostFunctionBuilder) WithGoFunction(fn api.GoFunction, params, results []api.ValueType) HostFunctionBuilder { + h.fn = &wasm.HostFunc{ParamTypes: params, ResultTypes: results, Code: wasm.Code{GoFunc: fn}} + return h +} + +// WithGoModuleFunction implements HostFunctionBuilder.WithGoModuleFunction +func (h *hostFunctionBuilder) WithGoModuleFunction(fn api.GoModuleFunction, params, results []api.ValueType) HostFunctionBuilder { + h.fn = &wasm.HostFunc{ParamTypes: params, ResultTypes: results, Code: wasm.Code{GoFunc: fn}} + return h +} + +// WithFunc implements HostFunctionBuilder.WithFunc +func (h *hostFunctionBuilder) WithFunc(fn interface{}) HostFunctionBuilder { + h.fn = fn + return h +} + +// WithName implements HostFunctionBuilder.WithName +func (h *hostFunctionBuilder) WithName(name string) HostFunctionBuilder { + h.name = name + return h +} + +// WithParameterNames implements HostFunctionBuilder.WithParameterNames +func (h *hostFunctionBuilder) WithParameterNames(names ...string) HostFunctionBuilder { + h.paramNames = names + return h +} + +// WithResultNames implements HostFunctionBuilder.WithResultNames +func (h *hostFunctionBuilder) WithResultNames(names ...string) HostFunctionBuilder { + h.resultNames = names + return h +} + +// Export implements HostFunctionBuilder.Export +func (h *hostFunctionBuilder) Export(exportName string) HostModuleBuilder { + var hostFn *wasm.HostFunc + if fn, ok := h.fn.(*wasm.HostFunc); ok { + hostFn = fn + } else { + hostFn = &wasm.HostFunc{Code: wasm.Code{GoFunc: h.fn}} + } + + // Assign any names from the builder + hostFn.ExportName = exportName + if h.name != "" { + hostFn.Name = h.name + } + if len(h.paramNames) != 0 { + hostFn.ParamNames = h.paramNames + } + if len(h.resultNames) != 0 { + hostFn.ResultNames = h.resultNames + } + + h.b.ExportHostFunc(hostFn) + return h.b +} + +// ExportHostFunc implements wasm.HostFuncExporter +func (b *hostModuleBuilder) ExportHostFunc(fn *wasm.HostFunc) { + if _, ok := b.nameToHostFunc[fn.ExportName]; !ok { // add a new name + b.exportNames = append(b.exportNames, fn.ExportName) + } + b.nameToHostFunc[fn.ExportName] = fn +} + +// NewFunctionBuilder implements HostModuleBuilder.NewFunctionBuilder +func (b *hostModuleBuilder) NewFunctionBuilder() HostFunctionBuilder { + return &hostFunctionBuilder{b: b} +} + +// Compile implements HostModuleBuilder.Compile +func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error) { + module, err := wasm.NewHostModule(b.moduleName, b.exportNames, b.nameToHostFunc, b.r.enabledFeatures) + if err != nil { + return nil, err + } else if err = module.Validate(b.r.enabledFeatures); err != nil { + return nil, err + } + + c := &compiledModule{module: module, compiledEngine: b.r.store.Engine} + listeners, err := buildFunctionListeners(ctx, module) + if err != nil { + return nil, err + } + + if err = b.r.store.Engine.CompileModule(ctx, module, listeners, false); err != nil { + return nil, err + } + + // typeIDs are static and compile-time known. + typeIDs, err := b.r.store.GetFunctionTypeIDs(module.TypeSection) + if err != nil { + return nil, err + } + c.typeIDs = typeIDs + + return c, nil +} + +// hostModuleInstance is a wrapper around api.Module that prevents calling ExportedFunction. +type hostModuleInstance struct{ api.Module } + +// ExportedFunction implements api.Module ExportedFunction. +func (h hostModuleInstance) ExportedFunction(name string) api.Function { + panic("calling ExportedFunction is forbidden on host modules. See the note on ExportedFunction interface") +} + +// Instantiate implements HostModuleBuilder.Instantiate +func (b *hostModuleBuilder) Instantiate(ctx context.Context) (api.Module, error) { + if compiled, err := b.Compile(ctx); err != nil { + return nil, err + } else { + compiled.(*compiledModule).closeWithModule = true + m, err := b.r.InstantiateModule(ctx, compiled, NewModuleConfig()) + if err != nil { + return nil, err + } + return hostModuleInstance{m}, nil + } +} diff --git a/vendor/github.com/tetratelabs/wazero/cache.go b/vendor/github.com/tetratelabs/wazero/cache.go new file mode 100644 index 00000000..83cdb94e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/cache.go @@ -0,0 +1,123 @@ +package wazero + +import ( + "context" + "errors" + "fmt" + "os" + "path" + "path/filepath" + goruntime "runtime" + "sync" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/filecache" + "github.com/tetratelabs/wazero/internal/version" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// CompilationCache reduces time spent compiling (Runtime.CompileModule) the same wasm module. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - Instances of this can be reused across multiple runtimes, if configured +// via RuntimeConfig. +// - The cache check happens before the compilation, so if multiple Goroutines are +// trying to compile the same module simultaneously, it is possible that they +// all compile the module. The design here is that the lock isn't held for the action "Compile" +// but only for checking and saving the compiled result. Therefore, we strongly recommend that the embedder +// does the centralized compilation in a single Goroutines (or multiple Goroutines per Wasm binary) to generate cache rather than +// trying to Compile in parallel for a single module. In other words, we always recommend to produce CompiledModule +// share it across multiple Goroutines to avoid trying to compile the same module simultaneously. +type CompilationCache interface{ api.Closer } + +// NewCompilationCache returns a new CompilationCache to be passed to RuntimeConfig. +// This configures only in-memory cache, and doesn't persist to the file system. See wazero.NewCompilationCacheWithDir for detail. +// +// The returned CompilationCache can be used to share the in-memory compilation results across multiple instances of wazero.Runtime. +func NewCompilationCache() CompilationCache { + return &cache{} +} + +// NewCompilationCacheWithDir is like wazero.NewCompilationCache except the result also writes +// state into the directory specified by `dirname` parameter. +// +// If the dirname doesn't exist, this creates it or returns an error. +// +// Those running wazero as a CLI or frequently restarting a process using the same wasm should +// use this feature to reduce time waiting to compile the same module a second time. +// +// The contents written into dirname are wazero-version specific, meaning different versions of +// wazero will duplicate entries for the same input wasm. +// +// Note: The embedder must safeguard this directory from external changes. +func NewCompilationCacheWithDir(dirname string) (CompilationCache, error) { + c := &cache{} + err := c.ensuresFileCache(dirname, version.GetWazeroVersion()) + return c, err +} + +// cache implements Cache interface. +type cache struct { + // eng is the engine for this cache. If the cache is configured, the engine is shared across multiple instances of + // Runtime, and its lifetime is not bound to them. Instead, the engine is alive until Cache.Close is called. + engs [engineKindCount]wasm.Engine + fileCache filecache.Cache + initOnces [engineKindCount]sync.Once +} + +func (c *cache) initEngine(ek engineKind, ne newEngine, ctx context.Context, features api.CoreFeatures) wasm.Engine { + c.initOnces[ek].Do(func() { c.engs[ek] = ne(ctx, features, c.fileCache) }) + return c.engs[ek] +} + +// Close implements the same method on the Cache interface. +func (c *cache) Close(_ context.Context) (err error) { + for _, eng := range c.engs { + if eng != nil { + if err = eng.Close(); err != nil { + return + } + } + } + return +} + +func (c *cache) ensuresFileCache(dir string, wazeroVersion string) error { + // Resolve a potentially relative directory into an absolute one. + var err error + dir, err = filepath.Abs(dir) + if err != nil { + return err + } + + // Ensure the user-supplied directory. + if err = mkdir(dir); err != nil { + return err + } + + // Create a version-specific directory to avoid conflicts. + dirname := path.Join(dir, "wazero-"+wazeroVersion+"-"+goruntime.GOARCH+"-"+goruntime.GOOS) + if err = mkdir(dirname); err != nil { + return err + } + + c.fileCache = filecache.New(dirname) + return nil +} + +func mkdir(dirname string) error { + if st, err := os.Stat(dirname); errors.Is(err, os.ErrNotExist) { + // If the directory not found, create the cache dir. + if err = os.MkdirAll(dirname, 0o700); err != nil { + return fmt.Errorf("create directory %s: %v", dirname, err) + } + } else if err != nil { + return err + } else if !st.IsDir() { + return fmt.Errorf("%s is not dir", dirname) + } + return nil +} diff --git a/vendor/github.com/tetratelabs/wazero/codecov.yml b/vendor/github.com/tetratelabs/wazero/codecov.yml new file mode 100644 index 00000000..cf9d94df --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/codecov.yml @@ -0,0 +1,9 @@ +# Codecov for main is visible here https://app.codecov.io/gh/tetratelabs/wazero + +# We use codecov only as a UI, so we disable PR comments and commit status. +# See https://docs.codecov.com/docs/pull-request-comments +comment: false +coverage: + status: + project: off + patch: off diff --git a/vendor/github.com/tetratelabs/wazero/config.go b/vendor/github.com/tetratelabs/wazero/config.go new file mode 100644 index 00000000..9fa2bada --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/config.go @@ -0,0 +1,899 @@ +package wazero + +import ( + "context" + "errors" + "fmt" + "io" + "io/fs" + "math" + "net" + "time" + + "github.com/tetratelabs/wazero/api" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/filecache" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/platform" + internalsock "github.com/tetratelabs/wazero/internal/sock" + internalsys "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/sys" +) + +// RuntimeConfig controls runtime behavior, with the default implementation as +// NewRuntimeConfig +// +// The example below explicitly limits to Wasm Core 1.0 features as opposed to +// relying on defaults: +// +// rConfig = wazero.NewRuntimeConfig().WithCoreFeatures(api.CoreFeaturesV1) +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - RuntimeConfig is immutable. Each WithXXX function returns a new instance +// including the corresponding change. +type RuntimeConfig interface { + // WithCoreFeatures sets the WebAssembly Core specification features this + // runtime supports. Defaults to api.CoreFeaturesV2. + // + // Example of disabling a specific feature: + // features := api.CoreFeaturesV2.SetEnabled(api.CoreFeatureMutableGlobal, false) + // rConfig = wazero.NewRuntimeConfig().WithCoreFeatures(features) + // + // # Why default to version 2.0? + // + // Many compilers that target WebAssembly require features after + // api.CoreFeaturesV1 by default. For example, TinyGo v0.24+ requires + // api.CoreFeatureBulkMemoryOperations. To avoid runtime errors, wazero + // defaults to api.CoreFeaturesV2, even though it is not yet a Web + // Standard (REC). + WithCoreFeatures(api.CoreFeatures) RuntimeConfig + + // WithMemoryLimitPages overrides the maximum pages allowed per memory. The + // default is 65536, allowing 4GB total memory per instance if the maximum is + // not encoded in a Wasm binary. Setting a value larger than default will panic. + // + // This example reduces the largest possible memory size from 4GB to 128KB: + // rConfig = wazero.NewRuntimeConfig().WithMemoryLimitPages(2) + // + // Note: Wasm has 32-bit memory and each page is 65536 (2^16) bytes. This + // implies a max of 65536 (2^16) addressable pages. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem + WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig + + // WithMemoryCapacityFromMax eagerly allocates max memory, unless max is + // not defined. The default is false, which means minimum memory is + // allocated and any call to grow memory results in re-allocations. + // + // This example ensures any memory.grow instruction will never re-allocate: + // rConfig = wazero.NewRuntimeConfig().WithMemoryCapacityFromMax(true) + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem + // + // Note: if the memory maximum is not encoded in a Wasm binary, this + // results in allocating 4GB. See the doc on WithMemoryLimitPages for detail. + WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig + + // WithDebugInfoEnabled toggles DWARF based stack traces in the face of + // runtime errors. Defaults to true. + // + // Those who wish to disable this, can like so: + // + // r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithDebugInfoEnabled(false) + // + // When disabled, a stack trace message looks like: + // + // wasm stack trace: + // .runtime._panic(i32) + // .myFunc() + // .main.main() + // .runtime.run() + // ._start() + // + // When enabled, the stack trace includes source code information: + // + // wasm stack trace: + // .runtime._panic(i32) + // 0x16e2: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_tinygowasm.go:73:6 + // .myFunc() + // 0x190b: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:19:7 + // .main.main() + // 0x18ed: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:4:3 + // .runtime.run() + // 0x18cc: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/scheduler_none.go:26:10 + // ._start() + // 0x18b6: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_wasm_wasi.go:22:5 + // + // Note: This only takes into effect when the original Wasm binary has the + // DWARF "custom sections" that are often stripped, depending on + // optimization flags passed to the compiler. + WithDebugInfoEnabled(bool) RuntimeConfig + + // WithCompilationCache configures how runtime caches the compiled modules. In the default configuration, compilation results are + // only in-memory until Runtime.Close is closed, and not shareable by multiple Runtime. + // + // Below defines the shared cache across multiple instances of Runtime: + // + // // Creates the new Cache and the runtime configuration with it. + // cache := wazero.NewCompilationCache() + // defer cache.Close() + // config := wazero.NewRuntimeConfig().WithCompilationCache(c) + // + // // Creates two runtimes while sharing compilation caches. + // foo := wazero.NewRuntimeWithConfig(context.Background(), config) + // bar := wazero.NewRuntimeWithConfig(context.Background(), config) + // + // # Cache Key + // + // Cached files are keyed on the version of wazero. This is obtained from go.mod of your application, + // and we use it to verify the compatibility of caches against the currently-running wazero. + // However, if you use this in tests of a package not named as `main`, then wazero cannot obtain the correct + // version of wazero due to the known issue of debug.BuildInfo function: https://github.com/golang/go/issues/33976. + // As a consequence, your cache won't contain the correct version information and always be treated as `dev` version. + // To avoid this issue, you can pass -ldflags "-X github.com/tetratelabs/wazero/internal/version.version=foo" when running tests. + WithCompilationCache(CompilationCache) RuntimeConfig + + // WithCustomSections toggles parsing of "custom sections". Defaults to false. + // + // When enabled, it is possible to retrieve custom sections from a CompiledModule: + // + // config := wazero.NewRuntimeConfig().WithCustomSections(true) + // r := wazero.NewRuntimeWithConfig(ctx, config) + // c, err := r.CompileModule(ctx, wasm) + // customSections := c.CustomSections() + WithCustomSections(bool) RuntimeConfig + + // WithCloseOnContextDone ensures the executions of functions to be terminated under one of the following circumstances: + // + // - context.Context passed to the Call method of api.Function is canceled during execution. (i.e. ctx by context.WithCancel) + // - context.Context passed to the Call method of api.Function reaches timeout during execution. (i.e. ctx by context.WithTimeout or context.WithDeadline) + // - Close or CloseWithExitCode of api.Module is explicitly called during execution. + // + // This is especially useful when one wants to run untrusted Wasm binaries since otherwise, any invocation of + // api.Function can potentially block the corresponding Goroutine forever. Moreover, it might block the + // entire underlying OS thread which runs the api.Function call. See "Why it's safe to execute runtime-generated + // machine codes against async Goroutine preemption" section in RATIONALE.md for detail. + // + // Upon the termination of the function executions, api.Module is closed. + // + // Note that this comes with a bit of extra cost when enabled. The reason is that internally this forces + // interpreter and compiler runtimes to insert the periodical checks on the conditions above. For that reason, + // this is disabled by default. + // + // See examples in context_done_example_test.go for the end-to-end demonstrations. + // + // When the invocations of api.Function are closed due to this, sys.ExitError is raised to the callers and + // the api.Module from which the functions are derived is made closed. + WithCloseOnContextDone(bool) RuntimeConfig +} + +// NewRuntimeConfig returns a RuntimeConfig using the compiler if it is supported in this environment, +// or the interpreter otherwise. +func NewRuntimeConfig() RuntimeConfig { + ret := engineLessConfig.clone() + ret.engineKind = engineKindAuto + return ret +} + +type newEngine func(context.Context, api.CoreFeatures, filecache.Cache) wasm.Engine + +type runtimeConfig struct { + enabledFeatures api.CoreFeatures + memoryLimitPages uint32 + memoryCapacityFromMax bool + engineKind engineKind + dwarfDisabled bool // negative as defaults to enabled + newEngine newEngine + cache CompilationCache + storeCustomSections bool + ensureTermination bool +} + +// engineLessConfig helps avoid copy/pasting the wrong defaults. +var engineLessConfig = &runtimeConfig{ + enabledFeatures: api.CoreFeaturesV2, + memoryLimitPages: wasm.MemoryLimitPages, + memoryCapacityFromMax: false, + dwarfDisabled: false, +} + +type engineKind int + +const ( + engineKindAuto engineKind = iota - 1 + engineKindCompiler + engineKindInterpreter + engineKindCount +) + +// NewRuntimeConfigCompiler compiles WebAssembly modules into +// runtime.GOARCH-specific assembly for optimal performance. +// +// The default implementation is AOT (Ahead of Time) compilation, applied at +// Runtime.CompileModule. This allows consistent runtime performance, as well +// the ability to reduce any first request penalty. +// +// Note: While this is technically AOT, this does not imply any action on your +// part. wazero automatically performs ahead-of-time compilation as needed when +// Runtime.CompileModule is invoked. +// +// # Warning +// +// - This panics at runtime if the runtime.GOOS or runtime.GOARCH does not +// support compiler. Use NewRuntimeConfig to safely detect and fallback to +// NewRuntimeConfigInterpreter if needed. +// +// - If you are using wazero in buildmode=c-archive or c-shared, make sure that you set up the alternate signal stack +// by using, e.g. `sigaltstack` combined with `SA_ONSTACK` flag on `sigaction` on Linux, +// before calling any api.Function. This is because the Go runtime does not set up the alternate signal stack +// for c-archive or c-shared modes, and wazero uses the different stack than the calling Goroutine. +// Hence, the signal handler might get invoked on the wazero's stack, which may cause a stack overflow. +// https://github.com/tetratelabs/wazero/blob/2092c0a879f30d49d7b37f333f4547574b8afe0d/internal/integration_test/fuzz/fuzz/tests/sigstack.rs#L19-L36 +func NewRuntimeConfigCompiler() RuntimeConfig { + ret := engineLessConfig.clone() + ret.engineKind = engineKindCompiler + return ret +} + +// NewRuntimeConfigInterpreter interprets WebAssembly modules instead of compiling them into assembly. +func NewRuntimeConfigInterpreter() RuntimeConfig { + ret := engineLessConfig.clone() + ret.engineKind = engineKindInterpreter + return ret +} + +// clone makes a deep copy of this runtime config. +func (c *runtimeConfig) clone() *runtimeConfig { + ret := *c // copy except maps which share a ref + return &ret +} + +// WithCoreFeatures implements RuntimeConfig.WithCoreFeatures +func (c *runtimeConfig) WithCoreFeatures(features api.CoreFeatures) RuntimeConfig { + ret := c.clone() + ret.enabledFeatures = features + return ret +} + +// WithCloseOnContextDone implements RuntimeConfig.WithCloseOnContextDone +func (c *runtimeConfig) WithCloseOnContextDone(ensure bool) RuntimeConfig { + ret := c.clone() + ret.ensureTermination = ensure + return ret +} + +// WithMemoryLimitPages implements RuntimeConfig.WithMemoryLimitPages +func (c *runtimeConfig) WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig { + ret := c.clone() + // This panics instead of returning an error as it is unlikely. + if memoryLimitPages > wasm.MemoryLimitPages { + panic(fmt.Errorf("memoryLimitPages invalid: %d > %d", memoryLimitPages, wasm.MemoryLimitPages)) + } + ret.memoryLimitPages = memoryLimitPages + return ret +} + +// WithCompilationCache implements RuntimeConfig.WithCompilationCache +func (c *runtimeConfig) WithCompilationCache(ca CompilationCache) RuntimeConfig { + ret := c.clone() + ret.cache = ca + return ret +} + +// WithMemoryCapacityFromMax implements RuntimeConfig.WithMemoryCapacityFromMax +func (c *runtimeConfig) WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig { + ret := c.clone() + ret.memoryCapacityFromMax = memoryCapacityFromMax + return ret +} + +// WithDebugInfoEnabled implements RuntimeConfig.WithDebugInfoEnabled +func (c *runtimeConfig) WithDebugInfoEnabled(dwarfEnabled bool) RuntimeConfig { + ret := c.clone() + ret.dwarfDisabled = !dwarfEnabled + return ret +} + +// WithCustomSections implements RuntimeConfig.WithCustomSections +func (c *runtimeConfig) WithCustomSections(storeCustomSections bool) RuntimeConfig { + ret := c.clone() + ret.storeCustomSections = storeCustomSections + return ret +} + +// CompiledModule is a WebAssembly module ready to be instantiated (Runtime.InstantiateModule) as an api.Module. +// +// In WebAssembly terminology, this is a decoded, validated, and possibly also compiled module. wazero avoids using +// the name "Module" for both before and after instantiation as the name conflation has caused confusion. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#semantic-phases%E2%91%A0 +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - Closing the wazero.Runtime closes any CompiledModule it compiled. +type CompiledModule interface { + // Name returns the module name encoded into the binary or empty if not. + Name() string + + // ImportedFunctions returns all the imported functions + // (api.FunctionDefinition) in this module or nil if there are none. + // + // Note: Unlike ExportedFunctions, there is no unique constraint on + // imports. + ImportedFunctions() []api.FunctionDefinition + + // ExportedFunctions returns all the exported functions + // (api.FunctionDefinition) in this module keyed on export name. + ExportedFunctions() map[string]api.FunctionDefinition + + // ImportedMemories returns all the imported memories + // (api.MemoryDefinition) in this module or nil if there are none. + // + // ## Notes + // - As of WebAssembly Core Specification 2.0, there can be at most one + // memory. + // - Unlike ExportedMemories, there is no unique constraint on imports. + ImportedMemories() []api.MemoryDefinition + + // ExportedMemories returns all the exported memories + // (api.MemoryDefinition) in this module keyed on export name. + // + // Note: As of WebAssembly Core Specification 2.0, there can be at most one + // memory. + ExportedMemories() map[string]api.MemoryDefinition + + // CustomSections returns all the custom sections + // (api.CustomSection) in this module keyed on the section name. + CustomSections() []api.CustomSection + + // Close releases all the allocated resources for this CompiledModule. + // + // Note: It is safe to call Close while having outstanding calls from an + // api.Module instantiated from this. + Close(context.Context) error +} + +// compile-time check to ensure compiledModule implements CompiledModule +var _ CompiledModule = &compiledModule{} + +type compiledModule struct { + module *wasm.Module + // compiledEngine holds an engine on which `module` is compiled. + compiledEngine wasm.Engine + // closeWithModule prevents leaking compiled code when a module is compiled implicitly. + closeWithModule bool + typeIDs []wasm.FunctionTypeID +} + +// Name implements CompiledModule.Name +func (c *compiledModule) Name() (moduleName string) { + if ns := c.module.NameSection; ns != nil { + moduleName = ns.ModuleName + } + return +} + +// Close implements CompiledModule.Close +func (c *compiledModule) Close(context.Context) error { + c.compiledEngine.DeleteCompiledModule(c.module) + // It is possible the underlying may need to return an error later, but in any case this matches api.Module.Close. + return nil +} + +// ImportedFunctions implements CompiledModule.ImportedFunctions +func (c *compiledModule) ImportedFunctions() []api.FunctionDefinition { + return c.module.ImportedFunctions() +} + +// ExportedFunctions implements CompiledModule.ExportedFunctions +func (c *compiledModule) ExportedFunctions() map[string]api.FunctionDefinition { + return c.module.ExportedFunctions() +} + +// ImportedMemories implements CompiledModule.ImportedMemories +func (c *compiledModule) ImportedMemories() []api.MemoryDefinition { + return c.module.ImportedMemories() +} + +// ExportedMemories implements CompiledModule.ExportedMemories +func (c *compiledModule) ExportedMemories() map[string]api.MemoryDefinition { + return c.module.ExportedMemories() +} + +// CustomSections implements CompiledModule.CustomSections +func (c *compiledModule) CustomSections() []api.CustomSection { + ret := make([]api.CustomSection, len(c.module.CustomSections)) + for i, d := range c.module.CustomSections { + ret[i] = &customSection{data: d.Data, name: d.Name} + } + return ret +} + +// customSection implements wasm.CustomSection +type customSection struct { + internalapi.WazeroOnlyType + name string + data []byte +} + +// Name implements wasm.CustomSection.Name +func (c *customSection) Name() string { + return c.name +} + +// Data implements wasm.CustomSection.Data +func (c *customSection) Data() []byte { + return c.data +} + +// ModuleConfig configures resources needed by functions that have low-level interactions with the host operating +// system. Using this, resources such as STDIN can be isolated, so that the same module can be safely instantiated +// multiple times. +// +// Here's an example: +// +// // Initialize base configuration: +// config := wazero.NewModuleConfig().WithStdout(buf).WithSysNanotime() +// +// // Assign different configuration on each instantiation +// mod, _ := r.InstantiateModule(ctx, compiled, config.WithName("rotate").WithArgs("rotate", "angle=90", "dir=cw")) +// +// While wazero supports Windows as a platform, host functions using ModuleConfig follow a UNIX dialect. +// See RATIONALE.md for design background and relationship to WebAssembly System Interfaces (WASI). +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - ModuleConfig is immutable. Each WithXXX function returns a new instance +// including the corresponding change. +type ModuleConfig interface { + // WithArgs assigns command-line arguments visible to an imported function that reads an arg vector (argv). Defaults to + // none. Runtime.InstantiateModule errs if any arg is empty. + // + // These values are commonly read by the functions like "args_get" in "wasi_snapshot_preview1" although they could be + // read by functions imported from other modules. + // + // Similar to os.Args and exec.Cmd Env, many implementations would expect a program name to be argv[0]. However, neither + // WebAssembly nor WebAssembly System Interfaces (WASI) define this. Regardless, you may choose to set the first + // argument to the same value set via WithName. + // + // Note: This does not default to os.Args as that violates sandboxing. + // + // See https://linux.die.net/man/3/argv and https://en.wikipedia.org/wiki/Null-terminated_string + WithArgs(...string) ModuleConfig + + // WithEnv sets an environment variable visible to a Module that imports functions. Defaults to none. + // Runtime.InstantiateModule errs if the key is empty or contains a NULL(0) or equals("") character. + // + // Validation is the same as os.Setenv on Linux and replaces any existing value. Unlike exec.Cmd Env, this does not + // default to the current process environment as that would violate sandboxing. This also does not preserve order. + // + // Environment variables are commonly read by the functions like "environ_get" in "wasi_snapshot_preview1" although + // they could be read by functions imported from other modules. + // + // While similar to process configuration, there are no assumptions that can be made about anything OS-specific. For + // example, neither WebAssembly nor WebAssembly System Interfaces (WASI) define concerns processes have, such as + // case-sensitivity on environment keys. For portability, define entries with case-insensitively unique keys. + // + // See https://linux.die.net/man/3/environ and https://en.wikipedia.org/wiki/Null-terminated_string + WithEnv(key, value string) ModuleConfig + + // WithFS is a convenience that calls WithFSConfig with an FSConfig of the + // input for the root ("/") guest path. + WithFS(fs.FS) ModuleConfig + + // WithFSConfig configures the filesystem available to each guest + // instantiated with this configuration. By default, no file access is + // allowed, so functions like `path_open` result in unsupported errors + // (e.g. syscall.ENOSYS). + WithFSConfig(FSConfig) ModuleConfig + + // WithName configures the module name. Defaults to what was decoded from + // the name section. Duplicate names are not allowed in a single Runtime. + // + // Calling this with the empty string "" makes the module anonymous. + // That is useful when you want to instantiate the same CompiledModule multiple times like below: + // + // for i := 0; i < N; i++ { + // // Instantiate a new Wasm module from the already compiled `compiledWasm` anonymously without a name. + // instance, err := r.InstantiateModule(ctx, compiledWasm, wazero.NewModuleConfig().WithName("")) + // // .... + // } + // + // See the `concurrent-instantiation` example for a complete usage. + // + // Non-empty named modules are available for other modules to import by name. + WithName(string) ModuleConfig + + // WithStartFunctions configures the functions to call after the module is + // instantiated. Defaults to "_start". + // + // Clearing the default is supported, via `WithStartFunctions()`. + // + // # Notes + // + // - If a start function doesn't exist, it is skipped. However, any that + // do exist are called in order. + // - Start functions are not intended to be called multiple times. + // Functions that should be called multiple times should be invoked + // manually via api.Module's `ExportedFunction` method. + // - Start functions commonly exit the module during instantiation, + // preventing use of any functions later. This is the case in "wasip1", + // which defines the default value "_start". + // - See /RATIONALE.md for motivation of this feature. + WithStartFunctions(...string) ModuleConfig + + // WithStderr configures where standard error (file descriptor 2) is written. Defaults to io.Discard. + // + // This writer is most commonly used by the functions like "fd_write" in "wasi_snapshot_preview1" although it could + // be used by functions imported from other modules. + // + // # Notes + // + // - The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close. + // - This does not default to os.Stderr as that both violates sandboxing and prevents concurrent modules. + // + // See https://linux.die.net/man/3/stderr + WithStderr(io.Writer) ModuleConfig + + // WithStdin configures where standard input (file descriptor 0) is read. Defaults to return io.EOF. + // + // This reader is most commonly used by the functions like "fd_read" in "wasi_snapshot_preview1" although it could + // be used by functions imported from other modules. + // + // # Notes + // + // - The caller is responsible to close any io.Reader they supply: It is not closed on api.Module Close. + // - This does not default to os.Stdin as that both violates sandboxing and prevents concurrent modules. + // + // See https://linux.die.net/man/3/stdin + WithStdin(io.Reader) ModuleConfig + + // WithStdout configures where standard output (file descriptor 1) is written. Defaults to io.Discard. + // + // This writer is most commonly used by the functions like "fd_write" in "wasi_snapshot_preview1" although it could + // be used by functions imported from other modules. + // + // # Notes + // + // - The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close. + // - This does not default to os.Stdout as that both violates sandboxing and prevents concurrent modules. + // + // See https://linux.die.net/man/3/stdout + WithStdout(io.Writer) ModuleConfig + + // WithWalltime configures the wall clock, sometimes referred to as the + // real time clock. sys.Walltime returns the current unix/epoch time, + // seconds since midnight UTC 1 January 1970, with a nanosecond fraction. + // This defaults to a fake result that increases by 1ms on each reading. + // + // Here's an example that uses a custom clock: + // moduleConfig = moduleConfig. + // WithWalltime(func(context.Context) (sec int64, nsec int32) { + // return clock.walltime() + // }, sys.ClockResolution(time.Microsecond.Nanoseconds())) + // + // # Notes: + // - This does not default to time.Now as that violates sandboxing. + // - This is used to implement host functions such as WASI + // `clock_time_get` with the `realtime` clock ID. + // - Use WithSysWalltime for a usable implementation. + WithWalltime(sys.Walltime, sys.ClockResolution) ModuleConfig + + // WithSysWalltime uses time.Now for sys.Walltime with a resolution of 1us + // (1000ns). + // + // See WithWalltime + WithSysWalltime() ModuleConfig + + // WithNanotime configures the monotonic clock, used to measure elapsed + // time in nanoseconds. Defaults to a fake result that increases by 1ms + // on each reading. + // + // Here's an example that uses a custom clock: + // moduleConfig = moduleConfig. + // WithNanotime(func(context.Context) int64 { + // return clock.nanotime() + // }, sys.ClockResolution(time.Microsecond.Nanoseconds())) + // + // # Notes: + // - This does not default to time.Since as that violates sandboxing. + // - This is used to implement host functions such as WASI + // `clock_time_get` with the `monotonic` clock ID. + // - Some compilers implement sleep by looping on sys.Nanotime (e.g. Go). + // - If you set this, you should probably set WithNanosleep also. + // - Use WithSysNanotime for a usable implementation. + WithNanotime(sys.Nanotime, sys.ClockResolution) ModuleConfig + + // WithSysNanotime uses time.Now for sys.Nanotime with a resolution of 1us. + // + // See WithNanotime + WithSysNanotime() ModuleConfig + + // WithNanosleep configures the how to pause the current goroutine for at + // least the configured nanoseconds. Defaults to return immediately. + // + // This example uses a custom sleep function: + // moduleConfig = moduleConfig. + // WithNanosleep(func(ns int64) { + // rel := unix.NsecToTimespec(ns) + // remain := unix.Timespec{} + // for { // loop until no more time remaining + // err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, &remain) + // --snip-- + // + // # Notes: + // - This does not default to time.Sleep as that violates sandboxing. + // - This is used to implement host functions such as WASI `poll_oneoff`. + // - Some compilers implement sleep by looping on sys.Nanotime (e.g. Go). + // - If you set this, you should probably set WithNanotime also. + // - Use WithSysNanosleep for a usable implementation. + WithNanosleep(sys.Nanosleep) ModuleConfig + + // WithOsyield yields the processor, typically to implement spin-wait + // loops. Defaults to return immediately. + // + // # Notes: + // - This primarily supports `sched_yield` in WASI + // - This does not default to runtime.osyield as that violates sandboxing. + WithOsyield(sys.Osyield) ModuleConfig + + // WithSysNanosleep uses time.Sleep for sys.Nanosleep. + // + // See WithNanosleep + WithSysNanosleep() ModuleConfig + + // WithRandSource configures a source of random bytes. Defaults to return a + // deterministic source. You might override this with crypto/rand.Reader + // + // This reader is most commonly used by the functions like "random_get" in + // "wasi_snapshot_preview1", "seed" in AssemblyScript standard "env", and + // "getRandomData" when runtime.GOOS is "js". + // + // Note: The caller is responsible to close any io.Reader they supply: It + // is not closed on api.Module Close. + WithRandSource(io.Reader) ModuleConfig +} + +type moduleConfig struct { + name string + nameSet bool + startFunctions []string + stdin io.Reader + stdout io.Writer + stderr io.Writer + randSource io.Reader + walltime sys.Walltime + walltimeResolution sys.ClockResolution + nanotime sys.Nanotime + nanotimeResolution sys.ClockResolution + nanosleep sys.Nanosleep + osyield sys.Osyield + args [][]byte + // environ is pair-indexed to retain order similar to os.Environ. + environ [][]byte + // environKeys allow overwriting of existing values. + environKeys map[string]int + // fsConfig is the file system configuration for ABI like WASI. + fsConfig FSConfig + // sockConfig is the network listener configuration for ABI like WASI. + sockConfig *internalsock.Config +} + +// NewModuleConfig returns a ModuleConfig that can be used for configuring module instantiation. +func NewModuleConfig() ModuleConfig { + return &moduleConfig{ + startFunctions: []string{"_start"}, + environKeys: map[string]int{}, + } +} + +// clone makes a deep copy of this module config. +func (c *moduleConfig) clone() *moduleConfig { + ret := *c // copy except maps which share a ref + ret.environKeys = make(map[string]int, len(c.environKeys)) + for key, value := range c.environKeys { + ret.environKeys[key] = value + } + return &ret +} + +// WithArgs implements ModuleConfig.WithArgs +func (c *moduleConfig) WithArgs(args ...string) ModuleConfig { + ret := c.clone() + ret.args = toByteSlices(args) + return ret +} + +func toByteSlices(strings []string) (result [][]byte) { + if len(strings) == 0 { + return + } + result = make([][]byte, len(strings)) + for i, a := range strings { + result[i] = []byte(a) + } + return +} + +// WithEnv implements ModuleConfig.WithEnv +func (c *moduleConfig) WithEnv(key, value string) ModuleConfig { + ret := c.clone() + // Check to see if this key already exists and update it. + if i, ok := ret.environKeys[key]; ok { + ret.environ[i+1] = []byte(value) // environ is pair-indexed, so the value is 1 after the key. + } else { + ret.environKeys[key] = len(ret.environ) + ret.environ = append(ret.environ, []byte(key), []byte(value)) + } + return ret +} + +// WithFS implements ModuleConfig.WithFS +func (c *moduleConfig) WithFS(fs fs.FS) ModuleConfig { + var config FSConfig + if fs != nil { + config = NewFSConfig().WithFSMount(fs, "") + } + return c.WithFSConfig(config) +} + +// WithFSConfig implements ModuleConfig.WithFSConfig +func (c *moduleConfig) WithFSConfig(config FSConfig) ModuleConfig { + ret := c.clone() + ret.fsConfig = config + return ret +} + +// WithName implements ModuleConfig.WithName +func (c *moduleConfig) WithName(name string) ModuleConfig { + ret := c.clone() + ret.nameSet = true + ret.name = name + return ret +} + +// WithStartFunctions implements ModuleConfig.WithStartFunctions +func (c *moduleConfig) WithStartFunctions(startFunctions ...string) ModuleConfig { + ret := c.clone() + ret.startFunctions = startFunctions + return ret +} + +// WithStderr implements ModuleConfig.WithStderr +func (c *moduleConfig) WithStderr(stderr io.Writer) ModuleConfig { + ret := c.clone() + ret.stderr = stderr + return ret +} + +// WithStdin implements ModuleConfig.WithStdin +func (c *moduleConfig) WithStdin(stdin io.Reader) ModuleConfig { + ret := c.clone() + ret.stdin = stdin + return ret +} + +// WithStdout implements ModuleConfig.WithStdout +func (c *moduleConfig) WithStdout(stdout io.Writer) ModuleConfig { + ret := c.clone() + ret.stdout = stdout + return ret +} + +// WithWalltime implements ModuleConfig.WithWalltime +func (c *moduleConfig) WithWalltime(walltime sys.Walltime, resolution sys.ClockResolution) ModuleConfig { + ret := c.clone() + ret.walltime = walltime + ret.walltimeResolution = resolution + return ret +} + +// We choose arbitrary resolutions here because there's no perfect alternative. For example, according to the +// source in time.go, windows monotonic resolution can be 15ms. This chooses arbitrarily 1us for wall time and +// 1ns for monotonic. See RATIONALE.md for more context. + +// WithSysWalltime implements ModuleConfig.WithSysWalltime +func (c *moduleConfig) WithSysWalltime() ModuleConfig { + return c.WithWalltime(platform.Walltime, sys.ClockResolution(time.Microsecond.Nanoseconds())) +} + +// WithNanotime implements ModuleConfig.WithNanotime +func (c *moduleConfig) WithNanotime(nanotime sys.Nanotime, resolution sys.ClockResolution) ModuleConfig { + ret := c.clone() + ret.nanotime = nanotime + ret.nanotimeResolution = resolution + return ret +} + +// WithSysNanotime implements ModuleConfig.WithSysNanotime +func (c *moduleConfig) WithSysNanotime() ModuleConfig { + return c.WithNanotime(platform.Nanotime, sys.ClockResolution(1)) +} + +// WithNanosleep implements ModuleConfig.WithNanosleep +func (c *moduleConfig) WithNanosleep(nanosleep sys.Nanosleep) ModuleConfig { + ret := *c // copy + ret.nanosleep = nanosleep + return &ret +} + +// WithOsyield implements ModuleConfig.WithOsyield +func (c *moduleConfig) WithOsyield(osyield sys.Osyield) ModuleConfig { + ret := *c // copy + ret.osyield = osyield + return &ret +} + +// WithSysNanosleep implements ModuleConfig.WithSysNanosleep +func (c *moduleConfig) WithSysNanosleep() ModuleConfig { + return c.WithNanosleep(platform.Nanosleep) +} + +// WithRandSource implements ModuleConfig.WithRandSource +func (c *moduleConfig) WithRandSource(source io.Reader) ModuleConfig { + ret := c.clone() + ret.randSource = source + return ret +} + +// toSysContext creates a baseline wasm.Context configured by ModuleConfig. +func (c *moduleConfig) toSysContext() (sysCtx *internalsys.Context, err error) { + var environ [][]byte // Intentionally doesn't pre-allocate to reduce logic to default to nil. + // Same validation as syscall.Setenv for Linux + for i := 0; i < len(c.environ); i += 2 { + key, value := c.environ[i], c.environ[i+1] + keyLen := len(key) + if keyLen == 0 { + err = errors.New("environ invalid: empty key") + return + } + valueLen := len(value) + result := make([]byte, keyLen+valueLen+1) + j := 0 + for ; j < keyLen; j++ { + if k := key[j]; k == '=' { // NUL enforced in NewContext + err = errors.New("environ invalid: key contains '=' character") + return + } else { + result[j] = k + } + } + result[j] = '=' + copy(result[j+1:], value) + environ = append(environ, result) + } + + var fs []experimentalsys.FS + var guestPaths []string + if f, ok := c.fsConfig.(*fsConfig); ok { + fs, guestPaths = f.preopens() + } + + var listeners []*net.TCPListener + if n := c.sockConfig; n != nil { + if listeners, err = n.BuildTCPListeners(); err != nil { + return + } + } + + return internalsys.NewContext( + math.MaxUint32, + c.args, + environ, + c.stdin, + c.stdout, + c.stderr, + c.randSource, + c.walltime, c.walltimeResolution, + c.nanotime, c.nanotimeResolution, + c.nanosleep, c.osyield, + fs, guestPaths, + listeners, + ) +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go b/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go new file mode 100644 index 00000000..c75db615 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go @@ -0,0 +1,35 @@ +package experimental + +import ( + "context" + + "github.com/tetratelabs/wazero/internal/expctxkeys" +) + +// Snapshot holds the execution state at the time of a Snapshotter.Snapshot call. +type Snapshot interface { + // Restore sets the Wasm execution state to the capture. Because a host function + // calling this is resetting the pointer to the executation stack, the host function + // will not be able to return values in the normal way. ret is a slice of values the + // host function intends to return from the restored function. + Restore(ret []uint64) +} + +// Snapshotter allows host functions to snapshot the WebAssembly execution environment. +type Snapshotter interface { + // Snapshot captures the current execution state. + Snapshot() Snapshot +} + +// WithSnapshotter enables snapshots. +// Passing the returned context to a exported function invocation enables snapshots, +// and allows host functions to retrieve the Snapshotter using GetSnapshotter. +func WithSnapshotter(ctx context.Context) context.Context { + return context.WithValue(ctx, expctxkeys.EnableSnapshotterKey{}, struct{}{}) +} + +// GetSnapshotter gets the Snapshotter from a host function. +// It is only present if WithSnapshotter was called with the function invocation context. +func GetSnapshotter(ctx context.Context) Snapshotter { + return ctx.Value(expctxkeys.SnapshotterKey{}).(Snapshotter) +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/close.go b/vendor/github.com/tetratelabs/wazero/experimental/close.go new file mode 100644 index 00000000..babecaec --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/close.go @@ -0,0 +1,63 @@ +package experimental + +import ( + "context" + + "github.com/tetratelabs/wazero/internal/expctxkeys" +) + +// CloseNotifier is a notification hook, invoked when a module is closed. +// +// Note: This is experimental progress towards #1197, and likely to change. Do +// not expose this in shared libraries as it can cause version locks. +type CloseNotifier interface { + // CloseNotify is a notification that occurs *before* an api.Module is + // closed. `exitCode` is zero on success or in the case there was no exit + // code. + // + // Notes: + // - This does not return an error because the module will be closed + // unconditionally. + // - Do not panic from this function as it doing so could cause resource + // leaks. + // - While this is only called once per module, if configured for + // multiple modules, it will be called for each, e.g. on runtime close. + CloseNotify(ctx context.Context, exitCode uint32) +} + +// ^-- Note: This might need to be a part of the listener or become a part of +// host state implementation. For example, if this is used to implement state +// cleanup for host modules, possibly something like below would be better, as +// it could be implemented in a way that allows concurrent module use. +// +// // key is like a context key, stateFactory is invoked per instantiate and +// // is associated with the key (exposed as `Module.State` similar to go +// // context). Using a key is better than the module name because we can +// // de-dupe it for host modules that can be instantiated into different +// // names. Also, you can make the key package private. +// HostModuleBuilder.WithState(key any, stateFactory func() Cleanup)` +// +// Such a design could work to isolate state only needed for wasip1, for +// example the dirent cache. However, if end users use this for different +// things, we may need separate designs. +// +// In summary, the purpose of this iteration is to identify projects that +// would use something like this, and then we can figure out which way it +// should go. + +// CloseNotifyFunc is a convenience for defining inlining a CloseNotifier. +type CloseNotifyFunc func(ctx context.Context, exitCode uint32) + +// CloseNotify implements CloseNotifier.CloseNotify. +func (f CloseNotifyFunc) CloseNotify(ctx context.Context, exitCode uint32) { + f(ctx, exitCode) +} + +// WithCloseNotifier registers the given CloseNotifier into the given +// context.Context. +func WithCloseNotifier(ctx context.Context, notifier CloseNotifier) context.Context { + if notifier != nil { + return context.WithValue(ctx, expctxkeys.CloseNotifierKey{}, notifier) + } + return ctx +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/experimental.go b/vendor/github.com/tetratelabs/wazero/experimental/experimental.go new file mode 100644 index 00000000..63fd564d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/experimental.go @@ -0,0 +1,41 @@ +// Package experimental includes features we aren't yet sure about. These are enabled with context.Context keys. +// +// Note: All features here may be changed or deleted at any time, so use with caution! +package experimental + +import ( + "github.com/tetratelabs/wazero/api" +) + +// InternalModule is an api.Module that exposes additional +// information. +type InternalModule interface { + api.Module + + // NumGlobal returns the count of all globals in the module. + NumGlobal() int + + // Global provides a read-only view for a given global index. + // + // The methods panics if i is out of bounds. + Global(i int) api.Global +} + +// ProgramCounter is an opaque value representing a specific execution point in +// a module. It is meant to be used with Function.SourceOffsetForPC and +// StackIterator. +type ProgramCounter uint64 + +// InternalFunction exposes some information about a function instance. +type InternalFunction interface { + // Definition provides introspection into the function's names and + // signature. + Definition() api.FunctionDefinition + + // SourceOffsetForPC resolves a program counter into its corresponding + // offset in the Code section of the module this function belongs to. + // The source offset is meant to help map the function calls to their + // location in the original source files. Returns 0 if the offset cannot + // be calculated. + SourceOffsetForPC(pc ProgramCounter) uint64 +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/features.go b/vendor/github.com/tetratelabs/wazero/experimental/features.go new file mode 100644 index 00000000..b2a5b906 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/features.go @@ -0,0 +1,15 @@ +package experimental + +import "github.com/tetratelabs/wazero/api" + +// CoreFeaturesThreads enables threads instructions ("threads"). +// +// # Notes +// +// - The instruction list is too long to enumerate in godoc. +// See https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md +// - Atomic operations are guest-only until api.Memory or otherwise expose them to host functions. +// - On systems without mmap available, the memory will pre-allocate to the maximum size. Many +// binaries will use a theroetical maximum like 4GB, so if using such a binary on a system +// without mmap, consider editing the binary to reduce the max size setting of memory. +const CoreFeaturesThreads = api.CoreFeatureSIMD << 1 diff --git a/vendor/github.com/tetratelabs/wazero/experimental/importresolver.go b/vendor/github.com/tetratelabs/wazero/experimental/importresolver.go new file mode 100644 index 00000000..36c0e22b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/importresolver.go @@ -0,0 +1,19 @@ +package experimental + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/expctxkeys" +) + +// ImportResolver is an experimental func type that, if set, +// will be used as the first step in resolving imports. +// See issue 2294. +// If the import name is not found, it should return nil. +type ImportResolver func(name string) api.Module + +// WithImportResolver returns a new context with the given ImportResolver. +func WithImportResolver(ctx context.Context, resolver ImportResolver) context.Context { + return context.WithValue(ctx, expctxkeys.ImportResolverKey{}, resolver) +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/listener.go b/vendor/github.com/tetratelabs/wazero/experimental/listener.go new file mode 100644 index 00000000..55fc6b66 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/listener.go @@ -0,0 +1,324 @@ +package experimental + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/expctxkeys" +) + +// StackIterator allows iterating on each function of the call stack, starting +// from the top. At least one call to Next() is required to start the iteration. +// +// Note: The iterator provides a view of the call stack at the time of +// iteration. As a result, parameter values may be different than the ones their +// function was called with. +type StackIterator interface { + // Next moves the iterator to the next function in the stack. Returns + // false if it reached the bottom of the stack. + Next() bool + // Function describes the function called by the current frame. + Function() InternalFunction + // ProgramCounter returns the program counter associated with the + // function call. + ProgramCounter() ProgramCounter +} + +// WithFunctionListenerFactory registers a FunctionListenerFactory +// with the context. +func WithFunctionListenerFactory(ctx context.Context, factory FunctionListenerFactory) context.Context { + return context.WithValue(ctx, expctxkeys.FunctionListenerFactoryKey{}, factory) +} + +// FunctionListenerFactory returns FunctionListeners to be notified when a +// function is called. +type FunctionListenerFactory interface { + // NewFunctionListener returns a FunctionListener for a defined function. + // If nil is returned, no listener will be notified. + NewFunctionListener(api.FunctionDefinition) FunctionListener + // ^^ A single instance can be returned to avoid instantiating a listener + // per function, especially as they may be thousands of functions. Shared + // listeners use their FunctionDefinition parameter to clarify. +} + +// FunctionListener can be registered for any function via +// FunctionListenerFactory to be notified when the function is called. +type FunctionListener interface { + // Before is invoked before a function is called. + // + // There is always one corresponding call to After or Abort for each call to + // Before. This guarantee allows the listener to maintain an internal stack + // to perform correlations between the entry and exit of functions. + // + // # Params + // + // - ctx: the context of the caller function which must be the same + // instance or parent of the result. + // - mod: the calling module. + // - def: the function definition. + // - params: api.ValueType encoded parameters. + // - stackIterator: iterator on the call stack. At least one entry is + // guaranteed (the called function), whose Args() will be equal to + // params. The iterator will be reused between calls to Before. + // + // Note: api.Memory is meant for inspection, not modification. + // mod can be cast to InternalModule to read non-exported globals. + Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator) + + // After is invoked after a function is called. + // + // # Params + // + // - ctx: the context of the caller function. + // - mod: the calling module. + // - def: the function definition. + // - results: api.ValueType encoded results. + // + // # Notes + // + // - api.Memory is meant for inspection, not modification. + // - This is not called when a host function panics, or a guest function traps. + // See Abort for more details. + After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64) + + // Abort is invoked when a function does not return due to a trap or panic. + // + // # Params + // + // - ctx: the context of the caller function. + // - mod: the calling module. + // - def: the function definition. + // - err: the error value representing the reason why the function aborted. + // + // # Notes + // + // - api.Memory is meant for inspection, not modification. + Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error) +} + +// FunctionListenerFunc is a function type implementing the FunctionListener +// interface, making it possible to use regular functions and methods as +// listeners of function invocation. +// +// The FunctionListener interface declares two methods (Before and After), +// but this type invokes its value only when Before is called. It is best +// suites for cases where the host does not need to perform correlation +// between the start and end of the function call. +type FunctionListenerFunc func(context.Context, api.Module, api.FunctionDefinition, []uint64, StackIterator) + +// Before satisfies the FunctionListener interface, calls f. +func (f FunctionListenerFunc) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator) { + f(ctx, mod, def, params, stackIterator) +} + +// After is declared to satisfy the FunctionListener interface, but it does +// nothing. +func (f FunctionListenerFunc) After(context.Context, api.Module, api.FunctionDefinition, []uint64) { +} + +// Abort is declared to satisfy the FunctionListener interface, but it does +// nothing. +func (f FunctionListenerFunc) Abort(context.Context, api.Module, api.FunctionDefinition, error) { +} + +// FunctionListenerFactoryFunc is a function type implementing the +// FunctionListenerFactory interface, making it possible to use regular +// functions and methods as factory of function listeners. +type FunctionListenerFactoryFunc func(api.FunctionDefinition) FunctionListener + +// NewFunctionListener satisfies the FunctionListenerFactory interface, calls f. +func (f FunctionListenerFactoryFunc) NewFunctionListener(def api.FunctionDefinition) FunctionListener { + return f(def) +} + +// MultiFunctionListenerFactory constructs a FunctionListenerFactory which +// combines the listeners created by each of the factories passed as arguments. +// +// This function is useful when multiple listeners need to be hooked to a module +// because the propagation mechanism based on installing a listener factory in +// the context.Context used when instantiating modules allows for a single +// listener to be installed. +// +// The stack iterator passed to the Before method is reset so that each listener +// can iterate the call stack independently without impacting the ability of +// other listeners to do so. +func MultiFunctionListenerFactory(factories ...FunctionListenerFactory) FunctionListenerFactory { + multi := make(multiFunctionListenerFactory, len(factories)) + copy(multi, factories) + return multi +} + +type multiFunctionListenerFactory []FunctionListenerFactory + +func (multi multiFunctionListenerFactory) NewFunctionListener(def api.FunctionDefinition) FunctionListener { + var lstns []FunctionListener + for _, factory := range multi { + if lstn := factory.NewFunctionListener(def); lstn != nil { + lstns = append(lstns, lstn) + } + } + switch len(lstns) { + case 0: + return nil + case 1: + return lstns[0] + default: + return &multiFunctionListener{lstns: lstns} + } +} + +type multiFunctionListener struct { + lstns []FunctionListener + stack stackIterator +} + +func (multi *multiFunctionListener) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si StackIterator) { + multi.stack.base = si + for _, lstn := range multi.lstns { + multi.stack.index = -1 + lstn.Before(ctx, mod, def, params, &multi.stack) + } +} + +func (multi *multiFunctionListener) After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64) { + for _, lstn := range multi.lstns { + lstn.After(ctx, mod, def, results) + } +} + +func (multi *multiFunctionListener) Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error) { + for _, lstn := range multi.lstns { + lstn.Abort(ctx, mod, def, err) + } +} + +type stackIterator struct { + base StackIterator + index int + pcs []uint64 + fns []InternalFunction +} + +func (si *stackIterator) Next() bool { + if si.base != nil { + si.pcs = si.pcs[:0] + si.fns = si.fns[:0] + + for si.base.Next() { + si.pcs = append(si.pcs, uint64(si.base.ProgramCounter())) + si.fns = append(si.fns, si.base.Function()) + } + + si.base = nil + } + si.index++ + return si.index < len(si.pcs) +} + +func (si *stackIterator) ProgramCounter() ProgramCounter { + return ProgramCounter(si.pcs[si.index]) +} + +func (si *stackIterator) Function() InternalFunction { + return si.fns[si.index] +} + +// StackFrame represents a frame on the call stack. +type StackFrame struct { + Function api.Function + Params []uint64 + Results []uint64 + PC uint64 + SourceOffset uint64 +} + +type internalFunction struct { + definition api.FunctionDefinition + sourceOffset uint64 +} + +func (f internalFunction) Definition() api.FunctionDefinition { + return f.definition +} + +func (f internalFunction) SourceOffsetForPC(pc ProgramCounter) uint64 { + return f.sourceOffset +} + +// stackFrameIterator is an implementation of the experimental.stackFrameIterator +// interface. +type stackFrameIterator struct { + index int + stack []StackFrame + fndef []api.FunctionDefinition +} + +func (si *stackFrameIterator) Next() bool { + si.index++ + return si.index < len(si.stack) +} + +func (si *stackFrameIterator) Function() InternalFunction { + return internalFunction{ + definition: si.fndef[si.index], + sourceOffset: si.stack[si.index].SourceOffset, + } +} + +func (si *stackFrameIterator) ProgramCounter() ProgramCounter { + return ProgramCounter(si.stack[si.index].PC) +} + +// NewStackIterator constructs a stack iterator from a list of stack frames. +// The top most frame is the last one. +func NewStackIterator(stack ...StackFrame) StackIterator { + si := &stackFrameIterator{ + index: -1, + stack: make([]StackFrame, len(stack)), + fndef: make([]api.FunctionDefinition, len(stack)), + } + for i := range stack { + si.stack[i] = stack[len(stack)-(i+1)] + } + // The size of function definition is only one pointer which should allow + // the compiler to optimize the conversion to api.FunctionDefinition; but + // the presence of internal.WazeroOnlyType, despite being defined as an + // empty struct, forces a heap allocation that we amortize by caching the + // result. + for i, frame := range stack { + si.fndef[i] = frame.Function.Definition() + } + return si +} + +// BenchmarkFunctionListener implements a benchmark for function listeners. +// +// The benchmark calls Before and After methods repeatedly using the provided +// module an stack frames to invoke the methods. +// +// The stack frame is a representation of the call stack that the Before method +// will be invoked with. The top of the stack is stored at index zero. The stack +// must contain at least one frame or the benchmark will fail. +func BenchmarkFunctionListener(n int, module api.Module, stack []StackFrame, listener FunctionListener) { + if len(stack) == 0 { + panic("cannot benchmark function listener with an empty stack") + } + + ctx := context.Background() + def := stack[0].Function.Definition() + params := stack[0].Params + results := stack[0].Results + stackIterator := &stackIterator{base: NewStackIterator(stack...)} + + for i := 0; i < n; i++ { + stackIterator.index = -1 + listener.Before(ctx, module, def, params, stackIterator) + listener.After(ctx, module, def, results) + } +} + +// TODO: the calls to Abort are not yet tested in internal/testing/enginetest, +// but they are validated indirectly in tests which exercise host logging, +// like Test_procExit in imports/wasi_snapshot_preview1. Eventually we should +// add dedicated tests to validate the behavior of the interpreter and compiler +// engines independently. diff --git a/vendor/github.com/tetratelabs/wazero/experimental/memory.go b/vendor/github.com/tetratelabs/wazero/experimental/memory.go new file mode 100644 index 00000000..8bf3aa35 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/memory.go @@ -0,0 +1,52 @@ +package experimental + +import ( + "context" + + "github.com/tetratelabs/wazero/internal/expctxkeys" +) + +// MemoryAllocator is a memory allocation hook, +// invoked to create a LinearMemory. +type MemoryAllocator interface { + // Allocate should create a new LinearMemory with the given specification: + // cap is the suggested initial capacity for the backing []byte, + // and max the maximum length that will ever be requested. + // + // Notes: + // - To back a shared memory, the address of the backing []byte cannot + // change. This is checked at runtime. Implementations should document + // if the returned LinearMemory meets this requirement. + Allocate(cap, max uint64) LinearMemory +} + +// MemoryAllocatorFunc is a convenience for defining inlining a MemoryAllocator. +type MemoryAllocatorFunc func(cap, max uint64) LinearMemory + +// Allocate implements MemoryAllocator.Allocate. +func (f MemoryAllocatorFunc) Allocate(cap, max uint64) LinearMemory { + return f(cap, max) +} + +// LinearMemory is an expandable []byte that backs a Wasm linear memory. +type LinearMemory interface { + // Reallocates the linear memory to size bytes in length. + // + // Notes: + // - To back a shared memory, Reallocate can't change the address of the + // backing []byte (only its length/capacity may change). + // - Reallocate may return nil if fails to grow the LinearMemory. This + // condition may or may not be handled gracefully by the Wasm module. + Reallocate(size uint64) []byte + // Free the backing memory buffer. + Free() +} + +// WithMemoryAllocator registers the given MemoryAllocator into the given +// context.Context. The context must be passed when initializing a module. +func WithMemoryAllocator(ctx context.Context, allocator MemoryAllocator) context.Context { + if allocator != nil { + return context.WithValue(ctx, expctxkeys.MemoryAllocatorKey{}, allocator) + } + return ctx +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go new file mode 100644 index 00000000..0b997cb8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go @@ -0,0 +1,92 @@ +package sys + +import ( + "fmt" + "io/fs" + + "github.com/tetratelabs/wazero/sys" +) + +// FileType is fs.FileMode masked on fs.ModeType. For example, zero is a +// regular file, fs.ModeDir is a directory and fs.ModeIrregular is unknown. +// +// Note: This is defined by Linux, not POSIX. +type FileType = fs.FileMode + +// Dirent is an entry read from a directory via File.Readdir. +// +// # Notes +// +// - This extends `dirent` defined in POSIX with some fields defined by +// Linux. See https://man7.org/linux/man-pages/man3/readdir.3.html and +// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html +// - This has a subset of fields defined in sys.Stat_t. Notably, there is no +// field corresponding to Stat_t.Dev because that value will be constant +// for all files in a directory. To get the Dev value, call File.Stat on +// the directory File.Readdir was called on. +type Dirent struct { + // Ino is the file serial number, or zero if not available. See Ino for + // more details including impact returning a zero value. + Ino sys.Inode + + // Name is the base name of the directory entry. Empty is invalid. + Name string + + // Type is fs.FileMode masked on fs.ModeType. For example, zero is a + // regular file, fs.ModeDir is a directory and fs.ModeIrregular is unknown. + // + // Note: This is defined by Linux, not POSIX. + Type fs.FileMode +} + +func (d *Dirent) String() string { + return fmt.Sprintf("name=%s, type=%v, ino=%d", d.Name, d.Type, d.Ino) +} + +// IsDir returns true if the Type is fs.ModeDir. +func (d *Dirent) IsDir() bool { + return d.Type == fs.ModeDir +} + +// DirFile is embeddable to reduce the amount of functions to implement a file. +type DirFile struct{} + +// IsAppend implements File.IsAppend +func (DirFile) IsAppend() bool { + return false +} + +// SetAppend implements File.SetAppend +func (DirFile) SetAppend(bool) Errno { + return EISDIR +} + +// IsDir implements File.IsDir +func (DirFile) IsDir() (bool, Errno) { + return true, 0 +} + +// Read implements File.Read +func (DirFile) Read([]byte) (int, Errno) { + return 0, EISDIR +} + +// Pread implements File.Pread +func (DirFile) Pread([]byte, int64) (int, Errno) { + return 0, EISDIR +} + +// Write implements File.Write +func (DirFile) Write([]byte) (int, Errno) { + return 0, EISDIR +} + +// Pwrite implements File.Pwrite +func (DirFile) Pwrite([]byte, int64) (int, Errno) { + return 0, EISDIR +} + +// Truncate implements File.Truncate +func (DirFile) Truncate(int64) Errno { + return EISDIR +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go new file mode 100644 index 00000000..23894949 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go @@ -0,0 +1,98 @@ +package sys + +import "strconv" + +// Errno is a subset of POSIX errno used by wazero interfaces. Zero is not an +// error. Other values should not be interpreted numerically, rather by constants +// prefixed with 'E'. +// +// See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html +type Errno uint16 + +// ^-- Note: This will eventually move to the public /sys package. It is +// experimental until we audit the socket related APIs to ensure we have all +// the Errno it returns, and we export fs.FS. This is not in /internal/sys as +// that would introduce a package cycle. + +// This is a subset of errors to reduce implementation burden. `wasip1` defines +// almost all POSIX error numbers, but not all are used in practice. wazero +// will add ones needed in POSIX order, as needed by functions that explicitly +// document returning them. +// +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16 +const ( + EACCES Errno = iota + 1 + EAGAIN + EBADF + EEXIST + EFAULT + EINTR + EINVAL + EIO + EISDIR + ELOOP + ENAMETOOLONG + ENOENT + ENOSYS + ENOTDIR + ERANGE + ENOTEMPTY + ENOTSOCK + ENOTSUP + EPERM + EROFS + + // NOTE ENOTCAPABLE is defined in wasip1, but not in POSIX. wasi-libc + // converts it to EBADF, ESPIPE or EINVAL depending on the call site. + // It isn't known if compilers who don't use ENOTCAPABLE would crash on it. +) + +// Error implements error +func (e Errno) Error() string { + switch e { + case 0: // not an error + return "success" + case EACCES: + return "permission denied" + case EAGAIN: + return "resource unavailable, try again" + case EBADF: + return "bad file descriptor" + case EEXIST: + return "file exists" + case EFAULT: + return "bad address" + case EINTR: + return "interrupted function" + case EINVAL: + return "invalid argument" + case EIO: + return "input/output error" + case EISDIR: + return "is a directory" + case ELOOP: + return "too many levels of symbolic links" + case ENAMETOOLONG: + return "filename too long" + case ENOENT: + return "no such file or directory" + case ENOSYS: + return "functionality not supported" + case ENOTDIR: + return "not a directory or a symbolic link to a directory" + case ERANGE: + return "result too large" + case ENOTEMPTY: + return "directory not empty" + case ENOTSOCK: + return "not a socket" + case ENOTSUP: + return "not supported (may be the same value as [EOPNOTSUPP])" + case EPERM: + return "operation not permitted" + case EROFS: + return "read-only file system" + default: + return "Errno(" + strconv.Itoa(int(e)) + ")" + } +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go new file mode 100644 index 00000000..a0c76019 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go @@ -0,0 +1,45 @@ +package sys + +import ( + "io" + "io/fs" + "os" +) + +// UnwrapOSError returns an Errno or zero if the input is nil. +func UnwrapOSError(err error) Errno { + if err == nil { + return 0 + } + err = underlyingError(err) + switch err { + case nil, io.EOF: + return 0 // EOF is not a Errno + case fs.ErrInvalid: + return EINVAL + case fs.ErrPermission: + return EPERM + case fs.ErrExist: + return EEXIST + case fs.ErrNotExist: + return ENOENT + case fs.ErrClosed: + return EBADF + } + return errorToErrno(err) +} + +// underlyingError returns the underlying error if a well-known OS error type. +// +// This impl is basically the same as os.underlyingError in os/error.go +func underlyingError(err error) error { + switch err := err.(type) { + case *os.PathError: + return err.Err + case *os.LinkError: + return err.Err + case *os.SyscallError: + return err.Err + } + return err +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go new file mode 100644 index 00000000..b6bfbcfe --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go @@ -0,0 +1,316 @@ +package sys + +import "github.com/tetratelabs/wazero/sys" + +// File is a writeable fs.File bridge backed by syscall functions needed for ABI +// including WASI. +// +// Implementations should embed UnimplementedFile for forward compatibility. Any +// unsupported method or parameter should return ENOSYS. +// +// # Errors +// +// All methods that can return an error return a Errno, which is zero +// on success. +// +// Restricting to Errno matches current WebAssembly host functions, +// which are constrained to well-known error codes. For example, WASI maps syscall +// errors to u32 numeric values. +// +// # Notes +// +// - You must call Close to avoid file resource conflicts. For example, +// Windows cannot delete the underlying directory while a handle to it +// remains open. +// - A writable filesystem abstraction is not yet implemented as of Go 1.20. +// See https://github.com/golang/go/issues/45757 +type File interface { + // Dev returns the device ID (Stat_t.Dev) of this file, zero if unknown or + // an error retrieving it. + // + // # Errors + // + // Possible errors are those from Stat, except ENOSYS should not + // be returned. Zero should be returned if there is no implementation. + // + // # Notes + // + // - Implementations should cache this result. + // - This combined with Ino can implement os.SameFile. + Dev() (uint64, Errno) + + // Ino returns the serial number (Stat_t.Ino) of this file, zero if unknown + // or an error retrieving it. + // + // # Errors + // + // Possible errors are those from Stat, except ENOSYS should not + // be returned. Zero should be returned if there is no implementation. + // + // # Notes + // + // - Implementations should cache this result. + // - This combined with Dev can implement os.SameFile. + Ino() (sys.Inode, Errno) + + // IsDir returns true if this file is a directory or an error there was an + // error retrieving this information. + // + // # Errors + // + // Possible errors are those from Stat, except ENOSYS should not + // be returned. false should be returned if there is no implementation. + // + // # Notes + // + // - Implementations should cache this result. + IsDir() (bool, Errno) + + // IsAppend returns true if the file was opened with O_APPEND, or + // SetAppend was successfully enabled on this file. + // + // # Notes + // + // - This might not match the underlying state of the file descriptor if + // the file was not opened via OpenFile. + IsAppend() bool + + // SetAppend toggles the append mode (O_APPEND) of this file. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - There is no `O_APPEND` for `fcntl` in POSIX, so implementations may + // have to re-open the underlying file to apply this. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html + SetAppend(enable bool) Errno + + // Stat is similar to syscall.Fstat. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - This is like syscall.Fstat and `fstatat` with `AT_FDCWD` in POSIX. + // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html + // - A fs.FileInfo backed implementation sets atim, mtim and ctim to the + // same value. + // - Windows allows you to stat a closed directory. + Stat() (sys.Stat_t, Errno) + + // Read attempts to read all bytes in the file into `buf`, and returns the + // count read even on error. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EISDIR: the file was a directory. + // + // # Notes + // + // - This is like io.Reader and `read` in POSIX, preferring semantics of + // io.Reader. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html + // - Unlike io.Reader, there is no io.EOF returned on end-of-file. To + // read the file completely, the caller must repeat until `n` is zero. + Read(buf []byte) (n int, errno Errno) + + // Pread attempts to read all bytes in the file into `p`, starting at the + // offset `off`, and returns the count read even on error. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EINVAL: the offset was negative. + // - EISDIR: the file was a directory. + // + // # Notes + // + // - This is like io.ReaderAt and `pread` in POSIX, preferring semantics + // of io.ReaderAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html + // - Unlike io.ReaderAt, there is no io.EOF returned on end-of-file. To + // read the file completely, the caller must repeat until `n` is zero. + Pread(buf []byte, off int64) (n int, errno Errno) + + // Seek attempts to set the next offset for Read or Write and returns the + // resulting absolute offset or an error. + // + // # Parameters + // + // The `offset` parameters is interpreted in terms of `whence`: + // - io.SeekStart: relative to the start of the file, e.g. offset=0 sets + // the next Read or Write to the beginning of the file. + // - io.SeekCurrent: relative to the current offset, e.g. offset=16 sets + // the next Read or Write 16 bytes past the prior. + // - io.SeekEnd: relative to the end of the file, e.g. offset=-1 sets the + // next Read or Write to the last byte in the file. + // + // # Behavior when a directory + // + // The only supported use case for a directory is seeking to `offset` zero + // (`whence` = io.SeekStart). This should have the same behavior as + // os.File, which resets any internal state used by Readdir. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EINVAL: the offset was negative. + // + // # Notes + // + // - This is like io.Seeker and `fseek` in POSIX, preferring semantics + // of io.Seeker. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html + Seek(offset int64, whence int) (newOffset int64, errno Errno) + + // Readdir reads the contents of the directory associated with file and + // returns a slice of up to n Dirent values in an arbitrary order. This is + // a stateful function, so subsequent calls return any next values. + // + // If n > 0, Readdir returns at most n entries or an error. + // If n <= 0, Readdir returns all remaining entries or an error. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file was closed or not a directory. + // - ENOENT: the directory could not be read (e.g. deleted). + // + // # Notes + // + // - This is like `Readdir` on os.File, but unlike `readdir` in POSIX. + // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html + // - Unlike os.File, there is no io.EOF returned on end-of-directory. To + // read the directory completely, the caller must repeat until the + // count read (`len(dirents)`) is less than `n`. + // - See /RATIONALE.md for design notes. + Readdir(n int) (dirents []Dirent, errno Errno) + + // Write attempts to write all bytes in `p` to the file, and returns the + // count written even on error. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file was closed, not writeable, or a directory. + // + // # Notes + // + // - This is like io.Writer and `write` in POSIX, preferring semantics of + // io.Writer. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html + Write(buf []byte) (n int, errno Errno) + + // Pwrite attempts to write all bytes in `p` to the file at the given + // offset `off`, and returns the count written even on error. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not writeable. + // - EINVAL: the offset was negative. + // - EISDIR: the file was a directory. + // + // # Notes + // + // - This is like io.WriterAt and `pwrite` in POSIX, preferring semantics + // of io.WriterAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html + Pwrite(buf []byte, off int64) (n int, errno Errno) + + // Truncate truncates a file to a specified length. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // - EINVAL: the `size` is negative. + // - EISDIR: the file was a directory. + // + // # Notes + // + // - This is like syscall.Ftruncate and `ftruncate` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html + // - Windows does not error when calling Truncate on a closed file. + Truncate(size int64) Errno + + // Sync synchronizes changes to the file. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - This is like syscall.Fsync and `fsync` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html + // - This returns with no error instead of ENOSYS when + // unimplemented. This prevents fake filesystems from erring. + // - Windows does not error when calling Sync on a closed file. + Sync() Errno + + // Datasync synchronizes the data of a file. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - This is like syscall.Fdatasync and `fdatasync` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html + // - This returns with no error instead of ENOSYS when + // unimplemented. This prevents fake filesystems from erring. + // - As this is commonly missing, some implementations dispatch to Sync. + Datasync() Errno + + // Utimens set file access and modification times of this file, at + // nanosecond precision. + // + // # Parameters + // + // The `atim` and `mtim` parameters refer to access and modification time + // stamps as defined in sys.Stat_t. To retain one or the other, substitute + // it with the pseudo-timestamp UTIME_OMIT. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - This is like syscall.UtimesNano and `futimens` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html + // - Windows requires files to be open with O_RDWR, which means you + // cannot use this to update timestamps on a directory (EPERM). + Utimens(atim, mtim int64) Errno + + // Close closes the underlying file. + // + // A zero Errno is returned if unimplemented or success. + // + // # Notes + // + // - This is like syscall.Close and `close` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html + Close() Errno +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go new file mode 100644 index 00000000..87810510 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go @@ -0,0 +1,292 @@ +package sys + +import ( + "io/fs" + + "github.com/tetratelabs/wazero/sys" +) + +// FS is a writeable fs.FS bridge backed by syscall functions needed for ABI +// including WASI. +// +// Implementations should embed UnimplementedFS for forward compatibility. Any +// unsupported method or parameter should return ENO +// +// # Errors +// +// All methods that can return an error return a Errno, which is zero +// on success. +// +// Restricting to Errno matches current WebAssembly host functions, +// which are constrained to well-known error codes. For example, WASI maps syscall +// errors to u32 numeric values. +// +// # Notes +// +// A writable filesystem abstraction is not yet implemented as of Go 1.20. See +// https://github.com/golang/go/issues/45757 +type FS interface { + // OpenFile opens a file. It should be closed via Close on File. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` or `flag` is invalid. + // - EISDIR: the path was a directory, but flag included O_RDWR or + // O_WRONLY + // - ENOENT: `path` doesn't exist and `flag` doesn't contain O_CREAT. + // + // # Constraints on the returned file + // + // Implementations that can read flags should enforce them regardless of + // the type returned. For example, while os.File implements io.Writer, + // attempts to write to a directory or a file opened with O_RDONLY fail + // with a EBADF. + // + // Some implementations choose whether to enforce read-only opens, namely + // fs.FS. While fs.FS is supported (Adapt), wazero cannot runtime enforce + // open flags. Instead, we encourage good behavior and test our built-in + // implementations. + // + // # Notes + // + // - This is like os.OpenFile, except the path is relative to this file + // system, and Errno is returned instead of os.PathError. + // - Implications of permissions when O_CREAT are described in Chmod notes. + // - This is like `open` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html + OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno) + + // Lstat gets file status without following symbolic links. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - ENOENT: `path` doesn't exist. + // + // # Notes + // + // - This is like syscall.Lstat, except the `path` is relative to this + // file system. + // - This is like `lstat` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html + // - An fs.FileInfo backed implementation sets atim, mtim and ctim to the + // same value. + // - When the path is a symbolic link, the stat returned is for the link, + // not the file it refers to. + Lstat(path string) (sys.Stat_t, Errno) + + // Stat gets file status. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - ENOENT: `path` doesn't exist. + // + // # Notes + // + // - This is like syscall.Stat, except the `path` is relative to this + // file system. + // - This is like `stat` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html + // - An fs.FileInfo backed implementation sets atim, mtim and ctim to the + // same value. + // - When the path is a symbolic link, the stat returned is for the file + // it refers to. + Stat(path string) (sys.Stat_t, Errno) + + // Mkdir makes a directory. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - EEXIST: `path` exists and is a directory. + // - ENOTDIR: `path` exists and is a file. + // + // # Notes + // + // - This is like syscall.Mkdir, except the `path` is relative to this + // file system. + // - This is like `mkdir` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html + // - Implications of permissions are described in Chmod notes. + Mkdir(path string, perm fs.FileMode) Errno + + // Chmod changes the mode of the file. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` does not exist. + // + // # Notes + // + // - This is like syscall.Chmod, except the `path` is relative to this + // file system. + // - This is like `chmod` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html + // - Windows ignores the execute bit, and any permissions come back as + // group and world. For example, chmod of 0400 reads back as 0444, and + // 0700 0666. Also, permissions on directories aren't supported at all. + Chmod(path string, perm fs.FileMode) Errno + + // Rename renames file or directory. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `from` or `to` is invalid. + // - ENOENT: `from` or `to` don't exist. + // - ENOTDIR: `from` is a directory and `to` exists as a file. + // - EISDIR: `from` is a file and `to` exists as a directory. + // - ENOTEMPTY: `both from` and `to` are existing directory, but + // `to` is not empty. + // + // # Notes + // + // - This is like syscall.Rename, except the paths are relative to this + // file system. + // - This is like `rename` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html + // - Windows doesn't let you overwrite an existing directory. + Rename(from, to string) Errno + + // Rmdir removes a directory. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` doesn't exist. + // - ENOTDIR: `path` exists, but isn't a directory. + // - ENOTEMPTY: `path` exists, but isn't empty. + // + // # Notes + // + // - This is like syscall.Rmdir, except the `path` is relative to this + // file system. + // - This is like `rmdir` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html + // - As of Go 1.19, Windows maps ENOTDIR to ENOENT. + Rmdir(path string) Errno + + // Unlink removes a directory entry. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` doesn't exist. + // - EISDIR: `path` exists, but is a directory. + // + // # Notes + // + // - This is like syscall.Unlink, except the `path` is relative to this + // file system. + // - This is like `unlink` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html + // - On Windows, syscall.Unlink doesn't delete symlink to directory unlike other platforms. Implementations might + // want to combine syscall.RemoveDirectory with syscall.Unlink in order to delete such links on Windows. + // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya + Unlink(path string) Errno + + // Link creates a "hard" link from oldPath to newPath, in contrast to a + // soft link (via Symlink). + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EPERM: `oldPath` is invalid. + // - ENOENT: `oldPath` doesn't exist. + // - EISDIR: `newPath` exists, but is a directory. + // + // # Notes + // + // - This is like syscall.Link, except the `oldPath` is relative to this + // file system. + // - This is like `link` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html + Link(oldPath, newPath string) Errno + + // Symlink creates a "soft" link from oldPath to newPath, in contrast to a + // hard link (via Link). + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EPERM: `oldPath` or `newPath` is invalid. + // - EEXIST: `newPath` exists. + // + // # Notes + // + // - This is like syscall.Symlink, except the `oldPath` is relative to + // this file system. + // - This is like `symlink` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html + // - Only `newPath` is relative to this file system and `oldPath` is kept + // as-is. That is because the link is only resolved relative to the + // directory when dereferencing it (e.g. ReadLink). + // See https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409 + // for how others implement this. + // - Symlinks in Windows requires `SeCreateSymbolicLinkPrivilege`. + // Otherwise, EPERM results. + // See https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links + Symlink(oldPath, linkName string) Errno + + // Readlink reads the contents of a symbolic link. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // + // # Notes + // + // - This is like syscall.Readlink, except the path is relative to this + // filesystem. + // - This is like `readlink` in POSIX. See + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html + // - On Windows, the path separator is different from other platforms, + // but to provide consistent results to Wasm, this normalizes to a "/" + // separator. + Readlink(path string) (string, Errno) + + // Utimens set file access and modification times on a path relative to + // this file system, at nanosecond precision. + // + // # Parameters + // + // If the path is a symbolic link, the target of expanding that link is + // updated. + // + // The `atim` and `mtim` parameters refer to access and modification time + // stamps as defined in sys.Stat_t. To retain one or the other, substitute + // it with the pseudo-timestamp UTIME_OMIT. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - EEXIST: `path` exists and is a directory. + // - ENOTDIR: `path` exists and is a file. + // + // # Notes + // + // - This is like syscall.UtimesNano and `utimensat` with `AT_FDCWD` in + // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html + Utimens(path string, atim, mtim int64) Errno +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go new file mode 100644 index 00000000..39ebd378 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go @@ -0,0 +1,70 @@ +package sys + +// Oflag are flags used for FS.OpenFile. Values, including zero, should not be +// interpreted numerically. Instead, use by constants prefixed with 'O_' with +// special casing noted below. +// +// # Notes +// +// - O_RDONLY, O_RDWR and O_WRONLY are mutually exclusive, while the other +// flags can coexist bitwise. +// - This is like `flag` in os.OpenFile and `oflag` in POSIX. See +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html +type Oflag uint32 + +// This is a subset of oflags to reduce implementation burden. `wasip1` splits +// these across `oflags` and `fdflags`. We can't rely on the Go `os` package, +// as it is missing some values. Any flags added will be defined in POSIX +// order, as needed by functions that explicitly document accepting them. +// +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16 +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fdflags-flagsu16 +const ( + // O_RDONLY is like os.O_RDONLY + O_RDONLY Oflag = iota + + // O_RDWR is like os.O_RDWR + O_RDWR + + // O_WRONLY is like os.O_WRONLY + O_WRONLY + + // Define bitflags as they are in POSIX `open`: alphabetically + + // O_APPEND is like os.O_APPEND + O_APPEND Oflag = 1 << iota + + // O_CREAT is link os.O_CREATE + O_CREAT + + // O_DIRECTORY is defined on some platforms as syscall.O_DIRECTORY. + // + // Note: This ensures that the opened file is a directory. Those emulating + // on platforms that don't support the O_DIRECTORY, can double-check the + // result with File.IsDir (or stat) and err if not a directory. + O_DIRECTORY + + // O_DSYNC is defined on some platforms as syscall.O_DSYNC. + O_DSYNC + + // O_EXCL is defined on some platforms as syscall.O_EXCL. + O_EXCL + + // O_NOFOLLOW is defined on some platforms as syscall.O_NOFOLLOW. + // + // Note: This allows programs to ensure that if the opened file is a + // symbolic link, the link itself is opened instead of its target. + O_NOFOLLOW + + // O_NONBLOCK is defined on some platforms as syscall.O_NONBLOCK. + O_NONBLOCK + + // O_RSYNC is defined on some platforms as syscall.O_RSYNC. + O_RSYNC + + // O_SYNC is defined on some platforms as syscall.O_SYNC. + O_SYNC + + // O_TRUNC is defined on some platforms as syscall.O_TRUNC. + O_TRUNC +) diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go new file mode 100644 index 00000000..ea511ec2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go @@ -0,0 +1,106 @@ +//go:build !plan9 && !aix + +package sys + +import "syscall" + +func syscallToErrno(err error) (Errno, bool) { + errno, ok := err.(syscall.Errno) + if !ok { + return 0, false + } + switch errno { + case 0: + return 0, true + case syscall.EACCES: + return EACCES, true + case syscall.EAGAIN: + return EAGAIN, true + case syscall.EBADF: + return EBADF, true + case syscall.EEXIST: + return EEXIST, true + case syscall.EFAULT: + return EFAULT, true + case syscall.EINTR: + return EINTR, true + case syscall.EINVAL: + return EINVAL, true + case syscall.EIO: + return EIO, true + case syscall.EISDIR: + return EISDIR, true + case syscall.ELOOP: + return ELOOP, true + case syscall.ENAMETOOLONG: + return ENAMETOOLONG, true + case syscall.ENOENT: + return ENOENT, true + case syscall.ENOSYS: + return ENOSYS, true + case syscall.ENOTDIR: + return ENOTDIR, true + case syscall.ERANGE: + return ERANGE, true + case syscall.ENOTEMPTY: + return ENOTEMPTY, true + case syscall.ENOTSOCK: + return ENOTSOCK, true + case syscall.ENOTSUP: + return ENOTSUP, true + case syscall.EPERM: + return EPERM, true + case syscall.EROFS: + return EROFS, true + default: + return EIO, true + } +} + +// Unwrap is a convenience for runtime.GOOS which define syscall.Errno. +func (e Errno) Unwrap() error { + switch e { + case 0: + return nil + case EACCES: + return syscall.EACCES + case EAGAIN: + return syscall.EAGAIN + case EBADF: + return syscall.EBADF + case EEXIST: + return syscall.EEXIST + case EFAULT: + return syscall.EFAULT + case EINTR: + return syscall.EINTR + case EINVAL: + return syscall.EINVAL + case EIO: + return syscall.EIO + case EISDIR: + return syscall.EISDIR + case ELOOP: + return syscall.ELOOP + case ENAMETOOLONG: + return syscall.ENAMETOOLONG + case ENOENT: + return syscall.ENOENT + case ENOSYS: + return syscall.ENOSYS + case ENOTDIR: + return syscall.ENOTDIR + case ENOTEMPTY: + return syscall.ENOTEMPTY + case ENOTSOCK: + return syscall.ENOTSOCK + case ENOTSUP: + return syscall.ENOTSUP + case EPERM: + return syscall.EPERM + case EROFS: + return syscall.EROFS + default: + return syscall.EIO + } +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go new file mode 100644 index 00000000..8a88ed76 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go @@ -0,0 +1,13 @@ +//go:build !windows + +package sys + +func errorToErrno(err error) Errno { + if errno, ok := err.(Errno); ok { + return errno + } + if errno, ok := syscallToErrno(err); ok { + return errno + } + return EIO +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go new file mode 100644 index 00000000..1c6d423d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go @@ -0,0 +1,7 @@ +//go:build plan9 || aix + +package sys + +func syscallToErrno(err error) (Errno, bool) { + return 0, false +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go new file mode 100644 index 00000000..5ebc1780 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go @@ -0,0 +1,66 @@ +package sys + +import "syscall" + +// These are errors not defined in the syscall package. They are prefixed with +// underscore to avoid exporting them. +// +// See https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- +const ( + // _ERROR_INVALID_HANDLE is a Windows error returned by syscall.Write + // instead of syscall.EBADF + _ERROR_INVALID_HANDLE = syscall.Errno(6) + + // _ERROR_INVALID_NAME is a Windows error returned by open when a file + // path has a trailing slash + _ERROR_INVALID_NAME = syscall.Errno(0x7B) + + // _ERROR_NEGATIVE_SEEK is a Windows error returned by os.Truncate + // instead of syscall.EINVAL + _ERROR_NEGATIVE_SEEK = syscall.Errno(0x83) + + // _ERROR_DIRECTORY is a Windows error returned by syscall.Rmdir + // instead of syscall.ENOTDIR + _ERROR_DIRECTORY = syscall.Errno(0x10B) + + // _ERROR_NOT_A_REPARSE_POINT is a Windows error returned by os.Readlink + // instead of syscall.EINVAL + _ERROR_NOT_A_REPARSE_POINT = syscall.Errno(0x1126) + + // _ERROR_INVALID_SOCKET is a Windows error returned by winsock_select + // when a given handle is not a socket. + _ERROR_INVALID_SOCKET = syscall.Errno(0x2736) +) + +func errorToErrno(err error) Errno { + switch err := err.(type) { + case Errno: + return err + case syscall.Errno: + // Note: In windows, _ERROR_PATH_NOT_FOUND(0x3) maps to syscall.ENOTDIR + switch err { + case syscall.ERROR_ALREADY_EXISTS: + return EEXIST + case _ERROR_DIRECTORY: + return ENOTDIR + case syscall.ERROR_DIR_NOT_EMPTY: + return ENOTEMPTY + case syscall.ERROR_FILE_EXISTS: + return EEXIST + case _ERROR_INVALID_HANDLE, _ERROR_INVALID_SOCKET: + return EBADF + case syscall.ERROR_ACCESS_DENIED: + // POSIX read and write functions expect EBADF, not EACCES when not + // open for reading or writing. + return EBADF + case syscall.ERROR_PRIVILEGE_NOT_HELD: + return EPERM + case _ERROR_NEGATIVE_SEEK, _ERROR_INVALID_NAME, _ERROR_NOT_A_REPARSE_POINT: + return EINVAL + } + errno, _ := syscallToErrno(err) + return errno + default: + return EIO + } +} diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go new file mode 100644 index 00000000..4f3e01fe --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go @@ -0,0 +1,10 @@ +package sys + +import "math" + +// UTIME_OMIT is a special constant for use in updating times via FS.Utimens +// or File.Utimens. When used for atim or mtim, the value is retained. +// +// Note: This may be implemented via a stat when the underlying filesystem +// does not support this value. +const UTIME_OMIT int64 = math.MinInt64 diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go new file mode 100644 index 00000000..d853d9e8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go @@ -0,0 +1,160 @@ +package sys + +import ( + "io/fs" + + "github.com/tetratelabs/wazero/sys" +) + +// UnimplementedFS is an FS that returns ENOSYS for all functions, +// This should be embedded to have forward compatible implementations. +type UnimplementedFS struct{} + +// OpenFile implements FS.OpenFile +func (UnimplementedFS) OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno) { + return nil, ENOSYS +} + +// Lstat implements FS.Lstat +func (UnimplementedFS) Lstat(path string) (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Stat implements FS.Stat +func (UnimplementedFS) Stat(path string) (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Readlink implements FS.Readlink +func (UnimplementedFS) Readlink(path string) (string, Errno) { + return "", ENOSYS +} + +// Mkdir implements FS.Mkdir +func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) Errno { + return ENOSYS +} + +// Chmod implements FS.Chmod +func (UnimplementedFS) Chmod(path string, perm fs.FileMode) Errno { + return ENOSYS +} + +// Rename implements FS.Rename +func (UnimplementedFS) Rename(from, to string) Errno { + return ENOSYS +} + +// Rmdir implements FS.Rmdir +func (UnimplementedFS) Rmdir(path string) Errno { + return ENOSYS +} + +// Link implements FS.Link +func (UnimplementedFS) Link(_, _ string) Errno { + return ENOSYS +} + +// Symlink implements FS.Symlink +func (UnimplementedFS) Symlink(_, _ string) Errno { + return ENOSYS +} + +// Unlink implements FS.Unlink +func (UnimplementedFS) Unlink(path string) Errno { + return ENOSYS +} + +// Utimens implements FS.Utimens +func (UnimplementedFS) Utimens(path string, atim, mtim int64) Errno { + return ENOSYS +} + +// UnimplementedFile is a File that returns ENOSYS for all functions, +// except where no-op are otherwise documented. +// +// This should be embedded to have forward compatible implementations. +type UnimplementedFile struct{} + +// Dev implements File.Dev +func (UnimplementedFile) Dev() (uint64, Errno) { + return 0, 0 +} + +// Ino implements File.Ino +func (UnimplementedFile) Ino() (sys.Inode, Errno) { + return 0, 0 +} + +// IsDir implements File.IsDir +func (UnimplementedFile) IsDir() (bool, Errno) { + return false, 0 +} + +// IsAppend implements File.IsAppend +func (UnimplementedFile) IsAppend() bool { + return false +} + +// SetAppend implements File.SetAppend +func (UnimplementedFile) SetAppend(bool) Errno { + return ENOSYS +} + +// Stat implements File.Stat +func (UnimplementedFile) Stat() (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Read implements File.Read +func (UnimplementedFile) Read([]byte) (int, Errno) { + return 0, ENOSYS +} + +// Pread implements File.Pread +func (UnimplementedFile) Pread([]byte, int64) (int, Errno) { + return 0, ENOSYS +} + +// Seek implements File.Seek +func (UnimplementedFile) Seek(int64, int) (int64, Errno) { + return 0, ENOSYS +} + +// Readdir implements File.Readdir +func (UnimplementedFile) Readdir(int) (dirents []Dirent, errno Errno) { + return nil, ENOSYS +} + +// Write implements File.Write +func (UnimplementedFile) Write([]byte) (int, Errno) { + return 0, ENOSYS +} + +// Pwrite implements File.Pwrite +func (UnimplementedFile) Pwrite([]byte, int64) (int, Errno) { + return 0, ENOSYS +} + +// Truncate implements File.Truncate +func (UnimplementedFile) Truncate(int64) Errno { + return ENOSYS +} + +// Sync implements File.Sync +func (UnimplementedFile) Sync() Errno { + return 0 // not ENOSYS +} + +// Datasync implements File.Datasync +func (UnimplementedFile) Datasync() Errno { + return 0 // not ENOSYS +} + +// Utimens implements File.Utimens +func (UnimplementedFile) Utimens(int64, int64) Errno { + return ENOSYS +} + +// Close implements File.Close +func (UnimplementedFile) Close() (errno Errno) { return } diff --git a/vendor/github.com/tetratelabs/wazero/fsconfig.go b/vendor/github.com/tetratelabs/wazero/fsconfig.go new file mode 100644 index 00000000..c21b6e80 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/fsconfig.go @@ -0,0 +1,213 @@ +package wazero + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/internal/sysfs" +) + +// FSConfig configures filesystem paths the embedding host allows the wasm +// guest to access. Unconfigured paths are not allowed, so functions like +// `path_open` result in unsupported errors (e.g. syscall.ENOSYS). +// +// # Guest Path +// +// `guestPath` is the name of the path the guest should use a filesystem for, or +// empty for any files. +// +// All `guestPath` paths are normalized, specifically removing any leading or +// trailing slashes. This means "/", "./" or "." all coerce to empty "". +// +// Multiple `guestPath` values can be configured, but the last longest match +// wins. For example, if "tmp", then "" were added, a request to open +// "tmp/foo.txt" use the filesystem associated with "tmp" even though a wider +// path, "" (all files), was added later. +// +// A `guestPath` of "." coerces to the empty string "" because the current +// directory is handled by the guest. In other words, the guest resolves ites +// current directory prior to requesting files. +// +// More notes on `guestPath` +// - Working directories are typically tracked in wasm, though possible some +// relative paths are requested. For example, TinyGo may attempt to resolve +// a path "../.." in unit tests. +// - Zig uses the first path name it sees as the initial working directory of +// the process. +// +// # Scope +// +// Configuration here is module instance scoped. This means you can use the +// same configuration for multiple calls to Runtime.InstantiateModule. Each +// module will have a different file descriptor table. Any errors accessing +// resources allowed here are deferred to instantiation time of each module. +// +// Any host resources present at the time of configuration, but deleted before +// Runtime.InstantiateModule will trap/panic when the guest wasm initializes or +// calls functions like `fd_read`. +// +// # Windows +// +// While wazero supports Windows as a platform, all known compilers use POSIX +// conventions at runtime. For example, even when running on Windows, paths +// used by wasm are separated by forward slash (/), not backslash (\). +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - FSConfig is immutable. Each WithXXX function returns a new instance +// including the corresponding change. +// - RATIONALE.md includes design background and relationship to WebAssembly +// System Interfaces (WASI). +type FSConfig interface { + // WithDirMount assigns a directory at `dir` to any paths beginning at + // `guestPath`. + // + // For example, `dirPath` as / (or c:\ in Windows), makes the entire host + // volume writeable to the path on the guest. The `guestPath` is always a + // POSIX style path, slash (/) delimited, even if run on Windows. + // + // If the same `guestPath` was assigned before, this overrides its value, + // retaining the original precedence. See the documentation of FSConfig for + // more details on `guestPath`. + // + // # Isolation + // + // The guest will have full access to this directory including escaping it + // via relative path lookups like "../../". Full access includes operations + // such as creating or deleting files, limited to any host level access + // controls. + // + // # os.DirFS + // + // This configuration optimizes for WASI compatibility which is sometimes + // at odds with the behavior of os.DirFS. Hence, this will not behave + // exactly the same as os.DirFS. See /RATIONALE.md for more. + WithDirMount(dir, guestPath string) FSConfig + + // WithReadOnlyDirMount assigns a directory at `dir` to any paths + // beginning at `guestPath`. + // + // This is the same as WithDirMount except only read operations are + // permitted. However, escaping the directory via relative path lookups + // like "../../" is still allowed. + WithReadOnlyDirMount(dir, guestPath string) FSConfig + + // WithFSMount assigns a fs.FS file system for any paths beginning at + // `guestPath`. + // + // If the same `guestPath` was assigned before, this overrides its value, + // retaining the original precedence. See the documentation of FSConfig for + // more details on `guestPath`. + // + // # Isolation + // + // fs.FS does not restrict the ability to overwrite returned files via + // io.Writer. Moreover, os.DirFS documentation includes important notes + // about isolation, which also applies to fs.Sub. As of Go 1.19, the + // built-in file-systems are not jailed (chroot). See + // https://github.com/golang/go/issues/42322 + // + // # os.DirFS + // + // Due to limited control and functionality available in os.DirFS, we + // advise using WithDirMount instead. There will be behavior differences + // between os.DirFS and WithDirMount, as the latter biases towards what's + // expected from WASI implementations. + // + // # Custom fs.FileInfo + // + // The underlying implementation supports data not usually in fs.FileInfo + // when `info.Sys` returns *sys.Stat_t. For example, a custom fs.FS can use + // this approach to generate or mask sys.Inode data. Such a filesystem + // needs to decorate any functions that can return fs.FileInfo: + // + // - `Stat` as defined on `fs.File` (always) + // - `Readdir` as defined on `os.File` (if defined) + // + // See sys.NewStat_t for examples. + WithFSMount(fs fs.FS, guestPath string) FSConfig +} + +type fsConfig struct { + // fs are the currently configured filesystems. + fs []experimentalsys.FS + // guestPaths are the user-supplied names of the filesystems, retained for + // error messages and fmt.Stringer. + guestPaths []string + // guestPathToFS are the normalized paths to the currently configured + // filesystems, used for de-duplicating. + guestPathToFS map[string]int +} + +// NewFSConfig returns a FSConfig that can be used for configuring module instantiation. +func NewFSConfig() FSConfig { + return &fsConfig{guestPathToFS: map[string]int{}} +} + +// clone makes a deep copy of this module config. +func (c *fsConfig) clone() *fsConfig { + ret := *c // copy except slice and maps which share a ref + ret.fs = make([]experimentalsys.FS, 0, len(c.fs)) + ret.fs = append(ret.fs, c.fs...) + ret.guestPaths = make([]string, 0, len(c.guestPaths)) + ret.guestPaths = append(ret.guestPaths, c.guestPaths...) + ret.guestPathToFS = make(map[string]int, len(c.guestPathToFS)) + for key, value := range c.guestPathToFS { + ret.guestPathToFS[key] = value + } + return &ret +} + +// WithDirMount implements FSConfig.WithDirMount +func (c *fsConfig) WithDirMount(dir, guestPath string) FSConfig { + return c.WithSysFSMount(sysfs.DirFS(dir), guestPath) +} + +// WithReadOnlyDirMount implements FSConfig.WithReadOnlyDirMount +func (c *fsConfig) WithReadOnlyDirMount(dir, guestPath string) FSConfig { + return c.WithSysFSMount(&sysfs.ReadFS{FS: sysfs.DirFS(dir)}, guestPath) +} + +// WithFSMount implements FSConfig.WithFSMount +func (c *fsConfig) WithFSMount(fs fs.FS, guestPath string) FSConfig { + var adapted experimentalsys.FS + if fs != nil { + adapted = &sysfs.AdaptFS{FS: fs} + } + return c.WithSysFSMount(adapted, guestPath) +} + +// WithSysFSMount implements sysfs.FSConfig +func (c *fsConfig) WithSysFSMount(fs experimentalsys.FS, guestPath string) FSConfig { + if _, ok := fs.(experimentalsys.UnimplementedFS); ok { + return c // don't add fake paths. + } + cleaned := sys.StripPrefixesAndTrailingSlash(guestPath) + ret := c.clone() + if i, ok := ret.guestPathToFS[cleaned]; ok { + ret.fs[i] = fs + ret.guestPaths[i] = guestPath + } else if fs != nil { + ret.guestPathToFS[cleaned] = len(ret.fs) + ret.fs = append(ret.fs, fs) + ret.guestPaths = append(ret.guestPaths, guestPath) + } + return ret +} + +// preopens returns the possible nil index-correlated preopened filesystems +// with guest paths. +func (c *fsConfig) preopens() ([]experimentalsys.FS, []string) { + preopenCount := len(c.fs) + if preopenCount == 0 { + return nil, nil + } + fs := make([]experimentalsys.FS, len(c.fs)) + copy(fs, c.fs) + guestPaths := make([]string, len(c.guestPaths)) + copy(guestPaths, c.guestPaths) + return fs, guestPaths +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/args.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/args.go new file mode 100644 index 00000000..4c82e95e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/args.go @@ -0,0 +1,97 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// argsGet is the WASI function named ArgsGetName that reads command-line +// argument data. +// +// # Parameters +// +// - argv: offset to begin writing argument offsets in uint32 little-endian +// encoding to api.Memory +// - argsSizesGet result argc * 4 bytes are written to this offset +// - argvBuf: offset to write the null terminated arguments to api.Memory +// - argsSizesGet result argv_len bytes are written to this offset +// +// Result (Errno) +// +// The return value is ErrnoSuccess except the following error conditions: +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if argsSizesGet wrote argc=2 and argvLen=5 for arguments: +// "a" and "bc" parameters argv=7 and argvBuf=1, this function writes the below +// to api.Memory: +// +// argvLen uint32le uint32le +// +----------------+ +--------+ +--------+ +// | | | | | | +// []byte{?, 'a', 0, 'b', 'c', 0, ?, 1, 0, 0, 0, 3, 0, 0, 0, ?} +// argvBuf --^ ^ ^ +// argv --| | +// offset that begins "a" --+ | +// offset that begins "bc" --+ +// +// See argsSizesGet +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_get +// See https://en.wikipedia.org/wiki/Null-terminated_string +var argsGet = newHostFunc(wasip1.ArgsGetName, argsGetFn, []api.ValueType{i32, i32}, "argv", "argv_buf") + +func argsGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + argv, argvBuf := uint32(params[0]), uint32(params[1]) + return writeOffsetsAndNullTerminatedValues(mod.Memory(), sysCtx.Args(), argv, argvBuf, sysCtx.ArgsSize()) +} + +// argsSizesGet is the WASI function named ArgsSizesGetName that reads +// command-line argument sizes. +// +// # Parameters +// +// - resultArgc: offset to write the argument count to api.Memory +// - resultArgvLen: offset to write the null-terminated argument length to +// api.Memory +// +// Result (Errno) +// +// The return value is ErrnoSuccess except the following error conditions: +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if args are "a", "bc" and parameters resultArgc=1 and +// resultArgvLen=6, this function writes the below to api.Memory: +// +// uint32le uint32le +// +--------+ +--------+ +// | | | | +// []byte{?, 2, 0, 0, 0, ?, 5, 0, 0, 0, ?} +// resultArgc --^ ^ +// 2 args --+ | +// resultArgvLen --| +// len([]byte{'a',0,'b',c',0}) --+ +// +// See argsGet +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_sizes_get +// See https://en.wikipedia.org/wiki/Null-terminated_string +var argsSizesGet = newHostFunc(wasip1.ArgsSizesGetName, argsSizesGetFn, []api.ValueType{i32, i32}, "result.argc", "result.argv_len") + +func argsSizesGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + mem := mod.Memory() + resultArgc, resultArgvLen := uint32(params[0]), uint32(params[1]) + + // argc and argv_len offsets are not necessarily sequential, so we have to + // write them independently. + if !mem.WriteUint32Le(resultArgc, uint32(len(sysCtx.Args()))) { + return sys.EFAULT + } + if !mem.WriteUint32Le(resultArgvLen, sysCtx.ArgsSize()) { + return sys.EFAULT + } + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/clock.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/clock.go new file mode 100644 index 00000000..31af9107 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/clock.go @@ -0,0 +1,116 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// clockResGet is the WASI function named ClockResGetName that returns the +// resolution of time values returned by clockTimeGet. +// +// # Parameters +// +// - id: clock ID to use +// - resultResolution: offset to write the resolution to api.Memory +// - the resolution is an uint64 little-endian encoding +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.ENOTSUP: the clock ID is not supported. +// - sys.EINVAL: the clock ID is invalid. +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if the resolution is 100ns, this function writes the below to +// api.Memory: +// +// uint64le +// +-------------------------------------+ +// | | +// []byte{?, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ?} +// resultResolution --^ +// +// Note: This is similar to `clock_getres` in POSIX. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_res_getid-clockid---errno-timestamp +// See https://linux.die.net/man/3/clock_getres +var clockResGet = newHostFunc(wasip1.ClockResGetName, clockResGetFn, []api.ValueType{i32, i32}, "id", "result.resolution") + +func clockResGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + id, resultResolution := uint32(params[0]), uint32(params[1]) + + var resolution uint64 // ns + switch id { + case wasip1.ClockIDRealtime: + resolution = uint64(sysCtx.WalltimeResolution()) + case wasip1.ClockIDMonotonic: + resolution = uint64(sysCtx.NanotimeResolution()) + default: + return sys.EINVAL + } + + if !mod.Memory().WriteUint64Le(resultResolution, resolution) { + return sys.EFAULT + } + return 0 +} + +// clockTimeGet is the WASI function named ClockTimeGetName that returns +// the time value of a name (time.Now). +// +// # Parameters +// +// - id: clock ID to use +// - precision: maximum lag (exclusive) that the returned time value may have, +// compared to its actual value +// - resultTimestamp: offset to write the timestamp to api.Memory +// - the timestamp is epoch nanos encoded as a little-endian uint64 +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.ENOTSUP: the clock ID is not supported. +// - sys.EINVAL: the clock ID is invalid. +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if time.Now returned exactly midnight UTC 2022-01-01 +// (1640995200000000000), and parameters resultTimestamp=1, this function +// writes the below to api.Memory: +// +// uint64le +// +------------------------------------------+ +// | | +// []byte{?, 0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16, ?} +// resultTimestamp --^ +// +// Note: This is similar to `clock_gettime` in POSIX. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp +// See https://linux.die.net/man/3/clock_gettime +var clockTimeGet = newHostFunc(wasip1.ClockTimeGetName, clockTimeGetFn, []api.ValueType{i32, i64, i32}, "id", "precision", "result.timestamp") + +func clockTimeGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + id := uint32(params[0]) + // TODO: precision is currently ignored. + // precision = params[1] + resultTimestamp := uint32(params[2]) + + var val int64 + switch id { + case wasip1.ClockIDRealtime: + val = sysCtx.WalltimeNanos() + case wasip1.ClockIDMonotonic: + val = sysCtx.Nanotime() + default: + return sys.EINVAL + } + + if !mod.Memory().WriteUint64Le(resultTimestamp, uint64(val)) { + return sys.EFAULT + } + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/environ.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/environ.go new file mode 100644 index 00000000..ec8df708 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/environ.go @@ -0,0 +1,100 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// environGet is the WASI function named EnvironGetName that reads +// environment variables. +// +// # Parameters +// +// - environ: offset to begin writing environment offsets in uint32 +// little-endian encoding to api.Memory +// - environSizesGet result environc * 4 bytes are written to this offset +// - environBuf: offset to write the null-terminated variables to api.Memory +// - the format is like os.Environ: null-terminated "key=val" entries +// - environSizesGet result environLen bytes are written to this offset +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if environSizesGet wrote environc=2 and environLen=9 for +// environment variables: "a=b", "b=cd" and parameters environ=11 and +// environBuf=1, this function writes the below to api.Memory: +// +// environLen uint32le uint32le +// +------------------------------------+ +--------+ +--------+ +// | | | | | | +// []byte{?, 'a', '=', 'b', 0, 'b', '=', 'c', 'd', 0, ?, 1, 0, 0, 0, 5, 0, 0, 0, ?} +// environBuf --^ ^ ^ +// environ offset for "a=b" --+ | +// environ offset for "b=cd" --+ +// +// See environSizesGet +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_get +// See https://en.wikipedia.org/wiki/Null-terminated_string +var environGet = newHostFunc(wasip1.EnvironGetName, environGetFn, []api.ValueType{i32, i32}, "environ", "environ_buf") + +func environGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + environ, environBuf := uint32(params[0]), uint32(params[1]) + + return writeOffsetsAndNullTerminatedValues(mod.Memory(), sysCtx.Environ(), environ, environBuf, sysCtx.EnvironSize()) +} + +// environSizesGet is the WASI function named EnvironSizesGetName that +// reads environment variable sizes. +// +// # Parameters +// +// - resultEnvironc: offset to write the count of environment variables to +// api.Memory +// - resultEnvironvLen: offset to write the null-terminated environment +// variable length to api.Memory +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EFAULT: there is not enough memory to write results +// +// For example, if environ are "a=b","b=cd" and parameters resultEnvironc=1 and +// resultEnvironvLen=6, this function writes the below to api.Memory: +// +// uint32le uint32le +// +--------+ +--------+ +// | | | | +// []byte{?, 2, 0, 0, 0, ?, 9, 0, 0, 0, ?} +// resultEnvironc --^ ^ +// 2 variables --+ | +// resultEnvironvLen --| +// len([]byte{'a','=','b',0, | +// 'b','=','c','d',0}) --+ +// +// See environGet +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_sizes_get +// and https://en.wikipedia.org/wiki/Null-terminated_string +var environSizesGet = newHostFunc(wasip1.EnvironSizesGetName, environSizesGetFn, []api.ValueType{i32, i32}, "result.environc", "result.environv_len") + +func environSizesGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + mem := mod.Memory() + resultEnvironc, resultEnvironvLen := uint32(params[0]), uint32(params[1]) + + // environc and environv_len offsets are not necessarily sequential, so we + // have to write them independently. + if !mem.WriteUint32Le(resultEnvironc, uint32(len(sysCtx.Environ()))) { + return sys.EFAULT + } + if !mem.WriteUint32Le(resultEnvironvLen, sysCtx.EnvironSize()) { + return sys.EFAULT + } + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/fs.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/fs.go new file mode 100644 index 00000000..150f75cc --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/fs.go @@ -0,0 +1,2010 @@ +package wasi_snapshot_preview1 + +import ( + "context" + "io" + "io/fs" + "math" + "path" + "strings" + "unsafe" + + "github.com/tetratelabs/wazero/api" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + socketapi "github.com/tetratelabs/wazero/internal/sock" + "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" + sysapi "github.com/tetratelabs/wazero/sys" +) + +// fdAdvise is the WASI function named FdAdviseName which provides file +// advisory information on a file descriptor. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_advisefd-fd-offset-filesize-len-filesize-advice-advice---errno +var fdAdvise = newHostFunc( + wasip1.FdAdviseName, fdAdviseFn, + []wasm.ValueType{i32, i64, i64, i32}, + "fd", "offset", "len", "advice", +) + +func fdAdviseFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := int32(params[0]) + _ = params[1] + _ = params[2] + advice := byte(params[3]) + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + _, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF + } + + switch advice { + case wasip1.FdAdviceNormal, + wasip1.FdAdviceSequential, + wasip1.FdAdviceRandom, + wasip1.FdAdviceWillNeed, + wasip1.FdAdviceDontNeed, + wasip1.FdAdviceNoReuse: + default: + return experimentalsys.EINVAL + } + + // FdAdvice corresponds to posix_fadvise, but it can only be supported on linux. + // However, the purpose of the call is just to do best-effort optimization on OS kernels, + // so just making this noop rather than returning NoSup error makes sense and doesn't affect + // the semantics of Wasm applications. + // TODO: invoke posix_fadvise on linux, and partially on darwin. + // - https://gitlab.com/cznic/fileutil/-/blob/v1.1.2/fileutil_linux.go#L87-95 + // - https://github.com/bytecodealliance/system-interface/blob/62b97f9776b86235f318c3a6e308395a1187439b/src/fs/file_io_ext.rs#L430-L442 + return 0 +} + +// fdAllocate is the WASI function named FdAllocateName which forces the +// allocation of space in a file. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_allocatefd-fd-offset-filesize-len-filesize---errno +var fdAllocate = newHostFunc( + wasip1.FdAllocateName, fdAllocateFn, + []wasm.ValueType{i32, i64, i64}, + "fd", "offset", "len", +) + +func fdAllocateFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := int32(params[0]) + offset := params[1] + length := params[2] + + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + f, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF + } + + tail := int64(offset + length) + if tail < 0 { + return experimentalsys.EINVAL + } + + st, errno := f.File.Stat() + if errno != 0 { + return errno + } + + if st.Size >= tail { + return 0 // We already have enough space. + } + + return f.File.Truncate(tail) +} + +// fdClose is the WASI function named FdCloseName which closes a file +// descriptor. +// +// # Parameters +// +// - fd: file descriptor to close +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: the fd was not open. +// - sys.ENOTSUP: the fs was a pre-open +// +// Note: This is similar to `close` in POSIX. +// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_close +// and https://linux.die.net/man/3/close +var fdClose = newHostFunc(wasip1.FdCloseName, fdCloseFn, []api.ValueType{i32}, "fd") + +func fdCloseFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd := int32(params[0]) + + return fsc.CloseFile(fd) +} + +// fdDatasync is the WASI function named FdDatasyncName which synchronizes +// the data of a file to disk. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_datasyncfd-fd---errno +var fdDatasync = newHostFunc(wasip1.FdDatasyncName, fdDatasyncFn, []api.ValueType{i32}, "fd") + +func fdDatasyncFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd := int32(params[0]) + + // Check to see if the file descriptor is available + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else { + return f.File.Datasync() + } +} + +// fdFdstatGet is the WASI function named FdFdstatGetName which returns the +// attributes of a file descriptor. +// +// # Parameters +// +// - fd: file descriptor to get the fdstat attributes data +// - resultFdstat: offset to write the result fdstat data +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `resultFdstat` points to an offset out of memory +// +// fdstat byte layout is 24-byte size, with the following fields: +// - fs_filetype 1 byte: the file type +// - fs_flags 2 bytes: the file descriptor flag +// - 5 pad bytes +// - fs_right_base 8 bytes: ignored as rights were removed from WASI. +// - fs_right_inheriting 8 bytes: ignored as rights were removed from WASI. +// +// For example, with a file corresponding with `fd` was a directory (=3) opened +// with `fd_read` right (=1) and no fs_flags (=0), parameter resultFdstat=1, +// this function writes the below to api.Memory: +// +// uint16le padding uint64le uint64le +// uint8 --+ +--+ +-----------+ +--------------------+ +--------------------+ +// | | | | | | | | | +// []byte{?, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0} +// resultFdstat --^ ^-- fs_flags ^-- fs_right_base ^-- fs_right_inheriting +// | +// +-- fs_filetype +// +// Note: fdFdstatGet returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as +// well as additional fields. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdstat +// and https://linux.die.net/man/3/fsync +var fdFdstatGet = newHostFunc(wasip1.FdFdstatGetName, fdFdstatGetFn, []api.ValueType{i32, i32}, "fd", "result.stat") + +// fdFdstatGetFn cannot currently use proxyResultParams because fdstat is larger +// than api.ValueTypeI64 (i64 == 8 bytes, but fdstat is 24). +func fdFdstatGetFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd, resultFdstat := int32(params[0]), uint32(params[1]) + + // Ensure we can write the fdstat + buf, ok := mod.Memory().Read(resultFdstat, 24) + if !ok { + return experimentalsys.EFAULT + } + + var fdflags uint16 + var st sysapi.Stat_t + var errno experimentalsys.Errno + f, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF + } else if st, errno = f.File.Stat(); errno != 0 { + return errno + } else if f.File.IsAppend() { + fdflags |= wasip1.FD_APPEND + } + + if f.File.IsNonblock() { + fdflags |= wasip1.FD_NONBLOCK + } + + var fsRightsBase uint32 + var fsRightsInheriting uint32 + fileType := getExtendedWasiFiletype(f.File, st.Mode) + + switch fileType { + case wasip1.FILETYPE_DIRECTORY: + // To satisfy wasi-testsuite, we must advertise that directories cannot + // be given seek permission (RIGHT_FD_SEEK). + fsRightsBase = dirRightsBase + fsRightsInheriting = fileRightsBase | dirRightsBase + case wasip1.FILETYPE_CHARACTER_DEVICE: + // According to wasi-libc, + // > A tty is a character device that we can't seek or tell on. + // See https://github.com/WebAssembly/wasi-libc/blob/a6f871343313220b76009827ed0153586361c0d5/libc-bottom-half/sources/isatty.c#L13-L18 + fsRightsBase = fileRightsBase &^ wasip1.RIGHT_FD_SEEK &^ wasip1.RIGHT_FD_TELL + default: + fsRightsBase = fileRightsBase + } + + writeFdstat(buf, fileType, fdflags, fsRightsBase, fsRightsInheriting) + return 0 +} + +// isPreopenedStdio returns true if the FD is sys.FdStdin, sys.FdStdout or +// sys.FdStderr and pre-opened. This double check is needed in case the guest +// closes stdin and re-opens it with a random alternative file. +// +// Currently, we only support non-blocking mode for standard I/O streams. +// Non-blocking mode is rarely supported for regular files, and we don't +// yet have support for sockets, so we make a special case. +// +// Note: this to get or set FD_NONBLOCK, but skip FD_APPEND. Our current +// implementation can't set FD_APPEND, without re-opening files. As stdio are +// pre-opened, we don't know how to re-open them, neither should we close the +// underlying file. Later, we could add support for setting FD_APPEND, similar +// to SetNonblock. +func isPreopenedStdio(fd int32, f *sys.FileEntry) bool { + return fd <= sys.FdStderr && f.IsPreopen +} + +const fileRightsBase = wasip1.RIGHT_FD_DATASYNC | + wasip1.RIGHT_FD_READ | + wasip1.RIGHT_FD_SEEK | + wasip1.RIGHT_FDSTAT_SET_FLAGS | + wasip1.RIGHT_FD_SYNC | + wasip1.RIGHT_FD_TELL | + wasip1.RIGHT_FD_WRITE | + wasip1.RIGHT_FD_ADVISE | + wasip1.RIGHT_FD_ALLOCATE | + wasip1.RIGHT_FD_FILESTAT_GET | + wasip1.RIGHT_FD_FILESTAT_SET_SIZE | + wasip1.RIGHT_FD_FILESTAT_SET_TIMES | + wasip1.RIGHT_POLL_FD_READWRITE + +const dirRightsBase = wasip1.RIGHT_FD_DATASYNC | + wasip1.RIGHT_FDSTAT_SET_FLAGS | + wasip1.RIGHT_FD_SYNC | + wasip1.RIGHT_PATH_CREATE_DIRECTORY | + wasip1.RIGHT_PATH_CREATE_FILE | + wasip1.RIGHT_PATH_LINK_SOURCE | + wasip1.RIGHT_PATH_LINK_TARGET | + wasip1.RIGHT_PATH_OPEN | + wasip1.RIGHT_FD_READDIR | + wasip1.RIGHT_PATH_READLINK | + wasip1.RIGHT_PATH_RENAME_SOURCE | + wasip1.RIGHT_PATH_RENAME_TARGET | + wasip1.RIGHT_PATH_FILESTAT_GET | + wasip1.RIGHT_PATH_FILESTAT_SET_SIZE | + wasip1.RIGHT_PATH_FILESTAT_SET_TIMES | + wasip1.RIGHT_FD_FILESTAT_GET | + wasip1.RIGHT_FD_FILESTAT_SET_TIMES | + wasip1.RIGHT_PATH_SYMLINK | + wasip1.RIGHT_PATH_REMOVE_DIRECTORY | + wasip1.RIGHT_PATH_UNLINK_FILE + +func writeFdstat(buf []byte, fileType uint8, fdflags uint16, fsRightsBase, fsRightsInheriting uint32) { + b := (*[24]byte)(buf) + le.PutUint16(b[0:], uint16(fileType)) + le.PutUint16(b[2:], fdflags) + le.PutUint32(b[4:], 0) + le.PutUint64(b[8:], uint64(fsRightsBase)) + le.PutUint64(b[16:], uint64(fsRightsInheriting)) +} + +// fdFdstatSetFlags is the WASI function named FdFdstatSetFlagsName which +// adjusts the flags associated with a file descriptor. +var fdFdstatSetFlags = newHostFunc(wasip1.FdFdstatSetFlagsName, fdFdstatSetFlagsFn, []wasm.ValueType{i32, i32}, "fd", "flags") + +func fdFdstatSetFlagsFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd, wasiFlag := int32(params[0]), uint16(params[1]) + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + // Currently we only support APPEND and NONBLOCK. + if wasip1.FD_DSYNC&wasiFlag != 0 || wasip1.FD_RSYNC&wasiFlag != 0 || wasip1.FD_SYNC&wasiFlag != 0 { + return experimentalsys.EINVAL + } + + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else { + nonblock := wasip1.FD_NONBLOCK&wasiFlag != 0 + errno := f.File.SetNonblock(nonblock) + if errno != 0 { + return errno + } + if stat, err := f.File.Stat(); err == 0 && stat.Mode.IsRegular() { + // For normal files, proceed to apply an append flag. + append := wasip1.FD_APPEND&wasiFlag != 0 + return f.File.SetAppend(append) + } + } + + return 0 +} + +// fdFdstatSetRights will not be implemented as rights were removed from WASI. +// +// See https://github.com/bytecodealliance/wasmtime/pull/4666 +var fdFdstatSetRights = stubFunction( + wasip1.FdFdstatSetRightsName, + []wasm.ValueType{i32, i64, i64}, + "fd", "fs_rights_base", "fs_rights_inheriting", +) + +// fdFilestatGet is the WASI function named FdFilestatGetName which returns +// the stat attributes of an open file. +// +// # Parameters +// +// - fd: file descriptor to get the filestat attributes data for +// - resultFilestat: offset to write the result filestat data +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EIO: could not stat `fd` on filesystem +// - sys.EFAULT: `resultFilestat` points to an offset out of memory +// +// filestat byte layout is 64-byte size, with the following fields: +// - dev 8 bytes: the device ID of device containing the file +// - ino 8 bytes: the file serial number +// - filetype 1 byte: the type of the file +// - 7 pad bytes +// - nlink 8 bytes: number of hard links to the file +// - size 8 bytes: for regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link +// - atim 8 bytes: ast data access timestamp +// - mtim 8 bytes: last data modification timestamp +// - ctim 8 bytes: ast file status change timestamp +// +// For example, with a regular file this function writes the below to api.Memory: +// +// uint8 --+ +// uint64le uint64le | padding uint64le uint64le uint64le uint64le uint64le +// +--------------------+ +--------------------+ | +-----------------+ +--------------------+ +-----------------------+ +----------------------------------+ +----------------------------------+ +----------------------------------+ +// | | | | | | | | | | | | | | | | | +// []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 80, 0, 0, 0, 0, 0, 0, 160, 153, 212, 128, 110, 221, 35, 23, 160, 153, 212, 128, 110, 221, 35, 23, 160, 153, 212, 128, 110, 221, 35, 23} +// resultFilestat ^-- dev ^-- ino ^ ^-- nlink ^-- size ^-- atim ^-- mtim ^-- ctim +// | +// +-- filetype +// +// The following properties of filestat are not implemented: +// - dev: not supported by Golang FS +// - ino: not supported by Golang FS +// - nlink: not supported by Golang FS, we use 1 +// - atime: not supported by Golang FS, we use mtim for this +// - ctim: not supported by Golang FS, we use mtim for this +// +// Note: This is similar to `fstat` in POSIX. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_getfd-fd---errno-filestat +// and https://linux.die.net/man/3/fstat +var fdFilestatGet = newHostFunc(wasip1.FdFilestatGetName, fdFilestatGetFn, []api.ValueType{i32, i32}, "fd", "result.filestat") + +// fdFilestatGetFn cannot currently use proxyResultParams because filestat is +// larger than api.ValueTypeI64 (i64 == 8 bytes, but filestat is 64). +func fdFilestatGetFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + return fdFilestatGetFunc(mod, int32(params[0]), uint32(params[1])) +} + +func fdFilestatGetFunc(mod api.Module, fd int32, resultBuf uint32) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + // Ensure we can write the filestat + buf, ok := mod.Memory().Read(resultBuf, 64) + if !ok { + return experimentalsys.EFAULT + } + + f, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF + } + + st, errno := f.File.Stat() + if errno != 0 { + return errno + } + + filetype := getExtendedWasiFiletype(f.File, st.Mode) + return writeFilestat(buf, &st, filetype) +} + +func getExtendedWasiFiletype(file experimentalsys.File, fm fs.FileMode) (ftype uint8) { + ftype = getWasiFiletype(fm) + if ftype == wasip1.FILETYPE_UNKNOWN { + if _, ok := file.(socketapi.TCPSock); ok { + ftype = wasip1.FILETYPE_SOCKET_STREAM + } else if _, ok = file.(socketapi.TCPConn); ok { + ftype = wasip1.FILETYPE_SOCKET_STREAM + } + } + return +} + +func getWasiFiletype(fm fs.FileMode) uint8 { + switch { + case fm.IsRegular(): + return wasip1.FILETYPE_REGULAR_FILE + case fm.IsDir(): + return wasip1.FILETYPE_DIRECTORY + case fm&fs.ModeSymlink != 0: + return wasip1.FILETYPE_SYMBOLIC_LINK + case fm&fs.ModeDevice != 0: + // Unlike ModeDevice and ModeCharDevice, FILETYPE_CHARACTER_DEVICE and + // FILETYPE_BLOCK_DEVICE are set mutually exclusively. + if fm&fs.ModeCharDevice != 0 { + return wasip1.FILETYPE_CHARACTER_DEVICE + } + return wasip1.FILETYPE_BLOCK_DEVICE + default: // unknown + return wasip1.FILETYPE_UNKNOWN + } +} + +func writeFilestat(buf []byte, st *sysapi.Stat_t, ftype uint8) (errno experimentalsys.Errno) { + le.PutUint64(buf, st.Dev) + le.PutUint64(buf[8:], st.Ino) + le.PutUint64(buf[16:], uint64(ftype)) + le.PutUint64(buf[24:], st.Nlink) + le.PutUint64(buf[32:], uint64(st.Size)) + le.PutUint64(buf[40:], uint64(st.Atim)) + le.PutUint64(buf[48:], uint64(st.Mtim)) + le.PutUint64(buf[56:], uint64(st.Ctim)) + return +} + +// fdFilestatSetSize is the WASI function named FdFilestatSetSizeName which +// adjusts the size of an open file. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_sizefd-fd-size-filesize---errno +var fdFilestatSetSize = newHostFunc(wasip1.FdFilestatSetSizeName, fdFilestatSetSizeFn, []wasm.ValueType{i32, i64}, "fd", "size") + +func fdFilestatSetSizeFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := int32(params[0]) + size := int64(params[1]) + + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + // Check to see if the file descriptor is available + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else { + return f.File.Truncate(size) + } +} + +// fdFilestatSetTimes is the WASI function named functionFdFilestatSetTimes +// which adjusts the times of an open file. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_timesfd-fd-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno +var fdFilestatSetTimes = newHostFunc( + wasip1.FdFilestatSetTimesName, fdFilestatSetTimesFn, + []wasm.ValueType{i32, i64, i64, i32}, + "fd", "atim", "mtim", "fst_flags", +) + +func fdFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := int32(params[0]) + atim := int64(params[1]) + mtim := int64(params[2]) + fstFlags := uint16(params[3]) + + sys := mod.(*wasm.ModuleInstance).Sys + fsc := sys.FS() + + f, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF + } + + atim, mtim, errno := toTimes(sys.WalltimeNanos, atim, mtim, fstFlags) + if errno != 0 { + return errno + } + + // Try to update the file timestamps by file-descriptor. + errno = f.File.Utimens(atim, mtim) + + // Fall back to path based, despite it being less precise. + switch errno { + case experimentalsys.EPERM, experimentalsys.ENOSYS: + errno = f.FS.Utimens(f.Name, atim, mtim) + } + + return errno +} + +func toTimes(walltime func() int64, atim, mtim int64, fstFlags uint16) (int64, int64, experimentalsys.Errno) { + // times[0] == atim, times[1] == mtim + + var nowTim int64 + + // coerce atim into a timespec + if set, now := fstFlags&wasip1.FstflagsAtim != 0, fstFlags&wasip1.FstflagsAtimNow != 0; set && now { + return 0, 0, experimentalsys.EINVAL + } else if set { + // atim is already correct + } else if now { + nowTim = walltime() + atim = nowTim + } else { + atim = experimentalsys.UTIME_OMIT + } + + // coerce mtim into a timespec + if set, now := fstFlags&wasip1.FstflagsMtim != 0, fstFlags&wasip1.FstflagsMtimNow != 0; set && now { + return 0, 0, experimentalsys.EINVAL + } else if set { + // mtim is already correct + } else if now { + if nowTim != 0 { + mtim = nowTim + } else { + mtim = walltime() + } + } else { + mtim = experimentalsys.UTIME_OMIT + } + return atim, mtim, 0 +} + +// fdPread is the WASI function named FdPreadName which reads from a file +// descriptor, without using and updating the file descriptor's offset. +// +// Except for handling offset, this implementation is identical to fdRead. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_preadfd-fd-iovs-iovec_array-offset-filesize---errno-size +var fdPread = newHostFunc( + wasip1.FdPreadName, fdPreadFn, + []api.ValueType{i32, i32, i32, i64, i32}, + "fd", "iovs", "iovs_len", "offset", "result.nread", +) + +func fdPreadFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + return fdReadOrPread(mod, params, true) +} + +// fdPrestatGet is the WASI function named FdPrestatGetName which returns +// the prestat data of a file descriptor. +// +// # Parameters +// +// - fd: file descriptor to get the prestat +// - resultPrestat: offset to write the result prestat data +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid or the `fd` is not a pre-opened directory +// - sys.EFAULT: `resultPrestat` points to an offset out of memory +// +// prestat byte layout is 8 bytes, beginning with an 8-bit tag and 3 pad bytes. +// The only valid tag is `prestat_dir`, which is tag zero. This simplifies the +// byte layout to 4 empty bytes followed by the uint32le encoded path length. +// +// For example, the directory name corresponding with `fd` was "/tmp" and +// parameter resultPrestat=1, this function writes the below to api.Memory: +// +// padding uint32le +// uint8 --+ +-----+ +--------+ +// | | | | | +// []byte{?, 0, 0, 0, 0, 4, 0, 0, 0, ?} +// resultPrestat --^ ^ +// tag --+ | +// +-- size in bytes of the string "/tmp" +// +// See fdPrestatDirName and +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#prestat +var fdPrestatGet = newHostFunc(wasip1.FdPrestatGetName, fdPrestatGetFn, []api.ValueType{i32, i32}, "fd", "result.prestat") + +func fdPrestatGetFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd, resultPrestat := int32(params[0]), uint32(params[1]) + + name, errno := preopenPath(fsc, fd) + if errno != 0 { + return errno + } + + // Upper 32-bits are zero because... + // * Zero-value 8-bit tag, and 3-byte zero-value padding + prestat := uint64(len(name) << 32) + if !mod.Memory().WriteUint64Le(resultPrestat, prestat) { + return experimentalsys.EFAULT + } + return 0 +} + +// fdPrestatDirName is the WASI function named FdPrestatDirNameName which +// returns the path of the pre-opened directory of a file descriptor. +// +// # Parameters +// +// - fd: file descriptor to get the path of the pre-opened directory +// - path: offset in api.Memory to write the result path +// - pathLen: count of bytes to write to `path` +// - This should match the uint32le fdPrestatGet writes to offset +// `resultPrestat`+4 +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `path` points to an offset out of memory +// - sys.ENAMETOOLONG: `pathLen` is longer than the actual length of the result +// +// For example, the directory name corresponding with `fd` was "/tmp" and +// # Parameters path=1 pathLen=4 (correct), this function will write the below to +// api.Memory: +// +// pathLen +// +--------------+ +// | | +// []byte{?, '/', 't', 'm', 'p', ?} +// path --^ +// +// See fdPrestatGet +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name +var fdPrestatDirName = newHostFunc( + wasip1.FdPrestatDirNameName, fdPrestatDirNameFn, + []api.ValueType{i32, i32, i32}, + "fd", "result.path", "result.path_len", +) + +func fdPrestatDirNameFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd, path, pathLen := int32(params[0]), uint32(params[1]), uint32(params[2]) + + name, errno := preopenPath(fsc, fd) + if errno != 0 { + return errno + } + + // Some runtimes may have another semantics. See /RATIONALE.md + if uint32(len(name)) < pathLen { + return experimentalsys.ENAMETOOLONG + } + + if !mod.Memory().Write(path, []byte(name)[:pathLen]) { + return experimentalsys.EFAULT + } + return 0 +} + +// fdPwrite is the WASI function named FdPwriteName which writes to a file +// descriptor, without using and updating the file descriptor's offset. +// +// Except for handling offset, this implementation is identical to fdWrite. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_pwritefd-fd-iovs-ciovec_array-offset-filesize---errno-size +var fdPwrite = newHostFunc( + wasip1.FdPwriteName, fdPwriteFn, + []api.ValueType{i32, i32, i32, i64, i32}, + "fd", "iovs", "iovs_len", "offset", "result.nwritten", +) + +func fdPwriteFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + return fdWriteOrPwrite(mod, params, true) +} + +// fdRead is the WASI function named FdReadName which reads from a file +// descriptor. +// +// # Parameters +// +// - fd: an opened file descriptor to read data from +// - iovs: offset in api.Memory to read offset, size pairs representing where +// to write file data +// - Both offset and length are encoded as uint32le +// - iovsCount: count of memory offset, size pairs to read sequentially +// starting at iovs +// - resultNread: offset in api.Memory to write the number of bytes read +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `iovs` or `resultNread` point to an offset out of memory +// - sys.EIO: a file system error +// +// For example, this function needs to first read `iovs` to determine where +// to write contents. If parameters iovs=1 iovsCount=2, this function reads two +// offset/length pairs from api.Memory: +// +// iovs[0] iovs[1] +// +---------------------+ +--------------------+ +// | uint32le uint32le| |uint32le uint32le| +// +---------+ +--------+ +--------+ +--------+ +// | | | | | | | | +// []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } +// iovs --^ ^ ^ ^ +// | | | | +// offset --+ length --+ offset --+ length --+ +// +// If the contents of the `fd` parameter was "wazero" (6 bytes) and parameter +// resultNread=26, this function writes the below to api.Memory: +// +// iovs[0].length iovs[1].length +// +--------------+ +----+ uint32le +// | | | | +--------+ +// []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ?, 6, 0, 0, 0 } +// iovs[0].offset --^ ^ ^ +// iovs[1].offset --+ | +// resultNread --+ +// +// Note: This is similar to `readv` in POSIX. https://linux.die.net/man/3/readv +// +// See fdWrite +// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read +var fdRead = newHostFunc( + wasip1.FdReadName, fdReadFn, + []api.ValueType{i32, i32, i32, i32}, + "fd", "iovs", "iovs_len", "result.nread", +) + +// preader tracks an offset across multiple reads. +type preader struct { + f experimentalsys.File + offset int64 +} + +// Read implements the same function as documented on sys.File. +func (w *preader) Read(buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length reads. + } + + n, err := w.f.Pread(buf, w.offset) + w.offset += int64(n) + return n, err +} + +func fdReadFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + return fdReadOrPread(mod, params, false) +} + +func fdReadOrPread(mod api.Module, params []uint64, isPread bool) experimentalsys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + iovs := uint32(params[1]) + iovsCount := uint32(params[2]) + + var resultNread uint32 + var reader func(buf []byte) (n int, errno experimentalsys.Errno) + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else if isPread { + offset := int64(params[3]) + reader = (&preader{f: f.File, offset: offset}).Read + resultNread = uint32(params[4]) + } else { + reader = f.File.Read + resultNread = uint32(params[3]) + } + + nread, errno := readv(mem, iovs, iovsCount, reader) + if errno != 0 { + return errno + } + if !mem.WriteUint32Le(resultNread, nread) { + return experimentalsys.EFAULT + } else { + return 0 + } +} + +func readv(mem api.Memory, iovs uint32, iovsCount uint32, reader func(buf []byte) (nread int, errno experimentalsys.Errno)) (uint32, experimentalsys.Errno) { + var nread uint32 + iovsStop := iovsCount << 3 // iovsCount * 8 + iovsBuf, ok := mem.Read(iovs, iovsStop) + if !ok { + return 0, experimentalsys.EFAULT + } + + for iovsPos := uint32(0); iovsPos < iovsStop; iovsPos += 8 { + offset := le.Uint32(iovsBuf[iovsPos:]) + l := le.Uint32(iovsBuf[iovsPos+4:]) + + if l == 0 { // A zero length iovec could be ahead of another. + continue + } + + b, ok := mem.Read(offset, l) + if !ok { + return 0, experimentalsys.EFAULT + } + + n, errno := reader(b) + nread += uint32(n) + + if errno == experimentalsys.ENOSYS { + return 0, experimentalsys.EBADF // e.g. unimplemented for read + } else if errno != 0 { + return 0, errno + } else if n < int(l) { + break // stop when we read less than capacity. + } + } + return nread, 0 +} + +// fdReaddir is the WASI function named wasip1.FdReaddirName which reads +// directory entries from a directory. Special behaviors required by this +// function are implemented in sys.DirentCache. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_readdirfd-fd-buf-pointeru8-buf_len-size-cookie-dircookie---errno-size +// +// # Result (Errno) +// +// The return value is 0 except the following known error conditions: +// - sys.ENOSYS: the implementation does not support this function. +// - sys.EBADF: the file was closed or not a directory. +// - sys.EFAULT: `buf` or `buf_len` point to an offset out of memory. +// - sys.ENOENT: `cookie` was invalid. +// - sys.EINVAL: `buf_len` was not large enough to write a dirent header. +// +// # End of Directory (EOF) +// +// More entries are available when `result.bufused` == `buf_len`. See +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_readdir +// https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c#L44 +var fdReaddir = newHostFunc( + wasip1.FdReaddirName, fdReaddirFn, + []wasm.ValueType{i32, i32, i32, i64, i32}, + "fd", "buf", "buf_len", "cookie", "result.bufused", +) + +func fdReaddirFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + buf := uint32(params[1]) + bufLen := uint32(params[2]) + cookie := params[3] + resultBufused := uint32(params[4]) + + // The bufLen must be enough to write a dirent header. + if bufLen < wasip1.DirentSize { + // This is a bug in the caller, as unless `buf_len` is large enough to + // write a dirent, it can't read the `d_namlen` from it. + return experimentalsys.EINVAL + } + + // Get or open a dirent cache for this file descriptor. + dir, errno := direntCache(fsc, fd) + if errno != 0 { + return errno + } + + // First, determine the maximum directory entries that can be encoded as + // dirents. The total size is DirentSize(24) + nameSize, for each file. + // Since a zero-length file name is invalid, the minimum size entry is + // 25 (DirentSize + 1 character). + maxDirEntries := bufLen/wasip1.DirentSize + 1 + + // While unlikely maxDirEntries will fit into bufLen, add one more just in + // case, as we need to know if we hit the end of the directory or not to + // write the correct bufused (e.g. == bufLen unless EOF). + // >> If less than the size of the read buffer, the end of the + // >> directory has been reached. + maxDirEntries += 1 + + // Read up to max entries. The underlying implementation will cache these, + // starting at the current location, so that they can be re-read. This is + // important because even the first could end up larger than bufLen due to + // the size of its name. + dirents, errno := dir.Read(cookie, maxDirEntries) + if errno != 0 { + return errno + } + + // Determine how many dirents we can write, including a potentially + // truncated last entry. + bufToWrite, direntCount, truncatedLen := maxDirents(dirents, bufLen) + + // Now, write entries to the underlying buffer. + if bufToWrite > 0 { + + // d_next is the index of the next file in the list, so it should + // always be one higher than the requested cookie. + d_next := cookie + 1 + // ^^ yes this can overflow to negative, which means our implementation + // doesn't support writing greater than max int64 entries. + + buf, ok := mem.Read(buf, bufToWrite) + if !ok { + return experimentalsys.EFAULT + } + + writeDirents(buf, dirents, d_next, direntCount, truncatedLen) + } + + // bufused == bufLen means more dirents exist, which is the case when one + // is truncated. + bufused := bufToWrite + if truncatedLen > 0 { + bufused = bufLen + } + + if !mem.WriteUint32Le(resultBufused, bufused) { + return experimentalsys.EFAULT + } + return 0 +} + +const largestDirent = int64(math.MaxUint32 - wasip1.DirentSize) + +// maxDirents returns the dirents to write. +// +// `bufToWrite` is the amount of memory needed to write direntCount, which +// includes up to wasip1.DirentSize of a last truncated entry. +func maxDirents(dirents []experimentalsys.Dirent, bufLen uint32) (bufToWrite uint32, direntCount int, truncatedLen uint32) { + lenRemaining := bufLen + for i := range dirents { + if lenRemaining == 0 { + break + } + d := dirents[i] + direntCount++ + + // use int64 to guard against huge filenames + nameLen := int64(len(d.Name)) + var entryLen uint32 + + // Check to see if DirentSize + nameLen overflows, or if it would be + // larger than possible to encode. + if el := int64(wasip1.DirentSize) + nameLen; el < 0 || el > largestDirent { + // panic, as testing is difficult. ex we would have to extract a + // function to get size of a string or allocate a 2^32 size one! + panic("invalid filename: too large") + } else { // we know this can fit into a uint32 + entryLen = uint32(el) + } + + if entryLen > lenRemaining { + // We haven't room to write the entry, and docs say to write the + // header. This helps especially when there is an entry with a very + // long filename. Ex if bufLen is 4096 and the filename is 4096, + // we need to write DirentSize(24) + 4096 bytes to write the entry. + // In this case, we only write up to DirentSize(24) to allow the + // caller to resize. + if lenRemaining >= wasip1.DirentSize { + truncatedLen = wasip1.DirentSize + } else { + truncatedLen = lenRemaining + } + bufToWrite += truncatedLen + break + } + + // This won't go negative because we checked entryLen <= lenRemaining. + lenRemaining -= entryLen + bufToWrite += entryLen + } + return +} + +// writeDirents writes the directory entries to the buffer, which is pre-sized +// based on maxDirents. truncatedEntryLen means the last is written without its +// name. +func writeDirents(buf []byte, dirents []experimentalsys.Dirent, d_next uint64, direntCount int, truncatedLen uint32) { + pos := uint32(0) + skipNameI := -1 + + // If the last entry was truncated, we either skip it or write it without + // its name, depending on the length. + if truncatedLen > 0 { + if truncatedLen < wasip1.DirentSize { + direntCount-- // skip as too small to write the header. + } else { + skipNameI = direntCount - 1 // write the header, but not the name. + } + } + + for i := 0; i < direntCount; i++ { + e := dirents[i] + nameLen := uint32(len(e.Name)) + writeDirent(buf[pos:], d_next, e.Ino, nameLen, e.Type) + d_next++ + pos += wasip1.DirentSize + + if i != skipNameI { + copy(buf[pos:], e.Name) + pos += nameLen + } + } +} + +// writeDirent writes DirentSize bytes +func writeDirent(buf []byte, dNext uint64, ino sysapi.Inode, dNamlen uint32, dType fs.FileMode) { + le.PutUint64(buf, dNext) // d_next + le.PutUint64(buf[8:], ino) // d_ino + le.PutUint32(buf[16:], dNamlen) // d_namlen + filetype := getWasiFiletype(dType) + le.PutUint32(buf[20:], uint32(filetype)) // d_type +} + +// direntCache lazy opens a sys.DirentCache for this directory or returns an +// error. +func direntCache(fsc *sys.FSContext, fd int32) (*sys.DirentCache, experimentalsys.Errno) { + if f, ok := fsc.LookupFile(fd); !ok { + return nil, experimentalsys.EBADF + } else if dir, errno := f.DirentCache(); errno == 0 { + return dir, 0 + } else if errno == experimentalsys.ENOTDIR { + // fd_readdir docs don't indicate whether to return sys.ENOTDIR or + // sys.EBADF. It has been noticed that rust will crash on sys.ENOTDIR, + // and POSIX C ref seems to not return this, so we don't either. + // + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_readdir + // and https://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/dirent.h + return nil, experimentalsys.EBADF + } else { + return nil, errno + } +} + +// fdRenumber is the WASI function named FdRenumberName which atomically +// replaces a file descriptor by renumbering another file descriptor. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_renumberfd-fd-to-fd---errno +var fdRenumber = newHostFunc(wasip1.FdRenumberName, fdRenumberFn, []wasm.ValueType{i32, i32}, "fd", "to") + +func fdRenumberFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + from := int32(params[0]) + to := int32(params[1]) + + if errno := fsc.Renumber(from, to); errno != 0 { + return errno + } + return 0 +} + +// fdSeek is the WASI function named FdSeekName which moves the offset of a +// file descriptor. +// +// # Parameters +// +// - fd: file descriptor to move the offset of +// - offset: signed int64, which is encoded as uint64, input argument to +// `whence`, which results in a new offset +// - whence: operator that creates the new offset, given `offset` bytes +// - If io.SeekStart, new offset == `offset`. +// - If io.SeekCurrent, new offset == existing offset + `offset`. +// - If io.SeekEnd, new offset == file size of `fd` + `offset`. +// - resultNewoffset: offset in api.Memory to write the new offset to, +// relative to start of the file +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `resultNewoffset` points to an offset out of memory +// - sys.EINVAL: `whence` is an invalid value +// - sys.EIO: a file system error +// - sys.EISDIR: the file was a directory. +// +// For example, if fd 3 is a file with offset 0, and parameters fd=3, offset=4, +// whence=0 (=io.SeekStart), resultNewOffset=1, this function writes the below +// to api.Memory: +// +// uint64le +// +--------------------+ +// | | +// []byte{?, 4, 0, 0, 0, 0, 0, 0, 0, ? } +// resultNewoffset --^ +// +// Note: This is similar to `lseek` in POSIX. https://linux.die.net/man/3/lseek +// +// See io.Seeker +// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_seek +var fdSeek = newHostFunc( + wasip1.FdSeekName, fdSeekFn, + []api.ValueType{i32, i64, i32, i32}, + "fd", "offset", "whence", "result.newoffset", +) + +func fdSeekFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd := int32(params[0]) + offset := params[1] + whence := uint32(params[2]) + resultNewoffset := uint32(params[3]) + + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else if isDir, _ := f.File.IsDir(); isDir { + return experimentalsys.EISDIR // POSIX doesn't forbid seeking a directory, but wasi-testsuite does. + } else if newOffset, errno := f.File.Seek(int64(offset), int(whence)); errno != 0 { + return errno + } else if !mod.Memory().WriteUint64Le(resultNewoffset, uint64(newOffset)) { + return experimentalsys.EFAULT + } + return 0 +} + +// fdSync is the WASI function named FdSyncName which synchronizes the data +// and metadata of a file to disk. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_syncfd-fd---errno +var fdSync = newHostFunc(wasip1.FdSyncName, fdSyncFn, []api.ValueType{i32}, "fd") + +func fdSyncFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + fd := int32(params[0]) + + // Check to see if the file descriptor is available + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else { + return f.File.Sync() + } +} + +// fdTell is the WASI function named FdTellName which returns the current +// offset of a file descriptor. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_tellfd-fd---errno-filesize +var fdTell = newHostFunc(wasip1.FdTellName, fdTellFn, []api.ValueType{i32, i32}, "fd", "result.offset") + +func fdTellFn(ctx context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := params[0] + offset := uint64(0) + whence := uint64(io.SeekCurrent) + resultNewoffset := params[1] + + fdSeekParams := []uint64{fd, offset, whence, resultNewoffset} + return fdSeekFn(ctx, mod, fdSeekParams) +} + +// fdWrite is the WASI function named FdWriteName which writes to a file +// descriptor. +// +// # Parameters +// +// - fd: an opened file descriptor to write data to +// - iovs: offset in api.Memory to read offset, size pairs representing the +// data to write to `fd` +// - Both offset and length are encoded as uint32le. +// - iovsCount: count of memory offset, size pairs to read sequentially +// starting at iovs +// - resultNwritten: offset in api.Memory to write the number of bytes +// written +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `iovs` or `resultNwritten` point to an offset out of memory +// - sys.EIO: a file system error +// +// For example, this function needs to first read `iovs` to determine what to +// write to `fd`. If parameters iovs=1 iovsCount=2, this function reads two +// offset/length pairs from api.Memory: +// +// iovs[0] iovs[1] +// +---------------------+ +--------------------+ +// | uint32le uint32le| |uint32le uint32le| +// +---------+ +--------+ +--------+ +--------+ +// | | | | | | | | +// []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } +// iovs --^ ^ ^ ^ +// | | | | +// offset --+ length --+ offset --+ length --+ +// +// This function reads those chunks api.Memory into the `fd` sequentially. +// +// iovs[0].length iovs[1].length +// +--------------+ +----+ +// | | | | +// []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ? } +// iovs[0].offset --^ ^ +// iovs[1].offset --+ +// +// Since "wazero" was written, if parameter resultNwritten=26, this function +// writes the below to api.Memory: +// +// uint32le +// +--------+ +// | | +// []byte{ 0..24, ?, 6, 0, 0, 0', ? } +// resultNwritten --^ +// +// Note: This is similar to `writev` in POSIX. https://linux.die.net/man/3/writev +// +// See fdRead +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#ciovec +// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write +var fdWrite = newHostFunc( + wasip1.FdWriteName, fdWriteFn, + []api.ValueType{i32, i32, i32, i32}, + "fd", "iovs", "iovs_len", "result.nwritten", +) + +func fdWriteFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + return fdWriteOrPwrite(mod, params, false) +} + +// pwriter tracks an offset across multiple writes. +type pwriter struct { + f experimentalsys.File + offset int64 +} + +// Write implements the same function as documented on sys.File. +func (w *pwriter) Write(buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length writes. + } + + n, err := w.f.Pwrite(buf, w.offset) + w.offset += int64(n) + return n, err +} + +func fdWriteOrPwrite(mod api.Module, params []uint64, isPwrite bool) experimentalsys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + iovs := uint32(params[1]) + iovsCount := uint32(params[2]) + + var resultNwritten uint32 + var writer func(buf []byte) (n int, errno experimentalsys.Errno) + if f, ok := fsc.LookupFile(fd); !ok { + return experimentalsys.EBADF + } else if isPwrite { + offset := int64(params[3]) + writer = (&pwriter{f: f.File, offset: offset}).Write + resultNwritten = uint32(params[4]) + } else { + writer = f.File.Write + resultNwritten = uint32(params[3]) + } + + nwritten, errno := writev(mem, iovs, iovsCount, writer) + if errno != 0 { + return errno + } + + if !mod.Memory().WriteUint32Le(resultNwritten, nwritten) { + return experimentalsys.EFAULT + } + return 0 +} + +func writev(mem api.Memory, iovs uint32, iovsCount uint32, writer func(buf []byte) (n int, errno experimentalsys.Errno)) (uint32, experimentalsys.Errno) { + var nwritten uint32 + iovsStop := iovsCount << 3 // iovsCount * 8 + iovsBuf, ok := mem.Read(iovs, iovsStop) + if !ok { + return 0, experimentalsys.EFAULT + } + + for iovsPos := uint32(0); iovsPos < iovsStop; iovsPos += 8 { + offset := le.Uint32(iovsBuf[iovsPos:]) + l := le.Uint32(iovsBuf[iovsPos+4:]) + + b, ok := mem.Read(offset, l) + if !ok { + return 0, experimentalsys.EFAULT + } + n, errno := writer(b) + nwritten += uint32(n) + if errno == experimentalsys.ENOSYS { + return 0, experimentalsys.EBADF // e.g. unimplemented for write + } else if errno != 0 { + return 0, errno + } + } + return nwritten, 0 +} + +// pathCreateDirectory is the WASI function named PathCreateDirectoryName which +// creates a directory. +// +// # Parameters +// +// - fd: file descriptor of a directory that `path` is relative to +// - path: offset in api.Memory to read the path string from +// - pathLen: length of `path` +// +// # Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.ENOENT: `path` does not exist. +// - sys.ENOTDIR: `path` is a file +// +// # Notes +// - This is similar to mkdirat in POSIX. +// See https://linux.die.net/man/2/mkdirat +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_create_directoryfd-fd-path-string---errno +var pathCreateDirectory = newHostFunc( + wasip1.PathCreateDirectoryName, pathCreateDirectoryFn, + []wasm.ValueType{i32, i32, i32}, + "fd", "path", "path_len", +) + +func pathCreateDirectoryFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + path := uint32(params[1]) + pathLen := uint32(params[2]) + + preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen) + if errno != 0 { + return errno + } + + if errno = preopen.Mkdir(pathName, 0o700); errno != 0 { + return errno + } + + return 0 +} + +// pathFilestatGet is the WASI function named PathFilestatGetName which +// returns the stat attributes of a file or directory. +// +// # Parameters +// +// - fd: file descriptor of the folder to look in for the path +// - flags: flags determining the method of how paths are resolved +// - path: path under fd to get the filestat attributes data for +// - path_len: length of the path that was given +// - resultFilestat: offset to write the result filestat data +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.ENOTDIR: `fd` points to a file not a directory +// - sys.EIO: could not stat `fd` on filesystem +// - sys.EINVAL: the path contained "../" +// - sys.ENAMETOOLONG: `path` + `path_len` is out of memory +// - sys.EFAULT: `resultFilestat` points to an offset out of memory +// - sys.ENOENT: could not find the path +// +// The rest of this implementation matches that of fdFilestatGet, so is not +// repeated here. +// +// Note: This is similar to `fstatat` in POSIX. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_getfd-fd-flags-lookupflags-path-string---errno-filestat +// and https://linux.die.net/man/2/fstatat +var pathFilestatGet = newHostFunc( + wasip1.PathFilestatGetName, pathFilestatGetFn, + []api.ValueType{i32, i32, i32, i32, i32}, + "fd", "flags", "path", "path_len", "result.filestat", +) + +func pathFilestatGetFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + flags := uint16(params[1]) + path := uint32(params[2]) + pathLen := uint32(params[3]) + + preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen) + if errno != 0 { + return errno + } + + // Stat the file without allocating a file descriptor. + var st sysapi.Stat_t + + if (flags & wasip1.LOOKUP_SYMLINK_FOLLOW) == 0 { + st, errno = preopen.Lstat(pathName) + } else { + st, errno = preopen.Stat(pathName) + } + if errno != 0 { + return errno + } + + // Write the stat result to memory + resultBuf := uint32(params[4]) + buf, ok := mod.Memory().Read(resultBuf, 64) + if !ok { + return experimentalsys.EFAULT + } + + filetype := getWasiFiletype(st.Mode) + return writeFilestat(buf, &st, filetype) +} + +// pathFilestatSetTimes is the WASI function named PathFilestatSetTimesName +// which adjusts the timestamps of a file or directory. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_set_timesfd-fd-flags-lookupflags-path-string-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno +var pathFilestatSetTimes = newHostFunc( + wasip1.PathFilestatSetTimesName, pathFilestatSetTimesFn, + []wasm.ValueType{i32, i32, i32, i32, i64, i64, i32}, + "fd", "flags", "path", "path_len", "atim", "mtim", "fst_flags", +) + +func pathFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fd := int32(params[0]) + flags := uint16(params[1]) + path := uint32(params[2]) + pathLen := uint32(params[3]) + atim := int64(params[4]) + mtim := int64(params[5]) + fstFlags := uint16(params[6]) + + sys := mod.(*wasm.ModuleInstance).Sys + fsc := sys.FS() + + atim, mtim, errno := toTimes(sys.WalltimeNanos, atim, mtim, fstFlags) + if errno != 0 { + return errno + } + + preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen) + if errno != 0 { + return errno + } + + symlinkFollow := flags&wasip1.LOOKUP_SYMLINK_FOLLOW != 0 + if symlinkFollow { + return preopen.Utimens(pathName, atim, mtim) + } + // Otherwise, we need to emulate don't follow by opening the file by path. + if f, errno := preopen.OpenFile(pathName, experimentalsys.O_WRONLY, 0); errno != 0 { + return errno + } else { + defer f.Close() + return f.Utimens(atim, mtim) + } +} + +// pathLink is the WASI function named PathLinkName which adjusts the +// timestamps of a file or directory. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_link +var pathLink = newHostFunc( + wasip1.PathLinkName, pathLinkFn, + []wasm.ValueType{i32, i32, i32, i32, i32, i32, i32}, + "old_fd", "old_flags", "old_path", "old_path_len", "new_fd", "new_path", "new_path_len", +) + +func pathLinkFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + oldFD := int32(params[0]) + // TODO: use old_flags? + _ = uint32(params[1]) + oldPath := uint32(params[2]) + oldPathLen := uint32(params[3]) + + oldFS, oldName, errno := atPath(fsc, mem, oldFD, oldPath, oldPathLen) + if errno != 0 { + return errno + } + + newFD := int32(params[4]) + newPath := uint32(params[5]) + newPathLen := uint32(params[6]) + + newFS, newName, errno := atPath(fsc, mem, newFD, newPath, newPathLen) + if errno != 0 { + return errno + } + + if oldFS != newFS { // TODO: handle link across filesystems + return experimentalsys.ENOSYS + } + + return oldFS.Link(oldName, newName) +} + +// pathOpen is the WASI function named PathOpenName which opens a file or +// directory. This returns sys.EBADF if the fd is invalid. +// +// # Parameters +// +// - fd: file descriptor of a directory that `path` is relative to +// - dirflags: flags to indicate how to resolve `path` +// - path: offset in api.Memory to read the path string from +// - pathLen: length of `path` +// - oFlags: open flags to indicate the method by which to open the file +// - fsRightsBase: interpret RIGHT_FD_WRITE to set O_RDWR +// - fsRightsInheriting: ignored as rights were removed from WASI. +// created file descriptor for `path` +// - fdFlags: file descriptor flags +// - resultOpenedFD: offset in api.Memory to write the newly created file +// descriptor to. +// - The result FD value is guaranteed to be less than 2**31 +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.EFAULT: `resultOpenedFD` points to an offset out of memory +// - sys.ENOENT: `path` does not exist. +// - sys.EEXIST: `path` exists, while `oFlags` requires that it must not. +// - sys.ENOTDIR: `path` is not a directory, while `oFlags` requires it. +// - sys.EIO: a file system error +// +// For example, this function needs to first read `path` to determine the file +// to open. If parameters `path` = 1, `pathLen` = 6, and the path is "wazero", +// pathOpen reads the path from api.Memory: +// +// pathLen +// +------------------------+ +// | | +// []byte{ ?, 'w', 'a', 'z', 'e', 'r', 'o', ?... } +// path --^ +// +// Then, if parameters resultOpenedFD = 8, and this function opened a new file +// descriptor 5 with the given flags, this function writes the below to +// api.Memory: +// +// uint32le +// +--------+ +// | | +// []byte{ 0..6, ?, 5, 0, 0, 0, ?} +// resultOpenedFD --^ +// +// # Notes +// - This is similar to `openat` in POSIX. https://linux.die.net/man/3/openat +// - The returned file descriptor is not guaranteed to be the lowest-number +// +// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#path_open +var pathOpen = newHostFunc( + wasip1.PathOpenName, pathOpenFn, + []api.ValueType{i32, i32, i32, i32, i32, i64, i64, i32, i32}, + "fd", "dirflags", "path", "path_len", "oflags", "fs_rights_base", "fs_rights_inheriting", "fdflags", "result.opened_fd", +) + +func pathOpenFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + preopenFD := int32(params[0]) + + // TODO: dirflags is a lookupflags, and it only has one bit: symlink_follow + // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags + dirflags := uint16(params[1]) + + path := uint32(params[2]) + pathLen := uint32(params[3]) + + oflags := uint16(params[4]) + + rights := uint32(params[5]) + // inherited rights aren't used + _ = params[6] + + fdflags := uint16(params[7]) + resultOpenedFD := uint32(params[8]) + + preopen, pathName, errno := atPath(fsc, mod.Memory(), preopenFD, path, pathLen) + if errno != 0 { + return errno + } + + if pathLen == 0 { + return experimentalsys.EINVAL + } + + fileOpenFlags := openFlags(dirflags, oflags, fdflags, rights) + isDir := fileOpenFlags&experimentalsys.O_DIRECTORY != 0 + + if isDir && oflags&wasip1.O_CREAT != 0 { + return experimentalsys.EINVAL // use pathCreateDirectory! + } + + newFD, errno := fsc.OpenFile(preopen, pathName, fileOpenFlags, 0o600) + if errno != 0 { + return errno + } + + // Check any flags that require the file to evaluate. + if isDir { + if f, ok := fsc.LookupFile(newFD); !ok { + return experimentalsys.EBADF // unexpected + } else if isDir, errno := f.File.IsDir(); errno != 0 { + _ = fsc.CloseFile(newFD) + return errno + } else if !isDir { + _ = fsc.CloseFile(newFD) + return experimentalsys.ENOTDIR + } + } + + if !mod.Memory().WriteUint32Le(resultOpenedFD, uint32(newFD)) { + _ = fsc.CloseFile(newFD) + return experimentalsys.EFAULT + } + return 0 +} + +// atPath returns the pre-open specific path after verifying it is a directory. +// +// # Notes +// +// Languages including Zig and Rust use only pre-opens for the FD because +// wasi-libc `__wasilibc_find_relpath` will only return a preopen. That said, +// our wasi.c example shows other languages act differently and can use a non +// pre-opened file descriptor. +// +// We don't handle `AT_FDCWD`, as that's resolved in the compiler. There's no +// working directory function in WASI, so most assume CWD is "/". Notably, Zig +// has different behavior which assumes it is whatever the first pre-open name +// is. +// +// See https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/sources/at_fdcwd.c +// See https://linux.die.net/man/2/openat +func atPath(fsc *sys.FSContext, mem api.Memory, fd int32, p, pathLen uint32) (experimentalsys.FS, string, experimentalsys.Errno) { + b, ok := mem.Read(p, pathLen) + if !ok { + return nil, "", experimentalsys.EFAULT + } + pathName := string(b) + + // interesting_paths wants us to break on trailing slash if the input ends + // up a file, not a directory! + hasTrailingSlash := strings.HasSuffix(pathName, "/") + + // interesting_paths includes paths that include relative links but end up + // not escaping + pathName = path.Clean(pathName) + + // interesting_paths wants to break on root paths or anything that escapes. + // This part is the same as fs.FS.Open() + if !fs.ValidPath(pathName) { + return nil, "", experimentalsys.EPERM + } + + // add the trailing slash back + if hasTrailingSlash { + pathName = pathName + "/" + } + + if f, ok := fsc.LookupFile(fd); !ok { + return nil, "", experimentalsys.EBADF // closed or invalid + } else if isDir, errno := f.File.IsDir(); errno != 0 { + return nil, "", errno + } else if !isDir { + return nil, "", experimentalsys.ENOTDIR + } else if f.IsPreopen { // don't append the pre-open name + return f.FS, pathName, 0 + } else { + // Join via concat to avoid name conflict on path.Join + return f.FS, f.Name + "/" + pathName, 0 + } +} + +func preopenPath(fsc *sys.FSContext, fd int32) (string, experimentalsys.Errno) { + if f, ok := fsc.LookupFile(fd); !ok { + return "", experimentalsys.EBADF // closed + } else if !f.IsPreopen { + return "", experimentalsys.EBADF + } else if isDir, errno := f.File.IsDir(); errno != 0 || !isDir { + // In wasip1, only directories can be returned by fd_prestat_get as + // there are no prestat types defined for files or sockets. + return "", errno + } else { + return f.Name, 0 + } +} + +func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags experimentalsys.Oflag) { + if dirflags&wasip1.LOOKUP_SYMLINK_FOLLOW == 0 { + openFlags |= experimentalsys.O_NOFOLLOW + } + if oflags&wasip1.O_DIRECTORY != 0 { + openFlags |= experimentalsys.O_DIRECTORY + } else if oflags&wasip1.O_EXCL != 0 { + openFlags |= experimentalsys.O_EXCL + } + // Because we don't implement rights, we partially rely on the open flags + // to determine the mode in which the file will be opened. This will create + // divergent behavior compared to WASI runtimes which have a more strict + // interpretation of the WASI capabilities model; for example, a program + // which sets O_CREAT but does not give read or write permissions will + // successfully create a file when running with wazero, but might get a + // permission denied error on other runtimes. + defaultMode := experimentalsys.O_RDONLY + if oflags&wasip1.O_TRUNC != 0 { + openFlags |= experimentalsys.O_TRUNC + defaultMode = experimentalsys.O_RDWR + } + if oflags&wasip1.O_CREAT != 0 { + openFlags |= experimentalsys.O_CREAT + defaultMode = experimentalsys.O_RDWR + } + if fdflags&wasip1.FD_NONBLOCK != 0 { + openFlags |= experimentalsys.O_NONBLOCK + } + if fdflags&wasip1.FD_APPEND != 0 { + openFlags |= experimentalsys.O_APPEND + defaultMode = experimentalsys.O_RDWR + } + if fdflags&wasip1.FD_DSYNC != 0 { + openFlags |= experimentalsys.O_DSYNC + } + if fdflags&wasip1.FD_RSYNC != 0 { + openFlags |= experimentalsys.O_RSYNC + } + if fdflags&wasip1.FD_SYNC != 0 { + openFlags |= experimentalsys.O_SYNC + } + + // Since rights were discontinued in wasi, we only interpret RIGHT_FD_WRITE + // because it is the only way to know that we need to set write permissions + // on a file if the application did not pass any of O_CREAT, O_APPEND, nor + // O_TRUNC. + const r = wasip1.RIGHT_FD_READ + const w = wasip1.RIGHT_FD_WRITE + const rw = r | w + switch { + case (rights & rw) == rw: + openFlags |= experimentalsys.O_RDWR + case (rights & w) == w: + openFlags |= experimentalsys.O_WRONLY + case (rights & r) == r: + openFlags |= experimentalsys.O_RDONLY + default: + openFlags |= defaultMode + } + return +} + +// pathReadlink is the WASI function named PathReadlinkName that reads the +// contents of a symbolic link. +// +// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_readlinkfd-fd-path-string-buf-pointeru8-buf_len-size---errno-size +var pathReadlink = newHostFunc( + wasip1.PathReadlinkName, pathReadlinkFn, + []wasm.ValueType{i32, i32, i32, i32, i32, i32}, + "fd", "path", "path_len", "buf", "buf_len", "result.bufused", +) + +func pathReadlinkFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + path := uint32(params[1]) + pathLen := uint32(params[2]) + buf := uint32(params[3]) + bufLen := uint32(params[4]) + resultBufused := uint32(params[5]) + + if pathLen == 0 || bufLen == 0 { + return experimentalsys.EINVAL + } + + mem := mod.Memory() + preopen, p, errno := atPath(fsc, mem, fd, path, pathLen) + if errno != 0 { + return errno + } + + dst, errno := preopen.Readlink(p) + if errno != 0 { + return errno + } + + if len(dst) > int(bufLen) { + return experimentalsys.ERANGE + } + + if ok := mem.WriteString(buf, dst); !ok { + return experimentalsys.EFAULT + } + + if !mem.WriteUint32Le(resultBufused, uint32(len(dst))) { + return experimentalsys.EFAULT + } + return 0 +} + +// pathRemoveDirectory is the WASI function named PathRemoveDirectoryName which +// removes a directory. +// +// # Parameters +// +// - fd: file descriptor of a directory that `path` is relative to +// - path: offset in api.Memory to read the path string from +// - pathLen: length of `path` +// +// # Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.ENOENT: `path` does not exist. +// - sys.ENOTEMPTY: `path` is not empty +// - sys.ENOTDIR: `path` is a file +// +// # Notes +// - This is similar to unlinkat with AT_REMOVEDIR in POSIX. +// See https://linux.die.net/man/2/unlinkat +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_remove_directoryfd-fd-path-string---errno +var pathRemoveDirectory = newHostFunc( + wasip1.PathRemoveDirectoryName, pathRemoveDirectoryFn, + []wasm.ValueType{i32, i32, i32}, + "fd", "path", "path_len", +) + +func pathRemoveDirectoryFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + path := uint32(params[1]) + pathLen := uint32(params[2]) + + preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen) + if errno != 0 { + return errno + } + + return preopen.Rmdir(pathName) +} + +// pathRename is the WASI function named PathRenameName which renames a file or +// directory. +// +// # Parameters +// +// - fd: file descriptor of a directory that `old_path` is relative to +// - old_path: offset in api.Memory to read the old path string from +// - old_path_len: length of `old_path` +// - new_fd: file descriptor of a directory that `new_path` is relative to +// - new_path: offset in api.Memory to read the new path string from +// - new_path_len: length of `new_path` +// +// # Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` or `new_fd` are invalid +// - sys.ENOENT: `old_path` does not exist. +// - sys.ENOTDIR: `old` is a directory and `new` exists, but is a file. +// - sys.EISDIR: `old` is a file and `new` exists, but is a directory. +// +// # Notes +// - This is similar to unlinkat in POSIX. +// See https://linux.die.net/man/2/renameat +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_renamefd-fd-old_path-string-new_fd-fd-new_path-string---errno +var pathRename = newHostFunc( + wasip1.PathRenameName, pathRenameFn, + []wasm.ValueType{i32, i32, i32, i32, i32, i32}, + "fd", "old_path", "old_path_len", "new_fd", "new_path", "new_path_len", +) + +func pathRenameFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + oldPath := uint32(params[1]) + oldPathLen := uint32(params[2]) + + newFD := int32(params[3]) + newPath := uint32(params[4]) + newPathLen := uint32(params[5]) + + oldFS, oldPathName, errno := atPath(fsc, mod.Memory(), fd, oldPath, oldPathLen) + if errno != 0 { + return errno + } + + newFS, newPathName, errno := atPath(fsc, mod.Memory(), newFD, newPath, newPathLen) + if errno != 0 { + return errno + } + + if oldFS != newFS { // TODO: handle renames across filesystems + return experimentalsys.ENOSYS + } + + return oldFS.Rename(oldPathName, newPathName) +} + +// pathSymlink is the WASI function named PathSymlinkName which creates a +// symbolic link. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_symlink +var pathSymlink = newHostFunc( + wasip1.PathSymlinkName, pathSymlinkFn, + []wasm.ValueType{i32, i32, i32, i32, i32}, + "old_path", "old_path_len", "fd", "new_path", "new_path_len", +) + +func pathSymlinkFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + oldPath := uint32(params[0]) + oldPathLen := uint32(params[1]) + fd := int32(params[2]) + newPath := uint32(params[3]) + newPathLen := uint32(params[4]) + + mem := mod.Memory() + + dir, ok := fsc.LookupFile(fd) + if !ok { + return experimentalsys.EBADF // closed + } else if isDir, errno := dir.File.IsDir(); errno != 0 { + return errno + } else if !isDir { + return experimentalsys.ENOTDIR + } + + if oldPathLen == 0 || newPathLen == 0 { + return experimentalsys.EINVAL + } + + oldPathBuf, ok := mem.Read(oldPath, oldPathLen) + if !ok { + return experimentalsys.EFAULT + } + + _, newPathName, errno := atPath(fsc, mod.Memory(), fd, newPath, newPathLen) + if errno != 0 { + return errno + } + + return dir.FS.Symlink( + // Do not join old path since it's only resolved when dereference the link created here. + // And the dereference result depends on the opening directory's file descriptor at that point. + unsafe.String(&oldPathBuf[0], int(oldPathLen)), + newPathName, + ) +} + +// pathUnlinkFile is the WASI function named PathUnlinkFileName which unlinks a +// file. +// +// # Parameters +// +// - fd: file descriptor of a directory that `path` is relative to +// - path: offset in api.Memory to read the path string from +// - pathLen: length of `path` +// +// # Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EBADF: `fd` is invalid +// - sys.ENOENT: `path` does not exist. +// - sys.EISDIR: `path` is a directory +// +// # Notes +// - This is similar to unlinkat without AT_REMOVEDIR in POSIX. +// See https://linux.die.net/man/2/unlinkat +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_unlink_filefd-fd-path-string---errno +var pathUnlinkFile = newHostFunc( + wasip1.PathUnlinkFileName, pathUnlinkFileFn, + []wasm.ValueType{i32, i32, i32}, + "fd", "path", "path_len", +) + +func pathUnlinkFileFn(_ context.Context, mod api.Module, params []uint64) experimentalsys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + path := uint32(params[1]) + pathLen := uint32(params[2]) + + preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen) + if errno != 0 { + return errno + } + + return preopen.Unlink(pathName) +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/poll.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/poll.go new file mode 100644 index 00000000..4f96af2d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/poll.go @@ -0,0 +1,237 @@ +package wasi_snapshot_preview1 + +import ( + "context" + "time" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + internalsys "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// pollOneoff is the WASI function named PollOneoffName that concurrently +// polls for the occurrence of a set of events. +// +// # Parameters +// +// - in: pointer to the subscriptions (48 bytes each) +// - out: pointer to the resulting events (32 bytes each) +// - nsubscriptions: count of subscriptions, zero returns sys.EINVAL. +// - resultNevents: count of events. +// +// Result (Errno) +// +// The return value is 0 except the following error conditions: +// - sys.EINVAL: the parameters are invalid +// - sys.ENOTSUP: a parameters is valid, but not yet supported. +// - sys.EFAULT: there is not enough memory to read the subscriptions or +// write results. +// +// # Notes +// +// - Since the `out` pointer nests Errno, the result is always 0. +// - This is similar to `poll` in POSIX. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#poll_oneoff +// See https://linux.die.net/man/3/poll +var pollOneoff = newHostFunc( + wasip1.PollOneoffName, pollOneoffFn, + []api.ValueType{i32, i32, i32, i32}, + "in", "out", "nsubscriptions", "result.nevents", +) + +type event struct { + eventType byte + userData []byte + errno wasip1.Errno +} + +func pollOneoffFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + in := uint32(params[0]) + out := uint32(params[1]) + nsubscriptions := uint32(params[2]) + resultNevents := uint32(params[3]) + + if nsubscriptions == 0 { + return sys.EINVAL + } + + mem := mod.Memory() + + // Ensure capacity prior to the read loop to reduce error handling. + inBuf, ok := mem.Read(in, nsubscriptions*48) + if !ok { + return sys.EFAULT + } + outBuf, ok := mem.Read(out, nsubscriptions*32) + // zero-out all buffer before writing + clear(outBuf) + + if !ok { + return sys.EFAULT + } + + // Eagerly write the number of events which will equal subscriptions unless + // there's a fault in parsing (not processing). + if !mod.Memory().WriteUint32Le(resultNevents, nsubscriptions) { + return sys.EFAULT + } + + // Loop through all subscriptions and write their output. + + // Extract FS context, used in the body of the for loop for FS access. + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + // Slice of events that are processed out of the loop (blocking stdin subscribers). + var blockingStdinSubs []*event + // The timeout is initialized at max Duration, the loop will find the minimum. + var timeout time.Duration = 1<<63 - 1 + // Count of all the subscriptions that have been already written back to outBuf. + // nevents*32 returns at all times the offset where the next event should be written: + // this way we ensure that there are no gaps between records. + nevents := uint32(0) + + // Layout is subscription_u: Union + // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#subscription_u + for i := uint32(0); i < nsubscriptions; i++ { + inOffset := i * 48 + outOffset := nevents * 32 + + eventType := inBuf[inOffset+8] // +8 past userdata + // +8 past userdata +8 contents_offset + argBuf := inBuf[inOffset+8+8:] + userData := inBuf[inOffset : inOffset+8] + + evt := &event{ + eventType: eventType, + userData: userData, + errno: wasip1.ErrnoSuccess, + } + + switch eventType { + case wasip1.EventTypeClock: // handle later + newTimeout, err := processClockEvent(argBuf) + if err != 0 { + return err + } + // Min timeout. + if newTimeout < timeout { + timeout = newTimeout + } + // Ack the clock event to the outBuf. + writeEvent(outBuf[outOffset:], evt) + nevents++ + case wasip1.EventTypeFdRead: + fd := int32(le.Uint32(argBuf)) + if fd < 0 { + return sys.EBADF + } + if file, ok := fsc.LookupFile(fd); !ok { + evt.errno = wasip1.ErrnoBadf + writeEvent(outBuf[outOffset:], evt) + nevents++ + } else if fd != internalsys.FdStdin && file.File.IsNonblock() { + writeEvent(outBuf[outOffset:], evt) + nevents++ + } else { + // if the fd is Stdin, and it is in blocking mode, + // do not ack yet, append to a slice for delayed evaluation. + blockingStdinSubs = append(blockingStdinSubs, evt) + } + case wasip1.EventTypeFdWrite: + fd := int32(le.Uint32(argBuf)) + if fd < 0 { + return sys.EBADF + } + if _, ok := fsc.LookupFile(fd); ok { + evt.errno = wasip1.ErrnoNotsup + } else { + evt.errno = wasip1.ErrnoBadf + } + nevents++ + writeEvent(outBuf[outOffset:], evt) + default: + return sys.EINVAL + } + } + + sysCtx := mod.(*wasm.ModuleInstance).Sys + if nevents == nsubscriptions { + // We already wrote back all the results. We already wrote this number + // earlier to offset `resultNevents`. + // We only need to observe the timeout (nonzero if there are clock subscriptions) + // and return. + if timeout > 0 { + sysCtx.Nanosleep(int64(timeout)) + } + return 0 + } + + // If there are blocking stdin subscribers, check for data with given timeout. + stdin, ok := fsc.LookupFile(internalsys.FdStdin) + if !ok { + return sys.EBADF + } + // Wait for the timeout to expire, or for some data to become available on Stdin. + + if stdinReady, errno := stdin.File.Poll(fsapi.POLLIN, int32(timeout.Milliseconds())); errno != 0 { + return errno + } else if stdinReady { + // stdin has data ready to for reading, write back all the events + for i := range blockingStdinSubs { + evt := blockingStdinSubs[i] + evt.errno = 0 + writeEvent(outBuf[nevents*32:], evt) + nevents++ + } + } + + if nevents != nsubscriptions { + if !mod.Memory().WriteUint32Le(resultNevents, nevents) { + return sys.EFAULT + } + } + + return 0 +} + +// processClockEvent supports only relative name events, as that's what's used +// to implement sleep in various compilers including Rust, Zig and TinyGo. +func processClockEvent(inBuf []byte) (time.Duration, sys.Errno) { + _ /* ID */ = le.Uint32(inBuf[0:8]) // See below + timeout := le.Uint64(inBuf[8:16]) // nanos if relative + _ /* precision */ = le.Uint64(inBuf[16:24]) // Unused + flags := le.Uint16(inBuf[24:32]) + + var err sys.Errno + // subclockflags has only one flag defined: subscription_clock_abstime + switch flags { + case 0: // relative time + case 1: // subscription_clock_abstime + err = sys.ENOTSUP + default: // subclockflags has only one flag defined. + err = sys.EINVAL + } + + if err != 0 { + return 0, err + } else { + // https://linux.die.net/man/3/clock_settime says relative timers are + // unaffected. Since this function only supports relative timeout, we can + // skip name ID validation and use a single sleep function. + + return time.Duration(timeout), 0 + } +} + +// writeEvent writes the event corresponding to the processed subscription. +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-event-struct +func writeEvent(outBuf []byte, evt *event) { + copy(outBuf, evt.userData) // userdata + outBuf[8] = byte(evt.errno) // uint16, but safe as < 255 + outBuf[9] = 0 + le.PutUint32(outBuf[10:], uint32(evt.eventType)) + // TODO: When FD events are supported, write outOffset+16 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/proc.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/proc.go new file mode 100644 index 00000000..cb0ab487 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/proc.go @@ -0,0 +1,44 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/sys" +) + +// procExit is the WASI function named ProcExitName that terminates the +// execution of the module with an exit code. The only successful exit code is +// zero. +// +// # Parameters +// +// - exitCode: exit code. +// +// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit +var procExit = &wasm.HostFunc{ + ExportName: wasip1.ProcExitName, + Name: wasip1.ProcExitName, + ParamTypes: []api.ValueType{i32}, + ParamNames: []string{"rval"}, + Code: wasm.Code{GoFunc: api.GoModuleFunc(procExitFn)}, +} + +func procExitFn(ctx context.Context, mod api.Module, params []uint64) { + exitCode := uint32(params[0]) + + // Ensure other callers see the exit code. + _ = mod.CloseWithExitCode(ctx, exitCode) + + // Prevent any code from executing after this function. For example, LLVM + // inserts unreachable instructions after calls to exit. + // See: https://github.com/emscripten-core/emscripten/issues/12322 + panic(sys.NewExitError(exitCode)) +} + +// procRaise is stubbed and will never be supported, as it was removed. +// +// See https://github.com/WebAssembly/WASI/pull/136 +var procRaise = stubFunction(wasip1.ProcRaiseName, []api.ValueType{i32}, "sig") diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/random.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/random.go new file mode 100644 index 00000000..e4d7ccee --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/random.go @@ -0,0 +1,55 @@ +package wasi_snapshot_preview1 + +import ( + "context" + "io" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// randomGet is the WASI function named RandomGetName which writes random +// data to a buffer. +// +// # Parameters +// +// - buf: api.Memory offset to write random values +// - bufLen: size of random data in bytes +// +// Result (Errno) +// +// The return value is ErrnoSuccess except the following error conditions: +// - sys.EFAULT: `buf` or `bufLen` point to an offset out of memory +// - sys.EIO: a file system error +// +// For example, if underlying random source was seeded like +// `rand.NewSource(42)`, we expect api.Memory to contain: +// +// bufLen (5) +// +--------------------------+ +// | | +// []byte{?, 0x53, 0x8c, 0x7f, 0x96, 0xb1, ?} +// buf --^ +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-bufLen-size---errno +var randomGet = newHostFunc(wasip1.RandomGetName, randomGetFn, []api.ValueType{i32, i32}, "buf", "buf_len") + +func randomGetFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + randSource := sysCtx.RandSource() + buf, bufLen := uint32(params[0]), uint32(params[1]) + + randomBytes, ok := mod.Memory().Read(buf, bufLen) + if !ok { // out-of-range + return sys.EFAULT + } + + // We can ignore the returned n as it only != byteCount on error + if _, err := io.ReadAtLeast(randSource, randomBytes, int(bufLen)); err != nil { + return sys.EIO + } + + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sched.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sched.go new file mode 100644 index 00000000..86748e6d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sched.go @@ -0,0 +1,22 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// schedYield is the WASI function named SchedYieldName which temporarily +// yields execution of the calling thread. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sched_yield---errno +var schedYield = newHostFunc(wasip1.SchedYieldName, schedYieldFn, nil) + +func schedYieldFn(_ context.Context, mod api.Module, _ []uint64) sys.Errno { + sysCtx := mod.(*wasm.ModuleInstance).Sys + sysCtx.Osyield() + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sock.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sock.go new file mode 100644 index 00000000..756c0d39 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/sock.go @@ -0,0 +1,188 @@ +package wasi_snapshot_preview1 + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + socketapi "github.com/tetratelabs/wazero/internal/sock" + "github.com/tetratelabs/wazero/internal/sysfs" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// sockAccept is the WASI function named SockAcceptName which accepts a new +// incoming connection. +// +// See: https://github.com/WebAssembly/WASI/blob/0ba0c5e2e37625ca5a6d3e4255a998dfaa3efc52/phases/snapshot/docs.md#sock_accept +// and https://github.com/WebAssembly/WASI/pull/458 +var sockAccept = newHostFunc( + wasip1.SockAcceptName, + sockAcceptFn, + []wasm.ValueType{i32, i32, i32}, + "fd", "flags", "result.fd", +) + +func sockAcceptFn(_ context.Context, mod api.Module, params []uint64) (errno sys.Errno) { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + flags := uint32(params[1]) + resultFd := uint32(params[2]) + nonblock := flags&uint32(wasip1.FD_NONBLOCK) != 0 + + var connFD int32 + if connFD, errno = fsc.SockAccept(fd, nonblock); errno == 0 { + mem.WriteUint32Le(resultFd, uint32(connFD)) + } + return +} + +// sockRecv is the WASI function named SockRecvName which receives a +// message from a socket. +// +// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_recvfd-fd-ri_data-iovec_array-ri_flags-riflags---errno-size-roflags +var sockRecv = newHostFunc( + wasip1.SockRecvName, + sockRecvFn, + []wasm.ValueType{i32, i32, i32, i32, i32, i32}, + "fd", "ri_data", "ri_data_len", "ri_flags", "result.ro_datalen", "result.ro_flags", +) + +func sockRecvFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + riData := uint32(params[1]) + riDataCount := uint32(params[2]) + riFlags := uint8(params[3]) + resultRoDatalen := uint32(params[4]) + resultRoFlags := uint32(params[5]) + + var conn socketapi.TCPConn + if e, ok := fsc.LookupFile(fd); !ok { + return sys.EBADF // Not open + } else if conn, ok = e.File.(socketapi.TCPConn); !ok { + return sys.EBADF // Not a conn + } + + if riFlags & ^(wasip1.RI_RECV_PEEK|wasip1.RI_RECV_WAITALL) != 0 { + return sys.ENOTSUP + } + + if riFlags&wasip1.RI_RECV_PEEK != 0 { + // Each record in riData is of the form: + // type iovec struct { buf *uint8; bufLen uint32 } + // This means that the first `uint32` is a `buf *uint8`. + firstIovecBufAddr, ok := mem.ReadUint32Le(riData) + if !ok { + return sys.EINVAL + } + // Read bufLen + firstIovecBufLen, ok := mem.ReadUint32Le(riData + 4) + if !ok { + return sys.EINVAL + } + firstIovecBuf, ok := mem.Read(firstIovecBufAddr, firstIovecBufLen) + if !ok { + return sys.EINVAL + } + n, err := conn.Recvfrom(firstIovecBuf, sysfs.MSG_PEEK) + if err != 0 { + return err + } + mem.WriteUint32Le(resultRoDatalen, uint32(n)) + mem.WriteUint16Le(resultRoFlags, 0) + return 0 + } + + // If riFlags&wasip1.RECV_WAITALL != 0 then we should + // do a blocking operation until all data has been retrieved; + // otherwise we are able to return earlier. + // For simplicity, we currently wait all regardless the flag. + bufSize, errno := readv(mem, riData, riDataCount, conn.Read) + if errno != 0 { + return errno + } + mem.WriteUint32Le(resultRoDatalen, bufSize) + mem.WriteUint16Le(resultRoFlags, 0) + return 0 +} + +// sockSend is the WASI function named SockSendName which sends a message +// on a socket. +// +// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_sendfd-fd-si_data-ciovec_array-si_flags-siflags---errno-size +var sockSend = newHostFunc( + wasip1.SockSendName, + sockSendFn, + []wasm.ValueType{i32, i32, i32, i32, i32}, + "fd", "si_data", "si_data_len", "si_flags", "result.so_datalen", +) + +func sockSendFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + mem := mod.Memory() + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + siData := uint32(params[1]) + siDataCount := uint32(params[2]) + siFlags := uint32(params[3]) + resultSoDatalen := uint32(params[4]) + + if siFlags != 0 { + return sys.ENOTSUP + } + + var conn socketapi.TCPConn + if e, ok := fsc.LookupFile(fd); !ok { + return sys.EBADF // Not open + } else if conn, ok = e.File.(socketapi.TCPConn); !ok { + return sys.EBADF // Not a conn + } + + bufSize, errno := writev(mem, siData, siDataCount, conn.Write) + if errno != 0 { + return errno + } + mem.WriteUint32Le(resultSoDatalen, bufSize) + return 0 +} + +// sockShutdown is the WASI function named SockShutdownName which shuts +// down socket send and receive channels. +// +// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_shutdownfd-fd-how-sdflags---errno +var sockShutdown = newHostFunc(wasip1.SockShutdownName, sockShutdownFn, []wasm.ValueType{i32, i32}, "fd", "how") + +func sockShutdownFn(_ context.Context, mod api.Module, params []uint64) sys.Errno { + fsc := mod.(*wasm.ModuleInstance).Sys.FS() + + fd := int32(params[0]) + how := uint8(params[1]) + + var conn socketapi.TCPConn + if e, ok := fsc.LookupFile(fd); !ok { + return sys.EBADF // Not open + } else if conn, ok = e.File.(socketapi.TCPConn); !ok { + return sys.EBADF // Not a conn + } + + sysHow := 0 + + switch how { + case wasip1.SD_RD | wasip1.SD_WR: + sysHow = socketapi.SHUT_RD | socketapi.SHUT_WR + case wasip1.SD_RD: + sysHow = socketapi.SHUT_RD + case wasip1.SD_WR: + sysHow = socketapi.SHUT_WR + default: + return sys.EINVAL + } + + // TODO: Map this instead of relying on syscall symbols. + return conn.Shutdown(sysHow) +} diff --git a/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/wasi.go b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/wasi.go new file mode 100644 index 00000000..4ef41d50 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/wasi.go @@ -0,0 +1,314 @@ +// Package wasi_snapshot_preview1 contains Go-defined functions to access +// system calls, such as opening a file, similar to Go's x/sys package. These +// are accessible from WebAssembly-defined functions via importing ModuleName. +// All WASI functions return a single Errno result: ErrnoSuccess on success. +// +// e.g. Call Instantiate before instantiating any wasm binary that imports +// "wasi_snapshot_preview1", Otherwise, it will error due to missing imports. +// +// ctx := context.Background() +// r := wazero.NewRuntime(ctx) +// defer r.Close(ctx) // This closes everything this Runtime created. +// +// wasi_snapshot_preview1.MustInstantiate(ctx, r) +// mod, _ := r.Instantiate(ctx, wasm) +// +// See https://github.com/WebAssembly/WASI +package wasi_snapshot_preview1 + +import ( + "context" + "encoding/binary" + + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/wasip1" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// ModuleName is the module name WASI functions are exported into. +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md +const ModuleName = wasip1.InternalModuleName + +const i32, i64 = wasm.ValueTypeI32, wasm.ValueTypeI64 + +var le = binary.LittleEndian + +// MustInstantiate calls Instantiate or panics on error. +// +// This is a simpler function for those who know the module ModuleName is not +// already instantiated, and don't need to unload it. +func MustInstantiate(ctx context.Context, r wazero.Runtime) { + if _, err := Instantiate(ctx, r); err != nil { + panic(err) + } +} + +// Instantiate instantiates the ModuleName module into the runtime. +// +// # Notes +// +// - Failure cases are documented on wazero.Runtime InstantiateModule. +// - Closing the wazero.Runtime has the same effect as closing the result. +func Instantiate(ctx context.Context, r wazero.Runtime) (api.Closer, error) { + return NewBuilder(r).Instantiate(ctx) +} + +// Builder configures the ModuleName module for later use via Compile or Instantiate. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type Builder interface { + // Compile compiles the ModuleName module. Call this before Instantiate. + // + // Note: This has the same effect as the same function on wazero.HostModuleBuilder. + Compile(context.Context) (wazero.CompiledModule, error) + + // Instantiate instantiates the ModuleName module and returns a function to close it. + // + // Note: This has the same effect as the same function on wazero.HostModuleBuilder. + Instantiate(context.Context) (api.Closer, error) +} + +// NewBuilder returns a new Builder. +func NewBuilder(r wazero.Runtime) Builder { + return &builder{r} +} + +type builder struct{ r wazero.Runtime } + +// hostModuleBuilder returns a new wazero.HostModuleBuilder for ModuleName +func (b *builder) hostModuleBuilder() wazero.HostModuleBuilder { + ret := b.r.NewHostModuleBuilder(ModuleName) + exportFunctions(ret) + return ret +} + +// Compile implements Builder.Compile +func (b *builder) Compile(ctx context.Context) (wazero.CompiledModule, error) { + return b.hostModuleBuilder().Compile(ctx) +} + +// Instantiate implements Builder.Instantiate +func (b *builder) Instantiate(ctx context.Context) (api.Closer, error) { + return b.hostModuleBuilder().Instantiate(ctx) +} + +// FunctionExporter exports functions into a wazero.HostModuleBuilder. +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +type FunctionExporter interface { + ExportFunctions(wazero.HostModuleBuilder) +} + +// NewFunctionExporter returns a new FunctionExporter. This is used for the +// following two use cases: +// - Overriding a builtin function with an alternate implementation. +// - Exporting functions to the module "wasi_unstable" for legacy code. +// +// # Example of overriding default behavior +// +// // Export the default WASI functions. +// wasiBuilder := r.NewHostModuleBuilder(ModuleName) +// wasi_snapshot_preview1.NewFunctionExporter().ExportFunctions(wasiBuilder) +// +// // Subsequent calls to NewFunctionBuilder override built-in exports. +// wasiBuilder.NewFunctionBuilder(). +// WithFunc(func(ctx context.Context, mod api.Module, exitCode uint32) { +// // your custom logic +// }).Export("proc_exit") +// +// # Example of using the old module name for WASI +// +// // Instantiate the current WASI functions under the wasi_unstable +// // instead of wasi_snapshot_preview1. +// wasiBuilder := r.NewHostModuleBuilder("wasi_unstable") +// wasi_snapshot_preview1.NewFunctionExporter().ExportFunctions(wasiBuilder) +// _, err := wasiBuilder.Instantiate(testCtx, r) +func NewFunctionExporter() FunctionExporter { + return &functionExporter{} +} + +type functionExporter struct{} + +// ExportFunctions implements FunctionExporter.ExportFunctions +func (functionExporter) ExportFunctions(builder wazero.HostModuleBuilder) { + exportFunctions(builder) +} + +// ## Translation notes +// ### String +// WebAssembly 1.0 has no string type, so any string input parameter expands to two uint32 parameters: offset +// and length. +// +// ### iovec_array +// `iovec_array` is encoded as two uin32le values (i32): offset and count. +// +// ### Result +// Each result besides Errno is always an uint32 parameter. WebAssembly 1.0 can have up to one result, +// which is already used by Errno. This forces other results to be parameters. A result parameter is a memory +// offset to write the result to. As memory offsets are uint32, each parameter representing a result is uint32. +// +// ### Errno +// The WASI specification is sometimes ambiguous resulting in some runtimes interpreting the same function ways. +// Errno mappings are not defined in WASI, yet, so these mappings are best efforts by maintainers. When in doubt +// about portability, first look at /RATIONALE.md and if needed an issue on +// https://github.com/WebAssembly/WASI/issues +// +// ## Memory +// In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means api.Memory is always the +// wasm.Store Memories index zero: `store.Memories[0].Buffer` +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md +// See https://github.com/WebAssembly/WASI/issues/215 +// See https://wwa.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0. + +// exportFunctions adds all go functions that implement wasi. +// These should be exported in the module named ModuleName. +func exportFunctions(builder wazero.HostModuleBuilder) { + exporter := builder.(wasm.HostFuncExporter) + + // Note: these are ordered per spec for consistency even if the resulting + // map can't guarantee that. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions + exporter.ExportHostFunc(argsGet) + exporter.ExportHostFunc(argsSizesGet) + exporter.ExportHostFunc(environGet) + exporter.ExportHostFunc(environSizesGet) + exporter.ExportHostFunc(clockResGet) + exporter.ExportHostFunc(clockTimeGet) + exporter.ExportHostFunc(fdAdvise) + exporter.ExportHostFunc(fdAllocate) + exporter.ExportHostFunc(fdClose) + exporter.ExportHostFunc(fdDatasync) + exporter.ExportHostFunc(fdFdstatGet) + exporter.ExportHostFunc(fdFdstatSetFlags) + exporter.ExportHostFunc(fdFdstatSetRights) + exporter.ExportHostFunc(fdFilestatGet) + exporter.ExportHostFunc(fdFilestatSetSize) + exporter.ExportHostFunc(fdFilestatSetTimes) + exporter.ExportHostFunc(fdPread) + exporter.ExportHostFunc(fdPrestatGet) + exporter.ExportHostFunc(fdPrestatDirName) + exporter.ExportHostFunc(fdPwrite) + exporter.ExportHostFunc(fdRead) + exporter.ExportHostFunc(fdReaddir) + exporter.ExportHostFunc(fdRenumber) + exporter.ExportHostFunc(fdSeek) + exporter.ExportHostFunc(fdSync) + exporter.ExportHostFunc(fdTell) + exporter.ExportHostFunc(fdWrite) + exporter.ExportHostFunc(pathCreateDirectory) + exporter.ExportHostFunc(pathFilestatGet) + exporter.ExportHostFunc(pathFilestatSetTimes) + exporter.ExportHostFunc(pathLink) + exporter.ExportHostFunc(pathOpen) + exporter.ExportHostFunc(pathReadlink) + exporter.ExportHostFunc(pathRemoveDirectory) + exporter.ExportHostFunc(pathRename) + exporter.ExportHostFunc(pathSymlink) + exporter.ExportHostFunc(pathUnlinkFile) + exporter.ExportHostFunc(pollOneoff) + exporter.ExportHostFunc(procExit) + exporter.ExportHostFunc(procRaise) + exporter.ExportHostFunc(schedYield) + exporter.ExportHostFunc(randomGet) + exporter.ExportHostFunc(sockAccept) + exporter.ExportHostFunc(sockRecv) + exporter.ExportHostFunc(sockSend) + exporter.ExportHostFunc(sockShutdown) +} + +// writeOffsetsAndNullTerminatedValues is used to write NUL-terminated values +// for args or environ, given a pre-defined bytesLen (which includes NUL +// terminators). +func writeOffsetsAndNullTerminatedValues(mem api.Memory, values [][]byte, offsets, bytes, bytesLen uint32) sys.Errno { + // The caller may not place bytes directly after offsets, so we have to + // read them independently. + valuesLen := len(values) + offsetsLen := uint32(valuesLen * 4) // uint32Le + offsetsBuf, ok := mem.Read(offsets, offsetsLen) + if !ok { + return sys.EFAULT + } + bytesBuf, ok := mem.Read(bytes, bytesLen) + if !ok { + return sys.EFAULT + } + + // Loop through the values, first writing the location of its data to + // offsetsBuf[oI], then its NUL-terminated data at bytesBuf[bI] + var oI, bI uint32 + for _, value := range values { + // Go can't guarantee inlining as there's not //go:inline directive. + // This inlines uint32 little-endian encoding instead. + bytesOffset := bytes + bI + offsetsBuf[oI] = byte(bytesOffset) + offsetsBuf[oI+1] = byte(bytesOffset >> 8) + offsetsBuf[oI+2] = byte(bytesOffset >> 16) + offsetsBuf[oI+3] = byte(bytesOffset >> 24) + oI += 4 // size of uint32 we just wrote + + // Write the next value to memory with a NUL terminator + copy(bytesBuf[bI:], value) + bI += uint32(len(value)) + bytesBuf[bI] = 0 // NUL terminator + bI++ + } + + return 0 +} + +func newHostFunc( + name string, + goFunc wasiFunc, + paramTypes []api.ValueType, + paramNames ...string, +) *wasm.HostFunc { + return &wasm.HostFunc{ + ExportName: name, + Name: name, + ParamTypes: paramTypes, + ParamNames: paramNames, + ResultTypes: []api.ValueType{i32}, + ResultNames: []string{"errno"}, + Code: wasm.Code{GoFunc: goFunc}, + } +} + +// wasiFunc special cases that all WASI functions return a single Errno +// result. The returned value will be written back to the stack at index zero. +type wasiFunc func(ctx context.Context, mod api.Module, params []uint64) sys.Errno + +// Call implements the same method as documented on api.GoModuleFunction. +func (f wasiFunc) Call(ctx context.Context, mod api.Module, stack []uint64) { + // Write the result back onto the stack + errno := f(ctx, mod, stack) + if errno != 0 { + stack[0] = uint64(wasip1.ToErrno(errno)) + } else { // special case ass ErrnoSuccess is zero + stack[0] = 0 + } +} + +// stubFunction stubs for GrainLang per #271. +func stubFunction(name string, paramTypes []wasm.ValueType, paramNames ...string) *wasm.HostFunc { + return &wasm.HostFunc{ + ExportName: name, + Name: name, + ParamTypes: paramTypes, + ParamNames: paramNames, + ResultTypes: []api.ValueType{i32}, + ResultNames: []string{"errno"}, + Code: wasm.Code{ + GoFunc: api.GoModuleFunc(func(_ context.Context, _ api.Module, stack []uint64) { stack[0] = uint64(wasip1.ErrnoNosys) }), + }, + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/descriptor/table.go b/vendor/github.com/tetratelabs/wazero/internal/descriptor/table.go new file mode 100644 index 00000000..a20e1910 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/descriptor/table.go @@ -0,0 +1,149 @@ +package descriptor + +import ( + "math/bits" + "slices" +) + +// Table is a data structure mapping 32 bit descriptor to items. +// +// # Negative keys are invalid. +// +// Negative keys (e.g. -1) are invalid inputs and will return a corresponding +// not-found value. This matches POSIX behavior of file descriptors. +// See https://pubs.opengroup.org/onlinepubs/9699919799/functions/dirfd.html#tag_16_90 +// +// # Data structure design +// +// The data structure optimizes for memory density and lookup performance, +// trading off compute at insertion time. This is a useful compromise for the +// use cases we employ it with: items are usually accessed a lot more often +// than they are inserted, each operation requires a table lookup, so we are +// better off spending extra compute to insert items in the table in order to +// get cheaper lookups. Memory efficiency is also crucial to support scaling +// with programs that maintain thousands of items: having a high or non-linear +// memory-to-item ratio could otherwise be used as an attack vector by +// malicious applications attempting to damage performance of the host. +type Table[Key ~int32, Item any] struct { + masks []uint64 + items []Item +} + +// Len returns the number of items stored in the table. +func (t *Table[Key, Item]) Len() (n int) { + // We could make this a O(1) operation if we cached the number of items in + // the table. More state usually means more problems, so until we have a + // clear need for this, the simple implementation may be a better trade off. + for _, mask := range t.masks { + n += bits.OnesCount64(mask) + } + return n +} + +// grow grows the table by n * 64 items. +func (t *Table[Key, Item]) grow(n int) { + total := len(t.masks) + n + t.masks = slices.Grow(t.masks, n)[:total] + + total = len(t.items) + n*64 + t.items = slices.Grow(t.items, n*64)[:total] +} + +// Insert inserts the given item to the table, returning the key that it is +// mapped to or false if the table was full. +// +// The method does not perform deduplication, it is possible for the same item +// to be inserted multiple times, each insertion will return a different key. +func (t *Table[Key, Item]) Insert(item Item) (key Key, ok bool) { + offset := 0 +insert: + // Note: this loop could be made a lot more efficient using vectorized + // operations: 256 bits vector registers would yield a theoretical 4x + // speed up (e.g. using AVX2). + for index, mask := range t.masks[offset:] { + if ^mask != 0 { // not full? + shift := bits.TrailingZeros64(^mask) + index += offset + key = Key(index)*64 + Key(shift) + t.items[key] = item + t.masks[index] = mask | uint64(1<= 0 + } + } + + // No free slot found, grow the table and retry. + offset = len(t.masks) + t.grow(1) + goto insert +} + +// Lookup returns the item associated with the given key (may be nil). +func (t *Table[Key, Item]) Lookup(key Key) (item Item, found bool) { + if key < 0 { // invalid key + return + } + if i := int(key); i >= 0 && i < len(t.items) { + index := uint(key) / 64 + shift := uint(key) % 64 + if (t.masks[index] & (1 << shift)) != 0 { + item, found = t.items[i], true + } + } + return +} + +// InsertAt inserts the given `item` at the item descriptor `key`. This returns +// false if the insert was impossible due to negative key. +func (t *Table[Key, Item]) InsertAt(item Item, key Key) bool { + if key < 0 { + return false + } + index := uint(key) / 64 + if diff := int(index) - len(t.masks) + 1; diff > 0 { + t.grow(diff) + } + shift := uint(key) % 64 + t.masks[index] |= 1 << shift + t.items[key] = item + return true +} + +// Delete deletes the item stored at the given key from the table. +func (t *Table[Key, Item]) Delete(key Key) { + if key < 0 { // invalid key + return + } + if index := uint(key) / 64; int(index) < len(t.masks) { + shift := uint(key) % 64 + mask := t.masks[index] + if (mask & (1 << shift)) != 0 { + var zero Item + t.items[key] = zero + t.masks[index] = mask & ^uint64(1< 0 { + // We reserve the stack slots for result values below the return call frame slots. + if diff := c.sig.ResultNumInUint64 - c.sig.ParamNumInUint64; diff > 0 { + current += diff + } + } + + // Non-func param locals Start after the return call frame. + current += c.callFrameStackSizeInUint64 + + for _, lt := range c.localTypes { + c.localIndexToStackHeightInUint64 = append(c.localIndexToStackHeightInUint64, current) + if lt == wasm.ValueTypeV128 { + current++ + } + current++ + } + + // Push function arguments. + for _, t := range c.sig.Params { + c.stackPush(wasmValueTypeTounsignedType(t)) + } + + if c.callFrameStackSizeInUint64 > 0 { + // Reserve the stack slots for results. + for i := 0; i < c.sig.ResultNumInUint64-c.sig.ParamNumInUint64; i++ { + c.stackPush(unsignedTypeI64) + } + + // Reserve the stack slots for call frame. + for i := 0; i < c.callFrameStackSizeInUint64; i++ { + c.stackPush(unsignedTypeI64) + } + } +} + +// compiler is in charge of lowering raw Wasm function body to get compilationResult. +// This is created per *wasm.Module and reused for all functions in it to reduce memory allocations. +type compiler struct { + module *wasm.Module + enabledFeatures api.CoreFeatures + callFrameStackSizeInUint64 int + stack []unsignedType + // stackLenInUint64 is the length of the stack in uint64. + stackLenInUint64 int + currentFrameID uint32 + controlFrames controlFrames + unreachableState struct { + on bool + depth int + } + pc, currentOpPC uint64 + result compilationResult + + // body holds the code for the function's body where Wasm instructions are stored. + body []byte + // sig is the function type of the target function. + sig *wasm.FunctionType + // localTypes holds the target function locals' value types except function params. + localTypes []wasm.ValueType + // localIndexToStackHeightInUint64 maps the local index (starting with function params) to the stack height + // where the local is places. This is the necessary mapping for functions who contain vector type locals. + localIndexToStackHeightInUint64 []int + + // types hold all the function types in the module where the targe function exists. + types []wasm.FunctionType + // funcs holds the type indexes for all declared functions in the module where the target function exists. + funcs []uint32 + // globals holds the global types for all declared globals in the module where the target function exists. + globals []wasm.GlobalType + + // needSourceOffset is true if this module requires DWARF based stack trace. + needSourceOffset bool + // bodyOffsetInCodeSection is the offset of the body of this function in the original Wasm binary's code section. + bodyOffsetInCodeSection uint64 + + ensureTermination bool + // Pre-allocated bytes.Reader to be used in various places. + br *bytes.Reader + funcTypeToSigs funcTypeToIRSignatures + + next int +} + +//lint:ignore U1000 for debugging only. +func (c *compiler) stackDump() string { + strs := make([]string, 0, len(c.stack)) + for _, s := range c.stack { + strs = append(strs, s.String()) + } + return "[" + strings.Join(strs, ", ") + "]" +} + +func (c *compiler) markUnreachable() { + c.unreachableState.on = true +} + +func (c *compiler) resetUnreachable() { + c.unreachableState.on = false +} + +// memoryType is the type of memory in a compiled module. +type memoryType byte + +const ( + // memoryTypeNone indicates there is no memory. + memoryTypeNone memoryType = iota + // memoryTypeStandard indicates there is a non-shared memory. + memoryTypeStandard + // memoryTypeShared indicates there is a shared memory. + memoryTypeShared +) + +type compilationResult struct { + // Operations holds interpreterir operations compiled from Wasm instructions in a Wasm function. + Operations []unionOperation + + // IROperationSourceOffsetsInWasmBinary is index-correlated with Operation and maps each operation to the corresponding source instruction's + // offset in the original WebAssembly binary. + // Non nil only when the given Wasm module has the DWARF section. + IROperationSourceOffsetsInWasmBinary []uint64 + + // LabelCallers maps label to the number of callers to that label. + // Here "callers" means that the call-sites which jumps to the label with br, br_if or br_table + // instructions. + // + // Note: zero possible and allowed in wasm. e.g. + // + // (block + // (br 0) + // (block i32.const 1111) + // ) + // + // This example the label corresponding to `(block i32.const 1111)` is never be reached at runtime because `br 0` exits the function before we reach there + LabelCallers map[label]uint32 + // UsesMemory is true if this function might use memory. + UsesMemory bool + + // The following fields are per-module values, not per-function. + + // Globals holds all the declarations of globals in the module from which this function is compiled. + Globals []wasm.GlobalType + // Functions holds all the declarations of function in the module from which this function is compiled, including itself. + Functions []wasm.Index + // Types holds all the types in the module from which this function is compiled. + Types []wasm.FunctionType + // Memory indicates the type of memory of the module. + Memory memoryType + // HasTable is true if the module from which this function is compiled has table declaration. + HasTable bool + // HasDataInstances is true if the module has data instances which might be used by memory.init or data.drop instructions. + HasDataInstances bool + // HasDataInstances is true if the module has element instances which might be used by table.init or elem.drop instructions. + HasElementInstances bool +} + +// newCompiler returns the new *compiler for the given parameters. +// Use compiler.Next function to get compilation result per function. +func newCompiler(enabledFeatures api.CoreFeatures, callFrameStackSizeInUint64 int, module *wasm.Module, ensureTermination bool) (*compiler, error) { + functions, globals, mem, tables, err := module.AllDeclarations() + if err != nil { + return nil, err + } + + hasTable, hasDataInstances, hasElementInstances := len(tables) > 0, + len(module.DataSection) > 0, len(module.ElementSection) > 0 + + var mt memoryType + switch { + case mem == nil: + mt = memoryTypeNone + case mem.IsShared: + mt = memoryTypeShared + default: + mt = memoryTypeStandard + } + + types := module.TypeSection + + c := &compiler{ + module: module, + enabledFeatures: enabledFeatures, + controlFrames: controlFrames{}, + callFrameStackSizeInUint64: callFrameStackSizeInUint64, + result: compilationResult{ + Globals: globals, + Functions: functions, + Types: types, + Memory: mt, + HasTable: hasTable, + HasDataInstances: hasDataInstances, + HasElementInstances: hasElementInstances, + LabelCallers: map[label]uint32{}, + }, + globals: globals, + funcs: functions, + types: types, + ensureTermination: ensureTermination, + br: bytes.NewReader(nil), + funcTypeToSigs: funcTypeToIRSignatures{ + indirectCalls: make([]*signature, len(types)), + directCalls: make([]*signature, len(types)), + wasmTypes: types, + }, + needSourceOffset: module.DWARFLines != nil, + } + return c, nil +} + +// Next returns the next compilationResult for this compiler. +func (c *compiler) Next() (*compilationResult, error) { + funcIndex := c.next + code := &c.module.CodeSection[funcIndex] + sig := &c.types[c.module.FunctionSection[funcIndex]] + + // Reset the previous result. + c.result.Operations = c.result.Operations[:0] + c.result.IROperationSourceOffsetsInWasmBinary = c.result.IROperationSourceOffsetsInWasmBinary[:0] + c.result.UsesMemory = false + // Clears the existing entries in LabelCallers. + for frameID := uint32(0); frameID <= c.currentFrameID; frameID++ { + for k := labelKind(0); k < labelKindNum; k++ { + delete(c.result.LabelCallers, newLabel(k, frameID)) + } + } + // Reset the previous states. + c.pc = 0 + c.currentOpPC = 0 + c.currentFrameID = 0 + c.stackLenInUint64 = 0 + c.unreachableState.on, c.unreachableState.depth = false, 0 + + if err := c.compile(sig, code.Body, code.LocalTypes, code.BodyOffsetInCodeSection); err != nil { + return nil, err + } + c.next++ + return &c.result, nil +} + +// Compile lowers given function instance into interpreterir operations +// so that the resulting operations can be consumed by the interpreter +// or the compiler compilation engine. +func (c *compiler) compile(sig *wasm.FunctionType, body []byte, localTypes []wasm.ValueType, bodyOffsetInCodeSection uint64) error { + // Set function specific fields. + c.body = body + c.localTypes = localTypes + c.sig = sig + c.bodyOffsetInCodeSection = bodyOffsetInCodeSection + + // Reuses the underlying slices. + c.stack = c.stack[:0] + c.controlFrames.frames = c.controlFrames.frames[:0] + + c.initializeStack() + + // Emit const expressions for locals. + // Note that here we don't take function arguments + // into account, meaning that callers must push + // arguments before entering into the function body. + for _, t := range c.localTypes { + c.emitDefaultValue(t) + } + + // Insert the function control frame. + c.controlFrames.push(controlFrame{ + frameID: c.nextFrameID(), + blockType: c.sig, + kind: controlFrameKindFunction, + }) + + // Now, enter the function body. + for !c.controlFrames.empty() && c.pc < uint64(len(c.body)) { + if err := c.handleInstruction(); err != nil { + return fmt.Errorf("handling instruction: %w", err) + } + } + return nil +} + +// Translate the current Wasm instruction to interpreterir's operations, +// and emit the results into c.results. +func (c *compiler) handleInstruction() error { + op := c.body[c.pc] + c.currentOpPC = c.pc + if false { + var instName string + if op == wasm.OpcodeVecPrefix { + instName = wasm.VectorInstructionName(c.body[c.pc+1]) + } else if op == wasm.OpcodeAtomicPrefix { + instName = wasm.AtomicInstructionName(c.body[c.pc+1]) + } else if op == wasm.OpcodeMiscPrefix { + instName = wasm.MiscInstructionName(c.body[c.pc+1]) + } else { + instName = wasm.InstructionName(op) + } + fmt.Printf("handling %s, unreachable_state(on=%v,depth=%d), stack=%v\n", + instName, c.unreachableState.on, c.unreachableState.depth, c.stack, + ) + } + + var peekValueType unsignedType + if len(c.stack) > 0 { + peekValueType = c.stackPeek() + } + + // Modify the stack according the current instruction. + // Note that some instructions will read "index" in + // applyToStack and advance c.pc inside the function. + index, err := c.applyToStack(op) + if err != nil { + return fmt.Errorf("apply stack failed for %s: %w", wasm.InstructionName(op), err) + } + // Now we handle each instruction, and + // emit the corresponding interpreterir operations to the results. +operatorSwitch: + switch op { + case wasm.OpcodeUnreachable: + c.emit(newOperationUnreachable()) + c.markUnreachable() + case wasm.OpcodeNop: + // Nop is noop! + case wasm.OpcodeBlock: + c.br.Reset(c.body[c.pc+1:]) + bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) + if err != nil { + return fmt.Errorf("reading block type for block instruction: %w", err) + } + c.pc += num + + if c.unreachableState.on { + // If it is currently in unreachable, + // just remove the entire block. + c.unreachableState.depth++ + break operatorSwitch + } + + // Create a new frame -- entering this block. + frame := controlFrame{ + frameID: c.nextFrameID(), + originalStackLenWithoutParam: len(c.stack) - len(bt.Params), + originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64, + kind: controlFrameKindBlockWithoutContinuationLabel, + blockType: bt, + } + c.controlFrames.push(frame) + + case wasm.OpcodeLoop: + c.br.Reset(c.body[c.pc+1:]) + bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) + if err != nil { + return fmt.Errorf("reading block type for loop instruction: %w", err) + } + c.pc += num + + if c.unreachableState.on { + // If it is currently in unreachable, + // just remove the entire block. + c.unreachableState.depth++ + break operatorSwitch + } + + // Create a new frame -- entering loop. + frame := controlFrame{ + frameID: c.nextFrameID(), + originalStackLenWithoutParam: len(c.stack) - len(bt.Params), + originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64, + kind: controlFrameKindLoop, + blockType: bt, + } + c.controlFrames.push(frame) + + // Prep labels for inside and the continuation of this loop. + loopLabel := newLabel(labelKindHeader, frame.frameID) + c.result.LabelCallers[loopLabel]++ + + // Emit the branch operation to enter inside the loop. + c.emit(newOperationBr(loopLabel)) + c.emit(newOperationLabel(loopLabel)) + + // Insert the exit code check on the loop header, which is the only necessary point in the function body + // to prevent infinite loop. + // + // Note that this is a little aggressive: this checks the exit code regardless the loop header is actually + // the loop. In other words, this checks even when no br/br_if/br_table instructions jumping to this loop + // exist. However, in reality, that shouldn't be an issue since such "noop" loop header will highly likely be + // optimized out by almost all guest language compilers which have the control flow optimization passes. + if c.ensureTermination { + c.emit(newOperationBuiltinFunctionCheckExitCode()) + } + case wasm.OpcodeIf: + c.br.Reset(c.body[c.pc+1:]) + bt, num, err := wasm.DecodeBlockType(c.types, c.br, c.enabledFeatures) + if err != nil { + return fmt.Errorf("reading block type for if instruction: %w", err) + } + c.pc += num + + if c.unreachableState.on { + // If it is currently in unreachable, + // just remove the entire block. + c.unreachableState.depth++ + break operatorSwitch + } + + // Create a new frame -- entering if. + frame := controlFrame{ + frameID: c.nextFrameID(), + originalStackLenWithoutParam: len(c.stack) - len(bt.Params), + originalStackLenWithoutParamUint64: c.stackLenInUint64 - bt.ParamNumInUint64, + // Note this will be set to controlFrameKindIfWithElse + // when else opcode found later. + kind: controlFrameKindIfWithoutElse, + blockType: bt, + } + c.controlFrames.push(frame) + + // Prep labels for if and else of this if. + thenLabel := newLabel(labelKindHeader, frame.frameID) + elseLabel := newLabel(labelKindElse, frame.frameID) + c.result.LabelCallers[thenLabel]++ + c.result.LabelCallers[elseLabel]++ + + // Emit the branch operation to enter the then block. + c.emit(newOperationBrIf(thenLabel, elseLabel, nopinclusiveRange)) + c.emit(newOperationLabel(thenLabel)) + case wasm.OpcodeElse: + frame := c.controlFrames.top() + if c.unreachableState.on && c.unreachableState.depth > 0 { + // If it is currently in unreachable, and the nested if, + // just remove the entire else block. + break operatorSwitch + } else if c.unreachableState.on { + // If it is currently in unreachable, and the non-nested if, + // reset the stack so we can correctly handle the else block. + top := c.controlFrames.top() + c.stackSwitchAt(top) + top.kind = controlFrameKindIfWithElse + + // Re-push the parameters to the if block so that else block can use them. + for _, t := range frame.blockType.Params { + c.stackPush(wasmValueTypeTounsignedType(t)) + } + + // We are no longer unreachable in else frame, + // so emit the correct label, and reset the unreachable state. + elseLabel := newLabel(labelKindElse, frame.frameID) + c.resetUnreachable() + c.emit( + newOperationLabel(elseLabel), + ) + break operatorSwitch + } + + // Change the Kind of this If block, indicating that + // the if has else block. + frame.kind = controlFrameKindIfWithElse + + // We need to reset the stack so that + // the values pushed inside the then block + // do not affect the else block. + dropOp := newOperationDrop(c.getFrameDropRange(frame, false)) + + // Reset the stack manipulated by the then block, and re-push the block param types to the stack. + + c.stackSwitchAt(frame) + for _, t := range frame.blockType.Params { + c.stackPush(wasmValueTypeTounsignedType(t)) + } + + // Prep labels for else and the continuation of this if block. + elseLabel := newLabel(labelKindElse, frame.frameID) + continuationLabel := newLabel(labelKindContinuation, frame.frameID) + c.result.LabelCallers[continuationLabel]++ + + // Emit the instructions for exiting the if loop, + // and then the initiation of else block. + c.emit(dropOp) + // Jump to the continuation of this block. + c.emit(newOperationBr(continuationLabel)) + // Initiate the else block. + c.emit(newOperationLabel(elseLabel)) + case wasm.OpcodeEnd: + if c.unreachableState.on && c.unreachableState.depth > 0 { + c.unreachableState.depth-- + break operatorSwitch + } else if c.unreachableState.on { + c.resetUnreachable() + + frame := c.controlFrames.pop() + if c.controlFrames.empty() { + return nil + } + + c.stackSwitchAt(frame) + for _, t := range frame.blockType.Results { + c.stackPush(wasmValueTypeTounsignedType(t)) + } + + continuationLabel := newLabel(labelKindContinuation, frame.frameID) + if frame.kind == controlFrameKindIfWithoutElse { + // Emit the else label. + elseLabel := newLabel(labelKindElse, frame.frameID) + c.result.LabelCallers[continuationLabel]++ + c.emit(newOperationLabel(elseLabel)) + c.emit(newOperationBr(continuationLabel)) + c.emit(newOperationLabel(continuationLabel)) + } else { + c.emit( + newOperationLabel(continuationLabel), + ) + } + + break operatorSwitch + } + + frame := c.controlFrames.pop() + + // We need to reset the stack so that + // the values pushed inside the block. + dropOp := newOperationDrop(c.getFrameDropRange(frame, true)) + c.stackSwitchAt(frame) + + // Push the result types onto the stack. + for _, t := range frame.blockType.Results { + c.stackPush(wasmValueTypeTounsignedType(t)) + } + + // Emit the instructions according to the Kind of the current control frame. + switch frame.kind { + case controlFrameKindFunction: + if !c.controlFrames.empty() { + // Should never happen. If so, there's a bug in the translation. + panic("bug: found more function control frames") + } + // Return from function. + c.emit(dropOp) + c.emit(newOperationBr(newLabel(labelKindReturn, 0))) + case controlFrameKindIfWithoutElse: + // This case we have to emit "empty" else label. + elseLabel := newLabel(labelKindElse, frame.frameID) + continuationLabel := newLabel(labelKindContinuation, frame.frameID) + c.result.LabelCallers[continuationLabel] += 2 + c.emit(dropOp) + c.emit(newOperationBr(continuationLabel)) + // Emit the else which soon branches into the continuation. + c.emit(newOperationLabel(elseLabel)) + c.emit(newOperationBr(continuationLabel)) + // Initiate the continuation. + c.emit(newOperationLabel(continuationLabel)) + case controlFrameKindBlockWithContinuationLabel, + controlFrameKindIfWithElse: + continuationLabel := newLabel(labelKindContinuation, frame.frameID) + c.result.LabelCallers[continuationLabel]++ + c.emit(dropOp) + c.emit(newOperationBr(continuationLabel)) + c.emit(newOperationLabel(continuationLabel)) + case controlFrameKindLoop, controlFrameKindBlockWithoutContinuationLabel: + c.emit( + dropOp, + ) + default: + // Should never happen. If so, there's a bug in the translation. + panic(fmt.Errorf("bug: invalid control frame Kind: 0x%x", frame.kind)) + } + + case wasm.OpcodeBr: + targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("read the target for br_if: %w", err) + } + c.pc += n + + if c.unreachableState.on { + // If it is currently in unreachable, br is no-op. + break operatorSwitch + } + + targetFrame := c.controlFrames.get(int(targetIndex)) + targetFrame.ensureContinuation() + dropOp := newOperationDrop(c.getFrameDropRange(targetFrame, false)) + targetID := targetFrame.asLabel() + c.result.LabelCallers[targetID]++ + c.emit(dropOp) + c.emit(newOperationBr(targetID)) + // Br operation is stack-polymorphic, and mark the state as unreachable. + // That means subsequent instructions in the current control frame are "unreachable" + // and can be safely removed. + c.markUnreachable() + case wasm.OpcodeBrIf: + targetIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("read the target for br_if: %w", err) + } + c.pc += n + + if c.unreachableState.on { + // If it is currently in unreachable, br-if is no-op. + break operatorSwitch + } + + targetFrame := c.controlFrames.get(int(targetIndex)) + targetFrame.ensureContinuation() + drop := c.getFrameDropRange(targetFrame, false) + target := targetFrame.asLabel() + c.result.LabelCallers[target]++ + + continuationLabel := newLabel(labelKindHeader, c.nextFrameID()) + c.result.LabelCallers[continuationLabel]++ + c.emit(newOperationBrIf(target, continuationLabel, drop)) + // Start emitting else block operations. + c.emit(newOperationLabel(continuationLabel)) + case wasm.OpcodeBrTable: + c.br.Reset(c.body[c.pc+1:]) + r := c.br + numTargets, n, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("error reading number of targets in br_table: %w", err) + } + c.pc += n + + if c.unreachableState.on { + // If it is currently in unreachable, br_table is no-op. + // But before proceeding to the next instruction, we must advance the pc + // according to the number of br_table targets. + for i := uint32(0); i <= numTargets; i++ { // inclusive as we also need to read the index of default target. + _, n, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("error reading target %d in br_table: %w", i, err) + } + c.pc += n + } + break operatorSwitch + } + + // Read the branch targets. + s := numTargets * 2 + targetLabels := make([]uint64, 2+s) // (label, inclusiveRange) * (default+numTargets) + for i := uint32(0); i < s; i += 2 { + l, n, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("error reading target %d in br_table: %w", i, err) + } + c.pc += n + targetFrame := c.controlFrames.get(int(l)) + targetFrame.ensureContinuation() + drop := c.getFrameDropRange(targetFrame, false) + targetLabel := targetFrame.asLabel() + targetLabels[i] = uint64(targetLabel) + targetLabels[i+1] = drop.AsU64() + c.result.LabelCallers[targetLabel]++ + } + + // Prep default target control frame. + l, n, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("error reading default target of br_table: %w", err) + } + c.pc += n + defaultTargetFrame := c.controlFrames.get(int(l)) + defaultTargetFrame.ensureContinuation() + defaultTargetDrop := c.getFrameDropRange(defaultTargetFrame, false) + defaultLabel := defaultTargetFrame.asLabel() + c.result.LabelCallers[defaultLabel]++ + targetLabels[s] = uint64(defaultLabel) + targetLabels[s+1] = defaultTargetDrop.AsU64() + c.emit(newOperationBrTable(targetLabels)) + + // br_table operation is stack-polymorphic, and mark the state as unreachable. + // That means subsequent instructions in the current control frame are "unreachable" + // and can be safely removed. + c.markUnreachable() + case wasm.OpcodeReturn: + functionFrame := c.controlFrames.functionFrame() + dropOp := newOperationDrop(c.getFrameDropRange(functionFrame, false)) + + // Cleanup the stack and then jmp to function frame's continuation (meaning return). + c.emit(dropOp) + c.emit(newOperationBr(functionFrame.asLabel())) + + // Return operation is stack-polymorphic, and mark the state as unreachable. + // That means subsequent instructions in the current control frame are "unreachable" + // and can be safely removed. + c.markUnreachable() + case wasm.OpcodeCall: + c.emit( + newOperationCall(index), + ) + case wasm.OpcodeCallIndirect: + typeIndex := index + tableIndex, n, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("read target for br_table: %w", err) + } + c.pc += n + c.emit( + newOperationCallIndirect(typeIndex, tableIndex), + ) + case wasm.OpcodeDrop: + r := inclusiveRange{Start: 0, End: 0} + if peekValueType == unsignedTypeV128 { + // inclusiveRange is the range in uint64 representation, so dropping a vector value on top + // should be translated as drop [0..1] inclusively. + r.End++ + } + c.emit(newOperationDrop(r)) + case wasm.OpcodeSelect: + // If it is on the unreachable state, ignore the instruction. + if c.unreachableState.on { + break operatorSwitch + } + isTargetVector := c.stackPeek() == unsignedTypeV128 + c.emit( + newOperationSelect(isTargetVector), + ) + case wasm.OpcodeTypedSelect: + // Skips two bytes: vector size fixed to 1, and the value type for select. + c.pc += 2 + // If it is on the unreachable state, ignore the instruction. + if c.unreachableState.on { + break operatorSwitch + } + // Typed select is semantically equivalent to select at runtime. + isTargetVector := c.stackPeek() == unsignedTypeV128 + c.emit( + newOperationSelect(isTargetVector), + ) + case wasm.OpcodeLocalGet: + depth := c.localDepth(index) + if isVector := c.localType(index) == wasm.ValueTypeV128; !isVector { + c.emit( + // -1 because we already manipulated the stack before + // called localDepth ^^. + newOperationPick(depth-1, isVector), + ) + } else { + c.emit( + // -2 because we already manipulated the stack before + // called localDepth ^^. + newOperationPick(depth-2, isVector), + ) + } + case wasm.OpcodeLocalSet: + depth := c.localDepth(index) + + isVector := c.localType(index) == wasm.ValueTypeV128 + if isVector { + c.emit( + // +2 because we already popped the operands for this operation from the c.stack before + // called localDepth ^^, + newOperationSet(depth+2, isVector), + ) + } else { + c.emit( + // +1 because we already popped the operands for this operation from the c.stack before + // called localDepth ^^, + newOperationSet(depth+1, isVector), + ) + } + case wasm.OpcodeLocalTee: + depth := c.localDepth(index) + isVector := c.localType(index) == wasm.ValueTypeV128 + if isVector { + c.emit(newOperationPick(1, isVector)) + c.emit(newOperationSet(depth+2, isVector)) + } else { + c.emit( + newOperationPick(0, isVector)) + c.emit(newOperationSet(depth+1, isVector)) + } + case wasm.OpcodeGlobalGet: + c.emit( + newOperationGlobalGet(index), + ) + case wasm.OpcodeGlobalSet: + c.emit( + newOperationGlobalSet(index), + ) + case wasm.OpcodeI32Load: + imm, err := c.readMemoryArg(wasm.OpcodeI32LoadName) + if err != nil { + return err + } + c.emit(newOperationLoad(unsignedTypeI32, imm)) + case wasm.OpcodeI64Load: + imm, err := c.readMemoryArg(wasm.OpcodeI64LoadName) + if err != nil { + return err + } + c.emit(newOperationLoad(unsignedTypeI64, imm)) + case wasm.OpcodeF32Load: + imm, err := c.readMemoryArg(wasm.OpcodeF32LoadName) + if err != nil { + return err + } + c.emit(newOperationLoad(unsignedTypeF32, imm)) + case wasm.OpcodeF64Load: + imm, err := c.readMemoryArg(wasm.OpcodeF64LoadName) + if err != nil { + return err + } + c.emit(newOperationLoad(unsignedTypeF64, imm)) + case wasm.OpcodeI32Load8S: + imm, err := c.readMemoryArg(wasm.OpcodeI32Load8SName) + if err != nil { + return err + } + c.emit(newOperationLoad8(signedInt32, imm)) + case wasm.OpcodeI32Load8U: + imm, err := c.readMemoryArg(wasm.OpcodeI32Load8UName) + if err != nil { + return err + } + c.emit(newOperationLoad8(signedUint32, imm)) + case wasm.OpcodeI32Load16S: + imm, err := c.readMemoryArg(wasm.OpcodeI32Load16SName) + if err != nil { + return err + } + c.emit(newOperationLoad16(signedInt32, imm)) + case wasm.OpcodeI32Load16U: + imm, err := c.readMemoryArg(wasm.OpcodeI32Load16UName) + if err != nil { + return err + } + c.emit(newOperationLoad16(signedUint32, imm)) + case wasm.OpcodeI64Load8S: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load8SName) + if err != nil { + return err + } + c.emit(newOperationLoad8(signedInt64, imm)) + case wasm.OpcodeI64Load8U: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load8UName) + if err != nil { + return err + } + c.emit(newOperationLoad8(signedUint64, imm)) + case wasm.OpcodeI64Load16S: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load16SName) + if err != nil { + return err + } + c.emit(newOperationLoad16(signedInt64, imm)) + case wasm.OpcodeI64Load16U: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load16UName) + if err != nil { + return err + } + c.emit(newOperationLoad16(signedUint64, imm)) + case wasm.OpcodeI64Load32S: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load32SName) + if err != nil { + return err + } + c.emit(newOperationLoad32(true, imm)) + case wasm.OpcodeI64Load32U: + imm, err := c.readMemoryArg(wasm.OpcodeI64Load32UName) + if err != nil { + return err + } + c.emit(newOperationLoad32(false, imm)) + case wasm.OpcodeI32Store: + imm, err := c.readMemoryArg(wasm.OpcodeI32StoreName) + if err != nil { + return err + } + c.emit( + newOperationStore(unsignedTypeI32, imm), + ) + case wasm.OpcodeI64Store: + imm, err := c.readMemoryArg(wasm.OpcodeI64StoreName) + if err != nil { + return err + } + c.emit( + newOperationStore(unsignedTypeI64, imm), + ) + case wasm.OpcodeF32Store: + imm, err := c.readMemoryArg(wasm.OpcodeF32StoreName) + if err != nil { + return err + } + c.emit( + newOperationStore(unsignedTypeF32, imm), + ) + case wasm.OpcodeF64Store: + imm, err := c.readMemoryArg(wasm.OpcodeF64StoreName) + if err != nil { + return err + } + c.emit( + newOperationStore(unsignedTypeF64, imm), + ) + case wasm.OpcodeI32Store8: + imm, err := c.readMemoryArg(wasm.OpcodeI32Store8Name) + if err != nil { + return err + } + c.emit( + newOperationStore8(imm), + ) + case wasm.OpcodeI32Store16: + imm, err := c.readMemoryArg(wasm.OpcodeI32Store16Name) + if err != nil { + return err + } + c.emit( + newOperationStore16(imm), + ) + case wasm.OpcodeI64Store8: + imm, err := c.readMemoryArg(wasm.OpcodeI64Store8Name) + if err != nil { + return err + } + c.emit( + newOperationStore8(imm), + ) + case wasm.OpcodeI64Store16: + imm, err := c.readMemoryArg(wasm.OpcodeI64Store16Name) + if err != nil { + return err + } + c.emit( + newOperationStore16(imm), + ) + case wasm.OpcodeI64Store32: + imm, err := c.readMemoryArg(wasm.OpcodeI64Store32Name) + if err != nil { + return err + } + c.emit( + newOperationStore32(imm), + ) + case wasm.OpcodeMemorySize: + c.result.UsesMemory = true + c.pc++ // Skip the reserved one byte. + c.emit( + newOperationMemorySize(), + ) + case wasm.OpcodeMemoryGrow: + c.result.UsesMemory = true + c.pc++ // Skip the reserved one byte. + c.emit( + newOperationMemoryGrow(), + ) + case wasm.OpcodeI32Const: + val, num, err := leb128.LoadInt32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationConstI32(uint32(val)), + ) + case wasm.OpcodeI64Const: + val, num, err := leb128.LoadInt64(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i64.const value: %v", err) + } + c.pc += num + c.emit( + newOperationConstI64(uint64(val)), + ) + case wasm.OpcodeF32Const: + v := math.Float32frombits(binary.LittleEndian.Uint32(c.body[c.pc+1:])) + c.pc += 4 + c.emit( + newOperationConstF32(v), + ) + case wasm.OpcodeF64Const: + v := math.Float64frombits(binary.LittleEndian.Uint64(c.body[c.pc+1:])) + c.pc += 8 + c.emit( + newOperationConstF64(v), + ) + case wasm.OpcodeI32Eqz: + c.emit( + newOperationEqz(unsignedInt32), + ) + case wasm.OpcodeI32Eq: + c.emit( + newOperationEq(unsignedTypeI32), + ) + case wasm.OpcodeI32Ne: + c.emit( + newOperationNe(unsignedTypeI32), + ) + case wasm.OpcodeI32LtS: + c.emit( + newOperationLt(signedTypeInt32), + ) + case wasm.OpcodeI32LtU: + c.emit( + newOperationLt(signedTypeUint32), + ) + case wasm.OpcodeI32GtS: + c.emit( + newOperationGt(signedTypeInt32), + ) + case wasm.OpcodeI32GtU: + c.emit( + newOperationGt(signedTypeUint32), + ) + case wasm.OpcodeI32LeS: + c.emit( + newOperationLe(signedTypeInt32), + ) + case wasm.OpcodeI32LeU: + c.emit( + newOperationLe(signedTypeUint32), + ) + case wasm.OpcodeI32GeS: + c.emit( + newOperationGe(signedTypeInt32), + ) + case wasm.OpcodeI32GeU: + c.emit( + newOperationGe(signedTypeUint32), + ) + case wasm.OpcodeI64Eqz: + c.emit( + newOperationEqz(unsignedInt64), + ) + case wasm.OpcodeI64Eq: + c.emit( + newOperationEq(unsignedTypeI64), + ) + case wasm.OpcodeI64Ne: + c.emit( + newOperationNe(unsignedTypeI64), + ) + case wasm.OpcodeI64LtS: + c.emit( + newOperationLt(signedTypeInt64), + ) + case wasm.OpcodeI64LtU: + c.emit( + newOperationLt(signedTypeUint64), + ) + case wasm.OpcodeI64GtS: + c.emit( + newOperationGt(signedTypeInt64), + ) + case wasm.OpcodeI64GtU: + c.emit( + newOperationGt(signedTypeUint64), + ) + case wasm.OpcodeI64LeS: + c.emit( + newOperationLe(signedTypeInt64), + ) + case wasm.OpcodeI64LeU: + c.emit( + newOperationLe(signedTypeUint64), + ) + case wasm.OpcodeI64GeS: + c.emit( + newOperationGe(signedTypeInt64), + ) + case wasm.OpcodeI64GeU: + c.emit( + newOperationGe(signedTypeUint64), + ) + case wasm.OpcodeF32Eq: + c.emit( + newOperationEq(unsignedTypeF32), + ) + case wasm.OpcodeF32Ne: + c.emit( + newOperationNe(unsignedTypeF32), + ) + case wasm.OpcodeF32Lt: + c.emit( + newOperationLt(signedTypeFloat32), + ) + case wasm.OpcodeF32Gt: + c.emit( + newOperationGt(signedTypeFloat32), + ) + case wasm.OpcodeF32Le: + c.emit( + newOperationLe(signedTypeFloat32), + ) + case wasm.OpcodeF32Ge: + c.emit( + newOperationGe(signedTypeFloat32), + ) + case wasm.OpcodeF64Eq: + c.emit( + newOperationEq(unsignedTypeF64), + ) + case wasm.OpcodeF64Ne: + c.emit( + newOperationNe(unsignedTypeF64), + ) + case wasm.OpcodeF64Lt: + c.emit( + newOperationLt(signedTypeFloat64), + ) + case wasm.OpcodeF64Gt: + c.emit( + newOperationGt(signedTypeFloat64), + ) + case wasm.OpcodeF64Le: + c.emit( + newOperationLe(signedTypeFloat64), + ) + case wasm.OpcodeF64Ge: + c.emit( + newOperationGe(signedTypeFloat64), + ) + case wasm.OpcodeI32Clz: + c.emit( + newOperationClz(unsignedInt32), + ) + case wasm.OpcodeI32Ctz: + c.emit( + newOperationCtz(unsignedInt32), + ) + case wasm.OpcodeI32Popcnt: + c.emit( + newOperationPopcnt(unsignedInt32), + ) + case wasm.OpcodeI32Add: + c.emit( + newOperationAdd(unsignedTypeI32), + ) + case wasm.OpcodeI32Sub: + c.emit( + newOperationSub(unsignedTypeI32), + ) + case wasm.OpcodeI32Mul: + c.emit( + newOperationMul(unsignedTypeI32), + ) + case wasm.OpcodeI32DivS: + c.emit( + newOperationDiv(signedTypeInt32), + ) + case wasm.OpcodeI32DivU: + c.emit( + newOperationDiv(signedTypeUint32), + ) + case wasm.OpcodeI32RemS: + c.emit( + newOperationRem(signedInt32), + ) + case wasm.OpcodeI32RemU: + c.emit( + newOperationRem(signedUint32), + ) + case wasm.OpcodeI32And: + c.emit( + newOperationAnd(unsignedInt32), + ) + case wasm.OpcodeI32Or: + c.emit( + newOperationOr(unsignedInt32), + ) + case wasm.OpcodeI32Xor: + c.emit( + newOperationXor(unsignedInt64), + ) + case wasm.OpcodeI32Shl: + c.emit( + newOperationShl(unsignedInt32), + ) + case wasm.OpcodeI32ShrS: + c.emit( + newOperationShr(signedInt32), + ) + case wasm.OpcodeI32ShrU: + c.emit( + newOperationShr(signedUint32), + ) + case wasm.OpcodeI32Rotl: + c.emit( + newOperationRotl(unsignedInt32), + ) + case wasm.OpcodeI32Rotr: + c.emit( + newOperationRotr(unsignedInt32), + ) + case wasm.OpcodeI64Clz: + c.emit( + newOperationClz(unsignedInt64), + ) + case wasm.OpcodeI64Ctz: + c.emit( + newOperationCtz(unsignedInt64), + ) + case wasm.OpcodeI64Popcnt: + c.emit( + newOperationPopcnt(unsignedInt64), + ) + case wasm.OpcodeI64Add: + c.emit( + newOperationAdd(unsignedTypeI64), + ) + case wasm.OpcodeI64Sub: + c.emit( + newOperationSub(unsignedTypeI64), + ) + case wasm.OpcodeI64Mul: + c.emit( + newOperationMul(unsignedTypeI64), + ) + case wasm.OpcodeI64DivS: + c.emit( + newOperationDiv(signedTypeInt64), + ) + case wasm.OpcodeI64DivU: + c.emit( + newOperationDiv(signedTypeUint64), + ) + case wasm.OpcodeI64RemS: + c.emit( + newOperationRem(signedInt64), + ) + case wasm.OpcodeI64RemU: + c.emit( + newOperationRem(signedUint64), + ) + case wasm.OpcodeI64And: + c.emit( + newOperationAnd(unsignedInt64), + ) + case wasm.OpcodeI64Or: + c.emit( + newOperationOr(unsignedInt64), + ) + case wasm.OpcodeI64Xor: + c.emit( + newOperationXor(unsignedInt64), + ) + case wasm.OpcodeI64Shl: + c.emit( + newOperationShl(unsignedInt64), + ) + case wasm.OpcodeI64ShrS: + c.emit( + newOperationShr(signedInt64), + ) + case wasm.OpcodeI64ShrU: + c.emit( + newOperationShr(signedUint64), + ) + case wasm.OpcodeI64Rotl: + c.emit( + newOperationRotl(unsignedInt64), + ) + case wasm.OpcodeI64Rotr: + c.emit( + newOperationRotr(unsignedInt64), + ) + case wasm.OpcodeF32Abs: + c.emit( + newOperationAbs(f32), + ) + case wasm.OpcodeF32Neg: + c.emit( + newOperationNeg(f32), + ) + case wasm.OpcodeF32Ceil: + c.emit( + newOperationCeil(f32), + ) + case wasm.OpcodeF32Floor: + c.emit( + newOperationFloor(f32), + ) + case wasm.OpcodeF32Trunc: + c.emit( + newOperationTrunc(f32), + ) + case wasm.OpcodeF32Nearest: + c.emit( + newOperationNearest(f32), + ) + case wasm.OpcodeF32Sqrt: + c.emit( + newOperationSqrt(f32), + ) + case wasm.OpcodeF32Add: + c.emit( + newOperationAdd(unsignedTypeF32), + ) + case wasm.OpcodeF32Sub: + c.emit( + newOperationSub(unsignedTypeF32), + ) + case wasm.OpcodeF32Mul: + c.emit( + newOperationMul(unsignedTypeF32), + ) + case wasm.OpcodeF32Div: + c.emit( + newOperationDiv(signedTypeFloat32), + ) + case wasm.OpcodeF32Min: + c.emit( + newOperationMin(f32), + ) + case wasm.OpcodeF32Max: + c.emit( + newOperationMax(f32), + ) + case wasm.OpcodeF32Copysign: + c.emit( + newOperationCopysign(f32), + ) + case wasm.OpcodeF64Abs: + c.emit( + newOperationAbs(f64), + ) + case wasm.OpcodeF64Neg: + c.emit( + newOperationNeg(f64), + ) + case wasm.OpcodeF64Ceil: + c.emit( + newOperationCeil(f64), + ) + case wasm.OpcodeF64Floor: + c.emit( + newOperationFloor(f64), + ) + case wasm.OpcodeF64Trunc: + c.emit( + newOperationTrunc(f64), + ) + case wasm.OpcodeF64Nearest: + c.emit( + newOperationNearest(f64), + ) + case wasm.OpcodeF64Sqrt: + c.emit( + newOperationSqrt(f64), + ) + case wasm.OpcodeF64Add: + c.emit( + newOperationAdd(unsignedTypeF64), + ) + case wasm.OpcodeF64Sub: + c.emit( + newOperationSub(unsignedTypeF64), + ) + case wasm.OpcodeF64Mul: + c.emit( + newOperationMul(unsignedTypeF64), + ) + case wasm.OpcodeF64Div: + c.emit( + newOperationDiv(signedTypeFloat64), + ) + case wasm.OpcodeF64Min: + c.emit( + newOperationMin(f64), + ) + case wasm.OpcodeF64Max: + c.emit( + newOperationMax(f64), + ) + case wasm.OpcodeF64Copysign: + c.emit( + newOperationCopysign(f64), + ) + case wasm.OpcodeI32WrapI64: + c.emit( + newOperationI32WrapFromI64(), + ) + case wasm.OpcodeI32TruncF32S: + c.emit( + newOperationITruncFromF(f32, signedInt32, false), + ) + case wasm.OpcodeI32TruncF32U: + c.emit( + newOperationITruncFromF(f32, signedUint32, false), + ) + case wasm.OpcodeI32TruncF64S: + c.emit( + newOperationITruncFromF(f64, signedInt32, false), + ) + case wasm.OpcodeI32TruncF64U: + c.emit( + newOperationITruncFromF(f64, signedUint32, false), + ) + case wasm.OpcodeI64ExtendI32S: + c.emit( + newOperationExtend(true), + ) + case wasm.OpcodeI64ExtendI32U: + c.emit( + newOperationExtend(false), + ) + case wasm.OpcodeI64TruncF32S: + c.emit( + newOperationITruncFromF(f32, signedInt64, false), + ) + case wasm.OpcodeI64TruncF32U: + c.emit( + newOperationITruncFromF(f32, signedUint64, false), + ) + case wasm.OpcodeI64TruncF64S: + c.emit( + newOperationITruncFromF(f64, signedInt64, false), + ) + case wasm.OpcodeI64TruncF64U: + c.emit( + newOperationITruncFromF(f64, signedUint64, false), + ) + case wasm.OpcodeF32ConvertI32S: + c.emit( + newOperationFConvertFromI(signedInt32, f32), + ) + case wasm.OpcodeF32ConvertI32U: + c.emit( + newOperationFConvertFromI(signedUint32, f32), + ) + case wasm.OpcodeF32ConvertI64S: + c.emit( + newOperationFConvertFromI(signedInt64, f32), + ) + case wasm.OpcodeF32ConvertI64U: + c.emit( + newOperationFConvertFromI(signedUint64, f32), + ) + case wasm.OpcodeF32DemoteF64: + c.emit( + newOperationF32DemoteFromF64(), + ) + case wasm.OpcodeF64ConvertI32S: + c.emit( + newOperationFConvertFromI(signedInt32, f64), + ) + case wasm.OpcodeF64ConvertI32U: + c.emit( + newOperationFConvertFromI(signedUint32, f64), + ) + case wasm.OpcodeF64ConvertI64S: + c.emit( + newOperationFConvertFromI(signedInt64, f64), + ) + case wasm.OpcodeF64ConvertI64U: + c.emit( + newOperationFConvertFromI(signedUint64, f64), + ) + case wasm.OpcodeF64PromoteF32: + c.emit( + newOperationF64PromoteFromF32(), + ) + case wasm.OpcodeI32ReinterpretF32: + c.emit( + newOperationI32ReinterpretFromF32(), + ) + case wasm.OpcodeI64ReinterpretF64: + c.emit( + newOperationI64ReinterpretFromF64(), + ) + case wasm.OpcodeF32ReinterpretI32: + c.emit( + newOperationF32ReinterpretFromI32(), + ) + case wasm.OpcodeF64ReinterpretI64: + c.emit( + newOperationF64ReinterpretFromI64(), + ) + case wasm.OpcodeI32Extend8S: + c.emit( + newOperationSignExtend32From8(), + ) + case wasm.OpcodeI32Extend16S: + c.emit( + newOperationSignExtend32From16(), + ) + case wasm.OpcodeI64Extend8S: + c.emit( + newOperationSignExtend64From8(), + ) + case wasm.OpcodeI64Extend16S: + c.emit( + newOperationSignExtend64From16(), + ) + case wasm.OpcodeI64Extend32S: + c.emit( + newOperationSignExtend64From32(), + ) + case wasm.OpcodeRefFunc: + c.pc++ + index, num, err := leb128.LoadUint32(c.body[c.pc:]) + if err != nil { + return fmt.Errorf("failed to read function index for ref.func: %v", err) + } + c.pc += num - 1 + c.emit( + newOperationRefFunc(index), + ) + case wasm.OpcodeRefNull: + c.pc++ // Skip the type of reftype as every ref value is opaque pointer. + c.emit( + newOperationConstI64(0), + ) + case wasm.OpcodeRefIsNull: + // Simply compare the opaque pointer (i64) with zero. + c.emit( + newOperationEqz(unsignedInt64), + ) + case wasm.OpcodeTableGet: + c.pc++ + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:]) + if err != nil { + return fmt.Errorf("failed to read function index for table.get: %v", err) + } + c.pc += num - 1 + c.emit( + newOperationTableGet(tableIndex), + ) + case wasm.OpcodeTableSet: + c.pc++ + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc:]) + if err != nil { + return fmt.Errorf("failed to read function index for table.set: %v", err) + } + c.pc += num - 1 + c.emit( + newOperationTableSet(tableIndex), + ) + case wasm.OpcodeMiscPrefix: + c.pc++ + // A misc opcode is encoded as an unsigned variable 32-bit integer. + miscOp, num, err := leb128.LoadUint32(c.body[c.pc:]) + if err != nil { + return fmt.Errorf("failed to read misc opcode: %v", err) + } + c.pc += num - 1 + switch byte(miscOp) { + case wasm.OpcodeMiscI32TruncSatF32S: + c.emit( + newOperationITruncFromF(f32, signedInt32, true), + ) + case wasm.OpcodeMiscI32TruncSatF32U: + c.emit( + newOperationITruncFromF(f32, signedUint32, true), + ) + case wasm.OpcodeMiscI32TruncSatF64S: + c.emit( + newOperationITruncFromF(f64, signedInt32, true), + ) + case wasm.OpcodeMiscI32TruncSatF64U: + c.emit( + newOperationITruncFromF(f64, signedUint32, true), + ) + case wasm.OpcodeMiscI64TruncSatF32S: + c.emit( + newOperationITruncFromF(f32, signedInt64, true), + ) + case wasm.OpcodeMiscI64TruncSatF32U: + c.emit( + newOperationITruncFromF(f32, signedUint64, true), + ) + case wasm.OpcodeMiscI64TruncSatF64S: + c.emit( + newOperationITruncFromF(f64, signedInt64, true), + ) + case wasm.OpcodeMiscI64TruncSatF64U: + c.emit( + newOperationITruncFromF(f64, signedUint64, true), + ) + case wasm.OpcodeMiscMemoryInit: + c.result.UsesMemory = true + dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + 1 // +1 to skip the memory index which is fixed to zero. + c.emit( + newOperationMemoryInit(dataIndex), + ) + case wasm.OpcodeMiscDataDrop: + dataIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationDataDrop(dataIndex), + ) + case wasm.OpcodeMiscMemoryCopy: + c.result.UsesMemory = true + c.pc += 2 // +2 to skip two memory indexes which are fixed to zero. + c.emit( + newOperationMemoryCopy(), + ) + case wasm.OpcodeMiscMemoryFill: + c.result.UsesMemory = true + c.pc += 1 // +1 to skip the memory index which is fixed to zero. + c.emit( + newOperationMemoryFill(), + ) + case wasm.OpcodeMiscTableInit: + elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + // Read table index which is fixed to zero currently. + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationTableInit(elemIndex, tableIndex), + ) + case wasm.OpcodeMiscElemDrop: + elemIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationElemDrop(elemIndex), + ) + case wasm.OpcodeMiscTableCopy: + // Read the source table inde.g. + dst, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + // Read the destination table inde.g. + src, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationTableCopy(src, dst), + ) + case wasm.OpcodeMiscTableGrow: + // Read the source table inde.g. + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationTableGrow(tableIndex), + ) + case wasm.OpcodeMiscTableSize: + // Read the source table inde.g. + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationTableSize(tableIndex), + ) + case wasm.OpcodeMiscTableFill: + // Read the source table index. + tableIndex, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return fmt.Errorf("reading i32.const value: %v", err) + } + c.pc += num + c.emit( + newOperationTableFill(tableIndex), + ) + default: + return fmt.Errorf("unsupported misc instruction in interpreterir: 0x%x", op) + } + case wasm.OpcodeVecPrefix: + c.pc++ + switch vecOp := c.body[c.pc]; vecOp { + case wasm.OpcodeVecV128Const: + c.pc++ + lo := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8]) + c.pc += 8 + hi := binary.LittleEndian.Uint64(c.body[c.pc : c.pc+8]) + c.emit( + newOperationV128Const(lo, hi), + ) + c.pc += 7 + case wasm.OpcodeVecV128Load: + arg, err := c.readMemoryArg(wasm.OpcodeI32LoadName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType128, arg), + ) + case wasm.OpcodeVecV128Load8x8s: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8SName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType8x8s, arg), + ) + case wasm.OpcodeVecV128Load8x8u: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8x8UName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType8x8u, arg), + ) + case wasm.OpcodeVecV128Load16x4s: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4SName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType16x4s, arg), + ) + case wasm.OpcodeVecV128Load16x4u: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16x4UName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType16x4u, arg), + ) + case wasm.OpcodeVecV128Load32x2s: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2SName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType32x2s, arg), + ) + case wasm.OpcodeVecV128Load32x2u: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32x2UName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType32x2u, arg), + ) + case wasm.OpcodeVecV128Load8Splat: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8SplatName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType8Splat, arg), + ) + case wasm.OpcodeVecV128Load16Splat: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16SplatName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType16Splat, arg), + ) + case wasm.OpcodeVecV128Load32Splat: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32SplatName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType32Splat, arg), + ) + case wasm.OpcodeVecV128Load64Splat: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64SplatName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType64Splat, arg), + ) + case wasm.OpcodeVecV128Load32zero: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32zeroName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType32zero, arg), + ) + case wasm.OpcodeVecV128Load64zero: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64zeroName) + if err != nil { + return err + } + c.emit( + newOperationV128Load(v128LoadType64zero, arg), + ) + case wasm.OpcodeVecV128Load8Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load8LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128LoadLane(laneIndex, 8, arg), + ) + case wasm.OpcodeVecV128Load16Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load16LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128LoadLane(laneIndex, 16, arg), + ) + case wasm.OpcodeVecV128Load32Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load32LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128LoadLane(laneIndex, 32, arg), + ) + case wasm.OpcodeVecV128Load64Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Load64LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128LoadLane(laneIndex, 64, arg), + ) + case wasm.OpcodeVecV128Store: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128StoreName) + if err != nil { + return err + } + c.emit( + newOperationV128Store(arg), + ) + case wasm.OpcodeVecV128Store8Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store8LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128StoreLane(laneIndex, 8, arg), + ) + case wasm.OpcodeVecV128Store16Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store16LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128StoreLane(laneIndex, 16, arg), + ) + case wasm.OpcodeVecV128Store32Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store32LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128StoreLane(laneIndex, 32, arg), + ) + case wasm.OpcodeVecV128Store64Lane: + arg, err := c.readMemoryArg(wasm.OpcodeVecV128Store64LaneName) + if err != nil { + return err + } + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128StoreLane(laneIndex, 64, arg), + ) + case wasm.OpcodeVecI8x16ExtractLaneS: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, true, shapeI8x16), + ) + case wasm.OpcodeVecI8x16ExtractLaneU: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeI8x16), + ) + case wasm.OpcodeVecI16x8ExtractLaneS: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, true, shapeI16x8), + ) + case wasm.OpcodeVecI16x8ExtractLaneU: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeI16x8), + ) + case wasm.OpcodeVecI32x4ExtractLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeI32x4), + ) + case wasm.OpcodeVecI64x2ExtractLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeI64x2), + ) + case wasm.OpcodeVecF32x4ExtractLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeF32x4), + ) + case wasm.OpcodeVecF64x2ExtractLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ExtractLane(laneIndex, false, shapeF64x2), + ) + case wasm.OpcodeVecI8x16ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeI8x16), + ) + case wasm.OpcodeVecI16x8ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeI16x8), + ) + case wasm.OpcodeVecI32x4ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeI32x4), + ) + case wasm.OpcodeVecI64x2ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeI64x2), + ) + case wasm.OpcodeVecF32x4ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeF32x4), + ) + case wasm.OpcodeVecF64x2ReplaceLane: + c.pc++ + laneIndex := c.body[c.pc] + c.emit( + newOperationV128ReplaceLane(laneIndex, shapeF64x2), + ) + case wasm.OpcodeVecI8x16Splat: + c.emit( + newOperationV128Splat(shapeI8x16), + ) + case wasm.OpcodeVecI16x8Splat: + c.emit( + newOperationV128Splat(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Splat: + c.emit( + newOperationV128Splat(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Splat: + c.emit( + newOperationV128Splat(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Splat: + c.emit( + newOperationV128Splat(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Splat: + c.emit( + newOperationV128Splat(shapeF64x2), + ) + case wasm.OpcodeVecI8x16Swizzle: + c.emit( + newOperationV128Swizzle(), + ) + case wasm.OpcodeVecV128i8x16Shuffle: + c.pc++ + lanes := make([]uint64, 16) + for i := uint64(0); i < 16; i++ { + lanes[i] = uint64(c.body[c.pc+i]) + } + op := newOperationV128Shuffle(lanes) + c.emit(op) + c.pc += 15 + case wasm.OpcodeVecV128AnyTrue: + c.emit( + newOperationV128AnyTrue(), + ) + case wasm.OpcodeVecI8x16AllTrue: + c.emit( + newOperationV128AllTrue(shapeI8x16), + ) + case wasm.OpcodeVecI16x8AllTrue: + c.emit( + newOperationV128AllTrue(shapeI16x8), + ) + case wasm.OpcodeVecI32x4AllTrue: + c.emit( + newOperationV128AllTrue(shapeI32x4), + ) + case wasm.OpcodeVecI64x2AllTrue: + c.emit( + newOperationV128AllTrue(shapeI64x2), + ) + case wasm.OpcodeVecI8x16BitMask: + c.emit( + newOperationV128BitMask(shapeI8x16), + ) + case wasm.OpcodeVecI16x8BitMask: + c.emit( + newOperationV128BitMask(shapeI16x8), + ) + case wasm.OpcodeVecI32x4BitMask: + c.emit( + newOperationV128BitMask(shapeI32x4), + ) + case wasm.OpcodeVecI64x2BitMask: + c.emit( + newOperationV128BitMask(shapeI64x2), + ) + case wasm.OpcodeVecV128And: + c.emit( + newOperationV128And(), + ) + case wasm.OpcodeVecV128Not: + c.emit( + newOperationV128Not(), + ) + case wasm.OpcodeVecV128Or: + c.emit( + newOperationV128Or(), + ) + case wasm.OpcodeVecV128Xor: + c.emit( + newOperationV128Xor(), + ) + case wasm.OpcodeVecV128Bitselect: + c.emit( + newOperationV128Bitselect(), + ) + case wasm.OpcodeVecV128AndNot: + c.emit( + newOperationV128AndNot(), + ) + case wasm.OpcodeVecI8x16Shl: + c.emit( + newOperationV128Shl(shapeI8x16), + ) + case wasm.OpcodeVecI8x16ShrS: + c.emit( + newOperationV128Shr(shapeI8x16, true), + ) + case wasm.OpcodeVecI8x16ShrU: + c.emit( + newOperationV128Shr(shapeI8x16, false), + ) + case wasm.OpcodeVecI16x8Shl: + c.emit( + newOperationV128Shl(shapeI16x8), + ) + case wasm.OpcodeVecI16x8ShrS: + c.emit( + newOperationV128Shr(shapeI16x8, true), + ) + case wasm.OpcodeVecI16x8ShrU: + c.emit( + newOperationV128Shr(shapeI16x8, false), + ) + case wasm.OpcodeVecI32x4Shl: + c.emit( + newOperationV128Shl(shapeI32x4), + ) + case wasm.OpcodeVecI32x4ShrS: + c.emit( + newOperationV128Shr(shapeI32x4, true), + ) + case wasm.OpcodeVecI32x4ShrU: + c.emit( + newOperationV128Shr(shapeI32x4, false), + ) + case wasm.OpcodeVecI64x2Shl: + c.emit( + newOperationV128Shl(shapeI64x2), + ) + case wasm.OpcodeVecI64x2ShrS: + c.emit( + newOperationV128Shr(shapeI64x2, true), + ) + case wasm.OpcodeVecI64x2ShrU: + c.emit( + newOperationV128Shr(shapeI64x2, false), + ) + case wasm.OpcodeVecI8x16Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16Eq), + ) + case wasm.OpcodeVecI8x16Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16Ne), + ) + case wasm.OpcodeVecI8x16LtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16LtS), + ) + case wasm.OpcodeVecI8x16LtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16LtU), + ) + case wasm.OpcodeVecI8x16GtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16GtS), + ) + case wasm.OpcodeVecI8x16GtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16GtU), + ) + case wasm.OpcodeVecI8x16LeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16LeS), + ) + case wasm.OpcodeVecI8x16LeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16LeU), + ) + case wasm.OpcodeVecI8x16GeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16GeS), + ) + case wasm.OpcodeVecI8x16GeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI8x16GeU), + ) + case wasm.OpcodeVecI16x8Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8Eq), + ) + case wasm.OpcodeVecI16x8Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8Ne), + ) + case wasm.OpcodeVecI16x8LtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8LtS), + ) + case wasm.OpcodeVecI16x8LtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8LtU), + ) + case wasm.OpcodeVecI16x8GtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8GtS), + ) + case wasm.OpcodeVecI16x8GtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8GtU), + ) + case wasm.OpcodeVecI16x8LeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8LeS), + ) + case wasm.OpcodeVecI16x8LeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8LeU), + ) + case wasm.OpcodeVecI16x8GeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8GeS), + ) + case wasm.OpcodeVecI16x8GeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI16x8GeU), + ) + case wasm.OpcodeVecI32x4Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4Eq), + ) + case wasm.OpcodeVecI32x4Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4Ne), + ) + case wasm.OpcodeVecI32x4LtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4LtS), + ) + case wasm.OpcodeVecI32x4LtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4LtU), + ) + case wasm.OpcodeVecI32x4GtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4GtS), + ) + case wasm.OpcodeVecI32x4GtU: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4GtU), + ) + case wasm.OpcodeVecI32x4LeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4LeS), + ) + case wasm.OpcodeVecI32x4LeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4LeU), + ) + case wasm.OpcodeVecI32x4GeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4GeS), + ) + case wasm.OpcodeVecI32x4GeU: + c.emit( + newOperationV128Cmp(v128CmpTypeI32x4GeU), + ) + case wasm.OpcodeVecI64x2Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2Eq), + ) + case wasm.OpcodeVecI64x2Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2Ne), + ) + case wasm.OpcodeVecI64x2LtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2LtS), + ) + case wasm.OpcodeVecI64x2GtS: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2GtS), + ) + case wasm.OpcodeVecI64x2LeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2LeS), + ) + case wasm.OpcodeVecI64x2GeS: + c.emit( + newOperationV128Cmp(v128CmpTypeI64x2GeS), + ) + case wasm.OpcodeVecF32x4Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Eq), + ) + case wasm.OpcodeVecF32x4Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Ne), + ) + case wasm.OpcodeVecF32x4Lt: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Lt), + ) + case wasm.OpcodeVecF32x4Gt: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Gt), + ) + case wasm.OpcodeVecF32x4Le: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Le), + ) + case wasm.OpcodeVecF32x4Ge: + c.emit( + newOperationV128Cmp(v128CmpTypeF32x4Ge), + ) + case wasm.OpcodeVecF64x2Eq: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Eq), + ) + case wasm.OpcodeVecF64x2Ne: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Ne), + ) + case wasm.OpcodeVecF64x2Lt: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Lt), + ) + case wasm.OpcodeVecF64x2Gt: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Gt), + ) + case wasm.OpcodeVecF64x2Le: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Le), + ) + case wasm.OpcodeVecF64x2Ge: + c.emit( + newOperationV128Cmp(v128CmpTypeF64x2Ge), + ) + case wasm.OpcodeVecI8x16Neg: + c.emit( + newOperationV128Neg(shapeI8x16), + ) + case wasm.OpcodeVecI16x8Neg: + c.emit( + newOperationV128Neg(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Neg: + c.emit( + newOperationV128Neg(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Neg: + c.emit( + newOperationV128Neg(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Neg: + c.emit( + newOperationV128Neg(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Neg: + c.emit( + newOperationV128Neg(shapeF64x2), + ) + case wasm.OpcodeVecI8x16Add: + c.emit( + newOperationV128Add(shapeI8x16), + ) + case wasm.OpcodeVecI16x8Add: + c.emit( + newOperationV128Add(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Add: + c.emit( + newOperationV128Add(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Add: + c.emit( + newOperationV128Add(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Add: + c.emit( + newOperationV128Add(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Add: + c.emit( + newOperationV128Add(shapeF64x2), + ) + case wasm.OpcodeVecI8x16Sub: + c.emit( + newOperationV128Sub(shapeI8x16), + ) + case wasm.OpcodeVecI16x8Sub: + c.emit( + newOperationV128Sub(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Sub: + c.emit( + newOperationV128Sub(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Sub: + c.emit( + newOperationV128Sub(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Sub: + c.emit( + newOperationV128Sub(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Sub: + c.emit( + newOperationV128Sub(shapeF64x2), + ) + case wasm.OpcodeVecI8x16AddSatS: + c.emit( + newOperationV128AddSat(shapeI8x16, true), + ) + case wasm.OpcodeVecI8x16AddSatU: + c.emit( + newOperationV128AddSat(shapeI8x16, false), + ) + case wasm.OpcodeVecI16x8AddSatS: + c.emit( + newOperationV128AddSat(shapeI16x8, true), + ) + case wasm.OpcodeVecI16x8AddSatU: + c.emit( + newOperationV128AddSat(shapeI16x8, false), + ) + case wasm.OpcodeVecI8x16SubSatS: + c.emit( + newOperationV128SubSat(shapeI8x16, true), + ) + case wasm.OpcodeVecI8x16SubSatU: + c.emit( + newOperationV128SubSat(shapeI8x16, false), + ) + case wasm.OpcodeVecI16x8SubSatS: + c.emit( + newOperationV128SubSat(shapeI16x8, true), + ) + case wasm.OpcodeVecI16x8SubSatU: + c.emit( + newOperationV128SubSat(shapeI16x8, false), + ) + case wasm.OpcodeVecI16x8Mul: + c.emit( + newOperationV128Mul(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Mul: + c.emit( + newOperationV128Mul(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Mul: + c.emit( + newOperationV128Mul(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Mul: + c.emit( + newOperationV128Mul(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Mul: + c.emit( + newOperationV128Mul(shapeF64x2), + ) + case wasm.OpcodeVecF32x4Sqrt: + c.emit( + newOperationV128Sqrt(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Sqrt: + c.emit( + newOperationV128Sqrt(shapeF64x2), + ) + case wasm.OpcodeVecF32x4Div: + c.emit( + newOperationV128Div(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Div: + c.emit( + newOperationV128Div(shapeF64x2), + ) + case wasm.OpcodeVecI8x16Abs: + c.emit( + newOperationV128Abs(shapeI8x16), + ) + case wasm.OpcodeVecI8x16Popcnt: + c.emit( + newOperationV128Popcnt(shapeI8x16), + ) + case wasm.OpcodeVecI16x8Abs: + c.emit( + newOperationV128Abs(shapeI16x8), + ) + case wasm.OpcodeVecI32x4Abs: + c.emit( + newOperationV128Abs(shapeI32x4), + ) + case wasm.OpcodeVecI64x2Abs: + c.emit( + newOperationV128Abs(shapeI64x2), + ) + case wasm.OpcodeVecF32x4Abs: + c.emit( + newOperationV128Abs(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Abs: + c.emit( + newOperationV128Abs(shapeF64x2), + ) + case wasm.OpcodeVecI8x16MinS: + c.emit( + newOperationV128Min(shapeI8x16, true), + ) + case wasm.OpcodeVecI8x16MinU: + c.emit( + newOperationV128Min(shapeI8x16, false), + ) + case wasm.OpcodeVecI8x16MaxS: + c.emit( + newOperationV128Max(shapeI8x16, true), + ) + case wasm.OpcodeVecI8x16MaxU: + c.emit( + newOperationV128Max(shapeI8x16, false), + ) + case wasm.OpcodeVecI8x16AvgrU: + c.emit( + newOperationV128AvgrU(shapeI8x16), + ) + case wasm.OpcodeVecI16x8MinS: + c.emit( + newOperationV128Min(shapeI16x8, true), + ) + case wasm.OpcodeVecI16x8MinU: + c.emit( + newOperationV128Min(shapeI16x8, false), + ) + case wasm.OpcodeVecI16x8MaxS: + c.emit( + newOperationV128Max(shapeI16x8, true), + ) + case wasm.OpcodeVecI16x8MaxU: + c.emit( + newOperationV128Max(shapeI16x8, false), + ) + case wasm.OpcodeVecI16x8AvgrU: + c.emit( + newOperationV128AvgrU(shapeI16x8), + ) + case wasm.OpcodeVecI32x4MinS: + c.emit( + newOperationV128Min(shapeI32x4, true), + ) + case wasm.OpcodeVecI32x4MinU: + c.emit( + newOperationV128Min(shapeI32x4, false), + ) + case wasm.OpcodeVecI32x4MaxS: + c.emit( + newOperationV128Max(shapeI32x4, true), + ) + case wasm.OpcodeVecI32x4MaxU: + c.emit( + newOperationV128Max(shapeI32x4, false), + ) + case wasm.OpcodeVecF32x4Min: + c.emit( + newOperationV128Min(shapeF32x4, false), + ) + case wasm.OpcodeVecF32x4Max: + c.emit( + newOperationV128Max(shapeF32x4, false), + ) + case wasm.OpcodeVecF64x2Min: + c.emit( + newOperationV128Min(shapeF64x2, false), + ) + case wasm.OpcodeVecF64x2Max: + c.emit( + newOperationV128Max(shapeF64x2, false), + ) + case wasm.OpcodeVecF32x4Pmin: + c.emit( + newOperationV128Pmin(shapeF32x4), + ) + case wasm.OpcodeVecF32x4Pmax: + c.emit( + newOperationV128Pmax(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Pmin: + c.emit( + newOperationV128Pmin(shapeF64x2), + ) + case wasm.OpcodeVecF64x2Pmax: + c.emit( + newOperationV128Pmax(shapeF64x2), + ) + case wasm.OpcodeVecF32x4Ceil: + c.emit( + newOperationV128Ceil(shapeF32x4), + ) + case wasm.OpcodeVecF32x4Floor: + c.emit( + newOperationV128Floor(shapeF32x4), + ) + case wasm.OpcodeVecF32x4Trunc: + c.emit( + newOperationV128Trunc(shapeF32x4), + ) + case wasm.OpcodeVecF32x4Nearest: + c.emit( + newOperationV128Nearest(shapeF32x4), + ) + case wasm.OpcodeVecF64x2Ceil: + c.emit( + newOperationV128Ceil(shapeF64x2), + ) + case wasm.OpcodeVecF64x2Floor: + c.emit( + newOperationV128Floor(shapeF64x2), + ) + case wasm.OpcodeVecF64x2Trunc: + c.emit( + newOperationV128Trunc(shapeF64x2), + ) + case wasm.OpcodeVecF64x2Nearest: + c.emit( + newOperationV128Nearest(shapeF64x2), + ) + case wasm.OpcodeVecI16x8ExtendLowI8x16S: + c.emit( + newOperationV128Extend(shapeI8x16, true, true), + ) + case wasm.OpcodeVecI16x8ExtendHighI8x16S: + c.emit( + newOperationV128Extend(shapeI8x16, true, false), + ) + case wasm.OpcodeVecI16x8ExtendLowI8x16U: + c.emit( + newOperationV128Extend(shapeI8x16, false, true), + ) + case wasm.OpcodeVecI16x8ExtendHighI8x16U: + c.emit( + newOperationV128Extend(shapeI8x16, false, false), + ) + case wasm.OpcodeVecI32x4ExtendLowI16x8S: + c.emit( + newOperationV128Extend(shapeI16x8, true, true), + ) + case wasm.OpcodeVecI32x4ExtendHighI16x8S: + c.emit( + newOperationV128Extend(shapeI16x8, true, false), + ) + case wasm.OpcodeVecI32x4ExtendLowI16x8U: + c.emit( + newOperationV128Extend(shapeI16x8, false, true), + ) + case wasm.OpcodeVecI32x4ExtendHighI16x8U: + c.emit( + newOperationV128Extend(shapeI16x8, false, false), + ) + case wasm.OpcodeVecI64x2ExtendLowI32x4S: + c.emit( + newOperationV128Extend(shapeI32x4, true, true), + ) + case wasm.OpcodeVecI64x2ExtendHighI32x4S: + c.emit( + newOperationV128Extend(shapeI32x4, true, false), + ) + case wasm.OpcodeVecI64x2ExtendLowI32x4U: + c.emit( + newOperationV128Extend(shapeI32x4, false, true), + ) + case wasm.OpcodeVecI64x2ExtendHighI32x4U: + c.emit( + newOperationV128Extend(shapeI32x4, false, false), + ) + case wasm.OpcodeVecI16x8Q15mulrSatS: + c.emit( + newOperationV128Q15mulrSatS(), + ) + case wasm.OpcodeVecI16x8ExtMulLowI8x16S: + c.emit( + newOperationV128ExtMul(shapeI8x16, true, true), + ) + case wasm.OpcodeVecI16x8ExtMulHighI8x16S: + c.emit( + newOperationV128ExtMul(shapeI8x16, true, false), + ) + case wasm.OpcodeVecI16x8ExtMulLowI8x16U: + c.emit( + newOperationV128ExtMul(shapeI8x16, false, true), + ) + case wasm.OpcodeVecI16x8ExtMulHighI8x16U: + c.emit( + newOperationV128ExtMul(shapeI8x16, false, false), + ) + case wasm.OpcodeVecI32x4ExtMulLowI16x8S: + c.emit( + newOperationV128ExtMul(shapeI16x8, true, true), + ) + case wasm.OpcodeVecI32x4ExtMulHighI16x8S: + c.emit( + newOperationV128ExtMul(shapeI16x8, true, false), + ) + case wasm.OpcodeVecI32x4ExtMulLowI16x8U: + c.emit( + newOperationV128ExtMul(shapeI16x8, false, true), + ) + case wasm.OpcodeVecI32x4ExtMulHighI16x8U: + c.emit( + newOperationV128ExtMul(shapeI16x8, false, false), + ) + case wasm.OpcodeVecI64x2ExtMulLowI32x4S: + c.emit( + newOperationV128ExtMul(shapeI32x4, true, true), + ) + case wasm.OpcodeVecI64x2ExtMulHighI32x4S: + c.emit( + newOperationV128ExtMul(shapeI32x4, true, false), + ) + case wasm.OpcodeVecI64x2ExtMulLowI32x4U: + c.emit( + newOperationV128ExtMul(shapeI32x4, false, true), + ) + case wasm.OpcodeVecI64x2ExtMulHighI32x4U: + c.emit( + newOperationV128ExtMul(shapeI32x4, false, false), + ) + case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S: + c.emit( + newOperationV128ExtAddPairwise(shapeI8x16, true), + ) + case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U: + c.emit( + newOperationV128ExtAddPairwise(shapeI8x16, false), + ) + case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S: + c.emit( + newOperationV128ExtAddPairwise(shapeI16x8, true), + ) + case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U: + c.emit( + newOperationV128ExtAddPairwise(shapeI16x8, false), + ) + case wasm.OpcodeVecF64x2PromoteLowF32x4Zero: + c.emit( + newOperationV128FloatPromote(), + ) + case wasm.OpcodeVecF32x4DemoteF64x2Zero: + c.emit( + newOperationV128FloatDemote(), + ) + case wasm.OpcodeVecF32x4ConvertI32x4S: + c.emit( + newOperationV128FConvertFromI(shapeF32x4, true), + ) + case wasm.OpcodeVecF32x4ConvertI32x4U: + c.emit( + newOperationV128FConvertFromI(shapeF32x4, false), + ) + case wasm.OpcodeVecF64x2ConvertLowI32x4S: + c.emit( + newOperationV128FConvertFromI(shapeF64x2, true), + ) + case wasm.OpcodeVecF64x2ConvertLowI32x4U: + c.emit( + newOperationV128FConvertFromI(shapeF64x2, false), + ) + case wasm.OpcodeVecI32x4DotI16x8S: + c.emit( + newOperationV128Dot(), + ) + case wasm.OpcodeVecI8x16NarrowI16x8S: + c.emit( + newOperationV128Narrow(shapeI16x8, true), + ) + case wasm.OpcodeVecI8x16NarrowI16x8U: + c.emit( + newOperationV128Narrow(shapeI16x8, false), + ) + case wasm.OpcodeVecI16x8NarrowI32x4S: + c.emit( + newOperationV128Narrow(shapeI32x4, true), + ) + case wasm.OpcodeVecI16x8NarrowI32x4U: + c.emit( + newOperationV128Narrow(shapeI32x4, false), + ) + case wasm.OpcodeVecI32x4TruncSatF32x4S: + c.emit( + newOperationV128ITruncSatFromF(shapeF32x4, true), + ) + case wasm.OpcodeVecI32x4TruncSatF32x4U: + c.emit( + newOperationV128ITruncSatFromF(shapeF32x4, false), + ) + case wasm.OpcodeVecI32x4TruncSatF64x2SZero: + c.emit( + newOperationV128ITruncSatFromF(shapeF64x2, true), + ) + case wasm.OpcodeVecI32x4TruncSatF64x2UZero: + c.emit( + newOperationV128ITruncSatFromF(shapeF64x2, false), + ) + default: + return fmt.Errorf("unsupported vector instruction in interpreterir: %s", wasm.VectorInstructionName(vecOp)) + } + case wasm.OpcodeAtomicPrefix: + c.pc++ + atomicOp := c.body[c.pc] + switch atomicOp { + case wasm.OpcodeAtomicMemoryWait32: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait32Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicMemoryWait(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicMemoryWait64: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryWait64Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicMemoryWait(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicMemoryNotify: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicMemoryNotifyName) + if err != nil { + return err + } + c.emit( + newOperationAtomicMemoryNotify(imm), + ) + case wasm.OpcodeAtomicFence: + // Skip immediate value + c.pc++ + _ = c.body[c.pc] + c.emit( + newOperationAtomicFence(), + ) + case wasm.OpcodeAtomicI32Load: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32LoadName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64Load: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64LoadName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI32Load8U: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load8UName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad8(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI32Load16U: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Load16UName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad16(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64Load8U: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load8UName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad8(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Load16U: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load16UName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad16(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Load32U: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Load32UName) + if err != nil { + return err + } + c.emit( + newOperationAtomicLoad(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI32Store: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32StoreName) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI32Store8: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store8Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore8(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI32Store16: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Store16Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore16(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64Store: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64StoreName) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Store8: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store8Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore8(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Store16: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store16Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore16(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Store32: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Store32Name) + if err != nil { + return err + } + c.emit( + newOperationAtomicStore(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI32RmwAdd: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAddName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI64RmwAdd: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAddName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI32Rmw8AddU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AddUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI64Rmw8AddU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AddUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI32Rmw16AddU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AddUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI64Rmw16AddU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AddUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI64Rmw32AddU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AddUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAdd), + ) + case wasm.OpcodeAtomicI32RmwSub: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwSubName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI64RmwSub: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwSubName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI32Rmw8SubU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8SubUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI64Rmw8SubU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8SubUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI32Rmw16SubU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16SubUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI64Rmw16SubU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16SubUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI64Rmw32SubU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32SubUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpSub), + ) + case wasm.OpcodeAtomicI32RmwAnd: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwAndName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI64RmwAnd: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwAndName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI32Rmw8AndU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8AndUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI64Rmw8AndU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8AndUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI32Rmw16AndU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16AndUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI64Rmw16AndU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16AndUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI64Rmw32AndU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32AndUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpAnd), + ) + case wasm.OpcodeAtomicI32RmwOr: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwOrName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI64RmwOr: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwOrName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI32Rmw8OrU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8OrUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI64Rmw8OrU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8OrUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI32Rmw16OrU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16OrUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI64Rmw16OrU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16OrUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI64Rmw32OrU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32OrUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpOr), + ) + case wasm.OpcodeAtomicI32RmwXor: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXorName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI64RmwXor: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXorName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI32Rmw8XorU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XorUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI64Rmw8XorU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XorUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI32Rmw16XorU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XorUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI64Rmw16XorU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XorUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI64Rmw32XorU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XorUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpXor), + ) + case wasm.OpcodeAtomicI32RmwXchg: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwXchgName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI64RmwXchg: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwXchgName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI64, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI32Rmw8XchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8XchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI32, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI64Rmw8XchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8XchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8(unsignedTypeI64, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI32Rmw16XchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16XchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI32, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI64Rmw16XchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16XchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16(unsignedTypeI64, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI64Rmw32XchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32XchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW(unsignedTypeI32, imm, atomicArithmeticOpNop), + ) + case wasm.OpcodeAtomicI32RmwCmpxchg: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32RmwCmpxchgName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMWCmpxchg(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64RmwCmpxchg: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64RmwCmpxchgName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMWCmpxchg(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI32Rmw8CmpxchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw8CmpxchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8Cmpxchg(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64Rmw8CmpxchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw8CmpxchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW8Cmpxchg(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI32Rmw16CmpxchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI32Rmw16CmpxchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16Cmpxchg(unsignedTypeI32, imm), + ) + case wasm.OpcodeAtomicI64Rmw16CmpxchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw16CmpxchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMW16Cmpxchg(unsignedTypeI64, imm), + ) + case wasm.OpcodeAtomicI64Rmw32CmpxchgU: + imm, err := c.readMemoryArg(wasm.OpcodeAtomicI64Rmw32CmpxchgUName) + if err != nil { + return err + } + c.emit( + newOperationAtomicRMWCmpxchg(unsignedTypeI32, imm), + ) + default: + return fmt.Errorf("unsupported atomic instruction in interpreterir: %s", wasm.AtomicInstructionName(atomicOp)) + } + default: + return fmt.Errorf("unsupported instruction in interpreterir: 0x%x", op) + } + + // Move the program counter to point to the next instruction. + c.pc++ + return nil +} + +func (c *compiler) nextFrameID() (id uint32) { + id = c.currentFrameID + 1 + c.currentFrameID++ + return +} + +func (c *compiler) applyToStack(opcode wasm.Opcode) (index uint32, err error) { + switch opcode { + case + // These are the opcodes that is coupled with "index" immediate + // and it DOES affect the signature of opcode. + wasm.OpcodeCall, + wasm.OpcodeCallIndirect, + wasm.OpcodeLocalGet, + wasm.OpcodeLocalSet, + wasm.OpcodeLocalTee, + wasm.OpcodeGlobalGet, + wasm.OpcodeGlobalSet: + // Assumes that we are at the opcode now so skip it before read immediates. + v, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return 0, fmt.Errorf("reading immediates: %w", err) + } + c.pc += num + index = v + default: + // Note that other opcodes are free of index + // as it doesn't affect the signature of opt code. + // In other words, the "index" argument of wasmOpcodeSignature + // is ignored there. + } + + if c.unreachableState.on { + return 0, nil + } + + // Retrieve the signature of the opcode. + s, err := c.wasmOpcodeSignature(opcode, index) + if err != nil { + return 0, err + } + + // Manipulate the stack according to the signature. + // Note that the following algorithm assumes that + // the unknown type is unique in the signature, + // and is determined by the actual type on the stack. + // The determined type is stored in this typeParam. + var typeParam unsignedType + var typeParamFound bool + for i := range s.in { + want := s.in[len(s.in)-1-i] + actual := c.stackPop() + if want == unsignedTypeUnknown && typeParamFound { + want = typeParam + } else if want == unsignedTypeUnknown { + want = actual + typeParam = want + typeParamFound = true + } + if want != actual { + return 0, fmt.Errorf("input signature mismatch: want %s but have %s", want, actual) + } + } + + for _, target := range s.out { + if target == unsignedTypeUnknown && !typeParamFound { + return 0, fmt.Errorf("cannot determine type of unknown result") + } else if target == unsignedTypeUnknown { + c.stackPush(typeParam) + } else { + c.stackPush(target) + } + } + + return index, nil +} + +func (c *compiler) stackPeek() (ret unsignedType) { + ret = c.stack[len(c.stack)-1] + return +} + +func (c *compiler) stackSwitchAt(frame *controlFrame) { + c.stack = c.stack[:frame.originalStackLenWithoutParam] + c.stackLenInUint64 = frame.originalStackLenWithoutParamUint64 +} + +func (c *compiler) stackPop() (ret unsignedType) { + // No need to check stack bound + // as we can assume that all the operations + // are valid thanks to validateFunction + // at module validation phase. + ret = c.stack[len(c.stack)-1] + c.stack = c.stack[:len(c.stack)-1] + c.stackLenInUint64 -= 1 + int(unsignedTypeV128&ret>>2) + return +} + +func (c *compiler) stackPush(ts unsignedType) { + c.stack = append(c.stack, ts) + c.stackLenInUint64 += 1 + int(unsignedTypeV128&ts>>2) +} + +// emit adds the operations into the result. +func (c *compiler) emit(op unionOperation) { + if !c.unreachableState.on { + switch op.Kind { + case operationKindDrop: + // If the drop range is nil, + // we could remove such operations. + // That happens when drop operation is unnecessary. + // i.e. when there's no need to adjust stack before jmp. + if int64(op.U1) == -1 { + return + } + } + c.result.Operations = append(c.result.Operations, op) + if c.needSourceOffset { + c.result.IROperationSourceOffsetsInWasmBinary = append(c.result.IROperationSourceOffsetsInWasmBinary, + c.currentOpPC+c.bodyOffsetInCodeSection) + } + } +} + +// Emit const expression with default values of the given type. +func (c *compiler) emitDefaultValue(t wasm.ValueType) { + switch t { + case wasm.ValueTypeI32: + c.stackPush(unsignedTypeI32) + c.emit(newOperationConstI32(0)) + case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + c.stackPush(unsignedTypeI64) + c.emit(newOperationConstI64(0)) + case wasm.ValueTypeF32: + c.stackPush(unsignedTypeF32) + c.emit(newOperationConstF32(0)) + case wasm.ValueTypeF64: + c.stackPush(unsignedTypeF64) + c.emit(newOperationConstF64(0)) + case wasm.ValueTypeV128: + c.stackPush(unsignedTypeV128) + c.emit(newOperationV128Const(0, 0)) + } +} + +// Returns the "depth" (starting from top of the stack) +// of the n-th local. +func (c *compiler) localDepth(index wasm.Index) int { + height := c.localIndexToStackHeightInUint64[index] + return c.stackLenInUint64 - 1 - height +} + +func (c *compiler) localType(index wasm.Index) (t wasm.ValueType) { + if params := uint32(len(c.sig.Params)); index < params { + t = c.sig.Params[index] + } else { + t = c.localTypes[index-params] + } + return +} + +// getFrameDropRange returns the range (starting from top of the stack) that spans across the (uint64) stack. The range is +// supposed to be dropped from the stack when the given frame exists or branch into it. +// +// * frame is the control frame which the call-site is trying to branch into or exit. +// * isEnd true if the call-site is handling wasm.OpcodeEnd. +func (c *compiler) getFrameDropRange(frame *controlFrame, isEnd bool) inclusiveRange { + var start int + if !isEnd && frame.kind == controlFrameKindLoop { + // If this is not End and the call-site is trying to branch into the Loop control frame, + // we have to Start executing from the beginning of the loop block. + // Therefore, we have to pass the inputs to the frame. + start = frame.blockType.ParamNumInUint64 + } else { + start = frame.blockType.ResultNumInUint64 + } + end := c.stackLenInUint64 - 1 - frame.originalStackLenWithoutParamUint64 + if start <= end { + return inclusiveRange{Start: int32(start), End: int32(end)} + } else { + return nopinclusiveRange + } +} + +func (c *compiler) readMemoryArg(tag string) (memoryArg, error) { + c.result.UsesMemory = true + alignment, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return memoryArg{}, fmt.Errorf("reading alignment for %s: %w", tag, err) + } + c.pc += num + offset, num, err := leb128.LoadUint32(c.body[c.pc+1:]) + if err != nil { + return memoryArg{}, fmt.Errorf("reading offset for %s: %w", tag, err) + } + c.pc += num + return memoryArg{Offset: offset, Alignment: alignment}, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/format.go b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/format.go new file mode 100644 index 00000000..8af1d94b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/format.go @@ -0,0 +1,22 @@ +package interpreter + +import ( + "bytes" +) + +func format(ops []unionOperation) string { + buf := bytes.NewBuffer(nil) + + _, _ = buf.WriteString(".entrypoint\n") + for i := range ops { + op := &ops[i] + str := op.String() + isLabel := op.Kind == operationKindLabel + if !isLabel { + const indent = "\t" + str = indent + str + } + _, _ = buf.WriteString(str + "\n") + } + return buf.String() +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/interpreter.go b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/interpreter.go new file mode 100644 index 00000000..5b5e6e9d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/interpreter.go @@ -0,0 +1,4596 @@ +package interpreter + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "math" + "math/bits" + "sync" + "unsafe" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/expctxkeys" + "github.com/tetratelabs/wazero/internal/filecache" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/moremath" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasmdebug" + "github.com/tetratelabs/wazero/internal/wasmruntime" +) + +// callStackCeiling is the maximum WebAssembly call frame stack height. This allows wazero to raise +// wasm.ErrCallStackOverflow instead of overflowing the Go runtime. +// +// The default value should suffice for most use cases. Those wishing to change this can via `go build -ldflags`. +var callStackCeiling = 2000 + +// engine is an interpreter implementation of wasm.Engine +type engine struct { + enabledFeatures api.CoreFeatures + compiledFunctions map[wasm.ModuleID][]compiledFunction // guarded by mutex. + mux sync.RWMutex +} + +func NewEngine(_ context.Context, enabledFeatures api.CoreFeatures, _ filecache.Cache) wasm.Engine { + return &engine{ + enabledFeatures: enabledFeatures, + compiledFunctions: map[wasm.ModuleID][]compiledFunction{}, + } +} + +// Close implements the same method as documented on wasm.Engine. +func (e *engine) Close() (err error) { + return +} + +// CompiledModuleCount implements the same method as documented on wasm.Engine. +func (e *engine) CompiledModuleCount() uint32 { + return uint32(len(e.compiledFunctions)) +} + +// DeleteCompiledModule implements the same method as documented on wasm.Engine. +func (e *engine) DeleteCompiledModule(m *wasm.Module) { + e.deleteCompiledFunctions(m) +} + +func (e *engine) deleteCompiledFunctions(module *wasm.Module) { + e.mux.Lock() + defer e.mux.Unlock() + delete(e.compiledFunctions, module.ID) +} + +func (e *engine) addCompiledFunctions(module *wasm.Module, fs []compiledFunction) { + e.mux.Lock() + defer e.mux.Unlock() + e.compiledFunctions[module.ID] = fs +} + +func (e *engine) getCompiledFunctions(module *wasm.Module) (fs []compiledFunction, ok bool) { + e.mux.RLock() + defer e.mux.RUnlock() + fs, ok = e.compiledFunctions[module.ID] + return +} + +// moduleEngine implements wasm.ModuleEngine +type moduleEngine struct { + // codes are the compiled functions in a module instances. + // The index is module instance-scoped. + functions []function + + // parentEngine holds *engine from which this module engine is created from. + parentEngine *engine +} + +// GetGlobalValue implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) GetGlobalValue(wasm.Index) (lo, hi uint64) { + panic("BUG: GetGlobalValue should never be called on interpreter mode") +} + +// SetGlobalValue implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) SetGlobalValue(idx wasm.Index, lo, hi uint64) { + panic("BUG: SetGlobalValue should never be called on interpreter mode") +} + +// OwnsGlobals implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) OwnsGlobals() bool { return false } + +// MemoryGrown implements wasm.ModuleEngine. +func (e *moduleEngine) MemoryGrown() {} + +// callEngine holds context per moduleEngine.Call, and shared across all the +// function calls originating from the same moduleEngine.Call execution. +// +// This implements api.Function. +type callEngine struct { + internalapi.WazeroOnlyType + + // stack contains the operands. + // Note that all the values are represented as uint64. + stack []uint64 + + // frames are the function call stack. + frames []*callFrame + + // f is the initial function for this call engine. + f *function + + // stackiterator for Listeners to walk frames and stack. + stackIterator stackIterator +} + +func (e *moduleEngine) newCallEngine(compiled *function) *callEngine { + return &callEngine{f: compiled} +} + +func (ce *callEngine) pushValue(v uint64) { + ce.stack = append(ce.stack, v) +} + +func (ce *callEngine) pushValues(v []uint64) { + ce.stack = append(ce.stack, v...) +} + +func (ce *callEngine) popValue() (v uint64) { + // No need to check stack bound + // as we can assume that all the operations + // are valid thanks to validateFunction + // at module validation phase + // and interpreterir translation + // before compilation. + stackTopIndex := len(ce.stack) - 1 + v = ce.stack[stackTopIndex] + ce.stack = ce.stack[:stackTopIndex] + return +} + +func (ce *callEngine) popValues(v []uint64) { + stackTopIndex := len(ce.stack) - len(v) + copy(v, ce.stack[stackTopIndex:]) + ce.stack = ce.stack[:stackTopIndex] +} + +// peekValues peeks api.ValueType values from the stack and returns them. +func (ce *callEngine) peekValues(count int) []uint64 { + if count == 0 { + return nil + } + stackLen := len(ce.stack) + return ce.stack[stackLen-count : stackLen] +} + +func (ce *callEngine) drop(raw uint64) { + r := inclusiveRangeFromU64(raw) + if r.Start == -1 { + return + } else if r.Start == 0 { + ce.stack = ce.stack[:int32(len(ce.stack))-1-r.End] + } else { + newStack := ce.stack[:int32(len(ce.stack))-1-r.End] + newStack = append(newStack, ce.stack[int32(len(ce.stack))-r.Start:]...) + ce.stack = newStack + } +} + +func (ce *callEngine) pushFrame(frame *callFrame) { + if callStackCeiling <= len(ce.frames) { + panic(wasmruntime.ErrRuntimeStackOverflow) + } + ce.frames = append(ce.frames, frame) +} + +func (ce *callEngine) popFrame() (frame *callFrame) { + // No need to check stack bound as we can assume that all the operations are valid thanks to validateFunction at + // module validation phase and interpreterir translation before compilation. + oneLess := len(ce.frames) - 1 + frame = ce.frames[oneLess] + ce.frames = ce.frames[:oneLess] + return +} + +type callFrame struct { + // pc is the program counter representing the current position in code.body. + pc uint64 + // f is the compiled function used in this function frame. + f *function + // base index in the frame of this function, used to detect the count of + // values on the stack. + base int +} + +type compiledFunction struct { + source *wasm.Module + body []unionOperation + listener experimental.FunctionListener + offsetsInWasmBinary []uint64 + hostFn interface{} + ensureTermination bool + index wasm.Index +} + +type function struct { + funcType *wasm.FunctionType + moduleInstance *wasm.ModuleInstance + typeID wasm.FunctionTypeID + parent *compiledFunction +} + +// functionFromUintptr resurrects the original *function from the given uintptr +// which comes from either funcref table or OpcodeRefFunc instruction. +func functionFromUintptr(ptr uintptr) *function { + // Wraps ptrs as the double pointer in order to avoid the unsafe access as detected by race detector. + // + // For example, if we have (*function)(unsafe.Pointer(ptr)) instead, then the race detector's "checkptr" + // subroutine wanrs as "checkptr: pointer arithmetic result points to invalid allocation" + // https://github.com/golang/go/blob/1ce7fcf139417d618c2730010ede2afb41664211/src/runtime/checkptr.go#L69 + var wrapped *uintptr = &ptr + return *(**function)(unsafe.Pointer(wrapped)) +} + +type snapshot struct { + stack []uint64 + frames []*callFrame + pc uint64 + + ret []uint64 + + ce *callEngine +} + +// Snapshot implements the same method as documented on experimental.Snapshotter. +func (ce *callEngine) Snapshot() experimental.Snapshot { + stack := make([]uint64, len(ce.stack)) + copy(stack, ce.stack) + + frames := make([]*callFrame, len(ce.frames)) + copy(frames, ce.frames) + + return &snapshot{ + stack: stack, + frames: frames, + ce: ce, + } +} + +// Restore implements the same method as documented on experimental.Snapshot. +func (s *snapshot) Restore(ret []uint64) { + s.ret = ret + panic(s) +} + +func (s *snapshot) doRestore() { + ce := s.ce + + ce.stack = s.stack + ce.frames = s.frames + ce.frames[len(ce.frames)-1].pc = s.pc + + copy(ce.stack[len(ce.stack)-len(s.ret):], s.ret) +} + +// Error implements the same method on error. +func (s *snapshot) Error() string { + return "unhandled snapshot restore, this generally indicates restore was called from a different " + + "exported function invocation than snapshot" +} + +// stackIterator implements experimental.StackIterator. +type stackIterator struct { + stack []uint64 + frames []*callFrame + started bool + fn *function + pc uint64 +} + +func (si *stackIterator) reset(stack []uint64, frames []*callFrame, f *function) { + si.fn = f + si.pc = 0 + si.stack = stack + si.frames = frames + si.started = false +} + +func (si *stackIterator) clear() { + si.stack = nil + si.frames = nil + si.started = false + si.fn = nil +} + +// Next implements the same method as documented on experimental.StackIterator. +func (si *stackIterator) Next() bool { + if !si.started { + si.started = true + return true + } + + if len(si.frames) == 0 { + return false + } + + frame := si.frames[len(si.frames)-1] + si.stack = si.stack[:frame.base] + si.fn = frame.f + si.pc = frame.pc + si.frames = si.frames[:len(si.frames)-1] + return true +} + +// Function implements the same method as documented on +// experimental.StackIterator. +func (si *stackIterator) Function() experimental.InternalFunction { + return internalFunction{si.fn} +} + +// ProgramCounter implements the same method as documented on +// experimental.StackIterator. +func (si *stackIterator) ProgramCounter() experimental.ProgramCounter { + return experimental.ProgramCounter(si.pc) +} + +// internalFunction implements experimental.InternalFunction. +type internalFunction struct{ *function } + +// Definition implements the same method as documented on +// experimental.InternalFunction. +func (f internalFunction) Definition() api.FunctionDefinition { + return f.definition() +} + +// SourceOffsetForPC implements the same method as documented on +// experimental.InternalFunction. +func (f internalFunction) SourceOffsetForPC(pc experimental.ProgramCounter) uint64 { + offsetsMap := f.parent.offsetsInWasmBinary + if uint64(pc) < uint64(len(offsetsMap)) { + return offsetsMap[pc] + } + return 0 +} + +// interpreter mode doesn't maintain call frames in the stack, so pass the zero size to the IR. +const callFrameStackSize = 0 + +// CompileModule implements the same method as documented on wasm.Engine. +func (e *engine) CompileModule(_ context.Context, module *wasm.Module, listeners []experimental.FunctionListener, ensureTermination bool) error { + if _, ok := e.getCompiledFunctions(module); ok { // cache hit! + return nil + } + + funcs := make([]compiledFunction, len(module.FunctionSection)) + irCompiler, err := newCompiler(e.enabledFeatures, callFrameStackSize, module, ensureTermination) + if err != nil { + return err + } + imported := module.ImportFunctionCount + for i := range module.CodeSection { + var lsn experimental.FunctionListener + if i < len(listeners) { + lsn = listeners[i] + } + + compiled := &funcs[i] + // If this is the host function, there's nothing to do as the runtime representation of + // host function in interpreter is its Go function itself as opposed to Wasm functions, + // which need to be compiled down to + if codeSeg := &module.CodeSection[i]; codeSeg.GoFunc != nil { + compiled.hostFn = codeSeg.GoFunc + } else { + ir, err := irCompiler.Next() + if err != nil { + return err + } + err = e.lowerIR(ir, compiled) + if err != nil { + def := module.FunctionDefinition(uint32(i) + module.ImportFunctionCount) + return fmt.Errorf("failed to lower func[%s] to interpreterir: %w", def.DebugName(), err) + } + } + compiled.source = module + compiled.ensureTermination = ensureTermination + compiled.listener = lsn + compiled.index = imported + uint32(i) + } + e.addCompiledFunctions(module, funcs) + return nil +} + +// NewModuleEngine implements the same method as documented on wasm.Engine. +func (e *engine) NewModuleEngine(module *wasm.Module, instance *wasm.ModuleInstance) (wasm.ModuleEngine, error) { + me := &moduleEngine{ + parentEngine: e, + functions: make([]function, len(module.FunctionSection)+int(module.ImportFunctionCount)), + } + + codes, ok := e.getCompiledFunctions(module) + if !ok { + return nil, errors.New("source module must be compiled before instantiation") + } + + for i := range codes { + c := &codes[i] + offset := i + int(module.ImportFunctionCount) + typeIndex := module.FunctionSection[i] + me.functions[offset] = function{ + moduleInstance: instance, + typeID: instance.TypeIDs[typeIndex], + funcType: &module.TypeSection[typeIndex], + parent: c, + } + } + return me, nil +} + +// lowerIR lowers the interpreterir operations to engine friendly struct. +func (e *engine) lowerIR(ir *compilationResult, ret *compiledFunction) error { + // Copy the body from the result. + ret.body = make([]unionOperation, len(ir.Operations)) + copy(ret.body, ir.Operations) + // Also copy the offsets if necessary. + if offsets := ir.IROperationSourceOffsetsInWasmBinary; len(offsets) > 0 { + ret.offsetsInWasmBinary = make([]uint64, len(offsets)) + copy(ret.offsetsInWasmBinary, offsets) + } + + labelAddressResolutions := [labelKindNum][]uint64{} + + // First, we iterate all labels, and resolve the address. + for i := range ret.body { + op := &ret.body[i] + switch op.Kind { + case operationKindLabel: + label := label(op.U1) + address := uint64(i) + + kind, fid := label.Kind(), label.FrameID() + frameToAddresses := labelAddressResolutions[label.Kind()] + // Expand the slice if necessary. + if diff := fid - len(frameToAddresses) + 1; diff > 0 { + for j := 0; j < diff; j++ { + frameToAddresses = append(frameToAddresses, 0) + } + } + frameToAddresses[fid] = address + labelAddressResolutions[kind] = frameToAddresses + } + } + + // Then resolve the label as the index to the body. + for i := range ret.body { + op := &ret.body[i] + switch op.Kind { + case operationKindBr: + e.setLabelAddress(&op.U1, label(op.U1), labelAddressResolutions) + case operationKindBrIf: + e.setLabelAddress(&op.U1, label(op.U1), labelAddressResolutions) + e.setLabelAddress(&op.U2, label(op.U2), labelAddressResolutions) + case operationKindBrTable: + for j := 0; j < len(op.Us); j += 2 { + target := op.Us[j] + e.setLabelAddress(&op.Us[j], label(target), labelAddressResolutions) + } + } + } + return nil +} + +func (e *engine) setLabelAddress(op *uint64, label label, labelAddressResolutions [labelKindNum][]uint64) { + if label.IsReturnTarget() { + // Jmp to the end of the possible binary. + *op = math.MaxUint64 + } else { + *op = labelAddressResolutions[label.Kind()][label.FrameID()] + } +} + +// ResolveImportedFunction implements wasm.ModuleEngine. +func (e *moduleEngine) ResolveImportedFunction(index, descFunc, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) { + imported := importedModuleEngine.(*moduleEngine) + e.functions[index] = imported.functions[indexInImportedModule] +} + +// ResolveImportedMemory implements wasm.ModuleEngine. +func (e *moduleEngine) ResolveImportedMemory(wasm.ModuleEngine) {} + +// DoneInstantiation implements wasm.ModuleEngine. +func (e *moduleEngine) DoneInstantiation() {} + +// FunctionInstanceReference implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) FunctionInstanceReference(funcIndex wasm.Index) wasm.Reference { + return uintptr(unsafe.Pointer(&e.functions[funcIndex])) +} + +// NewFunction implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) NewFunction(index wasm.Index) (ce api.Function) { + // Note: The input parameters are pre-validated, so a compiled function is only absent on close. Updates to + // code on close aren't locked, neither is this read. + compiled := &e.functions[index] + return e.newCallEngine(compiled) +} + +// LookupFunction implements the same method as documented on wasm.ModuleEngine. +func (e *moduleEngine) LookupFunction(t *wasm.TableInstance, typeId wasm.FunctionTypeID, tableOffset wasm.Index) (*wasm.ModuleInstance, wasm.Index) { + if tableOffset >= uint32(len(t.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + rawPtr := t.References[tableOffset] + if rawPtr == 0 { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + + tf := functionFromUintptr(rawPtr) + if tf.typeID != typeId { + panic(wasmruntime.ErrRuntimeIndirectCallTypeMismatch) + } + return tf.moduleInstance, tf.parent.index +} + +// Definition implements the same method as documented on api.Function. +func (ce *callEngine) Definition() api.FunctionDefinition { + return ce.f.definition() +} + +func (f *function) definition() api.FunctionDefinition { + compiled := f.parent + return compiled.source.FunctionDefinition(compiled.index) +} + +// Call implements the same method as documented on api.Function. +func (ce *callEngine) Call(ctx context.Context, params ...uint64) (results []uint64, err error) { + ft := ce.f.funcType + if n := ft.ParamNumInUint64; n != len(params) { + return nil, fmt.Errorf("expected %d params, but passed %d", n, len(params)) + } + return ce.call(ctx, params, nil) +} + +// CallWithStack implements the same method as documented on api.Function. +func (ce *callEngine) CallWithStack(ctx context.Context, stack []uint64) error { + params, results, err := wasm.SplitCallStack(ce.f.funcType, stack) + if err != nil { + return err + } + _, err = ce.call(ctx, params, results) + return err +} + +func (ce *callEngine) call(ctx context.Context, params, results []uint64) (_ []uint64, err error) { + m := ce.f.moduleInstance + if ce.f.parent.ensureTermination { + select { + case <-ctx.Done(): + // If the provided context is already done, close the call context + // and return the error. + m.CloseWithCtxErr(ctx) + return nil, m.FailIfClosed() + default: + } + } + + if ctx.Value(expctxkeys.EnableSnapshotterKey{}) != nil { + ctx = context.WithValue(ctx, expctxkeys.SnapshotterKey{}, ce) + } + + defer func() { + // If the module closed during the call, and the call didn't err for another reason, set an ExitError. + if err == nil { + err = m.FailIfClosed() + } + // TODO: ^^ Will not fail if the function was imported from a closed module. + + if v := recover(); v != nil { + err = ce.recoverOnCall(ctx, m, v) + } + }() + + ce.pushValues(params) + + if ce.f.parent.ensureTermination { + done := m.CloseModuleOnCanceledOrTimeout(ctx) + defer done() + } + + ce.callFunction(ctx, m, ce.f) + + // This returns a safe copy of the results, instead of a slice view. If we + // returned a re-slice, the caller could accidentally or purposefully + // corrupt the stack of subsequent calls. + ft := ce.f.funcType + if results == nil && ft.ResultNumInUint64 > 0 { + results = make([]uint64, ft.ResultNumInUint64) + } + ce.popValues(results) + return results, nil +} + +// functionListenerInvocation captures arguments needed to perform function +// listener invocations when unwinding the call stack. +type functionListenerInvocation struct { + experimental.FunctionListener + def api.FunctionDefinition +} + +// recoverOnCall takes the recovered value `recoverOnCall`, and wraps it +// with the call frame stack traces. Also, reset the state of callEngine +// so that it can be used for the subsequent calls. +func (ce *callEngine) recoverOnCall(ctx context.Context, m *wasm.ModuleInstance, v interface{}) (err error) { + if s, ok := v.(*snapshot); ok { + // A snapshot that wasn't handled was created by a different call engine possibly from a nested wasm invocation, + // let it propagate up to be handled by the caller. + panic(s) + } + + builder := wasmdebug.NewErrorBuilder() + frameCount := len(ce.frames) + functionListeners := make([]functionListenerInvocation, 0, 16) + + if frameCount > wasmdebug.MaxFrames { + frameCount = wasmdebug.MaxFrames + } + for i := 0; i < frameCount; i++ { + frame := ce.popFrame() + f := frame.f + def := f.definition() + var sources []string + if parent := frame.f.parent; parent.body != nil && len(parent.offsetsInWasmBinary) > 0 { + sources = parent.source.DWARFLines.Line(parent.offsetsInWasmBinary[frame.pc]) + } + builder.AddFrame(def.DebugName(), def.ParamTypes(), def.ResultTypes(), sources) + if f.parent.listener != nil { + functionListeners = append(functionListeners, functionListenerInvocation{ + FunctionListener: f.parent.listener, + def: f.definition(), + }) + } + } + + err = builder.FromRecovered(v) + for i := range functionListeners { + functionListeners[i].Abort(ctx, m, functionListeners[i].def, err) + } + + // Allows the reuse of CallEngine. + ce.stack, ce.frames = ce.stack[:0], ce.frames[:0] + return +} + +func (ce *callEngine) callFunction(ctx context.Context, m *wasm.ModuleInstance, f *function) { + if f.parent.hostFn != nil { + ce.callGoFuncWithStack(ctx, m, f) + } else if lsn := f.parent.listener; lsn != nil { + ce.callNativeFuncWithListener(ctx, m, f, lsn) + } else { + ce.callNativeFunc(ctx, m, f) + } +} + +func (ce *callEngine) callGoFunc(ctx context.Context, m *wasm.ModuleInstance, f *function, stack []uint64) { + typ := f.funcType + lsn := f.parent.listener + if lsn != nil { + params := stack[:typ.ParamNumInUint64] + ce.stackIterator.reset(ce.stack, ce.frames, f) + lsn.Before(ctx, m, f.definition(), params, &ce.stackIterator) + ce.stackIterator.clear() + } + frame := &callFrame{f: f, base: len(ce.stack)} + ce.pushFrame(frame) + + fn := f.parent.hostFn + switch fn := fn.(type) { + case api.GoModuleFunction: + fn.Call(ctx, m, stack) + case api.GoFunction: + fn.Call(ctx, stack) + } + + ce.popFrame() + if lsn != nil { + // TODO: This doesn't get the error due to use of panic to propagate them. + results := stack[:typ.ResultNumInUint64] + lsn.After(ctx, m, f.definition(), results) + } +} + +func (ce *callEngine) callNativeFunc(ctx context.Context, m *wasm.ModuleInstance, f *function) { + frame := &callFrame{f: f, base: len(ce.stack)} + moduleInst := f.moduleInstance + functions := moduleInst.Engine.(*moduleEngine).functions + memoryInst := moduleInst.MemoryInstance + globals := moduleInst.Globals + tables := moduleInst.Tables + typeIDs := moduleInst.TypeIDs + dataInstances := moduleInst.DataInstances + elementInstances := moduleInst.ElementInstances + ce.pushFrame(frame) + body := frame.f.parent.body + bodyLen := uint64(len(body)) + for frame.pc < bodyLen { + op := &body[frame.pc] + // TODO: add description of each operation/case + // on, for example, how many args are used, + // how the stack is modified, etc. + switch op.Kind { + case operationKindBuiltinFunctionCheckExitCode: + if err := m.FailIfClosed(); err != nil { + panic(err) + } + frame.pc++ + case operationKindUnreachable: + panic(wasmruntime.ErrRuntimeUnreachable) + case operationKindBr: + frame.pc = op.U1 + case operationKindBrIf: + if ce.popValue() > 0 { + ce.drop(op.U3) + frame.pc = op.U1 + } else { + frame.pc = op.U2 + } + case operationKindBrTable: + v := ce.popValue() + defaultAt := uint64(len(op.Us))/2 - 1 + if v > defaultAt { + v = defaultAt + } + v *= 2 + ce.drop(op.Us[v+1]) + frame.pc = op.Us[v] + case operationKindCall: + func() { + if ctx.Value(expctxkeys.EnableSnapshotterKey{}) != nil { + defer func() { + if r := recover(); r != nil { + if s, ok := r.(*snapshot); ok && s.ce == ce { + s.doRestore() + frame = ce.frames[len(ce.frames)-1] + body = frame.f.parent.body + bodyLen = uint64(len(body)) + } else { + panic(r) + } + } + }() + } + ce.callFunction(ctx, f.moduleInstance, &functions[op.U1]) + }() + frame.pc++ + case operationKindCallIndirect: + offset := ce.popValue() + table := tables[op.U2] + if offset >= uint64(len(table.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + rawPtr := table.References[offset] + if rawPtr == 0 { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + + tf := functionFromUintptr(rawPtr) + if tf.typeID != typeIDs[op.U1] { + panic(wasmruntime.ErrRuntimeIndirectCallTypeMismatch) + } + + ce.callFunction(ctx, f.moduleInstance, tf) + frame.pc++ + case operationKindDrop: + ce.drop(op.U1) + frame.pc++ + case operationKindSelect: + c := ce.popValue() + if op.B3 { // Target is vector. + x2Hi, x2Lo := ce.popValue(), ce.popValue() + if c == 0 { + _, _ = ce.popValue(), ce.popValue() // discard the x1's lo and hi bits. + ce.pushValue(x2Lo) + ce.pushValue(x2Hi) + } + } else { + v2 := ce.popValue() + if c == 0 { + _ = ce.popValue() + ce.pushValue(v2) + } + } + frame.pc++ + case operationKindPick: + index := len(ce.stack) - 1 - int(op.U1) + ce.pushValue(ce.stack[index]) + if op.B3 { // V128 value target. + ce.pushValue(ce.stack[index+1]) + } + frame.pc++ + case operationKindSet: + if op.B3 { // V128 value target. + lowIndex := len(ce.stack) - 1 - int(op.U1) + highIndex := lowIndex + 1 + hi, lo := ce.popValue(), ce.popValue() + ce.stack[lowIndex], ce.stack[highIndex] = lo, hi + } else { + index := len(ce.stack) - 1 - int(op.U1) + ce.stack[index] = ce.popValue() + } + frame.pc++ + case operationKindGlobalGet: + g := globals[op.U1] + ce.pushValue(g.Val) + if g.Type.ValType == wasm.ValueTypeV128 { + ce.pushValue(g.ValHi) + } + frame.pc++ + case operationKindGlobalSet: + g := globals[op.U1] + if g.Type.ValType == wasm.ValueTypeV128 { + g.ValHi = ce.popValue() + } + g.Val = ce.popValue() + frame.pc++ + case operationKindLoad: + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32, unsignedTypeF32: + if val, ok := memoryInst.ReadUint32Le(offset); !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } else { + ce.pushValue(uint64(val)) + } + case unsignedTypeI64, unsignedTypeF64: + if val, ok := memoryInst.ReadUint64Le(offset); !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } else { + ce.pushValue(val) + } + } + frame.pc++ + case operationKindLoad8: + val, ok := memoryInst.ReadByte(ce.popMemoryOffset(op)) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + + switch signedInt(op.B1) { + case signedInt32: + ce.pushValue(uint64(uint32(int8(val)))) + case signedInt64: + ce.pushValue(uint64(int8(val))) + case signedUint32, signedUint64: + ce.pushValue(uint64(val)) + } + frame.pc++ + case operationKindLoad16: + + val, ok := memoryInst.ReadUint16Le(ce.popMemoryOffset(op)) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + + switch signedInt(op.B1) { + case signedInt32: + ce.pushValue(uint64(uint32(int16(val)))) + case signedInt64: + ce.pushValue(uint64(int16(val))) + case signedUint32, signedUint64: + ce.pushValue(uint64(val)) + } + frame.pc++ + case operationKindLoad32: + val, ok := memoryInst.ReadUint32Le(ce.popMemoryOffset(op)) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + + if op.B1 == 1 { // Signed + ce.pushValue(uint64(int32(val))) + } else { + ce.pushValue(uint64(val)) + } + frame.pc++ + case operationKindStore: + val := ce.popValue() + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32, unsignedTypeF32: + if !memoryInst.WriteUint32Le(offset, uint32(val)) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + case unsignedTypeI64, unsignedTypeF64: + if !memoryInst.WriteUint64Le(offset, val) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + } + frame.pc++ + case operationKindStore8: + val := byte(ce.popValue()) + offset := ce.popMemoryOffset(op) + if !memoryInst.WriteByte(offset, val) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindStore16: + val := uint16(ce.popValue()) + offset := ce.popMemoryOffset(op) + if !memoryInst.WriteUint16Le(offset, val) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindStore32: + val := uint32(ce.popValue()) + offset := ce.popMemoryOffset(op) + if !memoryInst.WriteUint32Le(offset, val) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindMemorySize: + ce.pushValue(uint64(memoryInst.Pages())) + frame.pc++ + case operationKindMemoryGrow: + n := ce.popValue() + if res, ok := memoryInst.Grow(uint32(n)); !ok { + ce.pushValue(uint64(0xffffffff)) // = -1 in signed 32-bit integer. + } else { + ce.pushValue(uint64(res)) + } + frame.pc++ + case operationKindConstI32, operationKindConstI64, + operationKindConstF32, operationKindConstF64: + ce.pushValue(op.U1) + frame.pc++ + case operationKindEq: + var b bool + switch unsignedType(op.B1) { + case unsignedTypeI32: + v2, v1 := ce.popValue(), ce.popValue() + b = uint32(v1) == uint32(v2) + case unsignedTypeI64: + v2, v1 := ce.popValue(), ce.popValue() + b = v1 == v2 + case unsignedTypeF32: + v2, v1 := ce.popValue(), ce.popValue() + b = math.Float32frombits(uint32(v2)) == math.Float32frombits(uint32(v1)) + case unsignedTypeF64: + v2, v1 := ce.popValue(), ce.popValue() + b = math.Float64frombits(v2) == math.Float64frombits(v1) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindNe: + var b bool + switch unsignedType(op.B1) { + case unsignedTypeI32, unsignedTypeI64: + v2, v1 := ce.popValue(), ce.popValue() + b = v1 != v2 + case unsignedTypeF32: + v2, v1 := ce.popValue(), ce.popValue() + b = math.Float32frombits(uint32(v2)) != math.Float32frombits(uint32(v1)) + case unsignedTypeF64: + v2, v1 := ce.popValue(), ce.popValue() + b = math.Float64frombits(v2) != math.Float64frombits(v1) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindEqz: + if ce.popValue() == 0 { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindLt: + v2 := ce.popValue() + v1 := ce.popValue() + var b bool + switch signedType(op.B1) { + case signedTypeInt32: + b = int32(v1) < int32(v2) + case signedTypeInt64: + b = int64(v1) < int64(v2) + case signedTypeUint32, signedTypeUint64: + b = v1 < v2 + case signedTypeFloat32: + b = math.Float32frombits(uint32(v1)) < math.Float32frombits(uint32(v2)) + case signedTypeFloat64: + b = math.Float64frombits(v1) < math.Float64frombits(v2) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindGt: + v2 := ce.popValue() + v1 := ce.popValue() + var b bool + switch signedType(op.B1) { + case signedTypeInt32: + b = int32(v1) > int32(v2) + case signedTypeInt64: + b = int64(v1) > int64(v2) + case signedTypeUint32, signedTypeUint64: + b = v1 > v2 + case signedTypeFloat32: + b = math.Float32frombits(uint32(v1)) > math.Float32frombits(uint32(v2)) + case signedTypeFloat64: + b = math.Float64frombits(v1) > math.Float64frombits(v2) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindLe: + v2 := ce.popValue() + v1 := ce.popValue() + var b bool + switch signedType(op.B1) { + case signedTypeInt32: + b = int32(v1) <= int32(v2) + case signedTypeInt64: + b = int64(v1) <= int64(v2) + case signedTypeUint32, signedTypeUint64: + b = v1 <= v2 + case signedTypeFloat32: + b = math.Float32frombits(uint32(v1)) <= math.Float32frombits(uint32(v2)) + case signedTypeFloat64: + b = math.Float64frombits(v1) <= math.Float64frombits(v2) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindGe: + v2 := ce.popValue() + v1 := ce.popValue() + var b bool + switch signedType(op.B1) { + case signedTypeInt32: + b = int32(v1) >= int32(v2) + case signedTypeInt64: + b = int64(v1) >= int64(v2) + case signedTypeUint32, signedTypeUint64: + b = v1 >= v2 + case signedTypeFloat32: + b = math.Float32frombits(uint32(v1)) >= math.Float32frombits(uint32(v2)) + case signedTypeFloat64: + b = math.Float64frombits(v1) >= math.Float64frombits(v2) + } + if b { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindAdd: + v2 := ce.popValue() + v1 := ce.popValue() + switch unsignedType(op.B1) { + case unsignedTypeI32: + v := uint32(v1) + uint32(v2) + ce.pushValue(uint64(v)) + case unsignedTypeI64: + ce.pushValue(v1 + v2) + case unsignedTypeF32: + ce.pushValue(addFloat32bits(uint32(v1), uint32(v2))) + case unsignedTypeF64: + v := math.Float64frombits(v1) + math.Float64frombits(v2) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindSub: + v2 := ce.popValue() + v1 := ce.popValue() + switch unsignedType(op.B1) { + case unsignedTypeI32: + ce.pushValue(uint64(uint32(v1) - uint32(v2))) + case unsignedTypeI64: + ce.pushValue(v1 - v2) + case unsignedTypeF32: + ce.pushValue(subFloat32bits(uint32(v1), uint32(v2))) + case unsignedTypeF64: + v := math.Float64frombits(v1) - math.Float64frombits(v2) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindMul: + v2 := ce.popValue() + v1 := ce.popValue() + switch unsignedType(op.B1) { + case unsignedTypeI32: + ce.pushValue(uint64(uint32(v1) * uint32(v2))) + case unsignedTypeI64: + ce.pushValue(v1 * v2) + case unsignedTypeF32: + ce.pushValue(mulFloat32bits(uint32(v1), uint32(v2))) + case unsignedTypeF64: + v := math.Float64frombits(v2) * math.Float64frombits(v1) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindClz: + v := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(bits.LeadingZeros32(uint32(v)))) + } else { + // unsignedInt64 + ce.pushValue(uint64(bits.LeadingZeros64(v))) + } + frame.pc++ + case operationKindCtz: + v := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(bits.TrailingZeros32(uint32(v)))) + } else { + // unsignedInt64 + ce.pushValue(uint64(bits.TrailingZeros64(v))) + } + frame.pc++ + case operationKindPopcnt: + v := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(bits.OnesCount32(uint32(v)))) + } else { + // unsignedInt64 + ce.pushValue(uint64(bits.OnesCount64(v))) + } + frame.pc++ + case operationKindDiv: + // If an integer, check we won't divide by zero. + t := signedType(op.B1) + v2, v1 := ce.popValue(), ce.popValue() + switch t { + case signedTypeFloat32, signedTypeFloat64: // not integers + default: + if v2 == 0 { + panic(wasmruntime.ErrRuntimeIntegerDivideByZero) + } + } + + switch t { + case signedTypeInt32: + d := int32(v2) + n := int32(v1) + if n == math.MinInt32 && d == -1 { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + ce.pushValue(uint64(uint32(n / d))) + case signedTypeInt64: + d := int64(v2) + n := int64(v1) + if n == math.MinInt64 && d == -1 { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + ce.pushValue(uint64(n / d)) + case signedTypeUint32: + d := uint32(v2) + n := uint32(v1) + ce.pushValue(uint64(n / d)) + case signedTypeUint64: + d := v2 + n := v1 + ce.pushValue(n / d) + case signedTypeFloat32: + ce.pushValue(divFloat32bits(uint32(v1), uint32(v2))) + case signedTypeFloat64: + ce.pushValue(math.Float64bits(math.Float64frombits(v1) / math.Float64frombits(v2))) + } + frame.pc++ + case operationKindRem: + v2, v1 := ce.popValue(), ce.popValue() + if v2 == 0 { + panic(wasmruntime.ErrRuntimeIntegerDivideByZero) + } + switch signedInt(op.B1) { + case signedInt32: + d := int32(v2) + n := int32(v1) + ce.pushValue(uint64(uint32(n % d))) + case signedInt64: + d := int64(v2) + n := int64(v1) + ce.pushValue(uint64(n % d)) + case signedUint32: + d := uint32(v2) + n := uint32(v1) + ce.pushValue(uint64(n % d)) + case signedUint64: + d := v2 + n := v1 + ce.pushValue(n % d) + } + frame.pc++ + case operationKindAnd: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(uint32(v2) & uint32(v1))) + } else { + // unsignedInt64 + ce.pushValue(uint64(v2 & v1)) + } + frame.pc++ + case operationKindOr: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(uint32(v2) | uint32(v1))) + } else { + // unsignedInt64 + ce.pushValue(uint64(v2 | v1)) + } + frame.pc++ + case operationKindXor: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(uint32(v2) ^ uint32(v1))) + } else { + // unsignedInt64 + ce.pushValue(uint64(v2 ^ v1)) + } + frame.pc++ + case operationKindShl: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(uint32(v1) << (uint32(v2) % 32))) + } else { + // unsignedInt64 + ce.pushValue(v1 << (v2 % 64)) + } + frame.pc++ + case operationKindShr: + v2 := ce.popValue() + v1 := ce.popValue() + switch signedInt(op.B1) { + case signedInt32: + ce.pushValue(uint64(uint32(int32(v1) >> (uint32(v2) % 32)))) + case signedInt64: + ce.pushValue(uint64(int64(v1) >> (v2 % 64))) + case signedUint32: + ce.pushValue(uint64(uint32(v1) >> (uint32(v2) % 32))) + case signedUint64: + ce.pushValue(v1 >> (v2 % 64)) + } + frame.pc++ + case operationKindRotl: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(bits.RotateLeft32(uint32(v1), int(v2)))) + } else { + // unsignedInt64 + ce.pushValue(uint64(bits.RotateLeft64(v1, int(v2)))) + } + frame.pc++ + case operationKindRotr: + v2 := ce.popValue() + v1 := ce.popValue() + if op.B1 == 0 { + // unsignedInt32 + ce.pushValue(uint64(bits.RotateLeft32(uint32(v1), -int(v2)))) + } else { + // unsignedInt64 + ce.pushValue(uint64(bits.RotateLeft64(v1, -int(v2)))) + } + frame.pc++ + case operationKindAbs: + if op.B1 == 0 { + // float32 + const mask uint32 = 1 << 31 + ce.pushValue(uint64(uint32(ce.popValue()) &^ mask)) + } else { + // float64 + const mask uint64 = 1 << 63 + ce.pushValue(ce.popValue() &^ mask) + } + frame.pc++ + case operationKindNeg: + if op.B1 == 0 { + // float32 + v := -math.Float32frombits(uint32(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := -math.Float64frombits(ce.popValue()) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindCeil: + if op.B1 == 0 { + // float32 + v := moremath.WasmCompatCeilF32(math.Float32frombits(uint32(ce.popValue()))) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := moremath.WasmCompatCeilF64(math.Float64frombits(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindFloor: + if op.B1 == 0 { + // float32 + v := moremath.WasmCompatFloorF32(math.Float32frombits(uint32(ce.popValue()))) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := moremath.WasmCompatFloorF64(math.Float64frombits(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindTrunc: + if op.B1 == 0 { + // float32 + v := moremath.WasmCompatTruncF32(math.Float32frombits(uint32(ce.popValue()))) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := moremath.WasmCompatTruncF64(math.Float64frombits(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindNearest: + if op.B1 == 0 { + // float32 + f := math.Float32frombits(uint32(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(moremath.WasmCompatNearestF32(f)))) + } else { + // float64 + f := math.Float64frombits(ce.popValue()) + ce.pushValue(math.Float64bits(moremath.WasmCompatNearestF64(f))) + } + frame.pc++ + case operationKindSqrt: + if op.B1 == 0 { + // float32 + v := math.Sqrt(float64(math.Float32frombits(uint32(ce.popValue())))) + ce.pushValue(uint64(math.Float32bits(float32(v)))) + } else { + // float64 + v := math.Sqrt(math.Float64frombits(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + frame.pc++ + case operationKindMin: + if op.B1 == 0 { + // float32 + ce.pushValue(wasmCompatMin32bits(uint32(ce.popValue()), uint32(ce.popValue()))) + } else { + v2 := math.Float64frombits(ce.popValue()) + v1 := math.Float64frombits(ce.popValue()) + ce.pushValue(math.Float64bits(moremath.WasmCompatMin64(v1, v2))) + } + frame.pc++ + case operationKindMax: + if op.B1 == 0 { + ce.pushValue(wasmCompatMax32bits(uint32(ce.popValue()), uint32(ce.popValue()))) + } else { + // float64 + v2 := math.Float64frombits(ce.popValue()) + v1 := math.Float64frombits(ce.popValue()) + ce.pushValue(math.Float64bits(moremath.WasmCompatMax64(v1, v2))) + } + frame.pc++ + case operationKindCopysign: + if op.B1 == 0 { + // float32 + v2 := uint32(ce.popValue()) + v1 := uint32(ce.popValue()) + const signbit = 1 << 31 + ce.pushValue(uint64(v1&^signbit | v2&signbit)) + } else { + // float64 + v2 := ce.popValue() + v1 := ce.popValue() + const signbit = 1 << 63 + ce.pushValue(v1&^signbit | v2&signbit) + } + frame.pc++ + case operationKindI32WrapFromI64: + ce.pushValue(uint64(uint32(ce.popValue()))) + frame.pc++ + case operationKindITruncFromF: + if op.B1 == 0 { + // float32 + switch signedInt(op.B2) { + case signedInt32: + v := math.Trunc(float64(math.Float32frombits(uint32(ce.popValue())))) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + v = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < math.MinInt32 || v > math.MaxInt32 { + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing sources. + if v < 0 { + v = math.MinInt32 + } else { + v = math.MaxInt32 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(uint32(int32(v)))) + case signedInt64: + v := math.Trunc(float64(math.Float32frombits(uint32(ce.popValue())))) + res := int64(v) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + res = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < math.MinInt64 || v >= math.MaxInt64 { + // Note: math.MaxInt64 is rounded up to math.MaxInt64+1 in 64-bit float representation, + // and that's why we use '>=' not '>' to check overflow. + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing sources. + if v < 0 { + res = math.MinInt64 + } else { + res = math.MaxInt64 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(res)) + case signedUint32: + v := math.Trunc(float64(math.Float32frombits(uint32(ce.popValue())))) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + v = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < 0 || v > math.MaxUint32 { + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + v = 0 + } else { + v = math.MaxUint32 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(uint32(v))) + case signedUint64: + v := math.Trunc(float64(math.Float32frombits(uint32(ce.popValue())))) + res := uint64(v) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + res = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < 0 || v >= math.MaxUint64 { + // Note: math.MaxUint64 is rounded up to math.MaxUint64+1 in 64-bit float representation, + // and that's why we use '>=' not '>' to check overflow. + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + res = 0 + } else { + res = math.MaxUint64 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(res) + } + } else { + // float64 + switch signedInt(op.B2) { + case signedInt32: + v := math.Trunc(math.Float64frombits(ce.popValue())) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + v = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < math.MinInt32 || v > math.MaxInt32 { + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + v = math.MinInt32 + } else { + v = math.MaxInt32 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(uint32(int32(v)))) + case signedInt64: + v := math.Trunc(math.Float64frombits(ce.popValue())) + res := int64(v) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + res = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < math.MinInt64 || v >= math.MaxInt64 { + // Note: math.MaxInt64 is rounded up to math.MaxInt64+1 in 64-bit float representation, + // and that's why we use '>=' not '>' to check overflow. + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + res = math.MinInt64 + } else { + res = math.MaxInt64 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(res)) + case signedUint32: + v := math.Trunc(math.Float64frombits(ce.popValue())) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + v = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < 0 || v > math.MaxUint32 { + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + v = 0 + } else { + v = math.MaxUint32 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(uint64(uint32(v))) + case signedUint64: + v := math.Trunc(math.Float64frombits(ce.popValue())) + res := uint64(v) + if math.IsNaN(v) { // NaN cannot be compared with themselves, so we have to use IsNaN + if op.B3 { + // non-trapping conversion must cast nan to zero. + res = 0 + } else { + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + } + } else if v < 0 || v >= math.MaxUint64 { + // Note: math.MaxUint64 is rounded up to math.MaxUint64+1 in 64-bit float representation, + // and that's why we use '>=' not '>' to check overflow. + if op.B3 { + // non-trapping conversion must "saturate" the value for overflowing source. + if v < 0 { + res = 0 + } else { + res = math.MaxUint64 + } + } else { + panic(wasmruntime.ErrRuntimeIntegerOverflow) + } + } + ce.pushValue(res) + } + } + frame.pc++ + case operationKindFConvertFromI: + switch signedInt(op.B1) { + case signedInt32: + if op.B2 == 0 { + // float32 + v := float32(int32(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := float64(int32(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + case signedInt64: + if op.B2 == 0 { + // float32 + v := float32(int64(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := float64(int64(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + case signedUint32: + if op.B2 == 0 { + // float32 + v := float32(uint32(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := float64(uint32(ce.popValue())) + ce.pushValue(math.Float64bits(v)) + } + case signedUint64: + if op.B2 == 0 { + // float32 + v := float32(ce.popValue()) + ce.pushValue(uint64(math.Float32bits(v))) + } else { + // float64 + v := float64(ce.popValue()) + ce.pushValue(math.Float64bits(v)) + } + } + frame.pc++ + case operationKindF32DemoteFromF64: + v := float32(math.Float64frombits(ce.popValue())) + ce.pushValue(uint64(math.Float32bits(v))) + frame.pc++ + case operationKindF64PromoteFromF32: + v := float64(math.Float32frombits(uint32(ce.popValue()))) + ce.pushValue(math.Float64bits(v)) + frame.pc++ + case operationKindExtend: + if op.B1 == 1 { + // Signed. + v := int64(int32(ce.popValue())) + ce.pushValue(uint64(v)) + } else { + v := uint64(uint32(ce.popValue())) + ce.pushValue(v) + } + frame.pc++ + case operationKindSignExtend32From8: + v := uint32(int8(ce.popValue())) + ce.pushValue(uint64(v)) + frame.pc++ + case operationKindSignExtend32From16: + v := uint32(int16(ce.popValue())) + ce.pushValue(uint64(v)) + frame.pc++ + case operationKindSignExtend64From8: + v := int64(int8(ce.popValue())) + ce.pushValue(uint64(v)) + frame.pc++ + case operationKindSignExtend64From16: + v := int64(int16(ce.popValue())) + ce.pushValue(uint64(v)) + frame.pc++ + case operationKindSignExtend64From32: + v := int64(int32(ce.popValue())) + ce.pushValue(uint64(v)) + frame.pc++ + case operationKindMemoryInit: + dataInstance := dataInstances[op.U1] + copySize := ce.popValue() + inDataOffset := ce.popValue() + inMemoryOffset := ce.popValue() + if inDataOffset+copySize > uint64(len(dataInstance)) || + inMemoryOffset+copySize > uint64(len(memoryInst.Buffer)) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } else if copySize != 0 { + copy(memoryInst.Buffer[inMemoryOffset:inMemoryOffset+copySize], dataInstance[inDataOffset:]) + } + frame.pc++ + case operationKindDataDrop: + dataInstances[op.U1] = nil + frame.pc++ + case operationKindMemoryCopy: + memLen := uint64(len(memoryInst.Buffer)) + copySize := ce.popValue() + sourceOffset := ce.popValue() + destinationOffset := ce.popValue() + if sourceOffset+copySize > memLen || destinationOffset+copySize > memLen { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } else if copySize != 0 { + copy(memoryInst.Buffer[destinationOffset:], + memoryInst.Buffer[sourceOffset:sourceOffset+copySize]) + } + frame.pc++ + case operationKindMemoryFill: + fillSize := ce.popValue() + value := byte(ce.popValue()) + offset := ce.popValue() + if fillSize+offset > uint64(len(memoryInst.Buffer)) { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } else if fillSize != 0 { + // Uses the copy trick for faster filling buffer. + // https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d + buf := memoryInst.Buffer[offset : offset+fillSize] + buf[0] = value + for i := 1; i < len(buf); i *= 2 { + copy(buf[i:], buf[:i]) + } + } + frame.pc++ + case operationKindTableInit: + elementInstance := elementInstances[op.U1] + copySize := ce.popValue() + inElementOffset := ce.popValue() + inTableOffset := ce.popValue() + table := tables[op.U2] + if inElementOffset+copySize > uint64(len(elementInstance)) || + inTableOffset+copySize > uint64(len(table.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } else if copySize != 0 { + copy(table.References[inTableOffset:inTableOffset+copySize], elementInstance[inElementOffset:]) + } + frame.pc++ + case operationKindElemDrop: + elementInstances[op.U1] = nil + frame.pc++ + case operationKindTableCopy: + srcTable, dstTable := tables[op.U1].References, tables[op.U2].References + copySize := ce.popValue() + sourceOffset := ce.popValue() + destinationOffset := ce.popValue() + if sourceOffset+copySize > uint64(len(srcTable)) || destinationOffset+copySize > uint64(len(dstTable)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } else if copySize != 0 { + copy(dstTable[destinationOffset:], srcTable[sourceOffset:sourceOffset+copySize]) + } + frame.pc++ + case operationKindRefFunc: + ce.pushValue(uint64(uintptr(unsafe.Pointer(&functions[op.U1])))) + frame.pc++ + case operationKindTableGet: + table := tables[op.U1] + + offset := ce.popValue() + if offset >= uint64(len(table.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + + ce.pushValue(uint64(table.References[offset])) + frame.pc++ + case operationKindTableSet: + table := tables[op.U1] + ref := ce.popValue() + + offset := ce.popValue() + if offset >= uint64(len(table.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + + table.References[offset] = uintptr(ref) // externrefs are opaque uint64. + frame.pc++ + case operationKindTableSize: + table := tables[op.U1] + ce.pushValue(uint64(len(table.References))) + frame.pc++ + case operationKindTableGrow: + table := tables[op.U1] + num, ref := ce.popValue(), ce.popValue() + ret := table.Grow(uint32(num), uintptr(ref)) + ce.pushValue(uint64(ret)) + frame.pc++ + case operationKindTableFill: + table := tables[op.U1] + num := ce.popValue() + ref := uintptr(ce.popValue()) + offset := ce.popValue() + if num+offset > uint64(len(table.References)) { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } else if num > 0 { + // Uses the copy trick for faster filling the region with the value. + // https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d + targetRegion := table.References[offset : offset+num] + targetRegion[0] = ref + for i := 1; i < len(targetRegion); i *= 2 { + copy(targetRegion[i:], targetRegion[:i]) + } + } + frame.pc++ + case operationKindV128Const: + lo, hi := op.U1, op.U2 + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Add: + yHigh, yLow := ce.popValue(), ce.popValue() + xHigh, xLow := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + ce.pushValue( + uint64(uint8(xLow>>8)+uint8(yLow>>8))<<8 | uint64(uint8(xLow)+uint8(yLow)) | + uint64(uint8(xLow>>24)+uint8(yLow>>24))<<24 | uint64(uint8(xLow>>16)+uint8(yLow>>16))<<16 | + uint64(uint8(xLow>>40)+uint8(yLow>>40))<<40 | uint64(uint8(xLow>>32)+uint8(yLow>>32))<<32 | + uint64(uint8(xLow>>56)+uint8(yLow>>56))<<56 | uint64(uint8(xLow>>48)+uint8(yLow>>48))<<48, + ) + ce.pushValue( + uint64(uint8(xHigh>>8)+uint8(yHigh>>8))<<8 | uint64(uint8(xHigh)+uint8(yHigh)) | + uint64(uint8(xHigh>>24)+uint8(yHigh>>24))<<24 | uint64(uint8(xHigh>>16)+uint8(yHigh>>16))<<16 | + uint64(uint8(xHigh>>40)+uint8(yHigh>>40))<<40 | uint64(uint8(xHigh>>32)+uint8(yHigh>>32))<<32 | + uint64(uint8(xHigh>>56)+uint8(yHigh>>56))<<56 | uint64(uint8(xHigh>>48)+uint8(yHigh>>48))<<48, + ) + case shapeI16x8: + ce.pushValue( + uint64(uint16(xLow>>16+yLow>>16))<<16 | uint64(uint16(xLow)+uint16(yLow)) | + uint64(uint16(xLow>>48+yLow>>48))<<48 | uint64(uint16(xLow>>32+yLow>>32))<<32, + ) + ce.pushValue( + uint64(uint16(xHigh>>16)+uint16(yHigh>>16))<<16 | uint64(uint16(xHigh)+uint16(yHigh)) | + uint64(uint16(xHigh>>48)+uint16(yHigh>>48))<<48 | uint64(uint16(xHigh>>32)+uint16(yHigh>>32))<<32, + ) + case shapeI32x4: + ce.pushValue(uint64(uint32(xLow>>32)+uint32(yLow>>32))<<32 | uint64(uint32(xLow)+uint32(yLow))) + ce.pushValue(uint64(uint32(xHigh>>32)+uint32(yHigh>>32))<<32 | uint64(uint32(xHigh)+uint32(yHigh))) + case shapeI64x2: + ce.pushValue(xLow + yLow) + ce.pushValue(xHigh + yHigh) + case shapeF32x4: + ce.pushValue( + addFloat32bits(uint32(xLow), uint32(yLow)) | addFloat32bits(uint32(xLow>>32), uint32(yLow>>32))<<32, + ) + ce.pushValue( + addFloat32bits(uint32(xHigh), uint32(yHigh)) | addFloat32bits(uint32(xHigh>>32), uint32(yHigh>>32))<<32, + ) + case shapeF64x2: + ce.pushValue(math.Float64bits(math.Float64frombits(xLow) + math.Float64frombits(yLow))) + ce.pushValue(math.Float64bits(math.Float64frombits(xHigh) + math.Float64frombits(yHigh))) + } + frame.pc++ + case operationKindV128Sub: + yHigh, yLow := ce.popValue(), ce.popValue() + xHigh, xLow := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + ce.pushValue( + uint64(uint8(xLow>>8)-uint8(yLow>>8))<<8 | uint64(uint8(xLow)-uint8(yLow)) | + uint64(uint8(xLow>>24)-uint8(yLow>>24))<<24 | uint64(uint8(xLow>>16)-uint8(yLow>>16))<<16 | + uint64(uint8(xLow>>40)-uint8(yLow>>40))<<40 | uint64(uint8(xLow>>32)-uint8(yLow>>32))<<32 | + uint64(uint8(xLow>>56)-uint8(yLow>>56))<<56 | uint64(uint8(xLow>>48)-uint8(yLow>>48))<<48, + ) + ce.pushValue( + uint64(uint8(xHigh>>8)-uint8(yHigh>>8))<<8 | uint64(uint8(xHigh)-uint8(yHigh)) | + uint64(uint8(xHigh>>24)-uint8(yHigh>>24))<<24 | uint64(uint8(xHigh>>16)-uint8(yHigh>>16))<<16 | + uint64(uint8(xHigh>>40)-uint8(yHigh>>40))<<40 | uint64(uint8(xHigh>>32)-uint8(yHigh>>32))<<32 | + uint64(uint8(xHigh>>56)-uint8(yHigh>>56))<<56 | uint64(uint8(xHigh>>48)-uint8(yHigh>>48))<<48, + ) + case shapeI16x8: + ce.pushValue( + uint64(uint16(xLow>>16)-uint16(yLow>>16))<<16 | uint64(uint16(xLow)-uint16(yLow)) | + uint64(uint16(xLow>>48)-uint16(yLow>>48))<<48 | uint64(uint16(xLow>>32)-uint16(yLow>>32))<<32, + ) + ce.pushValue( + uint64(uint16(xHigh>>16)-uint16(yHigh>>16))<<16 | uint64(uint16(xHigh)-uint16(yHigh)) | + uint64(uint16(xHigh>>48)-uint16(yHigh>>48))<<48 | uint64(uint16(xHigh>>32)-uint16(yHigh>>32))<<32, + ) + case shapeI32x4: + ce.pushValue(uint64(uint32(xLow>>32-yLow>>32))<<32 | uint64(uint32(xLow)-uint32(yLow))) + ce.pushValue(uint64(uint32(xHigh>>32-yHigh>>32))<<32 | uint64(uint32(xHigh)-uint32(yHigh))) + case shapeI64x2: + ce.pushValue(xLow - yLow) + ce.pushValue(xHigh - yHigh) + case shapeF32x4: + ce.pushValue( + subFloat32bits(uint32(xLow), uint32(yLow)) | subFloat32bits(uint32(xLow>>32), uint32(yLow>>32))<<32, + ) + ce.pushValue( + subFloat32bits(uint32(xHigh), uint32(yHigh)) | subFloat32bits(uint32(xHigh>>32), uint32(yHigh>>32))<<32, + ) + case shapeF64x2: + ce.pushValue(math.Float64bits(math.Float64frombits(xLow) - math.Float64frombits(yLow))) + ce.pushValue(math.Float64bits(math.Float64frombits(xHigh) - math.Float64frombits(yHigh))) + } + frame.pc++ + case operationKindV128Load: + offset := ce.popMemoryOffset(op) + switch op.B1 { + case v128LoadType128: + lo, ok := memoryInst.ReadUint64Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(lo) + hi, ok := memoryInst.ReadUint64Le(offset + 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(hi) + case v128LoadType8x8s: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue( + uint64(uint16(int8(data[3])))<<48 | uint64(uint16(int8(data[2])))<<32 | uint64(uint16(int8(data[1])))<<16 | uint64(uint16(int8(data[0]))), + ) + ce.pushValue( + uint64(uint16(int8(data[7])))<<48 | uint64(uint16(int8(data[6])))<<32 | uint64(uint16(int8(data[5])))<<16 | uint64(uint16(int8(data[4]))), + ) + case v128LoadType8x8u: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue( + uint64(data[3])<<48 | uint64(data[2])<<32 | uint64(data[1])<<16 | uint64(data[0]), + ) + ce.pushValue( + uint64(data[7])<<48 | uint64(data[6])<<32 | uint64(data[5])<<16 | uint64(data[4]), + ) + case v128LoadType16x4s: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue( + uint64(int16(binary.LittleEndian.Uint16(data[2:])))<<32 | + uint64(uint32(int16(binary.LittleEndian.Uint16(data)))), + ) + ce.pushValue( + uint64(uint32(int16(binary.LittleEndian.Uint16(data[6:]))))<<32 | + uint64(uint32(int16(binary.LittleEndian.Uint16(data[4:])))), + ) + case v128LoadType16x4u: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue( + uint64(binary.LittleEndian.Uint16(data[2:]))<<32 | uint64(binary.LittleEndian.Uint16(data)), + ) + ce.pushValue( + uint64(binary.LittleEndian.Uint16(data[6:]))<<32 | uint64(binary.LittleEndian.Uint16(data[4:])), + ) + case v128LoadType32x2s: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(int32(binary.LittleEndian.Uint32(data)))) + ce.pushValue(uint64(int32(binary.LittleEndian.Uint32(data[4:])))) + case v128LoadType32x2u: + data, ok := memoryInst.Read(offset, 8) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(binary.LittleEndian.Uint32(data))) + ce.pushValue(uint64(binary.LittleEndian.Uint32(data[4:]))) + case v128LoadType8Splat: + v, ok := memoryInst.ReadByte(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + v8 := uint64(v)<<56 | uint64(v)<<48 | uint64(v)<<40 | uint64(v)<<32 | + uint64(v)<<24 | uint64(v)<<16 | uint64(v)<<8 | uint64(v) + ce.pushValue(v8) + ce.pushValue(v8) + case v128LoadType16Splat: + v, ok := memoryInst.ReadUint16Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + v4 := uint64(v)<<48 | uint64(v)<<32 | uint64(v)<<16 | uint64(v) + ce.pushValue(v4) + ce.pushValue(v4) + case v128LoadType32Splat: + v, ok := memoryInst.ReadUint32Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + vv := uint64(v)<<32 | uint64(v) + ce.pushValue(vv) + ce.pushValue(vv) + case v128LoadType64Splat: + lo, ok := memoryInst.ReadUint64Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(lo) + ce.pushValue(lo) + case v128LoadType32zero: + lo, ok := memoryInst.ReadUint32Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(lo)) + ce.pushValue(0) + case v128LoadType64zero: + lo, ok := memoryInst.ReadUint64Le(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(lo) + ce.pushValue(0) + } + frame.pc++ + case operationKindV128LoadLane: + hi, lo := ce.popValue(), ce.popValue() + offset := ce.popMemoryOffset(op) + switch op.B1 { + case 8: + b, ok := memoryInst.ReadByte(offset) + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if op.B2 < 8 { + s := op.B2 << 3 + lo = (lo & ^(0xff << s)) | uint64(b)< math.MaxUint32 { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if ok := memoryInst.WriteUint64Le(offset+8, hi); !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if ok := memoryInst.WriteUint64Le(offset, lo); !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindV128StoreLane: + hi, lo := ce.popValue(), ce.popValue() + offset := ce.popMemoryOffset(op) + var ok bool + switch op.B1 { + case 8: + if op.B2 < 8 { + ok = memoryInst.WriteByte(offset, byte(lo>>(op.B2*8))) + } else { + ok = memoryInst.WriteByte(offset, byte(hi>>((op.B2-8)*8))) + } + case 16: + if op.B2 < 4 { + ok = memoryInst.WriteUint16Le(offset, uint16(lo>>(op.B2*16))) + } else { + ok = memoryInst.WriteUint16Le(offset, uint16(hi>>((op.B2-4)*16))) + } + case 32: + if op.B2 < 2 { + ok = memoryInst.WriteUint32Le(offset, uint32(lo>>(op.B2*32))) + } else { + ok = memoryInst.WriteUint32Le(offset, uint32(hi>>((op.B2-2)*32))) + } + case 64: + if op.B2 == 0 { + ok = memoryInst.WriteUint64Le(offset, lo) + } else { + ok = memoryInst.WriteUint64Le(offset, hi) + } + } + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindV128ReplaceLane: + v := ce.popValue() + hi, lo := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + if op.B2 < 8 { + s := op.B2 << 3 + lo = (lo & ^(0xff << s)) | uint64(byte(v))<> (op.B2 * 8)) + } else { + u8 = byte(hi >> ((op.B2 - 8) * 8)) + } + if op.B3 { + // sign-extend. + v = uint64(uint32(int8(u8))) + } else { + v = uint64(u8) + } + case shapeI16x8: + var u16 uint16 + if op.B2 < 4 { + u16 = uint16(lo >> (op.B2 * 16)) + } else { + u16 = uint16(hi >> ((op.B2 - 4) * 16)) + } + if op.B3 { + // sign-extend. + v = uint64(uint32(int16(u16))) + } else { + v = uint64(u16) + } + case shapeI32x4, shapeF32x4: + if op.B2 < 2 { + v = uint64(uint32(lo >> (op.B2 * 32))) + } else { + v = uint64(uint32(hi >> ((op.B2 - 2) * 32))) + } + case shapeI64x2, shapeF64x2: + if op.B2 == 0 { + v = lo + } else { + v = hi + } + } + ce.pushValue(v) + frame.pc++ + case operationKindV128Splat: + v := ce.popValue() + var hi, lo uint64 + switch op.B1 { + case shapeI8x16: + v8 := uint64(byte(v))<<56 | uint64(byte(v))<<48 | uint64(byte(v))<<40 | uint64(byte(v))<<32 | + uint64(byte(v))<<24 | uint64(byte(v))<<16 | uint64(byte(v))<<8 | uint64(byte(v)) + hi, lo = v8, v8 + case shapeI16x8: + v4 := uint64(uint16(v))<<48 | uint64(uint16(v))<<32 | uint64(uint16(v))<<16 | uint64(uint16(v)) + hi, lo = v4, v4 + case shapeI32x4, shapeF32x4: + v2 := uint64(uint32(v))<<32 | uint64(uint32(v)) + lo, hi = v2, v2 + case shapeI64x2, shapeF64x2: + lo, hi = v, v + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Swizzle: + idxHi, idxLo := ce.popValue(), ce.popValue() + baseHi, baseLo := ce.popValue(), ce.popValue() + var newVal [16]byte + for i := 0; i < 16; i++ { + var id byte + if i < 8 { + id = byte(idxLo >> (i * 8)) + } else { + id = byte(idxHi >> ((i - 8) * 8)) + } + if id < 8 { + newVal[i] = byte(baseLo >> (id * 8)) + } else if id < 16 { + newVal[i] = byte(baseHi >> ((id - 8) * 8)) + } + } + ce.pushValue(binary.LittleEndian.Uint64(newVal[:8])) + ce.pushValue(binary.LittleEndian.Uint64(newVal[8:])) + frame.pc++ + case operationKindV128Shuffle: + xHi, xLo, yHi, yLo := ce.popValue(), ce.popValue(), ce.popValue(), ce.popValue() + var newVal [16]byte + for i, l := range op.Us { + if l < 8 { + newVal[i] = byte(yLo >> (l * 8)) + } else if l < 16 { + newVal[i] = byte(yHi >> ((l - 8) * 8)) + } else if l < 24 { + newVal[i] = byte(xLo >> ((l - 16) * 8)) + } else if l < 32 { + newVal[i] = byte(xHi >> ((l - 24) * 8)) + } + } + ce.pushValue(binary.LittleEndian.Uint64(newVal[:8])) + ce.pushValue(binary.LittleEndian.Uint64(newVal[8:])) + frame.pc++ + case operationKindV128AnyTrue: + hi, lo := ce.popValue(), ce.popValue() + if hi != 0 || lo != 0 { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindV128AllTrue: + hi, lo := ce.popValue(), ce.popValue() + var ret bool + switch op.B1 { + case shapeI8x16: + ret = (uint8(lo) != 0) && (uint8(lo>>8) != 0) && (uint8(lo>>16) != 0) && (uint8(lo>>24) != 0) && + (uint8(lo>>32) != 0) && (uint8(lo>>40) != 0) && (uint8(lo>>48) != 0) && (uint8(lo>>56) != 0) && + (uint8(hi) != 0) && (uint8(hi>>8) != 0) && (uint8(hi>>16) != 0) && (uint8(hi>>24) != 0) && + (uint8(hi>>32) != 0) && (uint8(hi>>40) != 0) && (uint8(hi>>48) != 0) && (uint8(hi>>56) != 0) + case shapeI16x8: + ret = (uint16(lo) != 0) && (uint16(lo>>16) != 0) && (uint16(lo>>32) != 0) && (uint16(lo>>48) != 0) && + (uint16(hi) != 0) && (uint16(hi>>16) != 0) && (uint16(hi>>32) != 0) && (uint16(hi>>48) != 0) + case shapeI32x4: + ret = (uint32(lo) != 0) && (uint32(lo>>32) != 0) && + (uint32(hi) != 0) && (uint32(hi>>32) != 0) + case shapeI64x2: + ret = (lo != 0) && + (hi != 0) + } + if ret { + ce.pushValue(1) + } else { + ce.pushValue(0) + } + frame.pc++ + case operationKindV128BitMask: + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#bitmask-extraction + hi, lo := ce.popValue(), ce.popValue() + var res uint64 + switch op.B1 { + case shapeI8x16: + for i := 0; i < 8; i++ { + if int8(lo>>(i*8)) < 0 { + res |= 1 << i + } + } + for i := 0; i < 8; i++ { + if int8(hi>>(i*8)) < 0 { + res |= 1 << (i + 8) + } + } + case shapeI16x8: + for i := 0; i < 4; i++ { + if int16(lo>>(i*16)) < 0 { + res |= 1 << i + } + } + for i := 0; i < 4; i++ { + if int16(hi>>(i*16)) < 0 { + res |= 1 << (i + 4) + } + } + case shapeI32x4: + for i := 0; i < 2; i++ { + if int32(lo>>(i*32)) < 0 { + res |= 1 << i + } + } + for i := 0; i < 2; i++ { + if int32(hi>>(i*32)) < 0 { + res |= 1 << (i + 2) + } + } + case shapeI64x2: + if int64(lo) < 0 { + res |= 0b01 + } + if int(hi) < 0 { + res |= 0b10 + } + } + ce.pushValue(res) + frame.pc++ + case operationKindV128And: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + ce.pushValue(x1Lo & x2Lo) + ce.pushValue(x1Hi & x2Hi) + frame.pc++ + case operationKindV128Not: + hi, lo := ce.popValue(), ce.popValue() + ce.pushValue(^lo) + ce.pushValue(^hi) + frame.pc++ + case operationKindV128Or: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + ce.pushValue(x1Lo | x2Lo) + ce.pushValue(x1Hi | x2Hi) + frame.pc++ + case operationKindV128Xor: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + ce.pushValue(x1Lo ^ x2Lo) + ce.pushValue(x1Hi ^ x2Hi) + frame.pc++ + case operationKindV128Bitselect: + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#bitwise-select + cHi, cLo := ce.popValue(), ce.popValue() + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + // v128.or(v128.and(v1, c), v128.and(v2, v128.not(c))) + ce.pushValue((x1Lo & cLo) | (x2Lo & (^cLo))) + ce.pushValue((x1Hi & cHi) | (x2Hi & (^cHi))) + frame.pc++ + case operationKindV128AndNot: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + ce.pushValue(x1Lo & (^x2Lo)) + ce.pushValue(x1Hi & (^x2Hi)) + frame.pc++ + case operationKindV128Shl: + s := ce.popValue() + hi, lo := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + s = s % 8 + lo = uint64(uint8(lo<>8)<>16)<>24)<>32)<>40)<>48)<>56)<>8)<>16)<>24)<>32)<>40)<>48)<>56)<>16)<>32)<>48)<>16)<>32)<>48)<>32)<>32)<>s)) | + uint64(uint8(int8(lo>>8)>>s))<<8 | + uint64(uint8(int8(lo>>16)>>s))<<16 | + uint64(uint8(int8(lo>>24)>>s))<<24 | + uint64(uint8(int8(lo>>32)>>s))<<32 | + uint64(uint8(int8(lo>>40)>>s))<<40 | + uint64(uint8(int8(lo>>48)>>s))<<48 | + uint64(uint8(int8(lo>>56)>>s))<<56 + hi = uint64(uint8(int8(hi)>>s)) | + uint64(uint8(int8(hi>>8)>>s))<<8 | + uint64(uint8(int8(hi>>16)>>s))<<16 | + uint64(uint8(int8(hi>>24)>>s))<<24 | + uint64(uint8(int8(hi>>32)>>s))<<32 | + uint64(uint8(int8(hi>>40)>>s))<<40 | + uint64(uint8(int8(hi>>48)>>s))<<48 | + uint64(uint8(int8(hi>>56)>>s))<<56 + } else { + lo = uint64(uint8(lo)>>s) | + uint64(uint8(lo>>8)>>s)<<8 | + uint64(uint8(lo>>16)>>s)<<16 | + uint64(uint8(lo>>24)>>s)<<24 | + uint64(uint8(lo>>32)>>s)<<32 | + uint64(uint8(lo>>40)>>s)<<40 | + uint64(uint8(lo>>48)>>s)<<48 | + uint64(uint8(lo>>56)>>s)<<56 + hi = uint64(uint8(hi)>>s) | + uint64(uint8(hi>>8)>>s)<<8 | + uint64(uint8(hi>>16)>>s)<<16 | + uint64(uint8(hi>>24)>>s)<<24 | + uint64(uint8(hi>>32)>>s)<<32 | + uint64(uint8(hi>>40)>>s)<<40 | + uint64(uint8(hi>>48)>>s)<<48 | + uint64(uint8(hi>>56)>>s)<<56 + } + case shapeI16x8: + s = s % 16 + if op.B3 { // signed + lo = uint64(uint16(int16(lo)>>s)) | + uint64(uint16(int16(lo>>16)>>s))<<16 | + uint64(uint16(int16(lo>>32)>>s))<<32 | + uint64(uint16(int16(lo>>48)>>s))<<48 + hi = uint64(uint16(int16(hi)>>s)) | + uint64(uint16(int16(hi>>16)>>s))<<16 | + uint64(uint16(int16(hi>>32)>>s))<<32 | + uint64(uint16(int16(hi>>48)>>s))<<48 + } else { + lo = uint64(uint16(lo)>>s) | + uint64(uint16(lo>>16)>>s)<<16 | + uint64(uint16(lo>>32)>>s)<<32 | + uint64(uint16(lo>>48)>>s)<<48 + hi = uint64(uint16(hi)>>s) | + uint64(uint16(hi>>16)>>s)<<16 | + uint64(uint16(hi>>32)>>s)<<32 | + uint64(uint16(hi>>48)>>s)<<48 + } + case shapeI32x4: + s = s % 32 + if op.B3 { + lo = uint64(uint32(int32(lo)>>s)) | uint64(uint32(int32(lo>>32)>>s))<<32 + hi = uint64(uint32(int32(hi)>>s)) | uint64(uint32(int32(hi>>32)>>s))<<32 + } else { + lo = uint64(uint32(lo)>>s) | uint64(uint32(lo>>32)>>s)<<32 + hi = uint64(uint32(hi)>>s) | uint64(uint32(hi>>32)>>s)<<32 + } + case shapeI64x2: + s = s % 64 + if op.B3 { // signed + lo = uint64(int64(lo) >> s) + hi = uint64(int64(hi) >> s) + } else { + lo = lo >> s + hi = hi >> s + } + + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Cmp: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + var result []bool + switch op.B1 { + case v128CmpTypeI8x16Eq: + result = []bool{ + byte(x1Lo>>0) == byte(x2Lo>>0), byte(x1Lo>>8) == byte(x2Lo>>8), + byte(x1Lo>>16) == byte(x2Lo>>16), byte(x1Lo>>24) == byte(x2Lo>>24), + byte(x1Lo>>32) == byte(x2Lo>>32), byte(x1Lo>>40) == byte(x2Lo>>40), + byte(x1Lo>>48) == byte(x2Lo>>48), byte(x1Lo>>56) == byte(x2Lo>>56), + byte(x1Hi>>0) == byte(x2Hi>>0), byte(x1Hi>>8) == byte(x2Hi>>8), + byte(x1Hi>>16) == byte(x2Hi>>16), byte(x1Hi>>24) == byte(x2Hi>>24), + byte(x1Hi>>32) == byte(x2Hi>>32), byte(x1Hi>>40) == byte(x2Hi>>40), + byte(x1Hi>>48) == byte(x2Hi>>48), byte(x1Hi>>56) == byte(x2Hi>>56), + } + case v128CmpTypeI8x16Ne: + result = []bool{ + byte(x1Lo>>0) != byte(x2Lo>>0), byte(x1Lo>>8) != byte(x2Lo>>8), + byte(x1Lo>>16) != byte(x2Lo>>16), byte(x1Lo>>24) != byte(x2Lo>>24), + byte(x1Lo>>32) != byte(x2Lo>>32), byte(x1Lo>>40) != byte(x2Lo>>40), + byte(x1Lo>>48) != byte(x2Lo>>48), byte(x1Lo>>56) != byte(x2Lo>>56), + byte(x1Hi>>0) != byte(x2Hi>>0), byte(x1Hi>>8) != byte(x2Hi>>8), + byte(x1Hi>>16) != byte(x2Hi>>16), byte(x1Hi>>24) != byte(x2Hi>>24), + byte(x1Hi>>32) != byte(x2Hi>>32), byte(x1Hi>>40) != byte(x2Hi>>40), + byte(x1Hi>>48) != byte(x2Hi>>48), byte(x1Hi>>56) != byte(x2Hi>>56), + } + case v128CmpTypeI8x16LtS: + result = []bool{ + int8(x1Lo>>0) < int8(x2Lo>>0), int8(x1Lo>>8) < int8(x2Lo>>8), + int8(x1Lo>>16) < int8(x2Lo>>16), int8(x1Lo>>24) < int8(x2Lo>>24), + int8(x1Lo>>32) < int8(x2Lo>>32), int8(x1Lo>>40) < int8(x2Lo>>40), + int8(x1Lo>>48) < int8(x2Lo>>48), int8(x1Lo>>56) < int8(x2Lo>>56), + int8(x1Hi>>0) < int8(x2Hi>>0), int8(x1Hi>>8) < int8(x2Hi>>8), + int8(x1Hi>>16) < int8(x2Hi>>16), int8(x1Hi>>24) < int8(x2Hi>>24), + int8(x1Hi>>32) < int8(x2Hi>>32), int8(x1Hi>>40) < int8(x2Hi>>40), + int8(x1Hi>>48) < int8(x2Hi>>48), int8(x1Hi>>56) < int8(x2Hi>>56), + } + case v128CmpTypeI8x16LtU: + result = []bool{ + byte(x1Lo>>0) < byte(x2Lo>>0), byte(x1Lo>>8) < byte(x2Lo>>8), + byte(x1Lo>>16) < byte(x2Lo>>16), byte(x1Lo>>24) < byte(x2Lo>>24), + byte(x1Lo>>32) < byte(x2Lo>>32), byte(x1Lo>>40) < byte(x2Lo>>40), + byte(x1Lo>>48) < byte(x2Lo>>48), byte(x1Lo>>56) < byte(x2Lo>>56), + byte(x1Hi>>0) < byte(x2Hi>>0), byte(x1Hi>>8) < byte(x2Hi>>8), + byte(x1Hi>>16) < byte(x2Hi>>16), byte(x1Hi>>24) < byte(x2Hi>>24), + byte(x1Hi>>32) < byte(x2Hi>>32), byte(x1Hi>>40) < byte(x2Hi>>40), + byte(x1Hi>>48) < byte(x2Hi>>48), byte(x1Hi>>56) < byte(x2Hi>>56), + } + case v128CmpTypeI8x16GtS: + result = []bool{ + int8(x1Lo>>0) > int8(x2Lo>>0), int8(x1Lo>>8) > int8(x2Lo>>8), + int8(x1Lo>>16) > int8(x2Lo>>16), int8(x1Lo>>24) > int8(x2Lo>>24), + int8(x1Lo>>32) > int8(x2Lo>>32), int8(x1Lo>>40) > int8(x2Lo>>40), + int8(x1Lo>>48) > int8(x2Lo>>48), int8(x1Lo>>56) > int8(x2Lo>>56), + int8(x1Hi>>0) > int8(x2Hi>>0), int8(x1Hi>>8) > int8(x2Hi>>8), + int8(x1Hi>>16) > int8(x2Hi>>16), int8(x1Hi>>24) > int8(x2Hi>>24), + int8(x1Hi>>32) > int8(x2Hi>>32), int8(x1Hi>>40) > int8(x2Hi>>40), + int8(x1Hi>>48) > int8(x2Hi>>48), int8(x1Hi>>56) > int8(x2Hi>>56), + } + case v128CmpTypeI8x16GtU: + result = []bool{ + byte(x1Lo>>0) > byte(x2Lo>>0), byte(x1Lo>>8) > byte(x2Lo>>8), + byte(x1Lo>>16) > byte(x2Lo>>16), byte(x1Lo>>24) > byte(x2Lo>>24), + byte(x1Lo>>32) > byte(x2Lo>>32), byte(x1Lo>>40) > byte(x2Lo>>40), + byte(x1Lo>>48) > byte(x2Lo>>48), byte(x1Lo>>56) > byte(x2Lo>>56), + byte(x1Hi>>0) > byte(x2Hi>>0), byte(x1Hi>>8) > byte(x2Hi>>8), + byte(x1Hi>>16) > byte(x2Hi>>16), byte(x1Hi>>24) > byte(x2Hi>>24), + byte(x1Hi>>32) > byte(x2Hi>>32), byte(x1Hi>>40) > byte(x2Hi>>40), + byte(x1Hi>>48) > byte(x2Hi>>48), byte(x1Hi>>56) > byte(x2Hi>>56), + } + case v128CmpTypeI8x16LeS: + result = []bool{ + int8(x1Lo>>0) <= int8(x2Lo>>0), int8(x1Lo>>8) <= int8(x2Lo>>8), + int8(x1Lo>>16) <= int8(x2Lo>>16), int8(x1Lo>>24) <= int8(x2Lo>>24), + int8(x1Lo>>32) <= int8(x2Lo>>32), int8(x1Lo>>40) <= int8(x2Lo>>40), + int8(x1Lo>>48) <= int8(x2Lo>>48), int8(x1Lo>>56) <= int8(x2Lo>>56), + int8(x1Hi>>0) <= int8(x2Hi>>0), int8(x1Hi>>8) <= int8(x2Hi>>8), + int8(x1Hi>>16) <= int8(x2Hi>>16), int8(x1Hi>>24) <= int8(x2Hi>>24), + int8(x1Hi>>32) <= int8(x2Hi>>32), int8(x1Hi>>40) <= int8(x2Hi>>40), + int8(x1Hi>>48) <= int8(x2Hi>>48), int8(x1Hi>>56) <= int8(x2Hi>>56), + } + case v128CmpTypeI8x16LeU: + result = []bool{ + byte(x1Lo>>0) <= byte(x2Lo>>0), byte(x1Lo>>8) <= byte(x2Lo>>8), + byte(x1Lo>>16) <= byte(x2Lo>>16), byte(x1Lo>>24) <= byte(x2Lo>>24), + byte(x1Lo>>32) <= byte(x2Lo>>32), byte(x1Lo>>40) <= byte(x2Lo>>40), + byte(x1Lo>>48) <= byte(x2Lo>>48), byte(x1Lo>>56) <= byte(x2Lo>>56), + byte(x1Hi>>0) <= byte(x2Hi>>0), byte(x1Hi>>8) <= byte(x2Hi>>8), + byte(x1Hi>>16) <= byte(x2Hi>>16), byte(x1Hi>>24) <= byte(x2Hi>>24), + byte(x1Hi>>32) <= byte(x2Hi>>32), byte(x1Hi>>40) <= byte(x2Hi>>40), + byte(x1Hi>>48) <= byte(x2Hi>>48), byte(x1Hi>>56) <= byte(x2Hi>>56), + } + case v128CmpTypeI8x16GeS: + result = []bool{ + int8(x1Lo>>0) >= int8(x2Lo>>0), int8(x1Lo>>8) >= int8(x2Lo>>8), + int8(x1Lo>>16) >= int8(x2Lo>>16), int8(x1Lo>>24) >= int8(x2Lo>>24), + int8(x1Lo>>32) >= int8(x2Lo>>32), int8(x1Lo>>40) >= int8(x2Lo>>40), + int8(x1Lo>>48) >= int8(x2Lo>>48), int8(x1Lo>>56) >= int8(x2Lo>>56), + int8(x1Hi>>0) >= int8(x2Hi>>0), int8(x1Hi>>8) >= int8(x2Hi>>8), + int8(x1Hi>>16) >= int8(x2Hi>>16), int8(x1Hi>>24) >= int8(x2Hi>>24), + int8(x1Hi>>32) >= int8(x2Hi>>32), int8(x1Hi>>40) >= int8(x2Hi>>40), + int8(x1Hi>>48) >= int8(x2Hi>>48), int8(x1Hi>>56) >= int8(x2Hi>>56), + } + case v128CmpTypeI8x16GeU: + result = []bool{ + byte(x1Lo>>0) >= byte(x2Lo>>0), byte(x1Lo>>8) >= byte(x2Lo>>8), + byte(x1Lo>>16) >= byte(x2Lo>>16), byte(x1Lo>>24) >= byte(x2Lo>>24), + byte(x1Lo>>32) >= byte(x2Lo>>32), byte(x1Lo>>40) >= byte(x2Lo>>40), + byte(x1Lo>>48) >= byte(x2Lo>>48), byte(x1Lo>>56) >= byte(x2Lo>>56), + byte(x1Hi>>0) >= byte(x2Hi>>0), byte(x1Hi>>8) >= byte(x2Hi>>8), + byte(x1Hi>>16) >= byte(x2Hi>>16), byte(x1Hi>>24) >= byte(x2Hi>>24), + byte(x1Hi>>32) >= byte(x2Hi>>32), byte(x1Hi>>40) >= byte(x2Hi>>40), + byte(x1Hi>>48) >= byte(x2Hi>>48), byte(x1Hi>>56) >= byte(x2Hi>>56), + } + case v128CmpTypeI16x8Eq: + result = []bool{ + uint16(x1Lo>>0) == uint16(x2Lo>>0), uint16(x1Lo>>16) == uint16(x2Lo>>16), + uint16(x1Lo>>32) == uint16(x2Lo>>32), uint16(x1Lo>>48) == uint16(x2Lo>>48), + uint16(x1Hi>>0) == uint16(x2Hi>>0), uint16(x1Hi>>16) == uint16(x2Hi>>16), + uint16(x1Hi>>32) == uint16(x2Hi>>32), uint16(x1Hi>>48) == uint16(x2Hi>>48), + } + case v128CmpTypeI16x8Ne: + result = []bool{ + uint16(x1Lo>>0) != uint16(x2Lo>>0), uint16(x1Lo>>16) != uint16(x2Lo>>16), + uint16(x1Lo>>32) != uint16(x2Lo>>32), uint16(x1Lo>>48) != uint16(x2Lo>>48), + uint16(x1Hi>>0) != uint16(x2Hi>>0), uint16(x1Hi>>16) != uint16(x2Hi>>16), + uint16(x1Hi>>32) != uint16(x2Hi>>32), uint16(x1Hi>>48) != uint16(x2Hi>>48), + } + case v128CmpTypeI16x8LtS: + result = []bool{ + int16(x1Lo>>0) < int16(x2Lo>>0), int16(x1Lo>>16) < int16(x2Lo>>16), + int16(x1Lo>>32) < int16(x2Lo>>32), int16(x1Lo>>48) < int16(x2Lo>>48), + int16(x1Hi>>0) < int16(x2Hi>>0), int16(x1Hi>>16) < int16(x2Hi>>16), + int16(x1Hi>>32) < int16(x2Hi>>32), int16(x1Hi>>48) < int16(x2Hi>>48), + } + case v128CmpTypeI16x8LtU: + result = []bool{ + uint16(x1Lo>>0) < uint16(x2Lo>>0), uint16(x1Lo>>16) < uint16(x2Lo>>16), + uint16(x1Lo>>32) < uint16(x2Lo>>32), uint16(x1Lo>>48) < uint16(x2Lo>>48), + uint16(x1Hi>>0) < uint16(x2Hi>>0), uint16(x1Hi>>16) < uint16(x2Hi>>16), + uint16(x1Hi>>32) < uint16(x2Hi>>32), uint16(x1Hi>>48) < uint16(x2Hi>>48), + } + case v128CmpTypeI16x8GtS: + result = []bool{ + int16(x1Lo>>0) > int16(x2Lo>>0), int16(x1Lo>>16) > int16(x2Lo>>16), + int16(x1Lo>>32) > int16(x2Lo>>32), int16(x1Lo>>48) > int16(x2Lo>>48), + int16(x1Hi>>0) > int16(x2Hi>>0), int16(x1Hi>>16) > int16(x2Hi>>16), + int16(x1Hi>>32) > int16(x2Hi>>32), int16(x1Hi>>48) > int16(x2Hi>>48), + } + case v128CmpTypeI16x8GtU: + result = []bool{ + uint16(x1Lo>>0) > uint16(x2Lo>>0), uint16(x1Lo>>16) > uint16(x2Lo>>16), + uint16(x1Lo>>32) > uint16(x2Lo>>32), uint16(x1Lo>>48) > uint16(x2Lo>>48), + uint16(x1Hi>>0) > uint16(x2Hi>>0), uint16(x1Hi>>16) > uint16(x2Hi>>16), + uint16(x1Hi>>32) > uint16(x2Hi>>32), uint16(x1Hi>>48) > uint16(x2Hi>>48), + } + case v128CmpTypeI16x8LeS: + result = []bool{ + int16(x1Lo>>0) <= int16(x2Lo>>0), int16(x1Lo>>16) <= int16(x2Lo>>16), + int16(x1Lo>>32) <= int16(x2Lo>>32), int16(x1Lo>>48) <= int16(x2Lo>>48), + int16(x1Hi>>0) <= int16(x2Hi>>0), int16(x1Hi>>16) <= int16(x2Hi>>16), + int16(x1Hi>>32) <= int16(x2Hi>>32), int16(x1Hi>>48) <= int16(x2Hi>>48), + } + case v128CmpTypeI16x8LeU: + result = []bool{ + uint16(x1Lo>>0) <= uint16(x2Lo>>0), uint16(x1Lo>>16) <= uint16(x2Lo>>16), + uint16(x1Lo>>32) <= uint16(x2Lo>>32), uint16(x1Lo>>48) <= uint16(x2Lo>>48), + uint16(x1Hi>>0) <= uint16(x2Hi>>0), uint16(x1Hi>>16) <= uint16(x2Hi>>16), + uint16(x1Hi>>32) <= uint16(x2Hi>>32), uint16(x1Hi>>48) <= uint16(x2Hi>>48), + } + case v128CmpTypeI16x8GeS: + result = []bool{ + int16(x1Lo>>0) >= int16(x2Lo>>0), int16(x1Lo>>16) >= int16(x2Lo>>16), + int16(x1Lo>>32) >= int16(x2Lo>>32), int16(x1Lo>>48) >= int16(x2Lo>>48), + int16(x1Hi>>0) >= int16(x2Hi>>0), int16(x1Hi>>16) >= int16(x2Hi>>16), + int16(x1Hi>>32) >= int16(x2Hi>>32), int16(x1Hi>>48) >= int16(x2Hi>>48), + } + case v128CmpTypeI16x8GeU: + result = []bool{ + uint16(x1Lo>>0) >= uint16(x2Lo>>0), uint16(x1Lo>>16) >= uint16(x2Lo>>16), + uint16(x1Lo>>32) >= uint16(x2Lo>>32), uint16(x1Lo>>48) >= uint16(x2Lo>>48), + uint16(x1Hi>>0) >= uint16(x2Hi>>0), uint16(x1Hi>>16) >= uint16(x2Hi>>16), + uint16(x1Hi>>32) >= uint16(x2Hi>>32), uint16(x1Hi>>48) >= uint16(x2Hi>>48), + } + case v128CmpTypeI32x4Eq: + result = []bool{ + uint32(x1Lo>>0) == uint32(x2Lo>>0), uint32(x1Lo>>32) == uint32(x2Lo>>32), + uint32(x1Hi>>0) == uint32(x2Hi>>0), uint32(x1Hi>>32) == uint32(x2Hi>>32), + } + case v128CmpTypeI32x4Ne: + result = []bool{ + uint32(x1Lo>>0) != uint32(x2Lo>>0), uint32(x1Lo>>32) != uint32(x2Lo>>32), + uint32(x1Hi>>0) != uint32(x2Hi>>0), uint32(x1Hi>>32) != uint32(x2Hi>>32), + } + case v128CmpTypeI32x4LtS: + result = []bool{ + int32(x1Lo>>0) < int32(x2Lo>>0), int32(x1Lo>>32) < int32(x2Lo>>32), + int32(x1Hi>>0) < int32(x2Hi>>0), int32(x1Hi>>32) < int32(x2Hi>>32), + } + case v128CmpTypeI32x4LtU: + result = []bool{ + uint32(x1Lo>>0) < uint32(x2Lo>>0), uint32(x1Lo>>32) < uint32(x2Lo>>32), + uint32(x1Hi>>0) < uint32(x2Hi>>0), uint32(x1Hi>>32) < uint32(x2Hi>>32), + } + case v128CmpTypeI32x4GtS: + result = []bool{ + int32(x1Lo>>0) > int32(x2Lo>>0), int32(x1Lo>>32) > int32(x2Lo>>32), + int32(x1Hi>>0) > int32(x2Hi>>0), int32(x1Hi>>32) > int32(x2Hi>>32), + } + case v128CmpTypeI32x4GtU: + result = []bool{ + uint32(x1Lo>>0) > uint32(x2Lo>>0), uint32(x1Lo>>32) > uint32(x2Lo>>32), + uint32(x1Hi>>0) > uint32(x2Hi>>0), uint32(x1Hi>>32) > uint32(x2Hi>>32), + } + case v128CmpTypeI32x4LeS: + result = []bool{ + int32(x1Lo>>0) <= int32(x2Lo>>0), int32(x1Lo>>32) <= int32(x2Lo>>32), + int32(x1Hi>>0) <= int32(x2Hi>>0), int32(x1Hi>>32) <= int32(x2Hi>>32), + } + case v128CmpTypeI32x4LeU: + result = []bool{ + uint32(x1Lo>>0) <= uint32(x2Lo>>0), uint32(x1Lo>>32) <= uint32(x2Lo>>32), + uint32(x1Hi>>0) <= uint32(x2Hi>>0), uint32(x1Hi>>32) <= uint32(x2Hi>>32), + } + case v128CmpTypeI32x4GeS: + result = []bool{ + int32(x1Lo>>0) >= int32(x2Lo>>0), int32(x1Lo>>32) >= int32(x2Lo>>32), + int32(x1Hi>>0) >= int32(x2Hi>>0), int32(x1Hi>>32) >= int32(x2Hi>>32), + } + case v128CmpTypeI32x4GeU: + result = []bool{ + uint32(x1Lo>>0) >= uint32(x2Lo>>0), uint32(x1Lo>>32) >= uint32(x2Lo>>32), + uint32(x1Hi>>0) >= uint32(x2Hi>>0), uint32(x1Hi>>32) >= uint32(x2Hi>>32), + } + case v128CmpTypeI64x2Eq: + result = []bool{x1Lo == x2Lo, x1Hi == x2Hi} + case v128CmpTypeI64x2Ne: + result = []bool{x1Lo != x2Lo, x1Hi != x2Hi} + case v128CmpTypeI64x2LtS: + result = []bool{int64(x1Lo) < int64(x2Lo), int64(x1Hi) < int64(x2Hi)} + case v128CmpTypeI64x2GtS: + result = []bool{int64(x1Lo) > int64(x2Lo), int64(x1Hi) > int64(x2Hi)} + case v128CmpTypeI64x2LeS: + result = []bool{int64(x1Lo) <= int64(x2Lo), int64(x1Hi) <= int64(x2Hi)} + case v128CmpTypeI64x2GeS: + result = []bool{int64(x1Lo) >= int64(x2Lo), int64(x1Hi) >= int64(x2Hi)} + case v128CmpTypeF32x4Eq: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) == math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) == math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) == math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) == math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF32x4Ne: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) != math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) != math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) != math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) != math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF32x4Lt: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) < math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) < math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) < math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) < math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF32x4Gt: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) > math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) > math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) > math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) > math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF32x4Le: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) <= math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) <= math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) <= math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) <= math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF32x4Ge: + result = []bool{ + math.Float32frombits(uint32(x1Lo>>0)) >= math.Float32frombits(uint32(x2Lo>>0)), + math.Float32frombits(uint32(x1Lo>>32)) >= math.Float32frombits(uint32(x2Lo>>32)), + math.Float32frombits(uint32(x1Hi>>0)) >= math.Float32frombits(uint32(x2Hi>>0)), + math.Float32frombits(uint32(x1Hi>>32)) >= math.Float32frombits(uint32(x2Hi>>32)), + } + case v128CmpTypeF64x2Eq: + result = []bool{ + math.Float64frombits(x1Lo) == math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) == math.Float64frombits(x2Hi), + } + case v128CmpTypeF64x2Ne: + result = []bool{ + math.Float64frombits(x1Lo) != math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) != math.Float64frombits(x2Hi), + } + case v128CmpTypeF64x2Lt: + result = []bool{ + math.Float64frombits(x1Lo) < math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) < math.Float64frombits(x2Hi), + } + case v128CmpTypeF64x2Gt: + result = []bool{ + math.Float64frombits(x1Lo) > math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) > math.Float64frombits(x2Hi), + } + case v128CmpTypeF64x2Le: + result = []bool{ + math.Float64frombits(x1Lo) <= math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) <= math.Float64frombits(x2Hi), + } + case v128CmpTypeF64x2Ge: + result = []bool{ + math.Float64frombits(x1Lo) >= math.Float64frombits(x2Lo), + math.Float64frombits(x1Hi) >= math.Float64frombits(x2Hi), + } + } + + var retLo, retHi uint64 + laneNum := len(result) + switch laneNum { + case 16: + for i, b := range result { + if b { + if i < 8 { + retLo |= 0xff << (i * 8) + } else { + retHi |= 0xff << ((i - 8) * 8) + } + } + } + case 8: + for i, b := range result { + if b { + if i < 4 { + retLo |= 0xffff << (i * 16) + } else { + retHi |= 0xffff << ((i - 4) * 16) + } + } + } + case 4: + for i, b := range result { + if b { + if i < 2 { + retLo |= 0xffff_ffff << (i * 32) + } else { + retHi |= 0xffff_ffff << ((i - 2) * 32) + } + } + } + case 2: + if result[0] { + retLo = ^uint64(0) + } + if result[1] { + retHi = ^uint64(0) + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128AddSat: + x2hi, x2Lo := ce.popValue(), ce.popValue() + x1hi, x1Lo := ce.popValue(), ce.popValue() + + var retLo, retHi uint64 + + // Lane-wise addition while saturating the overflowing values. + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-addition + switch op.B1 { + case shapeI8x16: + for i := 0; i < 16; i++ { + var v, w byte + if i < 8 { + v, w = byte(x1Lo>>(i*8)), byte(x2Lo>>(i*8)) + } else { + v, w = byte(x1hi>>((i-8)*8)), byte(x2hi>>((i-8)*8)) + } + + var uv uint64 + if op.B3 { // signed + if subbed := int64(int8(v)) + int64(int8(w)); subbed < math.MinInt8 { + uv = uint64(byte(0x80)) + } else if subbed > math.MaxInt8 { + uv = uint64(byte(0x7f)) + } else { + uv = uint64(byte(int8(subbed))) + } + } else { + if subbed := int64(v) + int64(w); subbed < 0 { + uv = uint64(byte(0)) + } else if subbed > math.MaxUint8 { + uv = uint64(byte(0xff)) + } else { + uv = uint64(byte(subbed)) + } + } + + if i < 8 { // first 8 lanes are on lower 64bits. + retLo |= uv << (i * 8) + } else { + retHi |= uv << ((i - 8) * 8) + } + } + case shapeI16x8: + for i := 0; i < 8; i++ { + var v, w uint16 + if i < 4 { + v, w = uint16(x1Lo>>(i*16)), uint16(x2Lo>>(i*16)) + } else { + v, w = uint16(x1hi>>((i-4)*16)), uint16(x2hi>>((i-4)*16)) + } + + var uv uint64 + if op.B3 { // signed + if added := int64(int16(v)) + int64(int16(w)); added < math.MinInt16 { + uv = uint64(uint16(0x8000)) + } else if added > math.MaxInt16 { + uv = uint64(uint16(0x7fff)) + } else { + uv = uint64(uint16(int16(added))) + } + } else { + if added := int64(v) + int64(w); added < 0 { + uv = uint64(uint16(0)) + } else if added > math.MaxUint16 { + uv = uint64(uint16(0xffff)) + } else { + uv = uint64(uint16(added)) + } + } + + if i < 4 { // first 4 lanes are on lower 64bits. + retLo |= uv << (i * 16) + } else { + retHi |= uv << ((i - 4) * 16) + } + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128SubSat: + x2hi, x2Lo := ce.popValue(), ce.popValue() + x1hi, x1Lo := ce.popValue(), ce.popValue() + + var retLo, retHi uint64 + + // Lane-wise subtraction while saturating the overflowing values. + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-subtraction + switch op.B1 { + case shapeI8x16: + for i := 0; i < 16; i++ { + var v, w byte + if i < 8 { + v, w = byte(x1Lo>>(i*8)), byte(x2Lo>>(i*8)) + } else { + v, w = byte(x1hi>>((i-8)*8)), byte(x2hi>>((i-8)*8)) + } + + var uv uint64 + if op.B3 { // signed + if subbed := int64(int8(v)) - int64(int8(w)); subbed < math.MinInt8 { + uv = uint64(byte(0x80)) + } else if subbed > math.MaxInt8 { + uv = uint64(byte(0x7f)) + } else { + uv = uint64(byte(int8(subbed))) + } + } else { + if subbed := int64(v) - int64(w); subbed < 0 { + uv = uint64(byte(0)) + } else if subbed > math.MaxUint8 { + uv = uint64(byte(0xff)) + } else { + uv = uint64(byte(subbed)) + } + } + + if i < 8 { + retLo |= uv << (i * 8) + } else { + retHi |= uv << ((i - 8) * 8) + } + } + case shapeI16x8: + for i := 0; i < 8; i++ { + var v, w uint16 + if i < 4 { + v, w = uint16(x1Lo>>(i*16)), uint16(x2Lo>>(i*16)) + } else { + v, w = uint16(x1hi>>((i-4)*16)), uint16(x2hi>>((i-4)*16)) + } + + var uv uint64 + if op.B3 { // signed + if subbed := int64(int16(v)) - int64(int16(w)); subbed < math.MinInt16 { + uv = uint64(uint16(0x8000)) + } else if subbed > math.MaxInt16 { + uv = uint64(uint16(0x7fff)) + } else { + uv = uint64(uint16(int16(subbed))) + } + } else { + if subbed := int64(v) - int64(w); subbed < 0 { + uv = uint64(uint16(0)) + } else if subbed > math.MaxUint16 { + uv = uint64(uint16(0xffff)) + } else { + uv = uint64(uint16(subbed)) + } + } + + if i < 4 { + retLo |= uv << (i * 16) + } else { + retHi |= uv << ((i - 4) * 16) + } + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Mul: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + switch op.B1 { + case shapeI16x8: + retHi = uint64(uint16(x1hi)*uint16(x2hi)) | (uint64(uint16(x1hi>>16)*uint16(x2hi>>16)) << 16) | + (uint64(uint16(x1hi>>32)*uint16(x2hi>>32)) << 32) | (uint64(uint16(x1hi>>48)*uint16(x2hi>>48)) << 48) + retLo = uint64(uint16(x1lo)*uint16(x2lo)) | (uint64(uint16(x1lo>>16)*uint16(x2lo>>16)) << 16) | + (uint64(uint16(x1lo>>32)*uint16(x2lo>>32)) << 32) | (uint64(uint16(x1lo>>48)*uint16(x2lo>>48)) << 48) + case shapeI32x4: + retHi = uint64(uint32(x1hi)*uint32(x2hi)) | (uint64(uint32(x1hi>>32)*uint32(x2hi>>32)) << 32) + retLo = uint64(uint32(x1lo)*uint32(x2lo)) | (uint64(uint32(x1lo>>32)*uint32(x2lo>>32)) << 32) + case shapeI64x2: + retHi = x1hi * x2hi + retLo = x1lo * x2lo + case shapeF32x4: + retHi = mulFloat32bits(uint32(x1hi), uint32(x2hi)) | mulFloat32bits(uint32(x1hi>>32), uint32(x2hi>>32))<<32 + retLo = mulFloat32bits(uint32(x1lo), uint32(x2lo)) | mulFloat32bits(uint32(x1lo>>32), uint32(x2lo>>32))<<32 + case shapeF64x2: + retHi = math.Float64bits(math.Float64frombits(x1hi) * math.Float64frombits(x2hi)) + retLo = math.Float64bits(math.Float64frombits(x1lo) * math.Float64frombits(x2lo)) + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Div: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + if op.B1 == shapeF64x2 { + retHi = math.Float64bits(math.Float64frombits(x1hi) / math.Float64frombits(x2hi)) + retLo = math.Float64bits(math.Float64frombits(x1lo) / math.Float64frombits(x2lo)) + } else { + retHi = divFloat32bits(uint32(x1hi), uint32(x2hi)) | divFloat32bits(uint32(x1hi>>32), uint32(x2hi>>32))<<32 + retLo = divFloat32bits(uint32(x1lo), uint32(x2lo)) | divFloat32bits(uint32(x1lo>>32), uint32(x2lo>>32))<<32 + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Neg: + hi, lo := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + lo = uint64(-byte(lo)) | (uint64(-byte(lo>>8)) << 8) | + (uint64(-byte(lo>>16)) << 16) | (uint64(-byte(lo>>24)) << 24) | + (uint64(-byte(lo>>32)) << 32) | (uint64(-byte(lo>>40)) << 40) | + (uint64(-byte(lo>>48)) << 48) | (uint64(-byte(lo>>56)) << 56) + hi = uint64(-byte(hi)) | (uint64(-byte(hi>>8)) << 8) | + (uint64(-byte(hi>>16)) << 16) | (uint64(-byte(hi>>24)) << 24) | + (uint64(-byte(hi>>32)) << 32) | (uint64(-byte(hi>>40)) << 40) | + (uint64(-byte(hi>>48)) << 48) | (uint64(-byte(hi>>56)) << 56) + case shapeI16x8: + hi = uint64(-uint16(hi)) | (uint64(-uint16(hi>>16)) << 16) | + (uint64(-uint16(hi>>32)) << 32) | (uint64(-uint16(hi>>48)) << 48) + lo = uint64(-uint16(lo)) | (uint64(-uint16(lo>>16)) << 16) | + (uint64(-uint16(lo>>32)) << 32) | (uint64(-uint16(lo>>48)) << 48) + case shapeI32x4: + hi = uint64(-uint32(hi)) | (uint64(-uint32(hi>>32)) << 32) + lo = uint64(-uint32(lo)) | (uint64(-uint32(lo>>32)) << 32) + case shapeI64x2: + hi = -hi + lo = -lo + case shapeF32x4: + hi = uint64(math.Float32bits(-math.Float32frombits(uint32(hi)))) | + (uint64(math.Float32bits(-math.Float32frombits(uint32(hi>>32)))) << 32) + lo = uint64(math.Float32bits(-math.Float32frombits(uint32(lo)))) | + (uint64(math.Float32bits(-math.Float32frombits(uint32(lo>>32)))) << 32) + case shapeF64x2: + hi = math.Float64bits(-math.Float64frombits(hi)) + lo = math.Float64bits(-math.Float64frombits(lo)) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Sqrt: + hi, lo := ce.popValue(), ce.popValue() + if op.B1 == shapeF64x2 { + hi = math.Float64bits(math.Sqrt(math.Float64frombits(hi))) + lo = math.Float64bits(math.Sqrt(math.Float64frombits(lo))) + } else { + hi = uint64(math.Float32bits(float32(math.Sqrt(float64(math.Float32frombits(uint32(hi))))))) | + (uint64(math.Float32bits(float32(math.Sqrt(float64(math.Float32frombits(uint32(hi>>32))))))) << 32) + lo = uint64(math.Float32bits(float32(math.Sqrt(float64(math.Float32frombits(uint32(lo))))))) | + (uint64(math.Float32bits(float32(math.Sqrt(float64(math.Float32frombits(uint32(lo>>32))))))) << 32) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Abs: + hi, lo := ce.popValue(), ce.popValue() + switch op.B1 { + case shapeI8x16: + lo = uint64(i8Abs(byte(lo))) | (uint64(i8Abs(byte(lo>>8))) << 8) | + (uint64(i8Abs(byte(lo>>16))) << 16) | (uint64(i8Abs(byte(lo>>24))) << 24) | + (uint64(i8Abs(byte(lo>>32))) << 32) | (uint64(i8Abs(byte(lo>>40))) << 40) | + (uint64(i8Abs(byte(lo>>48))) << 48) | (uint64(i8Abs(byte(lo>>56))) << 56) + hi = uint64(i8Abs(byte(hi))) | (uint64(i8Abs(byte(hi>>8))) << 8) | + (uint64(i8Abs(byte(hi>>16))) << 16) | (uint64(i8Abs(byte(hi>>24))) << 24) | + (uint64(i8Abs(byte(hi>>32))) << 32) | (uint64(i8Abs(byte(hi>>40))) << 40) | + (uint64(i8Abs(byte(hi>>48))) << 48) | (uint64(i8Abs(byte(hi>>56))) << 56) + case shapeI16x8: + hi = uint64(i16Abs(uint16(hi))) | (uint64(i16Abs(uint16(hi>>16))) << 16) | + (uint64(i16Abs(uint16(hi>>32))) << 32) | (uint64(i16Abs(uint16(hi>>48))) << 48) + lo = uint64(i16Abs(uint16(lo))) | (uint64(i16Abs(uint16(lo>>16))) << 16) | + (uint64(i16Abs(uint16(lo>>32))) << 32) | (uint64(i16Abs(uint16(lo>>48))) << 48) + case shapeI32x4: + hi = uint64(i32Abs(uint32(hi))) | (uint64(i32Abs(uint32(hi>>32))) << 32) + lo = uint64(i32Abs(uint32(lo))) | (uint64(i32Abs(uint32(lo>>32))) << 32) + case shapeI64x2: + if int64(hi) < 0 { + hi = -hi + } + if int64(lo) < 0 { + lo = -lo + } + case shapeF32x4: + hi = hi &^ (1<<31 | 1<<63) + lo = lo &^ (1<<31 | 1<<63) + case shapeF64x2: + hi = hi &^ (1 << 63) + lo = lo &^ (1 << 63) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Popcnt: + hi, lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + for i := 0; i < 16; i++ { + var v byte + if i < 8 { + v = byte(lo >> (i * 8)) + } else { + v = byte(hi >> ((i - 8) * 8)) + } + + var cnt uint64 + for i := 0; i < 8; i++ { + if (v>>i)&0b1 != 0 { + cnt++ + } + } + + if i < 8 { + retLo |= cnt << (i * 8) + } else { + retHi |= cnt << ((i - 8) * 8) + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Min: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + switch op.B1 { + case shapeI8x16: + if op.B3 { // signed + retLo = uint64(i8MinS(uint8(x1lo>>8), uint8(x2lo>>8)))<<8 | uint64(i8MinS(uint8(x1lo), uint8(x2lo))) | + uint64(i8MinS(uint8(x1lo>>24), uint8(x2lo>>24)))<<24 | uint64(i8MinS(uint8(x1lo>>16), uint8(x2lo>>16)))<<16 | + uint64(i8MinS(uint8(x1lo>>40), uint8(x2lo>>40)))<<40 | uint64(i8MinS(uint8(x1lo>>32), uint8(x2lo>>32)))<<32 | + uint64(i8MinS(uint8(x1lo>>56), uint8(x2lo>>56)))<<56 | uint64(i8MinS(uint8(x1lo>>48), uint8(x2lo>>48)))<<48 + retHi = uint64(i8MinS(uint8(x1hi>>8), uint8(x2hi>>8)))<<8 | uint64(i8MinS(uint8(x1hi), uint8(x2hi))) | + uint64(i8MinS(uint8(x1hi>>24), uint8(x2hi>>24)))<<24 | uint64(i8MinS(uint8(x1hi>>16), uint8(x2hi>>16)))<<16 | + uint64(i8MinS(uint8(x1hi>>40), uint8(x2hi>>40)))<<40 | uint64(i8MinS(uint8(x1hi>>32), uint8(x2hi>>32)))<<32 | + uint64(i8MinS(uint8(x1hi>>56), uint8(x2hi>>56)))<<56 | uint64(i8MinS(uint8(x1hi>>48), uint8(x2hi>>48)))<<48 + } else { + retLo = uint64(i8MinU(uint8(x1lo>>8), uint8(x2lo>>8)))<<8 | uint64(i8MinU(uint8(x1lo), uint8(x2lo))) | + uint64(i8MinU(uint8(x1lo>>24), uint8(x2lo>>24)))<<24 | uint64(i8MinU(uint8(x1lo>>16), uint8(x2lo>>16)))<<16 | + uint64(i8MinU(uint8(x1lo>>40), uint8(x2lo>>40)))<<40 | uint64(i8MinU(uint8(x1lo>>32), uint8(x2lo>>32)))<<32 | + uint64(i8MinU(uint8(x1lo>>56), uint8(x2lo>>56)))<<56 | uint64(i8MinU(uint8(x1lo>>48), uint8(x2lo>>48)))<<48 + retHi = uint64(i8MinU(uint8(x1hi>>8), uint8(x2hi>>8)))<<8 | uint64(i8MinU(uint8(x1hi), uint8(x2hi))) | + uint64(i8MinU(uint8(x1hi>>24), uint8(x2hi>>24)))<<24 | uint64(i8MinU(uint8(x1hi>>16), uint8(x2hi>>16)))<<16 | + uint64(i8MinU(uint8(x1hi>>40), uint8(x2hi>>40)))<<40 | uint64(i8MinU(uint8(x1hi>>32), uint8(x2hi>>32)))<<32 | + uint64(i8MinU(uint8(x1hi>>56), uint8(x2hi>>56)))<<56 | uint64(i8MinU(uint8(x1hi>>48), uint8(x2hi>>48)))<<48 + } + case shapeI16x8: + if op.B3 { // signed + retLo = uint64(i16MinS(uint16(x1lo), uint16(x2lo))) | + uint64(i16MinS(uint16(x1lo>>16), uint16(x2lo>>16)))<<16 | + uint64(i16MinS(uint16(x1lo>>32), uint16(x2lo>>32)))<<32 | + uint64(i16MinS(uint16(x1lo>>48), uint16(x2lo>>48)))<<48 + retHi = uint64(i16MinS(uint16(x1hi), uint16(x2hi))) | + uint64(i16MinS(uint16(x1hi>>16), uint16(x2hi>>16)))<<16 | + uint64(i16MinS(uint16(x1hi>>32), uint16(x2hi>>32)))<<32 | + uint64(i16MinS(uint16(x1hi>>48), uint16(x2hi>>48)))<<48 + } else { + retLo = uint64(i16MinU(uint16(x1lo), uint16(x2lo))) | + uint64(i16MinU(uint16(x1lo>>16), uint16(x2lo>>16)))<<16 | + uint64(i16MinU(uint16(x1lo>>32), uint16(x2lo>>32)))<<32 | + uint64(i16MinU(uint16(x1lo>>48), uint16(x2lo>>48)))<<48 + retHi = uint64(i16MinU(uint16(x1hi), uint16(x2hi))) | + uint64(i16MinU(uint16(x1hi>>16), uint16(x2hi>>16)))<<16 | + uint64(i16MinU(uint16(x1hi>>32), uint16(x2hi>>32)))<<32 | + uint64(i16MinU(uint16(x1hi>>48), uint16(x2hi>>48)))<<48 + } + case shapeI32x4: + if op.B3 { // signed + retLo = uint64(i32MinS(uint32(x1lo), uint32(x2lo))) | + uint64(i32MinS(uint32(x1lo>>32), uint32(x2lo>>32)))<<32 + retHi = uint64(i32MinS(uint32(x1hi), uint32(x2hi))) | + uint64(i32MinS(uint32(x1hi>>32), uint32(x2hi>>32)))<<32 + } else { + retLo = uint64(i32MinU(uint32(x1lo), uint32(x2lo))) | + uint64(i32MinU(uint32(x1lo>>32), uint32(x2lo>>32)))<<32 + retHi = uint64(i32MinU(uint32(x1hi), uint32(x2hi))) | + uint64(i32MinU(uint32(x1hi>>32), uint32(x2hi>>32)))<<32 + } + case shapeF32x4: + retHi = wasmCompatMin32bits(uint32(x1hi), uint32(x2hi)) | + wasmCompatMin32bits(uint32(x1hi>>32), uint32(x2hi>>32))<<32 + retLo = wasmCompatMin32bits(uint32(x1lo), uint32(x2lo)) | + wasmCompatMin32bits(uint32(x1lo>>32), uint32(x2lo>>32))<<32 + case shapeF64x2: + retHi = math.Float64bits(moremath.WasmCompatMin64( + math.Float64frombits(x1hi), + math.Float64frombits(x2hi), + )) + retLo = math.Float64bits(moremath.WasmCompatMin64( + math.Float64frombits(x1lo), + math.Float64frombits(x2lo), + )) + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Max: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + switch op.B1 { + case shapeI8x16: + if op.B3 { // signed + retLo = uint64(i8MaxS(uint8(x1lo>>8), uint8(x2lo>>8)))<<8 | uint64(i8MaxS(uint8(x1lo), uint8(x2lo))) | + uint64(i8MaxS(uint8(x1lo>>24), uint8(x2lo>>24)))<<24 | uint64(i8MaxS(uint8(x1lo>>16), uint8(x2lo>>16)))<<16 | + uint64(i8MaxS(uint8(x1lo>>40), uint8(x2lo>>40)))<<40 | uint64(i8MaxS(uint8(x1lo>>32), uint8(x2lo>>32)))<<32 | + uint64(i8MaxS(uint8(x1lo>>56), uint8(x2lo>>56)))<<56 | uint64(i8MaxS(uint8(x1lo>>48), uint8(x2lo>>48)))<<48 + retHi = uint64(i8MaxS(uint8(x1hi>>8), uint8(x2hi>>8)))<<8 | uint64(i8MaxS(uint8(x1hi), uint8(x2hi))) | + uint64(i8MaxS(uint8(x1hi>>24), uint8(x2hi>>24)))<<24 | uint64(i8MaxS(uint8(x1hi>>16), uint8(x2hi>>16)))<<16 | + uint64(i8MaxS(uint8(x1hi>>40), uint8(x2hi>>40)))<<40 | uint64(i8MaxS(uint8(x1hi>>32), uint8(x2hi>>32)))<<32 | + uint64(i8MaxS(uint8(x1hi>>56), uint8(x2hi>>56)))<<56 | uint64(i8MaxS(uint8(x1hi>>48), uint8(x2hi>>48)))<<48 + } else { + retLo = uint64(i8MaxU(uint8(x1lo>>8), uint8(x2lo>>8)))<<8 | uint64(i8MaxU(uint8(x1lo), uint8(x2lo))) | + uint64(i8MaxU(uint8(x1lo>>24), uint8(x2lo>>24)))<<24 | uint64(i8MaxU(uint8(x1lo>>16), uint8(x2lo>>16)))<<16 | + uint64(i8MaxU(uint8(x1lo>>40), uint8(x2lo>>40)))<<40 | uint64(i8MaxU(uint8(x1lo>>32), uint8(x2lo>>32)))<<32 | + uint64(i8MaxU(uint8(x1lo>>56), uint8(x2lo>>56)))<<56 | uint64(i8MaxU(uint8(x1lo>>48), uint8(x2lo>>48)))<<48 + retHi = uint64(i8MaxU(uint8(x1hi>>8), uint8(x2hi>>8)))<<8 | uint64(i8MaxU(uint8(x1hi), uint8(x2hi))) | + uint64(i8MaxU(uint8(x1hi>>24), uint8(x2hi>>24)))<<24 | uint64(i8MaxU(uint8(x1hi>>16), uint8(x2hi>>16)))<<16 | + uint64(i8MaxU(uint8(x1hi>>40), uint8(x2hi>>40)))<<40 | uint64(i8MaxU(uint8(x1hi>>32), uint8(x2hi>>32)))<<32 | + uint64(i8MaxU(uint8(x1hi>>56), uint8(x2hi>>56)))<<56 | uint64(i8MaxU(uint8(x1hi>>48), uint8(x2hi>>48)))<<48 + } + case shapeI16x8: + if op.B3 { // signed + retLo = uint64(i16MaxS(uint16(x1lo), uint16(x2lo))) | + uint64(i16MaxS(uint16(x1lo>>16), uint16(x2lo>>16)))<<16 | + uint64(i16MaxS(uint16(x1lo>>32), uint16(x2lo>>32)))<<32 | + uint64(i16MaxS(uint16(x1lo>>48), uint16(x2lo>>48)))<<48 + retHi = uint64(i16MaxS(uint16(x1hi), uint16(x2hi))) | + uint64(i16MaxS(uint16(x1hi>>16), uint16(x2hi>>16)))<<16 | + uint64(i16MaxS(uint16(x1hi>>32), uint16(x2hi>>32)))<<32 | + uint64(i16MaxS(uint16(x1hi>>48), uint16(x2hi>>48)))<<48 + } else { + retLo = uint64(i16MaxU(uint16(x1lo), uint16(x2lo))) | + uint64(i16MaxU(uint16(x1lo>>16), uint16(x2lo>>16)))<<16 | + uint64(i16MaxU(uint16(x1lo>>32), uint16(x2lo>>32)))<<32 | + uint64(i16MaxU(uint16(x1lo>>48), uint16(x2lo>>48)))<<48 + retHi = uint64(i16MaxU(uint16(x1hi), uint16(x2hi))) | + uint64(i16MaxU(uint16(x1hi>>16), uint16(x2hi>>16)))<<16 | + uint64(i16MaxU(uint16(x1hi>>32), uint16(x2hi>>32)))<<32 | + uint64(i16MaxU(uint16(x1hi>>48), uint16(x2hi>>48)))<<48 + } + case shapeI32x4: + if op.B3 { // signed + retLo = uint64(i32MaxS(uint32(x1lo), uint32(x2lo))) | + uint64(i32MaxS(uint32(x1lo>>32), uint32(x2lo>>32)))<<32 + retHi = uint64(i32MaxS(uint32(x1hi), uint32(x2hi))) | + uint64(i32MaxS(uint32(x1hi>>32), uint32(x2hi>>32)))<<32 + } else { + retLo = uint64(i32MaxU(uint32(x1lo), uint32(x2lo))) | + uint64(i32MaxU(uint32(x1lo>>32), uint32(x2lo>>32)))<<32 + retHi = uint64(i32MaxU(uint32(x1hi), uint32(x2hi))) | + uint64(i32MaxU(uint32(x1hi>>32), uint32(x2hi>>32)))<<32 + } + case shapeF32x4: + retHi = wasmCompatMax32bits(uint32(x1hi), uint32(x2hi)) | + wasmCompatMax32bits(uint32(x1hi>>32), uint32(x2hi>>32))<<32 + retLo = wasmCompatMax32bits(uint32(x1lo), uint32(x2lo)) | + wasmCompatMax32bits(uint32(x1lo>>32), uint32(x2lo>>32))<<32 + case shapeF64x2: + retHi = math.Float64bits(moremath.WasmCompatMax64( + math.Float64frombits(x1hi), + math.Float64frombits(x2hi), + )) + retLo = math.Float64bits(moremath.WasmCompatMax64( + math.Float64frombits(x1lo), + math.Float64frombits(x2lo), + )) + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128AvgrU: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + switch op.B1 { + case shapeI8x16: + retLo = uint64(i8RoundingAverage(uint8(x1lo>>8), uint8(x2lo>>8)))<<8 | uint64(i8RoundingAverage(uint8(x1lo), uint8(x2lo))) | + uint64(i8RoundingAverage(uint8(x1lo>>24), uint8(x2lo>>24)))<<24 | uint64(i8RoundingAverage(uint8(x1lo>>16), uint8(x2lo>>16)))<<16 | + uint64(i8RoundingAverage(uint8(x1lo>>40), uint8(x2lo>>40)))<<40 | uint64(i8RoundingAverage(uint8(x1lo>>32), uint8(x2lo>>32)))<<32 | + uint64(i8RoundingAverage(uint8(x1lo>>56), uint8(x2lo>>56)))<<56 | uint64(i8RoundingAverage(uint8(x1lo>>48), uint8(x2lo>>48)))<<48 + retHi = uint64(i8RoundingAverage(uint8(x1hi>>8), uint8(x2hi>>8)))<<8 | uint64(i8RoundingAverage(uint8(x1hi), uint8(x2hi))) | + uint64(i8RoundingAverage(uint8(x1hi>>24), uint8(x2hi>>24)))<<24 | uint64(i8RoundingAverage(uint8(x1hi>>16), uint8(x2hi>>16)))<<16 | + uint64(i8RoundingAverage(uint8(x1hi>>40), uint8(x2hi>>40)))<<40 | uint64(i8RoundingAverage(uint8(x1hi>>32), uint8(x2hi>>32)))<<32 | + uint64(i8RoundingAverage(uint8(x1hi>>56), uint8(x2hi>>56)))<<56 | uint64(i8RoundingAverage(uint8(x1hi>>48), uint8(x2hi>>48)))<<48 + case shapeI16x8: + retLo = uint64(i16RoundingAverage(uint16(x1lo), uint16(x2lo))) | + uint64(i16RoundingAverage(uint16(x1lo>>16), uint16(x2lo>>16)))<<16 | + uint64(i16RoundingAverage(uint16(x1lo>>32), uint16(x2lo>>32)))<<32 | + uint64(i16RoundingAverage(uint16(x1lo>>48), uint16(x2lo>>48)))<<48 + retHi = uint64(i16RoundingAverage(uint16(x1hi), uint16(x2hi))) | + uint64(i16RoundingAverage(uint16(x1hi>>16), uint16(x2hi>>16)))<<16 | + uint64(i16RoundingAverage(uint16(x1hi>>32), uint16(x2hi>>32)))<<32 | + uint64(i16RoundingAverage(uint16(x1hi>>48), uint16(x2hi>>48)))<<48 + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Pmin: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + if op.B1 == shapeF32x4 { + if flt32(math.Float32frombits(uint32(x2lo)), math.Float32frombits(uint32(x1lo))) { + retLo = x2lo & 0x00000000_ffffffff + } else { + retLo = x1lo & 0x00000000_ffffffff + } + if flt32(math.Float32frombits(uint32(x2lo>>32)), math.Float32frombits(uint32(x1lo>>32))) { + retLo |= x2lo & 0xffffffff_00000000 + } else { + retLo |= x1lo & 0xffffffff_00000000 + } + if flt32(math.Float32frombits(uint32(x2hi)), math.Float32frombits(uint32(x1hi))) { + retHi = x2hi & 0x00000000_ffffffff + } else { + retHi = x1hi & 0x00000000_ffffffff + } + if flt32(math.Float32frombits(uint32(x2hi>>32)), math.Float32frombits(uint32(x1hi>>32))) { + retHi |= x2hi & 0xffffffff_00000000 + } else { + retHi |= x1hi & 0xffffffff_00000000 + } + } else { + if flt64(math.Float64frombits(x2lo), math.Float64frombits(x1lo)) { + retLo = x2lo + } else { + retLo = x1lo + } + if flt64(math.Float64frombits(x2hi), math.Float64frombits(x1hi)) { + retHi = x2hi + } else { + retHi = x1hi + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Pmax: + x2hi, x2lo := ce.popValue(), ce.popValue() + x1hi, x1lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + if op.B1 == shapeF32x4 { + if flt32(math.Float32frombits(uint32(x1lo)), math.Float32frombits(uint32(x2lo))) { + retLo = x2lo & 0x00000000_ffffffff + } else { + retLo = x1lo & 0x00000000_ffffffff + } + if flt32(math.Float32frombits(uint32(x1lo>>32)), math.Float32frombits(uint32(x2lo>>32))) { + retLo |= x2lo & 0xffffffff_00000000 + } else { + retLo |= x1lo & 0xffffffff_00000000 + } + if flt32(math.Float32frombits(uint32(x1hi)), math.Float32frombits(uint32(x2hi))) { + retHi = x2hi & 0x00000000_ffffffff + } else { + retHi = x1hi & 0x00000000_ffffffff + } + if flt32(math.Float32frombits(uint32(x1hi>>32)), math.Float32frombits(uint32(x2hi>>32))) { + retHi |= x2hi & 0xffffffff_00000000 + } else { + retHi |= x1hi & 0xffffffff_00000000 + } + } else { + if flt64(math.Float64frombits(x1lo), math.Float64frombits(x2lo)) { + retLo = x2lo + } else { + retLo = x1lo + } + if flt64(math.Float64frombits(x1hi), math.Float64frombits(x2hi)) { + retHi = x2hi + } else { + retHi = x1hi + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Ceil: + hi, lo := ce.popValue(), ce.popValue() + if op.B1 == shapeF32x4 { + lo = uint64(math.Float32bits(moremath.WasmCompatCeilF32(math.Float32frombits(uint32(lo))))) | + (uint64(math.Float32bits(moremath.WasmCompatCeilF32(math.Float32frombits(uint32(lo>>32))))) << 32) + hi = uint64(math.Float32bits(moremath.WasmCompatCeilF32(math.Float32frombits(uint32(hi))))) | + (uint64(math.Float32bits(moremath.WasmCompatCeilF32(math.Float32frombits(uint32(hi>>32))))) << 32) + } else { + lo = math.Float64bits(moremath.WasmCompatCeilF64(math.Float64frombits(lo))) + hi = math.Float64bits(moremath.WasmCompatCeilF64(math.Float64frombits(hi))) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Floor: + hi, lo := ce.popValue(), ce.popValue() + if op.B1 == shapeF32x4 { + lo = uint64(math.Float32bits(moremath.WasmCompatFloorF32(math.Float32frombits(uint32(lo))))) | + (uint64(math.Float32bits(moremath.WasmCompatFloorF32(math.Float32frombits(uint32(lo>>32))))) << 32) + hi = uint64(math.Float32bits(moremath.WasmCompatFloorF32(math.Float32frombits(uint32(hi))))) | + (uint64(math.Float32bits(moremath.WasmCompatFloorF32(math.Float32frombits(uint32(hi>>32))))) << 32) + } else { + lo = math.Float64bits(moremath.WasmCompatFloorF64(math.Float64frombits(lo))) + hi = math.Float64bits(moremath.WasmCompatFloorF64(math.Float64frombits(hi))) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Trunc: + hi, lo := ce.popValue(), ce.popValue() + if op.B1 == shapeF32x4 { + lo = uint64(math.Float32bits(moremath.WasmCompatTruncF32(math.Float32frombits(uint32(lo))))) | + (uint64(math.Float32bits(moremath.WasmCompatTruncF32(math.Float32frombits(uint32(lo>>32))))) << 32) + hi = uint64(math.Float32bits(moremath.WasmCompatTruncF32(math.Float32frombits(uint32(hi))))) | + (uint64(math.Float32bits(moremath.WasmCompatTruncF32(math.Float32frombits(uint32(hi>>32))))) << 32) + } else { + lo = math.Float64bits(moremath.WasmCompatTruncF64(math.Float64frombits(lo))) + hi = math.Float64bits(moremath.WasmCompatTruncF64(math.Float64frombits(hi))) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Nearest: + hi, lo := ce.popValue(), ce.popValue() + if op.B1 == shapeF32x4 { + lo = uint64(math.Float32bits(moremath.WasmCompatNearestF32(math.Float32frombits(uint32(lo))))) | + (uint64(math.Float32bits(moremath.WasmCompatNearestF32(math.Float32frombits(uint32(lo>>32))))) << 32) + hi = uint64(math.Float32bits(moremath.WasmCompatNearestF32(math.Float32frombits(uint32(hi))))) | + (uint64(math.Float32bits(moremath.WasmCompatNearestF32(math.Float32frombits(uint32(hi>>32))))) << 32) + } else { + lo = math.Float64bits(moremath.WasmCompatNearestF64(math.Float64frombits(lo))) + hi = math.Float64bits(moremath.WasmCompatNearestF64(math.Float64frombits(hi))) + } + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128Extend: + hi, lo := ce.popValue(), ce.popValue() + var origin uint64 + if op.B3 { // use lower 64 bits + origin = lo + } else { + origin = hi + } + + signed := op.B2 == 1 + + var retHi, retLo uint64 + switch op.B1 { + case shapeI8x16: + for i := 0; i < 8; i++ { + v8 := byte(origin >> (i * 8)) + + var v16 uint16 + if signed { + v16 = uint16(int8(v8)) + } else { + v16 = uint16(v8) + } + + if i < 4 { + retLo |= uint64(v16) << (i * 16) + } else { + retHi |= uint64(v16) << ((i - 4) * 16) + } + } + case shapeI16x8: + for i := 0; i < 4; i++ { + v16 := uint16(origin >> (i * 16)) + + var v32 uint32 + if signed { + v32 = uint32(int16(v16)) + } else { + v32 = uint32(v16) + } + + if i < 2 { + retLo |= uint64(v32) << (i * 32) + } else { + retHi |= uint64(v32) << ((i - 2) * 32) + } + } + case shapeI32x4: + v32Lo := uint32(origin) + v32Hi := uint32(origin >> 32) + if signed { + retLo = uint64(int32(v32Lo)) + retHi = uint64(int32(v32Hi)) + } else { + retLo = uint64(v32Lo) + retHi = uint64(v32Hi) + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128ExtMul: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + var x1, x2 uint64 + if op.B3 { // use lower 64 bits + x1, x2 = x1Lo, x2Lo + } else { + x1, x2 = x1Hi, x2Hi + } + + signed := op.B2 == 1 + + var retLo, retHi uint64 + switch op.B1 { + case shapeI8x16: + for i := 0; i < 8; i++ { + v1, v2 := byte(x1>>(i*8)), byte(x2>>(i*8)) + + var v16 uint16 + if signed { + v16 = uint16(int16(int8(v1)) * int16(int8(v2))) + } else { + v16 = uint16(v1) * uint16(v2) + } + + if i < 4 { + retLo |= uint64(v16) << (i * 16) + } else { + retHi |= uint64(v16) << ((i - 4) * 16) + } + } + case shapeI16x8: + for i := 0; i < 4; i++ { + v1, v2 := uint16(x1>>(i*16)), uint16(x2>>(i*16)) + + var v32 uint32 + if signed { + v32 = uint32(int32(int16(v1)) * int32(int16(v2))) + } else { + v32 = uint32(v1) * uint32(v2) + } + + if i < 2 { + retLo |= uint64(v32) << (i * 32) + } else { + retHi |= uint64(v32) << ((i - 2) * 32) + } + } + case shapeI32x4: + v1Lo, v2Lo := uint32(x1), uint32(x2) + v1Hi, v2Hi := uint32(x1>>32), uint32(x2>>32) + if signed { + retLo = uint64(int64(int32(v1Lo)) * int64(int32(v2Lo))) + retHi = uint64(int64(int32(v1Hi)) * int64(int32(v2Hi))) + } else { + retLo = uint64(v1Lo) * uint64(v2Lo) + retHi = uint64(v1Hi) * uint64(v2Hi) + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Q15mulrSatS: + x2hi, x2Lo := ce.popValue(), ce.popValue() + x1hi, x1Lo := ce.popValue(), ce.popValue() + var retLo, retHi uint64 + for i := 0; i < 8; i++ { + var v, w int16 + if i < 4 { + v, w = int16(uint16(x1Lo>>(i*16))), int16(uint16(x2Lo>>(i*16))) + } else { + v, w = int16(uint16(x1hi>>((i-4)*16))), int16(uint16(x2hi>>((i-4)*16))) + } + + var uv uint64 + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-q-format-rounding-multiplication + if calc := ((int32(v) * int32(w)) + 0x4000) >> 15; calc < math.MinInt16 { + uv = uint64(uint16(0x8000)) + } else if calc > math.MaxInt16 { + uv = uint64(uint16(0x7fff)) + } else { + uv = uint64(uint16(int16(calc))) + } + + if i < 4 { + retLo |= uv << (i * 16) + } else { + retHi |= uv << ((i - 4) * 16) + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128ExtAddPairwise: + hi, lo := ce.popValue(), ce.popValue() + + signed := op.B3 + + var retLo, retHi uint64 + switch op.B1 { + case shapeI8x16: + for i := 0; i < 8; i++ { + var v1, v2 byte + if i < 4 { + v1, v2 = byte(lo>>((i*2)*8)), byte(lo>>((i*2+1)*8)) + } else { + v1, v2 = byte(hi>>(((i-4)*2)*8)), byte(hi>>(((i-4)*2+1)*8)) + } + + var v16 uint16 + if signed { + v16 = uint16(int16(int8(v1)) + int16(int8(v2))) + } else { + v16 = uint16(v1) + uint16(v2) + } + + if i < 4 { + retLo |= uint64(v16) << (i * 16) + } else { + retHi |= uint64(v16) << ((i - 4) * 16) + } + } + case shapeI16x8: + for i := 0; i < 4; i++ { + var v1, v2 uint16 + if i < 2 { + v1, v2 = uint16(lo>>((i*2)*16)), uint16(lo>>((i*2+1)*16)) + } else { + v1, v2 = uint16(hi>>(((i-2)*2)*16)), uint16(hi>>(((i-2)*2+1)*16)) + } + + var v32 uint32 + if signed { + v32 = uint32(int32(int16(v1)) + int32(int16(v2))) + } else { + v32 = uint32(v1) + uint32(v2) + } + + if i < 2 { + retLo |= uint64(v32) << (i * 32) + } else { + retHi |= uint64(v32) << ((i - 2) * 32) + } + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128FloatPromote: + _, toPromote := ce.popValue(), ce.popValue() + ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(toPromote))))) + ce.pushValue(math.Float64bits(float64(math.Float32frombits(uint32(toPromote >> 32))))) + frame.pc++ + case operationKindV128FloatDemote: + hi, lo := ce.popValue(), ce.popValue() + ce.pushValue( + uint64(math.Float32bits(float32(math.Float64frombits(lo)))) | + (uint64(math.Float32bits(float32(math.Float64frombits(hi)))) << 32), + ) + ce.pushValue(0) + frame.pc++ + case operationKindV128FConvertFromI: + hi, lo := ce.popValue(), ce.popValue() + v1, v2, v3, v4 := uint32(lo), uint32(lo>>32), uint32(hi), uint32(hi>>32) + signed := op.B3 + + var retLo, retHi uint64 + switch op.B1 { // Destination shape. + case shapeF32x4: // f32x4 from signed/unsigned i32x4 + if signed { + retLo = uint64(math.Float32bits(float32(int32(v1)))) | + (uint64(math.Float32bits(float32(int32(v2)))) << 32) + retHi = uint64(math.Float32bits(float32(int32(v3)))) | + (uint64(math.Float32bits(float32(int32(v4)))) << 32) + } else { + retLo = uint64(math.Float32bits(float32(v1))) | + (uint64(math.Float32bits(float32(v2))) << 32) + retHi = uint64(math.Float32bits(float32(v3))) | + (uint64(math.Float32bits(float32(v4))) << 32) + } + case shapeF64x2: // f64x2 from signed/unsigned i32x4 + if signed { + retLo, retHi = math.Float64bits(float64(int32(v1))), math.Float64bits(float64(int32(v2))) + } else { + retLo, retHi = math.Float64bits(float64(v1)), math.Float64bits(float64(v2)) + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Narrow: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + signed := op.B3 + + var retLo, retHi uint64 + switch op.B1 { + case shapeI16x8: // signed/unsigned i16x8 to i8x16 + for i := 0; i < 8; i++ { + var v16 uint16 + if i < 4 { + v16 = uint16(x1Lo >> (i * 16)) + } else { + v16 = uint16(x1Hi >> ((i - 4) * 16)) + } + + var v byte + if signed { + if s := int16(v16); s > math.MaxInt8 { + v = math.MaxInt8 + } else if s < math.MinInt8 { + s = math.MinInt8 + v = byte(s) + } else { + v = byte(v16) + } + } else { + if s := int16(v16); s > math.MaxUint8 { + v = math.MaxUint8 + } else if s < 0 { + v = 0 + } else { + v = byte(v16) + } + } + retLo |= uint64(v) << (i * 8) + } + for i := 0; i < 8; i++ { + var v16 uint16 + if i < 4 { + v16 = uint16(x2Lo >> (i * 16)) + } else { + v16 = uint16(x2Hi >> ((i - 4) * 16)) + } + + var v byte + if signed { + if s := int16(v16); s > math.MaxInt8 { + v = math.MaxInt8 + } else if s < math.MinInt8 { + s = math.MinInt8 + v = byte(s) + } else { + v = byte(v16) + } + } else { + if s := int16(v16); s > math.MaxUint8 { + v = math.MaxUint8 + } else if s < 0 { + v = 0 + } else { + v = byte(v16) + } + } + retHi |= uint64(v) << (i * 8) + } + case shapeI32x4: // signed/unsigned i32x4 to i16x8 + for i := 0; i < 4; i++ { + var v32 uint32 + if i < 2 { + v32 = uint32(x1Lo >> (i * 32)) + } else { + v32 = uint32(x1Hi >> ((i - 2) * 32)) + } + + var v uint16 + if signed { + if s := int32(v32); s > math.MaxInt16 { + v = math.MaxInt16 + } else if s < math.MinInt16 { + s = math.MinInt16 + v = uint16(s) + } else { + v = uint16(v32) + } + } else { + if s := int32(v32); s > math.MaxUint16 { + v = math.MaxUint16 + } else if s < 0 { + v = 0 + } else { + v = uint16(v32) + } + } + retLo |= uint64(v) << (i * 16) + } + + for i := 0; i < 4; i++ { + var v32 uint32 + if i < 2 { + v32 = uint32(x2Lo >> (i * 32)) + } else { + v32 = uint32(x2Hi >> ((i - 2) * 32)) + } + + var v uint16 + if signed { + if s := int32(v32); s > math.MaxInt16 { + v = math.MaxInt16 + } else if s < math.MinInt16 { + s = math.MinInt16 + v = uint16(s) + } else { + v = uint16(v32) + } + } else { + if s := int32(v32); s > math.MaxUint16 { + v = math.MaxUint16 + } else if s < 0 { + v = 0 + } else { + v = uint16(v32) + } + } + retHi |= uint64(v) << (i * 16) + } + } + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindV128Dot: + x2Hi, x2Lo := ce.popValue(), ce.popValue() + x1Hi, x1Lo := ce.popValue(), ce.popValue() + lo, hi := v128Dot(x1Hi, x1Lo, x2Hi, x2Lo) + ce.pushValue(lo) + ce.pushValue(hi) + frame.pc++ + case operationKindV128ITruncSatFromF: + hi, lo := ce.popValue(), ce.popValue() + signed := op.B3 + var retLo, retHi uint64 + + switch op.B1 { + case shapeF32x4: // f32x4 to i32x4 + for i, f64 := range [4]float64{ + math.Trunc(float64(math.Float32frombits(uint32(lo)))), + math.Trunc(float64(math.Float32frombits(uint32(lo >> 32)))), + math.Trunc(float64(math.Float32frombits(uint32(hi)))), + math.Trunc(float64(math.Float32frombits(uint32(hi >> 32)))), + } { + + var v uint32 + if math.IsNaN(f64) { + v = 0 + } else if signed { + if f64 < math.MinInt32 { + f64 = math.MinInt32 + } else if f64 > math.MaxInt32 { + f64 = math.MaxInt32 + } + v = uint32(int32(f64)) + } else { + if f64 < 0 { + f64 = 0 + } else if f64 > math.MaxUint32 { + f64 = math.MaxUint32 + } + v = uint32(f64) + } + + if i < 2 { + retLo |= uint64(v) << (i * 32) + } else { + retHi |= uint64(v) << ((i - 2) * 32) + } + } + + case shapeF64x2: // f64x2 to i32x4 + for i, f := range [2]float64{ + math.Trunc(math.Float64frombits(lo)), + math.Trunc(math.Float64frombits(hi)), + } { + var v uint32 + if math.IsNaN(f) { + v = 0 + } else if signed { + if f < math.MinInt32 { + f = math.MinInt32 + } else if f > math.MaxInt32 { + f = math.MaxInt32 + } + v = uint32(int32(f)) + } else { + if f < 0 { + f = 0 + } else if f > math.MaxUint32 { + f = math.MaxUint32 + } + v = uint32(f) + } + + retLo |= uint64(v) << (i * 32) + } + } + + ce.pushValue(retLo) + ce.pushValue(retHi) + frame.pc++ + case operationKindAtomicMemoryWait: + timeout := int64(ce.popValue()) + exp := ce.popValue() + offset := ce.popMemoryOffset(op) + // Runtime instead of validation error because the spec intends to allow binaries to include + // such instructions as long as they are not executed. + if !memoryInst.Shared { + panic(wasmruntime.ErrRuntimeExpectedSharedMemory) + } + + switch unsignedType(op.B1) { + case unsignedTypeI32: + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + if int(offset) > len(memoryInst.Buffer)-4 { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(memoryInst.Wait32(offset, uint32(exp), timeout, func(mem *wasm.MemoryInstance, offset uint32) uint32 { + mem.Mux.Lock() + defer mem.Mux.Unlock() + value, _ := mem.ReadUint32Le(offset) + return value + })) + case unsignedTypeI64: + if offset%8 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + if int(offset) > len(memoryInst.Buffer)-8 { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(memoryInst.Wait64(offset, exp, timeout, func(mem *wasm.MemoryInstance, offset uint32) uint64 { + mem.Mux.Lock() + defer mem.Mux.Unlock() + value, _ := mem.ReadUint64Le(offset) + return value + })) + } + frame.pc++ + case operationKindAtomicMemoryNotify: + count := ce.popValue() + offset := ce.popMemoryOffset(op) + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + // Just a bounds check + if offset >= memoryInst.Size() { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + res := memoryInst.Notify(offset, uint32(count)) + ce.pushValue(uint64(res)) + frame.pc++ + case operationKindAtomicFence: + // Memory not required for fence only + if memoryInst != nil { + // An empty critical section can be used as a synchronization primitive, which is what + // fence is. Probably, there are no spectests or defined behavior to confirm this yet. + memoryInst.Mux.Lock() + memoryInst.Mux.Unlock() //nolint:staticcheck + } + frame.pc++ + case operationKindAtomicLoad: + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32: + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + val, ok := memoryInst.ReadUint32Le(offset) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(val)) + case unsignedTypeI64: + if offset%8 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + val, ok := memoryInst.ReadUint64Le(offset) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(val) + } + frame.pc++ + case operationKindAtomicLoad8: + offset := ce.popMemoryOffset(op) + memoryInst.Mux.Lock() + val, ok := memoryInst.ReadByte(offset) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(val)) + frame.pc++ + case operationKindAtomicLoad16: + offset := ce.popMemoryOffset(op) + if offset%2 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + val, ok := memoryInst.ReadUint16Le(offset) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + ce.pushValue(uint64(val)) + frame.pc++ + case operationKindAtomicStore: + val := ce.popValue() + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32: + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + ok := memoryInst.WriteUint32Le(offset, uint32(val)) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + case unsignedTypeI64: + if offset%8 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + ok := memoryInst.WriteUint64Le(offset, val) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + } + frame.pc++ + case operationKindAtomicStore8: + val := byte(ce.popValue()) + offset := ce.popMemoryOffset(op) + memoryInst.Mux.Lock() + ok := memoryInst.WriteByte(offset, val) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindAtomicStore16: + val := uint16(ce.popValue()) + offset := ce.popMemoryOffset(op) + if offset%2 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + ok := memoryInst.WriteUint16Le(offset, val) + memoryInst.Mux.Unlock() + if !ok { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + frame.pc++ + case operationKindAtomicRMW: + val := ce.popValue() + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32: + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint32Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + var newVal uint32 + switch atomicArithmeticOp(op.B2) { + case atomicArithmeticOpAdd: + newVal = old + uint32(val) + case atomicArithmeticOpSub: + newVal = old - uint32(val) + case atomicArithmeticOpAnd: + newVal = old & uint32(val) + case atomicArithmeticOpOr: + newVal = old | uint32(val) + case atomicArithmeticOpXor: + newVal = old ^ uint32(val) + case atomicArithmeticOpNop: + newVal = uint32(val) + } + memoryInst.WriteUint32Le(offset, newVal) + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + case unsignedTypeI64: + if offset%8 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint64Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + var newVal uint64 + switch atomicArithmeticOp(op.B2) { + case atomicArithmeticOpAdd: + newVal = old + val + case atomicArithmeticOpSub: + newVal = old - val + case atomicArithmeticOpAnd: + newVal = old & val + case atomicArithmeticOpOr: + newVal = old | val + case atomicArithmeticOpXor: + newVal = old ^ val + case atomicArithmeticOpNop: + newVal = val + } + memoryInst.WriteUint64Le(offset, newVal) + memoryInst.Mux.Unlock() + ce.pushValue(old) + } + frame.pc++ + case operationKindAtomicRMW8: + val := ce.popValue() + offset := ce.popMemoryOffset(op) + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadByte(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + arg := byte(val) + var newVal byte + switch atomicArithmeticOp(op.B2) { + case atomicArithmeticOpAdd: + newVal = old + arg + case atomicArithmeticOpSub: + newVal = old - arg + case atomicArithmeticOpAnd: + newVal = old & arg + case atomicArithmeticOpOr: + newVal = old | arg + case atomicArithmeticOpXor: + newVal = old ^ arg + case atomicArithmeticOpNop: + newVal = arg + } + memoryInst.WriteByte(offset, newVal) + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + frame.pc++ + case operationKindAtomicRMW16: + val := ce.popValue() + offset := ce.popMemoryOffset(op) + if offset%2 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint16Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + arg := uint16(val) + var newVal uint16 + switch atomicArithmeticOp(op.B2) { + case atomicArithmeticOpAdd: + newVal = old + arg + case atomicArithmeticOpSub: + newVal = old - arg + case atomicArithmeticOpAnd: + newVal = old & arg + case atomicArithmeticOpOr: + newVal = old | arg + case atomicArithmeticOpXor: + newVal = old ^ arg + case atomicArithmeticOpNop: + newVal = arg + } + memoryInst.WriteUint16Le(offset, newVal) + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + frame.pc++ + case operationKindAtomicRMWCmpxchg: + rep := ce.popValue() + exp := ce.popValue() + offset := ce.popMemoryOffset(op) + switch unsignedType(op.B1) { + case unsignedTypeI32: + if offset%4 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint32Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if old == uint32(exp) { + memoryInst.WriteUint32Le(offset, uint32(rep)) + } + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + case unsignedTypeI64: + if offset%8 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint64Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if old == exp { + memoryInst.WriteUint64Le(offset, rep) + } + memoryInst.Mux.Unlock() + ce.pushValue(old) + } + frame.pc++ + case operationKindAtomicRMW8Cmpxchg: + rep := byte(ce.popValue()) + exp := byte(ce.popValue()) + offset := ce.popMemoryOffset(op) + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadByte(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if old == exp { + memoryInst.WriteByte(offset, rep) + } + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + frame.pc++ + case operationKindAtomicRMW16Cmpxchg: + rep := uint16(ce.popValue()) + exp := uint16(ce.popValue()) + offset := ce.popMemoryOffset(op) + if offset%2 != 0 { + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + } + memoryInst.Mux.Lock() + old, ok := memoryInst.ReadUint16Le(offset) + if !ok { + memoryInst.Mux.Unlock() + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + if old == exp { + memoryInst.WriteUint16Le(offset, rep) + } + memoryInst.Mux.Unlock() + ce.pushValue(uint64(old)) + frame.pc++ + default: + frame.pc++ + } + } + ce.popFrame() +} + +func wasmCompatMax32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(moremath.WasmCompatMax32( + math.Float32frombits(v1), + math.Float32frombits(v2), + ))) +} + +func wasmCompatMin32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(moremath.WasmCompatMin32( + math.Float32frombits(v1), + math.Float32frombits(v2), + ))) +} + +func addFloat32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(math.Float32frombits(v1) + math.Float32frombits(v2))) +} + +func subFloat32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(math.Float32frombits(v1) - math.Float32frombits(v2))) +} + +func mulFloat32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(math.Float32frombits(v1) * math.Float32frombits(v2))) +} + +func divFloat32bits(v1, v2 uint32) uint64 { + return uint64(math.Float32bits(math.Float32frombits(v1) / math.Float32frombits(v2))) +} + +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#xref-exec-numerics-op-flt-mathrm-flt-n-z-1-z-2 +func flt32(z1, z2 float32) bool { + if z1 != z1 || z2 != z2 { + return false + } else if z1 == z2 { + return false + } else if math.IsInf(float64(z1), 1) { + return false + } else if math.IsInf(float64(z1), -1) { + return true + } else if math.IsInf(float64(z2), 1) { + return true + } else if math.IsInf(float64(z2), -1) { + return false + } + return z1 < z2 +} + +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#xref-exec-numerics-op-flt-mathrm-flt-n-z-1-z-2 +func flt64(z1, z2 float64) bool { + if z1 != z1 || z2 != z2 { + return false + } else if z1 == z2 { + return false + } else if math.IsInf(z1, 1) { + return false + } else if math.IsInf(z1, -1) { + return true + } else if math.IsInf(z2, 1) { + return true + } else if math.IsInf(z2, -1) { + return false + } + return z1 < z2 +} + +func i8RoundingAverage(v1, v2 byte) byte { + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#lane-wise-integer-rounding-average + return byte((uint16(v1) + uint16(v2) + uint16(1)) / 2) +} + +func i16RoundingAverage(v1, v2 uint16) uint16 { + // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#lane-wise-integer-rounding-average + return uint16((uint32(v1) + uint32(v2) + 1) / 2) +} + +func i8Abs(v byte) byte { + if i := int8(v); i < 0 { + return byte(-i) + } else { + return byte(i) + } +} + +func i8MaxU(v1, v2 byte) byte { + if v1 < v2 { + return v2 + } else { + return v1 + } +} + +func i8MinU(v1, v2 byte) byte { + if v1 > v2 { + return v2 + } else { + return v1 + } +} + +func i8MaxS(v1, v2 byte) byte { + if int8(v1) < int8(v2) { + return v2 + } else { + return v1 + } +} + +func i8MinS(v1, v2 byte) byte { + if int8(v1) > int8(v2) { + return v2 + } else { + return v1 + } +} + +func i16MaxU(v1, v2 uint16) uint16 { + if v1 < v2 { + return v2 + } else { + return v1 + } +} + +func i16MinU(v1, v2 uint16) uint16 { + if v1 > v2 { + return v2 + } else { + return v1 + } +} + +func i16MaxS(v1, v2 uint16) uint16 { + if int16(v1) < int16(v2) { + return v2 + } else { + return v1 + } +} + +func i16MinS(v1, v2 uint16) uint16 { + if int16(v1) > int16(v2) { + return v2 + } else { + return v1 + } +} + +func i32MaxU(v1, v2 uint32) uint32 { + if v1 < v2 { + return v2 + } else { + return v1 + } +} + +func i32MinU(v1, v2 uint32) uint32 { + if v1 > v2 { + return v2 + } else { + return v1 + } +} + +func i32MaxS(v1, v2 uint32) uint32 { + if int32(v1) < int32(v2) { + return v2 + } else { + return v1 + } +} + +func i32MinS(v1, v2 uint32) uint32 { + if int32(v1) > int32(v2) { + return v2 + } else { + return v1 + } +} + +func i16Abs(v uint16) uint16 { + if i := int16(v); i < 0 { + return uint16(-i) + } else { + return uint16(i) + } +} + +func i32Abs(v uint32) uint32 { + if i := int32(v); i < 0 { + return uint32(-i) + } else { + return uint32(i) + } +} + +func (ce *callEngine) callNativeFuncWithListener(ctx context.Context, m *wasm.ModuleInstance, f *function, fnl experimental.FunctionListener) context.Context { + def, typ := f.definition(), f.funcType + + ce.stackIterator.reset(ce.stack, ce.frames, f) + fnl.Before(ctx, m, def, ce.peekValues(typ.ParamNumInUint64), &ce.stackIterator) + ce.stackIterator.clear() + ce.callNativeFunc(ctx, m, f) + fnl.After(ctx, m, def, ce.peekValues(typ.ResultNumInUint64)) + return ctx +} + +// popMemoryOffset takes a memory offset off the stack for use in load and store instructions. +// As the top of stack value is 64-bit, this ensures it is in range before returning it. +func (ce *callEngine) popMemoryOffset(op *unionOperation) uint32 { + offset := op.U2 + ce.popValue() + if offset > math.MaxUint32 { + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + } + return uint32(offset) +} + +func (ce *callEngine) callGoFuncWithStack(ctx context.Context, m *wasm.ModuleInstance, f *function) { + typ := f.funcType + paramLen := typ.ParamNumInUint64 + resultLen := typ.ResultNumInUint64 + stackLen := paramLen + + // In the interpreter engine, ce.stack may only have capacity to store + // parameters. Grow when there are more results than parameters. + if growLen := resultLen - paramLen; growLen > 0 { + for i := 0; i < growLen; i++ { + ce.stack = append(ce.stack, 0) + } + stackLen += growLen + } + + // Pass the stack elements to the go function. + stack := ce.stack[len(ce.stack)-stackLen:] + ce.callGoFunc(ctx, m, f, stack) + + // Shrink the stack when there were more parameters than results. + if shrinkLen := paramLen - resultLen; shrinkLen > 0 { + ce.stack = ce.stack[0 : len(ce.stack)-shrinkLen] + } +} + +// v128Dot performs a dot product of two 64-bit vectors. +// Note: for some reason (which I suspect is due to a bug in Go compiler's regalloc), +// inlining this function causes a bug which happens **only when** we run with -race AND arm64 AND Go 1.22. +func v128Dot(x1Hi, x1Lo, x2Hi, x2Lo uint64) (uint64, uint64) { + r1 := int32(int16(x1Lo>>0)) * int32(int16(x2Lo>>0)) + r2 := int32(int16(x1Lo>>16)) * int32(int16(x2Lo>>16)) + r3 := int32(int16(x1Lo>>32)) * int32(int16(x2Lo>>32)) + r4 := int32(int16(x1Lo>>48)) * int32(int16(x2Lo>>48)) + r5 := int32(int16(x1Hi>>0)) * int32(int16(x2Hi>>0)) + r6 := int32(int16(x1Hi>>16)) * int32(int16(x2Hi>>16)) + r7 := int32(int16(x1Hi>>32)) * int32(int16(x2Hi>>32)) + r8 := int32(int16(x1Hi>>48)) * int32(int16(x2Hi>>48)) + return uint64(uint32(r1+r2)) | (uint64(uint32(r3+r4)) << 32), uint64(uint32(r5+r6)) | (uint64(uint32(r7+r8)) << 32) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/operations.go b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/operations.go new file mode 100644 index 00000000..3087a718 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/interpreter/operations.go @@ -0,0 +1,2812 @@ +package interpreter + +import ( + "fmt" + "math" + "strings" +) + +// unsignedInt represents unsigned 32-bit or 64-bit integers. +type unsignedInt byte + +const ( + unsignedInt32 unsignedInt = iota + unsignedInt64 +) + +// String implements fmt.Stringer. +func (s unsignedInt) String() (ret string) { + switch s { + case unsignedInt32: + ret = "i32" + case unsignedInt64: + ret = "i64" + } + return +} + +// signedInt represents signed or unsigned integers. +type signedInt byte + +const ( + signedInt32 signedInt = iota + signedInt64 + signedUint32 + signedUint64 +) + +// String implements fmt.Stringer. +func (s signedInt) String() (ret string) { + switch s { + case signedUint32: + ret = "u32" + case signedUint64: + ret = "u64" + case signedInt32: + ret = "s32" + case signedInt64: + ret = "s64" + } + return +} + +// float represents the scalar double or single precision floating points. +type float byte + +const ( + f32 float = iota + f64 +) + +// String implements fmt.Stringer. +func (s float) String() (ret string) { + switch s { + case f32: + ret = "f32" + case f64: + ret = "f64" + } + return +} + +// unsignedType is the union of unsignedInt, float and V128 vector type. +type unsignedType byte + +const ( + unsignedTypeI32 unsignedType = iota + unsignedTypeI64 + unsignedTypeF32 + unsignedTypeF64 + unsignedTypeV128 + unsignedTypeUnknown +) + +// String implements fmt.Stringer. +func (s unsignedType) String() (ret string) { + switch s { + case unsignedTypeI32: + ret = "i32" + case unsignedTypeI64: + ret = "i64" + case unsignedTypeF32: + ret = "f32" + case unsignedTypeF64: + ret = "f64" + case unsignedTypeV128: + ret = "v128" + case unsignedTypeUnknown: + ret = "unknown" + } + return +} + +// signedType is the union of signedInt and float types. +type signedType byte + +const ( + signedTypeInt32 signedType = iota + signedTypeUint32 + signedTypeInt64 + signedTypeUint64 + signedTypeFloat32 + signedTypeFloat64 +) + +// String implements fmt.Stringer. +func (s signedType) String() (ret string) { + switch s { + case signedTypeInt32: + ret = "s32" + case signedTypeUint32: + ret = "u32" + case signedTypeInt64: + ret = "s64" + case signedTypeUint64: + ret = "u64" + case signedTypeFloat32: + ret = "f32" + case signedTypeFloat64: + ret = "f64" + } + return +} + +// operationKind is the Kind of each implementation of Operation interface. +type operationKind uint16 + +// String implements fmt.Stringer. +func (o operationKind) String() (ret string) { + switch o { + case operationKindUnreachable: + ret = "Unreachable" + case operationKindLabel: + ret = "label" + case operationKindBr: + ret = "Br" + case operationKindBrIf: + ret = "BrIf" + case operationKindBrTable: + ret = "BrTable" + case operationKindCall: + ret = "Call" + case operationKindCallIndirect: + ret = "CallIndirect" + case operationKindDrop: + ret = "Drop" + case operationKindSelect: + ret = "Select" + case operationKindPick: + ret = "Pick" + case operationKindSet: + ret = "Swap" + case operationKindGlobalGet: + ret = "GlobalGet" + case operationKindGlobalSet: + ret = "GlobalSet" + case operationKindLoad: + ret = "Load" + case operationKindLoad8: + ret = "Load8" + case operationKindLoad16: + ret = "Load16" + case operationKindLoad32: + ret = "Load32" + case operationKindStore: + ret = "Store" + case operationKindStore8: + ret = "Store8" + case operationKindStore16: + ret = "Store16" + case operationKindStore32: + ret = "Store32" + case operationKindMemorySize: + ret = "MemorySize" + case operationKindMemoryGrow: + ret = "MemoryGrow" + case operationKindConstI32: + ret = "ConstI32" + case operationKindConstI64: + ret = "ConstI64" + case operationKindConstF32: + ret = "ConstF32" + case operationKindConstF64: + ret = "ConstF64" + case operationKindEq: + ret = "Eq" + case operationKindNe: + ret = "Ne" + case operationKindEqz: + ret = "Eqz" + case operationKindLt: + ret = "Lt" + case operationKindGt: + ret = "Gt" + case operationKindLe: + ret = "Le" + case operationKindGe: + ret = "Ge" + case operationKindAdd: + ret = "Add" + case operationKindSub: + ret = "Sub" + case operationKindMul: + ret = "Mul" + case operationKindClz: + ret = "Clz" + case operationKindCtz: + ret = "Ctz" + case operationKindPopcnt: + ret = "Popcnt" + case operationKindDiv: + ret = "Div" + case operationKindRem: + ret = "Rem" + case operationKindAnd: + ret = "And" + case operationKindOr: + ret = "Or" + case operationKindXor: + ret = "Xor" + case operationKindShl: + ret = "Shl" + case operationKindShr: + ret = "Shr" + case operationKindRotl: + ret = "Rotl" + case operationKindRotr: + ret = "Rotr" + case operationKindAbs: + ret = "Abs" + case operationKindNeg: + ret = "Neg" + case operationKindCeil: + ret = "Ceil" + case operationKindFloor: + ret = "Floor" + case operationKindTrunc: + ret = "Trunc" + case operationKindNearest: + ret = "Nearest" + case operationKindSqrt: + ret = "Sqrt" + case operationKindMin: + ret = "Min" + case operationKindMax: + ret = "Max" + case operationKindCopysign: + ret = "Copysign" + case operationKindI32WrapFromI64: + ret = "I32WrapFromI64" + case operationKindITruncFromF: + ret = "ITruncFromF" + case operationKindFConvertFromI: + ret = "FConvertFromI" + case operationKindF32DemoteFromF64: + ret = "F32DemoteFromF64" + case operationKindF64PromoteFromF32: + ret = "F64PromoteFromF32" + case operationKindI32ReinterpretFromF32: + ret = "I32ReinterpretFromF32" + case operationKindI64ReinterpretFromF64: + ret = "I64ReinterpretFromF64" + case operationKindF32ReinterpretFromI32: + ret = "F32ReinterpretFromI32" + case operationKindF64ReinterpretFromI64: + ret = "F64ReinterpretFromI64" + case operationKindExtend: + ret = "Extend" + case operationKindMemoryInit: + ret = "MemoryInit" + case operationKindDataDrop: + ret = "DataDrop" + case operationKindMemoryCopy: + ret = "MemoryCopy" + case operationKindMemoryFill: + ret = "MemoryFill" + case operationKindTableInit: + ret = "TableInit" + case operationKindElemDrop: + ret = "ElemDrop" + case operationKindTableCopy: + ret = "TableCopy" + case operationKindRefFunc: + ret = "RefFunc" + case operationKindTableGet: + ret = "TableGet" + case operationKindTableSet: + ret = "TableSet" + case operationKindTableSize: + ret = "TableSize" + case operationKindTableGrow: + ret = "TableGrow" + case operationKindTableFill: + ret = "TableFill" + case operationKindV128Const: + ret = "ConstV128" + case operationKindV128Add: + ret = "V128Add" + case operationKindV128Sub: + ret = "V128Sub" + case operationKindV128Load: + ret = "V128Load" + case operationKindV128LoadLane: + ret = "V128LoadLane" + case operationKindV128Store: + ret = "V128Store" + case operationKindV128StoreLane: + ret = "V128StoreLane" + case operationKindV128ExtractLane: + ret = "V128ExtractLane" + case operationKindV128ReplaceLane: + ret = "V128ReplaceLane" + case operationKindV128Splat: + ret = "V128Splat" + case operationKindV128Shuffle: + ret = "V128Shuffle" + case operationKindV128Swizzle: + ret = "V128Swizzle" + case operationKindV128AnyTrue: + ret = "V128AnyTrue" + case operationKindV128AllTrue: + ret = "V128AllTrue" + case operationKindV128And: + ret = "V128And" + case operationKindV128Not: + ret = "V128Not" + case operationKindV128Or: + ret = "V128Or" + case operationKindV128Xor: + ret = "V128Xor" + case operationKindV128Bitselect: + ret = "V128Bitselect" + case operationKindV128AndNot: + ret = "V128AndNot" + case operationKindV128BitMask: + ret = "V128BitMask" + case operationKindV128Shl: + ret = "V128Shl" + case operationKindV128Shr: + ret = "V128Shr" + case operationKindV128Cmp: + ret = "V128Cmp" + case operationKindSignExtend32From8: + ret = "SignExtend32From8" + case operationKindSignExtend32From16: + ret = "SignExtend32From16" + case operationKindSignExtend64From8: + ret = "SignExtend64From8" + case operationKindSignExtend64From16: + ret = "SignExtend64From16" + case operationKindSignExtend64From32: + ret = "SignExtend64From32" + case operationKindV128AddSat: + ret = "V128AddSat" + case operationKindV128SubSat: + ret = "V128SubSat" + case operationKindV128Mul: + ret = "V128Mul" + case operationKindV128Div: + ret = "V128Div" + case operationKindV128Neg: + ret = "V128Neg" + case operationKindV128Sqrt: + ret = "V128Sqrt" + case operationKindV128Abs: + ret = "V128Abs" + case operationKindV128Popcnt: + ret = "V128Popcnt" + case operationKindV128Min: + ret = "V128Min" + case operationKindV128Max: + ret = "V128Max" + case operationKindV128AvgrU: + ret = "V128AvgrU" + case operationKindV128Ceil: + ret = "V128Ceil" + case operationKindV128Floor: + ret = "V128Floor" + case operationKindV128Trunc: + ret = "V128Trunc" + case operationKindV128Nearest: + ret = "V128Nearest" + case operationKindV128Pmin: + ret = "V128Pmin" + case operationKindV128Pmax: + ret = "V128Pmax" + case operationKindV128Extend: + ret = "V128Extend" + case operationKindV128ExtMul: + ret = "V128ExtMul" + case operationKindV128Q15mulrSatS: + ret = "V128Q15mulrSatS" + case operationKindV128ExtAddPairwise: + ret = "V128ExtAddPairwise" + case operationKindV128FloatPromote: + ret = "V128FloatPromote" + case operationKindV128FloatDemote: + ret = "V128FloatDemote" + case operationKindV128FConvertFromI: + ret = "V128FConvertFromI" + case operationKindV128Dot: + ret = "V128Dot" + case operationKindV128Narrow: + ret = "V128Narrow" + case operationKindV128ITruncSatFromF: + ret = "V128ITruncSatFromF" + case operationKindBuiltinFunctionCheckExitCode: + ret = "BuiltinFunctionCheckExitCode" + case operationKindAtomicMemoryWait: + ret = "operationKindAtomicMemoryWait" + case operationKindAtomicMemoryNotify: + ret = "operationKindAtomicMemoryNotify" + case operationKindAtomicFence: + ret = "operationKindAtomicFence" + case operationKindAtomicLoad: + ret = "operationKindAtomicLoad" + case operationKindAtomicLoad8: + ret = "operationKindAtomicLoad8" + case operationKindAtomicLoad16: + ret = "operationKindAtomicLoad16" + case operationKindAtomicStore: + ret = "operationKindAtomicStore" + case operationKindAtomicStore8: + ret = "operationKindAtomicStore8" + case operationKindAtomicStore16: + ret = "operationKindAtomicStore16" + case operationKindAtomicRMW: + ret = "operationKindAtomicRMW" + case operationKindAtomicRMW8: + ret = "operationKindAtomicRMW8" + case operationKindAtomicRMW16: + ret = "operationKindAtomicRMW16" + case operationKindAtomicRMWCmpxchg: + ret = "operationKindAtomicRMWCmpxchg" + case operationKindAtomicRMW8Cmpxchg: + ret = "operationKindAtomicRMW8Cmpxchg" + case operationKindAtomicRMW16Cmpxchg: + ret = "operationKindAtomicRMW16Cmpxchg" + default: + panic(fmt.Errorf("unknown operation %d", o)) + } + return +} + +const ( + // operationKindUnreachable is the Kind for NewOperationUnreachable. + operationKindUnreachable operationKind = iota + // operationKindLabel is the Kind for NewOperationLabel. + operationKindLabel + // operationKindBr is the Kind for NewOperationBr. + operationKindBr + // operationKindBrIf is the Kind for NewOperationBrIf. + operationKindBrIf + // operationKindBrTable is the Kind for NewOperationBrTable. + operationKindBrTable + // operationKindCall is the Kind for NewOperationCall. + operationKindCall + // operationKindCallIndirect is the Kind for NewOperationCallIndirect. + operationKindCallIndirect + // operationKindDrop is the Kind for NewOperationDrop. + operationKindDrop + // operationKindSelect is the Kind for NewOperationSelect. + operationKindSelect + // operationKindPick is the Kind for NewOperationPick. + operationKindPick + // operationKindSet is the Kind for NewOperationSet. + operationKindSet + // operationKindGlobalGet is the Kind for NewOperationGlobalGet. + operationKindGlobalGet + // operationKindGlobalSet is the Kind for NewOperationGlobalSet. + operationKindGlobalSet + // operationKindLoad is the Kind for NewOperationLoad. + operationKindLoad + // operationKindLoad8 is the Kind for NewOperationLoad8. + operationKindLoad8 + // operationKindLoad16 is the Kind for NewOperationLoad16. + operationKindLoad16 + // operationKindLoad32 is the Kind for NewOperationLoad32. + operationKindLoad32 + // operationKindStore is the Kind for NewOperationStore. + operationKindStore + // operationKindStore8 is the Kind for NewOperationStore8. + operationKindStore8 + // operationKindStore16 is the Kind for NewOperationStore16. + operationKindStore16 + // operationKindStore32 is the Kind for NewOperationStore32. + operationKindStore32 + // operationKindMemorySize is the Kind for NewOperationMemorySize. + operationKindMemorySize + // operationKindMemoryGrow is the Kind for NewOperationMemoryGrow. + operationKindMemoryGrow + // operationKindConstI32 is the Kind for NewOperationConstI32. + operationKindConstI32 + // operationKindConstI64 is the Kind for NewOperationConstI64. + operationKindConstI64 + // operationKindConstF32 is the Kind for NewOperationConstF32. + operationKindConstF32 + // operationKindConstF64 is the Kind for NewOperationConstF64. + operationKindConstF64 + // operationKindEq is the Kind for NewOperationEq. + operationKindEq + // operationKindNe is the Kind for NewOperationNe. + operationKindNe + // operationKindEqz is the Kind for NewOperationEqz. + operationKindEqz + // operationKindLt is the Kind for NewOperationLt. + operationKindLt + // operationKindGt is the Kind for NewOperationGt. + operationKindGt + // operationKindLe is the Kind for NewOperationLe. + operationKindLe + // operationKindGe is the Kind for NewOperationGe. + operationKindGe + // operationKindAdd is the Kind for NewOperationAdd. + operationKindAdd + // operationKindSub is the Kind for NewOperationSub. + operationKindSub + // operationKindMul is the Kind for NewOperationMul. + operationKindMul + // operationKindClz is the Kind for NewOperationClz. + operationKindClz + // operationKindCtz is the Kind for NewOperationCtz. + operationKindCtz + // operationKindPopcnt is the Kind for NewOperationPopcnt. + operationKindPopcnt + // operationKindDiv is the Kind for NewOperationDiv. + operationKindDiv + // operationKindRem is the Kind for NewOperationRem. + operationKindRem + // operationKindAnd is the Kind for NewOperationAnd. + operationKindAnd + // operationKindOr is the Kind for NewOperationOr. + operationKindOr + // operationKindXor is the Kind for NewOperationXor. + operationKindXor + // operationKindShl is the Kind for NewOperationShl. + operationKindShl + // operationKindShr is the Kind for NewOperationShr. + operationKindShr + // operationKindRotl is the Kind for NewOperationRotl. + operationKindRotl + // operationKindRotr is the Kind for NewOperationRotr. + operationKindRotr + // operationKindAbs is the Kind for NewOperationAbs. + operationKindAbs + // operationKindNeg is the Kind for NewOperationNeg. + operationKindNeg + // operationKindCeil is the Kind for NewOperationCeil. + operationKindCeil + // operationKindFloor is the Kind for NewOperationFloor. + operationKindFloor + // operationKindTrunc is the Kind for NewOperationTrunc. + operationKindTrunc + // operationKindNearest is the Kind for NewOperationNearest. + operationKindNearest + // operationKindSqrt is the Kind for NewOperationSqrt. + operationKindSqrt + // operationKindMin is the Kind for NewOperationMin. + operationKindMin + // operationKindMax is the Kind for NewOperationMax. + operationKindMax + // operationKindCopysign is the Kind for NewOperationCopysign. + operationKindCopysign + // operationKindI32WrapFromI64 is the Kind for NewOperationI32WrapFromI64. + operationKindI32WrapFromI64 + // operationKindITruncFromF is the Kind for NewOperationITruncFromF. + operationKindITruncFromF + // operationKindFConvertFromI is the Kind for NewOperationFConvertFromI. + operationKindFConvertFromI + // operationKindF32DemoteFromF64 is the Kind for NewOperationF32DemoteFromF64. + operationKindF32DemoteFromF64 + // operationKindF64PromoteFromF32 is the Kind for NewOperationF64PromoteFromF32. + operationKindF64PromoteFromF32 + // operationKindI32ReinterpretFromF32 is the Kind for NewOperationI32ReinterpretFromF32. + operationKindI32ReinterpretFromF32 + // operationKindI64ReinterpretFromF64 is the Kind for NewOperationI64ReinterpretFromF64. + operationKindI64ReinterpretFromF64 + // operationKindF32ReinterpretFromI32 is the Kind for NewOperationF32ReinterpretFromI32. + operationKindF32ReinterpretFromI32 + // operationKindF64ReinterpretFromI64 is the Kind for NewOperationF64ReinterpretFromI64. + operationKindF64ReinterpretFromI64 + // operationKindExtend is the Kind for NewOperationExtend. + operationKindExtend + // operationKindSignExtend32From8 is the Kind for NewOperationSignExtend32From8. + operationKindSignExtend32From8 + // operationKindSignExtend32From16 is the Kind for NewOperationSignExtend32From16. + operationKindSignExtend32From16 + // operationKindSignExtend64From8 is the Kind for NewOperationSignExtend64From8. + operationKindSignExtend64From8 + // operationKindSignExtend64From16 is the Kind for NewOperationSignExtend64From16. + operationKindSignExtend64From16 + // operationKindSignExtend64From32 is the Kind for NewOperationSignExtend64From32. + operationKindSignExtend64From32 + // operationKindMemoryInit is the Kind for NewOperationMemoryInit. + operationKindMemoryInit + // operationKindDataDrop is the Kind for NewOperationDataDrop. + operationKindDataDrop + // operationKindMemoryCopy is the Kind for NewOperationMemoryCopy. + operationKindMemoryCopy + // operationKindMemoryFill is the Kind for NewOperationMemoryFill. + operationKindMemoryFill + // operationKindTableInit is the Kind for NewOperationTableInit. + operationKindTableInit + // operationKindElemDrop is the Kind for NewOperationElemDrop. + operationKindElemDrop + // operationKindTableCopy is the Kind for NewOperationTableCopy. + operationKindTableCopy + // operationKindRefFunc is the Kind for NewOperationRefFunc. + operationKindRefFunc + // operationKindTableGet is the Kind for NewOperationTableGet. + operationKindTableGet + // operationKindTableSet is the Kind for NewOperationTableSet. + operationKindTableSet + // operationKindTableSize is the Kind for NewOperationTableSize. + operationKindTableSize + // operationKindTableGrow is the Kind for NewOperationTableGrow. + operationKindTableGrow + // operationKindTableFill is the Kind for NewOperationTableFill. + operationKindTableFill + + // Vector value related instructions are prefixed by V128. + + // operationKindV128Const is the Kind for NewOperationV128Const. + operationKindV128Const + // operationKindV128Add is the Kind for NewOperationV128Add. + operationKindV128Add + // operationKindV128Sub is the Kind for NewOperationV128Sub. + operationKindV128Sub + // operationKindV128Load is the Kind for NewOperationV128Load. + operationKindV128Load + // operationKindV128LoadLane is the Kind for NewOperationV128LoadLane. + operationKindV128LoadLane + // operationKindV128Store is the Kind for NewOperationV128Store. + operationKindV128Store + // operationKindV128StoreLane is the Kind for NewOperationV128StoreLane. + operationKindV128StoreLane + // operationKindV128ExtractLane is the Kind for NewOperationV128ExtractLane. + operationKindV128ExtractLane + // operationKindV128ReplaceLane is the Kind for NewOperationV128ReplaceLane. + operationKindV128ReplaceLane + // operationKindV128Splat is the Kind for NewOperationV128Splat. + operationKindV128Splat + // operationKindV128Shuffle is the Kind for NewOperationV128Shuffle. + operationKindV128Shuffle + // operationKindV128Swizzle is the Kind for NewOperationV128Swizzle. + operationKindV128Swizzle + // operationKindV128AnyTrue is the Kind for NewOperationV128AnyTrue. + operationKindV128AnyTrue + // operationKindV128AllTrue is the Kind for NewOperationV128AllTrue. + operationKindV128AllTrue + // operationKindV128BitMask is the Kind for NewOperationV128BitMask. + operationKindV128BitMask + // operationKindV128And is the Kind for NewOperationV128And. + operationKindV128And + // operationKindV128Not is the Kind for NewOperationV128Not. + operationKindV128Not + // operationKindV128Or is the Kind for NewOperationV128Or. + operationKindV128Or + // operationKindV128Xor is the Kind for NewOperationV128Xor. + operationKindV128Xor + // operationKindV128Bitselect is the Kind for NewOperationV128Bitselect. + operationKindV128Bitselect + // operationKindV128AndNot is the Kind for NewOperationV128AndNot. + operationKindV128AndNot + // operationKindV128Shl is the Kind for NewOperationV128Shl. + operationKindV128Shl + // operationKindV128Shr is the Kind for NewOperationV128Shr. + operationKindV128Shr + // operationKindV128Cmp is the Kind for NewOperationV128Cmp. + operationKindV128Cmp + // operationKindV128AddSat is the Kind for NewOperationV128AddSat. + operationKindV128AddSat + // operationKindV128SubSat is the Kind for NewOperationV128SubSat. + operationKindV128SubSat + // operationKindV128Mul is the Kind for NewOperationV128Mul. + operationKindV128Mul + // operationKindV128Div is the Kind for NewOperationV128Div. + operationKindV128Div + // operationKindV128Neg is the Kind for NewOperationV128Neg. + operationKindV128Neg + // operationKindV128Sqrt is the Kind for NewOperationV128Sqrt. + operationKindV128Sqrt + // operationKindV128Abs is the Kind for NewOperationV128Abs. + operationKindV128Abs + // operationKindV128Popcnt is the Kind for NewOperationV128Popcnt. + operationKindV128Popcnt + // operationKindV128Min is the Kind for NewOperationV128Min. + operationKindV128Min + // operationKindV128Max is the Kind for NewOperationV128Max. + operationKindV128Max + // operationKindV128AvgrU is the Kind for NewOperationV128AvgrU. + operationKindV128AvgrU + // operationKindV128Pmin is the Kind for NewOperationV128Pmin. + operationKindV128Pmin + // operationKindV128Pmax is the Kind for NewOperationV128Pmax. + operationKindV128Pmax + // operationKindV128Ceil is the Kind for NewOperationV128Ceil. + operationKindV128Ceil + // operationKindV128Floor is the Kind for NewOperationV128Floor. + operationKindV128Floor + // operationKindV128Trunc is the Kind for NewOperationV128Trunc. + operationKindV128Trunc + // operationKindV128Nearest is the Kind for NewOperationV128Nearest. + operationKindV128Nearest + // operationKindV128Extend is the Kind for NewOperationV128Extend. + operationKindV128Extend + // operationKindV128ExtMul is the Kind for NewOperationV128ExtMul. + operationKindV128ExtMul + // operationKindV128Q15mulrSatS is the Kind for NewOperationV128Q15mulrSatS. + operationKindV128Q15mulrSatS + // operationKindV128ExtAddPairwise is the Kind for NewOperationV128ExtAddPairwise. + operationKindV128ExtAddPairwise + // operationKindV128FloatPromote is the Kind for NewOperationV128FloatPromote. + operationKindV128FloatPromote + // operationKindV128FloatDemote is the Kind for NewOperationV128FloatDemote. + operationKindV128FloatDemote + // operationKindV128FConvertFromI is the Kind for NewOperationV128FConvertFromI. + operationKindV128FConvertFromI + // operationKindV128Dot is the Kind for NewOperationV128Dot. + operationKindV128Dot + // operationKindV128Narrow is the Kind for NewOperationV128Narrow. + operationKindV128Narrow + // operationKindV128ITruncSatFromF is the Kind for NewOperationV128ITruncSatFromF. + operationKindV128ITruncSatFromF + + // operationKindBuiltinFunctionCheckExitCode is the Kind for NewOperationBuiltinFunctionCheckExitCode. + operationKindBuiltinFunctionCheckExitCode + + // operationKindAtomicMemoryWait is the kind for NewOperationAtomicMemoryWait. + operationKindAtomicMemoryWait + // operationKindAtomicMemoryNotify is the kind for NewOperationAtomicMemoryNotify. + operationKindAtomicMemoryNotify + // operationKindAtomicFence is the kind for NewOperationAtomicFence. + operationKindAtomicFence + // operationKindAtomicLoad is the kind for NewOperationAtomicLoad. + operationKindAtomicLoad + // operationKindAtomicLoad8 is the kind for NewOperationAtomicLoad8. + operationKindAtomicLoad8 + // operationKindAtomicLoad16 is the kind for NewOperationAtomicLoad16. + operationKindAtomicLoad16 + // operationKindAtomicStore is the kind for NewOperationAtomicStore. + operationKindAtomicStore + // operationKindAtomicStore8 is the kind for NewOperationAtomicStore8. + operationKindAtomicStore8 + // operationKindAtomicStore16 is the kind for NewOperationAtomicStore16. + operationKindAtomicStore16 + + // operationKindAtomicRMW is the kind for NewOperationAtomicRMW. + operationKindAtomicRMW + // operationKindAtomicRMW8 is the kind for NewOperationAtomicRMW8. + operationKindAtomicRMW8 + // operationKindAtomicRMW16 is the kind for NewOperationAtomicRMW16. + operationKindAtomicRMW16 + + // operationKindAtomicRMWCmpxchg is the kind for NewOperationAtomicRMWCmpxchg. + operationKindAtomicRMWCmpxchg + // operationKindAtomicRMW8Cmpxchg is the kind for NewOperationAtomicRMW8Cmpxchg. + operationKindAtomicRMW8Cmpxchg + // operationKindAtomicRMW16Cmpxchg is the kind for NewOperationAtomicRMW16Cmpxchg. + operationKindAtomicRMW16Cmpxchg + + // operationKindEnd is always placed at the bottom of this iota definition to be used in the test. + operationKindEnd +) + +// NewOperationBuiltinFunctionCheckExitCode is a constructor for unionOperation with Kind operationKindBuiltinFunctionCheckExitCode. +// +// OperationBuiltinFunctionCheckExitCode corresponds to the instruction to check the api.Module is already closed due to +// context.DeadlineExceeded, context.Canceled, or the explicit call of CloseWithExitCode on api.Module. +func newOperationBuiltinFunctionCheckExitCode() unionOperation { + return unionOperation{Kind: operationKindBuiltinFunctionCheckExitCode} +} + +// label is the unique identifier for each block in a single function in interpreterir +// where "block" consists of multiple operations, and must End with branching operations +// (e.g. operationKindBr or operationKindBrIf). +type label uint64 + +// Kind returns the labelKind encoded in this label. +func (l label) Kind() labelKind { + return labelKind(uint32(l)) +} + +// FrameID returns the frame id encoded in this label. +func (l label) FrameID() int { + return int(uint32(l >> 32)) +} + +// NewLabel is a constructor for a label. +func newLabel(kind labelKind, frameID uint32) label { + return label(kind) | label(frameID)<<32 +} + +// String implements fmt.Stringer. +func (l label) String() (ret string) { + frameID := l.FrameID() + switch l.Kind() { + case labelKindHeader: + ret = fmt.Sprintf(".L%d", frameID) + case labelKindElse: + ret = fmt.Sprintf(".L%d_else", frameID) + case labelKindContinuation: + ret = fmt.Sprintf(".L%d_cont", frameID) + case labelKindReturn: + return ".return" + } + return +} + +func (l label) IsReturnTarget() bool { + return l.Kind() == labelKindReturn +} + +// labelKind is the Kind of the label. +type labelKind = byte + +const ( + // labelKindHeader is the header for various blocks. For example, the "then" block of + // wasm.OpcodeIfName in Wasm has the label of this Kind. + labelKindHeader labelKind = iota + // labelKindElse is the Kind of label for "else" block of wasm.OpcodeIfName in Wasm. + labelKindElse + // labelKindContinuation is the Kind of label which is the continuation of blocks. + // For example, for wasm text like + // (func + // .... + // (if (local.get 0) (then (nop)) (else (nop))) + // return + // ) + // we have the continuation block (of if-block) corresponding to "return" opcode. + labelKindContinuation + labelKindReturn + labelKindNum +) + +// unionOperation implements Operation and is the compilation (engine.lowerIR) result of a interpreterir.Operation. +// +// Not all operations result in a unionOperation, e.g. interpreterir.OperationI32ReinterpretFromF32, and some operations are +// more complex than others, e.g. interpreterir.NewOperationBrTable. +// +// Note: This is a form of union type as it can store fields needed for any operation. Hence, most fields are opaque and +// only relevant when in context of its kind. +type unionOperation struct { + // Kind determines how to interpret the other fields in this struct. + Kind operationKind + B1, B2 byte + B3 bool + U1, U2 uint64 + U3 uint64 + Us []uint64 +} + +// String implements fmt.Stringer. +func (o unionOperation) String() string { + switch o.Kind { + case operationKindUnreachable, + operationKindSelect, + operationKindMemorySize, + operationKindMemoryGrow, + operationKindI32WrapFromI64, + operationKindF32DemoteFromF64, + operationKindF64PromoteFromF32, + operationKindI32ReinterpretFromF32, + operationKindI64ReinterpretFromF64, + operationKindF32ReinterpretFromI32, + operationKindF64ReinterpretFromI64, + operationKindSignExtend32From8, + operationKindSignExtend32From16, + operationKindSignExtend64From8, + operationKindSignExtend64From16, + operationKindSignExtend64From32, + operationKindMemoryInit, + operationKindDataDrop, + operationKindMemoryCopy, + operationKindMemoryFill, + operationKindTableInit, + operationKindElemDrop, + operationKindTableCopy, + operationKindRefFunc, + operationKindTableGet, + operationKindTableSet, + operationKindTableSize, + operationKindTableGrow, + operationKindTableFill, + operationKindBuiltinFunctionCheckExitCode: + return o.Kind.String() + + case operationKindCall, + operationKindGlobalGet, + operationKindGlobalSet: + return fmt.Sprintf("%s %d", o.Kind, o.B1) + + case operationKindLabel: + return label(o.U1).String() + + case operationKindBr: + return fmt.Sprintf("%s %s", o.Kind, label(o.U1).String()) + + case operationKindBrIf: + thenTarget := label(o.U1) + elseTarget := label(o.U2) + return fmt.Sprintf("%s %s, %s", o.Kind, thenTarget, elseTarget) + + case operationKindBrTable: + var targets []string + var defaultLabel label + if len(o.Us) > 0 { + targets = make([]string, len(o.Us)-1) + for i, t := range o.Us[1:] { + targets[i] = label(t).String() + } + defaultLabel = label(o.Us[0]) + } + return fmt.Sprintf("%s [%s] %s", o.Kind, strings.Join(targets, ","), defaultLabel) + + case operationKindCallIndirect: + return fmt.Sprintf("%s: type=%d, table=%d", o.Kind, o.U1, o.U2) + + case operationKindDrop: + start := int64(o.U1) + end := int64(o.U2) + return fmt.Sprintf("%s %d..%d", o.Kind, start, end) + + case operationKindPick, operationKindSet: + return fmt.Sprintf("%s %d (is_vector=%v)", o.Kind, o.U1, o.B3) + + case operationKindLoad, operationKindStore: + return fmt.Sprintf("%s.%s (align=%d, offset=%d)", unsignedType(o.B1), o.Kind, o.U1, o.U2) + + case operationKindLoad8, + operationKindLoad16: + return fmt.Sprintf("%s.%s (align=%d, offset=%d)", signedType(o.B1), o.Kind, o.U1, o.U2) + + case operationKindStore8, + operationKindStore16, + operationKindStore32: + return fmt.Sprintf("%s (align=%d, offset=%d)", o.Kind, o.U1, o.U2) + + case operationKindLoad32: + var t string + if o.B1 == 1 { + t = "i64" + } else { + t = "u64" + } + return fmt.Sprintf("%s.%s (align=%d, offset=%d)", t, o.Kind, o.U1, o.U2) + + case operationKindEq, + operationKindNe, + operationKindAdd, + operationKindSub, + operationKindMul: + return fmt.Sprintf("%s.%s", unsignedType(o.B1), o.Kind) + + case operationKindEqz, + operationKindClz, + operationKindCtz, + operationKindPopcnt, + operationKindAnd, + operationKindOr, + operationKindXor, + operationKindShl, + operationKindRotl, + operationKindRotr: + return fmt.Sprintf("%s.%s", unsignedInt(o.B1), o.Kind) + + case operationKindRem, operationKindShr: + return fmt.Sprintf("%s.%s", signedInt(o.B1), o.Kind) + + case operationKindLt, + operationKindGt, + operationKindLe, + operationKindGe, + operationKindDiv: + return fmt.Sprintf("%s.%s", signedType(o.B1), o.Kind) + + case operationKindAbs, + operationKindNeg, + operationKindCeil, + operationKindFloor, + operationKindTrunc, + operationKindNearest, + operationKindSqrt, + operationKindMin, + operationKindMax, + operationKindCopysign: + return fmt.Sprintf("%s.%s", float(o.B1), o.Kind) + + case operationKindConstI32, + operationKindConstI64: + return fmt.Sprintf("%s %#x", o.Kind, o.U1) + + case operationKindConstF32: + return fmt.Sprintf("%s %f", o.Kind, math.Float32frombits(uint32(o.U1))) + case operationKindConstF64: + return fmt.Sprintf("%s %f", o.Kind, math.Float64frombits(o.U1)) + + case operationKindITruncFromF: + return fmt.Sprintf("%s.%s.%s (non_trapping=%v)", signedInt(o.B2), o.Kind, float(o.B1), o.B3) + case operationKindFConvertFromI: + return fmt.Sprintf("%s.%s.%s", float(o.B2), o.Kind, signedInt(o.B1)) + case operationKindExtend: + var in, out string + if o.B3 { + in = "i32" + out = "i64" + } else { + in = "u32" + out = "u64" + } + return fmt.Sprintf("%s.%s.%s", out, o.Kind, in) + + case operationKindV128Const: + return fmt.Sprintf("%s [%#x, %#x]", o.Kind, o.U1, o.U2) + case operationKindV128Add, + operationKindV128Sub: + return fmt.Sprintf("%s (shape=%s)", o.Kind, shapeName(o.B1)) + case operationKindV128Load, + operationKindV128LoadLane, + operationKindV128Store, + operationKindV128StoreLane, + operationKindV128ExtractLane, + operationKindV128ReplaceLane, + operationKindV128Splat, + operationKindV128Shuffle, + operationKindV128Swizzle, + operationKindV128AnyTrue, + operationKindV128AllTrue, + operationKindV128BitMask, + operationKindV128And, + operationKindV128Not, + operationKindV128Or, + operationKindV128Xor, + operationKindV128Bitselect, + operationKindV128AndNot, + operationKindV128Shl, + operationKindV128Shr, + operationKindV128Cmp, + operationKindV128AddSat, + operationKindV128SubSat, + operationKindV128Mul, + operationKindV128Div, + operationKindV128Neg, + operationKindV128Sqrt, + operationKindV128Abs, + operationKindV128Popcnt, + operationKindV128Min, + operationKindV128Max, + operationKindV128AvgrU, + operationKindV128Pmin, + operationKindV128Pmax, + operationKindV128Ceil, + operationKindV128Floor, + operationKindV128Trunc, + operationKindV128Nearest, + operationKindV128Extend, + operationKindV128ExtMul, + operationKindV128Q15mulrSatS, + operationKindV128ExtAddPairwise, + operationKindV128FloatPromote, + operationKindV128FloatDemote, + operationKindV128FConvertFromI, + operationKindV128Dot, + operationKindV128Narrow: + return o.Kind.String() + + case operationKindV128ITruncSatFromF: + if o.B3 { + return fmt.Sprintf("%s.%sS", o.Kind, shapeName(o.B1)) + } else { + return fmt.Sprintf("%s.%sU", o.Kind, shapeName(o.B1)) + } + + case operationKindAtomicMemoryWait, + operationKindAtomicMemoryNotify, + operationKindAtomicFence, + operationKindAtomicLoad, + operationKindAtomicLoad8, + operationKindAtomicLoad16, + operationKindAtomicStore, + operationKindAtomicStore8, + operationKindAtomicStore16, + operationKindAtomicRMW, + operationKindAtomicRMW8, + operationKindAtomicRMW16, + operationKindAtomicRMWCmpxchg, + operationKindAtomicRMW8Cmpxchg, + operationKindAtomicRMW16Cmpxchg: + return o.Kind.String() + + default: + panic(fmt.Sprintf("TODO: %v", o.Kind)) + } +} + +// NewOperationUnreachable is a constructor for unionOperation with operationKindUnreachable +// +// This corresponds to wasm.OpcodeUnreachable. +// +// The engines are expected to exit the execution with wasmruntime.ErrRuntimeUnreachable error. +func newOperationUnreachable() unionOperation { + return unionOperation{Kind: operationKindUnreachable} +} + +// NewOperationLabel is a constructor for unionOperation with operationKindLabel. +// +// This is used to inform the engines of the beginning of a label. +func newOperationLabel(label label) unionOperation { + return unionOperation{Kind: operationKindLabel, U1: uint64(label)} +} + +// NewOperationBr is a constructor for unionOperation with operationKindBr. +// +// The engines are expected to branch into U1 label. +func newOperationBr(target label) unionOperation { + return unionOperation{Kind: operationKindBr, U1: uint64(target)} +} + +// NewOperationBrIf is a constructor for unionOperation with operationKindBrIf. +// +// The engines are expected to pop a value and branch into U1 label if the value equals 1. +// Otherwise, the code branches into U2 label. +func newOperationBrIf(thenTarget, elseTarget label, thenDrop inclusiveRange) unionOperation { + return unionOperation{ + Kind: operationKindBrIf, + U1: uint64(thenTarget), + U2: uint64(elseTarget), + U3: thenDrop.AsU64(), + } +} + +// NewOperationBrTable is a constructor for unionOperation with operationKindBrTable. +// +// This corresponds to wasm.OpcodeBrTableName except that the label +// here means the interpreterir level, not the ones of Wasm. +// +// The engines are expected to do the br_table operation based on the default (Us[len(Us)-1], Us[len(Us)-2]) and +// targets (Us[:len(Us)-1], Rs[:len(Us)-1]). More precisely, this pops a value from the stack (called "index") +// and decides which branch we go into next based on the value. +// +// For example, assume we have operations like {default: L_DEFAULT, targets: [L0, L1, L2]}. +// If "index" >= len(defaults), then branch into the L_DEFAULT label. +// Otherwise, we enter label of targets[index]. +func newOperationBrTable(targetLabelsAndRanges []uint64) unionOperation { + return unionOperation{ + Kind: operationKindBrTable, + Us: targetLabelsAndRanges, + } +} + +// NewOperationCall is a constructor for unionOperation with operationKindCall. +// +// This corresponds to wasm.OpcodeCallName, and engines are expected to +// enter into a function whose index equals OperationCall.FunctionIndex. +func newOperationCall(functionIndex uint32) unionOperation { + return unionOperation{Kind: operationKindCall, U1: uint64(functionIndex)} +} + +// NewOperationCallIndirect implements Operation. +// +// This corresponds to wasm.OpcodeCallIndirectName, and engines are expected to +// consume the one value from the top of stack (called "offset"), +// and make a function call against the function whose function address equals +// Tables[OperationCallIndirect.TableIndex][offset]. +// +// Note: This is called indirect function call in the sense that the target function is indirectly +// determined by the current state (top value) of the stack. +// Therefore, two checks are performed at runtime before entering the target function: +// 1) whether "offset" exceeds the length of table Tables[OperationCallIndirect.TableIndex]. +// 2) whether the type of the function table[offset] matches the function type specified by OperationCallIndirect.TypeIndex. +func newOperationCallIndirect(typeIndex, tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindCallIndirect, U1: uint64(typeIndex), U2: uint64(tableIndex)} +} + +// inclusiveRange is the range which spans across the value stack starting from the top to the bottom, and +// both boundary are included in the range. +type inclusiveRange struct { + Start, End int32 +} + +// AsU64 is be used to convert inclusiveRange to uint64 so that it can be stored in unionOperation. +func (i inclusiveRange) AsU64() uint64 { + return uint64(uint32(i.Start))<<32 | uint64(uint32(i.End)) +} + +// inclusiveRangeFromU64 retrieves inclusiveRange from the given uint64 which is stored in unionOperation. +func inclusiveRangeFromU64(v uint64) inclusiveRange { + return inclusiveRange{ + Start: int32(uint32(v >> 32)), + End: int32(uint32(v)), + } +} + +// nopinclusiveRange is inclusiveRange which corresponds to no-operation. +var nopinclusiveRange = inclusiveRange{Start: -1, End: -1} + +// NewOperationDrop is a constructor for unionOperation with operationKindDrop. +// +// The engines are expected to discard the values selected by NewOperationDrop.Depth which +// starts from the top of the stack to the bottom. +// +// depth spans across the uint64 value stack at runtime to be dropped by this operation. +func newOperationDrop(depth inclusiveRange) unionOperation { + return unionOperation{Kind: operationKindDrop, U1: depth.AsU64()} +} + +// NewOperationSelect is a constructor for unionOperation with operationKindSelect. +// +// This corresponds to wasm.OpcodeSelect. +// +// The engines are expected to pop three values, say [..., x2, x1, c], then if the value "c" equals zero, +// "x1" is pushed back onto the stack and, otherwise "x2" is pushed back. +// +// isTargetVector true if the selection target value's type is wasm.ValueTypeV128. +func newOperationSelect(isTargetVector bool) unionOperation { + return unionOperation{Kind: operationKindSelect, B3: isTargetVector} +} + +// NewOperationPick is a constructor for unionOperation with operationKindPick. +// +// The engines are expected to copy a value pointed by depth, and push the +// copied value onto the top of the stack. +// +// depth is the location of the pick target in the uint64 value stack at runtime. +// If isTargetVector=true, this points to the location of the lower 64-bits of the vector. +func newOperationPick(depth int, isTargetVector bool) unionOperation { + return unionOperation{Kind: operationKindPick, U1: uint64(depth), B3: isTargetVector} +} + +// NewOperationSet is a constructor for unionOperation with operationKindSet. +// +// The engines are expected to set the top value of the stack to the location specified by +// depth. +// +// depth is the location of the set target in the uint64 value stack at runtime. +// If isTargetVector=true, this points the location of the lower 64-bits of the vector. +func newOperationSet(depth int, isTargetVector bool) unionOperation { + return unionOperation{Kind: operationKindSet, U1: uint64(depth), B3: isTargetVector} +} + +// NewOperationGlobalGet is a constructor for unionOperation with operationKindGlobalGet. +// +// The engines are expected to read the global value specified by OperationGlobalGet.Index, +// and push the copy of the value onto the stack. +// +// See wasm.OpcodeGlobalGet. +func newOperationGlobalGet(index uint32) unionOperation { + return unionOperation{Kind: operationKindGlobalGet, U1: uint64(index)} +} + +// NewOperationGlobalSet is a constructor for unionOperation with operationKindGlobalSet. +// +// The engines are expected to consume the value from the top of the stack, +// and write the value into the global specified by OperationGlobalSet.Index. +// +// See wasm.OpcodeGlobalSet. +func newOperationGlobalSet(index uint32) unionOperation { + return unionOperation{Kind: operationKindGlobalSet, U1: uint64(index)} +} + +// memoryArg is the "memarg" to all memory instructions. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instructions%E2%91%A0 +type memoryArg struct { + // Alignment the expected alignment (expressed as the exponent of a power of 2). Default to the natural alignment. + // + // "Natural alignment" is defined here as the smallest power of two that can hold the size of the value type. Ex + // wasm.ValueTypeI64 is encoded in 8 little-endian bytes. 2^3 = 8, so the natural alignment is three. + Alignment uint32 + + // Offset is the address offset added to the instruction's dynamic address operand, yielding a 33-bit effective + // address that is the zero-based index at which the memory is accessed. Default to zero. + Offset uint32 +} + +// NewOperationLoad is a constructor for unionOperation with operationKindLoad. +// +// This corresponds to wasm.OpcodeI32LoadName wasm.OpcodeI64LoadName wasm.OpcodeF32LoadName and wasm.OpcodeF64LoadName. +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationLoad(unsignedType unsignedType, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindLoad, B1: byte(unsignedType), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationLoad8 is a constructor for unionOperation with operationKindLoad8. +// +// This corresponds to wasm.OpcodeI32Load8SName wasm.OpcodeI32Load8UName wasm.OpcodeI64Load8SName wasm.OpcodeI64Load8UName. +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationLoad8(signedInt signedInt, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindLoad8, B1: byte(signedInt), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationLoad16 is a constructor for unionOperation with operationKindLoad16. +// +// This corresponds to wasm.OpcodeI32Load16SName wasm.OpcodeI32Load16UName wasm.OpcodeI64Load16SName wasm.OpcodeI64Load16UName. +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationLoad16(signedInt signedInt, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindLoad16, B1: byte(signedInt), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationLoad32 is a constructor for unionOperation with operationKindLoad32. +// +// This corresponds to wasm.OpcodeI64Load32SName wasm.OpcodeI64Load32UName. +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise load the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationLoad32(signed bool, arg memoryArg) unionOperation { + sigB := byte(0) + if signed { + sigB = 1 + } + return unionOperation{Kind: operationKindLoad32, B1: sigB, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationStore is a constructor for unionOperation with operationKindStore. +// +// # This corresponds to wasm.OpcodeI32StoreName wasm.OpcodeI64StoreName wasm.OpcodeF32StoreName wasm.OpcodeF64StoreName +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationStore(unsignedType unsignedType, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindStore, B1: byte(unsignedType), U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationStore8 is a constructor for unionOperation with operationKindStore8. +// +// # This corresponds to wasm.OpcodeI32Store8Name wasm.OpcodeI64Store8Name +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationStore8(arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindStore8, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationStore16 is a constructor for unionOperation with operationKindStore16. +// +// # This corresponds to wasm.OpcodeI32Store16Name wasm.OpcodeI64Store16Name +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationStore16(arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindStore16, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationStore32 is a constructor for unionOperation with operationKindStore32. +// +// # This corresponds to wasm.OpcodeI64Store32Name +// +// The engines are expected to check the boundary of memory length, and exit the execution if this exceeds the boundary, +// otherwise store the corresponding value following the semantics of the corresponding WebAssembly instruction. +func newOperationStore32(arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindStore32, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationMemorySize is a constructor for unionOperation with operationKindMemorySize. +// +// This corresponds to wasm.OpcodeMemorySize. +// +// The engines are expected to push the current page size of the memory onto the stack. +func newOperationMemorySize() unionOperation { + return unionOperation{Kind: operationKindMemorySize} +} + +// NewOperationMemoryGrow is a constructor for unionOperation with operationKindMemoryGrow. +// +// This corresponds to wasm.OpcodeMemoryGrow. +// +// The engines are expected to pop one value from the top of the stack, then +// execute wasm.MemoryInstance Grow with the value, and push the previous +// page size of the memory onto the stack. +func newOperationMemoryGrow() unionOperation { + return unionOperation{Kind: operationKindMemoryGrow} +} + +// NewOperationConstI32 is a constructor for unionOperation with OperationConstI32. +// +// This corresponds to wasm.OpcodeI32Const. +func newOperationConstI32(value uint32) unionOperation { + return unionOperation{Kind: operationKindConstI32, U1: uint64(value)} +} + +// NewOperationConstI64 is a constructor for unionOperation with OperationConstI64. +// +// This corresponds to wasm.OpcodeI64Const. +func newOperationConstI64(value uint64) unionOperation { + return unionOperation{Kind: operationKindConstI64, U1: value} +} + +// NewOperationConstF32 is a constructor for unionOperation with OperationConstF32. +// +// This corresponds to wasm.OpcodeF32Const. +func newOperationConstF32(value float32) unionOperation { + return unionOperation{Kind: operationKindConstF32, U1: uint64(math.Float32bits(value))} +} + +// NewOperationConstF64 is a constructor for unionOperation with OperationConstF64. +// +// This corresponds to wasm.OpcodeF64Const. +func newOperationConstF64(value float64) unionOperation { + return unionOperation{Kind: operationKindConstF64, U1: math.Float64bits(value)} +} + +// NewOperationEq is a constructor for unionOperation with operationKindEq. +// +// This corresponds to wasm.OpcodeI32EqName wasm.OpcodeI64EqName wasm.OpcodeF32EqName wasm.OpcodeF64EqName +func newOperationEq(b unsignedType) unionOperation { + return unionOperation{Kind: operationKindEq, B1: byte(b)} +} + +// NewOperationNe is a constructor for unionOperation with operationKindNe. +// +// This corresponds to wasm.OpcodeI32NeName wasm.OpcodeI64NeName wasm.OpcodeF32NeName wasm.OpcodeF64NeName +func newOperationNe(b unsignedType) unionOperation { + return unionOperation{Kind: operationKindNe, B1: byte(b)} +} + +// NewOperationEqz is a constructor for unionOperation with operationKindEqz. +// +// This corresponds to wasm.OpcodeI32EqzName wasm.OpcodeI64EqzName +func newOperationEqz(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindEqz, B1: byte(b)} +} + +// NewOperationLt is a constructor for unionOperation with operationKindLt. +// +// This corresponds to wasm.OpcodeI32LtS wasm.OpcodeI32LtU wasm.OpcodeI64LtS wasm.OpcodeI64LtU wasm.OpcodeF32Lt wasm.OpcodeF64Lt +func newOperationLt(b signedType) unionOperation { + return unionOperation{Kind: operationKindLt, B1: byte(b)} +} + +// NewOperationGt is a constructor for unionOperation with operationKindGt. +// +// This corresponds to wasm.OpcodeI32GtS wasm.OpcodeI32GtU wasm.OpcodeI64GtS wasm.OpcodeI64GtU wasm.OpcodeF32Gt wasm.OpcodeF64Gt +func newOperationGt(b signedType) unionOperation { + return unionOperation{Kind: operationKindGt, B1: byte(b)} +} + +// NewOperationLe is a constructor for unionOperation with operationKindLe. +// +// This corresponds to wasm.OpcodeI32LeS wasm.OpcodeI32LeU wasm.OpcodeI64LeS wasm.OpcodeI64LeU wasm.OpcodeF32Le wasm.OpcodeF64Le +func newOperationLe(b signedType) unionOperation { + return unionOperation{Kind: operationKindLe, B1: byte(b)} +} + +// NewOperationGe is a constructor for unionOperation with operationKindGe. +// +// This corresponds to wasm.OpcodeI32GeS wasm.OpcodeI32GeU wasm.OpcodeI64GeS wasm.OpcodeI64GeU wasm.OpcodeF32Ge wasm.OpcodeF64Ge +// NewOperationGe is the constructor for OperationGe +func newOperationGe(b signedType) unionOperation { + return unionOperation{Kind: operationKindGe, B1: byte(b)} +} + +// NewOperationAdd is a constructor for unionOperation with operationKindAdd. +// +// This corresponds to wasm.OpcodeI32AddName wasm.OpcodeI64AddName wasm.OpcodeF32AddName wasm.OpcodeF64AddName. +func newOperationAdd(b unsignedType) unionOperation { + return unionOperation{Kind: operationKindAdd, B1: byte(b)} +} + +// NewOperationSub is a constructor for unionOperation with operationKindSub. +// +// This corresponds to wasm.OpcodeI32SubName wasm.OpcodeI64SubName wasm.OpcodeF32SubName wasm.OpcodeF64SubName. +func newOperationSub(b unsignedType) unionOperation { + return unionOperation{Kind: operationKindSub, B1: byte(b)} +} + +// NewOperationMul is a constructor for unionOperation with wperationKindMul. +// +// This corresponds to wasm.OpcodeI32MulName wasm.OpcodeI64MulName wasm.OpcodeF32MulName wasm.OpcodeF64MulName. +// NewOperationMul is the constructor for OperationMul +func newOperationMul(b unsignedType) unionOperation { + return unionOperation{Kind: operationKindMul, B1: byte(b)} +} + +// NewOperationClz is a constructor for unionOperation with operationKindClz. +// +// This corresponds to wasm.OpcodeI32ClzName wasm.OpcodeI64ClzName. +// +// The engines are expected to count up the leading zeros in the +// current top of the stack, and push the count result. +// For example, stack of [..., 0x00_ff_ff_ff] results in [..., 8]. +// See wasm.OpcodeI32Clz wasm.OpcodeI64Clz +func newOperationClz(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindClz, B1: byte(b)} +} + +// NewOperationCtz is a constructor for unionOperation with operationKindCtz. +// +// This corresponds to wasm.OpcodeI32CtzName wasm.OpcodeI64CtzName. +// +// The engines are expected to count up the trailing zeros in the +// current top of the stack, and push the count result. +// For example, stack of [..., 0xff_ff_ff_00] results in [..., 8]. +func newOperationCtz(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindCtz, B1: byte(b)} +} + +// NewOperationPopcnt is a constructor for unionOperation with operationKindPopcnt. +// +// This corresponds to wasm.OpcodeI32PopcntName wasm.OpcodeI64PopcntName. +// +// The engines are expected to count up the number of set bits in the +// current top of the stack, and push the count result. +// For example, stack of [..., 0b00_00_00_11] results in [..., 2]. +func newOperationPopcnt(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindPopcnt, B1: byte(b)} +} + +// NewOperationDiv is a constructor for unionOperation with operationKindDiv. +// +// This corresponds to wasm.OpcodeI32DivS wasm.OpcodeI32DivU wasm.OpcodeI64DivS +// +// wasm.OpcodeI64DivU wasm.OpcodeF32Div wasm.OpcodeF64Div. +func newOperationDiv(b signedType) unionOperation { + return unionOperation{Kind: operationKindDiv, B1: byte(b)} +} + +// NewOperationRem is a constructor for unionOperation with operationKindRem. +// +// This corresponds to wasm.OpcodeI32RemS wasm.OpcodeI32RemU wasm.OpcodeI64RemS wasm.OpcodeI64RemU. +// +// The engines are expected to perform division on the top +// two values of integer type on the stack and puts the remainder of the result +// onto the stack. For example, stack [..., 10, 3] results in [..., 1] where +// the quotient is discarded. +// NewOperationRem is the constructor for OperationRem +func newOperationRem(b signedInt) unionOperation { + return unionOperation{Kind: operationKindRem, B1: byte(b)} +} + +// NewOperationAnd is a constructor for unionOperation with operationKindAnd. +// +// # This corresponds to wasm.OpcodeI32AndName wasm.OpcodeI64AndName +// +// The engines are expected to perform "And" operation on +// top two values on the stack, and pushes the result. +func newOperationAnd(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindAnd, B1: byte(b)} +} + +// NewOperationOr is a constructor for unionOperation with operationKindOr. +// +// # This corresponds to wasm.OpcodeI32OrName wasm.OpcodeI64OrName +// +// The engines are expected to perform "Or" operation on +// top two values on the stack, and pushes the result. +func newOperationOr(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindOr, B1: byte(b)} +} + +// NewOperationXor is a constructor for unionOperation with operationKindXor. +// +// # This corresponds to wasm.OpcodeI32XorName wasm.OpcodeI64XorName +// +// The engines are expected to perform "Xor" operation on +// top two values on the stack, and pushes the result. +func newOperationXor(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindXor, B1: byte(b)} +} + +// NewOperationShl is a constructor for unionOperation with operationKindShl. +// +// # This corresponds to wasm.OpcodeI32ShlName wasm.OpcodeI64ShlName +// +// The engines are expected to perform "Shl" operation on +// top two values on the stack, and pushes the result. +func newOperationShl(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindShl, B1: byte(b)} +} + +// NewOperationShr is a constructor for unionOperation with operationKindShr. +// +// # This corresponds to wasm.OpcodeI32ShrSName wasm.OpcodeI32ShrUName wasm.OpcodeI64ShrSName wasm.OpcodeI64ShrUName +// +// If OperationShr.Type is signed integer, then, the engines are expected to perform arithmetic right shift on the two +// top values on the stack, otherwise do the logical right shift. +func newOperationShr(b signedInt) unionOperation { + return unionOperation{Kind: operationKindShr, B1: byte(b)} +} + +// NewOperationRotl is a constructor for unionOperation with operationKindRotl. +// +// # This corresponds to wasm.OpcodeI32RotlName wasm.OpcodeI64RotlName +// +// The engines are expected to perform "Rotl" operation on +// top two values on the stack, and pushes the result. +func newOperationRotl(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindRotl, B1: byte(b)} +} + +// NewOperationRotr is a constructor for unionOperation with operationKindRotr. +// +// # This corresponds to wasm.OpcodeI32RotrName wasm.OpcodeI64RotrName +// +// The engines are expected to perform "Rotr" operation on +// top two values on the stack, and pushes the result. +func newOperationRotr(b unsignedInt) unionOperation { + return unionOperation{Kind: operationKindRotr, B1: byte(b)} +} + +// NewOperationAbs is a constructor for unionOperation with operationKindAbs. +// +// This corresponds to wasm.OpcodeF32Abs wasm.OpcodeF64Abs +func newOperationAbs(b float) unionOperation { + return unionOperation{Kind: operationKindAbs, B1: byte(b)} +} + +// NewOperationNeg is a constructor for unionOperation with operationKindNeg. +// +// This corresponds to wasm.OpcodeF32Neg wasm.OpcodeF64Neg +func newOperationNeg(b float) unionOperation { + return unionOperation{Kind: operationKindNeg, B1: byte(b)} +} + +// NewOperationCeil is a constructor for unionOperation with operationKindCeil. +// +// This corresponds to wasm.OpcodeF32CeilName wasm.OpcodeF64CeilName +func newOperationCeil(b float) unionOperation { + return unionOperation{Kind: operationKindCeil, B1: byte(b)} +} + +// NewOperationFloor is a constructor for unionOperation with operationKindFloor. +// +// This corresponds to wasm.OpcodeF32FloorName wasm.OpcodeF64FloorName +func newOperationFloor(b float) unionOperation { + return unionOperation{Kind: operationKindFloor, B1: byte(b)} +} + +// NewOperationTrunc is a constructor for unionOperation with operationKindTrunc. +// +// This corresponds to wasm.OpcodeF32TruncName wasm.OpcodeF64TruncName +func newOperationTrunc(b float) unionOperation { + return unionOperation{Kind: operationKindTrunc, B1: byte(b)} +} + +// NewOperationNearest is a constructor for unionOperation with operationKindNearest. +// +// # This corresponds to wasm.OpcodeF32NearestName wasm.OpcodeF64NearestName +// +// Note: this is *not* equivalent to math.Round and instead has the same +// the semantics of LLVM's rint intrinsic. See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic. +// For example, math.Round(-4.5) produces -5 while we want to produce -4. +func newOperationNearest(b float) unionOperation { + return unionOperation{Kind: operationKindNearest, B1: byte(b)} +} + +// NewOperationSqrt is a constructor for unionOperation with operationKindSqrt. +// +// This corresponds to wasm.OpcodeF32SqrtName wasm.OpcodeF64SqrtName +func newOperationSqrt(b float) unionOperation { + return unionOperation{Kind: operationKindSqrt, B1: byte(b)} +} + +// NewOperationMin is a constructor for unionOperation with operationKindMin. +// +// # This corresponds to wasm.OpcodeF32MinName wasm.OpcodeF64MinName +// +// The engines are expected to pop two values from the stack, and push back the maximum of +// these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 1.9]. +// +// Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, +// which is a different behavior different from math.Min. +func newOperationMin(b float) unionOperation { + return unionOperation{Kind: operationKindMin, B1: byte(b)} +} + +// NewOperationMax is a constructor for unionOperation with operationKindMax. +// +// # This corresponds to wasm.OpcodeF32MaxName wasm.OpcodeF64MaxName +// +// The engines are expected to pop two values from the stack, and push back the maximum of +// these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 100.1]. +// +// Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, +// which is a different behavior different from math.Max. +func newOperationMax(b float) unionOperation { + return unionOperation{Kind: operationKindMax, B1: byte(b)} +} + +// NewOperationCopysign is a constructor for unionOperation with operationKindCopysign. +// +// # This corresponds to wasm.OpcodeF32CopysignName wasm.OpcodeF64CopysignName +// +// The engines are expected to pop two float values from the stack, and copy the signbit of +// the first-popped value to the last one. +// For example, stack [..., 1.213, -5.0] results in [..., -1.213]. +func newOperationCopysign(b float) unionOperation { + return unionOperation{Kind: operationKindCopysign, B1: byte(b)} +} + +// NewOperationI32WrapFromI64 is a constructor for unionOperation with operationKindI32WrapFromI64. +// +// This corresponds to wasm.OpcodeI32WrapI64 and equivalent to uint64(uint32(v)) in Go. +// +// The engines are expected to replace the 64-bit int on top of the stack +// with the corresponding 32-bit integer. +func newOperationI32WrapFromI64() unionOperation { + return unionOperation{Kind: operationKindI32WrapFromI64} +} + +// NewOperationITruncFromF is a constructor for unionOperation with operationKindITruncFromF. +// +// This corresponds to +// +// wasm.OpcodeI32TruncF32SName wasm.OpcodeI32TruncF32UName wasm.OpcodeI32TruncF64SName +// wasm.OpcodeI32TruncF64UName wasm.OpcodeI64TruncF32SName wasm.OpcodeI64TruncF32UName wasm.OpcodeI64TruncF64SName +// wasm.OpcodeI64TruncF64UName. wasm.OpcodeI32TruncSatF32SName wasm.OpcodeI32TruncSatF32UName +// wasm.OpcodeI32TruncSatF64SName wasm.OpcodeI32TruncSatF64UName wasm.OpcodeI64TruncSatF32SName +// wasm.OpcodeI64TruncSatF32UName wasm.OpcodeI64TruncSatF64SName wasm.OpcodeI64TruncSatF64UName +// +// See [1] and [2] for when we encounter undefined behavior in the WebAssembly specification if NewOperationITruncFromF.NonTrapping == false. +// To summarize, if the source float value is NaN or doesn't fit in the destination range of integers (incl. +=Inf), +// then the runtime behavior is undefined. In wazero, the engines are expected to exit the execution in these undefined cases with +// wasmruntime.ErrRuntimeInvalidConversionToInteger error. +// +// [1] https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefop-trunc-umathrmtruncmathsfu_m-n-z for unsigned integers. +// [2] https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefop-trunc-smathrmtruncmathsfs_m-n-z for signed integers. +// +// nonTrapping true if this conversion is "nontrapping" in the sense of the +// https://github.com/WebAssembly/spec/blob/ce4b6c4d47eb06098cc7ab2e81f24748da822f20/proposals/nontrapping-float-to-int-conversion/Overview.md +func newOperationITruncFromF(inputType float, outputType signedInt, nonTrapping bool) unionOperation { + return unionOperation{ + Kind: operationKindITruncFromF, + B1: byte(inputType), + B2: byte(outputType), + B3: nonTrapping, + } +} + +// NewOperationFConvertFromI is a constructor for unionOperation with operationKindFConvertFromI. +// +// This corresponds to +// +// wasm.OpcodeF32ConvertI32SName wasm.OpcodeF32ConvertI32UName wasm.OpcodeF32ConvertI64SName wasm.OpcodeF32ConvertI64UName +// wasm.OpcodeF64ConvertI32SName wasm.OpcodeF64ConvertI32UName wasm.OpcodeF64ConvertI64SName wasm.OpcodeF64ConvertI64UName +// +// and equivalent to float32(uint32(x)), float32(int32(x)), etc in Go. +func newOperationFConvertFromI(inputType signedInt, outputType float) unionOperation { + return unionOperation{ + Kind: operationKindFConvertFromI, + B1: byte(inputType), + B2: byte(outputType), + } +} + +// NewOperationF32DemoteFromF64 is a constructor for unionOperation with operationKindF32DemoteFromF64. +// +// This corresponds to wasm.OpcodeF32DemoteF64 and is equivalent float32(float64(v)). +func newOperationF32DemoteFromF64() unionOperation { + return unionOperation{Kind: operationKindF32DemoteFromF64} +} + +// NewOperationF64PromoteFromF32 is a constructor for unionOperation with operationKindF64PromoteFromF32. +// +// This corresponds to wasm.OpcodeF64PromoteF32 and is equivalent float64(float32(v)). +func newOperationF64PromoteFromF32() unionOperation { + return unionOperation{Kind: operationKindF64PromoteFromF32} +} + +// NewOperationI32ReinterpretFromF32 is a constructor for unionOperation with operationKindI32ReinterpretFromF32. +// +// This corresponds to wasm.OpcodeI32ReinterpretF32Name. +func newOperationI32ReinterpretFromF32() unionOperation { + return unionOperation{Kind: operationKindI32ReinterpretFromF32} +} + +// NewOperationI64ReinterpretFromF64 is a constructor for unionOperation with operationKindI64ReinterpretFromF64. +// +// This corresponds to wasm.OpcodeI64ReinterpretF64Name. +func newOperationI64ReinterpretFromF64() unionOperation { + return unionOperation{Kind: operationKindI64ReinterpretFromF64} +} + +// NewOperationF32ReinterpretFromI32 is a constructor for unionOperation with operationKindF32ReinterpretFromI32. +// +// This corresponds to wasm.OpcodeF32ReinterpretI32Name. +func newOperationF32ReinterpretFromI32() unionOperation { + return unionOperation{Kind: operationKindF32ReinterpretFromI32} +} + +// NewOperationF64ReinterpretFromI64 is a constructor for unionOperation with operationKindF64ReinterpretFromI64. +// +// This corresponds to wasm.OpcodeF64ReinterpretI64Name. +func newOperationF64ReinterpretFromI64() unionOperation { + return unionOperation{Kind: operationKindF64ReinterpretFromI64} +} + +// NewOperationExtend is a constructor for unionOperation with operationKindExtend. +// +// # This corresponds to wasm.OpcodeI64ExtendI32SName wasm.OpcodeI64ExtendI32UName +// +// The engines are expected to extend the 32-bit signed or unsigned int on top of the stack +// as a 64-bit integer of corresponding signedness. For unsigned case, this is just reinterpreting the +// underlying bit pattern as 64-bit integer. For signed case, this is sign-extension which preserves the +// original integer's sign. +func newOperationExtend(signed bool) unionOperation { + op := unionOperation{Kind: operationKindExtend} + if signed { + op.B1 = 1 + } + return op +} + +// NewOperationSignExtend32From8 is a constructor for unionOperation with operationKindSignExtend32From8. +// +// This corresponds to wasm.OpcodeI32Extend8SName. +// +// The engines are expected to sign-extend the first 8-bits of 32-bit in as signed 32-bit int. +func newOperationSignExtend32From8() unionOperation { + return unionOperation{Kind: operationKindSignExtend32From8} +} + +// NewOperationSignExtend32From16 is a constructor for unionOperation with operationKindSignExtend32From16. +// +// This corresponds to wasm.OpcodeI32Extend16SName. +// +// The engines are expected to sign-extend the first 16-bits of 32-bit in as signed 32-bit int. +func newOperationSignExtend32From16() unionOperation { + return unionOperation{Kind: operationKindSignExtend32From16} +} + +// NewOperationSignExtend64From8 is a constructor for unionOperation with operationKindSignExtend64From8. +// +// This corresponds to wasm.OpcodeI64Extend8SName. +// +// The engines are expected to sign-extend the first 8-bits of 64-bit in as signed 32-bit int. +func newOperationSignExtend64From8() unionOperation { + return unionOperation{Kind: operationKindSignExtend64From8} +} + +// NewOperationSignExtend64From16 is a constructor for unionOperation with operationKindSignExtend64From16. +// +// This corresponds to wasm.OpcodeI64Extend16SName. +// +// The engines are expected to sign-extend the first 16-bits of 64-bit in as signed 32-bit int. +func newOperationSignExtend64From16() unionOperation { + return unionOperation{Kind: operationKindSignExtend64From16} +} + +// NewOperationSignExtend64From32 is a constructor for unionOperation with operationKindSignExtend64From32. +// +// This corresponds to wasm.OpcodeI64Extend32SName. +// +// The engines are expected to sign-extend the first 32-bits of 64-bit in as signed 32-bit int. +func newOperationSignExtend64From32() unionOperation { + return unionOperation{Kind: operationKindSignExtend64From32} +} + +// NewOperationMemoryInit is a constructor for unionOperation with operationKindMemoryInit. +// +// This corresponds to wasm.OpcodeMemoryInitName. +// +// dataIndex is the index of the data instance in ModuleInstance.DataInstances +// by which this operation instantiates a part of the memory. +func newOperationMemoryInit(dataIndex uint32) unionOperation { + return unionOperation{Kind: operationKindMemoryInit, U1: uint64(dataIndex)} +} + +// NewOperationDataDrop implements Operation. +// +// This corresponds to wasm.OpcodeDataDropName. +// +// dataIndex is the index of the data instance in ModuleInstance.DataInstances +// which this operation drops. +func newOperationDataDrop(dataIndex uint32) unionOperation { + return unionOperation{Kind: operationKindDataDrop, U1: uint64(dataIndex)} +} + +// NewOperationMemoryCopy is a consuctor for unionOperation with operationKindMemoryCopy. +// +// This corresponds to wasm.OpcodeMemoryCopyName. +func newOperationMemoryCopy() unionOperation { + return unionOperation{Kind: operationKindMemoryCopy} +} + +// NewOperationMemoryFill is a consuctor for unionOperation with operationKindMemoryFill. +func newOperationMemoryFill() unionOperation { + return unionOperation{Kind: operationKindMemoryFill} +} + +// NewOperationTableInit is a constructor for unionOperation with operationKindTableInit. +// +// This corresponds to wasm.OpcodeTableInitName. +// +// elemIndex is the index of the element by which this operation initializes a part of the table. +// tableIndex is the index of the table on which this operation initialize by the target element. +func newOperationTableInit(elemIndex, tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableInit, U1: uint64(elemIndex), U2: uint64(tableIndex)} +} + +// NewOperationElemDrop is a constructor for unionOperation with operationKindElemDrop. +// +// This corresponds to wasm.OpcodeElemDropName. +// +// elemIndex is the index of the element which this operation drops. +func newOperationElemDrop(elemIndex uint32) unionOperation { + return unionOperation{Kind: operationKindElemDrop, U1: uint64(elemIndex)} +} + +// NewOperationTableCopy implements Operation. +// +// This corresponds to wasm.OpcodeTableCopyName. +func newOperationTableCopy(srcTableIndex, dstTableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableCopy, U1: uint64(srcTableIndex), U2: uint64(dstTableIndex)} +} + +// NewOperationRefFunc constructor for unionOperation with operationKindRefFunc. +// +// This corresponds to wasm.OpcodeRefFuncName, and engines are expected to +// push the opaque pointer value of engine specific func for the given FunctionIndex. +// +// Note: in wazero, we express any reference types (funcref or externref) as opaque pointers which is uint64. +// Therefore, the engine implementations emit instructions to push the address of *function onto the stack. +func newOperationRefFunc(functionIndex uint32) unionOperation { + return unionOperation{Kind: operationKindRefFunc, U1: uint64(functionIndex)} +} + +// NewOperationTableGet constructor for unionOperation with operationKindTableGet. +// +// This corresponds to wasm.OpcodeTableGetName. +func newOperationTableGet(tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableGet, U1: uint64(tableIndex)} +} + +// NewOperationTableSet constructor for unionOperation with operationKindTableSet. +// +// This corresponds to wasm.OpcodeTableSetName. +func newOperationTableSet(tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableSet, U1: uint64(tableIndex)} +} + +// NewOperationTableSize constructor for unionOperation with operationKindTableSize. +// +// This corresponds to wasm.OpcodeTableSizeName. +func newOperationTableSize(tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableSize, U1: uint64(tableIndex)} +} + +// NewOperationTableGrow constructor for unionOperation with operationKindTableGrow. +// +// This corresponds to wasm.OpcodeTableGrowName. +func newOperationTableGrow(tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableGrow, U1: uint64(tableIndex)} +} + +// NewOperationTableFill constructor for unionOperation with operationKindTableFill. +// +// This corresponds to wasm.OpcodeTableFillName. +func newOperationTableFill(tableIndex uint32) unionOperation { + return unionOperation{Kind: operationKindTableFill, U1: uint64(tableIndex)} +} + +// NewOperationV128Const constructor for unionOperation with operationKindV128Const +func newOperationV128Const(lo, hi uint64) unionOperation { + return unionOperation{Kind: operationKindV128Const, U1: lo, U2: hi} +} + +// shape corresponds to a shape of v128 values. +// https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-shape +type shape = byte + +const ( + shapeI8x16 shape = iota + shapeI16x8 + shapeI32x4 + shapeI64x2 + shapeF32x4 + shapeF64x2 +) + +func shapeName(s shape) (ret string) { + switch s { + case shapeI8x16: + ret = "I8x16" + case shapeI16x8: + ret = "I16x8" + case shapeI32x4: + ret = "I32x4" + case shapeI64x2: + ret = "I64x2" + case shapeF32x4: + ret = "F32x4" + case shapeF64x2: + ret = "F64x2" + } + return +} + +// NewOperationV128Add constructor for unionOperation with operationKindV128Add. +// +// This corresponds to wasm.OpcodeVecI8x16AddName wasm.OpcodeVecI16x8AddName wasm.OpcodeVecI32x4AddName +// +// wasm.OpcodeVecI64x2AddName wasm.OpcodeVecF32x4AddName wasm.OpcodeVecF64x2AddName +func newOperationV128Add(shape shape) unionOperation { + return unionOperation{Kind: operationKindV128Add, B1: shape} +} + +// NewOperationV128Sub constructor for unionOperation with operationKindV128Sub. +// +// This corresponds to wasm.OpcodeVecI8x16SubName wasm.OpcodeVecI16x8SubName wasm.OpcodeVecI32x4SubName +// +// wasm.OpcodeVecI64x2SubName wasm.OpcodeVecF32x4SubName wasm.OpcodeVecF64x2SubName +func newOperationV128Sub(shape shape) unionOperation { + return unionOperation{Kind: operationKindV128Sub, B1: shape} +} + +// v128LoadType represents a type of wasm.OpcodeVecV128Load* instructions. +type v128LoadType = byte + +const ( + // v128LoadType128 corresponds to wasm.OpcodeVecV128LoadName. + v128LoadType128 v128LoadType = iota + // v128LoadType8x8s corresponds to wasm.OpcodeVecV128Load8x8SName. + v128LoadType8x8s + // v128LoadType8x8u corresponds to wasm.OpcodeVecV128Load8x8UName. + v128LoadType8x8u + // v128LoadType16x4s corresponds to wasm.OpcodeVecV128Load16x4SName + v128LoadType16x4s + // v128LoadType16x4u corresponds to wasm.OpcodeVecV128Load16x4UName + v128LoadType16x4u + // v128LoadType32x2s corresponds to wasm.OpcodeVecV128Load32x2SName + v128LoadType32x2s + // v128LoadType32x2u corresponds to wasm.OpcodeVecV128Load32x2UName + v128LoadType32x2u + // v128LoadType8Splat corresponds to wasm.OpcodeVecV128Load8SplatName + v128LoadType8Splat + // v128LoadType16Splat corresponds to wasm.OpcodeVecV128Load16SplatName + v128LoadType16Splat + // v128LoadType32Splat corresponds to wasm.OpcodeVecV128Load32SplatName + v128LoadType32Splat + // v128LoadType64Splat corresponds to wasm.OpcodeVecV128Load64SplatName + v128LoadType64Splat + // v128LoadType32zero corresponds to wasm.OpcodeVecV128Load32zeroName + v128LoadType32zero + // v128LoadType64zero corresponds to wasm.OpcodeVecV128Load64zeroName + v128LoadType64zero +) + +// NewOperationV128Load is a constructor for unionOperation with operationKindV128Load. +// +// This corresponds to +// +// wasm.OpcodeVecV128LoadName wasm.OpcodeVecV128Load8x8SName wasm.OpcodeVecV128Load8x8UName +// wasm.OpcodeVecV128Load16x4SName wasm.OpcodeVecV128Load16x4UName wasm.OpcodeVecV128Load32x2SName +// wasm.OpcodeVecV128Load32x2UName wasm.OpcodeVecV128Load8SplatName wasm.OpcodeVecV128Load16SplatName +// wasm.OpcodeVecV128Load32SplatName wasm.OpcodeVecV128Load64SplatName wasm.OpcodeVecV128Load32zeroName +// wasm.OpcodeVecV128Load64zeroName +func newOperationV128Load(loadType v128LoadType, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindV128Load, B1: loadType, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationV128LoadLane is a constructor for unionOperation with operationKindV128LoadLane. +// +// This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName +// +// wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. +// +// laneIndex is >=0 && <(128/LaneSize). +// laneSize is either 8, 16, 32, or 64. +func newOperationV128LoadLane(laneIndex, laneSize byte, arg memoryArg) unionOperation { + return unionOperation{Kind: operationKindV128LoadLane, B1: laneSize, B2: laneIndex, U1: uint64(arg.Alignment), U2: uint64(arg.Offset)} +} + +// NewOperationV128Store is a constructor for unionOperation with operationKindV128Store. +// +// This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName +// +// wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. +func newOperationV128Store(arg memoryArg) unionOperation { + return unionOperation{ + Kind: operationKindV128Store, + U1: uint64(arg.Alignment), + U2: uint64(arg.Offset), + } +} + +// NewOperationV128StoreLane implements Operation. +// +// This corresponds to wasm.OpcodeVecV128Load8LaneName wasm.OpcodeVecV128Load16LaneName +// +// wasm.OpcodeVecV128Load32LaneName wasm.OpcodeVecV128Load64LaneName. +// +// laneIndex is >=0 && <(128/LaneSize). +// laneSize is either 8, 16, 32, or 64. +func newOperationV128StoreLane(laneIndex byte, laneSize byte, arg memoryArg) unionOperation { + return unionOperation{ + Kind: operationKindV128StoreLane, + B1: laneSize, + B2: laneIndex, + U1: uint64(arg.Alignment), + U2: uint64(arg.Offset), + } +} + +// NewOperationV128ExtractLane is a constructor for unionOperation with operationKindV128ExtractLane. +// +// This corresponds to +// +// wasm.OpcodeVecI8x16ExtractLaneSName wasm.OpcodeVecI8x16ExtractLaneUName +// wasm.OpcodeVecI16x8ExtractLaneSName wasm.OpcodeVecI16x8ExtractLaneUName +// wasm.OpcodeVecI32x4ExtractLaneName wasm.OpcodeVecI64x2ExtractLaneName +// wasm.OpcodeVecF32x4ExtractLaneName wasm.OpcodeVecF64x2ExtractLaneName. +// +// laneIndex is >=0 && =0 && = l { + return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l) + } + var t wasm.ValueType + if index < inputLen { + t = c.sig.Params[index] + } else { + t = c.localTypes[index-inputLen] + } + return wasmValueTypeToUnsignedOutSignature(t), nil + case wasm.OpcodeLocalSet: + inputLen := uint32(len(c.sig.Params)) + if l := uint32(len(c.localTypes)) + inputLen; index >= l { + return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l) + } + var t wasm.ValueType + if index < inputLen { + t = c.sig.Params[index] + } else { + t = c.localTypes[index-inputLen] + } + return wasmValueTypeToUnsignedInSignature(t), nil + case wasm.OpcodeLocalTee: + inputLen := uint32(len(c.sig.Params)) + if l := uint32(len(c.localTypes)) + inputLen; index >= l { + return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l) + } + var t wasm.ValueType + if index < inputLen { + t = c.sig.Params[index] + } else { + t = c.localTypes[index-inputLen] + } + return wasmValueTypeToUnsignedInOutSignature(t), nil + case wasm.OpcodeGlobalGet: + if len(c.globals) <= int(index) { + return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals)) + } + return wasmValueTypeToUnsignedOutSignature(c.globals[index].ValType), nil + case wasm.OpcodeGlobalSet: + if len(c.globals) <= int(index) { + return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals)) + } + return wasmValueTypeToUnsignedInSignature(c.globals[index].ValType), nil + case wasm.OpcodeI32Load: + return signature_I32_I32, nil + case wasm.OpcodeI64Load: + return signature_I32_I64, nil + case wasm.OpcodeF32Load: + return signature_I32_F32, nil + case wasm.OpcodeF64Load: + return signature_I32_F64, nil + case wasm.OpcodeI32Load8S, wasm.OpcodeI32Load8U, wasm.OpcodeI32Load16S, wasm.OpcodeI32Load16U: + return signature_I32_I32, nil + case wasm.OpcodeI64Load8S, wasm.OpcodeI64Load8U, wasm.OpcodeI64Load16S, wasm.OpcodeI64Load16U, + wasm.OpcodeI64Load32S, wasm.OpcodeI64Load32U: + return signature_I32_I64, nil + case wasm.OpcodeI32Store: + return signature_I32I32_None, nil + case wasm.OpcodeI64Store: + return signature_I32I64_None, nil + case wasm.OpcodeF32Store: + return signature_I32F32_None, nil + case wasm.OpcodeF64Store: + return signature_I32F64_None, nil + case wasm.OpcodeI32Store8: + return signature_I32I32_None, nil + case wasm.OpcodeI32Store16: + return signature_I32I32_None, nil + case wasm.OpcodeI64Store8: + return signature_I32I64_None, nil + case wasm.OpcodeI64Store16: + return signature_I32I64_None, nil + case wasm.OpcodeI64Store32: + return signature_I32I64_None, nil + case wasm.OpcodeMemorySize: + return signature_None_I32, nil + case wasm.OpcodeMemoryGrow: + return signature_I32_I32, nil + case wasm.OpcodeI32Const: + return signature_None_I32, nil + case wasm.OpcodeI64Const: + return signature_None_I64, nil + case wasm.OpcodeF32Const: + return signature_None_F32, nil + case wasm.OpcodeF64Const: + return signature_None_F64, nil + case wasm.OpcodeI32Eqz: + return signature_I32_I32, nil + case wasm.OpcodeI32Eq, wasm.OpcodeI32Ne, wasm.OpcodeI32LtS, + wasm.OpcodeI32LtU, wasm.OpcodeI32GtS, wasm.OpcodeI32GtU, + wasm.OpcodeI32LeS, wasm.OpcodeI32LeU, wasm.OpcodeI32GeS, + wasm.OpcodeI32GeU: + return signature_I32I32_I32, nil + case wasm.OpcodeI64Eqz: + return signature_I64_I32, nil + case wasm.OpcodeI64Eq, wasm.OpcodeI64Ne, wasm.OpcodeI64LtS, + wasm.OpcodeI64LtU, wasm.OpcodeI64GtS, wasm.OpcodeI64GtU, + wasm.OpcodeI64LeS, wasm.OpcodeI64LeU, wasm.OpcodeI64GeS, + wasm.OpcodeI64GeU: + return signature_I64I64_I32, nil + case wasm.OpcodeF32Eq, wasm.OpcodeF32Ne, wasm.OpcodeF32Lt, + wasm.OpcodeF32Gt, wasm.OpcodeF32Le, wasm.OpcodeF32Ge: + return signature_F32F32_I32, nil + case wasm.OpcodeF64Eq, wasm.OpcodeF64Ne, wasm.OpcodeF64Lt, + wasm.OpcodeF64Gt, wasm.OpcodeF64Le, wasm.OpcodeF64Ge: + return signature_F64F64_I32, nil + case wasm.OpcodeI32Clz, wasm.OpcodeI32Ctz, wasm.OpcodeI32Popcnt: + return signature_I32_I32, nil + case wasm.OpcodeI32Add, wasm.OpcodeI32Sub, wasm.OpcodeI32Mul, + wasm.OpcodeI32DivS, wasm.OpcodeI32DivU, wasm.OpcodeI32RemS, + wasm.OpcodeI32RemU, wasm.OpcodeI32And, wasm.OpcodeI32Or, + wasm.OpcodeI32Xor, wasm.OpcodeI32Shl, wasm.OpcodeI32ShrS, + wasm.OpcodeI32ShrU, wasm.OpcodeI32Rotl, wasm.OpcodeI32Rotr: + return signature_I32I32_I32, nil + case wasm.OpcodeI64Clz, wasm.OpcodeI64Ctz, wasm.OpcodeI64Popcnt: + return signature_I64_I64, nil + case wasm.OpcodeI64Add, wasm.OpcodeI64Sub, wasm.OpcodeI64Mul, + wasm.OpcodeI64DivS, wasm.OpcodeI64DivU, wasm.OpcodeI64RemS, + wasm.OpcodeI64RemU, wasm.OpcodeI64And, wasm.OpcodeI64Or, + wasm.OpcodeI64Xor, wasm.OpcodeI64Shl, wasm.OpcodeI64ShrS, + wasm.OpcodeI64ShrU, wasm.OpcodeI64Rotl, wasm.OpcodeI64Rotr: + return signature_I64I64_I64, nil + case wasm.OpcodeF32Abs, wasm.OpcodeF32Neg, wasm.OpcodeF32Ceil, + wasm.OpcodeF32Floor, wasm.OpcodeF32Trunc, wasm.OpcodeF32Nearest, + wasm.OpcodeF32Sqrt: + return signature_F32_F32, nil + case wasm.OpcodeF32Add, wasm.OpcodeF32Sub, wasm.OpcodeF32Mul, + wasm.OpcodeF32Div, wasm.OpcodeF32Min, wasm.OpcodeF32Max, + wasm.OpcodeF32Copysign: + return signature_F32F32_F32, nil + case wasm.OpcodeF64Abs, wasm.OpcodeF64Neg, wasm.OpcodeF64Ceil, + wasm.OpcodeF64Floor, wasm.OpcodeF64Trunc, wasm.OpcodeF64Nearest, + wasm.OpcodeF64Sqrt: + return signature_F64_F64, nil + case wasm.OpcodeF64Add, wasm.OpcodeF64Sub, wasm.OpcodeF64Mul, + wasm.OpcodeF64Div, wasm.OpcodeF64Min, wasm.OpcodeF64Max, + wasm.OpcodeF64Copysign: + return signature_F64F64_F64, nil + case wasm.OpcodeI32WrapI64: + return signature_I64_I32, nil + case wasm.OpcodeI32TruncF32S, wasm.OpcodeI32TruncF32U: + return signature_F32_I32, nil + case wasm.OpcodeI32TruncF64S, wasm.OpcodeI32TruncF64U: + return signature_F64_I32, nil + case wasm.OpcodeI64ExtendI32S, wasm.OpcodeI64ExtendI32U: + return signature_I32_I64, nil + case wasm.OpcodeI64TruncF32S, wasm.OpcodeI64TruncF32U: + return signature_F32_I64, nil + case wasm.OpcodeI64TruncF64S, wasm.OpcodeI64TruncF64U: + return signature_F64_I64, nil + case wasm.OpcodeF32ConvertI32S, wasm.OpcodeF32ConvertI32U: + return signature_I32_F32, nil + case wasm.OpcodeF32ConvertI64S, wasm.OpcodeF32ConvertI64U: + return signature_I64_F32, nil + case wasm.OpcodeF32DemoteF64: + return signature_F64_F32, nil + case wasm.OpcodeF64ConvertI32S, wasm.OpcodeF64ConvertI32U: + return signature_I32_F64, nil + case wasm.OpcodeF64ConvertI64S, wasm.OpcodeF64ConvertI64U: + return signature_I64_F64, nil + case wasm.OpcodeF64PromoteF32: + return signature_F32_F64, nil + case wasm.OpcodeI32ReinterpretF32: + return signature_F32_I32, nil + case wasm.OpcodeI64ReinterpretF64: + return signature_F64_I64, nil + case wasm.OpcodeF32ReinterpretI32: + return signature_I32_F32, nil + case wasm.OpcodeF64ReinterpretI64: + return signature_I64_F64, nil + case wasm.OpcodeI32Extend8S, wasm.OpcodeI32Extend16S: + return signature_I32_I32, nil + case wasm.OpcodeI64Extend8S, wasm.OpcodeI64Extend16S, wasm.OpcodeI64Extend32S: + return signature_I64_I64, nil + case wasm.OpcodeTableGet: + // table.get takes table's offset and pushes the ref type value of opaque pointer as i64 value onto the stack. + return signature_I32_I64, nil + case wasm.OpcodeTableSet: + // table.set takes table's offset and the ref type value of opaque pointer as i64 value. + return signature_I32I64_None, nil + case wasm.OpcodeRefFunc: + // ref.func is translated as pushing the compiled function's opaque pointer (uint64) at interpreterir layer. + return signature_None_I64, nil + case wasm.OpcodeRefIsNull: + // ref.is_null is translated as checking if the uint64 on the top of the stack (opaque pointer) is zero or not. + return signature_I64_I32, nil + case wasm.OpcodeRefNull: + // ref.null is translated as i64.const 0. + return signature_None_I64, nil + case wasm.OpcodeMiscPrefix: + switch miscOp := c.body[c.pc+1]; miscOp { + case wasm.OpcodeMiscI32TruncSatF32S, wasm.OpcodeMiscI32TruncSatF32U: + return signature_F32_I32, nil + case wasm.OpcodeMiscI32TruncSatF64S, wasm.OpcodeMiscI32TruncSatF64U: + return signature_F64_I32, nil + case wasm.OpcodeMiscI64TruncSatF32S, wasm.OpcodeMiscI64TruncSatF32U: + return signature_F32_I64, nil + case wasm.OpcodeMiscI64TruncSatF64S, wasm.OpcodeMiscI64TruncSatF64U: + return signature_F64_I64, nil + case wasm.OpcodeMiscMemoryInit, wasm.OpcodeMiscMemoryCopy, wasm.OpcodeMiscMemoryFill, + wasm.OpcodeMiscTableInit, wasm.OpcodeMiscTableCopy: + return signature_I32I32I32_None, nil + case wasm.OpcodeMiscDataDrop, wasm.OpcodeMiscElemDrop: + return signature_None_None, nil + case wasm.OpcodeMiscTableGrow: + return signature_I64I32_I32, nil + case wasm.OpcodeMiscTableSize: + return signature_None_I32, nil + case wasm.OpcodeMiscTableFill: + return signature_I32I64I32_None, nil + default: + return nil, fmt.Errorf("unsupported misc instruction in interpreterir: 0x%x", op) + } + case wasm.OpcodeVecPrefix: + switch vecOp := c.body[c.pc+1]; vecOp { + case wasm.OpcodeVecV128Const: + return signature_None_V128, nil + case wasm.OpcodeVecV128Load, wasm.OpcodeVecV128Load8x8s, wasm.OpcodeVecV128Load8x8u, + wasm.OpcodeVecV128Load16x4s, wasm.OpcodeVecV128Load16x4u, wasm.OpcodeVecV128Load32x2s, + wasm.OpcodeVecV128Load32x2u, wasm.OpcodeVecV128Load8Splat, wasm.OpcodeVecV128Load16Splat, + wasm.OpcodeVecV128Load32Splat, wasm.OpcodeVecV128Load64Splat, wasm.OpcodeVecV128Load32zero, + wasm.OpcodeVecV128Load64zero: + return signature_I32_V128, nil + case wasm.OpcodeVecV128Load8Lane, wasm.OpcodeVecV128Load16Lane, + wasm.OpcodeVecV128Load32Lane, wasm.OpcodeVecV128Load64Lane: + return signature_I32V128_V128, nil + case wasm.OpcodeVecV128Store, + wasm.OpcodeVecV128Store8Lane, + wasm.OpcodeVecV128Store16Lane, + wasm.OpcodeVecV128Store32Lane, + wasm.OpcodeVecV128Store64Lane: + return signature_I32V128_None, nil + case wasm.OpcodeVecI8x16ExtractLaneS, + wasm.OpcodeVecI8x16ExtractLaneU, + wasm.OpcodeVecI16x8ExtractLaneS, + wasm.OpcodeVecI16x8ExtractLaneU, + wasm.OpcodeVecI32x4ExtractLane: + return signature_V128_I32, nil + case wasm.OpcodeVecI64x2ExtractLane: + return signature_V128_I64, nil + case wasm.OpcodeVecF32x4ExtractLane: + return signature_V128_F32, nil + case wasm.OpcodeVecF64x2ExtractLane: + return signature_V128_F64, nil + case wasm.OpcodeVecI8x16ReplaceLane, wasm.OpcodeVecI16x8ReplaceLane, wasm.OpcodeVecI32x4ReplaceLane, + wasm.OpcodeVecI8x16Shl, wasm.OpcodeVecI8x16ShrS, wasm.OpcodeVecI8x16ShrU, + wasm.OpcodeVecI16x8Shl, wasm.OpcodeVecI16x8ShrS, wasm.OpcodeVecI16x8ShrU, + wasm.OpcodeVecI32x4Shl, wasm.OpcodeVecI32x4ShrS, wasm.OpcodeVecI32x4ShrU, + wasm.OpcodeVecI64x2Shl, wasm.OpcodeVecI64x2ShrS, wasm.OpcodeVecI64x2ShrU: + return signature_V128I32_V128, nil + case wasm.OpcodeVecI64x2ReplaceLane: + return signature_V128I64_V128, nil + case wasm.OpcodeVecF32x4ReplaceLane: + return signature_V128F32_V128, nil + case wasm.OpcodeVecF64x2ReplaceLane: + return signature_V128F64_V128, nil + case wasm.OpcodeVecI8x16Splat, + wasm.OpcodeVecI16x8Splat, + wasm.OpcodeVecI32x4Splat: + return signature_I32_V128, nil + case wasm.OpcodeVecI64x2Splat: + return signature_I64_V128, nil + case wasm.OpcodeVecF32x4Splat: + return signature_F32_V128, nil + case wasm.OpcodeVecF64x2Splat: + return signature_F64_V128, nil + case wasm.OpcodeVecV128i8x16Shuffle, wasm.OpcodeVecI8x16Swizzle, wasm.OpcodeVecV128And, wasm.OpcodeVecV128Or, wasm.OpcodeVecV128Xor, wasm.OpcodeVecV128AndNot: + return signature_V128V128_V128, nil + case wasm.OpcodeVecI8x16AllTrue, wasm.OpcodeVecI16x8AllTrue, wasm.OpcodeVecI32x4AllTrue, wasm.OpcodeVecI64x2AllTrue, + wasm.OpcodeVecV128AnyTrue, + wasm.OpcodeVecI8x16BitMask, wasm.OpcodeVecI16x8BitMask, wasm.OpcodeVecI32x4BitMask, wasm.OpcodeVecI64x2BitMask: + return signature_V128_I32, nil + case wasm.OpcodeVecV128Not, wasm.OpcodeVecI8x16Neg, wasm.OpcodeVecI16x8Neg, wasm.OpcodeVecI32x4Neg, wasm.OpcodeVecI64x2Neg, + wasm.OpcodeVecF32x4Neg, wasm.OpcodeVecF64x2Neg, wasm.OpcodeVecF32x4Sqrt, wasm.OpcodeVecF64x2Sqrt, + wasm.OpcodeVecI8x16Abs, wasm.OpcodeVecI8x16Popcnt, wasm.OpcodeVecI16x8Abs, wasm.OpcodeVecI32x4Abs, wasm.OpcodeVecI64x2Abs, + wasm.OpcodeVecF32x4Abs, wasm.OpcodeVecF64x2Abs, + wasm.OpcodeVecF32x4Ceil, wasm.OpcodeVecF32x4Floor, wasm.OpcodeVecF32x4Trunc, wasm.OpcodeVecF32x4Nearest, + wasm.OpcodeVecF64x2Ceil, wasm.OpcodeVecF64x2Floor, wasm.OpcodeVecF64x2Trunc, wasm.OpcodeVecF64x2Nearest, + wasm.OpcodeVecI16x8ExtendLowI8x16S, wasm.OpcodeVecI16x8ExtendHighI8x16S, wasm.OpcodeVecI16x8ExtendLowI8x16U, wasm.OpcodeVecI16x8ExtendHighI8x16U, + wasm.OpcodeVecI32x4ExtendLowI16x8S, wasm.OpcodeVecI32x4ExtendHighI16x8S, wasm.OpcodeVecI32x4ExtendLowI16x8U, wasm.OpcodeVecI32x4ExtendHighI16x8U, + wasm.OpcodeVecI64x2ExtendLowI32x4S, wasm.OpcodeVecI64x2ExtendHighI32x4S, wasm.OpcodeVecI64x2ExtendLowI32x4U, wasm.OpcodeVecI64x2ExtendHighI32x4U, + wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S, wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U, + wasm.OpcodeVecF64x2PromoteLowF32x4Zero, wasm.OpcodeVecF32x4DemoteF64x2Zero, + wasm.OpcodeVecF32x4ConvertI32x4S, wasm.OpcodeVecF32x4ConvertI32x4U, + wasm.OpcodeVecF64x2ConvertLowI32x4S, wasm.OpcodeVecF64x2ConvertLowI32x4U, + wasm.OpcodeVecI32x4TruncSatF32x4S, wasm.OpcodeVecI32x4TruncSatF32x4U, + wasm.OpcodeVecI32x4TruncSatF64x2SZero, wasm.OpcodeVecI32x4TruncSatF64x2UZero: + return signature_V128_V128, nil + case wasm.OpcodeVecV128Bitselect: + return signature_V128V128V128_V32, nil + case wasm.OpcodeVecI8x16Eq, wasm.OpcodeVecI8x16Ne, wasm.OpcodeVecI8x16LtS, wasm.OpcodeVecI8x16LtU, wasm.OpcodeVecI8x16GtS, + wasm.OpcodeVecI8x16GtU, wasm.OpcodeVecI8x16LeS, wasm.OpcodeVecI8x16LeU, wasm.OpcodeVecI8x16GeS, wasm.OpcodeVecI8x16GeU, + wasm.OpcodeVecI16x8Eq, wasm.OpcodeVecI16x8Ne, wasm.OpcodeVecI16x8LtS, wasm.OpcodeVecI16x8LtU, wasm.OpcodeVecI16x8GtS, + wasm.OpcodeVecI16x8GtU, wasm.OpcodeVecI16x8LeS, wasm.OpcodeVecI16x8LeU, wasm.OpcodeVecI16x8GeS, wasm.OpcodeVecI16x8GeU, + wasm.OpcodeVecI32x4Eq, wasm.OpcodeVecI32x4Ne, wasm.OpcodeVecI32x4LtS, wasm.OpcodeVecI32x4LtU, wasm.OpcodeVecI32x4GtS, + wasm.OpcodeVecI32x4GtU, wasm.OpcodeVecI32x4LeS, wasm.OpcodeVecI32x4LeU, wasm.OpcodeVecI32x4GeS, wasm.OpcodeVecI32x4GeU, + wasm.OpcodeVecI64x2Eq, wasm.OpcodeVecI64x2Ne, wasm.OpcodeVecI64x2LtS, wasm.OpcodeVecI64x2GtS, wasm.OpcodeVecI64x2LeS, + wasm.OpcodeVecI64x2GeS, wasm.OpcodeVecF32x4Eq, wasm.OpcodeVecF32x4Ne, wasm.OpcodeVecF32x4Lt, wasm.OpcodeVecF32x4Gt, + wasm.OpcodeVecF32x4Le, wasm.OpcodeVecF32x4Ge, wasm.OpcodeVecF64x2Eq, wasm.OpcodeVecF64x2Ne, wasm.OpcodeVecF64x2Lt, + wasm.OpcodeVecF64x2Gt, wasm.OpcodeVecF64x2Le, wasm.OpcodeVecF64x2Ge, + wasm.OpcodeVecI8x16Add, wasm.OpcodeVecI8x16AddSatS, wasm.OpcodeVecI8x16AddSatU, wasm.OpcodeVecI8x16Sub, + wasm.OpcodeVecI8x16SubSatS, wasm.OpcodeVecI8x16SubSatU, + wasm.OpcodeVecI16x8Add, wasm.OpcodeVecI16x8AddSatS, wasm.OpcodeVecI16x8AddSatU, wasm.OpcodeVecI16x8Sub, + wasm.OpcodeVecI16x8SubSatS, wasm.OpcodeVecI16x8SubSatU, wasm.OpcodeVecI16x8Mul, + wasm.OpcodeVecI32x4Add, wasm.OpcodeVecI32x4Sub, wasm.OpcodeVecI32x4Mul, + wasm.OpcodeVecI64x2Add, wasm.OpcodeVecI64x2Sub, wasm.OpcodeVecI64x2Mul, + wasm.OpcodeVecF32x4Add, wasm.OpcodeVecF32x4Sub, wasm.OpcodeVecF32x4Mul, wasm.OpcodeVecF32x4Div, + wasm.OpcodeVecF64x2Add, wasm.OpcodeVecF64x2Sub, wasm.OpcodeVecF64x2Mul, wasm.OpcodeVecF64x2Div, + wasm.OpcodeVecI8x16MinS, wasm.OpcodeVecI8x16MinU, wasm.OpcodeVecI8x16MaxS, wasm.OpcodeVecI8x16MaxU, wasm.OpcodeVecI8x16AvgrU, + wasm.OpcodeVecI16x8MinS, wasm.OpcodeVecI16x8MinU, wasm.OpcodeVecI16x8MaxS, wasm.OpcodeVecI16x8MaxU, wasm.OpcodeVecI16x8AvgrU, + wasm.OpcodeVecI32x4MinS, wasm.OpcodeVecI32x4MinU, wasm.OpcodeVecI32x4MaxS, wasm.OpcodeVecI32x4MaxU, + wasm.OpcodeVecF32x4Min, wasm.OpcodeVecF32x4Max, wasm.OpcodeVecF64x2Min, wasm.OpcodeVecF64x2Max, + wasm.OpcodeVecF32x4Pmin, wasm.OpcodeVecF32x4Pmax, wasm.OpcodeVecF64x2Pmin, wasm.OpcodeVecF64x2Pmax, + wasm.OpcodeVecI16x8Q15mulrSatS, + wasm.OpcodeVecI16x8ExtMulLowI8x16S, wasm.OpcodeVecI16x8ExtMulHighI8x16S, wasm.OpcodeVecI16x8ExtMulLowI8x16U, wasm.OpcodeVecI16x8ExtMulHighI8x16U, + wasm.OpcodeVecI32x4ExtMulLowI16x8S, wasm.OpcodeVecI32x4ExtMulHighI16x8S, wasm.OpcodeVecI32x4ExtMulLowI16x8U, wasm.OpcodeVecI32x4ExtMulHighI16x8U, + wasm.OpcodeVecI64x2ExtMulLowI32x4S, wasm.OpcodeVecI64x2ExtMulHighI32x4S, wasm.OpcodeVecI64x2ExtMulLowI32x4U, wasm.OpcodeVecI64x2ExtMulHighI32x4U, + wasm.OpcodeVecI32x4DotI16x8S, + wasm.OpcodeVecI8x16NarrowI16x8S, wasm.OpcodeVecI8x16NarrowI16x8U, wasm.OpcodeVecI16x8NarrowI32x4S, wasm.OpcodeVecI16x8NarrowI32x4U: + return signature_V128V128_V128, nil + default: + return nil, fmt.Errorf("unsupported vector instruction in interpreterir: %s", wasm.VectorInstructionName(vecOp)) + } + case wasm.OpcodeAtomicPrefix: + switch atomicOp := c.body[c.pc+1]; atomicOp { + case wasm.OpcodeAtomicMemoryNotify: + return signature_I32I32_I32, nil + case wasm.OpcodeAtomicMemoryWait32: + return signature_I32I32I64_I32, nil + case wasm.OpcodeAtomicMemoryWait64: + return signature_I32I64I64_I32, nil + case wasm.OpcodeAtomicFence: + return signature_None_None, nil + case wasm.OpcodeAtomicI32Load, wasm.OpcodeAtomicI32Load8U, wasm.OpcodeAtomicI32Load16U: + return signature_I32_I32, nil + case wasm.OpcodeAtomicI64Load, wasm.OpcodeAtomicI64Load8U, wasm.OpcodeAtomicI64Load16U, wasm.OpcodeAtomicI64Load32U: + return signature_I32_I64, nil + case wasm.OpcodeAtomicI32Store, wasm.OpcodeAtomicI32Store8, wasm.OpcodeAtomicI32Store16: + return signature_I32I32_None, nil + case wasm.OpcodeAtomicI64Store, wasm.OpcodeAtomicI64Store8, wasm.OpcodeAtomicI64Store16, wasm.OpcodeAtomicI64Store32: + return signature_I32I64_None, nil + case wasm.OpcodeAtomicI32RmwAdd, wasm.OpcodeAtomicI32RmwSub, wasm.OpcodeAtomicI32RmwAnd, wasm.OpcodeAtomicI32RmwOr, wasm.OpcodeAtomicI32RmwXor, wasm.OpcodeAtomicI32RmwXchg, + wasm.OpcodeAtomicI32Rmw8AddU, wasm.OpcodeAtomicI32Rmw8SubU, wasm.OpcodeAtomicI32Rmw8AndU, wasm.OpcodeAtomicI32Rmw8OrU, wasm.OpcodeAtomicI32Rmw8XorU, wasm.OpcodeAtomicI32Rmw8XchgU, + wasm.OpcodeAtomicI32Rmw16AddU, wasm.OpcodeAtomicI32Rmw16SubU, wasm.OpcodeAtomicI32Rmw16AndU, wasm.OpcodeAtomicI32Rmw16OrU, wasm.OpcodeAtomicI32Rmw16XorU, wasm.OpcodeAtomicI32Rmw16XchgU: + return signature_I32I32_I32, nil + case wasm.OpcodeAtomicI64RmwAdd, wasm.OpcodeAtomicI64RmwSub, wasm.OpcodeAtomicI64RmwAnd, wasm.OpcodeAtomicI64RmwOr, wasm.OpcodeAtomicI64RmwXor, wasm.OpcodeAtomicI64RmwXchg, + wasm.OpcodeAtomicI64Rmw8AddU, wasm.OpcodeAtomicI64Rmw8SubU, wasm.OpcodeAtomicI64Rmw8AndU, wasm.OpcodeAtomicI64Rmw8OrU, wasm.OpcodeAtomicI64Rmw8XorU, wasm.OpcodeAtomicI64Rmw8XchgU, + wasm.OpcodeAtomicI64Rmw16AddU, wasm.OpcodeAtomicI64Rmw16SubU, wasm.OpcodeAtomicI64Rmw16AndU, wasm.OpcodeAtomicI64Rmw16OrU, wasm.OpcodeAtomicI64Rmw16XorU, wasm.OpcodeAtomicI64Rmw16XchgU, + wasm.OpcodeAtomicI64Rmw32AddU, wasm.OpcodeAtomicI64Rmw32SubU, wasm.OpcodeAtomicI64Rmw32AndU, wasm.OpcodeAtomicI64Rmw32OrU, wasm.OpcodeAtomicI64Rmw32XorU, wasm.OpcodeAtomicI64Rmw32XchgU: + return signature_I32I64_I64, nil + case wasm.OpcodeAtomicI32RmwCmpxchg, wasm.OpcodeAtomicI32Rmw8CmpxchgU, wasm.OpcodeAtomicI32Rmw16CmpxchgU: + return signature_I32I32I32_I32, nil + case wasm.OpcodeAtomicI64RmwCmpxchg, wasm.OpcodeAtomicI64Rmw8CmpxchgU, wasm.OpcodeAtomicI64Rmw16CmpxchgU, wasm.OpcodeAtomicI64Rmw32CmpxchgU: + return signature_I32I64I64_I64, nil + default: + return nil, fmt.Errorf("unsupported atomic instruction in interpreterir: %s", wasm.AtomicInstructionName(atomicOp)) + } + default: + return nil, fmt.Errorf("unsupported instruction in interpreterir: 0x%x", op) + } +} + +// funcTypeToIRSignatures is the central cache for a module to get the *signature +// for function calls. +type funcTypeToIRSignatures struct { + directCalls []*signature + indirectCalls []*signature + wasmTypes []wasm.FunctionType +} + +// get returns the *signature for the direct or indirect function call against functions whose type is at `typeIndex`. +func (f *funcTypeToIRSignatures) get(typeIndex wasm.Index, indirect bool) *signature { + var sig *signature + if indirect { + sig = f.indirectCalls[typeIndex] + } else { + sig = f.directCalls[typeIndex] + } + if sig != nil { + return sig + } + + tp := &f.wasmTypes[typeIndex] + if indirect { + sig = &signature{ + in: make([]unsignedType, 0, len(tp.Params)+1), // +1 to reserve space for call indirect index. + out: make([]unsignedType, 0, len(tp.Results)), + } + } else { + sig = &signature{ + in: make([]unsignedType, 0, len(tp.Params)), + out: make([]unsignedType, 0, len(tp.Results)), + } + } + + for _, vt := range tp.Params { + sig.in = append(sig.in, wasmValueTypeTounsignedType(vt)) + } + for _, vt := range tp.Results { + sig.out = append(sig.out, wasmValueTypeTounsignedType(vt)) + } + + if indirect { + sig.in = append(sig.in, unsignedTypeI32) + f.indirectCalls[typeIndex] = sig + } else { + f.directCalls[typeIndex] = sig + } + return sig +} + +func wasmValueTypeTounsignedType(vt wasm.ValueType) unsignedType { + switch vt { + case wasm.ValueTypeI32: + return unsignedTypeI32 + case wasm.ValueTypeI64, + // From interpreterir layer, ref type values are opaque 64-bit pointers. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + return unsignedTypeI64 + case wasm.ValueTypeF32: + return unsignedTypeF32 + case wasm.ValueTypeF64: + return unsignedTypeF64 + case wasm.ValueTypeV128: + return unsignedTypeV128 + } + panic("unreachable") +} + +func wasmValueTypeToUnsignedOutSignature(vt wasm.ValueType) *signature { + switch vt { + case wasm.ValueTypeI32: + return signature_None_I32 + case wasm.ValueTypeI64, + // From interpreterir layer, ref type values are opaque 64-bit pointers. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + return signature_None_I64 + case wasm.ValueTypeF32: + return signature_None_F32 + case wasm.ValueTypeF64: + return signature_None_F64 + case wasm.ValueTypeV128: + return signature_None_V128 + } + panic("unreachable") +} + +func wasmValueTypeToUnsignedInSignature(vt wasm.ValueType) *signature { + switch vt { + case wasm.ValueTypeI32: + return signature_I32_None + case wasm.ValueTypeI64, + // From interpreterir layer, ref type values are opaque 64-bit pointers. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + return signature_I64_None + case wasm.ValueTypeF32: + return signature_F32_None + case wasm.ValueTypeF64: + return signature_F64_None + case wasm.ValueTypeV128: + return signature_V128_None + } + panic("unreachable") +} + +func wasmValueTypeToUnsignedInOutSignature(vt wasm.ValueType) *signature { + switch vt { + case wasm.ValueTypeI32: + return signature_I32_I32 + case wasm.ValueTypeI64, + // At interpreterir layer, ref type values are opaque 64-bit pointers. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + return signature_I64_I64 + case wasm.ValueTypeF32: + return signature_F32_F32 + case wasm.ValueTypeF64: + return signature_F64_F64 + case wasm.ValueTypeV128: + return signature_V128_V128 + } + panic("unreachable") +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/abi.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/abi.go new file mode 100644 index 00000000..cf91c6b7 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/abi.go @@ -0,0 +1,170 @@ +package backend + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +type ( + // FunctionABI represents the ABI information for a function which corresponds to a ssa.Signature. + FunctionABI struct { + Initialized bool + + Args, Rets []ABIArg + ArgStackSize, RetStackSize int64 + + ArgIntRealRegs byte + ArgFloatRealRegs byte + RetIntRealRegs byte + RetFloatRealRegs byte + } + + // ABIArg represents either argument or return value's location. + ABIArg struct { + // Index is the index of the argument. + Index int + // Kind is the kind of the argument. + Kind ABIArgKind + // Reg is valid if Kind == ABIArgKindReg. + // This VReg must be based on RealReg. + Reg regalloc.VReg + // Offset is valid if Kind == ABIArgKindStack. + // This is the offset from the beginning of either arg or ret stack slot. + Offset int64 + // Type is the type of the argument. + Type ssa.Type + } + + // ABIArgKind is the kind of ABI argument. + ABIArgKind byte +) + +const ( + // ABIArgKindReg represents an argument passed in a register. + ABIArgKindReg = iota + // ABIArgKindStack represents an argument passed in the stack. + ABIArgKindStack +) + +// String implements fmt.Stringer. +func (a *ABIArg) String() string { + return fmt.Sprintf("args[%d]: %s", a.Index, a.Kind) +} + +// String implements fmt.Stringer. +func (a ABIArgKind) String() string { + switch a { + case ABIArgKindReg: + return "reg" + case ABIArgKindStack: + return "stack" + default: + panic("BUG") + } +} + +// Init initializes the abiImpl for the given signature. +func (a *FunctionABI) Init(sig *ssa.Signature, argResultInts, argResultFloats []regalloc.RealReg) { + if len(a.Rets) < len(sig.Results) { + a.Rets = make([]ABIArg, len(sig.Results)) + } + a.Rets = a.Rets[:len(sig.Results)] + a.RetStackSize = a.setABIArgs(a.Rets, sig.Results, argResultInts, argResultFloats) + if argsNum := len(sig.Params); len(a.Args) < argsNum { + a.Args = make([]ABIArg, argsNum) + } + a.Args = a.Args[:len(sig.Params)] + a.ArgStackSize = a.setABIArgs(a.Args, sig.Params, argResultInts, argResultFloats) + + // Gather the real registers usages in arg/return. + a.ArgIntRealRegs, a.ArgFloatRealRegs = 0, 0 + a.RetIntRealRegs, a.RetFloatRealRegs = 0, 0 + for i := range a.Rets { + r := &a.Rets[i] + if r.Kind == ABIArgKindReg { + if r.Type.IsInt() { + a.RetIntRealRegs++ + } else { + a.RetFloatRealRegs++ + } + } + } + for i := range a.Args { + arg := &a.Args[i] + if arg.Kind == ABIArgKindReg { + if arg.Type.IsInt() { + a.ArgIntRealRegs++ + } else { + a.ArgFloatRealRegs++ + } + } + } + + a.Initialized = true +} + +// setABIArgs sets the ABI arguments in the given slice. This assumes that len(s) >= len(types) +// where if len(s) > len(types), the last elements of s is for the multi-return slot. +func (a *FunctionABI) setABIArgs(s []ABIArg, types []ssa.Type, ints, floats []regalloc.RealReg) (stackSize int64) { + il, fl := len(ints), len(floats) + + var stackOffset int64 + intParamIndex, floatParamIndex := 0, 0 + for i, typ := range types { + arg := &s[i] + arg.Index = i + arg.Type = typ + if typ.IsInt() { + if intParamIndex >= il { + arg.Kind = ABIArgKindStack + const slotSize = 8 // Align 8 bytes. + arg.Offset = stackOffset + stackOffset += slotSize + } else { + arg.Kind = ABIArgKindReg + arg.Reg = regalloc.FromRealReg(ints[intParamIndex], regalloc.RegTypeInt) + intParamIndex++ + } + } else { + if floatParamIndex >= fl { + arg.Kind = ABIArgKindStack + slotSize := int64(8) // Align at least 8 bytes. + if typ.Bits() == 128 { // Vector. + slotSize = 16 + } + arg.Offset = stackOffset + stackOffset += slotSize + } else { + arg.Kind = ABIArgKindReg + arg.Reg = regalloc.FromRealReg(floats[floatParamIndex], regalloc.RegTypeFloat) + floatParamIndex++ + } + } + } + return stackOffset +} + +func (a *FunctionABI) AlignedArgResultStackSlotSize() uint32 { + stackSlotSize := a.RetStackSize + a.ArgStackSize + // Align stackSlotSize to 16 bytes. + stackSlotSize = (stackSlotSize + 15) &^ 15 + // Check overflow 32-bit. + if stackSlotSize > 0xFFFFFFFF { + panic("ABI stack slot size overflow") + } + return uint32(stackSlotSize) +} + +func (a *FunctionABI) ABIInfoAsUint64() uint64 { + return uint64(a.ArgIntRealRegs)<<56 | + uint64(a.ArgFloatRealRegs)<<48 | + uint64(a.RetIntRealRegs)<<40 | + uint64(a.RetFloatRealRegs)<<32 | + uint64(a.AlignedArgResultStackSlotSize()) +} + +func ABIInfoFromUint64(info uint64) (argIntRealRegs, argFloatRealRegs, retIntRealRegs, retFloatRealRegs byte, stackSlotSize uint32) { + return byte(info >> 56), byte(info >> 48), byte(info >> 40), byte(info >> 32), uint32(info) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/backend.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/backend.go new file mode 100644 index 00000000..dd67da43 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/backend.go @@ -0,0 +1,3 @@ +// Package backend must be free of Wasm-specific concept. In other words, +// this package must not import internal/wasm package. +package backend diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler.go new file mode 100644 index 00000000..62d36501 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler.go @@ -0,0 +1,399 @@ +package backend + +import ( + "context" + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// NewCompiler returns a new Compiler that can generate a machine code. +func NewCompiler(ctx context.Context, mach Machine, builder ssa.Builder) Compiler { + return newCompiler(ctx, mach, builder) +} + +func newCompiler(_ context.Context, mach Machine, builder ssa.Builder) *compiler { + argResultInts, argResultFloats := mach.ArgsResultsRegs() + c := &compiler{ + mach: mach, ssaBuilder: builder, + nextVRegID: regalloc.VRegIDNonReservedBegin, + argResultInts: argResultInts, + argResultFloats: argResultFloats, + } + mach.SetCompiler(c) + return c +} + +// Compiler is the backend of wazevo which takes ssa.Builder and Machine, +// use the information there to emit the final machine code. +type Compiler interface { + // SSABuilder returns the ssa.Builder used by this compiler. + SSABuilder() ssa.Builder + + // Compile executes the following steps: + // 1. Lower() + // 2. RegAlloc() + // 3. Finalize() + // 4. Encode() + // + // Each step can be called individually for testing purpose, therefore they are exposed in this interface too. + // + // The returned byte slices are the machine code and the relocation information for the machine code. + // The caller is responsible for copying them immediately since the compiler may reuse the buffer. + Compile(ctx context.Context) (_ []byte, _ []RelocationInfo, _ error) + + // Lower lowers the given ssa.Instruction to the machine-specific instructions. + Lower() + + // RegAlloc performs the register allocation after Lower is called. + RegAlloc() + + // Finalize performs the finalization of the compilation, including machine code emission. + // This must be called after RegAlloc. + Finalize(ctx context.Context) error + + // Buf returns the buffer of the encoded machine code. This is only used for testing purpose. + Buf() []byte + + BufPtr() *[]byte + + // Format returns the debug string of the current state of the compiler. + Format() string + + // Init initializes the internal state of the compiler for the next compilation. + Init() + + // AllocateVReg allocates a new virtual register of the given type. + AllocateVReg(typ ssa.Type) regalloc.VReg + + // ValueDefinition returns the definition of the given value. + ValueDefinition(ssa.Value) SSAValueDefinition + + // VRegOf returns the virtual register of the given ssa.Value. + VRegOf(value ssa.Value) regalloc.VReg + + // TypeOf returns the ssa.Type of the given virtual register. + TypeOf(regalloc.VReg) ssa.Type + + // MatchInstr returns true if the given definition is from an instruction with the given opcode, the current group ID, + // and a refcount of 1. That means, the instruction can be merged/swapped within the current instruction group. + MatchInstr(def SSAValueDefinition, opcode ssa.Opcode) bool + + // MatchInstrOneOf is the same as MatchInstr but for multiple opcodes. If it matches one of ssa.Opcode, + // this returns the opcode. Otherwise, this returns ssa.OpcodeInvalid. + // + // Note: caller should be careful to avoid excessive allocation on opcodes slice. + MatchInstrOneOf(def SSAValueDefinition, opcodes []ssa.Opcode) ssa.Opcode + + // AddRelocationInfo appends the relocation information for the function reference at the current buffer offset. + AddRelocationInfo(funcRef ssa.FuncRef) + + // AddSourceOffsetInfo appends the source offset information for the given offset. + AddSourceOffsetInfo(executableOffset int64, sourceOffset ssa.SourceOffset) + + // SourceOffsetInfo returns the source offset information for the current buffer offset. + SourceOffsetInfo() []SourceOffsetInfo + + // EmitByte appends a byte to the buffer. Used during the code emission. + EmitByte(b byte) + + // Emit4Bytes appends 4 bytes to the buffer. Used during the code emission. + Emit4Bytes(b uint32) + + // Emit8Bytes appends 8 bytes to the buffer. Used during the code emission. + Emit8Bytes(b uint64) + + // GetFunctionABI returns the ABI information for the given signature. + GetFunctionABI(sig *ssa.Signature) *FunctionABI +} + +// RelocationInfo represents the relocation information for a call instruction. +type RelocationInfo struct { + // Offset represents the offset from the beginning of the machine code of either a function or the entire module. + Offset int64 + // Target is the target function of the call instruction. + FuncRef ssa.FuncRef +} + +// compiler implements Compiler. +type compiler struct { + mach Machine + currentGID ssa.InstructionGroupID + ssaBuilder ssa.Builder + // nextVRegID is the next virtual register ID to be allocated. + nextVRegID regalloc.VRegID + // ssaValueToVRegs maps ssa.ValueID to regalloc.VReg. + ssaValueToVRegs [] /* VRegID to */ regalloc.VReg + ssaValuesInfo []ssa.ValueInfo + // returnVRegs is the list of virtual registers that store the return values. + returnVRegs []regalloc.VReg + varEdges [][2]regalloc.VReg + varEdgeTypes []ssa.Type + constEdges []struct { + cInst *ssa.Instruction + dst regalloc.VReg + } + vRegSet []bool + vRegIDs []regalloc.VRegID + tempRegs []regalloc.VReg + tmpVals []ssa.Value + ssaTypeOfVRegID [] /* VRegID to */ ssa.Type + buf []byte + relocations []RelocationInfo + sourceOffsets []SourceOffsetInfo + // abis maps ssa.SignatureID to the ABI implementation. + abis []FunctionABI + argResultInts, argResultFloats []regalloc.RealReg +} + +// SourceOffsetInfo is a data to associate the source offset with the executable offset. +type SourceOffsetInfo struct { + // SourceOffset is the source offset in the original source code. + SourceOffset ssa.SourceOffset + // ExecutableOffset is the offset in the compiled executable. + ExecutableOffset int64 +} + +// Compile implements Compiler.Compile. +func (c *compiler) Compile(ctx context.Context) ([]byte, []RelocationInfo, error) { + c.Lower() + if wazevoapi.PrintSSAToBackendIRLowering && wazevoapi.PrintEnabledIndex(ctx) { + fmt.Printf("[[[after lowering for %s ]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format()) + } + if wazevoapi.DeterministicCompilationVerifierEnabled { + wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After lowering to ISA specific IR", c.Format()) + } + c.RegAlloc() + if wazevoapi.PrintRegisterAllocated && wazevoapi.PrintEnabledIndex(ctx) { + fmt.Printf("[[[after regalloc for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format()) + } + if wazevoapi.DeterministicCompilationVerifierEnabled { + wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After Register Allocation", c.Format()) + } + if err := c.Finalize(ctx); err != nil { + return nil, nil, err + } + if wazevoapi.PrintFinalizedMachineCode && wazevoapi.PrintEnabledIndex(ctx) { + fmt.Printf("[[[after finalize for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format()) + } + if wazevoapi.DeterministicCompilationVerifierEnabled { + wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After Finalization", c.Format()) + } + return c.buf, c.relocations, nil +} + +// RegAlloc implements Compiler.RegAlloc. +func (c *compiler) RegAlloc() { + c.mach.RegAlloc() +} + +// Finalize implements Compiler.Finalize. +func (c *compiler) Finalize(ctx context.Context) error { + c.mach.PostRegAlloc() + return c.mach.Encode(ctx) +} + +// setCurrentGroupID sets the current instruction group ID. +func (c *compiler) setCurrentGroupID(gid ssa.InstructionGroupID) { + c.currentGID = gid +} + +// assignVirtualRegisters assigns a virtual register to each ssa.ValueID Valid in the ssa.Builder. +func (c *compiler) assignVirtualRegisters() { + builder := c.ssaBuilder + c.ssaValuesInfo = builder.ValuesInfo() + + if diff := len(c.ssaValuesInfo) - len(c.ssaValueToVRegs); diff > 0 { + c.ssaValueToVRegs = append(c.ssaValueToVRegs, make([]regalloc.VReg, diff+1)...) + } + + for blk := builder.BlockIteratorReversePostOrderBegin(); blk != nil; blk = builder.BlockIteratorReversePostOrderNext() { + // First we assign a virtual register to each parameter. + for i := 0; i < blk.Params(); i++ { + p := blk.Param(i) + pid := p.ID() + typ := p.Type() + vreg := c.AllocateVReg(typ) + c.ssaValueToVRegs[pid] = vreg + c.ssaTypeOfVRegID[vreg.ID()] = p.Type() + } + + // Assigns each value to a virtual register produced by instructions. + for cur := blk.Root(); cur != nil; cur = cur.Next() { + r, rs := cur.Returns() + if r.Valid() { + id := r.ID() + ssaTyp := r.Type() + typ := r.Type() + vReg := c.AllocateVReg(typ) + c.ssaValueToVRegs[id] = vReg + c.ssaTypeOfVRegID[vReg.ID()] = ssaTyp + } + for _, r := range rs { + id := r.ID() + ssaTyp := r.Type() + vReg := c.AllocateVReg(ssaTyp) + c.ssaValueToVRegs[id] = vReg + c.ssaTypeOfVRegID[vReg.ID()] = ssaTyp + } + } + } + + for i, retBlk := 0, builder.ReturnBlock(); i < retBlk.Params(); i++ { + typ := retBlk.Param(i).Type() + vReg := c.AllocateVReg(typ) + c.returnVRegs = append(c.returnVRegs, vReg) + c.ssaTypeOfVRegID[vReg.ID()] = typ + } +} + +// AllocateVReg implements Compiler.AllocateVReg. +func (c *compiler) AllocateVReg(typ ssa.Type) regalloc.VReg { + regType := regalloc.RegTypeOf(typ) + r := regalloc.VReg(c.nextVRegID).SetRegType(regType) + + id := r.ID() + if int(id) >= len(c.ssaTypeOfVRegID) { + c.ssaTypeOfVRegID = append(c.ssaTypeOfVRegID, make([]ssa.Type, id+1)...) + } + c.ssaTypeOfVRegID[id] = typ + c.nextVRegID++ + return r +} + +// Init implements Compiler.Init. +func (c *compiler) Init() { + c.currentGID = 0 + c.nextVRegID = regalloc.VRegIDNonReservedBegin + c.returnVRegs = c.returnVRegs[:0] + c.mach.Reset() + c.varEdges = c.varEdges[:0] + c.constEdges = c.constEdges[:0] + c.buf = c.buf[:0] + c.sourceOffsets = c.sourceOffsets[:0] + c.relocations = c.relocations[:0] +} + +// ValueDefinition implements Compiler.ValueDefinition. +func (c *compiler) ValueDefinition(value ssa.Value) SSAValueDefinition { + return SSAValueDefinition{ + V: value, + Instr: c.ssaBuilder.InstructionOfValue(value), + RefCount: c.ssaValuesInfo[value.ID()].RefCount, + } +} + +// VRegOf implements Compiler.VRegOf. +func (c *compiler) VRegOf(value ssa.Value) regalloc.VReg { + return c.ssaValueToVRegs[value.ID()] +} + +// Format implements Compiler.Format. +func (c *compiler) Format() string { + return c.mach.Format() +} + +// TypeOf implements Compiler.Format. +func (c *compiler) TypeOf(v regalloc.VReg) ssa.Type { + return c.ssaTypeOfVRegID[v.ID()] +} + +// MatchInstr implements Compiler.MatchInstr. +func (c *compiler) MatchInstr(def SSAValueDefinition, opcode ssa.Opcode) bool { + instr := def.Instr + return def.IsFromInstr() && + instr.Opcode() == opcode && + instr.GroupID() == c.currentGID && + def.RefCount < 2 +} + +// MatchInstrOneOf implements Compiler.MatchInstrOneOf. +func (c *compiler) MatchInstrOneOf(def SSAValueDefinition, opcodes []ssa.Opcode) ssa.Opcode { + instr := def.Instr + if !def.IsFromInstr() { + return ssa.OpcodeInvalid + } + + if instr.GroupID() != c.currentGID { + return ssa.OpcodeInvalid + } + + if def.RefCount >= 2 { + return ssa.OpcodeInvalid + } + + opcode := instr.Opcode() + for _, op := range opcodes { + if opcode == op { + return opcode + } + } + return ssa.OpcodeInvalid +} + +// SSABuilder implements Compiler .SSABuilder. +func (c *compiler) SSABuilder() ssa.Builder { + return c.ssaBuilder +} + +// AddSourceOffsetInfo implements Compiler.AddSourceOffsetInfo. +func (c *compiler) AddSourceOffsetInfo(executableOffset int64, sourceOffset ssa.SourceOffset) { + c.sourceOffsets = append(c.sourceOffsets, SourceOffsetInfo{ + SourceOffset: sourceOffset, + ExecutableOffset: executableOffset, + }) +} + +// SourceOffsetInfo implements Compiler.SourceOffsetInfo. +func (c *compiler) SourceOffsetInfo() []SourceOffsetInfo { + return c.sourceOffsets +} + +// AddRelocationInfo implements Compiler.AddRelocationInfo. +func (c *compiler) AddRelocationInfo(funcRef ssa.FuncRef) { + c.relocations = append(c.relocations, RelocationInfo{ + Offset: int64(len(c.buf)), + FuncRef: funcRef, + }) +} + +// Emit8Bytes implements Compiler.Emit8Bytes. +func (c *compiler) Emit8Bytes(b uint64) { + c.buf = append(c.buf, byte(b), byte(b>>8), byte(b>>16), byte(b>>24), byte(b>>32), byte(b>>40), byte(b>>48), byte(b>>56)) +} + +// Emit4Bytes implements Compiler.Emit4Bytes. +func (c *compiler) Emit4Bytes(b uint32) { + c.buf = append(c.buf, byte(b), byte(b>>8), byte(b>>16), byte(b>>24)) +} + +// EmitByte implements Compiler.EmitByte. +func (c *compiler) EmitByte(b byte) { + c.buf = append(c.buf, b) +} + +// Buf implements Compiler.Buf. +func (c *compiler) Buf() []byte { + return c.buf +} + +// BufPtr implements Compiler.BufPtr. +func (c *compiler) BufPtr() *[]byte { + return &c.buf +} + +func (c *compiler) GetFunctionABI(sig *ssa.Signature) *FunctionABI { + if int(sig.ID) >= len(c.abis) { + c.abis = append(c.abis, make([]FunctionABI, int(sig.ID)+1)...) + } + + abi := &c.abis[sig.ID] + if abi.Initialized { + return abi + } + + abi.Init(sig, c.argResultInts, c.argResultFloats) + return abi +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler_lower.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler_lower.go new file mode 100644 index 00000000..735cfa3d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/compiler_lower.go @@ -0,0 +1,226 @@ +package backend + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// Lower implements Compiler.Lower. +func (c *compiler) Lower() { + c.assignVirtualRegisters() + c.mach.SetCurrentABI(c.GetFunctionABI(c.ssaBuilder.Signature())) + c.mach.StartLoweringFunction(c.ssaBuilder.BlockIDMax()) + c.lowerBlocks() +} + +// lowerBlocks lowers each block in the ssa.Builder. +func (c *compiler) lowerBlocks() { + builder := c.ssaBuilder + for blk := builder.BlockIteratorReversePostOrderBegin(); blk != nil; blk = builder.BlockIteratorReversePostOrderNext() { + c.lowerBlock(blk) + } + + // After lowering all blocks, we need to link adjacent blocks to layout one single instruction list. + var prev ssa.BasicBlock + for next := builder.BlockIteratorReversePostOrderBegin(); next != nil; next = builder.BlockIteratorReversePostOrderNext() { + if prev != nil { + c.mach.LinkAdjacentBlocks(prev, next) + } + prev = next + } +} + +func (c *compiler) lowerBlock(blk ssa.BasicBlock) { + mach := c.mach + mach.StartBlock(blk) + + // We traverse the instructions in reverse order because we might want to lower multiple + // instructions together. + cur := blk.Tail() + + // First gather the branching instructions at the end of the blocks. + var br0, br1 *ssa.Instruction + if cur.IsBranching() { + br0 = cur + cur = cur.Prev() + if cur != nil && cur.IsBranching() { + br1 = cur + cur = cur.Prev() + } + } + + if br0 != nil { + c.lowerBranches(br0, br1) + } + + if br1 != nil && br0 == nil { + panic("BUG? when a block has conditional branch but doesn't end with an unconditional branch?") + } + + // Now start lowering the non-branching instructions. + for ; cur != nil; cur = cur.Prev() { + c.setCurrentGroupID(cur.GroupID()) + if cur.Lowered() { + continue + } + + switch cur.Opcode() { + case ssa.OpcodeReturn: + rets := cur.ReturnVals() + if len(rets) > 0 { + c.mach.LowerReturns(rets) + } + c.mach.InsertReturn() + default: + mach.LowerInstr(cur) + } + mach.FlushPendingInstructions() + } + + // Finally, if this is the entry block, we have to insert copies of arguments from the real location to the VReg. + if blk.EntryBlock() { + c.lowerFunctionArguments(blk) + } + + mach.EndBlock() +} + +// lowerBranches is called right after StartBlock and before any LowerInstr call if +// there are branches to the given block. br0 is the very end of the block and b1 is the before the br0 if it exists. +// At least br0 is not nil, but br1 can be nil if there's no branching before br0. +// +// See ssa.Instruction IsBranching, and the comment on ssa.BasicBlock. +func (c *compiler) lowerBranches(br0, br1 *ssa.Instruction) { + mach := c.mach + + c.setCurrentGroupID(br0.GroupID()) + c.mach.LowerSingleBranch(br0) + mach.FlushPendingInstructions() + if br1 != nil { + c.setCurrentGroupID(br1.GroupID()) + c.mach.LowerConditionalBranch(br1) + mach.FlushPendingInstructions() + } + + if br0.Opcode() == ssa.OpcodeJump { + _, args, targetBlockID := br0.BranchData() + argExists := len(args) != 0 + if argExists && br1 != nil { + panic("BUG: critical edge split failed") + } + target := c.ssaBuilder.BasicBlock(targetBlockID) + if argExists && target.ReturnBlock() { + if len(args) > 0 { + c.mach.LowerReturns(args) + } + } else if argExists { + c.lowerBlockArguments(args, target) + } + } + mach.FlushPendingInstructions() +} + +func (c *compiler) lowerFunctionArguments(entry ssa.BasicBlock) { + mach := c.mach + + c.tmpVals = c.tmpVals[:0] + data := c.ssaBuilder.ValuesInfo() + for i := 0; i < entry.Params(); i++ { + p := entry.Param(i) + if data[p.ID()].RefCount > 0 { + c.tmpVals = append(c.tmpVals, p) + } else { + // If the argument is not used, we can just pass an invalid value. + c.tmpVals = append(c.tmpVals, ssa.ValueInvalid) + } + } + mach.LowerParams(c.tmpVals) + mach.FlushPendingInstructions() +} + +// lowerBlockArguments lowers how to pass arguments to the given successor block. +func (c *compiler) lowerBlockArguments(args []ssa.Value, succ ssa.BasicBlock) { + if len(args) != succ.Params() { + panic("BUG: mismatched number of arguments") + } + + c.varEdges = c.varEdges[:0] + c.varEdgeTypes = c.varEdgeTypes[:0] + c.constEdges = c.constEdges[:0] + for i := 0; i < len(args); i++ { + dst := succ.Param(i) + src := args[i] + + dstReg := c.VRegOf(dst) + srcInstr := c.ssaBuilder.InstructionOfValue(src) + if srcInstr != nil && srcInstr.Constant() { + c.constEdges = append(c.constEdges, struct { + cInst *ssa.Instruction + dst regalloc.VReg + }{cInst: srcInstr, dst: dstReg}) + } else { + srcReg := c.VRegOf(src) + // Even when the src=dst, insert the move so that we can keep such registers keep-alive. + c.varEdges = append(c.varEdges, [2]regalloc.VReg{srcReg, dstReg}) + c.varEdgeTypes = append(c.varEdgeTypes, src.Type()) + } + } + + // Check if there's an overlap among the dsts and srcs in varEdges. + c.vRegIDs = c.vRegIDs[:0] + for _, edge := range c.varEdges { + src := edge[0].ID() + if int(src) >= len(c.vRegSet) { + c.vRegSet = append(c.vRegSet, make([]bool, src+1)...) + } + c.vRegSet[src] = true + c.vRegIDs = append(c.vRegIDs, src) + } + separated := true + for _, edge := range c.varEdges { + dst := edge[1].ID() + if int(dst) >= len(c.vRegSet) { + c.vRegSet = append(c.vRegSet, make([]bool, dst+1)...) + } else { + if c.vRegSet[dst] { + separated = false + break + } + } + } + for _, id := range c.vRegIDs { + c.vRegSet[id] = false // reset for the next use. + } + + if separated { + // If there's no overlap, we can simply move the source to destination. + for i, edge := range c.varEdges { + src, dst := edge[0], edge[1] + c.mach.InsertMove(dst, src, c.varEdgeTypes[i]) + } + } else { + // Otherwise, we allocate a temporary registers and move the source to the temporary register, + // + // First move all of them to temporary registers. + c.tempRegs = c.tempRegs[:0] + for i, edge := range c.varEdges { + src := edge[0] + typ := c.varEdgeTypes[i] + temp := c.AllocateVReg(typ) + c.tempRegs = append(c.tempRegs, temp) + c.mach.InsertMove(temp, src, typ) + } + // Then move the temporary registers to the destination. + for i, edge := range c.varEdges { + temp := c.tempRegs[i] + dst := edge[1] + c.mach.InsertMove(dst, temp, c.varEdgeTypes[i]) + } + } + + // Finally, move the constants. + for _, edge := range c.constEdges { + cInst, dst := edge.cInst, edge.dst + c.mach.InsertLoadConstantBlockArg(cInst, dst) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/go_call.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/go_call.go new file mode 100644 index 00000000..6fe6d7b3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/go_call.go @@ -0,0 +1,33 @@ +package backend + +import "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + +// GoFunctionCallRequiredStackSize returns the size of the stack required for the Go function call. +// argBegin is the index of the first argument in the signature which is not either execution context or module context. +func GoFunctionCallRequiredStackSize(sig *ssa.Signature, argBegin int) (ret, retUnaligned int64) { + var paramNeededInBytes, resultNeededInBytes int64 + for _, p := range sig.Params[argBegin:] { + s := int64(p.Size()) + if s < 8 { + s = 8 // We use uint64 for all basic types, except SIMD v128. + } + paramNeededInBytes += s + } + for _, r := range sig.Results { + s := int64(r.Size()) + if s < 8 { + s = 8 // We use uint64 for all basic types, except SIMD v128. + } + resultNeededInBytes += s + } + + if paramNeededInBytes > resultNeededInBytes { + ret = paramNeededInBytes + } else { + ret = resultNeededInBytes + } + retUnaligned = ret + // Align to 16 bytes. + ret = (ret + 15) &^ 15 + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi.go new file mode 100644 index 00000000..130f8c62 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi.go @@ -0,0 +1,186 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// For the details of the ABI, see: +// https://github.com/golang/go/blob/49d42128fd8594c172162961ead19ac95e247d24/src/cmd/compile/abi-internal.md#amd64-architecture + +var ( + intArgResultRegs = []regalloc.RealReg{rax, rbx, rcx, rdi, rsi, r8, r9, r10, r11} + floatArgResultRegs = []regalloc.RealReg{xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7} +) + +var regInfo = ®alloc.RegisterInfo{ + AllocatableRegisters: [regalloc.NumRegType][]regalloc.RealReg{ + regalloc.RegTypeInt: { + rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, + }, + regalloc.RegTypeFloat: { + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + }, + }, + CalleeSavedRegisters: regalloc.NewRegSet( + rdx, r12, r13, r14, r15, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + ), + CallerSavedRegisters: regalloc.NewRegSet( + rax, rcx, rbx, rsi, rdi, r8, r9, r10, r11, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + ), + RealRegToVReg: []regalloc.VReg{ + rax: raxVReg, rcx: rcxVReg, rdx: rdxVReg, rbx: rbxVReg, rsp: rspVReg, rbp: rbpVReg, rsi: rsiVReg, rdi: rdiVReg, + r8: r8VReg, r9: r9VReg, r10: r10VReg, r11: r11VReg, r12: r12VReg, r13: r13VReg, r14: r14VReg, r15: r15VReg, + xmm0: xmm0VReg, xmm1: xmm1VReg, xmm2: xmm2VReg, xmm3: xmm3VReg, xmm4: xmm4VReg, xmm5: xmm5VReg, xmm6: xmm6VReg, + xmm7: xmm7VReg, xmm8: xmm8VReg, xmm9: xmm9VReg, xmm10: xmm10VReg, xmm11: xmm11VReg, xmm12: xmm12VReg, + xmm13: xmm13VReg, xmm14: xmm14VReg, xmm15: xmm15VReg, + }, + RealRegName: func(r regalloc.RealReg) string { return regNames[r] }, + RealRegType: func(r regalloc.RealReg) regalloc.RegType { + if r < xmm0 { + return regalloc.RegTypeInt + } + return regalloc.RegTypeFloat + }, +} + +// ArgsResultsRegs implements backend.Machine. +func (m *machine) ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) { + return intArgResultRegs, floatArgResultRegs +} + +// LowerParams implements backend.Machine. +func (m *machine) LowerParams(args []ssa.Value) { + a := m.currentABI + + for i, ssaArg := range args { + if !ssaArg.Valid() { + continue + } + reg := m.c.VRegOf(ssaArg) + arg := &a.Args[i] + if arg.Kind == backend.ABIArgKindReg { + m.InsertMove(reg, arg.Reg, arg.Type) + } else { + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <-- RBP + // | ........... | + // | clobbered M | + // | ............ | + // | clobbered 0 | + // | spill slot N | + // | ........... | + // | spill slot 0 | + // RSP--> +-----------------+ + // (low address) + + // Load the value from the arg stack slot above the current RBP. + load := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmRBPReg(uint32(arg.Offset + 16))) + switch arg.Type { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, mem, reg) + case ssa.TypeI64: + load.asMov64MR(mem, reg) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, mem, reg) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, mem, reg) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, reg) + default: + panic("BUG") + } + m.insert(load) + } + } +} + +// LowerReturns implements backend.Machine. +func (m *machine) LowerReturns(rets []ssa.Value) { + // Load the XMM registers first as it might need a temporary register to inline + // constant return. + a := m.currentABI + for i, ret := range rets { + r := &a.Rets[i] + if !r.Type.IsInt() { + m.LowerReturn(ret, r) + } + } + // Then load the GPR registers. + for i, ret := range rets { + r := &a.Rets[i] + if r.Type.IsInt() { + m.LowerReturn(ret, r) + } + } +} + +func (m *machine) LowerReturn(ret ssa.Value, r *backend.ABIArg) { + reg := m.c.VRegOf(ret) + if def := m.c.ValueDefinition(ret); def.IsFromInstr() { + // Constant instructions are inlined. + if inst := def.Instr; inst.Constant() { + m.insertLoadConstant(inst, reg) + } + } + if r.Kind == backend.ABIArgKindReg { + m.InsertMove(r.Reg, reg, ret.Type()) + } else { + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <-- RBP + // | ........... | + // | clobbered M | + // | ............ | + // | clobbered 0 | + // | spill slot N | + // | ........... | + // | spill slot 0 | + // RSP--> +-----------------+ + // (low address) + + // Store the value to the return stack slot above the current RBP. + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmRBPReg(uint32(m.currentABI.ArgStackSize + 16 + r.Offset))) + switch r.Type { + case ssa.TypeI32: + store.asMovRM(reg, mem, 4) + case ssa.TypeI64: + store.asMovRM(reg, mem, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, reg, mem) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, reg, mem) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, reg, mem) + } + m.insert(store) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.go new file mode 100644 index 00000000..cbf1cfdc --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.go @@ -0,0 +1,9 @@ +package amd64 + +// entrypoint enters the machine code generated by this backend which begins with the preamble generated by functionABI.EmitGoEntryPreamble below. +// This implements wazevo.entrypoint, and see the comments there for detail. +func entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultPtr *uint64, goAllocatedStackSlicePtr uintptr) + +// afterGoFunctionCallEntrypoint enters the machine code after growing the stack. +// This implements wazevo.afterGoFunctionCallEntrypoint, and see the comments there for detail. +func afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s new file mode 100644 index 00000000..e9cb131d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s @@ -0,0 +1,29 @@ +#include "funcdata.h" +#include "textflag.h" + +// entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultPtr *uint64, goAllocatedStackSlicePtr uintptr +TEXT ·entrypoint(SB), NOSPLIT|NOFRAME, $0-48 + MOVQ preambleExecutable+0(FP), R11 + MOVQ functionExectuable+8(FP), R14 + MOVQ executionContextPtr+16(FP), AX // First argument is passed in AX. + MOVQ moduleContextPtr+24(FP), BX // Second argument is passed in BX. + MOVQ paramResultSlicePtr+32(FP), R12 + MOVQ goAllocatedStackSlicePtr+40(FP), R13 + JMP R11 + +// afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) +TEXT ·afterGoFunctionCallEntrypoint(SB), NOSPLIT|NOFRAME, $0-32 + MOVQ executable+0(FP), CX + MOVQ executionContextPtr+8(FP), AX // First argument is passed in AX. + + // Save the stack pointer and frame pointer. + MOVQ BP, 16(AX) // 16 == ExecutionContextOffsetOriginalFramePointer + MOVQ SP, 24(AX) // 24 == ExecutionContextOffsetOriginalStackPointer + + // Then set the stack pointer and frame pointer to the values we got from the Go runtime. + MOVQ framePointer+24(FP), BP + + // WARNING: do not update SP before BP, because the Go translates (FP) as (SP) + 8. + MOVQ stackPointer+16(FP), SP + + JMP CX diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go new file mode 100644 index 00000000..882d06c0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go @@ -0,0 +1,248 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +var ( + executionContextPtrReg = raxVReg + + // Followings are callee saved registers. They can be used freely in the entry preamble + // since the preamble is called via Go assembly function which has stack-based ABI. + + // savedExecutionContextPtr also must be a callee-saved reg so that they can be used in the prologue and epilogue. + savedExecutionContextPtr = rdxVReg + // paramResultSlicePtr must match with entrypoint function in abi_entry_amd64.s. + paramResultSlicePtr = r12VReg + // goAllocatedStackPtr must match with entrypoint function in abi_entry_amd64.s. + goAllocatedStackPtr = r13VReg + // functionExecutable must match with entrypoint function in abi_entry_amd64.s. + functionExecutable = r14VReg + tmpIntReg = r15VReg + tmpXmmReg = xmm15VReg +) + +// CompileEntryPreamble implements backend.Machine. +func (m *machine) CompileEntryPreamble(sig *ssa.Signature) []byte { + root := m.compileEntryPreamble(sig) + m.encodeWithoutSSA(root) + buf := m.c.Buf() + return buf +} + +func (m *machine) compileEntryPreamble(sig *ssa.Signature) *instruction { + abi := backend.FunctionABI{} + abi.Init(sig, intArgResultRegs, floatArgResultRegs) + + root := m.allocateNop() + + //// ----------------------------------- prologue ----------------------------------- //// + + // First, we save executionContextPtrReg into a callee-saved register so that it can be used in epilogue as well. + // mov %executionContextPtrReg, %savedExecutionContextPtr + cur := m.move64(executionContextPtrReg, savedExecutionContextPtr, root) + + // Next is to save the original RBP and RSP into the execution context. + cur = m.saveOriginalRSPRBP(cur) + + // Now set the RSP to the Go-allocated stack pointer. + // mov %goAllocatedStackPtr, %rsp + cur = m.move64(goAllocatedStackPtr, rspVReg, cur) + + if stackSlotSize := abi.AlignedArgResultStackSlotSize(); stackSlotSize > 0 { + // Allocate stack slots for the arguments and return values. + // sub $stackSlotSize, %rsp + spDec := m.allocateInstr().asAluRmiR(aluRmiROpcodeSub, newOperandImm32(uint32(stackSlotSize)), rspVReg, true) + cur = linkInstr(cur, spDec) + } + + var offset uint32 + for i := range abi.Args { + if i < 2 { + // module context ptr and execution context ptr are passed in rax and rbx by the Go assembly function. + continue + } + arg := &abi.Args[i] + cur = m.goEntryPreamblePassArg(cur, paramResultSlicePtr, offset, arg) + if arg.Type == ssa.TypeV128 { + offset += 16 + } else { + offset += 8 + } + } + + // Zero out RBP so that the unwind/stack growth code can correctly detect the end of the stack. + zerosRbp := m.allocateInstr().asAluRmiR(aluRmiROpcodeXor, newOperandReg(rbpVReg), rbpVReg, true) + cur = linkInstr(cur, zerosRbp) + + // Now ready to call the real function. Note that at this point stack pointer is already set to the Go-allocated, + // which is aligned to 16 bytes. + call := m.allocateInstr().asCallIndirect(newOperandReg(functionExecutable), &abi) + cur = linkInstr(cur, call) + + //// ----------------------------------- epilogue ----------------------------------- //// + + // Read the results from regs and the stack, and set them correctly into the paramResultSlicePtr. + offset = 0 + for i := range abi.Rets { + r := &abi.Rets[i] + cur = m.goEntryPreamblePassResult(cur, paramResultSlicePtr, offset, r, uint32(abi.ArgStackSize)) + if r.Type == ssa.TypeV128 { + offset += 16 + } else { + offset += 8 + } + } + + // Finally, restore the original RBP and RSP. + cur = m.restoreOriginalRSPRBP(cur) + + ret := m.allocateInstr().asRet() + linkInstr(cur, ret) + return root +} + +// saveOriginalRSPRBP saves the original RSP and RBP into the execution context. +func (m *machine) saveOriginalRSPRBP(cur *instruction) *instruction { + // mov %rbp, wazevoapi.ExecutionContextOffsetOriginalFramePointer(%executionContextPtrReg) + // mov %rsp, wazevoapi.ExecutionContextOffsetOriginalStackPointer(%executionContextPtrReg) + cur = m.loadOrStore64AtExecutionCtx(executionContextPtrReg, wazevoapi.ExecutionContextOffsetOriginalFramePointer, rbpVReg, true, cur) + cur = m.loadOrStore64AtExecutionCtx(executionContextPtrReg, wazevoapi.ExecutionContextOffsetOriginalStackPointer, rspVReg, true, cur) + return cur +} + +// restoreOriginalRSPRBP restores the original RSP and RBP from the execution context. +func (m *machine) restoreOriginalRSPRBP(cur *instruction) *instruction { + // mov wazevoapi.ExecutionContextOffsetOriginalFramePointer(%executionContextPtrReg), %rbp + // mov wazevoapi.ExecutionContextOffsetOriginalStackPointer(%executionContextPtrReg), %rsp + cur = m.loadOrStore64AtExecutionCtx(savedExecutionContextPtr, wazevoapi.ExecutionContextOffsetOriginalFramePointer, rbpVReg, false, cur) + cur = m.loadOrStore64AtExecutionCtx(savedExecutionContextPtr, wazevoapi.ExecutionContextOffsetOriginalStackPointer, rspVReg, false, cur) + return cur +} + +func (m *machine) move64(src, dst regalloc.VReg, prev *instruction) *instruction { + mov := m.allocateInstr().asMovRR(src, dst, true) + return linkInstr(prev, mov) +} + +func (m *machine) loadOrStore64AtExecutionCtx(execCtx regalloc.VReg, offset wazevoapi.Offset, r regalloc.VReg, store bool, prev *instruction) *instruction { + mem := newOperandMem(m.newAmodeImmReg(offset.U32(), execCtx)) + instr := m.allocateInstr() + if store { + instr.asMovRM(r, mem, 8) + } else { + instr.asMov64MR(mem, r) + } + return linkInstr(prev, instr) +} + +// This is for debugging. +func (m *machine) linkUD2(cur *instruction) *instruction { //nolint + return linkInstr(cur, m.allocateInstr().asUD2()) +} + +func (m *machine) goEntryPreamblePassArg(cur *instruction, paramSlicePtr regalloc.VReg, offsetInParamSlice uint32, arg *backend.ABIArg) *instruction { + var dst regalloc.VReg + argTyp := arg.Type + if arg.Kind == backend.ABIArgKindStack { + // Caller saved registers ca + switch argTyp { + case ssa.TypeI32, ssa.TypeI64: + dst = tmpIntReg + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + dst = tmpXmmReg + default: + panic("BUG") + } + } else { + dst = arg.Reg + } + + load := m.allocateInstr() + a := newOperandMem(m.newAmodeImmReg(offsetInParamSlice, paramSlicePtr)) + switch arg.Type { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, a, dst) + case ssa.TypeI64: + load.asMov64MR(a, dst) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, a, dst) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, a, dst) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, a, dst) + } + + cur = linkInstr(cur, load) + if arg.Kind == backend.ABIArgKindStack { + // Store back to the stack. + store := m.allocateInstr() + a := newOperandMem(m.newAmodeImmReg(uint32(arg.Offset), rspVReg)) + switch arg.Type { + case ssa.TypeI32: + store.asMovRM(dst, a, 4) + case ssa.TypeI64: + store.asMovRM(dst, a, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, dst, a) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, dst, a) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, dst, a) + } + cur = linkInstr(cur, store) + } + return cur +} + +func (m *machine) goEntryPreamblePassResult(cur *instruction, resultSlicePtr regalloc.VReg, offsetInResultSlice uint32, result *backend.ABIArg, resultStackSlotBeginOffset uint32) *instruction { + var r regalloc.VReg + if result.Kind == backend.ABIArgKindStack { + // Load the value to the temporary. + load := m.allocateInstr() + offset := resultStackSlotBeginOffset + uint32(result.Offset) + a := newOperandMem(m.newAmodeImmReg(offset, rspVReg)) + switch result.Type { + case ssa.TypeI32: + r = tmpIntReg + load.asMovzxRmR(extModeLQ, a, r) + case ssa.TypeI64: + r = tmpIntReg + load.asMov64MR(a, r) + case ssa.TypeF32: + r = tmpXmmReg + load.asXmmUnaryRmR(sseOpcodeMovss, a, r) + case ssa.TypeF64: + r = tmpXmmReg + load.asXmmUnaryRmR(sseOpcodeMovsd, a, r) + case ssa.TypeV128: + r = tmpXmmReg + load.asXmmUnaryRmR(sseOpcodeMovdqu, a, r) + default: + panic("BUG") + } + cur = linkInstr(cur, load) + } else { + r = result.Reg + } + + store := m.allocateInstr() + a := newOperandMem(m.newAmodeImmReg(offsetInResultSlice, resultSlicePtr)) + switch result.Type { + case ssa.TypeI32: + store.asMovRM(r, a, 4) + case ssa.TypeI64: + store.asMovRM(r, a, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, r, a) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, r, a) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, r, a) + } + + return linkInstr(cur, store) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go new file mode 100644 index 00000000..96f035e5 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go @@ -0,0 +1,440 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +var calleeSavedVRegs = []regalloc.VReg{ + rdxVReg, r12VReg, r13VReg, r14VReg, r15VReg, + xmm8VReg, xmm9VReg, xmm10VReg, xmm11VReg, xmm12VReg, xmm13VReg, xmm14VReg, xmm15VReg, +} + +// CompileGoFunctionTrampoline implements backend.Machine. +func (m *machine) CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte { + argBegin := 1 // Skips exec context by default. + if needModuleContextPtr { + argBegin++ + } + + abi := &backend.FunctionABI{} + abi.Init(sig, intArgResultRegs, floatArgResultRegs) + m.currentABI = abi + + cur := m.allocateNop() + m.rootInstr = cur + + // Execution context is always the first argument. + execCtrPtr := raxVReg + + // First we update RBP and RSP just like the normal prologue. + // + // (high address) (high address) + // RBP ----> +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | ====> | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | Return Addr | | Return Addr | + // RSP ----> +-----------------+ | Caller_RBP | + // (low address) +-----------------+ <----- RSP, RBP + // + cur = m.setupRBPRSP(cur) + + goSliceSizeAligned, goSliceSizeAlignedUnaligned := backend.GoFunctionCallRequiredStackSize(sig, argBegin) + cur = m.insertStackBoundsCheck(goSliceSizeAligned+8 /* size of the Go slice */, cur) + + // Save the callee saved registers. + cur = m.saveRegistersInExecutionContext(cur, execCtrPtr, calleeSavedVRegs) + + if needModuleContextPtr { + moduleCtrPtr := rbxVReg // Module context is always the second argument. + mem := m.newAmodeImmReg( + wazevoapi.ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque.U32(), + execCtrPtr) + store := m.allocateInstr().asMovRM(moduleCtrPtr, newOperandMem(mem), 8) + cur = linkInstr(cur, store) + } + + // Now let's advance the RSP to the stack slot for the arguments. + // + // (high address) (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | =======> | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | Return Addr | | Return Addr | + // | Caller_RBP | | Caller_RBP | + // RBP,RSP --> +-----------------+ +-----------------+ <----- RBP + // (low address) | arg[N]/ret[M] | + // | .......... | + // | arg[1]/ret[1] | + // | arg[0]/ret[0] | + // +-----------------+ <----- RSP + // (low address) + // + // where the region of "arg[0]/ret[0] ... arg[N]/ret[M]" is the stack used by the Go functions, + // therefore will be accessed as the usual []uint64. So that's where we need to pass/receive + // the arguments/return values to/from Go function. + cur = m.addRSP(-int32(goSliceSizeAligned), cur) + + // Next, we need to store all the arguments to the stack in the typical Wasm stack style. + var offsetInGoSlice int32 + for i := range abi.Args[argBegin:] { + arg := &abi.Args[argBegin+i] + var v regalloc.VReg + if arg.Kind == backend.ABIArgKindReg { + v = arg.Reg + } else { + // We have saved callee saved registers, so we can use them. + if arg.Type.IsInt() { + v = r15VReg + } else { + v = xmm15VReg + } + mem := newOperandMem(m.newAmodeImmReg(uint32(arg.Offset+16 /* to skip caller_rbp and ret_addr */), rbpVReg)) + load := m.allocateInstr() + switch arg.Type { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, mem, v) + case ssa.TypeI64: + load.asMov64MR(mem, v) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, mem, v) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, mem, v) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, v) + default: + panic("BUG") + } + cur = linkInstr(cur, load) + } + + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(offsetInGoSlice), rspVReg)) + switch arg.Type { + case ssa.TypeI32: + store.asMovRM(v, mem, 4) + offsetInGoSlice += 8 // always uint64 rep. + case ssa.TypeI64: + store.asMovRM(v, mem, 8) + offsetInGoSlice += 8 + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, v, mem) + offsetInGoSlice += 8 // always uint64 rep. + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, v, mem) + offsetInGoSlice += 8 + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, v, mem) + offsetInGoSlice += 16 + default: + panic("BUG") + } + cur = linkInstr(cur, store) + } + + // Finally we push the size of the slice to the stack so the stack looks like: + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | Return Addr | + // | Caller_RBP | + // +-----------------+ <----- RBP + // | arg[N]/ret[M] | + // | .......... | + // | arg[1]/ret[1] | + // | arg[0]/ret[0] | + // | slice size | + // +-----------------+ <----- RSP + // (low address) + // + // push $sliceSize + cur = linkInstr(cur, m.allocateInstr().asPush64(newOperandImm32(uint32(goSliceSizeAlignedUnaligned)))) + + // Load the exitCode to the register. + exitCodeReg := r12VReg // Callee saved which is already saved. + cur = linkInstr(cur, m.allocateInstr().asImm(exitCodeReg, uint64(exitCode), false)) + + saveRsp, saveRbp, setExitCode := m.allocateExitInstructions(execCtrPtr, exitCodeReg) + cur = linkInstr(cur, setExitCode) + cur = linkInstr(cur, saveRsp) + cur = linkInstr(cur, saveRbp) + + // Ready to exit the execution. + cur = m.storeReturnAddressAndExit(cur, execCtrPtr) + + // We don't need the slice size anymore, so pop it. + cur = m.addRSP(8, cur) + + // Ready to set up the results. + offsetInGoSlice = 0 + // To avoid overwriting with the execution context pointer by the result, we need to track the offset, + // and defer the restoration of the result to the end of this function. + var argOverlapWithExecCtxOffset int32 = -1 + for i := range abi.Rets { + r := &abi.Rets[i] + var v regalloc.VReg + isRegResult := r.Kind == backend.ABIArgKindReg + if isRegResult { + v = r.Reg + if v.RealReg() == execCtrPtr.RealReg() { + argOverlapWithExecCtxOffset = offsetInGoSlice + offsetInGoSlice += 8 // always uint64 rep. + continue + } + } else { + if r.Type.IsInt() { + v = r15VReg + } else { + v = xmm15VReg + } + } + + load := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(offsetInGoSlice), rspVReg)) + switch r.Type { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, mem, v) + offsetInGoSlice += 8 // always uint64 rep. + case ssa.TypeI64: + load.asMov64MR(mem, v) + offsetInGoSlice += 8 + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, mem, v) + offsetInGoSlice += 8 // always uint64 rep. + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, mem, v) + offsetInGoSlice += 8 + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, v) + offsetInGoSlice += 16 + default: + panic("BUG") + } + cur = linkInstr(cur, load) + + if !isRegResult { + // We need to store it back to the result slot above rbp. + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(abi.ArgStackSize+r.Offset+16 /* to skip caller_rbp and ret_addr */), rbpVReg)) + switch r.Type { + case ssa.TypeI32: + store.asMovRM(v, mem, 4) + case ssa.TypeI64: + store.asMovRM(v, mem, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, v, mem) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, v, mem) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, v, mem) + default: + panic("BUG") + } + cur = linkInstr(cur, store) + } + } + + // Before return, we need to restore the callee saved registers. + cur = m.restoreRegistersInExecutionContext(cur, execCtrPtr, calleeSavedVRegs) + + if argOverlapWithExecCtxOffset >= 0 { + // At this point execCtt is not used anymore, so we can finally store the + // result to the register which overlaps with the execution context pointer. + mem := newOperandMem(m.newAmodeImmReg(uint32(argOverlapWithExecCtxOffset), rspVReg)) + load := m.allocateInstr().asMov64MR(mem, execCtrPtr) + cur = linkInstr(cur, load) + } + + // Finally ready to return. + cur = m.revertRBPRSP(cur) + linkInstr(cur, m.allocateInstr().asRet()) + + m.encodeWithoutSSA(m.rootInstr) + return m.c.Buf() +} + +func (m *machine) saveRegistersInExecutionContext(cur *instruction, execCtx regalloc.VReg, regs []regalloc.VReg) *instruction { + offset := wazevoapi.ExecutionContextOffsetSavedRegistersBegin.I64() + for _, v := range regs { + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(offset), execCtx)) + switch v.RegType() { + case regalloc.RegTypeInt: + store.asMovRM(v, mem, 8) + case regalloc.RegTypeFloat: + store.asXmmMovRM(sseOpcodeMovdqu, v, mem) + default: + panic("BUG") + } + cur = linkInstr(cur, store) + offset += 16 // See execution context struct. Each register is 16 bytes-aligned unconditionally. + } + return cur +} + +func (m *machine) restoreRegistersInExecutionContext(cur *instruction, execCtx regalloc.VReg, regs []regalloc.VReg) *instruction { + offset := wazevoapi.ExecutionContextOffsetSavedRegistersBegin.I64() + for _, v := range regs { + load := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(offset), execCtx)) + switch v.RegType() { + case regalloc.RegTypeInt: + load.asMov64MR(mem, v) + case regalloc.RegTypeFloat: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, v) + default: + panic("BUG") + } + cur = linkInstr(cur, load) + offset += 16 // See execution context struct. Each register is 16 bytes-aligned unconditionally. + } + return cur +} + +func (m *machine) storeReturnAddressAndExit(cur *instruction, execCtx regalloc.VReg) *instruction { + readRip := m.allocateInstr() + cur = linkInstr(cur, readRip) + + ripReg := r12VReg // Callee saved which is already saved. + saveRip := m.allocateInstr().asMovRM( + ripReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetGoCallReturnAddress.U32(), execCtx)), + 8, + ) + cur = linkInstr(cur, saveRip) + + exit := m.allocateExitSeq(execCtx) + cur = linkInstr(cur, exit) + + nop, l := m.allocateBrTarget() + cur = linkInstr(cur, nop) + readRip.asLEA(newOperandLabel(l), ripReg) + return cur +} + +// saveRequiredRegs is the set of registers that must be saved/restored during growing stack when there's insufficient +// stack space left. Basically this is the all allocatable registers except for RSP and RBP, and RAX which contains the +// execution context pointer. ExecCtx pointer is always the first argument so we don't need to save it. +var stackGrowSaveVRegs = []regalloc.VReg{ + rdxVReg, r12VReg, r13VReg, r14VReg, r15VReg, + rcxVReg, rbxVReg, rsiVReg, rdiVReg, r8VReg, r9VReg, r10VReg, r11VReg, + xmm8VReg, xmm9VReg, xmm10VReg, xmm11VReg, xmm12VReg, xmm13VReg, xmm14VReg, xmm15VReg, + xmm0VReg, xmm1VReg, xmm2VReg, xmm3VReg, xmm4VReg, xmm5VReg, xmm6VReg, xmm7VReg, +} + +// CompileStackGrowCallSequence implements backend.Machine. +func (m *machine) CompileStackGrowCallSequence() []byte { + cur := m.allocateNop() + m.rootInstr = cur + + cur = m.setupRBPRSP(cur) + + // Execution context is always the first argument. + execCtrPtr := raxVReg + + // Save the callee saved and argument registers. + cur = m.saveRegistersInExecutionContext(cur, execCtrPtr, stackGrowSaveVRegs) + + // Load the exitCode to the register. + exitCodeReg := r12VReg // Already saved. + cur = linkInstr(cur, m.allocateInstr().asImm(exitCodeReg, uint64(wazevoapi.ExitCodeGrowStack), false)) + + saveRsp, saveRbp, setExitCode := m.allocateExitInstructions(execCtrPtr, exitCodeReg) + cur = linkInstr(cur, setExitCode) + cur = linkInstr(cur, saveRsp) + cur = linkInstr(cur, saveRbp) + + // Ready to exit the execution. + cur = m.storeReturnAddressAndExit(cur, execCtrPtr) + + // After the exit, restore the saved registers. + cur = m.restoreRegistersInExecutionContext(cur, execCtrPtr, stackGrowSaveVRegs) + + // Finally ready to return. + cur = m.revertRBPRSP(cur) + linkInstr(cur, m.allocateInstr().asRet()) + + m.encodeWithoutSSA(m.rootInstr) + return m.c.Buf() +} + +// insertStackBoundsCheck will insert the instructions after `cur` to check the +// stack bounds, and if there's no sufficient spaces required for the function, +// exit the execution and try growing it in Go world. +func (m *machine) insertStackBoundsCheck(requiredStackSize int64, cur *instruction) *instruction { + // add $requiredStackSize, %rsp ;; Temporarily update the sp. + // cmp ExecutionContextOffsetStackBottomPtr(%rax), %rsp ;; Compare the stack bottom and the sp. + // ja .ok + // sub $requiredStackSize, %rsp ;; Reverse the temporary update. + // pushq r15 ;; save the temporary. + // mov $requiredStackSize, %r15 + // mov %15, ExecutionContextOffsetStackGrowRequiredSize(%rax) ;; Set the required size in the execution context. + // popq r15 ;; restore the temporary. + // callq *ExecutionContextOffsetStackGrowCallTrampolineAddress(%rax) ;; Call the Go function to grow the stack. + // jmp .cont + // .ok: + // sub $requiredStackSize, %rsp ;; Reverse the temporary update. + // .cont: + cur = m.addRSP(-int32(requiredStackSize), cur) + cur = linkInstr(cur, m.allocateInstr().asCmpRmiR(true, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetStackBottomPtr.U32(), raxVReg)), + rspVReg, true)) + + ja := m.allocateInstr() + cur = linkInstr(cur, ja) + + cur = m.addRSP(int32(requiredStackSize), cur) + + // Save the temporary. + + cur = linkInstr(cur, m.allocateInstr().asPush64(newOperandReg(r15VReg))) + // Load the required size to the temporary. + cur = linkInstr(cur, m.allocateInstr().asImm(r15VReg, uint64(requiredStackSize), true)) + // Set the required size in the execution context. + cur = linkInstr(cur, m.allocateInstr().asMovRM(r15VReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetStackGrowRequiredSize.U32(), raxVReg)), 8)) + // Restore the temporary. + cur = linkInstr(cur, m.allocateInstr().asPop64(r15VReg)) + // Call the Go function to grow the stack. + cur = linkInstr(cur, m.allocateInstr().asCallIndirect(newOperandMem(m.newAmodeImmReg( + wazevoapi.ExecutionContextOffsetStackGrowCallTrampolineAddress.U32(), raxVReg)), nil)) + // Jump to the continuation. + jmpToCont := m.allocateInstr() + cur = linkInstr(cur, jmpToCont) + + // .ok: + okInstr, ok := m.allocateBrTarget() + cur = linkInstr(cur, okInstr) + ja.asJmpIf(condNBE, newOperandLabel(ok)) + // On the ok path, we only need to reverse the temporary update. + cur = m.addRSP(int32(requiredStackSize), cur) + + // .cont: + contInstr, cont := m.allocateBrTarget() + cur = linkInstr(cur, contInstr) + jmpToCont.asJmp(newOperandLabel(cont)) + + return cur +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/cond.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/cond.go new file mode 100644 index 00000000..75cbeab7 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/cond.go @@ -0,0 +1,168 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +type cond byte + +const ( + // condO represents (overflow) condition. + condO cond = iota + // condNO represents (no overflow) condition. + condNO + // condB represents (< unsigned) condition. + condB + // condNB represents (>= unsigned) condition. + condNB + // condZ represents (zero) condition. + condZ + // condNZ represents (not-zero) condition. + condNZ + // condBE represents (<= unsigned) condition. + condBE + // condNBE represents (> unsigned) condition. + condNBE + // condS represents (negative) condition. + condS + // condNS represents (not-negative) condition. + condNS + // condP represents (parity) condition. + condP + // condNP represents (not parity) condition. + condNP + // condL represents (< signed) condition. + condL + // condNL represents (>= signed) condition. + condNL + // condLE represents (<= signed) condition. + condLE + // condNLE represents (> signed) condition. + condNLE + + condInvalid +) + +func (c cond) String() string { + switch c { + case condO: + return "o" + case condNO: + return "no" + case condB: + return "b" + case condNB: + return "nb" + case condZ: + return "z" + case condNZ: + return "nz" + case condBE: + return "be" + case condNBE: + return "nbe" + case condS: + return "s" + case condNS: + return "ns" + case condL: + return "l" + case condNL: + return "nl" + case condLE: + return "le" + case condNLE: + return "nle" + case condP: + return "p" + case condNP: + return "np" + default: + panic("unreachable") + } +} + +func condFromSSAIntCmpCond(origin ssa.IntegerCmpCond) cond { + switch origin { + case ssa.IntegerCmpCondEqual: + return condZ + case ssa.IntegerCmpCondNotEqual: + return condNZ + case ssa.IntegerCmpCondSignedLessThan: + return condL + case ssa.IntegerCmpCondSignedGreaterThanOrEqual: + return condNL + case ssa.IntegerCmpCondSignedGreaterThan: + return condNLE + case ssa.IntegerCmpCondSignedLessThanOrEqual: + return condLE + case ssa.IntegerCmpCondUnsignedLessThan: + return condB + case ssa.IntegerCmpCondUnsignedGreaterThanOrEqual: + return condNB + case ssa.IntegerCmpCondUnsignedGreaterThan: + return condNBE + case ssa.IntegerCmpCondUnsignedLessThanOrEqual: + return condBE + default: + panic("unreachable") + } +} + +func condFromSSAFloatCmpCond(origin ssa.FloatCmpCond) cond { + switch origin { + case ssa.FloatCmpCondGreaterThanOrEqual: + return condNB + case ssa.FloatCmpCondGreaterThan: + return condNBE + case ssa.FloatCmpCondEqual, ssa.FloatCmpCondNotEqual, ssa.FloatCmpCondLessThan, ssa.FloatCmpCondLessThanOrEqual: + panic(fmt.Sprintf("cond %s must be treated as a special case", origin)) + default: + panic("unreachable") + } +} + +func (c cond) encoding() byte { + return byte(c) +} + +func (c cond) invert() cond { + switch c { + case condO: + return condNO + case condNO: + return condO + case condB: + return condNB + case condNB: + return condB + case condZ: + return condNZ + case condNZ: + return condZ + case condBE: + return condNBE + case condNBE: + return condBE + case condS: + return condNS + case condNS: + return condS + case condP: + return condNP + case condNP: + return condP + case condL: + return condNL + case condNL: + return condL + case condLE: + return condNLE + case condNLE: + return condLE + default: + panic("unreachable") + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/ext.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/ext.go new file mode 100644 index 00000000..5e731e82 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/ext.go @@ -0,0 +1,35 @@ +package amd64 + +// extMode represents the mode of extension in movzx/movsx. +type extMode byte + +const ( + // extModeBL represents Byte -> Longword. + extModeBL extMode = iota + // extModeBQ represents Byte -> Quadword. + extModeBQ + // extModeWL represents Word -> Longword. + extModeWL + // extModeWQ represents Word -> Quadword. + extModeWQ + // extModeLQ represents Longword -> Quadword. + extModeLQ +) + +// String implements fmt.Stringer. +func (e extMode) String() string { + switch e { + case extModeBL: + return "bl" + case extModeBQ: + return "bq" + case extModeWL: + return "wl" + case extModeWQ: + return "wq" + case extModeLQ: + return "lq" + default: + panic("BUG: invalid ext mode") + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr.go new file mode 100644 index 00000000..6a3e58f5 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr.go @@ -0,0 +1,2447 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +type instruction struct { + prev, next *instruction + op1, op2 operand + u1, u2 uint64 + b1 bool + addedBeforeRegAlloc bool + kind instructionKind +} + +// IsCall implements regalloc.Instr. +func (i *instruction) IsCall() bool { return i.kind == call } + +// IsIndirectCall implements regalloc.Instr. +func (i *instruction) IsIndirectCall() bool { return i.kind == callIndirect } + +// IsReturn implements regalloc.Instr. +func (i *instruction) IsReturn() bool { return i.kind == ret } + +// String implements regalloc.Instr. +func (i *instruction) String() string { + switch i.kind { + case nop0: + return "nop" + case sourceOffsetInfo: + return fmt.Sprintf("source_offset_info %d", i.u1) + case ret: + return "ret" + case imm: + if i.b1 { + return fmt.Sprintf("movabsq $%d, %s", int64(i.u1), i.op2.format(true)) + } else { + return fmt.Sprintf("movl $%d, %s", int32(i.u1), i.op2.format(false)) + } + case aluRmiR: + return fmt.Sprintf("%s %s, %s", aluRmiROpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1)) + case movRR: + if i.b1 { + return fmt.Sprintf("movq %s, %s", i.op1.format(true), i.op2.format(true)) + } else { + return fmt.Sprintf("movl %s, %s", i.op1.format(false), i.op2.format(false)) + } + case xmmRmR: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false)) + case gprToXmm: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1)) + case xmmUnaryRmR: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false)) + case xmmUnaryRmRImm: + return fmt.Sprintf("%s $%d, %s, %s", sseOpcode(i.u1), roundingMode(i.u2), i.op1.format(false), i.op2.format(false)) + case unaryRmR: + var suffix string + if i.b1 { + suffix = "q" + } else { + suffix = "l" + } + return fmt.Sprintf("%s%s %s, %s", unaryRmROpcode(i.u1), suffix, i.op1.format(i.b1), i.op2.format(i.b1)) + case not: + var op string + if i.b1 { + op = "notq" + } else { + op = "notl" + } + return fmt.Sprintf("%s %s", op, i.op1.format(i.b1)) + case neg: + var op string + if i.b1 { + op = "negq" + } else { + op = "negl" + } + return fmt.Sprintf("%s %s", op, i.op1.format(i.b1)) + case div: + var prefix string + var op string + if i.b1 { + op = "divq" + } else { + op = "divl" + } + if i.u1 != 0 { + prefix = "i" + } + return fmt.Sprintf("%s%s %s", prefix, op, i.op1.format(i.b1)) + case mulHi: + signed, _64 := i.u1 != 0, i.b1 + var op string + switch { + case signed && _64: + op = "imulq" + case !signed && _64: + op = "mulq" + case signed && !_64: + op = "imull" + case !signed && !_64: + op = "mull" + } + return fmt.Sprintf("%s %s", op, i.op1.format(i.b1)) + case signExtendData: + var op string + if i.b1 { + op = "cqo" + } else { + op = "cdq" + } + return op + case movzxRmR: + return fmt.Sprintf("movzx.%s %s, %s", extMode(i.u1), i.op1.format(true), i.op2.format(true)) + case mov64MR: + return fmt.Sprintf("movq %s, %s", i.op1.format(true), i.op2.format(true)) + case lea: + return fmt.Sprintf("lea %s, %s", i.op1.format(true), i.op2.format(true)) + case movsxRmR: + return fmt.Sprintf("movsx.%s %s, %s", extMode(i.u1), i.op1.format(true), i.op2.format(true)) + case movRM: + var suffix string + switch i.u1 { + case 1: + suffix = "b" + case 2: + suffix = "w" + case 4: + suffix = "l" + case 8: + suffix = "q" + } + return fmt.Sprintf("mov.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true)) + case shiftR: + var suffix string + if i.b1 { + suffix = "q" + } else { + suffix = "l" + } + return fmt.Sprintf("%s%s %s, %s", shiftROp(i.u1), suffix, i.op1.format(false), i.op2.format(i.b1)) + case xmmRmiReg: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(true), i.op2.format(true)) + case cmpRmiR: + var op, suffix string + if i.u1 != 0 { + op = "cmp" + } else { + op = "test" + } + if i.b1 { + suffix = "q" + } else { + suffix = "l" + } + if op == "test" && i.op1.kind == operandKindMem { + // Print consistently with AT&T syntax. + return fmt.Sprintf("%s%s %s, %s", op, suffix, i.op2.format(i.b1), i.op1.format(i.b1)) + } + return fmt.Sprintf("%s%s %s, %s", op, suffix, i.op1.format(i.b1), i.op2.format(i.b1)) + case setcc: + return fmt.Sprintf("set%s %s", cond(i.u1), i.op2.format(true)) + case cmove: + var suffix string + if i.b1 { + suffix = "q" + } else { + suffix = "l" + } + return fmt.Sprintf("cmov%s%s %s, %s", cond(i.u1), suffix, i.op1.format(i.b1), i.op2.format(i.b1)) + case push64: + return fmt.Sprintf("pushq %s", i.op1.format(true)) + case pop64: + return fmt.Sprintf("popq %s", i.op1.format(true)) + case xmmMovRM: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(true), i.op2.format(true)) + case xmmLoadConst: + panic("TODO") + case xmmToGpr: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1)) + case cvtUint64ToFloatSeq: + panic("TODO") + case cvtFloatToSintSeq: + panic("TODO") + case cvtFloatToUintSeq: + panic("TODO") + case xmmMinMaxSeq: + panic("TODO") + case xmmCmpRmR: + return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false)) + case xmmRmRImm: + op := sseOpcode(i.u1) + r1, r2 := i.op1.format(op == sseOpcodePextrq || op == sseOpcodePinsrq), + i.op2.format(op == sseOpcodePextrq || op == sseOpcodePinsrq) + return fmt.Sprintf("%s $%d, %s, %s", op, i.u2, r1, r2) + case jmp: + return fmt.Sprintf("jmp %s", i.op1.format(true)) + case jmpIf: + return fmt.Sprintf("j%s %s", cond(i.u1), i.op1.format(true)) + case jmpTableIsland: + return fmt.Sprintf("jump_table_island: jmp_table_index=%d", i.u1) + case exitSequence: + return fmt.Sprintf("exit_sequence %s", i.op1.format(true)) + case ud2: + return "ud2" + case call: + return fmt.Sprintf("call %s", ssa.FuncRef(i.u1)) + case callIndirect: + return fmt.Sprintf("callq *%s", i.op1.format(true)) + case xchg: + var suffix string + switch i.u1 { + case 1: + suffix = "b" + case 2: + suffix = "w" + case 4: + suffix = "l" + case 8: + suffix = "q" + } + return fmt.Sprintf("xchg.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true)) + case zeros: + return fmt.Sprintf("xor %s, %s", i.op2.format(true), i.op2.format(true)) + case fcvtToSintSequence: + execCtx, src, tmpGp, tmpGp2, tmpXmm, src64, dst64, sat := i.fcvtToSintSequenceData() + return fmt.Sprintf( + "fcvtToSintSequence execCtx=%s, src=%s, tmpGp=%s, tmpGp2=%s, tmpXmm=%s, src64=%v, dst64=%v, sat=%v", + formatVRegSized(execCtx, true), + formatVRegSized(src, true), + formatVRegSized(tmpGp, true), + formatVRegSized(tmpGp2, true), + formatVRegSized(tmpXmm, true), src64, dst64, sat) + case fcvtToUintSequence: + execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2, src64, dst64, sat := i.fcvtToUintSequenceData() + return fmt.Sprintf( + "fcvtToUintSequence execCtx=%s, src=%s, tmpGp=%s, tmpGp2=%s, tmpXmm=%s, tmpXmm2=%s, src64=%v, dst64=%v, sat=%v", + formatVRegSized(execCtx, true), + formatVRegSized(src, true), + formatVRegSized(tmpGp, true), + formatVRegSized(tmpGp2, true), + formatVRegSized(tmpXmm, true), + formatVRegSized(tmpXmm2, true), src64, dst64, sat) + case idivRemSequence: + execCtx, divisor, tmpGp, isDiv, signed, _64 := i.idivRemSequenceData() + return fmt.Sprintf("idivRemSequence execCtx=%s, divisor=%s, tmpGp=%s, isDiv=%v, signed=%v, _64=%v", + formatVRegSized(execCtx, true), formatVRegSized(divisor, _64), formatVRegSized(tmpGp, _64), isDiv, signed, _64) + case defineUninitializedReg: + return fmt.Sprintf("defineUninitializedReg %s", i.op2.format(true)) + case xmmCMov: + return fmt.Sprintf("xmmcmov%s %s, %s", cond(i.u1), i.op1.format(true), i.op2.format(true)) + case blendvpd: + return fmt.Sprintf("blendvpd %s, %s, %%xmm0", i.op1.format(false), i.op2.format(false)) + case mfence: + return "mfence" + case lockcmpxchg: + var suffix string + switch i.u1 { + case 1: + suffix = "b" + case 2: + suffix = "w" + case 4: + suffix = "l" + case 8: + suffix = "q" + } + return fmt.Sprintf("lock cmpxchg.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true)) + case lockxadd: + var suffix string + switch i.u1 { + case 1: + suffix = "b" + case 2: + suffix = "w" + case 4: + suffix = "l" + case 8: + suffix = "q" + } + return fmt.Sprintf("lock xadd.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true)) + + case nopUseReg: + return fmt.Sprintf("nop_use_reg %s", i.op1.format(true)) + + default: + panic(fmt.Sprintf("BUG: %d", int(i.kind))) + } +} + +// Defs implements regalloc.Instr. +func (i *instruction) Defs(regs *[]regalloc.VReg) []regalloc.VReg { + *regs = (*regs)[:0] + switch dk := defKinds[i.kind]; dk { + case defKindNone: + case defKindOp2: + *regs = append(*regs, i.op2.reg()) + case defKindCall: + _, _, retIntRealRegs, retFloatRealRegs, _ := backend.ABIInfoFromUint64(i.u2) + for i := byte(0); i < retIntRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[intArgResultRegs[i]]) + } + for i := byte(0); i < retFloatRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[floatArgResultRegs[i]]) + } + case defKindDivRem: + _, _, _, isDiv, _, _ := i.idivRemSequenceData() + if isDiv { + *regs = append(*regs, raxVReg) + } else { + *regs = append(*regs, rdxVReg) + } + default: + panic(fmt.Sprintf("BUG: invalid defKind \"%s\" for %s", dk, i)) + } + return *regs +} + +// Uses implements regalloc.Instr. +func (i *instruction) Uses(regs *[]regalloc.VReg) []regalloc.VReg { + *regs = (*regs)[:0] + switch uk := useKinds[i.kind]; uk { + case useKindNone: + case useKindOp1Op2Reg, useKindOp1RegOp2: + opAny, opReg := &i.op1, &i.op2 + if uk == useKindOp1RegOp2 { + opAny, opReg = opReg, opAny + } + // The destination operand (op2) can be only reg, + // the source operand (op1) can be imm32, reg or mem. + switch opAny.kind { + case operandKindReg: + *regs = append(*regs, opAny.reg()) + case operandKindMem: + opAny.addressMode().uses(regs) + case operandKindImm32: + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + if opReg.kind != operandKindReg { + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + *regs = append(*regs, opReg.reg()) + case useKindOp1: + op := i.op1 + switch op.kind { + case operandKindReg: + *regs = append(*regs, op.reg()) + case operandKindMem: + op.addressMode().uses(regs) + case operandKindImm32, operandKindLabel: + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + case useKindCallInd: + op := i.op1 + switch op.kind { + case operandKindReg: + *regs = append(*regs, op.reg()) + case operandKindMem: + op.addressMode().uses(regs) + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + fallthrough + case useKindCall: + argIntRealRegs, argFloatRealRegs, _, _, _ := backend.ABIInfoFromUint64(i.u2) + for i := byte(0); i < argIntRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[intArgResultRegs[i]]) + } + for i := byte(0); i < argFloatRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[floatArgResultRegs[i]]) + } + case useKindFcvtToSintSequence: + execCtx, src, tmpGp, tmpGp2, tmpXmm, _, _, _ := i.fcvtToSintSequenceData() + *regs = append(*regs, execCtx, src, tmpGp, tmpGp2, tmpXmm) + case useKindFcvtToUintSequence: + execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2, _, _, _ := i.fcvtToUintSequenceData() + *regs = append(*regs, execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2) + case useKindDivRem: + execCtx, divisor, tmpGp, _, _, _ := i.idivRemSequenceData() + // idiv uses rax and rdx as implicit operands. + *regs = append(*regs, raxVReg, rdxVReg, execCtx, divisor, tmpGp) + case useKindBlendvpd: + *regs = append(*regs, xmm0VReg) + + opAny, opReg := &i.op1, &i.op2 + switch opAny.kind { + case operandKindReg: + *regs = append(*regs, opAny.reg()) + case operandKindMem: + opAny.addressMode().uses(regs) + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + if opReg.kind != operandKindReg { + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + *regs = append(*regs, opReg.reg()) + + case useKindRaxOp1RegOp2: + opReg, opAny := &i.op1, &i.op2 + *regs = append(*regs, raxVReg, opReg.reg()) + switch opAny.kind { + case operandKindReg: + *regs = append(*regs, opAny.reg()) + case operandKindMem: + opAny.addressMode().uses(regs) + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + if opReg.kind != operandKindReg { + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + + default: + panic(fmt.Sprintf("BUG: invalid useKind %s for %s", uk, i)) + } + return *regs +} + +// AssignUse implements regalloc.Instr. +func (i *instruction) AssignUse(index int, v regalloc.VReg) { + switch uk := useKinds[i.kind]; uk { + case useKindNone: + case useKindCallInd: + if index != 0 { + panic("BUG") + } + op := &i.op1 + switch op.kind { + case operandKindReg: + op.setReg(v) + case operandKindMem: + op.addressMode().assignUses(index, v) + default: + panic("BUG") + } + case useKindOp1Op2Reg, useKindOp1RegOp2: + op, opMustBeReg := &i.op1, &i.op2 + if uk == useKindOp1RegOp2 { + op, opMustBeReg = opMustBeReg, op + } + switch op.kind { + case operandKindReg: + if index == 0 { + op.setReg(v) + } else if index == 1 { + opMustBeReg.setReg(v) + } else { + panic("BUG") + } + case operandKindMem: + nregs := op.addressMode().nregs() + if index < nregs { + op.addressMode().assignUses(index, v) + } else if index == nregs { + opMustBeReg.setReg(v) + } else { + panic("BUG") + } + case operandKindImm32: + if index == 0 { + opMustBeReg.setReg(v) + } else { + panic("BUG") + } + default: + panic(fmt.Sprintf("BUG: invalid operand pair: %s", i)) + } + case useKindOp1: + op := &i.op1 + switch op.kind { + case operandKindReg: + if index != 0 { + panic("BUG") + } + op.setReg(v) + case operandKindMem: + op.addressMode().assignUses(index, v) + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", i)) + } + case useKindFcvtToSintSequence: + switch index { + case 0: + i.op1.addressMode().base = v + case 1: + i.op1.addressMode().index = v + case 2: + i.op2.addressMode().base = v + case 3: + i.op2.addressMode().index = v + case 4: + i.u1 = uint64(v) + default: + panic("BUG") + } + case useKindFcvtToUintSequence: + switch index { + case 0: + i.op1.addressMode().base = v + case 1: + i.op1.addressMode().index = v + case 2: + i.op2.addressMode().base = v + case 3: + i.op2.addressMode().index = v + case 4: + i.u1 = uint64(v) + case 5: + i.u2 = uint64(v) + default: + panic("BUG") + } + case useKindDivRem: + switch index { + case 0: + if v != raxVReg { + panic("BUG") + } + case 1: + if v != rdxVReg { + panic("BUG") + } + case 2: + i.op1.setReg(v) + case 3: + i.op2.setReg(v) + case 4: + i.u1 = uint64(v) + default: + panic("BUG") + } + case useKindBlendvpd: + op, opMustBeReg := &i.op1, &i.op2 + if index == 0 { + if v.RealReg() != xmm0 { + panic("BUG") + } + } else { + switch op.kind { + case operandKindReg: + switch index { + case 1: + op.setReg(v) + case 2: + opMustBeReg.setReg(v) + default: + panic("BUG") + } + case operandKindMem: + nregs := op.addressMode().nregs() + index-- + if index < nregs { + op.addressMode().assignUses(index, v) + } else if index == nregs { + opMustBeReg.setReg(v) + } else { + panic("BUG") + } + default: + panic(fmt.Sprintf("BUG: invalid operand pair: %s", i)) + } + } + + case useKindRaxOp1RegOp2: + switch index { + case 0: + if v.RealReg() != rax { + panic("BUG") + } + case 1: + i.op1.setReg(v) + default: + op := &i.op2 + switch op.kind { + case operandKindReg: + switch index { + case 1: + op.setReg(v) + case 2: + op.setReg(v) + default: + panic("BUG") + } + case operandKindMem: + nregs := op.addressMode().nregs() + index -= 2 + if index < nregs { + op.addressMode().assignUses(index, v) + } else if index == nregs { + op.setReg(v) + } else { + panic("BUG") + } + default: + panic(fmt.Sprintf("BUG: invalid operand pair: %s", i)) + } + } + default: + panic(fmt.Sprintf("BUG: invalid useKind %s for %s", uk, i)) + } +} + +// AssignDef implements regalloc.Instr. +func (i *instruction) AssignDef(reg regalloc.VReg) { + switch dk := defKinds[i.kind]; dk { + case defKindNone: + case defKindOp2: + i.op2.setReg(reg) + default: + panic(fmt.Sprintf("BUG: invalid defKind \"%s\" for %s", dk, i)) + } +} + +// IsCopy implements regalloc.Instr. +func (i *instruction) IsCopy() bool { + k := i.kind + if k == movRR { + return true + } + if k == xmmUnaryRmR { + if i.op1.kind == operandKindReg { + sse := sseOpcode(i.u1) + return sse == sseOpcodeMovss || sse == sseOpcodeMovsd || sse == sseOpcodeMovdqu + } + } + return false +} + +func resetInstruction(i *instruction) { + *i = instruction{} +} + +func (i *instruction) asNop0WithLabel(label label) *instruction { //nolint + i.kind = nop0 + i.u1 = uint64(label) + return i +} + +func (i *instruction) nop0Label() label { + return label(i.u1) +} + +type instructionKind byte + +const ( + nop0 instructionKind = iota + 1 + + // Integer arithmetic/bit-twiddling: (add sub and or xor mul, etc.) (32 64) (reg addr imm) reg + aluRmiR + + // Instructions on GPR that only read src and defines dst (dst is not modified): bsr, etc. + unaryRmR + + // Bitwise not + not + + // Integer negation + neg + + // Integer quotient and remainder: (div idiv) $rax $rdx (reg addr) + div + + // The high bits (RDX) of a (un)signed multiply: RDX:RAX := RAX * rhs. + mulHi + + // Do a sign-extend based on the sign of the value in rax into rdx: (cwd cdq cqo) + // or al into ah: (cbw) + signExtendData + + // Constant materialization: (imm32 imm64) reg. + // Either: movl $imm32, %reg32 or movabsq $imm64, %reg64. + imm + + // GPR to GPR move: mov (64 32) reg reg. + movRR + + // movzxRmR is zero-extended loads or move (R to R), except for 64 bits: movz (bl bq wl wq lq) addr reg. + // Note that the lq variant doesn't really exist since the default zero-extend rule makes it + // unnecessary. For that case we emit the equivalent "movl AM, reg32". + movzxRmR + + // mov64MR is a plain 64-bit integer load, since movzxRmR can't represent that. + mov64MR + + // Loads the memory address of addr into dst. + lea + + // Sign-extended loads and moves: movs (bl bq wl wq lq) addr reg. + movsxRmR + + // Integer stores: mov (b w l q) reg addr. + movRM + + // Arithmetic shifts: (shl shr sar) (b w l q) imm reg. + shiftR + + // Arithmetic SIMD shifts. + xmmRmiReg + + // Integer comparisons/tests: cmp or test (b w l q) (reg addr imm) reg. + cmpRmiR + + // Materializes the requested condition code in the destination reg. + setcc + + // Integer conditional move. + // Overwrites the destination register. + cmove + + // pushq (reg addr imm) + push64 + + // popq reg + pop64 + + // XMM (scalar or vector) binary op: (add sub and or xor mul adc? sbb?) (32 64) (reg addr) reg + xmmRmR + + // XMM (scalar or vector) unary op: mov between XMM registers (32 64) (reg addr) reg. + // + // This differs from xmmRmR in that the dst register of xmmUnaryRmR is not used in the + // computation of the instruction dst value and so does not have to be a previously valid + // value. This is characteristic of mov instructions. + xmmUnaryRmR + + // XMM (scalar or vector) unary op with immediate: roundss, roundsd, etc. + // + // This differs from XMM_RM_R_IMM in that the dst register of + // XmmUnaryRmRImm is not used in the computation of the instruction dst + // value and so does not have to be a previously valid value. + xmmUnaryRmRImm + + // XMM (scalar or vector) unary op (from xmm to mem): stores, movd, movq + xmmMovRM + + // XMM (vector) unary op (to move a constant value into an xmm register): movups + xmmLoadConst + + // XMM (scalar) unary op (from xmm to integer reg): movd, movq, cvtts{s,d}2si + xmmToGpr + + // XMM (scalar) unary op (from integer to float reg): movd, movq, cvtsi2s{s,d} + gprToXmm + + // Converts an unsigned int64 to a float32/float64. + cvtUint64ToFloatSeq + + // Converts a scalar xmm to a signed int32/int64. + cvtFloatToSintSeq + + // Converts a scalar xmm to an unsigned int32/int64. + cvtFloatToUintSeq + + // A sequence to compute min/max with the proper NaN semantics for xmm registers. + xmmMinMaxSeq + + // Float comparisons/tests: cmp (b w l q) (reg addr imm) reg. + xmmCmpRmR + + // A binary XMM instruction with an 8-bit immediate: e.g. cmp (ps pd) imm (reg addr) reg + xmmRmRImm + + // Direct call: call simm32. + // Note that the offset is the relative to the *current RIP*, which points to the first byte of the next instruction. + call + + // Indirect call: callq (reg mem). + callIndirect + + // Return. + ret + + // Jump: jmp (reg, mem, imm32 or label) + jmp + + // Jump conditionally: jcond cond label. + jmpIf + + // jmpTableIsland is to emit the jump table. + jmpTableIsland + + // exitSequence exits the execution and go back to the Go world. + exitSequence + + // An instruction that will always trigger the illegal instruction exception. + ud2 + + // xchg is described in https://www.felixcloutier.com/x86/xchg. + // This instruction uses two operands, where one of them can be a memory address, and swaps their values. + // If the dst is a memory address, the execution is atomic. + xchg + + // lockcmpxchg is the cmpxchg instruction https://www.felixcloutier.com/x86/cmpxchg with a lock prefix. + lockcmpxchg + + // zeros puts zeros into the destination register. This is implemented as xor reg, reg for + // either integer or XMM registers. The reason why we have this instruction instead of using aluRmiR + // is that it requires the already-defined registers. From reg alloc's perspective, this defines + // the destination register and takes no inputs. + zeros + + // sourceOffsetInfo is a dummy instruction to emit source offset info. + // The existence of this instruction does not affect the execution. + sourceOffsetInfo + + // defineUninitializedReg is a no-op instruction that defines a register without a defining instruction. + defineUninitializedReg + + // fcvtToSintSequence is a sequence of instructions to convert a float to a signed integer. + fcvtToSintSequence + + // fcvtToUintSequence is a sequence of instructions to convert a float to an unsigned integer. + fcvtToUintSequence + + // xmmCMov is a conditional move instruction for XMM registers. Lowered after register allocation. + xmmCMov + + // idivRemSequence is a sequence of instructions to compute both the quotient and remainder of a division. + idivRemSequence + + // blendvpd is https://www.felixcloutier.com/x86/blendvpd. + blendvpd + + // mfence is https://www.felixcloutier.com/x86/mfence + mfence + + // lockxadd is xadd https://www.felixcloutier.com/x86/xadd with a lock prefix. + lockxadd + + // nopUseReg is a meta instruction that uses one register and does nothing. + nopUseReg + + instrMax +) + +func (i *instruction) asMFence() *instruction { + i.kind = mfence + return i +} + +func (i *instruction) asNopUseReg(r regalloc.VReg) *instruction { + i.kind = nopUseReg + i.op1 = newOperandReg(r) + return i +} + +func (i *instruction) asIdivRemSequence(execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool) *instruction { + i.kind = idivRemSequence + i.op1 = newOperandReg(execCtx) + i.op2 = newOperandReg(divisor) + i.u1 = uint64(tmpGp) + if isDiv { + i.u2 |= 1 + } + if signed { + i.u2 |= 2 + } + if _64 { + i.u2 |= 4 + } + return i +} + +func (i *instruction) idivRemSequenceData() ( + execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool, +) { + if i.kind != idivRemSequence { + panic("BUG") + } + return i.op1.reg(), i.op2.reg(), regalloc.VReg(i.u1), i.u2&1 != 0, i.u2&2 != 0, i.u2&4 != 0 +} + +func (i *instruction) asXmmCMov(cc cond, x operand, rd regalloc.VReg, size byte) *instruction { + i.kind = xmmCMov + i.op1 = x + i.op2 = newOperandReg(rd) + i.u1 = uint64(cc) + i.u2 = uint64(size) + return i +} + +func (i *instruction) asDefineUninitializedReg(r regalloc.VReg) *instruction { + i.kind = defineUninitializedReg + i.op2 = newOperandReg(r) + return i +} + +func (m *machine) allocateFcvtToUintSequence( + execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2 regalloc.VReg, + src64, dst64, sat bool, +) *instruction { + i := m.allocateInstr() + i.kind = fcvtToUintSequence + op1a := m.amodePool.Allocate() + op2a := m.amodePool.Allocate() + i.op1 = newOperandMem(op1a) + i.op2 = newOperandMem(op2a) + if src64 { + op1a.imm32 = 1 + } else { + op1a.imm32 = 0 + } + if dst64 { + op1a.imm32 |= 2 + } + if sat { + op1a.imm32 |= 4 + } + + op1a.base = execCtx + op1a.index = src + op2a.base = tmpGp + op2a.index = tmpGp2 + i.u1 = uint64(tmpXmm) + i.u2 = uint64(tmpXmm2) + return i +} + +func (i *instruction) fcvtToUintSequenceData() ( + execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2 regalloc.VReg, src64, dst64, sat bool, +) { + if i.kind != fcvtToUintSequence { + panic("BUG") + } + op1a := i.op1.addressMode() + op2a := i.op2.addressMode() + return op1a.base, op1a.index, op2a.base, op2a.index, regalloc.VReg(i.u1), regalloc.VReg(i.u2), + op1a.imm32&1 != 0, op1a.imm32&2 != 0, op1a.imm32&4 != 0 +} + +func (m *machine) allocateFcvtToSintSequence( + execCtx, src, tmpGp, tmpGp2, tmpXmm regalloc.VReg, + src64, dst64, sat bool, +) *instruction { + i := m.allocateInstr() + i.kind = fcvtToSintSequence + op1a := m.amodePool.Allocate() + op2a := m.amodePool.Allocate() + i.op1 = newOperandMem(op1a) + i.op2 = newOperandMem(op2a) + op1a.base = execCtx + op1a.index = src + op2a.base = tmpGp + op2a.index = tmpGp2 + i.u1 = uint64(tmpXmm) + if src64 { + i.u2 = 1 + } else { + i.u2 = 0 + } + if dst64 { + i.u2 |= 2 + } + if sat { + i.u2 |= 4 + } + return i +} + +func (i *instruction) fcvtToSintSequenceData() ( + execCtx, src, tmpGp, tmpGp2, tmpXmm regalloc.VReg, src64, dst64, sat bool, +) { + if i.kind != fcvtToSintSequence { + panic("BUG") + } + op1a := i.op1.addressMode() + op2a := i.op2.addressMode() + return op1a.base, op1a.index, op2a.base, op2a.index, regalloc.VReg(i.u1), + i.u2&1 != 0, i.u2&2 != 0, i.u2&4 != 0 +} + +func (k instructionKind) String() string { + switch k { + case nop0: + return "nop" + case ret: + return "ret" + case imm: + return "imm" + case aluRmiR: + return "aluRmiR" + case movRR: + return "movRR" + case xmmRmR: + return "xmmRmR" + case gprToXmm: + return "gprToXmm" + case xmmUnaryRmR: + return "xmmUnaryRmR" + case xmmUnaryRmRImm: + return "xmmUnaryRmRImm" + case unaryRmR: + return "unaryRmR" + case not: + return "not" + case neg: + return "neg" + case div: + return "div" + case mulHi: + return "mulHi" + case signExtendData: + return "signExtendData" + case movzxRmR: + return "movzxRmR" + case mov64MR: + return "mov64MR" + case lea: + return "lea" + case movsxRmR: + return "movsxRmR" + case movRM: + return "movRM" + case shiftR: + return "shiftR" + case xmmRmiReg: + return "xmmRmiReg" + case cmpRmiR: + return "cmpRmiR" + case setcc: + return "setcc" + case cmove: + return "cmove" + case push64: + return "push64" + case pop64: + return "pop64" + case xmmMovRM: + return "xmmMovRM" + case xmmLoadConst: + return "xmmLoadConst" + case xmmToGpr: + return "xmmToGpr" + case cvtUint64ToFloatSeq: + return "cvtUint64ToFloatSeq" + case cvtFloatToSintSeq: + return "cvtFloatToSintSeq" + case cvtFloatToUintSeq: + return "cvtFloatToUintSeq" + case xmmMinMaxSeq: + return "xmmMinMaxSeq" + case xmmCmpRmR: + return "xmmCmpRmR" + case xmmRmRImm: + return "xmmRmRImm" + case jmpIf: + return "jmpIf" + case jmp: + return "jmp" + case jmpTableIsland: + return "jmpTableIsland" + case exitSequence: + return "exit_sequence" + case ud2: + return "ud2" + case xchg: + return "xchg" + case zeros: + return "zeros" + case fcvtToSintSequence: + return "fcvtToSintSequence" + case fcvtToUintSequence: + return "fcvtToUintSequence" + case xmmCMov: + return "xmmCMov" + case idivRemSequence: + return "idivRemSequence" + case mfence: + return "mfence" + case lockcmpxchg: + return "lockcmpxchg" + case lockxadd: + return "lockxadd" + default: + panic("BUG") + } +} + +type aluRmiROpcode byte + +const ( + aluRmiROpcodeAdd aluRmiROpcode = iota + 1 + aluRmiROpcodeSub + aluRmiROpcodeAnd + aluRmiROpcodeOr + aluRmiROpcodeXor + aluRmiROpcodeMul +) + +func (a aluRmiROpcode) String() string { + switch a { + case aluRmiROpcodeAdd: + return "add" + case aluRmiROpcodeSub: + return "sub" + case aluRmiROpcodeAnd: + return "and" + case aluRmiROpcodeOr: + return "or" + case aluRmiROpcodeXor: + return "xor" + case aluRmiROpcodeMul: + return "imul" + default: + panic("BUG") + } +} + +func (i *instruction) asJmpIf(cond cond, target operand) *instruction { + i.kind = jmpIf + i.u1 = uint64(cond) + i.op1 = target + return i +} + +// asJmpTableSequence is used to emit the jump table. +// targetSliceIndex is the index of the target slice in machine.jmpTableTargets. +func (i *instruction) asJmpTableSequence(targetSliceIndex int, targetCount int) *instruction { + i.kind = jmpTableIsland + i.u1 = uint64(targetSliceIndex) + i.u2 = uint64(targetCount) + return i +} + +func (i *instruction) asJmp(target operand) *instruction { + i.kind = jmp + i.op1 = target + return i +} + +func (i *instruction) jmpLabel() label { + switch i.kind { + case jmp, jmpIf, lea, xmmUnaryRmR: + return i.op1.label() + default: + panic("BUG") + } +} + +func (i *instruction) asLEA(target operand, rd regalloc.VReg) *instruction { + i.kind = lea + i.op1 = target + i.op2 = newOperandReg(rd) + return i +} + +func (i *instruction) asCall(ref ssa.FuncRef, abi *backend.FunctionABI) *instruction { + i.kind = call + i.u1 = uint64(ref) + if abi != nil { + i.u2 = abi.ABIInfoAsUint64() + } + return i +} + +func (i *instruction) asCallIndirect(ptr operand, abi *backend.FunctionABI) *instruction { + if ptr.kind != operandKindReg && ptr.kind != operandKindMem { + panic("BUG") + } + i.kind = callIndirect + i.op1 = ptr + if abi != nil { + i.u2 = abi.ABIInfoAsUint64() + } + return i +} + +func (i *instruction) asRet() *instruction { + i.kind = ret + return i +} + +func (i *instruction) asImm(dst regalloc.VReg, value uint64, _64 bool) *instruction { + i.kind = imm + i.op2 = newOperandReg(dst) + i.u1 = value + i.b1 = _64 + return i +} + +func (i *instruction) asAluRmiR(op aluRmiROpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem && rm.kind != operandKindImm32 { + panic("BUG") + } + i.kind = aluRmiR + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.b1 = _64 + return i +} + +func (i *instruction) asZeros(dst regalloc.VReg) *instruction { + i.kind = zeros + i.op2 = newOperandReg(dst) + return i +} + +func (i *instruction) asBlendvpd(rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = blendvpd + i.op1 = rm + i.op2 = newOperandReg(rd) + return i +} + +func (i *instruction) asXmmRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmRmR + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + return i +} + +func (i *instruction) asXmmRmRImm(op sseOpcode, imm uint8, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmRmRImm + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.u2 = uint64(imm) + return i +} + +func (i *instruction) asGprToXmm(op sseOpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = gprToXmm + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.b1 = _64 + return i +} + +func (i *instruction) asEmitSourceOffsetInfo(l ssa.SourceOffset) *instruction { + i.kind = sourceOffsetInfo + i.u1 = uint64(l) + return i +} + +func (i *instruction) sourceOffsetInfo() ssa.SourceOffset { + return ssa.SourceOffset(i.u1) +} + +func (i *instruction) asXmmToGpr(op sseOpcode, rm, rd regalloc.VReg, _64 bool) *instruction { + i.kind = xmmToGpr + i.op1 = newOperandReg(rm) + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.b1 = _64 + return i +} + +func (i *instruction) asMovRM(rm regalloc.VReg, rd operand, size byte) *instruction { + if rd.kind != operandKindMem { + panic("BUG") + } + i.kind = movRM + i.op1 = newOperandReg(rm) + i.op2 = rd + i.u1 = uint64(size) + return i +} + +func (i *instruction) asMovsxRmR(ext extMode, src operand, rd regalloc.VReg) *instruction { + if src.kind != operandKindReg && src.kind != operandKindMem { + panic("BUG") + } + i.kind = movsxRmR + i.op1 = src + i.op2 = newOperandReg(rd) + i.u1 = uint64(ext) + return i +} + +func (i *instruction) asMovzxRmR(ext extMode, src operand, rd regalloc.VReg) *instruction { + if src.kind != operandKindReg && src.kind != operandKindMem { + panic("BUG") + } + i.kind = movzxRmR + i.op1 = src + i.op2 = newOperandReg(rd) + i.u1 = uint64(ext) + return i +} + +func (i *instruction) asSignExtendData(_64 bool) *instruction { + i.kind = signExtendData + i.b1 = _64 + return i +} + +func (i *instruction) asUD2() *instruction { + i.kind = ud2 + return i +} + +func (i *instruction) asDiv(rn operand, signed bool, _64 bool) *instruction { + i.kind = div + i.op1 = rn + i.b1 = _64 + if signed { + i.u1 = 1 + } + return i +} + +func (i *instruction) asMov64MR(rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindMem { + panic("BUG") + } + i.kind = mov64MR + i.op1 = rm + i.op2 = newOperandReg(rd) + return i +} + +func (i *instruction) asMovRR(rm, rd regalloc.VReg, _64 bool) *instruction { + i.kind = movRR + i.op1 = newOperandReg(rm) + i.op2 = newOperandReg(rd) + i.b1 = _64 + return i +} + +func (i *instruction) asNot(rm operand, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = not + i.op1 = rm + i.b1 = _64 + return i +} + +func (i *instruction) asNeg(rm operand, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = neg + i.op1 = rm + i.b1 = _64 + return i +} + +func (i *instruction) asMulHi(rm operand, signed, _64 bool) *instruction { + if rm.kind != operandKindReg && (rm.kind != operandKindMem) { + panic("BUG") + } + i.kind = mulHi + i.op1 = rm + i.b1 = _64 + if signed { + i.u1 = 1 + } + return i +} + +func (i *instruction) asUnaryRmR(op unaryRmROpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = unaryRmR + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.b1 = _64 + return i +} + +func (i *instruction) asShiftR(op shiftROp, amount operand, rd regalloc.VReg, _64 bool) *instruction { + if amount.kind != operandKindReg && amount.kind != operandKindImm32 { + panic("BUG") + } + i.kind = shiftR + i.op1 = amount + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.b1 = _64 + return i +} + +func (i *instruction) asXmmRmiReg(op sseOpcode, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindImm32 && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmRmiReg + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + return i +} + +func (i *instruction) asCmpRmiR(cmp bool, rm operand, rn regalloc.VReg, _64 bool) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindImm32 && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = cmpRmiR + i.op1 = rm + i.op2 = newOperandReg(rn) + if cmp { + i.u1 = 1 + } + i.b1 = _64 + return i +} + +func (i *instruction) asSetcc(c cond, rd regalloc.VReg) *instruction { + i.kind = setcc + i.op2 = newOperandReg(rd) + i.u1 = uint64(c) + return i +} + +func (i *instruction) asCmove(c cond, rm operand, rd regalloc.VReg, _64 bool) *instruction { + i.kind = cmove + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(c) + i.b1 = _64 + return i +} + +func (m *machine) allocateExitSeq(execCtx regalloc.VReg) *instruction { + i := m.allocateInstr() + i.kind = exitSequence + i.op1 = newOperandReg(execCtx) + // Allocate the address mode that will be used in encoding the exit sequence. + i.op2 = newOperandMem(m.amodePool.Allocate()) + return i +} + +func (i *instruction) asXmmUnaryRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmUnaryRmR + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + return i +} + +func (i *instruction) asXmmUnaryRmRImm(op sseOpcode, imm byte, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmUnaryRmRImm + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + i.u2 = uint64(imm) + return i +} + +func (i *instruction) asXmmCmpRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction { + if rm.kind != operandKindReg && rm.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmCmpRmR + i.op1 = rm + i.op2 = newOperandReg(rd) + i.u1 = uint64(op) + return i +} + +func (i *instruction) asXmmMovRM(op sseOpcode, rm regalloc.VReg, rd operand) *instruction { + if rd.kind != operandKindMem { + panic("BUG") + } + i.kind = xmmMovRM + i.op1 = newOperandReg(rm) + i.op2 = rd + i.u1 = uint64(op) + return i +} + +func (i *instruction) asPop64(rm regalloc.VReg) *instruction { + i.kind = pop64 + i.op1 = newOperandReg(rm) + return i +} + +func (i *instruction) asPush64(op operand) *instruction { + if op.kind != operandKindReg && op.kind != operandKindMem && op.kind != operandKindImm32 { + panic("BUG") + } + i.kind = push64 + i.op1 = op + return i +} + +func (i *instruction) asXCHG(rm regalloc.VReg, rd operand, size byte) *instruction { + i.kind = xchg + i.op1 = newOperandReg(rm) + i.op2 = rd + i.u1 = uint64(size) + return i +} + +func (i *instruction) asLockCmpXCHG(rm regalloc.VReg, rd *amode, size byte) *instruction { + i.kind = lockcmpxchg + i.op1 = newOperandReg(rm) + i.op2 = newOperandMem(rd) + i.u1 = uint64(size) + return i +} + +func (i *instruction) asLockXAdd(rm regalloc.VReg, rd *amode, size byte) *instruction { + i.kind = lockxadd + i.op1 = newOperandReg(rm) + i.op2 = newOperandMem(rd) + i.u1 = uint64(size) + return i +} + +type unaryRmROpcode byte + +const ( + unaryRmROpcodeBsr unaryRmROpcode = iota + unaryRmROpcodeBsf + unaryRmROpcodeLzcnt + unaryRmROpcodeTzcnt + unaryRmROpcodePopcnt +) + +func (u unaryRmROpcode) String() string { + switch u { + case unaryRmROpcodeBsr: + return "bsr" + case unaryRmROpcodeBsf: + return "bsf" + case unaryRmROpcodeLzcnt: + return "lzcnt" + case unaryRmROpcodeTzcnt: + return "tzcnt" + case unaryRmROpcodePopcnt: + return "popcnt" + default: + panic("BUG") + } +} + +type shiftROp byte + +const ( + shiftROpRotateLeft shiftROp = 0 + shiftROpRotateRight shiftROp = 1 + shiftROpShiftLeft shiftROp = 4 + shiftROpShiftRightLogical shiftROp = 5 + shiftROpShiftRightArithmetic shiftROp = 7 +) + +func (s shiftROp) String() string { + switch s { + case shiftROpRotateLeft: + return "rol" + case shiftROpRotateRight: + return "ror" + case shiftROpShiftLeft: + return "shl" + case shiftROpShiftRightLogical: + return "shr" + case shiftROpShiftRightArithmetic: + return "sar" + default: + panic("BUG") + } +} + +type sseOpcode byte + +const ( + sseOpcodeInvalid sseOpcode = iota + sseOpcodeAddps + sseOpcodeAddpd + sseOpcodeAddss + sseOpcodeAddsd + sseOpcodeAndps + sseOpcodeAndpd + sseOpcodeAndnps + sseOpcodeAndnpd + sseOpcodeBlendvps + sseOpcodeBlendvpd + sseOpcodeComiss + sseOpcodeComisd + sseOpcodeCmpps + sseOpcodeCmppd + sseOpcodeCmpss + sseOpcodeCmpsd + sseOpcodeCvtdq2ps + sseOpcodeCvtdq2pd + sseOpcodeCvtsd2ss + sseOpcodeCvtsd2si + sseOpcodeCvtsi2ss + sseOpcodeCvtsi2sd + sseOpcodeCvtss2si + sseOpcodeCvtss2sd + sseOpcodeCvttps2dq + sseOpcodeCvttss2si + sseOpcodeCvttsd2si + sseOpcodeDivps + sseOpcodeDivpd + sseOpcodeDivss + sseOpcodeDivsd + sseOpcodeInsertps + sseOpcodeMaxps + sseOpcodeMaxpd + sseOpcodeMaxss + sseOpcodeMaxsd + sseOpcodeMinps + sseOpcodeMinpd + sseOpcodeMinss + sseOpcodeMinsd + sseOpcodeMovaps + sseOpcodeMovapd + sseOpcodeMovd + sseOpcodeMovdqa + sseOpcodeMovdqu + sseOpcodeMovlhps + sseOpcodeMovmskps + sseOpcodeMovmskpd + sseOpcodeMovq + sseOpcodeMovss + sseOpcodeMovsd + sseOpcodeMovups + sseOpcodeMovupd + sseOpcodeMulps + sseOpcodeMulpd + sseOpcodeMulss + sseOpcodeMulsd + sseOpcodeOrps + sseOpcodeOrpd + sseOpcodePabsb + sseOpcodePabsw + sseOpcodePabsd + sseOpcodePackssdw + sseOpcodePacksswb + sseOpcodePackusdw + sseOpcodePackuswb + sseOpcodePaddb + sseOpcodePaddd + sseOpcodePaddq + sseOpcodePaddw + sseOpcodePaddsb + sseOpcodePaddsw + sseOpcodePaddusb + sseOpcodePaddusw + sseOpcodePalignr + sseOpcodePand + sseOpcodePandn + sseOpcodePavgb + sseOpcodePavgw + sseOpcodePcmpeqb + sseOpcodePcmpeqw + sseOpcodePcmpeqd + sseOpcodePcmpeqq + sseOpcodePcmpgtb + sseOpcodePcmpgtw + sseOpcodePcmpgtd + sseOpcodePcmpgtq + sseOpcodePextrb + sseOpcodePextrw + sseOpcodePextrd + sseOpcodePextrq + sseOpcodePinsrb + sseOpcodePinsrw + sseOpcodePinsrd + sseOpcodePinsrq + sseOpcodePmaddwd + sseOpcodePmaxsb + sseOpcodePmaxsw + sseOpcodePmaxsd + sseOpcodePmaxub + sseOpcodePmaxuw + sseOpcodePmaxud + sseOpcodePminsb + sseOpcodePminsw + sseOpcodePminsd + sseOpcodePminub + sseOpcodePminuw + sseOpcodePminud + sseOpcodePmovmskb + sseOpcodePmovsxbd + sseOpcodePmovsxbw + sseOpcodePmovsxbq + sseOpcodePmovsxwd + sseOpcodePmovsxwq + sseOpcodePmovsxdq + sseOpcodePmovzxbd + sseOpcodePmovzxbw + sseOpcodePmovzxbq + sseOpcodePmovzxwd + sseOpcodePmovzxwq + sseOpcodePmovzxdq + sseOpcodePmulld + sseOpcodePmullw + sseOpcodePmuludq + sseOpcodePor + sseOpcodePshufb + sseOpcodePshufd + sseOpcodePsllw + sseOpcodePslld + sseOpcodePsllq + sseOpcodePsraw + sseOpcodePsrad + sseOpcodePsrlw + sseOpcodePsrld + sseOpcodePsrlq + sseOpcodePsubb + sseOpcodePsubd + sseOpcodePsubq + sseOpcodePsubw + sseOpcodePsubsb + sseOpcodePsubsw + sseOpcodePsubusb + sseOpcodePsubusw + sseOpcodePtest + sseOpcodePunpckhbw + sseOpcodePunpcklbw + sseOpcodePxor + sseOpcodeRcpss + sseOpcodeRoundps + sseOpcodeRoundpd + sseOpcodeRoundss + sseOpcodeRoundsd + sseOpcodeRsqrtss + sseOpcodeSqrtps + sseOpcodeSqrtpd + sseOpcodeSqrtss + sseOpcodeSqrtsd + sseOpcodeSubps + sseOpcodeSubpd + sseOpcodeSubss + sseOpcodeSubsd + sseOpcodeUcomiss + sseOpcodeUcomisd + sseOpcodeXorps + sseOpcodeXorpd + sseOpcodePmulhrsw + sseOpcodeUnpcklps + sseOpcodeCvtps2pd + sseOpcodeCvtpd2ps + sseOpcodeCvttpd2dq + sseOpcodeShufps + sseOpcodePmaddubsw +) + +func (s sseOpcode) String() string { + switch s { + case sseOpcodeInvalid: + return "invalid" + case sseOpcodeAddps: + return "addps" + case sseOpcodeAddpd: + return "addpd" + case sseOpcodeAddss: + return "addss" + case sseOpcodeAddsd: + return "addsd" + case sseOpcodeAndps: + return "andps" + case sseOpcodeAndpd: + return "andpd" + case sseOpcodeAndnps: + return "andnps" + case sseOpcodeAndnpd: + return "andnpd" + case sseOpcodeBlendvps: + return "blendvps" + case sseOpcodeBlendvpd: + return "blendvpd" + case sseOpcodeComiss: + return "comiss" + case sseOpcodeComisd: + return "comisd" + case sseOpcodeCmpps: + return "cmpps" + case sseOpcodeCmppd: + return "cmppd" + case sseOpcodeCmpss: + return "cmpss" + case sseOpcodeCmpsd: + return "cmpsd" + case sseOpcodeCvtdq2ps: + return "cvtdq2ps" + case sseOpcodeCvtdq2pd: + return "cvtdq2pd" + case sseOpcodeCvtsd2ss: + return "cvtsd2ss" + case sseOpcodeCvtsd2si: + return "cvtsd2si" + case sseOpcodeCvtsi2ss: + return "cvtsi2ss" + case sseOpcodeCvtsi2sd: + return "cvtsi2sd" + case sseOpcodeCvtss2si: + return "cvtss2si" + case sseOpcodeCvtss2sd: + return "cvtss2sd" + case sseOpcodeCvttps2dq: + return "cvttps2dq" + case sseOpcodeCvttss2si: + return "cvttss2si" + case sseOpcodeCvttsd2si: + return "cvttsd2si" + case sseOpcodeDivps: + return "divps" + case sseOpcodeDivpd: + return "divpd" + case sseOpcodeDivss: + return "divss" + case sseOpcodeDivsd: + return "divsd" + case sseOpcodeInsertps: + return "insertps" + case sseOpcodeMaxps: + return "maxps" + case sseOpcodeMaxpd: + return "maxpd" + case sseOpcodeMaxss: + return "maxss" + case sseOpcodeMaxsd: + return "maxsd" + case sseOpcodeMinps: + return "minps" + case sseOpcodeMinpd: + return "minpd" + case sseOpcodeMinss: + return "minss" + case sseOpcodeMinsd: + return "minsd" + case sseOpcodeMovaps: + return "movaps" + case sseOpcodeMovapd: + return "movapd" + case sseOpcodeMovd: + return "movd" + case sseOpcodeMovdqa: + return "movdqa" + case sseOpcodeMovdqu: + return "movdqu" + case sseOpcodeMovlhps: + return "movlhps" + case sseOpcodeMovmskps: + return "movmskps" + case sseOpcodeMovmskpd: + return "movmskpd" + case sseOpcodeMovq: + return "movq" + case sseOpcodeMovss: + return "movss" + case sseOpcodeMovsd: + return "movsd" + case sseOpcodeMovups: + return "movups" + case sseOpcodeMovupd: + return "movupd" + case sseOpcodeMulps: + return "mulps" + case sseOpcodeMulpd: + return "mulpd" + case sseOpcodeMulss: + return "mulss" + case sseOpcodeMulsd: + return "mulsd" + case sseOpcodeOrps: + return "orps" + case sseOpcodeOrpd: + return "orpd" + case sseOpcodePabsb: + return "pabsb" + case sseOpcodePabsw: + return "pabsw" + case sseOpcodePabsd: + return "pabsd" + case sseOpcodePackssdw: + return "packssdw" + case sseOpcodePacksswb: + return "packsswb" + case sseOpcodePackusdw: + return "packusdw" + case sseOpcodePackuswb: + return "packuswb" + case sseOpcodePaddb: + return "paddb" + case sseOpcodePaddd: + return "paddd" + case sseOpcodePaddq: + return "paddq" + case sseOpcodePaddw: + return "paddw" + case sseOpcodePaddsb: + return "paddsb" + case sseOpcodePaddsw: + return "paddsw" + case sseOpcodePaddusb: + return "paddusb" + case sseOpcodePaddusw: + return "paddusw" + case sseOpcodePalignr: + return "palignr" + case sseOpcodePand: + return "pand" + case sseOpcodePandn: + return "pandn" + case sseOpcodePavgb: + return "pavgb" + case sseOpcodePavgw: + return "pavgw" + case sseOpcodePcmpeqb: + return "pcmpeqb" + case sseOpcodePcmpeqw: + return "pcmpeqw" + case sseOpcodePcmpeqd: + return "pcmpeqd" + case sseOpcodePcmpeqq: + return "pcmpeqq" + case sseOpcodePcmpgtb: + return "pcmpgtb" + case sseOpcodePcmpgtw: + return "pcmpgtw" + case sseOpcodePcmpgtd: + return "pcmpgtd" + case sseOpcodePcmpgtq: + return "pcmpgtq" + case sseOpcodePextrb: + return "pextrb" + case sseOpcodePextrw: + return "pextrw" + case sseOpcodePextrd: + return "pextrd" + case sseOpcodePextrq: + return "pextrq" + case sseOpcodePinsrb: + return "pinsrb" + case sseOpcodePinsrw: + return "pinsrw" + case sseOpcodePinsrd: + return "pinsrd" + case sseOpcodePinsrq: + return "pinsrq" + case sseOpcodePmaddwd: + return "pmaddwd" + case sseOpcodePmaxsb: + return "pmaxsb" + case sseOpcodePmaxsw: + return "pmaxsw" + case sseOpcodePmaxsd: + return "pmaxsd" + case sseOpcodePmaxub: + return "pmaxub" + case sseOpcodePmaxuw: + return "pmaxuw" + case sseOpcodePmaxud: + return "pmaxud" + case sseOpcodePminsb: + return "pminsb" + case sseOpcodePminsw: + return "pminsw" + case sseOpcodePminsd: + return "pminsd" + case sseOpcodePminub: + return "pminub" + case sseOpcodePminuw: + return "pminuw" + case sseOpcodePminud: + return "pminud" + case sseOpcodePmovmskb: + return "pmovmskb" + case sseOpcodePmovsxbd: + return "pmovsxbd" + case sseOpcodePmovsxbw: + return "pmovsxbw" + case sseOpcodePmovsxbq: + return "pmovsxbq" + case sseOpcodePmovsxwd: + return "pmovsxwd" + case sseOpcodePmovsxwq: + return "pmovsxwq" + case sseOpcodePmovsxdq: + return "pmovsxdq" + case sseOpcodePmovzxbd: + return "pmovzxbd" + case sseOpcodePmovzxbw: + return "pmovzxbw" + case sseOpcodePmovzxbq: + return "pmovzxbq" + case sseOpcodePmovzxwd: + return "pmovzxwd" + case sseOpcodePmovzxwq: + return "pmovzxwq" + case sseOpcodePmovzxdq: + return "pmovzxdq" + case sseOpcodePmulld: + return "pmulld" + case sseOpcodePmullw: + return "pmullw" + case sseOpcodePmuludq: + return "pmuludq" + case sseOpcodePor: + return "por" + case sseOpcodePshufb: + return "pshufb" + case sseOpcodePshufd: + return "pshufd" + case sseOpcodePsllw: + return "psllw" + case sseOpcodePslld: + return "pslld" + case sseOpcodePsllq: + return "psllq" + case sseOpcodePsraw: + return "psraw" + case sseOpcodePsrad: + return "psrad" + case sseOpcodePsrlw: + return "psrlw" + case sseOpcodePsrld: + return "psrld" + case sseOpcodePsrlq: + return "psrlq" + case sseOpcodePsubb: + return "psubb" + case sseOpcodePsubd: + return "psubd" + case sseOpcodePsubq: + return "psubq" + case sseOpcodePsubw: + return "psubw" + case sseOpcodePsubsb: + return "psubsb" + case sseOpcodePsubsw: + return "psubsw" + case sseOpcodePsubusb: + return "psubusb" + case sseOpcodePsubusw: + return "psubusw" + case sseOpcodePtest: + return "ptest" + case sseOpcodePunpckhbw: + return "punpckhbw" + case sseOpcodePunpcklbw: + return "punpcklbw" + case sseOpcodePxor: + return "pxor" + case sseOpcodeRcpss: + return "rcpss" + case sseOpcodeRoundps: + return "roundps" + case sseOpcodeRoundpd: + return "roundpd" + case sseOpcodeRoundss: + return "roundss" + case sseOpcodeRoundsd: + return "roundsd" + case sseOpcodeRsqrtss: + return "rsqrtss" + case sseOpcodeSqrtps: + return "sqrtps" + case sseOpcodeSqrtpd: + return "sqrtpd" + case sseOpcodeSqrtss: + return "sqrtss" + case sseOpcodeSqrtsd: + return "sqrtsd" + case sseOpcodeSubps: + return "subps" + case sseOpcodeSubpd: + return "subpd" + case sseOpcodeSubss: + return "subss" + case sseOpcodeSubsd: + return "subsd" + case sseOpcodeUcomiss: + return "ucomiss" + case sseOpcodeUcomisd: + return "ucomisd" + case sseOpcodeXorps: + return "xorps" + case sseOpcodeXorpd: + return "xorpd" + case sseOpcodePmulhrsw: + return "pmulhrsw" + case sseOpcodeUnpcklps: + return "unpcklps" + case sseOpcodeCvtps2pd: + return "cvtps2pd" + case sseOpcodeCvtpd2ps: + return "cvtpd2ps" + case sseOpcodeCvttpd2dq: + return "cvttpd2dq" + case sseOpcodeShufps: + return "shufps" + case sseOpcodePmaddubsw: + return "pmaddubsw" + default: + panic("BUG") + } +} + +type roundingMode uint8 + +const ( + roundingModeNearest roundingMode = iota + roundingModeDown + roundingModeUp + roundingModeZero +) + +func (r roundingMode) String() string { + switch r { + case roundingModeNearest: + return "nearest" + case roundingModeDown: + return "down" + case roundingModeUp: + return "up" + case roundingModeZero: + return "zero" + default: + panic("BUG") + } +} + +// cmpPred is the immediate value for a comparison operation in xmmRmRImm. +type cmpPred uint8 + +const ( + // cmpPredEQ_OQ is Equal (ordered, non-signaling) + cmpPredEQ_OQ cmpPred = iota + // cmpPredLT_OS is Less-than (ordered, signaling) + cmpPredLT_OS + // cmpPredLE_OS is Less-than-or-equal (ordered, signaling) + cmpPredLE_OS + // cmpPredUNORD_Q is Unordered (non-signaling) + cmpPredUNORD_Q + // cmpPredNEQ_UQ is Not-equal (unordered, non-signaling) + cmpPredNEQ_UQ + // cmpPredNLT_US is Not-less-than (unordered, signaling) + cmpPredNLT_US + // cmpPredNLE_US is Not-less-than-or-equal (unordered, signaling) + cmpPredNLE_US + // cmpPredORD_Q is Ordered (non-signaling) + cmpPredORD_Q + // cmpPredEQ_UQ is Equal (unordered, non-signaling) + cmpPredEQ_UQ + // cmpPredNGE_US is Not-greater-than-or-equal (unordered, signaling) + cmpPredNGE_US + // cmpPredNGT_US is Not-greater-than (unordered, signaling) + cmpPredNGT_US + // cmpPredFALSE_OQ is False (ordered, non-signaling) + cmpPredFALSE_OQ + // cmpPredNEQ_OQ is Not-equal (ordered, non-signaling) + cmpPredNEQ_OQ + // cmpPredGE_OS is Greater-than-or-equal (ordered, signaling) + cmpPredGE_OS + // cmpPredGT_OS is Greater-than (ordered, signaling) + cmpPredGT_OS + // cmpPredTRUE_UQ is True (unordered, non-signaling) + cmpPredTRUE_UQ + // Equal (ordered, signaling) + cmpPredEQ_OS + // Less-than (ordered, nonsignaling) + cmpPredLT_OQ + // Less-than-or-equal (ordered, nonsignaling) + cmpPredLE_OQ + // Unordered (signaling) + cmpPredUNORD_S + // Not-equal (unordered, signaling) + cmpPredNEQ_US + // Not-less-than (unordered, nonsignaling) + cmpPredNLT_UQ + // Not-less-than-or-equal (unordered, nonsignaling) + cmpPredNLE_UQ + // Ordered (signaling) + cmpPredORD_S + // Equal (unordered, signaling) + cmpPredEQ_US + // Not-greater-than-or-equal (unordered, non-signaling) + cmpPredNGE_UQ + // Not-greater-than (unordered, nonsignaling) + cmpPredNGT_UQ + // False (ordered, signaling) + cmpPredFALSE_OS + // Not-equal (ordered, signaling) + cmpPredNEQ_OS + // Greater-than-or-equal (ordered, nonsignaling) + cmpPredGE_OQ + // Greater-than (ordered, nonsignaling) + cmpPredGT_OQ + // True (unordered, signaling) + cmpPredTRUE_US +) + +func (r cmpPred) String() string { + switch r { + case cmpPredEQ_OQ: + return "eq_oq" + case cmpPredLT_OS: + return "lt_os" + case cmpPredLE_OS: + return "le_os" + case cmpPredUNORD_Q: + return "unord_q" + case cmpPredNEQ_UQ: + return "neq_uq" + case cmpPredNLT_US: + return "nlt_us" + case cmpPredNLE_US: + return "nle_us" + case cmpPredORD_Q: + return "ord_q" + case cmpPredEQ_UQ: + return "eq_uq" + case cmpPredNGE_US: + return "nge_us" + case cmpPredNGT_US: + return "ngt_us" + case cmpPredFALSE_OQ: + return "false_oq" + case cmpPredNEQ_OQ: + return "neq_oq" + case cmpPredGE_OS: + return "ge_os" + case cmpPredGT_OS: + return "gt_os" + case cmpPredTRUE_UQ: + return "true_uq" + case cmpPredEQ_OS: + return "eq_os" + case cmpPredLT_OQ: + return "lt_oq" + case cmpPredLE_OQ: + return "le_oq" + case cmpPredUNORD_S: + return "unord_s" + case cmpPredNEQ_US: + return "neq_us" + case cmpPredNLT_UQ: + return "nlt_uq" + case cmpPredNLE_UQ: + return "nle_uq" + case cmpPredORD_S: + return "ord_s" + case cmpPredEQ_US: + return "eq_us" + case cmpPredNGE_UQ: + return "nge_uq" + case cmpPredNGT_UQ: + return "ngt_uq" + case cmpPredFALSE_OS: + return "false_os" + case cmpPredNEQ_OS: + return "neq_os" + case cmpPredGE_OQ: + return "ge_oq" + case cmpPredGT_OQ: + return "gt_oq" + case cmpPredTRUE_US: + return "true_us" + default: + panic("BUG") + } +} + +func linkInstr(prev, next *instruction) *instruction { + prev.next = next + next.prev = prev + return next +} + +type defKind byte + +const ( + defKindNone defKind = iota + 1 + defKindOp2 + defKindCall + defKindDivRem +) + +var defKinds = [instrMax]defKind{ + nop0: defKindNone, + ret: defKindNone, + movRR: defKindOp2, + movRM: defKindNone, + xmmMovRM: defKindNone, + aluRmiR: defKindNone, + shiftR: defKindNone, + imm: defKindOp2, + unaryRmR: defKindOp2, + xmmRmiReg: defKindNone, + xmmUnaryRmR: defKindOp2, + xmmUnaryRmRImm: defKindOp2, + xmmCmpRmR: defKindNone, + xmmRmR: defKindNone, + xmmRmRImm: defKindNone, + mov64MR: defKindOp2, + movsxRmR: defKindOp2, + movzxRmR: defKindOp2, + gprToXmm: defKindOp2, + xmmToGpr: defKindOp2, + cmove: defKindNone, + call: defKindCall, + callIndirect: defKindCall, + ud2: defKindNone, + jmp: defKindNone, + jmpIf: defKindNone, + jmpTableIsland: defKindNone, + cmpRmiR: defKindNone, + exitSequence: defKindNone, + lea: defKindOp2, + setcc: defKindOp2, + zeros: defKindOp2, + sourceOffsetInfo: defKindNone, + fcvtToSintSequence: defKindNone, + defineUninitializedReg: defKindOp2, + fcvtToUintSequence: defKindNone, + xmmCMov: defKindOp2, + idivRemSequence: defKindDivRem, + blendvpd: defKindNone, + mfence: defKindNone, + xchg: defKindNone, + lockcmpxchg: defKindNone, + lockxadd: defKindNone, + neg: defKindNone, + nopUseReg: defKindNone, +} + +// String implements fmt.Stringer. +func (d defKind) String() string { + switch d { + case defKindNone: + return "none" + case defKindOp2: + return "op2" + case defKindCall: + return "call" + case defKindDivRem: + return "divrem" + default: + return "invalid" + } +} + +type useKind byte + +const ( + useKindNone useKind = iota + 1 + useKindOp1 + // useKindOp1Op2Reg is Op1 can be any operand, Op2 must be a register. + useKindOp1Op2Reg + // useKindOp1RegOp2 is Op1 must be a register, Op2 can be any operand. + useKindOp1RegOp2 + // useKindRaxOp1RegOp2 is Op1 must be a register, Op2 can be any operand, and RAX is used. + useKindRaxOp1RegOp2 + useKindDivRem + useKindBlendvpd + useKindCall + useKindCallInd + useKindFcvtToSintSequence + useKindFcvtToUintSequence +) + +var useKinds = [instrMax]useKind{ + nop0: useKindNone, + ret: useKindNone, + movRR: useKindOp1, + movRM: useKindOp1RegOp2, + xmmMovRM: useKindOp1RegOp2, + cmove: useKindOp1Op2Reg, + aluRmiR: useKindOp1Op2Reg, + shiftR: useKindOp1Op2Reg, + imm: useKindNone, + unaryRmR: useKindOp1, + xmmRmiReg: useKindOp1Op2Reg, + xmmUnaryRmR: useKindOp1, + xmmUnaryRmRImm: useKindOp1, + xmmCmpRmR: useKindOp1Op2Reg, + xmmRmR: useKindOp1Op2Reg, + xmmRmRImm: useKindOp1Op2Reg, + mov64MR: useKindOp1, + movzxRmR: useKindOp1, + movsxRmR: useKindOp1, + gprToXmm: useKindOp1, + xmmToGpr: useKindOp1, + call: useKindCall, + callIndirect: useKindCallInd, + ud2: useKindNone, + jmpIf: useKindOp1, + jmp: useKindOp1, + cmpRmiR: useKindOp1Op2Reg, + exitSequence: useKindOp1, + lea: useKindOp1, + jmpTableIsland: useKindNone, + setcc: useKindNone, + zeros: useKindNone, + sourceOffsetInfo: useKindNone, + fcvtToSintSequence: useKindFcvtToSintSequence, + defineUninitializedReg: useKindNone, + fcvtToUintSequence: useKindFcvtToUintSequence, + xmmCMov: useKindOp1, + idivRemSequence: useKindDivRem, + blendvpd: useKindBlendvpd, + mfence: useKindNone, + xchg: useKindOp1RegOp2, + lockcmpxchg: useKindRaxOp1RegOp2, + lockxadd: useKindOp1RegOp2, + neg: useKindOp1, + nopUseReg: useKindOp1, +} + +func (u useKind) String() string { + switch u { + case useKindNone: + return "none" + case useKindOp1: + return "op1" + case useKindOp1Op2Reg: + return "op1op2Reg" + case useKindOp1RegOp2: + return "op1RegOp2" + case useKindCall: + return "call" + case useKindCallInd: + return "callInd" + default: + return "invalid" + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go new file mode 100644 index 00000000..6637b428 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go @@ -0,0 +1,1683 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +func (i *instruction) encode(c backend.Compiler) (needsLabelResolution bool) { + switch kind := i.kind; kind { + case nop0, sourceOffsetInfo, defineUninitializedReg, fcvtToSintSequence, fcvtToUintSequence, nopUseReg: + case ret: + encodeRet(c) + case imm: + dst := regEncodings[i.op2.reg().RealReg()] + con := i.u1 + if i.b1 { // 64 bit. + if lower32willSignExtendTo64(con) { + // Sign extend mov(imm32). + encodeRegReg(c, + legacyPrefixesNone, + 0xc7, 1, + 0, + dst, + rexInfo(0).setW(), + ) + c.Emit4Bytes(uint32(con)) + } else { + c.EmitByte(rexEncodingW | dst.rexBit()) + c.EmitByte(0xb8 | dst.encoding()) + c.Emit8Bytes(con) + } + } else { + if dst.rexBit() > 0 { + c.EmitByte(rexEncodingDefault | 0x1) + } + c.EmitByte(0xb8 | dst.encoding()) + c.Emit4Bytes(uint32(con)) + } + + case aluRmiR: + var rex rexInfo + if i.b1 { + rex = rex.setW() + } else { + rex = rex.clearW() + } + + dst := regEncodings[i.op2.reg().RealReg()] + + aluOp := aluRmiROpcode(i.u1) + if aluOp == aluRmiROpcodeMul { + op1 := i.op1 + const regMemOpc, regMemOpcNum = 0x0FAF, 2 + switch op1.kind { + case operandKindReg: + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, legacyPrefixesNone, regMemOpc, regMemOpcNum, dst, src, rex) + case operandKindMem: + m := i.op1.addressMode() + encodeRegMem(c, legacyPrefixesNone, regMemOpc, regMemOpcNum, dst, m, rex) + case operandKindImm32: + imm8 := lower8willSignExtendTo32(op1.imm32()) + var opc uint32 + if imm8 { + opc = 0x6b + } else { + opc = 0x69 + } + encodeRegReg(c, legacyPrefixesNone, opc, 1, dst, dst, rex) + if imm8 { + c.EmitByte(byte(op1.imm32())) + } else { + c.Emit4Bytes(op1.imm32()) + } + default: + panic("BUG: invalid operand kind") + } + } else { + const opcodeNum = 1 + var opcR, opcM, subOpcImm uint32 + switch aluOp { + case aluRmiROpcodeAdd: + opcR, opcM, subOpcImm = 0x01, 0x03, 0x0 + case aluRmiROpcodeSub: + opcR, opcM, subOpcImm = 0x29, 0x2b, 0x5 + case aluRmiROpcodeAnd: + opcR, opcM, subOpcImm = 0x21, 0x23, 0x4 + case aluRmiROpcodeOr: + opcR, opcM, subOpcImm = 0x09, 0x0b, 0x1 + case aluRmiROpcodeXor: + opcR, opcM, subOpcImm = 0x31, 0x33, 0x6 + default: + panic("BUG: invalid aluRmiROpcode") + } + + op1 := i.op1 + switch op1.kind { + case operandKindReg: + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, legacyPrefixesNone, opcR, opcodeNum, src, dst, rex) + case operandKindMem: + m := i.op1.addressMode() + encodeRegMem(c, legacyPrefixesNone, opcM, opcodeNum, dst, m, rex) + case operandKindImm32: + imm8 := lower8willSignExtendTo32(op1.imm32()) + var opc uint32 + if imm8 { + opc = 0x83 + } else { + opc = 0x81 + } + encodeRegReg(c, legacyPrefixesNone, opc, opcodeNum, regEnc(subOpcImm), dst, rex) + if imm8 { + c.EmitByte(byte(op1.imm32())) + } else { + c.Emit4Bytes(op1.imm32()) + } + default: + panic("BUG: invalid operand kind") + } + } + + case movRR: + src := regEncodings[i.op1.reg().RealReg()] + dst := regEncodings[i.op2.reg().RealReg()] + var rex rexInfo + if i.b1 { + rex = rex.setW() + } else { + rex = rex.clearW() + } + encodeRegReg(c, legacyPrefixesNone, 0x89, 1, src, dst, rex) + + case xmmRmR, blendvpd: + op := sseOpcode(i.u1) + var legPrex legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + switch op { + case sseOpcodeAddps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F58, 2 + case sseOpcodeAddpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F58, 2 + case sseOpcodeAddss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F58, 2 + case sseOpcodeAddsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F58, 2 + case sseOpcodeAndps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F54, 2 + case sseOpcodeAndpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F54, 2 + case sseOpcodeAndnps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F55, 2 + case sseOpcodeAndnpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F55, 2 + case sseOpcodeBlendvps: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3814, 3 + case sseOpcodeBlendvpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3815, 3 + case sseOpcodeDivps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F5E, 2 + case sseOpcodeDivpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F5E, 2 + case sseOpcodeDivss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5E, 2 + case sseOpcodeDivsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F5E, 2 + case sseOpcodeMaxps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F5F, 2 + case sseOpcodeMaxpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F5F, 2 + case sseOpcodeMaxss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5F, 2 + case sseOpcodeMaxsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F5F, 2 + case sseOpcodeMinps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F5D, 2 + case sseOpcodeMinpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F5D, 2 + case sseOpcodeMinss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5D, 2 + case sseOpcodeMinsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F5D, 2 + case sseOpcodeMovlhps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F16, 2 + case sseOpcodeMovsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F10, 2 + case sseOpcodeMulps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F59, 2 + case sseOpcodeMulpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F59, 2 + case sseOpcodeMulss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F59, 2 + case sseOpcodeMulsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F59, 2 + case sseOpcodeOrpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F56, 2 + case sseOpcodeOrps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F56, 2 + case sseOpcodePackssdw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F6B, 2 + case sseOpcodePacksswb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F63, 2 + case sseOpcodePackusdw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F382B, 3 + case sseOpcodePackuswb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F67, 2 + case sseOpcodePaddb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FFC, 2 + case sseOpcodePaddd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FFE, 2 + case sseOpcodePaddq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FD4, 2 + case sseOpcodePaddw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FFD, 2 + case sseOpcodePaddsb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FEC, 2 + case sseOpcodePaddsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FED, 2 + case sseOpcodePaddusb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDC, 2 + case sseOpcodePaddusw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDD, 2 + case sseOpcodePand: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDB, 2 + case sseOpcodePandn: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDF, 2 + case sseOpcodePavgb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FE0, 2 + case sseOpcodePavgw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FE3, 2 + case sseOpcodePcmpeqb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F74, 2 + case sseOpcodePcmpeqw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F75, 2 + case sseOpcodePcmpeqd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F76, 2 + case sseOpcodePcmpeqq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3829, 3 + case sseOpcodePcmpgtb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F64, 2 + case sseOpcodePcmpgtw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F65, 2 + case sseOpcodePcmpgtd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F66, 2 + case sseOpcodePcmpgtq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3837, 3 + case sseOpcodePmaddwd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FF5, 2 + case sseOpcodePmaxsb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383C, 3 + case sseOpcodePmaxsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FEE, 2 + case sseOpcodePmaxsd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383D, 3 + case sseOpcodePmaxub: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDE, 2 + case sseOpcodePmaxuw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383E, 3 + case sseOpcodePmaxud: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383F, 3 + case sseOpcodePminsb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3838, 3 + case sseOpcodePminsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FEA, 2 + case sseOpcodePminsd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3839, 3 + case sseOpcodePminub: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FDA, 2 + case sseOpcodePminuw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383A, 3 + case sseOpcodePminud: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F383B, 3 + case sseOpcodePmulld: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3840, 3 + case sseOpcodePmullw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FD5, 2 + case sseOpcodePmuludq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FF4, 2 + case sseOpcodePor: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FEB, 2 + case sseOpcodePshufb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3800, 3 + case sseOpcodePsubb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FF8, 2 + case sseOpcodePsubd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FFA, 2 + case sseOpcodePsubq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FFB, 2 + case sseOpcodePsubw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FF9, 2 + case sseOpcodePsubsb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FE8, 2 + case sseOpcodePsubsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FE9, 2 + case sseOpcodePsubusb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FD8, 2 + case sseOpcodePsubusw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FD9, 2 + case sseOpcodePunpckhbw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F68, 2 + case sseOpcodePunpcklbw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F60, 2 + case sseOpcodePxor: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FEF, 2 + case sseOpcodeSubps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F5C, 2 + case sseOpcodeSubpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F5C, 2 + case sseOpcodeSubss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5C, 2 + case sseOpcodeSubsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F5C, 2 + case sseOpcodeXorps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F57, 2 + case sseOpcodeXorpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F57, 2 + case sseOpcodePmulhrsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F380B, 3 + case sseOpcodeUnpcklps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0F14, 2 + case sseOpcodePmaddubsw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3804, 3 + default: + if kind == blendvpd { + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3815, 3 + } else { + panic(fmt.Sprintf("Unsupported sseOpcode: %s", op)) + } + } + + dst := regEncodings[i.op2.reg().RealReg()] + + rex := rexInfo(0).clearW() + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, legPrex, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + m := i.op1.addressMode() + encodeRegMem(c, legPrex, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case gprToXmm: + var legPrefix legacyPrefixes + var opcode uint32 + const opcodeNum = 2 + switch sseOpcode(i.u1) { + case sseOpcodeMovd, sseOpcodeMovq: + legPrefix, opcode = legacyPrefixes0x66, 0x0f6e + case sseOpcodeCvtsi2ss: + legPrefix, opcode = legacyPrefixes0xF3, 0x0f2a + case sseOpcodeCvtsi2sd: + legPrefix, opcode = legacyPrefixes0xF2, 0x0f2a + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", sseOpcode(i.u1))) + } + + var rex rexInfo + if i.b1 { + rex = rex.setW() + } else { + rex = rex.clearW() + } + dst := regEncodings[i.op2.reg().RealReg()] + + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, legPrefix, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + m := i.op1.addressMode() + encodeRegMem(c, legPrefix, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case xmmUnaryRmR: + var prefix legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + op := sseOpcode(i.u1) + switch op { + case sseOpcodeCvtss2sd: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5A, 2 + case sseOpcodeCvtsd2ss: + prefix, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F5A, 2 + case sseOpcodeMovaps: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F28, 2 + case sseOpcodeMovapd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F28, 2 + case sseOpcodeMovdqa: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F6F, 2 + case sseOpcodeMovdqu: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F6F, 2 + case sseOpcodeMovsd: + prefix, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F10, 2 + case sseOpcodeMovss: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F10, 2 + case sseOpcodeMovups: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F10, 2 + case sseOpcodeMovupd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F10, 2 + case sseOpcodePabsb: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F381C, 3 + case sseOpcodePabsw: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F381D, 3 + case sseOpcodePabsd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F381E, 3 + case sseOpcodePmovsxbd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3821, 3 + case sseOpcodePmovsxbw: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3820, 3 + case sseOpcodePmovsxbq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3822, 3 + case sseOpcodePmovsxwd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3823, 3 + case sseOpcodePmovsxwq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3824, 3 + case sseOpcodePmovsxdq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3825, 3 + case sseOpcodePmovzxbd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3831, 3 + case sseOpcodePmovzxbw: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3830, 3 + case sseOpcodePmovzxbq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3832, 3 + case sseOpcodePmovzxwd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3833, 3 + case sseOpcodePmovzxwq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3834, 3 + case sseOpcodePmovzxdq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3835, 3 + case sseOpcodeSqrtps: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F51, 2 + case sseOpcodeSqrtpd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F51, 2 + case sseOpcodeSqrtss: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F51, 2 + case sseOpcodeSqrtsd: + prefix, opcode, opcodeNum = legacyPrefixes0xF2, 0x0F51, 2 + case sseOpcodeXorps: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F57, 2 + case sseOpcodeXorpd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F57, 2 + case sseOpcodeCvtdq2ps: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F5B, 2 + case sseOpcodeCvtdq2pd: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0FE6, 2 + case sseOpcodeCvtps2pd: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0F5A, 2 + case sseOpcodeCvtpd2ps: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0F5A, 2 + case sseOpcodeCvttps2dq: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0F5B, 2 + case sseOpcodeCvttpd2dq: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0FE6, 2 + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", op)) + } + + dst := regEncodings[i.op2.reg().RealReg()] + + rex := rexInfo(0).clearW() + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, prefix, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + m := i.op1.addressMode() + needsLabelResolution = encodeRegMem(c, prefix, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case xmmUnaryRmRImm: + var prefix legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + op := sseOpcode(i.u1) + switch op { + case sseOpcodeRoundps: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f3a08, 3 + case sseOpcodeRoundss: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f3a0a, 3 + case sseOpcodeRoundpd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f3a09, 3 + case sseOpcodeRoundsd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f3a0b, 3 + } + rex := rexInfo(0).clearW() + dst := regEncodings[i.op2.reg().RealReg()] + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, prefix, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + m := i.op1.addressMode() + encodeRegMem(c, prefix, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + c.EmitByte(byte(i.u2)) + + case unaryRmR: + var prefix legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + op := unaryRmROpcode(i.u1) + // We assume size is either 32 or 64. + switch op { + case unaryRmROpcodeBsr: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0fbd, 2 + case unaryRmROpcodeBsf: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0fbc, 2 + case unaryRmROpcodeLzcnt: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0fbd, 2 + case unaryRmROpcodeTzcnt: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0fbc, 2 + case unaryRmROpcodePopcnt: + prefix, opcode, opcodeNum = legacyPrefixes0xF3, 0x0fb8, 2 + default: + panic(fmt.Sprintf("Unsupported unaryRmROpcode: %s", op)) + } + + dst := regEncodings[i.op2.reg().RealReg()] + + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, prefix, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + m := i.op1.addressMode() + encodeRegMem(c, prefix, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case not: + var prefix legacyPrefixes + src := regEncodings[i.op1.reg().RealReg()] + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + subopcode := uint8(2) + encodeEncEnc(c, prefix, 0xf7, 1, subopcode, uint8(src), rex) + + case neg: + var prefix legacyPrefixes + src := regEncodings[i.op1.reg().RealReg()] + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + subopcode := uint8(3) + encodeEncEnc(c, prefix, 0xf7, 1, subopcode, uint8(src), rex) + + case div: + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + var subopcode uint8 + if i.u1 != 0 { // Signed. + subopcode = 7 + } else { + subopcode = 6 + } + + divisor := i.op1 + if divisor.kind == operandKindReg { + src := regEncodings[divisor.reg().RealReg()] + encodeEncEnc(c, legacyPrefixesNone, 0xf7, 1, subopcode, uint8(src), rex) + } else if divisor.kind == operandKindMem { + m := divisor.addressMode() + encodeEncMem(c, legacyPrefixesNone, 0xf7, 1, subopcode, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case mulHi: + var prefix legacyPrefixes + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + + signed := i.u1 != 0 + var subopcode uint8 + if signed { + subopcode = 5 + } else { + subopcode = 4 + } + + // src1 is implicitly rax, + // dst_lo is implicitly rax, + // dst_hi is implicitly rdx. + src2 := i.op1 + if src2.kind == operandKindReg { + src := regEncodings[src2.reg().RealReg()] + encodeEncEnc(c, prefix, 0xf7, 1, subopcode, uint8(src), rex) + } else if src2.kind == operandKindMem { + m := src2.addressMode() + encodeEncMem(c, prefix, 0xf7, 1, subopcode, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + case signExtendData: + if i.b1 { // 64 bit. + c.EmitByte(0x48) + c.EmitByte(0x99) + } else { + c.EmitByte(0x99) + } + case movzxRmR, movsxRmR: + signed := i.kind == movsxRmR + + ext := extMode(i.u1) + var opcode uint32 + var opcodeNum uint32 + var rex rexInfo + switch ext { + case extModeBL: + if signed { + opcode, opcodeNum, rex = 0x0fbe, 2, rex.clearW() + } else { + opcode, opcodeNum, rex = 0x0fb6, 2, rex.clearW() + } + case extModeBQ: + if signed { + opcode, opcodeNum, rex = 0x0fbe, 2, rex.setW() + } else { + opcode, opcodeNum, rex = 0x0fb6, 2, rex.setW() + } + case extModeWL: + if signed { + opcode, opcodeNum, rex = 0x0fbf, 2, rex.clearW() + } else { + opcode, opcodeNum, rex = 0x0fb7, 2, rex.clearW() + } + case extModeWQ: + if signed { + opcode, opcodeNum, rex = 0x0fbf, 2, rex.setW() + } else { + opcode, opcodeNum, rex = 0x0fb7, 2, rex.setW() + } + case extModeLQ: + if signed { + opcode, opcodeNum, rex = 0x63, 1, rex.setW() + } else { + opcode, opcodeNum, rex = 0x8b, 1, rex.clearW() + } + default: + panic("BUG: invalid extMode") + } + + op := i.op1 + dst := regEncodings[i.op2.reg().RealReg()] + switch op.kind { + case operandKindReg: + src := regEncodings[op.reg().RealReg()] + if ext == extModeBL || ext == extModeBQ { + // Some destinations must be encoded with REX.R = 1. + if e := src.encoding(); e >= 4 && e <= 7 { + rex = rex.always() + } + } + encodeRegReg(c, legacyPrefixesNone, opcode, opcodeNum, dst, src, rex) + case operandKindMem: + m := op.addressMode() + encodeRegMem(c, legacyPrefixesNone, opcode, opcodeNum, dst, m, rex) + default: + panic("BUG: invalid operand kind") + } + + case mov64MR: + m := i.op1.addressMode() + encodeLoad64(c, m, i.op2.reg().RealReg()) + + case lea: + needsLabelResolution = true + dst := regEncodings[i.op2.reg().RealReg()] + rex := rexInfo(0).setW() + const opcode, opcodeNum = 0x8d, 1 + switch i.op1.kind { + case operandKindMem: + a := i.op1.addressMode() + encodeRegMem(c, legacyPrefixesNone, opcode, opcodeNum, dst, a, rex) + case operandKindLabel: + rex.encode(c, regRexBit(byte(dst)), 0) + c.EmitByte(byte((opcode) & 0xff)) + + // Indicate "LEAQ [RIP + 32bit displacement]. + // https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing + c.EmitByte(encodeModRM(0b00, dst.encoding(), 0b101)) + + // This will be resolved later, so we just emit a placeholder (0xffffffff for testing). + c.Emit4Bytes(0xffffffff) + default: + panic("BUG: invalid operand kind") + } + + case movRM: + m := i.op2.addressMode() + src := regEncodings[i.op1.reg().RealReg()] + + var rex rexInfo + switch i.u1 { + case 1: + if e := src.encoding(); e >= 4 && e <= 7 { + rex = rex.always() + } + encodeRegMem(c, legacyPrefixesNone, 0x88, 1, src, m, rex.clearW()) + case 2: + encodeRegMem(c, legacyPrefixes0x66, 0x89, 1, src, m, rex.clearW()) + case 4: + encodeRegMem(c, legacyPrefixesNone, 0x89, 1, src, m, rex.clearW()) + case 8: + encodeRegMem(c, legacyPrefixesNone, 0x89, 1, src, m, rex.setW()) + default: + panic(fmt.Sprintf("BUG: invalid size %d: %s", i.u1, i.String())) + } + + case shiftR: + src := regEncodings[i.op2.reg().RealReg()] + amount := i.op1 + + var opcode uint32 + var prefix legacyPrefixes + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + + switch amount.kind { + case operandKindReg: + if amount.reg() != rcxVReg { + panic("BUG: invalid reg operand: must be rcx") + } + opcode, prefix = 0xd3, legacyPrefixesNone + encodeEncEnc(c, prefix, opcode, 1, uint8(i.u1), uint8(src), rex) + case operandKindImm32: + opcode, prefix = 0xc1, legacyPrefixesNone + encodeEncEnc(c, prefix, opcode, 1, uint8(i.u1), uint8(src), rex) + c.EmitByte(byte(amount.imm32())) + default: + panic("BUG: invalid operand kind") + } + case xmmRmiReg: + const legPrefix = legacyPrefixes0x66 + rex := rexInfo(0).clearW() + dst := regEncodings[i.op2.reg().RealReg()] + + var opcode uint32 + var regDigit uint8 + + op := sseOpcode(i.u1) + op1 := i.op1 + if i.op1.kind == operandKindImm32 { + switch op { + case sseOpcodePsllw: + opcode, regDigit = 0x0f71, 6 + case sseOpcodePslld: + opcode, regDigit = 0x0f72, 6 + case sseOpcodePsllq: + opcode, regDigit = 0x0f73, 6 + case sseOpcodePsraw: + opcode, regDigit = 0x0f71, 4 + case sseOpcodePsrad: + opcode, regDigit = 0x0f72, 4 + case sseOpcodePsrlw: + opcode, regDigit = 0x0f71, 2 + case sseOpcodePsrld: + opcode, regDigit = 0x0f72, 2 + case sseOpcodePsrlq: + opcode, regDigit = 0x0f73, 2 + default: + panic("invalid opcode") + } + + encodeEncEnc(c, legPrefix, opcode, 2, regDigit, uint8(dst), rex) + imm32 := op1.imm32() + if imm32 > 0xff&imm32 { + panic("immediate value does not fit 1 byte") + } + c.EmitByte(uint8(imm32)) + } else { + switch op { + case sseOpcodePsllw: + opcode = 0x0ff1 + case sseOpcodePslld: + opcode = 0x0ff2 + case sseOpcodePsllq: + opcode = 0x0ff3 + case sseOpcodePsraw: + opcode = 0x0fe1 + case sseOpcodePsrad: + opcode = 0x0fe2 + case sseOpcodePsrlw: + opcode = 0x0fd1 + case sseOpcodePsrld: + opcode = 0x0fd2 + case sseOpcodePsrlq: + opcode = 0x0fd3 + default: + panic("invalid opcode") + } + + if op1.kind == operandKindReg { + reg := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, legPrefix, opcode, 2, dst, reg, rex) + } else if op1.kind == operandKindMem { + m := op1.addressMode() + encodeRegMem(c, legPrefix, opcode, 2, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + } + + case cmpRmiR: + var opcode uint32 + isCmp := i.u1 != 0 + rex := rexInfo(0) + _64 := i.b1 + if _64 { // 64 bit. + rex = rex.setW() + } else { + rex = rex.clearW() + } + dst := regEncodings[i.op2.reg().RealReg()] + op1 := i.op1 + switch op1.kind { + case operandKindReg: + reg := regEncodings[op1.reg().RealReg()] + if isCmp { + opcode = 0x39 + } else { + opcode = 0x85 + } + // Here we swap the encoding of the operands for CMP to be consistent with the output of LLVM/GCC. + encodeRegReg(c, legacyPrefixesNone, opcode, 1, reg, dst, rex) + + case operandKindMem: + if isCmp { + opcode = 0x3b + } else { + opcode = 0x85 + } + m := op1.addressMode() + encodeRegMem(c, legacyPrefixesNone, opcode, 1, dst, m, rex) + + case operandKindImm32: + imm32 := op1.imm32() + useImm8 := isCmp && lower8willSignExtendTo32(imm32) + var subopcode uint8 + + switch { + case isCmp && useImm8: + opcode, subopcode = 0x83, 7 + case isCmp && !useImm8: + opcode, subopcode = 0x81, 7 + default: + opcode, subopcode = 0xf7, 0 + } + encodeEncEnc(c, legacyPrefixesNone, opcode, 1, subopcode, uint8(dst), rex) + if useImm8 { + c.EmitByte(uint8(imm32)) + } else { + c.Emit4Bytes(imm32) + } + + default: + panic("BUG: invalid operand kind") + } + case setcc: + cc := cond(i.u1) + dst := regEncodings[i.op2.reg().RealReg()] + rex := rexInfo(0).clearW().always() + opcode := uint32(0x0f90) + uint32(cc) + encodeEncEnc(c, legacyPrefixesNone, opcode, 2, 0, uint8(dst), rex) + case cmove: + cc := cond(i.u1) + dst := regEncodings[i.op2.reg().RealReg()] + rex := rexInfo(0) + if i.b1 { // 64 bit. + rex = rex.setW() + } else { + rex = rex.clearW() + } + opcode := uint32(0x0f40) + uint32(cc) + src := i.op1 + switch src.kind { + case operandKindReg: + srcReg := regEncodings[src.reg().RealReg()] + encodeRegReg(c, legacyPrefixesNone, opcode, 2, dst, srcReg, rex) + case operandKindMem: + m := src.addressMode() + encodeRegMem(c, legacyPrefixesNone, opcode, 2, dst, m, rex) + default: + panic("BUG: invalid operand kind") + } + case push64: + op := i.op1 + + switch op.kind { + case operandKindReg: + dst := regEncodings[op.reg().RealReg()] + if dst.rexBit() > 0 { + c.EmitByte(rexEncodingDefault | 0x1) + } + c.EmitByte(0x50 | dst.encoding()) + case operandKindMem: + m := op.addressMode() + encodeRegMem( + c, legacyPrefixesNone, 0xff, 1, regEnc(6), m, rexInfo(0).clearW(), + ) + case operandKindImm32: + c.EmitByte(0x68) + c.Emit4Bytes(op.imm32()) + default: + panic("BUG: invalid operand kind") + } + + case pop64: + dst := regEncodings[i.op1.reg().RealReg()] + if dst.rexBit() > 0 { + c.EmitByte(rexEncodingDefault | 0x1) + } + c.EmitByte(0x58 | dst.encoding()) + + case xmmMovRM: + var legPrefix legacyPrefixes + var opcode uint32 + const opcodeNum = 2 + switch sseOpcode(i.u1) { + case sseOpcodeMovaps: + legPrefix, opcode = legacyPrefixesNone, 0x0f29 + case sseOpcodeMovapd: + legPrefix, opcode = legacyPrefixes0x66, 0x0f29 + case sseOpcodeMovdqa: + legPrefix, opcode = legacyPrefixes0x66, 0x0f7f + case sseOpcodeMovdqu: + legPrefix, opcode = legacyPrefixes0xF3, 0x0f7f + case sseOpcodeMovss: + legPrefix, opcode = legacyPrefixes0xF3, 0x0f11 + case sseOpcodeMovsd: + legPrefix, opcode = legacyPrefixes0xF2, 0x0f11 + case sseOpcodeMovups: + legPrefix, opcode = legacyPrefixesNone, 0x0f11 + case sseOpcodeMovupd: + legPrefix, opcode = legacyPrefixes0x66, 0x0f11 + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", sseOpcode(i.u1))) + } + + dst := regEncodings[i.op1.reg().RealReg()] + encodeRegMem(c, legPrefix, opcode, opcodeNum, dst, i.op2.addressMode(), rexInfo(0).clearW()) + case xmmLoadConst: + panic("TODO") + case xmmToGpr: + var legPrefix legacyPrefixes + var opcode uint32 + var argSwap bool + const opcodeNum = 2 + switch sseOpcode(i.u1) { + case sseOpcodeMovd, sseOpcodeMovq: + legPrefix, opcode, argSwap = legacyPrefixes0x66, 0x0f7e, false + case sseOpcodeMovmskps: + legPrefix, opcode, argSwap = legacyPrefixesNone, 0x0f50, true + case sseOpcodeMovmskpd: + legPrefix, opcode, argSwap = legacyPrefixes0x66, 0x0f50, true + case sseOpcodePmovmskb: + legPrefix, opcode, argSwap = legacyPrefixes0x66, 0x0fd7, true + case sseOpcodeCvttss2si: + legPrefix, opcode, argSwap = legacyPrefixes0xF3, 0x0f2c, true + case sseOpcodeCvttsd2si: + legPrefix, opcode, argSwap = legacyPrefixes0xF2, 0x0f2c, true + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", sseOpcode(i.u1))) + } + + var rex rexInfo + if i.b1 { + rex = rex.setW() + } else { + rex = rex.clearW() + } + src := regEncodings[i.op1.reg().RealReg()] + dst := regEncodings[i.op2.reg().RealReg()] + if argSwap { + src, dst = dst, src + } + encodeRegReg(c, legPrefix, opcode, opcodeNum, src, dst, rex) + + case cvtUint64ToFloatSeq: + panic("TODO") + case cvtFloatToSintSeq: + panic("TODO") + case cvtFloatToUintSeq: + panic("TODO") + case xmmMinMaxSeq: + panic("TODO") + case xmmCmpRmR: + var prefix legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + rex := rexInfo(0) + _64 := i.b1 + if _64 { // 64 bit. + rex = rex.setW() + } else { + rex = rex.clearW() + } + + op := sseOpcode(i.u1) + switch op { + case sseOpcodePtest: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f3817, 3 + case sseOpcodeUcomisd: + prefix, opcode, opcodeNum = legacyPrefixes0x66, 0x0f2e, 2 + case sseOpcodeUcomiss: + prefix, opcode, opcodeNum = legacyPrefixesNone, 0x0f2e, 2 + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", op)) + } + + dst := regEncodings[i.op2.reg().RealReg()] + op1 := i.op1 + switch op1.kind { + case operandKindReg: + reg := regEncodings[op1.reg().RealReg()] + encodeRegReg(c, prefix, opcode, opcodeNum, dst, reg, rex) + + case operandKindMem: + m := op1.addressMode() + encodeRegMem(c, prefix, opcode, opcodeNum, dst, m, rex) + + default: + panic("BUG: invalid operand kind") + } + case xmmRmRImm: + op := sseOpcode(i.u1) + var legPrex legacyPrefixes + var opcode uint32 + var opcodeNum uint32 + var swap bool + switch op { + case sseOpcodeCmpps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0FC2, 2 + case sseOpcodeCmppd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FC2, 2 + case sseOpcodeCmpss: + legPrex, opcode, opcodeNum = legacyPrefixes0xF3, 0x0FC2, 2 + case sseOpcodeCmpsd: + legPrex, opcode, opcodeNum = legacyPrefixes0xF2, 0x0FC2, 2 + case sseOpcodeInsertps: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A21, 3 + case sseOpcodePalignr: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A0F, 3 + case sseOpcodePinsrb: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A20, 3 + case sseOpcodePinsrw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FC4, 2 + case sseOpcodePinsrd, sseOpcodePinsrq: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A22, 3 + case sseOpcodePextrb: + swap = true + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A14, 3 + case sseOpcodePextrw: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0FC5, 2 + case sseOpcodePextrd, sseOpcodePextrq: + swap = true + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A16, 3 + case sseOpcodePshufd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F70, 2 + case sseOpcodeRoundps: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A08, 3 + case sseOpcodeRoundpd: + legPrex, opcode, opcodeNum = legacyPrefixes0x66, 0x0F3A09, 3 + case sseOpcodeShufps: + legPrex, opcode, opcodeNum = legacyPrefixesNone, 0x0FC6, 2 + default: + panic(fmt.Sprintf("Unsupported sseOpcode: %s", op)) + } + + dst := regEncodings[i.op2.reg().RealReg()] + + var rex rexInfo + if op == sseOpcodePextrq || op == sseOpcodePinsrq { + rex = rexInfo(0).setW() + } else { + rex = rexInfo(0).clearW() + } + op1 := i.op1 + if op1.kind == operandKindReg { + src := regEncodings[op1.reg().RealReg()] + if swap { + src, dst = dst, src + } + encodeRegReg(c, legPrex, opcode, opcodeNum, dst, src, rex) + } else if i.op1.kind == operandKindMem { + if swap { + panic("BUG: this is not possible to encode") + } + m := i.op1.addressMode() + encodeRegMem(c, legPrex, opcode, opcodeNum, dst, m, rex) + } else { + panic("BUG: invalid operand kind") + } + + c.EmitByte(byte(i.u2)) + + case jmp: + const ( + regMemOpcode = 0xff + regMemOpcodeNum = 1 + regMemSubOpcode = 4 + ) + op := i.op1 + switch op.kind { + case operandKindLabel: + needsLabelResolution = true + fallthrough + case operandKindImm32: + c.EmitByte(0xe9) + c.Emit4Bytes(op.imm32()) + case operandKindMem: + m := op.addressMode() + encodeRegMem(c, + legacyPrefixesNone, + regMemOpcode, regMemOpcodeNum, + regMemSubOpcode, m, rexInfo(0).clearW(), + ) + case operandKindReg: + r := op.reg().RealReg() + encodeRegReg( + c, + legacyPrefixesNone, + regMemOpcode, regMemOpcodeNum, + regMemSubOpcode, + regEncodings[r], rexInfo(0).clearW(), + ) + default: + panic("BUG: invalid operand kind") + } + + case jmpIf: + op := i.op1 + switch op.kind { + case operandKindLabel: + needsLabelResolution = true + fallthrough + case operandKindImm32: + c.EmitByte(0x0f) + c.EmitByte(0x80 | cond(i.u1).encoding()) + c.Emit4Bytes(op.imm32()) + default: + panic("BUG: invalid operand kind") + } + + case jmpTableIsland: + needsLabelResolution = true + for tc := uint64(0); tc < i.u2; tc++ { + c.Emit8Bytes(0) + } + + case exitSequence: + execCtx := i.op1.reg() + allocatedAmode := i.op2.addressMode() + + // Restore the RBP, RSP, and return to the Go code: + *allocatedAmode = amode{ + kindWithShift: uint32(amodeImmReg), base: execCtx, + imm32: wazevoapi.ExecutionContextOffsetOriginalFramePointer.U32(), + } + encodeLoad64(c, allocatedAmode, rbp) + allocatedAmode.imm32 = wazevoapi.ExecutionContextOffsetOriginalStackPointer.U32() + encodeLoad64(c, allocatedAmode, rsp) + encodeRet(c) + + case ud2: + c.EmitByte(0x0f) + c.EmitByte(0x0b) + + case call: + c.EmitByte(0xe8) + // Meaning that the call target is a function value, and requires relocation. + c.AddRelocationInfo(ssa.FuncRef(i.u1)) + // Note that this is zero as a placeholder for the call target if it's a function value. + c.Emit4Bytes(uint32(i.u2)) + + case callIndirect: + op := i.op1 + + const opcodeNum = 1 + const opcode = 0xff + rex := rexInfo(0).clearW() + switch op.kind { + case operandKindReg: + dst := regEncodings[op.reg().RealReg()] + encodeRegReg(c, + legacyPrefixesNone, + opcode, opcodeNum, + regEnc(2), + dst, + rex, + ) + case operandKindMem: + m := op.addressMode() + encodeRegMem(c, + legacyPrefixesNone, + opcode, opcodeNum, + regEnc(2), + m, + rex, + ) + default: + panic("BUG: invalid operand kind") + } + + case xchg: + src, dst := regEncodings[i.op1.reg().RealReg()], i.op2 + size := i.u1 + + var rex rexInfo + var opcode uint32 + lp := legacyPrefixesNone + switch size { + case 8: + opcode = 0x87 + rex = rexInfo(0).setW() + case 4: + opcode = 0x87 + rex = rexInfo(0).clearW() + case 2: + lp = legacyPrefixes0x66 + opcode = 0x87 + rex = rexInfo(0).clearW() + case 1: + opcode = 0x86 + if i.op2.kind == operandKindReg { + panic("TODO?: xchg on two 1-byte registers") + } + // Some destinations must be encoded with REX.R = 1. + if e := src.encoding(); e >= 4 && e <= 7 { + rex = rexInfo(0).always() + } + default: + panic(fmt.Sprintf("BUG: invalid size %d: %s", size, i.String())) + } + + switch dst.kind { + case operandKindMem: + m := dst.addressMode() + encodeRegMem(c, lp, opcode, 1, src, m, rex) + case operandKindReg: + r := dst.reg().RealReg() + encodeRegReg(c, lp, opcode, 1, src, regEncodings[r], rex) + default: + panic("BUG: invalid operand kind") + } + + case lockcmpxchg: + src, dst := regEncodings[i.op1.reg().RealReg()], i.op2 + size := i.u1 + + var rex rexInfo + var opcode uint32 + lp := legacyPrefixes0xF0 // Lock prefix. + switch size { + case 8: + opcode = 0x0FB1 + rex = rexInfo(0).setW() + case 4: + opcode = 0x0FB1 + rex = rexInfo(0).clearW() + case 2: + lp = legacyPrefixes0x660xF0 // Legacy prefix + Lock prefix. + opcode = 0x0FB1 + rex = rexInfo(0).clearW() + case 1: + opcode = 0x0FB0 + // Some destinations must be encoded with REX.R = 1. + if e := src.encoding(); e >= 4 && e <= 7 { + rex = rexInfo(0).always() + } + default: + panic(fmt.Sprintf("BUG: invalid size %d: %s", size, i.String())) + } + + switch dst.kind { + case operandKindMem: + m := dst.addressMode() + encodeRegMem(c, lp, opcode, 2, src, m, rex) + default: + panic("BUG: invalid operand kind") + } + + case lockxadd: + src, dst := regEncodings[i.op1.reg().RealReg()], i.op2 + size := i.u1 + + var rex rexInfo + var opcode uint32 + lp := legacyPrefixes0xF0 // Lock prefix. + switch size { + case 8: + opcode = 0x0FC1 + rex = rexInfo(0).setW() + case 4: + opcode = 0x0FC1 + rex = rexInfo(0).clearW() + case 2: + lp = legacyPrefixes0x660xF0 // Legacy prefix + Lock prefix. + opcode = 0x0FC1 + rex = rexInfo(0).clearW() + case 1: + opcode = 0x0FC0 + // Some destinations must be encoded with REX.R = 1. + if e := src.encoding(); e >= 4 && e <= 7 { + rex = rexInfo(0).always() + } + default: + panic(fmt.Sprintf("BUG: invalid size %d: %s", size, i.String())) + } + + switch dst.kind { + case operandKindMem: + m := dst.addressMode() + encodeRegMem(c, lp, opcode, 2, src, m, rex) + default: + panic("BUG: invalid operand kind") + } + + case zeros: + r := i.op2.reg() + if r.RegType() == regalloc.RegTypeInt { + i.asAluRmiR(aluRmiROpcodeXor, newOperandReg(r), r, true) + } else { + i.asXmmRmR(sseOpcodePxor, newOperandReg(r), r) + } + i.encode(c) + + case mfence: + // https://www.felixcloutier.com/x86/mfence + c.EmitByte(0x0f) + c.EmitByte(0xae) + c.EmitByte(0xf0) + + default: + panic(fmt.Sprintf("TODO: %v", i.kind)) + } + return +} + +func encodeLoad64(c backend.Compiler, m *amode, rd regalloc.RealReg) { + dst := regEncodings[rd] + encodeRegMem(c, legacyPrefixesNone, 0x8b, 1, dst, m, rexInfo(0).setW()) +} + +func encodeRet(c backend.Compiler) { + c.EmitByte(0xc3) +} + +func encodeEncEnc( + c backend.Compiler, + legPrefixes legacyPrefixes, + opcodes uint32, + opcodeNum uint32, + r uint8, + rm uint8, + rex rexInfo, +) { + legPrefixes.encode(c) + rex.encode(c, r>>3, rm>>3) + + for opcodeNum > 0 { + opcodeNum-- + c.EmitByte(byte((opcodes >> (opcodeNum << 3)) & 0xff)) + } + c.EmitByte(encodeModRM(3, r&7, rm&7)) +} + +func encodeRegReg( + c backend.Compiler, + legPrefixes legacyPrefixes, + opcodes uint32, + opcodeNum uint32, + r regEnc, + rm regEnc, + rex rexInfo, +) { + encodeEncEnc(c, legPrefixes, opcodes, opcodeNum, uint8(r), uint8(rm), rex) +} + +func encodeModRM(mod byte, reg byte, rm byte) byte { + return mod<<6 | reg<<3 | rm +} + +func encodeSIB(shift byte, encIndex byte, encBase byte) byte { + return shift<<6 | encIndex<<3 | encBase +} + +func encodeRegMem( + c backend.Compiler, legPrefixes legacyPrefixes, opcodes uint32, opcodeNum uint32, r regEnc, m *amode, rex rexInfo, +) (needsLabelResolution bool) { + needsLabelResolution = encodeEncMem(c, legPrefixes, opcodes, opcodeNum, uint8(r), m, rex) + return +} + +func encodeEncMem( + c backend.Compiler, legPrefixes legacyPrefixes, opcodes uint32, opcodeNum uint32, r uint8, m *amode, rex rexInfo, +) (needsLabelResolution bool) { + legPrefixes.encode(c) + + const ( + modNoDisplacement = 0b00 + modShortDisplacement = 0b01 + modLongDisplacement = 0b10 + + useSBI = 4 // the encoding of rsp or r12 register. + ) + + switch m.kind() { + case amodeImmReg, amodeImmRBP: + base := m.base.RealReg() + baseEnc := regEncodings[base] + + rex.encode(c, regRexBit(r), baseEnc.rexBit()) + + for opcodeNum > 0 { + opcodeNum-- + c.EmitByte(byte((opcodes >> (opcodeNum << 3)) & 0xff)) + } + + // SIB byte is the last byte of the memory encoding before the displacement + const sibByte = 0x24 // == encodeSIB(0, 4, 4) + + immZero, baseRbp, baseR13 := m.imm32 == 0, base == rbp, base == r13 + short := lower8willSignExtendTo32(m.imm32) + rspOrR12 := base == rsp || base == r12 + + if immZero && !baseRbp && !baseR13 { // rbp or r13 can't be used as base for without displacement encoding. + c.EmitByte(encodeModRM(modNoDisplacement, regEncoding(r), baseEnc.encoding())) + if rspOrR12 { + c.EmitByte(sibByte) + } + } else if short { // Note: this includes the case where m.imm32 == 0 && base == rbp || base == r13. + c.EmitByte(encodeModRM(modShortDisplacement, regEncoding(r), baseEnc.encoding())) + if rspOrR12 { + c.EmitByte(sibByte) + } + c.EmitByte(byte(m.imm32)) + } else { + c.EmitByte(encodeModRM(modLongDisplacement, regEncoding(r), baseEnc.encoding())) + if rspOrR12 { + c.EmitByte(sibByte) + } + c.Emit4Bytes(m.imm32) + } + + case amodeRegRegShift: + base := m.base.RealReg() + baseEnc := regEncodings[base] + index := m.index.RealReg() + indexEnc := regEncodings[index] + + if index == rsp { + panic("BUG: rsp can't be used as index of addressing mode") + } + + rex.encodeForIndex(c, regEnc(r), indexEnc, baseEnc) + + for opcodeNum > 0 { + opcodeNum-- + c.EmitByte(byte((opcodes >> (opcodeNum << 3)) & 0xff)) + } + + immZero, baseRbp, baseR13 := m.imm32 == 0, base == rbp, base == r13 + if immZero && !baseRbp && !baseR13 { // rbp or r13 can't be used as base for without displacement encoding. (curious why? because it's interpreted as RIP relative addressing). + c.EmitByte(encodeModRM(modNoDisplacement, regEncoding(r), useSBI)) + c.EmitByte(encodeSIB(m.shift(), indexEnc.encoding(), baseEnc.encoding())) + } else if lower8willSignExtendTo32(m.imm32) { + c.EmitByte(encodeModRM(modShortDisplacement, regEncoding(r), useSBI)) + c.EmitByte(encodeSIB(m.shift(), indexEnc.encoding(), baseEnc.encoding())) + c.EmitByte(byte(m.imm32)) + } else { + c.EmitByte(encodeModRM(modLongDisplacement, regEncoding(r), useSBI)) + c.EmitByte(encodeSIB(m.shift(), indexEnc.encoding(), baseEnc.encoding())) + c.Emit4Bytes(m.imm32) + } + + case amodeRipRel: + rex.encode(c, regRexBit(r), 0) + for opcodeNum > 0 { + opcodeNum-- + c.EmitByte(byte((opcodes >> (opcodeNum << 3)) & 0xff)) + } + + // Indicate "LEAQ [RIP + 32bit displacement]. + // https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing + c.EmitByte(encodeModRM(0b00, regEncoding(r), 0b101)) + + // This will be resolved later, so we just emit a placeholder. + needsLabelResolution = true + c.Emit4Bytes(0) + + default: + panic("BUG: invalid addressing mode") + } + return +} + +const ( + rexEncodingDefault byte = 0x40 + rexEncodingW = rexEncodingDefault | 0x08 +) + +// rexInfo is a bit set to indicate: +// +// 0x01: W bit must be cleared. +// 0x02: REX prefix must be emitted. +type rexInfo byte + +func (ri rexInfo) setW() rexInfo { + return ri | 0x01 +} + +func (ri rexInfo) clearW() rexInfo { + return ri & 0x02 +} + +func (ri rexInfo) always() rexInfo { + return ri | 0x02 +} + +func (ri rexInfo) notAlways() rexInfo { //nolint + return ri & 0x01 +} + +func (ri rexInfo) encode(c backend.Compiler, r uint8, b uint8) { + var w byte = 0 + if ri&0x01 != 0 { + w = 0x01 + } + rex := rexEncodingDefault | w<<3 | r<<2 | b + if rex != rexEncodingDefault || ri&0x02 != 0 { + c.EmitByte(rex) + } +} + +func (ri rexInfo) encodeForIndex(c backend.Compiler, encR regEnc, encIndex regEnc, encBase regEnc) { + var w byte = 0 + if ri&0x01 != 0 { + w = 0x01 + } + r := encR.rexBit() + x := encIndex.rexBit() + b := encBase.rexBit() + rex := byte(0x40) | w<<3 | r<<2 | x<<1 | b + if rex != 0x40 || ri&0x02 != 0 { + c.EmitByte(rex) + } +} + +type regEnc byte + +func (r regEnc) rexBit() byte { + return regRexBit(byte(r)) +} + +func (r regEnc) encoding() byte { + return regEncoding(byte(r)) +} + +func regRexBit(r byte) byte { + return r >> 3 +} + +func regEncoding(r byte) byte { + return r & 0x07 +} + +var regEncodings = [...]regEnc{ + rax: 0b000, + rcx: 0b001, + rdx: 0b010, + rbx: 0b011, + rsp: 0b100, + rbp: 0b101, + rsi: 0b110, + rdi: 0b111, + r8: 0b1000, + r9: 0b1001, + r10: 0b1010, + r11: 0b1011, + r12: 0b1100, + r13: 0b1101, + r14: 0b1110, + r15: 0b1111, + xmm0: 0b000, + xmm1: 0b001, + xmm2: 0b010, + xmm3: 0b011, + xmm4: 0b100, + xmm5: 0b101, + xmm6: 0b110, + xmm7: 0b111, + xmm8: 0b1000, + xmm9: 0b1001, + xmm10: 0b1010, + xmm11: 0b1011, + xmm12: 0b1100, + xmm13: 0b1101, + xmm14: 0b1110, + xmm15: 0b1111, +} + +type legacyPrefixes byte + +const ( + legacyPrefixesNone legacyPrefixes = iota + legacyPrefixes0x66 + legacyPrefixes0xF0 + legacyPrefixes0x660xF0 + legacyPrefixes0xF2 + legacyPrefixes0xF3 +) + +func (p legacyPrefixes) encode(c backend.Compiler) { + switch p { + case legacyPrefixesNone: + case legacyPrefixes0x66: + c.EmitByte(0x66) + case legacyPrefixes0xF0: + c.EmitByte(0xf0) + case legacyPrefixes0x660xF0: + c.EmitByte(0x66) + c.EmitByte(0xf0) + case legacyPrefixes0xF2: + c.EmitByte(0xf2) + case legacyPrefixes0xF3: + c.EmitByte(0xf3) + default: + panic("BUG: invalid legacy prefix") + } +} + +func lower32willSignExtendTo64(x uint64) bool { + xs := int64(x) + return xs == int64(uint64(int32(xs))) +} + +func lower8willSignExtendTo32(x uint32) bool { + xs := int32(x) + return xs == ((xs << 24) >> 24) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_constant.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_constant.go new file mode 100644 index 00000000..55d05ef6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_constant.go @@ -0,0 +1,71 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// lowerConstant allocates a new VReg and inserts the instruction to load the constant value. +func (m *machine) lowerConstant(instr *ssa.Instruction) (vr regalloc.VReg) { + val := instr.Return() + valType := val.Type() + + vr = m.c.AllocateVReg(valType) + m.insertLoadConstant(instr, vr) + return +} + +// InsertLoadConstantBlockArg implements backend.Machine. +func (m *machine) InsertLoadConstantBlockArg(instr *ssa.Instruction, vr regalloc.VReg) { + m.insertLoadConstant(instr, vr) +} + +func (m *machine) insertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg) { + val := instr.Return() + valType := val.Type() + v := instr.ConstantVal() + + bits := valType.Bits() + if bits < 64 { // Clear the redundant bits just in case it's unexpectedly sign-extended, etc. + v = v & ((1 << valType.Bits()) - 1) + } + + switch valType { + case ssa.TypeF32, ssa.TypeF64: + m.lowerFconst(vr, v, bits == 64) + case ssa.TypeI32, ssa.TypeI64: + m.lowerIconst(vr, v, bits == 64) + default: + panic("BUG") + } +} + +func (m *machine) lowerFconst(dst regalloc.VReg, c uint64, _64 bool) { + if c == 0 { + xor := m.allocateInstr().asZeros(dst) + m.insert(xor) + } else { + var tmpType ssa.Type + if _64 { + tmpType = ssa.TypeI64 + } else { + tmpType = ssa.TypeI32 + } + tmpInt := m.c.AllocateVReg(tmpType) + loadToGP := m.allocateInstr().asImm(tmpInt, c, _64) + m.insert(loadToGP) + + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpInt), dst, _64) + m.insert(movToXmm) + } +} + +func (m *machine) lowerIconst(dst regalloc.VReg, c uint64, _64 bool) { + i := m.allocateInstr() + if c == 0 { + i.asZeros(dst) + } else { + i.asImm(dst, c, _64) + } + m.insert(i) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_mem.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_mem.go new file mode 100644 index 00000000..befe8c64 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/lower_mem.go @@ -0,0 +1,187 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +var addendsMatchOpcodes = [...]ssa.Opcode{ssa.OpcodeUExtend, ssa.OpcodeSExtend, ssa.OpcodeIadd, ssa.OpcodeIconst, ssa.OpcodeIshl} + +type addend struct { + r regalloc.VReg + off int64 + shift byte +} + +func (a addend) String() string { + return fmt.Sprintf("addend{r=%s, off=%d, shift=%d}", a.r, a.off, a.shift) +} + +// lowerToAddressMode converts a pointer to an addressMode that can be used as an operand for load/store instructions. +func (m *machine) lowerToAddressMode(ptr ssa.Value, offsetBase uint32) (am *amode) { + def := m.c.ValueDefinition(ptr) + + if offsetBase&0x80000000 != 0 { + // Special casing the huge base offset whose MSB is set. In x64, the immediate is always + // sign-extended, but our IR semantics requires the offset base is always unsigned. + // Note that this should be extremely rare or even this shouldn't hit in the real application, + // therefore we don't need to optimize this case in my opinion. + + a := m.lowerAddend(def) + off64 := a.off + int64(offsetBase) + offsetBaseReg := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(offsetBaseReg, uint64(off64), true) + if a.r != regalloc.VRegInvalid { + return m.newAmodeRegRegShift(0, offsetBaseReg, a.r, a.shift) + } else { + return m.newAmodeImmReg(0, offsetBaseReg) + } + } + + if op := m.c.MatchInstrOneOf(def, addendsMatchOpcodes[:]); op == ssa.OpcodeIadd { + add := def.Instr + x, y := add.Arg2() + xDef, yDef := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + ax := m.lowerAddend(xDef) + ay := m.lowerAddend(yDef) + add.MarkLowered() + return m.lowerAddendsToAmode(ax, ay, offsetBase) + } else { + // If it is not an Iadd, then we lower the one addend. + a := m.lowerAddend(def) + // off is always 0 if r is valid. + if a.r != regalloc.VRegInvalid { + if a.shift != 0 { + tmpReg := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(tmpReg, 0, true) + return m.newAmodeRegRegShift(offsetBase, tmpReg, a.r, a.shift) + } + return m.newAmodeImmReg(offsetBase, a.r) + } else { + off64 := a.off + int64(offsetBase) + tmpReg := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(tmpReg, uint64(off64), true) + return m.newAmodeImmReg(0, tmpReg) + } + } +} + +func (m *machine) lowerAddendsToAmode(x, y addend, offBase uint32) *amode { + if x.r != regalloc.VRegInvalid && x.off != 0 || y.r != regalloc.VRegInvalid && y.off != 0 { + panic("invalid input") + } + + u64 := uint64(x.off+y.off) + uint64(offBase) + if u64 != 0 { + if _, ok := asImm32(u64, false); !ok { + tmpReg := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(tmpReg, u64, true) + // Blank u64 as it has been already lowered. + u64 = 0 + + if x.r == regalloc.VRegInvalid { + x.r = tmpReg + } else if y.r == regalloc.VRegInvalid { + y.r = tmpReg + } else { + // We already know that either rx or ry is invalid, + // so we overwrite it with the temporary register. + panic("BUG") + } + } + } + + u32 := uint32(u64) + switch { + // We assume rx, ry are valid iff offx, offy are 0. + case x.r != regalloc.VRegInvalid && y.r != regalloc.VRegInvalid: + switch { + case x.shift != 0 && y.shift != 0: + // Cannot absorb two shifted registers, must lower one to a shift instruction. + shifted := m.allocateInstr() + shifted.asShiftR(shiftROpShiftLeft, newOperandImm32(uint32(x.shift)), x.r, true) + m.insert(shifted) + + return m.newAmodeRegRegShift(u32, x.r, y.r, y.shift) + case x.shift != 0 && y.shift == 0: + // Swap base and index. + x, y = y, x + fallthrough + default: + return m.newAmodeRegRegShift(u32, x.r, y.r, y.shift) + } + case x.r == regalloc.VRegInvalid && y.r != regalloc.VRegInvalid: + x, y = y, x + fallthrough + case x.r != regalloc.VRegInvalid && y.r == regalloc.VRegInvalid: + if x.shift != 0 { + zero := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(zero, 0, true) + return m.newAmodeRegRegShift(u32, zero, x.r, x.shift) + } + return m.newAmodeImmReg(u32, x.r) + default: // Both are invalid: use the offset. + tmpReg := m.c.AllocateVReg(ssa.TypeI64) + m.lowerIconst(tmpReg, u64, true) + return m.newAmodeImmReg(0, tmpReg) + } +} + +func (m *machine) lowerAddend(x backend.SSAValueDefinition) addend { + if !x.IsFromInstr() { + return addend{m.c.VRegOf(x.V), 0, 0} + } + // Ensure the addend is not referenced in multiple places; we will discard nested Iadds. + op := m.c.MatchInstrOneOf(x, addendsMatchOpcodes[:]) + if op != ssa.OpcodeInvalid && op != ssa.OpcodeIadd { + return m.lowerAddendFromInstr(x.Instr) + } + p := m.getOperand_Reg(x) + return addend{p.reg(), 0, 0} +} + +// lowerAddendFromInstr takes an instruction returns a Vreg and an offset that can be used in an address mode. +// The Vreg is regalloc.VRegInvalid if the addend cannot be lowered to a register. +// The offset is 0 if the addend can be lowered to a register. +func (m *machine) lowerAddendFromInstr(instr *ssa.Instruction) addend { + instr.MarkLowered() + switch op := instr.Opcode(); op { + case ssa.OpcodeIconst: + u64 := instr.ConstantVal() + if instr.Return().Type().Bits() == 32 { + return addend{regalloc.VRegInvalid, int64(int32(u64)), 0} // sign-extend. + } else { + return addend{regalloc.VRegInvalid, int64(u64), 0} + } + case ssa.OpcodeUExtend, ssa.OpcodeSExtend: + input := instr.Arg() + inputDef := m.c.ValueDefinition(input) + if input.Type().Bits() != 32 { + panic("BUG: invalid input type " + input.Type().String()) + } + constInst := inputDef.IsFromInstr() && inputDef.Instr.Constant() + switch { + case constInst && op == ssa.OpcodeSExtend: + return addend{regalloc.VRegInvalid, int64(uint32(inputDef.Instr.ConstantVal())), 0} + case constInst && op == ssa.OpcodeUExtend: + return addend{regalloc.VRegInvalid, int64(int32(inputDef.Instr.ConstantVal())), 0} // sign-extend! + default: + r := m.getOperand_Reg(inputDef) + return addend{r.reg(), 0, 0} + } + case ssa.OpcodeIshl: + // If the addend is a shift, we can only handle it if the shift amount is a constant. + x, amount := instr.Arg2() + amountDef := m.c.ValueDefinition(amount) + if amountDef.IsFromInstr() && amountDef.Instr.Constant() && amountDef.Instr.ConstantVal() <= 3 { + r := m.getOperand_Reg(m.c.ValueDefinition(x)) + return addend{r.reg(), 0, uint8(amountDef.Instr.ConstantVal())} + } + r := m.getOperand_Reg(m.c.ValueDefinition(x)) + return addend{r.reg(), 0, 0} + } + panic("BUG: invalid opcode") +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine.go new file mode 100644 index 00000000..fd0d69ca --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine.go @@ -0,0 +1,3733 @@ +package amd64 + +import ( + "context" + "encoding/binary" + "fmt" + "math" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/platform" +) + +// NewBackend returns a new backend for arm64. +func NewBackend() backend.Machine { + m := &machine{ + cpuFeatures: platform.CpuFeatures, + regAlloc: regalloc.NewAllocator[*instruction, *labelPosition, *regAllocFn](regInfo), + spillSlots: map[regalloc.VRegID]int64{}, + amodePool: wazevoapi.NewPool[amode](nil), + labelPositionPool: wazevoapi.NewIDedPool[labelPosition](resetLabelPosition), + instrPool: wazevoapi.NewPool[instruction](resetInstruction), + constSwizzleMaskConstIndex: -1, + constSqmulRoundSatIndex: -1, + constI8x16SHLMaskTableIndex: -1, + constI8x16LogicalSHRMaskTableIndex: -1, + constF64x2CvtFromIMaskIndex: -1, + constTwop52Index: -1, + constI32sMaxOnF64x2Index: -1, + constI32uMaxOnF64x2Index: -1, + constAllOnesI8x16Index: -1, + constAllOnesI16x8Index: -1, + constExtAddPairwiseI16x8uMask1Index: -1, + constExtAddPairwiseI16x8uMask2Index: -1, + } + m.regAllocFn.m = m + return m +} + +type ( + // machine implements backend.Machine for amd64. + machine struct { + c backend.Compiler + stackBoundsCheckDisabled bool + + instrPool wazevoapi.Pool[instruction] + amodePool wazevoapi.Pool[amode] + + cpuFeatures platform.CpuFeatureFlags + + regAlloc regalloc.Allocator[*instruction, *labelPosition, *regAllocFn] + regAllocFn regAllocFn + regAllocStarted bool + + // labelPositionPool is the pool of labelPosition. The id is the label where + // if the label is less than the maxSSABlockID, it's the ssa.BasicBlockID. + labelPositionPool wazevoapi.IDedPool[labelPosition] + // nextLabel is the next label to be allocated. The first free label comes after maxSSABlockID + // so that we can have an identical label for the SSA block ID, which is useful for debugging. + nextLabel label + // rootInstr is the first instruction of the function. + rootInstr *instruction + // currentLabelPos is the currently-compiled ssa.BasicBlock's labelPosition. + currentLabelPos *labelPosition + // orderedSSABlockLabelPos is the ordered list of labelPosition in the generated code for each ssa.BasicBlock. + orderedSSABlockLabelPos []*labelPosition + // returnLabelPos is the labelPosition for the return block. + returnLabelPos labelPosition + // perBlockHead and perBlockEnd are the head and tail of the instruction list per currently-compiled ssa.BasicBlock. + perBlockHead, perBlockEnd *instruction + // pendingInstructions are the instructions which are not yet emitted into the instruction list. + pendingInstructions []*instruction + // maxSSABlockID is the maximum ssa.BasicBlockID in the current function. + maxSSABlockID label + + spillSlotSize int64 + spillSlots map[regalloc.VRegID]int64 + currentABI *backend.FunctionABI + clobberedRegs []regalloc.VReg + + maxRequiredStackSizeForCalls int64 + + labelResolutionPends []labelResolutionPend + + // jmpTableTargets holds the labels of the jump table targets. + jmpTableTargets [][]uint32 + // jmpTableTargetNext is the index to the jmpTableTargets slice to be used for the next jump table. + jmpTableTargetsNext int + consts []_const + + constSwizzleMaskConstIndex, constSqmulRoundSatIndex, + constI8x16SHLMaskTableIndex, constI8x16LogicalSHRMaskTableIndex, + constF64x2CvtFromIMaskIndex, constTwop52Index, + constI32sMaxOnF64x2Index, constI32uMaxOnF64x2Index, + constAllOnesI8x16Index, constAllOnesI16x8Index, + constExtAddPairwiseI16x8uMask1Index, constExtAddPairwiseI16x8uMask2Index int + } + + _const struct { + lo, hi uint64 + _var []byte + label label + labelPos *labelPosition + } + + labelResolutionPend struct { + instr *instruction + instrOffset int64 + // imm32Offset is the offset of the last 4 bytes of the instruction. + imm32Offset int64 + } +) + +type ( + // label represents a position in the generated code which is either + // a real instruction or the constant InstructionPool (e.g. jump tables). + // + // This is exactly the same as the traditional "label" in assembly code. + label uint32 + + // labelPosition represents the regions of the generated code which the label represents. + // This implements regalloc.Block. + labelPosition struct { + // sb is not nil if this corresponds to a ssa.BasicBlock. + sb ssa.BasicBlock + // cur is used to walk through the instructions in the block during the register allocation. + cur, + // begin and end are the first and last instructions of the block. + begin, end *instruction + // binaryOffset is the offset in the binary where the label is located. + binaryOffset int64 + } +) + +// String implements backend.Machine. +func (l label) String() string { + return fmt.Sprintf("L%d", l) +} + +func resetLabelPosition(l *labelPosition) { + *l = labelPosition{} +} + +const labelReturn = math.MaxUint32 + +func ssaBlockLabel(sb ssa.BasicBlock) label { + if sb.ReturnBlock() { + return labelReturn + } + return label(sb.ID()) +} + +// getOrAllocateSSABlockLabelPosition returns the labelPosition for the given basic block. +func (m *machine) getOrAllocateSSABlockLabelPosition(sb ssa.BasicBlock) *labelPosition { + if sb.ReturnBlock() { + m.returnLabelPos.sb = sb + return &m.returnLabelPos + } + + l := ssaBlockLabel(sb) + pos := m.labelPositionPool.GetOrAllocate(int(l)) + pos.sb = sb + return pos +} + +func (m *machine) getOrAllocateConstLabel(i *int, _var []byte) label { + index := *i + if index == -1 { + l, pos := m.allocateLabel() + index = len(m.consts) + m.consts = append(m.consts, _const{ + _var: _var, + label: l, + labelPos: pos, + }) + *i = index + } + return m.consts[index].label +} + +// Reset implements backend.Machine. +func (m *machine) Reset() { + m.consts = m.consts[:0] + m.clobberedRegs = m.clobberedRegs[:0] + for key := range m.spillSlots { + m.clobberedRegs = append(m.clobberedRegs, regalloc.VReg(key)) + } + for _, key := range m.clobberedRegs { + delete(m.spillSlots, regalloc.VRegID(key)) + } + + m.stackBoundsCheckDisabled = false + m.regAlloc.Reset() + m.labelPositionPool.Reset() + m.instrPool.Reset() + m.regAllocStarted = false + m.clobberedRegs = m.clobberedRegs[:0] + + m.spillSlotSize = 0 + m.maxRequiredStackSizeForCalls = 0 + m.perBlockHead, m.perBlockEnd, m.rootInstr = nil, nil, nil + m.pendingInstructions = m.pendingInstructions[:0] + m.orderedSSABlockLabelPos = m.orderedSSABlockLabelPos[:0] + + m.amodePool.Reset() + m.jmpTableTargetsNext = 0 + m.constSwizzleMaskConstIndex = -1 + m.constSqmulRoundSatIndex = -1 + m.constI8x16SHLMaskTableIndex = -1 + m.constI8x16LogicalSHRMaskTableIndex = -1 + m.constF64x2CvtFromIMaskIndex = -1 + m.constTwop52Index = -1 + m.constI32sMaxOnF64x2Index = -1 + m.constI32uMaxOnF64x2Index = -1 + m.constAllOnesI8x16Index = -1 + m.constAllOnesI16x8Index = -1 + m.constExtAddPairwiseI16x8uMask1Index = -1 + m.constExtAddPairwiseI16x8uMask2Index = -1 +} + +// StartLoweringFunction implements backend.Machine StartLoweringFunction. +func (m *machine) StartLoweringFunction(maxBlockID ssa.BasicBlockID) { + m.maxSSABlockID = label(maxBlockID) + m.nextLabel = label(maxBlockID) + 1 +} + +// LinkAdjacentBlocks implements backend.Machine. +func (m *machine) LinkAdjacentBlocks(prev, next ssa.BasicBlock) { + prevPos, nextPos := m.getOrAllocateSSABlockLabelPosition(prev), m.getOrAllocateSSABlockLabelPosition(next) + prevPos.end.next = nextPos.begin +} + +// StartBlock implements backend.Machine. +func (m *machine) StartBlock(blk ssa.BasicBlock) { + m.currentLabelPos = m.getOrAllocateSSABlockLabelPosition(blk) + labelPos := m.currentLabelPos + end := m.allocateNop() + m.perBlockHead, m.perBlockEnd = end, end + labelPos.begin, labelPos.end = end, end + m.orderedSSABlockLabelPos = append(m.orderedSSABlockLabelPos, labelPos) +} + +// EndBlock implements ExecutableContext. +func (m *machine) EndBlock() { + // Insert nop0 as the head of the block for convenience to simplify the logic of inserting instructions. + m.insertAtPerBlockHead(m.allocateNop()) + + m.currentLabelPos.begin = m.perBlockHead + + if m.currentLabelPos.sb.EntryBlock() { + m.rootInstr = m.perBlockHead + } +} + +func (m *machine) insertAtPerBlockHead(i *instruction) { + if m.perBlockHead == nil { + m.perBlockHead = i + m.perBlockEnd = i + return + } + + i.next = m.perBlockHead + m.perBlockHead.prev = i + m.perBlockHead = i +} + +// FlushPendingInstructions implements backend.Machine. +func (m *machine) FlushPendingInstructions() { + l := len(m.pendingInstructions) + if l == 0 { + return + } + for i := l - 1; i >= 0; i-- { // reverse because we lower instructions in reverse order. + m.insertAtPerBlockHead(m.pendingInstructions[i]) + } + m.pendingInstructions = m.pendingInstructions[:0] +} + +// DisableStackCheck implements backend.Machine. +func (m *machine) DisableStackCheck() { m.stackBoundsCheckDisabled = true } + +// SetCompiler implements backend.Machine. +func (m *machine) SetCompiler(c backend.Compiler) { + m.c = c + m.regAllocFn.ssaB = c.SSABuilder() +} + +// SetCurrentABI implements backend.Machine. +func (m *machine) SetCurrentABI(abi *backend.FunctionABI) { m.currentABI = abi } + +// RegAlloc implements backend.Machine. +func (m *machine) RegAlloc() { + rf := m.regAllocFn + m.regAllocStarted = true + m.regAlloc.DoAllocation(&rf) + // Now that we know the final spill slot size, we must align spillSlotSize to 16 bytes. + m.spillSlotSize = (m.spillSlotSize + 15) &^ 15 +} + +// InsertReturn implements backend.Machine. +func (m *machine) InsertReturn() { + i := m.allocateInstr().asRet() + m.insert(i) +} + +// LowerSingleBranch implements backend.Machine. +func (m *machine) LowerSingleBranch(b *ssa.Instruction) { + switch b.Opcode() { + case ssa.OpcodeJump: + _, _, targetBlkID := b.BranchData() + if b.IsFallthroughJump() { + return + } + jmp := m.allocateInstr() + target := ssaBlockLabel(m.c.SSABuilder().BasicBlock(targetBlkID)) + if target == labelReturn { + jmp.asRet() + } else { + jmp.asJmp(newOperandLabel(target)) + } + m.insert(jmp) + case ssa.OpcodeBrTable: + index, targetBlkIDs := b.BrTableData() + m.lowerBrTable(index, targetBlkIDs) + default: + panic("BUG: unexpected branch opcode" + b.Opcode().String()) + } +} + +func (m *machine) addJmpTableTarget(targets ssa.Values) (index int) { + if m.jmpTableTargetsNext == len(m.jmpTableTargets) { + m.jmpTableTargets = append(m.jmpTableTargets, make([]uint32, 0, len(targets.View()))) + } + + index = m.jmpTableTargetsNext + m.jmpTableTargetsNext++ + m.jmpTableTargets[index] = m.jmpTableTargets[index][:0] + for _, targetBlockID := range targets.View() { + target := m.c.SSABuilder().BasicBlock(ssa.BasicBlockID(targetBlockID)) + m.jmpTableTargets[index] = append(m.jmpTableTargets[index], uint32(ssaBlockLabel(target))) + } + return +} + +var condBranchMatches = [...]ssa.Opcode{ssa.OpcodeIcmp, ssa.OpcodeFcmp} + +func (m *machine) lowerBrTable(index ssa.Value, targets ssa.Values) { + _v := m.getOperand_Reg(m.c.ValueDefinition(index)) + v := m.copyToTmp(_v.reg()) + + targetCount := len(targets.View()) + + // First, we need to do the bounds check. + maxIndex := m.c.AllocateVReg(ssa.TypeI32) + m.lowerIconst(maxIndex, uint64(targetCount-1), false) + cmp := m.allocateInstr().asCmpRmiR(true, newOperandReg(maxIndex), v, false) + m.insert(cmp) + + // Then do the conditional move maxIndex to v if v > maxIndex. + cmov := m.allocateInstr().asCmove(condNB, newOperandReg(maxIndex), v, false) + m.insert(cmov) + + // Now that v has the correct index. Load the address of the jump table into the addr. + addr := m.c.AllocateVReg(ssa.TypeI64) + leaJmpTableAddr := m.allocateInstr() + m.insert(leaJmpTableAddr) + + // Then add the target's offset into jmpTableAddr. + loadTargetOffsetFromJmpTable := m.allocateInstr().asAluRmiR(aluRmiROpcodeAdd, + // Shift by 3 because each entry is 8 bytes. + newOperandMem(m.newAmodeRegRegShift(0, addr, v, 3)), addr, true) + m.insert(loadTargetOffsetFromJmpTable) + + // Now ready to jump. + jmp := m.allocateInstr().asJmp(newOperandReg(addr)) + m.insert(jmp) + + jmpTableBegin, jmpTableBeginLabel := m.allocateBrTarget() + m.insert(jmpTableBegin) + leaJmpTableAddr.asLEA(newOperandLabel(jmpTableBeginLabel), addr) + + jmpTable := m.allocateInstr() + targetSliceIndex := m.addJmpTableTarget(targets) + jmpTable.asJmpTableSequence(targetSliceIndex, targetCount) + m.insert(jmpTable) +} + +// LowerConditionalBranch implements backend.Machine. +func (m *machine) LowerConditionalBranch(b *ssa.Instruction) { + cval, args, targetBlkID := b.BranchData() + if len(args) > 0 { + panic(fmt.Sprintf( + "conditional branch shouldn't have args; likely a bug in critical edge splitting: from %s to %s", + m.currentLabelPos.sb, + targetBlkID, + )) + } + + target := ssaBlockLabel(m.c.SSABuilder().BasicBlock(targetBlkID)) + cvalDef := m.c.ValueDefinition(cval) + + switch m.c.MatchInstrOneOf(cvalDef, condBranchMatches[:]) { + case ssa.OpcodeIcmp: + cvalInstr := cvalDef.Instr + x, y, c := cvalInstr.IcmpData() + + cc := condFromSSAIntCmpCond(c) + if b.Opcode() == ssa.OpcodeBrz { + cc = cc.invert() + } + + // First, perform the comparison and set the flag. + xd, yd := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + if !m.tryLowerBandToFlag(xd, yd) { + m.lowerIcmpToFlag(xd, yd, x.Type() == ssa.TypeI64) + } + + // Then perform the conditional branch. + m.insert(m.allocateInstr().asJmpIf(cc, newOperandLabel(target))) + cvalDef.Instr.MarkLowered() + case ssa.OpcodeFcmp: + cvalInstr := cvalDef.Instr + + f1, f2, and := m.lowerFcmpToFlags(cvalInstr) + isBrz := b.Opcode() == ssa.OpcodeBrz + if isBrz { + f1 = f1.invert() + } + if f2 == condInvalid { + m.insert(m.allocateInstr().asJmpIf(f1, newOperandLabel(target))) + } else { + if isBrz { + f2 = f2.invert() + and = !and + } + jmp1, jmp2 := m.allocateInstr(), m.allocateInstr() + m.insert(jmp1) + m.insert(jmp2) + notTaken, notTakenLabel := m.allocateBrTarget() + m.insert(notTaken) + if and { + jmp1.asJmpIf(f1.invert(), newOperandLabel(notTakenLabel)) + jmp2.asJmpIf(f2, newOperandLabel(target)) + } else { + jmp1.asJmpIf(f1, newOperandLabel(target)) + jmp2.asJmpIf(f2, newOperandLabel(target)) + } + } + + cvalDef.Instr.MarkLowered() + default: + v := m.getOperand_Reg(cvalDef) + + var cc cond + if b.Opcode() == ssa.OpcodeBrz { + cc = condZ + } else { + cc = condNZ + } + + // Perform test %v, %v to set the flag. + cmp := m.allocateInstr().asCmpRmiR(false, v, v.reg(), false) + m.insert(cmp) + m.insert(m.allocateInstr().asJmpIf(cc, newOperandLabel(target))) + } +} + +// LowerInstr implements backend.Machine. +func (m *machine) LowerInstr(instr *ssa.Instruction) { + if l := instr.SourceOffset(); l.Valid() { + info := m.allocateInstr().asEmitSourceOffsetInfo(l) + m.insert(info) + } + + switch op := instr.Opcode(); op { + case ssa.OpcodeBrz, ssa.OpcodeBrnz, ssa.OpcodeJump, ssa.OpcodeBrTable: + panic("BUG: branching instructions are handled by LowerBranches") + case ssa.OpcodeReturn: + panic("BUG: return must be handled by backend.Compiler") + case ssa.OpcodeIconst, ssa.OpcodeF32const, ssa.OpcodeF64const: // Constant instructions are inlined. + case ssa.OpcodeCall, ssa.OpcodeCallIndirect: + m.lowerCall(instr) + case ssa.OpcodeStore, ssa.OpcodeIstore8, ssa.OpcodeIstore16, ssa.OpcodeIstore32: + m.lowerStore(instr) + case ssa.OpcodeIadd: + m.lowerAluRmiROp(instr, aluRmiROpcodeAdd) + case ssa.OpcodeIsub: + m.lowerAluRmiROp(instr, aluRmiROpcodeSub) + case ssa.OpcodeImul: + m.lowerAluRmiROp(instr, aluRmiROpcodeMul) + case ssa.OpcodeSdiv, ssa.OpcodeUdiv, ssa.OpcodeSrem, ssa.OpcodeUrem: + isDiv := op == ssa.OpcodeSdiv || op == ssa.OpcodeUdiv + isSigned := op == ssa.OpcodeSdiv || op == ssa.OpcodeSrem + m.lowerIDivRem(instr, isDiv, isSigned) + case ssa.OpcodeBand: + m.lowerAluRmiROp(instr, aluRmiROpcodeAnd) + case ssa.OpcodeBor: + m.lowerAluRmiROp(instr, aluRmiROpcodeOr) + case ssa.OpcodeBxor: + m.lowerAluRmiROp(instr, aluRmiROpcodeXor) + case ssa.OpcodeIshl: + m.lowerShiftR(instr, shiftROpShiftLeft) + case ssa.OpcodeSshr: + m.lowerShiftR(instr, shiftROpShiftRightArithmetic) + case ssa.OpcodeUshr: + m.lowerShiftR(instr, shiftROpShiftRightLogical) + case ssa.OpcodeRotl: + m.lowerShiftR(instr, shiftROpRotateLeft) + case ssa.OpcodeRotr: + m.lowerShiftR(instr, shiftROpRotateRight) + case ssa.OpcodeClz: + m.lowerClz(instr) + case ssa.OpcodeCtz: + m.lowerCtz(instr) + case ssa.OpcodePopcnt: + m.lowerUnaryRmR(instr, unaryRmROpcodePopcnt) + case ssa.OpcodeFadd, ssa.OpcodeFsub, ssa.OpcodeFmul, ssa.OpcodeFdiv: + m.lowerXmmRmR(instr) + case ssa.OpcodeFabs: + m.lowerFabsFneg(instr) + case ssa.OpcodeFneg: + m.lowerFabsFneg(instr) + case ssa.OpcodeCeil: + m.lowerRound(instr, roundingModeUp) + case ssa.OpcodeFloor: + m.lowerRound(instr, roundingModeDown) + case ssa.OpcodeTrunc: + m.lowerRound(instr, roundingModeZero) + case ssa.OpcodeNearest: + m.lowerRound(instr, roundingModeNearest) + case ssa.OpcodeFmin, ssa.OpcodeFmax: + m.lowerFminFmax(instr) + case ssa.OpcodeFcopysign: + m.lowerFcopysign(instr) + case ssa.OpcodeBitcast: + m.lowerBitcast(instr) + case ssa.OpcodeSqrt: + m.lowerSqrt(instr) + case ssa.OpcodeFpromote: + v := instr.Arg() + rn := m.getOperand_Reg(m.c.ValueDefinition(v)) + rd := m.c.VRegOf(instr.Return()) + cnt := m.allocateInstr() + cnt.asXmmUnaryRmR(sseOpcodeCvtss2sd, rn, rd) + m.insert(cnt) + case ssa.OpcodeFdemote: + v := instr.Arg() + rn := m.getOperand_Reg(m.c.ValueDefinition(v)) + rd := m.c.VRegOf(instr.Return()) + cnt := m.allocateInstr() + cnt.asXmmUnaryRmR(sseOpcodeCvtsd2ss, rn, rd) + m.insert(cnt) + case ssa.OpcodeFcvtToSint, ssa.OpcodeFcvtToSintSat: + x, ctx := instr.Arg2() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + ctxVReg := m.c.VRegOf(ctx) + m.lowerFcvtToSint(ctxVReg, rn.reg(), rd, x.Type() == ssa.TypeF64, + instr.Return().Type().Bits() == 64, op == ssa.OpcodeFcvtToSintSat) + case ssa.OpcodeFcvtToUint, ssa.OpcodeFcvtToUintSat: + x, ctx := instr.Arg2() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + ctxVReg := m.c.VRegOf(ctx) + m.lowerFcvtToUint(ctxVReg, rn.reg(), rd, x.Type() == ssa.TypeF64, + instr.Return().Type().Bits() == 64, op == ssa.OpcodeFcvtToUintSat) + case ssa.OpcodeFcvtFromSint: + x := instr.Arg() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := newOperandReg(m.c.VRegOf(instr.Return())) + m.lowerFcvtFromSint(rn, rd, + x.Type() == ssa.TypeI64, instr.Return().Type().Bits() == 64) + case ssa.OpcodeFcvtFromUint: + x := instr.Arg() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := newOperandReg(m.c.VRegOf(instr.Return())) + m.lowerFcvtFromUint(rn, rd, x.Type() == ssa.TypeI64, + instr.Return().Type().Bits() == 64) + case ssa.OpcodeVanyTrue: + m.lowerVanyTrue(instr) + case ssa.OpcodeVallTrue: + m.lowerVallTrue(instr) + case ssa.OpcodeVhighBits: + m.lowerVhighBits(instr) + case ssa.OpcodeVbnot: + m.lowerVbnot(instr) + case ssa.OpcodeVband: + x, y := instr.Arg2() + m.lowerVbBinOp(sseOpcodePand, x, y, instr.Return()) + case ssa.OpcodeVbor: + x, y := instr.Arg2() + m.lowerVbBinOp(sseOpcodePor, x, y, instr.Return()) + case ssa.OpcodeVbxor: + x, y := instr.Arg2() + m.lowerVbBinOp(sseOpcodePxor, x, y, instr.Return()) + case ssa.OpcodeVbandnot: + m.lowerVbandnot(instr, sseOpcodePandn) + case ssa.OpcodeVbitselect: + m.lowerVbitselect(instr) + case ssa.OpcodeVIadd: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePaddb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePaddw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePaddd + case ssa.VecLaneI64x2: + vecOp = sseOpcodePaddq + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVSaddSat: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePaddsb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePaddsw + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVUaddSat: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePaddusb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePaddusw + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVIsub: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePsubb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePsubw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePsubd + case ssa.VecLaneI64x2: + vecOp = sseOpcodePsubq + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVSsubSat: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePsubsb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePsubsw + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVUsubSat: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePsubusb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePsubusw + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVImul: + m.lowerVImul(instr) + case ssa.OpcodeVIneg: + x, lane := instr.ArgWithLane() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePsubb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePsubw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePsubd + case ssa.VecLaneI64x2: + vecOp = sseOpcodePsubq + default: + panic("BUG") + } + + tmp := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asZeros(tmp)) + + i := m.allocateInstr() + i.asXmmRmR(vecOp, rn, tmp) + m.insert(i) + + m.copyTo(tmp, rd) + case ssa.OpcodeVFadd: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeAddps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeAddpd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVFsub: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeSubps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeSubpd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVFdiv: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeDivps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeDivpd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVFmul: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeMulps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeMulpd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVFneg: + x, lane := instr.ArgWithLane() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.c.AllocateVReg(ssa.TypeV128) + + var shiftOp, xorOp sseOpcode + var shiftAmt uint32 + switch lane { + case ssa.VecLaneF32x4: + shiftOp, shiftAmt, xorOp = sseOpcodePslld, 31, sseOpcodeXorps + case ssa.VecLaneF64x2: + shiftOp, shiftAmt, xorOp = sseOpcodePsllq, 63, sseOpcodeXorpd + } + + zero := m.allocateInstr() + zero.asZeros(tmp) + m.insert(zero) + + // Set all bits on tmp by CMPPD with arg=0 (== pseudo CMPEQPD instruction). + // See https://www.felixcloutier.com/x86/cmpps + // + // Note: if we do not clear all the bits ^ with XORPS, this might end up not setting ones on some lane + // if the lane is NaN. + cmp := m.allocateInstr() + cmp.asXmmRmRImm(sseOpcodeCmppd, uint8(cmpPredEQ_UQ), newOperandReg(tmp), tmp) + m.insert(cmp) + + // Do the left shift on each lane to set only the most significant bit in each. + i := m.allocateInstr() + i.asXmmRmiReg(shiftOp, newOperandImm32(shiftAmt), tmp) + m.insert(i) + + // Get the negated result by XOR on each lane with tmp. + i = m.allocateInstr() + i.asXmmRmR(xorOp, rn, tmp) + m.insert(i) + + m.copyTo(tmp, rd) + + case ssa.OpcodeVSqrt: + x, lane := instr.ArgWithLane() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeSqrtps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeSqrtpd + } + i := m.allocateInstr() + i.asXmmUnaryRmR(vecOp, rn, rd) + m.insert(i) + + case ssa.OpcodeVImin: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePminsb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePminsw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePminsd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVUmin: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePminub + case ssa.VecLaneI16x8: + vecOp = sseOpcodePminuw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePminud + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVImax: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePmaxsb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePmaxsw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePmaxsd + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVUmax: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePmaxub + case ssa.VecLaneI16x8: + vecOp = sseOpcodePmaxuw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePmaxud + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVAvgRound: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePavgb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePavgw + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + + case ssa.OpcodeVIcmp: + x, y, c, lane := instr.VIcmpData() + m.lowerVIcmp(x, y, c, instr.Return(), lane) + + case ssa.OpcodeVFcmp: + x, y, c, lane := instr.VFcmpData() + m.lowerVFcmp(x, y, c, instr.Return(), lane) + + case ssa.OpcodeExtractlane: + x, index, signed, lane := instr.ExtractlaneData() + m.lowerExtractLane(x, index, signed, instr.Return(), lane) + + case ssa.OpcodeInsertlane: + x, y, index, lane := instr.InsertlaneData() + m.lowerInsertLane(x, y, index, instr.Return(), lane) + + case ssa.OpcodeSwizzle: + x, y, _ := instr.Arg2WithLane() + m.lowerSwizzle(x, y, instr.Return()) + + case ssa.OpcodeShuffle: + x, y, lo, hi := instr.ShuffleData() + m.lowerShuffle(x, y, lo, hi, instr.Return()) + + case ssa.OpcodeSplat: + x, lane := instr.ArgWithLane() + m.lowerSplat(x, instr.Return(), lane) + + case ssa.OpcodeSqmulRoundSat: + x, y := instr.Arg2() + m.lowerSqmulRoundSat(x, y, instr.Return()) + + case ssa.OpcodeVZeroExtLoad: + ptr, offset, typ := instr.VZeroExtLoadData() + var sseOp sseOpcode + // Both movss and movsd clears the higher bits of the destination register upt 128 bits. + // https://www.felixcloutier.com/x86/movss + // https://www.felixcloutier.com/x86/movsd + if typ == ssa.TypeF32 { + sseOp = sseOpcodeMovss + } else { + sseOp = sseOpcodeMovsd + } + mem := m.lowerToAddressMode(ptr, offset) + dst := m.c.VRegOf(instr.Return()) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOp, newOperandMem(mem), dst)) + + case ssa.OpcodeVMinPseudo: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeMinps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeMinpd + default: + panic("BUG: unexpected lane type") + } + m.lowerVbBinOpUnaligned(vecOp, y, x, instr.Return()) + + case ssa.OpcodeVMaxPseudo: + x, y, lane := instr.Arg2WithLane() + var vecOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + vecOp = sseOpcodeMaxps + case ssa.VecLaneF64x2: + vecOp = sseOpcodeMaxpd + default: + panic("BUG: unexpected lane type") + } + m.lowerVbBinOpUnaligned(vecOp, y, x, instr.Return()) + + case ssa.OpcodeVIshl: + x, y, lane := instr.Arg2WithLane() + m.lowerVIshl(x, y, instr.Return(), lane) + + case ssa.OpcodeVSshr: + x, y, lane := instr.Arg2WithLane() + m.lowerVSshr(x, y, instr.Return(), lane) + + case ssa.OpcodeVUshr: + x, y, lane := instr.Arg2WithLane() + m.lowerVUshr(x, y, instr.Return(), lane) + + case ssa.OpcodeVCeil: + x, lane := instr.ArgWithLane() + m.lowerVRound(x, instr.Return(), 0x2, lane == ssa.VecLaneF64x2) + + case ssa.OpcodeVFloor: + x, lane := instr.ArgWithLane() + m.lowerVRound(x, instr.Return(), 0x1, lane == ssa.VecLaneF64x2) + + case ssa.OpcodeVTrunc: + x, lane := instr.ArgWithLane() + m.lowerVRound(x, instr.Return(), 0x3, lane == ssa.VecLaneF64x2) + + case ssa.OpcodeVNearest: + x, lane := instr.ArgWithLane() + m.lowerVRound(x, instr.Return(), 0x0, lane == ssa.VecLaneF64x2) + + case ssa.OpcodeExtIaddPairwise: + x, lane, signed := instr.ExtIaddPairwiseData() + m.lowerExtIaddPairwise(x, instr.Return(), lane, signed) + + case ssa.OpcodeUwidenLow, ssa.OpcodeSwidenLow: + x, lane := instr.ArgWithLane() + m.lowerWidenLow(x, instr.Return(), lane, op == ssa.OpcodeSwidenLow) + + case ssa.OpcodeUwidenHigh, ssa.OpcodeSwidenHigh: + x, lane := instr.ArgWithLane() + m.lowerWidenHigh(x, instr.Return(), lane, op == ssa.OpcodeSwidenHigh) + + case ssa.OpcodeLoadSplat: + ptr, offset, lane := instr.LoadSplatData() + m.lowerLoadSplat(ptr, offset, instr.Return(), lane) + + case ssa.OpcodeVFcvtFromUint, ssa.OpcodeVFcvtFromSint: + x, lane := instr.ArgWithLane() + m.lowerVFcvtFromInt(x, instr.Return(), lane, op == ssa.OpcodeVFcvtFromSint) + + case ssa.OpcodeVFcvtToSintSat, ssa.OpcodeVFcvtToUintSat: + x, lane := instr.ArgWithLane() + m.lowerVFcvtToIntSat(x, instr.Return(), lane, op == ssa.OpcodeVFcvtToSintSat) + + case ssa.OpcodeSnarrow, ssa.OpcodeUnarrow: + x, y, lane := instr.Arg2WithLane() + m.lowerNarrow(x, y, instr.Return(), lane, op == ssa.OpcodeSnarrow) + + case ssa.OpcodeFvpromoteLow: + x := instr.Arg() + src := m.getOperand_Reg(m.c.ValueDefinition(x)) + dst := m.c.VRegOf(instr.Return()) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtps2pd, src, dst)) + + case ssa.OpcodeFvdemote: + x := instr.Arg() + src := m.getOperand_Reg(m.c.ValueDefinition(x)) + dst := m.c.VRegOf(instr.Return()) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtpd2ps, src, dst)) + + case ssa.OpcodeWideningPairwiseDotProductS: + x, y := instr.Arg2() + m.lowerWideningPairwiseDotProductS(x, y, instr.Return()) + + case ssa.OpcodeVIabs: + m.lowerVIabs(instr) + case ssa.OpcodeVIpopcnt: + m.lowerVIpopcnt(instr) + case ssa.OpcodeVFmin: + m.lowerVFmin(instr) + case ssa.OpcodeVFmax: + m.lowerVFmax(instr) + case ssa.OpcodeVFabs: + m.lowerVFabs(instr) + case ssa.OpcodeUndefined: + m.insert(m.allocateInstr().asUD2()) + case ssa.OpcodeExitWithCode: + execCtx, code := instr.ExitWithCodeData() + m.lowerExitWithCode(m.c.VRegOf(execCtx), code) + case ssa.OpcodeExitIfTrueWithCode: + execCtx, c, code := instr.ExitIfTrueWithCodeData() + m.lowerExitIfTrueWithCode(m.c.VRegOf(execCtx), c, code) + case ssa.OpcodeLoad: + ptr, offset, typ := instr.LoadData() + dst := m.c.VRegOf(instr.Return()) + m.lowerLoad(ptr, offset, typ, dst) + case ssa.OpcodeUload8, ssa.OpcodeUload16, ssa.OpcodeUload32, ssa.OpcodeSload8, ssa.OpcodeSload16, ssa.OpcodeSload32: + ptr, offset, _ := instr.LoadData() + ret := m.c.VRegOf(instr.Return()) + m.lowerExtLoad(op, ptr, offset, ret) + case ssa.OpcodeVconst: + result := m.c.VRegOf(instr.Return()) + lo, hi := instr.VconstData() + m.lowerVconst(result, lo, hi) + case ssa.OpcodeSExtend, ssa.OpcodeUExtend: + from, to, signed := instr.ExtendData() + m.lowerExtend(instr.Arg(), instr.Return(), from, to, signed) + case ssa.OpcodeIcmp: + m.lowerIcmp(instr) + case ssa.OpcodeFcmp: + m.lowerFcmp(instr) + case ssa.OpcodeSelect: + cval, x, y := instr.SelectData() + m.lowerSelect(x, y, cval, instr.Return()) + case ssa.OpcodeIreduce: + rn := m.getOperand_Mem_Reg(m.c.ValueDefinition(instr.Arg())) + retVal := instr.Return() + rd := m.c.VRegOf(retVal) + + if retVal.Type() != ssa.TypeI32 { + panic("TODO?: Ireduce to non-i32") + } + m.insert(m.allocateInstr().asMovzxRmR(extModeLQ, rn, rd)) + + case ssa.OpcodeAtomicLoad: + ptr := instr.Arg() + size := instr.AtomicTargetSize() + dst := m.c.VRegOf(instr.Return()) + + // At this point, the ptr is ensured to be aligned, so using a normal load is atomic. + // https://github.com/golang/go/blob/adead1a93f472affa97c494ef19f2f492ee6f34a/src/runtime/internal/atomic/atomic_amd64.go#L30 + mem := newOperandMem(m.lowerToAddressMode(ptr, 0)) + load := m.allocateInstr() + switch size { + case 8: + load.asMov64MR(mem, dst) + case 4: + load.asMovzxRmR(extModeLQ, mem, dst) + case 2: + load.asMovzxRmR(extModeWQ, mem, dst) + case 1: + load.asMovzxRmR(extModeBQ, mem, dst) + default: + panic("BUG") + } + m.insert(load) + + case ssa.OpcodeFence: + m.insert(m.allocateInstr().asMFence()) + + case ssa.OpcodeAtomicStore: + ptr, _val := instr.Arg2() + size := instr.AtomicTargetSize() + + val := m.getOperand_Reg(m.c.ValueDefinition(_val)) + // The content on the val register will be overwritten by xchg, so we need to copy it to a temporary register. + copied := m.copyToTmp(val.reg()) + + mem := newOperandMem(m.lowerToAddressMode(ptr, 0)) + store := m.allocateInstr().asXCHG(copied, mem, byte(size)) + m.insert(store) + + case ssa.OpcodeAtomicCas: + addr, exp, repl := instr.Arg3() + size := instr.AtomicTargetSize() + m.lowerAtomicCas(addr, exp, repl, size, instr.Return()) + + case ssa.OpcodeAtomicRmw: + addr, val := instr.Arg2() + atomicOp, size := instr.AtomicRmwData() + m.lowerAtomicRmw(atomicOp, addr, val, size, instr.Return()) + + default: + panic("TODO: lowering " + op.String()) + } +} + +func (m *machine) lowerAtomicRmw(op ssa.AtomicRmwOp, addr, val ssa.Value, size uint64, ret ssa.Value) { + mem := m.lowerToAddressMode(addr, 0) + _val := m.getOperand_Reg(m.c.ValueDefinition(val)) + + switch op { + case ssa.AtomicRmwOpAdd, ssa.AtomicRmwOpSub: + valCopied := m.copyToTmp(_val.reg()) + if op == ssa.AtomicRmwOpSub { + // Negate the value. + m.insert(m.allocateInstr().asNeg(newOperandReg(valCopied), true)) + } + m.insert(m.allocateInstr().asLockXAdd(valCopied, mem, byte(size))) + m.clearHigherBitsForAtomic(valCopied, size, ret.Type()) + m.copyTo(valCopied, m.c.VRegOf(ret)) + + case ssa.AtomicRmwOpAnd, ssa.AtomicRmwOpOr, ssa.AtomicRmwOpXor: + accumulator := raxVReg + // Reserve rax for the accumulator to make regalloc happy. + // Note: do this initialization before defining valCopied, because it might be the same register and + // if that happens, the unnecessary load/store will be performed inside the loop. + // This can be mitigated in any way once the register allocator is clever enough. + m.insert(m.allocateInstr().asDefineUninitializedReg(accumulator)) + + // Copy the value to a temporary register. + valCopied := m.copyToTmp(_val.reg()) + m.clearHigherBitsForAtomic(valCopied, size, ret.Type()) + + memOp := newOperandMem(mem) + tmp := m.c.AllocateVReg(ssa.TypeI64) + beginLoop, beginLoopLabel := m.allocateBrTarget() + { + m.insert(beginLoop) + // Reset the value on tmp by the original value. + m.copyTo(valCopied, tmp) + // Load the current value at the memory location into accumulator. + switch size { + case 1: + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, memOp, accumulator)) + case 2: + m.insert(m.allocateInstr().asMovzxRmR(extModeWQ, memOp, accumulator)) + case 4: + m.insert(m.allocateInstr().asMovzxRmR(extModeLQ, memOp, accumulator)) + case 8: + m.insert(m.allocateInstr().asMov64MR(memOp, accumulator)) + default: + panic("BUG") + } + // Then perform the logical operation on the accumulator and the value on tmp. + switch op { + case ssa.AtomicRmwOpAnd: + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAnd, newOperandReg(accumulator), tmp, true)) + case ssa.AtomicRmwOpOr: + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeOr, newOperandReg(accumulator), tmp, true)) + case ssa.AtomicRmwOpXor: + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeXor, newOperandReg(accumulator), tmp, true)) + default: + panic("BUG") + } + // Finally, try compare-exchange the value at the memory location with the tmp. + m.insert(m.allocateInstr().asLockCmpXCHG(tmp, memOp.addressMode(), byte(size))) + // If it succeeds, ZF will be set, and we can break the loop. + m.insert(m.allocateInstr().asJmpIf(condNZ, newOperandLabel(beginLoopLabel))) + } + + // valCopied must be alive at the end of the loop. + m.insert(m.allocateInstr().asNopUseReg(valCopied)) + + // At this point, accumulator contains the result. + m.clearHigherBitsForAtomic(accumulator, size, ret.Type()) + m.copyTo(accumulator, m.c.VRegOf(ret)) + + case ssa.AtomicRmwOpXchg: + valCopied := m.copyToTmp(_val.reg()) + + m.insert(m.allocateInstr().asXCHG(valCopied, newOperandMem(mem), byte(size))) + m.clearHigherBitsForAtomic(valCopied, size, ret.Type()) + m.copyTo(valCopied, m.c.VRegOf(ret)) + + default: + panic("BUG") + } +} + +func (m *machine) lowerAtomicCas(addr, exp, repl ssa.Value, size uint64, ret ssa.Value) { + mem := m.lowerToAddressMode(addr, 0) + expOp := m.getOperand_Reg(m.c.ValueDefinition(exp)) + replOp := m.getOperand_Reg(m.c.ValueDefinition(repl)) + + accumulator := raxVReg + m.copyTo(expOp.reg(), accumulator) + m.insert(m.allocateInstr().asLockCmpXCHG(replOp.reg(), mem, byte(size))) + m.clearHigherBitsForAtomic(accumulator, size, ret.Type()) + m.copyTo(accumulator, m.c.VRegOf(ret)) +} + +func (m *machine) clearHigherBitsForAtomic(r regalloc.VReg, valSize uint64, resultType ssa.Type) { + switch resultType { + case ssa.TypeI32: + switch valSize { + case 1: + m.insert(m.allocateInstr().asMovzxRmR(extModeBL, newOperandReg(r), r)) + case 2: + m.insert(m.allocateInstr().asMovzxRmR(extModeWL, newOperandReg(r), r)) + } + case ssa.TypeI64: + switch valSize { + case 1: + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, newOperandReg(r), r)) + case 2: + m.insert(m.allocateInstr().asMovzxRmR(extModeWQ, newOperandReg(r), r)) + case 4: + m.insert(m.allocateInstr().asMovzxRmR(extModeLQ, newOperandReg(r), r)) + } + } +} + +func (m *machine) lowerFcmp(instr *ssa.Instruction) { + f1, f2, and := m.lowerFcmpToFlags(instr) + rd := m.c.VRegOf(instr.Return()) + if f2 == condInvalid { + tmp := m.c.AllocateVReg(ssa.TypeI32) + m.insert(m.allocateInstr().asSetcc(f1, tmp)) + // On amd64, setcc only sets the first byte of the register, so we need to zero extend it to match + // the semantics of Icmp that sets either 0 or 1. + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, newOperandReg(tmp), rd)) + } else { + tmp1, tmp2 := m.c.AllocateVReg(ssa.TypeI32), m.c.AllocateVReg(ssa.TypeI32) + m.insert(m.allocateInstr().asSetcc(f1, tmp1)) + m.insert(m.allocateInstr().asSetcc(f2, tmp2)) + var op aluRmiROpcode + if and { + op = aluRmiROpcodeAnd + } else { + op = aluRmiROpcodeOr + } + m.insert(m.allocateInstr().asAluRmiR(op, newOperandReg(tmp1), tmp2, false)) + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, newOperandReg(tmp2), rd)) + } +} + +func (m *machine) lowerIcmp(instr *ssa.Instruction) { + x, y, c := instr.IcmpData() + m.lowerIcmpToFlag(m.c.ValueDefinition(x), m.c.ValueDefinition(y), x.Type() == ssa.TypeI64) + rd := m.c.VRegOf(instr.Return()) + tmp := m.c.AllocateVReg(ssa.TypeI32) + m.insert(m.allocateInstr().asSetcc(condFromSSAIntCmpCond(c), tmp)) + // On amd64, setcc only sets the first byte of the register, so we need to zero extend it to match + // the semantics of Icmp that sets either 0 or 1. + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, newOperandReg(tmp), rd)) +} + +func (m *machine) lowerSelect(x, y, cval, ret ssa.Value) { + xo, yo := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)), m.getOperand_Reg(m.c.ValueDefinition(y)) + rd := m.c.VRegOf(ret) + + var cond cond + cvalDef := m.c.ValueDefinition(cval) + switch m.c.MatchInstrOneOf(cvalDef, condBranchMatches[:]) { + case ssa.OpcodeIcmp: + icmp := cvalDef.Instr + xc, yc, cc := icmp.IcmpData() + m.lowerIcmpToFlag(m.c.ValueDefinition(xc), m.c.ValueDefinition(yc), xc.Type() == ssa.TypeI64) + cond = condFromSSAIntCmpCond(cc) + icmp.Lowered() + default: // TODO: match ssa.OpcodeFcmp for optimization, but seems a bit complex. + cv := m.getOperand_Reg(cvalDef) + test := m.allocateInstr().asCmpRmiR(false, cv, cv.reg(), false) + m.insert(test) + cond = condNZ + } + + if typ := x.Type(); typ.IsInt() { + _64 := typ.Bits() == 64 + mov := m.allocateInstr() + tmp := m.c.AllocateVReg(typ) + switch yo.kind { + case operandKindReg: + mov.asMovRR(yo.reg(), tmp, _64) + case operandKindMem: + if _64 { + mov.asMov64MR(yo, tmp) + } else { + mov.asMovzxRmR(extModeLQ, yo, tmp) + } + default: + panic("BUG") + } + m.insert(mov) + cmov := m.allocateInstr().asCmove(cond, xo, tmp, _64) + m.insert(cmov) + m.insert(m.allocateInstr().asMovRR(tmp, rd, _64)) + } else { + mov := m.allocateInstr() + tmp := m.c.AllocateVReg(typ) + switch typ { + case ssa.TypeF32: + mov.asXmmUnaryRmR(sseOpcodeMovss, yo, tmp) + case ssa.TypeF64: + mov.asXmmUnaryRmR(sseOpcodeMovsd, yo, tmp) + case ssa.TypeV128: + mov.asXmmUnaryRmR(sseOpcodeMovdqu, yo, tmp) + default: + panic("BUG") + } + m.insert(mov) + + cmov := m.allocateInstr().asXmmCMov(cond, xo, tmp, typ.Size()) + m.insert(cmov) + + m.copyTo(tmp, rd) + } +} + +func (m *machine) lowerXmmCmovAfterRegAlloc(i *instruction) { + x := i.op1 + rd := i.op2.reg() + cond := cond(i.u1) + + jcc := m.allocateInstr() + m.insert(jcc) + + mov := m.allocateInstr() + switch i.u2 { + case 4: + mov.asXmmUnaryRmR(sseOpcodeMovss, x, rd) + case 8: + mov.asXmmUnaryRmR(sseOpcodeMovsd, x, rd) + case 16: + mov.asXmmUnaryRmR(sseOpcodeMovdqu, x, rd) + default: + panic("BUG") + } + m.insert(mov) + + nop, end := m.allocateBrTarget() + m.insert(nop) + jcc.asJmpIf(cond.invert(), newOperandLabel(end)) +} + +func (m *machine) lowerExtend(_arg, ret ssa.Value, from, to byte, signed bool) { + rd0 := m.c.VRegOf(ret) + arg := m.getOperand_Mem_Reg(m.c.ValueDefinition(_arg)) + + rd := m.c.AllocateVReg(ret.Type()) + + ext := m.allocateInstr() + switch { + case from == 8 && to == 16 && signed: + ext.asMovsxRmR(extModeBQ, arg, rd) + case from == 8 && to == 16 && !signed: + ext.asMovzxRmR(extModeBL, arg, rd) + case from == 8 && to == 32 && signed: + ext.asMovsxRmR(extModeBL, arg, rd) + case from == 8 && to == 32 && !signed: + ext.asMovzxRmR(extModeBQ, arg, rd) + case from == 8 && to == 64 && signed: + ext.asMovsxRmR(extModeBQ, arg, rd) + case from == 8 && to == 64 && !signed: + ext.asMovzxRmR(extModeBQ, arg, rd) + case from == 16 && to == 32 && signed: + ext.asMovsxRmR(extModeWL, arg, rd) + case from == 16 && to == 32 && !signed: + ext.asMovzxRmR(extModeWL, arg, rd) + case from == 16 && to == 64 && signed: + ext.asMovsxRmR(extModeWQ, arg, rd) + case from == 16 && to == 64 && !signed: + ext.asMovzxRmR(extModeWQ, arg, rd) + case from == 32 && to == 64 && signed: + ext.asMovsxRmR(extModeLQ, arg, rd) + case from == 32 && to == 64 && !signed: + ext.asMovzxRmR(extModeLQ, arg, rd) + default: + panic(fmt.Sprintf("BUG: unhandled extend: from=%d, to=%d, signed=%t", from, to, signed)) + } + m.insert(ext) + + m.copyTo(rd, rd0) +} + +func (m *machine) lowerVconst(dst regalloc.VReg, lo, hi uint64) { + if lo == 0 && hi == 0 { + m.insert(m.allocateInstr().asZeros(dst)) + return + } + + load := m.allocateInstr() + l, pos := m.allocateLabel() + m.consts = append(m.consts, _const{label: l, labelPos: pos, lo: lo, hi: hi}) + load.asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(l)), dst) + m.insert(load) +} + +func (m *machine) lowerCtz(instr *ssa.Instruction) { + if m.cpuFeatures.HasExtra(platform.CpuExtraFeatureAmd64ABM) { + m.lowerUnaryRmR(instr, unaryRmROpcodeTzcnt) + } else { + // On processors that do not support TZCNT, the BSF instruction is + // executed instead. The key difference between TZCNT and BSF + // instruction is that if source operand is zero, the content of + // destination operand is undefined. + // https://www.felixcloutier.com/x86/tzcnt.html + + x := instr.Arg() + if !x.Type().IsInt() { + panic("BUG?") + } + _64 := x.Type().Bits() == 64 + + xDef := m.c.ValueDefinition(x) + tmp := m.c.AllocateVReg(x.Type()) + rm := m.getOperand_Reg(xDef) + + // First, we have to check if the target is non-zero. + test := m.allocateInstr() + test.asCmpRmiR(false, rm, rm.reg(), _64) + m.insert(test) + + jmpNz := m.allocateInstr() + m.insert(jmpNz) + + // If the value is zero, we just push the const value. + m.lowerIconst(tmp, uint64(x.Type().Bits()), _64) + + // Now jump right after the non-zero case. + jmpAtEnd := m.allocateInstr() + m.insert(jmpAtEnd) + + // jmpNz target label is set here. + nop, nz := m.allocateBrTarget() + jmpNz.asJmpIf(condNZ, newOperandLabel(nz)) + m.insert(nop) + + // Emit the non-zero case. + bsr := m.allocateInstr() + bsr.asUnaryRmR(unaryRmROpcodeBsf, rm, tmp, _64) + m.insert(bsr) + + // jmpAtEnd target label is set here. + nopEnd, end := m.allocateBrTarget() + jmpAtEnd.asJmp(newOperandLabel(end)) + m.insert(nopEnd) + + m.copyTo(tmp, m.c.VRegOf(instr.Return())) + } +} + +func (m *machine) lowerClz(instr *ssa.Instruction) { + if m.cpuFeatures.HasExtra(platform.CpuExtraFeatureAmd64ABM) { + m.lowerUnaryRmR(instr, unaryRmROpcodeLzcnt) + } else { + // On processors that do not support LZCNT, we combine BSR (calculating + // most significant set bit) with XOR. This logic is described in + // "Replace Raw Assembly Code with Builtin Intrinsics" section in: + // https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code. + + x := instr.Arg() + if !x.Type().IsInt() { + panic("BUG?") + } + _64 := x.Type().Bits() == 64 + + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Reg(xDef) + tmp := m.c.AllocateVReg(x.Type()) + + // First, we have to check if the rm is non-zero as BSR is undefined + // on zero. See https://www.felixcloutier.com/x86/bsr. + test := m.allocateInstr() + test.asCmpRmiR(false, rm, rm.reg(), _64) + m.insert(test) + + jmpNz := m.allocateInstr() + m.insert(jmpNz) + + // If the value is zero, we just push the const value. + m.lowerIconst(tmp, uint64(x.Type().Bits()), _64) + + // Now jump right after the non-zero case. + jmpAtEnd := m.allocateInstr() + m.insert(jmpAtEnd) + + // jmpNz target label is set here. + nop, nz := m.allocateBrTarget() + jmpNz.asJmpIf(condNZ, newOperandLabel(nz)) + m.insert(nop) + + // Emit the non-zero case. + bsr := m.allocateInstr() + bsr.asUnaryRmR(unaryRmROpcodeBsr, rm, tmp, _64) + m.insert(bsr) + + // Now we XOR the value with the bit length minus one. + xor := m.allocateInstr() + xor.asAluRmiR(aluRmiROpcodeXor, newOperandImm32(uint32(x.Type().Bits()-1)), tmp, _64) + m.insert(xor) + + // jmpAtEnd target label is set here. + nopEnd, end := m.allocateBrTarget() + jmpAtEnd.asJmp(newOperandLabel(end)) + m.insert(nopEnd) + + m.copyTo(tmp, m.c.VRegOf(instr.Return())) + } +} + +func (m *machine) lowerUnaryRmR(si *ssa.Instruction, op unaryRmROpcode) { + x := si.Arg() + if !x.Type().IsInt() { + panic("BUG?") + } + _64 := x.Type().Bits() == 64 + + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Mem_Reg(xDef) + rd := m.c.VRegOf(si.Return()) + + instr := m.allocateInstr() + instr.asUnaryRmR(op, rm, rd, _64) + m.insert(instr) +} + +func (m *machine) lowerLoad(ptr ssa.Value, offset uint32, typ ssa.Type, dst regalloc.VReg) { + mem := newOperandMem(m.lowerToAddressMode(ptr, offset)) + load := m.allocateInstr() + switch typ { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, mem, dst) + case ssa.TypeI64: + load.asMov64MR(mem, dst) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, mem, dst) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, mem, dst) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, dst) + default: + panic("BUG") + } + m.insert(load) +} + +func (m *machine) lowerExtLoad(op ssa.Opcode, ptr ssa.Value, offset uint32, dst regalloc.VReg) { + mem := newOperandMem(m.lowerToAddressMode(ptr, offset)) + load := m.allocateInstr() + switch op { + case ssa.OpcodeUload8: + load.asMovzxRmR(extModeBQ, mem, dst) + case ssa.OpcodeUload16: + load.asMovzxRmR(extModeWQ, mem, dst) + case ssa.OpcodeUload32: + load.asMovzxRmR(extModeLQ, mem, dst) + case ssa.OpcodeSload8: + load.asMovsxRmR(extModeBQ, mem, dst) + case ssa.OpcodeSload16: + load.asMovsxRmR(extModeWQ, mem, dst) + case ssa.OpcodeSload32: + load.asMovsxRmR(extModeLQ, mem, dst) + default: + panic("BUG") + } + m.insert(load) +} + +func (m *machine) lowerExitIfTrueWithCode(execCtx regalloc.VReg, cond ssa.Value, code wazevoapi.ExitCode) { + condDef := m.c.ValueDefinition(cond) + if !m.c.MatchInstr(condDef, ssa.OpcodeIcmp) { + panic("TODO: ExitIfTrue must come after Icmp at the moment: " + condDef.Instr.Opcode().String()) + } + cvalInstr := condDef.Instr + cvalInstr.MarkLowered() + + // We need to copy the execution context to a temp register, because if it's spilled, + // it might end up being reloaded inside the exiting branch. + execCtxTmp := m.copyToTmp(execCtx) + + x, y, c := cvalInstr.IcmpData() + xx, yy := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + if !m.tryLowerBandToFlag(xx, yy) { + m.lowerIcmpToFlag(xx, yy, x.Type() == ssa.TypeI64) + } + + jmpIf := m.allocateInstr() + m.insert(jmpIf) + l := m.lowerExitWithCode(execCtxTmp, code) + jmpIf.asJmpIf(condFromSSAIntCmpCond(c).invert(), newOperandLabel(l)) +} + +func (m *machine) tryLowerBandToFlag(x, y backend.SSAValueDefinition) (ok bool) { + var target backend.SSAValueDefinition + var got bool + if x.IsFromInstr() && x.Instr.Constant() && x.Instr.ConstantVal() == 0 { + if m.c.MatchInstr(y, ssa.OpcodeBand) { + target = y + got = true + } + } + + if y.IsFromInstr() && y.Instr.Constant() && y.Instr.ConstantVal() == 0 { + if m.c.MatchInstr(x, ssa.OpcodeBand) { + target = x + got = true + } + } + + if !got { + return false + } + + bandInstr := target.Instr + bandX, bandY := bandInstr.Arg2() + + xx := m.getOperand_Reg(m.c.ValueDefinition(bandX)) + yy := m.getOperand_Mem_Imm32_Reg(m.c.ValueDefinition(bandY)) + test := m.allocateInstr().asCmpRmiR(false, yy, xx.reg(), bandX.Type() == ssa.TypeI64) + m.insert(test) + bandInstr.MarkLowered() + return true +} + +func (m *machine) allocateExitInstructions(execCtx, exitCodeReg regalloc.VReg) (saveRsp, saveRbp, setExitCode *instruction) { + saveRsp = m.allocateInstr().asMovRM( + rspVReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetStackPointerBeforeGoCall.U32(), execCtx)), + 8, + ) + + saveRbp = m.allocateInstr().asMovRM( + rbpVReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetFramePointerBeforeGoCall.U32(), execCtx)), + 8, + ) + setExitCode = m.allocateInstr().asMovRM( + exitCodeReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetExitCodeOffset.U32(), execCtx)), + 4, + ) + return +} + +func (m *machine) lowerExitWithCode(execCtx regalloc.VReg, code wazevoapi.ExitCode) (afterLabel label) { + exitCodeReg := rbpVReg + saveRsp, saveRbp, setExitCode := m.allocateExitInstructions(execCtx, exitCodeReg) + + // Set save RSP, RBP, and write exit code. + m.insert(saveRsp) + m.insert(saveRbp) + m.lowerIconst(exitCodeReg, uint64(code), false) + m.insert(setExitCode) + + ripReg := rbpVReg + + // Next is to save the current address for stack unwinding. + nop, currentAddrLabel := m.allocateBrTarget() + m.insert(nop) + readRip := m.allocateInstr().asLEA(newOperandLabel(currentAddrLabel), ripReg) + m.insert(readRip) + saveRip := m.allocateInstr().asMovRM( + ripReg, + newOperandMem(m.newAmodeImmReg(wazevoapi.ExecutionContextOffsetGoCallReturnAddress.U32(), execCtx)), + 8, + ) + m.insert(saveRip) + + // Finally exit. + exitSq := m.allocateExitSeq(execCtx) + m.insert(exitSq) + + // Return the label for continuation. + continuation, afterLabel := m.allocateBrTarget() + m.insert(continuation) + return afterLabel +} + +func (m *machine) lowerAluRmiROp(si *ssa.Instruction, op aluRmiROpcode) { + x, y := si.Arg2() + if !x.Type().IsInt() { + panic("BUG?") + } + + _64 := x.Type().Bits() == 64 + + xDef, yDef := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + + // TODO: commutative args can be swapped if one of them is an immediate. + rn := m.getOperand_Reg(xDef) + rm := m.getOperand_Mem_Imm32_Reg(yDef) + rd := m.c.VRegOf(si.Return()) + + // rn is being overwritten, so we first copy its value to a temp register, + // in case it is referenced again later. + tmp := m.copyToTmp(rn.reg()) + + alu := m.allocateInstr() + alu.asAluRmiR(op, rm, tmp, _64) + m.insert(alu) + + // tmp now contains the result, we copy it to the dest register. + m.copyTo(tmp, rd) +} + +func (m *machine) lowerShiftR(si *ssa.Instruction, op shiftROp) { + x, amt := si.Arg2() + if !x.Type().IsInt() { + panic("BUG?") + } + _64 := x.Type().Bits() == 64 + + xDef, amtDef := m.c.ValueDefinition(x), m.c.ValueDefinition(amt) + + opAmt := m.getOperand_Imm32_Reg(amtDef) + rx := m.getOperand_Reg(xDef) + rd := m.c.VRegOf(si.Return()) + + // rx is being overwritten, so we first copy its value to a temp register, + // in case it is referenced again later. + tmpDst := m.copyToTmp(rx.reg()) + + if opAmt.kind == operandKindReg { + // If opAmt is a register we must copy its value to rcx, + // because shiftR encoding mandates that the shift amount is in rcx. + m.copyTo(opAmt.reg(), rcxVReg) + + alu := m.allocateInstr() + alu.asShiftR(op, newOperandReg(rcxVReg), tmpDst, _64) + m.insert(alu) + + } else { + alu := m.allocateInstr() + alu.asShiftR(op, opAmt, tmpDst, _64) + m.insert(alu) + } + + // tmp now contains the result, we copy it to the dest register. + m.copyTo(tmpDst, rd) +} + +func (m *machine) lowerXmmRmR(instr *ssa.Instruction) { + x, y := instr.Arg2() + if !x.Type().IsFloat() { + panic("BUG?") + } + _64 := x.Type().Bits() == 64 + + var op sseOpcode + if _64 { + switch instr.Opcode() { + case ssa.OpcodeFadd: + op = sseOpcodeAddsd + case ssa.OpcodeFsub: + op = sseOpcodeSubsd + case ssa.OpcodeFmul: + op = sseOpcodeMulsd + case ssa.OpcodeFdiv: + op = sseOpcodeDivsd + default: + panic("BUG") + } + } else { + switch instr.Opcode() { + case ssa.OpcodeFadd: + op = sseOpcodeAddss + case ssa.OpcodeFsub: + op = sseOpcodeSubss + case ssa.OpcodeFmul: + op = sseOpcodeMulss + case ssa.OpcodeFdiv: + op = sseOpcodeDivss + default: + panic("BUG") + } + } + + xDef, yDef := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + rn := m.getOperand_Reg(yDef) + rm := m.getOperand_Reg(xDef) + rd := m.c.VRegOf(instr.Return()) + + // rm is being overwritten, so we first copy its value to a temp register, + // in case it is referenced again later. + tmp := m.copyToTmp(rm.reg()) + + xmm := m.allocateInstr().asXmmRmR(op, rn, tmp) + m.insert(xmm) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerSqrt(instr *ssa.Instruction) { + x := instr.Arg() + if !x.Type().IsFloat() { + panic("BUG") + } + _64 := x.Type().Bits() == 64 + var op sseOpcode + if _64 { + op = sseOpcodeSqrtsd + } else { + op = sseOpcodeSqrtss + } + + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Mem_Reg(xDef) + rd := m.c.VRegOf(instr.Return()) + + xmm := m.allocateInstr().asXmmUnaryRmR(op, rm, rd) + m.insert(xmm) +} + +func (m *machine) lowerFabsFneg(instr *ssa.Instruction) { + x := instr.Arg() + if !x.Type().IsFloat() { + panic("BUG") + } + _64 := x.Type().Bits() == 64 + var op sseOpcode + var mask uint64 + if _64 { + switch instr.Opcode() { + case ssa.OpcodeFabs: + mask, op = 0x7fffffffffffffff, sseOpcodeAndpd + case ssa.OpcodeFneg: + mask, op = 0x8000000000000000, sseOpcodeXorpd + } + } else { + switch instr.Opcode() { + case ssa.OpcodeFabs: + mask, op = 0x7fffffff, sseOpcodeAndps + case ssa.OpcodeFneg: + mask, op = 0x80000000, sseOpcodeXorps + } + } + + tmp := m.c.AllocateVReg(x.Type()) + + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Reg(xDef) + rd := m.c.VRegOf(instr.Return()) + + m.lowerFconst(tmp, mask, _64) + + xmm := m.allocateInstr().asXmmRmR(op, rm, tmp) + m.insert(xmm) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerStore(si *ssa.Instruction) { + value, ptr, offset, storeSizeInBits := si.StoreData() + rm := m.getOperand_Reg(m.c.ValueDefinition(value)) + mem := newOperandMem(m.lowerToAddressMode(ptr, offset)) + + store := m.allocateInstr() + switch value.Type() { + case ssa.TypeI32: + store.asMovRM(rm.reg(), mem, storeSizeInBits/8) + case ssa.TypeI64: + store.asMovRM(rm.reg(), mem, storeSizeInBits/8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, rm.reg(), mem) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, rm.reg(), mem) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, rm.reg(), mem) + default: + panic("BUG") + } + m.insert(store) +} + +func (m *machine) lowerCall(si *ssa.Instruction) { + isDirectCall := si.Opcode() == ssa.OpcodeCall + var indirectCalleePtr ssa.Value + var directCallee ssa.FuncRef + var sigID ssa.SignatureID + var args []ssa.Value + var isMemmove bool + if isDirectCall { + directCallee, sigID, args = si.CallData() + } else { + indirectCalleePtr, sigID, args, isMemmove = si.CallIndirectData() + } + calleeABI := m.c.GetFunctionABI(m.c.SSABuilder().ResolveSignature(sigID)) + + stackSlotSize := int64(calleeABI.AlignedArgResultStackSlotSize()) + if m.maxRequiredStackSizeForCalls < stackSlotSize+16 { + m.maxRequiredStackSizeForCalls = stackSlotSize + 16 // 16 == return address + RBP. + } + + // Note: See machine.SetupPrologue for the stack layout. + // The stack pointer decrease/increase will be inserted later in the compilation. + + for i, arg := range args { + reg := m.c.VRegOf(arg) + def := m.c.ValueDefinition(arg) + m.callerGenVRegToFunctionArg(calleeABI, i, reg, def, stackSlotSize) + } + + if isMemmove { + // Go's memmove *might* use all xmm0-xmm15, so we need to release them. + // https://github.com/golang/go/blob/49d42128fd8594c172162961ead19ac95e247d24/src/cmd/compile/abi-internal.md#architecture-specifics + // https://github.com/golang/go/blob/49d42128fd8594c172162961ead19ac95e247d24/src/runtime/memmove_amd64.s#L271-L286 + for i := regalloc.RealReg(0); i < 16; i++ { + m.insert(m.allocateInstr().asDefineUninitializedReg(regInfo.RealRegToVReg[xmm0+i])) + } + // Since Go 1.24 it may also use DX, which is not reserved for the function call's 3 args. + // https://github.com/golang/go/blob/go1.24.0/src/runtime/memmove_amd64.s#L123 + m.insert(m.allocateInstr().asDefineUninitializedReg(regInfo.RealRegToVReg[rdx])) + } + + if isDirectCall { + call := m.allocateInstr().asCall(directCallee, calleeABI) + m.insert(call) + } else { + ptrOp := m.getOperand_Mem_Reg(m.c.ValueDefinition(indirectCalleePtr)) + callInd := m.allocateInstr().asCallIndirect(ptrOp, calleeABI) + m.insert(callInd) + } + + if isMemmove { + for i := regalloc.RealReg(0); i < 16; i++ { + m.insert(m.allocateInstr().asNopUseReg(regInfo.RealRegToVReg[xmm0+i])) + } + m.insert(m.allocateInstr().asNopUseReg(regInfo.RealRegToVReg[rdx])) + } + + var index int + r1, rs := si.Returns() + if r1.Valid() { + m.callerGenFunctionReturnVReg(calleeABI, 0, m.c.VRegOf(r1), stackSlotSize) + index++ + } + + for _, r := range rs { + m.callerGenFunctionReturnVReg(calleeABI, index, m.c.VRegOf(r), stackSlotSize) + index++ + } +} + +// callerGenVRegToFunctionArg is the opposite of GenFunctionArgToVReg, which is used to generate the +// caller side of the function call. +func (m *machine) callerGenVRegToFunctionArg(a *backend.FunctionABI, argIndex int, reg regalloc.VReg, def backend.SSAValueDefinition, stackSlotSize int64) { + arg := &a.Args[argIndex] + if def.IsFromInstr() { + // Constant instructions are inlined. + if inst := def.Instr; inst.Constant() { + m.insertLoadConstant(inst, reg) + } + } + if arg.Kind == backend.ABIArgKindReg { + m.InsertMove(arg.Reg, reg, arg.Type) + } else { + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg( + // -stackSlotSize because the stack pointer is not yet decreased. + uint32(arg.Offset-stackSlotSize), rspVReg)) + switch arg.Type { + case ssa.TypeI32: + store.asMovRM(reg, mem, 4) + case ssa.TypeI64: + store.asMovRM(reg, mem, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, reg, mem) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, reg, mem) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, reg, mem) + default: + panic("BUG") + } + m.insert(store) + } +} + +func (m *machine) callerGenFunctionReturnVReg(a *backend.FunctionABI, retIndex int, reg regalloc.VReg, stackSlotSize int64) { + r := &a.Rets[retIndex] + if r.Kind == backend.ABIArgKindReg { + m.InsertMove(reg, r.Reg, r.Type) + } else { + load := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg( + // -stackSlotSize because the stack pointer is not yet decreased. + uint32(a.ArgStackSize+r.Offset-stackSlotSize), rspVReg)) + switch r.Type { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, mem, reg) + case ssa.TypeI64: + load.asMov64MR(mem, reg) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, mem, reg) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, mem, reg) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, mem, reg) + default: + panic("BUG") + } + m.insert(load) + } +} + +// InsertMove implements backend.Machine. +func (m *machine) InsertMove(dst, src regalloc.VReg, typ ssa.Type) { + switch typ { + case ssa.TypeI32, ssa.TypeI64: + i := m.allocateInstr().asMovRR(src, dst, typ.Bits() == 64) + m.insert(i) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + var op sseOpcode + switch typ { + case ssa.TypeF32: + op = sseOpcodeMovss + case ssa.TypeF64: + op = sseOpcodeMovsd + case ssa.TypeV128: + op = sseOpcodeMovdqa + } + i := m.allocateInstr().asXmmUnaryRmR(op, newOperandReg(src), dst) + m.insert(i) + default: + panic("BUG") + } +} + +// Format implements backend.Machine. +func (m *machine) Format() string { + begins := map[*instruction]label{} + for l := label(0); l < m.nextLabel; l++ { + pos := m.labelPositionPool.Get(int(l)) + if pos != nil { + begins[pos.begin] = l + } + } + + var lines []string + for cur := m.rootInstr; cur != nil; cur = cur.next { + if l, ok := begins[cur]; ok { + var labelStr string + if l <= m.maxSSABlockID { + labelStr = fmt.Sprintf("%s (SSA Block: blk%d):", l, l) + } else { + labelStr = fmt.Sprintf("%s:", l) + } + lines = append(lines, labelStr) + } + if cur.kind == nop0 { + continue + } + lines = append(lines, "\t"+cur.String()) + } + for _, vc := range m.consts { + if vc._var == nil { + lines = append(lines, fmt.Sprintf("%s: const [%d %d]", vc.label, vc.lo, vc.hi)) + } else { + lines = append(lines, fmt.Sprintf("%s: const %#x", vc.label, vc._var)) + } + } + return "\n" + strings.Join(lines, "\n") + "\n" +} + +func (m *machine) encodeWithoutSSA(root *instruction) { + m.labelResolutionPends = m.labelResolutionPends[:0] + bufPtr := m.c.BufPtr() + for cur := root; cur != nil; cur = cur.next { + offset := int64(len(*bufPtr)) + if cur.kind == nop0 { + l := cur.nop0Label() + pos := m.labelPositionPool.Get(int(l)) + if pos != nil { + pos.binaryOffset = offset + } + } + + needLabelResolution := cur.encode(m.c) + if needLabelResolution { + m.labelResolutionPends = append(m.labelResolutionPends, + labelResolutionPend{instr: cur, imm32Offset: int64(len(*bufPtr)) - 4}, + ) + } + } + + for i := range m.labelResolutionPends { + p := &m.labelResolutionPends[i] + switch p.instr.kind { + case jmp, jmpIf, lea: + target := p.instr.jmpLabel() + targetOffset := m.labelPositionPool.Get(int(target)).binaryOffset + imm32Offset := p.imm32Offset + jmpOffset := int32(targetOffset - (p.imm32Offset + 4)) // +4 because RIP points to the next instruction. + binary.LittleEndian.PutUint32((*bufPtr)[imm32Offset:], uint32(jmpOffset)) + default: + panic("BUG") + } + } +} + +// Encode implements backend.Machine Encode. +func (m *machine) Encode(ctx context.Context) (err error) { + bufPtr := m.c.BufPtr() + + var fn string + var fnIndex int + var labelPosToLabel map[*labelPosition]label + if wazevoapi.PerfMapEnabled { + fn = wazevoapi.GetCurrentFunctionName(ctx) + labelPosToLabel = make(map[*labelPosition]label) + for i := 0; i <= m.labelPositionPool.MaxIDEncountered(); i++ { + pos := m.labelPositionPool.Get(i) + labelPosToLabel[pos] = label(i) + } + fnIndex = wazevoapi.GetCurrentFunctionIndex(ctx) + } + + m.labelResolutionPends = m.labelResolutionPends[:0] + for _, pos := range m.orderedSSABlockLabelPos { + offset := int64(len(*bufPtr)) + pos.binaryOffset = offset + for cur := pos.begin; cur != pos.end.next; cur = cur.next { + offset := int64(len(*bufPtr)) + + switch cur.kind { + case nop0: + l := cur.nop0Label() + if pos := m.labelPositionPool.Get(int(l)); pos != nil { + pos.binaryOffset = offset + } + case sourceOffsetInfo: + m.c.AddSourceOffsetInfo(offset, cur.sourceOffsetInfo()) + } + + needLabelResolution := cur.encode(m.c) + if needLabelResolution { + m.labelResolutionPends = append(m.labelResolutionPends, + labelResolutionPend{instr: cur, instrOffset: offset, imm32Offset: int64(len(*bufPtr)) - 4}, + ) + } + } + + if wazevoapi.PerfMapEnabled { + l := labelPosToLabel[pos] + size := int64(len(*bufPtr)) - offset + wazevoapi.PerfMap.AddModuleEntry(fnIndex, offset, uint64(size), fmt.Sprintf("%s:::::%s", fn, l)) + } + } + + for i := range m.consts { + offset := int64(len(*bufPtr)) + vc := &m.consts[i] + vc.labelPos.binaryOffset = offset + if vc._var == nil { + lo, hi := vc.lo, vc.hi + m.c.Emit8Bytes(lo) + m.c.Emit8Bytes(hi) + } else { + for _, b := range vc._var { + m.c.EmitByte(b) + } + } + } + + buf := *bufPtr + for i := range m.labelResolutionPends { + p := &m.labelResolutionPends[i] + switch p.instr.kind { + case jmp, jmpIf, lea, xmmUnaryRmR: + target := p.instr.jmpLabel() + targetOffset := m.labelPositionPool.Get(int(target)).binaryOffset + imm32Offset := p.imm32Offset + jmpOffset := int32(targetOffset - (p.imm32Offset + 4)) // +4 because RIP points to the next instruction. + binary.LittleEndian.PutUint32(buf[imm32Offset:], uint32(jmpOffset)) + case jmpTableIsland: + tableBegin := p.instrOffset + // Each entry is the offset from the beginning of the jmpTableIsland instruction in 8 bytes. + targets := m.jmpTableTargets[p.instr.u1] + for i, l := range targets { + targetOffset := m.labelPositionPool.Get(int(l)).binaryOffset + jmpOffset := targetOffset - tableBegin + binary.LittleEndian.PutUint64(buf[tableBegin+int64(i)*8:], uint64(jmpOffset)) + } + default: + panic("BUG") + } + } + return +} + +// ResolveRelocations implements backend.Machine. +func (m *machine) ResolveRelocations(refToBinaryOffset []int, _ int, binary []byte, relocations []backend.RelocationInfo, _ []int) { + for _, r := range relocations { + offset := r.Offset + calleeFnOffset := refToBinaryOffset[r.FuncRef] + // offset is the offset of the last 4 bytes of the call instruction. + callInstrOffsetBytes := binary[offset : offset+4] + diff := int64(calleeFnOffset) - (offset + 4) // +4 because we want the offset of the next instruction (In x64, RIP always points to the next instruction). + callInstrOffsetBytes[0] = byte(diff) + callInstrOffsetBytes[1] = byte(diff >> 8) + callInstrOffsetBytes[2] = byte(diff >> 16) + callInstrOffsetBytes[3] = byte(diff >> 24) + } +} + +// CallTrampolineIslandInfo implements backend.Machine CallTrampolineIslandInfo. +func (m *machine) CallTrampolineIslandInfo(_ int) (_, _ int, _ error) { return } + +func (m *machine) lowerIcmpToFlag(xd, yd backend.SSAValueDefinition, _64 bool) { + x := m.getOperand_Reg(xd) + y := m.getOperand_Mem_Imm32_Reg(yd) + cmp := m.allocateInstr().asCmpRmiR(true, y, x.reg(), _64) + m.insert(cmp) +} + +func (m *machine) lowerFcmpToFlags(instr *ssa.Instruction) (f1, f2 cond, and bool) { + x, y, c := instr.FcmpData() + switch c { + case ssa.FloatCmpCondEqual: + f1, f2 = condNP, condZ + and = true + case ssa.FloatCmpCondNotEqual: + f1, f2 = condP, condNZ + case ssa.FloatCmpCondLessThan: + f1 = condFromSSAFloatCmpCond(ssa.FloatCmpCondGreaterThan) + f2 = condInvalid + x, y = y, x + case ssa.FloatCmpCondLessThanOrEqual: + f1 = condFromSSAFloatCmpCond(ssa.FloatCmpCondGreaterThanOrEqual) + f2 = condInvalid + x, y = y, x + default: + f1 = condFromSSAFloatCmpCond(c) + f2 = condInvalid + } + + var opc sseOpcode + if x.Type() == ssa.TypeF32 { + opc = sseOpcodeUcomiss + } else { + opc = sseOpcodeUcomisd + } + + xr := m.getOperand_Reg(m.c.ValueDefinition(x)) + yr := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + m.insert(m.allocateInstr().asXmmCmpRmR(opc, yr, xr.reg())) + return +} + +// allocateInstr allocates an instruction. +func (m *machine) allocateInstr() *instruction { + instr := m.instrPool.Allocate() + if !m.regAllocStarted { + instr.addedBeforeRegAlloc = true + } + return instr +} + +func (m *machine) allocateNop() *instruction { + instr := m.allocateInstr() + instr.kind = nop0 + return instr +} + +func (m *machine) insert(i *instruction) { + m.pendingInstructions = append(m.pendingInstructions, i) +} + +func (m *machine) allocateBrTarget() (nop *instruction, l label) { //nolint + l, pos := m.allocateLabel() + nop = m.allocateInstr() + nop.asNop0WithLabel(l) + pos.begin, pos.end = nop, nop + return +} + +func (m *machine) allocateLabel() (label, *labelPosition) { + l := m.nextLabel + pos := m.labelPositionPool.GetOrAllocate(int(l)) + m.nextLabel++ + return l, pos +} + +func (m *machine) getVRegSpillSlotOffsetFromSP(id regalloc.VRegID, size byte) int64 { + offset, ok := m.spillSlots[id] + if !ok { + offset = m.spillSlotSize + m.spillSlots[id] = offset + m.spillSlotSize += int64(size) + } + return offset +} + +func (m *machine) copyTo(src regalloc.VReg, dst regalloc.VReg) { + mov := m.allocateInstr() + if src.RegType() == regalloc.RegTypeInt { + mov.asMovRR(src, dst, true) + } else { + mov.asXmmUnaryRmR(sseOpcodeMovdqu, newOperandReg(src), dst) + } + m.insert(mov) +} + +func (m *machine) copyToTmp(v regalloc.VReg) regalloc.VReg { + typ := m.c.TypeOf(v) + tmp := m.c.AllocateVReg(typ) + m.copyTo(v, tmp) + return tmp +} + +func (m *machine) requiredStackSize() int64 { + return m.maxRequiredStackSizeForCalls + + m.frameSize() + + 16 + // Need for stack checking. + 16 // return address and the caller RBP. +} + +func (m *machine) frameSize() int64 { + s := m.clobberedRegSlotSize() + m.spillSlotSize + if s&0xf != 0 { + panic(fmt.Errorf("BUG: frame size %d is not 16-byte aligned", s)) + } + return s +} + +func (m *machine) clobberedRegSlotSize() int64 { + return int64(len(m.clobberedRegs) * 16) +} + +func (m *machine) lowerIDivRem(si *ssa.Instruction, isDiv bool, signed bool) { + x, y, execCtx := si.Arg3() + + dividend := m.getOperand_Reg(m.c.ValueDefinition(x)) + divisor := m.getOperand_Reg(m.c.ValueDefinition(y)) + ctxVReg := m.c.VRegOf(execCtx) + tmpGp := m.c.AllocateVReg(si.Return().Type()) + + m.copyTo(dividend.reg(), raxVReg) + m.insert(m.allocateInstr().asDefineUninitializedReg(rdxVReg)) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp)) + seq := m.allocateInstr().asIdivRemSequence(ctxVReg, divisor.reg(), tmpGp, isDiv, signed, x.Type().Bits() == 64) + m.insert(seq) + rd := m.c.VRegOf(si.Return()) + if isDiv { + m.copyTo(raxVReg, rd) + } else { + m.copyTo(rdxVReg, rd) + } +} + +func (m *machine) lowerIDivRemSequenceAfterRegAlloc(i *instruction) { + execCtx, divisor, tmpGp, isDiv, signed, _64 := i.idivRemSequenceData() + + dividend := raxVReg + + // Ensure yr is not zero. + test := m.allocateInstr() + test.asCmpRmiR(false, newOperandReg(divisor), divisor, _64) + m.insert(test) + + jnz := m.allocateInstr() + m.insert(jnz) + + nz := m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerDivisionByZero) + + // If not zero, we can proceed with the division. + jnz.asJmpIf(condNZ, newOperandLabel(nz)) + + var ifRemNeg1 *instruction + if signed { + var neg1 uint64 + if _64 { + neg1 = 0xffffffffffffffff + } else { + neg1 = 0xffffffff + } + m.lowerIconst(tmpGp, neg1, _64) + + if isDiv { + // For signed division, we have to have branches for "math.MinInt{32,64} / -1" + // case which results in the floating point exception via division error as + // the resulting value exceeds the maximum of signed int. + + // First, we check if the divisor is -1. + cmp := m.allocateInstr() + cmp.asCmpRmiR(true, newOperandReg(tmpGp), divisor, _64) + m.insert(cmp) + + ifNotNeg1 := m.allocateInstr() + m.insert(ifNotNeg1) + + var minInt uint64 + if _64 { + minInt = 0x8000000000000000 + } else { + minInt = 0x80000000 + } + m.lowerIconst(tmpGp, minInt, _64) + + // Next we check if the quotient is the most negative value for the signed integer, i.e. + // if we are trying to do (math.MinInt32 / -1) or (math.MinInt64 / -1) respectively. + cmp2 := m.allocateInstr() + cmp2.asCmpRmiR(true, newOperandReg(tmpGp), dividend, _64) + m.insert(cmp2) + + ifNotMinInt := m.allocateInstr() + m.insert(ifNotMinInt) + + // Trap if we are trying to do (math.MinInt32 / -1) or (math.MinInt64 / -1), + // as that is the overflow in division as the result becomes 2^31 which is larger than + // the maximum of signed 32-bit int (2^31-1). + end := m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + ifNotNeg1.asJmpIf(condNZ, newOperandLabel(end)) + ifNotMinInt.asJmpIf(condNZ, newOperandLabel(end)) + } else { + // If it is remainder, zeros DX register and compare the divisor to -1. + xor := m.allocateInstr().asZeros(rdxVReg) + m.insert(xor) + + // We check if the divisor is -1. + cmp := m.allocateInstr() + cmp.asCmpRmiR(true, newOperandReg(tmpGp), divisor, _64) + m.insert(cmp) + + ifRemNeg1 = m.allocateInstr() + m.insert(ifRemNeg1) + } + + // Sign-extend DX register to have 2*x.Type().Bits() dividend over DX and AX registers. + sed := m.allocateInstr() + sed.asSignExtendData(_64) + m.insert(sed) + } else { + // Zeros DX register to have 2*x.Type().Bits() dividend over DX and AX registers. + zeros := m.allocateInstr().asZeros(rdxVReg) + m.insert(zeros) + } + + div := m.allocateInstr() + div.asDiv(newOperandReg(divisor), signed, _64) + m.insert(div) + + nop, end := m.allocateBrTarget() + m.insert(nop) + // If we are compiling a Rem instruction, when the divisor is -1 we land at the end of the function. + if ifRemNeg1 != nil { + ifRemNeg1.asJmpIf(condZ, newOperandLabel(end)) + } +} + +func (m *machine) lowerRound(instr *ssa.Instruction, imm roundingMode) { + x := instr.Arg() + if !x.Type().IsFloat() { + panic("BUG?") + } + var op sseOpcode + if x.Type().Bits() == 64 { + op = sseOpcodeRoundsd + } else { + op = sseOpcodeRoundss + } + + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Mem_Reg(xDef) + rd := m.c.VRegOf(instr.Return()) + + xmm := m.allocateInstr().asXmmUnaryRmRImm(op, uint8(imm), rm, rd) + m.insert(xmm) +} + +func (m *machine) lowerFminFmax(instr *ssa.Instruction) { + x, y := instr.Arg2() + if !x.Type().IsFloat() { + panic("BUG?") + } + + _64 := x.Type().Bits() == 64 + isMin := instr.Opcode() == ssa.OpcodeFmin + var minMaxOp sseOpcode + + switch { + case _64 && isMin: + minMaxOp = sseOpcodeMinpd + case _64 && !isMin: + minMaxOp = sseOpcodeMaxpd + case !_64 && isMin: + minMaxOp = sseOpcodeMinps + case !_64 && !isMin: + minMaxOp = sseOpcodeMaxps + } + + xDef, yDef := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + rm := m.getOperand_Reg(xDef) + // We cannot ensure that y is aligned to 16 bytes, so we have to use it on reg. + rn := m.getOperand_Reg(yDef) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.copyToTmp(rm.reg()) + + // Check if this is (either x1 or x2 is NaN) or (x1 equals x2) case. + cmp := m.allocateInstr() + if _64 { + cmp.asXmmCmpRmR(sseOpcodeUcomisd, rn, tmp) + } else { + cmp.asXmmCmpRmR(sseOpcodeUcomiss, rn, tmp) + } + m.insert(cmp) + + // At this point, we have the three cases of conditional flags below + // (See https://www.felixcloutier.com/x86/ucomiss#operation for detail.) + // + // 1) Two values are NaN-free and different: All flags are cleared. + // 2) Two values are NaN-free and equal: Only ZF flags is set. + // 3) One of Two values is NaN: ZF, PF and CF flags are set. + + // Jump instruction to handle 1) case by checking the ZF flag + // as ZF is only set for 2) and 3) cases. + nanFreeOrDiffJump := m.allocateInstr() + m.insert(nanFreeOrDiffJump) + + // Start handling 2) and 3). + + // Jump if one of two values is NaN by checking the parity flag (PF). + ifIsNan := m.allocateInstr() + m.insert(ifIsNan) + + // Start handling 2) NaN-free and equal. + + // Before we exit this case, we have to ensure that positive zero (or negative zero for min instruction) is + // returned if two values are positive and negative zeros. + var op sseOpcode + switch { + case !_64 && isMin: + op = sseOpcodeOrps + case _64 && isMin: + op = sseOpcodeOrpd + case !_64 && !isMin: + op = sseOpcodeAndps + case _64 && !isMin: + op = sseOpcodeAndpd + } + orAnd := m.allocateInstr() + orAnd.asXmmRmR(op, rn, tmp) + m.insert(orAnd) + + // Done, jump to end. + sameExitJump := m.allocateInstr() + m.insert(sameExitJump) + + // Start handling 3) either is NaN. + isNanTarget, isNan := m.allocateBrTarget() + m.insert(isNanTarget) + ifIsNan.asJmpIf(condP, newOperandLabel(isNan)) + + // We emit the ADD instruction to produce the NaN in tmp. + add := m.allocateInstr() + if _64 { + add.asXmmRmR(sseOpcodeAddsd, rn, tmp) + } else { + add.asXmmRmR(sseOpcodeAddss, rn, tmp) + } + m.insert(add) + + // Exit from the NaN case branch. + nanExitJmp := m.allocateInstr() + m.insert(nanExitJmp) + + // Start handling 1). + doMinMaxTarget, doMinMax := m.allocateBrTarget() + m.insert(doMinMaxTarget) + nanFreeOrDiffJump.asJmpIf(condNZ, newOperandLabel(doMinMax)) + + // Now handle the NaN-free and different values case. + minMax := m.allocateInstr() + minMax.asXmmRmR(minMaxOp, rn, tmp) + m.insert(minMax) + + endNop, end := m.allocateBrTarget() + m.insert(endNop) + nanExitJmp.asJmp(newOperandLabel(end)) + sameExitJump.asJmp(newOperandLabel(end)) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerFcopysign(instr *ssa.Instruction) { + x, y := instr.Arg2() + if !x.Type().IsFloat() { + panic("BUG") + } + + _64 := x.Type().Bits() == 64 + + xDef, yDef := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + rm := m.getOperand_Reg(xDef) + rn := m.getOperand_Reg(yDef) + rd := m.c.VRegOf(instr.Return()) + + // Clear the non-sign bits of src via AND with the mask. + var opAnd, opOr sseOpcode + var signMask uint64 + if _64 { + signMask, opAnd, opOr = 0x8000000000000000, sseOpcodeAndpd, sseOpcodeOrpd + } else { + signMask, opAnd, opOr = 0x80000000, sseOpcodeAndps, sseOpcodeOrps + } + + signBitReg := m.c.AllocateVReg(x.Type()) + m.lowerFconst(signBitReg, signMask, _64) + nonSignBitReg := m.c.AllocateVReg(x.Type()) + m.lowerFconst(nonSignBitReg, ^signMask, _64) + + // Extract the sign bits of rn. + and := m.allocateInstr().asXmmRmR(opAnd, rn, signBitReg) + m.insert(and) + + // Clear the sign bit of dst via AND with the non-sign bit mask. + xor := m.allocateInstr().asXmmRmR(opAnd, rm, nonSignBitReg) + m.insert(xor) + + // Copy the sign bits of src to dst via OR. + or := m.allocateInstr().asXmmRmR(opOr, newOperandReg(signBitReg), nonSignBitReg) + m.insert(or) + + m.copyTo(nonSignBitReg, rd) +} + +func (m *machine) lowerBitcast(instr *ssa.Instruction) { + x, dstTyp := instr.BitcastData() + srcTyp := x.Type() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + switch { + case srcTyp == ssa.TypeF32 && dstTyp == ssa.TypeI32: + cvt := m.allocateInstr().asXmmToGpr(sseOpcodeMovd, rn.reg(), rd, false) + m.insert(cvt) + case srcTyp == ssa.TypeI32 && dstTyp == ssa.TypeF32: + cvt := m.allocateInstr().asGprToXmm(sseOpcodeMovd, rn, rd, false) + m.insert(cvt) + case srcTyp == ssa.TypeF64 && dstTyp == ssa.TypeI64: + cvt := m.allocateInstr().asXmmToGpr(sseOpcodeMovq, rn.reg(), rd, true) + m.insert(cvt) + case srcTyp == ssa.TypeI64 && dstTyp == ssa.TypeF64: + cvt := m.allocateInstr().asGprToXmm(sseOpcodeMovq, rn, rd, true) + m.insert(cvt) + default: + panic(fmt.Sprintf("invalid bitcast from %s to %s", srcTyp, dstTyp)) + } +} + +func (m *machine) lowerFcvtToSint(ctxVReg, rn, rd regalloc.VReg, src64, dst64, sat bool) { + var tmpXmm regalloc.VReg + if dst64 { + tmpXmm = m.c.AllocateVReg(ssa.TypeF64) + } else { + tmpXmm = m.c.AllocateVReg(ssa.TypeF32) + } + + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpXmm)) + tmpGp, tmpGp2 := m.c.AllocateVReg(ssa.TypeI64), m.c.AllocateVReg(ssa.TypeI64) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp)) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp2)) + + m.insert(m.allocateFcvtToSintSequence(ctxVReg, rn, tmpGp, tmpGp2, tmpXmm, src64, dst64, sat)) + m.copyTo(tmpGp, rd) +} + +func (m *machine) lowerFcvtToSintSequenceAfterRegalloc(i *instruction) { + execCtx, src, tmpGp, tmpGp2, tmpXmm, src64, dst64, sat := i.fcvtToSintSequenceData() + var cmpOp, truncOp sseOpcode + if src64 { + cmpOp, truncOp = sseOpcodeUcomisd, sseOpcodeCvttsd2si + } else { + cmpOp, truncOp = sseOpcodeUcomiss, sseOpcodeCvttss2si + } + + trunc := m.allocateInstr() + trunc.asXmmToGpr(truncOp, src, tmpGp, dst64) + m.insert(trunc) + + // Check if the dst operand was INT_MIN, by checking it against 1. + cmp1 := m.allocateInstr() + cmp1.asCmpRmiR(true, newOperandImm32(1), tmpGp, dst64) + m.insert(cmp1) + + // If no overflow, then we are done. + doneTarget, done := m.allocateBrTarget() + ifNoOverflow := m.allocateInstr() + ifNoOverflow.asJmpIf(condNO, newOperandLabel(done)) + m.insert(ifNoOverflow) + + // Now, check for NaN. + cmpNan := m.allocateInstr() + cmpNan.asXmmCmpRmR(cmpOp, newOperandReg(src), src) + m.insert(cmpNan) + + // We allocate the "non-nan target" here, but we will insert it later. + notNanTarget, notNaN := m.allocateBrTarget() + ifNotNan := m.allocateInstr() + ifNotNan.asJmpIf(condNP, newOperandLabel(notNaN)) + m.insert(ifNotNan) + + if sat { + // If NaN and saturating, return 0. + zeroDst := m.allocateInstr().asZeros(tmpGp) + m.insert(zeroDst) + + jmpEnd := m.allocateInstr() + jmpEnd.asJmp(newOperandLabel(done)) + m.insert(jmpEnd) + + // Otherwise: + m.insert(notNanTarget) + + // Zero-out the tmp register. + zero := m.allocateInstr().asZeros(tmpXmm) + m.insert(zero) + + cmpXmm := m.allocateInstr().asXmmCmpRmR(cmpOp, newOperandReg(tmpXmm), src) + m.insert(cmpXmm) + + // if >= jump to end. + jmpEnd2 := m.allocateInstr() + jmpEnd2.asJmpIf(condB, newOperandLabel(done)) + m.insert(jmpEnd2) + + // Otherwise, saturate to INT_MAX. + if dst64 { + m.lowerIconst(tmpGp, math.MaxInt64, dst64) + } else { + m.lowerIconst(tmpGp, math.MaxInt32, dst64) + } + + } else { + + // If non-sat, NaN, trap. + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeInvalidConversionToInteger) + + // Otherwise, we will jump here. + m.insert(notNanTarget) + + // jump over trap if src larger than threshold + condAboveThreshold := condNB + + // The magic constants are various combination of minInt for int[32|64] represented as float[32|64]. + var minInt uint64 + switch { + case src64 && dst64: + minInt = 0xc3e0000000000000 + case src64 && !dst64: + condAboveThreshold = condNBE + minInt = 0xC1E0_0000_0020_0000 + case !src64 && dst64: + minInt = 0xDF00_0000 + case !src64 && !dst64: + minInt = 0xCF00_0000 + } + + loadToGP := m.allocateInstr().asImm(tmpGp2, minInt, src64) + m.insert(loadToGP) + + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpGp2), tmpXmm, src64) + m.insert(movToXmm) + + cmpXmm := m.allocateInstr().asXmmCmpRmR(cmpOp, newOperandReg(tmpXmm), src) + m.insert(cmpXmm) + + jmpIfLarger := m.allocateInstr() + checkPositiveTarget, checkPositive := m.allocateBrTarget() + jmpIfLarger.asJmpIf(condAboveThreshold, newOperandLabel(checkPositive)) + m.insert(jmpIfLarger) + + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + + // If positive, it was a real overflow. + m.insert(checkPositiveTarget) + + // Zero out the temp register. + xorpd := m.allocateInstr() + xorpd.asXmmRmR(sseOpcodeXorpd, newOperandReg(tmpXmm), tmpXmm) + m.insert(xorpd) + + pos := m.allocateInstr() + pos.asXmmCmpRmR(cmpOp, newOperandReg(src), tmpXmm) + m.insert(pos) + + // If >= jump to end. + jmp := m.allocateInstr().asJmpIf(condNB, newOperandLabel(done)) + m.insert(jmp) + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + } + + m.insert(doneTarget) +} + +func (m *machine) lowerFcvtToUint(ctxVReg, rn, rd regalloc.VReg, src64, dst64, sat bool) { + tmpXmm, tmpXmm2 := m.c.AllocateVReg(ssa.TypeF64), m.c.AllocateVReg(ssa.TypeF64) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpXmm)) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpXmm2)) + tmpGp, tmpGp2 := m.c.AllocateVReg(ssa.TypeI64), m.c.AllocateVReg(ssa.TypeI64) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp)) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp2)) + + m.insert(m.allocateFcvtToUintSequence( + ctxVReg, rn, tmpGp, tmpGp2, tmpXmm, tmpXmm2, src64, dst64, sat, + )) + m.copyTo(tmpGp, rd) +} + +func (m *machine) lowerFcvtToUintSequenceAfterRegalloc(i *instruction) { + execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2, src64, dst64, sat := i.fcvtToUintSequenceData() + + var subOp, cmpOp, truncOp sseOpcode + if src64 { + subOp, cmpOp, truncOp = sseOpcodeSubsd, sseOpcodeUcomisd, sseOpcodeCvttsd2si + } else { + subOp, cmpOp, truncOp = sseOpcodeSubss, sseOpcodeUcomiss, sseOpcodeCvttss2si + } + + doneTarget, done := m.allocateBrTarget() + + switch { + case src64 && dst64: + loadToGP := m.allocateInstr().asImm(tmpGp, 0x43e0000000000000, true) + m.insert(loadToGP) + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpGp), tmpXmm, true) + m.insert(movToXmm) + case src64 && !dst64: + loadToGP := m.allocateInstr().asImm(tmpGp, 0x41e0000000000000, true) + m.insert(loadToGP) + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpGp), tmpXmm, true) + m.insert(movToXmm) + case !src64 && dst64: + loadToGP := m.allocateInstr().asImm(tmpGp, 0x5f000000, false) + m.insert(loadToGP) + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpGp), tmpXmm, false) + m.insert(movToXmm) + case !src64 && !dst64: + loadToGP := m.allocateInstr().asImm(tmpGp, 0x4f000000, false) + m.insert(loadToGP) + movToXmm := m.allocateInstr().asGprToXmm(sseOpcodeMovq, newOperandReg(tmpGp), tmpXmm, false) + m.insert(movToXmm) + } + + cmp := m.allocateInstr() + cmp.asXmmCmpRmR(cmpOp, newOperandReg(tmpXmm), src) + m.insert(cmp) + + // If above `tmp` ("large threshold"), jump to `ifAboveThreshold` + ifAboveThresholdTarget, ifAboveThreshold := m.allocateBrTarget() + jmpIfAboveThreshold := m.allocateInstr() + jmpIfAboveThreshold.asJmpIf(condNB, newOperandLabel(ifAboveThreshold)) + m.insert(jmpIfAboveThreshold) + + ifNotNaNTarget, ifNotNaN := m.allocateBrTarget() + jmpIfNotNaN := m.allocateInstr() + jmpIfNotNaN.asJmpIf(condNP, newOperandLabel(ifNotNaN)) + m.insert(jmpIfNotNaN) + + // If NaN, handle the error condition. + if sat { + // On NaN, saturating, we just return 0. + zeros := m.allocateInstr().asZeros(tmpGp) + m.insert(zeros) + + jmpEnd := m.allocateInstr() + jmpEnd.asJmp(newOperandLabel(done)) + m.insert(jmpEnd) + } else { + // On NaN, non-saturating, we trap. + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeInvalidConversionToInteger) + } + + // If not NaN, land here. + m.insert(ifNotNaNTarget) + + // Truncation happens here. + + trunc := m.allocateInstr() + trunc.asXmmToGpr(truncOp, src, tmpGp, dst64) + m.insert(trunc) + + // Check if the result is negative. + cmpNeg := m.allocateInstr() + cmpNeg.asCmpRmiR(true, newOperandImm32(0), tmpGp, dst64) + m.insert(cmpNeg) + + // If non-neg, jump to end. + jmpIfNonNeg := m.allocateInstr() + jmpIfNonNeg.asJmpIf(condNL, newOperandLabel(done)) + m.insert(jmpIfNonNeg) + + if sat { + // If the input was "small" (< 2**(width -1)), the only way to get an integer + // overflow is because the input was too small: saturate to the min value, i.e. 0. + zeros := m.allocateInstr().asZeros(tmpGp) + m.insert(zeros) + + jmpEnd := m.allocateInstr() + jmpEnd.asJmp(newOperandLabel(done)) + m.insert(jmpEnd) + } else { + // If not saturating, trap. + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + } + + // If above the threshold, land here. + m.insert(ifAboveThresholdTarget) + + // tmpDiff := threshold - rn. + copySrc := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandReg(src), tmpXmm2) + m.insert(copySrc) + + sub := m.allocateInstr() + sub.asXmmRmR(subOp, newOperandReg(tmpXmm), tmpXmm2) // must be -0x8000000000000000 + m.insert(sub) + + trunc2 := m.allocateInstr() + trunc2.asXmmToGpr(truncOp, tmpXmm2, tmpGp, dst64) + m.insert(trunc2) + + // Check if the result is negative. + cmpNeg2 := m.allocateInstr().asCmpRmiR(true, newOperandImm32(0), tmpGp, dst64) + m.insert(cmpNeg2) + + ifNextLargeTarget, ifNextLarge := m.allocateBrTarget() + jmpIfNextLarge := m.allocateInstr() + jmpIfNextLarge.asJmpIf(condNL, newOperandLabel(ifNextLarge)) + m.insert(jmpIfNextLarge) + + if sat { + // The input was "large" (>= maxInt), so the only way to get an integer + // overflow is because the input was too large: saturate to the max value. + var maxInt uint64 + if dst64 { + maxInt = math.MaxUint64 + } else { + maxInt = math.MaxUint32 + } + m.lowerIconst(tmpGp, maxInt, dst64) + + jmpToEnd := m.allocateInstr() + jmpToEnd.asJmp(newOperandLabel(done)) + m.insert(jmpToEnd) + } else { + // If not saturating, trap. + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + } + + m.insert(ifNextLargeTarget) + + var op operand + if dst64 { + m.lowerIconst(tmpGp2, 0x8000000000000000, true) + op = newOperandReg(tmpGp2) + } else { + op = newOperandImm32(0x80000000) + } + + add := m.allocateInstr() + add.asAluRmiR(aluRmiROpcodeAdd, op, tmpGp, dst64) + m.insert(add) + + m.insert(doneTarget) +} + +func (m *machine) lowerFcvtFromSint(rn, rd operand, src64, dst64 bool) { + var op sseOpcode + if dst64 { + op = sseOpcodeCvtsi2sd + } else { + op = sseOpcodeCvtsi2ss + } + + trunc := m.allocateInstr() + trunc.asGprToXmm(op, rn, rd.reg(), src64) + m.insert(trunc) +} + +func (m *machine) lowerFcvtFromUint(rn, rd operand, src64, dst64 bool) { + var op sseOpcode + if dst64 { + op = sseOpcodeCvtsi2sd + } else { + op = sseOpcodeCvtsi2ss + } + + // Src is 32 bit, then we just perform the conversion with 64 bit width. + // + // See the following link for why we use 64bit conversion for unsigned 32bit integer sources: + // https://stackoverflow.com/questions/41495498/fpu-operations-generated-by-gcc-during-casting-integer-to-float. + // + // Here's the summary: + // >> CVTSI2SS is indeed designed for converting a signed integer to a scalar single-precision float, + // >> not an unsigned integer like you have here. So what gives? Well, a 64-bit processor has 64-bit wide + // >> registers available, so the unsigned 32-bit input values can be stored as signed 64-bit intermediate values, + // >> which allows CVTSI2SS to be used after all. + // + if !src64 { + // Before we convert, we have to clear the higher 32-bits of the 64-bit register + // to get the correct result. + tmp := m.c.AllocateVReg(ssa.TypeI32) + m.insert(m.allocateInstr().asMovzxRmR(extModeLQ, rn, tmp)) + m.insert(m.allocateInstr().asGprToXmm(op, newOperandReg(tmp), rd.reg(), true)) + return + } + + // If uint64, we have to do a bit more work. + endTarget, end := m.allocateBrTarget() + + var tmpXmm regalloc.VReg + if dst64 { + tmpXmm = m.c.AllocateVReg(ssa.TypeF64) + } else { + tmpXmm = m.c.AllocateVReg(ssa.TypeF32) + } + + // Check if the most significant bit (sign bit) is set. + test := m.allocateInstr() + test.asCmpRmiR(false, rn, rn.reg(), src64) + m.insert(test) + + // Jump if the sign bit is set. + ifSignTarget, ifSign := m.allocateBrTarget() + jmpIfNeg := m.allocateInstr() + jmpIfNeg.asJmpIf(condS, newOperandLabel(ifSign)) + m.insert(jmpIfNeg) + + // If the sign bit is not set, we could fit the unsigned int into float32/float64. + // So, we convert it to float and emit jump instruction to exit from this branch. + cvt := m.allocateInstr() + cvt.asGprToXmm(op, rn, tmpXmm, src64) + m.insert(cvt) + + // We are done, jump to end. + jmpEnd := m.allocateInstr() + jmpEnd.asJmp(newOperandLabel(end)) + m.insert(jmpEnd) + + // Now handling the case where sign-bit is set. + // We emit the following sequences: + // mov %rn, %tmp + // shr 1, %tmp + // mov %rn, %tmp2 + // and 1, %tmp2 + // or %tmp2, %tmp + // cvtsi2ss %tmp, %xmm0 + // addsd %xmm0, %xmm0 + m.insert(ifSignTarget) + + tmp := m.copyToTmp(rn.reg()) + shr := m.allocateInstr() + shr.asShiftR(shiftROpShiftRightLogical, newOperandImm32(1), tmp, src64) + m.insert(shr) + + tmp2 := m.copyToTmp(rn.reg()) + and := m.allocateInstr() + and.asAluRmiR(aluRmiROpcodeAnd, newOperandImm32(1), tmp2, src64) + m.insert(and) + + or := m.allocateInstr() + or.asAluRmiR(aluRmiROpcodeOr, newOperandReg(tmp2), tmp, src64) + m.insert(or) + + cvt2 := m.allocateInstr() + cvt2.asGprToXmm(op, newOperandReg(tmp), tmpXmm, src64) + m.insert(cvt2) + + addsd := m.allocateInstr() + if dst64 { + addsd.asXmmRmR(sseOpcodeAddsd, newOperandReg(tmpXmm), tmpXmm) + } else { + addsd.asXmmRmR(sseOpcodeAddss, newOperandReg(tmpXmm), tmpXmm) + } + m.insert(addsd) + + m.insert(endTarget) + m.copyTo(tmpXmm, rd.reg()) +} + +func (m *machine) lowerVanyTrue(instr *ssa.Instruction) { + x := instr.Arg() + rm := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.c.AllocateVReg(ssa.TypeI32) + + cmp := m.allocateInstr() + cmp.asXmmCmpRmR(sseOpcodePtest, rm, rm.reg()) + m.insert(cmp) + + setcc := m.allocateInstr() + setcc.asSetcc(condNZ, tmp) + m.insert(setcc) + + // Clear the irrelevant bits. + and := m.allocateInstr() + and.asAluRmiR(aluRmiROpcodeAnd, newOperandImm32(1), tmp, false) + m.insert(and) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerVallTrue(instr *ssa.Instruction) { + x, lane := instr.ArgWithLane() + var op sseOpcode + switch lane { + case ssa.VecLaneI8x16: + op = sseOpcodePcmpeqb + case ssa.VecLaneI16x8: + op = sseOpcodePcmpeqw + case ssa.VecLaneI32x4: + op = sseOpcodePcmpeqd + case ssa.VecLaneI64x2: + op = sseOpcodePcmpeqq + } + rm := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.c.AllocateVReg(ssa.TypeV128) + + zeros := m.allocateInstr() + zeros.asZeros(tmp) + m.insert(zeros) + + pcmp := m.allocateInstr() + pcmp.asXmmRmR(op, rm, tmp) + m.insert(pcmp) + + test := m.allocateInstr() + test.asXmmCmpRmR(sseOpcodePtest, newOperandReg(tmp), tmp) + m.insert(test) + + tmp2 := m.c.AllocateVReg(ssa.TypeI32) + + setcc := m.allocateInstr() + setcc.asSetcc(condZ, tmp2) + m.insert(setcc) + + // Clear the irrelevant bits. + and := m.allocateInstr() + and.asAluRmiR(aluRmiROpcodeAnd, newOperandImm32(1), tmp2, false) + m.insert(and) + + m.copyTo(tmp2, rd) +} + +func (m *machine) lowerVhighBits(instr *ssa.Instruction) { + x, lane := instr.ArgWithLane() + rm := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + switch lane { + case ssa.VecLaneI8x16: + mov := m.allocateInstr() + mov.asXmmToGpr(sseOpcodePmovmskb, rm.reg(), rd, false) + m.insert(mov) + + case ssa.VecLaneI16x8: + // When we have: + // R1 = [R1(w1), R1(w2), R1(w3), R1(w4), R1(w5), R1(w6), R1(w7), R1(v8)] + // R2 = [R2(w1), R2(w2), R2(w3), R2(v4), R2(w5), R2(w6), R2(w7), R2(v8)] + // where RX(wn) is n-th signed word (16-bit) of RX register, + // + // "PACKSSWB R1, R2" produces + // R1 = [ + // byte_sat(R1(w1)), byte_sat(R1(w2)), byte_sat(R1(w3)), byte_sat(R1(w4)), + // byte_sat(R1(w5)), byte_sat(R1(w6)), byte_sat(R1(w7)), byte_sat(R1(w8)), + // byte_sat(R2(w1)), byte_sat(R2(w2)), byte_sat(R2(w3)), byte_sat(R2(w4)), + // byte_sat(R2(w5)), byte_sat(R2(w6)), byte_sat(R2(w7)), byte_sat(R2(w8)), + // ] + // where R1 is the destination register, and + // byte_sat(w) = int8(w) if w fits as signed 8-bit, + // 0x80 if w is less than 0x80 + // 0x7F if w is greater than 0x7f + // + // See https://www.felixcloutier.com/x86/packsswb:packssdw for detail. + // + // Therefore, v.register ends up having i-th and (i+8)-th bit set if i-th lane is negative (for i in 0..8). + tmp := m.copyToTmp(rm.reg()) + res := m.c.AllocateVReg(ssa.TypeI32) + + pak := m.allocateInstr() + pak.asXmmRmR(sseOpcodePacksswb, rm, tmp) + m.insert(pak) + + mov := m.allocateInstr() + mov.asXmmToGpr(sseOpcodePmovmskb, tmp, res, false) + m.insert(mov) + + // Clear the higher bits than 8. + shr := m.allocateInstr() + shr.asShiftR(shiftROpShiftRightLogical, newOperandImm32(8), res, false) + m.insert(shr) + + m.copyTo(res, rd) + + case ssa.VecLaneI32x4: + mov := m.allocateInstr() + mov.asXmmToGpr(sseOpcodeMovmskps, rm.reg(), rd, true) + m.insert(mov) + + case ssa.VecLaneI64x2: + mov := m.allocateInstr() + mov.asXmmToGpr(sseOpcodeMovmskpd, rm.reg(), rd, true) + m.insert(mov) + } +} + +func (m *machine) lowerVbnot(instr *ssa.Instruction) { + x := instr.Arg() + xDef := m.c.ValueDefinition(x) + rm := m.getOperand_Reg(xDef) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.copyToTmp(rm.reg()) + tmp2 := m.c.AllocateVReg(ssa.TypeV128) + + // Ensure tmp2 is considered defined by regalloc. + m.insert(m.allocateInstr().asDefineUninitializedReg(tmp2)) + + // Set all bits on tmp register. + pak := m.allocateInstr() + pak.asXmmRmR(sseOpcodePcmpeqd, newOperandReg(tmp2), tmp2) + m.insert(pak) + + // Then XOR with tmp to reverse all bits on v.register. + xor := m.allocateInstr() + xor.asXmmRmR(sseOpcodePxor, newOperandReg(tmp2), tmp) + m.insert(xor) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerSplat(x, ret ssa.Value, lane ssa.VecLane) { + tmpDst := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpDst)) + + switch lane { + case ssa.VecLaneI8x16: + tmp := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmp)) + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrb, 0, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp), tmp)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePshufb, newOperandReg(tmp), tmpDst)) + case ssa.VecLaneI16x8: + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrw, 0, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrw, 1, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0, newOperandReg(tmpDst), tmpDst)) + case ssa.VecLaneI32x4: + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrd, 0, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0, newOperandReg(tmpDst), tmpDst)) + case ssa.VecLaneI64x2: + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 0, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 1, xx, tmpDst)) + case ssa.VecLaneF32x4: + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeInsertps, 0, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0, newOperandReg(tmpDst), tmpDst)) + case ssa.VecLaneF64x2: + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovsd, xx, tmpDst)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMovlhps, xx, tmpDst)) + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.copyTo(tmpDst, m.c.VRegOf(ret)) +} + +func (m *machine) lowerShuffle(x, y ssa.Value, lo, hi uint64, ret ssa.Value) { + var xMask, yMask [2]uint64 + for i := 0; i < 8; i++ { + loLane := byte(lo >> (i * 8)) + if loLane < 16 { + xMask[0] |= uint64(loLane) << (i * 8) + yMask[0] |= uint64(0x80) << (i * 8) + } else { + xMask[0] |= uint64(0x80) << (i * 8) + yMask[0] |= uint64(loLane-16) << (i * 8) + } + hiLane := byte(hi >> (i * 8)) + if hiLane < 16 { + xMask[1] |= uint64(hiLane) << (i * 8) + yMask[1] |= uint64(0x80) << (i * 8) + } else { + xMask[1] |= uint64(0x80) << (i * 8) + yMask[1] |= uint64(hiLane-16) << (i * 8) + } + } + + xl, xmaskPos := m.allocateLabel() + m.consts = append(m.consts, _const{lo: xMask[0], hi: xMask[1], label: xl, labelPos: xmaskPos}) + yl, ymaskPos := m.allocateLabel() + m.consts = append(m.consts, _const{lo: yMask[0], hi: yMask[1], label: yl, labelPos: ymaskPos}) + + xx, yy := m.getOperand_Reg(m.c.ValueDefinition(x)), m.getOperand_Reg(m.c.ValueDefinition(y)) + tmpX, tmpY := m.copyToTmp(xx.reg()), m.copyToTmp(yy.reg()) + + // Apply mask to X. + tmp := m.c.AllocateVReg(ssa.TypeV128) + loadMaskLo := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(xl)), tmp) + m.insert(loadMaskLo) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePshufb, newOperandReg(tmp), tmpX)) + + // Apply mask to Y. + loadMaskHi := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(yl)), tmp) + m.insert(loadMaskHi) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePshufb, newOperandReg(tmp), tmpY)) + + // Combine the results. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeOrps, newOperandReg(tmpX), tmpY)) + + m.copyTo(tmpY, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVbBinOpUnaligned(op sseOpcode, x, y, ret ssa.Value) { + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rm := m.getOperand_Reg(m.c.ValueDefinition(y)) + rd := m.c.VRegOf(ret) + + tmp := m.copyToTmp(rn.reg()) + + binOp := m.allocateInstr() + binOp.asXmmRmR(op, rm, tmp) + m.insert(binOp) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerVbBinOp(op sseOpcode, x, y, ret ssa.Value) { + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rm := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + rd := m.c.VRegOf(ret) + + tmp := m.copyToTmp(rn.reg()) + + binOp := m.allocateInstr() + binOp.asXmmRmR(op, rm, tmp) + m.insert(binOp) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerVFcmp(x, y ssa.Value, c ssa.FloatCmpCond, ret ssa.Value, lane ssa.VecLane) { + var cmpOp sseOpcode + switch lane { + case ssa.VecLaneF32x4: + cmpOp = sseOpcodeCmpps + case ssa.VecLaneF64x2: + cmpOp = sseOpcodeCmppd + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + xx, yy := m.c.ValueDefinition(x), m.c.ValueDefinition(y) + var cmpImm cmpPred + switch c { + case ssa.FloatCmpCondGreaterThan: + yy, xx = xx, yy + cmpImm = cmpPredLT_OS + case ssa.FloatCmpCondGreaterThanOrEqual: + yy, xx = xx, yy + cmpImm = cmpPredLE_OS + case ssa.FloatCmpCondEqual: + cmpImm = cmpPredEQ_OQ + case ssa.FloatCmpCondNotEqual: + cmpImm = cmpPredNEQ_UQ + case ssa.FloatCmpCondLessThan: + cmpImm = cmpPredLT_OS + case ssa.FloatCmpCondLessThanOrEqual: + cmpImm = cmpPredLE_OS + default: + panic(fmt.Sprintf("invalid float comparison condition: %s", c)) + } + + tmp := m.c.AllocateVReg(ssa.TypeV128) + xxx := m.getOperand_Mem_Reg(xx) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, xxx, tmp)) + + rm := m.getOperand_Mem_Reg(yy) + m.insert(m.allocateInstr().asXmmRmRImm(cmpOp, byte(cmpImm), rm, tmp)) + + m.copyTo(tmp, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVIcmp(x, y ssa.Value, c ssa.IntegerCmpCond, ret ssa.Value, lane ssa.VecLane) { + var eq, gt, maxu, minu, mins sseOpcode + switch lane { + case ssa.VecLaneI8x16: + eq, gt, maxu, minu, mins = sseOpcodePcmpeqb, sseOpcodePcmpgtb, sseOpcodePmaxub, sseOpcodePminub, sseOpcodePminsb + case ssa.VecLaneI16x8: + eq, gt, maxu, minu, mins = sseOpcodePcmpeqw, sseOpcodePcmpgtw, sseOpcodePmaxuw, sseOpcodePminuw, sseOpcodePminsw + case ssa.VecLaneI32x4: + eq, gt, maxu, minu, mins = sseOpcodePcmpeqd, sseOpcodePcmpgtd, sseOpcodePmaxud, sseOpcodePminud, sseOpcodePminsd + case ssa.VecLaneI64x2: + eq, gt = sseOpcodePcmpeqq, sseOpcodePcmpgtq + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + tmp := m.c.AllocateVReg(ssa.TypeV128) + var op operand + switch c { + case ssa.IntegerCmpCondSignedLessThanOrEqual: + if lane == ssa.VecLaneI64x2 { + x := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + // Copy x to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, x, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + } else { + y := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + // Copy y to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, y, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + } + case ssa.IntegerCmpCondSignedGreaterThanOrEqual: + if lane == ssa.VecLaneI64x2 { + y := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + // Copy y to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, y, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + } else { + x := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + // Copy x to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, x, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + } + case ssa.IntegerCmpCondSignedLessThan, ssa.IntegerCmpCondUnsignedLessThan, ssa.IntegerCmpCondUnsignedLessThanOrEqual: + y := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + // Copy y to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, y, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + default: + x := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + // Copy x to tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, x, tmp)) + op = m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + } + + switch c { + case ssa.IntegerCmpCondEqual: + m.insert(m.allocateInstr().asXmmRmR(eq, op, tmp)) + case ssa.IntegerCmpCondNotEqual: + // First we compare for equality. + m.insert(m.allocateInstr().asXmmRmR(eq, op, tmp)) + // Then flip the bits. To do so, we set all bits on tmp2. + tmp2 := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmp2)) + m.insert(m.allocateInstr().asXmmRmR(eq, newOperandReg(tmp2), tmp2)) + // And then xor with tmp. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp2), tmp)) + case ssa.IntegerCmpCondSignedGreaterThan, ssa.IntegerCmpCondSignedLessThan: + m.insert(m.allocateInstr().asXmmRmR(gt, op, tmp)) + case ssa.IntegerCmpCondSignedGreaterThanOrEqual, ssa.IntegerCmpCondSignedLessThanOrEqual: + if lane == ssa.VecLaneI64x2 { + m.insert(m.allocateInstr().asXmmRmR(gt, op, tmp)) + // Then flip the bits. To do so, we set all bits on tmp2. + tmp2 := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmp2)) + m.insert(m.allocateInstr().asXmmRmR(eq, newOperandReg(tmp2), tmp2)) + // And then xor with tmp. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp2), tmp)) + } else { + // First take min of x and y. + m.insert(m.allocateInstr().asXmmRmR(mins, op, tmp)) + // Then compare for equality. + m.insert(m.allocateInstr().asXmmRmR(eq, op, tmp)) + } + case ssa.IntegerCmpCondUnsignedGreaterThan, ssa.IntegerCmpCondUnsignedLessThan: + // First maxu of x and y. + m.insert(m.allocateInstr().asXmmRmR(maxu, op, tmp)) + // Then compare for equality. + m.insert(m.allocateInstr().asXmmRmR(eq, op, tmp)) + // Then flip the bits. To do so, we set all bits on tmp2. + tmp2 := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmp2)) + m.insert(m.allocateInstr().asXmmRmR(eq, newOperandReg(tmp2), tmp2)) + // And then xor with tmp. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp2), tmp)) + case ssa.IntegerCmpCondUnsignedGreaterThanOrEqual, ssa.IntegerCmpCondUnsignedLessThanOrEqual: + m.insert(m.allocateInstr().asXmmRmR(minu, op, tmp)) + m.insert(m.allocateInstr().asXmmRmR(eq, op, tmp)) + default: + panic("BUG") + } + + m.copyTo(tmp, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVbandnot(instr *ssa.Instruction, op sseOpcode) { + x, y := instr.Arg2() + xDef := m.c.ValueDefinition(x) + yDef := m.c.ValueDefinition(y) + rm, rn := m.getOperand_Reg(xDef), m.getOperand_Reg(yDef) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.copyToTmp(rn.reg()) + + // pandn between rn, rm. + pand := m.allocateInstr() + pand.asXmmRmR(sseOpcodePandn, rm, tmp) + m.insert(pand) + + m.copyTo(tmp, rd) +} + +func (m *machine) lowerVbitselect(instr *ssa.Instruction) { + c, x, y := instr.SelectData() + xDef := m.c.ValueDefinition(x) + yDef := m.c.ValueDefinition(y) + rm, rn := m.getOperand_Reg(xDef), m.getOperand_Reg(yDef) + creg := m.getOperand_Reg(m.c.ValueDefinition(c)) + rd := m.c.VRegOf(instr.Return()) + + tmpC := m.copyToTmp(creg.reg()) + tmpX := m.copyToTmp(rm.reg()) + + // And between c, x (overwrites x). + pand := m.allocateInstr() + pand.asXmmRmR(sseOpcodePand, creg, tmpX) + m.insert(pand) + + // Andn between y, c (overwrites c). + pandn := m.allocateInstr() + pandn.asXmmRmR(sseOpcodePandn, rn, tmpC) + m.insert(pandn) + + por := m.allocateInstr() + por.asXmmRmR(sseOpcodePor, newOperandReg(tmpC), tmpX) + m.insert(por) + + m.copyTo(tmpX, rd) +} + +func (m *machine) lowerVFmin(instr *ssa.Instruction) { + x, y, lane := instr.Arg2WithLane() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rm := m.getOperand_Reg(m.c.ValueDefinition(y)) + rd := m.c.VRegOf(instr.Return()) + + var min, cmp, andn, or, srl /* shift right logical */ sseOpcode + var shiftNumToInverseNaN uint32 + if lane == ssa.VecLaneF32x4 { + min, cmp, andn, or, srl, shiftNumToInverseNaN = sseOpcodeMinps, sseOpcodeCmpps, sseOpcodeAndnps, sseOpcodeOrps, sseOpcodePsrld, 0xa + } else { + min, cmp, andn, or, srl, shiftNumToInverseNaN = sseOpcodeMinpd, sseOpcodeCmppd, sseOpcodeAndnpd, sseOpcodeOrpd, sseOpcodePsrlq, 0xd + } + + tmp1 := m.copyToTmp(rn.reg()) + tmp2 := m.copyToTmp(rm.reg()) + + // tmp1=min(rn, rm) + minIns1 := m.allocateInstr() + minIns1.asXmmRmR(min, rn, tmp2) + m.insert(minIns1) + + // tmp2=min(rm, rn) + minIns2 := m.allocateInstr() + minIns2.asXmmRmR(min, rm, tmp1) + m.insert(minIns2) + + // tmp3:=tmp1=min(rn, rm) + tmp3 := m.copyToTmp(tmp1) + + // tmp1 = -0 if (rn == -0 || rm == -0) && rn != NaN && rm !=NaN + // NaN if rn == NaN || rm == NaN + // min(rm, rm) otherwise + orIns := m.allocateInstr() + orIns.asXmmRmR(or, newOperandReg(tmp2), tmp1) + m.insert(orIns) + + // tmp3 is originally min(rn,rm). + // tmp3 = 0^ (set all bits) if rn == NaN || rm == NaN + // 0 otherwise + cmpIns := m.allocateInstr() + cmpIns.asXmmRmRImm(cmp, uint8(cmpPredUNORD_Q), newOperandReg(tmp2), tmp3) + m.insert(cmpIns) + + // tmp1 = -0 if (rn == -0 || rm == -0) && rn != NaN && rm !=NaN + // ^0 if rn == NaN || rm == NaN + // min(v1, v2) otherwise + orIns2 := m.allocateInstr() + orIns2.asXmmRmR(or, newOperandReg(tmp3), tmp1) + m.insert(orIns2) + + // tmp3 = set all bits on the mantissa bits + // 0 otherwise + shift := m.allocateInstr() + shift.asXmmRmiReg(srl, newOperandImm32(shiftNumToInverseNaN), tmp3) + m.insert(shift) + + // tmp3 = tmp1 and !tmp3 + // = -0 if (rn == -0 || rm == -0) && rn != NaN && rm !=NaN + // set all bits on exponential and sign bit (== NaN) if rn == NaN || rm == NaN + // min(rn, rm) otherwise + andnIns := m.allocateInstr() + andnIns.asXmmRmR(andn, newOperandReg(tmp1), tmp3) + m.insert(andnIns) + + m.copyTo(tmp3, rd) +} + +func (m *machine) lowerVFmax(instr *ssa.Instruction) { + x, y, lane := instr.Arg2WithLane() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rm := m.getOperand_Reg(m.c.ValueDefinition(y)) + rd := m.c.VRegOf(instr.Return()) + + var max, cmp, andn, or, xor, sub, srl /* shift right logical */ sseOpcode + var shiftNumToInverseNaN uint32 + if lane == ssa.VecLaneF32x4 { + max, cmp, andn, or, xor, sub, srl, shiftNumToInverseNaN = sseOpcodeMaxps, sseOpcodeCmpps, sseOpcodeAndnps, sseOpcodeOrps, sseOpcodeXorps, sseOpcodeSubps, sseOpcodePsrld, 0xa + } else { + max, cmp, andn, or, xor, sub, srl, shiftNumToInverseNaN = sseOpcodeMaxpd, sseOpcodeCmppd, sseOpcodeAndnpd, sseOpcodeOrpd, sseOpcodeXorpd, sseOpcodeSubpd, sseOpcodePsrlq, 0xd + } + + tmp0 := m.copyToTmp(rm.reg()) + tmp1 := m.copyToTmp(rn.reg()) + + // tmp0=max(rn, rm) + maxIns1 := m.allocateInstr() + maxIns1.asXmmRmR(max, rn, tmp0) + m.insert(maxIns1) + + // tmp1=max(rm, rn) + maxIns2 := m.allocateInstr() + maxIns2.asXmmRmR(max, rm, tmp1) + m.insert(maxIns2) + + // tmp2=max(rm, rn) + tmp2 := m.copyToTmp(tmp1) + + // tmp2 = -0 if (rn == -0 && rm == 0) || (rn == 0 && rm == -0) + // 0 if (rn == 0 && rm == 0) + // -0 if (rn == -0 && rm == -0) + // v1^v2 if rn == NaN || rm == NaN + // 0 otherwise + xorInstr := m.allocateInstr() + xorInstr.asXmmRmR(xor, newOperandReg(tmp0), tmp2) + m.insert(xorInstr) + // tmp1 = -0 if (rn == -0 && rm == 0) || (rn == 0 && rm == -0) + // 0 if (rn == 0 && rm == 0) + // -0 if (rn == -0 && rm == -0) + // NaN if rn == NaN || rm == NaN + // max(v1, v2) otherwise + orInstr := m.allocateInstr() + orInstr.asXmmRmR(or, newOperandReg(tmp2), tmp1) + m.insert(orInstr) + + tmp3 := m.copyToTmp(tmp1) + + // tmp3 = 0 if (rn == -0 && rm == 0) || (rn == 0 && rm == -0) || (rn == 0 && rm == 0) + // -0 if (rn == -0 && rm == -0) + // NaN if rn == NaN || rm == NaN + // max(v1, v2) otherwise + // + // Note: -0 - (-0) = 0 (!= -0) in floating point operation. + subIns := m.allocateInstr() + subIns.asXmmRmR(sub, newOperandReg(tmp2), tmp3) + m.insert(subIns) + + // tmp1 = 0^ if rn == NaN || rm == NaN + cmpIns := m.allocateInstr() + cmpIns.asXmmRmRImm(cmp, uint8(cmpPredUNORD_Q), newOperandReg(tmp1), tmp1) + m.insert(cmpIns) + + // tmp1 = set all bits on the mantissa bits + // 0 otherwise + shift := m.allocateInstr() + shift.asXmmRmiReg(srl, newOperandImm32(shiftNumToInverseNaN), tmp1) + m.insert(shift) + + andnIns := m.allocateInstr() + andnIns.asXmmRmR(andn, newOperandReg(tmp3), tmp1) + m.insert(andnIns) + + m.copyTo(tmp1, rd) +} + +func (m *machine) lowerVFabs(instr *ssa.Instruction) { + x, lane := instr.ArgWithLane() + rm := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + tmp := m.c.AllocateVReg(ssa.TypeV128) + + def := m.allocateInstr() + def.asDefineUninitializedReg(tmp) + m.insert(def) + + // Set all bits on tmp. + pcmp := m.allocateInstr() + pcmp.asXmmRmR(sseOpcodePcmpeqd, newOperandReg(tmp), tmp) + m.insert(pcmp) + + switch lane { + case ssa.VecLaneF32x4: + // Shift right packed single floats by 1 to clear the sign bits. + shift := m.allocateInstr() + shift.asXmmRmiReg(sseOpcodePsrld, newOperandImm32(1), tmp) + m.insert(shift) + // Clear the sign bit of rm. + andp := m.allocateInstr() + andp.asXmmRmR(sseOpcodeAndpd, rm, tmp) + m.insert(andp) + case ssa.VecLaneF64x2: + // Shift right packed single floats by 1 to clear the sign bits. + shift := m.allocateInstr() + shift.asXmmRmiReg(sseOpcodePsrlq, newOperandImm32(1), tmp) + m.insert(shift) + // Clear the sign bit of rm. + andp := m.allocateInstr() + andp.asXmmRmR(sseOpcodeAndps, rm, tmp) + m.insert(andp) + } + + m.copyTo(tmp, rd) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_pro_epi_logue.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_pro_epi_logue.go new file mode 100644 index 00000000..e5372986 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_pro_epi_logue.go @@ -0,0 +1,303 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" +) + +// PostRegAlloc implements backend.Machine. +func (m *machine) PostRegAlloc() { + m.setupPrologue() + m.postRegAlloc() +} + +func (m *machine) setupPrologue() { + cur := m.rootInstr + prevInitInst := cur.next + + // At this point, we have the stack layout as follows: + // + // (high address) + // +-----------------+ <----- RBP (somewhere in the middle of the stack) + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | Return Addr | + // RSP ----> +-----------------+ + // (low address) + + // First, we push the RBP, and update the RBP to the current RSP. + // + // (high address) (high address) + // RBP ----> +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | ====> | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | Return Addr | | Return Addr | + // RSP ----> +-----------------+ | Caller_RBP | + // (low address) +-----------------+ <----- RSP, RBP + // + cur = m.setupRBPRSP(cur) + + if !m.stackBoundsCheckDisabled { + cur = m.insertStackBoundsCheck(m.requiredStackSize(), cur) + } + + // + // (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | xxxxx | | xxxxx | + // | Return Addr | | Return Addr | + // | Caller_RBP | ====> | Caller_RBP | + // RBP,RSP->+-----------------+ +-----------------+ <----- RBP + // (low address) | clobbered M | + // | clobbered 1 | + // | ........... | + // | clobbered 0 | + // +-----------------+ <----- RSP + // + if regs := m.clobberedRegs; len(regs) > 0 { + for i := range regs { + r := regs[len(regs)-1-i] // Reverse order. + if r.RegType() == regalloc.RegTypeInt { + cur = linkInstr(cur, m.allocateInstr().asPush64(newOperandReg(r))) + } else { + // Push the XMM register is not supported by the PUSH instruction. + cur = m.addRSP(-16, cur) + push := m.allocateInstr().asXmmMovRM( + sseOpcodeMovdqu, r, newOperandMem(m.newAmodeImmReg(0, rspVReg)), + ) + cur = linkInstr(cur, push) + } + } + } + + if size := m.spillSlotSize; size > 0 { + // Simply decrease the RSP to allocate the spill slots. + // sub $size, %rsp + cur = linkInstr(cur, m.allocateInstr().asAluRmiR(aluRmiROpcodeSub, newOperandImm32(uint32(size)), rspVReg, true)) + + // At this point, we have the stack layout as follows: + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <--- RBP + // | clobbered M | + // | ............ | + // | clobbered 1 | + // | clobbered 0 | + // | spill slot N | + // | ............ | + // | spill slot 0 | + // +-----------------+ <--- RSP + // (low address) + } + + linkInstr(cur, prevInitInst) +} + +// postRegAlloc does multiple things while walking through the instructions: +// 1. Inserts the epilogue code. +// 2. Removes the redundant copy instruction. +// 3. Inserts the dec/inc RSP instruction right before/after the call instruction. +// 4. Lowering that is supposed to be done after regalloc. +func (m *machine) postRegAlloc() { + for cur := m.rootInstr; cur != nil; cur = cur.next { + switch k := cur.kind; k { + case ret: + m.setupEpilogueAfter(cur.prev) + continue + case fcvtToSintSequence, fcvtToUintSequence: + m.pendingInstructions = m.pendingInstructions[:0] + if k == fcvtToSintSequence { + m.lowerFcvtToSintSequenceAfterRegalloc(cur) + } else { + m.lowerFcvtToUintSequenceAfterRegalloc(cur) + } + prev := cur.prev + next := cur.next + cur := prev + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + linkInstr(cur, next) + continue + case xmmCMov: + m.pendingInstructions = m.pendingInstructions[:0] + m.lowerXmmCmovAfterRegAlloc(cur) + prev := cur.prev + next := cur.next + cur := prev + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + linkInstr(cur, next) + continue + case idivRemSequence: + m.pendingInstructions = m.pendingInstructions[:0] + m.lowerIDivRemSequenceAfterRegAlloc(cur) + prev := cur.prev + next := cur.next + cur := prev + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + linkInstr(cur, next) + continue + case call, callIndirect: + // At this point, reg alloc is done, therefore we can safely insert dec/inc RPS instruction + // right before/after the call instruction. If this is done before reg alloc, the stack slot + // can point to the wrong location and therefore results in a wrong value. + call := cur + next := call.next + _, _, _, _, size := backend.ABIInfoFromUint64(call.u2) + if size > 0 { + dec := m.allocateInstr().asAluRmiR(aluRmiROpcodeSub, newOperandImm32(size), rspVReg, true) + linkInstr(call.prev, dec) + linkInstr(dec, call) + inc := m.allocateInstr().asAluRmiR(aluRmiROpcodeAdd, newOperandImm32(size), rspVReg, true) + linkInstr(call, inc) + linkInstr(inc, next) + } + continue + } + + // Removes the redundant copy instruction. + if cur.IsCopy() && cur.op1.reg().RealReg() == cur.op2.reg().RealReg() { + prev, next := cur.prev, cur.next + // Remove the copy instruction. + prev.next = next + if next != nil { + next.prev = prev + } + } + } +} + +func (m *machine) setupEpilogueAfter(cur *instruction) { + prevNext := cur.next + + // At this point, we have the stack layout as follows: + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <--- RBP + // | clobbered M | + // | ............ | + // | clobbered 1 | + // | clobbered 0 | + // | spill slot N | + // | ............ | + // | spill slot 0 | + // +-----------------+ <--- RSP + // (low address) + + if size := m.spillSlotSize; size > 0 { + // Simply increase the RSP to free the spill slots. + // add $size, %rsp + cur = linkInstr(cur, m.allocateInstr().asAluRmiR(aluRmiROpcodeAdd, newOperandImm32(uint32(size)), rspVReg, true)) + } + + // + // (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | ReturnAddress | | ReturnAddress | + // | Caller_RBP | | Caller_RBP | + // RBP ---> +-----------------+ ========> +-----------------+ <---- RSP, RBP + // | clobbered M | + // | ............ | + // | clobbered 1 | + // | clobbered 0 | + // RSP ---> +-----------------+ + // (low address) + // + if regs := m.clobberedRegs; len(regs) > 0 { + for _, r := range regs { + if r.RegType() == regalloc.RegTypeInt { + cur = linkInstr(cur, m.allocateInstr().asPop64(r)) + } else { + // Pop the XMM register is not supported by the POP instruction. + pop := m.allocateInstr().asXmmUnaryRmR( + sseOpcodeMovdqu, newOperandMem(m.newAmodeImmReg(0, rspVReg)), r, + ) + cur = linkInstr(cur, pop) + cur = m.addRSP(16, cur) + } + } + } + + // Now roll back the RSP to RBP, and pop the caller's RBP. + cur = m.revertRBPRSP(cur) + + linkInstr(cur, prevNext) +} + +func (m *machine) addRSP(offset int32, cur *instruction) *instruction { + if offset == 0 { + return cur + } + opcode := aluRmiROpcodeAdd + if offset < 0 { + opcode = aluRmiROpcodeSub + offset = -offset + } + return linkInstr(cur, m.allocateInstr().asAluRmiR(opcode, newOperandImm32(uint32(offset)), rspVReg, true)) +} + +func (m *machine) setupRBPRSP(cur *instruction) *instruction { + cur = linkInstr(cur, m.allocateInstr().asPush64(newOperandReg(rbpVReg))) + cur = linkInstr(cur, m.allocateInstr().asMovRR(rspVReg, rbpVReg, true)) + return cur +} + +func (m *machine) revertRBPRSP(cur *instruction) *instruction { + cur = linkInstr(cur, m.allocateInstr().asMovRR(rbpVReg, rspVReg, true)) + cur = linkInstr(cur, m.allocateInstr().asPop64(rbpVReg)) + return cur +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_regalloc.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_regalloc.go new file mode 100644 index 00000000..de9dcc94 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_regalloc.go @@ -0,0 +1,352 @@ +package amd64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// regAllocFn implements regalloc.Function. +type regAllocFn struct { + ssaB ssa.Builder + m *machine + loopNestingForestRoots []ssa.BasicBlock + blockIter int +} + +// PostOrderBlockIteratorBegin implements regalloc.Function. +func (f *regAllocFn) PostOrderBlockIteratorBegin() *labelPosition { + f.blockIter = len(f.m.orderedSSABlockLabelPos) - 1 + return f.PostOrderBlockIteratorNext() +} + +// PostOrderBlockIteratorNext implements regalloc.Function. +func (f *regAllocFn) PostOrderBlockIteratorNext() *labelPosition { + if f.blockIter < 0 { + return nil + } + b := f.m.orderedSSABlockLabelPos[f.blockIter] + f.blockIter-- + return b +} + +// ReversePostOrderBlockIteratorBegin implements regalloc.Function. +func (f *regAllocFn) ReversePostOrderBlockIteratorBegin() *labelPosition { + f.blockIter = 0 + return f.ReversePostOrderBlockIteratorNext() +} + +// ReversePostOrderBlockIteratorNext implements regalloc.Function. +func (f *regAllocFn) ReversePostOrderBlockIteratorNext() *labelPosition { + if f.blockIter >= len(f.m.orderedSSABlockLabelPos) { + return nil + } + b := f.m.orderedSSABlockLabelPos[f.blockIter] + f.blockIter++ + return b +} + +// ClobberedRegisters implements regalloc.Function. +func (f *regAllocFn) ClobberedRegisters(regs []regalloc.VReg) { + f.m.clobberedRegs = append(f.m.clobberedRegs[:0], regs...) +} + +// LoopNestingForestRoots implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestRoots() int { + f.loopNestingForestRoots = f.ssaB.LoopNestingForestRoots() + return len(f.loopNestingForestRoots) +} + +// LoopNestingForestRoot implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestRoot(i int) *labelPosition { + root := f.loopNestingForestRoots[i] + pos := f.m.getOrAllocateSSABlockLabelPosition(root) + return pos +} + +// LowestCommonAncestor implements regalloc.Function. +func (f *regAllocFn) LowestCommonAncestor(blk1, blk2 *labelPosition) *labelPosition { + sb := f.ssaB.LowestCommonAncestor(blk1.sb, blk2.sb) + pos := f.m.getOrAllocateSSABlockLabelPosition(sb) + return pos +} + +// Idom implements regalloc.Function. +func (f *regAllocFn) Idom(blk *labelPosition) *labelPosition { + sb := f.ssaB.Idom(blk.sb) + pos := f.m.getOrAllocateSSABlockLabelPosition(sb) + return pos +} + +// SwapBefore implements regalloc.Function. +func (f *regAllocFn) SwapBefore(x1, x2, tmp regalloc.VReg, instr *instruction) { + f.m.swap(instr.prev, x1, x2, tmp) +} + +// StoreRegisterBefore implements regalloc.Function. +func (f *regAllocFn) StoreRegisterBefore(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertStoreRegisterAt(v, instr, false) +} + +// StoreRegisterAfter implements regalloc.Function. +func (f *regAllocFn) StoreRegisterAfter(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertStoreRegisterAt(v, instr, true) +} + +// ReloadRegisterBefore implements regalloc.Function. +func (f *regAllocFn) ReloadRegisterBefore(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertReloadRegisterAt(v, instr, false) +} + +// ReloadRegisterAfter implements regalloc.Function. +func (f *regAllocFn) ReloadRegisterAfter(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertReloadRegisterAt(v, instr, true) +} + +// InsertMoveBefore implements regalloc.Function. +func (f *regAllocFn) InsertMoveBefore(dst, src regalloc.VReg, instr *instruction) { + f.m.insertMoveBefore(dst, src, instr) +} + +// LoopNestingForestChild implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestChild(pos *labelPosition, i int) *labelPosition { + childSB := pos.sb.LoopNestingForestChildren()[i] + return f.m.getOrAllocateSSABlockLabelPosition(childSB) +} + +// Succ implements regalloc.Block. +func (f *regAllocFn) Succ(pos *labelPosition, i int) *labelPosition { + succSB := pos.sb.Succ(i) + if succSB.ReturnBlock() { + return nil + } + return f.m.getOrAllocateSSABlockLabelPosition(succSB) +} + +// Pred implements regalloc.Block. +func (f *regAllocFn) Pred(pos *labelPosition, i int) *labelPosition { + predSB := pos.sb.Pred(i) + return f.m.getOrAllocateSSABlockLabelPosition(predSB) +} + +// BlockParams implements regalloc.Function. +func (f *regAllocFn) BlockParams(pos *labelPosition, regs *[]regalloc.VReg) []regalloc.VReg { + c := f.m.c + *regs = (*regs)[:0] + for i := 0; i < pos.sb.Params(); i++ { + v := c.VRegOf(pos.sb.Param(i)) + *regs = append(*regs, v) + } + return *regs +} + +// ID implements regalloc.Block. +func (pos *labelPosition) ID() int32 { + return int32(pos.sb.ID()) +} + +// InstrIteratorBegin implements regalloc.Block. +func (pos *labelPosition) InstrIteratorBegin() *instruction { + ret := pos.begin + pos.cur = ret + return ret +} + +// InstrIteratorNext implements regalloc.Block. +func (pos *labelPosition) InstrIteratorNext() *instruction { + for { + if pos.cur == pos.end { + return nil + } + instr := pos.cur.next + pos.cur = instr + if instr == nil { + return nil + } else if instr.addedBeforeRegAlloc { + // Only concerned about the instruction added before regalloc. + return instr + } + } +} + +// InstrRevIteratorBegin implements regalloc.Block. +func (pos *labelPosition) InstrRevIteratorBegin() *instruction { + pos.cur = pos.end + return pos.cur +} + +// InstrRevIteratorNext implements regalloc.Block. +func (pos *labelPosition) InstrRevIteratorNext() *instruction { + for { + if pos.cur == pos.begin { + return nil + } + instr := pos.cur.prev + pos.cur = instr + if instr == nil { + return nil + } else if instr.addedBeforeRegAlloc { + // Only concerned about the instruction added before regalloc. + return instr + } + } +} + +// FirstInstr implements regalloc.Block. +func (pos *labelPosition) FirstInstr() *instruction { return pos.begin } + +// LastInstrForInsertion implements regalloc.Block. +func (pos *labelPosition) LastInstrForInsertion() *instruction { + return lastInstrForInsertion(pos.begin, pos.end) +} + +// Preds implements regalloc.Block. +func (pos *labelPosition) Preds() int { return pos.sb.Preds() } + +// Entry implements regalloc.Block. +func (pos *labelPosition) Entry() bool { return pos.sb.EntryBlock() } + +// Succs implements regalloc.Block. +func (pos *labelPosition) Succs() int { return pos.sb.Succs() } + +// LoopHeader implements regalloc.Block. +func (pos *labelPosition) LoopHeader() bool { return pos.sb.LoopHeader() } + +// LoopNestingForestChildren implements regalloc.Block. +func (pos *labelPosition) LoopNestingForestChildren() int { + return len(pos.sb.LoopNestingForestChildren()) +} + +func (m *machine) insertMoveBefore(dst, src regalloc.VReg, instr *instruction) { + typ := src.RegType() + if typ != dst.RegType() { + panic("BUG: src and dst must have the same type") + } + + mov := m.allocateInstr() + if typ == regalloc.RegTypeInt { + mov.asMovRR(src, dst, true) + } else { + mov.asXmmUnaryRmR(sseOpcodeMovdqu, newOperandReg(src), dst) + } + + cur := instr.prev + prevNext := cur.next + cur = linkInstr(cur, mov) + linkInstr(cur, prevNext) +} + +func (m *machine) insertStoreRegisterAt(v regalloc.VReg, instr *instruction, after bool) *instruction { + if !v.IsRealReg() { + panic("BUG: VReg must be backed by real reg to be stored") + } + + typ := m.c.TypeOf(v) + + var prevNext, cur *instruction + if after { + cur, prevNext = instr, instr.next + } else { + cur, prevNext = instr.prev, instr + } + + offsetFromSP := m.getVRegSpillSlotOffsetFromSP(v.ID(), typ.Size()) + store := m.allocateInstr() + mem := newOperandMem(m.newAmodeImmReg(uint32(offsetFromSP), rspVReg)) + switch typ { + case ssa.TypeI32: + store.asMovRM(v, mem, 4) + case ssa.TypeI64: + store.asMovRM(v, mem, 8) + case ssa.TypeF32: + store.asXmmMovRM(sseOpcodeMovss, v, mem) + case ssa.TypeF64: + store.asXmmMovRM(sseOpcodeMovsd, v, mem) + case ssa.TypeV128: + store.asXmmMovRM(sseOpcodeMovdqu, v, mem) + } + + cur = linkInstr(cur, store) + return linkInstr(cur, prevNext) +} + +func (m *machine) insertReloadRegisterAt(v regalloc.VReg, instr *instruction, after bool) *instruction { + if !v.IsRealReg() { + panic("BUG: VReg must be backed by real reg to be stored") + } + + typ := m.c.TypeOf(v) + var prevNext, cur *instruction + if after { + cur, prevNext = instr, instr.next + } else { + cur, prevNext = instr.prev, instr + } + + // Load the value to the temporary. + load := m.allocateInstr() + offsetFromSP := m.getVRegSpillSlotOffsetFromSP(v.ID(), typ.Size()) + a := newOperandMem(m.newAmodeImmReg(uint32(offsetFromSP), rspVReg)) + switch typ { + case ssa.TypeI32: + load.asMovzxRmR(extModeLQ, a, v) + case ssa.TypeI64: + load.asMov64MR(a, v) + case ssa.TypeF32: + load.asXmmUnaryRmR(sseOpcodeMovss, a, v) + case ssa.TypeF64: + load.asXmmUnaryRmR(sseOpcodeMovsd, a, v) + case ssa.TypeV128: + load.asXmmUnaryRmR(sseOpcodeMovdqu, a, v) + default: + panic("BUG") + } + + cur = linkInstr(cur, load) + return linkInstr(cur, prevNext) +} + +func (m *machine) swap(cur *instruction, x1, x2, tmp regalloc.VReg) { + if x1.RegType() == regalloc.RegTypeInt { + prevNext := cur.next + xc := m.allocateInstr().asXCHG(x1, newOperandReg(x2), 8) + cur = linkInstr(cur, xc) + linkInstr(cur, prevNext) + } else { + if tmp.Valid() { + prevNext := cur.next + m.insertMoveBefore(tmp, x1, prevNext) + m.insertMoveBefore(x1, x2, prevNext) + m.insertMoveBefore(x2, tmp, prevNext) + } else { + prevNext := cur.next + r2 := x2.RealReg() + // Temporarily spill x1 to stack. + cur = m.insertStoreRegisterAt(x1, cur, true).prev + // Then move x2 to x1. + cur = linkInstr(cur, m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqa, newOperandReg(x2), x1)) + linkInstr(cur, prevNext) + // Then reload the original value on x1 from stack to r2. + m.insertReloadRegisterAt(x1.SetRealReg(r2), cur, true) + } + } +} + +func lastInstrForInsertion(begin, end *instruction) *instruction { + cur := end + for cur.kind == nop0 { + cur = cur.prev + if cur == begin { + return end + } + } + switch cur.kind { + case jmp: + return cur + default: + return end + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_vec.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_vec.go new file mode 100644 index 00000000..8d514d85 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/machine_vec.go @@ -0,0 +1,992 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +var swizzleMask = [16]byte{ + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, +} + +func (m *machine) lowerSwizzle(x, y ssa.Value, ret ssa.Value) { + masklabel := m.getOrAllocateConstLabel(&m.constSwizzleMaskConstIndex, swizzleMask[:]) + + // Load mask to maskReg. + maskReg := m.c.AllocateVReg(ssa.TypeV128) + loadMask := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(masklabel)), maskReg) + m.insert(loadMask) + + // Copy x and y to tmp registers. + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + tmpDst := m.copyToTmp(xx.reg()) + yy := m.getOperand_Reg(m.c.ValueDefinition(y)) + tmpX := m.copyToTmp(yy.reg()) + + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePaddusb, newOperandReg(maskReg), tmpX)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePshufb, newOperandReg(tmpX), tmpDst)) + + // Copy the result to the destination register. + m.copyTo(tmpDst, m.c.VRegOf(ret)) +} + +func (m *machine) lowerInsertLane(x, y ssa.Value, index byte, ret ssa.Value, lane ssa.VecLane) { + // Copy x to tmp. + tmpDst := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, m.getOperand_Mem_Reg(m.c.ValueDefinition(x)), tmpDst)) + + yy := m.getOperand_Reg(m.c.ValueDefinition(y)) + switch lane { + case ssa.VecLaneI8x16: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrb, index, yy, tmpDst)) + case ssa.VecLaneI16x8: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrw, index, yy, tmpDst)) + case ssa.VecLaneI32x4: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrd, index, yy, tmpDst)) + case ssa.VecLaneI64x2: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, index, yy, tmpDst)) + case ssa.VecLaneF32x4: + // In INSERTPS instruction, the destination index is encoded at 4 and 5 bits of the argument. + // See https://www.felixcloutier.com/x86/insertps + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeInsertps, index<<4, yy, tmpDst)) + case ssa.VecLaneF64x2: + if index == 0 { + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovsd, yy, tmpDst)) + } else { + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMovlhps, yy, tmpDst)) + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.copyTo(tmpDst, m.c.VRegOf(ret)) +} + +func (m *machine) lowerExtractLane(x ssa.Value, index byte, signed bool, ret ssa.Value, lane ssa.VecLane) { + // Pextr variants are used to extract a lane from a vector register. + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + + tmpDst := m.c.AllocateVReg(ret.Type()) + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpDst)) + switch lane { + case ssa.VecLaneI8x16: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrb, index, xx, tmpDst)) + if signed { + m.insert(m.allocateInstr().asMovsxRmR(extModeBL, newOperandReg(tmpDst), tmpDst)) + } else { + m.insert(m.allocateInstr().asMovzxRmR(extModeBL, newOperandReg(tmpDst), tmpDst)) + } + case ssa.VecLaneI16x8: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrw, index, xx, tmpDst)) + if signed { + m.insert(m.allocateInstr().asMovsxRmR(extModeWL, newOperandReg(tmpDst), tmpDst)) + } else { + m.insert(m.allocateInstr().asMovzxRmR(extModeWL, newOperandReg(tmpDst), tmpDst)) + } + case ssa.VecLaneI32x4: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrd, index, xx, tmpDst)) + case ssa.VecLaneI64x2: + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrq, index, xx, tmpDst)) + case ssa.VecLaneF32x4: + if index == 0 { + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovss, xx, tmpDst)) + } else { + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, index, xx, tmpDst)) + } + case ssa.VecLaneF64x2: + if index == 0 { + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovsd, xx, tmpDst)) + } else { + m.copyTo(xx.reg(), tmpDst) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0b00_00_11_10, newOperandReg(tmpDst), tmpDst)) + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.copyTo(tmpDst, m.c.VRegOf(ret)) +} + +var sqmulRoundSat = [16]byte{ + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, +} + +func (m *machine) lowerSqmulRoundSat(x, y, ret ssa.Value) { + // See https://github.com/WebAssembly/simd/pull/365 for the following logic. + maskLabel := m.getOrAllocateConstLabel(&m.constSqmulRoundSatIndex, sqmulRoundSat[:]) + + tmp := m.c.AllocateVReg(ssa.TypeV128) + loadMask := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskLabel)), tmp) + m.insert(loadMask) + + xx, yy := m.getOperand_Reg(m.c.ValueDefinition(x)), m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + tmpX := m.copyToTmp(xx.reg()) + + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmulhrsw, yy, tmpX)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePcmpeqw, newOperandReg(tmpX), tmp)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp), tmpX)) + + m.copyTo(tmpX, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVUshr(x, y, ret ssa.Value, lane ssa.VecLane) { + switch lane { + case ssa.VecLaneI8x16: + m.lowerVUshri8x16(x, y, ret) + case ssa.VecLaneI16x8, ssa.VecLaneI32x4, ssa.VecLaneI64x2: + m.lowerShr(x, y, ret, lane, false) + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } +} + +// i8x16LogicalSHRMaskTable is necessary for emulating non-existent packed bytes logical right shifts on amd64. +// The mask is applied after performing packed word shifts on the value to clear out the unnecessary bits. +var i8x16LogicalSHRMaskTable = [8 * 16]byte{ // (the number of possible shift amount 0, 1, ..., 7.) * 16 bytes. + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // for 0 shift + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, // for 1 shift + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, // for 2 shift + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, // for 3 shift + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, // for 4 shift + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, // for 5 shift + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, // for 6 shift + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // for 7 shift +} + +func (m *machine) lowerVUshri8x16(x, y, ret ssa.Value) { + tmpGpReg := m.c.AllocateVReg(ssa.TypeI32) + // Load the modulo 8 mask to tmpReg. + m.lowerIconst(tmpGpReg, 0x7, false) + // Take the modulo 8 of the shift amount. + shiftAmt := m.getOperand_Mem_Imm32_Reg(m.c.ValueDefinition(y)) + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAnd, shiftAmt, tmpGpReg, false)) + + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + + vecTmp := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asGprToXmm(sseOpcodeMovd, newOperandReg(tmpGpReg), vecTmp, false)) + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsrlw, newOperandReg(vecTmp), xx)) + + maskTableLabel := m.getOrAllocateConstLabel(&m.constI8x16LogicalSHRMaskTableIndex, i8x16LogicalSHRMaskTable[:]) + base := m.c.AllocateVReg(ssa.TypeI64) + lea := m.allocateInstr().asLEA(newOperandLabel(maskTableLabel), base) + m.insert(lea) + + // Shift tmpGpReg by 4 to multiply the shift amount by 16. + m.insert(m.allocateInstr().asShiftR(shiftROpShiftLeft, newOperandImm32(4), tmpGpReg, false)) + + mem := m.newAmodeRegRegShift(0, base, tmpGpReg, 0) + loadMask := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(mem), vecTmp) + m.insert(loadMask) + + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePand, newOperandReg(vecTmp), xx)) + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVSshr(x, y, ret ssa.Value, lane ssa.VecLane) { + switch lane { + case ssa.VecLaneI8x16: + m.lowerVSshri8x16(x, y, ret) + case ssa.VecLaneI16x8, ssa.VecLaneI32x4: + m.lowerShr(x, y, ret, lane, true) + case ssa.VecLaneI64x2: + m.lowerVSshri64x2(x, y, ret) + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } +} + +func (m *machine) lowerVSshri8x16(x, y, ret ssa.Value) { + shiftAmtReg := m.c.AllocateVReg(ssa.TypeI32) + // Load the modulo 8 mask to tmpReg. + m.lowerIconst(shiftAmtReg, 0x7, false) + // Take the modulo 8 of the shift amount. + shiftAmt := m.getOperand_Mem_Imm32_Reg(m.c.ValueDefinition(y)) + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAnd, shiftAmt, shiftAmtReg, false)) + + // Copy the x value to two temporary registers. + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + vecTmp := m.c.AllocateVReg(ssa.TypeV128) + m.copyTo(xx, vecTmp) + + // Assuming that we have + // xx = [b1, ..., b16] + // vecTmp = [b1, ..., b16] + // at this point, then we use PUNPCKLBW and PUNPCKHBW to produce: + // xx = [b1, b1, b2, b2, ..., b8, b8] + // vecTmp = [b9, b9, b10, b10, ..., b16, b16] + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePunpcklbw, newOperandReg(xx), xx)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePunpckhbw, newOperandReg(vecTmp), vecTmp)) + + // Adding 8 to the shift amount, and then move the amount to vecTmp2. + vecTmp2 := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAdd, newOperandImm32(8), shiftAmtReg, false)) + m.insert(m.allocateInstr().asGprToXmm(sseOpcodeMovd, newOperandReg(shiftAmtReg), vecTmp2, false)) + + // Perform the word packed arithmetic right shifts on vreg and vecTmp. + // This changes these two registers as: + // xx = [xxx, b1 >> s, xxx, b2 >> s, ..., xxx, b8 >> s] + // vecTmp = [xxx, b9 >> s, xxx, b10 >> s, ..., xxx, b16 >> s] + // where xxx is 1 or 0 depending on each byte's sign, and ">>" is the arithmetic shift on a byte. + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsraw, newOperandReg(vecTmp2), xx)) + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsraw, newOperandReg(vecTmp2), vecTmp)) + + // Finally, we can get the result by packing these two word vectors. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePacksswb, newOperandReg(vecTmp), xx)) + + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVSshri64x2(x, y, ret ssa.Value) { + // Load the shift amount to RCX. + shiftAmt := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, shiftAmt, rcxVReg)) + + tmpGp := m.c.AllocateVReg(ssa.TypeI64) + + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xxReg := m.copyToTmp(_xx.reg()) + + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpGp)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrq, 0, newOperandReg(xxReg), tmpGp)) + m.insert(m.allocateInstr().asShiftR(shiftROpShiftRightArithmetic, newOperandReg(rcxVReg), tmpGp, true)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 0, newOperandReg(tmpGp), xxReg)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePextrq, 1, newOperandReg(xxReg), tmpGp)) + m.insert(m.allocateInstr().asShiftR(shiftROpShiftRightArithmetic, newOperandReg(rcxVReg), tmpGp, true)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 1, newOperandReg(tmpGp), xxReg)) + + m.copyTo(xxReg, m.c.VRegOf(ret)) +} + +func (m *machine) lowerShr(x, y, ret ssa.Value, lane ssa.VecLane, signed bool) { + var modulo uint64 + var shiftOp sseOpcode + switch lane { + case ssa.VecLaneI16x8: + modulo = 0xf + if signed { + shiftOp = sseOpcodePsraw + } else { + shiftOp = sseOpcodePsrlw + } + case ssa.VecLaneI32x4: + modulo = 0x1f + if signed { + shiftOp = sseOpcodePsrad + } else { + shiftOp = sseOpcodePsrld + } + case ssa.VecLaneI64x2: + modulo = 0x3f + if signed { + panic("BUG") + } + shiftOp = sseOpcodePsrlq + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + + tmpGpReg := m.c.AllocateVReg(ssa.TypeI32) + // Load the modulo 8 mask to tmpReg. + m.lowerIconst(tmpGpReg, modulo, false) + // Take the modulo 8 of the shift amount. + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAnd, + m.getOperand_Mem_Imm32_Reg(m.c.ValueDefinition(y)), tmpGpReg, false)) + // And move it to a xmm register. + tmpVec := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asGprToXmm(sseOpcodeMovd, newOperandReg(tmpGpReg), tmpVec, false)) + + // Then do the actual shift. + m.insert(m.allocateInstr().asXmmRmiReg(shiftOp, newOperandReg(tmpVec), xx)) + + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVIshl(x, y, ret ssa.Value, lane ssa.VecLane) { + var modulo uint64 + var shiftOp sseOpcode + var isI8x16 bool + switch lane { + case ssa.VecLaneI8x16: + isI8x16 = true + modulo = 0x7 + shiftOp = sseOpcodePsllw + case ssa.VecLaneI16x8: + modulo = 0xf + shiftOp = sseOpcodePsllw + case ssa.VecLaneI32x4: + modulo = 0x1f + shiftOp = sseOpcodePslld + case ssa.VecLaneI64x2: + modulo = 0x3f + shiftOp = sseOpcodePsllq + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + + tmpGpReg := m.c.AllocateVReg(ssa.TypeI32) + // Load the modulo 8 mask to tmpReg. + m.lowerIconst(tmpGpReg, modulo, false) + // Take the modulo 8 of the shift amount. + m.insert(m.allocateInstr().asAluRmiR(aluRmiROpcodeAnd, + m.getOperand_Mem_Imm32_Reg(m.c.ValueDefinition(y)), tmpGpReg, false)) + // And move it to a xmm register. + tmpVec := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asGprToXmm(sseOpcodeMovd, newOperandReg(tmpGpReg), tmpVec, false)) + + // Then do the actual shift. + m.insert(m.allocateInstr().asXmmRmiReg(shiftOp, newOperandReg(tmpVec), xx)) + + if isI8x16 { + maskTableLabel := m.getOrAllocateConstLabel(&m.constI8x16SHLMaskTableIndex, i8x16SHLMaskTable[:]) + base := m.c.AllocateVReg(ssa.TypeI64) + lea := m.allocateInstr().asLEA(newOperandLabel(maskTableLabel), base) + m.insert(lea) + + // Shift tmpGpReg by 4 to multiply the shift amount by 16. + m.insert(m.allocateInstr().asShiftR(shiftROpShiftLeft, newOperandImm32(4), tmpGpReg, false)) + + mem := m.newAmodeRegRegShift(0, base, tmpGpReg, 0) + loadMask := m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(mem), tmpVec) + m.insert(loadMask) + + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePand, newOperandReg(tmpVec), xx)) + } + + m.copyTo(xx, m.c.VRegOf(ret)) +} + +// i8x16SHLMaskTable is necessary for emulating non-existent packed bytes left shifts on amd64. +// The mask is applied after performing packed word shifts on the value to clear out the unnecessary bits. +var i8x16SHLMaskTable = [8 * 16]byte{ // (the number of possible shift amount 0, 1, ..., 7.) * 16 bytes. + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // for 0 shift + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, // for 1 shift + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, // for 2 shift + 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, // for 3 shift + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // for 4 shift + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, // for 5 shift + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, // for 6 shift + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // for 7 shift +} + +func (m *machine) lowerVRound(x, ret ssa.Value, imm byte, _64 bool) { + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + var round sseOpcode + if _64 { + round = sseOpcodeRoundpd + } else { + round = sseOpcodeRoundps + } + m.insert(m.allocateInstr().asXmmUnaryRmRImm(round, imm, xx, m.c.VRegOf(ret))) +} + +var ( + allOnesI8x16 = [16]byte{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} + allOnesI16x8 = [16]byte{0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0} + extAddPairwiseI16x8uMask1 = [16]byte{0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80} + extAddPairwiseI16x8uMask2 = [16]byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00} +) + +func (m *machine) lowerExtIaddPairwise(x, ret ssa.Value, srcLane ssa.VecLane, signed bool) { + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + switch srcLane { + case ssa.VecLaneI8x16: + allOneReg := m.c.AllocateVReg(ssa.TypeV128) + mask := m.getOrAllocateConstLabel(&m.constAllOnesI8x16Index, allOnesI8x16[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(mask)), allOneReg)) + + var resultReg regalloc.VReg + if signed { + resultReg = allOneReg + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaddubsw, newOperandReg(xx), resultReg)) + } else { + // Interpreter tmp (all ones) as signed byte meaning that all the multiply-add is unsigned. + resultReg = xx + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaddubsw, newOperandReg(allOneReg), resultReg)) + } + m.copyTo(resultReg, m.c.VRegOf(ret)) + + case ssa.VecLaneI16x8: + if signed { + allOnesReg := m.c.AllocateVReg(ssa.TypeV128) + mask := m.getOrAllocateConstLabel(&m.constAllOnesI16x8Index, allOnesI16x8[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(mask)), allOnesReg)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaddwd, newOperandReg(allOnesReg), xx)) + m.copyTo(xx, m.c.VRegOf(ret)) + } else { + maskReg := m.c.AllocateVReg(ssa.TypeV128) + mask := m.getOrAllocateConstLabel(&m.constExtAddPairwiseI16x8uMask1Index, extAddPairwiseI16x8uMask1[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(mask)), maskReg)) + + // Flip the sign bits on xx. + // + // Assuming that xx = [w1, ..., w8], now we have, + // xx[i] = int8(-w1) for i = 0...8 + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(maskReg), xx)) + + mask = m.getOrAllocateConstLabel(&m.constAllOnesI16x8Index, allOnesI16x8[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(mask)), maskReg)) + + // For i = 0,..4 (as this results in i32x4 lanes), now we have + // xx[i] = int32(-wn + -w(n+1)) = int32(-(wn + w(n+1))) + // c.assembler.CompileRegisterToRegister(amd64.PMADDWD, tmp, vr) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaddwd, newOperandReg(maskReg), xx)) + + mask = m.getOrAllocateConstLabel(&m.constExtAddPairwiseI16x8uMask2Index, extAddPairwiseI16x8uMask2[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(mask)), maskReg)) + + // vr[i] = int32(-(wn + w(n+1))) + int32(math.MaxInt16+1) = int32((wn + w(n+1))) = uint32(wn + w(n+1)). + // c.assembler.CompileRegisterToRegister(amd64.PADDD, tmp, vr) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePaddd, newOperandReg(maskReg), xx)) + + m.copyTo(xx, m.c.VRegOf(ret)) + } + default: + panic(fmt.Sprintf("invalid lane type: %s", srcLane)) + } +} + +func (m *machine) lowerWidenLow(x, ret ssa.Value, lane ssa.VecLane, signed bool) { + var sseOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + if signed { + sseOp = sseOpcodePmovsxbw + } else { + sseOp = sseOpcodePmovzxbw + } + case ssa.VecLaneI16x8: + if signed { + sseOp = sseOpcodePmovsxwd + } else { + sseOp = sseOpcodePmovzxwd + } + case ssa.VecLaneI32x4: + if signed { + sseOp = sseOpcodePmovsxdq + } else { + sseOp = sseOpcodePmovzxdq + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOp, xx, m.c.VRegOf(ret))) +} + +func (m *machine) lowerWidenHigh(x, ret ssa.Value, lane ssa.VecLane, signed bool) { + tmp := m.c.AllocateVReg(ssa.TypeV128) + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + m.copyTo(xx.reg(), tmp) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePalignr, 8, newOperandReg(tmp), tmp)) + + var sseOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + if signed { + sseOp = sseOpcodePmovsxbw + } else { + sseOp = sseOpcodePmovzxbw + } + case ssa.VecLaneI16x8: + if signed { + sseOp = sseOpcodePmovsxwd + } else { + sseOp = sseOpcodePmovzxwd + } + case ssa.VecLaneI32x4: + if signed { + sseOp = sseOpcodePmovsxdq + } else { + sseOp = sseOpcodePmovzxdq + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOp, newOperandReg(tmp), m.c.VRegOf(ret))) +} + +func (m *machine) lowerLoadSplat(ptr ssa.Value, offset uint32, ret ssa.Value, lane ssa.VecLane) { + tmpDst, tmpGp := m.c.AllocateVReg(ssa.TypeV128), m.c.AllocateVReg(ssa.TypeI64) + am := newOperandMem(m.lowerToAddressMode(ptr, offset)) + + m.insert(m.allocateInstr().asDefineUninitializedReg(tmpDst)) + switch lane { + case ssa.VecLaneI8x16: + m.insert(m.allocateInstr().asMovzxRmR(extModeBQ, am, tmpGp)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrb, 0, newOperandReg(tmpGp), tmpDst)) + tmpZeroVec := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asZeros(tmpZeroVec)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePshufb, newOperandReg(tmpZeroVec), tmpDst)) + case ssa.VecLaneI16x8: + m.insert(m.allocateInstr().asMovzxRmR(extModeWQ, am, tmpGp)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrw, 0, newOperandReg(tmpGp), tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrw, 1, newOperandReg(tmpGp), tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0, newOperandReg(tmpDst), tmpDst)) + case ssa.VecLaneI32x4: + m.insert(m.allocateInstr().asMovzxRmR(extModeLQ, am, tmpGp)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrd, 0, newOperandReg(tmpGp), tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePshufd, 0, newOperandReg(tmpDst), tmpDst)) + case ssa.VecLaneI64x2: + m.insert(m.allocateInstr().asMov64MR(am, tmpGp)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 0, newOperandReg(tmpGp), tmpDst)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodePinsrq, 1, newOperandReg(tmpGp), tmpDst)) + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.copyTo(tmpDst, m.c.VRegOf(ret)) +} + +var f64x2CvtFromIMask = [16]byte{ + 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +} + +func (m *machine) lowerVFcvtFromInt(x, ret ssa.Value, lane ssa.VecLane, signed bool) { + switch lane { + case ssa.VecLaneF32x4: + if signed { + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtdq2ps, xx, m.c.VRegOf(ret))) + } else { + xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + // Copy the value to two temporary registers. + tmp := m.copyToTmp(xx.reg()) + tmp2 := m.copyToTmp(xx.reg()) + + // Clear the higher 16 bits of each 32-bit element. + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePslld, newOperandImm32(0xa), tmp)) + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsrld, newOperandImm32(0xa), tmp)) + + // Subtract the higher 16-bits from tmp2: clear the lower 16-bits of tmp2. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePsubd, newOperandReg(tmp), tmp2)) + + // Convert the lower 16-bits in tmp. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtdq2ps, newOperandReg(tmp), tmp)) + + // Left shift by one and convert tmp2, meaning that halved conversion result of higher 16-bits in tmp2. + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsrld, newOperandImm32(1), tmp2)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtdq2ps, newOperandReg(tmp2), tmp2)) + + // Double the converted halved higher 16bits. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAddps, newOperandReg(tmp2), tmp2)) + + // Get the conversion result by add tmp (holding lower 16-bit conversion) into tmp2. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAddps, newOperandReg(tmp), tmp2)) + + m.copyTo(tmp2, m.c.VRegOf(ret)) + } + case ssa.VecLaneF64x2: + if signed { + xx := m.getOperand_Mem_Reg(m.c.ValueDefinition(x)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtdq2pd, xx, m.c.VRegOf(ret))) + } else { + maskReg := m.c.AllocateVReg(ssa.TypeV128) + maskLabel := m.getOrAllocateConstLabel(&m.constF64x2CvtFromIMaskIndex, f64x2CvtFromIMask[:]) + // maskReg = [0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskLabel)), maskReg)) + + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + + // Given that we have xx = [d1, d2, d3, d4], this results in + // xx = [d1, [0x00, 0x00, 0x30, 0x43], d2, [0x00, 0x00, 0x30, 0x43]] + // = [float64(uint32(d1)) + 0x1.0p52, float64(uint32(d2)) + 0x1.0p52] + // ^See https://stackoverflow.com/questions/13269523/can-all-32-bit-ints-be-exactly-represented-as-a-double + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeUnpcklps, newOperandReg(maskReg), xx)) + + // maskReg = [float64(0x1.0p52), float64(0x1.0p52)] + maskLabel = m.getOrAllocateConstLabel(&m.constTwop52Index, twop52[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskLabel)), maskReg)) + + // Now, we get the result as + // xx = [float64(uint32(d1)), float64(uint32(d2))] + // because the following equality always satisfies: + // float64(0x1.0p52 + float64(uint32(x))) - float64(0x1.0p52 + float64(uint32(y))) = float64(uint32(x)) - float64(uint32(y)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeSubpd, newOperandReg(maskReg), xx)) + + m.copyTo(xx, m.c.VRegOf(ret)) + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } +} + +var ( + // i32sMaxOnF64x2 holds math.MaxInt32(=2147483647.0) on two f64 lanes. + i32sMaxOnF64x2 = [16]byte{ + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xdf, 0x41, // float64(2147483647.0) + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xdf, 0x41, // float64(2147483647.0) + } + + // i32sMaxOnF64x2 holds math.MaxUint32(=4294967295.0) on two f64 lanes. + i32uMaxOnF64x2 = [16]byte{ + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xef, 0x41, // float64(4294967295.0) + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xef, 0x41, // float64(4294967295.0) + } + + // twop52 holds two float64(0x1.0p52) on two f64 lanes. 0x1.0p52 is special in the sense that + // with this exponent, the mantissa represents a corresponding uint32 number, and arithmetics, + // like addition or subtraction, the resulted floating point holds exactly the same + // bit representations in 32-bit integer on its mantissa. + // + // Note: the name twop52 is common across various compiler ecosystem. + // E.g. https://github.com/llvm/llvm-project/blob/92ab024f81e5b64e258b7c3baaf213c7c26fcf40/compiler-rt/lib/builtins/floatdidf.c#L28 + // E.g. https://opensource.apple.com/source/clang/clang-425.0.24/src/projects/compiler-rt/lib/floatdidf.c.auto.html + twop52 = [16]byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x43, // float64(0x1.0p52) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x43, // float64(0x1.0p52) + } +) + +func (m *machine) lowerVFcvtToIntSat(x, ret ssa.Value, lane ssa.VecLane, signed bool) { + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + + switch lane { + case ssa.VecLaneF32x4: + if signed { + tmp := m.copyToTmp(xx) + + // Assuming we have xx = [v1, v2, v3, v4]. + // + // Set all bits if lane is not NaN on tmp. + // tmp[i] = 0xffffffff if vi != NaN + // = 0 if vi == NaN + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeCmpps, uint8(cmpPredEQ_OQ), newOperandReg(tmp), tmp)) + + // Clear NaN lanes on xx, meaning that + // xx[i] = vi if vi != NaN + // 0 if vi == NaN + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAndps, newOperandReg(tmp), xx)) + + // tmp[i] = ^vi if vi != NaN + // = 0xffffffff if vi == NaN + // which means that tmp[i] & 0x80000000 != 0 if and only if vi is negative. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeXorps, newOperandReg(xx), tmp)) + + // xx[i] = int32(vi) if vi != NaN and xx is not overflowing. + // = 0x80000000 if vi != NaN and xx is overflowing (See https://www.felixcloutier.com/x86/cvttps2dq) + // = 0 if vi == NaN + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvttps2dq, newOperandReg(xx), xx)) + + // Below, we have to convert 0x80000000 into 0x7FFFFFFF for positive overflowing lane. + // + // tmp[i] = 0x80000000 if vi is positive + // = any satisfying any&0x80000000 = 0 if vi is negative or zero. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAndps, newOperandReg(xx), tmp)) + + // Arithmetic right shifting tmp by 31, meaning that we have + // tmp[i] = 0xffffffff if vi is positive, 0 otherwise. + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsrad, newOperandImm32(0x1f), tmp)) + + // Flipping 0x80000000 if vi is positive, otherwise keep intact. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp), xx)) + } else { + tmp := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asZeros(tmp)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMaxps, newOperandReg(tmp), xx)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePcmpeqd, newOperandReg(tmp), tmp)) + m.insert(m.allocateInstr().asXmmRmiReg(sseOpcodePsrld, newOperandImm32(0x1), tmp)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvtdq2ps, newOperandReg(tmp), tmp)) + tmp2 := m.copyToTmp(xx) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvttps2dq, newOperandReg(xx), xx)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeSubps, newOperandReg(tmp), tmp2)) + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeCmpps, uint8(cmpPredLE_OS), newOperandReg(tmp2), tmp)) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvttps2dq, newOperandReg(tmp2), tmp2)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp), tmp2)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(tmp), tmp)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaxsd, newOperandReg(tmp), tmp2)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePaddd, newOperandReg(tmp2), xx)) + } + + case ssa.VecLaneF64x2: + tmp2 := m.c.AllocateVReg(ssa.TypeV128) + if signed { + tmp := m.copyToTmp(xx) + + // Set all bits for non-NaN lanes, zeros otherwise. + // I.e. tmp[i] = 0xffffffff_ffffffff if vi != NaN, 0 otherwise. + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeCmppd, uint8(cmpPredEQ_OQ), newOperandReg(tmp), tmp)) + + maskLabel := m.getOrAllocateConstLabel(&m.constI32sMaxOnF64x2Index, i32sMaxOnF64x2[:]) + // Load the 2147483647 into tmp2's each lane. + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskLabel)), tmp2)) + + // tmp[i] = 2147483647 if vi != NaN, 0 otherwise. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAndps, newOperandReg(tmp2), tmp)) + + // MINPD returns the source register's value as-is, so we have + // xx[i] = vi if vi != NaN + // = 0 if vi == NaN + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMinpd, newOperandReg(tmp), xx)) + + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeCvttpd2dq, newOperandReg(xx), xx)) + } else { + tmp := m.c.AllocateVReg(ssa.TypeV128) + m.insert(m.allocateInstr().asZeros(tmp)) + + // xx[i] = vi if vi != NaN && vi > 0 + // = 0 if vi == NaN || vi <= 0 + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMaxpd, newOperandReg(tmp), xx)) + + // tmp2[i] = float64(math.MaxUint32) = math.MaxUint32 + maskIndex := m.getOrAllocateConstLabel(&m.constI32uMaxOnF64x2Index, i32uMaxOnF64x2[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskIndex)), tmp2)) + + // xx[i] = vi if vi != NaN && vi > 0 && vi <= math.MaxUint32 + // = 0 otherwise + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeMinpd, newOperandReg(tmp2), xx)) + + // Round the floating points into integer. + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeRoundpd, 0x3, newOperandReg(xx), xx)) + + // tmp2[i] = float64(0x1.0p52) + maskIndex = m.getOrAllocateConstLabel(&m.constTwop52Index, twop52[:]) + m.insert(m.allocateInstr().asXmmUnaryRmR(sseOpcodeMovdqu, newOperandMem(m.newAmodeRipRel(maskIndex)), tmp2)) + + // xx[i] = float64(0x1.0p52) + float64(uint32(vi)) if vi != NaN && vi > 0 && vi <= math.MaxUint32 + // = 0 otherwise + // + // This means that xx[i] holds exactly the same bit of uint32(vi) in its lower 32-bits. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodeAddpd, newOperandReg(tmp2), xx)) + + // At this point, we have + // xx = [uint32(v0), float64(0x1.0p52), uint32(v1), float64(0x1.0p52)] + // tmp = [0, 0, 0, 0] + // as 32x4 lanes. Therefore, SHUFPS with 0b00_00_10_00 results in + // xx = [xx[00], xx[10], tmp[00], tmp[00]] = [xx[00], xx[10], 0, 0] + // meaning that for i = 0 and 1, we have + // xx[i] = uint32(vi) if vi != NaN && vi > 0 && vi <= math.MaxUint32 + // = 0 otherwise. + m.insert(m.allocateInstr().asXmmRmRImm(sseOpcodeShufps, 0b00_00_10_00, newOperandReg(tmp), xx)) + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerNarrow(x, y, ret ssa.Value, lane ssa.VecLane, signed bool) { + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + yy := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + + var sseOp sseOpcode + switch lane { + case ssa.VecLaneI16x8: + if signed { + sseOp = sseOpcodePacksswb + } else { + sseOp = sseOpcodePackuswb + } + case ssa.VecLaneI32x4: + if signed { + sseOp = sseOpcodePackssdw + } else { + sseOp = sseOpcodePackusdw + } + default: + panic(fmt.Sprintf("invalid lane type: %s", lane)) + } + m.insert(m.allocateInstr().asXmmRmR(sseOp, yy, xx)) + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerWideningPairwiseDotProductS(x, y, ret ssa.Value) { + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + xx := m.copyToTmp(_xx.reg()) + yy := m.getOperand_Mem_Reg(m.c.ValueDefinition(y)) + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePmaddwd, yy, xx)) + m.copyTo(xx, m.c.VRegOf(ret)) +} + +func (m *machine) lowerVIabs(instr *ssa.Instruction) { + x, lane := instr.ArgWithLane() + rd := m.c.VRegOf(instr.Return()) + + if lane == ssa.VecLaneI64x2 { + _xx := m.getOperand_Reg(m.c.ValueDefinition(x)) + + blendReg := xmm0VReg + m.insert(m.allocateInstr().asDefineUninitializedReg(blendReg)) + + tmp := m.copyToTmp(_xx.reg()) + xx := m.copyToTmp(_xx.reg()) + + // Clear all bits on blendReg. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePxor, newOperandReg(blendReg), blendReg)) + // Subtract xx from blendMaskReg. + m.insert(m.allocateInstr().asXmmRmR(sseOpcodePsubq, newOperandReg(xx), blendReg)) + // Copy the subtracted value ^^ back into tmp. + m.copyTo(blendReg, xx) + + m.insert(m.allocateInstr().asBlendvpd(newOperandReg(tmp), xx)) + + m.copyTo(xx, rd) + } else { + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI8x16: + vecOp = sseOpcodePabsb + case ssa.VecLaneI16x8: + vecOp = sseOpcodePabsw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePabsd + } + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + + i := m.allocateInstr() + i.asXmmUnaryRmR(vecOp, rn, rd) + m.insert(i) + } +} + +func (m *machine) lowerVIpopcnt(instr *ssa.Instruction) { + x := instr.Arg() + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rd := m.c.VRegOf(instr.Return()) + + tmp1 := m.c.AllocateVReg(ssa.TypeV128) + m.lowerVconst(tmp1, 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f) + + // Copy input into tmp2. + tmp2 := m.copyToTmp(rn.reg()) + + // Given that we have: + // rm = [b1, ..., b16] where bn = hn:ln and hn and ln are higher and lower 4-bits of bn. + // + // Take PAND on tmp1 and tmp2, so that we mask out all the higher bits. + // tmp2 = [l1, ..., l16]. + pand := m.allocateInstr() + pand.asXmmRmR(sseOpcodePand, newOperandReg(tmp1), tmp2) + m.insert(pand) + + // Do logical (packed word) right shift by 4 on rm and PAND against the mask (tmp1); meaning that we have + // tmp3 = [h1, ...., h16]. + tmp3 := m.copyToTmp(rn.reg()) + psrlw := m.allocateInstr() + psrlw.asXmmRmiReg(sseOpcodePsrlw, newOperandImm32(4), tmp3) + m.insert(psrlw) + + pand2 := m.allocateInstr() + pand2.asXmmRmR(sseOpcodePand, newOperandReg(tmp1), tmp3) + m.insert(pand2) + + // Read the popcntTable into tmp4, and we have + // tmp4 = [0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04] + tmp4 := m.c.AllocateVReg(ssa.TypeV128) + m.lowerVconst(tmp4, 0x03_02_02_01_02_01_01_00, 0x04_03_03_02_03_02_02_01) + + // Make a copy for later. + tmp5 := m.copyToTmp(tmp4) + + // tmp4 = [popcnt(l1), ..., popcnt(l16)]. + pshufb := m.allocateInstr() + pshufb.asXmmRmR(sseOpcodePshufb, newOperandReg(tmp2), tmp4) + m.insert(pshufb) + + pshufb2 := m.allocateInstr() + pshufb2.asXmmRmR(sseOpcodePshufb, newOperandReg(tmp3), tmp5) + m.insert(pshufb2) + + // tmp4 + tmp5 is the result. + paddb := m.allocateInstr() + paddb.asXmmRmR(sseOpcodePaddb, newOperandReg(tmp4), tmp5) + m.insert(paddb) + + m.copyTo(tmp5, rd) +} + +func (m *machine) lowerVImul(instr *ssa.Instruction) { + x, y, lane := instr.Arg2WithLane() + rd := m.c.VRegOf(instr.Return()) + if lane == ssa.VecLaneI64x2 { + rn := m.getOperand_Reg(m.c.ValueDefinition(x)) + rm := m.getOperand_Reg(m.c.ValueDefinition(y)) + // Assuming that we have + // rm = [p1, p2] = [p1_lo, p1_hi, p2_lo, p2_high] + // rn = [q1, q2] = [q1_lo, q1_hi, q2_lo, q2_high] + // where pN and qN are 64-bit (quad word) lane, and pN_lo, pN_hi, qN_lo and qN_hi are 32-bit (double word) lane. + + // Copy rn into tmp1. + tmp1 := m.copyToTmp(rn.reg()) + + // And do the logical right shift by 32-bit on tmp1, which makes tmp1 = [0, p1_high, 0, p2_high] + shift := m.allocateInstr() + shift.asXmmRmiReg(sseOpcodePsrlq, newOperandImm32(32), tmp1) + m.insert(shift) + + // Execute "pmuludq rm,tmp1", which makes tmp1 = [p1_high*q1_lo, p2_high*q2_lo] where each lane is 64-bit. + mul := m.allocateInstr() + mul.asXmmRmR(sseOpcodePmuludq, rm, tmp1) + m.insert(mul) + + // Copy rm value into tmp2. + tmp2 := m.copyToTmp(rm.reg()) + + // And do the logical right shift by 32-bit on tmp2, which makes tmp2 = [0, q1_high, 0, q2_high] + shift2 := m.allocateInstr() + shift2.asXmmRmiReg(sseOpcodePsrlq, newOperandImm32(32), tmp2) + m.insert(shift2) + + // Execute "pmuludq rm,tmp2", which makes tmp2 = [p1_lo*q1_high, p2_lo*q2_high] where each lane is 64-bit. + mul2 := m.allocateInstr() + mul2.asXmmRmR(sseOpcodePmuludq, rn, tmp2) + m.insert(mul2) + + // Adds tmp1 and tmp2 and do the logical left shift by 32-bit, + // which makes tmp1 = [(p1_lo*q1_high+p1_high*q1_lo)<<32, (p2_lo*q2_high+p2_high*q2_lo)<<32] + add := m.allocateInstr() + add.asXmmRmR(sseOpcodePaddq, newOperandReg(tmp2), tmp1) + m.insert(add) + + shift3 := m.allocateInstr() + shift3.asXmmRmiReg(sseOpcodePsllq, newOperandImm32(32), tmp1) + m.insert(shift3) + + // Copy rm value into tmp3. + tmp3 := m.copyToTmp(rm.reg()) + + // "pmuludq rm,tmp3" makes tmp3 = [p1_lo*q1_lo, p2_lo*q2_lo] where each lane is 64-bit. + mul3 := m.allocateInstr() + mul3.asXmmRmR(sseOpcodePmuludq, rn, tmp3) + m.insert(mul3) + + // Finally, we get the result by computing tmp1 + tmp3, + // which makes tmp1 = [(p1_lo*q1_high+p1_high*q1_lo)<<32+p1_lo*q1_lo, (p2_lo*q2_high+p2_high*q2_lo)<<32+p2_lo*q2_lo] + add2 := m.allocateInstr() + add2.asXmmRmR(sseOpcodePaddq, newOperandReg(tmp3), tmp1) + m.insert(add2) + + m.copyTo(tmp1, rd) + + } else { + var vecOp sseOpcode + switch lane { + case ssa.VecLaneI16x8: + vecOp = sseOpcodePmullw + case ssa.VecLaneI32x4: + vecOp = sseOpcodePmulld + default: + panic("unsupported: " + lane.String()) + } + m.lowerVbBinOp(vecOp, x, y, instr.Return()) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/operands.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/operands.go new file mode 100644 index 00000000..78797568 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/operands.go @@ -0,0 +1,336 @@ +package amd64 + +import ( + "fmt" + "unsafe" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +type operand struct { + kind operandKind + data uint64 +} + +type operandKind byte + +const ( + // operandKindReg is an operand which is an integer Register. + operandKindReg operandKind = iota + 1 + + // operandKindMem is a value in Memory. + // 32, 64, or 128 bit value. + operandKindMem + + // operandKindImm32 is a signed-32-bit integer immediate value. + operandKindImm32 + + // operandKindLabel is a label. + operandKindLabel +) + +// String implements fmt.Stringer. +func (o operandKind) String() string { + switch o { + case operandKindReg: + return "reg" + case operandKindMem: + return "mem" + case operandKindImm32: + return "imm32" + case operandKindLabel: + return "label" + default: + panic("BUG: invalid operand kind") + } +} + +// format returns the string representation of the operand. +// _64 is only for the case where the operand is a register, and it's integer. +func (o *operand) format(_64 bool) string { + switch o.kind { + case operandKindReg: + return formatVRegSized(o.reg(), _64) + case operandKindMem: + return o.addressMode().String() + case operandKindImm32: + return fmt.Sprintf("$%d", int32(o.imm32())) + case operandKindLabel: + return label(o.imm32()).String() + default: + panic(fmt.Sprintf("BUG: invalid operand: %s", o.kind)) + } +} + +//go:inline +func (o *operand) reg() regalloc.VReg { + return regalloc.VReg(o.data) +} + +//go:inline +func (o *operand) setReg(r regalloc.VReg) { + o.data = uint64(r) +} + +//go:inline +func (o *operand) addressMode() *amode { + return wazevoapi.PtrFromUintptr[amode](uintptr(o.data)) +} + +//go:inline +func (o *operand) imm32() uint32 { + return uint32(o.data) +} + +func (o *operand) label() label { + switch o.kind { + case operandKindLabel: + return label(o.data) + case operandKindMem: + mem := o.addressMode() + if mem.kind() != amodeRipRel { + panic("BUG: invalid label") + } + return label(mem.imm32) + default: + panic("BUG: invalid operand kind") + } +} + +func newOperandLabel(label label) operand { + return operand{kind: operandKindLabel, data: uint64(label)} +} + +func newOperandReg(r regalloc.VReg) operand { + return operand{kind: operandKindReg, data: uint64(r)} +} + +func newOperandImm32(imm32 uint32) operand { + return operand{kind: operandKindImm32, data: uint64(imm32)} +} + +func newOperandMem(amode *amode) operand { + return operand{kind: operandKindMem, data: uint64(uintptr(unsafe.Pointer(amode)))} +} + +// amode is a memory operand (addressing mode). +type amode struct { + kindWithShift uint32 + imm32 uint32 + base regalloc.VReg + + // For amodeRegRegShift: + index regalloc.VReg +} + +type amodeKind byte + +const ( + // amodeRegRegShift calculates sign-extend-32-to-64(Immediate) + base + amodeImmReg amodeKind = iota + 1 + + // amodeImmRBP is the same as amodeImmReg, but the base register is fixed to RBP. + // The only differece is that it doesn't tell the register allocator to use RBP which is distracting for the + // register allocator. + amodeImmRBP + + // amodeRegRegShift calculates sign-extend-32-to-64(Immediate) + base + (Register2 << Shift) + amodeRegRegShift + + // amodeRipRel is a RIP-relative addressing mode specified by the label. + amodeRipRel + + // TODO: there are other addressing modes such as the one without base register. +) + +func (a *amode) kind() amodeKind { + return amodeKind(a.kindWithShift & 0xff) +} + +func (a *amode) shift() byte { + return byte(a.kindWithShift >> 8) +} + +func (a *amode) uses(rs *[]regalloc.VReg) { + switch a.kind() { + case amodeImmReg: + *rs = append(*rs, a.base) + case amodeRegRegShift: + *rs = append(*rs, a.base, a.index) + case amodeImmRBP, amodeRipRel: + default: + panic("BUG: invalid amode kind") + } +} + +func (a *amode) nregs() int { + switch a.kind() { + case amodeImmReg: + return 1 + case amodeRegRegShift: + return 2 + case amodeImmRBP, amodeRipRel: + return 0 + default: + panic("BUG: invalid amode kind") + } +} + +func (a *amode) assignUses(i int, reg regalloc.VReg) { + switch a.kind() { + case amodeImmReg: + if i == 0 { + a.base = reg + } else { + panic("BUG: invalid amode assignment") + } + case amodeRegRegShift: + if i == 0 { + a.base = reg + } else if i == 1 { + a.index = reg + } else { + panic("BUG: invalid amode assignment") + } + default: + panic("BUG: invalid amode assignment") + } +} + +func (m *machine) newAmodeImmReg(imm32 uint32, base regalloc.VReg) *amode { + ret := m.amodePool.Allocate() + *ret = amode{kindWithShift: uint32(amodeImmReg), imm32: imm32, base: base} + return ret +} + +func (m *machine) newAmodeImmRBPReg(imm32 uint32) *amode { + ret := m.amodePool.Allocate() + *ret = amode{kindWithShift: uint32(amodeImmRBP), imm32: imm32, base: rbpVReg} + return ret +} + +func (m *machine) newAmodeRegRegShift(imm32 uint32, base, index regalloc.VReg, shift byte) *amode { + if shift > 3 { + panic(fmt.Sprintf("BUG: invalid shift (must be 3>=): %d", shift)) + } + ret := m.amodePool.Allocate() + *ret = amode{kindWithShift: uint32(amodeRegRegShift) | uint32(shift)<<8, imm32: imm32, base: base, index: index} + return ret +} + +func (m *machine) newAmodeRipRel(label label) *amode { + ret := m.amodePool.Allocate() + *ret = amode{kindWithShift: uint32(amodeRipRel), imm32: uint32(label)} + return ret +} + +// String implements fmt.Stringer. +func (a *amode) String() string { + switch a.kind() { + case amodeImmReg, amodeImmRBP: + if a.imm32 == 0 { + return fmt.Sprintf("(%s)", formatVRegSized(a.base, true)) + } + return fmt.Sprintf("%d(%s)", int32(a.imm32), formatVRegSized(a.base, true)) + case amodeRegRegShift: + shift := 1 << a.shift() + if a.imm32 == 0 { + return fmt.Sprintf( + "(%s,%s,%d)", + formatVRegSized(a.base, true), formatVRegSized(a.index, true), shift) + } + return fmt.Sprintf( + "%d(%s,%s,%d)", + int32(a.imm32), formatVRegSized(a.base, true), formatVRegSized(a.index, true), shift) + case amodeRipRel: + return fmt.Sprintf("%s(%%rip)", label(a.imm32)) + default: + panic("BUG: invalid amode kind") + } +} + +func (m *machine) getOperand_Mem_Reg(def backend.SSAValueDefinition) (op operand) { + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) + } + + if def.V.Type() == ssa.TypeV128 { + // SIMD instructions require strict memory alignment, so we don't support the memory operand for V128 at the moment. + return m.getOperand_Reg(def) + } + + if m.c.MatchInstr(def, ssa.OpcodeLoad) { + instr := def.Instr + ptr, offset, _ := instr.LoadData() + op = newOperandMem(m.lowerToAddressMode(ptr, offset)) + instr.MarkLowered() + return op + } + return m.getOperand_Reg(def) +} + +func (m *machine) getOperand_Mem_Imm32_Reg(def backend.SSAValueDefinition) (op operand) { + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) + } + + if m.c.MatchInstr(def, ssa.OpcodeLoad) { + instr := def.Instr + ptr, offset, _ := instr.LoadData() + op = newOperandMem(m.lowerToAddressMode(ptr, offset)) + instr.MarkLowered() + return op + } + return m.getOperand_Imm32_Reg(def) +} + +func (m *machine) getOperand_Imm32_Reg(def backend.SSAValueDefinition) (op operand) { + if !def.IsFromInstr() { + return newOperandReg(m.c.VRegOf(def.V)) + } + + instr := def.Instr + if instr.Constant() { + // If the operation is 64-bit, x64 sign-extends the 32-bit immediate value. + // Therefore, we need to check if the immediate value is within the 32-bit range and if the sign bit is set, + // we should not use the immediate value. + if op, ok := asImm32Operand(instr.ConstantVal(), instr.Return().Type() == ssa.TypeI32); ok { + instr.MarkLowered() + return op + } + } + return m.getOperand_Reg(def) +} + +func asImm32Operand(val uint64, allowSignExt bool) (operand, bool) { + if imm32, ok := asImm32(val, allowSignExt); ok { + return newOperandImm32(imm32), true + } + return operand{}, false +} + +func asImm32(val uint64, allowSignExt bool) (uint32, bool) { + u32val := uint32(val) + if uint64(u32val) != val { + return 0, false + } + if !allowSignExt && u32val&0x80000000 != 0 { + return 0, false + } + return u32val, true +} + +func (m *machine) getOperand_Reg(def backend.SSAValueDefinition) (op operand) { + var v regalloc.VReg + if instr := def.Instr; instr != nil && instr.Constant() { + // We inline all the constant instructions so that we could reduce the register usage. + v = m.lowerConstant(instr) + instr.MarkLowered() + } else { + v = m.c.VRegOf(def.V) + } + return newOperandReg(v) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/reg.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/reg.go new file mode 100644 index 00000000..4aec856f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/reg.go @@ -0,0 +1,181 @@ +package amd64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" +) + +// Amd64-specific registers. +const ( + // rax is a gp register. + rax = regalloc.RealRegInvalid + 1 + iota + // rcx is a gp register. + rcx + // rdx is a gp register. + rdx + // rbx is a gp register. + rbx + // rsp is a gp register. + rsp + // rbp is a gp register. + rbp + // rsi is a gp register. + rsi + // rdi is a gp register. + rdi + // r8 is a gp register. + r8 + // r9 is a gp register. + r9 + // r10 is a gp register. + r10 + // r11 is a gp register. + r11 + // r12 is a gp register. + r12 + // r13 is a gp register. + r13 + // r14 is a gp register. + r14 + // r15 is a gp register. + r15 + + // xmm0 is a vector register. + xmm0 + // xmm1 is a vector register. + xmm1 + // xmm2 is a vector register. + xmm2 + // xmm3 is a vector register. + xmm3 + // xmm4 is a vector register. + xmm4 + // xmm5 is a vector register. + xmm5 + // xmm6 is a vector register. + xmm6 + // xmm7 is a vector register. + xmm7 + // xmm8 is a vector register. + xmm8 + // xmm9 is a vector register. + xmm9 + // xmm10 is a vector register. + xmm10 + // xmm11 is a vector register. + xmm11 + // xmm12 is a vector register. + xmm12 + // xmm13 is a vector register. + xmm13 + // xmm14 is a vector register. + xmm14 + // xmm15 is a vector register. + xmm15 +) + +var ( + raxVReg = regalloc.FromRealReg(rax, regalloc.RegTypeInt) + rcxVReg = regalloc.FromRealReg(rcx, regalloc.RegTypeInt) + rdxVReg = regalloc.FromRealReg(rdx, regalloc.RegTypeInt) + rbxVReg = regalloc.FromRealReg(rbx, regalloc.RegTypeInt) + rspVReg = regalloc.FromRealReg(rsp, regalloc.RegTypeInt) + rbpVReg = regalloc.FromRealReg(rbp, regalloc.RegTypeInt) + rsiVReg = regalloc.FromRealReg(rsi, regalloc.RegTypeInt) + rdiVReg = regalloc.FromRealReg(rdi, regalloc.RegTypeInt) + r8VReg = regalloc.FromRealReg(r8, regalloc.RegTypeInt) + r9VReg = regalloc.FromRealReg(r9, regalloc.RegTypeInt) + r10VReg = regalloc.FromRealReg(r10, regalloc.RegTypeInt) + r11VReg = regalloc.FromRealReg(r11, regalloc.RegTypeInt) + r12VReg = regalloc.FromRealReg(r12, regalloc.RegTypeInt) + r13VReg = regalloc.FromRealReg(r13, regalloc.RegTypeInt) + r14VReg = regalloc.FromRealReg(r14, regalloc.RegTypeInt) + r15VReg = regalloc.FromRealReg(r15, regalloc.RegTypeInt) + + xmm0VReg = regalloc.FromRealReg(xmm0, regalloc.RegTypeFloat) + xmm1VReg = regalloc.FromRealReg(xmm1, regalloc.RegTypeFloat) + xmm2VReg = regalloc.FromRealReg(xmm2, regalloc.RegTypeFloat) + xmm3VReg = regalloc.FromRealReg(xmm3, regalloc.RegTypeFloat) + xmm4VReg = regalloc.FromRealReg(xmm4, regalloc.RegTypeFloat) + xmm5VReg = regalloc.FromRealReg(xmm5, regalloc.RegTypeFloat) + xmm6VReg = regalloc.FromRealReg(xmm6, regalloc.RegTypeFloat) + xmm7VReg = regalloc.FromRealReg(xmm7, regalloc.RegTypeFloat) + xmm8VReg = regalloc.FromRealReg(xmm8, regalloc.RegTypeFloat) + xmm9VReg = regalloc.FromRealReg(xmm9, regalloc.RegTypeFloat) + xmm10VReg = regalloc.FromRealReg(xmm10, regalloc.RegTypeFloat) + xmm11VReg = regalloc.FromRealReg(xmm11, regalloc.RegTypeFloat) + xmm12VReg = regalloc.FromRealReg(xmm12, regalloc.RegTypeFloat) + xmm13VReg = regalloc.FromRealReg(xmm13, regalloc.RegTypeFloat) + xmm14VReg = regalloc.FromRealReg(xmm14, regalloc.RegTypeFloat) + xmm15VReg = regalloc.FromRealReg(xmm15, regalloc.RegTypeFloat) +) + +var regNames = [...]string{ + rax: "rax", + rcx: "rcx", + rdx: "rdx", + rbx: "rbx", + rsp: "rsp", + rbp: "rbp", + rsi: "rsi", + rdi: "rdi", + r8: "r8", + r9: "r9", + r10: "r10", + r11: "r11", + r12: "r12", + r13: "r13", + r14: "r14", + r15: "r15", + xmm0: "xmm0", + xmm1: "xmm1", + xmm2: "xmm2", + xmm3: "xmm3", + xmm4: "xmm4", + xmm5: "xmm5", + xmm6: "xmm6", + xmm7: "xmm7", + xmm8: "xmm8", + xmm9: "xmm9", + xmm10: "xmm10", + xmm11: "xmm11", + xmm12: "xmm12", + xmm13: "xmm13", + xmm14: "xmm14", + xmm15: "xmm15", +} + +func formatVRegSized(r regalloc.VReg, _64 bool) string { + if r.IsRealReg() { + if r.RegType() == regalloc.RegTypeInt { + rr := r.RealReg() + orig := regNames[rr] + if rr <= rdi { + if _64 { + return "%" + orig + } else { + return "%e" + orig[1:] + } + } else { + if _64 { + return "%" + orig + } else { + return "%" + orig + "d" + } + } + } else { + return "%" + regNames[r.RealReg()] + } + } else { + if r.RegType() == regalloc.RegTypeInt { + if _64 { + return fmt.Sprintf("%%r%d?", r.ID()) + } else { + return fmt.Sprintf("%%r%dd?", r.ID()) + } + } else { + return fmt.Sprintf("%%xmm%d?", r.ID()) + } + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/stack.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/stack.go new file mode 100644 index 00000000..ef823bdb --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64/stack.go @@ -0,0 +1,130 @@ +package amd64 + +import ( + "encoding/binary" + "reflect" + "unsafe" + + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +func stackView(rbp, top uintptr) []byte { + l := int(top - rbp) + var stackBuf []byte + { + //nolint:staticcheck + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&stackBuf)) + hdr.Data = rbp + hdr.Len = l + hdr.Cap = l + } + return stackBuf +} + +// UnwindStack implements wazevo.unwindStack. +func UnwindStack(_, rbp, top uintptr, returnAddresses []uintptr) []uintptr { + stackBuf := stackView(rbp, top) + + for i := uint64(0); i < uint64(len(stackBuf)); { + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <---- Caller_RBP + // | ........... | + // | clobbered M | + // | ............ | + // | clobbered 0 | + // | spill slot N | + // | ............ | + // | spill slot 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <---- RBP + // (low address) + + callerRBP := binary.LittleEndian.Uint64(stackBuf[i:]) + retAddr := binary.LittleEndian.Uint64(stackBuf[i+8:]) + returnAddresses = append(returnAddresses, uintptr(retAddr)) + i = callerRBP - uint64(rbp) + if len(returnAddresses) == wasmdebug.MaxFrames { + break + } + } + return returnAddresses +} + +// GoCallStackView implements wazevo.goCallStackView. +func GoCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { + // (high address) + // +-----------------+ <----+ + // | xxxxxxxxxxx | | ;; optional unused space to make it 16-byte aligned. + // ^ | arg[N]/ret[M] | | + // sliceSize | | ............ | | SizeInBytes/8 + // | | arg[1]/ret[1] | | + // v | arg[0]/ret[0] | <----+ + // | SizeInBytes | + // +-----------------+ <---- stackPointerBeforeGoCall + // (low address) + data := unsafe.Add(unsafe.Pointer(stackPointerBeforeGoCall), 8) + size := *stackPointerBeforeGoCall / 8 + return unsafe.Slice((*uint64)(data), size) +} + +func AdjustClonedStack(oldRsp, oldTop, rsp, rbp, top uintptr) { + diff := uint64(rsp - oldRsp) + + newBuf := stackView(rbp, top) + for i := uint64(0); i < uint64(len(newBuf)); { + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <---- Caller_RBP + // | ........... | + // | clobbered M | + // | ............ | + // | clobbered 0 | + // | spill slot N | + // | ............ | + // | spill slot 0 | + // | ReturnAddress | + // | Caller_RBP | + // +-----------------+ <---- RBP + // (low address) + + callerRBP := binary.LittleEndian.Uint64(newBuf[i:]) + if callerRBP == 0 { + // End of stack. + break + } + if i64 := int64(callerRBP); i64 < int64(oldRsp) || i64 >= int64(oldTop) { + panic("BUG: callerRBP is out of range") + } + if int(callerRBP) < 0 { + panic("BUG: callerRBP is negative") + } + adjustedCallerRBP := callerRBP + diff + if int(adjustedCallerRBP) < 0 { + panic("BUG: adjustedCallerRBP is negative") + } + binary.LittleEndian.PutUint64(newBuf[i:], adjustedCallerRBP) + i = adjustedCallerRBP - uint64(rbp) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi.go new file mode 100644 index 00000000..d1eaa7cd --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi.go @@ -0,0 +1,333 @@ +package arm64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// References: +// * https://github.com/golang/go/blob/49d42128fd8594c172162961ead19ac95e247d24/src/cmd/compile/abi-internal.md#arm64-architecture +// * https://developer.arm.com/documentation/102374/0101/Procedure-Call-Standard + +var ( + intParamResultRegs = []regalloc.RealReg{x0, x1, x2, x3, x4, x5, x6, x7} + floatParamResultRegs = []regalloc.RealReg{v0, v1, v2, v3, v4, v5, v6, v7} +) + +var regInfo = ®alloc.RegisterInfo{ + AllocatableRegisters: [regalloc.NumRegType][]regalloc.RealReg{ + // We don't allocate: + // - x18: Reserved by the macOS: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers + // - x28: Reserved by Go runtime. + // - x27(=tmpReg): because of the reason described on tmpReg. + regalloc.RegTypeInt: { + x8, x9, x10, x11, x12, x13, x14, x15, + x16, x17, x19, x20, x21, x22, x23, x24, x25, + x26, x29, x30, + // These are the argument/return registers. Less preferred in the allocation. + x7, x6, x5, x4, x3, x2, x1, x0, + }, + regalloc.RegTypeFloat: { + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, + // These are the argument/return registers. Less preferred in the allocation. + v7, v6, v5, v4, v3, v2, v1, v0, + }, + }, + CalleeSavedRegisters: regalloc.NewRegSet( + x19, x20, x21, x22, x23, x24, x25, x26, x28, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + ), + CallerSavedRegisters: regalloc.NewRegSet( + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x29, x30, + v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + ), + RealRegToVReg: []regalloc.VReg{ + x0: x0VReg, x1: x1VReg, x2: x2VReg, x3: x3VReg, x4: x4VReg, x5: x5VReg, x6: x6VReg, x7: x7VReg, x8: x8VReg, x9: x9VReg, x10: x10VReg, x11: x11VReg, x12: x12VReg, x13: x13VReg, x14: x14VReg, x15: x15VReg, x16: x16VReg, x17: x17VReg, x18: x18VReg, x19: x19VReg, x20: x20VReg, x21: x21VReg, x22: x22VReg, x23: x23VReg, x24: x24VReg, x25: x25VReg, x26: x26VReg, x27: x27VReg, x28: x28VReg, x29: x29VReg, x30: x30VReg, + v0: v0VReg, v1: v1VReg, v2: v2VReg, v3: v3VReg, v4: v4VReg, v5: v5VReg, v6: v6VReg, v7: v7VReg, v8: v8VReg, v9: v9VReg, v10: v10VReg, v11: v11VReg, v12: v12VReg, v13: v13VReg, v14: v14VReg, v15: v15VReg, v16: v16VReg, v17: v17VReg, v18: v18VReg, v19: v19VReg, v20: v20VReg, v21: v21VReg, v22: v22VReg, v23: v23VReg, v24: v24VReg, v25: v25VReg, v26: v26VReg, v27: v27VReg, v28: v28VReg, v29: v29VReg, v30: v30VReg, v31: v31VReg, + }, + RealRegName: func(r regalloc.RealReg) string { return regNames[r] }, + RealRegType: func(r regalloc.RealReg) regalloc.RegType { + if r < v0 { + return regalloc.RegTypeInt + } + return regalloc.RegTypeFloat + }, +} + +// ArgsResultsRegs implements backend.Machine. +func (m *machine) ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) { + return intParamResultRegs, floatParamResultRegs +} + +// LowerParams implements backend.FunctionABI. +func (m *machine) LowerParams(args []ssa.Value) { + a := m.currentABI + + for i, ssaArg := range args { + if !ssaArg.Valid() { + continue + } + reg := m.compiler.VRegOf(ssaArg) + arg := &a.Args[i] + if arg.Kind == backend.ABIArgKindReg { + m.InsertMove(reg, arg.Reg, arg.Type) + } else { + // TODO: we could use pair load if there's consecutive loads for the same type. + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | <-| + // | ReturnAddress | | + // +-----------------+ | + // | ........... | | + // | clobbered M | | argStackOffset: is unknown at this point of compilation. + // | ............ | | + // | clobbered 0 | | + // | spill slot N | | + // | ........... | | + // | spill slot 0 | | + // SP---> +-----------------+ <-+ + // (low address) + + bits := arg.Type.Bits() + // At this point of compilation, we don't yet know how much space exist below the return address. + // So we instruct the address mode to add the `argStackOffset` to the offset at the later phase of compilation. + amode := m.amodePool.Allocate() + *amode = addressMode{imm: arg.Offset, rn: spVReg, kind: addressModeKindArgStackSpace} + load := m.allocateInstr() + switch arg.Type { + case ssa.TypeI32, ssa.TypeI64: + load.asULoad(reg, amode, bits) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + load.asFpuLoad(reg, amode, bits) + default: + panic("BUG") + } + m.insert(load) + m.unresolvedAddressModes = append(m.unresolvedAddressModes, load) + } + } +} + +// LowerReturns lowers the given returns. +func (m *machine) LowerReturns(rets []ssa.Value) { + a := m.currentABI + + l := len(rets) - 1 + for i := range rets { + // Reverse order in order to avoid overwriting the stack returns existing in the return registers. + ret := rets[l-i] + r := &a.Rets[l-i] + reg := m.compiler.VRegOf(ret) + if def := m.compiler.ValueDefinition(ret); def.IsFromInstr() { + // Constant instructions are inlined. + if inst := def.Instr; inst.Constant() { + val := inst.Return() + valType := val.Type() + v := inst.ConstantVal() + m.insertLoadConstant(v, valType, reg) + } + } + if r.Kind == backend.ABIArgKindReg { + m.InsertMove(r.Reg, reg, ret.Type()) + } else { + // TODO: we could use pair store if there's consecutive stores for the same type. + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | <-+ + // | arg X | | + // | ....... | | + // | arg 1 | | + // | arg 0 | | + // | ReturnAddress | | + // +-----------------+ | + // | ........... | | + // | spill slot M | | retStackOffset: is unknown at this point of compilation. + // | ............ | | + // | spill slot 2 | | + // | spill slot 1 | | + // | clobbered 0 | | + // | clobbered 1 | | + // | ........... | | + // | clobbered N | | + // SP---> +-----------------+ <-+ + // (low address) + + bits := r.Type.Bits() + + // At this point of compilation, we don't yet know how much space exist below the return address. + // So we instruct the address mode to add the `retStackOffset` to the offset at the later phase of compilation. + amode := m.amodePool.Allocate() + *amode = addressMode{imm: r.Offset, rn: spVReg, kind: addressModeKindResultStackSpace} + store := m.allocateInstr() + store.asStore(operandNR(reg), amode, bits) + m.insert(store) + m.unresolvedAddressModes = append(m.unresolvedAddressModes, store) + } + } +} + +// callerGenVRegToFunctionArg is the opposite of GenFunctionArgToVReg, which is used to generate the +// caller side of the function call. +func (m *machine) callerGenVRegToFunctionArg(a *backend.FunctionABI, argIndex int, reg regalloc.VReg, def backend.SSAValueDefinition, slotBegin int64) { + arg := &a.Args[argIndex] + if def.IsFromInstr() { + // Constant instructions are inlined. + if inst := def.Instr; inst.Constant() { + val := inst.Return() + valType := val.Type() + v := inst.ConstantVal() + m.insertLoadConstant(v, valType, reg) + } + } + if arg.Kind == backend.ABIArgKindReg { + m.InsertMove(arg.Reg, reg, arg.Type) + } else { + // TODO: we could use pair store if there's consecutive stores for the same type. + // + // Note that at this point, stack pointer is already adjusted. + bits := arg.Type.Bits() + amode := m.resolveAddressModeForOffset(arg.Offset-slotBegin, bits, spVReg, false) + store := m.allocateInstr() + store.asStore(operandNR(reg), amode, bits) + m.insert(store) + } +} + +func (m *machine) callerGenFunctionReturnVReg(a *backend.FunctionABI, retIndex int, reg regalloc.VReg, slotBegin int64) { + r := &a.Rets[retIndex] + if r.Kind == backend.ABIArgKindReg { + m.InsertMove(reg, r.Reg, r.Type) + } else { + // TODO: we could use pair load if there's consecutive loads for the same type. + amode := m.resolveAddressModeForOffset(a.ArgStackSize+r.Offset-slotBegin, r.Type.Bits(), spVReg, false) + ldr := m.allocateInstr() + switch r.Type { + case ssa.TypeI32, ssa.TypeI64: + ldr.asULoad(reg, amode, r.Type.Bits()) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + ldr.asFpuLoad(reg, amode, r.Type.Bits()) + default: + panic("BUG") + } + m.insert(ldr) + } +} + +func (m *machine) resolveAddressModeForOffsetAndInsert(cur *instruction, offset int64, dstBits byte, rn regalloc.VReg, allowTmpRegUse bool) (*instruction, *addressMode) { + m.pendingInstructions = m.pendingInstructions[:0] + mode := m.resolveAddressModeForOffset(offset, dstBits, rn, allowTmpRegUse) + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + return cur, mode +} + +func (m *machine) resolveAddressModeForOffset(offset int64, dstBits byte, rn regalloc.VReg, allowTmpRegUse bool) *addressMode { + if rn.RegType() != regalloc.RegTypeInt { + panic("BUG: rn should be a pointer: " + formatVRegSized(rn, 64)) + } + amode := m.amodePool.Allocate() + if offsetFitsInAddressModeKindRegUnsignedImm12(dstBits, offset) { + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: rn, imm: offset} + } else if offsetFitsInAddressModeKindRegSignedImm9(offset) { + *amode = addressMode{kind: addressModeKindRegSignedImm9, rn: rn, imm: offset} + } else { + var indexReg regalloc.VReg + if allowTmpRegUse { + m.lowerConstantI64(tmpRegVReg, offset) + indexReg = tmpRegVReg + } else { + indexReg = m.compiler.AllocateVReg(ssa.TypeI64) + m.lowerConstantI64(indexReg, offset) + } + *amode = addressMode{kind: addressModeKindRegReg, rn: rn, rm: indexReg, extOp: extendOpUXTX /* indicates index rm is 64-bit */} + } + return amode +} + +func (m *machine) lowerCall(si *ssa.Instruction) { + isDirectCall := si.Opcode() == ssa.OpcodeCall + var indirectCalleePtr ssa.Value + var directCallee ssa.FuncRef + var sigID ssa.SignatureID + var args []ssa.Value + if isDirectCall { + directCallee, sigID, args = si.CallData() + } else { + indirectCalleePtr, sigID, args, _ /* on arm64, the calling convention is compatible with the Go runtime */ = si.CallIndirectData() + } + calleeABI := m.compiler.GetFunctionABI(m.compiler.SSABuilder().ResolveSignature(sigID)) + + stackSlotSize := int64(calleeABI.AlignedArgResultStackSlotSize()) + if m.maxRequiredStackSizeForCalls < stackSlotSize+16 { + m.maxRequiredStackSizeForCalls = stackSlotSize + 16 // return address frame. + } + + for i, arg := range args { + reg := m.compiler.VRegOf(arg) + def := m.compiler.ValueDefinition(arg) + m.callerGenVRegToFunctionArg(calleeABI, i, reg, def, stackSlotSize) + } + + if isDirectCall { + call := m.allocateInstr() + call.asCall(directCallee, calleeABI) + m.insert(call) + } else { + ptr := m.compiler.VRegOf(indirectCalleePtr) + callInd := m.allocateInstr() + callInd.asCallIndirect(ptr, calleeABI) + m.insert(callInd) + } + + var index int + r1, rs := si.Returns() + if r1.Valid() { + m.callerGenFunctionReturnVReg(calleeABI, 0, m.compiler.VRegOf(r1), stackSlotSize) + index++ + } + + for _, r := range rs { + m.callerGenFunctionReturnVReg(calleeABI, index, m.compiler.VRegOf(r), stackSlotSize) + index++ + } +} + +func (m *machine) insertAddOrSubStackPointer(rd regalloc.VReg, diff int64, add bool) { + if imm12Operand, ok := asImm12Operand(uint64(diff)); ok { + alu := m.allocateInstr() + var ao aluOp + if add { + ao = aluOpAdd + } else { + ao = aluOpSub + } + alu.asALU(ao, rd, operandNR(spVReg), imm12Operand, true) + m.insert(alu) + } else { + m.lowerConstantI64(tmpRegVReg, diff) + alu := m.allocateInstr() + var ao aluOp + if add { + ao = aluOpAdd + } else { + ao = aluOpSub + } + alu.asALU(ao, rd, operandNR(spVReg), operandNR(tmpRegVReg), true) + m.insert(alu) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.go new file mode 100644 index 00000000..5f0c613d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.go @@ -0,0 +1,9 @@ +package arm64 + +// entrypoint enters the machine code generated by this backend which begins with the preamble generated by functionABI.EmitGoEntryPreamble below. +// This implements wazevo.entrypoint, and see the comments there for detail. +func entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultPtr *uint64, goAllocatedStackSlicePtr uintptr) + +// afterGoFunctionCallEntrypoint enters the machine code after growing the stack. +// This implements wazevo.afterGoFunctionCallEntrypoint, and see the comments there for detail. +func afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.s b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.s new file mode 100644 index 00000000..0b579f85 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_arm64.s @@ -0,0 +1,29 @@ +//go:build arm64 + +#include "funcdata.h" +#include "textflag.h" + +// See the comments on EmitGoEntryPreamble for what this function is supposed to do. +TEXT ·entrypoint(SB), NOSPLIT|NOFRAME, $0-48 + MOVD preambleExecutable+0(FP), R27 + MOVD functionExectuable+8(FP), R24 + MOVD executionContextPtr+16(FP), R0 + MOVD moduleContextPtr+24(FP), R1 + MOVD paramResultSlicePtr+32(FP), R19 + MOVD goAllocatedStackSlicePtr+40(FP), R26 + JMP (R27) + +TEXT ·afterGoFunctionCallEntrypoint(SB), NOSPLIT|NOFRAME, $0-32 + MOVD goCallReturnAddress+0(FP), R20 + MOVD executionContextPtr+8(FP), R0 + MOVD stackPointer+16(FP), R19 + + // Save the current FP(R29), SP and LR(R30) into the wazevo.executionContext (stored in R0). + MOVD R29, 16(R0) // Store FP(R29) into [RO, #ExecutionContextOffsets.OriginalFramePointer] + MOVD RSP, R27 // Move SP to R27 (temporary register) since SP cannot be stored directly in str instructions. + MOVD R27, 24(R0) // Store R27 into [RO, #ExecutionContextOffsets.OriginalFramePointer] + MOVD R30, 32(R0) // Store R30 into [R0, #ExecutionContextOffsets.GoReturnAddress] + + // Load the new stack pointer (which sits somewhere in Go-allocated stack) into SP. + MOVD R19, RSP + JMP (R20) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_preamble.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_preamble.go new file mode 100644 index 00000000..f8b5d97a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_entry_preamble.go @@ -0,0 +1,233 @@ +package arm64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// CompileEntryPreamble implements backend.Machine. This assumes `entrypoint` function (in abi_go_entry_arm64.s) passes: +// +// 1. First (execution context ptr) and Second arguments are already passed in x0, and x1. +// 2. param/result slice ptr in x19; the pointer to []uint64{} which is used to pass arguments and accept return values. +// 3. Go-allocated stack slice ptr in x26. +// 4. Function executable in x24. +// +// also SP and FP are correct Go-runtime-based values, and LR is the return address to the Go-side caller. +func (m *machine) CompileEntryPreamble(signature *ssa.Signature) []byte { + root := m.constructEntryPreamble(signature) + m.encode(root) + return m.compiler.Buf() +} + +var ( + executionContextPtrReg = x0VReg + // callee-saved regs so that they can be used in the prologue and epilogue. + paramResultSlicePtr = x19VReg + savedExecutionContextPtr = x20VReg + // goAllocatedStackPtr is not used in the epilogue. + goAllocatedStackPtr = x26VReg + // paramResultSliceCopied is not used in the epilogue. + paramResultSliceCopied = x25VReg + // tmpRegVReg is not used in the epilogue. + functionExecutable = x24VReg +) + +func (m *machine) goEntryPreamblePassArg(cur *instruction, paramSlicePtr regalloc.VReg, arg *backend.ABIArg, argStartOffsetFromSP int64) *instruction { + typ := arg.Type + bits := typ.Bits() + isStackArg := arg.Kind == backend.ABIArgKindStack + + var loadTargetReg operand + if !isStackArg { + loadTargetReg = operandNR(arg.Reg) + } else { + switch typ { + case ssa.TypeI32, ssa.TypeI64: + loadTargetReg = operandNR(x15VReg) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + loadTargetReg = operandNR(v15VReg) + default: + panic("TODO?") + } + } + + var postIndexImm int64 + if typ == ssa.TypeV128 { + postIndexImm = 16 // v128 is represented as 2x64-bit in Go slice. + } else { + postIndexImm = 8 + } + loadMode := m.amodePool.Allocate() + *loadMode = addressMode{kind: addressModeKindPostIndex, rn: paramSlicePtr, imm: postIndexImm} + + instr := m.allocateInstr() + switch typ { + case ssa.TypeI32: + instr.asULoad(loadTargetReg.reg(), loadMode, 32) + case ssa.TypeI64: + instr.asULoad(loadTargetReg.reg(), loadMode, 64) + case ssa.TypeF32: + instr.asFpuLoad(loadTargetReg.reg(), loadMode, 32) + case ssa.TypeF64: + instr.asFpuLoad(loadTargetReg.reg(), loadMode, 64) + case ssa.TypeV128: + instr.asFpuLoad(loadTargetReg.reg(), loadMode, 128) + } + cur = linkInstr(cur, instr) + + if isStackArg { + var storeMode *addressMode + cur, storeMode = m.resolveAddressModeForOffsetAndInsert(cur, argStartOffsetFromSP+arg.Offset, bits, spVReg, true) + toStack := m.allocateInstr() + toStack.asStore(loadTargetReg, storeMode, bits) + cur = linkInstr(cur, toStack) + } + return cur +} + +func (m *machine) goEntryPreamblePassResult(cur *instruction, resultSlicePtr regalloc.VReg, result *backend.ABIArg, resultStartOffsetFromSP int64) *instruction { + isStackArg := result.Kind == backend.ABIArgKindStack + typ := result.Type + bits := typ.Bits() + + var storeTargetReg operand + if !isStackArg { + storeTargetReg = operandNR(result.Reg) + } else { + switch typ { + case ssa.TypeI32, ssa.TypeI64: + storeTargetReg = operandNR(x15VReg) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + storeTargetReg = operandNR(v15VReg) + default: + panic("TODO?") + } + } + + var postIndexImm int64 + if typ == ssa.TypeV128 { + postIndexImm = 16 // v128 is represented as 2x64-bit in Go slice. + } else { + postIndexImm = 8 + } + + if isStackArg { + var loadMode *addressMode + cur, loadMode = m.resolveAddressModeForOffsetAndInsert(cur, resultStartOffsetFromSP+result.Offset, bits, spVReg, true) + toReg := m.allocateInstr() + switch typ { + case ssa.TypeI32, ssa.TypeI64: + toReg.asULoad(storeTargetReg.reg(), loadMode, bits) + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + toReg.asFpuLoad(storeTargetReg.reg(), loadMode, bits) + default: + panic("TODO?") + } + cur = linkInstr(cur, toReg) + } + + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindPostIndex, rn: resultSlicePtr, imm: postIndexImm} + instr := m.allocateInstr() + instr.asStore(storeTargetReg, mode, bits) + cur = linkInstr(cur, instr) + return cur +} + +func (m *machine) constructEntryPreamble(sig *ssa.Signature) (root *instruction) { + abi := backend.FunctionABI{} + abi.Init(sig, intParamResultRegs, floatParamResultRegs) + + root = m.allocateNop() + + //// ----------------------------------- prologue ----------------------------------- //// + + // First, we save executionContextPtrReg into a callee-saved register so that it can be used in epilogue as well. + // mov savedExecutionContextPtr, x0 + cur := m.move64(savedExecutionContextPtr, executionContextPtrReg, root) + + // Next, save the current FP, SP and LR into the wazevo.executionContext: + // str fp, [savedExecutionContextPtr, #OriginalFramePointer] + // mov tmp, sp ;; sp cannot be str'ed directly. + // str sp, [savedExecutionContextPtr, #OriginalStackPointer] + // str lr, [savedExecutionContextPtr, #GoReturnAddress] + cur = m.loadOrStoreAtExecutionContext(fpVReg, wazevoapi.ExecutionContextOffsetOriginalFramePointer, true, cur) + cur = m.move64(tmpRegVReg, spVReg, cur) + cur = m.loadOrStoreAtExecutionContext(tmpRegVReg, wazevoapi.ExecutionContextOffsetOriginalStackPointer, true, cur) + cur = m.loadOrStoreAtExecutionContext(lrVReg, wazevoapi.ExecutionContextOffsetGoReturnAddress, true, cur) + + // Then, move the Go-allocated stack pointer to SP: + // mov sp, goAllocatedStackPtr + cur = m.move64(spVReg, goAllocatedStackPtr, cur) + + prReg := paramResultSlicePtr + if len(abi.Args) > 2 && len(abi.Rets) > 0 { + // paramResultSlicePtr is modified during the execution of goEntryPreamblePassArg, + // so copy it to another reg. + cur = m.move64(paramResultSliceCopied, paramResultSlicePtr, cur) + prReg = paramResultSliceCopied + } + + stackSlotSize := int64(abi.AlignedArgResultStackSlotSize()) + for i := range abi.Args { + if i < 2 { + // module context ptr and execution context ptr are passed in x0 and x1 by the Go assembly function. + continue + } + arg := &abi.Args[i] + cur = m.goEntryPreamblePassArg(cur, prReg, arg, -stackSlotSize) + } + + // Call the real function. + bl := m.allocateInstr() + bl.asCallIndirect(functionExecutable, &abi) + cur = linkInstr(cur, bl) + + ///// ----------------------------------- epilogue ----------------------------------- ///// + + // Store the register results into paramResultSlicePtr. + for i := range abi.Rets { + cur = m.goEntryPreamblePassResult(cur, paramResultSlicePtr, &abi.Rets[i], abi.ArgStackSize-stackSlotSize) + } + + // Finally, restore the FP, SP and LR, and return to the Go code. + // ldr fp, [savedExecutionContextPtr, #OriginalFramePointer] + // ldr tmp, [savedExecutionContextPtr, #OriginalStackPointer] + // mov sp, tmp ;; sp cannot be str'ed directly. + // ldr lr, [savedExecutionContextPtr, #GoReturnAddress] + // ret ;; --> return to the Go code + cur = m.loadOrStoreAtExecutionContext(fpVReg, wazevoapi.ExecutionContextOffsetOriginalFramePointer, false, cur) + cur = m.loadOrStoreAtExecutionContext(tmpRegVReg, wazevoapi.ExecutionContextOffsetOriginalStackPointer, false, cur) + cur = m.move64(spVReg, tmpRegVReg, cur) + cur = m.loadOrStoreAtExecutionContext(lrVReg, wazevoapi.ExecutionContextOffsetGoReturnAddress, false, cur) + retInst := m.allocateInstr() + retInst.asRet() + linkInstr(cur, retInst) + return +} + +func (m *machine) move64(dst, src regalloc.VReg, prev *instruction) *instruction { + instr := m.allocateInstr() + instr.asMove64(dst, src) + return linkInstr(prev, instr) +} + +func (m *machine) loadOrStoreAtExecutionContext(d regalloc.VReg, offset wazevoapi.Offset, store bool, prev *instruction) *instruction { + instr := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: savedExecutionContextPtr, imm: offset.I64()} + if store { + instr.asStore(operandNR(d), mode, 64) + } else { + instr.asULoad(d, mode, 64) + } + return linkInstr(prev, instr) +} + +func linkInstr(prev, next *instruction) *instruction { + prev.next = next + next.prev = prev + return next +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_go_call.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_go_call.go new file mode 100644 index 00000000..06f8a4a0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/abi_go_call.go @@ -0,0 +1,430 @@ +package arm64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +var calleeSavedRegistersSorted = []regalloc.VReg{ + x19VReg, x20VReg, x21VReg, x22VReg, x23VReg, x24VReg, x25VReg, x26VReg, x28VReg, + v18VReg, v19VReg, v20VReg, v21VReg, v22VReg, v23VReg, v24VReg, v25VReg, v26VReg, v27VReg, v28VReg, v29VReg, v30VReg, v31VReg, +} + +// CompileGoFunctionTrampoline implements backend.Machine. +func (m *machine) CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte { + argBegin := 1 // Skips exec context by default. + if needModuleContextPtr { + argBegin++ + } + + abi := &backend.FunctionABI{} + abi.Init(sig, intParamResultRegs, floatParamResultRegs) + m.currentABI = abi + + cur := m.allocateInstr() + cur.asNop0() + m.rootInstr = cur + + // Execution context is always the first argument. + execCtrPtr := x0VReg + + // In the following, we create the following stack layout: + // + // (high address) + // SP ------> +-----------------+ <----+ + // | ....... | | + // | ret Y | | + // | ....... | | + // | ret 0 | | + // | arg X | | size_of_arg_ret + // | ....... | | + // | arg 1 | | + // | arg 0 | <----+ <-------- originalArg0Reg + // | size_of_arg_ret | + // | ReturnAddress | + // +-----------------+ <----+ + // | xxxx | | ;; might be padded to make it 16-byte aligned. + // +--->| arg[N]/ret[M] | | + // sliceSize| | ............ | | goCallStackSize + // | | arg[1]/ret[1] | | + // +--->| arg[0]/ret[0] | <----+ <-------- arg0ret0AddrReg + // | sliceSize | + // | frame_size | + // +-----------------+ + // (low address) + // + // where the region of "arg[0]/ret[0] ... arg[N]/ret[M]" is the stack used by the Go functions, + // therefore will be accessed as the usual []uint64. So that's where we need to pass/receive + // the arguments/return values. + + // First of all, to update the SP, and create "ReturnAddress + size_of_arg_ret". + cur = m.createReturnAddrAndSizeOfArgRetSlot(cur) + + const frameInfoSize = 16 // == frame_size + sliceSize. + + // Next, we should allocate the stack for the Go function call if necessary. + goCallStackSize, sliceSizeInBytes := backend.GoFunctionCallRequiredStackSize(sig, argBegin) + cur = m.insertStackBoundsCheck(goCallStackSize+frameInfoSize, cur) + + originalArg0Reg := x17VReg // Caller save, so we can use it for whatever we want. + if m.currentABI.AlignedArgResultStackSlotSize() > 0 { + // At this point, SP points to `ReturnAddress`, so add 16 to get the original arg 0 slot. + cur = m.addsAddOrSubStackPointer(cur, originalArg0Reg, frameInfoSize, true) + } + + // Save the callee saved registers. + cur = m.saveRegistersInExecutionContext(cur, calleeSavedRegistersSorted) + + if needModuleContextPtr { + offset := wazevoapi.ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque.I64() + if !offsetFitsInAddressModeKindRegUnsignedImm12(64, offset) { + panic("BUG: too large or un-aligned offset for goFunctionCallCalleeModuleContextOpaque in execution context") + } + + // Module context is always the second argument. + moduleCtrPtr := x1VReg + store := m.allocateInstr() + amode := m.amodePool.Allocate() + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: execCtrPtr, imm: offset} + store.asStore(operandNR(moduleCtrPtr), amode, 64) + cur = linkInstr(cur, store) + } + + // Advances the stack pointer. + cur = m.addsAddOrSubStackPointer(cur, spVReg, goCallStackSize, false) + + // Copy the pointer to x15VReg. + arg0ret0AddrReg := x15VReg // Caller save, so we can use it for whatever we want. + copySp := m.allocateInstr() + copySp.asMove64(arg0ret0AddrReg, spVReg) + cur = linkInstr(cur, copySp) + + // Next, we need to store all the arguments to the stack in the typical Wasm stack style. + for i := range abi.Args[argBegin:] { + arg := &abi.Args[argBegin+i] + store := m.allocateInstr() + var v regalloc.VReg + if arg.Kind == backend.ABIArgKindReg { + v = arg.Reg + } else { + cur, v = m.goFunctionCallLoadStackArg(cur, originalArg0Reg, arg, + // Caller save, so we can use it for whatever we want. + x11VReg, v11VReg) + } + + var sizeInBits byte + if arg.Type == ssa.TypeV128 { + sizeInBits = 128 + } else { + sizeInBits = 64 + } + amode := m.amodePool.Allocate() + *amode = addressMode{kind: addressModeKindPostIndex, rn: arg0ret0AddrReg, imm: int64(sizeInBits / 8)} + store.asStore(operandNR(v), amode, sizeInBits) + cur = linkInstr(cur, store) + } + + // Finally, now that we've advanced SP to arg[0]/ret[0], we allocate `frame_size + sliceSize`. + var frameSizeReg, sliceSizeReg regalloc.VReg + if goCallStackSize > 0 { + cur = m.lowerConstantI64AndInsert(cur, tmpRegVReg, goCallStackSize) + frameSizeReg = tmpRegVReg + cur = m.lowerConstantI64AndInsert(cur, x16VReg, sliceSizeInBytes/8) + sliceSizeReg = x16VReg + } else { + frameSizeReg = xzrVReg + sliceSizeReg = xzrVReg + } + _amode := addressModePreOrPostIndex(m, spVReg, -16, true) + storeP := m.allocateInstr() + storeP.asStorePair64(frameSizeReg, sliceSizeReg, _amode) + cur = linkInstr(cur, storeP) + + // Set the exit status on the execution context. + cur = m.setExitCode(cur, x0VReg, exitCode) + + // Save the current stack pointer. + cur = m.saveCurrentStackPointer(cur, x0VReg) + + // Exit the execution. + cur = m.storeReturnAddressAndExit(cur) + + // After the call, we need to restore the callee saved registers. + cur = m.restoreRegistersInExecutionContext(cur, calleeSavedRegistersSorted) + + // Get the pointer to the arg[0]/ret[0]: We need to skip `frame_size + sliceSize`. + if len(abi.Rets) > 0 { + cur = m.addsAddOrSubStackPointer(cur, arg0ret0AddrReg, frameInfoSize, true) + } + + // Advances the SP so that it points to `ReturnAddress`. + cur = m.addsAddOrSubStackPointer(cur, spVReg, frameInfoSize+goCallStackSize, true) + ldr := m.allocateInstr() + // And load the return address. + amode := addressModePreOrPostIndex(m, spVReg, 16 /* stack pointer must be 16-byte aligned. */, false /* increment after loads */) + ldr.asULoad(lrVReg, amode, 64) + cur = linkInstr(cur, ldr) + + originalRet0Reg := x17VReg // Caller save, so we can use it for whatever we want. + if m.currentABI.RetStackSize > 0 { + cur = m.addsAddOrSubStackPointer(cur, originalRet0Reg, m.currentABI.ArgStackSize, true) + } + + // Make the SP point to the original address (above the result slot). + if s := int64(m.currentABI.AlignedArgResultStackSlotSize()); s > 0 { + cur = m.addsAddOrSubStackPointer(cur, spVReg, s, true) + } + + for i := range abi.Rets { + r := &abi.Rets[i] + if r.Kind == backend.ABIArgKindReg { + loadIntoReg := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindPostIndex, rn: arg0ret0AddrReg} + switch r.Type { + case ssa.TypeI32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoReg.asULoad(r.Reg, mode, 32) + case ssa.TypeI64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoReg.asULoad(r.Reg, mode, 64) + case ssa.TypeF32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoReg.asFpuLoad(r.Reg, mode, 32) + case ssa.TypeF64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoReg.asFpuLoad(r.Reg, mode, 64) + case ssa.TypeV128: + mode.imm = 16 + loadIntoReg.asFpuLoad(r.Reg, mode, 128) + default: + panic("TODO") + } + cur = linkInstr(cur, loadIntoReg) + } else { + // First we need to load the value to a temporary just like ^^. + intTmp, floatTmp := x11VReg, v11VReg + loadIntoTmpReg := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindPostIndex, rn: arg0ret0AddrReg} + var resultReg regalloc.VReg + switch r.Type { + case ssa.TypeI32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoTmpReg.asULoad(intTmp, mode, 32) + resultReg = intTmp + case ssa.TypeI64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoTmpReg.asULoad(intTmp, mode, 64) + resultReg = intTmp + case ssa.TypeF32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoTmpReg.asFpuLoad(floatTmp, mode, 32) + resultReg = floatTmp + case ssa.TypeF64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + loadIntoTmpReg.asFpuLoad(floatTmp, mode, 64) + resultReg = floatTmp + case ssa.TypeV128: + mode.imm = 16 + loadIntoTmpReg.asFpuLoad(floatTmp, mode, 128) + resultReg = floatTmp + default: + panic("TODO") + } + cur = linkInstr(cur, loadIntoTmpReg) + cur = m.goFunctionCallStoreStackResult(cur, originalRet0Reg, r, resultReg) + } + } + + ret := m.allocateInstr() + ret.asRet() + linkInstr(cur, ret) + + m.encode(m.rootInstr) + return m.compiler.Buf() +} + +func (m *machine) saveRegistersInExecutionContext(cur *instruction, regs []regalloc.VReg) *instruction { + offset := wazevoapi.ExecutionContextOffsetSavedRegistersBegin.I64() + for _, v := range regs { + store := m.allocateInstr() + var sizeInBits byte + switch v.RegType() { + case regalloc.RegTypeInt: + sizeInBits = 64 + case regalloc.RegTypeFloat: + sizeInBits = 128 + } + mode := m.amodePool.Allocate() + *mode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + // Execution context is always the first argument. + rn: x0VReg, imm: offset, + } + store.asStore(operandNR(v), mode, sizeInBits) + store.prev = cur + cur.next = store + cur = store + offset += 16 // Imm12 must be aligned 16 for vector regs, so we unconditionally store regs at the offset of multiple of 16. + } + return cur +} + +func (m *machine) restoreRegistersInExecutionContext(cur *instruction, regs []regalloc.VReg) *instruction { + offset := wazevoapi.ExecutionContextOffsetSavedRegistersBegin.I64() + for _, v := range regs { + load := m.allocateInstr() + var as func(dst regalloc.VReg, amode *addressMode, sizeInBits byte) + var sizeInBits byte + switch v.RegType() { + case regalloc.RegTypeInt: + as = load.asULoad + sizeInBits = 64 + case regalloc.RegTypeFloat: + as = load.asFpuLoad + sizeInBits = 128 + } + mode := m.amodePool.Allocate() + *mode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + // Execution context is always the first argument. + rn: x0VReg, imm: offset, + } + as(v, mode, sizeInBits) + cur = linkInstr(cur, load) + offset += 16 // Imm12 must be aligned 16 for vector regs, so we unconditionally load regs at the offset of multiple of 16. + } + return cur +} + +func (m *machine) lowerConstantI64AndInsert(cur *instruction, dst regalloc.VReg, v int64) *instruction { + m.pendingInstructions = m.pendingInstructions[:0] + m.lowerConstantI64(dst, v) + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + return cur +} + +func (m *machine) lowerConstantI32AndInsert(cur *instruction, dst regalloc.VReg, v int32) *instruction { + m.pendingInstructions = m.pendingInstructions[:0] + m.lowerConstantI32(dst, v) + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + return cur +} + +func (m *machine) setExitCode(cur *instruction, execCtr regalloc.VReg, exitCode wazevoapi.ExitCode) *instruction { + constReg := x17VReg // caller-saved, so we can use it. + cur = m.lowerConstantI32AndInsert(cur, constReg, int32(exitCode)) + + // Set the exit status on the execution context. + setExistStatus := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: execCtr, imm: wazevoapi.ExecutionContextOffsetExitCodeOffset.I64()} + setExistStatus.asStore(operandNR(constReg), mode, 32) + cur = linkInstr(cur, setExistStatus) + return cur +} + +func (m *machine) storeReturnAddressAndExit(cur *instruction) *instruction { + // Read the return address into tmp, and store it in the execution context. + adr := m.allocateInstr() + adr.asAdr(tmpRegVReg, exitSequenceSize+8) + cur = linkInstr(cur, adr) + + storeReturnAddr := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + // Execution context is always the first argument. + rn: x0VReg, imm: wazevoapi.ExecutionContextOffsetGoCallReturnAddress.I64(), + } + storeReturnAddr.asStore(operandNR(tmpRegVReg), mode, 64) + cur = linkInstr(cur, storeReturnAddr) + + // Exit the execution. + trapSeq := m.allocateInstr() + trapSeq.asExitSequence(x0VReg) + cur = linkInstr(cur, trapSeq) + return cur +} + +func (m *machine) saveCurrentStackPointer(cur *instruction, execCtr regalloc.VReg) *instruction { + // Save the current stack pointer: + // mov tmp, sp, + // str tmp, [exec_ctx, #stackPointerBeforeGoCall] + movSp := m.allocateInstr() + movSp.asMove64(tmpRegVReg, spVReg) + cur = linkInstr(cur, movSp) + + strSp := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: execCtr, imm: wazevoapi.ExecutionContextOffsetStackPointerBeforeGoCall.I64(), + } + strSp.asStore(operandNR(tmpRegVReg), mode, 64) + cur = linkInstr(cur, strSp) + return cur +} + +func (m *machine) goFunctionCallLoadStackArg(cur *instruction, originalArg0Reg regalloc.VReg, arg *backend.ABIArg, intVReg, floatVReg regalloc.VReg) (*instruction, regalloc.VReg) { + load := m.allocateInstr() + var result regalloc.VReg + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindPostIndex, rn: originalArg0Reg} + switch arg.Type { + case ssa.TypeI32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + load.asULoad(intVReg, mode, 32) + result = intVReg + case ssa.TypeI64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + load.asULoad(intVReg, mode, 64) + result = intVReg + case ssa.TypeF32: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + load.asFpuLoad(floatVReg, mode, 32) + result = floatVReg + case ssa.TypeF64: + mode.imm = 8 // We use uint64 for all basic types, except SIMD v128. + load.asFpuLoad(floatVReg, mode, 64) + result = floatVReg + case ssa.TypeV128: + mode.imm = 16 + load.asFpuLoad(floatVReg, mode, 128) + result = floatVReg + default: + panic("TODO") + } + + cur = linkInstr(cur, load) + return cur, result +} + +func (m *machine) goFunctionCallStoreStackResult(cur *instruction, originalRet0Reg regalloc.VReg, result *backend.ABIArg, resultVReg regalloc.VReg) *instruction { + store := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{kind: addressModeKindPostIndex, rn: originalRet0Reg} + var sizeInBits byte + switch result.Type { + case ssa.TypeI32, ssa.TypeF32: + mode.imm = 8 + sizeInBits = 32 + case ssa.TypeI64, ssa.TypeF64: + mode.imm = 8 + sizeInBits = 64 + case ssa.TypeV128: + mode.imm = 16 + sizeInBits = 128 + default: + panic("TODO") + } + store.asStore(operandNR(resultVReg), mode, sizeInBits) + return linkInstr(cur, store) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/cond.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/cond.go new file mode 100644 index 00000000..6f6cdd1b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/cond.go @@ -0,0 +1,215 @@ +package arm64 + +import ( + "strconv" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +type ( + cond uint64 + condKind byte +) + +const ( + // condKindRegisterZero represents a condition which checks if the register is zero. + // This indicates that the instruction must be encoded as CBZ: + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/CBZ--Compare-and-Branch-on-Zero- + condKindRegisterZero condKind = iota + // condKindRegisterNotZero indicates that the instruction must be encoded as CBNZ: + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/CBNZ--Compare-and-Branch-on-Nonzero- + condKindRegisterNotZero + // condKindCondFlagSet indicates that the instruction must be encoded as B.cond: + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/B-cond--Branch-conditionally- + condKindCondFlagSet +) + +// kind returns the kind of condition which is stored in the first two bits. +func (c cond) kind() condKind { + return condKind(c & 0b11) +} + +func (c cond) asUint64() uint64 { + return uint64(c) +} + +// register returns the register for register conditions. +// This panics if the condition is not a register condition (condKindRegisterZero or condKindRegisterNotZero). +func (c cond) register() regalloc.VReg { + if c.kind() != condKindRegisterZero && c.kind() != condKindRegisterNotZero { + panic("condition is not a register") + } + return regalloc.VReg(c >> 2) +} + +func registerAsRegZeroCond(r regalloc.VReg) cond { + return cond(r)<<2 | cond(condKindRegisterZero) +} + +func registerAsRegNotZeroCond(r regalloc.VReg) cond { + return cond(r)<<2 | cond(condKindRegisterNotZero) +} + +func (c cond) flag() condFlag { + if c.kind() != condKindCondFlagSet { + panic("condition is not a flag") + } + return condFlag(c >> 2) +} + +func (c condFlag) asCond() cond { + return cond(c)<<2 | cond(condKindCondFlagSet) +} + +// condFlag represents a condition flag for conditional branches. +// The value matches the encoding of condition flags in the ARM64 instruction set. +// https://developer.arm.com/documentation/den0024/a/The-A64-instruction-set/Data-processing-instructions/Conditional-instructions +type condFlag uint8 + +const ( + eq condFlag = iota // eq represents "equal" + ne // ne represents "not equal" + hs // hs represents "higher or same" + lo // lo represents "lower" + mi // mi represents "minus or negative result" + pl // pl represents "plus or positive result" + vs // vs represents "overflow set" + vc // vc represents "overflow clear" + hi // hi represents "higher" + ls // ls represents "lower or same" + ge // ge represents "greater or equal" + lt // lt represents "less than" + gt // gt represents "greater than" + le // le represents "less than or equal" + al // al represents "always" + nv // nv represents "never" +) + +// invert returns the inverted condition. +func (c condFlag) invert() condFlag { + switch c { + case eq: + return ne + case ne: + return eq + case hs: + return lo + case lo: + return hs + case mi: + return pl + case pl: + return mi + case vs: + return vc + case vc: + return vs + case hi: + return ls + case ls: + return hi + case ge: + return lt + case lt: + return ge + case gt: + return le + case le: + return gt + case al: + return nv + case nv: + return al + default: + panic(c) + } +} + +// String implements fmt.Stringer. +func (c condFlag) String() string { + switch c { + case eq: + return "eq" + case ne: + return "ne" + case hs: + return "hs" + case lo: + return "lo" + case mi: + return "mi" + case pl: + return "pl" + case vs: + return "vs" + case vc: + return "vc" + case hi: + return "hi" + case ls: + return "ls" + case ge: + return "ge" + case lt: + return "lt" + case gt: + return "gt" + case le: + return "le" + case al: + return "al" + case nv: + return "nv" + default: + panic(strconv.Itoa(int(c))) + } +} + +// condFlagFromSSAIntegerCmpCond returns the condition flag for the given ssa.IntegerCmpCond. +func condFlagFromSSAIntegerCmpCond(c ssa.IntegerCmpCond) condFlag { + switch c { + case ssa.IntegerCmpCondEqual: + return eq + case ssa.IntegerCmpCondNotEqual: + return ne + case ssa.IntegerCmpCondSignedLessThan: + return lt + case ssa.IntegerCmpCondSignedGreaterThanOrEqual: + return ge + case ssa.IntegerCmpCondSignedGreaterThan: + return gt + case ssa.IntegerCmpCondSignedLessThanOrEqual: + return le + case ssa.IntegerCmpCondUnsignedLessThan: + return lo + case ssa.IntegerCmpCondUnsignedGreaterThanOrEqual: + return hs + case ssa.IntegerCmpCondUnsignedGreaterThan: + return hi + case ssa.IntegerCmpCondUnsignedLessThanOrEqual: + return ls + default: + panic(c) + } +} + +// condFlagFromSSAFloatCmpCond returns the condition flag for the given ssa.FloatCmpCond. +func condFlagFromSSAFloatCmpCond(c ssa.FloatCmpCond) condFlag { + switch c { + case ssa.FloatCmpCondEqual: + return eq + case ssa.FloatCmpCondNotEqual: + return ne + case ssa.FloatCmpCondLessThan: + return mi + case ssa.FloatCmpCondLessThanOrEqual: + return ls + case ssa.FloatCmpCondGreaterThan: + return gt + case ssa.FloatCmpCondGreaterThanOrEqual: + return ge + default: + panic(c) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr.go new file mode 100644 index 00000000..1f563428 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr.go @@ -0,0 +1,2534 @@ +package arm64 + +import ( + "fmt" + "math" + "unsafe" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +type ( + // instruction represents either a real instruction in arm64, or the meta instructions + // that are convenient for code generation. For example, inline constants are also treated + // as instructions. + // + // Basically, each instruction knows how to get encoded in binaries. Hence, the final output of compilation + // can be considered equivalent to the sequence of such instructions. + // + // Each field is interpreted depending on the kind. + // + // TODO: optimize the layout later once the impl settles. + instruction struct { + prev, next *instruction + u1, u2 uint64 + rd regalloc.VReg + rm, rn operand + kind instructionKind + addedBeforeRegAlloc bool + } + + // instructionKind represents the kind of instruction. + // This controls how the instruction struct is interpreted. + instructionKind byte +) + +// IsCall implements regalloc.Instr IsCall. +func (i *instruction) IsCall() bool { + return i.kind == call +} + +// IsIndirectCall implements regalloc.Instr IsIndirectCall. +func (i *instruction) IsIndirectCall() bool { + return i.kind == callInd +} + +// IsReturn implements regalloc.Instr IsReturn. +func (i *instruction) IsReturn() bool { + return i.kind == ret +} + +type defKind byte + +const ( + defKindNone defKind = iota + 1 + defKindRD + defKindCall +) + +var defKinds = [numInstructionKinds]defKind{ + adr: defKindRD, + aluRRR: defKindRD, + aluRRRR: defKindRD, + aluRRImm12: defKindRD, + aluRRBitmaskImm: defKindRD, + aluRRRShift: defKindRD, + aluRRImmShift: defKindRD, + aluRRRExtend: defKindRD, + bitRR: defKindRD, + movZ: defKindRD, + movK: defKindRD, + movN: defKindRD, + mov32: defKindRD, + mov64: defKindRD, + fpuMov64: defKindRD, + fpuMov128: defKindRD, + fpuRR: defKindRD, + fpuRRR: defKindRD, + nop0: defKindNone, + call: defKindCall, + callInd: defKindCall, + ret: defKindNone, + store8: defKindNone, + store16: defKindNone, + store32: defKindNone, + store64: defKindNone, + exitSequence: defKindNone, + condBr: defKindNone, + br: defKindNone, + brTableSequence: defKindNone, + cSet: defKindRD, + extend: defKindRD, + fpuCmp: defKindNone, + uLoad8: defKindRD, + uLoad16: defKindRD, + uLoad32: defKindRD, + sLoad8: defKindRD, + sLoad16: defKindRD, + sLoad32: defKindRD, + uLoad64: defKindRD, + fpuLoad32: defKindRD, + fpuLoad64: defKindRD, + fpuLoad128: defKindRD, + vecLoad1R: defKindRD, + loadFpuConst32: defKindRD, + loadFpuConst64: defKindRD, + loadFpuConst128: defKindRD, + fpuStore32: defKindNone, + fpuStore64: defKindNone, + fpuStore128: defKindNone, + udf: defKindNone, + cSel: defKindRD, + fpuCSel: defKindRD, + movToVec: defKindRD, + movFromVec: defKindRD, + movFromVecSigned: defKindRD, + vecDup: defKindRD, + vecDupElement: defKindRD, + vecExtract: defKindRD, + vecMisc: defKindRD, + vecMovElement: defKindRD, + vecLanes: defKindRD, + vecShiftImm: defKindRD, + vecTbl: defKindRD, + vecTbl2: defKindRD, + vecPermute: defKindRD, + vecRRR: defKindRD, + vecRRRRewrite: defKindNone, + fpuToInt: defKindRD, + intToFpu: defKindRD, + cCmpImm: defKindNone, + movToFPSR: defKindNone, + movFromFPSR: defKindRD, + emitSourceOffsetInfo: defKindNone, + atomicRmw: defKindRD, + atomicCas: defKindNone, + atomicLoad: defKindRD, + atomicStore: defKindNone, + dmb: defKindNone, + loadConstBlockArg: defKindRD, +} + +// Defs returns the list of regalloc.VReg that are defined by the instruction. +// In order to reduce the number of allocations, the caller can pass the slice to be used. +func (i *instruction) Defs(regs *[]regalloc.VReg) []regalloc.VReg { + *regs = (*regs)[:0] + switch defKinds[i.kind] { + case defKindNone: + case defKindRD: + *regs = append(*regs, i.rd) + case defKindCall: + _, _, retIntRealRegs, retFloatRealRegs, _ := backend.ABIInfoFromUint64(i.u2) + for i := byte(0); i < retIntRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[intParamResultRegs[i]]) + } + for i := byte(0); i < retFloatRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[floatParamResultRegs[i]]) + } + default: + panic(fmt.Sprintf("defKind for %v not defined", i)) + } + return *regs +} + +// AssignDef implements regalloc.Instr AssignDef. +func (i *instruction) AssignDef(reg regalloc.VReg) { + switch defKinds[i.kind] { + case defKindNone: + case defKindRD: + i.rd = reg + case defKindCall: + panic("BUG: call instructions shouldn't be assigned") + default: + panic(fmt.Sprintf("defKind for %v not defined", i)) + } +} + +type useKind byte + +const ( + useKindNone useKind = iota + 1 + useKindRN + useKindRNRM + useKindRNRMRA + useKindRNRN1RM + useKindCall + useKindCallInd + useKindAMode + useKindRNAMode + useKindCond + // useKindRDRewrite indicates an instruction where RD is used both as a source and destination. + // A temporary register for RD must be allocated explicitly with the source copied to this + // register before the instruction and the value copied from this register to the instruction + // return register. + useKindRDRewrite +) + +var useKinds = [numInstructionKinds]useKind{ + udf: useKindNone, + aluRRR: useKindRNRM, + aluRRRR: useKindRNRMRA, + aluRRImm12: useKindRN, + aluRRBitmaskImm: useKindRN, + aluRRRShift: useKindRNRM, + aluRRImmShift: useKindRN, + aluRRRExtend: useKindRNRM, + bitRR: useKindRN, + movZ: useKindNone, + movK: useKindNone, + movN: useKindNone, + mov32: useKindRN, + mov64: useKindRN, + fpuMov64: useKindRN, + fpuMov128: useKindRN, + fpuRR: useKindRN, + fpuRRR: useKindRNRM, + nop0: useKindNone, + call: useKindCall, + callInd: useKindCallInd, + ret: useKindNone, + store8: useKindRNAMode, + store16: useKindRNAMode, + store32: useKindRNAMode, + store64: useKindRNAMode, + exitSequence: useKindRN, + condBr: useKindCond, + br: useKindNone, + brTableSequence: useKindRN, + cSet: useKindNone, + extend: useKindRN, + fpuCmp: useKindRNRM, + uLoad8: useKindAMode, + uLoad16: useKindAMode, + uLoad32: useKindAMode, + sLoad8: useKindAMode, + sLoad16: useKindAMode, + sLoad32: useKindAMode, + uLoad64: useKindAMode, + fpuLoad32: useKindAMode, + fpuLoad64: useKindAMode, + fpuLoad128: useKindAMode, + fpuStore32: useKindRNAMode, + fpuStore64: useKindRNAMode, + fpuStore128: useKindRNAMode, + loadFpuConst32: useKindNone, + loadFpuConst64: useKindNone, + loadFpuConst128: useKindNone, + vecLoad1R: useKindRN, + cSel: useKindRNRM, + fpuCSel: useKindRNRM, + movToVec: useKindRN, + movFromVec: useKindRN, + movFromVecSigned: useKindRN, + vecDup: useKindRN, + vecDupElement: useKindRN, + vecExtract: useKindRNRM, + cCmpImm: useKindRN, + vecMisc: useKindRN, + vecMovElement: useKindRN, + vecLanes: useKindRN, + vecShiftImm: useKindRN, + vecTbl: useKindRNRM, + vecTbl2: useKindRNRN1RM, + vecRRR: useKindRNRM, + vecRRRRewrite: useKindRDRewrite, + vecPermute: useKindRNRM, + fpuToInt: useKindRN, + intToFpu: useKindRN, + movToFPSR: useKindRN, + movFromFPSR: useKindNone, + adr: useKindNone, + emitSourceOffsetInfo: useKindNone, + atomicRmw: useKindRNRM, + atomicCas: useKindRDRewrite, + atomicLoad: useKindRN, + atomicStore: useKindRNRM, + loadConstBlockArg: useKindNone, + dmb: useKindNone, +} + +// Uses returns the list of regalloc.VReg that are used by the instruction. +// In order to reduce the number of allocations, the caller can pass the slice to be used. +func (i *instruction) Uses(regs *[]regalloc.VReg) []regalloc.VReg { + *regs = (*regs)[:0] + switch useKinds[i.kind] { + case useKindNone: + case useKindRN: + if rn := i.rn.reg(); rn.Valid() { + *regs = append(*regs, rn) + } + case useKindRNRM: + if rn := i.rn.reg(); rn.Valid() { + *regs = append(*regs, rn) + } + if rm := i.rm.reg(); rm.Valid() { + *regs = append(*regs, rm) + } + case useKindRNRMRA: + if rn := i.rn.reg(); rn.Valid() { + *regs = append(*regs, rn) + } + if rm := i.rm.reg(); rm.Valid() { + *regs = append(*regs, rm) + } + if ra := regalloc.VReg(i.u2); ra.Valid() { + *regs = append(*regs, ra) + } + case useKindRNRN1RM: + if rn := i.rn.reg(); rn.Valid() && rn.IsRealReg() { + rn1 := regalloc.FromRealReg(rn.RealReg()+1, rn.RegType()) + *regs = append(*regs, rn, rn1) + } + if rm := i.rm.reg(); rm.Valid() { + *regs = append(*regs, rm) + } + case useKindAMode: + amode := i.getAmode() + if amodeRN := amode.rn; amodeRN.Valid() { + *regs = append(*regs, amodeRN) + } + if amodeRM := amode.rm; amodeRM.Valid() { + *regs = append(*regs, amodeRM) + } + case useKindRNAMode: + *regs = append(*regs, i.rn.reg()) + amode := i.getAmode() + if amodeRN := amode.rn; amodeRN.Valid() { + *regs = append(*regs, amodeRN) + } + if amodeRM := amode.rm; amodeRM.Valid() { + *regs = append(*regs, amodeRM) + } + case useKindCond: + cnd := cond(i.u1) + if cnd.kind() != condKindCondFlagSet { + *regs = append(*regs, cnd.register()) + } + case useKindCallInd: + *regs = append(*regs, i.rn.nr()) + fallthrough + case useKindCall: + argIntRealRegs, argFloatRealRegs, _, _, _ := backend.ABIInfoFromUint64(i.u2) + for i := byte(0); i < argIntRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[intParamResultRegs[i]]) + } + for i := byte(0); i < argFloatRealRegs; i++ { + *regs = append(*regs, regInfo.RealRegToVReg[floatParamResultRegs[i]]) + } + case useKindRDRewrite: + *regs = append(*regs, i.rn.reg()) + *regs = append(*regs, i.rm.reg()) + *regs = append(*regs, i.rd) + default: + panic(fmt.Sprintf("useKind for %v not defined", i)) + } + return *regs +} + +func (i *instruction) AssignUse(index int, reg regalloc.VReg) { + switch useKinds[i.kind] { + case useKindNone: + case useKindRN: + if rn := i.rn.reg(); rn.Valid() { + i.rn = i.rn.assignReg(reg) + } + case useKindRNRM: + if index == 0 { + if rn := i.rn.reg(); rn.Valid() { + i.rn = i.rn.assignReg(reg) + } + } else { + if rm := i.rm.reg(); rm.Valid() { + i.rm = i.rm.assignReg(reg) + } + } + case useKindRDRewrite: + if index == 0 { + if rn := i.rn.reg(); rn.Valid() { + i.rn = i.rn.assignReg(reg) + } + } else if index == 1 { + if rm := i.rm.reg(); rm.Valid() { + i.rm = i.rm.assignReg(reg) + } + } else { + if rd := i.rd; rd.Valid() { + i.rd = reg + } + } + case useKindRNRN1RM: + if index == 0 { + if rn := i.rn.reg(); rn.Valid() { + i.rn = i.rn.assignReg(reg) + } + if rn1 := i.rn.reg() + 1; rn1.Valid() { + i.rm = i.rm.assignReg(reg + 1) + } + } else { + if rm := i.rm.reg(); rm.Valid() { + i.rm = i.rm.assignReg(reg) + } + } + case useKindRNRMRA: + if index == 0 { + if rn := i.rn.reg(); rn.Valid() { + i.rn = i.rn.assignReg(reg) + } + } else if index == 1 { + if rm := i.rm.reg(); rm.Valid() { + i.rm = i.rm.assignReg(reg) + } + } else { + if ra := regalloc.VReg(i.u2); ra.Valid() { + i.u2 = uint64(reg) + } + } + case useKindAMode: + if index == 0 { + amode := i.getAmode() + if amodeRN := amode.rn; amodeRN.Valid() { + amode.rn = reg + } + } else { + amode := i.getAmode() + if amodeRM := amode.rm; amodeRM.Valid() { + amode.rm = reg + } + } + case useKindRNAMode: + if index == 0 { + i.rn = i.rn.assignReg(reg) + } else if index == 1 { + amode := i.getAmode() + if amodeRN := amode.rn; amodeRN.Valid() { + amode.rn = reg + } else { + panic("BUG") + } + } else { + amode := i.getAmode() + if amodeRM := amode.rm; amodeRM.Valid() { + amode.rm = reg + } else { + panic("BUG") + } + } + case useKindCond: + c := cond(i.u1) + switch c.kind() { + case condKindRegisterZero: + i.u1 = uint64(registerAsRegZeroCond(reg)) + case condKindRegisterNotZero: + i.u1 = uint64(registerAsRegNotZeroCond(reg)) + } + case useKindCall: + panic("BUG: call instructions shouldn't be assigned") + case useKindCallInd: + i.rn = i.rn.assignReg(reg) + default: + panic(fmt.Sprintf("useKind for %v not defined", i)) + } +} + +func (i *instruction) asCall(ref ssa.FuncRef, abi *backend.FunctionABI) { + i.kind = call + i.u1 = uint64(ref) + if abi != nil { + i.u2 = abi.ABIInfoAsUint64() + } +} + +func (i *instruction) asCallIndirect(ptr regalloc.VReg, abi *backend.FunctionABI) { + i.kind = callInd + i.rn = operandNR(ptr) + if abi != nil { + i.u2 = abi.ABIInfoAsUint64() + } +} + +func (i *instruction) callFuncRef() ssa.FuncRef { + return ssa.FuncRef(i.u1) +} + +// shift must be divided by 16 and must be in range 0-3 (if dst64bit is true) or 0-1 (if dst64bit is false) +func (i *instruction) asMOVZ(dst regalloc.VReg, imm uint64, shift uint32, dst64bit bool) { + i.kind = movZ + i.rd = dst + i.u1 = imm + i.u2 = uint64(shift) + if dst64bit { + i.u2 |= 1 << 32 + } +} + +// shift must be divided by 16 and must be in range 0-3 (if dst64bit is true) or 0-1 (if dst64bit is false) +func (i *instruction) asMOVK(dst regalloc.VReg, imm uint64, shift uint32, dst64bit bool) { + i.kind = movK + i.rd = dst + i.u1 = imm + i.u2 = uint64(shift) + if dst64bit { + i.u2 |= 1 << 32 + } +} + +// shift must be divided by 16 and must be in range 0-3 (if dst64bit is true) or 0-1 (if dst64bit is false) +func (i *instruction) asMOVN(dst regalloc.VReg, imm uint64, shift uint32, dst64bit bool) { + i.kind = movN + i.rd = dst + i.u1 = imm + i.u2 = uint64(shift) + if dst64bit { + i.u2 |= 1 << 32 + } +} + +func (i *instruction) asNop0() *instruction { + i.kind = nop0 + return i +} + +func (i *instruction) asNop0WithLabel(l label) { + i.kind = nop0 + i.u1 = uint64(l) +} + +func (i *instruction) nop0Label() label { + return label(i.u1) +} + +func (i *instruction) asRet() { + i.kind = ret +} + +func (i *instruction) asStorePair64(src1, src2 regalloc.VReg, amode *addressMode) { + i.kind = storeP64 + i.rn = operandNR(src1) + i.rm = operandNR(src2) + i.setAmode(amode) +} + +func (i *instruction) asLoadPair64(src1, src2 regalloc.VReg, amode *addressMode) { + i.kind = loadP64 + i.rn = operandNR(src1) + i.rm = operandNR(src2) + i.setAmode(amode) +} + +func (i *instruction) asStore(src operand, amode *addressMode, sizeInBits byte) { + switch sizeInBits { + case 8: + i.kind = store8 + case 16: + i.kind = store16 + case 32: + if src.reg().RegType() == regalloc.RegTypeInt { + i.kind = store32 + } else { + i.kind = fpuStore32 + } + case 64: + if src.reg().RegType() == regalloc.RegTypeInt { + i.kind = store64 + } else { + i.kind = fpuStore64 + } + case 128: + i.kind = fpuStore128 + } + i.rn = src + i.setAmode(amode) +} + +func (i *instruction) asSLoad(dst regalloc.VReg, amode *addressMode, sizeInBits byte) { + switch sizeInBits { + case 8: + i.kind = sLoad8 + case 16: + i.kind = sLoad16 + case 32: + i.kind = sLoad32 + default: + panic("BUG") + } + i.rd = dst + i.setAmode(amode) +} + +func (i *instruction) asULoad(dst regalloc.VReg, amode *addressMode, sizeInBits byte) { + switch sizeInBits { + case 8: + i.kind = uLoad8 + case 16: + i.kind = uLoad16 + case 32: + i.kind = uLoad32 + case 64: + i.kind = uLoad64 + } + i.rd = dst + i.setAmode(amode) +} + +func (i *instruction) asFpuLoad(dst regalloc.VReg, amode *addressMode, sizeInBits byte) { + switch sizeInBits { + case 32: + i.kind = fpuLoad32 + case 64: + i.kind = fpuLoad64 + case 128: + i.kind = fpuLoad128 + } + i.rd = dst + i.setAmode(amode) +} + +func (i *instruction) getAmode() *addressMode { + return wazevoapi.PtrFromUintptr[addressMode](uintptr(i.u1)) +} + +func (i *instruction) setAmode(a *addressMode) { + i.u1 = uint64(uintptr(unsafe.Pointer(a))) +} + +func (i *instruction) asVecLoad1R(rd regalloc.VReg, rn operand, arr vecArrangement) { + // NOTE: currently only has support for no-offset loads, though it is suspicious that + // we would need to support offset load (that is only available for post-index). + i.kind = vecLoad1R + i.rd = rd + i.rn = rn + i.u1 = uint64(arr) +} + +func (i *instruction) asCSet(rd regalloc.VReg, mask bool, c condFlag) { + i.kind = cSet + i.rd = rd + i.u1 = uint64(c) + if mask { + i.u2 = 1 + } +} + +func (i *instruction) asCSel(rd regalloc.VReg, rn, rm operand, c condFlag, _64bit bool) { + i.kind = cSel + i.rd = rd + i.rn = rn + i.rm = rm + i.u1 = uint64(c) + if _64bit { + i.u2 = 1 + } +} + +func (i *instruction) asFpuCSel(rd regalloc.VReg, rn, rm operand, c condFlag, _64bit bool) { + i.kind = fpuCSel + i.rd = rd + i.rn = rn + i.rm = rm + i.u1 = uint64(c) + if _64bit { + i.u2 = 1 + } +} + +func (i *instruction) asBr(target label) { + if target == labelReturn { + panic("BUG: call site should special case for returnLabel") + } + i.kind = br + i.u1 = uint64(target) +} + +func (i *instruction) asBrTableSequence(indexReg regalloc.VReg, targetIndex, targetCounts int) { + i.kind = brTableSequence + i.rn = operandNR(indexReg) + i.u1 = uint64(targetIndex) + i.u2 = uint64(targetCounts) +} + +func (i *instruction) brTableSequenceOffsetsResolved() { + i.rm.data = 1 // indicate that the offsets are resolved, for debugging. +} + +func (i *instruction) brLabel() label { + return label(i.u1) +} + +// brOffsetResolved is called when the target label is resolved. +func (i *instruction) brOffsetResolve(offset int64) { + i.u2 = uint64(offset) + i.rm.data = 1 // indicate that the offset is resolved, for debugging. +} + +func (i *instruction) brOffset() int64 { + return int64(i.u2) +} + +// asCondBr encodes a conditional branch instruction. is64bit is only needed when cond is not flag. +func (i *instruction) asCondBr(c cond, target label, is64bit bool) { + i.kind = condBr + i.u1 = c.asUint64() + i.u2 = uint64(target) + if is64bit { + i.u2 |= 1 << 32 + } +} + +func (i *instruction) setCondBrTargets(target label) { + i.u2 = uint64(target) +} + +func (i *instruction) condBrLabel() label { + return label(i.u2) +} + +// condBrOffsetResolve is called when the target label is resolved. +func (i *instruction) condBrOffsetResolve(offset int64) { + i.rn.data = uint64(offset) + i.rn.data2 = 1 // indicate that the offset is resolved, for debugging. +} + +// condBrOffsetResolved returns true if condBrOffsetResolve is already called. +func (i *instruction) condBrOffsetResolved() bool { + return i.rn.data2 == 1 +} + +func (i *instruction) condBrOffset() int64 { + return int64(i.rn.data) +} + +func (i *instruction) condBrCond() cond { + return cond(i.u1) +} + +func (i *instruction) condBr64bit() bool { + return i.u2&(1<<32) != 0 +} + +func (i *instruction) asLoadFpuConst32(rd regalloc.VReg, raw uint64) { + i.kind = loadFpuConst32 + i.u1 = raw + i.rd = rd +} + +func (i *instruction) asLoadFpuConst64(rd regalloc.VReg, raw uint64) { + i.kind = loadFpuConst64 + i.u1 = raw + i.rd = rd +} + +func (i *instruction) asLoadFpuConst128(rd regalloc.VReg, lo, hi uint64) { + i.kind = loadFpuConst128 + i.u1 = lo + i.u2 = hi + i.rd = rd +} + +func (i *instruction) asFpuCmp(rn, rm operand, is64bit bool) { + i.kind = fpuCmp + i.rn, i.rm = rn, rm + if is64bit { + i.u1 = 1 + } +} + +func (i *instruction) asCCmpImm(rn operand, imm uint64, c condFlag, flag byte, is64bit bool) { + i.kind = cCmpImm + i.rn = rn + i.rm.data = imm + i.u1 = uint64(c) + i.u2 = uint64(flag) + if is64bit { + i.u2 |= 1 << 32 + } +} + +// asALU setups a basic ALU instruction. +func (i *instruction) asALU(aluOp aluOp, rd regalloc.VReg, rn, rm operand, dst64bit bool) { + switch rm.kind { + case operandKindNR: + i.kind = aluRRR + case operandKindSR: + i.kind = aluRRRShift + case operandKindER: + i.kind = aluRRRExtend + case operandKindImm12: + i.kind = aluRRImm12 + default: + panic("BUG") + } + i.u1 = uint64(aluOp) + i.rd, i.rn, i.rm = rd, rn, rm + if dst64bit { + i.u2 |= 1 << 32 + } +} + +// asALU setups a basic ALU instruction. +func (i *instruction) asALURRRR(aluOp aluOp, rd regalloc.VReg, rn, rm operand, ra regalloc.VReg, dst64bit bool) { + i.kind = aluRRRR + i.u1 = uint64(aluOp) + i.rd, i.rn, i.rm, i.u2 = rd, rn, rm, uint64(ra) + if dst64bit { + i.u1 |= 1 << 32 + } +} + +// asALUShift setups a shift based ALU instruction. +func (i *instruction) asALUShift(aluOp aluOp, rd regalloc.VReg, rn, rm operand, dst64bit bool) { + switch rm.kind { + case operandKindNR: + i.kind = aluRRR // If the shift amount op is a register, then the instruction is encoded as a normal ALU instruction with two register operands. + case operandKindShiftImm: + i.kind = aluRRImmShift + default: + panic("BUG") + } + i.u1 = uint64(aluOp) + i.rd, i.rn, i.rm = rd, rn, rm + if dst64bit { + i.u2 |= 1 << 32 + } +} + +func (i *instruction) asALUBitmaskImm(aluOp aluOp, rd, rn regalloc.VReg, imm uint64, dst64bit bool) { + i.kind = aluRRBitmaskImm + i.u1 = uint64(aluOp) + i.rn, i.rd = operandNR(rn), rd + i.u2 = imm + if dst64bit { + i.u1 |= 1 << 32 + } +} + +func (i *instruction) asMovToFPSR(rn regalloc.VReg) { + i.kind = movToFPSR + i.rn = operandNR(rn) +} + +func (i *instruction) asMovFromFPSR(rd regalloc.VReg) { + i.kind = movFromFPSR + i.rd = rd +} + +func (i *instruction) asBitRR(bitOp bitOp, rd, rn regalloc.VReg, is64bit bool) { + i.kind = bitRR + i.rn, i.rd = operandNR(rn), rd + i.u1 = uint64(bitOp) + if is64bit { + i.u2 = 1 + } +} + +func (i *instruction) asFpuRRR(op fpuBinOp, rd regalloc.VReg, rn, rm operand, dst64bit bool) { + i.kind = fpuRRR + i.u1 = uint64(op) + i.rd, i.rn, i.rm = rd, rn, rm + if dst64bit { + i.u2 = 1 + } +} + +func (i *instruction) asFpuRR(op fpuUniOp, rd regalloc.VReg, rn operand, dst64bit bool) { + i.kind = fpuRR + i.u1 = uint64(op) + i.rd, i.rn = rd, rn + if dst64bit { + i.u2 = 1 + } +} + +func (i *instruction) asExtend(rd, rn regalloc.VReg, fromBits, toBits byte, signed bool) { + i.kind = extend + i.rn, i.rd = operandNR(rn), rd + i.u1 = uint64(fromBits) + i.u2 = uint64(toBits) + if signed { + i.u2 |= 1 << 32 + } +} + +func (i *instruction) asMove32(rd, rn regalloc.VReg) { + i.kind = mov32 + i.rn, i.rd = operandNR(rn), rd +} + +func (i *instruction) asMove64(rd, rn regalloc.VReg) *instruction { + i.kind = mov64 + i.rn, i.rd = operandNR(rn), rd + return i +} + +func (i *instruction) asFpuMov64(rd, rn regalloc.VReg) { + i.kind = fpuMov64 + i.rn, i.rd = operandNR(rn), rd +} + +func (i *instruction) asFpuMov128(rd, rn regalloc.VReg) *instruction { + i.kind = fpuMov128 + i.rn, i.rd = operandNR(rn), rd + return i +} + +func (i *instruction) asMovToVec(rd regalloc.VReg, rn operand, arr vecArrangement, index vecIndex) { + i.kind = movToVec + i.rd = rd + i.rn = rn + i.u1, i.u2 = uint64(arr), uint64(index) +} + +func (i *instruction) asMovFromVec(rd regalloc.VReg, rn operand, arr vecArrangement, index vecIndex, signed bool) { + if signed { + i.kind = movFromVecSigned + } else { + i.kind = movFromVec + } + i.rd = rd + i.rn = rn + i.u1, i.u2 = uint64(arr), uint64(index) +} + +func (i *instruction) asVecDup(rd regalloc.VReg, rn operand, arr vecArrangement) { + i.kind = vecDup + i.u1 = uint64(arr) + i.rn, i.rd = rn, rd +} + +func (i *instruction) asVecDupElement(rd regalloc.VReg, rn operand, arr vecArrangement, index vecIndex) { + i.kind = vecDupElement + i.u1 = uint64(arr) + i.rn, i.rd = rn, rd + i.u2 = uint64(index) +} + +func (i *instruction) asVecExtract(rd regalloc.VReg, rn, rm operand, arr vecArrangement, index uint32) { + i.kind = vecExtract + i.u1 = uint64(arr) + i.rn, i.rm, i.rd = rn, rm, rd + i.u2 = uint64(index) +} + +func (i *instruction) asVecMovElement(rd regalloc.VReg, rn operand, arr vecArrangement, rdIndex, rnIndex vecIndex) { + i.kind = vecMovElement + i.u1 = uint64(arr) + i.u2 = uint64(rdIndex) | uint64(rnIndex)<<32 + i.rn, i.rd = rn, rd +} + +func (i *instruction) asVecMisc(op vecOp, rd regalloc.VReg, rn operand, arr vecArrangement) { + i.kind = vecMisc + i.u1 = uint64(op) + i.rn, i.rd = rn, rd + i.u2 = uint64(arr) +} + +func (i *instruction) asVecLanes(op vecOp, rd regalloc.VReg, rn operand, arr vecArrangement) { + i.kind = vecLanes + i.u1 = uint64(op) + i.rn, i.rd = rn, rd + i.u2 = uint64(arr) +} + +func (i *instruction) asVecShiftImm(op vecOp, rd regalloc.VReg, rn, rm operand, arr vecArrangement) *instruction { + i.kind = vecShiftImm + i.u1 = uint64(op) + i.rn, i.rm, i.rd = rn, rm, rd + i.u2 = uint64(arr) + return i +} + +func (i *instruction) asVecTbl(nregs byte, rd regalloc.VReg, rn, rm operand, arr vecArrangement) { + switch nregs { + case 0, 1: + i.kind = vecTbl + case 2: + i.kind = vecTbl2 + if !rn.reg().IsRealReg() { + panic("rn is not a RealReg") + } + if rn.realReg() == v31 { + panic("rn cannot be v31") + } + default: + panic(fmt.Sprintf("unsupported number of registers %d", nregs)) + } + i.rn, i.rm, i.rd = rn, rm, rd + i.u2 = uint64(arr) +} + +func (i *instruction) asVecPermute(op vecOp, rd regalloc.VReg, rn, rm operand, arr vecArrangement) { + i.kind = vecPermute + i.u1 = uint64(op) + i.rn, i.rm, i.rd = rn, rm, rd + i.u2 = uint64(arr) +} + +func (i *instruction) asVecRRR(op vecOp, rd regalloc.VReg, rn, rm operand, arr vecArrangement) *instruction { + i.kind = vecRRR + i.u1 = uint64(op) + i.rn, i.rd, i.rm = rn, rd, rm + i.u2 = uint64(arr) + return i +} + +// asVecRRRRewrite encodes a vector instruction that rewrites the destination register. +// IMPORTANT: the destination register must be already defined before this instruction. +func (i *instruction) asVecRRRRewrite(op vecOp, rd regalloc.VReg, rn, rm operand, arr vecArrangement) { + i.kind = vecRRRRewrite + i.u1 = uint64(op) + i.rn, i.rd, i.rm = rn, rd, rm + i.u2 = uint64(arr) +} + +func (i *instruction) IsCopy() bool { + op := i.kind + // We do not include mov32 as it is not a copy instruction in the sense that it does not preserve the upper 32 bits, + // and it is only used in the translation of IReduce, not the actual copy indeed. + return op == mov64 || op == fpuMov64 || op == fpuMov128 +} + +// String implements fmt.Stringer. +func (i *instruction) String() (str string) { + is64SizeBitToSize := func(v uint64) byte { + if v == 0 { + return 32 + } + return 64 + } + + switch i.kind { + case nop0: + if i.u1 != 0 { + l := label(i.u1) + str = fmt.Sprintf("%s:", l) + } else { + str = "nop0" + } + case aluRRR: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(), + formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), size), + i.rm.format(size)) + case aluRRRR: + size := is64SizeBitToSize(i.u1 >> 32) + str = fmt.Sprintf("%s %s, %s, %s, %s", aluOp(i.u1).String(), + formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), size), formatVRegSized(i.rm.nr(), size), formatVRegSized(regalloc.VReg(i.u2), size)) + case aluRRImm12: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(), + formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), size), i.rm.format(size)) + case aluRRBitmaskImm: + size := is64SizeBitToSize(i.u1 >> 32) + rd, rn := formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), size) + if size == 32 { + str = fmt.Sprintf("%s %s, %s, #%#x", aluOp(i.u1).String(), rd, rn, uint32(i.u2)) + } else { + str = fmt.Sprintf("%s %s, %s, #%#x", aluOp(i.u1).String(), rd, rn, i.u2) + } + case aluRRImmShift: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("%s %s, %s, %#x", + aluOp(i.u1).String(), + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + i.rm.shiftImm(), + ) + case aluRRRShift: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("%s %s, %s, %s", + aluOp(i.u1).String(), + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + i.rm.format(size), + ) + case aluRRRExtend: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("%s %s, %s, %s", aluOp(i.u1).String(), + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + // Regardless of the source size, the register is formatted in 32-bit. + i.rm.format(32), + ) + case bitRR: + size := is64SizeBitToSize(i.u2) + str = fmt.Sprintf("%s %s, %s", + bitOp(i.u1), + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + ) + case uLoad8: + str = fmt.Sprintf("ldrb %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case sLoad8: + str = fmt.Sprintf("ldrsb %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case uLoad16: + str = fmt.Sprintf("ldrh %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case sLoad16: + str = fmt.Sprintf("ldrsh %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case uLoad32: + str = fmt.Sprintf("ldr %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case sLoad32: + str = fmt.Sprintf("ldrs %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case uLoad64: + str = fmt.Sprintf("ldr %s, %s", formatVRegSized(i.rd, 64), i.getAmode().format(64)) + case store8: + str = fmt.Sprintf("strb %s, %s", formatVRegSized(i.rn.nr(), 32), i.getAmode().format(8)) + case store16: + str = fmt.Sprintf("strh %s, %s", formatVRegSized(i.rn.nr(), 32), i.getAmode().format(16)) + case store32: + str = fmt.Sprintf("str %s, %s", formatVRegSized(i.rn.nr(), 32), i.getAmode().format(32)) + case store64: + str = fmt.Sprintf("str %s, %s", formatVRegSized(i.rn.nr(), 64), i.getAmode().format(64)) + case storeP64: + str = fmt.Sprintf("stp %s, %s, %s", + formatVRegSized(i.rn.nr(), 64), formatVRegSized(i.rm.nr(), 64), i.getAmode().format(64)) + case loadP64: + str = fmt.Sprintf("ldp %s, %s, %s", + formatVRegSized(i.rn.nr(), 64), formatVRegSized(i.rm.nr(), 64), i.getAmode().format(64)) + case mov64: + str = fmt.Sprintf("mov %s, %s", + formatVRegSized(i.rd, 64), + formatVRegSized(i.rn.nr(), 64)) + case mov32: + str = fmt.Sprintf("mov %s, %s", formatVRegSized(i.rd, 32), formatVRegSized(i.rn.nr(), 32)) + case movZ: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("movz %s, #%#x, lsl %d", formatVRegSized(i.rd, size), uint16(i.u1), uint32(i.u2)*16) + case movN: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("movn %s, #%#x, lsl %d", formatVRegSized(i.rd, size), uint16(i.u1), uint32(i.u2)*16) + case movK: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("movk %s, #%#x, lsl %d", formatVRegSized(i.rd, size), uint16(i.u1), uint32(i.u2)*16) + case extend: + fromBits, toBits := byte(i.u1), byte(i.u2) + + var signedStr string + if i.u2>>32 == 1 { + signedStr = "s" + } else { + signedStr = "u" + } + var fromStr string + switch fromBits { + case 8: + fromStr = "b" + case 16: + fromStr = "h" + case 32: + fromStr = "w" + } + str = fmt.Sprintf("%sxt%s %s, %s", signedStr, fromStr, formatVRegSized(i.rd, toBits), formatVRegSized(i.rn.nr(), 32)) + case cSel: + size := is64SizeBitToSize(i.u2) + str = fmt.Sprintf("csel %s, %s, %s, %s", + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + formatVRegSized(i.rm.nr(), size), + condFlag(i.u1), + ) + case cSet: + if i.u2 != 0 { + str = fmt.Sprintf("csetm %s, %s", formatVRegSized(i.rd, 64), condFlag(i.u1)) + } else { + str = fmt.Sprintf("cset %s, %s", formatVRegSized(i.rd, 64), condFlag(i.u1)) + } + case cCmpImm: + size := is64SizeBitToSize(i.u2 >> 32) + str = fmt.Sprintf("ccmp %s, #%#x, #%#x, %s", + formatVRegSized(i.rn.nr(), size), i.rm.data, + i.u2&0b1111, + condFlag(i.u1)) + case fpuMov64: + str = fmt.Sprintf("mov %s, %s", + formatVRegVec(i.rd, vecArrangement8B, vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement8B, vecIndexNone)) + case fpuMov128: + str = fmt.Sprintf("mov %s, %s", + formatVRegVec(i.rd, vecArrangement16B, vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement16B, vecIndexNone)) + case fpuMovFromVec: + panic("TODO") + case fpuRR: + dstSz := is64SizeBitToSize(i.u2) + srcSz := dstSz + op := fpuUniOp(i.u1) + switch op { + case fpuUniOpCvt32To64: + srcSz = 32 + case fpuUniOpCvt64To32: + srcSz = 64 + } + str = fmt.Sprintf("%s %s, %s", op.String(), + formatVRegSized(i.rd, dstSz), formatVRegSized(i.rn.nr(), srcSz)) + case fpuRRR: + size := is64SizeBitToSize(i.u2) + str = fmt.Sprintf("%s %s, %s, %s", fpuBinOp(i.u1).String(), + formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), size), formatVRegSized(i.rm.nr(), size)) + case fpuRRI: + panic("TODO") + case fpuRRRR: + panic("TODO") + case fpuCmp: + size := is64SizeBitToSize(i.u1) + str = fmt.Sprintf("fcmp %s, %s", + formatVRegSized(i.rn.nr(), size), formatVRegSized(i.rm.nr(), size)) + case fpuLoad32: + str = fmt.Sprintf("ldr %s, %s", formatVRegSized(i.rd, 32), i.getAmode().format(32)) + case fpuStore32: + str = fmt.Sprintf("str %s, %s", formatVRegSized(i.rn.nr(), 32), i.getAmode().format(64)) + case fpuLoad64: + str = fmt.Sprintf("ldr %s, %s", formatVRegSized(i.rd, 64), i.getAmode().format(64)) + case fpuStore64: + str = fmt.Sprintf("str %s, %s", formatVRegSized(i.rn.nr(), 64), i.getAmode().format(64)) + case fpuLoad128: + str = fmt.Sprintf("ldr %s, %s", formatVRegSized(i.rd, 128), i.getAmode().format(64)) + case fpuStore128: + str = fmt.Sprintf("str %s, %s", formatVRegSized(i.rn.nr(), 128), i.getAmode().format(64)) + case loadFpuConst32: + str = fmt.Sprintf("ldr %s, #8; b 8; data.f32 %f", formatVRegSized(i.rd, 32), math.Float32frombits(uint32(i.u1))) + case loadFpuConst64: + str = fmt.Sprintf("ldr %s, #8; b 16; data.f64 %f", formatVRegSized(i.rd, 64), math.Float64frombits(i.u1)) + case loadFpuConst128: + str = fmt.Sprintf("ldr %s, #8; b 32; data.v128 %016x %016x", + formatVRegSized(i.rd, 128), i.u1, i.u2) + case fpuToInt: + var op, src, dst string + if signed := i.u1 == 1; signed { + op = "fcvtzs" + } else { + op = "fcvtzu" + } + if src64 := i.u2&1 != 0; src64 { + src = formatVRegWidthVec(i.rn.nr(), vecArrangementD) + } else { + src = formatVRegWidthVec(i.rn.nr(), vecArrangementS) + } + if dst64 := i.u2&2 != 0; dst64 { + dst = formatVRegSized(i.rd, 64) + } else { + dst = formatVRegSized(i.rd, 32) + } + str = fmt.Sprintf("%s %s, %s", op, dst, src) + + case intToFpu: + var op, src, dst string + if signed := i.u1 == 1; signed { + op = "scvtf" + } else { + op = "ucvtf" + } + if src64 := i.u2&1 != 0; src64 { + src = formatVRegSized(i.rn.nr(), 64) + } else { + src = formatVRegSized(i.rn.nr(), 32) + } + if dst64 := i.u2&2 != 0; dst64 { + dst = formatVRegWidthVec(i.rd, vecArrangementD) + } else { + dst = formatVRegWidthVec(i.rd, vecArrangementS) + } + str = fmt.Sprintf("%s %s, %s", op, dst, src) + case fpuCSel: + size := is64SizeBitToSize(i.u2) + str = fmt.Sprintf("fcsel %s, %s, %s, %s", + formatVRegSized(i.rd, size), + formatVRegSized(i.rn.nr(), size), + formatVRegSized(i.rm.nr(), size), + condFlag(i.u1), + ) + case movToVec: + var size byte + arr := vecArrangement(i.u1) + switch arr { + case vecArrangementB, vecArrangementH, vecArrangementS: + size = 32 + case vecArrangementD: + size = 64 + default: + panic("unsupported arrangement " + arr.String()) + } + str = fmt.Sprintf("ins %s, %s", formatVRegVec(i.rd, arr, vecIndex(i.u2)), formatVRegSized(i.rn.nr(), size)) + case movFromVec, movFromVecSigned: + var size byte + var opcode string + arr := vecArrangement(i.u1) + signed := i.kind == movFromVecSigned + switch arr { + case vecArrangementB, vecArrangementH, vecArrangementS: + size = 32 + if signed { + opcode = "smov" + } else { + opcode = "umov" + } + case vecArrangementD: + size = 64 + if signed { + opcode = "smov" + } else { + opcode = "mov" + } + default: + panic("unsupported arrangement " + arr.String()) + } + str = fmt.Sprintf("%s %s, %s", opcode, formatVRegSized(i.rd, size), formatVRegVec(i.rn.nr(), arr, vecIndex(i.u2))) + case vecDup: + str = fmt.Sprintf("dup %s, %s", + formatVRegVec(i.rd, vecArrangement(i.u1), vecIndexNone), + formatVRegSized(i.rn.nr(), 64), + ) + case vecDupElement: + arr := vecArrangement(i.u1) + str = fmt.Sprintf("dup %s, %s", + formatVRegVec(i.rd, arr, vecIndexNone), + formatVRegVec(i.rn.nr(), arr, vecIndex(i.u2)), + ) + case vecDupFromFpu: + panic("TODO") + case vecExtract: + str = fmt.Sprintf("ext %s, %s, %s, #%d", + formatVRegVec(i.rd, vecArrangement(i.u1), vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement(i.u1), vecIndexNone), + formatVRegVec(i.rm.nr(), vecArrangement(i.u1), vecIndexNone), + uint32(i.u2), + ) + case vecExtend: + panic("TODO") + case vecMovElement: + str = fmt.Sprintf("mov %s, %s", + formatVRegVec(i.rd, vecArrangement(i.u1), vecIndex(i.u2&0xffffffff)), + formatVRegVec(i.rn.nr(), vecArrangement(i.u1), vecIndex(i.u2>>32)), + ) + case vecMiscNarrow: + panic("TODO") + case vecRRR, vecRRRRewrite: + str = fmt.Sprintf("%s %s, %s, %s", + vecOp(i.u1), + formatVRegVec(i.rd, vecArrangement(i.u2), vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement(i.u2), vecIndexNone), + formatVRegVec(i.rm.nr(), vecArrangement(i.u2), vecIndexNone), + ) + case vecMisc: + vop := vecOp(i.u1) + if vop == vecOpCmeq0 { + str = fmt.Sprintf("cmeq %s, %s, #0", + formatVRegVec(i.rd, vecArrangement(i.u2), vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement(i.u2), vecIndexNone)) + } else { + str = fmt.Sprintf("%s %s, %s", + vop, + formatVRegVec(i.rd, vecArrangement(i.u2), vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement(i.u2), vecIndexNone)) + } + case vecLanes: + arr := vecArrangement(i.u2) + var destArr vecArrangement + switch arr { + case vecArrangement8B, vecArrangement16B: + destArr = vecArrangementH + case vecArrangement4H, vecArrangement8H: + destArr = vecArrangementS + case vecArrangement4S: + destArr = vecArrangementD + default: + panic("invalid arrangement " + arr.String()) + } + str = fmt.Sprintf("%s %s, %s", + vecOp(i.u1), + formatVRegWidthVec(i.rd, destArr), + formatVRegVec(i.rn.nr(), arr, vecIndexNone)) + case vecShiftImm: + arr := vecArrangement(i.u2) + str = fmt.Sprintf("%s %s, %s, #%d", + vecOp(i.u1), + formatVRegVec(i.rd, arr, vecIndexNone), + formatVRegVec(i.rn.nr(), arr, vecIndexNone), + i.rm.shiftImm()) + case vecTbl: + arr := vecArrangement(i.u2) + str = fmt.Sprintf("tbl %s, { %s }, %s", + formatVRegVec(i.rd, arr, vecIndexNone), + formatVRegVec(i.rn.nr(), vecArrangement16B, vecIndexNone), + formatVRegVec(i.rm.nr(), arr, vecIndexNone)) + case vecTbl2: + arr := vecArrangement(i.u2) + rd, rn, rm := i.rd, i.rn.nr(), i.rm.nr() + rn1 := regalloc.FromRealReg(rn.RealReg()+1, rn.RegType()) + str = fmt.Sprintf("tbl %s, { %s, %s }, %s", + formatVRegVec(rd, arr, vecIndexNone), + formatVRegVec(rn, vecArrangement16B, vecIndexNone), + formatVRegVec(rn1, vecArrangement16B, vecIndexNone), + formatVRegVec(rm, arr, vecIndexNone)) + case vecPermute: + arr := vecArrangement(i.u2) + str = fmt.Sprintf("%s %s, %s, %s", + vecOp(i.u1), + formatVRegVec(i.rd, arr, vecIndexNone), + formatVRegVec(i.rn.nr(), arr, vecIndexNone), + formatVRegVec(i.rm.nr(), arr, vecIndexNone)) + case movToFPSR: + str = fmt.Sprintf("msr fpsr, %s", formatVRegSized(i.rn.nr(), 64)) + case movFromFPSR: + str = fmt.Sprintf("mrs %s fpsr", formatVRegSized(i.rd, 64)) + case call: + str = fmt.Sprintf("bl %s", ssa.FuncRef(i.u1)) + case callInd: + str = fmt.Sprintf("bl %s", formatVRegSized(i.rn.nr(), 64)) + case ret: + str = "ret" + case br: + target := label(i.u1) + if i.rm.data != 0 { + str = fmt.Sprintf("b #%#x (%s)", i.brOffset(), target.String()) + } else { + str = fmt.Sprintf("b %s", target.String()) + } + case condBr: + size := is64SizeBitToSize(i.u2 >> 32) + c := cond(i.u1) + target := label(i.u2 & 0xffffffff) + switch c.kind() { + case condKindRegisterZero: + if !i.condBrOffsetResolved() { + str = fmt.Sprintf("cbz %s, (%s)", formatVRegSized(c.register(), size), target.String()) + } else { + str = fmt.Sprintf("cbz %s, #%#x %s", formatVRegSized(c.register(), size), i.condBrOffset(), target.String()) + } + case condKindRegisterNotZero: + if offset := i.condBrOffset(); offset != 0 { + str = fmt.Sprintf("cbnz %s, #%#x (%s)", formatVRegSized(c.register(), size), offset, target.String()) + } else { + str = fmt.Sprintf("cbnz %s, %s", formatVRegSized(c.register(), size), target.String()) + } + case condKindCondFlagSet: + if offset := i.condBrOffset(); offset != 0 { + if target == labelInvalid { + str = fmt.Sprintf("b.%s #%#x", c.flag(), offset) + } else { + str = fmt.Sprintf("b.%s #%#x, (%s)", c.flag(), offset, target.String()) + } + } else { + str = fmt.Sprintf("b.%s %s", c.flag(), target.String()) + } + } + case adr: + str = fmt.Sprintf("adr %s, #%#x", formatVRegSized(i.rd, 64), int64(i.u1)) + case brTableSequence: + targetIndex := i.u1 + str = fmt.Sprintf("br_table_sequence %s, table_index=%d", formatVRegSized(i.rn.nr(), 64), targetIndex) + case exitSequence: + str = fmt.Sprintf("exit_sequence %s", formatVRegSized(i.rn.nr(), 64)) + case atomicRmw: + m := atomicRmwOp(i.u1).String() + size := byte(32) + switch i.u2 { + case 8: + size = 64 + case 2: + m = m + "h" + case 1: + m = m + "b" + } + str = fmt.Sprintf("%s %s, %s, %s", m, formatVRegSized(i.rm.nr(), size), formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), 64)) + case atomicCas: + m := "casal" + size := byte(32) + switch i.u2 { + case 8: + size = 64 + case 2: + m = m + "h" + case 1: + m = m + "b" + } + str = fmt.Sprintf("%s %s, %s, %s", m, formatVRegSized(i.rd, size), formatVRegSized(i.rm.nr(), size), formatVRegSized(i.rn.nr(), 64)) + case atomicLoad: + m := "ldar" + size := byte(32) + switch i.u2 { + case 8: + size = 64 + case 2: + m = m + "h" + case 1: + m = m + "b" + } + str = fmt.Sprintf("%s %s, %s", m, formatVRegSized(i.rd, size), formatVRegSized(i.rn.nr(), 64)) + case atomicStore: + m := "stlr" + size := byte(32) + switch i.u2 { + case 8: + size = 64 + case 2: + m = m + "h" + case 1: + m = m + "b" + } + str = fmt.Sprintf("%s %s, %s", m, formatVRegSized(i.rm.nr(), size), formatVRegSized(i.rn.nr(), 64)) + case dmb: + str = "dmb" + case udf: + str = "udf" + case emitSourceOffsetInfo: + str = fmt.Sprintf("source_offset_info %d", ssa.SourceOffset(i.u1)) + case vecLoad1R: + str = fmt.Sprintf("ld1r {%s}, [%s]", formatVRegVec(i.rd, vecArrangement(i.u1), vecIndexNone), formatVRegSized(i.rn.nr(), 64)) + case loadConstBlockArg: + str = fmt.Sprintf("load_const_block_arg %s, %#x", formatVRegSized(i.rd, 64), i.u1) + default: + panic(i.kind) + } + return +} + +func (i *instruction) asAdr(rd regalloc.VReg, offset int64) { + i.kind = adr + i.rd = rd + i.u1 = uint64(offset) +} + +func (i *instruction) asAtomicRmw(op atomicRmwOp, rn, rs, rt regalloc.VReg, size uint64) { + i.kind = atomicRmw + i.rd, i.rn, i.rm = rt, operandNR(rn), operandNR(rs) + i.u1 = uint64(op) + i.u2 = size +} + +func (i *instruction) asAtomicCas(rn, rs, rt regalloc.VReg, size uint64) { + i.kind = atomicCas + i.rm, i.rn, i.rd = operandNR(rt), operandNR(rn), rs + i.u2 = size +} + +func (i *instruction) asAtomicLoad(rn, rt regalloc.VReg, size uint64) { + i.kind = atomicLoad + i.rn, i.rd = operandNR(rn), rt + i.u2 = size +} + +func (i *instruction) asAtomicStore(rn, rt operand, size uint64) { + i.kind = atomicStore + i.rn, i.rm = rn, rt + i.u2 = size +} + +func (i *instruction) asDMB() { + i.kind = dmb +} + +// TODO: delete unnecessary things. +const ( + // nop0 represents a no-op of zero size. + nop0 instructionKind = iota + 1 + // aluRRR represents an ALU operation with two register sources and a register destination. + aluRRR + // aluRRRR represents an ALU operation with three register sources and a register destination. + aluRRRR + // aluRRImm12 represents an ALU operation with a register source and an immediate-12 source, with a register destination. + aluRRImm12 + // aluRRBitmaskImm represents an ALU operation with a register source and a bitmask immediate, with a register destination. + aluRRBitmaskImm + // aluRRImmShift represents an ALU operation with a register source and an immediate-shifted source, with a register destination. + aluRRImmShift + // aluRRRShift represents an ALU operation with two register sources, one of which can be shifted, with a register destination. + aluRRRShift + // aluRRRExtend represents an ALU operation with two register sources, one of which can be extended, with a register destination. + aluRRRExtend + // bitRR represents a bit op instruction with a single register source. + bitRR + // uLoad8 represents an unsigned 8-bit load. + uLoad8 + // sLoad8 represents a signed 8-bit load into 64-bit register. + sLoad8 + // uLoad16 represents an unsigned 16-bit load into 64-bit register. + uLoad16 + // sLoad16 represents a signed 16-bit load into 64-bit register. + sLoad16 + // uLoad32 represents an unsigned 32-bit load into 64-bit register. + uLoad32 + // sLoad32 represents a signed 32-bit load into 64-bit register. + sLoad32 + // uLoad64 represents a 64-bit load. + uLoad64 + // store8 represents an 8-bit store. + store8 + // store16 represents a 16-bit store. + store16 + // store32 represents a 32-bit store. + store32 + // store64 represents a 64-bit store. + store64 + // storeP64 represents a store of a pair of registers. + storeP64 + // loadP64 represents a load of a pair of registers. + loadP64 + // mov64 represents a MOV instruction. These are encoded as ORR's but we keep them separate for better handling. + mov64 + // mov32 represents a 32-bit MOV. This zeroes the top 32 bits of the destination. + mov32 + // movZ represents a MOVZ with a 16-bit immediate. + movZ + // movN represents a MOVN with a 16-bit immediate. + movN + // movK represents a MOVK with a 16-bit immediate. + movK + // extend represents a sign- or zero-extend operation. + extend + // cSel represents a conditional-select operation. + cSel + // cSet represents a conditional-set operation. + cSet + // cCmpImm represents a conditional comparison with an immediate. + cCmpImm + // fpuMov64 represents a FPU move. Distinct from a vector-register move; moving just 64 bits appears to be significantly faster. + fpuMov64 + // fpuMov128 represents a vector register move. + fpuMov128 + // fpuMovFromVec represents a move to scalar from a vector element. + fpuMovFromVec + // fpuRR represents a 1-op FPU instruction. + fpuRR + // fpuRRR represents a 2-op FPU instruction. + fpuRRR + // fpuRRI represents a 2-op FPU instruction with immediate value. + fpuRRI + // fpuRRRR represents a 3-op FPU instruction. + fpuRRRR + // fpuCmp represents a FPU comparison, either 32 or 64 bit. + fpuCmp + // fpuLoad32 represents a floating-point load, single-precision (32 bit). + fpuLoad32 + // fpuStore32 represents a floating-point store, single-precision (32 bit). + fpuStore32 + // fpuLoad64 represents a floating-point load, double-precision (64 bit). + fpuLoad64 + // fpuStore64 represents a floating-point store, double-precision (64 bit). + fpuStore64 + // fpuLoad128 represents a floating-point/vector load, 128 bit. + fpuLoad128 + // fpuStore128 represents a floating-point/vector store, 128 bit. + fpuStore128 + // loadFpuConst32 represents a load of a 32-bit floating-point constant. + loadFpuConst32 + // loadFpuConst64 represents a load of a 64-bit floating-point constant. + loadFpuConst64 + // loadFpuConst128 represents a load of a 128-bit floating-point constant. + loadFpuConst128 + // vecLoad1R represents a load of a one single-element structure that replicates to all lanes of a vector. + vecLoad1R + // fpuToInt represents a conversion from FP to integer. + fpuToInt + // intToFpu represents a conversion from integer to FP. + intToFpu + // fpuCSel represents a 32/64-bit FP conditional select. + fpuCSel + // movToVec represents a move to a vector element from a GPR. + movToVec + // movFromVec represents an unsigned move from a vector element to a GPR. + movFromVec + // movFromVecSigned represents a signed move from a vector element to a GPR. + movFromVecSigned + // vecDup represents a duplication of general-purpose register to vector. + vecDup + // vecDupElement represents a duplication of a vector element to vector or scalar. + vecDupElement + // vecDupFromFpu represents a duplication of scalar to vector. + vecDupFromFpu + // vecExtract represents a vector extraction operation. + vecExtract + // vecExtend represents a vector extension operation. + vecExtend + // vecMovElement represents a move vector element to another vector element operation. + vecMovElement + // vecMiscNarrow represents a vector narrowing operation. + vecMiscNarrow + // vecRRR represents a vector ALU operation. + vecRRR + // vecRRRRewrite is exactly the same as vecRRR except that this rewrites the destination register. + // For example, BSL instruction rewrites the destination register, and the existing value influences the result. + // Therefore, the "destination" register in vecRRRRewrite will be treated as "use" which makes the register outlive + // the instruction while this instruction doesn't have "def" in the context of register allocation. + vecRRRRewrite + // vecMisc represents a vector two register miscellaneous instruction. + vecMisc + // vecLanes represents a vector instruction across lanes. + vecLanes + // vecShiftImm represents a SIMD scalar shift by immediate instruction. + vecShiftImm + // vecTbl represents a table vector lookup - single register table. + vecTbl + // vecTbl2 represents a table vector lookup - two register table. + vecTbl2 + // vecPermute represents a vector permute instruction. + vecPermute + // movToNZCV represents a move to the FPSR. + movToFPSR + // movFromNZCV represents a move from the FPSR. + movFromFPSR + // call represents a machine call instruction. + call + // callInd represents a machine indirect-call instruction. + callInd + // ret represents a machine return instruction. + ret + // br represents an unconditional branch. + br + // condBr represents a conditional branch. + condBr + // adr represents a compute the address (using a PC-relative offset) of a memory location. + adr + // brTableSequence represents a jump-table sequence. + brTableSequence + // exitSequence consists of multiple instructions, and exits the execution immediately. + // See encodeExitSequence. + exitSequence + // atomicRmw represents an atomic read-modify-write operation with two register sources and a register destination. + atomicRmw + // atomicCas represents an atomic compare-and-swap operation with three register sources. The value is loaded to + // the source register containing the comparison value. + atomicCas + // atomicLoad represents an atomic load with one source register and a register destination. + atomicLoad + // atomicStore represents an atomic store with two source registers and no destination. + atomicStore + // dmb represents the data memory barrier instruction in inner-shareable (ish) mode. + dmb + // UDF is the undefined instruction. For debugging only. + udf + // loadConstBlockArg represents a load of a constant block argument. + loadConstBlockArg + + // emitSourceOffsetInfo is a dummy instruction to emit source offset info. + // The existence of this instruction does not affect the execution. + emitSourceOffsetInfo + + // ------------------- do not define below this line ------------------- + numInstructionKinds +) + +func (i *instruction) asLoadConstBlockArg(v uint64, typ ssa.Type, dst regalloc.VReg) *instruction { + i.kind = loadConstBlockArg + i.u1 = v + i.u2 = uint64(typ) + i.rd = dst + return i +} + +func (i *instruction) loadConstBlockArgData() (v uint64, typ ssa.Type, dst regalloc.VReg) { + return i.u1, ssa.Type(i.u2), i.rd +} + +func (i *instruction) asEmitSourceOffsetInfo(l ssa.SourceOffset) *instruction { + i.kind = emitSourceOffsetInfo + i.u1 = uint64(l) + return i +} + +func (i *instruction) sourceOffsetInfo() ssa.SourceOffset { + return ssa.SourceOffset(i.u1) +} + +func (i *instruction) asUDF() *instruction { + i.kind = udf + return i +} + +func (i *instruction) asFpuToInt(rd regalloc.VReg, rn operand, rdSigned, src64bit, dst64bit bool) { + i.kind = fpuToInt + i.rn = rn + i.rd = rd + if rdSigned { + i.u1 = 1 + } + if src64bit { + i.u2 = 1 + } + if dst64bit { + i.u2 |= 2 + } +} + +func (i *instruction) asIntToFpu(rd regalloc.VReg, rn operand, rnSigned, src64bit, dst64bit bool) { + i.kind = intToFpu + i.rn = rn + i.rd = rd + if rnSigned { + i.u1 = 1 + } + if src64bit { + i.u2 = 1 + } + if dst64bit { + i.u2 |= 2 + } +} + +func (i *instruction) asExitSequence(ctx regalloc.VReg) *instruction { + i.kind = exitSequence + i.rn = operandNR(ctx) + return i +} + +// aluOp determines the type of ALU operation. Instructions whose kind is one of +// aluRRR, aluRRRR, aluRRImm12, aluRRBitmaskImm, aluRRImmShift, aluRRRShift and aluRRRExtend +// would use this type. +type aluOp uint32 + +func (a aluOp) String() string { + switch a { + case aluOpAdd: + return "add" + case aluOpSub: + return "sub" + case aluOpOrr: + return "orr" + case aluOpOrn: + return "orn" + case aluOpAnd: + return "and" + case aluOpAnds: + return "ands" + case aluOpBic: + return "bic" + case aluOpEor: + return "eor" + case aluOpAddS: + return "adds" + case aluOpSubS: + return "subs" + case aluOpSMulH: + return "sMulH" + case aluOpUMulH: + return "uMulH" + case aluOpSDiv: + return "sdiv" + case aluOpUDiv: + return "udiv" + case aluOpRotR: + return "ror" + case aluOpLsr: + return "lsr" + case aluOpAsr: + return "asr" + case aluOpLsl: + return "lsl" + case aluOpMAdd: + return "madd" + case aluOpMSub: + return "msub" + } + panic(int(a)) +} + +const ( + // 32/64-bit Add. + aluOpAdd aluOp = iota + // 32/64-bit Subtract. + aluOpSub + // 32/64-bit Bitwise OR. + aluOpOrr + // 32/64-bit Bitwise OR NOT. + aluOpOrn + // 32/64-bit Bitwise AND. + aluOpAnd + // 32/64-bit Bitwise ANDS. + aluOpAnds + // 32/64-bit Bitwise AND NOT. + aluOpBic + // 32/64-bit Bitwise XOR (Exclusive OR). + aluOpEor + // 32/64-bit Add setting flags. + aluOpAddS + // 32/64-bit Subtract setting flags. + aluOpSubS + // Signed multiply, high-word result. + aluOpSMulH + // Unsigned multiply, high-word result. + aluOpUMulH + // 64-bit Signed divide. + aluOpSDiv + // 64-bit Unsigned divide. + aluOpUDiv + // 32/64-bit Rotate right. + aluOpRotR + // 32/64-bit Logical shift right. + aluOpLsr + // 32/64-bit Arithmetic shift right. + aluOpAsr + // 32/64-bit Logical shift left. + aluOpLsl /// Multiply-add + + // MAdd and MSub are only applicable for aluRRRR. + aluOpMAdd + aluOpMSub +) + +// vecOp determines the type of vector operation. Instructions whose kind is one of +// vecOpCnt would use this type. +type vecOp int + +// String implements fmt.Stringer. +func (b vecOp) String() string { + switch b { + case vecOpCnt: + return "cnt" + case vecOpCmeq: + return "cmeq" + case vecOpCmgt: + return "cmgt" + case vecOpCmhi: + return "cmhi" + case vecOpCmge: + return "cmge" + case vecOpCmhs: + return "cmhs" + case vecOpFcmeq: + return "fcmeq" + case vecOpFcmgt: + return "fcmgt" + case vecOpFcmge: + return "fcmge" + case vecOpCmeq0: + return "cmeq0" + case vecOpUaddlv: + return "uaddlv" + case vecOpBit: + return "bit" + case vecOpBic: + return "bic" + case vecOpBsl: + return "bsl" + case vecOpNot: + return "not" + case vecOpAnd: + return "and" + case vecOpOrr: + return "orr" + case vecOpEOR: + return "eor" + case vecOpFadd: + return "fadd" + case vecOpAdd: + return "add" + case vecOpAddp: + return "addp" + case vecOpAddv: + return "addv" + case vecOpSub: + return "sub" + case vecOpFsub: + return "fsub" + case vecOpSmin: + return "smin" + case vecOpUmin: + return "umin" + case vecOpUminv: + return "uminv" + case vecOpSmax: + return "smax" + case vecOpUmax: + return "umax" + case vecOpUmaxp: + return "umaxp" + case vecOpUrhadd: + return "urhadd" + case vecOpFmul: + return "fmul" + case vecOpSqrdmulh: + return "sqrdmulh" + case vecOpMul: + return "mul" + case vecOpUmlal: + return "umlal" + case vecOpFdiv: + return "fdiv" + case vecOpFsqrt: + return "fsqrt" + case vecOpAbs: + return "abs" + case vecOpFabs: + return "fabs" + case vecOpNeg: + return "neg" + case vecOpFneg: + return "fneg" + case vecOpFrintp: + return "frintp" + case vecOpFrintm: + return "frintm" + case vecOpFrintn: + return "frintn" + case vecOpFrintz: + return "frintz" + case vecOpFcvtl: + return "fcvtl" + case vecOpFcvtn: + return "fcvtn" + case vecOpFcvtzu: + return "fcvtzu" + case vecOpFcvtzs: + return "fcvtzs" + case vecOpScvtf: + return "scvtf" + case vecOpUcvtf: + return "ucvtf" + case vecOpSqxtn: + return "sqxtn" + case vecOpUqxtn: + return "uqxtn" + case vecOpSqxtun: + return "sqxtun" + case vecOpRev64: + return "rev64" + case vecOpXtn: + return "xtn" + case vecOpShll: + return "shll" + case vecOpSshl: + return "sshl" + case vecOpSshll: + return "sshll" + case vecOpUshl: + return "ushl" + case vecOpUshll: + return "ushll" + case vecOpSshr: + return "sshr" + case vecOpZip1: + return "zip1" + case vecOpFmin: + return "fmin" + case vecOpFmax: + return "fmax" + case vecOpSmull: + return "smull" + case vecOpSmull2: + return "smull2" + } + panic(int(b)) +} + +const ( + vecOpCnt vecOp = iota + vecOpCmeq0 + vecOpCmeq + vecOpCmgt + vecOpCmhi + vecOpCmge + vecOpCmhs + vecOpFcmeq + vecOpFcmgt + vecOpFcmge + vecOpUaddlv + vecOpBit + vecOpBic + vecOpBsl + vecOpNot + vecOpAnd + vecOpOrr + vecOpEOR + vecOpAdd + vecOpFadd + vecOpAddv + vecOpSqadd + vecOpUqadd + vecOpAddp + vecOpSub + vecOpFsub + vecOpSqsub + vecOpUqsub + vecOpSmin + vecOpUmin + vecOpUminv + vecOpFmin + vecOpSmax + vecOpUmax + vecOpUmaxp + vecOpFmax + vecOpUrhadd + vecOpMul + vecOpFmul + vecOpSqrdmulh + vecOpUmlal + vecOpFdiv + vecOpFsqrt + vecOpAbs + vecOpFabs + vecOpNeg + vecOpFneg + vecOpFrintm + vecOpFrintn + vecOpFrintp + vecOpFrintz + vecOpFcvtl + vecOpFcvtn + vecOpFcvtzs + vecOpFcvtzu + vecOpScvtf + vecOpUcvtf + vecOpSqxtn + vecOpSqxtun + vecOpUqxtn + vecOpRev64 + vecOpXtn + vecOpShll + vecOpSshl + vecOpSshll + vecOpUshl + vecOpUshll + vecOpSshr + vecOpZip1 + vecOpSmull + vecOpSmull2 +) + +// bitOp determines the type of bitwise operation. Instructions whose kind is one of +// bitOpRbit and bitOpClz would use this type. +type bitOp int + +// String implements fmt.Stringer. +func (b bitOp) String() string { + switch b { + case bitOpRbit: + return "rbit" + case bitOpClz: + return "clz" + } + panic(int(b)) +} + +const ( + // 32/64-bit Rbit. + bitOpRbit bitOp = iota + // 32/64-bit Clz. + bitOpClz +) + +// fpuUniOp represents a unary floating-point unit (FPU) operation. +type fpuUniOp byte + +const ( + fpuUniOpNeg fpuUniOp = iota + fpuUniOpCvt32To64 + fpuUniOpCvt64To32 + fpuUniOpSqrt + fpuUniOpRoundPlus + fpuUniOpRoundMinus + fpuUniOpRoundZero + fpuUniOpRoundNearest + fpuUniOpAbs +) + +// String implements the fmt.Stringer. +func (f fpuUniOp) String() string { + switch f { + case fpuUniOpNeg: + return "fneg" + case fpuUniOpCvt32To64: + return "fcvt" + case fpuUniOpCvt64To32: + return "fcvt" + case fpuUniOpSqrt: + return "fsqrt" + case fpuUniOpRoundPlus: + return "frintp" + case fpuUniOpRoundMinus: + return "frintm" + case fpuUniOpRoundZero: + return "frintz" + case fpuUniOpRoundNearest: + return "frintn" + case fpuUniOpAbs: + return "fabs" + } + panic(int(f)) +} + +// fpuBinOp represents a binary floating-point unit (FPU) operation. +type fpuBinOp byte + +const ( + fpuBinOpAdd = iota + fpuBinOpSub + fpuBinOpMul + fpuBinOpDiv + fpuBinOpMax + fpuBinOpMin +) + +// String implements the fmt.Stringer. +func (f fpuBinOp) String() string { + switch f { + case fpuBinOpAdd: + return "fadd" + case fpuBinOpSub: + return "fsub" + case fpuBinOpMul: + return "fmul" + case fpuBinOpDiv: + return "fdiv" + case fpuBinOpMax: + return "fmax" + case fpuBinOpMin: + return "fmin" + } + panic(int(f)) +} + +// extMode represents the mode of a register operand extension. +// For example, aluRRRExtend instructions need this info to determine the extensions. +type extMode byte + +const ( + extModeNone extMode = iota + // extModeZeroExtend64 suggests a zero-extension to 32 bits if the original bit size is less than 32. + extModeZeroExtend32 + // extModeSignExtend64 stands for a sign-extension to 32 bits if the original bit size is less than 32. + extModeSignExtend32 + // extModeZeroExtend64 suggests a zero-extension to 64 bits if the original bit size is less than 64. + extModeZeroExtend64 + // extModeSignExtend64 stands for a sign-extension to 64 bits if the original bit size is less than 64. + extModeSignExtend64 +) + +func (e extMode) bits() byte { + switch e { + case extModeZeroExtend32, extModeSignExtend32: + return 32 + case extModeZeroExtend64, extModeSignExtend64: + return 64 + default: + return 0 + } +} + +func (e extMode) signed() bool { + switch e { + case extModeSignExtend32, extModeSignExtend64: + return true + default: + return false + } +} + +func extModeOf(t ssa.Type, signed bool) extMode { + switch t.Bits() { + case 32: + if signed { + return extModeSignExtend32 + } + return extModeZeroExtend32 + case 64: + if signed { + return extModeSignExtend64 + } + return extModeZeroExtend64 + default: + panic("TODO? do we need narrower than 32 bits?") + } +} + +type extendOp byte + +const ( + extendOpUXTB extendOp = 0b000 + extendOpUXTH extendOp = 0b001 + extendOpUXTW extendOp = 0b010 + // extendOpUXTX does nothing, but convenient symbol that officially exists. See: + // https://stackoverflow.com/questions/72041372/what-do-the-uxtx-and-sxtx-extensions-mean-for-32-bit-aarch64-adds-instruct + extendOpUXTX extendOp = 0b011 + extendOpSXTB extendOp = 0b100 + extendOpSXTH extendOp = 0b101 + extendOpSXTW extendOp = 0b110 + // extendOpSXTX does nothing, but convenient symbol that officially exists. See: + // https://stackoverflow.com/questions/72041372/what-do-the-uxtx-and-sxtx-extensions-mean-for-32-bit-aarch64-adds-instruct + extendOpSXTX extendOp = 0b111 + extendOpNone extendOp = 0xff +) + +func (e extendOp) srcBits() byte { + switch e { + case extendOpUXTB, extendOpSXTB: + return 8 + case extendOpUXTH, extendOpSXTH: + return 16 + case extendOpUXTW, extendOpSXTW: + return 32 + case extendOpUXTX, extendOpSXTX: + return 64 + } + panic(int(e)) +} + +func (e extendOp) String() string { + switch e { + case extendOpUXTB: + return "UXTB" + case extendOpUXTH: + return "UXTH" + case extendOpUXTW: + return "UXTW" + case extendOpUXTX: + return "UXTX" + case extendOpSXTB: + return "SXTB" + case extendOpSXTH: + return "SXTH" + case extendOpSXTW: + return "SXTW" + case extendOpSXTX: + return "SXTX" + } + panic(int(e)) +} + +func extendOpFrom(signed bool, from byte) extendOp { + switch from { + case 8: + if signed { + return extendOpSXTB + } + return extendOpUXTB + case 16: + if signed { + return extendOpSXTH + } + return extendOpUXTH + case 32: + if signed { + return extendOpSXTW + } + return extendOpUXTW + case 64: + if signed { + return extendOpSXTX + } + return extendOpUXTX + } + panic("invalid extendOpFrom") +} + +type shiftOp byte + +const ( + shiftOpLSL shiftOp = 0b00 + shiftOpLSR shiftOp = 0b01 + shiftOpASR shiftOp = 0b10 + shiftOpROR shiftOp = 0b11 +) + +func (s shiftOp) String() string { + switch s { + case shiftOpLSL: + return "lsl" + case shiftOpLSR: + return "lsr" + case shiftOpASR: + return "asr" + case shiftOpROR: + return "ror" + } + panic(int(s)) +} + +const exitSequenceSize = 6 * 4 // 6 instructions as in encodeExitSequence. + +// size returns the size of the instruction in encoded bytes. +func (i *instruction) size() int64 { + switch i.kind { + case exitSequence: + return exitSequenceSize // 5 instructions as in encodeExitSequence. + case nop0, loadConstBlockArg: + return 0 + case emitSourceOffsetInfo: + return 0 + case loadFpuConst32: + if i.u1 == 0 { + return 4 // zero loading can be encoded as a single instruction. + } + return 4 + 4 + 4 + case loadFpuConst64: + if i.u1 == 0 { + return 4 // zero loading can be encoded as a single instruction. + } + return 4 + 4 + 8 + case loadFpuConst128: + if i.u1 == 0 && i.u2 == 0 { + return 4 // zero loading can be encoded as a single instruction. + } + return 4 + 4 + 16 + case brTableSequence: + return 4*4 + int64(i.u2)*4 + default: + return 4 + } +} + +// vecArrangement is the arrangement of data within a vector register. +type vecArrangement byte + +const ( + // vecArrangementNone is an arrangement indicating no data is stored. + vecArrangementNone vecArrangement = iota + // vecArrangement8B is an arrangement of 8 bytes (64-bit vector) + vecArrangement8B + // vecArrangement16B is an arrangement of 16 bytes (128-bit vector) + vecArrangement16B + // vecArrangement4H is an arrangement of 4 half precisions (64-bit vector) + vecArrangement4H + // vecArrangement8H is an arrangement of 8 half precisions (128-bit vector) + vecArrangement8H + // vecArrangement2S is an arrangement of 2 single precisions (64-bit vector) + vecArrangement2S + // vecArrangement4S is an arrangement of 4 single precisions (128-bit vector) + vecArrangement4S + // vecArrangement1D is an arrangement of 1 double precision (64-bit vector) + vecArrangement1D + // vecArrangement2D is an arrangement of 2 double precisions (128-bit vector) + vecArrangement2D + + // Assign each vector size specifier to a vector arrangement ID. + // Instructions can only have an arrangement or a size specifier, but not both, so it + // simplifies the internal representation of vector instructions by being able to + // store either into the same field. + + // vecArrangementB is a size specifier of byte + vecArrangementB + // vecArrangementH is a size specifier of word (16-bit) + vecArrangementH + // vecArrangementS is a size specifier of double word (32-bit) + vecArrangementS + // vecArrangementD is a size specifier of quad word (64-bit) + vecArrangementD + // vecArrangementQ is a size specifier of the entire vector (128-bit) + vecArrangementQ +) + +// String implements fmt.Stringer +func (v vecArrangement) String() (ret string) { + switch v { + case vecArrangement8B: + ret = "8B" + case vecArrangement16B: + ret = "16B" + case vecArrangement4H: + ret = "4H" + case vecArrangement8H: + ret = "8H" + case vecArrangement2S: + ret = "2S" + case vecArrangement4S: + ret = "4S" + case vecArrangement1D: + ret = "1D" + case vecArrangement2D: + ret = "2D" + case vecArrangementB: + ret = "B" + case vecArrangementH: + ret = "H" + case vecArrangementS: + ret = "S" + case vecArrangementD: + ret = "D" + case vecArrangementQ: + ret = "Q" + case vecArrangementNone: + ret = "none" + default: + panic(v) + } + return +} + +// vecIndex is the index of an element of a vector register +type vecIndex byte + +// vecIndexNone indicates no vector index specified. +const vecIndexNone = ^vecIndex(0) + +func ssaLaneToArrangement(lane ssa.VecLane) vecArrangement { + switch lane { + case ssa.VecLaneI8x16: + return vecArrangement16B + case ssa.VecLaneI16x8: + return vecArrangement8H + case ssa.VecLaneI32x4: + return vecArrangement4S + case ssa.VecLaneI64x2: + return vecArrangement2D + case ssa.VecLaneF32x4: + return vecArrangement4S + case ssa.VecLaneF64x2: + return vecArrangement2D + default: + panic(lane) + } +} + +// atomicRmwOp is the type of atomic read-modify-write operation. +type atomicRmwOp byte + +const ( + // atomicRmwOpAdd is an atomic add operation. + atomicRmwOpAdd atomicRmwOp = iota + // atomicRmwOpClr is an atomic clear operation, i.e. AND NOT. + atomicRmwOpClr + // atomicRmwOpSet is an atomic set operation, i.e. OR. + atomicRmwOpSet + // atomicRmwOpEor is an atomic exclusive OR operation. + atomicRmwOpEor + // atomicRmwOpSwp is an atomic swap operation. + atomicRmwOpSwp +) + +// String implements fmt.Stringer +func (a atomicRmwOp) String() string { + switch a { + case atomicRmwOpAdd: + return "ldaddal" + case atomicRmwOpClr: + return "ldclral" + case atomicRmwOpSet: + return "ldsetal" + case atomicRmwOpEor: + return "ldeoral" + case atomicRmwOpSwp: + return "swpal" + } + panic(fmt.Sprintf("unknown atomicRmwOp: %d", a)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go new file mode 100644 index 00000000..21be9b71 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go @@ -0,0 +1,2351 @@ +package arm64 + +import ( + "context" + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// Encode implements backend.Machine Encode. +func (m *machine) Encode(ctx context.Context) error { + m.resolveRelativeAddresses(ctx) + m.encode(m.rootInstr) + if l := len(m.compiler.Buf()); l > maxFunctionExecutableSize { + return fmt.Errorf("function size exceeds the limit: %d > %d", l, maxFunctionExecutableSize) + } + return nil +} + +func (m *machine) encode(root *instruction) { + for cur := root; cur != nil; cur = cur.next { + cur.encode(m) + } +} + +func (i *instruction) encode(m *machine) { + c := m.compiler + switch kind := i.kind; kind { + case nop0, emitSourceOffsetInfo, loadConstBlockArg: + case exitSequence: + encodeExitSequence(c, i.rn.reg()) + case ret: + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/RET--Return-from-subroutine-?lang=en + c.Emit4Bytes(encodeRet()) + case br: + imm := i.brOffset() + c.Emit4Bytes(encodeUnconditionalBranch(false, imm)) + case call: + // We still don't know the exact address of the function to call, so we emit a placeholder. + c.AddRelocationInfo(i.callFuncRef()) + c.Emit4Bytes(encodeUnconditionalBranch(true, 0)) // 0 = placeholder + case callInd: + c.Emit4Bytes(encodeUnconditionalBranchReg(regNumberInEncoding[i.rn.realReg()], true)) + case store8, store16, store32, store64, fpuStore32, fpuStore64, fpuStore128: + c.Emit4Bytes(encodeLoadOrStore(i.kind, regNumberInEncoding[i.rn.realReg()], *i.getAmode())) + case uLoad8, uLoad16, uLoad32, uLoad64, sLoad8, sLoad16, sLoad32, fpuLoad32, fpuLoad64, fpuLoad128: + c.Emit4Bytes(encodeLoadOrStore(i.kind, regNumberInEncoding[i.rd.RealReg()], *i.getAmode())) + case vecLoad1R: + c.Emit4Bytes(encodeVecLoad1R( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(i.u1))) + case condBr: + imm19 := i.condBrOffset() + if imm19%4 != 0 { + panic("imm26 for branch must be a multiple of 4") + } + + imm19U32 := uint32(imm19/4) & 0b111_11111111_11111111 + brCond := i.condBrCond() + switch brCond.kind() { + case condKindRegisterZero: + rt := regNumberInEncoding[brCond.register().RealReg()] + c.Emit4Bytes(encodeCBZCBNZ(rt, false, imm19U32, i.condBr64bit())) + case condKindRegisterNotZero: + rt := regNumberInEncoding[brCond.register().RealReg()] + c.Emit4Bytes(encodeCBZCBNZ(rt, true, imm19U32, i.condBr64bit())) + case condKindCondFlagSet: + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/B-cond--Branch-conditionally- + fl := brCond.flag() + c.Emit4Bytes(0b01010100<<24 | (imm19U32 << 5) | uint32(fl)) + default: + panic("BUG") + } + case movN: + c.Emit4Bytes(encodeMoveWideImmediate(0b00, regNumberInEncoding[i.rd.RealReg()], i.u1, uint32(i.u2), uint32(i.u2>>32))) + case movZ: + c.Emit4Bytes(encodeMoveWideImmediate(0b10, regNumberInEncoding[i.rd.RealReg()], i.u1, uint32(i.u2), uint32(i.u2>>32))) + case movK: + c.Emit4Bytes(encodeMoveWideImmediate(0b11, regNumberInEncoding[i.rd.RealReg()], i.u1, uint32(i.u2), uint32(i.u2>>32))) + case mov32: + to, from := i.rd.RealReg(), i.rn.realReg() + c.Emit4Bytes(encodeAsMov32(regNumberInEncoding[from], regNumberInEncoding[to])) + case mov64: + to, from := i.rd.RealReg(), i.rn.realReg() + toIsSp := to == sp + fromIsSp := from == sp + c.Emit4Bytes(encodeMov64(regNumberInEncoding[to], regNumberInEncoding[from], toIsSp, fromIsSp)) + case loadP64, storeP64: + rt, rt2 := regNumberInEncoding[i.rn.realReg()], regNumberInEncoding[i.rm.realReg()] + amode := i.getAmode() + rn := regNumberInEncoding[amode.rn.RealReg()] + var pre bool + switch amode.kind { + case addressModeKindPostIndex: + case addressModeKindPreIndex: + pre = true + default: + panic("BUG") + } + c.Emit4Bytes(encodePreOrPostIndexLoadStorePair64(pre, kind == loadP64, rn, rt, rt2, amode.imm)) + case loadFpuConst32: + rd := regNumberInEncoding[i.rd.RealReg()] + if i.u1 == 0 { + c.Emit4Bytes(encodeVecRRR(vecOpEOR, rd, rd, rd, vecArrangement8B)) + } else { + encodeLoadFpuConst32(c, rd, i.u1) + } + case loadFpuConst64: + rd := regNumberInEncoding[i.rd.RealReg()] + if i.u1 == 0 { + c.Emit4Bytes(encodeVecRRR(vecOpEOR, rd, rd, rd, vecArrangement8B)) + } else { + encodeLoadFpuConst64(c, regNumberInEncoding[i.rd.RealReg()], i.u1) + } + case loadFpuConst128: + rd := regNumberInEncoding[i.rd.RealReg()] + lo, hi := i.u1, i.u2 + if lo == 0 && hi == 0 { + c.Emit4Bytes(encodeVecRRR(vecOpEOR, rd, rd, rd, vecArrangement16B)) + } else { + encodeLoadFpuConst128(c, rd, lo, hi) + } + case aluRRRR: + c.Emit4Bytes(encodeAluRRRR( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + regNumberInEncoding[regalloc.VReg(i.u2).RealReg()], + uint32(i.u1>>32), + )) + case aluRRImmShift: + c.Emit4Bytes(encodeAluRRImm( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + uint32(i.rm.shiftImm()), + uint32(i.u2>>32), + )) + case aluRRR: + rn := i.rn.realReg() + c.Emit4Bytes(encodeAluRRR( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[rn], + regNumberInEncoding[i.rm.realReg()], + i.u2>>32 == 1, + rn == sp, + )) + case aluRRRExtend: + rm, exo, to := i.rm.er() + c.Emit4Bytes(encodeAluRRRExtend( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[rm.RealReg()], + exo, + to, + )) + case aluRRRShift: + r, amt, sop := i.rm.sr() + c.Emit4Bytes(encodeAluRRRShift( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[r.RealReg()], + uint32(amt), + sop, + i.u2>>32 == 1, + )) + case aluRRBitmaskImm: + c.Emit4Bytes(encodeAluBitmaskImmediate( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + i.u2, + i.u1>>32 == 1, + )) + case bitRR: + c.Emit4Bytes(encodeBitRR( + bitOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + uint32(i.u2)), + ) + case aluRRImm12: + imm12, shift := i.rm.imm12() + c.Emit4Bytes(encodeAluRRImm12( + aluOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + imm12, shift, + i.u2>>32 == 1, + )) + case fpuRRR: + c.Emit4Bytes(encodeFpuRRR( + fpuBinOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + i.u2 == 1, + )) + case fpuMov64, fpuMov128: + // https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/MOV--vector---Move-vector--an-alias-of-ORR--vector--register-- + rd := regNumberInEncoding[i.rd.RealReg()] + rn := regNumberInEncoding[i.rn.realReg()] + var q uint32 + if kind == fpuMov128 { + q = 0b1 + } + c.Emit4Bytes(q<<30 | 0b1110101<<21 | rn<<16 | 0b000111<<10 | rn<<5 | rd) + case cSet: + rd := regNumberInEncoding[i.rd.RealReg()] + cf := condFlag(i.u1) + if i.u2 == 1 { + // https://developer.arm.com/documentation/ddi0602/2022-03/Base-Instructions/CSETM--Conditional-Set-Mask--an-alias-of-CSINV- + // Note that we set 64bit version here. + c.Emit4Bytes(0b1101101010011111<<16 | uint32(cf.invert())<<12 | 0b011111<<5 | rd) + } else { + // https://developer.arm.com/documentation/ddi0602/2022-06/Base-Instructions/CSET--Conditional-Set--an-alias-of-CSINC- + // Note that we set 64bit version here. + c.Emit4Bytes(0b1001101010011111<<16 | uint32(cf.invert())<<12 | 0b111111<<5 | rd) + } + case extend: + c.Emit4Bytes(encodeExtend((i.u2>>32) == 1, byte(i.u1), byte(i.u2), regNumberInEncoding[i.rd.RealReg()], regNumberInEncoding[i.rn.realReg()])) + case fpuCmp: + // https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/FCMP--Floating-point-quiet-Compare--scalar--?lang=en + rn, rm := regNumberInEncoding[i.rn.realReg()], regNumberInEncoding[i.rm.realReg()] + var ftype uint32 + if i.u1 == 1 { + ftype = 0b01 // double precision. + } + c.Emit4Bytes(0b1111<<25 | ftype<<22 | 1<<21 | rm<<16 | 0b1<<13 | rn<<5) + case udf: + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/UDF--Permanently-Undefined-?lang=en + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + c.Emit4Bytes(dummyInstruction) + } else { + c.Emit4Bytes(0) + } + case adr: + c.Emit4Bytes(encodeAdr(regNumberInEncoding[i.rd.RealReg()], uint32(i.u1))) + case cSel: + c.Emit4Bytes(encodeConditionalSelect( + kind, + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + condFlag(i.u1), + i.u2 == 1, + )) + case fpuCSel: + c.Emit4Bytes(encodeFpuCSel( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + condFlag(i.u1), + i.u2 == 1, + )) + case movToVec: + c.Emit4Bytes(encodeMoveToVec( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(byte(i.u1)), + vecIndex(i.u2), + )) + case movFromVec, movFromVecSigned: + c.Emit4Bytes(encodeMoveFromVec( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(byte(i.u1)), + vecIndex(i.u2), + i.kind == movFromVecSigned, + )) + case vecDup: + c.Emit4Bytes(encodeVecDup( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(byte(i.u1)))) + case vecDupElement: + c.Emit4Bytes(encodeVecDupElement( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(byte(i.u1)), + vecIndex(i.u2))) + case vecExtract: + c.Emit4Bytes(encodeVecExtract( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + vecArrangement(byte(i.u1)), + uint32(i.u2))) + case vecPermute: + c.Emit4Bytes(encodeVecPermute( + vecOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + vecArrangement(byte(i.u2)))) + case vecMovElement: + c.Emit4Bytes(encodeVecMovElement( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(i.u1), + uint32(i.u2), uint32(i.u2>>32), + )) + case vecMisc: + c.Emit4Bytes(encodeAdvancedSIMDTwoMisc( + vecOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(i.u2), + )) + case vecLanes: + c.Emit4Bytes(encodeVecLanes( + vecOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + vecArrangement(i.u2), + )) + case vecShiftImm: + c.Emit4Bytes(encodeVecShiftImm( + vecOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + uint32(i.rm.shiftImm()), + vecArrangement(i.u2), + )) + case vecTbl: + c.Emit4Bytes(encodeVecTbl( + 1, + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + vecArrangement(i.u2)), + ) + case vecTbl2: + c.Emit4Bytes(encodeVecTbl( + 2, + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + vecArrangement(i.u2)), + ) + case brTableSequence: + targets := m.jmpTableTargets[i.u1] + encodeBrTableSequence(c, i.rn.reg(), targets) + case fpuToInt, intToFpu: + c.Emit4Bytes(encodeCnvBetweenFloatInt(i)) + case fpuRR: + c.Emit4Bytes(encodeFloatDataOneSource( + fpuUniOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + i.u2 == 1, + )) + case vecRRR: + if op := vecOp(i.u1); op == vecOpBsl || op == vecOpBit || op == vecOpUmlal { + panic(fmt.Sprintf("vecOp %s must use vecRRRRewrite instead of vecRRR", op.String())) + } + fallthrough + case vecRRRRewrite: + c.Emit4Bytes(encodeVecRRR( + vecOp(i.u1), + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + vecArrangement(i.u2), + )) + case cCmpImm: + // Conditional compare (immediate) in https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en + sf := uint32((i.u2 >> 32) & 0b1) + nzcv := uint32(i.u2 & 0b1111) + cond := uint32(condFlag(i.u1)) + imm := uint32(i.rm.data & 0b11111) + rn := regNumberInEncoding[i.rn.realReg()] + c.Emit4Bytes( + sf<<31 | 0b111101001<<22 | imm<<16 | cond<<12 | 0b1<<11 | rn<<5 | nzcv, + ) + case movFromFPSR: + rt := regNumberInEncoding[i.rd.RealReg()] + c.Emit4Bytes(encodeSystemRegisterMove(rt, true)) + case movToFPSR: + rt := regNumberInEncoding[i.rn.realReg()] + c.Emit4Bytes(encodeSystemRegisterMove(rt, false)) + case atomicRmw: + c.Emit4Bytes(encodeAtomicRmw( + atomicRmwOp(i.u1), + regNumberInEncoding[i.rm.realReg()], + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rn.realReg()], + uint32(i.u2), + )) + case atomicCas: + c.Emit4Bytes(encodeAtomicCas( + regNumberInEncoding[i.rd.RealReg()], + regNumberInEncoding[i.rm.realReg()], + regNumberInEncoding[i.rn.realReg()], + uint32(i.u2), + )) + case atomicLoad: + c.Emit4Bytes(encodeAtomicLoadStore( + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rd.RealReg()], + uint32(i.u2), + 1, + )) + case atomicStore: + c.Emit4Bytes(encodeAtomicLoadStore( + regNumberInEncoding[i.rn.realReg()], + regNumberInEncoding[i.rm.realReg()], + uint32(i.u2), + 0, + )) + case dmb: + c.Emit4Bytes(encodeDMB()) + default: + panic(i.String()) + } +} + +func encodeMov64(rd, rn uint32, toIsSp, fromIsSp bool) uint32 { + if toIsSp || fromIsSp { + // This is an alias of ADD (immediate): + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOV--to-from-SP---Move-between-register-and-stack-pointer--an-alias-of-ADD--immediate-- + return encodeAddSubtractImmediate(0b100, 0, 0, rn, rd) + } else { + // This is an alias of ORR (shifted register): + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOV--register---Move--register---an-alias-of-ORR--shifted-register-- + return encodeLogicalShiftedRegister(0b101, 0, rn, 0, regNumberInEncoding[xzr], rd) + } +} + +// encodeSystemRegisterMove encodes as "System register move" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Branches--Exception-Generating-and-System-instructions?lang=en +// +// Note that currently we only supports read/write of FPSR. +func encodeSystemRegisterMove(rt uint32, fromSystem bool) uint32 { + ret := 0b11010101<<24 | 0b11011<<16 | 0b01000100<<8 | 0b001<<5 | rt + if fromSystem { + ret |= 0b1 << 21 + } + return ret +} + +// encodeVecRRR encodes as either "Advanced SIMD three *" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeVecRRR(op vecOp, rd, rn, rm uint32, arr vecArrangement) uint32 { + switch op { + case vecOpBit: + _, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b10 /* always has size 0b10 */, 0b1, q) + case vecOpBic: + if arr > vecArrangement16B { + panic("unsupported arrangement: " + arr.String()) + } + _, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b01 /* always has size 0b01 */, 0b0, q) + case vecOpBsl: + if arr > vecArrangement16B { + panic("unsupported arrangement: " + arr.String()) + } + _, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b01 /* always has size 0b01 */, 0b1, q) + case vecOpAnd: + if arr > vecArrangement16B { + panic("unsupported arrangement: " + arr.String()) + } + _, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b00 /* always has size 0b00 */, 0b0, q) + case vecOpOrr: + _, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b10 /* always has size 0b10 */, 0b0, q) + case vecOpEOR: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, size, 0b1, q) + case vecOpCmeq: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10001, size, 0b1, q) + case vecOpCmgt: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00110, size, 0b0, q) + case vecOpCmhi: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00110, size, 0b1, q) + case vecOpCmge: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00111, size, 0b0, q) + case vecOpCmhs: + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00111, size, 0b1, q) + case vecOpFcmeq: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11100, size, 0b0, q) + case vecOpFcmgt: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11100, size, 0b1, q) + case vecOpFcmge: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11100, size, 0b1, q) + case vecOpAdd: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10000, size, 0b0, q) + case vecOpSqadd: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00001, size, 0b0, q) + case vecOpUqadd: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00001, size, 0b1, q) + case vecOpAddp: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10111, size, 0b0, q) + case vecOpSqsub: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00101, size, 0b0, q) + case vecOpUqsub: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00101, size, 0b1, q) + case vecOpSub: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10000, size, 0b1, q) + case vecOpFmin: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11110, size, 0b0, q) + case vecOpSmin: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01101, size, 0b0, q) + case vecOpUmin: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01101, size, 0b1, q) + case vecOpFmax: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11110, size, 0b0, q) + case vecOpFadd: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11010, size, 0b0, q) + case vecOpFsub: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11010, size, 0b0, q) + case vecOpFmul: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11011, size, 0b1, q) + case vecOpSqrdmulh: + if arr < vecArrangement4H || arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10110, size, 0b1, q) + case vecOpFdiv: + var size, q uint32 + switch arr { + case vecArrangement4S: + size, q = 0b00, 0b1 + case vecArrangement2S: + size, q = 0b00, 0b0 + case vecArrangement2D: + size, q = 0b01, 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b11111, size, 0b1, q) + case vecOpSmax: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01100, size, 0b0, q) + case vecOpUmax: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01100, size, 0b1, q) + case vecOpUmaxp: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10100, size, 0b1, q) + case vecOpUrhadd: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00010, size, 0b1, q) + case vecOpMul: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b10011, size, 0b0, q) + case vecOpUmlal: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeDifferent(rd, rn, rm, 0b1000, size, 0b1, q) + case vecOpSshl: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01000, size, 0b0, q) + case vecOpUshl: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b01000, size, 0b1, q) + + case vecOpSmull: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, _ := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeDifferent(rd, rn, rm, 0b1100, size, 0b0, 0b0) + + case vecOpSmull2: + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, _ := arrToSizeQEncoded(arr) + return encodeAdvancedSIMDThreeDifferent(rd, rn, rm, 0b1100, size, 0b0, 0b1) + + default: + panic("TODO: " + op.String()) + } +} + +func arrToSizeQEncoded(arr vecArrangement) (size, q uint32) { + switch arr { + case vecArrangement16B: + q = 0b1 + fallthrough + case vecArrangement8B: + size = 0b00 + case vecArrangement8H: + q = 0b1 + fallthrough + case vecArrangement4H: + size = 0b01 + case vecArrangement4S: + q = 0b1 + fallthrough + case vecArrangement2S: + size = 0b10 + case vecArrangement2D: + q = 0b1 + fallthrough + case vecArrangement1D: + size = 0b11 + default: + panic("BUG") + } + return +} + +// encodeAdvancedSIMDThreeSame encodes as "Advanced SIMD three same" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeAdvancedSIMDThreeSame(rd, rn, rm, opcode, size, U, Q uint32) uint32 { + return Q<<30 | U<<29 | 0b111<<25 | size<<22 | 0b1<<21 | rm<<16 | opcode<<11 | 0b1<<10 | rn<<5 | rd +} + +// encodeAdvancedSIMDThreeDifferent encodes as "Advanced SIMD three different" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeAdvancedSIMDThreeDifferent(rd, rn, rm, opcode, size, U, Q uint32) uint32 { + return Q<<30 | U<<29 | 0b111<<25 | size<<22 | 0b1<<21 | rm<<16 | opcode<<12 | rn<<5 | rd +} + +// encodeFloatDataOneSource encodes as "Floating-point data-processing (1 source)" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en#simd-dp +func encodeFloatDataOneSource(op fpuUniOp, rd, rn uint32, dst64bit bool) uint32 { + var opcode, ptype uint32 + switch op { + case fpuUniOpCvt32To64: + opcode = 0b000101 + case fpuUniOpCvt64To32: + opcode = 0b000100 + ptype = 0b01 + case fpuUniOpNeg: + opcode = 0b000010 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpSqrt: + opcode = 0b000011 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpRoundPlus: + opcode = 0b001001 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpRoundMinus: + opcode = 0b001010 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpRoundZero: + opcode = 0b001011 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpRoundNearest: + opcode = 0b001000 + if dst64bit { + ptype = 0b01 + } + case fpuUniOpAbs: + opcode = 0b000001 + if dst64bit { + ptype = 0b01 + } + default: + panic("BUG") + } + return 0b1111<<25 | ptype<<22 | 0b1<<21 | opcode<<15 | 0b1<<14 | rn<<5 | rd +} + +// encodeCnvBetweenFloatInt encodes as "Conversion between floating-point and integer" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeCnvBetweenFloatInt(i *instruction) uint32 { + rd := regNumberInEncoding[i.rd.RealReg()] + rn := regNumberInEncoding[i.rn.realReg()] + + var opcode uint32 + var rmode uint32 + var ptype uint32 + var sf uint32 + switch i.kind { + case intToFpu: // Either UCVTF or SCVTF. + rmode = 0b00 + + signed := i.u1 == 1 + src64bit := i.u2&1 != 0 + dst64bit := i.u2&2 != 0 + if signed { + opcode = 0b010 + } else { + opcode = 0b011 + } + if src64bit { + sf = 0b1 + } + if dst64bit { + ptype = 0b01 + } else { + ptype = 0b00 + } + case fpuToInt: // Either FCVTZU or FCVTZS. + rmode = 0b11 + + signed := i.u1 == 1 + src64bit := i.u2&1 != 0 + dst64bit := i.u2&2 != 0 + + if signed { + opcode = 0b000 + } else { + opcode = 0b001 + } + if dst64bit { + sf = 0b1 + } + if src64bit { + ptype = 0b01 + } else { + ptype = 0b00 + } + } + return sf<<31 | 0b1111<<25 | ptype<<22 | 0b1<<21 | rmode<<19 | opcode<<16 | rn<<5 | rd +} + +// encodeAdr encodes a PC-relative ADR instruction. +// https://developer.arm.com/documentation/ddi0602/2022-06/Base-Instructions/ADR--Form-PC-relative-address- +func encodeAdr(rd uint32, offset uint32) uint32 { + if offset >= 1<<20 { + panic("BUG: too large adr instruction") + } + return offset&0b11<<29 | 0b1<<28 | offset&0b1111111111_1111111100<<3 | rd +} + +// encodeFpuCSel encodes as "Floating-point conditional select" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeFpuCSel(rd, rn, rm uint32, c condFlag, _64bit bool) uint32 { + var ftype uint32 + if _64bit { + ftype = 0b01 // double precision. + } + return 0b1111<<25 | ftype<<22 | 0b1<<21 | rm<<16 | uint32(c)<<12 | 0b11<<10 | rn<<5 | rd +} + +// encodeMoveToVec encodes as "Move general-purpose register to a vector element" (represented as `ins`) in +// https://developer.arm.com/documentation/dui0801/g/A64-SIMD-Vector-Instructions/MOV--vector--from-general- +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/MOV--from-general---Move-general-purpose-register-to-a-vector-element--an-alias-of-INS--general--?lang=en +func encodeMoveToVec(rd, rn uint32, arr vecArrangement, index vecIndex) uint32 { + var imm5 uint32 + switch arr { + case vecArrangementB: + imm5 |= 0b1 + imm5 |= uint32(index) << 1 + if index > 0b1111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 15", index)) + } + case vecArrangementH: + imm5 |= 0b10 + imm5 |= uint32(index) << 2 + if index > 0b111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 7", index)) + } + case vecArrangementS: + imm5 |= 0b100 + imm5 |= uint32(index) << 3 + if index > 0b11 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 3", index)) + } + case vecArrangementD: + imm5 |= 0b1000 + imm5 |= uint32(index) << 4 + if index > 0b1 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 1", index)) + } + default: + panic("Unsupported arrangement " + arr.String()) + } + + return 0b01001110000<<21 | imm5<<16 | 0b000111<<10 | rn<<5 | rd +} + +// encodeMoveToVec encodes as "Move vector element to another vector element, mov (element)" (represented as `ins`) in +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/MOV--element---Move-vector-element-to-another-vector-element--an-alias-of-INS--element--?lang=en +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/INS--element---Insert-vector-element-from-another-vector-element-?lang=en +func encodeVecMovElement(rd, rn uint32, arr vecArrangement, srcIndex, dstIndex uint32) uint32 { + var imm4, imm5 uint32 + switch arr { + case vecArrangementB: + imm5 |= 0b1 + imm5 |= srcIndex << 1 + imm4 = dstIndex + if srcIndex > 0b1111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 15", srcIndex)) + } + case vecArrangementH: + imm5 |= 0b10 + imm5 |= srcIndex << 2 + imm4 = dstIndex << 1 + if srcIndex > 0b111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 7", srcIndex)) + } + case vecArrangementS: + imm5 |= 0b100 + imm5 |= srcIndex << 3 + imm4 = dstIndex << 2 + if srcIndex > 0b11 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 3", srcIndex)) + } + case vecArrangementD: + imm5 |= 0b1000 + imm5 |= srcIndex << 4 + imm4 = dstIndex << 3 + if srcIndex > 0b1 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 1", srcIndex)) + } + default: + panic("Unsupported arrangement " + arr.String()) + } + + return 0b01101110000<<21 | imm5<<16 | imm4<<11 | 0b1<<10 | rn<<5 | rd +} + +// encodeUnconditionalBranchReg encodes as "Unconditional branch (register)" in: +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Branches--Exception-Generating-and-System-instructions?lang=en +func encodeUnconditionalBranchReg(rn uint32, link bool) uint32 { + var opc uint32 + if link { + opc = 0b0001 + } + return 0b1101011<<25 | opc<<21 | 0b11111<<16 | rn<<5 +} + +// encodeMoveFromVec encodes as "Move vector element to a general-purpose register" +// (represented as `umov` when dest is 32-bit, `umov` otherwise) in +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/UMOV--Unsigned-Move-vector-element-to-general-purpose-register-?lang=en +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/MOV--to-general---Move-vector-element-to-general-purpose-register--an-alias-of-UMOV-?lang=en +func encodeMoveFromVec(rd, rn uint32, arr vecArrangement, index vecIndex, signed bool) uint32 { + var op, imm4, q, imm5 uint32 + switch { + case arr == vecArrangementB: + imm5 |= 0b1 + imm5 |= uint32(index) << 1 + if index > 0b1111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 15", index)) + } + case arr == vecArrangementH: + imm5 |= 0b10 + imm5 |= uint32(index) << 2 + if index > 0b111 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 7", index)) + } + case arr == vecArrangementS && signed: + q = 0b1 + fallthrough + case arr == vecArrangementS: + imm5 |= 0b100 + imm5 |= uint32(index) << 3 + if index > 0b11 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 3", index)) + } + case arr == vecArrangementD && !signed: + imm5 |= 0b1000 + imm5 |= uint32(index) << 4 + q = 0b1 + if index > 0b1 { + panic(fmt.Sprintf("vector index is larger than the allowed bound: %d > 1", index)) + } + default: + panic("Unsupported arrangement " + arr.String()) + } + if signed { + op, imm4 = 0, 0b0101 + } else { + op, imm4 = 0, 0b0111 + } + return op<<29 | 0b01110000<<21 | q<<30 | imm5<<16 | imm4<<11 | 1<<10 | rn<<5 | rd +} + +// encodeVecDup encodes as "Duplicate general-purpose register to vector" DUP (general) +// (represented as `dup`) +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/DUP--general---Duplicate-general-purpose-register-to-vector-?lang=en +func encodeVecDup(rd, rn uint32, arr vecArrangement) uint32 { + var q, imm5 uint32 + switch arr { + case vecArrangement8B: + q, imm5 = 0b0, 0b1 + case vecArrangement16B: + q, imm5 = 0b1, 0b1 + case vecArrangement4H: + q, imm5 = 0b0, 0b10 + case vecArrangement8H: + q, imm5 = 0b1, 0b10 + case vecArrangement2S: + q, imm5 = 0b0, 0b100 + case vecArrangement4S: + q, imm5 = 0b1, 0b100 + case vecArrangement2D: + q, imm5 = 0b1, 0b1000 + default: + panic("Unsupported arrangement " + arr.String()) + } + return q<<30 | 0b001110000<<21 | imm5<<16 | 0b000011<<10 | rn<<5 | rd +} + +// encodeVecDup encodes as "Duplicate vector element to vector or scalar" DUP (element). +// (represented as `dup`) +// https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/DUP--element---Duplicate-vector-element-to-vector-or-scalar- +func encodeVecDupElement(rd, rn uint32, arr vecArrangement, srcIndex vecIndex) uint32 { + var q, imm5 uint32 + q = 0b1 + switch arr { + case vecArrangementB: + imm5 |= 0b1 + imm5 |= uint32(srcIndex) << 1 + case vecArrangementH: + imm5 |= 0b10 + imm5 |= uint32(srcIndex) << 2 + case vecArrangementS: + imm5 |= 0b100 + imm5 |= uint32(srcIndex) << 3 + case vecArrangementD: + imm5 |= 0b1000 + imm5 |= uint32(srcIndex) << 4 + default: + panic("unsupported arrangement" + arr.String()) + } + + return q<<30 | 0b001110000<<21 | imm5<<16 | 0b1<<10 | rn<<5 | rd +} + +// encodeVecExtract encodes as "Advanced SIMD extract." +// Currently only `ext` is defined. +// https://developer.arm.com/documentation/ddi0602/2023-06/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en#simd-dp +// https://developer.arm.com/documentation/ddi0602/2023-06/SIMD-FP-Instructions/EXT--Extract-vector-from-pair-of-vectors-?lang=en +func encodeVecExtract(rd, rn, rm uint32, arr vecArrangement, index uint32) uint32 { + var q, imm4 uint32 + switch arr { + case vecArrangement8B: + q, imm4 = 0, 0b0111&uint32(index) + case vecArrangement16B: + q, imm4 = 1, 0b1111&uint32(index) + default: + panic("Unsupported arrangement " + arr.String()) + } + return q<<30 | 0b101110000<<21 | rm<<16 | imm4<<11 | rn<<5 | rd +} + +// encodeVecPermute encodes as "Advanced SIMD permute." +// https://developer.arm.com/documentation/ddi0602/2023-06/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en#simd-dp +func encodeVecPermute(op vecOp, rd, rn, rm uint32, arr vecArrangement) uint32 { + var q, size, opcode uint32 + switch op { + case vecOpZip1: + opcode = 0b011 + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + default: + panic("TODO: " + op.String()) + } + return q<<30 | 0b001110<<24 | size<<22 | rm<<16 | opcode<<12 | 0b10<<10 | rn<<5 | rd +} + +// encodeConditionalSelect encodes as "Conditional select" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en#condsel +func encodeConditionalSelect(kind instructionKind, rd, rn, rm uint32, c condFlag, _64bit bool) uint32 { + if kind != cSel { + panic("TODO: support other conditional select") + } + + ret := 0b110101<<23 | rm<<16 | uint32(c)<<12 | rn<<5 | rd + if _64bit { + ret |= 0b1 << 31 + } + return ret +} + +const dummyInstruction uint32 = 0x14000000 // "b 0" + +// encodeLoadFpuConst32 encodes the following three instructions: +// +// ldr s8, #8 ;; literal load of data.f32 +// b 8 ;; skip the data +// data.f32 xxxxxxx +func encodeLoadFpuConst32(c backend.Compiler, rd uint32, rawF32 uint64) { + c.Emit4Bytes( + // https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/LDR--literal--SIMD-FP---Load-SIMD-FP-Register--PC-relative-literal--?lang=en + 0b111<<26 | (0x8/4)<<5 | rd, + ) + c.Emit4Bytes(encodeUnconditionalBranch(false, 8)) // b 8 + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + // Inlined data.f32 cannot be disassembled, so we add a dummy instruction here. + c.Emit4Bytes(dummyInstruction) + } else { + c.Emit4Bytes(uint32(rawF32)) // data.f32 xxxxxxx + } +} + +// encodeLoadFpuConst64 encodes the following three instructions: +// +// ldr d8, #8 ;; literal load of data.f64 +// b 12 ;; skip the data +// data.f64 xxxxxxx +func encodeLoadFpuConst64(c backend.Compiler, rd uint32, rawF64 uint64) { + c.Emit4Bytes( + // https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/LDR--literal--SIMD-FP---Load-SIMD-FP-Register--PC-relative-literal--?lang=en + 0b1<<30 | 0b111<<26 | (0x8/4)<<5 | rd, + ) + c.Emit4Bytes(encodeUnconditionalBranch(false, 12)) // b 12 + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + // Inlined data.f64 cannot be disassembled, so we add dummy instructions here. + c.Emit4Bytes(dummyInstruction) + c.Emit4Bytes(dummyInstruction) + } else { + // data.f64 xxxxxxx + c.Emit4Bytes(uint32(rawF64)) + c.Emit4Bytes(uint32(rawF64 >> 32)) + } +} + +// encodeLoadFpuConst128 encodes the following three instructions: +// +// ldr v8, #8 ;; literal load of data.f64 +// b 20 ;; skip the data +// data.v128 xxxxxxx +func encodeLoadFpuConst128(c backend.Compiler, rd uint32, lo, hi uint64) { + c.Emit4Bytes( + // https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/LDR--literal--SIMD-FP---Load-SIMD-FP-Register--PC-relative-literal--?lang=en + 0b1<<31 | 0b111<<26 | (0x8/4)<<5 | rd, + ) + c.Emit4Bytes(encodeUnconditionalBranch(false, 20)) // b 20 + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + // Inlined data.v128 cannot be disassembled, so we add dummy instructions here. + c.Emit4Bytes(dummyInstruction) + c.Emit4Bytes(dummyInstruction) + c.Emit4Bytes(dummyInstruction) + c.Emit4Bytes(dummyInstruction) + } else { + // data.v128 xxxxxxx + c.Emit4Bytes(uint32(lo)) + c.Emit4Bytes(uint32(lo >> 32)) + c.Emit4Bytes(uint32(hi)) + c.Emit4Bytes(uint32(hi >> 32)) + } +} + +// encodeAluRRRR encodes as Data-processing (3 source) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en +func encodeAluRRRR(op aluOp, rd, rn, rm, ra, _64bit uint32) uint32 { + var oO, op31 uint32 + switch op { + case aluOpMAdd: + op31, oO = 0b000, 0b0 + case aluOpMSub: + op31, oO = 0b000, 0b1 + default: + panic("TODO/BUG") + } + return _64bit<<31 | 0b11011<<24 | op31<<21 | rm<<16 | oO<<15 | ra<<10 | rn<<5 | rd +} + +// encodeBitRR encodes as Data-processing (1 source) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en +func encodeBitRR(op bitOp, rd, rn, _64bit uint32) uint32 { + var opcode2, opcode uint32 + switch op { + case bitOpRbit: + opcode2, opcode = 0b00000, 0b000000 + case bitOpClz: + opcode2, opcode = 0b00000, 0b000100 + default: + panic("TODO/BUG") + } + return _64bit<<31 | 0b1_0_11010110<<21 | opcode2<<15 | opcode<<10 | rn<<5 | rd +} + +func encodeAsMov32(rn, rd uint32) uint32 { + // This is an alias of ORR (shifted register): + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOV--register---Move--register---an-alias-of-ORR--shifted-register-- + return encodeLogicalShiftedRegister(0b001, 0, rn, 0, regNumberInEncoding[xzr], rd) +} + +// encodeExtend encodes extension instructions. +func encodeExtend(signed bool, from, to byte, rd, rn uint32) uint32 { + // UTXB: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/UXTB--Unsigned-Extend-Byte--an-alias-of-UBFM-?lang=en + // UTXH: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/UXTH--Unsigned-Extend-Halfword--an-alias-of-UBFM-?lang=en + // STXB: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/SXTB--Signed-Extend-Byte--an-alias-of-SBFM- + // STXH: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/SXTH--Sign-Extend-Halfword--an-alias-of-SBFM- + // STXW: https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/SXTW--Sign-Extend-Word--an-alias-of-SBFM- + var _31to10 uint32 + switch { + case !signed && from == 8 && to == 32: + // 32-bit UXTB + _31to10 = 0b0101001100000000000111 + case !signed && from == 16 && to == 32: + // 32-bit UXTH + _31to10 = 0b0101001100000000001111 + case !signed && from == 8 && to == 64: + // 64-bit UXTB + _31to10 = 0b0101001100000000000111 + case !signed && from == 16 && to == 64: + // 64-bit UXTH + _31to10 = 0b0101001100000000001111 + case !signed && from == 32 && to == 64: + return encodeAsMov32(rn, rd) + case signed && from == 8 && to == 32: + // 32-bit SXTB + _31to10 = 0b0001001100000000000111 + case signed && from == 16 && to == 32: + // 32-bit SXTH + _31to10 = 0b0001001100000000001111 + case signed && from == 8 && to == 64: + // 64-bit SXTB + _31to10 = 0b1001001101000000000111 + case signed && from == 16 && to == 64: + // 64-bit SXTH + _31to10 = 0b1001001101000000001111 + case signed && from == 32 && to == 64: + // SXTW + _31to10 = 0b1001001101000000011111 + default: + panic("BUG") + } + return _31to10<<10 | rn<<5 | rd +} + +func encodeLoadOrStore(kind instructionKind, rt uint32, amode addressMode) uint32 { + var _22to31 uint32 + var bits int64 + switch kind { + case uLoad8: + _22to31 = 0b0011100001 + bits = 8 + case sLoad8: + _22to31 = 0b0011100010 + bits = 8 + case uLoad16: + _22to31 = 0b0111100001 + bits = 16 + case sLoad16: + _22to31 = 0b0111100010 + bits = 16 + case uLoad32: + _22to31 = 0b1011100001 + bits = 32 + case sLoad32: + _22to31 = 0b1011100010 + bits = 32 + case uLoad64: + _22to31 = 0b1111100001 + bits = 64 + case fpuLoad32: + _22to31 = 0b1011110001 + bits = 32 + case fpuLoad64: + _22to31 = 0b1111110001 + bits = 64 + case fpuLoad128: + _22to31 = 0b0011110011 + bits = 128 + case store8: + _22to31 = 0b0011100000 + bits = 8 + case store16: + _22to31 = 0b0111100000 + bits = 16 + case store32: + _22to31 = 0b1011100000 + bits = 32 + case store64: + _22to31 = 0b1111100000 + bits = 64 + case fpuStore32: + _22to31 = 0b1011110000 + bits = 32 + case fpuStore64: + _22to31 = 0b1111110000 + bits = 64 + case fpuStore128: + _22to31 = 0b0011110010 + bits = 128 + default: + panic("BUG") + } + + switch amode.kind { + case addressModeKindRegScaledExtended: + return encodeLoadOrStoreExtended(_22to31, + regNumberInEncoding[amode.rn.RealReg()], + regNumberInEncoding[amode.rm.RealReg()], + rt, true, amode.extOp) + case addressModeKindRegScaled: + return encodeLoadOrStoreExtended(_22to31, + regNumberInEncoding[amode.rn.RealReg()], regNumberInEncoding[amode.rm.RealReg()], + rt, true, extendOpNone) + case addressModeKindRegExtended: + return encodeLoadOrStoreExtended(_22to31, + regNumberInEncoding[amode.rn.RealReg()], regNumberInEncoding[amode.rm.RealReg()], + rt, false, amode.extOp) + case addressModeKindRegReg: + return encodeLoadOrStoreExtended(_22to31, + regNumberInEncoding[amode.rn.RealReg()], regNumberInEncoding[amode.rm.RealReg()], + rt, false, extendOpNone) + case addressModeKindRegSignedImm9: + // e.g. https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDUR--Load-Register--unscaled-- + return encodeLoadOrStoreSIMM9(_22to31, 0b00 /* unscaled */, regNumberInEncoding[amode.rn.RealReg()], rt, amode.imm) + case addressModeKindPostIndex: + return encodeLoadOrStoreSIMM9(_22to31, 0b01 /* post index */, regNumberInEncoding[amode.rn.RealReg()], rt, amode.imm) + case addressModeKindPreIndex: + return encodeLoadOrStoreSIMM9(_22to31, 0b11 /* pre index */, regNumberInEncoding[amode.rn.RealReg()], rt, amode.imm) + case addressModeKindRegUnsignedImm12: + // "unsigned immediate" in https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Loads-and-Stores?lang=en + rn := regNumberInEncoding[amode.rn.RealReg()] + imm := amode.imm + div := bits / 8 + if imm != 0 && !offsetFitsInAddressModeKindRegUnsignedImm12(byte(bits), imm) { + panic("BUG") + } + imm /= div + return _22to31<<22 | 0b1<<24 | uint32(imm&0b111111111111)<<10 | rn<<5 | rt + default: + panic("BUG") + } +} + +// encodeVecLoad1R encodes as Load one single-element structure and Replicate to all lanes (of one register) in +// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/LD1R--Load-one-single-element-structure-and-Replicate-to-all-lanes--of-one-register--?lang=en#sa_imm +func encodeVecLoad1R(rt, rn uint32, arr vecArrangement) uint32 { + size, q := arrToSizeQEncoded(arr) + return q<<30 | 0b001101010000001100<<12 | size<<10 | rn<<5 | rt +} + +// encodeAluBitmaskImmediate encodes as Logical (immediate) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en +func encodeAluBitmaskImmediate(op aluOp, rd, rn uint32, imm uint64, _64bit bool) uint32 { + var _31to23 uint32 + switch op { + case aluOpAnd: + _31to23 = 0b00_100100 + case aluOpOrr: + _31to23 = 0b01_100100 + case aluOpEor: + _31to23 = 0b10_100100 + case aluOpAnds: + _31to23 = 0b11_100100 + default: + panic("BUG") + } + if _64bit { + _31to23 |= 0b1 << 8 + } + immr, imms, N := bitmaskImmediate(imm, _64bit) + return _31to23<<23 | uint32(N)<<22 | uint32(immr)<<16 | uint32(imms)<<10 | rn<<5 | rd +} + +func bitmaskImmediate(c uint64, is64bit bool) (immr, imms, N byte) { + var size uint32 + switch { + case c != c>>32|c<<32: + size = 64 + case c != c>>16|c<<48: + size = 32 + c = uint64(int32(c)) + case c != c>>8|c<<56: + size = 16 + c = uint64(int16(c)) + case c != c>>4|c<<60: + size = 8 + c = uint64(int8(c)) + case c != c>>2|c<<62: + size = 4 + c = uint64(int64(c<<60) >> 60) + default: + size = 2 + c = uint64(int64(c<<62) >> 62) + } + + neg := false + if int64(c) < 0 { + c = ^c + neg = true + } + + onesSize, nonZeroPos := getOnesSequenceSize(c) + if neg { + nonZeroPos = onesSize + nonZeroPos + onesSize = size - onesSize + } + + var mode byte = 32 + if is64bit && size == 64 { + N, mode = 0b1, 64 + } + + immr = byte((size - nonZeroPos) & (size - 1) & uint32(mode-1)) + imms = byte((onesSize - 1) | 63&^(size<<1-1)) + return +} + +func getOnesSequenceSize(x uint64) (size, nonZeroPos uint32) { + // Take 0b00111000 for example: + y := getLowestBit(x) // = 0b0000100 + nonZeroPos = setBitPos(y) // = 2 + size = setBitPos(x+y) - nonZeroPos // = setBitPos(0b0100000) - 2 = 5 - 2 = 3 + return +} + +func setBitPos(x uint64) (ret uint32) { + for ; ; ret++ { + if x == 0b1 { + break + } + x = x >> 1 + } + return +} + +// encodeLoadOrStoreExtended encodes store/load instruction as "extended register offset" in Load/store register (register offset): +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Loads-and-Stores?lang=en +func encodeLoadOrStoreExtended(_22to32 uint32, rn, rm, rt uint32, scaled bool, extOp extendOp) uint32 { + var option uint32 + switch extOp { + case extendOpUXTW: + option = 0b010 + case extendOpSXTW: + option = 0b110 + case extendOpNone: + option = 0b111 + default: + panic("BUG") + } + var s uint32 + if scaled { + s = 0b1 + } + return _22to32<<22 | 0b1<<21 | rm<<16 | option<<13 | s<<12 | 0b10<<10 | rn<<5 | rt +} + +// encodeLoadOrStoreSIMM9 encodes store/load instruction as one of post-index, pre-index or unscaled immediate as in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Loads-and-Stores?lang=en +func encodeLoadOrStoreSIMM9(_22to32, _1011 uint32, rn, rt uint32, imm9 int64) uint32 { + return _22to32<<22 | (uint32(imm9)&0b111111111)<<12 | _1011<<10 | rn<<5 | rt +} + +// encodeFpuRRR encodes as single or double precision (depending on `_64bit`) of Floating-point data-processing (2 source) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeFpuRRR(op fpuBinOp, rd, rn, rm uint32, _64bit bool) (ret uint32) { + // https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/ADD--vector--Add-vectors--scalar--floating-point-and-integer- + var opcode uint32 + switch op { + case fpuBinOpAdd: + opcode = 0b0010 + case fpuBinOpSub: + opcode = 0b0011 + case fpuBinOpMul: + opcode = 0b0000 + case fpuBinOpDiv: + opcode = 0b0001 + case fpuBinOpMax: + opcode = 0b0100 + case fpuBinOpMin: + opcode = 0b0101 + default: + panic("BUG") + } + var ptype uint32 + if _64bit { + ptype = 0b01 + } + return 0b1111<<25 | ptype<<22 | 0b1<<21 | rm<<16 | opcode<<12 | 0b1<<11 | rn<<5 | rd +} + +// encodeAluRRImm12 encodes as Add/subtract (immediate) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en +func encodeAluRRImm12(op aluOp, rd, rn uint32, imm12 uint16, shiftBit byte, _64bit bool) uint32 { + var _31to24 uint32 + switch op { + case aluOpAdd: + _31to24 = 0b00_10001 + case aluOpAddS: + _31to24 = 0b01_10001 + case aluOpSub: + _31to24 = 0b10_10001 + case aluOpSubS: + _31to24 = 0b11_10001 + default: + panic("BUG") + } + if _64bit { + _31to24 |= 0b1 << 7 + } + return _31to24<<24 | uint32(shiftBit)<<22 | uint32(imm12&0b111111111111)<<10 | rn<<5 | rd +} + +// encodeAluRRR encodes as Data Processing (shifted register), depending on aluOp. +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en#addsub_shift +func encodeAluRRRShift(op aluOp, rd, rn, rm, amount uint32, shiftOp shiftOp, _64bit bool) uint32 { + var _31to24 uint32 + var opc, n uint32 + switch op { + case aluOpAdd: + _31to24 = 0b00001011 + case aluOpAddS: + _31to24 = 0b00101011 + case aluOpSub: + _31to24 = 0b01001011 + case aluOpSubS: + _31to24 = 0b01101011 + case aluOpAnd, aluOpOrr, aluOpEor, aluOpAnds: + // "Logical (shifted register)". + switch op { + case aluOpAnd: + // all zeros + case aluOpOrr: + opc = 0b01 + case aluOpEor: + opc = 0b10 + case aluOpAnds: + opc = 0b11 + } + _31to24 = 0b000_01010 + default: + panic(op.String()) + } + + if _64bit { + _31to24 |= 0b1 << 7 + } + + var shift uint32 + switch shiftOp { + case shiftOpLSL: + shift = 0b00 + case shiftOpLSR: + shift = 0b01 + case shiftOpASR: + shift = 0b10 + default: + panic(shiftOp.String()) + } + return opc<<29 | n<<21 | _31to24<<24 | shift<<22 | rm<<16 | (amount << 10) | (rn << 5) | rd +} + +// "Add/subtract (extended register)" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en#addsub_ext +func encodeAluRRRExtend(ao aluOp, rd, rn, rm uint32, extOp extendOp, to byte) uint32 { + var s, op uint32 + switch ao { + case aluOpAdd: + op = 0b0 + case aluOpAddS: + op, s = 0b0, 0b1 + case aluOpSub: + op = 0b1 + case aluOpSubS: + op, s = 0b1, 0b1 + default: + panic("BUG: extended register operand can be used only for add/sub") + } + + var sf uint32 + if to == 64 { + sf = 0b1 + } + + var option uint32 + switch extOp { + case extendOpUXTB: + option = 0b000 + case extendOpUXTH: + option = 0b001 + case extendOpUXTW: + option = 0b010 + case extendOpSXTB: + option = 0b100 + case extendOpSXTH: + option = 0b101 + case extendOpSXTW: + option = 0b110 + case extendOpSXTX, extendOpUXTX: + panic(fmt.Sprintf("%s is essentially noop, and should be handled much earlier than encoding", extOp.String())) + } + return sf<<31 | op<<30 | s<<29 | 0b1011001<<21 | rm<<16 | option<<13 | rn<<5 | rd +} + +// encodeAluRRR encodes as Data Processing (register), depending on aluOp. +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en +func encodeAluRRR(op aluOp, rd, rn, rm uint32, _64bit, isRnSp bool) uint32 { + var _31to21, _15to10 uint32 + switch op { + case aluOpAdd: + if isRnSp { + // "Extended register" with UXTW. + _31to21 = 0b00001011_001 + _15to10 = 0b011000 + } else { + // "Shifted register" with shift = 0 + _31to21 = 0b00001011_000 + } + case aluOpAddS: + if isRnSp { + panic("TODO") + } + // "Shifted register" with shift = 0 + _31to21 = 0b00101011_000 + case aluOpSub: + if isRnSp { + // "Extended register" with UXTW. + _31to21 = 0b01001011_001 + _15to10 = 0b011000 + } else { + // "Shifted register" with shift = 0 + _31to21 = 0b01001011_000 + } + case aluOpSubS: + if isRnSp { + panic("TODO") + } + // "Shifted register" with shift = 0 + _31to21 = 0b01101011_000 + case aluOpAnd, aluOpOrr, aluOpOrn, aluOpEor, aluOpAnds: + // "Logical (shifted register)". + var opc, n uint32 + switch op { + case aluOpAnd: + // all zeros + case aluOpOrr: + opc = 0b01 + case aluOpOrn: + opc = 0b01 + n = 1 + case aluOpEor: + opc = 0b10 + case aluOpAnds: + opc = 0b11 + } + _31to21 = 0b000_01010_000 | opc<<8 | n + case aluOpLsl, aluOpAsr, aluOpLsr, aluOpRotR: + // "Data-processing (2 source)". + _31to21 = 0b00011010_110 + switch op { + case aluOpLsl: + _15to10 = 0b001000 + case aluOpLsr: + _15to10 = 0b001001 + case aluOpAsr: + _15to10 = 0b001010 + case aluOpRotR: + _15to10 = 0b001011 + } + case aluOpSDiv: + // "Data-processing (2 source)". + _31to21 = 0b11010110 + _15to10 = 0b000011 + case aluOpUDiv: + // "Data-processing (2 source)". + _31to21 = 0b11010110 + _15to10 = 0b000010 + default: + panic(op.String()) + } + if _64bit { + _31to21 |= 0b1 << 10 + } + return _31to21<<21 | rm<<16 | (_15to10 << 10) | (rn << 5) | rd +} + +// encodeLogicalShiftedRegister encodes as Logical (shifted register) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Register?lang=en +func encodeLogicalShiftedRegister(sf_opc uint32, shift_N uint32, rm uint32, imm6 uint32, rn, rd uint32) (ret uint32) { + ret = sf_opc << 29 + ret |= 0b01010 << 24 + ret |= shift_N << 21 + ret |= rm << 16 + ret |= imm6 << 10 + ret |= rn << 5 + ret |= rd + return +} + +// encodeAddSubtractImmediate encodes as Add/subtract (immediate) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en +func encodeAddSubtractImmediate(sf_op_s uint32, sh uint32, imm12 uint32, rn, rd uint32) (ret uint32) { + ret = sf_op_s << 29 + ret |= 0b100010 << 23 + ret |= sh << 22 + ret |= imm12 << 10 + ret |= rn << 5 + ret |= rd + return +} + +// encodePreOrPostIndexLoadStorePair64 encodes as Load/store pair (pre/post-indexed) in +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDP--Load-Pair-of-Registers- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/STP--Store-Pair-of-Registers- +func encodePreOrPostIndexLoadStorePair64(pre bool, load bool, rn, rt, rt2 uint32, imm7 int64) (ret uint32) { + if imm7%8 != 0 { + panic("imm7 for pair load/store must be a multiple of 8") + } + imm7 /= 8 + ret = rt + ret |= rn << 5 + ret |= rt2 << 10 + ret |= (uint32(imm7) & 0b1111111) << 15 + if load { + ret |= 0b1 << 22 + } + ret |= 0b101010001 << 23 + if pre { + ret |= 0b1 << 24 + } + return +} + +// encodeUnconditionalBranch encodes as B or BL instructions: +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/B--Branch- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/BL--Branch-with-Link- +func encodeUnconditionalBranch(link bool, imm26 int64) (ret uint32) { + if imm26%4 != 0 { + panic("imm26 for branch must be a multiple of 4") + } + imm26 /= 4 + ret = uint32(imm26 & 0b11_11111111_11111111_11111111) + ret |= 0b101 << 26 + if link { + ret |= 0b1 << 31 + } + return +} + +// encodeCBZCBNZ encodes as either CBZ or CBNZ: +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/CBZ--Compare-and-Branch-on-Zero- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/CBNZ--Compare-and-Branch-on-Nonzero- +func encodeCBZCBNZ(rt uint32, nz bool, imm19 uint32, _64bit bool) (ret uint32) { + ret = rt + ret |= imm19 << 5 + if nz { + ret |= 1 << 24 + } + ret |= 0b11010 << 25 + if _64bit { + ret |= 1 << 31 + } + return +} + +// encodeMoveWideImmediate encodes as either MOVZ, MOVN or MOVK, as Move wide (immediate) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en +// +// "shift" must have been divided by 16 at this point. +func encodeMoveWideImmediate(opc uint32, rd uint32, imm uint64, shift, _64bit uint32) (ret uint32) { + ret = rd + ret |= uint32(imm&0xffff) << 5 + ret |= (shift) << 21 + ret |= 0b100101 << 23 + ret |= opc << 29 + ret |= _64bit << 31 + return +} + +// encodeAluRRImm encodes as "Bitfield" in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en#log_imm +func encodeAluRRImm(op aluOp, rd, rn, amount, _64bit uint32) uint32 { + var opc uint32 + var immr, imms uint32 + switch op { + case aluOpLsl: + // LSL (immediate) is an alias for UBFM. + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/UBFM--Unsigned-Bitfield-Move-?lang=en + opc = 0b10 + if amount == 0 { + // This can be encoded as NOP, but we don't do it for consistency: lsr xn, xm, #0 + immr = 0 + if _64bit == 1 { + imms = 0b111111 + } else { + imms = 0b11111 + } + } else { + if _64bit == 1 { + immr = 64 - amount + } else { + immr = (32 - amount) & 0b11111 + } + imms = immr - 1 + } + case aluOpLsr: + // LSR (immediate) is an alias for UBFM. + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LSR--immediate---Logical-Shift-Right--immediate---an-alias-of-UBFM-?lang=en + opc = 0b10 + imms, immr = 0b011111|_64bit<<5, amount + case aluOpAsr: + // ASR (immediate) is an alias for SBFM. + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/SBFM--Signed-Bitfield-Move-?lang=en + opc = 0b00 + imms, immr = 0b011111|_64bit<<5, amount + default: + panic(op.String()) + } + return _64bit<<31 | opc<<29 | 0b100110<<23 | _64bit<<22 | immr<<16 | imms<<10 | rn<<5 | rd +} + +// encodeVecLanes encodes as Data Processing (Advanced SIMD across lanes) depending on vecOp in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeVecLanes(op vecOp, rd uint32, rn uint32, arr vecArrangement) uint32 { + var u, q, size, opcode uint32 + switch arr { + case vecArrangement8B: + q, size = 0b0, 0b00 + case vecArrangement16B: + q, size = 0b1, 0b00 + case vecArrangement4H: + q, size = 0, 0b01 + case vecArrangement8H: + q, size = 1, 0b01 + case vecArrangement4S: + q, size = 1, 0b10 + default: + panic("unsupported arrangement: " + arr.String()) + } + switch op { + case vecOpUaddlv: + u, opcode = 1, 0b00011 + case vecOpUminv: + u, opcode = 1, 0b11010 + case vecOpAddv: + u, opcode = 0, 0b11011 + default: + panic("unsupported or illegal vecOp: " + op.String()) + } + return q<<30 | u<<29 | 0b1110<<24 | size<<22 | 0b11000<<17 | opcode<<12 | 0b10<<10 | rn<<5 | rd +} + +// encodeVecLanes encodes as Data Processing (Advanced SIMD scalar shift by immediate) depending on vecOp in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en +func encodeVecShiftImm(op vecOp, rd uint32, rn, amount uint32, arr vecArrangement) uint32 { + var u, q, immh, immb, opcode uint32 + switch op { + case vecOpSshll: + u, opcode = 0b0, 0b10100 + case vecOpUshll: + u, opcode = 0b1, 0b10100 + case vecOpSshr: + u, opcode = 0, 0b00000 + default: + panic("unsupported or illegal vecOp: " + op.String()) + } + switch arr { + case vecArrangement16B: + q = 0b1 + fallthrough + case vecArrangement8B: + immh = 0b0001 + immb = 8 - uint32(amount&0b111) + case vecArrangement8H: + q = 0b1 + fallthrough + case vecArrangement4H: + v := 16 - uint32(amount&0b1111) + immb = v & 0b111 + immh = 0b0010 | (v >> 3) + case vecArrangement4S: + q = 0b1 + fallthrough + case vecArrangement2S: + v := 32 - uint32(amount&0b11111) + immb = v & 0b111 + immh = 0b0100 | (v >> 3) + case vecArrangement2D: + q = 0b1 + v := 64 - uint32(amount&0b111111) + immb = v & 0b111 + immh = 0b1000 | (v >> 3) + default: + panic("unsupported arrangement: " + arr.String()) + } + return q<<30 | u<<29 | 0b011110<<23 | immh<<19 | immb<<16 | 0b000001<<10 | opcode<<11 | 0b1<<10 | rn<<5 | rd +} + +// encodeVecTbl encodes as Data Processing (Advanced SIMD table lookup) in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en#simd-dp +// +// Note: tblOp may encode tbl1, tbl2... in the future. Currently, it is ignored. +func encodeVecTbl(nregs, rd, rn, rm uint32, arr vecArrangement) uint32 { + var q, op2, len, op uint32 + + switch nregs { + case 1: + // tbl: single-register + len = 0b00 + case 2: + // tbl2: 2-register table + len = 0b01 + default: + panic(fmt.Sprintf("unsupported number or registers %d", nregs)) + } + switch arr { + case vecArrangement8B: + q = 0b0 + case vecArrangement16B: + q = 0b1 + default: + panic("unsupported arrangement: " + arr.String()) + } + + return q<<30 | 0b001110<<24 | op2<<22 | rm<<16 | len<<13 | op<<12 | rn<<5 | rd +} + +// encodeVecMisc encodes as Data Processing (Advanced SIMD two-register miscellaneous) depending on vecOp in +// https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Scalar-Floating-Point-and-Advanced-SIMD?lang=en#simd-dp +func encodeAdvancedSIMDTwoMisc(op vecOp, rd, rn uint32, arr vecArrangement) uint32 { + var q, u, size, opcode uint32 + switch op { + case vecOpCnt: + opcode = 0b00101 + switch arr { + case vecArrangement8B: + q, size = 0b0, 0b00 + case vecArrangement16B: + q, size = 0b1, 0b00 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpCmeq0: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b01001 + size, q = arrToSizeQEncoded(arr) + case vecOpNot: + u = 1 + opcode = 0b00101 + switch arr { + case vecArrangement8B: + q, size = 0b0, 0b00 + case vecArrangement16B: + q, size = 0b1, 0b00 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpAbs: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b01011 + u = 0b0 + size, q = arrToSizeQEncoded(arr) + case vecOpNeg: + if arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b01011 + u = 0b1 + size, q = arrToSizeQEncoded(arr) + case vecOpFabs: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b01111 + u = 0b0 + size, q = arrToSizeQEncoded(arr) + case vecOpFneg: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b01111 + u = 0b1 + size, q = arrToSizeQEncoded(arr) + case vecOpFrintm: + u = 0b0 + opcode = 0b11001 + switch arr { + case vecArrangement2S: + q, size = 0b0, 0b00 + case vecArrangement4S: + q, size = 0b1, 0b00 + case vecArrangement2D: + q, size = 0b1, 0b01 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpFrintn: + u = 0b0 + opcode = 0b11000 + switch arr { + case vecArrangement2S: + q, size = 0b0, 0b00 + case vecArrangement4S: + q, size = 0b1, 0b00 + case vecArrangement2D: + q, size = 0b1, 0b01 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpFrintp: + u = 0b0 + opcode = 0b11000 + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + case vecOpFrintz: + u = 0b0 + opcode = 0b11001 + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + case vecOpFsqrt: + if arr < vecArrangement2S || arr == vecArrangement1D { + panic("unsupported arrangement: " + arr.String()) + } + opcode = 0b11111 + u = 0b1 + size, q = arrToSizeQEncoded(arr) + case vecOpFcvtl: + opcode = 0b10111 + u = 0b0 + switch arr { + case vecArrangement2S: + size, q = 0b01, 0b0 + case vecArrangement4H: + size, q = 0b00, 0b0 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpFcvtn: + opcode = 0b10110 + u = 0b0 + switch arr { + case vecArrangement2S: + size, q = 0b01, 0b0 + case vecArrangement4H: + size, q = 0b00, 0b0 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpFcvtzs: + opcode = 0b11011 + u = 0b0 + switch arr { + case vecArrangement2S: + q, size = 0b0, 0b10 + case vecArrangement4S: + q, size = 0b1, 0b10 + case vecArrangement2D: + q, size = 0b1, 0b11 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpFcvtzu: + opcode = 0b11011 + u = 0b1 + switch arr { + case vecArrangement2S: + q, size = 0b0, 0b10 + case vecArrangement4S: + q, size = 0b1, 0b10 + case vecArrangement2D: + q, size = 0b1, 0b11 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpScvtf: + opcode = 0b11101 + u = 0b0 + switch arr { + case vecArrangement4S: + q, size = 0b1, 0b00 + case vecArrangement2S: + q, size = 0b0, 0b00 + case vecArrangement2D: + q, size = 0b1, 0b01 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpUcvtf: + opcode = 0b11101 + u = 0b1 + switch arr { + case vecArrangement4S: + q, size = 0b1, 0b00 + case vecArrangement2S: + q, size = 0b0, 0b00 + case vecArrangement2D: + q, size = 0b1, 0b01 + default: + panic("unsupported arrangement: " + arr.String()) + } + case vecOpSqxtn: + // When q == 1 it encodes sqxtn2 (operates on upper 64 bits). + opcode = 0b10100 + u = 0b0 + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + case vecOpUqxtn: + // When q == 1 it encodes uqxtn2 (operates on upper 64 bits). + opcode = 0b10100 + u = 0b1 + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + case vecOpSqxtun: + // When q == 1 it encodes sqxtun2 (operates on upper 64 bits). + opcode = 0b10010 // 0b10100 + u = 0b1 + if arr > vecArrangement4S { + panic("unsupported arrangement: " + arr.String()) + } + size, q = arrToSizeQEncoded(arr) + case vecOpRev64: + opcode = 0b00000 + size, q = arrToSizeQEncoded(arr) + case vecOpXtn: + u = 0b0 + opcode = 0b10010 + size, q = arrToSizeQEncoded(arr) + case vecOpShll: + u = 0b1 + opcode = 0b10011 + switch arr { + case vecArrangement8B: + q, size = 0b0, 0b00 + case vecArrangement4H: + q, size = 0b0, 0b01 + case vecArrangement2S: + q, size = 0b0, 0b10 + default: + panic("unsupported arrangement: " + arr.String()) + } + default: + panic("unsupported or illegal vecOp: " + op.String()) + } + return q<<30 | u<<29 | 0b01110<<24 | size<<22 | 0b10000<<17 | opcode<<12 | 0b10<<10 | rn<<5 | rd +} + +// brTableSequenceOffsetTableBegin is the offset inside the brTableSequence where the table begins after 4 instructions +const brTableSequenceOffsetTableBegin = 16 + +func encodeBrTableSequence(c backend.Compiler, index regalloc.VReg, targets []uint32) { + tmpRegNumber := regNumberInEncoding[tmp] + indexNumber := regNumberInEncoding[index.RealReg()] + + // adr tmpReg, PC+16 (PC+16 is the address of the first label offset) + // ldrsw index, [tmpReg, index, UXTW 2] ;; index = int64(*(tmpReg + index*8)) + // add tmpReg, tmpReg, index + // br tmpReg + // [offset_to_l1, offset_to_l2, ..., offset_to_lN] + c.Emit4Bytes(encodeAdr(tmpRegNumber, 16)) + c.Emit4Bytes(encodeLoadOrStore(sLoad32, indexNumber, + addressMode{kind: addressModeKindRegScaledExtended, rn: tmpRegVReg, rm: index, extOp: extendOpUXTW}, + )) + c.Emit4Bytes(encodeAluRRR(aluOpAdd, tmpRegNumber, tmpRegNumber, indexNumber, true, false)) + c.Emit4Bytes(encodeUnconditionalBranchReg(tmpRegNumber, false)) + + // Offsets are resolved in ResolveRelativeAddress phase. + for _, offset := range targets { + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + // Inlined offset tables cannot be disassembled properly, so pad dummy instructions to make the debugging easier. + c.Emit4Bytes(dummyInstruction) + } else { + c.Emit4Bytes(offset) + } + } +} + +// encodeExitSequence matches the implementation detail of functionABI.emitGoEntryPreamble. +func encodeExitSequence(c backend.Compiler, ctxReg regalloc.VReg) { + // Restore the FP, SP and LR, and return to the Go code: + // ldr lr, [ctxReg, #GoReturnAddress] + // ldr fp, [ctxReg, #OriginalFramePointer] + // ldr tmp, [ctxReg, #OriginalStackPointer] + // mov sp, tmp ;; sp cannot be str'ed directly. + // ret ;; --> return to the Go code + + var ctxEvicted bool + if ctx := ctxReg.RealReg(); ctx == fp || ctx == lr { + // In order to avoid overwriting the context register, we move ctxReg to tmp. + c.Emit4Bytes(encodeMov64(regNumberInEncoding[tmp], regNumberInEncoding[ctx], false, false)) + ctxReg = tmpRegVReg + ctxEvicted = true + } + + restoreLr := encodeLoadOrStore( + uLoad64, + regNumberInEncoding[lr], + addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: ctxReg, + imm: wazevoapi.ExecutionContextOffsetGoReturnAddress.I64(), + }, + ) + + restoreFp := encodeLoadOrStore( + uLoad64, + regNumberInEncoding[fp], + addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: ctxReg, + imm: wazevoapi.ExecutionContextOffsetOriginalFramePointer.I64(), + }, + ) + + restoreSpToTmp := encodeLoadOrStore( + uLoad64, + regNumberInEncoding[tmp], + addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: ctxReg, + imm: wazevoapi.ExecutionContextOffsetOriginalStackPointer.I64(), + }, + ) + + movTmpToSp := encodeAddSubtractImmediate(0b100, 0, 0, + regNumberInEncoding[tmp], regNumberInEncoding[sp]) + + c.Emit4Bytes(restoreFp) + c.Emit4Bytes(restoreLr) + c.Emit4Bytes(restoreSpToTmp) + c.Emit4Bytes(movTmpToSp) + c.Emit4Bytes(encodeRet()) + if !ctxEvicted { + // In order to have the fixed-length exit sequence, we need to padd the binary. + // Since this will never be reached, we insert a dummy instruction. + c.Emit4Bytes(dummyInstruction) + } +} + +func encodeRet() uint32 { + // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/RET--Return-from-subroutine-?lang=en + return 0b1101011001011111<<16 | regNumberInEncoding[lr]<<5 +} + +func encodeAtomicRmw(op atomicRmwOp, rs, rt, rn uint32, size uint32) uint32 { + var _31to21, _15to10, sz uint32 + + switch size { + case 8: + sz = 0b11 + case 4: + sz = 0b10 + case 2: + sz = 0b01 + case 1: + sz = 0b00 + } + + _31to21 = 0b00111000_111 | sz<<9 + + switch op { + case atomicRmwOpAdd: + _15to10 = 0b000000 + case atomicRmwOpClr: + _15to10 = 0b000100 + case atomicRmwOpSet: + _15to10 = 0b001100 + case atomicRmwOpEor: + _15to10 = 0b001000 + case atomicRmwOpSwp: + _15to10 = 0b100000 + } + + return _31to21<<21 | rs<<16 | _15to10<<10 | rn<<5 | rt +} + +func encodeAtomicCas(rs, rt, rn uint32, size uint32) uint32 { + var _31to21, _15to10, sz uint32 + + switch size { + case 8: + sz = 0b11 + case 4: + sz = 0b10 + case 2: + sz = 0b01 + case 1: + sz = 0b00 + } + + _31to21 = 0b00001000_111 | sz<<9 + _15to10 = 0b111111 + + return _31to21<<21 | rs<<16 | _15to10<<10 | rn<<5 | rt +} + +func encodeAtomicLoadStore(rn, rt, size, l uint32) uint32 { + var _31to21, _20to16, _15to10, sz uint32 + + switch size { + case 8: + sz = 0b11 + case 4: + sz = 0b10 + case 2: + sz = 0b01 + case 1: + sz = 0b00 + } + + _31to21 = 0b00001000_100 | sz<<9 | l<<1 + _20to16 = 0b11111 + _15to10 = 0b111111 + + return _31to21<<21 | _20to16<<16 | _15to10<<10 | rn<<5 | rt +} + +func encodeDMB() uint32 { + return 0b11010101000000110011101110111111 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_constant.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_constant.go new file mode 100644 index 00000000..6c6824fb --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_constant.go @@ -0,0 +1,301 @@ +package arm64 + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// lowerConstant allocates a new VReg and inserts the instruction to load the constant value. +func (m *machine) lowerConstant(instr *ssa.Instruction) (vr regalloc.VReg) { + val := instr.Return() + valType := val.Type() + + vr = m.compiler.AllocateVReg(valType) + v := instr.ConstantVal() + m.insertLoadConstant(v, valType, vr) + return +} + +// InsertLoadConstantBlockArg implements backend.Machine. +func (m *machine) InsertLoadConstantBlockArg(instr *ssa.Instruction, vr regalloc.VReg) { + val := instr.Return() + valType := val.Type() + v := instr.ConstantVal() + load := m.allocateInstr() + load.asLoadConstBlockArg(v, valType, vr) + m.insert(load) +} + +func (m *machine) lowerLoadConstantBlockArgAfterRegAlloc(i *instruction) { + v, typ, dst := i.loadConstBlockArgData() + m.insertLoadConstant(v, typ, dst) +} + +func (m *machine) insertLoadConstant(v uint64, valType ssa.Type, vr regalloc.VReg) { + if valType.Bits() < 64 { // Clear the redundant bits just in case it's unexpectedly sign-extended, etc. + v = v & ((1 << valType.Bits()) - 1) + } + + switch valType { + case ssa.TypeF32: + loadF := m.allocateInstr() + loadF.asLoadFpuConst32(vr, v) + m.insert(loadF) + case ssa.TypeF64: + loadF := m.allocateInstr() + loadF.asLoadFpuConst64(vr, v) + m.insert(loadF) + case ssa.TypeI32: + if v == 0 { + m.InsertMove(vr, xzrVReg, ssa.TypeI32) + } else { + m.lowerConstantI32(vr, int32(v)) + } + case ssa.TypeI64: + if v == 0 { + m.InsertMove(vr, xzrVReg, ssa.TypeI64) + } else { + m.lowerConstantI64(vr, int64(v)) + } + default: + panic("TODO") + } +} + +// The following logics are based on the old asm/arm64 package. +// https://github.com/tetratelabs/wazero/blob/39f2ff23a6d609e10c82b9cc0b981f6de5b87a9c/internal/asm/arm64/impl.go + +func (m *machine) lowerConstantI32(dst regalloc.VReg, c int32) { + // Following the logic here: + // https://github.com/golang/go/blob/release-branch.go1.15/src/cmd/internal/obj/arm64/asm7.go#L1637 + ic := int64(uint32(c)) + if ic >= 0 && (ic <= 0xfff || (ic&0xfff) == 0 && (uint64(ic>>12) <= 0xfff)) { + if isBitMaskImmediate(uint64(c), false) { + m.lowerConstViaBitMaskImmediate(uint64(uint32(c)), dst, false) + return + } + } + + if t := const16bitAligned(int64(uint32(c))); t >= 0 { + // If the const can fit within 16-bit alignment, for example, 0xffff, 0xffff_0000 or 0xffff_0000_0000_0000 + // We could load it into temporary with movk. + m.insertMOVZ(dst, uint64(uint32(c)>>(16*t)), t, false) + } else if t := const16bitAligned(int64(^c)); t >= 0 { + // Also, if the inverse of the const can fit within 16-bit range, do the same ^^. + m.insertMOVN(dst, uint64(^c>>(16*t)), t, false) + } else if isBitMaskImmediate(uint64(uint32(c)), false) { + m.lowerConstViaBitMaskImmediate(uint64(c), dst, false) + } else { + // Otherwise, we use MOVZ and MOVK to load it. + c16 := uint16(c) + m.insertMOVZ(dst, uint64(c16), 0, false) + c16 = uint16(uint32(c) >> 16) + m.insertMOVK(dst, uint64(c16), 1, false) + } +} + +func (m *machine) lowerConstantI64(dst regalloc.VReg, c int64) { + // Following the logic here: + // https://github.com/golang/go/blob/release-branch.go1.15/src/cmd/internal/obj/arm64/asm7.go#L1798-L1852 + if c >= 0 && (c <= 0xfff || (c&0xfff) == 0 && (uint64(c>>12) <= 0xfff)) { + if isBitMaskImmediate(uint64(c), true) { + m.lowerConstViaBitMaskImmediate(uint64(c), dst, true) + return + } + } + + if t := const16bitAligned(c); t >= 0 { + // If the const can fit within 16-bit alignment, for example, 0xffff, 0xffff_0000 or 0xffff_0000_0000_0000 + // We could load it into temporary with movk. + m.insertMOVZ(dst, uint64(c)>>(16*t), t, true) + } else if t := const16bitAligned(^c); t >= 0 { + // Also, if the reverse of the const can fit within 16-bit range, do the same ^^. + m.insertMOVN(dst, uint64(^c)>>(16*t), t, true) + } else if isBitMaskImmediate(uint64(c), true) { + m.lowerConstViaBitMaskImmediate(uint64(c), dst, true) + } else { + m.load64bitConst(c, dst) + } +} + +func (m *machine) lowerConstViaBitMaskImmediate(c uint64, dst regalloc.VReg, b64 bool) { + instr := m.allocateInstr() + instr.asALUBitmaskImm(aluOpOrr, dst, xzrVReg, c, b64) + m.insert(instr) +} + +// isBitMaskImmediate determines if the value can be encoded as "bitmask immediate". +// +// Such an immediate is a 32-bit or 64-bit pattern viewed as a vector of identical elements of size e = 2, 4, 8, 16, 32, or 64 bits. +// Each element contains the same sub-pattern: a single run of 1 to e-1 non-zero bits, rotated by 0 to e-1 bits. +// +// See https://developer.arm.com/documentation/dui0802/b/A64-General-Instructions/MOV--bitmask-immediate- +func isBitMaskImmediate(x uint64, _64 bool) bool { + // All zeros and ones are not "bitmask immediate" by definition. + if x == 0 || (_64 && x == 0xffff_ffff_ffff_ffff) || (!_64 && x == 0xffff_ffff) { + return false + } + + switch { + case x != x>>32|x<<32: + // e = 64 + case x != x>>16|x<<48: + // e = 32 (x == x>>32|x<<32). + // e.g. 0x00ff_ff00_00ff_ff00 + x = uint64(int32(x)) + case x != x>>8|x<<56: + // e = 16 (x == x>>16|x<<48). + // e.g. 0x00ff_00ff_00ff_00ff + x = uint64(int16(x)) + case x != x>>4|x<<60: + // e = 8 (x == x>>8|x<<56). + // e.g. 0x0f0f_0f0f_0f0f_0f0f + x = uint64(int8(x)) + default: + // e = 4 or 2. + return true + } + return sequenceOfSetbits(x) || sequenceOfSetbits(^x) +} + +// sequenceOfSetbits returns true if the number's binary representation is the sequence set bit (1). +// For example: 0b1110 -> true, 0b1010 -> false +func sequenceOfSetbits(x uint64) bool { + y := getLowestBit(x) + // If x is a sequence of set bit, this should results in the number + // with only one set bit (i.e. power of two). + y += x + return (y-1)&y == 0 +} + +func getLowestBit(x uint64) uint64 { + return x & (^x + 1) +} + +// const16bitAligned check if the value is on the 16-bit alignment. +// If so, returns the shift num divided by 16, and otherwise -1. +func const16bitAligned(v int64) (ret int) { + ret = -1 + for s := 0; s < 64; s += 16 { + if (uint64(v) &^ (uint64(0xffff) << uint(s))) == 0 { + ret = s / 16 + break + } + } + return +} + +// load64bitConst loads a 64-bit constant into the register, following the same logic to decide how to load large 64-bit +// consts as in the Go assembler. +// +// See https://github.com/golang/go/blob/release-branch.go1.15/src/cmd/internal/obj/arm64/asm7.go#L6632-L6759 +func (m *machine) load64bitConst(c int64, dst regalloc.VReg) { + var bits [4]uint64 + var zeros, negs int + for i := 0; i < 4; i++ { + bits[i] = uint64(c) >> uint(i*16) & 0xffff + if v := bits[i]; v == 0 { + zeros++ + } else if v == 0xffff { + negs++ + } + } + + if zeros == 3 { + // one MOVZ instruction. + for i, v := range bits { + if v != 0 { + m.insertMOVZ(dst, v, i, true) + } + } + } else if negs == 3 { + // one MOVN instruction. + for i, v := range bits { + if v != 0xffff { + v = ^v + m.insertMOVN(dst, v, i, true) + } + } + } else if zeros == 2 { + // one MOVZ then one OVK. + var movz bool + for i, v := range bits { + if !movz && v != 0 { // MOVZ. + m.insertMOVZ(dst, v, i, true) + movz = true + } else if v != 0 { + m.insertMOVK(dst, v, i, true) + } + } + + } else if negs == 2 { + // one MOVN then one or two MOVK. + var movn bool + for i, v := range bits { // Emit MOVN. + if !movn && v != 0xffff { + v = ^v + // https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/MOVN + m.insertMOVN(dst, v, i, true) + movn = true + } else if v != 0xffff { + m.insertMOVK(dst, v, i, true) + } + } + + } else if zeros == 1 { + // one MOVZ then two MOVK. + var movz bool + for i, v := range bits { + if !movz && v != 0 { // MOVZ. + m.insertMOVZ(dst, v, i, true) + movz = true + } else if v != 0 { + m.insertMOVK(dst, v, i, true) + } + } + + } else if negs == 1 { + // one MOVN then two MOVK. + var movn bool + for i, v := range bits { // Emit MOVN. + if !movn && v != 0xffff { + v = ^v + // https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/MOVN + m.insertMOVN(dst, v, i, true) + movn = true + } else if v != 0xffff { + m.insertMOVK(dst, v, i, true) + } + } + + } else { + // one MOVZ then up to three MOVK. + var movz bool + for i, v := range bits { + if !movz && v != 0 { // MOVZ. + m.insertMOVZ(dst, v, i, true) + movz = true + } else if v != 0 { + m.insertMOVK(dst, v, i, true) + } + } + } +} + +func (m *machine) insertMOVZ(dst regalloc.VReg, v uint64, shift int, dst64 bool) { + instr := m.allocateInstr() + instr.asMOVZ(dst, v, uint32(shift), dst64) + m.insert(instr) +} + +func (m *machine) insertMOVK(dst regalloc.VReg, v uint64, shift int, dst64 bool) { + instr := m.allocateInstr() + instr.asMOVK(dst, v, uint32(shift), dst64) + m.insert(instr) +} + +func (m *machine) insertMOVN(dst regalloc.VReg, v uint64, shift int, dst64 bool) { + instr := m.allocateInstr() + instr.asMOVN(dst, v, uint32(shift), dst64) + m.insert(instr) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr.go new file mode 100644 index 00000000..f9df356c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr.go @@ -0,0 +1,2224 @@ +package arm64 + +// Files prefixed as lower_instr** do the instruction selection, meaning that lowering SSA level instructions +// into machine specific instructions. +// +// Importantly, what the lower** functions does includes tree-matching; find the pattern from the given instruction tree, +// and merge the multiple instructions if possible. It can be considered as "N:1" instruction selection. + +import ( + "fmt" + "math" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// LowerSingleBranch implements backend.Machine. +func (m *machine) LowerSingleBranch(br *ssa.Instruction) { + switch br.Opcode() { + case ssa.OpcodeJump: + _, _, targetBlkID := br.BranchData() + if br.IsFallthroughJump() { + return + } + b := m.allocateInstr() + targetBlk := m.compiler.SSABuilder().BasicBlock(targetBlkID) + if targetBlk.ReturnBlock() { + b.asRet() + } else { + b.asBr(ssaBlockLabel(targetBlk)) + } + m.insert(b) + case ssa.OpcodeBrTable: + m.lowerBrTable(br) + default: + panic("BUG: unexpected branch opcode" + br.Opcode().String()) + } +} + +func (m *machine) lowerBrTable(i *ssa.Instruction) { + index, targetBlockIDs := i.BrTableData() + targetBlockCount := len(targetBlockIDs.View()) + indexOperand := m.getOperand_NR(m.compiler.ValueDefinition(index), extModeNone) + + // Firstly, we have to do the bounds check of the index, and + // set it to the default target (sitting at the end of the list) if it's out of bounds. + + // mov maxIndexReg #maximum_index + // subs wzr, index, maxIndexReg + // csel adjustedIndex, maxIndexReg, index, hs ;; if index is higher or equal than maxIndexReg. + maxIndexReg := m.compiler.AllocateVReg(ssa.TypeI32) + m.lowerConstantI32(maxIndexReg, int32(targetBlockCount-1)) + subs := m.allocateInstr() + subs.asALU(aluOpSubS, xzrVReg, indexOperand, operandNR(maxIndexReg), false) + m.insert(subs) + csel := m.allocateInstr() + adjustedIndex := m.compiler.AllocateVReg(ssa.TypeI32) + csel.asCSel(adjustedIndex, operandNR(maxIndexReg), indexOperand, hs, false) + m.insert(csel) + + brSequence := m.allocateInstr() + + tableIndex := m.addJmpTableTarget(targetBlockIDs) + brSequence.asBrTableSequence(adjustedIndex, tableIndex, targetBlockCount) + m.insert(brSequence) +} + +// LowerConditionalBranch implements backend.Machine. +func (m *machine) LowerConditionalBranch(b *ssa.Instruction) { + cval, args, targetBlkID := b.BranchData() + if len(args) > 0 { + panic(fmt.Sprintf( + "conditional branch shouldn't have args; likely a bug in critical edge splitting: from %s to %s", + m.currentLabelPos.sb, + targetBlkID, + )) + } + + targetBlk := m.compiler.SSABuilder().BasicBlock(targetBlkID) + target := ssaBlockLabel(targetBlk) + cvalDef := m.compiler.ValueDefinition(cval) + + switch { + case m.compiler.MatchInstr(cvalDef, ssa.OpcodeIcmp): // This case, we can use the ALU flag set by SUBS instruction. + cvalInstr := cvalDef.Instr + x, y, c := cvalInstr.IcmpData() + cc, signed := condFlagFromSSAIntegerCmpCond(c), c.Signed() + if b.Opcode() == ssa.OpcodeBrz { + cc = cc.invert() + } + + if !m.tryLowerBandToFlag(x, y) { + m.lowerIcmpToFlag(x, y, signed) + } + cbr := m.allocateInstr() + cbr.asCondBr(cc.asCond(), target, false /* ignored */) + m.insert(cbr) + cvalDef.Instr.MarkLowered() + case m.compiler.MatchInstr(cvalDef, ssa.OpcodeFcmp): // This case we can use the Fpu flag directly. + cvalInstr := cvalDef.Instr + x, y, c := cvalInstr.FcmpData() + cc := condFlagFromSSAFloatCmpCond(c) + if b.Opcode() == ssa.OpcodeBrz { + cc = cc.invert() + } + m.lowerFcmpToFlag(x, y) + cbr := m.allocateInstr() + cbr.asCondBr(cc.asCond(), target, false /* ignored */) + m.insert(cbr) + cvalDef.Instr.MarkLowered() + default: + rn := m.getOperand_NR(cvalDef, extModeNone) + var c cond + if b.Opcode() == ssa.OpcodeBrz { + c = registerAsRegZeroCond(rn.nr()) + } else { + c = registerAsRegNotZeroCond(rn.nr()) + } + cbr := m.allocateInstr() + cbr.asCondBr(c, target, false) + m.insert(cbr) + } +} + +func (m *machine) tryLowerBandToFlag(x, y ssa.Value) (ok bool) { + xx := m.compiler.ValueDefinition(x) + yy := m.compiler.ValueDefinition(y) + if xx.IsFromInstr() && xx.Instr.Constant() && xx.Instr.ConstantVal() == 0 { + if m.compiler.MatchInstr(yy, ssa.OpcodeBand) { + bandInstr := yy.Instr + m.lowerBitwiseAluOp(bandInstr, aluOpAnds, true) + ok = true + bandInstr.MarkLowered() + return + } + } + + if yy.IsFromInstr() && yy.Instr.Constant() && yy.Instr.ConstantVal() == 0 { + if m.compiler.MatchInstr(xx, ssa.OpcodeBand) { + bandInstr := xx.Instr + m.lowerBitwiseAluOp(bandInstr, aluOpAnds, true) + ok = true + bandInstr.MarkLowered() + return + } + } + return +} + +// LowerInstr implements backend.Machine. +func (m *machine) LowerInstr(instr *ssa.Instruction) { + if l := instr.SourceOffset(); l.Valid() { + info := m.allocateInstr().asEmitSourceOffsetInfo(l) + m.insert(info) + } + + switch op := instr.Opcode(); op { + case ssa.OpcodeBrz, ssa.OpcodeBrnz, ssa.OpcodeJump, ssa.OpcodeBrTable: + panic("BUG: branching instructions are handled by LowerBranches") + case ssa.OpcodeReturn: + panic("BUG: return must be handled by backend.Compiler") + case ssa.OpcodeIadd, ssa.OpcodeIsub: + m.lowerSubOrAdd(instr, op == ssa.OpcodeIadd) + case ssa.OpcodeFadd, ssa.OpcodeFsub, ssa.OpcodeFmul, ssa.OpcodeFdiv, ssa.OpcodeFmax, ssa.OpcodeFmin: + m.lowerFpuBinOp(instr) + case ssa.OpcodeIconst, ssa.OpcodeF32const, ssa.OpcodeF64const: // Constant instructions are inlined. + case ssa.OpcodeExitWithCode: + execCtx, code := instr.ExitWithCodeData() + m.lowerExitWithCode(m.compiler.VRegOf(execCtx), code) + case ssa.OpcodeExitIfTrueWithCode: + execCtx, c, code := instr.ExitIfTrueWithCodeData() + m.lowerExitIfTrueWithCode(m.compiler.VRegOf(execCtx), c, code) + case ssa.OpcodeStore, ssa.OpcodeIstore8, ssa.OpcodeIstore16, ssa.OpcodeIstore32: + m.lowerStore(instr) + case ssa.OpcodeLoad: + dst := instr.Return() + ptr, offset, typ := instr.LoadData() + m.lowerLoad(ptr, offset, typ, dst) + case ssa.OpcodeVZeroExtLoad: + dst := instr.Return() + ptr, offset, typ := instr.VZeroExtLoadData() + m.lowerLoad(ptr, offset, typ, dst) + case ssa.OpcodeUload8, ssa.OpcodeUload16, ssa.OpcodeUload32, ssa.OpcodeSload8, ssa.OpcodeSload16, ssa.OpcodeSload32: + ptr, offset, _ := instr.LoadData() + ret := m.compiler.VRegOf(instr.Return()) + m.lowerExtLoad(op, ptr, offset, ret) + case ssa.OpcodeCall, ssa.OpcodeCallIndirect: + m.lowerCall(instr) + case ssa.OpcodeIcmp: + m.lowerIcmp(instr) + case ssa.OpcodeVIcmp: + m.lowerVIcmp(instr) + case ssa.OpcodeVFcmp: + m.lowerVFcmp(instr) + case ssa.OpcodeVCeil: + m.lowerVecMisc(vecOpFrintp, instr) + case ssa.OpcodeVFloor: + m.lowerVecMisc(vecOpFrintm, instr) + case ssa.OpcodeVTrunc: + m.lowerVecMisc(vecOpFrintz, instr) + case ssa.OpcodeVNearest: + m.lowerVecMisc(vecOpFrintn, instr) + case ssa.OpcodeVMaxPseudo: + m.lowerVMinMaxPseudo(instr, true) + case ssa.OpcodeVMinPseudo: + m.lowerVMinMaxPseudo(instr, false) + case ssa.OpcodeBand: + m.lowerBitwiseAluOp(instr, aluOpAnd, false) + case ssa.OpcodeBor: + m.lowerBitwiseAluOp(instr, aluOpOrr, false) + case ssa.OpcodeBxor: + m.lowerBitwiseAluOp(instr, aluOpEor, false) + case ssa.OpcodeIshl: + m.lowerShifts(instr, extModeNone, aluOpLsl) + case ssa.OpcodeSshr: + if instr.Return().Type().Bits() == 64 { + m.lowerShifts(instr, extModeSignExtend64, aluOpAsr) + } else { + m.lowerShifts(instr, extModeSignExtend32, aluOpAsr) + } + case ssa.OpcodeUshr: + if instr.Return().Type().Bits() == 64 { + m.lowerShifts(instr, extModeZeroExtend64, aluOpLsr) + } else { + m.lowerShifts(instr, extModeZeroExtend32, aluOpLsr) + } + case ssa.OpcodeRotl: + m.lowerRotl(instr) + case ssa.OpcodeRotr: + m.lowerRotr(instr) + case ssa.OpcodeSExtend, ssa.OpcodeUExtend: + from, to, signed := instr.ExtendData() + m.lowerExtend(instr.Arg(), instr.Return(), from, to, signed) + case ssa.OpcodeFcmp: + x, y, c := instr.FcmpData() + m.lowerFcmp(x, y, instr.Return(), c) + case ssa.OpcodeImul: + x, y := instr.Arg2() + result := instr.Return() + m.lowerImul(x, y, result) + case ssa.OpcodeUndefined: + undef := m.allocateInstr() + undef.asUDF() + m.insert(undef) + case ssa.OpcodeSelect: + c, x, y := instr.SelectData() + if x.Type() == ssa.TypeV128 { + rc := m.getOperand_NR(m.compiler.ValueDefinition(c), extModeNone) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerSelectVec(rc, rn, rm, rd) + } else { + m.lowerSelect(c, x, y, instr.Return()) + } + case ssa.OpcodeClz: + x := instr.Arg() + result := instr.Return() + m.lowerClz(x, result) + case ssa.OpcodeCtz: + x := instr.Arg() + result := instr.Return() + m.lowerCtz(x, result) + case ssa.OpcodePopcnt: + x := instr.Arg() + result := instr.Return() + m.lowerPopcnt(x, result) + case ssa.OpcodeFcvtToSint, ssa.OpcodeFcvtToSintSat: + x, ctx := instr.Arg2() + result := instr.Return() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(result) + ctxVReg := m.compiler.VRegOf(ctx) + m.lowerFpuToInt(rd, rn, ctxVReg, true, x.Type() == ssa.TypeF64, + result.Type().Bits() == 64, op == ssa.OpcodeFcvtToSintSat) + case ssa.OpcodeFcvtToUint, ssa.OpcodeFcvtToUintSat: + x, ctx := instr.Arg2() + result := instr.Return() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(result) + ctxVReg := m.compiler.VRegOf(ctx) + m.lowerFpuToInt(rd, rn, ctxVReg, false, x.Type() == ssa.TypeF64, + result.Type().Bits() == 64, op == ssa.OpcodeFcvtToUintSat) + case ssa.OpcodeFcvtFromSint: + x := instr.Arg() + result := instr.Return() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(result) + m.lowerIntToFpu(rd, rn, true, x.Type() == ssa.TypeI64, result.Type().Bits() == 64) + case ssa.OpcodeFcvtFromUint: + x := instr.Arg() + result := instr.Return() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(result) + m.lowerIntToFpu(rd, rn, false, x.Type() == ssa.TypeI64, result.Type().Bits() == 64) + case ssa.OpcodeFdemote: + v := instr.Arg() + rn := m.getOperand_NR(m.compiler.ValueDefinition(v), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + cnt := m.allocateInstr() + cnt.asFpuRR(fpuUniOpCvt64To32, rd, rn, false) + m.insert(cnt) + case ssa.OpcodeFpromote: + v := instr.Arg() + rn := m.getOperand_NR(m.compiler.ValueDefinition(v), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + cnt := m.allocateInstr() + cnt.asFpuRR(fpuUniOpCvt32To64, rd, rn, true) + m.insert(cnt) + case ssa.OpcodeIreduce: + rn := m.getOperand_NR(m.compiler.ValueDefinition(instr.Arg()), extModeNone) + retVal := instr.Return() + rd := m.compiler.VRegOf(retVal) + + if retVal.Type() != ssa.TypeI32 { + panic("TODO?: Ireduce to non-i32") + } + mov := m.allocateInstr() + mov.asMove32(rd, rn.reg()) + m.insert(mov) + case ssa.OpcodeFneg: + m.lowerFpuUniOp(fpuUniOpNeg, instr.Arg(), instr.Return()) + case ssa.OpcodeSqrt: + m.lowerFpuUniOp(fpuUniOpSqrt, instr.Arg(), instr.Return()) + case ssa.OpcodeCeil: + m.lowerFpuUniOp(fpuUniOpRoundPlus, instr.Arg(), instr.Return()) + case ssa.OpcodeFloor: + m.lowerFpuUniOp(fpuUniOpRoundMinus, instr.Arg(), instr.Return()) + case ssa.OpcodeTrunc: + m.lowerFpuUniOp(fpuUniOpRoundZero, instr.Arg(), instr.Return()) + case ssa.OpcodeNearest: + m.lowerFpuUniOp(fpuUniOpRoundNearest, instr.Arg(), instr.Return()) + case ssa.OpcodeFabs: + m.lowerFpuUniOp(fpuUniOpAbs, instr.Arg(), instr.Return()) + case ssa.OpcodeBitcast: + m.lowerBitcast(instr) + case ssa.OpcodeFcopysign: + x, y := instr.Arg2() + m.lowerFcopysign(x, y, instr.Return()) + case ssa.OpcodeSdiv, ssa.OpcodeUdiv: + x, y, ctx := instr.Arg3() + ctxVReg := m.compiler.VRegOf(ctx) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerIDiv(ctxVReg, rd, rn, rm, x.Type() == ssa.TypeI64, op == ssa.OpcodeSdiv) + case ssa.OpcodeSrem, ssa.OpcodeUrem: + x, y, ctx := instr.Arg3() + ctxVReg := m.compiler.VRegOf(ctx) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerIRem(ctxVReg, rd, rn.nr(), rm, x.Type() == ssa.TypeI64, op == ssa.OpcodeSrem) + case ssa.OpcodeVconst: + result := m.compiler.VRegOf(instr.Return()) + lo, hi := instr.VconstData() + v := m.allocateInstr() + v.asLoadFpuConst128(result, lo, hi) + m.insert(v) + case ssa.OpcodeVbnot: + x := instr.Arg() + ins := m.allocateInstr() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + ins.asVecMisc(vecOpNot, rd, rn, vecArrangement16B) + m.insert(ins) + case ssa.OpcodeVbxor: + x, y := instr.Arg2() + m.lowerVecRRR(vecOpEOR, x, y, instr.Return(), vecArrangement16B) + case ssa.OpcodeVbor: + x, y := instr.Arg2() + m.lowerVecRRR(vecOpOrr, x, y, instr.Return(), vecArrangement16B) + case ssa.OpcodeVband: + x, y := instr.Arg2() + m.lowerVecRRR(vecOpAnd, x, y, instr.Return(), vecArrangement16B) + case ssa.OpcodeVbandnot: + x, y := instr.Arg2() + m.lowerVecRRR(vecOpBic, x, y, instr.Return(), vecArrangement16B) + case ssa.OpcodeVbitselect: + c, x, y := instr.SelectData() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + creg := m.getOperand_NR(m.compiler.ValueDefinition(c), extModeNone) + tmp := m.compiler.AllocateVReg(ssa.TypeV128) + + // creg is overwritten by BSL, so we need to move it to the result register before the instruction + // in case when it is used somewhere else. + mov := m.allocateInstr() + mov.asFpuMov128(tmp, creg.nr()) + m.insert(mov) + + ins := m.allocateInstr() + ins.asVecRRRRewrite(vecOpBsl, tmp, rn, rm, vecArrangement16B) + m.insert(ins) + + mov2 := m.allocateInstr() + rd := m.compiler.VRegOf(instr.Return()) + mov2.asFpuMov128(rd, tmp) + m.insert(mov2) + case ssa.OpcodeVanyTrue, ssa.OpcodeVallTrue: + x, lane := instr.ArgWithLane() + var arr vecArrangement + if op == ssa.OpcodeVallTrue { + arr = ssaLaneToArrangement(lane) + } + rm := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerVcheckTrue(op, rm, rd, arr) + case ssa.OpcodeVhighBits: + x, lane := instr.ArgWithLane() + rm := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + arr := ssaLaneToArrangement(lane) + m.lowerVhighBits(rm, rd, arr) + case ssa.OpcodeVIadd: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpAdd, x, y, instr.Return(), arr) + case ssa.OpcodeExtIaddPairwise: + v, lane, signed := instr.ExtIaddPairwiseData() + vv := m.getOperand_NR(m.compiler.ValueDefinition(v), extModeNone) + + tmpLo, tmpHi := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)), operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + var widen vecOp + if signed { + widen = vecOpSshll + } else { + widen = vecOpUshll + } + + var loArr, hiArr, dstArr vecArrangement + switch lane { + case ssa.VecLaneI8x16: + loArr, hiArr, dstArr = vecArrangement8B, vecArrangement16B, vecArrangement8H + case ssa.VecLaneI16x8: + loArr, hiArr, dstArr = vecArrangement4H, vecArrangement8H, vecArrangement4S + case ssa.VecLaneI32x4: + loArr, hiArr, dstArr = vecArrangement2S, vecArrangement4S, vecArrangement2D + default: + panic("unsupported lane " + lane.String()) + } + + widenLo := m.allocateInstr().asVecShiftImm(widen, tmpLo.nr(), vv, operandShiftImm(0), loArr) + widenHi := m.allocateInstr().asVecShiftImm(widen, tmpHi.nr(), vv, operandShiftImm(0), hiArr) + addp := m.allocateInstr().asVecRRR(vecOpAddp, m.compiler.VRegOf(instr.Return()), tmpLo, tmpHi, dstArr) + m.insert(widenLo) + m.insert(widenHi) + m.insert(addp) + + case ssa.OpcodeVSaddSat: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSqadd, x, y, instr.Return(), arr) + case ssa.OpcodeVUaddSat: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpUqadd, x, y, instr.Return(), arr) + case ssa.OpcodeVIsub: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSub, x, y, instr.Return(), arr) + case ssa.OpcodeVSsubSat: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSqsub, x, y, instr.Return(), arr) + case ssa.OpcodeVUsubSat: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpUqsub, x, y, instr.Return(), arr) + case ssa.OpcodeVImin: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSmin, x, y, instr.Return(), arr) + case ssa.OpcodeVUmin: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpUmin, x, y, instr.Return(), arr) + case ssa.OpcodeVImax: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSmax, x, y, instr.Return(), arr) + case ssa.OpcodeVUmax: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpUmax, x, y, instr.Return(), arr) + case ssa.OpcodeVAvgRound: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpUrhadd, x, y, instr.Return(), arr) + case ssa.OpcodeVImul: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerVIMul(rd, rn, rm, arr) + case ssa.OpcodeVIabs: + m.lowerVecMisc(vecOpAbs, instr) + case ssa.OpcodeVIneg: + m.lowerVecMisc(vecOpNeg, instr) + case ssa.OpcodeVIpopcnt: + m.lowerVecMisc(vecOpCnt, instr) + case ssa.OpcodeVIshl, + ssa.OpcodeVSshr, ssa.OpcodeVUshr: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerVShift(op, rd, rn, rm, arr) + case ssa.OpcodeVSqrt: + m.lowerVecMisc(vecOpFsqrt, instr) + case ssa.OpcodeVFabs: + m.lowerVecMisc(vecOpFabs, instr) + case ssa.OpcodeVFneg: + m.lowerVecMisc(vecOpFneg, instr) + case ssa.OpcodeVFmin: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFmin, x, y, instr.Return(), arr) + case ssa.OpcodeVFmax: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFmax, x, y, instr.Return(), arr) + case ssa.OpcodeVFadd: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFadd, x, y, instr.Return(), arr) + case ssa.OpcodeVFsub: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFsub, x, y, instr.Return(), arr) + case ssa.OpcodeVFmul: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFmul, x, y, instr.Return(), arr) + case ssa.OpcodeSqmulRoundSat: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpSqrdmulh, x, y, instr.Return(), arr) + case ssa.OpcodeVFdiv: + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + m.lowerVecRRR(vecOpFdiv, x, y, instr.Return(), arr) + case ssa.OpcodeVFcvtToSintSat, ssa.OpcodeVFcvtToUintSat: + x, lane := instr.ArgWithLane() + arr := ssaLaneToArrangement(lane) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerVfpuToInt(rd, rn, arr, op == ssa.OpcodeVFcvtToSintSat) + case ssa.OpcodeVFcvtFromSint, ssa.OpcodeVFcvtFromUint: + x, lane := instr.ArgWithLane() + arr := ssaLaneToArrangement(lane) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + m.lowerVfpuFromInt(rd, rn, arr, op == ssa.OpcodeVFcvtFromSint) + case ssa.OpcodeSwidenLow, ssa.OpcodeUwidenLow: + x, lane := instr.ArgWithLane() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + var arr vecArrangement + switch lane { + case ssa.VecLaneI8x16: + arr = vecArrangement8B + case ssa.VecLaneI16x8: + arr = vecArrangement4H + case ssa.VecLaneI32x4: + arr = vecArrangement2S + } + + shll := m.allocateInstr() + if signed := op == ssa.OpcodeSwidenLow; signed { + shll.asVecShiftImm(vecOpSshll, rd, rn, operandShiftImm(0), arr) + } else { + shll.asVecShiftImm(vecOpUshll, rd, rn, operandShiftImm(0), arr) + } + m.insert(shll) + case ssa.OpcodeSwidenHigh, ssa.OpcodeUwidenHigh: + x, lane := instr.ArgWithLane() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + arr := ssaLaneToArrangement(lane) + + shll := m.allocateInstr() + if signed := op == ssa.OpcodeSwidenHigh; signed { + shll.asVecShiftImm(vecOpSshll, rd, rn, operandShiftImm(0), arr) + } else { + shll.asVecShiftImm(vecOpUshll, rd, rn, operandShiftImm(0), arr) + } + m.insert(shll) + + case ssa.OpcodeSnarrow, ssa.OpcodeUnarrow: + x, y, lane := instr.Arg2WithLane() + var arr, arr2 vecArrangement + switch lane { + case ssa.VecLaneI16x8: // I16x8 + arr = vecArrangement8B + arr2 = vecArrangement16B // Implies sqxtn2. + case ssa.VecLaneI32x4: + arr = vecArrangement4H + arr2 = vecArrangement8H // Implies sqxtn2. + default: + panic("unsupported lane " + lane.String()) + } + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + tmp := m.compiler.AllocateVReg(ssa.TypeV128) + + loQxtn := m.allocateInstr() + hiQxtn := m.allocateInstr() + if signed := op == ssa.OpcodeSnarrow; signed { + // Narrow lanes on rn and write them into lower-half of rd. + loQxtn.asVecMisc(vecOpSqxtn, tmp, rn, arr) // low + // Narrow lanes on rm and write them into higher-half of rd. + hiQxtn.asVecMisc(vecOpSqxtn, tmp, rm, arr2) // high (sqxtn2) + } else { + // Narrow lanes on rn and write them into lower-half of rd. + loQxtn.asVecMisc(vecOpSqxtun, tmp, rn, arr) // low + // Narrow lanes on rm and write them into higher-half of rd. + hiQxtn.asVecMisc(vecOpSqxtun, tmp, rm, arr2) // high (sqxtn2) + } + m.insert(loQxtn) + m.insert(hiQxtn) + + mov := m.allocateInstr() + mov.asFpuMov128(rd, tmp) + m.insert(mov) + case ssa.OpcodeFvpromoteLow: + x, lane := instr.ArgWithLane() + if lane != ssa.VecLaneF32x4 { + panic("unsupported lane type " + lane.String()) + } + ins := m.allocateInstr() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + ins.asVecMisc(vecOpFcvtl, rd, rn, vecArrangement2S) + m.insert(ins) + case ssa.OpcodeFvdemote: + x, lane := instr.ArgWithLane() + if lane != ssa.VecLaneF64x2 { + panic("unsupported lane type " + lane.String()) + } + ins := m.allocateInstr() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + ins.asVecMisc(vecOpFcvtn, rd, rn, vecArrangement2S) + m.insert(ins) + case ssa.OpcodeExtractlane: + x, index, signed, lane := instr.ExtractlaneData() + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + mov := m.allocateInstr() + switch lane { + case ssa.VecLaneI8x16: + mov.asMovFromVec(rd, rn, vecArrangementB, vecIndex(index), signed) + case ssa.VecLaneI16x8: + mov.asMovFromVec(rd, rn, vecArrangementH, vecIndex(index), signed) + case ssa.VecLaneI32x4: + mov.asMovFromVec(rd, rn, vecArrangementS, vecIndex(index), signed) + case ssa.VecLaneI64x2: + mov.asMovFromVec(rd, rn, vecArrangementD, vecIndex(index), signed) + case ssa.VecLaneF32x4: + mov.asVecMovElement(rd, rn, vecArrangementS, vecIndex(0), vecIndex(index)) + case ssa.VecLaneF64x2: + mov.asVecMovElement(rd, rn, vecArrangementD, vecIndex(0), vecIndex(index)) + default: + panic("unsupported lane: " + lane.String()) + } + + m.insert(mov) + + case ssa.OpcodeInsertlane: + x, y, index, lane := instr.InsertlaneData() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + tmpReg := m.compiler.AllocateVReg(ssa.TypeV128) + + // Initially mov rn to tmp. + mov1 := m.allocateInstr() + mov1.asFpuMov128(tmpReg, rn.nr()) + m.insert(mov1) + + // movToVec and vecMovElement do not clear the remaining bits to zero, + // thus, we can mov rm in-place to tmp. + mov2 := m.allocateInstr() + switch lane { + case ssa.VecLaneI8x16: + mov2.asMovToVec(tmpReg, rm, vecArrangementB, vecIndex(index)) + case ssa.VecLaneI16x8: + mov2.asMovToVec(tmpReg, rm, vecArrangementH, vecIndex(index)) + case ssa.VecLaneI32x4: + mov2.asMovToVec(tmpReg, rm, vecArrangementS, vecIndex(index)) + case ssa.VecLaneI64x2: + mov2.asMovToVec(tmpReg, rm, vecArrangementD, vecIndex(index)) + case ssa.VecLaneF32x4: + mov2.asVecMovElement(tmpReg, rm, vecArrangementS, vecIndex(index), vecIndex(0)) + case ssa.VecLaneF64x2: + mov2.asVecMovElement(tmpReg, rm, vecArrangementD, vecIndex(index), vecIndex(0)) + } + m.insert(mov2) + + // Finally mov tmp to rd. + mov3 := m.allocateInstr() + mov3.asFpuMov128(rd, tmpReg) + m.insert(mov3) + + case ssa.OpcodeSwizzle: + x, y, lane := instr.Arg2WithLane() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + arr := ssaLaneToArrangement(lane) + + // tbl ., { . }, . + tbl1 := m.allocateInstr() + tbl1.asVecTbl(1, rd, rn, rm, arr) + m.insert(tbl1) + + case ssa.OpcodeShuffle: + x, y, lane1, lane2 := instr.ShuffleData() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + m.lowerShuffle(rd, rn, rm, lane1, lane2) + + case ssa.OpcodeSplat: + x, lane := instr.ArgWithLane() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + + dup := m.allocateInstr() + switch lane { + case ssa.VecLaneI8x16: + dup.asVecDup(rd, rn, vecArrangement16B) + case ssa.VecLaneI16x8: + dup.asVecDup(rd, rn, vecArrangement8H) + case ssa.VecLaneI32x4: + dup.asVecDup(rd, rn, vecArrangement4S) + case ssa.VecLaneI64x2: + dup.asVecDup(rd, rn, vecArrangement2D) + case ssa.VecLaneF32x4: + dup.asVecDupElement(rd, rn, vecArrangementS, vecIndex(0)) + case ssa.VecLaneF64x2: + dup.asVecDupElement(rd, rn, vecArrangementD, vecIndex(0)) + } + m.insert(dup) + + case ssa.OpcodeWideningPairwiseDotProductS: + x, y := instr.Arg2() + xx, yy := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone), + m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + tmp, tmp2 := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)), operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + m.insert(m.allocateInstr().asVecRRR(vecOpSmull, tmp.nr(), xx, yy, vecArrangement8H)) + m.insert(m.allocateInstr().asVecRRR(vecOpSmull2, tmp2.nr(), xx, yy, vecArrangement8H)) + m.insert(m.allocateInstr().asVecRRR(vecOpAddp, tmp.nr(), tmp, tmp2, vecArrangement4S)) + + rd := m.compiler.VRegOf(instr.Return()) + m.insert(m.allocateInstr().asFpuMov128(rd, tmp.nr())) + + case ssa.OpcodeLoadSplat: + ptr, offset, lane := instr.LoadSplatData() + m.lowerLoadSplat(ptr, offset, lane, instr.Return()) + + case ssa.OpcodeAtomicRmw: + m.lowerAtomicRmw(instr) + + case ssa.OpcodeAtomicCas: + m.lowerAtomicCas(instr) + + case ssa.OpcodeAtomicLoad: + m.lowerAtomicLoad(instr) + + case ssa.OpcodeAtomicStore: + m.lowerAtomicStore(instr) + + case ssa.OpcodeFence: + instr := m.allocateInstr() + instr.asDMB() + m.insert(instr) + + default: + panic("TODO: lowering " + op.String()) + } + m.FlushPendingInstructions() +} + +func (m *machine) lowerShuffle(rd regalloc.VReg, rn, rm operand, lane1, lane2 uint64) { + // `tbl2` requires 2 consecutive registers, so we arbitrarily pick v29, v30. + vReg, wReg := v29VReg, v30VReg + + // Initialize v29, v30 to rn, rm. + movv := m.allocateInstr() + movv.asFpuMov128(vReg, rn.nr()) + m.insert(movv) + + movw := m.allocateInstr() + movw.asFpuMov128(wReg, rm.nr()) + m.insert(movw) + + // `lane1`, `lane2` are already encoded as two u64s with the right layout: + // lane1 := lane[7]<<56 | ... | lane[1]<<8 | lane[0] + // lane2 := lane[15]<<56 | ... | lane[9]<<8 | lane[8] + // Thus, we can use loadFpuConst128. + tmp := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + lfc := m.allocateInstr() + lfc.asLoadFpuConst128(tmp.nr(), lane1, lane2) + m.insert(lfc) + + // tbl .16b, { .16B, .16b }, .16b + tbl2 := m.allocateInstr() + tbl2.asVecTbl(2, rd, operandNR(vReg), tmp, vecArrangement16B) + m.insert(tbl2) +} + +func (m *machine) lowerVShift(op ssa.Opcode, rd regalloc.VReg, rn, rm operand, arr vecArrangement) { + var modulo byte + switch arr { + case vecArrangement16B: + modulo = 0x7 // Modulo 8. + case vecArrangement8H: + modulo = 0xf // Modulo 16. + case vecArrangement4S: + modulo = 0x1f // Modulo 32. + case vecArrangement2D: + modulo = 0x3f // Modulo 64. + default: + panic("unsupported arrangment " + arr.String()) + } + + rtmp := operandNR(m.compiler.AllocateVReg(ssa.TypeI64)) + vtmp := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + + and := m.allocateInstr() + and.asALUBitmaskImm(aluOpAnd, rtmp.nr(), rm.nr(), uint64(modulo), true) + m.insert(and) + + if op != ssa.OpcodeVIshl { + // Negate the amount to make this as right shift. + neg := m.allocateInstr() + neg.asALU(aluOpSub, rtmp.nr(), operandNR(xzrVReg), rtmp, true) + m.insert(neg) + } + + // Copy the shift amount into a vector register as sshl/ushl requires it to be there. + dup := m.allocateInstr() + dup.asVecDup(vtmp.nr(), rtmp, arr) + m.insert(dup) + + if op == ssa.OpcodeVIshl || op == ssa.OpcodeVSshr { + sshl := m.allocateInstr() + sshl.asVecRRR(vecOpSshl, rd, rn, vtmp, arr) + m.insert(sshl) + } else { + ushl := m.allocateInstr() + ushl.asVecRRR(vecOpUshl, rd, rn, vtmp, arr) + m.insert(ushl) + } +} + +func (m *machine) lowerVcheckTrue(op ssa.Opcode, rm operand, rd regalloc.VReg, arr vecArrangement) { + tmp := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + + // Special case VallTrue for i64x2. + if op == ssa.OpcodeVallTrue && arr == vecArrangement2D { + // cmeq v3?.2d, v2?.2d, #0 + // addp v3?.2d, v3?.2d, v3?.2d + // fcmp v3?, v3? + // cset dst, eq + + ins := m.allocateInstr() + ins.asVecMisc(vecOpCmeq0, tmp.nr(), rm, vecArrangement2D) + m.insert(ins) + + addp := m.allocateInstr() + addp.asVecRRR(vecOpAddp, tmp.nr(), tmp, tmp, vecArrangement2D) + m.insert(addp) + + fcmp := m.allocateInstr() + fcmp.asFpuCmp(tmp, tmp, true) + m.insert(fcmp) + + cset := m.allocateInstr() + cset.asCSet(rd, false, eq) + m.insert(cset) + + return + } + + // Create a scalar value with umaxp or uminv, then compare it against zero. + ins := m.allocateInstr() + if op == ssa.OpcodeVanyTrue { + // umaxp v4?.16b, v2?.16b, v2?.16b + ins.asVecRRR(vecOpUmaxp, tmp.nr(), rm, rm, vecArrangement16B) + } else { + // uminv d4?, v2?.4s + ins.asVecLanes(vecOpUminv, tmp.nr(), rm, arr) + } + m.insert(ins) + + // mov x3?, v4?.d[0] + // ccmp x3?, #0x0, #0x0, al + // cset x3?, ne + // mov x0, x3? + + movv := m.allocateInstr() + movv.asMovFromVec(rd, tmp, vecArrangementD, vecIndex(0), false) + m.insert(movv) + + fc := m.allocateInstr() + fc.asCCmpImm(operandNR(rd), uint64(0), al, 0, true) + m.insert(fc) + + cset := m.allocateInstr() + cset.asCSet(rd, false, ne) + m.insert(cset) +} + +func (m *machine) lowerVhighBits(rm operand, rd regalloc.VReg, arr vecArrangement) { + r0 := operandNR(m.compiler.AllocateVReg(ssa.TypeI64)) + v0 := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + v1 := operandNR(m.compiler.AllocateVReg(ssa.TypeV128)) + + switch arr { + case vecArrangement16B: + // sshr v6?.16b, v2?.16b, #7 + // movz x4?, #0x201, lsl 0 + // movk x4?, #0x804, lsl 16 + // movk x4?, #0x2010, lsl 32 + // movk x4?, #0x8040, lsl 48 + // dup v5?.2d, x4? + // and v6?.16b, v6?.16b, v5?.16b + // ext v5?.16b, v6?.16b, v6?.16b, #8 + // zip1 v5?.16b, v6?.16b, v5?.16b + // addv s5?, v5?.8h + // umov s3?, v5?.h[0] + + // Right arithmetic shift on the original vector and store the result into v1. So we have: + // v1[i] = 0xff if vi<0, 0 otherwise. + sshr := m.allocateInstr() + sshr.asVecShiftImm(vecOpSshr, v1.nr(), rm, operandShiftImm(7), vecArrangement16B) + m.insert(sshr) + + // Load the bit mask into r0. + m.insertMOVZ(r0.nr(), 0x0201, 0, true) + m.insertMOVK(r0.nr(), 0x0804, 1, true) + m.insertMOVK(r0.nr(), 0x2010, 2, true) + m.insertMOVK(r0.nr(), 0x8040, 3, true) + + // dup r0 to v0. + dup := m.allocateInstr() + dup.asVecDup(v0.nr(), r0, vecArrangement2D) + m.insert(dup) + + // Lane-wise logical AND with the bit mask, meaning that we have + // v[i] = (1 << i) if vi<0, 0 otherwise. + // + // Below, we use the following notation: + // wi := (1 << i) if vi<0, 0 otherwise. + and := m.allocateInstr() + and.asVecRRR(vecOpAnd, v1.nr(), v1, v0, vecArrangement16B) + m.insert(and) + + // Swap the lower and higher 8 byte elements, and write it into v0, meaning that we have + // v0[i] = w(i+8) if i < 8, w(i-8) otherwise. + ext := m.allocateInstr() + ext.asVecExtract(v0.nr(), v1, v1, vecArrangement16B, uint32(8)) + m.insert(ext) + + // v = [w0, w8, ..., w7, w15] + zip1 := m.allocateInstr() + zip1.asVecPermute(vecOpZip1, v0.nr(), v1, v0, vecArrangement16B) + m.insert(zip1) + + // v.h[0] = w0 + ... + w15 + addv := m.allocateInstr() + addv.asVecLanes(vecOpAddv, v0.nr(), v0, vecArrangement8H) + m.insert(addv) + + // Extract the v.h[0] as the result. + movfv := m.allocateInstr() + movfv.asMovFromVec(rd, v0, vecArrangementH, vecIndex(0), false) + m.insert(movfv) + case vecArrangement8H: + // sshr v6?.8h, v2?.8h, #15 + // movz x4?, #0x1, lsl 0 + // movk x4?, #0x2, lsl 16 + // movk x4?, #0x4, lsl 32 + // movk x4?, #0x8, lsl 48 + // dup v5?.2d, x4? + // lsl x4?, x4?, 0x4 + // ins v5?.d[1], x4? + // and v5?.16b, v6?.16b, v5?.16b + // addv s5?, v5?.8h + // umov s3?, v5?.h[0] + + // Right arithmetic shift on the original vector and store the result into v1. So we have: + // v[i] = 0xffff if vi<0, 0 otherwise. + sshr := m.allocateInstr() + sshr.asVecShiftImm(vecOpSshr, v1.nr(), rm, operandShiftImm(15), vecArrangement8H) + m.insert(sshr) + + // Load the bit mask into r0. + m.lowerConstantI64(r0.nr(), 0x0008000400020001) + + // dup r0 to vector v0. + dup := m.allocateInstr() + dup.asVecDup(v0.nr(), r0, vecArrangement2D) + m.insert(dup) + + lsl := m.allocateInstr() + lsl.asALUShift(aluOpLsl, r0.nr(), r0, operandShiftImm(4), true) + m.insert(lsl) + + movv := m.allocateInstr() + movv.asMovToVec(v0.nr(), r0, vecArrangementD, vecIndex(1)) + m.insert(movv) + + // Lane-wise logical AND with the bitmask, meaning that we have + // v[i] = (1 << i) if vi<0, 0 otherwise for i=0..3 + // = (1 << (i+4)) if vi<0, 0 otherwise for i=3..7 + and := m.allocateInstr() + and.asVecRRR(vecOpAnd, v0.nr(), v1, v0, vecArrangement16B) + m.insert(and) + + addv := m.allocateInstr() + addv.asVecLanes(vecOpAddv, v0.nr(), v0, vecArrangement8H) + m.insert(addv) + + movfv := m.allocateInstr() + movfv.asMovFromVec(rd, v0, vecArrangementH, vecIndex(0), false) + m.insert(movfv) + case vecArrangement4S: + // sshr v6?.8h, v2?.8h, #15 + // movz x4?, #0x1, lsl 0 + // movk x4?, #0x2, lsl 16 + // movk x4?, #0x4, lsl 32 + // movk x4?, #0x8, lsl 48 + // dup v5?.2d, x4? + // lsl x4?, x4?, 0x4 + // ins v5?.d[1], x4? + // and v5?.16b, v6?.16b, v5?.16b + // addv s5?, v5?.8h + // umov s3?, v5?.h[0] + + // Right arithmetic shift on the original vector and store the result into v1. So we have: + // v[i] = 0xffffffff if vi<0, 0 otherwise. + sshr := m.allocateInstr() + sshr.asVecShiftImm(vecOpSshr, v1.nr(), rm, operandShiftImm(31), vecArrangement4S) + m.insert(sshr) + + // Load the bit mask into r0. + m.lowerConstantI64(r0.nr(), 0x0000000200000001) + + // dup r0 to vector v0. + dup := m.allocateInstr() + dup.asVecDup(v0.nr(), r0, vecArrangement2D) + m.insert(dup) + + lsl := m.allocateInstr() + lsl.asALUShift(aluOpLsl, r0.nr(), r0, operandShiftImm(2), true) + m.insert(lsl) + + movv := m.allocateInstr() + movv.asMovToVec(v0.nr(), r0, vecArrangementD, vecIndex(1)) + m.insert(movv) + + // Lane-wise logical AND with the bitmask, meaning that we have + // v[i] = (1 << i) if vi<0, 0 otherwise for i in [0, 1] + // = (1 << (i+4)) if vi<0, 0 otherwise for i in [2, 3] + and := m.allocateInstr() + and.asVecRRR(vecOpAnd, v0.nr(), v1, v0, vecArrangement16B) + m.insert(and) + + addv := m.allocateInstr() + addv.asVecLanes(vecOpAddv, v0.nr(), v0, vecArrangement4S) + m.insert(addv) + + movfv := m.allocateInstr() + movfv.asMovFromVec(rd, v0, vecArrangementS, vecIndex(0), false) + m.insert(movfv) + case vecArrangement2D: + // mov d3?, v2?.d[0] + // mov x4?, v2?.d[1] + // lsr x4?, x4?, 0x3f + // lsr d3?, d3?, 0x3f + // add s3?, s3?, w4?, lsl #1 + + // Move the lower 64-bit int into result. + movv0 := m.allocateInstr() + movv0.asMovFromVec(rd, rm, vecArrangementD, vecIndex(0), false) + m.insert(movv0) + + // Move the higher 64-bit int into r0. + movv1 := m.allocateInstr() + movv1.asMovFromVec(r0.nr(), rm, vecArrangementD, vecIndex(1), false) + m.insert(movv1) + + // Move the sign bit into the least significant bit. + lsr1 := m.allocateInstr() + lsr1.asALUShift(aluOpLsr, r0.nr(), r0, operandShiftImm(63), true) + m.insert(lsr1) + + lsr2 := m.allocateInstr() + lsr2.asALUShift(aluOpLsr, rd, operandNR(rd), operandShiftImm(63), true) + m.insert(lsr2) + + // rd = (r0<<1) | rd + lsl := m.allocateInstr() + lsl.asALU(aluOpAdd, rd, operandNR(rd), operandSR(r0.nr(), 1, shiftOpLSL), false) + m.insert(lsl) + default: + panic("Unsupported " + arr.String()) + } +} + +func (m *machine) lowerVecMisc(op vecOp, instr *ssa.Instruction) { + x, lane := instr.ArgWithLane() + arr := ssaLaneToArrangement(lane) + ins := m.allocateInstr() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + ins.asVecMisc(op, rd, rn, arr) + m.insert(ins) +} + +func (m *machine) lowerVecRRR(op vecOp, x, y, ret ssa.Value, arr vecArrangement) { + ins := m.allocateInstr() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(ret) + ins.asVecRRR(op, rd, rn, rm, arr) + m.insert(ins) +} + +func (m *machine) lowerVIMul(rd regalloc.VReg, rn, rm operand, arr vecArrangement) { + if arr != vecArrangement2D { + mul := m.allocateInstr() + mul.asVecRRR(vecOpMul, rd, rn, rm, arr) + m.insert(mul) + } else { + tmp1 := m.compiler.AllocateVReg(ssa.TypeV128) + tmp2 := m.compiler.AllocateVReg(ssa.TypeV128) + tmp3 := m.compiler.AllocateVReg(ssa.TypeV128) + + tmpRes := m.compiler.AllocateVReg(ssa.TypeV128) + + // Following the algorithm in https://chromium-review.googlesource.com/c/v8/v8/+/1781696 + rev64 := m.allocateInstr() + rev64.asVecMisc(vecOpRev64, tmp2, rm, vecArrangement4S) + m.insert(rev64) + + mul := m.allocateInstr() + mul.asVecRRR(vecOpMul, tmp2, operandNR(tmp2), rn, vecArrangement4S) + m.insert(mul) + + xtn1 := m.allocateInstr() + xtn1.asVecMisc(vecOpXtn, tmp1, rn, vecArrangement2S) + m.insert(xtn1) + + addp := m.allocateInstr() + addp.asVecRRR(vecOpAddp, tmp2, operandNR(tmp2), operandNR(tmp2), vecArrangement4S) + m.insert(addp) + + xtn2 := m.allocateInstr() + xtn2.asVecMisc(vecOpXtn, tmp3, rm, vecArrangement2S) + m.insert(xtn2) + + // Note: do not write the result directly into result yet. This is the same reason as in bsl. + // In short, in UMLAL instruction, the result register is also one of the source register, and + // the value on the result register is significant. + shll := m.allocateInstr() + shll.asVecMisc(vecOpShll, tmpRes, operandNR(tmp2), vecArrangement2S) + m.insert(shll) + + umlal := m.allocateInstr() + umlal.asVecRRRRewrite(vecOpUmlal, tmpRes, operandNR(tmp3), operandNR(tmp1), vecArrangement2S) + m.insert(umlal) + + mov := m.allocateInstr() + mov.asFpuMov128(rd, tmpRes) + m.insert(mov) + } +} + +func (m *machine) lowerVMinMaxPseudo(instr *ssa.Instruction, max bool) { + x, y, lane := instr.Arg2WithLane() + arr := ssaLaneToArrangement(lane) + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + + // Note: this usage of tmp is important. + // BSL modifies the destination register, so we need to use a temporary register so that + // the actual definition of the destination register happens *after* the BSL instruction. + // That way, we can force the spill instruction to be inserted after the BSL instruction. + tmp := m.compiler.AllocateVReg(ssa.TypeV128) + + fcmgt := m.allocateInstr() + if max { + fcmgt.asVecRRR(vecOpFcmgt, tmp, rm, rn, arr) + } else { + // If min, swap the args. + fcmgt.asVecRRR(vecOpFcmgt, tmp, rn, rm, arr) + } + m.insert(fcmgt) + + bsl := m.allocateInstr() + bsl.asVecRRRRewrite(vecOpBsl, tmp, rm, rn, vecArrangement16B) + m.insert(bsl) + + res := operandNR(m.compiler.VRegOf(instr.Return())) + mov2 := m.allocateInstr() + mov2.asFpuMov128(res.nr(), tmp) + m.insert(mov2) +} + +func (m *machine) lowerIRem(execCtxVReg regalloc.VReg, rd, rn regalloc.VReg, rm operand, _64bit, signed bool) { + div := m.allocateInstr() + + if signed { + div.asALU(aluOpSDiv, rd, operandNR(rn), rm, _64bit) + } else { + div.asALU(aluOpUDiv, rd, operandNR(rn), rm, _64bit) + } + m.insert(div) + + // Check if rm is zero: + m.exitIfNot(execCtxVReg, registerAsRegNotZeroCond(rm.nr()), _64bit, wazevoapi.ExitCodeIntegerDivisionByZero) + + // rd = rn-rd*rm by MSUB instruction. + msub := m.allocateInstr() + msub.asALURRRR(aluOpMSub, rd, operandNR(rd), rm, rn, _64bit) + m.insert(msub) +} + +func (m *machine) lowerIDiv(execCtxVReg, rd regalloc.VReg, rn, rm operand, _64bit, signed bool) { + div := m.allocateInstr() + + if signed { + div.asALU(aluOpSDiv, rd, rn, rm, _64bit) + } else { + div.asALU(aluOpUDiv, rd, rn, rm, _64bit) + } + m.insert(div) + + // Check if rm is zero: + m.exitIfNot(execCtxVReg, registerAsRegNotZeroCond(rm.nr()), _64bit, wazevoapi.ExitCodeIntegerDivisionByZero) + + if signed { + // We need to check the signed overflow which happens iff "math.MinInt{32,64} / -1" + minusOneCheck := m.allocateInstr() + // Sets eq condition if rm == -1. + minusOneCheck.asALU(aluOpAddS, xzrVReg, rm, operandImm12(1, 0), _64bit) + m.insert(minusOneCheck) + + ccmp := m.allocateInstr() + // If eq condition is set, sets the flag by the result based on "rn - 1", otherwise clears the flag. + ccmp.asCCmpImm(rn, 1, eq, 0, _64bit) + m.insert(ccmp) + + // Check the overflow flag. + m.exitIfNot(execCtxVReg, vs.invert().asCond(), false, wazevoapi.ExitCodeIntegerOverflow) + } +} + +// exitIfNot emits a conditional branch to exit if the condition is not met. +// If `c` (cond type) is a register, `cond64bit` must be chosen to indicate whether the register is 32-bit or 64-bit. +// Otherwise, `cond64bit` is ignored. +func (m *machine) exitIfNot(execCtxVReg regalloc.VReg, c cond, cond64bit bool, code wazevoapi.ExitCode) { + execCtxTmp := m.copyToTmp(execCtxVReg) + + cbr := m.allocateInstr() + m.insert(cbr) + m.lowerExitWithCode(execCtxTmp, code) + // Conditional branch target is after exit. + l := m.insertBrTargetLabel() + cbr.asCondBr(c, l, cond64bit) +} + +func (m *machine) lowerFcopysign(x, y, ret ssa.Value) { + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + var tmpI, tmpF regalloc.VReg + _64 := x.Type() == ssa.TypeF64 + if _64 { + tmpF = m.compiler.AllocateVReg(ssa.TypeF64) + tmpI = m.compiler.AllocateVReg(ssa.TypeI64) + } else { + tmpF = m.compiler.AllocateVReg(ssa.TypeF32) + tmpI = m.compiler.AllocateVReg(ssa.TypeI32) + } + rd := m.compiler.VRegOf(ret) + m.lowerFcopysignImpl(rd, rn, rm, tmpI, tmpF, _64) +} + +func (m *machine) lowerFcopysignImpl(rd regalloc.VReg, rn, rm operand, tmpI, tmpF regalloc.VReg, _64bit bool) { + // This is exactly the same code emitted by GCC for "__builtin_copysign": + // + // mov x0, -9223372036854775808 + // fmov d2, x0 + // vbit v0.8b, v1.8b, v2.8b + // + + setMSB := m.allocateInstr() + if _64bit { + m.lowerConstantI64(tmpI, math.MinInt64) + setMSB.asMovToVec(tmpF, operandNR(tmpI), vecArrangementD, vecIndex(0)) + } else { + m.lowerConstantI32(tmpI, math.MinInt32) + setMSB.asMovToVec(tmpF, operandNR(tmpI), vecArrangementS, vecIndex(0)) + } + m.insert(setMSB) + + tmpReg := m.compiler.AllocateVReg(ssa.TypeF64) + + mov := m.allocateInstr() + mov.asFpuMov64(tmpReg, rn.nr()) + m.insert(mov) + + vbit := m.allocateInstr() + vbit.asVecRRRRewrite(vecOpBit, tmpReg, rm, operandNR(tmpF), vecArrangement8B) + m.insert(vbit) + + movDst := m.allocateInstr() + movDst.asFpuMov64(rd, tmpReg) + m.insert(movDst) +} + +func (m *machine) lowerBitcast(instr *ssa.Instruction) { + v, dstType := instr.BitcastData() + srcType := v.Type() + rn := m.getOperand_NR(m.compiler.ValueDefinition(v), extModeNone) + rd := m.compiler.VRegOf(instr.Return()) + srcInt := srcType.IsInt() + dstInt := dstType.IsInt() + switch { + case srcInt && !dstInt: // Int to Float: + mov := m.allocateInstr() + var arr vecArrangement + if srcType.Bits() == 64 { + arr = vecArrangementD + } else { + arr = vecArrangementS + } + mov.asMovToVec(rd, rn, arr, vecIndex(0)) + m.insert(mov) + case !srcInt && dstInt: // Float to Int: + mov := m.allocateInstr() + var arr vecArrangement + if dstType.Bits() == 64 { + arr = vecArrangementD + } else { + arr = vecArrangementS + } + mov.asMovFromVec(rd, rn, arr, vecIndex(0), false) + m.insert(mov) + default: + panic("TODO?BUG?") + } +} + +func (m *machine) lowerFpuUniOp(op fpuUniOp, in, out ssa.Value) { + rn := m.getOperand_NR(m.compiler.ValueDefinition(in), extModeNone) + rd := m.compiler.VRegOf(out) + + neg := m.allocateInstr() + neg.asFpuRR(op, rd, rn, in.Type().Bits() == 64) + m.insert(neg) +} + +func (m *machine) lowerFpuToInt(rd regalloc.VReg, rn operand, ctx regalloc.VReg, signed, src64bit, dst64bit, nonTrapping bool) { + if !nonTrapping { + // First of all, we have to clear the FPU flags. + flagClear := m.allocateInstr() + flagClear.asMovToFPSR(xzrVReg) + m.insert(flagClear) + } + + // Then, do the conversion which doesn't trap inherently. + cvt := m.allocateInstr() + cvt.asFpuToInt(rd, rn, signed, src64bit, dst64bit) + m.insert(cvt) + + if !nonTrapping { + tmpReg := m.compiler.AllocateVReg(ssa.TypeI64) + + // After the conversion, check the FPU flags. + getFlag := m.allocateInstr() + getFlag.asMovFromFPSR(tmpReg) + m.insert(getFlag) + + execCtx := m.copyToTmp(ctx) + _rn := operandNR(m.copyToTmp(rn.nr())) + + // Check if the conversion was undefined by comparing the status with 1. + // See https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/FPSR--Floating-point-Status-Register + alu := m.allocateInstr() + alu.asALU(aluOpSubS, xzrVReg, operandNR(tmpReg), operandImm12(1, 0), true) + m.insert(alu) + + // If it is not undefined, we can return the result. + ok := m.allocateInstr() + m.insert(ok) + + // Otherwise, we have to choose the status depending on it is overflow or NaN conversion. + + // Comparing itself to check if it is a NaN. + fpuCmp := m.allocateInstr() + fpuCmp.asFpuCmp(_rn, _rn, src64bit) + m.insert(fpuCmp) + // If the VC flag is not set (== VS flag is set), it is a NaN. + m.exitIfNot(execCtx, vc.asCond(), false, wazevoapi.ExitCodeInvalidConversionToInteger) + // Otherwise, it is an overflow. + m.lowerExitWithCode(execCtx, wazevoapi.ExitCodeIntegerOverflow) + + // Conditional branch target is after exit. + l := m.insertBrTargetLabel() + ok.asCondBr(ne.asCond(), l, false /* ignored */) + } +} + +func (m *machine) lowerIntToFpu(rd regalloc.VReg, rn operand, signed, src64bit, dst64bit bool) { + cvt := m.allocateInstr() + cvt.asIntToFpu(rd, rn, signed, src64bit, dst64bit) + m.insert(cvt) +} + +func (m *machine) lowerFpuBinOp(si *ssa.Instruction) { + instr := m.allocateInstr() + var op fpuBinOp + switch si.Opcode() { + case ssa.OpcodeFadd: + op = fpuBinOpAdd + case ssa.OpcodeFsub: + op = fpuBinOpSub + case ssa.OpcodeFmul: + op = fpuBinOpMul + case ssa.OpcodeFdiv: + op = fpuBinOpDiv + case ssa.OpcodeFmax: + op = fpuBinOpMax + case ssa.OpcodeFmin: + op = fpuBinOpMin + } + x, y := si.Arg2() + xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y) + rn := m.getOperand_NR(xDef, extModeNone) + rm := m.getOperand_NR(yDef, extModeNone) + rd := m.compiler.VRegOf(si.Return()) + instr.asFpuRRR(op, rd, rn, rm, x.Type().Bits() == 64) + m.insert(instr) +} + +func (m *machine) lowerSubOrAdd(si *ssa.Instruction, add bool) { + x, y := si.Arg2() + if !x.Type().IsInt() { + panic("BUG?") + } + + xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y) + rn := m.getOperand_NR(xDef, extModeNone) + rm, yNegated := m.getOperand_MaybeNegatedImm12_ER_SR_NR(yDef, extModeNone) + + var aop aluOp + switch { + case add && !yNegated: // rn+rm = x+y + aop = aluOpAdd + case add && yNegated: // rn-rm = x-(-y) = x+y + aop = aluOpSub + case !add && !yNegated: // rn-rm = x-y + aop = aluOpSub + case !add && yNegated: // rn+rm = x-(-y) = x-y + aop = aluOpAdd + } + rd := m.compiler.VRegOf(si.Return()) + alu := m.allocateInstr() + alu.asALU(aop, rd, rn, rm, x.Type().Bits() == 64) + m.insert(alu) +} + +// InsertMove implements backend.Machine. +func (m *machine) InsertMove(dst, src regalloc.VReg, typ ssa.Type) { + instr := m.allocateInstr() + switch typ { + case ssa.TypeI32, ssa.TypeI64: + instr.asMove64(dst, src) + case ssa.TypeF32, ssa.TypeF64: + instr.asFpuMov64(dst, src) + case ssa.TypeV128: + instr.asFpuMov128(dst, src) + default: + panic("TODO") + } + m.insert(instr) +} + +func (m *machine) lowerIcmp(si *ssa.Instruction) { + x, y, c := si.IcmpData() + flag := condFlagFromSSAIntegerCmpCond(c) + + in64bit := x.Type().Bits() == 64 + var ext extMode + if in64bit { + if c.Signed() { + ext = extModeSignExtend64 + } else { + ext = extModeZeroExtend64 + } + } else { + if c.Signed() { + ext = extModeSignExtend32 + } else { + ext = extModeZeroExtend32 + } + } + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), ext) + rm := m.getOperand_Imm12_ER_SR_NR(m.compiler.ValueDefinition(y), ext) + alu := m.allocateInstr() + alu.asALU(aluOpSubS, xzrVReg, rn, rm, in64bit) + m.insert(alu) + + cset := m.allocateInstr() + cset.asCSet(m.compiler.VRegOf(si.Return()), false, flag) + m.insert(cset) +} + +func (m *machine) lowerVIcmp(si *ssa.Instruction) { + x, y, c, lane := si.VIcmpData() + flag := condFlagFromSSAIntegerCmpCond(c) + arr := ssaLaneToArrangement(lane) + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(si.Return()) + + switch flag { + case eq: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmeq, rd, rn, rm, arr) + m.insert(cmp) + case ne: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmeq, rd, rn, rm, arr) + m.insert(cmp) + not := m.allocateInstr() + not.asVecMisc(vecOpNot, rd, operandNR(rd), vecArrangement16B) + m.insert(not) + case ge: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmge, rd, rn, rm, arr) + m.insert(cmp) + case gt: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmgt, rd, rn, rm, arr) + m.insert(cmp) + case le: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmge, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + case lt: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmgt, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + case hs: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmhs, rd, rn, rm, arr) + m.insert(cmp) + case hi: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmhi, rd, rn, rm, arr) + m.insert(cmp) + case ls: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmhs, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + case lo: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpCmhi, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + } +} + +func (m *machine) lowerVFcmp(si *ssa.Instruction) { + x, y, c, lane := si.VFcmpData() + flag := condFlagFromSSAFloatCmpCond(c) + arr := ssaLaneToArrangement(lane) + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + rd := m.compiler.VRegOf(si.Return()) + + switch flag { + case eq: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmeq, rd, rn, rm, arr) + m.insert(cmp) + case ne: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmeq, rd, rn, rm, arr) + m.insert(cmp) + not := m.allocateInstr() + not.asVecMisc(vecOpNot, rd, operandNR(rd), vecArrangement16B) + m.insert(not) + case ge: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmge, rd, rn, rm, arr) + m.insert(cmp) + case gt: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmgt, rd, rn, rm, arr) + m.insert(cmp) + case mi: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmgt, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + case ls: + cmp := m.allocateInstr() + cmp.asVecRRR(vecOpFcmge, rd, rm, rn, arr) // rm, rn are swapped + m.insert(cmp) + } +} + +func (m *machine) lowerVfpuToInt(rd regalloc.VReg, rn operand, arr vecArrangement, signed bool) { + cvt := m.allocateInstr() + if signed { + cvt.asVecMisc(vecOpFcvtzs, rd, rn, arr) + } else { + cvt.asVecMisc(vecOpFcvtzu, rd, rn, arr) + } + m.insert(cvt) + + if arr == vecArrangement2D { + narrow := m.allocateInstr() + if signed { + narrow.asVecMisc(vecOpSqxtn, rd, operandNR(rd), vecArrangement2S) + } else { + narrow.asVecMisc(vecOpUqxtn, rd, operandNR(rd), vecArrangement2S) + } + m.insert(narrow) + } +} + +func (m *machine) lowerVfpuFromInt(rd regalloc.VReg, rn operand, arr vecArrangement, signed bool) { + cvt := m.allocateInstr() + if signed { + cvt.asVecMisc(vecOpScvtf, rd, rn, arr) + } else { + cvt.asVecMisc(vecOpUcvtf, rd, rn, arr) + } + m.insert(cvt) +} + +func (m *machine) lowerShifts(si *ssa.Instruction, ext extMode, aluOp aluOp) { + x, amount := si.Arg2() + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), ext) + rm := m.getOperand_ShiftImm_NR(m.compiler.ValueDefinition(amount), ext, x.Type().Bits()) + rd := m.compiler.VRegOf(si.Return()) + + alu := m.allocateInstr() + alu.asALUShift(aluOp, rd, rn, rm, x.Type().Bits() == 64) + m.insert(alu) +} + +func (m *machine) lowerBitwiseAluOp(si *ssa.Instruction, op aluOp, ignoreResult bool) { + x, y := si.Arg2() + + xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y) + rn := m.getOperand_NR(xDef, extModeNone) + + var rd regalloc.VReg + if ignoreResult { + rd = xzrVReg + } else { + rd = m.compiler.VRegOf(si.Return()) + } + + _64 := x.Type().Bits() == 64 + alu := m.allocateInstr() + if instr := yDef.Instr; instr != nil && instr.Constant() { + c := instr.ConstantVal() + if isBitMaskImmediate(c, _64) { + // Constant bit wise operations can be lowered to a single instruction. + alu.asALUBitmaskImm(op, rd, rn.nr(), c, _64) + m.insert(alu) + return + } + } + + rm := m.getOperand_SR_NR(yDef, extModeNone) + alu.asALU(op, rd, rn, rm, _64) + m.insert(alu) +} + +func (m *machine) lowerRotl(si *ssa.Instruction) { + x, y := si.Arg2() + r := si.Return() + _64 := r.Type().Bits() == 64 + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + var tmp regalloc.VReg + if _64 { + tmp = m.compiler.AllocateVReg(ssa.TypeI64) + } else { + tmp = m.compiler.AllocateVReg(ssa.TypeI32) + } + rd := m.compiler.VRegOf(r) + + // Encode rotl as neg + rotr: neg is a sub against the zero-reg. + m.lowerRotlImpl(rd, rn, rm, tmp, _64) +} + +func (m *machine) lowerRotlImpl(rd regalloc.VReg, rn, rm operand, tmp regalloc.VReg, is64bit bool) { + // Encode rotl as neg + rotr: neg is a sub against the zero-reg. + neg := m.allocateInstr() + neg.asALU(aluOpSub, tmp, operandNR(xzrVReg), rm, is64bit) + m.insert(neg) + alu := m.allocateInstr() + alu.asALU(aluOpRotR, rd, rn, operandNR(tmp), is64bit) + m.insert(alu) +} + +func (m *machine) lowerRotr(si *ssa.Instruction) { + x, y := si.Arg2() + + xDef, yDef := m.compiler.ValueDefinition(x), m.compiler.ValueDefinition(y) + rn := m.getOperand_NR(xDef, extModeNone) + rm := m.getOperand_NR(yDef, extModeNone) + rd := m.compiler.VRegOf(si.Return()) + + alu := m.allocateInstr() + alu.asALU(aluOpRotR, rd, rn, rm, si.Return().Type().Bits() == 64) + m.insert(alu) +} + +func (m *machine) lowerExtend(arg, ret ssa.Value, from, to byte, signed bool) { + rd := m.compiler.VRegOf(ret) + def := m.compiler.ValueDefinition(arg) + + if instr := def.Instr; !signed && from == 32 && instr != nil { + // We can optimize out the unsigned extend because: + // Writes to the W register set bits [63:32] of the X register to zero + // https://developer.arm.com/documentation/den0024/a/An-Introduction-to-the-ARMv8-Instruction-Sets/The-ARMv8-instruction-sets/Distinguishing-between-32-bit-and-64-bit-A64-instructions + switch instr.Opcode() { + case + ssa.OpcodeIadd, ssa.OpcodeIsub, ssa.OpcodeLoad, + ssa.OpcodeBand, ssa.OpcodeBor, ssa.OpcodeBnot, + ssa.OpcodeIshl, ssa.OpcodeUshr, ssa.OpcodeSshr, + ssa.OpcodeRotl, ssa.OpcodeRotr, + ssa.OpcodeUload8, ssa.OpcodeUload16, ssa.OpcodeUload32: + // So, if the argument is the result of a 32-bit operation, we can just copy the register. + // It is highly likely that this copy will be optimized out after register allocation. + rn := m.compiler.VRegOf(arg) + mov := m.allocateInstr() + // Note: do not use move32 as it will be lowered to a 32-bit move, which is not copy (that is actually the impl of UExtend). + mov.asMove64(rd, rn) + m.insert(mov) + return + default: + } + } + rn := m.getOperand_NR(def, extModeNone) + + ext := m.allocateInstr() + ext.asExtend(rd, rn.nr(), from, to, signed) + m.insert(ext) +} + +func (m *machine) lowerFcmp(x, y, result ssa.Value, c ssa.FloatCmpCond) { + rn, rm := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone), m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + + fc := m.allocateInstr() + fc.asFpuCmp(rn, rm, x.Type().Bits() == 64) + m.insert(fc) + + cset := m.allocateInstr() + cset.asCSet(m.compiler.VRegOf(result), false, condFlagFromSSAFloatCmpCond(c)) + m.insert(cset) +} + +func (m *machine) lowerImul(x, y, result ssa.Value) { + rd := m.compiler.VRegOf(result) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + + // TODO: if this comes before Add/Sub, we could merge it by putting it into the place of xzrVReg. + + mul := m.allocateInstr() + mul.asALURRRR(aluOpMAdd, rd, rn, rm, xzrVReg, x.Type().Bits() == 64) + m.insert(mul) +} + +func (m *machine) lowerClz(x, result ssa.Value) { + rd := m.compiler.VRegOf(result) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + clz := m.allocateInstr() + clz.asBitRR(bitOpClz, rd, rn.nr(), x.Type().Bits() == 64) + m.insert(clz) +} + +func (m *machine) lowerCtz(x, result ssa.Value) { + rd := m.compiler.VRegOf(result) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rbit := m.allocateInstr() + _64 := x.Type().Bits() == 64 + var tmpReg regalloc.VReg + if _64 { + tmpReg = m.compiler.AllocateVReg(ssa.TypeI64) + } else { + tmpReg = m.compiler.AllocateVReg(ssa.TypeI32) + } + rbit.asBitRR(bitOpRbit, tmpReg, rn.nr(), _64) + m.insert(rbit) + + clz := m.allocateInstr() + clz.asBitRR(bitOpClz, rd, tmpReg, _64) + m.insert(clz) +} + +func (m *machine) lowerPopcnt(x, result ssa.Value) { + // arm64 doesn't have an instruction for population count on scalar register, + // so we use the vector instruction `cnt`. + // This is exactly what the official Go implements bits.OneCount. + // For example, "func () int { return bits.OneCount(10) }" is compiled as + // + // MOVD $10, R0 ;; Load 10. + // FMOVD R0, F0 + // VCNT V0.B8, V0.B8 + // UADDLV V0.B8, V0 + // + // In aarch64 asm, FMOVD is encoded as `ins`, VCNT is `cnt`, + // and the registers may use different names. In our encoding we use the following + // instructions: + // + // ins v0.d[0], x0 ;; mov from GPR to vec (FMOV above) is encoded as INS + // cnt v0.16b, v0.16b ;; we use vec arrangement 16b + // uaddlv h0, v0.8b ;; h0 is still v0 with the dest width specifier 'H', implied when src arrangement is 8b + // mov x5, v0.d[0] ;; finally we mov the result back to a GPR + // + + rd := m.compiler.VRegOf(result) + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + + rf1 := operandNR(m.compiler.AllocateVReg(ssa.TypeF64)) + ins := m.allocateInstr() + ins.asMovToVec(rf1.nr(), rn, vecArrangementD, vecIndex(0)) + m.insert(ins) + + rf2 := operandNR(m.compiler.AllocateVReg(ssa.TypeF64)) + cnt := m.allocateInstr() + cnt.asVecMisc(vecOpCnt, rf2.nr(), rf1, vecArrangement16B) + m.insert(cnt) + + rf3 := operandNR(m.compiler.AllocateVReg(ssa.TypeF64)) + uaddlv := m.allocateInstr() + uaddlv.asVecLanes(vecOpUaddlv, rf3.nr(), rf2, vecArrangement8B) + m.insert(uaddlv) + + mov := m.allocateInstr() + mov.asMovFromVec(rd, rf3, vecArrangementD, vecIndex(0), false) + m.insert(mov) +} + +// lowerExitWithCode lowers the lowerExitWithCode takes a context pointer as argument. +func (m *machine) lowerExitWithCode(execCtxVReg regalloc.VReg, code wazevoapi.ExitCode) { + tmpReg1 := m.compiler.AllocateVReg(ssa.TypeI32) + loadExitCodeConst := m.allocateInstr() + loadExitCodeConst.asMOVZ(tmpReg1, uint64(code), 0, true) + + setExitCode := m.allocateInstr() + mode := m.amodePool.Allocate() + *mode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: execCtxVReg, imm: wazevoapi.ExecutionContextOffsetExitCodeOffset.I64(), + } + setExitCode.asStore(operandNR(tmpReg1), mode, 32) + + // In order to unwind the stack, we also need to push the current stack pointer: + tmp2 := m.compiler.AllocateVReg(ssa.TypeI64) + movSpToTmp := m.allocateInstr() + movSpToTmp.asMove64(tmp2, spVReg) + strSpToExecCtx := m.allocateInstr() + mode2 := m.amodePool.Allocate() + *mode2 = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: execCtxVReg, imm: wazevoapi.ExecutionContextOffsetStackPointerBeforeGoCall.I64(), + } + strSpToExecCtx.asStore(operandNR(tmp2), mode2, 64) + // Also the address of this exit. + tmp3 := m.compiler.AllocateVReg(ssa.TypeI64) + currentAddrToTmp := m.allocateInstr() + currentAddrToTmp.asAdr(tmp3, 0) + storeCurrentAddrToExecCtx := m.allocateInstr() + mode3 := m.amodePool.Allocate() + *mode3 = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: execCtxVReg, imm: wazevoapi.ExecutionContextOffsetGoCallReturnAddress.I64(), + } + storeCurrentAddrToExecCtx.asStore(operandNR(tmp3), mode3, 64) + + exitSeq := m.allocateInstr() + exitSeq.asExitSequence(execCtxVReg) + + m.insert(loadExitCodeConst) + m.insert(setExitCode) + m.insert(movSpToTmp) + m.insert(strSpToExecCtx) + m.insert(currentAddrToTmp) + m.insert(storeCurrentAddrToExecCtx) + m.insert(exitSeq) +} + +func (m *machine) lowerIcmpToFlag(x, y ssa.Value, signed bool) { + if x.Type() != y.Type() { + panic( + fmt.Sprintf("TODO(maybe): support icmp with different types: v%d=%s != v%d=%s", + x.ID(), x.Type(), y.ID(), y.Type())) + } + + extMod := extModeOf(x.Type(), signed) + + // First operand must be in pure register form. + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extMod) + // Second operand can be in any of Imm12, ER, SR, or NR form supported by the SUBS instructions. + rm := m.getOperand_Imm12_ER_SR_NR(m.compiler.ValueDefinition(y), extMod) + + alu := m.allocateInstr() + // subs zr, rn, rm + alu.asALU( + aluOpSubS, + // We don't need the result, just need to set flags. + xzrVReg, + rn, + rm, + x.Type().Bits() == 64, + ) + m.insert(alu) +} + +func (m *machine) lowerFcmpToFlag(x, y ssa.Value) { + if x.Type() != y.Type() { + panic("TODO(maybe): support icmp with different types") + } + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + cmp := m.allocateInstr() + cmp.asFpuCmp(rn, rm, x.Type().Bits() == 64) + m.insert(cmp) +} + +func (m *machine) lowerExitIfTrueWithCode(execCtxVReg regalloc.VReg, cond ssa.Value, code wazevoapi.ExitCode) { + condDef := m.compiler.ValueDefinition(cond) + if !m.compiler.MatchInstr(condDef, ssa.OpcodeIcmp) { + panic("TODO: OpcodeExitIfTrueWithCode must come after Icmp at the moment: " + condDef.Instr.Opcode().String()) + } + condDef.Instr.MarkLowered() + + cvalInstr := condDef.Instr + x, y, c := cvalInstr.IcmpData() + signed := c.Signed() + + if !m.tryLowerBandToFlag(x, y) { + m.lowerIcmpToFlag(x, y, signed) + } + + // We need to copy the execution context to a temp register, because if it's spilled, + // it might end up being reloaded inside the exiting branch. + execCtxTmp := m.copyToTmp(execCtxVReg) + + // We have to skip the entire exit sequence if the condition is false. + cbr := m.allocateInstr() + m.insert(cbr) + m.lowerExitWithCode(execCtxTmp, code) + // conditional branch target is after exit. + l := m.insertBrTargetLabel() + cbr.asCondBr(condFlagFromSSAIntegerCmpCond(c).invert().asCond(), l, false /* ignored */) +} + +func (m *machine) lowerSelect(c, x, y, result ssa.Value) { + cvalDef := m.compiler.ValueDefinition(c) + + var cc condFlag + switch { + case m.compiler.MatchInstr(cvalDef, ssa.OpcodeIcmp): // This case, we can use the ALU flag set by SUBS instruction. + cvalInstr := cvalDef.Instr + x, y, c := cvalInstr.IcmpData() + cc = condFlagFromSSAIntegerCmpCond(c) + m.lowerIcmpToFlag(x, y, c.Signed()) + cvalDef.Instr.MarkLowered() + case m.compiler.MatchInstr(cvalDef, ssa.OpcodeFcmp): // This case we can use the Fpu flag directly. + cvalInstr := cvalDef.Instr + x, y, c := cvalInstr.FcmpData() + cc = condFlagFromSSAFloatCmpCond(c) + m.lowerFcmpToFlag(x, y) + cvalDef.Instr.MarkLowered() + default: + rn := m.getOperand_NR(cvalDef, extModeNone) + if c.Type() != ssa.TypeI32 && c.Type() != ssa.TypeI64 { + panic("TODO?BUG?: support select with non-integer condition") + } + alu := m.allocateInstr() + // subs zr, rn, zr + alu.asALU( + aluOpSubS, + // We don't need the result, just need to set flags. + xzrVReg, + rn, + operandNR(xzrVReg), + c.Type().Bits() == 64, + ) + m.insert(alu) + cc = ne + } + + rn := m.getOperand_NR(m.compiler.ValueDefinition(x), extModeNone) + rm := m.getOperand_NR(m.compiler.ValueDefinition(y), extModeNone) + + rd := m.compiler.VRegOf(result) + switch x.Type() { + case ssa.TypeI32, ssa.TypeI64: + // csel rd, rn, rm, cc + csel := m.allocateInstr() + csel.asCSel(rd, rn, rm, cc, x.Type().Bits() == 64) + m.insert(csel) + case ssa.TypeF32, ssa.TypeF64: + // fcsel rd, rn, rm, cc + fcsel := m.allocateInstr() + fcsel.asFpuCSel(rd, rn, rm, cc, x.Type().Bits() == 64) + m.insert(fcsel) + default: + panic("BUG") + } +} + +func (m *machine) lowerSelectVec(rc, rn, rm operand, rd regalloc.VReg) { + // First check if `rc` is zero or not. + checkZero := m.allocateInstr() + checkZero.asALU(aluOpSubS, xzrVReg, rc, operandNR(xzrVReg), false) + m.insert(checkZero) + + // Then use CSETM to set all bits to one if `rc` is zero. + allOnesOrZero := m.compiler.AllocateVReg(ssa.TypeI64) + cset := m.allocateInstr() + cset.asCSet(allOnesOrZero, true, ne) + m.insert(cset) + + // Then move the bits to the result vector register. + tmp2 := m.compiler.AllocateVReg(ssa.TypeV128) + dup := m.allocateInstr() + dup.asVecDup(tmp2, operandNR(allOnesOrZero), vecArrangement2D) + m.insert(dup) + + // Now that `tmp2` has either all bits one or zero depending on `rc`, + // we can use bsl to select between `rn` and `rm`. + ins := m.allocateInstr() + ins.asVecRRRRewrite(vecOpBsl, tmp2, rn, rm, vecArrangement16B) + m.insert(ins) + + // Finally, move the result to the destination register. + mov2 := m.allocateInstr() + mov2.asFpuMov128(rd, tmp2) + m.insert(mov2) +} + +func (m *machine) lowerAtomicRmw(si *ssa.Instruction) { + ssaOp, size := si.AtomicRmwData() + + var op atomicRmwOp + var negateArg bool + var flipArg bool + switch ssaOp { + case ssa.AtomicRmwOpAdd: + op = atomicRmwOpAdd + case ssa.AtomicRmwOpSub: + op = atomicRmwOpAdd + negateArg = true + case ssa.AtomicRmwOpAnd: + op = atomicRmwOpClr + flipArg = true + case ssa.AtomicRmwOpOr: + op = atomicRmwOpSet + case ssa.AtomicRmwOpXor: + op = atomicRmwOpEor + case ssa.AtomicRmwOpXchg: + op = atomicRmwOpSwp + default: + panic(fmt.Sprintf("unknown ssa atomic rmw op: %s", ssaOp)) + } + + addr, val := si.Arg2() + addrDef, valDef := m.compiler.ValueDefinition(addr), m.compiler.ValueDefinition(val) + rn := m.getOperand_NR(addrDef, extModeNone) + rt := m.compiler.VRegOf(si.Return()) + rs := m.getOperand_NR(valDef, extModeNone) + + _64 := si.Return().Type().Bits() == 64 + var tmp regalloc.VReg + if _64 { + tmp = m.compiler.AllocateVReg(ssa.TypeI64) + } else { + tmp = m.compiler.AllocateVReg(ssa.TypeI32) + } + m.lowerAtomicRmwImpl(op, rn.nr(), rs.nr(), rt, tmp, size, negateArg, flipArg, _64) +} + +func (m *machine) lowerAtomicRmwImpl(op atomicRmwOp, rn, rs, rt, tmp regalloc.VReg, size uint64, negateArg, flipArg, dst64bit bool) { + switch { + case negateArg: + neg := m.allocateInstr() + neg.asALU(aluOpSub, tmp, operandNR(xzrVReg), operandNR(rs), dst64bit) + m.insert(neg) + case flipArg: + flip := m.allocateInstr() + flip.asALU(aluOpOrn, tmp, operandNR(xzrVReg), operandNR(rs), dst64bit) + m.insert(flip) + default: + tmp = rs + } + + rmw := m.allocateInstr() + rmw.asAtomicRmw(op, rn, tmp, rt, size) + m.insert(rmw) +} + +func (m *machine) lowerAtomicCas(si *ssa.Instruction) { + addr, exp, repl := si.Arg3() + size := si.AtomicTargetSize() + + addrDef, expDef, replDef := m.compiler.ValueDefinition(addr), m.compiler.ValueDefinition(exp), m.compiler.ValueDefinition(repl) + rn := m.getOperand_NR(addrDef, extModeNone) + rt := m.getOperand_NR(replDef, extModeNone) + rs := m.getOperand_NR(expDef, extModeNone) + tmp := m.compiler.AllocateVReg(si.Return().Type()) + + _64 := si.Return().Type().Bits() == 64 + // rs is overwritten by CAS, so we need to move it to the result register before the instruction + // in case when it is used somewhere else. + mov := m.allocateInstr() + if _64 { + mov.asMove64(tmp, rs.nr()) + } else { + mov.asMove32(tmp, rs.nr()) + } + m.insert(mov) + + m.lowerAtomicCasImpl(rn.nr(), tmp, rt.nr(), size) + + mov2 := m.allocateInstr() + rd := m.compiler.VRegOf(si.Return()) + if _64 { + mov2.asMove64(rd, tmp) + } else { + mov2.asMove32(rd, tmp) + } + m.insert(mov2) +} + +func (m *machine) lowerAtomicCasImpl(rn, rs, rt regalloc.VReg, size uint64) { + cas := m.allocateInstr() + cas.asAtomicCas(rn, rs, rt, size) + m.insert(cas) +} + +func (m *machine) lowerAtomicLoad(si *ssa.Instruction) { + addr := si.Arg() + size := si.AtomicTargetSize() + + addrDef := m.compiler.ValueDefinition(addr) + rn := m.getOperand_NR(addrDef, extModeNone) + rt := m.compiler.VRegOf(si.Return()) + + m.lowerAtomicLoadImpl(rn.nr(), rt, size) +} + +func (m *machine) lowerAtomicLoadImpl(rn, rt regalloc.VReg, size uint64) { + ld := m.allocateInstr() + ld.asAtomicLoad(rn, rt, size) + m.insert(ld) +} + +func (m *machine) lowerAtomicStore(si *ssa.Instruction) { + addr, val := si.Arg2() + size := si.AtomicTargetSize() + + addrDef := m.compiler.ValueDefinition(addr) + valDef := m.compiler.ValueDefinition(val) + rn := m.getOperand_NR(addrDef, extModeNone) + rt := m.getOperand_NR(valDef, extModeNone) + + m.lowerAtomicStoreImpl(rn, rt, size) +} + +func (m *machine) lowerAtomicStoreImpl(rn, rt operand, size uint64) { + ld := m.allocateInstr() + ld.asAtomicStore(rn, rt, size) + m.insert(ld) +} + +// copyToTmp copies the given regalloc.VReg to a temporary register. This is called before cbr to avoid the regalloc issue +// e.g. reload happening in the middle of the exit sequence which is not the path the normal path executes +func (m *machine) copyToTmp(v regalloc.VReg) regalloc.VReg { + typ := m.compiler.TypeOf(v) + mov := m.allocateInstr() + tmp := m.compiler.AllocateVReg(typ) + if typ.IsInt() { + mov.asMove64(tmp, v) + } else { + mov.asFpuMov128(tmp, v) + } + m.insert(mov) + return tmp +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go new file mode 100644 index 00000000..7a398c3d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_instr_operands.go @@ -0,0 +1,340 @@ +package arm64 + +// This file contains the logic to "find and determine operands" for instructions. +// In order to finalize the form of an operand, we might end up merging/eliminating +// the source instructions into an operand whenever possible. + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +type ( + // operand represents an operand of an instruction whose type is determined by the kind. + operand struct { + kind operandKind + data, data2 uint64 + } + operandKind byte +) + +// Here's the list of operand kinds. We use the abbreviation of the kind name not only for these consts, +// but also names of functions which return the operand of the kind. +const ( + // operandKindNR represents "NormalRegister" (NR). This is literally the register without any special operation unlike others. + operandKindNR operandKind = iota + // operandKindSR represents "Shifted Register" (SR). This is a register which is shifted by a constant. + // Some of the arm64 instructions can take this kind of operand. + operandKindSR + // operandKindER represents "Extended Register (ER). This is a register which is sign/zero-extended to a larger size. + // Some of the arm64 instructions can take this kind of operand. + operandKindER + // operandKindImm12 represents "Immediate 12" (Imm12). This is a 12-bit immediate value which can be either shifted by 12 or not. + // See asImm12 function for detail. + operandKindImm12 + // operandKindShiftImm represents "Shifted Immediate" (ShiftImm) used by shift operations. + operandKindShiftImm +) + +// String implements fmt.Stringer for debugging. +func (o operand) format(size byte) string { + switch o.kind { + case operandKindNR: + return formatVRegSized(o.nr(), size) + case operandKindSR: + r, amt, sop := o.sr() + return fmt.Sprintf("%s, %s #%d", formatVRegSized(r, size), sop, amt) + case operandKindER: + r, eop, _ := o.er() + return fmt.Sprintf("%s %s", formatVRegSized(r, size), eop) + case operandKindImm12: + imm12, shiftBit := o.imm12() + if shiftBit == 1 { + return fmt.Sprintf("#%#x", uint64(imm12)<<12) + } else { + return fmt.Sprintf("#%#x", imm12) + } + default: + panic(fmt.Sprintf("unknown operand kind: %d", o.kind)) + } +} + +// operandNR encodes the given VReg as an operand of operandKindNR. +func operandNR(r regalloc.VReg) operand { + return operand{kind: operandKindNR, data: uint64(r)} +} + +// nr decodes the underlying VReg assuming the operand is of operandKindNR. +func (o operand) nr() regalloc.VReg { + return regalloc.VReg(o.data) +} + +// operandER encodes the given VReg as an operand of operandKindER. +func operandER(r regalloc.VReg, eop extendOp, to byte) operand { + if to < 32 { + panic("TODO?BUG?: when we need to extend to less than 32 bits?") + } + return operand{kind: operandKindER, data: uint64(r), data2: uint64(eop)<<32 | uint64(to)} +} + +// er decodes the underlying VReg, extend operation, and the target size assuming the operand is of operandKindER. +func (o operand) er() (r regalloc.VReg, eop extendOp, to byte) { + return regalloc.VReg(o.data), extendOp(o.data2>>32) & 0xff, byte(o.data2 & 0xff) +} + +// operandSR encodes the given VReg as an operand of operandKindSR. +func operandSR(r regalloc.VReg, amt byte, sop shiftOp) operand { + return operand{kind: operandKindSR, data: uint64(r), data2: uint64(amt)<<32 | uint64(sop)} +} + +// sr decodes the underlying VReg, shift amount, and shift operation assuming the operand is of operandKindSR. +func (o operand) sr() (r regalloc.VReg, amt byte, sop shiftOp) { + return regalloc.VReg(o.data), byte(o.data2>>32) & 0xff, shiftOp(o.data2) & 0xff +} + +// operandImm12 encodes the given imm12 as an operand of operandKindImm12. +func operandImm12(imm12 uint16, shiftBit byte) operand { + return operand{kind: operandKindImm12, data: uint64(imm12) | uint64(shiftBit)<<32} +} + +// imm12 decodes the underlying imm12 data assuming the operand is of operandKindImm12. +func (o operand) imm12() (v uint16, shiftBit byte) { + return uint16(o.data), byte(o.data >> 32) +} + +// operandShiftImm encodes the given amount as an operand of operandKindShiftImm. +func operandShiftImm(amount byte) operand { + return operand{kind: operandKindShiftImm, data: uint64(amount)} +} + +// shiftImm decodes the underlying shift amount data assuming the operand is of operandKindShiftImm. +func (o operand) shiftImm() byte { + return byte(o.data) +} + +// reg returns the register of the operand if applicable. +func (o operand) reg() regalloc.VReg { + switch o.kind { + case operandKindNR: + return o.nr() + case operandKindSR: + r, _, _ := o.sr() + return r + case operandKindER: + r, _, _ := o.er() + return r + case operandKindImm12: + // Does not have a register. + case operandKindShiftImm: + // Does not have a register. + default: + panic(o.kind) + } + return regalloc.VRegInvalid +} + +func (o operand) realReg() regalloc.RealReg { + return o.nr().RealReg() +} + +func (o operand) assignReg(v regalloc.VReg) operand { + switch o.kind { + case operandKindNR: + return operandNR(v) + case operandKindSR: + _, amt, sop := o.sr() + return operandSR(v, amt, sop) + case operandKindER: + _, eop, to := o.er() + return operandER(v, eop, to) + case operandKindImm12: + // Does not have a register. + case operandKindShiftImm: + // Does not have a register. + } + panic(o.kind) +} + +// ensureValueNR returns an operand of either operandKindER, operandKindSR, or operandKindNR from the given value (defined by `def). +// +// `mode` is used to extend the operand if the bit length is smaller than mode.bits(). +// If the operand can be expressed as operandKindImm12, `mode` is ignored. +func (m *machine) getOperand_Imm12_ER_SR_NR(def backend.SSAValueDefinition, mode extMode) (op operand) { + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) + } + + instr := def.Instr + if instr.Opcode() == ssa.OpcodeIconst { + if imm12Op, ok := asImm12Operand(instr.ConstantVal()); ok { + instr.MarkLowered() + return imm12Op + } + } + return m.getOperand_ER_SR_NR(def, mode) +} + +// getOperand_MaybeNegatedImm12_ER_SR_NR is almost the same as getOperand_Imm12_ER_SR_NR, but this might negate the immediate value. +// If the immediate value is negated, the second return value is true, otherwise always false. +func (m *machine) getOperand_MaybeNegatedImm12_ER_SR_NR(def backend.SSAValueDefinition, mode extMode) (op operand, negatedImm12 bool) { + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)), false + } + + instr := def.Instr + if instr.Opcode() == ssa.OpcodeIconst { + c := instr.ConstantVal() + if imm12Op, ok := asImm12Operand(c); ok { + instr.MarkLowered() + return imm12Op, false + } + + signExtended := int64(c) + if def.V.Type().Bits() == 32 { + signExtended = (signExtended << 32) >> 32 + } + negatedWithoutSign := -signExtended + if imm12Op, ok := asImm12Operand(uint64(negatedWithoutSign)); ok { + instr.MarkLowered() + return imm12Op, true + } + } + return m.getOperand_ER_SR_NR(def, mode), false +} + +// ensureValueNR returns an operand of either operandKindER, operandKindSR, or operandKindNR from the given value (defined by `def). +// +// `mode` is used to extend the operand if the bit length is smaller than mode.bits(). +func (m *machine) getOperand_ER_SR_NR(def backend.SSAValueDefinition, mode extMode) (op operand) { + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) + } + + if m.compiler.MatchInstr(def, ssa.OpcodeSExtend) || m.compiler.MatchInstr(def, ssa.OpcodeUExtend) { + extInstr := def.Instr + + signed := extInstr.Opcode() == ssa.OpcodeSExtend + innerExtFromBits, innerExtToBits := extInstr.ExtendFromToBits() + modeBits, modeSigned := mode.bits(), mode.signed() + if mode == extModeNone || innerExtToBits == modeBits { + eop := extendOpFrom(signed, innerExtFromBits) + extArg := m.getOperand_NR(m.compiler.ValueDefinition(extInstr.Arg()), extModeNone) + op = operandER(extArg.nr(), eop, innerExtToBits) + extInstr.MarkLowered() + return + } + + if innerExtToBits > modeBits { + panic("BUG?TODO?: need the results of inner extension to be larger than the mode") + } + + switch { + case (!signed && !modeSigned) || (signed && modeSigned): + // Two sign/zero extensions are equivalent to one sign/zero extension for the larger size. + eop := extendOpFrom(modeSigned, innerExtFromBits) + op = operandER(m.compiler.VRegOf(extInstr.Arg()), eop, modeBits) + extInstr.MarkLowered() + case (signed && !modeSigned) || (!signed && modeSigned): + // We need to {sign, zero}-extend the result of the {zero,sign} extension. + eop := extendOpFrom(modeSigned, innerExtToBits) + op = operandER(m.compiler.VRegOf(extInstr.Return()), eop, modeBits) + // Note that we failed to merge the inner extension instruction this case. + } + return + } + return m.getOperand_SR_NR(def, mode) +} + +// ensureValueNR returns an operand of either operandKindSR or operandKindNR from the given value (defined by `def). +// +// `mode` is used to extend the operand if the bit length is smaller than mode.bits(). +func (m *machine) getOperand_SR_NR(def backend.SSAValueDefinition, mode extMode) (op operand) { + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) + } + + if m.compiler.MatchInstr(def, ssa.OpcodeIshl) { + // Check if the shift amount is constant instruction. + targetVal, amountVal := def.Instr.Arg2() + targetVReg := m.getOperand_NR(m.compiler.ValueDefinition(targetVal), extModeNone).nr() + amountDef := m.compiler.ValueDefinition(amountVal) + if amountDef.IsFromInstr() && amountDef.Instr.Constant() { + // If that is the case, we can use the shifted register operand (SR). + c := byte(amountDef.Instr.ConstantVal()) & (targetVal.Type().Bits() - 1) // Clears the unnecessary bits. + def.Instr.MarkLowered() + amountDef.Instr.MarkLowered() + return operandSR(targetVReg, c, shiftOpLSL) + } + } + return m.getOperand_NR(def, mode) +} + +// getOperand_ShiftImm_NR returns an operand of either operandKindShiftImm or operandKindNR from the given value (defined by `def). +func (m *machine) getOperand_ShiftImm_NR(def backend.SSAValueDefinition, mode extMode, shiftBitWidth byte) (op operand) { + if !def.IsFromInstr() { + return operandNR(m.compiler.VRegOf(def.V)) + } + + instr := def.Instr + if instr.Constant() { + amount := byte(instr.ConstantVal()) & (shiftBitWidth - 1) // Clears the unnecessary bits. + return operandShiftImm(amount) + } + return m.getOperand_NR(def, mode) +} + +// ensureValueNR returns an operand of operandKindNR from the given value (defined by `def). +// +// `mode` is used to extend the operand if the bit length is smaller than mode.bits(). +func (m *machine) getOperand_NR(def backend.SSAValueDefinition, mode extMode) (op operand) { + var v regalloc.VReg + if def.IsFromInstr() && def.Instr.Constant() { + // We inline all the constant instructions so that we could reduce the register usage. + v = m.lowerConstant(def.Instr) + def.Instr.MarkLowered() + } else { + v = m.compiler.VRegOf(def.V) + } + + r := v + switch inBits := def.V.Type().Bits(); { + case mode == extModeNone: + case inBits == 32 && (mode == extModeZeroExtend32 || mode == extModeSignExtend32): + case inBits == 32 && mode == extModeZeroExtend64: + extended := m.compiler.AllocateVReg(ssa.TypeI64) + ext := m.allocateInstr() + ext.asExtend(extended, v, 32, 64, false) + m.insert(ext) + r = extended + case inBits == 32 && mode == extModeSignExtend64: + extended := m.compiler.AllocateVReg(ssa.TypeI64) + ext := m.allocateInstr() + ext.asExtend(extended, v, 32, 64, true) + m.insert(ext) + r = extended + case inBits == 64 && (mode == extModeZeroExtend64 || mode == extModeSignExtend64): + } + return operandNR(r) +} + +func asImm12Operand(val uint64) (op operand, ok bool) { + v, shiftBit, ok := asImm12(val) + if !ok { + return operand{}, false + } + return operandImm12(v, shiftBit), true +} + +func asImm12(val uint64) (v uint16, shiftBit byte, ok bool) { + const mask1, mask2 uint64 = 0xfff, 0xfff_000 + if val&^mask1 == 0 { + return uint16(val), 0, true + } else if val&^mask2 == 0 { + return uint16(val >> 12), 1, true + } else { + return 0, 0, false + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_mem.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_mem.go new file mode 100644 index 00000000..fd0760d7 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/lower_mem.go @@ -0,0 +1,451 @@ +package arm64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +type ( + // addressMode represents an ARM64 addressing mode. + // + // https://developer.arm.com/documentation/102374/0101/Loads-and-stores---addressing + // TODO: use the bit-packed layout like operand struct. + addressMode struct { + kind addressModeKind + rn, rm regalloc.VReg + extOp extendOp + imm int64 + } + + // addressModeKind represents the kind of ARM64 addressing mode. + addressModeKind byte +) + +func resetAddressMode(a *addressMode) { + a.kind = 0 + a.rn = 0 + a.rm = 0 + a.extOp = 0 + a.imm = 0 +} + +const ( + // addressModeKindRegExtended takes a base register and an index register. The index register is sign/zero-extended, + // and then scaled by bits(type)/8. + // + // e.g. + // - ldrh w1, [x2, w3, SXTW #1] ;; sign-extended and scaled by 2 (== LSL #1) + // - strh w1, [x2, w3, UXTW #1] ;; zero-extended and scaled by 2 (== LSL #1) + // - ldr w1, [x2, w3, SXTW #2] ;; sign-extended and scaled by 4 (== LSL #2) + // - str x1, [x2, w3, UXTW #3] ;; zero-extended and scaled by 8 (== LSL #3) + // + // See the following pages: + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRH--register---Load-Register-Halfword--register-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--register---Load-Register--register-- + addressModeKindRegScaledExtended addressModeKind = iota + + // addressModeKindRegScaled is the same as addressModeKindRegScaledExtended, but without extension factor. + addressModeKindRegScaled + + // addressModeKindRegScaled is the same as addressModeKindRegScaledExtended, but without scale factor. + addressModeKindRegExtended + + // addressModeKindRegReg takes a base register and an index register. The index register is not either scaled or extended. + addressModeKindRegReg + + // addressModeKindRegSignedImm9 takes a base register and a 9-bit "signed" immediate offset (-256 to 255). + // The immediate will be sign-extended, and be added to the base register. + // This is a.k.a. "unscaled" since the immediate is not scaled. + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDUR--Load-Register--unscaled-- + addressModeKindRegSignedImm9 + + // addressModeKindRegUnsignedImm12 takes a base register and a 12-bit "unsigned" immediate offset. scaled by + // the size of the type. In other words, the actual offset will be imm12 * bits(type)/8. + // See "Unsigned offset" in the following pages: + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRB--immediate---Load-Register-Byte--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRH--immediate---Load-Register-Halfword--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--immediate---Load-Register--immediate-- + addressModeKindRegUnsignedImm12 + + // addressModePostIndex takes a base register and a 9-bit "signed" immediate offset. + // After the load/store, the base register will be updated by the offset. + // + // Note that when this is used for pair load/store, the offset will be 7-bit "signed" immediate offset. + // + // See "Post-index" in the following pages for examples: + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRB--immediate---Load-Register-Byte--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRH--immediate---Load-Register-Halfword--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--immediate---Load-Register--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDP--Load-Pair-of-Registers- + addressModeKindPostIndex + + // addressModePostIndex takes a base register and a 9-bit "signed" immediate offset. + // Before the load/store, the base register will be updated by the offset. + // + // Note that when this is used for pair load/store, the offset will be 7-bit "signed" immediate offset. + // + // See "Pre-index" in the following pages for examples: + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRB--immediate---Load-Register-Byte--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDRH--immediate---Load-Register-Halfword--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--immediate---Load-Register--immediate-- + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDP--Load-Pair-of-Registers- + addressModeKindPreIndex + + // addressModeKindArgStackSpace is used to resolve the address of the argument stack space + // exiting right above the stack pointer. Since we don't know the exact stack space needed for a function + // at a compilation phase, this is used as a placeholder and further lowered to a real addressing mode like above. + addressModeKindArgStackSpace + + // addressModeKindResultStackSpace is used to resolve the address of the result stack space + // exiting right above the stack pointer. Since we don't know the exact stack space needed for a function + // at a compilation phase, this is used as a placeholder and further lowered to a real addressing mode like above. + addressModeKindResultStackSpace +) + +func (a addressMode) format(dstSizeBits byte) (ret string) { + base := formatVRegSized(a.rn, 64) + if rn := a.rn; rn.RegType() != regalloc.RegTypeInt { + panic("invalid base register type: " + a.rn.RegType().String()) + } else if rn.IsRealReg() && v0 <= a.rn.RealReg() && a.rn.RealReg() <= v30 { + panic("BUG: likely a bug in reg alloc or reset behavior") + } + + switch a.kind { + case addressModeKindRegScaledExtended: + amount := a.sizeInBitsToShiftAmount(dstSizeBits) + ret = fmt.Sprintf("[%s, %s, %s #%#x]", base, formatVRegSized(a.rm, a.indexRegBits()), a.extOp, amount) + case addressModeKindRegScaled: + amount := a.sizeInBitsToShiftAmount(dstSizeBits) + ret = fmt.Sprintf("[%s, %s, lsl #%#x]", base, formatVRegSized(a.rm, a.indexRegBits()), amount) + case addressModeKindRegExtended: + ret = fmt.Sprintf("[%s, %s, %s]", base, formatVRegSized(a.rm, a.indexRegBits()), a.extOp) + case addressModeKindRegReg: + ret = fmt.Sprintf("[%s, %s]", base, formatVRegSized(a.rm, a.indexRegBits())) + case addressModeKindRegSignedImm9: + if a.imm != 0 { + ret = fmt.Sprintf("[%s, #%#x]", base, a.imm) + } else { + ret = fmt.Sprintf("[%s]", base) + } + case addressModeKindRegUnsignedImm12: + if a.imm != 0 { + ret = fmt.Sprintf("[%s, #%#x]", base, a.imm) + } else { + ret = fmt.Sprintf("[%s]", base) + } + case addressModeKindPostIndex: + ret = fmt.Sprintf("[%s], #%#x", base, a.imm) + case addressModeKindPreIndex: + ret = fmt.Sprintf("[%s, #%#x]!", base, a.imm) + case addressModeKindArgStackSpace: + ret = fmt.Sprintf("[#arg_space, #%#x]", a.imm) + case addressModeKindResultStackSpace: + ret = fmt.Sprintf("[#ret_space, #%#x]", a.imm) + } + return +} + +func addressModePreOrPostIndex(m *machine, rn regalloc.VReg, imm int64, preIndex bool) *addressMode { + if !offsetFitsInAddressModeKindRegSignedImm9(imm) { + panic(fmt.Sprintf("BUG: offset %#x does not fit in addressModeKindRegSignedImm9", imm)) + } + mode := m.amodePool.Allocate() + if preIndex { + *mode = addressMode{kind: addressModeKindPreIndex, rn: rn, imm: imm} + } else { + *mode = addressMode{kind: addressModeKindPostIndex, rn: rn, imm: imm} + } + return mode +} + +func offsetFitsInAddressModeKindRegUnsignedImm12(dstSizeInBits byte, offset int64) bool { + divisor := int64(dstSizeInBits) / 8 + return 0 < offset && offset%divisor == 0 && offset/divisor < 4096 +} + +func offsetFitsInAddressModeKindRegSignedImm9(offset int64) bool { + return -256 <= offset && offset <= 255 +} + +func (a addressMode) indexRegBits() byte { + bits := a.extOp.srcBits() + if bits != 32 && bits != 64 { + panic("invalid index register for address mode. it must be either 32 or 64 bits") + } + return bits +} + +func (a addressMode) sizeInBitsToShiftAmount(sizeInBits byte) (lsl byte) { + switch sizeInBits { + case 8: + lsl = 0 + case 16: + lsl = 1 + case 32: + lsl = 2 + case 64: + lsl = 3 + } + return +} + +func extLoadSignSize(op ssa.Opcode) (size byte, signed bool) { + switch op { + case ssa.OpcodeUload8: + size, signed = 8, false + case ssa.OpcodeUload16: + size, signed = 16, false + case ssa.OpcodeUload32: + size, signed = 32, false + case ssa.OpcodeSload8: + size, signed = 8, true + case ssa.OpcodeSload16: + size, signed = 16, true + case ssa.OpcodeSload32: + size, signed = 32, true + default: + panic("BUG") + } + return +} + +func (m *machine) lowerExtLoad(op ssa.Opcode, ptr ssa.Value, offset uint32, ret regalloc.VReg) { + size, signed := extLoadSignSize(op) + amode := m.lowerToAddressMode(ptr, offset, size) + load := m.allocateInstr() + if signed { + load.asSLoad(ret, amode, size) + } else { + load.asULoad(ret, amode, size) + } + m.insert(load) +} + +func (m *machine) lowerLoad(ptr ssa.Value, offset uint32, typ ssa.Type, ret ssa.Value) { + amode := m.lowerToAddressMode(ptr, offset, typ.Bits()) + + dst := m.compiler.VRegOf(ret) + load := m.allocateInstr() + switch typ { + case ssa.TypeI32, ssa.TypeI64: + load.asULoad(dst, amode, typ.Bits()) + case ssa.TypeF32, ssa.TypeF64: + load.asFpuLoad(dst, amode, typ.Bits()) + case ssa.TypeV128: + load.asFpuLoad(dst, amode, 128) + default: + panic("TODO") + } + m.insert(load) +} + +func (m *machine) lowerLoadSplat(ptr ssa.Value, offset uint32, lane ssa.VecLane, ret ssa.Value) { + // vecLoad1R has offset address mode (base+imm) only for post index, so we simply add the offset to the base. + base := m.getOperand_NR(m.compiler.ValueDefinition(ptr), extModeNone).nr() + offsetReg := m.compiler.AllocateVReg(ssa.TypeI64) + m.lowerConstantI64(offsetReg, int64(offset)) + addedBase := m.addReg64ToReg64(base, offsetReg) + + rd := m.compiler.VRegOf(ret) + + ld1r := m.allocateInstr() + ld1r.asVecLoad1R(rd, operandNR(addedBase), ssaLaneToArrangement(lane)) + m.insert(ld1r) +} + +func (m *machine) lowerStore(si *ssa.Instruction) { + // TODO: merge consecutive stores into a single pair store instruction. + value, ptr, offset, storeSizeInBits := si.StoreData() + amode := m.lowerToAddressMode(ptr, offset, storeSizeInBits) + + valueOp := m.getOperand_NR(m.compiler.ValueDefinition(value), extModeNone) + store := m.allocateInstr() + store.asStore(valueOp, amode, storeSizeInBits) + m.insert(store) +} + +// lowerToAddressMode converts a pointer to an addressMode that can be used as an operand for load/store instructions. +func (m *machine) lowerToAddressMode(ptr ssa.Value, offsetBase uint32, size byte) (amode *addressMode) { + // TODO: currently the instruction selection logic doesn't support addressModeKindRegScaledExtended and + // addressModeKindRegScaled since collectAddends doesn't take ssa.OpcodeIshl into account. This should be fixed + // to support more efficient address resolution. + + a32s, a64s, offset := m.collectAddends(ptr) + offset += int64(offsetBase) + return m.lowerToAddressModeFromAddends(a32s, a64s, size, offset) +} + +// lowerToAddressModeFromAddends creates an addressMode from a list of addends collected by collectAddends. +// During the construction, this might emit additional instructions. +// +// Extracted as a separate function for easy testing. +func (m *machine) lowerToAddressModeFromAddends(a32s *wazevoapi.Queue[addend32], a64s *wazevoapi.Queue[regalloc.VReg], size byte, offset int64) (amode *addressMode) { + amode = m.amodePool.Allocate() + switch a64sExist, a32sExist := !a64s.Empty(), !a32s.Empty(); { + case a64sExist && a32sExist: + var base regalloc.VReg + base = a64s.Dequeue() + var a32 addend32 + a32 = a32s.Dequeue() + *amode = addressMode{kind: addressModeKindRegExtended, rn: base, rm: a32.r, extOp: a32.ext} + case a64sExist && offsetFitsInAddressModeKindRegUnsignedImm12(size, offset): + var base regalloc.VReg + base = a64s.Dequeue() + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: base, imm: offset} + offset = 0 + case a64sExist && offsetFitsInAddressModeKindRegSignedImm9(offset): + var base regalloc.VReg + base = a64s.Dequeue() + *amode = addressMode{kind: addressModeKindRegSignedImm9, rn: base, imm: offset} + offset = 0 + case a64sExist: + var base regalloc.VReg + base = a64s.Dequeue() + if !a64s.Empty() { + index := a64s.Dequeue() + *amode = addressMode{kind: addressModeKindRegReg, rn: base, rm: index, extOp: extendOpUXTX /* indicates index reg is 64-bit */} + } else { + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: base, imm: 0} + } + case a32sExist: + base32 := a32s.Dequeue() + + // First we need 64-bit base. + base := m.compiler.AllocateVReg(ssa.TypeI64) + baseExt := m.allocateInstr() + var signed bool + if base32.ext == extendOpSXTW { + signed = true + } + baseExt.asExtend(base, base32.r, 32, 64, signed) + m.insert(baseExt) + + if !a32s.Empty() { + index := a32s.Dequeue() + *amode = addressMode{kind: addressModeKindRegExtended, rn: base, rm: index.r, extOp: index.ext} + } else { + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: base, imm: 0} + } + default: // Only static offsets. + tmpReg := m.compiler.AllocateVReg(ssa.TypeI64) + m.lowerConstantI64(tmpReg, offset) + *amode = addressMode{kind: addressModeKindRegUnsignedImm12, rn: tmpReg, imm: 0} + offset = 0 + } + + baseReg := amode.rn + if offset > 0 { + baseReg = m.addConstToReg64(baseReg, offset) // baseReg += offset + } + + for !a64s.Empty() { + a64 := a64s.Dequeue() + baseReg = m.addReg64ToReg64(baseReg, a64) // baseReg += a64 + } + + for !a32s.Empty() { + a32 := a32s.Dequeue() + baseReg = m.addRegToReg64Ext(baseReg, a32.r, a32.ext) // baseReg += (a32 extended to 64-bit) + } + amode.rn = baseReg + return +} + +var addendsMatchOpcodes = [4]ssa.Opcode{ssa.OpcodeUExtend, ssa.OpcodeSExtend, ssa.OpcodeIadd, ssa.OpcodeIconst} + +func (m *machine) collectAddends(ptr ssa.Value) (addends32 *wazevoapi.Queue[addend32], addends64 *wazevoapi.Queue[regalloc.VReg], offset int64) { + m.addendsWorkQueue.Reset() + m.addends32.Reset() + m.addends64.Reset() + m.addendsWorkQueue.Enqueue(ptr) + + for !m.addendsWorkQueue.Empty() { + v := m.addendsWorkQueue.Dequeue() + + def := m.compiler.ValueDefinition(v) + switch op := m.compiler.MatchInstrOneOf(def, addendsMatchOpcodes[:]); op { + case ssa.OpcodeIadd: + // If the addend is an add, we recursively collect its operands. + x, y := def.Instr.Arg2() + m.addendsWorkQueue.Enqueue(x) + m.addendsWorkQueue.Enqueue(y) + def.Instr.MarkLowered() + case ssa.OpcodeIconst: + // If the addend is constant, we just statically merge it into the offset. + ic := def.Instr + u64 := ic.ConstantVal() + if ic.Return().Type().Bits() == 32 { + offset += int64(int32(u64)) // sign-extend. + } else { + offset += int64(u64) + } + def.Instr.MarkLowered() + case ssa.OpcodeUExtend, ssa.OpcodeSExtend: + input := def.Instr.Arg() + if input.Type().Bits() != 32 { + panic("illegal size: " + input.Type().String()) + } + + var ext extendOp + if op == ssa.OpcodeUExtend { + ext = extendOpUXTW + } else { + ext = extendOpSXTW + } + + inputDef := m.compiler.ValueDefinition(input) + constInst := inputDef.IsFromInstr() && inputDef.Instr.Constant() + switch { + case constInst && ext == extendOpUXTW: + // Zero-extension of a 32-bit constant can be merged into the offset. + offset += int64(uint32(inputDef.Instr.ConstantVal())) + case constInst && ext == extendOpSXTW: + // Sign-extension of a 32-bit constant can be merged into the offset. + offset += int64(int32(inputDef.Instr.ConstantVal())) // sign-extend! + default: + m.addends32.Enqueue(addend32{r: m.getOperand_NR(inputDef, extModeNone).nr(), ext: ext}) + } + def.Instr.MarkLowered() + continue + default: + // If the addend is not one of them, we simply use it as-is (without merging!), optionally zero-extending it. + m.addends64.Enqueue(m.getOperand_NR(def, extModeZeroExtend64 /* optional zero ext */).nr()) + } + } + return &m.addends32, &m.addends64, offset +} + +func (m *machine) addConstToReg64(r regalloc.VReg, c int64) (rd regalloc.VReg) { + rd = m.compiler.AllocateVReg(ssa.TypeI64) + alu := m.allocateInstr() + if imm12Op, ok := asImm12Operand(uint64(c)); ok { + alu.asALU(aluOpAdd, rd, operandNR(r), imm12Op, true) + } else if imm12Op, ok = asImm12Operand(uint64(-c)); ok { + alu.asALU(aluOpSub, rd, operandNR(r), imm12Op, true) + } else { + tmp := m.compiler.AllocateVReg(ssa.TypeI64) + m.load64bitConst(c, tmp) + alu.asALU(aluOpAdd, rd, operandNR(r), operandNR(tmp), true) + } + m.insert(alu) + return +} + +func (m *machine) addReg64ToReg64(rn, rm regalloc.VReg) (rd regalloc.VReg) { + rd = m.compiler.AllocateVReg(ssa.TypeI64) + alu := m.allocateInstr() + alu.asALU(aluOpAdd, rd, operandNR(rn), operandNR(rm), true) + m.insert(alu) + return +} + +func (m *machine) addRegToReg64Ext(rn, rm regalloc.VReg, ext extendOp) (rd regalloc.VReg) { + rd = m.compiler.AllocateVReg(ssa.TypeI64) + alu := m.allocateInstr() + alu.asALU(aluOpAdd, rd, operandNR(rn), operandER(rm, ext, 64), true) + m.insert(alu) + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine.go new file mode 100644 index 00000000..00e6b238 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine.go @@ -0,0 +1,631 @@ +package arm64 + +import ( + "context" + "fmt" + "math" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +type ( + // machine implements backend.Machine. + machine struct { + compiler backend.Compiler + currentABI *backend.FunctionABI + instrPool wazevoapi.Pool[instruction] + // labelPositionPool is the pool of labelPosition. The id is the label where + // if the label is less than the maxSSABlockID, it's the ssa.BasicBlockID. + labelPositionPool wazevoapi.IDedPool[labelPosition] + + // nextLabel is the next label to be allocated. The first free label comes after maxSSABlockID + // so that we can have an identical label for the SSA block ID, which is useful for debugging. + nextLabel label + // rootInstr is the first instruction of the function. + rootInstr *instruction + // currentLabelPos is the currently-compiled ssa.BasicBlock's labelPosition. + currentLabelPos *labelPosition + // orderedSSABlockLabelPos is the ordered list of labelPosition in the generated code for each ssa.BasicBlock. + orderedSSABlockLabelPos []*labelPosition + // returnLabelPos is the labelPosition for the return block. + returnLabelPos labelPosition + // perBlockHead and perBlockEnd are the head and tail of the instruction list per currently-compiled ssa.BasicBlock. + perBlockHead, perBlockEnd *instruction + // pendingInstructions are the instructions which are not yet emitted into the instruction list. + pendingInstructions []*instruction + // maxSSABlockID is the maximum ssa.BasicBlockID in the current function. + maxSSABlockID label + + regAlloc regalloc.Allocator[*instruction, *labelPosition, *regAllocFn] + regAllocFn regAllocFn + + amodePool wazevoapi.Pool[addressMode] + + // addendsWorkQueue is used during address lowering, defined here for reuse. + addendsWorkQueue wazevoapi.Queue[ssa.Value] + addends32 wazevoapi.Queue[addend32] + // addends64 is used during address lowering, defined here for reuse. + addends64 wazevoapi.Queue[regalloc.VReg] + unresolvedAddressModes []*instruction + + // condBrRelocs holds the conditional branches which need offset relocation. + condBrRelocs []condBrReloc + + // jmpTableTargets holds the labels of the jump table targets. + jmpTableTargets [][]uint32 + // jmpTableTargetNext is the index to the jmpTableTargets slice to be used for the next jump table. + jmpTableTargetsNext int + + // spillSlotSize is the size of the stack slot in bytes used for spilling registers. + // During the execution of the function, the stack looks like: + // + // + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | xxxxx | + // | ReturnAddress | + // +-----------------+ <<-| + // | ........... | | + // | spill slot M | | <--- spillSlotSize + // | ............ | | + // | spill slot 2 | | + // | spill slot 1 | <<-+ + // | clobbered N | + // | ........... | + // | clobbered 1 | + // | clobbered 0 | + // SP---> +-----------------+ + // (low address) + // + // and it represents the size of the space between FP and the first spilled slot. This must be a multiple of 16. + // Also note that this is only known after register allocation. + spillSlotSize int64 + spillSlots map[regalloc.VRegID]int64 // regalloc.VRegID to offset. + // clobberedRegs holds real-register backed VRegs saved at the function prologue, and restored at the epilogue. + clobberedRegs []regalloc.VReg + + maxRequiredStackSizeForCalls int64 + stackBoundsCheckDisabled bool + + regAllocStarted bool + } + + addend32 struct { + r regalloc.VReg + ext extendOp + } + + condBrReloc struct { + cbr *instruction + // currentLabelPos is the labelPosition within which condBr is defined. + currentLabelPos *labelPosition + // Next block's labelPosition. + nextLabel label + offset int64 + } +) + +type ( + // label represents a position in the generated code which is either + // a real instruction or the constant InstructionPool (e.g. jump tables). + // + // This is exactly the same as the traditional "label" in assembly code. + label uint32 + + // labelPosition represents the regions of the generated code which the label represents. + // This implements regalloc.Block. + labelPosition struct { + // sb is not nil if this corresponds to a ssa.BasicBlock. + sb ssa.BasicBlock + // cur is used to walk through the instructions in the block during the register allocation. + cur, + // begin and end are the first and last instructions of the block. + begin, end *instruction + // binaryOffset is the offset in the binary where the label is located. + binaryOffset int64 + } +) + +const ( + labelReturn label = math.MaxUint32 + labelInvalid = labelReturn - 1 +) + +// String implements backend.Machine. +func (l label) String() string { + return fmt.Sprintf("L%d", l) +} + +func resetLabelPosition(l *labelPosition) { + *l = labelPosition{} +} + +// NewBackend returns a new backend for arm64. +func NewBackend() backend.Machine { + m := &machine{ + spillSlots: make(map[regalloc.VRegID]int64), + regAlloc: regalloc.NewAllocator[*instruction, *labelPosition, *regAllocFn](regInfo), + amodePool: wazevoapi.NewPool[addressMode](resetAddressMode), + instrPool: wazevoapi.NewPool[instruction](resetInstruction), + labelPositionPool: wazevoapi.NewIDedPool[labelPosition](resetLabelPosition), + } + m.regAllocFn.m = m + return m +} + +func ssaBlockLabel(sb ssa.BasicBlock) label { + if sb.ReturnBlock() { + return labelReturn + } + return label(sb.ID()) +} + +// getOrAllocateSSABlockLabelPosition returns the labelPosition for the given basic block. +func (m *machine) getOrAllocateSSABlockLabelPosition(sb ssa.BasicBlock) *labelPosition { + if sb.ReturnBlock() { + m.returnLabelPos.sb = sb + return &m.returnLabelPos + } + + l := ssaBlockLabel(sb) + pos := m.labelPositionPool.GetOrAllocate(int(l)) + pos.sb = sb + return pos +} + +// LinkAdjacentBlocks implements backend.Machine. +func (m *machine) LinkAdjacentBlocks(prev, next ssa.BasicBlock) { + prevPos, nextPos := m.getOrAllocateSSABlockLabelPosition(prev), m.getOrAllocateSSABlockLabelPosition(next) + prevPos.end.next = nextPos.begin +} + +// StartBlock implements backend.Machine. +func (m *machine) StartBlock(blk ssa.BasicBlock) { + m.currentLabelPos = m.getOrAllocateSSABlockLabelPosition(blk) + labelPos := m.currentLabelPos + end := m.allocateNop() + m.perBlockHead, m.perBlockEnd = end, end + labelPos.begin, labelPos.end = end, end + m.orderedSSABlockLabelPos = append(m.orderedSSABlockLabelPos, labelPos) +} + +// EndBlock implements ExecutableContext. +func (m *machine) EndBlock() { + // Insert nop0 as the head of the block for convenience to simplify the logic of inserting instructions. + m.insertAtPerBlockHead(m.allocateNop()) + + m.currentLabelPos.begin = m.perBlockHead + + if m.currentLabelPos.sb.EntryBlock() { + m.rootInstr = m.perBlockHead + } +} + +func (m *machine) insertAtPerBlockHead(i *instruction) { + if m.perBlockHead == nil { + m.perBlockHead = i + m.perBlockEnd = i + return + } + + i.next = m.perBlockHead + m.perBlockHead.prev = i + m.perBlockHead = i +} + +// FlushPendingInstructions implements backend.Machine. +func (m *machine) FlushPendingInstructions() { + l := len(m.pendingInstructions) + if l == 0 { + return + } + for i := l - 1; i >= 0; i-- { // reverse because we lower instructions in reverse order. + m.insertAtPerBlockHead(m.pendingInstructions[i]) + } + m.pendingInstructions = m.pendingInstructions[:0] +} + +// RegAlloc implements backend.Machine Function. +func (m *machine) RegAlloc() { + m.regAllocStarted = true + m.regAlloc.DoAllocation(&m.regAllocFn) + // Now that we know the final spill slot size, we must align spillSlotSize to 16 bytes. + m.spillSlotSize = (m.spillSlotSize + 15) &^ 15 +} + +// Reset implements backend.Machine. +func (m *machine) Reset() { + m.clobberedRegs = m.clobberedRegs[:0] + for key := range m.spillSlots { + m.clobberedRegs = append(m.clobberedRegs, regalloc.VReg(key)) + } + for _, key := range m.clobberedRegs { + delete(m.spillSlots, regalloc.VRegID(key)) + } + m.clobberedRegs = m.clobberedRegs[:0] + m.regAllocStarted = false + m.regAlloc.Reset() + m.spillSlotSize = 0 + m.unresolvedAddressModes = m.unresolvedAddressModes[:0] + m.maxRequiredStackSizeForCalls = 0 + m.jmpTableTargetsNext = 0 + m.amodePool.Reset() + m.instrPool.Reset() + m.labelPositionPool.Reset() + m.pendingInstructions = m.pendingInstructions[:0] + m.perBlockHead, m.perBlockEnd, m.rootInstr = nil, nil, nil + m.orderedSSABlockLabelPos = m.orderedSSABlockLabelPos[:0] +} + +// StartLoweringFunction implements backend.Machine StartLoweringFunction. +func (m *machine) StartLoweringFunction(maxBlockID ssa.BasicBlockID) { + m.maxSSABlockID = label(maxBlockID) + m.nextLabel = label(maxBlockID) + 1 +} + +// SetCurrentABI implements backend.Machine SetCurrentABI. +func (m *machine) SetCurrentABI(abi *backend.FunctionABI) { + m.currentABI = abi +} + +// DisableStackCheck implements backend.Machine DisableStackCheck. +func (m *machine) DisableStackCheck() { + m.stackBoundsCheckDisabled = true +} + +// SetCompiler implements backend.Machine. +func (m *machine) SetCompiler(ctx backend.Compiler) { + m.compiler = ctx + m.regAllocFn.ssaB = ctx.SSABuilder() +} + +func (m *machine) insert(i *instruction) { + m.pendingInstructions = append(m.pendingInstructions, i) +} + +func (m *machine) insertBrTargetLabel() label { + nop, l := m.allocateBrTarget() + m.insert(nop) + return l +} + +func (m *machine) allocateBrTarget() (nop *instruction, l label) { + l = m.nextLabel + m.nextLabel++ + nop = m.allocateInstr() + nop.asNop0WithLabel(l) + pos := m.labelPositionPool.GetOrAllocate(int(l)) + pos.begin, pos.end = nop, nop + return +} + +// allocateInstr allocates an instruction. +func (m *machine) allocateInstr() *instruction { + instr := m.instrPool.Allocate() + if !m.regAllocStarted { + instr.addedBeforeRegAlloc = true + } + return instr +} + +func resetInstruction(i *instruction) { + *i = instruction{} +} + +func (m *machine) allocateNop() *instruction { + instr := m.allocateInstr() + instr.asNop0() + return instr +} + +func (m *machine) resolveAddressingMode(arg0offset, ret0offset int64, i *instruction) { + amode := i.getAmode() + switch amode.kind { + case addressModeKindResultStackSpace: + amode.imm += ret0offset + case addressModeKindArgStackSpace: + amode.imm += arg0offset + default: + panic("BUG") + } + + var sizeInBits byte + switch i.kind { + case store8, uLoad8: + sizeInBits = 8 + case store16, uLoad16: + sizeInBits = 16 + case store32, fpuStore32, uLoad32, fpuLoad32: + sizeInBits = 32 + case store64, fpuStore64, uLoad64, fpuLoad64: + sizeInBits = 64 + case fpuStore128, fpuLoad128: + sizeInBits = 128 + default: + panic("BUG") + } + + if offsetFitsInAddressModeKindRegUnsignedImm12(sizeInBits, amode.imm) { + amode.kind = addressModeKindRegUnsignedImm12 + } else { + // This case, we load the offset into the temporary register, + // and then use it as the index register. + newPrev := m.lowerConstantI64AndInsert(i.prev, tmpRegVReg, amode.imm) + linkInstr(newPrev, i) + *amode = addressMode{kind: addressModeKindRegReg, rn: amode.rn, rm: tmpRegVReg, extOp: extendOpUXTX /* indicates rm reg is 64-bit */} + } +} + +// resolveRelativeAddresses resolves the relative addresses before encoding. +func (m *machine) resolveRelativeAddresses(ctx context.Context) { + for { + if len(m.unresolvedAddressModes) > 0 { + arg0offset, ret0offset := m.arg0OffsetFromSP(), m.ret0OffsetFromSP() + for _, i := range m.unresolvedAddressModes { + m.resolveAddressingMode(arg0offset, ret0offset, i) + } + } + + // Reuse the slice to gather the unresolved conditional branches. + m.condBrRelocs = m.condBrRelocs[:0] + + var fn string + var fnIndex int + var labelPosToLabel map[*labelPosition]label + if wazevoapi.PerfMapEnabled { + labelPosToLabel = make(map[*labelPosition]label) + for i := 0; i <= m.labelPositionPool.MaxIDEncountered(); i++ { + labelPosToLabel[m.labelPositionPool.Get(i)] = label(i) + } + + fn = wazevoapi.GetCurrentFunctionName(ctx) + fnIndex = wazevoapi.GetCurrentFunctionIndex(ctx) + } + + // Next, in order to determine the offsets of relative jumps, we have to calculate the size of each label. + var offset int64 + for i, pos := range m.orderedSSABlockLabelPos { + pos.binaryOffset = offset + var size int64 + for cur := pos.begin; ; cur = cur.next { + switch cur.kind { + case nop0: + l := cur.nop0Label() + if pos := m.labelPositionPool.Get(int(l)); pos != nil { + pos.binaryOffset = offset + size + } + case condBr: + if !cur.condBrOffsetResolved() { + var nextLabel label + if i < len(m.orderedSSABlockLabelPos)-1 { + // Note: this is only used when the block ends with fallthrough, + // therefore can be safely assumed that the next block exists when it's needed. + nextLabel = ssaBlockLabel(m.orderedSSABlockLabelPos[i+1].sb) + } + m.condBrRelocs = append(m.condBrRelocs, condBrReloc{ + cbr: cur, currentLabelPos: pos, offset: offset + size, + nextLabel: nextLabel, + }) + } + } + size += cur.size() + if cur == pos.end { + break + } + } + + if wazevoapi.PerfMapEnabled { + if size > 0 { + wazevoapi.PerfMap.AddModuleEntry(fnIndex, offset, uint64(size), fmt.Sprintf("%s:::::%s", fn, labelPosToLabel[pos])) + } + } + offset += size + } + + // Before resolving any offsets, we need to check if all the conditional branches can be resolved. + var needRerun bool + for i := range m.condBrRelocs { + reloc := &m.condBrRelocs[i] + cbr := reloc.cbr + offset := reloc.offset + + target := cbr.condBrLabel() + offsetOfTarget := m.labelPositionPool.Get(int(target)).binaryOffset + diff := offsetOfTarget - offset + if divided := diff >> 2; divided < minSignedInt19 || divided > maxSignedInt19 { + // This case the conditional branch is too huge. We place the trampoline instructions at the end of the current block, + // and jump to it. + m.insertConditionalJumpTrampoline(cbr, reloc.currentLabelPos, reloc.nextLabel) + // Then, we need to recall this function to fix up the label offsets + // as they have changed after the trampoline is inserted. + needRerun = true + } + } + if needRerun { + if wazevoapi.PerfMapEnabled { + wazevoapi.PerfMap.Clear() + } + } else { + break + } + } + + var currentOffset int64 + for cur := m.rootInstr; cur != nil; cur = cur.next { + switch cur.kind { + case br: + target := cur.brLabel() + offsetOfTarget := m.labelPositionPool.Get(int(target)).binaryOffset + diff := offsetOfTarget - currentOffset + divided := diff >> 2 + if divided < minSignedInt26 || divided > maxSignedInt26 { + // This means the currently compiled single function is extremely large. + panic("too large function that requires branch relocation of large unconditional branch larger than 26-bit range") + } + cur.brOffsetResolve(diff) + case condBr: + if !cur.condBrOffsetResolved() { + target := cur.condBrLabel() + offsetOfTarget := m.labelPositionPool.Get(int(target)).binaryOffset + diff := offsetOfTarget - currentOffset + if divided := diff >> 2; divided < minSignedInt19 || divided > maxSignedInt19 { + panic("BUG: branch relocation for large conditional branch larger than 19-bit range must be handled properly") + } + cur.condBrOffsetResolve(diff) + } + case brTableSequence: + tableIndex := cur.u1 + targets := m.jmpTableTargets[tableIndex] + for i := range targets { + l := label(targets[i]) + offsetOfTarget := m.labelPositionPool.Get(int(l)).binaryOffset + diff := offsetOfTarget - (currentOffset + brTableSequenceOffsetTableBegin) + targets[i] = uint32(diff) + } + cur.brTableSequenceOffsetsResolved() + case emitSourceOffsetInfo: + m.compiler.AddSourceOffsetInfo(currentOffset, cur.sourceOffsetInfo()) + } + currentOffset += cur.size() + } +} + +const ( + maxSignedInt26 = 1<<25 - 1 + minSignedInt26 = -(1 << 25) + + maxSignedInt19 = 1<<18 - 1 + minSignedInt19 = -(1 << 18) +) + +func (m *machine) insertConditionalJumpTrampoline(cbr *instruction, currentBlk *labelPosition, nextLabel label) { + cur := currentBlk.end + originalTarget := cbr.condBrLabel() + endNext := cur.next + + if cur.kind != br { + // If the current block ends with a conditional branch, we can just insert the trampoline after it. + // Otherwise, we need to insert "skip" instruction to skip the trampoline instructions. + skip := m.allocateInstr() + skip.asBr(nextLabel) + cur = linkInstr(cur, skip) + } + + cbrNewTargetInstr, cbrNewTargetLabel := m.allocateBrTarget() + cbr.setCondBrTargets(cbrNewTargetLabel) + cur = linkInstr(cur, cbrNewTargetInstr) + + // Then insert the unconditional branch to the original, which should be possible to get encoded + // as 26-bit offset should be enough for any practical application. + br := m.allocateInstr() + br.asBr(originalTarget) + cur = linkInstr(cur, br) + + // Update the end of the current block. + currentBlk.end = cur + + linkInstr(cur, endNext) +} + +// Format implements backend.Machine. +func (m *machine) Format() string { + begins := map[*instruction]label{} + for l := label(0); l < m.nextLabel; l++ { + pos := m.labelPositionPool.Get(int(l)) + if pos != nil { + begins[pos.begin] = l + } + } + + var lines []string + for cur := m.rootInstr; cur != nil; cur = cur.next { + if l, ok := begins[cur]; ok { + var labelStr string + if l <= m.maxSSABlockID { + labelStr = fmt.Sprintf("%s (SSA Block: blk%d):", l, int(l)) + } else { + labelStr = fmt.Sprintf("%s:", l) + } + lines = append(lines, labelStr) + } + if cur.kind == nop0 { + continue + } + lines = append(lines, "\t"+cur.String()) + } + return "\n" + strings.Join(lines, "\n") + "\n" +} + +// InsertReturn implements backend.Machine. +func (m *machine) InsertReturn() { + i := m.allocateInstr() + i.asRet() + m.insert(i) +} + +func (m *machine) getVRegSpillSlotOffsetFromSP(id regalloc.VRegID, size byte) int64 { + offset, ok := m.spillSlots[id] + if !ok { + offset = m.spillSlotSize + // TODO: this should be aligned depending on the `size` to use Imm12 offset load/store as much as possible. + m.spillSlots[id] = offset + m.spillSlotSize += int64(size) + } + return offset + 16 // spill slot starts above the clobbered registers and the frame size. +} + +func (m *machine) clobberedRegSlotSize() int64 { + return int64(len(m.clobberedRegs) * 16) +} + +func (m *machine) arg0OffsetFromSP() int64 { + return m.frameSize() + + 16 + // 16-byte aligned return address + 16 // frame size saved below the clobbered registers. +} + +func (m *machine) ret0OffsetFromSP() int64 { + return m.arg0OffsetFromSP() + m.currentABI.ArgStackSize +} + +func (m *machine) requiredStackSize() int64 { + return m.maxRequiredStackSizeForCalls + + m.frameSize() + + 16 + // 16-byte aligned return address. + 16 // frame size saved below the clobbered registers. +} + +func (m *machine) frameSize() int64 { + s := m.clobberedRegSlotSize() + m.spillSlotSize + if s&0xf != 0 { + panic(fmt.Errorf("BUG: frame size %d is not 16-byte aligned", s)) + } + return s +} + +func (m *machine) addJmpTableTarget(targets ssa.Values) (index int) { + if m.jmpTableTargetsNext == len(m.jmpTableTargets) { + m.jmpTableTargets = append(m.jmpTableTargets, make([]uint32, 0, len(targets.View()))) + } + + index = m.jmpTableTargetsNext + m.jmpTableTargetsNext++ + m.jmpTableTargets[index] = m.jmpTableTargets[index][:0] + for _, targetBlockID := range targets.View() { + target := m.compiler.SSABuilder().BasicBlock(ssa.BasicBlockID(targetBlockID)) + m.jmpTableTargets[index] = append(m.jmpTableTargets[index], uint32(target.ID())) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue.go new file mode 100644 index 00000000..c646a8fa --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue.go @@ -0,0 +1,467 @@ +package arm64 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// PostRegAlloc implements backend.Machine. +func (m *machine) PostRegAlloc() { + m.setupPrologue() + m.postRegAlloc() +} + +// setupPrologue initializes the prologue of the function. +func (m *machine) setupPrologue() { + cur := m.rootInstr + prevInitInst := cur.next + + // + // (high address) (high address) + // SP----> +-----------------+ +------------------+ <----+ + // | ....... | | ....... | | + // | ret Y | | ret Y | | + // | ....... | | ....... | | + // | ret 0 | | ret 0 | | + // | arg X | | arg X | | size_of_arg_ret. + // | ....... | ====> | ....... | | + // | arg 1 | | arg 1 | | + // | arg 0 | | arg 0 | <----+ + // |-----------------| | size_of_arg_ret | + // | return address | + // +------------------+ <---- SP + // (low address) (low address) + + // Saves the return address (lr) and the size_of_arg_ret below the SP. + // size_of_arg_ret is used for stack unwinding. + cur = m.createReturnAddrAndSizeOfArgRetSlot(cur) + + if !m.stackBoundsCheckDisabled { + cur = m.insertStackBoundsCheck(m.requiredStackSize(), cur) + } + + // Decrement SP if spillSlotSize > 0. + if m.spillSlotSize == 0 && len(m.spillSlots) != 0 { + panic(fmt.Sprintf("BUG: spillSlotSize=%d, spillSlots=%v\n", m.spillSlotSize, m.spillSlots)) + } + + if regs := m.clobberedRegs; len(regs) > 0 { + // + // (high address) (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | size_of_arg_ret | | size_of_arg_ret | + // | ReturnAddress | | ReturnAddress | + // SP----> +-----------------+ ====> +-----------------+ + // (low address) | clobbered M | + // | ............ | + // | clobbered 0 | + // +-----------------+ <----- SP + // (low address) + // + _amode := addressModePreOrPostIndex(m, spVReg, + -16, // stack pointer must be 16-byte aligned. + true, // Decrement before store. + ) + for _, vr := range regs { + // TODO: pair stores to reduce the number of instructions. + store := m.allocateInstr() + store.asStore(operandNR(vr), _amode, regTypeToRegisterSizeInBits(vr.RegType())) + cur = linkInstr(cur, store) + } + } + + if size := m.spillSlotSize; size > 0 { + // Check if size is 16-byte aligned. + if size&0xf != 0 { + panic(fmt.Errorf("BUG: spill slot size %d is not 16-byte aligned", size)) + } + + cur = m.addsAddOrSubStackPointer(cur, spVReg, size, false) + + // At this point, the stack looks like: + // + // (high address) + // +------------------+ + // | ....... | + // | ret Y | + // | ....... | + // | ret 0 | + // | arg X | + // | ....... | + // | arg 1 | + // | arg 0 | + // | size_of_arg_ret | + // | ReturnAddress | + // +------------------+ + // | clobbered M | + // | ............ | + // | clobbered 0 | + // | spill slot N | + // | ............ | + // | spill slot 2 | + // | spill slot 0 | + // SP----> +------------------+ + // (low address) + } + + // We push the frame size into the stack to make it possible to unwind stack: + // + // + // (high address) (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | size_of_arg_ret | | size_of_arg_ret | + // | ReturnAddress | | ReturnAddress | + // +-----------------+ ==> +-----------------+ <----+ + // | clobbered M | | clobbered M | | + // | ............ | | ............ | | + // | clobbered 2 | | clobbered 2 | | + // | clobbered 1 | | clobbered 1 | | frame size + // | clobbered 0 | | clobbered 0 | | + // | spill slot N | | spill slot N | | + // | ............ | | ............ | | + // | spill slot 0 | | spill slot 0 | <----+ + // SP---> +-----------------+ | xxxxxx | ;; unused space to make it 16-byte aligned. + // | frame_size | + // +-----------------+ <---- SP + // (low address) + // + cur = m.createFrameSizeSlot(cur, m.frameSize()) + + linkInstr(cur, prevInitInst) +} + +func (m *machine) createReturnAddrAndSizeOfArgRetSlot(cur *instruction) *instruction { + // First we decrement the stack pointer to point the arg0 slot. + var sizeOfArgRetReg regalloc.VReg + s := int64(m.currentABI.AlignedArgResultStackSlotSize()) + if s > 0 { + cur = m.lowerConstantI64AndInsert(cur, tmpRegVReg, s) + sizeOfArgRetReg = tmpRegVReg + + subSp := m.allocateInstr() + subSp.asALU(aluOpSub, spVReg, operandNR(spVReg), operandNR(sizeOfArgRetReg), true) + cur = linkInstr(cur, subSp) + } else { + sizeOfArgRetReg = xzrVReg + } + + // Saves the return address (lr) and the size_of_arg_ret below the SP. + // size_of_arg_ret is used for stack unwinding. + pstr := m.allocateInstr() + amode := addressModePreOrPostIndex(m, spVReg, -16, true /* decrement before store */) + pstr.asStorePair64(lrVReg, sizeOfArgRetReg, amode) + cur = linkInstr(cur, pstr) + return cur +} + +func (m *machine) createFrameSizeSlot(cur *instruction, s int64) *instruction { + var frameSizeReg regalloc.VReg + if s > 0 { + cur = m.lowerConstantI64AndInsert(cur, tmpRegVReg, s) + frameSizeReg = tmpRegVReg + } else { + frameSizeReg = xzrVReg + } + _amode := addressModePreOrPostIndex(m, spVReg, + -16, // stack pointer must be 16-byte aligned. + true, // Decrement before store. + ) + store := m.allocateInstr() + store.asStore(operandNR(frameSizeReg), _amode, 64) + cur = linkInstr(cur, store) + return cur +} + +// postRegAlloc does multiple things while walking through the instructions: +// 1. Removes the redundant copy instruction. +// 2. Inserts the epilogue. +func (m *machine) postRegAlloc() { + for cur := m.rootInstr; cur != nil; cur = cur.next { + switch cur.kind { + case ret: + m.setupEpilogueAfter(cur.prev) + case loadConstBlockArg: + lc := cur + next := lc.next + m.pendingInstructions = m.pendingInstructions[:0] + m.lowerLoadConstantBlockArgAfterRegAlloc(lc) + for _, instr := range m.pendingInstructions { + cur = linkInstr(cur, instr) + } + linkInstr(cur, next) + m.pendingInstructions = m.pendingInstructions[:0] + default: + // Removes the redundant copy instruction. + if cur.IsCopy() && cur.rn.realReg() == cur.rd.RealReg() { + prev, next := cur.prev, cur.next + // Remove the copy instruction. + prev.next = next + if next != nil { + next.prev = prev + } + } + } + } +} + +func (m *machine) setupEpilogueAfter(cur *instruction) { + prevNext := cur.next + + // We've stored the frame size in the prologue, and now that we are about to return from this function, we won't need it anymore. + cur = m.addsAddOrSubStackPointer(cur, spVReg, 16, true) + + if s := m.spillSlotSize; s > 0 { + // Adjust SP to the original value: + // + // (high address) (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | xxxxx | | xxxxx | + // | ReturnAddress | | ReturnAddress | + // +-----------------+ ====> +-----------------+ + // | clobbered M | | clobbered M | + // | ............ | | ............ | + // | clobbered 1 | | clobbered 1 | + // | clobbered 0 | | clobbered 0 | + // | spill slot N | +-----------------+ <---- SP + // | ............ | + // | spill slot 0 | + // SP---> +-----------------+ + // (low address) + // + cur = m.addsAddOrSubStackPointer(cur, spVReg, s, true) + } + + // First we need to restore the clobbered registers. + if len(m.clobberedRegs) > 0 { + // (high address) + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | xxxxx | | xxxxx | + // | ReturnAddress | | ReturnAddress | + // +-----------------+ ========> +-----------------+ <---- SP + // | clobbered M | + // | ........... | + // | clobbered 1 | + // | clobbered 0 | + // SP---> +-----------------+ + // (low address) + + l := len(m.clobberedRegs) - 1 + for i := range m.clobberedRegs { + vr := m.clobberedRegs[l-i] // reverse order to restore. + load := m.allocateInstr() + amode := addressModePreOrPostIndex(m, spVReg, + 16, // stack pointer must be 16-byte aligned. + false, // Increment after store. + ) + // TODO: pair loads to reduce the number of instructions. + switch regTypeToRegisterSizeInBits(vr.RegType()) { + case 64: // save int reg. + load.asULoad(vr, amode, 64) + case 128: // save vector reg. + load.asFpuLoad(vr, amode, 128) + } + cur = linkInstr(cur, load) + } + } + + // Reload the return address (lr). + // + // +-----------------+ +-----------------+ + // | ....... | | ....... | + // | ret Y | | ret Y | + // | ....... | | ....... | + // | ret 0 | | ret 0 | + // | arg X | | arg X | + // | ....... | ===> | ....... | + // | arg 1 | | arg 1 | + // | arg 0 | | arg 0 | + // | xxxxx | +-----------------+ <---- SP + // | ReturnAddress | + // SP----> +-----------------+ + + ldr := m.allocateInstr() + ldr.asULoad(lrVReg, + addressModePreOrPostIndex(m, spVReg, 16 /* stack pointer must be 16-byte aligned. */, false /* increment after loads */), 64) + cur = linkInstr(cur, ldr) + + if s := int64(m.currentABI.AlignedArgResultStackSlotSize()); s > 0 { + cur = m.addsAddOrSubStackPointer(cur, spVReg, s, true) + } + + linkInstr(cur, prevNext) +} + +// saveRequiredRegs is the set of registers that must be saved/restored during growing stack when there's insufficient +// stack space left. Basically this is the combination of CalleeSavedRegisters plus argument registers execpt for x0, +// which always points to the execution context whenever the native code is entered from Go. +var saveRequiredRegs = []regalloc.VReg{ + x1VReg, x2VReg, x3VReg, x4VReg, x5VReg, x6VReg, x7VReg, + x19VReg, x20VReg, x21VReg, x22VReg, x23VReg, x24VReg, x25VReg, x26VReg, x28VReg, lrVReg, + v0VReg, v1VReg, v2VReg, v3VReg, v4VReg, v5VReg, v6VReg, v7VReg, + v18VReg, v19VReg, v20VReg, v21VReg, v22VReg, v23VReg, v24VReg, v25VReg, v26VReg, v27VReg, v28VReg, v29VReg, v30VReg, v31VReg, +} + +// insertStackBoundsCheck will insert the instructions after `cur` to check the +// stack bounds, and if there's no sufficient spaces required for the function, +// exit the execution and try growing it in Go world. +// +// TODO: we should be able to share the instructions across all the functions to reduce the size of compiled executable. +func (m *machine) insertStackBoundsCheck(requiredStackSize int64, cur *instruction) *instruction { + if requiredStackSize%16 != 0 { + panic("BUG") + } + + if immm12op, ok := asImm12Operand(uint64(requiredStackSize)); ok { + // sub tmp, sp, #requiredStackSize + sub := m.allocateInstr() + sub.asALU(aluOpSub, tmpRegVReg, operandNR(spVReg), immm12op, true) + cur = linkInstr(cur, sub) + } else { + // This case, we first load the requiredStackSize into the temporary register, + cur = m.lowerConstantI64AndInsert(cur, tmpRegVReg, requiredStackSize) + // Then subtract it. + sub := m.allocateInstr() + sub.asALU(aluOpSub, tmpRegVReg, operandNR(spVReg), operandNR(tmpRegVReg), true) + cur = linkInstr(cur, sub) + } + + tmp2 := x11VReg // Caller save, so it is safe to use it here in the prologue. + + // ldr tmp2, [executionContext #StackBottomPtr] + ldr := m.allocateInstr() + amode := m.amodePool.Allocate() + *amode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: x0VReg, // execution context is always the first argument. + imm: wazevoapi.ExecutionContextOffsetStackBottomPtr.I64(), + } + ldr.asULoad(tmp2, amode, 64) + cur = linkInstr(cur, ldr) + + // subs xzr, tmp, tmp2 + subs := m.allocateInstr() + subs.asALU(aluOpSubS, xzrVReg, operandNR(tmpRegVReg), operandNR(tmp2), true) + cur = linkInstr(cur, subs) + + // b.ge #imm + cbr := m.allocateInstr() + cbr.asCondBr(ge.asCond(), labelInvalid, false /* ignored */) + cur = linkInstr(cur, cbr) + + // Set the required stack size and set it to the exec context. + { + // First load the requiredStackSize into the temporary register, + cur = m.lowerConstantI64AndInsert(cur, tmpRegVReg, requiredStackSize) + setRequiredStackSize := m.allocateInstr() + amode := m.amodePool.Allocate() + *amode = addressMode{ + kind: addressModeKindRegUnsignedImm12, + // Execution context is always the first argument. + rn: x0VReg, imm: wazevoapi.ExecutionContextOffsetStackGrowRequiredSize.I64(), + } + setRequiredStackSize.asStore(operandNR(tmpRegVReg), amode, 64) + + cur = linkInstr(cur, setRequiredStackSize) + } + + ldrAddress := m.allocateInstr() + amode2 := m.amodePool.Allocate() + *amode2 = addressMode{ + kind: addressModeKindRegUnsignedImm12, + rn: x0VReg, // execution context is always the first argument + imm: wazevoapi.ExecutionContextOffsetStackGrowCallTrampolineAddress.I64(), + } + ldrAddress.asULoad(tmpRegVReg, amode2, 64) + cur = linkInstr(cur, ldrAddress) + + // Then jumps to the stack grow call sequence's address, meaning + // transferring the control to the code compiled by CompileStackGrowCallSequence. + bl := m.allocateInstr() + bl.asCallIndirect(tmpRegVReg, nil) + cur = linkInstr(cur, bl) + + // Now that we know the entire code, we can finalize how many bytes + // we have to skip when the stack size is sufficient. + var cbrOffset int64 + for _cur := cbr; ; _cur = _cur.next { + cbrOffset += _cur.size() + if _cur == cur { + break + } + } + cbr.condBrOffsetResolve(cbrOffset) + return cur +} + +// CompileStackGrowCallSequence implements backend.Machine. +func (m *machine) CompileStackGrowCallSequence() []byte { + cur := m.allocateInstr() + cur.asNop0() + m.rootInstr = cur + + // Save the callee saved and argument registers. + cur = m.saveRegistersInExecutionContext(cur, saveRequiredRegs) + + // Save the current stack pointer. + cur = m.saveCurrentStackPointer(cur, x0VReg) + + // Set the exit status on the execution context. + cur = m.setExitCode(cur, x0VReg, wazevoapi.ExitCodeGrowStack) + + // Exit the execution. + cur = m.storeReturnAddressAndExit(cur) + + // After the exit, restore the saved registers. + cur = m.restoreRegistersInExecutionContext(cur, saveRequiredRegs) + + // Then goes back the original address of this stack grow call. + ret := m.allocateInstr() + ret.asRet() + linkInstr(cur, ret) + + m.encode(m.rootInstr) + return m.compiler.Buf() +} + +func (m *machine) addsAddOrSubStackPointer(cur *instruction, rd regalloc.VReg, diff int64, add bool) *instruction { + m.pendingInstructions = m.pendingInstructions[:0] + m.insertAddOrSubStackPointer(rd, diff, add) + for _, inserted := range m.pendingInstructions { + cur = linkInstr(cur, inserted) + } + return cur +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_regalloc.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_regalloc.go new file mode 100644 index 00000000..f2ed53ae --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_regalloc.go @@ -0,0 +1,351 @@ +package arm64 + +// This file implements the interfaces required for register allocations. See backend.RegAllocFunctionMachine. + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// regAllocFn implements regalloc.Function. +type regAllocFn struct { + ssaB ssa.Builder + m *machine + loopNestingForestRoots []ssa.BasicBlock + blockIter int +} + +// PostOrderBlockIteratorBegin implements regalloc.Function. +func (f *regAllocFn) PostOrderBlockIteratorBegin() *labelPosition { + f.blockIter = len(f.m.orderedSSABlockLabelPos) - 1 + return f.PostOrderBlockIteratorNext() +} + +// PostOrderBlockIteratorNext implements regalloc.Function. +func (f *regAllocFn) PostOrderBlockIteratorNext() *labelPosition { + if f.blockIter < 0 { + return nil + } + b := f.m.orderedSSABlockLabelPos[f.blockIter] + f.blockIter-- + return b +} + +// ReversePostOrderBlockIteratorBegin implements regalloc.Function. +func (f *regAllocFn) ReversePostOrderBlockIteratorBegin() *labelPosition { + f.blockIter = 0 + return f.ReversePostOrderBlockIteratorNext() +} + +// ReversePostOrderBlockIteratorNext implements regalloc.Function. +func (f *regAllocFn) ReversePostOrderBlockIteratorNext() *labelPosition { + if f.blockIter >= len(f.m.orderedSSABlockLabelPos) { + return nil + } + b := f.m.orderedSSABlockLabelPos[f.blockIter] + f.blockIter++ + return b +} + +// ClobberedRegisters implements regalloc.Function. +func (f *regAllocFn) ClobberedRegisters(regs []regalloc.VReg) { + f.m.clobberedRegs = append(f.m.clobberedRegs[:0], regs...) +} + +// LoopNestingForestRoots implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestRoots() int { + f.loopNestingForestRoots = f.ssaB.LoopNestingForestRoots() + return len(f.loopNestingForestRoots) +} + +// LoopNestingForestRoot implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestRoot(i int) *labelPosition { + root := f.loopNestingForestRoots[i] + pos := f.m.getOrAllocateSSABlockLabelPosition(root) + return pos +} + +// LowestCommonAncestor implements regalloc.Function. +func (f *regAllocFn) LowestCommonAncestor(blk1, blk2 *labelPosition) *labelPosition { + sb := f.ssaB.LowestCommonAncestor(blk1.sb, blk2.sb) + pos := f.m.getOrAllocateSSABlockLabelPosition(sb) + return pos +} + +// Idom implements regalloc.Function. +func (f *regAllocFn) Idom(blk *labelPosition) *labelPosition { + sb := f.ssaB.Idom(blk.sb) + pos := f.m.getOrAllocateSSABlockLabelPosition(sb) + return pos +} + +// SwapBefore implements regalloc.Function. +func (f *regAllocFn) SwapBefore(x1, x2, tmp regalloc.VReg, instr *instruction) { + f.m.swap(instr.prev, x1, x2, tmp) +} + +// StoreRegisterBefore implements regalloc.Function. +func (f *regAllocFn) StoreRegisterBefore(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertStoreRegisterAt(v, instr, false) +} + +// StoreRegisterAfter implements regalloc.Function. +func (f *regAllocFn) StoreRegisterAfter(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertStoreRegisterAt(v, instr, true) +} + +// ReloadRegisterBefore implements regalloc.Function. +func (f *regAllocFn) ReloadRegisterBefore(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertReloadRegisterAt(v, instr, false) +} + +// ReloadRegisterAfter implements regalloc.Function. +func (f *regAllocFn) ReloadRegisterAfter(v regalloc.VReg, instr *instruction) { + m := f.m + m.insertReloadRegisterAt(v, instr, true) +} + +// InsertMoveBefore implements regalloc.Function. +func (f *regAllocFn) InsertMoveBefore(dst, src regalloc.VReg, instr *instruction) { + f.m.insertMoveBefore(dst, src, instr) +} + +// LoopNestingForestChild implements regalloc.Function. +func (f *regAllocFn) LoopNestingForestChild(pos *labelPosition, i int) *labelPosition { + childSB := pos.sb.LoopNestingForestChildren()[i] + return f.m.getOrAllocateSSABlockLabelPosition(childSB) +} + +// Succ implements regalloc.Block. +func (f *regAllocFn) Succ(pos *labelPosition, i int) *labelPosition { + succSB := pos.sb.Succ(i) + if succSB.ReturnBlock() { + return nil + } + return f.m.getOrAllocateSSABlockLabelPosition(succSB) +} + +// Pred implements regalloc.Block. +func (f *regAllocFn) Pred(pos *labelPosition, i int) *labelPosition { + predSB := pos.sb.Pred(i) + return f.m.getOrAllocateSSABlockLabelPosition(predSB) +} + +// BlockParams implements regalloc.Function. +func (f *regAllocFn) BlockParams(pos *labelPosition, regs *[]regalloc.VReg) []regalloc.VReg { + c := f.m.compiler + *regs = (*regs)[:0] + for i := 0; i < pos.sb.Params(); i++ { + v := c.VRegOf(pos.sb.Param(i)) + *regs = append(*regs, v) + } + return *regs +} + +// ID implements regalloc.Block. +func (pos *labelPosition) ID() int32 { + return int32(pos.sb.ID()) +} + +// InstrIteratorBegin implements regalloc.Block. +func (pos *labelPosition) InstrIteratorBegin() *instruction { + ret := pos.begin + pos.cur = ret + return ret +} + +// InstrIteratorNext implements regalloc.Block. +func (pos *labelPosition) InstrIteratorNext() *instruction { + for { + if pos.cur == pos.end { + return nil + } + instr := pos.cur.next + pos.cur = instr + if instr == nil { + return nil + } else if instr.addedBeforeRegAlloc { + // Only concerned about the instruction added before regalloc. + return instr + } + } +} + +// InstrRevIteratorBegin implements regalloc.Block. +func (pos *labelPosition) InstrRevIteratorBegin() *instruction { + pos.cur = pos.end + return pos.cur +} + +// InstrRevIteratorNext implements regalloc.Block. +func (pos *labelPosition) InstrRevIteratorNext() *instruction { + for { + if pos.cur == pos.begin { + return nil + } + instr := pos.cur.prev + pos.cur = instr + if instr == nil { + return nil + } else if instr.addedBeforeRegAlloc { + // Only concerned about the instruction added before regalloc. + return instr + } + } +} + +// FirstInstr implements regalloc.Block. +func (pos *labelPosition) FirstInstr() *instruction { return pos.begin } + +// LastInstrForInsertion implements regalloc.Block. +func (pos *labelPosition) LastInstrForInsertion() *instruction { + return lastInstrForInsertion(pos.begin, pos.end) +} + +// Preds implements regalloc.Block. +func (pos *labelPosition) Preds() int { return pos.sb.Preds() } + +// Entry implements regalloc.Block. +func (pos *labelPosition) Entry() bool { return pos.sb.EntryBlock() } + +// Succs implements regalloc.Block. +func (pos *labelPosition) Succs() int { return pos.sb.Succs() } + +// LoopHeader implements regalloc.Block. +func (pos *labelPosition) LoopHeader() bool { return pos.sb.LoopHeader() } + +// LoopNestingForestChildren implements regalloc.Block. +func (pos *labelPosition) LoopNestingForestChildren() int { + return len(pos.sb.LoopNestingForestChildren()) +} + +func (m *machine) swap(cur *instruction, x1, x2, tmp regalloc.VReg) { + prevNext := cur.next + var mov1, mov2, mov3 *instruction + if x1.RegType() == regalloc.RegTypeInt { + if !tmp.Valid() { + tmp = tmpRegVReg + } + mov1 = m.allocateInstr().asMove64(tmp, x1) + mov2 = m.allocateInstr().asMove64(x1, x2) + mov3 = m.allocateInstr().asMove64(x2, tmp) + cur = linkInstr(cur, mov1) + cur = linkInstr(cur, mov2) + cur = linkInstr(cur, mov3) + linkInstr(cur, prevNext) + } else { + if !tmp.Valid() { + r2 := x2.RealReg() + // Temporarily spill x1 to stack. + cur = m.insertStoreRegisterAt(x1, cur, true).prev + // Then move x2 to x1. + cur = linkInstr(cur, m.allocateInstr().asFpuMov128(x1, x2)) + linkInstr(cur, prevNext) + // Then reload the original value on x1 from stack to r2. + m.insertReloadRegisterAt(x1.SetRealReg(r2), cur, true) + } else { + mov1 = m.allocateInstr().asFpuMov128(tmp, x1) + mov2 = m.allocateInstr().asFpuMov128(x1, x2) + mov3 = m.allocateInstr().asFpuMov128(x2, tmp) + cur = linkInstr(cur, mov1) + cur = linkInstr(cur, mov2) + cur = linkInstr(cur, mov3) + linkInstr(cur, prevNext) + } + } +} + +func (m *machine) insertMoveBefore(dst, src regalloc.VReg, instr *instruction) { + typ := src.RegType() + if typ != dst.RegType() { + panic("BUG: src and dst must have the same type") + } + + mov := m.allocateInstr() + if typ == regalloc.RegTypeInt { + mov.asMove64(dst, src) + } else { + mov.asFpuMov128(dst, src) + } + + cur := instr.prev + prevNext := cur.next + cur = linkInstr(cur, mov) + linkInstr(cur, prevNext) +} + +func (m *machine) insertStoreRegisterAt(v regalloc.VReg, instr *instruction, after bool) *instruction { + if !v.IsRealReg() { + panic("BUG: VReg must be backed by real reg to be stored") + } + + typ := m.compiler.TypeOf(v) + + var prevNext, cur *instruction + if after { + cur, prevNext = instr, instr.next + } else { + cur, prevNext = instr.prev, instr + } + + offsetFromSP := m.getVRegSpillSlotOffsetFromSP(v.ID(), typ.Size()) + var amode *addressMode + cur, amode = m.resolveAddressModeForOffsetAndInsert(cur, offsetFromSP, typ.Bits(), spVReg, true) + store := m.allocateInstr() + store.asStore(operandNR(v), amode, typ.Bits()) + + cur = linkInstr(cur, store) + return linkInstr(cur, prevNext) +} + +func (m *machine) insertReloadRegisterAt(v regalloc.VReg, instr *instruction, after bool) *instruction { + if !v.IsRealReg() { + panic("BUG: VReg must be backed by real reg to be stored") + } + + typ := m.compiler.TypeOf(v) + + var prevNext, cur *instruction + if after { + cur, prevNext = instr, instr.next + } else { + cur, prevNext = instr.prev, instr + } + + offsetFromSP := m.getVRegSpillSlotOffsetFromSP(v.ID(), typ.Size()) + var amode *addressMode + cur, amode = m.resolveAddressModeForOffsetAndInsert(cur, offsetFromSP, typ.Bits(), spVReg, true) + load := m.allocateInstr() + switch typ { + case ssa.TypeI32, ssa.TypeI64: + load.asULoad(v, amode, typ.Bits()) + case ssa.TypeF32, ssa.TypeF64: + load.asFpuLoad(v, amode, typ.Bits()) + case ssa.TypeV128: + load.asFpuLoad(v, amode, 128) + default: + panic("TODO") + } + + cur = linkInstr(cur, load) + return linkInstr(cur, prevNext) +} + +func lastInstrForInsertion(begin, end *instruction) *instruction { + cur := end + for cur.kind == nop0 { + cur = cur.prev + if cur == begin { + return end + } + } + switch cur.kind { + case br: + return cur + default: + return end + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_relocation.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_relocation.go new file mode 100644 index 00000000..932fe842 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/machine_relocation.go @@ -0,0 +1,122 @@ +package arm64 + +import ( + "encoding/binary" + "fmt" + "math" + "sort" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" +) + +const ( + // trampolineCallSize is the size of the trampoline instruction sequence for each function in an island. + trampolineCallSize = 4*4 + 4 // Four instructions + 32-bit immediate. + + // Unconditional branch offset is encoded as divided by 4 in imm26. + // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/BL--Branch-with-Link-?lang=en + + maxUnconditionalBranchOffset = maxSignedInt26 * 4 + minUnconditionalBranchOffset = minSignedInt26 * 4 + + // trampolineIslandInterval is the range of the trampoline island. + // Half of the range is used for the trampoline island, and the other half is used for the function. + trampolineIslandInterval = (maxUnconditionalBranchOffset - 1) / 2 + + // maxNumFunctions explicitly specifies the maximum number of functions that can be allowed in a single executable. + maxNumFunctions = trampolineIslandInterval >> 6 + + // maxFunctionExecutableSize is the maximum size of a function that can exist in a trampoline island. + // Conservatively set to 1/4 of the trampoline island interval. + maxFunctionExecutableSize = trampolineIslandInterval >> 2 +) + +// CallTrampolineIslandInfo implements backend.Machine CallTrampolineIslandInfo. +func (m *machine) CallTrampolineIslandInfo(numFunctions int) (interval, size int, err error) { + if numFunctions > maxNumFunctions { + return 0, 0, fmt.Errorf("too many functions: %d > %d", numFunctions, maxNumFunctions) + } + return trampolineIslandInterval, trampolineCallSize * numFunctions, nil +} + +// ResolveRelocations implements backend.Machine ResolveRelocations. +func (m *machine) ResolveRelocations( + refToBinaryOffset []int, + importedFns int, + executable []byte, + relocations []backend.RelocationInfo, + callTrampolineIslandOffsets []int, +) { + for _, islandOffset := range callTrampolineIslandOffsets { + encodeCallTrampolineIsland(refToBinaryOffset, importedFns, islandOffset, executable) + } + + for _, r := range relocations { + instrOffset := r.Offset + calleeFnOffset := refToBinaryOffset[r.FuncRef] + diff := int64(calleeFnOffset) - (instrOffset) + // Check if the diff is within the range of the branch instruction. + if diff < minUnconditionalBranchOffset || diff > maxUnconditionalBranchOffset { + // Find the near trampoline island from callTrampolineIslandOffsets. + islandOffset := searchTrampolineIsland(callTrampolineIslandOffsets, int(instrOffset)) + islandTargetOffset := islandOffset + trampolineCallSize*int(r.FuncRef) + diff = int64(islandTargetOffset) - (instrOffset) + if diff < minUnconditionalBranchOffset || diff > maxUnconditionalBranchOffset { + panic("BUG in trampoline placement") + } + } + binary.LittleEndian.PutUint32(executable[instrOffset:instrOffset+4], encodeUnconditionalBranch(true, diff)) + } +} + +// encodeCallTrampolineIsland encodes a trampoline island for the given functions. +// Each island consists of a trampoline instruction sequence for each function. +// Each trampoline instruction sequence consists of 4 instructions + 32-bit immediate. +func encodeCallTrampolineIsland(refToBinaryOffset []int, importedFns int, islandOffset int, executable []byte) { + // We skip the imported functions: they don't need trampolines + // and are not accounted for. + binaryOffsets := refToBinaryOffset[importedFns:] + + for i := 0; i < len(binaryOffsets); i++ { + trampolineOffset := islandOffset + trampolineCallSize*i + + fnOffset := binaryOffsets[i] + diff := fnOffset - (trampolineOffset + 16) + if diff > math.MaxInt32 || diff < math.MinInt32 { + // This case even amd64 can't handle. 4GB is too big. + panic("too big binary") + } + + // The tmpReg, tmpReg2 is safe to overwrite (in fact any caller-saved register is safe to use). + tmpReg, tmpReg2 := regNumberInEncoding[tmpRegVReg.RealReg()], regNumberInEncoding[x11] + + // adr tmpReg, PC+16: load the address of #diff into tmpReg. + binary.LittleEndian.PutUint32(executable[trampolineOffset:], encodeAdr(tmpReg, 16)) + // ldrsw tmpReg2, [tmpReg]: Load #diff into tmpReg2. + binary.LittleEndian.PutUint32(executable[trampolineOffset+4:], + encodeLoadOrStore(sLoad32, tmpReg2, addressMode{kind: addressModeKindRegUnsignedImm12, rn: tmpRegVReg})) + // add tmpReg, tmpReg2, tmpReg: add #diff to the address of #diff, getting the absolute address of the function. + binary.LittleEndian.PutUint32(executable[trampolineOffset+8:], + encodeAluRRR(aluOpAdd, tmpReg, tmpReg, tmpReg2, true, false)) + // br tmpReg: branch to the function without overwriting the link register. + binary.LittleEndian.PutUint32(executable[trampolineOffset+12:], encodeUnconditionalBranchReg(tmpReg, false)) + // #diff + binary.LittleEndian.PutUint32(executable[trampolineOffset+16:], uint32(diff)) + } +} + +// searchTrampolineIsland finds the nearest trampoline island from callTrampolineIslandOffsets. +// Note that even if the offset is in the middle of two islands, it returns the latter one. +// That is ok because the island is always placed in the middle of the range. +// +// precondition: callTrampolineIslandOffsets is sorted in ascending order. +func searchTrampolineIsland(callTrampolineIslandOffsets []int, offset int) int { + l := len(callTrampolineIslandOffsets) + n := sort.Search(l, func(i int) bool { + return callTrampolineIslandOffsets[i] >= offset + }) + if n == l { + n = l - 1 + } + return callTrampolineIslandOffsets[n] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/reg.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/reg.go new file mode 100644 index 00000000..45737516 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/reg.go @@ -0,0 +1,397 @@ +package arm64 + +import ( + "fmt" + "strconv" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" +) + +// Arm64-specific registers. +// +// See https://developer.arm.com/documentation/dui0801/a/Overview-of-AArch64-state/Predeclared-core-register-names-in-AArch64-state + +const ( + // General purpose registers. Note that we do not distinguish wn and xn registers + // because they are the same from the perspective of register allocator, and + // the size can be determined by the type of the instruction. + + x0 = regalloc.RealRegInvalid + 1 + iota + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 + + // Vector registers. Note that we do not distinguish vn and dn, ... registers + // because they are the same from the perspective of register allocator, and + // the size can be determined by the type of the instruction. + + v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + v13 + v14 + v15 + v16 + v17 + v18 + v19 + v20 + v21 + v22 + v23 + v24 + v25 + v26 + v27 + v28 + v29 + v30 + v31 + + // Special registers + + xzr + sp + lr = x30 + fp = x29 + tmp = x27 +) + +var ( + x0VReg = regalloc.FromRealReg(x0, regalloc.RegTypeInt) + x1VReg = regalloc.FromRealReg(x1, regalloc.RegTypeInt) + x2VReg = regalloc.FromRealReg(x2, regalloc.RegTypeInt) + x3VReg = regalloc.FromRealReg(x3, regalloc.RegTypeInt) + x4VReg = regalloc.FromRealReg(x4, regalloc.RegTypeInt) + x5VReg = regalloc.FromRealReg(x5, regalloc.RegTypeInt) + x6VReg = regalloc.FromRealReg(x6, regalloc.RegTypeInt) + x7VReg = regalloc.FromRealReg(x7, regalloc.RegTypeInt) + x8VReg = regalloc.FromRealReg(x8, regalloc.RegTypeInt) + x9VReg = regalloc.FromRealReg(x9, regalloc.RegTypeInt) + x10VReg = regalloc.FromRealReg(x10, regalloc.RegTypeInt) + x11VReg = regalloc.FromRealReg(x11, regalloc.RegTypeInt) + x12VReg = regalloc.FromRealReg(x12, regalloc.RegTypeInt) + x13VReg = regalloc.FromRealReg(x13, regalloc.RegTypeInt) + x14VReg = regalloc.FromRealReg(x14, regalloc.RegTypeInt) + x15VReg = regalloc.FromRealReg(x15, regalloc.RegTypeInt) + x16VReg = regalloc.FromRealReg(x16, regalloc.RegTypeInt) + x17VReg = regalloc.FromRealReg(x17, regalloc.RegTypeInt) + x18VReg = regalloc.FromRealReg(x18, regalloc.RegTypeInt) + x19VReg = regalloc.FromRealReg(x19, regalloc.RegTypeInt) + x20VReg = regalloc.FromRealReg(x20, regalloc.RegTypeInt) + x21VReg = regalloc.FromRealReg(x21, regalloc.RegTypeInt) + x22VReg = regalloc.FromRealReg(x22, regalloc.RegTypeInt) + x23VReg = regalloc.FromRealReg(x23, regalloc.RegTypeInt) + x24VReg = regalloc.FromRealReg(x24, regalloc.RegTypeInt) + x25VReg = regalloc.FromRealReg(x25, regalloc.RegTypeInt) + x26VReg = regalloc.FromRealReg(x26, regalloc.RegTypeInt) + x27VReg = regalloc.FromRealReg(x27, regalloc.RegTypeInt) + x28VReg = regalloc.FromRealReg(x28, regalloc.RegTypeInt) + x29VReg = regalloc.FromRealReg(x29, regalloc.RegTypeInt) + x30VReg = regalloc.FromRealReg(x30, regalloc.RegTypeInt) + v0VReg = regalloc.FromRealReg(v0, regalloc.RegTypeFloat) + v1VReg = regalloc.FromRealReg(v1, regalloc.RegTypeFloat) + v2VReg = regalloc.FromRealReg(v2, regalloc.RegTypeFloat) + v3VReg = regalloc.FromRealReg(v3, regalloc.RegTypeFloat) + v4VReg = regalloc.FromRealReg(v4, regalloc.RegTypeFloat) + v5VReg = regalloc.FromRealReg(v5, regalloc.RegTypeFloat) + v6VReg = regalloc.FromRealReg(v6, regalloc.RegTypeFloat) + v7VReg = regalloc.FromRealReg(v7, regalloc.RegTypeFloat) + v8VReg = regalloc.FromRealReg(v8, regalloc.RegTypeFloat) + v9VReg = regalloc.FromRealReg(v9, regalloc.RegTypeFloat) + v10VReg = regalloc.FromRealReg(v10, regalloc.RegTypeFloat) + v11VReg = regalloc.FromRealReg(v11, regalloc.RegTypeFloat) + v12VReg = regalloc.FromRealReg(v12, regalloc.RegTypeFloat) + v13VReg = regalloc.FromRealReg(v13, regalloc.RegTypeFloat) + v14VReg = regalloc.FromRealReg(v14, regalloc.RegTypeFloat) + v15VReg = regalloc.FromRealReg(v15, regalloc.RegTypeFloat) + v16VReg = regalloc.FromRealReg(v16, regalloc.RegTypeFloat) + v17VReg = regalloc.FromRealReg(v17, regalloc.RegTypeFloat) + v18VReg = regalloc.FromRealReg(v18, regalloc.RegTypeFloat) + v19VReg = regalloc.FromRealReg(v19, regalloc.RegTypeFloat) + v20VReg = regalloc.FromRealReg(v20, regalloc.RegTypeFloat) + v21VReg = regalloc.FromRealReg(v21, regalloc.RegTypeFloat) + v22VReg = regalloc.FromRealReg(v22, regalloc.RegTypeFloat) + v23VReg = regalloc.FromRealReg(v23, regalloc.RegTypeFloat) + v24VReg = regalloc.FromRealReg(v24, regalloc.RegTypeFloat) + v25VReg = regalloc.FromRealReg(v25, regalloc.RegTypeFloat) + v26VReg = regalloc.FromRealReg(v26, regalloc.RegTypeFloat) + v27VReg = regalloc.FromRealReg(v27, regalloc.RegTypeFloat) + // lr (link register) holds the return address at the function entry. + lrVReg = x30VReg + // tmpReg is used to perform spill/load on large stack offsets, and load large constants. + // Therefore, be cautious to use this register in the middle of the compilation, especially before the register allocation. + // This is the same as golang/go, but it's only described in the source code: + // https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L59 + // https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L13-L15 + tmpRegVReg = regalloc.FromRealReg(tmp, regalloc.RegTypeInt) + v28VReg = regalloc.FromRealReg(v28, regalloc.RegTypeFloat) + v29VReg = regalloc.FromRealReg(v29, regalloc.RegTypeFloat) + v30VReg = regalloc.FromRealReg(v30, regalloc.RegTypeFloat) + v31VReg = regalloc.FromRealReg(v31, regalloc.RegTypeFloat) + xzrVReg = regalloc.FromRealReg(xzr, regalloc.RegTypeInt) + spVReg = regalloc.FromRealReg(sp, regalloc.RegTypeInt) + fpVReg = regalloc.FromRealReg(fp, regalloc.RegTypeInt) +) + +var regNames = [...]string{ + x0: "x0", + x1: "x1", + x2: "x2", + x3: "x3", + x4: "x4", + x5: "x5", + x6: "x6", + x7: "x7", + x8: "x8", + x9: "x9", + x10: "x10", + x11: "x11", + x12: "x12", + x13: "x13", + x14: "x14", + x15: "x15", + x16: "x16", + x17: "x17", + x18: "x18", + x19: "x19", + x20: "x20", + x21: "x21", + x22: "x22", + x23: "x23", + x24: "x24", + x25: "x25", + x26: "x26", + x27: "x27", + x28: "x28", + x29: "x29", + x30: "x30", + xzr: "xzr", + sp: "sp", + v0: "v0", + v1: "v1", + v2: "v2", + v3: "v3", + v4: "v4", + v5: "v5", + v6: "v6", + v7: "v7", + v8: "v8", + v9: "v9", + v10: "v10", + v11: "v11", + v12: "v12", + v13: "v13", + v14: "v14", + v15: "v15", + v16: "v16", + v17: "v17", + v18: "v18", + v19: "v19", + v20: "v20", + v21: "v21", + v22: "v22", + v23: "v23", + v24: "v24", + v25: "v25", + v26: "v26", + v27: "v27", + v28: "v28", + v29: "v29", + v30: "v30", + v31: "v31", +} + +func formatVRegSized(r regalloc.VReg, size byte) (ret string) { + if r.IsRealReg() { + ret = regNames[r.RealReg()] + switch ret[0] { + case 'x': + switch size { + case 32: + ret = strings.Replace(ret, "x", "w", 1) + case 64: + default: + panic("BUG: invalid register size: " + strconv.Itoa(int(size))) + } + case 'v': + switch size { + case 32: + ret = strings.Replace(ret, "v", "s", 1) + case 64: + ret = strings.Replace(ret, "v", "d", 1) + case 128: + ret = strings.Replace(ret, "v", "q", 1) + default: + panic("BUG: invalid register size") + } + } + } else { + switch r.RegType() { + case regalloc.RegTypeInt: + switch size { + case 32: + ret = fmt.Sprintf("w%d?", r.ID()) + case 64: + ret = fmt.Sprintf("x%d?", r.ID()) + default: + panic("BUG: invalid register size: " + strconv.Itoa(int(size))) + } + case regalloc.RegTypeFloat: + switch size { + case 32: + ret = fmt.Sprintf("s%d?", r.ID()) + case 64: + ret = fmt.Sprintf("d%d?", r.ID()) + case 128: + ret = fmt.Sprintf("q%d?", r.ID()) + default: + panic("BUG: invalid register size") + } + default: + panic(fmt.Sprintf("BUG: invalid register type: %d for %s", r.RegType(), r)) + } + } + return +} + +func formatVRegWidthVec(r regalloc.VReg, width vecArrangement) (ret string) { + var id string + wspec := strings.ToLower(width.String()) + if r.IsRealReg() { + id = regNames[r.RealReg()][1:] + } else { + id = fmt.Sprintf("%d?", r.ID()) + } + ret = fmt.Sprintf("%s%s", wspec, id) + return +} + +func formatVRegVec(r regalloc.VReg, arr vecArrangement, index vecIndex) (ret string) { + id := fmt.Sprintf("v%d?", r.ID()) + if r.IsRealReg() { + id = regNames[r.RealReg()] + } + ret = fmt.Sprintf("%s.%s", id, strings.ToLower(arr.String())) + if index != vecIndexNone { + ret += fmt.Sprintf("[%d]", index) + } + return +} + +func regTypeToRegisterSizeInBits(r regalloc.RegType) byte { + switch r { + case regalloc.RegTypeInt: + return 64 + case regalloc.RegTypeFloat: + return 128 + default: + panic("BUG: invalid register type") + } +} + +var regNumberInEncoding = [...]uint32{ + x0: 0, + x1: 1, + x2: 2, + x3: 3, + x4: 4, + x5: 5, + x6: 6, + x7: 7, + x8: 8, + x9: 9, + x10: 10, + x11: 11, + x12: 12, + x13: 13, + x14: 14, + x15: 15, + x16: 16, + x17: 17, + x18: 18, + x19: 19, + x20: 20, + x21: 21, + x22: 22, + x23: 23, + x24: 24, + x25: 25, + x26: 26, + x27: 27, + x28: 28, + x29: 29, + x30: 30, + xzr: 31, + sp: 31, + v0: 0, + v1: 1, + v2: 2, + v3: 3, + v4: 4, + v5: 5, + v6: 6, + v7: 7, + v8: 8, + v9: 9, + v10: 10, + v11: 11, + v12: 12, + v13: 13, + v14: 14, + v15: 15, + v16: 16, + v17: 17, + v18: 18, + v19: 19, + v20: 20, + v21: 21, + v22: 22, + v23: 23, + v24: 24, + v25: 25, + v26: 26, + v27: 27, + v28: 28, + v29: 29, + v30: 30, + v31: 31, +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go new file mode 100644 index 00000000..a72b86f6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go @@ -0,0 +1,84 @@ +package arm64 + +import ( + "encoding/binary" + "reflect" + "unsafe" + + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +// UnwindStack implements wazevo.unwindStack. +func UnwindStack(sp, _, top uintptr, returnAddresses []uintptr) []uintptr { + l := int(top - sp) + + var stackBuf []byte + { + //nolint:staticcheck + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&stackBuf)) + hdr.Data = sp + hdr.Len = l + hdr.Cap = l + } + + for i := uint64(0); i < uint64(l); { + // (high address) + // +-----------------+ + // | ....... | + // | ret Y | <----+ + // | ....... | | + // | ret 0 | | + // | arg X | | size_of_arg_ret + // | ....... | | + // | arg 1 | | + // | arg 0 | <----+ + // | size_of_arg_ret | + // | ReturnAddress | + // +-----------------+ <----+ + // | ........... | | + // | spill slot M | | + // | ............ | | + // | spill slot 2 | | + // | spill slot 1 | | frame size + // | spill slot 1 | | + // | clobbered N | | + // | ............ | | + // | clobbered 0 | <----+ + // | xxxxxx | ;; unused space to make it 16-byte aligned. + // | frame_size | + // +-----------------+ <---- SP + // (low address) + + frameSize := binary.LittleEndian.Uint64(stackBuf[i:]) + i += frameSize + + 16 // frame size + aligned space. + retAddr := binary.LittleEndian.Uint64(stackBuf[i:]) + i += 8 // ret addr. + sizeOfArgRet := binary.LittleEndian.Uint64(stackBuf[i:]) + i += 8 + sizeOfArgRet + returnAddresses = append(returnAddresses, uintptr(retAddr)) + if len(returnAddresses) == wasmdebug.MaxFrames { + break + } + } + return returnAddresses +} + +// GoCallStackView implements wazevo.goCallStackView. +func GoCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { + // (high address) + // +-----------------+ <----+ + // | xxxxxxxxxxx | | ;; optional unused space to make it 16-byte aligned. + // ^ | arg[N]/ret[M] | | + // sliceSize | | ............ | | sliceSize + // | | arg[1]/ret[1] | | + // v | arg[0]/ret[0] | <----+ + // | sliceSize | + // | frame_size | + // +-----------------+ <---- stackPointerBeforeGoCall + // (low address) + ptr := unsafe.Pointer(stackPointerBeforeGoCall) + data := (*uint64)(unsafe.Add(ptr, 16)) // skips the (frame_size, sliceSize). + size := *(*uint64)(unsafe.Add(ptr, 8)) + return unsafe.Slice(data, size) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/machine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/machine.go new file mode 100644 index 00000000..3a29e7cd --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/machine.go @@ -0,0 +1,119 @@ +package backend + +import ( + "context" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +type ( + // Machine is a backend for a specific ISA machine. + Machine interface { + // StartLoweringFunction is called when the compilation of the given function is started. + // The maxBlockID is the maximum ssa.BasicBlockID in the function. + StartLoweringFunction(maxBlockID ssa.BasicBlockID) + + // LinkAdjacentBlocks is called after finished lowering all blocks in order to create one single instruction list. + LinkAdjacentBlocks(prev, next ssa.BasicBlock) + + // StartBlock is called when the compilation of the given block is started. + // The order of this being called is the reverse post order of the ssa.BasicBlock(s) as we iterate with + // ssa.Builder BlockIteratorReversePostOrderBegin and BlockIteratorReversePostOrderEnd. + StartBlock(ssa.BasicBlock) + + // EndBlock is called when the compilation of the current block is finished. + EndBlock() + + // FlushPendingInstructions flushes the pending instructions to the buffer. + // This will be called after the lowering of each SSA Instruction. + FlushPendingInstructions() + + // DisableStackCheck disables the stack check for the current compilation for debugging/testing. + DisableStackCheck() + + // SetCurrentABI initializes the FunctionABI for the given signature. + SetCurrentABI(abi *FunctionABI) + + // SetCompiler sets the compilation context used for the lifetime of Machine. + // This is only called once per Machine, i.e. before the first compilation. + SetCompiler(Compiler) + + // LowerSingleBranch is called when the compilation of the given single branch is started. + LowerSingleBranch(b *ssa.Instruction) + + // LowerConditionalBranch is called when the compilation of the given conditional branch is started. + LowerConditionalBranch(b *ssa.Instruction) + + // LowerInstr is called for each instruction in the given block except for the ones marked as already lowered + // via Compiler.MarkLowered. The order is reverse, i.e. from the last instruction to the first one. + // + // Note: this can lower multiple instructions (which produce the inputs) at once whenever it's possible + // for optimization. + LowerInstr(*ssa.Instruction) + + // Reset resets the machine state for the next compilation. + Reset() + + // InsertMove inserts a move instruction from src to dst whose type is typ. + InsertMove(dst, src regalloc.VReg, typ ssa.Type) + + // InsertReturn inserts the return instruction to return from the current function. + InsertReturn() + + // InsertLoadConstantBlockArg inserts the instruction(s) to load the constant value into the given regalloc.VReg. + InsertLoadConstantBlockArg(instr *ssa.Instruction, vr regalloc.VReg) + + // Format returns the string representation of the currently compiled machine code. + // This is only for testing purpose. + Format() string + + // RegAlloc does the register allocation after lowering. + RegAlloc() + + // PostRegAlloc does the post register allocation, e.g. setting up prologue/epilogue, redundant move elimination, etc. + PostRegAlloc() + + // ResolveRelocations resolves the relocations after emitting machine code. + // * refToBinaryOffset: the map from the function reference (ssa.FuncRef) to the executable offset. + // * importedFns: the max index of the imported functions at the beginning of refToBinaryOffset + // * executable: the binary to resolve the relocations. + // * relocations: the relocations to resolve. + // * callTrampolineIslandOffsets: the offsets of the trampoline islands in the executable. + ResolveRelocations( + refToBinaryOffset []int, + importedFns int, + executable []byte, + relocations []RelocationInfo, + callTrampolineIslandOffsets []int, + ) + + // Encode encodes the machine instructions to the Compiler. + Encode(ctx context.Context) error + + // CompileGoFunctionTrampoline compiles the trampoline function to call a Go function of the given exit code and signature. + CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte + + // CompileStackGrowCallSequence returns the sequence of instructions shared by all functions to + // call the stack grow builtin function. + CompileStackGrowCallSequence() []byte + + // CompileEntryPreamble returns the sequence of instructions shared by multiple functions to + // enter the function from Go. + CompileEntryPreamble(signature *ssa.Signature) []byte + + // LowerParams lowers the given parameters. + LowerParams(params []ssa.Value) + + // LowerReturns lowers the given returns. + LowerReturns(returns []ssa.Value) + + // ArgsResultsRegs returns the registers used for arguments and return values. + ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) + + // CallTrampolineIslandInfo returns the interval of the offset where the trampoline island is placed, and + // the size of the trampoline island. If islandSize is zero, the trampoline island is not used on this machine. + CallTrampolineIslandInfo(numFunctions int) (interval, islandSize int, err error) + } +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/api.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/api.go new file mode 100644 index 00000000..5d15bd9d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/api.go @@ -0,0 +1,124 @@ +package regalloc + +import "fmt" + +// These interfaces are implemented by ISA-specific backends to abstract away the details, and allow the register +// allocators to work on any ISA. + +type ( + // Function is the top-level interface to do register allocation, which corresponds to a CFG containing + // Blocks(s). + // + // I is the type of the instruction, and B is the type of the basic block. + Function[I Instr, B Block[I]] interface { + // PostOrderBlockIteratorBegin returns the first block in the post-order traversal of the CFG. + // In other words, the last blocks in the CFG will be returned first. + PostOrderBlockIteratorBegin() B + // PostOrderBlockIteratorNext returns the next block in the post-order traversal of the CFG. + PostOrderBlockIteratorNext() B + // ReversePostOrderBlockIteratorBegin returns the first block in the reverse post-order traversal of the CFG. + // In other words, the first blocks in the CFG will be returned first. + ReversePostOrderBlockIteratorBegin() B + // ReversePostOrderBlockIteratorNext returns the next block in the reverse post-order traversal of the CFG. + ReversePostOrderBlockIteratorNext() B + // ClobberedRegisters tell the clobbered registers by this function. + ClobberedRegisters([]VReg) + // LoopNestingForestRoots returns the number of roots of the loop nesting forest in a function. + LoopNestingForestRoots() int + // LoopNestingForestRoot returns the i-th root of the loop nesting forest in a function. + LoopNestingForestRoot(i int) B + // LowestCommonAncestor returns the lowest common ancestor of two blocks in the dominator tree. + LowestCommonAncestor(blk1, blk2 B) B + // Idom returns the immediate dominator of the given block. + Idom(blk B) B + + // LoopNestingForestChild returns the i-th child of the block in the loop nesting forest. + LoopNestingForestChild(b B, i int) B + // Pred returns the i-th predecessor of the block in the CFG. + Pred(b B, i int) B + // Succ returns the i-th successor of the block in the CFG. + Succ(b B, i int) B + // BlockParams returns the virtual registers used as the parameters of this block. + BlockParams(B, *[]VReg) []VReg + + // Followings are for rewriting the function. + + // SwapBefore swaps the two virtual registers at the end of the given block. + SwapBefore(x1, x2, tmp VReg, instr I) + // StoreRegisterBefore inserts store instruction(s) before the given instruction for the given virtual register. + StoreRegisterBefore(v VReg, instr I) + // StoreRegisterAfter inserts store instruction(s) after the given instruction for the given virtual register. + StoreRegisterAfter(v VReg, instr I) + // ReloadRegisterBefore inserts reload instruction(s) before the given instruction for the given virtual register. + ReloadRegisterBefore(v VReg, instr I) + // ReloadRegisterAfter inserts reload instruction(s) after the given instruction for the given virtual register. + ReloadRegisterAfter(v VReg, instr I) + // InsertMoveBefore inserts move instruction(s) before the given instruction for the given virtual registers. + InsertMoveBefore(dst, src VReg, instr I) + } + + // Block is a basic block in the CFG of a function, and it consists of multiple instructions, and predecessor Block(s). + // Right now, this corresponds to a ssa.BasicBlock lowered to the machine level. + Block[I Instr] interface { + comparable + // ID returns the unique identifier of this block which is ordered in the reverse post-order traversal of the CFG. + ID() int32 + // InstrIteratorBegin returns the first instruction in this block. Instructions added after lowering must be skipped. + // Note: multiple Instr(s) will not be held at the same time, so it's safe to use the same impl for the return Instr. + InstrIteratorBegin() I + // InstrIteratorNext returns the next instruction in this block. Instructions added after lowering must be skipped. + // Note: multiple Instr(s) will not be held at the same time, so it's safe to use the same impl for the return Instr. + InstrIteratorNext() I + // InstrRevIteratorBegin is the same as InstrIteratorBegin, but in the reverse order. + InstrRevIteratorBegin() I + // InstrRevIteratorNext is the same as InstrIteratorNext, but in the reverse order. + InstrRevIteratorNext() I + // FirstInstr returns the fist instruction in this block where instructions will be inserted after it. + FirstInstr() I + // LastInstrForInsertion returns the last instruction in this block where instructions will be inserted before it. + // Such insertions only happen when we need to insert spill/reload instructions to adjust the merge edges. + // At the time of register allocation, all the critical edges are already split, so there is no need + // to worry about the case where branching instruction has multiple successors. + // Therefore, usually, it is the nop instruction, but if the block ends with an unconditional branching, then it returns + // the unconditional branch, not the nop. In other words it is either nop or unconditional branch. + LastInstrForInsertion() I + // Preds returns the number of predecessors of this block in the CFG. + Preds() int + // Entry returns true if the block is for the entry block. + Entry() bool + // Succs returns the number of successors of this block in the CFG. + Succs() int + // LoopHeader returns true if this block is a loop header. + LoopHeader() bool + // LoopNestingForestChildren returns the number of children of this block in the loop nesting forest. + LoopNestingForestChildren() int + } + + // Instr is an instruction in a block, abstracting away the underlying ISA. + Instr interface { + comparable + fmt.Stringer + // Defs returns the virtual registers defined by this instruction. + Defs(*[]VReg) []VReg + // Uses returns the virtual registers used by this instruction. + // Note: multiple returned []VReg will not be held at the same time, so it's safe to use the same slice for this. + Uses(*[]VReg) []VReg + // AssignUse assigns the RealReg-allocated virtual register used by this instruction at the given index. + AssignUse(index int, v VReg) + // AssignDef assigns a RealReg-allocated virtual register defined by this instruction. + // This only accepts one register because we don't allocate registers for multi-def instructions (i.e. call instruction) + AssignDef(VReg) + // IsCopy returns true if this instruction is a move instruction between two registers. + // If true, the instruction is of the form of dst = src, and if the src and dst do not interfere with each other, + // we could coalesce them, and hence the copy can be eliminated from the final code. + IsCopy() bool + // IsCall returns true if this instruction is a call instruction. The result is used to insert + // caller saved register spills and restores. + IsCall() bool + // IsIndirectCall returns true if this instruction is an indirect call instruction which calls a function pointer. + // The result is used to insert caller saved register spills and restores. + IsIndirectCall() bool + // IsReturn returns true if this instruction is a return instruction. + IsReturn() bool + } +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/reg.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/reg.go new file mode 100644 index 00000000..46df807e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/reg.go @@ -0,0 +1,123 @@ +package regalloc + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// VReg represents a register which is assigned to an SSA value. This is used to represent a register in the backend. +// A VReg may or may not be a physical register, and the info of physical register can be obtained by RealReg. +type VReg uint64 + +// VRegID is the lower 32bit of VReg, which is the pure identifier of VReg without RealReg info. +type VRegID uint32 + +// RealReg returns the RealReg of this VReg. +func (v VReg) RealReg() RealReg { + return RealReg(v >> 32) +} + +// IsRealReg returns true if this VReg is backed by a physical register. +func (v VReg) IsRealReg() bool { + return v.RealReg() != RealRegInvalid +} + +// FromRealReg returns a VReg from the given RealReg and RegType. +// This is used to represent a specific pre-colored register in the backend. +func FromRealReg(r RealReg, typ RegType) VReg { + rid := VRegID(r) + if rid > vRegIDReservedForRealNum { + panic(fmt.Sprintf("invalid real reg %d", r)) + } + return VReg(r).SetRealReg(r).SetRegType(typ) +} + +// SetRealReg sets the RealReg of this VReg and returns the updated VReg. +func (v VReg) SetRealReg(r RealReg) VReg { + return VReg(r)<<32 | (v & 0xff_00_ffffffff) +} + +// RegType returns the RegType of this VReg. +func (v VReg) RegType() RegType { + return RegType(v >> 40) +} + +// SetRegType sets the RegType of this VReg and returns the updated VReg. +func (v VReg) SetRegType(t RegType) VReg { + return VReg(t)<<40 | (v & 0x00_ff_ffffffff) +} + +// ID returns the VRegID of this VReg. +func (v VReg) ID() VRegID { + return VRegID(v & 0xffffffff) +} + +// Valid returns true if this VReg is Valid. +func (v VReg) Valid() bool { + return v.ID() != vRegIDInvalid && v.RegType() != RegTypeInvalid +} + +// RealReg represents a physical register. +type RealReg byte + +const RealRegInvalid RealReg = 0 + +const ( + vRegIDInvalid VRegID = 1 << 31 + VRegIDNonReservedBegin = vRegIDReservedForRealNum + vRegIDReservedForRealNum VRegID = 128 + VRegInvalid = VReg(vRegIDInvalid) +) + +// String implements fmt.Stringer. +func (r RealReg) String() string { + switch r { + case RealRegInvalid: + return "invalid" + default: + return fmt.Sprintf("r%d", r) + } +} + +// String implements fmt.Stringer. +func (v VReg) String() string { + if v.IsRealReg() { + return fmt.Sprintf("r%d", v.ID()) + } + return fmt.Sprintf("v%d?", v.ID()) +} + +// RegType represents the type of a register. +type RegType byte + +const ( + RegTypeInvalid RegType = iota + RegTypeInt + RegTypeFloat + NumRegType +) + +// String implements fmt.Stringer. +func (r RegType) String() string { + switch r { + case RegTypeInt: + return "int" + case RegTypeFloat: + return "float" + default: + return "invalid" + } +} + +// RegTypeOf returns the RegType of the given ssa.Type. +func RegTypeOf(p ssa.Type) RegType { + switch p { + case ssa.TypeI32, ssa.TypeI64: + return RegTypeInt + case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128: + return RegTypeFloat + default: + panic("invalid type") + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regalloc.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regalloc.go new file mode 100644 index 00000000..a5857f4f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regalloc.go @@ -0,0 +1,1189 @@ +// Package regalloc performs register allocation. The algorithm can work on any ISA by implementing the interfaces in +// api.go. +// +// References: +// - https://web.stanford.edu/class/archive/cs/cs143/cs143.1128/lectures/17/Slides17.pdf +// - https://en.wikipedia.org/wiki/Chaitin%27s_algorithm +// - https://llvm.org/ProjectsWithLLVM/2004-Fall-CS426-LS.pdf +// - https://pfalcon.github.io/ssabook/latest/book-full.pdf: Chapter 9. for liveness analysis. +// - https://github.com/golang/go/blob/release-branch.go1.21/src/cmd/compile/internal/ssa/regalloc.go +package regalloc + +import ( + "fmt" + "math" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// NewAllocator returns a new Allocator. +func NewAllocator[I Instr, B Block[I], F Function[I, B]](allocatableRegs *RegisterInfo) Allocator[I, B, F] { + a := Allocator[I, B, F]{ + regInfo: allocatableRegs, + phiDefInstListPool: wazevoapi.NewPool[phiDefInstList[I]](resetPhiDefInstList[I]), + blockStates: wazevoapi.NewIDedPool[blockState[I, B, F]](resetBlockState[I, B, F]), + } + a.state.vrStates = wazevoapi.NewIDedPool[vrState[I, B, F]](resetVrState[I, B, F]) + a.state.reset() + for _, regs := range allocatableRegs.AllocatableRegisters { + for _, r := range regs { + a.allocatableSet = a.allocatableSet.add(r) + } + } + return a +} + +type ( + // RegisterInfo holds the statically-known ISA-specific register information. + RegisterInfo struct { + // AllocatableRegisters is a 2D array of allocatable RealReg, indexed by regTypeNum and regNum. + // The order matters: the first element is the most preferred one when allocating. + AllocatableRegisters [NumRegType][]RealReg + CalleeSavedRegisters RegSet + CallerSavedRegisters RegSet + RealRegToVReg []VReg + // RealRegName returns the name of the given RealReg for debugging. + RealRegName func(r RealReg) string + RealRegType func(r RealReg) RegType + } + + // Allocator is a register allocator. + Allocator[I Instr, B Block[I], F Function[I, B]] struct { + // regInfo is static per ABI/ISA, and is initialized by the machine during Machine.PrepareRegisterAllocator. + regInfo *RegisterInfo + // allocatableSet is a set of allocatable RealReg derived from regInfo. Static per ABI/ISA. + allocatableSet RegSet + allocatedCalleeSavedRegs []VReg + vs []VReg + ss []*vrState[I, B, F] + copies []_copy[I, B, F] + phiDefInstListPool wazevoapi.Pool[phiDefInstList[I]] + + // Followings are re-used during various places. + blks []B + reals []RealReg + + // Following two fields are updated while iterating the blocks in the reverse postorder. + state state[I, B, F] + blockStates wazevoapi.IDedPool[blockState[I, B, F]] + } + + // _copy represents a source and destination pair of a copy instruction. + _copy[I Instr, B Block[I], F Function[I, B]] struct { + src *vrState[I, B, F] + dstID VRegID + } + + // programCounter represents an opaque index into the program which is used to represents a LiveInterval of a VReg. + programCounter int32 + + state[I Instr, B Block[I], F Function[I, B]] struct { + argRealRegs []VReg + regsInUse regInUseSet[I, B, F] + vrStates wazevoapi.IDedPool[vrState[I, B, F]] + + currentBlockID int32 + + // allocatedRegSet is a set of RealReg that are allocated during the allocation phase. This is reset per function. + allocatedRegSet RegSet + } + + blockState[I Instr, B Block[I], F Function[I, B]] struct { + // liveIns is a list of VReg that are live at the beginning of the block. + liveIns []*vrState[I, B, F] + // seen is true if the block is visited during the liveness analysis. + seen bool + // visited is true if the block is visited during the allocation phase. + visited bool + startFromPredIndex int + // startRegs is a list of RealReg that are used at the beginning of the block. This is used to fix the merge edges. + startRegs regInUseSet[I, B, F] + // endRegs is a list of RealReg that are used at the end of the block. This is used to fix the merge edges. + endRegs regInUseSet[I, B, F] + } + + vrState[I Instr, B Block[I], f Function[I, B]] struct { + v VReg + r RealReg + // defInstr is the instruction that defines this value. If this is the phi value and not the entry block, this is nil. + defInstr I + // defBlk is the block that defines this value. If this is the phi value, this is the block whose arguments contain this value. + defBlk B + // lca = lowest common ancestor. This is the block that is the lowest common ancestor of all the blocks that + // reloads this value. This is used to determine the spill location. Only valid if spilled=true. + lca B + // lastUse is the program counter of the last use of this value. This changes while iterating the block, and + // should not be used across the blocks as it becomes invalid. To check the validity, use lastUseUpdatedAtBlockID. + lastUse programCounter + lastUseUpdatedAtBlockID int32 + // spilled is true if this value is spilled i.e. the value is reload from the stack somewhere in the program. + // + // Note that this field is used during liveness analysis for different purpose. This is used to determine the + // value is live-in or not. + spilled bool + // isPhi is true if this is a phi value. + isPhi bool + desiredLoc desiredLoc + // phiDefInstList is a list of instructions that defines this phi value. + // This is used to determine the spill location, and only valid if isPhi=true. + *phiDefInstList[I] + } + + // phiDefInstList is a linked list of instructions that defines a phi value. + phiDefInstList[I Instr] struct { + instr I + v VReg + next *phiDefInstList[I] + } + + // desiredLoc represents a desired location for a VReg. + desiredLoc uint16 + // desiredLocKind is a kind of desired location for a VReg. + desiredLocKind uint16 +) + +const ( + // desiredLocKindUnspecified is a kind of desired location for a VReg that is not specified. + desiredLocKindUnspecified desiredLocKind = iota + // desiredLocKindStack is a kind of desired location for a VReg that is on the stack, only used for the phi values. + desiredLocKindStack + // desiredLocKindReg is a kind of desired location for a VReg that is in a register. + desiredLocKindReg + desiredLocUnspecified = desiredLoc(desiredLocKindUnspecified) + desiredLocStack = desiredLoc(desiredLocKindStack) +) + +func newDesiredLocReg(r RealReg) desiredLoc { + return desiredLoc(desiredLocKindReg) | desiredLoc(r<<2) +} + +func (d desiredLoc) realReg() RealReg { + return RealReg(d >> 2) +} + +func (d desiredLoc) stack() bool { + return d&3 == desiredLoc(desiredLocKindStack) +} + +func resetPhiDefInstList[I Instr](l *phiDefInstList[I]) { + var nilInstr I + l.instr = nilInstr + l.next = nil + l.v = VRegInvalid +} + +func (s *state[I, B, F]) dump(info *RegisterInfo) { //nolint:unused + fmt.Println("\t\tstate:") + fmt.Println("\t\t\targRealRegs:", s.argRealRegs) + fmt.Println("\t\t\tregsInUse", s.regsInUse.format(info)) + fmt.Println("\t\t\tallocatedRegSet:", s.allocatedRegSet.format(info)) + fmt.Println("\t\t\tused:", s.regsInUse.format(info)) + var strs []string + for i := 0; i <= s.vrStates.MaxIDEncountered(); i++ { + vs := s.vrStates.Get(i) + if vs == nil { + continue + } + if vs.r != RealRegInvalid { + strs = append(strs, fmt.Sprintf("(v%d: %s)", vs.v.ID(), info.RealRegName(vs.r))) + } + } + fmt.Println("\t\t\tvrStates:", strings.Join(strs, ", ")) +} + +func (s *state[I, B, F]) reset() { + s.argRealRegs = s.argRealRegs[:0] + s.vrStates.Reset() + s.allocatedRegSet = RegSet(0) + s.regsInUse.reset() + s.currentBlockID = -1 +} + +func resetVrState[I Instr, B Block[I], F Function[I, B]](vs *vrState[I, B, F]) { + vs.v = VRegInvalid + vs.r = RealRegInvalid + var nilInstr I + vs.defInstr = nilInstr + var nilBlk B + vs.defBlk = nilBlk + vs.spilled = false + vs.lastUse = -1 + vs.lastUseUpdatedAtBlockID = -1 + vs.lca = nilBlk + vs.isPhi = false + vs.phiDefInstList = nil + vs.desiredLoc = desiredLocUnspecified +} + +func (s *state[I, B, F]) getOrAllocateVRegState(v VReg) *vrState[I, B, F] { + st := s.vrStates.GetOrAllocate(int(v.ID())) + if st.v == VRegInvalid { + st.v = v + } + return st +} + +func (s *state[I, B, F]) getVRegState(v VRegID) *vrState[I, B, F] { + return s.vrStates.Get(int(v)) +} + +func (s *state[I, B, F]) useRealReg(r RealReg, vr *vrState[I, B, F]) { + s.regsInUse.add(r, vr) + vr.r = r + s.allocatedRegSet = s.allocatedRegSet.add(r) +} + +func (s *state[I, B, F]) releaseRealReg(r RealReg) { + current := s.regsInUse.get(r) + if current != nil { + s.regsInUse.remove(r) + current.r = RealRegInvalid + } +} + +// recordReload records that the given VReg is reloaded in the given block. +// This is used to determine the spill location by tracking the lowest common ancestor of all the blocks that reloads the value. +func (vs *vrState[I, B, F]) recordReload(f F, blk B) { + vs.spilled = true + var nilBlk B + if lca := vs.lca; lca == nilBlk { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is reloaded in blk%d,\n", vs.v.ID(), blk.ID()) + } + vs.lca = blk + } else if lca != blk { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is reloaded in blk%d, lca=%d\n", vs.v.ID(), blk.ID(), vs.lca.ID()) + } + vs.lca = f.LowestCommonAncestor(lca, blk) + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("updated lca=%d\n", vs.lca.ID()) + } + } +} + +func (a *Allocator[I, B, F]) findOrSpillAllocatable(s *state[I, B, F], allocatable []RealReg, forbiddenMask RegSet, preferred RealReg) (r RealReg) { + r = RealRegInvalid + // First, check if the preferredMask has any allocatable register. + if preferred != RealRegInvalid && !forbiddenMask.has(preferred) && !s.regsInUse.has(preferred) { + return preferred + } + + var lastUseAt programCounter + var spillVReg VReg + for _, candidateReal := range allocatable { + if forbiddenMask.has(candidateReal) { + continue + } + + using := s.regsInUse.get(candidateReal) + if using == nil { + // This is not used at this point. + return candidateReal + } + + // Real registers in use should not be spilled, so we skip them. + // For example, if the register is used as an argument register, and it might be + // spilled and not reloaded when it ends up being used as a temporary to pass + // stack based argument. + if using.v.IsRealReg() { + continue + } + + isPreferred := candidateReal == preferred + + // last == -1 means the value won't be used anymore. + if last := using.lastUse; r == RealRegInvalid || isPreferred || last == -1 || (lastUseAt != -1 && last > lastUseAt) { + lastUseAt = last + r = candidateReal + spillVReg = using.v + if isPreferred { + break + } + } + } + + if r == RealRegInvalid { + panic("not found any allocatable register") + } + + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\tspilling v%d when lastUseAt=%d and regsInUse=%s\n", spillVReg.ID(), lastUseAt, s.regsInUse.format(a.regInfo)) + } + s.releaseRealReg(r) + return r +} + +func (s *state[I, B, F]) findAllocatable(allocatable []RealReg, forbiddenMask RegSet) RealReg { + for _, r := range allocatable { + if !s.regsInUse.has(r) && !forbiddenMask.has(r) { + return r + } + } + return RealRegInvalid +} + +func (s *state[I, B, F]) resetAt(bs *blockState[I, B, F]) { + s.regsInUse.range_(func(_ RealReg, vs *vrState[I, B, F]) { + vs.r = RealRegInvalid + }) + s.regsInUse.reset() + bs.endRegs.range_(func(r RealReg, vs *vrState[I, B, F]) { + if vs.lastUseUpdatedAtBlockID == s.currentBlockID && vs.lastUse == programCounterLiveIn { + s.regsInUse.add(r, vs) + vs.r = r + } + }) +} + +func resetBlockState[I Instr, B Block[I], F Function[I, B]](b *blockState[I, B, F]) { + b.seen = false + b.visited = false + b.endRegs.reset() + b.startRegs.reset() + b.startFromPredIndex = -1 + b.liveIns = b.liveIns[:0] +} + +func (b *blockState[I, B, F]) dump(a *RegisterInfo) { + fmt.Println("\t\tblockState:") + fmt.Println("\t\t\tstartRegs:", b.startRegs.format(a)) + fmt.Println("\t\t\tendRegs:", b.endRegs.format(a)) + fmt.Println("\t\t\tstartFromPredIndex:", b.startFromPredIndex) + fmt.Println("\t\t\tvisited:", b.visited) +} + +// DoAllocation performs register allocation on the given Function. +func (a *Allocator[I, B, F]) DoAllocation(f F) { + a.livenessAnalysis(f) + a.alloc(f) + a.determineCalleeSavedRealRegs(f) +} + +func (a *Allocator[I, B, F]) determineCalleeSavedRealRegs(f F) { + a.allocatedCalleeSavedRegs = a.allocatedCalleeSavedRegs[:0] + a.state.allocatedRegSet.Range(func(allocatedRealReg RealReg) { + if a.regInfo.CalleeSavedRegisters.has(allocatedRealReg) { + a.allocatedCalleeSavedRegs = append(a.allocatedCalleeSavedRegs, a.regInfo.RealRegToVReg[allocatedRealReg]) + } + }) + f.ClobberedRegisters(a.allocatedCalleeSavedRegs) +} + +func (a *Allocator[I, B, F]) getOrAllocateBlockState(blockID int32) *blockState[I, B, F] { + return a.blockStates.GetOrAllocate(int(blockID)) +} + +// phiBlk returns the block that defines the given phi value, nil otherwise. +func (vs *vrState[I, B, F]) phiBlk() B { + if vs.isPhi { + return vs.defBlk + } + var nilBlk B + return nilBlk +} + +const ( + programCounterLiveIn = math.MinInt32 + programCounterLiveOut = math.MaxInt32 +) + +// liveAnalysis constructs Allocator.blockLivenessData. +// The algorithm here is described in https://pfalcon.github.io/ssabook/latest/book-full.pdf Chapter 9.2. +func (a *Allocator[I, B, F]) livenessAnalysis(f F) { + s := &a.state + + for i := VRegID(0); i < vRegIDReservedForRealNum; i++ { + s.getOrAllocateVRegState(VReg(i).SetRealReg(RealReg(i))) + } + + var nilBlk B + var nilInstr I + for blk := f.PostOrderBlockIteratorBegin(); blk != nilBlk; blk = f.PostOrderBlockIteratorNext() { + // We should gather phi value data. + for _, p := range f.BlockParams(blk, &a.vs) { + vs := s.getOrAllocateVRegState(p) + vs.isPhi = true + vs.defBlk = blk + } + + blkID := blk.ID() + info := a.getOrAllocateBlockState(blkID) + + a.ss = a.ss[:0] + const ( + flagDeleted = false + flagLive = true + ) + ns := blk.Succs() + for i := 0; i < ns; i++ { + succ := f.Succ(blk, i) + if succ == nilBlk { + continue + } + + succID := succ.ID() + succInfo := a.getOrAllocateBlockState(succID) + if !succInfo.seen { // This means the back edge. + continue + } + + for _, st := range succInfo.liveIns { + if st.phiBlk() != succ && st.spilled != flagLive { //nolint:gosimple + // We use .spilled field to store the flag. + st.spilled = flagLive + a.ss = append(a.ss, st) + } + } + } + + for instr := blk.InstrRevIteratorBegin(); instr != nilInstr; instr = blk.InstrRevIteratorNext() { + + var use, def VReg + var defIsPhi bool + for _, def = range instr.Defs(&a.vs) { + if !def.IsRealReg() { + st := s.getOrAllocateVRegState(def) + defIsPhi = st.isPhi + // Note: We use .spilled field to store the flag. + st.spilled = flagDeleted + } + } + for _, use = range instr.Uses(&a.vs) { + if !use.IsRealReg() { + st := s.getOrAllocateVRegState(use) + // Note: We use .spilled field to store the flag. + if st.spilled != flagLive { //nolint:gosimple + st.spilled = flagLive + a.ss = append(a.ss, st) + } + } + } + + if defIsPhi { + if use.Valid() && use.IsRealReg() { + // If the destination is a phi value, and the source is a real register, this is the beginning of the function. + a.state.argRealRegs = append(a.state.argRealRegs, use) + } + } + } + + for _, st := range a.ss { + // We use .spilled field to store the flag. + if st.spilled == flagLive { //nolint:gosimple + info.liveIns = append(info.liveIns, st) + st.spilled = false + } + } + + info.seen = true + } + + nrs := f.LoopNestingForestRoots() + for i := 0; i < nrs; i++ { + root := f.LoopNestingForestRoot(i) + a.loopTreeDFS(f, root) + } +} + +// loopTreeDFS implements the Algorithm 9.3 in the book in an iterative way. +func (a *Allocator[I, B, F]) loopTreeDFS(f F, entry B) { + a.blks = a.blks[:0] + a.blks = append(a.blks, entry) + + for len(a.blks) > 0 { + tail := len(a.blks) - 1 + loop := a.blks[tail] + a.blks = a.blks[:tail] + a.ss = a.ss[:0] + const ( + flagDone = false + flagPending = true + ) + info := a.getOrAllocateBlockState(loop.ID()) + for _, st := range info.liveIns { + if st.phiBlk() != loop { + a.ss = append(a.ss, st) + // We use .spilled field to store the flag. + st.spilled = flagPending + } + } + + var siblingAddedView []*vrState[I, B, F] + cn := loop.LoopNestingForestChildren() + for i := 0; i < cn; i++ { + child := f.LoopNestingForestChild(loop, i) + childID := child.ID() + childInfo := a.getOrAllocateBlockState(childID) + + if i == 0 { + begin := len(childInfo.liveIns) + for _, st := range a.ss { + // We use .spilled field to store the flag. + if st.spilled == flagPending { //nolint:gosimple + st.spilled = flagDone + // TODO: deduplicate, though I don't think it has much impact. + childInfo.liveIns = append(childInfo.liveIns, st) + } + } + siblingAddedView = childInfo.liveIns[begin:] + } else { + // TODO: deduplicate, though I don't think it has much impact. + childInfo.liveIns = append(childInfo.liveIns, siblingAddedView...) + } + + if child.LoopHeader() { + a.blks = append(a.blks, child) + } + } + + if cn == 0 { + // If there's no forest child, we haven't cleared the .spilled field at this point. + for _, st := range a.ss { + st.spilled = false + } + } + } +} + +// alloc allocates registers for the given function by iterating the blocks in the reverse postorder. +// The algorithm here is derived from the Go compiler's allocator https://github.com/golang/go/blob/release-branch.go1.21/src/cmd/compile/internal/ssa/regalloc.go +// In short, this is a simply linear scan register allocation where each block inherits the register allocation state from +// one of its predecessors. Each block inherits the selected state and starts allocation from there. +// If there's a discrepancy in the end states between predecessors, the adjustments are made to ensure consistency after allocation is done (which we call "fixing merge state"). +// The spill instructions (store into the dedicated slots) are inserted after all the allocations and fixing merge states. That is because +// at the point, we all know where the reloads happen, and therefore we can know the best place to spill the values. More precisely, +// the spill happens in the block that is the lowest common ancestor of all the blocks that reloads the value. +// +// All of these logics are almost the same as Go's compiler which has a dedicated description in the source file ^^. +func (a *Allocator[I, B, F]) alloc(f F) { + // First we allocate each block in the reverse postorder (at least one predecessor should be allocated for each block). + var nilBlk B + for blk := f.ReversePostOrderBlockIteratorBegin(); blk != nilBlk; blk = f.ReversePostOrderBlockIteratorNext() { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("========== allocating blk%d ========\n", blk.ID()) + } + if blk.Entry() { + a.finalizeStartReg(f, blk) + } + a.allocBlock(f, blk) + } + // After the allocation, we all know the start and end state of each block. So we can fix the merge states. + for blk := f.ReversePostOrderBlockIteratorBegin(); blk != nilBlk; blk = f.ReversePostOrderBlockIteratorNext() { + a.fixMergeState(f, blk) + } + // Finally, we insert the spill instructions as we know all the places where the reloads happen. + a.scheduleSpills(f) +} + +func (a *Allocator[I, B, F]) updateLiveInVRState(liveness *blockState[I, B, F]) { + currentBlockID := a.state.currentBlockID + for _, vs := range liveness.liveIns { + vs.lastUse = programCounterLiveIn + vs.lastUseUpdatedAtBlockID = currentBlockID + } +} + +func (a *Allocator[I, B, F]) finalizeStartReg(f F, blk B) { + bID := blk.ID() + s := &a.state + currentBlkState := a.getOrAllocateBlockState(bID) + if currentBlkState.startFromPredIndex > -1 { + return + } + + s.currentBlockID = bID + a.updateLiveInVRState(currentBlkState) + + preds := blk.Preds() + var predState *blockState[I, B, F] + switch preds { + case 0: // This is the entry block. + case 1: + predID := f.Pred(blk, 0).ID() + predState = a.getOrAllocateBlockState(predID) + currentBlkState.startFromPredIndex = 0 + default: + // TODO: there should be some better heuristic to choose the predecessor. + for i := 0; i < preds; i++ { + predID := f.Pred(blk, i).ID() + if _predState := a.getOrAllocateBlockState(predID); _predState.visited { + predState = _predState + currentBlkState.startFromPredIndex = i + break + } + } + } + if predState == nil { + if !blk.Entry() { + panic(fmt.Sprintf("BUG: at lease one predecessor should be visited for blk%d", blk.ID())) + } + for _, u := range s.argRealRegs { + s.useRealReg(u.RealReg(), s.getVRegState(u.ID())) + } + currentBlkState.startFromPredIndex = 0 + } else { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("allocating blk%d starting from blk%d (on index=%d) \n", + bID, f.Pred(blk, currentBlkState.startFromPredIndex).ID(), currentBlkState.startFromPredIndex) + } + s.resetAt(predState) + } + + s.regsInUse.range_(func(allocated RealReg, v *vrState[I, B, F]) { + currentBlkState.startRegs.add(allocated, v) + }) + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("finalized start reg for blk%d: %s\n", blk.ID(), currentBlkState.startRegs.format(a.regInfo)) + } +} + +func (a *Allocator[I, B, F]) allocBlock(f F, blk B) { + bID := blk.ID() + s := &a.state + currentBlkState := a.getOrAllocateBlockState(bID) + s.currentBlockID = bID + + if currentBlkState.startFromPredIndex < 0 { + panic("BUG: startFromPredIndex should be set in finalizeStartReg prior to allocBlock") + } + + // Clears the previous state. + s.regsInUse.range_(func(allocatedRealReg RealReg, vr *vrState[I, B, F]) { vr.r = RealRegInvalid }) + s.regsInUse.reset() + // Then set the start state. + currentBlkState.startRegs.range_(func(allocatedRealReg RealReg, vr *vrState[I, B, F]) { s.useRealReg(allocatedRealReg, vr) }) + + desiredUpdated := a.ss[:0] + + // Update the last use of each VReg. + a.copies = a.copies[:0] // Stores the copy instructions. + var pc programCounter + var nilInstr I + for instr := blk.InstrIteratorBegin(); instr != nilInstr; instr = blk.InstrIteratorNext() { + var useState *vrState[I, B, F] + for _, use := range instr.Uses(&a.vs) { + useState = s.getVRegState(use.ID()) + if !use.IsRealReg() { + useState.lastUse = pc + } + } + + if instr.IsCopy() { + def := instr.Defs(&a.vs)[0] + a.copies = append(a.copies, _copy[I, B, F]{src: useState, dstID: def.ID()}) + r := def.RealReg() + if r != RealRegInvalid { + if !useState.isPhi { // TODO: no idea why do we need this. + useState.desiredLoc = newDesiredLocReg(r) + desiredUpdated = append(desiredUpdated, useState) + } + } + } + pc++ + } + + // Mark all live-out values by checking live-in of the successors. + // While doing so, we also update the desired register values. + var succ B + var nilBlk B + for i, ns := 0, blk.Succs(); i < ns; i++ { + succ = f.Succ(blk, i) + if succ == nilBlk { + continue + } + + succID := succ.ID() + succState := a.getOrAllocateBlockState(succID) + for _, st := range succState.liveIns { + if st.phiBlk() != succ { + st.lastUse = programCounterLiveOut + } + } + + if succState.startFromPredIndex > -1 { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("blk%d -> blk%d: start_regs: %s\n", bID, succID, succState.startRegs.format(a.regInfo)) + } + succState.startRegs.range_(func(allocatedRealReg RealReg, vs *vrState[I, B, F]) { + vs.desiredLoc = newDesiredLocReg(allocatedRealReg) + desiredUpdated = append(desiredUpdated, vs) + }) + for _, p := range f.BlockParams(succ, &a.vs) { + vs := s.getVRegState(p.ID()) + if vs.desiredLoc.realReg() == RealRegInvalid { + vs.desiredLoc = desiredLocStack + desiredUpdated = append(desiredUpdated, vs) + } + } + } + } + + // Propagate the desired register values from the end of the block to the beginning. + for _, instr := range a.copies { + defState := s.getVRegState(instr.dstID) + desired := defState.desiredLoc.realReg() + useState := instr.src + if useState.phiBlk() != succ && useState.desiredLoc == desiredLocUnspecified { + useState.desiredLoc = newDesiredLocReg(desired) + desiredUpdated = append(desiredUpdated, useState) + } + } + + pc = 0 + for instr := blk.InstrIteratorBegin(); instr != nilInstr; instr = blk.InstrIteratorNext() { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Println(instr) + } + + var currentUsedSet RegSet + killSet := a.reals[:0] + + // Gather the set of registers that will be used in the current instruction. + uses := instr.Uses(&a.vs) + for _, use := range uses { + if use.IsRealReg() { + r := use.RealReg() + currentUsedSet = currentUsedSet.add(r) + if a.allocatableSet.has(r) { + killSet = append(killSet, r) + } + } else { + vs := s.getVRegState(use.ID()) + if r := vs.r; r != RealRegInvalid { + currentUsedSet = currentUsedSet.add(r) + } + } + } + + for i, use := range uses { + if !use.IsRealReg() { + vs := s.getVRegState(use.ID()) + killed := vs.lastUse == pc + r := vs.r + + if r == RealRegInvalid { + r = a.findOrSpillAllocatable(s, a.regInfo.AllocatableRegisters[use.RegType()], currentUsedSet, + // Prefer the desired register if it's available. + vs.desiredLoc.realReg()) + vs.recordReload(f, blk) + f.ReloadRegisterBefore(use.SetRealReg(r), instr) + s.useRealReg(r, vs) + } + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\ttrying to use v%v on %s\n", use.ID(), a.regInfo.RealRegName(r)) + } + instr.AssignUse(i, use.SetRealReg(r)) + currentUsedSet = currentUsedSet.add(r) + if killed { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\tkill v%d with %s\n", use.ID(), a.regInfo.RealRegName(r)) + } + killSet = append(killSet, r) + } + } + } + + isIndirect := instr.IsIndirectCall() + if instr.IsCall() || isIndirect { + addr := RealRegInvalid + if isIndirect { + addr = a.vs[0].RealReg() + } + a.releaseCallerSavedRegs(addr) + } + + for _, r := range killSet { + s.releaseRealReg(r) + } + a.reals = killSet + + defs := instr.Defs(&a.vs) + switch len(defs) { + default: + // Some instructions define multiple values on real registers. + // E.g. call instructions (following calling convention) / div instruction on x64 that defines both rax and rdx. + // + // Note that currently I assume that such instructions define only the pre colored real registers, not the VRegs + // that require allocations. If we need to support such case, we need to add the logic to handle it here, + // though is there any such instruction? + for _, def := range defs { + if !def.IsRealReg() { + panic("BUG: multiple defs should be on real registers") + } + r := def.RealReg() + if s.regsInUse.has(r) { + s.releaseRealReg(r) + } + s.useRealReg(r, s.getVRegState(def.ID())) + } + case 0: + case 1: + def := defs[0] + vState := s.getVRegState(def.ID()) + if def.IsRealReg() { + r := def.RealReg() + if a.allocatableSet.has(r) { + if s.regsInUse.has(r) { + s.releaseRealReg(r) + } + s.useRealReg(r, vState) + } + } else { + r := vState.r + + if desired := vState.desiredLoc.realReg(); desired != RealRegInvalid { + if r != desired { + if (vState.isPhi && vState.defBlk == succ) || + // If this is not a phi and it's already assigned a real reg, + // this value has multiple definitions, hence we cannot assign the desired register. + (!s.regsInUse.has(desired) && r == RealRegInvalid) { + // If the phi value is passed via a real register, we force the value to be in the desired register. + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is phi and desiredReg=%s\n", def.ID(), a.regInfo.RealRegName(desired)) + } + if r != RealRegInvalid { + // If the value is already in a different real register, we release it to change the state. + // Otherwise, multiple registers might have the same values at the end, which results in + // messing up the merge state reconciliation. + s.releaseRealReg(r) + } + r = desired + s.releaseRealReg(r) + s.useRealReg(r, vState) + } + } + } + + // Allocate a new real register if `def` is not currently assigned one. + // It can happen when multiple instructions define the same VReg (e.g. const loads). + if r == RealRegInvalid { + if instr.IsCopy() { + copySrc := instr.Uses(&a.vs)[0].RealReg() + if a.allocatableSet.has(copySrc) && !s.regsInUse.has(copySrc) { + r = copySrc + } + } + if r == RealRegInvalid { + typ := def.RegType() + r = a.findOrSpillAllocatable(s, a.regInfo.AllocatableRegisters[typ], RegSet(0), RealRegInvalid) + } + s.useRealReg(r, vState) + } + dr := def.SetRealReg(r) + instr.AssignDef(dr) + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\tdefining v%d with %s\n", def.ID(), a.regInfo.RealRegName(r)) + } + if vState.isPhi { + if vState.desiredLoc.stack() { // Stack based phi value. + f.StoreRegisterAfter(dr, instr) + // Release the real register as it's not used anymore. + s.releaseRealReg(r) + } else { + // Only the register based phis are necessary to track the defining instructions + // since the stack-based phis are already having stores inserted ^. + n := a.phiDefInstListPool.Allocate() + n.instr = instr + n.next = vState.phiDefInstList + n.v = dr + vState.phiDefInstList = n + } + } else { + vState.defInstr = instr + vState.defBlk = blk + } + } + } + if wazevoapi.RegAllocLoggingEnabled { + fmt.Println(instr) + } + pc++ + } + + s.regsInUse.range_(func(allocated RealReg, v *vrState[I, B, F]) { currentBlkState.endRegs.add(allocated, v) }) + + currentBlkState.visited = true + if wazevoapi.RegAllocLoggingEnabled { + currentBlkState.dump(a.regInfo) + } + + // Reset the desired end location. + for _, vs := range desiredUpdated { + vs.desiredLoc = desiredLocUnspecified + } + a.ss = desiredUpdated[:0] + + for i := 0; i < blk.Succs(); i++ { + succ := f.Succ(blk, i) + if succ == nilBlk { + continue + } + // If the successor is not visited yet, finalize the start state. + a.finalizeStartReg(f, succ) + } +} + +func (a *Allocator[I, B, F]) releaseCallerSavedRegs(addrReg RealReg) { + s := &a.state + + for allocated := RealReg(0); allocated < 64; allocated++ { + if allocated == addrReg { // If this is the call indirect, we should not touch the addr register. + continue + } + if vs := s.regsInUse.get(allocated); vs != nil { + if vs.v.IsRealReg() { + continue // This is the argument register as it's already used by VReg backed by the corresponding RealReg. + } + if !a.regInfo.CallerSavedRegisters.has(allocated) { + // If this is not a caller-saved register, it is safe to keep it across the call. + continue + } + s.releaseRealReg(allocated) + } + } +} + +func (a *Allocator[I, B, F]) fixMergeState(f F, blk B) { + preds := blk.Preds() + if preds <= 1 { + return + } + + s := &a.state + + // Restores the state at the beginning of the block. + bID := blk.ID() + blkSt := a.getOrAllocateBlockState(bID) + desiredOccupants := &blkSt.startRegs + var desiredOccupantsSet RegSet + for i, v := range desiredOccupants { + if v != nil { + desiredOccupantsSet = desiredOccupantsSet.add(RealReg(i)) + } + } + + if wazevoapi.RegAllocLoggingEnabled { + fmt.Println("fixMergeState", blk.ID(), ":", desiredOccupants.format(a.regInfo)) + } + + s.currentBlockID = bID + a.updateLiveInVRState(blkSt) + + for i := 0; i < preds; i++ { + if i == blkSt.startFromPredIndex { + continue + } + + pred := f.Pred(blk, i) + predSt := a.getOrAllocateBlockState(pred.ID()) + + s.resetAt(predSt) + + // Finds the free registers if any. + intTmp, floatTmp := VRegInvalid, VRegInvalid + if intFree := s.findAllocatable( + a.regInfo.AllocatableRegisters[RegTypeInt], desiredOccupantsSet, + ); intFree != RealRegInvalid { + intTmp = FromRealReg(intFree, RegTypeInt) + } + if floatFree := s.findAllocatable( + a.regInfo.AllocatableRegisters[RegTypeFloat], desiredOccupantsSet, + ); floatFree != RealRegInvalid { + floatTmp = FromRealReg(floatFree, RegTypeFloat) + } + + for r := RealReg(0); r < 64; r++ { + desiredVReg := desiredOccupants.get(r) + if desiredVReg == nil { + continue + } + + currentVReg := s.regsInUse.get(r) + if currentVReg != nil && desiredVReg.v.ID() == currentVReg.v.ID() { + continue + } + + typ := desiredVReg.v.RegType() + var tmpRealReg VReg + if typ == RegTypeInt { + tmpRealReg = intTmp + } else { + tmpRealReg = floatTmp + } + a.reconcileEdge(f, r, pred, currentVReg, desiredVReg, tmpRealReg, typ) + } + } +} + +// reconcileEdge reconciles the register state between the current block and the predecessor for the real register `r`. +// +// - currentVReg is the current VReg value that sits on the register `r`. This can be VRegInvalid if the register is not used at the end of the predecessor. +// - desiredVReg is the desired VReg value that should be on the register `r`. +// - freeReg is the temporary register that can be used to swap the values, which may or may not be used. +// - typ is the register type of the `r`. +func (a *Allocator[I, B, F]) reconcileEdge(f F, + r RealReg, + pred B, + currentState, desiredState *vrState[I, B, F], + freeReg VReg, + typ RegType, +) { + desiredVReg := desiredState.v + currentVReg := VRegInvalid + if currentState != nil { + currentVReg = currentState.v + } + // There are four cases to consider: + // 1. currentVReg is valid, but desiredVReg is on the stack. + // 2. Both currentVReg and desiredVReg are valid. + // 3. Desired is on a different register than `r` and currentReg is not valid. + // 4. Desired is on the stack and currentReg is not valid. + + s := &a.state + if currentVReg.Valid() { + er := desiredState.r + if er == RealRegInvalid { + // Case 1: currentVReg is valid, but desiredVReg is on the stack. + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is desired to be on %s, but currently on the stack\n", + desiredVReg.ID(), a.regInfo.RealRegName(r), + ) + } + // We need to move the current value to the stack, and reload the desired value into the register. + // TODO: we can do better here. + f.StoreRegisterBefore(currentVReg.SetRealReg(r), pred.LastInstrForInsertion()) + s.releaseRealReg(r) + + desiredState.recordReload(f, pred) + f.ReloadRegisterBefore(desiredVReg.SetRealReg(r), pred.LastInstrForInsertion()) + s.useRealReg(r, desiredState) + return + } else { + // Case 2: Both currentVReg and desiredVReg are valid. + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is desired to be on %s, but currently on %s\n", + desiredVReg.ID(), a.regInfo.RealRegName(r), a.regInfo.RealRegName(er), + ) + } + // This case, we need to swap the values between the current and desired values. + f.SwapBefore( + currentVReg.SetRealReg(r), + desiredVReg.SetRealReg(er), + freeReg, + pred.LastInstrForInsertion(), + ) + s.allocatedRegSet = s.allocatedRegSet.add(freeReg.RealReg()) + s.releaseRealReg(r) + s.releaseRealReg(er) + s.useRealReg(r, desiredState) + s.useRealReg(er, currentState) + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d previously on %s moved to %s\n", currentVReg.ID(), a.regInfo.RealRegName(r), a.regInfo.RealRegName(er)) + } + } + } else { + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("\t\tv%d is desired to be on %s, current not used\n", + desiredVReg.ID(), a.regInfo.RealRegName(r), + ) + } + if currentReg := desiredState.r; currentReg != RealRegInvalid { + // Case 3: Desired is on a different register than `r` and currentReg is not valid. + // We simply need to move the desired value to the register. + f.InsertMoveBefore( + FromRealReg(r, typ), + desiredVReg.SetRealReg(currentReg), + pred.LastInstrForInsertion(), + ) + s.releaseRealReg(currentReg) + } else { + // Case 4: Both currentVReg and desiredVReg are not valid. + // We simply need to reload the desired value into the register. + desiredState.recordReload(f, pred) + f.ReloadRegisterBefore(desiredVReg.SetRealReg(r), pred.LastInstrForInsertion()) + } + s.useRealReg(r, desiredState) + } +} + +func (a *Allocator[I, B, F]) scheduleSpills(f F) { + states := a.state.vrStates + for i := 0; i <= states.MaxIDEncountered(); i++ { + vs := states.Get(i) + if vs == nil { + continue + } + if vs.spilled { + a.scheduleSpill(f, vs) + } + } +} + +func (a *Allocator[I, B, F]) scheduleSpill(f F, vs *vrState[I, B, F]) { + v := vs.v + // If the value is the phi value, we need to insert a spill after each phi definition. + if vs.isPhi { + for defInstr := vs.phiDefInstList; defInstr != nil; defInstr = defInstr.next { + f.StoreRegisterAfter(defInstr.v, defInstr.instr) + } + return + } + + pos := vs.lca + definingBlk := vs.defBlk + r := RealRegInvalid + var nilBlk B + if definingBlk == nilBlk { + panic(fmt.Sprintf("BUG: definingBlk should not be nil for %s. This is likley a bug in backend lowering logic", vs.v.String())) + } + if pos == nilBlk { + panic(fmt.Sprintf("BUG: pos should not be nil for %s. This is likley a bug in backend lowering logic", vs.v.String())) + } + + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("v%d is spilled in blk%d, lca=blk%d\n", v.ID(), definingBlk.ID(), pos.ID()) + } + for pos != definingBlk { + st := a.getOrAllocateBlockState(pos.ID()) + for rr := RealReg(0); rr < 64; rr++ { + if vs := st.startRegs.get(rr); vs != nil && vs.v == v { + r = rr + // Already in the register, so we can place the spill at the beginning of the block. + break + } + } + + if r != RealRegInvalid { + break + } + + pos = f.Idom(pos) + } + + if pos == definingBlk { + defInstr := vs.defInstr + defInstr.Defs(&a.vs) + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("schedule spill v%d after %v\n", v.ID(), defInstr) + } + f.StoreRegisterAfter(a.vs[0], defInstr) + } else { + // Found an ancestor block that holds the value in the register at the beginning of the block. + // We need to insert a spill before the last use. + first := pos.FirstInstr() + if wazevoapi.RegAllocLoggingEnabled { + fmt.Printf("schedule spill v%d before %v\n", v.ID(), first) + } + f.StoreRegisterAfter(v.SetRealReg(r), first) + } +} + +// Reset resets the allocator's internal state so that it can be reused. +func (a *Allocator[I, B, F]) Reset() { + a.state.reset() + a.blockStates.Reset() + a.phiDefInstListPool.Reset() + a.vs = a.vs[:0] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regset.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regset.go new file mode 100644 index 00000000..ce84c9c0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc/regset.go @@ -0,0 +1,96 @@ +package regalloc + +import ( + "fmt" + "strings" +) + +// NewRegSet returns a new RegSet with the given registers. +func NewRegSet(regs ...RealReg) RegSet { + var ret RegSet + for _, r := range regs { + ret = ret.add(r) + } + return ret +} + +// RegSet represents a set of registers. +type RegSet uint64 + +func (rs RegSet) format(info *RegisterInfo) string { //nolint:unused + var ret []string + for i := 0; i < 64; i++ { + if rs&(1<= 64 { + return rs + } + return rs | 1<v%d)", info.RealRegName(RealReg(i)), vr.v.ID())) + } + } + return strings.Join(ret, ", ") +} + +func (rs *regInUseSet[I, B, F]) has(r RealReg) bool { + return r < 64 && rs[r] != nil +} + +func (rs *regInUseSet[I, B, F]) get(r RealReg) *vrState[I, B, F] { + return rs[r] +} + +func (rs *regInUseSet[I, B, F]) remove(r RealReg) { + rs[r] = nil +} + +func (rs *regInUseSet[I, B, F]) add(r RealReg, vr *vrState[I, B, F]) { + if r >= 64 { + return + } + rs[r] = vr +} + +func (rs *regInUseSet[I, B, F]) range_(f func(allocatedRealReg RealReg, vr *vrState[I, B, F])) { + for i, vr := range rs { + if vr != nil { + f(RealReg(i), vr) + } + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/vdef.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/vdef.go new file mode 100644 index 00000000..47a275a3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/backend/vdef.go @@ -0,0 +1,19 @@ +package backend + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +// SSAValueDefinition represents a definition of an SSA value. +type SSAValueDefinition struct { + V ssa.Value + // Instr is not nil if this is a definition from an instruction. + Instr *ssa.Instruction + // RefCount is the number of references to the result. + RefCount uint32 +} + +// IsFromInstr returns true if this definition is from an instruction. +func (d *SSAValueDefinition) IsFromInstr() bool { + return d.Instr != nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/call_engine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/call_engine.go new file mode 100644 index 00000000..639429a6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/call_engine.go @@ -0,0 +1,708 @@ +package wazevo + +import ( + "context" + "fmt" + "reflect" + "runtime" + "sync/atomic" + "unsafe" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/expctxkeys" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasmdebug" + "github.com/tetratelabs/wazero/internal/wasmruntime" +) + +type ( + // callEngine implements api.Function. + callEngine struct { + internalapi.WazeroOnly + stack []byte + // stackTop is the pointer to the *aligned* top of the stack. This must be updated + // whenever the stack is changed. This is passed to the assembly function + // at the very beginning of api.Function Call/CallWithStack. + stackTop uintptr + // executable is the pointer to the executable code for this function. + executable *byte + preambleExecutable *byte + // parent is the *moduleEngine from which this callEngine is created. + parent *moduleEngine + // indexInModule is the index of the function in the module. + indexInModule wasm.Index + // sizeOfParamResultSlice is the size of the parameter/result slice. + sizeOfParamResultSlice int + requiredParams int + // execCtx holds various information to be read/written by assembly functions. + execCtx executionContext + // execCtxPtr holds the pointer to the executionContext which doesn't change after callEngine is created. + execCtxPtr uintptr + numberOfResults int + stackIteratorImpl stackIterator + } + + // executionContext is the struct to be read/written by assembly functions. + executionContext struct { + // exitCode holds the wazevoapi.ExitCode describing the state of the function execution. + exitCode wazevoapi.ExitCode + // callerModuleContextPtr holds the moduleContextOpaque for Go function calls. + callerModuleContextPtr *byte + // originalFramePointer holds the original frame pointer of the caller of the assembly function. + originalFramePointer uintptr + // originalStackPointer holds the original stack pointer of the caller of the assembly function. + originalStackPointer uintptr + // goReturnAddress holds the return address to go back to the caller of the assembly function. + goReturnAddress uintptr + // stackBottomPtr holds the pointer to the bottom of the stack. + stackBottomPtr *byte + // goCallReturnAddress holds the return address to go back to the caller of the Go function. + goCallReturnAddress *byte + // stackPointerBeforeGoCall holds the stack pointer before calling a Go function. + stackPointerBeforeGoCall *uint64 + // stackGrowRequiredSize holds the required size of stack grow. + stackGrowRequiredSize uintptr + // memoryGrowTrampolineAddress holds the address of memory grow trampoline function. + memoryGrowTrampolineAddress *byte + // stackGrowCallTrampolineAddress holds the address of stack grow trampoline function. + stackGrowCallTrampolineAddress *byte + // checkModuleExitCodeTrampolineAddress holds the address of check-module-exit-code function. + checkModuleExitCodeTrampolineAddress *byte + // savedRegisters is the opaque spaces for save/restore registers. + // We want to align 16 bytes for each register, so we use [64][2]uint64. + savedRegisters [64][2]uint64 + // goFunctionCallCalleeModuleContextOpaque is the pointer to the target Go function's moduleContextOpaque. + goFunctionCallCalleeModuleContextOpaque uintptr + // tableGrowTrampolineAddress holds the address of table grow trampoline function. + tableGrowTrampolineAddress *byte + // refFuncTrampolineAddress holds the address of ref-func trampoline function. + refFuncTrampolineAddress *byte + // memmoveAddress holds the address of memmove function implemented by Go runtime. See memmove.go. + memmoveAddress uintptr + // framePointerBeforeGoCall holds the frame pointer before calling a Go function. Note: only used in amd64. + framePointerBeforeGoCall uintptr + // memoryWait32TrampolineAddress holds the address of memory_wait32 trampoline function. + memoryWait32TrampolineAddress *byte + // memoryWait32TrampolineAddress holds the address of memory_wait64 trampoline function. + memoryWait64TrampolineAddress *byte + // memoryNotifyTrampolineAddress holds the address of the memory_notify trampoline function. + memoryNotifyTrampolineAddress *byte + } +) + +func (c *callEngine) requiredInitialStackSize() int { + const initialStackSizeDefault = 10240 + stackSize := initialStackSizeDefault + paramResultInBytes := c.sizeOfParamResultSlice * 8 * 2 // * 8 because uint64 is 8 bytes, and *2 because we need both separated param/result slots. + required := paramResultInBytes + 32 + 16 // 32 is enough to accommodate the call frame info, and 16 exists just in case when []byte is not aligned to 16 bytes. + if required > stackSize { + stackSize = required + } + return stackSize +} + +func (c *callEngine) init() { + stackSize := c.requiredInitialStackSize() + if wazevoapi.StackGuardCheckEnabled { + stackSize += wazevoapi.StackGuardCheckGuardPageSize + } + c.stack = make([]byte, stackSize) + c.stackTop = alignedStackTop(c.stack) + if wazevoapi.StackGuardCheckEnabled { + c.execCtx.stackBottomPtr = &c.stack[wazevoapi.StackGuardCheckGuardPageSize] + } else { + c.execCtx.stackBottomPtr = &c.stack[0] + } + c.execCtxPtr = uintptr(unsafe.Pointer(&c.execCtx)) +} + +// alignedStackTop returns 16-bytes aligned stack top of given stack. +// 16 bytes should be good for all platform (arm64/amd64). +func alignedStackTop(s []byte) uintptr { + stackAddr := uintptr(unsafe.Pointer(&s[len(s)-1])) + return stackAddr - (stackAddr & (16 - 1)) +} + +// Definition implements api.Function. +func (c *callEngine) Definition() api.FunctionDefinition { + return c.parent.module.Source.FunctionDefinition(c.indexInModule) +} + +// Call implements api.Function. +func (c *callEngine) Call(ctx context.Context, params ...uint64) ([]uint64, error) { + if c.requiredParams != len(params) { + return nil, fmt.Errorf("expected %d params, but passed %d", c.requiredParams, len(params)) + } + paramResultSlice := make([]uint64, c.sizeOfParamResultSlice) + copy(paramResultSlice, params) + if err := c.callWithStack(ctx, paramResultSlice); err != nil { + return nil, err + } + return paramResultSlice[:c.numberOfResults], nil +} + +func (c *callEngine) addFrame(builder wasmdebug.ErrorBuilder, addr uintptr) (def api.FunctionDefinition, listener experimental.FunctionListener) { + eng := c.parent.parent.parent + cm := eng.compiledModuleOfAddr(addr) + if cm == nil { + // This case, the module might have been closed and deleted from the engine. + // We fall back to searching the imported modules that can be referenced from this callEngine. + + // First, we check itself. + if checkAddrInBytes(addr, c.parent.parent.executable) { + cm = c.parent.parent + } else { + // Otherwise, search all imported modules. TODO: maybe recursive, but not sure it's useful in practice. + p := c.parent + for i := range p.importedFunctions { + candidate := p.importedFunctions[i].me.parent + if checkAddrInBytes(addr, candidate.executable) { + cm = candidate + break + } + } + } + } + + if cm != nil { + index := cm.functionIndexOf(addr) + def = cm.module.FunctionDefinition(cm.module.ImportFunctionCount + index) + var sources []string + if dw := cm.module.DWARFLines; dw != nil { + sourceOffset := cm.getSourceOffset(addr) + sources = dw.Line(sourceOffset) + } + builder.AddFrame(def.DebugName(), def.ParamTypes(), def.ResultTypes(), sources) + if len(cm.listeners) > 0 { + listener = cm.listeners[index] + } + } + return +} + +// CallWithStack implements api.Function. +func (c *callEngine) CallWithStack(ctx context.Context, paramResultStack []uint64) (err error) { + if c.sizeOfParamResultSlice > len(paramResultStack) { + return fmt.Errorf("need %d params, but stack size is %d", c.sizeOfParamResultSlice, len(paramResultStack)) + } + return c.callWithStack(ctx, paramResultStack) +} + +// CallWithStack implements api.Function. +func (c *callEngine) callWithStack(ctx context.Context, paramResultStack []uint64) (err error) { + snapshotEnabled := ctx.Value(expctxkeys.EnableSnapshotterKey{}) != nil + if snapshotEnabled { + ctx = context.WithValue(ctx, expctxkeys.SnapshotterKey{}, c) + } + + if wazevoapi.StackGuardCheckEnabled { + defer func() { + wazevoapi.CheckStackGuardPage(c.stack) + }() + } + + p := c.parent + ensureTermination := p.parent.ensureTermination + m := p.module + if ensureTermination { + select { + case <-ctx.Done(): + // If the provided context is already done, close the module and return the error. + m.CloseWithCtxErr(ctx) + return m.FailIfClosed() + default: + } + } + + var paramResultPtr *uint64 + if len(paramResultStack) > 0 { + paramResultPtr = ¶mResultStack[0] + } + defer func() { + r := recover() + if s, ok := r.(*snapshot); ok { + // A snapshot that wasn't handled was created by a different call engine possibly from a nested wasm invocation, + // let it propagate up to be handled by the caller. + panic(s) + } + if r != nil { + type listenerForAbort struct { + def api.FunctionDefinition + lsn experimental.FunctionListener + } + + var listeners []listenerForAbort + builder := wasmdebug.NewErrorBuilder() + def, lsn := c.addFrame(builder, uintptr(unsafe.Pointer(c.execCtx.goCallReturnAddress))) + if lsn != nil { + listeners = append(listeners, listenerForAbort{def, lsn}) + } + returnAddrs := unwindStack( + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), + c.execCtx.framePointerBeforeGoCall, + c.stackTop, + nil, + ) + for _, retAddr := range returnAddrs[:len(returnAddrs)-1] { // the last return addr is the trampoline, so we skip it. + def, lsn = c.addFrame(builder, retAddr) + if lsn != nil { + listeners = append(listeners, listenerForAbort{def, lsn}) + } + } + err = builder.FromRecovered(r) + + for _, lsn := range listeners { + lsn.lsn.Abort(ctx, m, lsn.def, err) + } + } else { + if err != wasmruntime.ErrRuntimeStackOverflow { // Stackoverflow case shouldn't be panic (to avoid extreme stack unwinding). + err = c.parent.module.FailIfClosed() + } + } + + if err != nil { + // Ensures that we can reuse this callEngine even after an error. + c.execCtx.exitCode = wazevoapi.ExitCodeOK + } + }() + + if ensureTermination { + done := m.CloseModuleOnCanceledOrTimeout(ctx) + defer done() + } + + if c.stackTop&(16-1) != 0 { + panic("BUG: stack must be aligned to 16 bytes") + } + entrypoint(c.preambleExecutable, c.executable, c.execCtxPtr, c.parent.opaquePtr, paramResultPtr, c.stackTop) + for { + switch ec := c.execCtx.exitCode; ec & wazevoapi.ExitCodeMask { + case wazevoapi.ExitCodeOK: + return nil + case wazevoapi.ExitCodeGrowStack: + oldsp := uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)) + oldTop := c.stackTop + oldStack := c.stack + var newsp, newfp uintptr + if wazevoapi.StackGuardCheckEnabled { + newsp, newfp, err = c.growStackWithGuarded() + } else { + newsp, newfp, err = c.growStack() + } + if err != nil { + return err + } + adjustClonedStack(oldsp, oldTop, newsp, newfp, c.stackTop) + // Old stack must be alive until the new stack is adjusted. + runtime.KeepAlive(oldStack) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, newsp, newfp) + case wazevoapi.ExitCodeGrowMemory: + mod := c.callerModuleInstance() + mem := mod.MemoryInstance + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + argRes := &s[0] + if res, ok := mem.Grow(uint32(*argRes)); !ok { + *argRes = uint64(0xffffffff) // = -1 in signed 32-bit integer. + } else { + *argRes = uint64(res) + } + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeTableGrow: + mod := c.callerModuleInstance() + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + tableIndex, num, ref := uint32(s[0]), uint32(s[1]), uintptr(s[2]) + table := mod.Tables[tableIndex] + s[0] = uint64(uint32(int32(table.Grow(num, ref)))) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallGoFunction: + index := wazevoapi.GoFunctionIndexFromExitCode(ec) + f := hostModuleGoFuncFromOpaque[api.GoFunction](index, c.execCtx.goFunctionCallCalleeModuleContextOpaque) + func() { + if snapshotEnabled { + defer snapshotRecoverFn(c) + } + f.Call(ctx, goCallStackView(c.execCtx.stackPointerBeforeGoCall)) + }() + // Back to the native code. + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallGoFunctionWithListener: + index := wazevoapi.GoFunctionIndexFromExitCode(ec) + f := hostModuleGoFuncFromOpaque[api.GoFunction](index, c.execCtx.goFunctionCallCalleeModuleContextOpaque) + listeners := hostModuleListenersSliceFromOpaque(c.execCtx.goFunctionCallCalleeModuleContextOpaque) + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + // Call Listener.Before. + callerModule := c.callerModuleInstance() + listener := listeners[index] + hostModule := hostModuleFromOpaque(c.execCtx.goFunctionCallCalleeModuleContextOpaque) + def := hostModule.FunctionDefinition(wasm.Index(index)) + listener.Before(ctx, callerModule, def, s, c.stackIterator(true)) + // Call into the Go function. + func() { + if snapshotEnabled { + defer snapshotRecoverFn(c) + } + f.Call(ctx, s) + }() + // Call Listener.After. + listener.After(ctx, callerModule, def, s) + // Back to the native code. + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallGoModuleFunction: + index := wazevoapi.GoFunctionIndexFromExitCode(ec) + f := hostModuleGoFuncFromOpaque[api.GoModuleFunction](index, c.execCtx.goFunctionCallCalleeModuleContextOpaque) + mod := c.callerModuleInstance() + func() { + if snapshotEnabled { + defer snapshotRecoverFn(c) + } + f.Call(ctx, mod, goCallStackView(c.execCtx.stackPointerBeforeGoCall)) + }() + // Back to the native code. + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallGoModuleFunctionWithListener: + index := wazevoapi.GoFunctionIndexFromExitCode(ec) + f := hostModuleGoFuncFromOpaque[api.GoModuleFunction](index, c.execCtx.goFunctionCallCalleeModuleContextOpaque) + listeners := hostModuleListenersSliceFromOpaque(c.execCtx.goFunctionCallCalleeModuleContextOpaque) + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + // Call Listener.Before. + callerModule := c.callerModuleInstance() + listener := listeners[index] + hostModule := hostModuleFromOpaque(c.execCtx.goFunctionCallCalleeModuleContextOpaque) + def := hostModule.FunctionDefinition(wasm.Index(index)) + listener.Before(ctx, callerModule, def, s, c.stackIterator(true)) + // Call into the Go function. + func() { + if snapshotEnabled { + defer snapshotRecoverFn(c) + } + f.Call(ctx, callerModule, s) + }() + // Call Listener.After. + listener.After(ctx, callerModule, def, s) + // Back to the native code. + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallListenerBefore: + stack := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + index := wasm.Index(stack[0]) + mod := c.callerModuleInstance() + listener := mod.Engine.(*moduleEngine).listeners[index] + def := mod.Source.FunctionDefinition(index + mod.Source.ImportFunctionCount) + listener.Before(ctx, mod, def, stack[1:], c.stackIterator(false)) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCallListenerAfter: + stack := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + index := wasm.Index(stack[0]) + mod := c.callerModuleInstance() + listener := mod.Engine.(*moduleEngine).listeners[index] + def := mod.Source.FunctionDefinition(index + mod.Source.ImportFunctionCount) + listener.After(ctx, mod, def, stack[1:]) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeCheckModuleExitCode: + // Note: this operation must be done in Go, not native code. The reason is that + // native code cannot be preempted and that means it can block forever if there are not + // enough OS threads (which we don't have control over). + if err := m.FailIfClosed(); err != nil { + panic(err) + } + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeRefFunc: + mod := c.callerModuleInstance() + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + funcIndex := wasm.Index(s[0]) + ref := mod.Engine.FunctionInstanceReference(funcIndex) + s[0] = uint64(ref) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeMemoryWait32: + mod := c.callerModuleInstance() + mem := mod.MemoryInstance + if !mem.Shared { + panic(wasmruntime.ErrRuntimeExpectedSharedMemory) + } + + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + timeout, exp, addr := int64(s[0]), uint32(s[1]), uintptr(s[2]) + base := uintptr(unsafe.Pointer(&mem.Buffer[0])) + + offset := uint32(addr - base) + res := mem.Wait32(offset, exp, timeout, func(mem *wasm.MemoryInstance, offset uint32) uint32 { + addr := unsafe.Add(unsafe.Pointer(&mem.Buffer[0]), offset) + return atomic.LoadUint32((*uint32)(addr)) + }) + s[0] = res + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeMemoryWait64: + mod := c.callerModuleInstance() + mem := mod.MemoryInstance + if !mem.Shared { + panic(wasmruntime.ErrRuntimeExpectedSharedMemory) + } + + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + timeout, exp, addr := int64(s[0]), uint64(s[1]), uintptr(s[2]) + base := uintptr(unsafe.Pointer(&mem.Buffer[0])) + + offset := uint32(addr - base) + res := mem.Wait64(offset, exp, timeout, func(mem *wasm.MemoryInstance, offset uint32) uint64 { + addr := unsafe.Add(unsafe.Pointer(&mem.Buffer[0]), offset) + return atomic.LoadUint64((*uint64)(addr)) + }) + s[0] = uint64(res) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeMemoryNotify: + mod := c.callerModuleInstance() + mem := mod.MemoryInstance + + s := goCallStackView(c.execCtx.stackPointerBeforeGoCall) + count, addr := uint32(s[0]), s[1] + offset := uint32(uintptr(addr) - uintptr(unsafe.Pointer(&mem.Buffer[0]))) + res := mem.Notify(offset, count) + s[0] = uint64(res) + c.execCtx.exitCode = wazevoapi.ExitCodeOK + afterGoFunctionCallEntrypoint(c.execCtx.goCallReturnAddress, c.execCtxPtr, + uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall) + case wazevoapi.ExitCodeUnreachable: + panic(wasmruntime.ErrRuntimeUnreachable) + case wazevoapi.ExitCodeMemoryOutOfBounds: + panic(wasmruntime.ErrRuntimeOutOfBoundsMemoryAccess) + case wazevoapi.ExitCodeTableOutOfBounds: + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + case wazevoapi.ExitCodeIndirectCallNullPointer: + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + case wazevoapi.ExitCodeIndirectCallTypeMismatch: + panic(wasmruntime.ErrRuntimeIndirectCallTypeMismatch) + case wazevoapi.ExitCodeIntegerOverflow: + panic(wasmruntime.ErrRuntimeIntegerOverflow) + case wazevoapi.ExitCodeIntegerDivisionByZero: + panic(wasmruntime.ErrRuntimeIntegerDivideByZero) + case wazevoapi.ExitCodeInvalidConversionToInteger: + panic(wasmruntime.ErrRuntimeInvalidConversionToInteger) + case wazevoapi.ExitCodeUnalignedAtomic: + panic(wasmruntime.ErrRuntimeUnalignedAtomic) + default: + panic("BUG") + } + } +} + +func (c *callEngine) callerModuleInstance() *wasm.ModuleInstance { + return moduleInstanceFromOpaquePtr(c.execCtx.callerModuleContextPtr) +} + +const callStackCeiling = uintptr(50000000) // in uint64 (8 bytes) == 400000000 bytes in total == 400mb. + +func (c *callEngine) growStackWithGuarded() (newSP uintptr, newFP uintptr, err error) { + if wazevoapi.StackGuardCheckEnabled { + wazevoapi.CheckStackGuardPage(c.stack) + } + newSP, newFP, err = c.growStack() + if err != nil { + return + } + if wazevoapi.StackGuardCheckEnabled { + c.execCtx.stackBottomPtr = &c.stack[wazevoapi.StackGuardCheckGuardPageSize] + } + return +} + +// growStack grows the stack, and returns the new stack pointer. +func (c *callEngine) growStack() (newSP, newFP uintptr, err error) { + currentLen := uintptr(len(c.stack)) + if callStackCeiling < currentLen { + err = wasmruntime.ErrRuntimeStackOverflow + return + } + + newLen := 2*currentLen + c.execCtx.stackGrowRequiredSize + 16 // Stack might be aligned to 16 bytes, so add 16 bytes just in case. + newSP, newFP, c.stackTop, c.stack = c.cloneStack(newLen) + c.execCtx.stackBottomPtr = &c.stack[0] + return +} + +func (c *callEngine) cloneStack(l uintptr) (newSP, newFP, newTop uintptr, newStack []byte) { + newStack = make([]byte, l) + + relSp := c.stackTop - uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)) + relFp := c.stackTop - c.execCtx.framePointerBeforeGoCall + + // Copy the existing contents in the previous Go-allocated stack into the new one. + var prevStackAligned, newStackAligned []byte + { + //nolint:staticcheck + sh := (*reflect.SliceHeader)(unsafe.Pointer(&prevStackAligned)) + sh.Data = c.stackTop - relSp + sh.Len = int(relSp) + sh.Cap = int(relSp) + } + newTop = alignedStackTop(newStack) + { + newSP = newTop - relSp + newFP = newTop - relFp + //nolint:staticcheck + sh := (*reflect.SliceHeader)(unsafe.Pointer(&newStackAligned)) + sh.Data = newSP + sh.Len = int(relSp) + sh.Cap = int(relSp) + } + copy(newStackAligned, prevStackAligned) + return +} + +func (c *callEngine) stackIterator(onHostCall bool) experimental.StackIterator { + c.stackIteratorImpl.reset(c, onHostCall) + return &c.stackIteratorImpl +} + +// stackIterator implements experimental.StackIterator. +type stackIterator struct { + retAddrs []uintptr + retAddrCursor int + eng *engine + pc uint64 + + currentDef *wasm.FunctionDefinition +} + +func (si *stackIterator) reset(c *callEngine, onHostCall bool) { + if onHostCall { + si.retAddrs = append(si.retAddrs[:0], uintptr(unsafe.Pointer(c.execCtx.goCallReturnAddress))) + } else { + si.retAddrs = si.retAddrs[:0] + } + si.retAddrs = unwindStack(uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)), c.execCtx.framePointerBeforeGoCall, c.stackTop, si.retAddrs) + si.retAddrs = si.retAddrs[:len(si.retAddrs)-1] // the last return addr is the trampoline, so we skip it. + si.retAddrCursor = 0 + si.eng = c.parent.parent.parent +} + +// Next implements the same method as documented on experimental.StackIterator. +func (si *stackIterator) Next() bool { + if si.retAddrCursor >= len(si.retAddrs) { + return false + } + + addr := si.retAddrs[si.retAddrCursor] + cm := si.eng.compiledModuleOfAddr(addr) + if cm != nil { + index := cm.functionIndexOf(addr) + def := cm.module.FunctionDefinition(cm.module.ImportFunctionCount + index) + si.currentDef = def + si.retAddrCursor++ + si.pc = uint64(addr) + return true + } + return false +} + +// ProgramCounter implements the same method as documented on experimental.StackIterator. +func (si *stackIterator) ProgramCounter() experimental.ProgramCounter { + return experimental.ProgramCounter(si.pc) +} + +// Function implements the same method as documented on experimental.StackIterator. +func (si *stackIterator) Function() experimental.InternalFunction { + return si +} + +// Definition implements the same method as documented on experimental.InternalFunction. +func (si *stackIterator) Definition() api.FunctionDefinition { + return si.currentDef +} + +// SourceOffsetForPC implements the same method as documented on experimental.InternalFunction. +func (si *stackIterator) SourceOffsetForPC(pc experimental.ProgramCounter) uint64 { + upc := uintptr(pc) + cm := si.eng.compiledModuleOfAddr(upc) + return cm.getSourceOffset(upc) +} + +// snapshot implements experimental.Snapshot +type snapshot struct { + sp, fp, top uintptr + returnAddress *byte + stack []byte + savedRegisters [64][2]uint64 + ret []uint64 + c *callEngine +} + +// Snapshot implements the same method as documented on experimental.Snapshotter. +func (c *callEngine) Snapshot() experimental.Snapshot { + returnAddress := c.execCtx.goCallReturnAddress + oldTop, oldSp := c.stackTop, uintptr(unsafe.Pointer(c.execCtx.stackPointerBeforeGoCall)) + newSP, newFP, newTop, newStack := c.cloneStack(uintptr(len(c.stack)) + 16) + adjustClonedStack(oldSp, oldTop, newSP, newFP, newTop) + return &snapshot{ + sp: newSP, + fp: newFP, + top: newTop, + savedRegisters: c.execCtx.savedRegisters, + returnAddress: returnAddress, + stack: newStack, + c: c, + } +} + +// Restore implements the same method as documented on experimental.Snapshot. +func (s *snapshot) Restore(ret []uint64) { + s.ret = ret + panic(s) +} + +func (s *snapshot) doRestore() { + spp := *(**uint64)(unsafe.Pointer(&s.sp)) + view := goCallStackView(spp) + copy(view, s.ret) + + c := s.c + c.stack = s.stack + c.stackTop = s.top + ec := &c.execCtx + ec.stackBottomPtr = &c.stack[0] + ec.stackPointerBeforeGoCall = spp + ec.framePointerBeforeGoCall = s.fp + ec.goCallReturnAddress = s.returnAddress + ec.savedRegisters = s.savedRegisters +} + +// Error implements the same method on error. +func (s *snapshot) Error() string { + return "unhandled snapshot restore, this generally indicates restore was called from a different " + + "exported function invocation than snapshot" +} + +func snapshotRecoverFn(c *callEngine) { + if r := recover(); r != nil { + if s, ok := r.(*snapshot); ok && s.c == c { + s.doRestore() + } else { + panic(r) + } + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine.go new file mode 100644 index 00000000..a6df3e7e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine.go @@ -0,0 +1,843 @@ +package wazevo + +import ( + "context" + "encoding/hex" + "errors" + "fmt" + "runtime" + "sort" + "sync" + "unsafe" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/frontend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/filecache" + "github.com/tetratelabs/wazero/internal/platform" + "github.com/tetratelabs/wazero/internal/version" + "github.com/tetratelabs/wazero/internal/wasm" +) + +type ( + // engine implements wasm.Engine. + engine struct { + wazeroVersion string + fileCache filecache.Cache + compiledModules map[wasm.ModuleID]*compiledModule + // sortedCompiledModules is a list of compiled modules sorted by the initial address of the executable. + sortedCompiledModules []*compiledModule + mux sync.RWMutex + // sharedFunctions is compiled functions shared by all modules. + sharedFunctions *sharedFunctions + // setFinalizer defaults to runtime.SetFinalizer, but overridable for tests. + setFinalizer func(obj interface{}, finalizer interface{}) + + // The followings are reused for compiling shared functions. + machine backend.Machine + be backend.Compiler + } + + sharedFunctions struct { + // memoryGrowExecutable is a compiled trampoline executable for memory.grow builtin function. + memoryGrowExecutable []byte + // checkModuleExitCode is a compiled trampoline executable for checking module instance exit code. This + // is used when ensureTermination is true. + checkModuleExitCode []byte + // stackGrowExecutable is a compiled executable for growing stack builtin function. + stackGrowExecutable []byte + // tableGrowExecutable is a compiled trampoline executable for table.grow builtin function. + tableGrowExecutable []byte + // refFuncExecutable is a compiled trampoline executable for ref.func builtin function. + refFuncExecutable []byte + // memoryWait32Executable is a compiled trampoline executable for memory.wait32 builtin function + memoryWait32Executable []byte + // memoryWait64Executable is a compiled trampoline executable for memory.wait64 builtin function + memoryWait64Executable []byte + // memoryNotifyExecutable is a compiled trampoline executable for memory.notify builtin function + memoryNotifyExecutable []byte + listenerBeforeTrampolines map[*wasm.FunctionType][]byte + listenerAfterTrampolines map[*wasm.FunctionType][]byte + } + + // compiledModule is a compiled variant of a wasm.Module and ready to be used for instantiation. + compiledModule struct { + *executables + // functionOffsets maps a local function index to the offset in the executable. + functionOffsets []int + parent *engine + module *wasm.Module + ensureTermination bool + listeners []experimental.FunctionListener + listenerBeforeTrampolines []*byte + listenerAfterTrampolines []*byte + + // The followings are only available for non host modules. + + offsets wazevoapi.ModuleContextOffsetData + sharedFunctions *sharedFunctions + sourceMap sourceMap + } + + executables struct { + executable []byte + entryPreambles [][]byte + } +) + +// sourceMap is a mapping from the offset of the executable to the offset of the original wasm binary. +type sourceMap struct { + // executableOffsets is a sorted list of offsets of the executable. This is index-correlated with wasmBinaryOffsets, + // in other words executableOffsets[i] is the offset of the executable which corresponds to the offset of a Wasm + // binary pointed by wasmBinaryOffsets[i]. + executableOffsets []uintptr + // wasmBinaryOffsets is the counterpart of executableOffsets. + wasmBinaryOffsets []uint64 +} + +var _ wasm.Engine = (*engine)(nil) + +// NewEngine returns the implementation of wasm.Engine. +func NewEngine(ctx context.Context, _ api.CoreFeatures, fc filecache.Cache) wasm.Engine { + machine := newMachine() + be := backend.NewCompiler(ctx, machine, ssa.NewBuilder()) + e := &engine{ + compiledModules: make(map[wasm.ModuleID]*compiledModule), + setFinalizer: runtime.SetFinalizer, + machine: machine, + be: be, + fileCache: fc, + wazeroVersion: version.GetWazeroVersion(), + } + e.compileSharedFunctions() + return e +} + +// CompileModule implements wasm.Engine. +func (e *engine) CompileModule(ctx context.Context, module *wasm.Module, listeners []experimental.FunctionListener, ensureTermination bool) (err error) { + if wazevoapi.PerfMapEnabled { + wazevoapi.PerfMap.Lock() + defer wazevoapi.PerfMap.Unlock() + } + + if _, ok, err := e.getCompiledModule(module, listeners, ensureTermination); ok { // cache hit! + return nil + } else if err != nil { + return err + } + + if wazevoapi.DeterministicCompilationVerifierEnabled { + ctx = wazevoapi.NewDeterministicCompilationVerifierContext(ctx, len(module.CodeSection)) + } + cm, err := e.compileModule(ctx, module, listeners, ensureTermination) + if err != nil { + return err + } + if err = e.addCompiledModule(module, cm); err != nil { + return err + } + + if wazevoapi.DeterministicCompilationVerifierEnabled { + for i := 0; i < wazevoapi.DeterministicCompilationVerifyingIter; i++ { + _, err := e.compileModule(ctx, module, listeners, ensureTermination) + if err != nil { + return err + } + } + } + + if len(listeners) > 0 { + cm.listeners = listeners + cm.listenerBeforeTrampolines = make([]*byte, len(module.TypeSection)) + cm.listenerAfterTrampolines = make([]*byte, len(module.TypeSection)) + for i := range module.TypeSection { + typ := &module.TypeSection[i] + before, after := e.getListenerTrampolineForType(typ) + cm.listenerBeforeTrampolines[i] = before + cm.listenerAfterTrampolines[i] = after + } + } + return nil +} + +func (exec *executables) compileEntryPreambles(m *wasm.Module, machine backend.Machine, be backend.Compiler) { + exec.entryPreambles = make([][]byte, len(m.TypeSection)) + for i := range m.TypeSection { + typ := &m.TypeSection[i] + sig := frontend.SignatureForWasmFunctionType(typ) + be.Init() + buf := machine.CompileEntryPreamble(&sig) + executable := mmapExecutable(buf) + exec.entryPreambles[i] = executable + + if wazevoapi.PerfMapEnabled { + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&executable[0])), + uint64(len(executable)), fmt.Sprintf("entry_preamble::type=%s", typ.String())) + } + } +} + +func (e *engine) compileModule(ctx context.Context, module *wasm.Module, listeners []experimental.FunctionListener, ensureTermination bool) (*compiledModule, error) { + withListener := len(listeners) > 0 + cm := &compiledModule{ + offsets: wazevoapi.NewModuleContextOffsetData(module, withListener), parent: e, module: module, + ensureTermination: ensureTermination, + executables: &executables{}, + } + + if module.IsHostModule { + return e.compileHostModule(ctx, module, listeners) + } + + importedFns, localFns := int(module.ImportFunctionCount), len(module.FunctionSection) + if localFns == 0 { + return cm, nil + } + + rels := make([]backend.RelocationInfo, 0) + refToBinaryOffset := make([]int, importedFns+localFns) + + if wazevoapi.DeterministicCompilationVerifierEnabled { + // The compilation must be deterministic regardless of the order of functions being compiled. + wazevoapi.DeterministicCompilationVerifierRandomizeIndexes(ctx) + } + + needSourceInfo := module.DWARFLines != nil + + // Creates new compiler instances which are reused for each function. + ssaBuilder := ssa.NewBuilder() + fe := frontend.NewFrontendCompiler(module, ssaBuilder, &cm.offsets, ensureTermination, withListener, needSourceInfo) + machine := newMachine() + be := backend.NewCompiler(ctx, machine, ssaBuilder) + + cm.executables.compileEntryPreambles(module, machine, be) + + totalSize := 0 // Total binary size of the executable. + cm.functionOffsets = make([]int, localFns) + bodies := make([][]byte, localFns) + + // Trampoline relocation related variables. + trampolineInterval, callTrampolineIslandSize, err := machine.CallTrampolineIslandInfo(localFns) + if err != nil { + return nil, err + } + needCallTrampoline := callTrampolineIslandSize > 0 + var callTrampolineIslandOffsets []int // Holds the offsets of trampoline islands. + + for i := range module.CodeSection { + if wazevoapi.DeterministicCompilationVerifierEnabled { + i = wazevoapi.DeterministicCompilationVerifierGetRandomizedLocalFunctionIndex(ctx, i) + } + + fidx := wasm.Index(i + importedFns) + + if wazevoapi.NeedFunctionNameInContext { + def := module.FunctionDefinition(fidx) + name := def.DebugName() + if len(def.ExportNames()) > 0 { + name = def.ExportNames()[0] + } + ctx = wazevoapi.SetCurrentFunctionName(ctx, i, fmt.Sprintf("[%d/%d]%s", i, len(module.CodeSection)-1, name)) + } + + needListener := len(listeners) > 0 && listeners[i] != nil + body, relsPerFunc, err := e.compileLocalWasmFunction(ctx, module, wasm.Index(i), fe, ssaBuilder, be, needListener) + if err != nil { + return nil, fmt.Errorf("compile function %d/%d: %v", i, len(module.CodeSection)-1, err) + } + + // Align 16-bytes boundary. + totalSize = (totalSize + 15) &^ 15 + cm.functionOffsets[i] = totalSize + + if needSourceInfo { + // At the beginning of the function, we add the offset of the function body so that + // we can resolve the source location of the call site of before listener call. + cm.sourceMap.executableOffsets = append(cm.sourceMap.executableOffsets, uintptr(totalSize)) + cm.sourceMap.wasmBinaryOffsets = append(cm.sourceMap.wasmBinaryOffsets, module.CodeSection[i].BodyOffsetInCodeSection) + + for _, info := range be.SourceOffsetInfo() { + cm.sourceMap.executableOffsets = append(cm.sourceMap.executableOffsets, uintptr(totalSize)+uintptr(info.ExecutableOffset)) + cm.sourceMap.wasmBinaryOffsets = append(cm.sourceMap.wasmBinaryOffsets, uint64(info.SourceOffset)) + } + } + + fref := frontend.FunctionIndexToFuncRef(fidx) + refToBinaryOffset[fref] = totalSize + + // At this point, relocation offsets are relative to the start of the function body, + // so we adjust it to the start of the executable. + for _, r := range relsPerFunc { + r.Offset += int64(totalSize) + rels = append(rels, r) + } + + bodies[i] = body + totalSize += len(body) + if wazevoapi.PrintMachineCodeHexPerFunction { + fmt.Printf("[[[machine code for %s]]]\n%s\n\n", wazevoapi.GetCurrentFunctionName(ctx), hex.EncodeToString(body)) + } + + if needCallTrampoline { + // If the total size exceeds the trampoline interval, we need to add a trampoline island. + if totalSize/trampolineInterval > len(callTrampolineIslandOffsets) { + callTrampolineIslandOffsets = append(callTrampolineIslandOffsets, totalSize) + totalSize += callTrampolineIslandSize + } + } + } + + // Allocate executable memory and then copy the generated machine code. + executable, err := platform.MmapCodeSegment(totalSize) + if err != nil { + panic(err) + } + cm.executable = executable + + for i, b := range bodies { + offset := cm.functionOffsets[i] + copy(executable[offset:], b) + } + + if wazevoapi.PerfMapEnabled { + wazevoapi.PerfMap.Flush(uintptr(unsafe.Pointer(&executable[0])), cm.functionOffsets) + } + + if needSourceInfo { + for i := range cm.sourceMap.executableOffsets { + cm.sourceMap.executableOffsets[i] += uintptr(unsafe.Pointer(&cm.executable[0])) + } + } + + // Resolve relocations for local function calls. + if len(rels) > 0 { + machine.ResolveRelocations(refToBinaryOffset, importedFns, executable, rels, callTrampolineIslandOffsets) + } + + if runtime.GOARCH == "arm64" { + // On arm64, we cannot give all of rwx at the same time, so we change it to exec. + if err = platform.MprotectRX(executable); err != nil { + return nil, err + } + } + cm.sharedFunctions = e.sharedFunctions + e.setFinalizer(cm.executables, executablesFinalizer) + return cm, nil +} + +func (e *engine) compileLocalWasmFunction( + ctx context.Context, + module *wasm.Module, + localFunctionIndex wasm.Index, + fe *frontend.Compiler, + ssaBuilder ssa.Builder, + be backend.Compiler, + needListener bool, +) (body []byte, rels []backend.RelocationInfo, err error) { + typIndex := module.FunctionSection[localFunctionIndex] + typ := &module.TypeSection[typIndex] + codeSeg := &module.CodeSection[localFunctionIndex] + + // Initializes both frontend and backend compilers. + fe.Init(localFunctionIndex, typIndex, typ, codeSeg.LocalTypes, codeSeg.Body, needListener, codeSeg.BodyOffsetInCodeSection) + be.Init() + + // Lower Wasm to SSA. + fe.LowerToSSA() + if wazevoapi.PrintSSA && wazevoapi.PrintEnabledIndex(ctx) { + fmt.Printf("[[[SSA for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), ssaBuilder.Format()) + } + + if wazevoapi.DeterministicCompilationVerifierEnabled { + wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "SSA", ssaBuilder.Format()) + } + + // Run SSA-level optimization passes. + ssaBuilder.RunPasses() + + if wazevoapi.PrintOptimizedSSA && wazevoapi.PrintEnabledIndex(ctx) { + fmt.Printf("[[[Optimized SSA for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), ssaBuilder.Format()) + } + + if wazevoapi.DeterministicCompilationVerifierEnabled { + wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "Optimized SSA", ssaBuilder.Format()) + } + + // Now our ssaBuilder contains the necessary information to further lower them to + // machine code. + original, rels, err := be.Compile(ctx) + if err != nil { + return nil, nil, fmt.Errorf("ssa->machine code: %v", err) + } + + // TODO: optimize as zero copy. + copied := make([]byte, len(original)) + copy(copied, original) + return copied, rels, nil +} + +func (e *engine) compileHostModule(ctx context.Context, module *wasm.Module, listeners []experimental.FunctionListener) (*compiledModule, error) { + machine := newMachine() + be := backend.NewCompiler(ctx, machine, ssa.NewBuilder()) + + num := len(module.CodeSection) + cm := &compiledModule{module: module, listeners: listeners, executables: &executables{}} + cm.functionOffsets = make([]int, num) + totalSize := 0 // Total binary size of the executable. + bodies := make([][]byte, num) + var sig ssa.Signature + for i := range module.CodeSection { + totalSize = (totalSize + 15) &^ 15 + cm.functionOffsets[i] = totalSize + + typIndex := module.FunctionSection[i] + typ := &module.TypeSection[typIndex] + + // We can relax until the index fits together in ExitCode as we do in wazevoapi.ExitCodeCallGoModuleFunctionWithIndex. + // However, 1 << 16 should be large enough for a real use case. + const hostFunctionNumMaximum = 1 << 16 + if i >= hostFunctionNumMaximum { + return nil, fmt.Errorf("too many host functions (maximum %d)", hostFunctionNumMaximum) + } + + sig.ID = ssa.SignatureID(typIndex) // This is important since we reuse the `machine` which caches the ABI based on the SignatureID. + sig.Params = append(sig.Params[:0], + ssa.TypeI64, // First argument must be exec context. + ssa.TypeI64, // The second argument is the moduleContextOpaque of this host module. + ) + for _, t := range typ.Params { + sig.Params = append(sig.Params, frontend.WasmTypeToSSAType(t)) + } + + sig.Results = sig.Results[:0] + for _, t := range typ.Results { + sig.Results = append(sig.Results, frontend.WasmTypeToSSAType(t)) + } + + c := &module.CodeSection[i] + if c.GoFunc == nil { + panic("BUG: GoFunc must be set for host module") + } + + withListener := len(listeners) > 0 && listeners[i] != nil + var exitCode wazevoapi.ExitCode + fn := c.GoFunc + switch fn.(type) { + case api.GoModuleFunction: + exitCode = wazevoapi.ExitCodeCallGoModuleFunctionWithIndex(i, withListener) + case api.GoFunction: + exitCode = wazevoapi.ExitCodeCallGoFunctionWithIndex(i, withListener) + } + + be.Init() + machine.CompileGoFunctionTrampoline(exitCode, &sig, true) + if err := be.Finalize(ctx); err != nil { + return nil, err + } + body := be.Buf() + + if wazevoapi.PerfMapEnabled { + name := module.FunctionDefinition(wasm.Index(i)).DebugName() + wazevoapi.PerfMap.AddModuleEntry(i, + int64(totalSize), + uint64(len(body)), + fmt.Sprintf("trampoline:%s", name)) + } + + // TODO: optimize as zero copy. + copied := make([]byte, len(body)) + copy(copied, body) + bodies[i] = copied + totalSize += len(body) + } + + if totalSize == 0 { + // Empty module. + return cm, nil + } + + // Allocate executable memory and then copy the generated machine code. + executable, err := platform.MmapCodeSegment(totalSize) + if err != nil { + panic(err) + } + cm.executable = executable + + for i, b := range bodies { + offset := cm.functionOffsets[i] + copy(executable[offset:], b) + } + + if wazevoapi.PerfMapEnabled { + wazevoapi.PerfMap.Flush(uintptr(unsafe.Pointer(&executable[0])), cm.functionOffsets) + } + + if runtime.GOARCH == "arm64" { + // On arm64, we cannot give all of rwx at the same time, so we change it to exec. + if err = platform.MprotectRX(executable); err != nil { + return nil, err + } + } + e.setFinalizer(cm.executables, executablesFinalizer) + return cm, nil +} + +// Close implements wasm.Engine. +func (e *engine) Close() (err error) { + e.mux.Lock() + defer e.mux.Unlock() + e.sortedCompiledModules = nil + e.compiledModules = nil + e.sharedFunctions = nil + return nil +} + +// CompiledModuleCount implements wasm.Engine. +func (e *engine) CompiledModuleCount() uint32 { + e.mux.RLock() + defer e.mux.RUnlock() + return uint32(len(e.compiledModules)) +} + +// DeleteCompiledModule implements wasm.Engine. +func (e *engine) DeleteCompiledModule(m *wasm.Module) { + e.mux.Lock() + defer e.mux.Unlock() + cm, ok := e.compiledModules[m.ID] + if ok { + if len(cm.executable) > 0 { + e.deleteCompiledModuleFromSortedList(cm) + } + delete(e.compiledModules, m.ID) + } +} + +func (e *engine) addCompiledModuleToSortedList(cm *compiledModule) { + ptr := uintptr(unsafe.Pointer(&cm.executable[0])) + + index := sort.Search(len(e.sortedCompiledModules), func(i int) bool { + return uintptr(unsafe.Pointer(&e.sortedCompiledModules[i].executable[0])) >= ptr + }) + e.sortedCompiledModules = append(e.sortedCompiledModules, nil) + copy(e.sortedCompiledModules[index+1:], e.sortedCompiledModules[index:]) + e.sortedCompiledModules[index] = cm +} + +func (e *engine) deleteCompiledModuleFromSortedList(cm *compiledModule) { + ptr := uintptr(unsafe.Pointer(&cm.executable[0])) + + index := sort.Search(len(e.sortedCompiledModules), func(i int) bool { + return uintptr(unsafe.Pointer(&e.sortedCompiledModules[i].executable[0])) >= ptr + }) + if index >= len(e.sortedCompiledModules) { + return + } + copy(e.sortedCompiledModules[index:], e.sortedCompiledModules[index+1:]) + e.sortedCompiledModules = e.sortedCompiledModules[:len(e.sortedCompiledModules)-1] +} + +func (e *engine) compiledModuleOfAddr(addr uintptr) *compiledModule { + e.mux.RLock() + defer e.mux.RUnlock() + + index := sort.Search(len(e.sortedCompiledModules), func(i int) bool { + return uintptr(unsafe.Pointer(&e.sortedCompiledModules[i].executable[0])) > addr + }) + index -= 1 + if index < 0 { + return nil + } + candidate := e.sortedCompiledModules[index] + if checkAddrInBytes(addr, candidate.executable) { + // If a module is already deleted, the found module may have been wrong. + return candidate + } + return nil +} + +func checkAddrInBytes(addr uintptr, b []byte) bool { + return uintptr(unsafe.Pointer(&b[0])) <= addr && addr <= uintptr(unsafe.Pointer(&b[len(b)-1])) +} + +// NewModuleEngine implements wasm.Engine. +func (e *engine) NewModuleEngine(m *wasm.Module, mi *wasm.ModuleInstance) (wasm.ModuleEngine, error) { + me := &moduleEngine{} + + // Note: imported functions are resolved in moduleEngine.ResolveImportedFunction. + me.importedFunctions = make([]importedFunction, m.ImportFunctionCount) + + compiled, ok := e.getCompiledModuleFromMemory(m) + if !ok { + return nil, errors.New("source module must be compiled before instantiation") + } + me.parent = compiled + me.module = mi + me.listeners = compiled.listeners + + if m.IsHostModule { + me.opaque = buildHostModuleOpaque(m, compiled.listeners) + me.opaquePtr = &me.opaque[0] + } else { + if size := compiled.offsets.TotalSize; size != 0 { + opaque := newAlignedOpaque(size) + me.opaque = opaque + me.opaquePtr = &opaque[0] + } + } + return me, nil +} + +func (e *engine) compileSharedFunctions() { + e.sharedFunctions = &sharedFunctions{ + listenerBeforeTrampolines: make(map[*wasm.FunctionType][]byte), + listenerAfterTrampolines: make(map[*wasm.FunctionType][]byte), + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeGrowMemory, &ssa.Signature{ + Params: []ssa.Type{ssa.TypeI64 /* exec context */, ssa.TypeI32}, + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.memoryGrowExecutable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.memoryGrowExecutable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "memory_grow_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeTableGrow, &ssa.Signature{ + Params: []ssa.Type{ssa.TypeI64 /* exec context */, ssa.TypeI32 /* table index */, ssa.TypeI32 /* num */, ssa.TypeI64 /* ref */}, + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.tableGrowExecutable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.tableGrowExecutable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "table_grow_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeCheckModuleExitCode, &ssa.Signature{ + Params: []ssa.Type{ssa.TypeI32 /* exec context */}, + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.checkModuleExitCode = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.checkModuleExitCode + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "check_module_exit_code_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeRefFunc, &ssa.Signature{ + Params: []ssa.Type{ssa.TypeI64 /* exec context */, ssa.TypeI32 /* function index */}, + Results: []ssa.Type{ssa.TypeI64}, // returns the function reference. + }, false) + e.sharedFunctions.refFuncExecutable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.refFuncExecutable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "ref_func_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileStackGrowCallSequence() + e.sharedFunctions.stackGrowExecutable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.stackGrowExecutable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "stack_grow_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeMemoryWait32, &ssa.Signature{ + // exec context, timeout, expected, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32, ssa.TypeI64}, + // Returns the status. + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.memoryWait32Executable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.memoryWait32Executable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "memory_wait32_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeMemoryWait64, &ssa.Signature{ + // exec context, timeout, expected, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI64}, + // Returns the status. + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.memoryWait64Executable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.memoryWait64Executable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "memory_wait64_trampoline") + } + } + + e.be.Init() + { + src := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeMemoryNotify, &ssa.Signature{ + // exec context, count, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64}, + // Returns the number notified. + Results: []ssa.Type{ssa.TypeI32}, + }, false) + e.sharedFunctions.memoryNotifyExecutable = mmapExecutable(src) + if wazevoapi.PerfMapEnabled { + exe := e.sharedFunctions.memoryNotifyExecutable + wazevoapi.PerfMap.AddEntry(uintptr(unsafe.Pointer(&exe[0])), uint64(len(exe)), "memory_notify_trampoline") + } + } + + e.setFinalizer(e.sharedFunctions, sharedFunctionsFinalizer) +} + +func sharedFunctionsFinalizer(sf *sharedFunctions) { + if err := platform.MunmapCodeSegment(sf.memoryGrowExecutable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.checkModuleExitCode); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.stackGrowExecutable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.tableGrowExecutable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.refFuncExecutable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.memoryWait32Executable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.memoryWait64Executable); err != nil { + panic(err) + } + if err := platform.MunmapCodeSegment(sf.memoryNotifyExecutable); err != nil { + panic(err) + } + for _, f := range sf.listenerBeforeTrampolines { + if err := platform.MunmapCodeSegment(f); err != nil { + panic(err) + } + } + for _, f := range sf.listenerAfterTrampolines { + if err := platform.MunmapCodeSegment(f); err != nil { + panic(err) + } + } + + sf.memoryGrowExecutable = nil + sf.checkModuleExitCode = nil + sf.stackGrowExecutable = nil + sf.tableGrowExecutable = nil + sf.refFuncExecutable = nil + sf.memoryWait32Executable = nil + sf.memoryWait64Executable = nil + sf.memoryNotifyExecutable = nil + sf.listenerBeforeTrampolines = nil + sf.listenerAfterTrampolines = nil +} + +func executablesFinalizer(exec *executables) { + if len(exec.executable) > 0 { + if err := platform.MunmapCodeSegment(exec.executable); err != nil { + panic(err) + } + } + exec.executable = nil + + for _, f := range exec.entryPreambles { + if err := platform.MunmapCodeSegment(f); err != nil { + panic(err) + } + } + exec.entryPreambles = nil +} + +func mmapExecutable(src []byte) []byte { + executable, err := platform.MmapCodeSegment(len(src)) + if err != nil { + panic(err) + } + + copy(executable, src) + + if runtime.GOARCH == "arm64" { + // On arm64, we cannot give all of rwx at the same time, so we change it to exec. + if err = platform.MprotectRX(executable); err != nil { + panic(err) + } + } + return executable +} + +func (cm *compiledModule) functionIndexOf(addr uintptr) wasm.Index { + addr -= uintptr(unsafe.Pointer(&cm.executable[0])) + offset := cm.functionOffsets + index := sort.Search(len(offset), func(i int) bool { + return offset[i] > int(addr) + }) + index-- + if index < 0 { + panic("BUG") + } + return wasm.Index(index) +} + +func (e *engine) getListenerTrampolineForType(functionType *wasm.FunctionType) (before, after *byte) { + e.mux.Lock() + defer e.mux.Unlock() + + beforeBuf, ok := e.sharedFunctions.listenerBeforeTrampolines[functionType] + afterBuf := e.sharedFunctions.listenerAfterTrampolines[functionType] + if ok { + return &beforeBuf[0], &afterBuf[0] + } + + beforeSig, afterSig := frontend.SignatureForListener(functionType) + + e.be.Init() + buf := e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeCallListenerBefore, beforeSig, false) + beforeBuf = mmapExecutable(buf) + + e.be.Init() + buf = e.machine.CompileGoFunctionTrampoline(wazevoapi.ExitCodeCallListenerAfter, afterSig, false) + afterBuf = mmapExecutable(buf) + + e.sharedFunctions.listenerBeforeTrampolines[functionType] = beforeBuf + e.sharedFunctions.listenerAfterTrampolines[functionType] = afterBuf + return &beforeBuf[0], &afterBuf[0] +} + +func (cm *compiledModule) getSourceOffset(pc uintptr) uint64 { + offsets := cm.sourceMap.executableOffsets + if len(offsets) == 0 { + return 0 + } + + index := sort.Search(len(offsets), func(i int) bool { + return offsets[i] >= pc + }) + + index-- + if index < 0 { + return 0 + } + return cm.sourceMap.wasmBinaryOffsets[index] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine_cache.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine_cache.go new file mode 100644 index 00000000..e49353dc --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/engine_cache.go @@ -0,0 +1,303 @@ +package wazevo + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/binary" + "fmt" + "hash/crc32" + "io" + "runtime" + "unsafe" + + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/filecache" + "github.com/tetratelabs/wazero/internal/platform" + "github.com/tetratelabs/wazero/internal/u32" + "github.com/tetratelabs/wazero/internal/u64" + "github.com/tetratelabs/wazero/internal/wasm" +) + +var crc = crc32.MakeTable(crc32.Castagnoli) + +// fileCacheKey returns a key for the file cache. +// In order to avoid collisions with the existing compiler, we do not use m.ID directly, +// but instead we rehash it with magic. +func fileCacheKey(m *wasm.Module) (ret filecache.Key) { + s := sha256.New() + s.Write(m.ID[:]) + s.Write(magic) + // Write the CPU features so that we can cache the compiled module for the same CPU. + // This prevents the incompatible CPU features from being used. + cpu := platform.CpuFeatures.Raw() + // Reuse the `ret` buffer to write the first 8 bytes of the CPU features so that we can avoid the allocation. + binary.LittleEndian.PutUint64(ret[:8], cpu) + s.Write(ret[:8]) + // Finally, write the hash to the ret buffer. + s.Sum(ret[:0]) + return +} + +func (e *engine) addCompiledModule(module *wasm.Module, cm *compiledModule) (err error) { + e.addCompiledModuleToMemory(module, cm) + if !module.IsHostModule && e.fileCache != nil { + err = e.addCompiledModuleToCache(module, cm) + } + return +} + +func (e *engine) getCompiledModule(module *wasm.Module, listeners []experimental.FunctionListener, ensureTermination bool) (cm *compiledModule, ok bool, err error) { + cm, ok = e.getCompiledModuleFromMemory(module) + if ok { + return + } + cm, ok, err = e.getCompiledModuleFromCache(module) + if ok { + cm.parent = e + cm.module = module + cm.sharedFunctions = e.sharedFunctions + cm.ensureTermination = ensureTermination + cm.offsets = wazevoapi.NewModuleContextOffsetData(module, len(listeners) > 0) + if len(listeners) > 0 { + cm.listeners = listeners + cm.listenerBeforeTrampolines = make([]*byte, len(module.TypeSection)) + cm.listenerAfterTrampolines = make([]*byte, len(module.TypeSection)) + for i := range module.TypeSection { + typ := &module.TypeSection[i] + before, after := e.getListenerTrampolineForType(typ) + cm.listenerBeforeTrampolines[i] = before + cm.listenerAfterTrampolines[i] = after + } + } + e.addCompiledModuleToMemory(module, cm) + ssaBuilder := ssa.NewBuilder() + machine := newMachine() + be := backend.NewCompiler(context.Background(), machine, ssaBuilder) + cm.executables.compileEntryPreambles(module, machine, be) + + // Set the finalizer. + e.setFinalizer(cm.executables, executablesFinalizer) + } + return +} + +func (e *engine) addCompiledModuleToMemory(m *wasm.Module, cm *compiledModule) { + e.mux.Lock() + defer e.mux.Unlock() + e.compiledModules[m.ID] = cm + if len(cm.executable) > 0 { + e.addCompiledModuleToSortedList(cm) + } +} + +func (e *engine) getCompiledModuleFromMemory(module *wasm.Module) (cm *compiledModule, ok bool) { + e.mux.RLock() + defer e.mux.RUnlock() + cm, ok = e.compiledModules[module.ID] + return +} + +func (e *engine) addCompiledModuleToCache(module *wasm.Module, cm *compiledModule) (err error) { + if e.fileCache == nil || module.IsHostModule { + return + } + err = e.fileCache.Add(fileCacheKey(module), serializeCompiledModule(e.wazeroVersion, cm)) + return +} + +func (e *engine) getCompiledModuleFromCache(module *wasm.Module) (cm *compiledModule, hit bool, err error) { + if e.fileCache == nil || module.IsHostModule { + return + } + + // Check if the entries exist in the external cache. + var cached io.ReadCloser + cached, hit, err = e.fileCache.Get(fileCacheKey(module)) + if !hit || err != nil { + return + } + + // Otherwise, we hit the cache on external cache. + // We retrieve *code structures from `cached`. + var staleCache bool + // Note: cached.Close is ensured to be called in deserializeCodes. + cm, staleCache, err = deserializeCompiledModule(e.wazeroVersion, cached) + if err != nil { + hit = false + return + } else if staleCache { + return nil, false, e.fileCache.Delete(fileCacheKey(module)) + } + return +} + +var magic = []byte{'W', 'A', 'Z', 'E', 'V', 'O'} + +func serializeCompiledModule(wazeroVersion string, cm *compiledModule) io.Reader { + buf := bytes.NewBuffer(nil) + // First 6 byte: WAZEVO header. + buf.Write(magic) + // Next 1 byte: length of version: + buf.WriteByte(byte(len(wazeroVersion))) + // Version of wazero. + buf.WriteString(wazeroVersion) + // Number of *code (== locally defined functions in the module): 4 bytes. + buf.Write(u32.LeBytes(uint32(len(cm.functionOffsets)))) + for _, offset := range cm.functionOffsets { + // The offset of this function in the executable (8 bytes). + buf.Write(u64.LeBytes(uint64(offset))) + } + // The length of code segment (8 bytes). + buf.Write(u64.LeBytes(uint64(len(cm.executable)))) + // Append the native code. + buf.Write(cm.executable) + // Append checksum. + checksum := crc32.Checksum(cm.executable, crc) + buf.Write(u32.LeBytes(checksum)) + if sm := cm.sourceMap; len(sm.executableOffsets) > 0 { + buf.WriteByte(1) // indicates that source map is present. + l := len(sm.wasmBinaryOffsets) + buf.Write(u64.LeBytes(uint64(l))) + executableAddr := uintptr(unsafe.Pointer(&cm.executable[0])) + for i := 0; i < l; i++ { + buf.Write(u64.LeBytes(sm.wasmBinaryOffsets[i])) + // executableOffsets is absolute address, so we need to subtract executableAddr. + buf.Write(u64.LeBytes(uint64(sm.executableOffsets[i] - executableAddr))) + } + } else { + buf.WriteByte(0) // indicates that source map is not present. + } + return bytes.NewReader(buf.Bytes()) +} + +func deserializeCompiledModule(wazeroVersion string, reader io.ReadCloser) (cm *compiledModule, staleCache bool, err error) { + defer reader.Close() + cacheHeaderSize := len(magic) + 1 /* version size */ + len(wazeroVersion) + 4 /* number of functions */ + + // Read the header before the native code. + header := make([]byte, cacheHeaderSize) + n, err := reader.Read(header) + if err != nil { + return nil, false, fmt.Errorf("compilationcache: error reading header: %v", err) + } + + if n != cacheHeaderSize { + return nil, false, fmt.Errorf("compilationcache: invalid header length: %d", n) + } + + if !bytes.Equal(header[:len(magic)], magic) { + return nil, false, fmt.Errorf( + "compilationcache: invalid magic number: got %s but want %s", magic, header[:len(magic)]) + } + + // Check the version compatibility. + versionSize := int(header[len(magic)]) + + cachedVersionBegin, cachedVersionEnd := len(magic)+1, len(magic)+1+versionSize + if cachedVersionEnd >= len(header) { + staleCache = true + return + } else if cachedVersion := string(header[cachedVersionBegin:cachedVersionEnd]); cachedVersion != wazeroVersion { + staleCache = true + return + } + + functionsNum := binary.LittleEndian.Uint32(header[len(header)-4:]) + cm = &compiledModule{functionOffsets: make([]int, functionsNum), executables: &executables{}} + + var eightBytes [8]byte + for i := uint32(0); i < functionsNum; i++ { + // Read the offset of each function in the executable. + var offset uint64 + if offset, err = readUint64(reader, &eightBytes); err != nil { + err = fmt.Errorf("compilationcache: error reading func[%d] executable offset: %v", i, err) + return + } + cm.functionOffsets[i] = int(offset) + } + + executableLen, err := readUint64(reader, &eightBytes) + if err != nil { + err = fmt.Errorf("compilationcache: error reading executable size: %v", err) + return + } + + if executableLen > 0 { + executable, err := platform.MmapCodeSegment(int(executableLen)) + if err != nil { + err = fmt.Errorf("compilationcache: error mmapping executable (len=%d): %v", executableLen, err) + return nil, false, err + } + + _, err = io.ReadFull(reader, executable) + if err != nil { + err = fmt.Errorf("compilationcache: error reading executable (len=%d): %v", executableLen, err) + return nil, false, err + } + + expected := crc32.Checksum(executable, crc) + if _, err = io.ReadFull(reader, eightBytes[:4]); err != nil { + return nil, false, fmt.Errorf("compilationcache: could not read checksum: %v", err) + } else if checksum := binary.LittleEndian.Uint32(eightBytes[:4]); expected != checksum { + return nil, false, fmt.Errorf("compilationcache: checksum mismatch (expected %d, got %d)", expected, checksum) + } + + if runtime.GOARCH == "arm64" { + // On arm64, we cannot give all of rwx at the same time, so we change it to exec. + if err = platform.MprotectRX(executable); err != nil { + return nil, false, err + } + } + cm.executable = executable + } + + if _, err := io.ReadFull(reader, eightBytes[:1]); err != nil { + return nil, false, fmt.Errorf("compilationcache: error reading source map presence: %v", err) + } + + if eightBytes[0] == 1 { + sm := &cm.sourceMap + sourceMapLen, err := readUint64(reader, &eightBytes) + if err != nil { + err = fmt.Errorf("compilationcache: error reading source map length: %v", err) + return nil, false, err + } + executableOffset := uintptr(unsafe.Pointer(&cm.executable[0])) + for i := uint64(0); i < sourceMapLen; i++ { + wasmBinaryOffset, err := readUint64(reader, &eightBytes) + if err != nil { + err = fmt.Errorf("compilationcache: error reading source map[%d] wasm binary offset: %v", i, err) + return nil, false, err + } + executableRelativeOffset, err := readUint64(reader, &eightBytes) + if err != nil { + err = fmt.Errorf("compilationcache: error reading source map[%d] executable offset: %v", i, err) + return nil, false, err + } + sm.wasmBinaryOffsets = append(sm.wasmBinaryOffsets, wasmBinaryOffset) + // executableOffsets is absolute address, so we need to add executableOffset. + sm.executableOffsets = append(sm.executableOffsets, uintptr(executableRelativeOffset)+executableOffset) + } + } + return +} + +// readUint64 strictly reads an uint64 in little-endian byte order, using the +// given array as a buffer. This returns io.EOF if less than 8 bytes were read. +func readUint64(reader io.Reader, b *[8]byte) (uint64, error) { + s := b[0:8] + n, err := reader.Read(s) + if err != nil { + return 0, err + } else if n < 8 { // more strict than reader.Read + return 0, io.EOF + } + + // Read the u64 from the underlying buffer. + ret := binary.LittleEndian.Uint64(s) + return ret, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_amd64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_amd64.go new file mode 100644 index 00000000..18f60af3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_amd64.go @@ -0,0 +1,15 @@ +//go:build amd64 && !tinygo + +package wazevo + +import _ "unsafe" + +// entrypoint is implemented by the backend. +// +//go:linkname entrypoint github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64.entrypoint +func entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultStackPtr *uint64, goAllocatedStackSlicePtr uintptr) + +// entrypoint is implemented by the backend. +// +//go:linkname afterGoFunctionCallEntrypoint github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64.afterGoFunctionCallEntrypoint +func afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_arm64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_arm64.go new file mode 100644 index 00000000..e16d64f6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_arm64.go @@ -0,0 +1,15 @@ +//go:build arm64 && !tinygo + +package wazevo + +import _ "unsafe" + +// entrypoint is implemented by the backend. +// +//go:linkname entrypoint github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64.entrypoint +func entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultStackPtr *uint64, goAllocatedStackSlicePtr uintptr) + +// entrypoint is implemented by the backend. +// +//go:linkname afterGoFunctionCallEntrypoint github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64.afterGoFunctionCallEntrypoint +func afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_others.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_others.go new file mode 100644 index 00000000..8f9d64b2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/entrypoint_others.go @@ -0,0 +1,15 @@ +//go:build (!arm64 && !amd64) || tinygo + +package wazevo + +import ( + "runtime" +) + +func entrypoint(preambleExecutable, functionExecutable *byte, executionContextPtr uintptr, moduleContextPtr *byte, paramResultStackPtr *uint64, goAllocatedStackSlicePtr uintptr) { + panic(runtime.GOARCH) +} + +func afterGoFunctionCallEntrypoint(executable *byte, executionContextPtr uintptr, stackPointer, framePointer uintptr) { + panic(runtime.GOARCH) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/frontend.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/frontend.go new file mode 100644 index 00000000..eebdba03 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/frontend.go @@ -0,0 +1,567 @@ +// Package frontend implements the translation of WebAssembly to SSA IR using the ssa package. +package frontend + +import ( + "bytes" + "math" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// Compiler is in charge of lowering Wasm to SSA IR, and does the optimization +// on top of it in architecture-independent way. +type Compiler struct { + // Per-module data that is used across all functions. + + m *wasm.Module + offset *wazevoapi.ModuleContextOffsetData + // ssaBuilder is a ssa.Builder used by this frontend. + ssaBuilder ssa.Builder + signatures map[*wasm.FunctionType]*ssa.Signature + listenerSignatures map[*wasm.FunctionType][2]*ssa.Signature + memoryGrowSig ssa.Signature + memoryWait32Sig ssa.Signature + memoryWait64Sig ssa.Signature + memoryNotifySig ssa.Signature + checkModuleExitCodeSig ssa.Signature + tableGrowSig ssa.Signature + refFuncSig ssa.Signature + memmoveSig ssa.Signature + ensureTermination bool + + // Followings are reset by per function. + + // wasmLocalToVariable maps the index (considered as wasm.Index of locals) + // to the corresponding ssa.Variable. + wasmLocalToVariable [] /* local index to */ ssa.Variable + wasmLocalFunctionIndex wasm.Index + wasmFunctionTypeIndex wasm.Index + wasmFunctionTyp *wasm.FunctionType + wasmFunctionLocalTypes []wasm.ValueType + wasmFunctionBody []byte + wasmFunctionBodyOffsetInCodeSection uint64 + memoryBaseVariable, memoryLenVariable ssa.Variable + needMemory bool + memoryShared bool + globalVariables []ssa.Variable + globalVariablesTypes []ssa.Type + mutableGlobalVariablesIndexes []wasm.Index // index to ^. + needListener bool + needSourceOffsetInfo bool + // br is reused during lowering. + br *bytes.Reader + loweringState loweringState + + knownSafeBounds [] /* ssa.ValueID to */ knownSafeBound + knownSafeBoundsSet []ssa.ValueID + + knownSafeBoundsAtTheEndOfBlocks [] /* ssa.BlockID to */ knownSafeBoundsAtTheEndOfBlock + varLengthKnownSafeBoundWithIDPool wazevoapi.VarLengthPool[knownSafeBoundWithID] + + execCtxPtrValue, moduleCtxPtrValue ssa.Value + + // Following are reused for the known safe bounds analysis. + + pointers []int + bounds [][]knownSafeBoundWithID +} + +type ( + // knownSafeBound represents a known safe bound for a value. + knownSafeBound struct { + // bound is a constant upper bound for the value. + bound uint64 + // absoluteAddr is the absolute address of the value. + absoluteAddr ssa.Value + } + // knownSafeBoundWithID is a knownSafeBound with the ID of the value. + knownSafeBoundWithID struct { + knownSafeBound + id ssa.ValueID + } + knownSafeBoundsAtTheEndOfBlock = wazevoapi.VarLength[knownSafeBoundWithID] +) + +var knownSafeBoundsAtTheEndOfBlockNil = wazevoapi.NewNilVarLength[knownSafeBoundWithID]() + +// NewFrontendCompiler returns a frontend Compiler. +func NewFrontendCompiler(m *wasm.Module, ssaBuilder ssa.Builder, offset *wazevoapi.ModuleContextOffsetData, ensureTermination bool, listenerOn bool, sourceInfo bool) *Compiler { + c := &Compiler{ + m: m, + ssaBuilder: ssaBuilder, + br: bytes.NewReader(nil), + offset: offset, + ensureTermination: ensureTermination, + needSourceOffsetInfo: sourceInfo, + varLengthKnownSafeBoundWithIDPool: wazevoapi.NewVarLengthPool[knownSafeBoundWithID](), + } + c.declareSignatures(listenerOn) + return c +} + +func (c *Compiler) declareSignatures(listenerOn bool) { + m := c.m + c.signatures = make(map[*wasm.FunctionType]*ssa.Signature, len(m.TypeSection)+2) + if listenerOn { + c.listenerSignatures = make(map[*wasm.FunctionType][2]*ssa.Signature, len(m.TypeSection)) + } + for i := range m.TypeSection { + wasmSig := &m.TypeSection[i] + sig := SignatureForWasmFunctionType(wasmSig) + sig.ID = ssa.SignatureID(i) + c.signatures[wasmSig] = &sig + c.ssaBuilder.DeclareSignature(&sig) + + if listenerOn { + beforeSig, afterSig := SignatureForListener(wasmSig) + beforeSig.ID = ssa.SignatureID(i) + ssa.SignatureID(len(m.TypeSection)) + afterSig.ID = ssa.SignatureID(i) + ssa.SignatureID(len(m.TypeSection))*2 + c.listenerSignatures[wasmSig] = [2]*ssa.Signature{beforeSig, afterSig} + c.ssaBuilder.DeclareSignature(beforeSig) + c.ssaBuilder.DeclareSignature(afterSig) + } + } + + begin := ssa.SignatureID(len(m.TypeSection)) + if listenerOn { + begin *= 3 + } + c.memoryGrowSig = ssa.Signature{ + ID: begin, + // Takes execution context and the page size to grow. + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, + // Returns the previous page size. + Results: []ssa.Type{ssa.TypeI32}, + } + c.ssaBuilder.DeclareSignature(&c.memoryGrowSig) + + c.checkModuleExitCodeSig = ssa.Signature{ + ID: c.memoryGrowSig.ID + 1, + // Only takes execution context. + Params: []ssa.Type{ssa.TypeI64}, + } + c.ssaBuilder.DeclareSignature(&c.checkModuleExitCodeSig) + + c.tableGrowSig = ssa.Signature{ + ID: c.checkModuleExitCodeSig.ID + 1, + Params: []ssa.Type{ssa.TypeI64 /* exec context */, ssa.TypeI32 /* table index */, ssa.TypeI32 /* num */, ssa.TypeI64 /* ref */}, + // Returns the previous size. + Results: []ssa.Type{ssa.TypeI32}, + } + c.ssaBuilder.DeclareSignature(&c.tableGrowSig) + + c.refFuncSig = ssa.Signature{ + ID: c.tableGrowSig.ID + 1, + Params: []ssa.Type{ssa.TypeI64 /* exec context */, ssa.TypeI32 /* func index */}, + // Returns the function reference. + Results: []ssa.Type{ssa.TypeI64}, + } + c.ssaBuilder.DeclareSignature(&c.refFuncSig) + + c.memmoveSig = ssa.Signature{ + ID: c.refFuncSig.ID + 1, + // dst, src, and the byte count. + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64}, + } + + c.ssaBuilder.DeclareSignature(&c.memmoveSig) + + c.memoryWait32Sig = ssa.Signature{ + ID: c.memmoveSig.ID + 1, + // exec context, timeout, expected, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32, ssa.TypeI64}, + // Returns the status. + Results: []ssa.Type{ssa.TypeI32}, + } + c.ssaBuilder.DeclareSignature(&c.memoryWait32Sig) + + c.memoryWait64Sig = ssa.Signature{ + ID: c.memoryWait32Sig.ID + 1, + // exec context, timeout, expected, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI64}, + // Returns the status. + Results: []ssa.Type{ssa.TypeI32}, + } + c.ssaBuilder.DeclareSignature(&c.memoryWait64Sig) + + c.memoryNotifySig = ssa.Signature{ + ID: c.memoryWait64Sig.ID + 1, + // exec context, count, addr + Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64}, + // Returns the number notified. + Results: []ssa.Type{ssa.TypeI32}, + } + c.ssaBuilder.DeclareSignature(&c.memoryNotifySig) +} + +// SignatureForWasmFunctionType returns the ssa.Signature for the given wasm.FunctionType. +func SignatureForWasmFunctionType(typ *wasm.FunctionType) ssa.Signature { + sig := ssa.Signature{ + // +2 to pass moduleContextPtr and executionContextPtr. See the inline comment LowerToSSA. + Params: make([]ssa.Type, len(typ.Params)+2), + Results: make([]ssa.Type, len(typ.Results)), + } + sig.Params[0] = executionContextPtrTyp + sig.Params[1] = moduleContextPtrTyp + for j, typ := range typ.Params { + sig.Params[j+2] = WasmTypeToSSAType(typ) + } + for j, typ := range typ.Results { + sig.Results[j] = WasmTypeToSSAType(typ) + } + return sig +} + +// Init initializes the state of frontendCompiler and make it ready for a next function. +func (c *Compiler) Init(idx, typIndex wasm.Index, typ *wasm.FunctionType, localTypes []wasm.ValueType, body []byte, needListener bool, bodyOffsetInCodeSection uint64) { + c.ssaBuilder.Init(c.signatures[typ]) + c.loweringState.reset() + + c.wasmFunctionTypeIndex = typIndex + c.wasmLocalFunctionIndex = idx + c.wasmFunctionTyp = typ + c.wasmFunctionLocalTypes = localTypes + c.wasmFunctionBody = body + c.wasmFunctionBodyOffsetInCodeSection = bodyOffsetInCodeSection + c.needListener = needListener + c.clearSafeBounds() + c.varLengthKnownSafeBoundWithIDPool.Reset() + c.knownSafeBoundsAtTheEndOfBlocks = c.knownSafeBoundsAtTheEndOfBlocks[:0] +} + +// Note: this assumes 64-bit platform (I believe we won't have 32-bit backend ;)). +const executionContextPtrTyp, moduleContextPtrTyp = ssa.TypeI64, ssa.TypeI64 + +// LowerToSSA lowers the current function to SSA function which will be held by ssaBuilder. +// After calling this, the caller will be able to access the SSA info in *Compiler.ssaBuilder. +// +// Note that this only does the naive lowering, and do not do any optimization, instead the caller is expected to do so. +func (c *Compiler) LowerToSSA() { + builder := c.ssaBuilder + + // Set up the entry block. + entryBlock := builder.AllocateBasicBlock() + builder.SetCurrentBlock(entryBlock) + + // Functions always take two parameters in addition to Wasm-level parameters: + // + // 1. executionContextPtr: pointer to the *executionContext in wazevo package. + // This will be used to exit the execution in the face of trap, plus used for host function calls. + // + // 2. moduleContextPtr: pointer to the *moduleContextOpaque in wazevo package. + // This will be used to access memory, etc. Also, this will be used during host function calls. + // + // Note: it's clear that sometimes a function won't need them. For example, + // if the function doesn't trap and doesn't make function call, then + // we might be able to eliminate the parameter. However, if that function + // can be called via call_indirect, then we cannot eliminate because the + // signature won't match with the expected one. + // TODO: maybe there's some way to do this optimization without glitches, but so far I have no clue about the feasibility. + // + // Note: In Wasmtime or many other runtimes, moduleContextPtr is called "vmContext". Also note that `moduleContextPtr` + // is wazero-specific since other runtimes can naturally use the OS-level signal to do this job thanks to the fact that + // they can use native stack vs wazero cannot use Go-routine stack and have to use Go-runtime allocated []byte as a stack. + c.execCtxPtrValue = entryBlock.AddParam(builder, executionContextPtrTyp) + c.moduleCtxPtrValue = entryBlock.AddParam(builder, moduleContextPtrTyp) + builder.AnnotateValue(c.execCtxPtrValue, "exec_ctx") + builder.AnnotateValue(c.moduleCtxPtrValue, "module_ctx") + + for i, typ := range c.wasmFunctionTyp.Params { + st := WasmTypeToSSAType(typ) + variable := builder.DeclareVariable(st) + value := entryBlock.AddParam(builder, st) + builder.DefineVariable(variable, value, entryBlock) + c.setWasmLocalVariable(wasm.Index(i), variable) + } + c.declareWasmLocals() + c.declareNecessaryVariables() + + c.lowerBody(entryBlock) +} + +// localVariable returns the SSA variable for the given Wasm local index. +func (c *Compiler) localVariable(index wasm.Index) ssa.Variable { + return c.wasmLocalToVariable[index] +} + +func (c *Compiler) setWasmLocalVariable(index wasm.Index, variable ssa.Variable) { + idx := int(index) + if idx >= len(c.wasmLocalToVariable) { + c.wasmLocalToVariable = append(c.wasmLocalToVariable, make([]ssa.Variable, idx+1-len(c.wasmLocalToVariable))...) + } + c.wasmLocalToVariable[idx] = variable +} + +// declareWasmLocals declares the SSA variables for the Wasm locals. +func (c *Compiler) declareWasmLocals() { + localCount := wasm.Index(len(c.wasmFunctionTyp.Params)) + for i, typ := range c.wasmFunctionLocalTypes { + st := WasmTypeToSSAType(typ) + variable := c.ssaBuilder.DeclareVariable(st) + c.setWasmLocalVariable(wasm.Index(i)+localCount, variable) + c.ssaBuilder.InsertZeroValue(st) + } +} + +func (c *Compiler) declareNecessaryVariables() { + if c.needMemory = c.m.MemorySection != nil; c.needMemory { + c.memoryShared = c.m.MemorySection.IsShared + } else if c.needMemory = c.m.ImportMemoryCount > 0; c.needMemory { + for _, imp := range c.m.ImportSection { + if imp.Type == wasm.ExternTypeMemory { + c.memoryShared = imp.DescMem.IsShared + break + } + } + } + + if c.needMemory { + c.memoryBaseVariable = c.ssaBuilder.DeclareVariable(ssa.TypeI64) + c.memoryLenVariable = c.ssaBuilder.DeclareVariable(ssa.TypeI64) + } + + c.globalVariables = c.globalVariables[:0] + c.mutableGlobalVariablesIndexes = c.mutableGlobalVariablesIndexes[:0] + c.globalVariablesTypes = c.globalVariablesTypes[:0] + for _, imp := range c.m.ImportSection { + if imp.Type == wasm.ExternTypeGlobal { + desc := imp.DescGlobal + c.declareWasmGlobal(desc.ValType, desc.Mutable) + } + } + for _, g := range c.m.GlobalSection { + desc := g.Type + c.declareWasmGlobal(desc.ValType, desc.Mutable) + } + + // TODO: add tables. +} + +func (c *Compiler) declareWasmGlobal(typ wasm.ValueType, mutable bool) { + var st ssa.Type + switch typ { + case wasm.ValueTypeI32: + st = ssa.TypeI32 + case wasm.ValueTypeI64, + // Both externref and funcref are represented as I64 since we only support 64-bit platforms. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + st = ssa.TypeI64 + case wasm.ValueTypeF32: + st = ssa.TypeF32 + case wasm.ValueTypeF64: + st = ssa.TypeF64 + case wasm.ValueTypeV128: + st = ssa.TypeV128 + default: + panic("TODO: " + wasm.ValueTypeName(typ)) + } + v := c.ssaBuilder.DeclareVariable(st) + index := wasm.Index(len(c.globalVariables)) + c.globalVariables = append(c.globalVariables, v) + c.globalVariablesTypes = append(c.globalVariablesTypes, st) + if mutable { + c.mutableGlobalVariablesIndexes = append(c.mutableGlobalVariablesIndexes, index) + } +} + +// WasmTypeToSSAType converts wasm.ValueType to ssa.Type. +func WasmTypeToSSAType(vt wasm.ValueType) ssa.Type { + switch vt { + case wasm.ValueTypeI32: + return ssa.TypeI32 + case wasm.ValueTypeI64, + // Both externref and funcref are represented as I64 since we only support 64-bit platforms. + wasm.ValueTypeExternref, wasm.ValueTypeFuncref: + return ssa.TypeI64 + case wasm.ValueTypeF32: + return ssa.TypeF32 + case wasm.ValueTypeF64: + return ssa.TypeF64 + case wasm.ValueTypeV128: + return ssa.TypeV128 + default: + panic("TODO: " + wasm.ValueTypeName(vt)) + } +} + +// addBlockParamsFromWasmTypes adds the block parameters to the given block. +func (c *Compiler) addBlockParamsFromWasmTypes(tps []wasm.ValueType, blk ssa.BasicBlock) { + for _, typ := range tps { + st := WasmTypeToSSAType(typ) + blk.AddParam(c.ssaBuilder, st) + } +} + +// formatBuilder outputs the constructed SSA function as a string with a source information. +func (c *Compiler) formatBuilder() string { + return c.ssaBuilder.Format() +} + +// SignatureForListener returns the signatures for the listener functions. +func SignatureForListener(wasmSig *wasm.FunctionType) (*ssa.Signature, *ssa.Signature) { + beforeSig := &ssa.Signature{} + beforeSig.Params = make([]ssa.Type, len(wasmSig.Params)+2) + beforeSig.Params[0] = ssa.TypeI64 // Execution context. + beforeSig.Params[1] = ssa.TypeI32 // Function index. + for i, p := range wasmSig.Params { + beforeSig.Params[i+2] = WasmTypeToSSAType(p) + } + afterSig := &ssa.Signature{} + afterSig.Params = make([]ssa.Type, len(wasmSig.Results)+2) + afterSig.Params[0] = ssa.TypeI64 // Execution context. + afterSig.Params[1] = ssa.TypeI32 // Function index. + for i, p := range wasmSig.Results { + afterSig.Params[i+2] = WasmTypeToSSAType(p) + } + return beforeSig, afterSig +} + +// isBoundSafe returns true if the given value is known to be safe to access up to the given bound. +func (c *Compiler) getKnownSafeBound(v ssa.ValueID) *knownSafeBound { + if int(v) >= len(c.knownSafeBounds) { + return nil + } + return &c.knownSafeBounds[v] +} + +// recordKnownSafeBound records the given safe bound for the given value. +func (c *Compiler) recordKnownSafeBound(v ssa.ValueID, safeBound uint64, absoluteAddr ssa.Value) { + if int(v) >= len(c.knownSafeBounds) { + c.knownSafeBounds = append(c.knownSafeBounds, make([]knownSafeBound, v+1)...) + } + + if exiting := c.knownSafeBounds[v]; exiting.bound == 0 { + c.knownSafeBounds[v] = knownSafeBound{ + bound: safeBound, + absoluteAddr: absoluteAddr, + } + c.knownSafeBoundsSet = append(c.knownSafeBoundsSet, v) + } else if safeBound > exiting.bound { + c.knownSafeBounds[v].bound = safeBound + } +} + +// clearSafeBounds clears the known safe bounds. +func (c *Compiler) clearSafeBounds() { + for _, v := range c.knownSafeBoundsSet { + ptr := &c.knownSafeBounds[v] + ptr.bound = 0 + ptr.absoluteAddr = ssa.ValueInvalid + } + c.knownSafeBoundsSet = c.knownSafeBoundsSet[:0] +} + +// resetAbsoluteAddressInSafeBounds resets the absolute addresses recorded in the known safe bounds. +func (c *Compiler) resetAbsoluteAddressInSafeBounds() { + for _, v := range c.knownSafeBoundsSet { + ptr := &c.knownSafeBounds[v] + ptr.absoluteAddr = ssa.ValueInvalid + } +} + +func (k *knownSafeBound) valid() bool { + return k != nil && k.bound > 0 +} + +func (c *Compiler) allocateVarLengthValues(_cap int, vs ...ssa.Value) ssa.Values { + builder := c.ssaBuilder + pool := builder.VarLengthPool() + args := pool.Allocate(_cap) + args = args.Append(builder.VarLengthPool(), vs...) + return args +} + +func (c *Compiler) finalizeKnownSafeBoundsAtTheEndOfBlock(bID ssa.BasicBlockID) { + _bID := int(bID) + if l := len(c.knownSafeBoundsAtTheEndOfBlocks); _bID >= l { + c.knownSafeBoundsAtTheEndOfBlocks = append(c.knownSafeBoundsAtTheEndOfBlocks, + make([]knownSafeBoundsAtTheEndOfBlock, _bID+1-len(c.knownSafeBoundsAtTheEndOfBlocks))...) + for i := l; i < len(c.knownSafeBoundsAtTheEndOfBlocks); i++ { + c.knownSafeBoundsAtTheEndOfBlocks[i] = knownSafeBoundsAtTheEndOfBlockNil + } + } + p := &c.varLengthKnownSafeBoundWithIDPool + size := len(c.knownSafeBoundsSet) + allocated := c.varLengthKnownSafeBoundWithIDPool.Allocate(size) + // Sort the known safe bounds by the value ID so that we can use the intersection algorithm in initializeCurrentBlockKnownBounds. + sortSSAValueIDs(c.knownSafeBoundsSet) + for _, vID := range c.knownSafeBoundsSet { + kb := c.knownSafeBounds[vID] + allocated = allocated.Append(p, knownSafeBoundWithID{ + knownSafeBound: kb, + id: vID, + }) + } + c.knownSafeBoundsAtTheEndOfBlocks[bID] = allocated + c.clearSafeBounds() +} + +func (c *Compiler) initializeCurrentBlockKnownBounds() { + currentBlk := c.ssaBuilder.CurrentBlock() + switch preds := currentBlk.Preds(); preds { + case 0: + case 1: + pred := currentBlk.Pred(0).ID() + for _, kb := range c.getKnownSafeBoundsAtTheEndOfBlocks(pred).View() { + // Unless the block is sealed, we cannot assume the absolute address is valid: + // later we might add another predecessor that has no visibility of that value. + addr := ssa.ValueInvalid + if currentBlk.Sealed() { + addr = kb.absoluteAddr + } + c.recordKnownSafeBound(kb.id, kb.bound, addr) + } + default: + c.pointers = c.pointers[:0] + c.bounds = c.bounds[:0] + for i := 0; i < preds; i++ { + c.bounds = append(c.bounds, c.getKnownSafeBoundsAtTheEndOfBlocks(currentBlk.Pred(i).ID()).View()) + c.pointers = append(c.pointers, 0) + } + + // If there are multiple predecessors, we need to find the intersection of the known safe bounds. + + outer: + for { + smallestID := ssa.ValueID(math.MaxUint32) + for i, ptr := range c.pointers { + if ptr >= len(c.bounds[i]) { + break outer + } + cb := &c.bounds[i][ptr] + if id := cb.id; id < smallestID { + smallestID = cb.id + } + } + + // Check if current elements are the same across all lists. + same := true + minBound := uint64(math.MaxUint64) + for i := 0; i < preds; i++ { + cb := &c.bounds[i][c.pointers[i]] + if cb.id != smallestID { + same = false + } else { + if cb.bound < minBound { + minBound = cb.bound + } + c.pointers[i]++ + } + } + + if same { // All elements are the same. + // Absolute address cannot be used in the intersection since the value might be only defined in one of the predecessors. + c.recordKnownSafeBound(smallestID, minBound, ssa.ValueInvalid) + } + } + } +} + +func (c *Compiler) getKnownSafeBoundsAtTheEndOfBlocks(id ssa.BasicBlockID) knownSafeBoundsAtTheEndOfBlock { + if int(id) >= len(c.knownSafeBoundsAtTheEndOfBlocks) { + return knownSafeBoundsAtTheEndOfBlockNil + } + return c.knownSafeBoundsAtTheEndOfBlocks[id] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/lower.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/lower.go new file mode 100644 index 00000000..e73debbd --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/lower.go @@ -0,0 +1,4261 @@ +package frontend + +import ( + "encoding/binary" + "fmt" + "math" + "runtime" + "strings" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +type ( + // loweringState is used to keep the state of lowering. + loweringState struct { + // values holds the values on the Wasm stack. + values []ssa.Value + controlFrames []controlFrame + unreachable bool + unreachableDepth int + tmpForBrTable []uint32 + pc int + } + controlFrame struct { + kind controlFrameKind + // originalStackLen holds the number of values on the Wasm stack + // when start executing this control frame minus params for the block. + originalStackLenWithoutParam int + // blk is the loop header if this is loop, and is the else-block if this is an if frame. + blk, + // followingBlock is the basic block we enter if we reach "end" of block. + followingBlock ssa.BasicBlock + blockType *wasm.FunctionType + // clonedArgs hold the arguments to Else block. + clonedArgs ssa.Values + } + + controlFrameKind byte +) + +// String implements fmt.Stringer for debugging. +func (l *loweringState) String() string { + var str []string + for _, v := range l.values { + str = append(str, fmt.Sprintf("v%v", v.ID())) + } + var frames []string + for i := range l.controlFrames { + frames = append(frames, l.controlFrames[i].kind.String()) + } + return fmt.Sprintf("\n\tunreachable=%v(depth=%d)\n\tstack: %s\n\tcontrol frames: %s", + l.unreachable, l.unreachableDepth, + strings.Join(str, ", "), + strings.Join(frames, ", "), + ) +} + +const ( + controlFrameKindFunction = iota + 1 + controlFrameKindLoop + controlFrameKindIfWithElse + controlFrameKindIfWithoutElse + controlFrameKindBlock +) + +// String implements fmt.Stringer for debugging. +func (k controlFrameKind) String() string { + switch k { + case controlFrameKindFunction: + return "function" + case controlFrameKindLoop: + return "loop" + case controlFrameKindIfWithElse: + return "if_with_else" + case controlFrameKindIfWithoutElse: + return "if_without_else" + case controlFrameKindBlock: + return "block" + default: + panic(k) + } +} + +// isLoop returns true if this is a loop frame. +func (ctrl *controlFrame) isLoop() bool { + return ctrl.kind == controlFrameKindLoop +} + +// reset resets the state of loweringState for reuse. +func (l *loweringState) reset() { + l.values = l.values[:0] + l.controlFrames = l.controlFrames[:0] + l.pc = 0 + l.unreachable = false + l.unreachableDepth = 0 +} + +func (l *loweringState) peek() (ret ssa.Value) { + tail := len(l.values) - 1 + return l.values[tail] +} + +func (l *loweringState) pop() (ret ssa.Value) { + tail := len(l.values) - 1 + ret = l.values[tail] + l.values = l.values[:tail] + return +} + +func (l *loweringState) push(ret ssa.Value) { + l.values = append(l.values, ret) +} + +func (c *Compiler) nPeekDup(n int) ssa.Values { + if n == 0 { + return ssa.ValuesNil + } + + l := c.state() + tail := len(l.values) + + args := c.allocateVarLengthValues(n) + args = args.Append(c.ssaBuilder.VarLengthPool(), l.values[tail-n:tail]...) + return args +} + +func (l *loweringState) ctrlPop() (ret controlFrame) { + tail := len(l.controlFrames) - 1 + ret = l.controlFrames[tail] + l.controlFrames = l.controlFrames[:tail] + return +} + +func (l *loweringState) ctrlPush(ret controlFrame) { + l.controlFrames = append(l.controlFrames, ret) +} + +func (l *loweringState) ctrlPeekAt(n int) (ret *controlFrame) { + tail := len(l.controlFrames) - 1 + return &l.controlFrames[tail-n] +} + +// lowerBody lowers the body of the Wasm function to the SSA form. +func (c *Compiler) lowerBody(entryBlk ssa.BasicBlock) { + c.ssaBuilder.Seal(entryBlk) + + if c.needListener { + c.callListenerBefore() + } + + // Pushes the empty control frame which corresponds to the function return. + c.loweringState.ctrlPush(controlFrame{ + kind: controlFrameKindFunction, + blockType: c.wasmFunctionTyp, + followingBlock: c.ssaBuilder.ReturnBlock(), + }) + + for c.loweringState.pc < len(c.wasmFunctionBody) { + blkBeforeLowering := c.ssaBuilder.CurrentBlock() + c.lowerCurrentOpcode() + blkAfterLowering := c.ssaBuilder.CurrentBlock() + if blkBeforeLowering != blkAfterLowering { + // In Wasm, once a block exits, that means we've done compiling the block. + // Therefore, we finalize the known bounds at the end of the block for the exiting block. + c.finalizeKnownSafeBoundsAtTheEndOfBlock(blkBeforeLowering.ID()) + // After that, we initialize the known bounds for the new compilation target block. + c.initializeCurrentBlockKnownBounds() + } + } +} + +func (c *Compiler) state() *loweringState { + return &c.loweringState +} + +func (c *Compiler) lowerCurrentOpcode() { + op := c.wasmFunctionBody[c.loweringState.pc] + + if c.needSourceOffsetInfo { + c.ssaBuilder.SetCurrentSourceOffset( + ssa.SourceOffset(c.loweringState.pc) + ssa.SourceOffset(c.wasmFunctionBodyOffsetInCodeSection), + ) + } + + builder := c.ssaBuilder + state := c.state() + switch op { + case wasm.OpcodeI32Const: + c := c.readI32s() + if state.unreachable { + break + } + + iconst := builder.AllocateInstruction().AsIconst32(uint32(c)).Insert(builder) + value := iconst.Return() + state.push(value) + case wasm.OpcodeI64Const: + c := c.readI64s() + if state.unreachable { + break + } + iconst := builder.AllocateInstruction().AsIconst64(uint64(c)).Insert(builder) + value := iconst.Return() + state.push(value) + case wasm.OpcodeF32Const: + f32 := c.readF32() + if state.unreachable { + break + } + f32const := builder.AllocateInstruction(). + AsF32const(f32). + Insert(builder). + Return() + state.push(f32const) + case wasm.OpcodeF64Const: + f64 := c.readF64() + if state.unreachable { + break + } + f64const := builder.AllocateInstruction(). + AsF64const(f64). + Insert(builder). + Return() + state.push(f64const) + case wasm.OpcodeI32Add, wasm.OpcodeI64Add: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + iadd := builder.AllocateInstruction() + iadd.AsIadd(x, y) + builder.InsertInstruction(iadd) + value := iadd.Return() + state.push(value) + case wasm.OpcodeI32Sub, wasm.OpcodeI64Sub: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsIsub(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeF32Add, wasm.OpcodeF64Add: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + iadd := builder.AllocateInstruction() + iadd.AsFadd(x, y) + builder.InsertInstruction(iadd) + value := iadd.Return() + state.push(value) + case wasm.OpcodeI32Mul, wasm.OpcodeI64Mul: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + imul := builder.AllocateInstruction() + imul.AsImul(x, y) + builder.InsertInstruction(imul) + value := imul.Return() + state.push(value) + case wasm.OpcodeF32Sub, wasm.OpcodeF64Sub: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsFsub(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeF32Mul, wasm.OpcodeF64Mul: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsFmul(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeF32Div, wasm.OpcodeF64Div: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsFdiv(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeF32Max, wasm.OpcodeF64Max: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsFmax(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeF32Min, wasm.OpcodeF64Min: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + isub := builder.AllocateInstruction() + isub.AsFmin(x, y) + builder.InsertInstruction(isub) + value := isub.Return() + state.push(value) + case wasm.OpcodeI64Extend8S: + if state.unreachable { + break + } + c.insertIntegerExtend(true, 8, 64) + case wasm.OpcodeI64Extend16S: + if state.unreachable { + break + } + c.insertIntegerExtend(true, 16, 64) + case wasm.OpcodeI64Extend32S, wasm.OpcodeI64ExtendI32S: + if state.unreachable { + break + } + c.insertIntegerExtend(true, 32, 64) + case wasm.OpcodeI64ExtendI32U: + if state.unreachable { + break + } + c.insertIntegerExtend(false, 32, 64) + case wasm.OpcodeI32Extend8S: + if state.unreachable { + break + } + c.insertIntegerExtend(true, 8, 32) + case wasm.OpcodeI32Extend16S: + if state.unreachable { + break + } + c.insertIntegerExtend(true, 16, 32) + case wasm.OpcodeI32Eqz, wasm.OpcodeI64Eqz: + if state.unreachable { + break + } + x := state.pop() + zero := builder.AllocateInstruction() + if op == wasm.OpcodeI32Eqz { + zero.AsIconst32(0) + } else { + zero.AsIconst64(0) + } + builder.InsertInstruction(zero) + icmp := builder.AllocateInstruction(). + AsIcmp(x, zero.Return(), ssa.IntegerCmpCondEqual). + Insert(builder). + Return() + state.push(icmp) + case wasm.OpcodeI32Eq, wasm.OpcodeI64Eq: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondEqual) + case wasm.OpcodeI32Ne, wasm.OpcodeI64Ne: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondNotEqual) + case wasm.OpcodeI32LtS, wasm.OpcodeI64LtS: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondSignedLessThan) + case wasm.OpcodeI32LtU, wasm.OpcodeI64LtU: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondUnsignedLessThan) + case wasm.OpcodeI32GtS, wasm.OpcodeI64GtS: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondSignedGreaterThan) + case wasm.OpcodeI32GtU, wasm.OpcodeI64GtU: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondUnsignedGreaterThan) + case wasm.OpcodeI32LeS, wasm.OpcodeI64LeS: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondSignedLessThanOrEqual) + case wasm.OpcodeI32LeU, wasm.OpcodeI64LeU: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondUnsignedLessThanOrEqual) + case wasm.OpcodeI32GeS, wasm.OpcodeI64GeS: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondSignedGreaterThanOrEqual) + case wasm.OpcodeI32GeU, wasm.OpcodeI64GeU: + if state.unreachable { + break + } + c.insertIcmp(ssa.IntegerCmpCondUnsignedGreaterThanOrEqual) + + case wasm.OpcodeF32Eq, wasm.OpcodeF64Eq: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondEqual) + case wasm.OpcodeF32Ne, wasm.OpcodeF64Ne: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondNotEqual) + case wasm.OpcodeF32Lt, wasm.OpcodeF64Lt: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondLessThan) + case wasm.OpcodeF32Gt, wasm.OpcodeF64Gt: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondGreaterThan) + case wasm.OpcodeF32Le, wasm.OpcodeF64Le: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondLessThanOrEqual) + case wasm.OpcodeF32Ge, wasm.OpcodeF64Ge: + if state.unreachable { + break + } + c.insertFcmp(ssa.FloatCmpCondGreaterThanOrEqual) + case wasm.OpcodeF32Neg, wasm.OpcodeF64Neg: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsFneg(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Sqrt, wasm.OpcodeF64Sqrt: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsSqrt(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Abs, wasm.OpcodeF64Abs: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsFabs(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Copysign, wasm.OpcodeF64Copysign: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + v := builder.AllocateInstruction().AsFcopysign(x, y).Insert(builder).Return() + state.push(v) + + case wasm.OpcodeF32Ceil, wasm.OpcodeF64Ceil: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsCeil(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Floor, wasm.OpcodeF64Floor: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsFloor(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Trunc, wasm.OpcodeF64Trunc: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsTrunc(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeF32Nearest, wasm.OpcodeF64Nearest: + if state.unreachable { + break + } + x := state.pop() + v := builder.AllocateInstruction().AsNearest(x).Insert(builder).Return() + state.push(v) + case wasm.OpcodeI64TruncF64S, wasm.OpcodeI64TruncF32S, + wasm.OpcodeI32TruncF64S, wasm.OpcodeI32TruncF32S, + wasm.OpcodeI64TruncF64U, wasm.OpcodeI64TruncF32U, + wasm.OpcodeI32TruncF64U, wasm.OpcodeI32TruncF32U: + if state.unreachable { + break + } + ret := builder.AllocateInstruction().AsFcvtToInt( + state.pop(), + c.execCtxPtrValue, + op == wasm.OpcodeI64TruncF64S || op == wasm.OpcodeI64TruncF32S || op == wasm.OpcodeI32TruncF32S || op == wasm.OpcodeI32TruncF64S, + op == wasm.OpcodeI64TruncF64S || op == wasm.OpcodeI64TruncF32S || op == wasm.OpcodeI64TruncF64U || op == wasm.OpcodeI64TruncF32U, + false, + ).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeMiscPrefix: + state.pc++ + // A misc opcode is encoded as an unsigned variable 32-bit integer. + miscOpUint, num, err := leb128.LoadUint32(c.wasmFunctionBody[state.pc:]) + if err != nil { + // In normal conditions this should never happen because the function has passed validation. + panic(fmt.Sprintf("failed to read misc opcode: %v", err)) + } + state.pc += int(num - 1) + miscOp := wasm.OpcodeMisc(miscOpUint) + switch miscOp { + case wasm.OpcodeMiscI64TruncSatF64S, wasm.OpcodeMiscI64TruncSatF32S, + wasm.OpcodeMiscI32TruncSatF64S, wasm.OpcodeMiscI32TruncSatF32S, + wasm.OpcodeMiscI64TruncSatF64U, wasm.OpcodeMiscI64TruncSatF32U, + wasm.OpcodeMiscI32TruncSatF64U, wasm.OpcodeMiscI32TruncSatF32U: + if state.unreachable { + break + } + ret := builder.AllocateInstruction().AsFcvtToInt( + state.pop(), + c.execCtxPtrValue, + miscOp == wasm.OpcodeMiscI64TruncSatF64S || miscOp == wasm.OpcodeMiscI64TruncSatF32S || miscOp == wasm.OpcodeMiscI32TruncSatF32S || miscOp == wasm.OpcodeMiscI32TruncSatF64S, + miscOp == wasm.OpcodeMiscI64TruncSatF64S || miscOp == wasm.OpcodeMiscI64TruncSatF32S || miscOp == wasm.OpcodeMiscI64TruncSatF64U || miscOp == wasm.OpcodeMiscI64TruncSatF32U, + true, + ).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeMiscTableSize: + tableIndex := c.readI32u() + if state.unreachable { + break + } + + // Load the table. + loadTableInstancePtr := builder.AllocateInstruction() + loadTableInstancePtr.AsLoad(c.moduleCtxPtrValue, c.offset.TableOffset(int(tableIndex)).U32(), ssa.TypeI64) + builder.InsertInstruction(loadTableInstancePtr) + tableInstancePtr := loadTableInstancePtr.Return() + + // Load the table's length. + loadTableLen := builder.AllocateInstruction(). + AsLoad(tableInstancePtr, tableInstanceLenOffset, ssa.TypeI32). + Insert(builder) + state.push(loadTableLen.Return()) + + case wasm.OpcodeMiscTableGrow: + tableIndex := c.readI32u() + if state.unreachable { + break + } + + c.storeCallerModuleContext() + + tableIndexVal := builder.AllocateInstruction().AsIconst32(tableIndex).Insert(builder).Return() + + num := state.pop() + r := state.pop() + + tableGrowPtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetTableGrowTrampolineAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + args := c.allocateVarLengthValues(4, c.execCtxPtrValue, tableIndexVal, num, r) + callGrowRet := builder. + AllocateInstruction(). + AsCallIndirect(tableGrowPtr, &c.tableGrowSig, args). + Insert(builder).Return() + state.push(callGrowRet) + + case wasm.OpcodeMiscTableCopy: + dstTableIndex := c.readI32u() + srcTableIndex := c.readI32u() + if state.unreachable { + break + } + + copySize := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + srcOffset := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + dstOffset := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + + // Out of bounds check. + dstTableInstancePtr := c.boundsCheckInTable(dstTableIndex, dstOffset, copySize) + srcTableInstancePtr := c.boundsCheckInTable(srcTableIndex, srcOffset, copySize) + + dstTableBaseAddr := c.loadTableBaseAddr(dstTableInstancePtr) + srcTableBaseAddr := c.loadTableBaseAddr(srcTableInstancePtr) + + three := builder.AllocateInstruction().AsIconst64(3).Insert(builder).Return() + + dstOffsetInBytes := builder.AllocateInstruction().AsIshl(dstOffset, three).Insert(builder).Return() + dstAddr := builder.AllocateInstruction().AsIadd(dstTableBaseAddr, dstOffsetInBytes).Insert(builder).Return() + srcOffsetInBytes := builder.AllocateInstruction().AsIshl(srcOffset, three).Insert(builder).Return() + srcAddr := builder.AllocateInstruction().AsIadd(srcTableBaseAddr, srcOffsetInBytes).Insert(builder).Return() + + copySizeInBytes := builder.AllocateInstruction().AsIshl(copySize, three).Insert(builder).Return() + c.callMemmove(dstAddr, srcAddr, copySizeInBytes) + + case wasm.OpcodeMiscMemoryCopy: + state.pc += 2 // +2 to skip two memory indexes which are fixed to zero. + if state.unreachable { + break + } + + copySize := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + srcOffset := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + dstOffset := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + + // Out of bounds check. + memLen := c.getMemoryLenValue(false) + c.boundsCheckInMemory(memLen, dstOffset, copySize) + c.boundsCheckInMemory(memLen, srcOffset, copySize) + + memBase := c.getMemoryBaseValue(false) + dstAddr := builder.AllocateInstruction().AsIadd(memBase, dstOffset).Insert(builder).Return() + srcAddr := builder.AllocateInstruction().AsIadd(memBase, srcOffset).Insert(builder).Return() + + c.callMemmove(dstAddr, srcAddr, copySize) + + case wasm.OpcodeMiscTableFill: + tableIndex := c.readI32u() + if state.unreachable { + break + } + fillSize := state.pop() + value := state.pop() + offset := state.pop() + + fillSizeExt := builder. + AllocateInstruction().AsUExtend(fillSize, 32, 64).Insert(builder).Return() + offsetExt := builder. + AllocateInstruction().AsUExtend(offset, 32, 64).Insert(builder).Return() + tableInstancePtr := c.boundsCheckInTable(tableIndex, offsetExt, fillSizeExt) + + three := builder.AllocateInstruction().AsIconst64(3).Insert(builder).Return() + offsetInBytes := builder.AllocateInstruction().AsIshl(offsetExt, three).Insert(builder).Return() + fillSizeInBytes := builder.AllocateInstruction().AsIshl(fillSizeExt, three).Insert(builder).Return() + + // Calculate the base address of the table. + tableBaseAddr := c.loadTableBaseAddr(tableInstancePtr) + addr := builder.AllocateInstruction().AsIadd(tableBaseAddr, offsetInBytes).Insert(builder).Return() + + // Prepare the loop and following block. + beforeLoop := builder.AllocateBasicBlock() + loopBlk := builder.AllocateBasicBlock() + loopVar := loopBlk.AddParam(builder, ssa.TypeI64) + followingBlk := builder.AllocateBasicBlock() + + // Uses the copy trick for faster filling buffer like memory.fill, but in this case we copy 8 bytes at a time. + // buf := memoryInst.Buffer[offset : offset+fillSize] + // buf[0:8] = value + // for i := 8; i < fillSize; i *= 2 { Begin with 8 bytes. + // copy(buf[i:], buf[:i]) + // } + + // Insert the jump to the beforeLoop block; If the fillSize is zero, then jump to the following block to skip entire logics. + zero := builder.AllocateInstruction().AsIconst64(0).Insert(builder).Return() + ifFillSizeZero := builder.AllocateInstruction().AsIcmp(fillSizeExt, zero, ssa.IntegerCmpCondEqual). + Insert(builder).Return() + builder.AllocateInstruction().AsBrnz(ifFillSizeZero, ssa.ValuesNil, followingBlk).Insert(builder) + c.insertJumpToBlock(ssa.ValuesNil, beforeLoop) + + // buf[0:8] = value + builder.SetCurrentBlock(beforeLoop) + builder.AllocateInstruction().AsStore(ssa.OpcodeStore, value, addr, 0).Insert(builder) + initValue := builder.AllocateInstruction().AsIconst64(8).Insert(builder).Return() + c.insertJumpToBlock(c.allocateVarLengthValues(1, initValue), loopBlk) + + builder.SetCurrentBlock(loopBlk) + dstAddr := builder.AllocateInstruction().AsIadd(addr, loopVar).Insert(builder).Return() + + // If loopVar*2 > fillSizeInBytes, then count must be fillSizeInBytes-loopVar. + var count ssa.Value + { + loopVarDoubled := builder.AllocateInstruction().AsIadd(loopVar, loopVar).Insert(builder).Return() + loopVarDoubledLargerThanFillSize := builder. + AllocateInstruction().AsIcmp(loopVarDoubled, fillSizeInBytes, ssa.IntegerCmpCondUnsignedGreaterThanOrEqual). + Insert(builder).Return() + diff := builder.AllocateInstruction().AsIsub(fillSizeInBytes, loopVar).Insert(builder).Return() + count = builder.AllocateInstruction().AsSelect(loopVarDoubledLargerThanFillSize, diff, loopVar).Insert(builder).Return() + } + + c.callMemmove(dstAddr, addr, count) + + shiftAmount := builder.AllocateInstruction().AsIconst64(1).Insert(builder).Return() + newLoopVar := builder.AllocateInstruction().AsIshl(loopVar, shiftAmount).Insert(builder).Return() + loopVarLessThanFillSize := builder.AllocateInstruction(). + AsIcmp(newLoopVar, fillSizeInBytes, ssa.IntegerCmpCondUnsignedLessThan).Insert(builder).Return() + + builder.AllocateInstruction(). + AsBrnz(loopVarLessThanFillSize, c.allocateVarLengthValues(1, newLoopVar), loopBlk). + Insert(builder) + + c.insertJumpToBlock(ssa.ValuesNil, followingBlk) + builder.SetCurrentBlock(followingBlk) + + builder.Seal(beforeLoop) + builder.Seal(loopBlk) + builder.Seal(followingBlk) + + case wasm.OpcodeMiscMemoryFill: + state.pc++ // Skip the memory index which is fixed to zero. + if state.unreachable { + break + } + + fillSize := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + value := state.pop() + offset := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + + // Out of bounds check. + c.boundsCheckInMemory(c.getMemoryLenValue(false), offset, fillSize) + + // Calculate the base address: + addr := builder.AllocateInstruction().AsIadd(c.getMemoryBaseValue(false), offset).Insert(builder).Return() + + // Uses the copy trick for faster filling buffer: https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d + // buf := memoryInst.Buffer[offset : offset+fillSize] + // buf[0] = value + // for i := 1; i < fillSize; i *= 2 { + // copy(buf[i:], buf[:i]) + // } + + // Prepare the loop and following block. + beforeLoop := builder.AllocateBasicBlock() + loopBlk := builder.AllocateBasicBlock() + loopVar := loopBlk.AddParam(builder, ssa.TypeI64) + followingBlk := builder.AllocateBasicBlock() + + // Insert the jump to the beforeLoop block; If the fillSize is zero, then jump to the following block to skip entire logics. + zero := builder.AllocateInstruction().AsIconst64(0).Insert(builder).Return() + ifFillSizeZero := builder.AllocateInstruction().AsIcmp(fillSize, zero, ssa.IntegerCmpCondEqual). + Insert(builder).Return() + builder.AllocateInstruction().AsBrnz(ifFillSizeZero, ssa.ValuesNil, followingBlk).Insert(builder) + c.insertJumpToBlock(ssa.ValuesNil, beforeLoop) + + // buf[0] = value + builder.SetCurrentBlock(beforeLoop) + builder.AllocateInstruction().AsStore(ssa.OpcodeIstore8, value, addr, 0).Insert(builder) + initValue := builder.AllocateInstruction().AsIconst64(1).Insert(builder).Return() + c.insertJumpToBlock(c.allocateVarLengthValues(1, initValue), loopBlk) + + builder.SetCurrentBlock(loopBlk) + dstAddr := builder.AllocateInstruction().AsIadd(addr, loopVar).Insert(builder).Return() + + // If loopVar*2 > fillSizeExt, then count must be fillSizeExt-loopVar. + var count ssa.Value + { + loopVarDoubled := builder.AllocateInstruction().AsIadd(loopVar, loopVar).Insert(builder).Return() + loopVarDoubledLargerThanFillSize := builder. + AllocateInstruction().AsIcmp(loopVarDoubled, fillSize, ssa.IntegerCmpCondUnsignedGreaterThanOrEqual). + Insert(builder).Return() + diff := builder.AllocateInstruction().AsIsub(fillSize, loopVar).Insert(builder).Return() + count = builder.AllocateInstruction().AsSelect(loopVarDoubledLargerThanFillSize, diff, loopVar).Insert(builder).Return() + } + + c.callMemmove(dstAddr, addr, count) + + shiftAmount := builder.AllocateInstruction().AsIconst64(1).Insert(builder).Return() + newLoopVar := builder.AllocateInstruction().AsIshl(loopVar, shiftAmount).Insert(builder).Return() + loopVarLessThanFillSize := builder.AllocateInstruction(). + AsIcmp(newLoopVar, fillSize, ssa.IntegerCmpCondUnsignedLessThan).Insert(builder).Return() + + builder.AllocateInstruction(). + AsBrnz(loopVarLessThanFillSize, c.allocateVarLengthValues(1, newLoopVar), loopBlk). + Insert(builder) + + c.insertJumpToBlock(ssa.ValuesNil, followingBlk) + builder.SetCurrentBlock(followingBlk) + + builder.Seal(beforeLoop) + builder.Seal(loopBlk) + builder.Seal(followingBlk) + + case wasm.OpcodeMiscMemoryInit: + index := c.readI32u() + state.pc++ // Skip the memory index which is fixed to zero. + if state.unreachable { + break + } + + copySize := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + offsetInDataInstance := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + offsetInMemory := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + + dataInstPtr := c.dataOrElementInstanceAddr(index, c.offset.DataInstances1stElement) + + // Bounds check. + c.boundsCheckInMemory(c.getMemoryLenValue(false), offsetInMemory, copySize) + c.boundsCheckInDataOrElementInstance(dataInstPtr, offsetInDataInstance, copySize, wazevoapi.ExitCodeMemoryOutOfBounds) + + dataInstBaseAddr := builder.AllocateInstruction().AsLoad(dataInstPtr, 0, ssa.TypeI64).Insert(builder).Return() + srcAddr := builder.AllocateInstruction().AsIadd(dataInstBaseAddr, offsetInDataInstance).Insert(builder).Return() + + memBase := c.getMemoryBaseValue(false) + dstAddr := builder.AllocateInstruction().AsIadd(memBase, offsetInMemory).Insert(builder).Return() + + c.callMemmove(dstAddr, srcAddr, copySize) + + case wasm.OpcodeMiscTableInit: + elemIndex := c.readI32u() + tableIndex := c.readI32u() + if state.unreachable { + break + } + + copySize := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + offsetInElementInstance := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + offsetInTable := builder. + AllocateInstruction().AsUExtend(state.pop(), 32, 64).Insert(builder).Return() + + elemInstPtr := c.dataOrElementInstanceAddr(elemIndex, c.offset.ElementInstances1stElement) + + // Bounds check. + tableInstancePtr := c.boundsCheckInTable(tableIndex, offsetInTable, copySize) + c.boundsCheckInDataOrElementInstance(elemInstPtr, offsetInElementInstance, copySize, wazevoapi.ExitCodeTableOutOfBounds) + + three := builder.AllocateInstruction().AsIconst64(3).Insert(builder).Return() + // Calculates the destination address in the table. + tableOffsetInBytes := builder.AllocateInstruction().AsIshl(offsetInTable, three).Insert(builder).Return() + tableBaseAddr := c.loadTableBaseAddr(tableInstancePtr) + dstAddr := builder.AllocateInstruction().AsIadd(tableBaseAddr, tableOffsetInBytes).Insert(builder).Return() + + // Calculates the source address in the element instance. + srcOffsetInBytes := builder.AllocateInstruction().AsIshl(offsetInElementInstance, three).Insert(builder).Return() + elemInstBaseAddr := builder.AllocateInstruction().AsLoad(elemInstPtr, 0, ssa.TypeI64).Insert(builder).Return() + srcAddr := builder.AllocateInstruction().AsIadd(elemInstBaseAddr, srcOffsetInBytes).Insert(builder).Return() + + copySizeInBytes := builder.AllocateInstruction().AsIshl(copySize, three).Insert(builder).Return() + c.callMemmove(dstAddr, srcAddr, copySizeInBytes) + + case wasm.OpcodeMiscElemDrop: + index := c.readI32u() + if state.unreachable { + break + } + + c.dropDataOrElementInstance(index, c.offset.ElementInstances1stElement) + + case wasm.OpcodeMiscDataDrop: + index := c.readI32u() + if state.unreachable { + break + } + c.dropDataOrElementInstance(index, c.offset.DataInstances1stElement) + + default: + panic("Unknown MiscOp " + wasm.MiscInstructionName(miscOp)) + } + + case wasm.OpcodeI32ReinterpretF32: + if state.unreachable { + break + } + reinterpret := builder.AllocateInstruction(). + AsBitcast(state.pop(), ssa.TypeI32). + Insert(builder).Return() + state.push(reinterpret) + + case wasm.OpcodeI64ReinterpretF64: + if state.unreachable { + break + } + reinterpret := builder.AllocateInstruction(). + AsBitcast(state.pop(), ssa.TypeI64). + Insert(builder).Return() + state.push(reinterpret) + + case wasm.OpcodeF32ReinterpretI32: + if state.unreachable { + break + } + reinterpret := builder.AllocateInstruction(). + AsBitcast(state.pop(), ssa.TypeF32). + Insert(builder).Return() + state.push(reinterpret) + + case wasm.OpcodeF64ReinterpretI64: + if state.unreachable { + break + } + reinterpret := builder.AllocateInstruction(). + AsBitcast(state.pop(), ssa.TypeF64). + Insert(builder).Return() + state.push(reinterpret) + + case wasm.OpcodeI32DivS, wasm.OpcodeI64DivS: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + result := builder.AllocateInstruction().AsSDiv(x, y, c.execCtxPtrValue).Insert(builder).Return() + state.push(result) + + case wasm.OpcodeI32DivU, wasm.OpcodeI64DivU: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + result := builder.AllocateInstruction().AsUDiv(x, y, c.execCtxPtrValue).Insert(builder).Return() + state.push(result) + + case wasm.OpcodeI32RemS, wasm.OpcodeI64RemS: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + result := builder.AllocateInstruction().AsSRem(x, y, c.execCtxPtrValue).Insert(builder).Return() + state.push(result) + + case wasm.OpcodeI32RemU, wasm.OpcodeI64RemU: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + result := builder.AllocateInstruction().AsURem(x, y, c.execCtxPtrValue).Insert(builder).Return() + state.push(result) + + case wasm.OpcodeI32And, wasm.OpcodeI64And: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + and := builder.AllocateInstruction() + and.AsBand(x, y) + builder.InsertInstruction(and) + value := and.Return() + state.push(value) + case wasm.OpcodeI32Or, wasm.OpcodeI64Or: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + or := builder.AllocateInstruction() + or.AsBor(x, y) + builder.InsertInstruction(or) + value := or.Return() + state.push(value) + case wasm.OpcodeI32Xor, wasm.OpcodeI64Xor: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + xor := builder.AllocateInstruction() + xor.AsBxor(x, y) + builder.InsertInstruction(xor) + value := xor.Return() + state.push(value) + case wasm.OpcodeI32Shl, wasm.OpcodeI64Shl: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + ishl := builder.AllocateInstruction() + ishl.AsIshl(x, y) + builder.InsertInstruction(ishl) + value := ishl.Return() + state.push(value) + case wasm.OpcodeI32ShrU, wasm.OpcodeI64ShrU: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + ishl := builder.AllocateInstruction() + ishl.AsUshr(x, y) + builder.InsertInstruction(ishl) + value := ishl.Return() + state.push(value) + case wasm.OpcodeI32ShrS, wasm.OpcodeI64ShrS: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + ishl := builder.AllocateInstruction() + ishl.AsSshr(x, y) + builder.InsertInstruction(ishl) + value := ishl.Return() + state.push(value) + case wasm.OpcodeI32Rotl, wasm.OpcodeI64Rotl: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + rotl := builder.AllocateInstruction() + rotl.AsRotl(x, y) + builder.InsertInstruction(rotl) + value := rotl.Return() + state.push(value) + case wasm.OpcodeI32Rotr, wasm.OpcodeI64Rotr: + if state.unreachable { + break + } + y, x := state.pop(), state.pop() + rotr := builder.AllocateInstruction() + rotr.AsRotr(x, y) + builder.InsertInstruction(rotr) + value := rotr.Return() + state.push(value) + case wasm.OpcodeI32Clz, wasm.OpcodeI64Clz: + if state.unreachable { + break + } + x := state.pop() + clz := builder.AllocateInstruction() + clz.AsClz(x) + builder.InsertInstruction(clz) + value := clz.Return() + state.push(value) + case wasm.OpcodeI32Ctz, wasm.OpcodeI64Ctz: + if state.unreachable { + break + } + x := state.pop() + ctz := builder.AllocateInstruction() + ctz.AsCtz(x) + builder.InsertInstruction(ctz) + value := ctz.Return() + state.push(value) + case wasm.OpcodeI32Popcnt, wasm.OpcodeI64Popcnt: + if state.unreachable { + break + } + x := state.pop() + popcnt := builder.AllocateInstruction() + popcnt.AsPopcnt(x) + builder.InsertInstruction(popcnt) + value := popcnt.Return() + state.push(value) + + case wasm.OpcodeI32WrapI64: + if state.unreachable { + break + } + x := state.pop() + wrap := builder.AllocateInstruction().AsIreduce(x, ssa.TypeI32).Insert(builder).Return() + state.push(wrap) + case wasm.OpcodeGlobalGet: + index := c.readI32u() + if state.unreachable { + break + } + v := c.getWasmGlobalValue(index, false) + state.push(v) + case wasm.OpcodeGlobalSet: + index := c.readI32u() + if state.unreachable { + break + } + v := state.pop() + c.setWasmGlobalValue(index, v) + case wasm.OpcodeLocalGet: + index := c.readI32u() + if state.unreachable { + break + } + variable := c.localVariable(index) + state.push(builder.MustFindValue(variable)) + + case wasm.OpcodeLocalSet: + index := c.readI32u() + if state.unreachable { + break + } + variable := c.localVariable(index) + newValue := state.pop() + builder.DefineVariableInCurrentBB(variable, newValue) + + case wasm.OpcodeLocalTee: + index := c.readI32u() + if state.unreachable { + break + } + variable := c.localVariable(index) + newValue := state.peek() + builder.DefineVariableInCurrentBB(variable, newValue) + + case wasm.OpcodeSelect, wasm.OpcodeTypedSelect: + if op == wasm.OpcodeTypedSelect { + state.pc += 2 // ignores the type which is only needed during validation. + } + + if state.unreachable { + break + } + + cond := state.pop() + v2 := state.pop() + v1 := state.pop() + + sl := builder.AllocateInstruction(). + AsSelect(cond, v1, v2). + Insert(builder). + Return() + state.push(sl) + + case wasm.OpcodeMemorySize: + state.pc++ // skips the memory index. + if state.unreachable { + break + } + + var memSizeInBytes ssa.Value + if c.offset.LocalMemoryBegin < 0 { + memInstPtr := builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, c.offset.ImportedMemoryBegin.U32(), ssa.TypeI64). + Insert(builder). + Return() + + memSizeInBytes = builder.AllocateInstruction(). + AsLoad(memInstPtr, memoryInstanceBufSizeOffset, ssa.TypeI32). + Insert(builder). + Return() + } else { + memSizeInBytes = builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, c.offset.LocalMemoryLen().U32(), ssa.TypeI32). + Insert(builder). + Return() + } + + amount := builder.AllocateInstruction() + amount.AsIconst32(uint32(wasm.MemoryPageSizeInBits)) + builder.InsertInstruction(amount) + memSize := builder.AllocateInstruction(). + AsUshr(memSizeInBytes, amount.Return()). + Insert(builder). + Return() + state.push(memSize) + + case wasm.OpcodeMemoryGrow: + state.pc++ // skips the memory index. + if state.unreachable { + break + } + + c.storeCallerModuleContext() + + pages := state.pop() + memoryGrowPtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetMemoryGrowTrampolineAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + args := c.allocateVarLengthValues(1, c.execCtxPtrValue, pages) + callGrowRet := builder. + AllocateInstruction(). + AsCallIndirect(memoryGrowPtr, &c.memoryGrowSig, args). + Insert(builder).Return() + state.push(callGrowRet) + + // After the memory grow, reload the cached memory base and len. + c.reloadMemoryBaseLen() + + case wasm.OpcodeI32Store, + wasm.OpcodeI64Store, + wasm.OpcodeF32Store, + wasm.OpcodeF64Store, + wasm.OpcodeI32Store8, + wasm.OpcodeI32Store16, + wasm.OpcodeI64Store8, + wasm.OpcodeI64Store16, + wasm.OpcodeI64Store32: + + _, offset := c.readMemArg() + if state.unreachable { + break + } + var opSize uint64 + var opcode ssa.Opcode + switch op { + case wasm.OpcodeI32Store, wasm.OpcodeF32Store: + opcode = ssa.OpcodeStore + opSize = 4 + case wasm.OpcodeI64Store, wasm.OpcodeF64Store: + opcode = ssa.OpcodeStore + opSize = 8 + case wasm.OpcodeI32Store8, wasm.OpcodeI64Store8: + opcode = ssa.OpcodeIstore8 + opSize = 1 + case wasm.OpcodeI32Store16, wasm.OpcodeI64Store16: + opcode = ssa.OpcodeIstore16 + opSize = 2 + case wasm.OpcodeI64Store32: + opcode = ssa.OpcodeIstore32 + opSize = 4 + default: + panic("BUG") + } + + value := state.pop() + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), opSize) + builder.AllocateInstruction(). + AsStore(opcode, value, addr, offset). + Insert(builder) + + case wasm.OpcodeI32Load, + wasm.OpcodeI64Load, + wasm.OpcodeF32Load, + wasm.OpcodeF64Load, + wasm.OpcodeI32Load8S, + wasm.OpcodeI32Load8U, + wasm.OpcodeI32Load16S, + wasm.OpcodeI32Load16U, + wasm.OpcodeI64Load8S, + wasm.OpcodeI64Load8U, + wasm.OpcodeI64Load16S, + wasm.OpcodeI64Load16U, + wasm.OpcodeI64Load32S, + wasm.OpcodeI64Load32U: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + var opSize uint64 + switch op { + case wasm.OpcodeI32Load, wasm.OpcodeF32Load: + opSize = 4 + case wasm.OpcodeI64Load, wasm.OpcodeF64Load: + opSize = 8 + case wasm.OpcodeI32Load8S, wasm.OpcodeI32Load8U: + opSize = 1 + case wasm.OpcodeI32Load16S, wasm.OpcodeI32Load16U: + opSize = 2 + case wasm.OpcodeI64Load8S, wasm.OpcodeI64Load8U: + opSize = 1 + case wasm.OpcodeI64Load16S, wasm.OpcodeI64Load16U: + opSize = 2 + case wasm.OpcodeI64Load32S, wasm.OpcodeI64Load32U: + opSize = 4 + default: + panic("BUG") + } + + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), opSize) + load := builder.AllocateInstruction() + switch op { + case wasm.OpcodeI32Load: + load.AsLoad(addr, offset, ssa.TypeI32) + case wasm.OpcodeI64Load: + load.AsLoad(addr, offset, ssa.TypeI64) + case wasm.OpcodeF32Load: + load.AsLoad(addr, offset, ssa.TypeF32) + case wasm.OpcodeF64Load: + load.AsLoad(addr, offset, ssa.TypeF64) + case wasm.OpcodeI32Load8S: + load.AsExtLoad(ssa.OpcodeSload8, addr, offset, false) + case wasm.OpcodeI32Load8U: + load.AsExtLoad(ssa.OpcodeUload8, addr, offset, false) + case wasm.OpcodeI32Load16S: + load.AsExtLoad(ssa.OpcodeSload16, addr, offset, false) + case wasm.OpcodeI32Load16U: + load.AsExtLoad(ssa.OpcodeUload16, addr, offset, false) + case wasm.OpcodeI64Load8S: + load.AsExtLoad(ssa.OpcodeSload8, addr, offset, true) + case wasm.OpcodeI64Load8U: + load.AsExtLoad(ssa.OpcodeUload8, addr, offset, true) + case wasm.OpcodeI64Load16S: + load.AsExtLoad(ssa.OpcodeSload16, addr, offset, true) + case wasm.OpcodeI64Load16U: + load.AsExtLoad(ssa.OpcodeUload16, addr, offset, true) + case wasm.OpcodeI64Load32S: + load.AsExtLoad(ssa.OpcodeSload32, addr, offset, true) + case wasm.OpcodeI64Load32U: + load.AsExtLoad(ssa.OpcodeUload32, addr, offset, true) + default: + panic("BUG") + } + builder.InsertInstruction(load) + state.push(load.Return()) + case wasm.OpcodeBlock: + // Note: we do not need to create a BB for this as that would always have only one predecessor + // which is the current BB, and therefore it's always ok to merge them in any way. + + bt := c.readBlockType() + + if state.unreachable { + state.unreachableDepth++ + break + } + + followingBlk := builder.AllocateBasicBlock() + c.addBlockParamsFromWasmTypes(bt.Results, followingBlk) + + state.ctrlPush(controlFrame{ + kind: controlFrameKindBlock, + originalStackLenWithoutParam: len(state.values) - len(bt.Params), + followingBlock: followingBlk, + blockType: bt, + }) + case wasm.OpcodeLoop: + bt := c.readBlockType() + + if state.unreachable { + state.unreachableDepth++ + break + } + + loopHeader, afterLoopBlock := builder.AllocateBasicBlock(), builder.AllocateBasicBlock() + c.addBlockParamsFromWasmTypes(bt.Params, loopHeader) + c.addBlockParamsFromWasmTypes(bt.Results, afterLoopBlock) + + originalLen := len(state.values) - len(bt.Params) + state.ctrlPush(controlFrame{ + originalStackLenWithoutParam: originalLen, + kind: controlFrameKindLoop, + blk: loopHeader, + followingBlock: afterLoopBlock, + blockType: bt, + }) + + args := c.allocateVarLengthValues(originalLen) + args = args.Append(builder.VarLengthPool(), state.values[originalLen:]...) + + // Insert the jump to the header of loop. + br := builder.AllocateInstruction() + br.AsJump(args, loopHeader) + builder.InsertInstruction(br) + + c.switchTo(originalLen, loopHeader) + + if c.ensureTermination { + checkModuleExitCodePtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + args := c.allocateVarLengthValues(1, c.execCtxPtrValue) + builder.AllocateInstruction(). + AsCallIndirect(checkModuleExitCodePtr, &c.checkModuleExitCodeSig, args). + Insert(builder) + } + case wasm.OpcodeIf: + bt := c.readBlockType() + + if state.unreachable { + state.unreachableDepth++ + break + } + + v := state.pop() + thenBlk, elseBlk, followingBlk := builder.AllocateBasicBlock(), builder.AllocateBasicBlock(), builder.AllocateBasicBlock() + + // We do not make the Wasm-level block parameters as SSA-level block params for if-else blocks + // since they won't be PHI and the definition is unique. + + // On the other hand, the following block after if-else-end will likely have + // multiple definitions (one in Then and another in Else blocks). + c.addBlockParamsFromWasmTypes(bt.Results, followingBlk) + + args := c.allocateVarLengthValues(len(bt.Params)) + args = args.Append(builder.VarLengthPool(), state.values[len(state.values)-len(bt.Params):]...) + + // Insert the conditional jump to the Else block. + brz := builder.AllocateInstruction() + brz.AsBrz(v, ssa.ValuesNil, elseBlk) + builder.InsertInstruction(brz) + + // Then, insert the jump to the Then block. + br := builder.AllocateInstruction() + br.AsJump(ssa.ValuesNil, thenBlk) + builder.InsertInstruction(br) + + state.ctrlPush(controlFrame{ + kind: controlFrameKindIfWithoutElse, + originalStackLenWithoutParam: len(state.values) - len(bt.Params), + blk: elseBlk, + followingBlock: followingBlk, + blockType: bt, + clonedArgs: args, + }) + + builder.SetCurrentBlock(thenBlk) + + // Then and Else (if exists) have only one predecessor. + builder.Seal(thenBlk) + builder.Seal(elseBlk) + case wasm.OpcodeElse: + ifctrl := state.ctrlPeekAt(0) + if unreachable := state.unreachable; unreachable && state.unreachableDepth > 0 { + // If it is currently in unreachable and is a nested if, + // we just remove the entire else block. + break + } + + ifctrl.kind = controlFrameKindIfWithElse + if !state.unreachable { + // If this Then block is currently reachable, we have to insert the branching to the following BB. + followingBlk := ifctrl.followingBlock // == the BB after if-then-else. + args := c.nPeekDup(len(ifctrl.blockType.Results)) + c.insertJumpToBlock(args, followingBlk) + } else { + state.unreachable = false + } + + // Reset the stack so that we can correctly handle the else block. + state.values = state.values[:ifctrl.originalStackLenWithoutParam] + elseBlk := ifctrl.blk + for _, arg := range ifctrl.clonedArgs.View() { + state.push(arg) + } + + builder.SetCurrentBlock(elseBlk) + + case wasm.OpcodeEnd: + if state.unreachableDepth > 0 { + state.unreachableDepth-- + break + } + + ctrl := state.ctrlPop() + followingBlk := ctrl.followingBlock + + unreachable := state.unreachable + if !unreachable { + // Top n-th args will be used as a result of the current control frame. + args := c.nPeekDup(len(ctrl.blockType.Results)) + + // Insert the unconditional branch to the target. + c.insertJumpToBlock(args, followingBlk) + } else { // recover from the unreachable state. + state.unreachable = false + } + + switch ctrl.kind { + case controlFrameKindFunction: + break // This is the very end of function. + case controlFrameKindLoop: + // Loop header block can be reached from any br/br_table contained in the loop, + // so now that we've reached End of it, we can seal it. + builder.Seal(ctrl.blk) + case controlFrameKindIfWithoutElse: + // If this is the end of Then block, we have to emit the empty Else block. + elseBlk := ctrl.blk + builder.SetCurrentBlock(elseBlk) + c.insertJumpToBlock(ctrl.clonedArgs, followingBlk) + } + + builder.Seal(followingBlk) + + // Ready to start translating the following block. + c.switchTo(ctrl.originalStackLenWithoutParam, followingBlk) + + case wasm.OpcodeBr: + labelIndex := c.readI32u() + if state.unreachable { + break + } + + targetBlk, argNum := state.brTargetArgNumFor(labelIndex) + args := c.nPeekDup(argNum) + c.insertJumpToBlock(args, targetBlk) + + state.unreachable = true + + case wasm.OpcodeBrIf: + labelIndex := c.readI32u() + if state.unreachable { + break + } + + v := state.pop() + + targetBlk, argNum := state.brTargetArgNumFor(labelIndex) + args := c.nPeekDup(argNum) + var sealTargetBlk bool + if c.needListener && targetBlk.ReturnBlock() { // In this case, we have to call the listener before returning. + // Save the currently active block. + current := builder.CurrentBlock() + + // Allocate the trampoline block to the return where we call the listener. + targetBlk = builder.AllocateBasicBlock() + builder.SetCurrentBlock(targetBlk) + sealTargetBlk = true + + c.callListenerAfter() + + instr := builder.AllocateInstruction() + instr.AsReturn(args) + builder.InsertInstruction(instr) + + args = ssa.ValuesNil + + // Revert the current block. + builder.SetCurrentBlock(current) + } + + // Insert the conditional jump to the target block. + brnz := builder.AllocateInstruction() + brnz.AsBrnz(v, args, targetBlk) + builder.InsertInstruction(brnz) + + if sealTargetBlk { + builder.Seal(targetBlk) + } + + // Insert the unconditional jump to the Else block which corresponds to after br_if. + elseBlk := builder.AllocateBasicBlock() + c.insertJumpToBlock(ssa.ValuesNil, elseBlk) + + // Now start translating the instructions after br_if. + builder.Seal(elseBlk) // Else of br_if has the current block as the only one successor. + builder.SetCurrentBlock(elseBlk) + + case wasm.OpcodeBrTable: + labels := state.tmpForBrTable[:0] + labelCount := c.readI32u() + for i := 0; i < int(labelCount); i++ { + labels = append(labels, c.readI32u()) + } + labels = append(labels, c.readI32u()) // default label. + if state.unreachable { + break + } + + index := state.pop() + if labelCount == 0 { // If this br_table is empty, we can just emit the unconditional jump. + targetBlk, argNum := state.brTargetArgNumFor(labels[0]) + args := c.nPeekDup(argNum) + c.insertJumpToBlock(args, targetBlk) + } else { + c.lowerBrTable(labels, index) + } + state.tmpForBrTable = labels // reuse the temporary slice for next use. + state.unreachable = true + + case wasm.OpcodeNop: + case wasm.OpcodeReturn: + if state.unreachable { + break + } + if c.needListener { + c.callListenerAfter() + } + + results := c.nPeekDup(c.results()) + instr := builder.AllocateInstruction() + + instr.AsReturn(results) + builder.InsertInstruction(instr) + state.unreachable = true + + case wasm.OpcodeUnreachable: + if state.unreachable { + break + } + exit := builder.AllocateInstruction() + exit.AsExitWithCode(c.execCtxPtrValue, wazevoapi.ExitCodeUnreachable) + builder.InsertInstruction(exit) + state.unreachable = true + + case wasm.OpcodeCallIndirect: + typeIndex := c.readI32u() + tableIndex := c.readI32u() + if state.unreachable { + break + } + c.lowerCallIndirect(typeIndex, tableIndex) + + case wasm.OpcodeCall: + fnIndex := c.readI32u() + if state.unreachable { + break + } + + var typIndex wasm.Index + if fnIndex < c.m.ImportFunctionCount { + // Before transfer the control to the callee, we have to store the current module's moduleContextPtr + // into execContext.callerModuleContextPtr in case when the callee is a Go function. + c.storeCallerModuleContext() + var fi int + for i := range c.m.ImportSection { + imp := &c.m.ImportSection[i] + if imp.Type == wasm.ExternTypeFunc { + if fi == int(fnIndex) { + typIndex = imp.DescFunc + break + } + fi++ + } + } + } else { + typIndex = c.m.FunctionSection[fnIndex-c.m.ImportFunctionCount] + } + typ := &c.m.TypeSection[typIndex] + + argN := len(typ.Params) + tail := len(state.values) - argN + vs := state.values[tail:] + state.values = state.values[:tail] + args := c.allocateVarLengthValues(2+len(vs), c.execCtxPtrValue) + + sig := c.signatures[typ] + call := builder.AllocateInstruction() + if fnIndex >= c.m.ImportFunctionCount { + args = args.Append(builder.VarLengthPool(), c.moduleCtxPtrValue) // This case the callee module is itself. + args = args.Append(builder.VarLengthPool(), vs...) + call.AsCall(FunctionIndexToFuncRef(fnIndex), sig, args) + builder.InsertInstruction(call) + } else { + // This case we have to read the address of the imported function from the module context. + moduleCtx := c.moduleCtxPtrValue + loadFuncPtr, loadModuleCtxPtr := builder.AllocateInstruction(), builder.AllocateInstruction() + funcPtrOffset, moduleCtxPtrOffset, _ := c.offset.ImportedFunctionOffset(fnIndex) + loadFuncPtr.AsLoad(moduleCtx, funcPtrOffset.U32(), ssa.TypeI64) + loadModuleCtxPtr.AsLoad(moduleCtx, moduleCtxPtrOffset.U32(), ssa.TypeI64) + builder.InsertInstruction(loadFuncPtr) + builder.InsertInstruction(loadModuleCtxPtr) + + args = args.Append(builder.VarLengthPool(), loadModuleCtxPtr.Return()) + args = args.Append(builder.VarLengthPool(), vs...) + call.AsCallIndirect(loadFuncPtr.Return(), sig, args) + builder.InsertInstruction(call) + } + + first, rest := call.Returns() + if first.Valid() { + state.push(first) + } + for _, v := range rest { + state.push(v) + } + + c.reloadAfterCall() + + case wasm.OpcodeDrop: + if state.unreachable { + break + } + _ = state.pop() + case wasm.OpcodeF64ConvertI32S, wasm.OpcodeF64ConvertI64S, wasm.OpcodeF64ConvertI32U, wasm.OpcodeF64ConvertI64U: + if state.unreachable { + break + } + result := builder.AllocateInstruction().AsFcvtFromInt( + state.pop(), + op == wasm.OpcodeF64ConvertI32S || op == wasm.OpcodeF64ConvertI64S, + true, + ).Insert(builder).Return() + state.push(result) + case wasm.OpcodeF32ConvertI32S, wasm.OpcodeF32ConvertI64S, wasm.OpcodeF32ConvertI32U, wasm.OpcodeF32ConvertI64U: + if state.unreachable { + break + } + result := builder.AllocateInstruction().AsFcvtFromInt( + state.pop(), + op == wasm.OpcodeF32ConvertI32S || op == wasm.OpcodeF32ConvertI64S, + false, + ).Insert(builder).Return() + state.push(result) + case wasm.OpcodeF32DemoteF64: + if state.unreachable { + break + } + cvt := builder.AllocateInstruction() + cvt.AsFdemote(state.pop()) + builder.InsertInstruction(cvt) + state.push(cvt.Return()) + case wasm.OpcodeF64PromoteF32: + if state.unreachable { + break + } + cvt := builder.AllocateInstruction() + cvt.AsFpromote(state.pop()) + builder.InsertInstruction(cvt) + state.push(cvt.Return()) + + case wasm.OpcodeVecPrefix: + state.pc++ + vecOp := c.wasmFunctionBody[state.pc] + switch vecOp { + case wasm.OpcodeVecV128Const: + state.pc++ + lo := binary.LittleEndian.Uint64(c.wasmFunctionBody[state.pc:]) + state.pc += 8 + hi := binary.LittleEndian.Uint64(c.wasmFunctionBody[state.pc:]) + state.pc += 7 + if state.unreachable { + break + } + ret := builder.AllocateInstruction().AsVconst(lo, hi).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Load: + _, offset := c.readMemArg() + if state.unreachable { + break + } + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), 16) + load := builder.AllocateInstruction() + load.AsLoad(addr, offset, ssa.TypeV128) + builder.InsertInstruction(load) + state.push(load.Return()) + case wasm.OpcodeVecV128Load8Lane, wasm.OpcodeVecV128Load16Lane, wasm.OpcodeVecV128Load32Lane: + _, offset := c.readMemArg() + state.pc++ + if state.unreachable { + break + } + var lane ssa.VecLane + var loadOp ssa.Opcode + var opSize uint64 + switch vecOp { + case wasm.OpcodeVecV128Load8Lane: + loadOp, lane, opSize = ssa.OpcodeUload8, ssa.VecLaneI8x16, 1 + case wasm.OpcodeVecV128Load16Lane: + loadOp, lane, opSize = ssa.OpcodeUload16, ssa.VecLaneI16x8, 2 + case wasm.OpcodeVecV128Load32Lane: + loadOp, lane, opSize = ssa.OpcodeUload32, ssa.VecLaneI32x4, 4 + } + laneIndex := c.wasmFunctionBody[state.pc] + vector := state.pop() + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), opSize) + load := builder.AllocateInstruction(). + AsExtLoad(loadOp, addr, offset, false). + Insert(builder).Return() + ret := builder.AllocateInstruction(). + AsInsertlane(vector, load, laneIndex, lane). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Load64Lane: + _, offset := c.readMemArg() + state.pc++ + if state.unreachable { + break + } + laneIndex := c.wasmFunctionBody[state.pc] + vector := state.pop() + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), 8) + load := builder.AllocateInstruction(). + AsLoad(addr, offset, ssa.TypeI64). + Insert(builder).Return() + ret := builder.AllocateInstruction(). + AsInsertlane(vector, load, laneIndex, ssa.VecLaneI64x2). + Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecV128Load32zero, wasm.OpcodeVecV128Load64zero: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + var scalarType ssa.Type + switch vecOp { + case wasm.OpcodeVecV128Load32zero: + scalarType = ssa.TypeF32 + case wasm.OpcodeVecV128Load64zero: + scalarType = ssa.TypeF64 + } + + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), uint64(scalarType.Size())) + + ret := builder.AllocateInstruction(). + AsVZeroExtLoad(addr, offset, scalarType). + Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecV128Load8x8u, wasm.OpcodeVecV128Load8x8s, + wasm.OpcodeVecV128Load16x4u, wasm.OpcodeVecV128Load16x4s, + wasm.OpcodeVecV128Load32x2u, wasm.OpcodeVecV128Load32x2s: + _, offset := c.readMemArg() + if state.unreachable { + break + } + var lane ssa.VecLane + var signed bool + switch vecOp { + case wasm.OpcodeVecV128Load8x8s: + signed = true + fallthrough + case wasm.OpcodeVecV128Load8x8u: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecV128Load16x4s: + signed = true + fallthrough + case wasm.OpcodeVecV128Load16x4u: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecV128Load32x2s: + signed = true + fallthrough + case wasm.OpcodeVecV128Load32x2u: + lane = ssa.VecLaneI32x4 + } + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), 8) + load := builder.AllocateInstruction(). + AsLoad(addr, offset, ssa.TypeF64). + Insert(builder).Return() + ret := builder.AllocateInstruction(). + AsWiden(load, lane, signed, true). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Load8Splat, wasm.OpcodeVecV128Load16Splat, + wasm.OpcodeVecV128Load32Splat, wasm.OpcodeVecV128Load64Splat: + _, offset := c.readMemArg() + if state.unreachable { + break + } + var lane ssa.VecLane + var opSize uint64 + switch vecOp { + case wasm.OpcodeVecV128Load8Splat: + lane, opSize = ssa.VecLaneI8x16, 1 + case wasm.OpcodeVecV128Load16Splat: + lane, opSize = ssa.VecLaneI16x8, 2 + case wasm.OpcodeVecV128Load32Splat: + lane, opSize = ssa.VecLaneI32x4, 4 + case wasm.OpcodeVecV128Load64Splat: + lane, opSize = ssa.VecLaneI64x2, 8 + } + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), opSize) + ret := builder.AllocateInstruction(). + AsLoadSplat(addr, offset, lane). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Store: + _, offset := c.readMemArg() + if state.unreachable { + break + } + value := state.pop() + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), 16) + builder.AllocateInstruction(). + AsStore(ssa.OpcodeStore, value, addr, offset). + Insert(builder) + case wasm.OpcodeVecV128Store8Lane, wasm.OpcodeVecV128Store16Lane, + wasm.OpcodeVecV128Store32Lane, wasm.OpcodeVecV128Store64Lane: + _, offset := c.readMemArg() + state.pc++ + if state.unreachable { + break + } + laneIndex := c.wasmFunctionBody[state.pc] + var storeOp ssa.Opcode + var lane ssa.VecLane + var opSize uint64 + switch vecOp { + case wasm.OpcodeVecV128Store8Lane: + storeOp, lane, opSize = ssa.OpcodeIstore8, ssa.VecLaneI8x16, 1 + case wasm.OpcodeVecV128Store16Lane: + storeOp, lane, opSize = ssa.OpcodeIstore16, ssa.VecLaneI16x8, 2 + case wasm.OpcodeVecV128Store32Lane: + storeOp, lane, opSize = ssa.OpcodeIstore32, ssa.VecLaneI32x4, 4 + case wasm.OpcodeVecV128Store64Lane: + storeOp, lane, opSize = ssa.OpcodeStore, ssa.VecLaneI64x2, 8 + } + vector := state.pop() + baseAddr := state.pop() + addr := c.memOpSetup(baseAddr, uint64(offset), opSize) + value := builder.AllocateInstruction(). + AsExtractlane(vector, laneIndex, lane, false). + Insert(builder).Return() + builder.AllocateInstruction(). + AsStore(storeOp, value, addr, offset). + Insert(builder) + case wasm.OpcodeVecV128Not: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVbnot(v1).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128And: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVband(v1, v2).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128AndNot: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVbandnot(v1, v2).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Or: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVbor(v1, v2).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Xor: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVbxor(v1, v2).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128Bitselect: + if state.unreachable { + break + } + c := state.pop() + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVbitselect(c, v1, v2).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128AnyTrue: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVanyTrue(v1).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16AllTrue, wasm.OpcodeVecI16x8AllTrue, wasm.OpcodeVecI32x4AllTrue, wasm.OpcodeVecI64x2AllTrue: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16AllTrue: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8AllTrue: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4AllTrue: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2AllTrue: + lane = ssa.VecLaneI64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVallTrue(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16BitMask, wasm.OpcodeVecI16x8BitMask, wasm.OpcodeVecI32x4BitMask, wasm.OpcodeVecI64x2BitMask: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16BitMask: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8BitMask: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4BitMask: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2BitMask: + lane = ssa.VecLaneI64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVhighBits(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Abs, wasm.OpcodeVecI16x8Abs, wasm.OpcodeVecI32x4Abs, wasm.OpcodeVecI64x2Abs: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Abs: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Abs: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Abs: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Abs: + lane = ssa.VecLaneI64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVIabs(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Neg, wasm.OpcodeVecI16x8Neg, wasm.OpcodeVecI32x4Neg, wasm.OpcodeVecI64x2Neg: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Neg: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Neg: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Neg: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Neg: + lane = ssa.VecLaneI64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVIneg(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Popcnt: + if state.unreachable { + break + } + lane := ssa.VecLaneI8x16 + v1 := state.pop() + + ret := builder.AllocateInstruction().AsVIpopcnt(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Add, wasm.OpcodeVecI16x8Add, wasm.OpcodeVecI32x4Add, wasm.OpcodeVecI64x2Add: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Add: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Add: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Add: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Add: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVIadd(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16AddSatS, wasm.OpcodeVecI16x8AddSatS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16AddSatS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8AddSatS: + lane = ssa.VecLaneI16x8 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVSaddSat(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16AddSatU, wasm.OpcodeVecI16x8AddSatU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16AddSatU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8AddSatU: + lane = ssa.VecLaneI16x8 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVUaddSat(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16SubSatS, wasm.OpcodeVecI16x8SubSatS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16SubSatS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8SubSatS: + lane = ssa.VecLaneI16x8 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVSsubSat(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16SubSatU, wasm.OpcodeVecI16x8SubSatU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16SubSatU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8SubSatU: + lane = ssa.VecLaneI16x8 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVUsubSat(v1, v2, lane).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI8x16Sub, wasm.OpcodeVecI16x8Sub, wasm.OpcodeVecI32x4Sub, wasm.OpcodeVecI64x2Sub: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Sub: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Sub: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Sub: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Sub: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVIsub(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16MinS, wasm.OpcodeVecI16x8MinS, wasm.OpcodeVecI32x4MinS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16MinS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8MinS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4MinS: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVImin(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16MinU, wasm.OpcodeVecI16x8MinU, wasm.OpcodeVecI32x4MinU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16MinU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8MinU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4MinU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVUmin(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16MaxS, wasm.OpcodeVecI16x8MaxS, wasm.OpcodeVecI32x4MaxS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16MaxS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8MaxS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4MaxS: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVImax(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16MaxU, wasm.OpcodeVecI16x8MaxU, wasm.OpcodeVecI32x4MaxU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16MaxU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8MaxU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4MaxU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVUmax(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16AvgrU, wasm.OpcodeVecI16x8AvgrU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16AvgrU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8AvgrU: + lane = ssa.VecLaneI16x8 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVAvgRound(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI16x8Mul, wasm.OpcodeVecI32x4Mul, wasm.OpcodeVecI64x2Mul: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI16x8Mul: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Mul: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Mul: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVImul(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI16x8Q15mulrSatS: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsSqmulRoundSat(v1, v2, ssa.VecLaneI16x8).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Eq, wasm.OpcodeVecI16x8Eq, wasm.OpcodeVecI32x4Eq, wasm.OpcodeVecI64x2Eq: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Eq: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Eq: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Eq: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Eq: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Ne, wasm.OpcodeVecI16x8Ne, wasm.OpcodeVecI32x4Ne, wasm.OpcodeVecI64x2Ne: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Ne: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Ne: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Ne: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Ne: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondNotEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16LtS, wasm.OpcodeVecI16x8LtS, wasm.OpcodeVecI32x4LtS, wasm.OpcodeVecI64x2LtS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16LtS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8LtS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4LtS: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2LtS: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondSignedLessThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16LtU, wasm.OpcodeVecI16x8LtU, wasm.OpcodeVecI32x4LtU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16LtU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8LtU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4LtU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondUnsignedLessThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16LeS, wasm.OpcodeVecI16x8LeS, wasm.OpcodeVecI32x4LeS, wasm.OpcodeVecI64x2LeS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16LeS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8LeS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4LeS: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2LeS: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondSignedLessThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16LeU, wasm.OpcodeVecI16x8LeU, wasm.OpcodeVecI32x4LeU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16LeU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8LeU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4LeU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondUnsignedLessThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16GtS, wasm.OpcodeVecI16x8GtS, wasm.OpcodeVecI32x4GtS, wasm.OpcodeVecI64x2GtS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16GtS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8GtS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4GtS: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2GtS: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondSignedGreaterThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16GtU, wasm.OpcodeVecI16x8GtU, wasm.OpcodeVecI32x4GtU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16GtU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8GtU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4GtU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondUnsignedGreaterThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16GeS, wasm.OpcodeVecI16x8GeS, wasm.OpcodeVecI32x4GeS, wasm.OpcodeVecI64x2GeS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16GeS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8GeS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4GeS: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2GeS: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondSignedGreaterThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16GeU, wasm.OpcodeVecI16x8GeU, wasm.OpcodeVecI32x4GeU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16GeU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8GeU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4GeU: + lane = ssa.VecLaneI32x4 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVIcmp(v1, v2, ssa.IntegerCmpCondUnsignedGreaterThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Max, wasm.OpcodeVecF64x2Max: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Max: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Max: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFmax(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Abs, wasm.OpcodeVecF64x2Abs: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Abs: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Abs: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFabs(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Min, wasm.OpcodeVecF64x2Min: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Min: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Min: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFmin(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Neg, wasm.OpcodeVecF64x2Neg: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Neg: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Neg: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFneg(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Sqrt, wasm.OpcodeVecF64x2Sqrt: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Sqrt: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Sqrt: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVSqrt(v1, lane).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecF32x4Add, wasm.OpcodeVecF64x2Add: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Add: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Add: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFadd(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Sub, wasm.OpcodeVecF64x2Sub: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Sub: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Sub: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFsub(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Mul, wasm.OpcodeVecF64x2Mul: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Mul: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Mul: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFmul(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Div, wasm.OpcodeVecF64x2Div: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Div: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Div: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFdiv(v1, v2, lane).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S, wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U: + if state.unreachable { + break + } + v := state.pop() + signed := vecOp == wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S + ret := builder.AllocateInstruction().AsExtIaddPairwise(v, ssa.VecLaneI8x16, signed).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U: + if state.unreachable { + break + } + v := state.pop() + signed := vecOp == wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S + ret := builder.AllocateInstruction().AsExtIaddPairwise(v, ssa.VecLaneI16x8, signed).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI16x8ExtMulLowI8x16S, wasm.OpcodeVecI16x8ExtMulLowI8x16U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI8x16, ssa.VecLaneI16x8, + vecOp == wasm.OpcodeVecI16x8ExtMulLowI8x16S, true) + state.push(ret) + + case wasm.OpcodeVecI16x8ExtMulHighI8x16S, wasm.OpcodeVecI16x8ExtMulHighI8x16U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI8x16, ssa.VecLaneI16x8, + vecOp == wasm.OpcodeVecI16x8ExtMulHighI8x16S, false) + state.push(ret) + + case wasm.OpcodeVecI32x4ExtMulLowI16x8S, wasm.OpcodeVecI32x4ExtMulLowI16x8U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI16x8, ssa.VecLaneI32x4, + vecOp == wasm.OpcodeVecI32x4ExtMulLowI16x8S, true) + state.push(ret) + + case wasm.OpcodeVecI32x4ExtMulHighI16x8S, wasm.OpcodeVecI32x4ExtMulHighI16x8U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI16x8, ssa.VecLaneI32x4, + vecOp == wasm.OpcodeVecI32x4ExtMulHighI16x8S, false) + state.push(ret) + case wasm.OpcodeVecI64x2ExtMulLowI32x4S, wasm.OpcodeVecI64x2ExtMulLowI32x4U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI32x4, ssa.VecLaneI64x2, + vecOp == wasm.OpcodeVecI64x2ExtMulLowI32x4S, true) + state.push(ret) + + case wasm.OpcodeVecI64x2ExtMulHighI32x4S, wasm.OpcodeVecI64x2ExtMulHighI32x4U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := c.lowerExtMul( + v1, v2, + ssa.VecLaneI32x4, ssa.VecLaneI64x2, + vecOp == wasm.OpcodeVecI64x2ExtMulHighI32x4S, false) + state.push(ret) + + case wasm.OpcodeVecI32x4DotI16x8S: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + + ret := builder.AllocateInstruction().AsWideningPairwiseDotProductS(v1, v2).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecF32x4Eq, wasm.OpcodeVecF64x2Eq: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Eq: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Eq: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Ne, wasm.OpcodeVecF64x2Ne: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Ne: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Ne: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondNotEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Lt, wasm.OpcodeVecF64x2Lt: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Lt: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Lt: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondLessThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Le, wasm.OpcodeVecF64x2Le: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Le: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Le: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondLessThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Gt, wasm.OpcodeVecF64x2Gt: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Gt: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Gt: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondGreaterThan, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Ge, wasm.OpcodeVecF64x2Ge: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Ge: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Ge: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcmp(v1, v2, ssa.FloatCmpCondGreaterThanOrEqual, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Ceil, wasm.OpcodeVecF64x2Ceil: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Ceil: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Ceil: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVCeil(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Floor, wasm.OpcodeVecF64x2Floor: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Floor: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Floor: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVFloor(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Trunc, wasm.OpcodeVecF64x2Trunc: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Trunc: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Trunc: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVTrunc(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Nearest, wasm.OpcodeVecF64x2Nearest: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Nearest: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Nearest: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsVNearest(v1, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Pmin, wasm.OpcodeVecF64x2Pmin: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Pmin: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Pmin: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVMinPseudo(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4Pmax, wasm.OpcodeVecF64x2Pmax: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecF32x4Pmax: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Pmax: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVMaxPseudo(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI32x4TruncSatF32x4S, wasm.OpcodeVecI32x4TruncSatF32x4U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcvtToIntSat(v1, ssa.VecLaneF32x4, vecOp == wasm.OpcodeVecI32x4TruncSatF32x4S).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI32x4TruncSatF64x2SZero, wasm.OpcodeVecI32x4TruncSatF64x2UZero: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcvtToIntSat(v1, ssa.VecLaneF64x2, vecOp == wasm.OpcodeVecI32x4TruncSatF64x2SZero).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4ConvertI32x4S, wasm.OpcodeVecF32x4ConvertI32x4U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsVFcvtFromInt(v1, ssa.VecLaneF32x4, vecOp == wasm.OpcodeVecF32x4ConvertI32x4S).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF64x2ConvertLowI32x4S, wasm.OpcodeVecF64x2ConvertLowI32x4U: + if state.unreachable { + break + } + v1 := state.pop() + if runtime.GOARCH == "arm64" { + // TODO: this is weird. fix. + v1 = builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI32x4, vecOp == wasm.OpcodeVecF64x2ConvertLowI32x4S, true).Insert(builder).Return() + } + ret := builder.AllocateInstruction(). + AsVFcvtFromInt(v1, ssa.VecLaneF64x2, vecOp == wasm.OpcodeVecF64x2ConvertLowI32x4S). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16NarrowI16x8S, wasm.OpcodeVecI8x16NarrowI16x8U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsNarrow(v1, v2, ssa.VecLaneI16x8, vecOp == wasm.OpcodeVecI8x16NarrowI16x8S). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI16x8NarrowI32x4S, wasm.OpcodeVecI16x8NarrowI32x4U: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsNarrow(v1, v2, ssa.VecLaneI32x4, vecOp == wasm.OpcodeVecI16x8NarrowI32x4S). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI16x8ExtendLowI8x16S, wasm.OpcodeVecI16x8ExtendLowI8x16U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI8x16, vecOp == wasm.OpcodeVecI16x8ExtendLowI8x16S, true). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI16x8ExtendHighI8x16S, wasm.OpcodeVecI16x8ExtendHighI8x16U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI8x16, vecOp == wasm.OpcodeVecI16x8ExtendHighI8x16S, false). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI32x4ExtendLowI16x8S, wasm.OpcodeVecI32x4ExtendLowI16x8U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI16x8, vecOp == wasm.OpcodeVecI32x4ExtendLowI16x8S, true). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI32x4ExtendHighI16x8S, wasm.OpcodeVecI32x4ExtendHighI16x8U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI16x8, vecOp == wasm.OpcodeVecI32x4ExtendHighI16x8S, false). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI64x2ExtendLowI32x4S, wasm.OpcodeVecI64x2ExtendLowI32x4U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI32x4, vecOp == wasm.OpcodeVecI64x2ExtendLowI32x4S, true). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI64x2ExtendHighI32x4S, wasm.OpcodeVecI64x2ExtendHighI32x4U: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsWiden(v1, ssa.VecLaneI32x4, vecOp == wasm.OpcodeVecI64x2ExtendHighI32x4S, false). + Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecF64x2PromoteLowF32x4Zero: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsFvpromoteLow(v1, ssa.VecLaneF32x4). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecF32x4DemoteF64x2Zero: + if state.unreachable { + break + } + v1 := state.pop() + ret := builder.AllocateInstruction(). + AsFvdemote(v1, ssa.VecLaneF64x2). + Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16Shl, wasm.OpcodeVecI16x8Shl, wasm.OpcodeVecI32x4Shl, wasm.OpcodeVecI64x2Shl: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Shl: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Shl: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Shl: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Shl: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVIshl(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16ShrS, wasm.OpcodeVecI16x8ShrS, wasm.OpcodeVecI32x4ShrS, wasm.OpcodeVecI64x2ShrS: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16ShrS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8ShrS: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4ShrS: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2ShrS: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVSshr(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16ShrU, wasm.OpcodeVecI16x8ShrU, wasm.OpcodeVecI32x4ShrU, wasm.OpcodeVecI64x2ShrU: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16ShrU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8ShrU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4ShrU: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2ShrU: + lane = ssa.VecLaneI64x2 + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsVUshr(v1, v2, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecI8x16ExtractLaneS, wasm.OpcodeVecI16x8ExtractLaneS: + state.pc++ + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16ExtractLaneS: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8ExtractLaneS: + lane = ssa.VecLaneI16x8 + } + v1 := state.pop() + index := c.wasmFunctionBody[state.pc] + ext := builder.AllocateInstruction().AsExtractlane(v1, index, lane, true).Insert(builder).Return() + state.push(ext) + case wasm.OpcodeVecI8x16ExtractLaneU, wasm.OpcodeVecI16x8ExtractLaneU, + wasm.OpcodeVecI32x4ExtractLane, wasm.OpcodeVecI64x2ExtractLane, + wasm.OpcodeVecF32x4ExtractLane, wasm.OpcodeVecF64x2ExtractLane: + state.pc++ // Skip the immediate value. + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16ExtractLaneU: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8ExtractLaneU: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4ExtractLane: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2ExtractLane: + lane = ssa.VecLaneI64x2 + case wasm.OpcodeVecF32x4ExtractLane: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2ExtractLane: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + index := c.wasmFunctionBody[state.pc] + ext := builder.AllocateInstruction().AsExtractlane(v1, index, lane, false).Insert(builder).Return() + state.push(ext) + case wasm.OpcodeVecI8x16ReplaceLane, wasm.OpcodeVecI16x8ReplaceLane, + wasm.OpcodeVecI32x4ReplaceLane, wasm.OpcodeVecI64x2ReplaceLane, + wasm.OpcodeVecF32x4ReplaceLane, wasm.OpcodeVecF64x2ReplaceLane: + state.pc++ + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16ReplaceLane: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8ReplaceLane: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4ReplaceLane: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2ReplaceLane: + lane = ssa.VecLaneI64x2 + case wasm.OpcodeVecF32x4ReplaceLane: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2ReplaceLane: + lane = ssa.VecLaneF64x2 + } + v2 := state.pop() + v1 := state.pop() + index := c.wasmFunctionBody[state.pc] + ret := builder.AllocateInstruction().AsInsertlane(v1, v2, index, lane).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeVecV128i8x16Shuffle: + state.pc++ + laneIndexes := c.wasmFunctionBody[state.pc : state.pc+16] + state.pc += 15 + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsShuffle(v1, v2, laneIndexes).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI8x16Swizzle: + if state.unreachable { + break + } + v2 := state.pop() + v1 := state.pop() + ret := builder.AllocateInstruction().AsSwizzle(v1, v2, ssa.VecLaneI8x16).Insert(builder).Return() + state.push(ret) + + case wasm.OpcodeVecI8x16Splat, + wasm.OpcodeVecI16x8Splat, + wasm.OpcodeVecI32x4Splat, + wasm.OpcodeVecI64x2Splat, + wasm.OpcodeVecF32x4Splat, + wasm.OpcodeVecF64x2Splat: + if state.unreachable { + break + } + var lane ssa.VecLane + switch vecOp { + case wasm.OpcodeVecI8x16Splat: + lane = ssa.VecLaneI8x16 + case wasm.OpcodeVecI16x8Splat: + lane = ssa.VecLaneI16x8 + case wasm.OpcodeVecI32x4Splat: + lane = ssa.VecLaneI32x4 + case wasm.OpcodeVecI64x2Splat: + lane = ssa.VecLaneI64x2 + case wasm.OpcodeVecF32x4Splat: + lane = ssa.VecLaneF32x4 + case wasm.OpcodeVecF64x2Splat: + lane = ssa.VecLaneF64x2 + } + v1 := state.pop() + ret := builder.AllocateInstruction().AsSplat(v1, lane).Insert(builder).Return() + state.push(ret) + + default: + panic("TODO: unsupported vector instruction: " + wasm.VectorInstructionName(vecOp)) + } + case wasm.OpcodeAtomicPrefix: + state.pc++ + atomicOp := c.wasmFunctionBody[state.pc] + switch atomicOp { + case wasm.OpcodeAtomicMemoryWait32, wasm.OpcodeAtomicMemoryWait64: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + c.storeCallerModuleContext() + + var opSize uint64 + var trampoline wazevoapi.Offset + var sig *ssa.Signature + switch atomicOp { + case wasm.OpcodeAtomicMemoryWait32: + opSize = 4 + trampoline = wazevoapi.ExecutionContextOffsetMemoryWait32TrampolineAddress + sig = &c.memoryWait32Sig + case wasm.OpcodeAtomicMemoryWait64: + opSize = 8 + trampoline = wazevoapi.ExecutionContextOffsetMemoryWait64TrampolineAddress + sig = &c.memoryWait64Sig + } + + timeout := state.pop() + exp := state.pop() + baseAddr := state.pop() + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), opSize) + + memoryWaitPtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + trampoline.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + args := c.allocateVarLengthValues(3, c.execCtxPtrValue, timeout, exp, addr) + memoryWaitRet := builder.AllocateInstruction(). + AsCallIndirect(memoryWaitPtr, sig, args). + Insert(builder).Return() + state.push(memoryWaitRet) + case wasm.OpcodeAtomicMemoryNotify: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + c.storeCallerModuleContext() + count := state.pop() + baseAddr := state.pop() + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), 4) + + memoryNotifyPtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetMemoryNotifyTrampolineAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + args := c.allocateVarLengthValues(2, c.execCtxPtrValue, count, addr) + memoryNotifyRet := builder.AllocateInstruction(). + AsCallIndirect(memoryNotifyPtr, &c.memoryNotifySig, args). + Insert(builder).Return() + state.push(memoryNotifyRet) + case wasm.OpcodeAtomicI32Load, wasm.OpcodeAtomicI64Load, wasm.OpcodeAtomicI32Load8U, wasm.OpcodeAtomicI32Load16U, wasm.OpcodeAtomicI64Load8U, wasm.OpcodeAtomicI64Load16U, wasm.OpcodeAtomicI64Load32U: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + baseAddr := state.pop() + + var size uint64 + switch atomicOp { + case wasm.OpcodeAtomicI64Load: + size = 8 + case wasm.OpcodeAtomicI32Load, wasm.OpcodeAtomicI64Load32U: + size = 4 + case wasm.OpcodeAtomicI32Load16U, wasm.OpcodeAtomicI64Load16U: + size = 2 + case wasm.OpcodeAtomicI32Load8U, wasm.OpcodeAtomicI64Load8U: + size = 1 + } + + var typ ssa.Type + switch atomicOp { + case wasm.OpcodeAtomicI64Load, wasm.OpcodeAtomicI64Load32U, wasm.OpcodeAtomicI64Load16U, wasm.OpcodeAtomicI64Load8U: + typ = ssa.TypeI64 + case wasm.OpcodeAtomicI32Load, wasm.OpcodeAtomicI32Load16U, wasm.OpcodeAtomicI32Load8U: + typ = ssa.TypeI32 + } + + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), size) + res := builder.AllocateInstruction().AsAtomicLoad(addr, size, typ).Insert(builder).Return() + state.push(res) + case wasm.OpcodeAtomicI32Store, wasm.OpcodeAtomicI64Store, wasm.OpcodeAtomicI32Store8, wasm.OpcodeAtomicI32Store16, wasm.OpcodeAtomicI64Store8, wasm.OpcodeAtomicI64Store16, wasm.OpcodeAtomicI64Store32: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + val := state.pop() + baseAddr := state.pop() + + var size uint64 + switch atomicOp { + case wasm.OpcodeAtomicI64Store: + size = 8 + case wasm.OpcodeAtomicI32Store, wasm.OpcodeAtomicI64Store32: + size = 4 + case wasm.OpcodeAtomicI32Store16, wasm.OpcodeAtomicI64Store16: + size = 2 + case wasm.OpcodeAtomicI32Store8, wasm.OpcodeAtomicI64Store8: + size = 1 + } + + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), size) + builder.AllocateInstruction().AsAtomicStore(addr, val, size).Insert(builder) + case wasm.OpcodeAtomicI32RmwAdd, wasm.OpcodeAtomicI64RmwAdd, wasm.OpcodeAtomicI32Rmw8AddU, wasm.OpcodeAtomicI32Rmw16AddU, wasm.OpcodeAtomicI64Rmw8AddU, wasm.OpcodeAtomicI64Rmw16AddU, wasm.OpcodeAtomicI64Rmw32AddU, + wasm.OpcodeAtomicI32RmwSub, wasm.OpcodeAtomicI64RmwSub, wasm.OpcodeAtomicI32Rmw8SubU, wasm.OpcodeAtomicI32Rmw16SubU, wasm.OpcodeAtomicI64Rmw8SubU, wasm.OpcodeAtomicI64Rmw16SubU, wasm.OpcodeAtomicI64Rmw32SubU, + wasm.OpcodeAtomicI32RmwAnd, wasm.OpcodeAtomicI64RmwAnd, wasm.OpcodeAtomicI32Rmw8AndU, wasm.OpcodeAtomicI32Rmw16AndU, wasm.OpcodeAtomicI64Rmw8AndU, wasm.OpcodeAtomicI64Rmw16AndU, wasm.OpcodeAtomicI64Rmw32AndU, + wasm.OpcodeAtomicI32RmwOr, wasm.OpcodeAtomicI64RmwOr, wasm.OpcodeAtomicI32Rmw8OrU, wasm.OpcodeAtomicI32Rmw16OrU, wasm.OpcodeAtomicI64Rmw8OrU, wasm.OpcodeAtomicI64Rmw16OrU, wasm.OpcodeAtomicI64Rmw32OrU, + wasm.OpcodeAtomicI32RmwXor, wasm.OpcodeAtomicI64RmwXor, wasm.OpcodeAtomicI32Rmw8XorU, wasm.OpcodeAtomicI32Rmw16XorU, wasm.OpcodeAtomicI64Rmw8XorU, wasm.OpcodeAtomicI64Rmw16XorU, wasm.OpcodeAtomicI64Rmw32XorU, + wasm.OpcodeAtomicI32RmwXchg, wasm.OpcodeAtomicI64RmwXchg, wasm.OpcodeAtomicI32Rmw8XchgU, wasm.OpcodeAtomicI32Rmw16XchgU, wasm.OpcodeAtomicI64Rmw8XchgU, wasm.OpcodeAtomicI64Rmw16XchgU, wasm.OpcodeAtomicI64Rmw32XchgU: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + val := state.pop() + baseAddr := state.pop() + + var rmwOp ssa.AtomicRmwOp + var size uint64 + switch atomicOp { + case wasm.OpcodeAtomicI32RmwAdd, wasm.OpcodeAtomicI64RmwAdd, wasm.OpcodeAtomicI32Rmw8AddU, wasm.OpcodeAtomicI32Rmw16AddU, wasm.OpcodeAtomicI64Rmw8AddU, wasm.OpcodeAtomicI64Rmw16AddU, wasm.OpcodeAtomicI64Rmw32AddU: + rmwOp = ssa.AtomicRmwOpAdd + switch atomicOp { + case wasm.OpcodeAtomicI64RmwAdd: + size = 8 + case wasm.OpcodeAtomicI32RmwAdd, wasm.OpcodeAtomicI64Rmw32AddU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16AddU, wasm.OpcodeAtomicI64Rmw16AddU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8AddU, wasm.OpcodeAtomicI64Rmw8AddU: + size = 1 + } + case wasm.OpcodeAtomicI32RmwSub, wasm.OpcodeAtomicI64RmwSub, wasm.OpcodeAtomicI32Rmw8SubU, wasm.OpcodeAtomicI32Rmw16SubU, wasm.OpcodeAtomicI64Rmw8SubU, wasm.OpcodeAtomicI64Rmw16SubU, wasm.OpcodeAtomicI64Rmw32SubU: + rmwOp = ssa.AtomicRmwOpSub + switch atomicOp { + case wasm.OpcodeAtomicI64RmwSub: + size = 8 + case wasm.OpcodeAtomicI32RmwSub, wasm.OpcodeAtomicI64Rmw32SubU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16SubU, wasm.OpcodeAtomicI64Rmw16SubU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8SubU, wasm.OpcodeAtomicI64Rmw8SubU: + size = 1 + } + case wasm.OpcodeAtomicI32RmwAnd, wasm.OpcodeAtomicI64RmwAnd, wasm.OpcodeAtomicI32Rmw8AndU, wasm.OpcodeAtomicI32Rmw16AndU, wasm.OpcodeAtomicI64Rmw8AndU, wasm.OpcodeAtomicI64Rmw16AndU, wasm.OpcodeAtomicI64Rmw32AndU: + rmwOp = ssa.AtomicRmwOpAnd + switch atomicOp { + case wasm.OpcodeAtomicI64RmwAnd: + size = 8 + case wasm.OpcodeAtomicI32RmwAnd, wasm.OpcodeAtomicI64Rmw32AndU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16AndU, wasm.OpcodeAtomicI64Rmw16AndU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8AndU, wasm.OpcodeAtomicI64Rmw8AndU: + size = 1 + } + case wasm.OpcodeAtomicI32RmwOr, wasm.OpcodeAtomicI64RmwOr, wasm.OpcodeAtomicI32Rmw8OrU, wasm.OpcodeAtomicI32Rmw16OrU, wasm.OpcodeAtomicI64Rmw8OrU, wasm.OpcodeAtomicI64Rmw16OrU, wasm.OpcodeAtomicI64Rmw32OrU: + rmwOp = ssa.AtomicRmwOpOr + switch atomicOp { + case wasm.OpcodeAtomicI64RmwOr: + size = 8 + case wasm.OpcodeAtomicI32RmwOr, wasm.OpcodeAtomicI64Rmw32OrU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16OrU, wasm.OpcodeAtomicI64Rmw16OrU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8OrU, wasm.OpcodeAtomicI64Rmw8OrU: + size = 1 + } + case wasm.OpcodeAtomicI32RmwXor, wasm.OpcodeAtomicI64RmwXor, wasm.OpcodeAtomicI32Rmw8XorU, wasm.OpcodeAtomicI32Rmw16XorU, wasm.OpcodeAtomicI64Rmw8XorU, wasm.OpcodeAtomicI64Rmw16XorU, wasm.OpcodeAtomicI64Rmw32XorU: + rmwOp = ssa.AtomicRmwOpXor + switch atomicOp { + case wasm.OpcodeAtomicI64RmwXor: + size = 8 + case wasm.OpcodeAtomicI32RmwXor, wasm.OpcodeAtomicI64Rmw32XorU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16XorU, wasm.OpcodeAtomicI64Rmw16XorU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8XorU, wasm.OpcodeAtomicI64Rmw8XorU: + size = 1 + } + case wasm.OpcodeAtomicI32RmwXchg, wasm.OpcodeAtomicI64RmwXchg, wasm.OpcodeAtomicI32Rmw8XchgU, wasm.OpcodeAtomicI32Rmw16XchgU, wasm.OpcodeAtomicI64Rmw8XchgU, wasm.OpcodeAtomicI64Rmw16XchgU, wasm.OpcodeAtomicI64Rmw32XchgU: + rmwOp = ssa.AtomicRmwOpXchg + switch atomicOp { + case wasm.OpcodeAtomicI64RmwXchg: + size = 8 + case wasm.OpcodeAtomicI32RmwXchg, wasm.OpcodeAtomicI64Rmw32XchgU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16XchgU, wasm.OpcodeAtomicI64Rmw16XchgU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8XchgU, wasm.OpcodeAtomicI64Rmw8XchgU: + size = 1 + } + } + + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), size) + res := builder.AllocateInstruction().AsAtomicRmw(rmwOp, addr, val, size).Insert(builder).Return() + state.push(res) + case wasm.OpcodeAtomicI32RmwCmpxchg, wasm.OpcodeAtomicI64RmwCmpxchg, wasm.OpcodeAtomicI32Rmw8CmpxchgU, wasm.OpcodeAtomicI32Rmw16CmpxchgU, wasm.OpcodeAtomicI64Rmw8CmpxchgU, wasm.OpcodeAtomicI64Rmw16CmpxchgU, wasm.OpcodeAtomicI64Rmw32CmpxchgU: + _, offset := c.readMemArg() + if state.unreachable { + break + } + + repl := state.pop() + exp := state.pop() + baseAddr := state.pop() + + var size uint64 + switch atomicOp { + case wasm.OpcodeAtomicI64RmwCmpxchg: + size = 8 + case wasm.OpcodeAtomicI32RmwCmpxchg, wasm.OpcodeAtomicI64Rmw32CmpxchgU: + size = 4 + case wasm.OpcodeAtomicI32Rmw16CmpxchgU, wasm.OpcodeAtomicI64Rmw16CmpxchgU: + size = 2 + case wasm.OpcodeAtomicI32Rmw8CmpxchgU, wasm.OpcodeAtomicI64Rmw8CmpxchgU: + size = 1 + } + addr := c.atomicMemOpSetup(baseAddr, uint64(offset), size) + res := builder.AllocateInstruction().AsAtomicCas(addr, exp, repl, size).Insert(builder).Return() + state.push(res) + case wasm.OpcodeAtomicFence: + order := c.readByte() + if state.unreachable { + break + } + if c.needMemory { + builder.AllocateInstruction().AsFence(order).Insert(builder) + } + default: + panic("TODO: unsupported atomic instruction: " + wasm.AtomicInstructionName(atomicOp)) + } + case wasm.OpcodeRefFunc: + funcIndex := c.readI32u() + if state.unreachable { + break + } + + c.storeCallerModuleContext() + + funcIndexVal := builder.AllocateInstruction().AsIconst32(funcIndex).Insert(builder).Return() + + refFuncPtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetRefFuncTrampolineAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + args := c.allocateVarLengthValues(2, c.execCtxPtrValue, funcIndexVal) + refFuncRet := builder. + AllocateInstruction(). + AsCallIndirect(refFuncPtr, &c.refFuncSig, args). + Insert(builder).Return() + state.push(refFuncRet) + + case wasm.OpcodeRefNull: + c.loweringState.pc++ // skips the reference type as we treat both of them as i64(0). + if state.unreachable { + break + } + ret := builder.AllocateInstruction().AsIconst64(0).Insert(builder).Return() + state.push(ret) + case wasm.OpcodeRefIsNull: + if state.unreachable { + break + } + r := state.pop() + zero := builder.AllocateInstruction().AsIconst64(0).Insert(builder) + icmp := builder.AllocateInstruction(). + AsIcmp(r, zero.Return(), ssa.IntegerCmpCondEqual). + Insert(builder). + Return() + state.push(icmp) + case wasm.OpcodeTableSet: + tableIndex := c.readI32u() + if state.unreachable { + break + } + r := state.pop() + targetOffsetInTable := state.pop() + + elementAddr := c.lowerAccessTableWithBoundsCheck(tableIndex, targetOffsetInTable) + builder.AllocateInstruction().AsStore(ssa.OpcodeStore, r, elementAddr, 0).Insert(builder) + + case wasm.OpcodeTableGet: + tableIndex := c.readI32u() + if state.unreachable { + break + } + targetOffsetInTable := state.pop() + elementAddr := c.lowerAccessTableWithBoundsCheck(tableIndex, targetOffsetInTable) + loaded := builder.AllocateInstruction().AsLoad(elementAddr, 0, ssa.TypeI64).Insert(builder).Return() + state.push(loaded) + default: + panic("TODO: unsupported in wazevo yet: " + wasm.InstructionName(op)) + } + + if wazevoapi.FrontEndLoggingEnabled { + fmt.Println("--------- Translated " + wasm.InstructionName(op) + " --------") + fmt.Println("state: " + c.loweringState.String()) + fmt.Println(c.formatBuilder()) + fmt.Println("--------------------------") + } + c.loweringState.pc++ +} + +func (c *Compiler) lowerExtMul(v1, v2 ssa.Value, from, to ssa.VecLane, signed, low bool) ssa.Value { + // TODO: The sequence `Widen; Widen; VIMul` can be substituted for a single instruction on some ISAs. + builder := c.ssaBuilder + + v1lo := builder.AllocateInstruction().AsWiden(v1, from, signed, low).Insert(builder).Return() + v2lo := builder.AllocateInstruction().AsWiden(v2, from, signed, low).Insert(builder).Return() + + return builder.AllocateInstruction().AsVImul(v1lo, v2lo, to).Insert(builder).Return() +} + +const ( + tableInstanceBaseAddressOffset = 0 + tableInstanceLenOffset = tableInstanceBaseAddressOffset + 8 +) + +func (c *Compiler) lowerAccessTableWithBoundsCheck(tableIndex uint32, elementOffsetInTable ssa.Value) (elementAddress ssa.Value) { + builder := c.ssaBuilder + + // Load the table. + loadTableInstancePtr := builder.AllocateInstruction() + loadTableInstancePtr.AsLoad(c.moduleCtxPtrValue, c.offset.TableOffset(int(tableIndex)).U32(), ssa.TypeI64) + builder.InsertInstruction(loadTableInstancePtr) + tableInstancePtr := loadTableInstancePtr.Return() + + // Load the table's length. + loadTableLen := builder.AllocateInstruction() + loadTableLen.AsLoad(tableInstancePtr, tableInstanceLenOffset, ssa.TypeI32) + builder.InsertInstruction(loadTableLen) + tableLen := loadTableLen.Return() + + // Compare the length and the target, and trap if out of bounds. + checkOOB := builder.AllocateInstruction() + checkOOB.AsIcmp(elementOffsetInTable, tableLen, ssa.IntegerCmpCondUnsignedGreaterThanOrEqual) + builder.InsertInstruction(checkOOB) + exitIfOOB := builder.AllocateInstruction() + exitIfOOB.AsExitIfTrueWithCode(c.execCtxPtrValue, checkOOB.Return(), wazevoapi.ExitCodeTableOutOfBounds) + builder.InsertInstruction(exitIfOOB) + + // Get the base address of wasm.TableInstance.References. + loadTableBaseAddress := builder.AllocateInstruction() + loadTableBaseAddress.AsLoad(tableInstancePtr, tableInstanceBaseAddressOffset, ssa.TypeI64) + builder.InsertInstruction(loadTableBaseAddress) + tableBase := loadTableBaseAddress.Return() + + // Calculate the address of the target function. First we need to multiply targetOffsetInTable by 8 (pointer size). + multiplyBy8 := builder.AllocateInstruction() + three := builder.AllocateInstruction() + three.AsIconst64(3) + builder.InsertInstruction(three) + multiplyBy8.AsIshl(elementOffsetInTable, three.Return()) + builder.InsertInstruction(multiplyBy8) + targetOffsetInTableMultipliedBy8 := multiplyBy8.Return() + + // Then add the multiplied value to the base which results in the address of the target function (*wazevo.functionInstance) + calcElementAddressInTable := builder.AllocateInstruction() + calcElementAddressInTable.AsIadd(tableBase, targetOffsetInTableMultipliedBy8) + builder.InsertInstruction(calcElementAddressInTable) + return calcElementAddressInTable.Return() +} + +func (c *Compiler) lowerCallIndirect(typeIndex, tableIndex uint32) { + builder := c.ssaBuilder + state := c.state() + + elementOffsetInTable := state.pop() + functionInstancePtrAddress := c.lowerAccessTableWithBoundsCheck(tableIndex, elementOffsetInTable) + loadFunctionInstancePtr := builder.AllocateInstruction() + loadFunctionInstancePtr.AsLoad(functionInstancePtrAddress, 0, ssa.TypeI64) + builder.InsertInstruction(loadFunctionInstancePtr) + functionInstancePtr := loadFunctionInstancePtr.Return() + + // Check if it is not the null pointer. + zero := builder.AllocateInstruction() + zero.AsIconst64(0) + builder.InsertInstruction(zero) + checkNull := builder.AllocateInstruction() + checkNull.AsIcmp(functionInstancePtr, zero.Return(), ssa.IntegerCmpCondEqual) + builder.InsertInstruction(checkNull) + exitIfNull := builder.AllocateInstruction() + exitIfNull.AsExitIfTrueWithCode(c.execCtxPtrValue, checkNull.Return(), wazevoapi.ExitCodeIndirectCallNullPointer) + builder.InsertInstruction(exitIfNull) + + // We need to do the type check. First, load the target function instance's typeID. + loadTypeID := builder.AllocateInstruction() + loadTypeID.AsLoad(functionInstancePtr, wazevoapi.FunctionInstanceTypeIDOffset, ssa.TypeI32) + builder.InsertInstruction(loadTypeID) + actualTypeID := loadTypeID.Return() + + // Next, we load the expected TypeID: + loadTypeIDsBegin := builder.AllocateInstruction() + loadTypeIDsBegin.AsLoad(c.moduleCtxPtrValue, c.offset.TypeIDs1stElement.U32(), ssa.TypeI64) + builder.InsertInstruction(loadTypeIDsBegin) + typeIDsBegin := loadTypeIDsBegin.Return() + + loadExpectedTypeID := builder.AllocateInstruction() + loadExpectedTypeID.AsLoad(typeIDsBegin, uint32(typeIndex)*4 /* size of wasm.FunctionTypeID */, ssa.TypeI32) + builder.InsertInstruction(loadExpectedTypeID) + expectedTypeID := loadExpectedTypeID.Return() + + // Check if the type ID matches. + checkTypeID := builder.AllocateInstruction() + checkTypeID.AsIcmp(actualTypeID, expectedTypeID, ssa.IntegerCmpCondNotEqual) + builder.InsertInstruction(checkTypeID) + exitIfNotMatch := builder.AllocateInstruction() + exitIfNotMatch.AsExitIfTrueWithCode(c.execCtxPtrValue, checkTypeID.Return(), wazevoapi.ExitCodeIndirectCallTypeMismatch) + builder.InsertInstruction(exitIfNotMatch) + + // Now ready to call the function. Load the executable and moduleContextOpaquePtr from the function instance. + loadExecutablePtr := builder.AllocateInstruction() + loadExecutablePtr.AsLoad(functionInstancePtr, wazevoapi.FunctionInstanceExecutableOffset, ssa.TypeI64) + builder.InsertInstruction(loadExecutablePtr) + executablePtr := loadExecutablePtr.Return() + loadModuleContextOpaquePtr := builder.AllocateInstruction() + loadModuleContextOpaquePtr.AsLoad(functionInstancePtr, wazevoapi.FunctionInstanceModuleContextOpaquePtrOffset, ssa.TypeI64) + builder.InsertInstruction(loadModuleContextOpaquePtr) + moduleContextOpaquePtr := loadModuleContextOpaquePtr.Return() + + typ := &c.m.TypeSection[typeIndex] + tail := len(state.values) - len(typ.Params) + vs := state.values[tail:] + state.values = state.values[:tail] + args := c.allocateVarLengthValues(2+len(vs), c.execCtxPtrValue, moduleContextOpaquePtr) + args = args.Append(builder.VarLengthPool(), vs...) + + // Before transfer the control to the callee, we have to store the current module's moduleContextPtr + // into execContext.callerModuleContextPtr in case when the callee is a Go function. + c.storeCallerModuleContext() + + call := builder.AllocateInstruction() + call.AsCallIndirect(executablePtr, c.signatures[typ], args) + builder.InsertInstruction(call) + + first, rest := call.Returns() + if first.Valid() { + state.push(first) + } + for _, v := range rest { + state.push(v) + } + + c.reloadAfterCall() +} + +// memOpSetup inserts the bounds check and calculates the address of the memory operation (loads/stores). +func (c *Compiler) memOpSetup(baseAddr ssa.Value, constOffset, operationSizeInBytes uint64) (address ssa.Value) { + address = ssa.ValueInvalid + builder := c.ssaBuilder + + baseAddrID := baseAddr.ID() + ceil := constOffset + operationSizeInBytes + if known := c.getKnownSafeBound(baseAddrID); known.valid() { + // We reuse the calculated absolute address even if the bound is not known to be safe. + address = known.absoluteAddr + if ceil <= known.bound { + if !address.Valid() { + // This means that, the bound is known to be safe, but the memory base might have changed. + // So, we re-calculate the address. + memBase := c.getMemoryBaseValue(false) + extBaseAddr := builder.AllocateInstruction(). + AsUExtend(baseAddr, 32, 64). + Insert(builder). + Return() + address = builder.AllocateInstruction(). + AsIadd(memBase, extBaseAddr).Insert(builder).Return() + known.absoluteAddr = address // Update the absolute address for the subsequent memory access. + } + return + } + } + + ceilConst := builder.AllocateInstruction() + ceilConst.AsIconst64(ceil) + builder.InsertInstruction(ceilConst) + + // We calculate the offset in 64-bit space. + extBaseAddr := builder.AllocateInstruction(). + AsUExtend(baseAddr, 32, 64). + Insert(builder). + Return() + + // Note: memLen is already zero extended to 64-bit space at the load time. + memLen := c.getMemoryLenValue(false) + + // baseAddrPlusCeil = baseAddr + ceil + baseAddrPlusCeil := builder.AllocateInstruction() + baseAddrPlusCeil.AsIadd(extBaseAddr, ceilConst.Return()) + builder.InsertInstruction(baseAddrPlusCeil) + + // Check for out of bounds memory access: `memLen >= baseAddrPlusCeil`. + cmp := builder.AllocateInstruction() + cmp.AsIcmp(memLen, baseAddrPlusCeil.Return(), ssa.IntegerCmpCondUnsignedLessThan) + builder.InsertInstruction(cmp) + exitIfNZ := builder.AllocateInstruction() + exitIfNZ.AsExitIfTrueWithCode(c.execCtxPtrValue, cmp.Return(), wazevoapi.ExitCodeMemoryOutOfBounds) + builder.InsertInstruction(exitIfNZ) + + // Load the value from memBase + extBaseAddr. + if address == ssa.ValueInvalid { // Reuse the value if the memBase is already calculated at this point. + memBase := c.getMemoryBaseValue(false) + address = builder.AllocateInstruction(). + AsIadd(memBase, extBaseAddr).Insert(builder).Return() + } + + // Record the bound ceil for this baseAddr is known to be safe for the subsequent memory access in the same block. + c.recordKnownSafeBound(baseAddrID, ceil, address) + return +} + +// atomicMemOpSetup inserts the bounds check and calculates the address of the memory operation (loads/stores), including +// the constant offset and performs an alignment check on the final address. +func (c *Compiler) atomicMemOpSetup(baseAddr ssa.Value, constOffset, operationSizeInBytes uint64) (address ssa.Value) { + builder := c.ssaBuilder + + addrWithoutOffset := c.memOpSetup(baseAddr, constOffset, operationSizeInBytes) + var addr ssa.Value + if constOffset == 0 { + addr = addrWithoutOffset + } else { + offset := builder.AllocateInstruction().AsIconst64(constOffset).Insert(builder).Return() + addr = builder.AllocateInstruction().AsIadd(addrWithoutOffset, offset).Insert(builder).Return() + } + + c.memAlignmentCheck(addr, operationSizeInBytes) + + return addr +} + +func (c *Compiler) memAlignmentCheck(addr ssa.Value, operationSizeInBytes uint64) { + if operationSizeInBytes == 1 { + return // No alignment restrictions when accessing a byte + } + var checkBits uint64 + switch operationSizeInBytes { + case 2: + checkBits = 0b1 + case 4: + checkBits = 0b11 + case 8: + checkBits = 0b111 + } + + builder := c.ssaBuilder + + mask := builder.AllocateInstruction().AsIconst64(checkBits).Insert(builder).Return() + masked := builder.AllocateInstruction().AsBand(addr, mask).Insert(builder).Return() + zero := builder.AllocateInstruction().AsIconst64(0).Insert(builder).Return() + cmp := builder.AllocateInstruction().AsIcmp(masked, zero, ssa.IntegerCmpCondNotEqual).Insert(builder).Return() + builder.AllocateInstruction().AsExitIfTrueWithCode(c.execCtxPtrValue, cmp, wazevoapi.ExitCodeUnalignedAtomic).Insert(builder) +} + +func (c *Compiler) callMemmove(dst, src, size ssa.Value) { + args := c.allocateVarLengthValues(3, dst, src, size) + if size.Type() != ssa.TypeI64 { + panic("TODO: memmove size must be i64") + } + + builder := c.ssaBuilder + memmovePtr := builder.AllocateInstruction(). + AsLoad(c.execCtxPtrValue, + wazevoapi.ExecutionContextOffsetMemmoveAddress.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + builder.AllocateInstruction().AsCallGoRuntimeMemmove(memmovePtr, &c.memmoveSig, args).Insert(builder) +} + +func (c *Compiler) reloadAfterCall() { + // Note that when these are not used in the following instructions, they will be optimized out. + // So in any ways, we define them! + + // After calling any function, memory buffer might have changed. So we need to re-define the variable. + // However, if the memory is shared, we don't need to reload the memory base and length as the base will never change. + if c.needMemory && !c.memoryShared { + c.reloadMemoryBaseLen() + } + + // Also, any mutable Global can change. + for _, index := range c.mutableGlobalVariablesIndexes { + _ = c.getWasmGlobalValue(index, true) + } +} + +func (c *Compiler) reloadMemoryBaseLen() { + _ = c.getMemoryBaseValue(true) + _ = c.getMemoryLenValue(true) + + // This function being called means that the memory base might have changed. + // Therefore, we need to clear the absolute addresses recorded in the known safe bounds + // because we cache the absolute address of the memory access per each base offset. + c.resetAbsoluteAddressInSafeBounds() +} + +func (c *Compiler) setWasmGlobalValue(index wasm.Index, v ssa.Value) { + variable := c.globalVariables[index] + opaqueOffset := c.offset.GlobalInstanceOffset(index) + + builder := c.ssaBuilder + if index < c.m.ImportGlobalCount { + loadGlobalInstPtr := builder.AllocateInstruction() + loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), ssa.TypeI64) + builder.InsertInstruction(loadGlobalInstPtr) + + store := builder.AllocateInstruction() + store.AsStore(ssa.OpcodeStore, v, loadGlobalInstPtr.Return(), uint32(0)) + builder.InsertInstruction(store) + + } else { + store := builder.AllocateInstruction() + store.AsStore(ssa.OpcodeStore, v, c.moduleCtxPtrValue, uint32(opaqueOffset)) + builder.InsertInstruction(store) + } + + // The value has changed to `v`, so we record it. + builder.DefineVariableInCurrentBB(variable, v) +} + +func (c *Compiler) getWasmGlobalValue(index wasm.Index, forceLoad bool) ssa.Value { + variable := c.globalVariables[index] + typ := c.globalVariablesTypes[index] + opaqueOffset := c.offset.GlobalInstanceOffset(index) + + builder := c.ssaBuilder + if !forceLoad { + if v := builder.FindValueInLinearPath(variable); v.Valid() { + return v + } + } + + var load *ssa.Instruction + if index < c.m.ImportGlobalCount { + loadGlobalInstPtr := builder.AllocateInstruction() + loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), ssa.TypeI64) + builder.InsertInstruction(loadGlobalInstPtr) + load = builder.AllocateInstruction(). + AsLoad(loadGlobalInstPtr.Return(), uint32(0), typ) + } else { + load = builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), typ) + } + + v := load.Insert(builder).Return() + builder.DefineVariableInCurrentBB(variable, v) + return v +} + +const ( + memoryInstanceBufOffset = 0 + memoryInstanceBufSizeOffset = memoryInstanceBufOffset + 8 +) + +func (c *Compiler) getMemoryBaseValue(forceReload bool) ssa.Value { + builder := c.ssaBuilder + variable := c.memoryBaseVariable + if !forceReload { + if v := builder.FindValueInLinearPath(variable); v.Valid() { + return v + } + } + + var ret ssa.Value + if c.offset.LocalMemoryBegin < 0 { + loadMemInstPtr := builder.AllocateInstruction() + loadMemInstPtr.AsLoad(c.moduleCtxPtrValue, c.offset.ImportedMemoryBegin.U32(), ssa.TypeI64) + builder.InsertInstruction(loadMemInstPtr) + memInstPtr := loadMemInstPtr.Return() + + loadBufPtr := builder.AllocateInstruction() + loadBufPtr.AsLoad(memInstPtr, memoryInstanceBufOffset, ssa.TypeI64) + builder.InsertInstruction(loadBufPtr) + ret = loadBufPtr.Return() + } else { + load := builder.AllocateInstruction() + load.AsLoad(c.moduleCtxPtrValue, c.offset.LocalMemoryBase().U32(), ssa.TypeI64) + builder.InsertInstruction(load) + ret = load.Return() + } + + builder.DefineVariableInCurrentBB(variable, ret) + return ret +} + +func (c *Compiler) getMemoryLenValue(forceReload bool) ssa.Value { + variable := c.memoryLenVariable + builder := c.ssaBuilder + if !forceReload && !c.memoryShared { + if v := builder.FindValueInLinearPath(variable); v.Valid() { + return v + } + } + + var ret ssa.Value + if c.offset.LocalMemoryBegin < 0 { + loadMemInstPtr := builder.AllocateInstruction() + loadMemInstPtr.AsLoad(c.moduleCtxPtrValue, c.offset.ImportedMemoryBegin.U32(), ssa.TypeI64) + builder.InsertInstruction(loadMemInstPtr) + memInstPtr := loadMemInstPtr.Return() + + loadBufSizePtr := builder.AllocateInstruction() + if c.memoryShared { + sizeOffset := builder.AllocateInstruction().AsIconst64(memoryInstanceBufSizeOffset).Insert(builder).Return() + addr := builder.AllocateInstruction().AsIadd(memInstPtr, sizeOffset).Insert(builder).Return() + loadBufSizePtr.AsAtomicLoad(addr, 8, ssa.TypeI64) + } else { + loadBufSizePtr.AsLoad(memInstPtr, memoryInstanceBufSizeOffset, ssa.TypeI64) + } + builder.InsertInstruction(loadBufSizePtr) + + ret = loadBufSizePtr.Return() + } else { + load := builder.AllocateInstruction() + if c.memoryShared { + lenOffset := builder.AllocateInstruction().AsIconst64(c.offset.LocalMemoryLen().U64()).Insert(builder).Return() + addr := builder.AllocateInstruction().AsIadd(c.moduleCtxPtrValue, lenOffset).Insert(builder).Return() + load.AsAtomicLoad(addr, 8, ssa.TypeI64) + } else { + load.AsExtLoad(ssa.OpcodeUload32, c.moduleCtxPtrValue, c.offset.LocalMemoryLen().U32(), true) + } + builder.InsertInstruction(load) + ret = load.Return() + } + + builder.DefineVariableInCurrentBB(variable, ret) + return ret +} + +func (c *Compiler) insertIcmp(cond ssa.IntegerCmpCond) { + state, builder := c.state(), c.ssaBuilder + y, x := state.pop(), state.pop() + cmp := builder.AllocateInstruction() + cmp.AsIcmp(x, y, cond) + builder.InsertInstruction(cmp) + value := cmp.Return() + state.push(value) +} + +func (c *Compiler) insertFcmp(cond ssa.FloatCmpCond) { + state, builder := c.state(), c.ssaBuilder + y, x := state.pop(), state.pop() + cmp := builder.AllocateInstruction() + cmp.AsFcmp(x, y, cond) + builder.InsertInstruction(cmp) + value := cmp.Return() + state.push(value) +} + +// storeCallerModuleContext stores the current module's moduleContextPtr into execContext.callerModuleContextPtr. +func (c *Compiler) storeCallerModuleContext() { + builder := c.ssaBuilder + execCtx := c.execCtxPtrValue + store := builder.AllocateInstruction() + store.AsStore(ssa.OpcodeStore, + c.moduleCtxPtrValue, execCtx, wazevoapi.ExecutionContextOffsetCallerModuleContextPtr.U32()) + builder.InsertInstruction(store) +} + +func (c *Compiler) readByte() byte { + v := c.wasmFunctionBody[c.loweringState.pc+1] + c.loweringState.pc++ + return v +} + +func (c *Compiler) readI32u() uint32 { + v, n, err := leb128.LoadUint32(c.wasmFunctionBody[c.loweringState.pc+1:]) + if err != nil { + panic(err) // shouldn't be reached since compilation comes after validation. + } + c.loweringState.pc += int(n) + return v +} + +func (c *Compiler) readI32s() int32 { + v, n, err := leb128.LoadInt32(c.wasmFunctionBody[c.loweringState.pc+1:]) + if err != nil { + panic(err) // shouldn't be reached since compilation comes after validation. + } + c.loweringState.pc += int(n) + return v +} + +func (c *Compiler) readI64s() int64 { + v, n, err := leb128.LoadInt64(c.wasmFunctionBody[c.loweringState.pc+1:]) + if err != nil { + panic(err) // shouldn't be reached since compilation comes after validation. + } + c.loweringState.pc += int(n) + return v +} + +func (c *Compiler) readF32() float32 { + v := math.Float32frombits(binary.LittleEndian.Uint32(c.wasmFunctionBody[c.loweringState.pc+1:])) + c.loweringState.pc += 4 + return v +} + +func (c *Compiler) readF64() float64 { + v := math.Float64frombits(binary.LittleEndian.Uint64(c.wasmFunctionBody[c.loweringState.pc+1:])) + c.loweringState.pc += 8 + return v +} + +// readBlockType reads the block type from the current position of the bytecode reader. +func (c *Compiler) readBlockType() *wasm.FunctionType { + state := c.state() + + c.br.Reset(c.wasmFunctionBody[state.pc+1:]) + bt, num, err := wasm.DecodeBlockType(c.m.TypeSection, c.br, api.CoreFeaturesV2) + if err != nil { + panic(err) // shouldn't be reached since compilation comes after validation. + } + state.pc += int(num) + + return bt +} + +func (c *Compiler) readMemArg() (align, offset uint32) { + state := c.state() + + align, num, err := leb128.LoadUint32(c.wasmFunctionBody[state.pc+1:]) + if err != nil { + panic(fmt.Errorf("read memory align: %v", err)) + } + + state.pc += int(num) + offset, num, err = leb128.LoadUint32(c.wasmFunctionBody[state.pc+1:]) + if err != nil { + panic(fmt.Errorf("read memory offset: %v", err)) + } + + state.pc += int(num) + return align, offset +} + +// insertJumpToBlock inserts a jump instruction to the given block in the current block. +func (c *Compiler) insertJumpToBlock(args ssa.Values, targetBlk ssa.BasicBlock) { + if targetBlk.ReturnBlock() { + if c.needListener { + c.callListenerAfter() + } + } + + builder := c.ssaBuilder + jmp := builder.AllocateInstruction() + jmp.AsJump(args, targetBlk) + builder.InsertInstruction(jmp) +} + +func (c *Compiler) insertIntegerExtend(signed bool, from, to byte) { + state := c.state() + builder := c.ssaBuilder + v := state.pop() + extend := builder.AllocateInstruction() + if signed { + extend.AsSExtend(v, from, to) + } else { + extend.AsUExtend(v, from, to) + } + builder.InsertInstruction(extend) + value := extend.Return() + state.push(value) +} + +func (c *Compiler) switchTo(originalStackLen int, targetBlk ssa.BasicBlock) { + if targetBlk.Preds() == 0 { + c.loweringState.unreachable = true + } + + // Now we should adjust the stack and start translating the continuation block. + c.loweringState.values = c.loweringState.values[:originalStackLen] + + c.ssaBuilder.SetCurrentBlock(targetBlk) + + // At this point, blocks params consist only of the Wasm-level parameters, + // (since it's added only when we are trying to resolve variable *inside* this block). + for i := 0; i < targetBlk.Params(); i++ { + value := targetBlk.Param(i) + c.loweringState.push(value) + } +} + +// results returns the number of results of the current function. +func (c *Compiler) results() int { + return len(c.wasmFunctionTyp.Results) +} + +func (c *Compiler) lowerBrTable(labels []uint32, index ssa.Value) { + state := c.state() + builder := c.ssaBuilder + + f := state.ctrlPeekAt(int(labels[0])) + var numArgs int + if f.isLoop() { + numArgs = len(f.blockType.Params) + } else { + numArgs = len(f.blockType.Results) + } + + varPool := builder.VarLengthPool() + trampolineBlockIDs := varPool.Allocate(len(labels)) + + // We need trampoline blocks since depending on the target block structure, we might end up inserting moves before jumps, + // which cannot be done with br_table. Instead, we can do such per-block moves in the trampoline blocks. + // At the linking phase (very end of the backend), we can remove the unnecessary jumps, and therefore no runtime overhead. + currentBlk := builder.CurrentBlock() + for _, l := range labels { + // Args are always on the top of the stack. Note that we should not share the args slice + // among the jump instructions since the args are modified during passes (e.g. redundant phi elimination). + args := c.nPeekDup(numArgs) + targetBlk, _ := state.brTargetArgNumFor(l) + trampoline := builder.AllocateBasicBlock() + builder.SetCurrentBlock(trampoline) + c.insertJumpToBlock(args, targetBlk) + trampolineBlockIDs = trampolineBlockIDs.Append(builder.VarLengthPool(), ssa.Value(trampoline.ID())) + } + builder.SetCurrentBlock(currentBlk) + + // If the target block has no arguments, we can just jump to the target block. + brTable := builder.AllocateInstruction() + brTable.AsBrTable(index, trampolineBlockIDs) + builder.InsertInstruction(brTable) + + for _, trampolineID := range trampolineBlockIDs.View() { + builder.Seal(builder.BasicBlock(ssa.BasicBlockID(trampolineID))) + } +} + +func (l *loweringState) brTargetArgNumFor(labelIndex uint32) (targetBlk ssa.BasicBlock, argNum int) { + targetFrame := l.ctrlPeekAt(int(labelIndex)) + if targetFrame.isLoop() { + targetBlk, argNum = targetFrame.blk, len(targetFrame.blockType.Params) + } else { + targetBlk, argNum = targetFrame.followingBlock, len(targetFrame.blockType.Results) + } + return +} + +func (c *Compiler) callListenerBefore() { + c.storeCallerModuleContext() + + builder := c.ssaBuilder + beforeListeners1stElement := builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, + c.offset.BeforeListenerTrampolines1stElement.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + beforeListenerPtr := builder.AllocateInstruction(). + AsLoad(beforeListeners1stElement, uint32(c.wasmFunctionTypeIndex)*8 /* 8 bytes per index */, ssa.TypeI64).Insert(builder).Return() + + entry := builder.EntryBlock() + ps := entry.Params() + + args := c.allocateVarLengthValues(ps, c.execCtxPtrValue, + builder.AllocateInstruction().AsIconst32(c.wasmLocalFunctionIndex).Insert(builder).Return()) + for i := 2; i < ps; i++ { + args = args.Append(builder.VarLengthPool(), entry.Param(i)) + } + + beforeSig := c.listenerSignatures[c.wasmFunctionTyp][0] + builder.AllocateInstruction(). + AsCallIndirect(beforeListenerPtr, beforeSig, args). + Insert(builder) +} + +func (c *Compiler) callListenerAfter() { + c.storeCallerModuleContext() + + builder := c.ssaBuilder + afterListeners1stElement := builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, + c.offset.AfterListenerTrampolines1stElement.U32(), + ssa.TypeI64, + ).Insert(builder).Return() + + afterListenerPtr := builder.AllocateInstruction(). + AsLoad(afterListeners1stElement, + uint32(c.wasmFunctionTypeIndex)*8 /* 8 bytes per index */, ssa.TypeI64). + Insert(builder). + Return() + + afterSig := c.listenerSignatures[c.wasmFunctionTyp][1] + args := c.allocateVarLengthValues( + c.results()+2, + c.execCtxPtrValue, + builder.AllocateInstruction().AsIconst32(c.wasmLocalFunctionIndex).Insert(builder).Return(), + ) + + l := c.state() + tail := len(l.values) + args = args.Append(c.ssaBuilder.VarLengthPool(), l.values[tail-c.results():tail]...) + builder.AllocateInstruction(). + AsCallIndirect(afterListenerPtr, afterSig, args). + Insert(builder) +} + +const ( + elementOrDataInstanceLenOffset = 8 + elementOrDataInstanceSize = 24 +) + +// dropInstance inserts instructions to drop the element/data instance specified by the given index. +func (c *Compiler) dropDataOrElementInstance(index uint32, firstItemOffset wazevoapi.Offset) { + builder := c.ssaBuilder + instPtr := c.dataOrElementInstanceAddr(index, firstItemOffset) + + zero := builder.AllocateInstruction().AsIconst64(0).Insert(builder).Return() + + // Clear the instance. + builder.AllocateInstruction().AsStore(ssa.OpcodeStore, zero, instPtr, 0).Insert(builder) + builder.AllocateInstruction().AsStore(ssa.OpcodeStore, zero, instPtr, elementOrDataInstanceLenOffset).Insert(builder) + builder.AllocateInstruction().AsStore(ssa.OpcodeStore, zero, instPtr, elementOrDataInstanceLenOffset+8).Insert(builder) +} + +func (c *Compiler) dataOrElementInstanceAddr(index uint32, firstItemOffset wazevoapi.Offset) ssa.Value { + builder := c.ssaBuilder + + _1stItemPtr := builder. + AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, firstItemOffset.U32(), ssa.TypeI64). + Insert(builder).Return() + + // Each data/element instance is a slice, so we need to multiply index by 16 to get the offset of the target instance. + index = index * elementOrDataInstanceSize + indexExt := builder.AllocateInstruction().AsIconst64(uint64(index)).Insert(builder).Return() + // Then, add the offset to the address of the instance. + instPtr := builder.AllocateInstruction().AsIadd(_1stItemPtr, indexExt).Insert(builder).Return() + return instPtr +} + +func (c *Compiler) boundsCheckInDataOrElementInstance(instPtr, offsetInInstance, copySize ssa.Value, exitCode wazevoapi.ExitCode) { + builder := c.ssaBuilder + dataInstLen := builder.AllocateInstruction(). + AsLoad(instPtr, elementOrDataInstanceLenOffset, ssa.TypeI64). + Insert(builder).Return() + ceil := builder.AllocateInstruction().AsIadd(offsetInInstance, copySize).Insert(builder).Return() + cmp := builder.AllocateInstruction(). + AsIcmp(dataInstLen, ceil, ssa.IntegerCmpCondUnsignedLessThan). + Insert(builder). + Return() + builder.AllocateInstruction(). + AsExitIfTrueWithCode(c.execCtxPtrValue, cmp, exitCode). + Insert(builder) +} + +func (c *Compiler) boundsCheckInTable(tableIndex uint32, offset, size ssa.Value) (tableInstancePtr ssa.Value) { + builder := c.ssaBuilder + dstCeil := builder.AllocateInstruction().AsIadd(offset, size).Insert(builder).Return() + + // Load the table. + tableInstancePtr = builder.AllocateInstruction(). + AsLoad(c.moduleCtxPtrValue, c.offset.TableOffset(int(tableIndex)).U32(), ssa.TypeI64). + Insert(builder).Return() + + // Load the table's length. + tableLen := builder.AllocateInstruction(). + AsLoad(tableInstancePtr, tableInstanceLenOffset, ssa.TypeI32).Insert(builder).Return() + tableLenExt := builder.AllocateInstruction().AsUExtend(tableLen, 32, 64).Insert(builder).Return() + + // Compare the length and the target, and trap if out of bounds. + checkOOB := builder.AllocateInstruction() + checkOOB.AsIcmp(tableLenExt, dstCeil, ssa.IntegerCmpCondUnsignedLessThan) + builder.InsertInstruction(checkOOB) + exitIfOOB := builder.AllocateInstruction() + exitIfOOB.AsExitIfTrueWithCode(c.execCtxPtrValue, checkOOB.Return(), wazevoapi.ExitCodeTableOutOfBounds) + builder.InsertInstruction(exitIfOOB) + return +} + +func (c *Compiler) loadTableBaseAddr(tableInstancePtr ssa.Value) ssa.Value { + builder := c.ssaBuilder + loadTableBaseAddress := builder. + AllocateInstruction(). + AsLoad(tableInstancePtr, tableInstanceBaseAddressOffset, ssa.TypeI64). + Insert(builder) + return loadTableBaseAddress.Return() +} + +func (c *Compiler) boundsCheckInMemory(memLen, offset, size ssa.Value) { + builder := c.ssaBuilder + ceil := builder.AllocateInstruction().AsIadd(offset, size).Insert(builder).Return() + cmp := builder.AllocateInstruction(). + AsIcmp(memLen, ceil, ssa.IntegerCmpCondUnsignedLessThan). + Insert(builder). + Return() + builder.AllocateInstruction(). + AsExitIfTrueWithCode(c.execCtxPtrValue, cmp, wazevoapi.ExitCodeMemoryOutOfBounds). + Insert(builder) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/misc.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/misc.go new file mode 100644 index 00000000..2db2b892 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/misc.go @@ -0,0 +1,10 @@ +package frontend + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func FunctionIndexToFuncRef(idx wasm.Index) ssa.FuncRef { + return ssa.FuncRef(idx) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/sort_id.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/sort_id.go new file mode 100644 index 00000000..5b055d12 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/frontend/sort_id.go @@ -0,0 +1,13 @@ +package frontend + +import ( + "slices" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" +) + +func sortSSAValueIDs(IDs []ssa.ValueID) { + slices.SortFunc(IDs, func(i, j ssa.ValueID) int { + return int(i) - int(j) + }) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/hostmodule.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/hostmodule.go new file mode 100644 index 00000000..800a5d2a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/hostmodule.go @@ -0,0 +1,88 @@ +package wazevo + +import ( + "encoding/binary" + "reflect" + "unsafe" + + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func buildHostModuleOpaque(m *wasm.Module, listeners []experimental.FunctionListener) moduleContextOpaque { + size := len(m.CodeSection)*16 + 32 + ret := newAlignedOpaque(size) + + binary.LittleEndian.PutUint64(ret[0:], uint64(uintptr(unsafe.Pointer(m)))) + + if len(listeners) > 0 { + //nolint:staticcheck + sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&listeners)) + binary.LittleEndian.PutUint64(ret[8:], uint64(sliceHeader.Data)) + binary.LittleEndian.PutUint64(ret[16:], uint64(sliceHeader.Len)) + binary.LittleEndian.PutUint64(ret[24:], uint64(sliceHeader.Cap)) + } + + offset := 32 + for i := range m.CodeSection { + goFn := m.CodeSection[i].GoFunc + writeIface(goFn, ret[offset:]) + offset += 16 + } + return ret +} + +func hostModuleFromOpaque(opaqueBegin uintptr) *wasm.Module { + var opaqueViewOverSlice []byte + //nolint:staticcheck + sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice)) + sh.Data = opaqueBegin + sh.Len = 32 + sh.Cap = 32 + return *(**wasm.Module)(unsafe.Pointer(&opaqueViewOverSlice[0])) +} + +func hostModuleListenersSliceFromOpaque(opaqueBegin uintptr) []experimental.FunctionListener { + var opaqueViewOverSlice []byte + //nolint:staticcheck + sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice)) + sh.Data = opaqueBegin + sh.Len = 32 + sh.Cap = 32 + + b := binary.LittleEndian.Uint64(opaqueViewOverSlice[8:]) + l := binary.LittleEndian.Uint64(opaqueViewOverSlice[16:]) + c := binary.LittleEndian.Uint64(opaqueViewOverSlice[24:]) + var ret []experimental.FunctionListener + //nolint:staticcheck + sh = (*reflect.SliceHeader)(unsafe.Pointer(&ret)) + sh.Data = uintptr(b) + sh.Len = int(l) + sh.Cap = int(c) + return ret +} + +func hostModuleGoFuncFromOpaque[T any](index int, opaqueBegin uintptr) T { + offset := uintptr(index*16) + 32 + ptr := opaqueBegin + offset + + var opaqueViewOverFunction []byte + //nolint:staticcheck + sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverFunction)) + sh.Data = ptr + sh.Len = 16 + sh.Cap = 16 + return readIface(opaqueViewOverFunction).(T) +} + +func writeIface(goFn interface{}, buf []byte) { + goFnIface := *(*[2]uint64)(unsafe.Pointer(&goFn)) + binary.LittleEndian.PutUint64(buf, goFnIface[0]) + binary.LittleEndian.PutUint64(buf[8:], goFnIface[1]) +} + +func readIface(buf []byte) interface{} { + b := binary.LittleEndian.Uint64(buf) + s := binary.LittleEndian.Uint64(buf[8:]) + return *(*interface{})(unsafe.Pointer(&[2]uint64{b, s})) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_amd64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_amd64.go new file mode 100644 index 00000000..da27cc10 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_amd64.go @@ -0,0 +1,30 @@ +//go:build amd64 + +package wazevo + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64" +) + +func newMachine() backend.Machine { + return amd64.NewBackend() +} + +// unwindStack is a function to unwind the stack, and appends return addresses to `returnAddresses` slice. +// The implementation must be aligned with the ABI/Calling convention. +func unwindStack(sp, fp, top uintptr, returnAddresses []uintptr) []uintptr { + return amd64.UnwindStack(sp, fp, top, returnAddresses) +} + +// goCallStackView is a function to get a view of the stack before a Go call, which +// is the view of the stack allocated in CompileGoFunctionTrampoline. +func goCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { + return amd64.GoCallStackView(stackPointerBeforeGoCall) +} + +// adjustClonedStack is a function to adjust the stack after it is grown. +// More precisely, absolute addresses (frame pointers) in the stack must be adjusted. +func adjustClonedStack(oldsp, oldTop, sp, fp, top uintptr) { + amd64.AdjustClonedStack(oldsp, oldTop, sp, fp, top) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_arm64.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_arm64.go new file mode 100644 index 00000000..e7a84654 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_arm64.go @@ -0,0 +1,32 @@ +//go:build arm64 + +package wazevo + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64" +) + +func newMachine() backend.Machine { + return arm64.NewBackend() +} + +// unwindStack is a function to unwind the stack, and appends return addresses to `returnAddresses` slice. +// The implementation must be aligned with the ABI/Calling convention. +func unwindStack(sp, fp, top uintptr, returnAddresses []uintptr) []uintptr { + return arm64.UnwindStack(sp, fp, top, returnAddresses) +} + +// goCallStackView is a function to get a view of the stack before a Go call, which +// is the view of the stack allocated in CompileGoFunctionTrampoline. +func goCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { + return arm64.GoCallStackView(stackPointerBeforeGoCall) +} + +// adjustClonedStack is a function to adjust the stack after it is grown. +// More precisely, absolute addresses (frame pointers) in the stack must be adjusted. +func adjustClonedStack(oldsp, oldTop, sp, fp, top uintptr) { + // TODO: currently, the frame pointers are not used, and saved old sps are relative to the current stack pointer, + // so no need to adjustment on arm64. However, when we make it absolute, which in my opinion is better perf-wise + // at the expense of slightly costly stack growth, we need to adjust the pushed frame pointers. +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_other.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_other.go new file mode 100644 index 00000000..c5afc631 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/isa_other.go @@ -0,0 +1,29 @@ +//go:build !(amd64 || arm64) + +package wazevo + +import ( + "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" +) + +func newMachine() backend.Machine { + panic("unsupported architecture") +} + +// unwindStack is a function to unwind the stack, and appends return addresses to `returnAddresses` slice. +// The implementation must be aligned with the ABI/Calling convention. +func unwindStack(sp, fp, top uintptr, returnAddresses []uintptr) []uintptr { + panic("unsupported architecture") +} + +// goCallStackView is a function to get a view of the stack before a Go call, which +// is the view of the stack allocated in CompileGoFunctionTrampoline. +func goCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { + panic("unsupported architecture") +} + +// adjustClonedStack is a function to adjust the stack after it is grown. +// More precisely, absolute addresses (frame pointers) in the stack must be adjusted. +func adjustClonedStack(oldsp, oldTop, sp, fp, top uintptr) { + panic("unsupported architecture") +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/memmove.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/memmove.go new file mode 100644 index 00000000..88992210 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/memmove.go @@ -0,0 +1,11 @@ +package wazevo + +import ( + "reflect" + "unsafe" +) + +//go:linkname memmove runtime.memmove +func memmove(_, _ unsafe.Pointer, _ uintptr) + +var memmovPtr = reflect.ValueOf(memmove).Pointer() diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/module_engine.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/module_engine.go new file mode 100644 index 00000000..8811feed --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/module_engine.go @@ -0,0 +1,331 @@ +package wazevo + +import ( + "encoding/binary" + "unsafe" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasmruntime" +) + +type ( + // moduleEngine implements wasm.ModuleEngine. + moduleEngine struct { + // opaquePtr equals &opaque[0]. + opaquePtr *byte + parent *compiledModule + module *wasm.ModuleInstance + opaque moduleContextOpaque + localFunctionInstances []*functionInstance + importedFunctions []importedFunction + listeners []experimental.FunctionListener + } + + functionInstance struct { + executable *byte + moduleContextOpaquePtr *byte + typeID wasm.FunctionTypeID + indexInModule wasm.Index + } + + importedFunction struct { + me *moduleEngine + indexInModule wasm.Index + } + + // moduleContextOpaque is the opaque byte slice of Module instance specific contents whose size + // is only Wasm-compile-time known, hence dynamic. Its contents are basically the pointers to the module instance, + // specific objects as well as functions. This is sometimes called "VMContext" in other Wasm runtimes. + // + // Internally, the buffer is structured as follows: + // + // type moduleContextOpaque struct { + // moduleInstance *wasm.ModuleInstance + // localMemoryBufferPtr *byte (optional) + // localMemoryLength uint64 (optional) + // importedMemoryInstance *wasm.MemoryInstance (optional) + // importedMemoryOwnerOpaqueCtx *byte (optional) + // importedFunctions [# of importedFunctions]functionInstance + // importedGlobals []ImportedGlobal (optional) + // localGlobals []Global (optional) + // typeIDsBegin &wasm.ModuleInstance.TypeIDs[0] (optional) + // tables []*wasm.TableInstance (optional) + // beforeListenerTrampolines1stElement **byte (optional) + // afterListenerTrampolines1stElement **byte (optional) + // dataInstances1stElement []wasm.DataInstance (optional) + // elementInstances1stElement []wasm.ElementInstance (optional) + // } + // + // type ImportedGlobal struct { + // *Global + // _ uint64 // padding + // } + // + // type Global struct { + // Val, ValHi uint64 + // } + // + // See wazevoapi.NewModuleContextOffsetData for the details of the offsets. + // + // Note that for host modules, the structure is entirely different. See buildHostModuleOpaque. + moduleContextOpaque []byte +) + +func newAlignedOpaque(size int) moduleContextOpaque { + // Check if the size is a multiple of 16. + if size%16 != 0 { + panic("size must be a multiple of 16") + } + buf := make([]byte, size+16) + // Align the buffer to 16 bytes. + rem := uintptr(unsafe.Pointer(&buf[0])) % 16 + buf = buf[16-rem:] + return buf +} + +func (m *moduleEngine) setupOpaque() { + inst := m.module + offsets := &m.parent.offsets + opaque := m.opaque + + binary.LittleEndian.PutUint64(opaque[offsets.ModuleInstanceOffset:], + uint64(uintptr(unsafe.Pointer(m.module))), + ) + + if lm := offsets.LocalMemoryBegin; lm >= 0 { + m.putLocalMemory() + } + + // Note: imported memory is resolved in ResolveImportedFunction. + + // Note: imported functions are resolved in ResolveImportedFunction. + + if globalOffset := offsets.GlobalsBegin; globalOffset >= 0 { + for i, g := range inst.Globals { + if i < int(inst.Source.ImportGlobalCount) { + importedME := g.Me.(*moduleEngine) + offset := importedME.parent.offsets.GlobalInstanceOffset(g.Index) + importedMEOpaque := importedME.opaque + binary.LittleEndian.PutUint64(opaque[globalOffset:], + uint64(uintptr(unsafe.Pointer(&importedMEOpaque[offset])))) + } else { + binary.LittleEndian.PutUint64(opaque[globalOffset:], g.Val) + binary.LittleEndian.PutUint64(opaque[globalOffset+8:], g.ValHi) + } + globalOffset += 16 + } + } + + if tableOffset := offsets.TablesBegin; tableOffset >= 0 { + // First we write the first element's address of typeIDs. + if len(inst.TypeIDs) > 0 { + binary.LittleEndian.PutUint64(opaque[offsets.TypeIDs1stElement:], uint64(uintptr(unsafe.Pointer(&inst.TypeIDs[0])))) + } + + // Then we write the table addresses. + for _, table := range inst.Tables { + binary.LittleEndian.PutUint64(opaque[tableOffset:], uint64(uintptr(unsafe.Pointer(table)))) + tableOffset += 8 + } + } + + if beforeListenerOffset := offsets.BeforeListenerTrampolines1stElement; beforeListenerOffset >= 0 { + binary.LittleEndian.PutUint64(opaque[beforeListenerOffset:], uint64(uintptr(unsafe.Pointer(&m.parent.listenerBeforeTrampolines[0])))) + } + if afterListenerOffset := offsets.AfterListenerTrampolines1stElement; afterListenerOffset >= 0 { + binary.LittleEndian.PutUint64(opaque[afterListenerOffset:], uint64(uintptr(unsafe.Pointer(&m.parent.listenerAfterTrampolines[0])))) + } + if len(inst.DataInstances) > 0 { + binary.LittleEndian.PutUint64(opaque[offsets.DataInstances1stElement:], uint64(uintptr(unsafe.Pointer(&inst.DataInstances[0])))) + } + if len(inst.ElementInstances) > 0 { + binary.LittleEndian.PutUint64(opaque[offsets.ElementInstances1stElement:], uint64(uintptr(unsafe.Pointer(&inst.ElementInstances[0])))) + } +} + +// NewFunction implements wasm.ModuleEngine. +func (m *moduleEngine) NewFunction(index wasm.Index) api.Function { + if wazevoapi.PrintMachineCodeHexPerFunctionDisassemblable { + panic("When PrintMachineCodeHexPerFunctionDisassemblable enabled, functions must not be called") + } + + localIndex := index + if importedFnCount := m.module.Source.ImportFunctionCount; index < importedFnCount { + imported := &m.importedFunctions[index] + return imported.me.NewFunction(imported.indexInModule) + } else { + localIndex -= importedFnCount + } + + src := m.module.Source + typIndex := src.FunctionSection[localIndex] + typ := src.TypeSection[typIndex] + sizeOfParamResultSlice := typ.ResultNumInUint64 + if ps := typ.ParamNumInUint64; ps > sizeOfParamResultSlice { + sizeOfParamResultSlice = ps + } + p := m.parent + offset := p.functionOffsets[localIndex] + + ce := &callEngine{ + indexInModule: index, + executable: &p.executable[offset], + parent: m, + preambleExecutable: &m.parent.entryPreambles[typIndex][0], + sizeOfParamResultSlice: sizeOfParamResultSlice, + requiredParams: typ.ParamNumInUint64, + numberOfResults: typ.ResultNumInUint64, + } + + ce.execCtx.memoryGrowTrampolineAddress = &m.parent.sharedFunctions.memoryGrowExecutable[0] + ce.execCtx.stackGrowCallTrampolineAddress = &m.parent.sharedFunctions.stackGrowExecutable[0] + ce.execCtx.checkModuleExitCodeTrampolineAddress = &m.parent.sharedFunctions.checkModuleExitCode[0] + ce.execCtx.tableGrowTrampolineAddress = &m.parent.sharedFunctions.tableGrowExecutable[0] + ce.execCtx.refFuncTrampolineAddress = &m.parent.sharedFunctions.refFuncExecutable[0] + ce.execCtx.memoryWait32TrampolineAddress = &m.parent.sharedFunctions.memoryWait32Executable[0] + ce.execCtx.memoryWait64TrampolineAddress = &m.parent.sharedFunctions.memoryWait64Executable[0] + ce.execCtx.memoryNotifyTrampolineAddress = &m.parent.sharedFunctions.memoryNotifyExecutable[0] + ce.execCtx.memmoveAddress = memmovPtr + ce.init() + return ce +} + +// GetGlobalValue implements the same method as documented on wasm.ModuleEngine. +func (m *moduleEngine) GetGlobalValue(i wasm.Index) (lo, hi uint64) { + offset := m.parent.offsets.GlobalInstanceOffset(i) + buf := m.opaque[offset:] + if i < m.module.Source.ImportGlobalCount { + panic("GetGlobalValue should not be called for imported globals") + } + return binary.LittleEndian.Uint64(buf), binary.LittleEndian.Uint64(buf[8:]) +} + +// SetGlobalValue implements the same method as documented on wasm.ModuleEngine. +func (m *moduleEngine) SetGlobalValue(i wasm.Index, lo, hi uint64) { + offset := m.parent.offsets.GlobalInstanceOffset(i) + buf := m.opaque[offset:] + if i < m.module.Source.ImportGlobalCount { + panic("GetGlobalValue should not be called for imported globals") + } + binary.LittleEndian.PutUint64(buf, lo) + binary.LittleEndian.PutUint64(buf[8:], hi) +} + +// OwnsGlobals implements the same method as documented on wasm.ModuleEngine. +func (m *moduleEngine) OwnsGlobals() bool { return true } + +// MemoryGrown implements wasm.ModuleEngine. +func (m *moduleEngine) MemoryGrown() { + m.putLocalMemory() +} + +// putLocalMemory writes the local memory buffer pointer and length to the opaque buffer. +func (m *moduleEngine) putLocalMemory() { + mem := m.module.MemoryInstance + offset := m.parent.offsets.LocalMemoryBegin + + s := uint64(len(mem.Buffer)) + var b uint64 + if len(mem.Buffer) > 0 { + b = uint64(uintptr(unsafe.Pointer(&mem.Buffer[0]))) + } + binary.LittleEndian.PutUint64(m.opaque[offset:], b) + binary.LittleEndian.PutUint64(m.opaque[offset+8:], s) +} + +// ResolveImportedFunction implements wasm.ModuleEngine. +func (m *moduleEngine) ResolveImportedFunction(index, descFunc, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) { + executableOffset, moduleCtxOffset, typeIDOffset := m.parent.offsets.ImportedFunctionOffset(index) + importedME := importedModuleEngine.(*moduleEngine) + + if int(indexInImportedModule) >= len(importedME.importedFunctions) { + indexInImportedModule -= wasm.Index(len(importedME.importedFunctions)) + } else { + imported := &importedME.importedFunctions[indexInImportedModule] + m.ResolveImportedFunction(index, descFunc, imported.indexInModule, imported.me) + return // Recursively resolve the imported function. + } + + offset := importedME.parent.functionOffsets[indexInImportedModule] + typeID := m.module.TypeIDs[descFunc] + executable := &importedME.parent.executable[offset] + // Write functionInstance. + binary.LittleEndian.PutUint64(m.opaque[executableOffset:], uint64(uintptr(unsafe.Pointer(executable)))) + binary.LittleEndian.PutUint64(m.opaque[moduleCtxOffset:], uint64(uintptr(unsafe.Pointer(importedME.opaquePtr)))) + binary.LittleEndian.PutUint64(m.opaque[typeIDOffset:], uint64(typeID)) + + // Write importedFunction so that it can be used by NewFunction. + m.importedFunctions[index] = importedFunction{me: importedME, indexInModule: indexInImportedModule} +} + +// ResolveImportedMemory implements wasm.ModuleEngine. +func (m *moduleEngine) ResolveImportedMemory(importedModuleEngine wasm.ModuleEngine) { + importedME := importedModuleEngine.(*moduleEngine) + inst := importedME.module + + var memInstPtr uint64 + var memOwnerOpaquePtr uint64 + if offs := importedME.parent.offsets; offs.ImportedMemoryBegin >= 0 { + offset := offs.ImportedMemoryBegin + memInstPtr = binary.LittleEndian.Uint64(importedME.opaque[offset:]) + memOwnerOpaquePtr = binary.LittleEndian.Uint64(importedME.opaque[offset+8:]) + } else { + memInstPtr = uint64(uintptr(unsafe.Pointer(inst.MemoryInstance))) + memOwnerOpaquePtr = uint64(uintptr(unsafe.Pointer(importedME.opaquePtr))) + } + offset := m.parent.offsets.ImportedMemoryBegin + binary.LittleEndian.PutUint64(m.opaque[offset:], memInstPtr) + binary.LittleEndian.PutUint64(m.opaque[offset+8:], memOwnerOpaquePtr) +} + +// DoneInstantiation implements wasm.ModuleEngine. +func (m *moduleEngine) DoneInstantiation() { + if !m.module.Source.IsHostModule { + m.setupOpaque() + } +} + +// FunctionInstanceReference implements wasm.ModuleEngine. +func (m *moduleEngine) FunctionInstanceReference(funcIndex wasm.Index) wasm.Reference { + if funcIndex < m.module.Source.ImportFunctionCount { + begin, _, _ := m.parent.offsets.ImportedFunctionOffset(funcIndex) + return uintptr(unsafe.Pointer(&m.opaque[begin])) + } + localIndex := funcIndex - m.module.Source.ImportFunctionCount + p := m.parent + executable := &p.executable[p.functionOffsets[localIndex]] + typeID := m.module.TypeIDs[m.module.Source.FunctionSection[localIndex]] + + lf := &functionInstance{ + executable: executable, + moduleContextOpaquePtr: m.opaquePtr, + typeID: typeID, + indexInModule: funcIndex, + } + m.localFunctionInstances = append(m.localFunctionInstances, lf) + return uintptr(unsafe.Pointer(lf)) +} + +// LookupFunction implements wasm.ModuleEngine. +func (m *moduleEngine) LookupFunction(t *wasm.TableInstance, typeId wasm.FunctionTypeID, tableOffset wasm.Index) (*wasm.ModuleInstance, wasm.Index) { + if tableOffset >= uint32(len(t.References)) || t.Type != wasm.RefTypeFuncref { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + rawPtr := t.References[tableOffset] + if rawPtr == 0 { + panic(wasmruntime.ErrRuntimeInvalidTableAccess) + } + + tf := wazevoapi.PtrFromUintptr[functionInstance](rawPtr) + if tf.typeID != typeId { + panic(wasmruntime.ErrRuntimeIndirectCallTypeMismatch) + } + return moduleInstanceFromOpaquePtr(tf.moduleContextOpaquePtr), tf.indexInModule +} + +func moduleInstanceFromOpaquePtr(ptr *byte) *wasm.ModuleInstance { + return *(**wasm.ModuleInstance)(unsafe.Pointer(ptr)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go new file mode 100644 index 00000000..cf7f14d3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block.go @@ -0,0 +1,379 @@ +package ssa + +import ( + "fmt" + "strconv" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// BasicBlock represents the Basic Block of an SSA function. +// Each BasicBlock always ends with branching instructions (e.g. Branch, Return, etc.), +// and at most two branches are allowed. If there's two branches, these two are placed together at the end of the block. +// In other words, there's no branching instruction in the middle of the block. +// +// Note: we use the "block argument" variant of SSA, instead of PHI functions. See the package level doc comments. +// +// Note: we use "parameter/param" as a placeholder which represents a variant of PHI, and "argument/arg" as an actual +// Value passed to that "parameter/param". +type BasicBlock interface { + // ID returns the unique ID of this block. + ID() BasicBlockID + + // Name returns the unique string ID of this block. e.g. blk0, blk1, ... + Name() string + + // AddParam adds the parameter to the block whose type specified by `t`. + AddParam(b Builder, t Type) Value + + // Params returns the number of parameters to this block. + Params() int + + // Param returns (Variable, Value) which corresponds to the i-th parameter of this block. + // The returned Value is the definition of the param in this block. + Param(i int) Value + + // Root returns the root instruction of this block. + Root() *Instruction + + // Tail returns the tail instruction of this block. + Tail() *Instruction + + // EntryBlock returns true if this block represents the function entry. + EntryBlock() bool + + // ReturnBlock returns ture if this block represents the function return. + ReturnBlock() bool + + // Valid is true if this block is still valid even after optimizations. + Valid() bool + + // Sealed is true if this block has been sealed. + Sealed() bool + + // Preds returns the number of predecessors of this block. + Preds() int + + // Pred returns the i-th predecessor of this block. + Pred(i int) BasicBlock + + // Succs returns the number of successors of this block. + Succs() int + + // Succ returns the i-th successor of this block. + Succ(i int) BasicBlock + + // LoopHeader returns true if this block is a loop header. + LoopHeader() bool + + // LoopNestingForestChildren returns the children of this block in the loop nesting forest. + LoopNestingForestChildren() []BasicBlock +} + +type ( + // basicBlock is a basic block in a SSA-transformed function. + basicBlock struct { + id BasicBlockID + rootInstr, currentInstr *Instruction + // params are Values that represent parameters to a basicBlock. + // Each parameter can be considered as an output of PHI instruction in traditional SSA. + params Values + preds []basicBlockPredecessorInfo + success []*basicBlock + // singlePred is the alias to preds[0] for fast lookup, and only set after Seal is called. + singlePred *basicBlock + // lastDefinitions maps Variable to its last definition in this block. + lastDefinitions map[Variable]Value + // unknownsValues are used in builder.findValue. The usage is well-described in the paper. + unknownValues []unknownValue + // invalid is true if this block is made invalid during optimizations. + invalid bool + // sealed is true if this is sealed (all the predecessors are known). + sealed bool + // loopHeader is true if this block is a loop header: + // + // > A loop header (sometimes called the entry point of the loop) is a dominator that is the target + // > of a loop-forming back edge. The loop header dominates all blocks in the loop body. + // > A block may be a loop header for more than one loop. A loop may have multiple entry points, + // > in which case it has no "loop header". + // + // See https://en.wikipedia.org/wiki/Control-flow_graph for more details. + // + // This is modified during the subPassLoopDetection pass. + loopHeader bool + + // loopNestingForestChildren holds the children of this block in the loop nesting forest. + // Non-empty if and only if this block is a loop header (i.e. loopHeader=true) + loopNestingForestChildren wazevoapi.VarLength[BasicBlock] + + // reversePostOrder is used to sort all the blocks in the function in reverse post order. + // This is used in builder.LayoutBlocks. + reversePostOrder int32 + + // visited is used during various traversals. + visited int32 + + // child and sibling are the ones in the dominator tree. + child, sibling *basicBlock + } + // BasicBlockID is the unique ID of a basicBlock. + BasicBlockID uint32 + + unknownValue struct { + // variable is the variable that this unknownValue represents. + variable Variable + // value is the value that this unknownValue represents. + value Value + } +) + +// basicBlockVarLengthNil is the default nil value for basicBlock.loopNestingForestChildren. +var basicBlockVarLengthNil = wazevoapi.NewNilVarLength[BasicBlock]() + +const basicBlockIDReturnBlock = 0xffffffff + +// Name implements BasicBlock.Name. +func (bb *basicBlock) Name() string { + if bb.id == basicBlockIDReturnBlock { + return "blk_ret" + } else { + return fmt.Sprintf("blk%d", bb.id) + } +} + +// String implements fmt.Stringer for debugging. +func (bid BasicBlockID) String() string { + if bid == basicBlockIDReturnBlock { + return "blk_ret" + } else { + return fmt.Sprintf("blk%d", bid) + } +} + +// ID implements BasicBlock.ID. +func (bb *basicBlock) ID() BasicBlockID { + return bb.id +} + +// basicBlockPredecessorInfo is the information of a predecessor of a basicBlock. +// predecessor is determined by a pair of block and the branch instruction used to jump to the successor. +type basicBlockPredecessorInfo struct { + blk *basicBlock + branch *Instruction +} + +// EntryBlock implements BasicBlock.EntryBlock. +func (bb *basicBlock) EntryBlock() bool { + return bb.id == 0 +} + +// ReturnBlock implements BasicBlock.ReturnBlock. +func (bb *basicBlock) ReturnBlock() bool { + return bb.id == basicBlockIDReturnBlock +} + +// AddParam implements BasicBlock.AddParam. +func (bb *basicBlock) AddParam(b Builder, typ Type) Value { + paramValue := b.allocateValue(typ) + bb.params = bb.params.Append(&b.(*builder).varLengthPool, paramValue) + return paramValue +} + +// addParamOn adds a parameter to this block whose value is already allocated. +func (bb *basicBlock) addParamOn(b *builder, value Value) { + bb.params = bb.params.Append(&b.varLengthPool, value) +} + +// Params implements BasicBlock.Params. +func (bb *basicBlock) Params() int { + return len(bb.params.View()) +} + +// Param implements BasicBlock.Param. +func (bb *basicBlock) Param(i int) Value { + return bb.params.View()[i] +} + +// Valid implements BasicBlock.Valid. +func (bb *basicBlock) Valid() bool { + return !bb.invalid +} + +// Sealed implements BasicBlock.Sealed. +func (bb *basicBlock) Sealed() bool { + return bb.sealed +} + +// insertInstruction implements BasicBlock.InsertInstruction. +func (bb *basicBlock) insertInstruction(b *builder, next *Instruction) { + current := bb.currentInstr + if current != nil { + current.next = next + next.prev = current + } else { + bb.rootInstr = next + } + bb.currentInstr = next + + switch next.opcode { + case OpcodeJump, OpcodeBrz, OpcodeBrnz: + target := BasicBlockID(next.rValue) + b.basicBlock(target).addPred(bb, next) + case OpcodeBrTable: + for _, _target := range next.rValues.View() { + target := BasicBlockID(_target) + b.basicBlock(target).addPred(bb, next) + } + } +} + +// NumPreds implements BasicBlock.NumPreds. +func (bb *basicBlock) NumPreds() int { + return len(bb.preds) +} + +// Preds implements BasicBlock.Preds. +func (bb *basicBlock) Preds() int { + return len(bb.preds) +} + +// Pred implements BasicBlock.Pred. +func (bb *basicBlock) Pred(i int) BasicBlock { + return bb.preds[i].blk +} + +// Succs implements BasicBlock.Succs. +func (bb *basicBlock) Succs() int { + return len(bb.success) +} + +// Succ implements BasicBlock.Succ. +func (bb *basicBlock) Succ(i int) BasicBlock { + return bb.success[i] +} + +// Root implements BasicBlock.Root. +func (bb *basicBlock) Root() *Instruction { + return bb.rootInstr +} + +// Tail implements BasicBlock.Tail. +func (bb *basicBlock) Tail() *Instruction { + return bb.currentInstr +} + +// reset resets the basicBlock to its initial state so that it can be reused for another function. +func resetBasicBlock(bb *basicBlock) { + bb.params = ValuesNil + bb.rootInstr, bb.currentInstr = nil, nil + bb.preds = bb.preds[:0] + bb.success = bb.success[:0] + bb.invalid, bb.sealed = false, false + bb.singlePred = nil + bb.unknownValues = bb.unknownValues[:0] + bb.lastDefinitions = wazevoapi.ResetMap(bb.lastDefinitions) + bb.reversePostOrder = -1 + bb.visited = 0 + bb.loopNestingForestChildren = basicBlockVarLengthNil + bb.loopHeader = false + bb.sibling = nil + bb.child = nil +} + +// addPred adds a predecessor to this block specified by the branch instruction. +func (bb *basicBlock) addPred(blk BasicBlock, branch *Instruction) { + if bb.sealed { + panic("BUG: trying to add predecessor to a sealed block: " + bb.Name()) + } + + pred := blk.(*basicBlock) + for i := range bb.preds { + existingPred := &bb.preds[i] + if existingPred.blk == pred && existingPred.branch != branch { + // If the target is already added, then this must come from the same BrTable, + // otherwise such redundant branch should be eliminated by the frontend. (which should be simpler). + panic(fmt.Sprintf("BUG: redundant non BrTable jumps in %s whose targes are the same", bb.Name())) + } + } + + bb.preds = append(bb.preds, basicBlockPredecessorInfo{ + blk: pred, + branch: branch, + }) + + pred.success = append(pred.success, bb) +} + +// formatHeader returns the string representation of the header of the basicBlock. +func (bb *basicBlock) formatHeader(b Builder) string { + ps := make([]string, len(bb.params.View())) + for i, p := range bb.params.View() { + ps[i] = p.formatWithType(b) + } + + if len(bb.preds) > 0 { + preds := make([]string, 0, len(bb.preds)) + for _, pred := range bb.preds { + if pred.blk.invalid { + continue + } + preds = append(preds, fmt.Sprintf("blk%d", pred.blk.id)) + + } + return fmt.Sprintf("blk%d: (%s) <-- (%s)", + bb.id, strings.Join(ps, ","), strings.Join(preds, ",")) + } else { + return fmt.Sprintf("blk%d: (%s)", bb.id, strings.Join(ps, ", ")) + } +} + +// validates validates the basicBlock for debugging purpose. +func (bb *basicBlock) validate(b *builder) { + if bb.invalid { + panic("BUG: trying to validate an invalid block: " + bb.Name()) + } + if len(bb.preds) > 0 { + for _, pred := range bb.preds { + if pred.branch.opcode != OpcodeBrTable { + blockID := int(pred.branch.rValue) + target := b.basicBlocksPool.View(blockID) + if target != bb { + panic(fmt.Sprintf("BUG: '%s' is not branch to %s, but to %s", + pred.branch.Format(b), bb.Name(), target.Name())) + } + } + + var exp int + if bb.ReturnBlock() { + exp = len(b.currentSignature.Results) + } else { + exp = len(bb.params.View()) + } + + if len(pred.branch.vs.View()) != exp { + panic(fmt.Sprintf( + "BUG: len(argument at %s) != len(params at %s): %d != %d: %s", + pred.blk.Name(), bb.Name(), + len(pred.branch.vs.View()), len(bb.params.View()), pred.branch.Format(b), + )) + } + + } + } +} + +// String implements fmt.Stringer for debugging purpose only. +func (bb *basicBlock) String() string { + return strconv.Itoa(int(bb.id)) +} + +// LoopNestingForestChildren implements BasicBlock.LoopNestingForestChildren. +func (bb *basicBlock) LoopNestingForestChildren() []BasicBlock { + return bb.loopNestingForestChildren.View() +} + +// LoopHeader implements BasicBlock.LoopHeader. +func (bb *basicBlock) LoopHeader() bool { + return bb.loopHeader +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go new file mode 100644 index 00000000..fb98298f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/basic_block_sort.go @@ -0,0 +1,32 @@ +package ssa + +import ( + "slices" +) + +func sortBlocks(blocks []*basicBlock) { + slices.SortFunc(blocks, func(i, j *basicBlock) int { + jIsReturn := j.ReturnBlock() + iIsReturn := i.ReturnBlock() + if iIsReturn && jIsReturn { + return 0 + } + if jIsReturn { + return 1 + } + if iIsReturn { + return -1 + } + iRoot, jRoot := i.rootInstr, j.rootInstr + if iRoot == nil && jRoot == nil { // For testing. + return 0 + } + if jRoot == nil { + return 1 + } + if iRoot == nil { + return -1 + } + return i.rootInstr.id - j.rootInstr.id + }) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go new file mode 100644 index 00000000..43dd7d29 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/builder.go @@ -0,0 +1,790 @@ +package ssa + +import ( + "fmt" + "sort" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// Builder is used to builds SSA consisting of Basic Blocks per function. +type Builder interface { + // Init must be called to reuse this builder for the next function. + Init(typ *Signature) + + // Signature returns the Signature of the currently-compiled function. + Signature() *Signature + + // BlockIDMax returns the maximum value of BasicBlocksID existing in the currently-compiled function. + BlockIDMax() BasicBlockID + + // AllocateBasicBlock creates a basic block in SSA function. + AllocateBasicBlock() BasicBlock + + // CurrentBlock returns the currently handled BasicBlock which is set by the latest call to SetCurrentBlock. + CurrentBlock() BasicBlock + + // EntryBlock returns the entry BasicBlock of the currently-compiled function. + EntryBlock() BasicBlock + + // SetCurrentBlock sets the instruction insertion target to the BasicBlock `b`. + SetCurrentBlock(b BasicBlock) + + // DeclareVariable declares a Variable of the given Type. + DeclareVariable(Type) Variable + + // DefineVariable defines a variable in the `block` with value. + // The defining instruction will be inserted into the `block`. + DefineVariable(variable Variable, value Value, block BasicBlock) + + // DefineVariableInCurrentBB is the same as DefineVariable except the definition is + // inserted into the current BasicBlock. Alias to DefineVariable(x, y, CurrentBlock()). + DefineVariableInCurrentBB(variable Variable, value Value) + + // AllocateInstruction returns a new Instruction. + AllocateInstruction() *Instruction + + // InsertInstruction executes BasicBlock.InsertInstruction for the currently handled basic block. + InsertInstruction(raw *Instruction) + + // allocateValue allocates an unused Value. + allocateValue(typ Type) Value + + // MustFindValue searches the latest definition of the given Variable and returns the result. + MustFindValue(variable Variable) Value + + // FindValueInLinearPath tries to find the latest definition of the given Variable in the linear path to the current BasicBlock. + // If it cannot find the definition, or it's not sealed yet, it returns ValueInvalid. + FindValueInLinearPath(variable Variable) Value + + // Seal declares that we've known all the predecessors to this block and were added via AddPred. + // After calling this, AddPred will be forbidden. + Seal(blk BasicBlock) + + // AnnotateValue is for debugging purpose. + AnnotateValue(value Value, annotation string) + + // DeclareSignature appends the *Signature to be referenced by various instructions (e.g. OpcodeCall). + DeclareSignature(signature *Signature) + + // Signatures returns the slice of declared Signatures. + Signatures() []*Signature + + // ResolveSignature returns the Signature which corresponds to SignatureID. + ResolveSignature(id SignatureID) *Signature + + // RunPasses runs various passes on the constructed SSA function. + RunPasses() + + // Format returns the debugging string of the SSA function. + Format() string + + // BlockIteratorBegin initializes the state to iterate over all the valid BasicBlock(s) compiled. + // Combined with BlockIteratorNext, we can use this like: + // + // for blk := builder.BlockIteratorBegin(); blk != nil; blk = builder.BlockIteratorNext() { + // // ... + // } + // + // The returned blocks are ordered in the order of AllocateBasicBlock being called. + BlockIteratorBegin() BasicBlock + + // BlockIteratorNext advances the state for iteration initialized by BlockIteratorBegin. + // Returns nil if there's no unseen BasicBlock. + BlockIteratorNext() BasicBlock + + // ValuesInfo returns the data per Value used to lower the SSA in backend. + // This is indexed by ValueID. + ValuesInfo() []ValueInfo + + // BlockIteratorReversePostOrderBegin is almost the same as BlockIteratorBegin except it returns the BasicBlock in the reverse post-order. + // This is available after RunPasses is run. + BlockIteratorReversePostOrderBegin() BasicBlock + + // BlockIteratorReversePostOrderNext is almost the same as BlockIteratorPostOrderNext except it returns the BasicBlock in the reverse post-order. + // This is available after RunPasses is run. + BlockIteratorReversePostOrderNext() BasicBlock + + // ReturnBlock returns the BasicBlock which is used to return from the function. + ReturnBlock() BasicBlock + + // InsertUndefined inserts an undefined instruction at the current position. + InsertUndefined() + + // SetCurrentSourceOffset sets the current source offset. The incoming instruction will be annotated with this offset. + SetCurrentSourceOffset(line SourceOffset) + + // LoopNestingForestRoots returns the roots of the loop nesting forest. + LoopNestingForestRoots() []BasicBlock + + // LowestCommonAncestor returns the lowest common ancestor in the dominator tree of the given BasicBlock(s). + LowestCommonAncestor(blk1, blk2 BasicBlock) BasicBlock + + // Idom returns the immediate dominator of the given BasicBlock. + Idom(blk BasicBlock) BasicBlock + + // VarLengthPool returns the VarLengthPool of Value. + VarLengthPool() *wazevoapi.VarLengthPool[Value] + + // InsertZeroValue inserts a zero value constant instruction of the given type. + InsertZeroValue(t Type) + + // BasicBlock returns the BasicBlock of the given ID. + BasicBlock(id BasicBlockID) BasicBlock + + // InstructionOfValue returns the Instruction that produces the given Value or nil if the Value is not produced by any Instruction. + InstructionOfValue(v Value) *Instruction +} + +// NewBuilder returns a new Builder implementation. +func NewBuilder() Builder { + return &builder{ + instructionsPool: wazevoapi.NewPool[Instruction](resetInstruction), + basicBlocksPool: wazevoapi.NewPool[basicBlock](resetBasicBlock), + varLengthBasicBlockPool: wazevoapi.NewVarLengthPool[BasicBlock](), + varLengthPool: wazevoapi.NewVarLengthPool[Value](), + valueAnnotations: make(map[ValueID]string), + signatures: make(map[SignatureID]*Signature), + returnBlk: &basicBlock{id: basicBlockIDReturnBlock}, + } +} + +// builder implements Builder interface. +type builder struct { + basicBlocksPool wazevoapi.Pool[basicBlock] + instructionsPool wazevoapi.Pool[Instruction] + varLengthPool wazevoapi.VarLengthPool[Value] + signatures map[SignatureID]*Signature + currentSignature *Signature + + // reversePostOrderedBasicBlocks are the BasicBlock(s) ordered in the reverse post-order after passCalculateImmediateDominators. + reversePostOrderedBasicBlocks []*basicBlock + currentBB *basicBlock + returnBlk *basicBlock + + // nextValueID is used by builder.AllocateValue. + nextValueID ValueID + // nextVariable is used by builder.AllocateVariable. + nextVariable Variable + + // valueAnnotations contains the annotations for each Value, only used for debugging. + valueAnnotations map[ValueID]string + + // valuesInfo contains the data per Value used to lower the SSA in backend. This is indexed by ValueID. + valuesInfo []ValueInfo + + // dominators stores the immediate dominator of each BasicBlock. + // The index is blockID of the BasicBlock. + dominators []*basicBlock + sparseTree dominatorSparseTree + + varLengthBasicBlockPool wazevoapi.VarLengthPool[BasicBlock] + + // loopNestingForestRoots are the roots of the loop nesting forest. + loopNestingForestRoots []BasicBlock + + // The followings are used for optimization passes/deterministic compilation. + instStack []*Instruction + blkStack []*basicBlock + blkStack2 []*basicBlock + redundantParams []redundantParam + + // blockIterCur is used to implement blockIteratorBegin and blockIteratorNext. + blockIterCur int + + // donePreBlockLayoutPasses is true if all the passes before LayoutBlocks are called. + donePreBlockLayoutPasses bool + // doneBlockLayout is true if LayoutBlocks is called. + doneBlockLayout bool + // donePostBlockLayoutPasses is true if all the passes after LayoutBlocks are called. + donePostBlockLayoutPasses bool + + currentSourceOffset SourceOffset + + // zeros are the zero value constants for each type. + zeros [typeEnd]Value +} + +// ValueInfo contains the data per Value used to lower the SSA in backend. +type ValueInfo struct { + // RefCount is the reference count of the Value. + RefCount uint32 + alias Value +} + +// redundantParam is a pair of the index of the redundant parameter and the Value. +// This is used to eliminate the redundant parameters in the optimization pass. +type redundantParam struct { + // index is the index of the redundant parameter in the basicBlock. + index int + // uniqueValue is the Value which is passed to the redundant parameter. + uniqueValue Value +} + +// BasicBlock implements Builder.BasicBlock. +func (b *builder) BasicBlock(id BasicBlockID) BasicBlock { + return b.basicBlock(id) +} + +func (b *builder) basicBlock(id BasicBlockID) *basicBlock { + if id == basicBlockIDReturnBlock { + return b.returnBlk + } + return b.basicBlocksPool.View(int(id)) +} + +// InsertZeroValue implements Builder.InsertZeroValue. +func (b *builder) InsertZeroValue(t Type) { + if b.zeros[t].Valid() { + return + } + zeroInst := b.AllocateInstruction() + switch t { + case TypeI32: + zeroInst.AsIconst32(0) + case TypeI64: + zeroInst.AsIconst64(0) + case TypeF32: + zeroInst.AsF32const(0) + case TypeF64: + zeroInst.AsF64const(0) + case TypeV128: + zeroInst.AsVconst(0, 0) + default: + panic("TODO: " + t.String()) + } + b.zeros[t] = zeroInst.Insert(b).Return() +} + +func (b *builder) VarLengthPool() *wazevoapi.VarLengthPool[Value] { + return &b.varLengthPool +} + +// ReturnBlock implements Builder.ReturnBlock. +func (b *builder) ReturnBlock() BasicBlock { + return b.returnBlk +} + +// Init implements Builder.Reset. +func (b *builder) Init(s *Signature) { + b.nextVariable = 0 + b.currentSignature = s + b.zeros = [typeEnd]Value{ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid, ValueInvalid} + resetBasicBlock(b.returnBlk) + b.instructionsPool.Reset() + b.basicBlocksPool.Reset() + b.varLengthPool.Reset() + b.varLengthBasicBlockPool.Reset() + b.donePreBlockLayoutPasses = false + b.doneBlockLayout = false + b.donePostBlockLayoutPasses = false + for _, sig := range b.signatures { + sig.used = false + } + + b.redundantParams = b.redundantParams[:0] + b.blkStack = b.blkStack[:0] + b.blkStack2 = b.blkStack2[:0] + b.dominators = b.dominators[:0] + b.loopNestingForestRoots = b.loopNestingForestRoots[:0] + b.basicBlocksPool.Reset() + + for v := ValueID(0); v < b.nextValueID; v++ { + delete(b.valueAnnotations, v) + b.valuesInfo[v] = ValueInfo{alias: ValueInvalid} + } + b.nextValueID = 0 + b.reversePostOrderedBasicBlocks = b.reversePostOrderedBasicBlocks[:0] + b.doneBlockLayout = false + b.currentSourceOffset = sourceOffsetUnknown +} + +// Signature implements Builder.Signature. +func (b *builder) Signature() *Signature { + return b.currentSignature +} + +// AnnotateValue implements Builder.AnnotateValue. +func (b *builder) AnnotateValue(value Value, a string) { + b.valueAnnotations[value.ID()] = a +} + +// AllocateInstruction implements Builder.AllocateInstruction. +func (b *builder) AllocateInstruction() *Instruction { + instr := b.instructionsPool.Allocate() + instr.id = b.instructionsPool.Allocated() + return instr +} + +// DeclareSignature implements Builder.AnnotateValue. +func (b *builder) DeclareSignature(s *Signature) { + b.signatures[s.ID] = s + s.used = false +} + +// Signatures implements Builder.Signatures. +func (b *builder) Signatures() (ret []*Signature) { + for _, sig := range b.signatures { + ret = append(ret, sig) + } + sort.Slice(ret, func(i, j int) bool { + return ret[i].ID < ret[j].ID + }) + return +} + +// SetCurrentSourceOffset implements Builder.SetCurrentSourceOffset. +func (b *builder) SetCurrentSourceOffset(l SourceOffset) { + b.currentSourceOffset = l +} + +func (b *builder) usedSignatures() (ret []*Signature) { + for _, sig := range b.signatures { + if sig.used { + ret = append(ret, sig) + } + } + sort.Slice(ret, func(i, j int) bool { + return ret[i].ID < ret[j].ID + }) + return +} + +// ResolveSignature implements Builder.ResolveSignature. +func (b *builder) ResolveSignature(id SignatureID) *Signature { + return b.signatures[id] +} + +// AllocateBasicBlock implements Builder.AllocateBasicBlock. +func (b *builder) AllocateBasicBlock() BasicBlock { + return b.allocateBasicBlock() +} + +// allocateBasicBlock allocates a new basicBlock. +func (b *builder) allocateBasicBlock() *basicBlock { + id := BasicBlockID(b.basicBlocksPool.Allocated()) + blk := b.basicBlocksPool.Allocate() + blk.id = id + return blk +} + +// Idom implements Builder.Idom. +func (b *builder) Idom(blk BasicBlock) BasicBlock { + return b.dominators[blk.ID()] +} + +// InsertInstruction implements Builder.InsertInstruction. +func (b *builder) InsertInstruction(instr *Instruction) { + b.currentBB.insertInstruction(b, instr) + + if l := b.currentSourceOffset; l.Valid() { + // Emit the source offset info only when the instruction has side effect because + // these are the only instructions that are accessed by stack unwinding. + // This reduces the significant amount of the offset info in the binary. + if instr.sideEffect() != sideEffectNone { + instr.annotateSourceOffset(l) + } + } + + resultTypesFn := instructionReturnTypes[instr.opcode] + if resultTypesFn == nil { + panic("TODO: " + instr.Format(b)) + } + + t1, ts := resultTypesFn(b, instr) + if t1.invalid() { + return + } + + r1 := b.allocateValue(t1) + instr.rValue = r1.setInstructionID(instr.id) + + tsl := len(ts) + if tsl == 0 { + return + } + + rValues := b.varLengthPool.Allocate(tsl) + for i := 0; i < tsl; i++ { + rn := b.allocateValue(ts[i]) + rValues = rValues.Append(&b.varLengthPool, rn.setInstructionID(instr.id)) + } + instr.rValues = rValues +} + +// DefineVariable implements Builder.DefineVariable. +func (b *builder) DefineVariable(variable Variable, value Value, block BasicBlock) { + bb := block.(*basicBlock) + bb.lastDefinitions[variable] = value +} + +// DefineVariableInCurrentBB implements Builder.DefineVariableInCurrentBB. +func (b *builder) DefineVariableInCurrentBB(variable Variable, value Value) { + b.DefineVariable(variable, value, b.currentBB) +} + +// SetCurrentBlock implements Builder.SetCurrentBlock. +func (b *builder) SetCurrentBlock(bb BasicBlock) { + b.currentBB = bb.(*basicBlock) +} + +// CurrentBlock implements Builder.CurrentBlock. +func (b *builder) CurrentBlock() BasicBlock { + return b.currentBB +} + +// EntryBlock implements Builder.EntryBlock. +func (b *builder) EntryBlock() BasicBlock { + return b.entryBlk() +} + +// DeclareVariable implements Builder.DeclareVariable. +func (b *builder) DeclareVariable(typ Type) Variable { + v := b.nextVariable + b.nextVariable++ + return v.setType(typ) +} + +// allocateValue implements Builder.AllocateValue. +func (b *builder) allocateValue(typ Type) (v Value) { + v = Value(b.nextValueID) + v = v.setType(typ) + b.nextValueID++ + return +} + +// FindValueInLinearPath implements Builder.FindValueInLinearPath. +func (b *builder) FindValueInLinearPath(variable Variable) Value { + return b.findValueInLinearPath(variable, b.currentBB) +} + +func (b *builder) findValueInLinearPath(variable Variable, blk *basicBlock) Value { + if val, ok := blk.lastDefinitions[variable]; ok { + return val + } else if !blk.sealed { + return ValueInvalid + } + + if pred := blk.singlePred; pred != nil { + // If this block is sealed and have only one predecessor, + // we can use the value in that block without ambiguity on definition. + return b.findValueInLinearPath(variable, pred) + } + if len(blk.preds) == 1 { + panic("BUG") + } + return ValueInvalid +} + +// MustFindValue implements Builder.MustFindValue. +func (b *builder) MustFindValue(variable Variable) Value { + return b.findValue(variable.getType(), variable, b.currentBB) +} + +// findValue recursively tries to find the latest definition of a `variable`. The algorithm is described in +// the section 2 of the paper https://link.springer.com/content/pdf/10.1007/978-3-642-37051-9_6.pdf. +// +// TODO: reimplement this in iterative, not recursive, to avoid stack overflow. +func (b *builder) findValue(typ Type, variable Variable, blk *basicBlock) Value { + if val, ok := blk.lastDefinitions[variable]; ok { + // The value is already defined in this block! + return val + } else if !blk.sealed { // Incomplete CFG as in the paper. + // If this is not sealed, that means it might have additional unknown predecessor later on. + // So we temporarily define the placeholder value here (not add as a parameter yet!), + // and record it as unknown. + // The unknown values are resolved when we call seal this block via BasicBlock.Seal(). + value := b.allocateValue(typ) + if wazevoapi.SSALoggingEnabled { + fmt.Printf("adding unknown value placeholder for %s at %d\n", variable, blk.id) + } + blk.lastDefinitions[variable] = value + blk.unknownValues = append(blk.unknownValues, unknownValue{ + variable: variable, + value: value, + }) + return value + } else if blk.EntryBlock() { + // If this is the entry block, we reach the uninitialized variable which has zero value. + return b.zeros[variable.getType()] + } + + if pred := blk.singlePred; pred != nil { + // If this block is sealed and have only one predecessor, + // we can use the value in that block without ambiguity on definition. + return b.findValue(typ, variable, pred) + } else if len(blk.preds) == 0 { + panic("BUG: value is not defined for " + variable.String()) + } + + // If this block has multiple predecessors, we have to gather the definitions, + // and treat them as an argument to this block. + // + // But before that, we have to check if the possible definitions are the same Value. + tmpValue := b.allocateValue(typ) + // Break the cycle by defining the variable with the tmpValue. + b.DefineVariable(variable, tmpValue, blk) + // Check all the predecessors if they have the same definition. + uniqueValue := ValueInvalid + for i := range blk.preds { + predValue := b.findValue(typ, variable, blk.preds[i].blk) + if uniqueValue == ValueInvalid { + uniqueValue = predValue + } else if uniqueValue != predValue { + uniqueValue = ValueInvalid + break + } + } + + if uniqueValue != ValueInvalid { + // If all the predecessors have the same definition, we can use that value. + b.alias(tmpValue, uniqueValue) + return uniqueValue + } else { + // Otherwise, add the tmpValue to this block as a parameter which may or may not be redundant, but + // later we eliminate trivial params in an optimization pass. This must be done before finding the + // definitions in the predecessors so that we can break the cycle. + blk.addParamOn(b, tmpValue) + // After the new param is added, we have to manipulate the original branching instructions + // in predecessors so that they would pass the definition of `variable` as the argument to + // the newly added PHI. + for i := range blk.preds { + pred := &blk.preds[i] + value := b.findValue(typ, variable, pred.blk) + pred.branch.addArgumentBranchInst(b, value) + } + return tmpValue + } +} + +// Seal implements Builder.Seal. +func (b *builder) Seal(raw BasicBlock) { + blk := raw.(*basicBlock) + if len(blk.preds) == 1 { + blk.singlePred = blk.preds[0].blk + } + blk.sealed = true + + for _, v := range blk.unknownValues { + variable, phiValue := v.variable, v.value + typ := variable.getType() + blk.addParamOn(b, phiValue) + for i := range blk.preds { + pred := &blk.preds[i] + predValue := b.findValue(typ, variable, pred.blk) + if !predValue.Valid() { + panic("BUG: value is not defined anywhere in the predecessors in the CFG") + } + pred.branch.addArgumentBranchInst(b, predValue) + } + } +} + +// Format implements Builder.Format. +func (b *builder) Format() string { + str := strings.Builder{} + usedSigs := b.usedSignatures() + if len(usedSigs) > 0 { + str.WriteByte('\n') + str.WriteString("signatures:\n") + for _, sig := range usedSigs { + str.WriteByte('\t') + str.WriteString(sig.String()) + str.WriteByte('\n') + } + } + + var iterBegin, iterNext func() *basicBlock + if b.doneBlockLayout { + iterBegin, iterNext = b.blockIteratorReversePostOrderBegin, b.blockIteratorReversePostOrderNext + } else { + iterBegin, iterNext = b.blockIteratorBegin, b.blockIteratorNext + } + for bb := iterBegin(); bb != nil; bb = iterNext() { + str.WriteByte('\n') + str.WriteString(bb.formatHeader(b)) + str.WriteByte('\n') + + for cur := bb.Root(); cur != nil; cur = cur.Next() { + str.WriteByte('\t') + str.WriteString(cur.Format(b)) + str.WriteByte('\n') + } + } + return str.String() +} + +// BlockIteratorNext implements Builder.BlockIteratorNext. +func (b *builder) BlockIteratorNext() BasicBlock { + if blk := b.blockIteratorNext(); blk == nil { + return nil // BasicBlock((*basicBlock)(nil)) != BasicBlock(nil) + } else { + return blk + } +} + +// BlockIteratorNext implements Builder.BlockIteratorNext. +func (b *builder) blockIteratorNext() *basicBlock { + index := b.blockIterCur + for { + if index == b.basicBlocksPool.Allocated() { + return nil + } + ret := b.basicBlocksPool.View(index) + index++ + if !ret.invalid { + b.blockIterCur = index + return ret + } + } +} + +// BlockIteratorBegin implements Builder.BlockIteratorBegin. +func (b *builder) BlockIteratorBegin() BasicBlock { + return b.blockIteratorBegin() +} + +// BlockIteratorBegin implements Builder.BlockIteratorBegin. +func (b *builder) blockIteratorBegin() *basicBlock { + b.blockIterCur = 0 + return b.blockIteratorNext() +} + +// BlockIteratorReversePostOrderBegin implements Builder.BlockIteratorReversePostOrderBegin. +func (b *builder) BlockIteratorReversePostOrderBegin() BasicBlock { + return b.blockIteratorReversePostOrderBegin() +} + +// BlockIteratorBegin implements Builder.BlockIteratorBegin. +func (b *builder) blockIteratorReversePostOrderBegin() *basicBlock { + b.blockIterCur = 0 + return b.blockIteratorReversePostOrderNext() +} + +// BlockIteratorReversePostOrderNext implements Builder.BlockIteratorReversePostOrderNext. +func (b *builder) BlockIteratorReversePostOrderNext() BasicBlock { + if blk := b.blockIteratorReversePostOrderNext(); blk == nil { + return nil // BasicBlock((*basicBlock)(nil)) != BasicBlock(nil) + } else { + return blk + } +} + +// BlockIteratorNext implements Builder.BlockIteratorNext. +func (b *builder) blockIteratorReversePostOrderNext() *basicBlock { + if b.blockIterCur >= len(b.reversePostOrderedBasicBlocks) { + return nil + } else { + ret := b.reversePostOrderedBasicBlocks[b.blockIterCur] + b.blockIterCur++ + return ret + } +} + +// ValuesInfo implements Builder.ValuesInfo. +func (b *builder) ValuesInfo() []ValueInfo { + return b.valuesInfo +} + +// alias records the alias of the given values. The alias(es) will be +// eliminated in the optimization pass via resolveArgumentAlias. +func (b *builder) alias(dst, src Value) { + did := int(dst.ID()) + if did >= len(b.valuesInfo) { + l := did + 1 - len(b.valuesInfo) + b.valuesInfo = append(b.valuesInfo, make([]ValueInfo, l)...) + view := b.valuesInfo[len(b.valuesInfo)-l:] + for i := range view { + view[i].alias = ValueInvalid + } + } + b.valuesInfo[did].alias = src +} + +// resolveArgumentAlias resolves the alias of the arguments of the given instruction. +func (b *builder) resolveArgumentAlias(instr *Instruction) { + if instr.v.Valid() { + instr.v = b.resolveAlias(instr.v) + } + + if instr.v2.Valid() { + instr.v2 = b.resolveAlias(instr.v2) + } + + if instr.v3.Valid() { + instr.v3 = b.resolveAlias(instr.v3) + } + + view := instr.vs.View() + for i, v := range view { + view[i] = b.resolveAlias(v) + } +} + +// resolveAlias resolves the alias of the given value. +func (b *builder) resolveAlias(v Value) Value { + info := b.valuesInfo + l := ValueID(len(info)) + // Some aliases are chained, so we need to resolve them recursively. + for { + vid := v.ID() + if vid < l && info[vid].alias.Valid() { + v = info[vid].alias + } else { + break + } + } + return v +} + +// entryBlk returns the entry block of the function. +func (b *builder) entryBlk() *basicBlock { + return b.basicBlocksPool.View(0) +} + +// isDominatedBy returns true if the given block `n` is dominated by the given block `d`. +// Before calling this, the builder must pass by passCalculateImmediateDominators. +func (b *builder) isDominatedBy(n *basicBlock, d *basicBlock) bool { + if len(b.dominators) == 0 { + panic("BUG: passCalculateImmediateDominators must be called before calling isDominatedBy") + } + ent := b.entryBlk() + doms := b.dominators + for n != d && n != ent { + n = doms[n.id] + } + return n == d +} + +// BlockIDMax implements Builder.BlockIDMax. +func (b *builder) BlockIDMax() BasicBlockID { + return BasicBlockID(b.basicBlocksPool.Allocated()) +} + +// InsertUndefined implements Builder.InsertUndefined. +func (b *builder) InsertUndefined() { + instr := b.AllocateInstruction() + instr.opcode = OpcodeUndefined + b.InsertInstruction(instr) +} + +// LoopNestingForestRoots implements Builder.LoopNestingForestRoots. +func (b *builder) LoopNestingForestRoots() []BasicBlock { + return b.loopNestingForestRoots +} + +// LowestCommonAncestor implements Builder.LowestCommonAncestor. +func (b *builder) LowestCommonAncestor(blk1, blk2 BasicBlock) BasicBlock { + return b.sparseTree.findLCA(blk1.ID(), blk2.ID()) +} + +// InstructionOfValue returns the instruction that produces the given Value, or nil +// if the Value is not produced by any instruction. +func (b *builder) InstructionOfValue(v Value) *Instruction { + instrID := v.instructionID() + if instrID <= 0 { + return nil + } + return b.instructionsPool.View(instrID - 1) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/cmp.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/cmp.go new file mode 100644 index 00000000..15b62ca8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/cmp.go @@ -0,0 +1,107 @@ +package ssa + +// IntegerCmpCond represents a condition for integer comparison. +type IntegerCmpCond byte + +const ( + // IntegerCmpCondInvalid represents an invalid condition. + IntegerCmpCondInvalid IntegerCmpCond = iota + // IntegerCmpCondEqual represents "==". + IntegerCmpCondEqual + // IntegerCmpCondNotEqual represents "!=". + IntegerCmpCondNotEqual + // IntegerCmpCondSignedLessThan represents Signed "<". + IntegerCmpCondSignedLessThan + // IntegerCmpCondSignedGreaterThanOrEqual represents Signed ">=". + IntegerCmpCondSignedGreaterThanOrEqual + // IntegerCmpCondSignedGreaterThan represents Signed ">". + IntegerCmpCondSignedGreaterThan + // IntegerCmpCondSignedLessThanOrEqual represents Signed "<=". + IntegerCmpCondSignedLessThanOrEqual + // IntegerCmpCondUnsignedLessThan represents Unsigned "<". + IntegerCmpCondUnsignedLessThan + // IntegerCmpCondUnsignedGreaterThanOrEqual represents Unsigned ">=". + IntegerCmpCondUnsignedGreaterThanOrEqual + // IntegerCmpCondUnsignedGreaterThan represents Unsigned ">". + IntegerCmpCondUnsignedGreaterThan + // IntegerCmpCondUnsignedLessThanOrEqual represents Unsigned "<=". + IntegerCmpCondUnsignedLessThanOrEqual +) + +// String implements fmt.Stringer. +func (i IntegerCmpCond) String() string { + switch i { + case IntegerCmpCondEqual: + return "eq" + case IntegerCmpCondNotEqual: + return "neq" + case IntegerCmpCondSignedLessThan: + return "lt_s" + case IntegerCmpCondSignedGreaterThanOrEqual: + return "ge_s" + case IntegerCmpCondSignedGreaterThan: + return "gt_s" + case IntegerCmpCondSignedLessThanOrEqual: + return "le_s" + case IntegerCmpCondUnsignedLessThan: + return "lt_u" + case IntegerCmpCondUnsignedGreaterThanOrEqual: + return "ge_u" + case IntegerCmpCondUnsignedGreaterThan: + return "gt_u" + case IntegerCmpCondUnsignedLessThanOrEqual: + return "le_u" + default: + panic("invalid integer comparison condition") + } +} + +// Signed returns true if the condition is signed integer comparison. +func (i IntegerCmpCond) Signed() bool { + switch i { + case IntegerCmpCondSignedLessThan, IntegerCmpCondSignedGreaterThanOrEqual, + IntegerCmpCondSignedGreaterThan, IntegerCmpCondSignedLessThanOrEqual: + return true + default: + return false + } +} + +type FloatCmpCond byte + +const ( + // FloatCmpCondInvalid represents an invalid condition. + FloatCmpCondInvalid FloatCmpCond = iota + // FloatCmpCondEqual represents "==". + FloatCmpCondEqual + // FloatCmpCondNotEqual represents "!=". + FloatCmpCondNotEqual + // FloatCmpCondLessThan represents "<". + FloatCmpCondLessThan + // FloatCmpCondLessThanOrEqual represents "<=". + FloatCmpCondLessThanOrEqual + // FloatCmpCondGreaterThan represents ">". + FloatCmpCondGreaterThan + // FloatCmpCondGreaterThanOrEqual represents ">=". + FloatCmpCondGreaterThanOrEqual +) + +// String implements fmt.Stringer. +func (f FloatCmpCond) String() string { + switch f { + case FloatCmpCondEqual: + return "eq" + case FloatCmpCondNotEqual: + return "neq" + case FloatCmpCondLessThan: + return "lt" + case FloatCmpCondLessThanOrEqual: + return "le" + case FloatCmpCondGreaterThan: + return "gt" + case FloatCmpCondGreaterThanOrEqual: + return "ge" + default: + panic("invalid float comparison condition") + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/funcref.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/funcref.go new file mode 100644 index 00000000..d9620762 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/funcref.go @@ -0,0 +1,12 @@ +package ssa + +import "fmt" + +// FuncRef is a unique identifier for a function of the frontend, +// and is used to reference the function in function call. +type FuncRef uint32 + +// String implements fmt.Stringer. +func (r FuncRef) String() string { + return fmt.Sprintf("f%d", r) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go new file mode 100644 index 00000000..9a3d1da6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/instructions.go @@ -0,0 +1,2976 @@ +package ssa + +import ( + "fmt" + "math" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// Opcode represents a SSA instruction. +type Opcode uint32 + +// Instruction represents an instruction whose opcode is specified by +// Opcode. Since Go doesn't have union type, we use this flattened type +// for all instructions, and therefore each field has different meaning +// depending on Opcode. +type Instruction struct { + // id is the unique ID of this instruction which ascends from 0 following the order of program. + id int + opcode Opcode + u1, u2 uint64 + v Value + v2 Value + v3 Value + vs Values + typ Type + prev, next *Instruction + + // rValue is the (first) return value of this instruction. + // For branching instructions except for OpcodeBrTable, they hold BlockID to jump cast to Value. + rValue Value + // rValues are the rest of the return values of this instruction. + // For OpcodeBrTable, it holds the list of BlockID to jump cast to Value. + rValues Values + gid InstructionGroupID + sourceOffset SourceOffset + live bool + alreadyLowered bool +} + +// SourceOffset represents the offset of the source of an instruction. +type SourceOffset int64 + +const sourceOffsetUnknown = -1 + +// Valid returns true if this source offset is valid. +func (l SourceOffset) Valid() bool { + return l != sourceOffsetUnknown +} + +func (i *Instruction) annotateSourceOffset(line SourceOffset) { + i.sourceOffset = line +} + +// SourceOffset returns the source offset of this instruction. +func (i *Instruction) SourceOffset() SourceOffset { + return i.sourceOffset +} + +// Opcode returns the opcode of this instruction. +func (i *Instruction) Opcode() Opcode { + return i.opcode +} + +// GroupID returns the InstructionGroupID of this instruction. +func (i *Instruction) GroupID() InstructionGroupID { + return i.gid +} + +// MarkLowered marks this instruction as already lowered. +func (i *Instruction) MarkLowered() { + i.alreadyLowered = true +} + +// Lowered returns true if this instruction is already lowered. +func (i *Instruction) Lowered() bool { + return i.alreadyLowered +} + +// resetInstruction resets this instruction to the initial state. +func resetInstruction(i *Instruction) { + *i = Instruction{} + i.v = ValueInvalid + i.v2 = ValueInvalid + i.v3 = ValueInvalid + i.rValue = ValueInvalid + i.typ = typeInvalid + i.vs = ValuesNil + i.sourceOffset = sourceOffsetUnknown +} + +// InstructionGroupID is assigned to each instruction and represents a group of instructions +// where each instruction is interchangeable with others except for the last instruction +// in the group which has side effects. In short, InstructionGroupID is determined by the side effects of instructions. +// That means, if there's an instruction with side effect between two instructions, then these two instructions +// will have different instructionGroupID. Note that each block always ends with branching, which is with side effects, +// therefore, instructions in different blocks always have different InstructionGroupID(s). +// +// The notable application of this is used in lowering SSA-level instruction to a ISA specific instruction, +// where we eagerly try to merge multiple instructions into single operation etc. Such merging cannot be done +// if these instruction have different InstructionGroupID since it will change the semantics of a program. +// +// See passDeadCodeElimination. +type InstructionGroupID uint32 + +// Returns Value(s) produced by this instruction if any. +// The `first` is the first return value, and `rest` is the rest of the values. +func (i *Instruction) Returns() (first Value, rest []Value) { + if i.IsBranching() { + return ValueInvalid, nil + } + return i.rValue, i.rValues.View() +} + +// Return returns a Value(s) produced by this instruction if any. +// If there's multiple return values, only the first one is returned. +func (i *Instruction) Return() (first Value) { + return i.rValue +} + +// Args returns the arguments to this instruction. +func (i *Instruction) Args() (v1, v2, v3 Value, vs []Value) { + return i.v, i.v2, i.v3, i.vs.View() +} + +// Arg returns the first argument to this instruction. +func (i *Instruction) Arg() Value { + return i.v +} + +// Arg2 returns the first two arguments to this instruction. +func (i *Instruction) Arg2() (Value, Value) { + return i.v, i.v2 +} + +// ArgWithLane returns the first argument to this instruction, and the lane type. +func (i *Instruction) ArgWithLane() (Value, VecLane) { + return i.v, VecLane(i.u1) +} + +// Arg2WithLane returns the first two arguments to this instruction, and the lane type. +func (i *Instruction) Arg2WithLane() (Value, Value, VecLane) { + return i.v, i.v2, VecLane(i.u1) +} + +// ShuffleData returns the first two arguments to this instruction and 2 uint64s `lo`, `hi`. +// +// Note: Each uint64 encodes a sequence of 8 bytes where each byte encodes a VecLane, +// so that the 128bit integer `hi<<64|lo` packs a slice `[16]VecLane`, +// where `lane[0]` is the least significant byte, and `lane[n]` is shifted to offset `n*8`. +func (i *Instruction) ShuffleData() (v Value, v2 Value, lo uint64, hi uint64) { + return i.v, i.v2, i.u1, i.u2 +} + +// Arg3 returns the first three arguments to this instruction. +func (i *Instruction) Arg3() (Value, Value, Value) { + return i.v, i.v2, i.v3 +} + +// Next returns the next instruction laid out next to itself. +func (i *Instruction) Next() *Instruction { + return i.next +} + +// Prev returns the previous instruction laid out prior to itself. +func (i *Instruction) Prev() *Instruction { + return i.prev +} + +// IsBranching returns true if this instruction is a branching instruction. +func (i *Instruction) IsBranching() bool { + switch i.opcode { + case OpcodeJump, OpcodeBrz, OpcodeBrnz, OpcodeBrTable: + return true + default: + return false + } +} + +// TODO: complete opcode comments. +const ( + OpcodeInvalid Opcode = iota + + // OpcodeUndefined is a placeholder for undefined opcode. This can be used for debugging to intentionally + // cause a crash at certain point. + OpcodeUndefined + + // OpcodeJump takes the list of args to the `block` and unconditionally jumps to it. + OpcodeJump + + // OpcodeBrz branches into `blk` with `args` if the value `c` equals zero: `Brz c, blk, args`. + OpcodeBrz + + // OpcodeBrnz branches into `blk` with `args` if the value `c` is not zero: `Brnz c, blk, args`. + OpcodeBrnz + + // OpcodeBrTable takes the index value `index`, and branches into `labelX`. If the `index` is out of range, + // it branches into the last labelN: `BrTable index, [label1, label2, ... labelN]`. + OpcodeBrTable + + // OpcodeExitWithCode exit the execution immediately. + OpcodeExitWithCode + + // OpcodeExitIfTrueWithCode exits the execution immediately if the value `c` is not zero. + OpcodeExitIfTrueWithCode + + // OpcodeReturn returns from the function: `return rvalues`. + OpcodeReturn + + // OpcodeCall calls a function specified by the symbol FN with arguments `args`: `returnvals = Call FN, args...` + // This is a "near" call, which means the call target is known at compile time, and the target is relatively close + // to this function. If the target cannot be reached by near call, the backend fails to compile. + OpcodeCall + + // OpcodeCallIndirect calls a function specified by `callee` which is a function address: `returnvals = call_indirect SIG, callee, args`. + // Note that this is different from call_indirect in Wasm, which also does type checking, etc. + OpcodeCallIndirect + + // OpcodeSplat performs a vector splat operation: `v = Splat.lane x`. + OpcodeSplat + + // OpcodeSwizzle performs a vector swizzle operation: `v = Swizzle.lane x, y`. + OpcodeSwizzle + + // OpcodeInsertlane inserts a lane value into a vector: `v = InsertLane x, y, Idx`. + OpcodeInsertlane + + // OpcodeExtractlane extracts a lane value from a vector: `v = ExtractLane x, Idx`. + OpcodeExtractlane + + // OpcodeLoad loads a Type value from the [base + offset] address: `v = Load base, offset`. + OpcodeLoad + + // OpcodeStore stores a Type value to the [base + offset] address: `Store v, base, offset`. + OpcodeStore + + // OpcodeUload8 loads the 8-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload8 base, offset`. + OpcodeUload8 + + // OpcodeSload8 loads the 8-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload8 base, offset`. + OpcodeSload8 + + // OpcodeIstore8 stores the 8-bit value to the [base + offset] address, sign-extended to 64 bits: `Istore8 v, base, offset`. + OpcodeIstore8 + + // OpcodeUload16 loads the 16-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload16 base, offset`. + OpcodeUload16 + + // OpcodeSload16 loads the 16-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload16 base, offset`. + OpcodeSload16 + + // OpcodeIstore16 stores the 16-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`. + OpcodeIstore16 + + // OpcodeUload32 loads the 32-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload32 base, offset`. + OpcodeUload32 + + // OpcodeSload32 loads the 32-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload32 base, offset`. + OpcodeSload32 + + // OpcodeIstore32 stores the 32-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`. + OpcodeIstore32 + + // OpcodeLoadSplat represents a load that replicates the loaded value to all lanes `v = LoadSplat.lane p, Offset`. + OpcodeLoadSplat + + // OpcodeVZeroExtLoad loads a scalar single/double precision floating point value from the [p + Offset] address, + // and zero-extend it to the V128 value: `v = VExtLoad p, Offset`. + OpcodeVZeroExtLoad + + // OpcodeIconst represents the integer const. + OpcodeIconst + + // OpcodeF32const represents the single-precision const. + OpcodeF32const + + // OpcodeF64const represents the double-precision const. + OpcodeF64const + + // OpcodeVconst represents the 128bit vector const. + OpcodeVconst + + // OpcodeVbor computes binary or between two 128bit vectors: `v = bor x, y`. + OpcodeVbor + + // OpcodeVbxor computes binary xor between two 128bit vectors: `v = bxor x, y`. + OpcodeVbxor + + // OpcodeVband computes binary and between two 128bit vectors: `v = band x, y`. + OpcodeVband + + // OpcodeVbandnot computes binary and-not between two 128bit vectors: `v = bandnot x, y`. + OpcodeVbandnot + + // OpcodeVbnot negates a 128bit vector: `v = bnot x`. + OpcodeVbnot + + // OpcodeVbitselect uses the bits in the control mask c to select the corresponding bit from x when 1 + // and y when 0: `v = bitselect c, x, y`. + OpcodeVbitselect + + // OpcodeShuffle shuffles two vectors using the given 128-bit immediate: `v = shuffle imm, x, y`. + // For each byte in the immediate, a value i in [0, 15] selects the i-th byte in vector x; + // i in [16, 31] selects the (i-16)-th byte in vector y. + OpcodeShuffle + + // OpcodeSelect chooses between two values based on a condition `c`: `v = Select c, x, y`. + OpcodeSelect + + // OpcodeVanyTrue performs a any true operation: `s = VanyTrue a`. + OpcodeVanyTrue + + // OpcodeVallTrue performs a lane-wise all true operation: `s = VallTrue.lane a`. + OpcodeVallTrue + + // OpcodeVhighBits performs a lane-wise extract of the high bits: `v = VhighBits.lane a`. + OpcodeVhighBits + + // OpcodeIcmp compares two integer values with the given condition: `v = icmp Cond, x, y`. + OpcodeIcmp + + // OpcodeVIcmp compares two integer values with the given condition: `v = vicmp Cond, x, y` on vector. + OpcodeVIcmp + + // OpcodeIcmpImm compares an integer value with the immediate value on the given condition: `v = icmp_imm Cond, x, Y`. + OpcodeIcmpImm + + // OpcodeIadd performs an integer addition: `v = Iadd x, y`. + OpcodeIadd + + // OpcodeVIadd performs an integer addition: `v = VIadd.lane x, y` on vector. + OpcodeVIadd + + // OpcodeVSaddSat performs a signed saturating vector addition: `v = VSaddSat.lane x, y` on vector. + OpcodeVSaddSat + + // OpcodeVUaddSat performs an unsigned saturating vector addition: `v = VUaddSat.lane x, y` on vector. + OpcodeVUaddSat + + // OpcodeIsub performs an integer subtraction: `v = Isub x, y`. + OpcodeIsub + + // OpcodeVIsub performs an integer subtraction: `v = VIsub.lane x, y` on vector. + OpcodeVIsub + + // OpcodeVSsubSat performs a signed saturating vector subtraction: `v = VSsubSat.lane x, y` on vector. + OpcodeVSsubSat + + // OpcodeVUsubSat performs an unsigned saturating vector subtraction: `v = VUsubSat.lane x, y` on vector. + OpcodeVUsubSat + + // OpcodeVImin performs a signed integer min: `v = VImin.lane x, y` on vector. + OpcodeVImin + + // OpcodeVUmin performs an unsigned integer min: `v = VUmin.lane x, y` on vector. + OpcodeVUmin + + // OpcodeVImax performs a signed integer max: `v = VImax.lane x, y` on vector. + OpcodeVImax + + // OpcodeVUmax performs an unsigned integer max: `v = VUmax.lane x, y` on vector. + OpcodeVUmax + + // OpcodeVAvgRound performs an unsigned integer avg, truncating to zero: `v = VAvgRound.lane x, y` on vector. + OpcodeVAvgRound + + // OpcodeVImul performs an integer multiplication: `v = VImul.lane x, y` on vector. + OpcodeVImul + + // OpcodeVIneg negates the given integer vector value: `v = VIneg x`. + OpcodeVIneg + + // OpcodeVIpopcnt counts the number of 1-bits in the given vector: `v = VIpopcnt x`. + OpcodeVIpopcnt + + // OpcodeVIabs returns the absolute value for the given vector value: `v = VIabs.lane x`. + OpcodeVIabs + + // OpcodeVIshl shifts x left by (y mod lane-width): `v = VIshl.lane x, y` on vector. + OpcodeVIshl + + // OpcodeVUshr shifts x right by (y mod lane-width), unsigned: `v = VUshr.lane x, y` on vector. + OpcodeVUshr + + // OpcodeVSshr shifts x right by (y mod lane-width), signed: `v = VSshr.lane x, y` on vector. + OpcodeVSshr + + // OpcodeVFabs takes the absolute value of a floating point value: `v = VFabs.lane x on vector. + OpcodeVFabs + + // OpcodeVFmax takes the maximum of two floating point values: `v = VFmax.lane x, y on vector. + OpcodeVFmax + + // OpcodeVFmin takes the minimum of two floating point values: `v = VFmin.lane x, y on vector. + OpcodeVFmin + + // OpcodeVFneg negates the given floating point vector value: `v = VFneg x`. + OpcodeVFneg + + // OpcodeVFadd performs a floating point addition: `v = VFadd.lane x, y` on vector. + OpcodeVFadd + + // OpcodeVFsub performs a floating point subtraction: `v = VFsub.lane x, y` on vector. + OpcodeVFsub + + // OpcodeVFmul performs a floating point multiplication: `v = VFmul.lane x, y` on vector. + OpcodeVFmul + + // OpcodeVFdiv performs a floating point division: `v = VFdiv.lane x, y` on vector. + OpcodeVFdiv + + // OpcodeVFcmp compares two float values with the given condition: `v = VFcmp.lane Cond, x, y` on float. + OpcodeVFcmp + + // OpcodeVCeil takes the ceiling of the given floating point value: `v = ceil.lane x` on vector. + OpcodeVCeil + + // OpcodeVFloor takes the floor of the given floating point value: `v = floor.lane x` on vector. + OpcodeVFloor + + // OpcodeVTrunc takes the truncation of the given floating point value: `v = trunc.lane x` on vector. + OpcodeVTrunc + + // OpcodeVNearest takes the nearest integer of the given floating point value: `v = nearest.lane x` on vector. + OpcodeVNearest + + // OpcodeVMaxPseudo computes the lane-wise maximum value `v = VMaxPseudo.lane x, y` on vector defined as `x < y ? x : y`. + OpcodeVMaxPseudo + + // OpcodeVMinPseudo computes the lane-wise minimum value `v = VMinPseudo.lane x, y` on vector defined as `y < x ? x : y`. + OpcodeVMinPseudo + + // OpcodeVSqrt takes the minimum of two floating point values: `v = VFmin.lane x, y` on vector. + OpcodeVSqrt + + // OpcodeVFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat.lane x` on vector. + OpcodeVFcvtToUintSat + + // OpcodeVFcvtToSintSat converts a floating point value to a signed integer: `v = VFcvtToSintSat.lane x` on vector. + OpcodeVFcvtToSintSat + + // OpcodeVFcvtFromUint converts a floating point value from an unsigned integer: `v = FcvtFromUint.lane x` on vector. + // x is always a 32-bit integer lane, and the result is either a 32-bit or 64-bit floating point-sized vector. + OpcodeVFcvtFromUint + + // OpcodeVFcvtFromSint converts a floating point value from a signed integer: `v = VFcvtFromSint.lane x` on vector. + // x is always a 32-bit integer lane, and the result is either a 32-bit or 64-bit floating point-sized vector. + OpcodeVFcvtFromSint + + // OpcodeImul performs an integer multiplication: `v = Imul x, y`. + OpcodeImul + + // OpcodeUdiv performs the unsigned integer division `v = Udiv x, y`. + OpcodeUdiv + + // OpcodeSdiv performs the signed integer division `v = Sdiv x, y`. + OpcodeSdiv + + // OpcodeUrem computes the remainder of the unsigned integer division `v = Urem x, y`. + OpcodeUrem + + // OpcodeSrem computes the remainder of the signed integer division `v = Srem x, y`. + OpcodeSrem + + // OpcodeBand performs a binary and: `v = Band x, y`. + OpcodeBand + + // OpcodeBor performs a binary or: `v = Bor x, y`. + OpcodeBor + + // OpcodeBxor performs a binary xor: `v = Bxor x, y`. + OpcodeBxor + + // OpcodeBnot performs a binary not: `v = Bnot x`. + OpcodeBnot + + // OpcodeRotl rotates the given integer value to the left: `v = Rotl x, y`. + OpcodeRotl + + // OpcodeRotr rotates the given integer value to the right: `v = Rotr x, y`. + OpcodeRotr + + // OpcodeIshl does logical shift left: `v = Ishl x, y`. + OpcodeIshl + + // OpcodeUshr does logical shift right: `v = Ushr x, y`. + OpcodeUshr + + // OpcodeSshr does arithmetic shift right: `v = Sshr x, y`. + OpcodeSshr + + // OpcodeClz counts the number of leading zeros: `v = clz x`. + OpcodeClz + + // OpcodeCtz counts the number of trailing zeros: `v = ctz x`. + OpcodeCtz + + // OpcodePopcnt counts the number of 1-bits: `v = popcnt x`. + OpcodePopcnt + + // OpcodeFcmp compares two floating point values: `v = fcmp Cond, x, y`. + OpcodeFcmp + + // OpcodeFadd performs a floating point addition: / `v = Fadd x, y`. + OpcodeFadd + + // OpcodeFsub performs a floating point subtraction: `v = Fsub x, y`. + OpcodeFsub + + // OpcodeFmul performs a floating point multiplication: `v = Fmul x, y`. + OpcodeFmul + + // OpcodeSqmulRoundSat performs a lane-wise saturating rounding multiplication + // in Q15 format: `v = SqmulRoundSat.lane x,y` on vector. + OpcodeSqmulRoundSat + + // OpcodeFdiv performs a floating point division: `v = Fdiv x, y`. + OpcodeFdiv + + // OpcodeSqrt takes the square root of the given floating point value: `v = sqrt x`. + OpcodeSqrt + + // OpcodeFneg negates the given floating point value: `v = Fneg x`. + OpcodeFneg + + // OpcodeFabs takes the absolute value of the given floating point value: `v = fabs x`. + OpcodeFabs + + // OpcodeFcopysign copies the sign of the second floating point value to the first floating point value: + // `v = Fcopysign x, y`. + OpcodeFcopysign + + // OpcodeFmin takes the minimum of two floating point values: `v = fmin x, y`. + OpcodeFmin + + // OpcodeFmax takes the maximum of two floating point values: `v = fmax x, y`. + OpcodeFmax + + // OpcodeCeil takes the ceiling of the given floating point value: `v = ceil x`. + OpcodeCeil + + // OpcodeFloor takes the floor of the given floating point value: `v = floor x`. + OpcodeFloor + + // OpcodeTrunc takes the truncation of the given floating point value: `v = trunc x`. + OpcodeTrunc + + // OpcodeNearest takes the nearest integer of the given floating point value: `v = nearest x`. + OpcodeNearest + + // OpcodeBitcast is a bitcast operation: `v = bitcast x`. + OpcodeBitcast + + // OpcodeIreduce narrow the given integer: `v = Ireduce x`. + OpcodeIreduce + + // OpcodeSnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, signed `v = Snarrow.lane x, y`. + OpcodeSnarrow + + // OpcodeUnarrow converts two input vectors x, y into a smaller lane vector by narrowing each lane, unsigned `v = Unarrow.lane x, y`. + OpcodeUnarrow + + // OpcodeSwidenLow converts low half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenLow.lane x`. + OpcodeSwidenLow + + // OpcodeSwidenHigh converts high half of the smaller lane vector to a larger lane vector, sign extended: `v = SwidenHigh.lane x`. + OpcodeSwidenHigh + + // OpcodeUwidenLow converts low half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenLow.lane x`. + OpcodeUwidenLow + + // OpcodeUwidenHigh converts high half of the smaller lane vector to a larger lane vector, zero (unsigned) extended: `v = UwidenHigh.lane x`. + OpcodeUwidenHigh + + // OpcodeExtIaddPairwise is a lane-wise integer extended pairwise addition producing extended results (twice wider results than the inputs): `v = extiadd_pairwise x, y` on vector. + OpcodeExtIaddPairwise + + // OpcodeWideningPairwiseDotProductS is a lane-wise widening pairwise dot product with signed saturation: `v = WideningPairwiseDotProductS x, y` on vector. + // Currently, the only lane is i16, and the result is i32. + OpcodeWideningPairwiseDotProductS + + // OpcodeUExtend zero-extends the given integer: `v = UExtend x, from->to`. + OpcodeUExtend + + // OpcodeSExtend sign-extends the given integer: `v = SExtend x, from->to`. + OpcodeSExtend + + // OpcodeFpromote promotes the given floating point value: `v = Fpromote x`. + OpcodeFpromote + + // OpcodeFvpromoteLow converts the two lower single-precision floating point lanes + // to the two double-precision lanes of the result: `v = FvpromoteLow.lane x` on vector. + OpcodeFvpromoteLow + + // OpcodeFdemote demotes the given float point value: `v = Fdemote x`. + OpcodeFdemote + + // OpcodeFvdemote converts the two double-precision floating point lanes + // to two lower single-precision lanes of the result `v = Fvdemote.lane x`. + OpcodeFvdemote + + // OpcodeFcvtToUint converts a floating point value to an unsigned integer: `v = FcvtToUint x`. + OpcodeFcvtToUint + + // OpcodeFcvtToSint converts a floating point value to a signed integer: `v = FcvtToSint x`. + OpcodeFcvtToSint + + // OpcodeFcvtToUintSat converts a floating point value to an unsigned integer: `v = FcvtToUintSat x` which saturates on overflow. + OpcodeFcvtToUintSat + + // OpcodeFcvtToSintSat converts a floating point value to a signed integer: `v = FcvtToSintSat x` which saturates on overflow. + OpcodeFcvtToSintSat + + // OpcodeFcvtFromUint converts an unsigned integer to a floating point value: `v = FcvtFromUint x`. + OpcodeFcvtFromUint + + // OpcodeFcvtFromSint converts a signed integer to a floating point value: `v = FcvtFromSint x`. + OpcodeFcvtFromSint + + // OpcodeAtomicRmw is atomic read-modify-write operation: `v = atomic_rmw op, p, offset, value`. + OpcodeAtomicRmw + + // OpcodeAtomicCas is atomic compare-and-swap operation. + OpcodeAtomicCas + + // OpcodeAtomicLoad is atomic load operation. + OpcodeAtomicLoad + + // OpcodeAtomicStore is atomic store operation. + OpcodeAtomicStore + + // OpcodeFence is a memory fence operation. + OpcodeFence + + // opcodeEnd marks the end of the opcode list. + opcodeEnd +) + +// AtomicRmwOp represents the atomic read-modify-write operation. +type AtomicRmwOp byte + +const ( + // AtomicRmwOpAdd is an atomic add operation. + AtomicRmwOpAdd AtomicRmwOp = iota + // AtomicRmwOpSub is an atomic sub operation. + AtomicRmwOpSub + // AtomicRmwOpAnd is an atomic and operation. + AtomicRmwOpAnd + // AtomicRmwOpOr is an atomic or operation. + AtomicRmwOpOr + // AtomicRmwOpXor is an atomic xor operation. + AtomicRmwOpXor + // AtomicRmwOpXchg is an atomic swap operation. + AtomicRmwOpXchg +) + +// String implements the fmt.Stringer. +func (op AtomicRmwOp) String() string { + switch op { + case AtomicRmwOpAdd: + return "add" + case AtomicRmwOpSub: + return "sub" + case AtomicRmwOpAnd: + return "and" + case AtomicRmwOpOr: + return "or" + case AtomicRmwOpXor: + return "xor" + case AtomicRmwOpXchg: + return "xchg" + } + panic(fmt.Sprintf("unknown AtomicRmwOp: %d", op)) +} + +// returnTypesFn provides the info to determine the type of instruction. +// t1 is the type of the first result, ts are the types of the remaining results. +type returnTypesFn func(b *builder, instr *Instruction) (t1 Type, ts []Type) + +var ( + returnTypesFnNoReturns returnTypesFn = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return typeInvalid, nil } + returnTypesFnSingle = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return instr.typ, nil } + returnTypesFnI32 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeI32, nil } + returnTypesFnF32 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF32, nil } + returnTypesFnF64 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeF64, nil } + returnTypesFnV128 = func(b *builder, instr *Instruction) (t1 Type, ts []Type) { return TypeV128, nil } +) + +// sideEffect provides the info to determine if an instruction has side effects which +// is used to determine if it can be optimized out, interchanged with others, etc. +type sideEffect byte + +const ( + sideEffectUnknown sideEffect = iota + // sideEffectStrict represents an instruction with side effects, and should be always alive plus cannot be reordered. + sideEffectStrict + // sideEffectTraps represents an instruction that can trap, and should be always alive but can be reordered within the group. + sideEffectTraps + // sideEffectNone represents an instruction without side effects, and can be eliminated if the result is not used, plus can be reordered within the group. + sideEffectNone +) + +// instructionSideEffects provides the info to determine if an instruction has side effects. +// Instructions with side effects must not be eliminated regardless whether the result is used or not. +var instructionSideEffects = [opcodeEnd]sideEffect{ + OpcodeUndefined: sideEffectStrict, + OpcodeJump: sideEffectStrict, + OpcodeIconst: sideEffectNone, + OpcodeCall: sideEffectStrict, + OpcodeCallIndirect: sideEffectStrict, + OpcodeIadd: sideEffectNone, + OpcodeImul: sideEffectNone, + OpcodeIsub: sideEffectNone, + OpcodeIcmp: sideEffectNone, + OpcodeExtractlane: sideEffectNone, + OpcodeInsertlane: sideEffectNone, + OpcodeBand: sideEffectNone, + OpcodeBor: sideEffectNone, + OpcodeBxor: sideEffectNone, + OpcodeRotl: sideEffectNone, + OpcodeRotr: sideEffectNone, + OpcodeFcmp: sideEffectNone, + OpcodeFadd: sideEffectNone, + OpcodeClz: sideEffectNone, + OpcodeCtz: sideEffectNone, + OpcodePopcnt: sideEffectNone, + OpcodeLoad: sideEffectNone, + OpcodeLoadSplat: sideEffectNone, + OpcodeUload8: sideEffectNone, + OpcodeUload16: sideEffectNone, + OpcodeUload32: sideEffectNone, + OpcodeSload8: sideEffectNone, + OpcodeSload16: sideEffectNone, + OpcodeSload32: sideEffectNone, + OpcodeSExtend: sideEffectNone, + OpcodeUExtend: sideEffectNone, + OpcodeSwidenLow: sideEffectNone, + OpcodeUwidenLow: sideEffectNone, + OpcodeSwidenHigh: sideEffectNone, + OpcodeUwidenHigh: sideEffectNone, + OpcodeSnarrow: sideEffectNone, + OpcodeUnarrow: sideEffectNone, + OpcodeSwizzle: sideEffectNone, + OpcodeShuffle: sideEffectNone, + OpcodeSplat: sideEffectNone, + OpcodeFsub: sideEffectNone, + OpcodeF32const: sideEffectNone, + OpcodeF64const: sideEffectNone, + OpcodeIshl: sideEffectNone, + OpcodeSshr: sideEffectNone, + OpcodeUshr: sideEffectNone, + OpcodeStore: sideEffectStrict, + OpcodeIstore8: sideEffectStrict, + OpcodeIstore16: sideEffectStrict, + OpcodeIstore32: sideEffectStrict, + OpcodeExitWithCode: sideEffectStrict, + OpcodeExitIfTrueWithCode: sideEffectStrict, + OpcodeReturn: sideEffectStrict, + OpcodeBrz: sideEffectStrict, + OpcodeBrnz: sideEffectStrict, + OpcodeBrTable: sideEffectStrict, + OpcodeFdiv: sideEffectNone, + OpcodeFmul: sideEffectNone, + OpcodeFmax: sideEffectNone, + OpcodeSqmulRoundSat: sideEffectNone, + OpcodeSelect: sideEffectNone, + OpcodeFmin: sideEffectNone, + OpcodeFneg: sideEffectNone, + OpcodeFcvtToSint: sideEffectTraps, + OpcodeFcvtToUint: sideEffectTraps, + OpcodeFcvtFromSint: sideEffectNone, + OpcodeFcvtFromUint: sideEffectNone, + OpcodeFcvtToSintSat: sideEffectNone, + OpcodeFcvtToUintSat: sideEffectNone, + OpcodeVFcvtFromUint: sideEffectNone, + OpcodeVFcvtFromSint: sideEffectNone, + OpcodeFdemote: sideEffectNone, + OpcodeFvpromoteLow: sideEffectNone, + OpcodeFvdemote: sideEffectNone, + OpcodeFpromote: sideEffectNone, + OpcodeBitcast: sideEffectNone, + OpcodeIreduce: sideEffectNone, + OpcodeSqrt: sideEffectNone, + OpcodeCeil: sideEffectNone, + OpcodeFloor: sideEffectNone, + OpcodeTrunc: sideEffectNone, + OpcodeNearest: sideEffectNone, + OpcodeSdiv: sideEffectTraps, + OpcodeSrem: sideEffectTraps, + OpcodeUdiv: sideEffectTraps, + OpcodeUrem: sideEffectTraps, + OpcodeFabs: sideEffectNone, + OpcodeFcopysign: sideEffectNone, + OpcodeExtIaddPairwise: sideEffectNone, + OpcodeVconst: sideEffectNone, + OpcodeVbor: sideEffectNone, + OpcodeVbxor: sideEffectNone, + OpcodeVband: sideEffectNone, + OpcodeVbandnot: sideEffectNone, + OpcodeVbnot: sideEffectNone, + OpcodeVbitselect: sideEffectNone, + OpcodeVanyTrue: sideEffectNone, + OpcodeVallTrue: sideEffectNone, + OpcodeVhighBits: sideEffectNone, + OpcodeVIadd: sideEffectNone, + OpcodeVSaddSat: sideEffectNone, + OpcodeVUaddSat: sideEffectNone, + OpcodeVIsub: sideEffectNone, + OpcodeVSsubSat: sideEffectNone, + OpcodeVUsubSat: sideEffectNone, + OpcodeVIcmp: sideEffectNone, + OpcodeVImin: sideEffectNone, + OpcodeVUmin: sideEffectNone, + OpcodeVImax: sideEffectNone, + OpcodeVUmax: sideEffectNone, + OpcodeVAvgRound: sideEffectNone, + OpcodeVImul: sideEffectNone, + OpcodeVIabs: sideEffectNone, + OpcodeVIneg: sideEffectNone, + OpcodeVIpopcnt: sideEffectNone, + OpcodeVIshl: sideEffectNone, + OpcodeVSshr: sideEffectNone, + OpcodeVUshr: sideEffectNone, + OpcodeVSqrt: sideEffectNone, + OpcodeVFabs: sideEffectNone, + OpcodeVFmin: sideEffectNone, + OpcodeVFmax: sideEffectNone, + OpcodeVFneg: sideEffectNone, + OpcodeVFadd: sideEffectNone, + OpcodeVFsub: sideEffectNone, + OpcodeVFmul: sideEffectNone, + OpcodeVFdiv: sideEffectNone, + OpcodeVFcmp: sideEffectNone, + OpcodeVCeil: sideEffectNone, + OpcodeVFloor: sideEffectNone, + OpcodeVTrunc: sideEffectNone, + OpcodeVNearest: sideEffectNone, + OpcodeVMaxPseudo: sideEffectNone, + OpcodeVMinPseudo: sideEffectNone, + OpcodeVFcvtToUintSat: sideEffectNone, + OpcodeVFcvtToSintSat: sideEffectNone, + OpcodeVZeroExtLoad: sideEffectNone, + OpcodeAtomicRmw: sideEffectStrict, + OpcodeAtomicLoad: sideEffectStrict, + OpcodeAtomicStore: sideEffectStrict, + OpcodeAtomicCas: sideEffectStrict, + OpcodeFence: sideEffectStrict, + OpcodeWideningPairwiseDotProductS: sideEffectNone, +} + +// sideEffect returns true if this instruction has side effects. +func (i *Instruction) sideEffect() sideEffect { + if e := instructionSideEffects[i.opcode]; e == sideEffectUnknown { + panic("BUG: side effect info not registered for " + i.opcode.String()) + } else { + return e + } +} + +// instructionReturnTypes provides the function to determine the return types of an instruction. +var instructionReturnTypes = [opcodeEnd]returnTypesFn{ + OpcodeExtIaddPairwise: returnTypesFnV128, + OpcodeVbor: returnTypesFnV128, + OpcodeVbxor: returnTypesFnV128, + OpcodeVband: returnTypesFnV128, + OpcodeVbnot: returnTypesFnV128, + OpcodeVbandnot: returnTypesFnV128, + OpcodeVbitselect: returnTypesFnV128, + OpcodeVanyTrue: returnTypesFnI32, + OpcodeVallTrue: returnTypesFnI32, + OpcodeVhighBits: returnTypesFnI32, + OpcodeVIadd: returnTypesFnV128, + OpcodeVSaddSat: returnTypesFnV128, + OpcodeVUaddSat: returnTypesFnV128, + OpcodeVIsub: returnTypesFnV128, + OpcodeVSsubSat: returnTypesFnV128, + OpcodeVUsubSat: returnTypesFnV128, + OpcodeVIcmp: returnTypesFnV128, + OpcodeVImin: returnTypesFnV128, + OpcodeVUmin: returnTypesFnV128, + OpcodeVImax: returnTypesFnV128, + OpcodeVUmax: returnTypesFnV128, + OpcodeVImul: returnTypesFnV128, + OpcodeVAvgRound: returnTypesFnV128, + OpcodeVIabs: returnTypesFnV128, + OpcodeVIneg: returnTypesFnV128, + OpcodeVIpopcnt: returnTypesFnV128, + OpcodeVIshl: returnTypesFnV128, + OpcodeVSshr: returnTypesFnV128, + OpcodeVUshr: returnTypesFnV128, + OpcodeExtractlane: returnTypesFnSingle, + OpcodeInsertlane: returnTypesFnV128, + OpcodeBand: returnTypesFnSingle, + OpcodeFcopysign: returnTypesFnSingle, + OpcodeBitcast: returnTypesFnSingle, + OpcodeBor: returnTypesFnSingle, + OpcodeBxor: returnTypesFnSingle, + OpcodeRotl: returnTypesFnSingle, + OpcodeRotr: returnTypesFnSingle, + OpcodeIshl: returnTypesFnSingle, + OpcodeSshr: returnTypesFnSingle, + OpcodeSdiv: returnTypesFnSingle, + OpcodeSrem: returnTypesFnSingle, + OpcodeUdiv: returnTypesFnSingle, + OpcodeUrem: returnTypesFnSingle, + OpcodeUshr: returnTypesFnSingle, + OpcodeJump: returnTypesFnNoReturns, + OpcodeUndefined: returnTypesFnNoReturns, + OpcodeIconst: returnTypesFnSingle, + OpcodeSelect: returnTypesFnSingle, + OpcodeSExtend: returnTypesFnSingle, + OpcodeUExtend: returnTypesFnSingle, + OpcodeSwidenLow: returnTypesFnV128, + OpcodeUwidenLow: returnTypesFnV128, + OpcodeSwidenHigh: returnTypesFnV128, + OpcodeUwidenHigh: returnTypesFnV128, + OpcodeSnarrow: returnTypesFnV128, + OpcodeUnarrow: returnTypesFnV128, + OpcodeSwizzle: returnTypesFnSingle, + OpcodeShuffle: returnTypesFnV128, + OpcodeSplat: returnTypesFnV128, + OpcodeIreduce: returnTypesFnSingle, + OpcodeFabs: returnTypesFnSingle, + OpcodeSqrt: returnTypesFnSingle, + OpcodeCeil: returnTypesFnSingle, + OpcodeFloor: returnTypesFnSingle, + OpcodeTrunc: returnTypesFnSingle, + OpcodeNearest: returnTypesFnSingle, + OpcodeCallIndirect: func(b *builder, instr *Instruction) (t1 Type, ts []Type) { + sigID := SignatureID(instr.u1) + sig, ok := b.signatures[sigID] + if !ok { + panic("BUG") + } + switch len(sig.Results) { + case 0: + t1 = typeInvalid + case 1: + t1 = sig.Results[0] + default: + t1, ts = sig.Results[0], sig.Results[1:] + } + return + }, + OpcodeCall: func(b *builder, instr *Instruction) (t1 Type, ts []Type) { + sigID := SignatureID(instr.u2) + sig, ok := b.signatures[sigID] + if !ok { + panic("BUG") + } + switch len(sig.Results) { + case 0: + t1 = typeInvalid + case 1: + t1 = sig.Results[0] + default: + t1, ts = sig.Results[0], sig.Results[1:] + } + return + }, + OpcodeLoad: returnTypesFnSingle, + OpcodeVZeroExtLoad: returnTypesFnV128, + OpcodeLoadSplat: returnTypesFnV128, + OpcodeIadd: returnTypesFnSingle, + OpcodeIsub: returnTypesFnSingle, + OpcodeImul: returnTypesFnSingle, + OpcodeIcmp: returnTypesFnI32, + OpcodeFcmp: returnTypesFnI32, + OpcodeFadd: returnTypesFnSingle, + OpcodeFsub: returnTypesFnSingle, + OpcodeFdiv: returnTypesFnSingle, + OpcodeFmul: returnTypesFnSingle, + OpcodeFmax: returnTypesFnSingle, + OpcodeFmin: returnTypesFnSingle, + OpcodeSqmulRoundSat: returnTypesFnV128, + OpcodeF32const: returnTypesFnF32, + OpcodeF64const: returnTypesFnF64, + OpcodeClz: returnTypesFnSingle, + OpcodeCtz: returnTypesFnSingle, + OpcodePopcnt: returnTypesFnSingle, + OpcodeStore: returnTypesFnNoReturns, + OpcodeIstore8: returnTypesFnNoReturns, + OpcodeIstore16: returnTypesFnNoReturns, + OpcodeIstore32: returnTypesFnNoReturns, + OpcodeExitWithCode: returnTypesFnNoReturns, + OpcodeExitIfTrueWithCode: returnTypesFnNoReturns, + OpcodeReturn: returnTypesFnNoReturns, + OpcodeBrz: returnTypesFnNoReturns, + OpcodeBrnz: returnTypesFnNoReturns, + OpcodeBrTable: returnTypesFnNoReturns, + OpcodeUload8: returnTypesFnSingle, + OpcodeUload16: returnTypesFnSingle, + OpcodeUload32: returnTypesFnSingle, + OpcodeSload8: returnTypesFnSingle, + OpcodeSload16: returnTypesFnSingle, + OpcodeSload32: returnTypesFnSingle, + OpcodeFcvtToSint: returnTypesFnSingle, + OpcodeFcvtToUint: returnTypesFnSingle, + OpcodeFcvtFromSint: returnTypesFnSingle, + OpcodeFcvtFromUint: returnTypesFnSingle, + OpcodeFcvtToSintSat: returnTypesFnSingle, + OpcodeFcvtToUintSat: returnTypesFnSingle, + OpcodeVFcvtFromUint: returnTypesFnV128, + OpcodeVFcvtFromSint: returnTypesFnV128, + OpcodeFneg: returnTypesFnSingle, + OpcodeFdemote: returnTypesFnF32, + OpcodeFvdemote: returnTypesFnV128, + OpcodeFvpromoteLow: returnTypesFnV128, + OpcodeFpromote: returnTypesFnF64, + OpcodeVconst: returnTypesFnV128, + OpcodeVFabs: returnTypesFnV128, + OpcodeVSqrt: returnTypesFnV128, + OpcodeVFmax: returnTypesFnV128, + OpcodeVFmin: returnTypesFnV128, + OpcodeVFneg: returnTypesFnV128, + OpcodeVFadd: returnTypesFnV128, + OpcodeVFsub: returnTypesFnV128, + OpcodeVFmul: returnTypesFnV128, + OpcodeVFdiv: returnTypesFnV128, + OpcodeVFcmp: returnTypesFnV128, + OpcodeVCeil: returnTypesFnV128, + OpcodeVFloor: returnTypesFnV128, + OpcodeVTrunc: returnTypesFnV128, + OpcodeVNearest: returnTypesFnV128, + OpcodeVMaxPseudo: returnTypesFnV128, + OpcodeVMinPseudo: returnTypesFnV128, + OpcodeVFcvtToUintSat: returnTypesFnV128, + OpcodeVFcvtToSintSat: returnTypesFnV128, + OpcodeAtomicRmw: returnTypesFnSingle, + OpcodeAtomicLoad: returnTypesFnSingle, + OpcodeAtomicStore: returnTypesFnNoReturns, + OpcodeAtomicCas: returnTypesFnSingle, + OpcodeFence: returnTypesFnNoReturns, + OpcodeWideningPairwiseDotProductS: returnTypesFnV128, +} + +// AsLoad initializes this instruction as a store instruction with OpcodeLoad. +func (i *Instruction) AsLoad(ptr Value, offset uint32, typ Type) *Instruction { + i.opcode = OpcodeLoad + i.v = ptr + i.u1 = uint64(offset) + i.typ = typ + return i +} + +// AsExtLoad initializes this instruction as a store instruction with OpcodeLoad. +func (i *Instruction) AsExtLoad(op Opcode, ptr Value, offset uint32, dst64bit bool) *Instruction { + i.opcode = op + i.v = ptr + i.u1 = uint64(offset) + if dst64bit { + i.typ = TypeI64 + } else { + i.typ = TypeI32 + } + return i +} + +// AsVZeroExtLoad initializes this instruction as a store instruction with OpcodeVExtLoad. +func (i *Instruction) AsVZeroExtLoad(ptr Value, offset uint32, scalarType Type) *Instruction { + i.opcode = OpcodeVZeroExtLoad + i.v = ptr + i.u1 = uint64(offset) + i.u2 = uint64(scalarType) + i.typ = TypeV128 + return i +} + +// VZeroExtLoadData returns the operands for a load instruction. The returned `typ` is the scalar type of the load target. +func (i *Instruction) VZeroExtLoadData() (ptr Value, offset uint32, typ Type) { + return i.v, uint32(i.u1), Type(i.u2) +} + +// AsLoadSplat initializes this instruction as a store instruction with OpcodeLoadSplat. +func (i *Instruction) AsLoadSplat(ptr Value, offset uint32, lane VecLane) *Instruction { + i.opcode = OpcodeLoadSplat + i.v = ptr + i.u1 = uint64(offset) + i.u2 = uint64(lane) + i.typ = TypeV128 + return i +} + +// LoadData returns the operands for a load instruction. +func (i *Instruction) LoadData() (ptr Value, offset uint32, typ Type) { + return i.v, uint32(i.u1), i.typ +} + +// LoadSplatData returns the operands for a load splat instruction. +func (i *Instruction) LoadSplatData() (ptr Value, offset uint32, lane VecLane) { + return i.v, uint32(i.u1), VecLane(i.u2) +} + +// AsStore initializes this instruction as a store instruction with OpcodeStore. +func (i *Instruction) AsStore(storeOp Opcode, value, ptr Value, offset uint32) *Instruction { + i.opcode = storeOp + i.v = value + i.v2 = ptr + + var dstSize uint64 + switch storeOp { + case OpcodeStore: + dstSize = uint64(value.Type().Bits()) + case OpcodeIstore8: + dstSize = 8 + case OpcodeIstore16: + dstSize = 16 + case OpcodeIstore32: + dstSize = 32 + default: + panic("invalid store opcode" + storeOp.String()) + } + i.u1 = uint64(offset) | dstSize<<32 + return i +} + +// StoreData returns the operands for a store instruction. +func (i *Instruction) StoreData() (value, ptr Value, offset uint32, storeSizeInBits byte) { + return i.v, i.v2, uint32(i.u1), byte(i.u1 >> 32) +} + +// AsIconst64 initializes this instruction as a 64-bit integer constant instruction with OpcodeIconst. +func (i *Instruction) AsIconst64(v uint64) *Instruction { + i.opcode = OpcodeIconst + i.typ = TypeI64 + i.u1 = v + return i +} + +// AsIconst32 initializes this instruction as a 32-bit integer constant instruction with OpcodeIconst. +func (i *Instruction) AsIconst32(v uint32) *Instruction { + i.opcode = OpcodeIconst + i.typ = TypeI32 + i.u1 = uint64(v) + return i +} + +// AsIadd initializes this instruction as an integer addition instruction with OpcodeIadd. +func (i *Instruction) AsIadd(x, y Value) *Instruction { + i.opcode = OpcodeIadd + i.v = x + i.v2 = y + i.typ = x.Type() + return i +} + +// AsVIadd initializes this instruction as an integer addition instruction with OpcodeVIadd on a vector. +func (i *Instruction) AsVIadd(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVIadd + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsWideningPairwiseDotProductS initializes this instruction as a lane-wise integer extended pairwise addition instruction +// with OpcodeIaddPairwise on a vector. +func (i *Instruction) AsWideningPairwiseDotProductS(x, y Value) *Instruction { + i.opcode = OpcodeWideningPairwiseDotProductS + i.v = x + i.v2 = y + i.typ = TypeV128 + return i +} + +// AsExtIaddPairwise initializes this instruction as a lane-wise integer extended pairwise addition instruction +// with OpcodeIaddPairwise on a vector. +func (i *Instruction) AsExtIaddPairwise(x Value, srcLane VecLane, signed bool) *Instruction { + i.opcode = OpcodeExtIaddPairwise + i.v = x + i.u1 = uint64(srcLane) + if signed { + i.u2 = 1 + } + i.typ = TypeV128 + return i +} + +// ExtIaddPairwiseData returns the operands for a lane-wise integer extended pairwise addition instruction. +func (i *Instruction) ExtIaddPairwiseData() (x Value, srcLane VecLane, signed bool) { + return i.v, VecLane(i.u1), i.u2 != 0 +} + +// AsVSaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSaddSat on a vector. +func (i *Instruction) AsVSaddSat(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVSaddSat + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVUaddSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUaddSat on a vector. +func (i *Instruction) AsVUaddSat(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVUaddSat + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVIsub initializes this instruction as an integer subtraction instruction with OpcodeVIsub on a vector. +func (i *Instruction) AsVIsub(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVIsub + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVSsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVSsubSat on a vector. +func (i *Instruction) AsVSsubSat(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVSsubSat + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVUsubSat initializes this instruction as a vector addition with saturation instruction with OpcodeVUsubSat on a vector. +func (i *Instruction) AsVUsubSat(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVUsubSat + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVImin initializes this instruction as a signed integer min instruction with OpcodeVImin on a vector. +func (i *Instruction) AsVImin(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVImin + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVUmin initializes this instruction as an unsigned integer min instruction with OpcodeVUmin on a vector. +func (i *Instruction) AsVUmin(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVUmin + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVImax initializes this instruction as a signed integer max instruction with OpcodeVImax on a vector. +func (i *Instruction) AsVImax(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVImax + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVUmax initializes this instruction as an unsigned integer max instruction with OpcodeVUmax on a vector. +func (i *Instruction) AsVUmax(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVUmax + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVAvgRound initializes this instruction as an unsigned integer avg instruction, truncating to zero with OpcodeVAvgRound on a vector. +func (i *Instruction) AsVAvgRound(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVAvgRound + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVImul initializes this instruction as an integer multiplication with OpcodeVImul on a vector. +func (i *Instruction) AsVImul(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVImul + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsSqmulRoundSat initializes this instruction as a lane-wise saturating rounding multiplication +// in Q15 format with OpcodeSqmulRoundSat on a vector. +func (i *Instruction) AsSqmulRoundSat(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeSqmulRoundSat + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVIabs initializes this instruction as a vector absolute value with OpcodeVIabs. +func (i *Instruction) AsVIabs(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVIabs + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVIneg initializes this instruction as a vector negation with OpcodeVIneg. +func (i *Instruction) AsVIneg(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVIneg + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVIpopcnt initializes this instruction as a Population Count instruction with OpcodeVIpopcnt on a vector. +func (i *Instruction) AsVIpopcnt(x Value, lane VecLane) *Instruction { + if lane != VecLaneI8x16 { + panic("Unsupported lane type " + lane.String()) + } + i.opcode = OpcodeVIpopcnt + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVSqrt initializes this instruction as a sqrt instruction with OpcodeVSqrt on a vector. +func (i *Instruction) AsVSqrt(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVSqrt + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFabs initializes this instruction as a float abs instruction with OpcodeVFabs on a vector. +func (i *Instruction) AsVFabs(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFabs + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFneg initializes this instruction as a float neg instruction with OpcodeVFneg on a vector. +func (i *Instruction) AsVFneg(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFneg + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFmax initializes this instruction as a float max instruction with OpcodeVFmax on a vector. +func (i *Instruction) AsVFmax(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFmax + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFmin initializes this instruction as a float min instruction with OpcodeVFmin on a vector. +func (i *Instruction) AsVFmin(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFmin + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFadd initializes this instruction as a floating point add instruction with OpcodeVFadd on a vector. +func (i *Instruction) AsVFadd(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFadd + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFsub initializes this instruction as a floating point subtraction instruction with OpcodeVFsub on a vector. +func (i *Instruction) AsVFsub(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFsub + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFmul initializes this instruction as a floating point multiplication instruction with OpcodeVFmul on a vector. +func (i *Instruction) AsVFmul(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFmul + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFdiv initializes this instruction as a floating point division instruction with OpcodeVFdiv on a vector. +func (i *Instruction) AsVFdiv(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFdiv + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsImul initializes this instruction as an integer addition instruction with OpcodeImul. +func (i *Instruction) AsImul(x, y Value) *Instruction { + i.opcode = OpcodeImul + i.v = x + i.v2 = y + i.typ = x.Type() + return i +} + +func (i *Instruction) Insert(b Builder) *Instruction { + b.InsertInstruction(i) + return i +} + +// AsIsub initializes this instruction as an integer subtraction instruction with OpcodeIsub. +func (i *Instruction) AsIsub(x, y Value) *Instruction { + i.opcode = OpcodeIsub + i.v = x + i.v2 = y + i.typ = x.Type() + return i +} + +// AsIcmp initializes this instruction as an integer comparison instruction with OpcodeIcmp. +func (i *Instruction) AsIcmp(x, y Value, c IntegerCmpCond) *Instruction { + i.opcode = OpcodeIcmp + i.v = x + i.v2 = y + i.u1 = uint64(c) + i.typ = TypeI32 + return i +} + +// AsFcmp initializes this instruction as an integer comparison instruction with OpcodeFcmp. +func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond) { + i.opcode = OpcodeFcmp + i.v = x + i.v2 = y + i.u1 = uint64(c) + i.typ = TypeI32 +} + +// AsVIcmp initializes this instruction as an integer vector comparison instruction with OpcodeVIcmp. +func (i *Instruction) AsVIcmp(x, y Value, c IntegerCmpCond, lane VecLane) *Instruction { + i.opcode = OpcodeVIcmp + i.v = x + i.v2 = y + i.u1 = uint64(c) + i.u2 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsVFcmp initializes this instruction as a float comparison instruction with OpcodeVFcmp on Vector. +func (i *Instruction) AsVFcmp(x, y Value, c FloatCmpCond, lane VecLane) *Instruction { + i.opcode = OpcodeVFcmp + i.v = x + i.v2 = y + i.u1 = uint64(c) + i.typ = TypeV128 + i.u2 = uint64(lane) + return i +} + +// AsVCeil initializes this instruction as an instruction with OpcodeCeil. +func (i *Instruction) AsVCeil(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVCeil + i.v = x + i.typ = x.Type() + i.u1 = uint64(lane) + return i +} + +// AsVFloor initializes this instruction as an instruction with OpcodeFloor. +func (i *Instruction) AsVFloor(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVFloor + i.v = x + i.typ = x.Type() + i.u1 = uint64(lane) + return i +} + +// AsVTrunc initializes this instruction as an instruction with OpcodeTrunc. +func (i *Instruction) AsVTrunc(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVTrunc + i.v = x + i.typ = x.Type() + i.u1 = uint64(lane) + return i +} + +// AsVNearest initializes this instruction as an instruction with OpcodeNearest. +func (i *Instruction) AsVNearest(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVNearest + i.v = x + i.typ = x.Type() + i.u1 = uint64(lane) + return i +} + +// AsVMaxPseudo initializes this instruction as an instruction with OpcodeVMaxPseudo. +func (i *Instruction) AsVMaxPseudo(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVMaxPseudo + i.typ = x.Type() + i.v = x + i.v2 = y + i.u1 = uint64(lane) + return i +} + +// AsVMinPseudo initializes this instruction as an instruction with OpcodeVMinPseudo. +func (i *Instruction) AsVMinPseudo(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeVMinPseudo + i.typ = x.Type() + i.v = x + i.v2 = y + i.u1 = uint64(lane) + return i +} + +// AsSDiv initializes this instruction as an integer bitwise and instruction with OpcodeSdiv. +func (i *Instruction) AsSDiv(x, y, ctx Value) *Instruction { + i.opcode = OpcodeSdiv + i.v = x + i.v2 = y + i.v3 = ctx + i.typ = x.Type() + return i +} + +// AsUDiv initializes this instruction as an integer bitwise and instruction with OpcodeUdiv. +func (i *Instruction) AsUDiv(x, y, ctx Value) *Instruction { + i.opcode = OpcodeUdiv + i.v = x + i.v2 = y + i.v3 = ctx + i.typ = x.Type() + return i +} + +// AsSRem initializes this instruction as an integer bitwise and instruction with OpcodeSrem. +func (i *Instruction) AsSRem(x, y, ctx Value) *Instruction { + i.opcode = OpcodeSrem + i.v = x + i.v2 = y + i.v3 = ctx + i.typ = x.Type() + return i +} + +// AsURem initializes this instruction as an integer bitwise and instruction with OpcodeUrem. +func (i *Instruction) AsURem(x, y, ctx Value) *Instruction { + i.opcode = OpcodeUrem + i.v = x + i.v2 = y + i.v3 = ctx + i.typ = x.Type() + return i +} + +// AsBand initializes this instruction as an integer bitwise and instruction with OpcodeBand. +func (i *Instruction) AsBand(x, amount Value) *Instruction { + i.opcode = OpcodeBand + i.v = x + i.v2 = amount + i.typ = x.Type() + return i +} + +// AsBor initializes this instruction as an integer bitwise or instruction with OpcodeBor. +func (i *Instruction) AsBor(x, amount Value) { + i.opcode = OpcodeBor + i.v = x + i.v2 = amount + i.typ = x.Type() +} + +// AsBxor initializes this instruction as an integer bitwise xor instruction with OpcodeBxor. +func (i *Instruction) AsBxor(x, amount Value) { + i.opcode = OpcodeBxor + i.v = x + i.v2 = amount + i.typ = x.Type() +} + +// AsIshl initializes this instruction as an integer shift left instruction with OpcodeIshl. +func (i *Instruction) AsIshl(x, amount Value) *Instruction { + i.opcode = OpcodeIshl + i.v = x + i.v2 = amount + i.typ = x.Type() + return i +} + +// AsVIshl initializes this instruction as an integer shift left instruction with OpcodeVIshl on vector. +func (i *Instruction) AsVIshl(x, amount Value, lane VecLane) *Instruction { + i.opcode = OpcodeVIshl + i.v = x + i.v2 = amount + i.u1 = uint64(lane) + i.typ = x.Type() + return i +} + +// AsUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeUshr. +func (i *Instruction) AsUshr(x, amount Value) *Instruction { + i.opcode = OpcodeUshr + i.v = x + i.v2 = amount + i.typ = x.Type() + return i +} + +// AsVUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeVUshr on vector. +func (i *Instruction) AsVUshr(x, amount Value, lane VecLane) *Instruction { + i.opcode = OpcodeVUshr + i.v = x + i.v2 = amount + i.u1 = uint64(lane) + i.typ = x.Type() + return i +} + +// AsSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeSshr. +func (i *Instruction) AsSshr(x, amount Value) *Instruction { + i.opcode = OpcodeSshr + i.v = x + i.v2 = amount + i.typ = x.Type() + return i +} + +// AsVSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeVSshr on vector. +func (i *Instruction) AsVSshr(x, amount Value, lane VecLane) *Instruction { + i.opcode = OpcodeVSshr + i.v = x + i.v2 = amount + i.u1 = uint64(lane) + i.typ = x.Type() + return i +} + +// AsExtractlane initializes this instruction as an extract lane instruction with OpcodeExtractlane on vector. +func (i *Instruction) AsExtractlane(x Value, index byte, lane VecLane, signed bool) *Instruction { + i.opcode = OpcodeExtractlane + i.v = x + // We do not have a field for signedness, but `index` is a byte, + // so we just encode the flag in the high bits of `u1`. + i.u1 = uint64(index) + if signed { + i.u1 = i.u1 | 1<<32 + } + i.u2 = uint64(lane) + switch lane { + case VecLaneI8x16, VecLaneI16x8, VecLaneI32x4: + i.typ = TypeI32 + case VecLaneI64x2: + i.typ = TypeI64 + case VecLaneF32x4: + i.typ = TypeF32 + case VecLaneF64x2: + i.typ = TypeF64 + } + return i +} + +// AsInsertlane initializes this instruction as an insert lane instruction with OpcodeInsertlane on vector. +func (i *Instruction) AsInsertlane(x, y Value, index byte, lane VecLane) *Instruction { + i.opcode = OpcodeInsertlane + i.v = x + i.v2 = y + i.u1 = uint64(index) + i.u2 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsShuffle initializes this instruction as a shuffle instruction with OpcodeShuffle on vector. +func (i *Instruction) AsShuffle(x, y Value, lane []byte) *Instruction { + i.opcode = OpcodeShuffle + i.v = x + i.v2 = y + // Encode the 16 bytes as 8 bytes in u1, and 8 bytes in u2. + i.u1 = uint64(lane[7])<<56 | uint64(lane[6])<<48 | uint64(lane[5])<<40 | uint64(lane[4])<<32 | uint64(lane[3])<<24 | uint64(lane[2])<<16 | uint64(lane[1])<<8 | uint64(lane[0]) + i.u2 = uint64(lane[15])<<56 | uint64(lane[14])<<48 | uint64(lane[13])<<40 | uint64(lane[12])<<32 | uint64(lane[11])<<24 | uint64(lane[10])<<16 | uint64(lane[9])<<8 | uint64(lane[8]) + i.typ = TypeV128 + return i +} + +// AsSwizzle initializes this instruction as an insert lane instruction with OpcodeSwizzle on vector. +func (i *Instruction) AsSwizzle(x, y Value, lane VecLane) *Instruction { + i.opcode = OpcodeSwizzle + i.v = x + i.v2 = y + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsSplat initializes this instruction as an insert lane instruction with OpcodeSplat on vector. +func (i *Instruction) AsSplat(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeSplat + i.v = x + i.u1 = uint64(lane) + i.typ = TypeV128 + return i +} + +// AsRotl initializes this instruction as a word rotate left instruction with OpcodeRotl. +func (i *Instruction) AsRotl(x, amount Value) { + i.opcode = OpcodeRotl + i.v = x + i.v2 = amount + i.typ = x.Type() +} + +// AsRotr initializes this instruction as a word rotate right instruction with OpcodeRotr. +func (i *Instruction) AsRotr(x, amount Value) { + i.opcode = OpcodeRotr + i.v = x + i.v2 = amount + i.typ = x.Type() +} + +// IcmpData returns the operands and comparison condition of this integer comparison instruction. +func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond) { + return i.v, i.v2, IntegerCmpCond(i.u1) +} + +// FcmpData returns the operands and comparison condition of this floating-point comparison instruction. +func (i *Instruction) FcmpData() (x, y Value, c FloatCmpCond) { + return i.v, i.v2, FloatCmpCond(i.u1) +} + +// VIcmpData returns the operands and comparison condition of this integer comparison instruction on vector. +func (i *Instruction) VIcmpData() (x, y Value, c IntegerCmpCond, l VecLane) { + return i.v, i.v2, IntegerCmpCond(i.u1), VecLane(i.u2) +} + +// VFcmpData returns the operands and comparison condition of this float comparison instruction on vector. +func (i *Instruction) VFcmpData() (x, y Value, c FloatCmpCond, l VecLane) { + return i.v, i.v2, FloatCmpCond(i.u1), VecLane(i.u2) +} + +// ExtractlaneData returns the operands and sign flag of Extractlane on vector. +func (i *Instruction) ExtractlaneData() (x Value, index byte, signed bool, l VecLane) { + x = i.v + index = byte(0b00001111 & i.u1) + signed = i.u1>>32 != 0 + l = VecLane(i.u2) + return +} + +// InsertlaneData returns the operands and sign flag of Insertlane on vector. +func (i *Instruction) InsertlaneData() (x, y Value, index byte, l VecLane) { + x = i.v + y = i.v2 + index = byte(i.u1) + l = VecLane(i.u2) + return +} + +// AsFadd initializes this instruction as a floating-point addition instruction with OpcodeFadd. +func (i *Instruction) AsFadd(x, y Value) { + i.opcode = OpcodeFadd + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsFsub initializes this instruction as a floating-point subtraction instruction with OpcodeFsub. +func (i *Instruction) AsFsub(x, y Value) { + i.opcode = OpcodeFsub + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsFmul initializes this instruction as a floating-point multiplication instruction with OpcodeFmul. +func (i *Instruction) AsFmul(x, y Value) { + i.opcode = OpcodeFmul + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsFdiv initializes this instruction as a floating-point division instruction with OpcodeFdiv. +func (i *Instruction) AsFdiv(x, y Value) { + i.opcode = OpcodeFdiv + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsFmin initializes this instruction to take the minimum of two floating-points with OpcodeFmin. +func (i *Instruction) AsFmin(x, y Value) { + i.opcode = OpcodeFmin + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsFmax initializes this instruction to take the maximum of two floating-points with OpcodeFmax. +func (i *Instruction) AsFmax(x, y Value) { + i.opcode = OpcodeFmax + i.v = x + i.v2 = y + i.typ = x.Type() +} + +// AsF32const initializes this instruction as a 32-bit floating-point constant instruction with OpcodeF32const. +func (i *Instruction) AsF32const(f float32) *Instruction { + i.opcode = OpcodeF32const + i.typ = TypeF64 + i.u1 = uint64(math.Float32bits(f)) + return i +} + +// AsF64const initializes this instruction as a 64-bit floating-point constant instruction with OpcodeF64const. +func (i *Instruction) AsF64const(f float64) *Instruction { + i.opcode = OpcodeF64const + i.typ = TypeF64 + i.u1 = math.Float64bits(f) + return i +} + +// AsVconst initializes this instruction as a vector constant instruction with OpcodeVconst. +func (i *Instruction) AsVconst(lo, hi uint64) *Instruction { + i.opcode = OpcodeVconst + i.typ = TypeV128 + i.u1 = lo + i.u2 = hi + return i +} + +// AsVbnot initializes this instruction as a vector negation instruction with OpcodeVbnot. +func (i *Instruction) AsVbnot(v Value) *Instruction { + i.opcode = OpcodeVbnot + i.typ = TypeV128 + i.v = v + return i +} + +// AsVband initializes this instruction as an and vector instruction with OpcodeVband. +func (i *Instruction) AsVband(x, y Value) *Instruction { + i.opcode = OpcodeVband + i.typ = TypeV128 + i.v = x + i.v2 = y + return i +} + +// AsVbor initializes this instruction as an or vector instruction with OpcodeVbor. +func (i *Instruction) AsVbor(x, y Value) *Instruction { + i.opcode = OpcodeVbor + i.typ = TypeV128 + i.v = x + i.v2 = y + return i +} + +// AsVbxor initializes this instruction as a xor vector instruction with OpcodeVbxor. +func (i *Instruction) AsVbxor(x, y Value) *Instruction { + i.opcode = OpcodeVbxor + i.typ = TypeV128 + i.v = x + i.v2 = y + return i +} + +// AsVbandnot initializes this instruction as an and-not vector instruction with OpcodeVbandnot. +func (i *Instruction) AsVbandnot(x, y Value) *Instruction { + i.opcode = OpcodeVbandnot + i.typ = TypeV128 + i.v = x + i.v2 = y + return i +} + +// AsVbitselect initializes this instruction as a bit select vector instruction with OpcodeVbitselect. +func (i *Instruction) AsVbitselect(c, x, y Value) *Instruction { + i.opcode = OpcodeVbitselect + i.typ = TypeV128 + i.v = c + i.v2 = x + i.v3 = y + return i +} + +// AsVanyTrue initializes this instruction as an anyTrue vector instruction with OpcodeVanyTrue. +func (i *Instruction) AsVanyTrue(x Value) *Instruction { + i.opcode = OpcodeVanyTrue + i.typ = TypeI32 + i.v = x + return i +} + +// AsVallTrue initializes this instruction as an allTrue vector instruction with OpcodeVallTrue. +func (i *Instruction) AsVallTrue(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVallTrue + i.typ = TypeI32 + i.v = x + i.u1 = uint64(lane) + return i +} + +// AsVhighBits initializes this instruction as a highBits vector instruction with OpcodeVhighBits. +func (i *Instruction) AsVhighBits(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeVhighBits + i.typ = TypeI32 + i.v = x + i.u1 = uint64(lane) + return i +} + +// VconstData returns the operands of this vector constant instruction. +func (i *Instruction) VconstData() (lo, hi uint64) { + return i.u1, i.u2 +} + +// AsReturn initializes this instruction as a return instruction with OpcodeReturn. +func (i *Instruction) AsReturn(vs wazevoapi.VarLength[Value]) *Instruction { + i.opcode = OpcodeReturn + i.vs = vs + return i +} + +// AsIreduce initializes this instruction as a reduction instruction with OpcodeIreduce. +func (i *Instruction) AsIreduce(v Value, dstType Type) *Instruction { + i.opcode = OpcodeIreduce + i.v = v + i.typ = dstType + return i +} + +// AsWiden initializes this instruction as a signed or unsigned widen instruction +// on low half or high half of the given vector with OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh. +func (i *Instruction) AsWiden(v Value, lane VecLane, signed, low bool) *Instruction { + switch { + case signed && low: + i.opcode = OpcodeSwidenLow + case !signed && low: + i.opcode = OpcodeUwidenLow + case signed && !low: + i.opcode = OpcodeSwidenHigh + case !signed && !low: + i.opcode = OpcodeUwidenHigh + } + i.v = v + i.u1 = uint64(lane) + return i +} + +// AsAtomicLoad initializes this instruction as an atomic load. +// The size is in bytes and must be 1, 2, 4, or 8. +func (i *Instruction) AsAtomicLoad(addr Value, size uint64, typ Type) *Instruction { + i.opcode = OpcodeAtomicLoad + i.u1 = size + i.v = addr + i.typ = typ + return i +} + +// AsAtomicLoad initializes this instruction as an atomic store. +// The size is in bytes and must be 1, 2, 4, or 8. +func (i *Instruction) AsAtomicStore(addr, val Value, size uint64) *Instruction { + i.opcode = OpcodeAtomicStore + i.u1 = size + i.v = addr + i.v2 = val + i.typ = val.Type() + return i +} + +// AsAtomicRmw initializes this instruction as an atomic read-modify-write. +// The size is in bytes and must be 1, 2, 4, or 8. +func (i *Instruction) AsAtomicRmw(op AtomicRmwOp, addr, val Value, size uint64) *Instruction { + i.opcode = OpcodeAtomicRmw + i.u1 = uint64(op) + i.u2 = size + i.v = addr + i.v2 = val + i.typ = val.Type() + return i +} + +// AsAtomicCas initializes this instruction as an atomic compare-and-swap. +// The size is in bytes and must be 1, 2, 4, or 8. +func (i *Instruction) AsAtomicCas(addr, exp, repl Value, size uint64) *Instruction { + i.opcode = OpcodeAtomicCas + i.u1 = size + i.v = addr + i.v2 = exp + i.v3 = repl + i.typ = repl.Type() + return i +} + +// AsFence initializes this instruction as a memory fence. +// A single byte immediate may be used to indicate fence ordering in the future +// but is currently always 0 and ignored. +func (i *Instruction) AsFence(order byte) *Instruction { + i.opcode = OpcodeFence + i.u1 = uint64(order) + return i +} + +// AtomicRmwData returns the data for this atomic read-modify-write instruction. +func (i *Instruction) AtomicRmwData() (op AtomicRmwOp, size uint64) { + return AtomicRmwOp(i.u1), i.u2 +} + +// AtomicTargetSize returns the target memory size of the atomic instruction. +func (i *Instruction) AtomicTargetSize() (size uint64) { + return i.u1 +} + +// ReturnVals returns the return values of OpcodeReturn. +func (i *Instruction) ReturnVals() []Value { + return i.vs.View() +} + +// AsExitWithCode initializes this instruction as a trap instruction with OpcodeExitWithCode. +func (i *Instruction) AsExitWithCode(ctx Value, code wazevoapi.ExitCode) { + i.opcode = OpcodeExitWithCode + i.v = ctx + i.u1 = uint64(code) +} + +// AsExitIfTrueWithCode initializes this instruction as a trap instruction with OpcodeExitIfTrueWithCode. +func (i *Instruction) AsExitIfTrueWithCode(ctx, c Value, code wazevoapi.ExitCode) *Instruction { + i.opcode = OpcodeExitIfTrueWithCode + i.v = ctx + i.v2 = c + i.u1 = uint64(code) + return i +} + +// ExitWithCodeData returns the context and exit code of OpcodeExitWithCode. +func (i *Instruction) ExitWithCodeData() (ctx Value, code wazevoapi.ExitCode) { + return i.v, wazevoapi.ExitCode(i.u1) +} + +// ExitIfTrueWithCodeData returns the context and exit code of OpcodeExitWithCode. +func (i *Instruction) ExitIfTrueWithCodeData() (ctx, c Value, code wazevoapi.ExitCode) { + return i.v, i.v2, wazevoapi.ExitCode(i.u1) +} + +// InvertBrx inverts either OpcodeBrz or OpcodeBrnz to the other. +func (i *Instruction) InvertBrx() { + switch i.opcode { + case OpcodeBrz: + i.opcode = OpcodeBrnz + case OpcodeBrnz: + i.opcode = OpcodeBrz + default: + panic("BUG") + } +} + +// BranchData returns the branch data for this instruction necessary for backends. +func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlockID) { + switch i.opcode { + case OpcodeJump: + condVal = ValueInvalid + case OpcodeBrz, OpcodeBrnz: + condVal = i.v + default: + panic("BUG") + } + blockArgs = i.vs.View() + target = BasicBlockID(i.rValue) + return +} + +// BrTableData returns the branch table data for this instruction necessary for backends. +func (i *Instruction) BrTableData() (index Value, targets Values) { + if i.opcode != OpcodeBrTable { + panic("BUG: BrTableData only available for OpcodeBrTable") + } + index = i.v + targets = i.rValues + return +} + +// AsJump initializes this instruction as a jump instruction with OpcodeJump. +func (i *Instruction) AsJump(vs Values, target BasicBlock) *Instruction { + i.opcode = OpcodeJump + i.vs = vs + i.rValue = Value(target.ID()) + return i +} + +// IsFallthroughJump returns true if this instruction is a fallthrough jump. +func (i *Instruction) IsFallthroughJump() bool { + if i.opcode != OpcodeJump { + panic("BUG: IsFallthrough only available for OpcodeJump") + } + return i.opcode == OpcodeJump && i.u1 != 0 +} + +// AsFallthroughJump marks this instruction as a fallthrough jump. +func (i *Instruction) AsFallthroughJump() { + if i.opcode != OpcodeJump { + panic("BUG: AsFallthroughJump only available for OpcodeJump") + } + i.u1 = 1 +} + +// AsBrz initializes this instruction as a branch-if-zero instruction with OpcodeBrz. +func (i *Instruction) AsBrz(v Value, args Values, target BasicBlock) { + i.opcode = OpcodeBrz + i.v = v + i.vs = args + i.rValue = Value(target.ID()) +} + +// AsBrnz initializes this instruction as a branch-if-not-zero instruction with OpcodeBrnz. +func (i *Instruction) AsBrnz(v Value, args Values, target BasicBlock) *Instruction { + i.opcode = OpcodeBrnz + i.v = v + i.vs = args + i.rValue = Value(target.ID()) + return i +} + +// AsBrTable initializes this instruction as a branch-table instruction with OpcodeBrTable. +// targets is a list of basic block IDs cast to Values. +func (i *Instruction) AsBrTable(index Value, targets Values) { + i.opcode = OpcodeBrTable + i.v = index + i.rValues = targets +} + +// AsCall initializes this instruction as a call instruction with OpcodeCall. +func (i *Instruction) AsCall(ref FuncRef, sig *Signature, args Values) { + i.opcode = OpcodeCall + i.u1 = uint64(ref) + i.vs = args + i.u2 = uint64(sig.ID) + sig.used = true +} + +// CallData returns the call data for this instruction necessary for backends. +func (i *Instruction) CallData() (ref FuncRef, sigID SignatureID, args []Value) { + if i.opcode != OpcodeCall { + panic("BUG: CallData only available for OpcodeCall") + } + ref = FuncRef(i.u1) + sigID = SignatureID(i.u2) + args = i.vs.View() + return +} + +// AsCallIndirect initializes this instruction as a call-indirect instruction with OpcodeCallIndirect. +func (i *Instruction) AsCallIndirect(funcPtr Value, sig *Signature, args Values) *Instruction { + i.opcode = OpcodeCallIndirect + i.typ = TypeF64 + i.vs = args + i.v = funcPtr + i.u1 = uint64(sig.ID) + sig.used = true + return i +} + +// AsCallGoRuntimeMemmove is the same as AsCallIndirect, but with a special flag set to indicate that it is a call to the Go runtime memmove function. +func (i *Instruction) AsCallGoRuntimeMemmove(funcPtr Value, sig *Signature, args Values) *Instruction { + i.AsCallIndirect(funcPtr, sig, args) + i.u2 = 1 + return i +} + +// CallIndirectData returns the call indirect data for this instruction necessary for backends. +func (i *Instruction) CallIndirectData() (funcPtr Value, sigID SignatureID, args []Value, isGoMemmove bool) { + if i.opcode != OpcodeCallIndirect { + panic("BUG: CallIndirectData only available for OpcodeCallIndirect") + } + funcPtr = i.v + sigID = SignatureID(i.u1) + args = i.vs.View() + isGoMemmove = i.u2 == 1 + return +} + +// AsClz initializes this instruction as a Count Leading Zeroes instruction with OpcodeClz. +func (i *Instruction) AsClz(x Value) { + i.opcode = OpcodeClz + i.v = x + i.typ = x.Type() +} + +// AsCtz initializes this instruction as a Count Trailing Zeroes instruction with OpcodeCtz. +func (i *Instruction) AsCtz(x Value) { + i.opcode = OpcodeCtz + i.v = x + i.typ = x.Type() +} + +// AsPopcnt initializes this instruction as a Population Count instruction with OpcodePopcnt. +func (i *Instruction) AsPopcnt(x Value) { + i.opcode = OpcodePopcnt + i.v = x + i.typ = x.Type() +} + +// AsFneg initializes this instruction as an instruction with OpcodeFneg. +func (i *Instruction) AsFneg(x Value) *Instruction { + i.opcode = OpcodeFneg + i.v = x + i.typ = x.Type() + return i +} + +// AsSqrt initializes this instruction as an instruction with OpcodeSqrt. +func (i *Instruction) AsSqrt(x Value) *Instruction { + i.opcode = OpcodeSqrt + i.v = x + i.typ = x.Type() + return i +} + +// AsFabs initializes this instruction as an instruction with OpcodeFabs. +func (i *Instruction) AsFabs(x Value) *Instruction { + i.opcode = OpcodeFabs + i.v = x + i.typ = x.Type() + return i +} + +// AsFcopysign initializes this instruction as an instruction with OpcodeFcopysign. +func (i *Instruction) AsFcopysign(x, y Value) *Instruction { + i.opcode = OpcodeFcopysign + i.v = x + i.v2 = y + i.typ = x.Type() + return i +} + +// AsCeil initializes this instruction as an instruction with OpcodeCeil. +func (i *Instruction) AsCeil(x Value) *Instruction { + i.opcode = OpcodeCeil + i.v = x + i.typ = x.Type() + return i +} + +// AsFloor initializes this instruction as an instruction with OpcodeFloor. +func (i *Instruction) AsFloor(x Value) *Instruction { + i.opcode = OpcodeFloor + i.v = x + i.typ = x.Type() + return i +} + +// AsTrunc initializes this instruction as an instruction with OpcodeTrunc. +func (i *Instruction) AsTrunc(x Value) *Instruction { + i.opcode = OpcodeTrunc + i.v = x + i.typ = x.Type() + return i +} + +// AsNearest initializes this instruction as an instruction with OpcodeNearest. +func (i *Instruction) AsNearest(x Value) *Instruction { + i.opcode = OpcodeNearest + i.v = x + i.typ = x.Type() + return i +} + +// AsBitcast initializes this instruction as an instruction with OpcodeBitcast. +func (i *Instruction) AsBitcast(x Value, dstType Type) *Instruction { + i.opcode = OpcodeBitcast + i.v = x + i.typ = dstType + return i +} + +// BitcastData returns the operands for a bitcast instruction. +func (i *Instruction) BitcastData() (x Value, dstType Type) { + return i.v, i.typ +} + +// AsFdemote initializes this instruction as an instruction with OpcodeFdemote. +func (i *Instruction) AsFdemote(x Value) { + i.opcode = OpcodeFdemote + i.v = x + i.typ = TypeF32 +} + +// AsFpromote initializes this instruction as an instruction with OpcodeFpromote. +func (i *Instruction) AsFpromote(x Value) { + i.opcode = OpcodeFpromote + i.v = x + i.typ = TypeF64 +} + +// AsFcvtFromInt initializes this instruction as an instruction with either OpcodeFcvtFromUint or OpcodeFcvtFromSint +func (i *Instruction) AsFcvtFromInt(x Value, signed bool, dst64bit bool) *Instruction { + if signed { + i.opcode = OpcodeFcvtFromSint + } else { + i.opcode = OpcodeFcvtFromUint + } + i.v = x + if dst64bit { + i.typ = TypeF64 + } else { + i.typ = TypeF32 + } + return i +} + +// AsFcvtToInt initializes this instruction as an instruction with either OpcodeFcvtToUint or OpcodeFcvtToSint +func (i *Instruction) AsFcvtToInt(x, ctx Value, signed bool, dst64bit bool, sat bool) *Instruction { + switch { + case signed && !sat: + i.opcode = OpcodeFcvtToSint + case !signed && !sat: + i.opcode = OpcodeFcvtToUint + case signed && sat: + i.opcode = OpcodeFcvtToSintSat + case !signed && sat: + i.opcode = OpcodeFcvtToUintSat + } + i.v = x + i.v2 = ctx + if dst64bit { + i.typ = TypeI64 + } else { + i.typ = TypeI32 + } + return i +} + +// AsVFcvtToIntSat initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat +func (i *Instruction) AsVFcvtToIntSat(x Value, lane VecLane, signed bool) *Instruction { + if signed { + i.opcode = OpcodeVFcvtToSintSat + } else { + i.opcode = OpcodeVFcvtToUintSat + } + i.v = x + i.u1 = uint64(lane) + return i +} + +// AsVFcvtFromInt initializes this instruction as an instruction with either OpcodeVFcvtToSintSat or OpcodeVFcvtToUintSat +func (i *Instruction) AsVFcvtFromInt(x Value, lane VecLane, signed bool) *Instruction { + if signed { + i.opcode = OpcodeVFcvtFromSint + } else { + i.opcode = OpcodeVFcvtFromUint + } + i.v = x + i.u1 = uint64(lane) + return i +} + +// AsNarrow initializes this instruction as an instruction with either OpcodeSnarrow or OpcodeUnarrow +func (i *Instruction) AsNarrow(x, y Value, lane VecLane, signed bool) *Instruction { + if signed { + i.opcode = OpcodeSnarrow + } else { + i.opcode = OpcodeUnarrow + } + i.v = x + i.v2 = y + i.u1 = uint64(lane) + return i +} + +// AsFvpromoteLow initializes this instruction as an instruction with OpcodeFvpromoteLow +func (i *Instruction) AsFvpromoteLow(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeFvpromoteLow + i.v = x + i.u1 = uint64(lane) + return i +} + +// AsFvdemote initializes this instruction as an instruction with OpcodeFvdemote +func (i *Instruction) AsFvdemote(x Value, lane VecLane) *Instruction { + i.opcode = OpcodeFvdemote + i.v = x + i.u1 = uint64(lane) + return i +} + +// AsSExtend initializes this instruction as a sign extension instruction with OpcodeSExtend. +func (i *Instruction) AsSExtend(v Value, from, to byte) *Instruction { + i.opcode = OpcodeSExtend + i.v = v + i.u1 = uint64(from)<<8 | uint64(to) + if to == 64 { + i.typ = TypeI64 + } else { + i.typ = TypeI32 + } + return i +} + +// AsUExtend initializes this instruction as an unsigned extension instruction with OpcodeUExtend. +func (i *Instruction) AsUExtend(v Value, from, to byte) *Instruction { + i.opcode = OpcodeUExtend + i.v = v + i.u1 = uint64(from)<<8 | uint64(to) + if to == 64 { + i.typ = TypeI64 + } else { + i.typ = TypeI32 + } + return i +} + +func (i *Instruction) ExtendData() (from, to byte, signed bool) { + if i.opcode != OpcodeSExtend && i.opcode != OpcodeUExtend { + panic("BUG: ExtendData only available for OpcodeSExtend and OpcodeUExtend") + } + from = byte(i.u1 >> 8) + to = byte(i.u1) + signed = i.opcode == OpcodeSExtend + return +} + +// AsSelect initializes this instruction as an unsigned extension instruction with OpcodeSelect. +func (i *Instruction) AsSelect(c, x, y Value) *Instruction { + i.opcode = OpcodeSelect + i.v = c + i.v2 = x + i.v3 = y + i.typ = x.Type() + return i +} + +// SelectData returns the select data for this instruction necessary for backends. +func (i *Instruction) SelectData() (c, x, y Value) { + c = i.v + x = i.v2 + y = i.v3 + return +} + +// ExtendFromToBits returns the from and to bit size for the extension instruction. +func (i *Instruction) ExtendFromToBits() (from, to byte) { + from = byte(i.u1 >> 8) + to = byte(i.u1) + return +} + +// Format returns a string representation of this instruction with the given builder. +// For debugging purposes only. +func (i *Instruction) Format(b Builder) string { + var instSuffix string + switch i.opcode { + case OpcodeExitWithCode: + instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), wazevoapi.ExitCode(i.u1)) + case OpcodeExitIfTrueWithCode: + instSuffix = fmt.Sprintf(" %s, %s, %s", i.v2.Format(b), i.v.Format(b), wazevoapi.ExitCode(i.u1)) + case OpcodeIadd, OpcodeIsub, OpcodeImul, OpcodeFadd, OpcodeFsub, OpcodeFmin, OpcodeFmax, OpcodeFdiv, OpcodeFmul: + instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b)) + case OpcodeIcmp: + instSuffix = fmt.Sprintf(" %s, %s, %s", IntegerCmpCond(i.u1), i.v.Format(b), i.v2.Format(b)) + case OpcodeFcmp: + instSuffix = fmt.Sprintf(" %s, %s, %s", FloatCmpCond(i.u1), i.v.Format(b), i.v2.Format(b)) + case OpcodeSExtend, OpcodeUExtend: + instSuffix = fmt.Sprintf(" %s, %d->%d", i.v.Format(b), i.u1>>8, i.u1&0xff) + case OpcodeCall, OpcodeCallIndirect: + view := i.vs.View() + vs := make([]string, len(view)) + for idx := range vs { + vs[idx] = view[idx].Format(b) + } + if i.opcode == OpcodeCallIndirect { + instSuffix = fmt.Sprintf(" %s:%s, %s", i.v.Format(b), SignatureID(i.u1), strings.Join(vs, ", ")) + } else { + instSuffix = fmt.Sprintf(" %s:%s, %s", FuncRef(i.u1), SignatureID(i.u2), strings.Join(vs, ", ")) + } + case OpcodeStore, OpcodeIstore8, OpcodeIstore16, OpcodeIstore32: + instSuffix = fmt.Sprintf(" %s, %s, %#x", i.v.Format(b), i.v2.Format(b), uint32(i.u1)) + case OpcodeLoad, OpcodeVZeroExtLoad: + instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1)) + case OpcodeLoadSplat: + instSuffix = fmt.Sprintf(".%s %s, %#x", VecLane(i.u2), i.v.Format(b), int32(i.u1)) + case OpcodeUload8, OpcodeUload16, OpcodeUload32, OpcodeSload8, OpcodeSload16, OpcodeSload32: + instSuffix = fmt.Sprintf(" %s, %#x", i.v.Format(b), int32(i.u1)) + case OpcodeSelect, OpcodeVbitselect: + instSuffix = fmt.Sprintf(" %s, %s, %s", i.v.Format(b), i.v2.Format(b), i.v3.Format(b)) + case OpcodeIconst: + switch i.typ { + case TypeI32: + instSuffix = fmt.Sprintf("_32 %#x", uint32(i.u1)) + case TypeI64: + instSuffix = fmt.Sprintf("_64 %#x", i.u1) + } + case OpcodeVconst: + instSuffix = fmt.Sprintf(" %016x %016x", i.u1, i.u2) + case OpcodeF32const: + instSuffix = fmt.Sprintf(" %f", math.Float32frombits(uint32(i.u1))) + case OpcodeF64const: + instSuffix = fmt.Sprintf(" %f", math.Float64frombits(i.u1)) + case OpcodeReturn: + view := i.vs.View() + if len(view) == 0 { + break + } + vs := make([]string, len(view)) + for idx := range vs { + vs[idx] = view[idx].Format(b) + } + instSuffix = fmt.Sprintf(" %s", strings.Join(vs, ", ")) + case OpcodeJump: + view := i.vs.View() + vs := make([]string, len(view)+1) + if i.IsFallthroughJump() { + vs[0] = " fallthrough" + } else { + blockId := BasicBlockID(i.rValue) + vs[0] = " " + b.BasicBlock(blockId).Name() + } + for idx := range view { + vs[idx+1] = view[idx].Format(b) + } + + instSuffix = strings.Join(vs, ", ") + case OpcodeBrz, OpcodeBrnz: + view := i.vs.View() + vs := make([]string, len(view)+2) + vs[0] = " " + i.v.Format(b) + blockId := BasicBlockID(i.rValue) + vs[1] = b.BasicBlock(blockId).Name() + for idx := range view { + vs[idx+2] = view[idx].Format(b) + } + instSuffix = strings.Join(vs, ", ") + case OpcodeBrTable: + // `BrTable index, [label1, label2, ... labelN]` + instSuffix = fmt.Sprintf(" %s", i.v.Format(b)) + instSuffix += ", [" + for i, target := range i.rValues.View() { + blk := b.BasicBlock(BasicBlockID(target)) + if i == 0 { + instSuffix += blk.Name() + } else { + instSuffix += ", " + blk.Name() + } + } + instSuffix += "]" + case OpcodeBand, OpcodeBor, OpcodeBxor, OpcodeRotr, OpcodeRotl, OpcodeIshl, OpcodeSshr, OpcodeUshr, + OpcodeSdiv, OpcodeUdiv, OpcodeFcopysign, OpcodeSrem, OpcodeUrem, + OpcodeVbnot, OpcodeVbxor, OpcodeVbor, OpcodeVband, OpcodeVbandnot, OpcodeVIcmp, OpcodeVFcmp: + instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b)) + case OpcodeUndefined: + case OpcodeClz, OpcodeCtz, OpcodePopcnt, OpcodeFneg, OpcodeFcvtToSint, OpcodeFcvtToUint, OpcodeFcvtFromSint, + OpcodeFcvtFromUint, OpcodeFcvtToSintSat, OpcodeFcvtToUintSat, OpcodeFdemote, OpcodeFpromote, OpcodeIreduce, OpcodeBitcast, OpcodeSqrt, OpcodeFabs, + OpcodeCeil, OpcodeFloor, OpcodeTrunc, OpcodeNearest: + instSuffix = " " + i.v.Format(b) + case OpcodeVIadd, OpcodeExtIaddPairwise, OpcodeVSaddSat, OpcodeVUaddSat, OpcodeVIsub, OpcodeVSsubSat, OpcodeVUsubSat, + OpcodeVImin, OpcodeVUmin, OpcodeVImax, OpcodeVUmax, OpcodeVImul, OpcodeVAvgRound, + OpcodeVFadd, OpcodeVFsub, OpcodeVFmul, OpcodeVFdiv, + OpcodeVIshl, OpcodeVSshr, OpcodeVUshr, + OpcodeVFmin, OpcodeVFmax, OpcodeVMinPseudo, OpcodeVMaxPseudo, + OpcodeSnarrow, OpcodeUnarrow, OpcodeSwizzle, OpcodeSqmulRoundSat: + instSuffix = fmt.Sprintf(".%s %s, %s", VecLane(i.u1), i.v.Format(b), i.v2.Format(b)) + case OpcodeVIabs, OpcodeVIneg, OpcodeVIpopcnt, OpcodeVhighBits, OpcodeVallTrue, OpcodeVanyTrue, + OpcodeVFabs, OpcodeVFneg, OpcodeVSqrt, OpcodeVCeil, OpcodeVFloor, OpcodeVTrunc, OpcodeVNearest, + OpcodeVFcvtToUintSat, OpcodeVFcvtToSintSat, OpcodeVFcvtFromUint, OpcodeVFcvtFromSint, + OpcodeFvpromoteLow, OpcodeFvdemote, OpcodeSwidenLow, OpcodeUwidenLow, OpcodeSwidenHigh, OpcodeUwidenHigh, + OpcodeSplat: + instSuffix = fmt.Sprintf(".%s %s", VecLane(i.u1), i.v.Format(b)) + case OpcodeExtractlane: + var signedness string + if i.u1 != 0 { + signedness = "signed" + } else { + signedness = "unsigned" + } + instSuffix = fmt.Sprintf(".%s %d, %s (%s)", VecLane(i.u2), 0x0000FFFF&i.u1, i.v.Format(b), signedness) + case OpcodeInsertlane: + instSuffix = fmt.Sprintf(".%s %d, %s, %s", VecLane(i.u2), i.u1, i.v.Format(b), i.v2.Format(b)) + case OpcodeShuffle: + lanes := make([]byte, 16) + for idx := 0; idx < 8; idx++ { + lanes[idx] = byte(i.u1 >> (8 * idx)) + } + for idx := 0; idx < 8; idx++ { + lanes[idx+8] = byte(i.u2 >> (8 * idx)) + } + // Prints Shuffle.[0 1 2 3 4 5 6 7 ...] v2, v3 + instSuffix = fmt.Sprintf(".%v %s, %s", lanes, i.v.Format(b), i.v2.Format(b)) + case OpcodeAtomicRmw: + instSuffix = fmt.Sprintf(" %s_%d, %s, %s", AtomicRmwOp(i.u1), 8*i.u2, i.v.Format(b), i.v2.Format(b)) + case OpcodeAtomicLoad: + instSuffix = fmt.Sprintf("_%d, %s", 8*i.u1, i.v.Format(b)) + case OpcodeAtomicStore: + instSuffix = fmt.Sprintf("_%d, %s, %s", 8*i.u1, i.v.Format(b), i.v2.Format(b)) + case OpcodeAtomicCas: + instSuffix = fmt.Sprintf("_%d, %s, %s, %s", 8*i.u1, i.v.Format(b), i.v2.Format(b), i.v3.Format(b)) + case OpcodeFence: + instSuffix = fmt.Sprintf(" %d", i.u1) + case OpcodeWideningPairwiseDotProductS: + instSuffix = fmt.Sprintf(" %s, %s", i.v.Format(b), i.v2.Format(b)) + default: + panic(fmt.Sprintf("TODO: format for %s", i.opcode)) + } + + instr := i.opcode.String() + instSuffix + + var rvs []string + r1, rs := i.Returns() + if r1.Valid() { + rvs = append(rvs, r1.formatWithType(b)) + } + + for _, v := range rs { + rvs = append(rvs, v.formatWithType(b)) + } + + if len(rvs) > 0 { + return fmt.Sprintf("%s = %s", strings.Join(rvs, ", "), instr) + } else { + return instr + } +} + +// addArgumentBranchInst adds an argument to this instruction. +func (i *Instruction) addArgumentBranchInst(b *builder, v Value) { + switch i.opcode { + case OpcodeJump, OpcodeBrz, OpcodeBrnz: + i.vs = i.vs.Append(&b.varLengthPool, v) + default: + panic("BUG: " + i.opcode.String()) + } +} + +// Constant returns true if this instruction is a constant instruction. +func (i *Instruction) Constant() bool { + switch i.opcode { + case OpcodeIconst, OpcodeF32const, OpcodeF64const: + return true + } + return false +} + +// ConstantVal returns the constant value of this instruction. +// How to interpret the return value depends on the opcode. +func (i *Instruction) ConstantVal() (ret uint64) { + switch i.opcode { + case OpcodeIconst, OpcodeF32const, OpcodeF64const: + ret = i.u1 + default: + panic("TODO") + } + return +} + +// String implements fmt.Stringer. +func (o Opcode) String() (ret string) { + switch o { + case OpcodeInvalid: + return "invalid" + case OpcodeUndefined: + return "Undefined" + case OpcodeJump: + return "Jump" + case OpcodeBrz: + return "Brz" + case OpcodeBrnz: + return "Brnz" + case OpcodeBrTable: + return "BrTable" + case OpcodeExitWithCode: + return "Exit" + case OpcodeExitIfTrueWithCode: + return "ExitIfTrue" + case OpcodeReturn: + return "Return" + case OpcodeCall: + return "Call" + case OpcodeCallIndirect: + return "CallIndirect" + case OpcodeSplat: + return "Splat" + case OpcodeSwizzle: + return "Swizzle" + case OpcodeInsertlane: + return "Insertlane" + case OpcodeExtractlane: + return "Extractlane" + case OpcodeLoad: + return "Load" + case OpcodeLoadSplat: + return "LoadSplat" + case OpcodeStore: + return "Store" + case OpcodeUload8: + return "Uload8" + case OpcodeSload8: + return "Sload8" + case OpcodeIstore8: + return "Istore8" + case OpcodeUload16: + return "Uload16" + case OpcodeSload16: + return "Sload16" + case OpcodeIstore16: + return "Istore16" + case OpcodeUload32: + return "Uload32" + case OpcodeSload32: + return "Sload32" + case OpcodeIstore32: + return "Istore32" + case OpcodeIconst: + return "Iconst" + case OpcodeF32const: + return "F32const" + case OpcodeF64const: + return "F64const" + case OpcodeVconst: + return "Vconst" + case OpcodeShuffle: + return "Shuffle" + case OpcodeSelect: + return "Select" + case OpcodeVanyTrue: + return "VanyTrue" + case OpcodeVallTrue: + return "VallTrue" + case OpcodeVhighBits: + return "VhighBits" + case OpcodeIcmp: + return "Icmp" + case OpcodeIcmpImm: + return "IcmpImm" + case OpcodeVIcmp: + return "VIcmp" + case OpcodeIadd: + return "Iadd" + case OpcodeIsub: + return "Isub" + case OpcodeImul: + return "Imul" + case OpcodeUdiv: + return "Udiv" + case OpcodeSdiv: + return "Sdiv" + case OpcodeUrem: + return "Urem" + case OpcodeSrem: + return "Srem" + case OpcodeBand: + return "Band" + case OpcodeBor: + return "Bor" + case OpcodeBxor: + return "Bxor" + case OpcodeBnot: + return "Bnot" + case OpcodeRotl: + return "Rotl" + case OpcodeRotr: + return "Rotr" + case OpcodeIshl: + return "Ishl" + case OpcodeUshr: + return "Ushr" + case OpcodeSshr: + return "Sshr" + case OpcodeClz: + return "Clz" + case OpcodeCtz: + return "Ctz" + case OpcodePopcnt: + return "Popcnt" + case OpcodeFcmp: + return "Fcmp" + case OpcodeFadd: + return "Fadd" + case OpcodeFsub: + return "Fsub" + case OpcodeFmul: + return "Fmul" + case OpcodeFdiv: + return "Fdiv" + case OpcodeSqmulRoundSat: + return "SqmulRoundSat" + case OpcodeSqrt: + return "Sqrt" + case OpcodeFneg: + return "Fneg" + case OpcodeFabs: + return "Fabs" + case OpcodeFcopysign: + return "Fcopysign" + case OpcodeFmin: + return "Fmin" + case OpcodeFmax: + return "Fmax" + case OpcodeCeil: + return "Ceil" + case OpcodeFloor: + return "Floor" + case OpcodeTrunc: + return "Trunc" + case OpcodeNearest: + return "Nearest" + case OpcodeBitcast: + return "Bitcast" + case OpcodeIreduce: + return "Ireduce" + case OpcodeSnarrow: + return "Snarrow" + case OpcodeUnarrow: + return "Unarrow" + case OpcodeSwidenLow: + return "SwidenLow" + case OpcodeSwidenHigh: + return "SwidenHigh" + case OpcodeUwidenLow: + return "UwidenLow" + case OpcodeUwidenHigh: + return "UwidenHigh" + case OpcodeExtIaddPairwise: + return "IaddPairwise" + case OpcodeWideningPairwiseDotProductS: + return "WideningPairwiseDotProductS" + case OpcodeUExtend: + return "UExtend" + case OpcodeSExtend: + return "SExtend" + case OpcodeFpromote: + return "Fpromote" + case OpcodeFdemote: + return "Fdemote" + case OpcodeFvdemote: + return "Fvdemote" + case OpcodeFcvtToUint: + return "FcvtToUint" + case OpcodeFcvtToSint: + return "FcvtToSint" + case OpcodeFcvtToUintSat: + return "FcvtToUintSat" + case OpcodeFcvtToSintSat: + return "FcvtToSintSat" + case OpcodeFcvtFromUint: + return "FcvtFromUint" + case OpcodeFcvtFromSint: + return "FcvtFromSint" + case OpcodeAtomicRmw: + return "AtomicRmw" + case OpcodeAtomicCas: + return "AtomicCas" + case OpcodeAtomicLoad: + return "AtomicLoad" + case OpcodeAtomicStore: + return "AtomicStore" + case OpcodeFence: + return "Fence" + case OpcodeVbor: + return "Vbor" + case OpcodeVbxor: + return "Vbxor" + case OpcodeVband: + return "Vband" + case OpcodeVbandnot: + return "Vbandnot" + case OpcodeVbnot: + return "Vbnot" + case OpcodeVbitselect: + return "Vbitselect" + case OpcodeVIadd: + return "VIadd" + case OpcodeVSaddSat: + return "VSaddSat" + case OpcodeVUaddSat: + return "VUaddSat" + case OpcodeVSsubSat: + return "VSsubSat" + case OpcodeVUsubSat: + return "VUsubSat" + case OpcodeVAvgRound: + return "OpcodeVAvgRound" + case OpcodeVIsub: + return "VIsub" + case OpcodeVImin: + return "VImin" + case OpcodeVUmin: + return "VUmin" + case OpcodeVImax: + return "VImax" + case OpcodeVUmax: + return "VUmax" + case OpcodeVImul: + return "VImul" + case OpcodeVIabs: + return "VIabs" + case OpcodeVIneg: + return "VIneg" + case OpcodeVIpopcnt: + return "VIpopcnt" + case OpcodeVIshl: + return "VIshl" + case OpcodeVUshr: + return "VUshr" + case OpcodeVSshr: + return "VSshr" + case OpcodeVFabs: + return "VFabs" + case OpcodeVFmax: + return "VFmax" + case OpcodeVFmin: + return "VFmin" + case OpcodeVFneg: + return "VFneg" + case OpcodeVFadd: + return "VFadd" + case OpcodeVFsub: + return "VFsub" + case OpcodeVFmul: + return "VFmul" + case OpcodeVFdiv: + return "VFdiv" + case OpcodeVFcmp: + return "VFcmp" + case OpcodeVCeil: + return "VCeil" + case OpcodeVFloor: + return "VFloor" + case OpcodeVTrunc: + return "VTrunc" + case OpcodeVNearest: + return "VNearest" + case OpcodeVMaxPseudo: + return "VMaxPseudo" + case OpcodeVMinPseudo: + return "VMinPseudo" + case OpcodeVSqrt: + return "VSqrt" + case OpcodeVFcvtToUintSat: + return "VFcvtToUintSat" + case OpcodeVFcvtToSintSat: + return "VFcvtToSintSat" + case OpcodeVFcvtFromUint: + return "VFcvtFromUint" + case OpcodeVFcvtFromSint: + return "VFcvtFromSint" + case OpcodeFvpromoteLow: + return "FvpromoteLow" + case OpcodeVZeroExtLoad: + return "VZeroExtLoad" + } + panic(fmt.Sprintf("unknown opcode %d", o)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go new file mode 100644 index 00000000..b9763791 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass.go @@ -0,0 +1,393 @@ +package ssa + +import ( + "fmt" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// RunPasses implements Builder.RunPasses. +// +// The order here matters; some pass depends on the previous ones. +// +// Note that passes suffixed with "Opt" are the optimization passes, meaning that they edit the instructions and blocks +// while the other passes are not, like passEstimateBranchProbabilities does not edit them, but only calculates the additional information. +func (b *builder) RunPasses() { + b.runPreBlockLayoutPasses() + b.runBlockLayoutPass() + b.runPostBlockLayoutPasses() + b.runFinalizingPasses() +} + +func (b *builder) runPreBlockLayoutPasses() { + passSortSuccessors(b) + passDeadBlockEliminationOpt(b) + // The result of passCalculateImmediateDominators will be used by various passes below. + passCalculateImmediateDominators(b) + passRedundantPhiEliminationOpt(b) + passNopInstElimination(b) + + // TODO: implement either conversion of irreducible CFG into reducible one, or irreducible CFG detection where we panic. + // WebAssembly program shouldn't result in irreducible CFG, but we should handle it properly in just in case. + // See FixIrreducible pass in LLVM: https://llvm.org/doxygen/FixIrreducible_8cpp_source.html + + // TODO: implement more optimization passes like: + // block coalescing. + // Copy-propagation. + // Constant folding. + // Common subexpression elimination. + // Arithmetic simplifications. + // and more! + + // passDeadCodeEliminationOpt could be more accurate if we do this after other optimizations. + passDeadCodeEliminationOpt(b) + b.donePreBlockLayoutPasses = true +} + +func (b *builder) runBlockLayoutPass() { + if !b.donePreBlockLayoutPasses { + panic("runBlockLayoutPass must be called after all pre passes are done") + } + passLayoutBlocks(b) + b.doneBlockLayout = true +} + +// runPostBlockLayoutPasses runs the post block layout passes. After this point, CFG is somewhat stable, +// but still can be modified before finalizing passes. At this point, critical edges are split by passLayoutBlocks. +func (b *builder) runPostBlockLayoutPasses() { + if !b.doneBlockLayout { + panic("runPostBlockLayoutPasses must be called after block layout pass is done") + } + // TODO: Do more. e.g. tail duplication, loop unrolling, etc. + + b.donePostBlockLayoutPasses = true +} + +// runFinalizingPasses runs the finalizing passes. After this point, CFG should not be modified. +func (b *builder) runFinalizingPasses() { + if !b.donePostBlockLayoutPasses { + panic("runFinalizingPasses must be called after post block layout passes are done") + } + // Critical edges are split, so we fix the loop nesting forest. + passBuildLoopNestingForest(b) + passBuildDominatorTree(b) + // Now that we know the final placement of the blocks, we can explicitly mark the fallthrough jumps. + b.markFallthroughJumps() +} + +// passDeadBlockEliminationOpt searches the unreachable blocks, and sets the basicBlock.invalid flag true if so. +func passDeadBlockEliminationOpt(b *builder) { + entryBlk := b.entryBlk() + b.blkStack = append(b.blkStack, entryBlk) + for len(b.blkStack) > 0 { + reachableBlk := b.blkStack[len(b.blkStack)-1] + b.blkStack = b.blkStack[:len(b.blkStack)-1] + reachableBlk.visited = 1 + + if !reachableBlk.sealed && !reachableBlk.ReturnBlock() { + panic(fmt.Sprintf("%s is not sealed", reachableBlk)) + } + + if wazevoapi.SSAValidationEnabled { + reachableBlk.validate(b) + } + + for _, succ := range reachableBlk.success { + if succ.visited == 1 { + continue + } + b.blkStack = append(b.blkStack, succ) + } + } + + for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { + if blk.visited != 1 { + blk.invalid = true + } + blk.visited = 0 + } +} + +// passRedundantPhiEliminationOpt eliminates the redundant PHIs (in our terminology, parameters of a block). +// This requires the reverse post-order traversal to be calculated before calling this function, +// hence passCalculateImmediateDominators must be called before this. +func passRedundantPhiEliminationOpt(b *builder) { + redundantParams := b.redundantParams[:0] // reuse the slice from previous iterations. + + // TODO: this might be costly for large programs, but at least, as far as I did the experiment, it's almost the + // same as the single iteration version in terms of the overall compilation time. That *might be* mostly thanks to the fact + // that removing many PHIs results in the reduction of the total instructions, not because of this indefinite iteration is + // relatively small. For example, sqlite speedtest binary results in the large number of redundant PHIs, + // the maximum number of iteration was 22, which seems to be acceptable but not that small either since the + // complexity here is O(BlockNum * Iterations) at the worst case where BlockNum might be the order of thousands. + // -- Note -- + // Currently, each iteration can run in any order of blocks, but it empirically converges quickly in practice when + // running on the reverse post-order. It might be possible to optimize this further by using the dominator tree. + for { + changed := false + _ = b.blockIteratorReversePostOrderBegin() // skip entry block! + // Below, we intentionally use the named iteration variable name, as this comes with inevitable nested for loops! + for blk := b.blockIteratorReversePostOrderNext(); blk != nil; blk = b.blockIteratorReversePostOrderNext() { + params := blk.params.View() + paramNum := len(params) + + for paramIndex := 0; paramIndex < paramNum; paramIndex++ { + phiValue := params[paramIndex] + redundant := true + + nonSelfReferencingValue := ValueInvalid + for predIndex := range blk.preds { + br := blk.preds[predIndex].branch + // Resolve the alias in the arguments so that we could use the previous iteration's result. + b.resolveArgumentAlias(br) + pred := br.vs.View()[paramIndex] + if pred == phiValue { + // This is self-referencing: PHI from the same PHI. + continue + } + + if !nonSelfReferencingValue.Valid() { + nonSelfReferencingValue = pred + continue + } + + if nonSelfReferencingValue != pred { + redundant = false + break + } + } + + if !nonSelfReferencingValue.Valid() { + // This shouldn't happen, and must be a bug in builder.go. + panic("BUG: params added but only self-referencing") + } + + if redundant { + redundantParams = append(redundantParams, redundantParam{ + index: paramIndex, uniqueValue: nonSelfReferencingValue, + }) + } + } + + if len(redundantParams) == 0 { + continue + } + changed = true + + // Remove the redundant PHIs from the argument list of branching instructions. + for predIndex := range blk.preds { + redundantParamsCur, predParamCur := 0, 0 + predBlk := blk.preds[predIndex] + branchInst := predBlk.branch + view := branchInst.vs.View() + for argIndex, value := range view { + if len(redundantParams) == redundantParamsCur || + redundantParams[redundantParamsCur].index != argIndex { + view[predParamCur] = value + predParamCur++ + } else { + redundantParamsCur++ + } + } + branchInst.vs.Cut(predParamCur) + } + + // Still need to have the definition of the value of the PHI (previously as the parameter). + for i := range redundantParams { + redundantValue := &redundantParams[i] + phiValue := params[redundantValue.index] + // Create an alias in this block from the only phi argument to the phi value. + b.alias(phiValue, redundantValue.uniqueValue) + } + + // Finally, Remove the param from the blk. + paramsCur, redundantParamsCur := 0, 0 + for paramIndex := 0; paramIndex < paramNum; paramIndex++ { + param := params[paramIndex] + if len(redundantParams) == redundantParamsCur || redundantParams[redundantParamsCur].index != paramIndex { + params[paramsCur] = param + paramsCur++ + } else { + redundantParamsCur++ + } + } + blk.params.Cut(paramsCur) + + // Clears the map for the next iteration. + redundantParams = redundantParams[:0] + } + + if !changed { + break + } + } + + // Reuse the slice for the future passes. + b.redundantParams = redundantParams +} + +// passDeadCodeEliminationOpt traverses all the instructions, and calculates the reference count of each Value, and +// eliminates all the unnecessary instructions whose ref count is zero. +// The results are stored at builder.valueRefCounts. This also assigns a InstructionGroupID to each Instruction +// during the process. This is the last SSA-level optimization pass and after this, +// the SSA function is ready to be used by backends. +// +// TODO: the algorithm here might not be efficient. Get back to this later. +func passDeadCodeEliminationOpt(b *builder) { + nvid := int(b.nextValueID) + if nvid >= len(b.valuesInfo) { + l := nvid - len(b.valuesInfo) + 1 + b.valuesInfo = append(b.valuesInfo, make([]ValueInfo, l)...) + view := b.valuesInfo[len(b.valuesInfo)-l:] + for i := range view { + view[i].alias = ValueInvalid + } + } + + // First, we gather all the instructions with side effects. + liveInstructions := b.instStack[:0] + // During the process, we will assign InstructionGroupID to each instruction, which is not + // relevant to dead code elimination, but we need in the backend. + var gid InstructionGroupID + for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { + for cur := blk.rootInstr; cur != nil; cur = cur.next { + cur.gid = gid + switch cur.sideEffect() { + case sideEffectTraps: + // The trappable should always be alive. + liveInstructions = append(liveInstructions, cur) + case sideEffectStrict: + liveInstructions = append(liveInstructions, cur) + // The strict side effect should create different instruction groups. + gid++ + } + } + } + + // Find all the instructions referenced by live instructions transitively. + for len(liveInstructions) > 0 { + tail := len(liveInstructions) - 1 + live := liveInstructions[tail] + liveInstructions = liveInstructions[:tail] + if live.live { + // If it's already marked alive, this is referenced multiple times, + // so we can skip it. + continue + } + live.live = true + + // Before we walk, we need to resolve the alias first. + b.resolveArgumentAlias(live) + + v1, v2, v3, vs := live.Args() + if v1.Valid() { + producingInst := b.InstructionOfValue(v1) + if producingInst != nil { + liveInstructions = append(liveInstructions, producingInst) + } + } + + if v2.Valid() { + producingInst := b.InstructionOfValue(v2) + if producingInst != nil { + liveInstructions = append(liveInstructions, producingInst) + } + } + + if v3.Valid() { + producingInst := b.InstructionOfValue(v3) + if producingInst != nil { + liveInstructions = append(liveInstructions, producingInst) + } + } + + for _, v := range vs { + producingInst := b.InstructionOfValue(v) + if producingInst != nil { + liveInstructions = append(liveInstructions, producingInst) + } + } + } + + // Now that all the live instructions are flagged as live=true, we eliminate all dead instructions. + for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { + for cur := blk.rootInstr; cur != nil; cur = cur.next { + if !cur.live { + // Remove the instruction from the list. + if prev := cur.prev; prev != nil { + prev.next = cur.next + } else { + blk.rootInstr = cur.next + } + if next := cur.next; next != nil { + next.prev = cur.prev + } + continue + } + + // If the value alive, we can be sure that arguments are used definitely. + // Hence, we can increment the value reference counts. + v1, v2, v3, vs := cur.Args() + if v1.Valid() { + b.incRefCount(v1.ID(), cur) + } + if v2.Valid() { + b.incRefCount(v2.ID(), cur) + } + if v3.Valid() { + b.incRefCount(v3.ID(), cur) + } + for _, v := range vs { + b.incRefCount(v.ID(), cur) + } + } + } + + b.instStack = liveInstructions // we reuse the stack for the next iteration. +} + +func (b *builder) incRefCount(id ValueID, from *Instruction) { + if wazevoapi.SSALoggingEnabled { + fmt.Printf("v%d referenced from %v\n", id, from.Format(b)) + } + info := &b.valuesInfo[id] + info.RefCount++ +} + +// passNopInstElimination eliminates the instructions which is essentially a no-op. +func passNopInstElimination(b *builder) { + for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { + for cur := blk.rootInstr; cur != nil; cur = cur.next { + switch cur.Opcode() { + // TODO: add more logics here. + case OpcodeIshl, OpcodeSshr, OpcodeUshr: + x, amount := cur.Arg2() + definingInst := b.InstructionOfValue(amount) + if definingInst == nil { + // If there's no defining instruction, that means the amount is coming from the parameter. + continue + } + if definingInst.Constant() { + v := definingInst.ConstantVal() + + if x.Type().Bits() == 64 { + v = v % 64 + } else { + v = v % 32 + } + if v == 0 { + b.alias(cur.Return(), x) + } + } + } + } + } +} + +// passSortSuccessors sorts the successors of each block in the natural program order. +func passSortSuccessors(b *builder) { + for i := 0; i < b.basicBlocksPool.Allocated(); i++ { + blk := b.basicBlocksPool.View(i) + sortBlocks(blk.success) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go new file mode 100644 index 00000000..0118e8b2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_blk_layouts.go @@ -0,0 +1,334 @@ +package ssa + +import ( + "fmt" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// passLayoutBlocks implements Builder.LayoutBlocks. This re-organizes builder.reversePostOrderedBasicBlocks. +// +// TODO: there are tons of room for improvement here. e.g. LLVM has BlockPlacementPass using BlockFrequencyInfo, +// BranchProbabilityInfo, and LoopInfo to do a much better job. Also, if we have the profiling instrumentation +// like ball-larus algorithm, then we could do profile-guided optimization. Basically all of them are trying +// to maximize the fall-through opportunities which is most efficient. +// +// Here, fallthrough happens when a block ends with jump instruction whose target is the right next block in the +// builder.reversePostOrderedBasicBlocks. +// +// Currently, we just place blocks using the DFS reverse post-order of the dominator tree with the heuristics: +// 1. a split edge trampoline towards a loop header will be placed as a fallthrough. +// 2. we invert the brz and brnz if it makes the fallthrough more likely. +// +// This heuristic is done in maybeInvertBranches function. +func passLayoutBlocks(b *builder) { + // We might end up splitting critical edges which adds more basic blocks, + // so we store the currently existing basic blocks in nonSplitBlocks temporarily. + // That way we can iterate over the original basic blocks while appending new ones into reversePostOrderedBasicBlocks. + nonSplitBlocks := b.blkStack[:0] + for i, blk := range b.reversePostOrderedBasicBlocks { + if !blk.Valid() { + continue + } + nonSplitBlocks = append(nonSplitBlocks, blk) + if i != len(b.reversePostOrderedBasicBlocks)-1 { + _ = maybeInvertBranches(b, blk, b.reversePostOrderedBasicBlocks[i+1]) + } + } + + var trampolines []*basicBlock + + // Reset the order slice since we update on the fly by splitting critical edges. + b.reversePostOrderedBasicBlocks = b.reversePostOrderedBasicBlocks[:0] + uninsertedTrampolines := b.blkStack2[:0] + for _, blk := range nonSplitBlocks { + for i := range blk.preds { + pred := blk.preds[i].blk + if pred.visited == 1 || !pred.Valid() { + continue + } else if pred.reversePostOrder < blk.reversePostOrder { + // This means the edge is critical, and this pred is the trampoline and yet to be inserted. + // Split edge trampolines must come before the destination in reverse post-order. + b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, pred) + pred.visited = 1 // mark as inserted. + } + } + + // Now that we've already added all the potential trampoline blocks incoming to this block, + // we can add this block itself. + b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, blk) + blk.visited = 1 // mark as inserted. + + if len(blk.success) < 2 { + // There won't be critical edge originating from this block. + continue + } else if blk.currentInstr.opcode == OpcodeBrTable { + // We don't split critical edges here, because at the construction site of BrTable, we already split the edges. + continue + } + + for sidx, succ := range blk.success { + if !succ.ReturnBlock() && // If the successor is a return block, we need to split the edge any way because we need "epilogue" to be inserted. + // Plus if there's no multiple incoming edges to this successor, (pred, succ) is not critical. + len(succ.preds) < 2 { + continue + } + + // Otherwise, we are sure this is a critical edge. To modify the CFG, we need to find the predecessor info + // from the successor. + var predInfo *basicBlockPredecessorInfo + for i := range succ.preds { // This linear search should not be a problem since the number of predecessors should almost always small. + pred := &succ.preds[i] + if pred.blk == blk { + predInfo = pred + break + } + } + + if predInfo == nil { + // This must be a bug in somewhere around branch manipulation. + panic("BUG: predecessor info not found while the successor exists in successors list") + } + + if wazevoapi.SSALoggingEnabled { + fmt.Printf("trying to split edge from %d->%d at %s\n", + blk.ID(), succ.ID(), predInfo.branch.Format(b)) + } + + trampoline := b.splitCriticalEdge(blk, succ, predInfo) + // Update the successors slice because the target is no longer the original `succ`. + blk.success[sidx] = trampoline + + if wazevoapi.SSAValidationEnabled { + trampolines = append(trampolines, trampoline) + } + + if wazevoapi.SSALoggingEnabled { + fmt.Printf("edge split from %d->%d at %s as %d->%d->%d \n", + blk.ID(), succ.ID(), predInfo.branch.Format(b), + blk.ID(), trampoline.ID(), succ.ID()) + } + + fallthroughBranch := blk.currentInstr + if fallthroughBranch.opcode == OpcodeJump && BasicBlockID(fallthroughBranch.rValue) == trampoline.id { + // This can be lowered as fallthrough at the end of the block. + b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, trampoline) + trampoline.visited = 1 // mark as inserted. + } else { + uninsertedTrampolines = append(uninsertedTrampolines, trampoline) + } + } + + for _, trampoline := range uninsertedTrampolines { + if trampoline.success[0].reversePostOrder <= trampoline.reversePostOrder { // "<=", not "<" because the target might be itself. + // This means the critical edge was backward, so we insert after the current block immediately. + b.reversePostOrderedBasicBlocks = append(b.reversePostOrderedBasicBlocks, trampoline) + trampoline.visited = 1 // mark as inserted. + } // If the target is forward, we can wait to insert until the target is inserted. + } + uninsertedTrampolines = uninsertedTrampolines[:0] // Reuse the stack for the next block. + } + + if wazevoapi.SSALoggingEnabled { + var bs []string + for _, blk := range b.reversePostOrderedBasicBlocks { + bs = append(bs, blk.Name()) + } + fmt.Println("ordered blocks: ", strings.Join(bs, ", ")) + } + + if wazevoapi.SSAValidationEnabled { + for _, trampoline := range trampolines { + if trampoline.visited != 1 { + panic("BUG: trampoline block not inserted: " + trampoline.formatHeader(b)) + } + trampoline.validate(b) + } + } + + // Reuse the stack for the next iteration. + b.blkStack2 = uninsertedTrampolines[:0] +} + +// markFallthroughJumps finds the fallthrough jumps and marks them as such. +func (b *builder) markFallthroughJumps() { + l := len(b.reversePostOrderedBasicBlocks) - 1 + for i, blk := range b.reversePostOrderedBasicBlocks { + if i < l { + cur := blk.currentInstr + if cur.opcode == OpcodeJump && BasicBlockID(cur.rValue) == b.reversePostOrderedBasicBlocks[i+1].id { + cur.AsFallthroughJump() + } + } + } +} + +// maybeInvertBranches inverts the branch instructions if it is likely possible to the fallthrough more likely with simple heuristics. +// nextInRPO is the next block in the reverse post-order. +// +// Returns true if the branch is inverted for testing purpose. +func maybeInvertBranches(b *builder, now *basicBlock, nextInRPO *basicBlock) bool { + fallthroughBranch := now.currentInstr + if fallthroughBranch.opcode == OpcodeBrTable { + return false + } + + condBranch := fallthroughBranch.prev + if condBranch == nil || (condBranch.opcode != OpcodeBrnz && condBranch.opcode != OpcodeBrz) { + return false + } + + if len(fallthroughBranch.vs.View()) != 0 || len(condBranch.vs.View()) != 0 { + // If either one of them has arguments, we don't invert the branches. + return false + } + + // So this block has two branches (a conditional branch followed by an unconditional branch) at the end. + // We can invert the condition of the branch if it makes the fallthrough more likely. + + fallthroughTarget := b.basicBlock(BasicBlockID(fallthroughBranch.rValue)) + condTarget := b.basicBlock(BasicBlockID(condBranch.rValue)) + + if fallthroughTarget.loopHeader { + // First, if the tail's target is loopHeader, we don't need to do anything here, + // because the edge is likely to be critical edge for complex loops (e.g. loop with branches inside it). + // That means, we will split the edge in the end of LayoutBlocks function, and insert the trampoline block + // right after this block, which will be fallthrough in any way. + return false + } else if condTarget.loopHeader { + // On the other hand, if the condBranch's target is loopHeader, we invert the condition of the branch + // so that we could get the fallthrough to the trampoline block. + goto invert + } + + if fallthroughTarget == nextInRPO { + // Also, if the tail's target is the next block in the reverse post-order, we don't need to do anything here, + // because if this is not critical edge, we would end up placing these two blocks adjacent to each other. + // Even if it is the critical edge, we place the trampoline block right after this block, which will be fallthrough in any way. + return false + } else if condTarget == nextInRPO { + // If the condBranch's target is the next block in the reverse post-order, we invert the condition of the branch + // so that we could get the fallthrough to the block. + goto invert + } else { + return false + } + +invert: + for i := range fallthroughTarget.preds { + pred := &fallthroughTarget.preds[i] + if pred.branch == fallthroughBranch { + pred.branch = condBranch + break + } + } + for i := range condTarget.preds { + pred := &condTarget.preds[i] + if pred.branch == condBranch { + pred.branch = fallthroughBranch + break + } + } + + condBranch.InvertBrx() + condBranch.rValue = Value(fallthroughTarget.ID()) + fallthroughBranch.rValue = Value(condTarget.ID()) + if wazevoapi.SSALoggingEnabled { + fmt.Printf("inverting branches at %d->%d and %d->%d\n", + now.ID(), fallthroughTarget.ID(), now.ID(), condTarget.ID()) + } + + return true +} + +// splitCriticalEdge splits the critical edge between the given predecessor (`pred`) and successor (owning `predInfo`). +// +// - `pred` is the source of the critical edge, +// - `succ` is the destination of the critical edge, +// - `predInfo` is the predecessor info in the succ.preds slice which represents the critical edge. +// +// Why splitting critical edges is important? See following links: +// +// - https://en.wikipedia.org/wiki/Control-flow_graph +// - https://nickdesaulniers.github.io/blog/2023/01/27/critical-edge-splitting/ +// +// The returned basic block is the trampoline block which is inserted to split the critical edge. +func (b *builder) splitCriticalEdge(pred, succ *basicBlock, predInfo *basicBlockPredecessorInfo) *basicBlock { + // In the following, we convert the following CFG: + // + // pred --(originalBranch)--> succ + // + // to the following CFG: + // + // pred --(newBranch)--> trampoline --(originalBranch)-> succ + // + // where trampoline is a new basic block which is created to split the critical edge. + + trampoline := b.allocateBasicBlock() + if int(trampoline.id) >= len(b.dominators) { + b.dominators = append(b.dominators, make([]*basicBlock, trampoline.id+1)...) + } + b.dominators[trampoline.id] = pred + + originalBranch := predInfo.branch + + // Replace originalBranch with the newBranch. + newBranch := b.AllocateInstruction() + newBranch.opcode = originalBranch.opcode + newBranch.rValue = Value(trampoline.ID()) + switch originalBranch.opcode { + case OpcodeJump: + case OpcodeBrz, OpcodeBrnz: + originalBranch.opcode = OpcodeJump // Trampoline consists of one unconditional branch. + newBranch.v = originalBranch.v + originalBranch.v = ValueInvalid + default: + panic("BUG: critical edge shouldn't be originated from br_table") + } + swapInstruction(pred, originalBranch, newBranch) + + // Replace the original branch with the new branch. + trampoline.rootInstr = originalBranch + trampoline.currentInstr = originalBranch + trampoline.success = append(trampoline.success, succ) // Do not use []*basicBlock{pred} because we might have already allocated the slice. + trampoline.preds = append(trampoline.preds, // same as ^. + basicBlockPredecessorInfo{blk: pred, branch: newBranch}) + b.Seal(trampoline) + + // Update the original branch to point to the trampoline. + predInfo.blk = trampoline + predInfo.branch = originalBranch + + if wazevoapi.SSAValidationEnabled { + trampoline.validate(b) + } + + if len(trampoline.params.View()) > 0 { + panic("trampoline should not have params") + } + + // Assign the same order as the original block so that this will be placed before the actual destination. + trampoline.reversePostOrder = pred.reversePostOrder + return trampoline +} + +// swapInstruction replaces `old` in the block `blk` with `New`. +func swapInstruction(blk *basicBlock, old, New *Instruction) { + if blk.rootInstr == old { + blk.rootInstr = New + next := old.next + New.next = next + next.prev = New + } else { + if blk.currentInstr == old { + blk.currentInstr = New + } + prev := old.prev + prev.next, New.prev = New, prev + if next := old.next; next != nil { + New.next, next.prev = next, New + } + } + old.prev, old.next = nil, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go new file mode 100644 index 00000000..e8288c4b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/pass_cfg.go @@ -0,0 +1,313 @@ +package ssa + +import ( + "fmt" + "math" + "strings" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// passCalculateImmediateDominators calculates immediate dominators for each basic block. +// The result is stored in b.dominators. This make it possible for the following passes to +// use builder.isDominatedBy to check if a block is dominated by another block. +// +// At the last of pass, this function also does the loop detection and sets the basicBlock.loop flag. +func passCalculateImmediateDominators(b *builder) { + reversePostOrder := b.reversePostOrderedBasicBlocks[:0] + + // Store the reverse postorder from the entrypoint into reversePostOrder slice. + // This calculation of reverse postorder is not described in the paper, + // so we use heuristic to calculate it so that we could potentially handle arbitrary + // complex CFGs under the assumption that success is sorted in program's natural order. + // That means blk.success[i] always appears before blk.success[i+1] in the source program, + // which is a reasonable assumption as long as SSA Builder is properly used. + // + // First we push blocks in postorder iteratively visit successors of the entry block. + entryBlk := b.entryBlk() + exploreStack := append(b.blkStack[:0], entryBlk) + // These flags are used to track the state of the block in the DFS traversal. + // We temporarily use the reversePostOrder field to store the state. + const visitStateUnseen, visitStateSeen, visitStateDone = 0, 1, 2 + entryBlk.visited = visitStateSeen + for len(exploreStack) > 0 { + tail := len(exploreStack) - 1 + blk := exploreStack[tail] + exploreStack = exploreStack[:tail] + switch blk.visited { + case visitStateUnseen: + // This is likely a bug in the frontend. + panic("BUG: unsupported CFG") + case visitStateSeen: + // This is the first time to pop this block, and we have to see the successors first. + // So push this block again to the stack. + exploreStack = append(exploreStack, blk) + // And push the successors to the stack if necessary. + for _, succ := range blk.success { + if succ.ReturnBlock() || succ.invalid { + continue + } + if succ.visited == visitStateUnseen { + succ.visited = visitStateSeen + exploreStack = append(exploreStack, succ) + } + } + // Finally, we could pop this block once we pop all of its successors. + blk.visited = visitStateDone + case visitStateDone: + // Note: at this point we push blk in postorder despite its name. + reversePostOrder = append(reversePostOrder, blk) + default: + panic("BUG") + } + } + // At this point, reversePostOrder has postorder actually, so we reverse it. + for i := len(reversePostOrder)/2 - 1; i >= 0; i-- { + j := len(reversePostOrder) - 1 - i + reversePostOrder[i], reversePostOrder[j] = reversePostOrder[j], reversePostOrder[i] + } + + for i, blk := range reversePostOrder { + blk.reversePostOrder = int32(i) + } + + // Reuse the dominators slice if possible from the previous computation of function. + b.dominators = b.dominators[:cap(b.dominators)] + if len(b.dominators) < b.basicBlocksPool.Allocated() { + // Generously reserve space in the slice because the slice will be reused future allocation. + b.dominators = append(b.dominators, make([]*basicBlock, b.basicBlocksPool.Allocated())...) + } + calculateDominators(reversePostOrder, b.dominators) + + // Reuse the slices for the future use. + b.blkStack = exploreStack + + // For the following passes. + b.reversePostOrderedBasicBlocks = reversePostOrder + + // Ready to detect loops! + subPassLoopDetection(b) +} + +// calculateDominators calculates the immediate dominator of each node in the CFG, and store the result in `doms`. +// The algorithm is based on the one described in the paper "A Simple, Fast Dominance Algorithm" +// https://www.cs.rice.edu/~keith/EMBED/dom.pdf which is a faster/simple alternative to the well known Lengauer-Tarjan algorithm. +// +// The following code almost matches the pseudocode in the paper with one exception (see the code comment below). +// +// The result slice `doms` must be pre-allocated with the size larger than the size of dfsBlocks. +func calculateDominators(reversePostOrderedBlks []*basicBlock, doms []*basicBlock) { + entry, reversePostOrderedBlks := reversePostOrderedBlks[0], reversePostOrderedBlks[1: /* skips entry point */] + for _, blk := range reversePostOrderedBlks { + doms[blk.id] = nil + } + doms[entry.id] = entry + + changed := true + for changed { + changed = false + for _, blk := range reversePostOrderedBlks { + var u *basicBlock + for i := range blk.preds { + pred := blk.preds[i].blk + // Skip if this pred is not reachable yet. Note that this is not described in the paper, + // but it is necessary to handle nested loops etc. + if doms[pred.id] == nil { + continue + } + + if u == nil { + u = pred + continue + } else { + u = intersect(doms, u, pred) + } + } + if doms[blk.id] != u { + doms[blk.id] = u + changed = true + } + } + } +} + +// intersect returns the common dominator of blk1 and blk2. +// +// This is the `intersect` function in the paper. +func intersect(doms []*basicBlock, blk1 *basicBlock, blk2 *basicBlock) *basicBlock { + finger1, finger2 := blk1, blk2 + for finger1 != finger2 { + // Move the 'finger1' upwards to its immediate dominator. + for finger1.reversePostOrder > finger2.reversePostOrder { + finger1 = doms[finger1.id] + } + // Move the 'finger2' upwards to its immediate dominator. + for finger2.reversePostOrder > finger1.reversePostOrder { + finger2 = doms[finger2.id] + } + } + return finger1 +} + +// subPassLoopDetection detects loops in the function using the immediate dominators. +// +// This is run at the last of passCalculateImmediateDominators. +func subPassLoopDetection(b *builder) { + for blk := b.blockIteratorBegin(); blk != nil; blk = b.blockIteratorNext() { + for i := range blk.preds { + pred := blk.preds[i].blk + if pred.invalid { + continue + } + if b.isDominatedBy(pred, blk) { + blk.loopHeader = true + } + } + } +} + +// buildLoopNestingForest builds the loop nesting forest for the function. +// This must be called after branch splitting since it relies on the CFG. +func passBuildLoopNestingForest(b *builder) { + ent := b.entryBlk() + doms := b.dominators + for _, blk := range b.reversePostOrderedBasicBlocks { + n := doms[blk.id] + for !n.loopHeader && n != ent { + n = doms[n.id] + } + + if n == ent && blk.loopHeader { + b.loopNestingForestRoots = append(b.loopNestingForestRoots, blk) + } else if n == ent { + } else if n.loopHeader { + n.loopNestingForestChildren = n.loopNestingForestChildren.Append(&b.varLengthBasicBlockPool, blk) + } + } + + if wazevoapi.SSALoggingEnabled { + for _, root := range b.loopNestingForestRoots { + printLoopNestingForest(root.(*basicBlock), 0) + } + } +} + +func printLoopNestingForest(root *basicBlock, depth int) { + fmt.Println(strings.Repeat("\t", depth), "loop nesting forest root:", root.ID()) + for _, child := range root.loopNestingForestChildren.View() { + fmt.Println(strings.Repeat("\t", depth+1), "child:", child.ID()) + if child.LoopHeader() { + printLoopNestingForest(child.(*basicBlock), depth+2) + } + } +} + +type dominatorSparseTree struct { + time int32 + euler []*basicBlock + first, depth []int32 + table [][]int32 +} + +// passBuildDominatorTree builds the dominator tree for the function, and constructs builder.sparseTree. +func passBuildDominatorTree(b *builder) { + // First we materialize the children of each node in the dominator tree. + idoms := b.dominators + for _, blk := range b.reversePostOrderedBasicBlocks { + parent := idoms[blk.id] + if parent == nil { + panic("BUG") + } else if parent == blk { + // This is the entry block. + continue + } + if prev := parent.child; prev == nil { + parent.child = blk + } else { + parent.child = blk + blk.sibling = prev + } + } + + // Reset the state from the previous computation. + n := b.basicBlocksPool.Allocated() + st := &b.sparseTree + st.euler = append(st.euler[:0], make([]*basicBlock, 2*n-1)...) + st.first = append(st.first[:0], make([]int32, n)...) + for i := range st.first { + st.first[i] = -1 + } + st.depth = append(st.depth[:0], make([]int32, 2*n-1)...) + st.time = 0 + + // Start building the sparse tree. + st.eulerTour(b.entryBlk(), 0) + st.buildSparseTable() +} + +func (dt *dominatorSparseTree) eulerTour(node *basicBlock, height int32) { + if wazevoapi.SSALoggingEnabled { + fmt.Println(strings.Repeat("\t", int(height)), "euler tour:", node.ID()) + } + dt.euler[dt.time] = node + dt.depth[dt.time] = height + if dt.first[node.id] == -1 { + dt.first[node.id] = dt.time + } + dt.time++ + + for child := node.child; child != nil; child = child.sibling { + dt.eulerTour(child, height+1) + dt.euler[dt.time] = node // add the current node again after visiting a child + dt.depth[dt.time] = height + dt.time++ + } +} + +// buildSparseTable builds a sparse table for RMQ queries. +func (dt *dominatorSparseTree) buildSparseTable() { + n := len(dt.depth) + k := int(math.Log2(float64(n))) + 1 + table := dt.table + + if n >= len(table) { + table = append(table, make([][]int32, n-len(table)+1)...) + } + for i := range table { + if len(table[i]) < k { + table[i] = append(table[i], make([]int32, k-len(table[i]))...) + } + table[i][0] = int32(i) + } + + for j := 1; 1< first[v] { + u, v = v, u + } + return dt.euler[dt.rmq(first[u], first[v])] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/signature.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/signature.go new file mode 100644 index 00000000..43483395 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/signature.go @@ -0,0 +1,49 @@ +package ssa + +import ( + "fmt" + "strings" +) + +// Signature is a function prototype. +type Signature struct { + // ID is a unique identifier for this signature used to lookup. + ID SignatureID + // Params and Results are the types of the parameters and results of the function. + Params, Results []Type + + // used is true if this is used by the currently-compiled function. + // Debugging only. + used bool +} + +// String implements fmt.Stringer. +func (s *Signature) String() string { + str := strings.Builder{} + str.WriteString(s.ID.String()) + str.WriteString(": ") + if len(s.Params) > 0 { + for _, typ := range s.Params { + str.WriteString(typ.String()) + } + } else { + str.WriteByte('v') + } + str.WriteByte('_') + if len(s.Results) > 0 { + for _, typ := range s.Results { + str.WriteString(typ.String()) + } + } else { + str.WriteByte('v') + } + return str.String() +} + +// SignatureID is an unique identifier used to lookup. +type SignatureID int + +// String implements fmt.Stringer. +func (s SignatureID) String() string { + return fmt.Sprintf("sig%d", s) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/ssa.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/ssa.go new file mode 100644 index 00000000..b477e58b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/ssa.go @@ -0,0 +1,14 @@ +// Package ssa is used to construct SSA function. By nature this is free of Wasm specific thing +// and ISA. +// +// We use the "block argument" variant of SSA: https://en.wikipedia.org/wiki/Static_single-assignment_form#Block_arguments +// which is equivalent to the traditional PHI function based one, but more convenient during optimizations. +// However, in this package's source code comment, we might use PHI whenever it seems necessary in order to be aligned with +// existing literatures, e.g. SSA level optimization algorithms are often described using PHI nodes. +// +// The rationale doc for the choice of "block argument" by MLIR of LLVM is worth a read: +// https://mlir.llvm.org/docs/Rationale/Rationale/#block-arguments-vs-phi-nodes +// +// The algorithm to resolve variable definitions used here is based on the paper +// "Simple and Efficient Construction of Static Single Assignment Form": https://link.springer.com/content/pdf/10.1007/978-3-642-37051-9_6.pdf. +package ssa diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go new file mode 100644 index 00000000..73daf426 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/type.go @@ -0,0 +1,115 @@ +package ssa + +type Type byte + +const ( + typeInvalid Type = iota + + // TODO: add 8, 16 bit types when it's needed for optimizations. + + // TypeI32 represents an integer type with 32 bits. + TypeI32 + + // TypeI64 represents an integer type with 64 bits. + TypeI64 + + // TypeF32 represents 32-bit floats in the IEEE 754. + TypeF32 + + // TypeF64 represents 64-bit floats in the IEEE 754. + TypeF64 + + // TypeV128 represents 128-bit SIMD vectors. + TypeV128 + + // -- Do not add new types after this line. ---- + typeEnd +) + +// String implements fmt.Stringer. +func (t Type) String() (ret string) { + switch t { + case typeInvalid: + return "invalid" + case TypeI32: + return "i32" + case TypeI64: + return "i64" + case TypeF32: + return "f32" + case TypeF64: + return "f64" + case TypeV128: + return "v128" + default: + panic(int(t)) + } +} + +// IsInt returns true if the type is an integer type. +func (t Type) IsInt() bool { + return t == TypeI32 || t == TypeI64 +} + +// IsFloat returns true if the type is a floating point type. +func (t Type) IsFloat() bool { + return t == TypeF32 || t == TypeF64 +} + +// Bits returns the number of bits required to represent the type. +func (t Type) Bits() byte { + switch t { + case TypeI32, TypeF32: + return 32 + case TypeI64, TypeF64: + return 64 + case TypeV128: + return 128 + default: + panic(int(t)) + } +} + +// Size returns the number of bytes required to represent the type. +func (t Type) Size() byte { + return t.Bits() / 8 +} + +func (t Type) invalid() bool { + return t == typeInvalid +} + +// VecLane represents a lane in a SIMD vector. +type VecLane byte + +const ( + VecLaneInvalid VecLane = 1 + iota + VecLaneI8x16 + VecLaneI16x8 + VecLaneI32x4 + VecLaneI64x2 + VecLaneF32x4 + VecLaneF64x2 +) + +// String implements fmt.Stringer. +func (vl VecLane) String() (ret string) { + switch vl { + case VecLaneInvalid: + return "invalid" + case VecLaneI8x16: + return "i8x16" + case VecLaneI16x8: + return "i16x8" + case VecLaneI32x4: + return "i32x4" + case VecLaneI64x2: + return "i64x2" + case VecLaneF32x4: + return "f32x4" + case VecLaneF64x2: + return "f64x2" + default: + panic(int(vl)) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go new file mode 100644 index 00000000..d906e7e3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/ssa/vs.go @@ -0,0 +1,114 @@ +package ssa + +import ( + "fmt" + "math" + + "github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi" +) + +// Variable is a unique identifier for a source program's variable and will correspond to +// multiple ssa Value(s). +// +// For example, `Local 1` is a Variable in WebAssembly, and Value(s) will be created for it +// whenever it executes `local.set 1`. +// +// Variable is useful to track the SSA Values of a variable in the source program, and +// can be used to find the corresponding latest SSA Value via Builder.FindValue. +// +// Higher 4-bit is used to store Type for this variable. +type Variable uint32 + +// String implements fmt.Stringer. +func (v Variable) String() string { + return fmt.Sprintf("var%d", v&0x0fffffff) +} + +func (v Variable) setType(typ Type) Variable { + if v >= 1<<28 { + panic(fmt.Sprintf("Too large variable: %d", v)) + } + return Variable(typ)<<28 | v +} + +func (v Variable) getType() Type { + return Type(v >> 28) +} + +// Value represents an SSA value with a type information. The relationship with Variable is 1: N (including 0), +// that means there might be multiple Variable(s) for a Value. +// +// 32 to 59-bit is used to store the unique identifier of the Instruction that generates this value if any. +// 60 to 63-bit is used to store Type for this value. +type Value uint64 + +// ValueID is the lower 32bit of Value, which is the pure identifier of Value without type info. +type ValueID uint32 + +const ( + valueIDInvalid ValueID = math.MaxUint32 + ValueInvalid = Value(valueIDInvalid) +) + +// Format creates a debug string for this Value using the data stored in Builder. +func (v Value) Format(b Builder) string { + if annotation, ok := b.(*builder).valueAnnotations[v.ID()]; ok { + return annotation + } + return fmt.Sprintf("v%d", v.ID()) +} + +func (v Value) formatWithType(b Builder) (ret string) { + if annotation, ok := b.(*builder).valueAnnotations[v.ID()]; ok { + ret = annotation + ":" + v.Type().String() + } else { + ret = fmt.Sprintf("v%d:%s", v.ID(), v.Type()) + } + + if wazevoapi.SSALoggingEnabled { // This is useful to check live value analysis bugs. + if bd := b.(*builder); bd.donePostBlockLayoutPasses { + id := v.ID() + ret += fmt.Sprintf("(ref=%d)", bd.valuesInfo[id].RefCount) + } + } + return ret +} + +// Valid returns true if this value is valid. +func (v Value) Valid() bool { + return v.ID() != valueIDInvalid +} + +// Type returns the Type of this value. +func (v Value) Type() Type { + return Type(v >> 60) +} + +// ID returns the valueID of this value. +func (v Value) ID() ValueID { + return ValueID(v) +} + +// setType sets a type to this Value and returns the updated Value. +func (v Value) setType(typ Type) Value { + return v | Value(typ)<<60 +} + +// setInstructionID sets an Instruction.id to this Value and returns the updated Value. +func (v Value) setInstructionID(id int) Value { + if id < 0 || uint(id) >= 1<<28 { + panic(fmt.Sprintf("Too large instruction ID: %d", id)) + } + return v | Value(id)<<32 +} + +// instructionID() returns the Instruction.id of this Value. +func (v Value) instructionID() int { + return int(v>>32) & 0x0fffffff +} + +// Values is a slice of Value. Use this instead of []Value to reuse the underlying memory. +type Values = wazevoapi.VarLength[Value] + +// ValuesNil is a nil Values. +var ValuesNil = wazevoapi.NewNilVarLength[Value]() diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/debug_options.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/debug_options.go new file mode 100644 index 00000000..2db61e21 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/debug_options.go @@ -0,0 +1,196 @@ +package wazevoapi + +import ( + "context" + "encoding/hex" + "fmt" + "math/rand" + "os" + "time" +) + +// These consts are used various places in the wazevo implementations. +// Instead of defining them in each file, we define them here so that we can quickly iterate on +// debugging without spending "where do we have debug logging?" time. + +// ----- Debug logging ----- +// These consts must be disabled by default. Enable them only when debugging. + +const ( + FrontEndLoggingEnabled = false + SSALoggingEnabled = false + RegAllocLoggingEnabled = false +) + +// ----- Output prints ----- +// These consts must be disabled by default. Enable them only when debugging. + +const ( + PrintSSA = false + PrintOptimizedSSA = false + PrintSSAToBackendIRLowering = false + PrintRegisterAllocated = false + PrintFinalizedMachineCode = false + PrintMachineCodeHexPerFunction = printMachineCodeHexPerFunctionUnmodified || PrintMachineCodeHexPerFunctionDisassemblable //nolint + printMachineCodeHexPerFunctionUnmodified = false + // PrintMachineCodeHexPerFunctionDisassemblable prints the machine code while modifying the actual result + // to make it disassemblable. This is useful when debugging the final machine code. See the places where this is used for detail. + // When this is enabled, functions must not be called. + PrintMachineCodeHexPerFunctionDisassemblable = false +) + +// printTarget is the function index to print the machine code. This is used for debugging to print the machine code +// of a specific function. +const printTarget = -1 + +// PrintEnabledIndex returns true if the current function index is the print target. +func PrintEnabledIndex(ctx context.Context) bool { + if printTarget == -1 { + return true + } + return GetCurrentFunctionIndex(ctx) == printTarget +} + +// ----- Validations ----- +const ( + // SSAValidationEnabled enables the SSA validation. This is disabled by default since the operation is expensive. + SSAValidationEnabled = false +) + +// ----- Stack Guard Check ----- +const ( + // StackGuardCheckEnabled enables the stack guard check to ensure that our stack bounds check works correctly. + StackGuardCheckEnabled = false + StackGuardCheckGuardPageSize = 8096 +) + +// CheckStackGuardPage checks the given stack guard page is not corrupted. +func CheckStackGuardPage(s []byte) { + for i := 0; i < StackGuardCheckGuardPageSize; i++ { + if s[i] != 0 { + panic( + fmt.Sprintf("BUG: stack guard page is corrupted:\n\tguard_page=%s\n\tstack=%s", + hex.EncodeToString(s[:StackGuardCheckGuardPageSize]), + hex.EncodeToString(s[StackGuardCheckGuardPageSize:]), + )) + } + } +} + +// ----- Deterministic compilation verifier ----- + +const ( + // DeterministicCompilationVerifierEnabled enables the deterministic compilation verifier. This is disabled by default + // since the operation is expensive. But when in doubt, enable this to make sure the compilation is deterministic. + DeterministicCompilationVerifierEnabled = false + DeterministicCompilationVerifyingIter = 5 +) + +type ( + verifierState struct { + initialCompilationDone bool + maybeRandomizedIndexes []int + r *rand.Rand + values map[string]string + } + verifierStateContextKey struct{} + currentFunctionNameKey struct{} + currentFunctionIndexKey struct{} +) + +// NewDeterministicCompilationVerifierContext creates a new context with the deterministic compilation verifier used per wasm.Module. +func NewDeterministicCompilationVerifierContext(ctx context.Context, localFunctions int) context.Context { + maybeRandomizedIndexes := make([]int, localFunctions) + for i := range maybeRandomizedIndexes { + maybeRandomizedIndexes[i] = i + } + r := rand.New(rand.NewSource(time.Now().UnixNano())) + return context.WithValue(ctx, verifierStateContextKey{}, &verifierState{ + r: r, maybeRandomizedIndexes: maybeRandomizedIndexes, values: map[string]string{}, + }) +} + +// DeterministicCompilationVerifierRandomizeIndexes randomizes the indexes for the deterministic compilation verifier. +// To get the randomized index, use DeterministicCompilationVerifierGetRandomizedLocalFunctionIndex. +func DeterministicCompilationVerifierRandomizeIndexes(ctx context.Context) { + state := ctx.Value(verifierStateContextKey{}).(*verifierState) + if !state.initialCompilationDone { + // If this is the first attempt, we use the index as-is order. + state.initialCompilationDone = true + return + } + r := state.r + r.Shuffle(len(state.maybeRandomizedIndexes), func(i, j int) { + state.maybeRandomizedIndexes[i], state.maybeRandomizedIndexes[j] = state.maybeRandomizedIndexes[j], state.maybeRandomizedIndexes[i] + }) +} + +// DeterministicCompilationVerifierGetRandomizedLocalFunctionIndex returns the randomized index for the given `index` +// which is assigned by DeterministicCompilationVerifierRandomizeIndexes. +func DeterministicCompilationVerifierGetRandomizedLocalFunctionIndex(ctx context.Context, index int) int { + state := ctx.Value(verifierStateContextKey{}).(*verifierState) + ret := state.maybeRandomizedIndexes[index] + return ret +} + +// VerifyOrSetDeterministicCompilationContextValue verifies that the `newValue` is the same as the previous value for the given `scope` +// and the current function name. If the previous value doesn't exist, it sets the value to the given `newValue`. +// +// If the verification fails, this prints the diff and exits the process. +func VerifyOrSetDeterministicCompilationContextValue(ctx context.Context, scope string, newValue string) { + fn := ctx.Value(currentFunctionNameKey{}).(string) + key := fn + ": " + scope + verifierCtx := ctx.Value(verifierStateContextKey{}).(*verifierState) + oldValue, ok := verifierCtx.values[key] + if !ok { + verifierCtx.values[key] = newValue + return + } + if oldValue != newValue { + fmt.Printf( + `BUG: Deterministic compilation failed for function%s at scope="%s". + +This is mostly due to (but might not be limited to): + * Resetting ssa.Builder, backend.Compiler or frontend.Compiler, etc doens't work as expected, and the compilation has been affected by the previous iterations. + * Using a map with non-deterministic iteration order. + +---------- [old] ---------- +%s + +---------- [new] ---------- +%s +`, + fn, scope, oldValue, newValue, + ) + os.Exit(1) + } +} + +// nolint +const NeedFunctionNameInContext = PrintSSA || + PrintOptimizedSSA || + PrintSSAToBackendIRLowering || + PrintRegisterAllocated || + PrintFinalizedMachineCode || + PrintMachineCodeHexPerFunction || + DeterministicCompilationVerifierEnabled || + PerfMapEnabled + +// SetCurrentFunctionName sets the current function name to the given `functionName`. +func SetCurrentFunctionName(ctx context.Context, index int, functionName string) context.Context { + ctx = context.WithValue(ctx, currentFunctionNameKey{}, functionName) + ctx = context.WithValue(ctx, currentFunctionIndexKey{}, index) + return ctx +} + +// GetCurrentFunctionName returns the current function name. +func GetCurrentFunctionName(ctx context.Context) string { + ret, _ := ctx.Value(currentFunctionNameKey{}).(string) + return ret +} + +// GetCurrentFunctionIndex returns the current function index. +func GetCurrentFunctionIndex(ctx context.Context) int { + ret, _ := ctx.Value(currentFunctionIndexKey{}).(int) + return ret +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/exitcode.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/exitcode.go new file mode 100644 index 00000000..5ad59498 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/exitcode.go @@ -0,0 +1,109 @@ +package wazevoapi + +// ExitCode is an exit code of an execution of a function. +type ExitCode uint32 + +const ( + ExitCodeOK ExitCode = iota + ExitCodeGrowStack + ExitCodeGrowMemory + ExitCodeUnreachable + ExitCodeMemoryOutOfBounds + // ExitCodeCallGoModuleFunction is an exit code for a call to an api.GoModuleFunction. + ExitCodeCallGoModuleFunction + // ExitCodeCallGoFunction is an exit code for a call to an api.GoFunction. + ExitCodeCallGoFunction + ExitCodeTableOutOfBounds + ExitCodeIndirectCallNullPointer + ExitCodeIndirectCallTypeMismatch + ExitCodeIntegerDivisionByZero + ExitCodeIntegerOverflow + ExitCodeInvalidConversionToInteger + ExitCodeCheckModuleExitCode + ExitCodeCallListenerBefore + ExitCodeCallListenerAfter + ExitCodeCallGoModuleFunctionWithListener + ExitCodeCallGoFunctionWithListener + ExitCodeTableGrow + ExitCodeRefFunc + ExitCodeMemoryWait32 + ExitCodeMemoryWait64 + ExitCodeMemoryNotify + ExitCodeUnalignedAtomic + exitCodeMax +) + +const ExitCodeMask = 0xff + +// String implements fmt.Stringer. +func (e ExitCode) String() string { + switch e { + case ExitCodeOK: + return "ok" + case ExitCodeGrowStack: + return "grow_stack" + case ExitCodeCallGoModuleFunction: + return "call_go_module_function" + case ExitCodeCallGoFunction: + return "call_go_function" + case ExitCodeUnreachable: + return "unreachable" + case ExitCodeMemoryOutOfBounds: + return "memory_out_of_bounds" + case ExitCodeUnalignedAtomic: + return "unaligned_atomic" + case ExitCodeTableOutOfBounds: + return "table_out_of_bounds" + case ExitCodeIndirectCallNullPointer: + return "indirect_call_null_pointer" + case ExitCodeIndirectCallTypeMismatch: + return "indirect_call_type_mismatch" + case ExitCodeIntegerDivisionByZero: + return "integer_division_by_zero" + case ExitCodeIntegerOverflow: + return "integer_overflow" + case ExitCodeInvalidConversionToInteger: + return "invalid_conversion_to_integer" + case ExitCodeCheckModuleExitCode: + return "check_module_exit_code" + case ExitCodeCallListenerBefore: + return "call_listener_before" + case ExitCodeCallListenerAfter: + return "call_listener_after" + case ExitCodeCallGoModuleFunctionWithListener: + return "call_go_module_function_with_listener" + case ExitCodeCallGoFunctionWithListener: + return "call_go_function_with_listener" + case ExitCodeGrowMemory: + return "grow_memory" + case ExitCodeTableGrow: + return "table_grow" + case ExitCodeRefFunc: + return "ref_func" + case ExitCodeMemoryWait32: + return "memory_wait32" + case ExitCodeMemoryWait64: + return "memory_wait64" + case ExitCodeMemoryNotify: + return "memory_notify" + } + panic("TODO") +} + +func ExitCodeCallGoModuleFunctionWithIndex(index int, withListener bool) ExitCode { + if withListener { + return ExitCodeCallGoModuleFunctionWithListener | ExitCode(index<<8) + } + return ExitCodeCallGoModuleFunction | ExitCode(index<<8) +} + +func ExitCodeCallGoFunctionWithIndex(index int, withListener bool) ExitCode { + if withListener { + return ExitCodeCallGoFunctionWithListener | ExitCode(index<<8) + } + return ExitCodeCallGoFunction | ExitCode(index<<8) +} + +func GoFunctionIndexFromExitCode(exitCode ExitCode) int { + return int(exitCode >> 8) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/offsetdata.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/offsetdata.go new file mode 100644 index 00000000..fe6161b0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/offsetdata.go @@ -0,0 +1,216 @@ +package wazevoapi + +import ( + "github.com/tetratelabs/wazero/internal/wasm" +) + +const ( + // FunctionInstanceSize is the size of wazevo.functionInstance. + FunctionInstanceSize = 24 + // FunctionInstanceExecutableOffset is an offset of `executable` field in wazevo.functionInstance + FunctionInstanceExecutableOffset = 0 + // FunctionInstanceModuleContextOpaquePtrOffset is an offset of `moduleContextOpaquePtr` field in wazevo.functionInstance + FunctionInstanceModuleContextOpaquePtrOffset = 8 + // FunctionInstanceTypeIDOffset is an offset of `typeID` field in wazevo.functionInstance + FunctionInstanceTypeIDOffset = 16 +) + +const ( + // ExecutionContextOffsetExitCodeOffset is an offset of `exitCode` field in wazevo.executionContext + ExecutionContextOffsetExitCodeOffset Offset = 0 + // ExecutionContextOffsetCallerModuleContextPtr is an offset of `callerModuleContextPtr` field in wazevo.executionContext + ExecutionContextOffsetCallerModuleContextPtr Offset = 8 + // ExecutionContextOffsetOriginalFramePointer is an offset of `originalFramePointer` field in wazevo.executionContext + ExecutionContextOffsetOriginalFramePointer Offset = 16 + // ExecutionContextOffsetOriginalStackPointer is an offset of `originalStackPointer` field in wazevo.executionContext + ExecutionContextOffsetOriginalStackPointer Offset = 24 + // ExecutionContextOffsetGoReturnAddress is an offset of `goReturnAddress` field in wazevo.executionContext + ExecutionContextOffsetGoReturnAddress Offset = 32 + // ExecutionContextOffsetStackBottomPtr is an offset of `stackBottomPtr` field in wazevo.executionContext + ExecutionContextOffsetStackBottomPtr Offset = 40 + // ExecutionContextOffsetGoCallReturnAddress is an offset of `goCallReturnAddress` field in wazevo.executionContext + ExecutionContextOffsetGoCallReturnAddress Offset = 48 + // ExecutionContextOffsetStackPointerBeforeGoCall is an offset of `StackPointerBeforeGoCall` field in wazevo.executionContext + ExecutionContextOffsetStackPointerBeforeGoCall Offset = 56 + // ExecutionContextOffsetStackGrowRequiredSize is an offset of `stackGrowRequiredSize` field in wazevo.executionContext + ExecutionContextOffsetStackGrowRequiredSize Offset = 64 + // ExecutionContextOffsetMemoryGrowTrampolineAddress is an offset of `memoryGrowTrampolineAddress` field in wazevo.executionContext + ExecutionContextOffsetMemoryGrowTrampolineAddress Offset = 72 + // ExecutionContextOffsetStackGrowCallTrampolineAddress is an offset of `stackGrowCallTrampolineAddress` field in wazevo.executionContext. + ExecutionContextOffsetStackGrowCallTrampolineAddress Offset = 80 + // ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress is an offset of `checkModuleExitCodeTrampolineAddress` field in wazevo.executionContext. + ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress Offset = 88 + // ExecutionContextOffsetSavedRegistersBegin is an offset of the first element of `savedRegisters` field in wazevo.executionContext + ExecutionContextOffsetSavedRegistersBegin Offset = 96 + // ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque is an offset of `goFunctionCallCalleeModuleContextOpaque` field in wazevo.executionContext + ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque Offset = 1120 + // ExecutionContextOffsetTableGrowTrampolineAddress is an offset of `tableGrowTrampolineAddress` field in wazevo.executionContext + ExecutionContextOffsetTableGrowTrampolineAddress Offset = 1128 + // ExecutionContextOffsetRefFuncTrampolineAddress is an offset of `refFuncTrampolineAddress` field in wazevo.executionContext + ExecutionContextOffsetRefFuncTrampolineAddress Offset = 1136 + ExecutionContextOffsetMemmoveAddress Offset = 1144 + ExecutionContextOffsetFramePointerBeforeGoCall Offset = 1152 + ExecutionContextOffsetMemoryWait32TrampolineAddress Offset = 1160 + ExecutionContextOffsetMemoryWait64TrampolineAddress Offset = 1168 + ExecutionContextOffsetMemoryNotifyTrampolineAddress Offset = 1176 +) + +// ModuleContextOffsetData allows the compilers to get the information about offsets to the fields of wazevo.moduleContextOpaque, +// This is unique per module. +type ModuleContextOffsetData struct { + TotalSize int + ModuleInstanceOffset, + LocalMemoryBegin, + ImportedMemoryBegin, + ImportedFunctionsBegin, + GlobalsBegin, + TypeIDs1stElement, + TablesBegin, + BeforeListenerTrampolines1stElement, + AfterListenerTrampolines1stElement, + DataInstances1stElement, + ElementInstances1stElement Offset +} + +// ImportedFunctionOffset returns an offset of the i-th imported function. +// Each item is stored as wazevo.functionInstance whose size matches FunctionInstanceSize. +func (m *ModuleContextOffsetData) ImportedFunctionOffset(i wasm.Index) ( + executableOffset, moduleCtxOffset, typeIDOffset Offset, +) { + base := m.ImportedFunctionsBegin + Offset(i)*FunctionInstanceSize + return base, base + 8, base + 16 +} + +// GlobalInstanceOffset returns an offset of the i-th global instance. +func (m *ModuleContextOffsetData) GlobalInstanceOffset(i wasm.Index) Offset { + return m.GlobalsBegin + Offset(i)*16 +} + +// Offset represents an offset of a field of a struct. +type Offset int32 + +// U32 encodes an Offset as uint32 for convenience. +func (o Offset) U32() uint32 { + return uint32(o) +} + +// I64 encodes an Offset as int64 for convenience. +func (o Offset) I64() int64 { + return int64(o) +} + +// U64 encodes an Offset as int64 for convenience. +func (o Offset) U64() uint64 { + return uint64(o) +} + +// LocalMemoryBase returns an offset of the first byte of the local memory. +func (m *ModuleContextOffsetData) LocalMemoryBase() Offset { + return m.LocalMemoryBegin +} + +// LocalMemoryLen returns an offset of the length of the local memory buffer. +func (m *ModuleContextOffsetData) LocalMemoryLen() Offset { + if l := m.LocalMemoryBegin; l >= 0 { + return l + 8 + } + return -1 +} + +// TableOffset returns an offset of the i-th table instance. +func (m *ModuleContextOffsetData) TableOffset(tableIndex int) Offset { + return m.TablesBegin + Offset(tableIndex)*8 +} + +// NewModuleContextOffsetData creates a ModuleContextOffsetData determining the structure of moduleContextOpaque for the given Module. +// The structure is described in the comment of wazevo.moduleContextOpaque. +func NewModuleContextOffsetData(m *wasm.Module, withListener bool) ModuleContextOffsetData { + ret := ModuleContextOffsetData{} + var offset Offset + + ret.ModuleInstanceOffset = 0 + offset += 8 + + if m.MemorySection != nil { + ret.LocalMemoryBegin = offset + // buffer base + memory size. + const localMemorySizeInOpaqueModuleContext = 16 + offset += localMemorySizeInOpaqueModuleContext + } else { + // Indicates that there's no local memory + ret.LocalMemoryBegin = -1 + } + + if m.ImportMemoryCount > 0 { + offset = align8(offset) + // *wasm.MemoryInstance + imported memory's owner (moduleContextOpaque) + const importedMemorySizeInOpaqueModuleContext = 16 + ret.ImportedMemoryBegin = offset + offset += importedMemorySizeInOpaqueModuleContext + } else { + // Indicates that there's no imported memory + ret.ImportedMemoryBegin = -1 + } + + if m.ImportFunctionCount > 0 { + offset = align8(offset) + ret.ImportedFunctionsBegin = offset + // Each function is stored wazevo.functionInstance. + size := int(m.ImportFunctionCount) * FunctionInstanceSize + offset += Offset(size) + } else { + ret.ImportedFunctionsBegin = -1 + } + + if globals := int(m.ImportGlobalCount) + len(m.GlobalSection); globals > 0 { + // Align to 16 bytes for globals, as f32/f64/v128 might be loaded via SIMD instructions. + offset = align16(offset) + ret.GlobalsBegin = offset + // Pointers to *wasm.GlobalInstance. + offset += Offset(globals) * 16 + } else { + ret.GlobalsBegin = -1 + } + + if tables := len(m.TableSection) + int(m.ImportTableCount); tables > 0 { + offset = align8(offset) + ret.TypeIDs1stElement = offset + offset += 8 // First element of TypeIDs. + + ret.TablesBegin = offset + // Pointers to *wasm.TableInstance. + offset += Offset(tables) * 8 + } else { + ret.TypeIDs1stElement = -1 + ret.TablesBegin = -1 + } + + if withListener { + offset = align8(offset) + ret.BeforeListenerTrampolines1stElement = offset + offset += 8 // First element of BeforeListenerTrampolines. + + ret.AfterListenerTrampolines1stElement = offset + offset += 8 // First element of AfterListenerTrampolines. + } else { + ret.BeforeListenerTrampolines1stElement = -1 + ret.AfterListenerTrampolines1stElement = -1 + } + + ret.DataInstances1stElement = offset + offset += 8 // First element of DataInstances. + + ret.ElementInstances1stElement = offset + offset += 8 // First element of ElementInstances. + + ret.TotalSize = int(align16(offset)) + return ret +} + +func align16(o Offset) Offset { + return (o + 15) &^ 15 +} + +func align8(o Offset) Offset { + return (o + 7) &^ 7 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap.go new file mode 100644 index 00000000..642c7f75 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap.go @@ -0,0 +1,96 @@ +package wazevoapi + +import ( + "fmt" + "os" + "strconv" + "sync" +) + +var PerfMap *Perfmap + +func init() { + if PerfMapEnabled { + pid := os.Getpid() + filename := "/tmp/perf-" + strconv.Itoa(pid) + ".map" + + fh, err := os.OpenFile(filename, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0o644) + if err != nil { + panic(err) + } + + PerfMap = &Perfmap{fh: fh} + } +} + +// Perfmap holds perfmap entries to be flushed into a perfmap file. +type Perfmap struct { + entries []entry + mux sync.Mutex + fh *os.File +} + +type entry struct { + index int + offset int64 + size uint64 + name string +} + +func (f *Perfmap) Lock() { + f.mux.Lock() +} + +func (f *Perfmap) Unlock() { + f.mux.Unlock() +} + +// AddModuleEntry adds a perfmap entry into the perfmap file. +// index is the index of the function in the module, offset is the offset of the function in the module, +// size is the size of the function, and name is the name of the function. +// +// Note that the entries are not flushed into the perfmap file until Flush is called, +// and the entries are module-scoped; Perfmap must be locked until Flush is called. +func (f *Perfmap) AddModuleEntry(index int, offset int64, size uint64, name string) { + e := entry{index: index, offset: offset, size: size, name: name} + if f.entries == nil { + f.entries = []entry{e} + return + } + f.entries = append(f.entries, e) +} + +// Flush writes the perfmap entries into the perfmap file where the entries are adjusted by the given `addr` and `functionOffsets`. +func (f *Perfmap) Flush(addr uintptr, functionOffsets []int) { + defer func() { + _ = f.fh.Sync() + }() + + for _, e := range f.entries { + if _, err := f.fh.WriteString(fmt.Sprintf("%x %s %s\n", + uintptr(e.offset)+addr+uintptr(functionOffsets[e.index]), + strconv.FormatUint(e.size, 16), + e.name, + )); err != nil { + panic(err) + } + } + f.entries = f.entries[:0] +} + +// Clear clears the perfmap entries not yet flushed. +func (f *Perfmap) Clear() { + f.entries = f.entries[:0] +} + +// AddEntry writes a perfmap entry directly into the perfmap file, not using the entries. +func (f *Perfmap) AddEntry(addr uintptr, size uint64, name string) { + _, err := f.fh.WriteString(fmt.Sprintf("%x %s %s\n", + addr, + strconv.FormatUint(size, 16), + name, + )) + if err != nil { + panic(err) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_disabled.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_disabled.go new file mode 100644 index 00000000..bcc4e545 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_disabled.go @@ -0,0 +1,5 @@ +//go:build !perfmap + +package wazevoapi + +const PerfMapEnabled = false diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_enabled.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_enabled.go new file mode 100644 index 00000000..2a39879e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/perfmap_enabled.go @@ -0,0 +1,5 @@ +//go:build perfmap + +package wazevoapi + +const PerfMapEnabled = true diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/pool.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/pool.go new file mode 100644 index 00000000..313e34f9 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/pool.go @@ -0,0 +1,215 @@ +package wazevoapi + +const poolPageSize = 128 + +// Pool is a pool of T that can be allocated and reset. +// This is useful to avoid unnecessary allocations. +type Pool[T any] struct { + pages []*[poolPageSize]T + resetFn func(*T) + allocated, index int +} + +// NewPool returns a new Pool. +// resetFn is called when a new T is allocated in Pool.Allocate. +func NewPool[T any](resetFn func(*T)) Pool[T] { + var ret Pool[T] + ret.resetFn = resetFn + ret.Reset() + return ret +} + +// Allocated returns the number of allocated T currently in the pool. +func (p *Pool[T]) Allocated() int { + return p.allocated +} + +// Allocate allocates a new T from the pool. +func (p *Pool[T]) Allocate() *T { + if p.index == poolPageSize { + if len(p.pages) == cap(p.pages) { + p.pages = append(p.pages, new([poolPageSize]T)) + } else { + i := len(p.pages) + p.pages = p.pages[:i+1] + if p.pages[i] == nil { + p.pages[i] = new([poolPageSize]T) + } + } + p.index = 0 + } + ret := &p.pages[len(p.pages)-1][p.index] + if p.resetFn != nil { + p.resetFn(ret) + } + p.index++ + p.allocated++ + return ret +} + +// View returns the pointer to i-th item from the pool. +func (p *Pool[T]) View(i int) *T { + page, index := i/poolPageSize, i%poolPageSize + return &p.pages[page][index] +} + +// Reset resets the pool. +func (p *Pool[T]) Reset() { + p.pages = p.pages[:0] + p.index = poolPageSize + p.allocated = 0 +} + +// IDedPool is a pool of T that can be allocated and reset, with a way to get T by an ID. +type IDedPool[T any] struct { + pool Pool[T] + idToItems []*T + maxIDEncountered int +} + +// NewIDedPool returns a new IDedPool. +func NewIDedPool[T any](resetFn func(*T)) IDedPool[T] { + return IDedPool[T]{pool: NewPool[T](resetFn), maxIDEncountered: -1} +} + +// GetOrAllocate returns the T with the given id. +func (p *IDedPool[T]) GetOrAllocate(id int) *T { + if p.maxIDEncountered < id { + p.maxIDEncountered = id + } + if id >= len(p.idToItems) { + p.idToItems = append(p.idToItems, make([]*T, id-len(p.idToItems)+1)...) + } + if p.idToItems[id] == nil { + p.idToItems[id] = p.pool.Allocate() + } + return p.idToItems[id] +} + +// Get returns the T with the given id, or nil if it's not allocated. +func (p *IDedPool[T]) Get(id int) *T { + if id >= len(p.idToItems) { + return nil + } + return p.idToItems[id] +} + +// Reset resets the pool. +func (p *IDedPool[T]) Reset() { + p.pool.Reset() + for i := 0; i <= p.maxIDEncountered; i++ { + p.idToItems[i] = nil + } + p.maxIDEncountered = -1 +} + +// MaxIDEncountered returns the maximum id encountered so far. +func (p *IDedPool[T]) MaxIDEncountered() int { + return p.maxIDEncountered +} + +// arraySize is the size of the array used in VarLengthPool's arrayPool. +// This is chosen to be 8, which is empirically a good number among 8, 12, 16 and 20. +const arraySize = 8 + +// VarLengthPool is a pool of VarLength[T] that can be allocated and reset. +type ( + VarLengthPool[T any] struct { + arrayPool Pool[varLengthPoolArray[T]] + slicePool Pool[[]T] + } + // varLengthPoolArray wraps an array and keeps track of the next index to be used to avoid the heap allocation. + varLengthPoolArray[T any] struct { + arr [arraySize]T + next int + } +) + +// VarLength is a variable length array that can be reused via a pool. +type VarLength[T any] struct { + arr *varLengthPoolArray[T] + slc *[]T +} + +// NewVarLengthPool returns a new VarLengthPool. +func NewVarLengthPool[T any]() VarLengthPool[T] { + return VarLengthPool[T]{ + arrayPool: NewPool[varLengthPoolArray[T]](func(v *varLengthPoolArray[T]) { + v.next = 0 + }), + slicePool: NewPool[[]T](func(i *[]T) { + *i = (*i)[:0] + }), + } +} + +// NewNilVarLength returns a new VarLength[T] with a nil backing. +func NewNilVarLength[T any]() VarLength[T] { + return VarLength[T]{} +} + +// Allocate allocates a new VarLength[T] from the pool. +func (p *VarLengthPool[T]) Allocate(knownMin int) VarLength[T] { + if knownMin <= arraySize { + arr := p.arrayPool.Allocate() + return VarLength[T]{arr: arr} + } + slc := p.slicePool.Allocate() + return VarLength[T]{slc: slc} +} + +// Reset resets the pool. +func (p *VarLengthPool[T]) Reset() { + p.arrayPool.Reset() + p.slicePool.Reset() +} + +// Append appends items to the backing slice just like the `append` builtin function in Go. +func (i VarLength[T]) Append(p *VarLengthPool[T], items ...T) VarLength[T] { + if i.slc != nil { + *i.slc = append(*i.slc, items...) + return i + } + + if i.arr == nil { + i.arr = p.arrayPool.Allocate() + } + + arr := i.arr + if arr.next+len(items) <= arraySize { + for _, item := range items { + arr.arr[arr.next] = item + arr.next++ + } + } else { + slc := p.slicePool.Allocate() + // Copy the array to the slice. + for ptr := 0; ptr < arr.next; ptr++ { + *slc = append(*slc, arr.arr[ptr]) + } + i.slc = slc + *i.slc = append(*i.slc, items...) + } + return i +} + +// View returns the backing slice. +func (i VarLength[T]) View() []T { + if i.slc != nil { + return *i.slc + } else if i.arr != nil { + arr := i.arr + return arr.arr[:arr.next] + } + return nil +} + +// Cut cuts the backing slice to the given length. +// Precondition: n <= len(i.backing). +func (i VarLength[T]) Cut(n int) { + if i.slc != nil { + *i.slc = (*i.slc)[:n] + } else if i.arr != nil { + i.arr.next = n + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/ptr.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/ptr.go new file mode 100644 index 00000000..f21e1a5d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/ptr.go @@ -0,0 +1,15 @@ +package wazevoapi + +import "unsafe" + +// PtrFromUintptr resurrects the original *T from the given uintptr. +// The caller of this function MUST be sure that ptr is valid. +func PtrFromUintptr[T any](ptr uintptr) *T { + // Wraps ptrs as the double pointer in order to avoid the unsafe access as detected by race detector. + // + // For example, if we have (*function)(unsafe.Pointer(ptr)) instead, then the race detector's "checkptr" + // subroutine wanrs as "checkptr: pointer arithmetic result points to invalid allocation" + // https://github.com/golang/go/blob/1ce7fcf139417d618c2730010ede2afb41664211/src/runtime/checkptr.go#L69 + var wrapped *uintptr = &ptr + return *(**T)(unsafe.Pointer(wrapped)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/queue.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/queue.go new file mode 100644 index 00000000..e3118fa6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/queue.go @@ -0,0 +1,26 @@ +package wazevoapi + +// Queue is the resettable queue where the underlying slice is reused. +type Queue[T any] struct { + index int + Data []T +} + +func (q *Queue[T]) Enqueue(v T) { + q.Data = append(q.Data, v) +} + +func (q *Queue[T]) Dequeue() (ret T) { + ret = q.Data[q.index] + q.index++ + return +} + +func (q *Queue[T]) Empty() bool { + return q.index >= len(q.Data) +} + +func (q *Queue[T]) Reset() { + q.index = 0 + q.Data = q.Data[:0] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/resetmap.go b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/resetmap.go new file mode 100644 index 00000000..3fc7aa14 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi/resetmap.go @@ -0,0 +1,11 @@ +package wazevoapi + +// ResetMap resets the map to an empty state, or creates a new map if it is nil. +func ResetMap[K comparable, V any](m map[K]V) map[K]V { + if m == nil { + m = make(map[K]V) + } else { + clear(m) + } + return m +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/checkpoint.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/checkpoint.go new file mode 100644 index 00000000..fc62e83f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/checkpoint.go @@ -0,0 +1,10 @@ +package expctxkeys + +// EnableSnapshotterKey is a context key to indicate that snapshotting should be enabled. +// The context.Context passed to a exported function invocation should have this key set +// to a non-nil value, and host functions will be able to retrieve it using SnapshotterKey. +type EnableSnapshotterKey struct{} + +// SnapshotterKey is a context key to access a Snapshotter from a host function. +// It is only present if EnableSnapshotter was set in the function invocation context. +type SnapshotterKey struct{} diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/close.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/close.go new file mode 100644 index 00000000..75e5134e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/close.go @@ -0,0 +1,5 @@ +package expctxkeys + +// CloseNotifierKey is a context.Context Value key. Its associated value should be a +// Notifier. +type CloseNotifierKey struct{} diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/expctxkeys.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/expctxkeys.go new file mode 100644 index 00000000..6800005b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/expctxkeys.go @@ -0,0 +1,2 @@ +// Package expctxkeys provides keys for the context used to store the experimental APIs. +package expctxkeys diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/importresolver.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/importresolver.go new file mode 100644 index 00000000..af52cc80 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/importresolver.go @@ -0,0 +1,6 @@ +package expctxkeys + +// ImportResolverKey is a context.Context Value key. +// Its associated value should be an ImportResolver. +// See issue 2294. +type ImportResolverKey struct{} diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/listener.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/listener.go new file mode 100644 index 00000000..9565db8e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/listener.go @@ -0,0 +1,7 @@ +package expctxkeys + +// FunctionListenerFactoryKey is a context.Context Value key. +// Its associated value should be a FunctionListenerFactory. +// +// See https://github.com/tetratelabs/wazero/issues/451 +type FunctionListenerFactoryKey struct{} diff --git a/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/memory.go b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/memory.go new file mode 100644 index 00000000..d41c0191 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/expctxkeys/memory.go @@ -0,0 +1,4 @@ +package expctxkeys + +// MemoryAllocatorKey is a context.Context key for the experimental memory allocator. +type MemoryAllocatorKey struct{} diff --git a/vendor/github.com/tetratelabs/wazero/internal/filecache/compilationcache.go b/vendor/github.com/tetratelabs/wazero/internal/filecache/compilationcache.go new file mode 100644 index 00000000..b2dbd465 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/filecache/compilationcache.go @@ -0,0 +1,42 @@ +package filecache + +import ( + "crypto/sha256" + "io" +) + +// Cache allows the compiler engine to skip compilation of wasm to machine code +// where doing so is redundant for the same wasm binary and version of wazero. +// +// This augments the default in-memory cache of compiled functions, by +// decoupling it from a wazero.Runtime instance. Concretely, a runtime loses +// its cache once closed. This cache allows the runtime to rebuild its +// in-memory cache quicker, significantly reducing first-hit penalty on a hit. +// +// See New for the example implementation. +type Cache interface { + // Get is called when the runtime is trying to get the cached compiled functions. + // Implementations are supposed to return compiled function in io.Reader with ok=true + // if the key exists on the cache. In the case of not-found, this should return + // ok=false with err=nil. content.Close() is automatically called by + // the caller of this Get. + // + // Note: the returned content won't go through the validation pass of Wasm binary + // which is applied when the binary is compiled from scratch without cache hit. + Get(key Key) (content io.ReadCloser, ok bool, err error) + // + // Add is called when the runtime is trying to add the new cache entry. + // The given `content` must be un-modified, and returned as-is in Get method. + // + // Note: the `content` is ensured to be safe through the validation phase applied on the Wasm binary. + Add(key Key, content io.Reader) (err error) + // + // Delete is called when the cache on the `key` returned by Get is no longer usable, and + // must be purged. Specifically, this is called happens when the wazero's version has been changed. + // For example, that is when there's a difference between the version of compiling wazero and the + // version of the currently used wazero. + Delete(key Key) (err error) +} + +// Key represents the 256-bit unique identifier assigned to each cache entry. +type Key = [sha256.Size]byte diff --git a/vendor/github.com/tetratelabs/wazero/internal/filecache/file_cache.go b/vendor/github.com/tetratelabs/wazero/internal/filecache/file_cache.go new file mode 100644 index 00000000..940a79a8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/filecache/file_cache.go @@ -0,0 +1,76 @@ +package filecache + +import ( + "encoding/hex" + "errors" + "io" + "os" + "path" + "path/filepath" +) + +// New returns a new Cache implemented by fileCache. +func New(dir string) Cache { + return newFileCache(dir) +} + +func newFileCache(dir string) *fileCache { + return &fileCache{dirPath: dir} +} + +// fileCache persists compiled functions into dirPath. +// +// Note: this can be expanded to do binary signing/verification, set TTL on each entry, etc. +type fileCache struct { + dirPath string +} + +func (fc *fileCache) path(key Key) string { + return path.Join(fc.dirPath, hex.EncodeToString(key[:])) +} + +func (fc *fileCache) Get(key Key) (content io.ReadCloser, ok bool, err error) { + f, err := os.Open(fc.path(key)) + if errors.Is(err, os.ErrNotExist) { + return nil, false, nil + } else if err != nil { + return nil, false, err + } else { + return f, true, nil + } +} + +func (fc *fileCache) Add(key Key, content io.Reader) (err error) { + path := fc.path(key) + dirPath, fileName := filepath.Split(path) + + file, err := os.CreateTemp(dirPath, fileName+".*.tmp") + if err != nil { + return + } + defer func() { + file.Close() + if err != nil { + _ = os.Remove(file.Name()) + } + }() + if _, err = io.Copy(file, content); err != nil { + return + } + if err = file.Sync(); err != nil { + return + } + if err = file.Close(); err != nil { + return + } + err = os.Rename(file.Name(), path) + return +} + +func (fc *fileCache) Delete(key Key) (err error) { + err = os.Remove(fc.path(key)) + if errors.Is(err, os.ErrNotExist) { + err = nil + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/fsapi/file.go b/vendor/github.com/tetratelabs/wazero/internal/fsapi/file.go new file mode 100644 index 00000000..0640b227 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/fsapi/file.go @@ -0,0 +1,69 @@ +package fsapi + +import experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + +// File includes methods not yet ready to document for end users, notably +// non-blocking functionality. +// +// Particularly, Poll is subject to debate. For example, whether a user should +// be able to choose how to implement timeout or not. Currently, this interface +// allows the user to choose to sleep or use native polling, and which choice +// they make impacts thread behavior as summarized here: +// https://github.com/tetratelabs/wazero/pull/1606#issuecomment-1665475516 +type File interface { + experimentalsys.File + + // IsNonblock returns true if the file was opened with O_NONBLOCK, or + // SetNonblock was successfully enabled on this file. + // + // # Notes + // + // - This might not match the underlying state of the file descriptor if + // the file was not opened via OpenFile. + IsNonblock() bool + + // SetNonblock toggles the non-blocking mode (O_NONBLOCK) of this file. + // + // # Errors + // + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // + // # Notes + // + // - This is like syscall.SetNonblock and `fcntl` with O_NONBLOCK in + // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html + SetNonblock(enable bool) experimentalsys.Errno + + // Poll returns if the file has data ready to be read or written. + // + // # Parameters + // + // The `flag` parameter determines which event to await, such as POLLIN, + // POLLOUT, or a combination like `POLLIN|POLLOUT`. + // + // The `timeoutMillis` parameter is how long to block for an event, or + // interrupted, in milliseconds. There are two special values: + // - zero returns immediately + // - any negative value blocks any amount of time + // + // # Results + // + // `ready` means there was data ready to read or written. False can mean no + // event was ready or `errno` is not zero. + // + // A zero `errno` is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - ENOTSUP: the implementation does not the flag combination. + // - EINTR: the call was interrupted prior to an event. + // + // # Notes + // + // - This is like `poll` in POSIX, for a single file. + // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html + // - No-op files, such as those which read from /dev/null, should return + // immediately true, as data will never become available. + // - See /RATIONALE.md for detailed notes including impact of blocking. + Poll(flag Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/fsapi/poll.go b/vendor/github.com/tetratelabs/wazero/internal/fsapi/poll.go new file mode 100644 index 00000000..25f7c571 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/fsapi/poll.go @@ -0,0 +1,20 @@ +package fsapi + +// Pflag are bit flags used for File.Poll. Values, including zero, should not +// be interpreted numerically. Instead, use by constants prefixed with 'POLL'. +// +// # Notes +// +// - This is like `pollfd.events` flags for `poll` in POSIX. See +// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html +type Pflag uint32 + +// Only define bitflags we support and are needed by `poll_oneoff` in wasip1 +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#eventrwflags +const ( + // POLLIN is a read event. + POLLIN Pflag = 1 << iota + + // POLLOUT is a write event. + POLLOUT +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/fsapi/unimplemented.go b/vendor/github.com/tetratelabs/wazero/internal/fsapi/unimplemented.go new file mode 100644 index 00000000..99d9c2db --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/fsapi/unimplemented.go @@ -0,0 +1,27 @@ +package fsapi + +import experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + +func Adapt(f experimentalsys.File) File { + if f, ok := f.(File); ok { + return f + } + return unimplementedFile{f} +} + +type unimplementedFile struct{ experimentalsys.File } + +// IsNonblock implements File.IsNonblock +func (unimplementedFile) IsNonblock() bool { + return false +} + +// SetNonblock implements File.SetNonblock +func (unimplementedFile) SetNonblock(bool) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Poll implements File.Poll +func (unimplementedFile) Poll(Pflag, int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/ieee754/ieee754.go b/vendor/github.com/tetratelabs/wazero/internal/ieee754/ieee754.go new file mode 100644 index 00000000..0c929895 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/ieee754/ieee754.go @@ -0,0 +1,29 @@ +package ieee754 + +import ( + "encoding/binary" + "io" + "math" +) + +// DecodeFloat32 decodes a float32 in IEEE 754 binary representation. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#floating-point%E2%91%A2 +func DecodeFloat32(buf []byte) (float32, error) { + if len(buf) < 4 { + return 0, io.ErrUnexpectedEOF + } + + raw := binary.LittleEndian.Uint32(buf[:4]) + return math.Float32frombits(raw), nil +} + +// DecodeFloat64 decodes a float64 in IEEE 754 binary representation. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#floating-point%E2%91%A2 +func DecodeFloat64(buf []byte) (float64, error) { + if len(buf) < 8 { + return 0, io.ErrUnexpectedEOF + } + + raw := binary.LittleEndian.Uint64(buf) + return math.Float64frombits(raw), nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/internalapi/internal.go b/vendor/github.com/tetratelabs/wazero/internal/internalapi/internal.go new file mode 100644 index 00000000..a4f35435 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/internalapi/internal.go @@ -0,0 +1,9 @@ +package internalapi + +type WazeroOnly interface { + wazeroOnly() +} + +type WazeroOnlyType struct{} + +func (WazeroOnlyType) wazeroOnly() {} diff --git a/vendor/github.com/tetratelabs/wazero/internal/leb128/leb128.go b/vendor/github.com/tetratelabs/wazero/internal/leb128/leb128.go new file mode 100644 index 00000000..a3105172 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/leb128/leb128.go @@ -0,0 +1,285 @@ +package leb128 + +import ( + "errors" + "fmt" + "io" +) + +const ( + maxVarintLen32 = 5 + maxVarintLen33 = maxVarintLen32 + maxVarintLen64 = 10 + + int33Mask int64 = 1 << 7 + int33Mask2 = ^int33Mask + int33Mask3 = 1 << 6 + int33Mask4 = 8589934591 // 2^33-1 + int33Mask5 = 1 << 32 + int33Mask6 = int33Mask4 + 1 // 2^33 + + int64Mask3 = 1 << 6 + int64Mask4 = ^0 +) + +var ( + errOverflow32 = errors.New("overflows a 32-bit integer") + errOverflow33 = errors.New("overflows a 33-bit integer") + errOverflow64 = errors.New("overflows a 64-bit integer") +) + +// EncodeInt32 encodes the signed value into a buffer in LEB128 format +// +// See https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer +func EncodeInt32(value int32) []byte { + return EncodeInt64(int64(value)) +} + +// EncodeInt64 encodes the signed value into a buffer in LEB128 format +// +// See https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer +func EncodeInt64(value int64) (buf []byte) { + for { + // Take 7 remaining low-order bits from the value into b. + b := uint8(value & 0x7f) + // Extract the sign bit. + s := uint8(value & 0x40) + value >>= 7 + + // The encoding unsigned numbers is simpler as it only needs to check if the value is non-zero to tell if there + // are more bits to encode. Signed is a little more complicated as you have to double-check the sign bit. + // If either case, set the high-order bit to tell the reader there are more bytes in this int. + if (value != -1 || s == 0) && (value != 0 || s != 0) { + b |= 0x80 + } + + // Append b into the buffer + buf = append(buf, b) + if b&0x80 == 0 { + break + } + } + return buf +} + +// EncodeUint32 encodes the value into a buffer in LEB128 format +// +// See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer +func EncodeUint32(value uint32) []byte { + return EncodeUint64(uint64(value)) +} + +// EncodeUint64 encodes the value into a buffer in LEB128 format +// +// See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer +func EncodeUint64(value uint64) (buf []byte) { + // This is effectively a do/while loop where we take 7 bits of the value and encode them until it is zero. + for { + // Take 7 remaining low-order bits from the value into b. + b := uint8(value & 0x7f) + value = value >> 7 + + // If there are remaining bits, the value won't be zero: Set the high- + // order bit to tell the reader there are more bytes in this uint. + if value != 0 { + b |= 0x80 + } + + // Append b into the buffer + buf = append(buf, b) + if b&0x80 == 0 { + return buf + } + } +} + +type nextByte func(i int) (byte, error) + +func DecodeUint32(r io.ByteReader) (ret uint32, bytesRead uint64, err error) { + return decodeUint32(func(_ int) (byte, error) { return r.ReadByte() }) +} + +func LoadUint32(buf []byte) (ret uint32, bytesRead uint64, err error) { + return decodeUint32(func(i int) (byte, error) { + if i >= len(buf) { + return 0, io.EOF + } + return buf[i], nil + }) +} + +func decodeUint32(next nextByte) (ret uint32, bytesRead uint64, err error) { + // Derived from https://github.com/golang/go/blob/go1.20/src/encoding/binary/varint.go + // with the modification on the overflow handling tailored for 32-bits. + var s uint32 + for i := 0; i < maxVarintLen32; i++ { + b, err := next(i) + if err != nil { + return 0, 0, err + } + if b < 0x80 { + // Unused bits must be all zero. + if i == maxVarintLen32-1 && (b&0xf0) > 0 { + return 0, 0, errOverflow32 + } + return ret | uint32(b)<= bufLen { + return 0, 0, io.EOF + } + b := buf[i] + if b < 0x80 { + // Unused bits (non first bit) must all be zero. + if i == maxVarintLen64-1 && b > 1 { + return 0, 0, errOverflow64 + } + return ret | uint64(b)<= len(buf) { + return 0, io.EOF + } + return buf[i], nil + }) +} + +func decodeInt32(next nextByte) (ret int32, bytesRead uint64, err error) { + var shift int + var b byte + for { + b, err = next(int(bytesRead)) + if err != nil { + return 0, 0, fmt.Errorf("readByte failed: %w", err) + } + ret |= (int32(b) & 0x7f) << shift + shift += 7 + bytesRead++ + if b&0x80 == 0 { + if shift < 32 && (b&0x40) != 0 { + ret |= ^0 << shift + } + // Over flow checks. + // fixme: can be optimized. + if bytesRead > maxVarintLen32 { + return 0, 0, errOverflow32 + } else if unused := b & 0b00110000; bytesRead == maxVarintLen32 && ret < 0 && unused != 0b00110000 { + return 0, 0, errOverflow32 + } else if bytesRead == maxVarintLen32 && ret >= 0 && unused != 0x00 { + return 0, 0, errOverflow32 + } + return + } + } +} + +// DecodeInt33AsInt64 is a special cased decoder for wasm.BlockType which is encoded as a positive signed integer, yet +// still needs to fit the 32-bit range of allowed indices. Hence, this is 33, not 32-bit! +// +// See https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions +func DecodeInt33AsInt64(r io.ByteReader) (ret int64, bytesRead uint64, err error) { + var shift int + var b int64 + var rb byte + for shift < 35 { + rb, err = r.ReadByte() + if err != nil { + return 0, 0, fmt.Errorf("readByte failed: %w", err) + } + b = int64(rb) + ret |= (b & int33Mask2) << shift + shift += 7 + bytesRead++ + if b&int33Mask == 0 { + break + } + } + + // fixme: can be optimized + if shift < 33 && (b&int33Mask3) == int33Mask3 { + ret |= int33Mask4 << shift + } + ret = ret & int33Mask4 + + // if 33rd bit == 1, we translate it as a corresponding signed-33bit minus value + if ret&int33Mask5 > 0 { + ret = ret - int33Mask6 + } + // Over flow checks. + // fixme: can be optimized. + if bytesRead > maxVarintLen33 { + return 0, 0, errOverflow33 + } else if unused := b & 0b00100000; bytesRead == maxVarintLen33 && ret < 0 && unused != 0b00100000 { + return 0, 0, errOverflow33 + } else if bytesRead == maxVarintLen33 && ret >= 0 && unused != 0x00 { + return 0, 0, errOverflow33 + } + return ret, bytesRead, nil +} + +func DecodeInt64(r io.ByteReader) (ret int64, bytesRead uint64, err error) { + return decodeInt64(func(_ int) (byte, error) { return r.ReadByte() }) +} + +func LoadInt64(buf []byte) (ret int64, bytesRead uint64, err error) { + return decodeInt64(func(i int) (byte, error) { + if i >= len(buf) { + return 0, io.EOF + } + return buf[i], nil + }) +} + +func decodeInt64(next nextByte) (ret int64, bytesRead uint64, err error) { + var shift int + var b byte + for { + b, err = next(int(bytesRead)) + if err != nil { + return 0, 0, fmt.Errorf("readByte failed: %w", err) + } + ret |= (int64(b) & 0x7f) << shift + shift += 7 + bytesRead++ + if b&0x80 == 0 { + if shift < 64 && (b&int64Mask3) == int64Mask3 { + ret |= int64Mask4 << shift + } + // Over flow checks. + // fixme: can be optimized. + if bytesRead > maxVarintLen64 { + return 0, 0, errOverflow64 + } else if unused := b & 0b00111110; bytesRead == maxVarintLen64 && ret < 0 && unused != 0b00111110 { + return 0, 0, errOverflow64 + } else if bytesRead == maxVarintLen64 && ret >= 0 && unused != 0x00 { + return 0, 0, errOverflow64 + } + return + } + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/moremath/moremath.go b/vendor/github.com/tetratelabs/wazero/internal/moremath/moremath.go new file mode 100644 index 00000000..4741f07b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/moremath/moremath.go @@ -0,0 +1,271 @@ +package moremath + +import ( + "math" +) + +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/values.html#floating-point +const ( + // F32CanonicalNaNBits is the 32-bit float where payload's MSB equals 1 and others are all zero. + F32CanonicalNaNBits = uint32(0x7fc0_0000) + // F32CanonicalNaNBitsMask can be used to judge the value `v` is canonical nan as "v&F32CanonicalNaNBitsMask == F32CanonicalNaNBits" + F32CanonicalNaNBitsMask = uint32(0x7fff_ffff) + // F64CanonicalNaNBits is the 64-bit float where payload's MSB equals 1 and others are all zero. + F64CanonicalNaNBits = uint64(0x7ff8_0000_0000_0000) + // F64CanonicalNaNBitsMask can be used to judge the value `v` is canonical nan as "v&F64CanonicalNaNBitsMask == F64CanonicalNaNBits" + F64CanonicalNaNBitsMask = uint64(0x7fff_ffff_ffff_ffff) + // F32ArithmeticNaNPayloadMSB is used to extract the most significant bit of payload of 32-bit arithmetic NaN values + F32ArithmeticNaNPayloadMSB = uint32(0x0040_0000) + // F32ExponentMask is used to extract the exponent of 32-bit floating point. + F32ExponentMask = uint32(0x7f80_0000) + // F32ArithmeticNaNBits is an example 32-bit arithmetic NaN. + F32ArithmeticNaNBits = F32CanonicalNaNBits | 0b1 // Set first bit to make this different from the canonical NaN. + // F64ArithmeticNaNPayloadMSB is used to extract the most significant bit of payload of 64-bit arithmetic NaN values + F64ArithmeticNaNPayloadMSB = uint64(0x0008_0000_0000_0000) + // F64ExponentMask is used to extract the exponent of 64-bit floating point. + F64ExponentMask = uint64(0x7ff0_0000_0000_0000) + // F64ArithmeticNaNBits is an example 64-bit arithmetic NaN. + F64ArithmeticNaNBits = F64CanonicalNaNBits | 0b1 // Set first bit to make this different from the canonical NaN. +) + +// WasmCompatMin64 is the Wasm spec compatible variant of math.Min for 64-bit floating points. +func WasmCompatMin64(x, y float64) float64 { + switch { + case math.IsNaN(x) || math.IsNaN(y): + return returnF64NaNBinOp(x, y) + case math.IsInf(x, -1) || math.IsInf(y, -1): + return math.Inf(-1) + case x == 0 && x == y: + if math.Signbit(x) { + return x + } + return y + } + if x < y { + return x + } + return y +} + +// WasmCompatMin32 is the Wasm spec compatible variant of math.Min for 32-bit floating points. +func WasmCompatMin32(x, y float32) float32 { + x64, y64 := float64(x), float64(y) + switch { + case math.IsNaN(x64) || math.IsNaN(y64): + return returnF32NaNBinOp(x, y) + case math.IsInf(x64, -1) || math.IsInf(y64, -1): + return float32(math.Inf(-1)) + case x == 0 && x == y: + if math.Signbit(x64) { + return x + } + return y + } + if x < y { + return x + } + return y +} + +// WasmCompatMax64 is the Wasm spec compatible variant of math.Max for 64-bit floating points. +func WasmCompatMax64(x, y float64) float64 { + switch { + case math.IsNaN(x) || math.IsNaN(y): + return returnF64NaNBinOp(x, y) + case math.IsInf(x, 1) || math.IsInf(y, 1): + return math.Inf(1) + case x == 0 && x == y: + if math.Signbit(x) { + return y + } + return x + } + if x > y { + return x + } + return y +} + +// WasmCompatMax32 is the Wasm spec compatible variant of math.Max for 32-bit floating points. +func WasmCompatMax32(x, y float32) float32 { + x64, y64 := float64(x), float64(y) + switch { + case math.IsNaN(x64) || math.IsNaN(y64): + return returnF32NaNBinOp(x, y) + case math.IsInf(x64, 1) || math.IsInf(y64, 1): + return float32(math.Inf(1)) + case x == 0 && x == y: + if math.Signbit(x64) { + return y + } + return x + } + if x > y { + return x + } + return y +} + +// WasmCompatNearestF32 is the Wasm spec compatible variant of math.Round, used for Nearest instruction. +// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic. +// +// e.g. math.Round(-4.5) results in -5 while this results in -4. +// +// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic. +func WasmCompatNearestF32(f float32) float32 { + var res float32 + // TODO: look at https://github.com/bytecodealliance/wasmtime/pull/2171 and reconsider this algorithm + if f != 0 { + ceil := float32(math.Ceil(float64(f))) + floor := float32(math.Floor(float64(f))) + distToCeil := math.Abs(float64(f - ceil)) + distToFloor := math.Abs(float64(f - floor)) + h := ceil / 2.0 + if distToCeil < distToFloor { + res = ceil + } else if distToCeil == distToFloor && float32(math.Floor(float64(h))) == h { + res = ceil + } else { + res = floor + } + } else { + res = f + } + return returnF32UniOp(f, res) +} + +// WasmCompatNearestF64 is the Wasm spec compatible variant of math.Round, used for Nearest instruction. +// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic. +// +// e.g. math.Round(-4.5) results in -5 while this results in -4. +// +// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic. +func WasmCompatNearestF64(f float64) float64 { + // TODO: look at https://github.com/bytecodealliance/wasmtime/pull/2171 and reconsider this algorithm + var res float64 + if f != 0 { + ceil := math.Ceil(f) + floor := math.Floor(f) + distToCeil := math.Abs(f - ceil) + distToFloor := math.Abs(f - floor) + h := ceil / 2.0 + if distToCeil < distToFloor { + res = ceil + } else if distToCeil == distToFloor && math.Floor(h) == h { + res = ceil + } else { + res = floor + } + } else { + res = f + } + return returnF64UniOp(f, res) +} + +// WasmCompatCeilF32 is the same as math.Ceil on 32-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatCeilF32(f float32) float32 { + return returnF32UniOp(f, float32(math.Ceil(float64(f)))) +} + +// WasmCompatCeilF64 is the same as math.Ceil on 64-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatCeilF64(f float64) float64 { + return returnF64UniOp(f, math.Ceil(f)) +} + +// WasmCompatFloorF32 is the same as math.Floor on 32-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatFloorF32(f float32) float32 { + return returnF32UniOp(f, float32(math.Floor(float64(f)))) +} + +// WasmCompatFloorF64 is the same as math.Floor on 64-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatFloorF64(f float64) float64 { + return returnF64UniOp(f, math.Floor(f)) +} + +// WasmCompatTruncF32 is the same as math.Trunc on 32-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatTruncF32(f float32) float32 { + return returnF32UniOp(f, float32(math.Trunc(float64(f)))) +} + +// WasmCompatTruncF64 is the same as math.Trunc on 64-bit except that +// the returned NaN value follows the Wasm specification on NaN +// propagation. +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func WasmCompatTruncF64(f float64) float64 { + return returnF64UniOp(f, math.Trunc(f)) +} + +func f32IsNaN(v float32) bool { + return v != v // this is how NaN is defined. +} + +func f64IsNaN(v float64) bool { + return v != v // this is how NaN is defined. +} + +// returnF32UniOp returns the result of 32-bit unary operation. This accepts `original` which is the operand, +// and `result` which is its result. This returns the `result` as-is if the result is not NaN. Otherwise, this follows +// the same logic as in the reference interpreter as well as the amd64 and arm64 floating point handling. +func returnF32UniOp(original, result float32) float32 { + // Following the same logic as in the reference interpreter: + // https://github.com/WebAssembly/spec/blob/d48af683f5e6d00c13f775ab07d29a15daf92203/interpreter/exec/fxx.ml#L115-L122 + if !f32IsNaN(result) { + return result + } + if !f32IsNaN(original) { + return math.Float32frombits(F32CanonicalNaNBits) + } + return math.Float32frombits(math.Float32bits(original) | F32CanonicalNaNBits) +} + +// returnF32UniOp returns the result of 64-bit unary operation. This accepts `original` which is the operand, +// and `result` which is its result. This returns the `result` as-is if the result is not NaN. Otherwise, this follows +// the same logic as in the reference interpreter as well as the amd64 and arm64 floating point handling. +func returnF64UniOp(original, result float64) float64 { + // Following the same logic as in the reference interpreter (== amd64 and arm64's behavior): + // https://github.com/WebAssembly/spec/blob/d48af683f5e6d00c13f775ab07d29a15daf92203/interpreter/exec/fxx.ml#L115-L122 + if !f64IsNaN(result) { + return result + } + if !f64IsNaN(original) { + return math.Float64frombits(F64CanonicalNaNBits) + } + return math.Float64frombits(math.Float64bits(original) | F64CanonicalNaNBits) +} + +// returnF64NaNBinOp returns a NaN for 64-bit binary operations. `x` and `y` are original floats +// and at least one of them is NaN. The returned NaN is guaranteed to comply with the NaN propagation +// procedure: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func returnF64NaNBinOp(x, y float64) float64 { + if f64IsNaN(x) { + return math.Float64frombits(math.Float64bits(x) | F64CanonicalNaNBits) + } else { + return math.Float64frombits(math.Float64bits(y) | F64CanonicalNaNBits) + } +} + +// returnF64NaNBinOp returns a NaN for 32-bit binary operations. `x` and `y` are original floats +// and at least one of them is NaN. The returned NaN is guaranteed to comply with the NaN propagation +// procedure: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagation +func returnF32NaNBinOp(x, y float32) float32 { + if f32IsNaN(x) { + return math.Float32frombits(math.Float32bits(x) | F32CanonicalNaNBits) + } else { + return math.Float32frombits(math.Float32bits(y) | F32CanonicalNaNBits) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go new file mode 100644 index 00000000..0220d56f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go @@ -0,0 +1,35 @@ +package platform + +// CpuFeatureFlags exposes methods for querying CPU capabilities +type CpuFeatureFlags interface { + // Has returns true when the specified flag (represented as uint64) is supported + Has(cpuFeature CpuFeature) bool + // HasExtra returns true when the specified extraFlag (represented as uint64) is supported + HasExtra(cpuFeature CpuFeature) bool + // Raw returns the raw bitset that represents CPU features used by wazero. This can be used for cache keying. + // For now, we only use four features, so uint64 is enough. + Raw() uint64 +} + +type CpuFeature uint64 + +const ( + // CpuFeatureAmd64SSE3 is the flag to query CpuFeatureFlags.Has for SSEv3 capabilities on amd64 + CpuFeatureAmd64SSE3 CpuFeature = 1 + // CpuFeatureAmd64SSE4_1 is the flag to query CpuFeatureFlags.Has for SSEv4.1 capabilities on amd64 + CpuFeatureAmd64SSE4_1 CpuFeature = 1 << 19 + // CpuFeatureAmd64SSE4_2 is the flag to query CpuFeatureFlags.Has for SSEv4.2 capabilities on amd64 + CpuFeatureAmd64SSE4_2 CpuFeature = 1 << 20 + // Note: when adding new features, ensure that the feature is included in CpuFeatureFlags.Raw. +) + +const ( + // CpuExtraFeatureAmd64ABM is the flag to query CpuFeatureFlags.HasExtra for Advanced Bit Manipulation capabilities (e.g. LZCNT) on amd64 + CpuExtraFeatureAmd64ABM CpuFeature = 1 << 5 + // Note: when adding new features, ensure that the feature is included in CpuFeatureFlags.Raw. +) + +const ( + // CpuFeatureArm64Atomic is the flag to query CpuFeatureFlags.Has for Large System Extensions capabilities on arm64 + CpuFeatureArm64Atomic CpuFeature = 1 << 21 +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go new file mode 100644 index 00000000..a0c7734a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go @@ -0,0 +1,80 @@ +//go:build gc + +package platform + +// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods. +var CpuFeatures = loadCpuFeatureFlags() + +// cpuFeatureFlags implements CpuFeatureFlags interface. +type cpuFeatureFlags struct { + flags uint64 + extraFlags uint64 +} + +// cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf) +// implemented in cpuid_amd64.s +func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32) + +// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap. +func cpuidAsBitmap(arg1, arg2 uint32) uint64 { + _ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2) + return (uint64(edx) << 32) | uint64(ecx) +} + +// loadStandardRange load flags from the standard range, panics otherwise. +func loadStandardRange(id uint32) uint64 { + // ensure that the id is in the valid range, returned by cpuid(0,0) + maxRange, _, _, _ := cpuid(0, 0) + if id > maxRange { + panic("cannot query standard CPU flags") + } + return cpuidAsBitmap(id, 0) +} + +// loadStandardRange load flags from the extended range, panics otherwise. +func loadExtendedRange(id uint32) uint64 { + // ensure that the id is in the valid range, returned by cpuid(0x80000000,0) + maxRange, _, _, _ := cpuid(0x80000000, 0) + if id > maxRange { + panic("cannot query extended CPU flags") + } + return cpuidAsBitmap(id, 0) +} + +func loadCpuFeatureFlags() CpuFeatureFlags { + return &cpuFeatureFlags{ + flags: loadStandardRange(1), + extraFlags: loadExtendedRange(0x80000001), + } +} + +// Has implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { + return (f.flags & uint64(cpuFeature)) != 0 +} + +// HasExtra implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { + return (f.extraFlags & uint64(cpuFeature)) != 0 +} + +// Raw implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) Raw() uint64 { + // Below, we only set bits for the features we care about, + // instead of setting all the unnecessary bits obtained from the + // CPUID instruction. + var ret uint64 + if f.Has(CpuFeatureAmd64SSE3) { + ret = 1 << 0 + } + if f.Has(CpuFeatureAmd64SSE4_1) { + ret |= 1 << 1 + } + if f.Has(CpuFeatureAmd64SSE4_2) { + ret |= 1 << 2 + } + if f.HasExtra(CpuExtraFeatureAmd64ABM) { + ret |= 1 << 3 + } + return ret +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s new file mode 100644 index 00000000..4950ee62 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s @@ -0,0 +1,16 @@ +//go:build gc + +#include "textflag.h" + +// lifted from github.com/intel-go/cpuid and src/internal/cpu/cpu_x86.s + +// func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32) +TEXT ·cpuid(SB), NOSPLIT, $0-24 + MOVL arg1+0(FP), AX + MOVL arg2+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.go b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.go new file mode 100644 index 00000000..5430353f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.go @@ -0,0 +1,71 @@ +//go:build gc + +package platform + +import "runtime" + +// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods. +var CpuFeatures = loadCpuFeatureFlags() + +// cpuFeatureFlags implements CpuFeatureFlags interface. +type cpuFeatureFlags struct { + isar0 uint64 + isar1 uint64 +} + +// implemented in cpuid_arm64.s +func getisar0() uint64 + +// implemented in cpuid_arm64.s +func getisar1() uint64 + +func loadCpuFeatureFlags() CpuFeatureFlags { + switch runtime.GOOS { + case "darwin", "windows": + // These OSes do not allow userland to read the instruction set attribute registers, + // but basically require atomic instructions: + // - "darwin" is the desktop version (mobile version is "ios"), + // and the M1 is a ARMv8.4. + // - "windows" requires them from Windows 11, see page 12 + // https://download.microsoft.com/download/7/8/8/788bf5ab-0751-4928-a22c-dffdc23c27f2/Minimum%20Hardware%20Requirements%20for%20Windows%2011.pdf + return &cpuFeatureFlags{ + isar0: uint64(CpuFeatureArm64Atomic), + isar1: 0, + } + case "linux", "freebsd": + // These OSes allow userland to read the instruction set attribute registers, + // which is otherwise restricted to EL0: + // https://kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt + // See these for contents of the registers: + // https://developer.arm.com/documentation/ddi0601/latest/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0 + // https://developer.arm.com/documentation/ddi0601/latest/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1 + return &cpuFeatureFlags{ + isar0: getisar0(), + isar1: getisar1(), + } + default: + return &cpuFeatureFlags{} + } +} + +// Has implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { + return (f.isar0 & uint64(cpuFeature)) != 0 +} + +// HasExtra implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { + return (f.isar1 & uint64(cpuFeature)) != 0 +} + +// Raw implements the same method on the CpuFeatureFlags interface. +func (f *cpuFeatureFlags) Raw() uint64 { + // Below, we only set bits for the features we care about, + // instead of setting all the unnecessary bits obtained from the + // instruction set attribute registers. + var ret uint64 + if f.Has(CpuFeatureArm64Atomic) { + ret = 1 << 0 + } + return ret +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.s b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.s new file mode 100644 index 00000000..98305ad4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_arm64.s @@ -0,0 +1,21 @@ +//go:build gc + +#include "textflag.h" + +// lifted from github.com/golang/sys and cpu/cpu_arm64.s + +// func getisar0() uint64 +TEXT ·getisar0(SB), NOSPLIT, $0-8 + // get Instruction Set Attributes 0 into x0 + // mrs x0, ID_AA64ISAR0_EL1 = d5380600 + WORD $0xd5380600 + MOVD R0, ret+0(FP) + RET + +// func getisar1() uint64 +TEXT ·getisar1(SB), NOSPLIT, $0-8 + // get Instruction Set Attributes 1 into x0 + // mrs x0, ID_AA64ISAR1_EL1 = d5380620 + WORD $0xd5380620 + MOVD R0, ret+0(FP) + RET diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go new file mode 100644 index 00000000..50a178f5 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go @@ -0,0 +1,17 @@ +//go:build !(amd64 || arm64) || !gc + +package platform + +var CpuFeatures CpuFeatureFlags = &cpuFeatureFlags{} + +// cpuFeatureFlags implements CpuFeatureFlags for unsupported platforms. +type cpuFeatureFlags struct{} + +// Has implements the same method on the CpuFeatureFlags interface. +func (c *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { return false } + +// HasExtra implements the same method on the CpuFeatureFlags interface. +func (c *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { return false } + +// Raw implements the same method on the CpuFeatureFlags interface. +func (c *cpuFeatureFlags) Raw() uint64 { return 0 } diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go b/vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go new file mode 100644 index 00000000..c141f00f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go @@ -0,0 +1,17 @@ +package platform + +import ( + "io" + "math/rand" +) + +// seed is a fixed seed value for NewFakeRandSource. +// +// Trivia: While arbitrary, 42 was chosen as it is the "Ultimate Answer" in +// the Douglas Adams novel "The Hitchhiker's Guide to the Galaxy." +const seed = int64(42) + +// NewFakeRandSource returns a deterministic source of random values. +func NewFakeRandSource() io.Reader { + return rand.New(rand.NewSource(seed)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go new file mode 100644 index 00000000..55906e82 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go @@ -0,0 +1,76 @@ +package platform + +import ( + "math/bits" + "os" + "sort" + "strconv" + "strings" + "syscall" +) + +const ( + // https://man7.org/linux/man-pages/man2/mmap.2.html + __MAP_HUGE_SHIFT = 26 + __MAP_HUGETLB = 0x40000 +) + +var hugePagesConfigs []hugePagesConfig + +type hugePagesConfig struct { + size int + flag int +} + +func (hpc *hugePagesConfig) match(size int) bool { + return (size & (hpc.size - 1)) == 0 +} + +func init() { + dirents, err := os.ReadDir("/sys/kernel/mm/hugepages/") + if err != nil { + return + } + + for _, dirent := range dirents { + name := dirent.Name() + if !strings.HasPrefix(name, "hugepages-") { + continue + } + if !strings.HasSuffix(name, "kB") { + continue + } + n, err := strconv.ParseUint(name[10:len(name)-2], 10, 64) + if err != nil { + continue + } + if bits.OnesCount64(n) != 1 { + continue + } + n *= 1024 + hugePagesConfigs = append(hugePagesConfigs, hugePagesConfig{ + size: int(n), + flag: int(bits.TrailingZeros64(n)<<__MAP_HUGE_SHIFT) | __MAP_HUGETLB, + }) + } + + sort.Slice(hugePagesConfigs, func(i, j int) bool { + return hugePagesConfigs[i].size > hugePagesConfigs[j].size + }) +} + +func mmapCodeSegment(size, prot int) ([]byte, error) { + flags := syscall.MAP_ANON | syscall.MAP_PRIVATE + + for _, hugePagesConfig := range hugePagesConfigs { + if hugePagesConfig.match(size) { + b, err := syscall.Mmap(-1, 0, size, prot, flags|hugePagesConfig.flag) + if err != nil { + continue + } + return b, nil + } + } + + return syscall.Mmap(-1, 0, size, prot, flags) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go new file mode 100644 index 00000000..9f0610f2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go @@ -0,0 +1,18 @@ +// Separated from linux which has support for huge pages. +//go:build darwin || freebsd || netbsd || dragonfly || solaris + +package platform + +import "syscall" + +func mmapCodeSegment(size, prot int) ([]byte, error) { + return syscall.Mmap( + -1, + 0, + size, + prot, + // Anonymous as this is not an actual file, but a memory, + // Private as this is in-process memory region. + syscall.MAP_ANON|syscall.MAP_PRIVATE, + ) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go new file mode 100644 index 00000000..8d0baa71 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go @@ -0,0 +1,32 @@ +//go:build (linux || darwin || freebsd || netbsd || dragonfly || solaris) && !tinygo + +package platform + +import ( + "syscall" +) + +const ( + mmapProtAMD64 = syscall.PROT_READ | syscall.PROT_WRITE | syscall.PROT_EXEC + mmapProtARM64 = syscall.PROT_READ | syscall.PROT_WRITE +) + +func munmapCodeSegment(code []byte) error { + return syscall.Munmap(code) +} + +// mmapCodeSegmentAMD64 gives all read-write-exec permission to the mmap region +// to enter the function. Otherwise, segmentation fault exception is raised. +func mmapCodeSegmentAMD64(size int) ([]byte, error) { + // The region must be RWX: RW for writing native codes, X for executing the region. + return mmapCodeSegment(size, mmapProtAMD64) +} + +// mmapCodeSegmentARM64 cannot give all read-write-exec permission to the mmap region. +// Otherwise, the mmap systemcall would raise an error. Here we give read-write +// to the region so that we can write contents at call-sites. Callers are responsible to +// execute MprotectRX on the returned buffer. +func mmapCodeSegmentARM64(size int) ([]byte, error) { + // The region must be RW: RW for writing native codes. + return mmapCodeSegment(size, mmapProtARM64) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go new file mode 100644 index 00000000..f3fa0911 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go @@ -0,0 +1,26 @@ +//go:build !(linux || darwin || freebsd || netbsd || dragonfly || solaris || windows) || tinygo + +package platform + +import ( + "fmt" + "runtime" +) + +var errUnsupported = fmt.Errorf("mmap unsupported on GOOS=%s. Use interpreter instead.", runtime.GOOS) + +func munmapCodeSegment(code []byte) error { + panic(errUnsupported) +} + +func mmapCodeSegmentAMD64(size int) ([]byte, error) { + panic(errUnsupported) +} + +func mmapCodeSegmentARM64(size int) ([]byte, error) { + panic(errUnsupported) +} + +func MprotectRX(b []byte) (err error) { + panic(errUnsupported) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go new file mode 100644 index 00000000..03a254d4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go @@ -0,0 +1,95 @@ +package platform + +import ( + "fmt" + "syscall" + "unsafe" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procVirtualAlloc = kernel32.NewProc("VirtualAlloc") + procVirtualProtect = kernel32.NewProc("VirtualProtect") + procVirtualFree = kernel32.NewProc("VirtualFree") +) + +const ( + windows_MEM_COMMIT uintptr = 0x00001000 + windows_MEM_RELEASE uintptr = 0x00008000 + windows_PAGE_READWRITE uintptr = 0x00000004 + windows_PAGE_EXECUTE_READ uintptr = 0x00000020 + windows_PAGE_EXECUTE_READWRITE uintptr = 0x00000040 +) + +func munmapCodeSegment(code []byte) error { + return freeMemory(code) +} + +// allocateMemory commits the memory region via the "VirtualAlloc" function. +// See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc +func allocateMemory(size uintptr, protect uintptr) (uintptr, error) { + address := uintptr(0) // system determines where to allocate the region. + alloctype := windows_MEM_COMMIT + if r, _, err := procVirtualAlloc.Call(address, size, alloctype, protect); r == 0 { + return 0, fmt.Errorf("compiler: VirtualAlloc error: %w", ensureErr(err)) + } else { + return r, nil + } +} + +// freeMemory releases the memory region via the "VirtualFree" function. +// See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualfree +func freeMemory(code []byte) error { + address := unsafe.Pointer(&code[0]) + size := uintptr(0) // size must be 0 because we're using MEM_RELEASE. + freetype := windows_MEM_RELEASE + if r, _, err := procVirtualFree.Call(uintptr(address), size, freetype); r == 0 { + return fmt.Errorf("compiler: VirtualFree error: %w", ensureErr(err)) + } + return nil +} + +func virtualProtect(address, size, newprotect uintptr, oldprotect *uint32) error { + if r, _, err := procVirtualProtect.Call(address, size, newprotect, uintptr(unsafe.Pointer(oldprotect))); r == 0 { + return fmt.Errorf("compiler: VirtualProtect error: %w", ensureErr(err)) + } + return nil +} + +func mmapCodeSegmentAMD64(size int) ([]byte, error) { + p, err := allocateMemory(uintptr(size), windows_PAGE_EXECUTE_READWRITE) + if err != nil { + return nil, err + } + + return unsafe.Slice((*byte)(unsafe.Pointer(p)), size), nil +} + +func mmapCodeSegmentARM64(size int) ([]byte, error) { + p, err := allocateMemory(uintptr(size), windows_PAGE_READWRITE) + if err != nil { + return nil, err + } + + return unsafe.Slice((*byte)(unsafe.Pointer(p)), size), nil +} + +var old = uint32(windows_PAGE_READWRITE) + +func MprotectRX(b []byte) (err error) { + err = virtualProtect(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), windows_PAGE_EXECUTE_READ, &old) + return +} + +// ensureErr returns syscall.EINVAL when the input error is nil. +// +// We are supposed to use "GetLastError" which is more precise, but it is not safe to execute in goroutines. While +// "GetLastError" is thread-local, goroutines are not pinned to threads. +// +// See https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror +func ensureErr(err error) error { + if err != nil { + return err + } + return syscall.EINVAL +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_bsd.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_bsd.go new file mode 100644 index 00000000..f8f40cab --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_bsd.go @@ -0,0 +1,22 @@ +//go:build (freebsd || netbsd || dragonfly) && !tinygo + +package platform + +import ( + "syscall" + "unsafe" +) + +// MprotectRX is like syscall.Mprotect with RX permission, defined locally so that BSD compiles. +func MprotectRX(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } + const prot = syscall.PROT_READ | syscall.PROT_EXEC + _, _, e1 := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + if e1 != 0 { + err = syscall.Errno(e1) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_syscall.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_syscall.go new file mode 100644 index 00000000..6fe96d6f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_syscall.go @@ -0,0 +1,10 @@ +//go:build (linux || darwin) && !tinygo + +package platform + +import "syscall" + +// MprotectRX is like syscall.Mprotect with RX permission. +func MprotectRX(b []byte) (err error) { + return syscall.Mprotect(b, syscall.PROT_READ|syscall.PROT_EXEC) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_unsupported.go new file mode 100644 index 00000000..84719ab0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/mprotect_unsupported.go @@ -0,0 +1,9 @@ +//go:build solaris && !tinygo + +package platform + +import "syscall" + +func MprotectRX(b []byte) error { + return syscall.ENOTSUP +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/path.go b/vendor/github.com/tetratelabs/wazero/internal/platform/path.go new file mode 100644 index 00000000..361049ae --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/path.go @@ -0,0 +1,6 @@ +//go:build !windows + +package platform + +// ToPosixPath returns the input, as only windows might return backslashes. +func ToPosixPath(in string) string { return in } diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go b/vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go new file mode 100644 index 00000000..77c4187d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go @@ -0,0 +1,17 @@ +package platform + +import "strings" + +// ToPosixPath returns the input, converting any backslashes to forward ones. +func ToPosixPath(in string) string { + // strings.Map only allocates on change, which is good enough especially as + // path.Join uses forward slash even on windows. + return strings.Map(windowsToPosixSeparator, in) +} + +func windowsToPosixSeparator(r rune) rune { + if r == '\\' { + return '/' + } + return r +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/platform.go b/vendor/github.com/tetratelabs/wazero/internal/platform/platform.go new file mode 100644 index 00000000..532cc7b8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/platform.go @@ -0,0 +1,56 @@ +// Package platform includes runtime-specific code needed for the compiler or otherwise. +// +// Note: This is a dependency-free alternative to depending on parts of Go's x/sys. +// See /RATIONALE.md for more context. +package platform + +import ( + "runtime" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" +) + +// CompilerSupported includes constraints here and also the assembler. +func CompilerSupported() bool { + return CompilerSupports(api.CoreFeaturesV2) +} + +func CompilerSupports(features api.CoreFeatures) bool { + switch runtime.GOOS { + case "linux", "darwin", "freebsd", "netbsd", "dragonfly", "windows": + if runtime.GOARCH == "arm64" { + if features.IsEnabled(experimental.CoreFeaturesThreads) { + return CpuFeatures.Has(CpuFeatureArm64Atomic) + } + return true + } + fallthrough + case "solaris", "illumos": + return runtime.GOARCH == "amd64" && CpuFeatures.Has(CpuFeatureAmd64SSE4_1) + default: + return false + } +} + +// MmapCodeSegment copies the code into the executable region and returns the byte slice of the region. +// +// See https://man7.org/linux/man-pages/man2/mmap.2.html for mmap API and flags. +func MmapCodeSegment(size int) ([]byte, error) { + if size == 0 { + panic("BUG: MmapCodeSegment with zero length") + } + if runtime.GOARCH == "amd64" { + return mmapCodeSegmentAMD64(size) + } else { + return mmapCodeSegmentARM64(size) + } +} + +// MunmapCodeSegment unmaps the given memory region. +func MunmapCodeSegment(code []byte) error { + if len(code) == 0 { + panic("BUG: MunmapCodeSegment with zero length") + } + return munmapCodeSegment(code) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/time.go b/vendor/github.com/tetratelabs/wazero/internal/platform/time.go new file mode 100644 index 00000000..fa9da1ac --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/time.go @@ -0,0 +1,76 @@ +package platform + +import ( + "sync/atomic" + "time" + + "github.com/tetratelabs/wazero/sys" +) + +const ( + ms = int64(time.Millisecond) + // FakeEpochNanos is midnight UTC 2022-01-01 and exposed for testing + FakeEpochNanos = 1640995200000 * ms +) + +// NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading. +// See /RATIONALE.md +func NewFakeWalltime() sys.Walltime { + // AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos + t := FakeEpochNanos - ms + return func() (sec int64, nsec int32) { + wt := atomic.AddInt64(&t, ms) + return wt / 1e9, int32(wt % 1e9) + } +} + +// NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading. +// See /RATIONALE.md +func NewFakeNanotime() sys.Nanotime { + // AddInt64 returns the new value. Adjust so the first reading will be zero. + t := int64(0) - ms + return func() int64 { + return atomic.AddInt64(&t, ms) + } +} + +// FakeNanosleep implements sys.Nanosleep by returning without sleeping. +var FakeNanosleep = sys.Nanosleep(func(int64) {}) + +// FakeOsyield implements sys.Osyield by returning without yielding. +var FakeOsyield = sys.Osyield(func() {}) + +// Walltime implements sys.Walltime with time.Now. +// +// Note: This is only notably less efficient than it could be is reading +// runtime.walltime(). time.Now defensively reads nanotime also, just in case +// time.Since is used. This doubles the performance impact. However, wall time +// is likely to be read less frequently than Nanotime. Also, doubling the cost +// matters less on fast platforms that can return both in <=100ns. +func Walltime() (sec int64, nsec int32) { + t := time.Now() + return t.Unix(), int32(t.Nanosecond()) +} + +// nanoBase uses time.Now to ensure a monotonic clock reading on all platforms +// via time.Since. +var nanoBase = time.Now() + +// nanotimePortable implements sys.Nanotime with time.Since. +// +// Note: This is less efficient than it could be is reading runtime.nanotime(), +// Just to do that requires CGO. +func nanotimePortable() int64 { + return time.Since(nanoBase).Nanoseconds() +} + +// Nanotime implements sys.Nanotime with runtime.nanotime() if CGO is available +// and time.Since if not. +func Nanotime() int64 { + return nanotime() +} + +// Nanosleep implements sys.Nanosleep with time.Sleep. +func Nanosleep(ns int64) { + time.Sleep(time.Duration(ns)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go b/vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go new file mode 100644 index 00000000..ff01d90c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go @@ -0,0 +1,11 @@ +//go:build cgo && !windows + +package platform + +import _ "unsafe" // for go:linkname + +// nanotime uses runtime.nanotime as it is available on all platforms and +// benchmarks faster than using time.Since. +// +//go:linkname nanotime runtime.nanotime +func nanotime() int64 diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go b/vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go new file mode 100644 index 00000000..0697b7c7 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go @@ -0,0 +1,7 @@ +//go:build !cgo && !windows + +package platform + +func nanotime() int64 { + return nanotimePortable() +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go b/vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go new file mode 100644 index 00000000..58731fc8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go @@ -0,0 +1,40 @@ +//go:build windows + +package platform + +import ( + "math/bits" + "time" + "unsafe" +) + +var ( + _QueryPerformanceCounter = kernel32.NewProc("QueryPerformanceCounter") + _QueryPerformanceFrequency = kernel32.NewProc("QueryPerformanceFrequency") +) + +var qpcfreq uint64 + +func init() { + _, _, _ = _QueryPerformanceFrequency.Call(uintptr(unsafe.Pointer(&qpcfreq))) +} + +// On Windows, time.Time handled in time package cannot have the nanosecond precision. +// The reason is that by default, it doesn't use QueryPerformanceCounter[1], but instead, use "interrupt time" +// which doesn't support nanoseconds precision (though it is a monotonic) [2, 3, 4, 5]. +// +// [1] https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter +// [2] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/sys_windows_amd64.s#L297-L298 +// [3] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/os_windows.go#L549-L551 +// [4] https://github.com/golang/go/blob/master/src/runtime/time_windows.h#L7-L13 +// [5] http://web.archive.org/web/20210411000829/https://wrkhpi.wordpress.com/2007/08/09/getting-os-information-the-kuser_shared_data-structure/ +// +// Therefore, on Windows, we directly invoke the syscall for QPC instead of time.Now or runtime.nanotime. +// See https://github.com/golang/go/issues/31160 for example. +func nanotime() int64 { + var counter uint64 + _, _, _ = _QueryPerformanceCounter.Call(uintptr(unsafe.Pointer(&counter))) + hi, lo := bits.Mul64(counter, uint64(time.Second)) + nanos, _ := bits.Div64(hi, lo, qpcfreq) + return int64(nanos) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sock/sock.go b/vendor/github.com/tetratelabs/wazero/internal/sock/sock.go new file mode 100644 index 00000000..ca17aa39 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sock/sock.go @@ -0,0 +1,89 @@ +package sock + +import ( + "fmt" + "net" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// TCPSock is a pseudo-file representing a TCP socket. +type TCPSock interface { + sys.File + + Accept() (TCPConn, sys.Errno) +} + +// TCPConn is a pseudo-file representing a TCP connection. +type TCPConn interface { + sys.File + + // Recvfrom only supports the flag sysfs.MSG_PEEK + // TODO: document this like sys.File with known sys.Errno + Recvfrom(p []byte, flags int) (n int, errno sys.Errno) + + // TODO: document this like sys.File with known sys.Errno + Shutdown(how int) sys.Errno +} + +// ConfigKey is a context.Context Value key. Its associated value should be a Config. +type ConfigKey struct{} + +// Config is an internal struct meant to implement +// the interface in experimental/sock/Config. +type Config struct { + // TCPAddresses is a slice of the configured host:port pairs. + TCPAddresses []TCPAddress +} + +// TCPAddress is a host:port pair to pre-open. +type TCPAddress struct { + // Host is the host name for this listener. + Host string + // Port is the port number for this listener. + Port int +} + +// WithTCPListener implements the method of the same name in experimental/sock/Config. +// +// However, to avoid cyclic dependencies, this is returning the *Config in this scope. +// The interface is implemented in experimental/sock/Config via delegation. +func (c *Config) WithTCPListener(host string, port int) *Config { + ret := c.clone() + ret.TCPAddresses = append(ret.TCPAddresses, TCPAddress{host, port}) + return &ret +} + +// Makes a deep copy of this sockConfig. +func (c *Config) clone() Config { + ret := *c + ret.TCPAddresses = make([]TCPAddress, 0, len(c.TCPAddresses)) + ret.TCPAddresses = append(ret.TCPAddresses, c.TCPAddresses...) + return ret +} + +// BuildTCPListeners build listeners from the current configuration. +func (c *Config) BuildTCPListeners() (tcpListeners []*net.TCPListener, err error) { + for _, tcpAddr := range c.TCPAddresses { + var ln net.Listener + ln, err = net.Listen("tcp", tcpAddr.String()) + if err != nil { + break + } + if tcpln, ok := ln.(*net.TCPListener); ok { + tcpListeners = append(tcpListeners, tcpln) + } + } + if err != nil { + // An error occurred, cleanup. + for _, l := range tcpListeners { + _ = l.Close() // Ignore errors, we are already cleaning. + } + tcpListeners = nil + } + return +} + +func (t TCPAddress) String() string { + return fmt.Sprintf("%s:%d", t.Host, t.Port) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sock/sock_supported.go b/vendor/github.com/tetratelabs/wazero/internal/sock/sock_supported.go new file mode 100644 index 00000000..e317be83 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sock/sock_supported.go @@ -0,0 +1,11 @@ +//go:build !plan9 && !js && !tinygo + +package sock + +import "syscall" + +const ( + SHUT_RD = syscall.SHUT_RD + SHUT_RDWR = syscall.SHUT_RDWR + SHUT_WR = syscall.SHUT_WR +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/sock/sock_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sock/sock_unsupported.go new file mode 100644 index 00000000..77026754 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sock/sock_unsupported.go @@ -0,0 +1,10 @@ +//go:build plan9 || js || tinygo + +package sock + +// plan9/js doesn't declare these constants +const ( + SHUT_RD = 1 << iota + SHUT_WR + SHUT_RDWR = SHUT_RD | SHUT_WR +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/sys/fs.go b/vendor/github.com/tetratelabs/wazero/internal/sys/fs.go new file mode 100644 index 00000000..157de788 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sys/fs.go @@ -0,0 +1,457 @@ +package sys + +import ( + "io" + "io/fs" + "net" + + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/descriptor" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" + "github.com/tetratelabs/wazero/internal/sysfs" +) + +const ( + FdStdin int32 = iota + FdStdout + FdStderr + // FdPreopen is the file descriptor of the first pre-opened directory. + // + // # Why file descriptor 3? + // + // While not specified, the most common WASI implementation, wasi-libc, + // expects POSIX style file descriptor allocation, where the lowest + // available number is used to open the next file. Since 1 and 2 are taken + // by stdout and stderr, the next is 3. + // - https://github.com/WebAssembly/WASI/issues/122 + // - https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_14 + // - https://github.com/WebAssembly/wasi-libc/blob/wasi-sdk-16/libc-bottom-half/sources/preopens.c#L215 + FdPreopen +) + +const modeDevice = fs.ModeDevice | 0o640 + +// FileEntry maps a path to an open file in a file system. +type FileEntry struct { + // Name is the name of the directory up to its pre-open, or the pre-open + // name itself when IsPreopen. + // + // # Notes + // + // - This can drift on rename. + // - This relates to the guest path, which is not the real file path + // except if the entire host filesystem was made available. + Name string + + // IsPreopen is a directory that is lazily opened. + IsPreopen bool + + // FS is the filesystem associated with the pre-open. + FS sys.FS + + // File is always non-nil. + File fsapi.File + + // direntCache is nil until DirentCache was called. + direntCache *DirentCache +} + +// DirentCache gets or creates a DirentCache for this file or returns an error. +// +// # Errors +// +// A zero sys.Errno is success. The below are expected otherwise: +// - sys.ENOSYS: the implementation does not support this function. +// - sys.EBADF: the dir was closed or not readable. +// - sys.ENOTDIR: the file was not a directory. +// +// # Notes +// +// - See /RATIONALE.md for design notes. +func (f *FileEntry) DirentCache() (*DirentCache, sys.Errno) { + if dir := f.direntCache; dir != nil { + return dir, 0 + } + + // Require the file to be a directory vs a late error on the same. + if isDir, errno := f.File.IsDir(); errno != 0 { + return nil, errno + } else if !isDir { + return nil, sys.ENOTDIR + } + + // Generate the dotEntries only once. + if dotEntries, errno := synthesizeDotEntries(f); errno != 0 { + return nil, errno + } else { + f.direntCache = &DirentCache{f: f.File, dotEntries: dotEntries} + } + + return f.direntCache, 0 +} + +// DirentCache is a caching abstraction of sys.File Readdir. +// +// This is special-cased for "wasi_snapshot_preview1.fd_readdir", and may be +// unneeded, or require changes, to support preview1 or preview2. +// - The position of the dirents are serialized as `d_next`. For reasons +// described below, any may need to be re-read. This accepts any positions +// in the cache, rather than track the position of the last dirent. +// - dot entries ("." and "..") must be returned. See /RATIONALE.md for why. +// - An sys.Dirent Name is variable length, it could exceed memory size and +// need to be re-read. +// - Multiple dirents may be returned. It is more efficient to read from the +// underlying file in bulk vs one-at-a-time. +// +// The last results returned by Read are cached, but entries before that +// position are not. This support re-reading entries that couldn't fit into +// memory without accidentally caching all entries in a large directory. This +// approach is sometimes called a sliding window. +type DirentCache struct { + // f is the underlying file + f sys.File + + // dotEntries are the "." and ".." entries added when the directory is + // initialized. + dotEntries []sys.Dirent + + // dirents are the potentially unread directory entries. + // + // Internal detail: nil is different from zero length. Zero length is an + // exhausted directory (eof). nil means the re-read. + dirents []sys.Dirent + + // countRead is the total count of dirents read since last rewind. + countRead uint64 + + // eof is true when the underlying file is at EOF. This avoids re-reading + // the directory when it is exhausted. Entires in an exhausted directory + // are not visible until it is rewound via calling Read with `pos==0`. + eof bool +} + +// synthesizeDotEntries generates a slice of the two elements "." and "..". +func synthesizeDotEntries(f *FileEntry) ([]sys.Dirent, sys.Errno) { + dotIno, errno := f.File.Ino() + if errno != 0 { + return nil, errno + } + result := [2]sys.Dirent{} + result[0] = sys.Dirent{Name: ".", Ino: dotIno, Type: fs.ModeDir} + // See /RATIONALE.md for why we don't attempt to get an inode for ".." and + // why in wasi-libc this won't fan-out either. + result[1] = sys.Dirent{Name: "..", Ino: 0, Type: fs.ModeDir} + return result[:], 0 +} + +// exhaustedDirents avoids allocating empty slices. +var exhaustedDirents = [0]sys.Dirent{} + +// Read is similar to and returns the same errors as `Readdir` on sys.File. +// The main difference is this caches entries returned, resulting in multiple +// valid positions to read from. +// +// When zero, `pos` means rewind to the beginning of this directory. This +// implies a rewind (Seek to zero on the underlying sys.File), unless the +// initial entries are still cached. +// +// When non-zero, `pos` is the zero based index of all dirents returned since +// last rewind. Only entries beginning at `pos` are cached for subsequent +// calls. A non-zero `pos` before the cache returns sys.ENOENT for reasons +// described on DirentCache documentation. +// +// Up to `n` entries are cached and returned. When `n` exceeds the cache, the +// difference are read from the underlying sys.File via `Readdir`. EOF is +// when `len(dirents)` returned are less than `n`. +func (d *DirentCache) Read(pos uint64, n uint32) (dirents []sys.Dirent, errno sys.Errno) { + switch { + case pos > d.countRead: // farther than read or negative coerced to uint64. + return nil, sys.ENOENT + case pos == 0 && d.dirents != nil: + // Rewind if we have already read entries. This allows us to see new + // entries added after the directory was opened. + if _, errno = d.f.Seek(0, io.SeekStart); errno != 0 { + return + } + d.dirents = nil // dump cache + d.countRead = 0 + } + + if n == 0 { + return // special case no entries. + } + + if d.dirents == nil { + // Always populate dot entries, which makes min len(dirents) == 2. + d.dirents = d.dotEntries + d.countRead = 2 + d.eof = false + + if countToRead := int(n - 2); countToRead <= 0 { + return + } else if dirents, errno = d.f.Readdir(countToRead); errno != 0 { + return + } else if countRead := len(dirents); countRead > 0 { + d.eof = countRead < countToRead + d.dirents = append(d.dotEntries, dirents...) + d.countRead += uint64(countRead) + } + + return d.cachedDirents(n), 0 + } + + // Reset our cache to the first entry being read. + cacheStart := d.countRead - uint64(len(d.dirents)) + if pos < cacheStart { + // We don't currently allow reads before our cache because Seek(0) is + // the only portable way. Doing otherwise requires skipping, which we + // won't do unless wasi-testsuite starts requiring it. Implementing + // this would allow re-reading a large directory, so care would be + // needed to not buffer the entire directory in memory while skipping. + errno = sys.ENOENT + return + } else if posInCache := pos - cacheStart; posInCache != 0 { + if uint64(len(d.dirents)) == posInCache { + // Avoid allocation re-slicing to zero length. + d.dirents = exhaustedDirents[:] + } else { + d.dirents = d.dirents[posInCache:] + } + } + + // See if we need more entries. + if countToRead := int(n) - len(d.dirents); countToRead > 0 && !d.eof { + // Try to read more, which could fail. + if dirents, errno = d.f.Readdir(countToRead); errno != 0 { + return + } + + // Append the next read entries if we weren't at EOF. + if countRead := len(dirents); countRead > 0 { + d.eof = countRead < countToRead + d.dirents = append(d.dirents, dirents...) + d.countRead += uint64(countRead) + } + } + + return d.cachedDirents(n), 0 +} + +// cachedDirents returns up to `n` dirents from the cache. +func (d *DirentCache) cachedDirents(n uint32) []sys.Dirent { + direntCount := uint32(len(d.dirents)) + switch { + case direntCount == 0: + return nil + case direntCount > n: + return d.dirents[:n] + } + return d.dirents +} + +type FSContext struct { + // openedFiles is a map of file descriptor numbers (>=FdPreopen) to open files + // (or directories) and defaults to empty. + // TODO: This is unguarded, so not goroutine-safe! + openedFiles FileTable +} + +// FileTable is a specialization of the descriptor.Table type used to map file +// descriptors to file entries. +type FileTable = descriptor.Table[int32, *FileEntry] + +// LookupFile returns a file if it is in the table. +func (c *FSContext) LookupFile(fd int32) (*FileEntry, bool) { + return c.openedFiles.Lookup(fd) +} + +// OpenFile opens the file into the table and returns its file descriptor. +// The result must be closed by CloseFile or Close. +func (c *FSContext) OpenFile(fs sys.FS, path string, flag sys.Oflag, perm fs.FileMode) (int32, sys.Errno) { + if f, errno := fs.OpenFile(path, flag, perm); errno != 0 { + return 0, errno + } else { + fe := &FileEntry{FS: fs, File: fsapi.Adapt(f)} + if path == "/" || path == "." { + fe.Name = "" + } else { + fe.Name = path + } + if newFD, ok := c.openedFiles.Insert(fe); !ok { + return 0, sys.EBADF + } else { + return newFD, 0 + } + } +} + +// Renumber assigns the file pointed by the descriptor `from` to `to`. +func (c *FSContext) Renumber(from, to int32) sys.Errno { + fromFile, ok := c.openedFiles.Lookup(from) + if !ok || to < 0 { + return sys.EBADF + } else if fromFile.IsPreopen { + return sys.ENOTSUP + } + + // If toFile is already open, we close it to prevent windows lock issues. + // + // The doc is unclear and other implementations do nothing for already-opened To FDs. + // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_renumberfd-fd-to-fd---errno + // https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi-common/src/snapshots/preview_1.rs#L531-L546 + if toFile, ok := c.openedFiles.Lookup(to); ok { + if toFile.IsPreopen { + return sys.ENOTSUP + } + _ = toFile.File.Close() + } + + c.openedFiles.Delete(from) + if !c.openedFiles.InsertAt(fromFile, to) { + return sys.EBADF + } + return 0 +} + +// SockAccept accepts a sock.TCPConn into the file table and returns its file +// descriptor. +func (c *FSContext) SockAccept(sockFD int32, nonblock bool) (int32, sys.Errno) { + var sock socketapi.TCPSock + if e, ok := c.LookupFile(sockFD); !ok || !e.IsPreopen { + return 0, sys.EBADF // Not a preopen + } else if sock, ok = e.File.(socketapi.TCPSock); !ok { + return 0, sys.EBADF // Not a sock + } + + conn, errno := sock.Accept() + if errno != 0 { + return 0, errno + } + + fe := &FileEntry{File: fsapi.Adapt(conn)} + + if nonblock { + if errno = fe.File.SetNonblock(true); errno != 0 { + _ = conn.Close() + return 0, errno + } + } + + if newFD, ok := c.openedFiles.Insert(fe); !ok { + return 0, sys.EBADF + } else { + return newFD, 0 + } +} + +// CloseFile returns any error closing the existing file. +func (c *FSContext) CloseFile(fd int32) (errno sys.Errno) { + f, ok := c.openedFiles.Lookup(fd) + if !ok { + return sys.EBADF + } + if errno = f.File.Close(); errno != 0 { + return errno + } + c.openedFiles.Delete(fd) + return errno +} + +// Close implements io.Closer +func (c *FSContext) Close() (err error) { + // Close any files opened in this context + c.openedFiles.Range(func(fd int32, entry *FileEntry) bool { + if errno := entry.File.Close(); errno != 0 { + err = errno // This means err returned == the last non-nil error. + } + return true + }) + // A closed FSContext cannot be reused so clear the state. + c.openedFiles = FileTable{} + return +} + +// InitFSContext initializes a FSContext with stdio streams and optional +// pre-opened filesystems and TCP listeners. +func (c *Context) InitFSContext( + stdin io.Reader, + stdout, stderr io.Writer, + fs []sys.FS, guestPaths []string, + tcpListeners []*net.TCPListener, +) (err error) { + inFile, err := stdinFileEntry(stdin) + if err != nil { + return err + } + c.fsc.openedFiles.Insert(inFile) + outWriter, err := stdioWriterFileEntry("stdout", stdout) + if err != nil { + return err + } + c.fsc.openedFiles.Insert(outWriter) + errWriter, err := stdioWriterFileEntry("stderr", stderr) + if err != nil { + return err + } + c.fsc.openedFiles.Insert(errWriter) + + for i, f := range fs { + guestPath := guestPaths[i] + + if StripPrefixesAndTrailingSlash(guestPath) == "" { + // Default to bind to '/' when guestPath is effectively empty. + guestPath = "/" + } + c.fsc.openedFiles.Insert(&FileEntry{ + FS: f, + Name: guestPath, + IsPreopen: true, + File: &lazyDir{fs: f}, + }) + } + + for _, tl := range tcpListeners { + c.fsc.openedFiles.Insert(&FileEntry{IsPreopen: true, File: fsapi.Adapt(sysfs.NewTCPListenerFile(tl))}) + } + return nil +} + +// StripPrefixesAndTrailingSlash skips any leading "./" or "/" such that the +// result index begins with another string. A result of "." coerces to the +// empty string "" because the current directory is handled by the guest. +// +// Results are the offset/len pair which is an optimization to avoid re-slicing +// overhead, as this function is called for every path operation. +// +// Note: Relative paths should be handled by the guest, as that's what knows +// what the current directory is. However, paths that escape the current +// directory e.g. "../.." have been found in `tinygo test` and this +// implementation takes care to avoid it. +func StripPrefixesAndTrailingSlash(path string) string { + // strip trailing slashes + pathLen := len(path) + for ; pathLen > 0 && path[pathLen-1] == '/'; pathLen-- { + } + + pathI := 0 +loop: + for pathI < pathLen { + switch path[pathI] { + case '/': + pathI++ + case '.': + nextI := pathI + 1 + if nextI < pathLen && path[nextI] == '/' { + pathI = nextI + 1 + } else if nextI == pathLen { + pathI = nextI + } else { + break loop + } + default: + break loop + } + } + return path[pathI:pathLen] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sys/lazy.go b/vendor/github.com/tetratelabs/wazero/internal/sys/lazy.go new file mode 100644 index 00000000..fe233d29 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sys/lazy.go @@ -0,0 +1,151 @@ +package sys + +import ( + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/sys" +) + +// compile-time check to ensure lazyDir implements sys.File. +var _ experimentalsys.File = (*lazyDir)(nil) + +type lazyDir struct { + experimentalsys.DirFile + + fs experimentalsys.FS + f experimentalsys.File +} + +// Dev implements the same method as documented on sys.File +func (d *lazyDir) Dev() (uint64, experimentalsys.Errno) { + if f, ok := d.file(); !ok { + return 0, experimentalsys.EBADF + } else { + return f.Dev() + } +} + +// Ino implements the same method as documented on sys.File +func (d *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) { + if f, ok := d.file(); !ok { + return 0, experimentalsys.EBADF + } else { + return f.Ino() + } +} + +// IsDir implements the same method as documented on sys.File +func (d *lazyDir) IsDir() (bool, experimentalsys.Errno) { + // Note: we don't return a constant because we don't know if this is really + // backed by a dir, until the first call. + if f, ok := d.file(); !ok { + return false, experimentalsys.EBADF + } else { + return f.IsDir() + } +} + +// IsAppend implements the same method as documented on sys.File +func (d *lazyDir) IsAppend() bool { + return false +} + +// SetAppend implements the same method as documented on sys.File +func (d *lazyDir) SetAppend(bool) experimentalsys.Errno { + return experimentalsys.EISDIR +} + +// Seek implements the same method as documented on sys.File +func (d *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { + if f, ok := d.file(); !ok { + return 0, experimentalsys.EBADF + } else { + return f.Seek(offset, whence) + } +} + +// Stat implements the same method as documented on sys.File +func (d *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) { + if f, ok := d.file(); !ok { + return sys.Stat_t{}, experimentalsys.EBADF + } else { + return f.Stat() + } +} + +// Readdir implements the same method as documented on sys.File +func (d *lazyDir) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { + if f, ok := d.file(); !ok { + return nil, experimentalsys.EBADF + } else { + return f.Readdir(n) + } +} + +// Sync implements the same method as documented on sys.File +func (d *lazyDir) Sync() experimentalsys.Errno { + if f, ok := d.file(); !ok { + return experimentalsys.EBADF + } else { + return f.Sync() + } +} + +// Datasync implements the same method as documented on sys.File +func (d *lazyDir) Datasync() experimentalsys.Errno { + if f, ok := d.file(); !ok { + return experimentalsys.EBADF + } else { + return f.Datasync() + } +} + +// Utimens implements the same method as documented on sys.File +func (d *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno { + if f, ok := d.file(); !ok { + return experimentalsys.EBADF + } else { + return f.Utimens(atim, mtim) + } +} + +// file returns the underlying file or false if it doesn't exist. +func (d *lazyDir) file() (experimentalsys.File, bool) { + if f := d.f; d.f != nil { + return f, true + } + var errno experimentalsys.Errno + d.f, errno = d.fs.OpenFile(".", experimentalsys.O_RDONLY, 0) + switch errno { + case 0: + return d.f, true + case experimentalsys.ENOENT: + return nil, false + default: + panic(errno) // unexpected + } +} + +// Close implements fs.File +func (d *lazyDir) Close() experimentalsys.Errno { + f := d.f + if f == nil { + return 0 // never opened + } + return f.Close() +} + +// IsNonblock implements the same method as documented on fsapi.File +func (d *lazyDir) IsNonblock() bool { + return false +} + +// SetNonblock implements the same method as documented on fsapi.File +func (d *lazyDir) SetNonblock(bool) experimentalsys.Errno { + return experimentalsys.EISDIR +} + +// Poll implements the same method as documented on fsapi.File +func (d *lazyDir) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sys/stdio.go b/vendor/github.com/tetratelabs/wazero/internal/sys/stdio.go new file mode 100644 index 00000000..32c33661 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sys/stdio.go @@ -0,0 +1,128 @@ +package sys + +import ( + "io" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/internal/sysfs" + "github.com/tetratelabs/wazero/sys" +) + +// StdinFile is a fs.ModeDevice file for use implementing FdStdin. +// This is safer than reading from os.DevNull as it can never overrun +// operating system file descriptors. +type StdinFile struct { + noopStdinFile + io.Reader +} + +// Read implements the same method as documented on sys.File +func (f *StdinFile) Read(buf []byte) (int, experimentalsys.Errno) { + n, err := f.Reader.Read(buf) + return n, experimentalsys.UnwrapOSError(err) +} + +type writerFile struct { + noopStdoutFile + + w io.Writer +} + +// Write implements the same method as documented on sys.File +func (f *writerFile) Write(buf []byte) (int, experimentalsys.Errno) { + n, err := f.w.Write(buf) + return n, experimentalsys.UnwrapOSError(err) +} + +// noopStdinFile is a fs.ModeDevice file for use implementing FdStdin. This is +// safer than reading from os.DevNull as it can never overrun operating system +// file descriptors. +type noopStdinFile struct { + noopStdioFile +} + +// Read implements the same method as documented on sys.File +func (noopStdinFile) Read([]byte) (int, experimentalsys.Errno) { + return 0, 0 // Always EOF +} + +// Poll implements the same method as documented on fsapi.File +func (noopStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + if flag != fsapi.POLLIN { + return false, experimentalsys.ENOTSUP + } + return true, 0 // always ready to read nothing +} + +// noopStdoutFile is a fs.ModeDevice file for use implementing FdStdout and +// FdStderr. +type noopStdoutFile struct { + noopStdioFile +} + +// Write implements the same method as documented on sys.File +func (noopStdoutFile) Write(buf []byte) (int, experimentalsys.Errno) { + return len(buf), 0 // same as io.Discard +} + +type noopStdioFile struct { + experimentalsys.UnimplementedFile +} + +// Stat implements the same method as documented on sys.File +func (noopStdioFile) Stat() (sys.Stat_t, experimentalsys.Errno) { + return sys.Stat_t{Mode: modeDevice, Nlink: 1}, 0 +} + +// IsDir implements the same method as documented on sys.File +func (noopStdioFile) IsDir() (bool, experimentalsys.Errno) { + return false, 0 +} + +// Close implements the same method as documented on sys.File +func (noopStdioFile) Close() (errno experimentalsys.Errno) { return } + +// IsNonblock implements the same method as documented on fsapi.File +func (noopStdioFile) IsNonblock() bool { + return false +} + +// SetNonblock implements the same method as documented on fsapi.File +func (noopStdioFile) SetNonblock(bool) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Poll implements the same method as documented on fsapi.File +func (noopStdioFile) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} + +func stdinFileEntry(r io.Reader) (*FileEntry, error) { + if r == nil { + return &FileEntry{Name: "stdin", IsPreopen: true, File: &noopStdinFile{}}, nil + } else if f, ok := r.(*os.File); ok { + if f, err := sysfs.NewStdioFile(true, f); err != nil { + return nil, err + } else { + return &FileEntry{Name: "stdin", IsPreopen: true, File: f}, nil + } + } else { + return &FileEntry{Name: "stdin", IsPreopen: true, File: &StdinFile{Reader: r}}, nil + } +} + +func stdioWriterFileEntry(name string, w io.Writer) (*FileEntry, error) { + if w == nil { + return &FileEntry{Name: name, IsPreopen: true, File: &noopStdoutFile{}}, nil + } else if f, ok := w.(*os.File); ok { + if f, err := sysfs.NewStdioFile(false, f); err != nil { + return nil, err + } else { + return &FileEntry{Name: name, IsPreopen: true, File: f}, nil + } + } else { + return &FileEntry{Name: name, IsPreopen: true, File: &writerFile{w: w}}, nil + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sys/sys.go b/vendor/github.com/tetratelabs/wazero/internal/sys/sys.go new file mode 100644 index 00000000..12279ee4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sys/sys.go @@ -0,0 +1,228 @@ +package sys + +import ( + "errors" + "fmt" + "io" + "net" + "time" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/platform" + "github.com/tetratelabs/wazero/sys" +) + +// Context holds module-scoped system resources currently only supported by +// built-in host functions. +type Context struct { + args, environ [][]byte + argsSize, environSize uint32 + + walltime sys.Walltime + walltimeResolution sys.ClockResolution + nanotime sys.Nanotime + nanotimeResolution sys.ClockResolution + nanosleep sys.Nanosleep + osyield sys.Osyield + randSource io.Reader + fsc FSContext +} + +// Args is like os.Args and defaults to nil. +// +// Note: The count will never be more than math.MaxUint32. +// See wazero.ModuleConfig WithArgs +func (c *Context) Args() [][]byte { + return c.args +} + +// ArgsSize is the size to encode Args as Null-terminated strings. +// +// Note: To get the size without null-terminators, subtract the length of Args from this value. +// See wazero.ModuleConfig WithArgs +// See https://en.wikipedia.org/wiki/Null-terminated_string +func (c *Context) ArgsSize() uint32 { + return c.argsSize +} + +// Environ are "key=value" entries like os.Environ and default to nil. +// +// Note: The count will never be more than math.MaxUint32. +// See wazero.ModuleConfig WithEnv +func (c *Context) Environ() [][]byte { + return c.environ +} + +// EnvironSize is the size to encode Environ as Null-terminated strings. +// +// Note: To get the size without null-terminators, subtract the length of Environ from this value. +// See wazero.ModuleConfig WithEnv +// See https://en.wikipedia.org/wiki/Null-terminated_string +func (c *Context) EnvironSize() uint32 { + return c.environSize +} + +// Walltime implements platform.Walltime. +func (c *Context) Walltime() (sec int64, nsec int32) { + return c.walltime() +} + +// WalltimeNanos returns platform.Walltime as epoch nanoseconds. +func (c *Context) WalltimeNanos() int64 { + sec, nsec := c.Walltime() + return (sec * time.Second.Nanoseconds()) + int64(nsec) +} + +// WalltimeResolution returns resolution of Walltime. +func (c *Context) WalltimeResolution() sys.ClockResolution { + return c.walltimeResolution +} + +// Nanotime implements sys.Nanotime. +func (c *Context) Nanotime() int64 { + return c.nanotime() +} + +// NanotimeResolution returns resolution of Nanotime. +func (c *Context) NanotimeResolution() sys.ClockResolution { + return c.nanotimeResolution +} + +// Nanosleep implements sys.Nanosleep. +func (c *Context) Nanosleep(ns int64) { + c.nanosleep(ns) +} + +// Osyield implements sys.Osyield. +func (c *Context) Osyield() { + c.osyield() +} + +// FS returns the possibly empty (UnimplementedFS) file system context. +func (c *Context) FS() *FSContext { + return &c.fsc +} + +// RandSource is a source of random bytes and defaults to a deterministic source. +// see wazero.ModuleConfig WithRandSource +func (c *Context) RandSource() io.Reader { + return c.randSource +} + +// DefaultContext returns Context with no values set except a possible nil +// sys.FS. +// +// Note: This is only used for testing. +func DefaultContext(fs experimentalsys.FS) *Context { + if sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []experimentalsys.FS{fs}, []string{""}, nil); err != nil { + panic(fmt.Errorf("BUG: DefaultContext should never error: %w", err)) + } else { + return sysCtx + } +} + +// NewContext is a factory function which helps avoid needing to know defaults or exporting all fields. +// Note: max is exposed for testing. max is only used for env/args validation. +func NewContext( + max uint32, + args, environ [][]byte, + stdin io.Reader, + stdout, stderr io.Writer, + randSource io.Reader, + walltime sys.Walltime, + walltimeResolution sys.ClockResolution, + nanotime sys.Nanotime, + nanotimeResolution sys.ClockResolution, + nanosleep sys.Nanosleep, + osyield sys.Osyield, + fs []experimentalsys.FS, guestPaths []string, + tcpListeners []*net.TCPListener, +) (sysCtx *Context, err error) { + sysCtx = &Context{args: args, environ: environ} + + if sysCtx.argsSize, err = nullTerminatedByteCount(max, args); err != nil { + return nil, fmt.Errorf("args invalid: %w", err) + } + + if sysCtx.environSize, err = nullTerminatedByteCount(max, environ); err != nil { + return nil, fmt.Errorf("environ invalid: %w", err) + } + + if randSource == nil { + sysCtx.randSource = platform.NewFakeRandSource() + } else { + sysCtx.randSource = randSource + } + + if walltime != nil { + if clockResolutionInvalid(walltimeResolution) { + return nil, fmt.Errorf("invalid Walltime resolution: %d", walltimeResolution) + } + sysCtx.walltime = walltime + sysCtx.walltimeResolution = walltimeResolution + } else { + sysCtx.walltime = platform.NewFakeWalltime() + sysCtx.walltimeResolution = sys.ClockResolution(time.Microsecond.Nanoseconds()) + } + + if nanotime != nil { + if clockResolutionInvalid(nanotimeResolution) { + return nil, fmt.Errorf("invalid Nanotime resolution: %d", nanotimeResolution) + } + sysCtx.nanotime = nanotime + sysCtx.nanotimeResolution = nanotimeResolution + } else { + sysCtx.nanotime = platform.NewFakeNanotime() + sysCtx.nanotimeResolution = sys.ClockResolution(time.Nanosecond) + } + + if nanosleep != nil { + sysCtx.nanosleep = nanosleep + } else { + sysCtx.nanosleep = platform.FakeNanosleep + } + + if osyield != nil { + sysCtx.osyield = osyield + } else { + sysCtx.osyield = platform.FakeOsyield + } + + err = sysCtx.InitFSContext(stdin, stdout, stderr, fs, guestPaths, tcpListeners) + + return +} + +// clockResolutionInvalid returns true if the value stored isn't reasonable. +func clockResolutionInvalid(resolution sys.ClockResolution) bool { + return resolution < 1 || resolution > sys.ClockResolution(time.Hour.Nanoseconds()) +} + +// nullTerminatedByteCount ensures the count or Nul-terminated length of the elements doesn't exceed max, and that no +// element includes the nul character. +func nullTerminatedByteCount(max uint32, elements [][]byte) (uint32, error) { + count := uint32(len(elements)) + if count > max { + return 0, errors.New("exceeds maximum count") + } + + // The buffer size is the total size including null terminators. The null terminator count == value count, sum + // count with each value length. This works because in Go, the length of a string is the same as its byte count. + bufSize, maxSize := uint64(count), uint64(max) // uint64 to allow summing without overflow + for _, e := range elements { + // As this is null-terminated, We have to validate there are no null characters in the string. + for _, c := range e { + if c == 0 { + return 0, errors.New("contains NUL character") + } + } + + nextSize := bufSize + uint64(len(e)) + if nextSize > maxSize { + return 0, errors.New("exceeds maximum size") + } + bufSize = nextSize + + } + return uint32(bufSize), nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/adapter.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/adapter.go new file mode 100644 index 00000000..51a9a548 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/adapter.go @@ -0,0 +1,105 @@ +package sysfs + +import ( + "fmt" + "io/fs" + "path" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +type AdaptFS struct { + FS fs.FS +} + +// String implements fmt.Stringer +func (a *AdaptFS) String() string { + return fmt.Sprintf("%v", a.FS) +} + +// OpenFile implements the same method as documented on sys.FS +func (a *AdaptFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + return OpenFSFile(a.FS, cleanPath(path), flag, perm) +} + +// Lstat implements the same method as documented on sys.FS +func (a *AdaptFS) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + // At this time, we make the assumption sys.FS instances do not support + // symbolic links, therefore Lstat is the same as Stat. This is obviously + // not true, but until FS.FS has a solid story for how to handle symlinks, + // we are better off not making a decision that would be difficult to + // revert later on. + // + // For further discussions on the topic, see: + // https://github.com/golang/go/issues/49580 + return a.Stat(path) +} + +// Stat implements the same method as documented on sys.FS +func (a *AdaptFS) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { + f, errno := a.OpenFile(path, experimentalsys.O_RDONLY, 0) + if errno != 0 { + return sys.Stat_t{}, errno + } + defer f.Close() + return f.Stat() +} + +// Readlink implements the same method as documented on sys.FS +func (a *AdaptFS) Readlink(string) (string, experimentalsys.Errno) { + return "", experimentalsys.ENOSYS +} + +// Mkdir implements the same method as documented on sys.FS +func (a *AdaptFS) Mkdir(string, fs.FileMode) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Chmod implements the same method as documented on sys.FS +func (a *AdaptFS) Chmod(string, fs.FileMode) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Rename implements the same method as documented on sys.FS +func (a *AdaptFS) Rename(string, string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Rmdir implements the same method as documented on sys.FS +func (a *AdaptFS) Rmdir(string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Link implements the same method as documented on sys.FS +func (a *AdaptFS) Link(string, string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Symlink implements the same method as documented on sys.FS +func (a *AdaptFS) Symlink(string, string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Unlink implements the same method as documented on sys.FS +func (a *AdaptFS) Unlink(string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Utimens implements the same method as documented on sys.FS +func (a *AdaptFS) Utimens(string, int64, int64) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +func cleanPath(name string) string { + if len(name) == 0 { + return name + } + // fs.ValidFile cannot be rooted (start with '/') + cleaned := name + if name[0] == '/' { + cleaned = name[1:] + } + cleaned = path.Clean(cleaned) // e.g. "sub/." -> "sub" + return cleaned +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_linux.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_linux.go new file mode 100644 index 00000000..5a8a415c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_linux.go @@ -0,0 +1,14 @@ +//go:build linux && !tinygo + +package sysfs + +import ( + "os" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func datasync(f *os.File) sys.Errno { + return sys.UnwrapOSError(syscall.Fdatasync(int(f.Fd()))) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_tinygo.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_tinygo.go new file mode 100644 index 00000000..e58fc914 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_tinygo.go @@ -0,0 +1,13 @@ +//go:build tinygo + +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func datasync(f *os.File) sys.Errno { + return sys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_unsupported.go new file mode 100644 index 00000000..aa05719b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/datasync_unsupported.go @@ -0,0 +1,14 @@ +//go:build !linux + +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func datasync(f *os.File) sys.Errno { + // Attempt to sync everything, even if we only need to sync the data. + return fsync(f) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/dir.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dir.go new file mode 100644 index 00000000..f9823287 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dir.go @@ -0,0 +1,24 @@ +package sysfs + +import ( + "io" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func adjustReaddirErr(f sys.File, isClosed bool, err error) sys.Errno { + if err == io.EOF { + return 0 // e.g. Readdir on darwin returns io.EOF, but linux doesn't. + } else if errno := sys.UnwrapOSError(err); errno != 0 { + errno = dirError(f, isClosed, errno) + // Comply with errors allowed on sys.File Readdir + switch errno { + case sys.EINVAL: // os.File Readdir can return this + return sys.EBADF + case sys.ENOTDIR: // dirError can return this + return sys.EBADF + } + return errno + } + return 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs.go new file mode 100644 index 00000000..04384038 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs.go @@ -0,0 +1,99 @@ +package sysfs + +import ( + "io/fs" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/platform" + "github.com/tetratelabs/wazero/sys" +) + +func DirFS(dir string) experimentalsys.FS { + return &dirFS{ + dir: dir, + cleanedDir: ensureTrailingPathSeparator(dir), + } +} + +func ensureTrailingPathSeparator(dir string) string { + if !os.IsPathSeparator(dir[len(dir)-1]) { + return dir + string(os.PathSeparator) + } + return dir +} + +// dirFS is not exported because the input fields must be maintained together. +// This is likely why os.DirFS doesn't, either! +type dirFS struct { + experimentalsys.UnimplementedFS + + dir string + // cleanedDir is for easier OS-specific concatenation, as it always has + // a trailing path separator. + cleanedDir string +} + +// String implements fmt.Stringer +func (d *dirFS) String() string { + return d.dir +} + +// OpenFile implements the same method as documented on sys.FS +func (d *dirFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + return OpenOSFile(d.join(path), flag, perm) +} + +// Lstat implements the same method as documented on sys.FS +func (d *dirFS) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + return lstat(d.join(path)) +} + +// Stat implements the same method as documented on sys.FS +func (d *dirFS) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { + return stat(d.join(path)) +} + +// Mkdir implements the same method as documented on sys.FS +func (d *dirFS) Mkdir(path string, perm fs.FileMode) (errno experimentalsys.Errno) { + err := os.Mkdir(d.join(path), perm) + if errno = experimentalsys.UnwrapOSError(err); errno == experimentalsys.ENOTDIR { + errno = experimentalsys.ENOENT + } + return +} + +// Readlink implements the same method as documented on sys.FS +func (d *dirFS) Readlink(path string) (string, experimentalsys.Errno) { + // Note: do not use syscall.Readlink as that causes race on Windows. + // In any case, syscall.Readlink does almost the same logic as os.Readlink. + dst, err := os.Readlink(d.join(path)) + if err != nil { + return "", experimentalsys.UnwrapOSError(err) + } + return platform.ToPosixPath(dst), 0 +} + +// Rmdir implements the same method as documented on sys.FS +func (d *dirFS) Rmdir(path string) experimentalsys.Errno { + return rmdir(d.join(path)) +} + +// Utimens implements the same method as documented on sys.FS +func (d *dirFS) Utimens(path string, atim, mtim int64) experimentalsys.Errno { + return utimens(d.join(path), atim, mtim) +} + +func (d *dirFS) join(path string) string { + switch path { + case "", ".", "/": + if d.cleanedDir == "/" { + return "/" + } + // cleanedDir includes an unnecessary delimiter for the root path. + return d.cleanedDir[:len(d.cleanedDir)-1] + } + // TODO: Enforce similar to safefilepath.FromFS(path), but be careful as + // relative path inputs are allowed. e.g. dir or path == ../ + return d.cleanedDir + path +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_supported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_supported.go new file mode 100644 index 00000000..a949bd54 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_supported.go @@ -0,0 +1,48 @@ +//go:build !tinygo + +package sysfs + +import ( + "io/fs" + "os" + "path" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +// Link implements the same method as documented on sys.FS +func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno { + err := os.Link(d.join(oldName), d.join(newName)) + return experimentalsys.UnwrapOSError(err) +} + +// Unlink implements the same method as documented on sys.FS +func (d *dirFS) Unlink(path string) (err experimentalsys.Errno) { + return unlink(d.join(path)) +} + +// Rename implements the same method as documented on sys.FS +func (d *dirFS) Rename(from, to string) experimentalsys.Errno { + from, to = d.join(from), d.join(to) + return rename(from, to) +} + +// Chmod implements the same method as documented on sys.FS +func (d *dirFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { + err := os.Chmod(d.join(path), perm) + return experimentalsys.UnwrapOSError(err) +} + +// Symlink implements the same method as documented on sys.FS +func (d *dirFS) Symlink(oldName, link string) experimentalsys.Errno { + // Creating a symlink with an absolute path string fails with a "not permitted" error. + // https://github.com/WebAssembly/wasi-filesystem/blob/v0.2.0/path-resolution.md#symlinks + if path.IsAbs(oldName) { + return experimentalsys.EPERM + } + // Note: do not resolve `oldName` relative to this dirFS. The link result is always resolved + // when dereference the `link` on its usage (e.g. readlink, read, etc). + // https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409 + err := os.Symlink(oldName, d.join(link)) + return experimentalsys.UnwrapOSError(err) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_unsupported.go new file mode 100644 index 00000000..98b1a3b8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/dirfs_unsupported.go @@ -0,0 +1,34 @@ +//go:build tinygo + +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +// Link implements the same method as documented on sys.FS +func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Unlink implements the same method as documented on sys.FS +func (d *dirFS) Unlink(path string) (err experimentalsys.Errno) { + return experimentalsys.ENOSYS +} + +// Rename implements the same method as documented on sys.FS +func (d *dirFS) Rename(from, to string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Chmod implements the same method as documented on sys.FS +func (d *dirFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Symlink implements the same method as documented on sys.FS +func (d *dirFS) Symlink(oldName, link string) experimentalsys.Errno { + return experimentalsys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go new file mode 100644 index 00000000..1b6d5f3d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go @@ -0,0 +1,523 @@ +package sysfs + +import ( + "io" + "io/fs" + "os" + "time" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/sys" +) + +func NewStdioFile(stdin bool, f fs.File) (fsapi.File, error) { + // Return constant stat, which has fake times, but keep the underlying + // file mode. Fake times are needed to pass wasi-testsuite. + // https://github.com/WebAssembly/wasi-testsuite/blob/af57727/tests/rust/src/bin/fd_filestat_get.rs#L1-L19 + var mode fs.FileMode + if st, err := f.Stat(); err != nil { + return nil, err + } else { + mode = st.Mode() + } + var flag experimentalsys.Oflag + if stdin { + flag = experimentalsys.O_RDONLY + } else { + flag = experimentalsys.O_WRONLY + } + var file fsapi.File + if of, ok := f.(*os.File); ok { + // This is ok because functions that need path aren't used by stdioFile + file = newOsFile("", flag, 0, of) + } else { + file = &fsFile{file: f} + } + return &stdioFile{File: file, st: sys.Stat_t{Mode: mode, Nlink: 1}}, nil +} + +func OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (*os.File, experimentalsys.Errno) { + return openFile(path, flag, perm) +} + +func OpenOSFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + f, errno := OpenFile(path, flag, perm) + if errno != 0 { + return nil, errno + } + return newOsFile(path, flag, perm, f), 0 +} + +func OpenFSFile(fs fs.FS, path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + if flag&experimentalsys.O_DIRECTORY != 0 && flag&(experimentalsys.O_WRONLY|experimentalsys.O_RDWR) != 0 { + return nil, experimentalsys.EISDIR // invalid to open a directory writeable + } + f, err := fs.Open(path) + if errno := experimentalsys.UnwrapOSError(err); errno != 0 { + return nil, errno + } + // Don't return an os.File because the path is not absolute. osFile needs + // the path to be real and certain FS.File impls are subrooted. + return &fsFile{fs: fs, name: path, file: f}, 0 +} + +type stdioFile struct { + fsapi.File + st sys.Stat_t +} + +// SetAppend implements File.SetAppend +func (f *stdioFile) SetAppend(bool) experimentalsys.Errno { + // Ignore for stdio. + return 0 +} + +// IsAppend implements File.SetAppend +func (f *stdioFile) IsAppend() bool { + return true +} + +// Stat implements File.Stat +func (f *stdioFile) Stat() (sys.Stat_t, experimentalsys.Errno) { + return f.st, 0 +} + +// Close implements File.Close +func (f *stdioFile) Close() experimentalsys.Errno { + return 0 +} + +// fsFile is used for wrapped fs.File, like os.Stdin or any fs.File +// implementation. Notably, this does not have access to the full file path. +// so certain operations can't be supported, such as inode lookups on Windows. +type fsFile struct { + experimentalsys.UnimplementedFile + + // fs is the file-system that opened the file, or nil when wrapped for + // pre-opens like stdio. + fs fs.FS + + // name is what was used in fs for Open, so it may not be the actual path. + name string + + // file is always set, possibly an os.File like os.Stdin. + file fs.File + + // reopenDir is true if reopen should be called before Readdir. This flag + // is deferred until Readdir to prevent redundant rewinds. This could + // happen if Seek(0) was called twice, or if in Windows, Seek(0) was called + // before Readdir. + reopenDir bool + + // closed is true when closed was called. This ensures proper sys.EBADF + closed bool + + // cachedStat includes fields that won't change while a file is open. + cachedSt *cachedStat +} + +type cachedStat struct { + // dev is the same as sys.Stat_t Dev. + dev uint64 + + // dev is the same as sys.Stat_t Ino. + ino sys.Inode + + // isDir is sys.Stat_t Mode masked with fs.ModeDir + isDir bool +} + +// cachedStat returns the cacheable parts of sys.Stat_t or an error if they +// couldn't be retrieved. +func (f *fsFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno experimentalsys.Errno) { + if f.cachedSt == nil { + if _, errno = f.Stat(); errno != 0 { + return + } + } + return f.cachedSt.dev, f.cachedSt.ino, f.cachedSt.isDir, 0 +} + +// Dev implements the same method as documented on sys.File +func (f *fsFile) Dev() (uint64, experimentalsys.Errno) { + dev, _, _, errno := f.cachedStat() + return dev, errno +} + +// Ino implements the same method as documented on sys.File +func (f *fsFile) Ino() (sys.Inode, experimentalsys.Errno) { + _, ino, _, errno := f.cachedStat() + return ino, errno +} + +// IsDir implements the same method as documented on sys.File +func (f *fsFile) IsDir() (bool, experimentalsys.Errno) { + _, _, isDir, errno := f.cachedStat() + return isDir, errno +} + +// IsAppend implements the same method as documented on sys.File +func (f *fsFile) IsAppend() bool { + return false +} + +// SetAppend implements the same method as documented on sys.File +func (f *fsFile) SetAppend(bool) (errno experimentalsys.Errno) { + return fileError(f, f.closed, experimentalsys.ENOSYS) +} + +// Stat implements the same method as documented on sys.File +func (f *fsFile) Stat() (sys.Stat_t, experimentalsys.Errno) { + if f.closed { + return sys.Stat_t{}, experimentalsys.EBADF + } + + st, errno := statFile(f.file) + switch errno { + case 0: + f.cachedSt = &cachedStat{dev: st.Dev, ino: st.Ino, isDir: st.Mode&fs.ModeDir == fs.ModeDir} + case experimentalsys.EIO: + errno = experimentalsys.EBADF + } + return st, errno +} + +// Read implements the same method as documented on sys.File +func (f *fsFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { + if n, errno = read(f.file, buf); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Pread implements the same method as documented on sys.File +func (f *fsFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if ra, ok := f.file.(io.ReaderAt); ok { + if n, errno = pread(ra, buf, off); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return + } + + // See /RATIONALE.md "fd_pread: io.Seeker fallback when io.ReaderAt is not supported" + if rs, ok := f.file.(io.ReadSeeker); ok { + // Determine the current position in the file, as we need to revert it. + currentOffset, err := rs.Seek(0, io.SeekCurrent) + if err != nil { + return 0, fileError(f, f.closed, experimentalsys.UnwrapOSError(err)) + } + + // Put the read position back when complete. + defer func() { _, _ = rs.Seek(currentOffset, io.SeekStart) }() + + // If the current offset isn't in sync with this reader, move it. + if off != currentOffset { + if _, err = rs.Seek(off, io.SeekStart); err != nil { + return 0, fileError(f, f.closed, experimentalsys.UnwrapOSError(err)) + } + } + + n, err = rs.Read(buf) + if errno = experimentalsys.UnwrapOSError(err); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + } else { + errno = experimentalsys.ENOSYS // unsupported + } + return +} + +// Seek implements the same method as documented on sys.File +func (f *fsFile) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { + // If this is a directory, and we're attempting to seek to position zero, + // we have to re-open the file to ensure the directory state is reset. + var isDir bool + if offset == 0 && whence == io.SeekStart { + if isDir, errno = f.IsDir(); errno == 0 && isDir { + f.reopenDir = true + return + } + } + + if s, ok := f.file.(io.Seeker); ok { + if newOffset, errno = seek(s, offset, whence); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + } else { + errno = experimentalsys.ENOSYS // unsupported + } + return +} + +// Readdir implements the same method as documented on sys.File +// +// Notably, this uses readdirFile or fs.ReadDirFile if available. This does not +// return inodes on windows. +func (f *fsFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { + // Windows lets you Readdir after close, FS.File also may not implement + // close in a meaningful way. read our closed field to return consistent + // results. + if f.closed { + errno = experimentalsys.EBADF + return + } + + if f.reopenDir { // re-open the directory if needed. + f.reopenDir = false + if errno = adjustReaddirErr(f, f.closed, f.rewindDir()); errno != 0 { + return + } + } + + if of, ok := f.file.(readdirFile); ok { + // We can't use f.name here because it is the path up to the sys.FS, + // not necessarily the real path. For this reason, Windows may not be + // able to populate inodes. However, Darwin and Linux will. + if dirents, errno = readdir(of, "", n); errno != 0 { + errno = adjustReaddirErr(f, f.closed, errno) + } + return + } + + // Try with FS.ReadDirFile which is available on api.FS implementations + // like embed:FS. + if rdf, ok := f.file.(fs.ReadDirFile); ok { + entries, e := rdf.ReadDir(n) + if errno = adjustReaddirErr(f, f.closed, e); errno != 0 { + return + } + dirents = make([]experimentalsys.Dirent, 0, len(entries)) + for _, e := range entries { + // By default, we don't attempt to read inode data + dirents = append(dirents, experimentalsys.Dirent{Name: e.Name(), Type: e.Type()}) + } + } else { + errno = experimentalsys.EBADF // not a directory + } + return +} + +// Write implements the same method as documented on sys.File. +func (f *fsFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { + if w, ok := f.file.(io.Writer); ok { + if n, errno = write(w, buf); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + } else { + errno = experimentalsys.ENOSYS // unsupported + } + return +} + +// Pwrite implements the same method as documented on sys.File. +func (f *fsFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if wa, ok := f.file.(io.WriterAt); ok { + if n, errno = pwrite(wa, buf, off); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + } else { + errno = experimentalsys.ENOSYS // unsupported + } + return +} + +// Close implements the same method as documented on sys.File. +func (f *fsFile) Close() experimentalsys.Errno { + if f.closed { + return 0 + } + f.closed = true + return f.close() +} + +func (f *fsFile) close() experimentalsys.Errno { + return experimentalsys.UnwrapOSError(f.file.Close()) +} + +// IsNonblock implements the same method as documented on fsapi.File +func (f *fsFile) IsNonblock() bool { + return false +} + +// SetNonblock implements the same method as documented on fsapi.File +func (f *fsFile) SetNonblock(bool) experimentalsys.Errno { + return experimentalsys.ENOSYS +} + +// Poll implements the same method as documented on fsapi.File +func (f *fsFile) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} + +// dirError is used for commands that work against a directory, but not a file. +func dirError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { + if vErrno := validate(f, isClosed, false, true); vErrno != 0 { + return vErrno + } + return errno +} + +// fileError is used for commands that work against a file, but not a directory. +func fileError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { + if vErrno := validate(f, isClosed, true, false); vErrno != 0 { + return vErrno + } + return errno +} + +// validate is used to making syscalls which will fail. +func validate(f experimentalsys.File, isClosed, wantFile, wantDir bool) experimentalsys.Errno { + if isClosed { + return experimentalsys.EBADF + } + + isDir, errno := f.IsDir() + if errno != 0 { + return errno + } + + if wantFile && isDir { + return experimentalsys.EISDIR + } else if wantDir && !isDir { + return experimentalsys.ENOTDIR + } + return 0 +} + +func read(r io.Reader, buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length reads. + } + + n, err := r.Read(buf) + return n, experimentalsys.UnwrapOSError(err) +} + +func pread(ra io.ReaderAt, buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length reads. + } + + n, err := ra.ReadAt(buf, off) + return n, experimentalsys.UnwrapOSError(err) +} + +func seek(s io.Seeker, offset int64, whence int) (int64, experimentalsys.Errno) { + if uint(whence) > io.SeekEnd { + return 0, experimentalsys.EINVAL // negative or exceeds the largest valid whence + } + + newOffset, err := s.Seek(offset, whence) + return newOffset, experimentalsys.UnwrapOSError(err) +} + +func (f *fsFile) rewindDir() experimentalsys.Errno { + // Reopen the directory to rewind it. + file, err := f.fs.Open(f.name) + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + fi, err := file.Stat() + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + // Can't check if it's still the same file, + // but is it still a directory, at least? + if !fi.IsDir() { + return experimentalsys.ENOTDIR + } + // Only update f on success. + _ = f.file.Close() + f.file = file + return 0 +} + +// readdirFile allows masking the `Readdir` function on os.File. +type readdirFile interface { + Readdir(n int) ([]fs.FileInfo, error) +} + +// readdir uses readdirFile.Readdir, special casing windows when path !="". +func readdir(f readdirFile, path string, n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { + fis, e := f.Readdir(n) + if errno = experimentalsys.UnwrapOSError(e); errno != 0 { + return + } + + dirents = make([]experimentalsys.Dirent, 0, len(fis)) + + // linux/darwin won't have to fan out to lstat, but windows will. + var ino sys.Inode + for fi := range fis { + t := fis[fi] + // inoFromFileInfo is more efficient than sys.NewStat_t, as it gets the + // inode without allocating an instance and filling other fields. + if ino, errno = inoFromFileInfo(path, t); errno != 0 { + return + } + dirents = append(dirents, experimentalsys.Dirent{Name: t.Name(), Ino: ino, Type: t.Mode().Type()}) + } + return +} + +func write(w io.Writer, buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length writes. + } + + n, err := w.Write(buf) + return n, experimentalsys.UnwrapOSError(err) +} + +func pwrite(w io.WriterAt, buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // less overhead on zero-length writes. + } + + n, err := w.WriteAt(buf, off) + return n, experimentalsys.UnwrapOSError(err) +} + +func chtimes(path string, atim, mtim int64) (errno experimentalsys.Errno) { //nolint:unused + // When both inputs are omitted, there is nothing to change. + if atim == experimentalsys.UTIME_OMIT && mtim == experimentalsys.UTIME_OMIT { + return + } + + // UTIME_OMIT is expensive until progress is made in Go, as it requires a + // stat to read-back the value to re-apply. + // - https://github.com/golang/go/issues/32558. + // - https://go-review.googlesource.com/c/go/+/219638 (unmerged) + var st sys.Stat_t + if atim == experimentalsys.UTIME_OMIT || mtim == experimentalsys.UTIME_OMIT { + if st, errno = stat(path); errno != 0 { + return + } + } + + var atime, mtime time.Time + if atim == experimentalsys.UTIME_OMIT { + atime = epochNanosToTime(st.Atim) + mtime = epochNanosToTime(mtim) + } else if mtim == experimentalsys.UTIME_OMIT { + atime = epochNanosToTime(atim) + mtime = epochNanosToTime(st.Mtim) + } else { + atime = epochNanosToTime(atim) + mtime = epochNanosToTime(mtim) + } + return experimentalsys.UnwrapOSError(os.Chtimes(path, atime, mtime)) +} + +func epochNanosToTime(epochNanos int64) time.Time { //nolint:unused + seconds := epochNanos / 1e9 + nanos := epochNanos % 1e9 + return time.Unix(seconds, nanos) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unix.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unix.go new file mode 100644 index 00000000..f201e813 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unix.go @@ -0,0 +1,39 @@ +//go:build unix && !tinygo + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const ( + nonBlockingFileReadSupported = true + nonBlockingFileWriteSupported = true +) + +func rmdir(path string) sys.Errno { + err := syscall.Rmdir(path) + return sys.UnwrapOSError(err) +} + +// readFd exposes syscall.Read. +func readFd(fd uintptr, buf []byte) (int, sys.Errno) { + if len(buf) == 0 { + return 0, 0 // Short-circuit 0-len reads. + } + n, err := syscall.Read(int(fd), buf) + errno := sys.UnwrapOSError(err) + return n, errno +} + +// writeFd exposes syscall.Write. +func writeFd(fd uintptr, buf []byte) (int, sys.Errno) { + if len(buf) == 0 { + return 0, 0 // Short-circuit 0-len writes. + } + n, err := syscall.Write(int(fd), buf) + errno := sys.UnwrapOSError(err) + return n, errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unsupported.go new file mode 100644 index 00000000..a028b947 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_unsupported.go @@ -0,0 +1,28 @@ +//go:build !(unix || windows) || tinygo + +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const ( + nonBlockingFileReadSupported = false + nonBlockingFileWriteSupported = false +) + +func rmdir(path string) sys.Errno { + return sys.UnwrapOSError(os.Remove(path)) +} + +// readFd returns ENOSYS on unsupported platforms. +func readFd(fd uintptr, buf []byte) (int, sys.Errno) { + return -1, sys.ENOSYS +} + +// writeFd returns ENOSYS on unsupported platforms. +func writeFd(fd uintptr, buf []byte) (int, sys.Errno) { + return -1, sys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_windows.go new file mode 100644 index 00000000..37870ea3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file_windows.go @@ -0,0 +1,175 @@ +package sysfs + +import ( + "errors" + "syscall" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const ( + nonBlockingFileReadSupported = true + nonBlockingFileWriteSupported = false + + _ERROR_IO_INCOMPLETE = syscall.Errno(996) +) + +var kernel32 = syscall.NewLazyDLL("kernel32.dll") + +// procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe +var ( + // procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe + procPeekNamedPipe = kernel32.NewProc("PeekNamedPipe") + // procGetOverlappedResult is the syscall.LazyProc in kernel32 for GetOverlappedResult + procGetOverlappedResult = kernel32.NewProc("GetOverlappedResult") + // procCreateEventW is the syscall.LazyProc in kernel32 for CreateEventW + procCreateEventW = kernel32.NewProc("CreateEventW") +) + +// readFd returns ENOSYS on unsupported platforms. +// +// PeekNamedPipe: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe +// "GetFileType can assist in determining what device type the handle refers to. A console handle presents as FILE_TYPE_CHAR." +// https://learn.microsoft.com/en-us/windows/console/console-handles +func readFd(fd uintptr, buf []byte) (int, sys.Errno) { + handle := syscall.Handle(fd) + fileType, err := syscall.GetFileType(handle) + if err != nil { + return 0, sys.UnwrapOSError(err) + } + if fileType&syscall.FILE_TYPE_CHAR == 0 { + return -1, sys.ENOSYS + } + n, errno := peekNamedPipe(handle) + if errno == syscall.ERROR_BROKEN_PIPE { + return 0, 0 + } + if n == 0 { + return -1, sys.EAGAIN + } + un, err := syscall.Read(handle, buf[0:n]) + return un, sys.UnwrapOSError(err) +} + +func writeFd(fd uintptr, buf []byte) (int, sys.Errno) { + return -1, sys.ENOSYS +} + +func readSocket(h uintptr, buf []byte) (int, sys.Errno) { + // Poll the socket to ensure that we never perform a blocking/overlapped Read. + // + // When the socket is closed by the remote peer, wsaPoll will return n=1 and + // errno=0, and syscall.ReadFile will return n=0 and errno=0 -- which indicates + // io.EOF. + if n, errno := wsaPoll( + []pollFd{newPollFd(h, _POLLIN, 0)}, 0); !errors.Is(errno, sys.Errno(0)) { + return 0, sys.UnwrapOSError(errno) + } else if n <= 0 { + return 0, sys.EAGAIN + } + + // Properly use overlapped result. + // + // If hFile was opened with FILE_FLAG_OVERLAPPED, the following conditions are in effect: + // - The lpOverlapped parameter must point to a valid and unique OVERLAPPED structure, + // otherwise the function can incorrectly report that the read operation is complete. + // - The lpNumberOfBytesRead parameter should be set to NULL. Use the GetOverlappedResult + // function to get the actual number of bytes read. If the hFile parameter is associated + // with an I/O completion port, you can also get the number of bytes read by calling the + // GetQueuedCompletionStatus function. + // + // We are currently skipping checking if hFile was opened with FILE_FLAG_OVERLAPPED but using + // both lpOverlapped and lpNumberOfBytesRead. + var overlapped syscall.Overlapped + + // Create an event to wait on. + if hEvent, err := createEventW(nil, true, false, nil); err != 0 { + return 0, sys.UnwrapOSError(err) + } else { + overlapped.HEvent = syscall.Handle(hEvent) + } + + var done uint32 + errno := syscall.ReadFile(syscall.Handle(h), buf, &done, &overlapped) + if errors.Is(errno, syscall.ERROR_IO_PENDING) { + errno = syscall.CancelIo(syscall.Handle(h)) + if errno != nil { + return 0, sys.UnwrapOSError(errno) // This is a fatal error. CancelIo failed. + } + + done, errno = getOverlappedResult(syscall.Handle(h), &overlapped, true) // wait for I/O to complete(cancel or finish). Overwrite done and errno. + if errors.Is(errno, syscall.ERROR_OPERATION_ABORTED) { + return int(done), sys.EAGAIN // This is one of the expected behavior, I/O was cancelled(completed) before finished. + } + } + + return int(done), sys.UnwrapOSError(errno) +} + +func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) { + var done uint32 + var overlapped syscall.Overlapped + errno := syscall.WriteFile(syscall.Handle(fd), buf, &done, &overlapped) + if errors.Is(errno, syscall.ERROR_IO_PENDING) { + errno = syscall.EAGAIN + } + return int(done), sys.UnwrapOSError(errno) +} + +// peekNamedPipe partially exposes PeekNamedPipe from the Win32 API +// see https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe +func peekNamedPipe(handle syscall.Handle) (uint32, syscall.Errno) { + var totalBytesAvail uint32 + totalBytesPtr := unsafe.Pointer(&totalBytesAvail) + _, _, errno := syscall.SyscallN( + procPeekNamedPipe.Addr(), + uintptr(handle), // [in] HANDLE hNamedPipe, + 0, // [out, optional] LPVOID lpBuffer, + 0, // [in] DWORD nBufferSize, + 0, // [out, optional] LPDWORD lpBytesRead + uintptr(totalBytesPtr), // [out, optional] LPDWORD lpTotalBytesAvail, + 0) // [out, optional] LPDWORD lpBytesLeftThisMessage + return totalBytesAvail, errno +} + +func rmdir(path string) sys.Errno { + err := syscall.Rmdir(path) + return sys.UnwrapOSError(err) +} + +func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, wait bool) (uint32, syscall.Errno) { + var totalBytesAvail uint32 + var bwait uintptr + if wait { + bwait = 0xFFFFFFFF + } + totalBytesPtr := unsafe.Pointer(&totalBytesAvail) + _, _, errno := syscall.SyscallN( + procGetOverlappedResult.Addr(), + uintptr(handle), // [in] HANDLE hFile, + uintptr(unsafe.Pointer(overlapped)), // [in] LPOVERLAPPED lpOverlapped, + uintptr(totalBytesPtr), // [out] LPDWORD lpNumberOfBytesTransferred, + bwait) // [in] BOOL bWait + return totalBytesAvail, errno +} + +func createEventW(lpEventAttributes *syscall.SecurityAttributes, bManualReset bool, bInitialState bool, lpName *uint16) (uintptr, syscall.Errno) { + var manualReset uintptr + var initialState uintptr + if bManualReset { + manualReset = 1 + } + if bInitialState { + initialState = 1 + } + handle, _, errno := syscall.SyscallN( + procCreateEventW.Addr(), + uintptr(unsafe.Pointer(lpEventAttributes)), // [in] LPSECURITY_ATTRIBUTES lpEventAttributes, + manualReset, // [in] BOOL bManualReset, + initialState, // [in] BOOL bInitialState, + uintptr(unsafe.Pointer(lpName)), // [in, opt]LPCWSTR lpName, + ) + + return handle, errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens.go new file mode 100644 index 00000000..7f6b1109 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens.go @@ -0,0 +1,37 @@ +//go:build (linux || darwin) && !tinygo + +package sysfs + +import ( + "syscall" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func timesToPtr(times *[2]syscall.Timespec) unsafe.Pointer { //nolint:unused + if times != nil { + return unsafe.Pointer(×[0]) + } + return unsafe.Pointer(nil) +} + +func timesToTimespecs(atim int64, mtim int64) (times *[2]syscall.Timespec) { + // When both inputs are omitted, there is nothing to change. + if atim == sys.UTIME_OMIT && mtim == sys.UTIME_OMIT { + return + } + + times = &[2]syscall.Timespec{} + if atim == sys.UTIME_OMIT { + times[0] = syscall.Timespec{Nsec: _UTIME_OMIT} + times[1] = syscall.NsecToTimespec(mtim) + } else if mtim == sys.UTIME_OMIT { + times[0] = syscall.NsecToTimespec(atim) + times[1] = syscall.Timespec{Nsec: _UTIME_OMIT} + } else { + times[0] = syscall.NsecToTimespec(atim) + times[1] = syscall.NsecToTimespec(mtim) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.go new file mode 100644 index 00000000..88e4008f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.go @@ -0,0 +1,51 @@ +package sysfs + +import ( + "syscall" + _ "unsafe" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +const ( + _AT_FDCWD = -0x2 + _AT_SYMLINK_NOFOLLOW = 0x0020 + _UTIME_OMIT = -2 +) + +//go:noescape +//go:linkname utimensat syscall.utimensat +func utimensat(dirfd int, path string, times *[2]syscall.Timespec, flags int) error + +func utimens(path string, atim, mtim int64) experimentalsys.Errno { + times := timesToTimespecs(atim, mtim) + if times == nil { + return 0 + } + var flags int + return experimentalsys.UnwrapOSError(utimensat(_AT_FDCWD, path, times, flags)) +} + +func futimens(fd uintptr, atim, mtim int64) experimentalsys.Errno { + times := timesToTimespecs(atim, mtim) + if times == nil { + return 0 + } + _p0 := timesToPtr(times) + + // Warning: futimens only exists since High Sierra (10.13). + _, _, e1 := syscall_syscall6(libc_futimens_trampoline_addr, fd, uintptr(_p0), 0, 0, 0, 0) + return experimentalsys.UnwrapOSError(e1) +} + +// libc_futimens_trampoline_addr is the address of the +// `libc_futimens_trampoline` symbol, defined in `futimens_darwin.s`. +// +// We use this to invoke the syscall through syscall_syscall6 imported below. +var libc_futimens_trampoline_addr uintptr + +// Imports the futimens symbol from libc as `libc_futimens`. +// +// Note: CGO mechanisms are used in darwin regardless of the CGO_ENABLED value +// or the "cgo" build flag. See /RATIONALE.md for why. +//go:cgo_import_dynamic libc_futimens futimens "/usr/lib/libSystem.B.dylib" diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.s b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.s new file mode 100644 index 00000000..b86aecdf --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_darwin.s @@ -0,0 +1,8 @@ +// lifted from golang.org/x/sys unix +#include "textflag.h" + +TEXT libc_futimens_trampoline<>(SB), NOSPLIT, $0-0 + JMP libc_futimens(SB) + +GLOBL ·libc_futimens_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimens_trampoline_addr(SB)/8, $libc_futimens_trampoline<>(SB) diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_linux.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_linux.go new file mode 100644 index 00000000..db3b1b8b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_linux.go @@ -0,0 +1,49 @@ +//go:build !tinygo + +package sysfs + +import ( + "syscall" + "unsafe" + _ "unsafe" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +const ( + _AT_FDCWD = -0x64 + _UTIME_OMIT = (1 << 30) - 2 +) + +func utimens(path string, atim, mtim int64) experimentalsys.Errno { + times := timesToTimespecs(atim, mtim) + if times == nil { + return 0 + } + + var flags int + var _p0 *byte + _p0, err := syscall.BytePtrFromString(path) + if err == nil { + err = utimensat(_AT_FDCWD, uintptr(unsafe.Pointer(_p0)), times, flags) + } + return experimentalsys.UnwrapOSError(err) +} + +// On linux, implement futimens via utimensat with the NUL path. +func futimens(fd uintptr, atim, mtim int64) experimentalsys.Errno { + times := timesToTimespecs(atim, mtim) + if times == nil { + return 0 + } + return experimentalsys.UnwrapOSError(utimensat(int(fd), 0 /* NUL */, times, 0)) +} + +// utimensat is like syscall.utimensat special-cased to accept a NUL string for the path value. +func utimensat(dirfd int, strPtr uintptr, times *[2]syscall.Timespec, flags int) (err error) { + _, _, e1 := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(dirfd), strPtr, uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = e1 + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_unsupported.go new file mode 100644 index 00000000..69d56494 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_unsupported.go @@ -0,0 +1,18 @@ +//go:build (!windows && !linux && !darwin) || tinygo + +package sysfs + +import ( + "github.com/tetratelabs/wazero/experimental/sys" +) + +func utimens(path string, atim, mtim int64) sys.Errno { + return chtimes(path, atim, mtim) +} + +func futimens(fd uintptr, atim, mtim int64) error { + // Go exports syscall.Futimes, which is microsecond granularity, and + // WASI tests expect nanosecond. We don't yet have a way to invoke the + // futimens syscall portably. + return sys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_windows.go new file mode 100644 index 00000000..e0c89f30 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/futimens_windows.go @@ -0,0 +1,42 @@ +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func utimens(path string, atim, mtim int64) sys.Errno { + return chtimes(path, atim, mtim) +} + +func futimens(fd uintptr, atim, mtim int64) error { + // Per docs, zero isn't a valid timestamp as it cannot be differentiated + // from nil. In both cases, it is a marker like sys.UTIME_OMIT. + // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfiletime + a, w := timespecToFiletime(atim, mtim) + + if a == nil && w == nil { + return nil // both omitted, so nothing to change + } + + // Attempt to get the stat by handle, which works for normal files + h := syscall.Handle(fd) + + // Note: This returns ERROR_ACCESS_DENIED when the input is a directory. + return syscall.SetFileTime(h, nil, a, w) +} + +func timespecToFiletime(atim, mtim int64) (a, w *syscall.Filetime) { + a = timespecToFileTime(atim) + w = timespecToFileTime(mtim) + return +} + +func timespecToFileTime(tim int64) *syscall.Filetime { + if tim == sys.UTIME_OMIT { + return nil + } + ft := syscall.NsecToFiletime(tim) + return &ft +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino.go new file mode 100644 index 00000000..8344cd16 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino.go @@ -0,0 +1,22 @@ +//go:build !windows && !plan9 && !tinygo + +package sysfs + +import ( + "io/fs" + "syscall" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +func inoFromFileInfo(_ string, info fs.FileInfo) (sys.Inode, experimentalsys.Errno) { + switch v := info.Sys().(type) { + case *sys.Stat_t: + return v.Ino, 0 + case *syscall.Stat_t: + return v.Ino, 0 + default: + return 0, 0 + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_plan9.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_plan9.go new file mode 100644 index 00000000..9c669a47 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_plan9.go @@ -0,0 +1,15 @@ +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +func inoFromFileInfo(_ string, info fs.FileInfo) (sys.Inode, experimentalsys.Errno) { + if v, ok := info.Sys().(*sys.Stat_t); ok { + return v.Ino, 0 + } + return 0, 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_tinygo.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_tinygo.go new file mode 100644 index 00000000..2099231c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_tinygo.go @@ -0,0 +1,14 @@ +//go:build tinygo + +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +func inoFromFileInfo(_ string, info fs.FileInfo) (sys.Inode, experimentalsys.Errno) { + return 0, experimentalsys.ENOTSUP +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_windows.go new file mode 100644 index 00000000..d163b360 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/ino_windows.go @@ -0,0 +1,28 @@ +package sysfs + +import ( + "io/fs" + "path" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +// inoFromFileInfo uses stat to get the inode information of the file. +func inoFromFileInfo(dirPath string, info fs.FileInfo) (ino sys.Inode, errno experimentalsys.Errno) { + if v, ok := info.Sys().(*sys.Stat_t); ok { + return v.Ino, 0 + } + if dirPath == "" { + // This is a FS.File backed implementation which doesn't have access to + // the original file path. + return + } + // Ino is no not in Win32FileAttributeData + inoPath := path.Clean(path.Join(dirPath, info.Name())) + var st sys.Stat_t + if st, errno = lstat(inoPath); errno == 0 { + ino = st.Ino + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unix.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unix.go new file mode 100644 index 00000000..4477ee97 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unix.go @@ -0,0 +1,17 @@ +//go:build !windows && !plan9 && !tinygo + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func setNonblock(fd uintptr, enable bool) sys.Errno { + return sys.UnwrapOSError(syscall.SetNonblock(int(fd), enable)) +} + +func isNonblock(f *osFile) bool { + return f.flag&sys.O_NONBLOCK == sys.O_NONBLOCK +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unsupported.go new file mode 100644 index 00000000..3e141a7b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_unsupported.go @@ -0,0 +1,13 @@ +//go:build plan9 || tinygo + +package sysfs + +import "github.com/tetratelabs/wazero/experimental/sys" + +func setNonblock(fd uintptr, enable bool) sys.Errno { + return sys.ENOSYS +} + +func isNonblock(f *osFile) bool { + return false +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_windows.go new file mode 100644 index 00000000..eb38ea5a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/nonblock_windows.go @@ -0,0 +1,23 @@ +package sysfs + +import ( + "io/fs" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func setNonblock(fd uintptr, enable bool) sys.Errno { + // We invoke the syscall, but this is currently no-op. + return sys.UnwrapOSError(syscall.SetNonblock(syscall.Handle(fd), enable)) +} + +func isNonblock(f *osFile) bool { + // On Windows, we support non-blocking reads only on named pipes. + isValid := false + st, errno := f.Stat() + if errno == 0 { + isValid = st.Mode&fs.ModeNamedPipe != 0 + } + return isValid && f.flag&sys.O_NONBLOCK == sys.O_NONBLOCK +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/oflag.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/oflag.go new file mode 100644 index 00000000..be6d2c35 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/oflag.go @@ -0,0 +1,38 @@ +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// toOsOpenFlag converts the input to the flag parameter of os.OpenFile +func toOsOpenFlag(oflag sys.Oflag) (flag int) { + // First flags are exclusive + switch oflag & (sys.O_RDONLY | sys.O_RDWR | sys.O_WRONLY) { + case sys.O_RDONLY: + flag |= os.O_RDONLY + case sys.O_RDWR: + flag |= os.O_RDWR + case sys.O_WRONLY: + flag |= os.O_WRONLY + } + + // Run down the flags defined in the os package + if oflag&sys.O_APPEND != 0 { + flag |= os.O_APPEND + } + if oflag&sys.O_CREAT != 0 { + flag |= os.O_CREATE + } + if oflag&sys.O_EXCL != 0 { + flag |= os.O_EXCL + } + if oflag&sys.O_SYNC != 0 { + flag |= os.O_SYNC + } + if oflag&sys.O_TRUNC != 0 { + flag |= os.O_TRUNC + } + return withSyscallOflag(oflag, flag) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_darwin.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_darwin.go new file mode 100644 index 00000000..a4f54ca2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_darwin.go @@ -0,0 +1,26 @@ +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { + flag |= syscall.O_DIRECTORY + } + if oflag&sys.O_DSYNC != 0 { + flag |= syscall.O_DSYNC + } + if oflag&sys.O_NOFOLLOW != 0 { + flag |= syscall.O_NOFOLLOW + } + if oflag&sys.O_NONBLOCK != 0 { + flag |= syscall.O_NONBLOCK + } + // syscall.O_RSYNC not defined on darwin + return flag +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_freebsd.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_freebsd.go new file mode 100644 index 00000000..42adaa21 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_freebsd.go @@ -0,0 +1,24 @@ +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_NOFOLLOW | sys.O_NONBLOCK + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { + flag |= syscall.O_DIRECTORY + } + // syscall.O_DSYNC not defined on darwin + if oflag&sys.O_NOFOLLOW != 0 { + flag |= syscall.O_NOFOLLOW + } + if oflag&sys.O_NONBLOCK != 0 { + flag |= syscall.O_NONBLOCK + } + // syscall.O_RSYNC not defined on darwin + return flag +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_linux.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_linux.go new file mode 100644 index 00000000..3fe2bb6e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_linux.go @@ -0,0 +1,30 @@ +//go:build !tinygo + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK | sys.O_RSYNC + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { + flag |= syscall.O_DIRECTORY + } + if oflag&sys.O_DSYNC != 0 { + flag |= syscall.O_DSYNC + } + if oflag&sys.O_NOFOLLOW != 0 { + flag |= syscall.O_NOFOLLOW + } + if oflag&sys.O_NONBLOCK != 0 { + flag |= syscall.O_NONBLOCK + } + if oflag&sys.O_RSYNC != 0 { + flag |= syscall.O_RSYNC + } + return flag +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_notwindows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_notwindows.go new file mode 100644 index 00000000..670e3591 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_notwindows.go @@ -0,0 +1,20 @@ +//go:build !windows && !tinygo + +package sysfs + +import ( + "io/fs" + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// openFile is like os.OpenFile except it accepts a sys.Oflag and returns +// sys.Errno. A zero sys.Errno is success. +func openFile(path string, oflag sys.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { + f, err := os.OpenFile(path, toOsOpenFlag(oflag), perm) + // Note: This does not return a sys.File because sys.FS that returns + // one may want to hide the real OS path. For example, this is needed for + // pre-opens. + return f, sys.UnwrapOSError(err) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_sun.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_sun.go new file mode 100644 index 00000000..bdf7dd84 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_sun.go @@ -0,0 +1,31 @@ +//go:build illumos || solaris + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK | sys.O_RSYNC + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { + // See https://github.com/illumos/illumos-gate/blob/edd580643f2cf1434e252cd7779e83182ea84945/usr/src/uts/common/sys/fcntl.h#L90 + flag |= 0x1000000 + } + if oflag&sys.O_DSYNC != 0 { + flag |= syscall.O_DSYNC + } + if oflag&sys.O_NOFOLLOW != 0 { + flag |= syscall.O_NOFOLLOW + } + if oflag&sys.O_NONBLOCK != 0 { + flag |= syscall.O_NONBLOCK + } + if oflag&sys.O_RSYNC != 0 { + flag |= syscall.O_RSYNC + } + return flag +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_tinygo.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_tinygo.go new file mode 100644 index 00000000..ccf6847c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_tinygo.go @@ -0,0 +1,25 @@ +//go:build tinygo + +package sysfs + +import ( + "io/fs" + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.Oflag(0) + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + // O_DIRECTORY not defined + // O_DSYNC not defined + // O_NOFOLLOW not defined + // O_NONBLOCK not defined + // O_RSYNC not defined + return flag +} + +func openFile(path string, oflag sys.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { + return nil, sys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_unsupported.go new file mode 100644 index 00000000..9f7a6d08 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_unsupported.go @@ -0,0 +1,18 @@ +//go:build !darwin && !linux && !windows && !illumos && !solaris && !freebsd + +package sysfs + +import ( + "github.com/tetratelabs/wazero/experimental/sys" +) + +const supportedSyscallOflag = sys.Oflag(0) + +func withSyscallOflag(oflag sys.Oflag, flag int) int { + // O_DIRECTORY not defined + // O_DSYNC not defined + // O_NOFOLLOW not defined + // O_NONBLOCK not defined + // O_RSYNC not defined + return flag +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_windows.go new file mode 100644 index 00000000..717f8598 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/open_file_windows.go @@ -0,0 +1,161 @@ +package sysfs + +import ( + "io/fs" + "os" + "strings" + "syscall" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func openFile(path string, oflag sys.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { + isDir := oflag&sys.O_DIRECTORY > 0 + flag := toOsOpenFlag(oflag) + + // TODO: document why we are opening twice + fd, err := open(path, flag|syscall.O_CLOEXEC, uint32(perm)) + if err == nil { + return os.NewFile(uintptr(fd), path), 0 + } + + // TODO: Set FILE_SHARE_DELETE for directory as well. + f, err := os.OpenFile(path, flag, perm) + errno := sys.UnwrapOSError(err) + if errno == 0 { + return f, 0 + } + + switch errno { + case sys.EINVAL: + // WASI expects ENOTDIR for a file path with a trailing slash. + if strings.HasSuffix(path, "/") { + errno = sys.ENOTDIR + } + // To match expectations of WASI, e.g. TinyGo TestStatBadDir, return + // ENOENT, not ENOTDIR. + case sys.ENOTDIR: + errno = sys.ENOENT + case sys.ENOENT: + if isSymlink(path) { + // Either symlink or hard link not found. We change the returned + // errno depending on if it is symlink or not to have consistent + // behavior across OSes. + if isDir { + // Dangling symlink dir must raise ENOTDIR. + errno = sys.ENOTDIR + } else { + errno = sys.ELOOP + } + } + } + return f, errno +} + +const supportedSyscallOflag = sys.O_NONBLOCK + +// Map to synthetic values here https://github.com/golang/go/blob/go1.20/src/syscall/types_windows.go#L34-L48 +func withSyscallOflag(oflag sys.Oflag, flag int) int { + // O_DIRECTORY not defined in windows + // O_DSYNC not defined in windows + // O_NOFOLLOW not defined in windows + if oflag&sys.O_NONBLOCK != 0 { + flag |= syscall.O_NONBLOCK + } + // O_RSYNC not defined in windows + return flag +} + +func isSymlink(path string) bool { + if st, e := os.Lstat(path); e == nil && st.Mode()&os.ModeSymlink != 0 { + return true + } + return false +} + +// # Differences from syscall.Open +// +// This code is based on syscall.Open from the below link with some differences +// https://github.com/golang/go/blame/go1.20/src/syscall/syscall_windows.go#L308-L379 +// +// - syscall.O_CREAT doesn't imply syscall.GENERIC_WRITE as that breaks +// flag expectations in wasi. +// - add support for setting FILE_SHARE_DELETE. +func open(path string, mode int, perm uint32) (fd syscall.Handle, err error) { + if len(path) == 0 { + return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return syscall.InvalidHandle, err + } + var access uint32 + switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) { + case syscall.O_RDONLY: + access = syscall.GENERIC_READ + case syscall.O_WRONLY: + access = syscall.GENERIC_WRITE + case syscall.O_RDWR: + access = syscall.GENERIC_READ | syscall.GENERIC_WRITE + } + if mode&syscall.O_APPEND != 0 { + access &^= syscall.GENERIC_WRITE + access |= syscall.FILE_APPEND_DATA + } + sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE) + var sa *syscall.SecurityAttributes + if mode&syscall.O_CLOEXEC == 0 { + var _sa syscall.SecurityAttributes + _sa.Length = uint32(unsafe.Sizeof(sa)) + _sa.InheritHandle = 1 + sa = &_sa + } + var createmode uint32 + switch { + case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL): + createmode = syscall.CREATE_NEW + case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC): + createmode = syscall.CREATE_ALWAYS + case mode&syscall.O_CREAT == syscall.O_CREAT: + createmode = syscall.OPEN_ALWAYS + case mode&syscall.O_TRUNC == syscall.O_TRUNC: + createmode = syscall.TRUNCATE_EXISTING + default: + createmode = syscall.OPEN_EXISTING + } + var attrs uint32 = syscall.FILE_ATTRIBUTE_NORMAL + if perm&syscall.S_IWRITE == 0 { + attrs = syscall.FILE_ATTRIBUTE_READONLY + if createmode == syscall.CREATE_ALWAYS { + // We have been asked to create a read-only file. + // If the file already exists, the semantics of + // the Unix open system call is to preserve the + // existing permissions. If we pass CREATE_ALWAYS + // and FILE_ATTRIBUTE_READONLY to CreateFile, + // and the file already exists, CreateFile will + // change the file permissions. + // Avoid that to preserve the Unix semantics. + h, e := syscall.CreateFile(pathp, access, sharemode, sa, syscall.TRUNCATE_EXISTING, syscall.FILE_ATTRIBUTE_NORMAL, 0) + switch e { + case syscall.ERROR_FILE_NOT_FOUND, syscall.ERROR_PATH_NOT_FOUND: + // File does not exist. These are the same + // errors as Errno.Is checks for ErrNotExist. + // Carry on to create the file. + default: + // Success or some different error. + return h, e + } + } + } + + // This shouldn't be included before 1.20 to have consistent behavior. + // https://github.com/golang/go/commit/0f0aa5d8a6a0253627d58b3aa083b24a1091933f + if createmode == syscall.OPEN_EXISTING && access == syscall.GENERIC_READ { + // Necessary for opening directory handles. + attrs |= syscall.FILE_FLAG_BACKUP_SEMANTICS + } + + h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) + return h, e +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/osfile.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/osfile.go new file mode 100644 index 00000000..32d6ebb3 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/osfile.go @@ -0,0 +1,319 @@ +package sysfs + +import ( + "io" + "io/fs" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/sys" +) + +func newOsFile(path string, flag experimentalsys.Oflag, perm fs.FileMode, f *os.File) fsapi.File { + // On POSIX, if a file is removed from or added to the directory after the + // most recent call to opendir() or rewinddir(), whether a subsequent call + // to readdir() returns an entry for that file is unspecified. + // + // And Windows cannot read files added to a directory after it was opened. + // This was noticed in #1087 in zig tests. + // + // So there is no guarantee that files added after opendir() will be visible + // in readdir(). Since we want those files to be visible, we need to + // reopendir() to get the new state of the directory before readdir(). + return &osFile{path: path, flag: flag, perm: perm, reopenDir: true, file: f, fd: f.Fd()} +} + +// osFile is a file opened with this package, and uses os.File or syscalls to +// implement api.File. +type osFile struct { + path string + flag experimentalsys.Oflag + perm fs.FileMode + file *os.File + fd uintptr + + // reopenDir is true if reopen should be called before Readdir. This flag + // is deferred until Readdir to prevent redundant rewinds. This could + // happen if Seek(0) was called twice, or if in Windows, Seek(0) was called + // before Readdir. + reopenDir bool + + // closed is true when closed was called. This ensures proper sys.EBADF + closed bool + + // cachedStat includes fields that won't change while a file is open. + cachedSt *cachedStat +} + +// cachedStat returns the cacheable parts of sys.Stat_t or an error if they +// couldn't be retrieved. +func (f *osFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno experimentalsys.Errno) { + if f.cachedSt == nil { + if _, errno = f.Stat(); errno != 0 { + return + } + } + return f.cachedSt.dev, f.cachedSt.ino, f.cachedSt.isDir, 0 +} + +// Dev implements the same method as documented on sys.File +func (f *osFile) Dev() (uint64, experimentalsys.Errno) { + dev, _, _, errno := f.cachedStat() + return dev, errno +} + +// Ino implements the same method as documented on sys.File +func (f *osFile) Ino() (sys.Inode, experimentalsys.Errno) { + _, ino, _, errno := f.cachedStat() + return ino, errno +} + +// IsDir implements the same method as documented on sys.File +func (f *osFile) IsDir() (bool, experimentalsys.Errno) { + _, _, isDir, errno := f.cachedStat() + return isDir, errno +} + +// IsAppend implements File.IsAppend +func (f *osFile) IsAppend() bool { + return f.flag&experimentalsys.O_APPEND == experimentalsys.O_APPEND +} + +// SetAppend implements the same method as documented on sys.File +func (f *osFile) SetAppend(enable bool) (errno experimentalsys.Errno) { + if enable { + f.flag |= experimentalsys.O_APPEND + } else { + f.flag &= ^experimentalsys.O_APPEND + } + + // appendMode cannot be changed later, so we have to re-open the file + // https://github.com/golang/go/blob/go1.23/src/os/file_unix.go#L60 + return fileError(f, f.closed, f.reopen()) +} + +func (f *osFile) reopen() (errno experimentalsys.Errno) { + var ( + isDir bool + offset int64 + err error + ) + + isDir, errno = f.IsDir() + if errno != 0 { + return errno + } + + if !isDir { + offset, err = f.file.Seek(0, io.SeekCurrent) + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + } + + // Clear any create or trunc flag, as we are re-opening, not re-creating. + flag := f.flag &^ (experimentalsys.O_CREAT | experimentalsys.O_TRUNC) + file, errno := OpenFile(f.path, flag, f.perm) + if errno != 0 { + return errno + } + errno = f.checkSameFile(file) + if errno != 0 { + return errno + } + + if !isDir { + _, err = file.Seek(offset, io.SeekStart) + if err != nil { + _ = file.Close() + return experimentalsys.UnwrapOSError(err) + } + } + + // Only update f on success. + _ = f.file.Close() + f.file = file + f.fd = file.Fd() + return 0 +} + +func (f *osFile) checkSameFile(osf *os.File) experimentalsys.Errno { + fi1, err := f.file.Stat() + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + fi2, err := osf.Stat() + if err != nil { + return experimentalsys.UnwrapOSError(err) + } + if os.SameFile(fi1, fi2) { + return 0 + } + return experimentalsys.ENOENT +} + +// IsNonblock implements the same method as documented on fsapi.File +func (f *osFile) IsNonblock() bool { + return isNonblock(f) +} + +// SetNonblock implements the same method as documented on fsapi.File +func (f *osFile) SetNonblock(enable bool) (errno experimentalsys.Errno) { + if enable { + f.flag |= experimentalsys.O_NONBLOCK + } else { + f.flag &= ^experimentalsys.O_NONBLOCK + } + if errno = setNonblock(f.fd, enable); errno != 0 { + return fileError(f, f.closed, errno) + } + return 0 +} + +// Stat implements the same method as documented on sys.File +func (f *osFile) Stat() (sys.Stat_t, experimentalsys.Errno) { + if f.closed { + return sys.Stat_t{}, experimentalsys.EBADF + } + + st, errno := statFile(f.file) + switch errno { + case 0: + f.cachedSt = &cachedStat{dev: st.Dev, ino: st.Ino, isDir: st.Mode&fs.ModeDir == fs.ModeDir} + case experimentalsys.EIO: + errno = experimentalsys.EBADF + } + return st, errno +} + +// Read implements the same method as documented on sys.File +func (f *osFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // Short-circuit 0-len reads. + } + if nonBlockingFileReadSupported && f.IsNonblock() { + n, errno = readFd(f.fd, buf) + } else { + n, errno = read(f.file, buf) + } + if errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Pread implements the same method as documented on sys.File +func (f *osFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if n, errno = pread(f.file, buf, off); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Seek implements the same method as documented on sys.File +func (f *osFile) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { + if newOffset, errno = seek(f.file, offset, whence); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + + // If the error was trying to rewind a directory, re-open it. Notably, + // seeking to zero on a directory doesn't work on Windows with Go 1.19. + if errno == experimentalsys.EISDIR && offset == 0 && whence == io.SeekStart { + errno = 0 + f.reopenDir = true + } + } + return +} + +// Poll implements the same method as documented on fsapi.File +func (f *osFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + return poll(f.fd, flag, timeoutMillis) +} + +// Readdir implements File.Readdir. Notably, this uses "Readdir", not +// "ReadDir", from os.File. +func (f *osFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { + if f.reopenDir { // re-open the directory if needed. + f.reopenDir = false + if errno = adjustReaddirErr(f, f.closed, f.reopen()); errno != 0 { + return + } + } + + if dirents, errno = readdir(f.file, f.path, n); errno != 0 { + errno = adjustReaddirErr(f, f.closed, errno) + } + return +} + +// Write implements the same method as documented on sys.File +func (f *osFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // Short-circuit 0-len writes. + } + if nonBlockingFileWriteSupported && f.IsNonblock() { + n, errno = writeFd(f.fd, buf) + } else if n, errno = write(f.file, buf); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Pwrite implements the same method as documented on sys.File +func (f *osFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) { + if n, errno = pwrite(f.file, buf, off); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Truncate implements the same method as documented on sys.File +func (f *osFile) Truncate(size int64) (errno experimentalsys.Errno) { + if size < 0 { + return experimentalsys.EINVAL + } + if errno = experimentalsys.UnwrapOSError(f.file.Truncate(size)); errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Sync implements the same method as documented on sys.File +func (f *osFile) Sync() experimentalsys.Errno { + return fsync(f.file) +} + +// Datasync implements the same method as documented on sys.File +func (f *osFile) Datasync() experimentalsys.Errno { + return datasync(f.file) +} + +// Utimens implements the same method as documented on sys.File +func (f *osFile) Utimens(atim, mtim int64) experimentalsys.Errno { + if f.closed { + return experimentalsys.EBADF + } + + err := futimens(f.fd, atim, mtim) + return experimentalsys.UnwrapOSError(err) +} + +// Close implements the same method as documented on sys.File +func (f *osFile) Close() experimentalsys.Errno { + if f.closed { + return 0 + } + f.closed = true + return f.close() +} + +func (f *osFile) close() experimentalsys.Errno { + return experimentalsys.UnwrapOSError(f.file.Close()) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll.go new file mode 100644 index 00000000..a2e1103e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll.go @@ -0,0 +1,18 @@ +//go:build windows || (linux && !tinygo) || darwin + +package sysfs + +import ( + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" +) + +// poll implements `Poll` as documented on sys.File via a file descriptor. +func poll(fd uintptr, flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno sys.Errno) { + if flag != fsapi.POLLIN { + return false, sys.ENOTSUP + } + fds := []pollFd{newPollFd(fd, _POLLIN, 0)} + count, errno := _poll(fds, timeoutMillis) + return count > 0, errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.go new file mode 100644 index 00000000..1f7f8909 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.go @@ -0,0 +1,55 @@ +package sysfs + +import ( + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// pollFd is the struct to query for file descriptor events using poll. +type pollFd struct { + // fd is the file descriptor. + fd int32 + // events is a bitmap containing the requested events. + events int16 + // revents is a bitmap containing the returned events. + revents int16 +} + +// newPollFd is a constructor for pollFd that abstracts the platform-specific type of file descriptors. +func newPollFd(fd uintptr, events, revents int16) pollFd { + return pollFd{fd: int32(fd), events: events, revents: revents} +} + +// _POLLIN subscribes a notification when any readable data is available. +const _POLLIN = 0x0001 + +// _poll implements poll on Darwin via the corresponding libc function. +func _poll(fds []pollFd, timeoutMillis int32) (n int, errno sys.Errno) { + var fdptr *pollFd + nfds := len(fds) + if nfds > 0 { + fdptr = &fds[0] + } + n1, _, err := syscall_syscall6( + libc_poll_trampoline_addr, + uintptr(unsafe.Pointer(fdptr)), + uintptr(nfds), + uintptr(int(timeoutMillis)), + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil))) + return int(n1), sys.UnwrapOSError(err) +} + +// libc_poll_trampoline_addr is the address of the +// `libc_poll_trampoline` symbol, defined in `poll_darwin.s`. +// +// We use this to invoke the syscall through syscall_syscall6 imported below. +var libc_poll_trampoline_addr uintptr + +// Imports the select symbol from libc as `libc_poll`. +// +// Note: CGO mechanisms are used in darwin regardless of the CGO_ENABLED value +// or the "cgo" build flag. See /RATIONALE.md for why. +//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.s b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.s new file mode 100644 index 00000000..e04fca58 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_darwin.s @@ -0,0 +1,8 @@ +// lifted from golang.org/x/sys unix +#include "textflag.h" + +TEXT libc_poll_trampoline<>(SB), NOSPLIT, $0-0 + JMP libc_poll(SB) + +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_linux.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_linux.go new file mode 100644 index 00000000..49bf4fd0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_linux.go @@ -0,0 +1,59 @@ +//go:build !tinygo + +package sysfs + +import ( + "syscall" + "time" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// pollFd is the struct to query for file descriptor events using poll. +type pollFd struct { + // fd is the file descriptor. + fd int32 + // events is a bitmap containing the requested events. + events int16 + // revents is a bitmap containing the returned events. + revents int16 +} + +// newPollFd is a constructor for pollFd that abstracts the platform-specific type of file descriptors. +func newPollFd(fd uintptr, events, revents int16) pollFd { + return pollFd{fd: int32(fd), events: events, revents: revents} +} + +// _POLLIN subscribes a notification when any readable data is available. +const _POLLIN = 0x0001 + +// _poll implements poll on Linux via ppoll. +func _poll(fds []pollFd, timeoutMillis int32) (n int, errno sys.Errno) { + var ts syscall.Timespec + if timeoutMillis >= 0 { + ts = syscall.NsecToTimespec(int64(time.Duration(timeoutMillis) * time.Millisecond)) + } + return ppoll(fds, &ts) +} + +// ppoll is a poll variant that allows to subscribe to a mask of signals. +// However, we do not need such mask, so the corresponding argument is always nil. +func ppoll(fds []pollFd, timespec *syscall.Timespec) (n int, err sys.Errno) { + var fdptr *pollFd + nfd := len(fds) + if nfd != 0 { + fdptr = &fds[0] + } + + n1, _, errno := syscall.Syscall6( + uintptr(syscall.SYS_PPOLL), + uintptr(unsafe.Pointer(fdptr)), + uintptr(nfd), + uintptr(unsafe.Pointer(timespec)), + uintptr(unsafe.Pointer(nil)), // sigmask is currently always ignored + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil))) + + return int(n1), sys.UnwrapOSError(errno) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_unsupported.go new file mode 100644 index 00000000..2301a067 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_unsupported.go @@ -0,0 +1,13 @@ +//go:build !(linux || darwin || windows) || tinygo + +package sysfs + +import ( + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" +) + +// poll implements `Poll` as documented on fsapi.File via a file descriptor. +func poll(uintptr, fsapi.Pflag, int32) (bool, sys.Errno) { + return false, sys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_windows.go new file mode 100644 index 00000000..82c8b2ba --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/poll_windows.go @@ -0,0 +1,224 @@ +package sysfs + +import ( + "syscall" + "time" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +var ( + procWSAPoll = modws2_32.NewProc("WSAPoll") + procGetNamedPipeInfo = kernel32.NewProc("GetNamedPipeInfo") +) + +const ( + // _POLLRDNORM subscribes to normal data for read. + _POLLRDNORM = 0x0100 + // _POLLRDBAND subscribes to priority band (out-of-band) data for read. + _POLLRDBAND = 0x0200 + // _POLLIN subscribes a notification when any readable data is available. + _POLLIN = (_POLLRDNORM | _POLLRDBAND) +) + +// pollFd is the struct to query for file descriptor events using poll. +type pollFd struct { + // fd is the file descriptor. + fd uintptr + // events is a bitmap containing the requested events. + events int16 + // revents is a bitmap containing the returned events. + revents int16 +} + +// newPollFd is a constructor for pollFd that abstracts the platform-specific type of file descriptors. +func newPollFd(fd uintptr, events, revents int16) pollFd { + return pollFd{fd: fd, events: events, revents: revents} +} + +// pollInterval is the interval between each calls to peekNamedPipe in selectAllHandles +const pollInterval = 100 * time.Millisecond + +// _poll implements poll on Windows, for a subset of cases. +// +// fds may contain any number of file handles, but regular files and pipes are only processed for _POLLIN. +// Stdin is a pipe, thus it is checked for readiness when present. Pipes are checked using PeekNamedPipe. +// Regular files always immediately reported as ready, regardless their actual state and timeouts. +// +// If n==0 it will wait for the given timeout duration, but it will return sys.ENOSYS if timeout is nil, +// i.e. it won't block indefinitely. The given ctx is used to allow for cancellation, +// and it is currently used only in tests. +// +// The implementation actually polls every 100 milliseconds (pollInterval) until it reaches the +// given timeout (in millis). +// +// The duration may be negative, in which case it will wait indefinitely. The given ctx is +// used to allow for cancellation, and it is currently used only in tests. +func _poll(fds []pollFd, timeoutMillis int32) (n int, errno sys.Errno) { + if fds == nil { + return -1, sys.ENOSYS + } + + regular, pipes, sockets, errno := partionByFtype(fds) + nregular := len(regular) + if errno != 0 { + return -1, errno + } + + // Ticker that emits at every pollInterval. + tick := time.NewTicker(pollInterval) + tickCh := tick.C + defer tick.Stop() + + // Timer that expires after the given duration. + // Initialize afterCh as nil: the select below will wait forever. + var afterCh <-chan time.Time + if timeoutMillis >= 0 { + // If duration is not nil, instantiate the timer. + after := time.NewTimer(time.Duration(timeoutMillis) * time.Millisecond) + defer after.Stop() + afterCh = after.C + } + + npipes, nsockets, errno := peekAll(pipes, sockets) + if errno != 0 { + return -1, errno + } + count := nregular + npipes + nsockets + if count > 0 { + return count, 0 + } + + for { + select { + case <-afterCh: + return 0, 0 + case <-tickCh: + npipes, nsockets, errno := peekAll(pipes, sockets) + if errno != 0 { + return -1, errno + } + count = nregular + npipes + nsockets + if count > 0 { + return count, 0 + } + } + } +} + +func peekAll(pipes, sockets []pollFd) (npipes, nsockets int, errno sys.Errno) { + npipes, errno = peekPipes(pipes) + if errno != 0 { + return + } + + // Invoke wsaPoll with a 0-timeout to avoid blocking. + // Timeouts are handled in pollWithContext instead. + nsockets, errno = wsaPoll(sockets, 0) + if errno != 0 { + return + } + + count := npipes + nsockets + if count > 0 { + return + } + + return +} + +func peekPipes(fds []pollFd) (n int, errno sys.Errno) { + for _, fd := range fds { + bytes, errno := peekNamedPipe(syscall.Handle(fd.fd)) + if errno != 0 { + return -1, sys.UnwrapOSError(errno) + } + if bytes > 0 { + n++ + } + } + return +} + +// wsaPoll is the WSAPoll function from winsock2. +// +// See https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll +func wsaPoll(fds []pollFd, timeout int) (n int, errno sys.Errno) { + if len(fds) > 0 { + sockptr := &fds[0] + ns, _, e := syscall.SyscallN( + procWSAPoll.Addr(), + uintptr(unsafe.Pointer(sockptr)), + uintptr(len(fds)), + uintptr(timeout)) + if e != 0 { + return -1, sys.UnwrapOSError(e) + } + n = int(ns) + } + return +} + +// ftype is a type of file that can be handled by poll. +type ftype uint8 + +const ( + ftype_regular ftype = iota + ftype_pipe + ftype_socket +) + +// partionByFtype checks the type of each fd in fds and returns 3 distinct partitions +// for regular files, named pipes and sockets. +func partionByFtype(fds []pollFd) (regular, pipe, socket []pollFd, errno sys.Errno) { + for _, pfd := range fds { + t, errno := ftypeOf(pfd.fd) + if errno != 0 { + return nil, nil, nil, errno + } + switch t { + case ftype_regular: + regular = append(regular, pfd) + case ftype_pipe: + pipe = append(pipe, pfd) + case ftype_socket: + socket = append(socket, pfd) + } + } + return +} + +// ftypeOf checks the type of fd and return the corresponding ftype. +func ftypeOf(fd uintptr) (ftype, sys.Errno) { + h := syscall.Handle(fd) + t, err := syscall.GetFileType(h) + if err != nil { + return 0, sys.UnwrapOSError(err) + } + switch t { + case syscall.FILE_TYPE_CHAR, syscall.FILE_TYPE_DISK: + return ftype_regular, 0 + case syscall.FILE_TYPE_PIPE: + if isSocket(h) { + return ftype_socket, 0 + } else { + return ftype_pipe, 0 + } + default: + return ftype_regular, 0 + } +} + +// isSocket returns true if the given file handle +// is a pipe. +func isSocket(fd syscall.Handle) bool { + r, _, errno := syscall.SyscallN( + procGetNamedPipeInfo.Addr(), + uintptr(fd), + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil)), + uintptr(unsafe.Pointer(nil))) + return r == 0 || errno != 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/readfs.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/readfs.go new file mode 100644 index 00000000..59e331a2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/readfs.go @@ -0,0 +1,117 @@ +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +type ReadFS struct { + experimentalsys.FS +} + +// OpenFile implements the same method as documented on sys.FS +func (r *ReadFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + // Mask the mutually exclusive bits as they determine write mode. + switch flag & (experimentalsys.O_RDONLY | experimentalsys.O_WRONLY | experimentalsys.O_RDWR) { + case experimentalsys.O_WRONLY, experimentalsys.O_RDWR: + // Return the correct error if a directory was opened for write. + if flag&experimentalsys.O_DIRECTORY != 0 { + return nil, experimentalsys.EISDIR + } + return nil, experimentalsys.ENOSYS + default: // sys.O_RDONLY (integer zero) so we are ok! + } + + f, errno := r.FS.OpenFile(path, flag, perm) + if errno != 0 { + return nil, errno + } + return &readFile{f}, 0 +} + +// Mkdir implements the same method as documented on sys.FS +func (r *ReadFS) Mkdir(path string, perm fs.FileMode) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Chmod implements the same method as documented on sys.FS +func (r *ReadFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Rename implements the same method as documented on sys.FS +func (r *ReadFS) Rename(from, to string) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Rmdir implements the same method as documented on sys.FS +func (r *ReadFS) Rmdir(path string) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Link implements the same method as documented on sys.FS +func (r *ReadFS) Link(_, _ string) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Symlink implements the same method as documented on sys.FS +func (r *ReadFS) Symlink(_, _ string) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Unlink implements the same method as documented on sys.FS +func (r *ReadFS) Unlink(path string) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// Utimens implements the same method as documented on sys.FS +func (r *ReadFS) Utimens(path string, atim, mtim int64) experimentalsys.Errno { + return experimentalsys.EROFS +} + +// compile-time check to ensure readFile implements api.File. +var _ experimentalsys.File = (*readFile)(nil) + +type readFile struct { + experimentalsys.File +} + +// Write implements the same method as documented on sys.File. +func (r *readFile) Write([]byte) (int, experimentalsys.Errno) { + return 0, r.writeErr() +} + +// Pwrite implements the same method as documented on sys.File. +func (r *readFile) Pwrite([]byte, int64) (n int, errno experimentalsys.Errno) { + return 0, r.writeErr() +} + +// Truncate implements the same method as documented on sys.File. +func (r *readFile) Truncate(int64) experimentalsys.Errno { + return r.writeErr() +} + +// Sync implements the same method as documented on sys.File. +func (r *readFile) Sync() experimentalsys.Errno { + return experimentalsys.EBADF +} + +// Datasync implements the same method as documented on sys.File. +func (r *readFile) Datasync() experimentalsys.Errno { + return experimentalsys.EBADF +} + +// Utimens implements the same method as documented on sys.File. +func (r *readFile) Utimens(int64, int64) experimentalsys.Errno { + return experimentalsys.EBADF +} + +func (r *readFile) writeErr() experimentalsys.Errno { + if isDir, errno := r.IsDir(); errno != 0 { + return errno + } else if isDir { + return experimentalsys.EISDIR + } + return experimentalsys.EBADF +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename.go new file mode 100644 index 00000000..37c53571 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename.go @@ -0,0 +1,16 @@ +//go:build !windows && !plan9 && !tinygo + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func rename(from, to string) sys.Errno { + if from == to { + return 0 + } + return sys.UnwrapOSError(syscall.Rename(from, to)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_plan9.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_plan9.go new file mode 100644 index 00000000..474cc759 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_plan9.go @@ -0,0 +1,14 @@ +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func rename(from, to string) sys.Errno { + if from == to { + return 0 + } + return sys.UnwrapOSError(os.Rename(from, to)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go new file mode 100644 index 00000000..5e810223 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go @@ -0,0 +1,55 @@ +package sysfs + +import ( + "os" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func rename(from, to string) sys.Errno { + if from == to { + return 0 + } + + var fromIsDir, toIsDir bool + if fromStat, errno := stat(from); errno != 0 { + return errno // failed to stat from + } else { + fromIsDir = fromStat.Mode.IsDir() + } + if toStat, errno := stat(to); errno == sys.ENOENT { + return syscallRename(from, to) // file or dir to not-exist is ok + } else if errno != 0 { + return errno // failed to stat to + } else { + toIsDir = toStat.Mode.IsDir() + } + + // Now, handle known cases + switch { + case !fromIsDir && toIsDir: // file to dir + return sys.EISDIR + case !fromIsDir && !toIsDir: // file to file + // Use os.Rename instead of syscall.Rename to overwrite a file. + // This uses MoveFileEx instead of MoveFile (used by syscall.Rename). + return sys.UnwrapOSError(os.Rename(from, to)) + case fromIsDir && !toIsDir: // dir to file + return sys.ENOTDIR + default: // dir to dir + + // We can't tell if a directory is empty or not, via stat information. + // Reading the directory is expensive, as it can buffer large amounts + // of data on fail. Instead, speculatively try to remove the directory. + // This is only one syscall and won't buffer anything. + if errno := rmdir(to); errno == 0 || errno == sys.ENOENT { + return syscallRename(from, to) + } else { + return errno + } + } +} + +func syscallRename(from string, to string) sys.Errno { + return sys.UnwrapOSError(syscall.Rename(from, to)) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock.go new file mode 100644 index 00000000..ab9bb1ff --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock.go @@ -0,0 +1,187 @@ +package sysfs + +import ( + "net" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" + "github.com/tetratelabs/wazero/sys" +) + +// NewTCPListenerFile creates a socketapi.TCPSock for a given *net.TCPListener. +func NewTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { + return newTCPListenerFile(tl) +} + +// baseSockFile implements base behavior for all TCPSock, TCPConn files, +// regardless the platform. +type baseSockFile struct { + experimentalsys.UnimplementedFile +} + +var _ experimentalsys.File = (*baseSockFile)(nil) + +// IsDir implements the same method as documented on File.IsDir +func (*baseSockFile) IsDir() (bool, experimentalsys.Errno) { + // We need to override this method because WASI-libc prestats the FD + // and the default impl returns ENOSYS otherwise. + return false, 0 +} + +// Stat implements the same method as documented on File.Stat +func (f *baseSockFile) Stat() (fs sys.Stat_t, errno experimentalsys.Errno) { + // The mode is not really important, but it should be neither a regular file nor a directory. + fs.Mode = os.ModeIrregular + return +} + +var _ socketapi.TCPSock = (*tcpListenerFile)(nil) + +type tcpListenerFile struct { + baseSockFile + + tl *net.TCPListener + closed bool + nonblock bool +} + +// newTCPListenerFile is a constructor for a socketapi.TCPSock. +// +// The current strategy is to wrap a net.TCPListener +// and invoking raw syscalls using syscallConnControl: +// this internal calls RawConn.Control(func(fd)), making sure +// that the underlying file descriptor is valid throughout +// the duration of the syscall. +func newDefaultTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { + return &tcpListenerFile{tl: tl} +} + +// Close implements the same method as documented on experimentalsys.File +func (f *tcpListenerFile) Close() experimentalsys.Errno { + if !f.closed { + return experimentalsys.UnwrapOSError(f.tl.Close()) + } + return 0 +} + +// Addr is exposed for testing. +func (f *tcpListenerFile) Addr() *net.TCPAddr { + return f.tl.Addr().(*net.TCPAddr) +} + +// IsNonblock implements the same method as documented on fsapi.File +func (f *tcpListenerFile) IsNonblock() bool { + return f.nonblock +} + +// Poll implements the same method as documented on fsapi.File +func (f *tcpListenerFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} + +var _ socketapi.TCPConn = (*tcpConnFile)(nil) + +type tcpConnFile struct { + baseSockFile + + tc *net.TCPConn + + // nonblock is true when the underlying connection is flagged as non-blocking. + // This ensures that reads and writes return experimentalsys.EAGAIN without blocking the caller. + nonblock bool + // closed is true when closed was called. This ensures proper experimentalsys.EBADF + closed bool +} + +func newTcpConn(tc *net.TCPConn) socketapi.TCPConn { + return &tcpConnFile{tc: tc} +} + +// Read implements the same method as documented on experimentalsys.File +func (f *tcpConnFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { + if len(buf) == 0 { + return 0, 0 // Short-circuit 0-len reads. + } + if nonBlockingFileReadSupported && f.IsNonblock() { + n, errno = syscallConnControl(f.tc, func(fd uintptr) (int, experimentalsys.Errno) { + n, err := readSocket(fd, buf) + errno = experimentalsys.UnwrapOSError(err) + errno = fileError(f, f.closed, errno) + return n, errno + }) + } else { + n, errno = read(f.tc, buf) + } + if errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Write implements the same method as documented on experimentalsys.File +func (f *tcpConnFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { + if nonBlockingFileWriteSupported && f.IsNonblock() { + return syscallConnControl(f.tc, func(fd uintptr) (int, experimentalsys.Errno) { + n, err := writeSocket(fd, buf) + errno = experimentalsys.UnwrapOSError(err) + errno = fileError(f, f.closed, errno) + return n, errno + }) + } else { + n, errno = write(f.tc, buf) + } + if errno != 0 { + // Defer validation overhead until we've already had an error. + errno = fileError(f, f.closed, errno) + } + return +} + +// Recvfrom implements the same method as documented on socketapi.TCPConn +func (f *tcpConnFile) Recvfrom(p []byte, flags int) (n int, errno experimentalsys.Errno) { + if flags != MSG_PEEK { + errno = experimentalsys.EINVAL + return + } + return syscallConnControl(f.tc, func(fd uintptr) (int, experimentalsys.Errno) { + n, err := recvfrom(fd, p, MSG_PEEK) + errno = experimentalsys.UnwrapOSError(err) + errno = fileError(f, f.closed, errno) + return n, errno + }) +} + +// Close implements the same method as documented on experimentalsys.File +func (f *tcpConnFile) Close() experimentalsys.Errno { + return f.close() +} + +func (f *tcpConnFile) close() experimentalsys.Errno { + if f.closed { + return 0 + } + f.closed = true + return f.Shutdown(socketapi.SHUT_RDWR) +} + +// SetNonblock implements the same method as documented on fsapi.File +func (f *tcpConnFile) SetNonblock(enabled bool) (errno experimentalsys.Errno) { + f.nonblock = enabled + _, errno = syscallConnControl(f.tc, func(fd uintptr) (int, experimentalsys.Errno) { + return 0, experimentalsys.UnwrapOSError(setNonblockSocket(fd, enabled)) + }) + return +} + +// IsNonblock implements the same method as documented on fsapi.File +func (f *tcpConnFile) IsNonblock() bool { + return f.nonblock +} + +// Poll implements the same method as documented on fsapi.File +func (f *tcpConnFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + return false, experimentalsys.ENOSYS +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_supported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_supported.go new file mode 100644 index 00000000..6c976fb8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_supported.go @@ -0,0 +1,77 @@ +//go:build (linux || darwin || windows) && !tinygo + +package sysfs + +import ( + "net" + "syscall" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" +) + +// Accept implements the same method as documented on socketapi.TCPSock +func (f *tcpListenerFile) Accept() (socketapi.TCPConn, experimentalsys.Errno) { + // Ensure we have an incoming connection, otherwise return immediately. + if f.nonblock { + if ready, errno := _pollSock(f.tl, fsapi.POLLIN, 0); !ready || errno != 0 { + return nil, experimentalsys.EAGAIN + } + } + + // Accept normally blocks goroutines, but we + // made sure that we have an incoming connection, + // so we should be safe. + if conn, err := f.tl.Accept(); err != nil { + return nil, experimentalsys.UnwrapOSError(err) + } else { + return newTcpConn(conn.(*net.TCPConn)), 0 + } +} + +// SetNonblock implements the same method as documented on fsapi.File +func (f *tcpListenerFile) SetNonblock(enabled bool) (errno experimentalsys.Errno) { + f.nonblock = enabled + _, errno = syscallConnControl(f.tl, func(fd uintptr) (int, experimentalsys.Errno) { + return 0, setNonblockSocket(fd, enabled) + }) + return +} + +// Shutdown implements the same method as documented on experimentalsys.Conn +func (f *tcpConnFile) Shutdown(how int) experimentalsys.Errno { + // FIXME: can userland shutdown listeners? + var err error + switch how { + case socketapi.SHUT_RD: + err = f.tc.CloseRead() + case socketapi.SHUT_WR: + err = f.tc.CloseWrite() + case socketapi.SHUT_RDWR: + return f.close() + default: + return experimentalsys.EINVAL + } + return experimentalsys.UnwrapOSError(err) +} + +// syscallConnControl extracts a syscall.RawConn from the given syscall.Conn and applies +// the given fn to a file descriptor, returning an integer or a nonzero syscall.Errno on failure. +// +// syscallConnControl streamlines the pattern of extracting the syscall.Rawconn, +// invoking its syscall.RawConn.Control method, then handling properly the errors that may occur +// within fn or returned by syscall.RawConn.Control itself. +func syscallConnControl(conn syscall.Conn, fn func(fd uintptr) (int, experimentalsys.Errno)) (n int, errno experimentalsys.Errno) { + syscallConn, err := conn.SyscallConn() + if err != nil { + return 0, experimentalsys.UnwrapOSError(err) + } + // Prioritize the inner errno over Control + if controlErr := syscallConn.Control(func(fd uintptr) { + n, errno = fn(fd) + }); errno == 0 { + errno = experimentalsys.UnwrapOSError(controlErr) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unix.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unix.go new file mode 100644 index 00000000..99ef018a --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unix.go @@ -0,0 +1,49 @@ +//go:build (linux || darwin) && !tinygo + +package sysfs + +import ( + "net" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" +) + +// MSG_PEEK is the constant syscall.MSG_PEEK +const MSG_PEEK = syscall.MSG_PEEK + +func newTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { + return newDefaultTCPListenerFile(tl) +} + +func _pollSock(conn syscall.Conn, flag fsapi.Pflag, timeoutMillis int32) (bool, sys.Errno) { + n, errno := syscallConnControl(conn, func(fd uintptr) (int, sys.Errno) { + if ready, errno := poll(fd, fsapi.POLLIN, 0); !ready || errno != 0 { + return -1, errno + } else { + return 0, errno + } + }) + return n >= 0, errno +} + +func setNonblockSocket(fd uintptr, enabled bool) sys.Errno { + return sys.UnwrapOSError(setNonblock(fd, enabled)) +} + +func readSocket(fd uintptr, buf []byte) (int, sys.Errno) { + n, err := syscall.Read(int(fd), buf) + return n, sys.UnwrapOSError(err) +} + +func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) { + n, err := syscall.Write(int(fd), buf) + return n, sys.UnwrapOSError(err) +} + +func recvfrom(fd uintptr, buf []byte, flags int32) (n int, errno sys.Errno) { + n, _, err := syscall.Recvfrom(int(fd), buf, int(flags)) + return n, sys.UnwrapOSError(err) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unsupported.go new file mode 100644 index 00000000..8c27fed7 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_unsupported.go @@ -0,0 +1,81 @@ +//go:build (!linux && !darwin && !windows) || tinygo + +package sysfs + +import ( + "net" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" +) + +// MSG_PEEK is a filler value. +const MSG_PEEK = 0x2 + +func newTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { + return &unsupportedSockFile{} +} + +type unsupportedSockFile struct { + baseSockFile +} + +// Accept implements the same method as documented on socketapi.TCPSock +func (f *unsupportedSockFile) Accept() (socketapi.TCPConn, sys.Errno) { + return nil, sys.ENOSYS +} + +func _pollSock(conn syscall.Conn, flag fsapi.Pflag, timeoutMillis int32) (bool, sys.Errno) { + return false, sys.ENOTSUP +} + +func setNonblockSocket(fd uintptr, enabled bool) sys.Errno { + return sys.ENOTSUP +} + +func readSocket(fd uintptr, buf []byte) (int, sys.Errno) { + return -1, sys.ENOTSUP +} + +func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) { + return -1, sys.ENOTSUP +} + +func recvfrom(fd uintptr, buf []byte, flags int32) (n int, errno sys.Errno) { + return -1, sys.ENOTSUP +} + +// syscallConnControl extracts a syscall.RawConn from the given syscall.Conn and applies +// the given fn to a file descriptor, returning an integer or a nonzero syscall.Errno on failure. +// +// syscallConnControl streamlines the pattern of extracting the syscall.Rawconn, +// invoking its syscall.RawConn.Control method, then handling properly the errors that may occur +// within fn or returned by syscall.RawConn.Control itself. +func syscallConnControl(conn syscall.Conn, fn func(fd uintptr) (int, experimentalsys.Errno)) (n int, errno sys.Errno) { + return -1, sys.ENOTSUP +} + +// Accept implements the same method as documented on socketapi.TCPSock +func (f *tcpListenerFile) Accept() (socketapi.TCPConn, experimentalsys.Errno) { + return nil, experimentalsys.ENOSYS +} + +// Shutdown implements the same method as documented on experimentalsys.Conn +func (f *tcpConnFile) Shutdown(how int) experimentalsys.Errno { + // FIXME: can userland shutdown listeners? + var err error + switch how { + case socketapi.SHUT_RD: + err = f.tc.Close() + case socketapi.SHUT_WR: + err = f.tc.Close() + case socketapi.SHUT_RDWR: + return f.close() + default: + return experimentalsys.EINVAL + } + return experimentalsys.UnwrapOSError(err) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_windows.go new file mode 100644 index 00000000..703df42f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sock_windows.go @@ -0,0 +1,80 @@ +//go:build windows + +package sysfs + +import ( + "net" + "syscall" + "unsafe" + + "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/fsapi" + socketapi "github.com/tetratelabs/wazero/internal/sock" +) + +const ( + // MSG_PEEK is the flag PEEK for syscall.Recvfrom on Windows. + // This constant is not exported on this platform. + MSG_PEEK = 0x2 + // _FIONBIO is the flag to set the O_NONBLOCK flag on socket handles using ioctlsocket. + _FIONBIO = 0x8004667e +) + +var ( + // modws2_32 is WinSock. + modws2_32 = syscall.NewLazyDLL("ws2_32.dll") + // procrecvfrom exposes recvfrom from WinSock. + procrecvfrom = modws2_32.NewProc("recvfrom") + // procioctlsocket exposes ioctlsocket from WinSock. + procioctlsocket = modws2_32.NewProc("ioctlsocket") +) + +func newTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { + return newDefaultTCPListenerFile(tl) +} + +// recvfrom exposes the underlying syscall in Windows. +// +// Note: since we are only using this to expose MSG_PEEK, +// we do not need really need all the parameters that are actually +// allowed in WinSock. +// We ignore `from *sockaddr` and `fromlen *int`. +func recvfrom(s uintptr, buf []byte, flags int32) (n int, errno sys.Errno) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := syscall.SyscallN( + procrecvfrom.Addr(), + s, + uintptr(unsafe.Pointer(_p0)), + uintptr(len(buf)), + uintptr(flags), + 0, // from *sockaddr (optional) + 0) // fromlen *int (optional) + return int(r0), sys.UnwrapOSError(e1) +} + +func setNonblockSocket(fd uintptr, enabled bool) sys.Errno { + opt := uint64(0) + if enabled { + opt = 1 + } + // ioctlsocket(fd, FIONBIO, &opt) + _, _, errno := syscall.SyscallN( + procioctlsocket.Addr(), + uintptr(fd), + uintptr(_FIONBIO), + uintptr(unsafe.Pointer(&opt))) + return sys.UnwrapOSError(errno) +} + +func _pollSock(conn syscall.Conn, flag fsapi.Pflag, timeoutMillis int32) (bool, sys.Errno) { + if flag != fsapi.POLLIN { + return false, sys.ENOTSUP + } + n, errno := syscallConnControl(conn, func(fd uintptr) (int, sys.Errno) { + return _poll([]pollFd{newPollFd(fd, _POLLIN, 0)}, timeoutMillis) + }) + return n > 0, errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat.go new file mode 100644 index 00000000..2d973b16 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat.go @@ -0,0 +1,16 @@ +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +func defaultStatFile(f fs.File) (sys.Stat_t, experimentalsys.Errno) { + if info, err := f.Stat(); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_bsd.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_bsd.go new file mode 100644 index 00000000..254e204c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_bsd.go @@ -0,0 +1,37 @@ +//go:build (amd64 || arm64) && (darwin || freebsd) + +package sysfs + +import ( + "io/fs" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +// dirNlinkIncludesDot is true because even though os.File filters out dot +// entries, the underlying syscall.Stat includes them. +// +// Note: this is only used in tests +const dirNlinkIncludesDot = true + +func lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Lstat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func stat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Stat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func statFile(f fs.File) (sys.Stat_t, experimentalsys.Errno) { + return defaultStatFile(f) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_linux.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_linux.go new file mode 100644 index 00000000..fd289756 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_linux.go @@ -0,0 +1,40 @@ +//go:build (amd64 || arm64 || riscv64) && linux + +// Note: This expression is not the same as compiler support, even if it looks +// similar. Platform functions here are used in interpreter mode as well. + +package sysfs + +import ( + "io/fs" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +// dirNlinkIncludesDot is true because even though os.File filters out dot +// entries, the underlying syscall.Stat includes them. +// +// Note: this is only used in tests +const dirNlinkIncludesDot = true + +func lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Lstat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func stat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Stat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func statFile(f fs.File) (sys.Stat_t, experimentalsys.Errno) { + return defaultStatFile(f) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_unsupported.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_unsupported.go new file mode 100644 index 00000000..4b05a897 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_unsupported.go @@ -0,0 +1,40 @@ +//go:build (!((amd64 || arm64 || riscv64) && linux) && !((amd64 || arm64) && (darwin || freebsd)) && !((amd64 || arm64) && windows)) || js + +package sysfs + +import ( + "io/fs" + "os" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +// Note: go:build constraints must be the same as /sys.stat_unsupported.go for +// the same reasons. + +// dirNlinkIncludesDot might be true for some operating systems, which can have +// new stat_XX.go files as necessary. +// +// Note: this is only used in tests +const dirNlinkIncludesDot = false + +func lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Lstat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func stat(path string) (sys.Stat_t, experimentalsys.Errno) { + if info, err := os.Stat(path); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } else { + return sys.NewStat_t(info), 0 + } +} + +func statFile(f fs.File) (sys.Stat_t, experimentalsys.Errno) { + return defaultStatFile(f) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_windows.go new file mode 100644 index 00000000..4456dd78 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/stat_windows.go @@ -0,0 +1,120 @@ +//go:build (amd64 || arm64) && windows + +package sysfs + +import ( + "io/fs" + "syscall" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/sys" +) + +// dirNlinkIncludesDot is false because Windows does not return dot entries. +// +// Note: this is only used in tests +const dirNlinkIncludesDot = false + +func lstat(path string) (sys.Stat_t, experimentalsys.Errno) { + attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) + // Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink. + // See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted + attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT + return statPath(attrs, path) +} + +func stat(path string) (sys.Stat_t, experimentalsys.Errno) { + attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) + return statPath(attrs, path) +} + +func statPath(createFileAttrs uint32, path string) (sys.Stat_t, experimentalsys.Errno) { + if len(path) == 0 { + return sys.Stat_t{}, experimentalsys.ENOENT + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return sys.Stat_t{}, experimentalsys.EINVAL + } + + // open the file handle + h, err := syscall.CreateFile(pathp, 0, 0, nil, + syscall.OPEN_EXISTING, createFileAttrs, 0) + if err != nil { + errno := experimentalsys.UnwrapOSError(err) + // To match expectations of WASI, e.g. TinyGo TestStatBadDir, return + // ENOENT, not ENOTDIR. + if errno == experimentalsys.ENOTDIR { + errno = experimentalsys.ENOENT + } + return sys.Stat_t{}, errno + } + defer syscall.CloseHandle(h) + + return statHandle(h) +} + +// fdFile allows masking the `Fd` function on os.File. +type fdFile interface { + Fd() uintptr +} + +func statFile(f fs.File) (sys.Stat_t, experimentalsys.Errno) { + if osF, ok := f.(fdFile); ok { + // Attempt to get the stat by handle, which works for normal files + st, err := statHandle(syscall.Handle(osF.Fd())) + + // ERROR_INVALID_HANDLE happens before Go 1.20. Don't fail as we only + // use that approach to fill in inode data, which is not critical. + // + // Note: statHandle uses UnwrapOSError which coerces + // ERROR_INVALID_HANDLE to EBADF. + if err != experimentalsys.EBADF { + return st, err + } + } + return defaultStatFile(f) +} + +func statHandle(h syscall.Handle) (sys.Stat_t, experimentalsys.Errno) { + winFt, err := syscall.GetFileType(h) + if err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } + + var fi syscall.ByHandleFileInformation + if err = syscall.GetFileInformationByHandle(h, &fi); err != nil { + return sys.Stat_t{}, experimentalsys.UnwrapOSError(err) + } + + var m fs.FileMode + if fi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 { + m |= 0o444 + } else { + m |= 0o666 + } + + switch { // check whether this is a symlink first + case fi.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0: + m |= fs.ModeSymlink + case winFt == syscall.FILE_TYPE_PIPE: + m |= fs.ModeNamedPipe + case winFt == syscall.FILE_TYPE_CHAR: + m |= fs.ModeDevice | fs.ModeCharDevice + case fi.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0: + m |= fs.ModeDir | 0o111 // e.g. 0o444 -> 0o555 + } + + st := sys.Stat_t{} + // FileIndex{High,Low} can be combined and used as a unique identifier like inode. + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information + st.Dev = uint64(fi.VolumeSerialNumber) + st.Ino = (uint64(fi.FileIndexHigh) << 32) | uint64(fi.FileIndexLow) + st.Mode = m + st.Nlink = uint64(fi.NumberOfLinks) + st.Size = int64(fi.FileSizeHigh)<<32 + int64(fi.FileSizeLow) + st.Atim = fi.LastAccessTime.Nanoseconds() + st.Mtim = fi.LastWriteTime.Nanoseconds() + st.Ctim = fi.CreationTime.Nanoseconds() + return st, 0 +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync.go new file mode 100644 index 00000000..86f9a086 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync.go @@ -0,0 +1,13 @@ +//go:build !windows + +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func fsync(f *os.File) sys.Errno { + return sys.UnwrapOSError(f.Sync()) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync_windows.go new file mode 100644 index 00000000..f288eb25 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sync_windows.go @@ -0,0 +1,20 @@ +package sysfs + +import ( + "os" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func fsync(f *os.File) sys.Errno { + errno := sys.UnwrapOSError(f.Sync()) + // Coerce error performing stat on a directory to 0, as it won't work + // on Windows. + switch errno { + case sys.EACCES /* Go 1.20 */, sys.EBADF /* Go 1.19 */ : + if st, err := f.Stat(); err == nil && st.IsDir() { + errno = 0 + } + } + return errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/syscall6_darwin.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/syscall6_darwin.go new file mode 100644 index 00000000..9fde5baa --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/syscall6_darwin.go @@ -0,0 +1,13 @@ +package sysfs + +import ( + "syscall" + _ "unsafe" +) + +// syscall_syscall6 is a private symbol that we link below. We need to use this +// instead of syscall.Syscall6 because the public syscall.Syscall6 won't work +// when fn is an address. +// +//go:linkname syscall_syscall6 syscall.syscall6 +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/sysfs.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sysfs.go new file mode 100644 index 00000000..dd0a8882 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/sysfs.go @@ -0,0 +1,6 @@ +// Package sysfs includes a low-level filesystem interface and utilities needed +// for WebAssembly host functions (ABI) such as WASI. +// +// The name sysfs was chosen because wazero's public API has a "sys" package, +// which was named after https://github.com/golang/sys. +package sysfs diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink.go new file mode 100644 index 00000000..e3f05100 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink.go @@ -0,0 +1,17 @@ +//go:build !windows && !plan9 && !tinygo + +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func unlink(name string) (errno sys.Errno) { + err := syscall.Unlink(name) + if errno = sys.UnwrapOSError(err); errno == sys.EPERM { + errno = sys.EISDIR + } + return errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_plan9.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_plan9.go new file mode 100644 index 00000000..16ed06ab --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_plan9.go @@ -0,0 +1,12 @@ +package sysfs + +import ( + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func unlink(name string) sys.Errno { + err := syscall.Remove(name) + return sys.UnwrapOSError(err) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_windows.go new file mode 100644 index 00000000..be31c7b9 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/unlink_windows.go @@ -0,0 +1,25 @@ +package sysfs + +import ( + "os" + "syscall" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +func unlink(name string) sys.Errno { + err := syscall.Unlink(name) + if err == nil { + return 0 + } + errno := sys.UnwrapOSError(err) + if errno == sys.EBADF { + lstat, errLstat := os.Lstat(name) + if errLstat == nil && lstat.Mode()&os.ModeSymlink != 0 { + errno = sys.UnwrapOSError(os.Remove(name)) + } else { + errno = sys.EISDIR + } + } + return errno +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/u32/u32.go b/vendor/github.com/tetratelabs/wazero/internal/u32/u32.go new file mode 100644 index 00000000..5960a6f0 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/u32/u32.go @@ -0,0 +1,11 @@ +package u32 + +// LeBytes returns a byte slice corresponding to the 4 bytes in the uint32 in little-endian byte order. +func LeBytes(v uint32) []byte { + return []byte{ + byte(v), + byte(v >> 8), + byte(v >> 16), + byte(v >> 24), + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/u64/u64.go b/vendor/github.com/tetratelabs/wazero/internal/u64/u64.go new file mode 100644 index 00000000..65c7cd12 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/u64/u64.go @@ -0,0 +1,15 @@ +package u64 + +// LeBytes returns a byte slice corresponding to the 8 bytes in the uint64 in little-endian byte order. +func LeBytes(v uint64) []byte { + return []byte{ + byte(v), + byte(v >> 8), + byte(v >> 16), + byte(v >> 24), + byte(v >> 32), + byte(v >> 40), + byte(v >> 48), + byte(v >> 56), + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/version/version.go b/vendor/github.com/tetratelabs/wazero/internal/version/version.go new file mode 100644 index 00000000..9261df0f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/version/version.go @@ -0,0 +1,52 @@ +package version + +import ( + "runtime/debug" + "strings" +) + +// Default is the default version value used when none was found. +const Default = "dev" + +// version holds the current version from the go.mod of downstream users or set by ldflag for wazero CLI. +var version string + +// GetWazeroVersion returns the current version of wazero either in the go.mod or set by ldflag for wazero CLI. +// +// If this is not CLI, this assumes that downstream users of wazero imports wazero as "github.com/tetratelabs/wazero". +// To be precise, the returned string matches the require statement there. +// For example, if the go.mod has "require github.com/tetratelabs/wazero 0.1.2-12314124-abcd", +// then this returns "0.1.2-12314124-abcd". +// +// Note: this is tested in ./testdata/main_test.go with a separate go.mod to pretend as the wazero user. +func GetWazeroVersion() (ret string) { + if len(version) != 0 { + return version + } + + info, ok := debug.ReadBuildInfo() + if ok { + for _, dep := range info.Deps { + // Note: here's the assumption that wazero is imported as github.com/tetratelabs/wazero. + if strings.Contains(dep.Path, "github.com/tetratelabs/wazero") { + ret = dep.Version + } + } + + // In wazero CLI, wazero is a main module, so we have to get the version info from info.Main. + if versionMissing(ret) { + ret = info.Main.Version + } + } + if versionMissing(ret) { + return Default // don't return parens + } + + // Cache for the subsequent calls. + version = ret + return ret +} + +func versionMissing(ret string) bool { + return ret == "" || ret == "(devel)" // pkg.go defaults to (devel) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/args.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/args.go new file mode 100644 index 00000000..212d3b2d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/args.go @@ -0,0 +1,6 @@ +package wasip1 + +const ( + ArgsGetName = "args_get" + ArgsSizesGetName = "args_sizes_get" +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/clock.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/clock.go new file mode 100644 index 00000000..1d1b8c12 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/clock.go @@ -0,0 +1,16 @@ +package wasip1 + +const ( + ClockResGetName = "clock_res_get" + ClockTimeGetName = "clock_time_get" +) + +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clockid-enumu32 +const ( + // ClockIDRealtime is the name ID named "realtime" like sys.Walltime + ClockIDRealtime = iota + // ClockIDMonotonic is the name ID named "monotonic" like sys.Nanotime + ClockIDMonotonic + // Note: clockIDProcessCputime and clockIDThreadCputime were removed by + // WASI maintainers: https://github.com/WebAssembly/wasi-libc/pull/294 +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/environ.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/environ.go new file mode 100644 index 00000000..2b0d5982 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/environ.go @@ -0,0 +1,6 @@ +package wasip1 + +const ( + EnvironGetName = "environ_get" + EnvironSizesGetName = "environ_sizes_get" +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/errno.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/errno.go new file mode 100644 index 00000000..028573d2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/errno.go @@ -0,0 +1,314 @@ +package wasip1 + +import ( + "fmt" + + "github.com/tetratelabs/wazero/experimental/sys" +) + +// Errno is neither uint16 nor an alias for parity with wasm.ValueType. +type Errno = uint32 + +// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is +// not an error. e.g. Errno2big -> "E2BIG" +func ErrnoName(errno uint32) string { + if int(errno) < len(errnoToString) { + return errnoToString[errno] + } + return fmt.Sprintf("errno(%d)", errno) +} + +// Note: Below prefers POSIX symbol names over WASI ones, even if the docs are from WASI. +// See https://linux.die.net/man/3/errno +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#variants-1 +const ( + // ErrnoSuccess No error occurred. System call completed successfully. + ErrnoSuccess Errno = iota + // Errno2big Argument list too long. + Errno2big + // ErrnoAcces Permission denied. + ErrnoAcces + // ErrnoAddrinuse Address in use. + ErrnoAddrinuse + // ErrnoAddrnotavail Address not available. + ErrnoAddrnotavail + // ErrnoAfnosupport Address family not supported. + ErrnoAfnosupport + // ErrnoAgain Resource unavailable, or operation would block. + ErrnoAgain + // ErrnoAlready Connection already in progress. + ErrnoAlready + // ErrnoBadf Bad file descriptor. + ErrnoBadf + // ErrnoBadmsg Bad message. + ErrnoBadmsg + // ErrnoBusy Device or resource busy. + ErrnoBusy + // ErrnoCanceled Operation canceled. + ErrnoCanceled + // ErrnoChild No child processes. + ErrnoChild + // ErrnoConnaborted Connection aborted. + ErrnoConnaborted + // ErrnoConnrefused Connection refused. + ErrnoConnrefused + // ErrnoConnreset Connection reset. + ErrnoConnreset + // ErrnoDeadlk Resource deadlock would occur. + ErrnoDeadlk + // ErrnoDestaddrreq Destination address required. + ErrnoDestaddrreq + // ErrnoDom Mathematics argument out of domain of function. + ErrnoDom + // ErrnoDquot Reserved. + ErrnoDquot + // ErrnoExist File exists. + ErrnoExist + // ErrnoFault Bad address. + ErrnoFault + // ErrnoFbig File too large. + ErrnoFbig + // ErrnoHostunreach Host is unreachable. + ErrnoHostunreach + // ErrnoIdrm Identifier removed. + ErrnoIdrm + // ErrnoIlseq Illegal byte sequence. + ErrnoIlseq + // ErrnoInprogress Operation in progress. + ErrnoInprogress + // ErrnoIntr Interrupted function. + ErrnoIntr + // ErrnoInval Invalid argument. + ErrnoInval + // ErrnoIo I/O error. + ErrnoIo + // ErrnoIsconn Socket is connected. + ErrnoIsconn + // ErrnoIsdir Is a directory. + ErrnoIsdir + // ErrnoLoop Too many levels of symbolic links. + ErrnoLoop + // ErrnoMfile File descriptor value too large. + ErrnoMfile + // ErrnoMlink Too many links. + ErrnoMlink + // ErrnoMsgsize Message too large. + ErrnoMsgsize + // ErrnoMultihop Reserved. + ErrnoMultihop + // ErrnoNametoolong Filename too long. + ErrnoNametoolong + // ErrnoNetdown Network is down. + ErrnoNetdown + // ErrnoNetreset Connection aborted by network. + ErrnoNetreset + // ErrnoNetunreach Network unreachable. + ErrnoNetunreach + // ErrnoNfile Too many files open in system. + ErrnoNfile + // ErrnoNobufs No buffer space available. + ErrnoNobufs + // ErrnoNodev No such device. + ErrnoNodev + // ErrnoNoent No such file or directory. + ErrnoNoent + // ErrnoNoexec Executable file format error. + ErrnoNoexec + // ErrnoNolck No locks available. + ErrnoNolck + // ErrnoNolink Reserved. + ErrnoNolink + // ErrnoNomem Not enough space. + ErrnoNomem + // ErrnoNomsg No message of the desired type. + ErrnoNomsg + // ErrnoNoprotoopt No message of the desired type. + ErrnoNoprotoopt + // ErrnoNospc No space left on device. + ErrnoNospc + // ErrnoNosys function not supported. + ErrnoNosys + // ErrnoNotconn The socket is not connected. + ErrnoNotconn + // ErrnoNotdir Not a directory or a symbolic link to a directory. + ErrnoNotdir + // ErrnoNotempty Directory not empty. + ErrnoNotempty + // ErrnoNotrecoverable State not recoverable. + ErrnoNotrecoverable + // ErrnoNotsock Not a socket. + ErrnoNotsock + // ErrnoNotsup Not supported, or operation not supported on socket. + ErrnoNotsup + // ErrnoNotty Inappropriate I/O control operation. + ErrnoNotty + // ErrnoNxio No such device or address. + ErrnoNxio + // ErrnoOverflow Value too large to be stored in data type. + ErrnoOverflow + // ErrnoOwnerdead Previous owner died. + ErrnoOwnerdead + // ErrnoPerm Operation not permitted. + ErrnoPerm + // ErrnoPipe Broken pipe. + ErrnoPipe + // ErrnoProto Protocol error. + ErrnoProto + // ErrnoProtonosupport Protocol error. + ErrnoProtonosupport + // ErrnoPrototype Protocol wrong type for socket. + ErrnoPrototype + // ErrnoRange Result too large. + ErrnoRange + // ErrnoRofs Read-only file system. + ErrnoRofs + // ErrnoSpipe Invalid seek. + ErrnoSpipe + // ErrnoSrch No such process. + ErrnoSrch + // ErrnoStale Reserved. + ErrnoStale + // ErrnoTimedout Connection timed out. + ErrnoTimedout + // ErrnoTxtbsy Text file busy. + ErrnoTxtbsy + // ErrnoXdev Cross-device link. + ErrnoXdev + + // Note: ErrnoNotcapable was removed by WASI maintainers. + // See https://github.com/WebAssembly/wasi-libc/pull/294 +) + +var errnoToString = [...]string{ + "ESUCCESS", + "E2BIG", + "EACCES", + "EADDRINUSE", + "EADDRNOTAVAIL", + "EAFNOSUPPORT", + "EAGAIN", + "EALREADY", + "EBADF", + "EBADMSG", + "EBUSY", + "ECANCELED", + "ECHILD", + "ECONNABORTED", + "ECONNREFUSED", + "ECONNRESET", + "EDEADLK", + "EDESTADDRREQ", + "EDOM", + "EDQUOT", + "EEXIST", + "EFAULT", + "EFBIG", + "EHOSTUNREACH", + "EIDRM", + "EILSEQ", + "EINPROGRESS", + "EINTR", + "EINVAL", + "EIO", + "EISCONN", + "EISDIR", + "ELOOP", + "EMFILE", + "EMLINK", + "EMSGSIZE", + "EMULTIHOP", + "ENAMETOOLONG", + "ENETDOWN", + "ENETRESET", + "ENETUNREACH", + "ENFILE", + "ENOBUFS", + "ENODEV", + "ENOENT", + "ENOEXEC", + "ENOLCK", + "ENOLINK", + "ENOMEM", + "ENOMSG", + "ENOPROTOOPT", + "ENOSPC", + "ENOSYS", + "ENOTCONN", + "ENOTDIR", + "ENOTEMPTY", + "ENOTRECOVERABLE", + "ENOTSOCK", + "ENOTSUP", + "ENOTTY", + "ENXIO", + "EOVERFLOW", + "EOWNERDEAD", + "EPERM", + "EPIPE", + "EPROTO", + "EPROTONOSUPPORT", + "EPROTOTYPE", + "ERANGE", + "EROFS", + "ESPIPE", + "ESRCH", + "ESTALE", + "ETIMEDOUT", + "ETXTBSY", + "EXDEV", + "ENOTCAPABLE", +} + +// ToErrno coerces the error to a WASI Errno. +// +// Note: Coercion isn't centralized in sys.FSContext because ABI use different +// error codes. For example, wasi-filesystem doesn't map to these +// Errno. +func ToErrno(errno sys.Errno) Errno { + switch errno { + case 0: + return ErrnoSuccess + case sys.EACCES: + return ErrnoAcces + case sys.EAGAIN: + return ErrnoAgain + case sys.EBADF: + return ErrnoBadf + case sys.EEXIST: + return ErrnoExist + case sys.EFAULT: + return ErrnoFault + case sys.EINTR: + return ErrnoIntr + case sys.EINVAL: + return ErrnoInval + case sys.EIO: + return ErrnoIo + case sys.EISDIR: + return ErrnoIsdir + case sys.ELOOP: + return ErrnoLoop + case sys.ENAMETOOLONG: + return ErrnoNametoolong + case sys.ENOENT: + return ErrnoNoent + case sys.ENOSYS: + return ErrnoNosys + case sys.ENOTDIR: + return ErrnoNotdir + case sys.ERANGE: + return ErrnoRange + case sys.ENOTEMPTY: + return ErrnoNotempty + case sys.ENOTSOCK: + return ErrnoNotsock + case sys.ENOTSUP: + return ErrnoNotsup + case sys.EPERM: + return ErrnoPerm + case sys.EROFS: + return ErrnoRofs + default: + return ErrnoIo + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/fs.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/fs.go new file mode 100644 index 00000000..ed8df1ed --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/fs.go @@ -0,0 +1,164 @@ +package wasip1 + +import ( + "fmt" +) + +const ( + FdAdviseName = "fd_advise" + FdAllocateName = "fd_allocate" + FdCloseName = "fd_close" + FdDatasyncName = "fd_datasync" + FdFdstatGetName = "fd_fdstat_get" + FdFdstatSetFlagsName = "fd_fdstat_set_flags" + FdFdstatSetRightsName = "fd_fdstat_set_rights" + FdFilestatGetName = "fd_filestat_get" + FdFilestatSetSizeName = "fd_filestat_set_size" + FdFilestatSetTimesName = "fd_filestat_set_times" + FdPreadName = "fd_pread" + FdPrestatGetName = "fd_prestat_get" + FdPrestatDirNameName = "fd_prestat_dir_name" + FdPwriteName = "fd_pwrite" + FdReadName = "fd_read" + FdReaddirName = "fd_readdir" + FdRenumberName = "fd_renumber" + FdSeekName = "fd_seek" + FdSyncName = "fd_sync" + FdTellName = "fd_tell" + FdWriteName = "fd_write" + + PathCreateDirectoryName = "path_create_directory" + PathFilestatGetName = "path_filestat_get" + PathFilestatSetTimesName = "path_filestat_set_times" + PathLinkName = "path_link" + PathOpenName = "path_open" + PathReadlinkName = "path_readlink" + PathRemoveDirectoryName = "path_remove_directory" + PathRenameName = "path_rename" + PathSymlinkName = "path_symlink" + PathUnlinkFileName = "path_unlink_file" +) + +// oflags are open flags used by path_open +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16 +const ( + // O_CREAT creates a file if it does not exist. + O_CREAT uint16 = 1 << iota //nolint + // O_DIRECTORY fails if not a directory. + O_DIRECTORY + // O_EXCL fails if file already exists. + O_EXCL //nolint + // O_TRUNC truncates the file to size 0. + O_TRUNC //nolint +) + +func OflagsString(oflags int) string { + return flagsString(oflagNames[:], oflags) +} + +var oflagNames = [...]string{ + "CREAT", + "DIRECTORY", + "EXCL", + "TRUNC", +} + +// file descriptor flags +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdflags +const ( + FD_APPEND uint16 = 1 << iota //nolint + FD_DSYNC + FD_NONBLOCK + FD_RSYNC + FD_SYNC +) + +func FdFlagsString(fdflags int) string { + return flagsString(fdflagNames[:], fdflags) +} + +var fdflagNames = [...]string{ + "APPEND", + "DSYNC", + "NONBLOCK", + "RSYNC", + "SYNC", +} + +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags +const ( + // LOOKUP_SYMLINK_FOLLOW expands a path if it resolves into a symbolic + // link. + LOOKUP_SYMLINK_FOLLOW uint16 = 1 << iota //nolint +) + +var lookupflagNames = [...]string{ + "SYMLINK_FOLLOW", +} + +func LookupflagsString(lookupflags int) string { + return flagsString(lookupflagNames[:], lookupflags) +} + +// DirentSize is the size of the dirent struct, which should be followed by the +// length of a file name. +const DirentSize = uint32(24) + +const ( + FILETYPE_UNKNOWN uint8 = iota + FILETYPE_BLOCK_DEVICE + FILETYPE_CHARACTER_DEVICE + FILETYPE_DIRECTORY + FILETYPE_REGULAR_FILE + FILETYPE_SOCKET_DGRAM + FILETYPE_SOCKET_STREAM + FILETYPE_SYMBOLIC_LINK +) + +// FiletypeName returns string name of the file type. +func FiletypeName(filetype uint8) string { + if int(filetype) < len(filetypeToString) { + return filetypeToString[filetype] + } + return fmt.Sprintf("filetype(%d)", filetype) +} + +var filetypeToString = [...]string{ + "UNKNOWN", + "BLOCK_DEVICE", + "CHARACTER_DEVICE", + "DIRECTORY", + "REGULAR_FILE", + "SOCKET_DGRAM", + "SOCKET_STREAM", + "SYMBOLIC_LINK", +} + +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fstflags +const ( + FstflagsAtim uint16 = 1 << iota + FstflagsAtimNow + FstflagsMtim + FstflagsMtimNow +) + +var fstflagNames = [...]string{ + "ATIM", + "ATIM_NOW", + "MTIM", + "MTIM_NOW", +} + +func FstflagsString(fdflags int) string { + return flagsString(fstflagNames[:], fdflags) +} + +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-advice-enumu8 +const ( + FdAdviceNormal byte = iota + FdAdviceSequential + FdAdviceRandom + FdAdviceWillNeed + FdAdviceDontNeed + FdAdviceNoReuse +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/poll.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/poll.go new file mode 100644 index 00000000..9bde768f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/poll.go @@ -0,0 +1,15 @@ +package wasip1 + +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-eventtype-enumu8 +const ( + // EventTypeClock is the timeout event named "name". + EventTypeClock = iota + // EventTypeFdRead is the data available event named "fd_read". + EventTypeFdRead + // EventTypeFdWrite is the capacity available event named "fd_write". + EventTypeFdWrite +) + +const ( + PollOneoffName = "poll_oneoff" +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/proc.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/proc.go new file mode 100644 index 00000000..50b040c9 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/proc.go @@ -0,0 +1,6 @@ +package wasip1 + +const ( + ProcExitName = "proc_exit" + ProcRaiseName = "proc_raise" +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/random.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/random.go new file mode 100644 index 00000000..23645337 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/random.go @@ -0,0 +1,3 @@ +package wasip1 + +const RandomGetName = "random_get" diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/rights.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/rights.go new file mode 100644 index 00000000..2ab56c60 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/rights.go @@ -0,0 +1,148 @@ +package wasip1 + +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-rights-flagsu64 +const ( + // RIGHT_FD_DATASYNC is the right to invoke fd_datasync. If RIGHT_PATH_OPEN + // is set, includes the right to invoke path_open with FD_DSYNC. + RIGHT_FD_DATASYNC uint32 = 1 << iota //nolint + + // RIGHT_FD_READ is he right to invoke fd_read and sock_recv. If + // RIGHT_FD_SYNC is set, includes the right to invoke fd_pread. + RIGHT_FD_READ + + // RIGHT_FD_SEEK is the right to invoke fd_seek. This flag implies + // RIGHT_FD_TELL. + RIGHT_FD_SEEK + + // RIGHT_FDSTAT_SET_FLAGS is the right to invoke fd_fdstat_set_flags. + RIGHT_FDSTAT_SET_FLAGS + + // RIGHT_FD_SYNC The right to invoke fd_sync. If path_open is set, includes + // the right to invoke path_open with FD_RSYNC and FD_DSYNC. + RIGHT_FD_SYNC + + // RIGHT_FD_TELL is the right to invoke fd_seek in such a way that the file + // offset remains unaltered (i.e., whence::cur with offset zero), or to + // invoke fd_tell. + RIGHT_FD_TELL + + // RIGHT_FD_WRITE is the right to invoke fd_write and sock_send. If + // RIGHT_FD_SEEK is set, includes the right to invoke fd_pwrite. + RIGHT_FD_WRITE + + // RIGHT_FD_ADVISE is the right to invoke fd_advise. + RIGHT_FD_ADVISE + + // RIGHT_FD_ALLOCATE is the right to invoke fd_allocate. + RIGHT_FD_ALLOCATE + + // RIGHT_PATH_CREATE_DIRECTORY is the right to invoke + // path_create_directory. + RIGHT_PATH_CREATE_DIRECTORY + + // RIGHT_PATH_CREATE_FILE when RIGHT_PATH_OPEN is set, the right to invoke + // path_open with O_CREAT. + RIGHT_PATH_CREATE_FILE + + // RIGHT_PATH_LINK_SOURCE is the right to invoke path_link with the file + // descriptor as the source directory. + RIGHT_PATH_LINK_SOURCE + + // RIGHT_PATH_LINK_TARGET is the right to invoke path_link with the file + // descriptor as the target directory. + RIGHT_PATH_LINK_TARGET + + // RIGHT_PATH_OPEN is the right to invoke path_open. + RIGHT_PATH_OPEN + + // RIGHT_FD_READDIR is the right to invoke fd_readdir. + RIGHT_FD_READDIR + + // RIGHT_PATH_READLINK is the right to invoke path_readlink. + RIGHT_PATH_READLINK + + // RIGHT_PATH_RENAME_SOURCE is the right to invoke path_rename with the + // file descriptor as the source directory. + RIGHT_PATH_RENAME_SOURCE + + // RIGHT_PATH_RENAME_TARGET is the right to invoke path_rename with the + // file descriptor as the target directory. + RIGHT_PATH_RENAME_TARGET + + // RIGHT_PATH_FILESTAT_GET is the right to invoke path_filestat_get. + RIGHT_PATH_FILESTAT_GET + + // RIGHT_PATH_FILESTAT_SET_SIZE is the right to change a file's size (there + // is no path_filestat_set_size). If RIGHT_PATH_OPEN is set, includes the + // right to invoke path_open with O_TRUNC. + RIGHT_PATH_FILESTAT_SET_SIZE + + // RIGHT_PATH_FILESTAT_SET_TIMES is the right to invoke + // path_filestat_set_times. + RIGHT_PATH_FILESTAT_SET_TIMES + + // RIGHT_FD_FILESTAT_GET is the right to invoke fd_filestat_get. + RIGHT_FD_FILESTAT_GET + + // RIGHT_FD_FILESTAT_SET_SIZE is the right to invoke fd_filestat_set_size. + RIGHT_FD_FILESTAT_SET_SIZE + + // RIGHT_FD_FILESTAT_SET_TIMES is the right to invoke + // fd_filestat_set_times. + RIGHT_FD_FILESTAT_SET_TIMES + + // RIGHT_PATH_SYMLINK is the right to invoke path_symlink. + RIGHT_PATH_SYMLINK + + // RIGHT_PATH_REMOVE_DIRECTORY is the right to invoke + // path_remove_directory. + RIGHT_PATH_REMOVE_DIRECTORY + + // RIGHT_PATH_UNLINK_FILE is the right to invoke path_unlink_file. + RIGHT_PATH_UNLINK_FILE + + // RIGHT_POLL_FD_READWRITE when RIGHT_FD_READ is set, includes the right to + // invoke poll_oneoff to subscribe to eventtype::fd_read. If RIGHT_FD_WRITE + // is set, includes the right to invoke poll_oneoff to subscribe to + // eventtype::fd_write. + RIGHT_POLL_FD_READWRITE + + // RIGHT_SOCK_SHUTDOWN is the right to invoke sock_shutdown. + RIGHT_SOCK_SHUTDOWN +) + +func RightsString(rights int) string { + return flagsString(rightNames[:], rights) +} + +var rightNames = [...]string{ + "FD_DATASYNC", + "FD_READ", + "FD_SEEK", + "FDSTAT_SET_FLAGS", + "FD_SYNC", + "FD_TELL", + "FD_WRITE", + "FD_ADVISE", + "FD_ALLOCATE", + "PATH_CREATE_DIRECTORY", + "PATH_CREATE_FILE", + "PATH_LINK_SOURCE", + "PATH_LINK_TARGET", + "PATH_OPEN", + "FD_READDIR", + "PATH_READLINK", + "PATH_RENAME_SOURCE", + "PATH_RENAME_TARGET", + "PATH_FILESTAT_GET", + "PATH_FILESTAT_SET_SIZE", + "PATH_FILESTAT_SET_TIMES", + "FD_FILESTAT_GET", + "FD_FILESTAT_SET_SIZE", + "FD_FILESTAT_SET_TIMES", + "PATH_SYMLINK", + "PATH_REMOVE_DIRECTORY", + "PATH_UNLINK_FILE", + "POLL_FD_READWRITE", + "SOCK_SHUTDOWN", +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/sched.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/sched.go new file mode 100644 index 00000000..bc6e3938 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/sched.go @@ -0,0 +1,3 @@ +package wasip1 + +const SchedYieldName = "sched_yield" diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/sock.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/sock.go new file mode 100644 index 00000000..90d33ece --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/sock.go @@ -0,0 +1,71 @@ +package wasip1 + +import "strconv" + +const ( + SockAcceptName = "sock_accept" + SockRecvName = "sock_recv" + SockSendName = "sock_send" + SockShutdownName = "sock_shutdown" +) + +// SD Flags indicate which channels on a socket to shut down. +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sdflags-flagsu8 +const ( + // SD_RD disables further receive operations. + SD_RD uint8 = 1 << iota //nolint + // SD_WR disables further send operations. + SD_WR +) + +func SdFlagsString(sdflags int) string { + return flagsString(sdflagNames[:], sdflags) +} + +var sdflagNames = [...]string{ + "RD", + "WR", +} + +// SI Flags are flags provided to sock_send. As there are currently no flags defined, it must be set to zero. +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-siflags-u16 + +func SiFlagsString(siflags int) string { + if siflags == 0 { + return "" + } + return strconv.Itoa(siflags) +} + +// RI Flags are flags provided to sock_recv. +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-riflags-flagsu16 +const ( + // RI_RECV_PEEK returns the message without removing it from the socket's receive queue + RI_RECV_PEEK uint8 = 1 << iota //nolint + // RI_RECV_WAITALL on byte-stream sockets, block until the full amount of data can be returned. + RI_RECV_WAITALL +) + +func RiFlagsString(riflags int) string { + return flagsString(riflagNames[:], riflags) +} + +var riflagNames = [...]string{ + "RECV_PEEK", + "RECV_WAITALL", +} + +// RO Flags are flags returned by sock_recv. +// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-roflags-flagsu16 +const ( + // RO_RECV_DATA_TRUNCATED is returned by sock_recv when message data has been truncated. + RO_RECV_DATA_TRUNCATED uint8 = 1 << iota //nolint +) + +func RoFlagsString(roflags int) string { + return flagsString(roflagNames[:], roflags) +} + +var roflagNames = [...]string{ + "RECV_DATA_TRUNCATED", +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasip1/wasi.go b/vendor/github.com/tetratelabs/wazero/internal/wasip1/wasi.go new file mode 100644 index 00000000..299feea2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasip1/wasi.go @@ -0,0 +1,26 @@ +// Package wasip1 is a helper to remove package cycles re-using constants. +package wasip1 + +import ( + "strings" +) + +// InternalModuleName is not named ModuleName, to avoid a clash on dot imports. +const InternalModuleName = "wasi_snapshot_preview1" + +func flagsString(names []string, f int) string { + var builder strings.Builder + first := true + for i, sf := range names { + target := 1 << i + if target&f != 0 { + if !first { + builder.WriteByte('|') + } else { + first = false + } + builder.WriteString(sf) + } + } + return builder.String() +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go new file mode 100644 index 00000000..2fac9196 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go @@ -0,0 +1,100 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + "math" + + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeCode(r *bytes.Reader, codeSectionStart uint64, ret *wasm.Code) (err error) { + ss, _, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("get the size of code: %w", err) + } + remaining := int64(ss) + + // Parse #locals. + ls, bytesRead, err := leb128.DecodeUint32(r) + remaining -= int64(bytesRead) + if err != nil { + return fmt.Errorf("get the size locals: %v", err) + } else if remaining < 0 { + return io.EOF + } + + // Validate the locals. + bytesRead = 0 + var sum uint64 + for i := uint32(0); i < ls; i++ { + num, n, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("read n of locals: %v", err) + } else if remaining < 0 { + return io.EOF + } + + sum += uint64(num) + + b, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read type of local: %v", err) + } + + bytesRead += n + 1 + switch vt := b; vt { + case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64, + wasm.ValueTypeFuncref, wasm.ValueTypeExternref, wasm.ValueTypeV128: + default: + return fmt.Errorf("invalid local type: 0x%x", vt) + } + } + + if sum > math.MaxUint32 { + return fmt.Errorf("too many locals: %d", sum) + } + + // Rewind the buffer. + _, err = r.Seek(-int64(bytesRead), io.SeekCurrent) + if err != nil { + return err + } + + localTypes := make([]wasm.ValueType, 0, sum) + for i := uint32(0); i < ls; i++ { + num, bytesRead, err := leb128.DecodeUint32(r) + remaining -= int64(bytesRead) + 1 // +1 for the subsequent ReadByte + if err != nil { + return fmt.Errorf("read n of locals: %v", err) + } else if remaining < 0 { + return io.EOF + } + + b, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read type of local: %v", err) + } + + for j := uint32(0); j < num; j++ { + localTypes = append(localTypes, b) + } + } + + bodyOffsetInCodeSection := codeSectionStart - uint64(r.Len()) + body := make([]byte, remaining) + if _, err = io.ReadFull(r, body); err != nil { + return fmt.Errorf("read body: %w", err) + } + + if endIndex := len(body) - 1; endIndex < 0 || body[endIndex] != wasm.OpcodeEnd { + return fmt.Errorf("expr not end with OpcodeEnd") + } + + ret.BodyOffsetInCodeSection = bodyOffsetInCodeSection + ret.LocalTypes = localTypes + ret.Body = body + return nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go new file mode 100644 index 00000000..edfc0a08 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go @@ -0,0 +1,105 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/ieee754" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeConstantExpression(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.ConstantExpression) error { + b, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read opcode: %v", err) + } + + remainingBeforeData := int64(r.Len()) + offsetAtData := r.Size() - remainingBeforeData + + opcode := b + switch opcode { + case wasm.OpcodeI32Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + _, _, err = leb128.DecodeInt32(r) + case wasm.OpcodeI64Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + _, _, err = leb128.DecodeInt64(r) + case wasm.OpcodeF32Const: + buf := make([]byte, 4) + if _, err := io.ReadFull(r, buf); err != nil { + return fmt.Errorf("read f32 constant: %v", err) + } + _, err = ieee754.DecodeFloat32(buf) + case wasm.OpcodeF64Const: + buf := make([]byte, 8) + if _, err := io.ReadFull(r, buf); err != nil { + return fmt.Errorf("read f64 constant: %v", err) + } + _, err = ieee754.DecodeFloat64(buf) + case wasm.OpcodeGlobalGet: + _, _, err = leb128.DecodeUint32(r) + case wasm.OpcodeRefNull: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + return fmt.Errorf("ref.null is not supported as %w", err) + } + reftype, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read reference type for ref.null: %w", err) + } else if reftype != wasm.RefTypeFuncref && reftype != wasm.RefTypeExternref { + return fmt.Errorf("invalid type for ref.null: 0x%x", reftype) + } + case wasm.OpcodeRefFunc: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + return fmt.Errorf("ref.func is not supported as %w", err) + } + // Parsing index. + _, _, err = leb128.DecodeUint32(r) + case wasm.OpcodeVecPrefix: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil { + return fmt.Errorf("vector instructions are not supported as %w", err) + } + opcode, err = r.ReadByte() + if err != nil { + return fmt.Errorf("read vector instruction opcode suffix: %w", err) + } + + if opcode != wasm.OpcodeVecV128Const { + return fmt.Errorf("invalid vector opcode for const expression: %#x", opcode) + } + + remainingBeforeData = int64(r.Len()) + offsetAtData = r.Size() - remainingBeforeData + + n, err := r.Read(make([]byte, 16)) + if err != nil { + return fmt.Errorf("read vector const instruction immediates: %w", err) + } else if n != 16 { + return fmt.Errorf("read vector const instruction immediates: needs 16 bytes but was %d bytes", n) + } + default: + return fmt.Errorf("%v for const expression opt code: %#x", ErrInvalidByte, b) + } + + if err != nil { + return fmt.Errorf("read value: %v", err) + } + + if b, err = r.ReadByte(); err != nil { + return fmt.Errorf("look for end opcode: %v", err) + } + + if b != wasm.OpcodeEnd { + return fmt.Errorf("constant expression has been not terminated") + } + + ret.Data = make([]byte, remainingBeforeData-int64(r.Len())-1) + if _, err = r.ReadAt(ret.Data, offsetAtData); err != nil { + return fmt.Errorf("error re-buffering ConstantExpression.Data") + } + ret.Opcode = opcode + return nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go new file mode 100644 index 00000000..771f8c32 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go @@ -0,0 +1,22 @@ +package binary + +import ( + "bytes" + + "github.com/tetratelabs/wazero/internal/wasm" +) + +// decodeCustomSection deserializes the data **not** associated with the "name" key in SectionIDCustom. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0 +func decodeCustomSection(r *bytes.Reader, name string, limit uint64) (result *wasm.CustomSection, err error) { + buf := make([]byte, limit) + _, err = r.Read(buf) + + result = &wasm.CustomSection{ + Name: name, + Data: buf, + } + + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go new file mode 100644 index 00000000..054ccb3c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go @@ -0,0 +1,79 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// dataSegmentPrefix represents three types of data segments. +// +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section +type dataSegmentPrefix = uint32 + +const ( + // dataSegmentPrefixActive is the prefix for the version 1.0 compatible data segment, which is classified as "active" in 2.0. + dataSegmentPrefixActive dataSegmentPrefix = 0x0 + // dataSegmentPrefixPassive prefixes the "passive" data segment as in version 2.0 specification. + dataSegmentPrefixPassive dataSegmentPrefix = 0x1 + // dataSegmentPrefixActiveWithMemoryIndex is the active prefix with memory index encoded which is defined for futur use as of 2.0. + dataSegmentPrefixActiveWithMemoryIndex dataSegmentPrefix = 0x2 +) + +func decodeDataSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.DataSegment) (err error) { + dataSegmentPrefx, _, err := leb128.DecodeUint32(r) + if err != nil { + err = fmt.Errorf("read data segment prefix: %w", err) + return + } + + if dataSegmentPrefx != dataSegmentPrefixActive { + if err = enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + err = fmt.Errorf("non-zero prefix for data segment is invalid as %w", err) + return + } + } + + switch dataSegmentPrefx { + case dataSegmentPrefixActive, + dataSegmentPrefixActiveWithMemoryIndex: + // Active data segment as in + // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section + if dataSegmentPrefx == 0x2 { + d, _, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("read memory index: %v", err) + } else if d != 0 { + return fmt.Errorf("memory index must be zero but was %d", d) + } + } + + err = decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpression) + if err != nil { + return fmt.Errorf("read offset expression: %v", err) + } + case dataSegmentPrefixPassive: + // Passive data segment doesn't need const expr nor memory index encoded. + // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section + ret.Passive = true + default: + err = fmt.Errorf("invalid data segment prefix: 0x%x", dataSegmentPrefx) + return + } + + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + err = fmt.Errorf("get the size of vector: %v", err) + return + } + + ret.Init = make([]byte, vs) + if _, err = io.ReadFull(r, ret.Init); err != nil { + err = fmt.Errorf("read bytes for init: %v", err) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go new file mode 100644 index 00000000..c4191dae --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go @@ -0,0 +1,193 @@ +package binary + +import ( + "bytes" + "debug/dwarf" + "errors" + "fmt" + "io" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +// DecodeModule implements wasm.DecodeModule for the WebAssembly 1.0 (20191205) Binary Format +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-format%E2%91%A0 +func DecodeModule( + binary []byte, + enabledFeatures api.CoreFeatures, + memoryLimitPages uint32, + memoryCapacityFromMax, + dwarfEnabled, storeCustomSections bool, +) (*wasm.Module, error) { + r := bytes.NewReader(binary) + + // Magic number. + buf := make([]byte, 4) + if _, err := io.ReadFull(r, buf); err != nil || !bytes.Equal(buf, Magic) { + return nil, ErrInvalidMagicNumber + } + + // Version. + if _, err := io.ReadFull(r, buf); err != nil || !bytes.Equal(buf, version) { + return nil, ErrInvalidVersion + } + + memSizer := newMemorySizer(memoryLimitPages, memoryCapacityFromMax) + + m := &wasm.Module{} + var info, line, str, abbrev, ranges []byte // For DWARF Data. + for { + // TODO: except custom sections, all others are required to be in order, but we aren't checking yet. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#modules%E2%91%A0%E2%93%AA + sectionID, err := r.ReadByte() + if err == io.EOF { + break + } else if err != nil { + return nil, fmt.Errorf("read section id: %w", err) + } + + sectionSize, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of section %s: %v", wasm.SectionIDName(sectionID), err) + } + + sectionContentStart := r.Len() + switch sectionID { + case wasm.SectionIDCustom: + // First, validate the section and determine if the section for this name has already been set + name, nameSize, decodeErr := decodeUTF8(r, "custom section name") + if decodeErr != nil { + err = decodeErr + break + } else if sectionSize < nameSize { + err = fmt.Errorf("malformed custom section %s", name) + break + } else if name == "name" && m.NameSection != nil { + err = fmt.Errorf("redundant custom section %s", name) + break + } + + // Now, either decode the NameSection or CustomSection + limit := sectionSize - nameSize + + var c *wasm.CustomSection + if name != "name" { + if storeCustomSections || dwarfEnabled { + c, err = decodeCustomSection(r, name, uint64(limit)) + if err != nil { + return nil, fmt.Errorf("failed to read custom section name[%s]: %w", name, err) + } + m.CustomSections = append(m.CustomSections, c) + if dwarfEnabled { + switch name { + case ".debug_info": + info = c.Data + case ".debug_line": + line = c.Data + case ".debug_str": + str = c.Data + case ".debug_abbrev": + abbrev = c.Data + case ".debug_ranges": + ranges = c.Data + } + } + } else { + if _, err = io.CopyN(io.Discard, r, int64(limit)); err != nil { + return nil, fmt.Errorf("failed to skip name[%s]: %w", name, err) + } + } + } else { + m.NameSection, err = decodeNameSection(r, uint64(limit)) + } + case wasm.SectionIDType: + m.TypeSection, err = decodeTypeSection(enabledFeatures, r) + case wasm.SectionIDImport: + m.ImportSection, m.ImportPerModule, m.ImportFunctionCount, m.ImportGlobalCount, m.ImportMemoryCount, m.ImportTableCount, err = decodeImportSection(r, memSizer, memoryLimitPages, enabledFeatures) + if err != nil { + return nil, err // avoid re-wrapping the error. + } + case wasm.SectionIDFunction: + m.FunctionSection, err = decodeFunctionSection(r) + case wasm.SectionIDTable: + m.TableSection, err = decodeTableSection(r, enabledFeatures) + case wasm.SectionIDMemory: + m.MemorySection, err = decodeMemorySection(r, enabledFeatures, memSizer, memoryLimitPages) + case wasm.SectionIDGlobal: + if m.GlobalSection, err = decodeGlobalSection(r, enabledFeatures); err != nil { + return nil, err // avoid re-wrapping the error. + } + case wasm.SectionIDExport: + m.ExportSection, m.Exports, err = decodeExportSection(r) + case wasm.SectionIDStart: + if m.StartSection != nil { + return nil, errors.New("multiple start sections are invalid") + } + m.StartSection, err = decodeStartSection(r) + case wasm.SectionIDElement: + m.ElementSection, err = decodeElementSection(r, enabledFeatures) + case wasm.SectionIDCode: + m.CodeSection, err = decodeCodeSection(r) + case wasm.SectionIDData: + m.DataSection, err = decodeDataSection(r, enabledFeatures) + case wasm.SectionIDDataCount: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + return nil, fmt.Errorf("data count section not supported as %v", err) + } + m.DataCountSection, err = decodeDataCountSection(r) + default: + err = ErrInvalidSectionID + } + + readBytes := sectionContentStart - r.Len() + if err == nil && int(sectionSize) != readBytes { + err = fmt.Errorf("invalid section length: expected to be %d but got %d", sectionSize, readBytes) + } + + if err != nil { + return nil, fmt.Errorf("section %s: %v", wasm.SectionIDName(sectionID), err) + } + } + + if dwarfEnabled { + d, _ := dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str) + m.DWARFLines = wasmdebug.NewDWARFLines(d) + } + + functionCount, codeCount := m.SectionElementCount(wasm.SectionIDFunction), m.SectionElementCount(wasm.SectionIDCode) + if functionCount != codeCount { + return nil, fmt.Errorf("function and code section have inconsistent lengths: %d != %d", functionCount, codeCount) + } + return m, nil +} + +// memorySizer derives min, capacity and max pages from decoded wasm. +type memorySizer func(minPages uint32, maxPages *uint32) (min uint32, capacity uint32, max uint32) + +// newMemorySizer sets capacity to minPages unless max is defined and +// memoryCapacityFromMax is true. +func newMemorySizer(memoryLimitPages uint32, memoryCapacityFromMax bool) memorySizer { + return func(minPages uint32, maxPages *uint32) (min, capacity, max uint32) { + if maxPages != nil { + if memoryCapacityFromMax { + return minPages, *maxPages, *maxPages + } + // This is an invalid value: let it propagate, we will fail later. + if *maxPages > wasm.MemoryLimitPages { + return minPages, minPages, *maxPages + } + // This is a valid value, but it goes over the run-time limit: return the limit. + if *maxPages > memoryLimitPages { + return minPages, minPages, memoryLimitPages + } + return minPages, minPages, *maxPages + } + if memoryCapacityFromMax { + return minPages, memoryLimitPages, memoryLimitPages + } + return minPages, minPages, memoryLimitPages + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go new file mode 100644 index 00000000..7ab4b48e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go @@ -0,0 +1,269 @@ +package binary + +import ( + "bytes" + "errors" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func ensureElementKindFuncRef(r *bytes.Reader) error { + elemKind, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read element prefix: %w", err) + } + if elemKind != 0x0 { // ElemKind is fixed to 0x0 now: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section + return fmt.Errorf("element kind must be zero but was 0x%x", elemKind) + } + return nil +} + +func decodeElementInitValueVector(r *bytes.Reader) ([]wasm.Index, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + vec := make([]wasm.Index, vs) + for i := range vec { + u32, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("read function index: %w", err) + } + + if u32 >= wasm.MaximumFunctionIndex { + return nil, fmt.Errorf("too large function index in Element init: %d", u32) + } + vec[i] = u32 + } + return vec, nil +} + +func decodeElementConstExprVector(r *bytes.Reader, elemType wasm.RefType, enabledFeatures api.CoreFeatures) ([]wasm.Index, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("failed to get the size of constexpr vector: %w", err) + } + vec := make([]wasm.Index, vs) + for i := range vec { + var expr wasm.ConstantExpression + err := decodeConstantExpression(r, enabledFeatures, &expr) + if err != nil { + return nil, err + } + switch expr.Opcode { + case wasm.OpcodeRefFunc: + if elemType != wasm.RefTypeFuncref { + return nil, fmt.Errorf("element type mismatch: want %s, but constexpr has funcref", wasm.RefTypeName(elemType)) + } + v, _, _ := leb128.LoadUint32(expr.Data) + if v >= wasm.MaximumFunctionIndex { + return nil, fmt.Errorf("too large function index in Element init: %d", v) + } + vec[i] = v + case wasm.OpcodeRefNull: + if elemType != expr.Data[0] { + return nil, fmt.Errorf("element type mismatch: want %s, but constexpr has %s", + wasm.RefTypeName(elemType), wasm.RefTypeName(expr.Data[0])) + } + vec[i] = wasm.ElementInitNullReference + case wasm.OpcodeGlobalGet: + i32, _, _ := leb128.LoadInt32(expr.Data) + // Resolving the reference type from globals is done at instantiation phase. See the comment on + // wasm.elementInitImportedGlobalReferenceType. + vec[i] = wasm.WrapGlobalIndexAsElementInit(wasm.Index(i32)) + default: + return nil, fmt.Errorf("const expr must be either ref.null or ref.func but was %s", wasm.InstructionName(expr.Opcode)) + } + } + return vec, nil +} + +func decodeElementRefType(r *bytes.Reader) (ret wasm.RefType, err error) { + ret, err = r.ReadByte() + if err != nil { + err = fmt.Errorf("read element ref type: %w", err) + return + } + if ret != wasm.RefTypeFuncref && ret != wasm.RefTypeExternref { + return 0, errors.New("ref type must be funcref or externref for element as of WebAssembly 2.0") + } + return +} + +const ( + // The prefix is explained at https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section + + // elementSegmentPrefixLegacy is the legacy prefix and is only valid one before CoreFeatureBulkMemoryOperations. + elementSegmentPrefixLegacy = iota + // elementSegmentPrefixPassiveFuncrefValueVector is the passive element whose indexes are encoded as vec(varint), and reftype is fixed to funcref. + elementSegmentPrefixPassiveFuncrefValueVector + // elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex is the same as elementSegmentPrefixPassiveFuncrefValueVector but active and table index is encoded. + elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex + // elementSegmentPrefixDeclarativeFuncrefValueVector is the same as elementSegmentPrefixPassiveFuncrefValueVector but declarative. + elementSegmentPrefixDeclarativeFuncrefValueVector + // elementSegmentPrefixActiveFuncrefConstExprVector is active whoce reftype is fixed to funcref and indexes are encoded as vec(const_expr). + elementSegmentPrefixActiveFuncrefConstExprVector + // elementSegmentPrefixPassiveConstExprVector is passive whoce indexes are encoded as vec(const_expr), and reftype is encoded. + elementSegmentPrefixPassiveConstExprVector + // elementSegmentPrefixPassiveConstExprVector is active whoce indexes are encoded as vec(const_expr), and reftype and table index are encoded. + elementSegmentPrefixActiveConstExprVector + // elementSegmentPrefixDeclarativeConstExprVector is declarative whoce indexes are encoded as vec(const_expr), and reftype is encoded. + elementSegmentPrefixDeclarativeConstExprVector +) + +func decodeElementSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.ElementSegment) error { + prefix, _, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("read element prefix: %w", err) + } + + if prefix != elementSegmentPrefixLegacy { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + return fmt.Errorf("non-zero prefix for element segment is invalid as %w", err) + } + } + + // Encoding depends on the prefix and described at https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section + switch prefix { + case elementSegmentPrefixLegacy: + // Legacy prefix which is WebAssembly 1.0 compatible. + err = decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr) + if err != nil { + return fmt.Errorf("read expr for offset: %w", err) + } + + ret.Init, err = decodeElementInitValueVector(r) + if err != nil { + return err + } + + ret.Mode = wasm.ElementModeActive + ret.Type = wasm.RefTypeFuncref + return nil + case elementSegmentPrefixPassiveFuncrefValueVector: + // Prefix 1 requires funcref. + if err = ensureElementKindFuncRef(r); err != nil { + return err + } + + ret.Init, err = decodeElementInitValueVector(r) + if err != nil { + return err + } + ret.Mode = wasm.ElementModePassive + ret.Type = wasm.RefTypeFuncref + return nil + case elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex: + ret.TableIndex, _, err = leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("get size of vector: %w", err) + } + + if ret.TableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("table index must be zero but was %d: %w", ret.TableIndex, err) + } + } + + err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr) + if err != nil { + return fmt.Errorf("read expr for offset: %w", err) + } + + // Prefix 2 requires funcref. + if err = ensureElementKindFuncRef(r); err != nil { + return err + } + + ret.Init, err = decodeElementInitValueVector(r) + if err != nil { + return err + } + + ret.Mode = wasm.ElementModeActive + ret.Type = wasm.RefTypeFuncref + return nil + case elementSegmentPrefixDeclarativeFuncrefValueVector: + // Prefix 3 requires funcref. + if err = ensureElementKindFuncRef(r); err != nil { + return err + } + ret.Init, err = decodeElementInitValueVector(r) + if err != nil { + return err + } + ret.Type = wasm.RefTypeFuncref + ret.Mode = wasm.ElementModeDeclarative + return nil + case elementSegmentPrefixActiveFuncrefConstExprVector: + err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr) + if err != nil { + return fmt.Errorf("read expr for offset: %w", err) + } + + ret.Init, err = decodeElementConstExprVector(r, wasm.RefTypeFuncref, enabledFeatures) + if err != nil { + return err + } + ret.Mode = wasm.ElementModeActive + ret.Type = wasm.RefTypeFuncref + return nil + case elementSegmentPrefixPassiveConstExprVector: + ret.Type, err = decodeElementRefType(r) + if err != nil { + return err + } + ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures) + if err != nil { + return err + } + ret.Mode = wasm.ElementModePassive + return nil + case elementSegmentPrefixActiveConstExprVector: + ret.TableIndex, _, err = leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("get size of vector: %w", err) + } + + if ret.TableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("table index must be zero but was %d: %w", ret.TableIndex, err) + } + } + err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr) + if err != nil { + return fmt.Errorf("read expr for offset: %w", err) + } + + ret.Type, err = decodeElementRefType(r) + if err != nil { + return err + } + + ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures) + if err != nil { + return err + } + + ret.Mode = wasm.ElementModeActive + return nil + case elementSegmentPrefixDeclarativeConstExprVector: + ret.Type, err = decodeElementRefType(r) + if err != nil { + return err + } + ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures) + if err != nil { + return err + } + + ret.Mode = wasm.ElementModeDeclarative + return nil + default: + return fmt.Errorf("invalid element segment prefix: 0x%x", prefix) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go new file mode 100644 index 00000000..b9125b03 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go @@ -0,0 +1,11 @@ +package binary + +import "errors" + +var ( + ErrInvalidByte = errors.New("invalid byte") + ErrInvalidMagicNumber = errors.New("invalid magic number") + ErrInvalidVersion = errors.New("invalid version header") + ErrInvalidSectionID = errors.New("invalid section id") + ErrCustomSectionNotFound = errors.New("custom section not found") +) diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go new file mode 100644 index 00000000..925e9c49 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go @@ -0,0 +1,32 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeExport(r *bytes.Reader, ret *wasm.Export) (err error) { + if ret.Name, _, err = decodeUTF8(r, "export name"); err != nil { + return + } + + b, err := r.ReadByte() + if err != nil { + err = fmt.Errorf("error decoding export kind: %w", err) + return + } + + ret.Type = b + switch ret.Type { + case wasm.ExternTypeFunc, wasm.ExternTypeTable, wasm.ExternTypeMemory, wasm.ExternTypeGlobal: + if ret.Index, _, err = leb128.DecodeUint32(r); err != nil { + err = fmt.Errorf("error decoding export index: %w", err) + } + default: + err = fmt.Errorf("%w: invalid byte for exportdesc: %#x", ErrInvalidByte, b) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go new file mode 100644 index 00000000..bb9e2b64 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go @@ -0,0 +1,56 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeFunctionType(enabledFeatures api.CoreFeatures, r *bytes.Reader, ret *wasm.FunctionType) (err error) { + b, err := r.ReadByte() + if err != nil { + return fmt.Errorf("read leading byte: %w", err) + } + + if b != 0x60 { + return fmt.Errorf("%w: %#x != 0x60", ErrInvalidByte, b) + } + + paramCount, _, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("could not read parameter count: %w", err) + } + + paramTypes, err := decodeValueTypes(r, paramCount) + if err != nil { + return fmt.Errorf("could not read parameter types: %w", err) + } + + resultCount, _, err := leb128.DecodeUint32(r) + if err != nil { + return fmt.Errorf("could not read result count: %w", err) + } + + // Guard >1.0 feature multi-value + if resultCount > 1 { + if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil { + return fmt.Errorf("multiple result types invalid as %v", err) + } + } + + resultTypes, err := decodeValueTypes(r, resultCount) + if err != nil { + return fmt.Errorf("could not read result types: %w", err) + } + + ret.Params = paramTypes + ret.Results = resultTypes + + // cache the key for the function type + _ = ret.String() + + return nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go new file mode 100644 index 00000000..4e1c16fd --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go @@ -0,0 +1,50 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// decodeGlobal returns the api.Global decoded with the WebAssembly 1.0 (20191205) Binary Format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-global +func decodeGlobal(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.Global) (err error) { + ret.Type, err = decodeGlobalType(r) + if err != nil { + return err + } + + err = decodeConstantExpression(r, enabledFeatures, &ret.Init) + return +} + +// decodeGlobalType returns the wasm.GlobalType decoded with the WebAssembly 1.0 (20191205) Binary Format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-globaltype +func decodeGlobalType(r *bytes.Reader) (wasm.GlobalType, error) { + vt, err := decodeValueTypes(r, 1) + if err != nil { + return wasm.GlobalType{}, fmt.Errorf("read value type: %w", err) + } + + ret := wasm.GlobalType{ + ValType: vt[0], + } + + b, err := r.ReadByte() + if err != nil { + return wasm.GlobalType{}, fmt.Errorf("read mutablity: %w", err) + } + + switch mut := b; mut { + case 0x00: // not mutable + case 0x01: // mutable + ret.Mutable = true + default: + return wasm.GlobalType{}, fmt.Errorf("%w for mutability: %#x != 0x00 or 0x01", ErrInvalidByte, mut) + } + return ret, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go new file mode 100644 index 00000000..29ba1b59 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go @@ -0,0 +1,9 @@ +package binary + +// Magic is the 4 byte preamble (literally "\0asm") of the binary format +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-magic +var Magic = []byte{0x00, 0x61, 0x73, 0x6D} + +// version is format version and doesn't change between known specification versions +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-version +var version = []byte{0x01, 0x00, 0x00, 0x00} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go new file mode 100644 index 00000000..39d310c5 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go @@ -0,0 +1,52 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeImport( + r *bytes.Reader, + idx uint32, + memorySizer memorySizer, + memoryLimitPages uint32, + enabledFeatures api.CoreFeatures, + ret *wasm.Import, +) (err error) { + if ret.Module, _, err = decodeUTF8(r, "import module"); err != nil { + err = fmt.Errorf("import[%d] error decoding module: %w", idx, err) + return + } + + if ret.Name, _, err = decodeUTF8(r, "import name"); err != nil { + err = fmt.Errorf("import[%d] error decoding name: %w", idx, err) + return + } + + b, err := r.ReadByte() + if err != nil { + err = fmt.Errorf("import[%d] error decoding type: %w", idx, err) + return + } + ret.Type = b + switch ret.Type { + case wasm.ExternTypeFunc: + ret.DescFunc, _, err = leb128.DecodeUint32(r) + case wasm.ExternTypeTable: + err = decodeTable(r, enabledFeatures, &ret.DescTable) + case wasm.ExternTypeMemory: + ret.DescMem, err = decodeMemory(r, enabledFeatures, memorySizer, memoryLimitPages) + case wasm.ExternTypeGlobal: + ret.DescGlobal, err = decodeGlobalType(r) + default: + err = fmt.Errorf("%w: invalid byte for importdesc: %#x", ErrInvalidByte, b) + } + if err != nil { + err = fmt.Errorf("import[%d] %s[%s.%s]: %w", idx, wasm.ExternTypeName(ret.Type), ret.Module, ret.Name, err) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go new file mode 100644 index 00000000..ff2d73b5 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go @@ -0,0 +1,47 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/internal/leb128" +) + +// decodeLimitsType returns the `limitsType` (min, max) decoded with the WebAssembly 1.0 (20191205) Binary Format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#limits%E2%91%A6 +// +// Extended in threads proposal: https://webassembly.github.io/threads/core/binary/types.html#limits +func decodeLimitsType(r *bytes.Reader) (min uint32, max *uint32, shared bool, err error) { + var flag byte + if flag, err = r.ReadByte(); err != nil { + err = fmt.Errorf("read leading byte: %v", err) + return + } + + switch flag { + case 0x00, 0x02: + min, _, err = leb128.DecodeUint32(r) + if err != nil { + err = fmt.Errorf("read min of limit: %v", err) + } + case 0x01, 0x03: + min, _, err = leb128.DecodeUint32(r) + if err != nil { + err = fmt.Errorf("read min of limit: %v", err) + return + } + var m uint32 + if m, _, err = leb128.DecodeUint32(r); err != nil { + err = fmt.Errorf("read max of limit: %v", err) + } else { + max = &m + } + default: + err = fmt.Errorf("%v for limits: %#x not in (0x00, 0x01, 0x02, 0x03)", ErrInvalidByte, flag) + } + + shared = flag == 0x02 || flag == 0x03 + + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go new file mode 100644 index 00000000..e1b17512 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go @@ -0,0 +1,42 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// decodeMemory returns the api.Memory decoded with the WebAssembly 1.0 (20191205) Binary Format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-memory +func decodeMemory( + r *bytes.Reader, + enabledFeatures api.CoreFeatures, + memorySizer func(minPages uint32, maxPages *uint32) (min, capacity, max uint32), + memoryLimitPages uint32, +) (*wasm.Memory, error) { + min, maxP, shared, err := decodeLimitsType(r) + if err != nil { + return nil, err + } + + if shared { + if !enabledFeatures.IsEnabled(experimental.CoreFeaturesThreads) { + return nil, fmt.Errorf("shared memory requested but threads feature not enabled") + } + + // This restriction may be lifted in the future. + // https://webassembly.github.io/threads/core/binary/types.html#memory-types + if maxP == nil { + return nil, fmt.Errorf("shared memory requires a maximum size to be specified") + } + } + + min, capacity, max := memorySizer(min, maxP) + mem := &wasm.Memory{Min: min, Cap: capacity, Max: max, IsMaxEncoded: maxP != nil, IsShared: shared} + + return mem, mem.Validate(memoryLimitPages) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go new file mode 100644 index 00000000..56fb96dc --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go @@ -0,0 +1,151 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +const ( + // subsectionIDModuleName contains only the module name. + subsectionIDModuleName = uint8(0) + // subsectionIDFunctionNames is a map of indices to function names, in ascending order by function index + subsectionIDFunctionNames = uint8(1) + // subsectionIDLocalNames contain a map of function indices to a map of local indices to their names, in ascending + // order by function and local index + subsectionIDLocalNames = uint8(2) +) + +// decodeNameSection deserializes the data associated with the "name" key in SectionIDCustom according to the +// standard: +// +// * ModuleName decode from subsection 0 +// * FunctionNames decode from subsection 1 +// * LocalNames decode from subsection 2 +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namesec +func decodeNameSection(r *bytes.Reader, limit uint64) (result *wasm.NameSection, err error) { + // TODO: add leb128 functions that work on []byte and offset. While using a reader allows us to reuse reader-based + // leb128 functions, it is less efficient, causes untestable code and in some cases more complex vs plain []byte. + result = &wasm.NameSection{} + + // subsectionID is decoded if known, and skipped if not + var subsectionID uint8 + // subsectionSize is the length to skip when the subsectionID is unknown + var subsectionSize uint32 + var bytesRead uint64 + for limit > 0 { + if subsectionID, err = r.ReadByte(); err != nil { + if err == io.EOF { + return result, nil + } + // TODO: untestable as this can't fail for a reason beside EOF reading a byte from a buffer + return nil, fmt.Errorf("failed to read a subsection ID: %w", err) + } + limit-- + + if subsectionSize, bytesRead, err = leb128.DecodeUint32(r); err != nil { + return nil, fmt.Errorf("failed to read the size of subsection[%d]: %w", subsectionID, err) + } + limit -= bytesRead + + switch subsectionID { + case subsectionIDModuleName: + if result.ModuleName, _, err = decodeUTF8(r, "module name"); err != nil { + return nil, err + } + case subsectionIDFunctionNames: + if result.FunctionNames, err = decodeFunctionNames(r); err != nil { + return nil, err + } + case subsectionIDLocalNames: + if result.LocalNames, err = decodeLocalNames(r); err != nil { + return nil, err + } + default: // Skip other subsections. + // Note: Not Seek because it doesn't err when given an offset past EOF. Rather, it leads to undefined state. + if _, err = io.CopyN(io.Discard, r, int64(subsectionSize)); err != nil { + return nil, fmt.Errorf("failed to skip subsection[%d]: %w", subsectionID, err) + } + } + limit -= uint64(subsectionSize) + } + return +} + +func decodeFunctionNames(r *bytes.Reader) (wasm.NameMap, error) { + functionCount, err := decodeFunctionCount(r, subsectionIDFunctionNames) + if err != nil { + return nil, err + } + + result := make(wasm.NameMap, functionCount) + for i := uint32(0); i < functionCount; i++ { + functionIndex, err := decodeFunctionIndex(r, subsectionIDFunctionNames) + if err != nil { + return nil, err + } + + name, _, err := decodeUTF8(r, "function[%d] name", functionIndex) + if err != nil { + return nil, err + } + result[i] = wasm.NameAssoc{Index: functionIndex, Name: name} + } + return result, nil +} + +func decodeLocalNames(r *bytes.Reader) (wasm.IndirectNameMap, error) { + functionCount, err := decodeFunctionCount(r, subsectionIDLocalNames) + if err != nil { + return nil, err + } + + result := make(wasm.IndirectNameMap, functionCount) + for i := uint32(0); i < functionCount; i++ { + functionIndex, err := decodeFunctionIndex(r, subsectionIDLocalNames) + if err != nil { + return nil, err + } + + localCount, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("failed to read the local count for function[%d]: %w", functionIndex, err) + } + + locals := make(wasm.NameMap, localCount) + for j := uint32(0); j < localCount; j++ { + localIndex, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("failed to read a local index of function[%d]: %w", functionIndex, err) + } + + name, _, err := decodeUTF8(r, "function[%d] local[%d] name", functionIndex, localIndex) + if err != nil { + return nil, err + } + locals[j] = wasm.NameAssoc{Index: localIndex, Name: name} + } + result[i] = wasm.NameMapAssoc{Index: functionIndex, NameMap: locals} + } + return result, nil +} + +func decodeFunctionIndex(r *bytes.Reader, subsectionID uint8) (uint32, error) { + functionIndex, _, err := leb128.DecodeUint32(r) + if err != nil { + return 0, fmt.Errorf("failed to read a function index in subsection[%d]: %w", subsectionID, err) + } + return functionIndex, nil +} + +func decodeFunctionCount(r *bytes.Reader, subsectionID uint8) (uint32, error) { + functionCount, _, err := leb128.DecodeUint32(r) + if err != nil { + return 0, fmt.Errorf("failed to read the function count of subsection[%d]: %w", subsectionID, err) + } + return functionCount, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go new file mode 100644 index 00000000..622ee592 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go @@ -0,0 +1,226 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeTypeSection(enabledFeatures api.CoreFeatures, r *bytes.Reader) ([]wasm.FunctionType, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]wasm.FunctionType, vs) + for i := uint32(0); i < vs; i++ { + if err = decodeFunctionType(enabledFeatures, r, &result[i]); err != nil { + return nil, fmt.Errorf("read %d-th type: %v", i, err) + } + } + return result, nil +} + +// decodeImportSection decodes the decoded import segments plus the count per wasm.ExternType. +func decodeImportSection( + r *bytes.Reader, + memorySizer memorySizer, + memoryLimitPages uint32, + enabledFeatures api.CoreFeatures, +) (result []wasm.Import, + perModule map[string][]*wasm.Import, + funcCount, globalCount, memoryCount, tableCount wasm.Index, err error, +) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + err = fmt.Errorf("get size of vector: %w", err) + return + } + + perModule = make(map[string][]*wasm.Import) + result = make([]wasm.Import, vs) + for i := uint32(0); i < vs; i++ { + imp := &result[i] + if err = decodeImport(r, i, memorySizer, memoryLimitPages, enabledFeatures, imp); err != nil { + return + } + switch imp.Type { + case wasm.ExternTypeFunc: + imp.IndexPerType = funcCount + funcCount++ + case wasm.ExternTypeGlobal: + imp.IndexPerType = globalCount + globalCount++ + case wasm.ExternTypeMemory: + imp.IndexPerType = memoryCount + memoryCount++ + case wasm.ExternTypeTable: + imp.IndexPerType = tableCount + tableCount++ + } + perModule[imp.Module] = append(perModule[imp.Module], imp) + } + return +} + +func decodeFunctionSection(r *bytes.Reader) ([]uint32, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]uint32, vs) + for i := uint32(0); i < vs; i++ { + if result[i], _, err = leb128.DecodeUint32(r); err != nil { + return nil, fmt.Errorf("get type index: %w", err) + } + } + return result, err +} + +func decodeTableSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Table, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("error reading size") + } + if vs > 1 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return nil, fmt.Errorf("at most one table allowed in module as %w", err) + } + } + + ret := make([]wasm.Table, vs) + for i := range ret { + err = decodeTable(r, enabledFeatures, &ret[i]) + if err != nil { + return nil, err + } + } + return ret, nil +} + +func decodeMemorySection( + r *bytes.Reader, + enabledFeatures api.CoreFeatures, + memorySizer memorySizer, + memoryLimitPages uint32, +) (*wasm.Memory, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("error reading size") + } + if vs > 1 { + return nil, fmt.Errorf("at most one memory allowed in module, but read %d", vs) + } else if vs == 0 { + // memory count can be zero. + return nil, nil + } + + return decodeMemory(r, enabledFeatures, memorySizer, memoryLimitPages) +} + +func decodeGlobalSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Global, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]wasm.Global, vs) + for i := uint32(0); i < vs; i++ { + if err = decodeGlobal(r, enabledFeatures, &result[i]); err != nil { + return nil, fmt.Errorf("global[%d]: %w", i, err) + } + } + return result, nil +} + +func decodeExportSection(r *bytes.Reader) ([]wasm.Export, map[string]*wasm.Export, error) { + vs, _, sizeErr := leb128.DecodeUint32(r) + if sizeErr != nil { + return nil, nil, fmt.Errorf("get size of vector: %v", sizeErr) + } + + exportMap := make(map[string]*wasm.Export, vs) + exportSection := make([]wasm.Export, vs) + for i := wasm.Index(0); i < vs; i++ { + export := &exportSection[i] + err := decodeExport(r, export) + if err != nil { + return nil, nil, fmt.Errorf("read export: %w", err) + } + if _, ok := exportMap[export.Name]; ok { + return nil, nil, fmt.Errorf("export[%d] duplicates name %q", i, export.Name) + } else { + exportMap[export.Name] = export + } + } + return exportSection, exportMap, nil +} + +func decodeStartSection(r *bytes.Reader) (*wasm.Index, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get function index: %w", err) + } + return &vs, nil +} + +func decodeElementSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.ElementSegment, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]wasm.ElementSegment, vs) + for i := uint32(0); i < vs; i++ { + if err = decodeElementSegment(r, enabledFeatures, &result[i]); err != nil { + return nil, fmt.Errorf("read element: %w", err) + } + } + return result, nil +} + +func decodeCodeSection(r *bytes.Reader) ([]wasm.Code, error) { + codeSectionStart := uint64(r.Len()) + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]wasm.Code, vs) + for i := uint32(0); i < vs; i++ { + err = decodeCode(r, codeSectionStart, &result[i]) + if err != nil { + return nil, fmt.Errorf("read %d-th code segment: %v", i, err) + } + } + return result, nil +} + +func decodeDataSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.DataSegment, error) { + vs, _, err := leb128.DecodeUint32(r) + if err != nil { + return nil, fmt.Errorf("get size of vector: %w", err) + } + + result := make([]wasm.DataSegment, vs) + for i := uint32(0); i < vs; i++ { + if err = decodeDataSegment(r, enabledFeatures, &result[i]); err != nil { + return nil, fmt.Errorf("read data segment: %w", err) + } + } + return result, nil +} + +func decodeDataCountSection(r *bytes.Reader) (count *uint32, err error) { + v, _, err := leb128.DecodeUint32(r) + if err != nil && err != io.EOF { + // data count is optional, so EOF is fine. + return nil, err + } + return &v, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go new file mode 100644 index 00000000..353ec756 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go @@ -0,0 +1,43 @@ +package binary + +import ( + "bytes" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" +) + +// decodeTable returns the wasm.Table decoded with the WebAssembly 1.0 (20191205) Binary Format. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-table +func decodeTable(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.Table) (err error) { + ret.Type, err = r.ReadByte() + if err != nil { + return fmt.Errorf("read leading byte: %v", err) + } + + if ret.Type != wasm.RefTypeFuncref { + if err = enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("table type funcref is invalid: %w", err) + } + } + + var shared bool + ret.Min, ret.Max, shared, err = decodeLimitsType(r) + if err != nil { + return fmt.Errorf("read limits: %v", err) + } + if ret.Min > wasm.MaximumFunctionIndex { + return fmt.Errorf("table min must be at most %d", wasm.MaximumFunctionIndex) + } + if ret.Max != nil { + if *ret.Max < ret.Min { + return fmt.Errorf("table size minimum must not be greater than maximum") + } + } + if shared { + return fmt.Errorf("tables cannot be marked as shared") + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go new file mode 100644 index 00000000..dfc4417e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go @@ -0,0 +1,59 @@ +package binary + +import ( + "bytes" + "fmt" + "io" + "unicode/utf8" + "unsafe" + + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasm" +) + +func decodeValueTypes(r *bytes.Reader, num uint32) ([]wasm.ValueType, error) { + if num == 0 { + return nil, nil + } + + ret := make([]wasm.ValueType, num) + _, err := io.ReadFull(r, ret) + if err != nil { + return nil, err + } + + for _, v := range ret { + switch v { + case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64, + wasm.ValueTypeExternref, wasm.ValueTypeFuncref, wasm.ValueTypeV128: + default: + return nil, fmt.Errorf("invalid value type: %d", v) + } + } + return ret, nil +} + +// decodeUTF8 decodes a size prefixed string from the reader, returning it and the count of bytes read. +// contextFormat and contextArgs apply an error format when present +func decodeUTF8(r *bytes.Reader, contextFormat string, contextArgs ...interface{}) (string, uint32, error) { + size, sizeOfSize, err := leb128.DecodeUint32(r) + if err != nil { + return "", 0, fmt.Errorf("failed to read %s size: %w", fmt.Sprintf(contextFormat, contextArgs...), err) + } + + if size == 0 { + return "", uint32(sizeOfSize), nil + } + + buf := make([]byte, size) + if _, err = io.ReadFull(r, buf); err != nil { + return "", 0, fmt.Errorf("failed to read %s: %w", fmt.Sprintf(contextFormat, contextArgs...), err) + } + + if !utf8.Valid(buf) { + return "", 0, fmt.Errorf("%s is not valid UTF-8", fmt.Sprintf(contextFormat, contextArgs...)) + } + + ret := unsafe.String(&buf[0], int(size)) + return ret, size + uint32(sizeOfSize), nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go new file mode 100644 index 00000000..685a4094 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go @@ -0,0 +1,51 @@ +package wasm + +import "fmt" + +// SectionElementCount returns the count of elements in a given section ID +// +// For example... +// * SectionIDType returns the count of FunctionType +// * SectionIDCustom returns the count of CustomSections plus one if NameSection is present +// * SectionIDHostFunction returns the count of HostFunctionSection +// * SectionIDExport returns the count of unique export names +func (m *Module) SectionElementCount(sectionID SectionID) uint32 { // element as in vector elements! + switch sectionID { + case SectionIDCustom: + numCustomSections := uint32(len(m.CustomSections)) + if m.NameSection != nil { + numCustomSections++ + } + return numCustomSections + case SectionIDType: + return uint32(len(m.TypeSection)) + case SectionIDImport: + return uint32(len(m.ImportSection)) + case SectionIDFunction: + return uint32(len(m.FunctionSection)) + case SectionIDTable: + return uint32(len(m.TableSection)) + case SectionIDMemory: + if m.MemorySection != nil { + return 1 + } + return 0 + case SectionIDGlobal: + return uint32(len(m.GlobalSection)) + case SectionIDExport: + return uint32(len(m.ExportSection)) + case SectionIDStart: + if m.StartSection != nil { + return 1 + } + return 0 + case SectionIDElement: + return uint32(len(m.ElementSection)) + case SectionIDCode: + return uint32(len(m.CodeSection)) + case SectionIDData: + return uint32(len(m.DataSection)) + default: + panic(fmt.Errorf("BUG: unknown section: %d", sectionID)) + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go new file mode 100644 index 00000000..8c387e9e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go @@ -0,0 +1,76 @@ +package wasm + +import ( + "context" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" +) + +// Engine is a Store-scoped mechanism to compile functions declared or imported by a module. +// This is a top-level type implemented by an interpreter or compiler. +type Engine interface { + // Close closes this engine, and releases all the compiled cache. + Close() (err error) + + // CompileModule implements the same method as documented on wasm.Engine. + CompileModule(ctx context.Context, module *Module, listeners []experimental.FunctionListener, ensureTermination bool) error + + // CompiledModuleCount is exported for testing, to track the size of the compilation cache. + CompiledModuleCount() uint32 + + // DeleteCompiledModule releases compilation caches for the given module (source). + // Note: it is safe to call this function for a module from which module instances are instantiated even when these + // module instances have outstanding calls. + DeleteCompiledModule(module *Module) + + // NewModuleEngine compiles down the function instances in a module, and returns ModuleEngine for the module. + // + // * module is the source module from which moduleFunctions are instantiated. This is used for caching. + // * instance is the *ModuleInstance which is created from `module`. + // + // Note: Input parameters must be pre-validated with wasm.Module Validate, to ensure no fields are invalid + // due to reasons such as out-of-bounds. + NewModuleEngine(module *Module, instance *ModuleInstance) (ModuleEngine, error) +} + +// ModuleEngine implements function calls for a given module. +type ModuleEngine interface { + // DoneInstantiation is called at the end of the instantiation of the module. + DoneInstantiation() + + // NewFunction returns an api.Function for the given function pointed by the given Index. + NewFunction(index Index) api.Function + + // ResolveImportedFunction is used to add imported functions needed to make this ModuleEngine fully functional. + // - `index` is the function Index of this imported function. + // - `descFunc` is the type Index in Module.TypeSection of this imported function. It corresponds to Import.DescFunc. + // - `indexInImportedModule` is the function Index of the imported function in the imported module. + // - `importedModuleEngine` is the ModuleEngine for the imported ModuleInstance. + ResolveImportedFunction(index, descFunc, indexInImportedModule Index, importedModuleEngine ModuleEngine) + + // ResolveImportedMemory is called when this module imports a memory from another module. + ResolveImportedMemory(importedModuleEngine ModuleEngine) + + // LookupFunction returns the FunctionModule and the Index of the function in the returned ModuleInstance at the given offset in the table. + LookupFunction(t *TableInstance, typeId FunctionTypeID, tableOffset Index) (*ModuleInstance, Index) + + // GetGlobalValue returns the value of the global variable at the given Index. + // Only called when OwnsGlobals() returns true, and must not be called for imported globals + GetGlobalValue(idx Index) (lo, hi uint64) + + // SetGlobalValue sets the value of the global variable at the given Index. + // Only called when OwnsGlobals() returns true, and must not be called for imported globals + SetGlobalValue(idx Index, lo, hi uint64) + + // OwnsGlobals returns true if this ModuleEngine owns the global variables. If true, wasm.GlobalInstance's Val,ValHi should + // not be accessed directly. + OwnsGlobals() bool + + // FunctionInstanceReference returns Reference for the given Index for a FunctionInstance. The returned values are used by + // the initialization via ElementSegment. + FunctionInstanceReference(funcIndex Index) Reference + + // MemoryGrown notifies the engine that the memory has grown. + MemoryGrown() +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go new file mode 100644 index 00000000..60448922 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go @@ -0,0 +1,2336 @@ +package wasm + +import ( + "bytes" + "errors" + "fmt" + "strconv" + "strings" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/leb128" +) + +// The wazero specific limitation described at RATIONALE.md. +const maximumValuesOnStack = 1 << 27 + +// validateFunction validates the instruction sequence of a function. +// following the specification https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#instructions%E2%91%A2. +// +// * idx is the index in the FunctionSection +// * functions are the function index, which is prefixed by imports. The value is the TypeSection index. +// * globals are the global index, which is prefixed by imports. +// * memory is the potentially imported memory and can be nil. +// * table is the potentially imported table and can be nil. +// * declaredFunctionIndexes is the set of function indexes declared by declarative element segments which can be acceed by OpcodeRefFunc instruction. +// +// Returns an error if the instruction sequence is not valid, +// or potentially it can exceed the maximum number of values on the stack. +func (m *Module) validateFunction(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index, + globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader, +) error { + return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br) +} + +func readMemArg(pc uint64, body []byte) (align, offset uint32, read uint64, err error) { + align, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + err = fmt.Errorf("read memory align: %v", err) + return + } + read += num + + offset, num, err = leb128.LoadUint32(body[pc+num:]) + if err != nil { + err = fmt.Errorf("read memory offset: %v", err) + return + } + + read += num + return align, offset, read, nil +} + +// validateFunctionWithMaxStackValues is like validateFunction, but allows overriding maxStackValues for testing. +// +// * stacks is to track the state of Wasm value and control frame stacks at anypoint of execution, and reused to reduce allocation. +// * maxStackValues is the maximum height of values stack which the target is allowed to reach. +func (m *Module) validateFunctionWithMaxStackValues( + sts *stacks, + enabledFeatures api.CoreFeatures, + idx Index, + functions []Index, + globals []GlobalType, + memory *Memory, + tables []Table, + maxStackValues int, + declaredFunctionIndexes map[Index]struct{}, + br *bytes.Reader, +) error { + functionType := &m.TypeSection[m.FunctionSection[idx]] + code := &m.CodeSection[idx] + body := code.Body + localTypes := code.LocalTypes + + sts.reset(functionType) + valueTypeStack := &sts.vs + // We start with the outermost control block which is for function return if the code branches into it. + controlBlockStack := &sts.cs + + // Now start walking through all the instructions in the body while tracking + // control blocks and value types to check the validity of all instructions. + for pc := uint64(0); pc < uint64(len(body)); pc++ { + op := body[pc] + if false { + var instName string + if op == OpcodeMiscPrefix { + instName = MiscInstructionName(body[pc+1]) + } else if op == OpcodeVecPrefix { + instName = VectorInstructionName(body[pc+1]) + } else if op == OpcodeAtomicPrefix { + instName = AtomicInstructionName(body[pc+1]) + } else { + instName = InstructionName(op) + } + fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack) + } + + if len(controlBlockStack.stack) == 0 { + return fmt.Errorf("unexpected end of function at pc=%#x", pc) + } + + if OpcodeI32Load <= op && op <= OpcodeI64Store32 { + if memory == nil { + return fmt.Errorf("memory must exist for %s", InstructionName(op)) + } + pc++ + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + pc += read - 1 + switch op { + case OpcodeI32Load: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeF32Load: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeF32) + case OpcodeI32Store: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeF32Store: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI64Load: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeF64Load: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeF64) + case OpcodeI64Store: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeF64Store: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI32Load8S: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32Load8U: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Load8S, OpcodeI64Load8U: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI32Store8: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI64Store8: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI32Load16S, OpcodeI32Load16U: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Load16S, OpcodeI64Load16U: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI32Store16: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI64Store16: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeI64Load32S, OpcodeI64Load32U: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI64Store32: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + } + } else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow { + if memory == nil { + return fmt.Errorf("memory must exist for %s", InstructionName(op)) + } + pc++ + val, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } + if val != 0 || num != 1 { + return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte") + } + switch Opcode(op) { + case OpcodeMemoryGrow: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeMemorySize: + valueTypeStack.push(ValueTypeI32) + } + pc += num - 1 + } else if OpcodeI32Const <= op && op <= OpcodeF64Const { + pc++ + switch Opcode(op) { + case OpcodeI32Const: + _, num, err := leb128.LoadInt32(body[pc:]) + if err != nil { + return fmt.Errorf("read i32 immediate: %s", err) + } + pc += num - 1 + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Const: + _, num, err := leb128.LoadInt64(body[pc:]) + if err != nil { + return fmt.Errorf("read i64 immediate: %v", err) + } + valueTypeStack.push(ValueTypeI64) + pc += num - 1 + case OpcodeF32Const: + valueTypeStack.push(ValueTypeF32) + pc += 3 + case OpcodeF64Const: + valueTypeStack.push(ValueTypeF64) + pc += 7 + } + } else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet { + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } + pc += num - 1 + switch op { + case OpcodeLocalGet: + inputLen := uint32(len(functionType.Params)) + if l := uint32(len(localTypes)) + inputLen; index >= l { + return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))", + OpcodeLocalGetName, index, l) + } + if index < inputLen { + valueTypeStack.push(functionType.Params[index]) + } else { + valueTypeStack.push(localTypes[index-inputLen]) + } + case OpcodeLocalSet: + inputLen := uint32(len(functionType.Params)) + if l := uint32(len(localTypes)) + inputLen; index >= l { + return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))", + OpcodeLocalSetName, index, l) + } + var expType ValueType + if index < inputLen { + expType = functionType.Params[index] + } else { + expType = localTypes[index-inputLen] + } + if err := valueTypeStack.popAndVerifyType(expType); err != nil { + return err + } + case OpcodeLocalTee: + inputLen := uint32(len(functionType.Params)) + if l := uint32(len(localTypes)) + inputLen; index >= l { + return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))", + OpcodeLocalTeeName, index, l) + } + var expType ValueType + if index < inputLen { + expType = functionType.Params[index] + } else { + expType = localTypes[index-inputLen] + } + if err := valueTypeStack.popAndVerifyType(expType); err != nil { + return err + } + valueTypeStack.push(expType) + case OpcodeGlobalGet: + if index >= uint32(len(globals)) { + return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName) + } + valueTypeStack.push(globals[index].ValType) + case OpcodeGlobalSet: + if index >= uint32(len(globals)) { + return fmt.Errorf("invalid global index") + } else if !globals[index].Mutable { + return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName) + } else if err := valueTypeStack.popAndVerifyType( + globals[index].ValType); err != nil { + return err + } + } + } else if op == OpcodeBr { + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } else if int(index) >= len(controlBlockStack.stack) { + return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName) + } + pc += num - 1 + // Check type soundness. + target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1] + var targetResultType []ValueType + if target.op == OpcodeLoop { + targetResultType = target.blockType.Params + } else { + targetResultType = target.blockType.Results + } + if err = valueTypeStack.popResults(op, targetResultType, false); err != nil { + return err + } + // br instruction is stack-polymorphic. + valueTypeStack.unreachable() + } else if op == OpcodeBrIf { + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } else if int(index) >= len(controlBlockStack.stack) { + return fmt.Errorf( + "invalid ln param given for %s: index=%d with %d for the current label stack length", + OpcodeBrIfName, index, len(controlBlockStack.stack)) + } + pc += num - 1 + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName) + } + // Check type soundness. + target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1] + var targetResultType []ValueType + if target.op == OpcodeLoop { + targetResultType = target.blockType.Params + } else { + targetResultType = target.blockType.Results + } + if err := valueTypeStack.popResults(op, targetResultType, false); err != nil { + return err + } + // Push back the result + for _, t := range targetResultType { + valueTypeStack.push(t) + } + } else if op == OpcodeBrTable { + pc++ + br.Reset(body[pc:]) + nl, num, err := leb128.DecodeUint32(br) + if err != nil { + return fmt.Errorf("read immediate: %w", err) + } + + sts.ls = sts.ls[:0] + for i := uint32(0); i < nl; i++ { + l, n, err := leb128.DecodeUint32(br) + if err != nil { + return fmt.Errorf("read immediate: %w", err) + } + num += n + sts.ls = append(sts.ls, l) + } + ln, n, err := leb128.DecodeUint32(br) + if err != nil { + return fmt.Errorf("read immediate: %w", err) + } else if int(ln) >= len(controlBlockStack.stack) { + return fmt.Errorf( + "invalid ln param given for %s: ln=%d with %d for the current label stack length", + OpcodeBrTableName, ln, len(controlBlockStack.stack)) + } + pc += n + num - 1 + // Check type soundness. + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName) + } + lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)] + var defaultLabelType []ValueType + // Below, we might modify the slice in case of unreachable. Therefore, + // we have to copy the content of block result types, otherwise the original + // function type might result in invalid value types if the block is the outermost label + // which equals the function's type. + if lnLabel.op != OpcodeLoop { // Loop operation doesn't require results since the continuation is the beginning of the loop. + defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results)) + copy(defaultLabelType, lnLabel.blockType.Results) + } else { + defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params)) + copy(defaultLabelType, lnLabel.blockType.Params) + } + + if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) { + // As of reference-types proposal, br_table on unreachable state + // can choose unknown types for expected parameter types for each label. + // https://github.com/WebAssembly/reference-types/pull/116 + for i := range defaultLabelType { + index := len(defaultLabelType) - 1 - i + exp := defaultLabelType[index] + actual, err := valueTypeStack.pop() + if err != nil { + return err + } + if actual == valueTypeUnknown { + // Re-assign the expected type to unknown. + defaultLabelType[index] = valueTypeUnknown + } else if actual != exp { + return typeMismatchError(true, OpcodeBrTableName, actual, exp, i) + } + } + } else { + if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil { + return err + } + } + + for _, l := range sts.ls { + if int(l) >= len(controlBlockStack.stack) { + return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName) + } + label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)] + var tableLabelType []ValueType + if label.op != OpcodeLoop { + tableLabelType = label.blockType.Results + } else { + tableLabelType = label.blockType.Params + } + if len(defaultLabelType) != len(tableLabelType) { + return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l) + } + for i := range defaultLabelType { + if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] { + return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l) + } + } + } + + // br_table instruction is stack-polymorphic. + valueTypeStack.unreachable() + } else if op == OpcodeCall { + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } + pc += num - 1 + if int(index) >= len(functions) { + return fmt.Errorf("invalid function index") + } + funcType := &m.TypeSection[functions[index]] + for i := 0; i < len(funcType.Params); i++ { + if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil { + return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err) + } + } + for _, exp := range funcType.Results { + valueTypeStack.push(exp) + } + } else if op == OpcodeCallIndirect { + pc++ + typeIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } + pc += num + + if int(typeIndex) >= len(m.TypeSection) { + return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex) + } + + tableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read table index: %v", err) + } + pc += num - 1 + if tableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err) + } + } + + if tableIndex >= uint32(len(tables)) { + return fmt.Errorf("unknown table index: %d", tableIndex) + } + + table := tables[tableIndex] + if table.Type != RefTypeFuncref { + return fmt.Errorf("table is not funcref type but was %s for %s", RefTypeName(table.Type), OpcodeCallIndirectName) + } + + if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the offset in table for %s", OpcodeCallIndirectName) + } + funcType := &m.TypeSection[typeIndex] + for i := 0; i < len(funcType.Params); i++ { + if err = valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil { + return fmt.Errorf("type mismatch on %s operation input type", OpcodeCallIndirectName) + } + } + for _, exp := range funcType.Results { + valueTypeStack.push(exp) + } + } else if OpcodeI32Eqz <= op && op <= OpcodeI64Extend32S { + switch op { + case OpcodeI32Eqz: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32EqzName, err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32Eq, OpcodeI32Ne, OpcodeI32LtS, + OpcodeI32LtU, OpcodeI32GtS, OpcodeI32GtU, OpcodeI32LeS, + OpcodeI32LeU, OpcodeI32GeS, OpcodeI32GeU: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the 1st i32 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the 2nd i32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Eqz: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64EqzName, err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Eq, OpcodeI64Ne, OpcodeI64LtS, + OpcodeI64LtU, OpcodeI64GtS, OpcodeI64GtU, + OpcodeI64LeS, OpcodeI64LeU, OpcodeI64GeS, OpcodeI64GeU: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeF32Eq, OpcodeF32Ne, OpcodeF32Lt, OpcodeF32Gt, OpcodeF32Le, OpcodeF32Ge: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeF64Eq, OpcodeF64Ne, OpcodeF64Lt, OpcodeF64Gt, OpcodeF64Le, OpcodeF64Ge: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32Clz, OpcodeI32Ctz, OpcodeI32Popcnt: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32Add, OpcodeI32Sub, OpcodeI32Mul, OpcodeI32DivS, + OpcodeI32DivU, OpcodeI32RemS, OpcodeI32RemU, OpcodeI32And, + OpcodeI32Or, OpcodeI32Xor, OpcodeI32Shl, OpcodeI32ShrS, + OpcodeI32ShrU, OpcodeI32Rotl, OpcodeI32Rotr: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the 1st operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the 2nd operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Clz, OpcodeI64Ctz, OpcodeI64Popcnt: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI64Add, OpcodeI64Sub, OpcodeI64Mul, OpcodeI64DivS, + OpcodeI64DivU, OpcodeI64RemS, OpcodeI64RemU, OpcodeI64And, + OpcodeI64Or, OpcodeI64Xor, OpcodeI64Shl, OpcodeI64ShrS, + OpcodeI64ShrU, OpcodeI64Rotl, OpcodeI64Rotr: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeF32Abs, OpcodeF32Neg, OpcodeF32Ceil, + OpcodeF32Floor, OpcodeF32Trunc, OpcodeF32Nearest, + OpcodeF32Sqrt: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF32Add, OpcodeF32Sub, OpcodeF32Mul, + OpcodeF32Div, OpcodeF32Min, OpcodeF32Max, + OpcodeF32Copysign: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF64Abs, OpcodeF64Neg, OpcodeF64Ceil, + OpcodeF64Floor, OpcodeF64Trunc, OpcodeF64Nearest, + OpcodeF64Sqrt: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeF64Add, OpcodeF64Sub, OpcodeF64Mul, + OpcodeF64Div, OpcodeF64Min, OpcodeF64Max, + OpcodeF64Copysign: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeI32WrapI64: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32WrapI64Name, err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32TruncF32S, OpcodeI32TruncF32U: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI32TruncF64S, OpcodeI32TruncF64U: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64ExtendI32S, OpcodeI64ExtendI32U: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI64TruncF32S, OpcodeI64TruncF32U: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeI64TruncF64S, OpcodeI64TruncF64U: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeF32ConvertI32S, OpcodeF32ConvertI32U: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF32ConvertI64S, OpcodeF32ConvertI64U: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF32DemoteF64: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32DemoteF64Name, err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF64ConvertI32S, OpcodeF64ConvertI32U: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeF64ConvertI64S, OpcodeF64ConvertI64U: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeF64PromoteF32: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64PromoteF32Name, err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeI32ReinterpretF32: + if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32ReinterpretF32Name, err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64ReinterpretF64: + if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64ReinterpretF64Name, err) + } + valueTypeStack.push(ValueTypeI64) + case OpcodeF32ReinterpretI32: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32ReinterpretI32Name, err) + } + valueTypeStack.push(ValueTypeF32) + case OpcodeF64ReinterpretI64: + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64ReinterpretI64Name, err) + } + valueTypeStack.push(ValueTypeF64) + case OpcodeI32Extend8S, OpcodeI32Extend16S: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil { + return fmt.Errorf("%s invalid as %v", instructionNames[op], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeI64Extend8S, OpcodeI64Extend16S, OpcodeI64Extend32S: + if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil { + return fmt.Errorf("%s invalid as %v", instructionNames[op], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err) + } + valueTypeStack.push(ValueTypeI64) + default: + return fmt.Errorf("invalid numeric instruction 0x%x", op) + } + } else if op >= OpcodeRefNull && op <= OpcodeRefFunc { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("%s invalid as %v", instructionNames[op], err) + } + switch op { + case OpcodeRefNull: + pc++ + switch reftype := body[pc]; reftype { + case ValueTypeExternref: + valueTypeStack.push(ValueTypeExternref) + case ValueTypeFuncref: + valueTypeStack.push(ValueTypeFuncref) + default: + return fmt.Errorf("unknown type for ref.null: 0x%x", reftype) + } + case OpcodeRefIsNull: + tp, err := valueTypeStack.pop() + if err != nil { + return fmt.Errorf("cannot pop the operand for ref.is_null: %v", err) + } else if !isReferenceValueType(tp) && tp != valueTypeUnknown { + return fmt.Errorf("type mismatch: expected reference type but was %s", ValueTypeName(tp)) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeRefFunc: + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read function index for ref.func: %v", err) + } + if _, ok := declaredFunctionIndexes[index]; !ok { + return fmt.Errorf("undeclared function index %d for ref.func", index) + } + pc += num - 1 + valueTypeStack.push(ValueTypeFuncref) + } + } else if op == OpcodeTableGet || op == OpcodeTableSet { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("%s is invalid as %v", InstructionName(op), err) + } + pc++ + tableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("read immediate: %v", err) + } + if tableIndex >= uint32(len(tables)) { + return fmt.Errorf("table of index %d not found", tableIndex) + } + + refType := tables[tableIndex].Type + if op == OpcodeTableGet { + if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for table.get: %v", err) + } + valueTypeStack.push(refType) + } else { + if err := valueTypeStack.popAndVerifyType(refType); err != nil { + return fmt.Errorf("cannot pop the operand for table.set: %v", err) + } + if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for table.set: %v", err) + } + } + pc += num - 1 + } else if op == OpcodeMiscPrefix { + pc++ + // A misc opcode is encoded as an unsigned variable 32-bit integer. + miscOp32, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read misc opcode: %v", err) + } + pc += num - 1 + miscOpcode := byte(miscOp32) + // If the misc opcode is beyond byte range, it is highly likely this is an invalid binary, or + // it is due to the new opcode from a new proposal. In the latter case, we have to + // change the alias type of OpcodeMisc (which is currently byte) to uint32. + if uint32(byte(miscOp32)) != miscOp32 { + return fmt.Errorf("invalid misc opcode: %#x", miscOp32) + } + if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil { + return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) + } + var inType, outType ValueType + switch miscOpcode { + case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U: + inType, outType = ValueTypeF32, ValueTypeI32 + case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U: + inType, outType = ValueTypeF64, ValueTypeI32 + case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U: + inType, outType = ValueTypeF32, ValueTypeI64 + case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U: + inType, outType = ValueTypeF64, ValueTypeI64 + } + if err := valueTypeStack.popAndVerifyType(inType); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) + } + valueTypeStack.push(outType) + } else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { + return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) + } + var params []ValueType + // Handle opcodes added in bulk-memory-operations/WebAssembly 2.0. + switch miscOpcode { + case OpcodeMiscDataDrop: + if m.DataCountSection == nil { + return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode)) + } + + // We need to read the index to the data section. + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if int(index) >= len(m.DataSection) { + return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection)) + } + pc += num - 1 + case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill: + if memory == nil { + return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode)) + } + params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} + + if miscOpcode == OpcodeMiscMemoryInit { + if m.DataCountSection == nil { + return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode)) + } + + // We need to read the index to the data section. + pc++ + index, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if int(index) >= len(m.DataSection) { + return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection)) + } + pc += num - 1 + } + + pc++ + val, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if val != 0 || num != 1 { + return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode)) + } + if miscOpcode == OpcodeMiscMemoryCopy { + pc++ + // memory.copy needs two memory index which are reserved as zero. + val, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if val != 0 || num != 1 { + return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode)) + } + } + + case OpcodeMiscTableInit: + params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} + pc++ + elementIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if int(elementIndex) >= len(m.ElementSection) { + return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection)) + } + pc += num + + tableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if tableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) + } + } + if tableIndex >= uint32(len(tables)) { + return fmt.Errorf("table of index %d not found", tableIndex) + } + + if m.ElementSection[elementIndex].Type != tables[tableIndex].Type { + return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s", + RefTypeName(m.ElementSection[elementIndex].Type), + RefTypeName(tables[tableIndex].Type), + ) + } + pc += num - 1 + case OpcodeMiscElemDrop: + pc++ + elementIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err) + } else if int(elementIndex) >= len(m.ElementSection) { + return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection)) + } + pc += num - 1 + case OpcodeMiscTableCopy: + params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} + pc++ + + dstTableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if dstTableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) + } + } + if dstTableIndex >= uint32(len(tables)) { + return fmt.Errorf("table of index %d not found", dstTableIndex) + } + pc += num + + srcTableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if srcTableIndex != 0 { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) + } + } + if srcTableIndex >= uint32(len(tables)) { + return fmt.Errorf("table of index %d not found", srcTableIndex) + } + + if tables[srcTableIndex].Type != tables[dstTableIndex].Type { + return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)", + RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type)) + } + + pc += num - 1 + } + for _, p := range params { + if err := valueTypeStack.popAndVerifyType(p); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) + } + } + } else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) + } + + pc++ + tableIndex, num, err := leb128.LoadUint32(body[pc:]) + if err != nil { + return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err) + } + if tableIndex >= uint32(len(tables)) { + return fmt.Errorf("table of index %d not found", tableIndex) + } + pc += num - 1 + + var params, results []ValueType + reftype := tables[tableIndex].Type + if miscOpcode == OpcodeMiscTableGrow { + params = []ValueType{ValueTypeI32, reftype} + results = []ValueType{ValueTypeI32} + } else if miscOpcode == OpcodeMiscTableSize { + results = []ValueType{ValueTypeI32} + } else if miscOpcode == OpcodeMiscTableFill { + params = []ValueType{ValueTypeI32, reftype, ValueTypeI32} + } + + for _, p := range params { + if err := valueTypeStack.popAndVerifyType(p); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) + } + } + for _, r := range results { + valueTypeStack.push(r) + } + } else { + return fmt.Errorf("unknown misc opcode %#x", miscOpcode) + } + } else if op == OpcodeVecPrefix { + pc++ + // Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix, + // and the second byte determines the actual instruction. + vecOpcode := body[pc] + if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil { + return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err) + } + + switch vecOpcode { + case OpcodeVecV128Const: + // Read 128-bit = 16 bytes constants + if int(pc+16) >= len(body) { + return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode]) + } + pc += 16 + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue, + OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeI32) + case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u, + OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat, + OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat, + OpcodeVecV128Load32zero, OpcodeVecV128Load64zero: + if memory == nil { + return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) + } + pc++ + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + pc += read - 1 + var maxAlign uint32 + switch vecOpcode { + case OpcodeVecV128Load: + maxAlign = 128 / 8 + case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u, + OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u: + maxAlign = 64 / 8 + case OpcodeVecV128Load8Splat: + maxAlign = 1 + case OpcodeVecV128Load16Splat: + maxAlign = 16 / 8 + case OpcodeVecV128Load32Splat: + maxAlign = 32 / 8 + case OpcodeVecV128Load64Splat: + maxAlign = 64 / 8 + case OpcodeVecV128Load32zero: + maxAlign = 32 / 8 + case OpcodeVecV128Load64zero: + maxAlign = 64 / 8 + } + + if 1< maxAlign { + return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode)) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128Store: + if memory == nil { + return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) + } + pc++ + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + pc += read - 1 + if 1< 128/8 { + return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err) + } + case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane: + if memory == nil { + return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) + } + attr := vecLoadLanes[vecOpcode] + pc++ + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + if 1< attr.alignMax { + return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode]) + } + pc += read + if pc >= uint64(len(body)) { + return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName) + } + lane := body[pc] + if lane >= attr.laneCeil { + return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane: + if memory == nil { + return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) + } + attr := vecStoreLanes[vecOpcode] + pc++ + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + if 1< attr.alignMax { + return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode]) + } + pc += read + if pc >= uint64(len(body)) { + return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) + } + lane := body[pc] + if lane >= attr.laneCeil { + return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + case OpcodeVecI8x16ExtractLaneS, + OpcodeVecI8x16ExtractLaneU, + OpcodeVecI16x8ExtractLaneS, + OpcodeVecI16x8ExtractLaneU, + OpcodeVecI32x4ExtractLane, + OpcodeVecI64x2ExtractLane, + OpcodeVecF32x4ExtractLane, + OpcodeVecF64x2ExtractLane: + pc++ + if pc >= uint64(len(body)) { + return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) + } + attr := vecExtractLanes[vecOpcode] + lane := body[pc] + if lane >= attr.laneCeil { + return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(attr.resultType) + case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane, + OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane: + pc++ + if pc >= uint64(len(body)) { + return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) + } + attr := vecReplaceLanes[vecOpcode] + lane := body[pc] + if lane >= attr.laneCeil { + return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) + } + if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat, + OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat: + tp := vecSplatValueTypes[vecOpcode] + if err := valueTypeStack.popAndVerifyType(tp); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128Bitselect: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128Not: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecV128i8x16Shuffle: + pc++ + if pc+15 >= uint64(len(body)) { + return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode]) + } + lanes := body[pc : pc+16] + for i, l := range lanes { + if l >= 32 { + return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode]) + } + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + pc += 15 + case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU, + OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU, + OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU, + OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU: + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS, + OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU, + OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS, + OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU, + OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS, + OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU, + OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS, + OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt, + OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt, + OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge, + OpcodeVecI32x4DotI16x8S, + OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg, + OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt, + OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs, + OpcodeVecF32x4Abs, OpcodeVecF64x2Abs, + OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest, + OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest, + OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U, + OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U, + OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U, + OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U, + OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U, + OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero, + OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U, + OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U, + OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + + case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU, + OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul, + OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul, + OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul, + OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div, + OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div, + OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU, + OpcodeVecI8x16AvgrU, + OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU, + OpcodeVecI16x8AvgrU, + OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU, + OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max, + OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax, + OpcodeVecI16x8Q15mulrSatS, + OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U, + OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U, + OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U: + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { + return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) + } + valueTypeStack.push(ValueTypeV128) + default: + return fmt.Errorf("unknown SIMD instruction %s", vectorInstructionName[vecOpcode]) + } + } else if op == OpcodeBlock { + br.Reset(body[pc+1:]) + bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures) + if err != nil { + return fmt.Errorf("read block: %w", err) + } + controlBlockStack.push(pc, 0, 0, bt, num, 0) + if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { + return err + } + // Plus we have to push any block params again. + for _, p := range bt.Params { + valueTypeStack.push(p) + } + valueTypeStack.pushStackLimit(len(bt.Params)) + pc += num + } else if op == OpcodeAtomicPrefix { + pc++ + // Atomic instructions come with two bytes where the first byte is always OpcodeAtomicPrefix, + // and the second byte determines the actual instruction. + atomicOpcode := body[pc] + if err := enabledFeatures.RequireEnabled(experimental.CoreFeaturesThreads); err != nil { + return fmt.Errorf("%s invalid as %v", atomicInstructionName[atomicOpcode], err) + } + pc++ + + if atomicOpcode == OpcodeAtomicFence { + // No memory requirement and no arguments or return, however the immediate byte value must be 0. + imm := body[pc] + if imm != 0x0 { + return fmt.Errorf("invalid immediate value for %s", AtomicInstructionName(atomicOpcode)) + } + continue + } + + // All atomic operations except fence (checked above) require memory + if memory == nil { + return fmt.Errorf("memory must exist for %s", AtomicInstructionName(atomicOpcode)) + } + align, _, read, err := readMemArg(pc, body) + if err != nil { + return err + } + pc += read - 1 + switch atomicOpcode { + case OpcodeAtomicMemoryNotify: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicMemoryWait32: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicMemoryWait64: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI32Load: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI64Load: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI32Load8U: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Load32U: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI32Store: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI64Store: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI32Store8: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI32Store16: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI64Store8: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI64Store16: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI64Store32: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + case OpcodeAtomicI32RmwAdd, OpcodeAtomicI32RmwSub, OpcodeAtomicI32RmwAnd, OpcodeAtomicI32RmwOr, OpcodeAtomicI32RmwXor, OpcodeAtomicI32RmwXchg: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI32Rmw8AddU, OpcodeAtomicI32Rmw8SubU, OpcodeAtomicI32Rmw8AndU, OpcodeAtomicI32Rmw8OrU, OpcodeAtomicI32Rmw8XorU, OpcodeAtomicI32Rmw8XchgU: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI32Rmw16AddU, OpcodeAtomicI32Rmw16SubU, OpcodeAtomicI32Rmw16AndU, OpcodeAtomicI32Rmw16OrU, OpcodeAtomicI32Rmw16XorU, OpcodeAtomicI32Rmw16XchgU: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI64RmwAdd, OpcodeAtomicI64RmwSub, OpcodeAtomicI64RmwAnd, OpcodeAtomicI64RmwOr, OpcodeAtomicI64RmwXor, OpcodeAtomicI64RmwXchg: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw8AddU, OpcodeAtomicI64Rmw8SubU, OpcodeAtomicI64Rmw8AndU, OpcodeAtomicI64Rmw8OrU, OpcodeAtomicI64Rmw8XorU, OpcodeAtomicI64Rmw8XchgU: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw16AddU, OpcodeAtomicI64Rmw16SubU, OpcodeAtomicI64Rmw16AndU, OpcodeAtomicI64Rmw16OrU, OpcodeAtomicI64Rmw16XorU, OpcodeAtomicI64Rmw16XchgU: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw32AddU, OpcodeAtomicI64Rmw32SubU, OpcodeAtomicI64Rmw32AndU, OpcodeAtomicI64Rmw32OrU, OpcodeAtomicI64Rmw32XorU, OpcodeAtomicI64Rmw32XchgU: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI32RmwCmpxchg: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI32Rmw8CmpxchgU: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI32Rmw16CmpxchgU: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI32) + case OpcodeAtomicI64RmwCmpxchg: + if 1< 64/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw8CmpxchgU: + if 1< 1 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw16CmpxchgU: + if 1< 16/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + case OpcodeAtomicI64Rmw32CmpxchgU: + if 1< 32/8 { + return fmt.Errorf("invalid memory alignment") + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil { + return err + } + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return err + } + valueTypeStack.push(ValueTypeI64) + default: + return fmt.Errorf("invalid atomic opcode: 0x%x", atomicOpcode) + } + } else if op == OpcodeLoop { + br.Reset(body[pc+1:]) + bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures) + if err != nil { + return fmt.Errorf("read block: %w", err) + } + controlBlockStack.push(pc, 0, 0, bt, num, op) + if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { + return err + } + // Plus we have to push any block params again. + for _, p := range bt.Params { + valueTypeStack.push(p) + } + valueTypeStack.pushStackLimit(len(bt.Params)) + pc += num + } else if op == OpcodeIf { + br.Reset(body[pc+1:]) + bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures) + if err != nil { + return fmt.Errorf("read block: %w", err) + } + controlBlockStack.push(pc, 0, 0, bt, num, op) + if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("cannot pop the operand for 'if': %v", err) + } + if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { + return err + } + // Plus we have to push any block params again. + for _, p := range bt.Params { + valueTypeStack.push(p) + } + valueTypeStack.pushStackLimit(len(bt.Params)) + pc += num + } else if op == OpcodeElse { + bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1] + if bl.op != OpcodeIf { + return fmt.Errorf("else instruction must be used in if block: %#x", pc) + } + bl.op = OpcodeElse + bl.elseAt = pc + // Check the type soundness of the instructions *before* entering this else Op. + if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil { + return err + } + // Before entering instructions inside else, we pop all the values pushed by then block. + valueTypeStack.resetAtStackLimit() + // Plus we have to push any block params again. + for _, p := range bl.blockType.Params { + valueTypeStack.push(p) + } + } else if op == OpcodeEnd { + bl := controlBlockStack.pop() + bl.endAt = pc + + // OpcodeEnd can end a block or the function itself. Check to see what it is: + + ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt + if ifMissingElse { + // If this is the end of block without else, the number of block's results and params must be same. + // Otherwise, the value stack would result in the inconsistent state at runtime. + if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) { + return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results) + } + // -1 skips else, to handle if block without else properly. + bl.elseAt = bl.endAt - 1 + } + + // Determine the block context + ctx := "" // the outer-most block: the function return + if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 { + ctx = OpcodeElseName + } else if bl.op != 0 { + ctx = InstructionName(bl.op) + } + + // Check return types match + if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil { + return err + } + + // Put the result types at the end after resetting at the stack limit + // since we might have Any type between the limit and the current top. + valueTypeStack.resetAtStackLimit() + for _, exp := range bl.blockType.Results { + valueTypeStack.push(exp) + } + // We exit if/loop/block, so reset the constraints on the stack manipulation + // on values previously pushed by outer blocks. + valueTypeStack.popStackLimit() + } else if op == OpcodeReturn { + // Same formatting as OpcodeEnd on the outer-most block + if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil { + return err + } + // return instruction is stack-polymorphic. + valueTypeStack.unreachable() + } else if op == OpcodeDrop { + _, err := valueTypeStack.pop() + if err != nil { + return fmt.Errorf("invalid drop: %v", err) + } + } else if op == OpcodeSelect || op == OpcodeTypedSelect { + if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { + return fmt.Errorf("type mismatch on 3rd select operand: %v", err) + } + v1, err := valueTypeStack.pop() + if err != nil { + return fmt.Errorf("invalid select: %v", err) + } + v2, err := valueTypeStack.pop() + if err != nil { + return fmt.Errorf("invalid select: %v", err) + } + + if op == OpcodeTypedSelect { + if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil { + return fmt.Errorf("%s is invalid as %w", InstructionName(op), err) + } + pc++ + if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 { + return fmt.Errorf("too many type immediates for %s", InstructionName(op)) + } + pc++ + tp := body[pc] + if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 && + tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 { + return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName) + } + } else if isReferenceValueType(v1) || isReferenceValueType(v2) { + return fmt.Errorf("reference types cannot be used for non typed select instruction") + } + + if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown { + return fmt.Errorf("type mismatch on 1st and 2nd select operands") + } + if v1 == valueTypeUnknown { + valueTypeStack.push(v2) + } else { + valueTypeStack.push(v1) + } + } else if op == OpcodeUnreachable { + // unreachable instruction is stack-polymorphic. + valueTypeStack.unreachable() + } else if op == OpcodeNop { + } else { + return fmt.Errorf("invalid instruction 0x%x", op) + } + } + + if len(controlBlockStack.stack) > 0 { + return fmt.Errorf("ill-nested block exists") + } + if valueTypeStack.maximumStackPointer > maxStackValues { + return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues) + } + return nil +} + +var vecExtractLanes = [...]struct { + laneCeil byte + resultType ValueType +}{ + OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32}, + OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32}, + OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32}, + OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32}, + OpcodeVecI32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeI32}, + OpcodeVecI64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeI64}, + OpcodeVecF32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeF32}, + OpcodeVecF64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeF64}, +} + +var vecReplaceLanes = [...]struct { + laneCeil byte + paramType ValueType +}{ + OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32}, + OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32}, + OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32}, + OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64}, + OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32}, + OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64}, +} + +var vecStoreLanes = [...]struct { + alignMax uint32 + laneCeil byte +}{ + OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64}, + OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32}, + OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16}, + OpcodeVecV128Store8Lane: {alignMax: 1, laneCeil: 128 / 8}, +} + +var vecLoadLanes = [...]struct { + alignMax uint32 + laneCeil byte +}{ + OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64}, + OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32}, + OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16}, + OpcodeVecV128Load8Lane: {alignMax: 1, laneCeil: 128 / 8}, +} + +var vecSplatValueTypes = [...]ValueType{ + OpcodeVecI8x16Splat: ValueTypeI32, + OpcodeVecI16x8Splat: ValueTypeI32, + OpcodeVecI32x4Splat: ValueTypeI32, + OpcodeVecI64x2Splat: ValueTypeI64, + OpcodeVecF32x4Splat: ValueTypeF32, + OpcodeVecF64x2Splat: ValueTypeF64, +} + +type stacks struct { + vs valueTypeStack + cs controlBlockStack + // ls is the label slice that is reused for each br_table instruction. + ls []uint32 +} + +func (sts *stacks) reset(functionType *FunctionType) { + // Reset valueStack for reuse. + sts.vs.stack = sts.vs.stack[:0] + sts.vs.stackLimits = sts.vs.stackLimits[:0] + sts.vs.maximumStackPointer = 0 + sts.cs.stack = sts.cs.stack[:0] + sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType}) + sts.ls = sts.ls[:0] +} + +type controlBlockStack struct { + stack []controlBlock +} + +func (s *controlBlockStack) pop() *controlBlock { + tail := len(s.stack) - 1 + ret := &s.stack[tail] + s.stack = s.stack[:tail] + return ret +} + +func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) { + s.stack = append(s.stack, controlBlock{ + startAt: startAt, + elseAt: elseAt, + endAt: endAt, + blockType: blockType, + blockTypeBytes: blockTypeBytes, + op: op, + }) +} + +type valueTypeStack struct { + stack []ValueType + stackLimits []int + maximumStackPointer int + // requireStackValuesTmp is used in requireStackValues function to reduce the allocation. + requireStackValuesTmp []ValueType +} + +// Only used in the analyzeFunction below. +const valueTypeUnknown = ValueType(0xFF) + +func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) { + if len(s.stackLimits) > 0 { + limit = s.stackLimits[len(s.stackLimits)-1] + } + stackLen := len(s.stack) + if stackLen <= limit { + return + } else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown { + vt = valueTypeUnknown + ok = true + return + } else { + vt = s.stack[stackLen-1] + s.stack = s.stack[:stackLen-1] + ok = true + return + } +} + +func (s *valueTypeStack) pop() (ValueType, error) { + if vt, limit, ok := s.tryPop(); ok { + return vt, nil + } else { + return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit) + } +} + +// popAndVerifyType returns an error if the stack value is unexpected. +func (s *valueTypeStack) popAndVerifyType(expected ValueType) error { + have, _, ok := s.tryPop() + if !ok { + return fmt.Errorf("%s missing", ValueTypeName(expected)) + } + if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown { + return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have)) + } + return nil +} + +func (s *valueTypeStack) push(v ValueType) { + s.stack = append(s.stack, v) + if sp := len(s.stack); sp > s.maximumStackPointer { + s.maximumStackPointer = sp + } +} + +func (s *valueTypeStack) unreachable() { + s.resetAtStackLimit() + s.stack = append(s.stack, valueTypeUnknown) +} + +func (s *valueTypeStack) resetAtStackLimit() { + if len(s.stackLimits) != 0 { + s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]] + } else { + s.stack = s.stack[:0] + } +} + +func (s *valueTypeStack) popStackLimit() { + if len(s.stackLimits) != 0 { + s.stackLimits = s.stackLimits[:len(s.stackLimits)-1] + } +} + +// pushStackLimit pushes the control frame's bottom of the stack. +func (s *valueTypeStack) pushStackLimit(params int) { + limit := len(s.stack) - params + s.stackLimits = append(s.stackLimits, limit) +} + +func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error { + return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit) +} + +func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error { + return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit) +} + +func (s *valueTypeStack) requireStackValues( + isParam bool, + context string, + want []ValueType, + checkAboveLimit bool, +) error { + limit := 0 + if len(s.stackLimits) > 0 { + limit = s.stackLimits[len(s.stackLimits)-1] + } + // Iterate backwards as we are comparing the desired slice against stack value types. + countWanted := len(want) + + // First, check if there are enough values on the stack. + s.requireStackValuesTmp = s.requireStackValuesTmp[:0] + for i := countWanted - 1; i >= 0; i-- { + popped, _, ok := s.tryPop() + if !ok { + if len(s.requireStackValuesTmp) > len(want) { + return typeCountError(isParam, context, s.requireStackValuesTmp, want) + } + return typeCountError(isParam, context, s.requireStackValuesTmp, want) + } + s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped) + } + + // Now, check if there are too many values. + if checkAboveLimit { + if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) { + return typeCountError(isParam, context, append(s.stack, want...), want) + } + } + + // Finally, check the types of the values: + for i, v := range s.requireStackValuesTmp { + nextWant := want[countWanted-i-1] // have is in reverse order (stack) + if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown { + return typeMismatchError(isParam, context, v, nextWant, i) + } + } + return nil +} + +// typeMismatchError returns an error similar to go compiler's error on type mismatch. +func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error { + var ret strings.Builder + ret.WriteString("cannot use ") + ret.WriteString(ValueTypeName(have)) + if context != "" { + ret.WriteString(" in ") + ret.WriteString(context) + ret.WriteString(" block") + } + if isParam { + ret.WriteString(" as param") + } else { + ret.WriteString(" as result") + } + ret.WriteString("[") + ret.WriteString(strconv.Itoa(i)) + ret.WriteString("] type ") + ret.WriteString(ValueTypeName(want)) + return errors.New(ret.String()) +} + +// typeCountError returns an error similar to go compiler's error on type count mismatch. +func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error { + var ret strings.Builder + if len(have) > len(want) { + ret.WriteString("too many ") + } else { + ret.WriteString("not enough ") + } + if isParam { + ret.WriteString("params") + } else { + ret.WriteString("results") + } + if context != "" { + if isParam { + ret.WriteString(" for ") + } else { + ret.WriteString(" in ") + } + ret.WriteString(context) + ret.WriteString(" block") + } + ret.WriteString("\n\thave (") + writeValueTypes(have, &ret) + ret.WriteString(")\n\twant (") + writeValueTypes(want, &ret) + ret.WriteByte(')') + return errors.New(ret.String()) +} + +func writeValueTypes(vts []ValueType, ret *strings.Builder) { + switch len(vts) { + case 0: + case 1: + ret.WriteString(ValueTypeName(vts[0])) + default: + ret.WriteString(ValueTypeName(vts[0])) + for _, vt := range vts[1:] { + ret.WriteString(", ") + ret.WriteString(ValueTypeName(vt)) + } + } +} + +func (s *valueTypeStack) String() string { + var typeStrs, limits []string + for _, v := range s.stack { + var str string + if v == valueTypeUnknown { + str = "unknown" + } else { + str = ValueTypeName(v) + } + typeStrs = append(typeStrs, str) + } + for _, d := range s.stackLimits { + limits = append(limits, fmt.Sprintf("%d", d)) + } + return fmt.Sprintf("{stack: [%s], limits: [%s]}", + strings.Join(typeStrs, ", "), strings.Join(limits, ",")) +} + +type controlBlock struct { + startAt, elseAt, endAt uint64 + blockType *FunctionType + blockTypeBytes uint64 + // op is zero when the outermost block + op Opcode +} + +// DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one +// WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include +// CoreFeatureMultiValue and include an index in the Module.TypeSection. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype +// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md +func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) { + raw, num, err := leb128.DecodeInt33AsInt64(r) + if err != nil { + return nil, 0, fmt.Errorf("decode int33: %w", err) + } + + var ret *FunctionType + switch raw { + case -64: // 0x40 in original byte = nil + ret = blockType_v_v + case -1: // 0x7f in original byte = i32 + ret = blockType_v_i32 + case -2: // 0x7e in original byte = i64 + ret = blockType_v_i64 + case -3: // 0x7d in original byte = f32 + ret = blockType_v_f32 + case -4: // 0x7c in original byte = f64 + ret = blockType_v_f64 + case -5: // 0x7b in original byte = v128 + ret = blockType_v_v128 + case -16: // 0x70 in original byte = funcref + ret = blockType_v_funcref + case -17: // 0x6f in original byte = externref + ret = blockType_v_externref + default: + if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil { + return nil, num, fmt.Errorf("block with function type return invalid as %v", err) + } + if raw < 0 || (raw >= int64(len(types))) { + return nil, 0, fmt.Errorf("type index out of range: %d", raw) + } + ret = &types[raw] + } + return ret, num, err +} + +// These block types are defined as globals in order to avoid allocations in DecodeBlockType. +var ( + blockType_v_v = &FunctionType{} + blockType_v_i32 = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1} + blockType_v_i64 = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1} + blockType_v_f32 = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1} + blockType_v_f64 = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1} + blockType_v_v128 = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2} + blockType_v_funcref = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1} + blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1} +) + +// SplitCallStack returns the input stack resliced to the count of params and +// results, or errors if it isn't long enough for either. +func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) { + stackLen := len(stack) + if n := ft.ParamNumInUint64; n > stackLen { + return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen) + } else if n > 0 { + params = stack[:n] + } + if n := ft.ResultNumInUint64; n > stackLen { + return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen) + } else if n > 0 { + results = stack[:n] + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go new file mode 100644 index 00000000..c5f6e912 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go @@ -0,0 +1,188 @@ +package wasm + +import ( + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +// ImportedFunctions returns the definitions of each imported function. +// +// Note: Unlike ExportedFunctions, there is no unique constraint on imports. +func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) { + for i := uint32(0); i < m.ImportFunctionCount; i++ { + ret = append(ret, m.FunctionDefinition(i)) + } + return +} + +// ExportedFunctions returns the definitions of each exported function. +func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition { + ret := map[string]api.FunctionDefinition{} + for i := range m.ExportSection { + exp := &m.ExportSection[i] + if exp.Type == ExternTypeFunc { + d := m.FunctionDefinition(exp.Index) + ret[exp.Name] = d + } + } + return ret +} + +// FunctionDefinition returns the FunctionDefinition for the given `index`. +func (m *Module) FunctionDefinition(index Index) *FunctionDefinition { + // TODO: function initialization is lazy, but bulk. Make it per function. + m.buildFunctionDefinitions() + return &m.FunctionDefinitionSection[index] +} + +// buildFunctionDefinitions generates function metadata that can be parsed from +// the module. This must be called after all validation. +func (m *Module) buildFunctionDefinitions() { + m.functionDefinitionSectionInitOnce.Do(m.buildFunctionDefinitionsOnce) +} + +func (m *Module) buildFunctionDefinitionsOnce() { + var moduleName string + var functionNames NameMap + var localNames, resultNames IndirectNameMap + if m.NameSection != nil { + moduleName = m.NameSection.ModuleName + functionNames = m.NameSection.FunctionNames + localNames = m.NameSection.LocalNames + resultNames = m.NameSection.ResultNames + } + + importCount := m.ImportFunctionCount + m.FunctionDefinitionSection = make([]FunctionDefinition, importCount+uint32(len(m.FunctionSection))) + + importFuncIdx := Index(0) + for i := range m.ImportSection { + imp := &m.ImportSection[i] + if imp.Type != ExternTypeFunc { + continue + } + + def := &m.FunctionDefinitionSection[importFuncIdx] + def.importDesc = imp + def.index = importFuncIdx + def.Functype = &m.TypeSection[imp.DescFunc] + importFuncIdx++ + } + + for codeIndex, typeIndex := range m.FunctionSection { + code := &m.CodeSection[codeIndex] + idx := importFuncIdx + Index(codeIndex) + def := &m.FunctionDefinitionSection[idx] + def.index = idx + def.Functype = &m.TypeSection[typeIndex] + def.goFunc = code.GoFunc + } + + n, nLen := 0, len(functionNames) + for i := range m.FunctionDefinitionSection { + d := &m.FunctionDefinitionSection[i] + // The function name section begins with imports, but can be sparse. + // This keeps track of how far in the name section we've searched. + funcIdx := d.index + var funcName string + for ; n < nLen; n++ { + next := &functionNames[n] + if next.Index > funcIdx { + break // we have function names, but starting at a later index. + } else if next.Index == funcIdx { + funcName = next.Name + break + } + } + + d.moduleName = moduleName + d.name = funcName + d.Debugname = wasmdebug.FuncName(moduleName, funcName, funcIdx) + d.paramNames = paramNames(localNames, funcIdx, len(d.Functype.Params)) + d.resultNames = paramNames(resultNames, funcIdx, len(d.Functype.Results)) + + for i := range m.ExportSection { + e := &m.ExportSection[i] + if e.Type == ExternTypeFunc && e.Index == funcIdx { + d.exportNames = append(d.exportNames, e.Name) + } + } + } +} + +// FunctionDefinition implements api.FunctionDefinition +type FunctionDefinition struct { + internalapi.WazeroOnlyType + moduleName string + index Index + name string + // Debugname is exported for testing purpose. + Debugname string + goFunc interface{} + // Functype is exported for testing purpose. + Functype *FunctionType + importDesc *Import + exportNames []string + paramNames []string + resultNames []string +} + +// ModuleName implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) ModuleName() string { + return f.moduleName +} + +// Index implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) Index() uint32 { + return f.index +} + +// Name implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) Name() string { + return f.name +} + +// DebugName implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) DebugName() string { + return f.Debugname +} + +// Import implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) Import() (moduleName, name string, isImport bool) { + if f.importDesc != nil { + importDesc := f.importDesc + moduleName, name, isImport = importDesc.Module, importDesc.Name, true + } + return +} + +// ExportNames implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) ExportNames() []string { + return f.exportNames +} + +// GoFunction implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) GoFunction() interface{} { + return f.goFunc +} + +// ParamTypes implements api.FunctionDefinition ParamTypes. +func (f *FunctionDefinition) ParamTypes() []ValueType { + return f.Functype.Params +} + +// ParamNames implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) ParamNames() []string { + return f.paramNames +} + +// ResultTypes implements api.FunctionDefinition ResultTypes. +func (f *FunctionDefinition) ResultTypes() []ValueType { + return f.Functype.Results +} + +// ResultNames implements the same method as documented on api.FunctionDefinition. +func (f *FunctionDefinition) ResultNames() []string { + return f.resultNames +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go new file mode 100644 index 00000000..abaa2d1f --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go @@ -0,0 +1,55 @@ +package wasm + +import ( + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/internalapi" +) + +// constantGlobal wraps GlobalInstance to implement api.Global. +type constantGlobal struct { + internalapi.WazeroOnlyType + g *GlobalInstance +} + +// Type implements api.Global. +func (g constantGlobal) Type() api.ValueType { + return g.g.Type.ValType +} + +// Get implements api.Global. +func (g constantGlobal) Get() uint64 { + ret, _ := g.g.Value() + return ret +} + +// String implements api.Global. +func (g constantGlobal) String() string { + return g.g.String() +} + +// mutableGlobal extends constantGlobal to allow updates. +type mutableGlobal struct { + internalapi.WazeroOnlyType + g *GlobalInstance +} + +// Type implements api.Global. +func (g mutableGlobal) Type() api.ValueType { + return g.g.Type.ValType +} + +// Get implements api.Global. +func (g mutableGlobal) Get() uint64 { + ret, _ := g.g.Value() + return ret +} + +// String implements api.Global. +func (g mutableGlobal) String() string { + return g.g.String() +} + +// Set implements the same method as documented on api.MutableGlobal. +func (g mutableGlobal) Set(v uint64) { + g.g.SetValue(v, 0) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go new file mode 100644 index 00000000..9510c258 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go @@ -0,0 +1,279 @@ +package wasm + +import ( + "bytes" + "context" + "errors" + "fmt" + "math" + "reflect" + + "github.com/tetratelabs/wazero/api" +) + +type paramsKind byte + +const ( + paramsKindNoContext paramsKind = iota + paramsKindContext + paramsKindContextModule +) + +// Below are reflection code to get the interface type used to parse functions and set values. + +var ( + moduleType = reflect.TypeOf((*api.Module)(nil)).Elem() + goContextType = reflect.TypeOf((*context.Context)(nil)).Elem() + errorType = reflect.TypeOf((*error)(nil)).Elem() +) + +// compile-time check to ensure reflectGoModuleFunction implements +// api.GoModuleFunction. +var _ api.GoModuleFunction = (*reflectGoModuleFunction)(nil) + +type reflectGoModuleFunction struct { + fn *reflect.Value + params, results []ValueType +} + +// Call implements the same method as documented on api.GoModuleFunction. +func (f *reflectGoModuleFunction) Call(ctx context.Context, mod api.Module, stack []uint64) { + callGoFunc(ctx, mod, f.fn, stack) +} + +// EqualTo is exposed for testing. +func (f *reflectGoModuleFunction) EqualTo(that interface{}) bool { + if f2, ok := that.(*reflectGoModuleFunction); !ok { + return false + } else { + // TODO compare reflect pointers + return bytes.Equal(f.params, f2.params) && bytes.Equal(f.results, f2.results) + } +} + +// compile-time check to ensure reflectGoFunction implements api.GoFunction. +var _ api.GoFunction = (*reflectGoFunction)(nil) + +type reflectGoFunction struct { + fn *reflect.Value + pk paramsKind + params, results []ValueType +} + +// EqualTo is exposed for testing. +func (f *reflectGoFunction) EqualTo(that interface{}) bool { + if f2, ok := that.(*reflectGoFunction); !ok { + return false + } else { + // TODO compare reflect pointers + return f.pk == f2.pk && + bytes.Equal(f.params, f2.params) && bytes.Equal(f.results, f2.results) + } +} + +// Call implements the same method as documented on api.GoFunction. +func (f *reflectGoFunction) Call(ctx context.Context, stack []uint64) { + if f.pk == paramsKindNoContext { + ctx = nil + } + callGoFunc(ctx, nil, f.fn, stack) +} + +// callGoFunc executes the reflective function by converting params to Go +// types. The results of the function call are converted back to api.ValueType. +func callGoFunc(ctx context.Context, mod api.Module, fn *reflect.Value, stack []uint64) { + tp := fn.Type() + + var in []reflect.Value + pLen := tp.NumIn() + if pLen != 0 { + in = make([]reflect.Value, pLen) + + i := 0 + if ctx != nil { + in[0] = newContextVal(ctx) + i++ + } + if mod != nil { + in[1] = newModuleVal(mod) + i++ + } + + for j := 0; i < pLen; i++ { + next := tp.In(i) + val := reflect.New(next).Elem() + k := next.Kind() + raw := stack[j] + j++ + + switch k { + case reflect.Float32: + val.SetFloat(float64(math.Float32frombits(uint32(raw)))) + case reflect.Float64: + val.SetFloat(math.Float64frombits(raw)) + case reflect.Uint32, reflect.Uint64, reflect.Uintptr: + val.SetUint(raw) + case reflect.Int32, reflect.Int64: + val.SetInt(int64(raw)) + default: + panic(fmt.Errorf("BUG: param[%d] has an invalid type: %v", i, k)) + } + in[i] = val + } + } + + // Execute the host function and push back the call result onto the stack. + for i, ret := range fn.Call(in) { + switch ret.Kind() { + case reflect.Float32: + stack[i] = uint64(math.Float32bits(float32(ret.Float()))) + case reflect.Float64: + stack[i] = math.Float64bits(ret.Float()) + case reflect.Uint32, reflect.Uint64, reflect.Uintptr: + stack[i] = ret.Uint() + case reflect.Int32, reflect.Int64: + stack[i] = uint64(ret.Int()) + default: + panic(fmt.Errorf("BUG: result[%d] has an invalid type: %v", i, ret.Kind())) + } + } +} + +func newContextVal(ctx context.Context) reflect.Value { + val := reflect.New(goContextType).Elem() + val.Set(reflect.ValueOf(ctx)) + return val +} + +func newModuleVal(m api.Module) reflect.Value { + val := reflect.New(moduleType).Elem() + val.Set(reflect.ValueOf(m)) + return val +} + +// MustParseGoReflectFuncCode parses Code from the go function or panics. +// +// Exposing this simplifies FunctionDefinition of host functions in built-in host +// modules and tests. +func MustParseGoReflectFuncCode(fn interface{}) Code { + _, _, code, err := parseGoReflectFunc(fn) + if err != nil { + panic(err) + } + return code +} + +func parseGoReflectFunc(fn interface{}) (params, results []ValueType, code Code, err error) { + fnV := reflect.ValueOf(fn) + p := fnV.Type() + + if fnV.Kind() != reflect.Func { + err = fmt.Errorf("kind != func: %s", fnV.Kind().String()) + return + } + + pk, kindErr := kind(p) + if kindErr != nil { + err = kindErr + return + } + + pOffset := 0 + switch pk { + case paramsKindNoContext: + case paramsKindContext: + pOffset = 1 + case paramsKindContextModule: + pOffset = 2 + } + + pCount := p.NumIn() - pOffset + if pCount > 0 { + params = make([]ValueType, pCount) + } + for i := 0; i < len(params); i++ { + pI := p.In(i + pOffset) + if t, ok := getTypeOf(pI.Kind()); ok { + params[i] = t + continue + } + + // Now, we will definitely err, decide which message is best + var arg0Type reflect.Type + if hc := pI.Implements(moduleType); hc { + arg0Type = moduleType + } else if gc := pI.Implements(goContextType); gc { + arg0Type = goContextType + } + + if arg0Type != nil { + err = fmt.Errorf("param[%d] is a %s, which may be defined only once as param[0]", i+pOffset, arg0Type) + } else { + err = fmt.Errorf("param[%d] is unsupported: %s", i+pOffset, pI.Kind()) + } + return + } + + rCount := p.NumOut() + if rCount > 0 { + results = make([]ValueType, rCount) + } + for i := 0; i < len(results); i++ { + rI := p.Out(i) + if t, ok := getTypeOf(rI.Kind()); ok { + results[i] = t + continue + } + + // Now, we will definitely err, decide which message is best + if rI.Implements(errorType) { + err = fmt.Errorf("result[%d] is an error, which is unsupported", i) + } else { + err = fmt.Errorf("result[%d] is unsupported: %s", i, rI.Kind()) + } + return + } + + code = Code{} + if pk == paramsKindContextModule { + code.GoFunc = &reflectGoModuleFunction{fn: &fnV, params: params, results: results} + } else { + code.GoFunc = &reflectGoFunction{pk: pk, fn: &fnV, params: params, results: results} + } + return +} + +func kind(p reflect.Type) (paramsKind, error) { + pCount := p.NumIn() + if pCount > 0 && p.In(0).Kind() == reflect.Interface { + p0 := p.In(0) + if p0.Implements(moduleType) { + return 0, errors.New("invalid signature: api.Module parameter must be preceded by context.Context") + } else if p0.Implements(goContextType) { + if pCount >= 2 && p.In(1).Implements(moduleType) { + return paramsKindContextModule, nil + } + return paramsKindContext, nil + } + } + // Without context param allows portability with reflective runtimes. + // This allows people to more easily port to wazero. + return paramsKindNoContext, nil +} + +func getTypeOf(kind reflect.Kind) (ValueType, bool) { + switch kind { + case reflect.Float64: + return ValueTypeF64, true + case reflect.Float32: + return ValueTypeF32, true + case reflect.Int32, reflect.Uint32: + return ValueTypeI32, true + case reflect.Int64, reflect.Uint64: + return ValueTypeI64, true + case reflect.Uintptr: + return ValueTypeExternref, true + default: + return 0x00, false + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go new file mode 100644 index 00000000..bca686d1 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go @@ -0,0 +1,179 @@ +package wasm + +import ( + "errors" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +type HostFuncExporter interface { + ExportHostFunc(*HostFunc) +} + +// HostFunc is a function with an inlined type, used for NewHostModule. +// Any corresponding FunctionType will be reused or added to the Module. +type HostFunc struct { + // ExportName is the only value returned by api.FunctionDefinition. + ExportName string + + // Name is equivalent to the same method on api.FunctionDefinition. + Name string + + // ParamTypes is equivalent to the same method on api.FunctionDefinition. + ParamTypes []ValueType + + // ParamNames is equivalent to the same method on api.FunctionDefinition. + ParamNames []string + + // ResultTypes is equivalent to the same method on api.FunctionDefinition. + ResultTypes []ValueType + + // ResultNames is equivalent to the same method on api.FunctionDefinition. + ResultNames []string + + // Code is the equivalent function in the SectionIDCode. + Code Code +} + +// WithGoModuleFunc returns a copy of the function, replacing its Code.GoFunc. +func (f *HostFunc) WithGoModuleFunc(fn api.GoModuleFunc) *HostFunc { + ret := *f + ret.Code.GoFunc = fn + return &ret +} + +// NewHostModule is defined internally for use in WASI tests and to keep the code size in the root directory small. +func NewHostModule( + moduleName string, + exportNames []string, + nameToHostFunc map[string]*HostFunc, + enabledFeatures api.CoreFeatures, +) (m *Module, err error) { + if moduleName != "" { + m = &Module{NameSection: &NameSection{ModuleName: moduleName}} + } else { + return nil, errors.New("a module name must not be empty") + } + + if exportCount := uint32(len(nameToHostFunc)); exportCount > 0 { + m.ExportSection = make([]Export, 0, exportCount) + m.Exports = make(map[string]*Export, exportCount) + if err = addFuncs(m, exportNames, nameToHostFunc, enabledFeatures); err != nil { + return + } + } + + m.IsHostModule = true + // Uses the address of *wasm.Module as the module ID so that host functions can have each state per compilation. + // Downside of this is that compilation cache on host functions (trampoline codes for Go functions and + // Wasm codes for Wasm-implemented host functions) are not available and compiles each time. On the other hand, + // compilation of host modules is not costly as it's merely small trampolines vs the real-world native Wasm binary. + // TODO: refactor engines so that we can properly cache compiled machine codes for host modules. + m.AssignModuleID([]byte(fmt.Sprintf("@@@@@@@@%p", m)), // @@@@@@@@ = any 8 bytes different from Wasm header. + nil, false) + return +} + +func addFuncs( + m *Module, + exportNames []string, + nameToHostFunc map[string]*HostFunc, + enabledFeatures api.CoreFeatures, +) (err error) { + if m.NameSection == nil { + m.NameSection = &NameSection{} + } + moduleName := m.NameSection.ModuleName + + for _, k := range exportNames { + hf := nameToHostFunc[k] + if hf.Name == "" { + hf.Name = k // default name to export name + } + switch hf.Code.GoFunc.(type) { + case api.GoModuleFunction, api.GoFunction: + continue // already parsed + } + + // Resolve the code using reflection + hf.ParamTypes, hf.ResultTypes, hf.Code, err = parseGoReflectFunc(hf.Code.GoFunc) + if err != nil { + return fmt.Errorf("func[%s.%s] %w", moduleName, k, err) + } + + // Assign names to the function, if they exist. + params := hf.ParamTypes + if paramNames := hf.ParamNames; paramNames != nil { + if paramNamesLen := len(paramNames); paramNamesLen != len(params) { + return fmt.Errorf("func[%s.%s] has %d params, but %d params names", moduleName, k, paramNamesLen, len(params)) + } + } + + results := hf.ResultTypes + if resultNames := hf.ResultNames; resultNames != nil { + if resultNamesLen := len(resultNames); resultNamesLen != len(results) { + return fmt.Errorf("func[%s.%s] has %d results, but %d results names", moduleName, k, resultNamesLen, len(results)) + } + } + } + + funcCount := uint32(len(exportNames)) + m.NameSection.FunctionNames = make([]NameAssoc, 0, funcCount) + m.FunctionSection = make([]Index, 0, funcCount) + m.CodeSection = make([]Code, 0, funcCount) + + idx := Index(0) + for _, name := range exportNames { + hf := nameToHostFunc[name] + debugName := wasmdebug.FuncName(moduleName, name, idx) + typeIdx, typeErr := m.maybeAddType(hf.ParamTypes, hf.ResultTypes, enabledFeatures) + if typeErr != nil { + return fmt.Errorf("func[%s] %v", debugName, typeErr) + } + m.FunctionSection = append(m.FunctionSection, typeIdx) + m.CodeSection = append(m.CodeSection, hf.Code) + + export := hf.ExportName + m.ExportSection = append(m.ExportSection, Export{Type: ExternTypeFunc, Name: export, Index: idx}) + m.Exports[export] = &m.ExportSection[len(m.ExportSection)-1] + m.NameSection.FunctionNames = append(m.NameSection.FunctionNames, NameAssoc{Index: idx, Name: hf.Name}) + + if len(hf.ParamNames) > 0 { + localNames := NameMapAssoc{Index: idx} + for i, n := range hf.ParamNames { + localNames.NameMap = append(localNames.NameMap, NameAssoc{Index: Index(i), Name: n}) + } + m.NameSection.LocalNames = append(m.NameSection.LocalNames, localNames) + } + if len(hf.ResultNames) > 0 { + resultNames := NameMapAssoc{Index: idx} + for i, n := range hf.ResultNames { + resultNames.NameMap = append(resultNames.NameMap, NameAssoc{Index: Index(i), Name: n}) + } + m.NameSection.ResultNames = append(m.NameSection.ResultNames, resultNames) + } + idx++ + } + return nil +} + +func (m *Module) maybeAddType(params, results []ValueType, enabledFeatures api.CoreFeatures) (Index, error) { + if len(results) > 1 { + // Guard >1.0 feature multi-value + if err := enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil { + return 0, fmt.Errorf("multiple result types invalid as %v", err) + } + } + for i := range m.TypeSection { + t := &m.TypeSection[i] + if t.EqualsSignature(params, results) { + return Index(i), nil + } + } + + result := m.SectionElementCount(SectionIDType) + m.TypeSection = append(m.TypeSection, FunctionType{Params: params, Results: results}) + return result, nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go new file mode 100644 index 00000000..67f196b8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go @@ -0,0 +1,1866 @@ +package wasm + +// Opcode is the binary Opcode of an instruction. See also InstructionName +type Opcode = byte + +const ( + // OpcodeUnreachable causes an unconditional trap. + OpcodeUnreachable Opcode = 0x00 + // OpcodeNop does nothing + OpcodeNop Opcode = 0x01 + // OpcodeBlock brackets a sequence of instructions. A branch instruction on an if label breaks out to after its + // OpcodeEnd. + OpcodeBlock Opcode = 0x02 + // OpcodeLoop brackets a sequence of instructions. A branch instruction on a loop label will jump back to the + // beginning of its block. + OpcodeLoop Opcode = 0x03 + // OpcodeIf brackets a sequence of instructions. When the top of the stack evaluates to 1, the block is executed. + // Zero jumps to the optional OpcodeElse. A branch instruction on an if label breaks out to after its OpcodeEnd. + OpcodeIf Opcode = 0x04 + // OpcodeElse brackets a sequence of instructions enclosed by an OpcodeIf. A branch instruction on a then label + // breaks out to after the OpcodeEnd on the enclosing OpcodeIf. + OpcodeElse Opcode = 0x05 + // OpcodeEnd terminates a control instruction OpcodeBlock, OpcodeLoop or OpcodeIf. + OpcodeEnd Opcode = 0x0b + + // OpcodeBr is a stack-polymorphic opcode that performs an unconditional branch. How the stack is modified depends + // on whether the "br" is enclosed by a loop, and if CoreFeatureMultiValue is enabled. + // + // Here are the rules in pseudocode about how the stack is modified based on the "br" operand L (label): + // if L is loop: append(L.originalStackWithoutInputs, N-values popped from the stack) where N == L.inputs + // else: append(L.originalStackWithoutInputs, N-values popped from the stack) where N == L.results + // + // In WebAssembly 1.0 (20191205), N can be zero or one. When CoreFeatureMultiValue is enabled, N can be more than one, + // depending on the type use of the label L. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-controlmathsfbrl + OpcodeBr Opcode = 0x0c + + OpcodeBrIf Opcode = 0x0d + OpcodeBrTable Opcode = 0x0e + OpcodeReturn Opcode = 0x0f + OpcodeCall Opcode = 0x10 + OpcodeCallIndirect Opcode = 0x11 + + // parametric instructions + + OpcodeDrop Opcode = 0x1a + OpcodeSelect Opcode = 0x1b + OpcodeTypedSelect Opcode = 0x1c + + // variable instructions + + OpcodeLocalGet Opcode = 0x20 + OpcodeLocalSet Opcode = 0x21 + OpcodeLocalTee Opcode = 0x22 + OpcodeGlobalGet Opcode = 0x23 + OpcodeGlobalSet Opcode = 0x24 + + // Below are toggled with CoreFeatureReferenceTypes + + OpcodeTableGet Opcode = 0x25 + OpcodeTableSet Opcode = 0x26 + + // memory instructions + + OpcodeI32Load Opcode = 0x28 + OpcodeI64Load Opcode = 0x29 + OpcodeF32Load Opcode = 0x2a + OpcodeF64Load Opcode = 0x2b + OpcodeI32Load8S Opcode = 0x2c + OpcodeI32Load8U Opcode = 0x2d + OpcodeI32Load16S Opcode = 0x2e + OpcodeI32Load16U Opcode = 0x2f + OpcodeI64Load8S Opcode = 0x30 + OpcodeI64Load8U Opcode = 0x31 + OpcodeI64Load16S Opcode = 0x32 + OpcodeI64Load16U Opcode = 0x33 + OpcodeI64Load32S Opcode = 0x34 + OpcodeI64Load32U Opcode = 0x35 + OpcodeI32Store Opcode = 0x36 + OpcodeI64Store Opcode = 0x37 + OpcodeF32Store Opcode = 0x38 + OpcodeF64Store Opcode = 0x39 + OpcodeI32Store8 Opcode = 0x3a + OpcodeI32Store16 Opcode = 0x3b + OpcodeI64Store8 Opcode = 0x3c + OpcodeI64Store16 Opcode = 0x3d + OpcodeI64Store32 Opcode = 0x3e + OpcodeMemorySize Opcode = 0x3f + OpcodeMemoryGrow Opcode = 0x40 + + // const instructions + + OpcodeI32Const Opcode = 0x41 + OpcodeI64Const Opcode = 0x42 + OpcodeF32Const Opcode = 0x43 + OpcodeF64Const Opcode = 0x44 + + // numeric instructions + + OpcodeI32Eqz Opcode = 0x45 + OpcodeI32Eq Opcode = 0x46 + OpcodeI32Ne Opcode = 0x47 + OpcodeI32LtS Opcode = 0x48 + OpcodeI32LtU Opcode = 0x49 + OpcodeI32GtS Opcode = 0x4a + OpcodeI32GtU Opcode = 0x4b + OpcodeI32LeS Opcode = 0x4c + OpcodeI32LeU Opcode = 0x4d + OpcodeI32GeS Opcode = 0x4e + OpcodeI32GeU Opcode = 0x4f + + OpcodeI64Eqz Opcode = 0x50 + OpcodeI64Eq Opcode = 0x51 + OpcodeI64Ne Opcode = 0x52 + OpcodeI64LtS Opcode = 0x53 + OpcodeI64LtU Opcode = 0x54 + OpcodeI64GtS Opcode = 0x55 + OpcodeI64GtU Opcode = 0x56 + OpcodeI64LeS Opcode = 0x57 + OpcodeI64LeU Opcode = 0x58 + OpcodeI64GeS Opcode = 0x59 + OpcodeI64GeU Opcode = 0x5a + + OpcodeF32Eq Opcode = 0x5b + OpcodeF32Ne Opcode = 0x5c + OpcodeF32Lt Opcode = 0x5d + OpcodeF32Gt Opcode = 0x5e + OpcodeF32Le Opcode = 0x5f + OpcodeF32Ge Opcode = 0x60 + + OpcodeF64Eq Opcode = 0x61 + OpcodeF64Ne Opcode = 0x62 + OpcodeF64Lt Opcode = 0x63 + OpcodeF64Gt Opcode = 0x64 + OpcodeF64Le Opcode = 0x65 + OpcodeF64Ge Opcode = 0x66 + + OpcodeI32Clz Opcode = 0x67 + OpcodeI32Ctz Opcode = 0x68 + OpcodeI32Popcnt Opcode = 0x69 + OpcodeI32Add Opcode = 0x6a + OpcodeI32Sub Opcode = 0x6b + OpcodeI32Mul Opcode = 0x6c + OpcodeI32DivS Opcode = 0x6d + OpcodeI32DivU Opcode = 0x6e + OpcodeI32RemS Opcode = 0x6f + OpcodeI32RemU Opcode = 0x70 + OpcodeI32And Opcode = 0x71 + OpcodeI32Or Opcode = 0x72 + OpcodeI32Xor Opcode = 0x73 + OpcodeI32Shl Opcode = 0x74 + OpcodeI32ShrS Opcode = 0x75 + OpcodeI32ShrU Opcode = 0x76 + OpcodeI32Rotl Opcode = 0x77 + OpcodeI32Rotr Opcode = 0x78 + + OpcodeI64Clz Opcode = 0x79 + OpcodeI64Ctz Opcode = 0x7a + OpcodeI64Popcnt Opcode = 0x7b + OpcodeI64Add Opcode = 0x7c + OpcodeI64Sub Opcode = 0x7d + OpcodeI64Mul Opcode = 0x7e + OpcodeI64DivS Opcode = 0x7f + OpcodeI64DivU Opcode = 0x80 + OpcodeI64RemS Opcode = 0x81 + OpcodeI64RemU Opcode = 0x82 + OpcodeI64And Opcode = 0x83 + OpcodeI64Or Opcode = 0x84 + OpcodeI64Xor Opcode = 0x85 + OpcodeI64Shl Opcode = 0x86 + OpcodeI64ShrS Opcode = 0x87 + OpcodeI64ShrU Opcode = 0x88 + OpcodeI64Rotl Opcode = 0x89 + OpcodeI64Rotr Opcode = 0x8a + + OpcodeF32Abs Opcode = 0x8b + OpcodeF32Neg Opcode = 0x8c + OpcodeF32Ceil Opcode = 0x8d + OpcodeF32Floor Opcode = 0x8e + OpcodeF32Trunc Opcode = 0x8f + OpcodeF32Nearest Opcode = 0x90 + OpcodeF32Sqrt Opcode = 0x91 + OpcodeF32Add Opcode = 0x92 + OpcodeF32Sub Opcode = 0x93 + OpcodeF32Mul Opcode = 0x94 + OpcodeF32Div Opcode = 0x95 + OpcodeF32Min Opcode = 0x96 + OpcodeF32Max Opcode = 0x97 + OpcodeF32Copysign Opcode = 0x98 + + OpcodeF64Abs Opcode = 0x99 + OpcodeF64Neg Opcode = 0x9a + OpcodeF64Ceil Opcode = 0x9b + OpcodeF64Floor Opcode = 0x9c + OpcodeF64Trunc Opcode = 0x9d + OpcodeF64Nearest Opcode = 0x9e + OpcodeF64Sqrt Opcode = 0x9f + OpcodeF64Add Opcode = 0xa0 + OpcodeF64Sub Opcode = 0xa1 + OpcodeF64Mul Opcode = 0xa2 + OpcodeF64Div Opcode = 0xa3 + OpcodeF64Min Opcode = 0xa4 + OpcodeF64Max Opcode = 0xa5 + OpcodeF64Copysign Opcode = 0xa6 + + OpcodeI32WrapI64 Opcode = 0xa7 + OpcodeI32TruncF32S Opcode = 0xa8 + OpcodeI32TruncF32U Opcode = 0xa9 + OpcodeI32TruncF64S Opcode = 0xaa + OpcodeI32TruncF64U Opcode = 0xab + + OpcodeI64ExtendI32S Opcode = 0xac + OpcodeI64ExtendI32U Opcode = 0xad + OpcodeI64TruncF32S Opcode = 0xae + OpcodeI64TruncF32U Opcode = 0xaf + OpcodeI64TruncF64S Opcode = 0xb0 + OpcodeI64TruncF64U Opcode = 0xb1 + + OpcodeF32ConvertI32S Opcode = 0xb2 + OpcodeF32ConvertI32U Opcode = 0xb3 + OpcodeF32ConvertI64S Opcode = 0xb4 + OpcodeF32ConvertI64U Opcode = 0xb5 + OpcodeF32DemoteF64 Opcode = 0xb6 + + OpcodeF64ConvertI32S Opcode = 0xb7 + OpcodeF64ConvertI32U Opcode = 0xb8 + OpcodeF64ConvertI64S Opcode = 0xb9 + OpcodeF64ConvertI64U Opcode = 0xba + OpcodeF64PromoteF32 Opcode = 0xbb + + OpcodeI32ReinterpretF32 Opcode = 0xbc + OpcodeI64ReinterpretF64 Opcode = 0xbd + OpcodeF32ReinterpretI32 Opcode = 0xbe + OpcodeF64ReinterpretI64 Opcode = 0xbf + + // OpcodeRefNull pushes a null reference value whose type is specified by immediate to this opcode. + // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well. + // + // Currently only supported in the constant expression in element segments. + OpcodeRefNull = 0xd0 + // OpcodeRefIsNull pops a reference value, and pushes 1 if it is null, 0 otherwise. + // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well. + // + // Currently not supported. + OpcodeRefIsNull = 0xd1 + // OpcodeRefFunc pushes a funcref value whose index equals the immediate to this opcode. + // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well. + // + // Currently, this is only supported in the constant expression in element segments. + OpcodeRefFunc = 0xd2 + + // Below are toggled with CoreFeatureSignExtensionOps + + // OpcodeI32Extend8S extends a signed 8-bit integer to a 32-bit integer. + // Note: This is dependent on the flag CoreFeatureSignExtensionOps + OpcodeI32Extend8S Opcode = 0xc0 + + // OpcodeI32Extend16S extends a signed 16-bit integer to a 32-bit integer. + // Note: This is dependent on the flag CoreFeatureSignExtensionOps + OpcodeI32Extend16S Opcode = 0xc1 + + // OpcodeI64Extend8S extends a signed 8-bit integer to a 64-bit integer. + // Note: This is dependent on the flag CoreFeatureSignExtensionOps + OpcodeI64Extend8S Opcode = 0xc2 + + // OpcodeI64Extend16S extends a signed 16-bit integer to a 64-bit integer. + // Note: This is dependent on the flag CoreFeatureSignExtensionOps + OpcodeI64Extend16S Opcode = 0xc3 + + // OpcodeI64Extend32S extends a signed 32-bit integer to a 64-bit integer. + // Note: This is dependent on the flag CoreFeatureSignExtensionOps + OpcodeI64Extend32S Opcode = 0xc4 + + // OpcodeMiscPrefix is the prefix of various multi-byte opcodes. + // Introduced in CoreFeatureNonTrappingFloatToIntConversion, but used in other + // features, such as CoreFeatureBulkMemoryOperations. + OpcodeMiscPrefix Opcode = 0xfc + + // OpcodeVecPrefix is the prefix of all vector isntructions introduced in + // CoreFeatureSIMD. + OpcodeVecPrefix Opcode = 0xfd + + // OpcodeAtomicPrefix is the prefix of all atomic instructions introduced in + // CoreFeatureThreads. + OpcodeAtomicPrefix Opcode = 0xfe +) + +// OpcodeMisc represents opcodes of the miscellaneous operations. +// Such an operations has multi-byte encoding which is prefixed by OpcodeMiscPrefix. +type OpcodeMisc = byte + +const ( + // Below are toggled with CoreFeatureNonTrappingFloatToIntConversion. + // https://github.com/WebAssembly/spec/blob/ce4b6c4d47eb06098cc7ab2e81f24748da822f20/proposals/nontrapping-float-to-int-conversion/Overview.md + + OpcodeMiscI32TruncSatF32S OpcodeMisc = 0x00 + OpcodeMiscI32TruncSatF32U OpcodeMisc = 0x01 + OpcodeMiscI32TruncSatF64S OpcodeMisc = 0x02 + OpcodeMiscI32TruncSatF64U OpcodeMisc = 0x03 + OpcodeMiscI64TruncSatF32S OpcodeMisc = 0x04 + OpcodeMiscI64TruncSatF32U OpcodeMisc = 0x05 + OpcodeMiscI64TruncSatF64S OpcodeMisc = 0x06 + OpcodeMiscI64TruncSatF64U OpcodeMisc = 0x07 + + // Below are toggled with CoreFeatureBulkMemoryOperations. + // Opcodes are those new in document/core/appendix/index-instructions.rst (the commit that merged the feature). + // See https://github.com/WebAssembly/spec/commit/7fa2f20a6df4cf1c114582c8cb60f5bfcdbf1be1 + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions + + OpcodeMiscMemoryInit OpcodeMisc = 0x08 + OpcodeMiscDataDrop OpcodeMisc = 0x09 + OpcodeMiscMemoryCopy OpcodeMisc = 0x0a + OpcodeMiscMemoryFill OpcodeMisc = 0x0b + OpcodeMiscTableInit OpcodeMisc = 0x0c + OpcodeMiscElemDrop OpcodeMisc = 0x0d + OpcodeMiscTableCopy OpcodeMisc = 0x0e + + // Below are toggled with CoreFeatureReferenceTypes + + OpcodeMiscTableGrow OpcodeMisc = 0x0f + OpcodeMiscTableSize OpcodeMisc = 0x10 + OpcodeMiscTableFill OpcodeMisc = 0x11 +) + +// OpcodeVec represents an opcode of a vector instructions which has +// multi-byte encoding and is prefixed by OpcodeMiscPrefix. +// +// These opcodes are toggled with CoreFeatureSIMD. +type OpcodeVec = byte + +const ( + // Loads and stores. + + OpcodeVecV128Load OpcodeVec = 0x00 + OpcodeVecV128Load8x8s OpcodeVec = 0x01 + OpcodeVecV128Load8x8u OpcodeVec = 0x02 + OpcodeVecV128Load16x4s OpcodeVec = 0x03 + OpcodeVecV128Load16x4u OpcodeVec = 0x04 + OpcodeVecV128Load32x2s OpcodeVec = 0x05 + OpcodeVecV128Load32x2u OpcodeVec = 0x06 + OpcodeVecV128Load8Splat OpcodeVec = 0x07 + OpcodeVecV128Load16Splat OpcodeVec = 0x08 + OpcodeVecV128Load32Splat OpcodeVec = 0x09 + OpcodeVecV128Load64Splat OpcodeVec = 0x0a + + OpcodeVecV128Load32zero OpcodeVec = 0x5c + OpcodeVecV128Load64zero OpcodeVec = 0x5d + + OpcodeVecV128Store OpcodeVec = 0x0b + OpcodeVecV128Load8Lane OpcodeVec = 0x54 + OpcodeVecV128Load16Lane OpcodeVec = 0x55 + OpcodeVecV128Load32Lane OpcodeVec = 0x56 + OpcodeVecV128Load64Lane OpcodeVec = 0x57 + OpcodeVecV128Store8Lane OpcodeVec = 0x58 + OpcodeVecV128Store16Lane OpcodeVec = 0x59 + OpcodeVecV128Store32Lane OpcodeVec = 0x5a + OpcodeVecV128Store64Lane OpcodeVec = 0x5b + + // OpcodeVecV128Const is the vector const instruction. + OpcodeVecV128Const OpcodeVec = 0x0c + + // OpcodeVecV128i8x16Shuffle is the vector shuffle instruction. + OpcodeVecV128i8x16Shuffle OpcodeVec = 0x0d + + // Extrac and replaces. + + OpcodeVecI8x16ExtractLaneS OpcodeVec = 0x15 + OpcodeVecI8x16ExtractLaneU OpcodeVec = 0x16 + OpcodeVecI8x16ReplaceLane OpcodeVec = 0x17 + OpcodeVecI16x8ExtractLaneS OpcodeVec = 0x18 + OpcodeVecI16x8ExtractLaneU OpcodeVec = 0x19 + OpcodeVecI16x8ReplaceLane OpcodeVec = 0x1a + OpcodeVecI32x4ExtractLane OpcodeVec = 0x1b + OpcodeVecI32x4ReplaceLane OpcodeVec = 0x1c + OpcodeVecI64x2ExtractLane OpcodeVec = 0x1d + OpcodeVecI64x2ReplaceLane OpcodeVec = 0x1e + OpcodeVecF32x4ExtractLane OpcodeVec = 0x1f + OpcodeVecF32x4ReplaceLane OpcodeVec = 0x20 + OpcodeVecF64x2ExtractLane OpcodeVec = 0x21 + OpcodeVecF64x2ReplaceLane OpcodeVec = 0x22 + + // Splat and swizzle. + + OpcodeVecI8x16Swizzle OpcodeVec = 0x0e + OpcodeVecI8x16Splat OpcodeVec = 0x0f + OpcodeVecI16x8Splat OpcodeVec = 0x10 + OpcodeVecI32x4Splat OpcodeVec = 0x11 + OpcodeVecI64x2Splat OpcodeVec = 0x12 + OpcodeVecF32x4Splat OpcodeVec = 0x13 + OpcodeVecF64x2Splat OpcodeVec = 0x14 + + // i8 comparisons. + + OpcodeVecI8x16Eq OpcodeVec = 0x23 + OpcodeVecI8x16Ne OpcodeVec = 0x24 + OpcodeVecI8x16LtS OpcodeVec = 0x25 + OpcodeVecI8x16LtU OpcodeVec = 0x26 + OpcodeVecI8x16GtS OpcodeVec = 0x27 + OpcodeVecI8x16GtU OpcodeVec = 0x28 + OpcodeVecI8x16LeS OpcodeVec = 0x29 + OpcodeVecI8x16LeU OpcodeVec = 0x2a + OpcodeVecI8x16GeS OpcodeVec = 0x2b + OpcodeVecI8x16GeU OpcodeVec = 0x2c + + // i16 comparisons. + + OpcodeVecI16x8Eq OpcodeVec = 0x2d + OpcodeVecI16x8Ne OpcodeVec = 0x2e + OpcodeVecI16x8LtS OpcodeVec = 0x2f + OpcodeVecI16x8LtU OpcodeVec = 0x30 + OpcodeVecI16x8GtS OpcodeVec = 0x31 + OpcodeVecI16x8GtU OpcodeVec = 0x32 + OpcodeVecI16x8LeS OpcodeVec = 0x33 + OpcodeVecI16x8LeU OpcodeVec = 0x34 + OpcodeVecI16x8GeS OpcodeVec = 0x35 + OpcodeVecI16x8GeU OpcodeVec = 0x36 + + // i32 comparisons. + + OpcodeVecI32x4Eq OpcodeVec = 0x37 + OpcodeVecI32x4Ne OpcodeVec = 0x38 + OpcodeVecI32x4LtS OpcodeVec = 0x39 + OpcodeVecI32x4LtU OpcodeVec = 0x3a + OpcodeVecI32x4GtS OpcodeVec = 0x3b + OpcodeVecI32x4GtU OpcodeVec = 0x3c + OpcodeVecI32x4LeS OpcodeVec = 0x3d + OpcodeVecI32x4LeU OpcodeVec = 0x3e + OpcodeVecI32x4GeS OpcodeVec = 0x3f + OpcodeVecI32x4GeU OpcodeVec = 0x40 + + // i64 comparisons. + + OpcodeVecI64x2Eq OpcodeVec = 0xd6 + OpcodeVecI64x2Ne OpcodeVec = 0xd7 + OpcodeVecI64x2LtS OpcodeVec = 0xd8 + OpcodeVecI64x2GtS OpcodeVec = 0xd9 + OpcodeVecI64x2LeS OpcodeVec = 0xda + OpcodeVecI64x2GeS OpcodeVec = 0xdb + + // f32 comparisons. + + OpcodeVecF32x4Eq OpcodeVec = 0x41 + OpcodeVecF32x4Ne OpcodeVec = 0x42 + OpcodeVecF32x4Lt OpcodeVec = 0x43 + OpcodeVecF32x4Gt OpcodeVec = 0x44 + OpcodeVecF32x4Le OpcodeVec = 0x45 + OpcodeVecF32x4Ge OpcodeVec = 0x46 + + // f64 comparisons. + + OpcodeVecF64x2Eq OpcodeVec = 0x47 + OpcodeVecF64x2Ne OpcodeVec = 0x48 + OpcodeVecF64x2Lt OpcodeVec = 0x49 + OpcodeVecF64x2Gt OpcodeVec = 0x4a + OpcodeVecF64x2Le OpcodeVec = 0x4b + OpcodeVecF64x2Ge OpcodeVec = 0x4c + + // v128 logical instructions. + + OpcodeVecV128Not OpcodeVec = 0x4d + OpcodeVecV128And OpcodeVec = 0x4e + OpcodeVecV128AndNot OpcodeVec = 0x4f + OpcodeVecV128Or OpcodeVec = 0x50 + OpcodeVecV128Xor OpcodeVec = 0x51 + OpcodeVecV128Bitselect OpcodeVec = 0x52 + OpcodeVecV128AnyTrue OpcodeVec = 0x53 + + // i8 misc. + + OpcodeVecI8x16Abs OpcodeVec = 0x60 + OpcodeVecI8x16Neg OpcodeVec = 0x61 + OpcodeVecI8x16Popcnt OpcodeVec = 0x62 + OpcodeVecI8x16AllTrue OpcodeVec = 0x63 + OpcodeVecI8x16BitMask OpcodeVec = 0x64 + OpcodeVecI8x16NarrowI16x8S OpcodeVec = 0x65 + OpcodeVecI8x16NarrowI16x8U OpcodeVec = 0x66 + + OpcodeVecI8x16Shl OpcodeVec = 0x6b + OpcodeVecI8x16ShrS OpcodeVec = 0x6c + OpcodeVecI8x16ShrU OpcodeVec = 0x6d + OpcodeVecI8x16Add OpcodeVec = 0x6e + OpcodeVecI8x16AddSatS OpcodeVec = 0x6f + + OpcodeVecI8x16AddSatU OpcodeVec = 0x70 + OpcodeVecI8x16Sub OpcodeVec = 0x71 + OpcodeVecI8x16SubSatS OpcodeVec = 0x72 + OpcodeVecI8x16SubSatU OpcodeVec = 0x73 + OpcodeVecI8x16MinS OpcodeVec = 0x76 + OpcodeVecI8x16MinU OpcodeVec = 0x77 + OpcodeVecI8x16MaxS OpcodeVec = 0x78 + OpcodeVecI8x16MaxU OpcodeVec = 0x79 + OpcodeVecI8x16AvgrU OpcodeVec = 0x7b + + // i16 misc. + + OpcodeVecI16x8ExtaddPairwiseI8x16S OpcodeVec = 0x7c + OpcodeVecI16x8ExtaddPairwiseI8x16U OpcodeVec = 0x7d + OpcodeVecI16x8Abs OpcodeVec = 0x80 + OpcodeVecI16x8Neg OpcodeVec = 0x81 + OpcodeVecI16x8Q15mulrSatS OpcodeVec = 0x82 + OpcodeVecI16x8AllTrue OpcodeVec = 0x83 + OpcodeVecI16x8BitMask OpcodeVec = 0x84 + OpcodeVecI16x8NarrowI32x4S OpcodeVec = 0x85 + OpcodeVecI16x8NarrowI32x4U OpcodeVec = 0x86 + OpcodeVecI16x8ExtendLowI8x16S OpcodeVec = 0x87 + OpcodeVecI16x8ExtendHighI8x16S OpcodeVec = 0x88 + OpcodeVecI16x8ExtendLowI8x16U OpcodeVec = 0x89 + OpcodeVecI16x8ExtendHighI8x16U OpcodeVec = 0x8a + OpcodeVecI16x8Shl OpcodeVec = 0x8b + OpcodeVecI16x8ShrS OpcodeVec = 0x8c + OpcodeVecI16x8ShrU OpcodeVec = 0x8d + OpcodeVecI16x8Add OpcodeVec = 0x8e + OpcodeVecI16x8AddSatS OpcodeVec = 0x8f + OpcodeVecI16x8AddSatU OpcodeVec = 0x90 + OpcodeVecI16x8Sub OpcodeVec = 0x91 + OpcodeVecI16x8SubSatS OpcodeVec = 0x92 + OpcodeVecI16x8SubSatU OpcodeVec = 0x93 + OpcodeVecI16x8Mul OpcodeVec = 0x95 + OpcodeVecI16x8MinS OpcodeVec = 0x96 + OpcodeVecI16x8MinU OpcodeVec = 0x97 + OpcodeVecI16x8MaxS OpcodeVec = 0x98 + OpcodeVecI16x8MaxU OpcodeVec = 0x99 + OpcodeVecI16x8AvgrU OpcodeVec = 0x9b + OpcodeVecI16x8ExtMulLowI8x16S OpcodeVec = 0x9c + OpcodeVecI16x8ExtMulHighI8x16S OpcodeVec = 0x9d + OpcodeVecI16x8ExtMulLowI8x16U OpcodeVec = 0x9e + OpcodeVecI16x8ExtMulHighI8x16U OpcodeVec = 0x9f + + // i32 misc. + + OpcodeVecI32x4ExtaddPairwiseI16x8S OpcodeVec = 0x7e + OpcodeVecI32x4ExtaddPairwiseI16x8U OpcodeVec = 0x7f + OpcodeVecI32x4Abs OpcodeVec = 0xa0 + OpcodeVecI32x4Neg OpcodeVec = 0xa1 + OpcodeVecI32x4AllTrue OpcodeVec = 0xa3 + OpcodeVecI32x4BitMask OpcodeVec = 0xa4 + OpcodeVecI32x4ExtendLowI16x8S OpcodeVec = 0xa7 + OpcodeVecI32x4ExtendHighI16x8S OpcodeVec = 0xa8 + OpcodeVecI32x4ExtendLowI16x8U OpcodeVec = 0xa9 + OpcodeVecI32x4ExtendHighI16x8U OpcodeVec = 0xaa + OpcodeVecI32x4Shl OpcodeVec = 0xab + OpcodeVecI32x4ShrS OpcodeVec = 0xac + OpcodeVecI32x4ShrU OpcodeVec = 0xad + OpcodeVecI32x4Add OpcodeVec = 0xae + OpcodeVecI32x4Sub OpcodeVec = 0xb1 + OpcodeVecI32x4Mul OpcodeVec = 0xb5 + OpcodeVecI32x4MinS OpcodeVec = 0xb6 + OpcodeVecI32x4MinU OpcodeVec = 0xb7 + OpcodeVecI32x4MaxS OpcodeVec = 0xb8 + OpcodeVecI32x4MaxU OpcodeVec = 0xb9 + OpcodeVecI32x4DotI16x8S OpcodeVec = 0xba + OpcodeVecI32x4ExtMulLowI16x8S OpcodeVec = 0xbc + OpcodeVecI32x4ExtMulHighI16x8S OpcodeVec = 0xbd + OpcodeVecI32x4ExtMulLowI16x8U OpcodeVec = 0xbe + OpcodeVecI32x4ExtMulHighI16x8U OpcodeVec = 0xbf + + // i64 misc. + + OpcodeVecI64x2Abs OpcodeVec = 0xc0 + OpcodeVecI64x2Neg OpcodeVec = 0xc1 + OpcodeVecI64x2AllTrue OpcodeVec = 0xc3 + OpcodeVecI64x2BitMask OpcodeVec = 0xc4 + OpcodeVecI64x2ExtendLowI32x4S OpcodeVec = 0xc7 + OpcodeVecI64x2ExtendHighI32x4S OpcodeVec = 0xc8 + OpcodeVecI64x2ExtendLowI32x4U OpcodeVec = 0xc9 + OpcodeVecI64x2ExtendHighI32x4U OpcodeVec = 0xca + OpcodeVecI64x2Shl OpcodeVec = 0xcb + OpcodeVecI64x2ShrS OpcodeVec = 0xcc + OpcodeVecI64x2ShrU OpcodeVec = 0xcd + OpcodeVecI64x2Add OpcodeVec = 0xce + OpcodeVecI64x2Sub OpcodeVec = 0xd1 + OpcodeVecI64x2Mul OpcodeVec = 0xd5 + OpcodeVecI64x2ExtMulLowI32x4S OpcodeVec = 0xdc + OpcodeVecI64x2ExtMulHighI32x4S OpcodeVec = 0xdd + OpcodeVecI64x2ExtMulLowI32x4U OpcodeVec = 0xde + OpcodeVecI64x2ExtMulHighI32x4U OpcodeVec = 0xdf + + // f32 misc. + + OpcodeVecF32x4Ceil OpcodeVec = 0x67 + OpcodeVecF32x4Floor OpcodeVec = 0x68 + OpcodeVecF32x4Trunc OpcodeVec = 0x69 + OpcodeVecF32x4Nearest OpcodeVec = 0x6a + OpcodeVecF32x4Abs OpcodeVec = 0xe0 + OpcodeVecF32x4Neg OpcodeVec = 0xe1 + OpcodeVecF32x4Sqrt OpcodeVec = 0xe3 + OpcodeVecF32x4Add OpcodeVec = 0xe4 + OpcodeVecF32x4Sub OpcodeVec = 0xe5 + OpcodeVecF32x4Mul OpcodeVec = 0xe6 + OpcodeVecF32x4Div OpcodeVec = 0xe7 + OpcodeVecF32x4Min OpcodeVec = 0xe8 + OpcodeVecF32x4Max OpcodeVec = 0xe9 + OpcodeVecF32x4Pmin OpcodeVec = 0xea + OpcodeVecF32x4Pmax OpcodeVec = 0xeb + + // f64 misc. + + OpcodeVecF64x2Ceil OpcodeVec = 0x74 + OpcodeVecF64x2Floor OpcodeVec = 0x75 + OpcodeVecF64x2Trunc OpcodeVec = 0x7a + OpcodeVecF64x2Nearest OpcodeVec = 0x94 + OpcodeVecF64x2Abs OpcodeVec = 0xec + OpcodeVecF64x2Neg OpcodeVec = 0xed + OpcodeVecF64x2Sqrt OpcodeVec = 0xef + OpcodeVecF64x2Add OpcodeVec = 0xf0 + OpcodeVecF64x2Sub OpcodeVec = 0xf1 + OpcodeVecF64x2Mul OpcodeVec = 0xf2 + OpcodeVecF64x2Div OpcodeVec = 0xf3 + OpcodeVecF64x2Min OpcodeVec = 0xf4 + OpcodeVecF64x2Max OpcodeVec = 0xf5 + OpcodeVecF64x2Pmin OpcodeVec = 0xf6 + OpcodeVecF64x2Pmax OpcodeVec = 0xf7 + + // conversions. + + OpcodeVecI32x4TruncSatF32x4S OpcodeVec = 0xf8 + OpcodeVecI32x4TruncSatF32x4U OpcodeVec = 0xf9 + OpcodeVecF32x4ConvertI32x4S OpcodeVec = 0xfa + OpcodeVecF32x4ConvertI32x4U OpcodeVec = 0xfb + OpcodeVecI32x4TruncSatF64x2SZero OpcodeVec = 0xfc + OpcodeVecI32x4TruncSatF64x2UZero OpcodeVec = 0xfd + OpcodeVecF64x2ConvertLowI32x4S OpcodeVec = 0xfe + OpcodeVecF64x2ConvertLowI32x4U OpcodeVec = 0xff + OpcodeVecF32x4DemoteF64x2Zero OpcodeVec = 0x5e + OpcodeVecF64x2PromoteLowF32x4Zero OpcodeVec = 0x5f +) + +// OpcodeAtomic represents an opcode of atomic instructions which has +// multi-byte encoding and is prefixed by OpcodeAtomicPrefix. +// +// These opcodes are toggled with CoreFeaturesThreads. +type OpcodeAtomic = byte + +const ( + // OpcodeAtomicMemoryNotify represents the instruction memory.atomic.notify. + OpcodeAtomicMemoryNotify OpcodeAtomic = 0x00 + // OpcodeAtomicMemoryWait32 represents the instruction memory.atomic.wait32. + OpcodeAtomicMemoryWait32 OpcodeAtomic = 0x01 + // OpcodeAtomicMemoryWait64 represents the instruction memory.atomic.wait64. + OpcodeAtomicMemoryWait64 OpcodeAtomic = 0x02 + // OpcodeAtomicFence represents the instruction atomic.fence. + OpcodeAtomicFence OpcodeAtomic = 0x03 + + // OpcodeAtomicI32Load represents the instruction i32.atomic.load. + OpcodeAtomicI32Load OpcodeAtomic = 0x10 + // OpcodeAtomicI64Load represents the instruction i64.atomic.load. + OpcodeAtomicI64Load OpcodeAtomic = 0x11 + // OpcodeAtomicI32Load8U represents the instruction i32.atomic.load8_u. + OpcodeAtomicI32Load8U OpcodeAtomic = 0x12 + // OpcodeAtomicI32Load16U represents the instruction i32.atomic.load16_u. + OpcodeAtomicI32Load16U OpcodeAtomic = 0x13 + // OpcodeAtomicI64Load8U represents the instruction i64.atomic.load8_u. + OpcodeAtomicI64Load8U OpcodeAtomic = 0x14 + // OpcodeAtomicI64Load16U represents the instruction i64.atomic.load16_u. + OpcodeAtomicI64Load16U OpcodeAtomic = 0x15 + // OpcodeAtomicI64Load32U represents the instruction i64.atomic.load32_u. + OpcodeAtomicI64Load32U OpcodeAtomic = 0x16 + // OpcodeAtomicI32Store represents the instruction i32.atomic.store. + OpcodeAtomicI32Store OpcodeAtomic = 0x17 + // OpcodeAtomicI64Store represents the instruction i64.atomic.store. + OpcodeAtomicI64Store OpcodeAtomic = 0x18 + // OpcodeAtomicI32Store8 represents the instruction i32.atomic.store8. + OpcodeAtomicI32Store8 OpcodeAtomic = 0x19 + // OpcodeAtomicI32Store16 represents the instruction i32.atomic.store16. + OpcodeAtomicI32Store16 OpcodeAtomic = 0x1a + // OpcodeAtomicI64Store8 represents the instruction i64.atomic.store8. + OpcodeAtomicI64Store8 OpcodeAtomic = 0x1b + // OpcodeAtomicI64Store16 represents the instruction i64.atomic.store16. + OpcodeAtomicI64Store16 OpcodeAtomic = 0x1c + // OpcodeAtomicI64Store32 represents the instruction i64.atomic.store32. + OpcodeAtomicI64Store32 OpcodeAtomic = 0x1d + + // OpcodeAtomicI32RmwAdd represents the instruction i32.atomic.rmw.add. + OpcodeAtomicI32RmwAdd OpcodeAtomic = 0x1e + // OpcodeAtomicI64RmwAdd represents the instruction i64.atomic.rmw.add. + OpcodeAtomicI64RmwAdd OpcodeAtomic = 0x1f + // OpcodeAtomicI32Rmw8AddU represents the instruction i32.atomic.rmw8.add_u. + OpcodeAtomicI32Rmw8AddU OpcodeAtomic = 0x20 + // OpcodeAtomicI32Rmw16AddU represents the instruction i32.atomic.rmw16.add_u. + OpcodeAtomicI32Rmw16AddU OpcodeAtomic = 0x21 + // OpcodeAtomicI64Rmw8AddU represents the instruction i64.atomic.rmw8.add_u. + OpcodeAtomicI64Rmw8AddU OpcodeAtomic = 0x22 + // OpcodeAtomicI64Rmw16AddU represents the instruction i64.atomic.rmw16.add_u. + OpcodeAtomicI64Rmw16AddU OpcodeAtomic = 0x23 + // OpcodeAtomicI64Rmw32AddU represents the instruction i64.atomic.rmw32.add_u. + OpcodeAtomicI64Rmw32AddU OpcodeAtomic = 0x24 + + // OpcodeAtomicI32RmwSub represents the instruction i32.atomic.rmw.sub. + OpcodeAtomicI32RmwSub OpcodeAtomic = 0x25 + // OpcodeAtomicI64RmwSub represents the instruction i64.atomic.rmw.sub. + OpcodeAtomicI64RmwSub OpcodeAtomic = 0x26 + // OpcodeAtomicI32Rmw8SubU represents the instruction i32.atomic.rmw8.sub_u. + OpcodeAtomicI32Rmw8SubU OpcodeAtomic = 0x27 + // OpcodeAtomicI32Rmw16SubU represents the instruction i32.atomic.rmw16.sub_u. + OpcodeAtomicI32Rmw16SubU OpcodeAtomic = 0x28 + // OpcodeAtomicI64Rmw8SubU represents the instruction i64.atomic.rmw8.sub_u. + OpcodeAtomicI64Rmw8SubU OpcodeAtomic = 0x29 + // OpcodeAtomicI64Rmw16SubU represents the instruction i64.atomic.rmw16.sub_u. + OpcodeAtomicI64Rmw16SubU OpcodeAtomic = 0x2a + // OpcodeAtomicI64Rmw32SubU represents the instruction i64.atomic.rmw32.sub_u. + OpcodeAtomicI64Rmw32SubU OpcodeAtomic = 0x2b + + // OpcodeAtomicI32RmwAnd represents the instruction i32.atomic.rmw.and. + OpcodeAtomicI32RmwAnd OpcodeAtomic = 0x2c + // OpcodeAtomicI64RmwAnd represents the instruction i64.atomic.rmw.and. + OpcodeAtomicI64RmwAnd OpcodeAtomic = 0x2d + // OpcodeAtomicI32Rmw8AndU represents the instruction i32.atomic.rmw8.and_u. + OpcodeAtomicI32Rmw8AndU OpcodeAtomic = 0x2e + // OpcodeAtomicI32Rmw16AndU represents the instruction i32.atomic.rmw16.and_u. + OpcodeAtomicI32Rmw16AndU OpcodeAtomic = 0x2f + // OpcodeAtomicI64Rmw8AndU represents the instruction i64.atomic.rmw8.and_u. + OpcodeAtomicI64Rmw8AndU OpcodeAtomic = 0x30 + // OpcodeAtomicI64Rmw16AndU represents the instruction i64.atomic.rmw16.and_u. + OpcodeAtomicI64Rmw16AndU OpcodeAtomic = 0x31 + // OpcodeAtomicI64Rmw32AndU represents the instruction i64.atomic.rmw32.and_u. + OpcodeAtomicI64Rmw32AndU OpcodeAtomic = 0x32 + + // OpcodeAtomicI32RmwOr represents the instruction i32.atomic.rmw.or. + OpcodeAtomicI32RmwOr OpcodeAtomic = 0x33 + // OpcodeAtomicI64RmwOr represents the instruction i64.atomic.rmw.or. + OpcodeAtomicI64RmwOr OpcodeAtomic = 0x34 + // OpcodeAtomicI32Rmw8OrU represents the instruction i32.atomic.rmw8.or_u. + OpcodeAtomicI32Rmw8OrU OpcodeAtomic = 0x35 + // OpcodeAtomicI32Rmw16OrU represents the instruction i32.atomic.rmw16.or_u. + OpcodeAtomicI32Rmw16OrU OpcodeAtomic = 0x36 + // OpcodeAtomicI64Rmw8OrU represents the instruction i64.atomic.rmw8.or_u. + OpcodeAtomicI64Rmw8OrU OpcodeAtomic = 0x37 + // OpcodeAtomicI64Rmw16OrU represents the instruction i64.atomic.rmw16.or_u. + OpcodeAtomicI64Rmw16OrU OpcodeAtomic = 0x38 + // OpcodeAtomicI64Rmw32OrU represents the instruction i64.atomic.rmw32.or_u. + OpcodeAtomicI64Rmw32OrU OpcodeAtomic = 0x39 + + // OpcodeAtomicI32RmwXor represents the instruction i32.atomic.rmw.xor. + OpcodeAtomicI32RmwXor OpcodeAtomic = 0x3a + // OpcodeAtomicI64RmwXor represents the instruction i64.atomic.rmw.xor. + OpcodeAtomicI64RmwXor OpcodeAtomic = 0x3b + // OpcodeAtomicI32Rmw8XorU represents the instruction i32.atomic.rmw8.xor_u. + OpcodeAtomicI32Rmw8XorU OpcodeAtomic = 0x3c + // OpcodeAtomicI32Rmw16XorU represents the instruction i32.atomic.rmw16.xor_u. + OpcodeAtomicI32Rmw16XorU OpcodeAtomic = 0x3d + // OpcodeAtomicI64Rmw8XorU represents the instruction i64.atomic.rmw8.xor_u. + OpcodeAtomicI64Rmw8XorU OpcodeAtomic = 0x3e + // OpcodeAtomicI64Rmw16XorU represents the instruction i64.atomic.rmw16.xor_u. + OpcodeAtomicI64Rmw16XorU OpcodeAtomic = 0x3f + // OpcodeAtomicI64Rmw32XorU represents the instruction i64.atomic.rmw32.xor_u. + OpcodeAtomicI64Rmw32XorU OpcodeAtomic = 0x40 + + // OpcodeAtomicI32RmwXchg represents the instruction i32.atomic.rmw.xchg. + OpcodeAtomicI32RmwXchg OpcodeAtomic = 0x41 + // OpcodeAtomicI64RmwXchg represents the instruction i64.atomic.rmw.xchg. + OpcodeAtomicI64RmwXchg OpcodeAtomic = 0x42 + // OpcodeAtomicI32Rmw8XchgU represents the instruction i32.atomic.rmw8.xchg_u. + OpcodeAtomicI32Rmw8XchgU OpcodeAtomic = 0x43 + // OpcodeAtomicI32Rmw16XchgU represents the instruction i32.atomic.rmw16.xchg_u. + OpcodeAtomicI32Rmw16XchgU OpcodeAtomic = 0x44 + // OpcodeAtomicI64Rmw8XchgU represents the instruction i64.atomic.rmw8.xchg_u. + OpcodeAtomicI64Rmw8XchgU OpcodeAtomic = 0x45 + // OpcodeAtomicI64Rmw16XchgU represents the instruction i64.atomic.rmw16.xchg_u. + OpcodeAtomicI64Rmw16XchgU OpcodeAtomic = 0x46 + // OpcodeAtomicI64Rmw32XchgU represents the instruction i64.atomic.rmw32.xchg_u. + OpcodeAtomicI64Rmw32XchgU OpcodeAtomic = 0x47 + + // OpcodeAtomicI32RmwCmpxchg represents the instruction i32.atomic.rmw.cmpxchg. + OpcodeAtomicI32RmwCmpxchg OpcodeAtomic = 0x48 + // OpcodeAtomicI64RmwCmpxchg represents the instruction i64.atomic.rmw.cmpxchg. + OpcodeAtomicI64RmwCmpxchg OpcodeAtomic = 0x49 + // OpcodeAtomicI32Rmw8CmpxchgU represents the instruction i32.atomic.rmw8.cmpxchg_u. + OpcodeAtomicI32Rmw8CmpxchgU OpcodeAtomic = 0x4a + // OpcodeAtomicI32Rmw16CmpxchgU represents the instruction i32.atomic.rmw16.cmpxchg_u. + OpcodeAtomicI32Rmw16CmpxchgU OpcodeAtomic = 0x4b + // OpcodeAtomicI64Rmw8CmpxchgU represents the instruction i64.atomic.rmw8.cmpxchg_u. + OpcodeAtomicI64Rmw8CmpxchgU OpcodeAtomic = 0x4c + // OpcodeAtomicI64Rmw16CmpxchgU represents the instruction i64.atomic.rmw16.cmpxchg_u. + OpcodeAtomicI64Rmw16CmpxchgU OpcodeAtomic = 0x4d + // OpcodeAtomicI64Rmw32CmpxchgU represents the instruction i64.atomic.rmw32.cmpxchg_u. + OpcodeAtomicI64Rmw32CmpxchgU OpcodeAtomic = 0x4e +) + +const ( + OpcodeUnreachableName = "unreachable" + OpcodeNopName = "nop" + OpcodeBlockName = "block" + OpcodeLoopName = "loop" + OpcodeIfName = "if" + OpcodeElseName = "else" + OpcodeEndName = "end" + OpcodeBrName = "br" + OpcodeBrIfName = "br_if" + OpcodeBrTableName = "br_table" + OpcodeReturnName = "return" + OpcodeCallName = "call" + OpcodeCallIndirectName = "call_indirect" + OpcodeDropName = "drop" + OpcodeSelectName = "select" + OpcodeTypedSelectName = "typed_select" + OpcodeLocalGetName = "local.get" + OpcodeLocalSetName = "local.set" + OpcodeLocalTeeName = "local.tee" + OpcodeGlobalGetName = "global.get" + OpcodeGlobalSetName = "global.set" + OpcodeI32LoadName = "i32.load" + OpcodeI64LoadName = "i64.load" + OpcodeF32LoadName = "f32.load" + OpcodeF64LoadName = "f64.load" + OpcodeI32Load8SName = "i32.load8_s" + OpcodeI32Load8UName = "i32.load8_u" + OpcodeI32Load16SName = "i32.load16_s" + OpcodeI32Load16UName = "i32.load16_u" + OpcodeI64Load8SName = "i64.load8_s" + OpcodeI64Load8UName = "i64.load8_u" + OpcodeI64Load16SName = "i64.load16_s" + OpcodeI64Load16UName = "i64.load16_u" + OpcodeI64Load32SName = "i64.load32_s" + OpcodeI64Load32UName = "i64.load32_u" + OpcodeI32StoreName = "i32.store" + OpcodeI64StoreName = "i64.store" + OpcodeF32StoreName = "f32.store" + OpcodeF64StoreName = "f64.store" + OpcodeI32Store8Name = "i32.store8" + OpcodeI32Store16Name = "i32.store16" + OpcodeI64Store8Name = "i64.store8" + OpcodeI64Store16Name = "i64.store16" + OpcodeI64Store32Name = "i64.store32" + OpcodeMemorySizeName = "memory.size" + OpcodeMemoryGrowName = "memory.grow" + OpcodeI32ConstName = "i32.const" + OpcodeI64ConstName = "i64.const" + OpcodeF32ConstName = "f32.const" + OpcodeF64ConstName = "f64.const" + OpcodeI32EqzName = "i32.eqz" + OpcodeI32EqName = "i32.eq" + OpcodeI32NeName = "i32.ne" + OpcodeI32LtSName = "i32.lt_s" + OpcodeI32LtUName = "i32.lt_u" + OpcodeI32GtSName = "i32.gt_s" + OpcodeI32GtUName = "i32.gt_u" + OpcodeI32LeSName = "i32.le_s" + OpcodeI32LeUName = "i32.le_u" + OpcodeI32GeSName = "i32.ge_s" + OpcodeI32GeUName = "i32.ge_u" + OpcodeI64EqzName = "i64.eqz" + OpcodeI64EqName = "i64.eq" + OpcodeI64NeName = "i64.ne" + OpcodeI64LtSName = "i64.lt_s" + OpcodeI64LtUName = "i64.lt_u" + OpcodeI64GtSName = "i64.gt_s" + OpcodeI64GtUName = "i64.gt_u" + OpcodeI64LeSName = "i64.le_s" + OpcodeI64LeUName = "i64.le_u" + OpcodeI64GeSName = "i64.ge_s" + OpcodeI64GeUName = "i64.ge_u" + OpcodeF32EqName = "f32.eq" + OpcodeF32NeName = "f32.ne" + OpcodeF32LtName = "f32.lt" + OpcodeF32GtName = "f32.gt" + OpcodeF32LeName = "f32.le" + OpcodeF32GeName = "f32.ge" + OpcodeF64EqName = "f64.eq" + OpcodeF64NeName = "f64.ne" + OpcodeF64LtName = "f64.lt" + OpcodeF64GtName = "f64.gt" + OpcodeF64LeName = "f64.le" + OpcodeF64GeName = "f64.ge" + OpcodeI32ClzName = "i32.clz" + OpcodeI32CtzName = "i32.ctz" + OpcodeI32PopcntName = "i32.popcnt" + OpcodeI32AddName = "i32.add" + OpcodeI32SubName = "i32.sub" + OpcodeI32MulName = "i32.mul" + OpcodeI32DivSName = "i32.div_s" + OpcodeI32DivUName = "i32.div_u" + OpcodeI32RemSName = "i32.rem_s" + OpcodeI32RemUName = "i32.rem_u" + OpcodeI32AndName = "i32.and" + OpcodeI32OrName = "i32.or" + OpcodeI32XorName = "i32.xor" + OpcodeI32ShlName = "i32.shl" + OpcodeI32ShrSName = "i32.shr_s" + OpcodeI32ShrUName = "i32.shr_u" + OpcodeI32RotlName = "i32.rotl" + OpcodeI32RotrName = "i32.rotr" + OpcodeI64ClzName = "i64.clz" + OpcodeI64CtzName = "i64.ctz" + OpcodeI64PopcntName = "i64.popcnt" + OpcodeI64AddName = "i64.add" + OpcodeI64SubName = "i64.sub" + OpcodeI64MulName = "i64.mul" + OpcodeI64DivSName = "i64.div_s" + OpcodeI64DivUName = "i64.div_u" + OpcodeI64RemSName = "i64.rem_s" + OpcodeI64RemUName = "i64.rem_u" + OpcodeI64AndName = "i64.and" + OpcodeI64OrName = "i64.or" + OpcodeI64XorName = "i64.xor" + OpcodeI64ShlName = "i64.shl" + OpcodeI64ShrSName = "i64.shr_s" + OpcodeI64ShrUName = "i64.shr_u" + OpcodeI64RotlName = "i64.rotl" + OpcodeI64RotrName = "i64.rotr" + OpcodeF32AbsName = "f32.abs" + OpcodeF32NegName = "f32.neg" + OpcodeF32CeilName = "f32.ceil" + OpcodeF32FloorName = "f32.floor" + OpcodeF32TruncName = "f32.trunc" + OpcodeF32NearestName = "f32.nearest" + OpcodeF32SqrtName = "f32.sqrt" + OpcodeF32AddName = "f32.add" + OpcodeF32SubName = "f32.sub" + OpcodeF32MulName = "f32.mul" + OpcodeF32DivName = "f32.div" + OpcodeF32MinName = "f32.min" + OpcodeF32MaxName = "f32.max" + OpcodeF32CopysignName = "f32.copysign" + OpcodeF64AbsName = "f64.abs" + OpcodeF64NegName = "f64.neg" + OpcodeF64CeilName = "f64.ceil" + OpcodeF64FloorName = "f64.floor" + OpcodeF64TruncName = "f64.trunc" + OpcodeF64NearestName = "f64.nearest" + OpcodeF64SqrtName = "f64.sqrt" + OpcodeF64AddName = "f64.add" + OpcodeF64SubName = "f64.sub" + OpcodeF64MulName = "f64.mul" + OpcodeF64DivName = "f64.div" + OpcodeF64MinName = "f64.min" + OpcodeF64MaxName = "f64.max" + OpcodeF64CopysignName = "f64.copysign" + OpcodeI32WrapI64Name = "i32.wrap_i64" + OpcodeI32TruncF32SName = "i32.trunc_f32_s" + OpcodeI32TruncF32UName = "i32.trunc_f32_u" + OpcodeI32TruncF64SName = "i32.trunc_f64_s" + OpcodeI32TruncF64UName = "i32.trunc_f64_u" + OpcodeI64ExtendI32SName = "i64.extend_i32_s" + OpcodeI64ExtendI32UName = "i64.extend_i32_u" + OpcodeI64TruncF32SName = "i64.trunc_f32_s" + OpcodeI64TruncF32UName = "i64.trunc_f32_u" + OpcodeI64TruncF64SName = "i64.trunc_f64_s" + OpcodeI64TruncF64UName = "i64.trunc_f64_u" + OpcodeF32ConvertI32SName = "f32.convert_i32_s" + OpcodeF32ConvertI32UName = "f32.convert_i32_u" + OpcodeF32ConvertI64SName = "f32.convert_i64_s" + OpcodeF32ConvertI64UName = "f32.convert_i64u" + OpcodeF32DemoteF64Name = "f32.demote_f64" + OpcodeF64ConvertI32SName = "f64.convert_i32_s" + OpcodeF64ConvertI32UName = "f64.convert_i32_u" + OpcodeF64ConvertI64SName = "f64.convert_i64_s" + OpcodeF64ConvertI64UName = "f64.convert_i64_u" + OpcodeF64PromoteF32Name = "f64.promote_f32" + OpcodeI32ReinterpretF32Name = "i32.reinterpret_f32" + OpcodeI64ReinterpretF64Name = "i64.reinterpret_f64" + OpcodeF32ReinterpretI32Name = "f32.reinterpret_i32" + OpcodeF64ReinterpretI64Name = "f64.reinterpret_i64" + + OpcodeRefNullName = "ref.null" + OpcodeRefIsNullName = "ref.is_null" + OpcodeRefFuncName = "ref.func" + + OpcodeTableGetName = "table.get" + OpcodeTableSetName = "table.set" + + // Below are toggled with CoreFeatureSignExtensionOps + + OpcodeI32Extend8SName = "i32.extend8_s" + OpcodeI32Extend16SName = "i32.extend16_s" + OpcodeI64Extend8SName = "i64.extend8_s" + OpcodeI64Extend16SName = "i64.extend16_s" + OpcodeI64Extend32SName = "i64.extend32_s" + + OpcodeMiscPrefixName = "misc_prefix" + OpcodeVecPrefixName = "vector_prefix" + OpcodeAtomicPrefixName = "atomic_prefix" +) + +var instructionNames = [256]string{ + OpcodeUnreachable: OpcodeUnreachableName, + OpcodeNop: OpcodeNopName, + OpcodeBlock: OpcodeBlockName, + OpcodeLoop: OpcodeLoopName, + OpcodeIf: OpcodeIfName, + OpcodeElse: OpcodeElseName, + OpcodeEnd: OpcodeEndName, + OpcodeBr: OpcodeBrName, + OpcodeBrIf: OpcodeBrIfName, + OpcodeBrTable: OpcodeBrTableName, + OpcodeReturn: OpcodeReturnName, + OpcodeCall: OpcodeCallName, + OpcodeCallIndirect: OpcodeCallIndirectName, + OpcodeDrop: OpcodeDropName, + OpcodeSelect: OpcodeSelectName, + OpcodeTypedSelect: OpcodeTypedSelectName, + OpcodeLocalGet: OpcodeLocalGetName, + OpcodeLocalSet: OpcodeLocalSetName, + OpcodeLocalTee: OpcodeLocalTeeName, + OpcodeGlobalGet: OpcodeGlobalGetName, + OpcodeGlobalSet: OpcodeGlobalSetName, + OpcodeI32Load: OpcodeI32LoadName, + OpcodeI64Load: OpcodeI64LoadName, + OpcodeF32Load: OpcodeF32LoadName, + OpcodeF64Load: OpcodeF64LoadName, + OpcodeI32Load8S: OpcodeI32Load8SName, + OpcodeI32Load8U: OpcodeI32Load8UName, + OpcodeI32Load16S: OpcodeI32Load16SName, + OpcodeI32Load16U: OpcodeI32Load16UName, + OpcodeI64Load8S: OpcodeI64Load8SName, + OpcodeI64Load8U: OpcodeI64Load8UName, + OpcodeI64Load16S: OpcodeI64Load16SName, + OpcodeI64Load16U: OpcodeI64Load16UName, + OpcodeI64Load32S: OpcodeI64Load32SName, + OpcodeI64Load32U: OpcodeI64Load32UName, + OpcodeI32Store: OpcodeI32StoreName, + OpcodeI64Store: OpcodeI64StoreName, + OpcodeF32Store: OpcodeF32StoreName, + OpcodeF64Store: OpcodeF64StoreName, + OpcodeI32Store8: OpcodeI32Store8Name, + OpcodeI32Store16: OpcodeI32Store16Name, + OpcodeI64Store8: OpcodeI64Store8Name, + OpcodeI64Store16: OpcodeI64Store16Name, + OpcodeI64Store32: OpcodeI64Store32Name, + OpcodeMemorySize: OpcodeMemorySizeName, + OpcodeMemoryGrow: OpcodeMemoryGrowName, + OpcodeI32Const: OpcodeI32ConstName, + OpcodeI64Const: OpcodeI64ConstName, + OpcodeF32Const: OpcodeF32ConstName, + OpcodeF64Const: OpcodeF64ConstName, + OpcodeI32Eqz: OpcodeI32EqzName, + OpcodeI32Eq: OpcodeI32EqName, + OpcodeI32Ne: OpcodeI32NeName, + OpcodeI32LtS: OpcodeI32LtSName, + OpcodeI32LtU: OpcodeI32LtUName, + OpcodeI32GtS: OpcodeI32GtSName, + OpcodeI32GtU: OpcodeI32GtUName, + OpcodeI32LeS: OpcodeI32LeSName, + OpcodeI32LeU: OpcodeI32LeUName, + OpcodeI32GeS: OpcodeI32GeSName, + OpcodeI32GeU: OpcodeI32GeUName, + OpcodeI64Eqz: OpcodeI64EqzName, + OpcodeI64Eq: OpcodeI64EqName, + OpcodeI64Ne: OpcodeI64NeName, + OpcodeI64LtS: OpcodeI64LtSName, + OpcodeI64LtU: OpcodeI64LtUName, + OpcodeI64GtS: OpcodeI64GtSName, + OpcodeI64GtU: OpcodeI64GtUName, + OpcodeI64LeS: OpcodeI64LeSName, + OpcodeI64LeU: OpcodeI64LeUName, + OpcodeI64GeS: OpcodeI64GeSName, + OpcodeI64GeU: OpcodeI64GeUName, + OpcodeF32Eq: OpcodeF32EqName, + OpcodeF32Ne: OpcodeF32NeName, + OpcodeF32Lt: OpcodeF32LtName, + OpcodeF32Gt: OpcodeF32GtName, + OpcodeF32Le: OpcodeF32LeName, + OpcodeF32Ge: OpcodeF32GeName, + OpcodeF64Eq: OpcodeF64EqName, + OpcodeF64Ne: OpcodeF64NeName, + OpcodeF64Lt: OpcodeF64LtName, + OpcodeF64Gt: OpcodeF64GtName, + OpcodeF64Le: OpcodeF64LeName, + OpcodeF64Ge: OpcodeF64GeName, + OpcodeI32Clz: OpcodeI32ClzName, + OpcodeI32Ctz: OpcodeI32CtzName, + OpcodeI32Popcnt: OpcodeI32PopcntName, + OpcodeI32Add: OpcodeI32AddName, + OpcodeI32Sub: OpcodeI32SubName, + OpcodeI32Mul: OpcodeI32MulName, + OpcodeI32DivS: OpcodeI32DivSName, + OpcodeI32DivU: OpcodeI32DivUName, + OpcodeI32RemS: OpcodeI32RemSName, + OpcodeI32RemU: OpcodeI32RemUName, + OpcodeI32And: OpcodeI32AndName, + OpcodeI32Or: OpcodeI32OrName, + OpcodeI32Xor: OpcodeI32XorName, + OpcodeI32Shl: OpcodeI32ShlName, + OpcodeI32ShrS: OpcodeI32ShrSName, + OpcodeI32ShrU: OpcodeI32ShrUName, + OpcodeI32Rotl: OpcodeI32RotlName, + OpcodeI32Rotr: OpcodeI32RotrName, + OpcodeI64Clz: OpcodeI64ClzName, + OpcodeI64Ctz: OpcodeI64CtzName, + OpcodeI64Popcnt: OpcodeI64PopcntName, + OpcodeI64Add: OpcodeI64AddName, + OpcodeI64Sub: OpcodeI64SubName, + OpcodeI64Mul: OpcodeI64MulName, + OpcodeI64DivS: OpcodeI64DivSName, + OpcodeI64DivU: OpcodeI64DivUName, + OpcodeI64RemS: OpcodeI64RemSName, + OpcodeI64RemU: OpcodeI64RemUName, + OpcodeI64And: OpcodeI64AndName, + OpcodeI64Or: OpcodeI64OrName, + OpcodeI64Xor: OpcodeI64XorName, + OpcodeI64Shl: OpcodeI64ShlName, + OpcodeI64ShrS: OpcodeI64ShrSName, + OpcodeI64ShrU: OpcodeI64ShrUName, + OpcodeI64Rotl: OpcodeI64RotlName, + OpcodeI64Rotr: OpcodeI64RotrName, + OpcodeF32Abs: OpcodeF32AbsName, + OpcodeF32Neg: OpcodeF32NegName, + OpcodeF32Ceil: OpcodeF32CeilName, + OpcodeF32Floor: OpcodeF32FloorName, + OpcodeF32Trunc: OpcodeF32TruncName, + OpcodeF32Nearest: OpcodeF32NearestName, + OpcodeF32Sqrt: OpcodeF32SqrtName, + OpcodeF32Add: OpcodeF32AddName, + OpcodeF32Sub: OpcodeF32SubName, + OpcodeF32Mul: OpcodeF32MulName, + OpcodeF32Div: OpcodeF32DivName, + OpcodeF32Min: OpcodeF32MinName, + OpcodeF32Max: OpcodeF32MaxName, + OpcodeF32Copysign: OpcodeF32CopysignName, + OpcodeF64Abs: OpcodeF64AbsName, + OpcodeF64Neg: OpcodeF64NegName, + OpcodeF64Ceil: OpcodeF64CeilName, + OpcodeF64Floor: OpcodeF64FloorName, + OpcodeF64Trunc: OpcodeF64TruncName, + OpcodeF64Nearest: OpcodeF64NearestName, + OpcodeF64Sqrt: OpcodeF64SqrtName, + OpcodeF64Add: OpcodeF64AddName, + OpcodeF64Sub: OpcodeF64SubName, + OpcodeF64Mul: OpcodeF64MulName, + OpcodeF64Div: OpcodeF64DivName, + OpcodeF64Min: OpcodeF64MinName, + OpcodeF64Max: OpcodeF64MaxName, + OpcodeF64Copysign: OpcodeF64CopysignName, + OpcodeI32WrapI64: OpcodeI32WrapI64Name, + OpcodeI32TruncF32S: OpcodeI32TruncF32SName, + OpcodeI32TruncF32U: OpcodeI32TruncF32UName, + OpcodeI32TruncF64S: OpcodeI32TruncF64SName, + OpcodeI32TruncF64U: OpcodeI32TruncF64UName, + OpcodeI64ExtendI32S: OpcodeI64ExtendI32SName, + OpcodeI64ExtendI32U: OpcodeI64ExtendI32UName, + OpcodeI64TruncF32S: OpcodeI64TruncF32SName, + OpcodeI64TruncF32U: OpcodeI64TruncF32UName, + OpcodeI64TruncF64S: OpcodeI64TruncF64SName, + OpcodeI64TruncF64U: OpcodeI64TruncF64UName, + OpcodeF32ConvertI32S: OpcodeF32ConvertI32SName, + OpcodeF32ConvertI32U: OpcodeF32ConvertI32UName, + OpcodeF32ConvertI64S: OpcodeF32ConvertI64SName, + OpcodeF32ConvertI64U: OpcodeF32ConvertI64UName, + OpcodeF32DemoteF64: OpcodeF32DemoteF64Name, + OpcodeF64ConvertI32S: OpcodeF64ConvertI32SName, + OpcodeF64ConvertI32U: OpcodeF64ConvertI32UName, + OpcodeF64ConvertI64S: OpcodeF64ConvertI64SName, + OpcodeF64ConvertI64U: OpcodeF64ConvertI64UName, + OpcodeF64PromoteF32: OpcodeF64PromoteF32Name, + OpcodeI32ReinterpretF32: OpcodeI32ReinterpretF32Name, + OpcodeI64ReinterpretF64: OpcodeI64ReinterpretF64Name, + OpcodeF32ReinterpretI32: OpcodeF32ReinterpretI32Name, + OpcodeF64ReinterpretI64: OpcodeF64ReinterpretI64Name, + + OpcodeRefNull: OpcodeRefNullName, + OpcodeRefIsNull: OpcodeRefIsNullName, + OpcodeRefFunc: OpcodeRefFuncName, + + OpcodeTableGet: OpcodeTableGetName, + OpcodeTableSet: OpcodeTableSetName, + + // Below are toggled with CoreFeatureSignExtensionOps + + OpcodeI32Extend8S: OpcodeI32Extend8SName, + OpcodeI32Extend16S: OpcodeI32Extend16SName, + OpcodeI64Extend8S: OpcodeI64Extend8SName, + OpcodeI64Extend16S: OpcodeI64Extend16SName, + OpcodeI64Extend32S: OpcodeI64Extend32SName, + + OpcodeMiscPrefix: OpcodeMiscPrefixName, + OpcodeVecPrefix: OpcodeVecPrefixName, +} + +// InstructionName returns the instruction corresponding to this binary Opcode. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#a7-index-of-instructions +func InstructionName(oc Opcode) string { + return instructionNames[oc] +} + +const ( + OpcodeI32TruncSatF32SName = "i32.trunc_sat_f32_s" + OpcodeI32TruncSatF32UName = "i32.trunc_sat_f32_u" + OpcodeI32TruncSatF64SName = "i32.trunc_sat_f64_s" + OpcodeI32TruncSatF64UName = "i32.trunc_sat_f64_u" + OpcodeI64TruncSatF32SName = "i64.trunc_sat_f32_s" + OpcodeI64TruncSatF32UName = "i64.trunc_sat_f32_u" + OpcodeI64TruncSatF64SName = "i64.trunc_sat_f64_s" + OpcodeI64TruncSatF64UName = "i64.trunc_sat_f64_u" + + OpcodeMemoryInitName = "memory.init" + OpcodeDataDropName = "data.drop" + OpcodeMemoryCopyName = "memory.copy" + OpcodeMemoryFillName = "memory.fill" + OpcodeTableInitName = "table.init" + OpcodeElemDropName = "elem.drop" + OpcodeTableCopyName = "table.copy" + OpcodeTableGrowName = "table.grow" + OpcodeTableSizeName = "table.size" + OpcodeTableFillName = "table.fill" +) + +var miscInstructionNames = [256]string{ + OpcodeMiscI32TruncSatF32S: OpcodeI32TruncSatF32SName, + OpcodeMiscI32TruncSatF32U: OpcodeI32TruncSatF32UName, + OpcodeMiscI32TruncSatF64S: OpcodeI32TruncSatF64SName, + OpcodeMiscI32TruncSatF64U: OpcodeI32TruncSatF64UName, + OpcodeMiscI64TruncSatF32S: OpcodeI64TruncSatF32SName, + OpcodeMiscI64TruncSatF32U: OpcodeI64TruncSatF32UName, + OpcodeMiscI64TruncSatF64S: OpcodeI64TruncSatF64SName, + OpcodeMiscI64TruncSatF64U: OpcodeI64TruncSatF64UName, + + OpcodeMiscMemoryInit: OpcodeMemoryInitName, + OpcodeMiscDataDrop: OpcodeDataDropName, + OpcodeMiscMemoryCopy: OpcodeMemoryCopyName, + OpcodeMiscMemoryFill: OpcodeMemoryFillName, + OpcodeMiscTableInit: OpcodeTableInitName, + OpcodeMiscElemDrop: OpcodeElemDropName, + OpcodeMiscTableCopy: OpcodeTableCopyName, + OpcodeMiscTableGrow: OpcodeTableGrowName, + OpcodeMiscTableSize: OpcodeTableSizeName, + OpcodeMiscTableFill: OpcodeTableFillName, +} + +// MiscInstructionName returns the instruction corresponding to this miscellaneous Opcode. +func MiscInstructionName(oc OpcodeMisc) string { + return miscInstructionNames[oc] +} + +const ( + OpcodeVecV128LoadName = "v128.load" + OpcodeVecV128Load8x8SName = "v128.load8x8_s" + OpcodeVecV128Load8x8UName = "v128.load8x8_u" + OpcodeVecV128Load16x4SName = "v128.load16x4_s" + OpcodeVecV128Load16x4UName = "v128.load16x4_u" + OpcodeVecV128Load32x2SName = "v128.load32x2_s" + OpcodeVecV128Load32x2UName = "v128.load32x2_u" + OpcodeVecV128Load8SplatName = "v128.load8_splat" + OpcodeVecV128Load16SplatName = "v128.load16_splat" + OpcodeVecV128Load32SplatName = "v128.load32_splat" + OpcodeVecV128Load64SplatName = "v128.load64_splat" + OpcodeVecV128Load32zeroName = "v128.load32_zero" + OpcodeVecV128Load64zeroName = "v128.load64_zero" + OpcodeVecV128StoreName = "v128.store" + OpcodeVecV128Load8LaneName = "v128.load8_lane" + OpcodeVecV128Load16LaneName = "v128.load16_lane" + OpcodeVecV128Load32LaneName = "v128.load32_lane" + OpcodeVecV128Load64LaneName = "v128.load64_lane" + OpcodeVecV128Store8LaneName = "v128.store8_lane" + OpcodeVecV128Store16LaneName = "v128.store16_lane" + OpcodeVecV128Store32LaneName = "v128.store32_lane" + OpcodeVecV128Store64LaneName = "v128.store64_lane" + OpcodeVecV128ConstName = "v128.const" + OpcodeVecV128i8x16ShuffleName = "v128.shuffle" + OpcodeVecI8x16ExtractLaneSName = "i8x16.extract_lane_s" + OpcodeVecI8x16ExtractLaneUName = "i8x16.extract_lane_u" + OpcodeVecI8x16ReplaceLaneName = "i8x16.replace_lane" + OpcodeVecI16x8ExtractLaneSName = "i16x8.extract_lane_s" + OpcodeVecI16x8ExtractLaneUName = "i16x8.extract_lane_u" + OpcodeVecI16x8ReplaceLaneName = "i16x8.replace_lane" + OpcodeVecI32x4ExtractLaneName = "i32x4.extract_lane" + OpcodeVecI32x4ReplaceLaneName = "i32x4.replace_lane" + OpcodeVecI64x2ExtractLaneName = "i64x2.extract_lane" + OpcodeVecI64x2ReplaceLaneName = "i64x2.replace_lane" + OpcodeVecF32x4ExtractLaneName = "f32x4.extract_lane" + OpcodeVecF32x4ReplaceLaneName = "f32x4.replace_lane" + OpcodeVecF64x2ExtractLaneName = "f64x2.extract_lane" + OpcodeVecF64x2ReplaceLaneName = "f64x2.replace_lane" + OpcodeVecI8x16SwizzleName = "i8x16.swizzle" + OpcodeVecI8x16SplatName = "i8x16.splat" + OpcodeVecI16x8SplatName = "i16x8.splat" + OpcodeVecI32x4SplatName = "i32x4.splat" + OpcodeVecI64x2SplatName = "i64x2.splat" + OpcodeVecF32x4SplatName = "f32x4.splat" + OpcodeVecF64x2SplatName = "f64x2.splat" + OpcodeVecI8x16EqName = "i8x16.eq" + OpcodeVecI8x16NeName = "i8x16.ne" + OpcodeVecI8x16LtSName = "i8x16.lt_s" + OpcodeVecI8x16LtUName = "i8x16.lt_u" + OpcodeVecI8x16GtSName = "i8x16.gt_s" + OpcodeVecI8x16GtUName = "i8x16.gt_u" + OpcodeVecI8x16LeSName = "i8x16.le_s" + OpcodeVecI8x16LeUName = "i8x16.le_u" + OpcodeVecI8x16GeSName = "i8x16.ge_s" + OpcodeVecI8x16GeUName = "i8x16.ge_u" + OpcodeVecI16x8EqName = "i16x8.eq" + OpcodeVecI16x8NeName = "i16x8.ne" + OpcodeVecI16x8LtSName = "i16x8.lt_s" + OpcodeVecI16x8LtUName = "i16x8.lt_u" + OpcodeVecI16x8GtSName = "i16x8.gt_s" + OpcodeVecI16x8GtUName = "i16x8.gt_u" + OpcodeVecI16x8LeSName = "i16x8.le_s" + OpcodeVecI16x8LeUName = "i16x8.le_u" + OpcodeVecI16x8GeSName = "i16x8.ge_s" + OpcodeVecI16x8GeUName = "i16x8.ge_u" + OpcodeVecI32x4EqName = "i32x4.eq" + OpcodeVecI32x4NeName = "i32x4.ne" + OpcodeVecI32x4LtSName = "i32x4.lt_s" + OpcodeVecI32x4LtUName = "i32x4.lt_u" + OpcodeVecI32x4GtSName = "i32x4.gt_s" + OpcodeVecI32x4GtUName = "i32x4.gt_u" + OpcodeVecI32x4LeSName = "i32x4.le_s" + OpcodeVecI32x4LeUName = "i32x4.le_u" + OpcodeVecI32x4GeSName = "i32x4.ge_s" + OpcodeVecI32x4GeUName = "i32x4.ge_u" + OpcodeVecI64x2EqName = "i64x2.eq" + OpcodeVecI64x2NeName = "i64x2.ne" + OpcodeVecI64x2LtSName = "i64x2.lt" + OpcodeVecI64x2GtSName = "i64x2.gt" + OpcodeVecI64x2LeSName = "i64x2.le" + OpcodeVecI64x2GeSName = "i64x2.ge" + OpcodeVecF32x4EqName = "f32x4.eq" + OpcodeVecF32x4NeName = "f32x4.ne" + OpcodeVecF32x4LtName = "f32x4.lt" + OpcodeVecF32x4GtName = "f32x4.gt" + OpcodeVecF32x4LeName = "f32x4.le" + OpcodeVecF32x4GeName = "f32x4.ge" + OpcodeVecF64x2EqName = "f64x2.eq" + OpcodeVecF64x2NeName = "f64x2.ne" + OpcodeVecF64x2LtName = "f64x2.lt" + OpcodeVecF64x2GtName = "f64x2.gt" + OpcodeVecF64x2LeName = "f64x2.le" + OpcodeVecF64x2GeName = "f64x2.ge" + OpcodeVecV128NotName = "v128.not" + OpcodeVecV128AndName = "v128.and" + OpcodeVecV128AndNotName = "v128.andnot" + OpcodeVecV128OrName = "v128.or" + OpcodeVecV128XorName = "v128.xor" + OpcodeVecV128BitselectName = "v128.bitselect" + OpcodeVecV128AnyTrueName = "v128.any_true" + OpcodeVecI8x16AbsName = "i8x16.abs" + OpcodeVecI8x16NegName = "i8x16.neg" + OpcodeVecI8x16PopcntName = "i8x16.popcnt" + OpcodeVecI8x16AllTrueName = "i8x16.all_true" + OpcodeVecI8x16BitMaskName = "i8x16.bitmask" + OpcodeVecI8x16NarrowI16x8SName = "i8x16.narrow_i16x8_s" + OpcodeVecI8x16NarrowI16x8UName = "i8x16.narrow_i16x8_u" + OpcodeVecI8x16ShlName = "i8x16.shl" + OpcodeVecI8x16ShrSName = "i8x16.shr_s" + OpcodeVecI8x16ShrUName = "i8x16.shr_u" + OpcodeVecI8x16AddName = "i8x16.add" + OpcodeVecI8x16AddSatSName = "i8x16.add_sat_s" + OpcodeVecI8x16AddSatUName = "i8x16.add_sat_u" + OpcodeVecI8x16SubName = "i8x16.sub" + OpcodeVecI8x16SubSatSName = "i8x16.sub_s" + OpcodeVecI8x16SubSatUName = "i8x16.sub_u" + OpcodeVecI8x16MinSName = "i8x16.min_s" + OpcodeVecI8x16MinUName = "i8x16.min_u" + OpcodeVecI8x16MaxSName = "i8x16.max_s" + OpcodeVecI8x16MaxUName = "i8x16.max_u" + OpcodeVecI8x16AvgrUName = "i8x16.avgr_u" + OpcodeVecI16x8ExtaddPairwiseI8x16SName = "i16x8.extadd_pairwise_i8x16_s" + OpcodeVecI16x8ExtaddPairwiseI8x16UName = "i16x8.extadd_pairwise_i8x16_u" + OpcodeVecI16x8AbsName = "i16x8.abs" + OpcodeVecI16x8NegName = "i16x8.neg" + OpcodeVecI16x8Q15mulrSatSName = "i16x8.q15mulr_sat_s" + OpcodeVecI16x8AllTrueName = "i16x8.all_true" + OpcodeVecI16x8BitMaskName = "i16x8.bitmask" + OpcodeVecI16x8NarrowI32x4SName = "i16x8.narrow_i32x4_s" + OpcodeVecI16x8NarrowI32x4UName = "i16x8.narrow_i32x4_u" + OpcodeVecI16x8ExtendLowI8x16SName = "i16x8.extend_low_i8x16_s" + OpcodeVecI16x8ExtendHighI8x16SName = "i16x8.extend_high_i8x16_s" + OpcodeVecI16x8ExtendLowI8x16UName = "i16x8.extend_low_i8x16_u" + OpcodeVecI16x8ExtendHighI8x16UName = "i16x8.extend_high_i8x16_u" + OpcodeVecI16x8ShlName = "i16x8.shl" + OpcodeVecI16x8ShrSName = "i16x8.shr_s" + OpcodeVecI16x8ShrUName = "i16x8.shr_u" + OpcodeVecI16x8AddName = "i16x8.add" + OpcodeVecI16x8AddSatSName = "i16x8.add_sat_s" + OpcodeVecI16x8AddSatUName = "i16x8.add_sat_u" + OpcodeVecI16x8SubName = "i16x8.sub" + OpcodeVecI16x8SubSatSName = "i16x8.sub_sat_s" + OpcodeVecI16x8SubSatUName = "i16x8.sub_sat_u" + OpcodeVecI16x8MulName = "i16x8.mul" + OpcodeVecI16x8MinSName = "i16x8.min_s" + OpcodeVecI16x8MinUName = "i16x8.min_u" + OpcodeVecI16x8MaxSName = "i16x8.max_s" + OpcodeVecI16x8MaxUName = "i16x8.max_u" + OpcodeVecI16x8AvgrUName = "i16x8.avgr_u" + OpcodeVecI16x8ExtMulLowI8x16SName = "i16x8.extmul_low_i8x16_s" + OpcodeVecI16x8ExtMulHighI8x16SName = "i16x8.extmul_high_i8x16_s" + OpcodeVecI16x8ExtMulLowI8x16UName = "i16x8.extmul_low_i8x16_u" + OpcodeVecI16x8ExtMulHighI8x16UName = "i16x8.extmul_high_i8x16_u" + OpcodeVecI32x4ExtaddPairwiseI16x8SName = "i32x4.extadd_pairwise_i16x8_s" + OpcodeVecI32x4ExtaddPairwiseI16x8UName = "i32x4.extadd_pairwise_i16x8_u" + OpcodeVecI32x4AbsName = "i32x4.abs" + OpcodeVecI32x4NegName = "i32x4.neg" + OpcodeVecI32x4AllTrueName = "i32x4.all_true" + OpcodeVecI32x4BitMaskName = "i32x4.bitmask" + OpcodeVecI32x4ExtendLowI16x8SName = "i32x4.extend_low_i16x8_s" + OpcodeVecI32x4ExtendHighI16x8SName = "i32x4.extend_high_i16x8_s" + OpcodeVecI32x4ExtendLowI16x8UName = "i32x4.extend_low_i16x8_u" + OpcodeVecI32x4ExtendHighI16x8UName = "i32x4.extend_high_i16x8_u" + OpcodeVecI32x4ShlName = "i32x4.shl" + OpcodeVecI32x4ShrSName = "i32x4.shr_s" + OpcodeVecI32x4ShrUName = "i32x4.shr_u" + OpcodeVecI32x4AddName = "i32x4.add" + OpcodeVecI32x4SubName = "i32x4.sub" + OpcodeVecI32x4MulName = "i32x4.mul" + OpcodeVecI32x4MinSName = "i32x4.min_s" + OpcodeVecI32x4MinUName = "i32x4.min_u" + OpcodeVecI32x4MaxSName = "i32x4.max_s" + OpcodeVecI32x4MaxUName = "i32x4.max_u" + OpcodeVecI32x4DotI16x8SName = "i32x4.dot_i16x8_s" + OpcodeVecI32x4ExtMulLowI16x8SName = "i32x4.extmul_low_i16x8_s" + OpcodeVecI32x4ExtMulHighI16x8SName = "i32x4.extmul_high_i16x8_s" + OpcodeVecI32x4ExtMulLowI16x8UName = "i32x4.extmul_low_i16x8_u" + OpcodeVecI32x4ExtMulHighI16x8UName = "i32x4.extmul_high_i16x8_u" + OpcodeVecI64x2AbsName = "i64x2.abs" + OpcodeVecI64x2NegName = "i64x2.neg" + OpcodeVecI64x2AllTrueName = "i64x2.all_true" + OpcodeVecI64x2BitMaskName = "i64x2.bitmask" + OpcodeVecI64x2ExtendLowI32x4SName = "i64x2.extend_low_i32x4_s" + OpcodeVecI64x2ExtendHighI32x4SName = "i64x2.extend_high_i32x4_s" + OpcodeVecI64x2ExtendLowI32x4UName = "i64x2.extend_low_i32x4_u" + OpcodeVecI64x2ExtendHighI32x4UName = "i64x2.extend_high_i32x4_u" + OpcodeVecI64x2ShlName = "i64x2.shl" + OpcodeVecI64x2ShrSName = "i64x2.shr_s" + OpcodeVecI64x2ShrUName = "i64x2.shr_u" + OpcodeVecI64x2AddName = "i64x2.add" + OpcodeVecI64x2SubName = "i64x2.sub" + OpcodeVecI64x2MulName = "i64x2.mul" + OpcodeVecI64x2ExtMulLowI32x4SName = "i64x2.extmul_low_i32x4_s" + OpcodeVecI64x2ExtMulHighI32x4SName = "i64x2.extmul_high_i32x4_s" + OpcodeVecI64x2ExtMulLowI32x4UName = "i64x2.extmul_low_i32x4_u" + OpcodeVecI64x2ExtMulHighI32x4UName = "i64x2.extmul_high_i32x4_u" + OpcodeVecF32x4CeilName = "f32x4.ceil" + OpcodeVecF32x4FloorName = "f32x4.floor" + OpcodeVecF32x4TruncName = "f32x4.trunc" + OpcodeVecF32x4NearestName = "f32x4.nearest" + OpcodeVecF32x4AbsName = "f32x4.abs" + OpcodeVecF32x4NegName = "f32x4.neg" + OpcodeVecF32x4SqrtName = "f32x4.sqrt" + OpcodeVecF32x4AddName = "f32x4.add" + OpcodeVecF32x4SubName = "f32x4.sub" + OpcodeVecF32x4MulName = "f32x4.mul" + OpcodeVecF32x4DivName = "f32x4.div" + OpcodeVecF32x4MinName = "f32x4.min" + OpcodeVecF32x4MaxName = "f32x4.max" + OpcodeVecF32x4PminName = "f32x4.pmin" + OpcodeVecF32x4PmaxName = "f32x4.pmax" + OpcodeVecF64x2CeilName = "f64x2.ceil" + OpcodeVecF64x2FloorName = "f64x2.floor" + OpcodeVecF64x2TruncName = "f64x2.trunc" + OpcodeVecF64x2NearestName = "f64x2.nearest" + OpcodeVecF64x2AbsName = "f64x2.abs" + OpcodeVecF64x2NegName = "f64x2.neg" + OpcodeVecF64x2SqrtName = "f64x2.sqrt" + OpcodeVecF64x2AddName = "f64x2.add" + OpcodeVecF64x2SubName = "f64x2.sub" + OpcodeVecF64x2MulName = "f64x2.mul" + OpcodeVecF64x2DivName = "f64x2.div" + OpcodeVecF64x2MinName = "f64x2.min" + OpcodeVecF64x2MaxName = "f64x2.max" + OpcodeVecF64x2PminName = "f64x2.pmin" + OpcodeVecF64x2PmaxName = "f64x2.pmax" + OpcodeVecI32x4TruncSatF32x4SName = "i32x4.trunc_sat_f32x4_s" + OpcodeVecI32x4TruncSatF32x4UName = "i32x4.trunc_sat_f32x4_u" + OpcodeVecF32x4ConvertI32x4SName = "f32x4.convert_i32x4_s" + OpcodeVecF32x4ConvertI32x4UName = "f32x4.convert_i32x4_u" + OpcodeVecI32x4TruncSatF64x2SZeroName = "i32x4.trunc_sat_f64x2_s_zero" + OpcodeVecI32x4TruncSatF64x2UZeroName = "i32x4.trunc_sat_f64x2_u_zero" + OpcodeVecF64x2ConvertLowI32x4SName = "f64x2.convert_low_i32x4_s" + OpcodeVecF64x2ConvertLowI32x4UName = "f64x2.convert_low_i32x4_u" + OpcodeVecF32x4DemoteF64x2ZeroName = "f32x4.demote_f64x2_zero" + OpcodeVecF64x2PromoteLowF32x4ZeroName = "f64x2.promote_low_f32x4" +) + +var vectorInstructionName = map[OpcodeVec]string{ + OpcodeVecV128Load: OpcodeVecV128LoadName, + OpcodeVecV128Load8x8s: OpcodeVecV128Load8x8SName, + OpcodeVecV128Load8x8u: OpcodeVecV128Load8x8UName, + OpcodeVecV128Load16x4s: OpcodeVecV128Load16x4SName, + OpcodeVecV128Load16x4u: OpcodeVecV128Load16x4UName, + OpcodeVecV128Load32x2s: OpcodeVecV128Load32x2SName, + OpcodeVecV128Load32x2u: OpcodeVecV128Load32x2UName, + OpcodeVecV128Load8Splat: OpcodeVecV128Load8SplatName, + OpcodeVecV128Load16Splat: OpcodeVecV128Load16SplatName, + OpcodeVecV128Load32Splat: OpcodeVecV128Load32SplatName, + OpcodeVecV128Load64Splat: OpcodeVecV128Load64SplatName, + OpcodeVecV128Load32zero: OpcodeVecV128Load32zeroName, + OpcodeVecV128Load64zero: OpcodeVecV128Load64zeroName, + OpcodeVecV128Store: OpcodeVecV128StoreName, + OpcodeVecV128Load8Lane: OpcodeVecV128Load8LaneName, + OpcodeVecV128Load16Lane: OpcodeVecV128Load16LaneName, + OpcodeVecV128Load32Lane: OpcodeVecV128Load32LaneName, + OpcodeVecV128Load64Lane: OpcodeVecV128Load64LaneName, + OpcodeVecV128Store8Lane: OpcodeVecV128Store8LaneName, + OpcodeVecV128Store16Lane: OpcodeVecV128Store16LaneName, + OpcodeVecV128Store32Lane: OpcodeVecV128Store32LaneName, + OpcodeVecV128Store64Lane: OpcodeVecV128Store64LaneName, + OpcodeVecV128Const: OpcodeVecV128ConstName, + OpcodeVecV128i8x16Shuffle: OpcodeVecV128i8x16ShuffleName, + OpcodeVecI8x16ExtractLaneS: OpcodeVecI8x16ExtractLaneSName, + OpcodeVecI8x16ExtractLaneU: OpcodeVecI8x16ExtractLaneUName, + OpcodeVecI8x16ReplaceLane: OpcodeVecI8x16ReplaceLaneName, + OpcodeVecI16x8ExtractLaneS: OpcodeVecI16x8ExtractLaneSName, + OpcodeVecI16x8ExtractLaneU: OpcodeVecI16x8ExtractLaneUName, + OpcodeVecI16x8ReplaceLane: OpcodeVecI16x8ReplaceLaneName, + OpcodeVecI32x4ExtractLane: OpcodeVecI32x4ExtractLaneName, + OpcodeVecI32x4ReplaceLane: OpcodeVecI32x4ReplaceLaneName, + OpcodeVecI64x2ExtractLane: OpcodeVecI64x2ExtractLaneName, + OpcodeVecI64x2ReplaceLane: OpcodeVecI64x2ReplaceLaneName, + OpcodeVecF32x4ExtractLane: OpcodeVecF32x4ExtractLaneName, + OpcodeVecF32x4ReplaceLane: OpcodeVecF32x4ReplaceLaneName, + OpcodeVecF64x2ExtractLane: OpcodeVecF64x2ExtractLaneName, + OpcodeVecF64x2ReplaceLane: OpcodeVecF64x2ReplaceLaneName, + OpcodeVecI8x16Swizzle: OpcodeVecI8x16SwizzleName, + OpcodeVecI8x16Splat: OpcodeVecI8x16SplatName, + OpcodeVecI16x8Splat: OpcodeVecI16x8SplatName, + OpcodeVecI32x4Splat: OpcodeVecI32x4SplatName, + OpcodeVecI64x2Splat: OpcodeVecI64x2SplatName, + OpcodeVecF32x4Splat: OpcodeVecF32x4SplatName, + OpcodeVecF64x2Splat: OpcodeVecF64x2SplatName, + OpcodeVecI8x16Eq: OpcodeVecI8x16EqName, + OpcodeVecI8x16Ne: OpcodeVecI8x16NeName, + OpcodeVecI8x16LtS: OpcodeVecI8x16LtSName, + OpcodeVecI8x16LtU: OpcodeVecI8x16LtUName, + OpcodeVecI8x16GtS: OpcodeVecI8x16GtSName, + OpcodeVecI8x16GtU: OpcodeVecI8x16GtUName, + OpcodeVecI8x16LeS: OpcodeVecI8x16LeSName, + OpcodeVecI8x16LeU: OpcodeVecI8x16LeUName, + OpcodeVecI8x16GeS: OpcodeVecI8x16GeSName, + OpcodeVecI8x16GeU: OpcodeVecI8x16GeUName, + OpcodeVecI16x8Eq: OpcodeVecI16x8EqName, + OpcodeVecI16x8Ne: OpcodeVecI16x8NeName, + OpcodeVecI16x8LtS: OpcodeVecI16x8LtSName, + OpcodeVecI16x8LtU: OpcodeVecI16x8LtUName, + OpcodeVecI16x8GtS: OpcodeVecI16x8GtSName, + OpcodeVecI16x8GtU: OpcodeVecI16x8GtUName, + OpcodeVecI16x8LeS: OpcodeVecI16x8LeSName, + OpcodeVecI16x8LeU: OpcodeVecI16x8LeUName, + OpcodeVecI16x8GeS: OpcodeVecI16x8GeSName, + OpcodeVecI16x8GeU: OpcodeVecI16x8GeUName, + OpcodeVecI32x4Eq: OpcodeVecI32x4EqName, + OpcodeVecI32x4Ne: OpcodeVecI32x4NeName, + OpcodeVecI32x4LtS: OpcodeVecI32x4LtSName, + OpcodeVecI32x4LtU: OpcodeVecI32x4LtUName, + OpcodeVecI32x4GtS: OpcodeVecI32x4GtSName, + OpcodeVecI32x4GtU: OpcodeVecI32x4GtUName, + OpcodeVecI32x4LeS: OpcodeVecI32x4LeSName, + OpcodeVecI32x4LeU: OpcodeVecI32x4LeUName, + OpcodeVecI32x4GeS: OpcodeVecI32x4GeSName, + OpcodeVecI32x4GeU: OpcodeVecI32x4GeUName, + OpcodeVecI64x2Eq: OpcodeVecI64x2EqName, + OpcodeVecI64x2Ne: OpcodeVecI64x2NeName, + OpcodeVecI64x2LtS: OpcodeVecI64x2LtSName, + OpcodeVecI64x2GtS: OpcodeVecI64x2GtSName, + OpcodeVecI64x2LeS: OpcodeVecI64x2LeSName, + OpcodeVecI64x2GeS: OpcodeVecI64x2GeSName, + OpcodeVecF32x4Eq: OpcodeVecF32x4EqName, + OpcodeVecF32x4Ne: OpcodeVecF32x4NeName, + OpcodeVecF32x4Lt: OpcodeVecF32x4LtName, + OpcodeVecF32x4Gt: OpcodeVecF32x4GtName, + OpcodeVecF32x4Le: OpcodeVecF32x4LeName, + OpcodeVecF32x4Ge: OpcodeVecF32x4GeName, + OpcodeVecF64x2Eq: OpcodeVecF64x2EqName, + OpcodeVecF64x2Ne: OpcodeVecF64x2NeName, + OpcodeVecF64x2Lt: OpcodeVecF64x2LtName, + OpcodeVecF64x2Gt: OpcodeVecF64x2GtName, + OpcodeVecF64x2Le: OpcodeVecF64x2LeName, + OpcodeVecF64x2Ge: OpcodeVecF64x2GeName, + OpcodeVecV128Not: OpcodeVecV128NotName, + OpcodeVecV128And: OpcodeVecV128AndName, + OpcodeVecV128AndNot: OpcodeVecV128AndNotName, + OpcodeVecV128Or: OpcodeVecV128OrName, + OpcodeVecV128Xor: OpcodeVecV128XorName, + OpcodeVecV128Bitselect: OpcodeVecV128BitselectName, + OpcodeVecV128AnyTrue: OpcodeVecV128AnyTrueName, + OpcodeVecI8x16Abs: OpcodeVecI8x16AbsName, + OpcodeVecI8x16Neg: OpcodeVecI8x16NegName, + OpcodeVecI8x16Popcnt: OpcodeVecI8x16PopcntName, + OpcodeVecI8x16AllTrue: OpcodeVecI8x16AllTrueName, + OpcodeVecI8x16BitMask: OpcodeVecI8x16BitMaskName, + OpcodeVecI8x16NarrowI16x8S: OpcodeVecI8x16NarrowI16x8SName, + OpcodeVecI8x16NarrowI16x8U: OpcodeVecI8x16NarrowI16x8UName, + OpcodeVecI8x16Shl: OpcodeVecI8x16ShlName, + OpcodeVecI8x16ShrS: OpcodeVecI8x16ShrSName, + OpcodeVecI8x16ShrU: OpcodeVecI8x16ShrUName, + OpcodeVecI8x16Add: OpcodeVecI8x16AddName, + OpcodeVecI8x16AddSatS: OpcodeVecI8x16AddSatSName, + OpcodeVecI8x16AddSatU: OpcodeVecI8x16AddSatUName, + OpcodeVecI8x16Sub: OpcodeVecI8x16SubName, + OpcodeVecI8x16SubSatS: OpcodeVecI8x16SubSatSName, + OpcodeVecI8x16SubSatU: OpcodeVecI8x16SubSatUName, + OpcodeVecI8x16MinS: OpcodeVecI8x16MinSName, + OpcodeVecI8x16MinU: OpcodeVecI8x16MinUName, + OpcodeVecI8x16MaxS: OpcodeVecI8x16MaxSName, + OpcodeVecI8x16MaxU: OpcodeVecI8x16MaxUName, + OpcodeVecI8x16AvgrU: OpcodeVecI8x16AvgrUName, + OpcodeVecI16x8ExtaddPairwiseI8x16S: OpcodeVecI16x8ExtaddPairwiseI8x16SName, + OpcodeVecI16x8ExtaddPairwiseI8x16U: OpcodeVecI16x8ExtaddPairwiseI8x16UName, + OpcodeVecI16x8Abs: OpcodeVecI16x8AbsName, + OpcodeVecI16x8Neg: OpcodeVecI16x8NegName, + OpcodeVecI16x8Q15mulrSatS: OpcodeVecI16x8Q15mulrSatSName, + OpcodeVecI16x8AllTrue: OpcodeVecI16x8AllTrueName, + OpcodeVecI16x8BitMask: OpcodeVecI16x8BitMaskName, + OpcodeVecI16x8NarrowI32x4S: OpcodeVecI16x8NarrowI32x4SName, + OpcodeVecI16x8NarrowI32x4U: OpcodeVecI16x8NarrowI32x4UName, + OpcodeVecI16x8ExtendLowI8x16S: OpcodeVecI16x8ExtendLowI8x16SName, + OpcodeVecI16x8ExtendHighI8x16S: OpcodeVecI16x8ExtendHighI8x16SName, + OpcodeVecI16x8ExtendLowI8x16U: OpcodeVecI16x8ExtendLowI8x16UName, + OpcodeVecI16x8ExtendHighI8x16U: OpcodeVecI16x8ExtendHighI8x16UName, + OpcodeVecI16x8Shl: OpcodeVecI16x8ShlName, + OpcodeVecI16x8ShrS: OpcodeVecI16x8ShrSName, + OpcodeVecI16x8ShrU: OpcodeVecI16x8ShrUName, + OpcodeVecI16x8Add: OpcodeVecI16x8AddName, + OpcodeVecI16x8AddSatS: OpcodeVecI16x8AddSatSName, + OpcodeVecI16x8AddSatU: OpcodeVecI16x8AddSatUName, + OpcodeVecI16x8Sub: OpcodeVecI16x8SubName, + OpcodeVecI16x8SubSatS: OpcodeVecI16x8SubSatSName, + OpcodeVecI16x8SubSatU: OpcodeVecI16x8SubSatUName, + OpcodeVecI16x8Mul: OpcodeVecI16x8MulName, + OpcodeVecI16x8MinS: OpcodeVecI16x8MinSName, + OpcodeVecI16x8MinU: OpcodeVecI16x8MinUName, + OpcodeVecI16x8MaxS: OpcodeVecI16x8MaxSName, + OpcodeVecI16x8MaxU: OpcodeVecI16x8MaxUName, + OpcodeVecI16x8AvgrU: OpcodeVecI16x8AvgrUName, + OpcodeVecI16x8ExtMulLowI8x16S: OpcodeVecI16x8ExtMulLowI8x16SName, + OpcodeVecI16x8ExtMulHighI8x16S: OpcodeVecI16x8ExtMulHighI8x16SName, + OpcodeVecI16x8ExtMulLowI8x16U: OpcodeVecI16x8ExtMulLowI8x16UName, + OpcodeVecI16x8ExtMulHighI8x16U: OpcodeVecI16x8ExtMulHighI8x16UName, + OpcodeVecI32x4ExtaddPairwiseI16x8S: OpcodeVecI32x4ExtaddPairwiseI16x8SName, + OpcodeVecI32x4ExtaddPairwiseI16x8U: OpcodeVecI32x4ExtaddPairwiseI16x8UName, + OpcodeVecI32x4Abs: OpcodeVecI32x4AbsName, + OpcodeVecI32x4Neg: OpcodeVecI32x4NegName, + OpcodeVecI32x4AllTrue: OpcodeVecI32x4AllTrueName, + OpcodeVecI32x4BitMask: OpcodeVecI32x4BitMaskName, + OpcodeVecI32x4ExtendLowI16x8S: OpcodeVecI32x4ExtendLowI16x8SName, + OpcodeVecI32x4ExtendHighI16x8S: OpcodeVecI32x4ExtendHighI16x8SName, + OpcodeVecI32x4ExtendLowI16x8U: OpcodeVecI32x4ExtendLowI16x8UName, + OpcodeVecI32x4ExtendHighI16x8U: OpcodeVecI32x4ExtendHighI16x8UName, + OpcodeVecI32x4Shl: OpcodeVecI32x4ShlName, + OpcodeVecI32x4ShrS: OpcodeVecI32x4ShrSName, + OpcodeVecI32x4ShrU: OpcodeVecI32x4ShrUName, + OpcodeVecI32x4Add: OpcodeVecI32x4AddName, + OpcodeVecI32x4Sub: OpcodeVecI32x4SubName, + OpcodeVecI32x4Mul: OpcodeVecI32x4MulName, + OpcodeVecI32x4MinS: OpcodeVecI32x4MinSName, + OpcodeVecI32x4MinU: OpcodeVecI32x4MinUName, + OpcodeVecI32x4MaxS: OpcodeVecI32x4MaxSName, + OpcodeVecI32x4MaxU: OpcodeVecI32x4MaxUName, + OpcodeVecI32x4DotI16x8S: OpcodeVecI32x4DotI16x8SName, + OpcodeVecI32x4ExtMulLowI16x8S: OpcodeVecI32x4ExtMulLowI16x8SName, + OpcodeVecI32x4ExtMulHighI16x8S: OpcodeVecI32x4ExtMulHighI16x8SName, + OpcodeVecI32x4ExtMulLowI16x8U: OpcodeVecI32x4ExtMulLowI16x8UName, + OpcodeVecI32x4ExtMulHighI16x8U: OpcodeVecI32x4ExtMulHighI16x8UName, + OpcodeVecI64x2Abs: OpcodeVecI64x2AbsName, + OpcodeVecI64x2Neg: OpcodeVecI64x2NegName, + OpcodeVecI64x2AllTrue: OpcodeVecI64x2AllTrueName, + OpcodeVecI64x2BitMask: OpcodeVecI64x2BitMaskName, + OpcodeVecI64x2ExtendLowI32x4S: OpcodeVecI64x2ExtendLowI32x4SName, + OpcodeVecI64x2ExtendHighI32x4S: OpcodeVecI64x2ExtendHighI32x4SName, + OpcodeVecI64x2ExtendLowI32x4U: OpcodeVecI64x2ExtendLowI32x4UName, + OpcodeVecI64x2ExtendHighI32x4U: OpcodeVecI64x2ExtendHighI32x4UName, + OpcodeVecI64x2Shl: OpcodeVecI64x2ShlName, + OpcodeVecI64x2ShrS: OpcodeVecI64x2ShrSName, + OpcodeVecI64x2ShrU: OpcodeVecI64x2ShrUName, + OpcodeVecI64x2Add: OpcodeVecI64x2AddName, + OpcodeVecI64x2Sub: OpcodeVecI64x2SubName, + OpcodeVecI64x2Mul: OpcodeVecI64x2MulName, + OpcodeVecI64x2ExtMulLowI32x4S: OpcodeVecI64x2ExtMulLowI32x4SName, + OpcodeVecI64x2ExtMulHighI32x4S: OpcodeVecI64x2ExtMulHighI32x4SName, + OpcodeVecI64x2ExtMulLowI32x4U: OpcodeVecI64x2ExtMulLowI32x4UName, + OpcodeVecI64x2ExtMulHighI32x4U: OpcodeVecI64x2ExtMulHighI32x4UName, + OpcodeVecF32x4Ceil: OpcodeVecF32x4CeilName, + OpcodeVecF32x4Floor: OpcodeVecF32x4FloorName, + OpcodeVecF32x4Trunc: OpcodeVecF32x4TruncName, + OpcodeVecF32x4Nearest: OpcodeVecF32x4NearestName, + OpcodeVecF32x4Abs: OpcodeVecF32x4AbsName, + OpcodeVecF32x4Neg: OpcodeVecF32x4NegName, + OpcodeVecF32x4Sqrt: OpcodeVecF32x4SqrtName, + OpcodeVecF32x4Add: OpcodeVecF32x4AddName, + OpcodeVecF32x4Sub: OpcodeVecF32x4SubName, + OpcodeVecF32x4Mul: OpcodeVecF32x4MulName, + OpcodeVecF32x4Div: OpcodeVecF32x4DivName, + OpcodeVecF32x4Min: OpcodeVecF32x4MinName, + OpcodeVecF32x4Max: OpcodeVecF32x4MaxName, + OpcodeVecF32x4Pmin: OpcodeVecF32x4PminName, + OpcodeVecF32x4Pmax: OpcodeVecF32x4PmaxName, + OpcodeVecF64x2Ceil: OpcodeVecF64x2CeilName, + OpcodeVecF64x2Floor: OpcodeVecF64x2FloorName, + OpcodeVecF64x2Trunc: OpcodeVecF64x2TruncName, + OpcodeVecF64x2Nearest: OpcodeVecF64x2NearestName, + OpcodeVecF64x2Abs: OpcodeVecF64x2AbsName, + OpcodeVecF64x2Neg: OpcodeVecF64x2NegName, + OpcodeVecF64x2Sqrt: OpcodeVecF64x2SqrtName, + OpcodeVecF64x2Add: OpcodeVecF64x2AddName, + OpcodeVecF64x2Sub: OpcodeVecF64x2SubName, + OpcodeVecF64x2Mul: OpcodeVecF64x2MulName, + OpcodeVecF64x2Div: OpcodeVecF64x2DivName, + OpcodeVecF64x2Min: OpcodeVecF64x2MinName, + OpcodeVecF64x2Max: OpcodeVecF64x2MaxName, + OpcodeVecF64x2Pmin: OpcodeVecF64x2PminName, + OpcodeVecF64x2Pmax: OpcodeVecF64x2PmaxName, + OpcodeVecI32x4TruncSatF32x4S: OpcodeVecI32x4TruncSatF32x4SName, + OpcodeVecI32x4TruncSatF32x4U: OpcodeVecI32x4TruncSatF32x4UName, + OpcodeVecF32x4ConvertI32x4S: OpcodeVecF32x4ConvertI32x4SName, + OpcodeVecF32x4ConvertI32x4U: OpcodeVecF32x4ConvertI32x4UName, + OpcodeVecI32x4TruncSatF64x2SZero: OpcodeVecI32x4TruncSatF64x2SZeroName, + OpcodeVecI32x4TruncSatF64x2UZero: OpcodeVecI32x4TruncSatF64x2UZeroName, + OpcodeVecF64x2ConvertLowI32x4S: OpcodeVecF64x2ConvertLowI32x4SName, + OpcodeVecF64x2ConvertLowI32x4U: OpcodeVecF64x2ConvertLowI32x4UName, + OpcodeVecF32x4DemoteF64x2Zero: OpcodeVecF32x4DemoteF64x2ZeroName, + OpcodeVecF64x2PromoteLowF32x4Zero: OpcodeVecF64x2PromoteLowF32x4ZeroName, +} + +// VectorInstructionName returns the instruction name corresponding to the vector Opcode. +func VectorInstructionName(oc OpcodeVec) (ret string) { + return vectorInstructionName[oc] +} + +const ( + OpcodeAtomicMemoryNotifyName = "memory.atomic.notify" + OpcodeAtomicMemoryWait32Name = "memory.atomic.wait32" + OpcodeAtomicMemoryWait64Name = "memory.atomic.wait64" + OpcodeAtomicFenceName = "atomic.fence" + + OpcodeAtomicI32LoadName = "i32.atomic.load" + OpcodeAtomicI64LoadName = "i64.atomic.load" + OpcodeAtomicI32Load8UName = "i32.atomic.load8_u" + OpcodeAtomicI32Load16UName = "i32.atomic.load16_u" + OpcodeAtomicI64Load8UName = "i64.atomic.load8_u" + OpcodeAtomicI64Load16UName = "i64.atomic.load16_u" + OpcodeAtomicI64Load32UName = "i64.atomic.load32_u" + OpcodeAtomicI32StoreName = "i32.atomic.store" + OpcodeAtomicI64StoreName = "i64.atomic.store" + OpcodeAtomicI32Store8Name = "i32.atomic.store8" + OpcodeAtomicI32Store16Name = "i32.atomic.store16" + OpcodeAtomicI64Store8Name = "i64.atomic.store8" + OpcodeAtomicI64Store16Name = "i64.atomic.store16" + OpcodeAtomicI64Store32Name = "i64.atomic.store32" + + OpcodeAtomicI32RmwAddName = "i32.atomic.rmw.add" + OpcodeAtomicI64RmwAddName = "i64.atomic.rmw.add" + OpcodeAtomicI32Rmw8AddUName = "i32.atomic.rmw8.add_u" + OpcodeAtomicI32Rmw16AddUName = "i32.atomic.rmw16.add_u" + OpcodeAtomicI64Rmw8AddUName = "i64.atomic.rmw8.add_u" + OpcodeAtomicI64Rmw16AddUName = "i64.atomic.rmw16.add_u" + OpcodeAtomicI64Rmw32AddUName = "i64.atomic.rmw32.add_u" + + OpcodeAtomicI32RmwSubName = "i32.atomic.rmw.sub" + OpcodeAtomicI64RmwSubName = "i64.atomic.rmw.sub" + OpcodeAtomicI32Rmw8SubUName = "i32.atomic.rmw8.sub_u" + OpcodeAtomicI32Rmw16SubUName = "i32.atomic.rmw16.sub_u" + OpcodeAtomicI64Rmw8SubUName = "i64.atomic.rmw8.sub_u" + OpcodeAtomicI64Rmw16SubUName = "i64.atomic.rmw16.sub_u" + OpcodeAtomicI64Rmw32SubUName = "i64.atomic.rmw32.sub_u" + + OpcodeAtomicI32RmwAndName = "i32.atomic.rmw.and" + OpcodeAtomicI64RmwAndName = "i64.atomic.rmw.and" + OpcodeAtomicI32Rmw8AndUName = "i32.atomic.rmw8.and_u" + OpcodeAtomicI32Rmw16AndUName = "i32.atomic.rmw16.and_u" + OpcodeAtomicI64Rmw8AndUName = "i64.atomic.rmw8.and_u" + OpcodeAtomicI64Rmw16AndUName = "i64.atomic.rmw16.and_u" + OpcodeAtomicI64Rmw32AndUName = "i64.atomic.rmw32.and_u" + + OpcodeAtomicI32RmwOrName = "i32.atomic.rmw.or" + OpcodeAtomicI64RmwOrName = "i64.atomic.rmw.or" + OpcodeAtomicI32Rmw8OrUName = "i32.atomic.rmw8.or_u" + OpcodeAtomicI32Rmw16OrUName = "i32.atomic.rmw16.or_u" + OpcodeAtomicI64Rmw8OrUName = "i64.atomic.rmw8.or_u" + OpcodeAtomicI64Rmw16OrUName = "i64.atomic.rmw16.or_u" + OpcodeAtomicI64Rmw32OrUName = "i64.atomic.rmw32.or_u" + + OpcodeAtomicI32RmwXorName = "i32.atomic.rmw.xor" + OpcodeAtomicI64RmwXorName = "i64.atomic.rmw.xor" + OpcodeAtomicI32Rmw8XorUName = "i32.atomic.rmw8.xor_u" + OpcodeAtomicI32Rmw16XorUName = "i32.atomic.rmw16.xor_u" + OpcodeAtomicI64Rmw8XorUName = "i64.atomic.rmw8.xor_u" + OpcodeAtomicI64Rmw16XorUName = "i64.atomic.rmw16.xor_u" + OpcodeAtomicI64Rmw32XorUName = "i64.atomic.rmw32.xor_u" + + OpcodeAtomicI32RmwXchgName = "i32.atomic.rmw.xchg" + OpcodeAtomicI64RmwXchgName = "i64.atomic.rmw.xchg" + OpcodeAtomicI32Rmw8XchgUName = "i32.atomic.rmw8.xchg_u" + OpcodeAtomicI32Rmw16XchgUName = "i32.atomic.rmw16.xchg_u" + OpcodeAtomicI64Rmw8XchgUName = "i64.atomic.rmw8.xchg_u" + OpcodeAtomicI64Rmw16XchgUName = "i64.atomic.rmw16.xchg_u" + OpcodeAtomicI64Rmw32XchgUName = "i64.atomic.rmw32.xchg_u" + + OpcodeAtomicI32RmwCmpxchgName = "i32.atomic.rmw.cmpxchg" + OpcodeAtomicI64RmwCmpxchgName = "i64.atomic.rmw.cmpxchg" + OpcodeAtomicI32Rmw8CmpxchgUName = "i32.atomic.rmw8.cmpxchg_u" + OpcodeAtomicI32Rmw16CmpxchgUName = "i32.atomic.rmw16.cmpxchg_u" + OpcodeAtomicI64Rmw8CmpxchgUName = "i64.atomic.rmw8.cmpxchg_u" + OpcodeAtomicI64Rmw16CmpxchgUName = "i64.atomic.rmw16.cmpxchg_u" + OpcodeAtomicI64Rmw32CmpxchgUName = "i64.atomic.rmw32.cmpxchg_u" +) + +var atomicInstructionName = map[OpcodeAtomic]string{ + OpcodeAtomicMemoryNotify: OpcodeAtomicMemoryNotifyName, + OpcodeAtomicMemoryWait32: OpcodeAtomicMemoryWait32Name, + OpcodeAtomicMemoryWait64: OpcodeAtomicMemoryWait64Name, + OpcodeAtomicFence: OpcodeAtomicFenceName, + + OpcodeAtomicI32Load: OpcodeAtomicI32LoadName, + OpcodeAtomicI64Load: OpcodeAtomicI64LoadName, + OpcodeAtomicI32Load8U: OpcodeAtomicI32Load8UName, + OpcodeAtomicI32Load16U: OpcodeAtomicI32Load16UName, + OpcodeAtomicI64Load8U: OpcodeAtomicI64Load8UName, + OpcodeAtomicI64Load16U: OpcodeAtomicI64Load16UName, + OpcodeAtomicI64Load32U: OpcodeAtomicI64Load32UName, + OpcodeAtomicI32Store: OpcodeAtomicI32StoreName, + OpcodeAtomicI64Store: OpcodeAtomicI64StoreName, + OpcodeAtomicI32Store8: OpcodeAtomicI32Store8Name, + OpcodeAtomicI32Store16: OpcodeAtomicI32Store16Name, + OpcodeAtomicI64Store8: OpcodeAtomicI64Store8Name, + OpcodeAtomicI64Store16: OpcodeAtomicI64Store16Name, + OpcodeAtomicI64Store32: OpcodeAtomicI64Store32Name, + + OpcodeAtomicI32RmwAdd: OpcodeAtomicI32RmwAddName, + OpcodeAtomicI64RmwAdd: OpcodeAtomicI64RmwAddName, + OpcodeAtomicI32Rmw8AddU: OpcodeAtomicI32Rmw8AddUName, + OpcodeAtomicI32Rmw16AddU: OpcodeAtomicI32Rmw16AddUName, + OpcodeAtomicI64Rmw8AddU: OpcodeAtomicI64Rmw8AddUName, + OpcodeAtomicI64Rmw16AddU: OpcodeAtomicI64Rmw16AddUName, + OpcodeAtomicI64Rmw32AddU: OpcodeAtomicI64Rmw32AddUName, + + OpcodeAtomicI32RmwSub: OpcodeAtomicI32RmwSubName, + OpcodeAtomicI64RmwSub: OpcodeAtomicI64RmwSubName, + OpcodeAtomicI32Rmw8SubU: OpcodeAtomicI32Rmw8SubUName, + OpcodeAtomicI32Rmw16SubU: OpcodeAtomicI32Rmw16SubUName, + OpcodeAtomicI64Rmw8SubU: OpcodeAtomicI64Rmw8SubUName, + OpcodeAtomicI64Rmw16SubU: OpcodeAtomicI64Rmw16SubUName, + OpcodeAtomicI64Rmw32SubU: OpcodeAtomicI64Rmw32SubUName, + + OpcodeAtomicI32RmwAnd: OpcodeAtomicI32RmwAndName, + OpcodeAtomicI64RmwAnd: OpcodeAtomicI64RmwAndName, + OpcodeAtomicI32Rmw8AndU: OpcodeAtomicI32Rmw8AndUName, + OpcodeAtomicI32Rmw16AndU: OpcodeAtomicI32Rmw16AndUName, + OpcodeAtomicI64Rmw8AndU: OpcodeAtomicI64Rmw8AndUName, + OpcodeAtomicI64Rmw16AndU: OpcodeAtomicI64Rmw16AndUName, + OpcodeAtomicI64Rmw32AndU: OpcodeAtomicI64Rmw32AndUName, + + OpcodeAtomicI32RmwOr: OpcodeAtomicI32RmwOrName, + OpcodeAtomicI64RmwOr: OpcodeAtomicI64RmwOrName, + OpcodeAtomicI32Rmw8OrU: OpcodeAtomicI32Rmw8OrUName, + OpcodeAtomicI32Rmw16OrU: OpcodeAtomicI32Rmw16OrUName, + OpcodeAtomicI64Rmw8OrU: OpcodeAtomicI64Rmw8OrUName, + OpcodeAtomicI64Rmw16OrU: OpcodeAtomicI64Rmw16OrUName, + OpcodeAtomicI64Rmw32OrU: OpcodeAtomicI64Rmw32OrUName, + + OpcodeAtomicI32RmwXor: OpcodeAtomicI32RmwXorName, + OpcodeAtomicI64RmwXor: OpcodeAtomicI64RmwXorName, + OpcodeAtomicI32Rmw8XorU: OpcodeAtomicI32Rmw8XorUName, + OpcodeAtomicI32Rmw16XorU: OpcodeAtomicI32Rmw16XorUName, + OpcodeAtomicI64Rmw8XorU: OpcodeAtomicI64Rmw8XorUName, + OpcodeAtomicI64Rmw16XorU: OpcodeAtomicI64Rmw16XorUName, + OpcodeAtomicI64Rmw32XorU: OpcodeAtomicI64Rmw32XorUName, + + OpcodeAtomicI32RmwXchg: OpcodeAtomicI32RmwXchgName, + OpcodeAtomicI64RmwXchg: OpcodeAtomicI64RmwXchgName, + OpcodeAtomicI32Rmw8XchgU: OpcodeAtomicI32Rmw8XchgUName, + OpcodeAtomicI32Rmw16XchgU: OpcodeAtomicI32Rmw16XchgUName, + OpcodeAtomicI64Rmw8XchgU: OpcodeAtomicI64Rmw8XchgUName, + OpcodeAtomicI64Rmw16XchgU: OpcodeAtomicI64Rmw16XchgUName, + OpcodeAtomicI64Rmw32XchgU: OpcodeAtomicI64Rmw32XchgUName, + + OpcodeAtomicI32RmwCmpxchg: OpcodeAtomicI32RmwCmpxchgName, + OpcodeAtomicI64RmwCmpxchg: OpcodeAtomicI64RmwCmpxchgName, + OpcodeAtomicI32Rmw8CmpxchgU: OpcodeAtomicI32Rmw8CmpxchgUName, + OpcodeAtomicI32Rmw16CmpxchgU: OpcodeAtomicI32Rmw16CmpxchgUName, + OpcodeAtomicI64Rmw8CmpxchgU: OpcodeAtomicI64Rmw8CmpxchgUName, + OpcodeAtomicI64Rmw16CmpxchgU: OpcodeAtomicI64Rmw16CmpxchgUName, + OpcodeAtomicI64Rmw32CmpxchgU: OpcodeAtomicI64Rmw32CmpxchgUName, +} + +// AtomicInstructionName returns the instruction name corresponding to the atomic Opcode. +func AtomicInstructionName(oc OpcodeAtomic) (ret string) { + return atomicInstructionName[oc] +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go new file mode 100644 index 00000000..9a1f0c6d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go @@ -0,0 +1,476 @@ +package wasm + +import ( + "container/list" + "encoding/binary" + "fmt" + "math" + "reflect" + "sync" + "sync/atomic" + "time" + "unsafe" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/wasmruntime" +) + +const ( + // MemoryPageSize is the unit of memory length in WebAssembly, + // and is defined as 2^16 = 65536. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0 + MemoryPageSize = uint32(65536) + // MemoryLimitPages is maximum number of pages defined (2^16). + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem + MemoryLimitPages = uint32(65536) + // MemoryPageSizeInBits satisfies the relation: "1 << MemoryPageSizeInBits == MemoryPageSize". + MemoryPageSizeInBits = 16 +) + +// compile-time check to ensure MemoryInstance implements api.Memory +var _ api.Memory = &MemoryInstance{} + +type waiters struct { + mux sync.Mutex + l *list.List +} + +// MemoryInstance represents a memory instance in a store, and implements api.Memory. +// +// Note: In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means the precise memory is always +// wasm.Store Memories index zero: `store.Memories[0]` +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0. +type MemoryInstance struct { + internalapi.WazeroOnlyType + + Buffer []byte + Min, Cap, Max uint32 + Shared bool + // definition is known at compile time. + definition api.MemoryDefinition + + // Mux is used in interpreter mode to prevent overlapping calls to atomic instructions, + // introduced with WebAssembly threads proposal, and in compiler mode to make memory modifications + // within Grow non-racy for the Go race detector. + Mux sync.Mutex + + // waiters implements atomic wait and notify. It is implemented similarly to golang.org/x/sync/semaphore, + // with a fixed weight of 1 and no spurious notifications. + waiters sync.Map + + // ownerModuleEngine is the module engine that owns this memory instance. + ownerModuleEngine ModuleEngine + + expBuffer experimental.LinearMemory +} + +// NewMemoryInstance creates a new instance based on the parameters in the SectionIDMemory. +func NewMemoryInstance(memSec *Memory, allocator experimental.MemoryAllocator, moduleEngine ModuleEngine) *MemoryInstance { + minBytes := MemoryPagesToBytesNum(memSec.Min) + capBytes := MemoryPagesToBytesNum(memSec.Cap) + maxBytes := MemoryPagesToBytesNum(memSec.Max) + + var buffer []byte + var expBuffer experimental.LinearMemory + if allocator != nil { + expBuffer = allocator.Allocate(capBytes, maxBytes) + buffer = expBuffer.Reallocate(minBytes) + _ = buffer[:minBytes] // Bounds check that the minimum was allocated. + } else if memSec.IsShared { + // Shared memory needs a fixed buffer, so allocate with the maximum size. + // + // The rationale as to why we can simply use make([]byte) to a fixed buffer is that Go's GC is non-relocating. + // That is not a part of Go spec, but is well-known thing in Go community (wazero's compiler heavily relies on it!) + // * https://github.com/go4org/unsafe-assume-no-moving-gc + // + // Also, allocating Max here isn't harmful as the Go runtime uses mmap for large allocations, therefore, + // the memory buffer allocation here is virtual and doesn't consume physical memory until it's used. + // * https://github.com/golang/go/blob/8121604559035734c9677d5281bbdac8b1c17a1e/src/runtime/malloc.go#L1059 + // * https://github.com/golang/go/blob/8121604559035734c9677d5281bbdac8b1c17a1e/src/runtime/malloc.go#L1165 + buffer = make([]byte, minBytes, maxBytes) + } else { + buffer = make([]byte, minBytes, capBytes) + } + return &MemoryInstance{ + Buffer: buffer, + Min: memSec.Min, + Cap: memoryBytesNumToPages(uint64(cap(buffer))), + Max: memSec.Max, + Shared: memSec.IsShared, + expBuffer: expBuffer, + ownerModuleEngine: moduleEngine, + } +} + +// Definition implements the same method as documented on api.Memory. +func (m *MemoryInstance) Definition() api.MemoryDefinition { + return m.definition +} + +// Size implements the same method as documented on api.Memory. +func (m *MemoryInstance) Size() uint32 { + return uint32(len(m.Buffer)) +} + +// ReadByte implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadByte(offset uint32) (byte, bool) { + if !m.hasSize(offset, 1) { + return 0, false + } + return m.Buffer[offset], true +} + +// ReadUint16Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadUint16Le(offset uint32) (uint16, bool) { + if !m.hasSize(offset, 2) { + return 0, false + } + return binary.LittleEndian.Uint16(m.Buffer[offset : offset+2]), true +} + +// ReadUint32Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadUint32Le(offset uint32) (uint32, bool) { + return m.readUint32Le(offset) +} + +// ReadFloat32Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadFloat32Le(offset uint32) (float32, bool) { + v, ok := m.readUint32Le(offset) + if !ok { + return 0, false + } + return math.Float32frombits(v), true +} + +// ReadUint64Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadUint64Le(offset uint32) (uint64, bool) { + return m.readUint64Le(offset) +} + +// ReadFloat64Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) { + v, ok := m.readUint64Le(offset) + if !ok { + return 0, false + } + return math.Float64frombits(v), true +} + +// Read implements the same method as documented on api.Memory. +func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) { + if !m.hasSize(offset, uint64(byteCount)) { + return nil, false + } + return m.Buffer[offset : offset+byteCount : offset+byteCount], true +} + +// WriteByte implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteByte(offset uint32, v byte) bool { + if !m.hasSize(offset, 1) { + return false + } + m.Buffer[offset] = v + return true +} + +// WriteUint16Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteUint16Le(offset uint32, v uint16) bool { + if !m.hasSize(offset, 2) { + return false + } + binary.LittleEndian.PutUint16(m.Buffer[offset:], v) + return true +} + +// WriteUint32Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteUint32Le(offset, v uint32) bool { + return m.writeUint32Le(offset, v) +} + +// WriteFloat32Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteFloat32Le(offset uint32, v float32) bool { + return m.writeUint32Le(offset, math.Float32bits(v)) +} + +// WriteUint64Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteUint64Le(offset uint32, v uint64) bool { + return m.writeUint64Le(offset, v) +} + +// WriteFloat64Le implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteFloat64Le(offset uint32, v float64) bool { + return m.writeUint64Le(offset, math.Float64bits(v)) +} + +// Write implements the same method as documented on api.Memory. +func (m *MemoryInstance) Write(offset uint32, val []byte) bool { + if !m.hasSize(offset, uint64(len(val))) { + return false + } + copy(m.Buffer[offset:], val) + return true +} + +// WriteString implements the same method as documented on api.Memory. +func (m *MemoryInstance) WriteString(offset uint32, val string) bool { + if !m.hasSize(offset, uint64(len(val))) { + return false + } + copy(m.Buffer[offset:], val) + return true +} + +// MemoryPagesToBytesNum converts the given pages into the number of bytes contained in these pages. +func MemoryPagesToBytesNum(pages uint32) (bytesNum uint64) { + return uint64(pages) << MemoryPageSizeInBits +} + +// Grow implements the same method as documented on api.Memory. +func (m *MemoryInstance) Grow(delta uint32) (result uint32, ok bool) { + if m.Shared { + m.Mux.Lock() + defer m.Mux.Unlock() + } + + currentPages := m.Pages() + if delta == 0 { + return currentPages, true + } + + newPages := currentPages + delta + if newPages > m.Max || int32(delta) < 0 { + return 0, false + } else if m.expBuffer != nil { + buffer := m.expBuffer.Reallocate(MemoryPagesToBytesNum(newPages)) + if buffer == nil { + // Allocator failed to grow. + return 0, false + } + if m.Shared { + if unsafe.SliceData(buffer) != unsafe.SliceData(m.Buffer) { + panic("shared memory cannot move, this is a bug in the memory allocator") + } + // We assume grow is called under a guest lock. + // But the memory length is accessed elsewhere, + // so use atomic to make the new length visible across threads. + atomicStoreLengthAndCap(&m.Buffer, uintptr(len(buffer)), uintptr(cap(buffer))) + m.Cap = memoryBytesNumToPages(uint64(cap(buffer))) + } else { + m.Buffer = buffer + m.Cap = newPages + } + } else if newPages > m.Cap { // grow the memory. + if m.Shared { + panic("shared memory cannot be grown, this is a bug in wazero") + } + m.Buffer = append(m.Buffer, make([]byte, MemoryPagesToBytesNum(delta))...) + m.Cap = newPages + } else { // We already have the capacity we need. + if m.Shared { + // We assume grow is called under a guest lock. + // But the memory length is accessed elsewhere, + // so use atomic to make the new length visible across threads. + atomicStoreLength(&m.Buffer, uintptr(MemoryPagesToBytesNum(newPages))) + } else { + m.Buffer = m.Buffer[:MemoryPagesToBytesNum(newPages)] + } + } + m.ownerModuleEngine.MemoryGrown() + return currentPages, true +} + +// Pages implements the same method as documented on api.Memory. +func (m *MemoryInstance) Pages() (result uint32) { + return memoryBytesNumToPages(uint64(len(m.Buffer))) +} + +// PagesToUnitOfBytes converts the pages to a human-readable form similar to what's specified. e.g. 1 -> "64Ki" +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0 +func PagesToUnitOfBytes(pages uint32) string { + k := pages * 64 + if k < 1024 { + return fmt.Sprintf("%d Ki", k) + } + m := k / 1024 + if m < 1024 { + return fmt.Sprintf("%d Mi", m) + } + g := m / 1024 + if g < 1024 { + return fmt.Sprintf("%d Gi", g) + } + return fmt.Sprintf("%d Ti", g/1024) +} + +// Below are raw functions used to implement the api.Memory API: + +// Uses atomic write to update the length of a slice. +func atomicStoreLengthAndCap(slice *[]byte, length uintptr, cap uintptr) { + //nolint:staticcheck + slicePtr := (*reflect.SliceHeader)(unsafe.Pointer(slice)) + capPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Cap)) + atomic.StoreUintptr(capPtr, cap) + lenPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Len)) + atomic.StoreUintptr(lenPtr, length) +} + +// Uses atomic write to update the length of a slice. +func atomicStoreLength(slice *[]byte, length uintptr) { + //nolint:staticcheck + slicePtr := (*reflect.SliceHeader)(unsafe.Pointer(slice)) + lenPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Len)) + atomic.StoreUintptr(lenPtr, length) +} + +// memoryBytesNumToPages converts the given number of bytes into the number of pages. +func memoryBytesNumToPages(bytesNum uint64) (pages uint32) { + return uint32(bytesNum >> MemoryPageSizeInBits) +} + +// hasSize returns true if Len is sufficient for byteCount at the given offset. +// +// Note: This is always fine, because memory can grow, but never shrink. +func (m *MemoryInstance) hasSize(offset uint32, byteCount uint64) bool { + return uint64(offset)+byteCount <= uint64(len(m.Buffer)) // uint64 prevents overflow on add +} + +// readUint32Le implements ReadUint32Le without using a context. This is extracted as both ints and floats are stored in +// memory as uint32le. +func (m *MemoryInstance) readUint32Le(offset uint32) (uint32, bool) { + if !m.hasSize(offset, 4) { + return 0, false + } + return binary.LittleEndian.Uint32(m.Buffer[offset : offset+4]), true +} + +// readUint64Le implements ReadUint64Le without using a context. This is extracted as both ints and floats are stored in +// memory as uint64le. +func (m *MemoryInstance) readUint64Le(offset uint32) (uint64, bool) { + if !m.hasSize(offset, 8) { + return 0, false + } + return binary.LittleEndian.Uint64(m.Buffer[offset : offset+8]), true +} + +// writeUint32Le implements WriteUint32Le without using a context. This is extracted as both ints and floats are stored +// in memory as uint32le. +func (m *MemoryInstance) writeUint32Le(offset uint32, v uint32) bool { + if !m.hasSize(offset, 4) { + return false + } + binary.LittleEndian.PutUint32(m.Buffer[offset:], v) + return true +} + +// writeUint64Le implements WriteUint64Le without using a context. This is extracted as both ints and floats are stored +// in memory as uint64le. +func (m *MemoryInstance) writeUint64Le(offset uint32, v uint64) bool { + if !m.hasSize(offset, 8) { + return false + } + binary.LittleEndian.PutUint64(m.Buffer[offset:], v) + return true +} + +// Wait32 suspends the caller until the offset is notified by a different agent. +func (m *MemoryInstance) Wait32(offset uint32, exp uint32, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint32) uint64 { + w := m.getWaiters(offset) + w.mux.Lock() + + cur := reader(m, offset) + if cur != exp { + w.mux.Unlock() + return 1 + } + + return m.wait(w, timeout) +} + +// Wait64 suspends the caller until the offset is notified by a different agent. +func (m *MemoryInstance) Wait64(offset uint32, exp uint64, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint64) uint64 { + w := m.getWaiters(offset) + w.mux.Lock() + + cur := reader(m, offset) + if cur != exp { + w.mux.Unlock() + return 1 + } + + return m.wait(w, timeout) +} + +func (m *MemoryInstance) wait(w *waiters, timeout int64) uint64 { + if w.l == nil { + w.l = list.New() + } + + // The specification requires a trap if the number of existing waiters + 1 == 2^32, so we add a check here. + // In practice, it is unlikely the application would ever accumulate such a large number of waiters as it + // indicates several GB of RAM used just for the list of waiters. + // https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#wait + if uint64(w.l.Len()+1) == 1<<32 { + w.mux.Unlock() + panic(wasmruntime.ErrRuntimeTooManyWaiters) + } + + ready := make(chan struct{}) + elem := w.l.PushBack(ready) + w.mux.Unlock() + + if timeout < 0 { + <-ready + return 0 + } else { + select { + case <-ready: + return 0 + case <-time.After(time.Duration(timeout)): + // While we could see if the channel completed by now and ignore the timeout, similar to x/sync/semaphore, + // the Wasm spec doesn't specify this behavior, so we keep things simple by prioritizing the timeout. + w.mux.Lock() + w.l.Remove(elem) + w.mux.Unlock() + return 2 + } + } +} + +func (m *MemoryInstance) getWaiters(offset uint32) *waiters { + wAny, ok := m.waiters.Load(offset) + if !ok { + // The first time an address is waited on, simultaneous waits will cause extra allocations. + // Further operations will be loaded above, which is also the general pattern of usage with + // mutexes. + wAny, _ = m.waiters.LoadOrStore(offset, &waiters{}) + } + + return wAny.(*waiters) +} + +// Notify wakes up at most count waiters at the given offset. +func (m *MemoryInstance) Notify(offset uint32, count uint32) uint32 { + wAny, ok := m.waiters.Load(offset) + if !ok { + return 0 + } + w := wAny.(*waiters) + + w.mux.Lock() + defer w.mux.Unlock() + if w.l == nil { + return 0 + } + + res := uint32(0) + for num := w.l.Len(); num > 0 && res < count; num = w.l.Len() { + w := w.l.Remove(w.l.Front()).(chan struct{}) + close(w) + res++ + } + + return res +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go new file mode 100644 index 00000000..03d6fd30 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go @@ -0,0 +1,128 @@ +package wasm + +import ( + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/internalapi" +) + +// ImportedMemories implements the same method as documented on wazero.CompiledModule. +func (m *Module) ImportedMemories() (ret []api.MemoryDefinition) { + for i := range m.MemoryDefinitionSection { + d := &m.MemoryDefinitionSection[i] + if d.importDesc != nil { + ret = append(ret, d) + } + } + return +} + +// ExportedMemories implements the same method as documented on wazero.CompiledModule. +func (m *Module) ExportedMemories() map[string]api.MemoryDefinition { + ret := map[string]api.MemoryDefinition{} + for i := range m.MemoryDefinitionSection { + d := &m.MemoryDefinitionSection[i] + for _, e := range d.exportNames { + ret[e] = d + } + } + return ret +} + +// BuildMemoryDefinitions generates memory metadata that can be parsed from +// the module. This must be called after all validation. +// +// Note: This is exported for wazero.Runtime `CompileModule`. +func (m *Module) BuildMemoryDefinitions() { + var moduleName string + if m.NameSection != nil { + moduleName = m.NameSection.ModuleName + } + + memoryCount := m.ImportMemoryCount + if m.MemorySection != nil { + memoryCount++ + } + + if memoryCount == 0 { + return + } + + m.MemoryDefinitionSection = make([]MemoryDefinition, 0, memoryCount) + importMemIdx := Index(0) + for i := range m.ImportSection { + imp := &m.ImportSection[i] + if imp.Type != ExternTypeMemory { + continue + } + + m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{ + importDesc: &[2]string{imp.Module, imp.Name}, + index: importMemIdx, + memory: imp.DescMem, + }) + importMemIdx++ + } + + if m.MemorySection != nil { + m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{ + index: importMemIdx, + memory: m.MemorySection, + }) + } + + for i := range m.MemoryDefinitionSection { + d := &m.MemoryDefinitionSection[i] + d.moduleName = moduleName + for i := range m.ExportSection { + e := &m.ExportSection[i] + if e.Type == ExternTypeMemory && e.Index == d.index { + d.exportNames = append(d.exportNames, e.Name) + } + } + } +} + +// MemoryDefinition implements api.MemoryDefinition +type MemoryDefinition struct { + internalapi.WazeroOnlyType + moduleName string + index Index + importDesc *[2]string + exportNames []string + memory *Memory +} + +// ModuleName implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) ModuleName() string { + return f.moduleName +} + +// Index implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) Index() uint32 { + return f.index +} + +// Import implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) Import() (moduleName, name string, isImport bool) { + if importDesc := f.importDesc; importDesc != nil { + moduleName, name, isImport = importDesc[0], importDesc[1], true + } + return +} + +// ExportNames implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) ExportNames() []string { + return f.exportNames +} + +// Min implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) Min() uint32 { + return f.memory.Min +} + +// Max implements the same method as documented on api.MemoryDefinition. +func (f *MemoryDefinition) Max() (max uint32, encoded bool) { + max = f.memory.Max + encoded = f.memory.IsMaxEncoded + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go new file mode 100644 index 00000000..8369ad9e --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go @@ -0,0 +1,1078 @@ +package wasm + +import ( + "bytes" + "crypto/sha256" + "encoding/binary" + "errors" + "fmt" + "io" + "sort" + "strings" + "sync" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/ieee754" + "github.com/tetratelabs/wazero/internal/leb128" + "github.com/tetratelabs/wazero/internal/wasmdebug" +) + +// Module is a WebAssembly binary representation. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#modules%E2%91%A8 +// +// Differences from the specification: +// * NameSection is the only key ("name") decoded from the SectionIDCustom. +// * ExportSection is represented as a map for lookup convenience. +// * Code.GoFunc is contains any go `func`. It may be present when Code.Body is not. +type Module struct { + // TypeSection contains the unique FunctionType of functions imported or defined in this module. + // + // Note: Currently, there is no type ambiguity in the index as WebAssembly 1.0 only defines function type. + // In the future, other types may be introduced to support CoreFeatures such as module linking. + // + // Note: In the Binary Format, this is SectionIDType. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#types%E2%91%A0%E2%91%A0 + TypeSection []FunctionType + + // ImportSection contains imported functions, tables, memories or globals required for instantiation + // (Store.Instantiate). + // + // Note: there are no unique constraints relating to the two-level namespace of Import.Module and Import.Name. + // + // Note: In the Binary Format, this is SectionIDImport. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#import-section%E2%91%A0 + ImportSection []Import + // ImportFunctionCount ImportGlobalCount ImportMemoryCount, and ImportTableCount are + // the cached import count per ExternType set during decoding. + ImportFunctionCount, + ImportGlobalCount, + ImportMemoryCount, + ImportTableCount Index + // ImportPerModule maps a module name to the list of Import to be imported from the module. + // This is used to do fast import resolution during instantiation. + ImportPerModule map[string][]*Import + + // FunctionSection contains the index in TypeSection of each function defined in this module. + // + // Note: The function Index space begins with imported functions and ends with those defined in this module. + // For example, if there are two imported functions and one defined in this module, the function Index 3 is defined + // in this module at FunctionSection[0]. + // + // Note: FunctionSection is index correlated with the CodeSection. If given the same position, e.g. 2, a function + // type is at TypeSection[FunctionSection[2]], while its locals and body are at CodeSection[2]. + // + // Note: In the Binary Format, this is SectionIDFunction. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-section%E2%91%A0 + FunctionSection []Index + + // TableSection contains each table defined in this module. + // + // Note: The table Index space begins with imported tables and ends with those defined in this module. + // For example, if there are two imported tables and one defined in this module, the table Index 3 is defined in + // this module at TableSection[0]. + // + // Note: Version 1.0 (20191205) of the WebAssembly spec allows at most one table definition per module, so the + // length of the TableSection can be zero or one, and can only be one if there is no imported table. + // + // Note: In the Binary Format, this is SectionIDTable. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-section%E2%91%A0 + TableSection []Table + + // MemorySection contains each memory defined in this module. + // + // Note: The memory Index space begins with imported memories and ends with those defined in this module. + // For example, if there are two imported memories and one defined in this module, the memory Index 3 is defined in + // this module at TableSection[0]. + // + // Note: Version 1.0 (20191205) of the WebAssembly spec allows at most one memory definition per module, so the + // length of the MemorySection can be zero or one, and can only be one if there is no imported memory. + // + // Note: In the Binary Format, this is SectionIDMemory. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-section%E2%91%A0 + MemorySection *Memory + + // GlobalSection contains each global defined in this module. + // + // Global indexes are offset by any imported globals because the global index begins with imports, followed by + // ones defined in this module. For example, if there are two imported globals and three defined in this module, the + // global at index 3 is defined in this module at GlobalSection[0]. + // + // Note: In the Binary Format, this is SectionIDGlobal. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#global-section%E2%91%A0 + GlobalSection []Global + + // ExportSection contains each export defined in this module. + // + // Note: In the Binary Format, this is SectionIDExport. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0 + ExportSection []Export + // Exports maps a name to Export, and is convenient for fast look up of exported instances at runtime. + // Each item of this map points to an element of ExportSection. + Exports map[string]*Export + + // StartSection is the index of a function to call before returning from Store.Instantiate. + // + // Note: The index here is not the position in the FunctionSection, rather in the function index, which + // begins with imported functions. + // + // Note: In the Binary Format, this is SectionIDStart. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#start-section%E2%91%A0 + StartSection *Index + + // Note: In the Binary Format, this is SectionIDElement. + ElementSection []ElementSegment + + // CodeSection is index-correlated with FunctionSection and contains each + // function's locals and body. + // + // When present, the HostFunctionSection of the same index must be nil. + // + // Note: In the Binary Format, this is SectionIDCode. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#code-section%E2%91%A0 + CodeSection []Code + + // Note: In the Binary Format, this is SectionIDData. + DataSection []DataSegment + + // NameSection is set when the SectionIDCustom "name" was successfully decoded from the binary format. + // + // Note: This is the only SectionIDCustom defined in the WebAssembly 1.0 (20191205) Binary Format. + // Others are skipped as they are not used in wazero. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0 + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0 + NameSection *NameSection + + // CustomSections are set when the SectionIDCustom other than "name" were successfully decoded from the binary format. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0 + CustomSections []*CustomSection + + // DataCountSection is the optional section and holds the number of data segments in the data section. + // + // Note: This may exist in WebAssembly 2.0 or WebAssembly 1.0 with CoreFeatureBulkMemoryOperations. + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-count-section + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions + DataCountSection *uint32 + + // ID is the sha256 value of the source wasm plus the configurations which affect the runtime representation of + // Wasm binary. This is only used for caching. + ID ModuleID + + // IsHostModule true if this is the host module, false otherwise. + IsHostModule bool + + // functionDefinitionSectionInitOnce guards FunctionDefinitionSection so that it is initialized exactly once. + functionDefinitionSectionInitOnce sync.Once + + // FunctionDefinitionSection is a wazero-specific section. + FunctionDefinitionSection []FunctionDefinition + + // MemoryDefinitionSection is a wazero-specific section. + MemoryDefinitionSection []MemoryDefinition + + // DWARFLines is used to emit DWARF based stack trace. This is created from the multiple custom sections + // as described in https://yurydelendik.github.io/webassembly-dwarf/, though it is not specified in the Wasm + // specification: https://github.com/WebAssembly/debugging/issues/1 + DWARFLines *wasmdebug.DWARFLines +} + +// ModuleID represents sha256 hash value uniquely assigned to Module. +type ModuleID = [sha256.Size]byte + +// The wazero specific limitation described at RATIONALE.md. +// TL;DR; We multiply by 8 (to get offsets in bytes) and the multiplication result must be less than 32bit max +const ( + MaximumGlobals = uint32(1 << 27) + MaximumFunctionIndex = uint32(1 << 27) + MaximumTableIndex = uint32(1 << 27) +) + +// AssignModuleID calculates a sha256 checksum on `wasm` and other args, and set Module.ID to the result. +// See the doc on Module.ID on what it's used for. +func (m *Module) AssignModuleID(wasm []byte, listeners []experimental.FunctionListener, withEnsureTermination bool) { + h := sha256.New() + h.Write(wasm) + // Use the pre-allocated space backed by m.ID below. + + // Write the existence of listeners to the checksum per function. + for i, l := range listeners { + binary.LittleEndian.PutUint32(m.ID[:], uint32(i)) + m.ID[4] = boolToByte(l != nil) + h.Write(m.ID[:5]) + } + // Write the flag of ensureTermination to the checksum. + m.ID[0] = boolToByte(withEnsureTermination) + h.Write(m.ID[:1]) + // Get checksum by passing the slice underlying m.ID. + h.Sum(m.ID[:0]) +} + +func boolToByte(b bool) (ret byte) { + if b { + ret = 1 + } + return +} + +// typeOfFunction returns the wasm.FunctionType for the given function space index or nil. +func (m *Module) typeOfFunction(funcIdx Index) *FunctionType { + typeSectionLength, importedFunctionCount := uint32(len(m.TypeSection)), m.ImportFunctionCount + if funcIdx < importedFunctionCount { + // Imports are not exclusively functions. This is the current function index in the loop. + cur := Index(0) + for i := range m.ImportSection { + imp := &m.ImportSection[i] + if imp.Type != ExternTypeFunc { + continue + } + if funcIdx == cur { + if imp.DescFunc >= typeSectionLength { + return nil + } + return &m.TypeSection[imp.DescFunc] + } + cur++ + } + } + + funcSectionIdx := funcIdx - m.ImportFunctionCount + if funcSectionIdx >= uint32(len(m.FunctionSection)) { + return nil + } + typeIdx := m.FunctionSection[funcSectionIdx] + if typeIdx >= typeSectionLength { + return nil + } + return &m.TypeSection[typeIdx] +} + +func (m *Module) Validate(enabledFeatures api.CoreFeatures) error { + for i := range m.TypeSection { + tp := &m.TypeSection[i] + tp.CacheNumInUint64() + } + + if err := m.validateStartSection(); err != nil { + return err + } + + functions, globals, memory, tables, err := m.AllDeclarations() + if err != nil { + return err + } + + if err = m.validateImports(enabledFeatures); err != nil { + return err + } + + if err = m.validateGlobals(globals, uint32(len(functions)), MaximumGlobals); err != nil { + return err + } + + if err = m.validateMemory(memory, globals, enabledFeatures); err != nil { + return err + } + + if err = m.validateExports(enabledFeatures, functions, globals, memory, tables); err != nil { + return err + } + + if m.CodeSection != nil { + if err = m.validateFunctions(enabledFeatures, functions, globals, memory, tables, MaximumFunctionIndex); err != nil { + return err + } + } // No need to validate host functions as NewHostModule validates + + if err = m.validateTable(enabledFeatures, tables, MaximumTableIndex); err != nil { + return err + } + + if err = m.validateDataCountSection(); err != nil { + return err + } + return nil +} + +func (m *Module) validateStartSection() error { + // Check the start function is valid. + // TODO: this should be verified during decode so that errors have the correct source positions + if m.StartSection != nil { + startIndex := *m.StartSection + ft := m.typeOfFunction(startIndex) + if ft == nil { // TODO: move this check to decoder so that a module can never be decoded invalidly + return fmt.Errorf("invalid start function: func[%d] has an invalid type", startIndex) + } + if len(ft.Params) > 0 || len(ft.Results) > 0 { + return fmt.Errorf("invalid start function: func[%d] must have an empty (nullary) signature: %s", startIndex, ft) + } + } + return nil +} + +func (m *Module) validateGlobals(globals []GlobalType, numFuncts, maxGlobals uint32) error { + if uint32(len(globals)) > maxGlobals { + return fmt.Errorf("too many globals in a module") + } + + // Global initialization constant expression can only reference the imported globals. + // See the note on https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#constant-expressions%E2%91%A0 + importedGlobals := globals[:m.ImportGlobalCount] + for i := range m.GlobalSection { + g := &m.GlobalSection[i] + if err := validateConstExpression(importedGlobals, numFuncts, &g.Init, g.Type.ValType); err != nil { + return err + } + } + return nil +} + +func (m *Module) validateFunctions(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table, maximumFunctionIndex uint32) error { + if uint32(len(functions)) > maximumFunctionIndex { + return fmt.Errorf("too many functions (%d) in a module", len(functions)) + } + + functionCount := m.SectionElementCount(SectionIDFunction) + codeCount := m.SectionElementCount(SectionIDCode) + if functionCount == 0 && codeCount == 0 { + return nil + } + + typeCount := m.SectionElementCount(SectionIDType) + if codeCount != functionCount { + return fmt.Errorf("code count (%d) != function count (%d)", codeCount, functionCount) + } + + declaredFuncIndexes, err := m.declaredFunctionIndexes() + if err != nil { + return err + } + + // Create bytes.Reader once as it causes allocation, and + // we frequently need it (e.g. on every If instruction). + br := bytes.NewReader(nil) + // Also, we reuse the stacks across multiple function validations to reduce allocations. + vs := &stacks{} + for idx, typeIndex := range m.FunctionSection { + if typeIndex >= typeCount { + return fmt.Errorf("invalid %s: type section index %d out of range", m.funcDesc(SectionIDFunction, Index(idx)), typeIndex) + } + c := &m.CodeSection[idx] + if c.GoFunc != nil { + continue + } + if err = m.validateFunction(vs, enabledFeatures, Index(idx), functions, globals, memory, tables, declaredFuncIndexes, br); err != nil { + return fmt.Errorf("invalid %s: %w", m.funcDesc(SectionIDFunction, Index(idx)), err) + } + } + return nil +} + +// declaredFunctionIndexes returns a set of function indexes that can be used as an immediate for OpcodeRefFunc instruction. +// +// The criteria for which function indexes can be available for that instruction is vague in the spec: +// +// - "References: the list of function indices that occur in the module outside functions and can hence be used to form references inside them." +// - https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/conventions.html#contexts +// - "Ref is the set funcidx(module with functions=ε, start=ε) , i.e., the set of function indices occurring in the module, except in its functions or start function." +// - https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/modules.html#valid-module +// +// To clarify, we reverse-engineer logic required to pass the WebAssembly Core specification 2.0 test suite: +// https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/ref_func.wast#L78-L115 +// +// To summarize, the function indexes OpcodeRefFunc can refer include: +// - existing in an element section regardless of its mode (active, passive, declarative). +// - defined as globals whose value type is ValueRefFunc. +// - used as an exported function. +// +// See https://github.com/WebAssembly/reference-types/issues/31 +// See https://github.com/WebAssembly/reference-types/issues/76 +func (m *Module) declaredFunctionIndexes() (ret map[Index]struct{}, err error) { + ret = map[uint32]struct{}{} + + for i := range m.ExportSection { + exp := &m.ExportSection[i] + if exp.Type == ExternTypeFunc { + ret[exp.Index] = struct{}{} + } + } + + for i := range m.GlobalSection { + g := &m.GlobalSection[i] + if g.Init.Opcode == OpcodeRefFunc { + var index uint32 + index, _, err = leb128.LoadUint32(g.Init.Data) + if err != nil { + err = fmt.Errorf("%s[%d] failed to initialize: %w", SectionIDName(SectionIDGlobal), i, err) + return + } + ret[index] = struct{}{} + } + } + + for i := range m.ElementSection { + elem := &m.ElementSection[i] + for _, index := range elem.Init { + if index != ElementInitNullReference { + ret[index] = struct{}{} + } + } + } + return +} + +func (m *Module) funcDesc(sectionID SectionID, sectionIndex Index) string { + // Try to improve the error message by collecting any exports: + var exportNames []string + funcIdx := sectionIndex + m.ImportFunctionCount + for i := range m.ExportSection { + exp := &m.ExportSection[i] + if exp.Index == funcIdx && exp.Type == ExternTypeFunc { + exportNames = append(exportNames, fmt.Sprintf("%q", exp.Name)) + } + } + sectionIDName := SectionIDName(sectionID) + if exportNames == nil { + return fmt.Sprintf("%s[%d]", sectionIDName, sectionIndex) + } + sort.Strings(exportNames) // go map keys do not iterate consistently + return fmt.Sprintf("%s[%d] export[%s]", sectionIDName, sectionIndex, strings.Join(exportNames, ",")) +} + +func (m *Module) validateMemory(memory *Memory, globals []GlobalType, _ api.CoreFeatures) error { + var activeElementCount int + for i := range m.DataSection { + d := &m.DataSection[i] + if !d.IsPassive() { + activeElementCount++ + } + } + if activeElementCount > 0 && memory == nil { + return fmt.Errorf("unknown memory") + } + + // Constant expression can only reference imported globals. + // https://github.com/WebAssembly/spec/blob/5900d839f38641989a9d8df2df4aee0513365d39/test/core/data.wast#L84-L91 + importedGlobals := globals[:m.ImportGlobalCount] + for i := range m.DataSection { + d := &m.DataSection[i] + if !d.IsPassive() { + if err := validateConstExpression(importedGlobals, 0, &d.OffsetExpression, ValueTypeI32); err != nil { + return fmt.Errorf("calculate offset: %w", err) + } + } + } + return nil +} + +func (m *Module) validateImports(enabledFeatures api.CoreFeatures) error { + for i := range m.ImportSection { + imp := &m.ImportSection[i] + if imp.Module == "" { + return fmt.Errorf("import[%d] has an empty module name", i) + } + switch imp.Type { + case ExternTypeFunc: + if int(imp.DescFunc) >= len(m.TypeSection) { + return fmt.Errorf("invalid import[%q.%q] function: type index out of range", imp.Module, imp.Name) + } + case ExternTypeGlobal: + if !imp.DescGlobal.Mutable { + continue + } + if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil { + return fmt.Errorf("invalid import[%q.%q] global: %w", imp.Module, imp.Name, err) + } + } + } + return nil +} + +func (m *Module) validateExports(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table) error { + for i := range m.ExportSection { + exp := &m.ExportSection[i] + index := exp.Index + switch exp.Type { + case ExternTypeFunc: + if index >= uint32(len(functions)) { + return fmt.Errorf("unknown function for export[%q]", exp.Name) + } + case ExternTypeGlobal: + if index >= uint32(len(globals)) { + return fmt.Errorf("unknown global for export[%q]", exp.Name) + } + if !globals[index].Mutable { + continue + } + if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil { + return fmt.Errorf("invalid export[%q] global[%d]: %w", exp.Name, index, err) + } + case ExternTypeMemory: + if index > 0 || memory == nil { + return fmt.Errorf("memory for export[%q] out of range", exp.Name) + } + case ExternTypeTable: + if index >= uint32(len(tables)) { + return fmt.Errorf("table for export[%q] out of range", exp.Name) + } + } + } + return nil +} + +func validateConstExpression(globals []GlobalType, numFuncs uint32, expr *ConstantExpression, expectedType ValueType) (err error) { + var actualType ValueType + switch expr.Opcode { + case OpcodeI32Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + _, _, err = leb128.LoadInt32(expr.Data) + if err != nil { + return fmt.Errorf("read i32: %w", err) + } + actualType = ValueTypeI32 + case OpcodeI64Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + _, _, err = leb128.LoadInt64(expr.Data) + if err != nil { + return fmt.Errorf("read i64: %w", err) + } + actualType = ValueTypeI64 + case OpcodeF32Const: + _, err = ieee754.DecodeFloat32(expr.Data) + if err != nil { + return fmt.Errorf("read f32: %w", err) + } + actualType = ValueTypeF32 + case OpcodeF64Const: + _, err = ieee754.DecodeFloat64(expr.Data) + if err != nil { + return fmt.Errorf("read f64: %w", err) + } + actualType = ValueTypeF64 + case OpcodeGlobalGet: + id, _, err := leb128.LoadUint32(expr.Data) + if err != nil { + return fmt.Errorf("read index of global: %w", err) + } + if uint32(len(globals)) <= id { + return fmt.Errorf("global index out of range") + } + actualType = globals[id].ValType + case OpcodeRefNull: + if len(expr.Data) == 0 { + return fmt.Errorf("read reference type for ref.null: %w", io.ErrShortBuffer) + } + reftype := expr.Data[0] + if reftype != RefTypeFuncref && reftype != RefTypeExternref { + return fmt.Errorf("invalid type for ref.null: 0x%x", reftype) + } + actualType = reftype + case OpcodeRefFunc: + index, _, err := leb128.LoadUint32(expr.Data) + if err != nil { + return fmt.Errorf("read i32: %w", err) + } else if index >= numFuncs { + return fmt.Errorf("ref.func index out of range [%d] with length %d", index, numFuncs-1) + } + actualType = ValueTypeFuncref + case OpcodeVecV128Const: + if len(expr.Data) != 16 { + return fmt.Errorf("%s needs 16 bytes but was %d bytes", OpcodeVecV128ConstName, len(expr.Data)) + } + actualType = ValueTypeV128 + default: + return fmt.Errorf("invalid opcode for const expression: 0x%x", expr.Opcode) + } + + if actualType != expectedType { + return fmt.Errorf("const expression type mismatch expected %s but got %s", + ValueTypeName(expectedType), ValueTypeName(actualType)) + } + return nil +} + +func (m *Module) validateDataCountSection() (err error) { + if m.DataCountSection != nil && int(*m.DataCountSection) != len(m.DataSection) { + err = fmt.Errorf("data count section (%d) doesn't match the length of data section (%d)", + *m.DataCountSection, len(m.DataSection)) + } + return +} + +func (m *ModuleInstance) buildGlobals(module *Module, funcRefResolver func(funcIndex Index) Reference) { + importedGlobals := m.Globals[:module.ImportGlobalCount] + + me := m.Engine + engineOwnGlobal := me.OwnsGlobals() + for i := Index(0); i < Index(len(module.GlobalSection)); i++ { + gs := &module.GlobalSection[i] + g := &GlobalInstance{} + if engineOwnGlobal { + g.Me = me + g.Index = i + module.ImportGlobalCount + } + m.Globals[i+module.ImportGlobalCount] = g + g.Type = gs.Type + g.initialize(importedGlobals, &gs.Init, funcRefResolver) + } +} + +func paramNames(localNames IndirectNameMap, funcIdx uint32, paramLen int) []string { + for i := range localNames { + nm := &localNames[i] + // Only build parameter names if we have one for each. + if nm.Index != funcIdx || len(nm.NameMap) < paramLen { + continue + } + + ret := make([]string, paramLen) + for j := range nm.NameMap { + p := &nm.NameMap[j] + if int(p.Index) < paramLen { + ret[p.Index] = p.Name + } + } + return ret + } + return nil +} + +func (m *ModuleInstance) buildMemory(module *Module, allocator experimental.MemoryAllocator) { + memSec := module.MemorySection + if memSec != nil { + m.MemoryInstance = NewMemoryInstance(memSec, allocator, m.Engine) + m.MemoryInstance.definition = &module.MemoryDefinitionSection[0] + } +} + +// Index is the offset in an index, not necessarily an absolute position in a Module section. This is because +// indexs are often preceded by a corresponding type in the Module.ImportSection. +// +// For example, the function index starts with any ExternTypeFunc in the Module.ImportSection followed by +// the Module.FunctionSection +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-index +type Index = uint32 + +// FunctionType is a possibly empty function signature. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-types%E2%91%A0 +type FunctionType struct { + // Params are the possibly empty sequence of value types accepted by a function with this signature. + Params []ValueType + + // Results are the possibly empty sequence of value types returned by a function with this signature. + // + // Note: In WebAssembly 1.0 (20191205), there can be at most one result. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#result-types%E2%91%A0 + Results []ValueType + + // string is cached as it is used both for String and key + string string + + // ParamNumInUint64 is the number of uint64 values requires to represent the Wasm param type. + ParamNumInUint64 int + + // ResultsNumInUint64 is the number of uint64 values requires to represent the Wasm result type. + ResultNumInUint64 int +} + +func (f *FunctionType) CacheNumInUint64() { + if f.ParamNumInUint64 == 0 { + for _, tp := range f.Params { + f.ParamNumInUint64++ + if tp == ValueTypeV128 { + f.ParamNumInUint64++ + } + } + } + + if f.ResultNumInUint64 == 0 { + for _, tp := range f.Results { + f.ResultNumInUint64++ + if tp == ValueTypeV128 { + f.ResultNumInUint64++ + } + } + } +} + +// EqualsSignature returns true if the function type has the same parameters and results. +func (f *FunctionType) EqualsSignature(params []ValueType, results []ValueType) bool { + return bytes.Equal(f.Params, params) && bytes.Equal(f.Results, results) +} + +// key gets or generates the key for Store.typeIDs. e.g. "i32_v" for one i32 parameter and no (void) result. +func (f *FunctionType) key() string { + if f.string != "" { + return f.string + } + var ret string + for _, b := range f.Params { + ret += ValueTypeName(b) + } + if len(f.Params) == 0 { + ret += "v_" + } else { + ret += "_" + } + for _, b := range f.Results { + ret += ValueTypeName(b) + } + if len(f.Results) == 0 { + ret += "v" + } + f.string = ret + return ret +} + +// String implements fmt.Stringer. +func (f *FunctionType) String() string { + return f.key() +} + +// Import is the binary representation of an import indicated by Type +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-import +type Import struct { + Type ExternType + // Module is the possibly empty primary namespace of this import + Module string + // Module is the possibly empty secondary namespace of this import + Name string + // DescFunc is the index in Module.TypeSection when Type equals ExternTypeFunc + DescFunc Index + // DescTable is the inlined Table when Type equals ExternTypeTable + DescTable Table + // DescMem is the inlined Memory when Type equals ExternTypeMemory + DescMem *Memory + // DescGlobal is the inlined GlobalType when Type equals ExternTypeGlobal + DescGlobal GlobalType + // IndexPerType has the index of this import per ExternType. + IndexPerType Index +} + +// Memory describes the limits of pages (64KB) in a memory. +type Memory struct { + Min, Cap, Max uint32 + // IsMaxEncoded true if the Max is encoded in the original binary. + IsMaxEncoded bool + // IsShared true if the memory is shared for access from multiple agents. + IsShared bool +} + +// Validate ensures values assigned to Min, Cap and Max are within valid thresholds. +func (m *Memory) Validate(memoryLimitPages uint32) error { + min, capacity, max := m.Min, m.Cap, m.Max + + if max > memoryLimitPages { + return fmt.Errorf("max %d pages (%s) over limit of %d pages (%s)", + max, PagesToUnitOfBytes(max), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages)) + } else if min > memoryLimitPages { + return fmt.Errorf("min %d pages (%s) over limit of %d pages (%s)", + min, PagesToUnitOfBytes(min), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages)) + } else if min > max { + return fmt.Errorf("min %d pages (%s) > max %d pages (%s)", + min, PagesToUnitOfBytes(min), max, PagesToUnitOfBytes(max)) + } else if capacity < min { + return fmt.Errorf("capacity %d pages (%s) less than minimum %d pages (%s)", + capacity, PagesToUnitOfBytes(capacity), min, PagesToUnitOfBytes(min)) + } else if capacity > memoryLimitPages { + return fmt.Errorf("capacity %d pages (%s) over limit of %d pages (%s)", + capacity, PagesToUnitOfBytes(capacity), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages)) + } + return nil +} + +type GlobalType struct { + ValType ValueType + Mutable bool +} + +type Global struct { + Type GlobalType + Init ConstantExpression +} + +type ConstantExpression struct { + Opcode Opcode + Data []byte +} + +// Export is the binary representation of an export indicated by Type +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-export +type Export struct { + Type ExternType + + // Name is what the host refers to this definition as. + Name string + + // Index is the index of the definition to export, the index is by Type + // e.g. If ExternTypeFunc, this is a position in the function index. + Index Index +} + +// Code is an entry in the Module.CodeSection containing the locals and body of the function. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-code +type Code struct { + // LocalTypes are any function-scoped variables in insertion order. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-local + LocalTypes []ValueType + + // Body is a sequence of expressions ending in OpcodeEnd + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-expr + Body []byte + + // GoFunc is non-nil when IsHostFunction and defined in go, either + // api.GoFunction or api.GoModuleFunction. When present, LocalTypes and Body must + // be nil. + // + // Note: This has no serialization format, so is not encodable. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#host-functions%E2%91%A2 + GoFunc interface{} + + // BodyOffsetInCodeSection is the offset of the beginning of the body in the code section. + // This is used for DWARF based stack trace where a program counter represents an offset in code section. + BodyOffsetInCodeSection uint64 +} + +type DataSegment struct { + OffsetExpression ConstantExpression + Init []byte + Passive bool +} + +// IsPassive returns true if this data segment is "passive" in the sense that memory offset and +// index is determined at runtime and used by OpcodeMemoryInitName instruction in the bulk memory +// operations proposal. +// +// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions +func (d *DataSegment) IsPassive() bool { + return d.Passive +} + +// NameSection represent the known custom name subsections defined in the WebAssembly Binary Format +// +// Note: This can be nil if no names were decoded for any reason including configuration. +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0 +type NameSection struct { + // ModuleName is the symbolic identifier for a module. e.g. math + // + // Note: This can be empty for any reason including configuration. + ModuleName string + + // FunctionNames is an association of a function index to its symbolic identifier. e.g. add + // + // * the key (idx) is in the function index, where module defined functions are preceded by imported ones. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#functions%E2%91%A7 + // + // For example, assuming the below text format is the second import, you would expect FunctionNames[1] = "mul" + // (import "Math" "Mul" (func $mul (param $x f32) (param $y f32) (result f32))) + // + // Note: FunctionNames are only used for debugging. At runtime, functions are called based on raw numeric index. + // Note: This can be nil for any reason including configuration. + FunctionNames NameMap + + // LocalNames contains symbolic names for function parameters or locals that have one. + // + // Note: In the Text Format, function local names can inherit parameter + // names from their type. Here are some examples: + // * (module (import (func (param $x i32) (param i32))) (func (type 0))) = [{0, {x,0}}] + // * (module (import (func (param i32) (param $y i32))) (func (type 0) (local $z i32))) = [0, [{y,1},{z,2}]] + // * (module (func (param $x i32) (local $y i32) (local $z i32))) = [{x,0},{y,1},{z,2}] + // + // Note: LocalNames are only used for debugging. At runtime, locals are called based on raw numeric index. + // Note: This can be nil for any reason including configuration. + LocalNames IndirectNameMap + + // ResultNames is a wazero-specific mechanism to store result names. + ResultNames IndirectNameMap +} + +// CustomSection contains the name and raw data of a custom section. +type CustomSection struct { + Name string + Data []byte +} + +// NameMap associates an index with any associated names. +// +// Note: Often the index bridges multiple sections. For example, the function index starts with any +// ExternTypeFunc in the Module.ImportSection followed by the Module.FunctionSection +// +// Note: NameMap is unique by NameAssoc.Index, but NameAssoc.Name needn't be unique. +// Note: When encoding in the Binary format, this must be ordered by NameAssoc.Index +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namemap +type NameMap []NameAssoc + +type NameAssoc struct { + Index Index + Name string +} + +// IndirectNameMap associates an index with an association of names. +// +// Note: IndirectNameMap is unique by NameMapAssoc.Index, but NameMapAssoc.NameMap needn't be unique. +// Note: When encoding in the Binary format, this must be ordered by NameMapAssoc.Index +// https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-indirectnamemap +type IndirectNameMap []NameMapAssoc + +type NameMapAssoc struct { + Index Index + NameMap NameMap +} + +// AllDeclarations returns all declarations for functions, globals, memories and tables in a module including imported ones. +func (m *Module) AllDeclarations() (functions []Index, globals []GlobalType, memory *Memory, tables []Table, err error) { + for i := range m.ImportSection { + imp := &m.ImportSection[i] + switch imp.Type { + case ExternTypeFunc: + functions = append(functions, imp.DescFunc) + case ExternTypeGlobal: + globals = append(globals, imp.DescGlobal) + case ExternTypeMemory: + memory = imp.DescMem + case ExternTypeTable: + tables = append(tables, imp.DescTable) + } + } + + functions = append(functions, m.FunctionSection...) + for i := range m.GlobalSection { + g := &m.GlobalSection[i] + globals = append(globals, g.Type) + } + if m.MemorySection != nil { + if memory != nil { // shouldn't be possible due to Validate + err = errors.New("at most one table allowed in module") + return + } + memory = m.MemorySection + } + if m.TableSection != nil { + tables = append(tables, m.TableSection...) + } + return +} + +// SectionID identifies the sections of a Module in the WebAssembly 1.0 (20191205) Binary Format. +// +// Note: these are defined in the wasm package, instead of the binary package, as a key per section is needed regardless +// of format, and deferring to the binary type avoids confusion. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0 +type SectionID = byte + +const ( + // SectionIDCustom includes the standard defined NameSection and possibly others not defined in the standard. + SectionIDCustom SectionID = iota // don't add anything not in https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0 + SectionIDType + SectionIDImport + SectionIDFunction + SectionIDTable + SectionIDMemory + SectionIDGlobal + SectionIDExport + SectionIDStart + SectionIDElement + SectionIDCode + SectionIDData + + // SectionIDDataCount may exist in WebAssembly 2.0 or WebAssembly 1.0 with CoreFeatureBulkMemoryOperations enabled. + // + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-count-section + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions + SectionIDDataCount +) + +// SectionIDName returns the canonical name of a module section. +// https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0 +func SectionIDName(sectionID SectionID) string { + switch sectionID { + case SectionIDCustom: + return "custom" + case SectionIDType: + return "type" + case SectionIDImport: + return "import" + case SectionIDFunction: + return "function" + case SectionIDTable: + return "table" + case SectionIDMemory: + return "memory" + case SectionIDGlobal: + return "global" + case SectionIDExport: + return "export" + case SectionIDStart: + return "start" + case SectionIDElement: + return "element" + case SectionIDCode: + return "code" + case SectionIDData: + return "data" + case SectionIDDataCount: + return "data_count" + } + return "unknown" +} + +// ValueType is an alias of api.ValueType defined to simplify imports. +type ValueType = api.ValueType + +const ( + ValueTypeI32 = api.ValueTypeI32 + ValueTypeI64 = api.ValueTypeI64 + ValueTypeF32 = api.ValueTypeF32 + ValueTypeF64 = api.ValueTypeF64 + // TODO: ValueTypeV128 is not exposed in the api pkg yet. + ValueTypeV128 ValueType = 0x7b + // TODO: ValueTypeFuncref is not exposed in the api pkg yet. + ValueTypeFuncref ValueType = 0x70 + ValueTypeExternref = api.ValueTypeExternref +) + +// ValueTypeName is an alias of api.ValueTypeName defined to simplify imports. +func ValueTypeName(t ValueType) string { + if t == ValueTypeFuncref { + return "funcref" + } else if t == ValueTypeV128 { + return "v128" + } + return api.ValueTypeName(t) +} + +func isReferenceValueType(vt ValueType) bool { + return vt == ValueTypeExternref || vt == ValueTypeFuncref +} + +// ExternType is an alias of api.ExternType defined to simplify imports. +type ExternType = api.ExternType + +const ( + ExternTypeFunc = api.ExternTypeFunc + ExternTypeFuncName = api.ExternTypeFuncName + ExternTypeTable = api.ExternTypeTable + ExternTypeTableName = api.ExternTypeTableName + ExternTypeMemory = api.ExternTypeMemory + ExternTypeMemoryName = api.ExternTypeMemoryName + ExternTypeGlobal = api.ExternTypeGlobal + ExternTypeGlobalName = api.ExternTypeGlobalName +) + +// ExternTypeName is an alias of api.ExternTypeName defined to simplify imports. +func ExternTypeName(t ValueType) string { + return api.ExternTypeName(t) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go new file mode 100644 index 00000000..20c733e6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go @@ -0,0 +1,251 @@ +package wasm + +import ( + "context" + "errors" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/sys" +) + +// FailIfClosed returns a sys.ExitError if CloseWithExitCode was called. +func (m *ModuleInstance) FailIfClosed() (err error) { + if closed := m.Closed.Load(); closed != 0 { + switch closed & exitCodeFlagMask { + case exitCodeFlagResourceClosed: + case exitCodeFlagResourceNotClosed: + // This happens when this module is closed asynchronously in CloseModuleOnCanceledOrTimeout, + // and the closure of resources have been deferred here. + _ = m.ensureResourcesClosed(context.Background()) + } + return sys.NewExitError(uint32(closed >> 32)) // Unpack the high order bits as the exit code. + } + return nil +} + +// CloseModuleOnCanceledOrTimeout take a context `ctx`, which might be a Cancel or Timeout context, +// and spawns the Goroutine to check the context is canceled ot deadline exceeded. If it reaches +// one of the conditions, it sets the appropriate exit code. +// +// Callers of this function must invoke the returned context.CancelFunc to release the spawned Goroutine. +func (m *ModuleInstance) CloseModuleOnCanceledOrTimeout(ctx context.Context) context.CancelFunc { + // Creating an empty channel in this case is a bit more efficient than + // creating a context.Context and canceling it with the same effect. We + // really just need to be notified when to stop listening to the users + // context. Closing the channel will unblock the select in the goroutine + // causing it to return an stop listening to ctx.Done(). + cancelChan := make(chan struct{}) + go m.closeModuleOnCanceledOrTimeout(ctx, cancelChan) + return func() { close(cancelChan) } +} + +// closeModuleOnCanceledOrTimeout is extracted from CloseModuleOnCanceledOrTimeout for testing. +func (m *ModuleInstance) closeModuleOnCanceledOrTimeout(ctx context.Context, cancelChan <-chan struct{}) { + select { + case <-ctx.Done(): + select { + case <-cancelChan: + // In some cases by the time this goroutine is scheduled, the caller + // has already closed both the context and the cancelChan. In this + // case go will randomize which branch of the outer select to enter + // and we don't want to close the module. + default: + // This is the same logic as CloseWithCtxErr except this calls closeWithExitCodeWithoutClosingResource + // so that we can defer the resource closure in FailIfClosed. + switch { + case errors.Is(ctx.Err(), context.Canceled): + // TODO: figure out how to report error here. + _ = m.closeWithExitCodeWithoutClosingResource(sys.ExitCodeContextCanceled) + case errors.Is(ctx.Err(), context.DeadlineExceeded): + // TODO: figure out how to report error here. + _ = m.closeWithExitCodeWithoutClosingResource(sys.ExitCodeDeadlineExceeded) + } + } + case <-cancelChan: + } +} + +// CloseWithCtxErr closes the module with an exit code based on the type of +// error reported by the context. +// +// If the context's error is unknown or nil, the module does not close. +func (m *ModuleInstance) CloseWithCtxErr(ctx context.Context) { + switch { + case errors.Is(ctx.Err(), context.Canceled): + // TODO: figure out how to report error here. + _ = m.CloseWithExitCode(ctx, sys.ExitCodeContextCanceled) + case errors.Is(ctx.Err(), context.DeadlineExceeded): + // TODO: figure out how to report error here. + _ = m.CloseWithExitCode(ctx, sys.ExitCodeDeadlineExceeded) + } +} + +// Name implements the same method as documented on api.Module +func (m *ModuleInstance) Name() string { + return m.ModuleName +} + +// String implements the same method as documented on api.Module +func (m *ModuleInstance) String() string { + return fmt.Sprintf("Module[%s]", m.Name()) +} + +// Close implements the same method as documented on api.Module. +func (m *ModuleInstance) Close(ctx context.Context) (err error) { + return m.CloseWithExitCode(ctx, 0) +} + +// CloseWithExitCode implements the same method as documented on api.Module. +func (m *ModuleInstance) CloseWithExitCode(ctx context.Context, exitCode uint32) (err error) { + if !m.setExitCode(exitCode, exitCodeFlagResourceClosed) { + return nil // not an error to have already closed + } + _ = m.s.deleteModule(m) + return m.ensureResourcesClosed(ctx) +} + +// IsClosed implements the same method as documented on api.Module. +func (m *ModuleInstance) IsClosed() bool { + return m.Closed.Load() != 0 +} + +func (m *ModuleInstance) closeWithExitCodeWithoutClosingResource(exitCode uint32) (err error) { + if !m.setExitCode(exitCode, exitCodeFlagResourceNotClosed) { + return nil // not an error to have already closed + } + _ = m.s.deleteModule(m) + return nil +} + +// closeWithExitCode is the same as CloseWithExitCode besides this doesn't delete it from Store.moduleList. +func (m *ModuleInstance) closeWithExitCode(ctx context.Context, exitCode uint32) (err error) { + if !m.setExitCode(exitCode, exitCodeFlagResourceClosed) { + return nil // not an error to have already closed + } + return m.ensureResourcesClosed(ctx) +} + +type exitCodeFlag = uint64 + +const exitCodeFlagMask = 0xff + +const ( + // exitCodeFlagResourceClosed indicates that the module was closed and resources were already closed. + exitCodeFlagResourceClosed = 1 << iota + // exitCodeFlagResourceNotClosed indicates that the module was closed while resources are not closed yet. + exitCodeFlagResourceNotClosed +) + +func (m *ModuleInstance) setExitCode(exitCode uint32, flag exitCodeFlag) bool { + closed := flag | uint64(exitCode)<<32 // Store exitCode as high-order bits. + return m.Closed.CompareAndSwap(0, closed) +} + +// ensureResourcesClosed ensures that resources assigned to ModuleInstance is released. +// Only one call will happen per module, due to external atomic guards on Closed. +func (m *ModuleInstance) ensureResourcesClosed(ctx context.Context) (err error) { + if closeNotifier := m.CloseNotifier; closeNotifier != nil { // experimental + closeNotifier.CloseNotify(ctx, uint32(m.Closed.Load()>>32)) + m.CloseNotifier = nil + } + + if sysCtx := m.Sys; sysCtx != nil { // nil if from HostModuleBuilder + err = sysCtx.FS().Close() + m.Sys = nil + } + + if mem := m.MemoryInstance; mem != nil { + if mem.expBuffer != nil { + mem.expBuffer.Free() + mem.expBuffer = nil + } + } + + if m.CodeCloser != nil { + if e := m.CodeCloser.Close(ctx); err == nil { + err = e + } + m.CodeCloser = nil + } + return err +} + +// Memory implements the same method as documented on api.Module. +func (m *ModuleInstance) Memory() api.Memory { + return m.MemoryInstance +} + +// ExportedMemory implements the same method as documented on api.Module. +func (m *ModuleInstance) ExportedMemory(name string) api.Memory { + _, err := m.getExport(name, ExternTypeMemory) + if err != nil { + return nil + } + // We Assume that we have at most one memory. + return m.MemoryInstance +} + +// ExportedMemoryDefinitions implements the same method as documented on +// api.Module. +func (m *ModuleInstance) ExportedMemoryDefinitions() map[string]api.MemoryDefinition { + // Special case as we currently only support one memory. + if mem := m.MemoryInstance; mem != nil { + // Now, find out if it is exported + for name, exp := range m.Exports { + if exp.Type == ExternTypeMemory { + return map[string]api.MemoryDefinition{name: mem.definition} + } + } + } + return map[string]api.MemoryDefinition{} +} + +// ExportedFunction implements the same method as documented on api.Module. +func (m *ModuleInstance) ExportedFunction(name string) api.Function { + exp, err := m.getExport(name, ExternTypeFunc) + if err != nil { + return nil + } + return m.Engine.NewFunction(exp.Index) +} + +// ExportedFunctionDefinitions implements the same method as documented on +// api.Module. +func (m *ModuleInstance) ExportedFunctionDefinitions() map[string]api.FunctionDefinition { + result := map[string]api.FunctionDefinition{} + for name, exp := range m.Exports { + if exp.Type == ExternTypeFunc { + result[name] = m.Source.FunctionDefinition(exp.Index) + } + } + return result +} + +// GlobalVal is an internal hack to get the lower 64 bits of a global. +func (m *ModuleInstance) GlobalVal(idx Index) uint64 { + return m.Globals[idx].Val +} + +// ExportedGlobal implements the same method as documented on api.Module. +func (m *ModuleInstance) ExportedGlobal(name string) api.Global { + exp, err := m.getExport(name, ExternTypeGlobal) + if err != nil { + return nil + } + g := m.Globals[exp.Index] + if g.Type.Mutable { + return mutableGlobal{g: g} + } + return constantGlobal{g: g} +} + +// NumGlobal implements experimental.InternalModule. +func (m *ModuleInstance) NumGlobal() int { + return len(m.Globals) +} + +// Global implements experimental.InternalModule. +func (m *ModuleInstance) Global(idx int) api.Global { + return constantGlobal{g: m.Globals[idx]} +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go new file mode 100644 index 00000000..442d26a2 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go @@ -0,0 +1,73 @@ +package wasm + +import ( + "context" + "fmt" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/internalapi" +) + +// LookupFunction looks up the table by the given index, and returns the api.Function implementation if found, +// otherwise this panics according to the same semantics as call_indirect instruction. +// Currently, this is only used by emscripten which needs to do call_indirect-like operation in the host function. +func (m *ModuleInstance) LookupFunction(t *TableInstance, typeId FunctionTypeID, tableOffset Index) api.Function { + fm, index := m.Engine.LookupFunction(t, typeId, tableOffset) + if source := fm.Source; source.IsHostModule { + // This case, the found function is a host function stored in the table. Generally, Engine.NewFunction are only + // responsible for calling Wasm-defined functions (not designed for calling Go functions!). Hence we need to wrap + // the host function as a special case. + def := &source.FunctionDefinitionSection[index] + goF := source.CodeSection[index].GoFunc + switch typed := goF.(type) { + case api.GoFunction: + // GoFunction doesn't need looked up module. + return &lookedUpGoFunction{def: def, g: goFunctionAsGoModuleFunction(typed)} + case api.GoModuleFunction: + return &lookedUpGoFunction{def: def, lookedUpModule: m, g: typed} + default: + panic(fmt.Sprintf("unexpected GoFunc type: %T", goF)) + } + } else { + return fm.Engine.NewFunction(index) + } +} + +// lookedUpGoFunction implements lookedUpGoModuleFunction. +type lookedUpGoFunction struct { + internalapi.WazeroOnly + def *FunctionDefinition + // lookedUpModule is the *ModuleInstance from which this Go function is looked up, i.e. owner of the table. + lookedUpModule *ModuleInstance + g api.GoModuleFunction +} + +// goFunctionAsGoModuleFunction converts api.GoFunction to api.GoModuleFunction which ignores the api.Module argument. +func goFunctionAsGoModuleFunction(g api.GoFunction) api.GoModuleFunction { + return api.GoModuleFunc(func(ctx context.Context, _ api.Module, stack []uint64) { + g.Call(ctx, stack) + }) +} + +// Definition implements api.Function. +func (l *lookedUpGoFunction) Definition() api.FunctionDefinition { return l.def } + +// Call implements api.Function. +func (l *lookedUpGoFunction) Call(ctx context.Context, params ...uint64) ([]uint64, error) { + typ := l.def.Functype + stackSize := typ.ParamNumInUint64 + rn := typ.ResultNumInUint64 + if rn > stackSize { + stackSize = rn + } + stack := make([]uint64, stackSize) + copy(stack, params) + return stack[:rn], l.CallWithStack(ctx, stack) +} + +// CallWithStack implements api.Function. +func (l *lookedUpGoFunction) CallWithStack(ctx context.Context, stack []uint64) error { + // The Go host function always needs to access caller's module, in this case the one holding the table. + l.g.Call(ctx, l.lookedUpModule, stack) + return nil +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go new file mode 100644 index 00000000..c7909c67 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go @@ -0,0 +1,679 @@ +package wasm + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "sync" + "sync/atomic" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/expctxkeys" + "github.com/tetratelabs/wazero/internal/internalapi" + "github.com/tetratelabs/wazero/internal/leb128" + internalsys "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/sys" +) + +// nameToModuleShrinkThreshold is the size the nameToModule map can grow to +// before it starts to be monitored for shrinking. +// The capacity will never be smaller than this once the threshold is met. +const nameToModuleShrinkThreshold = 100 + +type ( + // Store is the runtime representation of "instantiated" Wasm module and objects. + // Multiple modules can be instantiated within a single store, and each instance, + // (e.g. function instance) can be referenced by other module instances in a Store via Module.ImportSection. + // + // Every type whose name ends with "Instance" suffix belongs to exactly one store. + // + // Note that store is not thread (concurrency) safe, meaning that using single Store + // via multiple goroutines might result in race conditions. In that case, the invocation + // and access to any methods and field of Store must be guarded by mutex. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#store%E2%91%A0 + Store struct { + // moduleList ensures modules are closed in reverse initialization order. + moduleList *ModuleInstance // guarded by mux + + // nameToModule holds the instantiated Wasm modules by module name from Instantiate. + // It ensures no race conditions instantiating two modules of the same name. + nameToModule map[string]*ModuleInstance // guarded by mux + + // nameToModuleCap tracks the growth of the nameToModule map in order to + // track when to shrink it. + nameToModuleCap int // guarded by mux + + // EnabledFeatures are read-only to allow optimizations. + EnabledFeatures api.CoreFeatures + + // Engine is a global context for a Store which is in responsible for compilation and execution of Wasm modules. + Engine Engine + + // typeIDs maps each FunctionType.String() to a unique FunctionTypeID. This is used at runtime to + // do type-checks on indirect function calls. + typeIDs map[string]FunctionTypeID + + // functionMaxTypes represents the limit on the number of function types in a store. + // Note: this is fixed to 2^27 but have this a field for testability. + functionMaxTypes uint32 + + // mux is used to guard the fields from concurrent access. + mux sync.RWMutex + } + + // ModuleInstance represents instantiated wasm module. + // The difference from the spec is that in wazero, a ModuleInstance holds pointers + // to the instances, rather than "addresses" (i.e. index to Store.Functions, Globals, etc) for convenience. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-moduleinst + // + // This implements api.Module. + ModuleInstance struct { + internalapi.WazeroOnlyType + + ModuleName string + Exports map[string]*Export + Globals []*GlobalInstance + MemoryInstance *MemoryInstance + Tables []*TableInstance + + // Engine implements function calls for this module. + Engine ModuleEngine + + // TypeIDs is index-correlated with types and holds typeIDs which is uniquely assigned to a type by store. + // This is necessary to achieve fast runtime type checking for indirect function calls at runtime. + TypeIDs []FunctionTypeID + + // DataInstances holds data segments bytes of the module. + // This is only used by bulk memory operations. + // + // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#data-instances + DataInstances []DataInstance + + // ElementInstances holds the element instance, and each holds the references to either functions + // or external objects (unimplemented). + ElementInstances []ElementInstance + + // Sys is exposed for use in special imports such as WASI, assemblyscript. + // + // # Notes + // + // - This is a part of ModuleInstance so that scope and Close is coherent. + // - This is not exposed outside this repository (as a host function + // parameter) because we haven't thought through capabilities based + // security implications. + Sys *internalsys.Context + + // Closed is used both to guard moduleEngine.CloseWithExitCode and to store the exit code. + // + // The update value is closedType + exitCode << 32. This ensures an exit code of zero isn't mistaken for never closed. + // + // Note: Exclusively reading and updating this with atomics guarantees cross-goroutine observations. + // See /RATIONALE.md + Closed atomic.Uint64 + + // CodeCloser is non-nil when the code should be closed after this module. + CodeCloser api.Closer + + // s is the Store on which this module is instantiated. + s *Store + // prev and next hold the nodes in the linked list of ModuleInstance held by Store. + prev, next *ModuleInstance + // Source is a pointer to the Module from which this ModuleInstance derives. + Source *Module + + // CloseNotifier is an experimental hook called once on close. + CloseNotifier experimental.CloseNotifier + } + + // DataInstance holds bytes corresponding to the data segment in a module. + // + // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#data-instances + DataInstance = []byte + + // GlobalInstance represents a global instance in a store. + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#global-instances%E2%91%A0 + GlobalInstance struct { + Type GlobalType + // Val holds a 64-bit representation of the actual value. + // If me is non-nil, the value will not be updated and the current value is stored in the module engine. + Val uint64 + // ValHi is only used for vector type globals, and holds the higher bits of the vector. + // If me is non-nil, the value will not be updated and the current value is stored in the module engine. + ValHi uint64 + // Me is the module engine that owns this global instance. + // The .Val and .ValHi fields are only valid when me is nil. + // If me is non-nil, the value is stored in the module engine. + Me ModuleEngine + Index Index + } + + // FunctionTypeID is a uniquely assigned integer for a function type. + // This is wazero specific runtime object and specific to a store, + // and used at runtime to do type-checks on indirect function calls. + FunctionTypeID uint32 +) + +// The wazero specific limitations described at RATIONALE.md. +const maximumFunctionTypes = 1 << 27 + +// GetFunctionTypeID is used by emscripten. +func (m *ModuleInstance) GetFunctionTypeID(t *FunctionType) FunctionTypeID { + id, err := m.s.GetFunctionTypeID(t) + if err != nil { + // This is not recoverable in practice since the only error GetFunctionTypeID returns is + // when there's too many function types in the store. + panic(err) + } + return id +} + +func (m *ModuleInstance) buildElementInstances(elements []ElementSegment) { + m.ElementInstances = make([][]Reference, len(elements)) + for i, elm := range elements { + if elm.Type == RefTypeFuncref && elm.Mode == ElementModePassive { + // Only passive elements can be access as element instances. + // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/modules.html#element-segments + inits := elm.Init + inst := make([]Reference, len(inits)) + m.ElementInstances[i] = inst + for j, idx := range inits { + if index, ok := unwrapElementInitGlobalReference(idx); ok { + global := m.Globals[index] + inst[j] = Reference(global.Val) + } else { + if idx != ElementInitNullReference { + inst[j] = m.Engine.FunctionInstanceReference(idx) + } + } + } + } + } +} + +func (m *ModuleInstance) applyElements(elems []ElementSegment) { + for elemI := range elems { + elem := &elems[elemI] + if !elem.IsActive() || + // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op. + len(elem.Init) == 0 { + continue + } + var offset uint32 + if elem.OffsetExpr.Opcode == OpcodeGlobalGet { + // Ignore error as it's already validated. + globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data) + global := m.Globals[globalIdx] + offset = uint32(global.Val) + } else { + // Ignore error as it's already validated. + o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data) + offset = uint32(o) + } + + table := m.Tables[elem.TableIndex] + references := table.References + if int(offset)+len(elem.Init) > len(references) { + // ErrElementOffsetOutOfBounds is the error raised when the active element offset exceeds the table length. + // Before CoreFeatureReferenceTypes, this was checked statically before instantiation, after the proposal, + // this must be raised as runtime error (as in assert_trap in spectest), not even an instantiation error. + // https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/linking.wast#L264-L274 + // + // In wazero, we ignore it since in any way, the instantiated module and engines are fine and can be used + // for function invocations. + return + } + + if table.Type == RefTypeExternref { + for i := 0; i < len(elem.Init); i++ { + references[offset+uint32(i)] = Reference(0) + } + } else { + for i, init := range elem.Init { + if init == ElementInitNullReference { + continue + } + + var ref Reference + if index, ok := unwrapElementInitGlobalReference(init); ok { + global := m.Globals[index] + ref = Reference(global.Val) + } else { + ref = m.Engine.FunctionInstanceReference(index) + } + references[offset+uint32(i)] = ref + } + } + } +} + +// validateData ensures that data segments are valid in terms of memory boundary. +// Note: this is used only when bulk-memory/reference type feature is disabled. +func (m *ModuleInstance) validateData(data []DataSegment) (err error) { + for i := range data { + d := &data[i] + if !d.IsPassive() { + offset := int(executeConstExpressionI32(m.Globals, &d.OffsetExpression)) + ceil := offset + len(d.Init) + if offset < 0 || ceil > len(m.MemoryInstance.Buffer) { + return fmt.Errorf("%s[%d]: out of bounds memory access", SectionIDName(SectionIDData), i) + } + } + } + return +} + +// applyData uses the given data segments and mutate the memory according to the initial contents on it +// and populate the `DataInstances`. This is called after all the validation phase passes and out of +// bounds memory access error here is not a validation error, but rather a runtime error. +func (m *ModuleInstance) applyData(data []DataSegment) error { + m.DataInstances = make([][]byte, len(data)) + for i := range data { + d := &data[i] + m.DataInstances[i] = d.Init + if !d.IsPassive() { + offset := executeConstExpressionI32(m.Globals, &d.OffsetExpression) + if offset < 0 || int(offset)+len(d.Init) > len(m.MemoryInstance.Buffer) { + return fmt.Errorf("%s[%d]: out of bounds memory access", SectionIDName(SectionIDData), i) + } + copy(m.MemoryInstance.Buffer[offset:], d.Init) + } + } + return nil +} + +// GetExport returns an export of the given name and type or errs if not exported or the wrong type. +func (m *ModuleInstance) getExport(name string, et ExternType) (*Export, error) { + exp, ok := m.Exports[name] + if !ok { + return nil, fmt.Errorf("%q is not exported in module %q", name, m.ModuleName) + } + if exp.Type != et { + return nil, fmt.Errorf("export %q in module %q is a %s, not a %s", name, m.ModuleName, ExternTypeName(exp.Type), ExternTypeName(et)) + } + return exp, nil +} + +func NewStore(enabledFeatures api.CoreFeatures, engine Engine) *Store { + return &Store{ + nameToModule: map[string]*ModuleInstance{}, + nameToModuleCap: nameToModuleShrinkThreshold, + EnabledFeatures: enabledFeatures, + Engine: engine, + typeIDs: map[string]FunctionTypeID{}, + functionMaxTypes: maximumFunctionTypes, + } +} + +// Instantiate uses name instead of the Module.NameSection ModuleName as it allows instantiating the same module under +// different names safely and concurrently. +// +// * ctx: the default context used for function calls. +// * name: the name of the module. +// * sys: the system context, which will be closed (SysContext.Close) on ModuleInstance.Close. +// +// Note: Module.Validate must be called prior to instantiation. +func (s *Store) Instantiate( + ctx context.Context, + module *Module, + name string, + sys *internalsys.Context, + typeIDs []FunctionTypeID, +) (*ModuleInstance, error) { + // Instantiate the module and add it to the store so that other modules can import it. + m, err := s.instantiate(ctx, module, name, sys, typeIDs) + if err != nil { + return nil, err + } + + // Now that the instantiation is complete without error, add it. + if err = s.registerModule(m); err != nil { + _ = m.Close(ctx) + return nil, err + } + return m, nil +} + +func (s *Store) instantiate( + ctx context.Context, + module *Module, + name string, + sysCtx *internalsys.Context, + typeIDs []FunctionTypeID, +) (m *ModuleInstance, err error) { + m = &ModuleInstance{ModuleName: name, TypeIDs: typeIDs, Sys: sysCtx, s: s, Source: module} + + m.Tables = make([]*TableInstance, int(module.ImportTableCount)+len(module.TableSection)) + m.Globals = make([]*GlobalInstance, int(module.ImportGlobalCount)+len(module.GlobalSection)) + m.Engine, err = s.Engine.NewModuleEngine(module, m) + if err != nil { + return nil, err + } + + if err = m.resolveImports(ctx, module); err != nil { + return nil, err + } + + err = m.buildTables(module, + // As of reference-types proposal, boundary check must be done after instantiation. + s.EnabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes)) + if err != nil { + return nil, err + } + + allocator, _ := ctx.Value(expctxkeys.MemoryAllocatorKey{}).(experimental.MemoryAllocator) + + m.buildGlobals(module, m.Engine.FunctionInstanceReference) + m.buildMemory(module, allocator) + m.Exports = module.Exports + for _, exp := range m.Exports { + if exp.Type == ExternTypeTable { + t := m.Tables[exp.Index] + t.involvingModuleInstances = append(t.involvingModuleInstances, m) + } + } + + // As of reference types proposal, data segment validation must happen after instantiation, + // and the side effect must persist even if there's out of bounds error after instantiation. + // https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/linking.wast#L395-L405 + if !s.EnabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) { + if err = m.validateData(module.DataSection); err != nil { + return nil, err + } + } + + // After engine creation, we can create the funcref element instances and initialize funcref type globals. + m.buildElementInstances(module.ElementSection) + + // Now all the validation passes, we are safe to mutate memory instances (possibly imported ones). + if err = m.applyData(module.DataSection); err != nil { + return nil, err + } + + m.applyElements(module.ElementSection) + + m.Engine.DoneInstantiation() + + // Execute the start function. + if module.StartSection != nil { + funcIdx := *module.StartSection + ce := m.Engine.NewFunction(funcIdx) + _, err = ce.Call(ctx) + if exitErr, ok := err.(*sys.ExitError); ok { // Don't wrap an exit error! + return nil, exitErr + } else if err != nil { + return nil, fmt.Errorf("start %s failed: %w", module.funcDesc(SectionIDFunction, funcIdx), err) + } + } + return +} + +func (m *ModuleInstance) resolveImports(ctx context.Context, module *Module) (err error) { + // Check if ctx contains an ImportResolver. + resolveImport, _ := ctx.Value(expctxkeys.ImportResolverKey{}).(experimental.ImportResolver) + + for moduleName, imports := range module.ImportPerModule { + var importedModule *ModuleInstance + if resolveImport != nil { + if v := resolveImport(moduleName); v != nil { + importedModule = v.(*ModuleInstance) + } + } + if importedModule == nil { + importedModule, err = m.s.module(moduleName) + if err != nil { + return err + } + } + + for _, i := range imports { + var imported *Export + imported, err = importedModule.getExport(i.Name, i.Type) + if err != nil { + return + } + + switch i.Type { + case ExternTypeFunc: + expectedType := &module.TypeSection[i.DescFunc] + src := importedModule.Source + actual := src.typeOfFunction(imported.Index) + if !actual.EqualsSignature(expectedType.Params, expectedType.Results) { + err = errorInvalidImport(i, fmt.Errorf("signature mismatch: %s != %s", expectedType, actual)) + return + } + + m.Engine.ResolveImportedFunction(i.IndexPerType, i.DescFunc, imported.Index, importedModule.Engine) + case ExternTypeTable: + expected := i.DescTable + importedTable := importedModule.Tables[imported.Index] + if expected.Type != importedTable.Type { + err = errorInvalidImport(i, fmt.Errorf("table type mismatch: %s != %s", + RefTypeName(expected.Type), RefTypeName(importedTable.Type))) + return + } + + if expected.Min > importedTable.Min { + err = errorMinSizeMismatch(i, expected.Min, importedTable.Min) + return + } + + if expected.Max != nil { + expectedMax := *expected.Max + if importedTable.Max == nil { + err = errorNoMax(i, expectedMax) + return + } else if expectedMax < *importedTable.Max { + err = errorMaxSizeMismatch(i, expectedMax, *importedTable.Max) + return + } + } + m.Tables[i.IndexPerType] = importedTable + importedTable.involvingModuleInstancesMutex.Lock() + if len(importedTable.involvingModuleInstances) == 0 { + panic("BUG: involvingModuleInstances must not be nil when it's imported") + } + importedTable.involvingModuleInstances = append(importedTable.involvingModuleInstances, m) + importedTable.involvingModuleInstancesMutex.Unlock() + case ExternTypeMemory: + expected := i.DescMem + importedMemory := importedModule.MemoryInstance + + if expected.Min > memoryBytesNumToPages(uint64(len(importedMemory.Buffer))) { + err = errorMinSizeMismatch(i, expected.Min, importedMemory.Min) + return + } + + if expected.Max < importedMemory.Max { + err = errorMaxSizeMismatch(i, expected.Max, importedMemory.Max) + return + } + m.MemoryInstance = importedMemory + m.Engine.ResolveImportedMemory(importedModule.Engine) + case ExternTypeGlobal: + expected := i.DescGlobal + importedGlobal := importedModule.Globals[imported.Index] + + if expected.Mutable != importedGlobal.Type.Mutable { + err = errorInvalidImport(i, fmt.Errorf("mutability mismatch: %t != %t", + expected.Mutable, importedGlobal.Type.Mutable)) + return + } + + if expected.ValType != importedGlobal.Type.ValType { + err = errorInvalidImport(i, fmt.Errorf("value type mismatch: %s != %s", + ValueTypeName(expected.ValType), ValueTypeName(importedGlobal.Type.ValType))) + return + } + m.Globals[i.IndexPerType] = importedGlobal + } + } + } + return +} + +func errorMinSizeMismatch(i *Import, expected, actual uint32) error { + return errorInvalidImport(i, fmt.Errorf("minimum size mismatch: %d > %d", expected, actual)) +} + +func errorNoMax(i *Import, expected uint32) error { + return errorInvalidImport(i, fmt.Errorf("maximum size mismatch: %d, but actual has no max", expected)) +} + +func errorMaxSizeMismatch(i *Import, expected, actual uint32) error { + return errorInvalidImport(i, fmt.Errorf("maximum size mismatch: %d < %d", expected, actual)) +} + +func errorInvalidImport(i *Import, err error) error { + return fmt.Errorf("import %s[%s.%s]: %w", ExternTypeName(i.Type), i.Module, i.Name, err) +} + +// executeConstExpressionI32 executes the ConstantExpression which returns ValueTypeI32. +// The validity of the expression is ensured when calling this function as this is only called +// during instantiation phrase, and the validation happens in compilation (validateConstExpression). +func executeConstExpressionI32(importedGlobals []*GlobalInstance, expr *ConstantExpression) (ret int32) { + switch expr.Opcode { + case OpcodeI32Const: + ret, _, _ = leb128.LoadInt32(expr.Data) + case OpcodeGlobalGet: + id, _, _ := leb128.LoadUint32(expr.Data) + g := importedGlobals[id] + ret = int32(g.Val) + } + return +} + +// initialize initializes the value of this global instance given the const expr and imported globals. +// funcRefResolver is called to get the actual funcref (engine specific) from the OpcodeRefFunc const expr. +// +// Global initialization constant expression can only reference the imported globals. +// See the note on https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#constant-expressions%E2%91%A0 +func (g *GlobalInstance) initialize(importedGlobals []*GlobalInstance, expr *ConstantExpression, funcRefResolver func(funcIndex Index) Reference) { + switch expr.Opcode { + case OpcodeI32Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + v, _, _ := leb128.LoadInt32(expr.Data) + g.Val = uint64(uint32(v)) + case OpcodeI64Const: + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + v, _, _ := leb128.LoadInt64(expr.Data) + g.Val = uint64(v) + case OpcodeF32Const: + g.Val = uint64(binary.LittleEndian.Uint32(expr.Data)) + case OpcodeF64Const: + g.Val = binary.LittleEndian.Uint64(expr.Data) + case OpcodeGlobalGet: + id, _, _ := leb128.LoadUint32(expr.Data) + importedG := importedGlobals[id] + switch importedG.Type.ValType { + case ValueTypeI32: + g.Val = uint64(uint32(importedG.Val)) + case ValueTypeI64: + g.Val = importedG.Val + case ValueTypeF32: + g.Val = importedG.Val + case ValueTypeF64: + g.Val = importedG.Val + case ValueTypeV128: + g.Val, g.ValHi = importedG.Val, importedG.ValHi + case ValueTypeFuncref, ValueTypeExternref: + g.Val = importedG.Val + } + case OpcodeRefNull: + switch expr.Data[0] { + case ValueTypeExternref, ValueTypeFuncref: + g.Val = 0 // Reference types are opaque 64bit pointer at runtime. + } + case OpcodeRefFunc: + v, _, _ := leb128.LoadUint32(expr.Data) + g.Val = uint64(funcRefResolver(v)) + case OpcodeVecV128Const: + g.Val, g.ValHi = binary.LittleEndian.Uint64(expr.Data[0:8]), binary.LittleEndian.Uint64(expr.Data[8:16]) + } +} + +// String implements api.Global. +func (g *GlobalInstance) String() string { + switch g.Type.ValType { + case ValueTypeI32, ValueTypeI64: + return fmt.Sprintf("global(%d)", g.Val) + case ValueTypeF32: + return fmt.Sprintf("global(%f)", api.DecodeF32(g.Val)) + case ValueTypeF64: + return fmt.Sprintf("global(%f)", api.DecodeF64(g.Val)) + default: + panic(fmt.Errorf("BUG: unknown value type %X", g.Type.ValType)) + } +} + +func (g *GlobalInstance) Value() (uint64, uint64) { + if g.Me != nil { + return g.Me.GetGlobalValue(g.Index) + } + return g.Val, g.ValHi +} + +func (g *GlobalInstance) SetValue(lo, hi uint64) { + if g.Me != nil { + g.Me.SetGlobalValue(g.Index, lo, hi) + } else { + g.Val, g.ValHi = lo, hi + } +} + +func (s *Store) GetFunctionTypeIDs(ts []FunctionType) ([]FunctionTypeID, error) { + ret := make([]FunctionTypeID, len(ts)) + for i := range ts { + t := &ts[i] + inst, err := s.GetFunctionTypeID(t) + if err != nil { + return nil, err + } + ret[i] = inst + } + return ret, nil +} + +func (s *Store) GetFunctionTypeID(t *FunctionType) (FunctionTypeID, error) { + s.mux.RLock() + key := t.key() + id, ok := s.typeIDs[key] + s.mux.RUnlock() + if !ok { + s.mux.Lock() + defer s.mux.Unlock() + // Check again in case another goroutine has already added the type. + if id, ok = s.typeIDs[key]; ok { + return id, nil + } + l := len(s.typeIDs) + if uint32(l) >= s.functionMaxTypes { + return 0, fmt.Errorf("too many function types in a store") + } + id = FunctionTypeID(l) + s.typeIDs[key] = id + } + return id, nil +} + +// CloseWithExitCode implements the same method as documented on wazero.Runtime. +func (s *Store) CloseWithExitCode(ctx context.Context, exitCode uint32) error { + s.mux.Lock() + defer s.mux.Unlock() + // Close modules in reverse initialization order. + var errs []error + for m := s.moduleList; m != nil; m = m.next { + // If closing this module errs, proceed anyway to close the others. + if err := m.closeWithExitCode(ctx, exitCode); err != nil { + errs = append(errs, err) + } + } + s.moduleList = nil + s.nameToModule = nil + s.nameToModuleCap = 0 + s.typeIDs = nil + return errors.Join(errs...) +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go new file mode 100644 index 00000000..ede3047d --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go @@ -0,0 +1,95 @@ +package wasm + +import ( + "errors" + "fmt" +) + +// deleteModule makes the moduleName available for instantiation again. +func (s *Store) deleteModule(m *ModuleInstance) error { + s.mux.Lock() + defer s.mux.Unlock() + + // Remove this module name. + if m.prev != nil { + m.prev.next = m.next + } + if m.next != nil { + m.next.prev = m.prev + } + if s.moduleList == m { + s.moduleList = m.next + } + // Clear the m state so it does not enter any other branch + // on subsequent calls to deleteModule. + m.prev = nil + m.next = nil + + if m.ModuleName != "" { + delete(s.nameToModule, m.ModuleName) + + // Shrink the map if it's allocated more than twice the size of the list + newCap := len(s.nameToModule) + if newCap < nameToModuleShrinkThreshold { + newCap = nameToModuleShrinkThreshold + } + if newCap*2 <= s.nameToModuleCap { + nameToModule := make(map[string]*ModuleInstance, newCap) + for k, v := range s.nameToModule { + nameToModule[k] = v + } + s.nameToModule = nameToModule + s.nameToModuleCap = newCap + } + } + return nil +} + +// module returns the module of the given name or error if not in this store +func (s *Store) module(moduleName string) (*ModuleInstance, error) { + s.mux.RLock() + defer s.mux.RUnlock() + m, ok := s.nameToModule[moduleName] + if !ok { + return nil, fmt.Errorf("module[%s] not instantiated", moduleName) + } + return m, nil +} + +// registerModule registers a ModuleInstance into the store. +// This makes the ModuleInstance visible for import if it's not anonymous, and ensures it is closed when the store is. +func (s *Store) registerModule(m *ModuleInstance) error { + s.mux.Lock() + defer s.mux.Unlock() + + if s.nameToModule == nil { + return errors.New("already closed") + } + + if m.ModuleName != "" { + if _, ok := s.nameToModule[m.ModuleName]; ok { + return fmt.Errorf("module[%s] has already been instantiated", m.ModuleName) + } + s.nameToModule[m.ModuleName] = m + if len(s.nameToModule) > s.nameToModuleCap { + s.nameToModuleCap = len(s.nameToModule) + } + } + + // Add the newest node to the moduleNamesList as the head. + m.next = s.moduleList + if m.next != nil { + m.next.prev = m + } + s.moduleList = m + return nil +} + +// Module implements wazero.Runtime Module +func (s *Store) Module(moduleName string) *ModuleInstance { + m, err := s.module(moduleName) + if err != nil { + return nil + } + return m +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go new file mode 100644 index 00000000..2123693c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go @@ -0,0 +1,339 @@ +package wasm + +import ( + "fmt" + "math" + "sync" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/leb128" +) + +// Table describes the limits of elements and its type in a table. +type Table struct { + Min uint32 + Max *uint32 + Type RefType +} + +// RefType is either RefTypeFuncref or RefTypeExternref as of WebAssembly core 2.0. +type RefType = byte + +const ( + // RefTypeFuncref represents a reference to a function. + RefTypeFuncref = ValueTypeFuncref + // RefTypeExternref represents a reference to a host object, which is not currently supported in wazero. + RefTypeExternref = ValueTypeExternref +) + +func RefTypeName(t RefType) (ret string) { + switch t { + case RefTypeFuncref: + ret = "funcref" + case RefTypeExternref: + ret = "externref" + default: + ret = fmt.Sprintf("unknown(0x%x)", t) + } + return +} + +// ElementMode represents a mode of element segment which is either active, passive or declarative. +// +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/modules.html#element-segments +type ElementMode = byte + +const ( + // ElementModeActive is the mode which requires the runtime to initialize table with the contents in .Init field combined with OffsetExpr. + ElementModeActive ElementMode = iota + // ElementModePassive is the mode which doesn't require the runtime to initialize table, and only used with OpcodeTableInitName. + ElementModePassive + // ElementModeDeclarative is introduced in reference-types proposal which can be used to declare function indexes used by OpcodeRefFunc. + ElementModeDeclarative +) + +// ElementSegment are initialization instructions for a TableInstance +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-elem +type ElementSegment struct { + // OffsetExpr returns the table element offset to apply to Init indices. + // Note: This can be validated prior to instantiation unless it includes OpcodeGlobalGet (an imported global). + OffsetExpr ConstantExpression + + // TableIndex is the table's index to which this element segment is applied. + // Note: This is used if and only if the Mode is active. + TableIndex Index + + // Followings are set/used regardless of the Mode. + + // Init indices are (nullable) table elements where each index is the function index by which the module initialize the table. + Init []Index + + // Type holds the type of this element segment, which is the RefType in WebAssembly 2.0. + Type RefType + + // Mode is the mode of this element segment. + Mode ElementMode +} + +const ( + // ElementInitNullReference represents the null reference in ElementSegment's Init. + // In Wasm spec, an init item represents either Function's Index or null reference, + // and in wazero, we limit the maximum number of functions available in a module to + // MaximumFunctionIndex. Therefore, it is safe to use 1 << 31 to represent the null + // reference in Element segments. + ElementInitNullReference Index = 1 << 31 + // elementInitImportedGlobalReferenceType represents an init item which is resolved via an imported global constexpr. + // The actual function reference stored at Global is only known at instantiation-time, so we set this flag + // to items of ElementSegment.Init at binary decoding, and unwrap this flag at instantiation to resolve the value. + // + // This might collide the init element resolved via ref.func instruction which is resolved with the func index at decoding, + // but in practice, that is not allowed in wazero thanks to our limit MaximumFunctionIndex. Thus, it is safe to set this flag + // in init element to indicate as such. + elementInitImportedGlobalReferenceType Index = 1 << 30 +) + +// unwrapElementInitGlobalReference takes an item of the init vector of an ElementSegment, +// and returns the Global index if it is supposed to get generated from a global. +// ok is true if the given init item is as such. +func unwrapElementInitGlobalReference(init Index) (_ Index, ok bool) { + if init&elementInitImportedGlobalReferenceType == elementInitImportedGlobalReferenceType { + return init &^ elementInitImportedGlobalReferenceType, true + } + return init, false +} + +// WrapGlobalIndexAsElementInit wraps the given index as an init item which is resolved via an imported global value. +// See the comments on elementInitImportedGlobalReferenceType for more details. +func WrapGlobalIndexAsElementInit(init Index) Index { + return init | elementInitImportedGlobalReferenceType +} + +// IsActive returns true if the element segment is "active" mode which requires the runtime to initialize table +// with the contents in .Init field. +func (e *ElementSegment) IsActive() bool { + return e.Mode == ElementModeActive +} + +// TableInstance represents a table of (RefTypeFuncref) elements in a module. +// +// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-instances%E2%91%A0 +type TableInstance struct { + // References holds references whose type is either RefTypeFuncref or RefTypeExternref (unsupported). + // + // Currently, only function references are supported. + References []Reference + + // Min is the minimum (function) elements in this table and cannot grow to accommodate ElementSegment. + Min uint32 + + // Max if present is the maximum (function) elements in this table, or nil if unbounded. + Max *uint32 + + // Type is either RefTypeFuncref or RefTypeExternRef. + Type RefType + + // The following is only used when the table is exported. + + // involvingModuleInstances is a set of module instances which are involved in the table instance. + // This is critical for safety purpose because once a table is imported, it can hold any reference to + // any function in the owner and importing module instances. Therefore, these module instance, + // transitively the compiled modules, must be alive as long as the table instance is alive. + involvingModuleInstances []*ModuleInstance + // involvingModuleInstancesMutex is a mutex to protect involvingModuleInstances. + involvingModuleInstancesMutex sync.RWMutex +} + +// ElementInstance represents an element instance in a module. +// +// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#element-instances +type ElementInstance = []Reference + +// Reference is the runtime representation of RefType which is either RefTypeFuncref or RefTypeExternref. +type Reference = uintptr + +// validateTable ensures any ElementSegment is valid. This caches results via Module.validatedActiveElementSegments. +// Note: limitsType are validated by decoders, so not re-validated here. +func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) error { + if len(tables) > int(maximumTableIndex) { + return fmt.Errorf("too many tables in a module: %d given with limit %d", len(tables), maximumTableIndex) + } + + importedTableCount := m.ImportTableCount + + // Create bounds checks as these can err prior to instantiation + funcCount := m.ImportFunctionCount + m.SectionElementCount(SectionIDFunction) + globalsCount := m.ImportGlobalCount + m.SectionElementCount(SectionIDGlobal) + + // Now, we have to figure out which table elements can be resolved before instantiation and also fail early if there + // are any imported globals that are known to be invalid by their declarations. + for i := range m.ElementSection { + elem := &m.ElementSection[i] + idx := Index(i) + initCount := uint32(len(elem.Init)) + + // Any offset applied is to the element, not the function index: validate here if the funcidx is sound. + for ei, init := range elem.Init { + if init == ElementInitNullReference { + continue + } + index, ok := unwrapElementInitGlobalReference(init) + if ok { + if index >= globalsCount { + return fmt.Errorf("%s[%d].init[%d] global index %d out of range", SectionIDName(SectionIDElement), idx, ei, index) + } + } else { + if elem.Type == RefTypeExternref { + return fmt.Errorf("%s[%d].init[%d] must be ref.null but was %d", SectionIDName(SectionIDElement), idx, ei, init) + } + if index >= funcCount { + return fmt.Errorf("%s[%d].init[%d] func index %d out of range", SectionIDName(SectionIDElement), idx, ei, index) + } + } + } + + if elem.IsActive() { + if len(tables) <= int(elem.TableIndex) { + return fmt.Errorf("unknown table %d as active element target", elem.TableIndex) + } + + t := tables[elem.TableIndex] + if t.Type != elem.Type { + return fmt.Errorf("element type mismatch: table has %s but element has %s", + RefTypeName(t.Type), RefTypeName(elem.Type), + ) + } + + // global.get needs to be discovered during initialization + oc := elem.OffsetExpr.Opcode + if oc == OpcodeGlobalGet { + globalIdx, _, err := leb128.LoadUint32(elem.OffsetExpr.Data) + if err != nil { + return fmt.Errorf("%s[%d] couldn't read global.get parameter: %w", SectionIDName(SectionIDElement), idx, err) + } else if err = m.verifyImportGlobalI32(SectionIDElement, idx, globalIdx); err != nil { + return err + } + } else if oc == OpcodeI32Const { + // Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 we must pass if imported + // table has set its min=0. Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142, we + // have to do fail if module-defined min=0. + if !enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) && elem.TableIndex >= importedTableCount { + // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md + o, _, err := leb128.LoadInt32(elem.OffsetExpr.Data) + if err != nil { + return fmt.Errorf("%s[%d] couldn't read i32.const parameter: %w", SectionIDName(SectionIDElement), idx, err) + } + offset := Index(o) + if err = checkSegmentBounds(t.Min, uint64(initCount)+uint64(offset), idx); err != nil { + return err + } + } + } else { + return fmt.Errorf("%s[%d] has an invalid const expression: %s", SectionIDName(SectionIDElement), idx, InstructionName(oc)) + } + } + } + return nil +} + +// buildTable returns TableInstances if the module defines or imports a table. +// - importedTables: returned as `tables` unmodified. +// - importedGlobals: include all instantiated, imported globals. +// +// If the result `init` is non-nil, it is the `tableInit` parameter of Engine.NewModuleEngine. +// +// Note: An error is only possible when an ElementSegment.OffsetExpr is out of range of the TableInstance.Min. +func (m *ModuleInstance) buildTables(module *Module, skipBoundCheck bool) (err error) { + idx := module.ImportTableCount + for i := range module.TableSection { + tsec := &module.TableSection[i] + // The module defining the table is the one that sets its Min/Max etc. + m.Tables[idx] = &TableInstance{ + References: make([]Reference, tsec.Min), Min: tsec.Min, Max: tsec.Max, + Type: tsec.Type, + } + idx++ + } + + if !skipBoundCheck { + for elemI := range module.ElementSection { // Do not loop over the value since elementSegments is a slice of value. + elem := &module.ElementSection[elemI] + table := m.Tables[elem.TableIndex] + var offset uint32 + if elem.OffsetExpr.Opcode == OpcodeGlobalGet { + // Ignore error as it's already validated. + globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data) + global := m.Globals[globalIdx] + offset = uint32(global.Val) + } else { // i32.const + // Ignore error as it's already validated. + o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data) + offset = uint32(o) + } + + // Check to see if we are out-of-bounds + initCount := uint64(len(elem.Init)) + if err = checkSegmentBounds(table.Min, uint64(offset)+initCount, Index(elemI)); err != nil { + return + } + } + } + return +} + +// checkSegmentBounds fails if the capacity needed for an ElementSegment.Init is larger than limitsType.Min +// +// WebAssembly 1.0 (20191205) doesn't forbid growing to accommodate element segments, and spectests are inconsistent. +// For example, the spectests enforce elements within Table limitsType.Min, but ignore Import.DescTable min. What this +// means is we have to delay offset checks on imported tables until we link to them. +// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 wants pass on min=0 for import +// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142 wants fail on min=0 module-defined +func checkSegmentBounds(min uint32, requireMin uint64, idx Index) error { // uint64 in case offset was set to -1 + if requireMin > uint64(min) { + return fmt.Errorf("%s[%d].init exceeds min table size", SectionIDName(SectionIDElement), idx) + } + return nil +} + +func (m *Module) verifyImportGlobalI32(sectionID SectionID, sectionIdx Index, idx uint32) error { + ig := uint32(math.MaxUint32) // +1 == 0 + for i := range m.ImportSection { + imp := &m.ImportSection[i] + if imp.Type == ExternTypeGlobal { + ig++ + if ig == idx { + if imp.DescGlobal.ValType != ValueTypeI32 { + return fmt.Errorf("%s[%d] (global.get %d): import[%d].global.ValType != i32", SectionIDName(sectionID), sectionIdx, idx, i) + } + return nil + } + } + } + return fmt.Errorf("%s[%d] (global.get %d): out of range of imported globals", SectionIDName(sectionID), sectionIdx, idx) +} + +// Grow appends the `initialRef` by `delta` times into the References slice. +// Returns -1 if the operation is not valid, otherwise the old length of the table. +// +// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/instructions.html#xref-syntax-instructions-syntax-instr-table-mathsf-table-grow-x +func (t *TableInstance) Grow(delta uint32, initialRef Reference) (currentLen uint32) { + currentLen = uint32(len(t.References)) + if delta == 0 { + return + } + + if newLen := int64(currentLen) + int64(delta); // adding as 64bit ints to avoid overflow. + newLen >= math.MaxUint32 || (t.Max != nil && newLen > int64(*t.Max)) { + return 0xffffffff // = -1 in signed 32-bit integer. + } + t.References = append(t.References, make([]uintptr, delta)...) + + // Uses the copy trick for faster filling the new region with the initial value. + // https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d + newRegion := t.References[currentLen:] + newRegion[0] = initialRef + for i := 1; i < len(newRegion); i *= 2 { + copy(newRegion[i:], newRegion[:i]) + } + return +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/debug.go b/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/debug.go new file mode 100644 index 00000000..ff0e0ccc --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/debug.go @@ -0,0 +1,170 @@ +// Package wasmdebug contains utilities used to give consistent search keys between stack traces and error messages. +// Note: This is named wasmdebug to avoid conflicts with the normal go module. +// Note: This only imports "api" as importing "wasm" would create a cyclic dependency. +package wasmdebug + +import ( + "fmt" + "runtime" + "runtime/debug" + "strconv" + "strings" + + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasmruntime" + "github.com/tetratelabs/wazero/sys" +) + +// FuncName returns the naming convention of "moduleName.funcName". +// +// - moduleName is the possibly empty name the module was instantiated with. +// - funcName is the name in the Custom Name section. +// - funcIdx is the position in the function index, prefixed with +// imported functions. +// +// Note: "moduleName.$funcIdx" is used when the funcName is empty, as commonly +// the case in TinyGo. +func FuncName(moduleName, funcName string, funcIdx uint32) string { + var ret strings.Builder + + // Start module.function + ret.WriteString(moduleName) + ret.WriteByte('.') + if funcName == "" { + ret.WriteByte('$') + ret.WriteString(strconv.Itoa(int(funcIdx))) + } else { + ret.WriteString(funcName) + } + + return ret.String() +} + +// signature returns a formatted signature similar to how it is defined in Go. +// +// * paramTypes should be from wasm.FunctionType +// * resultTypes should be from wasm.FunctionType +// TODO: add paramNames +func signature(funcName string, paramTypes []api.ValueType, resultTypes []api.ValueType) string { + var ret strings.Builder + ret.WriteString(funcName) + + // Start params + ret.WriteByte('(') + paramCount := len(paramTypes) + switch paramCount { + case 0: + case 1: + ret.WriteString(api.ValueTypeName(paramTypes[0])) + default: + ret.WriteString(api.ValueTypeName(paramTypes[0])) + for _, vt := range paramTypes[1:] { + ret.WriteByte(',') + ret.WriteString(api.ValueTypeName(vt)) + } + } + ret.WriteByte(')') + + // Start results + resultCount := len(resultTypes) + switch resultCount { + case 0: + case 1: + ret.WriteByte(' ') + ret.WriteString(api.ValueTypeName(resultTypes[0])) + default: // As this is used for errors, don't panic if there are multiple returns, even if that's invalid! + ret.WriteByte(' ') + ret.WriteByte('(') + ret.WriteString(api.ValueTypeName(resultTypes[0])) + for _, vt := range resultTypes[1:] { + ret.WriteByte(',') + ret.WriteString(api.ValueTypeName(vt)) + } + ret.WriteByte(')') + } + + return ret.String() +} + +// ErrorBuilder helps build consistent errors, particularly adding a WASM stack trace. +// +// AddFrame should be called beginning at the frame that panicked until no more frames exist. Once done, call Format. +type ErrorBuilder interface { + // AddFrame adds the next frame. + // + // * funcName should be from FuncName + // * paramTypes should be from wasm.FunctionType + // * resultTypes should be from wasm.FunctionType + // * sources is the source code information for this frame and can be empty. + // + // Note: paramTypes and resultTypes are present because signature misunderstanding, mismatch or overflow are common. + AddFrame(funcName string, paramTypes, resultTypes []api.ValueType, sources []string) + + // FromRecovered returns an error with the wasm stack trace appended to it. + FromRecovered(recovered interface{}) error +} + +func NewErrorBuilder() ErrorBuilder { + return &stackTrace{} +} + +type stackTrace struct { + // frameCount is the number of stack frame currently pushed into lines. + frameCount int + // lines contains the stack trace and possibly the inlined source code information. + lines []string +} + +// GoRuntimeErrorTracePrefix is the prefix coming before the Go runtime stack trace included in the face of runtime.Error. +// This is exported for testing purpose. +const GoRuntimeErrorTracePrefix = "Go runtime stack trace:" + +func (s *stackTrace) FromRecovered(recovered interface{}) error { + if false { + debug.PrintStack() + } + + if exitErr, ok := recovered.(*sys.ExitError); ok { // Don't wrap an exit error! + return exitErr + } + + stack := strings.Join(s.lines, "\n\t") + + // If the error was internal, don't mention it was recovered. + if wasmErr, ok := recovered.(*wasmruntime.Error); ok { + return fmt.Errorf("wasm error: %w\nwasm stack trace:\n\t%s", wasmErr, stack) + } + + // If we have a runtime.Error, something severe happened which should include the stack trace. This could be + // a nil pointer from wazero or a user-defined function from HostModuleBuilder. + if runtimeErr, ok := recovered.(runtime.Error); ok { + return fmt.Errorf("%w (recovered by wazero)\nwasm stack trace:\n\t%s\n\n%s\n%s", + runtimeErr, stack, GoRuntimeErrorTracePrefix, debug.Stack()) + } + + // At this point we expect the error was from a function defined by HostModuleBuilder that intentionally called panic. + if runtimeErr, ok := recovered.(error); ok { // e.g. panic(errors.New("whoops")) + return fmt.Errorf("%w (recovered by wazero)\nwasm stack trace:\n\t%s", runtimeErr, stack) + } else { // e.g. panic("whoops") + return fmt.Errorf("%v (recovered by wazero)\nwasm stack trace:\n\t%s", recovered, stack) + } +} + +// MaxFrames is the maximum number of frames to include in the stack trace. +const MaxFrames = 30 + +// AddFrame implements ErrorBuilder.AddFrame +func (s *stackTrace) AddFrame(funcName string, paramTypes, resultTypes []api.ValueType, sources []string) { + if s.frameCount == MaxFrames { + return + } + s.frameCount++ + sig := signature(funcName, paramTypes, resultTypes) + s.lines = append(s.lines, sig) + for _, source := range sources { + s.lines = append(s.lines, "\t"+source) + } + if s.frameCount == MaxFrames { + s.lines = append(s.lines, "... maybe followed by omitted frames") + } +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/dwarf.go b/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/dwarf.go new file mode 100644 index 00000000..50ba7b2b --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasmdebug/dwarf.go @@ -0,0 +1,225 @@ +package wasmdebug + +import ( + "debug/dwarf" + "errors" + "fmt" + "io" + "sort" + "strings" + "sync" +) + +// DWARFLines is used to retrieve source code line information from the DWARF data. +type DWARFLines struct { + // d is created by DWARF custom sections. + d *dwarf.Data + // linesPerEntry maps dwarf.Offset for dwarf.Entry to the list of lines contained by the entry. + // The value is sorted in the increasing order by the address. + linesPerEntry map[dwarf.Offset][]line + mux sync.Mutex +} + +type line struct { + addr uint64 + pos dwarf.LineReaderPos +} + +// NewDWARFLines returns DWARFLines for the given *dwarf.Data. +func NewDWARFLines(d *dwarf.Data) *DWARFLines { + if d == nil { + return nil + } + return &DWARFLines{d: d, linesPerEntry: map[dwarf.Offset][]line{}} +} + +// isTombstoneAddr returns true if the given address is invalid a.k.a tombstone address which was made no longer valid +// by linker. According to the DWARF spec[1], the value is encoded as 0xffffffff for Wasm (as 32-bit target), +// but some tools encode it either in -1, -2 [2] or 1<<32 (This might not be by tools, but by debug/dwarf package's bug). +// +// [1] https://dwarfstd.org/issues/200609.1.html +// [2] https://github.com/WebAssembly/binaryen/blob/97178d08d4a20d2a5e3a6be813fc6a7079ef86e1/src/wasm/wasm-debug.cpp#L651-L660 +// [3] https://reviews.llvm.org/D81784 +func isTombstoneAddr(addr uint64) bool { + addr32 := int32(addr) + return addr32 == -1 || addr32 == -2 || + addr32 == 0 // This covers 1 <<32. +} + +// Line returns the line information for the given instructionOffset which is an offset in +// the code section of the original Wasm binary. Returns empty string if the info is not found. +func (d *DWARFLines) Line(instructionOffset uint64) (ret []string) { + if d == nil { + return + } + + // DWARFLines is created per Wasm binary, so there's a possibility that multiple instances + // created from a same binary face runtime error at the same time, and that results in + // concurrent access to this function. + d.mux.Lock() + defer d.mux.Unlock() + + r := d.d.Reader() + + var inlinedRoutines []*dwarf.Entry + var cu *dwarf.Entry + var inlinedDone bool +entry: + for { + ent, err := r.Next() + if err != nil || ent == nil { + break + } + + // If we already found the compilation unit and relevant inlined routines, we can stop searching entries. + if cu != nil && inlinedDone { + break + } + + switch ent.Tag { + case dwarf.TagCompileUnit, dwarf.TagInlinedSubroutine: + default: + // Only CompileUnit and InlinedSubroutines are relevant. + continue + } + + // Check if the entry spans the range which contains the target instruction. + ranges, err := d.d.Ranges(ent) + if err != nil { + continue + } + for _, pcs := range ranges { + start, end := pcs[0], pcs[1] + if isTombstoneAddr(start) || isTombstoneAddr(end) { + continue + } + if start <= instructionOffset && instructionOffset < end { + switch ent.Tag { + case dwarf.TagCompileUnit: + cu = ent + case dwarf.TagInlinedSubroutine: + inlinedRoutines = append(inlinedRoutines, ent) + // Search inlined subroutines until all the children. + inlinedDone = !ent.Children + // Not that "children" in the DWARF spec is defined as the next entry to this entry. + // See "2.3 Relationship of Debugging Information Entries" in https://dwarfstd.org/doc/DWARF4.pdf + } + continue entry + } + } + } + + // If the relevant compilation unit is not found, nothing we can do with this DWARF info. + if cu == nil { + return + } + + lineReader, err := d.d.LineReader(cu) + if err != nil || lineReader == nil { + return + } + var lines []line + var ok bool + var le dwarf.LineEntry + // Get the lines inside the entry. + if lines, ok = d.linesPerEntry[cu.Offset]; !ok { + // If not found, we create the list of lines by reading all the LineEntries in the Entry. + // + // Note that the dwarf.LineEntry.SeekPC API shouldn't be used because the Go's dwarf package assumes that + // all the line entries in an Entry are sorted in increasing order which *might not* be true + // for some languages. Such order requirement is not a part of DWARF specification, + // and in fact Zig language tends to emit interleaved line information. + // + // Thus, here we read all line entries here, and sort them in the increasing order wrt addresses. + for { + pos := lineReader.Tell() + err = lineReader.Next(&le) + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return + } + // TODO: Maybe we should ignore tombstone addresses by using isTombstoneAddr, + // but not sure if that would be an issue in practice. + lines = append(lines, line{addr: le.Address, pos: pos}) + } + sort.Slice(lines, func(i, j int) bool { return lines[i].addr < lines[j].addr }) + d.linesPerEntry[cu.Offset] = lines // Caches for the future inquiries for the same Entry. + } + + // Now we have the lines for this entry. We can find the corresponding source line for instructionOffset + // via binary search on the list. + n := len(lines) + index := sort.Search(n, func(i int) bool { return lines[i].addr >= instructionOffset }) + + if index == n { // This case the address is not found. See the doc sort.Search. + return + } + + ln := lines[index] + if ln.addr != instructionOffset { + // If the address doesn't match exactly, the previous entry is the one that contains the instruction. + // That can happen anytime as the DWARF spec allows it, and other tools can handle it in this way conventionally + // https://github.com/gimli-rs/addr2line/blob/3a2dbaf84551a06a429f26e9c96071bb409b371f/src/lib.rs#L236-L242 + // https://github.com/kateinoigakukun/wasminspect/blob/f29f052f1b03104da9f702508ac0c1bbc3530ae4/crates/debugger/src/dwarf/mod.rs#L453-L459 + if index-1 < 0 { + return + } + ln = lines[index-1] + } + + // Advance the line reader for the found position. + lineReader.Seek(ln.pos) + err = lineReader.Next(&le) + if err != nil { + // If we reach this block, that means there's a bug in the []line creation logic above. + panic("BUG: stored dwarf.LineReaderPos is invalid") + } + + // In the inlined case, the line info is the innermost inlined function call. + inlined := len(inlinedRoutines) != 0 + prefix := fmt.Sprintf("%#x: ", instructionOffset) + ret = append(ret, formatLine(prefix, le.File.Name, int64(le.Line), int64(le.Column), inlined)) + + if inlined { + prefix = strings.Repeat(" ", len(prefix)) + files := lineReader.Files() + // inlinedRoutines contain the inlined call information in the reverse order (children is higher than parent), + // so we traverse the reverse order and emit the inlined calls. + for i := len(inlinedRoutines) - 1; i >= 0; i-- { + inlined := inlinedRoutines[i] + fileIndex, ok := inlined.Val(dwarf.AttrCallFile).(int64) + if !ok { + return + } else if fileIndex >= int64(len(files)) { + // This in theory shouldn't happen according to the spec, but guard against ill-formed DWARF info. + return + } + fileName := files[fileIndex] + line, _ := inlined.Val(dwarf.AttrCallLine).(int64) + col, _ := inlined.Val(dwarf.AttrCallColumn).(int64) + ret = append(ret, formatLine(prefix, fileName.Name, line, col, + // Last one is the origin of the inlined function calls. + i != 0)) + } + } + return +} + +func formatLine(prefix, fileName string, line, col int64, inlined bool) string { + builder := strings.Builder{} + builder.WriteString(prefix) + builder.WriteString(fileName) + + if line != 0 { + builder.WriteString(fmt.Sprintf(":%d", line)) + if col != 0 { + builder.WriteString(fmt.Sprintf(":%d", col)) + } + } + + if inlined { + builder.WriteString(" (inlined)") + } + return builder.String() +} diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasmruntime/errors.go b/vendor/github.com/tetratelabs/wazero/internal/wasmruntime/errors.go new file mode 100644 index 00000000..556e5de8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/internal/wasmruntime/errors.go @@ -0,0 +1,50 @@ +// Package wasmruntime contains internal symbols shared between modules for error handling. +// Note: This is named wasmruntime to avoid conflicts with the normal go module. +// Note: This only imports "api" as importing "wasm" would create a cyclic dependency. +package wasmruntime + +var ( + // ErrRuntimeStackOverflow indicates that there are too many function calls, + // and the Engine terminated the execution. + ErrRuntimeStackOverflow = New("stack overflow") + // ErrRuntimeInvalidConversionToInteger indicates the Wasm function tries to + // convert NaN floating point value to integers during trunc variant instructions. + ErrRuntimeInvalidConversionToInteger = New("invalid conversion to integer") + // ErrRuntimeIntegerOverflow indicates that an integer arithmetic resulted in + // overflow value. For example, when the program tried to truncate a float value + // which doesn't fit in the range of target integer. + ErrRuntimeIntegerOverflow = New("integer overflow") + // ErrRuntimeIntegerDivideByZero indicates that an integer div or rem instructions + // was executed with 0 as the divisor. + ErrRuntimeIntegerDivideByZero = New("integer divide by zero") + // ErrRuntimeUnreachable means "unreachable" instruction was executed by the program. + ErrRuntimeUnreachable = New("unreachable") + // ErrRuntimeOutOfBoundsMemoryAccess indicates that the program tried to access the + // region beyond the linear memory. + ErrRuntimeOutOfBoundsMemoryAccess = New("out of bounds memory access") + // ErrRuntimeInvalidTableAccess means either offset to the table was out of bounds of table, or + // the target element in the table was uninitialized during call_indirect instruction. + ErrRuntimeInvalidTableAccess = New("invalid table access") + // ErrRuntimeIndirectCallTypeMismatch indicates that the type check failed during call_indirect. + ErrRuntimeIndirectCallTypeMismatch = New("indirect call type mismatch") + // ErrRuntimeUnalignedAtomic indicates that an atomic operation was made with incorrect memory alignment. + ErrRuntimeUnalignedAtomic = New("unaligned atomic") + // ErrRuntimeExpectedSharedMemory indicates that an operation was made against unshared memory when not allowed. + ErrRuntimeExpectedSharedMemory = New("expected shared memory") + // ErrRuntimeTooManyWaiters indicates that atomic.wait was called with too many waiters. + ErrRuntimeTooManyWaiters = New("too many waiters") +) + +// Error is returned by a wasm.Engine during the execution of Wasm functions, and they indicate that the Wasm runtime +// state is unrecoverable. +type Error struct { + s string +} + +func New(text string) *Error { + return &Error{s: text} +} + +func (e *Error) Error() string { + return e.s +} diff --git a/vendor/github.com/tetratelabs/wazero/netlify.toml b/vendor/github.com/tetratelabs/wazero/netlify.toml new file mode 100644 index 00000000..1ba638bf --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/netlify.toml @@ -0,0 +1,15 @@ +[build] + base = "site" + publish = "public" + +[build.environment] + HUGO_VERSION = "0.115.2" + +[context.production] + command = "git submodule update --init && hugo --gc --minify" + +[context.deploy-preview] + command = "git submodule update --init && hugo --gc --minify -b $DEPLOY_PRIME_URL" + +[context.branch-deploy] + command = "git submodule update --init && hugo --gc --minify -b $DEPLOY_PRIME_URL" diff --git a/vendor/github.com/tetratelabs/wazero/runtime.go b/vendor/github.com/tetratelabs/wazero/runtime.go new file mode 100644 index 00000000..7072f3f6 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/runtime.go @@ -0,0 +1,399 @@ +package wazero + +import ( + "context" + "fmt" + "sync/atomic" + + "github.com/tetratelabs/wazero/api" + experimentalapi "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/internal/engine/interpreter" + "github.com/tetratelabs/wazero/internal/engine/wazevo" + "github.com/tetratelabs/wazero/internal/expctxkeys" + "github.com/tetratelabs/wazero/internal/platform" + internalsock "github.com/tetratelabs/wazero/internal/sock" + internalsys "github.com/tetratelabs/wazero/internal/sys" + "github.com/tetratelabs/wazero/internal/wasm" + binaryformat "github.com/tetratelabs/wazero/internal/wasm/binary" + "github.com/tetratelabs/wazero/sys" +) + +// Runtime allows embedding of WebAssembly modules. +// +// The below is an example of basic initialization: +// +// ctx := context.Background() +// r := wazero.NewRuntime(ctx) +// defer r.Close(ctx) // This closes everything this Runtime created. +// +// mod, _ := r.Instantiate(ctx, wasm) +// +// # Notes +// +// - This is an interface for decoupling, not third-party implementations. +// All implementations are in wazero. +// - Closing this closes any CompiledModule or Module it instantiated. +type Runtime interface { + // Instantiate instantiates a module from the WebAssembly binary (%.wasm) + // with default configuration, which notably calls the "_start" function, + // if it exists. + // + // Here's an example: + // ctx := context.Background() + // r := wazero.NewRuntime(ctx) + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // mod, _ := r.Instantiate(ctx, wasm) + // + // # Notes + // + // - See notes on InstantiateModule for error scenarios. + // - See InstantiateWithConfig for configuration overrides. + Instantiate(ctx context.Context, source []byte) (api.Module, error) + + // InstantiateWithConfig instantiates a module from the WebAssembly binary + // (%.wasm) or errs for reasons including exit or validation. + // + // Here's an example: + // ctx := context.Background() + // r := wazero.NewRuntime(ctx) + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // mod, _ := r.InstantiateWithConfig(ctx, wasm, + // wazero.NewModuleConfig().WithName("rotate")) + // + // # Notes + // + // - See notes on InstantiateModule for error scenarios. + // - If you aren't overriding defaults, use Instantiate. + // - This is a convenience utility that chains CompileModule with + // InstantiateModule. To instantiate the same source multiple times, + // use CompileModule as InstantiateModule avoids redundant decoding + // and/or compilation. + InstantiateWithConfig(ctx context.Context, source []byte, config ModuleConfig) (api.Module, error) + + // NewHostModuleBuilder lets you create modules out of functions defined in Go. + // + // Below defines and instantiates a module named "env" with one function: + // + // ctx := context.Background() + // hello := func() { + // fmt.Fprintln(stdout, "hello!") + // } + // _, err := r.NewHostModuleBuilder("env"). + // NewFunctionBuilder().WithFunc(hello).Export("hello"). + // Instantiate(ctx, r) + // + // Note: empty `moduleName` is not allowed. + NewHostModuleBuilder(moduleName string) HostModuleBuilder + + // CompileModule decodes the WebAssembly binary (%.wasm) or errs if invalid. + // Any pre-compilation done after decoding wasm is dependent on RuntimeConfig. + // + // There are two main reasons to use CompileModule instead of Instantiate: + // - Improve performance when the same module is instantiated multiple times under different names + // - Reduce the amount of errors that can occur during InstantiateModule. + // + // # Notes + // + // - The resulting module name defaults to what was binary from the custom name section. + // - Any pre-compilation done after decoding the source is dependent on RuntimeConfig. + // + // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0 + CompileModule(ctx context.Context, binary []byte) (CompiledModule, error) + + // InstantiateModule instantiates the module or errs for reasons including + // exit or validation. + // + // Here's an example: + // mod, _ := n.InstantiateModule(ctx, compiled, wazero.NewModuleConfig(). + // WithName("prod")) + // + // # Errors + // + // While CompiledModule is pre-validated, there are a few situations which + // can cause an error: + // - The module name is already in use. + // - The module has a table element initializer that resolves to an index + // outside the Table minimum size. + // - The module has a start function, and it failed to execute. + // - The module was compiled to WASI and exited with a non-zero exit + // code, you'll receive a sys.ExitError. + // - RuntimeConfig.WithCloseOnContextDone was enabled and a context + // cancellation or deadline triggered before a start function returned. + InstantiateModule(ctx context.Context, compiled CompiledModule, config ModuleConfig) (api.Module, error) + + // CloseWithExitCode closes all the modules that have been initialized in this Runtime with the provided exit code. + // An error is returned if any module returns an error when closed. + // + // Here's an example: + // ctx := context.Background() + // r := wazero.NewRuntime(ctx) + // defer r.CloseWithExitCode(ctx, 2) // This closes everything this Runtime created. + // + // // Everything below here can be closed, but will anyway due to above. + // _, _ = wasi_snapshot_preview1.InstantiateSnapshotPreview1(ctx, r) + // mod, _ := r.Instantiate(ctx, wasm) + CloseWithExitCode(ctx context.Context, exitCode uint32) error + + // Module returns an instantiated module in this runtime or nil if there aren't any. + Module(moduleName string) api.Module + + // Closer closes all compiled code by delegating to CloseWithExitCode with an exit code of zero. + api.Closer +} + +// NewRuntime returns a runtime with a configuration assigned by NewRuntimeConfig. +func NewRuntime(ctx context.Context) Runtime { + return NewRuntimeWithConfig(ctx, NewRuntimeConfig()) +} + +// NewRuntimeWithConfig returns a runtime with the given configuration. +func NewRuntimeWithConfig(ctx context.Context, rConfig RuntimeConfig) Runtime { + config := rConfig.(*runtimeConfig) + configKind := config.engineKind + configEngine := config.newEngine + if configKind == engineKindAuto { + if platform.CompilerSupports(config.enabledFeatures) { + configKind = engineKindCompiler + } else { + configKind = engineKindInterpreter + } + } + if configEngine == nil { + if configKind == engineKindCompiler { + configEngine = wazevo.NewEngine + } else { + configEngine = interpreter.NewEngine + } + } + var engine wasm.Engine + var cacheImpl *cache + if c := config.cache; c != nil { + // If the Cache is configured, we share the engine. + cacheImpl = c.(*cache) + engine = cacheImpl.initEngine(configKind, configEngine, ctx, config.enabledFeatures) + } else { + // Otherwise, we create a new engine. + engine = configEngine(ctx, config.enabledFeatures, nil) + } + store := wasm.NewStore(config.enabledFeatures, engine) + return &runtime{ + cache: cacheImpl, + store: store, + enabledFeatures: config.enabledFeatures, + memoryLimitPages: config.memoryLimitPages, + memoryCapacityFromMax: config.memoryCapacityFromMax, + dwarfDisabled: config.dwarfDisabled, + storeCustomSections: config.storeCustomSections, + ensureTermination: config.ensureTermination, + } +} + +// runtime allows decoupling of public interfaces from internal representation. +type runtime struct { + store *wasm.Store + cache *cache + enabledFeatures api.CoreFeatures + memoryLimitPages uint32 + memoryCapacityFromMax bool + dwarfDisabled bool + storeCustomSections bool + + // closed is the pointer used both to guard moduleEngine.CloseWithExitCode and to store the exit code. + // + // The update value is 1 + exitCode << 32. This ensures an exit code of zero isn't mistaken for never closed. + // + // Note: Exclusively reading and updating this with atomics guarantees cross-goroutine observations. + // See /RATIONALE.md + closed atomic.Uint64 + + ensureTermination bool +} + +// Module implements Runtime.Module. +func (r *runtime) Module(moduleName string) api.Module { + if len(moduleName) == 0 { + return nil + } + m := r.store.Module(moduleName) + if m == nil { + return nil + } else if m.Source.IsHostModule { + return hostModuleInstance{m} + } + return m +} + +// CompileModule implements Runtime.CompileModule +func (r *runtime) CompileModule(ctx context.Context, binary []byte) (CompiledModule, error) { + if err := r.failIfClosed(); err != nil { + return nil, err + } + + internal, err := binaryformat.DecodeModule(binary, r.enabledFeatures, + r.memoryLimitPages, r.memoryCapacityFromMax, !r.dwarfDisabled, r.storeCustomSections) + if err != nil { + return nil, err + } else if err = internal.Validate(r.enabledFeatures); err != nil { + // TODO: decoders should validate before returning, as that allows + // them to err with the correct position in the wasm binary. + return nil, err + } + + // Now that the module is validated, cache the memory definitions. + // TODO: lazy initialization of memory definition. + internal.BuildMemoryDefinitions() + + c := &compiledModule{module: internal, compiledEngine: r.store.Engine} + + // typeIDs are static and compile-time known. + typeIDs, err := r.store.GetFunctionTypeIDs(internal.TypeSection) + if err != nil { + return nil, err + } + c.typeIDs = typeIDs + + listeners, err := buildFunctionListeners(ctx, internal) + if err != nil { + return nil, err + } + internal.AssignModuleID(binary, listeners, r.ensureTermination) + if err = r.store.Engine.CompileModule(ctx, internal, listeners, r.ensureTermination); err != nil { + return nil, err + } + return c, nil +} + +func buildFunctionListeners(ctx context.Context, internal *wasm.Module) ([]experimentalapi.FunctionListener, error) { + // Test to see if internal code are using an experimental feature. + fnlf := ctx.Value(expctxkeys.FunctionListenerFactoryKey{}) + if fnlf == nil { + return nil, nil + } + factory := fnlf.(experimentalapi.FunctionListenerFactory) + importCount := internal.ImportFunctionCount + listeners := make([]experimentalapi.FunctionListener, len(internal.FunctionSection)) + for i := 0; i < len(listeners); i++ { + listeners[i] = factory.NewFunctionListener(internal.FunctionDefinition(uint32(i) + importCount)) + } + return listeners, nil +} + +// failIfClosed returns an error if CloseWithExitCode was called implicitly (by Close) or explicitly. +func (r *runtime) failIfClosed() error { + if closed := r.closed.Load(); closed != 0 { + return fmt.Errorf("runtime closed with exit_code(%d)", uint32(closed>>32)) + } + return nil +} + +// Instantiate implements Runtime.Instantiate +func (r *runtime) Instantiate(ctx context.Context, binary []byte) (api.Module, error) { + return r.InstantiateWithConfig(ctx, binary, NewModuleConfig()) +} + +// InstantiateWithConfig implements Runtime.InstantiateWithConfig +func (r *runtime) InstantiateWithConfig(ctx context.Context, binary []byte, config ModuleConfig) (api.Module, error) { + if compiled, err := r.CompileModule(ctx, binary); err != nil { + return nil, err + } else { + compiled.(*compiledModule).closeWithModule = true + return r.InstantiateModule(ctx, compiled, config) + } +} + +// InstantiateModule implements Runtime.InstantiateModule. +func (r *runtime) InstantiateModule( + ctx context.Context, + compiled CompiledModule, + mConfig ModuleConfig, +) (mod api.Module, err error) { + if err = r.failIfClosed(); err != nil { + return nil, err + } + + code := compiled.(*compiledModule) + config := mConfig.(*moduleConfig) + + // Only add guest module configuration to guests. + if !code.module.IsHostModule { + if sockConfig, ok := ctx.Value(internalsock.ConfigKey{}).(*internalsock.Config); ok { + config.sockConfig = sockConfig + } + } + + var sysCtx *internalsys.Context + if sysCtx, err = config.toSysContext(); err != nil { + return nil, err + } + + name := config.name + if !config.nameSet && code.module.NameSection != nil && code.module.NameSection.ModuleName != "" { + name = code.module.NameSection.ModuleName + } + + // Instantiate the module. + mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx, code.typeIDs) + if err != nil { + // If there was an error, don't leak the compiled module. + if code.closeWithModule { + _ = code.Close(ctx) // don't overwrite the error + } + return nil, err + } + + if closeNotifier, ok := ctx.Value(expctxkeys.CloseNotifierKey{}).(experimentalapi.CloseNotifier); ok { + mod.(*wasm.ModuleInstance).CloseNotifier = closeNotifier + } + + // Attach the code closer so that anything afterward closes the compiled + // code when closing the module. + if code.closeWithModule { + mod.(*wasm.ModuleInstance).CodeCloser = code + } + + // Now, invoke any start functions, failing at first error. + for _, fn := range config.startFunctions { + start := mod.ExportedFunction(fn) + if start == nil { + continue + } + if _, err = start.Call(ctx); err != nil { + _ = mod.Close(ctx) // Don't leak the module on error. + + if se, ok := err.(*sys.ExitError); ok { + if se.ExitCode() == 0 { // Don't err on success. + err = nil + } + return // Don't wrap an exit error + } + err = fmt.Errorf("module[%s] function[%s] failed: %w", name, fn, err) + return + } + } + return +} + +// Close implements api.Closer embedded in Runtime. +func (r *runtime) Close(ctx context.Context) error { + return r.CloseWithExitCode(ctx, 0) +} + +// CloseWithExitCode implements Runtime.CloseWithExitCode +// +// Note: it also marks the internal `closed` field +func (r *runtime) CloseWithExitCode(ctx context.Context, exitCode uint32) error { + closed := uint64(1) + uint64(exitCode)<<32 // Store exitCode as high-order bits. + if !r.closed.CompareAndSwap(0, closed) { + return nil + } + err := r.store.CloseWithExitCode(ctx, exitCode) + if r.cache == nil { + // Close the engine if the cache is not configured, which means that this engine is scoped in this runtime. + if errCloseEngine := r.store.Engine.Close(); errCloseEngine != nil { + return errCloseEngine + } + } + return err +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/clock.go b/vendor/github.com/tetratelabs/wazero/sys/clock.go new file mode 100644 index 00000000..1c91ce24 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/clock.go @@ -0,0 +1,26 @@ +package sys + +// ClockResolution is a positive granularity of clock precision in +// nanoseconds. For example, if the resolution is 1us, this returns 1000. +// +// Note: Some implementations return arbitrary resolution because there's +// no perfect alternative. For example, according to the source in time.go, +// windows monotonic resolution can be 15ms. See /RATIONALE.md. +type ClockResolution uint32 + +// Walltime returns the current unix/epoch time, seconds since midnight UTC +// 1 January 1970, with a nanosecond fraction. +type Walltime func() (sec int64, nsec int32) + +// Nanotime returns nanoseconds since an arbitrary start point, used to measure +// elapsed time. This is sometimes referred to as a tick or monotonic time. +// +// Note: There are no constraints on the value return except that it +// increments. For example, -1 is a valid if the next value is >= 0. +type Nanotime func() int64 + +// Nanosleep puts the current goroutine to sleep for at least ns nanoseconds. +type Nanosleep func(ns int64) + +// Osyield yields the processor, typically to implement spin-wait loops. +type Osyield func() diff --git a/vendor/github.com/tetratelabs/wazero/sys/error.go b/vendor/github.com/tetratelabs/wazero/sys/error.go new file mode 100644 index 00000000..c3efbad9 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/error.go @@ -0,0 +1,83 @@ +// Package sys includes constants and types used by both public and internal APIs. +package sys + +import ( + "context" + "fmt" +) + +// These two special exit codes are reserved by wazero for context Cancel and Timeout integrations. +// The assumption here is that well-behaving Wasm programs won't use these two exit codes. +const ( + // ExitCodeContextCanceled corresponds to context.Canceled and returned by ExitError.ExitCode in that case. + ExitCodeContextCanceled uint32 = 0xffffffff + // ExitCodeDeadlineExceeded corresponds to context.DeadlineExceeded and returned by ExitError.ExitCode in that case. + ExitCodeDeadlineExceeded uint32 = 0xefffffff +) + +// ExitError is returned to a caller of api.Function when api.Module CloseWithExitCode was invoked, +// or context.Context passed to api.Function Call was canceled or reached the Timeout. +// +// ExitCode zero value means success while any other value is an error. +// +// Here's an example of how to get the exit code: +// +// main := module.ExportedFunction("main") +// if err := main(ctx); err != nil { +// if exitErr, ok := err.(*sys.ExitError); ok { +// // This means your module exited with non-zero code! +// } +// --snip-- +// +// Note: While possible the reason of this was "proc_exit" from "wasi_snapshot_preview1", it could be from other host +// functions, for example an AssemblyScript's abort handler, or any arbitrary caller of CloseWithExitCode. +// +// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit and +// https://www.assemblyscript.org/concepts.html#special-imports +// +// Note: In the case of context cancellation or timeout, the api.Module from which the api.Function created is closed. +type ExitError struct { + // Note: this is a struct not a uint32 type as it was originally one and + // we don't want to break call-sites that cast into it. + exitCode uint32 +} + +var exitZero = &ExitError{} + +func NewExitError(exitCode uint32) *ExitError { + if exitCode == 0 { + return exitZero + } + return &ExitError{exitCode: exitCode} +} + +// ExitCode returns zero on success, and an arbitrary value otherwise. +func (e *ExitError) ExitCode() uint32 { + return e.exitCode +} + +// Error implements the error interface. +func (e *ExitError) Error() string { + switch e.exitCode { + case ExitCodeContextCanceled: + return fmt.Sprintf("module closed with %s", context.Canceled) + case ExitCodeDeadlineExceeded: + return fmt.Sprintf("module closed with %s", context.DeadlineExceeded) + default: + return fmt.Sprintf("module closed with exit_code(%d)", e.exitCode) + } +} + +// Is allows use via errors.Is +func (e *ExitError) Is(err error) bool { + if target, ok := err.(*ExitError); ok { + return e.exitCode == target.exitCode + } + if e.exitCode == ExitCodeContextCanceled && err == context.Canceled { + return true + } + if e.exitCode == ExitCodeDeadlineExceeded && err == context.DeadlineExceeded { + return true + } + return false +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/stat.go b/vendor/github.com/tetratelabs/wazero/sys/stat.go new file mode 100644 index 00000000..32888554 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/stat.go @@ -0,0 +1,105 @@ +package sys + +import "io/fs" + +// Inode is the file serial number, or zero if unknown. +// +// Any constant value will invalidate functions that use this for +// equivalence, such as os.SameFile (Stat_t.Ino). +// +// When zero is returned by a `readdir`, some compilers will attempt to +// get a non-zero value with `lstat`. Those using this for darwin's definition +// of `getdirentries` conflate zero `d_fileno` with a deleted file, so skip the +// entry. See /RATIONALE.md for more on this. +type Inode = uint64 + +// ^-- Inode is a type alias to consolidate documentation and aid in reference +// searches. While only Stat_t is exposed publicly at the moment, this is used +// internally for Dirent and several function return values. + +// EpochNanos is a timestamp in epoch nanoseconds, or zero if unknown. +// +// This defines epoch time the same way as Walltime, except this value is +// packed into an int64. Common conversions are detailed in the examples. +type EpochNanos = int64 + +// Stat_t is similar to syscall.Stat_t, except available on all operating +// systems, including Windows. +// +// # Notes +// +// - This is used for WebAssembly ABI emulating the POSIX `stat` system call. +// See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html +// - Fields here are required for WebAssembly ABI including wasip1 +// (a.k.a. wasix) and wasi-filesystem (a.k.a. wasip2). +// - This isn't the same as syscall.Stat_t because wazero supports Windows, +// which doesn't have that type. runtime.GOOS that has this already also +// have inconsistent field lengths, which complicates wasm binding. +// - Use NewStat_t to create this from an existing fs.FileInfo. +// - For portability, numeric fields are 64-bit when at least one platform +// defines it that large. +type Stat_t struct { + // Dev is the device ID of device containing the file. + Dev uint64 + + // Ino is the file serial number, or zero if not available. See Inode for + // more details including impact returning a zero value. + Ino Inode + + // Mode is the same as Mode on fs.FileInfo containing bits to identify the + // type of the file (fs.ModeType) and its permissions (fs.ModePerm). + Mode fs.FileMode + + // Nlink is the number of hard links to the file. + // + // Note: This value is platform-specific and often at least one. Linux will + // return 1+N for a directory, where BSD (like Darwin) return 2+N, which + // includes the dot entry. + Nlink uint64 + + // Size is the length in bytes for regular files. For symbolic links, this + // is length in bytes of the pathname contained in the symbolic link. + Size int64 + + // Atim is the last data access timestamp in epoch nanoseconds. + Atim EpochNanos + + // Mtim is the last data modification timestamp in epoch nanoseconds. + Mtim EpochNanos + + // Ctim is the last file status change timestamp in epoch nanoseconds. + Ctim EpochNanos +} + +// NewStat_t fills a new Stat_t from `info`, including any runtime.GOOS-specific +// details from fs.FileInfo `Sys`. When `Sys` is already a *Stat_t, it is +// returned as-is. +// +// # Notes +// +// - When already in fs.FileInfo `Sys`, Stat_t must be a pointer. +// - When runtime.GOOS is "windows" Stat_t.Ino will be zero. +// - When fs.FileInfo `Sys` is nil or unknown, some fields not in fs.FileInfo +// are defaulted: Stat_t.Atim and Stat_t.Ctim are set to `ModTime`, and +// are set to ModTime and Stat_t.Nlink is set to 1. +func NewStat_t(info fs.FileInfo) Stat_t { + // Note: Pointer, not val, for parity with Go, which sets *syscall.Stat_t + if st, ok := info.Sys().(*Stat_t); ok { + return *st + } + return statFromFileInfo(info) +} + +func defaultStatFromFileInfo(info fs.FileInfo) Stat_t { + st := Stat_t{} + st.Ino = 0 + st.Dev = 0 + st.Mode = info.Mode() + st.Nlink = 1 + st.Size = info.Size() + mtim := info.ModTime().UnixNano() // Set all times to the mod time + st.Atim = mtim + st.Mtim = mtim + st.Ctim = mtim + return st +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/stat_bsd.go b/vendor/github.com/tetratelabs/wazero/sys/stat_bsd.go new file mode 100644 index 00000000..3bf9b5d1 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/stat_bsd.go @@ -0,0 +1,29 @@ +//go:build (amd64 || arm64) && (darwin || freebsd) + +package sys + +import ( + "io/fs" + "syscall" +) + +const sysParseable = true + +func statFromFileInfo(info fs.FileInfo) Stat_t { + if d, ok := info.Sys().(*syscall.Stat_t); ok { + st := Stat_t{} + st.Dev = uint64(d.Dev) + st.Ino = d.Ino + st.Mode = info.Mode() + st.Nlink = uint64(d.Nlink) + st.Size = d.Size + atime := d.Atimespec + st.Atim = atime.Sec*1e9 + atime.Nsec + mtime := d.Mtimespec + st.Mtim = mtime.Sec*1e9 + mtime.Nsec + ctime := d.Ctimespec + st.Ctim = ctime.Sec*1e9 + ctime.Nsec + return st + } + return defaultStatFromFileInfo(info) +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/stat_linux.go b/vendor/github.com/tetratelabs/wazero/sys/stat_linux.go new file mode 100644 index 00000000..9b5e20e8 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/stat_linux.go @@ -0,0 +1,32 @@ +//go:build (amd64 || arm64 || riscv64) && linux + +// Note: This expression is not the same as compiler support, even if it looks +// similar. Platform functions here are used in interpreter mode as well. + +package sys + +import ( + "io/fs" + "syscall" +) + +const sysParseable = true + +func statFromFileInfo(info fs.FileInfo) Stat_t { + if d, ok := info.Sys().(*syscall.Stat_t); ok { + st := Stat_t{} + st.Dev = uint64(d.Dev) + st.Ino = uint64(d.Ino) + st.Mode = info.Mode() + st.Nlink = uint64(d.Nlink) + st.Size = d.Size + atime := d.Atim + st.Atim = atime.Sec*1e9 + atime.Nsec + mtime := d.Mtim + st.Mtim = mtime.Sec*1e9 + mtime.Nsec + ctime := d.Ctim + st.Ctim = ctime.Sec*1e9 + ctime.Nsec + return st + } + return defaultStatFromFileInfo(info) +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/stat_unsupported.go b/vendor/github.com/tetratelabs/wazero/sys/stat_unsupported.go new file mode 100644 index 00000000..cc37012c --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/stat_unsupported.go @@ -0,0 +1,14 @@ +//go:build (!((amd64 || arm64 || riscv64) && linux) && !((amd64 || arm64) && (darwin || freebsd)) && !((amd64 || arm64) && windows)) || js + +package sys + +import "io/fs" + +// sysParseable is only used here as we define "supported" as being able to +// parse `info.Sys()`. The above `go:build` constraints exclude 32-bit until +// that's requested. +const sysParseable = false + +func statFromFileInfo(info fs.FileInfo) Stat_t { + return defaultStatFromFileInfo(info) +} diff --git a/vendor/github.com/tetratelabs/wazero/sys/stat_windows.go b/vendor/github.com/tetratelabs/wazero/sys/stat_windows.go new file mode 100644 index 00000000..1a7070f4 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/stat_windows.go @@ -0,0 +1,26 @@ +//go:build (amd64 || arm64) && windows + +package sys + +import ( + "io/fs" + "syscall" +) + +const sysParseable = true + +func statFromFileInfo(info fs.FileInfo) Stat_t { + if d, ok := info.Sys().(*syscall.Win32FileAttributeData); ok { + st := Stat_t{} + st.Ino = 0 // not in Win32FileAttributeData + st.Dev = 0 // not in Win32FileAttributeData + st.Mode = info.Mode() + st.Nlink = 1 // not in Win32FileAttributeData + st.Size = info.Size() + st.Atim = d.LastAccessTime.Nanoseconds() + st.Mtim = d.LastWriteTime.Nanoseconds() + st.Ctim = d.CreationTime.Nanoseconds() + return st + } + return defaultStatFromFileInfo(info) +} diff --git a/vendor/github.com/wasilibs/go-re2/.gitattributes b/vendor/github.com/wasilibs/go-re2/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/vendor/github.com/wasilibs/go-re2/.gitignore b/vendor/github.com/wasilibs/go-re2/.gitignore new file mode 100644 index 00000000..c41d2ff9 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/.gitignore @@ -0,0 +1,3 @@ +.idea +out +go.work.sum diff --git a/vendor/github.com/wasilibs/go-re2/.golangci.yml b/vendor/github.com/wasilibs/go-re2/.golangci.yml new file mode 100644 index 00000000..65a95745 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/.golangci.yml @@ -0,0 +1,19 @@ +linters: + enable: + - gci + - gofumpt +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/wasilibs/go-re2) +issues: + exclude-rules: + - path: magefiles + linters: + - deadcode + - path: _test.go + linters: + # We have tests for deprecated methods + - staticcheck diff --git a/vendor/github.com/wasilibs/go-re2/.yamllint.yaml b/vendor/github.com/wasilibs/go-re2/.yamllint.yaml new file mode 100644 index 00000000..9fa37374 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/.yamllint.yaml @@ -0,0 +1,5 @@ +rules: + document-start: disable + line-length: disable + truthy: + check-keys: false diff --git a/vendor/github.com/wasilibs/go-re2/CODE_OF_CONDUCT.md b/vendor/github.com/wasilibs/go-re2/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..561f3dd0 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of + any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, + without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +anuraaga@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/vendor/github.com/wasilibs/go-re2/LICENSE b/vendor/github.com/wasilibs/go-re2/LICENSE new file mode 100644 index 00000000..5c5a70be --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 wasilibs authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/wasilibs/go-re2/NOTICE.txt b/vendor/github.com/wasilibs/go-re2/NOTICE.txt new file mode 100644 index 00000000..7db80320 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/NOTICE.txt @@ -0,0 +1,29 @@ +Test code has been copied from https://github.com/golang/go + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/wasilibs/go-re2/RATIONALE.md b/vendor/github.com/wasilibs/go-re2/RATIONALE.md new file mode 100644 index 00000000..487e32d0 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/RATIONALE.md @@ -0,0 +1,34 @@ +# Notable rationale of go-re2 + +## No Close method + +This library does not add a `Close` method to `Regexp` to allow manually freeing native memory as is +typical with libraries that wrap C++ in Go. A finalizer is set to allow release when the GC reclaims +the object. In many other cases of native wrappers, this is not sufficient - the GC will not be aware +of the real memory usage on the native side and not perform correctly. + +In this library, we have chosen not to add it because in the default mode for Go apps using wazero, +the above limitation is not true. Because wazero itself allocates the memory used by the WebAssembly +module, all the memory allocated in C++ code is actually allocated by the Go GC. This means the GC +does know exactly how much memory is used by `Regexp` and acts correctly. + +However, for cgo or TinyGo, this is not the case. We still go ahead and leave out `Close` for now +for the less concrete reason that closing would generally only be needed with short-lived regular +expressions. Compilation time with this library takes much longer than the standard library - it is +not appropriate for use with short-lived expressions. In the case that it is acceptable and the +static match functions are used, the regular expressions will be freed as soon as they're used. +If code decides to use this library and has short-lived compiled expressions, rather than adding +`Close` it should be simple to switch to the match functions instead. + +This leaves medium-lived expressions as a use case for `Close` - for example there may be some +business logic that is dynamically loaded and unloaded that gets compiled as regex. For now, we +will leave it as future work to add `Close` for this use case, under cgo or TinyGo, if it gets +asked for. All other use cases are expected to work fine without it. + +## No implementation of Reader methods + +The standard library gives leeway to read an arbitrary amount of input from a `Reader` when processing. +This means that we could implement the API surface by reading the entire string and passing to re2. +This defeats the purpose of the `Reader` methods though, and we choose to keep it a compilation failure. +For applications where buffering the entire string is acceptable, they can be rewritten to do so in their +logic, while when not acceptable it is fine to continue to use the standard library. diff --git a/vendor/github.com/wasilibs/go-re2/README.md b/vendor/github.com/wasilibs/go-re2/README.md new file mode 100644 index 00000000..426ed991 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/README.md @@ -0,0 +1,274 @@ +# go-re2 + +go-re2 is a drop-in replacement for the standard library [regexp][1] package which uses the C++ +[re2][2] library for improved performance with large inputs or complex expressions. By default, +re2 is packaged as a WebAssembly module and accessed with the pure Go runtime, [wazero][3]. +This means that it is compatible with any Go application, regardless of availability of cgo. + +Note that if your regular expressions or input are small, this library is slower than the +standard library. You will generally "know" if your application requires high performance for +complex regular expressions, for example in security filtering software. If you do not know +your app has such needs, you should turn away now. + +## Behavior differences + +The library is almost fully compatible with the standard library regexp package, with just a few +behavior differences. These are likely corner cases that don't affect typical applications. It is +best to confirm them before proceeding. + +- Invalid utf-8 strings are treated differently. The standard library silently replaces invalid utf-8 + with the unicode replacement character. This library will stop consuming strings when encountering + invalid utf-8. + + - `experimental.CompileLatin1` can be used to match against non-utf8 strings + +- `reflect.DeepEqual` cannot compare `Regexp` objects. + +Continue to use the standard library if your usage would match any of these. + +Searching this codebase for `// GAP` will allow finding tests that have been tweaked to demonstrate +behavior differences. + +## API differences + +All APIs found in `regexp` are available except + +- `*Reader`: re2 does not support streaming input + +Note that unlike many packages that wrap C++ libraries, there is no added `Close` type of method. +See the [rationale](./RATIONALE.md) for more details. + +### Experimental APIs + +The [experimental](./experimental) package contains APIs not part of standard `regexp` that are +incubating. They may in the future be moved to stable packages. The experimental package does not +provide any guarantee of API stability even across minor version updates. + +## Usage + +go-re2 is a standard Go library package and can be added to a go.mod file. It will work fine in +any Go project. See [below](#tinygo) for notes about TinyGo support. + +``` +go get github.com/wasilibs/go-re2 +``` + +Because the library is a drop-in replacement for the standard library, an import alias can make +migrating code to use it simple. + +```go +import "regexp" +``` + +can be changed to + +```go +import regexp "github.com/wasilibs/go-re2" +``` + +### cgo + +This library also supports opting into using cgo to wrap re2 instead of using WebAssembly. This +requires having re2 installed and available via `pkg-config` on the system. The build tag `re2_cgo` +can be used to enable cgo support. + +#### Ubuntu + +On Ubuntu install the gcc tool chain and the re2 library as follows: + +```bash +sudo apt install build-essential +sudo apt-get install -y libre2-dev +``` + +#### Alpine + +On Alpine install the gcc tool chain and the re2 library as follows: + +```bash +apk add build-base pkgconfig re2-dev +``` + +#### Windows + +On Windows start by installing [MSYS2][8]. Then open the MINGW64 terminal and install the gcc toolchain and re2 via pacman: + +```bash +pacman -S mingw-w64-x86_64-gcc +pacman -S mingw-w64-x86_64-re2 +pacman -S mingw-w64-x86_64-pkg-config +``` + +If you want to run the resulting exe program outside the MINGW64 terminal you need to add a path to the MinGW-w64 libraries to the PATH environmental variable (adjust as needed for your system): + +```cmd +SET PATH=C:\msys64\mingw64\bin;%PATH% +``` + +#### MacOS + +On Mac start by installing [homebrew][9] including installation of the command line tools. Then install re2 via brew: + +```bash +brew install re2 +``` + +### TinyGo + +This project began as a way to use re2 with TinyGo WASI projects. However, recent versions of re2 have reworked +their build, notably depending on absl which requires threads support and breaks compatibility with TinyGo programs. +To stay up-to-date with re2, after much time this project has removed building of TinyGo-specific Wasm artifacts. +Build tags to enable cgo codepaths for TinyGo are kept to provide best-effort support with projects bringing their +own Wasm, with the only known usage currently in [coraza-wasilibs][10]. + +## Performance + +Benchmarks are run against every commit in the [bench][4] workflow. GitHub action runners are highly +virtualized and do not have stable performance across runs, but the relative numbers within a run +should still be somewhat, though not precisely, informative. + +### wafbench + +wafbench tests the performance of replacing the regex operator of the OWASP [CoreRuleSet][5] and +[Coraza][6] implementation with this library. This benchmark is considered a real world performance +test, with the regular expressions being real ones used in production. Security filtering rules +often have highly complex expressions. + +One run looks like this + +``` +name \ time/op build/wafbench_stdlib.txt build/wafbench.txt build/wafbench_cgo.txt +WAF/FTW-4 21.72 ± ∞ ¹ 21.17 ± ∞ ¹ -2.55% (p=0.008 n=5) 19.51 ± ∞ ¹ -10.19% (p=0.008 n=5) +WAF/POST/1-4 2.308m ± ∞ ¹ 2.727m ± ∞ ¹ +18.18% (p=0.008 n=5) 2.479m ± ∞ ¹ +7.44% (p=0.008 n=5) +WAF/POST/1000-4 15.399m ± ∞ ¹ 4.734m ± ∞ ¹ -69.26% (p=0.008 n=5) 3.742m ± ∞ ¹ -75.70% (p=0.008 n=5) +WAF/POST/10000-4 150.65m ± ∞ ¹ 19.90m ± ∞ ¹ -86.79% (p=0.008 n=5) 13.47m ± ∞ ¹ -91.06% (p=0.008 n=5) +WAF/POST/100000-4 1511.3m ± ∞ ¹ 171.7m ± ∞ ¹ -88.64% (p=0.008 n=5) 110.4m ± ∞ ¹ -92.69% (p=0.008 n=5) +``` + +`FTW` is the time to run the standard CoreRuleSet test framework. The performance of this +library with WebAssembly, wafbench.txt, shows a slight improvement over the standard library +in this baseline test case. + +The FTW test suite will issue many requests with various payloads, generally somewhat small. +The `POST` tests show the same ruleset applied to requests with payload sizes as shown, in bytes. +We see that only with the absolute smallest payload of 1 byte does the standard library perform +a bit better than this library. For any larger size, even a fairly typical 1KB, go-re2 +greatly outperforms. + +cgo seems to offer about a 30% improvement on WebAssembly in this library. Many apps may accept +the somewhat slower performance in exchange for the build and deployment flexibility of +WebAssembly but either option will work with no changes to the codebase. + +### Microbenchmarks + +Microbenchmarks are the same as included in the Go standard library. Full results can be +viewed in the workflow, a sample of results for one run looks like this + +``` +name \ time/op build/bench_stdlib.txt build/bench.txt build/bench_cgo.txt +Find-4 162.3n ± ∞ ¹ 1057.0n ± ∞ ¹ +551.26% (p=0.008 n=5) 397.5n ± ∞ ¹ +144.92% (p=0.008 n=5) +Compile/Onepass-4 4.017µ ± ∞ ¹ 23.585µ ± ∞ ¹ +487.13% (p=0.008 n=5) 7.803µ ± ∞ ¹ +94.25% (p=0.008 n=5) +Compile/Medium-4 9.042µ ± ∞ ¹ 45.105µ ± ∞ ¹ +398.84% (p=0.008 n=5) 13.346µ ± ∞ ¹ +47.60% (p=0.008 n=5) +Compile/Hard-4 66.52µ ± ∞ ¹ 272.58µ ± ∞ ¹ +309.80% (p=0.008 n=5) 94.49µ ± ∞ ¹ +42.06% (p=0.008 n=5) +Match/Easy0/16-4 3.721n ± ∞ ¹ 615.300n ± ∞ ¹ +16435.88% (p=0.008 n=5) 155.900n ± ∞ ¹ +4089.73% (p=0.008 n=5) +Match/Easy0/32-4 40.41n ± ∞ ¹ 620.10n ± ∞ ¹ +1434.52% (p=0.008 n=5) 155.00n ± ∞ ¹ +283.57% (p=0.008 n=5) +Match/Easy0/1K-4 242.3n ± ∞ ¹ 689.7n ± ∞ ¹ +184.65% (p=0.008 n=5) 154.8n ± ∞ ¹ -36.11% (p=0.008 n=5) +Match/Easy0/32K-4 3279.0n ± ∞ ¹ 1384.0n ± ∞ ¹ -57.79% (p=0.008 n=5) 154.0n ± ∞ ¹ -95.30% (p=0.008 n=5) +Match/Easy0/1M-4 240196.0n ± ∞ ¹ 42954.0n ± ∞ ¹ -82.12% (p=0.008 n=5) 155.0n ± ∞ ¹ -99.94% (p=0.008 n=5) +Match/Easy0/32M-4 7942195.0n ± ∞ ¹ 1359859.0n ± ∞ ¹ -82.88% (p=0.008 n=5) 155.4n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Easy0i/16-4 3.723n ± ∞ ¹ 589.600n ± ∞ ¹ +15736.69% (p=0.008 n=5) 155.800n ± ∞ ¹ +4084.80% (p=0.008 n=5) +Match/Easy0i/32-4 681.2n ± ∞ ¹ 593.3n ± ∞ ¹ -12.90% (p=0.008 n=5) 154.3n ± ∞ ¹ -77.35% (p=0.008 n=5) +Match/Easy0i/1K-4 20325.0n ± ∞ ¹ 667.6n ± ∞ ¹ -96.72% (p=0.008 n=5) 155.4n ± ∞ ¹ -99.24% (p=0.008 n=5) +Match/Easy0i/32K-4 913391.0n ± ∞ ¹ 1368.0n ± ∞ ¹ -99.85% (p=0.008 n=5) 155.2n ± ∞ ¹ -99.98% (p=0.008 n=5) +Match/Easy0i/1M-4 29087522.0n ± ∞ ¹ 42975.0n ± ∞ ¹ -99.85% (p=0.008 n=5) 155.5n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Easy0i/32M-4 929572314.0n ± ∞ ¹ 1362975.0n ± ∞ ¹ -99.85% (p=0.008 n=5) 155.7n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Easy1/16-4 3.721n ± ∞ ¹ 591.000n ± ∞ ¹ +15782.83% (p=0.008 n=5) 156.600n ± ∞ ¹ +4108.55% (p=0.008 n=5) +Match/Easy1/32-4 37.39n ± ∞ ¹ 595.30n ± ∞ ¹ +1492.14% (p=0.008 n=5) 155.40n ± ∞ ¹ +315.62% (p=0.008 n=5) +Match/Easy1/1K-4 517.5n ± ∞ ¹ 685.1n ± ∞ ¹ +32.39% (p=0.008 n=5) 156.4n ± ∞ ¹ -69.78% (p=0.008 n=5) +Match/Easy1/32K-4 25905.0n ± ∞ ¹ 1342.0n ± ∞ ¹ -94.82% (p=0.008 n=5) 158.2n ± ∞ ¹ -99.39% (p=0.008 n=5) +Match/Easy1/1M-4 929177.0n ± ∞ ¹ 42940.0n ± ∞ ¹ -95.38% (p=0.008 n=5) 155.1n ± ∞ ¹ -99.98% (p=0.008 n=5) +Match/Easy1/32M-4 29798707.0n ± ∞ ¹ 1362212.0n ± ∞ ¹ -95.43% (p=0.008 n=5) 155.6n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Medium/16-4 3.723n ± ∞ ¹ 590.900n ± ∞ ¹ +15771.61% (p=0.008 n=5) 155.000n ± ∞ ¹ +4063.31% (p=0.008 n=5) +Match/Medium/32-4 566.8n ± ∞ ¹ 595.2n ± ∞ ¹ +5.01% (p=0.008 n=5) 154.9n ± ∞ ¹ -72.67% (p=0.008 n=5) +Match/Medium/1K-4 20063.0n ± ∞ ¹ 669.7n ± ∞ ¹ -96.66% (p=0.008 n=5) 155.3n ± ∞ ¹ -99.23% (p=0.008 n=5) +Match/Medium/32K-4 924929.0n ± ∞ ¹ 1340.0n ± ∞ ¹ -99.86% (p=0.008 n=5) 155.8n ± ∞ ¹ -99.98% (p=0.008 n=5) +Match/Medium/1M-4 29406989.0n ± ∞ ¹ 42947.0n ± ∞ ¹ -99.85% (p=0.008 n=5) 154.6n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Medium/32M-4 963966642.0n ± ∞ ¹ 1363441.0n ± ∞ ¹ -99.86% (p=0.008 n=5) 154.6n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Hard/16-4 3.744n ± ∞ ¹ 596.000n ± ∞ ¹ +15818.80% (p=0.008 n=5) 155.600n ± ∞ ¹ +4055.98% (p=0.008 n=5) +Match/Hard/32-4 997.3n ± ∞ ¹ 598.1n ± ∞ ¹ -40.03% (p=0.008 n=5) 155.6n ± ∞ ¹ -84.40% (p=0.008 n=5) +Match/Hard/1K-4 30435.0n ± ∞ ¹ 686.5n ± ∞ ¹ -97.74% (p=0.008 n=5) 154.7n ± ∞ ¹ -99.49% (p=0.008 n=5) +Match/Hard/32K-4 1348825.0n ± ∞ ¹ 1342.0n ± ∞ ¹ -99.90% (p=0.008 n=5) 155.7n ± ∞ ¹ -99.99% (p=0.008 n=5) +Match/Hard/1M-4 43023861.0n ± ∞ ¹ 42891.0n ± ∞ ¹ -99.90% (p=0.008 n=5) 155.9n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Hard/32M-4 1380076363.0n ± ∞ ¹ 1362504.0n ± ∞ ¹ -99.90% (p=0.008 n=5) 155.7n ± ∞ ¹ -100.00% (p=0.008 n=5) +Match/Hard1/16-4 2661.0n ± ∞ ¹ 697.6n ± ∞ ¹ -73.78% (p=0.008 n=5) 169.0n ± ∞ ¹ -93.65% (p=0.008 n=5) +Match/Hard1/32-4 5084.0n ± ∞ ¹ 796.9n ± ∞ ¹ -84.33% (p=0.008 n=5) 201.5n ± ∞ ¹ -96.04% (p=0.008 n=5) +Match/Hard1/1K-4 157.089µ ± ∞ ¹ 6.838µ ± ∞ ¹ -95.65% (p=0.008 n=5) 2.092µ ± ∞ ¹ -98.67% (p=0.008 n=5) +Match/Hard1/32K-4 6748.74µ ± ∞ ¹ 196.99µ ± ∞ ¹ -97.08% (p=0.008 n=5) 62.52µ ± ∞ ¹ -99.07% (p=0.008 n=5) +Match/Hard1/1M-4 214.239m ± ∞ ¹ 6.290m ± ∞ ¹ -97.06% (p=0.008 n=5) 1.895m ± ∞ ¹ -99.12% (p=0.008 n=5) +Match/Hard1/32M-4 6936.54m ± ∞ ¹ 201.05m ± ∞ ¹ -97.10% (p=0.008 n=5) 59.88m ± ∞ ¹ -99.14% (p=0.008 n=5) +MatchParallel/Easy0/16-4 1.710n ± ∞ ¹ 942.200n ± ∞ ¹ +54999.42% (p=0.008 n=5) 81.700n ± ∞ ¹ +4677.78% (p=0.008 n=5) +MatchParallel/Easy0/32-4 19.10n ± ∞ ¹ 944.80n ± ∞ ¹ +4846.60% (p=0.008 n=5) 82.03n ± ∞ ¹ +329.48% (p=0.008 n=5) +MatchParallel/Easy0/1K-4 96.72n ± ∞ ¹ 978.40n ± ∞ ¹ +911.58% (p=0.008 n=5) 80.82n ± ∞ ¹ -16.44% (p=0.008 n=5) +MatchParallel/Easy0/32K-4 1285.00n ± ∞ ¹ 1425.00n ± ∞ ¹ +10.89% (p=0.008 n=5) 80.82n ± ∞ ¹ -93.71% (p=0.008 n=5) +MatchParallel/Easy0/1M-4 74284.00n ± ∞ ¹ 41354.00n ± ∞ ¹ -44.33% (p=0.008 n=5) 79.92n ± ∞ ¹ -99.89% (p=0.008 n=5) +MatchParallel/Easy0/32M-4 2382580.00n ± ∞ ¹ 1320813.00n ± ∞ ¹ -44.56% (p=0.008 n=5) 80.95n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Easy0i/16-4 1.711n ± ∞ ¹ 937.600n ± ∞ ¹ +54698.36% (p=0.008 n=5) 81.650n ± ∞ ¹ +4672.06% (p=0.008 n=5) +MatchParallel/Easy0i/32-4 339.90n ± ∞ ¹ 945.70n ± ∞ ¹ +178.23% (p=0.008 n=5) 81.28n ± ∞ ¹ -76.09% (p=0.008 n=5) +MatchParallel/Easy0i/1K-4 10107.00n ± ∞ ¹ 992.20n ± ∞ ¹ -90.18% (p=0.008 n=5) 81.21n ± ∞ ¹ -99.20% (p=0.008 n=5) +MatchParallel/Easy0i/32K-4 451362.00n ± ∞ ¹ 1422.00n ± ∞ ¹ -99.68% (p=0.008 n=5) 81.38n ± ∞ ¹ -99.98% (p=0.008 n=5) +MatchParallel/Easy0i/1M-4 14439204.00n ± ∞ ¹ 41325.00n ± ∞ ¹ -99.71% (p=0.008 n=5) 80.67n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Easy0i/32M-4 563552821.00n ± ∞ ¹ 1322234.00n ± ∞ ¹ -99.77% (p=0.008 n=5) 80.94n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Easy1/16-4 1.712n ± ∞ ¹ 940.700n ± ∞ ¹ +54847.43% (p=0.008 n=5) 82.050n ± ∞ ¹ +4692.64% (p=0.008 n=5) +MatchParallel/Easy1/32-4 18.04n ± ∞ ¹ 944.10n ± ∞ ¹ +5133.37% (p=0.008 n=5) 81.89n ± ∞ ¹ +353.94% (p=0.008 n=5) +MatchParallel/Easy1/1K-4 256.50n ± ∞ ¹ 1007.00n ± ∞ ¹ +292.59% (p=0.008 n=5) 81.64n ± ∞ ¹ -68.17% (p=0.008 n=5) +MatchParallel/Easy1/32K-4 11781.00n ± ∞ ¹ 1424.00n ± ∞ ¹ -87.91% (p=0.008 n=5) 81.45n ± ∞ ¹ -99.31% (p=0.008 n=5) +MatchParallel/Easy1/1M-4 407922.00n ± ∞ ¹ 41413.00n ± ∞ ¹ -89.85% (p=0.008 n=5) 81.57n ± ∞ ¹ -99.98% (p=0.008 n=5) +MatchParallel/Easy1/32M-4 13077618.00n ± ∞ ¹ 1326004.00n ± ∞ ¹ -89.86% (p=0.008 n=5) 81.48n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Medium/16-4 1.719n ± ∞ ¹ 937.100n ± ∞ ¹ +54414.25% (p=0.008 n=5) 79.930n ± ∞ ¹ +4549.80% (p=0.008 n=5) +MatchParallel/Medium/32-4 284.90n ± ∞ ¹ 948.90n ± ∞ ¹ +233.06% (p=0.008 n=5) 79.97n ± ∞ ¹ -71.93% (p=0.008 n=5) +MatchParallel/Medium/1K-4 9223.00n ± ∞ ¹ 1003.00n ± ∞ ¹ -89.13% (p=0.008 n=5) 80.01n ± ∞ ¹ -99.13% (p=0.008 n=5) +MatchParallel/Medium/32K-4 469468.00n ± ∞ ¹ 1418.00n ± ∞ ¹ -99.70% (p=0.008 n=5) 79.45n ± ∞ ¹ -99.98% (p=0.008 n=5) +MatchParallel/Medium/1M-4 14414208.00n ± ∞ ¹ 41372.00n ± ∞ ¹ -99.71% (p=0.008 n=5) 80.16n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Medium/32M-4 571771553.00n ± ∞ ¹ 1320563.00n ± ∞ ¹ -99.77% (p=0.008 n=5) 79.68n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Hard/16-4 1.717n ± ∞ ¹ 940.800n ± ∞ ¹ +54693.24% (p=0.008 n=5) 81.440n ± ∞ ¹ +4643.16% (p=0.008 n=5) +MatchParallel/Hard/32-4 487.00n ± ∞ ¹ 949.10n ± ∞ ¹ +94.89% (p=0.008 n=5) 81.31n ± ∞ ¹ -83.30% (p=0.008 n=5) +MatchParallel/Hard/1K-4 14814.00n ± ∞ ¹ 1002.00n ± ∞ ¹ -93.24% (p=0.008 n=5) 81.13n ± ∞ ¹ -99.45% (p=0.008 n=5) +MatchParallel/Hard/32K-4 685271.00n ± ∞ ¹ 1423.00n ± ∞ ¹ -99.79% (p=0.008 n=5) 81.37n ± ∞ ¹ -99.99% (p=0.008 n=5) +MatchParallel/Hard/1M-4 21979040.00n ± ∞ ¹ 41376.00n ± ∞ ¹ -99.81% (p=0.008 n=5) 81.13n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Hard/32M-4 1382894393.00n ± ∞ ¹ 1321072.00n ± ∞ ¹ -99.90% (p=0.008 n=5) 81.32n ± ∞ ¹ -100.00% (p=0.008 n=5) +MatchParallel/Hard1/16-4 1303.00n ± ∞ ¹ 1020.00n ± ∞ ¹ -21.72% (p=0.008 n=5) 86.51n ± ∞ ¹ -93.36% (p=0.008 n=5) +MatchParallel/Hard1/32-4 2526.00n ± ∞ ¹ 1094.00n ± ∞ ¹ -56.69% (p=0.008 n=5) 97.66n ± ∞ ¹ -96.13% (p=0.008 n=5) +MatchParallel/Hard1/1K-4 77806.0n ± ∞ ¹ 3413.0n ± ∞ ¹ -95.61% (p=0.008 n=5) 633.1n ± ∞ ¹ -99.19% (p=0.008 n=5) +MatchParallel/Hard1/32K-4 3519.23µ ± ∞ ¹ 97.97µ ± ∞ ¹ -97.22% (p=0.008 n=5) 17.12µ ± ∞ ¹ -99.51% (p=0.008 n=5) +MatchParallel/Hard1/1M-4 121966.5µ ± ∞ ¹ 3122.6µ ± ∞ ¹ -97.44% (p=0.008 n=5) 517.1µ ± ∞ ¹ -99.58% (p=0.008 n=5) +MatchParallel/Hard1/32M-4 6725.29m ± ∞ ¹ 100.80m ± ∞ ¹ -98.50% (p=0.008 n=5) 16.86m ± ∞ ¹ -99.75% (p=0.008 n=5) +``` + +Most benchmarks from the standard library are similar to `Find`, testing simple expressions with small input. +In all of these, the standard library performs much better. To reiterate the guidance at the top of this README, +if you only use simple expressions with small input, you should not use this library. + +The compilation benchmarks show that re2 is much slower to compile expressions than the standard +library - this is more than just the overhead of foreign function invocation. This likely results +in the improved performance at runtime in other cases. Because memory allocated in Wasm or cgo is +essentially "off-heap", it is difficult to measure allocation overhead compared to standard library. +More investigation needs to be done, but we expect the memory overhead for all approaches to be +similar. + +The match benchmarks show the performance tradeoffs for complexity vs input size. We see the standard +library perform the best with low complexity and size, but for high complexity or high input size, +go-re2 with WebAssembly outperforms, often significantly. Notable is `Hard1`, where even on the smallest +size this library outperforms. The expression is `ABCD|CDEF|EFGH|GHIJ|IJKL|KLMN|MNOP|OPQR|QRST|STUV|UVWX|WXYZ`, +a simple OR of literals - re2 has the concept of regex sets and likely is able to optimize this in a +special way. The CoreRuleSet contains many expressions of a form like this - this possibly indicates good +performance in real world use cases. + +[1]: https://pkg.go.dev/regexp +[2]: https://github.com/google/re2 +[3]: https://wazero.io +[4]: https://github.com/wasilibs/go-re2/actions/workflows/bench.yaml +[5]: https://github.com/coreruleset/coreruleset +[6]: https://github.com/corazawaf/coraza +[8]: https://www.msys2.org/ +[9]: https://brew.sh/ +[10]: https://github.com/corazawaf/coraza-wasilibs diff --git a/vendor/github.com/wasilibs/go-re2/go-re2.code-workspace b/vendor/github.com/wasilibs/go-re2/go-re2.code-workspace new file mode 100644 index 00000000..7e006f3a --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/go-re2.code-workspace @@ -0,0 +1,24 @@ +{ + "folders": [ + { + "name": "/", + "path": "." + } + ], + "extensions": { + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] + }, + "settings": { + "editor.formatOnSave": true, + "editor.tabSize": 2, + "eslint.workingDirectories": [{ "mode": "auto" }], + "go.lintFlags": ["--fix"], + "go.lintTool": "golangci-lint", + "gopls": { + "formatting.gofumpt": true + }, + "[yaml]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } + } +} diff --git a/vendor/github.com/wasilibs/go-re2/go.work b/vendor/github.com/wasilibs/go-re2/go.work new file mode 100644 index 00000000..3879542e --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/go.work @@ -0,0 +1,8 @@ +go 1.22.5 + +use ( + . + ./build + ./internal/e2e + ./wafbench +) diff --git a/vendor/github.com/wasilibs/go-re2/internal/cre2/NOTICE.txt b/vendor/github.com/wasilibs/go-re2/internal/cre2/NOTICE.txt new file mode 100644 index 00000000..799a2d97 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/cre2/NOTICE.txt @@ -0,0 +1,32 @@ +cre2 source code copied from https://github.com/marcomaggi/cre2 + +Copyright (c) 2012, 2013, 2015-2017, 2019 Marco Maggi
+Copyright (c) 2011 Keegan McAllister
+All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the author nor the names of his contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.cpp b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.cpp new file mode 100644 index 00000000..fa4dee70 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.cpp @@ -0,0 +1,719 @@ +//go:build tinygo.wasm || re2_cgo + +/* + Source file for CRE2, a C language wrapper for RE2: a regular + expressions library by Google. + + Copyright (c) 2012, 2016, 2019 Marco Maggi + Copyright (c) 2011 Keegan McAllister + All rights reserved. + + For the license notice see the COPYING file. +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include "cre2.h" + +#include +#include +#include + + +/** -------------------------------------------------------------------- + ** Options objects. + ** ----------------------------------------------------------------- */ + +/* Cast the pointer argument "opt" to a pointer of type + "RE2::Options*". */ +#define TO_OPT(opt) (reinterpret_cast(opt)) + +cre2_options_t * +cre2_opt_new(void) +/* Allocate and return a new options object. */ +{ + // FIXME: is this use of "nothrow" good to avoid raising exceptions + // when memory allocation fails and to return NULL instead? + return reinterpret_cast(new (std::nothrow) RE2::Options()); +} +void +cre2_opt_delete (cre2_options_t *opt) +/* Finalise an options object. */ +{ + delete TO_OPT(opt); +} + +/* Set or unset option flags in an options object. */ +#define OPT_BOOL(name) \ + void cre2_opt_set_##name (cre2_options_t *opt, int flag) \ + { \ + TO_OPT(opt)->set_##name(bool(flag)); \ + } \ + int cre2_opt_##name (cre2_options_t *opt) \ + { \ + return TO_OPT(opt)->name(); \ + } +OPT_BOOL(posix_syntax) +OPT_BOOL(longest_match) +OPT_BOOL(log_errors) +OPT_BOOL(literal) +OPT_BOOL(never_nl) +OPT_BOOL(dot_nl) +OPT_BOOL(never_capture) +OPT_BOOL(case_sensitive) +OPT_BOOL(perl_classes) +OPT_BOOL(word_boundary) +OPT_BOOL(one_line) +#undef OPT_BOOL + +void +cre2_opt_set_encoding (cre2_options_t *opt, cre2_encoding_t enc) +/* Select the encoding in an options object. */ +{ + switch (enc) { + case CRE2_UTF8: + TO_OPT(opt)->set_encoding(RE2::Options::EncodingUTF8); + break; + case CRE2_Latin1: + TO_OPT(opt)->set_encoding(RE2::Options::EncodingLatin1); + break; + default: + fprintf(stderr, "CRE2: internal error: unknown encoding %d\n", enc); + exit(EXIT_FAILURE); + } +} +cre2_encoding_t +cre2_opt_encoding (cre2_options_t *opt) +{ + RE2::Options::Encoding E = TO_OPT(opt)->encoding(); + switch (E) { + case RE2::Options::EncodingUTF8: + return CRE2_UTF8; + case RE2::Options::EncodingLatin1: + return CRE2_Latin1; + default: + return CRE2_UNKNOWN; + } +} +void +cre2_opt_set_max_mem (cre2_options_t *opt, int64_t m) +/* Configure the maximum amount of memory in an options object. */ +{ + TO_OPT(opt)->set_max_mem(m); +} +int64_t +cre2_opt_max_mem (cre2_options_t *opt) +{ + return TO_OPT(opt)->max_mem(); +} +void +cre2_opt_set_latin1_encoding(cre2_options_t *opt) +{ + TO_OPT(opt)->set_encoding(RE2::Options::EncodingLatin1); +} + + +/** -------------------------------------------------------------------- + ** Precompiled regular expressions objects. + ** ----------------------------------------------------------------- */ + +#define TO_RE2(re) (reinterpret_cast(re)) +#define TO_CONST_RE2(re) (reinterpret_cast(re)) + +cre2_regexp_t * +cre2_new (const char *pattern, int pattern_len, const cre2_options_t *opt) +{ + re2::StringPiece pattern_re2(pattern, pattern_len); + if (opt) { + // FIXME: is this use of "nothrow" enough to avoid raising + // exceptions when memory allocation fails and to return NULL + // instead? + return reinterpret_cast + (new (std::nothrow) RE2(pattern_re2, *reinterpret_cast(opt))); + } else { + return reinterpret_cast (new (std::nothrow) RE2(pattern_re2)); + } +} +void +cre2_delete (cre2_regexp_t *re) +{ + delete TO_RE2(re); +} +const char * +cre2_pattern (const cre2_regexp_t *re) +{ + return TO_CONST_RE2(re)->pattern().c_str(); +} +int +cre2_error_code (const cre2_regexp_t *re) +{ + return int(TO_CONST_RE2(re)->error_code()); +} +const char * +cre2_error_string (const cre2_regexp_t *re) +{ + return TO_CONST_RE2(re)->error().c_str(); +} +const char * +cre2_error_arg (const cre2_regexp_t *re) +{ + return TO_CONST_RE2(re)->error_arg().c_str(); +} +int +cre2_num_capturing_groups (const cre2_regexp_t *re) +{ + return TO_CONST_RE2(re)->NumberOfCapturingGroups(); +} +int +cre2_find_named_capturing_groups (const cre2_regexp_t *re, const char* group_name) +{ + const std::map& m = TO_CONST_RE2(re)->NamedCapturingGroups(); + std::map::const_iterator it = m.find(group_name); + + if(it != m.end()) { + return it->second; + } + else { + return -1; + } +} + +int +cre2_program_size (const cre2_regexp_t *re) +{ + return TO_CONST_RE2(re)->ProgramSize(); +} + + +/** -------------------------------------------------------------------- + ** Named capture group iteration. + ** ----------------------------------------------------------------- */ + +struct cre2_named_groups_iter_t +{ + const RE2 * re; + std::map::const_iterator it; +}; + +cre2_named_groups_iter_t * +cre2_named_groups_iter_new(const cre2_regexp_t *re) +{ + cre2_named_groups_iter_t * iter = new (std::nothrow)cre2_named_groups_iter_t; + iter->re = TO_CONST_RE2(re); + iter->it = iter->re->CapturingGroupNames().begin(); + return iter; +} +bool +cre2_named_groups_iter_next(cre2_named_groups_iter_t* iter, const char ** name, int *index) +{ + if (iter->it == iter->re->CapturingGroupNames().end()) { + *name = NULL; + *index = -1; + return false; + } else { + *index = iter->it->first; + *name = iter->it->second.c_str(); + ++iter->it; + return true; + } +} +void +cre2_named_groups_iter_delete(cre2_named_groups_iter_t *iter) +{ + delete iter; +} + + +/** -------------------------------------------------------------------- + ** Matching with precompiled regular expressions objects. + ** ----------------------------------------------------------------- */ + +static RE2::Anchor +to_cre2_anchor(cre2_anchor_t anchor) +{ + RE2::Anchor anchor_re2 = RE2::UNANCHORED; + switch (anchor) { + case CRE2_ANCHOR_START: + anchor_re2 = RE2::ANCHOR_START; + break; + case CRE2_ANCHOR_BOTH: + anchor_re2 = RE2::ANCHOR_BOTH; + break; + case CRE2_UNANCHORED: + break; + } + return anchor_re2; +} + +int +cre2_match (const cre2_regexp_t *re , const char *text, + int textlen, int startpos, int endpos, cre2_anchor_t anchor, + cre2_string_t *match, int nmatch) +{ + re2::StringPiece text_re2(text, textlen); + std::vector match_re2(nmatch); + RE2::Anchor anchor_re2 = to_cre2_anchor(anchor); + bool retval; // 0 for no match + // 1 for successful matching + retval = TO_CONST_RE2(re)->Match(text_re2, startpos, endpos, anchor_re2, match_re2.data(), nmatch); + if (retval) { + for (int i=0; idata, text->length); \ + std::vector strv(nmatch); \ + std::vector argv(nmatch); \ + std::vector args(nmatch); \ + bool retval; \ + for (int i=0; idata, text->length); \ + std::vector strv(nmatch); \ + std::vector argv(nmatch); \ + std::vector args(nmatch); \ + bool retval; \ + for (int i=0; idata = input.data(); \ + text->length = input.length(); \ + for (int i=0; idata, text->length); \ + std::vector strv(nmatch); \ + std::vector argv(nmatch); \ + std::vector args(nmatch); \ + bool retval; \ + for (int i=0; idata, text->length); \ + std::vector strv(nmatch); \ + std::vector argv(nmatch); \ + std::vector args(nmatch); \ + bool retval; \ + for (int i=0; idata = input.data(); \ + text->length = input.length(); \ + for (int i=0; idata, text_and_target->length); + re2::StringPiece R(rewrite->data, rewrite->length); + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = RE2::Replace(&S, pattern, R); + text_and_target->length = S.length(); + buffer = (char *)malloc(1+text_and_target->length); + if (buffer) { + S.copy(buffer, text_and_target->length); + buffer[text_and_target->length] = '\0'; + text_and_target->data = buffer; + } else + return -1; + return int(retval); +} +int +cre2_replace_re (cre2_regexp_t * rex, cre2_string_t * text_and_target, cre2_string_t * rewrite) +{ + std::string S(text_and_target->data, text_and_target->length); + re2::StringPiece R(rewrite->data, rewrite->length); + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = RE2::Replace(&S, *TO_RE2(rex), R); + text_and_target->length = S.length(); + buffer = (char *)malloc(1+text_and_target->length); + if (buffer) { + S.copy(buffer, text_and_target->length); + buffer[text_and_target->length] = '\0'; + text_and_target->data = buffer; + } else + return -1; + return int(retval); +} + +/* ------------------------------------------------------------------ */ + +int +cre2_global_replace (const char * pattern, cre2_string_t * text_and_target, cre2_string_t * rewrite) +{ + std::string S(text_and_target->data, text_and_target->length); + re2::StringPiece R(rewrite->data, rewrite->length); + char * buffer; /* this exists to make GCC shut up about const */ + int retval; + retval = RE2::GlobalReplace(&S, pattern, R); + text_and_target->length = S.length(); + buffer = (char *)malloc(1+text_and_target->length); + if (buffer) { + S.copy(buffer, text_and_target->length); + buffer[text_and_target->length] = '\0'; + text_and_target->data = buffer; + } else + return -1; + return int(retval); +} +int +cre2_global_replace_re (cre2_regexp_t * rex, cre2_string_t * text_and_target, cre2_string_t * rewrite) +{ + std::string S(text_and_target->data, text_and_target->length); + re2::StringPiece R(rewrite->data, rewrite->length); + char * buffer; /* this exists to make GCC shut up about const */ + int retval; + retval = RE2::GlobalReplace(&S, *TO_RE2(rex), R); + text_and_target->length = S.length(); + buffer = (char *)malloc(1+text_and_target->length); + if (buffer) { + S.copy(buffer, text_and_target->length); + buffer[text_and_target->length] = '\0'; + text_and_target->data = buffer; + } else + return -1; + return retval; +} + +/* ------------------------------------------------------------------ */ + +int +cre2_extract (const char * pattern, cre2_string_t * text, + cre2_string_t * rewrite, cre2_string_t * target) +{ + re2::StringPiece T(text->data, text->length); + re2::StringPiece R(rewrite->data, rewrite->length); + std::string O; + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = RE2::Extract(T, pattern, R, &O); + target->length = O.length(); + buffer = (char *)malloc(1+target->length); + if (buffer) { + O.copy(buffer, target->length); + buffer[target->length] = '\0'; + target->data = buffer; + } else + return -1; + return int(retval); +} +int +cre2_extract_re (cre2_regexp_t * rex, cre2_string_t * text, + cre2_string_t * rewrite, cre2_string_t * target) +{ + re2::StringPiece T(text->data, text->length); + re2::StringPiece R(rewrite->data, rewrite->length); + std::string O; + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = RE2::Extract(T, *TO_RE2(rex), R, &O); + target->length = O.length(); + buffer = (char *)malloc(1+target->length); + if (buffer) { + O.copy(buffer, target->length); + buffer[target->length] = '\0'; + target->data = buffer; + } else + return -1; + return int(retval); +} + +/* ------------------------------------------------------------------ */ + +int +cre2_quote_meta (cre2_string_t * quoted, cre2_string_t * original) +{ + re2::StringPiece O(original->data, original->length); + std::string Q; + char * buffer; /* this exists to make GCC shut up about const */ + Q = RE2::QuoteMeta(O); + quoted->length = Q.length(); + buffer = (char *)malloc(1+quoted->length); + if (buffer) { + Q.copy(buffer, quoted->length); + buffer[quoted->length] = '\0'; + quoted->data = buffer; + return 0; + } else + return -1; +} +int +cre2_possible_match_range (cre2_regexp_t * rex, + cre2_string_t * min_, cre2_string_t * max_, int maxlen) +{ + std::string MIN, MAX; + cre2_string_t min, max; + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = TO_RE2(rex)->PossibleMatchRange(&MIN, &MAX, maxlen); + if (retval) { + /* copy MIN */ + min.length = MIN.length(); + buffer = (char *)malloc(1+min.length); + if (buffer) { + MIN.copy(buffer, min.length); + buffer[min.length] = '\0'; + min.data = buffer; + } else + return -1; + /* copy MAX */ + max.length = MAX.length(); + buffer = (char *)malloc(1+max.length); + if (buffer) { + MAX.copy(buffer, max.length); + buffer[max.length] = '\0'; + max.data = buffer; + } else { + free((void *)min.data); + min.data = NULL; + return -1; + } + *min_ = min; + *max_ = max; + return 1; + } else + return 0; +} +int +cre2_check_rewrite_string (cre2_regexp_t * rex, cre2_string_t * rewrite, cre2_string_t * errmsg) +{ + re2::StringPiece R(rewrite->data, rewrite->length); + std::string E; + char * buffer; /* this exists to make GCC shut up about const */ + bool retval; + retval = TO_RE2(rex)->CheckRewriteString(R, &E); + if (retval) { + errmsg->data = NULL; + errmsg->length = 0; + return 1; + } else { + errmsg->length = E.length(); + buffer = (char *)malloc(1+errmsg->length); + if (buffer) { + E.copy(buffer, errmsg->length); + buffer[errmsg->length] = '\0'; + errmsg->data = buffer; + } else + return -1; + return 0; + } +} + + +/** -------------------------------------------------------------------- + ** Set match. + ** ----------------------------------------------------------------- */ + +#define TO_RE2_SET(set) (reinterpret_cast(set)) +#define TO_CRE2_SET(set) (reinterpret_cast(set)) + +// RE2::Set constructor and destructor +cre2_set* +cre2_set_new(cre2_options_t *opt, cre2_anchor_t anchor) +{ + return TO_CRE2_SET(new (std::nothrow) RE2::Set(*TO_OPT(opt), to_cre2_anchor(anchor))); +} + +void +cre2_set_delete(cre2_set *set) +{ + delete TO_RE2_SET(set); +} + +static char* ok = "ok"; + +// Add a regex to the set. If invalid: return error message that must be freed. If valid, return "ok". +char* +cre2_set_add(cre2_set *set, const char *pattern, size_t pattern_len) +{ + RE2::Set *s = TO_RE2_SET(set); + re2::StringPiece regex(pattern, static_cast(pattern_len)); + std::string err; + int regex_index = s->Add(regex, &err); + if (regex_index >= 0) { + return ok; + } + size_t len = err.size() + 1; + void* msg = malloc(len); + if (msg == NULL) { + return NULL; + } + memcpy(msg, err.c_str(), len); + return (char*)msg; +} + +// Add pattern without NULL byte. Don't store error message. +int +cre2_set_add_simple(cre2_set *set, const char *pattern) +{ + RE2::Set *s = TO_RE2_SET(set); + re2::StringPiece regex(pattern, static_cast(strlen(pattern))); + return s->Add(regex, NULL); +} + + +// Compile the regex set into a DFA. Must be called after add and before match. +int +cre2_set_compile(cre2_set *set) +{ + RE2::Set *s = TO_RE2_SET(set); + return static_cast(s->Compile()); +} + +// Match the set of regex against text and store indices of matching regexes in match array. +// Returns the number of regexes which match. +size_t +cre2_set_match(cre2_set *set, const char *text, size_t text_len, int *match, size_t match_len) +{ + RE2::Set *s = TO_RE2_SET(set); + re2::StringPiece data(text, static_cast(text_len)); + std::vector v; + bool does_match = s->Match(data, &v); + if (!does_match) { + return 0; + } + size_t min = v.size() < match_len ? v.size() : match_len; + std::copy(v.begin(), v.begin() + min, match); + return v.size(); +} + +/* end of file */ diff --git a/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.go b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.go new file mode 100644 index 00000000..b5f0190f --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.go @@ -0,0 +1,168 @@ +//go:build tinygo.wasm || re2_cgo + +package cre2 + +/* +#include +#include + +void* cre2_new(void* pattern, int pattern_len, void* opts); +void cre2_delete(void* re); +int cre2_error_code(void* re); +void* cre2_error_arg(void* re); +int cre2_match(void* re, void* text, int text_len, int startpos, int endpos, int anchor, void* match_arr, int nmatch); +int cre2_find_and_consume_re(void* re, void* text, void* match, int nmatch); +int cre2_global_replace_re(void* re, void* textAndTarget, void* rewrite); +int cre2_num_capturing_groups(void* re); +void* cre2_named_groups_iter_new(void* re); +bool cre2_named_groups_iter_next(void* iter, void** name, int* index); +void cre2_named_groups_iter_delete(void* iter); + +void* cre2_opt_new(); +void cre2_opt_delete(void* opts); +void cre2_opt_set_log_errors(void* opt, int flag); +void cre2_opt_set_longest_match(void* opt, int flag); +void cre2_opt_set_posix_syntax(void* opt, int flag); +void cre2_opt_set_case_sensitive(void* opt, int flag); +void cre2_opt_set_latin1_encoding(void* opt); +void cre2_opt_set_max_mem(void* opt, int64_t size); +void* cre2_set_new(void* opt, int anchor); +void* cre2_set_add(void* set, void* pattern, int pattern_len); +int cre2_set_compile(void* set); +int cre2_set_match(void* set, void* text, int text_len, void* match, int nmatch); +void cre2_set_delete(void* set); + +void* malloc(size_t size); +void free(void* ptr); +*/ +import "C" + +import ( + "unsafe" +) + +func New(patternPtr unsafe.Pointer, patternLen int, opts unsafe.Pointer) unsafe.Pointer { + return C.cre2_new(patternPtr, C.int(patternLen), opts) +} + +func Delete(ptr unsafe.Pointer) { + C.cre2_delete(ptr) +} + +func ErrorCode(rePtr unsafe.Pointer) int { + return int(C.cre2_error_code(rePtr)) +} + +func ErrorArg(rePtr unsafe.Pointer) unsafe.Pointer { + return C.cre2_error_arg(rePtr) +} + +func FindAndConsume(rePtr unsafe.Pointer, textPtr unsafe.Pointer, matchPtr unsafe.Pointer, nMatch int) bool { + return C.cre2_find_and_consume_re(rePtr, textPtr, matchPtr, C.int(nMatch)) > 0 +} + +func GlobalReplace(rePtr unsafe.Pointer, textAndTargetPtr unsafe.Pointer, rewritePtr unsafe.Pointer) bool { + return C.cre2_global_replace_re(rePtr, textAndTargetPtr, rewritePtr) > 0 +} + +func Match(rePtr unsafe.Pointer, textPtr unsafe.Pointer, textLen int, startPos int, endPos int, anchor int, matchArr unsafe.Pointer, nMatch int) bool { + return C.cre2_match(rePtr, textPtr, C.int(textLen), C.int(startPos), C.int(endPos), C.int(anchor), matchArr, C.int(nMatch)) > 0 +} + +func NamedGroupsIterNew(rePtr unsafe.Pointer) unsafe.Pointer { + return C.cre2_named_groups_iter_new(rePtr) +} + +func NamedGroupsIterNext(iterPtr unsafe.Pointer, namePtr *unsafe.Pointer, indexPtr *int) bool { + cIndex := C.int(0) + res := C.cre2_named_groups_iter_next(iterPtr, namePtr, &cIndex) + *indexPtr = int(cIndex) + return bool(res) +} + +func NamedGroupsIterDelete(iterPtr unsafe.Pointer) { + C.cre2_named_groups_iter_delete(iterPtr) +} + +func NumCapturingGroups(rePtr unsafe.Pointer) int { + return int(C.cre2_num_capturing_groups(rePtr)) +} + +func NewOpt() unsafe.Pointer { + return C.cre2_opt_new() +} + +func DeleteOpt(opt unsafe.Pointer) { + C.cre2_opt_delete(opt) +} + +func OptSetLogErrors(opt unsafe.Pointer, flag bool) { + C.cre2_opt_set_log_errors(opt, cFlag(flag)) +} + +func OptSetLongestMatch(opt unsafe.Pointer, flag bool) { + C.cre2_opt_set_longest_match(opt, cFlag(flag)) +} + +func OptSetPosixSyntax(opt unsafe.Pointer, flag bool) { + C.cre2_opt_set_posix_syntax(opt, cFlag(flag)) +} + +func OptSetCaseSensitive(opt unsafe.Pointer, flag bool) { + C.cre2_opt_set_case_sensitive(opt, cFlag(flag)) +} + +func OptSetLatin1Encoding(opt unsafe.Pointer) { + C.cre2_opt_set_latin1_encoding(opt) +} + +func OptSetMaxMem(opt unsafe.Pointer, size int) { + C.cre2_opt_set_max_mem(opt, C.int64_t(size)) +} + +func NewSet(opt unsafe.Pointer, anchor int) unsafe.Pointer { + return C.cre2_set_new(opt, C.int(anchor)) +} + +func SetAdd(set unsafe.Pointer, patternPtr unsafe.Pointer, patternLen int) unsafe.Pointer { + return C.cre2_set_add(set, patternPtr, C.int(patternLen)) +} + +func SetCompile(set unsafe.Pointer) int { + return int(C.cre2_set_compile(set)) +} + +func SetMatch(set unsafe.Pointer, textPtr unsafe.Pointer, textLen int, match unsafe.Pointer, nMatch int) int { + return int(C.cre2_set_match(set, textPtr, C.int(textLen), match, C.int(nMatch))) +} + +func SetDelete(ptr unsafe.Pointer) { + C.cre2_set_delete(ptr) +} + +func Malloc(size int) unsafe.Pointer { + return C.malloc(C.size_t(size)) +} + +func Free(ptr unsafe.Pointer) { + C.free(ptr) +} + +func CopyCBytes(sPtr unsafe.Pointer, sLen int) []byte { + return C.GoBytes(sPtr, C.int(sLen)) +} + +func CopyCString(sPtr unsafe.Pointer) string { + return C.GoString((*C.char)(sPtr)) +} + +func CopyCStringN(sPtr unsafe.Pointer, n int) string { + return C.GoStringN((*C.char)(sPtr), C.int(n)) +} + +func cFlag(flag bool) C.int { + if flag { + return C.int(1) + } + return C.int(0) +} diff --git a/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.h b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.h new file mode 100644 index 00000000..e5de1718 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2.h @@ -0,0 +1,343 @@ +//go:build tinygo.wasm || re2_cgo + +/* + Header file for CRE2, a C language wrapper for RE2: a regular + expressions library by Google. + + Copyright (c) 2012, 2015 Marco Maggi + Copyright (c) 2011 Keegan McAllister + All rights reserved. + + For the license notice see the COPYING file. +*/ + +#ifndef CRE2_H +#define CRE2_H 1 + + +/** -------------------------------------------------------------------- + ** Headers. + ** ----------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +#include + +#ifndef cre2_decl +# define cre2_decl extern +#endif + + +/** -------------------------------------------------------------------- + ** Regular expressions configuration options. + ** ----------------------------------------------------------------- */ + +typedef void cre2_options_t; + +typedef enum cre2_encoding_t { + CRE2_UNKNOWN = 0, /* should never happen */ + CRE2_UTF8 = 1, + CRE2_Latin1 = 2 +} cre2_encoding_t; + +cre2_decl cre2_options_t *cre2_opt_new (void); +cre2_decl void cre2_opt_delete (cre2_options_t *opt); + +cre2_decl void cre2_opt_set_posix_syntax (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_longest_match (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_log_errors (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_literal (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_never_nl (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_dot_nl (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_never_capture (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_case_sensitive (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_perl_classes (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_word_boundary (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_one_line (cre2_options_t *opt, int flag); +cre2_decl void cre2_opt_set_max_mem (cre2_options_t *opt, int64_t m); +cre2_decl void cre2_opt_set_encoding (cre2_options_t *opt, cre2_encoding_t enc); +cre2_decl void cre2_opt_set_latin1_encoding (cre2_options_t *opt); + +cre2_decl int cre2_opt_posix_syntax (cre2_options_t *opt); +cre2_decl int cre2_opt_longest_match (cre2_options_t *opt); +cre2_decl int cre2_opt_log_errors (cre2_options_t *opt); +cre2_decl int cre2_opt_literal (cre2_options_t *opt); +cre2_decl int cre2_opt_never_nl (cre2_options_t *opt); +cre2_decl int cre2_opt_dot_nl (cre2_options_t *opt); +cre2_decl int cre2_opt_never_capture (cre2_options_t *opt); +cre2_decl int cre2_opt_case_sensitive (cre2_options_t *opt); +cre2_decl int cre2_opt_perl_classes (cre2_options_t *opt); +cre2_decl int cre2_opt_word_boundary (cre2_options_t *opt); +cre2_decl int cre2_opt_one_line (cre2_options_t *opt); +cre2_decl int64_t cre2_opt_max_mem (cre2_options_t *opt); +cre2_decl cre2_encoding_t cre2_opt_encoding (cre2_options_t *opt); + + +/** -------------------------------------------------------------------- + ** Precompiled regular expressions. + ** ----------------------------------------------------------------- */ + +typedef struct cre2_string_t { + const char * data; + int length; +} cre2_string_t; + +typedef void cre2_regexp_t; + +typedef struct cre2_named_groups_iter_t cre2_named_groups_iter_t; + +/* This definition must be kept in sync with the definition of "enum + ErrorCode" in the file "re2.h" of the original RE2 distribution. */ +typedef enum cre2_error_code_t { + CRE2_NO_ERROR = 0, + CRE2_ERROR_INTERNAL, /* unexpected error */ + /* parse errors */ + CRE2_ERROR_BAD_ESCAPE, /* bad escape sequence */ + CRE2_ERROR_BAD_CHAR_CLASS, /* bad character class */ + CRE2_ERROR_BAD_CHAR_RANGE, /* bad character class range */ + CRE2_ERROR_MISSING_BRACKET, /* missing closing ] */ + CRE2_ERROR_MISSING_PAREN, /* missing closing ) */ + CRE2_ERROR_TRAILING_BACKSLASH,/* trailing \ at end of regexp */ + CRE2_ERROR_REPEAT_ARGUMENT, /* repeat argument missing, e.g. "*" */ + CRE2_ERROR_REPEAT_SIZE, /* bad repetition argument */ + CRE2_ERROR_REPEAT_OP, /* bad repetition operator */ + CRE2_ERROR_BAD_PERL_OP, /* bad perl operator */ + CRE2_ERROR_BAD_UTF8, /* invalid UTF-8 in regexp */ + CRE2_ERROR_BAD_NAMED_CAPTURE, /* bad named capture group */ + CRE2_ERROR_PATTERN_TOO_LARGE, /* pattern too large (compile failed) */ +} cre2_error_code_t; + +/* construction and destruction */ +cre2_decl cre2_regexp_t * cre2_new (const char *pattern, int pattern_len, + const cre2_options_t *opt); +cre2_decl void cre2_delete (cre2_regexp_t *re); + +/* regular expression inspection */ +cre2_decl const char * cre2_pattern (const cre2_regexp_t *re); +cre2_decl int cre2_error_code (const cre2_regexp_t *re); +cre2_decl int cre2_num_capturing_groups (const cre2_regexp_t *re); +cre2_decl int cre2_program_size (const cre2_regexp_t *re); + +/* named capture information */ +cre2_decl int cre2_find_named_capturing_groups (const cre2_regexp_t *re, const char *name); +cre2_decl cre2_named_groups_iter_t * cre2_named_groups_iter_new(const cre2_regexp_t *re); +cre2_decl bool cre2_named_groups_iter_next(cre2_named_groups_iter_t* iter, const char ** name, int *index); +cre2_decl void cre2_named_groups_iter_delete(cre2_named_groups_iter_t *iter); + +/* invalidated by further re use */ +cre2_decl const char *cre2_error_string(const cre2_regexp_t *re); +cre2_decl const char *cre2_error_arg(const cre2_regexp_t *re); + + +/** -------------------------------------------------------------------- + ** Main matching functions. + ** ----------------------------------------------------------------- */ + +typedef enum cre2_anchor_t { + CRE2_UNANCHORED = 1, + CRE2_ANCHOR_START = 2, + CRE2_ANCHOR_BOTH = 3 +} cre2_anchor_t; + +typedef struct cre2_range_t { + long start; /* inclusive start index for bytevector */ + long past; /* exclusive end index for bytevector */ +} cre2_range_t; + +cre2_decl int cre2_match (const cre2_regexp_t * re, + const char * text, int textlen, + int startpos, int endpos, cre2_anchor_t anchor, + cre2_string_t * match, int nmatch); + +cre2_decl int cre2_easy_match (const char * pattern, int pattern_len, + const char * text, int text_len, + cre2_string_t * match, int nmatch); + +cre2_decl void cre2_strings_to_ranges (const char * text, cre2_range_t * ranges, + cre2_string_t * strings, int nmatch); + + +/** -------------------------------------------------------------------- + ** Other matching functions. + ** ----------------------------------------------------------------- */ + +typedef int cre2_match_stringz_fun_t (const char * pattern, const cre2_string_t * text, + cre2_string_t * match, int nmatch); + +typedef int cre2_match_stringz2_fun_t (const char * pattern, cre2_string_t * text, + cre2_string_t * match, int nmatch); + +typedef int cre2_match_rex_fun_t (cre2_regexp_t * rex, const cre2_string_t * text, + cre2_string_t * match, int nmatch); + +typedef int cre2_match_rex2_fun_t (cre2_regexp_t * rex, cre2_string_t * text, + cre2_string_t * match, int nmatch); + +cre2_decl cre2_match_stringz_fun_t cre2_full_match; +cre2_decl cre2_match_stringz_fun_t cre2_partial_match; +cre2_decl cre2_match_stringz2_fun_t cre2_consume; +cre2_decl cre2_match_stringz2_fun_t cre2_find_and_consume; + +cre2_decl cre2_match_rex_fun_t cre2_full_match_re; +cre2_decl cre2_match_rex_fun_t cre2_partial_match_re; +cre2_decl cre2_match_rex2_fun_t cre2_consume_re; +cre2_decl cre2_match_rex2_fun_t cre2_find_and_consume_re; + + +/** -------------------------------------------------------------------- + ** Problematic functions. + ** ----------------------------------------------------------------- */ + +/* Match the text in the buffer "text_and_target" against the rex in + "pattern" or "rex". Mutate "text_and_target" so that it references a + malloc'ed buffer holding the original text in which the first, and + only the first, match is substituted with the text in "rewrite". + Numeric backslash sequences (\1 to \9) in "rewrite" are substituted + with the portions of text matching the corresponding parenthetical + subexpressions. + + Return 0 if no match, 1 if successful match, -1 if error allocating + memory. */ +cre2_decl int cre2_replace (const char * pattern, + cre2_string_t * text_and_target, + cre2_string_t * rewrite); +cre2_decl int cre2_replace_re (cre2_regexp_t * rex, + cre2_string_t * text_and_target, + cre2_string_t * rewrite); + +/* Match the text in the buffer "text_and_target" against the rex in + "pattern" or "rex". Mutate "text_and_target" so that it references a + malloc'ed buffer holding the original text in which the all the + matching substrings are substituted with the text in "rewrite". + Numeric backslash sequences (\1 to \9) in "rewrite" are substituted + with the portions of text matching the corresponding parenthetical + subexpressions. + + Return 0 if no match, positive integer representing the number of + substitutions performed if successful match, -1 if error allocating + memory. */ +cre2_decl int cre2_global_replace (const char * pattern, + cre2_string_t * text_and_target, + cre2_string_t * rewrite); +cre2_decl int cre2_global_replace_re (cre2_regexp_t * rex, + cre2_string_t * text_and_target, + cre2_string_t * rewrite); + +/* Match the text in the buffer "text" against the rex in "pattern" or + "rex". Mutate "target" so that it references a malloc'ed buffer + holding a copy of the text in "rewrite"; numeric backslash sequences + (\1 to \9) in "rewrite" are substituted with the portions of text + matching the corresponding parenthetical subexpressions. + + Non-matching text in "text" is ignored. + + Return 0 if no match, 1 if successful match, -1 if error allocating + memory. */ +cre2_decl int cre2_extract (const char * pattern, + cre2_string_t * text, + cre2_string_t * rewrite, + cre2_string_t * target); + +cre2_decl int cre2_extract_re (cre2_regexp_t * rex, + cre2_string_t * text, + cre2_string_t * rewrite, + cre2_string_t * target); + +/* ------------------------------------------------------------------ */ + +/* Allocate a zero-terminated malloc'ed buffer and fill it with the text + from "original" having all the regexp meta characters quoted with + single backslashes. Return 0 if successful, return -1 if an error + allocating memory occurs. */ +cre2_decl int cre2_quote_meta (cre2_string_t * quoted, cre2_string_t * original); + +/* Compute a "minimum" string and a "maximum" string matching the given + regular expression. The min and max can in some cases be arbitrarily + precise, so the caller gets to specify "maxlen" begin the maximum + desired length of string returned. + + Assuming the call returns successfully, any string S that is an + anchored match for this regexp satisfies: + + min <= S && S <= max. + + Note that this function will only consider the first copy of an + infinitely repeated element (i.e., any regexp element followed by a + '*' or '+' operator). Regexps with "{N}" constructions are not + affected, as those do not compile down to infinite repetitions. + + "min_" and "max_" are mutated to reference zero-terminated malloc'ed + buffers holding the min and max strings. + + Return 0 if failure, return 1 if successful, return -1 if an error + allocating memory occurs. */ +cre2_decl int cre2_possible_match_range (cre2_regexp_t * rex, + cre2_string_t * min_, cre2_string_t * max_, + int maxlen); + +/* Check that the given rewrite string is suitable for use with this + regular expression. It checks that: + + * The regular expression has enough parenthesized subexpressions to + satisfy all of the \N tokens in rewrite + + * The rewrite string doesn't have any syntax errors. E.g., '\' + followed by anything other than a digit or '\'. + + A true return value guarantees that the replace and extract functions + won't fail because of a bad rewrite string. + + In case of error: "errmsg" is mutated to reference a zero-terminated + malloc'ed string describing the problem. + + Return 1 if the string is correct, return 0 if the string is + incorrect, return -1 if an error occurred allocating memory. */ +cre2_decl int cre2_check_rewrite_string (cre2_regexp_t * rex, + cre2_string_t * rewrite, cre2_string_t * errmsg); + + +/** -------------------------------------------------------------------- + ** Set match. + ** ----------------------------------------------------------------- */ + +/* Struct used to represent an RE2::Set object. */ +struct cre2_set; +typedef struct cre2_set cre2_set; + +/* RE2::Set constructor */ +cre2_decl cre2_set *cre2_set_new(cre2_options_t *opt, cre2_anchor_t anchor); +/* RE2::Set destructor */ +cre2_decl void cre2_set_delete(cre2_set *set); + +// Add a regex to the set. If invalid: return error message that must be freed. If valid, return "ok". +cre2_decl char* cre2_set_add(cre2_set *set, const char *pattern, size_t pattern_len); + +/* Add pattern without NULL byte. Discard error message. + * Returns the index associated to this regex, -1 on error */ +cre2_decl int cre2_set_add_simple(cre2_set *set, const char *pattern); + +/* Compile the regex set into a DFA. Must be called after add and before match. + * Returns 1 on success, 0 on error */ +cre2_decl int cre2_set_compile(cre2_set *set); + +/* Match the set of regex against text and store indices of matching regexes in match array. + * Returns the number of regexes which match. */ +cre2_decl size_t cre2_set_match(cre2_set *set, const char *text, size_t text_len, + int *match, size_t match_len); + + +/** -------------------------------------------------------------------- + ** Done. + ** ----------------------------------------------------------------- */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* CRE2_H */ + +/* end of file */ diff --git a/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2_re2_cgo.go b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2_re2_cgo.go new file mode 100644 index 00000000..8f0e5dd8 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/cre2/cre2_re2_cgo.go @@ -0,0 +1,9 @@ +//go:build re2_cgo + +package cre2 + +/* +#cgo pkg-config: re2 +#cgo CXXFLAGS: -std=c++17 +*/ +import "C" diff --git a/vendor/github.com/wasilibs/go-re2/internal/re2.go b/vendor/github.com/wasilibs/go-re2/internal/re2.go new file mode 100644 index 00000000..f22373c0 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/re2.go @@ -0,0 +1,1043 @@ +package internal + +import ( + "bytes" + "fmt" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode" + "unicode/utf8" +) + +// Use same max size as regexp package. +// https://github.com/golang/go/blob/master/src/regexp/syntax/parse.go#L95 +const maxSize = 128 << 20 + +type Regexp struct { + ptr wasmPtr + + opts CompileOptions + + expr string + + numMatches int + groupNames []string + groupNamesOnce sync.Once + + abi *libre2ABI + + released uint32 +} + +// Copy returns a new Regexp object copied from re. +// Calling Longest on one copy does not affect another. +// +// Deprecated: In earlier releases, when using a Regexp in multiple goroutines, +// giving each goroutine its own copy helped to avoid lock contention. +// As of Go 1.12, using Copy is no longer necessary to avoid lock contention. +// Copy may still be appropriate if the reason for its use is to make +// two copies with different Longest settings. +func (re *Regexp) Copy() *Regexp { + // Recompiling is slower than this should be but for a deprecated method it + // is probably fine. The alternative would be to have reference counting to + // make sure regex is only deleted when the last reference is gone. + + // Recompiling regex, no chance of err so don't bother checking it. + c, _ := Compile(re.expr, re.opts) + return c +} + +type CompileOptions struct { + Posix bool + Longest bool + CaseInsensitive bool + Latin1 bool +} + +func Compile(expr string, opts CompileOptions) (*Regexp, error) { + abi := newABI() + alloc := abi.startOperation(len(expr) + 2) + defer abi.endOperation(alloc) + + cs := alloc.newCString(expr) + + rePtr := newRE(abi, cs, opts) + errCode, errArg := reError(abi, rePtr) + switch errCode { + case 0: + // No error. + case 1: + return nil, fmt.Errorf("error parsing regexp: unexpected error: %#q", errArg) + case 2: + return nil, fmt.Errorf("error parsing regexp: invalid escape sequence: %#q", errArg) + case 3: + return nil, fmt.Errorf("error parsing regexp: bad character class: %#q", errArg) + case 4: + return nil, fmt.Errorf("error parsing regexp: invalid character class range: %#q", errArg) + case 5: + return nil, fmt.Errorf("error parsing regexp: missing closing ]: %#q", errArg) + case 6: + return nil, fmt.Errorf("error parsing regexp: missing closing ): %#q", errArg) + case 7: + return nil, fmt.Errorf("error parsing regexp: unexpected ): %#q", errArg) + case 8: + return nil, fmt.Errorf("error parsing regexp: trailing backslash at end of expression: %#q", errArg) + case 9: + return nil, fmt.Errorf("error parsing regexp: missing argument to repetition operator: %#q", errArg) + case 10: + return nil, fmt.Errorf("error parsing regexp: bad repitition argument: %#q", errArg) + case 11: + return nil, fmt.Errorf("error parsing regexp: invalid nested repetition operator: %#q", errArg) + case 12: + return nil, fmt.Errorf("error parsing regexp: bad perl operator: %#q", errArg) + case 13: + return nil, fmt.Errorf("error parsing regexp: invalid UTF-8 in regexp: %#q", errArg) + case 14: + return nil, fmt.Errorf("error parsing regexp: bad named capture group: %#q", errArg) + case 15: + // TODO(anuraaga): While the unit test passes, it is likely that the actual limit is currently + // different than regexp. + return nil, fmt.Errorf("error parsing regexp: expression too large") + } + + // Does not include whole expression match, e.g. $0 + numGroups := numCapturingGroups(abi, rePtr) + + re := &Regexp{ + ptr: rePtr, + opts: opts, + expr: expr, + numMatches: numGroups + 1, + abi: abi, + } + + // Use func(interface{}) form for nottinygc compatibility. + runtime.SetFinalizer(re, func(obj interface{}) { + obj.(*Regexp).release() + }) + + return re, nil +} + +// Expand appends template to dst and returns the result; during the +// append, Expand replaces variables in the template with corresponding +// matches drawn from src. The match slice should have been returned by +// FindSubmatchIndex. +// +// In the template, a variable is denoted by a substring of the form +// $name or ${name}, where name is a non-empty sequence of letters, +// digits, and underscores. A purely numeric name like $1 refers to +// the submatch with the corresponding index; other names refer to +// capturing parentheses named with the (?P...) syntax. A +// reference to an out of range or unmatched index or a name that is not +// present in the regular expression is replaced with an empty slice. +// +// In the $name form, name is taken to be as long as possible: $1x is +// equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0. +// +// To insert a literal $ in the output, use $$ in the template. +func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte { + return re.expand(dst, string(template), src, "", match) +} + +// ExpandString is like Expand but the template and source are strings. +// It appends to and returns a byte slice in order to give the calling +// code control over allocation. +func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte { + return re.expand(dst, template, nil, src, match) +} + +func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, match []int) []byte { + for len(template) > 0 { + before, after, ok := strings.Cut(template, "$") + if !ok { + break + } + dst = append(dst, before...) + template = after + if template != "" && template[0] == '$' { + // Treat $$ as $. + dst = append(dst, '$') + template = template[1:] + continue + } + name, num, rest, ok := extract(template) + if !ok { + // Malformed; treat $ as raw text. + dst = append(dst, '$') + continue + } + template = rest + if num >= 0 { + if 2*num+1 < len(match) && match[2*num] >= 0 { + if bsrc != nil { + dst = append(dst, bsrc[match[2*num]:match[2*num+1]]...) + } else { + dst = append(dst, src[match[2*num]:match[2*num+1]]...) + } + } + } else { + for i, namei := range re.SubexpNames() { + if name == namei && 2*i+1 < len(match) && match[2*i] >= 0 { + if bsrc != nil { + dst = append(dst, bsrc[match[2*i]:match[2*i+1]]...) + } else { + dst = append(dst, src[match[2*i]:match[2*i+1]]...) + } + break + } + } + } + } + + runtime.KeepAlive(re) // don't allow finalizer to run during method + + dst = append(dst, template...) + return dst +} + +// Find returns a slice holding the text of the leftmost match in b of the regular expression. +// A return value of nil indicates no match. +func (re *Regexp) Find(b []byte) []byte { + alloc := re.abi.startOperation(len(b) + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var dstCap [2]int + + dst := re.find(&alloc, cs, dstCap[:0]) + return matchedBytes(b, dst) +} + +// FindIndex returns a two-element slice of integers defining the location of +// the leftmost match in b of the regular expression. The match itself is at +// b[loc[0]:loc[1]]. +// A return value of nil indicates no match. +func (re *Regexp) FindIndex(b []byte) (loc []int) { + alloc := re.abi.startOperation(len(b) + 8) + defer re.abi.endOperation(alloc) + cs := alloc.newCStringFromBytes(b) + + res := re.find(&alloc, cs, nil) + runtime.KeepAlive(b) + return res +} + +// FindString returns a string holding the text of the leftmost match in s of the regular +// expression. If there is no match, the return value is an empty string, +// but it will also be empty if the regular expression successfully matches +// an empty string. Use FindStringIndex or FindStringSubmatch if it is +// necessary to distinguish these cases. +func (re *Regexp) FindString(s string) string { + alloc := re.abi.startOperation(len(s) + 8) + defer re.abi.endOperation(alloc) + cs := alloc.newCString(s) + + var dstCap [2]int + + dst := re.find(&alloc, cs, dstCap[:0]) + return matchedString(s, dst) +} + +// FindStringIndex returns a two-element slice of integers defining the +// location of the leftmost match in s of the regular expression. The match +// itself is at s[loc[0]:loc[1]]. +// A return value of nil indicates no match. +func (re *Regexp) FindStringIndex(s string) (loc []int) { + alloc := re.abi.startOperation(len(s) + 8) + defer re.abi.endOperation(alloc) + cs := alloc.newCString(s) + + res := re.find(&alloc, cs, nil) + runtime.KeepAlive(s) + return res +} + +func (re *Regexp) find(alloc *allocation, cs cString, dstCap []int) []int { + matchArr := alloc.newCStringArray(1) + defer matchArr.free() + + res := match(re, cs, matchArr.ptr, 1) + if !res { + return nil + } + + m := readMatch(alloc, cs, matchArr.ptr, dstCap) + runtime.KeepAlive(matchArr) + + runtime.KeepAlive(re) // don't allow finalizer to run during method + + return m +} + +// FindAll is the 'All' version of Find; it returns a slice of all successive +// matches of the expression, as defined by the 'All' description in the +// package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAll(b []byte, n int) [][]byte { + alloc := re.abi.startOperation(len(b) + 16) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches [][]byte + + re.findAll(&alloc, b, "", cs, n, func(match []int) { + matches = append(matches, matchedBytes(b, match)) + }) + + return matches +} + +// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all +// successive matches of the expression, as defined by the 'All' description +// in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllIndex(b []byte, n int) [][]int { + alloc := re.abi.startOperation(len(b) + 16) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches [][]int + + re.findAll(&alloc, b, "", cs, n, func(match []int) { + matches = append(matches, append([]int(nil), match...)) + }) + + res := matches + runtime.KeepAlive(b) + return res +} + +// FindAllString is the 'All' version of FindString; it returns a slice of all +// successive matches of the expression, as defined by the 'All' description +// in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllString(s string, n int) []string { + alloc := re.abi.startOperation(len(s) + 16) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches []string + + re.findAll(&alloc, nil, s, cs, n, func(match []int) { + matches = append(matches, matchedString(s, match)) + }) + + return matches +} + +// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a +// slice of all successive matches of the expression, as defined by the 'All' +// description in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllStringIndex(s string, n int) [][]int { + alloc := re.abi.startOperation(len(s) + 16) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches [][]int + + re.findAll(&alloc, nil, s, cs, n, func(match []int) { + matches = append(matches, append([]int(nil), match...)) + }) + + res := matches + runtime.KeepAlive(s) + return res +} + +func (re *Regexp) findAll(alloc *allocation, bsrc []byte, src string, cs cString, n int, deliver func(match []int)) { + var dstCap [2]int + + if n < 0 { + n = cs.length + 1 + } + + matchArr := alloc.newCStringArray(1) + defer matchArr.free() + + count := 0 + prevMatchEnd := -1 + pos := 0 + for pos < cs.length+1 { + if !matchFrom(re, cs, pos, matchArr.ptr, 1) { + break + } + + match := readMatch(alloc, cs, matchArr.ptr, dstCap[:0]) + accept := true + // Check if it's an empty match following a match, which we ignore. + if match[0] == match[1] && match[0] == prevMatchEnd { + // We don't allow an empty match right + // after a previous match, so ignore it. + accept = false + } + + pos = nextPos(bsrc, src, pos, match[1]) + + if accept { + deliver(match) + count++ + } + prevMatchEnd = match[1] + + if count == n { + break + } + } + + runtime.KeepAlive(matchArr) + + runtime.KeepAlive(re) // don't allow finalizer to run during method +} + +// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice +// of all successive matches of the expression, as defined by the 'All' +// description in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte { + alloc := re.abi.startOperation(len(b) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches [][][]byte + + re.findAllSubmatch(&alloc, b, "", cs, re.numMatches, n, func(match []int) { + matched := make([][]byte, len(match)/2) + for i := 0; i < len(match); i += 2 { + matched[i/2] = matchedBytes(b, match[i:i+2]) + } + matches = append(matches, matched) + }) + + return matches +} + +// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns +// a slice of all successive matches of the expression, as defined by the +// 'All' description in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int { + alloc := re.abi.startOperation(len(b) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches [][]int + + re.findAllSubmatch(&alloc, b, "", cs, re.numMatches, n, func(match []int) { + matches = append(matches, match) + }) + + res := matches + runtime.KeepAlive(b) + return res +} + +// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it +// returns a slice of all successive matches of the expression, as defined by +// the 'All' description in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string { + alloc := re.abi.startOperation(len(s) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches [][]string + + re.findAllSubmatch(&alloc, nil, s, cs, re.numMatches, n, func(match []int) { + matched := make([]string, len(match)/2) + for i := 0; i < len(match); i += 2 { + matched[i/2] = matchedString(s, match[i:i+2]) + } + matches = append(matches, matched) + }) + + return matches +} + +// FindAllStringSubmatchIndex is the 'All' version of +// FindStringSubmatchIndex; it returns a slice of all successive matches of +// the expression, as defined by the 'All' description in the package +// comment. +// A return value of nil indicates no match. +func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int { + alloc := re.abi.startOperation(len(s) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches [][]int + + re.findAllSubmatch(&alloc, nil, s, cs, re.numMatches, n, func(match []int) { + matches = append(matches, match) + }) + + res := matches + runtime.KeepAlive(s) + return res +} + +func (re *Regexp) findAllSubmatch(alloc *allocation, bsrc []byte, src string, cs cString, nmatch, n int, deliver func(match []int)) { + if n < 0 { + n = cs.length + 1 + } + + matchArr := alloc.newCStringArray(nmatch) + defer matchArr.free() + + count := 0 + prevMatchEnd := -1 + pos := 0 + for pos < cs.length+1 { + if !matchFrom(re, cs, pos, matchArr.ptr, uint32(nmatch)) { + break + } + + var matches []int + accept := true + readMatches(alloc, cs, matchArr.ptr, nmatch, func(match []int) bool { + if len(matches) == 0 { + // First match, check if it's an empty match following a match, which we ignore. + if match[0] == match[1] && match[0] == prevMatchEnd { + accept = false + } + + pos = nextPos(bsrc, src, pos, match[1]) + prevMatchEnd = match[1] + } + if accept { + matches = append(matches, match...) + return true + } else { + return false + } + }) + if accept { + deliver(matches) + } + count++ + + if count == n { + break + } + } + + runtime.KeepAlive(matchArr) + + runtime.KeepAlive(re) // don't allow finalizer to run during method +} + +// FindSubmatch returns a slice of slices holding the text of the leftmost +// match of the regular expression in b and the matches, if any, of its +// subexpressions, as defined by the 'Submatch' descriptions in the package +// comment. +// A return value of nil indicates no match. +func (re *Regexp) FindSubmatch(b []byte) [][]byte { + alloc := re.abi.startOperation(len(b) + 8*re.numMatches) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches [][]byte + + re.findSubmatch(&alloc, cs, func(match []int) bool { + matches = append(matches, matchedBytes(b, match)) + return true + }) + + return matches +} + +// FindSubmatchIndex returns a slice holding the index pairs identifying the +// leftmost match of the regular expression in b and the matches, if any, of +// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions +// in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindSubmatchIndex(b []byte) []int { + alloc := re.abi.startOperation(len(b) + 8*re.numMatches) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches []int + + re.findSubmatch(&alloc, cs, func(match []int) bool { + matches = append(matches, match...) + return true + }) + + res := matches + runtime.KeepAlive(b) + return res +} + +func (re *Regexp) FindStringSubmatch(s string) []string { + alloc := re.abi.startOperation(len(s) + 8*re.numMatches) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches []string + + re.findSubmatch(&alloc, cs, func(match []int) bool { + matches = append(matches, matchedString(s, match)) + return true + }) + + return matches +} + +// FindStringSubmatchIndex returns a slice holding the index pairs +// identifying the leftmost match of the regular expression in s and the +// matches, if any, of its subexpressions, as defined by the 'Submatch' and +// 'Index' descriptions in the package comment. +// A return value of nil indicates no match. +func (re *Regexp) FindStringSubmatchIndex(s string) []int { + alloc := re.abi.startOperation(len(s) + 8*re.numMatches) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches []int + + re.findSubmatch(&alloc, cs, func(match []int) bool { + matches = append(matches, match...) + return true + }) + + res := matches + runtime.KeepAlive(s) + return res +} + +func (re *Regexp) findSubmatch(alloc *allocation, cs cString, deliver func(match []int) bool) { + numGroups := re.numMatches + matchArr := alloc.newCStringArray(numGroups) + defer matchArr.free() + + if !match(re, cs, matchArr.ptr, uint32(numGroups)) { + return + } + + readMatches(alloc, cs, matchArr.ptr, numGroups, deliver) + + runtime.KeepAlive(matchArr) + + runtime.KeepAlive(re) // don't allow finalizer to run during method +} + +// Longest makes future searches prefer the leftmost-longest match. +// That is, when matching against text, the regexp returns a match that +// begins as early as possible in the input (leftmost), and among those +// it chooses a match that is as long as possible. +// This method modifies the Regexp and may not be called concurrently +// with any other methods. +func (re *Regexp) Longest() { + alloc := re.abi.startOperation(len(re.expr) + 2) + defer re.abi.endOperation(alloc) + + if re.opts.Longest { + return + } + + // longest is not a mutable option in re2 so we must release and recompile. + deleteRE(re.abi, re.ptr) + + cs := alloc.newCString(re.expr) + newOpts := re.opts + newOpts.Longest = true + re.ptr = newRE(re.abi, cs, newOpts) +} + +// NumSubexp returns the number of parenthesized subexpressions in this Regexp. +func (re *Regexp) NumSubexp() int { + return re.numMatches - 1 +} + +// Split slices s into substrings separated by the expression and returns a slice of +// the substrings between those expression matches. +// +// The slice returned by this method consists of all the substrings of s +// not contained in the slice returned by FindAllString. When called on an expression +// that contains no metacharacters, it is equivalent to strings.SplitN. +// +// Example: +// +// s := regexp.MustCompile("a*").Split("abaabaccadaaae", 5) +// // s: ["", "b", "b", "c", "cadaaae"] +// +// The count determines the number of substrings to return: +// +// n > 0: at most n substrings; the last substring will be the unsplit remainder. +// n == 0: the result is nil (zero substrings) +// n < 0: all substrings +func (re *Regexp) Split(s string, n int) []string { + // Copied as is from + // https://github.com/golang/go/blob/78472603c6bac7a52d42d565558b9c0cb12c3f9a/src/regexp/regexp.go#L1253 + // The logic in this function is only for taking match indexes to split the string, regex itself + // delegates to our implementation. + + if n == 0 { + return nil + } + + if len(re.expr) > 0 && len(s) == 0 { + return []string{""} + } + + matches := re.FindAllStringIndex(s, n) + strings := make([]string, 0, len(matches)) + + beg := 0 + end := 0 + for _, match := range matches { + if n > 0 && len(strings) >= n-1 { + break + } + + end = match[0] + if match[1] != 0 { + strings = append(strings, s[beg:end]) + } + beg = match[1] + } + + if end != len(s) { + strings = append(strings, s[beg:]) + } + + return strings +} + +// SubexpNames returns the names of the parenthesized subexpressions +// in this Regexp. The name for the first sub-expression is names[1], +// so that if m is a match slice, the name for m[i] is SubexpNames()[i]. +// Since the Regexp as a whole cannot be named, names[0] is always +// the empty string. The slice should not be modified. +func (re *Regexp) SubexpNames() []string { + re.groupNamesOnce.Do(func() { + re.groupNames = subexpNames(re.abi, re.ptr, re.numMatches) + }) + return re.groupNames +} + +// SubexpIndex returns the index of the first subexpression with the given name, +// or -1 if there is no subexpression with that name. +// +// Note that multiple subexpressions can be written using the same name, as in +// (?Pa+)(?Pb+), which declares two subexpressions named "bob". +// In this case, SubexpIndex returns the index of the leftmost such subexpression +// in the regular expression. +func (re *Regexp) SubexpIndex(name string) int { + if name != "" { + for i, s := range re.SubexpNames() { + if name == s { + return i + } + } + } + return -1 +} + +// Match reports whether the byte slice b +// contains any match of the regular expression re. +func (re *Regexp) Match(b []byte) bool { + alloc := re.abi.startOperation(len(b)) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + res := match(re, cs, nilWasmPtr, 0) + runtime.KeepAlive(b) + + runtime.KeepAlive(re) // don't allow finalizer to run during method + + return res +} + +// MatchString reports whether the string s +// contains any match of the regular expression re. +func (re *Regexp) MatchString(s string) bool { + alloc := re.abi.startOperation(len(s)) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(s) + res := match(re, cs, nilWasmPtr, 0) + runtime.KeepAlive(s) + + runtime.KeepAlive(re) // don't allow finalizer to run during method + + return res +} + +func (re *Regexp) release() { + if !atomic.CompareAndSwapUint32(&re.released, 0, 1) { + return + } + release(re) +} + +func Release(re *Regexp) { + re.release() +} + +// ReplaceAll returns a copy of src, replacing matches of the Regexp +// with the replacement text repl. Inside repl, $ signs are interpreted as +// in Expand, so for instance $1 represents the text of the first submatch. +func (re *Regexp) ReplaceAll(src, repl []byte) []byte { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(src) + + n := 2 + if bytes.IndexByte(repl, '$') >= 0 { + n = re.numMatches + } + + srepl := "" + b := re.replaceAll(&alloc, src, "", cs, n, func(dst []byte, m []int) []byte { + if len(srepl) != len(repl) { + srepl = string(repl) + } + return re.expand(dst, srepl, src, "", m) + }) + return b +} + +// ReplaceAllFunc returns a copy of src in which all matches of the +// [Regexp] have been replaced by the return value of function repl applied +// to the matched byte slice. The replacement returned by repl is substituted +// directly, without using [Regexp.Expand]. +func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(src) + + return re.replaceAll(&alloc, src, "", cs, 2, func(dst []byte, m []int) []byte { + return append(dst, repl(src[m[0]:m[1]])...) + }) +} + +// ReplaceAllLiteral returns a copy of src, replacing matches of the Regexp +// with the replacement bytes repl. The replacement repl is substituted directly, +// without using Expand. +func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(src) + + return re.replaceAll(&alloc, src, "", cs, 2, func(dst []byte, m []int) []byte { + return append(dst, repl...) + }) +} + +// ReplaceAllLiteralString returns a copy of src, replacing matches of the Regexp +// with the replacement string repl. The replacement repl is substituted directly, +// without using Expand. +func (re *Regexp) ReplaceAllLiteralString(src, repl string) string { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(src) + + b := re.replaceAll(&alloc, nil, src, cs, 2, func(dst []byte, m []int) []byte { + return append(dst, repl...) + }) + + return string(b) +} + +// ReplaceAllString returns a copy of src, replacing matches of the Regexp +// with the replacement string repl. Inside repl, $ signs are interpreted as +// in Expand, so for instance $1 represents the text of the first submatch. +func (re *Regexp) ReplaceAllString(src, repl string) string { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(src) + + n := 2 + if strings.Contains(repl, "$") { + n = re.numMatches + } + + b := re.replaceAll(&alloc, nil, src, cs, n, func(dst []byte, m []int) []byte { + return re.expand(dst, repl, nil, src, m) + }) + + return string(b) +} + +// ReplaceAllStringFunc returns a copy of src in which all matches of the +// [Regexp] have been replaced by the return value of function repl applied +// to the matched substring. The replacement returned by repl is substituted +// directly, without using [Regexp.Expand]. +func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { + alloc := re.abi.startOperation(len(src) + 8*re.numMatches + 8) + defer re.abi.endOperation(alloc) + + cs := alloc.newCString(src) + + b := re.replaceAll(&alloc, nil, src, cs, 2, func(dst []byte, m []int) []byte { + return append(dst, repl(src[m[0]:m[1]])...) + }) + + return string(b) +} + +func (re *Regexp) replaceAll(alloc *allocation, bsrc []byte, src string, cs cString, nmatch int, repl func(dst []byte, m []int) []byte) []byte { + lastMatchEnd := 0 + var buf []byte + + re.findAllSubmatch(alloc, bsrc, src, cs, nmatch, -1, func(a []int) { + // Copy the unmatched characters before this match. + if bsrc != nil { + buf = append(buf, bsrc[lastMatchEnd:a[0]]...) + } else { + buf = append(buf, src[lastMatchEnd:a[0]]...) + } + + if a[1] > lastMatchEnd || a[0] == 0 { + buf = repl(buf, a) + } + lastMatchEnd = a[1] + }) + + if bsrc != nil { + buf = append(buf, bsrc[lastMatchEnd:]...) + } else { + buf = append(buf, src[lastMatchEnd:]...) + } + + return buf +} + +// String returns the source text used to compile the regular expression. +func (re *Regexp) String() string { + return re.expr +} + +func subexpNames(abi *libre2ABI, rePtr wasmPtr, numMatches int) []string { + res := make([]string, numMatches) + + iter := namedGroupsIter(abi, rePtr) + defer namedGroupsIterDelete(abi, iter) + + for { + name, index, ok := namedGroupsIterNext(abi, iter) + if !ok { + break + } + res[index] = name + } + + return res +} + +// extract returns the name from a leading "name" or "{name}" in str. +// (The $ has already been removed by the caller.) +// If it is a number, extract returns num set to that number; otherwise num = -1. +// Copied as is from +// https://github.com/golang/go/blob/0fd7be7ee5f36215b5d6b8f23f35d60bf749805a/src/regexp/regexp.go#L981 +func extract(str string) (name string, num int, rest string, ok bool) { + if str == "" { + return + } + brace := false + if str[0] == '{' { + brace = true + str = str[1:] + } + i := 0 + for i < len(str) { + rune, size := utf8.DecodeRuneInString(str[i:]) + if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' { + break + } + i += size + } + if i == 0 { + // empty name is not okay + return + } + name = str[:i] + if brace { + if i >= len(str) || str[i] != '}' { + // missing closing brace + return + } + i++ + } + + // Parse number. + num = 0 + for i := 0; i < len(name); i++ { + if name[i] < '0' || '9' < name[i] || num >= 1e8 { + num = -1 + break + } + num = num*10 + int(name[i]) - '0' + } + // Disallow leading zeros. + if name[0] == '0' && len(name) > 1 { + num = -1 + } + + rest = str[i:] + ok = true + return +} + +func matchedBytes(s []byte, match []int) []byte { + if len(match) < 2 || match[0] == -1 { + return nil + } + return s[match[0]:match[1]:match[1]] +} + +func matchedString(s string, match []int) string { + if len(match) < 2 || match[0] == -1 { + return "" + } + return s[match[0]:match[1]] +} + +func nextPos(bsrc []byte, src string, pos int, matchEnd int) int { + // Advance past the match; always advance at least one character. + var width int + if bsrc != nil { + _, width = utf8.DecodeRune(bsrc[pos:]) + } else { + _, width = utf8.DecodeRuneInString(src[pos:]) + } + + if pos+width > matchEnd { + return pos + width + } else if pos+1 > matchEnd { + // This clause is only needed at the end of the input + // string. In that case, DecodeRuneInString returns width=0. + return pos + 1 + } else { + return matchEnd + } +} + +func QuoteForError(s string) string { + if strconv.CanBackquote(s) { + return "`" + s + "`" + } + return strconv.Quote(s) +} diff --git a/vendor/github.com/wasilibs/go-re2/internal/re2_re2_cgo.go b/vendor/github.com/wasilibs/go-re2/internal/re2_re2_cgo.go new file mode 100644 index 00000000..858ecd7f --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/re2_re2_cgo.go @@ -0,0 +1,216 @@ +//go:build tinygo.wasm || re2_cgo + +package internal + +import ( + "fmt" + "unsafe" + + "github.com/wasilibs/go-re2/internal/cre2" +) + +type wasmPtr unsafe.Pointer + +var nilWasmPtr = wasmPtr(nil) + +type libre2ABI struct{} + +func newABI() *libre2ABI { + return &libre2ABI{} +} + +func (abi *libre2ABI) startOperation(memorySize int) allocation { + return allocation{} +} + +func (abi *libre2ABI) endOperation(allocation) { +} + +func newRE(abi *libre2ABI, pattern cString, opts CompileOptions) wasmPtr { + opt := cre2.NewOpt() + defer cre2.DeleteOpt(opt) + cre2.OptSetMaxMem(opt, maxSize) + cre2.OptSetLogErrors(opt, false) + if opts.Longest { + cre2.OptSetLongestMatch(opt, true) + } + if opts.Posix { + cre2.OptSetPosixSyntax(opt, true) + } + if opts.CaseInsensitive { + cre2.OptSetCaseSensitive(opt, false) + } + if opts.Latin1 { + cre2.OptSetLatin1Encoding(opt) + } + return wasmPtr(cre2.New(pattern.ptr, pattern.length, opt)) +} + +func reError(abi *libre2ABI, rePtr wasmPtr) (int, string) { + code := cre2.ErrorCode(unsafe.Pointer(rePtr)) + if code == 0 { + return 0, "" + } + + arg := cre2.CopyCString(cre2.ErrorArg(unsafe.Pointer(rePtr))) + return code, arg +} + +func numCapturingGroups(abi *libre2ABI, rePtr wasmPtr) int { + return cre2.NumCapturingGroups(unsafe.Pointer(rePtr)) +} + +func deleteRE(_ *libre2ABI, rePtr wasmPtr) { + cre2.Delete(unsafe.Pointer(rePtr)) +} + +func release(re *Regexp) { + deleteRE(re.abi, re.ptr) +} + +func match(re *Regexp, s cString, matchesPtr wasmPtr, nMatches uint32) bool { + return cre2.Match(unsafe.Pointer(re.ptr), s.ptr, + s.length, 0, s.length, 0, unsafe.Pointer(matchesPtr), int(nMatches)) +} + +func matchFrom(re *Regexp, s cString, startPos int, matchesPtr wasmPtr, nMatches uint32) bool { + return cre2.Match(unsafe.Pointer(re.ptr), s.ptr, + s.length, startPos, s.length, 0, unsafe.Pointer(matchesPtr), int(nMatches)) +} + +type allocation struct{} + +func (*allocation) newCString(s string) cString { + if len(s) == 0 { + // TinyGo uses a null pointer to represent an empty string, but this + // prevents us from distinguishing a match on the empty string vs no + // match for subexpressions. So we replace with an empty-length slice + // to a string that isn't null. + s = "a"[0:0] + } + res := cString{ + ptr: unsafe.Pointer(unsafe.StringData(s)), + length: len(s), + } + return res +} + +func (*allocation) newCStringFromBytes(s []byte) cString { + res := cString{ + ptr: unsafe.Pointer(unsafe.SliceData(s)), + length: len(s), + } + return res +} + +func (a *allocation) newCStringArray(n int) cStringArray { + sz := int(unsafe.Sizeof(cString{})) * n + ptr := cre2.Malloc(sz) + for i := 0; i < sz; i++ { + *(*byte)(unsafe.Add(ptr, i)) = 0 + } + + return cStringArray{ptr: wasmPtr(ptr)} +} + +func (a *allocation) read(ptr wasmPtr, size int) []byte { + return (*[1 << 30]byte)(unsafe.Pointer(ptr))[:size:size] +} + +type cString struct { + ptr unsafe.Pointer + length int +} + +type cStringArray struct { + ptr wasmPtr +} + +func (a cStringArray) free() { + cre2.Free(unsafe.Pointer(a.ptr)) +} + +func namedGroupsIter(_ *libre2ABI, rePtr wasmPtr) wasmPtr { + return wasmPtr(cre2.NamedGroupsIterNew(unsafe.Pointer(rePtr))) +} + +func namedGroupsIterNext(_ *libre2ABI, iterPtr wasmPtr) (string, int, bool) { + var namePtr unsafe.Pointer + var index int + if !cre2.NamedGroupsIterNext(unsafe.Pointer(iterPtr), &namePtr, &index) { + return "", 0, false + } + + name := cre2.CopyCString(namePtr) + return name, index, true +} + +func namedGroupsIterDelete(_ *libre2ABI, iterPtr wasmPtr) { + cre2.NamedGroupsIterDelete(unsafe.Pointer(iterPtr)) +} + +func readMatch(_ *allocation, cs cString, matchPtr wasmPtr, dstCap []int) []int { + match := (*cString)(matchPtr) + subStrPtr := match.ptr + if subStrPtr == nil { + return append(dstCap, -1, -1) + } + sIdx := uintptr(subStrPtr) - uintptr(cs.ptr) + return append(dstCap, int(sIdx), int(sIdx+uintptr(match.length))) +} + +func readMatches(alloc *allocation, cs cString, matchesPtr wasmPtr, n int, deliver func([]int) bool) { + var dstCap [2]int + + for i := 0; i < n; i++ { + dst := readMatch(alloc, cs, wasmPtr(unsafe.Add(unsafe.Pointer(matchesPtr), unsafe.Sizeof(cString{})*uintptr(i))), dstCap[:0]) + if !deliver(dst) { + break + } + } +} + +func newSet(_ *libre2ABI, opts CompileOptions) wasmPtr { + opt := cre2.NewOpt() + defer cre2.DeleteOpt(opt) + cre2.OptSetMaxMem(opt, maxSize) + cre2.OptSetLogErrors(opt, false) + if opts.Longest { + cre2.OptSetLongestMatch(opt, true) + } + if opts.Posix { + cre2.OptSetPosixSyntax(opt, true) + } + if opts.CaseInsensitive { + cre2.OptSetCaseSensitive(opt, false) + } + if opts.Latin1 { + cre2.OptSetLatin1Encoding(opt) + } + return wasmPtr(cre2.NewSet(opt, 0)) +} + +func setAdd(set *Set, s cString) string { + msgPtr := cre2.SetAdd(unsafe.Pointer(set.ptr), s.ptr, s.length) + if msgPtr == nil { + return unknownCompileError + } + msg := cre2.CopyCString(msgPtr) + if msg != "ok" { + cre2.Free(msgPtr) + return fmt.Sprintf("error parsing regexp: %s", msg) + } + return "" +} + +func setCompile(set *Set) int32 { + return int32(cre2.SetCompile(unsafe.Pointer(set.ptr))) +} + +func setMatch(set *Set, cs cString, matchedPtr wasmPtr, nMatch int) int { + return cre2.SetMatch(unsafe.Pointer(set.ptr), cs.ptr, cs.length, unsafe.Pointer(matchedPtr), nMatch) +} + +func deleteSet(_ *libre2ABI, setPtr wasmPtr) { + cre2.SetDelete(unsafe.Pointer(setPtr)) +} diff --git a/vendor/github.com/wasilibs/go-re2/internal/re2_wazero.go b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero.go new file mode 100644 index 00000000..29024978 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero.go @@ -0,0 +1,739 @@ +//go:build !tinygo.wasm && !re2_cgo + +package internal + +import ( + "container/list" + "context" + _ "embed" + "encoding/binary" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "sync/atomic" + "unsafe" + + wazero "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/experimental" + "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" + "github.com/wasilibs/wazero-helpers/allocator" +) + +var errFailedRead = errors.New("failed to read from wasm memory") + +//go:embed wasm/libcre2.wasm +var libre2 []byte + +// memoryWasm created by `wat2wasm --enable-threads internal/wasm/memory.wat -o internal/wasm/memory.wasm` +// +//go:embed wasm/memory.wasm +var memoryWasm []byte + +var ( + wasmRT wazero.Runtime + wasmCompiled wazero.CompiledModule + wasmMemory api.Memory + rootMod api.Module + + modPool *list.List + modPoolMu sync.Mutex +) + +type libre2ABI struct { + cre2New lazyFunction + cre2Delete lazyFunction + cre2Match lazyFunction + cre2NumCapturingGroups lazyFunction + cre2ErrorCode lazyFunction + cre2ErrorArg lazyFunction + cre2NamedGroupsIterNew lazyFunction + cre2NamedGroupsIterNext lazyFunction + cre2NamedGroupsIterDelete lazyFunction + cre2OptNew lazyFunction + cre2OptDelete lazyFunction + cre2OptSetLongestMatch lazyFunction + cre2OptSetPosixSyntax lazyFunction + cre2OptSetCaseSensitive lazyFunction + cre2OptSetLatin1Encoding lazyFunction + cre2OptSetMaxMem lazyFunction + + cre2SetNew lazyFunction + cre2SetAdd lazyFunction + cre2SetCompile lazyFunction + cre2SetMatch lazyFunction + cre2SetDelete lazyFunction + + malloc lazyFunction + free lazyFunction +} + +type wasmPtr uint32 + +var nilWasmPtr = wasmPtr(0) + +var prevTID uint32 + +type childModule struct { + mod api.Module + tlsBasePtr uint32 + functions map[string]api.Function +} + +func createChildModule(rt wazero.Runtime, root api.Module) *childModule { + ctx := context.Background() + + // Not executing function so is at end of stack + stackPointer := root.ExportedGlobal("__stack_pointer").Get() + tlsBase := root.ExportedGlobal("__tls_base").Get() + + // Thread-local-storage for the main thread is from __tls_base to __stack_pointer + // For now, let's preserve the size but in the future we can probably use less. + size := stackPointer - tlsBase + + malloc := root.ExportedFunction("malloc") + + // Allocate memory for the child thread stack + res, err := malloc.Call(ctx, size) + if err != nil { + panic(err) + } + ptr := uint32(res[0]) + + child, err := rt.InstantiateModule(ctx, wasmCompiled, wazero.NewModuleConfig().WithSysNanotime().WithSysWalltime().WithSysNanosleep().WithStdout(os.Stdout).WithStderr(os.Stderr). + // Don't need to execute start functions again in child, it crashes anyways. + WithStartFunctions(). + WithName("")) + if err != nil { + panic(err) + } + initTLS := child.ExportedFunction("__wasm_init_tls") + if _, err := initTLS.Call(ctx, uint64(ptr)); err != nil { + panic(err) + } + + tid := atomic.AddUint32(&prevTID, 1) + root.Memory().WriteUint32Le(ptr, ptr) + root.Memory().WriteUint32Le(ptr+20, tid) + child.ExportedGlobal("__stack_pointer").(api.MutableGlobal).Set(uint64(ptr) + size) + + ret := &childModule{ + mod: child, + tlsBasePtr: ptr, + functions: map[string]api.Function{}, + } + runtime.SetFinalizer(ret, func(obj interface{}) { + cm := obj.(*childModule) + free := cm.mod.ExportedFunction("free") + if _, err := free.Call(ctx, uint64(cm.tlsBasePtr)); err != nil { + panic(err) + } + _ = cm.mod.Close(context.Background()) + }) + return ret +} + +// We currently avoid sync.Pool as it tends to overallocate and Wasm functions can't be preempted, +// meaning have more than # of CPUs is mostly unnecessary. We can revisit in the future, but at least +// for now, a lock here is no more than before we added threads support. + +func getChildModule() *childModule { + modPoolMu.Lock() + if modPool == nil { + initWASM() + } + e := modPool.Front() + if e == nil { + modPoolMu.Unlock() + return createChildModule(wasmRT, rootMod) + } + modPool.Remove(e) + modPoolMu.Unlock() + return e.Value.(*childModule) +} + +func putChildModule(cm *childModule) { + modPoolMu.Lock() + modPool.PushBack(cm) + modPoolMu.Unlock() +} + +func initWASM() { + ctx := context.Background() + ctx = experimental.WithMemoryAllocator(ctx, allocator.NewNonMoving()) + + rtCfg := wazero.NewRuntimeConfig().WithCoreFeatures(api.CoreFeaturesV2 | experimental.CoreFeaturesThreads) + uc, err := os.UserCacheDir() + if err == nil { + cache, err := wazero.NewCompilationCacheWithDir(filepath.Join(uc, "com.github.wasilibs")) + if err == nil { + rtCfg = rtCfg.WithCompilationCache(cache) + } + } + + maxPages := defaultMaxPages + if unsafe.Sizeof(uintptr(0)) < 8 { + // On a 32-bit system. anything close to 4GB will fail (part of 4GB is already used by the rest of the process). + // We go ahead and cap to 1GB to to be extra conservative. It will be using interpreter mode anyways so either + // the memory limit or the performance will be an issue either way. + maxPagesLimit := uint32(65536 / 4) + if maxPages > maxPagesLimit { + maxPages = maxPagesLimit + } + } + rtCfg = rtCfg.WithMemoryLimitPages(maxPages) + + rt := wazero.NewRuntimeWithConfig(ctx, rtCfg) + + wasi_snapshot_preview1.MustInstantiate(ctx, rt) + + if _, err := rt.InstantiateWithConfig(ctx, memoryWasm, wazero.NewModuleConfig().WithName("env")); err != nil { + panic(err) + } + + code, err := rt.CompileModule(ctx, libre2) + if err != nil { + panic(err) + } + wasmCompiled = code + + // In some situations (eg, running as a service on windows) + // Stdout and Stderr may not be available. + // In this case, use io.Discard to avoid InstantiateModule returning an error. + var stdout, stderr io.Writer = os.Stdout, os.Stderr + + if _, err := os.Stdout.Stat(); err != nil { + stdout = io.Discard + } + if _, err := os.Stderr.Stat(); err != nil { + stderr = io.Discard + } + + wasmRT = rt + root, err := wasmRT.InstantiateModule(ctx, wasmCompiled, wazero.NewModuleConfig().WithSysWalltime().WithSysNanotime().WithSysNanosleep().WithStdout(stdout).WithStderr(stderr).WithStartFunctions("_initialize").WithName("")) + if err != nil { + panic(err) + } + wasmMemory = root.Memory() + rootMod = root + + modPool = list.New() +} + +func newABI() *libre2ABI { + abi := &libre2ABI{ + cre2New: newLazyFunction("cre2_new"), + cre2Delete: newLazyFunction("cre2_delete"), + cre2Match: newLazyFunction("cre2_match"), + cre2NumCapturingGroups: newLazyFunction("cre2_num_capturing_groups"), + cre2ErrorCode: newLazyFunction("cre2_error_code"), + cre2ErrorArg: newLazyFunction("cre2_error_arg"), + cre2NamedGroupsIterNew: newLazyFunction("cre2_named_groups_iter_new"), + cre2NamedGroupsIterNext: newLazyFunction("cre2_named_groups_iter_next"), + cre2NamedGroupsIterDelete: newLazyFunction("cre2_named_groups_iter_delete"), + cre2OptNew: newLazyFunction("cre2_opt_new"), + cre2OptDelete: newLazyFunction("cre2_opt_delete"), + cre2OptSetLongestMatch: newLazyFunction("cre2_opt_set_longest_match"), + cre2OptSetPosixSyntax: newLazyFunction("cre2_opt_set_posix_syntax"), + cre2OptSetCaseSensitive: newLazyFunction("cre2_opt_set_case_sensitive"), + cre2OptSetLatin1Encoding: newLazyFunction("cre2_opt_set_latin1_encoding"), + cre2OptSetMaxMem: newLazyFunction("cre2_opt_set_max_mem"), + cre2SetNew: newLazyFunction("cre2_set_new"), + cre2SetAdd: newLazyFunction("cre2_set_add"), + cre2SetCompile: newLazyFunction("cre2_set_compile"), + cre2SetMatch: newLazyFunction("cre2_set_match"), + cre2SetDelete: newLazyFunction("cre2_set_delete"), + malloc: newLazyFunction("malloc"), + free: newLazyFunction("free"), + } + + return abi +} + +func (abi *libre2ABI) startOperation(memorySize int) allocation { + return abi.reserve(uint32(memorySize)) +} + +func (abi *libre2ABI) endOperation(a allocation) { + a.free() +} + +func newRE(abi *libre2ABI, pattern cString, opts CompileOptions) wasmPtr { + ctx := context.Background() + optPtr := uint32(0) + res, err := abi.cre2OptNew.Call0(ctx) + if err != nil { + panic(err) + } + optPtr = uint32(res) + defer func() { + if _, err := abi.cre2OptDelete.Call1(ctx, uint64(optPtr)); err != nil { + panic(err) + } + }() + + _, err = abi.cre2OptSetMaxMem.Call2(ctx, uint64(optPtr), uint64(maxSize)) + if err != nil { + panic(err) + } + + if opts.Longest { + _, err = abi.cre2OptSetLongestMatch.Call2(ctx, uint64(optPtr), 1) + if err != nil { + panic(err) + } + } + if opts.Posix { + _, err = abi.cre2OptSetPosixSyntax.Call2(ctx, uint64(optPtr), 1) + if err != nil { + panic(err) + } + } + if opts.CaseInsensitive { + _, err = abi.cre2OptSetCaseSensitive.Call2(ctx, uint64(optPtr), 0) + if err != nil { + panic(err) + } + } + if opts.Latin1 { + _, err = abi.cre2OptSetLatin1Encoding.Call1(ctx, uint64(optPtr)) + if err != nil { + panic(err) + } + } + + res, err = abi.cre2New.Call3(ctx, uint64(pattern.ptr), uint64(pattern.length), uint64(optPtr)) + if err != nil { + panic(err) + } + return wasmPtr(res) +} + +func reError(abi *libre2ABI, rePtr wasmPtr) (int, string) { + ctx := context.Background() + res, err := abi.cre2ErrorCode.Call1(ctx, uint64(rePtr)) + if err != nil { + panic(err) + } + code := int(res) + if code == 0 { + return 0, "" + } + + res, err = abi.cre2ErrorArg.Call1(ctx, uint64(rePtr)) + if err != nil { + panic(err) + } + msg := copyCString(wasmPtr(res)) + return code, msg +} + +func numCapturingGroups(abi *libre2ABI, rePtr wasmPtr) int { + ctx := context.Background() + res, err := abi.cre2NumCapturingGroups.Call1(ctx, uint64(rePtr)) + if err != nil { + panic(err) + } + return int(res) +} + +func deleteRE(abi *libre2ABI, rePtr wasmPtr) { + ctx := context.Background() + if _, err := abi.cre2Delete.Call1(ctx, uint64(rePtr)); err != nil { + panic(err) + } +} + +func release(re *Regexp) { + deleteRE(re.abi, re.ptr) +} + +func match(re *Regexp, s cString, matchesPtr wasmPtr, nMatches uint32) bool { + ctx := context.Background() + res, err := re.abi.cre2Match.Call8(ctx, uint64(re.ptr), uint64(s.ptr), uint64(s.length), 0, uint64(s.length), 0, uint64(matchesPtr), uint64(nMatches)) + if err != nil { + panic(err) + } + + return res == 1 +} + +func matchFrom(re *Regexp, s cString, startPos int, matchesPtr wasmPtr, nMatches uint32) bool { + ctx := context.Background() + res, err := re.abi.cre2Match.Call8(ctx, uint64(re.ptr), uint64(s.ptr), uint64(s.length), uint64(startPos), uint64(s.length), 0, uint64(matchesPtr), uint64(nMatches)) + if err != nil { + panic(err) + } + + return res == 1 +} + +func readMatch(alloc *allocation, cs cString, matchPtr wasmPtr, dstCap []int) []int { + matchBuf := alloc.read(matchPtr, 8) + subStrPtr := uint32(binary.LittleEndian.Uint32(matchBuf)) + sLen := uint32(binary.LittleEndian.Uint32(matchBuf[4:])) + sIdx := subStrPtr - uint32(cs.ptr) + + return append(dstCap, int(sIdx), int(sIdx+sLen)) +} + +func readMatches(alloc *allocation, cs cString, matchesPtr wasmPtr, n int, deliver func([]int) bool) { + var dstCap [2]int + + matchesBuf := alloc.read(matchesPtr, 8*n) + for i := 0; i < n; i++ { + subStrPtr := uint32(binary.LittleEndian.Uint32(matchesBuf[8*i:])) + if subStrPtr == 0 { + if !deliver(append(dstCap[:0], -1, -1)) { + break + } + continue + } + sLen := uint32(binary.LittleEndian.Uint32(matchesBuf[8*i+4:])) + sIdx := subStrPtr - uint32(cs.ptr) + if !deliver(append(dstCap[:0], int(sIdx), int(sIdx+sLen))) { + break + } + } +} + +func namedGroupsIter(abi *libre2ABI, rePtr wasmPtr) wasmPtr { + ctx := context.Background() + + res, err := abi.cre2NamedGroupsIterNew.Call1(ctx, uint64(rePtr)) + if err != nil { + panic(err) + } + + return wasmPtr(res) +} + +func namedGroupsIterNext(abi *libre2ABI, iterPtr wasmPtr) (string, int, bool) { + ctx := context.Background() + + // Not on the hot path so don't bother optimizing this yet. + ptrs := malloc(abi, 8) + defer free(abi, ptrs) + namePtrPtr := ptrs + indexPtr := namePtrPtr + 4 + + res, err := abi.cre2NamedGroupsIterNext.Call3(ctx, uint64(iterPtr), uint64(namePtrPtr), uint64(indexPtr)) + if err != nil { + panic(err) + } + + if res == 0 { + return "", 0, false + } + + namePtr, ok := wasmMemory.ReadUint32Le(uint32(namePtrPtr)) + if !ok { + panic(errFailedRead) + } + + name := copyCString(wasmPtr(namePtr)) + + index, ok := wasmMemory.ReadUint32Le(uint32(indexPtr)) + if !ok { + panic(errFailedRead) + } + + return name, int(index), true +} + +func namedGroupsIterDelete(abi *libre2ABI, iterPtr wasmPtr) { + ctx := context.Background() + + _, err := abi.cre2NamedGroupsIterDelete.Call1(ctx, uint64(iterPtr)) + if err != nil { + panic(err) + } +} + +func newSet(abi *libre2ABI, opts CompileOptions) wasmPtr { + ctx := context.Background() + optPtr := uint32(0) + res, err := abi.cre2OptNew.Call0(ctx) + if err != nil { + panic(err) + } + optPtr = uint32(res) + defer func() { + if _, err := abi.cre2OptDelete.Call1(ctx, uint64(optPtr)); err != nil { + panic(err) + } + }() + + _, err = abi.cre2OptSetMaxMem.Call2(ctx, uint64(optPtr), uint64(maxSize)) + if err != nil { + panic(err) + } + + if opts.Longest { + _, err = abi.cre2OptSetLongestMatch.Call2(ctx, uint64(optPtr), 1) + if err != nil { + panic(err) + } + } + if opts.Posix { + _, err = abi.cre2OptSetPosixSyntax.Call2(ctx, uint64(optPtr), 1) + if err != nil { + panic(err) + } + } + if opts.CaseInsensitive { + _, err = abi.cre2OptSetCaseSensitive.Call2(ctx, uint64(optPtr), 0) + if err != nil { + panic(err) + } + } + if opts.Latin1 { + _, err = abi.cre2OptSetLatin1Encoding.Call1(ctx, uint64(optPtr)) + if err != nil { + panic(err) + } + } + + res, err = abi.cre2SetNew.Call2(ctx, uint64(optPtr), 0) + if err != nil { + panic(err) + } + return wasmPtr(res) +} + +func setAdd(set *Set, s cString) string { + ctx := context.Background() + res, err := set.abi.cre2SetAdd.Call3(ctx, uint64(set.ptr), uint64(s.ptr), uint64(s.length)) + if err != nil { + panic(err) + } + if res == 0 { + return unknownCompileError + } + msgPtr := wasmPtr(res) + msg := copyCString(wasmPtr(msgPtr)) + if msg != "ok" { + free(set.abi, msgPtr) + return fmt.Sprintf("error parsing regexp: %s", msg) + } + return "" +} + +func setCompile(set *Set) int32 { + ctx := context.Background() + res, err := set.abi.cre2SetCompile.Call1(ctx, uint64(set.ptr)) + if err != nil { + panic(err) + } + return int32(res) +} + +func setMatch(set *Set, cs cString, matchedPtr wasmPtr, nMatch int) int { + ctx := context.Background() + res, err := set.abi.cre2SetMatch.Call5(ctx, uint64(set.ptr), uint64(cs.ptr), uint64(cs.length), uint64(matchedPtr), uint64(nMatch)) + if err != nil { + panic(err) + } + return int(res) +} + +func deleteSet(abi *libre2ABI, setPtr wasmPtr) { + ctx := context.Background() + _, err := abi.cre2SetDelete.Call1(ctx, uint64(setPtr)) + if err != nil { + panic(err) + } +} + +type cString struct { + ptr wasmPtr + length int +} + +type cStringArray struct { + ptr wasmPtr +} + +func (a cStringArray) free() { + // We pool allocation and don't need to explicitly free. +} + +func malloc(abi *libre2ABI, size uint32) wasmPtr { + if res, err := abi.malloc.Call1(context.Background(), uint64(size)); err != nil { + panic(err) + } else { + return wasmPtr(res) + } +} + +func free(abi *libre2ABI, ptr wasmPtr) { + if _, err := abi.free.Call1(context.Background(), uint64(ptr)); err != nil { + panic(err) + } +} + +func copyCString(ptr wasmPtr) string { + res := strings.Builder{} + for { + b, ok := wasmMemory.ReadByte(uint32(ptr)) + if !ok { + panic(errFailedRead) + } + if b == 0 { + break + } + res.WriteByte(b) + ptr++ + } + return res.String() +} + +type allocation struct { + size uint32 + bufPtr wasmPtr + nextIdx uint32 + abi *libre2ABI +} + +func (abi *libre2ABI) reserve(size uint32) allocation { + ptr := malloc(abi, size) + return allocation{ + size: size, + bufPtr: ptr, + nextIdx: 0, + abi: abi, + } +} + +func (a *allocation) free() { + free(a.abi, a.bufPtr) +} + +func (a *allocation) allocate(size uint32) wasmPtr { + if a.nextIdx+size > a.size { + panic("not enough reserved shared memory") + } + + ptr := uint32(a.bufPtr) + a.nextIdx + a.nextIdx += size + return wasmPtr(ptr) +} + +func (a *allocation) read(ptr wasmPtr, size int) []byte { + buf, ok := wasmMemory.Read(uint32(ptr), uint32(size)) + if !ok { + panic(errFailedRead) + } + return buf +} + +func (a *allocation) write(b []byte) wasmPtr { + ptr := a.allocate(uint32(len(b))) + wasmMemory.Write(uint32(ptr), b) + return ptr +} + +func (a *allocation) writeString(s string) wasmPtr { + ptr := a.allocate(uint32(len(s))) + wasmMemory.WriteString(uint32(ptr), s) + return ptr +} + +func (a *allocation) newCString(s string) cString { + ptr := a.writeString(s) + return cString{ + ptr: ptr, + length: len(s), + } +} + +func (a *allocation) newCStringFromBytes(s []byte) cString { + ptr := a.write(s) + return cString{ + ptr: ptr, + length: len(s), + } +} + +func (a *allocation) newCStringArray(n int) cStringArray { + ptr := a.allocate(uint32(n * 8)) + return cStringArray{ptr: ptr} +} + +type lazyFunction struct { + name string +} + +func newLazyFunction(name string) lazyFunction { + return lazyFunction{name: name} +} + +func (f *lazyFunction) Call0(ctx context.Context) (uint64, error) { + var callStack [1]uint64 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) Call1(ctx context.Context, arg1 uint64) (uint64, error) { + var callStack [1]uint64 + callStack[0] = arg1 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) Call2(ctx context.Context, arg1 uint64, arg2 uint64) (uint64, error) { + var callStack [2]uint64 + callStack[0] = arg1 + callStack[1] = arg2 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) Call3(ctx context.Context, arg1 uint64, arg2 uint64, arg3 uint64) (uint64, error) { + var callStack [3]uint64 + callStack[0] = arg1 + callStack[1] = arg2 + callStack[2] = arg3 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) Call5(ctx context.Context, arg1 uint64, arg2 uint64, arg3 uint64, arg4 uint64, arg5 uint64) (uint64, error) { + var callStack [5]uint64 + callStack[0] = arg1 + callStack[1] = arg2 + callStack[2] = arg3 + callStack[3] = arg4 + callStack[4] = arg5 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) Call8(ctx context.Context, arg1 uint64, arg2 uint64, arg3 uint64, arg4 uint64, arg5 uint64, arg6 uint64, arg7 uint64, arg8 uint64) (uint64, error) { + var callStack [8]uint64 + callStack[0] = arg1 + callStack[1] = arg2 + callStack[2] = arg3 + callStack[3] = arg4 + callStack[4] = arg5 + callStack[5] = arg6 + callStack[6] = arg7 + callStack[7] = arg8 + return f.callWithStack(ctx, callStack[:]) +} + +func (f *lazyFunction) callWithStack(ctx context.Context, callStack []uint64) (uint64, error) { + modH := getChildModule() + defer putChildModule(modH) + + fun := modH.functions[f.name] + if fun == nil { + fun = modH.mod.ExportedFunction(f.name) + modH.functions[f.name] = fun + } + + if err := fun.CallWithStack(ctx, callStack); err != nil { + return 0, err + } + return callStack[0], nil +} diff --git a/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config.go b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config.go new file mode 100644 index 00000000..44766924 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config.go @@ -0,0 +1,5 @@ +//go:build !tinygo.wasm && !re2_cgo && !wasm + +package internal + +const defaultMaxPages = uint32(65536) diff --git a/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config_wasm.go b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config_wasm.go new file mode 100644 index 00000000..2bf216c1 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/re2_wazero_config_wasm.go @@ -0,0 +1,8 @@ +//go:build !tinygo.wasm && !re2_cgo && wasm + +package internal + +// While we normally use pointer size to determine a 32-bit system, Go +// uses 64-bit pointers even with a 32-bit address space. So we go ahead +// and recognize this special case and lower our max pages. +const defaultMaxPages = uint32(65536 / 4) diff --git a/vendor/github.com/wasilibs/go-re2/internal/set.go b/vendor/github.com/wasilibs/go-re2/internal/set.go new file mode 100644 index 00000000..ab4900d3 --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/internal/set.go @@ -0,0 +1,117 @@ +package internal + +import ( + "encoding/binary" + "fmt" + "runtime" + "sync/atomic" +) + +const unknownCompileError = "unknown error compiling pattern" + +type Set struct { + ptr wasmPtr + abi *libre2ABI + opts CompileOptions + exprs []string + released uint32 +} + +func CompileSet(exprs []string, opts CompileOptions) (*Set, error) { + abi := newABI() + setPtr := newSet(abi, opts) + set := &Set{ + ptr: setPtr, + abi: abi, + opts: opts, + exprs: exprs, + } + var estimatedMemorySize int + for _, expr := range exprs { + estimatedMemorySize += len(expr) + 2 + } + + alloc := abi.startOperation(estimatedMemorySize) + defer abi.endOperation(alloc) + + for _, expr := range exprs { + cs := alloc.newCString(expr) + errMsg := setAdd(set, cs) + if errMsg != "" { + return nil, fmt.Errorf("%s", errMsg) + } + } + setCompile(set) + // Use func(interface{}) form for nottinygc compatibility. + runtime.SetFinalizer(set, func(obj interface{}) { + obj.(*Set).release() + }) + return set, nil +} + +func (set *Set) release() { + if !atomic.CompareAndSwapUint32(&set.released, 0, 1) { + return + } + deleteSet(set.abi, set.ptr) +} + +// FindAllString finds all matches of the regular expressions in the Set against the input string. +// It returns a slice of indices of the matched patterns. If n >= 0, it returns at most n matches; otherwise, it returns all of them. +func (set *Set) FindAllString(s string, n int) []int { + if n == 0 { + return nil + } + if n < 0 { + n = len(set.exprs) + } + alloc := set.abi.startOperation(len(s) + 8 + n*8) + defer set.abi.endOperation(alloc) + + cs := alloc.newCString(s) + + var matches []int + + set.findAll(&alloc, cs, n, func(match int) { + matches = append(matches, match) + }) + return matches +} + +// FindAll executes the Set against the input bytes. It returns a slice +// with the indices of the matched patterns. If n >= 0, it returns at most +// n matches; otherwise, it returns all of them. +func (set *Set) FindAll(b []byte, n int) []int { + if n == 0 { + return nil + } + if n < 0 { + n = len(set.exprs) + } + alloc := set.abi.startOperation(len(b) + 8 + n*8) + defer set.abi.endOperation(alloc) + + cs := alloc.newCStringFromBytes(b) + + var matches []int + + set.findAll(&alloc, cs, n, func(match int) { + matches = append(matches, match) + }) + + return matches +} + +func (set *Set) findAll(alloc *allocation, cs cString, n int, deliver func(match int)) { + matchArr := alloc.newCStringArray(n) + defer matchArr.free() + + matchedCount := setMatch(set, cs, matchArr.ptr, n) + matches := alloc.read(matchArr.ptr, n*4) + for i := 0; i < matchedCount && i < n; i++ { + deliver(int(binary.LittleEndian.Uint32(matches[i*4:]))) + } + + runtime.KeepAlive(matchArr) + runtime.KeepAlive(set) // don't allow finalizer to run during method +} diff --git a/vendor/github.com/wasilibs/go-re2/internal/wasm/libcre2.wasm b/vendor/github.com/wasilibs/go-re2/internal/wasm/libcre2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..9067cbdb646653d50a94b1c254d59fd767d32a66 GIT binary patch literal 3181648 zcmeFadz@WWefPii+WTDhnVB=W5i$YxIYdj8C|GW_t;`xB37~@2_GzD&&nw)bFcU7B zgh<)__*5LZxa8{XJSyDQeXgdsC~e^kQo(_J^%)dHPWJy+7Zz_c>>h zNeIRE)jxg-{jSS)m+ZPKan2>5PtUqISx6Qx_6rM+E2j%?(*^s<_|a`$ zzr!ca-n)xy)zf(4E_UwXrag;={lY$1)pZv)$~VI+T6X+zwf9xM?z=c!*tZWzc)U+g z`MnFtUheksC-%&3glyl%ovJ(iR&DL&!a&}qR`Zb}+(t0$O?&vpT|61HwT~4+M!X;Sm7V1wa1R)6SY#U$X1UZM&|%$Q z-gD*rHCJzY)%M*kJxrm=s?e@0e{B1%BNiRMY{xa1&28I#)QEiF59;K`YU%kf4FvbU3SIx%eVdLmD_h*?j}=E zT)%4jRoBe_s87?y#Vmbi?Y5fFb3`)Bo|!oBy=yj7m!;{NtkrDhiM{ibPCSC^Ygx^u zt&HMn%59dpF?Y;&tz5Zg?MV~4Z#I)=Gfg(;?Pi+$tkGz++wJl3ajK@1u9jt~tJPBP zTaAqW>b_fVKC4zgwqE1!vGw-4XV=%(8}+Q-t*6bC>-y7P$3LxBYhp!f#Z+x#y)Nsz z=Cb3gNUPH+f4g0mB#yt`a!aCXZ)>YE$4N`MW^LjzN3Gg z{?-4Uzfx22kKO9g@_(IAl2ym>GF#mMGb#V8FUFj%rrU<9ZF zgg%WzJn#u!*HhnU*3y*c5S3bxt3`R9B(9P1z^5W6|It8Ft2cp`A%l`SIH~)Zud7;; z@eYy$3O&|Nhi)~OHQH&y|7ZAGt)V9EkMAT&+DzLZpy|_gmbIZaH+GLI7+T=ibAgz!2g(NI~yP5Oj z^2TSf<0^J`6Wg{S#b||VuetK--P`BsX4|&iJ9cfm^paiM(}dUPrmMDHdG(dM_1NXP zU0-?04%Ces>s&U!{dwE2xpw!qtGB<}{X%VGaDVys9ov!AU#uNFc(iLfy6u`>S6;tu z*NMG%5QfEYU5TSKDuQ7RqnQOuvcGq)watnxpwz;^R&9{RrA+e zckM2BdpTI?z{|^r+fZg`MY?-uIils>UccMDt9D$3?2yU>Jh!btMBT5{B4LDawf^oB zdfk^5?ieX@$>o>3_td)9fQnpp%~jW4xnsNg)pCS-78`zVt$x)dJ1`^e+1V@Sw{Lfw znn|a%zn-{|$HD z-{i66-;>9aCz3^fqu=y;|9bxh|5N;ZBmZyu1^MtM*iNK{7mu-$(xh6CY#=t{Bm-8^3LR4{QZ^W z-N~;e?@iv9Y`QbKE4e%Q_2dJ|2b14S?nyS?oBUSt;p8L9Zzms3K9+nunb>rH@;k`` z$tROfC7(_{lica=_8;>1`TPC7{=*FL{^WDX?c7nYU-5tL z|IB~Yf8GC`{~Q1J{;&LB`>*+L_=o*B{Xh7B_W$Dl)n9sZ`nq&6y)oUNzBYYLdQ*C9 z`m^cJr*BQ)p8jh3-gIKqUFoHl{$_el`jPav(+ASuO+TJ~BK<=8XX%6KSJJz(o3j1c zZQ0|=YqNh#Z_Zwq-I7iGMD~-}>$8W`o3fwE-k5zR{rT*dvv*`~$$l|=GgoiR-pwM#GUBx(B(e|zn1wMkdF4N2jG3;UDDn$G3>oS)X; z@aR8fJWU?o>fN}pu&+upQgNJj5KTQ|kZl2*!;o{c!^W+s=Ji#9<*s4OcKILZ5@LRdq|NiVGPvwrm zYt?zL#+&gc%k$4AsUjB~-s!^ilaTJrKuF;>Id^V09o$4tL&>bYId{wziC&C(9{S}T zrprCd;=?gqvmy!ET+j1Uo9iX%wC-nnVEQ%tn}z4P?*X}=&K2o=SiJEy`>)>_e>US! zSn-77g$IgWN(JtGk@Aj~3pbZ%3@?98){J8s{#&?{{8_!mi7s^K`q>6(_dxde3dhiP zGE6@m-ta)yJ!a%7W7ng#qFvhakxx>g#ur&=&UQ19p6={BaFK0tO@yMC;eW+w5X9fc%_Y z_0q5qnnf)nyF*sgruxn9bNdP1tSgct<$1dMG5i(PE8q{OYDFSOO1sYicX0?JGROK2nDRGEPp>fo{38JuP@t&p9)$>(D(u4O@83FwSB|BU9T#Vxjqt#a_G@B z%*YUYcT#965Sr!|6T7UJ8k4)1fL$QS`t>3?uit>SD%Apg^}w*F=6KNpxrXNs{Lq+E zfmD^?tvQjssXmc(b=Kllt!T{kYw8p9LU3W4v92xLj5{;!f)9$iP|S;VBAeel=GO^6 z0GW#wROBR$i&`40X`GY%$%QE1EqvYs6%k=Be;Mk{y6>ft5DrA8jKPN|lAWUSY_}dU z@3Vc-`N2VS7HjZK0R?Y2nO(XJDeTD8Wx~ zDD;lRLjzm>T`D~$1u`fF8qk70PorK^O|O;SF3U(4<@p;*NRpHMD#%C|=P;Hhp7`;d zlG&&@?{_FPa9L`10fjg%@+X_`+e68bWRp(qvD8r^Gzg5cpoSsv5f;?RD#=XQBE3n+RkYiopM7wQ4gl4;8GU(HGb5PstQ*~!lJeKY`|??(E+UVWox zOxsF)RLnFOl7Vti4;po27Ua;`)~UWoXpiP%-2y)P{|o*nqDP1yBD_dIcf|r`A;kxn zTv4O&XmpH$kt#BG7u{5num_8&uo@KaT|XZws5<;Pr<7*|3q~-p8}iwp5miwI9vA}| z@dxad|A;jr2A#&KNal(JeN!=PXzt8V8B~p0NE!g;gx!FFj-+{{@;{jjT^YQHE=G(I z`tGq(3f%WnSXNi7`WfAxrD0H#ryD zC~QoFv^u)4)TgmI`9Nw&ZPJaLC5rUGT9M-P7zAcnG^#}AQ`E7?DA84U{w80mObiMX z?R$<8z7QN%sk=Hqw})mg{0?~~dfV-18fa<*)jf@4fw)@Lugw)+15N456uE%v)iAe( z?`70S+EtQ4Zv{;hn$=?%B$KC7j&(Dy>KbdE_aZHI$Cla+ECMdjEqLC&V@Ei z5r!9w#rQEekh92a#AykkM$9GeYk6T_RN7rb2SrT?t`*7E=%|0JjSUfU@KupOt%U+L z?E3YSd=rACVJ-GDEIyv@49(s1TsHUEo!;!3pD!rq`mONizjEt)esps`n-URaZE zfG$6+5*^cIwB&~^`9VuQwnSZkq+P#zuJ12|V{rOJ6KTOGuiJPrHNe?CCP!Cc?@sXE z@6h1Bo&7eg&h~49>?oQWjHfx(#}5%KR7IgbIV98&Pi1qe)Bp*+v7&0OCl@H$)35a! zDVTw#@^1h#n?(@DvUQ?q_hOiE%ve02e|R{~urj!+@2C3X1q_1sQE+W-H5iqAnhu`N zQI0Mz2L)%~0r%Pk6_09cRE%RgFG?u`NQyBq%NU9g3?BvCR4D1U0OrMVjts#^Q`1;1 zA{YP+e`r~JHgGs4-wF)|rC^^aB!wX68A2w1@rEv#lFxtl>e=TeIMuD$6XDfYAYk3~ z`M>&7=Rsq)rC0M%$WK!%jd7ee9Y!ChRD3QxlfnWg`E)|G zdcB7>*eYtd7YnOJLR1$L<_(A;j6RBxcs)_R4rdd}CiBmCi3*4Mo^YS;T=3W(?CmtK z?@PDn^6vD)(hp1qwakiy&Ytj))vDSUG#Y?Qbr-Watohj&jKyxM_fpkKSg|KOvTXH1 z>s5K;@(C1MSX=EFugM`axY?k+>tO>NSY)TSyCH;D@mQEKn-cX1# zxKOjbx*mA!7x6WYB6ZrlMYp8#k9w*LAoZNok;3%>K>fAn3)vzk(13sS+5ke=#X~Ca zkYeXG_;5mlIoTz+IH%yWg_cwh5c;q|g3PP5*9u9mDC)fls-^P2&}wG&i#gn&6R6>* z17&w}_Y;7TG~ zLPyvj{NR1E|GReLfWr{kv z?FIjj3%3lGM=v3<*Y z0AgvW#;&4$Uau|@DcZ9|eTwP=(`c$xsnOJ$YvXg&;>!fOP) zoLdcsh`kz5e%@5Cl@~4QLpu$jUG>2bTn;(}hF7;kc1k1J>Z4>+DLTY_h&c5D>0lD~ zl3vHSyckmfB8?@~tC!R(eRKB`5r$Dfx{ioZQ?p{XTKK`h;G z@~0?~%!Q@^2cNYt6|D~P+9)P0y5q-KO)60S>_kkkZA>u-XGsD{X4XwnAYi_`f$`U@ z>R8>#r1zj?4E+80&VIKTi`;}xTqzatJOzaHl<|!`gQ~lN9V{UHz ztajeYS#qGzyZqDCFNQ7tY3H>}@8O`l&O~{hH^`CdJ(we!+L)fzTM>SLZEvD8R&v)U zWKah+HqMMS6XnOUW`Qco6|Mp&owcJk$5c0Wo|(E1;aM#Ay@~6ru5R#TI;5tCEv&3= ztkMd&i|jT3UjVBWE2WuNhDTj*b*GaT$DnxyZhyr^s5OY)kjK?1R@@O9JHsh*lZq8H zjUPgER?MWg^j4tn7^#M7<5PQRD1w&a7*m@tF{o^9r7y-_wmsush6puhXzPal3Mh?; z#QL3fP7{k=oMwCWAULaq&#$F%o}=sYsoq51K}4F?*7vzH2YpjvtoSYla13!ZW9g%c zy2tez9dx*`0XP2E=Nt)p9x2A<5rtc0DJ|4G4W7szcgmJuK=zowq(=JMR3V)CuMNkBO^d}(d(IH`>|o&|gMmG~@tb#3_5azw{Y z^^Pl!Js0U(TTE8I)WT)5D#uFo*44m$E>4eNjK*Jr0T?HqXFQAkJP|BBg0e2)-9=CS znc1(R5vey~p<*El$V^#LHSk1Yu6Je1XxYj^vS`iZE>SERIl$E8=tF_Q@_D%DyTZc{ zxMDTM`n9QW|8v8EPYTb)WHEW^RKVj^ml{PT*V@VYV1)l`M?!b%^86`i-9{bhF94du z((UyD^+3NuzjK$0KgA+D7=40syhFpAN7es@QxZngKgS^$dQsK7JKWxz?D*P2C20eO z)1(P6*6j`_To+n9i{oZ73ayZ1-UAn+MPp~bPPeVlnd{X`MmS}ak zpfwOp96zM5U=pu3T1Sjpn+pxXGpdi&8@BLtuIL??4xlCc#Tt0NSaaKfw}Q_#2e>La zGM$??PxU5E&UWx<{`oUnXzX#dq=VpbYTjfPF(*>p)BTu-Eyl&X-U8v6y3 ziDL3CB^DkEmq~QriwN=O`W)kW;HzfCOyx}$^?Pm`BCIzF?}#R70&8-PT#H7C)PZ=5 zD=MyV?vgR{D8q9Uamv{Q{(QhS@EU`o*1yZ6!I7LQx^w*r-08XV$8b)0A$WA5;;;20DOmvffts z8^!!kXexzu3ds1*E36?jMj5bV5RFBJ>CQJ4#gUc(m>TWZ4Jq~SJW{&wS%sAQZ1T%c zlAwx!+3yNZck+x~&o8sRwokBi%Y zhspe)3{X(8Y~!xp#u?XJL7^3vgP6FfsGW{Sxbfz_{q-}8KlhEVq>FMkiuDw*+kH2@ zfcJ{t)DYR*yeJF494pq=({{0fGP!)#y85z^LNDamD%FH?G952Z#Zi`Jgr@%a0# z-CoU+Itzz04ADQYHn?VgCM#h1R zV`p~&8-uoQ zT}3$JclUc?|Ha{5mlo@$`s*T>&Vp_A2|8K;Ge@}wECos#szR>DPH;q25{(?4Uca-~ z5~ai9$G`C09n{3drCKBU+Pzm~p>=+ z6=T4Vgdy@J;SmAFQ0o$pqSo(TDC*Iv^)1wD2Bs9;o$4l_VoiT{55 zd>knPIC)sBS*o*-NN%>b+I)ciI#~JDaKEe{eW_LB02oAJ08G=qcEIg&{q&6Si{G!6 z8)Awf3P_#ix9toM;LtKB*jrb0G#-=%fFcq6f4(NAYDMS#DQ>C)#n|lfWfWg4T)?eaYq_>H`3-Oai!@davm^dbB-+D9I*z>BJXQ$ zv3iN?HCDM^Q^i_o`n*hW;M5Fnim|QuI26_Ya?QmEIld46UCi*D&w#lb@p8r@v(zmf%@b;BAL+(Ma2sQQ(el zO!-zADNg8Pea&W$DvnXUAwfCESPUa2`>69Fp8#LK-Xo(^@{7&$%4s@<0o&k~42P^r zXzBj}!O^6kbSc4G=ZgyPfg)d&vGi;UecFA738Xx1SNxYM2lb}^rR>Fztxi);RhbYY z8C9%AC|kWT5>aMjOe2GR^ZeR~90-#5b_){UIAzM7L07q5aF6-h=3c@g%qB8sy4gBb zho8{HxN(r)lx6jM9)NU@mwz@Vma-sG_NRo10QDtfEDlAZvC>tkFkEW>bYBiDtmv&* z60oL!pnjG9qey!ZPrSYFhC2pnKy~_#M7hBARU)uhe-RVb>+i4$m$GsxOtPWF*dAj; zW}B*#BC;bx@XGWfumFNmZWiMo1Q6-RJCvy%4boT4O#BeMv0^4uUQ+B~wiHi{CbH{D zA zrHrvC^fO1+nS3>*reOk71H2zH0&0Odi=};;j<;A6r)XA28}})SK_?6nYljZTBJSZ} zj*udx&{G|Z)|b$wVhV92+_hEd(F7DLDPOF_F@ygHWW|NI`7N0H7+j1RB$n&F;v&l! zM>VK?@tE?s$TW@P-FC1AW2|XxjW`lYgK{tZ+ZF(5P@9|Uf{TpV0H}qO@k$v}IIW`X z%B8ejX|!EQ>F)$>N0?&*tzgswpeh}5C^Qo#G#FFie!`%c_zpoMq!|`atkv)>8w8=t z4v&xx`VVl!$nYDGtQvkyeAwW{=mS!GM>*3HAC;IPY?V8&034FrH z8W=--3`C09C080EfvFQFb5S#BW=#h&dwP=Ag)$+r3e*@zP_uol#^>omPqRnN_0O`3 zU{!vvcQILh@V~Uxnj2qHZ!~?Q*>X&KHQAQg%xW0?avoT{DSUKA^4$qDdRmKp=&MuQ zl2@TIODqqN&8n`=1}Ld5hC)-UMobjZ=l0|Do`L2 zb^GgF-ezIjX~A{B%jL&Vy4yyHr|hoLb`9H*k>@X@G+>_1R)F0QRGXeytcJaI7LV}L z-81d_Z1o@m%vzCCY<&`om|_LIHka3FqkD4x=&AW&@kzDR#D3#8g*N*|?zX*CCb_I# z4*p#q%*=Ww;_Sd3&@Xvw6T(`q#nbLaEyW@NNji>R^O4r>XZ1X5iCp;b`?HyaGr9N> z7mJJg@r3SUrLznBKbXyUT>ydwSmD~8;fwG6z?maFI{=YqGjek520 z=q(?#g_sdeZkE7lFA=)K!THc&)N%Z_gt}~)exEi5VtY>+2hG_b4z!Dgp^sp}^^))g zkYd~7*qaB2%gcwspo)jD^K3yEx2oJ5?Ac=<7+gL&xRllk`|rl%Ny4M=M`?*xV%hMB z?o^TM$GEnJxqd?|yvR>{ZEM9;>gVE{TlA)ErmTOf-q@og6jF?fwk$t<_K7^4B{2UQ zc<(EB@3{a~!Y$hK=fWT9#p@0JH+;JpK4zCTtq7YxoM>9_Q&x|dfE_(yN9 z7J4px#o+9vLH0e}!#XH>!uAO#HQ@tLYg!Sdj$)T=B#+PBc+^;ou_UC`6| z;sik5b!m9S37(P(2EWmwP>horza z(J-}l&0ffU*(zPuJQwwO@!s<63mPKNz!X+u$YLySFIB=}_{g?JR-AMMK7uvHNBr0} zLfsiY2=13KkaR%BTFn0AKN04Ik1p84U*sNwT)UH1Y9)g)eZ#809&1e^L!m90_tnf% zJvVI8i#{~NG7u=X3`cfx_yn z)sO`3w1}r|o~7LAIfFWaKuHfR5h&~nbQ;(LDH_`g0i%>6#ce5m+HDoBESr2~+9)$r z&!w5egz;GF882w5a`r>z%p9_WiXT?cXbj5mGR`L98d9MqNGh2)q=IU>vb&+lrRV)C4^FwB1VA}A)t~XkPPj5 z&QHS)Y;h@ddn)Ei5Skw7mw-@C@X)s6g)4%(`(fc%bVqbOYpc#yA46f-B#8S%pnU%pCxor3b;B_Af_F8Nswr~R}s~W zbV*;mUcwE*^*sN_zO16DywXvUgCTO^0%@%DrHS>rydxXCdgkFAqGR2wpz*RwL~je- zSE=?mFq*sDsxNWnO~obu)s8+>Yln68?=8m&{GTLq&$2s*wnNz!b>yN7cBCU25%Y;* z(HwvB3DZaz{@e!)N7}Vh_zOT28%)OBXg#ezW&=YNQn20|B0Fuat`ICw4L3V(gcQa> zw}g_$;857`JQf`38vjgTK9x1g|Ma6LGeW6>lY|lzI)ouI!klp7!9^`jTFU;_y3YbS zZ3HsdW|=50YRC)Q8rTJ-wQ@f1rKWa?IVnrbNHtBwdc|YLUraOfOF!Aq$xNuDWNxQc zJ|H1NJY$p_L}J|LOX0`ziGC^?067Ip3NSU^)cOTk9Tq67F8xCkw%S{(O039arhrOw z3iBydX1a^!{#Nf)*NM7+UwD6IO6F;3YAQ@P~9Q|a7m8n>9 za8hYfnRyy5wE94$I!u#eNUtx_IVJ+Ai4N12#K?^3VdN5ZSSdijBb}5T6wpaC3D}`# zlKZI8FOyF8ieZ5ZKG2ovE}n|CnTcQoz69Nz4z7nlC!1UZ6LyHo6MoeQ4V3GV7C={M zMhq79A>(05Jr7YXV7g%SF{>XmJ0G>Hs4gw4xXJWtV=!PtI>U)WmO-zT#zB?jvRWm@ zJdM(Zl$07&0=>k;YDlAx+g%A!Yqz70nuB>zaD|VKnz07e zs<_AQsi(LntsFIugpr}8#iR1mqT_DS&yv^&`b1Za?W;>%HP+l+9)V|jOs(@LJi9Xo7{Bl9J9Oy{vgcdUUs z);OFyX7+u3ksa!el~IomiTtuMPZ&8ddS#06U^|f=|F#OZ1ekb`Se4l3XuPt<5xp{* zAfn&6X{q$eZ1C7G@n#miG81vdd16BKpBkt$HDI+`6n^xUHlM-cXK9-SDvLPId^Y^msEFX(Guf{!rGUF}HcE{r z%uKKw8U1$R@=DEeR8kbinB;Unm~A9ut&l;m+I3S;xwkyK5_0B&>a{7W@Mh&VMI0A4 z;PN48NwC#mv})4`whjzvHjg=`Q78w~mfXq>iaBQ65YB2$#;8}MsVDhz3AQyFFW zAWX&F4hS+1NpcNbJ~Ms}=nqYFaHnQmYR8;d(BR=xe>g6M96HARSj--2xP;f1yRmpch_QHpea%wgiU*KnH`uaF6&OIc5!2Z~s_c|`Djaka)?!%E zPLyy&2li_L4CE0a#FLVhKv}#9`8Tj4E(5GuI{9*ujPN9Bq5%WFqKJR-l)TA-DYHHg zCH&XXDmklVIy$;n=7F2Dw#O8Epygp<_+6iM?sO z(}TB5`(+9lv5*Rf_E9#VJ>tE@r${TG!j^DQOHKq$t6tTHG(>DeBjf3+eu~#Hl01#K z(TPyvg=4M6(s)^jlai-EV%6{xh^NbYPO({%JT)hx%$@4c5la{MrTsw*J=2JWO~%!7 zrvoP`K(YA5;<&|>x=st8#JJDGA>&B?4nywYDBBo+poKrknQo4L?KyD&Xg7O7lN zYf>&~w$ue3G|7N`>4L&1XgC;E>1+6GlwVEJ!KcYFrQ7*5IA+xCJd|Sqe_4*PVUc`Yj$;mCh7r1Q074l#NKznM z^f+bs;{43Og2QdRmdELo035a8(Z@3j4g<)7^TRQdB2b4PhEXN}0*LvnM9{#I_>njnWcOUm?y<5QVeKVm%{geXwB{DY zIc4{#Eo%-N$(oaOsIq%iOlm0>8;gz!A}!VkYf+D^>k3VfF=Ob1I!j71kJb$@oUY+?G zhVJevlDqcx(>ruP(ZxaE#1p^p>4v@q#HEl$U~;w(w28b)h-7%b(I1Xt)dRY;%Y zH?}&<&(oR;A*&5(o9-8NR5vF zS+=V5fw7{rftrH9qwQy<^G(nV^Fp7V}0qzqQj*G z@N>B$P69OeNYuv%Q z2f40;beOrW)QYaF)w4E?zzPOoCu3=zaz3IIxaGgN<$OWAjVw+29G3RDt{&G_-X1JX zD^?ATQIa6uQ}0mMl~IYMK~(9wmbwO%+5l+aV3zhvT~~b6$kOD$OnvFBVuh#Xx*EKq zvWvWBy0lW|)385a z8DAB`9-J+;7NzczfvdW-MPoe!O*{=p$Wyg^=qQ6Qd1@?jh^IQ>2>kL<#u@cgsXWkm zhcF23Mg|$td18>tQ+=8YQtG^?!62ia>Y)q*_)6#=!XP%RWf^1{Rv4jb^i)M69XQ5` zI&o4AszgWCSE(j!EU#@LksJba`!dLp@oCw&{9qgEy={nq4i~Alq$qj zap?F^)}id6x<|ED7_h{wUIUb#m(c08>g4%?ywCDXZd+*@+Rt}73(J&(*0_@V&}p!` zw^bogEf}ag+Zs=G1>fW@EWA|%7J1Q!=ah$FbqkJB3ml@&vrTS-Ge%^_S^fG(KLS9? zBGT7=k%f1Gq>^oK@?Fm89>gA)qy9Qz19|6Q9?C6sq+xV=AWM@Jjj+Jg_G@{tZnvDR zdk&-U-PP;zShs|kR!Hxwv99nALCYbqgSr}m?>cXS+7Zn^xIlk#Xx7WLjr{F1Tu81BNGc%xK1+cwVd`*kXp9vRKqsZg+j z;5>qyTNG5fu$X9dw527_;RmKG;@wu7%EFt(CMVhDeqFvu^1;Rjf)F+UaELq(1lXql zGSKY{z6@Bj!rkQ`NJdZjh5cTnU{G_=a+WdfJc17}*?n#Krx76Q*BLQ8Q;K?dif&z{ zHESoai2jt;Kme(B8_+M|92t9-?oy3GjUK*xP_>NnW~fxc42TCGxa{+dgO%J7ndqFff*8XyjD_T5%ZVq6C^@vkwx;ASUQ5areheqeGl+5rMzPJ!xN)#~M zjNA+k>la~cRsP7w7GNsRA^rWdJT9Z3u|a`{I2XecGgx-0lta{$@cuUwOBBRjYU;%f zqfWDZVLjy-TC>{oPxGvi_+GR&g29%IqQ*Zr^y})yM1>Vy6lbl5>;}j}{`4Xql0XQm z$IxabiIqsd>%gpi;nR*Ku`C5i@8n55+hcEDn_0+7kbo2OQU z2V79sp2do2warr`Fj#TK^))-g_AOe$=qSC#4)K*oWTJkn4Of<_usskbCT0ye{aA7d zJvO-w$gg;UQ)D+-_jZKuX!jsBeuv=bx|hc8Fgxv;5j-)`>9iZ9{fh|EZRsJONYPx{ zCg+&&v%Egzz;=jtaj)0qkyIEpZ$j#5`5*&bie(HuW=d@ccs=>or{*Hq^L zxuE-@f+5-iC!7~DWyy0pe;gvCF<5`1^`e4O-4s)dJW)g-RD|d^ z1b;ZY=Sz(#z_B5vB9(TDN>O@-54njw^%=dt0^M7tGF(pxo;Kax~Yl{>om(Q2jk1{xnuL}%9P2^|cCVEx4RuLx+ z94iODbc{WH01e_&=^Qc$>&rK^<@#FDt@&!r`cTR?8FOK1fa)MhjDZekpFO=ggiLk^ zmew~H3Tjh?uR<~Sbs&TdKzwr{9WX^=9*1A z;1`^ks62Es0!}=q^!FRx@1wS|Q7qfm23Cfhan5F-n<@ILipFvlkm>w7vO9d?h%ze7 zF>M*ugxoCTw1TTFl`a(Pomi+d+j9)fs8HF}#6BxxT;$^yCUi1Q#W2$R5wTqw*0pG` z%C13_P#Q_GN~EA9q^N4FGEyYn7pNHYMGpd?F_9L1QC_nPTK8zuKU4=|cLrq}Eo8g; zj{d}JNT81XqJoAT9RMJ)Svv`u3>~l`*wyePxpvu+$4Ccgl%<7P2(l`cFkDyz zS{!1hVj*hSPyhv@k)hheE`XJSPfu(6xF`vDAJ(YG8`TJd7x7iJsweI)325JQ7&U*9 zNDw8bR>(0+nj8wA6(uKvOW0nLXeKht|Iv^5=L7S{dox)75g`|vusu%4?GyHR#)T!+ z@Jh-^78EUa@GO;$Wn7#v#7zeg;tdX_EL$=s8*4bJT9fhhVqa6^YFTENXJSGQzD2ME zw@z6x#Y}zpO!~uFIt(C8e;9@irOH5e7)T;16$B?X49ZIvGUH6=bsJXwh)j+ANgq`b zORZ@1@DbaB2f(`1`HL)ggj0}0$}V(6j1@X|i!yeAV2VLfkO(c(!WCbby^5SfyYEP< z$UHh=h1191XgS>Z!L0iNp*?)OR@bj_G4dA0! z;41`Q0*4OZlSP((PRiboR#KT41`FWb7Xn}`;=(WCuj;*+;S}7Cd`lTJ z%Ob{T9Sh1Vj&xwZ3}UpcReegCdU#Q;m|4+OlP@|Iu9iQSS7i&7g@_R?u;f8?AZGN9oXgj9ut?m1%L zroWWV!rJ1lg(;njn&%f(-6vw!Ww-={_~~U(4qFsglE4O50Y)Id75kUQ9?#{ja^nb|R#y`RDGRkWm zHXXU{R%3jCtkO>F%d``nl6JB_MPPZ0Wi*ViM-S~JTkcn+Gs#{e4SLHk2R4XAZ40QH zjRYNiL*EhuaX7U*NYKHV8V=qa-|azxUcCJuuUVHnAeGM10U!)P^4je9Ltf^}xxj~JGWHDqHILl6+j%0QXmb<1JL zY^E6F#B9W~dmd*KNy(7Hn4<4N!x-MB&C-D2i%phwaX|IKMxC}m3(=KDOM3f!fbtoT z2``&-eu$?72ljt9IWLaV1g#t;s>()5%C@AN4zpJyxOPN4cUkTxwAf+*Gqv{-JNmnN z%^?#U8D;b=%}sOo(#^g7+RR%4M8F*Ta-GU(ZQ`CMclDby3$OiQ`XujUyGN)*r*>y% zS<25yorGg{gxVe*f&Q_-aI+j2-vb3h?DajH9Bl9$Ajt~Wc|^m@%e>E>M>!+(ld^6} zV%jo1)C~{Fu68$)4Jq=w`VHjqhoT>L*US^iO$9N<&HELgh?S0vWbiWRLEoeTxkXc> zR}yPBCoX#;z^=*-|YdZ4zM@nI|w9wS9++j*kLW6{7UbIQzoR{g}5MOrzsH z&m=cpq|;tg4QU{R2T2Pt;t!i-rgy{{=|aa%B0jMp8o8mDB1Sk|MeTpe=Z$YHY1+E8 z&(qgp4=97iDy2^1$vLpm&ZPM^SxPC*MGU{i;F^0mN#;#DfL%+Lg_Fqh44Io*=)MTs zgS!hQa1^i5KNgytG*`G;L=xdkX-;-5%ddFK?JKCVKToZrcO+6(i%orK)t%$)&qE8h z_w@9MiStnP{5Iy`@q=Fe`!T%v_hZhR3Xf0B;l#ad zpFjBJBUe!Gkt_JL*UwDM$`^#J*5&M7GpF7B(cAN1e9o~#HUH~VIq?%Y!;j{~`{Dao z%FcaZT@mIid}ANqS6JIyQ5li(G;vs>@O!W3`RRNYBH@c4dYSTnWY0uDhcyaPZf552 zKcbN{q}e~%IJ`)j97n9Nbtvm*tbO7n^;q6!nXlRmtWY}34wh*)-F%@7M@=;a`%si;d zA8FwBMTDan`IpGOWPvl9aLzfm8g45v)=CV>5oGra_PlTgcx8Cam}~fEZkH>eFL;L^ z*RHr_8{h+HM}E!mu2t=qnd2b5Ro#z&;DydDF8tj8?$s?t52c?1TYLPSN zSNJ4ikWv{uYNsujFZ42-QW^q}GDQyHC#4B1Ry#5~AX$9x#gf&h%!TS~@~}<^F(%=w zP*1;q!4AE37*MHixD{tip8~KWG_i7FBM2IS&OE&%kk{;j+^W()!!fL3EDmbHP9nx+ zYbrzmKi@@8gR_O}hoQPY9>lUF3>dbSM1>~Af)0T=sAa0Z%-V_5@{#${I0HHQ$b3uM z(!$Cbt&TR6M!g|__~;NV(TV=B=!F=JT2lG3%4kDBKHMbHl60h&?&EIEs+|nAX7m*XghSID8@IQrbEKFJJ_kKAMLU)NZ5j4Y<|xW zU21QE`(%!m*EikMMB&C!=^%Mp{%GL#5pEyhrW*nw0Mulp`pAyH* zN6e{fr*U-UkuZO$(N$pWL=#6Y6eQr{IHJaV>j-@+10o9(Mwol1ZNC`Y(3+|5iRE2Lhn;}?HpiF=+hg6@R@>g zG@bmaB_ltCVU{93&GwdH`Dr}P?1q`fP5o6D0aMm%0-vV1il!Q8hdFSgPgZHtbJdLd z0WfDBQ%9dEXwEcmD2o%SG-Cl+u0ei&Z$zd<<-w?QnbdkIg`$_mzY9MgFP?s*^t^0L zaLVH=5x|O>jEPhS9D@=J)dpKCc)hGh=r~XFo_E{#1vrGi=#naLP0je5_s$eI5Ism1 z@A|{*}0^!E*=~euJgHbhmHin!%WZesS-><(r*VlChNTf#~+j%Z67F!3PICtqz zww+JiPC}R@$NaswbMXFwV$E&+Va-d1*n%yK?2hh*abn60*0RC7rHCDZXTdvhgKQ$V zrjd~lma=G(rIES9N+cZ9<(zVe(t=L?s1T`#kg51l2sT0+^}OYYo-)o@PWBvy zeuyn+rHY2dnE`fYO?!W(OpSm9mnH((2~=E_313>!A5js?f?yDfy2S}p5m{5x;l#oxx|7_*ZnbCm9kqIq(n3wt_%D+Ahvtny+5^PLLptw_Xp&ei0 z&ma1gj69#b_b2!o*aS@~Bb9=p&RxZXfX2(QcKXTb-pw4xM~JeS8}+T1m+MO(*m&?| zE0q>ykM&}oY*F(LKHd=i@0lfttw$Dp}eV52EZ1TxK1^_Xz6)+2Pw$itvz6)Okv1|{q$GR5AV{l}Z z%9SZq1=f{)`2RR%c_VQU1F1E{tB zn%jGPdjO?+I-m29*U~s2w!EP) ze*GiZ)a2%Vrdc%*#)ph91u^+YaKEeXpM#qM@4A@<4~3_-?%`VV zyrMM%0-Quz^JapvBy-f;imKIZM6&iksw+eekhfHXqKiSIx*$|+Ou(l`yB*l09yKs|y z8wd>|20=~phQcZDx?dlmF=X8W5%zyH0$bDx^osgBadr6=DK7PG1Oj5mlKD`D%c!L% zKK&d2z+RBO>`^Vy4uPG#aO!4#qM-UP=7WTa^#e7)S^QlJ)5ze}*XzCXYiws&uCZ>Q;9zTBv9C|=^Z@;amzq@=y1i?Op@ZGG)r!d726vy6%M6AU_LFWm> zjh)fmsPJzgZIM@Bt(<=0D~Uj;!uOMA`(xpGv&C9VfU^V>oz>Vf&zBemAShzNoN7YB z<{`iw-gEat8yj?wZsQ>-$R!@5T>HgrmMMaI{%D$23GvFTzJz3gAoE+yB?L*{Stv!O`a?&!n6PwK)Sy)NyT}8^oWi{iE zxgTO<`HV_AVVTaHazj6z`L#E__6wi<_&45}yv$|-ZCX<88jgT+a#{j@Zn#?q@)*_Gwl8^T+4seJ*FB^AxPm) zmb=NvJUHwo{3GvlEKNZ=RR}YES%tU3yw~Udoz^biyyG!ycJ+#RfIrml&b(WO{R5{ ztka*h^DW>9ptJoVdDDgWJ*WF}mmfFSZ;`3c3AIS4x^dqbEOdpUyq*3S^w^W6;hHW$BZCPIi%jn83 z3cMsh*Tiae=D?$M%Z1ARa|QA%wqVJ$9H6bGsj9DL9YV%bWUT3%okm6pDc=ER>RNOeAt1=YlA*h5mBf`}u2Yy7ec+!X z*FQjt!59UxJ}QWm6Fx-841A=e45p(p2o!YBF`1Rb@g*l=q!}?%axSZ)B{?HvC2VkT zF#MstTcs+{K(sR57z_-Q3?{rq2Frhb$#yI;udz`EYQ!T0_Lka#o<>TU&UQR&OBHK{fG>5 z?V(3^yq}7Iaex0P8KWE;pD~W7B8LU*^_GgF@BmjJiiOL6I4YzhqAQ9a;wI5gQPq$D z%;4I0e;9qP=Y#PZ7JI0xQSs-xM8n&BrH7*Kr^ib78<~`9R*=v(eoP6XqTbhDTrYYI z^*-Ty(PG-2Lr4(JmT5zd$#dN|)ueJzY`B1tWtIC_Y7BS~rLzv?ER^3(!y@S5ISeH^ zXlpi)1c~@n#o%-bsu+9LWg_q$xg;r6wuea?;qB5^MBpk_t)>0-fvupXnG5tn-ZFFX zKH&euN?(_FkouQaIs{*lZ2|JIcoK`(26&3Q+(z((tz|sI6U6`qJYmcjuGT4Q$PrKA z!?ak$0!K;ed_hn^fL9eMhwh_T+nxq={m@F~w;v<|Xyu^>gV&_(1&Rz28d?H~tP6~} z$cX4vCE^{AWi?(A7ZU3>3M~_SQf!J72a>A2n``&v10j`#6nC-(uGAeCR!UAqg8x-= z{wBu~Canr))vU1|(xId!aT!T6u&r!B3P+9>lw-N10AT8LLwQp$&KzH^34iPW-%9BXr+2sB?8m++@#3=oemd=jwnH^bMk zY`9Y4*H478!cP}PW=ps;R(M z(9aqE9K?ekHX+HQTo0-BRRW+(j8z!ZWP^%~2(htL3&I38#OdPH&GBwK(03??wU6cL)|pGZgLc6uPKCBii9 z?-07A&xG(JpsS`0pW2av46F2`1lX^3!K0U^9%Tb*DukX;xd8ZSLdkxOBOg|AUFa;4GrnIXHb z$EfKAurz6HSQvnX(hyh}&j=PUzy(Xdq9x&&56wDK$5^?tF9;O-qD8LQ<+XW?tkr)) zx4GsMt8Ot<-}!;*d$Sq@noT~D5qg!bOjHZKIyuN)f~6pFr=P};CbRA641con<$$r}9^z07Tl&4pX(O=PI9N_p5e09e;uY*1UNTUiq&U|E;jGA_!%9kPZ1hH# zY;vbdCs-ew+-YXT{T&&e0?Oc<{~H_P*Epy z^n!hFH{Qt-1e}AS$tfIqrzr%$l(jN*agr(flhl`)SD+JLU?RAZjXOg+4^yV4p=M_a z1sf{G%#hPB7F%p>XkVY_pYi6r34hw=^PeclL#u${9mwR-vIV0t@=~*E$OkFc*p#_X z14;>tLLd)L8>=Bk#zapUmqw?jg3P~5NLh`bQZWIyqdE~^3|cJFiMGVi2Eubzrj|O< zbV??DX>??z>NL|%A~^GPLsg&$r|H(dZUq)FQBfiD4DBMXveIjK z!qFkMqo-idnB_NDpVFs9S6_lwy0$RYz~4n7nmQ`WNmZ8I_psz8DxRmrHX};Fat_e%$1`+&t> zQV#V-$^}0J9nNbU9cE|kwU$gQ^Hv#JDj();xd}Gu`8+JXWa7On!y9MR1{0|WnMa_FJDJ+CBdckfxIv^B2V=BaYfU$Eu4RKKr!Kku$>b()Q zzhj|-ov_czRD@~vkG+-x(*#bP>LdcN5UQF2UEp5pLA6#2UCaA9?s74Q=E(XYq)3Dk zw1`3ZLqWw9B|1`h1KFEF>HyA3iIKoBPd^o=3;Y55mvE*SlK8&BJuf{$ZA5JbQxgtJXvE<>( z_;BTthpXa4`vAcJpR41;)k{jQi4WH-d3X%`h@il-H7s{z1@RQ3kZDVUE{F&uK@u4; z156`#lUgtV$dO>eLh@XZz3@>~nJ&ZqAF{JEU`2#R`UwTf3v)DzxUMs77#wrH|1aG} zZ)rSR_NfF*oQlDY$LS7Qh)wFi2d+#(!k~ew1+dL4`3N);bv%Ov zoH0SWbLNF3>v$g~;TQ~y3m-uOuGL-_&5!FlbBrCcGJM|A^BDU3;Zx=9%BSh@DREi# zG#ftE;S*)q+VCl+PA)Zpw2vbr+7`KcCzo|tHT@hc!Gz5pzC zE9U@1a&Sg8{0eqf!lE1}`u>ciK7Zhcx{(Qt@EDB3JckZtGR*}$>U(G?w{?)$W&yR2 z#Z+i|AJf2^AGdzU-&$suM_VRXrvn5uB7_6SxnngP6@=l5kEVPP%!LI00m>Gehll<$rUqqrd1aO&nh3bjv~1wxiHuJIt zCYNAPMKONXRE$<1Ia|S`vOa8}Hpm=5!{13dm*$v<9M^))g1x?hV_qq(?+m^Nju$7Y zsdQFuT`?Z-$7SuujqZ65O7yDH*-|M@6Qg{2>?A5KWhgYv*$%w!IRhB_i);EGe#nMP zkGTG(b}Ug%UoLc8Xjytu*k(vup)_ zQvI`n`}mLj#G$4oL`dmJIw7H*6^}5v%KuIxAfo!Tj5x&eIR;7az zNUF0)d?L4zcKDyA&GNRD+|LGWbOC+5?h@~tDIcz{747e1Hy4YdxcdG?saajI%v>7? zxZ+q94Jg&V5hx|z?PEmCMR*uMFs<1vu`hzB!&0hU6oyGe&m}){SXi2^~TJ zP20R+W{z!LZI!rU@7`XUDuuhV-_aQZqdfvZ)uVNWe2tA!c%)&Kr){;&5hsIzM+C44 zU(`Pe?>c!E?N2q;WF_>G{cQv zt5Z-w&v#wQ{}Y}@QmjCICG2+5Q(|HLoQf1O5hAINM*h#mFiWd@V>nPP29gaFCy{Iy ztN5@<84Vx)%r^6pyFa(jIHTo<{mSU;_Mb2*nwIqk@+%dM$*re$J zPZL=jnQ0ZvpglRag2YKvyINHx@)04|Lr%t=p96ljOS~8M$yGAXhNZ=Huk{ZEW6EA= z2Sh{zylfx!U?+isxI%L=$!-)m^Cv)iihXl-1w%wx0jpM(&_1z;rH7;qbN0T12R5&+ zsKI46&^StVnm(Pu0U^9ILWx5lEWuli<04%O6tWK5FX2Kx2W}LRjdOB)gbs9RRCxtR=t{L zkvf6HD1>_1+h23h*vg_)ta)iMIe#vfLN9q3^Nb|WY!E3AtAx1tt?^C6VBwpYf(06} zf)w2tSb9$CoVABq6wFgQvpI!LUH78iO4DRBHquJH-SE<}37cq@Dk{2Krfdrhi}4DZt140#9i5?NC@oPoqLIzq+Wr{p#_WM9ee*Vsjz#cD%VV?{UbGA{ALt6} z^hp@Qva#0X7U(3xF9T(Q@{mI!r6vU=eIxG(9*LR`y`r8e@?#g6X_8^%oo5@wQH}y< zDINw^wiQwK6zv;|S;-Z7FMLELVQZ+I0x=R>RC-P9urAH?E^pk#AukzYn-6nq^}PE` zOUpD&wa`xFNr^Ekh+F7OtJgApx-=E(9@2KKw&ZnK(8E>HFI^)wc(+&FlH&L3 zcP#&(X>^k1^>L7WaG0D$)K}I$o>}&EP6BJov+#^Kke=`f$t%|a(~c5DNac$Pa35DD zYg$q|#OFVg9yHGaX2<2{J@6?Pe(ICdz_Fad$0v`e1q(6nh~*>wNHN5TQ15)GYHB$t zca0&zgu$HI%5L9PhZ=k6eTj_6eV0s-XOnaatZd`=zP)<^keLZaenid-4E9;i261}nWqDhLy z6Ew8)E~ODw1v4rDtlHheQ>j^tN6QAa=VkfAdc0g|`Y+Gdkcm}FT55)7Wz3~+PaNixHqm1>3I-4oX!%p zf_Rr`j0N{XIwhUnPu9zHNCb6{lj0oYXMXX z$HM8_%581^Q`sAhxl}B!#V#zBo0uyo8-Dg%tl&Oh@e1wg!NcPMi{8p6uTgK17SYR5 z9B|^dR<1EFuTEd8((1$e;nnb%tceYLUeHfR-vgYY=$@gmE3yL;md0eVW1_kY2(FAt zdFh-=rzHf=o94zd{PF}HT;og_n-n3FrPn$$gpV=ljCNw@ehY!r)IJL>St&^rxF$S% zGpqI_U?=H~#Htlf>S~#SYXzps;(3V}l{(ggqv@mRU@^cI1^-Y(b`mZ?DuIEusV4dL zI}}A}gJ7pm#G_?~pCA`K8P;gaMN&-e4sTgp)Kp;tvAg`s9@#CuE_{X?Xq2k4HGOV8 zcS-d}ezL`AxH=485-_2~4y=H+oxm9b)q=-1Nv)q)i&{K|&6w|5Y+?>4*t^dzO||=- z{#(@UV{k;uKXk&z!~aRr>=_&Djb@7?9Tl6HT)Fy~HS5+NubYh_l=&o3`aqY2F$8CheSjhl))IlA>v$)ut$8n(3w|+(*#4|}*#LHN)5$YF=ZNQ6s z-6F@~W}RZ>Z5O99zhLY{-o7!uJ>k%|ecrw`zCE7KPxGs09v$hSKTFb)78Lz z53#1f-JrG5l7;XZ*A;I4@DEHT!-`iznE7M=$W+NNEy;?Q2)Y0<2%_M|C>dq2<4!P0 zKnFS?$8Dn-myxi0;$DM>@dQn*G3|xGB39ytF>Ay`p!t0FKKI9a^{Tq6yJeT{YAw~f z@4kD_*=L`9_SwHr0&&wts5X6u*vI~l&`>k)qq?@5xAjS1GpH<}W91A97%8oMy`hms zq&xj3Yq7x<^|Ka3= zMHZDX#OeSj(i`)>R2cS?Cq^W(YXKrIOKlHqsRcZC{359q7P1uXy)|MK)B{38h#!4w%WK2 zj`yHEESLyc4?;Ej~Eu$4r)@NUKlDK}E3q|FrNzj!l&5I3$2 zzEiW%hR$bgttnR7EUf5{S{V|68hV$}+`u4D9eyXce<8YC(i`9IUj119hIf999bma= z`8~JN^73lga?b#p+Azmzs^KGa-%a!8`LAi%95IQV=zdlp+dncqm!?T! z#gn+pkXiQNO)Sqyf{nHG$zVOf-ZcdN2!PFvIWQ+o+dkiVdn@R zyqOh4d7qF(Y3&k8Y(wn3GN0JO~Cf#CfN2d+cm4yRBo{6F&=b)wszJBAzsPox>OFg?dn#!%Vdi7(MSS<5=~KB ziuYI|%39^VggK~XUcf)d>Xz+==4F_X8GY2HvjvLFmX=hj!9G80jlxW)WY z@`6w1$C?=uh3r*bTZ$*|U0KP~oFWE{gx&x4CF;@Suj@&u339Du8z~sTqhrE5(3C#a za!$Ou@`lNp5f{lg$!9>bbS~JMvXY^9>+Pl?K-gp`w4g^}1(s2#p*f%|OiSWW%&~%y zU5B(Ti!wQO=(D=AyM*#%Z|MzV2ghs*^Fg|ad;fc<7P4)c#s;gQCwicAMk70&T^69! z9T9ko;j~REyk%TMnK5F^MyH?ZL*QbnYI8?U$W zf;itrZj5G?f+KPSa7T1+-qlu4yhUdF8?ZtfcU$R+=p0zUIWI=%1-5 zupE#Kf#ULKk4QWnvE|*0=LFqJi>A>pp@qh~5)! zLB3)F(e=Unv`32vH3^h=V-&0>kwF-;laP%CrmAQj5eCzsxd8@4g3m@1sf*VrbS`rV zN>l8_X@oyHJ3J%81kvg&Qgfzv*cFkQ7$0;Gr(7R0M!4szs98jUD#{--zz7NnPd;VF zP4GsvHE&W;!&t&PFj{pg8{y=$wSbS8Av86QlGSV;m9JKtM=emZ7&>=neFTr7p4ZH3 zC$cNTkWZ8pn;rAAIC@oZu6$xP9V_wokmzcPN~avx zsSm1ueGFp=Gk?T?PcV4##6w9QTL>2ejKjNnoHqp@U<}zxc?alZ+ZB{%6F_4|ba;rj zWGcn0qTUboekhoO64sWb0CK_1NPiqgqA)B@ z6jMoHZ*oBM>X5A!C^$=n)z-VuhAxW|exo7*-t&+t3@?2O`m*$RL^sR)Y?84E%vy5% zE0QcVRy`^eIaU`47!m;JsVD`&uWs$_{fQ&oh9S9G(p(0$r7RBSk2~UG1ZG{`64p}UbOHddok(#fFU=jrZP;R4bdi0EPxRjC(s14A@~Fu z6t^kqvWXZ4LwAx;w|(=x~~i|_~jwQ=l;v1~Pq zp?m`qA58eSu^gEp8w^t|Bry&!ASA(h9lHgRqI-GL@jD`>*D%}rlZIgk^$Ksfy!$xR z2pty2jzs{kC2H=C!y^_+M%z!Fv%FZ)Oe|*u-4s_*M$4`Iiywygj_5*&hh2YdO;AJ#(Gd@*h4L;6F0fV4_dVSxc(zPwSI9E4BxK_;Qa1lHg< zDLAwhGIE}zi3PZoriocKu!WM%!9Md51DlU6z~)g85_jJ15?JZy24soW(TJ*E z%1`IU;vw_oDM6Y07zVxv!H4@DyASVWhv*GHmqcpYaxRUS#QEsO(K%RXmBwYg8!6Y6 z9hY66Zned*x#@~~Y=mM%e#7Jy9nOQ*_3MkVsm=C#yhxaj479I?uh<*bJ%ah6|ZNrgY6nTPY;KAICr=%Dwm*Ne@W7scfx3@Pn; z20NXy`)8JfJD2jand977LCXv?-s%vkf(;vkqB#{2`{+#Yk2)sdBEE=d`7=<`Au_p5 z=M4*y5x?aqM#q~FpQ)&^LQDA{lPp;e0LSe2^+)F(vy2sB1<@8%;mzDW>JWONwO0x8^xSWj~0fIc?QgZct}8 z%z^YVaxydzUON)4$!H5_4$NUF!8c4$eLk{%8oJE~P4*>O+W40Rnt^bHnIItDQcvJP zXz1wZD>>FZibV2%f|Av>cwv)2ElGkoME|N$NVcF|6cs(dhgl1Ff{IH;1ks0iJh*E( zR5e)0$4JC%&;6+rBmTGri9}#JIM4%;fTaoA$fA3puH!x1jD&q;YzCeus%nU&WK)}B z1JLXtuOuk*OtP&ZfsNXwAJqJqaYGQh4=X#;(JFD?!xPiMxR7{Q+1A;lc#u&Cw2H|-&^QtsX}fETom$fV8}q?BqJ%Q-ZRqNs&}p@ zp~=Z!bq;&gV_NozL&oRB+o{b7Gx3zODq^z@-Bya;7Aw0H%MvjdqU^21H8uTDK?Y=C z^XF*vhZ>yd!Xk$hwla7)_LW|>1|trw*&@%PA^3^Fn?!tO7*1)+5CA`A`2Tc?e+^vx zLOI<8Br^E-$EpFxcQ!_CU&6B@0cG~nGh(~Qi29u=g*^;@I%pPlPppSlngpdnYxN$L z>H(38Pj#f}yODr+sE$a=#)nl&<5eeF(_Hlu3S|9}#ZemvfEiR0jKLGatGZOOVOT-yfF_yBCO4HLMQ5zsrFo+mzF{U&e-O~wcwOFdJfQvWKF%<7pV zSW1-s$}jPo^%77Tc1AjSlAi5N&|bW$8go1&HbkKtEd-Ydcr>EXYW>-gjJ2ffzp+Kg zl45vB9oqM3Vr(_a3Oca{v-n;fgQkw_X^;Q1Z78t9l3xhxS|}#|tdrPda?z)4x!F(8 z`A^UKPw+SwU;fPXCAc2>MyVtkZQMAFH9s}ku8@hPPk^d4H{p^q7wf{M;*O2HXeEWb zk^J=l*F@hV7FY5mnw)qLf5@8%VlntET-qb}8q@*84SNIDl{P6L3U?MIHkxiz2*8j8 z!igkMt*Eesg20?Yg*TuInn2k5Ok$b=FIWQ<9|H0AIwUgc<}d%Ore0-NUWXMq|4aKS zu6m69h>^j`7@7RJCMH6qdYJ+PJ_pE`+GJ%FVuctnc&6nD9;+q!X8Evf64i>f4&hAl zreZo;`Nf}&xp#;ljVS;BbiJfo3i&;N0;e5`{>W2UWj9K2Kl6{>h*z#x*#?4KwI5nV zGFZlRB@wYU(%M7t30D&YHQRzrL9%DMFc@)2 zwu0cz>z=6K4TRNzuxJ+EkSt?@c`3p+Dne2~or#d=&NX!UCu*6=Y&qWtZ-TqzPjX=) z?z(eaYmJU@>7|43!C0Y2Myx&|L_l%gv!W56QDt5&W&vnBhYkb#zS+hhH!NTc)SlB8 z{`D4+X~2G*;on!K?(nV@%?C^oc${DLt;5j@6p5)dZ6>X7BNByhP@mRTv?pB%k$cjG zBt2Hso^;U}{6h|N70cL@F1|LTi$AcCG}{WwjR0Q#+HD2W6$4}U4S}>{#N~2#fGykZ zAo*3hLs7i?)mI~9?_%+5gjld!;ApL}_S^6*X^%73-rQsDd#rs=aYRBy01JxaKZ?IA z-ec`wJBs6vCvH01RL-}cW<2Z1q!%ICW9_0GK5}+Y0Ibjexgl4q0KCm29@UIgfRe>y z?SQMNIzw2zo*q%f+|W?S`g&w-t?{=31}&YCzi5>`Nub(E52bW(hwc`_{+MiU!OnZT zz}_yfw+oEz0`J~4AAU`l4_}RU^)B%0tMixN2MD6O%uaB!rU>L?`@r57u(t*5Z2@Cj zz|Za3c)q5#fIqP2|I6tZY(sE*#q$P}&yV$Lu>zS#3ao|7F_pU?zZxUK>CfNK;QIf0IWKqW`o}ju z#r01^L?g*%^1JwITIq7KoKp}Db8002hk2Ut-gzVdj3l0Z5SykpKy8jk;AN z0P!G8qi#JCpc^6q^rZDVGZufaX(RyCXOS6`kpKzKukA(xv`DsP)>Jlw4~q!!V1T31 zXA0l8xy(Z)3q=daK|6R<(E%MMHYSFO*_QX*EiTX<_ORXPnkuDOl*2o`!W~O(-}FTiS@2NefK!M8x^)Oi!lG(E+AD}w zpl=-g1RTj*$GFt2@Ze6;C^OuLxCO-sC~iUV3Kq{Gv(w-o#}r~1e|76%1)A|pXv4Ri z?_yVJEm$F~f)yavTCjq}=tYCo(;xS*wUEyA5mqA1*e7NU3=)}~Pu6pCXSiYSWp zMx=*5>_OfvmN5+Hup$i@|5#`^eI1WP3La=H?cNRxPS~+MM!R~zZ z^PQh8FoI6H{AR%hl!{}$%c5AdArxAqg{_|wjIjpoD9oanTGIrE(JmmXK)qrp4lC?} z=*+__#9d@PrKv2jgK1oJqeuxdBDCS^KkoeKiTrvUV41{(U?gM|YJ6eT9oE! zbwqGE|CPr~D&Wts%Ffkx+lQA>K zW`5n9F~)Z7VFz5u?!7-LYKZ&@@gkJ)+bBBLO~qC}PDHTnSP=z}fbT=JyGHzsM>jFw zN5BIgic2CgoH)JPR8fZgl%VtPWv^6#$!G=|Bc4&E7Wl)nR%#&%r4~|J6i@2>YqHxW zOwexcRt!qg{O*W2CF9~3=2nhKo(LC(#M$cYNt}ec?@62?9(YgU+zk@v z{}@y7Yfs{2=VHqz`DY?L_Nz_eJe?E=OIeB8FZT`wzS*IaPp#Yxb|^Nl%j{5FY))^| z=A?g9H>mor#ojb!lX}k-v&gB^EFyD=l%Gpx5cz`r{f{-X$aCm;%7`dpypa?U$%>2! z?y}a75(_R_WQ1Ad0?*T2hAw!RPj>Nxd|(ziz=zBt*Qd+La{gsEiwMqIfc~at5oH4~ zxJ}F=3h-C_yMk4NS>)5)QVzj*g2Z$61c_i4Auk{SZKYX+#_DDf^~`CgQ_Lc@US$@k zdaQ*o2EZJa`V=uS7ceD^83{-R3Pysl1c_FDK!%R%-7IoJv~e{00xchn{-Z|ernF4Y zAdR;;5RE?&(q?86aQ+o&7J0!2{P`FO+o;^cb<83MO0x*T_zXN7H;WuZW`rtS66e4y zQHY2IBs2#96m2tWeM`#1l8($(=k=+Xj;gjQJ4p#aEvchsCt(7DorJ4kC&`p9aRqjg z&&R`%)N!$xVNdF)*-5g(P6Aw>)KS?<=r{S=u#;?>xp6f5yyyhp&uqWwNgWqMQpc%a zC;741%NcOUfFkd~qjVB-Gek6z_-*)*uA^f2Rv1B1`Lg9vT7HM7_?n_M;4D>@wtRY~ zW-VviT&8V6A%8*!8*{TD}j&Ob0M$9 z@Wg=u!sx)@;5FaBqWo6nA<+~E?&>^bj;v)1Ybj+n(FR4{WqBlk5+ULdO&iR?ZcksK zw;~^}&2i?e^aSY1pz7<7W$=+fZgzXtuURWS5luONq#G%Vrd?=J)zhnLP-@6=@dJr{0o{Kg_0tBh6-~#Hbl=Ou#5HN{mj4Q4Lp#mjzaf)7_`wbQo{n z^a5c7Yq{HCsD|}dF)|`p&0Ts>Iu4UiSA{GW&~V~F931239`>x z_nJi8IxZRr+1s)N6-je}N@-R5xbf20Lo@z$&&$X;S@sih{;A4wI4*bgGd;N(^yQ2QYlU{#bzy8EOYtL<7VZv;xsxh$uSue03O|LOA$1ju(sMVO5S0Y8Nih$La*ib)$Do(9jJ}lN9`qX5B4vydw#alcQ=%oVDAadjF*`(P=>PwBcYBVEg&MO$^;d- zg(`#uRW}`SN(9v&&EF2E# z_h1H5#WwSPfMdfXt+6flIM7GL&b?`2mwo$)IObsb$2=JddUgpxbu!JZwX_NiOuKu zdY8l0)@oIBLMil+LQ!)WfS&6a|^AIpOgt=jtYv zrvq-rO)BeklS-&L@pMcn0mRp$<^+uqSy9%UP|pZyL4ehhMSM%GSBbDyk2RA@SHmmj zsXi;HJWpQMq$2deEEGodq%0{`asqTo?i68Il!L{W^alTY`$Z?*K^{?jKuc2)o(Ee; zqu+~*2>|un-FeXoGeMG+n zey_AoJR_nI;x^bP$~X?-s@o@E;jEj=KEak#l#Wo*2~4NVk@;_NpkA9e4we=F3HvPM zu&nF`UxKNvwyY?_6sw9v8>+Ou*BtRv)?&#WW4L4N+%e?*djX!3I(_oj-3oE8s5` z;UoldRKjp-$kLyx7#k9MS&B_*L{VuMFr4!2jTXfr5U@^ru`~E}R2l^ej0dAY0u>-_ zQ4!J0O4HKUm`Iz{OY81w*D<7*Q=%T_#B|#G;0Ac9Qb}MX{amaZ)qrRF78~=BL z;slP^)1px~3-vYF&;RSJsH{a2n{i#=*C*YK+%-32k;t;`>~?JaxGXTJ?#SzC>FrnMbtK&=2!4C{?c2$3mv@O7 z-;myZBzYc6IFcy5Kexzk^ieJ;-0Yr7QPSXvuiW(Zjeb#OFdU8kAg=tP=vA*}dVASn z%`I9B+gAAIwQ`I8LFpD%UV}~O=5A5os=GylEh0&mJ!NR~TKwkrjo+MEE&i)WZ&zfH z`Q*0c7B#1+B7^XT7LHLnPG^c^R6alp8`;V+YFy5}pOfYI|DbY=e##xA7lLE-*{jWP zpXL~ymRl~zXpvi9IYzHI!`*$O3Y-}#!+n~|avBtJSr$-KF3T&(aF@dkPp90R2(HR- zpW?;z6sT>uZpSm+KiG&^!odY8F`!H>$25R0QKSmwE2&^C8cjq9gtvp3Hx6 zB7crE;b;8B0Y7s@=NSMU`s~(EI^Zj_ zT~$L803)xR<(_|RTY2qzGQ^OK7aYJZ%unL$JW}Sh2Ujd83Iz-@hmiSiO-*Z$dV7+T zw8cG1syN4KdwJX1Ss`@mTB92l9Yl`VBM3a8hs^8QvYO%LVK}PXr;nd zdC4!CLi=J(p_Sqyg;u1Y7+W>~iz!uftWl^bv^&mAMsCQz%nGd}_`S^Jt->Xl@ePT| zN0OHeZ!d}--2Oq*;ACR*CJHSm-}Q;f8x`7%4E1RAxp-2c{n8~Smk>mYDpx zQp1(u!e)4bhFc~k1J|U6`=w1x{xb9BEpn4TS82E}xQ6?D&~PsX4fm51iNU9IvKjHR z1WsDo?d39qP0@XXGsNm4z>?}8k%XR^DxmTZ13kfQ&ke4ty7Y4;xxudLqGeu#+~9|? zaS-T=#>y^K=B&1KVr#ODcA2tEkXcYSdtwC*5#EKi>uwrt-Ih4Pxrm+{nM*CgR3Y;R zA7;m}8&h373TN#EvnS^f5v(ru;(cP7(=+rrKw+wE9- zFo{8v>A@tel*z31^x*c&R_Vd*ZKMYau|v3lr3bgs$eEhg39L0{z%qkleS1jdE9Reil4S zIBQsHqMgsqGq_=zN2C2T6x~T87>&|xmdGf@FZL?M22xB^+yM;{qho>&QihO^!!kuP zk7h>3+9J|pG0NpHQ;3k0 zE#ng$*qpzhTsyohcd#hF5UIStj?(tMMo9j;l~E&~4TU{yB&6{FdJGSt=xkef(0`)w zMt+vE!h_Yhg(x2Xm&D|7@DSw_UPo)MQ=QB>0_72D>UO#sa3*(R#%ri50_1osI*K`u z@z}Tgn4YrdUngww9-UL@MhnZ}Y!p<@q6-TP+^?`~*gx3%Ngs{mbc#fut-)`=&7rhW zv$6#@%QPOAT75MrGYv}V+u9Q43_b&6r6ns75cl3t)&}rGw7^3}4r&9iBr_=8Xmjv- zR)N+aKTsUN?aLGgc)C4PkXrRgHWUS0+R&naWdCn_8I*(LWl&VGL(G8_ytz^e&|xcs z(hkhw#M821aPPX8d8ju4w|)(MhA-R$zbGAY7DVXJ)@4TksAGADO=Ba zHd~e_O$kn$JRS55KIqn05$twF+2Y7G0OY4wt1+iGuHuT?dijl0o2<^jwS~z_J{rZ_ zd6J>4bL(B)4_-!n?#wE4bcU^TS>C~D$ieQ}3>RAUGg)6Bss;i!ba3xzM(1JEh*wVq zSGYKaa~hF0aSeAN7r?Q5Ik| zOR2i*^Vp>_IoKd4Y<1LvjzE@h#G2scfGldC6ixCPP4cLaWi0?#6S!D>tVE}jP>h*7 z-c^@D%K1R~7Qe%1a{H2o9&iRupw7iZhEHX6w{5E^68oMS+b>jQ!Sony7=I5wL6X@P zI|d9|JB65dxnumd;jOK=jGwbDL&5&<`Bs~6n4J*eTZ$8vHUL9$du+?l{Kqr6&BmarO2g?SJKU;4U;h1CNWTNNfJXTOb8+qML3%xNDtJ3 zl=RSIk&pv5NeZw+CxuQRg|9070=HEGs z2*7!P2moGy@nC`g+RihB_*f7?D~POhUO;a~0IeJX*y9CB18L3J2pE0sdBMMLcPcTk z)IiqR(M-0~j&hF8NqWbO=^dz-QZYWPmMFiRkt{sbk+xyH1G!opfX!|u ze<(S@k(>`D5=f%_*FP0~7dr?3fBl^Q&ZiN;T^o7&(`>fT6T~2f;tgbyo!GY}Ww8~T zIwBD*QLcA{nS^ekB2!q_=;CDl@hJZjnxH&d-e8+Mlz$@1KNoHQ1b1lqV^RKD-80U` zFwn7YPO$I+!45PRPU`tiityR%`8O1skRgSeSOKNHmQBkbiXqy8|mX-EFtj`}Aq zgxR3l$&DW=#hrT(==yDI~7ORsQFN32<7s!Ce zWxZ^2=-|papnC!H{7se8ib-BT_ z3QXe&))F010dn4|KX(=zJS4@!YDrdvDI+p)(NsVzN*zTuRbcDq7+9obkg>8os`L*rjyQ0 z)k&xICY`kCZTmXutaMTVj7~IbvukB9#frKoolKve!>EKJEoP=dZ&F&vjSkSJ_C)|k zmCVda-X3<@1-r}`YBuQNLfaI&t3DW;I8CK{GM<8vOi^C|-5snh7$n-OL+l(@!ctAn zdwDZ>kf=|fn3B$5bE{+3<%uaj8v8R1ccjk6-MZNVut@*s6>ByOtFMFn6TBEg1`K_5#KB?_0~3m% zFN_8OSC|eAWwZrWogB=lAq5@u7yuJGx?nP#X@q7$DXkq{NgMQok%_?|%zT^X%ygWN zHCP*7zZjl&9O0^6&KvLsnk*(v2POe{KuBdtDxnvBs-K=H2nG-78l2MNy|1vcy8-R7@=F2C)!6b!+s0 z$*w?phKYrKjW>tbPhi5qpX&~8kKg>4fH<+(bmDLf;waAx~l3Oa14HZ%14`cy{+ z&`Kp88g97h(qVf-I&25&@X9-vY&g^c0fz5&7~a7LTeK*4Dk#gVW-t*b5Yf&A#d>!) zdUv;YcNyKCsbt1t+&h&SZ6F#C$dp}SW0NL2wq10@5_~2eQo|B%pi7d8N3+9dC!(Vi zjxo{EHWd>cg8^u&E!Rx1COU$CtyDv{cqa!4AUbM;p{(HZCB( zpbJa5szk>Z$4o{S-Qc)`wE#2HnB>Aha9j*KxC$AYYo{&OPG{KI$ppa}mT9Y!?bW!9 zbZA*jd~V`><=x5aMmiqEM%NHq)my`c*=vP*7$>Z|Ks|=d!a4_=9LfS><>B8k?ibO( zo{QiSRAT2+B`m++93xTwe6*oJJZzdSI%XV7oFQV`mvaKe#3G2F9UPsR`egoQ7aXE{MyVHs#_@}mq?XJE8nsfwy;@wk%tK)d`7u$bH!Oy|G{3aFNr&ttrrXxqJSZN9EOXhz5QVk29ZKrcoC-g zoqxJ`ZEH8euJt_sCs^>9>lqYWmGAi%(O`qTqVI^TiO>U*vdx#^KZvPO)W+cwuHEMVVgc=3z$1N9xpe|tE+Ii z!mC?_%k9*MJdNp0>rG6j=&fQp?9^g9{P|M)kdLa8chG2nKwJYyN|6gBsdmRcD^&g9Rf#bKyb2omN&qCsF15gQz-c6|g@b~(u_ zsza@E*Xoj?(zoi=Hc*;5byU#;L|xf){ne2+zHZikGv}=MOEdY)ufFa*9>Ns)#eaHt6S9cGAvhV_1hz=)@&jE~J@^ESv4%4aQt#kwN0`1fn&+co%Y_IB z?5^z-BW>CAz6w0U9$Pr;%n+{UNIR9~AU4wi_LbHA0c=6VLmcp?XVKd9p;%BpOqEmr z_Knr5o17q_52g|Q**fM}l%85Oq6+~pUY->>8>6+sDMQ-4Oe9c8g+iEYxDVt!+c*Dz zL-IH_UqdgVg&`MZ)F**iskJ~@x+bBa4w0ZZghZmSRRwPK*2gydH4+2LsDYPhB!79! z4S!nLz+V=xZN1^|+PDEq0k9+1;s!uLp^;os+`z?{_UbALJ(v(x(@CnpfzQ@_4hZ5r zT15`wm5A2D6 z>?vY5lOc!`BH*bpN|@v&MhRnK1T{_}N^n-QtK$e*Q+vEYI=I^!Hbxaq@P_G;1ee%l z%1DA2Ef-`WlHgCVW#=y@MI?c)z6v4+X<`Lae5fLe2@1eZLC&LatabDK_kd1j^=0j9apWdtbP=#>!w*x*& zEXiD&;DVEa)i#4^UmjoCHjut&ybR2Q<#AeXG6EF6RYm}F7fc!fEI_~m$>&O^{aiL@ zn$Je3y*Uo*PJ7y0&-(UsUE`)N=?zj}Lg^1z_ZgiuVsxj=gpK3<-cGZ`XiMea1^`m| zW&U)hz1-qB?eT0X;tFWoY2OY`dlZ#uI1%!bY{zL&tbsZ0dlOE3IZAQVxtF$d+B*!~ zCtM&n?K^VXE2IDenL$@M?Q!!MT(jGEO_ad|vj$hqY2OP@`}Sp=_5hB`UPRZIPJ5}s zmDApWy%^gDr+q<4=CsF6pE10`GQt-$SH{|6ADQKUH9qU^d))1tx$m)9Z2Zx94n#=M zz`*IQ>vX4P6*{11gZrLumHU1caS#%g`@Tj)3vL{l&lbF~`9Q?MDx#6nEKyIc4QKkj zhkvVP9BH`+zbE5J;lbB3mS(M3C^gIxTl$b42NVM_j|SribPcx5_Tg|9_7S@!)X7+G zVOSRG;ck3lAqqEs+uit`nj0S{J+0P;=^_1uZd){0WttnK(qak=H@>h8Y>pTi^E?(z zs4<%54zue1e27cgGznh)DWg#Ij*Y@h423^myf3{*F8xy}w2M*KT>1}N-eO}k=F2GXu!lnOwQo8h?Prj@!eUL4FI^ohc8Sa|6^pWAN!liFA+%%W|sk9ai z`tq1d|5+F{*1+xWn_217Cz#|K`t;An6FxJ=s%+}j|5sxcG(B4R_4&3F$G*v_=ciP6 zIIrlR%CmpL9>IojfucQ}{a(qcrd?b^*FFQ#ehEV%8%PpvaUfjq?c2@}Ya-nCzmlJA zj=T7SivH|)>iA?hI>7UEyj7spEtn3j`evOj!s+MX*aW+_p|6AfALEo67Ky zN8XO0(=qjMc}^gd!-D_pWfic%9Y3OSMa=o$5eJON=4#_j_-u8+eP`1H?t41m9>IWW z3f2N&6v%_O2T_U65T}^18}N+e-z;W<2rKbVxp(xZ*j&&s`6wg)UGn4@2=L6J=HT|v zZNZb!WG3rPHZoLNCQ@4~n`P<9E1{vwkt7MCkEr1;hZ`3947>>> z7SD)ZM*-cy-I1Us>LLazkCn|~Vjc0i7XOHB1&9Vb(VNkoe!{%^u^1@?C{1NAyp1TI z$_p`Unec;40wH$CGsNs@mXPG=d2)uDnp|v4`oVDSlUvPDvz#F!CPW#?XM9*;hdN0h z;4$RhsI#tNrG|?z2_-fZZ!y*cqX|@X1gbium`e}g?DzUnPu5gU-Mnm{>w#eUc!UEH z)$R!2etNx-IM&)0-TSo32gLGF)ejZTB;3ph$(!T1DRa@9zFJyZEm=IABQ8qk+mFqK zXnbM@D09JM@UG)}Ivg`C7~s-K$7o3Inwl$uk60^7Z@Elwcfs_RPW|bx{Qm#?zrE-G zpeP#butv(Epfmh28a!ST95HgOLs_lTzYmjDGdvr%~YNG`7ic z{JcM@;inIN23z1K^6CoaYjx@&!b`jCX4C`4ih4q<;RN+)!kl_^RZ));g(Z$uH5j%- zJ?d&Z)FUAT>d|ShjlsXsQfp{$Xq?cFEMNVz^C+bGOLJ07V`5qFBFd1hj9mSf=5X3C z+MYA8QF+aif_@%tmC4AqEsfft6t--B8wz3PC&}%z=Z=dyWh2OK1Bb!KxRbO)v7Z&E zuxsf^0LYr`mIU7BEq0+)u6ae<7b~O?2Aa2%H)u~d`)e-Qw!x#d`@NocAb2B|O2{)4 zguz)vQF(E!wl)&-WYueft+BaooQIv9xhM0$cJ{ETtVbtgSWMYB>}Oh++#oJh_G7{& z{RrK%a2!d(ZUcK|lZO$puQGIdqXobb;i_T|ws0AlxQ)H%!`&K>(>8^zMX0#gpxfBd z0^}ODDtsZK<`#}?%*wzrjMX7xRJQekrBlTtpX>vu&5~gs!H|IIxQ8nD76Fw_aOty+ToWz@<72d zdEWU-#VC#Ac&D+l7Q8tllYwPakCVC>ui=BV=YSEyqF~bz%VZo6ER%_$k1vx0$b}}o zYJv2xFQ;%bafbbAOq_Z1>~%J?g*el{ZdwzK`i?)|#QUk0w^%e`JAPk#S|wo0_&bVA z0TbTBbh1Pi8JH_x!aTFkl9b7{q|8>3GFjFA{Ut=IN}mL}~Ix`s9255_wt6d;$!G#G;TtEmqQBuor&wgTM0o z|MHXXd0`tbAn4Rq&m@!w5Q`>2?9fLY#Q7~7V3@s)!|e12V{OchwUJJs>OV+0n}FhQ zA9n%A0QJ2I3(m4y200=KWD9Q&(Pi9*b2+Mn6mHM2u7nXZ%Q>^ zd=WN>EjL`Sz|%aI6k}WUC^FN9E$zOoZ>=bvVf8bs+U$y5MZ39n_fZP-VOw;$hybz) zCCy}^s^n$O+h-d=Z*I=w31lgYKk#9EX1pLG**NG{;xKoD zt*c9HI0IJKbsR8KmklGZ zx-+KJWu_`^wcj0E?;Yb6tasr`tC>+S_$3f4POQ?Z2Phn9_f{pgg|?h>Xe%ru9!GM| z3U0#$u)}nQF%yvR8bHT+A4ZMD$gFnys>sDIu&SHb74qJj`H%!|2DiR)-tvdv9UtL1 zl1NMa$KD-(OSJjI?iHMX=!kZH>fJH(cx$8})knM$c-B-F(kx!YgS7=mc*Dj;5cO4> ztXc$^24Gq>C4ZA1OQuCRzFLp*#PV-#?D1ey330=Ms!Vs1(1ERju1$A}>bjFmK6UD$MfMf8QCc2X#{aA{)w0_|gtYa0ctprF z=A}YtBk(#{EaYw=gSO}48jbOs4RVfyWmi{j*;TkkPaDaY37jfvTApS@q+YIPx0&2H zV-^cpcFnVKdAYF=df7?gTBT)I#aT_v*usX#SVCQ58LCjK(Ai|H;#FgLeVpJDzoZq_ zd0^A5&h~28t-Dl%i(T$2jJvc=Gj80yY0S8bpEnqHyR2HXagRTWuv{2-8?w>Xjk~j@ zahDhddQEZ+zBD2;_*j3k3R7YZeWAZ1NAkFFSJ|OX%aw7LNj8RDniCt5wD!vxC56QB ziW2sDUaYltM|(-INkZiC`f5gCT0ziskx~BpVM~If=eD4f+MS+A+b&h{hr}D3>u?7$ z-2ga3r<;$z0-3+!sRP28wg-)k`nzEM)>05+S-vqV(Et{Y;+5X*9Q8n{ue*RSa zEh+nrGTzt2HJKCnxp0lpo1YEW5e!d)zstw6hEn)08eE8naVB$F+mr%LX-Xr7a~*9c;#zo%(0NRW>ES2ELcunTp$@BV?#Bg=EaTc*8fSX4 zp&8Rdj|rv|7>rCOR-)^WSxzJksGku}3#jR=P)1gaELcv`d|iSAiiZ$v>^!2xcb3qq z-;^MLUwmVus2oAZ3f5W$yL++xbU9fTj`*L2EO45PU*;u7$A^usu=P4i52KrAx|KCZ z_=&QxEwH6b-4<+Ea(%0Ey$MDg8EhSROvZ*dv{*OT+R!f#6A;(2BSSVOT1$i<$5EgN zL%h{PWt3BJ6r=?xA zZ52hfz6x$5F_!5Sw-M1EA2uuNq>Qwcl*FnJEflM`CR(v_<=#-S!V#ttDopZt)?`(2 z+rGj*tcMYBY+<1lI5>(>Po?9FCVAdfi*W<3HDj#H4ad-xu@Y!I46tUPmCT7ItDgN8 zDLch;J`D9#N5lp*ZH0;L%8Rp847E0m(I%3L+dYb%`0;qUp?0!~vCVwEi7PhL-Xs=} zuxpHyX_zq7mNMkc$xUvnEy*((IC+9jmNdqzZQE+|b696wT5jiO!!<$R`4i!qK!p5s zxGv2i6{KPmgk4_1HhGiTa`WeE4L)0I@O-Vo^=&q2w%$!gxm{cDrVZ@C)?2obPM~_* zw%)P@n=D91lf^9W%+@>J3LL4J^6lDsZ$b^Wji1ipTjpu3ZTxI5f#HmA{48T%slm#N zg%ew`f-wq9FZS6Y8mE+Ks*P3a9VRKxH;lY#Y{R)REaP9YcCfFO)($&^9^^O!F$?Du zPAc|kn!nhLL?9mzfTi+h8}ljNT`rkVkc4u{0KA-Hrn@bcfS- z7}n-&Tl;#GeZ9%P{#qM&ja&fU#hMC z7i+8k;?}GGXu(d*AbdJ>B%btGslj6?E;aaI93JOMi$x=59Nu)*Y|}Vgvng`D#*5KPtVwtD z1Ha>E34z&a6j>7iow*!5Kv{8}-s(}xSk!sRik0X`O3uM$kzpyjnx!(2lV%n!m6B8Kdf>@mu{LJ}2=6(#`zml|%ps5jt}(Hd~_PT7t8*muQ( zmZB`Z9$^L%CQZKn`2Vn$-Hem4!<+nT`^(4tWqbDjX%?mDP8GFD6!7wh>|6(KPTtF| zz}0C5J3Xdrc3)GlPQ}wSEXH{%9`c+AVcs_$gsGOkI9{@EEw(UBL-Tkf9j1qkik78? zmeDZa9!@9%dbhfKgpfh)s8%yefJ&~6@^=$ysh=O?Gs+*ezYirVgU>K)$uhTo^L%8U zyPwiizji({*WDW9<14ez-=DF+fF9=3tNn=V6j|1S_Ln>?-{RVeToMEz19B7e_>>lP8Ce#TPocE6?NZ} zk-K{#O<|rtCVmv2V#zaQDBvRr{$5ZoN+G&LRt*aVj1$<8JUnVa5&hB-GIqOgRKzD6DD2pLo{GyjN!kr@w!qBXSc4(V)-bP`5Ij(+mLuPeK)tG? z!2MH}NSze%k7xd~`RVn~i@V85v1FK8Uki`EMzdz;p=fwtmBT&qrYI#mh8a1+4GZjeH%8@H%DwCWAmw7^KS?J+rYmmmw*zQ!+m^yn$JZ( z{~e##^GV@+oMC+|C7ept&yTDOsauVxMX~EXJZpHs<8I~rl%P6HjUJXWe4HPm8Yy+@ zKGgW@0q!+31<14Eb>s^l=V3j-T`y00=|d9sr7oCKZ#2otfMVk03{y}#f5BVjW9wFV zpltQUEn5}CHTJJrPqaehePw+YRD4uNB<_<(wGV4$Jr+M?`e8tH0wD=d;D8PJkp4!h zB{j%;-;(sjc)7y-Y<3g4x3yk2aac{vmrcxD6a2L%=F2AL4Y_)Iv3ymrP+IWUmv@xi ztUH3gylJ`fvtP92yyhNk0ODQy!A25QtsM?UjIW3>yi?+4sY^oxO&Dqq%Vhl_QL$)}C)-r!= zB{I<#pTioQScNHT5BSp}Fo!P$<~T^j-)ukB&yrF0&0I5%(xgFv#r~X^>IP~^CGgaO zWP}ey0$%Hll6A%LP*59uLW2_lJP0*l*sbT@jx5r^p)-@<*4uNFSu2ec+P_O|XV!d=T2b z7@F^2%PdfFA~!@1dGT2EO~VA<0klfkq9L(A!hvi8Y!KF`Y?Th89Oh1V(_1cwV-2Su z)nmgM4l)+}SFPJ{4m*BASChl>g0l{W(5-o@51;*+IhpM+&ycIa5z;)mgC3Ywks|YK zbtD$Fsa~%?!2e$z*X=v*v9PuU3j+de-#yx=TDGY=xn*kwDnbu2U!1soU#xLpvB* zNa+#>eXO#x&JGk0pJ=*!S#7YRWXT{*I8auF2m#pV*}~rFUTr%aogAa1QV!Y)gHbet z*vqC2rr6<=U_~BV?i=G~jBS7oLq zRBVZjekwN>I;olgM^k2|absJAkf;$Ti6h)sFcPe%E4D_#41MdavZ&(wM$oS4_bp5L zNtTA`U3V=hgb0mfw3r{@6>u_(V!$%yT`yd1=cRVDMI=^h4tggvipOr$W9*dnm~uo9 zO1GV1bo)3gS(~RdjbKKE61R={KoFUgKhaDVEBURO-M?8dOs!l@hE%CJ7X5AKGZNP4 zvUvc+Gcuo{%giz$^wIg-HJI6QFvv4D4l3c>C`jl44~=YK@^&(8pkDLajUy^$V~*5Cr|4l?Re-WDClpB z0?HDBnK2Z|YP4Y}5}ll^Hi}^Qe>R9P?+Yv5ttBLwN>9O7Yf?C zR{dQmMW3LKUyuWrNA)>54GzciBa~w2d|GtA6A7s;LUH zoA^~-c2n4?q!c#lEHNR)saU#}_>0e>W`Cn3733WTCPAtu?<6b&*{nPa&)C@QvpUin zqUf1CqHX!$`rvPwELw_HugP|sUT(Wh%Tlti%SY#lUzhuXlpcws z_cJA<{dogEES@ccQMLekS^(AA0vcDryG_mmhe@&8t~QB|IJu4H3B*k?oVGyYfeD6# za^o15h7?elN-V8N2LUxOoVpN>Pwbe~6Nzw)EJ8Ha*d%;vgJl&V@!vtl|Hg(YY2Ij1 z#D|P6J2O-)_mL8Wc1aH~i^1m-2(FL)Z3Qz@uXk~#RoLb9iG@i;kQM!7 zxtVK<=)qL2l3psiEwc#ni0stZ8Wh$S0)ZHK2)t+Uf?uAtgJm8v8+2tqQZo;Us2-tZ zt~oLD=Hy{FRFmi76=qa0MAXnV~5VhIR|JnG}U%bmF#Us3bpTD+ojoN+>En6*}e!})!8@=5zVjxcWD?QQQ%w@t`$bHb9#(e@;zpPn)MMA z0SP08(H?t`)GSvQECnzXymNV}4ZC4r-9l ziBv?gZI-^$jrg8*RvfELp~!`aiKrA0I)FJ|@-RIa-s2@uH3Rc-2ua6e*{UUL2MX3Q ztWB33DVih@_iA)Po*6prd1q|%l+NTkqWr4-cOaSrME?u<2j+*${8~o=5!xXx{9AxF z_%;*d1wfWEOZopRm(H;3pELuA%7@^JUqh|`Kj)bgcykSTMuLhoj_zBQa8nqvP$+t+ zC+H52HHpJW9a%$zQrLZ0@^w$kG@P1%$Sh2%G@zq*)HRe^awRv#$2nD@!tYGLufV$; zhQN`06*tf|t8^_MS%4*rwG@S=2#@bYvV_^gnBG}wH}hI9O|J~gH< z{)&aV?&H-bD?i*b!4G#n_~Cv!E&Xu!Pj|(AG_cEf6IUE%S_)TOfPvmwVvI@-xjUe9 zDi(3Fp?ngOUL;D3PlA2&bb?RrnJe+h(zfI_E5-!^c~HIAFCzQHT^65_r9T93Eul{@c52pABp4MOi< zD7C(@lV=W2d;O-qxL4e3#z!Uf$ks9Gi{kY2wKP%DrQ#8VjZBsB}UITlo+jZe6#Y)^*Mo85n zS%(-t2dw7kf zp9BxwCU3cJFT(b6jP^bvwhqNbecF!+$b&+RfnipaM}k-awh9*x9e9HzOfe3LEYYnW{B1pI&CUp$u#H0*-qCL)GcZ zayd3UiT~UH1!hH}CwTy8ah`Eg-W2)^9>Cdk$$i|;RKj}-f~&TI`6x71qO4G37~+xO zE;}ldGu}UMT*kEx-aoM|I-VH7Y?#%mQyTy{mG=)6i?0iHhUMV@b0;Q0NZ|F6mYzRD z%f?pAp;)6BwteLBiYnv%?RK!Q@!!ovhmsSC{B@{7S$rXvnOJ)si0XJ%}N*>5w5~Il7DY$ zw1`n8Ta-@Dz2F_(hj;LLZjJV>LI(THMc8nfsI|6XY!JsL+>g+QsoYPY5o2;lA)A>( zc!j*rGUUbk;0Y!UjV;`hV++^UD;O4SZ)b6u_og6a(X?};y4SCvdGCd(VGW0=F)!hD zQ@n&zpU-CT&$*+}3aM3FN-5mUZ6e%lAE}oY?PP*u?S?@7fK;NM>uju8`;(Y80TJ|6 zgpC|(&OwUsx+5*P2hr=~9;BzPdDAM_;M|03a1JK{?m#&S(5zARWN2vAT!URW7&MQQ zfXCz{&|_mx0$hW}{pFa%ocZ7h^A0jdwTA`4CKq1K_G9}^u!6$w#Z9#mCE9AW{Fm9R z+=6N47R2LWZoy=OTM!eTy9FDJ0N-L8&0`s<$lZdeyam)VbdM%(!G_#|N#Pd63xcjC zqo&pUSE9l&&9M{L3A~twim?YnaK(GgEr|YUW(&H%BFL!>w<+Yf1-AjY?~b6;+=902 z`#PoFvE5`UMR|OjUKmqbT#1r+fVpU@m?SQ1Vv$ZO{HtI2CKK|)c?fUPnU8I|cP zpJEW_$Eb5+s>Kl+5}>N}CQ)QFuirJKfJ#HSJn1__SMWzc_K7M2U76g!^;^4L?%$?g zF))7jD>f*figHJCLs?Fs1J{E3l;F#U=}SdTc##^$Z09>u)8t{8GPQ&<0#@d7iVaJ| zZJdiD0&o!cmV9GAfvwW7NIxoh!-q97Ud_~+z-Ke*Rix$8pE%ZlfD+_o9W<3w_fi4S z3mcGCDwP$la>1(j2zzAdR%DY?bf~sSj)~pet;kdI1*UJe939qC;S7w_oVyiMB#~qo zrOU>2uhy+drjFL@TeB#*6&s=P_}G?iMHX1)R+JrAp3E)XiZX$~M5ehF+2aNTNk|U1_LL87Kj6i0t%oI`{QK~GsGSiG} zJX@@pQ4hTn^<5lAJc?gN-NK(~CFHwoBcp%@V{JZjPS{w%7I)m?b?(~xa`*`^K{Yj$|;T##oi zx*{%8q8@H{>JFC>Xd!;+&dBEL(*e}hQjsx+p09Hr3J&$B@CeB*$pLQ&2>A<9{)KPn z4##nQCl2NpBK-B^#~bO};7#0plFt*+r`6?Of{vmuc;IQEQWPsc7+}Hd>Iy z(V}S0lB{*&9eiHzvkM&_QM(0iX}fTWBFR)v(F-vfddN+DVj}88gTmXV3@KgS$kn+b zIq}?N%!g%ZOq`I3s~r21pN~1iLN5iG-IFTizI`JP9kUyO@DGrM`lZvIwv6Q+(UZR69Sk&VwMoI{x8e{8WO z!mS;wC~E*Sr~`G_snPsr0raS##s14&q7wmKS9!Y{rVa3D^a%szFTF-|LL6n zB#&n45oK2?PfaR(v>_(I+$8E}jt=Im!`xS4TC74v{QYvHtnSyn!T1HaHwn=4R(EO| zosNET*IjW4l&8^kH>A;7bC#Id86m8OG`jB8G`eZ6DvhpawMwI#)~bk^<&by?lnhuB zI&?&pc&JdXNm_`t5mRr|Qt7H6GJYWXef;Son>{U09oDZhP6{=Ej5H|&LNX*2GVi#e zWPn_C5*{3cB5e+O4tI*QIrU!Nw6wWeXpi-veO^7V(T5%s6GLvFb^~=Y)`X?aaZ;)* z=AZ(84v_q{COCsNG-2@;_BIS8fTTS_TY1;g<~R;m5pwUInVIC+vBH||$uw6!-GOvj z-n!yHP;tFt6y};yOo|#+8DJp>s#V}Ezo6h`K`m0~7%85#*^Y`*}QmuNk&cu<~fps}h4AgNwZ_nOfKe<3t;6?ZvvmM-%jb@jM_3qY(J z&d3EW%@{Hi(=w2omwJpp8Qb>|Jt0W<9Q%;bwlaM}kQ-B#UjhpApVy z`=zmzxTyx!1qMANY^;ndl^1KN^#Puc9+{>5Bz@UW(TD&8zi)K&D(6Ee0l2zL??aWk z*L;u0DWaMXqX-3f(=WqE1qqZ!{K}$QT=eM@i2(hgubV}qFe4^gb2za8nY-4NAsHtY zx2{*zIGD8siP7XvWLMUpN+2NM69=c#0wQcIIALw#t3x*6r`3@K`!QMQE}EyFa}0#) zvxFTFRz95gC03HL4KK@RC--*%>o7c}T8D z+g4#DFhT|1)+5#)D}*ydo5{)%FlIY~hvLTCsj^9HD1v)4I z>?6(|vrWVUXyu5$U1y;}IyWOXxKO5=82U~*3=`5G4&T?p_Xj{Kd^|r>lf@pl>tC+P zWekmHUbYZ(#r-0qSx_6Xl!RPWum)%MsIPtDK9}E+LTmEdgOYE4A}&TnvlMoqwWHC` zS2vk<6W=Bt4$|Ak$0fbBkltW|ET@*qY+VvjLq&@&z-p_sluN^_mL;oJh#V0{M%8S# z9-+a6(WBAh2GK8TlrET72naG9ZE6nrqrlrKGTcv8(%70yV-J`_rGe5f)5*K1{FjFd z5$+eOpT-40ECum)L^umXL?|l-wx64-Hl5}u`RQuYS#~ParZZAQPN7zJLFlzro6fXX z!tv@;)TT3SsZH#Gn`lmtsN`h`mmkxd9>FFI$Y$2MIAPY(;=CwRR;4*za-)`NXiONj zwyimxX-{fS9_?9aPG_)7jcHCVr@ja;@u@}mV)%YBe19%{e^!|%5Lf<)j3W8N_V*$C zyJmlZn){52zt7s=3ykB%pgCPgr)f@~qVc2Ar_(Xb=>@y_`RZn|^d_GUYj5N8n`%xz ziCZgA5_U@c$%c6(c?j9}NU|oA(Bv@NgFl_7KXIV#xc>C%v|M4&rKUeUn})^r`Rb<^ z{iln?Pyea<>1F@vlK%vUBE+>IyPfGzr#mb4<#>7hXTU8p}@>~uHkPo)NxH*yTgOOzxDs#F$9 znJ82#eX^%n$%48%HDKh5wTm-dAxmUIjyGd@+a<7h6&PmH5%{n`+bgnuNE*RpSgKNO z1lvNDG96=}$L&>=A5*T_Xw_1CI3Ogsrb{6Q>%3LdrRZ&GG%sC>@L=uCNDNDKEde6v zQtgc6Tn!G>rmmMZwSX`vU5at?C6%zgj-H?fr1!E6!Wj!q=@u)a1u0O7v_Wf@2 z+ccwjp|a477Abfm-D`9Z&B*T8G^71lbyu2^PD`U!foMd)qd94|N1`NsMa(caYqsDj z(LB15O%%^Sm#8hktSU;(HpnjC$`FcCzvt{$kVMH@u3-%eSjEFT^_=R(%m zLjL+>_0xI(X}$PqQ-O}`qjWo>naPrML9BrRrFSD@0h^i^QsMer5-(e6#du+sk{OhO zY#Q$1`#5C?v%>r1%e=*5hI$G6h7@Dm3c+nk6$99JGVWC6*Ly~IDfyS;R2;m!3HOw* z5Oze8D3rxFbMfL%#V?|yI~J5`t>Dq6Tq{c&_MG?|+Ae#4l8mJz=NBw71~|_9MJ$s; zCS}=7_NbhYFPm-jN>44r?Ks4fXRRv+!>#-oe>K&sBN%0DnU%Ofmj{=`R&eW+ke2pv8%0#a>LlWR{@N3Pe_f#CxBYF6_Q$9l&27pwnf!!iq1}E-nh-q?j z6(Z4guRt7j2U~2umPR&bZcRgp`-RF(@R(Z=PGLb%XC3Cw92rcSHhmz#-mkqIMt5r@ z(+M_W9wf>|Mh9k>aWJ4i)3<-I+^i(d{DluU{(4_j%n{$rE&BY}UB21fat7Ha0t)hV zF13RSsX|`BywIsjK62TVpt}451n_i3h1mQL3Q~XoizlCdx{-hJ143(lkxRAd;SgSr z_)(>GHF7>GdmMIRlU-1Sxbnm4cz|m^obEA8>l&uH+IAb?1pOGsM}!DS@@jhM0frt~ zDfw6(e4$trWZQvr?#U>tWn-RxqaV;~rFzSPu$#|(phy*_?EwjMtZl;b~Lj9+c;4*jI7kCp) zyAN+bRm0n3z_|8)!`piU-s*hg5g$JvTaTXy%JH8n#;>+_-}r&5HvZGV_~L0B{|Baw z|GhqbKDHh|50v9SU5sCC@4oQ^Rc-uF0OJ>Z{?AMq|D!&BKDHh|50vA7tQf!A-hJZ- zs@nL^0^{@l+~)tuDdYcukDrgN$Ik=h_@5}oueNvJ_<^c6{%4+P5X6Q^xelc0t z(AWMaqnS??_<3;(ex7vv@Ub<1c%a13xdK1xWcT3*sA~9m2^gPriTu)(@qfT2az3^m zKM$1Sf1;4c)%NZiKTy@i|3zSY;&CH{m#2*XjE|p>t;f#;<@nDQ<5%0eZ~Q=28~-c7 z_{tMD{+_-}r&5HvUI|@u}am@t>M9exgvNbnvnD_<5ilzelU0bg1p!H-4b1jsH<# zeD=3&{Etl;KSyL}{CsRZejX^t??-7cezm>(#t&4r@xK=spLx>8e|pOJzv$!VW9#wr zKskQ*wljXUz5B)wRJHMc02t4G(8mA7l<~jf+(@%b}0{tH~5@ylnYpyC;4g?wy{ z3LYp?alR0R)b{Q}1yI#caS<3__;o|Yb6h^@m(Nc@#RW$NA6uh>2TD{tTcAR1?>UMx_kCU+kSfvSeWS2XP3wgtKN@r}Ca z2b?$avGw?Qpd9}b1#ec{yKnqJRU7|94Eo8ZZ2S*T8UGm{KOb9w2y`9*GV8!yjDc)<(J0}5g*D>BR3uSW?J;9)%|hY;VwgG2#% zB1~^B_UumztIPdPC_yw-s3;8+F|s926$9b^cNIARlN>yt211NORHVX8)TVbYIDrcs zIHA14d3v>eX+!0z)jetcZzH@=9S}N$8(3+bCn!Ovh>_lLhMXlHhe3Rb4KKW*$d}@I zJ*!bu21WG*7!wy>PoAKP-hZxPs%lrdoGg2wtj@btO@tUsRqdQmz$fqP?ZkpY36RpI;MDFqat8EW#i1j5tF-r6F z2S-t!-tC7nFr-I6Z-)ec@i_0?&u^FhBC=S@e;eJsQhd2P@761t9A2o^gB>_CY_~)Fq zsFaEkDL0~C1wK(6|1MRFASR31X;PYjKqEh$1c>8R9XTL+%1@Wj_&}+vkq8xrmML(;qe{Azk zYsBT&RwCSIg()$Pq0_xNo!1dYiueOiaJnoAig$En+{o?`D5nf9?opM4!}4?ma~${; z$8azD6`6kr{fYqg!w?05(c%Hh8dLQbWkW{2Ifh^}v=-mBwBCEYeRakH_cO+#MsoeE zq)0$sArNqKPQO(+Ak4HLD`t`G9In8T67*I^XX%*i!H+|#3OX}dP?_FsF8VqttQsj4 z^d?eR?>#V1)nJenenstTS#Cnq!h;Y%NSmF_q2+Wn1KCK^ufag3(e$)|Y>%A5j$Ve- zh^V$l&c!<_Nkgq(mG9z;AX1f3;);VsC|si}>hXvXa>Y^fM33r<)99%~qpS9qvAG(o$B|DIQa6YWGpKni1zHwzthi)gsPO?nT>FuK#Vpw58s^_3|7`7xq z)3J2tbl9PoKgWLM}!?L&MLU_n;%a0coJTSDmEB_*7dW8hj&lAMI%C8D(SS zI(a1{C+4nM6-2Vf=PZa=H|dL;b1RaIfJ5(Fx(~O8v!qXf`!3lPh;j4mxSZoaPP!^J z17H_!IYZNAlYw((o-2~k&k7sda|q}t^cb(qC5@C{+vEx&7(7TSwv#4LHx`f5o(Sp@s$BZ#ClJ<8rFN*C{$pXzhj{{U_h6P~F0GjBVALFfl zOt$(l-TX%bo|--cI?rf#QkITz#eF+VJyk*8wP8G9D`9Ec!W>L4%zdnjWL1ZP4!iVxitH)zguV?$rBKQ4XRWeo z^EIea#mq=DXBfJk*MiSxts8@JmSe9u`*j&W=klM3-^Plc%ai*@y|*Yjo(!nImaz)O zP&Dl=oWC~sVORsHa(x!)f-sxFa#&s71!tj-_OH?<$11Cq2#kYj=rpj(GaODZmvt#k z;$^AQi~{{xC(wcbNws{bW5p7t3jL5d@#<9_X(e;|!=hN#`WFK<^icDH`sVTAURF?o z=>In0>C=fIw6h>NgUS~YCDbXp;_oZB5YT`IL}ne}nG0ZWZTJ97T9R`~5+SbGfhDwL zKWfVotKb_X43exSecyOZpZO58*~jgDMtxn!k*`nMRQ5of(>RUO9rfU#X)XdOYuZ@+ z8XKHObs1nk&S_><9LI>6aR`*K`XDcnu&*ROYV=3zMtzXAFW6LE#FiW>R?dUUbs5$j z1D{-S<$e)>gwkk41PPlZy#3xG6)XU?WuQ{D!srbpXk{*KBr*J!dumoI(RhKw+XC`p zEgEYm7bA=zTnC=uNBtV?wn77YPkNt9LMDW-$0pO@Zx$GZyF<*zy4kgXGIE5XkAi53 z$7(p_K&bCB5U|SwCwx4DFwx3HLP^f*gTIKOs}TtRC+{V3#ag#hCw)4|S9NCG&Q!)s z{8-(kxX_cTSI$<%K>j$J_wosL2M=_Bj3V(>6O>blU zat)-CU9=gJFPtvt!1L{KG@8Kx@-%g0NjBqBh8z%)uo5N7DdmRLT!awe&Q>^Q>p=iY zO6Bo+d%Sp9655@!EsA;>efff#$y@j5>+wA%1%yVcrt&wQKuy$-FgvyQ8+HsHX!A#D zGM&<7|Ni{qrcKgc*{Ze+8^;!1ekdiM1$4~hYwOT{OOn&ob^pWAKT??ss2)qdMcE`4coh_FzR1J+(Hk2knKe9xUgD z9hJ%p%nTswY*Bc5@Vgw~gjzVX?r`gcFWb2UqI^=^^W^%Rayf5?P0IE%2;T zJ)Qh_I6#i-Bl#ba>v$3(vbkkNNcM(bGEM6gYFb187hiwl2_9|Tm#>3ce)86(fF#~# zVr_oG+X4!;CfS1atT~k%^#5q*V!S#x7bUfSv9QSf6ZvU%h%6btuBm!iUt(?v4y6!i z7^OiCCv;N4NfsA9cLl2e23-2;Lu&@`|Igg}z}r<-_rB}T{(JU5$qoiN+KbD_F8kzIp&ySjycAdV~#l| zZ0fOQuY7@ZYFIyvV-bzOg@4Z9SLr z0B($7Kg9XbC^SGru3$zT9Zr|≺yxt={S6kqiwT3WZE>niRzp!gT52itn zseXMH!A(^#%y=7Wf2kvRByitAQz}H&bF!@zyrvk#f@nhChB`igslcTRC2;Ar_DD%& zBqdKMmD-Y$CEzM38;OhnEHupn5(Y*WZ-C^4E@9EI{=i-POoYB(KQpn7mnAK1f@%V&ceT zP(JY(;_7N=v*{RRqz_(3$HnfK=w6{rOOb`rBPI)R3&dC*1uH6%8MfGQtQgzKNMjEu z!$kqH`>$0G6lYl)O9*l7SOO^vzW>JA4Y(yIZ zg2gaz6~jEBio?s{ER#_gyDKilb}Aa~(M26BMR#OSx2l8M<5elg|kcYV|j@7>M|qAa$`kzwerSd&;=2*5<*)vSLziiF3m-g`QV z#FwJ}q7=sf9j_GrOWLGTlYrD-df5UGANkXdvFfQ5R**WKbM!RPJHwBwXt0BQUx)d( zFn^XpJLGT!klXWtqMF#<7@k|5kHx|9!-zr5%9T-sQ6Rvfxn2>yZ^e9m#2`o3qp!_y5(?|NA`m*HhO3eX8j-PWJJYo) z)CV4bzQQkO=n1sUYuI_NTFP1(*+mSg%J=`wT9%w6efZGNU@AhQ&W0rfx%yawtcD;r zRS0shAPDKVe*mhBXq}r|Y%^pt-0(CF-g=7C*!j6?DsPs0a&JywEOzJHx6}|mW}&(x zx73_^%pJZ(KC!yvqhqDd60n8T7@f%U@JY{)q8C{wA3e#p%YDBB=V$@v!2pMk9u5f= zIFAnDe7}IR{ooLv$0(-b-rOSr4j&!sjg}DL$XNRyzA#34nOz&{&=y%h+1C}0%6K0x53rwj=d%DjD|r10ZKi#}C>v#-G9#sG(p9upEOn0)QF zdp@?e#N-PV2scwe98N5orwJb&Yrd8cAc&x!d9Kk!2J5GvYe+@z&I+8{3pk4b4j(-n z5-M=+7{d8t0q5%#IEM;2cLg|n^l(V1z}Y)h;`8680zUt<0_Xk$&V2z6A3YorDsYbe zTnXp9KNsM9uL9?R0?v^DhmRf(2^BaGo?OEDyORT)M=Nk1F5nyuaQNuqkWhj1-t{G% zYu5)j@A%wsEG&GEV(PEQ0vtYiI3!fyy!(_A&TpO);2ivHO+#9xB^VU4M-n5v^Fkd- z+>a2dk^9yywV5Ca^m;$9WI^q?d;O#79@m{Uw|3{TnB!mR@F zGhV9w&kBV5DWDmeyDvcCqx7F81PD@scb{&&DdXUePY-(Idlfhj6mX6NIDGVQNT|TM z?s+AgYo8b3JX(SCFvV=F91U>z7{*))N91_NL^)Qj_5zo*FAOQX@C5=uY|I5Xe3UK2 zAS~giF<<_>&tU10{GLkTT}9!YU+~?-M_-tP&=_C%6L&UM_#>6V*OAxs#I>O?AHAL+ zArzJ-{=ym?;(~L_nm~z`958NbAV#T zYx@EmK6+jwA;1x@eI+*}MBF?5W90s@0_PybjMr`saQNtXjf4P4y!Ms9{Km)r?C$$M z`46T+zgmHCM*-pX0D+Gl0tpoew}1IJD-ga}fp9Mcj5`hm2z>P1K|+9_2K@HAk~`kB zE=bb9slYj0z_~xb;iHE`LIuusx8n1{a*_&t@2ydQ^iT!Tg9W4q0wg|qNF-DsJ>h#v zfPR<QTPkpFD&QOlaQNuqkWhj1kIyOT{Lpg(oG(@2EEaGM z1~`25a7d`YdFN24|9YX*zgB^BR{`ga0Edqr4ha=F_Y7^7uNJn-w<>V%E8yH4;PBDI zA)x~2TQ4r#^%pM=?Yaw9iQW;{NS#SpkrY(r9u}?5#`wbLM^xoOUW2N<$v=*&%7>*> zMpPwlrWAMoVO3S~W~ry3D)p?|kAnMs=yBN+kMaBn&$1tO-dc0lFUGFU^R+zR6rT6+ zd>7BMANKKlKhHIuZ|3=Ec)p$I9k+Vh;}Fk#c$R%~KhJmYthyfH`2n6)*TX#Ty3Ic? z+*Wf3cozI!JTHdl>v%pCo^Rm!aCknzbAiu6o{xs~J9u8;E-t~jm*?H#`7qCW!t;YX z9|+Hn@VpqFcW~g^q40b!9R`g|ZHEpcX=#UjZ*io<9^^H2*b)CY+F@VDC_FsUVZ2$_ z+&t1@yjkkAWE6%D``8~2CD08ZD(5XN@)C%TPT_7!2%M(4O7l869 z0R0b407roGWxi$Oo=$?e+Nsb-NaGKecx(mF!wblDIs_eX?hzt7H z!-CZ>{I`SF*_8}e39!0ux0MH+xu*z!E-{pMlG_|}g0m9*pEy5bjyA@>hX+xQIvbhg zai#&>$0`BMk|mFs9#^&SLy|}FvC4&;v>&IT=&(RsE#Tq$kK`A?@ZG-w6Ob(c38ar* z#v`slh!g5L-?2D{)%x zJGn&oUmqfS@2BuKzm5laV^^!V_TJcAm$?O}vSs|deGl$uo}m;$e}ZeD*7_f=@=?aK zDKk7sc^5yvGc8x6;QJcT!H6aqe^GJOx-WL8F1|DzoEo+||`G>Jnqr~cZJ-}=B=T(!&3$=|} zt*rg(-khit{^Fe($C*1$XbB!_u0ZR3Rl%}^&J(^!EXumH#fAocaAaeVX~iWT%wL_Q zbC>SV5s106vO_mN~8pV3lAigFeGcUwB zWR0zTn#nh+UbS_T^T4v~7 zVrzE|@?`N2iZr)v&0*jLs|*yWmVp5ftMf9UwT)##DlUN1ZjV|r2Wms0^nIgF4*^8~ z7V^fntyy|ZTM3EvZEZbiTZwh{ZEgK)+bVK_y!!B|wACtBTVbDNn`!};H4!kK>(^Pg z>!{`0#bH+$b0fHRmyG#9vbLBkW_0n;vRx;h^V{~hbG8@p`$}OqyaP$R?r)JrX2n`u zV!($>WW##dJwZG?FJfF4Ftn2M5H)JNGT`+SMm0VKA~yKbNPl`>5-g~(?mZerjo6K_!Nm*VOqH3QFK}H@k%Buzi z)Ua+d-|;2hf84fA5TgYir{ua703b2t0&Zt;w}r=yrG0IGLU|Aq!qC@w_aHXfUJd-R zy%UPkReS4Tqy3Hq9Rq+?De4dqp+z+$106?ynVh$ELkNR&nZLHOI{db>niCE2EZ&ck zm#??RiDHnw+_W9!e(N~mA1WI!g<2G)$zrGEC%+q{Tt`2zO(rC?hXq;i1#JeO5D$>VlkXaFZZ!*%MzygB*}GetfCaYqKlDV`ftgY){xa&!12^u_5_~|c`oA;S0l)h+(OA0uc8EgwY*9{*04p*60gof$;j;vo{lxe+0!HFR?(rx zp1^_*H7zGI6&toy8@k~u)G@j-?C&RtAzXBsxSKv*>pe_FxDSs?LKd2plw+O~#Eq84 zn6CoQ`7}X{7M-!tkRWe#Q9tFLPoV;%K3Vm39o0_t48AOMm|gJ;$5II~7#?A;VH62v zh)eiI6&nWUnbAdHOSf&*<;UQXrHgR6zZYs^RXg%sQsrk)<$CCS5tH5rW%YUI{|t-U z%Cw$t<7XmI2q()Ttv|2N5=;m7%%tGO2%mB-*&gaQNFV!rGL2|F8TFw{zs9dbj!PgQ zSuoBz@9{&!SCTGQNvf@cR@!>Br2r`;F&qyf^eEC)?Ph_T-7?w~AY6KO$A)g+h-W25 zENbckcE6h>7#7lz4_yF=+aazHMY?@BUG5fVU#YJH(XXgB+Qgo^$fIrM?J4XslkkFO z2(t<*!i+?$6@FG@nndijrpKe+Yw0S2`d(>XTk4j?DC9;bJQ5XW{ym5mH zuQD_n=Z)KlFzg|^rW9miZ^hm~B$(Phs!E?afq?EeC9bn(#e5j!qNbmP9hh>w&Koq> z{*j-(`Q`xy`mVL$9p*d~FRc}c;$pG{rcYw={Kp>`WDr^d-}kewqmd0_CYkDjj~U`hYWC&Mqv0EB_rT z1?jiPRxgdO+93aHo4(`U9|tILBrSG-Z1bDB93kcWqdN!bHF;yO5Wk)-Z}cPPO2I;m zn5aaTGVG#3b7vnmQV<-o7@sw^tcq)vC|)kBLq#!w(cCo&s2SO$fR_6P-|Z~go;Srd z*W5OCR#P$A=_{S0(7M1iuh^e822VuWcbpSZdHJbXd}{6tUlCS=6+5v#*nT02YCCl$ zZsbiVOJcx-Y*9GCW&DGi)v8fYV2duS8TzzO_!2`a#loA=t_$DR2)+R+X12%RTk}=M z5V6EJ7QPtJ9$(w^uh`2Gd~rLJ_?B>muNgxTG7Wr1+xjfQrRv9yN@A8IqxoXMV5+XI5*|*VGO}7v$0I#{<%8&8^ zi^jfu)5_blhqz?LsWO}70=j%mN`^>Z_VKdY54O?{I?^rIyjm`@Lm#Pi-gK%!DzbOQ zpMe+fM|j#Yr4D2tei|!2Rmk2F*~M?L344Dp@Ys2>7bTh9lw>dA3ctXC6*fr&o1ogE zU6oa|m&|ZBR;l95y=-h!2$M==hJGAt;NvXni03u=W= zywM&wyDpSziWEZDunDawKO6vJs7Aq1m`LqcbndLRiVdLnw9KD{6o8}RDo3HoOOA@^ zq_B@uz8-`K=7%@}P3~zfR;umKrQrE@$)p@Fl0Xy;tP~11i-Mk&;CAdNvyHv~E|oj5 zwzA`Nbslw!Z5m#>@HUHa*$~@|0ho51bg3aAOuCfaTlo|Qa;rL8N7-h~vklNCT?(Mw z8MhqU;6d=U`WtR-Iw=Cn5=8d;TVErf(0yD?JE>HiIMHudgE)0TgN&cqe&l&d;)hXz zbH=3_9Cj>4XQX-723dOra-qdys9};ZnF1J!B=UtdGCB#?QVm6K9k+yFT$lMD&C$@f_q{YtO3Eb(`~R|ZFLcs{&b3;?B!(a#{o??!WPpxNrnRp-tN%I$84w zJQH8O{j^?t{c4`hY6$-{Y?9@P-8??AHRlV&u6bgssu5x{9TTzn!3PN@jQ9QCLwM=r zUM6$&n4iUIu7|@^_#)dRa8%N!A_0Fol?gd982U#i&>2`p>?Do+q!2RTm9jmn+7oGs zZ0so#@hF8vb-)_7x-gMd?$k|Ou|=kUHa&`3ih0-YVNz>Ifc}0k(?sjXLAA2o$Mln! zm}3=f?t$;=&`Ho%&L>SxWgE(2A~yo@nkR(|OGQvTKm2LUxE&w2b2o9pC~!5E=R(v~ zv5dt<6};o58MiBB8^aYr(xH>&h3UL9^*U?l^g<2PkQ!d@!Re{)C{N*mykP=Z(ip+b zv%1`B>OJhM1K`y$lL`+kq7lXu66Kmk`D8gLwdQHtERtz3H7AL*k59kj83$FOLEIHTWSdeTi{@gf5$I1=s0#dfRghq{GTA6A)=gcIJqbI+eYa%653yaRZ7 zNm{eS@Zk#a>2B4PD2|1NkN!ctX^VT$x39lH-gLPe{}or?2vj~zOd(5r2VriwObV*G!BW=>KKoGjsZ?N(Yn<@# z5m)&d5}xi-le$|KMb>mHs^r$)xatisEW4=a z8N58|966uL{(*NUt|0TmPeOV$(VA;p_6J z0LC^@SQmKeG%Us=40Q}wFCl|^*46M`&Oi^>uJFgdVf)N7!^5QxZC{RML#;N^l-mnI zAF!m2{-e|`f|!qJ_@y6%{liCDZDD|0N!>Z!ww1pp8`bF&3KaZX0z*m{B49LY(PdBG zp`F{Mserc7ViJM<$yjdn9!d6R(cD1jcDLaa$aZGY)yN}#v{g!e6?yW6-xx3T<=U^T zX(2vQVZ0BTl<@w7NU96*R-4sh;?gTPpmzT?JIJDQ(`@xIpe4B_3)yfH!yYN=Q97Z zf!cLnAF}GEZ!x_b_uKh~5ewaUGKgMhJcFjjwNKqsv$?c> zj1ZT}0FVR?!OUyz`iNIJ5^KMIKyv@%F8Z-p18~ z=+#@WD1dPBIQa%lPt+!)_5L}s@de4(*Z9W7!f}|&bCZ?X6IlBXp`3FpTnp*Guhtvx?*RYX^!_)cqIBOY$@7(pN@Bc-#ZP1y^YmZMr0?^yb2xB$G zW%|ec@#&S^Ne_1+NVdq7jC()OniVR|`rE9h&gL>OE2UN)KQ7at4}11&$uwzZs` z5ej!OE5c@#LX>+VulF8JgrqD<2&w~~slq7w_y&$Rw7#@;Wlbovr1Ob5SfTF7SNs|B ze<8t>OzYhdD*3y=@$rU=68@!>19!*0$2gL@<8J6OkKJ&{-x*jJbY9q|eq4S5)*V0RT^izG_q}@n&-w|*k^)Ac%^58C zG0MCZ%YYGo6LB@y>D-kx!|)CFbFl3thueO&EMqZlQZu9 z@g^Jtx4K``m)O4Gd8mG=>r1jPtMA)7H#bN1*UytOmvI2j*1;$Kv9(Qjk8K@%C)vh# z9jiz1QMwgg>14|&$KbF2ZWXz0{!b=-Bg<<;7WoM*%T~qd z$aSzgo%gkMzR_$2r$phL2$Pk%#Fm7d`6OUljsSI2Z^EKwnFxy|tMPNOrdF&JX*`@B zoq}ws4?eka5c8j~J7*s63J0nT&e^uLw~Ow~>J-ZAQxPYUOhq`QrXpNYQ}BGvO<^_q z5zcJjoHyl-eRKN6Yz?2>Ih$tp&3O=#0bxP;^l0r1BL(**r$_6ANCwp_%ZkhrC+d(8 zWI5OY=AW7s?oEWW@IBXu4rulUl3NE0pSo)M^XCV#1&iJN_+uNl&G{%j&5407nXjlv z&!t92`YU3}na5KR9IPhshxKDMi9cPTOlgzGWU%%FQ(AGY7RtRe);xhmpbkZz#7)c! zT;fg&zt6N^;Rp*DQ4@Ef(&osty7(w62O1eQb=Kn3qm{+!>3)TcI>I)YMo2YY2@^rM zO+@hw37Dm?QL?a2#by6nw#G(7EgbOMPnf~mp^bQAugqJ4-4p~#WBPc@SfrlfAY;5- z3^@)by_^XYufatblYz4Zrrz}UNy)~4S$hNf{kZ#3I>!P^9z5klb7c&Dj+*v+%jlSJ zQ$%w%n|F#q&v`edtJGp!&$mGj2{AwNmN#;kF}})k2`5iTAgqrF2iSlqhqytJWeF!x z`1F&PrjPmbHA~ZRtOyQNABBSySRb828mH+_GXTf@SSe5$L&Aa1tErnxv1$}?Fe}5o zEsqH+N5rCdeDvw07Z_E@T6hzqy@@Z zU4v(odRmMu5!Mom79|UW(;>puPeM3#CBoHDLO4Z41PW9?b@^Zj8!@xgI#ej(6ch!m zR#6Z)*M!JdE!_6$CofGmRMtmpmZlpX>dqx_K%(eQMDv(DbTvh9(RtneN&4yZpP`?z zKA{(|QU65!wEE9fJ}fQ{TDdZBh_ZO_i7kaGv-)d|8%x4IQwKOrc=k*Y^h70{ zTqK>Sq}57VQzWfc(leAaStLC}Nhc}E^B=y+DcN`piHN3Oj%?&jTgcGtuaFX#VDDu$ zHBDoONLd+x*_h2A*QFT<`!OXQnxe_%m&FDofZRAdj4kN27A302=doHsIIj>QeO-=F z(h#dD{G!QmMEJL{al_~5`Ojm=`FxuH+*$53uvEc%f$s)BL3hg9g?oCYM4|V^_@RZe zmY!SUH8nxKBz+n12i=!*rcZ&jYZ^~-eyR{}aIOp>RUN}pLo{`bVFtL$kKXX9KKuk@ zjeM%Gxs#jie@G@+trJ=j@}x@+t^k#0EUZ4mbQ30_nt@w z6Wiucv;N=w)tCngtrBdx@Ix&L(B~*^ig|0st7dAZukB4M)TYsS6ILRb(Svkv0R&mV zyGg1g6`z$(aQ0H)=6_ZP%SHiyU!&V#bKJG?;P7i<*JsWM8vRxJ8S9^*HZA_BI&leN z@@pOxaXxr&E^BSgR%H?E?x5miHsptG|Nhna_#mS!gYIo~0CxRDNtI2A;=o z7SEd`)FMof@dd}*=dlq%DF&4Uw@;lVpN1Uo2WZLZ-lTaNoX)~V$>}zL+f{0a+e=Ot zY)^EnMU?+>bGrEzDz-XKi4A#+X;6ltleM&4r9OuvM^hRs_m<{p##@Xj+2iVbV+Q>( zdz^UJ=Q+tkg@HETdCMZx=en>@UQ!)RlxO(uU7tg-%)ibEnWLOFpxr*hev;Of&}2 zC`4XrbUg*>B|iK2kY0AUTcrm~z6EJGl04c`5`3})5xUaws7NfEigHg!lsgnDl{<&= z$#6E2LHarjVUrhQUb&|xkEA5gGV7z~`Ojnd@}E!hpF7KaZeqItp{m?%cFPhpQ}}|3 zCJNJfsc<7?Hv>9ay+qgWM8~g>`dAZ|Zbk^{vhzvLm!`|kC;d4~(~0z5AD!wYn#L>R zh@TF6P2*Tf4IX8N){&>Q^fYKJWEcOLDzY1F^{f!bw{|Rnk;UqzI$#d)udS|YWG}L z8&Q+I6>5@4Q0zRUs zX7ph1YYEP$5WSt??N6pM`&mowo+6+d?uTEBIOE}~@GouBA2axSf5kk>U3~}Mpzw`j z`w-5WK>Kg+`|7aV+4!l>w($3#&r?Mb)F+ku90WjplJf2wWR7`QlgL0Owh4NHnU6?U z^u2lU*>I%THaK3<_jscbJc6@2Z)zWd&Ol@eiZ$-W6ikU>#(9J~NVK^{Zs}Gy^00+d zd|}~j<^adA@)jH6LJ$Q1uh}tH8WYDKbO<27v7sxk3c>c;KNX2w^tFiFvZ)BoN6ml_ zD}5CK zer62a2-a5&d)(6w!$hkW+M$-X-LW`* zM>-5}^nn!Hio@}nuq|FfIr-%*w7n^A$|15*V}q;0$bTE_CJLC7AST3&dbQG`;5_e z@Io)4(`hNSTksL{Cv>0;@U{B0PJf=KKd0%>dTccbXfCue-zZ{UPqtEpUSX+ABGjIG zm|-sVfl3h*|FA*skxDOk4_9zpH%^Vz_DV14BG2RXg3W1dp^J^V*h&=jyNk^@i)1}D z!L`q=P*^Nbj$(Wf$kevk*U)uxH88wex@U#$QkN^h5Cf1+rdlV0O#~};_eHa0sCIXhswIdg2?V!x zh707Z%aK~_krH1{QzMmWMO0mGHETuGy4*Npt)j%}a(h{)7rGoOz$&V)%@U-)y~{8F zj*ua)7Xv-RAHGq4UZp>;)}M>@=Mql|EwDApe&?y^cljW-0wl|uMIg&E;bOb$t>Jrq ztn-_;PR*e}U-6U6_0iA!(Mz9C+YXeoZ3oKw2yGO0rkr8v>qGi!WqNf}j>J_AT_VM1 zv8urCCN6KaB4VcUlZ~iu@u|~}vZ!}WO1=-Y{XTy0W-T49xK^i8Rl&82nIW}^<3G|* zN;gpxqtLF*+B|W8b@!2HU!-_HXRajnrT_EQAI~quVG^RBk zV%;{wWaQn=cw|vyaPN&@d+gh5F6EiyNx616wgUVAs`k-2mWAJXnCk;n&p-Y4`}cqLJ)h|Lnv@<2KF}=7 zDRt8<(T0(W*i;Z9?6gD$V~fLBs;jZ)Jb;*!EO=o%*A{3Jo{g-=w)GnGJigUf37gDo zd;2WhlS{*gh=jdB6U08;K8RlpwMf^$g`EBTmc7h}kRltrrPW@>j7+f?P{cPjff_I^lUYgv?Kd<@4+_Rpbq$g)9yrptWoSrm&c@RJW? zU-`OJ#M&B%pwla37Lh;;vkui(CPY^YP=?xXQj4CM;1C~>H8)PO3xr-%*$aWfr(Qm` z6(I*;eY2@^mB7BFw7Qz6D{saO0nSrm3SNRG8P$a32z(ZZk|xbVDwAutOOh z#T5Kg@FEtD#Fb;ysS$CndP7&P>53){rOU+tIYkeAZ5M}owC46&M!&`>o`MDYX&_`g zTX3Lbb|TdPPm%>@)HRmISmH0vT`c%(M6YZYeO?XmqKgUTNY+3YEkG9ko8KX1usG&D zo2t|IY6;&E^)T5;cezZXr5(^=REQa6s=$QPv#?~^xhJj<7k|9O0lG1xx6o?E7GJR- z)#d3+08UYbOh7y8s^P_;uZ+8uD{pM|yjqhL>OXNfhNW@E1!SD<(>vnk8ZoNKO$tFK zt;^dWt-p3$H}gRJKFB~n{1&8GeWZx8Dy{aKP^LkMNgzR+sPn!!(Q1|#r+&adB0rEU z5QoebpJP>5c$5X$mBF_OP8F)_0|ul_ep}h*9*jKn_{)Sa3ly>isLO3v^K_trwJ$6a zBawyNU3I@{q1Y~)YOQ@fAHzpQ9F&C`Fcb5MEhWz79e%cEvb9^bFpmHP2bA`lce-a| zKG}bk7l}_WEAaqCMGQXqk1fRy)qp|)5~y&i`0?7Uw!ENsNqlACL=-<}Vnib>mb_fD zV32NS+zq~)=>Okg36z{yZJgxyNOY9~eCnja=5w$YKjhMgOm$&uI@tfAWU%i;ig^QA zPAleAI&W!+?Z#wj0|uGH+diTplwAv}txIdum_9XXFr@J>)1m@a+ugg>9bwL9M70vb5d9 zbB+)J_s*26Y;Uo_?zd<(0+OvQBDP30JtUEZoj{_rAd&8gL;(pfQcl{5AJ+OT6|%Eo zdGIV8bD*6pD&l70P^{CL`kdC&Zzsaas(_BVrzyeOaxv0G6jC3A9=>WL+n#A)Ha@ct z;oN$i8kA^42h{G%`?Oq=$1h~l-SEnOx`b|z<#t2TybwxV?{_GrF!pZvlT^Nd%dN7mT8C;Ma0ig=uAduK{KEHyyvx~ETs z%BJC0fviro>Y{PqHD2mT<7XSQU;H<8rKmSTzl-dXBNGPSRQ_ zzD~A@kwnpDNQ}-g5?5Hrli1h-^*a_&>O4Da0uL6yCPxfIx4X?#Z?e<*I-1nm_5@R4 z_AzC_Tcs#b24Qc8a5s&{NB`Iy4~hH!9Xw!}yDyyMSbk$?2u(@OU|$f6Nxi~)r*9QH zO0TlBQL%0dr1+q>t$Ps_{hI6zBsTVmeU@263iG)lTaMLSSKgp{vvea-nefz$-$6mI zsPLs|bjMz`>x8M7$UgBNyuXQuJJiB}r+G|W;v)XCUqf_hwt{FgJ0M|_lBMT~ucOy? zB!^JIXW}%|c1+azS;-lstYuos4{id5Icd_*91)}RH9R$6g4o&7ZDfQ@><6MU?*Z6B~QMl!#Q>;QVP1v5M?L3fyD%pAH zZn7u1HjxJmhcyKw3U${!rA#14_*<-Y9H(YnENM}pW~0e8ufA5S6cB;5DQbW^<$mv2 z5`=JOPjPOZT42bKcC%sY7UIi$FIH2Q0W@0x^7rA!Zj#B~aj|30D(#{nfWaBL&mwhE zLGF-Ml*j!@`0@b;J^W?dUvfJb$4B6-&2~7V{H{9pm?BP%9c27r%+fZ!qm%=lu)n7~ z^JeRv&64ugVyNzfKs*aF@%gy8eGYD{PDKHc2A);b=aDV?1v|P%?H0v-BymnYJ7$FJj4C9} zY@f-Yv2)V-A=_Uox;LRv@Bc}$atYm~0a2#zjkl;-K9O?0$CKbZY~u8#NF4IDLOyvH z1VI#VE&RhW>j9J{cwsG%goSd9>v}}27ugmyVwkOVNY6&gWLp1G7t`=T^BrOJlL2T0 zKPK*$K>fV2qMgM4e-XjS#EHs{*3hhAqz%hdEpAFF^ac~hw6=^%*2z9}+ytXVUhTNI z-h4B$ScF9^+|Wd2#4gvgfq-7|kpj^n5XBzr@P@ho+LT2&v&A@ayVR}XwCfMmY(CIq z660>Z|G(#AA-quq66r-&Y}E3rq&cthMzhPe{=o$KHKuG%K|nZr0-6BExhZ6JsEl6N<#Tjb?$ zyo}SEG|p>o&+|liPEW2<{#s^y9yKYQXXzg$?4DD0ed$_k>RwH(s}3-P30ffDK*+TG z;O9rHL>L!i8j>K09hRreNLDNSSIU_ScWwORU{XfBKd_{3=hI2D6sTioGtB}-U2j>+ z_C*zEhd%g+;yC)y)-xu`G0@qGuguhBF!S!Q6*4=v5;k@z!6pXj7A7)s=jt0MfR2}Q zLWjjHbssbXLArz1W1^_Tn0s1r=84e2$+}>Iq)ukN9(AN1Cu|M5nJQ*bk}Id?d#tz)92CZ=P8fQJ=6%Ife{8@$7@BK*t}i3tlZ zkM?X%-)dgF92Y4gO*Jl}BxW15Z%7~+7qxhUnt_Y3aYPNzgxcOwa#1QSYLJ1$awq(Ly2*a5mrhJ2*Xi(#zm`5fwQ*B ze>x2R6mQPhT8U6537(-ZML-6%Xp|TeLvjL!bqsI4-%6&TttYEJKtyJXWR`vvVX}@O zG4n+<3LZCA(r&>kz{*&5TnCN07qI~ZAA>$>%pe5 z)dtkk89rnTYNNkPI7t64GV(g@8xG7XF(K#0|0`Y@jt|QP;FY68}dji`7e%gjKl(vx9`Z0ajjj$@Ddgt&yY-c zviMjVFM>7QO@~J3RlEbWIuiN59;vSq(za{P+e+Wejf$|4Z=0Tu1jQTz!@bqz7J6N{X@Y%f~gHlipaJ*ASudbi#p`dsE^9?n~yiC2DZ< zJFqD&{*JQRE4l64dYNixUNMd{o4h%_9_89J+Ua70sa!$tigB;5FN}M2z4gGcUEk0o z3V5!@u3PQMLv;)(TI*e#!kMgoqZo@yXt!rofn>mq&Q_Gm&sX&1om-kU(H!pX(tJS6 zRy_9z{2}Z6Qu6~PW>23=-?Y;=+go`$P~^K)`7q`Rcz=!+!UQ03 zH}bHj$aS}J?HT6!4j&EMkKPHe-9@%T%0`e<0Zcr721&-#QvoyMX}o9N5&0aH*rqd~ zw@3Rk@&-=N+DBHM3+rUW*fS*%8^bko9rR4NnS+0_=7p262>@8uFr|;foX%hspr3j! zHR}3W@?EzRY5t@ZIh&4=PRJ5%~OcD6p7h&<$7g5#7Q?CvP zG61lg4>Ln>-!)^D}7*=8Xsn2(m{Qh&^W^w*5pg4%`#`jhj$8jg8~?{C5+ObP#^*! zjgihc@q+7@`L#}dL$#9+7i=137XK&X4$3jxGi$}%9)8SJ2Mf7u1P#ZG%)(k_IF$m# z>c8!qH1`S+xcW98-VzY_mKcc*{>DjitLUGGzK*E3nu`%WDn?+rLXa@URG#Ji1cwsl zKWG8G?~1Icxpy<4TG%G{g2K@>o!Q_&%V|vfh=mxL9|%vn9K*p;gvF#VBX|V^R-s3D zkC~a;Qx6E7;DA1>Kmb|+K~q4@oCFQQktfA79&c7W%UZ;(WVNc~_*t$h(kuWDw>MmG z)n_~@>hCNCq5$8#9uXT*Z<4Q54>$XVlcR%p)JT#I$B!+V`1)BS2*JpjYDQ9hN zQ_0?YQ~CXrDH+;Ag@U0K6g`eDM3cQWgosbPH6%7(#t_22g*IHm#xjMDb$4}cPPCL1 z0>zTBm?Y;GEE&PX^IFJCxhMsWlWR4;RIAPL_Kmh!i1U?`I|dlutZfks8rVIoMcG;j zM=#K(uoe|BS&ND_HtVXZr$tAWq?mQZ#%Gma33#v`mY8&S0tYMjyHVtIe*d zW!>H^#g3C>@Pn1DRL#?lu#lA}TApG!`PdNX4d#ReF#kIR5yKCW=hT<5WW^~XXUQL@ z6(C!XW(>0Q!$7xa^Ou!JawIs0*CubvBW^xFnDpTRY{8q7K3vVi%?VSf(8J)A&bk-t zUL3^G<2GnIy8EM!978nIp_sOvgDpkzdAFngwGM*1hY9e4+u@zXe^|=UN;z7Zt9btt z_BOivNL{>HMzcHg4_*ejJ9yZ+cVS`Avyl(=WZn{j47nYF`L49bSq3@``&~l)KKTgw zotFO=Kv0eLUL;!av@SXOtdvMgJ)LWQZ?a;Zu+k=}#mbi=I+^?9(;!z}Q9C9OpoIs< z+eX@^;I$Oi(Q3H@*jPFA@o5UE;rPKp{c4tR_cA$DFE=mOLN@_Oc*DR<`hl-kSHseh zY5$*sc{k|KFuKg5(4dAzp`oLRF3X#QR%FqjzQb5)<)!MRL46zI)dzy*Q4yHcBrr>h z;2^|77qxCG90*K95DyT{3NAwh=n)9^N)VcYt-#@I+=2XLb6NY6EoK}CFo}6#-zE=3 zx1kUqB76gktO-a}2T3T~Lm%@q5iq8XB?t!eI7LURC!kfvugS6x?Ex{xuL%+z5}H<& zeBF5JBXo3-hqGo7Khz^76skriMtd2s;zIZnCBt7lRCt(V7hq+`dbZ$4Q1vloo;!%XReo42@OBnB7#4*c zZ4G5%&uu?(76vo|W+Q4D&}wW=@tG*>i|YabPs37I5gIz{9{c+(yyk)gJf68hVy2v#XrW-5O(n{7FZ@oELrmluY>&qm< zj2?CSt7{*qxLPfhazi77yU2_h9ApcDL_=GYRu(n`@<-sv%3*?V58v63 zz)fK?eesF%N46?2xY_w*FY6*Q@`o6sI*2hh)KZXu@o0-306Pzf1|JABlCtD{)^`~x zVitvz@o05w-U{?u-lWddVg?d43-beATLITFkoCxBD))?}tft*RflTldoA;supxTXM*GoO<@g{$Zz zo)$@X>FUMklZrl#f<7z&7(Rfinfug)Y0U^n1GQ9PRtBtRRvL2+e9lpdfRmr1FT>wV zEK@o<0hScj@+Zz z!rlH4-r*uY<`AY^<@1LvJVhNvIY|;tU-)BpHla6fN5}oYED9f5xnj81P(BrUGi=2e zN1=p@#XCH@`w74ei{n_Ak-{youw&=e?j-+Pvy0e$c#?%+z^iwThQ$;3>5g@*Rh z|58#y)757>74P!RZmnOQZ*O+(^YPil?$pgLJAb_1Av4?pQX2SOaw);xZUlpyX(|EM zzsv0UJls36`%LU^Aq6MO=BB)1^43&2CA#(8%O2E*iLkP5<$j}mS}7v$y^X~J$)?15O1z#c+s-z;DLxF9j-703!-3E6!8p#z28YYBCbdW9ZZmldRqfICO3Qbl7LCu+G_uE=2=Wgq(76~;c z(BdZ*-2(**LKRbJTP&d;dLLm94kJph$W1E^FM*Ag2l?KIaf#n$CQBcye(5Lmh1Q6m z=r3U5@PplKmb@;`TN#WUiJ^8dg|x{@_aOG(onn-sJvwwp1r1t``6va(?VLWQg`vm_ zU%@bC1_`02gwgo8mJl>xfou)~M(UP6k!(_}u;r-il43ZfAw?Uxx%AjJW{H-7Atp_g zjf$d{h2j%>>yWUJU`3^|SdC`)sj;%DX{=5elR%WvJe6Mw&CI0^q4^#PI7!hg17K*B6-eCewl=~pLS*<=NK72t_)af z-UDhmE(tm0_dC<0KjO7-k$Za0Wf>Ic4e$9dp^7le!^X|6Y zgV0!k?SIX2jseU6&X&>8Fd#EX#>r1C!2o9ogWgOOgv%+?zzkNgWGv?1A_?jv&HS!I zau^3iv5^Efpz)9E~m->)u3mOKsciu1bCZb3>P>fo$#cs3U^{cUud9sqQ_* zEJIn2%Q`chdEse)5G}UII|R zS)cy?I$z$#4+_R*eb(-Lp^of4cHDY6W|IIAHuRMdJHpV^))c7kXH{cN=KXgYl&BL3 zWL(4aQIf{?3X_ATNdT+1tcG{2zz5@&S4uEQaqBV~k5vHjRT+e1KcRO_|FJvY_N!)1 zum6-RTKdVp+zMQ^5L5zVwW9nK4kAfp>OqQ~8NbwVh6T)VNp43jZNR`gxzq+9Jc0K@ z8`$V*xQEY_l;A7|ltz#eM;MhhBC&W<2L=?mzQ)=N#rU;_4&Vs7*{%vdPqKPL?)h7e2(kR&8>0a!rjU z!)Q)}=Pfl}z7TK5_U$%_(Q^;|2|D}=9;Er+;!L#cUd4Mcp)jN9eF*hmCh^ywU+T8& zm8sNi4fhXd&`U`AZswOT5m6simZ5Sp9u3UUluEY&VLyf~L>M9qn(s93k}eu{6FH*AehtaH5nS-h$&Q>C1Y-~5&_5VRuRKxu_l$UJ) ziCu|uCYa~i)4%UDiTAlS-r0#PfS;8!X0M5*7M2f(U`~}rK(ws=Hd7VGfwD< zvlUFonKrE8>>aioGt{6l^(U%SgHEen;b3)5*JT{#O{Oyml!s54mmqJL80b;qKWv4< ze-02Dz)x58DoQg!3@ABA_0e+*aWDKTWQhGv02hhRkCIeXQ$98*XQtW6k**$b*w58Nl-Kp%6!qRz1>n&1aZkIRhMSj_NCf{V^K?6Q1 zQF8+x6j z>4sT_g@*G2@w8$_6@(7)EKNu7qK1nrfOZ6vum*E%svqpc)pp+jhXU_%g zfr&KqwNoKuWOM1Xdi!?XQRzm6$l5JtOSohhC1doLY1qvzii#)J#aAJiDjiS9gpQ9g zo|k8Ri3a21*<4sq_c82?o7FG)7O`(d$1NB8hVZCq8Jfl{v^8??Z45^)j!?~vWOHa8 z03uK)hflD9uAee|l2qMZmrH`PpbUHP!?=?8GIPURy~j-3iy8fLUJEEFF_|z<{fu6Q zVwq6P=+n}C!wp`VZyC=BtYStF-bDU`JjEOC>qOH?v3xcw70YhD7m9^GR^w`Jj!{nu zB%$wV*wGuTwm_L8i;?(p9Ri;0$>uF)j$@(uH2Fb|UeE^Dn~VcSMVB8xN0Tl1UZ!Zl z7W^otq@SIMYA=dy1|TlP$}xoK8m^X!H?!9ih!LnM1kOf@rbwiTomiVeq4#tMt;8IR z%>crq=4pq&SZbOt@FEQ94FnJ~C1xz;CoO8TMlY>V?6wCwOi+`|3P3=cXo<^p3eqJi ztt6-VL-(%ocB^SJX=47cj%NAla$wp$G^(#I|EZxya02hP)oTP((wPrR+w(;8G#%2E zfoCFl)k3~=Nj;4)Duk3`kp;DF;!xT}4~9HRggpv*&4o&=^-`eAG2TLy{qKlNBN~Pm z3c(QZMhM*nDGeL`cpi}*YI-^CylCmVNcVD7%LHCzX4pEc0?hdrm-A~niNP%&Z|A~M zKgfxGvW>bc%J}IvzU5-NowJWY&SuMM_F4fejr`4PH!rBfQ%OE45R3IWzq8_0;UB7=6LMnX75 z|2xO7=c*3ks1PVr?H{gN(uurVC%S7NLg;=C!NR6N-fIiZM zsN%QwF31`8I`SwfzDQbF$-PpNH@rlYL0O7g#4=M+%~udn!DIW)ea(Q?@PlFa(IEu< zw7B~6_s{IDzyS281mfT3*t`UeaUEG>aX6E&$r*u~?s9?<|I-lz8Oc~6x?q;oG)WRNX6dSCq>HjvmPc`Mq843Tv-7shU}bnG zZdd3}4O%0SB&bzo6RW5XG6e~-LWrn*t3tC0wljolw54}6HbKW{B*j~Erf~eneWrfY zAU+;bNDDF6+6q&aoA1559?3RJuIQc7=>tL<#lq0kRfY$hV@DziP0N|t{hjJ8z-p7T zdLCBvhAZnzpi2uomcu@Z3#>0?qjx@;nB<}lSsbDd6M6!^ch`EOA64y+ex(o?GSRPx z^U5U(is`Z|)_D@PsKZX9A@xc*aBs0yc?gGL2oV{WSb6s<;wW77Y+Qwv*IS`pmw@&o zFJa_a&BO2qi}eJ5VY@+RxW1AQfkfv`KvczhkbW*qMSzn}ma5erUSl5{?#%xDV3&dc z8|GX#*ERyc8>*flj20gWYytxwEEepdnB$sKxjNMjo~CE^@9Y!asjvxksobE1e(k>| zL;LN|Ydd%J;mNGF6FWn_suLsxAK;yjq&1?yY#kf;c6?myP8ahsJtAh;k#p9V!Er&k z)_GXK))m_Joz}P~ZvFc6^+jyD`zz6#bNkseyPq3wvuOX0JQ@7cJzPt*n)}@uQb$*E z9q-`!c^tTN+?C4-J7oA9zK`u3ynEr`!qKZ1bz$$|pA>h+|02uSvW)5ftpP_s-hso5 zS8cy$*L72zd_6dO`_8k3Pe!<1dgUzCk~T%&-1hb7znLNMH_;|Hrn3gG+=QU#Hpr~L z#T__I&(z!)+26{i*5)f;WH7imn6i9PX&s2-+f>_ciL}o*?BB3emBySENv)2}a4r{p zAtFbeA2iF*KiFN%n$n{5p8xl9WTiO9Up=pZ-nfvUN#jKB(MC^bbA=a)Y$!`mlyFFc ze-cj!pcZosg+5Ui(lST4?rzOUBC2m0BMkfvJmU^TD_x{aQ6CCP!0J33w9^K;Ft9}7 z&a5egYbH#Wk1Y0F#1EdN4I>3*#QTCe^Pj6D{=mrUR^)xW>M!aKyYSkPLTnco7dj=8C zEp0`?W=UkTPyuJa8vaHIBae_)%W2f{sUzD*c~Ar;Z8Vl_@`F7D0f61~u$yW(v{Ca! z8))QtKpx%W@c_-I8Pl@`4~Vcv8<+{&K>Fj+#=skGVo&fPV{vdWKsh=%FjfFMLYpTc z4JI<`8NxgzR)3OaGEoUEFl89ABRlmhU>F^r)v?<`L7aXxW$g?T^Cx3F8aI4wxXu`-ec_?%Ywq;8QoG%$Lc4l(3UI>)E8Rc;{o{ok(B@qd@oXFT@ENe?*Sv4#g+Q9Xe z{CH`}XX83H(9mgR<7UpYU%e1Qwju^vCW125jrp%N*CaAic;FNU54DhS%?&E>azHa+ z#_82IDavAD#(|IGLGlYmS&U7PzG7DgrO z;XaG0HBIC~_v^qux?i&2_q?&2S3jO<^3?ad&T;XmmK?|^qvs884QABZlAf0@UCtI8 zT~y(RrJ7qQMk}r7k>)S&aI0s zU`K2{>tM2zh3?aV8LiW!IB()sQBy1+#ZFY_IA@d>=vVeM^kTY zC3SO7IPZv`s7Ua;;wKo~){NMo%raWjWm!l3)CCEZu>k`=@f@+(z)!7@M5IuwpdQ1# zN{It;rUm^2>}Ts}1TlETQA8}u=Z6$;l~SA=9QDayTNQT4%aEg%K)x{ssfN1|$R^55 z$l@ufNmFwf_sS@uCu5pn4KaEIo-#3~m?$mV$r={%I@t=f&Q3M;#8!`uh`GoQ%u>wR z0INZ~rD6{6W0e?tJj!fC%*>B~;IiR~b785V3rN^>K%`!YEJ?DJ7f$9K-(`lBi3w^q zp2}N8OUtuq5VnxD%IZj;qO*dKyDm0g4)<aSrOc2$ldA50o}Ib|(F*W|#>+qVW7!8C7_AE`N*)?=tH^c1w+*yi^DrN8@d@ z!kC$%_m89UI@y@aXElyl7U#kix{1di0!T6ukV*uMWvT8DQ&8Vkonb1#NSethU zMy>I!v!k3Y!bN{ERP!GhRuWXx0jhe^Cc#q5po74x3VC zm`2_kuLy4d&s{j44l^eqGvN+~nPG}k*n{{Nq~e?eM`)qlVzIk3lB7mm>a`&QIvPOf z-dAxJFw03Z>^Xkc=A9j$@?;`5JO)EEGBLsiV*}gMCgH@%?v&PMt+pj!Sm`Eu^)g9R zWs638s0Ebh)#%L5MtZ@F80<3{bz}ZC0DAhz&~5lKtKCME|5e?V{4eP?R>op?E@D2J z=G0I9G zI8kMA3Kj$l(Q9BG8#uV67@HuN>DVLv%rZu`A#*r%8q82=0ZY&+tCAofW~3vqi_pM2 zb{lq3JA?#ZP>&#<*I%#UZ1PRR+7H>PEa>h;2Fz5(jJ&vBt}wEt+}qnVF|&XUBoQXF zZjX>4P;89P>gy6s3t(y}L?Ztze>)oV7V5N2*B@IrfTx6kmttsdS8JB3fygQ(8;!*B zuohdMMR3#IsfH(hyhL=-oh~kB2rFn;f-C^mjR;CNY>|0+%l)*?xdCk=kRi6{uF~ob zOPv>tE6fbskVZz%JT@jv#c2GeeFkj*b3Z-1q8lgW|04L2*>%AVHWLmq4L_ykCx!y1 z46P=Y7P}F7s73w$jPD?m!K?!svbwYomoI2*dC9kcMHSSe(M^I^tpriJlM0}~j(Oy= zNwK5@uH5C}2wCS+5kEY*?+STF45dul0q&6A$5C|a(w&J0%?dp(*yFe!kH%i+JrbMH z(?}ZMj?{7wXc>Tx#y$d2Rr1-nCloy#v*c>xuX~L6vo>OZsft7KsQg3lN&byV{;gyV z%VZDvhxE%*hB85moSF0FLwQ_d z63E*X)7wm}{b^P9_-Zq9fX7E!p2kiKo>jvD2dYs`8%Ppx%a|&u$ z2sQ0oT9ZbEBoeH-mRMh3Q82#gJP5jCd!VSr?F!f%Jl1bqg7gTejmzR(6)0xp4f{*c z69PW%fo~{)H`a4w)RPGu1+EkVCm_57Mt*u?M{Dlj|6>+Am^V*L?4VnYBXV4f*q5=i zTPM+Eap#}vORt5~E?BL{raq`k3nzHWbX9Qbe)5IUv^J2&@KNf{VAaMV3B1ZvOwtGL zj4Z;Dcscf^ydG`pt}m04BI%)T6uD|e(zm`^Bxys775wxc7fC&zlw#f!GDZ*6acAVz zmvJdFd*|?zbLogu&nB(SX|gs4R=QU==d59va5o-o1I}*Gox}nmre!pJ_)d!(LU{4CICPyd5~4oioxb~)_P~iKwul!U||Pp=vMyCp9KQg{_d)p z9AB*C{9L-0pC-F4n@kDpyuwpSXgJ2Ni&*w!aV?|B0!`86CB=#*6w%KgELf9;QZ>sr zRA_9NM70I#OPtR1{-Yo&wvn0?zGn4uAP+h%Hwqzh>u*vfj`-A%oOO_HUGhe) zhvWX0v(|ia1X*gThj!p_Yku(TzR?%78nu{F6r`JY){+Ivh}K!OMuA$G$uY2Di)!bq zG3tNY+YDdVJD)mpm2L7G-SFj?W#;S)lfGn{|5zr8R%R>z3uPYs zVr2h5{Zj%O#2;84u{wbq((_c*P=!`Nm98Ev4BmF@+-SLQ2= zHvRnnkrmHT^nYz;DzNesSlwKu>$FmoOd^I>xfgJpto6;b|C_Z}G^0k`NE#_Yg{Z_c z6WptGi=8)zr^-(EHj?j(lW9TFZr4>=_gDAMx(;TAyDFAtN>yj2^4n(Jvr^pX_6xfx zS^YmvR*6Lj!|7X$ZF}OQ#_(71NN{~BZD-er_!-BZ-73L1ab|A>9aKBC}+7OFb0QHEmAIlgJs}J zNTB;{Ycs%@d=vdokSfM1#L39P&)U4ZkvJWI258R^G!`U)x{#lsm%KA*Y~v~zt_g!R z#@@_W3kYZ?HMWVXXf05M*o|j^(fdF3*LUgP$=l|1H&1t9K9UpqP+Rkjr;EN!<0rOh zf>+R|>t2wp!ppFKr<&uYFPv0U7=;i^(2JHB@`bBL7(>fWfeqvlb=c8swk<*$jxQ*` z%Doj{gAKbdVrNEF&&)k9x0s2VSOnWhbf&GuV_pyBrnnG>GPOR8+@UX^^0WY$5kjSm zZfST5aSRWYbZprc<%D{&i;9G5%}s>sQ&eU0z}h#y|%mmza$4 zxZVWRa1xdTuubdB9|1KN99Dq<&3}k;nK+P(7T9>(i9FFTl#tZ#MxV^p$|i~#iX7Cz zHek#@TWilXchLlfi+CZ_tT>UiN*$lXW_@Wao~LpkF&ov4rQvX3(Vp%`!jqxYxFXgy zB^VFf9H_3H#-e9D5atLGj!NM&7)gDU3PMl;+A>UPVWF^W{7sL6!J6pB*B zu}CTUi|S*Ta2%Cr?l$ZF@sV09T|a~z(e>6X#{I|X^{lZ4*c6)86i`yg+d4HrA1?d7 zrjBRQpiVHT3~uXq70p4r=y)RK6s&q|$JdV6@l~ka8D>1Cj@K~v9Z&P^-oKU@Si4$N zRXD{SI+Jq76*t21;)Xrpcgl0c*$!5ce-=b_I)%yLyeHL^X8h<{BosME+!Jf*Fd@)z z+B)4~1ogy+Y`F7x)+ujd?pw%&2h>FuWCUi$uTT)AoIS`V3L~#nyRlL8rcYNFb^`3m?O2fVkPcr?FzOG#zO6FCTY(l`9>iuh{D-_aTgcw)M5Wr~0& zTd){clFW3x?pcab|78)6&6WJL*ClVz5f|gEa?9y%5l<`h70-IKaR-^@xlt35cM=m|?X&)y?;gnk|X}Fr&1HLdbkrf6yPhMx0i_+T|yn4Tk>?>Qj)o~tpoS!c3PHATOujD_M+EzjJb zryt*QaMf}>H)TDi8Lrld>0YxdDjioWl|e0iGO)qgW+qfpV}u>n8X<_0QMld^s5*|B zNLVUO?Ot}!k2RGEw!b&9F^M^jpD{LtS~GPC+iH-Z>Ky|BYWd;CvJ*#_s5d!Y1wTR2 zhdg$fzA+2+eaO4|n;&FhmIkafO=3PlyWSvKV4R!@U5RH4X|bc;ASS*+=~=5I1T7gp z8r?Rj_(guWof?zvZT<<9?JWSh2b1lWNnv%J!!*PZ3o5~GGDSpNweEgBUM8to{70|u z#&)Y;xt!IOY9q7zlfrB(U%lN{zIwy0eD#)F`6|;b3<9PuICcL8jHqL=pEe^x16#cp zQCQj=5`F?k)M-!!BWm3biB~M!4Hxd0WyE2ZjsPV}1)ylxz=#3pC?mFy%ZPzQ-g;tw zBknJP8%#c++)3&Z4x6`SB(cSad4OPD^lYQel@GRUB7l{@}j;l zF}#C`p-wL2agj%kEz`V*zZ2}6P-mbl^@@k#6E=fkhC#B;4EcLK^TSWtg=PdAx+qd24YM1PElv3Qa%Ej)qPB9vqs0NEm}5(-4$Pw4dDR!lE0bRcps(WcjN+HVB+QQSyoqU5Y4iJQ|Z zvWFMIuz?+_+oDIfn>huG;v-0(NoBO5oC`6zOfDy@rbwLVGUK;!(T|wlZr-L@MREGe z7Z0n&|5oYTwWK+2({@pX&VVA7>ij~R=wyhCc8rZ7S9(hCQwcvY^qesnSDGoZW6(|B~$@{=>OGWbCx$>9pW!tUKw3A~Oy~zb97v zJ~RRmbxa1`X}rpuUXt1KvifDn%S$rp;}T9*lAos!IXRT_!%>=65_ZVPOm4VSR^|y& zn%F}53+U#FXil5U$(=vNe-yoPO2GmD__A4%=36c@ZECa zk4<)5k1^L`>l7}|{X27<58Lrr$ZDyvDJSQ;)_Df#39qMVu6IFgey|b`3TxTq)0!(R z!0O@V^Xz_6W{(#$fy7Q^J5S5~|LnaB(57cup!puYQ~%$8_`35aH0hAM-I%x?+m3oJRYyIav%1{g@HRYmLh8%m&x0~ zrZuMtaM+xMD$=5O(@^DOkp>~%fVa0X^fgR^bfE^wu!3*@X*T=8Bx*qTfvGX8e=cVcL^<2J~ z!fy!)#NriJ9*I#9dNI$3ctyaOf(ThSXCjdbEAF6G-J!38B2_}O3sf-E&a0{XI~rMK zU*#?izNY%An-<;5vxdQ`dq1?_VY5LEsNMt=2Oc#XFcGI{>$4OgU99g3VZ}lO5@Te^ z?qg36FhCFP48>59S<~iGs4)?s)eBi3+A;nGCR=l37(2_`CWW;bTy2@y%ZD06$|ZMy zxB{#Ga+@!u7k+vu$!p}0aR(6n174VPOX@X>L8s*{)EFeW3ZRiy)|RW^yHXY}_z=5m zwNf>ig`GIpWWr9=vmf182WyKlyf>0!oo_|(U1vosIumvSO3cYLOlWp>m;|!YBdn_2 zqs|hHh~Q-_0{H}JQU9zV%?X!b0;UeCT1MO~YA0t5khJA#0Z#*I?8o-=dqlIn*3f}qo*u|EtAJyrb9RSJ!tN{ zN((F9Ril%8A=4p)AW!aE+Pj4O3QfCxu*Q%;p8cCDr~QDDg~Q}Uti{3r!MhhV;SC5Dtk`bJw2KtwLq82! zQIJkGS5(_nc!}(^N<0Rz(@@$3Jl)C>KI8ElCVL+Wdtc=`yY5Q%J-gGUAc6*y>6&Vy zlOnDT;`~Nb`Vh~>OVd@M2m8gzsS@k*u{_@+WlV^lK{lJh^J16AaQTw%P7B=^;(25j z(>Op4KT@&xma~+abr!<*-NBhfs6aO(HBu5BIg?mVr86ZL6P88R(0o8x6=*G?$kG)z zr$v-@XM?8=1}P3*Myc?k3y3`{jo|X4fijb~tWKn~8kOx4bZPadMl^l)=KGw{Gg{iQF2O~JBzk+b%sisH&Y?#bJamydsX~G!R5IYyDDCx zDuyr>U)yF^kbE#^29bQx7;9n9T6JIm{}^o^!Z6vi>Wc!;>+Gx~qdF<~dXi z>E^H#d0*ii2FlOXn|ZxX;an4$PvNoTvJRzGO)3yEG6o<3a51E{ItVBXloI%%KA+aG zV4kH0^VeZ?C2HW(8)#%6FTt%UnErL#oGcYHg*@xQVO)FnxT`?KjM=JDW~xpB?(7&8 zr*a+hV(80JX1t0JObKOCc+%cD!vAvMMDAl6U3jHmocQV;&(n@g{5eNsoGrmuGD+BN zxI_#a<`iu2UN8=Y9!{pk$e+A!3#5P$ZsmPUU8GR1PE@D>K?;o3M&x31u0_X$5-gUd zQ8i&cK9N0VT5u%{z=fs`=`U!(Eemc+TBd~~G4xJ-f?>xzB4Z?lXr}WRN2i=QSPVZL zKcR&#ledS=zX3;OribVy(I9!VI@+LXH!j38eQ?h?PeVUTD*zaOF}6-6r-lgacgEE) zFU->#u%XiF9g6^T&Y9nf97?tPbz6~J@?+YgCHU+D4N1Cqi*gkUBJ+B8kwcw0S|*1K zjzE|>^AH${R9CSvM{K#10lVSV>tp~&#PQ)Sc(Gzqw@o6vc}uDn$bem=VlFNu19U6v z<6RloULv4ef>+G)7JEokJ#X^>InD)cQ7L3Qg$oSh&yx`R(V z4nCHcLuPlGb^hxvG0=nfTgB>FmaTEKoee|3YR@w0H(De0VAuNdW8R{&ydgLAhMqAS z73=Ce&(%NJ!z39ms@HH`sXk0%s>gHmMop}x>bixC)h&b8R`}Ni8$y~kK`$?`I*7rtD*`?llYxVwGJ@&$Ry^pL+3*c<; zu6{dLPX^#OZm(AFt=0Q$_1k+?zisc|y*Zh0lUw0oi@3@ZF;`~;C(<1wlfnp4M9em% z^G&>ilhZ^BhLw`pF#Z|76e(c?a4Zgqs9HG*`f@WmWL(9_dUhgCfUW1I%)+yJ?-{UI zr){&9xPuCcTj-%vqRsBbMS~?DOaVsTJ#H%a(aJkmN-lEVyI>~Nm0rxEGRspn;!LhV zZ`|Bp@RLp3k$bZWdg$4y&1T0jDUth?s)1ixKGy~<&&x9=ZxSQePz5`r7P_;~kgn>X zsrJOcymCdlbPIkhcMkTUg%*$+c90q-NDa@2)V>9zScsTIDnCwxW~lRbKxeb@XCUZ|jK?2AmIYV2R0vf) z%TQ>7v!dlDWi<2}mAp_(5OpeBI&?M6ZbX?=wNap|w%2jsAuFW3M=goe2?&=^Yhd_! zB{7=ml+nRb`zV*84u=ZLWvHOIsH1O)6rE}V#qG3kQx#DzqF?OaRrqE1aH%~02C|{x zDpbZ;98Y_6A}B2$^$69a^PyWgjFl0XLnWfN_q!&YbZJm}VV8Xa!%y{xdpN3vYK4s@ zJJ_sLY8MGMSgBE!ij{!mhty2|hLlRev?I~)=(Q|jrhde%-G7&w26Z7q2@q>0&qa41 zpKJRZ0oHKNAhD%=@)EXXa1XvzdGUavrgv`cT)K(fuLDwMFKoEKr>Q4Ojp1W|UCh+a zhb1cam+$}w$ih!)iM`kK=hcCz7DdD9x8$DF-_TmEaT75h^Ga7RAW(Y=4Kg6+MhGUeoR4nD z)=L-8C$}O9%ISLJs#cMf3BPiJ#{V_%_4x!H=eDVarv#--1pV~}vNAB4MevP?DFazU zoo8ObQn0K>u|ksmdT)J~B+coe;^-LyUFQ-s>;OdH+zt?}=s>lDRRH$)!xAV`?5iI7 zjfZAyJk=hcxoi&v2~&$Tv65W2P^wiWaNj;sVg zwq=w?Fl)u)Zc$(>Y09=3^J!?^kc1b+#-()P8$kCP-B4sIEjSJAxYX!aO&wS`rj z?V0%ZS+{Ofm#_5TtK;s#J?&@qtY+TIYQ5)}CAb~BV;Kq-6gPt6Lma12zQd;;Zu*#o zMl0dxb=L+Ou2kdPAQ9Zi;<7MKH)h}=h!n#)`7cm`laQ6wHh@x~g$aXV?xau!w0zXh zreuTH{otPBBFOU(!slm&sdNh${--Wt`#LwGYs4xX@o9EXAE zf&mRGDGPY!!otLn4x>Okgv3YQOLVLOEwjO{9cNbFyh_YVTfhZCtEqWnHl(Ha;U5Sb!z95fJUzM6# z(hSo0XnJW~NdXdan#u8aZoo}G7YDpDMfzW7E>*^K;I?qq!W)Uolcocn>zHD(5;V?Z z(vOUDLacN;kid)S0PCC%7`(AmF z(h3|v8jOwcDYOT-=m@LlVd4cz+OPfan`mLuB0cYJ&%Kg(NF^+Bk#vd=ZjR~3lS5?~ zFdpTCYXx|oZp|LxSPqfp{qpu5?=0F+p|2P_Hr>zHlh%+EyJ}sGVxnXkQ3&aTKa(GF zOHYH(jAj+lEzl<1fg_@(RRzVznb0XQC%J{_NV5fO*sWpudsnoK?ta_>PMgSKhHu|t&DF6zLI^x~in!-UwQxoY zAnXI$ID~8YC_%??E#H&#O}4J%MEL=q%7bJ=7K4ns6l&cdZ*LGY1_-3(2pEZj%&Q9Kuva(t#xLFw=psF!DKQR$JW6pL@Q z(iP_1REalZ<0kA&0y1G=W)0zr@8%M(`~~I`IVq9Jzve`C9u|S+biSF3pwI}|m!Aeh zYLORPdm)7@yA&;nIx%)AsNNSERblFpJePE-Bbc;`We_Wm62Wj8`cDY1*ss;^Rf0=5BP%Sq5nyj^vkM$Ee65|Fb&$;XVvxbRdWh_v_a(}DvI@d1_)p3b2X z@%q8?)YHmh#vxMwZB+0HI91vHDSy*9>_jw{;W!ToCZ)pIF3II=kfLRE*r36*!!vo) za+E_~sPAEv2wyczsd#O^o>qw8J5^W1YM zDB*j9ZbZNV{R6-2@$2?2lBVQi7b2Vs0w6hHB7otX001~16hV;)U?>56btZtssbaA{ z2!N{<0>Fyj3;ipkhU!*F0Cj(`N&v7}2>^>z0_aHqWhMaB*(Cy4`7oUh0SE3j-J``R znx61>0(;?WJw{$uLOQ5T#L%@2~OvV4z(;>=-5IBP% zak)q>Lz$Jak{ip!j%|sH3~xm?a1>ZD0eJ|>n0ZLuekvl7qKa4$$K7_CkKt&K)@SBi zt#1+#V=DEB!YOVIKiuqUK7L94}K`GizZ+)d-iTOo7zfUOnhpoi!dTEH8Ucp zIx`}!=8P!$BNvS5Tm&43-*|}=LAW?u5+_15AE*DuCBliiTJ@QwT94pt(Ei=UiKyVh zoCupKYr}92IT6E0l18iYmEc4$DLGN7Fqspv$3Tou5x)t_m=r3-e%$z6}L?*i$ zgfe`Pij(g)I8kYjvvVi-GuI%&>kZ5s>4x_HwQ; zl87WuMfJxb2)I5Gn0BUpB;`^<5I#bq=hAU=+S2+Ct~!ImQSQy$V6cgV&}Zs$#1uyh z{XpAew`EU$ajre~EfGHKFuukUY!N6_*fxvW(9EK?T-V;i*QQ(@K5I$gkj)UlKQ)Jd zHSPgW6Z;6%=Ox>BwL0rs>6@TUI+lHpU12Nlb8~W8w)X zh#Ce^-j%!YC&kToYRoQAFxH}#M3b9MIdxy5CIkdM9RF-DB4&cN+G7z@h>Cz#SuuZ% z4qya97f?78z#Fy1x+Cb%L(tsP`q~|*QhE9lHQdCD|G)JAi=bAe83TtQQ0H6cBeM;< z^v0KYd>9jo5S>*IHI*wDlW!Y;da|*Q2P;jNo<soJdji7KPW;Z zpET~LATCF|nHCjDr>~T(xHn0j9ClrO8v6k<#Vf=QTeqSj96QgbKBkA+lnvf!n@rwa6Svam`)bL__z#47))D9$AkeESO3{E%Y92QIij51)sTm>vX z2`ng{#)T`4t5sOwNQrOhRul&omLY&8mB9;^%it-cJ1O;E=KdKLbh(l}bIz9&CxeD7 zcKi{AH};(zVcdyXDo|n3pLgVE4?MH{92YyJQA{1NrUWE#GxbW8;#+Ve&|_#TMf=pi z9J_aWP|NLRs}Lx-IClXBbr%F#1`29p8X(TIJV1Jt5TwmOY5(wjyTEd!D|KXEN~uML zO!33UqbDyg=$#HMk~z-wZPZ;}7=YnW18e~fb(XTDMdq%|`j@j}BFEUmOtePmU&BuSD!YN{#6kbc zco$Cp(7#G3aH#&3*KAV1lm0~rNT*>DY8bAlz=x!N;TP-PvQVu4h!PWnWB31?~HRIGBgg(*#k~-iU=}AY-nU? z&(GPAIW4oDjSAl(wU{hJYYLLgjK9P(VaY6Rq3_+v4Z` zyHI_5#ENjeeg}C-W@heCFLB9g-LP~#BNcH}l89~c^HS6ye8^bdvR!}Zh}s6hA1F8e zxWkfd4A|k<^BR%NUsrkBk8|1E-(%MK;7IkIv}bNy-T;aeDA@hpdI)2i9=Az_k1;Sl zvnH`k!T$GB|J9Lhr4C0OhN^JCnx|{>v2Yql&b-RfeF;Af!s#Q$=_i6;|?#YQt2Z!zmq1`+R^6(mU5rFtzn>Ckbw3!-Loo(r^1c ze_-P#w!U2Wuhd*vb3x58!3WbJ-G!ro0JI$n&i7_dj8E7A=Q%^{D~Vt*l!@So()lbwfi*mDxHQ-_NzOUZ=@;*r~tV& z0MOIWWBDiHS?E9IlzxDrDsUKEG?_+`>>ck!hU94o>KwnON_ekPnVgPaftQ0_W&1hN`Sn~+ewX3-m9i8Jdq#EG`v9Esy4iXUJD(48kbXcoGmc&o& zb2;LN^ydl*vjIEFPA1X)7@J2#1FBb1^ziRu@*agzxNEBMPgI=*%uz-O9FidsGSo47 zq?)NFb-8%x6-vAGMYXANTAs-dNM3WMZElJk3PkGS-$uE^o(Uh>k>WNJy!4HU4TgS& zvd3BawO{FlUD%e7URm|PieCGsN0cMIWz>I{YzxZsz#zkI$BQ>w{dFc7~u>KFJ2`~pz2*uWdAp=%K_ritK=gj)+U(RT%Ic0#JbIPco44@gng=qNrftMo>9(XzQIC*~sc`(6AQog0$ zx8m#xWCYqLu*5+{H)+~pZ}Q&SqlFs*k6u7mIc+7OY{_@-*JQ2m5h8Pu^*G`|y%+{a z2bbdOjIlj-AYB*%tM-?ESp?KR6yvG|##Qb88RLQw=~KqImC7ZDgXY6H5C3B`7cBGf zn(to_|4kzSGoIsrf8HA?i+A(h?81K!vk~_pgkgL(*}o4VvI-H%l0ht}KwwG;?i&EM zqsecR;>yEIxGBarb{iv^qNFS@O%X&JQxp?4`4~+{;i@bA?#z6b6(bc2z>=``aS%#0 zzlP63NkRpKg@OjXcAGG1@d@&Pk;0O*Dy81kyRJI2LmYr4R82mk+*gaL5ALEL%V!db zjX9|^#T>gC_#C?nu^XzTnnn@|3StOTs45Qw)VuIN0-qC|G7}f3wBTmcsMuMepsc-p zkjVLLyFdmVb8_gV9#zO0qS7?|dZ<*`>NM@f=zy1p_`5vG{**RWK z805v&yF-Q0Q^^geBy=*5m~Ev5GngRZ!slN+!ifJ?=@-ubt@!&uq* zEu7E&2k;q2KSGN8*IJtw)oPf?u9lh9@!kEo7 z6+C(T{|JdhJ}_+* z_=#87RBUKQmjOy|DYG{N`U zP>%WXhGH98If9L-Y;zTi1vp)eLUDKRekbXr{i{oKKfb*izD zw1S)i7h59oZfB;=wTP^2Kl9$M3!$C_kH(rNOP2EJqhtc}d zXXgr2;FV7=5JXMwPBAaXJN0XK9)T%u-MjNee_r+4SHq)nnaK;78-T)C+wz{7=Dj!U z6u=Gbstod->b)OZ;za>yUw4?DSiHAnHS8rcI3A?7!O=Q zG_K1P7$WkbeJ~+`t4}^M4c9+RmesnrdyGAQpU`b_v{`S~F$@%v1rO0@e#fk`N8>bf z@N)|Cwx0%Px4jv(Klj-V7ZEGf3GXM*2Eud!v)HXBzq`&!VO8se@zE$a&?YC@>UDY# zP@KD*faeGhQm;oJ-^+RMGJ$Mdt z&~IPs(w8r&Qp@oUEaqrUFksVVD&;CsDZ99$dH?h#-wJvYlSCiK&9=J_fydF}I)`$S zP5`GPzzvi*y`VeET*U>U39}tT4k1yMwc_)xwd^3q}@MH*SrzhT8 z?)p=c_t&=NGMptJdB;jgAi_hI0xe13lIxCs9lzY(9TkpFx00VR9c=3`XxazoI32n` zd=Y+6W~qGimg3Eybp#nN?Hvjlit%U`&GwaBx(+ZABQ^s&fOvhYji+ zR?ztki0A|93P8&nY+{j=q4``ThVq31|SVs9?!hWZD8XtqQBJDILxO_z5E z=?Onar%&<+{Zf8wMhmv=2S5*U#fIOLDs*vmLNPc}49=QzdUaDx4>LMlSYt-#nF?-P z3&gmd+dvj{#ZihE0A%e{?9wH-PZ8PU(#87rb8u%EM*>N}Jpx<1DySPX2K8|)AKu(~ z*7t_us`C0+@fr@>WbMrjNB7^vd3EZYW&6b+`LjPl2sE3aOjd1m4+q$_pB%pAVaE`; z&sg?nn8>$r3;x~9&rkmzo%-(f#+!RxBy^aXB~jKtrK zb|T=Jjlw{XFb#&M=)>R;v#1&-L&3U9cj0=+b0%{`eGld~Y43-upk#Z?4@`uKH^hNm zSz#H3vY(X6chyPE9;t4m5J}NsCJ-LV#;u1~kqN)xShlE>RNfyZZk0?`85*q^}Tr$i$9X0r66UEjHCr)ZzlKC^x1Q0nE^-e9Ex>jjzn0FB;s{BwCfXr~LHkNzG@_B^*F`jP znG=1axr`9k=~wdu9b?^r*Rv8<)P5QwOj=sLn>?GR6C}}-U348cPj)CZKmYDs-T9YK zZvVG;6#?D~7$Uu{M0$Owpv)SID>w}N?(tfEA8+!O_fAO&Wr8YrT$FJ6@2WwAlkCI6u7nEsrwO4<~uWbc$N}XVBhhX z0WZUZp5P{D4BRneHz=sw9(xHIt;u9~9WSQ)Ymh*c7}^IJ3pH-#>!qI~*sH%7vzvak z7G7CBvt+|i{w1nHIlSMN_Pdw>LbGt8)AIoX@VbUP9kpvHPOq|2`T4vDaKb%$z?KS2 zendB@pG`0U2V%P&e1^V zHvpFn3$O}gOSquTDqX5VGrZvGbLyZ1B*BCv%BGEG$Kc9KfpIM z^QI5H=~A|uZoyc#a=H5_KiFsOV++ig95)%zm|`3%hpyz_vA`()oW`u0W7K{yin+hT zQ!PWA3#^($6|BlYjUhAV0_yx(oC7Kk|9q?>`h_Dg=*|NkXWn7ed}3*6KCfccya!;_ z9zFPb!K%wU+!3n|bvI(w72Sa*Zs`-G#syw30bBRM4i>}D`S6wt# z?QR=C=Mq*yv4Kd+q4xIgVm6^*SPR@HLj16lebz@Vxj0Igm0RPH{!FJ5u#9y;+1B(@ zF%zxC$lEmi>NMZpRbu{ca}DhqGYemp%1=v(}ZWJjaYh0o2j-pa(!%+~kCAf_@TI@@1~ExCO<}m#$!~cG)CS&v%J!eo>_h!22p?!85`3Dwhj^- z*}z8*^LK9>ONePU@wuer7IG>K2$tW$AW*5}M`g#4@Js;A;A8r0z`M!u;6&hufp39{ zGzJoGbL$6Wj4kkw*nYsIymAC((@E-6O6k9ur#;N<^7l7w(+q5+e)pSQxEU zZ-C2(C_KH2`|2Khe+bAeTC-2HD^MkQl-K&>c+G?#!#RF%mGOhCj2~QO{NO6^18yzT z%-r+}3Ga%K(Ob<`!gI?l>J9>v7T7lEyG3(}seUh+e4XPRO*f!jPXooN9!TnepdFoT z80nkkw1fB=I1#O;wY zLmglo3PfDNfEgysIn#2%MP=Qy&D$lRq(PTSgD#ge=yIV!D-$+%Uink~SL{6ct1o-u z#TL^G;lX5^4>6sbN(LfJML?%7NSI3>Yj*>f8&5MHrsNi4d3Y5mKL#9iLxuro?1mc( zSdc$55uzK-o6Eos@bk!f@DIdX_Sz4|nS z^c2mf>A%%}onK8b199Zvn;9c01e>2zkMx8lTY|hdjP^ zTxB30(|qz!djMui%XM3{`zHUT9{XJ%EOwx$5_`ZFu^tK zbGWWvQPeKF#z?+8Jil~)|EOpt%~O;M6Qv*Ch~}~ovZHi`koAkpa5}2(aCL2QMYu(L z*5D@@i@(Qsu=R+Juz7<&omlGmEl`51;#lAJ)x*wz;9` zr|)lh!tV!s5BnRX?{9s=@Aswe$Lagqp748)fAbsxe3p7GiFU=)r%RDASKUx2z;`BN ztdr@8%y(Ko{opVWS0 zc&h#U2Y6F+^Mmi@&CmZKdyRVB{rC^yi~QpsdRuYp#(-@i@NRJh`gdg$6{bqJ)!*j! zNlirtg|5bMHJbw2s?+X)INT%b5!gaF?CYQByyFyLZU#zIYbYh(mo?TZG5Ya~l!3>(9WK$A6RV!MGE9uq80m=j{9m*w2L2(6AquvG!j3T3V&d zU6{w)%~#E?EuQbv78v7pIAjd72q^bb{Ykg$}l;;Fy}rS|2S zScW#VEGAz7+Axecv?19J+83Jg_JQRUYwuhdn7o-3S6reUu#od*nGyCu4ghV>^5&-r zZb0H6z&=A3zbpnXRLp)R2e@hleivOgR9E+&Md9~C)wW}qVUsp@L zTnnXvW)XG$oPmR2HMki)M5TTPJcy;+Zz{g{UP7P)kO`u!52uJrJLLKZT#u?^*2FWz zZ6<$|0$$m%c_!iBi((!Ag)zlPi|1vOW5aAbe|9|Q&()>U3~}=9mygd?%R3!lEyNX9Cz=9y!Chi2D9mTZ zQm{KiEEbpyc#g5Rr`d-+!VW`39UnpKelW!BL74eHYrIlwHu1O}2NTE!-UtIvJ9sn) z7b##nm#jWi_alQ_207sn#ak75sED>`i>d4#r9tGOTljo+pb>n*j@d2AnAgr>>L-#m zKc`cCyH3O|C1SqO*&PFLVg%hVf$36la<2GEPyAYE?%XAqQ?-o7FG`6Wm=c$_$z+pA z2F~Za6OeOHL(ZRj?jm=n5{l0V^5D^91*s<+e%%8P zo;!R0t7dha^F#CT5$LqnN4@x{{_o7r)b#$jKd0IuIvWu1R0~9}Y+^ov%th`NF;1jY zjoE33xi>&#cqTvIq6QmB)!6f+c%199A!@dv$eA#HRq3Sjfc2m=f(=c?TO6g-7hf_L zqf-Xv0LD}78I491Or)tEq%Y_@<2lV=vZwlp+U^mu?wN^!O-w34Y{*B#qYv8IR-)+f z_)X;^N6&o$2GA_ffD@6TcdTg|12!Pei}RsVt3bPa&1`sGK{YH*EKSLE1?HxaeuOrr zYmQJqi@&jeG2{_Y{W|YM%8;S>9ve7y2eV-B^^N!LND?)0h-cYZ{uAp52&LL9=xQa@ zDrpxRNxKkKfSe|vWi~l+O(a1e7>QD(Yq{!%E53XJU!o7}A@gU%n8AAhd(T~BJ^MRH z>@jceH$rJ7QW6L$z72OFWgkZzLSx8C!ZTQ(O2r?yNN8vl=_dp|qnL*~I$59w6Y5Gu zbd&&uX;lTT6fm_+FZ&+ec`{iy5&}HD(|_#?P*#J_jb@I{SL@S>0WoqlwnNfK$ckPq z&EKn7IUT+(#&z$`qkr?)U-%UGrA>fv;5h$(UGEf2Gbo^Y{{XY9f}I) z-u|MPUJ?*D4#dW{{25KrQ0UHNIwa7eq7zhLc;T!D?Ohk>O)EW=HKa!nS%de#+1_6l ztZ2sMtfk2rJ30H)7^p^lsKI`8d7_DB0vHg0t85H=_85BhLd-UDM$@Jd^As^iG?Mm1+;D7peD(} zIbk4@70N!TbSqZ1Kk}5{O}uIUR!-2hw^DgbN*y<;;P}Rqi<2sU1($9lQsI zm9Tt?1%=YodoG|GeX~qUrKr3Ij=|L31*_D2XXw(7KlZxgSSKN)i{MyLIF&KdDn>fE zh>==kX{64lI->LKP(5#cG^R67DFluTgiXL=<&6@(xSMp0{0ZKopq3=-eAvrcMSx6Y zL}F082>OZdTxZ27#6IER6v-m&w)<&+5N`JY)34e9Ro>?8FV?6$$(cPhc- zkRL^GO_)6C5x3O6UTzucfYp&bAfQO})sM#DrLA~sM;dam8ar%iR|6zyzk z`co8-_HP~&$ZeU_kZ`BeA&<*qwfLvoK==GC@!Xdv@;5UqUC9iegF_w(u&6~G=&mZe@o zC02DJ@{Y|=U|3_~4hNT82#WSQ5`gOGa)&ac%qZG_MqUP!Nd$MQ#!u%NzMm4t(3a0E zp{|BdB1?yoO4nqy@yVtSpIKgpvGLI|^kOs$!WFb&il>!>nC{7`_J4g=`(F?vKGkL; zrh>Kg_Uvz>Tt!UdH5F^Xs`t{9A;9J2_iNUN(!a(~Hi%(!e_6+WMf$1hDw&VlM9Mju z3&megz77@?A5m|f z@qa(|D2h&v?tWFF^L0Y^VFwIyu0}7rjw7J#?9k2*b7$GaL})jwN{V$IUlbw92vo|- zKFuSL0u2&hiqQYg3N*=QXK$fX%%K+e{O~Sp8HgK$J+OuE9xGn8)0u|lebe=fHsBA^ zzj{bbagIULQEle{dDA#2eo0X;{DiI{rpp|D;eYOTZqQ5aZ zITHVH0>6s73Y^Gr>Orzfo54zDzSSRTXwD3ex1mVrfksfRO&&4H$%P;tD{J#fW*h(+ zz|Vv$O@DEZ7XuOjupleA+51X$j~-IPx&CvFfhJ_lv!muugf^&wo?|g=}FEOlWM;=A~j7;oE2RIcf!NHDG1>r+6QZ(Ee*vP4Z zA4pk*nvysHI0|m_*jiiGCfqwugcW5_x)qf}QVt0P7m-y2KiH$RpcAFpb zrayjsW`-vC6_OaE!ls*(*p?)=`L`mmI7o(lDyOD#$a}LPiESkkOBl2?8JY7sNpn6L z$Tx)n(L~8-<#F8g6g@+q2ZB2<*gXE zw9FxK=;JGhJ(9PMUenZbNnHD+MiQfnPSrQkR!E$bt}DxG$}=f|hi%{CtpzW2-$q2w zMpK=`vMVHSwb89poT-OILq)s$6zdm+iXqn4`9Pm%iYOhlE@522qXjl`MD%m{01IN2 z2EsF3?QAQJqj)OD%{L35*$n^c4TUV3A73RO8bvlavm5qH-@s5Ty6cKjXw?D-?XVq9 zKE`a*&gEgRwEum3uPv<~IyLz^ZG&A6rHY+QtMnvr$(Mkb=W3pQv**&$)q$$1+;@!| zpF0ym2cMLx(Zx>4Y=|_oB@+$(>#vD}I(w!$y<1l#u{+6H`E_`~A531oV zQ0Yj-(w~Eh_W>%NGON2mwH~O6gauNrW3x7{{{?ry96{PvxxE0M@|`(H3#vz8CX zNdFev9xEm_QXEkOyVxxgE~ucNuX3?S`p|3)ygRuN5XZNl)OJ*|B%?@+&35My4{MAF z4U7P}rwQ6{JFG`OClLR8i5>#+m=1cR_MQ-ags=FBFOohwh7UYq$$R!fBL z^ArhB`B-NC*|J-$1MNBTG#E$Kj`ZPF{}cwEc*u4bKX|kqdW9%@jAIiHO^%~t(ESQ3 z3g))0KfP9L+62x6={=l#Fgfa{R(eisu{ZE|#7^7HYmuE*;G23N9}oeIS_Uzzko;a5 zw)wTeXd-1f`W~G2CU}}22{;^n%j7ZiNILUS(icBc4>^bg2yKm zF^OGkytOrw8o~Q*bn@qMjR!qlf8RA%&Pk^up$q?J;tHbk8spl3O|@B-1)@}1!_i_d zaho_PMH}aBVL_?IqnGHOh&veN?x${pLOF7LK+hl6OjRS$*SEsWkn5w#*c6Gt;y(|f zPf^59p&IFH9(9gKd1_)AZ)27{cA3@BSa3>MNxt;EH&`J5T-R$BxHzs z3phLZ3&`L`9$tT{h0rITt$~HDMYkY+`;t4st{9{UsYUc1*=rij)$Z{PtZxl)wO@Ev z`>CO(q30%Yf|-qdujvTrO0$*^kM~{LB)=9t_pQ%jlRPo+Vf4A$%#1tPHwB>CIzGAu zQ?-FX65X_q{J5cmdCRNW@U(j*;egadzk#Ou3dAAA(_{e0Dvo64Ty^T5Z7~DQR>$v5 zbH|6A7aafxo-FB3K!g16fA_fQ1>CWbpBi{iVxB}9;T;R_|hdBN= zHe6uQh*Urj6uvOvdtjET~q+orPxXOPx(-+>NO&rk{IG0b4YU*%6m z2t+cNcuT;!Ob-X0S>efM&3Y zS*nDa9%K9L;Q|Ql6Jncf|7L^L_NU$cTg*7uN>ePRf=l?s{$!~d*a(6yWF3iJ&`Qz_ zH=7G+q5dh#Xb=Idu0p}dY_k~%5U#gpn_O(_3*IMRbn({`eJUwWr}G`tXP97g#oiMx zi#9;8u`)ku-sZTacoChvY4-AaSQJviM41ULt^ zL_rYBEygz6^!Wkc)2cUsXa|(%n+_;rbiiSDpyPvE)FDgy#6Xs`$@a4~rPEgX&<7}U zgm$+gfi5wunD}_BwxR-G`SB5xc3jR7f1fDSCFli9q%%FoZ|gn6ec@J{sNd5oxkfv@ z%InJwXe*|T5X!2#!9YjXzg4Gk-SIcaApZjTYcd z`)~vBY7;g<6?zxuP$jI7bKJMZlWto#JMZud>_Ta@ti<0qOKX4dF~}A;!ARU|#}7LI zlv*slhZolaMopg?DV&B4X%duOvZH>*SC(MrPR|Y?j){$wZbFq{LCl2YyumDc+01Qs zEIzY+P)*cceTHAQ6Xp%gY9CQ#3vr%z5cVC^-Bx(vu84F8A{u1E^q~o)O|PWO62zfC zlWo^d?~``-g+qn6%pjQf6dtkNwAp~&nVX#*(FVpsYDkafps@0UvtW{;^~*c>f0UTx zhRo403Caa9He%(854g>&3-licUyPW z9YIcOz|hn*LvAs&twaFqAF|tn&>IuhA>So{szJ5Eqo25O zB>}8U08xTvWQa}zfN!daW^8ufDQ^gkdKtQ*UMBbRCjuDE34k1EjBQ?oVRi&S$V3nT ziOr-%LOJXT;S+X+15zBFD+K#90az3b$d5RhT>_v0ku*umOL&wCz!wkzVBr4^_Ud6O z2{UePn&K3b2GFOVnNWL!0`>*gW2I*zK!%xT#w4vgGwO+u99@A(0pq3Nl>?Jcsa~K$ z1cj{o8RQboBgqDEgcj``Uj#xS?hh2@uK%Q&pbpx=sQ^8R8Jc@V5j7pfP}* zlV3FS2_e7%(~_qJu*y#bd$AV2K~0JH-2pz_$W(y{?WG=@h(m(mKJ}Pdqg@ofu6mlB zuqOW`)%9a6;-b?oKI+kdILU<+;2|8}x=-OKb+MFln4kB55ZE-J6ekciu1otatxH3B z(60*<@qHwr!MhvttxT6}FR&f81&>+v`C z>-9qW?@RWo)>68YPaWGx#K}a|bdq)_(41JjHrO;=@6+I$g zAD0#c?%q(wIw$b)oWM6A@QseZ_j5TX@LqE;2t3YeK?J3)pdm@Nu>W9`u)gg~;1(so zC=qztnw1DV7+q+m{Y>DLMMn|FC&7m~sjn}S`uc8CM`uo%kF)?mQ%nN4{~ZBy`8jOx z^A&o}08d0smH|dW+VuGFG}6u!X0ArrGbV!OC2sU$;Fi8QYDw;q><%#Y17h}v*{z=4 z8I=!=MADM`y^TtPC)P5OE{sZ_Wur18Dw;!KPa;`k8Y{g9j0Vz57IaO-7=rO8qRMe> zFw|)up#rC2WH6;z0Ynfn-sE|v@5z`Ese%w)0C2oIDl`#vVc=fK#)DuR^B6y-IwrSA z^Y^9|f^&kodc@d$2v=PvAL3<*{=x2D-HZL*aRq9CPd#{P(1JVqOIO^32nel`2+&hp z(qMr_8-P3AR}r{Cr0`?)OBB8c8u~_fx)K(9CkTO{%n-X{hoS8pZMdz8Hqa0xG`yR( zfd|Ak@Q2w3ceK%d`LQjk^;4R$;!%=Y2r%CTDqo`0l+aB@v(53`P(^&#AObQ6?u^cX zyoXa;%^j>`@PNejIKoahb#`nNh>-;Z7{cR0zyWLu2xE6(@k$~&J)H$U`T&K2Lc*2x zxMgzGtW3BH!sta+NI(i)LYIgu=QVdgr#?Z1E7}wtlf=RUFo&Dk5#R!0FN-La%f!Ut zc&lh})KVGU!2>k@2e@JbPIHeZvxqyW9m^;2cslX*+|?;vlAa);Og;Xq+JKP9`3E&? zV@C_&vpqkGN{8g`@Tmwm3+%^t44YV#C&bFxI=>q5iE7dmGCsT6xk(k1lt7M(pzv`= z2)ry2?^uzHg0*@IFs6}Hw!78j2!eKGpje%K=(W?SiOV#zWw|w<8?JPM)cG%5=`(P6 z8#HGwWt^&nesgBJA0*IB*q|wN64g$9L!k~ki|B!9yz-B@3J*|Rp_P$~5(P5q8e=*| z-P!#E_a})-Gf_BdL{mFjWyXw3%%Bo~+{F%Ntce+jhib!O7TsC#uQ1o3=5dI~wJ6U1sRuvayRH62hPV5+JbFY#o%NvL`m z@jQYmM0)Re9Q+I1-7a5Z0PraeimU~&vH)vKc5a0hAlHU(N0Hz>7(;AoWxDXL%*Z(G zgkT~y`+`e?AG~0BCg~|_&OfB7vcmizYvdS7;D_F#nZj7slLa4^i(E^La1iklr!+Z0 z9fT9V7=#uUZ{WZTF9xwTA4GpXh=r{ZgJAu-vsJ=h!XWm^>>UKsArHc@=7ZShATY@1 zgJ4GKWN0mn$QQ8@%50eQubXxwBeeFMbC;SBISV6q2GaR_Wrm%2Q4!bTAmTiirnxuc zKsY&GI*v=+A2ES)1H10pg87CLP{YWy*QSxcN5YRl1cdEmJ}<^)$SZH{_tCgm0?R?pd4o z(+?JtFV;Yp-h&EBCaUFxA2w9@sB#IRu0xqgm}JB?3v{BO>vXs%ar3O~48;;vm@1;i zZ>$$v*_KXz5(S`j6%Gc)_^7Teog}E2(wny)VyfD6ABoJnv;IY#S!Gfmpb8_C-c9P` zB6A3Q`a}J|-7T_c9x`XxOek-#zr`+Dw#9`~4bWqX_|SRUnlbMu$u8{U;P;0n-xe=; ztmFz(w1}EuVPbH0z&0>QYjLcTZ)3L7@c7w1JaZO3(GK7~!z-yW@uiDBl8aHwo#+%U zsu-Ig5fRd$dP-k^>ya=c!CEX$#uB~kO@07GOM`j+&jCZ`X!0Xqi#YNx`5ph+^1N0j znj-K#*zx2aGl2z%yz;{~55S8;PtBS^ZtVl~upKmqfU-p-1+f}K0|d~j+4~jo8CHq{ z0%I^g0!n6bT9~70uR?sK0h4MC1ds##;~=b=*b-C-+rUBxM6HX=(X(>$e?WJqc<9FT zX^aJ7rJlw-V{XJ@_UX_AdO=P7bJlX&%7cozqqInY_@Z+uVE_i;8ttszIx7=4;nz^N z?GhRkhxFOvZMjG1AS?i@khnZ*>a|zh12Ao!)_OJuPWdD?Q;g}QuEltz7)29Hp5_te)LXe)>K&`8TDx0BLGEq#q+!L5I&90F&V8x!xi74RXfH+SShZ5PK+1~ca8RO`I3#fK z(Yh@eR($GWrnWLGg5!7W8+1ynzlJ9^Wf%+*Ev;~!Vf2>3w@#1ifGI)*TZ3V7F^bRw zSepg~+PYMuy@Lq|s8p%YPSbi=($p!X<~5iWZ4p$~V@H#Q0!la99Se%4u7LlANDJYf zEGyy|q(*6i2p$v;25a@mKW7Gd@ez|1ND`JL5J_*TSEYR2xNSt6aAGx5u^p@xb0s3F zd(WW+W8pJ~Q!&50|HYiw_A%H@!ZMVasD@v_9RcF%1G?g4_LaP5rh-5EX-ur$ z;w90*j(|7a0Cfqb(S&Z0?O-H{BtSJyVfSOGQ|37yR#YqWBE&nMu`|i0@-uY#I`t@O z!8Z_xV)OPn8%)53Ivp*?|0WnG&KB@o^s>_E{_IM%01^5 z{f+_MBrtAf+I$-@q#Xfx6BwerVZ$hvU#g8IzkzGsX=ZTIRirDcQQk3Acn9R8PRKf* zMuX0w&b-tb;>7P0u;;tSW1hRdiTv!g3z`J(bdSM1#nC-Aa3Rr6F+t)n#i1pLzTy0+ z^AdT&pyiqiYeqBt+to~Ga?OcEMHG<}n8#1*I~~oB>3F$T3n*&BbJ8&i82VIYo87utK z_#f31Fc-3i5g4STRpyS9suxAvFVJOh#|2B60%ccPhv1vFxqq4^5!EDxcYr1iCq%2a24}l*Is&ST)43p^e6a*5LR0}1n%S-nz<%a# za0{%$%7|FW#OM+1pj8KJ(qz!PV5E5DLC)Bn&w`E64tJFa)Pu*6k@rM(qD7GN{|H!m z5+AzXl*B2s!L+P+>nc~Qj<8t8B1v!RR$myulMp&NYrUZrK+zsc+CaHX*=+!sU({P5 z58C5_7~th21cUkEL`qh<7-KM$y3@Tk3?95FdbD)WDSd?)~3{)5!2{p zaXP#~t`d?AbG;Im_y}JFcCB44ZW+I=T=GJuVb^!lysRd%z4)PG89kDV3&VaGS>n#Y z$DDBb#l)aTh^_b($iNCmgi#L=_&xbJxd{J+&KgtAY8`! zYS0P!sWh`tV_|g?SnYdU{6SE&@WwJf#SG05=>l;>KSeYA7Kl9vst7WJra%?7l4%h? zQkV%`kVmbjFJh}5PCHce58J*=xWE|dp$q(MtJJW2cuIV`E4;xQVq;XG&5~oAV*!$j zjef-1`4m=1AMNH4JVs(zwW5j2f>80(J?e@ipGk?-2)WR;ZTP4Dh#nqBkf=CXT-C(@ zMkpYdpTi!42GSb0M#7Xb)*lW4*h;&`E>|E&vnGv3mCa zRG+$pvW;&(<_)ef4} zl`0!@E%Pph#zT|3GR2J1_L!$db5t{i7vR-Fy6cFQodqF-A-SK+zz_xV=z+xE^!UU5 zjvk+y=(%DDUGaJsI zCWh>$tD0(}Ub%ScNr(YfKP6DOjm)ux{S%s4+3Ygri%Rn@%qMO|K`?#?Ms6-aC~CgUC3ZU_pozx-;wL9iDh8OVe*3v zN?9QOOdZ;UzKS zW||>_HO_{fmS#rh5Q2o%HQ%}LifDU;_Ljg_|F?pZist2i#3aYd$s;Cb1>$2OxeRS*!ne_z2ERy)lk%gp+BPTu2+jli6I6dNYg=w`!%w3&&B zZ(WPv?%)ALay#^lk&}#(5B_H20oN8)ORxjr4MhE`Aks{tgz7EfGD16Uf9xVk5+$}& zax<4ql}nEoZgYL5h|=EBRAAoj*EKoKqUQdU=6Ez9A`FAv7SY>ZC6~97nw9p@*~W?xFh;=pnsg7Xg1T zS?FZgX~*sB6Lm67)um37>C|1oz$mtnM<@}HQ%So$(R0wLFgrd2evH~PxM?e(+T`D( zw*7R$N~fP*-A>3RNmkSGT5JeH-W}sXeNA;tz}F2%(qS4sLEvoQD}RvWf;-`B3{got|Qee~J_JPE$ zQMu#ohZ8S1V92t+owznGcyC31C5|A74&rPAc@HZw*$D zLJ@VmJ2jZB@u&kFM_?+B>o!XZnQ;5F@3i283dn#rd8JNStOd30x0Blpn^k$Fa-jzT z@S~P{23WFSfjI166Vk|-x5I@gYQP+|8iT_vdoyCEZ1AtO@QTUUSfdOpci+RrN|vYR zo-mt209jBLj36`)Lia|*Xu5}u>4lAkLu4FVZm2=;5o8k<&Z6oa{bsra!*|qGhVTl9 zix5xq(XeVO*Q4#+>BZgvzP9mU3PcdZGgSS_1E9C2UqMHHG_frfPkBr|DZg8cA?kFX z*+37Dqr@>;RGP3y-VyWHX;2xR7)pl&Psc2jAragwLpt{!^iAmMaXHeFJ?Oom4D=3f zVOK1FIG|_2lz1w=Gv6m?^&uG*2mdtnGE;)1ap-o(ltSNNRA~?&2Pcu9J@hDIvseJV z6A6=SD?~pkS^LR%@TA?ET&Zc` zcY3qWZu+8>s@hLIP31Q(UwL)XgL(QxS9s~Pwg2-qUNU9n!xAl_&Jo?wVuak*RPDPt zn(8FKh>&OVqX;osLVaC*j34|wC*@>Zp|5)YdptX#2no}taXNV}JSj@_^5+=OId4ipmFh`ph_(zsy&>x zgA_b8C=mr!c2~B)wJ4}f2vukkqAi%9Gn57}bq|}cjF%`+$tKJNx^FMSCWH*LO=t|j zvQ3D+74?Qq7!@-wsxO{<;=DC9vuYFa8k14l39!{fq6c>T8E${>u1qvR)F>#-Sx5yHb%~39)l}|#T)0DgL3`xzug^H214Sc z?DI0B4HI(`q`2JRw0J|b$7X0{Ub$+<4>1lx0)zbygcLCD-E>GN=y39r;YDS8Xq5BM zLA-np%}eb!i2oo`_D$tWW+=-!5Db;0vbNLh!8=%P60h9D#g85cwlCs<(Dz={;HXlP zKb)~j2o4EC=5-~rak(adk*#{+0^wwx*76N^MrbuQBx8c>d7voL+K;0Ro8e@Xw91d6 zdP8v#oSJ_@HXkT5%!kqbKE5CYC>G8^U7u+X@e{s|NRK!p?@?XI68S)7A(B+dF6BJN zygPFHIt_!v&Ex7GfHH3rnEk$Hfvw zMpQP(5>etM%x^asd%eJt4!~|E!7G@sBzXk!$XHpPM@9U^9zdNky0ZP%(AX#t{0dzHHth+n97g`+0Ep*F$L4~9yk(6pKVF(=UF-e#)y zSAQd#3Hcq_z(vZ`Ol<-ZYcQ&;$kaX4ORWI`uyD>Z8>dEu@Ol;E zn#?bfEA!hhRFv;)i>(`qXE8k-5=IZ6g;1Eh55G(u-WiI1`n(SL~C&!*By{xRHr^*0|zAd>BOnE#`zV zi=|U+j+(wI1fbDKP$J2Lt-Z;Qx?XNgm=k^0nxOy`6-r^~k{}K2b$Ow?MG2x6j57u+ z?Epf!t#WfFOi);SoodJ$PpU|=5?hMY6&y>-OnO8owbu<=@yAWk(SFWx$5u7evfwRb zBXwDTI_lH~lRiXSV09Xs$&i2z?R z(_uq$W^@TlspC;cjF5W(;^O0cjC{bX(Sg{(ftd(8$IPc)$n*k*BntBpszXyd*G>%G zrcY*NV8UaM%K$882ktr?Ad)qZi;}l^KEma(=De-}E!m=_$mzpYQ{4JwE;NM(irX_v zw;qn%D$Nm*Zk6^SG8-?B>O;TV6CRHz%RJiaW({0zha@$si_)0n{*F6Ht|I=UC7eVf zxW7}TyI_@(mT_CrvzRgy#@XIKHKc0yzsR!In#qNQmjS)42fbbrC_VHJy!G~DenrK2`Bg*}4pe#* zb8MzSpG{(5k>V_NS&{+Gkz~(su8OfoF@2;p>65x)cJ-#WzMt`>EOJPLL=Lib^SA-9D)z0##L?^Q|*m#I00 zhFf`HbmU{hqk7sbX_dL{3}jfHonMZve0BT2#q5~TZtvLvi9x-#VvY3^U>ID1BsLPr znw(&tmNhdP(KwQ9P)p*GO$dkxRFz0Xl3J2x9BmI8;bH9y@4pP&i}ai@mucZspd@XG zuGLKjiE@XC^e(PPOV{i98cH-oWr}o_@-jRby$W#+y-V%I?wX@i^cxQ%%9`pA)H7vv zFT~Bz`-q5X!wsaf(?O8)iPmX@LlpUsfB+~KbrxT6=5DAnL_EmB?dLo-g_~V%&yLA` zW>p#vQ?557%L%n#Dz~uE@0^`;HWgwfv3;3wc*S9OwifcD-X$-%KMiwU78}tC$xsNT zy-bWzaJp0m(+*+5=6PpX{=<(Ui{xjHG@najcpNDK8Za4=Cy*I}x`@$npdo$%WrkV(jKg9ad&-QQfDf5Lw^w8a;d-gECy*Jz z+(Ih0YmpZdl0hs+{1;(&td6DlBp8l&+>XCo=AelRq!Jy>oSMUK6c!**C;4t z(^fTUr{2BAhv9G zge^jQ1^?w~?+u=wPLTy%a#C9SR`kLskH}Hwrlu zbm%?9Hk?KvJgiXNua=yN0+pPhV}I5OFpsuxOzj zR6lrOL&6t-P%0qfe48vQX7K;w?%iW1Kd<|~-(_ardEa?2v&*Hl<+9eym^H|jv=vvD z2$qfaw-6~(qHLwrA8H|>`a?j1UD@!iXhLu$k_si3cHKruil%LVKy?+b8jG@0D~XfX z3GLeTr5D(+4LcV{@+~!z)KMB2QDa-~=X1{U`^{zFT`nc6HM)!4nfYCw%X!Y_`<&-I z=h3M^fcVvAOY5B`)CKzKKS}6kziN7g+#6{Mx39&RT%<*ei<*kycw((Itymz%xKWIC zBQ0w$8*eM zSk-ka+9GPB;2=pnB}HH&;m6nz#K9)4P(M*(1|CYA+o;p&ELee-gtU>xawx>z|C%@| z%t1S~Jz~9RLovqs1c4iljmQSN@$zynCt%aH+$^fpNmX}DMj2S3xkyI|3MS({C^=>Y zsZ{Aj_yRGX1kTkwMYiV30cJ#0BvF8I%?^q8Nzzz3p3a;YL;Rj>MeXXPxSg=3m=_0V z0!;usQk2crUe%cOJ?7N^7%?CtJTqy!SAKrMpD`PAVUdI>uGxf{lw&aGBW4{`60GMt z8{EPWI>U(6P#F2Z8tZa>P}lFC`MhDRa=IH1qUIWN$cnARYl9} zt}b5qztTIp(adPygtD8Pwl8Uhu_^690(BDhF4-i>KX=MTuUSEieV=@1(`_8#6wL^Z z=`j1zR(D*Oi>Qn2TSR)x%_I>POYSe2DO5=3-aHC*9k`@8LM29*w~CRUOEDo7NT$W0 z*D1!>>JtMq=Qs8?T&g-?QjsSK40w<5<~G1uuf^NU zy#h+gDbe2?&40y)ev14Kkv{_m0IZ!o6iUUED7}?h3%jbnQ)f|zZ^yC@zqTAZG-(9a z&01nH`O?mQXn#8hu4HnF_&^p&Mk$|RgTouCYG#mdL*mwrcrm;|X&AhWW`$;>hKC?P z`oj-H33&mxhiP|UI$e__5Q^0lT*ps;n<^Gl9Q#0!3Z9bh#<2~BH(eH>UIsOsOQ=BZ znm5UWLv*LOm!Ie=sx~7D><+r{z4Gw!{ah%kOyAXht<1$4|5v` z8FdL94iC`cKuV0dFTBnLl0!;y+ui)X8#zI};qoVFL6rALc04?`%z^$RHXbab>z+Df zaPEegS~-bhpv6l)C!zJYPTR@-vSP5^52d4gg$g4uiSJGk5Q!M8DLP z6cMhg>119*mCG}eZPq(Gvi6#9WZK(1=Ca+4Bh-$=NX%hl#LHi4bnO))sw zTQ>sbsU@RaWcaCOy6b9s!GZ)oSY~RGJ>#@JLn#?jk8mF zoxT&a%Z~1e5vC8RdrZC+2M%DJEsG)KbAw}uef=|Ih#5>nMjbQ^6F^P~cjR&5+|7#kda955Ll>av`s}c`}t;n zmyl-aQHca8$^4$gYzi^i*68h$Mh_zORBS?nt7H)c8aZ*R6yJPZ*_rgzv^}&_E5V0E zRU@*q1s32%3CSmfY>F)OgcMVeoymAJDCImP`2`sSPWE+0<@l*x$2V*p&pF&qHKqGQ zNHq$bSQLi(xPQDnZS>ew# zEs@zYHn*4!lkJd;=OYa!!@AfDH=M(cG}+`#-+~@|g0W*vph$Sdc_QbR6iYkZ>50}w z{9NT)?Z>u?{oLHP53@Uh__G8Qip5);i}J9ykT3iqs~Ou*@R_Qda_)jiF`D$)Yo}zS ziR&Z_zmCa0z8;xX)a2m0RC8#5owFqHST@bY=HgseGLw?V0c!-aU@*2XF>Q4kO5#A0-XI=b%#u+kx`*IS=eBYD zl;b#>{|+I?HWH*pRddWEGD-Q7A7v7tfO#2TLgOPOJ{F-VzFKl*GNWT3Y7{`iD`}(% z!vQ=R0Wy&WE-s!!L{R#_!+^5ZCHJEA?|fZiFFiMkgoJJ4rSI$c3rE0-zQ~ z&*TGU@ajW8`LVdhc*h;#Zixqdo5JPIE5l6|96$ejh~WX#T|9+f_ziK;L3j8*zl!S* zbQ9~TrUR&&RcNrMRvce#+*L?0+gV(uRdCHzghj#@NdA3yw{SGa`|zf#h7`CzQp1O z`e~C`hl_oWWZERwA&W~p#0qP~qS+>~sA+>(w6~NZxm>C{ZtIryq@bkX<#=3ze6R+u zO1`65yXt>@2!fx( z`DHdgieZTR=o#ew`Y2B|>;~P*oHG>A0(qN%KP$oC$djmqEDlA?Uc&SlsFa<-^E1rK zqWU%(K|^Ohxe62?xW5o5_OU>)j! z$uXJk{G680z4AGEYv!wCZ471M8jcPFx~aQqYONyWH*!(90y$TKSDY8 zkY~Q3^ZnQf(nE7+klwU}a>njDVmMj#;bE0{yd9yOC{L$+#$tUtyxwGRmdCdZQEQ`I zWe?-6lRZK?W71Q#7o$l3V~zawLODml^>E4UhH_FB&9)A!8A3VHSbZpGdBP(@%46$L z&dJR}Ipa{DR~E_{uZ&f!i*a}ebwZ0%VA+jO&bKl;?FE)Tn&d6H3Iq=m@jIOFTzQ!o zP6;ZF91%^6av8rPD9~P>XL);!*%|6!GYUKnSAZ$K?|<-0)AI@}cmuB>?AyH32iQdk z=#d+Er3p@PK?13vA7Q`-Ucp-D)I0#_5YXvN4rOIwWvpzcjlChDQySw7M>4&8V?Zai zn}zDFxWDKYtAy)l=6bRB=!NJ%jYOT^PCzFsPLV6h((=_!h8{!%imgQ>nmBTiD~F2O z(33y{)ZOlwl|WAS7i|V|PBM^l(g$+Jxi%4DDJ)Bsk*?86`dXWebvreq#q38mGj@b_ ze~o<+{Q|xC7FmgC8}80TEVP`hpqK*kHvnzz2%e%Zg5&q_kD3Ia0ezL!rzL@bIfF4O zv`^EONp*SE9%HeXmcf>pA)(DZ6WG#Dq??LRSuuifn8AG8NIx;e=5NV}6tP4vsoVkVqWaHA2I^GT+N8ef~q z(Udc^7S1VM$tbbI$RV;A^)C*A4H$ci5F!QT9*saXN1kOO9C@e$_yJ7po1?x;-4RPl zk9np9*ZpSoA_=jZXUeS(_yW4sh0Yp@CQ2WZ2e@$zjo%toEUyz)>JN*}+x!=Cgt(@VMaZnCL^pxd!w+GP)Gsk>Ou8GH^e_!vU`=e4YcR9F*q-VxG+DB8zKWz#cYhnp2B7_M_p_h)vp-WQ z$6u(0WYQ6M$$ix5llTjqXL)wQ&-fg4hB|{)x)&e&75Jh6l}fai3o- zHaQKl2hbAY;*L??_=fJv`O>s|@3--&TxPfO3~k1$E;H*s@d|!28W&S5mbX?!tE4v3 zx4R<5D~2u}a&_26D@Lz8f~^Y_leTBSOwCy5LZ69bI43!By1_QgX3z$~bRmGwJr)7qpz;n=?xWFt!u=7^kq6 zd*i6^*V405MH%b4C2D8X{W!_FHDQlABj8HY&B*vft)(fQ(n3>+%xU|Ucr9AOA>aR2 zEGk8S?xfTY|0K* zhPFTul66$4&}Q9|S3sM#&}O4Ov)T8zr#O{!xql2u$1dueh|L+y0{*G7pG&!A=`3K} z{e_=}Z*RUiLkc;rQe2sc{)C6NcLE>>I02-IGyf@b(ewhC53S~Oxt!)smwU}cu88Bw z`L*wqm7HJZE?d=)tqx*(>(=Da6F8?j{J(04dU0?epG0YTfM$J#E6y#TD&w#?GzuW* z|A=nHrYuHsE@^&62@W0qm?+iFMgMvkr#fYG!fjK79d)#zHz~g!rmv5(*5hIk#-029 zq?V0PK2%?Gw5cxganf-R6+dT)K~yRo;(-RT$iL$NMYA6o-)I%_LuWt}ff*fcbsAWA z&rWstAl~?9g_(7#&4>;D2LZ~lG;DTQ&0aE{=iy@3eU3i-T*2$S6X;XX#~{U4xXPZ> z5G)0g*bDQ2l*od?%Gt>LHyvCZkFh596Z*5dKlsDA=qI(%>8{53K`$2>AWSq1eN*wn z*0P+S!ohn#21u9J$9}3(;+YEKtY3iaybyExP){mHowek)ZXq za+}s9oLQicz;I5oCfz@OP1nxBJRNapFMWDMSd0;9)r^_24e9=?>ll-2g<#;Y=)Uk_ zoiJ(Abp(>~ zu#RSQ$KLF(Y=ZS<)tLFS0B{|Ssjlmq5nuhsb>p`QjoPbf6ePUjCn2uqdXHO-${-GGyZnGTr zG9YD-DcCc(roZ;G<&k!YzRzaqQjfb zmWPaL&SsZ#Xf|H(Xg0&N-RyNa(QLUXu!5pF>JGYtu$OS(vud3R#QrS!#(<%3PjVpVH(pwKR99zH?b0FJ*nI8XA-}GKkwX($>s=LA4YWKceYK(S9oa zzg|ZMF!+zQRQ~7mbuA>R#^R<@(xzBv4iHUul^QrwTf;8W9P1O$hZd`&NI%rnKQ332M4p_FR&>$M3XqrKs)kE}c@{x*WLM;&Jc zM(GhrNJ@zit{6}>)A{+|7zxodIsRLlonYI_zEZgZ(K1O7n*#yE+C*PzfA*Dj^VCKM zP@VR*LM2#3Z(?rR)r^vMgEMW`#*9*HpkV*v^oGgGpyn7c?b>=NxLOTH7&3%1k+EoX zl-gV}1F|0PxQlv^R>ri^&=FOT1{52)NsdsEs&Xm9OeL*wuG1PySL|)N7b60uq5@mC z;FLAWrBgHl9QN4J#7R(5pz#bu+EzhQxtBS#Pi&ESK%>i5O^ajsa=a+C*x0Sq5G+V|WqKch!U7@+50r-zRnas0Q6 zdjJGj;{&VE4&8R>BnVm+ufmO8 z)y|zke_#s1bgYL#5E>>2MPrn@?x6p5?60H#7sWDD>wmE%Uz-;y-=oO7^EkmM#lzXU zS^tYcGEJPB1^EO{zVu7=We05J(FAzL`Uhjfj6=B^zvPLXdMm!j^RL%y6-#&n`V0tf z4bFv4!xO`u`+a6n!uFd@N;P`Zprk}?{aY%M5jKpbh`XW(grYa*uu4W(nHYhkIRp7p z7Lk8+S@jk)Zh9#dUy4wXnm~G6BFy$Wz-NIIquEF6VXH^#h1iQuM+nb6_*TG6)xGHo z|NR(DHh%k2&5XQrayx!|-23GUNF#>mT!EPx4NHcUjB9ma6}^PtwHZ%RPtG)DPFeOv5 z@?oOE_^5bR7u@_mL<)|tFDoR40vY%>;-b=*@x=oilESDK2wX}?+da4QF z%6`4WRYeix#AVFFW+S5M`p}~hxknBZ56*1nnH2;57-itfQAa{#)|21ZJe(I`Q7(`J zsAxdQ(TKocle)dw&_t6jF=YN5Ky0)%Zl&4cp${;Uy^^NYVf%X3%PfIX!swb^jvo() z(R~=ex1eR*gv0w=Va^_=>nJ%uN89}bBT>&kiJ|31$Y2z_CwVL7ivtM`DF zn$V>QKI&eh+mCK?J4T_Tsi&^@TAVF=9ozUF*MtMrrSTaeoYQ$#x~sa z&%ObY^ybYuw%Bzj4Xcjg^c!lgyKhE;*a`jt-IkgFOxp4+9F4Ti0>B4pRuQa2?B|MRXI~m%C7VeclWA~_?87z*C_WmaH)Yqmf3`+`*&ktvzI*)oHs-IqUAl_Q{ZJdL>uX>S$m{3N14$0|QZ| zEczVv+^KMRm5OJK2Np<+Ba2OS7ejSLc^Vi=Uk4Fl&BgA2`4^)vovnCD-=DwcZysG_ zaPZ!pLED_c5U-~4Ca%xE1b(UfolYX1{VbMYeqwoNdy&ySqIY*%o>SVR#o6u?pUflM zPUgohhR3|h&Dg6s)7-H`GB>4WndTlj%{_uJMO#=R-Qa~X!P7?PB(L!*O*~dXC6gw6k+t=m6~a?mb^c(mPizZrfnJb zObEMKJ#?UfA0~n$EHo|97m3->6UjdBNE0(Bq;3Y|%s-7DPKJ2>Ep{e+mJOHkE|iz@CB!5Bi9j!7*{fIg+T=>5|5ks`)-MGSCM zx=vS9#9|f-)v)vhdjnMzYKzl(Aw@&P_J@XIOEFE^Ubhs2c}ccVY-kFe>0@jky^15C zRa{D~_$L|~s^;NGv1L;NwuFm>;WmwW6&(`stMt86`L}A3=q$p*gXzp-xVEbwXd`YN(SY;~v)*hv$B&x^n!wwwyD(`N3gl zhjm;q*?}W4j*zwt8-T$HdQ7dG_vZd)*=pSVGXk@GN{yWN{$*Za5sf`P@!a~}-^qKJ zOuTEAH;riG#btYyH3A@*!BH4hmE>Ji@ZBJA%PO?3>^*{EM!#Gl4=Rh!0@V6xo`%o*p;q00ejokQ&J<*z8^- z5Z zVO1r*s8ZVEm(($>M4*4|nr~HUy(1vHgRpv|jJbrw^(|aWjh=0q=A_Z?+ACf0p>i^v_0#uIP*MoZ_Lb~mbj1IuSe$4zrkV|AoLV+<@t z#IrBstzYF8LAS50rcB!*BF&9)KSXIjreFykuA(;7fc>kwkNqbNV$&2_=^S0L3e?5U z@uP33APWBlnQD7jODne*Cy_{>4#|>bdRL3%v7lG>b80_TK@lHup7}Ww|9hh?*sb^# zA@^_)!HjxJ=<5&T(VF(Hr?X|UWz#|lKOhhAE!fAN#rR2I`8FKVS@a@5oC%EBrJ(Y;y|0gny!jqMC1CG31R86sxy8pX(`p>;yrLPK}ZV*JltJ)p7jFAv*CAW5%maH`q^(@t@35&%J11RxJT1xDio zs8kB-ro1zmb^Cni#$cJCeGuPK`+*Hd5G-#%m1_O)UT@z@7INB0YVO{(KI`^loxfx}NCIU{H12l z=r-38a8`b80sdR0@UDh9f&k{w>VxjL($an)h`@ZJZ=*q2{Cdw8-Fcj+k$Oj0S% zqmzCcuhPBFo@56-YsYM*w#`U>(}R6L$3ov}cLzys5?4V#M+!LfBn%U{1B4N1?1QV= z6KYcd%-rG`lvQ@ik&DvdJL_>WYArG7A8^p|6kZQU4z9%qsz=hvw&4)83*9%X*>NoD zQ>00Wefu^82ct#x5#D#4dFIe{uiGBt>LFg%)hs-yfHpq4+~2g7clFqo*F4UXjJ!@N&SU_;GvQ&n@O~cWup4kM!z=0prfIP0 zSG*sv@=!h!IgS!Jjx4btN9rv>d~uU~B{vP?qZHH~c9>Ab3^GpS=w)PEL2eAc6U8xR z@1zm#!h%rj&%?md&-w|BGyG<7AHLXoQ;VZjg-$5*L{O9N6W1w@Erpq{`+mLvVw*xH zBKYIT{Oi+ zxv*_m5zI%nB=T9B`haR$cZx4uXFRW2iHQd6$(OtHNGHi00Dys)DlW57S)qzF50zQ& zZqv-WgZjh=couk4h5ZUOiZTp;uRJwOgZxqa#=MTP2*pazx&CIz_pFXH49F1Q;%+1>>x`W$7iZh zO?IXAp9b5ruJG*3)zeP|Le4nxk`CRvVM22{iq=K;!<8Rk_rdgS6ppA%)@!>4t+3C2 zO8_EVW3)sdKZ#b3McPfP|HzRuT2>_Dom0I0OgFc@{AW}^r;paldih^lh_&|eM`D?P zDWFhF212m_l3lH`tKO*DVjQ}6m~`Foa-<%!niK=cgq7Yep-RnOzgXlGwe~ZY^=?8y zd=BAh)#}BY5*A_Z(AMI*s5TLm~G)~;nPfna8?1i5bj~T;%lFMOto{2BCaMu zZnI#YRvSDnlAQD)cOuBGdywl{3VO!S2Ls48##)dotK_`s!QeG_^?j-A>U#zKq;uhW zV44Lw-tL@zg#gJs2lB+b34M5k_3ESn7e0V+%Z_`Dgmbpu!DxPhTd9PoZb1t`U623;D2Z6a9x4S)@Isxk9*?LbYqFx z_bV)on;QL5ar$h=H*xXn87fRSrtDOw4-`iEXu5$7O3piJOXCLW;_jhA+a`sBl}1hv zVkO8GAl+q14N5vNZww!{PJb-W)tQh&1^@@hZ!Q$Zd}8xL%p+zt$l!W|Hl2Hb21ZKi zL04{pWj1d$x>JLpSGBIV+R5UMD~`h+am6(k%dHqmD00Z4@UWij$nSvYraMcKpdaDN z3#z+slow)8l>!|=fX55X@eW14%y6`kVcL;}vuGF`nq;B-F}65`HUBH?T~b1hZD^U- zz#7@cb1Ue|I1CHRBCj}GCDxRUxlgJts#uDqb5Mqant&Yqm z)naykC38%=57#*vuejj$R6nK$mT{AXzXd{}>ywhg1L|!MYCP<1SR}5;Z71aum*Dd% zu8s26V(LSrc!<}D;V#88os3%$@`zg@yvRN=NotyjPczlOzp7Vz*`%p;!h05Xl%>W~ z(WIJ&_f7ICE44|}p-FmMyzE_tAC+spE5pi5vF6D27EL5kqUTSQ-(xXpJQs1Kz;6 z@zf%E-Z#Y_l%~)vOGByBzx@?~F&KBFS)zK=dr*~66hf-N_ZU^CJ!}VxuopO|v?&Rd zQ#+oEhEsNqcf(NI7N)*_Z1PQcu<%Vh1qg_TB}-weWDq62a86zymkM&U2F@{}mP_uu z+u)o=fnXVtvdKi#;%;0W=e!OL#yze(tvd+rW8iEw1G=1`0$_yIh`=1|zE?bGizg#A zpTUVopmL3lhK0w2W?DJ#F!>~XS zU;gyB6)&O!go>dLg9;q?RqJw6H}>&2}nulK^8)|`9$xvuG#ZBiYker zhO~AvTtbS}#HP|3ZV^D1w^4qfWMGiD2hE}uhYivb^+8!Ul&m?g*;faPb@6bSvC64K zkM6=pi>>~me>VCH>9R36yqIm<+k@hGpfZkh%eGDNbBYY>D>Jr0rDo}SN=GO#E0+YL z`QLVYl8#t~zs(xlVxnh6zHb)C^B)1AS!+Rey#g2D*+iV_$)*PwG!%==qIi(T0h9C!N9va z55e&%YKZHLcrotuqNZ!nuE&r|FFTs@wrW*`R6P_|)1K_8Pto7)+P2DEG^v!_3j1EC)OkMVQB@G^;%7#G!8%e&48xhS;G}q74zba+6IvF=DIHqt_s?S^^z` z3Q-J{4!WO4rSt`?DFuZwXU2CC8X?stTO`ZX5KI6T ztS{Auo=!TUY8K|`M5%n}MU8U>_<*b!45m_!fMzPWwO0I>S=X2(>e#P8YB6EQ@b4G9!dBi(RzA z2FeIjMMWivB7a$EDvYc}oxuAz@L$59mpY z*_)Xoq;8e*pnYd>Cy=YvOv*`5}fB zKn!2GMakvWd;}#P6$;4F3AUEP!(xyG*`=>2dog|~IlJ6LT|_hTW;A2$fu4*&T;FIO zLmD-B8$r(IMMaP$-;X*>@zPvmWa1HYr%&dcY~v_S3@z6arbOFOAQsbR{Q+NaOhi3# zJ?qETT7O;-`$MSR_f2ltG1Jh9&A)UBA2FxFR5jA-p z)j$)BpAA7GHJre}Vo#}y{DTclVbjV8#e4_=C(MDTZBrQqJE6jzEMXB;i7*hkE-=u$ zd)%GI-9URGBDOC};Q?Mt^_7;2r!7C(NNucgT(QfTqLP$=e4hyATCfLHfj(YW2!nRC zU)usXJ>Q3`X>;f--!||t=qtLeQ8Kd7j-zdwLV-cd={nlkDPL(}PWcvEB-5@kzvO06 zP8$_hqGKU=_Bi?l9?M5vg``VKONn7S*elNNZy**5a>TzjR7>=<7e~hciU*!xu!Sqg zgS~IMrvp@AIIc)^2arapR=j(e(#tHiRkO9kBI#0$nS`cx&p4dW-WevX2CgqZic7Vy zPRfWLD9+>P>e*co6)yVYyc_FRe-cxSwwu2+n*FEePd4{!-1z-gexb-$f)_0PLepKp zkgIC9at)ChM51U!hy!qZHoQaOV2_xI-WAh(hjbM}pKxLN6vG-17w1P@kK4kx-aEuq z7{0s}dzau+YfV=Sa>5hN@r`g}#0i|HLCr@9)A4}ivrhIq`w>q? zlfaBalbjlPd%H;@elL5M6>>N)>dhu)v3iHRMUxC1iYCz-tgo$sdbkLC?@;fnvLq0d zAMsSQW;*z)bg&{J+_p8nuZpX-hRfcKwM4u_R?_>bY=zz-KcT;^!SfD@aFIF+(evUR znil_-ZJ=B6f!W8!linecW~FzCeX=lR)>jDWWF924;~gq(NTGz2d;}^xU1a|r5rCS5a(`iJ0jx&)hq#>#yY>&6oC<|R zXB;T~KS4r@gbA`&_R-%~pA$g9a6)Jo$KA2FgdVGRvQHuk&Y9pe<*xmKDyx_>U+uzgaWg26~}1)<7+zNANuhd{6jD4 zAEMSI&rSV9Wc2W42>x@yfx72ER{TR~VEsevz(5sP67)wSV0JhELyWx5 zjCHn35U^;M=s!jrtXup;lL8F9JLT?P+%5hg$VRcH6dvF;fdR&tw=_Z_BwVK&XNe{w zO8*c>+N$Hs57a_jcYy=|P#ij{ABHSyi0gxYC@b~-^beIGr+#`!XlizJ$3Nstw9HE5 zsrcBe&5jIZ4*nsZheD+;{6krJl!FD2h86!%))0?|f2cGIL=%MX{X3NYd2?8&IZ)arDJ9A1XW()+<{LlstFK$fL%I9iZFi0kY#D&R$S z{u|zt6)@1FKr2e1HN_y~r@YI-RuU*LgrTnu@z4VjH4;fH6I!vGkxIokb5jsY`<*N1 zjY4TY03%PW4we-yLl=Z~Z7%AaeUjC2^6FhJE(?>11zupv>bH_59GM8m1ze8fg8ne3 zw1FYaq4EP!xRv7q)suP#4Zt+Y;bNAmqGo2;`z?m*Mbc3xi!isW6UW7I@3`R0w&P;4 z4?aL(Fm;j;$4h!Hn02cO^<1!7Eu7FwxSk7W%+}H}N#|h5u6b-ZhiV~8XadKwI53K= z5s77I<|0OeQ{Pooq_Cp z*>+#tKq%(^@>n@-PbxTk8qY$SB*hXR5JjQHxEbRJh4o+Hka&`$O1LmozA!EPBtT!g zFoKEnm>1~5%}N+&a$yffzcLFUb1RUM~bdxH9`Gb0kG(1NK z+QO)x37W<9t_*LZF8#>sg`tWoBd({RoXtM|a;^-utMP|hz6=;FN-nHQyCiCuD&Qa$ zI0-~smFHxd(1zKNu$S19;Vmbafe+%TQfTkYCWG6%E%C9&Al8wCqGo=sI(#Aq^NEmnb zl*70?7M#Rb+rTV^2YAgJ`IZ*5@QUS!PIee^$mq@pd$6CKi)jwE$L-?I5VZtRs3EQ| z^n>*73@wrHjh&MNd`qg?cV1Du2dp5gP)~xwr~%xVmN=87#rC~0V?cQNfjn_D-oyU3 zaiw^05I#yTZ)y7j-@)mSCy5!HFI&+xkVxc@;!rd(0u9*}2viKw=;%_&1{y8UClCTx zTpSrc+ioS(T2zJ) zAI3-f7$3EP-f@v_SKi|!cRt#80!%W#8zh?a4$ z>_kivB@yI4zx?8*b5Fl>>+$X$!W|<*$jYDPkBQzHj>c*^11GE_R1s}KTKFNaS>b|f z$e`!eF~sNdmwRb=-V>L29(vi~`DQ&gE0vYa+bI=RD5ajmltz;cmD{IXHML=N7zisR z#Wq=b<7}k=x#`C;a)u~4MEyER<=cZ@L!Y7HMOI3?kAJRSCWkXTDJd7jx!*kvm%)$q zeU%=F(WPfTdTH;4k6iljpZ>@TAN%-A&(_a<*Y&P_iZR08w+b1A$aR748KfWoF>lL( z1gO(f-HLdk@uyNU^*2=Of45r&*pzbmDkvo@NyCA8U@wG5BF_?{n`BbertlljWCw*X z-_O8pb-+K;6BYXn59Xc`rYa=usJoB-_rTQd+4^z3c)v#2#s4wAEjQj-;=p9S)rlYH z1wc7i{V_|T1_o`ffu_pw0U)vMi0o!toSF>~$_Kd-cp%C+Tpjz|q13{m@h&9)(A+w! z)E(U(*({mEH}Q9IbUdo+x~XTp4p4b2vu1lFpM{+9>E_DuxF!K~)yz65PnLk4$KoM_ zJm*IS*)8TS|MH~4;=nzpD$^?uR47&V=j<&?h9R!o{s~n_#;n;Zv>WaY&nx*MpSm(dLPYpm3`L`BszWY#5Ix>as6O%;{1ka z(+DF{dg+f{HPuGFKtwOQcNtB==Kolh97pPmcTtx#4EGxulh!npf^}8Zs8;*UY9AXB zA7#&WYy{lwILO`;chV)1Wv2&G;?uY&HqX$20^#Z#U5l;TJvrD89s#rAq0l#rexKyF zq@cH(1&NlGJ2>J4^RnN~+4o|9-|C_l7}HrWHAPFZ+ZO148q&c! zsNHR2j;bIzhLJ7=$Q{GN#e_<(Wmq#!N7c;Wcy>HtvwhBG4tg5}WLav98_MEhl$8qv zbdBGo?%R6axh%6Aj!8iwGB$bM1=9o2*8a8m|1?@cFE^5(jU~@TJ^P*GGh3OSGV9Zg zxu3|CLn_$>ZTItm5xSQT48c8oOuKv7@8Ks~e_fCV1|7-(>OEmZYCXO|wG0~NJEwA` zUwRTVV=m~6cEen{Ou{vd+arELNXl8DN}im@A_`f1sYau@uUTP)^-A(XCr~MP{7u#L z()a#M{lQB=|M$N5n}<)YMr;UMj6Mn*IKg&CNt0IN7ncXLRzbtpvj454r}_Tjsh=(# zjpzS&lU{DWf3bNH(z4SA75_~YFq9Q^1j?@mm&VUu`aG<3^1=Lg?)i_*mPZtFbYlw` z2uX0<9X`ba2fGhkrzLw&z27F1KJDs@YfJbvCB_Ou_)}=G!trHo z>A^?o^fMpDq7J6?L(g4$w*T?WbF0xi3}*^@oPkFno%%1#?d7ZFeSv++F>?oXtR{vc zIYvGn`|9~ITE*`4NOTlqbY^ibMk#ff#=QOz)m*Cny)cFc+V;uwi-WCZyu(yPCyX!r zOA34qg39cU7+|#HS%x}1ZaKi*1h?N!!}(a)|D2KE*WL?!2zqkF2fc)oB~UTZ9KfL%lun0{;TsZ4uSY#Y7UK$@mzpsuYt-F=3OM;!zD^ z!ZU-I_&vph{k-*}RyHcUG+&;WoF*J7vCp-uAYIJ3AmJg6;lLQ^22JT86JAk!xB%gZ zm~FBuCTZQ#Nr-%edylyqT_0ZHp%*LY+j=6k^(f2;}!Jx`Jm0BKSRt5NF&s z50l^6B9e zhp$Lw1X=W1(k&Q&P#I^S&Ef=MldNl%!Q*R{aW<$adxpxGW06$suSjL6xlkHn5R?X! zg0V`&o}t3dTozJd^>aeA*}xP_5)e+`)QTI9;T&N2{5RS{r2sm(Y2hS%28xym%@Azk z9I&MBaL4SF$!10msfW%Z%+m*|IdBuh&jolArJ$}V+uLW~JHBO7edO%?Dy*w`<(c;{ zfv$1pM=J&kI5QP?!i^!B`yxQqe!~<8e8VbzQ;#AA5#%O!Cb}CJnvP*lqQ`1Mj&pj)K&q92^LJz4MAac@EH*OTN!n|>`!f(7(b^mN) zx+Pe+J8S9V?stDB&C_BW8O_vkE*;K)0T){cIJDM&dHH-M0BuMB3d-*?%6Lp7Cqmvn zJ3GEHPGo%rH3{w`Q4O;MJ$fiTC$D^fz{)VQHMVAkhjAn|l#Tt~Y37ESbR-aS`}ZHb zUaS~rJH>814Jo_2X{%>DDXwl08{Yre@c!NT{^z&e$M3+ibZYbc&HDe`@czG<@Bh`U z_qE6_0c^gXPD*_WI?s;a+Gisq6vfGDoR|(0)_y?bdHG9oMy_Qvkv7Q&BhmO;tqx=# zC$dDfq@+e6y;P>|<9+yaI{&HUU8g@zAkp-4BYSqtaK~3quJCvw*zp=TsNrP86~|$a ziS`=89^_cn7x3}c%4M@o9^q*OP$2Lh{?^Dpo|P0b-rQ4oNdLY`5s< zsF$`gOXvG9kh~ZhnCbO~+fy`Tc`(O#~fd+Y+3;HOj& z%p5~2q;`{HF&)ZQFmgF|ptW;+*L^1QF%0l%cQ5l6xSrILE#TlL?Pw$c=jI+~gZB7k z-|u=H>l(CjA&-Yr?M3TEk%tdd6&i_fTongpJMz)TyCHmzJRL40A2XB~d2w7Q3LLeL zd`9$?kq<2rg_MyW7q-(pczDpecvT&YHCpT7y-_t9vCkg4IflQnSx$B@@b%;Zr(y6L z=3qMiK*ge?-z2!okDb`icoFL<CTdA?y}+EnGo(NDa>%hIbJchRp*4u>TMU8tCpeIbKc1-02Vw}kFV~Cf?PS5 zsTf?6IR}qs3IaqH=d7ag;%!$U2qWvyZWU&_!hUaYk-x9EUCmai1}A9W zi61t*J4#~IeSLP~Z++utA8_Y$YYnIn046RERd+M)aKjAdg!SR=JE-t5cAlGJA*i>X z8_^L1wqEIYhTGq+x__WTnlcFtT!0#Ym2_>xMRH)ca+}lwT&m#4T`h2EXmmJ>4p&D} zKU;n_wSd!&%d0tWuLu?Kdd34uV zoQT+^4ayvwPz<-f3B?rCvc`+zKC6$EPNT^DFuDe%h`JMSq<%(4s37vvpsL43Nx&XZ zTNSgK=J;YnQ%g)kOR&m;u=7vR#IizA6Ba4nQ?3^|4-sW~cSA&ZmNqP!BBI#A5YdAo zq6gemMB@{&VD7jjqUPD{g@0ZoYB%?yAzAa^A1J)!)gqqmvhw2GE@a!QXglhlaF3i8kVF=SGWsnm1dFGmWG?t+Y z(KJy5{1an!9J~XMJNtp{F>j`AH`lKTMHCglI&X%oR7F-WhUlY|6;U@VqV*Nw8>n}2#F{H7I(5vk8ZG-gRHO@ zPM67S0g_rMKKYAvX0DA`zXd}a)79B0&b(s$F%J9@>vjcy7^SL|EerSnEZ+b=JUv(N z;XJ%(9hO~_l!EJ1)J_2(F!vgK@B<)?{gIStIMhz8$3=RmqISUK5-pr7p>}YB4{E0e zADc6*(@41iJ}R2cacp?uH!%ouqStt&aZb2I=D z_#HO16ALnq$+T#v$azaai9&#mq7a54QHW!KKn4mi>$``=3S|yM%?>Dpxk0G7+eabH zQwl!d+ginq2NW_YC?r3hfU`v2qh8&Sw!D1$W$A;T)m6M;h7S5(E|3fcxb9BbF3 zkb#S^8;L?%QOMAVL?KLH6NQYsL?L}2NV3GOL?La?rw0An-W-Jl^?DQnJ0%LiX(tM4 zcTtErfK^P3NrLS1H3S=>0hKU8Nc8}J`F&T@5)FcMyL{H85*Evfdf?Nwan-{a-d>%} z#mTvvmQYr1Y@m`e3(n#t7&ot`i!##r-dfW#Ia!?C5{$G17%^-9Ne@O8gK%u{$pRJa zzdQgF)oK6}2qr4=_kc?FwopkNDLfIC;7saG=42a{D5_Z69+e=}iAqB5Lu6gOT8nJB z$iEU)ax0MyRFb0jSP{XmSY**}qLM-eY~}_k8TdVgR#XtE%CkR1OZV+D%OoEa#ps@ zOvYWT9VXH(^lCsA+>n3k8)LTTDwABlx&~$*r@ z3Lb4zxFY~N_RRH+m2QN#H`rOqFyxHFOpfRccAh33%+$tE$rH|`bt7Q87{S1L=wo#E z0#0EF8571Xyzod=T9`22UN@LBEDTJeh0*4+W?3xusJ$3hcql+FBivh<81A*jj#qL6 zUUz;cn<}AM!xPA?l$1L@33gDz(tL?=Si1>?002 z78UpwoFE)|y~{@J?2EU*VuLsrB;uM)9XKFzW9&c>MDw0i>abT#DJDmUt669k7PmLO zBS|T}jI4w?hg$8+8M+~%)NJ64vKKMvH!I-_JKmAgDTQ{IJ}w$d)?ALEFYaH(U*b|M zL+yTTRBX-20Y`9oNrC=v%Qq*kgjVqE%5}v}FG$AG_Uz%)@wD# z6mr8_4d<`8R&%^j2nQlTy}?VOu)Wf?njU%}9le)ifkFa$#9B@B>Ozm0=a+F1_=J~a zqN#CtXk)F$W#&-cWv%9XuGO43jkEXC!!VAilH;iUPM2wTNlF#C-L}?hZnFx_TJLGz zs3M`qHW%T`-hdv`?H14@%;&Hk!wGjGdalQugn4jjGANYGGsG6l+r*4>0wL^yGbA;v z+BC&uUv0PrJ>Z zI!qbxc-c}V_6SJ7i8?rZROZxF!L~fV!L~eU>)OKmIQMAVc_ldPIME7$I^q-5fnR+K zb>P_;P{)mIyZ_Zg9fc5XWgd$J%x3-4HWKb zXl$awo~IIZ)II9RQU;b{1h!B|>};59p^ix5y+$2q%|~GDA zP#|n6f)Db*ZRan!L6BLH$1lC|wHo667Jw=SXvucN+$w)8GQ+_k3gg>3VM(IYHey8r zx9ykZ8t#G2<(Xh(?0IM;pe+L(&X6%o6O6zrv9TgZ{Go9VD4j!p1XSfSP80*W;lpxQ zpo(F2MnG~HWw9@TD*@d&xJ@F)+A-&b#VYZBya3ZCbR*}&6$5i*8vfgg710R>T0QA8 z2B(le!!8El$+-j}XVG+ftS49bNPrN!W$SAbz7h-;iBoMNe%SK}8ATxU$o}WKkBr>y z%3*))*SN+shRq8+@HI1X6hl1+PGFgS+;iyVO4%roMvc)Xq&eF|nppL0v8Sl!a{oq1 zvkpHgw!Va)@GHD2OiSpU!SU_mD~u68ICpe;C;#Tfn=H&rH61n)esbGYaE29CWcbNO6$xp!xu^;*!u&+|$xuTdelp30pGjHx>HA># z$!0w74W5>O+6eX;;LbSg65$|=px#mZG~E?&-a~2OcCk+HXuZg5saaye9H^I_EumQq za`A|64N1&UZ%{0TpS+x6k)2i;4L^!viP`R2v9!0XSac3?v}9T%v@+YpM@GNai(^-O zockXy4MSPGqE6EMo@l2~NfCvDz=a{Brc|Ko6-Y#sT867!iVU2kO2=YJ`|_ep^Dg5K|q}>*)*6(uTotl-{lLt5FeCJras( zd?FgOa|^<`ovwFB-YBM{uY#BsY+A^02U0XuP$dz3yA>zq>fh;timRP_>646T(IBIO zI#wqqiO0C41`;DiW6huHXJfHv)T6j81?-Z6TFf42xKRe*(H%}g?+EcoH{S_-qeCG= zP>3eM?hGL)L=*#+O9)EH3+ps8U5 z7-C%_tEq z7}e5)n~f^moL%j3ks+9|R5UiKW#~kL8~6H0Z0(KU##JZl4Y<85!>Uv(?74S&_EEVc#36*7=R3da&)C*o}f zp3eo?o6kyotp__fW$0a2>fll~zLhnJ0Xq?Iy90K17Rm;WK=tCJKptGHL=%JtpN910 zLfP%b+um+uOD;8>E;iaYIP8{@ElzHU9}xGhA`*jzZN+9C*|HglaqGyI4MY9PB3lah ziTK;^J9Bn3cI9T@7sE#P4n+CNd^ZEYDZZQI#T`4o8`qde>AQ)Dbpv9Kl^`6kDyee+ zMtBqcT!LwCwj7o4#@%b}crV!83%N9`ff_l z?$%n7q4&U>QzK!#m(U<5bN#M_gg4>4DOH$kJyyKJce4|&aPumhb@q`k8&#z5W}Axu zs0nYvck?olFtM&OEJqRY5L#IO%q*0!!C66}Tt@JW9GsIk`e#7(I4+p3rNtkL)z<;% zcoQ&Fr)L9Sj1q1jfZVYaH`gS{X`G?HoTfp2^_wL6z4cY-v{X)+tt{ttuRzn(F%cX< z&doFpfCx=P&v3ER38q7S^!}N>wST59{+YZqK$hN-n~-G~!aWrMQ8p@qw1DWRrD#Pl z4w1xCrW}%1&M!rn^{}j+Ger(J*4IJ~|L8`f73a(#CU{wf^|c)_xp_<){>O~!$!M`& z4E2VWg55VXP`G0X>YRQMl2fC424-dyW+2JIGZQ(zQcehcPwqaM6pY|x)a_5r2;B3$1f2t_3Q_~ zJd9%N1Do(=6Pxh!tBXx?FJG@QBCh3Cz$TF(Z5Nx+7g81&=WzHUC=1G3l#~3#WN6VYj{-#f$G|s&$<+zW7!pNmv z<^j=0LL9Dg+{Beq)%m4UEm}&h@a)9hY@Uvr{5ShoC$kMtkr`f}&djf0TeMmB6l&VqnO)}l%Q)Kz19V8e#-?DvHI7mBz0~o$_lJ`|Dqz#$QPUL zS4%GE{qBCZWDrA49&nhx`@Qe~o=;D{^jPBvw%zAR==b}0B|)sJ*irY})%*>V%8cp0 z_D{|KNA^yA2ao+~{iUv{?qU|Z_ekVqm~~&MGMuWuYQzF$a1KUW4*@;;Y5eKeFRNLf zxkwyXU89ZDEl|NBs4v_pwe_p!g+QzG1N06)(Ert3kFR>D&= z9-Sj}N%G~lGxVrVt}~~w14)`$7?)`h*~*NZa&4Za@yg|w;7MW?9;!?{+!8Od zB5T*Zu=e+1&^#1??OZVl@q_hro?=7AJ$&rbE}O#|%+Nx-Di2k>u{eCFI?KnIhpIdH zn6glh=w!3%dn#BEtrwP)x+&rd~3*BtAdR=T2}5 z+N$I?S@^AACWTYrnMGr833?)yN%Qk7PC*pCCv0L(idbvPKu|KV1}%;kB-SsqV3F^( zXrY&YtS8cfbF1|WrG2L>CDQya9cALPy89Y=z3zV0)JAq3`CKRy3f$U1c}Ns6+LogD zKtLQ!b5NdRxO0REP&Dw|G2#PF`M4hdMm$XI+q@&a&*ZvA-;Dpu%qn38|MhIf_uRGF z3IvZ`u9qwSO3&wVmB_nc`fn#fHeFgJAz;!pggdZ)p8L00cnI<^HG zal%Kwbw7jAKsaW9u%G11hMS)w3*7Hsd%63knF$Lvqku3L#?klRkL(2c6EjMF4Lyy3*!yXT&t!Ep#70K|DU5xEY_#NI$Vh4Kv6{gZ+PRKmSlBTYnJ43o*UYhEXl5+EJoi{Ne+(Cx>ZJXcaR(o z3Dbub;C|Z3qh2mwH+%Xryvi=N*gul+8FRSLPmZF3_(?fpj2^1KPIV;*!!Hk2{{|n# zO*<#^Cddy_YO6NmX|zm%9&=ITLQi{YC~8Tc0_HiBiW%m~FU4ZzGr_y1l~x zdyii5WeR?ZfvTE|T-$$~2O6ZxEI(5yp8ILBheQ;XREW=7#MBhzJRAEvILnv@dZe+p z{!ojl31yY=Eyyc%m`=_(=T>|RhjG4mpZ$J z?YPHo(RysHIdA`))(p(O925*3*mOmX?(G!dt<2qi6ds{KnVSy`)r*l6ppm(oWbURg zH-nFofVm0Dm(iQT+=PG>=4QNl=H5H?xB$3iF&&tDXhF;-s2lEp*=!D3T$v~CK6xGK zB>_0$5Kq1T>Iy*UVcy*{CLrCv53s<%$Jsj1Keu%VK>Lo-MaZr8IACB_2c-VDskeM3 z()s&JTTTmD0vmjbK|$(Pao{-jyS*z{y~>FOSGgyb!kYoFBx24C-dI($m+CfVB~Ryg zRJ-HRI3CSMRfdiSWA1p6m%eRa6~|*IFTIc;^3peshu?3Jm%cr9JRtUBG*EeHfgNpk zFJGS>Dw|EnTs8a8qC3ti>+YrM+t7rQCt;%2BR#6i_qEj}^K6c;y!iZct0qoiXuj+E zVswq8zMn~R7$&hjZmYUs$*H=po${dK1;Jmcc+hL0uKwDyb-8waeeERcT+3O*@ z=ee_@>$&YHLz+@w{da0t!zC!`Sz(;flc2t9D5lw;`<_x96W&u=L=-__rI_xk1&{mm!(oA2mv&i;Ng>SxK~c!o#9 za0cpXj0CZDD#ET?5O*>msR2+r3-qn(`>yzV09ijr`r{v~`h>_AxH15Je*oz(T!SS6 z-NB-;aTG)`-3hwd3D+X>>mnf6V72;zs-n^hN>~KRHQoFg75g{u!uq?FR-2V_n@U5| z@~SVD&cqE!IW#b5BD=-SNCizJtfqSOb{>EKg_#YEN#B#*;_9{8cQ^e(VaSA1@dz~g zLr*<|w$S;r;0r&07!_xb2x?bL)24l9hYkxDV+KVV_L)f4wi+7>(sDYz%D;_sIrNdt zzfikY#c`ZWh&hc@rHWd8{6egjB6E3O)#De)kWT`D{=H{B&rA#0a(33tpllk%MqhW2 zXIn5dLNB717Ljfh^7}M%q&L!Re#P;kJo8z9fFwRc5Se_NTOSxyZ_Q@kH$Lr{uVRgY zIMoVQ$!Dfi%;#s_XhhFzW-=Mmg0gmtF*Ett*Isp|9p{OPQH2m~p2)>}Y%ieQ|mqSCil$qZ= z>yWxpUcL2Kc6>utGUkSADCXl+Sl7K^ACF1Nz0IdMe<(wdP$Hq_9oa@M8_8wp_bbfd zU@kDQrvpCApXOVS$QkS%!a2W_urP4V;$+~f@xWJO_zIvoyb>%G9A(-8IV$`|CXI_U zKGc?*!f7p$aVA`NBTeL&P84C}C;fpyd;-GDQJJ;`DtK$g9wfTKB#E{{Iouo0C4@)3 z-Sd#Sw;{!6NQ;V+iNpIsQn>1-OL#U&^$9}wDUv!=e!fvXHv98;ABAS@kyD6pe}#Dj z2dW(2Q)#gJzb)V3SdO^HY1Ey+VnQVzTON7CTMIDEm5|=!$-%+iq#e_~N%z_(pfOzx zsQ8q$h?AlNf_d%3b$CG;hN&|1DQHtg1={emheC8K-PET!!ZBFtHS9ncdd zii=4$g+OBh9ga$?$=zIfG6~0&U0_!4$3_`8Lbnw?neM#GROuFXd3$Wo$KK`&IVO-r_FJ zV4;0ICZ!F#b=i{*+QWwY-W`cTN=E|vY_~NTM%F^{ms^FkHjB!eoY^IhVl8-b6@8s7 z=5(1o56e9q5rzF?i1I1vQOL5{P|BtV$}?z-8$)^1jq>PRu%amxqB0T}T3Lgb_);%L z1M@PUio8(4>;o5Xi$c7*LDk@F3TiL|zQsVZ`D~RdPk}#e2P_4WDD!n>v zp2l<$yve)^Buo4wC%5r5-Vg+AT?z`(%lK(4Lx0%Qp;!12>7%aF2k18r`x2Maob>l- z#Vn}B8*ywQ60xe@uAYc1S=7KVJ{}B3DpxEFHY>_R6?2+OUuI067}I=Upx!oH^{?L8 zoc_)Yg)*R%$Fp$j0|RLa0W~=+qM}3Q5sZJwjMlt*(1NcOCBhAAB%Hm_R_YYmP~4(6 zp4P+W=})5o%-)WHAjyx4Z1Z7+5nmdmoqA6|F-BAPJ|>d$-mW0POG*mD-kc7F1e-O{ zEUGCK*u3EY^mGVaJ6i=6*oV_o0S{7AAzPwGg6ZbJVT!s?%h0I=wZR0~^hfk!8Yc%Qk8(myOn!jF3zG^dqWZbCHiQN! z$FSfeDrUaY4@6XK->n!RTn_y90M%l>q%-`ZN(^?5+7 zT|-m!FhCqsLbE(bI5@+t4ESEP1-&~P3p|Z~S$`BCSMY(ZM$4L}Q{u|Y%|$TyfcZRI z=1WAlwpT^r*H+VVOIWOPYcY9@k~p%4+I5a{#qCOn#p)aEb3v4m|3v7ikd3$lRJ zve|T0Hi9)nt^&QLWV#gMu;8aS65cXs>KAag%z}%dkedDS$KCu z4Xr$e%R5@kd}mGLDrwC0tI&8TGiV&r4D*FyrH)NH14!w$Geoj;Zqu3VHJ8oU>Cm36 zhxVjz@9K=zvMqJNml)bx(|Ln9+GS~bR6zm{F$xw`=LcmGrPA7Lm<#~$f+_7qiBC zgG)hH9+eHLf=k`nH`kGl&WO)nXmfE%=f&pV@aWx*jWaTue&Gh@i&M(QGO%aUeL(jF zx+JeP7a0?LOgMCkf7D;PU(#FZub3K#@6=!6dKrGL{i@yzB{JM&?Pa4B!npch;}=$w z7gl>Otfnul_Fq^Xys(Q7@l(ac}EllNYC37u&qJzjbkx7Z0{Bj`QLyFX}L+q6tS#`vr!;Ya=wG+QWF{ z!t7)wEQ%$E&@kyA3`-5Q>Cjg1v!fo(8znA}kdUL8ZbStjuBdN zW&SlQ>Z`naPgpqI8JFQ3)*cp>_>+d1kW8hMPXm-(l4@vdSIu5(bo_@;a8X6Xj&qW| zkS*hP{N>DkPXYs5i?%1;<@prvv4&e6`H%efN~R zJU%qbLP{HU>r#i)lu}!AeHI8kN_8Ng8(Nj+yllPDGE2L$-q|Pjrb)rxB~yF!7fu-h zySjRNADq3>?{YjDk1JLdz;%Ix?Bp<`E7%iAxk1oYBJ+5Fah~WOM?aJja&5}-lA??e z-p?p%3RvokQZ-r>{4f-;^_cw>c%lRQ8tpl>i&0;X@W$<_6BM8K!}$%B46P9chVkTM zw?D3|M34B7+);KU@p^Dmbd_ng8eVt?UZ>OzyuMKf6=pMc>j=glNDE_@-XtyzLf8|e zV?bVo&E`Qi=n;6m^l!tXP##O_?vPE>gKDtZ!$1+TXHOKw(w-13eHy`B;K%$r@5yO~ zAITZQCEDI4^F~>=<|chB0!AgLc4?!Hx9AcA29r7lLQSmo9{&!Si|xe*PFoK*T>$&Y zM4*qo<)}bk)@lO!GD+|p(NXsuIFC)W2jN1>ekSAM0MP&n9wZ(mR7V7 zO5EFA)IA>G9$YozjHUyIUC4BM_@e74;R`euKt>#yerDD^SikVM>lZT4z0DguQ3$Q1 z0dG0p-rS4)9AEC>3DzFDXg~qi-q^f>?N?vFZVA~q;w4r2DGy5<+|dvE$!VGoFGlEc z28X4^d%I_5-yUmv-H-g`aBpiEG8A_H_eK$udT*oI;q8iub=6&)pz^)WyrrMUv%V%>76&aEbxw(cjYZ)Yir z)oe@+G~DCD`>u2kzmI!d;l#`g-sQ)Gg%Dp~$`xP5P)`#Io#W85LR3yR_MyWSn&nE@ zJY}IgPWdB(NEp@2n&9pQJmM}gkFHP^Lzpk|GXhcQJ~Munvfvd8ZdgMCzWri7taK)+ z&sh^|Eq;)`lj^>61*F2)4w|qJeZedd(<#?X$_xFo4bhL7^A+-T(Z4~YJRg{bdw??1 z6bG(iePdF%F4^@+i*;U`<<{8{&KjmWj19HGh#wR(5=J70Xj71qFNet|V>BC6v{Au=q?Gsc=Nfy0Sr;MIl z9zvN0ZW1ETtO}7g#F|PBIw$6bN>zBc79>N{om?&Ddqg$mI}}X3_=+>vs8}4~Zz4J; z6ksqprpCyeq7hjIly6ClKmW(E{#9r|SDc3-jSp3axpc4Gx!9!hmf69RYCy@NhT#Nh^>oG~t;D#Fw|A z392{P6`3qFfwMMf5*mu0EcW^#c$2Ig%W#lvlH&2j4Sf=`n&?&J4TB%3IqY(w5gmGL z^fcGoOALO{!ifs(94%oGyGe|Wxku_J`+8?tF{2>uIa~hF99YSElS1}O;Gmw~We|9X z-wq zZc@yqT4PcSpU;|9?`4r`_AkdrJAgkTI@1WQ^&Im2sY_>`U(_#N+JF8ds-61zkF54J za{HIQ_h;%MglS}K)##%uI#4}#>BE2eBQJdH<1am1Kb<)i-?iE!qKy6!T=ssgRrhn` zMgDIt7y|p^@pCLtjg&sjtC>!CeJU3XLz2b05LGv&s5Rh83=wUDn4!%J5e3u2ow` zH&~vPL|Hz3>M*<$GS(lVY78o3)X4D7O&LDI{b2au!wq&vU?A_<0p)M7dsEoG!$g%K z9c>M1Fg*ANGs=+ap$v|1yXq~o+3)Oa!k`kgk=))2gO<}lSI`d@E>N$mlh$~aq^EO4 z_!@@A->xGkoQC9qM!WI+=z;3>p*#z7V;PAb-Mi|_5AL}YDvx3!RZ@7J2=ZaVGkTPQ z_yiU3pFhUn=#wOvQu*HlLXba!7Kp5Eqbbl?3_ z)%}x^6A$>lyTgeG34y=PdB+-(c`N4~o?5h17ErFuARj*H23V;#*fby5Wi!k8tR#QZ zWoYpK!`{0GTY6mue&6HV_r2YxyRTZUzHRF}$DO1#v~X8NNR6!E{xq`GvKmm;n29pw z3H^tvQ1umwyOC6`jIi2Zh+u$`2gs-@PEZX7Da2-62}w~Ek`WUiB%uNW7|Z~%JYZs8 z!4or#F%-)0x7Pm7Ikz8rAe{14#%MAV({!r0As@% zr@%$iuP~q)lP8HUBV%EYB3SV4vmC0MuY19DBM#8)#o^nT&dBcZvvH?n`I=d zEWlXIL92uz6&*{L6EG$8%zI`w`f+q%U&nO6h^45U5KV-*MQ) z!od`Xm};5?!{6k6H{Lb_mhWNo}Una0EyIy|jWxtX%)4zxf$XBEwX_NnRb?*eF zKw|ehl^Cu4)&1rA z-fr_EF}a3qpf9_A$@YcnT(^~*3Hq1!=cWDUx_xZJw3EE>a(k}Z@5W39T0=1*h3fvy z#cmnt)W1ERdizEA7n6(gyj;1byYm;jb??7?b2f9cPptF(fDgnYm)~>o-YrWVm#&!& z-B@>E{EjWdIGqqf1z%FkkN?Oa*B2B*UU!isujW>ZxK=Lk*v7Q}8YCC;0Zof-IkWLy z2Zb7lyh!mvLE4VLZCbXP`U9J5O@te*-MKW_onfP|40dPO=qtrWUy1-!_TYw?=i^uo z{1K0jV*HxDAsS&1#LX3CnWiU6a|@=Ya{C0@i9w&Ay1|L*<9D48K)9VLc345;0tNCP zZsm;Y+{NL`a<>yty^V_}jh8V% zqJ-S4pH~g8*`3rmoP0nW&fcPnI=Q)P0a1}xap@n&`q^-0K8G%@px2C}M z)MRLwd+>-HTXC&WO|%~50`K?#n5)Slz{9W}D0>_> zuOnaC%OQcm2)Y#Ktb}t=9E;AG>)}g_9Mbgvq$U@iKos5ulPnS5kl*L2uKg4sUW6-H zgi#p99ImZ!tqNQrPe<1(A&6f`Q5DgIL3{}Ej$pkgFb$r4~* zF`W9U;W+Rsh6AYQ!$Drm`4+29zMT(efDA*yOB{yt*}DJZ`EVS`d@x(m0Zk%K-q=`> ztB$2$3D8_UmH_fKDJoF*B}!2+!5nx&Rac?$T2yrv8efU3u0UgK0~)9*(RjB@dUL*4 za|Iy;zbC;B@Y6b-=`6@V3H}B+vKqoAp*deaM}`m?cwzXg3lRd@|IZn85tLU8w_uh5 zlwW$nEoARZv<%>sEDJ=#Qa_=MCR0bvOAO~C=(#piD1%BFZq0N`p{?_h{cBMvA{Yvj z|Ig#Xn2o~<$FG$@VpKXoiNv0h<_tR1OcoW4Dr|XXl3ZKZRK7)J6H1%O=&7r+=cE(Ku8Hl)gX@MtVmFmsn=^D4Q(~Vo`9_~$}6C0eZrJ&;) zFKqnua>hXxJ)-xeFSNoWRZBWw+oQiY(d!hr}%83{e3`~)CTwIVTAJXBu; zdAJ-hNWKj`r(rDJazwaekwF_2!qNs5coN}XWz()n;{c~gOyHA}DpvMLbI;D8WacrO zL)aB+%|Ya}Q>6T!Sx`X|mh9`vYD=tZf*Xi=%X$GlX{hF++1;6cKI+g0;v)0()?eBq4|hqsr9|x1+%H6 ztSZlJ=pejzyCW(d3t?Axr>jM8-Dd2}ifU3Zn^$ezxm>T|iG&uBat1;NN=A|wRskQs zt|UzZWFeid#XjIVWa|IQ@;!9Eb%mFsUobI{w%GdE$8)HYnYDDyPA1;auczuL4- z0=u~$>l%kaZm8*UeLwR5Q)Y}iorhsul?@*+u?`Y6doly0_Gh$&$Nvb-Ed2azEP!JN zMfeEPjijE{%|mlsEP`tDpuqxIFPv5>Rw7?*STH<8CeBGb$4i9D5PA zv{ww#`QBJpKZ>rdo)4Vsd=Nuo4-{#va^l}D%_DcTU4ASH-d|Y|Mk^_T5Fm`Eh$VmE$RHv@7$F-h4B|5W zx}u2rhyAK-AVA`-ONeA9hW0L5V>Q>os;HMjHSvupuNq5Q5J(Y-wObPnCgy)GbW1ot zyR`~D-LeBDx?MpcSpNNrmGXsdW1$wA%lfcjrgzdNjQVd<6J;|BQSF)Ut9G38ef5qR zAPnNPOUL#Zy=TXS)m5Tl88pc?{Ng1j5+bM`zXKKRx8^;juCapxQ)tF{d=rM?h)i&f zcA#xSYtV_S;6$aWNekOK8N-gN#5-3e>(FqEj$3Vz`x;Tau>r72rJ8OEMB}_2wYF_) zGn=B=4{W76^PH?gL7NK{1ZNex*-ToB)nXV+b!G@GliSd2NkjXjA;vbNAsUeMxtQvV zV3cENhvjON$P+}JhDDQXm*)4XGnVutmBkMCJL`FO06n{7jut5g`$0RKKs@ie3eF3V;#_eg4ZuHEDVYb(?zh~_6RpcIWdV1wH@^c*(qbC zjO!7A2Xr4ZAc}3jJK;fb2=y$GLlZz*-Gzc6237)1v=SA!R%!J#tb$NTKoTe-u2CnQ zkzgPdqnMbNpkzIm@h7C+kZ&;^>q=}5k=?Pb#1_@&jJiUUDrqdzxkdd~h@*DY=CupNa(w<-yr+=}+l6zwOyQ9sm@(MdI z1UIQlf}6wv0SoMCzW@^0WfGQN2;AZwXB{FL94y-^5Gjl>3;#d^NLGb{`XL~&5LcG0 z*}nz34(2-Z2Dp-}&C_s*(&Ytq@Z1#Nvp1fR9a!HE$~AF{OIM2089St|w8GSa4i1ZB za}GNWxGUgOm4&!!PZ#i=UI5?kjpAT%I#+uK=o!@bk4Ky9G-eq-#fT)=e-Vub`l|LS z{}8|ch?9TU0Na{cHV3&4v6R$E2_;7x2Tv$Sm*tX>yHr`>f_2f}69?iRO=bjUP{(vt zamq69lXwb9_QxO>Q3WSmQ$4pqF8T^ZQO{)D$^ueR%PyY~gD|Bdc4%ftp@|$!>E~YKr#rlnY!lk|q#ji9|M6f@jyg?!ZcNU&6Pb#VANy8@hW4bBU zhQP;iS$dr5Dty#py6FI1Ls!j$1?dVi^Tl9R`pD{P4S$`FYSCFOsvtsJDj;hUX{MmV z4GxAXh!mI)tq>i=;rKs}jXzJm$8`gMwzRBu6=Qwv4mllf(k~xwi2;11GAM+B_M{m? z51!fxq<+%H%gABrf1R&ka{m)oy5d^IYSB(eT!B66|CDXIF4A$O>A&EfT_9u|C>XBL z1ixRZ9=LQ-%Lxb%5douC1Y#o`P`(oj!1TcV#JP5?{@E1gB{l=#2rSI@ZC37C3M$m* zyAr0qQegT+ze;_(Rvj6UliQnjvjV)<|3-CT{7+vA)(mB>zg!zLe_>CR@P!x;5uRUg z0hWIji7MmxT3 z{A;elL;1H`Z`k%J&Mmn#@t;bAzt2myerxrf*gsV|cyALd@`0M1T?X)UZR{3wfCp@|M#lq9 z=9x8k81*h=*SBD(b0N#gtZ(UnX1C2>vTk9h(3Xx%m^*O5^x?6coY(W zE{M&@Pq#H^ppDwD{iz?hWi?v%eOTsmHBIPphfCh!0jg9XO0C`lAquF1RzIJv)xd#a zVB!@BEC`aFnO!{)7*bFIqrr2+1v!!gh93rg*!~trIz1WLiKH+EqGtrQCV}zloWRy3 zu$8?8wpd!6skeY5_0f z3;DwMjf{_o5Y#WGEZ{Q>_#GeEy(Pr@yFutS2zD69@c;u~Zes_FI`5X|#Iy;T)~W?m zw^nEDbjICJ;#IvyLLcaEk-%|wu1(-jaeX}^pK?#H3J?^|0mjg|Yc7-udY)p9XBZTg z&hi2;(G_whNu0cMd5NW|AaSdhnT3CCUV@n*+F|ss+GKLgt2OD^Iow#nTnnF#8A&LM zOcabG%Zd;=o6kqRXs}I*U5&pmioB%Q&&hqSvaJo8LJOm(annB7?kT33OPQ!=5Do*l zwrC(TqLT7x{>v4WrQLn|s%8II$KT}!H^anQeQr1oV+O+nn?}O~$lkj{OXJ@oT;TvW zO;e<-b^8!n4|k3IA0IZ0By5iy0YOYu<#HuK+_> zLSGaN{r8(!W9YLL8+l==+6~35>IMTre-y1`=d6FW!$9yG2Sxj_I^DAy7u|pFjv{Jp z{4J1;dsg^!B+8QWFha&X0B#T#g_;h?r4bj(24SWeOA}yJEAM1}90QPC$LhzN?Vr*M zj1VUP)>=8?hlT0m7lyAFv5mb*PDhMD{z0r90j-WYhsJ((4EZL;gVmekL7mUXqxoUQ z2<;GhX2DyS_;$y8CcJmh;gG-J-coKMZMK!$mX^Zcwj>wd2nA~;ezdGTF&@xi=!E-&7b7t5gT%8O>K(B`RpvJhG!p)M~%c6PL#PfB{%n3JIl z9LA_O1<$j|&_V#%jKa*!2q_2G)*@C=7IQII#4sf3+bR^9U}At)FBjwY7SAk!Cj7?c zWXg75pZBPJG~WsD;X1F#d&Uuh)|-LW-On)NJt+2;7V2YMPWxnjP!xbg&z1}BWeDDb zL&PR@FYoaYheG&^)FwYp=fwry^Oo}nCxBsSoUpJ$1pua=EVBt^3@meMM&c*(8zAXs zAc2k-*of5>O9!g*y3v9C*W{3b)8(pyc#k z054N&fZN+_ZreqoM74o4Om?U?5Up+UQ~Mz2i#HNWVXs5zU~HT=Ia(!*$3qx^8b=Lm zN8y58xCi=v3#Mh-@tm~)&^HO>3SF(qjx?~$!w*H72dw-a|IDj==FXcT%gn?Ws!$w8y%1`!&_{zH(jM2g z((&PQ)6dG-$6e}AZNeo@4y#{q`yqvgKHEcKtZ;=|_EAHFbUc9O+@eWJyRae2E&aH4 z<0&B>{%0X|`dowfrwv{a^vqu!dL9DR@@lvCwfF>(p#;vF_+xAYwfka->2$)hA>nxG zp(*)au&-Y5G!_;p-KoSxel0^&`yU9Nud@RA%0>Kho*ta#vJ_20V%*!QJt|aP7*jduIljV*Ie2cI}XbIE^!&Gdn2Da4D6}I87?FDX%nQUE|3o#iE2Cmt3Yr%>tRo<&h6`< zW(=E^i&i51*;q_&_B0y-mJOit56bS;cuk`61ekmSXJug^!e$xT61BXPVP?EBNsGj& znl19+oN+;9jw?QLT)_@Z%K#;$^K?fOwEk|_RXw6DY5}^#HCHq2pO_7fBd;WHCSTTT?byaYluup#> zc4OIONCfgeBvH20`VpdnbfIj8Ddet=*!U@^ z3Hi->#pc}GD}u}BukJPEs@%RXS0=eF*frT=?F%GPL5mq<+8~P@LQHOEHsMiaNsO-X zP>%ZXDFIVJQa_M~av&f3KX=2ahjI)gs&S;mOqVr4kz$_9>?+TIV{k~Wstpzn{1G7_ zQ0wTr6}FNg7_H(n;=~Zg8sZCS$s^kX_W3gIHq~EzOP*taMv$$0rQmB5$RWU*R6P-Q z2*{;>ej%mVcD#V3WYFxQrW^kWp@#z97p4cI!4L?$`}mYGNa%17%~` zC6H;)CEqL_MWiUP*OBQEW;+`aDmsygAPd5k*|={c98pWx<+pfK10Rg;1n9wzkujl7 zgbFEetcP$H>)o~|4RfH11|tj-=j;nWrjF)QAIH&g+@S#D3fd5j({1_Yh`_H`G-iVG z%3w!FH%w4)Sohe%ay>i9n-lU=FcKuhePJ+2 zuC53nz7YL{u_kSpL3BB7`(OEykN-&hwOgD^V5KeE<`A{VriW;v?GACi$H%?j?d$pY zcm;`Ssm|WwSjT?z(eZ6Wem6+%)Hrcu zTfWCoB+jjl0s%-H=~+|HlOf{99L&NrfGo#3aZ4r?8sPLV27vx&jaV~ab-E%5NH4cl zjg85=bB~)S=3SG=9(T%U(1G_1nsWz~JkF32*8vCJR@YSrRyFNyWq5@=NhqMep#fS! z4y9KBxn9)c# zL^=&TEssmrA&a28GDYo*`4lnjq$T{I$4y`1-$psg1+>qmn5ZsFlNGSVDXNy?$E07t zS*A!3l^bz}3mO%MFC*f6Owp)gnD8m4Hk=eJ659TWI6P8oQ_+>{!3Q(MNG$stqepw4 zXwFVYJ6JkpST3viHCEWTdsl={V;uxfK6zEJ@+0)FhycE;{r5mtV=l)^+O|fhyQliE z>XyC%2H2&qB~Ev?=6%zz?snS<(s-61QIKn?+g30DK7~JbQ^--?-@0vTSxm*y$tq)X z@&P{3$;lo*fnt_aku6C85q|*{LAM-_;65hSQ%@I3 zG6?xXVKo&A-*O1lF%nJ(y;7w1GIA9vX)kc)-YpafWfXFvaW#$Zk{=p!5sWeZ1Tr!l zlSQ0jKNlg)XX(s7GC^12tU-@xC>o39Lm(HLD5?(Rz_ezktWLJBhAUePj8o>NE`3$%p5MVM|*DIHN9gme#9l(A#v3}{w-A?CRd z$IIeMDSrjD)t&(K!Ss0aF=Xse-64`U#0x0o&FLW+B&a5BGU>whlVXNIF?{8~ysj9W zQ;TcBK>{3pW4{9l?DHG+9K?2$KW0|uO%81%i48dHPkV0@#h*$yY+KH02Wp|uL+SEc z+jgTnB;c5r(26m|^6;YL+Gg^KQ4^|~FZo>JE~TSKa-S;OeWsiDbckbpKB&V@}fdaFe^ ziD)@aXN{4aMKZ;4A2FPkRmG0HZ@634BB&__%mjFw->eirE?kt!a7G9=PBD=ioSqVG z%VAwdq7Cw_XsRS?Uk)1tlezE;+7|Mf%d`bv8AQE0QyvJLIBfGaS(D4fCiVev6&Aw~ z_46%ZfW~7AoIoB`!sAIe*gIhn;|=*Q2s0Q#$V&QMt2mS9qxWLJ1{WY|Bv1}86KX}u zkTH3n+aIKqSJQCkoO!xWii3n1dWtisyofW*gd)yjmQnRT`RqW@oqTp+CeFI{UJ|#8 zft^Avv+aTbB9y}hvK3d>+NOonUIIKghA_HgpO0Tf)fv}2zMNUe3#Uy4pi9ie!p%}R+Bq#th z9t}*Qf*6f5#r2%_@xsTXl`%k9_9DTsL65WKV>m(7kI-N#-wzD(J?vw~5#30X;iwh) zjtO|k$=|vF44SU9Fq?5dU32J|HZ-a>Tb6`H!hhH`39-i+>zHwy)OBGv1S(Gy4LFQJPH7YQK0}bL|g+vHJFjsM0vq;xW$xT{yEP=A; zcxQ`9*;fDT>II|~>m^(LGf1UF!;h!=aZ~x>$7RXuK%@>DS+&f~6fo;DD5T(jCEr0u zVHlJEZFi7pEYUhXMpKer>~VA)Ce&exg5e5m#quaX)96-dN5s9U6-W_^dGws2R>N zowaB9xLYslzImQ$b}*u6d}&nS)`h7FD3~leX;opQ@^AD`&xg_5=FYxuzh)^ix&Ks^ z@%eSKi{0CPkkwT3nl$j%xfy>R*gcQmM;B0j`Ls0WM=b0hBO87r_NZ2rfb%LD;%5NDAzjqeQHP6h9Gd6jpdy8sRU6 zJL<X}(dv`^6>X!D|)s4vw#9HY6&$0Ns8)Ao?j`iiIps{DM zJk9OGLfZv{sLVJLhlxD58d+J|5V)wa+j6mgSsV-A(z{=SO9*1e$8Gs>SAN_>3hdEt z%)%>H<_Wx=2v}f!G`$D=vVM0`Lz673j;&;AqvmF0ePKDw*kxKr^jw zhD{TGW(OO_629>8ENEaps2@1A_g2KeF76VD8c*=~!f()#qkSx3K-%uUtuCJ5aH$zC zkpNPjs)tJirt(s}Wy%N%EE@6P^+Ml<*JY!EJ!~L-CNLZ+b&DP6`xtS)56dj#l?j6) zaytGaP#w!QB3BDPR#d{%p^|>&2#m!u=4Q7I=wR|t4Vu`4~lE|9|^4qd#&|9Hv5{|G6VqUIIrD(`CBeuex|#l`B40j zef-~3ruVPI9KrnQjp>#7PqM`K^Y%lz@2D&xv{hSU2E%MBQ{tYeR+!>9^w$Q>;=UF2 zh4preW@)$y1AVGOvuJvuS^Q&&+b7`=gg=+MU7A8P=m2X_xTaY~p@|ViT4H6Bp1-Ld z-@g?}>Dn1Q-Clf0H@@Vm`&z%=uREx<@oyrKJ-Si0$Fwyq=hVe_xC=SXG;G2Lh0EF7G z=ihLPkqvEc?rFHWs^M;#rMXPjj@4k_hx-{eO)k9y;p;*6zyt}xIrbrlILAIbOk!6u z1q`XQwZbp)C@>iham4#3+o<(4BcXB@$JIdPPI#KEV)JincFy?R(_AJ#I(x+;y)#?g zRbTC`OooQpqIcTtHd3Uv1AAIRzXCC{C{5)bxcvnj5^Tp@gf+_1)Kd>i@A#2SMfY0m*z-|#uC9NB|vE+-g6Z1#!41ZqAqV=Cxb zrXpsjn3AnLwqDmT%qKEm9-qc~&x}8iZ@Jz>JcIKk`M3WXEVU_cTlondd%<&TkV~fPf+`MH#y1qBIZfDqEJBsI#oVP}lFqe6ct##EiUY#-Y33u0LcQ?CD?_wb4UCdf--dJWpMyY^o zlXn(7oV{L)!g=FSU)yoGOnd4=9KhrKI(lX+iV|&- zO>nkSd>5$%7<{d);%?0PZFLGa{f_~DiZqfhcY!$Y^B~oLAHh}Ln87d7-Ow$PUV;%? z*?e?;rCW~)c^<$;0gNYQ1{6lny%P&>*h&C(I~&>R_7~ig zmmAt1Ugp>Zw|RoV5X%la0uT<3ZQD5_-N$ZiVN5)~IG@GAX^S!RJwpsM0g&>N^qhR4 zhfjQj1DeP5kPnK~I6`p+IriInf83+K8fqAO+ zsF_EY00n_9$Y>NHOz_q!&l(HZV9JW9)xP;AmMt+?b!K|xFHx1gp42qBu7N0rIJv3S z}a%McYN~+>A1f_*u}F}z9p-TCiy=Gh9mQRb6{vMTY-rKO3?~A*bHqNhiw3t zt8O*dyu~{$vnp@x85TQMz-gYWhVQ6)jgM7~;5KAc2uOg3E)tZZ7qN>0a7`i>Fyvtg zm0z6SU9-?L{u@jVh_g~?CYSp|0)KoUtOy7wD%m(xAst=Rg`jA;ChQObNQcz+aLNAz z`DwGiJa(O~M+%L@2M^u}L^}>;mC69XFa!kxEhs&QVR44jO1JjW$qfMa$lc5DyW0c9 z_kZi;MxI~^@5u9e=x>5_6`}oq;%;Uc&H*7|0xu9r&?=kvqS)m+NA1cEkS|b^R(PEC znLu!?^@fYS{?YEnZ=W7>FF_Tt$mRZ1#VfhVLyuYQWQA|3n?GTGM-oglb>!~)$?1{q zhB(-0gNe8aS~*06Lk#N0t!P@kXLR^lci_?M++pX-HCx-nu)|8aJdR5ZvQ0UrM#5not|bu_vpLgbn(YheN9kx08lOv2`GrdI!GnKwxq;A%_XbzITiUbJBX?K-J|#;pUw*M#>evavGYBJh(LxQx0q6z8 z?4wV9^WB%*Z}w>jq58U=jS0tmDy)w~Gi)n)B&^)O#~GRQ%fwO6OB+Wkp1Jm+l83o9 zYzD}0)?nC(%bxUVCK*B^OEcu<#qC8=v0>xQb^X4?<2BA4dfvAXDz{YC9aZ_ZdPlXo z@qdjhwCTTLFG2ju1lBgKHVt*&(f)1w>TQ*4lh_RUDAY@0>lN4CcVOT%OZi};Q~>VK z1r}XkZfo*ifcFr&n5>&L7VG)3WZv}Zc)n8{u(Jdwl56GI+l?Sj0 znls%>aBkRlbli`}|2&oi)mTf>t!kHNh}w6}U8Z4d z8;<9FoTwP`e|5?>b2=fg>dTujvUC~xk}1={1*j{FSH?U|6ks0-8Fwr4$|CeV3!_{5 zw&&5YdAt+uipM*V0Yh4lR$A3Rf#E-L3g83eI=R5r46DhRyauk3QV327L_d5}_G1xt@nLjaCmxuud^ z7y#dbghYs1r)Ku(qs*DR3jB1f?1KUS+qFEtJ&A4MFQmrSmC^C4IRn&zs4VwWE>U!1 z|EDU*fU|)m3hhp$q?ZwgkRUl+-T`HSs?ZRAtEQ`F5db3MhD>(VfH%YJ-}jA#Gg-I- zjFMgGF(dkUUag%79Yw$Bk;Z{S#4bz#?I9oAsvr0BUd-1aS%TnlGz^g==52h|V3rSn%#!xa2s!FCv7#gGgvp1VXFNYFyy)gd4kp&{Jy8Pi$ zY41xGA6Uj;iuh=?Un?Ms#|1HA%Ri2VyACC_10})KT!%=Pp(T*5rG!U#Vanz*cHiDcUxhml{bT>uxDe!i^qHmJNE6P;q3XsUSV#vyz?*R`4Z+%Esj2Ee#B2D|NGEHlEQ9H?>@)P1<6; z_y|&#k8L=Ek1>W8A7nzxixGRO%%_C@rMP7-0-2z6p5Yg;ap1uzfG8n_d@v1_NntP~ zt2;Ngb+&Q7uZh9bVMdJr-`Lq-v9T|YwjPDn-uS}mzE|3Z2Qun_0#P1(%L_3)EKH8* z+aPI{TwwQx;KqXvj)-JM)fr<1b=)2)p-3FXyg)^g4&Lp<(bh!e*gGZ>sALxrb46b< zP8BJJe4~%Rijfr}>fQdy2aL?(B7msL8UWWPhT%hkjd(o-dB-4W%D8E$-w;l{Vc;jYJUeb2=_mQ+v+!5tUy zgMh&+jvMm=g3NInQ`ztGPGy`;8CxjM)cj0nqO2;gr=!__kF4bgKT=F4%Ky5-E*qoG6(yA;cO<6F!(zAeu8z@GVT=scRM z)$_W`gRFuw@mHR;;geJ=rU3u}0*blN*yj3LNCO>DM`f`npJ9g&*hNg~p_C~~ml3eT zBXW-K6}1~!djWOiflI%HqtIS{kgw{8?mQomm>&jJ`7qqYhpD%GsQd6cn2*yX`^I!( zEj{MBybICuz-*GXU+6K7kVGiCYRM;j(R1W%Iovu&+(3`yuy$)@#O!BLSC58) zw~c>VFU@6-g2NnDK1g3gU36A2YA|t9Z{RM+4|he#adDLua(E)b%F0Zob;^~DqBObW zt@+dPP=xV1hNc~Ch)`LT3)=QN3A?D+B4HUd`OLV4dFcvCyWsio7S~isaSLqzi|AJ0~fmIFvDk${SPa%mbHswYQ87G${Rqbu3}{03swH4Nkm%Ff2t1hC*I@B_&B z%7!EaD#}wEnTWUB?KDwmyI_DSF*2^)yG7iFjV`t?p=3Tp>^>s695eL&d_LmbrO)Vb zLiD}?zq5ZNJY}!*cQ6|XN)7*<4F4w=f+mqO{K8fx8Oj{hre0aCmiJK*7=E;cG8)w< z@Zid14KyP0SlYX_ashXTulskH9=}HxGmLLbCf8iE4a4s&+uXm!jumuYcr9edpw6%H zxGO1C$iKL?j<3&&2?$9*477ngX6+k?{k}H{`!@vbs$N@fR>zFtT2luiuLNemjeZp1 z*Lc}@cL6gS+XgUS2gn7l1=5=a#BdLw@GL4A zwhJ$=+O`ku7!_gKfFc*I>c@v^}U7*Lr#?B;;G(BLYkM)iZ zmt0*39RE6z)o<#Wi%O_O3Y021*35GT8)Xm6Ih*p zB~{B`cNpQac~l?{eQ4Q`e-lQiiW~Js4kKLdt{FzS;_}QLl&rrb!#e+e2qTD;e-lRd zqJ|NEcx?!>4{^^3wx`v*qSYHpuQ?OuW7s~pHM{VHQX3~T?9Mf-Y_=Lk#6~DC<8%BV z@V+@kd!XF%*CVkmsJeL=#tMDHXYS9`-di+%&yhYyC5gdqv;m$#EuyaJCG!5$eB4*e z$EBuj+X~6Nr0Tbm)L48|Er;I1q_n!4H^U?_h{!OvVvt_m?(p7KdK`HjuctD87(b2Y zm_SY@Z0b}?)6M&_(pfmXk33wI3JFDDi^_7`ulBq}qndNWLl zqBMW2@vuTnmQ`vyNQNGeDTT8>CJAKZua%lt1u=qeVXT(ZZ%H1ie{lzo_frJJ0%N9&2K~DCBC0B~ULxf|n)PTjs^BZuEN9ePX_3YQ z_qq35-kI!&+K0w9d^N4Q{TrXTs@ChNNG;0VPeUkxk`)e&crGEL2pgA*7A)7h-pR!y z6sW*!;K@_0g#e&OQzq#BQhE-cSyPDHr;XbopR7MdEQqq6T}#-t|L1S-|3#H&d$#?y zmSfxhgI~kOJORhHR1}t%4W6fsNpfF4^Wv}UdB&ixYfsvt5v!(x*@?Jz0+QDZHSPf& z+5YeCZQm>alLq76eqTQGzwT{cdTeKnvubjJ3$~l54Ga(_OcSukTtlG}(bLHM58{8+ zNFb|%yP%1fmkEZ%gd~6b5B|4efde;zurJzYSl)I6bTEB*?$HzRs_;v!%()p&@=`=I zLjnV5{Sa5d1PG!htJcG=h0PB&-nuIZamv)gOePyT;S^2+Q5evynx z$CLqC$~`~f=5^4)i`6$upHp)crW>*CX-NSd$ps9D47aDl6FUw40uF<>Ff$pMMa%IF z{O>9phZ6xeep+rM79NRX389AMfQ0XfGPn$R0H@g5Zkj!2;SV7<@rAlCh$~w(j%_&vG3qafIa)2SjKwz{m zYEyKGZhP+Lr7GQwQ4x!9#;w&2YVr+57#)$|ic?1KsU*2~F;3#}%);m(mPcbWq9in^ z1G#Dt21G+z41?h5>kVQB`+x#B**yc9PmPy|B^|2jX06@N0gp>mpCn%92W;&J3Y8B@ zj@XW?G!2l3L!OROsM(}i;ud0R8}c*-3v^7)u;sCIOxufC2=%R1Wg}4HLL;mRSlAsPl7tZUxiwF=vaZLLwK;m{9Xoc@bvWA!I zPXh@OvIIaZTz64O!54#LgMIU>0i`vnZ@2JINLz%gfg5bt_(@(6i_)yiq!4pGQ4vP* z_oCrZ;4Y%GKoR!bG1LL+d$oRHVFc6omhRnJBS<0y3Be{=usGoI6Qc@Af~i9_ZLFQ5 zOFkO$3gs%bj!yFN(kDVsp!h?V5ES5I>IncS0*qH6P`G>|k2I+;tC-+AR#6p$iuRSH z-TKDAI6j#N>R+dV&0k3z;D(5JE|MuU<%}(;)4l` z$?^q6nHk&hn=MV38~9v`;WVtgbz0BiuZLQ9*_Uw}9dpUf zpq+??aQ)ew=~iSBlj5^vvM2ys*!)pflRXdMk}}Ekq)ePh+l@+3G$|o{{h(R!O<_5g ziV-p{&N)DYe2lZUVMxJurW?G4Ind^IDR#5)dKY;n=Izi|6H8&MT@J#oXJz@1vLF-B zxUR?WqS7-b;m{pW-TMX)B3uyaJOtXu|4$3B?Hq*mN3cRYL%D{hO_|0!=o{0P0RWG` ztww%$dmq=Ux7CM%T~h9bjYY0LMvU9G%+~K~hD~8pY6Y{!eC!XrSiR46^YqbN3wipk z*MRC(7UrQvEatT1E~-l2+TUzt0W97V&6$v&9fuKYXyqK|X~u#=Y*+8Dzy0p^sqvqX z^TcsJ9Wd=`nxj*MOC3Ja#B7we#D$NSn?s=(Te z`06&T56?CagcSdHNRKc^P=)2V`~F9OX~2nO7z5u+v1kkJm8M;ruw7}*UbZ1TJDcKT z(=Bh*yFC(wJS*+s?bHFArtkS2Ii7W_>W9VKp}>_MK=7U!f3-mJV@JZ^ZAhO-fonHW zU;jjNp1m3@sT;^3DxjHLN#cAXVBdfG&sx{M8ggu=laFvfVf)D4`QA2cA7J!Q@Pp<%eFS{ZlH_il=!g>ne-l9LTG=I(@)#9LVBH ztpAv+Z_o6b(h(?c1GK=UX4=mQ zSP)$Bu{5nsDWNb+KYr{I;Civr`rg@@90oxk?#-ZKrRz*qncV1io}t__@6aymc^zr_ z-Ob+Co7(7ZbQW(;qjY*BJAnIBp%%Nt(tH{x+=>_;2yE?_eTypDzGGp>cx zLkzR+KP3%)$_>r91wM(5&bDU%kR%l2ugPs?#KSbS+Ao1Irm>RKaPt6F(5W@gSqjLy}yH^=l4k6hW6iKD*7jo~C$Ky{cURL(5Xrp8@aibf;a zK;0b)urGLRnO=#Vl^pmgtc6Bmr=?tXPU-CpVRZiKuI` z54;R~xZ;q^enh-d)Wj(sEdDC+X;C{>jn8OlF+}*90(^hpbcSqr+_{9Mc59`>OJ^f&fc|qYR{gg(<4?3mihuO; zafD@&X?8#SXa9RO{##Sx zFO~aOiruJr7{d;qNKUHR(h?sG4BNfz*?~2Qwv+qCd_k7n5yw-p7BT+yw*R#NFzI6_ ztN%D%FAQFaVDR^0aof63q05QPJdxw3r@Q~5A@`xBkD&uNa^G|CnEyP5;wh`PPcPDqWI?&A#tqzyHz(wl_0dpo}xSK^cEoLm3kT z)<}^@`1paJ5AqI-KddL}y$lHppV(qcOar2UR-}=-YjzZ>k`Hh~10)rIqdL(~ocEl# zOOJkTX#kvn87an+W0-gNzJJPGaFBnUaQXFUgzImc(GF!===_wlvoxojd1G{wK^u^B zTgZX;;c%G>gt7wx?7-LWiYNyIx}|v+`?n;E%d%kgw@Rqv2s?JBZ+SjWF3I~JtGNdQ zWyr(oKj0gv`f7$em`C!7oGaJ9n z%-Lrm$d-@I6b*DT-=hNaRH|XZ+{;P#nsyVa>8X&Q>VK0{x>t zajXE$YD&f*mj029mp>ko5mJa(6(@X0T!g|2w)OSMyN_L+{u;wLd>k;%^w#Pi#tk2b z@RIr1c5Rn{Oh)n!EBA_|=xY*>kQ?8(AJa~DX|#Wf*e$b30Dk|9sSZ0ULT)#Ry*{FcL$e+?9hss$qt<6 zL3 z$#!iP)*aG43TG~1B+z7Rup-3!?jghrGFbz!nTPd#(J6aqbhZE3UK+&~I<5(wgblkx zBjEFRf*z0EI8d8t2yCz@-v8W7z!)oIhy#V-7YS8~1Jy$uh>4wqgK5(!>&S3WeD8A2 z4T_2&OoW3F`Z%3!;KguI9XF8{84lvfZJeVF2eBeI3kR(g=|sR~Asj?#AD%AZAnQ3c z3r*8Zva7js(vL2%sD32FfNJlskLkDYE6E1D=y=l%sVJ2;6{2^dK=1Gz4BQ zWp8Fa@#)gO<@NQIb~%^XZ#>7+4H?qdB`)7_SRiZY zgb?_dfgwb3w>ADg!#tR!key~KUT0qFSj%zYd8s?#1q3!~l`pHrr@81FTvW?fv9Tmq zcw3Wf;RaoJgGV9`4!u;gvwBNA_8Oq2&NYw*fJCiu1~qLray&iGzdL#wm? zc!0~0N=$KIPSJq+-YKq^m{qb5Q;)%O-Vdb4tHeQ85d7n$O-x50WJsKSsnl`iUVmGsjstk;ylS{K0968nQR6DYM|;?`v5U3 zCp~Y~N3+$H9T&xXV|Nlxf;14ZFZAcM`f6NX$iXNHu*G} z^#Lv{_8Ap$bp?!3s!^uH&~yM;tQ!HQoN+ml)7lmR<(Tmz#sZ>22W!+!3CR{X)2y&u(6QsXZ%|Wkou@U?g!QbNaYL#ap^<#3Cm$1 z7(A1=c*k#He#&x+P3lt>XtJQoonUp?GYknBSbIWN&*fbpX|ut-*%~<8rK#MZZ-eYD zDRP2(?%Yv1q4_ji;zM_i^w#`PP!Y|o%Qy|u%YICpBG65_KHKgAF$FQGeVI ze-$>eu)tm>1suLw2kHzA;)SSVe5I+umVCZ_Q(XkgGoGj|b>Rja0KtmbO+-@9Z2Qh7S= z#pS=BSx1VxqVcr7RNAeWTH0$}G+s-K0~=X$0%NmS7e$x5q%HOs@>w1UT`u;hHlYng z$WkgFG|$|ID*9`Me;B;h-{EPLfAAhbF}z@DjaYKL&bN7SZbwqI)R$dgx6E7xYSJiBkI^ zx)JtN(Wv|+uM5rh6bMG5F;^zc6U(UiIUL;y5uQfkGiETyvucp;(GbUA7OHpE zP>2jbhD;ze7?GKd7MWgcJ!5K&T}YotQhh=`A{zCn)1Vw&zQ7pC{Fzxu46c+Mx)Rm; z1fn`f8svsG!~_$$L9nsE-B?^87q!vjzEUP)E0D_G`)QMD)_A>->DkF;BwXXJyBwO= zkfWv`@b=fR94yZDdIB~THC~EA8u)jv2m)$QME9FXE|sLQ5w|paupVIwjel%L;Xz}I z#sor6pF>`yfsQX$t^k!gfdH-F!3+wMge?kQi(d9|Hi0d(KsM_oOe9|K))#wOx0ku2 z7Wqob>@*|TFhPi#oq{P`XuDib^oMsn0@C)Jq(ryi$pMKcT-`!Se3P&}yGmrylB+H8 z!Rs0VVR67Qtg9(%A9JC45A?wbiRM90MAD;&d)eL*B+1_Qz#yQ?_$MAR+|I zL#Kf@=C%$$v~|>HE}maEC_OXcIjE;#C@klo`QqQBKxH7+;baSbuR#t%nu=O}kT%*a zCo1I{HurBOMiFVr61a{$w~3**JVC02+eOlbhbY&Vuo6fqHLC%p2-ATZUI+l+` z9o!f!GE><>&4`qsVA2MpW}cLqK`|{BYA#+7)LcC5w9cZYTM-*)S$!$0&jJwhCR@+4>+hm zXMHE?2m}Pk0=b^xc+Jc_cx_iPvkT2l=EJPQKWruWkA`B ziZfzy(`6PXyvA~Z*QCqoYFsnwv>G;vxFn)!gpG^AcVT<+L)$CNPav)>qH3IlC&E_I zI23T;6hJFwq(xXZ;*zl|#1U-r3~v^ABeW&$#gW04XC1Ay4PmnckeR=ZmTRg>MjM9v zY_v2J%B)z5qX%NNt{2H@j1~K?h=Pd03mwLR-BpIkULS`EzdLBUF;K-zWta@uVO}*P zJecCxL@2Lu=y)((n|m-hqvrH1qhHKD=_6XH^ z{9deC47H$^ux9yjKSu6AEv-}2EE}xJ8GRsLtpmi=@r33K$d5S#24!RDh&=<`;>JK&gH!lv_j)>FBZp-g`j6 z`~G-<23cJWRu_}5I*<$;+S~KV=PW-UF<4%pPilr3Nc2~bSh74oj9;u=>Y`p-XoPH& zYjU-*w1CMb83YFv`08m$4=FT4z%5R+0L@2~6d{KzC!ewzovEe>@()R>Oh(?%1sp#f zVAdI*A&?Ub<5!B~;4Q}$^R=&q`2vSwzKDvb3U%fCd&PM)@(MEjwNU=GWI9t0Dj}Y; zK>2V%i23=HgYt(dUmHDwcu;|b@&hvi;Suh3u7tTGH zEqTYc*>0y?30)yIrOqv$ut@v^ot38GzU8H*s%~0rXybLEVM5zvkS<8Q-K*jjgu{&a zhaeq7o=WZDay1|#0r}$rE=vSZjM&3ioXM>q`5*yb3+(wTNnkArHm&2CmeV3mSh%=p z5>Qk+Kw&NfD#=uY$h}e-s2qZk^31~JYB7FERAAvAg)=dt027ZG+N)d@Z_cQRBv$Rs zG@$^`BGZJTL^^OyMTum9BvSPN8`DHm^#pAAk+6w$$%IX@gv0+filW}@IUNa~;U!R-&8CH0^PAh_S2vz++hpcY zY9us_VB?pn@mFXM#`y*AE5i*{B^=`era2;I-qMi9yb9|ZbU%&&!Ow3`^TB{GGa-}T znb2WAm=KPY6Y`{soDe)LnY}ySYu?2#ay5e?p?eCCPnU9oARn~NT$}NC68{3I$18N5 zx$DEITp!|1LngdA<^@KDpYm5fDzX*sXirE*F}Pu>H;b)1t2gt(RNbq^RL#20sWNFU zvG3W@=PV+RscRLyqoj*!;~zB;Mj|*f8_8F3HK_K#Fc>1kN#rY}&yhyP7SJo6Fqdg~ zg3}j#b^OoF;q{e!uDo!PHrQ}EYh%U~=tr1BE$OSX7Eip+=Z}{Te_uK2sed`3@{?3K z$M*`I?%mvZCK4u3$7G!2K8Sco53et7+!#MkhR_B@C9Jixu@cu$SwsJ+eigo}Q`_?~ zekOG|#J%zN>PAMeNv~@-AyBmFSyQ-gYJwo*j9sdgZ0ASIW`dBqY{=rG^4H}?Ha{V@ zO+zEAJo;v%pH0C|Ep0?tD(cfN@iQ<>jdOZ+MF2R-X!N@A17CG?kHVd)TdppCPo+G& zlFIlX9Ldt7EPK!Z+;;3k&Aq&CT=$qRd@6Q1P0iCj1V?SUJ&d(cb={Z`hOz0fsBGa6 z9-JVUM<<+V?kVf-<^5q{+Jj`jr*#q}4+jwD-h{jVyKXo(k2(FO9}ulG#j^cKX?#hu7XVyqtIV))nnfrMOL=kq=y zhK>QpN1DEYv6vrM=67PM?u9@T!1EW_I8${uoZTVmi&3%h$M7pF)`K}jPYmF$Zj&v` zQz%0cnchgB8*GDVyBqK4W7AE+v5;(=JRsOZQ}OnV?#y=q`$o(4jwV%mCicXdgKH5` za%hS5_CJZy<>uC-9!$moFZCB<9oL@H{Mbk(z^^YPc-kE za5@kIMi8p{eh{VDzxfF^5iXy-NF$8Yx$&y2@hknCo&Z)1bL|}ywv#~+0%~XJ^)$J+ z5#iO<`&u^8q4(y*^4m-7t0AoT1D`OBnHwKz7PiW;4nsDjsq@_pZn9d364-{!{z^!I zjLdgsMkWyc<%&cvNpSpKC}vQC(*`L(+O;+ws)0Dgc~<+MAUfWRe=$nl`2K&B z`QF?Tp@^w?t|8moqBuVB1HY6#-7G7G_IVz-+&d zCCt{)Faa|HpL=1ppJuKDGj93zJpn7L$Jn2>+YoyT63+W)&?K|4{7N~oTpPx;LUk-?~^)_fVSY`q06myXk4|*O8zb#d_aJl!`Ot+y4G?N1h9^ ziCw%1RA98fKi~$ou{F%Bx@D#@_c(0T>BuzxI!eQ@W>yC5M;||X2=3_&-#PU zm;6NaeWt#neJ(NfTwv^3c!UxNAORt_h%sImqzZf58C6Oam_(X_^ zdkDSFh5Tv0gNI)zc=!Z(P()L@17eu8pt8aMy38i=II-FA2(pWgADgl*)2*5B++pAA z)a~{tj0%FDOBm9~;&O zEanF^u!6j(8AA2pP!kq-V4atIcP0P%v_YWc%IbX>4kWV0?t7xb*8Y#R%u?QfvH%Bq z7OVR<=D`{tI|w5RgzDYAG$Ag)r0@jzu8p#KiCxQt$1Y8}?y$iHvJe;pbQlH-hj`-u zcI(Wn+qvNU*i>uXy3zC|svhYDGjR?Yu!c%}yq6BB9I#%hL{*+0DAfB?!9vHnoBHt+ zk5bVqOnun2WA8hPLHM!p8yw%%zsTW76Grv+iFrhet_d z!0cNOvoAaxP#KV_1dMLjTHsC7sD2jlgjlxr^*x%RWjwexfsFhQVMp=yP( zMC#2W`EeTSzPi17d;U6?AMeVKcgMZv;rw-~V-?>mMe+JQDzJwT1muO?(wv`Sd|3TE zh-*btq|0ANa7UVZr^rWy-X)offEJr%Ry3s%;-Yeg!Wf5Kl)p(3``}ziJu|l1qh%T7dng=Q(}TTW?~2 z=<|p}@V3vd9Ptyy)YvScBfZqI1CWCQt$KCXkM6*wJF6S`w$<(Mjgypn3zEz#rP1?| z3kU}taFC=dz-^Kf87Ucy)@O*}P530*a3a|B(f;ih;FWKLMGd8K#&C>Mvf7IMfxOz` zcrgH_yr+3^zmpRIcS#et*J6=6Cyn0)_%3zp|Ws%Ts+u7)eTwp>A zfgCuF5Yu;9$*z@|NpZQm`Wr~YP)%)nhA&ZJ%7>Nt$2?jX@YlOM3;K?zGOfpi${D{j ziqbxoP{|9Q;zBKWfz|lU8yk>YEBToFSZMA^u06-k6-AvpYOIMBek@mDGWpoB#6K-(dzRBJbZoEaP6V_wR6L@2Zw99LD&eA z(gJ0^AT8WrF-VIq6lw9n1>>A*Od%S6qKJkcUla{zQ#5?6h=w0WG(3n%cn%w99g(o! z-^S8;BtG{Z)*?X#yBBEzZ)eb2X#q012Tm265E%~C_ydNTPIA_3U^{;oTt=0)(~#r^ zAH4??7qy;*Z;+i&%Y!PpG2f9x_|ZzGE`J>f;`59G%DQ-j0-|V-fI6B2O8au%`H(qwQwk?UQVORB zif|&)E$qZ$nV5kF%`ol*PTj$WEl8OC{w*BZ1F3+w6&2ghPqFGaUo><@Y~=GBM#M2x zcz|(w1XF7IW|R&#eL7u zMg+hB0wFkc;~KVZYzVLQ>R8J<+P(P_CL-A_o&ZV-AJCO}-Wol{;TK!VCIn6FTCN}1 z5!)^<^s5+cs~gsVh+-nhjHDgO1XbaOmAg^B#3wWESn#&uII%<}8{~?_2jY)1-N{kI zL(Q3%|2m4zb#MVCJrNPYW!wE~Eucwb_<(^M@O+xt6}98qSn6d`QvOqSA`rn)HTyPQ z)c_a?asO6J`zsVIPc3oOc40hmMy=%~Zt~Pu^RNc@fE1MbvFQ;lPHyhn+Dtk*z$&B@ z;wlO}#Ra7kGDhiC73t(aA`1-x#rN}Jp8aK*})>Nb%l;b$Uxz@rMIaR6nyrPVh14i3@uUNQsk`5MA)6t2VZgEwHJ1 z{_fs4p{^V%G{Ot3JgDs-WRl0DFd@vK7&V3jkMKa)+)NfLsi0*vIRb`(sE^Ds%&6D8 z0mG*f!=^dWdJ+$Iue?LNy8M3hwS3Rimb6c7a_yHY2w@{xHurN;^7MHByYI z#)vh_3wvRB`G|0l^JK;TmtG{~Im(hkYyEL+QLgoWV8Lp47Of%Lvizi8lOb{n`!J3u zDRedf0V@SR4;6*xP&<)OQ)FuoP#q7c*H`cbLN(a}_8LGEv`)fW3oC#h^%Ecfo=zKR z1#tN^qdMkVfXhe&xU}ustcJ8O7G$~RA)5i^Ed%Z#Cj##X83hd%idQC#X5xkLkE+3- zH~1LC39#W~$rJ|w`3_VWyLYDuHAh3)Gi~mqp@-wiO`eR0R(*)I*76XEU#b8#KN1)D z5QFS%M#!FQXi0Gw#6vqwgu=L8ZI5+K%iZx%3_UgW2yW+S{JE$MrTBSMqVYSAE@IKw z)$4~Ov(t9L0%10Uyd*bk<& z45d9ZZ5R1I7apip)>zEin`DX>L{K?1CRtD*-2LED}5O|M;#GKzo()iW{1L9HYg zNu|OwkV$AZZg7(;7$}Jdk|c(kr-z$&&2MTz$D3(D^X6bc^Y!>}^Z4-QiTRtyhMTNC zXP@Zo=yM$-P7l+F5jG>BUa%SQ&So~_6< z|E;nf_$@yJbu6w20v%pB6{2p{BR68%@Pog4#bYkhuUg|7cA^wmwBZ$kr_+`-l8N0y zNAY$X5wO@v2Ys#*9Ei6)gdiUK(3PEdR)O2(vJ*Tb+JI$VwRx&S@LtxXUhNrNH2=L; ziCY|nK?wK7XY(#`UfBbBD_(u+r>}TbQL^fL3Vo2W%91UF5K5~llAA>-kkhvpCvDIL zwHIAJy}{#5m8>i68B%vRH4|ZHKx0U(ts_Ij;$!iR4W!N|GD5WH02@KV{N-nk03IjI;uDnW5L{(S(g(m=xK!Gz9-hT;`7;8+e&=B1a6=N84T8Fm%f z8S!A~SuXKVr<$Br#;#CB*pc=$%ac&|Oa~w-Y}#sbdsG2jbz# zp}l*X~f6SE1%Jdi0y-uhA_P$;cUdYQdF zlpns~=I7~(-WodTj`l3DadR*qrQWuo5YgkGV?uqxS#^3JG-NGkKiqAb6{EZ5s1x1a z5QU?4U=IT^Vy91)K1Vu#iU*5K@Yoke_Rj&>a3AZh;P2>q5m{%o2E#7a9+s zX(IV(Z+){B>zlchz*~7g>zi4c&M6qG(E?fy|JwRy_sm*%9B1rv-(A&x(HW0sBU$2% zU(e60Oi^JllHvq6;(?Fj(`9`xq~9&gU9xjf-=-H(fl?3IkvMT8xDE_W$*|;Dfybw- z4z7+tS@zi66d=)Yd%15P$0mSlJGRq@<4`gD&l=9XpKNG?JUJQOd&*z|>AP$*8sD}7 z{cbQY3XWsP5cw#BLKH~PTo?vL9z!0;Xv6GK(!W8+hIrP_fSQC2sc%Y4Q>lXIxDhi6 z7QKsF-Bo4?lArkNzIhu(yD3XZp zoz)5G48fpe=L1Eee3}CKlT5VjtNyFH>Kllw?E3RwBGuGO@X3?dWS9Bh2}%Y-iQaH zVe%#rfZ%Nxp509tQBL7;HDX6_7HZOz5Q2nob*ye9`Imc9FE3j$tF@K&u?%VS_|SHe za4`Hxja2m%VGo=DrP>n-Le?L_SQ(KjO!8AT*?N?Q23nX>&y@y0M6(KP zLJFu1Jmy=gCYSfHq3j<4?JBQgh7d9=8Vl>hW4|uAd4*_Z|9&EB^-&Rl2xclc1W%w} zUjCNLFIInZXQ_YgyO#~kQzaQMfBeD7mTb=COv#rBsQtE$Q@zpDh*RFWy?Mz?V1sz% z)8+0<+&#hFPq2hk$3hY|xsJe}LNn@FVsg*aP%`rQyIlEse;ggLr1HWeMnn1eVea_( zLj5(P_wha~{0u!#fK}M0k^k-k&(+h)?Z`wr4cb+50`sjO15dCrQ6GIv2{7_5BcNRl z0Ej@%hbXee>(r!x2#upg{EPUNo)Zle&xvWW2n8yvwp_-CXq+tPYu9_c7=h1;BTr-d zaLj?87&FtN8nf~pUmpqdGWUr6d;)GT=JMD_?|#38@II_QB&*adAR$}v0kWHdk4RPN zxHRB{y^taS=g257e?Jp{SqrPjze`*#67CdSG#NmCDAfh;oty4|-fnKK-o^SJ9}oM) zEzP?<0X@e{l>;(P^KiUnV{OYs7r3c7svkpAp~v?dCMQ?}r^DFcXEeyI{=FBwePRy$ zxOUCnHA5215pQEBJ7IXM)wrb%6z;zm=kfI&L9A32pp#Qo$SlZA>5UDGZ z{n|@LNT3Gm2oo&0gD7v9a0EAH6z}4ds3YP7K@oV}8h?REpqhb<5G~5O|Bl-=E#l{0 z<>zTWp`4eb9ME}2HzK}qsI=-wtAsxU9|`(E_~f>m5=a6iI{#MQ%awctECK(_XxE=| z1mjQp3{qE10!3gLh4kCK9u^BAvVOU}2@gT)_gP&mmY4tqYPf|`Ei3KhRjm1D68BBI8exf{H zqdJRaF)6fAwwDqqY}m>O-)xmpJ;--Pb=FQi$uNGM&W}^@MMDA;e<-(}NNV~|!q}@I z$%k*PzP_x(hCyq{uhG8KYI-&baLad`)AcAHB)F>Fu<>qb9#LL<4;hWs*_aCMGi0wW zKGVfB8Ipmo8DivSJ`$Iq0|3CekB$=j_z?4VZ_GLRzf9 zBcRDFh30?dsb`4jzkA0l8w5HuxaQNFQ)!tc1}ws;!ogme6lp6)Rily{twoVkDTKoP zk`|Il`h_jrt+bvLrbmZVP$`-}e;-B1D>m=# z^-!iE=9v_)lie|WwJ~@!UAPjf5p)uysEpu0xQCXx!kH|~Iu?8#4L6x^-o)$6n>-;^ z6ef7O99GxpI!GR$Bos2IPvkt;Sb8l%J5j3X5LLlh`S^d?JMX|K%KZO7n+7QqL3$t? zB~n6Q(-Wj5bcBRRC?aLq>~4}Zo84s#5F5b;Dk`?~JPUX#)dG6nodt!SuH&L(fOv(KjNYiU66BUt3o`$M) z|8AV}&Ew=xH^jx7E-1VX4XVQFuXhCkF0aSz zaC%%$hnnGY`fWk+ko{PxcLjs^mwU~DkiFJi?Q%QKUccGl@;mK8ufL&ri_h=XayCgq zIG4Ku!GM}$bBCPfpx0}5+x#_7bG7Vg3zB$)Px4_7_-uBk+3lz(xyKZoHB`3Y4O3N)yxo*+jT@{uQVpdk=+)|>4%x4R`2K0dGC=6AUp%ps3$smnpk~6zqo;vooIkLPScG8Yek6KNL9Hmwo#7vou_j)`W zx)hO=X^>MuIXV4NMHh6{lRa-J*g9}^C_qV0@dkosSAfjr-;_J+^w|oJ*it zocwy5r@`#?aY$0Q+F=?6%rR-@?QjO{ewU96io7@+s$&U_F9+QVUApH5-3s- zl6=eM){?fI;(+Yx_S);BQ)s@p9GrjIXkO+G5xLiH5BXJP(8k@R-#~WnQtk}7eJcE1 zH{MXd>|N$@%AL^awz1o|5#4xA3VHOaMD};p``k_`OZ`@==VaTsAGpdnaxOB5en(8@ zE)2S=T}12W>R(Fe>15qpYYUjGoRnX{NiOiM@Oy(^yVq@;F)0HhPUGwcI2LD6O>hQ+ zE{}dg8-+y7OG1*QDl>A?e1En?yUfqI)AFRoTgUZfsl{;Pe0Bebw*?@ za*0>l>gCpy7@9X~w~%o}DiW}D8s*O5GOxc*ZX5^Yt|IHvcTszHrbpi|`bM->Me;|L zQe911>$OnJ0aa>+Cu!OBo1MZk{3KT`o-MVd&CT8HXplRY3$sS<=BNrG+Lw!pi&VSn zYi%9}7u2aCFIA#*x!vh>$Z4V0cGY@)W*apxRSsU`Z9ZF-%k2ufw7Vxjwq16Y+?uVI zP)xac)%35p`{R0>E|33rOwYKl)OE3@*rNEmP3M_r#Eys?pk9vuv+5Q*Aofwy+p!(h z9r4QKi22gwjL+j2OuJ*UVyDNw8^12*U|ec^$N23r)8c!?ELSsQM#X*^`<~hrdrsVQ zYD;WG{JipQn>U~p(xNG7T#bv6~OvR?F)T8k?n8wFUGW{oh z!Sb^*mY<`}%5Z3ZhDGc->TI>(Om&LQ6S7g&mwFmhrPJoO*Us=bD{NYYNMQ%4b$Gl* zwvBTI^&8XWIeKIHq*Bho(f$*T@}CuQ1{}5qHP`9z=&s6;M?A{BnwjKxX>0go)Q`w; zjL5(dFjwoocstnc|onTmU?FLY|~N1K;XF)XDv350m6Ep-O0rF9{H zNR@{IwIMZ2aJoY^Awtwwg;a$tWF7DFSf|+V2}#-(96ag3{6uUq#zusd47DoRKyJ#804SNok#d4#Bt$Ln`UMb_d~Z*$8-DB3GTj6NQ<_-T(` z^D2cbEwLHC*%V=n@$!{a`ezV=pr7TY$zXaAEf3nf=4`hv5W^)C7=Je5KPsr`|1^wo; z&o<*N^`lfI)@qteZmZU+3#jJsoYdCg^=RZ=Yw`V5B+WsiV$l4u#sq7nCW~aMbs}wo zw4Xs2*MeLUS!3LCMF-Txng(Cc#d(>+gUwsxZt&FxxYun#8V_xJ%Lu?lZf_M-o^H~} zlbf!><_|cv^Eh&(=B5ejp5(UG1k{3nIz6B&0&0AK>m$Qw<|4@mDE)ZMfm-dsUhC!Q zPD@8_U1=rBv1+XXxt;VgtL>@A*E(qpG+$>UC8~_T$P9<(n&Ea>XE)T;(ntsd{Vq?9 zb*am_Y~;v5sET#frkvWAwsvC%>Rdj#F^w~z$e6X3litQ#-?!!3P#)(pYi-oUqDp;! zwNz`2E033|LvOTc&u!ZMR3ciXLGz1-J>7yT4!Ax4$aPCNw=~xD(7t8b&AV(+K+dVd zDNTGLsrP!E4b~c3zj|MTgmp*sJ*)LXrcsa4Hm0vog{^e*JgXO1nXS$iuwff)o_egy z8?aVUosJx7=iJD4zgpl|@<63UFv~kjyDXP9-(J$nl*__L4d^u2_`M;Y8WHf@HQer{ z^;tZJ&!AXFxLsBD<;!_~YMZDGmeQ)TN)N>4srC-H`+Qm|JY#&4KXtlKWlSBJQ8qH8 z(wyNlE`-5L%_o@$*Oi6la&MW>HjB$I?jb|uTr{s5^@&_0BaQ3H?$tUhBemO-OU1m5 z+MQ})8Ff5`t9d*91aBuXJ*1Z0Os-U?Ur$cU$kE$=D)A~Wsmaw&$}~G7nb6w2wNAHO z);=1{L9Z(Fd({-4$R4j(mDhRITw1iXUNz3^^VWN-y|jcHyfpk(nak!?)1lIel`e-vtUS|ZiDSIx zTd$_qON2EcH|NYv#Z~9DYP~$Us3|%9wySL55-8{4B$bWJO)NCxRh4$}NOPddRbzH~ zyrCKf2aQV`ZsTHdZ2`Xg?2x?7dI)pWP=)^S}pgHD&V%+^5H zd@^l>I;B6JxuEQI9A(f}rz-2zG}|&4^}Ef@-9yROx;e*3oe$l&%;|ABtijPHux@YAWi7YWuu{&ALGI)Vq35)eY->(7TFazuh&Qc5 zHHRCwF0{l&OTf*=h_%()&Jf2qzpb_&(m^z z;%#FjqE?)fL;m_u9gZ@uLt>T11-W%t(m=*h58ORzFq&|cdTu*%6rMBA!4r1ofxdR9vNh(~3;t)a?k z4QVYoiLjE}m7A`fx`f!BoRJzH7uCv=os*lFUr<<7Tsm(2go%?{)@@aGswB0bT2)l5 zjNz8){Dtw=&5xO=CuP8Orju*cXrPP_QL8LU6IBD%+VhzqN7+dotuqD<<*woR%AMqFxo;RQ zW%P?433V^SsF4O8Lu)o))F836D5W5m@vJqP#hyXb;hbi6!5)B*+^DK1WW=I}iJ&dbWE&&rUKRp*hL zOl$g^@u;u2`SdlKlMdz6`(9RUgv9FdQ1p71T5Xkqji25qSL`wO4DcA@)@mnWJz4$v zaO~|`BPMF^3O&=(ws-nRj+`Z9`Le=&78Oc+eA=o4PM1529>fTo?h#VHBe=6UA2#<0 z3f#)=PF)qW$`-578*nWj&gc|PW9lNink~%>aZIKIOY>5k6RG9AJ{(k`{52Y|^*F~j z(DY)sUGtmDh=Ado74p~NoGkUDow0fvltklhU@FM2rt&nTz3Y~SrshFo(jglrIPER% zfPitY47VGeZI3J<4M4_(U1!pC@_I&SMSIN9-2W}bz=~BW11m!-&3i}#r0qHlMjuU- z<}g2(hvtHgTxN2aIQ`B0>y4Zm#*kWh1(|=59(ya#Dpyc@O1JX#$yh@xAH7M^;@38d z(t(XWa(S}Q0=81$cJVetvlMRlX=-*$vL-S?5e`9%D4vXYLc@`EvVw5D6=Xy zHN)@XFHLwFd)Ap=c|@{KJC07wGMh9_SabPnLqYNN)C6pFr$Y2=YUw#KVOYao8M(_E zBey!mr$1b&`!$CQH?_Z^`dAyL*=VoRf>2XjewvdwXrPLr%TZTP@-9y;tyx<7HV;oL zHQnjsxi4Kdzs+Hz`Rbv&V57UlpbpJ^6$sUv$B-ShNX=igV7bMT#c*=ArJCiOg~~ji z!BCGpb{q@U{E>_3pLl{J#o6LowA?|rL-&nxE^6^@aV_%6yp0|~vuhF0BPs)lwZ*lF z;W@*z#kI)h_Jr!SkS(r7c1CR7nrDk^QI*@~sna}LT#IZ0yUV5T-t1b$Ir7zNo-M9L z+N6c%+2UHnBif<)H9N?Vuhyo=Xt=Z~Um5@$&ca1m3)J8tXPq;D;n2*nXAfUAaDn2w z&>HCG1zHoGriw9h8leyR8ixbGp0laPUfkK8I@B{ zQ6!* z(pja`RcYn;sZ-V5(wXH`%O|VprTig+quTar!34EnyqZ00JR{kR$@;D1)PivlH*c7f zD6SP|5IKIEJ_4%^#4uUQu!z}PB|}DI)fjc63@ijjEAxpmQiMZBAsJj_oW{c_pVr(M zt;SZ2QiI2ijLL=@KYaGANm)hB%`bgTs|VyV&Sv!AqO^M}Ym8PeXf>+UPD?9j9%Ht& z`?#Jtv2^;Zsbv#~nNJD^hDgiIqUvTkrE)VGC^8hrBTCyszk#t!X<}*3h~d%$mo?^= z&8_EGq_@s2xeV~gXuQ#g8m=bkqvA9~v;k87xU=LLMv2ju7%r1^ljxN>9W$v?oJPBr z)|a$G>UmEfItFficf*-9K;`<;`#Zz+sntrGjQ;3PRcX%C5MzW=3mJ3{SNid3$H6RV z(C=+0|CB)!-1ui(S-t(>Y9Oh0dj)E?qI{Y7MUSE*nPU%0sJj8qavATN(#kIU`4w%Q)8H zA;ZkoG88?eb&XnYt6?ICGgBrG#_q(-rc@|Pskb<((KYZ8)l#*#yK8CGj?F=bsKFt< zIfhHdlrdwcP{3t!xifAp>sj?97l|FoVRELboy+tg8f{LZoWmbHMC;k<&j6oSD_tr8 zbJR9HOH^`<;fbgk1qdXSnZ zGT$a2Z;?)m9nk`i(K@uVnnn(lDC-E^SP?RnZvTQ<~7U zb{mX7SGuZ@BV6k82Sd_mkGvzH_sG(f-h^Y0-xZKCVJ;|#*%6ZFn%U_83?7oMsHc{j zmDUT=t4*zP_B)x&m)D@UMWrs)JZqV%(;n_-+B%UQSaU<(pOZDlE7c}b{q1hgj@mAr z0GTDC0V6#Q?!u@w&1tUZR-xLGc9cHmVOEj;nK8s*Y?bPTib%Sua%|DQ+Ni4L+1$Ni zKAUk#f-$Nq1HBZAj7u?%#S0|zY6I1X=G0z2u+`J~rlwQ!ZkTk)^lQRMW0t=`OWde+ zxw#lH;4K7)neJS(Q#;m>N6U+B(vK;!FK>eB?<$y8hTXzqwpd2;k7;hl@C-`yGOZJ*}LPCx%L0_v7&T0dcB6oJQGR7!ZZN?B6XA3GyQPGs!M zO#qoc%FLu!g|Lfk;iGz_&7&Q9IYcGQ4)ZetX6bP+G|w!Z%lcHKL8ldm8ida< zelN^Rm@Le3mY6e!`pisVB}G<}lzA{^Z?B_GWOt5CVv0w5tw$T|mkW|H2ssCCd1=Vu z4e^$gUJyK2c!x&s1M||4+|_Jz3{RTH2nS<~gmVRl$?IF@EVrE*J03WUR(Y}{rYs{S z8V12y{WU!q*`V7)1ZwEep=L(@xQ!y!rj|pqo<%d8lT>2sw`2OKB-N)+AMuRWw`c*9 zBcb}J`Xwg!Rw^-pjmauO_A&O11Qy#lvO>(AWP2y2VpO7dC(6d=?U8WJ zHl^96RCjS}e-d?X{zh+)3W~F9)M^*paq>qc>fZc~-X0YcXSb-;cUBX(QxjKv6PI`s z*KQLRY!mlQ6BkhvS4R_F*-_U8MgK>F*-_UEH1znp6t=r?7tt`=`8787!85BIB6M zkh9#8qtq}c&$h@6i@biYG&{S%Y7Nx7>a~{-w4f6u?8}6k0HclyU&y}l@=)s?BzzER zL6$#ao zTbAWU+)}4R=b;M!lJyrUC& zYlpb>mv)Fyca)Z?in7SCkJFqn%bYPU>NQDY6sXmEG^%BLOT~Ru6p=lpC>PCdn75F> zp7MpN!5L5%Fn7urD78%bjfc2fP5!!wh%^o`v1)W5d1#FXFxx`wI3v?5prkcpcuruSls_jM`4z z>)@$yIA$=JU}?@rE@_^`wsRqKs4^|Y4j!u1Slpv=b3K|SvqKtwsW1SBvri5bKt9a4 zU8!l1je9V50*t_&1>X%(s+9G^*i6=k!iTuW<2Mu@WPK3a4;jz{zizivR@3!-nlY4P zbAD%$pCFtB8BhXa3G+|(eFOGG6FkB`QsF#``$>2ao`Hj~1-5}y2x|!U81D7h?FOg%{_Dg&`u!&ujta)b>(pvb-TFxCEYJS{)!%J zdtTlBnqJrT{zISZ`u?fkjeTxPy}AFo0UOdbr`?sd-F%PvZ|OTvc>KhtPJH&nw+4Q7 z;(s!}JIS0ia`@;GV=QB{OR~r3Ovs&>SCM~e!OX(SqFKfBM$SKZ!6@5k`xxig>XO=0 z*SIrE>c+b#c*iZ7=${mte9n~frmi~W;%S#mzjXSVva8B(nsIZ*#JOknKfC`q{a2iJ z(Y)2CUwrx{r>~iR`GPAJ+_CV^MRzT_d(orT=N3P2d%?E5YLERz$1BcPtM}F%sQuFQ z)fr#cedGSN{(H~itRq?BtP0nuu9>b%*DTj;*BsYe*J-YKuG3xfT?p$*z>CTt8y|Vq)d-gu| z+T*W3@lV>lG-wl=mre-@og*vK2u|o8SxZPbzDJAuf7aEr7wPr>zmR4hiLls!7>@${=4SdksG;H-#_ zZ_r#>nNwq@#4cZO*752ONv6!f2?=Uw!qB0a9Ui z`Apui=wM1P&DM^SzcB+>%F+WU2X)Vjx|DkUIg{Ee%lTRW?av*}i~fX+Dj(WFQENsC zm5Z15Cu&>Fstv8xDwCXz=CdVvZ0C&qj$W;jN>M4TvXa?hs66F<{n9#?R;OUj9QVo| zk?XD1miAXVxMNE*GmVSVFvI4w8}=9HHN~wRl62>O!IF^iYc=Q0n@{?geYjp{%$YMR zbH$uF#hIC0hArzW3q$kITA;1R+!04hJbF7Nk<)$UT;*MP?$dkE&04v#^SQ+0iy!=nlhnMI<}hiOe#@Vyn{NW$v8NL^eav4T zd1UWi?(d(`-o2HNOn#ZWDn2@q4kq=B&)zRMWo?7BxdWwtu2f52+Xg>+Ju0tSoi(Gm z4vW-f*sRRVhU3LH3|%lt_rFag{Y6|eV%sV0pE}|x&3R~N$4G9P!yL;I3D`kRiQGZb zRr@VVBr477m8TJM+_E4K>7?x1=FapHwh;lOwr1{OmW*Ke?8*xim*=H(@G~8uTZW#qM8~)PG zmqo%$#TOl3{3A9e4AJ1uH2j8PC7;7Vj*Tw5$_9oz zRW3x9I2=DmJQZp@;iCDueSYcoSmHj9xPL3-c*6V=eky)x0k#YIk~00hI948VNWWc3 zTh7<-Mcee{9R2U|za`+NKFOmP@YCBmF(Bc`LJ5?@ zI2aGIEGFCp>_m`olVCDP{Wld(0fvW_A41>+S*pPX(uD~?#6JVK)W657tJ&0U{o1zv zlz1e5vk|^3%I%19x2>n62o{t zt9ef%I1zuD%Nj=5^+v`0n6aOvq3wsA0TsZhR1~|CX9dIWYBoqCbS|6*l3yd8e7npx zPF*%}V#FugqIqe*p(bIO8{0ry7Sg>2D@zPWzQsOdSn)rN49KyZ4w9$&umBdqBCx_@ zka9QDFO*kw>`Q}F?e=UY^6L53J8v>tgHid(F@i*Lr01!Cv?Nc*%R#e5=cxieS(oKG zBTrShB~Nyc^Xmk;#%iDzT+lX869PwNN=tLo&!kzxNsw|l10>Blkn32kTMu|a+5$`9 z=rkvU+LnYIXR4f7mSY{~UyL;6K9V#8AorErQ%gab$IC(5Ge@QAYX3Ob{!E&KxzOY| z&jd;HETHYJ&HO7WvFzw*00qA?c^(R{}^c&@jk5f!vQT( z_LF!A&TN&hmN1gA5oU@JM%EuAo%68ggPfNO;6k_vWON5SH|nhNOMzfO4q28+9K}{^b1W^sGJ|h;M`{GAqb8AOxlb%uSxm6laEt$El#eXY z*Hx{tUHoTJQOdRaN04K_9{vP3z>RPd+zjhrJ=_9+hFhWSF)usjF>6~|9W$r!7{{!i zT*>=Dsl-{@9@9P}|Ix=Z$_OjrM^W+1G2I4oOt-@Z*a(|oGi-saa0f&m2QL^J=g#|I zoI5R+qt6}Q(dRCPd}`+?>Nr#JlSTYD8UE47IndZHVd8kW$#LEZa-4U;-LMU|!#!{> z`~~iVw#TWTulA1fm!2;<&X)7_vXM7AU(v_0*6@!$j?bcxg9r3q+2?N{$MJW#A0B`Q z;UU-o4+GQ5;W)zY#N7msz@xAW9)rihIL;#N&GP^DX4E2)-=$5|+5|f&b0dCvyC;%_ zRerqB&*y9OT2p^kzeZR&kIS*L#6qO~um?XWj~``QM_@U?aXo>35~LiSf~Vmbcov?6 z=ivpAa**)5aqoc_;UDl4ybQ0vQRVPo+@QxeSncFXJ@hzvkz;Md%F^Dkek9wBW4(q3 z*{iJX1v%E&pjCeV%NtQ%8`Dk>@k}Ic$zzB#C6D~1N?W3@$2H<-+zFySyE5e^Yj63$_H}Ea|2fl-Y@IADb<}#xkB+Vdk%5tnU?FPyDAZ(94CH94(I>v5D>G@xQ2KTIaF3ZW&72lE?Sj z$>RjJMV13b9+QkbCSy~M%Hw}qu}F7KD@QFNE@iE5dBMozY9l|<<@ixl9}urkIBYlQ-jdHE>wNg>!mzopVF3+Bh#(@=4D18an4^p8&41hE+Lpq!QC&EC;fRkVl#7SZ-KH?b6 z`Vf%+U_cN*ncK(&S)OBk815{Hq%$1%2#8L{!n&lB4U&$`PZ-BgOizFhb#Wxe>c^9g zj9om(u}K+3YUF%<$L2oePwcLhO&ocR?3=6a>(zHY_MX~voc&}W%jzKM$9@wIN8)M8 z13xxnOrrgm=)@NrKdqM03ayu}AJb~$mUC64r9fMsiYS+a@_<*i!-Dwbvt9u25jK@| z3mlBvFZx_X_KQAOk^CBkEyqoUf9mLuo#!IbmblkoW5}OFnH46SKnWpSCM1j4Xo+7^ zI9YG-h2vzk%@RX7XkJp@Ml5;|qktkNF5(ay38_qGuHHs&gGk!4uPK}m?hx)6)_+0u zP|QO#GVvv^@=mZGyZ&}CQ8h2eH@n(*NDPsE_0;rm`tcsUk4ZafJ+GWd?P}6XNy3Ut zY)g!TRg$)1q|&@aLjB)f^zw{8KFNxnAD$syW63~_VNIHi9Fc6(w`<3;LUMZ6)sH%5 zyV!qpyft3@-ZF^nH_5f!=@=oO$Y_~?mvF{%P+fl8EO9qJa-sC@RpX>uy~lUvRIMk_ zc&D^zS@tLEEtl%gt+Lv9{cf9B_53!jSk~25QvIvO3xo3b(w1$w_-{wmC>RZ6U@VkC zDU5^iJo%bZc8)t3u;y5D@+^fpIoY{dZ&>>v0l(h*_=+{$@KBiE@Qc0e23o*zM4EkAcYS_Nk1_YU8OI6E4NBx2>5 z_slK7;lH2RRLQ$JGU~(ulfB^$!O2Vmq}-vk(QpK{`c3EpYbu9k!Jan09lCq z7Y_1&J!oIRl-pqB$f*a#x#qhsSTjJYU^Z-A-y`(uK|BoDem>}DdW68DTS@JCfmO@LB zrPyM#R9Wm6hs9~B&bDM{XH&Ce=Vj+-7i1S^7iAY`+p?>&?b(iOXLdDpPj*gDPHs+K zPJT{7PGL?_PH~Pcrz*#uS9ZAc5zN|ZgF05esMu@VR2D$aj~tqs@PuaD0UWC+bp(hTaGQ)mS@Yi71#=GMYdv_ z%~oZz^L;L-t-8umm0gunm0Oipm0wj*RajM2MU$ths>)vFsB%_S+b#BNdyYNVo@dXu z7uXB!MfPI5&0b}<+Z}eNz1m@MWIJ*kxsE(XzN5fV=qPd&J8X_Bhuz`e(?Zowi!518h#`k=I2nYmoBU(Cw3Cg3!=7kh`2k4 zRZLRHl*ZT#!{>#&#vQkspB~0{qlI))B*gzyYdw*Y1CIniAdsc81cw6TpD)O zPy@B#g0{;qdH$p<(U0p4_OAms$Z^$!o}au~-b$_0qJOK@$jdiT#}p(E58=JwgC*dH z02pyZzP1yIL-Q`szphfCdrqyWv{+>bQtLC$AWk{vBCH!^`MZ%$ka$C|6qdnqFw$xL zp;sfX>!ae3xFoL)AbC9#&VsWcdMRZ^8n|Y#0Zj<``C_;ZE9^Au<2ioAU&dmD6ylMw zl`{?h`>=xi9JvYmDwyFlc-wHlgB9dw%lokJfu!|5R+wbwr>WTgfcVS&z!Ae8#tPaP z5ot^RpMP3EztC_OW2b;rFwzc^GUK0CZc=vq1Uf9`aV|)h6?V+WZpI4Ye+TwX;GepSKZ5w*jok(kemnLacpd+Hv41uE z|ArOb!2j>q`+KLK~H;Xe{9@H2XKGIkUYBs>}`@YDM67_6ZE z#2#A${M25RV#k4mACDFI`F(f-R*<@AqF9)WdlGgANPa4?g8W4PRIDIB)t`wKfHGtRSBnXv7M9<{*3?R*=sRoR1a6e-&1cPZF%g3gUk;R^T%Q;Y+ZW0-q}g zufYm@wjg{JR^amm;hV66e8%8rtib0C)WldF8Nl%24uG7yrPyVL`z-7^a320Eu!7Xz z7h#2yaIeN*0vWj1V1*Lgmt(JhvAEY_h4FN#uf*O0X8do(3Te1+!)`VF@4yOtLLq!7 z_HN))3gK;7A(wczV}*VA--8uo+~HpAUkv~IutEv`f5raI@c%njkUszYSRtM`AHWI) z_&so6!uJd|@4)Uf{F|^sPr^Tf6)d^K4c@z|+`|0!5u6#mn&GYtOzm&2=Bp;h}YxH#?Aq`er(u_K>AVZyK?=2e9GfVtRU{^v4XhwV1EGl z2-IP0*l@4!&iMsC|3Mp@a|CkD9K;?5xds~9U*Pi};gwi{&wzx_!wP&3Bz!(r;Bz72 z3$TKe!-ZIZ&xM39!U}vgB)keM@L7@YYOEli8Ci>c0QmGscn5Z;;cno%7vwV|=U{~o z=!aa67332na&s>RN!NxIM&ho*UTgT@fED;ON%&^0z$Z$=>#<>weWkML08$Pev0XsQ zp)0nB;olqE-|#nM2O0i@u_FwB3%1bkFT##B{7bMC4gV?FGQ|2ZV8vZ`)5;z5aKQ;t&a4*F!0|)Nq*am3C zeJ1uS@Zmlidk&n7yAitzB>vUdD?rj+i@nb9|08yt;lCcc(eU4dz1#5LhTU%X--{Iz ziSzH+`$6J-0Q(^DshIFXSbUU}zMo(}g|)ap!wP(|C;T;5 zkh~ofKWN1N2kap@5BHB)LGpQ0I?qx#pKEm}R!Dy*9L~fFf5M%E6}V+oIaYX&eHUZB zz%8$Q*cEU9|MRgI0M77V2U6!iU&8FceheSruZD3wg9U#J)(TSREXLZvgnt!Q;L|!` zJ67NmJ7EV_;8QzcCsyE-JK<`qz^8Y@HCQ)D9_q0IpW_L8umYdu345^upXUktumYdy z3Hz}DkUWI2OF`l}7rO%Zj8C```z}bBPqCkag!u~lwc#&65X=BR_Y)q36~vu|6~tY# zf%^j_o@rQN^wMy6I=0^MZ^YhUxKG$fxq*bw!FmmM1NLl?Je-3S_{0kh z>@y(8wFmnm$iA;)UpL&}V*djYrgAHFAn=)_un)Tv_-s-*{t)lPfrLp9Q^$jucuKLS z!#?~~oJkFW!T1lx&VbkO--dn3@P7?^$nf{Yo79;wi124)FEQL}uvZ!GYp~ZE?(49( z!0W_$D|Wl#z88DH;eHVNkl}7jF{yi?g!r4VUqKW5uJ3J9JHage*mpqkU*a(-D~SJM z>tmBjhZFEW0XrVvCcKR4SooD%A~QiLd^^>w?MWbGk!_`n$XJn$(UnA=ne3t* z=j%2S?!FWCa&7B>H;ohtUrTsSee*KS2;bKK;S@c5BjMwkLo<$Igm3GgK$u7#C4Z7v zvE0cVQ=)M^X{@c#!lm=Xk?m&f$wOVpui-{gy7SdyeuHx^d+22#@yHU1J97N``Xu70 z*0ztPK;`%bUeNmZa`2~k!)^UvFv431AEU*f|Jh}PZ|i@y5x$7Q+Jv8Mgm3Hrak`$5>231!HvV$FZT+t_;;(2E{vsp(w*K9X@Uz;4 z?`VW?>%YUu&uMMK-(%#bt^W}t{9?k#MG6!9wGqCp{{|yJKElUDg}=ebPh0=NM)>7z z^3&f4-`4*DBYb0<{A@GAxAlL?$p2cx$42GnNhAMl{pFe7YT>@01{E+57J(I-mtH2- z7y3gcSYQ&U3D`;4gg8E2m7LItuXLp*3`j61j7=y_I3;0Df;VAF!kYv(y`wH>eQ_{Wa>JHFd7+_B=&qlaEPH2QGK;VTYbb@<7{yU~He;lsWo!6QqL{CFgi z{^HIibuJu+FsRQ>Di-1)4btHR7-%pED-3}g$b&*CHaHn8j5C;w6{Z?Y!wO|E15SmR zFw0;rR+winA1f?0uwn%pRDr{w273m$!4E-L1`TjFoNLgCy%;Wq8{ihW6>f*kuoWJJ z1Mnqe$IpqM7k^3oW${e(N`Uw?QT-iq60DdzFHBsMctzsc#H$lGC2mRFmUs{PYvTQh4<$a9_+;W! ziO(j!khmAUnfO-XJBjZmevo)Xnxp!XYEm5`2@0SHCPD?c;ggt8W8$+%WUtTOnXT>6 zm9mGK5P}s3YH)b4>f5jHfWB#cOL|o@I}}-@E?>v*mG0zPjOQ9mO?V4+>CmNvTyOtE zoqKogoow!69%>$LUTo&S7dLy&Jj4%%kA#nWA3nsBzGc}#dcyMtmORQ4)<48~fWV6; zbtahjkhoxm6(GIu!(r)xcg4~|K7K{dZN0zky{#|LWmq3$QhUI{bKDMI1L-76{v*q; zJ&v}=@Z0lmu0zJbEehrPTfC zXg=56XujOM-rQtX=^5#R(ubrEOV3WvO)pEI zk#0@DIQ`P}wdp4fEE#ypz{LZ@gVc~f=F-e-`8rlOQw?7@{J@AfO9JXB|IY%iF^sZ| zwcKF2(Xt*LvixXSo4qc(Df`{*FOWIMnzJHjcTO0cmK)A(DhrpXjp-X#Z@grqWmEB{ z;hTqV-i_vOoxk;rt#w<+93FeP>ybW3EJtP@nRTT4NbQk2uGH`mQ`j6nIb0H+A9jX) z=;rXc@V@W|;g7=vyWoC!&|n947d#H}uW)>j1fAe`=n1JX0E*#c7y~6R0VWxof~|m=aQmw! zwF#cxYf>*j7?ylyQhx!{zfEd1r~^FrzyeppdbkU=!%lbvcEgMCEy#q+o$vvK!Sog9 z1G>V=Py$n+0#1d+-~^eF*~{e1oA4PNfFD67VV1&K@H*^+PvL-pI%rbK&=n>_1DNqN8rL1={W8TfbP{6a^ABy2tuLJ^EI z7>gCwj-U?&%}d+`ajW7+#5bm{PR;C}*?&3O$9G>#Hmut){K$wSmVF#ITwx&nJL%Ik zFNqb2vlH!!)rl(-_iYMqk{8Gmp?T?JQVEb~kb>VVxBI&Nz1zdxn$V-&9`E*4w^zHp)~##zZryuy@7?|M?hCu0 z-Mz8<_1zn@{*bjkYeUwith=(dW&Jhl?^zFLHDx`K^;FgiS$ncx&3Y~C?JU#Qgsq8N zJ8wO1YtOCbttV|Aymk22eIIhI!$;oY)oU0(22t z9eYXa8gzN=EwQ)8?vFhX8;(7x|Iq#m``h|g_dlcmPNdR$r1ehgpJq;*m^LM?EUhAK zZrVIFA1y@Iv~$uL)Bck7*R;pdo=AHs?bWn5(%wq@BJHcRZ_@sgb|mej^pnz^Tb+z% zv@9jm?U%!P1N9HuTM$`RCY_&jVbWzuS0r7Tbam3Eq%BF?lI}^mH|f5l`;#6@dOYdL zq^FafO?p0Q589XXZqf%yUnYH@6i$llzqmj371Tg2oB@}^TDTIfhCjl3*bJtm*rfQR zq@*rMU6Z;e4Ne-GWJ$_N%1z2oDo83yDoz@O#w3kPnw&HxX)~p|DXh!WTo1A8 z?h~VWR>y^p8*UlFTZ)%wtDFHji*wG+S-kn|&FYR@_io$!#NKE39@@J;{4g)4JsEx` zygU4l@ZRu0!*8~bHOU<#Cl^djJqgqTEgrEA38O0R^qn4FZA7$`j6C?Q}?C*EA^w)f1_{E!PM_l zoBD_Qr{Cn!^A-fQTr7SpHk!*W;wB`_OK11mIcetz?w&985Md-FS+<@g)B zn$)8ZY0o#NtVy{%Wo^n;DVtKZq}-cwU&{R{52ZYo@?Cw!3bdBPV7KP3Ff$U-=wYlp5Kx^)=Q zp{&F09k!!qI(*XMn-1T0_yMVoJv#P91JPhq(($y8i#wjt(bsWR$BP+{Sl{vKj&X^_ ziK9^kIxW$bxFoUhnEl-yi96`&zF_oo_a`1m{4()J^i%a)q%QL(1&>+p?nv5U)VKSo zYrjv5PfkhhlH4`9d-CAqp~;ryoaEf({N&=~(P%;P!enc*EqMt#A6=MyN%G~%Ym=`^ zzBc*#e{JWr;(jTqjEH>)0|G$PPR^Gc3RQt z!cKqa^rueSJKfvq!A?6+Q>Q07nL1lK=XB2PT+(?`=arq$>wE#asPiSA*L1$M^X+J3 z=WU(u>3nbJ9jK}EW1XKsZ+3pCGhON~C0!l*61vg_sO==R2c*FI|Oent04pVxG}yQjD3ik>Tb{;B8so}cvmvgg5` zs@HM7(t2h0D(Q7t@g5IloZ|c1T$(VrZGoVjJ zpZY$&KEXbXeYW=5*5~Oys&CJ}=DxG~Zbb3@a{EnW+~)j#>-*i+@9usN^n1UbN8a(q0?evi0<>3%0tp`nLXSYjiuKx!rRp z;gF2|^+#!k1|J&QZo6Q+Hr`rcjJF;*e5iS>H9b5sTpB(-T-|QFh5n_YpA9F$U>FIb zU^I+{GN^!s&x{A*_OJa1T5H zzowrm?W@JG6dK`X*ay+=Jo)fN4=_V9G{WEDVb}@s+!wk+d(ZpD_@51pa3eIqlkhaW z2a$2%NPB59Z6#?(HNur3FHBE?$oyhtZc))jJrNo^)1HTIupLwv##>;JfdxAee6SK^ zZ16GI2hvZCr43dHOTZ5@wkwVbl+PlXyt_qXk z6tIE~8sTnu3?7Fk4H|ne&IGT)8z3L87y%Ou8nIj8?*{Tg3z?@W0d0PUF@{W74>A`V zhMya^7{U0&Sc6imupTzT7T5#(4c^5H+K=q}Qb#}zj5Mgg3Jc(3xXD1q!w-V|kR>uN zFdTP@fggJX$Pe}tpd%zgGFV`eL3{nsi`gc9PhsBx?k|X;?JUGWq+Okhdz(RIJSsB& zB;!d3K*n1};614p#Wz`AvO(^YVOhaGU|l7pyNC8&{Sj^iAJF@s058e6VN0y#WdA44V9r8=u}jRW}~@i9-5C9A}g{XJ945LgLY(@xV9=xOvEdI9Z0|3ELJSJ7+epXg1~Tc&r=e)KMSAAN{EMxUa8qc2Pc zOkbmK(f8;OI*jBqCZ-ruOe~5=9Z(`lMx9U>bR6oAdZ1pY59){dqcoI`PDB}K5E_Cq zQ5G73vQchKam*+*Hl`$I9GZ-#qG_lM&4{@==GvIMW0u4&VdOo)$kMXdvlx3{i|&Yh zA$Cvfi?Of7?u~sNy@B3B@1XtYUGzTs5Pgh3MgK-$#C{$7Ejow}#r_y;iL=JpkR3Tu z4RWD6RFAx92@0SPT80|XS?C^ac77eT}|F-=Xi(A#@mpk=(qoNR|#L5hbHes0%s{bw@o=FVqM1 zL;X=2N=GN63^WK0L76BEjX>IXAah5DnLCnq4`lp9F}J7Jzklj)8ekd_i{eoSl!%g1 zC)5QUhq|L4s28G29MBK-M`orp5fAT$JJqAWB5Wush_j|x#SIvI^dV^Jv@k0zqY zXeye9%FqmSDyl@Y(OfhS%|{E771@v-IZ+LAp*mELyl4pupb%Py8qitj9JB(hMCYRm z(JFK?x)fc8u0U6!tI@RsZW^!--GXjKx1)_{Gun#oM0ca@=w5Um`Ww0*J&1Ooo#+v? z3q6jWL{Fn<(er3GdJ(;ZUO{`&>*x*i7J3KmNAIHd(TC_`^eOr``T~84zDD1o@6h+? z5IT&)13IL2W!}u3HYm-KR+v`8+?mXqEl#UR^J(*CtJ2n{U6-~#ZDZOtZSL%EQDawWB9Hk98hgA=& zMQ0#4T7m+@g2R>$J8RfVbUwNetwI;0OVMTM3Unp98eNO7L)W7l&`oF^x&_^eZbuu@ zX0#REiS9<*(Y@$C^fz=rdJyeEJJBO(7kV5$iJnH!qUX_W^dfo*y@K|l*U=m3E%XlB zkKSdx?lbf``nt`SUFn9>4dc;7G#O1r(@+_jflfu0Xf~RQ=Arp$A+jPHvLh#|K`vB> z>d{JcKDrRe|8{sWx)fc8u0U6!tI@USI&?j{0iC$<#Eltf5E_CqQ5G7pF?(Y!%14E$ z7@dqpqp_$IjYkvFWHc2`LuF_NIu%u-*=R1BhvuV&$ck*pj-03lxlkRdM_#mK(LG9CbSOSf^J2(BUv`1yU~5_FYaeOy1&?u{$F%|aW?DG{lzO-kM1u%&ARj%BmKri z+T_V?+U1dV>my~lE#~MsGI{syOf-)-IpsY!nd6GgVMWhhJ)Y^%o{9cZeSSi7RWm;rezWo5#_u=Eduksb-xeRE)^Bb3nlbAITdnk7 z7@s!YNsAn-*kkoyBI6^+8uvKX_(r5Z9_fcmUt5UupJiTB`fU%I9yB$XcA2h;xh6)R zFPFJQ{oUl~`NW@_OO!dpqvs8uI%?j~|G)Ewt>)B!-+9A{zi8g@x6T==pkID&JF(byx_8^_g(e5!2I;0beUuOCG%_YF6$^`UTq!kj>x=P_?Yu*$FJ|X zUgp-mV{R?Ed2Y?a+?vd*U9s_sjo+a|zhNFt=FmQDcMi?FWy#OZqrGX&qkYxxJX+H+ z=FfiXyjkSEkDq+s=l`&G9dK3`$N%>@uD&aeJGc(_jsuRP97pePC`Akk_AZE6qjGkW zSWc`M3zpcU#27pj>|eQlHV-nJ*3ZKAvP|n;QQnsOU;ZbpYyEE>YwP?Y|J~NH{sArgqulkXOzTqQ=k{f;KNUcqrX=exU9G#k3O#U(*InMkd;;nJ`#!QSYn?@O z{s&_Z#vTFu8t@L_+`5bEuB^MhuA}b9b!z~R0zL)E^R(W={)5lcMp7~{$GQV@0C|7{ zKp~(QkN}hddIHJ;m4IqMEdVCKSQ5||&<`*GFc2^ZFa*#HXaS4>i~@`Sj0a2vOa@E^ zOap8Sm;smt*d8zkup?j|U}wOtfZYLm0`>;%3)mm90I(3S2yigqP{84UBLGJM+5pD@ zjsu(kI4Smx*tYuL%=PuAIENu-5$FW@RQixu{D4P01pFx1$YebIN%AuZvnpp{2uTJz#jq6 z12zC&1iS=z8So0=Rlw_jHvw-0-UGZJ`!Mz~;8VaR0Nkp((O-8!4j>Ou04M|$0}_Bz zKuTUJ}vF@O^QVKF<0qYgqRMfQ5iXfP(>t0uBcp0XPcK1~>+A9N+}NNq}zxP6nI` zXa}4JI3I8!U>V>Nz-55T0apU923!lc4zL_>1K>u$3P1;772t<}TL7y8w*l?|+y%HB z@H4;~z*@k%?)P>71>ixz!+>7`ehqjGupaOv;3>eD0-ggr57+>B5%3b=Wxy+d zR{^gB-UMs}yaRX-@IK%}z{h}30h<6(c0@}>+1&xy&X=7Bz-EB#LO?Mf0VoCZ1e614 z^IkQe7C^@QB%m*#A7B7rAYc$+2%s52{=%-mC;4fLUnFAq5SjJq4#2kLK6!uwKp~(Q zkN}hddIHJ;l>lrm?NbY&za*e9pdVlWU?5-+Ul` zw*XcHZUfu_xC?MM;Aem}fVF^ifcpUt03HH70{9i+QNV8i>j6&!o&r1#cn0t+;5oqa zfDM2b0WSew2D}1z74SOXO~6LLJAn59?*l#rd<^&$unCY?SEBaP46GYgH?D4~+E3%} zrI}xMXx-wvyX$^l_ekBZ>z=`0npfcG`eEHCYGIQ6TI2Oa^@;k@`b@s9E%hVorzqdn z8Sra81AeW;hAaRq9I|N0A%MdGUk4mHq;1GCfa3wD4rw2<1aKzcY{0pI^8n`qE(9zC zTmrZZa5>;gz}0|j0oMVR18xA^2v`B=0IUN15O51%HQ+YD9e}$4cLRO~SOZuKSO>Tt z@BrW;z$1WP0UibX2CyFRB;YB)(|~6H&jOwUJP+6acoFa#;0?e#fL3_XZUdMOm z;6lJMz$Jjo0G9)<1Y8a13s2sDfB}GkfI$FSKxqby0E_~R0gMAo089c*0ki_P0Za$X z1Z)S`9xw;6BVZn2XTYw2-2r<7_6F<=*dMR}un@2aa4_Idz~O)+07n770r(c+l$%by zsU5Hca3{*KfgcKojP`HsW=E!pRL1fDw! zX*tqQk)A?&11S%-|9YfJNV_4mAuUCs{lMf`_97Dblhwk$Pkv;(Ba#2uG9>aF`;|`Q zzeRC$+Pks8b26X(cc|aT;DkjD}4B z+MAbd|6NG4_d?c!gH?-1WDzDImv z{J{7Uz}ooz@rUA%#D5ikEdF~yRM@?65@1T<^un2i+ZAqKxI^J?g}WCnEIhFA^ujZ+ z2Ww5?+QJ9CeONDI57xVYs3@ywV$r0cDMizZW)^K%w0+SIMSB1i79Ci0deIq0zXCj7 z^ie!;421Pbi*MykqgLfIEuU6qB!4Wl2@ZXuw#&c)*mBsU=63 zoLO>q$vGt#lw47ARmqx?hX8{UQxdx;_DbxZSddtlSd=&*&^z1HfjWj)sm#5+5Dy z9jABP(eYr%hK{$f!@09#0QQ#6TDi;0_LXO>ynW@mm45{^A@0MrfH{c$@U2y+tXd7Y zZPgvCezNNBRclw>yXro`YpdQ`^^aBWulmc)uipIn&2QXHi}bwrZ z`oD>UX2xf9k3*t(B1@1~BmE5New`xtjCVt7M56c?GmvH?9jjA2ewQHKj0_pci&mwI=dPyftzoP=Akx1i_CL&Einx)fD_}vHTJfy3ThQYU6;=oMB|1Uwh z327zLT}Z>>yFCVJf=-k0I~i#z(hQ_oI-Q5#aNqG2$a@z)-|r*QL2qymjIwkZgo?iQi+8GVN>K=1I^2QuHjoi!>4G2&Ch6IupN?u0gsU>3c{&M%vPS@)GBu1^&uo zkZysGGNsp%-lAXF%-%v;4`1Y`k)}hIZI2}TZE4>H?YSU-`VR@OX8)h?;CeBHmuVv4*iC&O9qX2gS)>b@N z@o>c>6%ADbs+yFq@9?UTRpY9vs;ePucB|e4Z~)-I>P6K@Rv%N{9r9*0U?O00&9s_r zA$yi6x%0i66*V{2tOEQE@M_KLHE#mmQL<=o?Wo$(Dz454h^Iq);2S#nL83HjdGd>n zogqWc0NkYFRaM)hI|2k|QKZPJ!HbZPlAfcKidfcs?*Q$yB6s_orquG zibVYS=SXXHB7QvrX(G}jq$xW65WkdeLHaS$T{6kyI-=Fgp z==a^A-;;(vDSul2cKJI1te$_m((~_wp8puY>i6B0em^aUuVMB3B}%`)PwDrMAnM0s z1y;Y0DgAzGd}@3ebo?EZe!siX@7KlGL9>4hdOd0OqT9Eo(d|!Hy8XR{_d>USsPIw5 zSRlO~>#<6wp9Y6lNv+FosSba1$*CpnX>|CZiI&8O#Ms36#Dv6T=<|DO zeV+CBC5f{VXG5F60Ghn$@;#x;k92hTJ1c%taZklVfL~_R>-$zURt>Bg0T_=x78TW% z(C}-jcL(gL^!x?Y3jqgJA5nd*(fRMGzE|n}S znw2#-tGU3-HLukCz2*(TTQzUj45=MiJI2fn(#PajpL{O)XTV=m<_R35WATc`8RrT8 zI|itE!UHLDgq<))Sb{mi?JMtE`O}qaR^FrM3eBsAuNtvxw3#!^S#>fX-JId|Rc~Na zzQ5|PH~;nKR{(DW^MA1cN zX)Th>8)(izX&7YBaHLT>jlplGc?8WR{(>a)32cio^NCjcpHdj7XdL9tRHSW?rX$hZ z!JR+cj_bRTex}pC_+5u|KN8I=Zi8H+dBqx}dywu$a_1K#A%`X)P1b2Der3KvbB-VB zv>Ly6BGDW~<{@>ES$&cEBQ+vXe9>W$TVs*NBhmbX;%7}lqB#jAnu}0+3Q6W8f5iW3 zPD06@kBoz?N;e7id)rsaTTQhG7=PQ}!DTh4Kb=;kQ_xVW#dYXsx(<7;#K!&l;&C~w(`Ze!Hd>H#SkA_rk8;-K{xbLA{Kbfk`d0pX`5)yU zT(B6iwcaW?IKDW3O#H<7%kg*O2Ny0bJgM+h6?bUQqWv+aI;rU8qPL3X74N0?C?-or zmb4~jCzd6yN*so`ZEu!uESK0l3AA@6_V%r>dbX;)dTI5t>Z_{f)$CQXy5^@ft=Jbh zuXeB6wj{;9{6?}pximSieo6gVh;q50-!=VS?bq4wgvLu7KO6Gd5EvbGe60yBmkj?7 zVplee*lxt!5j!DKphy4e2JNA0tV8ta9jTHAtk#-Gj6a$<^mt3pftaDfm4V>AOhRBhkF{EhLE_C2^%z z#!)`f$FOyGB1yci1+YC)JmTIZ(7BOzLfRGSK_rTWN^xr!BW*V4(7m4)g$B`tCG{w=p8R5JJ&m z6^)0@jRUEl(6i9f!JDC%t)Y|gnoj;6(8*qqQJLr@6J2bszonn0-=uvK&xrWY^HncY zMWE?@koH450BIfKa($NDnJdo|4_lyk(Yf_5?;-v|&k)}@4k;6V5c-z#T;5B3mU!z% z@K)lh#8cbAQwM>M691%_XV0RZK3}BRzo~pN6E7qlDBq@E;djTQ&Ry}le>Feb556A6o~?)~3o55q&8VU{@XM=LRCiSW zsCw_31vRH2#y!QYpIAG!_Ehxuy4r^k1^lKMsla*F3J6qry%b41&I5d z*AQ=LY8cdTXyfsX4>ms3_;TZ0jb}7n+4M})ADcdH`mE`rA)gM}gqX!`L)(T%&CSg% z&2yV~M%?dMOBP~&_h{+aQir(TEiID)9P|5=mQ9FxP_&|C#j$`>0q-E@{&5{AcKoK} z@s1BWKJNGw(2N+4^8xoEP9?>tq?qc@uXvy2bho8;6gj&>bi~^NTu7#T;-Z($z@UB3*}c1Cqpno(7&b z1Buo#jz;=GuZwI8U285r`t4!hGe|PepfeUIjfKuN5ox+kS3vh7o8^m(IZ@1K zO6NQaeHqD|%Yo--Acgu{=&!v1eM)-rI@DdoThc^9=hjS3wkCH4jNCM8(+->FZX)^- zni+~itj^QCfW~1CW>Se{uVh7YMRPS^Li5DtR=|FM+Ll^128jNLZyK>_PXN(tQD;%7 z&_z?!1a7pS;zJWlCSuf2F1Z%tdS-GaM&hX$i5DjG8}cz4;~0&D8V+kbtnurBBLRy6 zM+1%p91nO1@HfEU0j~kx0K5e_v+2yHvjOJ<&I6nexDc=ma0%ctz~z7|0e=Ae5%3wH zp}C>CKcErN1lS$0Ctz>DzJUCe{1$}YY$*bi0D1s=0V)6psM1mc=mS15<+CZDRc@-> zGzKsZFaa>KTCWCzKORGG2#E0Y(QWCh8IR2h+7nY)#8qC8oVOe$G1E;%td zB{>Z;W0sN`yCipm-0;KQQ|CqOv1$IM0|J?m3#mbJqp-8s zksXsdCv_eGSmer#f3m#zpPcxL0Xz%%6wtT1Z*xDu0Kh=NHh|p#djR$V>;uSy)`igVErkGt z6K=uM4s@`dE#-hpKsBH@U@Fc|sn}GpX*6IgU_4+VU@~ATU>aasz%0OCfPDb_0dOQ0 z&Q_VI^r-pJq80)Oh3#>Uk16_&*o9iK)=hdG#Q}bk;sEQveo?<@Fkn(NCE6db0B|zk zRKN|QxJ=pC@btcYh-QEDag>!L^$LRuR;!K?P0ZY0s z=}zZ7<>chy#I1NvaZU-&*LptZ?|{#8Hs!pZ`+n{w%&pJOJ2&s0{CD#|&i^F;ZN%?y zi?_w!jei_Jt?;zMxkYn}z5$@~b7Cb~C1rqKB^4#rC3PjE0Am2-0BcJgEP1%((URYk zJYGWQ>|6(X=Q5lVab)?C<$tXBV+F+$dmiz^52!i3=D3=ZYwoGLr|#am`|2L6dmLvJ zyioTB&MEi|XB13NPEYO(_-69tSlgrh4JF)t#`keZ_`uzHyfb#lEgy3nY?+<7M zGyzD+O{kw(-&#MtetUH$&)oX+)R{cF4TTK@8wNM<**w?w!wIAP4{5xt@qxyN8~@t4 zv2jV$RZYKddamh{rcKV7J%1hY>X3QOJ2kuK32YqJiBo*Kx0JS&;S`@_%NU&FGew`{ zvuyaq!!LKv@S#}$gGS66F%Pf+r}>;WV)cl1Bls+zWj8)_V{}vbO-Y>TvlM6g4D1-( zF$U-QoVe;6tK>`{ROgf1aOPR-XLHqAXP@G%vxS=$Zd$bI;7x}CD3DSdP}|w3a|)mp zurFYLfSmF3DbDzj^L)MmKD`v_d?Y&WLC*JCj{j4VbAC>Q4tNsMBhcL`O@;1D>37gm z-$t4QU2>|{DM_!S^F}DmdmQszBovf#9?+sE_&lH^@OuW*nMmPzK+%)X!I9|f2}%*{ zh`S@*_cW(J;+N7VI`#TJ;@={T)@d$&DJ|A%DSj!f)ae)ar4&5_o%;{ar=cTHKsplX zIHVJh&OkZ~>1-sj1yJgQ&63g&U+1(Mzm%F`kEA5$szn>O?%bcEw=oYwdKu~e!+Adu z{Eunw-;Oon-_RO>!~brGeh^&*K1Do=_!04i}=1(d9bNU7H zA5IsuKJ+Q3b(nWx#}Ip%d{20M2RQqW0m9R};^oAjGx1A0L(JtR!as<22w(V1=U+NM zc^5cA5?LcMhGfgF0FfyqH%MNDe7F)kmw4;f0L$txtG~Mbn)>B{?*moc+^{;K+G>#wi>Ui}UAH`f24{-*jL z)&IEuvHJD(Pt^Yw@VokVG2J8iS=Z24$C8z0c`_FzTVrY&R`roZ19Z1GY9W5*q(>CHL`VU6raQ+?1M(WZpQ$9WizVm0Ke}$afTDd0jOyt;CA-_Hb|B2p%z3qMY4I=#~o?F*a z!gfo|4on<+S-+(i=4AhCuerB|Y|0TlqvToj3p;oT_UY`9J2#ikmWkk(TL+M{Kxj{h zob^G^C(YguUZYyPLT-Jd%z}`s7jpxvL9?jwP9}?@TZ8;Ioxh(x zUtQif7y0!5oqhOs8Lnxvx)Hzq@cU93=O>o>=U<<$^QD|5?$fDg*H`lME&5vSe^1wE z9P;UVll1T7_?TCJ{oXmfIDbJ<&UpQN8}jK?UHO|9l(QQ5yW?iDuIGAOJEye4huZ({ z27SLLqF+;eKE$cBOX zvs%CRrvRUK>-;x@{B`=hOOsswdVP(e)Za%qEspB50r`ZVxRHM;)te4frfUgsxpoy5&$_@(*|(Rf>p>jHTRzlZDRpV9Acz%SM3mazOw_`CD# z{dOggkE%zipHXPT*SpuF&=0i2OJ* zlb7-DD>}a&*KYYYC;fV^!+q-CPf9s|J+9q;`+k{!y#e=$-hU$f`yC#)$Wni;8V~)D zPvy4Ym+<^RfVX-2{^6QGEWkBB6|KfE^}`Q(`QME$=kj{>^z#!s|5nX^lDKxq<31X1 zC{q2k=;u$+^=!p8NZb64)%oqnC%&*;|1JyavjO=E59M5+4{=THmA{2LU#_DonEr1I z#!)Ns>Ae{}xSV;oCVa`?*Mf2u=;yBs^4oO&w;Q;ec3hu~j%@p`Ix;uvr~9!5(w^u< z{G$pp^4pM~i-&%z%jv*1 zsu}%I|1Q*cUWe<$fS9&hBdmZ%(O-4Hue&XRhZ^YQcBbp$y8g*KP=6G(`fl)S-0umZ zr*fCy>yPVPjsNw?-w)-_`z4pZT|ie?{)*op9po=ZKK0jex?QVry_V|pSQMRv-=?r% zp5Su!)BTG_)Za-ue~m7`9oK{x`TLz7FV`ZUz9)a@2K8C3@3(0@$aCwEpM{HW1@+mW zzq2gK^-4Yo9OJnSzm1}q_aGC=Ub6a?WhmRS)kuLs0Y7yu6|D5J4(~Ta^!D|%+)V2K2Ht$Yr~(pK6yd; z8<9`-c{{*c^di@%q&MGB;<`VcTZdn;&ZtS_bNOFB>I-`wNgy?K&dBbDJ*j%;5Qxbp9`b^4oPelY(-V>F4(j z@~_nS-w(=PuJdakq}_IQ==>ifIe#^-UAcU&)+Yro8*!i7^87B`FU^fue>rhz;gok2@iMZb|rBgmxu8?Soh;Rj*LnUs!T4%>hw17bUC(oIP2ZEhQ+59?3-Wi<_+O6vE9v2XMA1(8 zS*q)E?gxH3&m_5>%Yyv#bpCSWm*V}6_$4|&O5+FrReyOO^7}sz=r*DA9}V!9L_W2n zuENJ}3-YP_J#_i=a19cO+I2Y>X#6b0HJTpfeZ=p-sLM~_dNlGk;+Ohipx_^;haZdU zDMe$S1xd zfA4DgSss-0^CUmtfqcS?{C%M5`HtZEr*ym4A)ol8`P2HwQ^E7k>w3y_8}$8Zoxc&+ zq|dj&`bv0sBFXiU=Ua9Ds3Jdq9`dPuZ=&;P9Jk>bkC?yNx_@s(KHZnU4vmKnU9RL` zs`0-X`K}(aPCx%B@?HG=GU=DQL6`Rqh}iw!M=0e$>@x}x^}NSB|$wfkPB&X@Wn zahK+gxdELl(B=Fxz;m0K@`od$=yxddDg3U%??xp0 zqhI>Y=}1eE_D7=c(42vEWYWV)hbFz7bZpWONatFX#JmL|81o6kq$+I>D2rC)}{B;BN6>RnfHA)?EZvnO2MP* zy?@5@=VLAOB7AHa(#1%ZAYF=d8ItOkaoa9FvhA=VGIhs}yUZUo^Oyq;nSpMhK3RnF zs84pq@0qmDia+}O4*q*N(iKQoB3*?Qs!b zvy&JZh6?_eh_R z(wx@HE4Hc1DxMIZ7;mhaS_MRnin5Almr+JHu%GUuqS_+9KN}-5dnv~4@G`99M>(S- z%E>Lq4?lqB_QT6l;&D_szZw7KVkfDBqo5MIK`3|Qk4>$T&t-9;-EBG9-D9)M;&FNa z-yDcSYr)NOks?fI?5EB5W|t-LWI=OGK0mu`Y87S0vvrNA+J*FGDwHmYOhFjt#U-j; zC1of;zMCk*(~OjHD5;0NEQ)^}@06CsiO1^YT0e4DVI;GHdiX{)c zUYr*Z*;In&(X}2;r>mMJWdB(`2vg|at$268;@S3+sV>J-9mWHZm_H)yw+pzB?j}L1h$uOU5`;Yk3OQD6$U;H7z1c4S?b-Tk-DP zuIvG*Wll=*ja4+Z(WO37<`FepqRe-Py6)z%4vHCNszb)_X4CkwAIk9uL#`bRd3G?& zF5}^l&-e$Q^4V~M}p6nktwP^q_t#l@T2_Q>h31)hvFkyD17- zvCI`0mbohG$gB+nWN!Mnz{eX=y(3VF>YWi*f@>`m3}p2 zrW;v|16QtO?A08<-o%lddZ%(Ew~+<58FAeVg&wAeLT-jHgt%L})KQp?mkJv%vuwMk z+nc?FT*{d=U=v}jBrR2BY=21pK031fZrnVhbl93ON>gc2bKDM(LX!__EaD#fVpX@j zk)7Hb=w}+A8R`6U4_4iy+zAOHzaHs(A{~QuanRkRcSmO+-jHMQCK`iue_Awir3$%H zKrWbyRH}qk7g5|(v<6FVVQ+LPYZ-q)yy54hpQ_PC|G~JTA24y&S0US3$2I!C()3-4 zFSU33k{&8{rvt)1Fz)CcgeQx2mPC}*gA}Dwr(W^^DIjJ3aPLVf&u$f>nfD4c^K#a* zyG9JiSr|}PJ!%;mD}}jMDg3P2Ig#$35YT!k(cn?n=R?T827CN@M6DPrcS-O-vBEc6{b>m)L0l2(ZBIlDOX`m^HIjE%Rp6 zm*|JBQLe)|1R+t)bLcl3~B>XF;PV!weU(!hko$i7Tw#Y(mo+kIy|1qFG*&D zaG3h)$G@GFr7C+8Hg&{OztRA7CKy{PYGsJB46F*rd0JcrEKPHGMM~LhmJPK`hq8cQ zL|393=ZQX%Z;4b*yxH=(HT24w4rV`MboFVLiM5oZLON?KVc6A1Xy7Rwg#J?{Bd}UV zV2$N)wW;h3##v#cG6?#(9JkIL1c=@s@}5RZI<14nkwdMJgmh= zLbVs`2sJ0|tPprE>Y{?_umqYFEV&HRnmUx7#gW-ek9n3Jtysb5H)nj!pl+uy0*`jU zd^7YKSb^JX6+WW?q1!G@8UNMHpleLCfr?r)nw5p;i*>UdOP^zI&6O))!Dba9)UnX5 zaM2g7utW1oAX|hfv1~7MY;$re3^U3z-&b_vvO9MmYKHg4@cDU$jU{-E68WMr(E^SVtLzJe|7t*&ho#9qlq{GLR+#Ur50x~C?mL{`!;B*(cl5HENW*jV6 za((fY$GiZ%%&u`3xJ!(2Sz;_?I`c81W*XtpGbVdXr}WTMHu@fB=&4ImvRP!S%QDk< z>awR66zZavC9IU$hx!^MSOE{@Y+8%0bRm7FmrS!b%#_erD*n+sbH#F zr1_efWGE)>Vby1GL`p3ktHNl`@2GtdH4XH&NLc218EI3qZln{@<-7i zA+5noT0=w&9cs(wlACP?3E5#T!)wv^6b|X`aD7){eT03J^`nul@E)b;4AmS>s_dAM z2rwnbO26rGH6b5o=s{hMcithiOrWRfKNFoB%v~CJRb~3HL?9<&iy@+4{=~?CIey2)jK{J`p{joGb~oX|a)p?zMVom?N*I*@k87u5(rh za@?;vbNsZQB+~H}VoQsz*;&RR*GCzkouS}Y&&9h?mNQhtdT2?eEj}#E4C@1fvFrXy z7F|27J1uqy^Ai9QdC4I^r(V{XcgvV48hSh}3pjz?hYFF$jQ?QyB1+t9g zPajvLVj@Px$pAJI05VM3c~$4CPc-N;jz>sD^s_xGBfATE7E&|{8KbZ@FubE}xJ_X` z-iV?>(o8s;8yu=~hBy*j3EQC}MVfsf48g~?T?jpYs-WtWIwBpi6vm{b21wG-8ZeS= zcuNksvgMNcWI0!!C{X#9@vt~87zVCGECKAtj-^7&f8f+$YAQU7#~&7JT)9-@H&y9f z)VrWiZgVLi#eSnKL>dvM61@;5#0krZxmPe(X6`ReT9!LhGe4_gQBmuPir!|xDV5)> zJ_y0oF~3c+tg9D_lG_j-TvrxR4Kx}J*%_v7sLtdJAX(PP0tobFQO4yojaLkKkRUkK zV~Mbh^+X5lTo19wDZ`{iW188JgJgF$Bn`5rVDY=K_!PEeNDHjWPUJvmb|R;+S}ZD{ zbyvbe36@z{o}+$bqmSr@X&JBkIa#GK+?S}^?@MRa|1Vi!)09DoByI$|pY0ERqwW z*JmZ7SQxtK#{|*e4p^oaxZmE?LlHg*V-x|V{GE|VAj{AQ( z#L*qdI1*0eGI6r5YQT5g?E7~+ zN%|d67`aO;s7t{kyoCygv>_Qf|bvg`s z!%1oF>Rf0(=hH#t

{TtKm;gjuZWQ>gg{ zvC4XYmKo-Ux>@H7eBH59hv-#IBE`WLQv)ZDcz1W{PI8YRR*Q-m+R+ zgcUH+Zq2eQIpTZ{Hvyy3q#*}lV3>BfT2>{SDXPRw;p~q2Vx9ce4Se89Olj_b^9O&} z7)1;2U-F4Un^4^<&c-C>U}H(uman| zClB8M%=ByxKC%N+G;=Iu+DBMHs9>WFyaY4QGI`@Tk~lP2__Um&iie2)Pb5K&GsRzB z2Iygv?!wQ*aumn!lJ2>a8@CTI&81$q@1;y`yy-x1ZB`GbJa&R3ll62H8%r4tmPPmT zSu_q678X5#^^>%Hn2}yKuM|7>Dbb0oPL#*r6t@VMTVcnQ)XeU;QevgZ*14Efml9E3 z64u-#_DLF@Wjs22x>m1{#L4AG|sTS6IP zdP)(>P)jJy|DF7iD6NcWt0&V^FPDtV4K@^$^!z=-fuoq5W$mJEy4WUi>O!Al<;2;# zP0wfCkHgA0?Z|PsNMT4vu9n3FW%uG(s*w%aj47dctN;g~Ba?}(fP^hL* zti+7WRX5Cvs{m#t_v!K4ZWe(kD$}a*q^c2dYJl0#KpDz)K?K!T6JIape(Uy?M@K7Dgl5ZTbkMV3Op1@pW zB2oGzz2c`FZYIk`6iw-+hSpR@k)i{%svXj1nyl3`CQQ!;pZ1IV_!swB^C?feL8txV7NgeU(sxnwS{QzUCoh?FxNriOQkVaP zEq#K%L7i+xcQKpJA?QRew8MRXWobj}DTl17+|zjd2}~t&*#{(C2(xy?DVS zX6GspBmZ32p-`Q4`~0SmMs(5)&9sL3)dHgWH)l@MMx=HqsF5%VAy3x`^; z-_jioMr-ELLO9fZmti+3DmRG3bH3p{!`D-{NVs3mybtWl`?}NiFp^G2_7Z+wk)YLq zQ=GyqMY?;bnn7`JoRdix$j@F7n-I?BBGv2xq5h!Wz#Q08bg?&>iK5k{j;0JW--Vk5 z{a8l{khhIahQe%gGQ~x0G$ST&Sz(~TX5%e}lm$--RvzvCbMY^nTsXvF%VBNtlgUpUSj2 zB2GekWu4JPdu5%uLuEMMvYW%Dw?Qy0N^6DPS#Md}-wsRS&fP+9S>^B5mnUHjGA(kv zdcr%720QT!Pi&!o6D%&Wm_1lXgVzp_VR9u6r6X=$le@aCM5*>;MS})NT+`X#Q znQA=If4Uq=tS``li=qIGBznb;BQdMjSrSY?ex#?k$Kg?#hBMNrZ}5k?$Bmg7`tz7e z;lYaJT^_8wCIDFPR$YX*i#?jXQ;t+q2Wjp)0)Y zH3_5aXneArkNK9XhOrLlDfE8drQ?vy+H5EfF2py{+s;<;@mSUKizbeb;#y-+*>>{T2iO3kv$JQgx`VSocF{@?w2zbwto{7EGn8|XhQX;8S0bKi@ zqSW*JsB2c|bX7Jg&*cIML(dP+f4W*^DV`tLeA&*LyhhS6`&=>H_>hrG7ELe zerA2?oXMwJs7t5xFtIhb@~59G)BBsHRb?F+Ags2L33nh7Zj)&5jwcGMP+}#(uqQ!0 z#GOnyVON-T5q2d7pNPIf3xzFAbHmd-p)|4)G7213Y$Ue{XC`(P-ozSG)0E9TFJy9t zc2ozF{mkKru&=rtG5szSF(k{R*YblxZm5nz{W7=S703AkXtCZa!@#k#iu+(- z`6}oo1C)s+DEHFtU(be{9lF$p+*IX{h|?D&^fa7QIMR#SElkb^;#Y4L%fZ8VWMY>i zGc~#-M-c3ebu-9&1j0mnY3SGJIn2-{Q(grfNfsA>qAC%7E`Ih&D%*OzsQQAu>~mD2 z8qhVyVG&5F6{nKk*6XGZ{TG4dqB;j-s2=9^`lE4fC{9GRyLB<6m%D-pSjEDueojB5 z$o{n`fdss_sg`ij7#2sFj^~RYsEO+!jvD&R1M;SEXVzen&QyHRFb%PKj3)EP1FHWvn zRE=??@KxRlPnY9Kh7s$eWhVCfnh?B%ew#Qfq5(6>VY{{;$i_0+=d)8Bw-Y7jraIzH zWwg=@G~tK04VzTAk!8wli7V4B_}H+qXa*iuIdG`qoLRmY-OlY>w&~1v#n<-Xp5?Fk zo=|hd#cT)9`3#ufk=8)wl4smJ_ZuW2cXGu)oM{9jbZ-}PiP1veoTLYzodaBCYo(Qer~d$L}AakA1@|>e~HMGSQQ8w~>1CprY63r|DNcwinoG z!2xbX8OaOJSrP*|MbUxw9^YAnJD@BaC}+1WA3O{>L`R3Deh+vdIy%(QkwVmAMnJ2} z!%eR%73u2^QK^h09I{gxM~XG+D8+$*l*Q$!1JOE;vm~nG3qtkL=2Cs@7(RO7ST;`{ z$BR10(+BJ-&*Gh<>*#`(PF|D?{JEmz9n-F*m*+6YcKCn8dFOXSnWEE&alro;+LfQo9p*#+k<&Qhv8s?=mA> zfE2CRjEgJBT+?vvzl#MG%_M+Ps;yeZ#lFv|8_u53>eg9wKta`hyICems2pGg*aQ?HV&|Z+78T zWjGd3ZkQ0lQokSpNxRLtk(#LUtzaI@)tgwLOpiFGM2R4rP~25j)5m<>YFY=i z6j*BUqWqKOGfRg)rKsgY8XCneCHl|E&KUOzA;KQMdQmDmu@kPuFU+BMDZ{v`v$P5~ zLl~VKt+2|w)}yOPVX>-uoHP)uT?_YxmhS2VC5(k#ck`m zVf>NSVzqV6GYGv6qK#wG&3=Mf2uoQ!_tQr|(}W?C{Mel`vD?OA8~8rMJs_#7j@ z6;5|xjcP~Ia_1TvfJ}mdEd zF)H5Do$wB4Q7S`wRgB)eac{Ru9Y1O3kn-lg2}O@~}~%4haAYE8$X3B9=+`fxX>IllO|CXH&LERywtB2gXYTpgcsf8ucQ}$4mo|a%> zC9=q3Jq;FcMILg;CpJg4%r5h9sjX!k6IjBhse!Kuidm2HsAG!3ZgL0~mfu^YQ-z$D z+&L6a?kB9azp&Z?!jv0@Wst9ide}dzScVo;*I=S92o+&iFm|V*{${4~VNB&M?$iOM zZs}_-aRko}Mhe9WS&xzj`7skBi!RkvVGL39SobNFJ&q`PJPU;hE~RlfX(?LfhG~~~ zy40hXf2bgUAYH>^;xr^&nvI5Qy5noqBvnvox{$_2znzxk8yQaS%Bf zFu9^^i1C;k@p8l7s9VUQXO$vo=-gKgPW2)5oQMcwq0@?y*q{d(7OHH}jlK;ULG;bc z3B}nk`q~CP$i7YGvkh8SdW;Pk#IL(bD{nAkYILe+sBsc#UuRJBhJ~-ub1gQLT1;6O zAAa#{a~=_9v(0&=&1RHg)X3|Up+>}Llc(te(d8_)@q1$}-y7!`P*I`r&LyxmK^W@9 z5L>W$nk-{No$ON@VZvx?P?V$^x~5Z&cBN)%tybNGrY6stc5Op?)V5ZbPq%!1hRBVX zEXilFO=vsjOS6eZY;TzuHVcY0pA)j>9f%jhvKeqWRwd_heR;6WBaUhZ?M@*xhHl3E zbrt^&OsjRyRo8Dd6^d7>L_Y_3R;Mj{e@!rC`_u+aATgEQJpu(h-?B_D#{cUGy z6V802sGy%0$eiE+=FbcHCYdh{XJXP>B<7fdc-nff^hieCGDU$1Ey>wpW5!W{X2^mT zb1m=76W(WhZn-vU=}}o~9Oi*n3x)R~u%^%Zym>1XLc=h1#wvI8ISj)4N-ggzvlt~c z$DSpOi(b0s;EUxhU-Y)p(1$(NOvA-4D;d66?KBNtRb#$u*5+IWjVJ7OYQ-1(_Cv;)|A(YrZ%%l`l41z6fo`rNtKK5?C89d~rmGEi6fyEW;N^ z`B~IxhfOmAS?3%Rs;GLQitUl(gqnSQbG&ITh{nG)L0IEN_ZeP^nB;05lVu!(Wm^;5 z)Doo>v@&0v#>&w)Y>(eo?D5mBIerFn-kHpKXA$S!j*1}WFq>yv;KTv5V(tpIY$xM$ zERWuSDlVKZl{FKmBgX9T;&~3oRfdF}gclQ2R;(ARP*Nn;pY$AGNuk~7W$VbkyEC&^ zW$oc|)je&$YOcDM^pK2-y+ z8k0G#m9X`^Tt=i945iZNomC=6sx2S?A3vp4Kds$v4L>z@R`A22V#ier`!pX=kuB^d zQmgxF?rSw)Bk17%q`9`q8tL>OXl;~;b#PB#tdDWon+R`A7o|YS8pnf8`L`1mJ4ub6xbr|yCl_H9qEB)Omi-Qylu?;#!q2elVxNGjFQqA zS76Mbx#vt{;Z>eAFizS>$>g$~%jsvk^Gm~xy-^=U#El)63V!S|$sIxtyCdBvop!Fz zJ{2prHsGCngD2T9RoISQL;>E_VYfb-rBj(tL3 zhkgCUi2Xzl-Jg1wXR`DCjv&dsAk3o4`2i`J7y}DKf~ME4Ljb5;y9Aj2QdVT@v4g~a z0ImVV^A6EHhzH;cK(iEh04O3;IfvU4xX7=Im%$N2i@siPWEyU-r)5XkdDvo8tQxgS zk7^^)b+pwMj!CEr9!p|AijHFi;CNO5P9O!~MA=m=YGQj#nkusQbiEe6#Jj`m>u02{MxTkt9Myz0i?jT!iE+w2 z+gtiS$A5$G!Ez_nrQgx63YVuY^#9u^9XJ3hg;Vz~j z**{da23TbaQ!h&k#GUNKOUq!&#I%c_@_C4zcHvq7mUaf@S&NO`2U94OCl)lV3c!A5 z#TBE^+Rx1D53T+|i*Tz;qSetOM8<3PKyM~SQ*>)BGn{v{Z*dr78UI-44k%$9v*GbP zMya<5wG)VdET$(~t~kj?`(y&3ENkQ7%nbhnQRzxfe>ycsu`x;e)=4W$wezpVgY{+x=J)9fLRAu)f zCWlFtpkZe#F)*r3z!*qN*xRxQJF64w5#Q?1OoMA!LTiEhWXg6%J^Bt&9fr z7912u!#Tq-aSmbPA#eIcg9`>O86(=TrKVpzb?V^{HRW`~lFHHlXdN3%W%dBjFt&t0 z2+AEstJE%Mw=2mki_K z+`_D2IF0HN#2ZF3Qy9etm(i?LVU8mx{)!z?LK8oMCyy8H=s9|+-!^pOJf`n!R@Vh zns!iM6_^4GOp`bA9fHC_iq?(>eFqT8eiclUmxk(Z{ng zemvZy<$v5gz|U=wgqi8$vl+h#0(aYoD14TXvxQxENzt}PW%_|ZPTeo(TH5X?}O`K>7pZJ`zcdB}oof2WHwHrzYtFK5fw}yHyq9`RF>A&e+I- zO>|aa z%m4pRa#|E+?A|m%lbjES`}f^po9k{0&kJke9R4QEiv|Gi zYj-=W*zKtje`F@?B_Ar#!$!2U@!LS~2=7j8vL|nt7cM|LU`niVW`E8O)*2C!teMra zCfM6l3q;k&)I%9B(qfng`xb}$b2w)XSIIv}&;7i6_Bt9Hetz@L_mMzPGs*&KG!#-7fhL`6TE1=GBu`&e zWMSE7hWS7GQ?$lR{i!sbjHHt~2XTj}orPF}(BBKmW;355MZl`5VdH!joid^3!RcxU zRGlt@?{wK*ha-i7&s}vT3~MV~eyam=u%MTKqK5r~>jbPRL}~iz7*85f!W20jWRU|# z>I(xH3W&JCO%-V=doNAI7$@p7#X@01;Mjv2)q}E!u8S5WGV()r(z1nte|-{?S(1n+ zQ5s#%qRVjXMn%)HmP)Lus1HeH(IBU$k*F(UeNmiYNMGcsV~A(NJg`XR4k*2$MXdLs zE!K*_bV15QIYm%jHvWiGO`PqEtaAhFveU-1HWah! zQbLGKFe1fRMTjipQLc=Ha5M7h*5Gq9(QBL{GF@`u*H&A1owuQ3Q4$Uv5`lH{{h7*=Hssr!0v{}+aPPMz+dV0z_^8qO9 zG$nA3VYX3Jp{MCJhc3^{IjaFYKSrP9T`neiq)RAc$`Nd@}a}PQ1!3+c% z@0Kx;i4@jmtdF`30c)dacrGEC){>m*yE^IDvcn$CLg6@K^T>I`=@vht9zQ12VcAH? zvd8%RTPtCRDW!Coilg8D%?*SWt0bO?H>$}b+D+FLmSWSiT^wh$bS1tA=NXIV^m3B= zjLx}qdLTt!hFDdy$6yuTaqV72uvi(Q!2{FQ=2kQvQbCYMmvRc2LC2ZRrL96nA|zhy zG-%64I@j4pGfr+}1XVA3*y60t6+DPJs6i(%`} zz$@s83#Xfsp`I3^d^59Bl;)6=s}LD-R4m=4-0&0sWxZ-U^Iy*}GLpe&G$-A8&Xm~g zKsjMMJ)8LN=}sPZY4BPXleFV1Ed@Y&__ly>>E8crXlM3?22QY|F3)Gxt3XsQEksm&d-fSAvN~6> z7#%XNuv#oT3Yu^}ELd1v`nwm?Hkc%C>bixYX(%a`O!DS5gOY7tiaE(l<*_{E^72%_V)I2b5LN@?#EDE+PBm=pfd8M7J#_vGCFRzy z2{@$blTRuI_||IMEq2M0h{!3>@*$%2&{M=`6#j{eOczD}bhebrzgW1YW^Pqq6p!Hd~XQRZp&t@s@`Wsn3>{1XRN6`)ary!Li;U8w1 zl6Nuy_Nix(UutKAeXGQ$Lpvi!J>`(N|5`fy59=m((Eb1FD2JMThLJiZGO}r>44*T9 zg;HgU_?u;Ep5c&Lnyhju3#65IVBlYoQsP@Zz$O08ZApeh()7IRH5f;auLw=-q4K$P zlW<=v^hwlL-E&!WCpTfoCa`60!meOcnmsG|#XSEJZPPqO9Nw5aaZzf_oyu{hjAsu$ zW%kg^$|$T4lH!^cC#<`;rm&0y4|s6rPOvq*ZKg9L92A6()2{8bz>X`70z0~S{s*0$ zYU^8WHBPu8J~Q1?oB(AGPSPU7#r1#5IQfDD!xy=s&xGwqS2<#m@)sW5PO^))if}&{ z38d}5FTS|I^o0dQ>jh_P%S+ANI`#=ovnzoeki+V!sUhRi+10^c%k0(eBOeDbp;p=K z5n$abRjpFa#N)MXiLXi4?Gnom?DzqX?a?bDr#_enQZ!JS2dPc6R{z}0I){A_n`KRT zqys1?1o{u$59lY2=XEM8aE_gmIYJ-W{EpLs?3YXg>Xgk#>5M(DQq~|_f)TsOR94s# z{2YA-m$pySyvP&~8uMM%-#y$lwb9stLj2FQZ!q^0_Yx)>JAVLU>w4~)W{={mGTv^S z9qta!8HTUZe$ZUIP1v3Xqry?pHbXOeBc9FiF<^4xz0k4^#@}qnp|&(vmjE1Qx1zs) z7&a}tCD^}}aJFa@^%^0lt46^`tYlP!!)!X@y29n!7B5-QG~|mch00BQ6MUsY_FTgr z?QQ`FHCy~in_$wEqNM7yc^NL-lFbgKghpfJq>s{m=HB5`aOAe-i6?5EAVI!q!+0q) zz!yXUKlPPI!8brC)~8qT-hM3cR57?KULj_GyBrqd#PEW*ub{xTW1!6xjAGZg{~UHm z+AMlXxdab(_Oqe}2-Bqop!y&oL^g}73CpbY|Q1(RG+dWAJG?UR} zse<&B6D>yKT2AF5M-eq!&1Xz>w`oqiB_PO&7Q=@r*;p|;d<>z)MvH;B57mSNsLik) zz}Xz|XQrWbd;t5yP2@9NZs+Pmv;FE31#eH4N5B|!C$9Q{Zq1P(COgP z4&pS|t)72to++OZgZ|mc&x)d*oj?hw`7V5)gAnX$#+610Rd6@2bMVUUZUvZ-i3azu z*?z6|bl5)$wY_|ay|>km?B;chJNov%esG%ooRVbNj8T)u{Y{xFeEWRIh^kzy7Kji# zz)|(oorNrE4|Lv8?njFxV$MOvn53RR*j%c|5Oao?Zw@6nNX=fON4WxUu`9pZQk$+CezY%skD-Yd)#6xcrwuA}oYU*T>+urB z=Y%la&xv+qvcNjY){z3hA|#EFC0~Bi+*dS1PasT<^bS9BvVA3rPI2!>5kl4oFC!{C zO|dQv&h{7$j3_!iMmfx1OpF@vIj-FqCg=+VreUpwgQ`(f8jD=Q_Sw!8R80y><32%o z6qQEmPJ^GnvNWdU1L>6*0q5BmFxlg>>Ai2;91*c-!}+!}bQTR2Y9gJ3W53H5kPDq4 zH*^?|tpneuvv3$q#78cUk$!gxj;^tJbnK0kN>+i(2!CMO-?8~%3Uudk_5GL}5OpJ>{xB&-(GL*!N1hYyctx6W(Lbcf-((xChF6De zu)1Dp8?3HZ#mL+5W~VaL%SvYdFwIxc15xxNe1qtSdh!-fmOfiY)7Fn|S$IM?Dd|S5 z(-laC-0HnTU3?pIvWod-8~*QhL^|>h^0`AjN0o6ubf;=Gagn=%a;O?VL0$^^jKN3m zRvl?6@~1=$MfUn<>Y9rEIsQk#Ytj^j;iJ%ZPr7?iv^HiVQQRA|p(xhHOe~7~oGv%L zalbkbi)}~0!1-5%w+C>t75zRKW2?|ZF)<50?3|wUNGzeA`lUKG>sR_LtzYZ2v>sKb zV?BljDfew9eSV|LCEecNBSybbzJ6#W@Z)Q4-S(efhhaO*h0|6g!zkLr4fJ_%;RpZqJDL#TTh z&+uSo4jM&&b4rP#S8!#>kt+6gH-j!#1jGc8!Rlx6xdSvv=sqH0NEvKnZsCp40|oon_@e{0F70qUe49hMe8<0jOPY z8bu$bggN`jyryRU6zAq+lcgHRIQqoTM3Fik+o$G+3V%c2Vyu1U1y0+f!>M(e8kn)y z-mMoX^Ym_lcynV(H;x%}Mz{aPZ&EJbXg55A-rne3XdLk~ z%*^d1V-Ee7>bHaWhN_1;^MH#ZibEJzB90>w%1Jg+&GRQ&JNc7WHSso&AU+CqK?@k%%Z;B)8GP9S4PKPZkenx?=7Z>eb_v)uRF)skER%ET1^-t zNj%?_fMU4>OshqfBD||RUtK85_<`sKl?b?S_TfWr5NdPD5>6u zSylgVs~LXXDuzcGz3@nj7E{JitN|`&6|aqBh#k$b!j2&qcNMagRJr3=lRF-S5uHHV z+=;B8V1CT%hbRgv{OLDb?dhAQSxO7~mYFlD%aeIxbV_J|I8_V~r}-9#cBLkfVt2aL zK9p%ye94&^5Rc>SvB{t*SWl z2>Lpm{OWui1uC>(XDg`&*7aI-TJ9-S-_uGdX1ZpO@n^noats~csKVA_va4%kZmiH@ zYj5&m<#rge$x5U0u5wHm+CqG@38b5LS;q)R^lp|I|6SjFX}wuh}%If$IYf0 zr_MQ2c9a*UtSs^*-t`l6=l3?2EDhQH&~`A zbEke{%q8MRFJm<$U93a35~~-)oTU*oEsTtn`U%-xCpe(0k*I=463^_gDkccG;t7s` zVJ3;ZxTOV=IfV{Y*;lCRiX7XnGA+6B$DFr_3*e{)_hn*G{+VJ{M<7&TiI=;W4do^v zpRZU1>tnEEP{Ye!4U#p?cSsFv5YlU8g zQdpwZnH34tAjy z46hrH6&#q}7)K*)ygY8QId&+Iut}s`;J{Vs1G<=^bPsiwV#qa>e--!77W)!8i27Wc zak;b8*2Itql+i460eb0@hqEVgDj)Z?nk@^y!MM;757XAsAs?m~`F!X);D3Irod>uk z1&l33-oegT7b9Waw5!TihiowVmNEfK&<6KQU2Z$(>RG2RbetEgL5P)*q*$8Ear~XR z84(Kugf{6bPSYzKjkJwlEiqC2K*iT=JT5ECvA%D{y>uLLi5iKu)dMOt!Z;8jZ8$FV zMeJE}*@F|vff)@pE0Hj*PxA%J?@QIP+@-! zYH{$@_N8r?_!T8kW7Wy2BeEbyKOtZn$>4h5Rayn>b zT8vu-&X?X9o3&ZrWW8LchD_+2%>7bOVPXb_ktA$1p|rI%^nqUSwI3k~?iEzh5(QKq zdl67b#%6{Ai~X^0gJY>?BHX3BL{%J$I~DXo%^1WUgLwiAKt&~VtIT}~o^#(Un7;A;zPwL?;4QnA6Y zne@_D%urQVT!+*-1T*Ikif#mv;M9QIz9j)uQra&XDTUs5WDM;|b0iR*x#L_WT$0%X zLjn=Dm@Sls)Kg};wahymKA}V6rbSN1s)ow5U)3<6k^O#ds<2nndbqlpjzC)qEV-oJ zN7+Sx{;$d^tcs#crr)2E(i_R3`n=6UMr+_z+!7sTtgE z(Y2WUh?bRUZ|dgvXF2^6GGw3sc&8Pl;C^%D#??(ZsQ@TV%ZIiI=NU(SXfXECy?OF; zhLMmT*I!5aOk3rQwfVPXoyr`s#Z{(tvoB~MF+B=yU&xaJv%8|pxbHkxd+=B-wPO_l zJ2`H)*_s!2%jVnYh}UormgQ?1iWPQ5(-L2$Vp{PJsItY0L{wv%UIsmKS;UNB>b7i+ z?n=ZBweACckiuceMnds6oVGwi_4EpVAgjIZRE$I}pu;1SeFho@FI&Oz!#QQ4YSGi5 zn)I@~DqS3HSg@%88wsY8d$UTp&0+AnvG>K5j#kp6-qO1W&q;Wxqg9HuJ>e3TNGN$3 zGXr|r-9<;`U_)_QG={+`Y~vh8tl2PC(p@$Za-i>}t*4Tprm|>zcXNSmcI7D3Pp&jV zSS!^W0y3rMEMmZ@ToNFPa9I0hC_;j%VwHmpZ2roI+$IZLnaoVmZ&?#Fm);wT?P`{s z8FQ69_^Vv`TH3!=?k42PY`ccQc@S8;cwQk?`_WQOE_idf@ZPNB_y=XCg zxw{%<1i%FA_puVtgo^%#>J@(+U^tz+Y;>)o0}T$8^FR|5`XEgv>iNMwvkFP#pKnj) zI*~r;j9u7K-I1-%ji-e%!gQgG#vmtN_y6 zCsbn}Bny+%ry;lYdz`qngPtwxR#RO_lW?bI#%|15Us76~Dx^l!ckh0&seuuLK)M|H z!Tn+NLfo~o+fBL<+Px>OTt(mqY4StWBU96}GQXbB}4>Okk%crEChkk<(c>`=i&y%-^*^UZ zTor3m{t^*Pq~I{0OcI{FARHbL9%bMv{S~3cjuk#?aGLc!XIwaOmYMmc?Q!~!<7C1_ zBC${m838>xE*}Zcg0Ps)7gB@mIT5J7$fbHaK~U%_5p?;1d>CD&Jd)HA3_S&1aNm^9XLOY_ zzYj4I5|z*INH}g0zjKk{D=3ymB$|y&BV8VrB#p+hH4RFf>!ijeH*0g_y&RY4z*oxo=`EgDm!?x1+)cw{-u9)|jpS7nZbYRPpr*?gpve82?YLug!g@G_Uzf`NHQch_uc#6FXt!iy{4~Ovu4ejnKiT1#_l{C zEX;u(Yfp@|0JbJAabJnzs zK&xKk&D%=KaW9smO01PN7njKotOAmkiF8lcXd|men_k~#Vn1>movvb*=8Ew6N*IhU zri!NNjA40PXLEB@>vEO3={r$ie{Q^WkAYEM(nC&i_l?g9pf>&F zbQKOMRam0Sr8-f>JOpQ&bsmx$&KW)6)5^aD)L(FwGLruRnd@!s!J2J;` z>uKW2Jv#dOoDs=9DsI!E!T-j|P<>~_C{`3{QPt5J)Mx9)#LWpQ#d2eVWR}V%7*~0= zZWDXO)c8aQXgMJ!5gZfaeB(2B_PQN%Bg~ZJDDfG*sTF4K$Yz?3qs`o>N7agN2hiu| zX2g`L3YcjF?9~N2&8AX|#!ycla^AdX}vg9~Fq4tT#)(Hk!%k5a*J4lZuNxEqbe5d5P z`qJcxw6kAjqX3HOY$m!Q3@ z?fwdz85@Gxt?Z3{v*~A;RLyR;>7qY7q7h03zl*gkqpN>ZxUYmZikb3 z{tT?GkK^#l8+)kjRD_w3(-2~gUGPj_A|oE{I6caS>&&Fg8S$~b=r$Yi)wkK0Y|f6d zHf%|`EtUR-t4 zjND@*J@ismDzUtCS>)EVy4BpwzWhnaW|p>nuvB`u8fR#`|p0xbacP8{!N=L46kSMtGU>C`y&ODLQw^ zOKsS+_UMhh(Z-y0l|bHTlRRN_TgQWhw?`)&afOW*50T)OyK5pJmM&fNPC3hXSBzL3 zaCdxG@t*i#qQ0R6A8cusNPnJ^&J`dLO8F;v5m!Q?p4g!=1g8T_bVdF1tqb z<>gKrrAwk!k2H2HsTi)c)ItYmKTm$xRj=TgEx#Cb@DNTB8G{LXhDeA}u*4|pZc$^p zMaeQ+#plK~8SH3_>e|s(mLt2xWh1Op8tBf@`Oz41Xyw5e$_fmpUGSQWO_ralZIY9` zo~xF*)hn!qN>;Q9m1-=NN}5Vy)ky)LwCmJ8soZ6E?6L~gEnnGPlAFGoaFrXrwsGwx z@Pf8Ez(fwvXy;AiCO;gf(Uwo3ciLG0l_I=0>AzCs|0XFSimo2z6W>qJoNSGuC`l~$ zhPn@=Odr7BHY_Bpl#^q>R%LL*R}u!V zjGrOVH>}nqD3q^W1;xgSo+iQ2RVywsvlUgw60bIir5??3ypp4NeUiH{!kXd8j<3R9 z=4d7OuDj;xM#IwymAOZk<502`V|bqA(x6h$wQE>YQoNa7le zcFCX}9gerg3bt34E14S`mz^*-x=W?z-Mx~R8>@M_Q-1pYA6?jo=y4dVA_gyFAexRkgxfStae{dF2GZL0E`IP~RE~R^&AKw&M8(!6CL4*3QDD`}?v>c>$#`MW zZcV~V?<(|3%3X+NTNxd0t16YvW%Cpyl=q)rL~eYgT$xZQS0+}E0MHcm)OE5M3Z^gxM}Vnz1ejLM7r0i` z?#|4Jw`6AOVQo{rc`_?rd4}NMj2r1@eArw|+bt;ZXPb(cg=@K_aZ6ndy|h1vNZLNX z6);RJOwFwp0rL`-)Z2mf+NZ54%@_1W!}GrMZ4BX!Qn0PvRoTvNwk*^$)$Q2~X18Qf za&X>(LT9nw9ojLjHP~rM+|c@~B1-LKhX>6~OA|c@blRDlWV>jV#J!&8^5tdvx~$zy zYNi!F*u4SqagnF(%HqA8#wG~C;4`3DA9%%5_vRu8BBgNGb0;Gbd8c|>XI0TaH|)1u z4eGR1o7uOw_WWNjbwhQv9QALndv#jV4V9VX<7BCt!$Mu*|1HyHGJa%o^si%`=x#}@ z|E2c%*VYJ$Zl`!A_(&K3|F#lsRQ&3lfrQkN^>M388_{Y{eOl2Pf7{D!D3}2~9+e;z zx>?oQ?heS%(P$@bOQvKk(gi%F!PpyEIVm<85@lbPDpQv$F?{d zk%&X0){LVkCObx=V6tOd98(>lscqgiiZhFB*)Zj?BscT8kx5w&)5~O&h+;Y_sW*>~ zsT5BH$5{D4HWvEhv@qVp+GmZAn;!L?kQ@dkCguJlJ<*uV4nIYU@~M>W)3iYsj3^WG zoRgjzoN5r5X{JG&Rtxl5MxbwI1$t}^Y3R6xHsJ0!xzT1`mD3xeQOLxGh0oP;eO?86 zTt%R5*L4j20ESN(m|~acv23TfQP78$TIPxFFW=dWal3HB1N%kYSC?@nwVRpsR4ai0Y4K<1 zD@JRkLYxW7(Qmt4luuZJqc+uc1-8#nh=_SVWn_HRkhTG}71q4Sq|Vw7S1jyQ+S3|s zkVRCR%l`M1Gx4If&Y@sZdrh+`(yfNiWAux(``t|M+&>4oK1crG+! z|Mr!7*P`k(FgxfE2QQ8hkISWK+R+Z@iIpkS4m%|i>8aU&^s_TId!4y8L5~TEYH$06Ty~(SgQ} z97g6=`#8w>^33}hDijCDqa8TykfaJ?zC}Y7?}B_G)rTZ9QTn6`gaUa6LCam-!`@vd&AGaPyu|7^_$8@m>(s${>BAq$jRPbMg1X7#*s$e^HF)^<}JJoP>;LOfiF^G9W#nxHp z8)uqrl3EpuGcp{9a;xP%wygE=WhR|f^GpsTIA&Ry40FzS%tLr{0)2=F2=u6)GA-+w z$RDBR-mO@X!TeHMHu9hxw;O1&c$Z7}BP`;iiH$T}@qRI;Q9{`DTCbR=aP5A)3;>j1 z>tHcp`B1m4M<+XKX6tKcA|KFU*a*l#nNo60+sK>&9AWj2ks8!9&W&R_MaS_*C3&29 z;3Fb2p2&ZURjJ3u^auXqq5>eOH?etg*y9*IKAEc?;3vexcDy{0JjIt7;3sKTBW9F(+;XKW`}3VaG|eAr&k>zD9o6Mc3{3iV|1`hwZdRvNu(c zeUd81zDX5hm0so8kBZ1@>KXed^^*h4Zs&o9yzx$}9=yM!@zrDGK^-D-=*Drnm zMHPzIXRIm&%4j7>YnP{2C_|<3vZHBYx#t{F2Kc>sA(jm| zFH#21k5zyRx=;bIL9EB&gq@<^{qQ$ra}~>52!@1_cNgk~`M9X3cPaeXv?fRlmB=Y! z%B5#16xb=-ZOp7JHtaH^H13Bpvc<+R7poZcA#a6u*GoEjF}kxw9foieg4$sQURzdO zjAUXosHb4%*k`Xy!tjKJZrS2X4rOAcqlb)y!eKa}LgC;n0k=cy250Z6Slrf<6^4{H z9J^Q+UmcDuEZe(!+cBn9K#|sc^q@fO`&Nzx^r~9K)+0}UGix0{LPL*8GRdIiATwAG zGHqt4!cw(qzIa3#YDMU=77c582>mZckOS&Efst6YxO8-ioZhTvGc z3n^DiY#OOlz#9m}Ewt$<<@hl#rdq66n;URNLLG=!T{llCWZ=BSr+T?PGn*sTmU``Zj&3WA{~T538cAa~ za2`jb`DUGVYlEf6ae>~(+{Pq|n{e9(q{1k#s}y@L)W#~XuQ5!h^Qjgd-(bC>#TJJj zP9LfdQB~4ygO>$q-pClukIr+H#!uCfZ9+%c6{K;U(%i55vGuWznAd1`aj4J6mybbSjaI%Bn!sBOH?JBRFz zblCKtfT0Cve(k)PyS&zn3*~@!FnU(Xh0F+uN=~q?=?0`l&I)BScgdRp4I9IjGjZ=C z@J|j&B_r5tD`#vtY>*uFa5axtfPR&X z(Z5>4%WcZkZ3h}{7dI$tZFg|>c+qA=ynLIJiK=c-9%dHshMT#~M#(Svjj-KrWTLA^ z)iFz`8^`idbYe`kO?^o?nb(Zw@Q~b}wPWu%t1@g7kImz?9Gzg~D89}~l25XtZ?cu6 zFgvxQ^VH=0WttWP)AcBh39?=oooR>TP3<5(OAmva=@F>owk!v;*;=q|$sue`^_a7j z8TUF4c~J$0NZj*|vyHK1xa4Sn)_WnhLMK_UkijnR6WNk0f zWpqYY`afvY0oE?Zd# zo-t3>5c?Qd$7q%{_lL&wCZJvQ-9fqbt-7uv%E_tb zu#07@%5Po78B>l|vS+%>rsR#W2{KgQm!0H4-i45eTF_<#o!pY0INWS*Kd2tB>NM+B z*Hv^nscV-AS8H;X8lmpVUEGaqtj#S;%6er`M9?t~{%x$!CtpqQU>gZ~S#h-fz~@5)9t)7t$~J3|)xX{s|F?o;Tr0StP{rcV}MF{R*|2w2sk4NcuT z($r7Q_XM@5HbMdE?2Q95(&8RdL$;!&3=6>3FJ06WGBDYZYpc~i9O=@^o?O988kEiW zB3FJ|B0<^Jo3owLq)PxOY03Xd7S@7t1E0aD z<~f+OX`b5vYMejCniZB%Y<vM3O$=dUVHfl964}h}9`UxGLf$*~XVK6Ks=|NlC1uQ(NE?J4}4rk5XA(q~k_J z7yN-8iDdmd{b;RhpV?2$X`AG4_?(ztUFm`*UEor!LRL;2Wc|r3&2+wMSW?^k8?~r4QHq50NqB&weXSIdYpnIn z(8-IeL8Srg)Rmi12^nXItCu1MN1|TH(H3JR`!hpgoW(gbv1f@=hMC33;qidOvW3=gAYMDT&*xqrFp<71_m@ZPIaZ(FsGBgpCXr zx+?5raM&VV83bu`hk+fjA)fY_WR`m;$04yf%ar68I<+JHQ3IUMsFWbnlSAzcS#yRU zo@rK#H?<44vuuHSRd_S&p>f+>l7kdm#37Nr$83(_xR~11#Vm4TjWCvbQJB;Qdt-4w zlj;22N|8LzZdlH@>!Vx8>!S;-l-owD4BKk;Xgj^sxlkK_U|Y=WJHpV#*oy98)nQwFY5sHvfUgNZzsC z9o5%Y-`yGExf9_Ntc%hH=R|-C4+E59;Myl0<*ZC!gje8amLUt*%VhrIC^t|`ffh1C zEQ8q}FZI-Ua93bAPj=^%m?)-4{Wg%vaKYTt=PI&O_P`Tkz z@bQ#?7D`U}sq|Vzyy;C`nLW>Un>=`l&-;IX&+N=$z{~emv5@TkfSt`*hLbzChVZ_C z^EWT@lr#HLg4cs?&Ni*2Q{h=WK7R+9jCYDJ0Is=cH&3l{8%sy^@)QHzW>q?EBce*3zL{dTI$8#~snX^w6yG1@RvJvc3s|`Sem-Kr*31|BvqQz+f(-wp6r*Jdqn5mK{ODv!1HSGkDk z6bTm(z@z4~hdg`$_}$XaQU2xd2;NgA+z>8x3I6Dpc1PQ=F2SGDs(3Yk`Z7tOihO!^ z!J~K|9u0mD92EG4r{K8wZ8ZL|PVsrbHS>StsKzi`y7708dIuh14%=Oy0KnWAE>-*- zaN}2aG+kSCRgW8<_f$HCPoYFH992Zl%0C#Ghfd8^V6?Q;w^Tm^G)5e!pDJAywS&{& zSIw7`69qlC>DT7|xfw!`V(A9DD~J`%OoOypoO5wk-sS{D$nr91hd1rl!IV@&z%Be0lL| zPeJyGd~p||_l-al*9*K8A=JEya8MvPvm+6qx*@Kwev-(c;a*RD4{k~*ccU#l$-xOD z$ux!~>c(@QL^5V?0^LUs^wiGuKzXO2ynr69ZaJL1%u`J1HmR@{Tuh1W_IAR*wxre7 zgj@Y^9eTixgomY7>QVsyYT*$h2Zi(8Y)H=g3FCqD(oX=${00w5Ldv2nB~*@_m)D%< z-VgX=cshZuLE$Snv`~y_P;}D0;CCIWT68j#0G4Ni4`u=I)sBD+ZRcWCK_AzYY3LVG z26bHwDtcNBySo{GUzex;PTH#PCh|G*c2C_A<%2@x=k5b(%H|9M3`1xXg$Uq3Po%BW z=u_H027jkn`INQ-_wjv7TMeguO50yBPT#ywX)Excl22*-Tlx0(O+6I)i;-a+mDQ*ACuu+43O4~08j~?bz z+M+uuXUs^S(pLP(j`1mN1s*rvr?izgn@sj8ZGFZcKi#Laok@7YET7VLTjn`+c9?f2 z`joa?Fl>_YDQ&kUJlXdtZN(qb)~B?U%1&G8Q`$-er!V#?ZFgjX8B2Xi+p7rAT;@~S z-b#4W3z-IIion;YOk|Lu8a*D7-7e=egr83CW6XEQ? z>r*(7gNOf~@+q8IivLI7r*LM~eF*0iKEHx>UIwWYpV_&1q_)AMn9;(yW=}XMoZVxc z)INYc=^{baXBRmJ9s#;YX&r#tOYjI)>TJB~&c~ykU8JnLNQqRD7|OfG*qd1#p#HRDL_)?6r7!y1qVTZuU$()OR2dd|qo7V?Fx@Pjv$h2J2SD670r9 z1#nLHG$**5!uv&Z7w1ZE$HzfV*WDgIA>*v~zG%dlnl_R=Cf^Ic1m+DZpc)5)IljK4 z+-|2vZl`@7n9}Y39k|2Y(IWdikLXPtSyDt;e(66j4=f>|w($csh<=7-HNQfvzP6;* zJ=4nVcV=ADyUlR-r#n2>lr&IE>H(+x(gTd{yuZJl;!oi>&_ zU13TZEhU{8m*k_rxkJ9Gq(v-gvMovKG^MIeQ>9KnG9^uyk~mE2I_=LqHun_iK=k9o}crjkx%%@Rr|B4me^V7JZJ;;H3{V^{7 zjwYb9!nnQm6XqlS%2!DUAga;XN6^8{AtHGj%hbfjwE@NQID%C{&*H2a^Mk)pD5YSGQBSS0n;2AXWuc? z6EL*8XH;c+resQGUNSvfGQBv?^a7?iWdoTWO-XQZRi>9%LJ6;2s(JwPGfg3vOCkS^ z3ptm0oEH}&BBdkxsZS8=dsQV}Z%ev_;WzBWl5R02-6SQggkY6lx-a8g^-U#t7*E~1 zs!F=smb4jk5BHuGD2Wo(Z7*Sp;r@W`@Cj4$eNyt9aml@z=WVuR;XOV&R&*@M@o-h~ zkJ#dcq>moN;@&gG{ZxwECe-y*>AB3~N47XZ9ZUKQ%A@;CRY}j4|T(R)ry!4>3+?)z4pIAJ92;DqZxHZ zc^Z>91e48Drp{|w#!Ho$WH!*pH-~s||5Sz3pDj+G{0aHJzcI?x&D@uA=YxTf+iMrO z^cN!od@U9~6wyD^;P|oN_{SK>MJ)4ei=%}$fap~efPb$-^h=AVFvM5;k~qsu!T*$k zcTXGQ+{-*Zv&9io*(fyD4Iag$#7#LYDksW;$l|oavgqNof7A^zG7g7QdbsWLNtLW~ zEHi6o8RE@?Z8gw5v=qA#j znwFEdLX7bazEGK@IFwy7X-^1JNz{3iFv(ReDE;ANC5OZBt#`wu$1Tmv8565!K#pA4_#(p))D+ z@N~c5-Wdmvd>Mn9h{+u^LT|+gO=3xN69~mb=zEy<#eob-GjhnRdvSuCF(59xLVg}fhp+#UD7>qNqv~l3R_Ya_1Jnc5IU^7xWg00 zNq0V?x;r0P-8+ub9Jksabc{x5bL?E`Hs6&ct*Jstu<8OeEImQHsYdP81ZpDgPIEp& z8Tr#uut>Yp1+)B329Yx~A}>dXq?}@eQJRxRulPpU%XGcoG4;B< zs$O@PdKDb17wbDicSGcMI6!}|8u9C^5x=1t@f#C}i=uFoL(M=7cF`1Wjy(dcD%|2w zSIEO=NjKSTx@vvlmhO3bRn^vET||C`Rw8*-*Hx2l8~5Fgt+Vbo=oR-RDtQ{GGxsMd zc`TLC2NIS19mmukCMtOXll&-7;U8h~(9!mE^+Kp4fx{eQ5 z)iLJJLrbQzml4^!x~}Xu=?lAaQRIn4Wkp|jGRE9#e}IbHQ;Et7D?Xj5?4ykFjI%sq zR=-`;>t`M6(`@2E>(|f49%1`CO!B-#U7s;hS_J>n*_9&r64YP1=?j`3_ZfP;SVfOx zY7H3Zn_%0;MR1);HYJ&VeK@h3`>v8?vb{T-*hzDS=T?XJc;{iC*UEb2t z?T)Zf9edkjy-Ez>X84aM&_RhWTYc~ouI9BB;^|Q)zclxaYdfb2YS+x zJeP`Neihu(k$mkw&7dE+13}AF+<#)=VOVd-udpX^`=YaYSb^9D%Y6AVny2Vmom*;A zBRG<~op$L|rMMQZu0^e`#SNww^&0D+nOc;!`wylT4PDjZxzqxx<`9c#jUQ$(l7X$AzrSlIVplhz9S#sy)Q!KEqw|680yGRgBI)}b;RbpH?XqlrkUI@A@;@+m zAFT2IRgCwS#ARh?c-y|zMK!M30Z1NQU5#TB)wq?_IM%fj;0sud;}X?a&1xL)F0HJ_ z37V;2Fj#+AV|^-3V)!fE&7u$6FxDL#f2TT>er7eoXC)Bc4s>zPc2|;SpP16m(WR%* z@#I%HfcczSReHzbo?x`gB%1C_eX!F3k2T0WwSAo1t&Db|%?*=S6w~J|?0T&#u0=HW zcs$l~`{YtDGHqb*C{hx*RNCME1LAI6q_XMWhR284GV*7*_X7;L$8wYRAxciA-6!Gm z0=BOFE!~#@ZomqfbwVAtlK#vzm$}6NnoM0S9*4aFkGs8k zz8n23yz*!)C2frW|7sX!EJmZU|M=H?ZkcKlbtL~5FJ0ymq&V*MN=i!Hh9#!FI@Wm! z@jlwCV;$DBgwLGfp-5VHA|5N~G0v~&d%9on%a?$2|Hh1KeN}d`#|w)a<#+Sb<#7g? zX1`Sa4C7XjA+3I6nJa}{Z1D&9t!3)yq?td&A6%w>E{+lY$a1@JjPb`SLFWUa`LIUq z9>QO{;{WOEfCFF9f1DWp!jmS^yK}{HD7a=49(7ybF$8Vs-|p7)o%XMF%anC&O8*9I zJ5rxwllr&1KI~SQ=tw*kG1t{WJ>O}6-=MsEv!~cr{;B}qBmSwQu0$+AY)DFK>UxpnRGsdS^r_{uxnfKEk8!D?EA- z>Bro9zSI8w8tGPyO8$?NNIycP2f(|AxCw2pCY?TXizK+T^{e!F$*rS`I*-{taqP93pq}rM{y!3U!t6~NYaVk+ z1;}MbKrgYeKJ)AO9_)YO+s6GXN@e37#rU7H)KdZ7$oL=o4ScuyANb`yu#tO!QT~GX zeW3@JAYA+p;W!Re7sp4KC)fQ9aptg!&-?X!xB5Ty%iOBt_L=`6;=hT)qysz#B62HD z98aJJvGP8%eb#T(mFM2Le=Cd<;9El?{=u)8xBr@7{_fu$#g_EnWWj9TCmE$aD9%E3 zY2Ob?ydiP`E;r|Pf}ZFcy&z^w38tTJkcVBeBwrK(a#|KGwcUC z^)~KBed(qZLU6K)8?sjJ7)DC*p^RPWwScqS@1H+Agn)B$y;s0N9N{xdHQx$2S!x7P+osLX|c7{(P?sww2nY93G zSWMF2)cjb31Q zdH?e~H5$_w!^=nv(_1{ek$Cu%@!+WEKIR58`nmVJAscuZ0$hxKA&2ZE>EP(+?g_}- z2anXjcxZ(!qE(8lOf}8j*iZl-@@?9zpBr;Jmv&pTV+_*E$b@g_ol~?)B*jXYngjNR6y+zY@~7M3E>)F(sxcEyhEo z2IHyaPHHqjZLO2ma>pkkk=%)To>WMhw9X|3QY#VVVN}rBA!-Y(a0BPV@TlEo6|7x@ zRNZIOJaq{?IQsPf=~#S_@m0Op5BjPX7|ud2B1HTH=-dcSHk#w_3TFzjwHbttop#qNuIoGD76{FJ1^SWJPId{MOOSRF zjZt&VIdch|B)yaO=)4`ycjzp93{0{wMfk*k%CTA9W`;_Nd=|+BQetmOdU-oUM#Ygq zr&ohG#WEf>LN-5DBH0Ea4=4d8l8w0dAX{NN0JcF;=j(1&%XD?y;o+)!ZN}!&%Ug~| zac?{#+i34#z~$rcpy2fOc4|a$hP_G@oRDWK?5#=^oNo|r^-C0-8cvreINzavpL~ge zQ~djuN)((LE|(}c1s>Q~qTu`+;}2>nQE-;9nidXjEm3d|A>7u##3qvXLk5>9IHf6v z4igi4X~$tB#e`nNV@ed9Y=v<6_!0#tSv?#zxkSM!{$p_O3yI0w;x(&7>Yr{FVfX^DbU;!IywqTtl<$`S>q;4|}p5(TG* z*ND|R&;u(Ts-klUATgTZ&mckrvB)#3^1h^-H5GTB<>l#AUIUURLdd#N$OwiI1D!@7 zW~mBW!;@0cd(78Tu^at8?zMLp2{;E%UyX&tGrcT#qo?{8t9lvolAm-eA8q6mXELK$ zGC9Rp5y20T5w{(6u>T>t12-LYXyC3-rx;i>0BOT!#1%EEbT^Ww&ebJAOv}#Z{ULob z&-3vIK3t^9wBn(%58|N(Q}zjfS|Q45!IUQ+kzmScg(&|Kyg0dVpK-Ha0;ZLrw?3yS zk}o1pPD9+6+-wtIN@?%XoF35%L^V4S56*qv3E4>iIfM3Y%IO)j)-jWi zAz=)u)Kze649(c636mj-vk&1Bb$P8T`C3NLL~~{76^Qu-27?4w0_(J;sl8CGn4R zC7LSxk**~Ek*;(n{f(}~{3Bh7M+y8$R}y@TuEaP-R}xt3N`g$vDagUGVW=;lJWHFibj3ZpY z{1f~Tjm9-ByOg;P(TryF7~oow3sf$B^&o5jj9fSjHvKzdWtg1o4#p5M0?B=xc34K6 z{z-5|OytYB;q(ePZk&hi;`CMl$Bjz~xB3Cc4GpIQjvLq0zfV5kxFP<1O996X4VMFs z8v+k(3^;B)%J_p?0*)J)I4NgvYrt^>mb1!f>mP93koZFe2OKwEWt^eI0xH};Av|nk zK!sbwV*-vF_tJm(_<-ZaH0CpEa=>vz{KsJ96640^^dC1X;J6|F<7WpPH@2exgt-B` z>2Sgm7X%zPFhs!UesREYL-3ilG~l=)ai%W|IBsZoWx#Pm@R@l)z;Q#vYXU0VoK!eq zqA)tYb|r8PBm4PV0H=vehAC92J9dg~lX{$Cth|I}h(d-=m4*BghH~pdttF(;sL8mT zC+WB;n7^wWi%dbMRB0lt^Am_gtL%7qY5@~!p&DxCJI~;P*y4v;`A$*GFOtRF#ea9y zL2zLiz&jgrz#MDfW_R(_sq`)DQz3c!*04$2>5H=|H+09`jR@7=3?Jx?TB}i08Lp0o zf@oN_&qba(tJVr%R$ENbZ^lA`v((c_iUEDJHV`d*#)_no(C?GB(;(NsAYnO%(stf$ z=h#8WYv;(3*%>kV15nv36cq5EI=K_`c>nxLc&YppJPJEt?Df_Xbc#Gu=&k(~;9?W_ zQG4gM!$}(NFvd{+m3Y+jTM3Wrqv+Q&x+-n<94J`S*%Wd5$1QS9YnBvIv&VRxkKt3UIuJ_?(mw1>x=_$??yLs zD(L%j@oQj%Z05(Q9X^4i|0L{-GSC!@W-OPt^mRO9%8ilVe#PYe} zprLnqYClvy9=^e2?kMCJo%ZlH0qjR7j{=@NVjxZ)iLep4k1xVT!|8x0kA4iCaPlbN z$s>UWl>(kTdY1k}%K=Xw2|TPZ;K`$x=s&zA;K?I_H);)d^60npAJISH$s-L92zm18 zb^7z`Pf zkCR6MPaa8Sr!5S4@<=K;eX&Tsc}zTGX~2_5JdESaTo&-;(N%;uT^{h{ksyVWM`?vG;d;NeGyjshM!8iE3F=qTW!BNl)|M*$BVvDQ3vZ(K{nu_BMLqqI;uGaK#BI{m~)+oS1pBK z9Spq$xRdBeEn-jg&{+m_+=e(s&@9E`ec4#*t40ZBh4=? z`YjHYqH*dpKFrXIlEb;Xa1`br`oUZad?=6g?7bH%o?b-{ryIp%dKKe#qj=QbtrU;x z)sm!PAVy#3o~Xw6NR4IoeGh|mjRjPF3|6MbSF*2kcpI`X5tVjL+rAdNEs4*B4tS8M9Pqc zwK635M9PqcwKBwBm4Pyp(aMlV8>#+8pukwldz@}oQrra=RiIOOJkgK{`5ewDfDO&kf&a!RG)be2;pY6EVc ze3nxx@$Xy8a!RG)a+Xsnfd@8bIi>nD;}2@da!LiOBTVpGvz$_Kly=+tXQ_Wn{2_z0 zoKgk!A37|{DHSnyhmFi~N~Pg3Sx%`~LwET2ET>c}7=P5{ET>fBKW2KCQ>qz^Gj3Lv zQ!4QvKRe4Q)oR9{FgMF7)%JuZF3569wLjrWi?f_k2|m-7W;vyjIMbJ9Ii=F@$}Fc; zg3rtYvYb+Bcukg5sw0?>ol@}trI}Ls6a+aUlV=L$e?&JcEbcsu&C{t0+|JM{L^O@^ zTi}z3%PGE&>r+SaSd7nMDn}%Begd&LRagd3${7E#%4t;5UxScn2IU_MSZvsY;ba;d$VK4w-_&y4vqGT=eVfLsRrTYd%+<<~&L5CnO0r|PEtY>FM&X==+~ z#j)9of>6iyg+^`KU>+XP`au}2 zAEe0a-vh<4evl%w-%7aEPm$R*oKBJ1@27vCe2UC2{(Va+GP{P$DKfjj0~=FhcFs1i zevl%we?@q3Yl_U?O2W1EPm$Rr{*b{bGCTGH6xI(?WOkAW>jx<^yN1W4$n4;8h4q6J znO)}nqb8@w?BYLWdWy`x9rGVID@A4(|M9a^WOkX~Pneq`vrlB4i3?I>b`Et|KS+_; z1)ph4Q)G6DGksZ#%&y^;DKfj@GxLBHnO(zcQe^f$nGcvf+OYHQ1g_B{l+W39hR9@@ z!fc}YFVdU!7Vj)e&(f)KpW#WKck7~EE8ju(iMZY1)N%c0fO(eY4`3YPs`C?wrK;R! z@T^>$)U$FqL0|BxI7h2fK2Pq;(m_oTlOI3rl&GlsX~7)4r+XLM)4Xeg!=px>K* zHybhHDjU+&g7F>iaO9F$Z}yIZ8@WY46ZbZd(J2Q98UL^cm6s(ct;(cNf`8^5Jfe{* z8;w*sc3v4(daE2eFPt2ya_qbsPUqNp|4IKo`5Zg1`1dX4*m*Tv&av|fJg_mx&Wrg0 zN2(k{KrhsvGZ~@6(d!Somc$F&(5*)QvPD3%CYkvN_gUe96RrYgeNV|vGWQ( z)0XDgc_q&DWjS_U4X@0x^9nvQ56H3eYIseKo%b5%gU*}MdSsgVbxJS(rFq*$p2!rK z0w4aMn-vy!fyEZ+RK?MF>X9m?7yQy( zhd%Z+f&Boy48VsH=eEBEDA)#Ge*qAhl);Vg`8#}6>L}xvCeyn+oC$a4e0oOKGPz3t z=f8(X#KDD#gNx)~%zUY970JONG6V+~$-x><7sMA(6 zNDdZ!rY$X!gC)-NWkqtZhF2EJ!Gh1s1B&Ee4X-JZgYRWN;NYz0;2f4HRaSFwj=E+I zkrNEba`8&Csbzys1WWa8`40j>Bmp?#eiBZa;vvEG9=$UPB~xegd&LRbv0t z9Gul0oYfp$$Kd+h9SF{94$l1uaG8rY4Xs6tq&^XHy73wn2WF~}_A-?a?{2bn=jY+u zUFJ+7BR6(`y(e_2lGH>s5z{78s0T6O&#-zkSi)&xRhw&3)U>_m{2H0H$l5ARRh<^* z()=Pg{N^7TCxg9qDZ7Pb_xvk@1*=|+-Ten>en*2xQk!dKC3~@BnV-`q^hTgacCBC@ zfXWWFH+-Z+sni?DpTD?kr9O##RGK50JC~X3_Uz4N7F+_v%3|O`|IfilLA9!Tki=L2 zz*jaOQ|#7e7| zSZVeC^DC|3{)&}WpDV5X{X%dn-j5*AFRFNL+^_M2h2Y@F>0e6AIzHEH{n}P+>Hw&# zc>&K7Gi@~MvK7m=48h6-V}aN8&vf=jF3)gKIn#6N0`ENZczsXj71(wwg*Y>?H?C9a18*mzf~TJi)Fi_B zbnxhNf#M3PQ|J|}!_o&AQk~+^VBFJz+Ldr=Rxls&_a$6AKlnc4uO(c!EI9F*K%GFi z{?K4M-2HhL;qo~_ANXHNxZ&#H2;_4;;qJEu7vfG(N!$2T@FeoNi~dc22<9Pk$c7(aP!B=!9Qv5o%0(O>n|fkVH^w-P{Q`Gxh1S*a@d2M9E84d{8tbb}jS26TiJWBR+{^>9eY*fDOn$V3~rsTE+43tQlja<bA>uAa`Qc>a*!4U_Lk7Zbd)(}YTO(vB)2z7P4_^cZg3ih}{qR6I zq#5`A!Vgyg1F7jg=^*?BY4BxJr@=K+>$%B4+gly$$J>h*e0yO$j)gfa?-)V*>7xfJ+HDpMZNM;9>&q zlYq+!xIO{bB;eWv+&uv|C*Yn57;9EBCE5~jO9F0C?hGha%g_>TW8mF^1^X0E@M!YQ zQ{I7qGm)J?Gs~X}5AHns@~{HGXuS7=UL!r=UKyg=ee9hoM`7+;ArQ0 zApN7AXMv-g=i&5^cAf=}cAiJkKiYZL@PHzBo;RUCcb<#fc@|f^^UU+8UbOSPDdA}6 zc|PH2=UM!too9igoo9&??L2SI_|eYu8HA&q=c_TEdQ)fDD?V12cxtEaf) zLr%dh#9JdU2!WRV8T5N#{mjiRfM>cHyHT7my16-Y25_GJ0G+?1a{}<@EY!_SgENEg zXzPnW3va<0?-XW!3V+TP-LgdcEu3;GX#EF>raXGet)O-BX6AeF!pCw@#ZL%5hlhHG zPPHdic1*pG#lc`RQ^n5K5oR^)Vl{hdRkC!8tTKBg|?;~G3vI>W8PtT76{4Gz7akki!88y|mm=BEfOJb_0}uK}oQ zz%9NCd4?@oY2EW)PyL`*RgI#}UhalQ7DE11z(Hgo6w*S7fv^w?xt=3%A3x-Jj)v1A zErcG!Bp4P#AuWUi9#jfxcfnnESO|r*5E6J;V@M03SLr{zC8ULrz#FxOv=D+&Qm_yT zX(6QH0V&F9Zi_=ok91O$)8e9>4rw8Tr7Hysp^z3rxKT#ILMWt#5LaqpAr#U=Nc_i+ z327lD@VN0IErcY_CX++XTe)@y3!#t}LQ~LWP^cmqzmxr_v5~Luf zGu*n<7D7=6i#Fu5%sopgL|xG*EYZm!n78`8Z8#7)?Y$e)LWo;?n74+s5MlwCw}!M3 zVy!uEl?}gqfkDdWGs|Ti9}_z)VMkjWT<(l4g#0}L2a$!4+}wRQJs_uRP6ANkoE%%h z>+q^Qn<3G>HRQbY7x2KmHEuD?TSLxUpQV2(E!@RiIB&%PTh3cKF_lakm8)6Y%v(ua z3BmZmSdod5aA5-~BR|t)FToO27?K0JHDCvZ9X1TXYpT15_Ye1E@KU%NX>S#VIQ65N z^g@!(D8v`~G9>@IV9#`854Kwm+=Z_EL-6p9$72jeGWT$&c@*Ah04?n;X*sI_ShZZ& zBX(e5_#foztGQTMGu`xTbkoCItGcN!+X|kmQ4Pnx8{P@Q<6j=Rop#p4@o$9N-`AuK zSa)~XNpOc3@xkEmhYU`w$3tXGY_QF|vRC5~ZDyrd80+jenuCiEF$x7w?s+^|YwvI; zFSQ0xV68tx0AN*Mts{qT_Vv`y5sF2%MCEU|(o;X~^9_~%(uElHuVdERqYbY^BWov@ z*qwF`h>lOZg2NEJCpO5O@MJn~hVyT85t{l5oFT^m{!(ctO#gGarn4G{;@e7Ek{6e`lyLcWPDGnUqy(Zp(mbnsemUWAoGUTeQ zw?ZO51@9Cy)DM=Vn=|tgpnQRm$QXWI?p=VH_wguxfd@AqLUZOS&}Xi;ae+^C=4vtF zR(VCq}nJbAOow*X?L}#vu zaS)xk(y%^rwT5YC47r_28Bt~K2AE~u8Ja-W5;Ms(B@oL{h1c-pjzd^=LbZ;;^%-(h<|}}*)sPdG zn+QK&odkW+bc3_g5w zf%h2dZ1ePOz?J=wTw=W&c=uutGIp#&h&#bS`rDkqyJ$c%16O5fA>um&b8llkN9A6` z)5$%Br<;2nPcQd-JpJ4+@eFc5!!yjif@dn1!V*b3w*>1cncT5hJIUsb!84b;1&cTN z+--Okau?uP%q@d|O>S2_OS#7pzc%-CJnM3|BD6mD4*bixL$FBGkUJ31Zn=-(-#xb& zaT;^)qLilGJ9zfUoelry-0dj61qW`P#Pt+@o>a>hz*T|Xu+KLU*7`?&0AaoRm8U)v zL`Ue@Sb3^n1?pp3Ne&_#XViF+#DIMI73ltSl0_YpYj--hfzN4v+P z`1&1C+^#r{;yfhi)E^8t4@x)>i@Pj)W={y*K#hdIhFO?_2rwD31&D*@MLyP+3N;Se zFP{MvUUa0!e=A2de$m+;8I>LfM@o%fbWTL-(oJwnjbC*B43ukyWKyLUop<0-Ivo+D z$}c);)B#l-zXxmligUiMu^gXue(yY^ooUfw-gI8kPX8{dJa0Md5%uSy#8-QQye~WC z_WGa0Eq2te3bOT|z%65C#H*|ixH({0p^CaVb z0qzS5DDQP4X8mHQMEuHy!EZJ6iVqq8P3I#NRlWmL9_P1`S9uL#T~7BAn0Pqa#=ZLp zM0D-}w$NplfF9=OeClMIPK5_IiJX#K+oO!yUCkKH^fo`Ix0~+q3J}*p0Z3?m&I&i( z@+aU}3(uA`kZS?ZV*!9cjMjX2GM`0={0S=f5IkFkA=Q&o)|<&VOAv<_B>jbPegZ(Q zEo>g0Ec8^@@7cOJOS}XHEd|i4qF&c|EpH;=Q0CjaBIJ8+6$wsvgUYOAk+ z2R@4Ok=Sl)C#OpmPdTlKYQdUy?r!!Q=eNYdICkcqFOi zdXv7g;6Iy!AML8(94OFv!Kz;?O6l>lA)q-cI~bL{6+jc&6-xuyjC0a07r<9I^iTkr zLo2G@*D)x3g$SM2ecNGOp-|bm`Z-=DXZ1(kBZX@ZKo*_mec!jtdq8#G1LM43LKfSg z$}OKph4fS_;Ox*rhC`@zPRYt@45}__a7?1DkVU7}IJe8ZRX73MgF%yBW8<4*VsbDRgD6Xv+uaifkg6Pi}1HKz*pZK!&U<5n`qwa8mD#}B&7 z`=4Fr-CQA(Z*+<+Jnuk}++z^{sY(+&BIeY}xyA8YZh^Pp*<2wWZ*!XaJKDb@%R7+e z6H%5ea|cCa@&VYq?_=I~BJV@tEqU0+3DGOpfZ~;i-iKT_YKz8>R{#j{j{=~HUxC_> zoWP(~;s0Z&XXGz6e2!Q=2rT-eNWnsh|9kX*)bUzo8vjcA|156XWr)ye+umSOR?0XG zDXKEBcGn1z3qXoa^LowDs6$?rz3)o5N{C#AyfvSE)m7fJ26x4Sm1tfaXSF+05X~+` z#Z6siSc&X4)yQ5O6XNlxgbre;gw~d3>OhEw$EAxxU483+8!#IB4u1`^46wuiap^Iz zfuK0fzXu%Ab)o-WhU@>+8U9OX{GTn|psEJYq%WAuIm8 zw3p>d9hR)xXfOLm!h>7eXfKY<1Mtj-e%zxahHrmUI|M=N$w3pqNX(!BW<9EP}v~~%D+H2YbPx+kYx;{Q|13s8R8*_C}bUj3vdr%(K?|(%vTk-0-&v6hteaz z2_g;SF2n$uO9wmH(udQOGnl8DU?bi{jp2TTOxiCd_9J9McrhohBV?|4u}1A_6f^R! zClLK9nP52^OT?#~+Yz%Yv%se%0JmTPgHZ=#mB6``pff_2qHpDjgU(&NM@+|VigT;r zKWYMuubsORvG206#aoT)g{F7zPei%jMiKAPvZVdPc_>D0G-WqT6R(IWc7;@oo2bqe z(-AsCCb3trXkAAQ%2Zdt(USbiqcIHVRj4sr08)+`bvP0^&oE___cM~W6#dNckj*-8 zi7`Uvz8aLgH7GM&0Y|UE_L%dl^N?)xGh7CFi5ZWUDe-Rvl-cjgY>d$|@qO`T#(mQT z5*n20x(2yaANfji=*(o>ke0k~*}pDNZ*Mwk zAz|GTa9$0d*?F)+dVbusbw?b>it}eSCfXzeCgE>i8X9<-LLMdQDZ$pmk~b=H!= z40hXPd1)#yR6eL3C0CIqfpD8vwyAv#)1?HB~Cc^4nJcYQ;+4 zcku3@0&R*kovJ`q1B%DANrD3&hG?}oR^^Upm>E%_VfUCE+)&CMA@$@!vk8 zWcJ@FTxoYl7S_P~28hI5ekw66WvrilQ8YPjlO0`jplF^*~ zRU11$GjY~{BhE%~l5jzSBL*vv^cH`7zL}Zlxh$HOR@gs>AoVBA@%5fTAGHLV*T2BT zqaBCJ&Ck6FyYgNgK4a<|FJX$0;9AM0w%);RAnDCGNbK~6OvL6h&iOe*KO=ZErT_4= z0H#c0T$-2{?|$^g*>enz^2>5&D8F1dieb6b8VsU%9ejzr4!KEQhyF-jhdnK?!(Wrv z5r3E0kv)K9E_Kw#@;Z99ypCBeuVasp*KsT_mpc9&ah-6hyiVlzfpV$uz9+AfynwEg z%kny9guG7OOkSt$B(HU}zRRUfKVDvETqLhEe=M)F-jmna>5x&@^RAd&>YO?9I(H{| zowrh6=N~Mu3r>>Pg%`@};%nt~$piAb^hJ4H_Kv(R|4Lq0q(IJG>dHoWUE5Dy*Nv6e z^;^m7hMnbg<7#=`bPQjay@Z0973Yg<XWx>og**M4K%v*kQnL~QYYwgDJI&=$p9kx(jhwmw`BiQP> z%#lZk>!@?&b#%MDj=4o%$NpGe$2}vjD^-7Bxt-;&oE|0Az6%jg5S%=)SFI%jKnoxc<>bQ116xF=2oeg&+@tHM$~zJrG< z>MfF*&EY7KM{6-UiJFV68tbU$*03j(XdYj`FCIm`K~{S-;H%i@*Er>q0ki)%bfawW zCw6BbWkZnfejVez0g16?V-aG%`#o@TcO_j{jCNNZoC@T&7vzYA%74`j9!sr9(__u> zI7g%Y5u?z@ef;h<`DxYQ5kFnvbdPe29?FH{sJ9sO`K2E$PBjzF0 zLXyuhpu5M~uqdZF%;_}o7P3a(+tB;;$^taW^IJ0LjLH;I(AO;EBwI#YeiZ&b!@q08 zr9^4S{3bMm+gpM(85g||s(*)+Dp;bh`BnaF*mk(9C2k@C1;2ZQcu2lF?s(?APa;|a zJ@&6oJcz!ls(l{>^SIJi3->{k6r?`#kj!hyIeFR=xGTh$x4CqP#7j&{@8Z!Te=_Dw z?jBMKGbsEMzN*H9C@EdStn!#6xw}d@iBRZ=5a9-FIl_`5@bkwohvhcLbi}~bVtCf; z9H92N%Oo9hP)&!RL%6#Yv}0@Rn7KP^NB$Ht%aS-Nln&*_-N|}11@t(p03ralp3o}X z?F20$FCQvDl)eiqeTCC;VfP^9zk_6_b2xnqcr1=RbiU0OVUprr%pCGOI__R1P0ojE zo&uG`-Ipoy+mY)|k;E(+3_X)R>tdgX#d56G(XlV$jb$bWhz}nsUqePYQam(be`rCP z6XG;Fr|wrm3}5~_1j5{w?zaHGjPSgk_{jOZURz@lN+SF7R4-mFtYKeue-RNcWyJYC zgOWdABK{SA{(K!#!)aKMK&J@O`4fPy-#-Ugt;tc;I%mHBM=oyZOyF3Am4e?_8df9y zXL|Hweo+JULreREBr9p4osg-jS%znc)XX2rq6QwpqHK8aAgBwzpRa|Y;Sav3DsW30 z{*>}57Bxi5j#Fy3%)iB;VS+_<&@(?m(9nBOv@I`6bu&{9&tVv;4l3%+>EnXMiE$|sQiWWC^0bUdpYkM zm?VTgoh6jk;Firf2Y8c$`IUaY@aIvl13fTNNq>$siG;6A>*TYIf6MU%Fr0VLmTGKETK6Brq zfoFGhGSd6%#J+}DJ=I=!d+Mnn*vO8K{vv|H1W5l(-TN)U>@{-&JiWCbgZ{q8UU2$L zqL?a>uZ%sNqHlO09{P^x@JN9Aj_8y&aEUIjQ0E}PSDzk*cX~TS9 zSBN96{0w%>UdFJH8VJAeQebyBmipWjkxe}ar`+b%I0()(agkq!>Y+E$I}3|!;Skf}*fg8>CmYACY{`EDR?}BAgUzyK6hEkN`#2Ks1dJnAX^CD-eAK)P=b`?qA53{bzHocJ$3Q z`TY=3|E4;{5DGZ>g1oLL2j+`=#jH-2Y+jzvpJG&p;Q zlX=v*+Ol^$nImCJE@4Bm_c@tg8gdQI{>aIEU??#>`;e14qKAi-O%yO9`)O)xtb0)z`D%6B%Oj{qgJsu-J9`_!@K0(n(^yrKngR{+kgl! zMUZOW4n(-lkA)58-T_4JGR^Y+OkQP~Q!zy{%xCQ`PG|RnPYsi1*AgQ4O6`|3e03(p zjK&bYFH=I8{7i?ZLf~!6rle_>Y9|)nrp&DF7x0uH)~WOlF`V|Jk-~ksmPyKQfo-3| zb_v`}((ou)#{ArmYrSrtCq3Ho9#(hsuW3L_%U;9!q{nGxujODA`8{~H{6Fly zd7MvfbDmw1l*CVkU(!hFG`irI zG>rdq_+P=8W|t?gLdLU=ZA#HLZ|m^fk1@K~nI3{yA<{I;lTF^o(ke*$5<*1M8ZBu) zB$vh>QM*|Z$s@COA+?*ZkrV+eftp1uziB`|iI0a3GJ692!c!AvFN1#uQ*V|mQh=(L zP~PXUo%B!k&wK!aPl3od`(S$sfkObeaRBQ8qyXea$h-jJ{=gKWo(9oyqG~pPWo9?L z6XC7dL0@`^QU}AAIS0T(00mYvfH_Ixy+g`R;60}sL7#S|R+FG8(thLc;Y~NHlYqGc zn9NN89u)E-`uhEqdKJi;FPO#)Ao(?EKLGH10uI9esw1IX;t5Pjew0glvN3bZ$IRMfWjK9pyz#I)s5sKgcolok40IujpeF!i&GH4ZmI~c7f-d5nY zbtC@@m}k0S-UNnU_jQYy9j4T7B5MXg{>(Udzl67DI(;X@7bper27n}hg6#JIQwxl$ zSxU-@9jM-J1S^5*AVE>2CHtX@yHQ;S3=a{^>;kY*$W_fH z7w@Zk@yqZ_FCQiSszA6K0n)uk_w1jaV-u=9UZNLsPU8)QaGt3-?+3qdo+S)&!t6lJ ztf~x>Z9o~>hb6K=)z$wfKKEY`=!cGTHnQfJ`<~ zaM6=ZK7W~Iz%2%6RYSX0W&^xuFva*trB*VA#$K5ysXld-nTB2hAk$D60GWo$uPDyrHHmPhyi=*? zfy@jB@M8i$0q_=qKLPlVK+R};K}BF906PWXGypLG-OKFScslbrl9DnLndVTY+u~03 z+2AEp<1_#w(`Eo7Qz3in!1ZKstvQpKdl|lKnb>Xs+~=7o8KcyF01Bm7`+efa0sm6~ z1x~$zd9NE~=18FaN$M*BgvyJlzYk0rm?8$B0o98r`BikA`T#ub~0V4@#VdMr?0~rv}Y0CzmB0E&(dU;KoP! z(fZLTD@RS(K0ZZdIQJY(TlPsB{w}`Jwa-d1Mb&s3mNoX|xYf|>F)*DRKaWgBUzr-G zzEYn{rV%hbPNN%i;L8#IyAfc}77D#X22WsNWsme2j1&e9G9ZnNQ-x@dOpO#>I>+mu z>`?-%x>>X!ZxI#KB)_GU$v22Dx5U7Gr_uPZ&KvvI z=~9=HUMD5pASJy{3bEmx`Cz|Jm$c;TdR+s@z_Mv?6bpkMA8*w7tC`uGbd9Yc{9O%; z1UJjrs*C@YIEz2`90%g{n&uMHU#syCu|TiW_zQ@?LBr!<4zas5A1R^@0@vrpl4z@V zP?9oyKcz+bk_GXkj`A6H*V#{-DAGrE>Hs}tYFIkLPMJu+O8UsoI7hGgTv3o2JL7un zls>XE&OzIB3hgQKO4E}*;&GEcvNJA&u{UZ(H!d!v9~nO;+*WC zkEgb>nwzP5GYWs6L5HUn*o)&1Bk759vD9_yrUPNvWIJ3eWt#c`ercD+e-8Z83y+fm z%svLcl=TuRpR98bG;t21$7}y2_@$6f)c!Nzf1Q2cBwYbg87Byw*Ku;v$j%gGL6^#% z#}0RHPwWR|c42o0+4V?8YHgKHbtn8%J*%YV^a!ZKiV~38TqT8^mnHi)qRM2d1G0S% zhGm+ASx>^R3u&@F6!>OuLKGReS4njic>fduGU@7o;y8ankW9dX~wH{A*_dA3dQ&zf?o;+_JVE#>t?;WdqL>ttx2<=AgV~W zx`%W>VgTpb)zaM4A`TvUF3`y0Y)0oOCDX)esln_p_@x{4NIiQh0;Ef<)?FgcIopL0 zlPxKCCfVYp>$P{j-gL%m+&_6Fi7b4h;lc`br8_VJ1Bx4kk zJq!WT@K2VNY4_FE*~yT$F}^ITtiHQxZ+t0PhWknhQ}+l zg-!f?AuI%pLjd=D+m}j=nmYri@{@s-vREU?>^<;H6|WIHmTvbt47Mi3&{e%A$&#!2 zIaz!kQKY?VWVU{SY46%!5a6>yT0PqPDnya?z9z}xs}SXB1W0?=0mVUYB1l@)nj{C! zLY$I`ro9_^_JLp8yY}l^%aiM&;}&gWC}3sixLaduK4rdT*m$5vnH~Y&QhX2U;=2NV zDZU4bicg2B8aL<_--EjN>VU}JgD6sb8kuztFvX|+d6BYj6w>NZe8(b+6yJkAifNd)&y}-ow@5&J?o4V8+w?jcsndWnk0+dhPq6F2iekgTe0P3y7>aeE1MjYXg(Hxl46XaNL zqKP8jXgt!Anluk-@l9o%OZ7mj@rW;qMN=93xmlTOPfipGFTn7U(ZHZ@R4j|O`=wscGX*w)(Uxx5J9Rv`VcoCIn&s% zi{|gV-*lpBtoi}tYheDxVCGDZR39`&sRQA!?gL-}fXw*-jt5Y49!N6fQ!(}sJsQ9& z0NtnXds3nD$AR^J=mZ(|MSs`pz*e7tNbdj`Xnlld<_37bAn-B(UykgjAu9mN&#v`Y zV6y&mGB(iKLQH@0$>&67jswz0br#ebN`w`xvNC8P+}nZ@;=l3j>2o|B9*a0xAtu zA^!WoG)b`(aMnziGrLjs2c{F4%pm|K3waTbRX{H3iQEe0J*Wo!@gZKcPHa&r{~<>C%ZU{w^%8VYQRi}E?Z}QoxQt`95?`anqQTW`qB;`o0#XKo0fNka4ZjR51GIffW@sIzYK9_)9$W^9ou+0w zSyUZrR1l5Ko(jJVG}@mp^6Yp7n6!GRAa5WfoXu4 zh6-`!B0y9SBhSU~%Rr_5Qs8-Nt-$T8ZDa+kC~y-rwq_BtEehOJ!Q{!Z4}rDhXu2-F zx8ax4n_g6UIt-&gzVxQ+(&N6s?AM4Q3Y=O(d#^o#Hi+$K(2mZB1+p_ z-R@_@FKaxVYCdjuEdoSoo2yNOg^(u^VzMG-&0N=QqZ$8$6elCA;Xx_`AEeecql6dI zi1mS}DO&r{u-1NlYqTGJ2WWq&wI9(0b{oA$3@HgIS3EpL?hz#B%wk%45;_b!Wt>?| zuHTy&beNnam$YsF6d1BQWy`=Ol!Bh^pO!fqq@tG_~=nFLk=Gao=^9{|SzsM*2E z=}Y*|AbM}uS5^Wj9?(YgrXN4g%}e<_i)2_?ky&S085OeBA5ef&EW<<>NUc5GY{}97 zY&ra*$aa)*qAisC{RrSUmG-_`iKwY#mHq)(Q6DD=Hru!WulT4FPZWP4`e+1*GB{bZ zj_yu&YI>pR*0kiBJboU9SP5R|dZZR5aP; z+eTe0vwTQ7`B@E8w}+H7F=)Zu05rE;49k0pHGq4&<}zBp!_oM}S~8arTj%rv()^rx zMv|j7@|*~_aaN$EdYgi0VpDKnKw(qxYiKz3OlamKz`{Px+=<8!^L)qpussAJR<(ea z5v&lf6`-@$&t1QP;N2iQ4E2SJ;#}W6NaU^?hi$U%4``)#?}XLTac|v$aQ820i#UmH z-Pg7{;rbwUlrse@#OLm@jtZZRw|2g9Tj324Xn_C{9zK=4$884|yYm7aPXdSphQBP% zh_}TV^(Q)^W5gFa_G|GiD#3gENNDk3agJLk&XUW-IsUuioN%u=Cq5<4Nqo^C2`%*p z=$zaj&M70sIhF6aBcWxdigVg}aZcYL&KdWLbLO++EdP->XT2xR*rg3HBOd8arRJ}J(sSH!vKZE-ICQk+ZTE}320OPtGwi*xz0 z;#_f#IBPg}MnY>}5a;Tji?jX%I`NHPiF0cd4ImQVR4dMH{3an1zhfV9HuI~xNc_%2 z#JTGzaqc-uoGoXGbMGo~?z>8y2W}E)>mA}exK*5oo)Bl-3*v15u{e*sDbAz67w3EY zARrQd{GZ}H!ApZ9@h4N_JY6f!j=thNvyV8tu&G!@l2fI^lhY=NZ~9VkX7Jm*NOC5> z&5I;wJt5A4+>9Sd9`vy|2fJbVX6MA2!;SZm`iX@My5oh7v;v6|uoTCnhqoQoH{CV@$_BZ@$&SB^mr;i6VwiQELZjtAW zUjy6*6oGwKB=IVO9)-Wuw+qj2V095#-H%Po_6qjg*vB3#@d~R)$!cXJ5nlLjSSLpp{N5=%rP}X?r_}I!C-MtVQ8oPDNy9$n z8wo;w?-ZU|?N5ZK3ZZ{E*i~8my;F|gJB6E0MXcJh@K9O(y;J!Lcrq8_k=5TX zek#2Eh-Y!o7v}>%{&74^_ux>fXYm{Cz%{Mvk9C zg`4^HU2TCft3QRx@l&X93-1vx4%DAQ<@hO7xUWc&k6A0DZH}KpgA2Dm>DNU5-gH zJennH3ZGv=h4(9}FMb6T9w&*Mj1jn29(h4)&j3!9pN?m9`FHT_Em8B7s)64^h4+_y z6!NE|wRqn`MbD9H;zQ;5EmU}-R1F_0$8Vv+2S|nRp<29ep`vR!%heV_a{Lx5JcCnU zZ4rZ6#LnzV%Wt8=2j+9C%RR?$p~43V_FzmEx}KR`RW}#@a(;)G)!#zp_$^fUV4;-~ zWSGkFTd44CDWM)5a{Lx5JV$~aBJ)T2(9Fr8?n(H|pTQ$TRylqU72a3)>w4q|QQ=Xh z>Zr1XhvsWv^YH~R{9TPR^kWxf^?|Uy3@|?<=HjeADb`1hLw^s<bpYeVk)g60G-eo_(HRgO77<3uzmDoNxa|Y?JUkgJ6a5eGFi!C48$uTWSm6 zKae0Td`~Bs6TXj<))Bsyq{a6M;QMamhg3O-6qWlau>-qf zO#{5_*Op4{)jde%ZX|YacdUuPOeeUgfI3>77fV{TvE8)pq=S zn0&kiNR4`J9gZFu4C~D|eP{>O!tUyiMWW?ggtBq^Ky{Jhot!J+)pr5BhMO65u-{%A zmxGb~cpZW-l|UlDpuT3899+gz=2-vG)qumd;9-spiq19WlD>C!l*fkcPq?Kn z%45ThBiyGc%9DzOzHdvE$A+~L->)@F10*HKHM>z-EH&H~bm=xBfmCKEb|G!#~5$3oSQ+0nkQE_HNm6 z+5!8_Ejw}>8Uu05j-S;ju(=IQ!}>O~Cy|zAZbK8;+=hnFZxn9X@$;4)fz54byr%@W z?D%=hj=<(NG<@~0aLbOLx9n)RSAe(dyhA*1*$MEL9r5LFL&GGXaLZ2qu2I~wAf>*ruNgEaLKKLHzfQV z3^kncb1)RRIpgPGcm(NtSNk~_^1!5$mO4KN!!E*on*1CLg}!f#pMxP=TS>oG={=Ob zq;-(oeyia&KLBKB0mR1k!Q?OKL=XDQR53dQ~;<=Pf*13%|6hp@rh|HDy zERY=T>}SnzS9}F;78LUHOcFeL#`Q5~r7Y~(a0-4)F7$SNl(>qg(0>Z$(G8UFvTxM| z9m(7Z&fA}AMlHlHLI645@#*~n6|JiFaO!&a)t+VmRmWMr8}7M-@&8oBRn|P;2^6M$C^^6 zmSh&nf?#M4uPRRf=HXQpX)fY@9U1DBS^v%q@YE?QNzB8n0ui-ulx6l&ze1Va=(klH zCSvcLxfV{+UYY$1zd~vB`KB_n@eV~bWZ=(rNN zL|}NAI3u=-Gin!|&@ti*9gF?0@Gbh4IE#H~n~BhIZQ?AMEY9(ViF3k<;+(iboRjVn zXX*3eocz8xr~Ff#Q?ppbB|^*E#5wI?aZW!%oHKafTOxGkDsh(c3e!aBtWDya{g^o4 z;cK!)=$s#kbM9N>tk^BidH)dS{3zDQiO>a8#96smoD0ttXVsPBT(m))i+TK8B6P`X z;#~S$aW4CZIG4AeB_~2x>?_V1u9_2}wU>x<^$p^zrxiL8-$?UwB7Q56cuT}Ly(7+T zyT!TVZ{lp`xo?U1ot5I;)k~av28pv}xH$LjFV1~4#Cc$zI9rbu=fP9NdFUK*wp}95 z_I2Vsa*H^R-X+fW9v0{Er^R{V2jV>WQ*oYtN1PqI#d+p$;_R}}8xv(yrNYamRf})> zXmMunEV)G4%u~dfb%i(w(q5e?JLoBK4*rEWvp*4MP6(^AMA;#A;v70$oVkaJGjEwV zhpiT8{%ztM{**WiUKi(xKZ>)^hd!4mJF-@sqXxlIrTELwn^gXQ*Fee59u}@u9VxS4 z5=6>Fd&IB7{Cql$;#Qr$gPs;~tL{s%sQ3<=w*1nYFmxVEqDlr>8TKH)k@8jS!S6AU zo=MU^Ny_2`#0Cw$H3tKK6gXMyx(k{*zx9Ny2GSNd%tRh;Y5?J?1J^@kWp$67EGW!Ig-!hD{j zVEKM8vsRg7RVt4IeN`pDs`j(k&B$KO*~5v~tOhElDmheUZUn3?_O-OwXYPhyTkOpz z51A)`(H47ij!OntOBsuOUFMg7wZ*j9l7c zUr&p@5cUTyJXI5F7_Tbz;;&I#?0LeR$gTp~V&A9@^c;XSzEKGv*x&T(*#>ZIT8nuD`X%ZDE1KL2}s15YL?h&XB^o`m;FH+=V*2px` zs15WYPtPE2pl4|p(lfENfu46c_Y4YX1AQ-Tpl2G*+CX2!8BaB81O0`J$q`8&s&}(C z(AN;J8nuBwPoo;OfnE>=Y>PI~H);dDlsTK0s@4X2Eorqj&>OL}fu1F53SS%Oi|R`o z=p~WCm?diDkr!0zHXajwtHqZ;Llpw=Yqc+e>3H9L6s15WIw2aJ`^P!oOLDRYLSFXgvPgafEKrj4t zJ!%8JsXA?-&)2@@li>?tZJ-Zm1AXQfz-R+~KpW^YOWw4BzLk1%|K!dHCVT41jWpP&B2wz@z}1Z4Lsub@O>Fs%G}x!2LL`rT zpHYo8*q0BG<|0jiLyT(tDX{~)V@-pk!M=R2?m?=N2K(~C-LWPD4ff@Iq}AlRp$VeF zz9Jz(tC6DV@-*0&w|B>y2sGH259=PJ8fmaE?uY&?(YjUlGfvh&Ol%uAoYwXn3p6AL7`r(ZdTXsHJE& zdIi;}Pv|SGp!$E)3Q8}O-oeth7mN@-XIltOOzAB{VNVHh)*XqWiEsx|v<9}76s(rP zTr&u**aFyBf;lpXb-@gz!T41KTZqNIgIE;5fw#iJHY?U2-;D*^7*myoHok%`SsJ>P zx^!u1)1Sq;&4(P6hVG~kXLE}&H1u>#oE=ofOGD4}6KB^D zIS1hmM*?ooa3GsXUSXQ9RG~wo}~)yMu}13w7r7^ z%O<0}EqoG+@L=8ExC_x5%#w}M%46+AbSmDM271_$;DiCMq7}GwhPMJdj_6jcwTFIP zmb2B#RcOFt7{BuKg?fLZHHMt4P5>j}z8^!Y{|ub>v-XSDlq1+iK+Z$fjs_+RjDo35 z935hf^VhTd`Kv!syQ+S-N6|p_%NJ!DjchrE{QHwlRM-RYMlPUwsR}CWdt~BNl$m5= zqGaOIBTXhIG84_##3Ty1H-%q>u4Nq@s@V(*3f^)a5Vh~Zr-j~A$UPGa&xcJ7-`&l!!-*lvPI=DUa4t9-Wu+dP;dpsAd=_M9K#!<*D#} ztCW3BqRLyIUOP~!XJN9o&e0Nb>!o!L6Ru}}kY7Klz`j@`v1$(vkK+Zpa9B~qVFhWM zEqqxDMx`F3J>p*2YU{Y?7sWka$30()>D%MJ0LhzJzAKC3t`y0?J<@9sRwAt`inK~6 zxJrb5>05=p9KuT6i;Lo3tm9rR!sg?aeT+?7PqP2o_Mkgi{mXa^;t-|7;Pc2K1HN2Fi??NL+Hz0UirM%N*uxuVep zt9_HgHCt~|ifYgB4Om%kPSTsbchFZD0`_40f!FKbE@Jz(S9qqd-qyK%TRPUCp^(dO z4_;4uBEDb5>wPWa`(F9my8Pdl^8a>T*MOIF(%%*F`dtsXe)n&fl%NuY$?hU1yL&L% ztuwbMow-kXWR6E1sQNsw0bKJ8EZO-K+BMfap&=ZW6v+Z-y&`FV~w9OZalV8L@>g*PG$A@a1|l zoD;rWZ$=#9%k^f&Cw#fy4A+LT&>FekwC5Rvo#;CUhG_lZX52((uh6N0Y1(rq?-g1Bn5I2<%3#0iPT8BLJ*MnVQG3(0 zr(vH8-3cU3d+yZ1{)9VK2w7R~R86R1S2fV4=Qh0oa#3$Qn_dHLdTu>yT;m&P({me` zfI-lv=Qfg&LC~h>_7+yXq4qYm;-T88G_~youwn=wV}Wa+P0wwfL81bsvFSC?rsuYt z*dtKe^crZ>bNh-E`IwEAQZ>+~=eCMGJ%eb|bNf-DEu?2+(WdA2XZ!0Jv=5DW?m#l{ zM`NBlsF4jQoX>)hc|nq1SVCR*#<5n6^O zTI<}AMj%@2+|ev6Q>?Vsx%(B>1g&-MI7#FdDF2P}V0YKk;%&gGicNU7SKNi?P>GtS zRQ+hJbN3gOt1yu^O0;2~wJv#%Q~)2Ufz~>Aq7*tGs)5!z_W&tsKGZPJT9;hQC6#Uz z64F3xojZf;t;Qk-wAQ&Zd(zTc=N_2Psh;2)XsvS(66{JWR&+HnyQ=LH_$#i!BcQEy z4Yby|2Meu~Aj4Dxt#$5fDWM)58fdL^=jg&C^AGsY%*mkbL-;E`!NX5h4Yby|`wD+u zkF?ggqjc4Eq@j`eu`ffZ&+zxDR|k2jJ_# zAJeex-t*l-?-FQ5KsBJ`V}*=C1g{= z$R%$uETq2^2;T!Z@&F#uC-5+@m}7j!9DbfbFX0h?4UdrC2hX`7sm1M*@OMd>#Kw$3* z2B4E+kHg7$yz~JuWqvu6pOcAmyV*NuHY_P-&Zh=o%a}IM)Tmb>O6ll=C>gZMd>weA zaQ~*|XD5}Phn@+a?{gfcX7#cBCM>_wVQ;nu2JS^w`~Z7stbvT{gOy<@+7{{&zuMlR7q`TYDb&!= z;u=B*d|kX(%4+1^2&Wwq%Vmy@Z<7&%tu7vXVKs7}mvbtDrPnl;A=o(xUgwtqlmAM#JFKh z@C}I=H;idG72}36ftxciZWvoe`rg&C3$gm%K)9tY#tmc767JI!W5$KPZ%d3D#-zOZ zwZ^#Jk`g{${9Q&#tmbFZ|jV4!`SD<4;dTdhB3hp zoe<-Ov40RhY;uen#@-^_F+Ii&V_y>V;s@S+$ujEOvB zmd3bYOvB4!+%Q&xB6kWK#=?hzui2&;UJN)cRm2!7yqtb!*rnfPvM#+UaRZ*xGQHii z;oE^JqWxZ;HjI-|RVkARa|2hLLTY{jF*%j^1CZQK=J&RfnccHV2A73tRx!H}!!f`q z?w*y44tQ}DzD>X*G5`+_xc+5UIZILY_mDe(-q^H1s@aM$6YK;^cAi-=DWJy1rjNuZ zyyJ&gI=N7%*P>5IGf(hdo%ECNZbvm*rBWan<}Z5>LM&COH%4VBltIb9Xx9qH*ayD` zsfD|&*#8*WDuEJ8q~t(u&^yTrvoooX#a{nnTcOwQK(9X(is3g-5z^~lMi%=Jcy6F#be`qR z2khgRlJST9ci~;)sX+L{Xp}1e$X@9G>27JGVL8LWAhjGH4+I?9d0!5ZO$1uti*;4l_MrVh$ka3ICVBDwr87%Z#wJXPFB8r+Mq@oK`udP3id z88SGLfqIj!NIj8K*I=`u{yE(6WbeS^dM@I(Sh)-ywM`J?#|+tGsXD8w>TQIe+ ze~g=cJOKsZ>P1P%o7`fsVn1r7&D#o4+&s6RSU*FzMaI-w|; zJGMIN#R-M62vKmc&++(pdN9^9%5wI_i)efAGl}>4PjFPi7xbTta5DGdyM*HbQ(O0y zU>gzYOP!6@>G*?sM^R9JjT~5sfKOlv35*V`0Z2=b|L&mPQ{w_5KTHI6*S2w(2qH&A z(2}iS_Yv}FMUICzBOzW{tASyFZmsSW#{9e>ny12jL8O3XGxZ{szB@Vsbxd)lw0a* z)cp@Q>iY-usGI-H6HqJvGf(_4&l55?1ixi&_#?E{fSw!B^;FkcRp?WBztzQ00|E{% zWK!wf=(U_I0s*$`%)QwFO+Ka`2TYa{x8R7&Sw16f^<8p!V2 z1t?at1lP#@#qwVzECgZQp%QZdd;*{p!-hJKr7$X(7!Kr8CY79wAOSe` z$ghm!t6%P1Of3X5#i0quQsBw4D&PyA0XQl7Q8$IqzrB2>hE$d+c-;J!e8SyjwlfPv@?>d{u3JB5O0{EcG)zc$n8a!x71 z<)l#ZwOOVSUrGcw8}iL0SD6gd*WmpIcfa8Bui(-B?XJK43JabNa?v0BaeWZz7=vy^ zztzRzBG54&{;Cz|rW`E-qe))19$t)&K-QW@RqbBs%k?!B%=LA;b zbG`ytiqq6ok`tH{0#q8uLoZ*#digR42wa~o%NKqf8^)aN4hNERcF1o&4{c_)o0*K7 zhV*^v@ezf=^a%{6cTDdwn6gay^Ol_F{~GHRhYKYA?t@Lra?XL@H`l(l5|0P&xYN73mc_P=quHcSnnHAJ%Zx zm{0wyi0MgpJ8Dr8Q%3vGr1zgm&l!lO^}lOw6FZwMa=I<3_;t0bzpk#}eCHm|!w4!k z-)VH3^POAtb#=ykU0qT5y1Jt9b#(=2D)V)9e#Y~DzvQ zctM6#C!%0I7{N00C4~BTc=@I(P(!<4)m8A)3>e7KTk{AW-Y*afsobt&#K2H3=4#dT zDv)&#BjyJT&B<(UVg-ge^=1HZ_C`kSQFxdct%37bBL`Lv{hZO71jB)Kg~2p(V7<)q zaA3X8c>a4cnmRwsG3uUCg@NyKENBP8bmzSwX+f#jqam-)8sj|wBTPWfvhM~kb36nX zA4F<u6CxNAD`PLE-OTikU`4pwb|_ilB0#7dTM+aQ-mtO$OeHg^f$ zVG2BCsN4K9wnUMpeT2(Vtdj81PM1fl@MWJpY^=*8R=B3M_ni=m*c~p9SUHSg!?CRe z?{L2Co#h4c`lDwVFR?sEO2?m3frE& z-%+j~5k)8*u@Z*5Cr7L}Q+(#^MQufhkb8us;L{&x1qchdek~ad)B+Lw4Cd#E|99>S zkQ6UVVJ=nf*>S8{3ID<8E<`Od*M1za65#9QSe!vBz-MG39)V-=Ncgnn!GAV9d}-jE zX9dm!9F&&^fso6W20Sn(fCgF0!#$D@(5C`-z$v>2j}(tsDc2f;ToNc0=!?`weflL? zfZ3|x+k&9OMr5U_u)AjvZDnKtJA>~(Gcte)Ix7R%a#E-O%ej&YySv$tZzj2_*EWok0)BQK2ca#UXJRr1{e+lG*=Fl_BJacmV#|8tqg}sdmE!< zIN)heRi1-$dfi8iOpg@Oc|OPZy4P#V!$S* ze;BQtt~%L4gJ}6NttPGH{sC zpHm#Zm(yTfC5Ub^Smy?rgzEYTax|mh(f^rr z*Sd|r`DSUZ^Y==iZdM^n-ze5iPOkw7*Cp4j7B=ru3%xD^rDS~*09_Gc>|^ofUImV( zHERo-TK)6IrFx&q{3}4#L!rYD zR8{5x$u(eq!BADX$Y5Hjs$A`PsH)szJQ(oF+YI=Hp&f_MaH2H$zBDhExOuVSRI5~9 zvG+bCSdm>I9-bZVg<{Yd2!9Gcm*f#&;4^?_9EO7O&N3W#`OY#9+HeB@N&tMN7Md6y z4fcAoUw{XKmJP%sC`-&((B%?yIuJ2T)?8w87LQ?x8J-IymzYt%Pn-VxuEbF1zd+=Y z(kmWr?XKwaXu3NYT75a%gbcSk`R2U(Zg^$4iG*SdjV#0@Y(2|4Dz_AYi#bZ}`U=Bs z?nQVxyBTlYsjvZIr;PO+8FwELUN9~D8wRak*xfooVbJ<3*#FmqR=2_L-Kg$dI0LeK zw*p5UQq-*`L)QP2ccEW+EnEeEj)MqOR*fi>EC4H~M4{BM&s{#!*ima;cZ1RjqE#Dl z#|2SMkjkn{r~oIb0W9i32oFDZ_CJlPceY#o2H_#?nS1;JtNwyvdp_7;q&+Y6JZ#S= z8c%V1j;KO=228C;+H*t=U}G4-Mk?yAPyGrF&U@eb36$_dW*3xj5Fr=l=Pj2`=1i@R z;FLK++KzJtsA%A^x_Ui^2H~X80(?unxc&zA^D8fcKS0U=g9A693(4M>(qR4^=&_YFp@Jb&{%ERi7ik`{%|6yu-Z5y@M5Yy=ooDT8CQ5^c#6dcK#2!hk^{V^0GF-S&Q z%~w%Y*K(jD!}56K=`Is84#*fU+QODcFw*wN$f_bz%e7-X2`qR$k%@^&M1G|lFnwi| zA<2}Jgp_j>z_O)yu)X@XTd6^KlygR6#jRc^f+$v1?DLT^LW@V6j_%=0rS$2S#Tzq19+ zJAzZd{Qelups}3q*Z~#-@Ae6fnCeK0IOkyE@ckuhI{TKib40D=MVsK$9BgI;)2?!xHL60s10Twi{J@oN{kWaJ`E>fV07O=`k)2rWk z7V;h}^4{>GkvEJY$jeKQmUknR^+8S_%Uv?tQL`!UV9HCh)7J`Z5_!efPy51mioBaW zd0VXqDHI7!(8)N#c>~5RXMmPWf|w~4sYQ=^9<9mhJosT>;&Bgt&=R))!sWC+ z=K?!kg2j%C2T{#dypolTn#(*MM9sC?fp^gu-ohuo?ndaC7r;Q{bf7TY>)>M$Om9A? zf zsb#E)t!Rw_Y1Cb1ti7X9_W@}%U8$9jCk=}c4siVlha|&?#XqwDOZcv)Z>8mP+)^aC znZ8w)>$so6=Fx`*b&(ZuO8>>SKFSL59Eb3^d`KQ6d@=tFGqk_1e1@y!__J_92QzfI zj-irM_roz{%+QGjQ|?PbK%e7WYPn;7TcJKIG3~od`@#dH5P#6i z)WYQ!KNt`~9aJiD*BI(1VNgnT>kK=kD*P9r99`#(z!}U1I=hsPyiZIoMspzAS*e`# z-WZD53!MvnPUa+pIA?~oFnifa2Vg;rdB!ue~n!y-&!BWICi$B0ixptTC1S2O5u*^-dWagk@E^SJW@+G^%o5 zNx!5K*xl&h1Vf*5N#KXb&2xC=ShE@h{y2C#*Q?xzoP930LOYl=k*ZcuR~XcDMAdB? zVurFcufpFg=+}SstIaz%1!Pc?Xph*#yu)5_4`;3#})kV>Y!e`y( zQy(*Y9dm2qQ@(JXNOMvR)o9tDV;FF5xBdRnUvY4}!fxbn@X?ddzZ&`=oVIFbjjb9$ zrw05TTVYSaH~8NLzp)7M=kP5mEQY;!&`J~U>UkB$FxW78xZzLU19+0t%$8v;aOy3m zS@xFGEPKmomc8XP%igzQDd+30PqS>f_n)@9hGpL&S(NhUX_kF>nx(H}B-&>mxwWZ- zw9 zu~r&sSRu}>E#hqI5a+gW;@q(l*=UVzo-MvRStG5n zyP}Y}HFnQpL2g+l&b=$dxo@>N53Cnw>jrTiyhogewu`fEr#RbxD9$5qi1X-s;(YI8 zaUTCdoF|+V6M8Zx&eK_Ob~K6e%s_E=bHv)5V#7wm37c6=&w-;>`M)I0t?t z&Ot$JIc_aIxIvuRL&cdhOPoU%i*x9O;>_J7&b%kZIqWCm%>P)N!-Ey%vYv=nN%gt9h2l&*Rh${u!+{lNEz;&P!P;UC^k?uK zMD_1Bw#6-$+DoIT|NX?E22ua}*z-{TkAP~^n)p6i4IKPsA!G=t z28Ymw4C#~c2Gg+ zxDJnYcIPJI^w#qZj^*uCD~1V@x>q}M-p&bg*bf*_AU;MNiE;aEi!12W?bO+ZeaLWu z_-N-)KJ1^w3B*S`2acu;9^6%K-QA{lm3L4VXlD_&Z^d$881EqK5QvZVG4xW5PG0z7 z@kFW72f%J~41hlGVP0^ql1WRX?0g?-Tc>$6{6=4ic%6JtVy*E4xQ9>6*v>UWC)aw` z7B6(WgtA4BS$ZjkdGh?e7x*@S{o+_XI%_P^VnpiBGa#$=M~{f-%Z|Od3Pj^A=0deg zX;RR;T--{h@f3bQz3BB3h>miH*;~zW~hqmHvfWP@4D9H&IB624<`Fqz+TtY_X=S;Oz z2aGR9Je!_m^N8I8u7UjC&$+7aWJ%#(Ag9=m>Y%B=0UeL#0+)VMABSftJ>#wT#9ND5 zUTI~f{T}kL%qRL`cJh8$bY-Rmmcg2!krQKx@BN$^R@wCWV(I}_i<&wfB$qImd6qMA z?_&CEz^n<(SdtSb6h~~ZDyNM>$Q%zj<8`R*{LSELUIN792B_-^sF^fd1}_DTg7Gk0(?P0pJ)8MZL@6|L z8t|R9qEkqVUn?!X^9weHg&w6e_Rc5R&QJGn(#|`tVB1{n;iPT$%A##9kafYqx}h%A z4Heyt?ekHOn(b4~#$SHY#IC{W!QZ#2dG(d%wE(3l&8wd@uj9dC10wrdgA?Zf_I}PB zJ8{5(V#JHJldRD|OmZgUdBC&9jcn}z-N@bpa+38io0`MxDDj(m9;hEh3eF*RT$(WNm2E=fyTrmFG!4 z@oW>-`4qZCaU#3sV83DM74k?^~CF&sNVCWo_K>Sx_DAgys?S1HBah^ zHwj;!)Dy1|zC5WXVF_QJ)RVAWSxsFHh=8IKr1F^(1`4mnZeaYo*9| zQjaxH%8EzySW_gYJfg?CR+I%E(PKTFFHCE~OdblGj8K0IFG=CCln-jqY8H{RPJ_Sw zEIj7U#LEgRe&Ya;NZ*s?y-eMJm;XkI)iHkFVdCM#2cn#q%5%i6nR4KJP)TQ;nF zkebPpV#_+nvXCVmVV-wVZ21v|!jR}9z&!7y*z(CDx;z-HX7Z%ivQfgbAlf|dq}XyP ztFX{BSk3cJiY-61Cnug1Th`f=lXp^V`Jw{7aGJ@JV$1duY@vc?@}$^gtVbrK@@Mi? zjIxOmLCek~Fj6rF>JpWvH6J}P?H7=5BD4O(s!?neetCOQ8LZ*k3$DW|T~))k7wp%S zczZFQn=-1#bHO%K?GH230lxB8R zo#4y{VyB77t%BVP&kl*uk3rKVXuJeXW{|{sjwwtb^RNWX{2>ujix8g^FlA58gF@LwDBROW>7PxXv{Q^}PnKY|HU)p*M7fIUqs2 z%CDE1aiQ&LoKKOY?Ei8uq4$UIN^NTIjYc5LK`kQ@lS5XL)TSqrymk#<4YZ$JSsqSC-HmGU zsqYj?_XWQGUXNPx>he4&4SUq(`A49#99UuHm9IIC!(p1>W`15yzK>TRR>FU(hYwWp z&Elcv8)5e%;7ceL503FIwnB1njGYVf;F#SO60cQZ9vlO&vg>?d9vq`#H_U@$P<8lf zF%ss%F@kSMgn4j`hEri493yaZCd`9lWD{lY>M#$E!TS(}YZt>jI0j}zg=-hXJUB+^ z`?iF6a7+vF{aVA^M9LiE+Ql$8k!rXt%!6ZC61a9T%!6ZAlYa1sFb|Fqd|PLjZ@tzM zKV)o}2geA0=!7s2j=7fjVUxq$lzArMj_F|@9CIDv;d8<~I7Z|dH80GAV}z!2L6`@} zXn0YW2gis!W0r<_aEykRg}HBY6Zzoa81n_Z%VQOSx+}Zbu&5#wCdwE%+=qTLsp_Qq2;@u2RV?x^mx2Qrq>x`zOaGa2_t(ojgvPar0zVk?2v*DiMdPCmilQun(E z4r*hMdne!|_iN(458Kz_lkhYjh~Kr&Q77$qwr=}iMhTKmxw=o4tOOjo5)acIU*bQ+2h4t%UXB>ZV%4YK<1^qy$^HRg@W)Itnt`AiXL!2v6NqUENem zMs%m;eql{paxlO+lPOt18VafT3B=@7>^vZKQ+4$M!PU!<1cOUUZa}cBn`+7JfOS*l zG1xvea&n=m9={!L%8n{D)$6}$V0{Rsh8K}CBg%1H?)Q<1-dFR8gzW(1JqOtV$6!D% zd&bb30lAEE{i!qY;tmyHRWPc5FubyXqMXzL&hGLHvZL5X5GiTqkN0{7nD8(0Fs;7Z zy|^3}(CX!0Tp3Kwy|^0I_u}qP8gnnM;LW|b8rJvX3T*DhWu18U;$A@5+>1*~qjxW^ z(3^X4mlAL8#bu7YdvP_a@5OzFcyllAk4bOt#TC4{7xx#$n|pBuZ|=o?i+FP{E{o8+ z7nffYdiUarJmy|pp)vR3YFOWkEAp6oaW$;(#obLlg_FHP99X@3aVG(eJpFu`O(_mGA{YJLJe19mF@5|Fyp_qZ3A z!O75X5bWKH`zc_3FYZ(5Nj|mrltQcbKZaMYN5j%(cBGKE*<$1j1w7y-XkN|EegMUI zeT=P**S^m(*m6*I1Mrrgx}j6npEQf|pnN3nr0xMWU~`L0c@(J!o_PZ%y^173est<& z7)?31;W3A4O|u84@zrC(p-Ou#y1so_Fk#PhPk7o^OwFF9Tc<#b3a^Zo5;^)h zh|jMCaScPGry-POYULO=`Xsz8Q>&IK#bi%+^(ulgOiG-%?B$0Xs%Den!}73LtuG?f%)7zZ(? zsigFUNKTzEO(jLcZkkF8H|XLZ#x#`_!8at*R8lmYN>fP@xH*%ik^(OeVoXy>Swgs_ zE=?t6HQ_!@X(}l~-?t@AC4~cl)2}s6C54jXAjUM66b-kfsiZJlPXD24Dk+#Y6%Jxd zQ%MngTW6X|%9F$o8Jnh(BKV;b(o|BOA%588G?kRw2zN|RQ%TuHc=((&l@yU@)Vws6 z6rt%{kfxHN;YDdGDI(99rD-ZD8eW#BlJX+?V7N}P`KEX>OHnPP#?sF$O0ASJp)wiz zvPS{r0PXYE*Qur5Y1!s9ZHnC_btQu-k!B?jGpe%p1F6SmzaDD*S|gFxUzK8iOuY=6 zYHH0j)G6$Afr;|#Ayyp+v$;>5H?7duU%LZmxj+&2`ueA6>$cMhe&$0bKVOkqE|p*_ zAWL}nTEGF>1nzDiDBaTK`aGaD77_D{G>>*?JY!bb1bu-3bqh&Ot-;Emp`VXb!yZ1nD7q&Ir^(S(iOeJNq1 zcMHAIyD7h?cefEXdbftP-pvB>^zLn>F?zS)jouA|PG0X8ywSTkk$8HyEa!~g&GPZ| zZjs06-9lsZZVhX_TjVi%w}!Rey_4ypNt=%<9oRRN`99C-12{@yVvK>k&wT7lBy%mu z7}JhPCC0gm)@q0`g*eA`r(Kb!m0Qe9m=^aasVF7Y`~+f}Dt;f3x~ZG*8q61c2?jgZ zldDSE$de@IPiDLM0dyLfGL8e3`UE5VX$1P6t<-q{$~k>`KPz3LX{FmlLBe@7H4(r; z04g|5%FkK=ZyMi}v3F*UMYvd8vYuv><>)8BN_IJax{w)F#knjHV58SqHrtpKD{(#K zpX>MJ$4)twT7{%eA+Qs`IRLuLUtKK!CXk5yZvznd&+~rW<^LMt-zI;xaMbJItjm-Ffh21kgKr)_%!9X%TKr((Rypr(&l5zHY z?`I7%8J9tz9fUFntR;j0dJs4WB$Dy_0py!!VGzi?4E(odT*fTEXY*YfXYTo)&G)d{ z1<5y`JdRlj5zU{scz6~=iS4@=82_*pT9q~4-4IKR z(?||2Yzaa++1kO!={+CbW++;=3`0TJ4!E3^$;ig;;J>FF)vRHRtooIUIs45f%~c;j z<*ieGXdphdswf+^uoyr5KhMSx=$E$d@8Im0VTCGr!EbemVo{+26X4y8dP`8eFT*>DaZAMOp0Ctv*nelonAgDT@G|4JEY|X6 zLaF{unW(QySP;(4LVdPjrL=Hyp*|l#E4HEKD(frD>457SjYrQ#l0BUiKD$7HR^onH zp{>N$0VS7WHF`5?4)Z&&VZDXj>39e)TxxR};4sGzZZ@-THw!7}E{_D4uG|OMyf+E& z06Y?_GN;t9t2oSsE*qSEx6unDo%qVc8oLd6D=K>1*b7nGQCSX+C9~*jFw9#Te5wMy zT!Xi#^Pnuo1RJ}_0d_J^j)?U-0gEsV=J00Unj+ZwOlT_k#ujjuHci06e8r%_{W%)U z6l^%y>(wktWyULDkq^Y?aAs&zDPa zwZ~TBtHnYBtG7QwAYYv?#nqmM-4s`QeQQP4Y#GZ+G9R_ z{fDNw+PjGKgGZ#e+7ot^TmoPNf$Q)d^&SF$2e6&M{7aSENnj@cv-g*ImSY$9=shZdb3ng5WNK3U1fs3hoN-yZ_&>y3aX1lLVKK@AG}$??2CzlkV#3 z>Z)Ft{%v~|JG#HxIdLqt#m2`!e69st6NWkdvk$YL2X8qoemkd(<|Z_(N9 zzeil=m1$CB`{`$+vp~@}`{?+!h|7F7UB_QX{6p+bI|rGeg}BU(CSJ8rDVa7+e1F7c zHk;v4S+xHr;xg|ZtmEqumx*ttj^7Fqf5G0AbBNH_L-kMz|H&TYH&oL$Y}#VAx|sv( z*5OQCOV;&;f6^Sa)J%*!x^8Q4L$+>Dfpyu}?J3d7B2&}dCE6QNspuXgrZ;oDG35`5 zrMlDHj_%<+ikv0#APuD+1ks4L&R94c6bU_L7*RQxo9Vk(y~U%q_D zr<@x)D!v2{+Io&>>*f3#kOCH!vlAZ1CX}m;%+^|w*)2}ce&`J<*ey=bexSy}ZgGP4 zgAV5;Xg^SIVYfIz`$6DUi3IHj9d4bV{UG5kr3u;(yAi*pU4r(*e1>Z~CTKt0$Z*%r z3EB^W->o)5`(ZZW-FqZxKa6L%N1p`k2OaL8p#8w=z;1DZ_QM+D^c|9*{UGrE!xFR~ zPy~026SN-$KCmG{`(X_8ZktZfeqgO(w>Uxjf%Svk;sosn;iqno1nmdG88$UR`$2~f zOwfK1en!kn(0GKS}fhP;xfeBOu>MYu3Ev*o0jgPbICJQnOi34dm~yt7l;@qs;xQ- z&vw{Rn}`4HF9Mhri|TM_nEw!%X9B81>+wJaO!*v_v1@>)q2#)lkKon|;h0x8hB|XB zSR8j2j_>g}?%b5)E;h$&JdT|VjyG+FW53$Gd4_jBhPvK`s?lS+D_PKEyDN+DFa;0! z`BS~06(1^bdUsf05IS7%VRkIU*tDYI?FJgtdl%^Jl?dmv+|V`zZ{r|I9ky%0=mIF(A1y``3E&cyKd;ViK{$Li z&UdFG5W=k?+`iGShW`S@Jsl7EML|i$=HpSKa%SUSF82P6zo2)CpgzuwQ_Aq@tB@=^ z;swN3g+wnTk)qRgLKDlE$eqOJ`!W1DF@#|39W+5fl5ze#HWxk#-QJ2Mie-S%QVxkD zM}j_op;nzBek%&|9jB92ZtGo8W0b%WA=Mj5{Jfnz&nfJWaEZ7}rC}&V)Tz4#HFxt3 zVKwg1powc)b23F0>k0~{C~RQslb5JD%N>s*Wtw_l95HkAb}GO;)o~TTPQL63cU+5b zzHH8Qe1}2VnCr;-CSQ(%1X;Y6oK716jmzZT`FjRsU0X$U9G6+UHwhQS<$!3bOQd;?i85OlAO_AV7P1NBxf|i z?^c`Sj7C{7qa`_`9m{Z!K1t4KI@~|W8I4tj87;{f?MLGD9g^gXCh-2llAO^(VZgW9 zKFJwP-~$_yoYD4V-fh!K&S)Pp@1U_s&S){>51y3dj3)fl?UCe+COE^UCOM<&@PSFr zXu{8kSxL@lI(%f3Gg>Rs31+kyt3P%a3MwWSt%#~(Y|`kSSi9Oj*b#$ zQ%wF35K;0v+%tzxJ~MSth}Xm%$}}6`Q<3*jM>f zGSTHy*Bh8BW0Kk>R#3@VGN(;YJ*p$mopPfbOB%`%&`L5BmQ@S0qm&tJ{EdOF&&S(; z415m=?^4gKg`svW>;hb=g*FJx1L5*{-mke@xB?WV7G?uIvlbQt^4qmgMdtaF)?4u) z)(pehsXBd+?4pc@N2!8c5S1#}QL2Ew*ZVnROch8^eg=rr zlV>CF8$J0$ph$HsL|`81ZN4Xei;9st;|HVe1$r=^s{zq}8(__&1A2~wr1#!6LD-FZJ}ys0WtebvY( zs_z-(_zl%J61Y-T9|CtC=xtv0jRTfc)imVGtf~_M`5jf&#pBttp5EjkK>_C!Zp|3C z*8)yKod#bD8yC}_Q^0wrQ+q_0LKkZ6+FMazPo5ei)`Dj3dPHTvvPjQQ?7=+2b1%$c zyYK|hy<2T`p>NcoyW?q={4c^1jm!${sRI+9J=OZR?5WUX5DsByfHOsSe?&5O2K0+B zY%SVb;ZkF7by^RI8C;#dMOY86P7W-deA&9~#5~%_>PnwPZDe&TV^EB&+Czx2UmSF{ zAvI%U4gNQT#&og~5AGU-yj_FXPkEu4Y#1VZesT;dpe3ol6W z1VZdB;m6opf@AD09oF`i@MG*P9oF_%57M#hEmnVQAq3I(7Ex7E!VfVRsmw+uJ>_cA0b#Mg>V!UlSNHWLZXCna6~5dRP6;PTO zTA{^9VgJAx{yIidn~N|c^;G>KqxT@Hr|QoTEj*d2+FF|Y}NXA!8tpZq!$U8dAJ33gl$=J@OAL`V<{f;>tz1>i`pdiD?+_H^4cK&I?nVkE4g2hf1Fg(Bmi5{Cq;GM6VKQ_coeeh zbY?|XbLS$|r+JNE#9nP_{37OPv*dE4@r&5=+bl#>G`?WhwntPnelfLX?QV#Q#!t!! z$=o67Oq9-4sj5955w+J8JdMu(9@5ze8W(T)b@wkmZ9nk}L>S`{=Elj1;#n&H;c7i4)) zLujBA9zbT~o(8AXbU4T5Jq-_`WTz_bUWW1{T$6BlPs0m@ zcW>?To(2i`D0O*H!z+aMZ0GWx1_}4-=<=Qh?1W)2t+UH}8g#fi%6l5#CY<*)M0rnx z#CT7G%X=E|QoVBe)=C?G!f?MHF7IjJJ8n+@J}&QR5ct;pUEb3m;cW)Gyr)5M1`Kik zlG|q9#XxXIOm%rr!)FYS+}Gtj4Z;-eX~@AKlY1IMV@y}eHSV^o$~@MBc@rhfu%NSN zhKuvV*b7q;xu+rWzRPC=4J;t?VZ`M<4g7F)1ot%j`P*iq!R5}pr$Jxt z{5p!WFL&0X&efytaU{BC)Uh>OGwQJ0hIc>osN=?si%}O|i9m7DOL!(o)E{H5^cd4u z7BdBc6H9KY$!X#0&;MeZM&ISEx0|`e6?2clOw#5V=p63i=;YGlK{6&+z?6Lns@^Y_ zTTza_DZldR=s?G|xfM8dz{VAO zZ*Iqk%Z)A_&T+ZX^&xR8<1RP41YVVJxzVM=tzB+(Nw`a?%Z;w@iC@#su`UU8(owqx932Y8(pJN3AufT zxU3?9_aEkRql=?Acbn~9ZgdHJV1vtzF7~n9ZPP9{y2g=*L1SHRbg`r74xZ$4qf7Xy z+r#BXm*5PW>T;t?hYxhQ(IxzhnB{V#ONWnixzV*d>A>*vZUp}f^0%`Z;1|Xzq%=qY ziz;9g#yYsMQhFk4Qu-p8kJ-&<6tcJ z0w9;Y1C4z6{)pyZ&1e#NkB07z<+Dx8rXb2gn3!DXRsI8D-Y=Hly6wL}kH5A{QIG^y zGzq+KAgUebh1?@VeUK4-X=C_B1VeA)k)g!%v=Zm6kY_3JJWGk^b<|26pQu%NmJ-ji zlz3iMpv3cx5+6l;qr|5&Y?S!l8Mc&oo~6X|j1ni`c}9uraG=EVEG3?2De*i@iRW2L zJkL_%c}9s}NggaEo@XiXJfp+~$0%_f)=FIXF-lyA10|jZB_19O;_dzF$JZkn7wt`S zTYK-9nZmCl8tr`|f?9ji6}>&nFOb|4(%SoG05i0AyPjwSC?n09z?l3kZ@%r%4L%d=R~YmGkD3=F1Tpi=` zpbL56@*u|LfyB5xh+4~oD3^F_FDwtD*76`~Ef1pB@*rw052DucAZpE4QO;K5NpomJ z4rZ&UHCsh#_?X!$YR^_t&Q>C9-GnG-D-m$mq$sT#Gh0Qi*(z!+52E(+KyE$c$HPKn zLgsMZEDuOsT;?OJ3c)k$f(X|Iu2~mEt#v`vS{Fp^bwQ*z`ir@RGD4#+Zx{fPdOQk4 z`o%_kiBKPKhvqqvy%2VJgjX8Pi*j*$1OVCVg2>+i6!&OXR^x6#l&f*GF7TTQ(^QnJ zakDOvZsn~DB2Cr>A^moaX>P>qhmSklV_ zp7+P1tj;!XV(9YK?^q6_r5V#rZX1BkHxigTb}ybz$}KF^6ZZ)F2qddoDYIH6h@{7rrk|yHJOXXa}2R##V zm__AYf`@UK$h{une5S<-)jQbnM-gN%i4^DQ-lTQ~B%6p_caC+e>@)jlsgRnqC4WDzq0Fn-bSz4)GE|4?zWj4Q2q*5^4Z5`)lhfj4@U;# zX|zvhJA^Z|4--A@BVnU`bXaR2-sa(H9|;@n^D^N^`$*VmA9Pw@`$*VmAGEHoeRNoB zA8edh+DBr(_W6`)eQTvlW98>-AC5z8PKfpq_}2YJ`$%}3fuel`XTT8AKKzanY-Q0t zL(rRHD~t9SN4TYZhBIxj677Rk6>VkFJ_3iWEZRqeHQGl6G}>nuW*EN5X0?wnh0TfF z=TWlOKBm8T?l`2L&sxaS(?^J5LD$=6@em9}qlCimixTPsK==bCN{9u7Ka7YHqSRq* zPK34wLO~&uREW=fYSz$>cogMnB^22k5qjA`35E7WSSuk{E1|grU~?j|0D&Zy0@$1g z@ob}*d-YlgMYIy4%8V2$zr`Y!5{e{pLUa9U=>HBS2EgYR6{h%uG3}- zqTIfY<}N{MoA(i=5{u^0Kqy@nh2VLQAz1ca2o8EZAgd~O5%+%4WK^}q2jf)eCOnEo zabinV6|)iBKF9=S7cr(I>$8DGg0hit+XoQyQD3z)wd~b}%VAwqr&t zoe>-3#eO2iT}&*HqqT~?f`;HutkcUJA9hDXgv^oWAeGYx5aVZ>yFJ4GN#ih36{Ptp zHn%{jX{58*&^g4TQ>t=^nAerv(5c8@KN{_t|1zFV{c zjOM?FXDmOq3fIo$PsU9nx%u;+cU4~giFoGc|MNvx#q)2&vmpOMJPY%u0$!BAH=c?7 zCxM^LUx{aN{t~3N%HIHZ>-;&m#3q$L8_$ybjexhwp9GxJ{P$5xS^fq*%k$3xylwvN zD7~HMY#Wy`O=Ch&K*pghPDp$l9_F(N@jV&VUs8x4#IXMCYn+uBKNf%j4o5w88Hc6# zB7!f+Lmv(s-!xZ$U)I$_QL<5kxnp3=>mMfG@Z#67H{mRB$VkxuY{`os+yZAU4)Tl2 z5Kmy^80ksslklRS)Sx0v+zXr=@-X7Vi@sBB`R3XwUVN20ZzSlQ>fFzCxYG_PMf5ah z1){|hL2mCKK<;!YuJ{PVXW;uF&KVMK#T9{bzJyz!jd90c>(yv&39QO70Y7Pjfds1% zNaQZQd^n1{o&uFDy4nbI{eMBGWbIW(p6lB~ypn$-D&kyU1L?Rv4=)yeudhP9DtTk{Zo(4pRP?qo}sErw`swud-3vD=odK~&ra zmyoTpI4H|!6m|4#MCBCjMotZ7w}WXhcyzSuHF(G7QJ>Udh!*q3gqwv_>RP3b>~!=3 zM7cHY{8P%^>N@Nq^u(yrsdpeMCr!6W-s@o+$ua!x5^ZyX{``-l%l#Bl`L@i`$57AZ zOR*j6+)BjqBN>ze+V*||ocs-a6Z*0@7MIRE3Ag*wYZ@dt%ktX44w<5;^Y-5(kVHUr zsKIk7l%(@kvSKb68%k(9LcO2!Sx&{N;89XKW{~XaMB0x7gF^E#1cYW&oW&l_Lmp1+ zolOa?XZ^nxc+{i3!3+3>`bj?ITMwscl8@sj6`YNf{{ZQ4 zvwbyp^#wk#p_;q;j}pFZx|)mIr3?=mTg_d4j)&;rN!8rd7k=vYsOGM|;0&8u&0T#R zKCqg*`ohnMS=HRt*Wn|px&B>2I@l13k4K=3RrC8WPU)m2s#r!9qj>QmGi4E?CWZ5E z{4yr9Xq{0)q^k-zuV}Z_8UkwL!$|HKpmyc@wNlQCj_`S?l3d-m#S$H(`$PBkD=_RA zIXz^CSVTd3h}K#}W!gjZ*&@wl6#zNZgFWwh8hI`xF-Id`xC7G4MG0LbWyJd+u~N2; zPTvn{Rm`VLEFc1xnK=b$Vg2*gkNv5MXHjRX#iEsGiOw#&QOQ+P&Mf9-a%i!r_*qo( zt@kzq0R^_l9_Wcgs^U~v^#&fjRUb;#=N*LOv_C3ki9AKv5@sv8Y>h3ErlHij?ko9G z>bypF3texOG-&fD3iWMKq)^wmeMDTv(od4~$xIi5h6R$r0y9%w?Z(jhG;bg;_64CE zL+)`xiUdR&)mOVL6x;!{o6v0Wct3XLg$Ra;Dppsn3Ueki;r^_}9A|np+lCf}v!AMF zQ~wGa=Rj3W#}E>64ncRyLv3bwX7yopgolA^p_fo`(vH(iP&-BdRZs1Ur!khl`e#_} zazbD%Z=|toW_)1ri)*WBmsGDO!2xJg>1oxU1Bahza2Cr3LG{IyP^D(Ni6H1-NTFMsa1kbmwm0prF_yWR>q3*RWi92@3yJ4s?P3 z<w0mX>ybdxbU1v~aSQbi3XSY)gUsWL8-jTjfPQxQGAJuLeolJ*Bc&P(7? zez{a}v5Cx^$5EO0Js(o7@vjgppfvGc7~=Z^ttfmctFJ7DsB%=f@o3;go8#mpKF7x- zn9<2q^12a8IrzkbR0DOGdze$eF{_H8nIkG^e>{ykX^*w{h7$vILJpB#|3sU-NDUCV z3y|ppU z7hR`dMNGxrjiKl!EHwXx)otvuGNoR|+!E{37H@rHg3EahOSfTLp&@35o!m+7a7#Rw zdhU;*yo;U>tNQ_PFUGXzCb794ch3vw-Ssu>Ae8N%kAs>L44_{axd05s-Eml?#NCPE zyt8obxC5zzx4abgO7~)9w{U*J0z_soGASIJRPf6SCboOn*<0n3&kv;h??Q3+Wz1c1 zH?67FQ8t)(c_c8KMeY=i6m&vJ%7$(#tHdd&O0P~Mx|IKlK4HaGp6IJAVIqc9Q zx~S-Aybb7H5l*ZEH_441F#MS}`7)v^m-Vw@1Z(2^P;ui?VKp3;<=z{<7Ku6s8B)1F zAYTKL9CtX{;O{t}L4CSUhMyr`&%U6%PVk=XsMMESCA%ZSxhI0LQNoxCw-Pqih8>}* zT1)gz6V=RUl=nT@08mvLw#kOs$Uk}sLjvTYh%O^Zn2p@WOBfL#_w!(RL}ta9A_p}| zNM6Dk(+mysQl%={oF-wEmmq~ps+Dbrrm5K|(>xT4uUje`WkypJtBl*c)O!N1?y_M< zjydcW|27FK_0HM&yg539`$*(6Dl%zQmHS2&wrT-(+;2juhS&Aox$g4Fso>63v$Rv{ zpYNsi*dL6qlUt*EXG0 z`2hy}ot-uH5T=d)vech4m^p0*K1)j0f6f4J1$WceiTz6kkxu(M>TMS3xE5Qf@q-<8 zH5R09*kw=is-TJkU|Mb^|g8ucnf>xSHm(2||t*zUN$ zgi>!|+fon*xGxE!s8~vNfbiKBTe6wv1&r#CJOx z{GRdbMitSm*7$HvSd*U8JZYk;)Ic4w9Z&0|>{ z&e`4&oZT`ij%hFmgu^+_V_6(_M3W2ZY0abRcK^qAA$5m~IrHo&^Xlm*d3EN%ZPS3G z^I~}OxEDt20xT(v4^?`lhj6Ju@Mj^da!ZO3o0!KaaEIQ1M8Q{Sl_|_;{^o*+9H?VSrQR6O+9tWZxk?z>`J%KaHJ+^GVQc|g6 z?Bof;12%%+D4O-u-MbpBhnmGwsV8*|$n2RRbqjV*-REosi;)9{8ibc@gltB3faiyhd8Jt_ zm3kC4A_(hj1dEZrhlJF9WaM=l!D8egFd_)=+6dW<{0K$_>%C^NRO%3H6$-)z8^L1a zTQKqj8Trsguox*u(+I*w8zGyKr4tO+7tLa+REIqb!dEte#mJ+FhSXXz@~w?vF)|a3 z2*NKmLN+4@O*B|4Hai%pK9)+Y0V6^tWFuINobq-={fq-(HxeuK4N{|_k63HcitIEN zr1dh{RjD1I$Av<&Wh{-)oGSGxW_`ggxADodN?i)YEop7-w4g+dbrWU+!D`lea5m1&*rG}etu^QKRXy|du+ucn9nJ~s zv_5v4rnwF@C0~C#P19TeK2Q7{I&F}hrfDuY3ty^X+E6=9(_A*+q>ZrCG|fRTVXg5o z@{P9ARLRwqj#{@4y16lCG-}zV+d}FbYOHZFy#vD=;}}OZz#rGWB6b5>SntFX_nB*;SH`#}WC(wV z#o0=(+^){xV)t#qFTpoS7dFTfuxtM&oOazM8OSAr9Q7%|OKs%EH-}UMp?BHHWlvrg zQePE<<@;@L@rrM;uSrQBv1#0hovLfFv*a!_$g)dSe8UE%?jd+Zi~u8G^nC+;D#lGJ z&2#bH|5a)Nai6nsQ|}q*i#BdA>=YkK+?Q&-}3%Bf8e2I3$ufTmXCM6|rMODi~ zl|`=#seQP~@{viCrY*Y^%-)HuaQ6!hR%QSBXGk4Elkoct#6dTN)C%?%Y&rKNS=}{m zxjm%5VUH=4?`~;mSvl1BEH0MHa&$jpN0c;!Fa=8jK`6=1LQrLg!q}0twk9)6(q?bj zm&kVwTqoS>Y{IJSrNP+C#bKH|(9S2Bn|Y|R%Z7y1=U67Yb-xdPTj-=*TC+DBo|~Z> z$e5I|S9b9oA$1_PNhVr_sIqd{-8XUHV2TAcb@L@w!jHmr&)w6ciFz&Th<5`7ypIJ= zcE!eyDr~AwDV3eY4hwfO>@tc5%m(;IMqs1WsC3; z76C7`z=n-eFEnZA+i6l%@rBU#53=Ph%pn6otE=K&uyB{8i?Wh*g%n58=p(qMy0rQ9 zyWtPNgj*apS?RtltIGHP53cL|3F-IguB*yR#$ek9=O^xi2GVxp*6?X|3v${`g%3iG zGVxu)?LLBD$XB_iV?Vk7_S}5=DO7yj*pQm}HvHvcd6cC+XOtQ+Xh~&Q9|6pLUTunL zjA4IRsMN5LAvHA?Q|>*5GXF;3!1m{4XrB&@nvL$D#~qnDpjw^zBMPaCI0jqnaPBL^ z$FOTejV=b^<8z~fLFx)v%r+KbNj`9K5z)?%ID$8=MZB`|V?*lZ$-w=)CP`GubKIjL zQwKg(QxS!`Mby*GazuRedR4K0*&P|5ZS+E$LD_537JU&zV}4DXA+@$T{%7@8nMZx-esC(7fbXf0l0KfeQrO-yV>o`8A# zE4UaV@~L#RCoz%6s*&&xhI04bI4ojekOW6TXPZTgRz|r}Hg3i1OgPg}y zksm5=K@Q3n`MJ1YT1dULEQSy2JFG5Y;{?=t@_fHo)!E$@Ova;Aqi2ANB#xW~tsIAx z)i<^WsCpdE%~Vb75~U8pxo7mGR){-^B_N?{j`N@k`U&(-f%e(WQG22?qo*ymaIg2E zXT4|P9s%c+a(q`Iy68dVb&`(>g-_EsO(pdF6#=xi^$vO$AbPPbKlu!idz3&iM&~%u z29PbF0CfnIKmcJf`Pi4JA_OQ@WotQ<*Em2;4T+vm}qRkNQl>2<88 z!~&$K%H#0lK76#7+RDA6oPDomD|e{`YAf6a|AV0t9VM-i!KveO>hxt#@pw!p7Lu-J zZ;V82hIi5s&2ZO;3`0}cLONq5dxbFEP<4!#z6aYXajh`S6FOnIQT21TZ3~9oPePsD zyLUhji*=BJaTZi@_l-E|Ev(6|=p?u$Bi6S8 zxK83jLc8ABkq&Xh?_3k%X@5mb#rn;#Fzy0|92Lhp)jaftQsYTun=g^uqkJ?@aRfSu zN4^@Gl-aLlQ<4iX>K5GaRoj z@FXL)Q$Sav)r?*pQvFC_d^UxeM_vx8FPUp%lU%1hug_&-y9c#n2)dm>->F+6=oJ*Yko>I)Y$bm)}y`yeX zPW*n0egtvZq6B8QXlu^2HS7EqEw3bF9SH3@7plo?(O!Ow4zVy60K;q14StK(BDa&! zl&|tzl!x;gYFf0s+-p%g!vTJaHp%db-=aE+Tqd6YJF4pP80EDnE7??>*P^U}B;jn)u4ox)QMQ7#Xc+=tixS9+%x=*N z_X_reybEQF)?vD;+WGLXIvG78@0KSZbdvodn1b>yswAoRpNOiwE0pUF!dC!sd!pl8 zP`-1@*7Vib1-S7V#}QYO{TRX0J#Y|-mpI}HGKncSgd(j@fzrbJ6i(tWK$MR5HPIvu zQk7a&>B_NryuWh-02)=NY5Z+Gd@`COX+vmtJHf#A^kDkjy>qcXTaQn3mUUu%&u8{r zHm3M}#5*{tcW3Go_4srfCv{YjKE#gimjNDW4zc01YEeur&ewL-cqj zCpF(3qQ~djIH?bE^!a!EZyDe>rt9Vy_+Wkh9sh^JsxT6z*7wxs-|$%!>Q0Ca=AGnjxTb)@rBSep3BZBN6GPWCsm8x51tUmFKB|8+RmIm z#xJqbRO%{o{usX^1N`;h_4a-IYG>c-px)Tj;)@e6bxIDoETk3|pd(%9HLi4mk{2!w zscD4Yk_qoy?8*s3{B{q{j)m)S%?U>Qe&;Q}EWLgpK_jSdK*p<`)UP|})piym{lExMG~zKE!D8fYFd_(X8zGyKXRs?S zSjEj^sZ_}k`oJPyZX;NX9A-{5;*~an#mHVbOX877yo-&H&B(Xd;Sj7I&0?w417L&) z7V-Wzg2hOCbD|L+Y$I5V+zCd6!Y~^ln~|H%$w_=vvsfy%?~(ezBEFN2U@`I(7~#Q4 zd{-O6V#Gz$2*MN_A)Ari&B;l8TC-Rxl|&!mfdyXXYrc=1XihZZvuy;6kv+kPP?%#Q zWHZtVeMGR1Zx&0XmRGxSIuM^93e>9^?z=72rvvd*?6hJ`PAc`*-%Z*Xb{eNym73PY zl@oyYLOYGMtWv*%CQk?A=hCgoQ=_=BuC-#cPmG_&E=*nAjmvQBN2KmL6 zH(hUBdBdYESKc3xEUvs;H)Of;UIaihuDr+L1!~uG<$a2g3$R+va^;Qm1JzxPD{q34 z-NHGWcjYCYEx7XLQ8v$&cLmN%c`qd13R1pS@TR9NSKd9qSW{PC zQng%pr4V5zaOD-)D&hsMygp2Gt`q3WD+wdc_kssl~-WbQU+Fx<;t6x zkla2fgRZ=iDpkqmv|M>5feZ;fI~!ejvr>hCMVYR=f==yl45DC$@jLM??Ecpg8Zork7 z{aEt}!_xz=kFeVs5mUp>!UL|nHufS9{BZ{McX_@m@7aBP+PM$lV=BHY?~Y~_;(igi zQ*byyRPMik{y`S&OYtczt~$APPH zW-3{Kqvgu$C#sSGwkxj%pJco8TJXqF%axaKRnpyd<<+45ZC73arFxq6m+#6e?UWj0 z)?aYtozvH=5Um?>3(zrrSKeQ-A~LSLiv=-YDz_MjvI*nDm3Pg2-<3C;V(M%!ZJ3)) zBvlc(@>&Bx6k{r0gR28MaK^e;njSda(Y+;Yf}JL{o{Ft?Jy%{UpB{{F!<9r_V)wT5 z>GDntTzRd0nOX{880+M_@>*ErN>^a23?`NoG1o3avwc5$i*e<(GFv^S!?l(xZ&2B( zK~ONpmDkEBGL`HLMd7>hN*>+&o~W{1d3Ard_;%lwH)sl#`p5%cW%UP@`nj|3%4=iq zWLDVjEjD(^fbA_;UST7cAt<3rjSO6QEg^K}f3wDS<+akZc6|q)u;NC$)~?a)hB>0j zcjdJxSPjz+Hms0&$0nm2rVAQI(%!Yxf`&=G__C`JezFmCr#d-s<+Vzd%v!kNfh%uw z2*D(%Qjc}?U3s%nEm5XdD$kX-IV_cW2QL+h4{m8R8^IFlEA$-W${S1!Nh(^cz)}&M z;2BrmYy^wUc+`zx4T@%C=?a<~xbil~jY?gB%N@kmcUU$BmHIbc`IWTc*=fS5N<9x3 zFyqSG9QCAbgDdKNSKbz}?1t!!h7hVfyq3N*Jtms3Y~97qN0SKF9?fG} z71}p&<+aL|c9DmcXxwz)mA6?ei^Evp%G)BUO7$o;9L}*h42rcleBmX0CWj)Q);y|i z_fxm=U3r;TPrS)Cp03miv&{sv_vKy~%?q%kFg{f2Egr(92EkX1nnKB~%Pm)4Nu-o` z?ILjHWo391|Fvc>5U#v7c)SO`HA)seqiV_PzANu2%cy$kFymr-Pt=mlS4t|?dRv3= zfQ{fcie^1Euf||K)GU@teNbx<9<~u4M8y~ioxuoqlHkhQJR>Uy8ibWLLN+7sbTL>@ zHH)QESAr2K=V=?kVk8l`@;1-NK?95r?n^d>Y(`2t8?0BF#Zsx0yBdUbHiE^-YA_-$ zwy)a=R?|EJMg-wq8zGyKm0(1$-fI>M4w&5x!Uh|`V&vSwmACmCX^o~auDljPHY3MZ z8>}zva(pb6dK-)gnXhaFi;+DJH7>T_+6Y#S912Fn2lp2n!7svewXM-d1WU!5V;6e7 zyFm!q2o@u~vR!#)Wv%sDX|^k`q_H3=-stgfVP<5w@-~B|@tISlp2e)6;mRxcluV`O zLUCuf@@CP}ST9wW5uQYaX zzrdBZ9a>nn1XS@U9`wo>w_)_czwC^g0#{y(iyv^3Wn6hl(;$Bf?_AH7*FwGze!s?* z*Fqi*WY3j1KrWkkUEsd+d+j8aoJ@}>2NuDe3Z{sILN0be*TzUOW zs_cP=z?Ihr8@|rATzMr;lyKPYeff-lcHkK=I zkfvREzsFlxo-41Prpk&eS6&}%*oa!Lyg{0F0U3sDB4#0l0c#F`LcNQ2j zuDmSJa^)4N{m!n63xR1|c{4E0{$+rfY8(+#dq?5x>bdfA`;+G+#_iT0bGjdY#76Y{ zwkq4Fwnc|s;fek~zu~Z(g;#bvzHHmF!)_+FX{i@S`wqLTfAK(R$zhiWbkZxi8^<-y zXHo9}rTRV`ps1?dJP+HAJXKF_z&^Krh?8g42<+YRZGYz*#wA5n<#-;pKW3sQ*K(H} zWwnFDv*X<6mlY-LEAi^Qcm~c{5mG01oDcmjp0p1nSF=#bTS@N3U- z@&1?bsz*K7;q?Iy+{U(Jv%$HS6~k^?eLjwJ0_Wb10IQn!Z}psezee0i5Ne!zufN)J z?tK^;?WEeLFrGc?n6h6^M(!1bkTy`tm6O4l{Yczu|+d-F! zfrIWKQt=#g8L`>hDIpNe-sul|4!W#mNl}$-Sz)iC>Qyg&57u{LClapYxtnp&?d*;p zuAMm9^?WDJ+ks3cP6D%?I8P^yn%#XT&bNT;B+e(a>(F%I#L3T^X}4Tw#{gpoV0ccP zGkhn`E0NntXv&>^Cr%#UYN&DIywZ2ewKIHN=(*)K$#978#Ho|WW%6{eqq^=2Mm#6Z z&(?TuxdB~`R`bP+o?C7=s=Dn5voYx9Ai}IjdLrsgW^jp-<(7MQL(Iy!# z@>^6Vk;~*BW7wj#V8m8@l7zEGukl)xtspIWCjwrJ63B|oZc(T<=7U=<+g#jotMMv`cFWxZLMPcTg2@AJ zxg_=GJ;p8fl3R^iu4gC3JV%qJZn>``qqyY~SDZascFSGQQUkYKMw2uyRqFJ>E%z$` zoJ5coxaA6rjA}PNoj|u-Kf!X#6_`FlADGnV&KA%e8P) zuNL}lxiH+$}I%l*+WQsuI#eYe~WU~6Fk#suARrE#@e?mXKq z*MfIST5h=lXUD>K2Fz&$+;ZoP^Tp#h5gCo3w0PycF1qFBo0A8)<#M5<`;Ud4nw;&H z%bH9QSEX*xcFUEtz)4nPwZ|Hrdyu|cZZlYRiL@R?nwR0sya!FGvI_|iu3hqA#MU`|2c zmTQ&cW2w{uU_{(yosflKG4eHbo&_OhBUp_5Ymh;R+X#LUhLMZRDM-AySuB-WcDQku zEw>RYMz%7i6L8D5IJFp=igO|3mTMtoGqMc36~-;MIV_brC~(WQ5G+RC0wdyeJGcc# z?gk@*Fw92CX5=Vy3IexWs~jIor3wPKTnoWsQW!K#rMn#Q>0S_pm-rfI6p zDG1zho5O;mG8hqe*@J8Zi;>~xbOLU<76pruy}^i3m}4VkGx8P~5v=2z#Zsvwv)yuK zfRPcnXm!&&{k~hSq}?oO8?n32Q-HYVmMdwTW^tOB?UrlNoNG=2e79VS=H=D;6u@`O zwP?Np<;C56-!0dod3{&C)9<_GS~Ty6hl}L%+;Rh&YMYPVgj?>~bul%t2aY{*@$Pz2 zg?`J23mO|5@mKXKv=U!d+IDZeU-=R;v>K*;Ul&}4)08TB;eJctLJho@z&WKkDhDqD zw@Pc^0RUFGQ?A2iLEB5Cd|_TT3+C>IDj#$qzAthDklS9CSM}qa5!G#uBvW{%lF77ALQ~W;c`UOBQ&_G zcN|xjk;^f{B@=iXx|>(Gaf@Ce}5*IkP1s_giLMBR5dSnz(mYx0Ig zJ`FjGyRL_GZm2(=BSQQLb=}<-R=WWP>lFa&_Oep8I?|+^%al)Wyy5+}I>e-OLCVNi z&T!OdqR2f{2B**7t#sl2zJR&Blbw10xK5b`;P#E~qP!Bx4U)_3J=1GanI_cgnvrf9_)wezq6^lH7N#zVc;aj+Jb_2Z<+PmHVgc)SNEng`MHdiSeI+H~FzsA?J=5D=*1#$wqAIY(7#+SRDk&{Tpx9t zs}D}8>qPQwz3?5O|1r`-Nt<)FxGot0 zk}X+gVq=^ml4t9ZrG);^&?OVMe5D+i@K9+WpYTK zsED^&2MvFXk@4b|uY*mSse{opvJyB-@7<8CD2EaHmn+JmMO$1k^ajZm6$6c~Ng{c+ zqMS$QU#=*}Z29^)WOMaFqw8XkJX=xTN9g|yMR~@SuasLiS1DAKt3>?2Mo~Vs<>mcw zGxEwJtf3%BsaVRY!^*d&?KzUy6`YcHH3lYv;o>s3r)frZKy_@2(;-$+r~nZutwWP zqumI!?v$mMg(hK*)=Q&}#fjN7?SLj<;dQhK64q#PD5x4%fm(SP(7IXFB&^Z8X=*0` zZ6$f@YoSS4qxIEjJ%BclXoD;?32U@L8tpY4T-KKWZG?p;VU0FIqZPgqRyEfL&EcJ^ zHf;_$^;A31cV;6lWskJ(ydzH__iBLWa%x`sAKT$OPU#n)L1UyJ$CIDOMe=M(J|=yc zB;U^C;q=2eRCLmd5DcY{#uGQr6Lmbk_8uu&n7(Zfyy%)<3XkY;`i4fp(r51(Rvps+ z#1#-ux}*)hqL=>U69<>3orF(P=A`?j@nQV5TOU@Bs&sdt7NqAQIhK9{;lgy~i#VQ6 zKlv(}N~Mq5E3A^~sxZFuk*-701JXO<%j`YVWgk1Lb$Sd^iYs)o8I|ZN3}~=yoUFgRC+oHwNLY=+lut?>agmRzN$E+ zx}^J}{F-#m4q;WBUIr4~(nX)*JU%@i9Q95=hyr@0pU3l&=Ty2JqHL8eZ5>j5)6;<4 zFFpP%M?H>|+aS@9^pSvdPoqjzkMysAtW@bZ3fv}rC<@s&{ls1&wH(M-fxE5K-I3BK z-5%jV>7Ka4K0kdivXrOiK$^PryLb*t*SrDG>GVjPmJdz;3pk;Eyl0ahhN_RI&qF0GSLuI%<$>wfpK#O*D6th-dRnF1pk<#@>0iQ2*)cs5S+`4{h|g~=gMVV#(MrAgFI*SZyTV-#=R~JX`{+$@g!mhL zxGEWl-G#&owNw9o!2A_w>*WAe4n;&=8&zdh@@7J1B1e@@t7Pxo4$#tyohrTWv9{}v zyocF&k40qSvwq%BlgztQ|MP5|D-pTnIl0-&JZ|8X1rIYi=cN&q|L z;cH=Mr~VskoK1*4vf9UathFvS?-)z06e6!bFE}jgj#k9kd8hvT=01JZ3NfNKALBbb z0cOjwvAYj<)y-$dRAGG>PFzlu&&%=Zid>?#>kA0%^_io7e$iEp9S%gv^(P?O*ymdZ z!2!T+99@Vjj_Xe)v=!Xi3hOz18+nCwVLh{s4>*}l zLDbka!(0`TdgiCyohY9ff<>2roj+O6%=&xlnFXt{2}t+McaZMD7TD3!9T-TbgCgC5 zfpiCI>Bd01>1VJPahNz!J~O3z^3O}htiM+}7OciD-WXCF*mj4sz>b#gkU%;e6zL8L zq&q}Qx3bPvcb-n^I2s)>Q!=Id@1K{BS%0r|Vg-%u1?eWR?GA5&9WCAAfpj`3(j6X1 zces}B_#v*k>s*k#}P9wSALfuQL``OK7~4v;`o{C0Z~ z|M$wl($v_?(H=KYj(c0+LCbM(Acqc$9QSHDmX35)p^Ta=1q+(iU{`1a@M^_O^O?^94dxdlNr<&y)-CkK>I4k(|j$72fhHt95wtItx+9;4Aq|9rhM>+h{M zJyRS8>3;nT?3~g9J6gI^0_jc(q&p>$?i4NEu_Ih{%c+zuOEvq_-Sg+AW7gj*ot`N^ z{34`sDBYPYu%o3rGm!4gK)N#n>CV*By#;IPqf;ndmTLB;TlMFqW7gj*ot`PCL%I_w z-J%xQ(b6pnq+1k7wo*qj+HI&pygN@$gwhzW2MNk%hrE$)wHEiRoLID!wSa<)*kG4ockt}VQqO*SAA>Tc;=Zp7_ldz!~Ihi?G_|g5$7aS=Ss*DruW0`wdj96-XmSN<(_}n@rX{ak4{Dbuj&;>OFE>Y%D%_^Y`0t}x z4cV8hYK|sVi%pa9-=aAgO{I2u4zh2&U1+k$I`XwQu?+rvyZ1!9uU*?5%|GAnXF>M; zb-QQr`RCjHXYe^ew|f@NKi}?qqTSzrsX5vIe7iq%3_fF_+dYfVKi%$ecNA9mPGLzf z(03iMpOVj_7q)Ts#`Zv>E4I3zso&hyRWt8|M89S!hWn7-X%%)SI18}%HI{L0|105* zvOtg=jfv-=6Mp60hK)bsm6O6>i9hjG>{k^!P8GIUcANO~M?eXSYT0e#*4Ps)bR~u5 zJG;AT(HEO5pW6G6luvxG{5~y~&lHyb`EIW2wP|zZQ|tbb@`>-2KeWa2nSx*3-5wUR zQ`j*Wn!7%~uW6}Dr)W7^YR=cvQWMZpkKaK~v$~1uv; zUZ3 z!-|wncrx@WennGm!-19%e=aoT(^qkCF$;P=H027sw=ASz2u+FLL_or8LQ}rScT*(% zQfSJzI1!QX%b_VBdGJ?4Q)b`{Lg=guO&JH>CgE2@Q}*`4uZ5;mU_bm+a`<{^$~5fY z3(gzJi_;wmzZ;rTG}Q?HUxX8e&-X%8_J`^docBXh&cs%&gg*{VIT~jOXOZS7p}lHj zj#`UaNIkXiEF8(~b;o)5Mi7KgJ+0%r-k{XI=vJv`bbR8kPysliNUhTGYu-_+GrCvm zMIHb2bbNpsa;4tX@pDdt`hh&D|LFL%GaWUZ@waq*R>)CLv;4Ouj&A)EzHfkT9hJ8- z`SlqF`1Kj--i&zNTf#y2J{KY-d3&hey#;bLAyqs0-TOww69I13-G28DQY26D!9n*9 zl63cOA9U{^Nq6triJ*H+F+@;htE}$*Pe3%M=-JQVCQ9~fnn1tZvmLut-Usgx=-#d4+l0N|Ephbj(NlEqmKRgmyLmwC_ikHx zGogLZyB}qrd4gTZQ{Do3fsm>ty*%apGUAB5qiN@mc5Q2BY3v1jdPXl3%eCBL#Jpn2uZ;-9QEoQt|fs7*nk^+ zJCyO3RFS4bnTRmG_v)}(hwq0a5{_YpeAyf&gaOT6LUT8L26BDz19DY6&b}03LQkBv zA;!#_)oNi?P2UlpWf(|7dO429>SbZ|vINp$BT#=M(6j^cUDfA1Xr_Cm?BE(lnSo#6 zf#GHNr2fk|I&aUaJ0Ek6%#;(xqg9cMEihqs)QzDq;V#&X9{fpQdvG?g2~T{R-@|)I z@~Vc@orpT&3cUASGxSU@7M%-~T7h?+qa@uGo);2Wftf)9Iq(yaz-jQdh{lFF>NVK* z(I|4ANn{450jKdEDY|r5C zAXCwc!Tl_-6sMPLvLz=DJ zT`*lbm2E5B&b%Hsr@p!Zq?qtJul3Ct*>Lv+S1r3574ZP`!8FISjVJ#%p0tb6+FG^; ziO?vrJtRSq?O_RuY>!A#WP6mdjl1v7kg9l$HKZEezBGa}?U?F#o|srsBFsUX>M_IH z8z=Fh8dp|?fh2XqG1T!qf*XUN${eV7{5`DhhkrrxGi#uJMoxl(+A!m%u=))5eYft* zaT0u1ps^PYpj%7Ls%byxx$4z#(KmnoQ+@Mit8Z!wx^Eh|^i2bozNy2zO+1{PHWVVq zsHTUH4XK}2g46i~IHJ%veT#~tX45Q7syN-Wp3nQ?8by)Kr*ylG`y57P>k9}**E|BG zWMCPRfq@{ywE4)zhpM_487>&%mq7DVGB6Ni*ynC!-~$zy9v@N9WBTh{t;Z6ZI-`@A z=`Rm6OXq5G+PG{|*b7p*Yp9y`M6Rn|`vx+v_*1=Oh1EMW1>HLgTzZFrOYhKOt&gA5 z{h^@|z2PXRq3TlI-JV%@8+Z0Q z*zB($7z5&xsH=|W6twT35_w-sWKChh3$xMJ_jT9`6GUVU*J2)^#hlgy}so6O+nYRflILlE;X&gX6UVx%)4oZUeyetCbmOO$YgxupJM4oizQ7#*TjuhO=!4b z<2F-r!+j^X>V+3#s!My00PVyg{de#sxYln3CY1O*X20N1344Jhtfrvr-@v8*4P5G9hjoo#uH~Ng)7=p@ z>=A5)9V!6J`0;F>2{a;{!*p5f;$E12+zYdloAAU*n6I5V4)08#*bg>MtTi?*KP+n7w9|5+ zq6Sb!c_t%2yu`aK1C!DF)?o7{BbjN=WE8kGoTfZM8cv6G!#(5>M>V{qBI=RLX)>l3 zW|)jjmYQThOhyL8WMn{0#)Gc<4U>_W+N_c}cmWOGE6Fr#7%QVd@SS3F3#u>~clZ9xfYTTp`979`Udw%}~o zf)`v7*n&iugYKklL4GoD5+9x|C_-xkkYHmA3P!{7&Pv??r_h?^V%dpxRI{9gt7%u} zU~>B!J;yWX{#eiXSz2HBoJ@m`Xj6o+nsD=eF=zfMrYR!5A92q*I>&OhpkY-s@ z#jvSa&lEA}YSsq^UCk#1L#lp|>Uc_}O)WhtfB$%R&yq@0@C>>@Dg&4Cpu@gFMKtuB|Kwv;5OEhPzRONm)MONn6gw0B)sokq>OubDFc zn8^EDB5Mksr9?W-SxQpwwC7OMo!G%WOX-glyV@!?(^4XNUF>EoB_jEjlCB6f?H{NK znS(q_>5s8=qs3CDr4-aemZhXiZaCoRkopl;Pt6)`v^tGvZGz+f8YVWLVg<2_Rik&Y zrX7IkQX0*(bN(2s7g(%j+Bqy#*IvtZj&MEgpRjZKED<}0082x86SZgO2u)+>NZ8mp z5;k@Y!x?stv27@qZS$yxZDHq39Ua&?%qg=o6^Ui%bbBAwr|q2H2&x0n+2!YbwQl|3 zi24G1LhcPkJTE>_b_7}V?qfMT112D}m<<2`eOC{PbjMo+Ky_~_qRKvKCgP=x-&{mz z`-7Gv&Rrmq0I353o(!%n+7jLouxKd{(xZz~E9wZGWs zobRd`#7J~Q{oP&^CNZ`6b3p1__jJ?`2#jWiTBHM6C+CB=`o2i!Yo91$lU?fVMO|mU zZUb(Lc2Ebu-)J$tRLTjd#h(E>%K0A8;VQBNYU;C#J;_kqr7R9uWmpuAaysK#ceRyX zH6^cpESPu}u=+z0SgRAKt~K3g>Jr0-?77H%<}F5KxA{Zt%k<|U_C738|UfO)^d=f~9Ff@&EJ*uk?82ol`th+F?OQjQ0( z{(xSNIv0VFrvq{&0yA6Vx-akN*5-yYyHHJTcvQqi&1QW15q)D+M85bK(O-N#IAfHx z&qZ=f(;Xd|tJE;`r^4sAtN#dvc0s)UA+WI(17Aa;AqKMF3O#D6K^<9B> z72@@;BXBDNydv#i3>*gh#}F8qhorR(%tzo|2EIq&QwGig&UXmZo%>lJW8vuGx?f)b zU}k5&Av!}R{RDvz&hFMaX#2V@=qZnau>L)y=WV?wm!oZpfb`tJKsxmS}FL4m7GNfV{QT z2-0NwDZI%{KTl*&Kg(pcv8JD8G9Mju=4od7S*fR+`w%Y$dG|>jPvAgNrk|&ZR-;%w z{X82?KlkBg7xIOg|&e_}$abxyaM}^z$%Mnw@?=Lc->zpAwY5rKTU5TvQ`!=eeSA z{Zvr)r<77ap*HGI0I<1<zAO=rHI$h0~-%8a32I*!9Z&SUPM4%5bK?G#x7z>>LSu@A+;OKwv%#qo%&q2?A@l2rcHDeJHeXH^$BETubx4B=t%&@7U~12^yudh zV2>89wUNoRc3fIJ+6wM2Dr=N0mX6z!rQ?dF)5MNKhn#sVCQcA3Tm#z`g`JIfeJAjH z2?J9g$8`+c3&`yVjD8cn_#EONlvmGNYI2x5oboYn3h+BH@G>A>5g0iOICTtsh`5*|9#eYJfy?EA|3W^Sc}qOUy%+w1X1a*ulOCdBPzG>mC5yY zv1@xBwt+QH<9!XF(qU(TuHRv2F*&ot-UJX$^FQ5TcQ{U|w}qGO>%T;)GZC*}fl`lV z;1@7{G6RzlI17Q%51@x7dV=>u^XmHoZ3E)fo@m<{KUX9z>ficWGf`KXW&c( zY8eP2sUHIuA}|yI>9E5{vq^`Y1ZXoIb{4@+JM5_h{}J2#ad7bemk!$-9rikQ*ma%J z60^QWOG$@aCmnYFAk$&jNr!z4cRWjnUFUb$tJpxVcCFtP8T}6XBx{@9 zq)A9M$$f+rsgQOhgwP>`&?yqd>2yLI#~Bfw4hc!eCBOIkv!3VKd+q(qG$lI!@A>c7 zYi51cXWiHHS!;bhpS9L!rCIMH{%i1Cw;=Q{1l~sc4+%5^upL0)ImG#iKwHE~LJon4 z0MsII8sao&o-)HS&p3kJ3akgg?j|~(U{l%xeJ})j32N}aL9hwoFRn{4u5N;>C?D;| z{5Wpq={CWBBn10qH=AHTBEjn1?MIf?0I|Kf+tUytl=>b3;cowfPW?l;+n+!?P4UUI zK04Jp2c5X3lbL5&8M^=@1RB=gu5t4U2&MSAP>f5`+I9ax={q> zPZSELUXQ~CxN4I1F|W^zYX%jo%(Nd1;SMFQnT4c9Bv%WD-D&C-FQ}%YD?0p3` zWp5YC9s;k3Y1=srbjsddWNqL$0Cya}Irwjc2xV6wf1&Khf%!uydnHIKyB#QXd!Ch! z(m#aX`WV1=0(JXOP5TLePH0vwG@4(P7;&&&o9nlI2oC07lfWSM5Q$nB* z;!Gg$GJtCd3`Csi0QzuhE@qyN0)o?Wkkj%+VD%|E$SHXy(b{wz z6@vW+1S=}ue~XHDc|V(A|1AXDqrXkC{}zJ1?+lw@|Lqd&YJQ-9kF;tbp-Zqk*yGfg zwFg!R_8kB&!De?ruuiarK>a3yop7CDOhYDF|F*1wC~OY=R&&&M5rI)?$1(ydfq5Q4 zpY5Qq<&1wvnl%&gvl-e8p^XSsAbv{%?*Y>uK%fk9`ViO&U=V>~1f5G@4}dWMgkUR~ zXB@%q1J;9Jvrhp!o?vr{J{W>+it7Ha5bQz_tf+Xu5*6>@Gi`$XN(lCo0XD&YB?Q|Y zUYTLPatSscotw3*wY36$<`V1}_BaW43$Q}4Wyseh*qIF0RlMtgBEcTAig(cU2H1Yq zCC%D{QYXM~y@67%CGaaMKApfw0QUgsvlbNAj`8nGvra*@UGQ7m0sM!+iD%)g1>;|X z_(uT<+BiC;*^lSmqf=uoHpxAlR8i#}n*Qq7Q~(*P;gh8w8sW z{&||M;{9g-F34?li)@1ZMhLdwK$~E{A;Ie0?KcJ1)%dR7-0fV12&HyJhQi&R4a^_H z-L|;FFjkXnzUgE=&kDkCO-D5b5g3COoeQAPB9PctMtddA+KXr#;kT9|+WQ1%Bic3q zf%g%#k3bQEd`K8r2Ox`pfjA8S=u(=a;{Ai9G^L8LRlIFbBM-v;KdIvFhrJ0=@qQ;N z-fIWhg!`Qk?lXgJ!u>9uaK9_GD$!BiglixlA>0Q52;r_q+&_eHzXC1oCPjYN*=mZ? zkGc_r_#J?T1pbN^wE)nk1kqAXMYOeP*7*pX4Zl?jp( zdXGQ}fKLGY_Ym$qsL}rh;rhb!K)9mf{a#eO#|*Uz_j@7SP4J51?E84a{eH03dPr4- z+ZQ21xa$G9yg^eCN(?jG1*qS|%svY$EFuAZ-`y%fVegYXyP@9O2tA>5eU7MK*M3CF&;qRRs>ZL_zb|^1STTR0svm*X@;wuSIuyh+AlL)rS{7V zduzWm74Ori(f?iYJl3D{HjX`=T>nJAk-$48CpR!oY?FXP9*D93U$7^^B)AYUk4a`&u%c=UU5AW1n9OvDWNO2bYX`BAXcV3~!f!l}8Z~;EhAPb@{&z17 zD5O#N=R1;&RJAB4@j15COMv}3;U$Svh?yF7NKg{`tU(qQn=%ie?AO&7>Qf}z)$mv-BF0rN3 zr^RG?;ZGG?D+MiRwguUa$b=D23uatEbqq zEGxi>I~(SK;OCbK{s%*B8pmf(v$^#O0vq3C7`@YT@jrCIhb&+HV9Pd#$I^V^JAkz= zM$CHwgmR+dG(6Qz8-EfIDqL-7Mujn za(Mi668(WeNcS8Nq1&P|^p~fe*rQ_<;-t1|xJdO4PBAjw)KuB^F~b310#lL0Sp@bE zH;s`1^gB?urzY!npzcWZU*->&sm}adH|t)?i}^R#+@1XOogeIml0)9U#0 z+6}0CQsu^yKfEvx71VD|%~oNF_RT5nn$;X!Gz?vZPH=wy`KhpN7u6X5)yc_mH>p5( zU82%Fkm|P@p98&!gDjphTxICqOfoKbxwYR|v_ERX;eh63QL_n0hQE8uLdMnyZzrg+ z)k}@7uBd{HtzIT$2hYSHswCz0GFwiJ;zqV5mk(>pOK>av9&LHY-M+{$5sI{JczNC%XIqK8jl=gY<)ZO z;K$ZHq^aT9nu&5e$JQzYc#o|e2=N?SIVje1Y~>@My0KM?@c-Vil|8EZu~m2}ID>QW zMwG)DP){rCuq?4va0ZN|a|VwJXYkitzwvSOKy`Af*+6A%qi`#XB~L(&8of*voO&iF ziZdY6C_E3G!Ap4Z&*2P+jZ{0&U9cM}P&k7;M!KY7UL0qTo?$4?pd}Ypn=@#s3Ti(i z(P#$yQtf(tH;bGBEetk;n0oR&Q-O0 z;8VlcjF-~HPSwTWGz3_+5dc$+1V-hjYJF~`)(Sim4Qh8TqYm5->xb>mqm8_Q(w6gC zf>BsHB++;f#$?);suDHxdEO;TS?x>RvTTsKwl9^26u!7U(P+b5ub^L7=+{F;+&G!~+b%7Y(O%!*07kXck0G!|QWeN*v?8VkeQmszST zokoFVokh>W2WmG%bUuK82L`dK&6yAqXlD>`f zLA&#Ln;wOq0%YER=)|LWSrsAUfb5+x3;(s7bnSZjtU1WC$|rvLGoV5Te?!FDb zl34ZRu|Iso`eVi6?~g6j^#`9k-Xtxz`{OnsR#HuHck6?d%d-(gK_IcIN2cJC7 z?#!0k{qeNZAMJ=$PagZTfBn_h@W>HKJG9_151OLtI)zUj7fSPw%#+7s?e<4EpfmgJ;n9pI>7JeJ{%K zWYCX89^MT40EBol=#voO$)G=sfa)0Z%?LjLgPv54@azA5h2N|21w4db4=MN*sNJrN zR=YXcu$nQ~qUh3jmzH1HQgCm@yUa#igm>v}GIsELFeyt(g1ybw*3$^Ae={{q&GA35 z3Ep-9LR-IbY1S2o&2aWE1ZnyqXqdS4nc*LyHR_cvvTTgbM}?17iXa&PtL*_`?YRJ3 z9tg1N1NZ@e=!3S}L&9o$A@)%i+#A7<0SK%I;5kUFaR_+|TB5udRgpCx0mDUoBub;* z_PDY7BlBk9d(_I^*@kRA(nJKxP}+CV!4IVcNK->ucMi(&97<~t;60RfA;fbiHAJzV zL#Y4()eWWb2tUA3N<4BysqV#|L&>plV_eV&dZaeLM(L4wimv8*B*u>6{u|w5k048p zppK}5j37%)rUma5jRD4c1Z5+{a|CrmK-35-V&+(RtS^DDas<^M zZI7UNmmd5G>VY&h96_B>j^_xv5CPsJXa+(&N6?E1@Ek#(BcQqwR2%jE?;SzUp>`gN zQDg*-gn}m{dIULomzu3XqEgY6&!;- zagLxm8##hLD#3kxj-XL{^burzi(F;{8PbGbEJ0Q_vdDq_)~k-lz%lZybuxl?V}|z@ zZ2Kd$O2Kv-YDvMi0+EiGAonl|Kg>M(I%HX`V7puz9xK>Z5~~E;q$4M@e0KQzBN0?r zWq(kx-6t)N6>OWHM)9sOnTR9UAIG8chnYTlRo5RBY`aLyV+Gsc#45oy=?Dw9#fQIB zrd8J|6l}*y^N);RyTESm;TCLPsix7+1TAcR1sdrgunRw7=m)!BgoIP}n->h!+yEM(bd$VS+KzUt7!H(2gBk$U=?Ev-?dSj%sr zNZJ(tt2^|NfS5Hp^w1O$Wn;DnfEsPgPC`V_joH@_;CblbVFXmYG5Zvh&pVv)F`DY> zuJ-uYjdY8FsKKF!-H2A7>BxPbaG7be{SNIK2HX1Ay3W1{z6WSqh zV9;2c;9>kH7eoc)m_snU0IE6W&m#^KknLI^`ZNn;1OdzA4NHLR4u8j2T`L*%#=SRQLgL@{5(A8P{^OC{{j$q-2NHUirbDI-Im^eg1-{QNlA5ZVxpun#l% z!r;tlQWXgaC?8D|iL)cYw?--<$n)cdJ32o`9%{^=m~er7AH=yG(ekop9YdNpSd z_9B}aok7S!mO|#~@pm)RzNGQlAH;OX{0|6jEOgtV`;BwZ>E7g@m{*(BXctdb>tM^2U;bol#Y ze0BXnS#r0u-0lx|leB(!SC%}2{W0_K_s8<;`h&7$J88MyAMPe;5wS{^^c`VY@}0xq zDZ8rc6v~ogr1?iimdu!-CW*r>OSVD2Rm~I*&t(M3EKfu0T@GR%Ji@Kb{s+dwn+xFg+p{D+u4n1oaoKpaX}k@D^&HCm z6oBx!mFyAjxa>plGzM=&@Eibv(ZG1ptd)fj&mEVp2(WitDD&-O<|O0h6HO!YJ7>@G zctF-dL>0;|LRbwcJ39~E*8iI7C_5KXgtEsXTbHs6fhBLe07#dz#{emm{SL4$Wmf=8 z%H9v;p;7k9sNlg;_Cbh&rN~|=`(XesZ@iT4J`7@@4_k=B8=t8NdNT?Uf<9AiA@&5p z?n7BwXPWJ--3Yu`2znd|I%^W{jFF&!w=F~xbauW?(4~`Yf*yu)U4qUn}5%hQzA_P4^?daVDg3a#z z#d}BZNrY6hqqh;kRqyESL}-;#*l^U6Qdmn=@`y=cy;1mK-m$qDSyshc^^v2h(s1Fj zlOj^sN@9<=6n6dL?~ldR^@ki)m6qH6;Ywlqh*dj!M^Fk|efayMvbz3|qpH2wa=SlV zDXbl_{~c1;{=?rX$6#uza?r?8RcZc_k;1y6a-1X%w-h$2nnoM;PlT{yG~N}$Cc+~^ z*nLRux&FuR=#hJ!$#h)ow;-LY?8dYjuk1^aIPf##SG{Agn)!2OKL*j}e5pMaMj?`} zP6ZDzCpt|7Gr1t`abQ9tqR{?&{vicvWx(__%JILqajOaq9(^lp)}!4hy`?%=dOk3L z>(MVk03p7*==`!wvyuKV7+$?HCM-qrz$zrT8VQ0eD{%IR8T!no)dnb+O-Yx0~DbOS(#>X zklj9p^+A{070*X(x8l>HD?aa!u6Sv5#f{P}iVCEIvW_y-jN&~IviXY#Vvclvez8s4 zgVcev>Bw0~dyq*(H9BbzGEe{GN&9Y)<8pqML1rsO+W!RRik&qi>-9()cnz)k!6EBP zW=67J3am@khJ}yqkabgf4vwt%BQuve@|oTt>*4hLkz{?s4Y6cB4pnf;x`OqIkaZzq zyA@v;UGbHFbj2q`SNu1SwJ&_;P@Aj=E3&=|ISW}2HfhF2C+opx{vS`)M^DGm4t|!w zW}7R5@YH0E-hl*xEojTtNFZ~xQD77EN?=`LZVIeR%=z>j95H9z7)2AsOz#l$M0);6 zV(yBnxF>65j-H7sxWv4a^@$Mk@aT%Kj;{FDKf2;KMpyhd5OYHK4DcVKVi+bWhA94H znBqUCeIHpJvxb?yLcOCA$C;T0Ip+e?(E1TV_gO<0Hm^ph}ym01s;;ww>l=u-s zw6I!rUIC`3@fQB~&Up|2gM)WMy+TU*Ji}jL2I1>zT!sG=Qu-LiRdUz$PI!CQxk3Kl zkN=@(AB~jeKPlaxpM)#1#}|cH0bgLgf&V>?&G?`9>SCu-xO)Gt8*eAj1?Kno-(!4K z3_Ny>rmUSCm3iBAe?gtCz=X8pKH!E5>iigq7&g^)@W4Irta(_SrY# zCIc|R}20N%Dz+xGt&Gts>uGp3h z=r8_?9Uz8Vc?aBzjD)k5vTX+HC)4`bid)eJ!r5lvHw=Vv$XXu=-GKT32SU_97{jj} zI}oM;`Tv=L&>ghx{IbqATdRR^D+j`CZ6K`2w_oH8gn4M941{ICx&vW3dxH!l2f})K zez$?(3!e)9Mh3!gH4qAJwg)Zr zkQ@k!;To+7i8Wji81Hvj5uyjeaP#CVa$pH1vJO;$2ATmQ>p*s)P5!08y5ye=tV{m+ z^c+_5zj`;u>6rB}hF@Py!b~)-Ii+i_4knz__qC_ft)V!1eXy!rbLyfi#aVodI1k<{ z&XOhKJp7b6kGv?(((R`*!J`d2(RqBMAeX%_&J)|jdGaf9mhThiPre@*^XV*co@pS? zv(3eMuB|xFcNJ%)CC-aQ;=D9coK>U6dAUrSSEq=x`WA84+$GN12k3Mey;Ph_pAl!w zYH><-iWAJ)$0(te;*@p~=dym{j2$J;<=2WcZjLx*Plz-AO>wT+F3tq=Kg{LICgNPx zTAZspi8Jv`ajqF5&ZJUtCf^{=l-tB9Un0)br^UH;wK&r@i*wy);#}YKN0x9yH*szp zD9%k6iF5On;@onlI28|zbL-3E+_puW+xLodN9Iq=WkzdpX3<2>HC^tyNSu4h=yV@j zAZUC5-F&P#xAYRH zVuU!iUMNUh_iIDIFGIp=dr(w^Z2*oEK5vaE>AQP=gH3EJT+LH<(G@|r`yDN z`Vn!S*(%P8o#H(EvpCPy_c52}^Tb(MEY1s4#CdV4IIFgZ^Kzv)ulyj+>a;|r`*UM) z)|^5oFhD+B;H(1i6^#{V;B;{YEfQz&%i;{#BF@m=;tb31Gx^!ai!(e=oO6bWGh)0r zBWH;->Tz+-T_etUABl7RUU7;ulbFi|t;D&ohd39F5a;4jI)xL2hzhTqD!!|vx`h+( z6yG(A#F_MrIFnx&XUgZ|ln;-K`fJ6x;eK&$d|sTJwu*D} z9&v6-N@4Pf-y(CARhgymANDpzA z4ix9ni^O^CN;>@-aKIX!eq5VmbQ<+clF^Sn+Tt_3H<118`3@(V{FRSj_^a1Uy zBm42<9jzTvY0{M-!z6R^+6IO(IRUAs5Sr8&5A`OPljd!}Ge?Q##5dyw{x6YrLhVTj zxMP%@Sk9Q`&o{!qmi+fkJESf{Nt4fPY#38{FaO$MNR*C!sHJ~}J>BG~L3jm+B1%zk zidp_h6C@zJFnJmRrw}TiPKW{J1CK!fbDz9`I4Nf-AqJGch;quGr&l0JA&?{!2xotc z$saPxWHh<_N9M(>r!h^N=NI^XxgfqB2hOsMIw63k0(yN{8!$A zUMYdlbtb`PX98TY4b5(Sy?N;|DaMrHK&0}+Yzg=bGoyuB9%Q=O$0LW2jziYh&?^xC zmD4+!S(V?#0QTc#LX!!Vi&xsR9Jm|IDapvWd=+DMJQ3mR2t5F3(if4=}Wp zOX-z>i~1u9z2&Qj6EFXjZ=hH5BXpffu)LDUM+X490{t50qldx zgeDUz7cZ-IquCnBtaql89;B1}4sO#;<{1q8o8R{EG&n9O5kcD+G|UNNe@Vre>K6tLj|)mPrjTH7 zG8==L&3-Djye>%D86g>Kos@2GwbLP!W9S$VP9Wh3M!rr8-A zQh<;!)0`d~aullYB0~Hxr1*U&){8DE)2YI@D$$e=5N|5ka%py&(Tw(aI`1%z+7C^- z6Ej?L;*_5mg@aw9tT(1)b^?MtydZLnX0)f^XPU<*eO({ZU&<|J`OjBjyffp~y?sWb z)|2)jz@O5L$pjN9rv=E#=fFRO&~>Kx<= zC$gB&*o3Y##m|4`g1l@dg14X!lixZUINFt*{1#&qy3Q0o|CJLtIfehm4Tn8FbE+R| z!9DQbYWDlaG=2r7X0!^k#nA{lsBB<}S zMk$7QdmFT@@0$$>)*(oK*G-VNn*$@;=xD3wFn_yDX z|ER!7xr;S@K~MS2_xMuJBr`T*{FyQS?h)e&C&p~X_{Af}A{Ar0`2-d^v+q9|qxK{B zfk^s(*O1^Z0FB%5r+&^l+rJAgR;3%p?Iy%^Bh1cauau2`6tBKwf8ReMiFGSG?lHr- z7kQqJ~kY)qYyd%R(d)zS6?}i1;TmU>Q z1O)*%>c_D5`5CpX0^sifLfhH`Ei{fleh}n_{xl}UX1+BZ3D*K~NW1z)%V3-npA_10 ztyz6CG7r%30U4<^YWM=D;j7$+$CNcNgJ#Ck4|@fAk#X<<4;$J;s!nJkUQKM&iJ_UDxzslJNJc_<0NbV;vtOB7FV=>Aoay>li}kTL zx(iI+<1P)#$WXnS-3+HQ_|r|tuS)gnq&XYb<~8H;ugE4A2?C z-##_vi&M4fW_}$k8AD_`&r%E5Vyt5R+9~;1@`jduiDlquwTMl5 z70XD4*&jlVc?0rP`P~ah7D?YYStLcosxU8QtVca!O_o^G&3hmcnMstBrebLrQh2G) zNIc1$jY5ZT$pt(dF|asKh%C;tB8&5^$l^T9UYxIIk&V&6Q5EBw;hRQ_(5jBp?9wk{ z=|ldr5ruX(Ef&g{fO{c8RiLw~K!w?XjKc&sUoMeq(O;V^AG5;rGsYY}hVqnOs(#wtsQPJl!+F|WUrL|PJX7UK&cO)Hj~aR?4_5F{!)-t^ zk{R9w$od$lA8nK`oOBP8TOKN|GZ<7()k^` zCe12%$}p}5P9?eChRpCCfC6a<+)N-Bz&`-w%|RZ{@7S*CdB>sGonO;?8d%d1v9;jz zsApuvMO|e_wH5&A=;kxs9CS3=GekJBOBDgef9-y~Ok;n_usZzONz2vOCS^x`?FK32 z?ubYTOJ)sZ9w_?|#Z4iXrTirwkX(2(Un;-5{=!OP>fgi zX;uaTrvhPZ1TdXI0f0FKt_QFfK=5B^*lr{+eF>>OUIxbbnH3of#;lcHTk;#u4l%+q zj|Dkz<|=%V!gIP0{vH4FiFO}N<=POEbI5kae)r*2B{dnvCluJ9WR{t|A6KX5o`^zg zJ&qAwi^6*?_AnNezB#DnK*Uvxib%y3W@BP6b+ICH-{pQ{XT{)4@((P8y&R}*V`NCZ zaxW!PzCbgja-{`M)lhl=s>G8@N9l-w&V#K=Oh#(3fJN*F5z9ug{jq$Riqz7L)E-bQ zucqRZsC5AH-Iai<;NMi#fE)EJK%rQk&Z_$i%=aL~+J|r79Dw@86XQ#LOyh*C`a+By zk;oy&s0nwsqQ8k=4nKQ&RR|%U;iQL?vd%#*9rDqa-IKBgsxXpJh$Q6v4u*_^ zS@U4TPL-8ry@;9>0$~jTFa!WgFvG<}%?GN~M)|@M0bS-482B7vcL5{gq5`>@JIwU> zaS=tdcbo5~ZouMXepwhznnM~>jc}T*Lql2;?yBG-l;uBN!B3EX?WW+HRwGV#1zW{f zvw8?T^o-r$Yd=aYL$aa$n9o0D?HVeJ(WkN)4V5+RGlf5e`R`EiJ1~Bwz{cI?p46XM z&)I$B>zS|0m3sD6u++1cf~B4T1xr19D_H7j35?nA?#S$Sudu(Okh(WA``t^{&SQda z(+_tp)5{=s#f;6eIV)@etM3w6g5uvI2w(UwW$3Q@N#7vzk^x8|EWiut>@uOig`|oX z(sQiZ2y`_#tBIusrya1i2B#9Zk~Q#4&%G>Jl>7|8^zbX`)aYDE2|VR!Bz`%)o=Z6; z4W9*dlh;@ysdT;1pVLp)H65>|>v{|$Srj;+(u9QY7!;rjkWl4xLH-mVNyy1z>T*=% zW`F|25ZDF)TYL+?Z_}euy>;oy)?NfW281;Mz&ikf{{)#9GWcgK$;Uls7zqrXkKmR7 z0Jd^04^jjAHY}ux~%?*lGT&EWc5$~P+9$p1Ip?h|(Zlw>4&fX^`eQFpMx~H>(IaEFiEH0LhDa8_Pwth2mlq@{f)xc za(Gk7;oVS_ryM>80p4=>Y=n5q;j0ngDTjZFfa>J%`lxSJa(Ht`*7kVt^ms=`_mIO| zKn~a6gl&@Q4^k&RlQUQ=5aKEnOLcS~E@w-D_ zI;TEWhtg`@mz01IqmgM5tC49TTw+NtL>Ef#Alz!GA(T7L&wolP#V6=+nh~ov?Nr!+ zU5y5mj9FzXVovi=#GDpO0H=WficzK~0o;xNZvt3}5KjX53;~`5kd10pM*!UrUKIg! zuZ94+RYL$h;uJCYseDoxETk6?qe6sVT!Y%E*)uXjRhV}sfk2)a>WBxFrH6=k*VfOe z#)EVJ9FYfQeu8vSoIBI0IZQMYd6HP4rv_(c@k=XhLbdZ$=~5Ko{QN^R(_EgwC_ir) z_T*2$7rXOg2=Oh(3UdJb=5+YwrAa=fBET>JN^$Tw!usCvjcFX;>LP--xS+~0p58Yi z+Whnr;^mVl1yo(7kD2+ht*@!8B;P_o5a@QbXmC?c+G<>*}i zaitPp$rV?26H9SrKd@>J*Y^S!rPp!i$CAWX>~Z#x$Sftt!7tLu!yeMfLy%6kq1&9F ze`$IqKaW40b|0jH%g}u1*Su|d%s%R4v677cK$6UPsEZ@X_+urRd<5F-y0$gEEZtVE zaK~Hc&LJF4v9rW_s9igMQc{8SJ3QR!Q;?|cLs2$&8o%=zPdh2+n8t^hNk?(6T#2L} z%9JgNR1#jbW!){VtZOS%6e8FLA0s6PRPYb%8}vZz(Lh-5A=B{y_`%HZRHB+9Y`Tr| zh35bYJ%xYH&wSIYX9W@GLpx4VcsroH<6OnOVYFzPZp}dyM_C`=uussi5gCb45=IUE z$SNT7#wax?x~{fQW!V14@XIL-<>x3$R6_hHCB*MW$udets$&^5kw8Yt`O5zm{IZG^ z%NYw1@|&_}MrPz#E0EY7HC>41sM!pxJ!&*2`@)PSkx{b)`N}96?Qtq&jQ7z4HLH4x z>`8yN`Pb$EV))lyKq)#mbe5|$qlrGQ&(Ek6qzqTYri{(-^`X=@1|CRkvrP(W)8J8e z4K*VSmuHAU9ACJG2Nv|9gF_x9DSPN>Vr32FINEL~MiXP@xB(E>yNwg(;oFz2LuN7_j!UD4O34SuO2)b#>bSJlK~Ag7NlVA4 z$rtv^AtK=r*ORL55IMmgwpm1tq?)H?=nJ{$NufAGs(~5+$EPY$`cN76Ev4!~o>Gu z3leu)1XqULXS?EuQrlw83+W}*4y8FVl=K}uGrbu{idp3jo*B1;w;r@3zq`$&GqWfY zJ&eMmCZV+nAi06E9X)grkDoTk^=lwpb;)e_rM`xg6XY~fAA*_x zmyBb@Voy7IFliX2(FTV6MrMAHqH`gG&CF)j)5u5;Sq1M!Z;T<@pXm#10(un?fnNZu zC(zUVxVTjT}m$mz6`lAMGycXxf zi||n7G^M;T!n1714BrpP`X};y1VA7J;28pQ0lW%8h;zBnV|pE{EwEhPLeYSKd^B|Rh@ zCh4Iuq=%s>Dn@$1&fLjq7pGz#I{6Z99uoec($AwUa?Zx+nsN+4=S*w`qiLUm()W13 zN~>2IyR&PAnxWp#&;M0gniWRbU4XP+2GE;$7Q2U#hLDb& zkwn(0Y~UNVKt3Z%%98$2h?07UAkDu>X4H~$__yJthkvx1VM&&iB-e{FbF9Ckny##| zk66kY{{dDJv1sG6!RY!g#q@I0dK~P+TxdOtJUPz@)0Im;7;3pQ5K1AzdKaNG*_goC zlMT;XI6vgoFupV0j)D&4YShG}dNpcQlTK(TOQx6uCLP-fCoPe1A zizIoHUA4T6|M5QZyivp>_e0qYL$ONww_AGR&Q3N zR2+;DPo?6u2=G)YK8}Ful#1^oyeg%ltyNC(dU4IxDto>pUbR+vBD<7Y<;mzKSF1eF zCf|F3v?tLxt@85-Q?p*wc&>&U>>f0YWtpdEQEBon(&|bR*%^67GzDeHZm^XmugGu~ zO~6Xl^NGyNz&Suz-=UtD0ATJ3 z;c`HMhY)rvfDjK^IY0AKIlc+*eK)X(4Q=gDfbwDvUs)wc{m;3``4#}*1HdnGRw{lH z93R5Wl6p6W{!H_)NWxBw=woEyHIgB()&S|nMk(JQ*OK$!w&lk&WFFA>UHV7uyOj75 zQ%;@~d1&8@VzuuuL1q1ds(22R)*GuDC_@qAIZ&=cfagGY0s++xln)SI)j)w!Dtg*xP=-%+5>(k`ut%R!lvc&eEK6KHcg;&sha&5V>QNV|j>>4FXt=6F zkqL1k)pAEe98Z-gV{yGX>rT;sevfwOLs=H3ZA$+cddD8h+uT~(jEO=7=U^xmvupi0 z+jul$Zvw*l8o);co&~Ujz^wrG5NHp;m~R-Dap>?DX!IAuXb6lxB0n%2c^vW5mmh!D z5cY~apG3xC{DJv>Xz{7_tN0Ak;K8vvp}|TgbQ)?W0%VHfytKoHDQN|&0zB*(X;R50 zNF)+yX4Kwrn$rDfLU~r&3A(73nbt+;l8uOE|AiA2f0r0BOf3dD6{*<#O1>z14y6F#A z%v^zPJ4}k1Ce(AZTF=EQo~}2Qna25tLf3Q5^eC!!2cyzbDoRycsG?w97R^el9Y>^b zU%{BL-isb99eSLFE|R-$F8~mF`~-l|WBb1v2Ct?CF4=6;sdNg5W+FCj_6@!U*kOl(NsIDQ?bkYtyVV!4XX4w08WO(G3v_($7t)Vh$C~WuE^V zP-)2}s4xlE-zS~4Tk6LrzqF04xuPS?0UyM5Wal0FQzN1_F?iU^f7e z17HsV-~ljw#US55(|xoCY8-Edg$2_?&qt_G%mLZ6?5kl#COxGpnilqalBCu-8+^u%j{bJOby zm5*ca2~bb9c;BY-!N^^xd@=x+%I7g2&kYYmJfZRj5!{mGz5#$x`F8+>$}dM8IY4{| z03r7$08~lt|E*^jk2JaKdR;lut8HMnNk3XwZObic?a(hR+6r4jS>zxN{cgbba)c61 zF$ycTdYOlE)VCdm<-bsZQVdil+Vr1ZNT~Pi=gvX zL>sW4H2XLG7N(|6``cl;^%-mpv7%Cym1ezxid+PQ)dIlf1j+&2LdoN}{K))cK4qp_ z+YzGfQF`nI^?_NUQ_~iuREs*$GM!uvU=rd4`h8^2E1Lnxyb?QB71i@H)*rP?x*t_>nepI; zyKy*!jl{BTtw6oW8TR3J*gRnQ#>+QAk}C`@z`x}{s)siJt~kOz6M}g~uV^{fInW*Gr1e^o* z#Q&f=>6G>{*iqgpdRX~$;TLItiJW}Wd*H#0hI+?yms8&vTawX6zlgLn!#;DXTaw|( z@xF*eekVZ=hgb!uOw6&Si-A&G7Gh^+I6wHK8Gh?};CT#56tv?6o6=ZVlL~rdJ62m_ z?BhrF-kYY#sNwOWg(y;eGy_{~wbC~vgUq;D8M`SmF=~r#qRgd3h0!`%F;?<9as)nG zaar}{Or_U(*uBVpO8P@6DP|+C>=o2T_Tes*eYmo^|FoB?%cR7zUhoS=D1XUL#FvuG zrDXj>m#51y|AXFzo0jge3m3c*m0rlNFfBdJ8jE_!_U(NDWczj<0C)R#HRBzfUPnIN zR`JB0Ex=x_OVELDk@`1p&>mCih^6|`B71}Oa9uv)25mPKWmAoZWu3dtSy?aF0v&yD zy+cQGN_sO4a`~Ick&z*C{oIB{-Pa^pws7UdqrxlA+3c(`jP#+hxj0wBl`!DwpO?jJ z&$v*Tfc`b*sInQ9>*PGD?0|0(6dNIvN8@3UDZC|JVP1PLl2pK-M8BMVCg6Gc`2s|< zPd^j%;67dldTrKZG&qW!WA;@WO6znL^6OdlUR_lxWam^)Xe0X3`T1YZk^_rIn7vzI ze9Hec`zJs1Yj`>NnBkvnC?TAT3I;~tlO0XqW&p<$*ahH305aR`CY8?4%3<0X95~na zt>VmwTA3j%IYZD601JZgLz)*&UKA-QzK=Jdkdgd*TLbPn2)*}>^Ny}rP zw>KhI1{_mP#RWInCCxIMWy0LRK)DewcjM)s+>MVvp)m!?*tM$7>`v8l>{3DrVW&5J zZf_>4-pu{P?#&AUNN>IcfW4{DLFm!=#paMYZyEBJ&YJ3y9@vtEPVpO~DZa*^C~=$piFyE#PxLT= z-}4hyAb&yPiK?aV3Ug%=rmprC&b-R4OLhCCv#gLF)6>O>JRGxKVzxZ< zC9zJrBWr&9gpcewKmWPWw@;?frhPn#?L&e)GxuatR;@&5dF*$+r1rbId}?z5FU9V6 zDTGX3DUC3D%+mI<^)WUpGipEk(2Xb5eZVl9srt~JAgujpz$gMA0yBodFaQ$> zJPBYLfZ)CO*99rf`M6b(^cju|0zpzv46g?i7zNaq0Q4=l8_aBL2|~E@9k=&Z8a=<7 zx0{fD-3_SzQ}T2KWe$Q;qhNU zlUzS}0#97s1H+ntxkL|h-!#Y^)>}2R5wzz|y{q93k99ENshIjZv^VeFf_LJBrxBkd;|Yth*4h z8wjfxYWp()<4T67G?wtZxh8$i4=F-f=wRmue+O$U5*`m^U?zaJ1X6Yw#_0ewo&cY$ zzO@liWX{|PpdXooCjrRh33_%GcGtk23wTT_XJUoFJN?V#DkeJNGOrOSMwt0rHt3#o zo0*C^pV<)=76yMl0AcXg18^DqLZ$_SZxsXUp3f{6EY4?61@>UhXYN7#-^~6u{a3Z@ z|KYmbMfSf3in7^%ou$1;?F}8wL38JNn8yb_27|dg80?Y>XmB|^)u$0GbhH@qhxv4NO8;5&pU3-j1JWUPU1tnqHFzKk{S zA&m0mel$F<4AI9=mv)Kiw#J>{kxxbG1Z7qS)&|q$MrVxgAWM3O$_J*!C`!un!3Zmg>eP0s#GZkb{ zYo)aoxLGpK4k1l_TQ4K(_D~GhUe^hebJVi=Gm&GvA#^ksqZOj9y&ZsT{;UAtYHMdQ z9<{X}0V~?t#DCkHKWzYrwsr^r+5EW~fb97^41l`Xz-s`;0`T1H^m*OH`7hY()OOAf z-e}A=w3*xKmhokrrtBD?ylxU4fgRQOEvCyH`YP#$YKj8#ST%KMmvWnl@(|};Y~>;3 zADW>Cu~wlxv_>F1_6X_O7kl@2qT3}g24s)V@L6*ZC^NIJo^6hx6>gBGLTr)Y6E)Rx z5^fE5sI<}AG9yjbo??s|p@QfE-7=$gU^9vz4P=j|Q6b4^q(WT$242sW;vHBk3t0DDdL^+u zm);dvd-48*p6|X3B|6$P=fP`_>}b|^ql-@mMbMsWQnSXTRXAMFG9IYH`_ z&Gn)ugn@?uBF@(Ga2^Gy*Adc+pS`p+r5kc}9t9u_Ip>8uqL12%bFdj64=67tm9+!Kj7LsZ(r!?qWEs2_ z5r?z(d=#KL@Q(ozVoRN$JPN=@IzQR839bcZ924?UfFdN^3Pfq_K6^VLz23a$h%&-* z>@tx%?V;FL1FTU<8MWKq4>>zOKi?0~sCW~GuNK37KVTrz>9n^g!&-^FNxLXlOXa>F zz*K6`kMc^t$4+n6-s24VP&m4RIJ+FWA`0R4et^nfEYT)jDFifxMBe&mDYSU=o64?kGNLp-uQ3+S$Di<&6DvuCd(*qWLqH zLZyJ?f*eu4OgGbeVi9tl8Q=mi)P82*M=V3mGXun9S!~@0aknEomDNvxv=;{WVpoOP zo3YZ-;MiEs3j^Z|5h00@qhA=v!>dxx3j?Pj23Gokk(K`K$V&fqWTk)GUg^(gkyG^| zxd8d5eeZAuKIer2J_YN(Fz_paofig5@&1 zu}_a7tL=+wm5=`%t?|j8(mzMk3j^2ZBfmmKiF_?|={ctXd!CN9Ul`ysX0`awm|TJg z)6M-6uHscb)uy-#0X=xp7m#K}W?@$rnUTAouban;Ft(KG#^b;wEC2WcP6aav(&V zAKOu_)c|I>`Aj#P=B4D|=Ee6tE+{OVZi`!;k-NkJtuslSTfYJ_aaqEDTk;Sc4 zo38PaKuDX=?dJpR=eu=wFq2m6v^9*+2gI$78h^;=1ID2ORn76!%^PHpbD}Z#ays-F z*>^ADI|7e(j*}SF$5!XF+@b8gBfyWV#L={SVT@gwCArY^#9LJ}R{5qJxc&jP}l zj#wiJBm%gUKt6yg00i5ktklAOWq^}skdtRqq7P!?ES~wWsS2NE?#BzSt-j_$C><_~h4aclPCnZ3 zJmRY5hI0Xyn=d$(yzOE|hQG_s4{B%oHQ2p~@WBIM!`jA?m_Dn!uMEhnUb@Vw8Y(ES z46M-+0i9FhD+B51(QKZJNp2W^1&eJQ>t=012j7j5s*M1t&vF26&IljqU4eT4QAb{_ z|DZ&d!Sfh@M=#~O0-v5v;ye|J9O8_cYj-Q^ycVHCox9!P=)Nn!;V1;tg%sevE1*_D zZN+up75GgnZt$O=(jrw>n)MQD)?hIRe=vX+0JucLvzP=y=6~W(wkl?gq|y~OwC1mAUR-Pb zwgLi76E!a!U{KQn(#5$qGpxSIpW+s z+YfX&DU!nWD;-44G5Hvx&wi^z=&TF!u;1$-J6JLSexbw4R0*GggF^Nj9_0H<=EE;^ z`I)efB`?B%3c43>c`&}NA)#q_t&ih1Bsku04MUj`4asnbb8-{mNuXUOavZQ^B0mJu zWg;tp6ecnWwQ!lpg}{=D>;UAUF_GsXWrT^;xj??!5XS{-e4@Jnr|UY@$hnkjT}*mw zE6Nj%-(CPQqb%oE9IB8}rZ2DDfcsq)AstY#yH1vBd^7J|Xq+|PbnsAV#1sGJPeBQn z_G>)jp%zz}Q!5i!aRR&u!%7IPAdQ6S7?T$w(-gk0F?mk1Is=1=mNS=D0GJr9{c8geH zyM@faC1)YJ5N!vU9YdOM?b?l>N|9S%T4*m3_;@)RcH`xHuVzosX8dI+ z&;8z&z;cRw07&F25I5zZL!@`sD%y0nZB%7b2Q{0fL}Mv(^DU zKmGetwPr;~R+!nkN`h`=;E8gmAN+Nd4D&UF~IDpjvf*;`DIM9&TeQ%GXiAxY1 z0&o-nO`l4$@3$hrQKQDUYAaebBI7UdO0=@0e0D2FsaBi>zg(bDex*W_ef9{#HT%Ab zL*i4EEJI|Z+IYVKImi$>U-@5#Ur4)HcF{!|tl;3F+4o0~*c~zpogwo&u=bGAwiq?D z?|(W-)$0WcPC4Mv`n_4-iO+e#{coL2@U<-9(W^Y#Hr8ShRY zMaFv*fFtAGimBiE`E7&pX1Io%-TH{MZ*-dBL*DUjk6y3`pfmTolA*`seZz}1&wf^* zipg6h>$y?xu=MXXo744yhvM*-3c9kre`sV;>ysm}(dByM(k4MDy$#3(q^znw*GbBxa(- zXE|u;oX0gDaX*IPs<}#D2U13GOX;>!tuigs>Ket)%<1vHPFV$7OYd0i_nIT$OV_@; zHo&XWzMFB{_e((<@}mv#4|4t#n3R zfn6KmWIrP|z{Tg$8$Dm94e$@!$5C(DH|S*B1~|(oX_5qSJ^>VCNI4;mR$&KRrvR}6 zqkR|H0uO1@5A1=f1x4u&9zfR=lOkyl{9F{a8i>Gj02>KB4PYyQO#nUva3z`ZX-v>C zGg%h_#X2}oYdAkx2j?*j=Lar3#1k6Mj{;Sm9L}&Y;H~p$|G@dd27EAU(K~EPSznZkp<=<@6GQ+EuejL+7;KnsB2f;^UTg`$i$weHQv;z>sa1(Tat!x<|0c*+=C4d$OdyFLGark!r6EJJph^eFxXBIKP9wq}sYB)6q3)dpxu&9($I;2wj7EJ3p~2 z-UemQ1k&mUU_L`#O>(ij7Q{2Vudkt9@ikqvIXEKKN=ME};+kIeF*26c&T#iOe9F$c zLX<3VntzeZ(j{qWrejx}{Uyw7CCQa`#m68rdqRkKAF-7GZU$Bnv8Zjbj|ZN1#a~2L zJoIIC0>H^dxP@E2?%^>s~#PB{gkPE2VTo zLs^y`yW(t*x&zZlv^B0>akbXPZ=AM$4U5X&L}T;GT2Ds=ZK1Ra5@RUsf<%^7)-K)d zdgXWQiuVRtPRK_ml$`}z>Ns5TGLp;e5q-C7}>d+r=`GB^Yk8&uI6bykV-j^99_-R4q&Ny>ICGW zX`V(SWmTG|sx*!Mu!rWUYE5HGbF`8s#MhuKSJT)OSW;>wkoJ5Tr)k`eFg3wN4c+)f zC4LOwx{kKQlSB+}oEa;Ii(>p0*=#HujZhK8Uy&iKHknyr*Os^}5^^e`Na5|f*Y2r= zF+?B4sf1wPCAdbd@=CLAL9Fw_02I5$Y%NCW<%>|pY5?m1;1}6ezQfJYS(Dej0m*X@$UH5}G?Jm;Qgy0jLkZy~ zfC3$lGL6;%bkc|A@Coypqslo5?!;h?&4jsdQMxWi6hBRccR~>^>2Cs-q(2%+m-Kf7 zDWpFKSeNv(TPV_B2jroV{$8Z4iu7S0TvxifM!`KuUyOolO7=6MWT!;l4wV$6;DgW^ zu0&o4EG6=BK)MonF_4tVX8b)UbX(l#8;S@x zf*Gx4kF1i?O@m`K8iSQa!>DCzG*T4%rJXTyjf?Y)Q=}V8x+0N?wwY0Tg=tE**8~I_ z7uSw4(YUzAD%-}zePJ(FnUjjoQE6xto((gC!%+)0_q!jc$I95v4SgTfSvYT#Mf&{r>ltxP3Pq?n}_gjpIYoBpq=IC6ksh2T9dKwbDY z_?kl@hB;<})I^bj+o_I4ZmDY2XV=9!TI7!XvT@r=#)O$I(5|R26y#Ntr9g^>_{I2q za?#{10K8Qa_!fZN8);tKRM$nCA8o4ZBI5zbb&&-CcwIzaM{pNJZQe0+-T=86Ik@Xc zC9qsaW&`Q2BSuSm9eE8{cO7X8ELo^MKpxsUG6WTjtRs3isrwxu^8*b4eUFz{AvDq3 zHNEYz{3z4gacq%G_g)rj9{UTeZRd96)cYdpukXqVgEY^-3KU+l6`|3_wzG5WDWy*@=AKI?jNnt5J= z5K<^+DJQA1{1^9cx3H)tZXI%Jdc$$gE%qr<=LZ0g{L3}d(|E6rMmirfK&RRrK(0PHz4{18$10re*Uq3GKaCe06jh7fhr z!b1VH?r$_dTw0X^NE9C1M7^UFK+-SU)NGMZ&z>DR$qHR^GW<8SfGN|?%D)7DnH_q_ zu82cI5qnbu5xSAsEcii!rk4h*uth#~opLb~mw^y$!cvKlFBZW&Udl4B5 z2`Rrj36^}00Qs5^s*T^;4V*I!%HIxtA)O_%5v=zBt>9`C1^2vkJua=_YG({wE4Ve? z8`vo_nXFS}3oE#+Y<+q>H|JDIhrDOH z6h*3!rmW!30efjuwI0Rwirg?UN+CQ^hO}b^SJ*+t$;rCzTEV5_(@SmqGqRtOJ`N>C z9R{M9Qnn7Y5nbM8qBSl%rlCD|UM3}$^@Cq1LitO+MSLl_TuRnIv}*;ILr`Zfs?{0O z3T~X5GsumHcKiykg3CTnQriw!p+>Upuo!@BJG=wH-F7Hq3fjZvM;s#_+QZd`q-GEI zN2LDE8w)KPxr#DvwRG*_9=?r*-YCkZA6JZusDx<`x1u{J>R%r?6h*;xh;0v-l;haL z6<8>(NwRD`$Wf3caw*iYhbxq3+rt%Dw}*SNg_8PigJC;!w_J;Q6J|ebkW^#tmfNrK z+J!qlgg}s0fQrsEFGPd%#at@YP%5RXI9xNfRjD|fjpg7+X#O;QeVDMdK1T`c536=# zY}69y3gA})GZ2)H%2+P~s0Sc$F@laKFcUyq0?nJ4#_0fph4?p*nbN}S4g{YCgtZF5 zB>?g^VmWty=64xZ64HGnIDMGVP;13E`yt>6cW7~ZH^x(U=pVFdd!bPGY}8q&Zri9Whf~?OW9=hZ zjbzxVJvt%(Mjqtv+O(~T{GD5kLjLR7v9M=r)kh&h{_6qA_nHqt$bU6zC*=Pn0Qp+I z5hP!04*>aE6-}eQR;BZ``U5Lpt0@4_uN6eV5&l|6-HiP9;}jOBcjreVw>@GebcDJ3VRs&Y-tsJ5@-WZ& z#33V56jzu-pa(Rk0-JQjfOxC7kwv+_jC{2y+pul*b|b=a!aj1V@GGFIt=@i(d@IZ)OmfsVr`D3hwtCA7AB5H05y)g!R$ZCyvW}0XLfh=E zOn1GS+tXdGsOe7F&sxdORG<@Hyn@i~;c{ z%hd<9ZQ^oRDqWMDEiZ~%Uu0w#CB=;FNDS8|F7qhqh*rs=kZaYUZ%t%#ZQ@qBfciX- zBhe;q93$Sd*(3T@ zSJy6X5xPj1@}XK&Q==MvM(KaB1Uo;mi>n=lb?xGE2*;cQbnW7*8CX*v!Zxn98)16t z39Y7Rpi&j;JE4s-nnW~PqY%k9r^;T@wNS1(Ra*EtX85!QhTj! zWJgNr9dZTF;dCOjmgWjQPf=J76@{h8_Re-he&l;4fEwWyHe`lhv7v74Lxob3G9x#E`@X0<=+6iiV zNDLV)XJl**#qaxkiTJLr-G++BxRl6jza@BDcssv@cy^gz3 zx#nw~waqnOD--8d^pPx7KX~XsUGue7E>sDg3l+`RR#&yz1!X0^hssO6w;Spc2#+;s~o2}s5 zCgUoPy`Vbv0yd8j5>fNGEkn64U2G zYMO*JXU03YaOaxu`<80{1-_V?YR-`UPUZ5>Z!W|_eC@>kBxcM%S%@|9#QEa{E6EmH z+C`-6Wb#{~^vBt?^~S2*SOdRKv8)>BZx$iZm!~pqLJkN?65CMzYeJI5 zHY9x~BuQnIq~@o5$FxiGY}g{fO1fg$E55HZ)Pm6{3BQ{6!&|H?E5|_d{#~*1ENuT> zHI9vPy;|5o(z@K(B2-Q+3Ts&2nz4qANcBgoL+cPx3TgGfC#g(RpTwQrR$kIaUU)R> z)8DK2?L8ta}PVr5|NrM%Cxg7 zW4gye33oerDO`_VD^hzPfuoMpq3zw2x&5=d(=r$G zucHOzO3Eik!?G4@+ka8k>~2xkEm78wP}uX9u!dzF6PC2BKV{&+kESL`$~qSQ#AQuo ztg@DCWoB7((=A%o`au11qo6Nh{O^~wY~XD$hX3kTUp0b+yP>o0A09>)o|RJ74;{R^ z${@JP=z;GB#x#qpj_&DutHyHUk zzK&R0kxT#_@p8mbD`3FH;Ex)~#$r>du#7X}= z8;O|zx=U3%AmQV939<y$?rAd!YTw z#85dN$V|I7j8m<+9$}0~BCDs|YtU)!>5{ik=g$S-yz7=TGjGG!SP>1k6)v5bWd;Wa zCA`ec?NwmpB(|ZlA={ifBy(yjGo{TeH6CNgZ<2(}laOk@4~1uDraZhC9dwwPt&y3E ziK_&cEp9V2Uu%!dEFBKoppOmJA%BzMF6oecqj7tYS8;^ukmFT18vDau#nGfgC?i9a zUJ34NF;HY(J!d*zD@!p-uLb6HVwTJ~<0*7?j#74DHJ<~svXo*{=v-TRF0gCKcVp=j z2=W@8x6B!fARb5QOkfrP)3Km*37kji43}<%vjswTEG*py=P$$-mEH~KLOM%J55V~( zon@t;RAUK6-X^659dTiV*rp=)GCD&d_dz&286vk3yqz2(_X{%QiQHLqHWs=2$?Fuk zVe+~}?&oAEF69Ja7c6yI6H1xmchEUlQhN`K`C02r*-h`IbDuDL1*=+CztTs3K@a+Y zp*jz`$tZmmo}1_yjEwho9^C5Gr*V@7f;$gZt-21zqr&2LsnVaoc_TT8fHR}>5aDFj zb{?WRwcD%ejfIVzs&mumln0om-#JugDHCaAzyu!wrcCBIGS{m&z9gmzrC2;o#z0PU zku&2M(3j(*ZZ^n&v%$Gwy)lnbHIqq6jHTYl91C=X%s=dC52I))kw(#aVpVT^Oj>J+ zK7sba!=Sa2YMnsa#c*w8#?*ke*?0y+c;^VKV#}xLtjv_TOTBS7e#D_mdMl=tGgtYj zmj50EY%r5(ByBZ$0#P1dZXhN@FfsHk#)_v<2wm!pdJLhRyE3-S`d=Yp{#Jaq7+Z}a zFM!ZZCv>av6n!UI$<9U7?A%NGK(icLq0~F~5iuraaUOK4}@dM0KVg^Xb@T1D6 zreXMm-d)%Ji%P^O^~OjhXV_t)?IK1HJv@OswE#&S8BMBahzQ%Bh4hXR^mj;Arj#oc zN3~-IS8r^62ppq@L$Xe~<$5EVnvRhqHV9a6oJ(4r(E4JAm^qLiQz&KJY;dMrZzvW| zcM&b6xYckH)59vTMpF@WjTD9m6A|^so2?zHn@@uA13~XT=TzPNcFd1&fhWz5i5vtb zV8=ZCqM^FUj}%)G7NYdKrQ3Ph{{@~5JLctQfRO-JsHND$@0Mlfxqb-bWZN;jF?a2j zW5@8ka<^PNraR*b*)b0?R9*}t-HHc09Nhz@oBn{!0nVN|^RGZvk#27a<|A2O*BdV) zhk6!DxJ6(?4!wdL>RDvR{0lkMvymOs3^~+O=CGM&sC%Jf&tf}I7ILU(i5*i4t$XVJ z&J1+`In=Yv&a;509GciM%aKDpo7yoqA+0^j?U-8_dow$xwl_jGk76=6>%{dVx-~sk zciNIlwV*y$QnpikOFQPzZ-J?ZVlvlgVaJJXMUNKN!39|zn6Yz=vF!lI7Ik!}4q;%2 z^h;4$(~Pkl0qc!-ikzy~Wujas5T(}7MqNJ%p7}w1>Wwaq!LpzsOTFu4HM%f`EU`!FCuT*0*i53=3fj(HgaNnLIWpi%7W@T+H~o*6KGFjsO@#W47CZg ztqgae47CZg`!VD1)isv4WPsAo6WuKytw-B>t<;khjvHK`+U7 zv1{;yAm3B5lM~QilDl_2+LF`>?WI>=snb#yBti75vK_ffeekEDdT$gZz_e+Fhb)o3!IEq2R{GX!f+c*B9Z|iHh-^N#;{nL7*>NE(*{YD$f-AqFs0~qW-M?$H)fFc zteBjq8}hzLUS{WJqcyUj*HR|3-l$*?ceSKZs;Km_^+s2suZW`AB{yNHm6Bsp^XiSG z>~iNsnXHcSU7}}2(G2@Oiu~j>nbe%&LL$!Lhsq+ih`rg^C8=0~;y+o>iG`V1tJ)ld zjJ|DUIwm>Atc2*-h>pagtspDV)caP&(-346(e2{VR*+VxxP4oQ@)EgSgMXsE*Xnr@ zGu;|@e+0U3CkYZoTjG92&(XJYJPjK3K=07EORTh_)k2k>JIJ9p&Ym(^azH*3Ub3s~ zU%xrjXQ+Xv3=;k2Lo$TUL^JK%Lxe{4P-RcecB%`|QcoEX3qZ0e%l_S=ex|5#F^Vbb zY>MjHP*goc{Tp4)Dd)rjh$yVn5JTTSg0>fqdKm|`g2@t6Z~TECyl;OAV#fL^+Ei^Y z8mlT@mf}!bFx~6lf144+`ncXW)ZMB2>#4grg8mT#MmJl*w0yh}h->wx$kExaQCRe~2;qO(Q(1@*tbo@hk#g2Dz+ z*m4OZObaDNs3&tKK_$7kq8Jx&AxoarpndZkG(XbTwn%oweCDhGzv_|7u}A41^MWn!f3<19?N`cKvqzLuwAz1jaX zYxcL4B|k1Ij8UUg?ms?;Y3U|njn&mOLJR3Xf^zkul{t%0t%x2OkG7J#23>0ZF(T1y zt1C|drY?%nvNszW`T@O>Lh23ILZu<5KRdgg9w_)k_&JtddABaJ~V@!;aGI(Q+z#^sH@s#JaK zaj5H7@kk!FEAiKF7=GOtXA6{3>UQ!MHk`PauUtHI6I5!{tc(`VZ`P=6aQ*sc{(O zz!UfcpCMy9!#c_h8!AIktqq69VenTf^RW!DMGV7{p$x_;G?g`WAa;BZm7~fapAmSK z+*!^3bgJun0o~qsD~i?;X1#wZj=o{-;OJz05T&Us7lOP;6+0&cQQ7V`nEo4%{n_rj zdg7-?9S`R0SnO1%7eLCxj5o-ns$4p+#!Ap}Am_3rPSu)<9VRI#iNKq;EzuHOA05S( zsiU6}qE8ul^g9L^Mqmic#7cVyn%>|D;<5%qJITO7#%VxkR!z%%iNOc!tl5mnw3z%m z2jkbPF^W5e=&W&M;2{T+&!9wAa6HFh>a%7XHewyaqWaM97y$)Bm^Y|A@s2dT!9wD) za*vz(j55lB(5#x4xthU8YkeX}p%#;W=@3(&F)@9F+>#PiI1Ae;h3+n#1{J!yej}h8 zOQ_J@L!|(uZb=icwXuL(D+O%pD&V%k0(MLiu=8R8w=Wd1>v{oq-Xh?xT>^IBFJRB3 z0`@*9;GQ=G-20J$`@R-%|1kj%IMKEWQ}+i294HX*P*VX9M+6+~BH&P80f&bQcx=3Y zBWD9BRdgFt)aY(}o`P|r@jf_GHarV+y{m}ru$Xnbh@avYL2`?iu9PCok{m|vmvGaF z?aWGXp!#`SCE%4m>qVPP){l&9HsIAl;7jE=E>E&w%=k-$6(5Vchj3rNCnq~JR zSlr^`r-t!Y}4FT@--E? z+*R_0L@sxg{D#Qou9Dv&a=EMI%M-cWRq{0!x!hIqJ4G&cmHaM|%Uva3v1BWEmAn(A zy>VB`J6Q6EyGq{ml0@z*dG|?Mm3ATxLu#5-Ep-(N%%yhXfQ2548>w?KG^YMdsb{gJ zYW+D{!R6Gsi+ZmAtj5X3l;J!dNOz-aaW>!$dS}qUp?b>aVC0rK%LuuwhWbnh)F(oeyNVouhERE;b)%eB${)Zo~ONsq!K!`Lnb?`w8fm zp1RV)`~Dh;fg#<$35YZmV0V`g=5mI~iG>Mn$Ec9*eDpAw$6+m|4&$N12n4Zd_gKN+z&JcEKI_pg3)m;Or_hB?U~0gE<-v zXG@8hZRMiITr=C!no^DVqDFVrus}y!rcVouKv!l+Pk#DFKc@-T!EYVv zJJ{A8S0`|3hPS?Ur~x=x=vZWD$fX!z$i5a6;vnN$3=Q0dXmFzV(wRDyU4F=^{=rC> zBS=cpAe61SgJ)W`ZAG+{W0AyaTlPdGn-=# zqR?Z%nD_}Lq5CZSq^6kF7qjI2-ab!6R#Hs;K7A_H8= zh=A0jEuma1!P`{m7-k)#nV9Xa{0>&(?hbqvOkRg{Ddj)&h*_q0H{^^JW&Us9m_@Y5 z#uO_VX{Z~eq3+0f9u3dPY7Lu{BkL%v!su#sr|}DP&v)$eu@a!aigp_Jqtj@E9Xh7n z@j#m4zaNZ0LudBzm5@3pa0Y&O{G_^!N z&k}AXBDsDEY!s1UD^Hq7MGE!iq#~~tE!$ZlucDS6MC1mF?2b`X1?w#>tD_=?+6UA` zEkA@>X^v~H>Kbin>%2zV2UHo4y}>5%CFOri`Pp-=O1S|Px2Akf*-3hEvr^_+mGUM8 zNl6;SRw=8kN_jK5Jq@{Il~NUi@2J7T1D%L*rcu~I;Iw?KBH39QXR^B~8iiBP#>|$i z61nbmOssKQh{s7tH72UiUbAm8Cb>erF&kiKYMky>jb_1$))ok3v9M~P;x1%(V+qlP z?2C=1?4=9YT^q~9NkPVPiYjCWZLFZPNHpBD5K98pX!_F*wG`u$@v2R_xV7}xM7oH4 zT|`n(;|+0&$Tvmg`ACuRHANO3I}Z&1WH3Bf2kCivNJy$7;)^9mw5M3K_X(j`)b|?{ zTP%^KX}81{&~Aw?XfVDKNkX{4QXB3c8WzX$LX|JX9p$;pPGk zwi9q@4wBS7?eIzBd#s;;BO?H?^5bN#;y5OOZn{ich#*?9xwSNxp8SmgRnZ(6x45e4 z;y70!A9^cTGb#qa)vBDMG*{2CrRdeOX^E*=$vCHj>ZYqTRp6hsu-OlaaolkPs5akV zFYGV|NyFpROQN=yW4~R{?-T7a(Gky9eU*C*l36)p3w9#=pgAa~AHpiXfWJN4ta5Vd zUo{`hKe4suILY6xp4HU+GaSy;_OR+0o9_a)y`ysT5x@?!?JWJXHOJLJw)@aVarZFN zsy8FH&w#9c7LFe@wc{cjaDH%|uaI)9>GX|EJqP!y^s>tbso(?4`slFXy_9Kjyq%KTS3HkbGS37St6jM`u6kIFd zNQ|=-ERw8Gz+xqfYS&OkW63out{&h`h-;`B*G4O@)8I%R*8^5ubKx-K>iShkr!(f5 z&aA^<6vG#Elyak`Cpx^y5sYKFO@jZO*l`so9`H>YY4%c!LRFQ^i z;TBhjF7^i%Jt>CkTWJCnY#9|DNaZZ1LO%3X^dpXQjSBhDE496Xx>Znxiu1_A?xbQS zT^ydIxzH-&n$R6_$e-0BZU(&=GXmB+yh;m~;__bpES{&qWArx)_ZSLxBGr@Dxh~{v zZ8ApN*SF*xY$h9LGqn(O3qG@ zJS|>wf~frzHQne3QNz&#$CR9(AnL++Q5BraReVh)=}M5Cl?BO{8b2Z@)3BD0vxLRZP^91W|MU3sE~M>PlleYECsOUrf}>1W{N07ovWosKti- z=51X0u1yfN9bmAJDZbEpb3H5&JrQ>~#1?_`-{6>i6oEaPM{7oLSiY&t)nSyMPv`P-mzKLZwQ zy`ORNMn+V)3cZ8-Y0h;DmqeY3oj^DT%zKTZxXOAX($-f-NEu`I8tfWsje87^t?^^& zJ|j&hTEe84s@EAxj>h(Ir-o)48~a*h}y$p4i1T`zed&f8y7-#${kBnsIa{piaxGB#Cc;SRzAb9AxE-5i3iXcYU$qMivKaVO76Vo7 zuEX=JoKk%ti-!1W@V+5aDm@X=Mf<<6204gPs=?2(^hIY@Rp*0Rhz111vrOirQ-rSL zu|kx;Q%tCkIM?PcxfomJ3N%{n{{#MG|V{(hj# zGHH!-Ao#29N9?V+9$o8v7ky~ePVj#YtD13x$ZNMdYMDm?T` zv6FUybQq+&fvoXjtMP#FJZa~-+nHC>0isy)>q#Q zvGyX9>GwvIYzccdmJ>n$d$g<~PIIug1; zC+m)Aw*zZSv3^W z7RhRK$q|RT0j6_f2pgACC^nrTY}SQ06MZVt_~ko}Y)@c0B$Z(UMv=q{_BqIB;fAwr zaF@VUeE{*!rK1)T+a+{Vz;PWMHGBtkGaQ3=;S=p!YAynOKQQgq+1Fk@9r@L(LD?qA zc5&;nL5`l)cY;RkSaUl#{@|`V;}>P0griu>ql2yHR@-WBM=6C8NpEKu`>}Kz&zV4t zgHwSaC6XsS9NKUpE1TAgihtG$;WI>HjB)VjN8}kO!%BX4d~F!hur|~+tPNvhwV{p$ zG(N62{LGx;@NF)erIKHiP#bbKo~Skq1x0E@J2>pMVJU@7aHK{{p=voeu1rT3Om=L+ zh2pBm;r|Ejdl{!Y_90arSI_F(^>h$fwlyEY!6J>yscDDv1<6ZuC@3c?&FP@& z(rm|wtUqI_Bd2;LXcE~@IN~Ea22AqELN}f`vJRl>$keHb=%<8Jjo3HQ+XU2JglvmiFNg9J4<>#oYRj><>2~oNlym=wfPUh-lz%6()xFlZ#KFmCiA;4bHJiX|Jy7_U zImm45;-!E72$GCtj`5h*MNYd(SN#b1DnEn%B6yhywsr5zC5Ea4V33CSw1cLtswWUy zOh+3X6j1eEJs#nqscDb)r{0VL=FDKfgQlgbYWQ!U|FDAtO4VfeWuEl7_)EA)W;`V+ zh#&A*>4x<`H$!DZQz@e!aF|U=%ut`Rn6Go#%usW|5vvAj#D7{1c9>C|&L?zi^g}M%0G72_=Bk6FVE4C!7KX}Y!#pm2kIoiF1nRn4o?1)RNL58GSMP+L8r@86T^ zS+xqaM{3_cbZy&?BV$tgzR~`d;g{O?v(!GBi}YjWeu^@PfGB0~AnPa!!^$P;rB64@ zU_7{_3_bx@(lV%C0v0KPOgPLUh$YxcUJPSpL1KdEAajfg=aT(R~0~X_>=f-Q`s?OYo zTk~|h23zS4I(~%XUN{nEdjh($bQk0Nd(7i5&UY4;5S&Ro3dFda&Jh{6}iEPT++bbN=JVs zqwnJiR-cZ5jJ2VWrg{?y$y?9<6UEg^4ch>@Rj-5LEN*0ulJpMSL*!pT@|cM+UXWE2 zaY9KZa%a09#6)h`n`CMSq|ElFx~5cM>RpS%w*HLsUHQX}D}kw*2R8m@WVA1@*#yjX zVB#n1U%B(E_k*IRcN7#2QT1;ts@o*0s*(#3ok>tZTcIA5cSnGa^^V%CF8x|omQ`0sWx zw?oQ*r;F*y=)Xl5a})uSb}`1CC+cE~K}i}{D_aXb2~5(>7}B>7t3!lUX8|eQj7N}4 zjbJ^s{)}&u)z!oqOY2t9z1r=hrRWPtOkydjmO-cTSx}{5I?BLPc^CXrFr8%ZsXP@Y z?xkRAL?7w-{0Z|I(Duj}Pxd@p5xL}m-`?n%Y(#$$R-@la6cXJ1;46ZvkjRtJfmkDlCjU)W**P! znMXoHdKVaDj(Ziy>b+1g$yhx{m)CWmN)&T-dCi1hqM4`tW8jzao3G2SBm7c+SH#Ni z7G~g;ZkydtkHpN&_MWemJHrSkJx`D@f>(bH@iKtF2uIS4O)SI_oF7_$##L^cwZxAt zDxTRimWZ}hb@21trmviruZP8jDg_31>-pT$6iZ#T<4chm+b85I-9WSUeFv$gt0mT%gk_;w`+=-3#Eu_SF++D_A^g9G+ z;Ww~cXE1zZCvcvBH0e+4Ic*N#S?dYZiVH z9RH)jf7aH@5;Nw92vmK={Sq2nDmF0awT> zJ%OTfo;Bmeo!f1%-cM!!IB%i&Er}x>Edl3*S^u| zk1j#?#G57+a#BPNb;v0hIXNN6$mDo}9KG?t2&m81tVAd|Rw5@r8n&7yG z68kjd$~CX@t_Rh{TcNm{>iZS&Q5P_NVsJY(?VXr!p!NkmAS$@^FY9jVzu>o%(pxd? z5ILYr=~_lc%@Fe@=&9c_0B?B+_1_eyQbmt1MUUZ`^x%{_y^fJa+8hj%O8Z7>Utj@I z!FiSvqnE*NC#C<3VaJFPjZt7)Mn<8fL|s$~p{}MlQ;F_VaaX{(z*2%<=T%19r=o=T zuGYT5m!d??ah(&+g*YJ&CCI2r>8%)ckthMb)5Ll;YHW%)M;x3oO?*Xd2a|f|8oHs z{3>9&593~T>V+KyTr^C;#nS~`vP{5?Z2~SmBw*%;0%m*qPDqv2v zfVl$&%o{FX{xkts%o4C*p@1vb3Ak#zfU7?du+YFBU3TiCkbrBN3s}svFWIR}h6`AF zj(}xX2w1UBz{GCdF%7ta|dat|VR>w7W1_%V??L9}y5@3d)(t$dTzD+0W}lL~+YiXI*@@fQ`*_+?E=q$MTu&ZxS<04*o z=ew@H!NqQ`Z*U2pb)`JtU{%6rUA5b#iZ%hsXI*_mirpE$A;P$yj6*b|cH@O-eJ#3_ zZ@c=Mz66c{drXz0pSdsP3$MOXwg!zagD zr(gZ)A@sNb4juAQeD&4WP3u;{M_+v>nQ7pgufAT)Ub7_lBbtFNy_^$azYPgLE& zOA^hC__oM-4d0d$G|H)(^4V8kZ7c;ksS>P}_3Uffd?_=2@RHL{2+&{3i62$UM_+vd zq;&XEt)`-l@X^<_wH#anF-j@leDw|E$Q!T;;FGVu;SG8D;;V0DG^J+t^1)Z%D8b&1 z(MuOPldH=1!JqRWJ}IAJ?(BAz^66LKXyKI{Bu$m_Hm&gD;fSrLbLE`QRS z6mgj6@+ZBi$mQ}UJtT6u{K+sxE|)(U4w1{{PkNrn4}C&MXnx%|m+iCiv! z(u<`x6S@sOx`bG^iT6vZC-m9Hz1s<(6+TKIf)HQge$Y^^UZr>rIBe%hcKmSR1 z5F@P{U&ZKU1fC``IOh%IHns%aeaLSF8nfOim-mX}4)yoDQL?s#a`pHP_|#t!i)KunVGv7hREcbi#`6(fN}G(plOC0s+GTwJ4;Q6&y-h$jrY1AB z$A0?K&K6(V)W^kl&PxKO{VL$x7D2L{*Gs_p!v$P0MZok+1zfmMz(w~9xcC(TmwY2& zMk+StGt(|@Dqv=eS4zEr@RjRNN0EnwdL0_Hz2;EJ~eEci^omB$2J zm5RFznQ2$^8bxN>!m|V{nj_$v6#^FDBw)$?0+v1}VA)3kRvZ(svS}uRuj(RT^(X;r z7YVrbdI8sOCCC^enU!%WuM}iv41G_)uww#-2eXJA(L%t;9s)*<6EJ$FfH5ls)ZHdv z?85@ay&+)y&jKc7!2X$;aauD06MG7nG)}xc=$^J2Y(iD$UtMw3>{7r@K~OJBV_0YG5rzKPP>3TnEETE#vg_<*JDg*U)&C*}R{2V`C>+Rj7%h-{Vr@nBQi z8BuM8dXsc9TG0y-((9g=!(?D-La+M@Bfy27shptj;Dn&Ga)QF^5`uajtSb14`52gc z;T!PVNqOf}rZzM1T`mb_mFlU_G5V!e^z^!y8v(8s&FBTS!bIul1-05lrE`uRyugZn zO#%FNQeHJ>{!Q{`8>6ReEBePI_3NzY>2-vnzBk!?l)AP#qX-J7lG>2+^00$kUc(FifwHI9eU}k>nwG-%iTQrp!YU{Vj~1vaRU5O7usp=;?JoVFX6Tq8HSYCQ3&ysHaWTSc(3i z75y_)Bzh4bq`WSa`K&}=jQ&DoBmM&YGE#UKa0U8Nq;N0b-H!pmb)+M!Kwmrxvx_S< z&VL%#hVkT<*;?yw8pQDaIEvso8s)9b}lptuoT zg5xJlZwbTl&$3a_O63gs5MyuDi`a8xZO|o`y&zHP0M1bJCMjRzEil(+s?}6uaVfJ6 z_8UG2rtFA?0yHj6ZFU|ApTOOG!FT++e>2@*~M+1Y#!cIo*jTuef( zNMNsB%xn3L#l=s8gawpP!OiUzaS{fK1a`c|8z@0s{3J+tloDD@g9Xipjw+_ZP?5mC zv-oXF5EnlQ5}fFLoUIl@hh=dRMu`M=f5k;$X)G>&5+wAcgx1d^AG~P2F&)N<1omLX z6DdJl{3J+NLJ4g?gM=k<5++fCdkd&Eq;PD9&}ye53HUVk_z+_iS21I3q%-42U^Smm7$5?Rt5S^ z#VT6Ng6ZsmLtG5WM|GgVEEv=sa}^C{!9bKnRncG;%n(EjTTO#mpi31EW`VAf=|>q+ z_&Iz#cA~*7&`oRIi3YR4NoEpgFbniz#+qe7gIS=DNH`9xs-nRx&{v{rixpl-K2dE$ z9e`8e_W0I>JLB6~f<`%22O7)*wUU}xB6YAXmccB2z7!chs)`1)Kz}JFepD3=W`O}x zIQ*zCmccB2Etl4z7^R8^v%oN}yF)esG?)d3H{_+kEHE;fQl0r#G?)cO36>Y~b-^;Z zs$D+(;YRorXoFc54Q7GS!YesQnyR9~EHFlLsDXqk8q5N9Lb`~;XY!+kQ$V{p@P`-R z)0m>FXfO+O7x_|}ooFx%^e~H#2D3m-v<{g1^P%0$G{L??>2LC*qad;!OQwoHHjt?+ zRjgozsfxcfkkwX_BPy~vs4D){K$h5GLQ$+4A%AHgtEypuO~kf~$C?57I|ErQBvsLB zVv=|-Cp$w($75BJzcP^3DIRME;ExPs=_+Rnz~30i>JrOlY0{FsF4k`h^-zjowRn2#aTv}E0ie+e}RW)~lEGlSK%^fURL91%+dPy6ts=51QjUY<_nXbzG zG|ZWn%$>rV?}RyJ33JvF=ENaf%u4cjKN?xTpBpo>z6&GkSvSUvtoe1;iIK3|*`xwf z1Ma%Yv+jM8ofz>>1v!;gSs$&kskF-a)3hnpSrMQqb`3g1XA2deDOTJqT>+Y6uSZBH zOtHZ&V4w}x*)07*cZ&KQ&DGg{Cy+)47fa6e!@-$JtE{sF(JI|C-a6ZoWMt5I>uftc zVzEVp4F)9lM~{1y;ToBB7s6eH(cZ`o8>m|qPL;E+F$}Pyav!8b6>=YZJO!K+vrmR^ z98}Hwj`;k4pl-X)GjjKltswhOhg#nq;Vu&W1RG|eRKYu29BS54FwfnL7<2$lD$E;# zpL1cTD@`;5Yg!Qlzsh@ct|?IW?$=XbUHCei3{U-Ks79OM_z;%kK;$?492-3DZa$pF$89cHo*!wo6y;|F>`rf5SkVM_`wHS!KmAR>v&}{=w8Yzvb(iomSQe{6rqtriN#dNUyCrG4FRN2MPn#dmC z5gCL4t}to6PV;={kQ}`quUR#!#^&v7Um{g3gD;S=O`k`q-heuu^PNVy6F+J$S>gHJ z(d-7Sb~^&$+2F*gGZXb7&2ycz*}WLh-i5}VbxzeRgxB9%A|0OV@u_eRdkU)o&nRcJ zRj3XhQYxxtvs|R{YkI~w{VlG6=T~~_oSwQCf8j-R@r`vFlTZv+IfrxkNr2JfO^J1#OZ3$1mVSVssk@hw2uO3Db8lK~hmg~PU)A^dy z;EyGwx4H}_eowtKcPL6Id6)4S}TfS-Y;sr z;WR|5YAfFNOs`f(vwUXZW>7(m``(VTGyiT8X2+P*T{@01adzfPi!eXN+}^^mNlV6< zQFcingnhAKJuRwaC5zJxR%;O?a-rIS4M?OmWSMNSF!{Qq8nT?5$YP6Qw?%!eO;oFU z?Km?Xvsf)2Gzlv5;c7!&fr{ignOA{ zvsub1a`kH_?PWVniY4;zlTviJ*X=aXFJdg!R(8+ZcG`2y>c|rOB)P=*zMUqe7n#1& z4EKSZh6NPDotK5?nTN-mKXS1in^i7y&_aLWVzo7s7-@b1u7YC)4y54vHlUK%(8RQ#ZmP?_k<0)l!GL0@HX;K|KDUtw_>~=ysaKXN^iiC2}2_hSk| z)`}=<|F>BDUsNP$J`nII%`@yB=ypAD|J zJE6f1L&Fi;P&-XGoNa4O+DJQ1H;%gQDLULZJ54vnP9M6|=d2-<>@?lLUpU2~X%{r4 z#d;|f*@dUmM8a%47q!wE7&!;K;lglvLk1NYgxVssId+<@#$0u)Lp5Tt&Wo!7krn7* zB;a-SfRd)lGISJ^-$S`?u)^rt7j9yxI^s7*>%*cw_~|;#7d4>T zEyw*23fLaU-Km+0zQfL4dBe#LbuRm)2P`#WBLq{ZBAecGsf)?+ygd;*^9SJ|h|vCS zr|I6c5(Oi)H|(_d;X_4s3^Tbtuyff8X5dv$E#||93@WmJno0Y}PNUjkU8%}Y0HVVm zb_QLk-hR`iKE#B{<4CbpVhOAhx3<=y8FG^{*sIs|r<$yx1Xf#87F~u}8Dq>#%B3RL zoMSTNCotF&bq{Keh$%>k4I|-S(94;rUXS`J3@sBFY+`QhmZG`3Byi~rdaS=gU4WN1 zJUx0w<4-}c2igj_>U%w;c# zV_0Yi|G4D*w$k`wmQ%BiKQXI{)SyU2;DqE{_6&W?OwlAetCWj;bc!CGVrqDPaxR;O zvraYzUVLI!6;WseqT#IMTs93$P~^h8EIF$#_r)i{HjTNKXLSn0n&Zp|R$r+*%&L9^ zVI#p2AkX@g^I}{Q89%Ds%@)HZlR+l>F^0-?9DY6r%Noz-6my7TJ5-Us%)>>V+ftYr z*6_FT8bfgj?AZ~A?rNcTrBFq4;uA@ISE*+)sqySd*n8ElF?(ZggoYG-Ju zNG=o+F;6GuQjvGZnhej_8ElGNe7-~70l(*YJA+M;sohP6SM3Z96&WzX%l zjz~Oj+8Jz$w7bBe_EV8}>Og-`N=&Dzay!$@N20E){7!!DRTiox!Ha;pqWm2qI&PsA+G(*EHP=pz1j5zm#9U@u{N?Nv z)fqQ>JSCpkd^^nLriyG|-M}NW86xEk9Tia<`=77K97g9*8 zw9~ZAHz8AK9qcqM^BU;6;9K-*UF1g3muVxRWVNTqdd zz3*eCMw0h=J8$kkP3+5d-nO48bt!pYwev2suy5FS+s_&5QlB0N?|UAJDf};Fs(e)Y zlv^C?3>sPfWzwW*+i&V&sC#&1cLt|~zs50kxy_-TWNk6LTDGnlcifHN zynhp)#%>PvEtbii9{(ACXY@&_oTt|QC;VY) zd+j&ub*OV_CK+W5gbc#GdnfG%<85eDuOG1zK8)>X&uJ!2I^p&uxO61wGi>N^e;9UD z`@9V%ZH}FGkI=4nS=>Q$<-)J9Y7*Dg)b=ruO9 zsm9XvCT*RaCQ-FskKX=amfU(T6^NC(YCQrAcOl)-fTS~|bqWf-H`i2~lGFFWka8DI z96N3F=v-EHIQxC24*UW7eqD7{htOb{Z3ZH351Sb5Fxav<;{g<%J}dj z7!kuq@KHe;Ts!r_$@O7nfs38$7|c2;r*lXNp9aIfd{o)>psd58fs`o?DJw44LsrVU z9A(4LM?bQ^QdYGXKL!?p^egEXvMTG++AR~>lxyPIwMJ!GLt)`TT}oN`cZQLVFlvz> zovNq$DQlCGU&7)?Qn@ikmbjT5Rd#KrQ>{YVOSyS6I*%|vdM|4pEcYqH%YFyF1G8g` zBwy%dTQK-tPWmp?E{8nNqYW7xu+0eV&C-JoTL2a*|e_~G|ahrP9;Id{pT`(Z|OKg{UFWLZ05gL1LB zv^K#8i^sk#Hbi6ewpfdU<__3+rbY)0x)EHq;rf-$w&)X>uG}074sv%u_U8Jl8h3pd zMoDk;8uuP?RCIQCE~J_AD@T`o13aqBDFaag?s_B~Ul51hY;G?2XBvZwV-ZC+4*X4w$U<}Dz<;@&C-S*h+x-3WOH*7HN}(e~Ymw8l@^{ zQOo|LKi{al;6@w@!09RfHmh(&rOFpK;qn*pcf{k{Wx2&_f@glr%D{@HA}^n$yK?^l z<9IZ#Fk6D8(M%|NZ`on?mm87e1GEXp|Cqu3G@Vg4?#PWz-Li)AA2sy4j};RHV~oChdJYEf%BZIt4=-*M0tv zPt2t=BXTlE4jO~}U)ZyZikl2`Pcs?5u`_U#HyMuiG8ulfGen!R$#tG-E%N`Glnc*Q z&D2I3zu~ZzolTMUP=sb4zsJsCQ)C|$5r#B7LqkQLg(X0^vXXM)>G&DiNaGLN8ElGN zXj*anrFI6JA`@XhqnXFw%+AnIkzX*Y6Ry@txm4sKC_*cazk{8@rbr{xisSEUXRs-9 z4-^pzJ?#t)6}jEC7Wr$Fa;eCfmue%8e~6vIrpVJ!gvKEMXgh;V5jToP7{=Qf8Y(i@ zv=;d%C*@L+Ow*~& zT1)&39kK4!>=eeB))M~`JFOiCCl&bzPG?BC6?PhjSrwVw%q>|9?xaehsdcdzX zH-Zhz2vLEaZE@;P{(5}}a1K_N+4+*p-l|Vd7tX!<qX499yWv_s( zM+DsZnt*K|2)OM_0Xu#cu+!U_0d5Zq*wtFVot*^S)my;s!2uuz{5`pIQX)FL+=VW{F#8qeh_fvPlBT9-Yx_e76`bg zrGSgO3b0_Y1&sMxK%KK2BO03{ zU|hL?@f`(B7(`HV)oB8*o-SbF30V7)fNPHlxGvb8Qq~mN9arwNJ^-%>``kE#Q_q0b6DW*t$%>t(ygGJ0M{DYXWZjR=|$bo|Lk) ziGbTr5^%=^0lO{{aOXk+cWo4~d!K;2Ulg$CUjp{Jdr`_gB?9g}RlvT}1>ASBfcsYp zc;J2k`(GFE;LidMl=NoshX)8aI7+}H=LtAGU%;cQ1w6Kmpve$vhD}brUwlK~5ism$ z0mIYKh4pDNqPc*PCkYr;Ct&mp0b`a4sM{uB>;VDeUK23>-vTDkxYMV}X-x%8>@HwZ zoq*G)3z)oAz!^6SnDU^2Gc(#DT=Pq%5;dRs43W)eiMq{azb(GYzZ5X%4*_$7eaSMf zt$_J`1za&fz=GKVu3RJFs@nuy{iuM2?+RG-i-2qLYAI!LI{{1j2v|B%z_LpPEMG2Q z#f<`1?iH}=sDRa<30UJfg;M_3T)^7i0ioUs6z%7*mwsjS-eXxKXQv~dsDd6_S0`9nhphW>2?8(kSlNJ8D z{B{JJExam!5mKkI6=QH7k(t(}*m{sG2QWwOJh z97IDJ`pG>wsfjp)xoj-MF2Tq83+8qiE;A+SK4PMcf`b|7Y7&z=Vt}2rGo`U6F=s|p z*-3AD(lm*=$-iNXZRB8XWVm@Tn^`i_c`trZ364>kSEw2Y#r*48YC2RMFY06jnaO%0TbA7z2hz}xGGFKjCVfX? zY(l1v1}&KPZ=7}fAu&_$g<6uSc`V5IROYp@r&8xfd@^6QlKH2V%oh9px5*sj9DB=i zZdJz$=RyA_by+Ih%AaxVWUNfsy_{6nHUrtsDwUAt0iXm6*5YYSHy9gKq*2f@gk6(h z0sGTozgQWJ+zu9Wv(n7C={9ivK7)J@KqKqVIo>^T2E@Dt+&JT({JOu@^zqJ#=fPzh zL6`=*Po(adU2r_oIf+Y@%v5aFI!_-?skKbU1WUfvAcE+@gN6BtX*gu1p-|HB03x&g zf<-5;!`>y3fTm&2^Q%G&{n9AZ+V9YR($(qHn`TpW6c z%Y(<*A#{c!Qg=%dJA{(%y1xGZ)FG6#x3XM1gfY-8zNIV#MmmJM;gAmD9XS4X9YR8G z^~4|^EPD$reNbX{{WNr6UxZ29>+}4SLlNe1J8@2dDe4$!54tx#nC+L zIX<~R$cv+SD}$8Di=%mKgPi^G;%MHDK?6&B-WbiZ-r);o1H&7mdE3pmB!lI^@ZxBm z^(c9e){I36RZtM5MT7T83&KHKHF$rtpfE_w2Jep+6a{JB;Qi5p(jYAyygyn{7NnJf z_eTqw1ZnBu{n3J^BA53^3qm57_eaBq$mRXfutVhX{%Ap-$mRXfg2p13_eaA{k<0s| zVVB6|{n3JA$#vcz&6^>RM8n7F6BTe>)|&v?2cd7Kn-{B23ejsyj|>E4sCyNz=OF)d^}+e;aBZi};tz?ztF=Bujv7DN>0 zQpbWgjeWmOMxDYYLFsuML}FM|<9A4!&R#x&^yI@JollEG0%Tu0Wm3E8AN_A3oS7B?sw0k^B)m=+$k9e#Z;H@-7-b=EcwK>d>s{5WQo!k)n zC3$}pA))Jo}0>$(zqMHJgx)iq&|m6BUh)#{G2Yn>BiG5f%GiJcY2A|RibX__VmiI=I+ z>-^AYp(YbKnP++H_{2=pfH28N4)_XF9iNyfZ_BI*Oa3tbR2`p~DVLWbVpuJ;j!(># zS2Ya4CuYjq#beC?d}5}&h3FhTSZtE`#7u^s1Tl-vL6=X=ly{NB5w-r9CLrsHnPwwm z{M1pESx?L~8yBN!Nql0ayk|p6))O<$&WZ7hq&hw^Q{G3g(bT9qJ~7iY7%M`_16_oC zVy3*m1dtemuff8)1rxc7{$~a;6|Otf-Ki=@NeDd<{(-Zi6}l-3BIj`&sH?a(EE5ez zs_OO*%kL>6gTcPDpx|aUA_r#dJZ~0t9itqC!u&M6TwopVbe&(3mA#i7lL z)6A*bQWo>Ls3=7H2dLv?h#WT&Ys@aA5yp#(5fm!*L_Vsn6|p1Zv1TgQphv72BjR+c zTX_l)by0+tJ7q&ZU^h}ioogb5ZHP8jHRU99*%jw8MBNBhucZ>$tfsw*SrNsUb;-|E z>3-kjtEP~PgpVIpm(CiYr_@@pf3p7R$#SgfowXeYjL&ZQ=v^?(@t3s3(l0hWmD(3O zJL>eS@HKz=>Jz6!P2C!M$LPvB`(yF00$52;!Krh@C~zM`1zzB;r6%rLEOqc?56NwW zT;Y(Bh1f(uUvrRb-FJgvMf9a{06gCOzDvZqbX zQ8;-h)YCSXyC3p&P>6XUPY31k=^zI4;OU@zJ{{z#^xcKMmUKV1s+7i5X-p0=1=iC+ zp6+!>q)=3W^>mP@2TsH)-#rk3>aCv+O8L$qIm)MlvUV2er-QOs27EfGkWU9)2zCA+ z?%q5;sv_$fuiMMLO?Q$8(xj7+G$b9G5FjLg$|59y3&>6bA#4FrHf4>ni$V4sWKmR% zxFYVmBB-c?%ZQ_n+vtqrFwQv6jE;{wZZpoj=X>hbz15xYywCIdy?;$UpWIXToKvSx zEnTuE!0agW3Z+i0>FWr~oz3&_U++o^}#C z$Q&lEeS}o#^{WsDTH=PFgW3Z+h;INL#MbzZp@Ryhk@E~4Wd7Szgr(V>PX!%R43Hl4 zpf~t8N;F(Zg&RiP@HccT3Q#@_9c2FCi7V(J^9e7#^$QsT4vB(}6px{U%mLoGf(|lY z_R{8g5&Rb{FQt$u=t6o79b^vl791qUc_Zo&!vE%gQTFqRVL^lm!~TebdVGjxyl3`Bzc*{rb5s`QU%$U2GUgsIw)O5GeFQmQkw00MbJSm z&&~&+gG_=BVu45~=pgf1UmqIj8eFNOU;))9LkF4PdJ+mc$b8Xv8F{C9ArcBY$b3_m zakV5AbddS3E@S@^3OdOAK$qcsMv+j^LFPxgjB78Upo7ehb=fX7)`Wr%GEe)^j#U;F zbddQ6ADXS5#e{+mGXIpKt)PRuj4l=!dv@}&L3OdL%Q`ibR$PA>g6?Blov)ySOo9&5`3gG7Bo28(GOo9%Qtb~FNGCTY6q;hgj zJw2d<%x-=hd?nekZzxzn4U_jinE&!56m*bzj=!E2xr;>(MZwji$k0LNPo9K=4l=8n zSWGDBAhWuOk%WQ{G6(vb{NNOHkU2`1$sdk_4l>8;GA{Lmf(|k#>N5FbRM0_Yoi5{! zIH90}%z5cDx0ezL1s!BA)3xB0EWm_<4l^jv zqN-&@K?j-9X0-^GakiJye9YV?3R?-KW>t|;&_U+p=C$+!wV{K|I$f3Pg)cHk3OdNVym>9nLj@gVE;_TS zNGRwab4l}BnuiKH$lTn#s;qYf9c1n>5!ZgstW$lZ>@Z6ebdb5<{D@!oc(l!l;UYRI z=pge3Tfun>NedknbdX8VL9*+??@%NZbdY(ciNa8iKLs6R-j%{u&_U)sCR|i~W{Y17 zh7K|xG-)fUV?;p*nUCptb2=rFP|!i<)4GCFDbn?Xf(|l|H>)KQ3OdMqMpxKH1!G%K z&_U)2T|sk1K?j*H=?dwNDCi*bm1ea>LO}ztk1d9Z}Fh=2y*XiG+d_|s3YsGuZRjA=XW=7?-6Oyekx}XYA#Uk*KdzvI%vNXClKO}# z5(+xV%-8kdvq&iDAhWG5b5oRB3OdLvJhPVlTU5|NW_$ihW@ittnN1(Uf(|mf=rU;QT z%cM;O9b{gp$wbFPw7Cq>K_)>5$x&#Tf(|lATe7!CiHo>`4l?B@M)`hTrl5n&NmdwN zYGg^r6?Bj}i&L|?3OdL`5mq1q>rTLv$_oh9b~>>EAv;XxPlHcPg-Eu z8C1|g<|`IHQc0iV3OdL>xa(=AibLFR8PPAR;DikdH? zOhE^kf3{^@wPgxA$oxvOMVW#QGJi->RM0`D5sx?US=(g_I>^im$aaK= z$TC|&K?j*REz%T3nSu^7+uD)Y@Gi8(G6fxEc1Sl&#}W6H&_QM|J)Yy0o4oCVf(|mP z{%86MI>@}>f1)4e-(H!54l>7Skwlq-4l*ZcY}+pd9b`_iW!wpuDd-^cVvQX>Mjv)W znSu^7SLm`1w0%O9Dd-?`wJpO4EG%UTI>>C$WzwdC4l*}sGEt_WgUp>8+jc`i2bp_y z87CE2&_U+@032{@UBnf1ka=C2NES$3K?j*PG%r`sLFQpi?u=zcX9XQ(J}H~7=&YcF z%wsl(W*8Vc$Un;Ykl#f?2l*$3M^fh$#zqMd!3S4B2l+?mDd-^oG&_Vv&Ig+%b zpo9E(ahbU0x+>@({}GOEO6VZpw>*ml=%BcQ4)R3}%s7OvKt?f>A|gE~h#3gq4-qw? z;QKD(r`HusIQjlnrl5m-=NK{`Tab}w&?jch68L@;AqgF1P2(vhKnHR1fDX#IfUJp( z%M0k5rJ#eXHJBVSg3nX>B1=IBS?e)7WCY)2u7VD-Hvg95DqRH~WNrU9bEU3=4zhNC zNO6tu$814C2U&an;Bs3k=pgHQX*2w1C{r6|=pceNLrGwI&zTP+v=dUne3(%Vp_&OB z7Q{+@dlGCo-{{j~BP2&oiz(cIw-g$h25}$Hr`>F zwZlNeRz?(bP;j@gnHC31c9=`NU?wHTpU;E&MnXXc1@|>kOepA}-~ml05(+vfcrb;n zpo4;kjPINzMFFas=O2T)Mn?r56eQ>%S-I>|M+F@eBA^JIIlgOO0sLBZz@%%^E3BDE6=Iw<&(A>aGZz{1cK2?ZS#d_$MP zcbT5lQqV!cch0P(`Ik`8LBU_?`Y14wP|!iak93)vqSR8*LBZdjST_FLBVQWA>9!L9TdEvSuK%J&_Tfwx`O72f({Cf*A+BJ6m(E< zlCF^Mh=L9ZPH$FABouT|aE`8^IijG0f{Szo%@GA16kMV!q&uRZgMzD?)e;E>9TZ&a zal2Q$Q&7-B!Hv4?4(>1%bWm`sF2iG1B&OTYLBXB644D%N1sxRJqsydC1sxQ;PM1lW z3OXowP?t%Y3OXp*sLP~H1sxPTq|4Z*s04ISC7^>MFVV{tpo2oiri2a(wF#g+Ftp;2 z8w?%P1JFTxDUXCZn0LF4=o8BG(c4$>0J0uI9IUwsMe`JNP^hgd7m*6+(gLVZ+?3Ek z%_StXghZZ#4hrSXL*(1i6Uw5mJAe)fwRPn*$URO=FAU>&&mU=N*)fV^ykPXamJoS3 z{G!qGhSzNV&y1dfX~`M$PttISmIS>`2^l^^M6d|$U7Dpfp2=l<&jnAAsW5SADE$3) zLu^ATuf#gyf%6VL%j&g*;6cHC{jkd=fA+CIo!Ot0@TZsbfy2F}4;=1e^xRA9-8kIW z$c8^NU}=HoPM2IZS04PiW^!wFUw^UD}ujuQqMZ73S*5dj8E*u4z{6Hf*IYj-=oDH+fu9#z@;r z*6;fp0!=kztbEY-fQ_tSJLzSBK7(eAhfO0Wxi7A!x7=Z*TazqvxMx)~*tl4=vR7bT zarW;^X_ej+KDuNUobwRTuaV1M{V0?fl-A*8U1irz%i*$aupyqh6U@Z{Z!4>7-+6td^$h+5 zVVt`%Of@+TnK*Ykp=isX=+~+b-X{9B>iZa3=-2983=#Xas(J}`Z4L?AXWp;Ptsy42 z6*9TKl*yevnB3K$$>C8&E2yK1^OXA0%)7C?*T0Gg-Kp z$)dGP7Vl+Je+QE*9%pjpOH7u$&t&OmOqTt~WO<18JNL_5QNUznSCF=Y`!g9bgvmuy znGBu7WY`KO!?!XSaTAk~_c0mu43p8nU^3=oCdvO|GS)-e!}_%ym(65+36q+$m`oVT zq;@isiSw9DTFqqgUXa2ycQCo;aVBd|Fj>cb7Op?ZcN^YgvN4Nxl=UmzgpFnW3O5gB zvSk&Mtv4~*_6U>huQS>48IzqqGTGIJHqZ1c+})YUwF8*!sbR8rHj{m;ne5-on0k179$?p+#RZ-ZdE(zpo&*qBzrv@gm>iwMicsnauDEfR#(KK{{N)ji|$wC49Gp-R-cfC*Li{2D5%0 zR*Yw|ayFAyo0weH$Yk~7Os;;5NyBGM*3iBbigyima`o%5_G~8WMl)Hzh{=X+Og0{5 zvgt`Cn_p+Lu06(N&nYH*KVY)&QzrYr zXL4PO^I+^i4wDQ&sq=S&dYy?}t%N|4D>cfMxSlSfF108hCvBE<)f{;j<`9r4{Dk*;M@lRIntY z%1e)(0n9_Ds#@a~p=t=uhal30Lcp48(dhzUO%1@yegT@A`i4<87_l&LufoW_x(2r# z!leqg)i7KQb5&PDio91NRE{RChw?92!AX;kF8bi>ONYPl4go5Hp-NcE2HhB%PszFe4g)4rQHBYE87)v-ThE zmD>8ZbP+uG6WGLjv04=LVB0kDk5hgdIp3%u$<$UN*- zKMKf_ND3+#W0(>krE@n@#xu*=N5?&~I5h3zl`bar35aD@u{M$Q3F#{^JLE8G(w_r zoD^4~rjzF)LxnW<;+%HGppFGjR#Zt}NTP7jWB*-liZB{Q?mUg0ogyy!Y}mB_!o|7L z8>A>w91Rz@lu;a&p)%@KB-#+XWs<)WddxhmsRzyTC)qiLqVap+voG7kDU9AKL{U zN=`d2Zs4IrCUdtBJe0_AE)n3NMD}wQfrk=#v=(?Mxk1#jdhx%}z(a{GWA*^j4&#kRnY@4)Rj^SDJe1hV)X3qPBoPxA(-n9qkt>X;D=7>-l)72~ zqQq7;V^+qh1t3bSf#vYuPO%n%D6zH8rBe$)l-Rn|7`8D0qQo|EQKJ+@EdWtsJK%np zGvyc*wE#qkZDC#HEG#1c5GA(LHI9N6wE#qk)iW1r_D=_ZD6x%NY5+uuZA~``K$O^S z=4!eCM2XElLT_c9QDT>4#M?v!K$O@5bn#6@07QxPb;}o3C~5(S5<54Q z%k4?j0uUwEKUE}Z0f-Xg49jZbmVgE*Y5|B6zrQ&gVAG4Z%$zPXVH|JHT%71ua74DL|BVx4RM~C-M{^O1t}AiHxHFQQAG_N@N@b zh|=ywSHdk%W)y%Zv5VM4ElU7IiH&l&q85NCv7rvbE)M{r#73}PH+$TqY5|B68{cf9 z01zcslNL*Q13;A61lLh^Ns0i7603DZS{?w165GqprS>7=&GfP^rtF|=)gHPGz=x7r z0HVYu@s9%jiCO@n#3r+^;EGxRqQs^$Vf0X$pGg zDL+!MiZua<6038)N>i@|AWCc+%lpu0fG}rBTEe_;EdWtsm$>okpv1RQ=@PoHLYlPz zM2TJMTH2hZxdWOg%4q;ZiETnAYXOK7yN2_~t#T&XUM&DoVyhkQWKj!1l-M>dEpBSH z07Qwca8&F*5P&GLB@UM&0uZGr16^`BpT1Ls+u?$@J23^!DOjOc3qX{jOjhCxm{O@0 zfGEY~JjKoBgYpx#07NP7mddpw01&0PGF2pM0fiQHH=-7RC`DP#Wug{_)TMKuAff zVK!%yowa2^NJ+?1gHr%x2?!~PEgS`kVOtvrDG51ZV82)5 zX&gZ|J0PSarpw`43m~KVc>z!Y(mG20J@!mq3 zBNWFs(A5S*>1=t#@9uWNP~M+N(`fisVyy9d|4n~hdR|Cq{DAP&M^s_TFQu0Jq!~Cu z=oc+o(<03v$@ouwJefp~mw))k($?S8&oOj@UX8Yqg0Wi~&hTAM4-ucSE%OFaIu6Np zkp-TyBYZE#5G^mm%}#kkc-1s*EPU6Kvd>uAx+C2PBm3*CNerY%2%ztx;N(z%z!KU2`R3iS?x??>w@L1(Nw2^CV(Perx)w>mZiY zkbf2sOM1~KV*VCu*@z`OiD9{jC6Hj4q^%4NyL(3a-I=OEE}Us`hH8lFM}&p6hzzEh$WVWSYo~C8&BS8Ubu)Q)|$0=ZSRKR?>$DH;SY=TmmRNuAq1oD5bP!9d zKc#3Z#1iW-DcTCL#QK}hG9B9mbu@EQL8C&$(hy6muY8?Z2R{%|Fp+c^vBc64ORT@^ zb{xbK>w7(_gIHqyGsPK&SYrK@!d8eS*1uAW#4nKtpIU}rbIU<2vAlk?G*v7LvBWY{ z*b1@43Z$?VVu{sSXFG@`79p0%7RZg6tI0tuu?Vrm6}pHe79p1Ce1%wI5n_qXSBNDR zA(k-TMJ%xhvBYL6#1e}TOC-xdEU`NKG57A|+(s<1y7~WRDYonz3NEFF$xE&+4Y9;J z$DbQeZNXN=L0pVjVrhsaR#g*=4q}N_-NcB4SYi$IH~GOS#1d zp%6=~iMmYw7!_iPRj13iBX$r=ta<4&x0iAeORQEQ&0}~a%f&$~vG$}ZxQHdz3Oxy} z#VEuQix5k+7T_S3SbOw{oF@md#3IBJ8ArB0g;-({Vu{@z);%c1&Ghlxx>2hN;UJb+ zw`jE|9K;gqjudT$SYjQ~wH?F~ix5ks8|WMLqEm<^)+s#`vhWpRiS?E)lfA1#EV16x zWvP!37qP_pSl7}jMj@71ze`te5lgJoy3DN@2eHKZr>-Cyl|n4BJf_wpII_%~LM*Y` zG^?POkwPr7a+;`WSy6~3RBBX&x%X5^Hnws5eGG66@V&wS*+0Vu|%hvsx}@bEbaH~Xt{_bmPc369NB0imRLRu-%{+~ zIvjBkORTUibAIM_KdulY~e}O@&xuRp>HlQz4dEJ$0G1sSr!7 zKDtcWREQ;3e_bYRD#Q|Npe~a(6=I2Xp(b+?ODsYxk)u!tvBVl}$=(_zE*!)XYb+a( z@8=F;i8aZJ;7g4xX$P^yn#IaCS0R>I2dyiphGlvVVu^LLh0idyVTD*?9ZK;+A(mK& zxe43K3bDkxFGX1)mRJw!$_lZ>dPG-t5KFA1I@>`kv7Xg!D8v%$1zVZFQaOkv)=3Kt zJA(?b#CpZTM=I&FgIHpn(sdPLiS?$gs}M`9w{=~GSYo}W={krd)^99MDYBf3nlHjZ zEV2G<%eZPC#1iW($#xM-tRGSo6=I2H1f*@*G!$Zql@)M)odn3y-y;^%G8`)}Alnfd zqW0S_Q-~#2PKz`J7qP@@Ye#0o+{_)s605vvJcU?d_0r=xUb)H3CRwHsORTE@nZ80S zvF^6hK9gyg694ub#1d(WHBKpeyp>xSm#3bDjGtjV3RtczG;Jt>>6i&$bEvpHSvq-jr|mGpM~Go7Ou z683#&pzAc+;1m!g+x|gdV8uS8oF^Kj_xNrr2#A5PPQ0U>DS!%vb>f{A36o9)N3e@1 zKGg#2#5=lDVV!uV;b9bcfTj%iA}STuiFZc2L}8tH=fZ_Z7w1w5>y--Y#M^*-7K=)S zb>dy0sxCdMR9Gk8ZG#YpFRUm{Dy$Rl?q%@D&6?59ij;K^vC*GSM$tUBuh$vhK z)`@parNTP#9^&k?yi#GEcyH%O(vreD@!rK{;+pHOuui;3IC>9>$nT%ZRe^n_J+Grl z25}Y;`Tds};o&H%vlSx0e<3!yNN$9)e6~X5_pdxb5p~fy3X$L6V6zcfM(c&hJgMWK zLG9u6iv+phAKM$=@&N*Qt;rY;5a@#g1pMQ|gGqvx!`S`i=Xo#%?Ed_7DFE#LOknqe zYknazf!z-QAyrcx53HNtvdt7Y7c*)U7m!PnNi~9LCJ}`NOwX7mGTPO%` zO&89^Jjamn*n*54qVMmRLNR}gXHNHsw_hMQk*)^Hh0|V5#T&WJNlWyQkS~F0dDQU> zK)$dVAYXc}DkN`uCTN02oUI^V0&D(6TqAspOo+1;Fz65svoZ=dhH`s!Ld8|i|od+raW$Ov@i%%Y{8i>A$oCGV&HpjplhW%Hz81kVhZmiiHPEOJ$x7r zl#6PK3KQs9Em2_trQIZqP2d8qjTBD}$5W#d66UO%6b72-*gqH7)k@?*gDT zl?t?`#SuZRGV(o}QLVehby0N10Ig|pP~=L`now)Q>5!c{*?|D9DWJzsNP*Ur;|8EL z=$(09l=hwT1ZWW?3bZCfpf%xM#1RZa6C%(WzK!$)&jGCo^)xOdhAxx(1X?5Yd9Dwp zZ9@cF;|gpZf!0W#oNiK}HKFOozbNxYco?F))14s=v?eq|*Kt5=LYJnn6=+RpUJ6@* z)`YG!X0>+{a^{Xg8fZ;uxvt}Y)`YG~VJpy@(3%vs0<8&cFi;eBjvUaM(54i&0<8&c zNntC{n$QjdKR9JXf!2g}8EeuKx;w-S|j;rST1Ny=%|rj>|_tW z1kR(KQRjIS(m-oM&l{Lhl?A0~JD@e8mke}bwgPlr(3;R2x(vQc3sOsg)`Z?UvzDHs z0<8)CO4sM{lml85`bd|#DM~E`S`+&HnYCnLBot^(=rg^@;JB@zKx;x@=nCi%Yy|~c z6Z%?LaDK|RmIAE_{m`tI3tAI0JX+mpjwsNYkfkeVjwsNYP=>CM?uY`d3AJuk%LT0o z^MBgV}fYxNhyGhWR<`NQGLZVWE)@0;iqic9adO`}cCZnw@ zZ@RJ%yNXWwsN28aS=l!en@1m2EBi8eW#0ptqe$sGNFEef;295vze18NGjQ{;yix1z zMv$`4*r!(Z9lXk3*>@cpBCqU&sqm{XkiAN+?7QAsjps<^YP{_IHXMm@poBJXk^!%g zrqX6OGJ(Z^EbvYy%k)yh*f3e$Gl30*r(0GJk@?3{1iwQmXZ7@*1$h>MS$+ghK24U;vfsZ3$RWR0|~oUO27vc}5i>7QWZY=sSzH6AvNu;eOin5-JkyX2my zuwk-l<&Teb#rYRxb)e(J`cv%o4S@^iQJFkND@cuz9Ca{u3mYSm80& zTB?z}AHfVPX&j3h5EpJ(Ouu1TtZww-8X4S)!-zbXBlp3WV#o=>po?>ZKjDooV-|ln$>QLh(BSuh%BfH`sl zU8`%!?-|*n7E^cvg{?0BjM1CVrd(pzbsk?|t!~M9 zUI<=$MB{Sej`8fI>+qL(r?ph_?)BGfAyZ!xZ;Z#JHMbKyt$3I6__4a-wroe3jkAb5 z7I{>E)}vO7vB_$6OKCo4Sz~Y18BbW282_}+DF|6Lhbh?;idlPwmYOj$GW?e*_gUi~ z(eAB5{*3XBI%AqYZ~RuBaoCKddilOZwZVn{1`2(eKcgmg+z?#uC&?2o_pc~`avz0q z{}c46%(+Gdtw^@A{h4AcDqHeGjRp;fXm)1O+LPy1SoHR%_l{;XrZu4D648H2`8NM+bfaV~MuD2>J?6dGTy zDVe>D7P7q#aFm8oX!vSwlQK2`I@{1zVoF2TQD}^D8(qgIHO*G%7#Y&srH<+%C>82T zWk#^(4JwO1#H@Lk0v9;a+OM@nWy}tW3&TC^{^K&)cX8)&89EPowsz@8PZjF0!tLZc zJRY`U5?*S)e1+hJTbE2mk2IB5=lil7rfld(&)z9-()M*R<$1aqg2jtiyll#iEPenc zraVI%S&b>XDd?H9l&)TSK$QL3qy^!}^YDcY2~Fi5x9;>L`9#k?;h7ewv%@cV#Pt2N zL?69r_KTkObs2=Q!8bqi)CE-dq-WYYIUex{lwR_PUaPQ~9N*?g#oV#o@O-b>C5LIsA^N z?$3(XuTGABWAqdM+-t4DlY7LiQ_%sWv?q zKeR`PMU?sMSLOZqI|&qlsw4a7@_yXEsm>#$|AxH3^>_4%;QqJrexb(@uOj`A`JO5oAYg$=XJ;f3>EezAB3*rFK_00v z!p~Cz+5s#*T}Olj8&CiWzhN=@nnRXo}X| z@ndm+JcG;WQQf*bKlv~Dp5SYyzGaG5mT@1sV_bRz;eX6TBNemuP>}e1bII33Jz`jY zuV|Gk6=yZl=!0%xd)8?x13Nr>&JY4TY1P)at%_`j8F_Uc@fLk8Zj;9!(VZ{Vg9p#@ z5))qs2e-~AJncMK5;J!G$}g_@iM)ObV-DBrJeV6#KS??1GWZwNT%^w6elxukM1I&( z>$msmRrg!&z(!Lz9JC0RvirE zGL*}#uJrkl?hsk#zXRuA%pFPxB=kb*lpBWBD%Z5iwNjE{yOes`rPQhgIq%!`PeZiK z&u{HRK^U2JR5j(a!;n6jp9N8V%m}ZgJ~0AjWD|Nv$#19gxmqQ^y~ejyi)JzJw!O{RQ7Om{SmaO^nGkqnWIo$7J1RChLzd*>IA{#`l?Q`i9Bo&{RaB8@4dH z@lGZ;J;~(YFPPl?A(LA^XL9=wOzy~-h7|6KGdX-Vle-5qIWiHXa3+3oiwb8g;=9?a znanxNWbUt+T=o@{%YDpC%6 z-EpVzOy9lg;~>Y`vGswhx$W|1TyxGB1IZ-MyJyJCw=3T9Ec5xUkxfT*!B$ zwlNufn8}!DnIu1CGWIJbgPmem;|nCo`F`jL9WiKuY>x+F?;i-<$aETz0pl>Mq=MJoFBeTR&xT+Yd}` z_sxRr&M=d^@|hg&!sPCAnA|gv$-Tpw+&6*A{WF+6IG@Qw%b7g9j>#iCnLKs_lgIC1 z^2CEoo_w0g(UVM`ev`?uUo$!WDU)ZvV)EQiOr8(ShJ!C;gLIxBW3r%v$-;q57L8@H zcqWtjWlXNv!sN=Em@K)U$)?DQLpm_I=qx5ftCQ8zFdeJ_(S&oD{8!DQ@dCgZ+gGTxkvglck`Oz6g>b^w!!NhXsn zWiojcNVhdRm|VlP*=_A1zFWtBc3aQgVYdx;F>~XyOg6p8Wb-#nwzRwqR<>3$**1j9 z_Dh-USi@xJ9wxgUV6yuplWTv&WY0HD_L`T&%DzG-`+G9EZakCg=P^03j>!$TFuCy< zlbhaWa_}1_H;3pkvZz~QM<%!QXL4vFlUo-txos1Z+iz!b$8${X{D8?_-!M6xH6K>) zE@g7$LMHc2WpeLACiiV*a{p~i9(b0?gC8<^=sPA4XD@)2N6usN=y)cN&1UlWIwnut z!{o`=m^}3-CPyQ*d3RB_W7SNK4`cGo3?|PlVRB*jy62((L=M0X`9-J$;feWL zJ(kmghR8Yprg5`ajKva*^Qb2#@MT&oAfXUViD_65eiXwxpdk8Mn-T@F9-8%7BT#OLp7`!XMi$ z0`6h3)0MzI^kcrL0F9lOWzaNOJy1#g`1V_mkHd=x;+8|W)Z=zB+l0CLX^)Em8jq z=;5Z*=2s=pHHj$gZat(wg)%S_w~I z2+mIz7{W6af=ki`Ua@pO39P3A>5@$0*+`O>U!@BMie)#Dpw$DeSG|NOapji#F|hOF zUCjTFa=PSGs2;=G`qwCqA0aO)b_LoS?Q36|NehOI!H@i%Ksy_-C`qjP+cjQsIW<_r zM-?UC39bSbBY+NOL6H_{VW=nSQHQIa&LP!KBui7u4`6BDtXfjE@_E(boH6v0VYO|6 zg`2bIOr^I*t9=W+y9lvze}t?^T%AkezMg%fX&Zy7SYSJmCbgA z|NFk=NH4NvJggjfi30r6;$MgglfS&xN$9-WRA(jYtejgwVrSXSEWAk3S{%Gd&BB`$ zg?o{PSUsc-=@nKt$@5X^`syW+_e+s;-e2IwrDC-o@+m2DF4+6*tWV=gIZaDq_ zujC)%4GQG=ldw zepyYL^?j*Axf&m)-f-xuC+)X|dNit$fV6yY0;w$x){G)iOS(_`DbN;y5(*?JFtQ(A zUWVG(b~T5IIULf{6qrE)G4e}lh95&bDLDQk3adY>gRfO>YyOldS>81nVidqLz9(&x z`fJ2fhUia>Rt0;9DZ1n_*Z4tJV=74A(*D6;$PCf=GP=x zM7%M^RdgMHjwWtZL|^m*AuL5{4U=G8RAk<(Sqe+yUB)=f@g_l!sL#EFx1lkc@!|XK_ zHG-GL$hCA?DApKIbe^iYgVz}7ey%ZICFGITz45f=msGLV*h;Ugd41MVE0%u>R^v4? zR7$@EZrcaXCr8b*Y?bv*lz$}UHE)ubwV$A0f@rGLjyln`f76xlChTeCx9hdY$NcxJ zNsPayv8Pb%o9>|p3ny```6R9(rJG;Tm9!*oPEBGJAaaxR>@psqSZwu|6c`MM+^pWv z9Sn%vtlm7&#t*%wUVTk5?)?ID3vjdHlM zD)fnuCc{Yhpc3-43SZ+0Y=YNyuf7dk?i)&uHXv3PfcHrXZ`HwD4DpnY`2SRV*b=L^ zL$~DxcH)vZ4ZIS?lQ!q$3DZmQ_$h?0-`{{nEFVa`bXcq$R6v@uet3N`3o=%z~AbB zPy;kDKh3}Ac@&VN)YZ?MBv_>c@^^L2BHpf49!=B=h9o8)p>HD`-mL4Z8nT&{(#a!$LE&L>VF{GKE;y-^Hvt|?oQ>Mf=kC0 zk6q@@u+A?#!zqyerm1|Ol&`w#U7uKv4%ML71UK7k;~!oIB}nUVdXl2?vp)3d@a>s8 zoS&h?k&iI$aejuUIFAQ&CsO2-r8QsBY-T3)woL|xva|VwI=kU%LqsX*%p)frEmn{% z9xYz*j3K&{v6_4e@UZdiXaBFm#ucRUKO8nLCbP{B8*e6oSxvcUGHiU6B+U*Rza>Gl z!^UFr=f4{^jv)E}k71+vzZ*6VM%iN6_!TAV3>&8r7sJMu&z*VLSWdDNR3`M7+6$ii z4}TQQrHu2VU>F6?^eFgGFN8Z)A#6%11ov%0Jrm|TZwsr&{NNWS3aMXMH`4Bcu-{~h z5vb%H5m(@P1@?EW`s^{k7!A$mNVDmt67IgROJ(pWdY=v~!S<5DyXbv7u!J|6tU9&V z5S`H3eW6m~(OpUh=V@#+iZot+oYqs|Kr1%tj-_5k*EakZeQ;5K#>;)tH5rYs5i@mV z*5&%jtkji6^TNYFCMVRNu^>497VX~pmA6Ih5{(g9O3$XWU)0N8|FZ{Ir&VKmF{Lqy zRVU~bXbK*hkB_!1=v@l%D^R4n^9mH{E?=HGmp8wjsM@q+&}*h?`Yqq^5l;8aSEKNqy0}WgqF|Sh458MA=IWe z$6@XmJna|o<5>CyochbvUeTX_0T;cX{Q^diasCCIO8W(z;$OgF67w(M6vlPKQ<8kW zq^6w2{0q380{jcuLIM5-@EC9z#(=N)sX0m9GmZhhjb|DIdKeu5O=g=N1MVe3^JBp0NYd;W@UJ9jb_|$H{`_}i!1GA{e;EUs z|IMdE>wh-}Jgmlmf1+faG2nCd7|{ILna6-7Bx`mI`1*f%*EEeX&Rx?$3Y@8H`cE%} zn^YmJPAP=cuIcq*|J|4{rL*!j-bL^1#vA{jr~V}Ftd5dl^|;3K*^nP&-$?7N-av1a zI#zqL&Hwvh*qi_1jrvEPHaM!N6Go(RHbIB7LTC30z17 zCmiKoVeI5pn>gaA!N3^;(QVB|X)thzKy-U*GSXawfl~yc8(5Y)Nu(5Tj6ig~tH6%3 zFAWCH5s1!V8JBc}frA91i+L7`&9MxHNG{?ef#`hZ=uvQ#Ky)Q@*tV^Wvjn0NFvPZv z!vvxWn#9Lx0@2HxuyLF~bSBSvt({6`%OSpS0&BSJ8VsB&5S_*RBh9KUr>?ERz~KVX z8Jq|=iI+&1+RG^-^;nD9VBmOxXdP?7-^drRhFf9Eqw^XJ95WET#8t_tBWZmry83M! zv_>O3jbn12`{0~`=ybci;+%o#6nWEN;Glu%M8_CBpw*+%NiL@kP8x{rloNRk296qt zCfPTqu~96XH4q(}%I4n$$#B>}w1zG6>VyUZrwv3WI2>tvmx1F3q6c84!N7R~(d)Sh z;39SzIB+0(86q_pIB_7li4DMug~Y;<1JSJxOEo;4IS^g#u%U@V2cip^g$r?T>OgcA zb8HWB>_C)f3;E|HtwmQ&6XM{2+a|s*)negYraLyyb)4Uh6BQshaEN;Ysu@plE09OEE`jvrqy7SeCZK+ zMY^Y1&k(1WYuonyFW|&sQ&n1=8bDr0Hpi7#HC>?Holm45rQ2YvLV}6u#E|)A4O1S@ z)nK%u)4B3WuTGQ7BN-bE3+a`y2aa{wW*dy(L)L|TX(D@_&gshQ%(KKzWcMIm*Kbo& zw0{TkRK{J#s}snnZYYXAuOL_v0frIf;MqDRd4Jstj}P(&^Kj*r#;eXK?C{lIRn9nG(Bzv*PA3!Z9j; zG0rQt&{CjwS8;XWLYdo4oV+1lP~+qtg*cnQxri$U7g0GYgAOhwzuWCTO!pC2(qN25 zc1EuTTQ`vedrTAU7I~D_u}%|}#ou6*UrPCv&(oJ@kR`5iUSqJvc%2yazod)#>1iD7 z*I?ZGG-;1#BV3FSlGoYrx`sG8?@1Rw3^f=6)z#mv z)xCxnoGMj;g|xmXub0yfR37B89PWM!{ih`r3ayq3p7A3>kQ^hUaO0kD1siqCc<*kyndsB#7|Tdy2> z1XXhxp+Vq3s1}BB6gyQMLRFmQq$;9c&~FWA-gammeRw8)mi#>}!pf!YzkMQmzk%a! z@dHcHaku*ooOg@gX#(fnMn5KPoN$|ajVaIcj($a)cfr|cUQEAyzlTx8aL{e;wkXWt zpxfNtQLIqKLASX#Mmx-s2i@l0V#--27h zc5$?AX%5@P(YBoowu_@}J9*eHjOPmxx={(aI|gie$E??w#|LC!NA$JWkGI$b}iv>+p>_(!RfYT89E2Y+m>bO z9Gq`kmZfuWz-?Jr=ir3fGWq)go0>F^xGig?>)?#rver5WhuoHB>l~bNTgJVR>WXm8 zZCM*#2j|?D<>(w7bX&%)LdN1C4!Z4<8LgNj54tUn)MKk8mmAKw&HcQ=z#+HgZP^l5 z!jsoH<+i*)=ir#z@$z0Sc=x8-u=VyA_(Zp({x9UOLB z9@jZI?Y6u`=is>8@(wx&=iQbkbPf)@E$`@XBG`aHnZt><M zhy8dmVIYd*Yb&%DK*h)TwH3=)pPzEvttcUmt*wwRI*u_l*u@F86>=P#8c`|Wh}sJI z3dxU0WfW)BR>YQ(LhE5A+DT;N+U}i*sr# zwy-uH!|ELb2h~>WWJOK@9*{Ops;%G!uB@nj4>+o}VxyiU&Z@20+QcjltF740Y+W0t z)mF^ru`s7Ll=f86Sa>v%dbmvwBN_`=%;K@It3j{RGzhMkgN{0)vvEdk#bxO3UAFQS zhtyWg=b@AnMaghVZN=q0`fVb^F|`#7&`&qDiF0Zz`nm;-$mBGgyd^5mO=YVmIZmpr z=$|U1C^)LNqAHcGqTsCBiUC|F7&}F9p(r@4w&J`dY@AkGF))>_EaAA?iu1V%bA#Z_ z;#O3u<7z7puoHaYfnKFLuD0@aSHdn-s^e-a?{_6KjykTk@+ns$Y2rXwH2crHf0|t)>aI4II2`|WNpO=w(Vw-+f{>sGixj4K-RIXiUx<) zR@9`$vwgy;wG|Uwe>t)(!?Cp$wXRIh3(l>r*vl@abpbsWa6|7yq`rzSe(Zs2FmQ5h z#U%cPpaO}5qiZYVCoZswgR^TZrgHtRfR*~I5g$8psB=RpUCaqyJBV5ehi-w^8sknP z^->Kd*H+ZIex>Qs$QG$iV+9_Dai-W#gMnjfD=u*(x1i5>DG7y%QIGLlgHaFNOI zrR(;EE{b!Pfun0HHX)M@2F|XnxQ6q{O|%bvAtN>pudR^Z55PvZjniu@wsDEUN#fx6 z+KLrT;^O?;iX{$vq1+k6n__s!3vX=UC8YeVl)r%117(Z4-!{I zd(zl*+lR#Jtyp=8>p9nCg?z*nlGV>vJS8`kLC0Ulh;zmq$!GWeT&;NGeq$j_Y3tC8GpO!_7YVEeZdjo(!6O z29Rk{9RATGGNFIb+-CHLZh-#UDYRyJ7zaDjK*k&nqa__-Wdy90R3kW&4T=uell#7b zKcI-~6SxsZN8Ea@G;$9jO?kIO-sRs4R_T)0>;hYQFWu{+P6H5k8SjL@)I(*-Hp*TY zPOmmpNS@^nAp#DyWa;BDCp!F@G=0lxC>Zc;?7W!hx#Y6wlK;9_z=TyJ*ha;s8gN~ zo#QsA^hM?7Gt$ks;AW{0Jv;QC{WUuecSPBntvsR|H5|_g{L;xIufZN6PX4D*>9(5^ z*n@~KQc3z;e?`xkll;Q-nkhV&aYEdn0Vq?lm|osImz7WhB@E=>8e-(H=?5?sjnF80 zYbwG^(H45%@)7M{q#v<=rY4)ova|dxe;}BeKzaOaYNx;I;1y>h(7t>xy~2D-8y*7{ zxX*1tT}M8A&&Msj^7<z9!R8x0g8cdLp;hsdudji;U< zB;E3}{DJo<%@*zAh&n6RD>(5n^hK~Kirl3uJ>nCB1Tog5tLZ(Hy0MF2qds;0D|Cx4 z)Mz|JUc2|6MnGH}>))iV9&&HvZ|PmfSpOQ`_qm9opQdiY*Z^xz@7QM@@h_y02gasV zRAPM|q}w9;dSGnk+h5b|zb+voTaYN>IfwduN;&Hr>iZp&bHVN#s`6wL$vV`R$*seg z+*Zfr_PI>%ypqXX4NMMS%jE8ZOzwGr$-PIJ-1jpk_rJm9!4H`{^hYKS{}+=-{>kJq zi}KMo>+#l1o+xDUWGR!QJ(xV*pUJTyOpcFb@@yTG=hje;`(`~qm+xM<5~S4#RA1j# zBOCZ`)E!JlKgVRu$4rv{U^2E9t2e#Yedx+r89u3<8G8^dgH4>K9@6qAv!G8y$DlhJ==GUg{H$*g?X z9NUh`xC$oY2QaA_!(_s2Cbi3%Ox(g`(v3_eKLk>|=6NR9aOoDW{A={^yun_c4>}e`0bVyAZ~1C}(ox5GFTW!sOu9Om5!Cr13!}x13~h=yyzR{f^0P znK4+oy_CrvgP7bog~?q@nH=8D!I$XhZ)Zxld5$=|7HFj9mmhYB#VX~qhla(WxtXjb2strt5A7pa%Q%oA(V6x^@ zCf9h1VRLOElXbnAte?PSLp_s?>zHh6WU~1&CR={aWb3b)Z2OAI_COrQc9b&NIhe_= z*-Un?WpeFpO!hp=WbX+k`(9_V|F=x8`;y6lpP1Z`T>_gomNU7jipjxoOm3dWjbP^(Ur-SgPANzGFdu}$+9I(mak>9VlR`G zN0_X7h{;tiGg#T%Z2g?cwg5d}`<8BxG1<|Z$?maCuDz7WzQrJ2&e_DI*LEhoZzCf518Jgvo7NuM zSYaA8aHY*PqP?i9#?64E^mz4i2p2yJJBDEhASb*Ea>9G38*kv(B)y(SM812CLH=C2 z=3p(JNl!Woi}NIF_CGx0ESr_{_U9fkSlwV-Vy%5c9%0nP9??sJguU>Nby?>_?7dWD z%%yPk0=isagA`Q5x9amKPwY27ult5q? zrxyHtKun|HAgwBTj1&j+J0eztJ%R#lq8*^2mQnD~ea&hQu}uqQyF0XFKPS5v!Q_)L zSv`Q5LocGs%k;f>7;9)L=C_j(Imypzw1dXEgAJBCE@pz zoiX1#NeradA8W0aL>3Kj{jErAY$v)Hg>=iAUP6JA`4){aEAVzwa(^BUS3z$x4zE;! z?kh=Q+{g3|5$GXvWMHiMKni>J=7SY2ZmB{OhDfj7-l?548dk& zUr|t^*3<&ECWeNCS<{Txu}petz^rLz?nHn4%rrAC5FZn$J~e?Fn?M{)p!(DVY77O82~^*<7;It!)wer_J`NM8z8hm(iTe(MY63Ne z?>m@4_1zIWOhQbc`i_`#F-i=tQkX{#=f&_kg?ZF)ehjZvm`4q_jp4Nl^Qhs17+$R~ zj~XtD;q?mhsNv!mUa>Hb8ji>CnuU4Pa0%PRJZdNvw2eoq?Cn{2S^0 zDgPE+@IVuj!JLd5PGZSJ>r7VS3z$+Vi4_mo<#;R2e-}|dq>Gr0`^oqUl*H19>~5*@ ze6$pi#L9>4%2bg^V&Ow}_f)PO0qY*JJMnLZJ>ZM9g=G(smMlWD`M8KARy|~&lghPi zVbMc&?^KaUV$DN#ADDD=BO{cnH4km3yXC;q*@1Gk=Aq3ncAYN}izJpjWLL3G*R^uB z#^fobzvM1MtYPfoltI%VinFP=z-73tdrTk z$6GNwt*nwB-RTP~7jC$;#}&$lmR-bIe*Zke#cXT!SWR5Kd(#HQ9+y)X9Z=gA0WqbB z`uc(k@sget7kEX%MYqzMc0N@3Lf=z|5c+Z;`7R|gQNLLkh!>l4?GSlCOa=LSuXf#xSl9u22r) z7neUAwk9L7YUHli@4qNsz$z@mtvgvP*{h@y@TBY!1l2umW0x*%-#jaU&;)CsQJ{$oKzQJKcT zdWfP@hmnuZJ|cMtX|lNlIana|b=e?HivM z_-~4UMftut##F4yPh#0bd?|a}mOj1Ycc4q1nB1O7HNFo_E<>mrUHm=iVtz^wG`}y2 zRTc58)1xJ^s3N|M*+7Ef=ae#84@0n##OjLp%GAjDdq^S%HqsSK=6zQf)6h*~#e5Pg zF5;`2u__}avEU-!z;d{6Cz!-~i?|%-Ia#w~V7WznU1|(lgw+=D4P5dl1d+sIi}((B zpU-)6{1!>9wTN$FU1Tg@M!-^w_)gb25*JCVw20R;7izL=NMfNye4~~c)>*{2rklhv zi}-HlYPwiu5ueR{Cg=NI`rIWZe@NGAxSPZpi}>7I)upXK&?<0MvE#OGjqrwNl- zXc6bB1($2Piggz8`54JH5n-7{{Bn$Gn~1Q=BEA5Fxh5hkvWWL}3l@10NvyGmpPS0H z$2(YJ5$~TW5=pGEh*za@?Fd+45g)*1j%J*Xi%4R9Mf|*UE|yos2c~juGgw^_Kc72% zZUJ1_xE1AUbw$Ymc7QKv3Zh)Ct|+>Riv zi4_!ap7P579epPi)qkX`A7AB?SU?fKn2qx@n?q)MQkop1Yc(rj`9!?V^&m|%iPaPF zX)Na<06Wh{l2|+uzr>At85xzmpG;&S62T}biKP?qOI;)T(ll>?CQ57y7EZ)BA!|vj zn}}b-S>?vJhZ{1MO~h9_+&YoOs)_hEE+cMHNi3R(uW(fCJ`QUp;!7NEorvWWQNK$M z>BNxf*qN2Y#;n9R){vbVwqzw_VKbvEwqzx)&F7vKr6H2oi=(;q z31TZ&Vq0q3b{SzOR$_aqFmV_c{&&SuM+&(TE2&Jd@r1nnP{BT{#3ioi z0HRjkOjo~*O53aw)9}I|AFf@o%_=e7zQH!D#1#9ni(OWUiH<2s_Mar3QusG5$OarQFW37ZppwNs!qjRm6CxiRGs2H zppXpgpz73-ZLr^W{vYl4={o#%SjyskV+9D%@%w?@0B_%4)wbq*Oca zNcGF;!&38jMXI0P-64sZ#~V`p{NfIQK!3qEd$x_9$9qz3W2EWtgSkdcd>HQTd+?T2 z+gM$?J$Ol~ZCp@P-jQmXBt1}9F|SCqO_3BdfH$Ptrb&LqeVqcgHEnrjGZ3yE7tyCa zNT}L*L8@)KltT*xi6s#Rh8Lvz|3=z{j+)2&QEfA&N$99~ydKrIxikbFH88v$)qfey zWi>_2Jl>9K+lsa{Ej@Gsyd2fGb$43cjcVJbP{v^P;nk=%J)?-OTYMi43Ux@~b-t{hu3b|=pVQ7M#kn`^M!|UR+M)#pP69Tu$Z1Q%fyW;9djyj_rDqQ#MkPM`(NxzlQpe9m>L^C)V5B6E_Sqe0 zf>%r^%?3_8{ubYtKR#t&dp5sszpHl>VD;FYPbctEoIMf6JyKbjFF%HTaJTIK%vT5Y zmw1#9*%8wRGbIx zX)H*s4scnIu|t>`qpXIZ3=T!Ges2cTXzQxgR+u(o53s7^K;K7L4kzLY zk2TPtk}OZnB9J5@ZLN+RDxm7J5P@H7gwxA-gn-(w5IwgOKqH;%;}FB4ZKX83(N3Lw zu~71>dXCY8#~S1G;>XA2fxQa#Y$f5UDkd8~)>xuWyQ-0-amn1}WJYWL4$Ipe!I}AMjmu*+n!i2+I8F9zO%@*OGxv-nv8Tq( ze%nx&Jd7j`jU;g>lTa;*(O=`YB{3!z=g(NY84f=aTKJQ`v_pO_n=C((C z4w9d%Pn4f)elI`Qu9TnaSIf^I?vkGy*2>R~Psz`!SLElW_vB~wm-2J-Px5oChyCW3 z^lg>$^QT7nxxK&q+%a5!{xV5^?wln*cWoy>_v|J=Yxb9)`xeX3{U`FrpL4eSYZI70p?S3ae3vQ5~?eCYL9bS>29ee zW#@MJ*<~~NS-7kGEILAdc3mbvyIn0mzqn6+c7F;#CQq;RsqAUq>!3L-o?h!Kr`KAl zC%#Ft>PgZh)ssJw(3EfGXWCElvsqJ$Br^uc&&-+fv-v{#+2SzynYC1YW?wHqbMBO% zE!WG>R-fYsCy>XZ*YSje@du;T$-!--6>%%}MVyf6r$Ia+aa;gu;|YlsVSpzjt`7oA z^=Bs=a1I<-wd)fS1FwN}jmP?5Rm2P;Reu}-4M_*x34h1Ea0cfegL@A;t#KRp>3}Qz zyap)z;735@$4B2KNcgD@1LUVQ2t@fwsUipPQzH z7zBUkPCyM6ADwpn<&zFhDxF6VB|bXC=yY&K?clUIh_a-E)7)@v+h)oA>k(ERoMnd} zgwY*4Tc8gC>OVo$h)3XdaF!iG(&5@>U5q;X&lu3Lr2-%+ZmePm(aalf8z~&ym(wp`W#tExX2*&hC&>Bsg`tU+0E2Ty0q+OElHP_-K;I?(z2Ura9Fjp z>>4{so$?5eFEM{8Fhr-p)I&#*JABRbYY-(XbY~GC9I1>v>HxZaQOsD zv&dTS&=y=VuShRU_YQ5r6+09$IwjhI%O`eEDYOMw>|LbS#iuQ}e2PGeEjFCC;Id4& zLP&2IPFryKOo^a#q%F8dhDcqb(${DUu5!dnTX4=9LsM`{n_YXxDrk1)q=9G^G`q6b z_JrAWEX}Spn{jp-PP1#x=94iE_#_oawQIBMaGG6fwh;IZoG3at_Y9}mwPvP34-_c9 z!)bP{*-}_OS)gaY9V!uMcCDE!s7nQP6;Tq4X4jh8OxzdLaGG6f=0pHAyVlH-l1tr* zk6qsXh-r;rX2WTAt=UR?K^z*f^gq?XDYBy+;c-4|St%IVuri9DAFhn*)Tb*gHTZ6& z9{Cce;4%BdW9gw}@3JRO`rGpXF`O%LI$isnrFRg#7h|}K;83!eS6X@!vGk-TS&|~u z_y^;5nUQ!FImP9Cp4|3IU~@&n!PSKX6abaz{Z~Vs3A?=}_k=u!Z{r$C%!(@c_F6;j z4P&>FA`8jsyg~(|laVE($;Ak6fzy*lMuHb1xHn9yMp}ZeBeH$Wu&Xp zj{-Fw;dB)|GvQI0ML;E|gPSXP?V_h-_ZWhEVb~h-h4Wv@3`4r5)-Yt21S;qjMByO$wWD; zQ5uYpHGSDRzNxz=E8J z17)G<@If?m0Bat$nhfW6Kv+j&gHL;rUhsqsU5iD#5kCV^=T*EZ#wfc4UUx}>>`BNE zt1Pa&Ndnzb#dUW}FlluNvbWW_5gz+rZmDT&iah!|gU1h$$_S7f8OPdCg~P975wIq~ zv2|+BNub!C6g?elEEeuADPnsNqT*U5OIQaZXdMB^I{^--aq~i3PvaOr`Uwk0#*MPn zbs@Y!ARY8(Vr$dpvXny08uc%r_7RHz(1JQ>U??*HeP!=&fo%LegPSAx&_@XN6YSv# z?uNZfql1iQRw4LjVn?u;*=KRbk1ynhcP5jN4w^a!>F`OR%W4lh0iP6GUp(=kJyW%z zr+_MWLK@|7`xNSOg+m6*R)>!AR>Io^jmg^2yB=O@H|9!PYd6-P0P*gF^A=>XHQ3g@ zt(?1ic6vWBQN{vl5-J1cjB;)c+Svk56ZGKbpq(ir7xgIt0dR9?k)ajpXrJ0ce}>ytw)bep|g2DM=qlw(1AEl>}7sgazRavFTh3m~{Y{*#_1N)43Hv zn|zs>*WiWfs2`i+%=Eut$UQRvy61!*R;E0$K*F(=?F17~Fv$eOEC#`iaFV(h-W~9# z1fZKH&Wd$LkWfdFcw|DQKZL_tac3lTH}jaXYC_{cTwVw_=(me6v((cM77IR-;_~9J z(M%vWnuDv{lri=sIL>r9!CC$oyz+$ga|pI&jlTC|+{8!kW~p%)##obDQ)>*B5UF=9 z^kkzilkna|1#X8OOQY{Tpigd#;VaWbzjCmcQlG+vYV;S>*+5CJXg`#ct8tD%tN;NBK*M=ya^%Ez$UK@lYoqYL$_5tW}*z68r5M=?Y0oS!8mf#yW<|MHy>Y zw@n@POp9ToYp+?vvyPKX&{j$4T1F3&XXbhFpb^?|US(M+-q^!lDJl7ap-_g4(sijS(H&7S6 z1-j#mm?#-YN1kx_UjYJN#`!AvR9QddY*$0uQbze$EbHuQre4mn+0`rPJpv{kP0?cs z8sF~8bSrv%TLEw{5{H4o5>T-&z~U@x<-I$Dri@@iCsW3ZiW4^Yu)0Q&gNZ~`fBQHt z@{@^)j8i=w3rb;RA{nXv_z6svWJZW{n=z^2v8Tj)J^}PRz*st?YZv%>rjWos@Zi9V zetP9VbQ~krvLeFAZgz_#yCc$Bf~@n=$@tV^^WwkZ85hPXc>Zst1EZ|wXWzi1>c58k zahwKNlp#lY!);_8Hi@{eW!G$AxPdjPnz-TNwh4eeyFr{w;Zsc<%CYo5NT5Lgz3WfM z?Gne;DXT?5*y;!@0K##1Eymq@&|6BDoYbbi#?sClX;?D;mhXzM&_ewE28RNOGQh6z_0Lpz+mh45iRonQ6|Xoin;`a%Q?&4{s1Ip(=5`f8(@r~f2{5FstMrZ@LA?@VPPk1;HT^~ zIJSsqJMBSV&EWH})nM4KVJZBRwx1(hHt?#$sQ>fNwM+fDWhk zn7n_&pG>+JqV&j8dfZFgkk%}v2OGoe9FV2-_!cEIhjwHsJp?{%XqM7L{KH3PDLsT{#MmsQ z$CHdZa$=U!Ba8YoM@`LAdh{WD{EV`cIXX+}fq598DOXua5B$g5i|j0=hrl5{vXmZD z*a_QYDLtfs6BlGDJ^C`jq@A*q9_VAroV+MY>2WXpQ+Cf%dI(dH9_5!IXD*AaZqlO% zQ}4lA2&9KczmRK{(t8%+j0g|=oh*fih4k%rRhGho>D%wwSqcvp+J^A(;vlG~BuaU7 zd-MdrL-S*tY2lF`f&hhwg?9vwfIlO`!}YSF+X3K0cvN$$%-zV4@^;2gPgI%8i12XI zSqhIYk-U>pg$8r7c9z29LJ&HBTsjw1aUeXZuZBmGD~OF6t;1EbS_K0O6{!;1_EgTw zp{2<>vlj(P%wmT$YTpBi_c5IGw{Upp!8+2YlPeGK)bq*%#{&GSo>v}%fUSDcSKEpa z=C#A=$-KM~^s&}!ClSH%CmHj0Lp-OTCPSipzY=aBQTm*RZRkh4NtFJ~P>)9>pr26C z@hq}o?E;`9>Z1qY#HC2^Bv>To0KZDGNI?Ku9fh5I ze7yeBB7gJ$XsIV6{OwI`9xEqh40f!Vc4RsM0h zumwwoJyWm)5&SDw()L`M)+_HuP-)(*cSH3tAQq;mE zQAU9JK8%82`>15Kwd@aO9315iMrrEVu07||4IcY1cFm92MYRVBuvZDL(@4~Ygq3%L zXIbj~z?xJAMBV!#!ZTQ@s>Z{7Y0s1NYU=6NiPl%rzm-wn#^0@thNl8?((o+mgipge zp$9MM`Z>sdf!a8_hsx*E&@c4N4LwJOog%BH^P-0;$Y0t*Q1)4(if@fG5tKgxz zU!KMrFon3Y*uG8po;lmJ36^hiH(@8(MuTAH892R2_<@E_VtW#&=R zOkJ$v6#el92(?72e{Y6aL}`vDX4J%>7Wi6GiJ#St2xv_dznU0wp`(kBsVk2%{w8jn zJ&;&OI@V#cr1F|ZHqkQZ$_zN)x{K4<3KLAb48NIk8s#G?ozU7GIoq6!HcMF z{2KT~jG{*41w}`BoR!8wYcGQQ&ijh6&Z*9y{jGRV) zTT7N=MCkjqW+_JI5#E1*EYQfYHK0RuXzd@Gr5IUBc>BmK#RwNx){wDTiV=YiotUK< zxs&kWQ?nE!0v|aeOEJ=yaYxOP1<&QA89g^kF~WtHHD*DUVnq0vuv3;|L}>7;9*Pm| z-#be&BK%A~FiSC_{fEk$Xg$+`81b~$nCgwNrxnT6K=^$!lVA*$8qY8bEa3#RO)#j+ zxShdaWS4tdi%jhcNQ9RA5t=r|O^tG9lRBF;WKyRmzLm_W>_z}7Wt;~*txtMd#q2?J zii=23Yr(0%!Cyi7lf;&wO1%cBocQ$TaCjHlIn=0RB~nS;$awk|WR_vG47yuOSG8GM z$9w^b4=UQQSx#qbWU&g;NK;pzi69M|MvRfGZ%0sXF|b{#pGELNG>j2vFm_Zpmf|%( z!T?rAb`n^UsKiS8qzY49faQd1s2127SVyN}B`P<6wFSrmjI z1%)ou_V6i(m;4P`!Wgb>aOmYsU{r;K(N8EtufoQWk=O%3ecVOwi7@PnDJyX|ya|y; zIwH165|R9rhaH@7yDJIdqEc)nnMQ4O!Ii~A?TkX*87b7Nf1^-*mBGJJs6+op3pL}a zVxcO}x6}cDE4I|yf1^-*VZ*;ssP*XXM!Z`~Nm#d3eB+k#{*{)x4sB+uuOo%p1BGgO zs#vHE|3#trvJ1mr$~0uckp3fKwNY1nhb2gKqm{6u`x+OiD(I>10cNAM=>mKerb5}%78FV-39 z^$b3Q;45Dst`5GB;9JFD3On!nVTRFI2NC44cK{iePKGUs9D|^cISgW0X+albC@^O$ z7#`3BPecm!DGJr}bg>B-6Cy@G;n#g# zs0=$D;9gFn#TZoX*>GYj;G|TXkZ=!O?>?wYF{Ev^0PPS~`-9-{z@Ot#a+^W+tcQ`9 zCEW1bqhWCcXk#@kyf{xG;$71^9|rkX(XfDo*u* zPy7Y_3;x;Yro(8SIFAvN)RmuNtiZaMU@e+9Azr~zsjm=DbB`_~Z|_lV!C$nwoS;!ozXd~=WZQ?*&Xxkvoz z#w_35BmPWFmT&Gk2i0$7TeEy~kHGQfp44&x(-*@Dj%g??WYI{?*A^S;^JSLme5Tlq zzTrr&fl5mAmC+EKv6zB@y(Jyx%)n1@o*<^%J`RXHVYh1rL&j<&A>C)S(I2@c_Ttc9 zZM4A8bC71&-%%O>8UldTRRdE&1Ymc)L{)RO(IcR6y3W~502u%_J}R~CbRgFliGW&l zNpD(X3;`hJ!muJIGww5=1K-ySfOXq|OB+NB74$XBBDICX|7*Zsr1A@wq)nfbWWnya_ z>$qXj_&t=z_(_hu&{*;l{HefLlBThQNEl1fT+)lb$xd@gul?~fjU^{RTEbY8rm;l) zc|T2Ki5O1$SEOky5&wW(n#Ph#NZ($Yrm;l)0~^ycmQY!Ru_R4niT3x&&{%Q};WU zO`66MDd5BfY3?szicm0?q-iXHNLMhHq-iX9kCi-S_cVJ5*qLWPsgw~S2@Qd!5bG%{LTS00x@aA1GuHy9hEct! zI|-w?r%aMO`(f0v5o#s_y;%mMqLH;(vm8Md!)TD;ZSZz{jbPItMDEoSjy$!oPqB=s zC$K^s@~Py|U7a?~u=^Vu@wE#Ei7|zIkrCA;j7=e9^+Ut7fi$Ky^ty&A^6|;Z5R@RE z#2p2cS?zW`++cgb#+iv#&lM+|xdnj)>&A*cXb28%sVAJhC>2OM0ApR{;4B7?a;yWJqfu~ZO{h+Gtb0i%@lSQEIiS)}u5qm9UI?sb z{8bxEH%)b`W0e=Oyw9;-%p;0|C^ptQRtw@6xx}X)gqL-WRmX(;lIju1sw$z1sn~cR z0-+Y40)HY9Y956ekq~Mgg_`)AY>z@s`{N#k+B#G}gqla8CjPwdQK<140W82Cg_`&W z#2^>PrqfnE=PT0nyP?G{qT;Nft;YfmlQ1d9%HqbwL zkw>BSA^lT!_bAkaDG0Un)5v*KLM_A8GpvO`sKx0Qa=izVjVF*^LWG+0jz^(3902EC znBpMRn1S=2?NO+))DBF*aSA2Bj3^bSn<)sS@<6D?_5e5#YVm#HPjKOri+LWU!Lb0u zDAdk?Cz#yh6jMEZPf`(TZrYmA8;WGMSRFcVY>^Vz_8J!&%qi&*zA%Wmv+`@^*b-) z^^05!v^NFO?Jg06?QAwice=)L!$!z+TZ5cdEn^5{=T;#&idY?NdL`JE986wv`yeQi zY*4Qlf*&F%XMHqUWiUtg9B~@E0*sAB-^g_LYB;F@j z+!Z|uq*jW0EQAz1Uv2~`pb8!bOiDU^Lr(!RB7i7J5&eWS$`=DriXKvxpT8PZWe-+m zu6{#M+)82#Ca&CZfDfocgEbIdhtX4bjK-GwOMsp!uws;Z09(j5?z?f6d~^NFg(#|l z>%6$j3N9lTp=mhY7l9uA;Ur`Um9RZ7p_p94Q6862;&*M2ODOTj;vSb!;*Y01E}_Jq z@I5Y}#P3yjTtbOIne(`W5`U`J;}S~z=|+!BDDh`nJT9TwJrdbgk4q?lL${8vBa57s z8u%hB?|350-UqOZ;;ZZv_!?CcrA8CuH*ggakI}1(+Q8X8>5`y~9gc6gfrwx-oF-Gr z23~VWXDDLI7)?b-k<)d;S~TU0%qudAUL*s06m7tsq{de-c+Jo|>@SilqAk4!da*hf zWWgwUkv#M^m-(`*`AQO4gi^9TdX=2!>X4LdYQD^zb2lO=!&L{rL{Ns`Yb-{t0S5|f zSRM==oQR-|#@AV<+C(~c5i^VKE5K+rWrkW0eH%|WZRBN&pCqScBl7kZt4&FpGa*}adQ848U z)+qr-m(*#IA`neEgZYsnsMegpdhK^)z&rCXYK-QZ!nlmHaB)^|QEcw6nq&wph6ZJ; zgKvNvC`aRs2njpeTUH;46m(scb%#5Q$@fLQ*$Q#Zg9jjMiqfb95IbiMG$|J z9ixh%{qY!81Z>AC95IbiMG$}9k5NTHqhc*r5u=JA{sFldRfKm5Z?BC}MG*hM#u!zE zj|d;s5~GTs{e9w85nzr{P!KwdI8_7*QALPRMffLiLt0~05q_kz6QhbC1)R7bMipTpBTU*UMit>>`X?`nQAPNc{wcf1 zs3HhcP!T+?!Koscvu$nn2rhahnR=475M0JH=@)XU2~XK`A~DKjjzFFDinaj!{MEi#%||w9sNWVj2?_0fabWD!q%T@QA6u0Uk*X zcNetw9^N=%y$S|JCY4Ebr<^`ppBFPb0H{D_@`PiRuVZxM>;)c`v?+Mak=w86omKf5 z>hP2INwlXOibR@U+;|S*$||5Yl;aqyq*3|i8~RX=8y^5{^#-&TwG!9s&EV}I{x#-6 zH^~gEN4}+x&bTQKzub4oKYZM3x954J97RaaE=Uv?at(qkhJ@tt7)f6z_Sgk@6wW-; zq;eOWhm)~aOX(lau=iwsLT#wJI;3FIYv$oAXK$$+OxSQZ&SW^j3A6g}gjoZP%gl}^ z%o=E14g$8S!yAs2c_18Nf=9m+IRzmD+4I(oa0A&h2zK9NU+N}%KqZezJie3Bu)6@T zS|EKynX|8AFoU32eI>|^TQT~^VDrFhcYxfN`+6>;y0Im2<%!ddY@S7Eg2`y-PU1qd zFBXm}wF*x9Rzh`$%B+Q-);#M_Bl{%$a^$OwP+H6El~G*2d3g2u7Li*!Ds^F5qG4LlBi3Ondw;nQ!!FWV)dbu~$@ zQeVT#kS-fXUcq~p{WADjJ7sYmc5u=ROHL|HGFF$HN-+=B4`ExKhRP0m#8X(RFM0K6 z>MR_d+e1nk3B7l(?K6v!n7xQe;<356E04n~F=pFA2)HCsvEcY2`$MpjNt_11Ct}L> zk`z;y0ANE*$wg(oPpcAWSCzSiq#~xwbdq9xVr?CZ+FH4x zTW!fM!_Z&{eF9=`a$_S#C5*y@ht~Nvs-mv2R5^Omj~@fzp7$g=y@;n{Levt3bXjPJmKxEiUNlP$VMJj$@@{Z zQ*}GDir)pdn$;U@%I0{n*GaI3t5_3N#Hsk3aOG4}j@PKnT2`^3gh=H$XSo@6B@L+L zRVmxmndlK5(<68YYG3vum_)D_A=@psTE4nCe5PHE*LS>L96lS+Nahek2^8J`+@+$T ziwzMfy8pRLH4PQ<|JYqB^ksR%nG@%^@WpP-T3tAeCO)GJ>lIbCKb-3RaOBDH-f_&Q zs+gVxpg78cm{et40{5)J_JHe%Dp^C(=sF~;;j0M(FZaz{`9#>p`$T+clPj0tYK0d` z!D9*x8(or&gzLy~__(RWrg)F=t^N*LTYY?Uag6WsJ4-$HMsbWYFLUhHB! z;{kUC!FkG<5pHs+u<9Pby4CcsaK@a5S%&)vrpMVWUWrWz&Kah6H-d>{5#-vy%&uqf zas;o&Ffuc+K;T9(9C_0Oz5owVq=GjENy4JQIn*hWL^*$>?^62c1cxyW!t@(zOCwOY z)86b>IFj-S8RrYX4C{D6w8q2}|Auu@5H`Bx*qC)b!uBuW$m2+9V~pgAa~8p|li>vK znu+}m{saLYaUQAE_R#ok^+klko3FIg_Yn@i`HzVG&vjMoCH(KXuF8JTCme1kKw@bz zb#~x0x-JNOX4e()Rbkbus{ahRa0fg&+Ku?+D2V0hNlhn~fs(4yyb7l*EMo%6%h4Pk z$bF&oVgS>>A-;y;8j|+ffPG)r{SZ-&T8?zrC0VU(PPinlI6(;p1il`TcVhQ~g#@C!4Ai z^=qVKt37WkioYqBTIxouO*gr~4w>giTnuXwB3pT|B#OMX7lUO8%FA>lsDhm{XFuRv zDvq&5aP+k`^#RIZt96mg>!3W&dZ(DVzwkfG3H;^TBk;UYdxhZHX2<8(;jB0f)t{QDR2(fj2IM-r5n zK(bL%QN|fv)ElcPVIs;SM_hc;CY493b8%wymSE2e^vIZ7)FWeVL5~c)+!2q7h}u|> zLYNyaYfk+Ec{9;w51sSD-UqZNut;zZmgYyxTeFf`c2FD>N<{s+|1ofHN?;gd*fg@Xy&JsYwS4y1+ zKXpKsD{FOBs$wo< z)lpfCxr|#!A)zVisH|y8SWhJ;rj@k@GR!BGLHycWtekl^7L>JEIn!lWD{HZGCf@W2 zs3Zd+@6GCJg;0o91oE-8)>xBf7ppDzUQlEIWtFMkAhlH!Hci9z>UkGhYS9Np5ww^h zNV8uoz`590H&TO80ILl4*Lrw(9QWK|NT(7OU%AMU!p6G18o}s#>IbZ6h2E6{UkMAD zk!Ac?C&=a9wHcDf79uEb;nl%25EK)?4ql63PtX}U_zZ%g9qOd&J_Z(>CPB)-M(}Iy zB5UG%5u6KyUl2@uVyNFix!1w?0#@oUz{aCSjCS$@*-hhzHyjSWSwe18+BT8ad;ivB z_u_gkz$RWC`{`)V?}$K#^!s`$xrh;hmj^w7s~?L=d7WdeL@gCl{uFjwSn_^Pf##Gr|>>)495kJm~f}a>{msYxPBqi+IXJNb;GZ{s{6+^m$gnNiyKQoI8u40bi zV{DPoTr%@$?)-+T!G#S@EJ^O-FP?%4v)qwc&gqt=gmsp4Bumyt_!x78ELky;EUSBg zIU1epp@bNYvcL9GvFvMD_J8q$AwOPh*n1$&;DVv} z!)sd`ZRqXI(*2KJF#Iu6s6U`k=X_i&)bsyFq4+iBf1^+<{znUS!(GLe+7?sFv`>nK zV!tSif^hUqM`P$-x;1>t=2w#qZx?tCM|z&e<|?SVM6j!x={UiB!jx9?9#16+^t(Bw zFIF% zuXjIwRXV&isYexe5(?dqto}^dK4haMNf0SpQuZNaoF&%*<;{i@K1RCa0%h_UAOd@K z>IL|9`Lt+hzNc8eCFqIsF&4uelaY%y(P%#_S|~HkHbnV((ZX+B|0|;9xc_O*s3S}>k^zcvC6l-A|uF$TESPM^vYO|^l-1(!@Z4rc>kG=o* zTKNmsM5bFSXNs+yLEGq7#;-hvU)s_?0UEZn-L0jU-&d@O56`pI^IsKfV%4I5y`@*O zrR9Ep(9+hwD$DL+`Q-9GD19uJnL?CM zG6(0J-e+-b!i|KCSo>J`l}Cuy36l)-32Uq`i=0>lNJQyNFj_*yP~t6k)8r(4@ZNsp|Bjya(Ij6rNj>7XO;q;#4< z=pF$K&pa5hV;QW(&CjV&5!+{KNrWzU9tH?na6cpb&AAB85tDB`A-#0`*`n zA~Z>!l39=^nTbAcDyIm`)B5OS#sXXppQiP}$y5yh+zYpJX)OXXeM!_Bv{&w^&q)R%%< z8c7FvJwU%Llua1Jb(=q6} z=fTlU7`*8;vyeDuW$ptf%eDxP%}7g_YzhAiIGb!;)_9?HgMh7)eA}A2u*l-$h#z4w z!~A-Xp$d#NNa3*YRjbTjDNN?!ro|!W;9CekbZh7#i1eRxgs8gz74w%lBWeo%|MH#e zv7ec^w#ZUOeTbH>;#KVMae3u-AfQ-Bz;%Q^Vo8P;#a^4F0>@V z3oRb!0_MdFEgt8BAP`6kYaug8VQy6^W}T8CGf`=-+9=TM&`6u%GA(8UndbCBf#&1_ zlWwLLAhAX`**9P~#Pf3k+f|ONKdUAi$Z!d7WlflsR zW4lt^N-%7Vj313af?tv!X*PJ7M_?!cBW9!W?ns;3k8A(`#D!#m_l|p8!1ylymXwzd z{e67zTWs+Oyl;hfRTwv)^Zp*jZLRgrs1D+`HF_6?{(ddqVL1OY0gRaaTfI|5|A01c z2wuw~@b-S*rE@IpAK2fU8o~z+@NNm=9qpcp7m*14;DKIw=pQo38yM1ec6b+u^g{=G z6GQm0A>OJGKD^WW5xS40Gh(Qh3DX%lOeG0SZM1{qq56yl*zr`7)v3P5aIn?BSh|M2 z{}^nVCXHfS`n#gAi}CV|5g@0POWJcR0`??04wtXtIRJjOi7Qc~!m*ZOB*gbxgX8ap zkxlTHiHwmlytx5Zw`HU%w-Y>3a1;GKmMEK1Jsv(tUI(X9*_YubmA)3P%4D@-BQNI& z@N$t+Qbm5JBEQ(L*5L!^pf;);>r4Xp+DL4c$_E0M0N{~liH^%lF(bU07<}T$?g2=BFJyl8x3T+Vh=>+Q*m(U2_gEbf#sxGX-cjH zSgsCil+{&zkYK;6>v=7spA@{Bk@$q%&~}vj0h!ZYlzSDPVes^v2&YCsk->?f> z+Ze$HVe17?$o9odYD*^7v>BL_)V9okr`{}3_!wIya(e*HA~mbhGMyNf>Ax&gOPExc z@virPtIhj}P?qa1n@hc_%aFIN#y?u@`iEeH!#9gvf8ws_`rVV;i<=J)3#oS$M9w=D zj0_uHl7+)8{=#%7-Jqa5j%*%vZH+3c<>nN#-EASXk= z;WiuQWa_d@f6_T+C8vW6Iq{0W*~<9QoMvLX#r9Jd0vv1_%BLu`f#Cf^VrZo|3a!+n z&cJ2gAJ9r&NQ}=~SgFnHaC*ur$0b;MCxBpz$NW_`0`Kms^3f239>kK=_}CrSZmQeX zJE(LDMqEzZ5tlom8yNQ+iRZ^*Wiuxi0!G;xpa?L2S;c+@j9JDH zFAHX(VVBio#tQLHqs%tM-f1#|F(>{{4DOZHIPGA0IDY z4cd!P9d%L;ayA?QcE5+ z)n`wm($7ARRUuHFOzIk-z9Z_lmlq;vRK<%&DRm#ZPI{SUK~;Q-L(3~C0P?#4QaNC~ zskT6Ur_a;1Q)IAe+o71x)5lfwb3gT}@^2qoYPW}DD!tsLy79x4csGeu=ytQfV&!%3 zS?a2r1wD1!DEb$Ij(uXOM|AAf*GJL667;Kxox4S1@A;=F`Y1s^|B#aZi1@B(y{ z`y^=C#n{&idO6U${7KM%giXDO{*$2hM6G>vr=TDBEQ%g9o3%C`<(_`MppX6{issu@ zRpnt{S?b6PUQD;#z4*i^dNV-}``l8u#{|9V>?nGkpr84|QvH*H_AiK{7Yh3KpW@Z2 z_`CrU|MZe5`j>(p{EekPSTC%7e|Hr9xD;&A*AT*w2>O$Iqv#g}y$a~Oj(sAw){E8h zj-YS+2foFN*T^I9>W8D~F9e-IxhKHr4)pcwqUfIl{TSYlvYRXD7axzJ+-ey)`V+#k{MfU;|O^M@&JV`&<;=Ea(@I_pGd-cg3=-82bo8uRxt&6c_ZYRZ;Yb zf*$=PYzMl|5C2OP{aZnQi@Y62=Y3ZceW9Q)LT~xw{ZcK@{ymDmTF{50w>)u^ptpN5 zioRLUw_%JeT_@-h|6)Wqe|jRMaOK(WV+&Vz`onf_q(I$<!>v-O^X`qJJLVI807gmmV}kzdk|_E?Nqj#HgMoUKG+r7-|0L*-fZkS*k}WTf zqDS>*;vZm?9Hd9dF<8SEYwZw0PXzjA-BX{rEsB0c&Lr z8pGLOU!&V(B2#Y8-o;Tzb20(GbT-lW9}xelAb#m|qVbau|I;9T>3pK`|6J&({n=ZQ ze(8jw@w)=QjNKLZ(kVmZZvcJbB4wrjr@0Jj|9GS($M&Iz}K-$0$)07XnYmY ze>uRH&S)AxXfH?I!G44IrNUX`uiVp7PqE_wUn-q7{(a!TcvRy{#k0mQ0^Seem&#|2 zuiC>=e`DW4`lSL|<4@SlQ6IAN0ADJhHU80GIO;@pP2fvKw8oFz)lu^)qJb}!(HcJ$ z?f)QWRp3jfRgFJ&XGitovb?3Vi9zs_|oXchnkB z<4dPjjlUZF-(YEc>D;REpCkVbLH?zajK=SR`pI*WLH?z)jK*Js{FiZ-0lsva(fA7R zzm!uu@aLAyGa7#a>hBcJGr*TlG#dX9>hDTUG{Be6G=f(>Wu^5K)XunJ92R2;MtX*g zBTR4m_E62vyid@tWlh6nn4nb68^4Y)G2`$Z_MX%#PIGVSE+UDFsd10Tdl6njS`NFihSKCdnmO(6aVGI$gzIh zFjp26#(rc&cuTG)gAF#<$Y{|M${VqgT8$ix6IHo|TM3^5Z!EDJSL_h@Pwqil11q2J z8MPv{cTgEv?hukRv2<3N=!_^Rb^J_xUy9x0Y`qMY_^SRF;EL-QV}Gt=B3!Aa#n{44 z&>4P?;nh8k?QdB@RrEU4Q0vi+hF_q;ctg%1_*N7lD|8K$7@JP^Q%}b54Xl$4m$kA3 z_S@WJdnxtacZO=-?r}>UhyLsSh%c4DUaQoaAHjtCJEQq~)PZ1rGVSIZ$WE>UnX=-2 z9ztciHyVaFb|4DbSAwg8U~)2HElmGyEQAgBOhXg=IVAXiqow5=Wc4(62Hd3q!TnJJ zos7=uu@b}_NuLFISE8R`^tpxn)R_T4I#NRrOzuE>4Qq>)X$706p7RkMp|6tXk-)?aCGG*AxF`KBvR}9y&QEA zcIe&tVMNwuay<7|TUayAb6BOnHCji59idzhQVJ{i%U_1E2MzD;Z2lEd4euDKhPG;a zXo?B%YA!=!K~=VV*`U-6P#f-rM*i54W;gRzp^>O9{{+n!9DeRaMt=Q4`b#(NFQVz> zo3Jm&58$}FN2BKZVNdiW?4!GTnz0_mTz^E09g^!MM*jGaW*@V^(CA#PMy2`*O_!19 zch32tCmarqq?4Z?f`1i_n&03X>J8?4NC`7n{Sse+B9DibfVcDTu251RR+7jR?09cr zmWxZkH;&WaQgn|r*)n1Eevaj-hb=t!HznY<)0Dh~&^^x716DW2rPx8ez8Pt6ZATJm zz2S6I9g_!mN!X+^lvGy?M|TbANI91?!E3f;Z(I&e2#rs zz76Jsuwbq4pJJ*x>|{nP5PG^djjeSw{PVDGid?oPerKz_Gf3yl5J_35^4HHrM}~#a z{Vv*(bEo5lTJ__RhiA!Lp*vQteKE!^!JFB73Tb;~m8t&0(X_qvco9kg@xb4jY5<4j zKAJcHZ&BxHaCIbUU6;9g&otHBOzrHFC}*Q&0-m-}l(w@fu^Idm3b2_)`KP(%?5EmJ z?;W6awAk#Lw^cM%wKQNxoG$a_IY#c}om}-aEEaChAlDmNHEkYJ7Vy3n)6*#vm6YUj zdv9f{hqeH-`vqJPEVzJR?1`@0m!f(9fPht=?1W;aa-GWp+^?dzzxE|=bhV?lWyKv7 zNm%9H#y67RW=T)BbWzq~DoxT+xv7_$YB$W>?&$$ex)ZT;WucwY8R?I0;<&@Rc+7j8)z?ovF-*yCm<-*`dlwt9TJZz zcY$NLx1q;fj0t=o4JpB}AS_8oruUv-je7RmW%XShUgzV18`P-g1NPO94nL$Gg%~~_`l+27h~4phaJnRR z{HuT(UO5J(N-YbaC;cSQoIroQ8{SHd87X$!b%-0%z8pf&`l~=S?X~gk(wXl^X3_T!Wz=%a3+eiKlglJ@5?-UlfJSRZ|l@>)H zx+vG)9~Ome=Mkei+0BBYR6YD+_!{*I$F)7OzrczG;Z5 zG4Hj&*&g5Z9kb@S7-Fmk&`6vojWPi;zW(GMjyeGqk+^P9BSzFkk_lUcgDG)-=VbtF z(dDYd#hr(u(b<&~7pNijJ6FY2g*Ut)(Ofdlg@5@em(&E+l725LxTo1q1@u=nBfM3H(uwlrzXoVriScOgd`=w z`pYnggw0a0}#M@MVb#5jYZ16aYm6VZ13pLP!dhq$=c=m+M8UzHpKs?tT*tId}l4ZTw8lnIzwI4 zn^f-yi)`=MVp8=7guvs9@hfkE&6Rq;cS6A0oM3(GEn!s#g;;y4UWR(7a>NI~vx6n8 zcY1_!)(k_v3W?yI9RXfF(@-A~_`3-3c)WFxi$L$Z4J?jSOy>Yp2S<%Jwlmzo@kZ9a z7LuNyYz}$q90F1fAa7j#-`n&G(OX_js(xg!KJ+dqMyi}2tdPA6B}3^hs&Z7YKK3rs zY*b!{wZjGE?P5*F6jbE{je1e&T@r<^gcdEdT^c$be5uNx0Oi8cTN#CZbR%B1&2+C6 zsH)ti#gO%+ca;X@{(81v%y^gsWcaYgRORbfnQ)EcU0Z}EHCG>D`S1^HKX`X&6nl)S z>~n#up?4RdNzoK52c8k2?unpewNUw2XvbU;c=r}jDtA5766lrzPs}1n>=q;@xQB`{ zw6|XK%SYj~QrM`3oqS)iKsA6t~p z?$1jK2h9#=_g4@$k^-$bee>e%&NP#6k{Hv&mzd}{XOr{)a-t(abfUY3sg%sw0?`xQ zWA}v<9gE=+Q!>$wxj&rfSRn6?0zR1N^tAS|tCGDspCJV%p;Yq_=djnHM5ZcT_6SiV z=@~N!B^kfZ7<{b+ZJDZ4_0OM(FBanDa;j%J*0$c}9B7>+5wQ^@-~twy#6d{(hFxGJa~X+wFg6HlL5qyb=I^xuqsKWf>IN zKgVjm8JBc&tpJ~km01;*KYKEO6UwT;vlVurQvQ6a`7EqFZeyz3f~XSn^8*ZQXC)_} zguuzDEq{R(TQK=Y?$pyN1&Gci!E;|6p`cu(;-Y4 zH@P{2s)h9=q9G)w-=aoQH+KO4mf ze|h6nym0}ls{cY1S4S&e{*)S1<6ep4r1kO#oEgO15XEiJ&YJ&axz_Fc*KPLWpv&d& z3c+vL?6yG>^ZEU?F~onjg!+gO{6PuzJ4tOL@jtQq4=AMF;?E0gB>q$@KROlAd~ROG;{Q+r9-PoN z6931NM4ETkHWJ@(B5dWi9;0m}zU8o|h1JqN5FekbLLYHUz&iw+8+dK)D)%58 z{qiWd)!Y}a>B6qI|3)h4Ez+5#nOa9)qqn^MYA1qJt;e6L4J&@nQutpk!|Vyeir-uc zUoakB7ls(WZva=VC*Q7ZFn((Rbo(b-_x9UDQ2ybQwW96!cQ~;XN`A4n*7$>*9s|P) zk)fzsCZS_;el`3b&HSr)u@%ia{s?ER5Q@NL302ExAQZEX|AU#|Wr;T3_!BltG2b)9 zP24Dv{6TNn>PHTa$<9UtZYvBN!Oe~0^uW1dS%BLniqnH*!FX54+aZe6gK@-bwt5%) zBL2cCP7mDoaK;fQ#cbgJDP+AkLr9OwuXx!O6S2QO zS_obFvz`uce~aR@bnQUH(6sD77sZuMA1Z(KRsq$9C{?6kwm2TA`-s zy&jERY?yp+G=N0@K1!fF)eFySgPU)Wsx$LHRlQTdgdB#3se-)|X^UKC|g z(ux#i$q{(>2@_1Gy633Na}w@O2|;e793zEVjh-V^J>B9olH}Bp)I;e!^j9J1w-G@k znajs&Q=&h5BPv}%_sulLTkRkT9? z9+YTdlvLV999^P&e-UuF-=?V|93DP3NbsPaCsjDr5O8?-rl}$vHloR;FsE&rRJZ%d z<4koE&Y${cyNs)+pXBUNR%(Gcb;cH^D#sm2|2&s#o`6a+qobx>5)!Nk2nw^1PN6mX zkY2a?U2Y%&IVx2CM;teAWy)8%tc-B_JM$!M)Az3~0gnm6*Slm(6{s&?Xrf(RoIP6!AdjuLcdq!NrsGV3-;rSdOr9}xUCN)Tb>p#4mBT^$%%A0>z| zve)>4;OQtqcSbg!7f?OBNh+0JgBp>1o{thl7#Xs^sct7DFGdL>jNAoAgy8ikL3c*J z10zE9<|e6Be*YZ{-z1gF*Y6Y% zd>JK(FtX+VQ$0sUzK#+^7}*bu2*Hn0g6@p$Ge4kGvB-EXP^tV=U__EJqXZE~PT63~ ztv}z6(d-k9buyyzhddYHvQbxklXn$IIm!3~Y#beboD&tpGqIA=`?RR3->mO z8z05#H19t#z)gXnqieeD*ehYp&m!5qggAh{v{>6w{EK7r z(84;uwvJy1&`V<66ABW34~w&hxpKR-gp2J*fnS2JkuDq%Z*v`v{I&pkLkV%!Xjmc$ zUKJ(oy4F-P2)#K^tlLa z?#Q|NK#%`&OmdR5Ji&n;ccnhiN-8HWJqdu1+I$O2RvLj)>NNhJ?($_uhEZ!OiECh zy!KzAPs-TKEx*ZBd&AJ;&kt%ssx4Ooz55#O8|)YX2Yh{jl`xMe`8x+V5yH8~(_IbT zEdmbC3so-f-mT@s^6Zk=u=$&?YisYz{_lXip#$l!mLJXKK;=K~how9j+EXuK-75xd%sgR9I_m$B_uk=A7G2!%+}pC*-9RXT&=UG4(g`9R z6qF*ch!h2-2#A6pqJm&U5j!@(0w`h!>tjJg>?i^%Ac!D}h$tu)6np)C=SpAOTc$$K2MZ6gPOJE(xg6@~`H`e9ZJ z;$$u82Ww#j^7{n_hnYUHj5ttK!f{dQhb^jQk=?~B4v3zr!U>mJ;f7u`I+@58p~4B4 zTH%IHt<7KmI|^4n;H4UccGecJ!4^`50cK+-FO2?A3k?;9M`uEIbQT_>MBjl>;e>*m zb8s&tw%99-qS}fs!$uH4M8N`J=D+QU3S&|+*PSC>mxy1ag89LBF%-1A($6cQ z6=qSIF`}SD(;&a#RG5=YE;TBsJOC?x7+We_e+xI zW6v4{%;O=V#{^K-l2O?W7YZAK!*MID%huYkU*acvp%e{G^9p zRBnM?EXpkSji`JLLInsB{5Aj{A4x|P9m(V1%9e1y7B#N6dm)i1j)P_J1n$G7W}Q`CUD58x8j`9i2K8lI0V#Db+H;8Q1^$) z7JKJIpkxet=ZCNmz>#s3J@1{*Jr;_!ZG>Gr5Zs~n&VL2ei`1ksBX*&N&Zz+^FH)DG zEr;s8^V=CJY46w2xhoyobIsm)Q}BAx)-2)czIyMxorPAd+Q;sllgwxrBF?V1Lq^8Y zj(2io91{&eP@IX3d-<~v%F=`jo3zWG8W~5mk>y0jy-QV=w9C#AxyycNz20S~%83w0 zlx)XSg_E7LLGQ9tHATK;{4P9AIN9o5=oneYv5AuOvSDss78ypz>h+EML{em!UO!H_ z>h+fpsb295D*NGN56M_UZGhG5Rd9jEpF)<2RG?Zdq1`}MueazKY+s9ZE55>gDo^*p zeKwT}xEsvH998+?M(pE)tx^+_Lv46F8m?EVZj}RQj+L5wks%~4_SgV42?Q`#YF)c0 zHI&l`nsZez%sc&wzF{oz5I(zt5V=YvT^x#epx|xkN)2K!;K0K`lF@cDxV7Zz*fC;g z2ijhi&?t>#BKBPkPjn`RZZ1QYihc?0QHtT!O?ayyhTalIT1MAG9eid8im=;IsebHe ze4v+hO)B-bawS=;=es^pLJ|h1N{GGmo=+SiuEC|au6{@E0aZHL){YXm`&dL!;9b1Z zsZ`0T;%al{j^etF5?tgw4E;D7pi(`=7R-T_yvn!AxpP8Al!*n-pF`(427? zptPl%Kcp>P3gE009YAmabV-TiRt9Z!BGk;j2yB(h@~l zM*jnK@VQSYqAfkaSlY^!WU+IMrBfxu_8Uu=;(F3p+SZN|m~))AG*z;yIBjXFfhfT# za- z+n9Z)s2}X`0%EN4DtpF{G66EZDPH6Q(B{QGkHcBMrUaG`Y>-M`HIJiFb`$0SU!c)d z2nfh)iDRI@0wQFxwMs_+CRltEj(X9yeqI|d3b$91N}Qx`tLaJ6D2Y~rPIeIrcB+QS zz5j-4BR_An_xSNt-<8O-wy`I91zvp5S#noDZ;VS5Kfj{fNY5LW1n#aj((@)IftN(( zMt><@Of8yR28a3 z@z0vcJ@~w&<#u-74IcSKTF7FxOPzPKx5pGh)_6l|e7v2VSJR6Z zVFiW`80IY~MHug__CWLQaBw1ix7q{EyE6&=;}voXA#bTSpr5TbGBw8o<>h-tlNR~J zjW~p#cb_&cH-e-QW8@a4(y)|G>N)-CUG4X1`B;+xejO5Q4OgUO5Eow$supyW*Q zIf}eSUi|Mqa!V!eRgdCZWJNjD@kO|)h1N9l)_QUsmKs=;Xhr-Fzrt;DaiqJHAgRvk zC0{A>-pfqo=GgQqxz?Ju!=(K3WkRatTaVR#X$!?oHmWX{ki~Kk)BpS0&H$Iks~YDS;wP zkmV9MiaZTPm>}j7q$;vuu%fD*mP*8{ohvs@@@l#Sjv{BPU6s6gE`g)S2<&Ikwo6`P zmmpP%t z67jL;$xV~I{w{%|$T}!On={xMb8P1*5`<}(V7N<=s>sP|_a<+2S}GB*gf>E(CV6MN z1dbw?s$G@5b6f&PkyD`vOPJ;oq$*McZG@>VN=qf;YZ?W4hazvbI#lZn3PW#{I}~|W zxwyZ0!1(wIg}cth(KIXKqj5D7?Ly?;=;EkwBK|jIGH#xWlQOSUyBB%4xi~4a2zt^E zMc$n*PRbmkb}#alxHu_uy4tQxh36?%%dK2V7W+tf zoz)&ol@J@aO}<}L`%fvZf{pV1qS`aIcBDX2LQdZhn51&2Cc&%l->cl$>qAxB>uXgv zl?Qme=p~5MtDNw9jfWdbuNsy6dvGcjeM~%`FbluB(IKeHdqhcP+_lmW0;?a_I`|w3 zuHI4-X<5})>6|nX`fP zZd;>zhu|x8=B#FZ>%g^u1ZuVJ^2;VqYyoSn&Z2}Cb^b!3Yjx<-0CWuQ;&qvaBh>u6 zE5}KBM%_$U_@XvuA2<{7uWK{ z3%El@UIP34({u^!!BErIWnTi@1~h8P>{?v5N^Xe01hxaAjw}5TIV4zL0y_{6io67N z8&vTk$y_35(NF|JqB=b9Ke5@MbuWQUp>;2TrHjuZq@1YOu=FLcj7{dYnu>}WeL-~z zEbByC&QdY|wM)=q)?h@45^uCVlAob`B^tJx;l%v!hhn8;{zLq8}tA3Fd8bzsEBdC(24o4`hki0UkR+Eg^0JZG5-#Z%@V(Nn_K`u%)f(U{o<<| zO$j1CT;G!utgpB#GhDc{_frO2+nTkHcl_Y#1fMWg)QWPEK z#{4_*liZkp2Oj9+#QYOn6g64t#QaOp>2AzFgW}DuOo{ntJH`8{MH0mPXN}MmBFBb? z>mlC6{Qr$*3l;O~t; zj`??Rvg0&qrf`FT4o-HCtoMUD=HJ1|&bS*fXB;~}(&dx+U20?g9lqpIO2nr(P%-}( zxDrS!S%L8y4d8X+H9vPoDuIZvLTh2%Oc&?0n1Xwqn15T@@eUYZRLsAl8<(kQECvb_ z^Upl8^}Sx-iTRi9;r7Q(%)d2-h<~ZUcRTGt#Q($zV!9m*G5;=gf3*yjyWFKNI?9dt zXEp2$K_wLN?l$J%DTJ*2pSGBoe+MT=*G~{K&++!}yS0{Tm~-nZs^$?#f@7E?>I*3* z6ip#OWGxKCS?qDMu!f0meotP0m-~lHARE=?Hs;?E%*?WIN86bHbOd%16!BN;s+j+3 zp;S_*C}Zjg8H-;%Efo&9RaXT0r3jot{eYIEV*c&K5T$`u4q)*BK6IjD{!18Efk3n@ddq1%zugm5r3|;iTO{#v8E#a4q`=B%zrxRQE7uak2Nv> z8L3=DG=w2o>ag@R=vd>;xV>paBEG*! z5xnRU&?}iPK~?-MVMfZOOUF_S}4L) zd(%=OQu_!+@VQIiD00gr6^s9cOW-I{6{b-!|4x;qDsoXHMfJTa#!!j)ZYaWHesBpK zMNXNlV)1`=2^>WxLlF+v|H~yXS*WIVB-#j5iL7+$VjORx2z)Mqqe%1An1AX_YJ|>D zjrnIBWyIMls-NLza0I@N`A4{Us-@>fV^g8CB>8WHQJ_7?c<8;h_iY!UB6-$0h zrDOinP^k*K_Oz6ke20`FCXIL(im`e@EuG#UeT8-;o)@x(M^>n14s+$6Hcj{s||Fj&@`I*$d6T z`7s;wZ-#PFT(4zv%s=zz|5jjQ{%NH~)^u@0Y}&gq|7`5y5*zdXA#&$;E>V1yhTfG` zpP*9kbr0E?e@Bbou-&X;{z;}H{uyEXI_BRYUWo$&D(2rI?g?TY^KXgs&$`dX{9ADG znLnGDe@8}r+)Sop{+XCpsfs`Q%*6Z?Ko#)V&rQrfEmBFHi@)1rV*VZ4fuEX~e}{JZ zUK8{0(7vmo?`K)s{46KtpY88l;<;>zjrnIB+agJo6*t6{98Vwl^uGNk}aH=|MJl1V@%R9|7Fuhd5p;K^dB4ZZ^Sx}$zX2<~ zZg67$8Ar2$$iMR%71xiLe*;#*_VaI3IK=#0oQ(Oe;Kckhjyy0G^IzSG`M0xZbOH)2 z9~_Eaa155M=|+?aKXEKRp+!Mhp9AVrwu-4T^Ylib=qTvnNJ&hO6h`^^#O;^EDgdBI+NLO1VML)wskQ$*dqwj zsK#Ua9@a+?sL|mCmkQ5Cj@`dhA3^8?Mi*6e9fmS}1c5oY#WLGrjv##ZB=*LWjv&z9 zntKFc3h9JaFk2l#AhD&7AP}_l5rkrrjw1*plaCLBX z$X9Rg;Rr$&aOwy`4OKw8$d~z8f@D4t8$Rj?LKSe(a2x!yc+n`I_yu3x!4U+iE>?q& zAZ#_+!X_s}NjieC4^9XlL7?pU2tw{ODAx8Ndd3QF*GCX8LfVUb4-q1Ei-yiw%+OyL zdMqvwJ{7CQS=ZE>ZfRF(=-iGBm9z(OtUzAQ8^E~YMI$u2#LhHF5OOWF>Rr9<5d_LV zT8)Sga|D5jl8zv>Q%4Y}ut}l*sYeiqAj>&|u$=NsI)cCu8RP%cI(-CzDknl1T=a)0 z?IqxH-t*S$BM4MYkyjbN0#9=U;SzNOf$Bapgw&pcGe$2}ifJqXf<|2M?%{RmJIWbgF?U!9`9(=w}Ze)Pa>aG@UHMq3LZv zN=BxG2YP@>2~F=+7vl;?6x~h-4_;H2Cf~{T8 zHPc#phq3fhhvG|6XiLvCmYxD`FCr!PGnS?(1qoG_UTZAvGE`L|V3m55Vz|v%TB1nH z=n+ssQNl`F|&wcpj2PL&W_U@TpV>r`WDTRTeNlg83i$*SVCrKtv@ z1gG$od$e`Q3T$0+Beiu2NEMl4T})i5q;DJLE?_&=hxZq>#!2=h3o(cpo z2M@SJ@!qKi4fk{t zVf+NO5sQNd7ANA*s*PA2JaEA=wPAsS2kT6hq9K{u96Tt1TIS#Z8&@7YnB^WkaNrFp zIR_6IP7MpUxu~ri96ac8i76iS6E34FD7ld4;6YSv+u+~<1=+~<<50(kr5-$>nv4>y zh(Dfs@PKjl7=Wazg9Q#+nl%Rx(onfMo`aVfrq>4#n4T&OQSsPQWt={EkRnS`or`Tj zrqTxw(oo6Di2r`R+_}NQ1E@k@L%;TxBL1_VXmVXcV?4!H!Rh+C+m)D{vB z9ys|JDiI$KMfli&=W_@gMSjGxJriWP1dbvrIw*peOJK54>fWZdkn$?0r4sSirm6!0 zHC+NnkydJJ2L}%vO&vu>VN*>VJa7n76?qLyJ?h{=Iw}!A^IW-egM$YSfuqRBP=wDF zbaV+EMV^KtOwi3GNLA!~wS|O(2TneQO2l){lRGy!c;FB?id?6*c5v{(A#fDQf@##j z1Bbw5p-j_AZ6V>{K{_fN#egDwAmB`wz)|FAwY7tT2aW_sk&#e@B}{V(QWg0aiZInh zX{ki~ywrmS+`&i@#J3$Gw@J*w1IA5f+(B$j(Dq86K6t=5nr5*Tn|koTkvT(cq2%d< z2ae3eY7502JaA-wh`}rA;DICaezk>S4jwo%S0Oxz`Sig9D^qm*@*{kO!6ob#5YB6 z@_CI*@S&5!q4*lpv^E$v_#Hp~~yuVDIEJyp3EmqovZ>2DmP=r1pe{#~Yj_e4d1Rax}A znLg4=>3@A$^xqJD|JGEO^L+f>;5*R@x#5V!$FKUums@~p>*qG(%k}#hefYMMcxb&( z^4%-5r)c=Y^Kr9De1-z9%(bRvCQU zoD!d2sLJ=O<_nj>$IU9SAzPJiwdTt%gO8h6qJ3RuhnF>9qzpc8W{K6ODZVwDFIom4 zH@C#!0~Oyo%@-?!kDFcM$d;;nf9m#XG#q2f zT&r?)8o3LfYxve-++HT59HvHpPNDS0b!be$D?B;|#6i(1XRX(()+abbM&&me)~f1F3R6uAOKBWyiVk zN<^JTqTckEu+rUcnkVXFbGF^f#i$A|^4pn2_vkT#?_ToST^&1Zx+jJb#VUs)wiUN8 z{W=cNZ5A3movPUusoj;a$QqwGP}wKieRSq^_=Gcyj~;inUqmTQN8ToW3V1>Fjt`*` zGzm7KOPTPoNz)dx-ku9GUvaai1LA`mpD29Kqi?=P*?*zSBlxBWd0j;D!o30USrkN9 z^O5l=pPB7JhM<#$@(g_+N-}~UH{-ZlbO6Cd(1SX!x~FUluGe~#a=g#Uk*}pF-gBN` zJY55*hdnxV8<{{{Mk7%?>^h)scE-!N6JW_S7 z@WiZYK7mdtjV!^JHOH3_vAbBeT@rZu7M}#SSKuyFOlt^y1hGN?BeigGRXgnxzxpM) z#Ek-G!?EkK1<5Y)!?!{A3@-8LBViip5+D1TafzGXNa~L#9Q~9JHlX7YQ#QsWu3%l_ zGMMF5b-Zk=!zXc>IcCBDPD#ELIg z2A_0^-)Ui7V#SwJ1|K)Sc)+^E#OJug85^1$XIfjASTY)yI3uGRaOzr@STY)yI3uGR zdA^6L$|aVJG)1sWoRLuuL6xmbEE$bUoRLwEMcu4REE$bUoRLuuN_*kGE0U0jHXvf4Ib525FaAl5nwN^ABm4xHnj2fkdpo zx*em=fT1joHIy##5h*S)iHRmCJHBbaxWtnlg-e`mT;fis3P}Hu=qPZ9t|KLvxQ=m& z9g5iSrb4;I78;#FzKOlg050)U&nLUYBtF_4XY!Rx-0>IKzDe-9r^plT?=xT2)2Tobv09w!3EMo#n-=l)RfA$WBB=_W_lU!9!l_cV z5rNKkkbn6!{L5bLwSRf_cjRBL44PMtuG{Vu;)LJrlIzb%JO1Sx0k82LuVb0)KAcj& zlnN~U%Tr(Ri>C0^f>rRe~5c(RiEfeyk-exX5s2j3_$fW%L$q#n3;vmkf;JPFw0QQ63WcN=16peIhf^C&61Uwh0T&U z6J}wS1)3$CnT5@h_$HxP7HO93%q(oC#9)|-b6KicBAHp(T=7pX_KWx4LPu>9qz)jR zoZGQdk+!E$E%RmLBL4A3e(?t_7-~kU&WwzNRE(pLV;@?D(~MN985s$w7)Kz-uCxlL z8L4VBG7?fTesKw|p#27nV^kTbf@kc+N1M|%K0+$S)4({77Sl8%RdYs0LP|zaZwoHN zjE%Zkem=72QJs2Yl8PLICogkQtjw3M(Ohze-Brq(dKZQ?#Ge<1#4#JtQ`!aO>Ikn- z*axpv@Z%Y*lZgD!Kz|YnQ&>_idSo5#MvD|hfua$g;Ju%+IwIhcdGUp195_p>2{@{? z+b4RH@FoF*x>S;28Wt@&)x@Gj(*UWc2w2;5X)ebi;u0F)SJ(2y^+)OPz3)C6-&Y0A zMA~)5y~*SI`$%UR-@mov`|qpF_BvGrnggmE(I`9Ngqthb;ec*gOa-x$825sV*l ze8;uhna1~Y^dhj}J{oY>V8A`w#4!AU7=~EkrY!4Fr^GO1ja?44y|#<+FKpLsj}Cc_ z-=Ur9Jbc!#BZASCUwz%zc-!-^id{W)G@xFjKb|7~G^W5d$6+?88Tu1iNN|*X%7jLJ&axurh$MknR)~*U0mXH2ERBZL0kY8Lr`rWYP)jpK5dHLw4 zOjgUMCFP;F`yC>_ETm#7YGjq8+M>Ua9q1wN&zAF8Zm9oEGE|QcyWXQw=WH;Mh@6D+ znQYZ3i)}?iGo#sNiTd#AT9M5XGINR)FzC#-OZ32WUzyA`MDqp9#Wx3jLOK;B(BH-|nQ4*n-gZ!tX=e zKcXR=oRu}oTN*JWMgF>>A@LaYfeIs8hoSNf35hSsN;8zK{v<1{!08~(ql%hcCh44k zAu*I}F}F<827^N)fIzRp+sY)}bYe(cNj1K-OwwT}ygxrI3Lh(z^gHN!^G~R!6=jl+ zgaY>w>C0u3K0PQT#-b|~{$3{OEvSJN9Z>`8%Ow30CK!t2MTJ|-B&~{K^(GVSDwDJe zblr{M)x!N{kv4n~`>}lgW?_{O?&jaX9{={>Kw1~h!dMU}{2*BUDEtuBH-#`zSD%pu z=b-xEC;4$T=9qpUK(sZ@1%bD4zki@`mtBfE@%+A+>}d2!{5cRS>jzQK-vp}zzyl94 zMH=wnq?Pa$?hYpY93;dg*t9G>sA)Z)rA< zyXdbl#O<*A`vW%l3sEtiheN^b+Dld@(b(ddK*@?)4gB zyB;?2diuOszQ(<2F|#6~29KcLP5k`wq9$E2(JxM;ecwvz^5m98a4s^8_I(7o+Eptr z#}^M?f;$0-I?vaZ6p1i3{fzSC82l3P3j#rL5>eH1saU2V#ZD!tPG1MA`iG-xa)Vzy zhZ~!{VjtZAGu8Aw5m)1ta{b25b(;;4q(#$_xpm41+FwdZzvH9;E=`zz! zzKFkkuEHJVqqke76~E~6gLDw_W@udJRD;qTeZ=PIF5lSW6Cs8Py0~IY9m#Q@-g`wn z4+qev(i?woA2$K6c`@j21n^HFa32Zo-<7O=vJClq@?mrvvbsndb)8?VplTc@3q$iY zquGF5or&J45vCa~YlJ3kOJl1wao}2<@}_D%MGFf$gi_d#(-qCBT3E=TafGcS&8V73 zXkl3nAy;=|A?k@~M#_5f<%S)alxk0W1($g;Rr@Ge?Y`V>hnm!r)t~4Nu}nBxi;Xyh z>CAv(?`0bHydtmr$C!olQMq1I&+{76J4YwncHwzVyzX1@MJ`4)^E_YoRxkKus=4O{ zx<3yqFs_B?g}Zk{HF64HCCTl+|1Bl5mFLy%{^CZ3!zW6*b)UaOrAj<+me>6ejckLY zultWXR31kn8R-5N-so9uM_EL?e-dRfmY!RQ316S5t#J^ zx%zLx)ql#wX4E-AuKv4Oc5NjkHbcAmi4~b${R<#pjXF(JUHwZa?|4`1>hFgZUWC9= z`Y9i&uD*@jfU7^)y87i|j?b{Je!1w2t*c)y`ia)nFBkn^@C`YVp(IoeddDY>Zw(q( zzdW4RQl-*EG_*@rDXxBB)OmyqCK3aOmUi_S%{EIsh2crL`kXn98U~%&c8T}kLMvBa z@deApR|OqSx%!GPR4%@oF-|L2U-4y?i|=RTr(Au-7cLiHk#+SIUv@e89JA)vO;}f- zJHoA|H?XU}n9P&^pZ?a>&rJ1YU+d~K6}$Rr1&-`zUHvjhC-t_jei@`uD4<>aGDuhU zv95j@q{pD}+SMfXjPGbgzDmXs-M(wlz6&!>{$v!(VMMhB* zHPYB;e@FZ5BBW?NpQTN7(muOSqkS&A{pHGM4}{K=Ir&}mtJ-G|X>`CvA8N0B_OM0= zU344mvqv;KoL_n1PN*?oLo~# zm-;RB@vFxO$IkNG&yoXf#%S+NFTV3)<$%BAJx%40Fg5**@PbbVy(uip1W0%#QS~^RqM`Io6C$F=JvbEXRbu$gF6dw1hTGwqT+r zY%`d|{;H{i4t0tp6EAx~F@|2He$&*U!%*+Sdp!I3zsq{{LeF=P}pny7zHu(4ttS5sO!imlf0~e+-VyV{uTM)H6QnSM(L;A zg$zMV^dQk!AOtIHM&O$%k3f$=;gR76ov{M)2FhI6 zHY^$uw6HxGb^)T29aK{8nM;z68b&fjqlbyDlV&TTZI&Ae)ES_?RG+-j%$wm{y;k?4 zn>1}#O>1{cQfNisl^3XWe2CWZp4p>*5PQ_I!t26jwkWkneYn<9lMF3eM>nkQvpL6v ztG`ICqb}j-r)(V!=@+Zilo0d~4Of`mYP1eBtx)Ue1B7DVAIxQn9kd3fV4d>Xy73ss@4_rKuPRG{dF72$J` zuNUdTHA^LsTPFVr$6Nj^#Ht)fdDf+gzud|bzt+IA-^wtZY*DQ7FKc^Z#EYPQF8rD! zQLl4)g-?d#m*sony6T`=<ri$LUbY3_5g_o3F1Y`>RQNTr>;Hkq#FZctFCL3e6k&Cv@C{iuGA^UJ9ugOxBE$kJ z`dW<+xag@IDv3{(Y z(~6Q;eGF>ASN(pJ#9#ePYz<)5JkXBYIDPJG!p}hwD0r2c{8zQ`1zfWm+h!*<`CYcj z^Y`Vc$$RB(@}6z-BcP{h^4HrYKNk7ot{y6wGrOS4zxb1B@(xXWSZb4J*7!xX$**uE zCN=qrw#hp*@k0QsChvmZ+M3ejWk%yto4f>fPHplGPHOVsqK8DN5=3Hu57XqiY}Di# z&0LB5hnps^&;b|y#Mz~ryu&?djA`;*9%}Lq`pi>JlUL|07oBIDyh4Xv^!O7>H+e_+ z7kx@Mc?W%Q-_lLqqD7zyOc(T1n`}sJ^2s%n`~hw9che@9?4~xk+fH}?N5k+G+a_PP zZSoi7iyINRP1-pPZSrT^CLNmi+|)M7tnsI8o9y$tm1tjtF%0*zZPKBMH?_mC3-+fD z!!n~qsclk%&rNNU3{Gm3vr*CrRf0&IXoq1g8?{MBGgl(l4#Nr^aM6|048sohR@)}I zJk%y#v~80Lo#mou**2-rVHf>Qnl|YO@1JHEcF=p$v`LE=ftR=uQk(2aZSuIa)F%Hx zn|#i+$s<3YHu;HdlmAEKV1hTmy$DzRHf1E_gxeI4Lt~k=iCDI4iYHGB~MCR)<~@ssxd^xQ7`hxop%X8O>aY z4tAVW=zxn(q!}k2?vQPhTpntZ4*D-Nc;y->be4-=4$nck1_~W^(IQQobcA1#W}I}; z^nvwM*TAAh;6!eO)FwS@liSx(n+(9TJIzbu5WWrOmWX|6Oo^mwJ9Y!SRqL#tm+dva zZ8O}FGqQ0Pmu-W^IL^j<2otlLuctP+l5q4>KFAA}F9^JXERQ7FD`CcE$Jd@0k`ktr zOTrp%<96mgJ-h$4q}TLperbFdg=PIjV!#P1^yS0|t47U((dAGv(H2_qamfobbD%uT ztX=W3aH00obteyIbNSbsI^iTm#6>Ca*j|$pr6`){CZe0!9*_#=_Wa_ZT=;t(vVC&PowHgaW%h%*d*W`m-}P&%e7GP*)z9~fV_=&4byeBq`c2VGhvdDw_2U{& znM=rNLhirF7VQW9(rPKuBIA^Ni6`IB+r0MA1t>uqF2E49e06O*XGu~> z@#{X7ij#4Y6u0*ai}rIj`2`WUiuVZJCd+wtSRq@xb=BX$`nWjns@ z{LLtThWX-MXrkWjp2MK5=8F-?$BS$y9Q~A!wDX1Cb;o?M@*Fc?lt;o|stdCryYF`9d)V%EQds6+is9KWV=B($q=D`GU4$qX&uZ zG+dn*Jp&JCU+@dnA}2hSI8QPMu-e4*cd zc)rk1qM9$hnlI-IqA5LJ+yY0>oiEx^A-Yf@Vv~Q=^92>~c%NEkzHmt8 zeBrnAMLWC}VeN@oPJYPD7qpP7!E4an)qLTC$L}-q#Q?BNT}0A+u|$(p@rE!7=QHH# zSt;{{%zp4OX175g#tl^Tl&&zM#S;4ZErH1rfNz?oZUN zlZIV}$YJ+#yxhrQmntVh7*Rs`s$ut4jqgg;6bX~sC4YcQ4ZEA=uuB}yu*(?`48(NS z`3H1U47-;?M9^Oq!|tDE*lqJ24ZGW-#^Wn>g81=mNyF|bQLphF+FKY9^&(GDUCLGD z**J#D%k3vdH?c+OQda&c{X~v)`UsdPpV4uS5%-Ha3vYd+@vqMhNl7P_CFxbF4&z4R z#Cf#;1*F=@D0}Jysme%2ktl?AyuC9)%A}E((TCSEF%r5k-@TeIPzE3C1fO#|pIhu< zE4I;WQf*1Z7nw{d6}_rm>6aqPm9|4M`_t!91@eQ($C;GmN2)8mIAZF+S9oWnsPP{@ zv5XdWzl7vj#CD~5@JqqLL4R$uprg(H z&$pjb3)&tvb3m#6pYOJ3Zb9`rA`97qdf}j#YC)C3;YH$vqn}O-Dx{=rL3Zm0El5uk zxPU7f-!;{=pfV(tAPaZyPH92&QQioth)wZErUkJ~YC()Xyq1Xp&_%T%#TO`pk99%| zYQvN3akgS@3pxP9h@xpiy^LjQLEn-6_`xmcXG-!Tb#g@uvXd)X&{@AbE$B~T^OG(3 z!7V78lKfyd!M30icfdaU;1-lebo@{)=y%|Q{)T8lKeyF8TaUpj3>P+unK4K&?$_Ii zhU4sK{e-cn;0J2h7<-N-(X!=CZW0np^YK>tRkQqCJPmN1=OLo4CK16%1BQG*x;w_pl6e4XGlisCK&DB6gA z6n+AYyK;$+$MdXw!hIYSfs0UppuZ^$aPN`Y08J?1r?6Sfbm4LtU@}#*+CoIZlMHYk z;T!{OKGzuF3$_pwq!e@(tE(HLR|o?vb`4;7k_|8v0wbi1NHk4j07j?ilQ8cANJ>aP?Y`x zOYqh$Hye62z$@KKliV6W5|f3(`a(#)Ym&{jV8!iYlY9po#DT9&awLhuqKD#Lb^yd7 zXvpN2YjdD}3Mymi`dr!x5L5+Hm2AyEh zy9Yz@f|6CzX{pg{E!LSBBMK&HU~}qnkz$aG+P99#5;Yq3UHF|R`YZ!)pA)fICpn_S z>IX%16dt0s{{c(J9aiSXKSf|^MN)r1^esS(4UBtSm*$=}NX|0Jqdr98ZZOHYRMy2N z+4gHBmz!h_O0G1?54u3q8z%V*iP~zCZ-0d3rzUwXVZS%Yk0_(uC$v^~{e)zJNydLc z^15dU`xT0?jf(Ic4l!U~3CSZcjRyYWB(0`?>_@WY$AtX@*cE1o-2NPTsQ0BjM)L+D z6?v?Dfqo3^j4yQHhwig~e*zoXLDS3kdyOZcHF*bdUglyDt3KOxTtL*pI*xb9m%oR` z#My+qkseFU<5BwclzBXdU!vgxJP*-omiLX1UAL1t@s&*U&lYRl)&in)^_4gNEk_VQ=}yXQYBd3)74Spo`V6gnheoG zO9-Y)NHIvF-BckeQnj{}rKi0Kqqa!A(p8ABsd`(<>ZNcy2R(5DzMxBW*IILjEjn#= zCpw*l$|9B$&5~_dXm@lhwM9yYiXX%)(xABFU*k$E&BUE*i9Ry}N_>IhT{5wELz*l5+mB=~-q zp1#ZIjdiGHnQcC@hYfA2de|8bsp?^q(8IVUQ+wFivWNBGgC0f%B5^NjnS0n&-Malg zMwhp?69uRn?qM^vgg~kUt9!aSN__sU>S32@3BgneDF#X0d5-E~m+J-}vMeG|UH7or zwuhNgiNy1`>X>`j6`DJ2xzkp6V$np^!{%s~Y|DZk^5AFGLt^M5r<)$qmZzQT{h|J7 z3gzh`W_i|oUU!Ol=oCY!O-ZXSJ56YxkW3qY7q+hel<4XK;JH^fZhNO_} z6gRq^;wFE*p`Lb@mdYSSV*GG#kP|Gsgd}Q^^)1Bfuhg5Zn7ttxWCR01b%d%5Ufd!dBB*vnaxl_ER z8>HXI=qY!)G4Z>Q+#dSmfB<52z$GnPO%)u zFPASC!}WXYi|s|Hc#_(bwE97eKo@ZdU8(gSYNcihFCcv}DusyO zb*u8l{CqbSHt-o-<#aVugdA#FW}A=A!Bhz;21%6YPSH@7 zo_sN*Hs-%B$`@-StCxH+2YtslHB&U!++mAOTiuCfx>Lk8OSWY}r`UXeIz?@CiW|&K zaTU)LEdrqsn!J$=Oq+d`@a;RmQZ9cM7Y|=BuDGsUX6r<58xF%CO#TeNs7Q%u| zAQHv;1?65r>mpH7(G**uO$RiC8QW65zsFv({vjR zSr(DFTF(^IZKp7$5{Z`j1?2+G9k$$Qt2+_WFDNrKOSWY}r}+FE>J$ypDXN)HaTCuJ zmpPrH+%v`Fx>H<*PH`HwDQWdN7=gG`T&o)58H78J9y873O8RxZdEA0uZl{>zc8b{n zXQsF!5KritVnL}4QY6MFo~k;16qmJmplV0BMdM~St1rg%e32&PI%F-YPJJyWdJZ8T(AMB*boQ@m+A zg(;OtY|}HvI?Wxn+-a*jF;>qM>orTZWkILd^Br}HrsxzOnNCrH)&6{Mj=d;HEnL}G zhg*W)@F(B)i$B5bEe?j|x)Ps7@vaIE--u{1M%@|A_6^TQqzj)txhoj+HNJTVmN~8s zdXW{>;$)ksw?dw8@vaXtTVypiwiADn@%`T1B=GMo<&hTehM+vsBB{6Z@kA$F7UkU- zy!CrpEn~3Rck{ffgYl-v<8Ef6xyhyJe-r7nAjm62YfvQC4R;Wz*i!FSnLl|WjAqG+ zio<0LzIU5O2V8XV*)j&-yIrbDTLKPu@x}PuAgOYPRE2y72R#kwV+p-bqq7{e2rN8A zc54H>U1QwdyRaQq+q>7^MOw;kPbj-R18#2>+0E?AdG|}ZG3t3(%GzypFjv{_A=vFr zYqxKoQFdD%WVXmVY`1#aZVxAcH)^{*qUo|gHO-5AZ16MKg#yFH`P0T=Dpc3WZX=5YJ9-JX@Iklh?~ zLfdVnMrS!_5!gGI>^7>W5JRyoP(oWNZE!XzzvU@STL`{Dsd1ra0xX3CmG>{w@_#aP zDppS!dMZ|x`A=_etQaW7#|J%;Gb`7>|LiO=;wvQj9fwGY%W{MM-Do=_U&AN8^k2^9 zxj7^6b^y6M1F@0aS6PbO>}dN@p>cqWycutD`Y(4;xc2Cq$2x#OFeXM;80tWlg!4y* z8W3dkT9iC#rZNmppqOY)>c8{!M_$t4|teOT8PA`(NrUXffV`w$NM9{9OMx z`Yq`Ao_GsdfVZHV3h)-R!+E91xivRud=6HZ_5wJ5Gd3i?!HU;YYfn-JK-p z+>C-A*Me@&AZTflptmy$%Eq<>YjhxkpnH-8#X+9FXk)aXWAP(h(e6zWbXi70FK9ta zjG)p3#?yoFi9*Cf=B!Z5CbN(j(+dN}vluYC6{aqmtjw)Yj%Aa7#0&Own@&@IN=;z<;FAP-SF=z>RbPwqQ3p_De61_ zo}zC2f3T>$$+WxlCettf`zF&JSTi0+YsOpECKIh0Khhg(#_wUxcuL*WO{Q(R6~{^`bd!Q3i_{Ry*hc5>HXXa&L-1|AWy%7exnw24t}ItLEoMv=+TUVzR-d; zWDv9?Nl+G!ex}!`J1|_dM))B$8b|wZxm8h%A0!DGt%QuDO}HZ9c?0fFE#OikAh~XK zCJEW0gp}UN%NwmU`8k8250eCyfINMX&enoXz>jp5{85sixfunm(}Et(AZS;TpnVwy zHNYW5uH+zoq|@l*Btb`mDt*x|)`CW65VSi<(4vfj-q(Vj%OL2JBtbuB6x3>rDq0o% zNLREyNrDofN?)|=w4g~D1bvz$Xjw)3rJ?S;-3JhDV9)6@N+Gk0E zPR%Ij4lU@y41zv)1<^p_ElID^vs%*g8T!aRSJL?RGOAPw_egNr4rNejf0CdUAWyH+ zL@lTvex$3UFOme&{T1m2y{-j4m_g8&NrFDjD5&ssRWuJj(rI)cNl<4{rPpYN7BoDA zps$hy-Ih_%7A@$R41&H+67*e0LCwaiqE*BXS+vsorVU05aWXzEoFgj9aPz51RKZ;~ zIbNlp|L%IJ`=-81v2yI2`u^t)3g3UVLE$U!28A!}28E9|D0~?qWIC=Odx-lpw$Eu?(jw{%WZ^XTh&)LhLV$x}# zUyl3WG(8>Ra_FDhXXxptm~{7)p!oAq(4TzlrU2yAN7IPD?;^aT^cg~zR!?3)?=C0P z@3V(}f?S8+*bm@I6()h~A!6OKnOJdVw`|s-eTj9-grM+0K&*c;YmXu2U>(D(FP(`G z3*Jwxfp;la`W(1bcq=Xq>_b;ZC8_46T*#~g z&I*dB9we_71jagp=YctOEW@e?!G|J3%9M~iEFzX&v(@0kM0JG9<1!b~6%&bkJ@cqo1zlDrP$5+c_eU@2ohr-{p z!UfDq$05sPZNUxoH#C`hxydwSRyvVaCTmA#oqkSG?0$^wdIGcFIlCOJJ(=~#$w5){ z2(ezmtWVrf4%QQywJkd3T<(+)GixsHU@lYPk<9uuI_0Y6lUInw~}$_Q)Ff4x{-}@!_=U7f`@|E%t{|+DwB05vu*7D2 zUcju^Gb?@Kq)gUB%o>GVC$n9jV^;d?N13dDGwU_5>!S}-HGR&kbOU^utWmDv^=Ah~ zEw*cw_o#;H3ga?at21ja*tIL$wHve2-L+-1Hel9IP}TvDlfsjjb@YAZV4cpaBcbq8 zZo>{6vnd^hhdL+iCE!@@X zZKE2dTRzKVeTrD8P<%N3=>xLsa1C?+UYJ?Wq=V$=1ilvDl7|GQzccA-TuS?vOvFd> zY}&u%rd5=F1QYw|YhLxlN(^r~6LQ8!?)8iBkRJEveL=Auz}zYon~g65G<<(hjN{|7 z-vat_pe|fgeg~Ks_ITap&UEji3*O3dWBG^b&&73EMLWx;-m4 z{&GMUtAn)TVy}7PYQj{h*k=6Qz_bKl{C524j2|OAK?D7lx7L?CzS@0$aRPv2y%Bg$ zZHweY{1{oqC0ys_kN*WCY63XQYpGCN=(~|u&V*WA)|E2fX6I57w^IT|O9iF__j z?m=KsoO7uZEh&LgKq=OJ0HsOy;n0M2pNAjmb>Ez<`*#_2e+rmn-N)p^6VZP;6JsMc zz#r0oxs3wBQQp^pjBMo|IgV%hM|u4LNj_mbAH@91=gC*T^qoH)PrsN(j`_iL zxWe*?h9!X`J@LmgAtH?HxZpLd&bKmOOz*hli)R7Yw1y~Y2ErXHB;gt`cunhs z2I8)NCZr!sSSU(*fbfo2L!#Mbtpk6(0>WmaLp5vS8sCq6qJ1_#K1?2Mvzfx*>4$GT z(d@KHBbudTViG5!O$buZt&{w0MzhIBA?;#bYp*b8TTEx-5fe(@NA}h6@tfwyh$g|M zg;~O@e5)5)fjlRmK6;%8&$Q-l1$IH`^{3X!5-iTT>msc8{~i*xMzxuS`?@7@ z)ze`kTqoLl5yZEu;_FM78}!-S4C&x)@iE zMkv2r%1^>B(XiSCo7v*apm;McEL!#OlTwPlh;i3-@JrnBeiGnC+TbZ=&HPK_2D&&Y z^Mg;7%u`&M9Z2Sd&%7Z&Ytd>au9IWkxGpaI^Fsyy1aO>wrbO1 zJ=#qdJe;zyHc?VK`u8|I$kx%i^pGWM9qjlk+JDO$vpgjc4dLW(aOHBVrd|umgPNoW z5%pyJx{SZXB^uDjlnB-eR|3!6xl^|FR_(pj(BF%^if8mqD$0yi(63cTe0hstDtWd_ zx+GIHY%9^t9HY&6uE)cb6iL#>%w^h?7bx5Z083djZ`mxrDbwl_Z#SSS+nKvH_)-NX z7IC@vQytXkiJliC!&9?Yw&w!K8k+50h3`g8D0u@Lj;hm6C|S_n>B0AGryktb>(g_( z5WTuxfD1;b_a?kvyYYK}cl_?}VO65!D zU()AN7$QHHlJ$oETuRLj=+T4`B_kj~eJ-V^#&_*N_z4n^r~F(BzH#=7`e+ah?xa`p zN9OM9h)=3HADLSS*67_NCHBsb`lCS)Anipg%6>G6U?ToNE%VVJhg5zvXyggzBXi?B zVIqh;!Yt3&j|NeFXmG=g=A%I_xHsOH)ko%58eNh<8g!W^sp7rJB%IHX%9o{lG)QLu z{4wUEK{6jMNYRgbeD-AG#&(Sj9#9i$G*MFLDt>gC{3{5lGT@)ll_CAW0iDUy!?+${f9cC7iq= z`HMgdt-9=0S%$3JW&Y9mL@Y|iLi0BF(dTkn2QOA_cq*DMwUvx*mxlQyD*An9T&)x;g@xW3d~#b4J2?k>ovz~ zxmppNat{%R0aS(`w2r;e5?bN&HvxRiaaoT1r~oTF6Uy?(94mI^es-m&zvkE$5~7_* z%vIh!cq^t^wEn(h0PrFfH^Y3+kziuxU$sq7b4a1o@Mn-}TNEQ6Mt&vTL0 zG^j~C!eZI!s`r_j(v9K?)7&2vHQed($U5V}+6o%+TybiAN>W9}4uueu3 z_C@X?aQ?oNLSpJhC=&}yf%HKqQT#B#3+r=6q>4m!MoZzZz;e|L!aIYk8hWc(0Z%u} zshY>Az+5%@b1bH6Rujrr&3Z~YRdd17$yLK?r)oIuR1K${s;Pjg*$$a*)fiYx)exPC z@5kCdS4{;~HMq%ReT;&}jb)l>*m))K{4!+7+pBR<6NTKqzY96}mi zr5osl_YC)o9xX5kzT&&i3y)NZ*UZFkm^g~p`09pZcnRUe>%MSU|9%53@8PxL zOQ=@77HdEx{AGAfzT%gz^Ukg)B<4*YeFdaq_%SRKaaM2p!e8(3t%Y#142BD7v$m%GClZj40TmOze%R= z`2^+v6Zp+C{q?m%+(lOXNTzSP#uI~4p5k3HJ^Ff_t)}$HGCjrTiS?BKZcdBVfkQ*^ z2H(1R<<@G%X9moxUeXO@=6RJ&6tzy5P_T`Ht4QepRF$3>@L@ z-@_#;IokQC?wx|i>B=-L--q^8(pyxfkK}FxqNGot)B7l3$qA8~5EZS<*)wFIgf!(G zD>spElO-csQ;wFlV0^K{oMti1Q@rI1sbxvfv#6p3Ro|uRC9@>gL3JQh{&(}_xLvZw zli3ij$RBjC0^=pH9UxLuly~MZE^i+y89z#ulgn(&*@d`!kWg9jff0rbAV@(s^=4c$ zVhGX_!?XoskJRO~80IPdZNDj}Magn5+oMpqo<+%We$zb2Z>LmFR)7dZeohAkMmbLb zL~4q1zPw-B)qMPtK1WCMFPE2~+OC9f?0OnWIfI1j@-pN+f)p$~LfdsF(h*BraIi?1 z*J7Bbc)GQ#Mal9uw05;9S>AQ%5UDB3+vzxIS1MT_dXy?Bm)Y9& zO5(nrgz9oKr63R3Bd+z9;m1*>^M1%iwXBcjFYxP;pVKgO;sa@Da)177Ll+*_&`&5s&zd#sf*g|X+M1DaqR;xrntNtQoBKIj zuIsDiHxs=~FS%cvTc#KNr6+os-mzPoTc%r@iC(5RU9HV6)3;ow%`MZ*J#B7IWBhve zWI0~1>?P#;5=}#9ye6m~uT$oy6*M}m#>0$b40)3v1)a=z{SML*OIt9{jMo;!JjJi> zHS?22$#LweU1ol=C^?SJSMN_WKXEohAo5o`CqEa&1} zI}dX9-|ReG8xW}}hOKNhZ0QBe z|C?_o^^p<3osjUPw-d(v)89@Oo41om2^zE-nK??PH<`B+nci&PPGq`hj~=vSdZL-5 zWIET(Q8InNyq(DO59aNJ(`ejtj+KqO)eJRgk&k5tErROKoZ@^HQIlzohw01==|GTz zUHTPaL^q@(mbRd+8MG{hd5TZ4joYGRo`E9rYP?p zN6SI0FZM6{(1Qmp`k~9ozwMyam$(O#P(5fdWCTG9`j|m$EYcB6Tky0Qv@C{siYMAZ z%c5jC>)1idqGUPGaRx2Uh6qIdCTGx^0EpBS<;?FX?MkKLK`Y6wZh2GeI)$W6BjLKd z47r>j1*e%o>uRJUmbRd(8MG{hd5Y^>yIPbi@0SQDrFB@m6k3!l@Avp}4sGSpWW?DJ zfyiIz3|cn;A~nUJ^{{fPFU27Jf7#cXk9^3fW?zfsyS^49|LMNgX=d1JG>C?+1IE{q z>3L?@QfV`6$@FJtQAMVknqf<(HT@jS8)WdVpGFt`!EPam5+b-M8%2NWFxXz*GGKf zR($%p;uH!SkWl$;k65L9d}7*K5MS7T2(3&LgG5zrG1VuICazfuOw1Ao6}P^JkGKWD z=0Jou|H4;6X+iE2+RAM4nHK1&3f#H(rC%0(UEf{I^98# zb_@~Mdj}BTTIEG7aCW{G^%41vawxd7x7=OH>FOizk(fmlmej*9MTJfTDE5R}N6R@j zhO~=9?N`_@ca)Dy$T1}2ZX6M~yK$8vD|t7LA#yh^8zG-^H}0&Huo_GlQIe0R+EMPU z@m;Sc{1J>Vz|-s~A4z+j*y*|w<)tQ^yrcXRb}HQ+`CWoX)B)EzCtW~m)z zNxRtWDEFc=NBgsc11USo46RzIw(4j{nevYgB4SZ;7XF>|hTKtpeYYGz-Z@VBbM(WE zAe7J}2>-St$W0{hRuZU35Qf}Ckb)uFn;G#C(h*Br5Y!&QX%@pg#l_aou_!r$d}v1y zi;^SAZ0BW#vmpYJ-|Bb!vho-pQd9KVH$RZ&rC<@Z9{n)orGzdo|F-3Qnxw2E;kvvG zd4nJYzvxnpcnj%>r7d{K_&FBCJjMI$h-p!>yo+pkElQU6IH$av4H1a^?;StqT|ktk zH4)ub@=EBq5)6OXc;O$_up+GDY*+vxqx2A+Uhy+Im7K}xM=JTxSha}KgZjco6^^jl}z_DYgaOThFQDfGz`CFhg_BcYel@#r^--Wy+_GsYj0_Q+GD5vrKd1KEC>YG4;!$lC%3J zmS|ISaUXajA@Zwd|Luv%ZMpy2m;PIB+f>($neZ{MHa@A0{R+?<@8oFpg7xyeaxA}?The8dr-sO^`(qUp$< zdGvQDO^rm3Tm%>a?3*ut!GFL#G4HBfL6PRj{MziJZSFbp^YShVBF_T3PW$pw%YAj13)z2g4MK2h%o znRlJL?R?pg8f|k{AK%P(AWB7(**e_~kjqG{>K!@JM2d+IVyai~Jc2Y!KD8_JyyQ=TQJM4GKRpzy{HvT+>d?JmGAond$uR`LzPv&|3~~ZAR5!w|19#) zMBDy854pR(tg#gx$Wxc_VQg6OG1_tbF2UEAZ9>9;U>Bl9Pwb!)rQn|+>7(C0BTKYc zHaOxI$B&_1$4lL&sd8P!X%S0i3xS*P#(K;G|`=-Z0XKE@mnuQ>W=8y_!}yk5{jnjkXS<9 zpCA1E<h-PYrl7sQ&m--0XyDCd+CCt~GpN?WDRFQMRcd7J$FMRQ`QvTk$h**{P z&p$3*3&dNf`GlIX%p||alTRb9KfXb%T9T%9d9n#|GqAD{2?;ERJedhZkHLsiTjpZw zwhS9$Fmp_(F0TTEWm5JdUk&YZO(fq{?8}q;5cNhvT&sC~3B*W3)YphAP;|ZmB;SCO zPstx|i;r^9ivFN;7Z$J+v{3#s4yklg zspOk1y2GNiMuH)Q^PWIq3m5<`tz0y=B?(Sae0H5Gi}i#D_|M+9w90 zYOfL*eNc$68Rz6bPu^`6EtQKFp4KRtR8(4m8^&>J7~^C#H;fDawqbk|S*z*Pwkq6$ zc6L*(C%9cTCr=S=ihghnYg3Ryy>U)EOqeQV%CCkLuJXz*BSnx&hIG`FL!#*Gj>kvZ zDHYaWA8E1`1kia6yYSKJ`uw$O-)cfNDOTA%&-(lJ!PP>1gh5l?+vSigdv$QO%(>(h zGasZc`$Duq$!v`;JEfw(>;&3h_G`Q)5s80YBmAxS#)SR4mM!;H^@#h4agxK>`0_i9 zlL*8IYICwjoZRgfRa3}Pszxrf4cB*Hdm)Z~i_azfm{>KX8Wd|LDQ^YhYqIb&m-q_T z`o>m>$JgX{1uei=HAgOko&}ozzsQjf)3F|whtxDYq^9Z9G7dw**sAd~3R)-^k*6Aa zDD0FA28;w|f+~1Y{w93lzJ`9$B2oIbPLN_B)EfWdF$wj-gVYv@lp+gGf%9YwHAtN$ zUjp@$@?t-)XxbP&8bt7zLv>2A?|Ka!XvEv1fy0bJM2}7Mikg&#W|E01mLhKE5HkqL zj^E)CS@?&eWny|J)v>iyo_QCxTD45Pg|eC&w7`j3XYiL>Jt7i~=ODrlPa$fJM&7`$ z7*Mn-KZC31DM{msrzK6AT2(-fe7AW;Gz!$ZyvkAeDzNxaUd~qxsH$sSp0h?(r$7u+ zu2~75ZMxZFEIV?&7ngMVMVp6w{2vo>As|pGAfgH2mnhr$d9V0X(RBy*YN8{6=?I9X zmni$zTKo^L=)P{M=?Gvt0;1_9s@)RsiCh##{eAevsH+CjfhOsCWqlaY%JV@$%*pB|B5j^&Bsj<&dmm2%IXu^jsnx^DQdDk;Q9b+EKeo?F?lx-AGyf#mM2>S@fJ~>V2UZX-6_S! zx)`;5sp-*1lQ^%7g=2Ltkz(iz=3!#E2Z%5+tN|iS3||1D#XuP>EQUeu`d3vJ((o@VZPf`pKFuF_(%~$K8Mn;pLiRm5X>3E|(|2 zHp+EUmFp`mm-pMk<#MTymr-AC^`%zzwL)G%(xkns@Hg42tLwmu8>v-S!+|iWW}(y- zM=6gkQOhOb@yn%MPl@EI>P|50=}D_R6ot!^EqC4N5`XT80dE#HFv*5W3gTZB$$*!c z^gB$E9Lk2Zdb8+vflM|~&Qf;Mi9ceRRc|rjX)3W3vTg*MVEb0Zu=LHoLyFxv@IzZe zX_&2udCaasvf{OG^*C}hPquG$!$G#qjX4a`*2Gtc7T%lS$aa;p<(2}km|1`%*Qq4w z&GR(tzX=|lt5B5&6LNvtucI_3Zbg3Ducw@0VBF~x2F7h0vhAA&b$VNCwf)z4#Wd_R zYulJo;4LT7B{38d?0*{brMA~qtJunm(*!|uJq4+KDGAx6OT9NUe4N0rYaVfA3J=gF@Q@1z2k=#WLD zg4Hm_y2R$+r06h(5?n3UU*i&FKOJnnbhZo|>2$tR<@Fz(e}zu)9dAu;GP2fBSZ~Xo-0q436gzhn1#n zaO{TpMy^c7^i&%h*DNN3<7P-m8yxL8w!zWH*ak<+G4uU52FGzoE6m{dJrH3A$GXVg zzce^zBWjqzaUBq02FEXeFb$4}X4=ijFgTt8Rv8?B29!3{AhHdP^K6>OIoSF1emKG65r?}CtRXBRxjA#xC0*Ri6?{ON4k9wGG1A$R>|*cwwt z8;L9PVpt+%UcAdBi7+qTW{I;4w`o(-I}xN!jFfcB0h0}x7+*3F@nm9LX(DhASGf4K zi7_lUWMVWcjZKV2R9edS2I~YeF$SSlt%ppECy?7Rj5EvN$E28BODY#HJS{RY7Lk@1 zO-*4gH3c#;Qd4;1zikTX)QGkcmz(~hX7FDb6-fi}$BH@%8x=_vvQhB>bS_!p$f%et zKf8!?G-s2w@HLcN`iS1J7Lr$63kfu=g=GjZLRm_c|w%pedf zlJ0Ve`8+0!SjDE%lwC*lW>M%r924GG0;Xgh6Bfg=$U17pDbQwv_6q!)F(Hvs=HuUl zSa>L?QlfWJLqUi2ItEo86&?!K(nCQaGVAEeA=XfkLZbOq+X}gXnh>0kVvrtDPxgQZN2A+6x9TC8FlnrvD9}!;H5rJUw z<0g-|(A_UeW~nt5syea(v*o{J)_UwjV9UP(Mc8oOn}07vbrTKeN2uX^!ZbacPa!_5 zrG%e0P;^M4S=eg1`ZhhhPf^4BFW~3leF_c#o#FjRHN1ZV!92VlrH1#d!H$RbX+;e0 zM@0_r)5C`M+cMqAET)?F@IGuv?#nOnmq$$6i6Qx~9y(VdSH7$Zlkl5HECu3W4BQjW zdnmg+xOU}VjE2eicL(FnuSV;)7aWWy{{f11(bEQVT0JBmjkTMEOCHizdGa$b9*n#t zT=tB`-lsfS`F5A6dJePWD;kjo#KagxaeIj(wckWl8Y)pjX>YmIBolGPQ#qW%>n*oJ z9?uaxhxaUTgHg11bzL0y`WE6{KmhzTN8bxi`~nPbZ}fPxD&OG}8-PeX+n;)bdg6Nq z{m!5$>-Fg_v4d!;4=`x@1Y4(^<_%OjQlDVOjBO}E)GZjMuP{iPR*K3vjeu8yOS#(! z@HUX;GD?E`0wB}+8zFIb$7Zxfz^xSUoRLc0wCWjS5%4N-BjtX)Q|>W>YuAub8H*8~ zXCqSz48HL<2fZ|z@aLZ-Y|6K0*i9-dkS_)zEVTr^^%LJe=oP7#O&RqHdPn~SsU(sp z2L|04H$arWNp6vT@1xk_0BngoZ^l3%*TSFP5U)W%b{!g(aT}1s;K!4)%uHnv*epWe zlM0!V2zJ(!5aX?pQf-=%r}Y>x)4{&h6MvKr_e}|FH8I|D8JoZ{135+527^2Sccg{K z-|h*f?l&mncX;Zjo(xBHNJ$uNB)P-mhdi-YqA{=p$^3SJQhqUFd7I0iA_~|T!%x zkINglm9=B+faMsR${XQlYsXln4)2AZ)#2E1b$F{%ha(Zp>TtYLhp)oV>Tp64>TrCd zI-C@y4qG4t^f>A;TmIVLE4pA<(zPFHZ}rLVON-597XPp|4g(G|RVgywT-dcAk?=UH zYd;#F;LB2bfLC-QZbSYVHzrfuhB(}YXl~o^oq8181g-BBeZGwER1$W{=dmMJ z|p|HP9P4>Kw# zEgn|=q{R<{V={7x)XpDsio#kvEIw)R_zxTk*5Y--5gk&-gd_Z8qM^Iv=?@lvrTm8w zn9|CiAQhhR4RSCH$bY1_J^zK?uK%dk+i?K?iQZn2s){?L9268iy#1GV4Ow;o=&Hw{ z`TAq9-?bm<6*Z6!*L-2KXGK<6^Uzi=Z4K_H0?II!?-bF-!v5UxI(||zi*=d4ZL`N|_pj|{( zEWL}!A#TRR+46zi9`Qwpb`h;#NVXsQYoT@#4a0Xq?;;{l?;;{1wTmc&qSkm)mYC)h z^Km8`?Gqx-yibS#W1kQwuJ#FW;!nzX*mAY!#t1Qy{0%XYSBr^2LrgDYv(=m~5n>`5 z783!6m>f0@2!xovs_PYZ;Oj(UvSMj5ImFGFI9ndy<`H9YUsTJ)_ZE?u?53r})P!su zYO@uAT1-Tw#B>73*^`*+O+_oi5o07K;>=?WN`1Tv;6?yw7>J*WTxhg$T_2Ktg=; zn)ZpAse|&%~=9xq}13mW`-KMlKsw#n?+N8?n6lki4iz zl90g-P*2BMA3v7)$+^Wl<%)8`uxryrY|o?CxD~Vl+%e$Xl3^$yr@IW7T_abE#0+J4cXcWY^nSnv0X?!!rD(wDeQ ziX%Od?c$|pY^~`&oXB`=romn)Y4_nI(21wC&oJ>yC>ON9t<7m+n1ZuwXwhr+HgEfQi;!3x=&|3arOwA4NxWy2P69`tY55JcQ-v(-qv_gWxS~VwI zo~U5Mn%^TG8vG_i2V2!V0MDM^@YRk9wySyE^27!^*2(P*?Dqi~^$vnnXXc-3Rlv_y z0R66_4rA)Qlww>6NLRdY{e;03#}vuuItlSLe#%X_6rkcE*sX$(g0V>6FieQWvB=IJ zR*NcSiycXxavq4 zs3`a^D>z^VkM1YLZ2Z8JAc79g8siK<;hZNad9-=r! zHWv=DnhSgWO>?<&p_t~v0mU?z>c~_S5s2hUPII9`K&oyR2YW73@CQTf=Awf=X7I_0 zg`0~JdqtYvT&RHDT#Vpl!|mpxgZ(D+E-7|%(ZK;Tcxm6l&Bb6|p@`;U1h4N|xVbpN z74og-QZ~qf(wieyb9ogj?L8B!1?_Q!poQ@Xj(cQ;JCaEK2I#n3MCtX;NJ zoItQjE$jXWTf1;bFqp{Ng*{QhCZ=|2XKI&@rgrJ-XqS)vD5kk^KrziF8JUVA0+Br1 zX)aU+tURZMf?fMS}z7YA#iSEGXSv8hIzyZo$!heXeZWKl_m|S!guFq|AgK7yrh}=pab&38e^T4L?-Z{ zCtDsp>k+qN`qR5#&3}8+<5JkYguo z$?5l*U-Z7Q7{-drgpKJn}U`X}J?)^sa2 zjU^-h3CNZ&g6h#jMD=YOqM`{(B-NnEz8{4j%9Yu>0-%hUL7b98z)Ap(beKE8Eg)m3 zPNOI^QlPR%02m4&NX_MEi1 z#-BDH|AJdjn}@w=^$dUOO75&ONPCEl3p-Z=f7aLhC+AA6kPWwCh5BxAx|Q;mYMv^A zKl1BQJ^le@b^}&(EHy|~&T5b*oQ4`4I?`5yylWs^-hh}RDW+C~#l$@9#5|&7CPNKA zkIjyj8l;gQw>JWKL#k4P#8In328&aJd+~o~eM1cv;%959Fg3_iYNZAlRBDhwTMcH* z`=I@n7}}5i1ZV9>KvCL{@LKyZsI(u0VcO3R?U#DO(SAe`##n1Vhu@73KL(+F)MLc50-EHdPGS>3s_m;F+bI0m=@qlR9b*R zr3DB?L;RqQPn>#_`uDB(QvaqgUu6HzmSdp>_F${6Ts>t5QPD)AFx7SQJfa5n({yh` zW=8RVk$6>-ws?zAQj6D4tlM}7m3S#JNM;Sh+l$z;T~GRm zg2hYWhIkz&QyeB7N84I1Zo>)U@^cTH=Jw&25e9Y=(66;ioCV;&_z6BBvQ9cIT=IR7 zj2efNgH4+l2OP5kjA_Vdit(ujQvu<6^hHcVD5hoQiAKsX@=FhQ;bKzm{dsuG-xQZJ z2NaXCZ!=OR0xRXAT;?+#U+*?9QB2B{PKT$w=3p^p=73^So=GVaftB)lPWfw(&)2rt zl=Hp~PdWNfF)4FEF)3f7l!?GfIdv=5^S4Hs*P`&@^*sA*c*+xsOPK?TNqOo^NSO$% zl(%xq-x*~tobn4lgs1#YaVc{^F)9B*DH8#8kd`BHA?v$zA|W5C@0)>x*^DC?H)6cX zyL;>-7%Qytiv3slMW4E_AWYh4`SY=O-3gaDt{nD0a4-@$^qg0`LG%s&o}Pn2f9s!a z@dI|#)N91ncJ5|07E%96H=-{DsA>)MiVxqy*@UCil+QZ;B$K8I%|^{rpNVu(xp2@+ zvvEaHjnh=i{`88B>h#;!2RMjO@+ASrZ(m#_QkqQ?3ABIv!k(dQY=)tTNlrxLw=O4Q z5`p4*$yVFvv16sWE1_Y)w(_^NR?z*aPgDIiYurwXm^u%VrMwDE=y%k?;X_n#WkOd0 z)vN%cmgi86tCVg1=qspYiYbyuVHln)F_)?pm;nTvGdTEB3VuPh!$CgZ(2o7Ofm{_H z%-|)ngy2Kr>II%wDaD$> z2}6Wh$G^r3E@1}uX^A_Mai~+mwN`MP8N6V&5EGz>6Y5*R@lLQM{m-x)0n%?2u&tnN zt<_Y2&y6ho-tEJr|0Ob7r1UwU80p`%71AdHk-T`{bq;vU3NWO88^y>~ zZT|2!NS$I@I@OJ}znFv-MrB(IfBwgIh9_7Cy9J9(kOPWI@Wxk>AQ4yzroi$MNN5vd z_ig{N4>_G3l+9)_GV11tbU2{76=0;Zono|%;X%P>N{3=v>HLa0Mj)YGjNOX;15bpf zlT%ze98gR;mA4}uBETS?mDO!1PmH|i6sIkM@UQD9SSzGeO^M~YL&zxfCN8RL7cN2$ zkXC?^=+rN_A}C^CO_#pSh($S#!6k#(kRc` z8;dAt87m;NpygFTZ$+LsrbxcYDriNgpd7rB81E?j618X|rwSS`lP|e+Nh`}PJ9SBm zh%X%NAxlbK)Q3@{W#p|cr%LIFMYE{mT=8{IQVnIgWYo%z;YH4fmW%7O zKQhHJMe^WB+~O5XzvL8G&-F-#7V0?oX<|$$kvws_rkUz$Ms12J&Y|fFR5am5ax9p& zyaHyoSdtDASv$dm$Ih-6n)HCO?x&_$ayY`4(eEgnz9$I*nXL%33IGG zmM{oySu?f%Em28AoqEl?ng&eW7fEi`p;Wl8PyvGF7rdg0SB!BqlvAh81HzI zN#T0`H8e4bDJpcsD$OKp8IVW34lnDwaRT3sD)Ixb)7fh>RvxjR~MbP6G)@CmVMB1|j74QVEq`I**^qqH}kt zgps>H*t1Y#&?w^nEWrz4>*P83#uP}=w*t4JwREh;vmZ$DKK)5pds7eesZ5#xbf`^V zc(pyMwzEB|4sVajmZuQqG)1Y$0|6DK9z|DC>N!!a(NQKImEs!OrPYw$ZSXNOT2&FJ&vQq0*0MhPl&ygM$zp{uUxwxSSwNJc#r9p}7CyGGH!^UHw#5GNSKR`wNu^$MB8=&NDw{;?9!4H=y$Cj&7U zrHgIu`w(<^3YYb@Bp-GPAkw3{tn0ALmCKs#`;znR#a>@7>pVu7Wu5OEgViL+2XVNp zIlgnMtcb&9U7!(XK*42Q=*#3N?Lon1U1XIN2rlbmx~v zh5gH+Zy>w1T-Js1H!ApQRn8T%9TTm#i1wL8FEY_WSqp36v3so;lMq95dD|rTRC}6M z0QHxOx+po8tM3zeWl>cl{nY$fN+O>Hnd&D&GDhaJBu610tX<^*MQM9z~Wlv$E#U{}b?O};6RWZ=?Hp%6UeByoTR-66Qt#C{^ zi{~Z(d8C{pSu!tc4;Szi|7P@y9LY^(Y1n>(1vjB(# z0Coe2C14eRN&r^K*C6$*ij}e20&h``WnM#{I8UAKG)p2^K3+w4y05rSbLB5Uut3h3 zO@*a$)~`C<7Lc%HzV^qWSh=zn&W~d0e4`OZLBSIG)_>RS)K43Lf~EAGZd@gSU`c(? zlENvN++fB5%?;)^uD%s=dJMI^&w%E}(k?)P)GefLfEtx3ws43dtq+}qkCa;AhH+s38-Ee zTTKh9Z$S0JYk=VD=*L{lJ~bLa?arbX4rF#K0Fm_W1Db_8i1WWfRsdSdaHc7Q`?QB; zc)u#F!(Yc3W5yV(h|t!QJ!T%Jt7Q^<^YDFmFPHGEm7h`{V!t<)Cowsu)M3C>l*GRA z!Cdsp#33^3wJ|&?(WJpOI7)#@y!3_6jt4uG32gIEp=n*O9k+XE2h$k|U^Td^3uCagu_NxRS z5x3+!kJ#}paydaW@J2F-$X48Y*smFf4Q7d%JYJ#Q-gdb}+zoAn_`W`_A)Tma;C?f7 zSvph^+F9Zx9XH^FDw#Ohr6wif-n%-0@nj86n;@S!#4s(_&}pVS`K2TuhIjrlY;ajh|*;pS~?%#8v5 zD(Gfa<5i!CPrRKM`nXxCWj&`^O%FKD>W&!ItY*rnUC0wJN|?>6VXAIcv+ZVeE9Rq7 zAtHX4UdQa$=LDU#Uq1jco7KIswDhQ&)!jz3x+gAusBTt|+RZ8=kza``zr+MUKKm5| zNW@kDUN@^ncC(6L5Rt98aap=qJ!Us6JBEn62+JrptHpM+GD53n=w`LVZdP`vl8KXD z)vP9u*Uf6F-K^{wX0u`>)dMxF2OIdr4jTOwgf*)-S(E8zbwGQ#S-lmYPmXR@2Lm+5 z(;wnP+QZH2?EsDK^oRHzvst}sH!IeF$5~%dE91|JD@d(OE4Cj@#rBs{Y&PXr+#WUM z7nauBBxfgKGfg?@{SxZ$3O%%l3zE*)C5qP`9&eT8jet62`R z97>)QdPR;!UM@zZAbt7B%cIYF?A0H_YuE#E>%KFX`_6J+s^-3<7N(uPv%=^*D|O#_ zMn=6k8Lg7)+Uz^OjnaK*t=)H?J%YaT4iTTA*Jt+YdxCzkUl#$HednoIT0B>MXO+=+ zo{ZZ%T=$(#cHfCe~{c2JPUUgYJzlg53= zZe|~!qA&lu_LrY`<9`avX5lfwVPg#NUVQK&j7JkcmQk8f5)=(#akS^sP|I6G9y z#L2E|a3>~cW&MlY;OrP^aC1=uJO*GS)dMxS9+)e9MRSGBum(5LRBe;Aha24FprNd@ zf;2bK%6f|SaD$r~q&b1sfVY_qZkpZTSj*kZEzE9kk8=CdD(@ky^%XWO@Tsb^R55<>pK4A+0f=j-fxi~}RJh>V{thraQ z=5~U#27i+C@1XPKUc}&z^@3T>^;S7iAxE$CiHqG)u&rSgvdz>0ubLWQyQu+om>OWG zsR4GG8eq3sA+OmL!W!T}xCS_CCW-kf`O%1B5h`z!gIY{FOY{QUY;S zG9Fh%GLI2oemz0Zv-WE}C6nCz2dxFlSsc8P93pa-+`v);<*k)gpA$tSAGSU`xEK>( zV)RkJ8C=^^1ok>@zzJ58ak9*sAi1@r2`X6$2AwFTD&V41eUK^$KouM#Rd6b-<$b1m zKidmF*BgT3a*%4I5U{vI+Jj%gnRS+FTLNirCOq80HKhsF7g4ifEE8hzQm%IdXF+28;2x3)G zn%Ox)S{0OuqCu#G&XdvDY|5&jMwDUhsK#`t4^&7=sDk%sFi>V}6ztWef%yXb9-TJgg4%Jn7nel@0qk_T9$fL0a< zZzP9^yd__>`hRPyJNld`_|eZA2efhezg>8d+!#kQu`!^n6+7U>Rcq8p4!9Btyh#W zZ|iL~w`9AyasMBvo7*PY1rx3SO}IvKm$q!Vsb*G2X^%2+bFb6Gja$q#Mspf^!j;Z( zsC_FtHpe0_r$656dz<9j(1k&qnh`rSOcuA9U2mG%^=>!2-gL9;-C=gUJI$_lmzmGI zZCUVFcurW?d*vhQdYy{sdeR@+^*WnfuZz|7dZX)YoQ3ur+4Tx6L&;56dv?2KpF-Dr zg{b$?tH6G}PtZs9>l7ff>-99dUU#$W^^nPbTE>zgRzjZ0guWuq{Q8-o3-;>@C6qkF z`t+t+9K4YnBJ!4;YIVI)R!{IbQABdU>UwET*Ru;RlE+w|-dn8L0VlSSjgw{7^(I@N z-qBW+pcBRHdYlZ^2z5P)uD6`J-h!~^w$NpgF#@q*d)HgX)h>%9`*^|n}DPkm~t z;tZ1b#9O6p&oDkU%Cg~nYQ~xEeZ1A)r=Y#xH5ZL2vb~>3({s(~RwHt|Zu(z zJ~eYJ4&F!(5qV3#cB-CnK4>*RpA$tSpRwBeT&KO;g%`=UTc4VTtk?l3wvvsLW!2t0 zTA!MSttde!irL;d8LAO$7tk@*Y4eMyW9g5q;~cY&7g%+ii#jfq4Z%g$akf>*SOuY_ zKw4B7d>VCJfv9WItDgO8Mo=sJbt53Nj+dBq{FqtCi)C_etB#+x67obQ)Rj2%>t=$6 z*sqb4Q1X6Dr>(O%cq2JPiDK3)w0X612~WB9g~hi$-5L zHES1MB!8H$2a0E`*a0WDl8uvPRkIhYWuvoJl%Nv@HM`of8F4aHBSkHX4u#Q@H?(xu zn>>;`>GkFwKC)Zl?$^$Gy}2hNc(Ucn=Py|=9~m%nQ z2b6vEhL-(6@OpD!y~$$@5WL>pPjB+59!E=~HIO=QXc?|Iw2Wc&3qbRRmMp!Y<#!-> zL(84TZ^YP-FEwvyId7GmM5N z2q?I$fBMwg`e`7zte16J_XELYy`sxHSCti<_>1n-YwIGOM3B&3Pd3Z&MhtCVE2*|m zKudy1;>@r22>Q@|eM$)>r&%i%4J;1cNDdKsOMcv1s%Xf! zKjRDLbE1gkYujnl@paY?Zoe5k%v!8yWW^3R!AdqxmX#)0Wvx~;wxR@`D5fUhqEn4n zIzEeQ_6O%XUg+!nqxtndhp#v5_}`)9A9@_(imcf-*4O(_OL4kgHNHp9&L`?+^jc-V zHW0Mger*F}*6eTQ*ZUV!$Nwsmh4uAzTlM0JOlUW8=GR*U9kyQ|P(sN+S~VMGaqvcR zh{#*=A6CsqTY~mEQABdCRkJZp&Dw<*$)~KEjkRJ2oY+b>PL@^8`mL{b2`fs_iDK3) zCqp$N#AfxEU>=SU2}tQ}K=!b7>^6*V#d<@iM(Fkh5g45s3=BT zOg_6nOsYCesyE}|onlhW8@1J7QiGYa`w>hSZ86!zIqBvwv2yYwCEeW{^`m0)19^Kf zli9?C(H4^noRiTG6DudoB;6ZTXC)VhnT%y72Z#xyv4=QRONeJHxJ0KAT~R0bXV6X| zeNsVn7^|1>!*CI=4~>ISfS|pnx$;LKZp**~ZF(GW$1R)#JYoxN^qdt({Lk>ri6diZ z$_8v)x1QJs;sP(@2H3z?K&CWD6zhpii;JiIXukXuV6$SuaVCI>`(JO2yb*YQfV*pgC;S53-bg&`0^GSk{L2e)UqaNd3viDB5q1G? z)I?9%1-Ko~+wwCmz#R@OwO4ok7(i*?{N@nZ7vOqqnmFdMLT)TWL#lpAp`9N;0ypFu z7`+;k=K_TA<+tXcI(+$U*kw}I<+rDp(Y;_~Tz-pPl8k;IXybBO`|8<~$Yg3CJ{4c} zx&&M!yFykkOPPAk%2XH5l(XKjQ0nVrDSAqiX|z#QN2lv!!!EyS9G#)hPQ_UfE@&2r|i#j+$~v z6f_?_d~`COv_XxVZ(XJT4Efg8bvWaMID=l_EKokT87T6kI*vw`};nx`dk<)$2dKowTvHHrrgV{WhM@b)H0NOxR#+j zd-GE1+8UBbbQ5j zAB6k|S8R`AMxTLEn3kEz=;);$br?b`*#imZ$^JkXYNybJ)!6mV5w8XvXRM2)jG6s> zGJ>?WA)YDCv9@nL38ZbpE@>id6L!gx(l-C>j|38a z$8)VaOl{K^+UB_jNZULO`ADWWv<*eq+J-u;(}o6$*8 zfY>)nyY=|F@d*su4wTNrF^{?O@y0MX9Pk!{|fR$ zrD>GK3_SU-^alOg4#t~brZghG!quzW21xm4@TLW8c?4&)Aj-JIcO=^1fIE9V^`tV6S_m;%UZ0AMqbHTI!lQ~}wR(rJ6Vfc4Y=nG#tKg6I$6(wdi{ z3RO@4>#oX|@+M%?9x>?Ktcb}N3i@@xA^a7J*3t+cc$GU}&X@|!t8&H+3iTPGNnI$k zE}@54cQjB^3qR0V7ACD$z{p_ZtCXU?1<15bekWw`UHlWSJO6hevo<4Bu|zV?C`9*^ z(kk*(RE}dL1N{u1#Q*oY^F4^1A<<&vh|5uMsRST>CTJ@_Ufp}TGZGNG2L6oJ0Coe& z8Vlfn%`N>dq}z~$`)o|cVj_nBRp~xJ*_jY@674_MoAElrUk5IIAF|XHkp?7q)2|0& z3}75EnQ_fa9+64}lNL%b7f75knK1>(#qeis2k-;{JWt3Rw4UdPMGgGDeB4ZEd_u-= zpu7y+a=U+KHF()0qM|52267yb-&0QSwd9ZR{u8dv>V<%nz^#;KU6t$+q#vG;YSxTb z&;}7RonjsbrvIe687C2I5&T&t5lYe1DfR_~B4$PpAXPm-A4W(=`W+Vu9tC7<|U{mfig9Zfnl3`c=ataz~2CcV( z#seFE#qi61fA|fg%rz&HK$-$EeL`1C7} zNca?K>>`9@jx<8$<0}`>#N2+7~z%i~jWLp36C*80Q z=eNz1NjH>EgC=}Zis@c4^Dm!BYOf;EDAY#>;0?t1h=EQ3^m(YvtUWUe;)K5G z060{Yn!$;g_$R#obrh%Z5pX(-{|NghO}rl?-TsYy_!dvRfe0ECfoM!4$D1$&9aJ@2 z=3n-ThNqC=vLX_+Z_@0)oI;hvS1`zRxRStmvVT4cF?@Bj9DXvAFgWHwTWSMkVAfKAb zpgO3v8=r&Q$omwm=5lZ?yWLj%C=T;KWP9*LN`NyP#$VN0R0=-Hd@POg64k0AZYz#U z_cQUtA?y%YGcL`y)V*H>QFZ^>2;(8NlJ3J*SE_^272lyng5@(~3E(qh2`F@CEFo2q zhcl?oj3uz}9a>a2B)O`;NBoK2J9t_Vz4tHcM11PK-042SE-!9#gQwYvX^`ZrK(Jkd zk=s_};OBlZplT6Is4wf|y@ zOcVeAFQ&*la37}i@Dw@Bf6Y_-J5~RItI480Hobx5MVNb@P&*?xjQ_$zNuzecorU> zBbp5SlN^N=gC+z2aU_}y{Kt`KGVo6#-G!6Vt%oNARP0>T4^IY2!W+rMlYw^)T5B@k z&p!=p$|5sJPX_$?FH_L5yPYbD*OLK%{uK)Ek4bARgpR_^aCHup3cpxj?Db01&h|CH==i_JYv1}OK5lwq1iQp;)ge=GN| z7`Y#^m2?cAA;0LB`!@g&cl4}a6-MmQAJT}OE_jeWdK)8lzV(6U035DI?1UB1+NKE0 zM*2lxuUL;;CHil8X{Z#F@lBBV^u_7Ffg-GyQ$F0qg}d|Bq=Nj_9s^YL2QWLg6Sr6z}rEE%}JB(1a49b(hgsEw^3`(V@ zk$yzZpRAwu1{hgS|EEf1jXmWN!D=wkZ3j>WKw9ergQ8BAv;#m|&xp*ZtOr3@2Q+EZ zjWWV;n0Adxm=TlpAqqE;FfgJ)M+R zqq-vkG5}xqnMVu(E-U48kC+4??T{f0WeGk@_5F=qI3dUq>_x;V(4%6@QZ%!^l_gl! z_l%8mq?XU{%sSRB_?Xsqw0AK5YjW_Ea zM67oe65RrzDS(x7l}VC*by_#1YCZiks;9jRD(itIGi|Bihcz>tfwE|(U0>6Q1JiNZ z9D^sU#%a
lvUE^_)kT}|}JmmaZS;a190I9<_tU@s2uNdu~tE^I*l0)>k(AXojO z2m^9UAbX)WY32Y72ITFMMqMjq#IVb>J!c^55Jb&71Yk4)HIe5@09MLLMrmOp4(C3p zZq_11`5zN#4|exZ-ool*YR!LBACcOJt;}J%7FOo)Y~EceYXWjmbT&zyh3VaGQTBwL zzb$NNB9%^4Rk6daT>e;WdcZAS{S!9@|3DuHkzcuj8!+uh8?wdP{`I8XD}ADUb!8}e z1vU}GQ1m&xY?(>Afvzbq3`ON`_u|xEWhkOZ|G-eh%nBKbwt_DvXMYB8{aC;+hEyeP z>LP^*Ly-#N>`-YRwa0d0I*dW#R4PvYB2qzGN8QTTjss`POqmr~OXvHVVh3YomPE3R9P8`C5 z?L;gX%|lzkrPx5IYT}(blhW3t3jMC=$KLPv5SBD7M^r~$v`nm7*{Ta_`)m$rnaJHOHHh=D z8DwKf%X-9BG@gUY=x$3u)EW^Q`vd1Dy|QBL5JDq(XMqQ#qBEf-zK?3uMZ9BhGcrJ^eC{p2RI>gD8o#C1J6MA7X6+GOZdD zD2~GyS4^qj#4eJEz1dX@!=NERJOF6Wp$aaqA2&skOyXc*B)VF}<US~$dp=uh%VB=ND z3)}s#Qg;8^S1|fl3j=j1s%T8ctq{y=WcU992D-to(Cuerw^l#Ag&D53rYB3avM{${ zka}Ww22D-h$a^Ol)koB}ztPpkmQaTA5$S(x7$1)Tsbdpoh$K4rI&4_*(1(L&fYNst zrWR}%r;_l8g8=?;5K!pDK}c;FXHb1O2-IH-%9Q?w5QrrA-s}goBCXI+C!nDY zEWV+tAm%Wzs&1%0w5=R!TlFc=5pBy@Ub0K12=($3VV!1XEiaA6Btb7P5dn&PEf#EM zP}}PIw{5Gd)3y}IZHqy3!6sYQ!79mKqcPa4B$Qs!HKUi=)WwB%X}S+*&}annCnRGh}t2K4%hT2$$PNrYZ%VNk8F5NNNj z5D$3NN(y=OQVWA>spS#OAc&sVS12;68e18qq108eiZBYTu1O+g!BFpN6~WGDlSBfI zRfLLAQnygVBqt)NWA1lNlAMSP;v;f1R&q+6P%AkU%F8eW7%Mp(OReM(i2ObBmq#=^ zNh>);RJP56S8^;~{E0GFa+oO%#s+YQ%v38mj8!W+oYZ{z{S>#z+l12@OSuo=OD=u% zCUuY_FCN6zMWx&{jtGxR-$D+3ptGpSjycMewVs$)+ zSXJC#aV&Zpv8tG{s;F4Iq`SqN$N}7zQ!95Ay_LIRuyUWjMY$U%DtFVJ%6)ORayREF z_vK~EedSr@ZrP;Vtvi(a>VD;JKcd_nCzZSNta5kvXvz6`?HA?Wb49s(gCnS1w`7)4 z?!-FEozz^ple;T7YnXDUWGZ*+Oy%CTP`T5dR_^VuD0g~+a_{&^xp(GwaZ@^XWwSfF zE8WnrOOEdL9fyzZep$Ia0x6WA(LF0Ex7W4G?cGMX$$gaDXOwdLPE~HdIm*2$SGhN@ zRc`+s${p~watEGL?x5e5J2*I!(;HG*xkKwKcUVVuJKaY=9PN^w?x&y0;LaM^jQtO& z{CAo?K+(+^qud9xl{@!YN_sI^*eQJnupPr`NXBH~=+4ag@y-&H%ol@?aOUhka@fPN{uAy?*->BRT zgO&UIZOVONfpRx)Q0}HTmHXmpUO68&5T_hsK`=KIR9LG0f`|DyrFHMJkR z+qRwIdV95&qTA6)xjXwRch?x@zIL~AU!SMkJ^WLs@&uQ%I*6t zyOXbpt$;r({6uUQw7s<^^SEA0!2#lq4v&NKF?%1}+Z|$K9pe@!86qkgwd# zP0F2EpxjBHDtGdEDRnEmQ+u;&&$=y1`KPr|?(JQaJAH(5@1Q@H5bw@0 zn1RE+Yn;O0Jw>_qWGnaHWy+ngM!7S$EBC%b%Dq2o9H%?0j&dJpsodGUlshLyxewl< z+_^c*eQ33EANhU&%jwZw%Ab8yx$}Nf?t<9y%zt5mau?TUcj{E7qNd)~QTeASIZvJ5 zU-|FIQ0|>~DEF>MlzaDj<=*p#a_@a$E|q`kj8Bw*rU!N|`0x8&`R^}1fzqEkYZ4aw z;6AV|le*s2*$otaP7mciI9$1N?@;bTIm&%_wQ?WXrrby0Rc`hf<<1LaGXMEkD>tX7 zauzEyY?{LYrNuD`WvLD>`qs=c9oB+eQKp}RrodD;5Ryq zE*9-tW~md_nEngCdmg5VmBq9I(&M^jyJ-8kZlQP(Z*Fz`lk-2Y4;q`8JAVkbtYy9_gy+7JdX%z#H<5Yhg!|^AJ8AQOAQ(K<<~%9mW+={ynnFF6bW_ zl4R^FkZVD;SHpw}NwW0CQcHZFPXG5@9g=Uu^Cn^tZGrs03Qrq=E;=6Wo<44={W)!}YL#yg-g* zSka7U_$|J zp24^)P_>?D_^5>|AH~V;M0|f?>Mxl)!6A8$VG0e&+Sqzkz}yRPCMt1PDV1TELPPQi zq!f~M7^7enSHX&df>(1|eVFnKEGX5rdH)RaLILL|LL{q>O65@A( zBoVy9Wl@!~9Pz5*Lg50|35T%plrhV>%7_vTf-$5vLUIW-O@Z9b z7=l9#7ijzp?Cskt_cON_ImOdVsbG4uW^9hDRjND+?E-StKMV@cE`UQ4cPrpsi7^VU z!|*e}?~!L9U#cv+vo$2!afpI@GQ1Y}0{nMG?-7h480qkvFdhWK5e^Sl#Z z&XD|pDd{VUMuc~PEcFPzeVE|yl^p@2UinQJG$^J~vFL0126sqRH#HE0I#z+KF^_mG zVVJgvhU5Um-XrJZQ|R{;$Ue-Aa3MJf@4a#rKH(v`VivvcXAHpwvJP`1)leYwfZro8 zU;)+}D3H&wZ!msA_PYuseNhYK4#xcm3O^{wAhJhJ!G2E<(j-I29@!fkQ#}YH1I8ZN zjePM1l9oaa%0tqN|GE<@d%W%+OHs2U?W2lD4ei~BX367PZ= z-QpcSBrPPX!oOFZSWDDbGrSCN0pmlG;1J9=IEN?`pkKl)l~BqTk~cFc1>oBbxRJLC z-VJMbO3fSZ7SxXLXI-him`3Z<^H;Fv0|-_J5=%|B@(_P5@+WX+0LDDe zQn4;0$LJA^q2m+wO1jGz70K@kz=tH^LrfErt(cN7LdGbIX$UUR!W+V&^IxIRbcT}w z7f8Z~B*7usb0fVUP<$B9VfgA7iSjHk1@cM8&^^iE!*9ZbVFgqg<}1>f=(mHrXLEs*;d zrq5x4d=GF)u6vW-yO^Hf0y*gby_5L;8Pj}>(064tb$8GvzfIxiIEKZ$H zJqApHEOP_Ng5Z#>&M<|B_Om*6gUZil`&2>l~p|AKX#b-p69pw2<7qw=lBy&iQoeH z#Jlt!!S9kxGvj^2xLQzYm0~EtFyTXT;d}J1&KLzd_yQeDd=5y(tvgc^jF|_&hcQOM zV*q1piyVgJ3&)72ocmh!X)rl>2=eu!lPra!hs8)N zd0ByfY=|cIGV*eY^77d4UNOjp{}L|Cgp7}lyT$WBWLyBS6@VD>6bjAHAvvE4QPJgf z|AohF+*MJX>nU(V5rJ(G_$CEDTtr}R@g7FT>am0tJInpe1|dca!$80d<6i7+x7Ymy zCKRaiApCDgQu6Qfgj~?qvn~-;zz88SUo8;Wkpepv5!f1LiAGSwfhu>(n)&#ThlW0Y zMa^fhI-@_nBm^2-H`m6X$VI5WXvCoxx|>?n9~0Rh5FkN|B86;l?qduF^aM_;6t(< z-mz^ltcVm$Ka8_J#V(e37sh(0DdADfh+ycNuLv`hF>!zkWG3K{tite2h8J?E!aT|t zMY$629{D)&hCpVYB~H7Tmf!+e{%gX#%a~e#F(TyH*D?Gt!#{AS!klG{qPzrnk8F<_ zQ9NcgbZQ^wKW#|>1Y@lK9bv9z%ng7sQUx56of&Sn2wB5lmi%k;RoW7$utBP z$o4-HW+r2L11^wvGUZT)A7ywYhbl}iV-)3DhUqT*kle#G3a0DjL-Kvb5PU>_0XQ}k zXZ9&C>QA%-dS9H^UA-55O=!-dhQ1U?`ZM-T1U_DY)akWE`xd-SB4~XG>_&kfBQUZd zv_oJz1^!V)UTLRx!GpJIr|Q3l%K+Ej#{}X zS<=4_Y_c$x2(jY*>G;o)hw1xl^b<#DwNz#xgj>3n~Gp_i_L~}bE$T*Z2lj6 z*Bw|zvAuV0NdW?(h$!HViqb3~C`hl803xCw1mz}#aDyVopcpHth@dD5@*vVKh)PgF z#0H9zr%@wCv7mq&;uAGkvAiet-*?W=?48}aiAmr+RDSo5WagVbdv@lVnX_{;kPY2s zlMtvsj%qU-e4f}^LK3ps+gN{g5Q`fTJE0{)20H{Q-lf~0N96CZ3!HFr{U%S#tmy%9 z2HEx+4k(PNsK5MuWercQf2*yAr=cGEU2AwILb6fA=*}O8%(zY+>vyu%iIPmOpibMw z)kv1m4N=-)YS-V$qg={(N>#XP{gZ7KrVQp;W$*(&swvIc_-zxrsEoc8#nHEJWgOd2 zwxdt|-SqV7v2ov02KQTK@YA>YcAMyqWC;Ti<)`}gcGPic$4!XLqLEU+zpWjV!4p;) z&UP%PGR{Yoaz{Jd%J`RR$I$ve+S)-G6kBCD+u`qzGEx!6Id-*1NAklm8u-1#n^M2h znmgedcqy**UTgPGwR>-lc&VHf4OQA3$b05d(Z#mKc+KVXJ8GM_k7C_##fps3Uesn2 z0uwjHMQ4!!0{I>STYMWG)(2rfAnc?^qr*BQ(?;ju9OF|kqK6ahk2My7?Gf1WdQdxO zU!9^#{7Hq;i*HUQb!Dyzw_t4BUz_@o3Q4#X-XGXIlf2X6ErnNqCE^hG0SdegfuA@6 zYoVhyQs9h4Jx#pI|8}JL4QXVonTh7wDq$AzP7SFVwA4zt1Kx8Y-aFwviDx_xoel3- zI6;w-?}GQUI+pitcpEjgymR19s7pRy{Lqw7!mGiWEJ-kyz`SR@5}Js$honQyaMk^ye?8mUWK=7M4~ps`*kF% zE#!^J%vN~6i)6J8-gt+pVXoL#`EBUxzPLEujAbbi+F!h3+dOx06As(%3VJa!(yx3bC-Y+<> z$T4pma*p^CZN54-UlW_J8EE|nJBZu|cFOac*bj01odEt1EifEj;co}pB;SDrQnO{n zf|Thx(3xO90gJHz$MFcpX$k-Rg%Q%S>p+XrPIMsjK(Qd8SbPdyd+bb~Nq>($mP+mi zcZq0^P#hJooBnQQcdF6LyKQ6LwqUu|kk(IE%c+?kU`oa$z zN!FsOSVUI2`i7*w`B*F>+m6K|vf-$2Ch8k!ILhH3r)?%|vAs)ep&g)N5m|U)6Z1R5 zY00G@Xy`ls`u@JY_ipZ;o7?63RA<%n3ci;rB6UF(KIF+Lv3$i*CIvoPJ%>Db-G+lI$*FA2nyF#TPFn9w}nRCEdk zv1T{n#p3?1^!FAb3CICwevFVCJM!HKA#I6b@jl~( z6pJRU>2Iy>6iV(A@e_xdc+600FNIg?qcjn2n=nP^b!_L(tR}SMZ%~R9S{>|x|{>KUlO^!^|TQmrH%L~?GVJo zV8m(3{i1li5B<%@;P#?e%R?NQE5Hc@HvURP-Sep*OoaYI(SSowW}MucB|>hTivY*w zTz|@8Ajcs$lo1%Azr~E>tos~_Gl}Dnd$UByjeQ}`hdv>|&N{~-_hw-t^cVZ_jBiV( znr|3LNYB9({{_a$y;&mU#=O9Jo_;RH`Gn(;d$TYR`diF6hC(P(m55rysO{w5ED>@; zW*EQxJaT_Olwx*dgxs4YLhfS5(c9-!oRJ)d+?ypr?qbG^#nxdI=LU{L?#&V*H-=Qk zPr8uYJBHKWhw&HB>u7qXMqx545$idQ>88JUk48|Q+ZiYKW{Hp+`+~rWS(^tEeiFsc zxrlJ%0%|q6akLCK^o>k>Bq4Oyb%|)famZaP+OgX}XtDUuDEixn5z`&PaT>#+1&Fy> z(BBgI*Bm8sIhBcDg_tGc4o1k02?qD$m59ZRkbAR4$X(2Mv7k>5N<oce5K_#O2raz5b-^7j-m5k`U=kc z!pAJ+~Hcp-)N0Xpi{*IG<5Mxei2P&Xqpr ztsvKVJ}p<%gG%kE5B#!W#XAGC^*k-Rw$O6RVscVFm8ms?8pC&Zdh(cDHDa= zI30s^WwG~R&ndA%+(W06HIXa7K=g(j0#W@lYPRyEyTvi}a^ zU3c^}I9=YMw@_=$I@&u#-vE2UCnQ2S<5l$zdBZz@QvUI$Kn~N=QOM>xq2Ax&b%UQ? zYftz>>GFot;mX{Nw{MGIo!RM6%2Td=Jo!^E(G;UV;4bsPvoSy`g(i0KGqEe)FZv8(tw@zVKSO za$Z8T=g83?(!3dt^m6=Bzr@+`j>~fIiuXsDYtHB23u6~0N`kbgA6};J!H@N3<;Ncr z`UnNp8i%$l(W0JtY^_i|Jq^r9 z&|nOZ=191596mk!rE!I^ixK;Bl&w!1VU)xIzm)`jrMMY>7I^lr68`@PqwHv?On*c# z>4&08zn}1R;a>Kd6cH z9LGdT{*__}8evYPDqKyZrG zNEboD!J0_lLG`tXbl_Da<)(JfS5;bp_Wy^__qm+ro6FHrnNX=s9 zM0yMQ*_udYj!#ZT^c7Z)8{o1}p`_SaDz;O!%`VZ@6#5&gEn+CLZ3=xGMOstnKdEV@ zBKc17)D%ko@mE6vcVaA{DKvx^jRe}9nwChHH~bJ>nJ41UenjLc z^d7{d7s`w|z>0YxTsd74m<~tq0c~WBOre{An$zQEnsz2?k*q0nh7~8DgEQA7zqqk- z3f+VP=*=-p-y>b#@E6kM5B~^P&gY001Ifx6Z~(gcaHO}#ANAuY)ON+BeF|-fL?=+9 z33?)$Lf_G9j5+m~j4~|-X3pRy%}*0%Mu7%ko^(!+Xa_D7;rY?$K0n5zGLiW)y*8v% z{b+s+o~8qGQj87vCDeYeCQph>^w=~hUZn#(DaK|BRe(`6C6eCP& zl~|6%=EO*u>mdz)bWD!_5(#}hKi9*{ay|C@%=TjKYSibb1{ zW-QvQ#N@FKz>BN_z6U#EKBM>9n7rQs$amz>XX^S|>?;Jwdvz`ld|{5cSBP~Su3_Ha z329Hq9^>FGxKU>+sg>hKp4Z_vZ{+FNWiynpdf?Asx^ZJ5?IX(CT!vJuMf*2Izs`aj zZ;IdXxZ!w9G#by2w?z^hd7{NjxYTEdDx5YO_lV<;@frQ7@O&yflDA&gQtqI^`qrk?24XTOimhg(Bt&j`@+`sHGyO5uyyRqEI>JoDwtB z^Er;jut`BGN~L1zw}_Z+MLd)GvQ(@fbcPeXi`JxzEtFUwDo=8?r3FCt{2;XRh z(?SnmBwQ)nl16&iVYvBZf9XJ$efb%tT=6$N+|X#3+_G`v9cgpV$h2rTzBoo<*0 znLMTyOA{#&6A@+lvmB)dSg5qw#P&6pduA%cAMScOj599x^aFA)w%d)3Sd9b*dw+t~ z%tG-XHYdpJK;T?&-RxK}3^vJ`;w77xbHx>P5HipkL_b8{TF#{RX~^_!FF)kqCE7?9 zNb#PKaXDTq^%I3{LQkQpw*kwf6NaR*{2~tz?FZ_5h!AQ6#!Y7kONHYQAyNxEIWP|4 z$$^o1G+No&tXoQG1Zr>^fXw|6*r9~(6>*_kfck+h6>kGpzl6I7FBRPYt6#$1Bgh#% z9WS{0p&O(7WexJP`X$ROdw8fEsC&PhfTwj>`em9~x0KKj)WGVO0z#=@t^->2eo4>N z`U;ZRD*bvpaCUID4h;1Qwvw|J#U(!Li=X@oLQBZA(Rb?P58x>?J$*9+c%2TIp4iZ` zUxd*CK&Tki>jg*VcZi#qVHp0-B0jVg!EqG4AHfab7{3wEs}+LlO^*#7Kn6g(V%MpAGath#d%Jeh*8Lhv*=%%62m z6>&5VnSrT+iKZiYKE}R9_;xpd`{SVXJHcao%-`*mice0#h_e`gIqu3atL#*u>zwGT zcK|K1(6`{iSV1@yO4a^a<7%OgNXTj!iN(zTWLm&R@htYS16f|0i)lJaqz#t91aB)$VdSrK2Zdki zr9)Nn$DMdN{Fix2k71!0kD8~o0C2Il1p~JL;A@gXoa0sL zmmF+2cpUOJN;6U@aTUxSXKu%^G;|zVI?-Eq{4R_c+3++^tDEs0jVSWh`~qBbZqVDM zfbM5yG_&~|g*KzRPXq?@gQs!Oc*-J=vb&%K*c-65^81(=YA(|l6{le|RNGO7C#GZFg=Z$c=>0}nbNlX|ZeQ0lo*3!qx(*=@3w*WsI3wo4^-o{HssfIK^x31mtXy6)e1G^Pbw#`wCww2{CaD&$y@_6wnE5OATo--fN z5I{LEz%d$*;ICS$gl38UjOR6=ODAu}b-KU3HTyiiOSB{I=C5BtcN?N47prN zb+gGx!f}aMY4OmookZ>?Z*3kL_QO-7p`nh?ZD>dwuMG|D$m23Jv~ecISZSk?H+zNs zIf6>26O~jyqLb-FC)E!?-yl&+^#ee9Oc=U|SCUJFiC6}SSgIe9OEVI&OEVJD%M7BI z>IaHx#vzVr#vziKCWv7MiD9ZAu}m{6(M&Tc@ysCcO!Z@~IUYU0Tr(Mt2-iHqdf`6R z3)5}AkeYOj`G`_Ct8CZV9M}%vxI42dJI*A<+1SUA_N5AoAf5hsGq-G|kV1MFn5!?RE0Ag$w^l!5` z1%LO5eNW;lONxCfV#iQOLUY`oO@WO;Kg{%JApN9m@WxIVfoPNRaHt$R4<&%@Kvq5(?w!1Uygp z(U*yZQt9Bflc3(P%G5I`6(!w~_ytE|UKb2kQQA`TKDMIpGNVkqi{VnljKNdoOH|20 zx0p{Nj@V-sd3lv&It}Q>${!zEpL&;p{hRNw-OF_RenHYvARfcH0TbQ(#l?7zyoqu( zZjuT-!1uDqy_N?B?X}o94jvROqBd0OBR6Z~pfeUQ*clxj8U)mRocwFR)UyP9LQMg`$3BIjvUF(cdF4+k!R! zYi&HnDmXBn!U)h)(&Y)iC|%z0cIonkKaehe_%padYmxK^3B`teTg^=3!u8<_O+nys zaO6yD>oMBGk$LyE!dRb+$?N2)oo`~PAMTK0kyW44$olSDk1?n6 zC1_#P5>!Lv60|UC0azHd04(&(!+ViB{<^5j@V@Acz>6G9&^~_060{Zo+Y+=0Lq5NC zRa=5m4Gzx|Gz~SkEkSPpaA=pHrRa;l;Sw|%^v_y?W)T;x$r7{}-5tFIok`iLC1@de zTzKZcoJr*pw1_IEmY_S~kxS71a7Hgd<3fl{OHd<5TY@G5u`0&~B)dwMye9 zXlH7LT7nLx%3Dj&EHfw}l&Uvynrh$-djoUU!GBnnprv}_{-R6JU(g1}5;QMXEcuq4Gl4IZbL&{ zmNqoBB9F_^(88JYh+BfDp$B*g+6Rs!b_u#z^}SMa4~e99WOznN!iR> zJ;p0DDm@oi9YxACM3S=AQKW2j6e(NnxsOQM&nS_9k;*VBYcL%o#X-ut#Y<8amgfRK z08Gjh@C-VENm)3m2H~h0gt-P9DVyy)7s$7c0pz*Bd<&500{1%31r|Ea1r|BZ1s2P5 zfmGC-N!eZUTwn?SCS?WsxxgLzxxgI#Tp-WoT;LAdxxh~JMKwv;{FFz?gv8%RtJ0LUz`&jdOwjpbZXEc1LYV z%ASIwW~8hUQZgy)1xJlY*+e9)HYv*^QIVvq5bm6}kxQkdtcXPJQF$&<22YKK2BVJK z&|qAu4Gl@;aTywpb0&3?vUPv=bAeR!0F$zAa8yLf{`S2vU-d$+truKKS*sjL%ILy` z-^O6eF~Wn?PFeH2JjU;pld^SDq)bC3DO(psiPl9?qII5eM9T6|q8lk&3H*#%c4dvT z5*(!LH?-MC%ANpF4N^umI6S26LNvuj%CZ3*T2l5V`r>a$$~t2}v`E=V8Xapw%IM4@ znv~`0BX2_}arHUz1RsxSCWo2+ild=O8n@HLB$j;&{iTHwqNm+xse?n5$ z4wbT#vR0_CMap_n!;iwrYtBaIO%DTW&BT_aV39C)YW|F8#Qnn24oY#;`rKD^0N>Wxx6;q_F2p&nwcETA=%Jx%iB4uA8JBzc#T`oykod$nGQq~5QvXinT)Yl?q zovHE`DI01AC4`cZ%4%SiYT#A&2Iee-|FDv>t$O4BqNMCIw825jZfYn=*+X#DjFiP8 zC6ls_aMXyDr6FOpN!c_K6-mkp;La&QE|rq9wIp(ilx>HnMnl8*C?2zr1?Svxq6SWV=86UT`60XI&*p8GRaE0Vx}>%wt?pIVsy1 zMancplCq6aq-0Hb*%~*|%u3jg%Dvs0Jyc8XO){ zmW-y@NZB|5hnAGRjK26AlCoA95G_)cOrv8>NZBLk?&y&>i?UNA@5~BD-p$UWl9Vl@ ziYZdI9v(@`w!;}s%E~D=k+O1RXK@w-_d@VaSxnSs{s>B4s7;)M#k<3dKYZ4ds-b8XDqojgcEEtJB1h z^oS#6$>;$lWo_U%VoBL_)eGZoz2HL1x?e3x85uyWfRw$z3b(pdPRfd+NSTI6QdSg2 z%8H^$S&^q0^+-MMA$L+X9{2|iQg*{Jl9VmrIuwY00GO01;68K$ld=U|g933fV(`@` z3%CLWA`SrGe6oPcCrVZ(`0MSB-l6=NIDL9v2R3K}&si#FrRKNj&s%`}7JZYYVkULY ziY!3toW1DKIV*PPoW11GIeVFP&gd(k*woKahgZC0Aea0x_3)`>pu|gdt`~|TG?Y2q z3tYfLu@LPVgfr>DtDM6A4S7*bbjAL8FuGzdR9jap2?JeVv(y#qMWbF#$ktQnhUgJB zjj~fC>a+?*)VG~UCD|&Vif!?l-;l3`N0O})I3?NI8qpOiquAR(w!TGn78f}{$>Tk$vKu{HmO{4`X`PPP)SL@QpCx?-*1iIA;cW>7+CFj83!97%Dg zfw}eu=G+heVI^DJ^~TxB*6RnMEB2N*;g7x{-~7kAV*CGCSM1-=75fTpaFDHAno6>@ z29BDMtvX1_WUDhAH6mN%kg(chE1N`x$yU@iVuAlzy`eMV-15CI&!ch_7`rG%y-KrO|ZM~4% z;c=75qz-&aI+CYI!bLXbr{GZB{z0U~$ysK|PlC6M#sxxjpUezF7ughu z)c}~0%;0Z?3&b1%{L!!pL_QjRSN~{um-*4K?H0D3!W;F`@Ykq-_0e$No${mM)+odM zqu~sM9F~uU3(dNvg!Z8Z)YG^bc5Ya)psueb?>|15pr1iZolfgwzv@0>bp2dAotxxK&$b= z^{M*z)w@N@blVr$?*XuVf&IRy7x@BPnc}f7G&A;@?+Knm?3er@ceuW%jNgsrs21Nm zI7<-km3Lk-GrmLg!)wKeC(PXVPJTNW@rIck&*m415nq_^hPq1(M5+RDD>CL+>h4I! zF=2kE=0uR#Fkd;9C-U3NqT<4QrBuG4E2KE%_%L581)~WHsTDqvu9dn+kalE&cn?MK z>pYKZvrsG=gAaFbS!kf0=c;x@=63+Nz8<8ogNIrfq??P>FL0u#k^OoSzGlW2rKRW8 z=qQ=@-YSeF^dgFB7&?l|1dwq${-_^)VBP@%6M<<{@A-gcQ{4A&(cS`$);H*>cgcKQ9AQ;NwD#?y^|Z+wSc`*uci$MSUu0Ne8Qk!FtN zYdgfSEngb|kjqyp|F61y-He9Xmaq4tU4QB2tAX3Xt>tSHJT>B{Md*fTe%gz&Q~WfI zJTCmS)R|N+UvsHqYWbQ6k6gYM!Wq4MEuz@8eEkL4S*yF9l#Et)#~$}5T)uWjrR>Ys z{nQGze2v5X^^xUk5_||s2#r80tAU*<4mI!=djoUUz<*emue&55+UcUB#&FF?`!j(kXsS&jod0a-+a%WOWxJDwrMYyuzk%Vg|oY9198O0{T6?1~dN7hp^ z;v+49{^`yO`k+#F!nK`Rp$JzwRo+t0Fs|kx+&QZ^unACZ;B0#XbJoLuSP9o&y>Wk0 z!sR(Jig3*bWZpRoN6iRV5>hhZ8VpB`2v;r=R-16OBT@N7!c~T>b;6ZQVy6gK7Cbc? z9_qAk8y;p-c4~MiB#+DR(8ihch$CF%(F07llHoXF3DNxvhG4m-0Hd;rwMC# zUo+3V#Qsr1m)M)eX##6`V=~WVAdm45Da`fI9_BjU!^|`3%;Pcx-V=R-_eApqvy>-! zJ2X!)MR|&MLi0?L^t7N_&K11hc|g#9Cu~;ShKnjeiSSoU`r$WW^z1;fCe?$j)1Dpb z)9sa|Voyg@J!`9KIbXr*;Cy!=^gOUnvu{j$1RYP7oNt@d5&7yQ$@vsegy+DVZyU4D z0T&ypN7|7K)Jocyqdz1m*(Z?oaU1S8a36POj}E zGX`_bPOjsl4d_fd+bN=v&hPV%C+j*p;UUX9J~Y8Pm)H-GFM=Hm)cssy212TEE|GM| zE$hTh;ku=S((vG{bBR`j(wWXepjAJYu%GF~_~Jq@BR!w#d<%zprem|N5bLXfb%i+J zL0DIa_f^-rLN9bipsvrfu8;;#ji$0SBvh9=tt(8U?9^1Yj65z=*;Z##$#mCK#p?M? z&6w@*NTyp3r)0W`KFhj-aSdYE_a%frLw45ATN9v61mjx$37PK6sFa=Qwxd=w@R`;X zlBx0*(@isj5<>lu%4%S)YGAg#fjNueKdel*L~op(={EE=sIhg0#y&Ue3Us@&`UM*M z;=>}5ZdZmO61qG&r(J9FTI3*Ii>!WhHL~+YWbK^l6V(4uU4+~K<;#nZ9hM;K`rIr* z*sQG_>x&P~LB*RU8flRUov6JfaV9ceNWD8OQW>fHs7 z2=$H}!mG=^twZ?KUw4=ympX&^7yUjLiQr~!7O-)u5>T7k#BXY|xyw()*#o^sp9@|F z(==gXaJ9(`qXWx#3gfbVV0W$FQT(k3T$AWx`!kw&&PSwTF#-|xh^OWV<3@^lfh{U5 zW1U9@T*w7*wx5WU0c_8fRh#M?c| zs9C4)L5((8rSv`*=}N_DLSJ{HH{)^{@v()Hy=sVWPY| zYJ0XSh9oC|tu7R+PQyL;KZ6gS>%Ecbt289JxDyduX-KjV{TmtBS)IvdNV3oM+N9uS zNOA+JYSG>87#5iBeh1W@?w$%kt^(aX^oAtM&AO$8Mxh24-8HV2boVx()u6jsdcU|C zl6(yLS^d(4N+Ej?p96L8my__c4oknZGwYTTIv+K#`XyQQ%Z)&*-Y@BE=zWzxHY8bW z2hI-uM+eA|ZB@Y>rJQt0rivp zNP$J&#Q@lBqHH!YgkZ~TWZZSq zY-CRa^SFKwg5Ab-OS$T9DH_%QpF9L3oiZC)Dt2FtG3Ax_)CeX=rME8u`hgRD{~tiV zv(Vq*!e|&clSb7a=Oe7%`zjv_lcpliLpY)xzkr6ulkr!aWku@^mkcWtbfPLIv7z-n z?cg>It+Nv;*HHo4R!T0sR197ZbcTiAJebBrHWj&BY2-A zInmFl-8*ckWhzpduP>o`9I&EzKj0RuLf4dvWNKX_Am&a4w=OactHZLh5#dq{#hM{U z8jD$rOoXK&N9SO?!eb%wu&f$}93P=d(l1gOJ}i3?_`-W=Qg{nfT4Yjq5yGQ4)*YWX zIO~qzpyvD;w6gA)fV%OnPSBgrQ&n34d`9MC?y)kXj^`uiKm7VR{rOMiv%uqkrN|cc zFLeIwRvv$wCXDSEh1kS~4{t#^JjCnEX)usKw({5(f$B%(e1Og02*w>pF*2T0Ue9!X zsiW@^%9+I6%^64`b9QjfxR9plxo2sy2>UB@fX28U9U_bhqFb~+q2J7c>Gx$+s? z1~_VT#`ZB1R{M-?KZ%O`06Ojld;oneT2SE!&@>n%Ay$BlYS3WN8J>e542DuJ7qqC( zU~q)lFkFDA!u0Q2I3o1#2xIjZ6!+vkKo>ie9#kfXJT%f^WwFXCPS>b{5*D6k5PxI=H$Z>Cwdl+Ym5 zz*@vDBb3f^t^r#0MO?6`n`YGSIdNiW1=8;T7;KTDbQi#Y`kE43aTn8W;H zCp@MC(RG}BILiFuj{umO-Y+_W#zh{E!~7!cPy}tuZ8!6aqmY~Rq*|#bbq`SYC$$YB zhviB2Qcvn=NRjoVMye;(7iiU=RC@np?MadO#nC!YMe~cl(v$se6wI7<_e%4N4W-Ky zPLeKf_*Cigg}X?XKRf`g&<-TMP(rccbm@uGp}y9_u@_a|S~!k0gAzh_>J7|R4Sd?(z?_fZKdcMKdS`2m z`-?6dPemIX3&(!~V&%*);i%cdaS&4S!tok7YP4`%frQmwIL;(dkqgIVaOc$S@&^mY z^(1m?;kX^1gI_q7Q!f9%aD5vDVP;Bfp=zmwXCTA|^1D!g#)1jiA(aLiY|Fxl1% zl`R~rVu-Q+zdgq8%IVqaD0-$LlAcw=5aV=|=tj>L0k1QU_Vv%}s?)Rf@G(6L%WeE0 z(E&`)6!0hjrf1bN#wh98Z0ElI9Is}x>nC*k6VkJ`sFa
Rna6;P&UtMP;__RL%n8DOSn1iFsDRbDzbHLhg*G_oS@+(Oo=t$GX7ub8hV)RkC~b2A&G< zo;?mngqR#*BsHOr?1iswy-*oFtBP^P^Wwb5z{=^_(^2$HLnJ+`hH=IhP$K^vhnu^A z-^BE63z{0CXRG0}(X*=o*yveX0M(#p%0T0vfS&C`&299|-`7FUP6SXBdX|Emj|6(w z4#THK&yo+xh@4ja5t->(E>%U*vpjetJu8GWdiSh|V$<%~Wq86CJ=;miX!mRuP>sF( zIkaL|qEZ%v;ls`S)Cxt<;%?FDSrU8*N(jBAH?T9sp$2|qZ(vUIeutT!rJw><2mfK+ zJ&R4&8uu5aXD6Wz4tll$5Yw}d;i%c}Szn}NdUgdIHKJ#Wkg(eHteiwe(lcW^=$SX= z59nDF#IopFJ9rMBo+VQ*|4+{&9xsnuTuk7QOm;grluGts!8V$+q&&*BkS z8((p^NoKVR=%0>R{eVi@nN&;k*hFLHYGYM2(fBml;9ypRa488ht83t>8ME4fT$x!3 zWKkn#bt)28n^{dGQDJ6PnTf`KAZy+Y!=(%~AQX_;(Ur?IAgqPw;Mr9P<#I6W>Thq3 za1R~=v#Wo?Q4zcP+xJ3K+@r(2@T;vCQcGHxWF>V^OX>JSql_=%E}sI?GEMRlWt8#w zbh+^|gTLY~5MBV%C?kD2Tp&J168@BUhT~IWhfzlUl-Tysx0_MM{>aVxlz7@~`O)`O zpzfa%Z$QXl`INZ8tXoQ`CpyIXlz1(n^wIZaK&$>KvHhcOGRn9B>G`AY7vbQKzU`l3 zyBTHt5K*nZD^Y#dbZkX^Hyj~{rSHhdAwK3$3EhkuSbcXu_1$WqRqwm>)Ag^e$ta`k zyKFMbX!|a^21Xe_<9Fi+R7)CVq_6Ge{Z)s+DB~_ITzq!kY=a48e27r>>#aUJZ!!Z(uG9pBK0AL2dEIJaRWZt_zD#$q#b}vnti&i| zyEb0q+sc=y#ZgOC4UtRKY8Yi)ffD)WQ1EyLcxzlhrY}(&4sk3|-@{a5TcVx~z_vtv z4uEZm8U|32QO3W}67?c9!?r|ikG}a!FHy^gk*X!?fkVPb6K7PLk@6C?71CKt)L!t& zCF)2xqnD`J6q}Z)=i(7qOVpW^j5hx-1FEgy{v5g)vrs8(6~~+Z%cvE~D$shWytPE# zZU!ZUR_YBbR}Fm2-oTvS;XkZP)VAkojr)r(QB%+c#}f4eK)ghaA6nBTY6w~I67?Q9 zYP3Y%goM>zq8c#s`^QVvmS~o~L~Vjp))KWHJO{r-O{QG_e~DVj0l<}b2)sDE0FEPe ziMm?#!W>&KxGYhtVtDbk4ql@TF5;==F4y<-(QAx#kg5l8 z!#k^FsBQks0oX{@7IcD*RGo(yHd56dKt+ZZ6{-5dx$j@@-1mRqx$pnKHoUkG4YiS~ z7tyZ2G^t9XF;tPN+(R;k=2d?THTV6gDqGaPKRjyRAI@k}wVz@WsoH}_V3Ddg7?5I8 z^()Xn9jR(MOyeC)s*+G&i&S-{%3Gvrs2P+HIvc6124<-SW&+h3n3E6xVI@`1>5cn~ zlB)O61_!CS;sQyk7Qs=oeg7YkE0d~|kVTD1)%i$RZBjLjMCA|n{WlKRuY+`(yFu>+as`C>0@ z;3SucF}QS6Sy-f~(!ydcT~O)R8+!-WP>uzm)c3~T7%pktHmSaGCjh2#3b+K_&NNQh zQoI~7Y_=5715kl2Me~ZFs@YN`J&uLqdK71~rMP;8WLL_T;=cjdY$=|85w7+mQ4d(i`f-B&D28k)W*|Ku#ms@jJc{{C*-~Vs6?6vMQe>qScn*H9%A;JWH&>bD zm8znwCl6a9IsvH0?fx7)g14hm_8q|_)Hk54 zCw8XFN64!gln{DAZ(x>c;2ZV^=KKo(VI{AvM{13;lhE$t(yhko$JP@a7aD5^N&}GQP~BrZ8F|Tjj19ZJ1-70TrC<|f zJ#im0Afb-7o_N$Kn_%ZWhnV!-`4yT*(xI#;7LezEX+5zwsumG%vYxn>WLQ~GETQ@+ z>xpILQPvX=kcVluX+1HK?x7~@i8MmBBM(_mq!B6^o`WBu(kPeejZpS)+yD0V5^uz# zg!2cC<`*aL}vR99fQ*Y_1ud|9&Diz zmnU2Xm!*O2(!kG=!;?1q4zhpT8~90ERJv)3YT(IWVQBVxLfhNX67kLw12!e-Z>e|> zf5in>j0tc}B3otyI(4TfsiF;nUWmBPiq`m2hyX?F{LXlUAfJH)5MhxO;X$~N__cG$ zdWzxPbcz+N|6`7~wcG~r%1980n zBsN;U9Udauk0Te0XqN+ILl-{-btl?qW>tx3#~pH`<;LAoZzml!u!wdNp+vM70j)aG zj?Bpm#Vbh3)-qf8Yqy44Wg;F?XJi{_;U6$Le}cyt2~Xla-)X_)Fk7l0fM)6W=vwtl z+!0#`sgsd9mr|ePuN4wVeF=c^SKv<`&;gy#qW8fUo({msXa;dozX6>ag#w6gv%j03 zNActj6&jM>0?H-o2cT!>$%s*CR`-lds$mgT_aoQZ8TKirrC+3fpf_QouWvAr8L1O& zF~*|4xZ=1M(BOAkTtCb%nn4W_l(A8}{TQ|v%@DG=m?p^JV(@M)oQy7-5!^3M?v7q? zn-A19kUSqlHCt6Y!S6DFoC4uLc9HFvhTbu$GQ}_1R({DC@q~FTy_MgxJi%|+R(``c z*cawkY^!f7-sRMp$eMqVVI5C1CL9Jnb+H=L%{RIpo-G&lj(np>qghH(+!^IVd1pw9@gID?;ADQ~4SG;rGZ5Sm^^FPL)VR-V}HuoUBlYf)+C-!Ur ze=q+w>96x+ZTNfp2jjq(hlu0)V`1Kh{R_pZsN@cO&JyV0e-8;3iWC4HvH*1T(%~cUu37qa9gr{nF!oLw3Og>MO+|&Ku(6wmHFo2;a;RwQ! zVZI@$ z8)Wj-<8L>S7fBnkVk~ zR*Jv(kCRp`D|DEXUq0mux zYyHyBEPHt9JfQCVG7BMxrC*X&zdVT=SpAZw`sG8QRqvPdQJ}l(7wG0|9bAdGU;P5z zeGP2dkcp@G>)2;iT3j0G8C$eOJ$$ty^Y>ga3Kq%(efSMpD3;HWTaSZ$Bk(#b6z>8k zI2JJmGceaYtRCnimKQvEzE-(@zQ&;h#O_L9x-IA&Ut>Ekz}Gm~7cYzY1yX$e44(#c z>Ez9LIX@DiOM7pqEi(TYSm+`+_QR2pqLtsJZEVKVS`Iz#@MmOe{_e+mb8bb#Wfqp+ zSMS?_z7~;QSt!0kRI+UzIG20IzF9KFcf6gcRQ1r^o|Sf0lig=U26!!ZsHXV-;ZN5Cl*qdOd(D2B5$zeE6c<^(uu z)R`^w_0Duqqf30k-nM6b@#(K<{D;g`SB*Rw;SOL(7$Ga8QARk8p(IyHl5Bk~{mmR?tBH+lO-7kEvNZ>Qjch#&;Lwn*O=u32t)JnjjBM@yuaPb8 zS0Y=HC#ZG_ULWZ-rd2LCuSLntYr5RL79}^Y`REibwe2W(x#AmxUND-b6Fu*uD#rsx|`fK6(40I*4oxV&aklSvdkZVt#c(Q`ktWr^tx zhbb}bEP5WR(eorq@n50m+@tOiBSw3T$19hZ*P|rnbzNd!kCK?zeH&?{xdd6ejWkyQ zZ-ZSTbLY%l)P0Dqwk_&T1z?ky7XjEL<^cdwVyHN5^#HI*%%LA?en$~DnQ1!7Au|I2 z)MTV#ndz)#W)R9@nYkT~%4BBfe@$k%Pu*qa%uBq+CzZ?0_9&UzuFK5!D4E&r+etE$ zkF4EfrVx0BLuRhHLdwi;F04RIM&Gl{?B=ox#QBK9GP9e@D-az3u*~e{;tIqMNWwC+ zTW$n+^VbWWoyNQFD@_Twfen+<}aSFZuZx{G8UTw-u$iR z((w+tJK)VPF_(^a%I$%VP!E=)EV(^UJKJMSX$)2w^3$q#p=b$!2cyg6e!&$0b{`GC zJ=y=^7SbPB1%M^(Ca%Xqu>$}vVQ-P8h$}tD+mz&1P9nD$rn+n~glt<3ng2+`<^f4o z$bVdD7rH16AaoQe{Rlbofoy;y=Q%iDCdVoSy#{Z*7k{#ecrJVL_p}{?_&li>c;@MePbUEP~zAwNmr_A{e6qC-}vHG@~ga zRgdYi3G(X>bLEtJ)t%;Qq)Ku6VIrho>IhjUYY!#07M?r(V(3M<_B~{Z-H`r?OSR3E z{`zK0f4P~$`zQT*|75Png$yN}!#gW;Mb}j9lMIp}PxORmFozf)iI2nx@DuSf9*{W< z$Kx0hyY6+j0j-a^ndn(?tdvCWRg4_DoLz%nB87 zGx#@e&vbNb&y3^knT4Y7Jgk;zjXPehaTft-z8~8(6Bv*iIAiqDt4Ql$Fj zHlXhPvI!xFrC)Zce)$|Vu=-`c>X)M-J~iFI8HWuV+s;UquTkhmWazSKa+$A@eKTMp zfUB>w-ZdjI$#ZGUKruU2RW>NIx?#tMB;WWqn>=Fs(Wb0`de zH-~P}H;1k>H-~KdJJ(iWf9E@t$y*WuWLu*xi9twM(f-bL_Whk_5ta9MZgkn-xye_% z`ujUK`Fh*;cW(aU{hjGi`#ZN|f9Klya(`zRD(Skvvj8!8f5#7p>;BG@2;k0a4@ZqU z^J^rGbf%Ghs=ixxr|)RHaL&Pwo=uAKp?#OIKuVGQ+-$+$eRC)U?dHv)ws2IsIb_j` zYvopEgkIz+q>>G!oj7Vb2CH)IlPc#~-5XI9{SBR>zrmC_PcU76!}m!?u=CR=xUuut z@HxO2JJ@;q90xl;6>QYT&Kn|zjh#P+7?Pb+aRuUC01kG()5*@)I@$RnPIkWE$-=5WIY}n7^T_TS z$gMv-aH7{3Y}*IZ560h&dfDFOmyP3i!~7b&DHo|l8KP*>@vj8xgeux3N zQe4T=B@KSWPv@AtEX$<_|A4=XeOb2BT$aUF^x$oWo{#uXh&ss2L^UlQn1?d>fHMr# zod@nhNELWs;vv_VDKzVr67r+lEFM@yC>?ON2U-mtXqy~Y`{N=5y>;Lob!1?z8lf5Y zJMOCNH-k0fc2DvewS$nE+OyxmpSk#Be8Ee#k-W6TAGK3VDgbo2Y=raS3SB$JW6=43 zXfzxT!(mfFAVmO*EL9M&e*98gPV2|6SE!XDuOExWU;r-)QsF8UIru9sv0|`_7wz$N z{@@&dlNucBfpY?_o=e5g-4J({6_>Ql@G%NvBsPuPg~RkbLCRt9jA}(E>qO8J2gR?1 zCtu7JV;aLdH2#&o)XF`g#bsXOs5Z!Ow_Aq2d|HORn35W0;@UolKZ&YW_ujduLm7<< zuX`_b<|O*$weG#EdL#2vk#Hs=cF0!kX1%y#aXfnCBk{GEPQ7xz6*>j3Jh2a2EJK51yGJ9{?N+KQF6OoPua^N`;zS>zxR2Y>67kdu1G&-PQt>SQ zVlzn9@N>AN1|F$!TG7Vf{v+{=6|FZkbfpH~wFp5zFJ6NP&C%`VUO+3jkaz&l649$e zlm^})guk+kH1Hn3&eXuW@?4t4Z-!!m{CI&AY%29%B!HjBoHq{iODtCmcgEk}&|Hq<+x83yZ0v z7)ftH!ScsScUxy`t5#CFD@3j{sjL?MGq_UAs2-$rN0m}PvtmZ@KN=Qj38lM}-_;_K z(p{Dvh|Q{v)8fS6@ryk+JPU!rZdwdKbniml(ZY)XR-$_6tG4RhSY+zP_Z5Xt9s(WV zidFAcLh657W~1};a_J0XE5BWg*i`RyhOw33FGhSe{kyoU<%6-2nwW3^cCT`w$%QZJuI2 zuhd`V3l!17b11}pvx0`)XA2w(aZ3Q$6yl}=;LcDAap?f0LL6zQ7l^(9q(a=jGYL2e zfK-SxfzX1gDa0-Aq$$Kj-ymrz#9fS$-N_P(hQx$fA?`L5XN~W1n6r3%-vrd1FaC&- zDva-kULh{YtXoQG7kbPZ-#ZgZWuF^-wj1tQifxV^DKC1zH5(stp1p0mN`6h z8Bq8BcmN@Xr9TSHx}}8PKn<+^SWhVR$FD%EKHu5zfvmA2T#^1!8WiD{i0!D4LkaG= zg$^aS?*M2@aM1f*B=1cf=p(WfTq*ZzXyyu#B3x^v*hpZyEr=B1Y(R|^;RYac-rJiD zM~(LO!blj|+p}M~2}QUiq8z=lP}D;+d6V>itpsQ5BUXaD^d5~ukP_S|)NLBTjJ8?` z)CNPhA>aZE_!4?=>PPy6k0GEA0zyB+aWuu)tUWf;A1u|fBK^SynxFIsPg;x%HzSyR zSMzVL@|KR)^R8xJINVrH)cVy$b?J^9y~e4_E2TKwq9~53@}^UqZBZ0Q>b-rA{Q2jg zIG&rlMuCIkTz8X$;=By1V52w}BZiIQ^Z+0!j;Z(N0pOrG2b>hA%-p-|Afk6qx9ZPic^3hY!v4S05*zK2H?<8oW1A)rZ`E+vNDRZ{l7+WD$#p;WvbUmt6X?q zixM7F?@bq;*P?_+D!;Xw<}N%vfxqDpo}#G^;i&__COr26unEs}08)5N<+o%24&gb} z{J0cF*o5aN05;({d0NechgF%%NeoE+tqrne!5I%nWvWaDF6{X4aN|nU-;7(l#yyn_ z&g)TvW2(RDg7bQm;7A>~bmZ?g>f{2iwZguzin-Y#IK%J&Y=Tn`z$Q4G0Z73yb>Qv> z;1HZcJ?gYTHEn{^3xG{I(SbXAy4QHQ za>3aiB{-%IoGv)qqXb7P!YxGpZi4d|@V*YgnRkm6oZVbvfhfQOV8Ky}a8nS21!p&x zS0F|LV8Ky}aLoX);6xPR$~_K6xFU~35pJWWB1O3Kc>>cE;mjFKQ-m|8u((^LFeyd2 zb^vTgZG!=@bSXu+c>rvRaIXPiaZ`$LKLLc2^>o|nE=RD??=@uH)) z-_Wak)Yb)k#Yb&V0pX*zf5E{=ZLc9Ha@3YhNh>^Rn@OSSsBIZ}Dm-diPoWhZwNQVXQqkirtZ`Q%s<{{a8eEoM8f{Nl zdTHdrE;T*oJ>vd6VT^}Md}K=*t(SKE{j^K+))I$a+LHimdT9#)u&60Dv}*xKy)<)| zWHbP&mu7B?bO#{y(oA3~NOGlmX}!Y^y|jA)xap;7`zRT{=zSDRFYOQZQI?=W*1my( z8v=MA$no5n|KZYiOCsDafVYYC7%`cI({00(hHc1spZnW_cY6wQUx=kr>iEv(+1#XX!S1f##WgXXbCOZ&v$0xij-6dalx) znS<0fOP=F3eyp4hzY#@;O?@++4!^o72OyQss?UVC6AL9KydGV|O!!#Tk(qEd5N5)Q z;b115hoA@(K0rw;WWtFswQ4cpR^+LW3HPGVikNVPN@ss{CR~xy*`~Q(;}qNe6TeL& z%nBE8M!j)vN@u3ZMWfs0YY1+%DmPMs>cFRml>CBY) zH2|d283FD}XT)(?>1-rD_-ZSi*-X>9DV^PcYFcD38)Y#0Ee7gN_I^W170BM9S2~+% z)-5H}2Hj?ny=8c4rI1U>SXm_ z4Ya+5UOkxVPpWC+Ob_30RwjO*gnQj$=+2nd&EgDp#2p)FYLWGrMffB#Ct*6FzxVpf z9^;&@*3EXcUxvg3-bZjp2V5#%UXKc_vnpU-^UM|aM92!Xyn-q~i%qToIkXCpS5|9%H)hUx(j z@4)e~C-90e5%>WZYiN_(4E#Gkwz#D z5|06``XG_HeWEaOkv7mGHeviOTrX1q58dGToOabr^9$-M6$UOtP`~Eg&$8XW*1UV8 z&<7~kcK_OV%3?ibcR`C~oO~yFT$29mOo}V8e$tL-1Fd4~;_BFDkSp6aNyj|kF@7qc zE4^ary;vyD0^r4E1%Xo;uxD~=>@g}6d%&5oja7gVY(s^}U*PQ6qtZlALNW>8PaV}I z_H>0&=f&Yd!a%p!2HbhA;HgpPU5JWDcV04Or#df-JT9G=<4lUq>!Lj?RIZcb=?xm= zXlJ+B<7JzIFW8gzSSm_2r1`mZ9l7_2Z62L_`cN%RphxUcPM~cjl{1a{u4ioQGA^Tl z8i@Q^Cf8C>zu4N`t=lQ2CNi1l>>HNJ{gj>R)pLFrOcm3T*v$d$Tyt0i7z1L~!HPej$1Y?Es?FfvYi!dx{C zktUi3a@{zUFU*x27*)A}T)Bl}ELzC58yR~&Y8RZPi_NImGfYjec|e1cwII5f*bKUf zf^0WQ;+kSJXz@56uk4@Yjfy=_hSKmB>5Wp+vJmq?%cW|Dq?YH22bw|(N5u@m%#kO! z2S&xju!kEzin}9Ea4Sb~E2VjbQ8DI?a2?*oOm#!dUC4K?U^U$vW3Fn4qKm~nz+Mz1 z9*UBWwFvlz<>QH!5&2kv`wJ7f3WKG1%tt6!LjiZAH(5LeOYz7>46fT?IeDf6VCfjl z4?s?h!N}Cu3U5OoD5u6=@X*xw2=cY2#*qMdYWyCk`_y%;9Hm4C zpFBaVEihV_;nBJbkJe>)v@XM=r3|+}3KQxKU50NrWjHc~u)=26a#*WfNwlxeLvC_A zM9OUogtFW!pxG)Zw?m}d#vlgE?GP!q<%q#@J4Bb;P(*GE@r(l@DYr%Nklc1bDobv6 znzAuGbPG^-x!s76!y>o)&AO$8($H{AZWHmP8O!Z#pw*DuG6;bB1+pNw>yiE}Je-`p zaP)4ke5#oMlWNGUd9-`j4^r{_o^};qP{x0(B2L% z<5InhOZ74?)yue4FXK|ZjIFASsZ_=tjxzX}XX#~R>1AZ;Wn}4PWXUo**Tek&t3Ew@ zVwqx=iXBwo&yE6l+jyd0;6%N^iF$z(^#UjAje18l${+yBbMMMoJtKaADO7^{~tRxe|$UdC9xjJ0MNHYyVr?(mS;xR26AIh2yMooMK?+F2384BnnpeY$luJIj0~;$q}&{{hleHsb)QcP z5mJTu#5m-1Jr37NV6ICErJ_%)`J@%0G@r}^S`FG`qw6=s`g4kqp6U7*a4=mD+NjaZ zh|}gVNlQk+!PH3qwsIc8uLk4wn(neZy)E_}lLu9}JQd*zm!~4^x;(utHr>o~@dR4D z23unAR=>b3)OQ_fbR&V0YSI$ltmSN8;=2arnL)uj^$h1B!|llMLjr?e>p=?;^c8~o zW7IV=FTmekcr1a1fa|RD7^@h58h=L;yaaF?zzG;?j9^pxD}RAy2pWi>D>-PY9<&lc zSqRzzFsBHPf5Bm2uKyNOFEkG!)E)L^KCVkP8K>Eg&SXhhF`%O-)(N|(RDtFefm>fb z6nir^BwYJ)P3#;B3hvh%vkr|ZLru@YDCL^!N%;gWqzI~aHXzk+NcE6C)k4wiaVdGv zyGY)q|AORga!8(yoxOl+cA*-9F&V-2dJA4c(0ByZ#fYg9H?=6WSiZH@ViBzfqV}XB zL5hr3hICzPcBD%Y(HT|+u?jtXoy^%<%SWaMwOKYCrN8G`LGWsx=ZE1u6BURNPs#aV zI8PYzfP?3Q;XEJ6Z8EkZFr4Ql-u=v`x9a=ZujShQI`TPy? zk&lRaV^ zjeH+@M2kZ!DnW@uGI?B*{^U&R6o!{-vJ_Sfa zp@9amb;i>{LoU_e+`6HDNW6~|vvlN{am-Ve^%O@+M;W=RA|2VtFuL^zIJuOLCd=Gg zf44I!q$ApTSLg|^LG$%kS~-SFF(!6{gC3A4oI=ojfJR8j7tSDPI-qPga*E)fdEFZD zTnZ>b0W^P)rDbDi#1l|2gu^UgH9^M$dPYLN@GAuUf_&eGBd0UMXr8aEfYwiX4PpUf zY0VgV4Jmw>;mrc-!xfqf=r{@a!fgq<3Q%V_a@N8@Y@xCO?mz*=CC1W%F?7z8xVZuj zvw*7!ss-p43Hicv2>Jr~E`}qg6~c&jR93*}D1cbWSXwQHijZO}9A*K#2)YH(Cld07 zzawZIAcH8#GB}9AR93*?r@RL7o3XT140Xn^(GCu?fbInSf=mWV$QQndpi)5N;K(@^ z(TN9DR={c$KrAVA0Fh~}NO_C!Jn8a;mrIv7yoRDpdK&hFCFBp6z?IV&5Ob>8aJX}- zJ_vDVMkvjY+|-p*8I^G=4rEScP0B8EocAjk z4x(d~6)?k14SXz^Yb|S?#ILrceOP4qNsdV|m-&3^3h$g_2a-M;M=u)JFQW3WS zi?|1ntvR=7Dj#2nZBJYJ8DE(CAEn|EU}A?OKI>;}6`Fp=R!*!W!tJ_)Uk|sqn_?W(&9aFxRK9<<{yqwFrFd*rRO+RBPqA;IP`We#z@cLHiXY75> z($Bb~6BY9^0I8orfTf>7YG9e9%rz8Brj~w27Cf}PZGu$Rs&*Pc-X%=~>b|O7h>$9* zY7f1BMuAzkl+ab^PHR=Wo={rVt^r#0RV`as-Hx=ZpFtK@%i$q5SpFW(tmcm=K${I- z%;EYCJKjyAE;X6dH^?Y(9tDy526bs6g&cI37EvzM z6WPc?LM1D?!1J)fvre&k8VT*=WlXp?VoXGgy`uL&_3`pV_;|cbmgA)#0B;8>;8XOM zO=06z06bh)rm$gd2c93hgcLS@QX(F`9@&L@-H&={3L8{?9;QW@Yc?=4a9au+G`8zQ zd36*vf@q;s*m#%}HlEN$#!}eW1T?r*3yLUgtfC;>Jzti>#>elV>mkf^X_@*3EQO6% z2#xecsc7&7CWf7x)RajrcURb$k9j3e@N*f(-QljVVSZ^R6*hVlMJsId1NNfm{Zy2E zq$A*cmXF6?h{#9eL~*bbk9!cx)lk5l=uMl##?^?y;-M5aE&{-_sY7AInk#qShZjvL zZ0v`J=E_yb*P1KiR>-;X8=&rUWm}X|g}L(3D{Lg0bxR4ojv82VWiLW$uKXEj)#u9K zHVA|IvBE~n7qRBU!^yb-j&^WpJ5+arXwa`Rg^eyRcn!)ll#lczY9<-~mvni;UrU!a z{EKw?!tp4F;`zgkspv;l9p005NL3}{q_I26@M4r=(mqp$-4r%786K_6utQ>QrO6bhvc>sQdx346CiWEsX*Q3b^}5Vi`*_V>y{F_1P!<3wun%Y+gU)XA-DMu z0QF;qjVF=*Q-C=i!tp(YMrJZ4J(bDrx5ZwAG7SY@#ySrUQ*IxWE>HMz>GFn)q{|oH zCSCsUZn$!~BPrKm0vuEaU2dNzxxMfuyWF}dY-nQ3d zvzR6zFLyB=fRMu?rb%YqQbOBM14~SM5lUhjTT(4CO~ErzKUUc2fb?MkBhvZQfUXiy&c?F4uuV^jBLFOhr)(dhNZA^4?T~`jxyX7HncLv z=w&z*HncJN0AJ_X1M z8z&+|Yd$G3$822c3DkW)c>p0*m`@J9!p3^DZYiOQ(2dr7vXfAnPx66QgZ9|yIw@>C zhxAO>_rbw*J!qpwq_EL)tE43tz`@i=-*w6dC>1uMm#3D(Mup2$5w37~D#EVIQ%hlk zm#0Q>Cnh2FV}*@JQKQo^qHCLDy21u6@m+)Rc=eB~t0}Gg1xR6I8#0_rU~ripL<$?9 zBj`T_X8JHL?#E+cg^l=aFzW&U*Qn!f+yj6~VWTDB=LrsOrN62SQrH-Ppc60(8Nqh+ zR|S#6#{aSR?QvF4-~Z2^bI#1U%+%?Accy!y8inquP)(FX7bDJ0$IO!`nUW-oD4`Ei z(Ps>G;uAs<6-APajOgN)E;NHMA_^Z0@q4em_w$@*pYu#j<7j@bPv7&$%-(CSz4m(c z+V{QI+Sy2&31IH42+Tu3-L8|u#vG(jb*S5XQ(;5YV{|rCVZ%PBRM?O*h=@E=mro}> zUtV24oAeqb1s}D33@L1U3Qm6|pdG~k}i3->y@5%XL z7@siYF&Uo^>=ZWmNKfaTsnn}TVS~;)dn5Aq&pR`T3SG?8Ic*+Aj&i7v)~y`ya`lYp z177v`_~%5ZXxJPda}|x~<70lPTR%~X%+k`UCDr`iR5|6?z&*g@V({Uc? zT25vSMVvj5{dbC73)sycm`WK!tbYN(r~TnEVzpDsh=>&|a;1zXL7?gFn84}NyAb10 z%J=}l>WD|*#faVZPZ$D^vqpv-e~qYOCp8R322jK3{2^2v!6lkVp>dXsNIlVmDDgu_Ibn!)G$KGTpMvr9@NYW1Wrv}4XX(UY8Z5%w1dK=hM|;xtQK&9=Q^%i zD4YA_(vKV(&AX#%2dMAH*tQ=5v7h{nKw*HAFfS6w8Lo|xemg)-5y*WN0h*u95zMB5 zKHD7{&BLQ<`=?*BH9@-=0a3t}1gZznH4@|uPa)7@(4B!m?pa8q`TA%DJca^jHXluU zKm8r#ScQNnU;}~f2WYDVIm4e2=z4&@K_GV-0yOI%tpLZzu*k z0$LF$37}3AkZH0}EISCQiu1VjP%5a>35{w+by z@L~dG0rWfqxeE}WmB`TwcoPNCI%PC%`Si0eOn-)eDBybn9R`u#CCC|eV^-I915^ir z+RVhsuy693-@#fOf3}xxzOgl>0D1d~HeNL>6C{e79%*oZJ9eZ{2m5q_hBUSRe^kfDpadYE7z?T+%0Jw?#R9xt;)`h4x2cW_ECP3;zzV^cBWWRtPJnLOzV< zBC?Y(*WjPCl;yQfe-+L4)=!Poro9N|^T#`pwzvab%#s5sM967QKBFFk2=y35aL9rP z$rJA4AY2*218Yrywz3v^^qI^2g!X)`A?Q>vtKWyLMeG2|d4siinBjD|8~(D!dmLIK z6?oNOOa#`xi@WIkn~oBE~!Ti9ofhlM91ID zHtwX`M>7Sr3*(60s1>?u#Hfc8>zCpk#f@kzcs-Gt+Z*hzG^}II&*Rn69Y|DldM_-Xd3B{CFpD4w2s}uE zz2Jc=P~V8aa}-#D09E8FSmq>eM<919kZo%;*yU8SL~79ieH2hf5is%@QB7?dnED*u zYA?HUk7#O-@>wbsG2YZJbk|#FKT9P5Mb1(!fKtHrVr{R?Qda>WXQ|WCp$b?(0OTx1 z0CScy4>!}BQ2SY`Axf!|St?)fmaadBsxfD&JvbZW0q1jSeT`BcZsU91`oC%UC7P@T$!$J1Hd|6(Sv-YK;_d_DWc+Am)L;2K)Rfx9#HR0z;#}jb*M|ivpU8eaN@3n( zRFlp8wTInAGsp0~m^sMtH=j8uz-JD6htqcEAPhNk@SvDE2;Fje!Izs4f$}ZrhI`qA zrPhvo`)B5yK^MXaEN6xv_*78`q~zQ| zfb4#-BuS$x#qh4bhr~$$=wa}58v;2$U$?%yj6m*Lz~6yDP8z;^3eadqxEjDr#Pwl7yM_XX5txiX4mGEIqK2uV-sk1_ z0qq#Vr6!r-{z|sZ@68dHkMYd_PgzrIBp*?IUkE|aI;DW^N0|@4%#%r!1#BxZ(UJqm zv0ee22LNBQtl?{x0(JudXhE`uuUiV(2mtunMF32Bq`X|~zfvCV71$P}yjttQp5l>1 zCy66vT`iiB3fWm8z}HBx@CDOcwq-vSKd^v*ra;62xSSPaA zYIULYgeyE-naMJ)l({n2d@Y0#fs~*e{wv}WaS@~1c!OQo2?iUiG2ZOG@T&PeF=g*U zPG2eg;nA;%(07c)^BsEtr8BRR`WN%B3fu_1$QzdnxcM0tXQY z-fBVi_jS4ilk@g8+kEG%rjxmwd z#9#WwHiZxNL38hQYg4d6Is~Ln3X*tKJFvxlFTgfA+J5WMhT7$Lzq}lykYmsr1|y%@ z_o~~0bnUT_o&eIl3X7$hUPxY$#DEIB7l>1Nhs%rZkTA5nzQF_%~ z=pVdS{Re?#^{VwoulnQ!_NqZBi}$K)5cqq&>eTNYT2j$58uMTvwNj9d)vNN5<9xdu z<@Tx*IHBG35Eh$c-Qj(Ko=egg`QqA9V2 z-3Dh+eJ%rq&1M+ zJNAG>yW%M2nteLX<$jKGr>W(xc+m2_=1fUWwDpU=gjp;Fu0dcY0>K;$a%83?7vB0T z;M`1s#R$woK+cp8A{hJ{e~e#bru-hzOm-N5F;hC{qZ+5oVFsF3?IStIEe0@?J%_)c zww837DG#G74+l(djY6|TVzA#8b~EM0fM&AGWm>FAjvRDo4=Yt;Be!NhI<%J+q+|8z zOOa!zU5;}5^i1Tqq1foIhwc0HGeCOaSV-G|v_e7pC;D`3RSx*cp}nt`dqR5EdX#(c zDCPcBy{gO44$c3zRbs)T^s0Ja$zIh7fn)WmA;96i>RJR&RIhp+or(9VAO3c)y5zqO zt%FiEHoa;JkOnJA$Ldv2BgZ(q9I{unpmpoeTCk%IeB&-+2eD-=V!M&)4IYkdvcDtk zAk0%O7IKbUsDi~}w)_RchL`ea%o66?>(nNkifQLOpon{dR#>#>GkRda|Fz>)?9y?| z@K$%A=qAdOS8-@>g5IJ+V+(%_2px>VS$N<I_Y8U?8F^Y3?b&B|2)!|gsj^;gKLoYG6F^doM*o7cj;^i}aKeIZI8S5E2L zGbsH}cQ?zoe-_`;8y|9Lv&$(xl}i6hDLv)uxYm3jN`J;ET{Gow(>#lSxyitcv=AH2 z?}7P^4Q3HbeU!S3_b_!A3dgp?wn$5TOz8w3`|ffnFwdzF=B>cI(!dm)6HVT>ds7Xo zZM$oHYxob8eoHx}XHw~E+s=+}=~I7mXpfXrdR}bXo)h2F525r|$|-$OY}C_NDHxPpPPVL|39*QS}=>)MSvEuuaN!*568Cc#6KL`MT?cT zUERKIrvY<(g)lRK`7Z-g@Iy4kxE`a0t9x*a^}}=42bp zO>8@~6iV2ju}&?#6=R+!!3i}Vz=l`H1wVHNFUHREy5fMT#hXk^I`c~qL!Mh#y0jKs zkf%50A%!GeE4?|g|PDoNqV#6+#vW>B~p6gtd@deYm8h@B-$JUa^$ z3%&K)Y%5nUBCE@0TVKOhpzy~RIJK{+@RyCkqZ#fJVVFwBpnm_mz~2pgLH{d+(5*)U zFVdlLuaOjXIGox8n~bfj3+f{OW{x?t6S(ceR8M;(6|kD$N+o#%P`VGVioFV7TvI*t zDFtjP+66bLp6U@=j~jr&jU%Rd#Oqv(0pKrfPW6<6$A?hLBKCA696}EFHbP$~KmnsW z)xZevXYXhn@BrIW6Qzvw=7Dp<$Y(d`z{v2!)7xQtVfDk_(INs%&`MU^6dC=*XV<0D8s`d9>JAP@>zP?~M?==UOln!rN# zEj0}JOS-Y`LiUIS6$gS)i>C+0)>9X{+$$6{cOXJ4Fgu9+Xz1I_!=D2Haut|V@M^CD zlYx{9sKCVk)j{_%&Re>kh6Z4&z_cMKslbc{wBjl-SqCSfY06*V3U7x6tT!l;5c62i z90=)3@2RpO{H!%Q04=wmw=)MoQGq{>n&qX7@j|u|1$P>Q9HYI|T?*Oz0C4Nu5N|r! zp?4Crksuz(^m_IANSpzH2DS2t&;nO^>qIot3R&uR2^zO`z1Dj^3JpGV2O5&W?Kp3p zPzMX3&$IqW-rNh3bv9CSKAFz62`IKt&)S*ZIs!k`^UesNKFhq=u_h#hCjl6`u76}H zbk1O}J_U4cH(f-*k)NCup#GRaUV&G4f0(=Wr+6(}<+9mAY2Tnz(C0Xu+l_`sIu*@U6HfL;2% z9N2D`BV989_`o(@4s5^dPtf>~bBAZu8I)xc0QdZe#(Afw(|uBx&Lv*6n!$%Ut^=MJ z=EKrV&v_V!I3y{|UHRVSp|OWU++jZ2&GKvmFC5|t^WpAp&r}R|1#BUT;-l9+9%K9~ z)!H>iyI<|OSoV}pv@>>tnYA7|0HeONTkBU1L*}cV;c^V!rH%Ry80$QV$f0Jwb3?$le0r+x5t@#?!AG1K>*lSbbo;>>0wx?Z5%- zUM>X2D;&UExb`e)uJHKuwx|}<4Q?u+WN~#BfaSTt)xs5XgWC#h#J2w4RD#j^Gbv)z z`p=8biq@~Fe!S-K#wdI&WKnt^(V5nJsvm!**DI50LuE3(S+Pv&u=}>B-2yfR)mX?L zMy2rw?l*acL+rwxFH!=VJg0IW$IGdIH=hV~OH$!$c=kmLc1*huom=&TTm;@^6U zr%jAQ;|GyRIy6>ZiQM9;nJHh1Y=S|{jrUOlTRj2&b>MddfIBu$1+>YK3-oURv^X~I zLdZKjwRug9B%I3B#C`v@tBEN@&Zvn3irCb|(&((wHL=6fHKryuA(LHA?C>;~H4&tm zFn)oZo&ZkasV+j~4mI(rTM(f6$ zt2ZKK{x}Y~rLg8)jl~AxlzM9M{1YfYF{Sdow_LtwQSQBx??qGs_gKWU1Q^aG}zj3zbxza>L z6$6}b5?h2EB@1ylJz6)*5og6#M3P6^d%O+ zU!KltYtX!{V_R{M*f)Lw=53KhjnnwyGa75b<<^3kw{7TF3!ug&HFFo?3l;*lkX>O- zxd3~T;H0N4JTb4IR-;<@-++c1S&{~y%h#z|xId-5X!(%AJ!DE5fT0{~%Gq9h9g4o& zfK8+t$wVbX7O8x2pCTe>^C7JOkxC6|?w{<2wADn;7}9o7#AZlq6`eJDNb`7m#|&xb zA(I@^XgDx_0k7Amj#=nl6M!p*1+{_rygpU7Dc<(MXxXamfm&vkwX;zx*3@Q};%%vE z3)lgCZXtUFWnV;_;o4qvI`zZ;Jy6FhyyK@KQmGn$Il9{TwqOX6GirPSMQmz(M|4)= zcNUQ6@`uv{b-lDsRcF|`-Ucy3_yu(A=9PNhnwh=%JIui~mIfSX;7!SG_A?Aq0n8nY zfb(etu0@~*0_u|FLC=}lAET=*0$YKwCn<+^TB{LhR_4lGi7aAoqGoy&U0&HwKITb@ z8t@x?8>%AZb3#{?Z~OwMfX!_v;YQ-_4+QR{Kts%Ya}Wr&Z)%w;!P!D~$kL_39tf$= zXw>mGjA@jkBNM4ocq^|jx7jbU@WBZ1!mmZ3qJ{Hby^X4^t+xj6)dvu%R2y4~Vq=$V zez=P=+gKV!Y}(lS(OIJ#R9kPOmLvg<(|yv=0~%BCK)o<8nOG|T0{=e_3> z1bFZH4T17|&ko9H^qvEVQ19t`=s0>0U&FcKge-8Dw+>&!r6NLWp({Z~@Xl9cT?nVW zw>4jp4Ivy1z4rh|4!ugh?BcCYW6l_$6|xtB#2;JkEyhS1U-O7sZ*M2Qlqf(%tbynW z_vMt-$6K9CdK)5@lJxf|G*;3Fh@3He`r&)eu4yM9j>;M>={`1NWm{yDk`7xZtUlhR z$~)TrGhNkUUe8uXEVy8f8De^S`^NN;;V4p6KB~G6KBkaO2PpX?ETjf_Tiu5xoOc}4 zdLt!}?sY9-BN56?{SEgx0Ow{Pa5)0OBlu(dQX2bRp>-BOx6Y2xRBQYUhyFB5c?d9l zI|7Rl2pyOlnWMX%mK3^we1v4Ldt9NmmUz#Gj@$&4ongYV??#PH0COo#{LQoJY4KTz zke6!SJQh)eSIPpmnm%C)a*rjRl&L!96n|T)w`HX3BY%M*UZz&=D^5?=TNVueT4%eg zPgTIV!9aF|1~8JulC2Y<6k_4t2nBz#KaE-_J(+8v z+wZb1G)Ca0Z3~l)S{QjU*TM@%Ej*ys!bR5AEk?(nvbg0p94Qy z7t;d0h^-!=X~pdEv;<&$&>t9MOpGV6#~)v_A=XlZ-$DuymJ-6(V(fBnpU2He|dU#jP{KW3CV|Ji+ z#izAF2>y|)<03kh(NX+dHa!`UraXeu>AZdq%fnyRRmsKg%bR_@=pv9UVSnZ`?O{T? zQbE$n%n1m$GT!h^Z2j^Xzi(+L?^|X%p$tz~yzS+E%UqX3Tyb>p6n3Fokx2mXD~>eJ zA`Tc10KeimLjt-0z^^zudY<4I4FTYH9GyH%Ip7bJ!Y?__lzDbE$rw&wDyyA@YowK(G#>ak$boestHn97UUVy^B`MyWV|(+TZoI zNQ9#yTpTZCci^w_Yjj&ugaht8BJNM_t`@wd>qEeSdDpv*pmf(e4bbDb>n%g&7{5S& z&zV_&S^)z*X9hERSuh58+68M{0RH!#E_JPRr#DGmE6wnprmmG{c>Abpr5RqbC&9Yq z|Hrk`M${)?D=k4FGCyirw^*tnkRDx8=_g%9B_zp;+8b3-^Q;v$5KZhUE8qeEUb6x& zjIPQHPr9n?WmIJ<0@gP7k+q@*MOW0Ildhts8WlB4t*F>(V2I~i)Lrl~>ohRLlNK`# z6o8O94U`$v!25vOPXo#BDw+l~JU7UFvvmOn<}^^Bpfn9!1?X{10|%`Q>tfGYSxM(u zM*X3lv(#x|sHgo&HVr(B`sC9HrF4|u?khljFGg=Sk8$<3X;PbQ{t>C(W&o}NfN!^^$?aC!A5w33 zn$+9v2Mn&aJ5B2CwgG_a?N0L)VeiDf6mhlPo2A-r!W=i(W1D7b?amfjySGTK-Gn(# zzN5R%RN9>-ly+}dm3F5}rCl#d(WM zg`hNr{{iUnOyQFv8`{8hZ->Y}w2<}tQ|ip#B_-7uy&*7DT4`yf^7`VghQPdyM zs%`E@)g9i>Q+f_mXQ%Ueh2tPMfc2L2^=Zzmv9savA^@MW>LMEOL{ zxFuRn5t|FprO{dO4T|n)d{q0g#^i2|RkoB#FdH?qwM^>>F@B^mg zEM*Az6A)FU<~rY{>LC)T)C4<1RK^byuC0$m4JI)MSZ%y90})$ z>QINM3BDx#HzbN7YQ$uVG_Uv3jT;=tUkj+p*UBW1`Yo%HlCqR>?4_h6YM*V;x@ZP= zzK>H`|3u$QI1JA2f}^$G)a)ku8fJfo4;e|31x{D?L_{V~0*6D} zf19FGGki z4OPDnDRYn#-D35Zkua7LqMEM$712V&6>T^e-G=p=;J46h*g>W3JSd#0!H+#CYeA)< zJs{HDVU60qDwX*jG_ut@)I_>>myBQyYs^HuFfe1vlTp80cL=Q9r+!6VL-WG+ zyq#xY!W26Maw7tNt{u<TZ2ohVs=WY1G%>#%>GNc$z>?z<^eJw z6lCgR)*1gVxD^@H`hB2{zsn3tdV5%>p5UN0@FH82eAbv|?yhc{x${{oigc5aA!yS6 z?lQ6r8fyL?GBRU5(0a&ujk1& z6d6d75*guZhf)NjIVf%$W~epO-!OS1(@7T1oAPYaw1ufIS<^7O0rfo zC)d$!A!kJRTB#%FN7mE5vTFF^6Fwox>}X3a-|NIL9Cn)!1T6JeqoK11x+xkOCTOV&EoK9GMV!7KX@8h$ z-0STg_VsIk*2FQ8s0az&M$k6V&jqovOFu-) zQluo3Gi4iF>(jfLw$_9p-2qBl>xQtk9{&L-d<_aQw$@wjGHtE77jDJYy2%2kR`(-h zZPi;A9&Kygib|$C^rSPXWJvh6_krIZ_@dH=B80JXAn=sUQd0Ojq!ev4Y^`ey61LXg zIi;=jl}IXJ*C#u~gJe@Z0&orh{LIF%wf6b&qAA%?7`E0;fuY!1I{=8XwccjfT3;g# z2a63`>l$F63iZLMEBs;%{xU`yIs69v=Onw|p)ZiXa`AGft$;&o^w z9{p_u4k8e`*MdT}*87k^O~A(1+D%m~f5O(f@6GT%z6RTH!`3^UQ{vkZ`}^#?GIHh!wD_1DOn2K1afpd3Q6eFoOnp8@b$#528X@OJ_8zYNXH zw*lNJ>4ZMBlwcZR*Pn?^%Jl=lt^AP@cCBg-?G6K`o}wJp2%8?kYlCvR5jKD85fM5F zqDSzI-|;_$HL75SHUB0LeWApSqqWMa-@To-evq#O%68 ze?cvy5@y%E-lHMyB9tS|uJ=LhsDQm!U5;_L%P}qt03YKFv+IcfC}!9F0XR;x>jIX7 zOw#I_Mj_Se`T$r_t*%F7*eYP3fm>;HZH$D+wz}S7SY6M=7gIO;(6G8T0OeX;FT${I zwYoOqhSjwZH>|FWxN3F%px>cdUB3W;w7Q;$K32$n131u&d^VVI_^ zJKmv6d773itCd$mVfir|ZBo8bx@om#SmTz};*Hv1FtQpT>uT5&PXZ{Uyi^N&;?*D} zUMvmXqGqX`yBBF;0COAH#Hxb=mm;u+0(l5*L_l?A*56k*_#vRi&p*`X%4EL)l8I5D z{ka;;ZfJ_qI-=3?c5S8PctCR*n z2IbKWplvPt2EYx@H}?>jh40{Q7cOI1hzCTgNaAbSa9G=Uf*t9cUGEMkbP=83yS6yYBpIp;5AUx28^{ylpd zvaKc>M?9x-8rvuvEYUfQGK0oM{(*Rtid!j9JiL@?^${aOc=d5{ZbDD}R(}&EeMe(D z=QEA4|MHx}%NRg}3_dd{!uia~qA^we0%UaGX<1~WfZUzcHcvM8^rgm6G%xxh=tVZx3SNC*20r%WB(waLLGS#LZJp0B-7gd zd=qB~;k;`3IMeR_2LMCktSPX&ZwGer0ULuCf9rH?6@CKYRZK>nH;}n3r%*k^IRdZe ze5zVQmP?F!=CWKblGc52&xT*e62ykop8uf8=Sz%Lsr5Tc`esnXu4CLezCB{^L2GV%p&m+JK z-+CN{^PXEu)kdcJ)T$04^7nhLfBoO=xn!Il-Gu5juH3?hb%&bdPqCC2dQum$)?5OY9d4C_{9GgcBH3nA5}D(ZY^Nad_hp+;RQ}Gy zLk9TKvfXLcPjC}BHGW{dX>g?lzzy&hS^>~mQYRB>fUgW3WPl&t3taG|DykdjpG)vj zh3pJ~q7CrZQw?$h{2d78ZUqWA!1utbVC4+(F9Qi~fIkC)N*UlkkBm_U_y@q8X@KwE zfHq(l;HOeV8sK+9IJY%8FW&(F7t8988{jL;K~ghNHr-@^uk5kcI?oM`v2MD_0N)3* zd;eefB{dA+jl^IN3x*5U_xdGZY7~Ic3Q%GJ7-e$r{2M0s^HC62ESQ2oM6n=PMc=*h zM1A+K#&_@h|KhvrG&w=?9*Kguyt^S#_41y4qP}~L@!b!r-+gj9*!Zte3m>bsP;o>0 znpt84o$=_n=)gZ`TEB2A0}8Y{vO@zTZr1gD;o<0eT|^2rUWWDHCB6Lef6~AxQrK{ci+r5$ny1(<#Sp zn;b(W$qPtn;SUpmD@6#;0KISv7Hz2iA~t?ehWZymfImS)G1M;wKpN`5%d>0%KpN@`z$^fyp}qi&1>oq0`eSc}KIC+4C5@l0q5fnr zXDSNhzabR`mIG?9D6kJH6;KpNj=Q4362V)#UbnSHQD8kmNl~CLpvR#oFaecg{J5e1 zOe=s4^*>hu?ShY30NhYtSyPdrzOtqwLw#jUMTYvynu-kdkG-ZEj}JQ`YpUl_5T9e` zArP5kwJg_dmbxO-e5Gp0G{1_fX6uQnnwo87)%+Y)HI1xQL&o@LSOH{=-`@)OKVy7- zuu+w12v}R$71oL(V|=BRkuiQ1wX$o$=n3h7&ly!SN39w=^ZSXYt>6;t;BIGrzZrzg z!F`7@xF?-j-r(K`DOEDKA20^@ap1tz0&^G1!TljXk7IDZ$=a02{QiC`fXwfewngUm zRn)fL#D|@bw&iXsN3eY;(c0}Ew^j`q+$&W>2KQA|HLbw$38|W^jjFi-0c+K~Vyzl7 zv477BAQStqt$_bCvDY6rs`9R=syt$?C^E5ES{a$xS5Yf_1B{-KR+f00?0{uz)g0BR zKB7pSwBJF?)$l9WzqZB(&+;lSZN3WFOvo}8EK+IThKz*b(>R|xR!bZ zMxXbbnlx`2IEgT_0N}gUy&jR}HUOkC3uRHS8cRHN)YDBCMfHgQ{|-P-Dbi8_h0UlQ2Ji^t*{|VG7XZm{RDTE14*|$2z@H(2 z!g^Hy6~JYPN893wLrrds=X@&!$DlFBc+K%q7Gu0gR;49wTAGv{*_~C}hHp|(_Hmm$ zIP$s~8L2cDo+(2K;W-F}qVnqtP+%Hp>aQTs9RbRf5blRi?oNO%=H;oo5Heux5p|Gj zcYe#l+)--zr?xC??;iD66l@NwS?#TrK<2GJD*)!L8FR9PTr=vDlL-2eqlnk9z{Y*m z1nY@|=_rC)OtjI#UZ65;-^BriVRW#_Ass~s8-twzsgOHOD&#&1fZ`}(BAg>~qXWZH z#NEJ997S9MfOHhG7khWBqX=Ph5OEY?m>ev1@b`{x@d`!TSVs{{9Q+xjavVhrLW$B* zgvH_@&l_uTK#n46;S0FMK_>)kEe?kwWT`F!HxOa_Frh_wV#bxCJ)jzE|t20&MAGcOw)o&H3`=lyqZ)6 z4DLFEt0AMYan~7iqg#f^-@nn-u!TC_8(qa>f}CZPV==K4wOX#lgn6W%HCZ&~a=m6u z0Ydr&o5jl&&7c=YR-&_9WSdsN{tbZinn8d<_A5B(NM^8O_?dShYYq&42(C-ODgdO{ z48DSBIW5w)xYrEj2AaHPMBhMb!OoTqHTRnF8Hi>AxR8yokmFu6tjdGWH8(wHY{xmY zsv%9@Gg5#Mtt6eLs6=x&4vK;mxp7c>KVS7cXyJpqaX1a6ivd*E4&=sR1X5_}5VK6U z0|~TDz)u}K$c@8hB#H*V-CC6C#^GB)RldlLgYqrp#z7fjq#K9&Xrfj(4%1Lq+3Rk> zngt2mjYBRX11Lgn91f$TOp1^jhi}1Ff28L2Z{g4`MIh@88nNV$yKzv8RNXkVMy3#D zQWlNm#(|cK#?KEo4k2148b9(bLJLIW$GwZt+R*sfco(51mli(Svd{x&BFjQ`0R$fn zL1l>~9W!{s=h8Y!t!M6-L1_@=m_b=Xq8%(`QOm?=sgq-dZ15!1r;)1k6mrZE-BVQg zbG3x*YB(OBLee6~40nKBM*wo4L*N_)RIa#VhG?#WN_&%z8C>DYwl}q9lVgU><~OQp zirg`SRdawlW>C7`Kc+G9EqFR1`_J~cFXE^Begw?rxE8q(HJ06pG~g<(7;eIl&AOs9 zCZ3L@h%1HzP%<%HF0*EeUlc#^8W8vl#H_cI+?swx65lKAVOyz;x)>37 zIot~YQHppW5LcSg3xTD?j&2d*b5BRUOE$d_&{lRXlU@jj7mF7H+V>J~3D=|G*+#*U zdbYC4OFc~%#HT?KF})D*k0@bVe|2i@h~6g#y=X54mall&Y558xBE1kaqk8*-)$p~Z zE9pk)uU2-XAA)s2GW`$`2a=uI@)nv;&$W2O;)j5X1P$XpZhqgt81!#8=^wt3%PWDP zbE2Uc;{korgo;mT|0`ArdG6KVCDsptU`q8vka{_&?6;%xo^uv`_8#`_TR`#Sgi3t0 zWax?jLHp6<}7Nd&Td z+u$;wfIR>J-!x}&O@#tB834X%&hm*@(MJN14F?~{@+r@9K2F23zvVQ(f>TItcAxMF zbeaO=ee~8f0oEqG{W<{G`N(?)0k*LRD9Z$2SlaTxD=hVI_ZhFE7c>4U@C@I*uM2b3 zw-~>PpUI0Q8XFnEiNDJPtY-WsewI(X3hbD(gz=mByL}Du-IS$(wWtNw?=b-nFn;lV zuaA6P(t0M%N1Wd$`AV2``l$zy;bGt77l`yWmkmJrBRpQnTHxCctOwwF3AhG;`=~<4 z`RM7zLN*HkTFM4;c@c$d8&y|504DnAiTFa6j0$aaIcQ9hfV%A++VigfaK9wl7l11o zVV9B5F{E39={|afd9HA1aHmu(8B`OL=lIAc=foSPGA$J?D{!N)6@SUS3q_{;#7pi& zsLf%ozZb=ud;Kv0^1c4)?aJHh=OE>ndwtYn+_(C9g12;iE;umnl@<|{w)*b^TJf!Z zke*jJet|oDZrTB+gr@+i9|9%**t+`s@ho2@oLg-nlM>hUa zUlhuOW1-CRwKz6Pr&yFM<>+LgFQB>|SmZ13;dCrf6$Ln8s?`72{AevjXXcBy`w)mM z-cGVwC^Kqd)5%;5Ejq}ykcfb#EhvspkJ@)CjG1xgEGHlDGLC#CM!t+m_loUu#7~Cl z3i>ev`Mhf+@{`m{Ixr}FrB1c4DF%3$c=iSczM(-N$(D*#WUn0ULBI@Cs_b??( zeZ0rGqp1S6Hw|{1usaC+M*?=BTDXGVV(%(=tHOE(7<^gqxL3TSvjhOXEO^2@iMzhI z2LQe-cv1p}0Kk_8OT6MGosIzTWx-S4sXR+<0Qj=tX$klR#qwprGhW+=bKddBKAiK8 zH}>Hi*BO?nb+wqjhUw=3YJZG=6H+QLwZ>l`Z=2vPU4I-Lm{V&RL1}7z573HFty#*$ zIh(z;)rWJocx$UKCT#JhoMbO1H0mh3{Sj1bq}yv*qaG2Rj5=yy8){B@N$0)jntSi0 ztGN+I&2>erL~Fs=OhpDwUUXwntag z_LHunwi*@nyjoGQs(d@Wu`lWD^v1rVvmb=aEtiI!JKu7(?o{5qkcE^gnHTB{-qQ7d zfdg}1NFylC3u^#9j(I_ONoO}kx1@6{!`&y*quVDZ-RR~xQ_c%tqGGM1Tds9p*n^r= zp4KUeuDOzvuIA1$YOW~))|ykE*7*$6fbz7?=Kv^A>wFPC+Luy4GRSPh(2{N<*Py3k8T|WX1e&)B#o5wdL1!p@ne)RaPcP0Q_ zdoLl(4 zTH{^JX$%2?@33B$fQ|t09o8#e+AK!y-w!gJ!@0xHHFRssa58+59Kg7nJHvYcAot%t zGABNvt&BzTiF=#C?_TmSu0DQ};Hw*Esp3_XC$F}g`nh~H)CXNocO|Q5PjrN)1(gTr z6MeNZwUv0ILv?wNXXs;J?$Cm>tOK{#m#X4?onplqCvh$_ajrus_eE6RR0{lzzzhUJ3oRTD z4Av5q-vLli{tThe7K1|rdF8Vm(aJPsDb9qd_-i0 ztZrvG^&5@mS<6T5wUA8(AopvWo>%ixF9^2%x5NDGKpoV4?{f%ZrBQ$^Z$bSm(14$> z&t;8KQ-Q`lYO88HXzXiaJc1LI(%e_yNU@TBAEdcYo0dNEIatWtT^!mqbUx9F1Lm^9 zbPv*+M}kVzYK;R>>(Q&fB2BBcFRS8BE1SpWa)N>LoY?bmw@R7 z2pm8lls-Qqs&1zxgUEDRG{F+@+0c=j+|{8ivcNQ@z5?BSHeFHePCa~$Y`Rmm z1(r2s4`1^zW6c2y?YFe^8W(r~PT-ho|LftCt@|J9e{J#Ay#IZNKs@_j?m!T%Y10w) zEl8m5r%y&;7y`MEA&_ZyNWAFwUtD>ex1FEb4M#QkXrT4YCASkrj4tfPDk1^c)Br{!4{h-Nc@1@tMp>|A+r#Av0U04KaUh3%qN5f5V7F68$#0Fm=L7B zF}-k(Z=@&AmCMq^@Ce{fj=C)E(p_GbhU8^wA^`ldG{kS;q*^||Ee*-r(z0&ywlpMf zOVTL z5?7zg%$v?bVg`QJ1pF*!;OES%Pd~rOy=v4*UhU>H(z~hke8Bc@$r1cvO)rW z0f0NzUTM9heA0SLxx{))xr(0-^NYzvG*~?;FD6$bLKl_y)r}1&U3nIenpE8s$@pY~E zY@yDCOMHXOcj6S!!%Hi3#ks74x0Oms&sHoGuZ0 zDKGhk9SdcRuja8)n#Q82x1VppsqNjCSKI={KEFCs@n_wXtD6rid_f9Km4W}Y3(^Ta z!-5A{Ui`YsKO|jC;O!Ed5^=Y zX@{X1b?P9xXIQ(+j0*59t$W63MlDZ@(u`V~6r~xJ z@06NRYoun>Z1MDLL^EoZGfFe+PN&q2qGD-9k>`|}Q3l|EBT6%>)FCyaM#(JO98xpN z0KDrcM>9(B714}(CQ37k;)Qse$<&MzfI$E#no(l`P&A`npz5+}Mtu)})Qlo?t3r0@ z98)t&5N*-h)QlnwQ!|Rpr;ec+l}ED*X-3hzD+LrWG^3UyLJN?Mkf*r-DF%=)K&pWU z`vu4Vq*P!55`WF8Qo&ogJ_#I{3lI$|i~N}WSwJhk0147#D8?_M8TApM`Yur7Poq>$ zGfH`TfHb2j@FIZvU;$}HRV0(u^onanDH`BhGb##Yf~p4}i$a=F$DlIL*C`f7T^o>Q zlwzqv+8y?mIyk?uDzXPiGfH9LA5&zXfL?V%6xmmxAg&AbAOe=DzKXv4y%Y7_wfo5L z{zd)nlS>nBh*1k25wJ+V;{8KeLLW^}>iD#urY{p`ND;-TPA^Nyk=apeiHP=70$6DhZN%1#E`b~;Q4AO6^B99pJ@L?xpAm5IH_&~lIfk;=@ zvIefV9LJJIlj4AkG@6vUB8{dhs;i$*R9$sGPu5if1gv$XI3Ob(CdC06=`bk{$o@}< zNuOv`<*=x#R2-0z4wKT#NQbG4TG<>hdO~{Shep-Bs8)^T@@y`8R;o0bwzqgRa93Ofb$blSN9op zH6g056pv)2nWT6mBh4hmBia9HCh41us$3dXm5N6)(o9lX8EGa}Q7bD0qbH=5oz`FW z$P@%DJ@Pnpk;Y-q!f!FPuvA7m!gmng!{$*cBRRT9DLs3RL1pujxbP0GZz>CSK;qRa^@{(5oJ_ij& z8L0>Wsf<*I^YH`#QW;4AW&u!1Wuy!ge=KDr#hr{$MiO3kCR;~KQVvpFGjQdg{x3xI zE=V~jbO72w#t(`>pbe1nJ9;t_ z$laKpfdKb5b`Ju=+ZdG`e1A7?;N>qsI#kw^G_L5PoKguLD&-9ku0vGu_?i6y-HWAhg?pAQXlUa7b2rq#8fuY!_5I zsi{FU7F{>Gy9({PmXs3JaYf2%bjaLY;9xHWmRxAxmj&(`a1-6DMamG${2Qp)_V0T@ zmG|$q2=M-$fk32xLw6>Pd^ijPeZ`5wBczvcjR}=*4&ET247Zz5@*@HYKa;l4bAToe zgDXs+*2b(%T;#%-S%xK5Z0eTTA z{9Z8R6ZeAm03daMI$;>28@ulu{2VZ%161bV6JJCJXs?4$d{1*4l%>?cC%$J)z&3Ho z7tsM)FE06(`HVZg<>Hd>Srf2ST=K>002!Bjh7OQ%$!F*QiR-s}P#aPQNC1iekUBt? z`?x24mist69U!`b)6nQl9iaNu0&xZR37V$4=cH!IPZ(RE{_IZ}uS7}(_MGw80U989 zOV?YV2FyL@7=n_e%$0yve9xIpGio04avdNV-U<*AIzY-q%5{J$I+3b#n$Q6f3lT*# zr=mJQ%4Htu09E8(PRT?%Ko!WuYhyXp2I&A%Z4{feVO@G~9iZ5`APQxedWRN!&qq2y z$Dp#t*EAMIz2_qxAgk*wt^=gZLR<$(x#}Ptpo(1ulJ<+j<3Dy4n0nC(+QEcS5I;da zAA!gYM!f<(ao>IWiTds$$!B+*jZ@IyeXl|bco{>0Tn$)Mgp90Xk#%!aR(jzn@Q1J4Zo2Cm{T}wA ze{gl$e0Ey~Pa&mhzN2=9r$T=j$)hpjXP@;8=1CgTPDv(14LAco4-g8u!h;bCl0v`n z^MB(Ys}LkTLeQ*HKrnv({f@3#xhi0|9rtZEVbuyY#bQQ$IOqNd=icUfGmxX@Cq|An z$5T}gBJ1F&td*#$JgTa7f8hBfrK&aqBI@H~go4UIXjaviv=Ghu5(vhRSJm$-z_zL` zdB>^UZpXc>sv)`|_aomW*am)&REtmdzRg{z`55e1f&JS`d+c2-<$Tuy ztf3S3VjWZhOd+;6$hBAzOI%@Be6@F-S`qS$L8_(rFHn4NGe{UeR^sd<+8hziA}>+K zFQuQWde**6B26!4fQxAnk0Ikx1poE83>(_MLwy@@Ze#Op4*~CIuwlar*w3?Ne>3v@ z1ol5y*>BRqw)TDp_64XtJM1F%n{5dlHaoTEkk2UOvsBPs_9a{a?Ee7M4!ej=LQ1Sm z=O9mae8YCNgoE}ayaw#P;M5Mgh<$Hc!cWL^ElL=&O8JJ%TiVuA(=ATz5tLwuy@&nK z2#u=;P(QxP-h4Jd$C|bsTMk^| zN)VAllwl9sRu`!AP0FtzBv2B)j&J>>r$;XcB&Ik94@cuGVj}=6VJlur&^|_pZL`a{ zhEY!PM(7#g&=Ox}UC*M1Tf%;RK0#ZTf^126yFh$OE_fRM)Q{MM-bkL%P(oc^!afWN zji`ip%qF(6c{ z_8|zBunj9++5jA2vFCx8NU)S9Zus2V7=xIUminNX@+l;(VZX`QpyH%QBy6Fzt1xZ58|N(VWqQ-x%#v1NXTdO<^v)xQU&7`!Fr&5 zw@KR~^14#w{UD>nvChjHlKh*Egbc57E=MjBDLprsc&#%JvLRw6JwR-`Nvzc{Dv!Ia zZ0K%+**Ralnb^?1vo#UpuTM1cJlRGN9!3Xp*-u@M+c;F!My98>* z;A+tdSnMIhUNzB1V00I)c7>G2IUKd;3kljd%v7w*L=DBDo(F_t_QEqnI};fSUP6Wj z?;9U-GcpKSvrSA=&jCsay8w*zECF&q6Zx(P@__`2e0UGhAN)CG`5N?Beu*qMnOWvV zvdnYHEE9lI!Ww}7o^OHtgozxEAfN4&$b~>DVYh?w+hsuhz(jr~g1pzDJOd~tY$cF? z`X0#I2gYZ<6hXerp!^(AidoS?`aA6>%9u<8%^k?t)y&vG(icV;pS%DlC9L+U1Z^M8 zt67eTe2ES6a-ftjKYH1~hk!iKL=Hxf7aJ`3fl|WiuT0R|hJn1^M83ub`M^R#p1C?f z>-QRv_nXLD&5sSNH2Uu!>j*gw$Xz!8x#5RK&Fr>8{^4~(z8uJ#i-6qUME=?a`3|6z zFc*-sa6rr^naDrcAlCy*33~~(@#Whfxef9IKq+BCw2j9W z19_N=3@*OtF7Xqb(U4swY@+y#@Gm#&TAe$rb13)QZ z)4;PEn+^7fiTq>)d7trt+jkOj19XJDcLUk8-T1&2HpnA@@)OOO{Aa9M`yo&Gd5Coc z20+WQ=#q8`+LP=QY|Ng)43QG156^iWlZ_wZN(pz=CnJewYCQviT?i~-X-LYQkLWju zX5WiHLjXx!%aZh6fYORUUx&aV1af~vU>O3zF<8qOKdcEFgfam&esJ5Kb%rJGI)l~2 z{Y)9=KjViy9qD-ot+_i)^J4IQYvM*nlQC|dh-8{f@eAHcQ=|MPzRHq}>@)j_rU(tTrly@4Nu{+2{X&NH*B~m*EmYWzJp~ReeDofu`5rtq zr{Gkq(n+8nB

#u3C$D&MElfLz@7+ys>^IfSnP~{u3Eyy^Aety1N;7Et|Flk*@9z zS~hXB4gC^Hz4fWcU{`*a$uhzIy_m?1U&!* z(u|E?&Ie$>44kAqnyhbt0Dq;=d6p6}ve4)30q`xvl^SF#&dFrQ;5nySTc*_~D*s8= ze*=|{i09BlOlgvI-JuTc$4Ze-2dM!>u0utVn z$@-Om79*bH#Y{OxvM?3E=7jgmW77$FQl$>GsyPk@97F7%AO^D}=MOiy!*>x{*Xm`Yv zJj05?E?MsgGAoJpzd_55M|`M736`=hNXr&UF7n1d{AoBy! zE&{DClJ-mhKaHWiw<3Heo{nuBky(+fKL#>w5zjdYT4N;bbpU#?7EonOM&EVFo5Sq z^A;FUfwq$KBWNurGOwUcL8fjy&>jI=#gg_+04G$Ac0152B{Hv~PC@2kqJ1Z59g?)y z0k|NB_TmcEY0enX^1}oz<+Wse7s$*e+RuYl8v>%8{Q}^o%F+H0X!RyCuP5s@hhYFC z+Iv82q@>**z+Yo%uXOi4cE8^PS`&!OhGcyp$RxA}Z68)uvn1^t09zogv@$WL6OExu8{_fRJUi;phr6w8wb*9J{_ZfmRxkc{^Ee3o_pm?bkqSfTZ0I zz#WyNjVEoiOd|76vOXGQPDMQDJJ6aUY2ON<3kynBmP33M;JY_ylJ@ri24iT~N$h>>`hF3#v=2f1y=2{s zrO7U$JrT502?$xX0&sSvXon6GZTU<22=gXL)k%YL$0E=(epJQ_NLUk72CbI1Amykl z55Df|4PI&8r5x7swHHR~(@~=FOZhli-v^RIh>OipTqNS;;;R@g_W6!oiy_@w#?EA& zj&JUzGJcCHqZbltVMn31unLt?pO$IzmlE!!=V6gWM>auv$MXG@$)yqL!JgX_i!Rt6Myl`cx|?+=zYZ1)*wf3;?h=g z)?E5_FmNy8xe1qpeFTCRPw!xmbJiAnT6BYebFI|aokJEDmWmwpNu$Pis=;&$XKBO-fPQt(uu8^4qi z)_Ng3-^$R#9xaRTjbBPB10mBR{5djrBArPdc@KDswp2p+ZnXMWxIEW`gNQsIqYB~j zq(e(CPYuU1B+nj5vX|#%q*RGK>vPsz`W`UA<>?(2KY6AR@#B?eD==V{=KvxSM|sl0 zv7J0G!{D`x%d;39MCAE2RS1{ob%s1Mr996=lD#}{MM{;(bBdJbS73n4v*s1?lV^Tq zom*+Nc5RvB#R3TiRbVtDZ=Xxp63z1|m&zVT65_#^B z^86kQaCtVoGJf(rP#Jli4F;_8bZ?Ju|D;F7F=JM=K zEMdI87D@K<73! z4}pV-Ja_eD&$=Ng&%Ox6OP<>*BhM?rfK{Gl zah50Pe%Q&=^Ixa7g3D98$|}##sY19sNjZeeQ-e_t_0MTYvX|$JNU0Ke*5|BY7msh? z^XEVW;w8^CB7VH=k&!Gs!OP=|ak>_|YV3p^RILnh1t?cCa6wWT`h;uLV z=UC!mzrBgtN#8@p+=7%Uk!KgqnoB<$ z-@xTL8i9Dpa|jVX-tqQUFkqGEm^jOmv>NT?nU0%;4qTq8W32K_KupM!)E>D!^Q1f< z0ju`%+>Vqgk!OLFXD@KgkVnUvznabr^D&@HttlG4U*F zm*-SsKTh(TP#Jm72Lo1l&Wf`6w<0Q`mm67L*V8AL*_b2h~pJYm8C(pxBU2-SV{&VDYR(Wp35sE z&y8TfD$n9L%aaW9?Bw|n6bburd5*c>D$jw433-ym9+zjSl;>WsYA?@Ikf}=Kc}U80 zCK%xIe1X`HlRW*OR-%7y0RvWfwjm;MTn~}Wq@6skhCXOEm*<3Bt2~DyCge#*m0X^^ zi6xA;-+@(odA35PDv{?%&YDZV4-9a5zD(@LNuCobBhT$%z$(vKah4~Uwc5$ED-Lh( zsDkIN5V8ANR zvN+3=ERXHv>8a_`{=?;&H_0l`(TE9ol4&xRrv?=y>YsmrReO1!jZ9S{&-$D-m%b1T zaCvSb_TwbaG$MYy>!Gi}fK{FYh)5jATQUx}ljlz8)^FhQoOOd$o?{Uc@+AKqT%MUy zo=zm$%d;0!szjbsq&%Mh16-c(6Z>(JXMSbm`8^o0%5zDaM)&85Ex2Dm&w zC-&nc&mlzoc*om6!GKksW8y4Na+zT#&ve)+1-LvHO|i;zI$}beohQb>LnHN%sg*zh@OhBUXgP~y!k>mk1blBqIquTAsBBd6$pUNit z#F4PFBHKhkmy8nyN~sJbgvm}ZckN{kjZ74?%B(hpjXg;b@A0{#f#U%?S*gOXkaOfu z_4EvW88W{|1E7JPF%muiV5%5eU_ph)6n!QVUIr{U&5{7~;JW$?NSOm*XqY9X`m_{% z4-&>w!V*g<)hDOwUhwlWV43VK{0-h>Np9JcdG)iAUT6Y?#TL5$7O<8?{W`**5;XX& zHLbZwbB4L+nXGD7qs^8cmzEW6cbQFgofD{{VbiJaLa}7enNt@PFbhyvaq5QvBnwWI z^{|y*8)T>p6TQbcFykC_2>NAA%K%&S`<8904{uCe$F@t*e9{+Kdq0}fD4+^oVB{%I z`-1Ic*agA=kqIZW#eBwx2&C~yb6Ah1>}2Fn4&KSYQ_61kY)`PYhh1A2nV&Z^3kPGD zfrG?@+%?!-mW}qCn2^N%gzaJJwSoUx6h1whn|POSCANnRst*(=?DJxLmR&D>md$7h zpJln+4;xtMP2Y8JAIXMn3FZV zX{7HZUgu=+CbYac!<)b4hw1RU;D4@jH2QQQy8-6K-8-Pd<~c7;g^y3G6(wMOvKtIZ z(u$E6k+byMk-a?txyumfPJt2x1|X2N`6o+}S2!DK*`ok16FJY&tD~G70MOGBxEFzJ za#ZAQ!8C6cYmh@uic%3lcgrRRMO_dk=S2FaA3L>+0mw;#M~K#3 zG%Dkl*x2cyj_VA+2B>}=aCTC1*4I{~rcOst0i-$|s~8_o>oo#)HYF~if|@xUxetQ~ z2P46Eagw&066QM{*$W|uZHRcsF_*puSg!$)or^zZfV#RckG>Poxd4Q|z#rr1>{lPo zff889R$<4_NL!l|86Ke>D-II!TT)fEju$B#DVZEB@MGCwZ))z7zIYW zP-nFSzs3)2o~31cFi#F4bM&q_iR>4W`^A9-lr(<_aQr*~8=U&K zAb$#Qi&zo}yup?NRKkk0HEjh#tTBLsmDWUGV3n|;|HW#DcKoC7`XvxTKD&;*G>Ql+;N5u% z+DCB2%bGMdN+CzQ!rL?3?wrHjNOB*c+l5;`;nuf=m0*szs}zNgFmsY6-7>}+IcR2( zZWJ2{XM}Lo+ue2R$OP@1FOcOPGYc7O<+B-Q!|P{vm&nHbsC9R74{~q^H#b4M2)OCrh;4OhS*aWTCK9rOQAGqS1$Z!KCRkxN@-6-j2l++mmIXm0LC-1pO zEs1>bmaubBQqKb@X@Z%PObSra3)YfeFiQIA!36DfxIJTwO#C;^k^(=vBTWzy-YSaN z!G%;(J>)#_D01#HbN+R#oT`r|4`1S9!SszKY^Ts z&72dDmGjoe8M^dGSO&Kk|1@^P4C7d!p1X+6Mb0;PLJ?cY!}q?#;E<8RCG5WZ1g#0; zYz?A9WP1>jOrBz`m{W|3p+bt-C9CQ00Zvhb|KMTI8lp~N_yc|@L3*)4UNh(NNSO~ zcc->7YGg1%vPSH=qnt%-1<&6HO=BPBzuL@y4?=L3-zC}7h`S`qMohViSff{{>^kUf zLlI(+n|U`LEidKz$(+ae-k}WmpJvTZ(8i)3Vmws3r#iGt2VjZ)DY5b-YjKnGSox{x zv9gr!Tl?vmND_`J4*`-p4N=okr5__ccT~9;Q0|{{Jpys_Pni|%lhVcsrEol{tmzUf z=x;K1`FtWBP=4B#){0u#a6p-GEC-Z*QMJMWWr$uvFn%eY4kbb^^DzWg{$mKN!jB<@ z9-~E){H1(WJv#-9iZ-P!NnF|EQy!7S__*>A3Ht7 zHVf0rDN`Fu2#P1lMve;w0=1M(TgO)-o!pd$*=?eYprW4xsrCPlz3+~bqG;Zq-f(Gm zjsrZBgp+JS5X3_PNg^upB9c7Ry%UZ>RKPgnn*v)!ckkClzBsGG)2M(!A| zwhl!8X#8wIDk)$D!KGoCF%iTJBC+u!d8R^h`HMHB;Zga z&sRRI418UwM*p?4(F^s{sL~h*;%lmBzan8PLgU9=H1SwPDwS7}CMe3f^!=5MLex)# zPUBq=7g0TViiE8Q4KH)GJ4nD`kwxWIWU5k){)b%Fq(P~%4Vt_PBA<=`JFpeI%>A5F zpLX084QfPQ1TX(e{A7HEHMfo4R4d^Q@CLWSPg5i$-x%e01`Ah+wx+bMdcUN|pgS~?-rCDc$yLD)DP3y9) zLp!zSx^J{uk=6sFlE2qHxLf?5~rl8zMG+u!I5!gZI> za_N#k2DR0IgY{(SQGl{(-e?>G@hFJ=PWWk#;MoyE*AZ!z#hel5)Xa>-DsFw_Mw08L?y zk3n<*k-rs6kG2do3S62S8;3w7Avs}&nqnF1QIz~2X{b;Rp4Ync0E|`tHm^qWb)yG} zF=P#OKUmD%`PhqIDlhB=wWT6PHP1)D@DbHb@dX^Chu)ge0CVki?^7B~fszB)Z=&iQ0Ec;*ANC zi0V9fVl3y1dnKnC{q2y<^5-N;WXc!cIUm0*%%m@|4#_fcgtG6a^{Vhrm^W~|V{L}k z=lR@25#dGp)?QkqXO1VrEA=KPEHbgl2ft2i?QM@T3dQAMywm_KIM+|_Ktqn#bb0t%bye#8!2z(0Wz(Gn%P6O{8 zahk$tcAghX45+DO9%N1(y^(vs9q3b%&cB{#<=#jaN|}mR%GP!MwKC;1Fblpy)jxn3 z*#BSli=_)fRq5Hhkttvf?5JiQ%wHUMBg4U*BfeAAyPzY~!{szZzQ1+oNu}tde1CF* z7X$EpV1{({CEf&I#_7eyU#d9v8&DQE=2 zyGStRX=sw+$1A;)koK~WH)r6+x}0lWcl!WT)$J=$?#EZ){kY+$1G_@1d%(+#)A;eD z)%dQ%XzW!rrkkk7&dqy=_;vWW)XjT$pbGi%Q^<>#veuP!wcj67PfbZW9|zII9+i^k z*bErQqu}u!2jyJoYaG828KU>E)|GT2f5QR=9|t!?FJY~VU&MMb&>Rb9?2Fjgm#?L~ za?Oi<(P|bRqF46Tm2{22@}R$PdFge%7NTQ>tP5%UL5V*?OSJq#eh9s<$EiWa2~h2J zyx8G4^W(v#4`I#$a|DUfEBY{){EGf^aOvPf%qZ|XkY3bVSGiu+--7a#PhcE2$Kgcr zHrJf3^IE^Z;9->E-a7w4N`hMF=P2r^TIUi7Ca85rUzJB+zF>s{s+%fKO z|4y$pGF8ZTdReR*zH^5H{GHxvQXilBBx0YEY%090-(Bv60_t~{J*kice&dlDp5_Bc(!o zK3@9#2`Iom|CrQIkk7;A@%bJop!$4af_+Y|ls@mnzI_^_?d8Ix={LsDYmhvK{XFGP z)z1aEGyS{}671(<>E|Gl-2L1YDHY=9tq zE2WrE?9aIqRDa%%JJX-^ z?G^iTqV#8NB)R*uFH$PRpL3-@-+%(_&u>Zn1o^Y5JpN3&+v(4>3HB$QWAEnAK3MSB z$o`xU4eY)B?!}$yPx@4i{kdEEvmuh){domaD#V}K4hkK9<6S7g{`{HLPmn)rP~l~5 zpXn2w{%lT#ByfyH-v_$+vk}&<4zNELLIc~M({N|{lRhA1e|BS|RWnXOlDj_#Bc($8 znJfMI0Tf_=9wPM<LN@n^Mroc^4WV1LqAn{NKxhvmoWDKrNvf(Euf3vp-qlRndA zf6kZwY=tCue-1-Rh4}L=>Cg30fc@#YH*x;lP#%BQg#v2-S(0FX(zmg0{(J|k$gSC* zZ$SgwpO2D3>f`gBFntWm{!GE=yEGnZizIh{jzUU>_%n-D!`Vqtfc=?vU*i0kO@)^= z-Zq8;sy};DAqkAP^aZk;KWE})Kp*yJF*LCK`7{}X{Yjr3vpVO_HD8BZFeNO`*s3SD#W*2rEm8@0rqXJNs06Af%5paH55>No3SggZIxUp zeR~Psa^YKY{Kok9BD}Jj&c59MZEWAZM#f>^HircJwkfHHINTda?!KLjlnU`}2UZPd zDnSAEZT-oK^KE}BysUA!Jrq!VJ0iipC0DX<_n2=jv6#=d{SAzvnzGJX15yd;|AAGIQ{!jY2UN0yi4yd|PG~^b`0a=gzBfb7tm< zg-JMe5kJ-ifm-GZ>MMvFI;AA41<6+`cnT$T19Oh3x!!({)wx&AIiico=#77(Eq_5N zxLsxydRwGLJ^VHo2aBa6(hBvY$8Ok(AobZ()7@pcZoc?>CZCBiGZQA2Q{w z9HeB8q%?CL!x~9BFW18-ujV=a=sPdPADX1vr#hknw}JOj7|f@P`i)Vwd0EE!9EokR8V6*w*R@xMd0NK0@{H+KLP`bEh_uRAG8 zi=;$_s)CAr(`m}A#ve${g7^=oqSQZ}YLR(SQTM-|-U925gp6@H2<1PhJC#OHR&ai0 zbw*~t@_nq86a8f53K@%Xv_)oP&WUn*%aE26C1(64KM;u$!`}CCM9eAuYm(Uh_H}#^ zvxxiKt>_`_{&pF4Slr)Itmgi9qU>)kLy~)c`yf&(q`#dj``bUE0Qa{iJ&?Hmwx~S) zZC5Cu_P1*j+~3l_6y5sUDfq5Q@11!j{!pm=PmBJ#7#61$$^N!?On*B%^B(lig<=2% zxWDbI_P04M{cYdF^tUSp_qP{)VsgxAcequ(%Ou=K1aYc7OZq z@tDCrlzG$0WS;M)ytstcmNRFzGv~j)_uj_+!&2Tmb*`5u#7i@a(4iNKf1^b1peJ(& zT_~xG&0FKp*@dGcYp@2Tj%KSVu8+kHQW zZBVRBpO%?o{D92wgZVPe=XZh#Wxu0{46KxaVLJX|90IqX=4)v2AYvxwonj~ET~I>E zQPm7obtZBjbyWk)Qk7#7;K9sF<{aZlivYKw3Lcb1K*&MKeHf`(7o2fi?x02B6ub_J zPe8;x_@%KAJ^=Rf{Ay3_^*QFaCM8lET;oXqpe2aVn0>ZP#@lK9jb=*ZVQ`JlQPsbR zcn87@K@?QbM!9mL4N_*q+5Xc-@+)yiM`xkuYgH*3>)eI+Hb5}eQ` zWyvH1O9&o~u)tjpgHaYpzMtHRvs3l`dTIG?XOmn(fhyV4C+yaqqbhkCl zpGP;=mGM=YH?)3?qRh55Z=T~xUP?~Qb5#0ra&lhR%at--O-@F6p^eJ&hW?m2GSDL1 z!8NAi>GpsKy`sqQ0?`dfd7DID0P!BDh8)@`o97aYH5R8mVKrk{ozM&u^mrQFRV>I1JWQfv{A)?5bf(!-wQLsBQ z8lWZ%8U7e#_#;P+jQOONg^ai8CW?#=boY-T<9P=%p2X9+BjX;VFf!f&;f9PCqsaIg z66He1t3bx|HzhJY1mTX17m&ip5Fi*CKY(CloDG7JVSr#{^m$7`MhThLLPkm!Zpwm; zEMzDMpgebEoQaeKAS0X9vXIe}ZlcH-LU+d!8E^dVwL+1mFU7RL5qfADZigbl%W%Ir z8CZtlw&#(i0)JwU5Z=WJ9csIXk_f{ zyG$h5YkTvqmFsqil39{wq97+q9L3ULPTU{OqMX=O!(Z?hxe}hmlwjO#&tg8tojHr4 z5irkUy75$@nsE)1+-EUQAf-ZPF}bXo-$XJK8%^gtc{(;{Fb>3)1*S7 zEtj*H6>=7{dWD?De5%f3iq%=nM=rCN6^EI{6k`^13hF7>EM^s^78fA%QBN&KLAZRg znD^4v!x*C53j zk^GHW%v@5-8j%#yO>{)EmhO(_h{Q3A`O+~~Ey2^dk5xZL3XfIO-*q3WejOdFo&t$- zVPhA@s+*CSXE8NamI4jq5JVUm7l2@7w1zAr<4$lG84E!$GUgyDij3W4S_>IkecY5~ ztXcyZ3VNeFcVvu5iiM27F^g$VYFWtWMmJGpPFYnNGSZR4$hZQsjEoDwVPu5CVPvcT!N^#Iq$n~*lW8qv zOre{yAY(o<6bwOm?#P&dlmsB-EmF%u#s<2HBBO-vjwLc2vzXr!F^dUQ`=@3xhhYAH zWERtIwVcJ&15w&62G8xB#k~9fXE8iM&WX;3qLY^>k=R+x;<0|MQYwAJe*oiddls{a zrUCpehDN|VieHOC-DHSq{c}vb>s!fx#m`)%PHH+C$o>|NlP(YoNC@FRqN;7Ge z{Nl-3U#N09cYeY?rsf`iY#BV-@gdqk(7I?7!8w9<4zw=p9;o4{hin*PnmBF~%<)Z? zNw8P`QW&8pndh4-_44n+%@DfTQl+_Z25hx}Of>v#`=x_k&zEdmj+FbrG;RVBCSoRt z$3ZxDg3_CK+vkePA7bZ+2KccqabvrPklWJ6*uS3d+&HVp+1mM4nz_%X)2xkr<=rk6 z%l@~f((1o?>EBfmp;;=Usjp4mx0l#<)lc&Rp7yt0(T}|Ty+RrDAnxksv3kWwL$DvMR~8+Gvv{FT-PAQBa+ zvZ?U0uD1+^0&1k{NrfbEy@j?+cZ*bK-HAxGuS(9%N!tF7j!1PkTAtjsi9^*sJ5+6@ z=C`lPdB){W%TUz<#D8_DqHQa!3y)SeMB7zbml>*PpGxbJq3Qq(Aw$)#Ri;y@+EOW5 z%Qzn9`L#;@{3mhKlx`?g-2)S?1tXM({hq8#@9s;^6%D{~L?y9Wv@2Uw>h5cwh^W-- zZ$zcMi*zL_9jGE)BF@F~{c+CGN1SyN{MtpSG&V|^p+=l;tb(tUCp=? zN$wHn4Wv{^#2L@3`HjYS297wrKqM;SgsJedMx0?#K#e#HsgMLl96CmUBTmf!Y97aC zbl0SkKQm^k{`{E?!v3Vw64;-`Y_w{|{YY~6=etO$5PxoE)%->?JOleP2SlR$d4LKp zt3O9U0o9)wI0q$>{-nb#-28b1wi3LL{aNEd)t`sRAnZ>%UxNMFlvKiqU zD#V{1ST(=V8qdJ~yb?sB{MnxhFRMStK>^jDBNFUSI@H6>pXXvn$fwz#Sr4iH^x)3) zC!P1f{+uZNISZ<~`*S@~D#V|2r9az4Yxd_*Qa?fa0~D3VpA(>f>d&*;^xoH z$$o7W`?G0S^=BIHOn=fDEbPzS(w~n(Rd;`GK}v=AQ~QoWhu`Q5t=XRiq<(_@S%V5M zYx|rG1yp}Fr$Q3gf70PM?9VU7Ej@f%T0NX;@%;lh0_{`$L$PlqkK+imhBzl}SVMfh znB3}Kn#OJszxBa6J32NqG|yCO0BRU*ty*b>JeX%41b&S!TUgt-o)5X2;*BAG?RHEc zl@CejOt-Lj9}hiW!@@;PF%k2mvh3v4`4#; zlE)PwcZ4iUiw~orNI|QImBWC-;P7EUL%@9ysu|TlM7NwQqGZ}~at64x{=5BAqs$T!duWe9}xF3yQa)+>K=3hH@>^X&Xv2y(_4r+mJGs&y38AJ&Bbc(YfJg zDVtA@TWe28l3o|di8^yg%jd&5zh}o@Y#tYp68RE`&S?4c&x9Ig$^d#`51;a5?12q> zAj!FUa+H4zr1N*IORpsYaYyc$74b&b#J87pYWR7ssP60&XPueLIbHL}5 zc8=%s8%L5Mn$zPRFB&@cbgUz)x}3FR?@?`?EU7HRSS|I3>3(fOP3s)UZ&5|g@73g@ zkKL|eTwkQ_48N8o3R1n=Ot(fo?h)Cjv$#=*#U?QL7_BTp%adWT6pSga;p6Ts@hn0H zH`$)_KqrV~V?CbMJV|Q^SOq`hHhPlQcyPG!)Ite-l2&UF|NkT{Ejd0kVO>u>;sv%Y zS2(415GLQ$7Xjk{tjz~e%>vS0tN$6-`$V4hlY{A;)o4?V!oiP=L>)S`XqMJdY~mIFG75H2E0{@PSlyBmd}u zR3XQKRGkEGdoLnxop^Nce9*kt*akk*c$09zK$)FU%7? zlB#EE<{46&dB(e&=fC(!s&g&#@R3vnFi-SIs<6X6%8^tH9p+Jvq$*a;W1qS7UwkB0 zSIaznB-Lb?Cwe5+*3!&#pfvMj>`@w*ZJz()BdK~)Jcd#DNGi|V(vGBB4-r0+sxCy1 z)sa-apvze(pO2)P2EzSFs=-L%BdHdENbr$VP2pg@H}qJIviV4=Uh|YAsX8E;kEHq) z$$TW$%}7q@kyQPu3ObUiK1%+NJZXuKq#8kn>I*|X3N`sis*@h|+DB4Nv<&qDlKDug zUPw;pkyLXnLmm20HI(y6svH>WW*C8wqA1`6PYTv{mfx2=1^+_!oHk(ECrra_QX) zxth4VFuFw?ya*30{C1ZZE*h zEkWEFfd!aekTw@!iohxuhTG@@%vx}G0p>w)c>!h-i2uI;b2JMu!^^(_vzvT#9Ts4& zhvRqwrZoun1(<42+6yo~a{*==giBq3@tF%SZ$PHB1sI>X0P`(G+!kP3p+;VSDX*0OA;HuF$rb0mKV3fFwSm%1y=&gTc7ua#mBhgWWqkfOdbixD~-AfBKakEsGp;HTtP*AnpEE?g^y)({JVSt0SytlWy0DRz^1{ z-VBWV60Ae_CoVqMF>VLf5AGa3Yd*R-Ke_uH(UyX;y!6R^vG!@;WuA4ROmD#gA3*2-;yK%!!$^yUElyS2gs@U;nHSQd^IqsQw++>lqgquN-cE`;e zq*MrQvPn0>O$R6*#Z7Dnl{jruQNhH?48!z|D9t;^GZyOSoB!$8g6@8nRUgZi+}Z!p*bL zAc~s}#3kJ91h@RSsq$jta8p7ml@&M5pn!^-lzk}VSm5R^{5{wWH~q0FwVQFX7OL3s zW)bcjxcME7SlnchwuGDRNOZ@|1f*05Zn8-?!cEhc6x{SDF5%`%aLbRI$;h3scta|c z6*o^q0TnkBsgPrVo9FTV%?&qGu!flup!J*XFRQp|hC2stMuQQHo4KSd;iedm;f@;* zvQ-FfibyxY&12BOjyJ?5+-w22{J2SbC2_bZA(hICo5oN;#ZAhuDCAh+rpGpS+!SNU zyD8(Q7^>Lu=4sqHaI+VTSlnchwuGB5NOZ@|IHXhvZn8-?!cEqz3U2xnmvEB=v+wq3Dgq!u?mLE5s#figB38_?8+|-2vDsEEtqmW~Pn;+kH z$4xd~s10G}q*7UNQwRlA+)SiGjsLdZi?_2?zs6GDHVd7BGQd;GXsi8akGKAgqsh*EkAA!A$Ov1Q$i}06*twEI&qV7 z0EHY2+*Dubj+^;-T|b|3Qv_A)cvFZw2X3~55sRBF(w1=33W@Hx8HSV!!A&;lM!3m% zUBOL%;u3By0Jr?O8HL=5!p#U$sjRq}1_d1Ph6*_rxOrxkJ8rh(>yBc^O{+Il+*HGz z12?%~#NuWyX-l|Sh{tfp&9_LY5Zn}zZiJirp|~Ayh)cM67u@pW=4a$i6mCjLrLy8C z{Y@usQVyb!V}YB`KXk`U4SWo=n{l%cs@U;n8txpp*$hT3Zn8*Q!p$j2bjQtLq*MrQ zvPn0>P0CveZu%3KaMKCg^5bS0awiHmBS@vP;^tl`;D|R=$g#jpuXXOY>4|U0Qi8O8 zbIRK)Zqjk*z)gQJVsSHbIiZf=JHj(9_b91Gm6z*l8% z>&0*3%hYa+n}#b?+$7=7ft#LS#NuWyX-l}7i^p)s%_gK&2yTi<{^xmx$mgBxgB>7+`JD) zEN-$$Tf$9kB)a3KFH$N5H`$~c;pPA|h~lO{aS1o4zx#J^a|LoI3O6H2rLyAYW+%nM>LdZo-gu$IZt`sSw;0k#2;W z>!ElQHyemcxLE*h`QyzdLdZl*xm9XG3y zQX#l0BHai#*Ff3Q$i}06*qgJfQp-xKTycAz)i^n8o3jNn-Wr~thm_;1ytOm{E0%2 z1#Y@8bjM9M{Kc~=<7VOqDsG12&Viekz=*|77HLbk@gdP2H|>#9A-KsV-3T{Zp+OWk z{fSGssrBLC!A)1>P84oNkV<96&6Q9<#mz)2iH;a%`A-E|b-3T|mp?DNG8;DD|nGA0EkTWACFEb_rBY^HNMDsbO`d@tN~ z>^C6q4@C-wL5b)VKI6gREqopYmp35q2_m`y`CLk-4an2h*&C22+Z&JHgOKsHfkHEPA`ivxL~cw$dLh!y>uB~Q&!;`f zchhqvem`=-em=#yA9;mbHxw13;of@-mN5~PAb?{`hpW` z(NEzwN%iK69^eeDHpqHfO-r8v={{f#61kE+E1Eh@^tu$gy}ZZG&ABu9YLOJbGkD0c z$@%-GY;rC)5n2knA88Yz-HDLap>AZuHR2>^nEF7ZI-l)B z*Ik92JHV{P4ltup#ZgA;Jlo?v)CN)lvr_#zBr?t>|h<(;U@Ky>f;4N<&V`;ndavtOhAc8o1}#OujW*r!ND#u2OWXYz!N z-%GQ;DSR1(2i8;jr-$2^t;!c^!|YJ3Pbi~T*_9`3xu*;2EVFw?Ad~8zg@406(asZH z+qtzg?Em(Q)m8Qah5oD-xL=AH(}i|sWuzO?^d;y$kn8x`;Es)QbHE)&{j0B2C8Y4t z8@^6Usc%HDT?evL#6c_{`Og&V!8H3~+-!sJ6hQ}d;N}2sQ1r&C5Z@3jnzs4}w?$v{ zzX{+w0dp5naMU`yOS*obq9Zr$R9qHs(hDDK~OH z(xI5_{HbVYyo*FW&%rrxSx>DycHp9go>O;x`b-GtArDJ@sd+0EiHxPbQ}e!XGCGIq zR-V0aWN0C6_;2q?$r0QK71!1}+^OZ4_FiJ7qzu!88l{3{0FBiSb}=l6%hwvqv1f&8|(Ie?p_ zI-bs<8`SVq#gmceh)17z5gB$XXPYD)=Q%m=W0mnPV3j`yMP_(VKu`XZN8fecRaeCv37kF_qnTW8Ve5D#nMBL3Y z9u?YF$y=jT3(b3I+DJOUv;!0+L%9qjfBKaW{K5iP1m{$OzI?@pzJ~k#8f{%>%z+9G zLBO8~eKg4k(dK2=#S@LCkogTvQ--D-106AKa(9Y&S_65mN&L2E(XlvUN9rN3w)qP* z>2a44V#S&4$d4*L(}IU2(vS)mr3gP|jY}>+#2r7_|6u z8Y5@;pjFP}pq%YDh02L*zx##$yXad9>VGYSrw4`>f>bb17ox*~w0+SQWpy(TK|l|9 z9>yujBHa;Z-nj_o?u}&Yf>@LM8F<1G(vzCc3BR(YQkUS|oXL$#P`$ z!&>emQm2yV-iL)2iB~5??z1k4Wf>!&-qCu}1rluz`L%C+NsMzXvR_gnBK$Zm*AXH&9fs;koo4uU0?aF7miqKDwrc=Wg0Tkw*3t z2~ssZ^+TTHZL?u?UwMu=h+~?pEB&^h#)JR4kf*`FQH%$r@qa1Zt-y z+kIuh@0+|@Dr(EiqN#zrGO|+Jg?2UeqpMi`g5MvKEw z9&AOGjs=+XMSdWi>UrAz=Fz&v>l7Ago8=->Jr30z6g&|Q3iUWBFvlC={gmr@_&_TP z6T2x)WO-U0ZJ5x!GEB5ag&ZbUd~xJ3F%&XK878hoxvpViG7{Xw#A`@#4HG+&;2I{X zK%c{fiS|f8LYPQCOqfV1TbQUpHl;AJ4b?`&M00Q{OlVt54-<8f<{Bol{@24q4xXID zL|YK0g^BuQ4HIHU8N$SPPm-oL@_dkrBSqqyr0kaY+{i|8ZL$#u4z*1-;x_3FC5?IH zP~K2tJ&Y1ctTF1@UZ{Ser#tp$zy0v4pQx(NuU8a~3@0bLsD5&pRrla9OLGZD%efU> z$MY3GkpB^?SHcL*7!AkQ0m0`gc0*&)n|T^j2dVYYVk!|V{@$h!2lp41Q>(P>=-Cu1JeDL05h zE0#rVt)cvk{68MUEEERHs9NdNkyEe22$62y@@3`UGt{H4HE(Lj5W}&IT*%YAliWlwY8cKWHVQKGK_Xxaa0YMgTxj1 zEw~)FSAz&uRRvdx8b&>&)B-bCG?z)vp=Vo9^8eIo)m%I;cOkcfP`VHYD%yE!ngIqD zXGFXKVL}A^C71kgbVs#nq08|C(7NRXrw<4yE`~)H+&!L&SKA#uYY^V}9D>p0_Ku!&sb3Kh*AE8FB>G}t;2rp}uH$c| z^;Kk=O-y^r{Ic*&4Q?js>y(AJ<8Mn1?ZvqV*41K&CpE7~Wqc-ZmcktIyqf8DS}Nz$ z2d0>MwlS{6LmcH-0@0V~%GwCqs8=9KyB2jDlTp|$L_7=PE)Z;!`BYbDPoMu}o6utC zTc)1p8>^wc{XGS7>3fP_kKR(s_XgJS1$Y0Ldo@~QtQA$_}g&Ni-q^iN=LCz9gl4&YQ{47haa zPd@b~O^J)%ggoPk%mPQ_j-`XiuVEBIdIo|F_b|D{MU*j$z#T_i>T1Rl7oo;j5AG~_ zCS2U<%%v3SboL^JJDpR$F0IoUiWH^Oxfi$YolbY8I6IyE>(PxBp)NdiKjV3%&jN#= zZv$!YM|!5QhPZe<*0_YYK7Y{oj<~F`GqnDdesW%HXw_mx+Q4WYPlT)!7l+LxG7;8= z)P6JLukSHJxd_{(0|MSigG!Lh@vQ0Z(Vkr*)S^G_fRTu}4H|E)gCSlHuMvdBxnMl= zGi;yZp|@zE1nTLUKxw^=lKh~MB&B>H&pE)1DZARuCYyAi9x2Of$?^zjE`)!O> z&MBf8=FX^|w6O`jk$e&6#7!MEPQ1z(yWXeGJ`s6_#pG$WA7a0Gms58W_z)lSpDLD%`*nAC$ZCM+LqH$qc^?_J#5*aJ zj%4eCn8YrXI*{JiS(o^vu8Hd3nVB=}{Zd=}Yi5Oa z7-K;MkX&%;POnx2M5y~fd%Tn}HuYo^9D~6n$`iQ`)WA(w+Cr^POEYEmf@#Y9#mV`@ zQC>DxIS%V+(^0{LU>E|#zlktFECf;TCWzOGIA^z4TMfebcH{okWam=;q*T8>b}QJi z%d2gqOpezbQ)6FuOvUStFHn)|I%X=$a9_tf11YZSn0ZKWUB{e6Wx+_Lz3y0y^wQQb zXPU1xQry-tXP9ZpZtIv2;&n$TM}1*2E47OAqp%y3ljn$-@4?V>I^J^3PW2m?!v}Kt z(!^9x!qiBtBoKmzNCXw!0x?&-%n>o*&=?2fEgZazjO_KVK(N>I0OT@zJsFvf((8Yr zB3G}U{7q?I?}rpuuit?LSFb-$WgW)rpCkPUUUyx+mR=Xf*z32#oR-&}9l-UTnsMDs z++fT(-<6YM$K3jQPvdeH?XX3zil=QI@*(Ry7TU1i{yT3G9fkh7a6B@;Fa}^2O5p_l9F`NzfeUsbt)P3bun`dg4FtWd4@_J>KDoq9^SJfPed0boxhU12|JQJ@mXQqO z_QPoSMO2$K0>;&U@@lm~3?6sC(3&DSz0hxbgw&^TKe#!5I)K@2K$`I*n3v%mmvhwC zALX5aVyu_Wj(+#n@?ym~3b@tNynK+$qct$=(r@*&bFP)&_P^erUkArI{$a!q9BbQf`pL!QgcvlOexI z;B_H|BiDsYj=e54$8+B6>bg*b?+Zm_pIjH3Ypx63a2XE5MjxWjL7!jm7kn-NhVclh zei}r61N@AjZi&`~E=2Nql)Mtjy+IV*2u>b|(Bp&bB_DfT=uL3Vf$3^c1FunpqU%Bv zqB2uCIlluseyl5l)`hyN z4ClJgxyV$XGF_$0(7MoiMavAV3k}?=NZ{+&(3{FVee^motT6DcYwRbkumJx3!NUxn z`!}vlpo~4t$O~MdJO>tiLd{f$ob#tdIukeVVl|Bin6p(5t@K>4GI*sYIp20y`dYlu z3T;tkXr<>4=(IyJ^9dz$2_+G%^bjVBBqj>xLCh5ab3}~0HTLXU%d?*&Bl|HKh-5zw z1W{%`c1EWE7(X_GGG+B+@-g<~ZP3Z`V`vTHk9FyDv3B#)W(8{WLBkxCK_4`1qA(^e z`9Vu;F^$Vv%&$t(`V$!IIqIVCA~HTxDyP3%HFh#OhlV&A$wLD8kT>HmT*oXZxpXvS*ug`REiE%9dxUJ80L@D}Hp1SDXl=T_2 z54{x?^7_nE+=p5p@zMH>$+6dGp7v~XuFpKfJtT*^-4yDc#`?@@`(=mt3<{2Rh+2y5 z5C-FJ9HTv2Q`v=QKR{1OYbrOQu03EFAA#^a zh&7ebQ<0R4HI;RKV*?U^Zx;Mx{cQE${-ORR2NiKY+ZKe<-%L7P_BT<&>TjYQPfj(g zp76C(tjBUn_m>}Rhn18~cncd?fb0RjhsNE{7 z7s?{F^i`f2j`G4{G>q}D>iAY|mFJ~1Wd)u{)9Uyd+~kDCB8cQ(!;DT4aVdY1RsM&b zWsdSyeLrMImxIDklt2}>H zk$8(=-da9rs<+5d;}pS8PW85aZ`YG(ZZhfd2*(q^S5^GcEySpX_e{fbLJ%`05O z@-@h%pW;0QUu^yMoFgm`r?4Dv-r2}N2+>=3t1PhGbpvGaojKHFZ?*7te->*ljzH1I zt2C5o`;0ID50pS5GZ4m@M-gico!Nj0O2%GJ($M>5jIa22sTe!5Nw|92{KQA6zFQ6 zdOrEbnSbc*QKP@_j_BK?ebLdI)qjm>kJi-GHy?e#B5S$GeC4^Y3;wPeAEW0X1NQ+Z z`BphIe97-2VGM`3>v(FH_MM_WnzSbm`mt@Td4u@;6IHNiF4 z*BXFwj77w1A;11U>VG#}iOO8tMz_C@)x*4ljxk5Wj!D{+m8{UQ7?iOIiY+H%4v4iN zoaX3$Y|OE=G;?(K@hI;f`>#Q-zi&W>Tn2g0lHq&)k)!6)8y z1VVC9SRCh-Vd@57?0m`OghdaC@Y=`?K3W@@742N633k#g?4)DqrTE9{aISo;M|`Kb zJ=ROmnPK+`!!9gtwx075`#I%`jLDfTI$*K0P<#wQeyn*F@L1Km%EwybyWH)uPV&je zS|T5-#CohHagSwkW{dv(Sly75AM5Q3c&t5mEM9rp?7J`ivD68|W{wFtHP4H7#}81` z>cZ{BZY=SDxEMJY=UaTw$5#;+gYo=4n%LrtU259GrnBpeFMI(CXZ^SPHpCaM>c8F8 zf1|Dc<)nY-BkEtdo78`&@AvpB!eXwa|IRr5cbfV~>x|cb7z$_ozxOqIOW?n}n@}2k z%S|yrP8h%U(ReBJ-tuVk*7Wav9gJ3fpSBrH;{fvP0#Q&6oS#9=5jB<9)}0&IoFlrZ zjHW`%xk55>_Cf`^q8xl*qP>jEL}4{@alNcF!8VRN}*66Br}dYb=%cF|SU^IK!RA>f|}4w8aQFd%%9mhWJU zr2C&kQdkVZa}{FqU_IUcqA6R6iLjV}l#@s_!@n3QE{fdL9g0-*ABmXznX*D*Z(NFh}Vw=9oxwC;KNINp2y@o$7zqAqOWlQ?+IPHM6bdjl9zz16hUR zi(H{&&eqJ&%SiDsson$CobLb9QH{&8ZfBBfebdS|E7P`lhm_Nj;WXPOZ-m$W4XK)9}YhL7u<2Kf6a^dY|=h!l#=D7F$wT*Af979%i%5X-2z%RsD&FRpcLaoIwfE#}K7@!c7O;@A1V!}!NpNr68Q z5oQ%PTUCV1QbjSUC={5I5FPmBoY5<$pS6?n%8-Ns)L6i<`!nWydivYL z0Ax4c(=%@;-rZ~8i)}#WPEklbd9E!>e3-YG%(DISzTd6&Pc z1u$=fQ8~fp$j<9-e?3O!vjK_9iT*~+C;)>&c@HxfrpXZw@AvvoW>ls_gi(1v7du;Q zb)a$vqjH*HM9wr3xslM521L#TB7H$Dn4w!V>VpUnu@fbp0HUA+IH!P!L1f!l2(`yn zF4>T)L1h*Kjbo58L`7Wz;sz?J5XAWSqB_ME)dk?DqO41Q*&oOiTvm})*7~C_OF`H4 z-ld{zaT$_;n8t*zr%lArS0G#Ihi`3kL5c?PAzO<7dSeSXz~ztZg$nv||7?J3yQrd@ zqhJbnVR0|+INq(0(AtaV=gxnHj8r`!!6-2qGTt#tR&ea1AQj}M{Vq4{Lh&xLFeFx* zouDJ2tn{Z_ZGArEUIko?<{&t(Tm#}LlPoMbW=&;c$fu zvAbFC%V}(6L&q}D=_pIz?EewwF-Op38W*`7lH1}>-{I(oWBb)FCC(nh6LSdr(hgWM zgee?3Z2OXNR4BF}(}%R#&{jV^hYEqzNT+ zd1~VO38N8+(?AsDfjA39j1#-Z`k@E;&$jzz{o~F3c@2EdbtSjSQd_5G;+e>=@AY?t z>9&hop+gjb4y5e!pIk5-sbxk=JRIVOQgtqc4)3Hjz|5-pE{6-JJN?arsPjmAWm+>x znxJ?XLKv18rwy?>Bu|9>yDDuM_cj-2$Z^wZ$=Hu4;n~%DX*aXP5->RQyq`9n8JWn! zp=XU`JOc(to)6L{K!PLB>F}ujQQA^0S@Uq|M7sYp?GwJ|MeS}hyZewO3dKfL@-R)| zK4y_Z(Gq2jrh(Tdk}({N+laANW|;&APk`5@)xelPrz-%$m)%y_CIfO{lh4ye#M)$Y zoK3z+yPqGhWmRdDEt0XZinPg>X<5Ew@|9#vLK$q6ZE24=Y_cP5 zyTc~C(@J7&@-<5oiX|wMZL*U^3PmQ$WSi`gjEliwn{1a^hJ(R2`Np)#=_})GVu8D0 z0L)U7wkXytC8}BY8B5sBK#@tPT}=r)+$HL)rPBAM?QoRtB6on~_NV!FtAKTp%eoA5 z2h$ojFRtRn_hmIYrT zowPt-hfXe&)2$?z5~zvU&?(|I=4!c~`y{naE~(*x^SVhI@R%1VLF%*aF*hHHjoJOc*9wQ^t^Bvv^bpvmv6x$+Zn+JLI5JJ5^h5 z!tK~+Y7W&y=*P_#-6N0%ScS!B@HjvBzXFZHP@lV} z&5_f_ivy=~rmJg8`1T59Tbbly#w9jK&Kr9N+CxS)R^I?=TqyRTZtjTtNJa~k%YAo0 zW^kUQ2t)Q#*^KXj2!p!6WV{0g_wPB(kSp{97{8(CR>=U0D5?(#)HSL?`b{ut&CMHm zAC&PVSUV*vDe?=b+`s(SmkjM}8WQqI0;081}(3crIz~CTZNX9KFgM-A7z-4S>%(~cq zS4%iz3qH2Zuz(J?vpqc#Hu+Vu#Xp5I*`C+1NTKkeOt$#7l5q|g93+OyESH19L1MTW zB%U-aqT0klU(P_7WmI5utXW2>X5nWX#kfI>Gzm3GjA8&O7Pm?-qS9{(RNA9r+eL0G z$&C#(JCa<=AjsVsxX2*~mBy>ua$_0KK2sZu!jVB@d|Z&YU3$e161OoYM|;22ets6| zG$AnFp_5CHC?>hdfsyFv`<6I@#H$n}Y`9v++eaCu1g?d!85mwS1H;t7^$fO1T^Sgr z1#SjIeb(tVM+Sx&feDcqlLpGHPIWSjK_ZQ8%MBEExyE zU|<)<1%_EN4qS|?8OV=F#w0Kp{Ik`-Fvle@%t2uI95uuQhT$mSCy2k6M-<>@bN4e7@m}j3&G&g!~DQwEKvyzZZuB?o@T~XU~ph~S~C6u zg9F1efrV^iD=;jO5VQir3vq$rS=q`@MGq$&{;-6uWU(*9j429x&RKj-IFSE1(gYDu8)}SSj!wduRu7+vSf`Jc&>}#Z1(t-+H z_!-lJvbW!FG<)UF3F=T;!z}1@tm!jb9;s&6A zfc}>m08R_8MgFkZ-%ySong^-6uvh{H%1iUqm9SkT;kPqawO!c&LA!kvOAz(w1|tH`BTxU;nIFJLqNx&+B(D*n#3 zIdXi~HK@U9VR3h3Y2)*PuF`1em6s`+zcj z1Z%itB}K*%YaNX8ZxFLZH!`^1#HTId+g!TshugPti{!a7A&$P(iH*a2)hPlN&6kMW71WfGj^GhdqaW2Cy2em#|bS#XA@UC?3f63KfLwGCw>RO|-9?M9!$S`Vdf-DP zQj?z$;GRIX6=EGkmNQ)}+I&KsUCcQbbg}pf^a^n?)4wq7FCcl7^A~eW$;#l{7~u~8 zOtAFpf(KB~c5z8l)8zhqt3P%Q&$LydYL&y`-HTFR0apoLuAoKz$_DrySykcn0`Z{XmYap_m z>0w{D$#@71M)>034wl%3lGyvN1xc&0cm@nc_!7yO z1O^X*mIi->G8%xv{cN#hd;$goc)4uYl}?cz{4&Wn6%6j+ zS1?0%&F`CCa{;VwUHbdMbi;u3onV@=ekv&ACRFi^WF4@idL3R({Hl^Da zaQg>t=_(d9(XeBzW$QUN!q%SzKVVybjtq*eKb5wweyX(fx*$1E#o&6IBL_pD1-)<| zjEhWc?F~WlGG~&5p^Y|24u&=bD?tWv6Pb80^to*Pmw>^x`oadXg!X2eBL_n}WDHq_ zOzfoXlCcX6cG6B}NQ>_>E&la-#p1hy)s0Dz-Up^>anEP4c-3Y;tu_c^B}Gmo)y_l%7we z?+tczl_#vc_w^-X zCK!zShLUkEs^#ERPd8r@-3A6XxVn-N0fQS{7Bgg1X{ysAMCf|^KdbngwVrNlg!BY3 z&89LPl<^(vd`_~GBCmnMbb+GLe#n;K*0pss8Uw4Irhmd#ZP3DD)#lQwA+Q;3Ep&2| z8ir1{IWi2j)aSApe?cY=L#=f3ry7RNusJdewbq|y%Z^1Rw#u10O(YA&BVe#q+Au?1 zRnN9LG7NRp%{86Mr%QKqkc`v7V0Uz4hO}*G)3$pyDPgFyUfo!SIRPRj5~xOlTgFZg^WO# z#_>Is-c#@9DBVTwxN(r{r5i_*YfEyy^$Czu!jM$CkE${QqmK;(8HN;&3`2eN*u|oL zwg+Vx>dTy*2Tdcog`st%SV&(SuNZ<$+7}dteuBtyri;b1%<zq;$5aI zfxkkWz^NwZc;=Xrr-F_TLw&*3hv`F6z;cZkW zFgOfdCmEN3!C|OCPep-Y@g_>*<}y+zt->N73=TurOU8L%a2UEl&xAywxC0ChLpRGH z^92|jhHjFK-@stp-y#_gpjr+?H|pjx(R*NUgBv9o-+;jlZZtDwQyF76m0LF}O=XN; z*JyBtPn!y+8HVP7GR{B&MMTU)Q@I!21H3B`v zkV6DA2{i&CKWyaEE{0L*v-EC`(p}^pB)K`daU{7nNN%n^0dm{Lk9aNx67y7z858pu z0b$YaOxe&(hSZ$@5H-(^KQh`pD&2bnGI6W;H#0&vnHD4~;w7gp*M06IdryaG7z6>{ z7kQjmI#_RlC^#9!`yggTJz4MqSf7K1D?XCUy#r4;Utf$TRAMYS1wrYqtrW_ZLS#A9 z#iGeq#QA_Ztw0xxV$dr@N2WJ1{XM6eoSn=uB@cj(SKx#@p}-6J4pg;WtbwXz;yPw1 zTcj^Tp0K#Mjcj!<>Qr4=WP-t=>?O(ApDjb#%lfA*F%S$6Wv}R@Ram5g!J+I`$@mU+ zaVRU&w?d*&G=T(%ve#vxx(y6&JWC}b0tPppHzcDa^kApGCL`ByFu2t&mW)YYaI0OS zhO#%!_IAkh3VBA;-$W=|3F#m#VTQ7rpp1>Evn3Jdg6IHZwg^)z+X2y0xWyH3)KPcA zsPE`K;Fay7@>vd}zAKG-5!ejdl{$HeQ7Ze*Vw)pF*(&{Kw&GXF#AaQslRG(+oY%c) zb7UxcU;mR0do?n#QPxPT-vb64ry$~YedJStg9k>`nZ8l={Pm@SIP$Oa^K;MUd1pHG01 zH|bMgWHXdW)NWz}vuWg}4al`Z+zpZCOc#sl+lliqa~gs!7Slnm5G|N~oat9N)#SXu98+>R==fImJ-GT_ zeI2UWF0O;BWa0*9DBGt`LTXt2(oVLzUv;W3EM5hJExcbc9tML)We4;KOMHWpxXm5Z zNh^%(z~E4JNHQJ(gVFSx{tP4v#d~0IDAUr-$zd`I<;L@uj9iVt;7}%{#5yoIl>H&+ zf|c9LR{OhToCXHB+CSCFp(mXuhmMsiPkLSBDoDqyT-|~yVpp!#QZu_7vgXRwZn}LD zx7Ny4yp?<13oECjw}+dyi!UImSUEM_v~taJq?Oas$!!c<8QTIjN5-~b`s=1yk%{fB zr;~pMv+#O|po z8Q*}x?#X0^9Hvz>ZS7dIs+L~IcmUEdYgU;Z;?}HwgRNrLtXe{<)HSOm_rcJ0(#ONl zW_*)SuER!V^T_yCC!K(a_+}C^N-!epq!S`t8cWUlQF{IK7agU$$aN&ShUp(4N$x6= zYn=WQ64Fd@bg(D}6P10j0iznJ1l*6~C%sJeem1hzZYnI+{N1S2^ zHkX3CLez!Ga;A&LZ_H`VoRpmumQDhVZwi=h%XAM;H96gwV@l?Lj&Cq`fUBRGz8D2> z7a@3@8qA4iSjtXsh}5w7s-tW$ZPKZ_uy`B{4ohcA#@%3WSUNksHA{SklDN6FO((6w z;t?=7EVYx2v0yL=+NXDdM4?y=28X52GU)6BgK^(UGOD5$#(fvbSPlkS`awEo&FU(Y7`tYbQVDVB2FRAWX0>rLta@R3 zeYj=2mo^=|4Q%8X1uPmv}@0F@~0YxF19%`4E0LS zWy}7Cn%F9rFdhpJS+jZ*s>ZBY?T1vUYgV16z|gtrgJ5Vg3`ywbvXRv=l*_n77%~Yp z4COKcT^h$+Dm_2_AxG&ha>XQPq`z_`xe}7QDt#T~lrSV!9;&L$z!+-7K!zcOBg4?p zxG;2$?Lirau4c~R)~xQC3dOEVPuUfx7=lYXa94=OA+nt5VzG`nuQF#F=wk5#=oR8e zrk69lj#Ev}hs-f0zXENCA%35qJPozql0F@|5revzt>rW`28~I71{tIy*(zhxsWSY5 z0)iZb#!1FlFgOU^n*KUVGysEx(D-!H2|)-94nns{MvHT05V}2m6(sEU*7tI_u;1rT z=7^)d&z~qGOh=T-&EkF;loo@*acq)g>;r?N)IBmwRn*GwtsmgFl2iQ~IUR|yOTFo^ z%gprOO}m`uu*-vSc6lhB%nZ9gknIwdjIm&_T^>&V+_VcAY?s1x@&@bz2HWKk$!O6{ z+GSSyE{9zr5?t2%{3p5Tt9F^q68O&(%4EAdF2luQFxW0nNX9-e*e-Kqma3?g?edgq z7w@-mcCp?~o;3reS(x5_x7F??To$Tk;b&aPu132z3ANoXWTz`=v`PAm+NMMw}s00k*3Di#zGETE`JHzF1+C@4Nr zK|nf+fC_>rMI=@P3nDiD-*aZ}-FtVJ;(NgReV+gQd~!2$&Y3f(&D^;&bLZ|wIxN0V z1LWJ1umGjMkW)IS_^zYc{nms3d^q}psKf*2t63EQ6WtC3aE(bMW zCrYwi4kdiZ6ypJ4yL_HN-k2?q0l;=StO1k3g9l|_Bpk5W-ZzP8tq;stnL0scDf}RjduSKaX*Rl`!{QbO(v<_k=e5e?+wVzqD&Y?fy@OoUPs8JO_d~{oh3jhSr>Ml-m7FkgVhMX88s~ zo@K~Jq&LfjNUxV4a{5(HZ(yu~tY(O!+=+BpyFUq#FWx^MrN58|;CzbjhN|8B{PTdd zw)+G>RfdW4&N{yR8t^Ada(pNHmoUX50ND3Qev)anEQul<-vJF+1^~x*vi}WGgxY;E zzkUB+nxCddtnr<~6m#WTRKoF{$|Q4T1MuW_Ut9xj0D$AWs4nsd036>X{JdfRO!s^L zJlLhI{~+5Xu8Yks84-3V=O;7ImXkop{b8mCR04qQQr`bAQ*1~5Y?lgt^2Ti078Gok zpay&f0NW+Y|FO+3mHjkv5gG?o^V6J!)h-p8Vy--jO4u${m}IWZ15dU~RSj4O0NbUK zF0vW`w##M8E@!#lSDp{k)bW=?B&l|EU)HS%A7F1kHL*Tnw_=q&ACi`>*IGPnDt>^N(?w?K5eZ|V=9ZfLGu6KeO( z7;?6DKV|_0YvbP-DHvMw?|`1rBQ7Bf+bpIcUHvWJ!MD(k+4O0S7K>ud0F5kmfQt3> zKa64{?Zw)vVw0m5EA}{wUEv>rVz1bXbymf;MlIHviVg6;fnq1^#d=aPwY7vMh7GO8 zqd>nU#@B4FK`Q@uMB@!e!6nc6lZJWl25n}1!K;AfU4_eRAQJaFix`MW zfDNsU%Tge`<4t%=fbg@Q?f0C&63u0YK8AD7GY8YU8fW`OQKC_SM{Ic2P~u~x^6P>A z5E87!W>Vrse~OYdF{H#nn-YlyrV_tel}Idzs>F-_s((|7-XSF-1107Oxb9{DU6{y! z^GDnJv(-D})Tbp^vmMEnL{>U~9GI;HFlUAZlZX$*8XlQX@WGp`So&J*XLdl#oHBVK z&WS7ezkjnYVQp$}F#u7>t#F#|MNS)WWW91h^an{syT#R3ZdNN+I zJJ+{kmqBIzrrje*guZEK|MC%R6QvmrUC7p5^;%TxMkz3h3cTVUKNnM6Kik~VFv1GwzyBv4PO^ZX zXCO{q9egV{F$ulYYJWY|sk8zlzX~ke1&P77HvY9UaqyLZ8o$J&&IW_W+5vr{ttR9@ z1p(IjHyP3@0mvRKKn)ULt-roSfGhqJ0d_@L;5!H~KMNh$djDmxf_`#A{W-;VVpdfD zfYnB*258Q^J3^?$3NE)2Z#SU%3nAW7B*soc;x{C6=3Qaw%qkXfs?N|=@Fc-=vaQ%G zVEHCgAJAM^7hH!FyV{glBs{9CY6@Vkt2eG!yKIjw&h%Ov}}~tkcTq0Pr&dS{e|$pGCVmx zClwgu2W$gn5~?F-D1LLb&Oe)zbq#siq^p>OQw&^LCCAAM(65o~1w`rPgi`rNMZ!zXtYei7rNeR(&x z_?tt>kDGAKxeXWNS0O{j<`xfqa@YQa-Au!|4F)+xel|32iG;}MPFMX)tY8pb323fs zDC6v($JMdu$V@EYFXZN2Z)Kok(NQpg8O*?Sh&L}JW5N!)MG8kj4FGdpZE(HX)!iUC zDE(s*7^5h(5`Gzh<6NT*k_IpK2y(Wv6FHbtvY;+`t2U6v53Wv9sD^+J@gKK{agxQ5 z1!WnSM-kEuy@owHRN(`_QOZ%ku`-~CiWU2JnM=`knTLVH*oMGU;Ml**TvmUVc_LMU zD9RrQ2bkYwegaVXF7q@1&F?a=0g%7Tyb4hByUYgxrSCEy1u$B4KvIln&JrQ{=@2j! zB!lCu?kgYuU1l9Mu4vz7MzDy%w(l~d1IgoX2tZ4OLjKLDiy~nt#XxaD;s5+u0FwI= zeEY4HBeL>e15SN-x&M{VD_2JOobR{t4V?ejdgBOm9{er&C_Tl4D9&B<7JuinbkSRk z+r&A#=v+7V&mTfQ?w`-nak{zV%%eWKhGB>wP>#Cie1A{e36U5|J#;&=$fNH3DgaXF zoZlV^>YvBvA)&kI=yw9Qx)Z>Nk$0#2UeKN7yM8zN$}@G6@A@yNxE2NH>LlG9_*)=S zSSNWWK>x#? zrN8I+9M3I88LmDBYTpk3;=T^?;~Lwuf3Kcy%p*1P1GWyJ#Ie)#NU40KIf+*2SODLVev zxEMbWl**}Ux$}T1Y3ykfZwFx5LAX7_55nz*JN&w37H)-@z~B!4eLyKC3-%zD^Mr*c zai1$bKfO2n24H?eBwk~z{aXSD{E0dDjy8D|A7_LQ~{*Y|kiNv*+!mdboz z`JLvs5<*AzidU4-AxJN6gZ^e>)O%_;-2W`!%{w5o?{$hPFtO|ftExaBfz&9D(z+C+ zn6V-std}8xE%7vcZ(VGe+60;(@(J*@~qC_owQzmC6R@8|ljB12Bp7_^*TJa%Xbtoq6eP;5K|BiRQT-uzdNvHZUtV1W zBou2AB%ipL1jG3`_>uxS=!8i|4#Kh5vG7ET#?&M*oYOz!5waQr#P@;!{aLtyM{9Sl zB5c{kANXfLl-aT$1@w>TR6dB(5q;oqZ|R7}gVgMZ)}Xyc?TGdO5w#;a4#b7;h-N}4 z-4WRv;s^c_B>P4D(qgFNi}b^5m|FCGRO-D@%c_x<93GnzpT z7zX)8-)p)-Oq|4Xg}&GPYQ5Kp#K?Qiui^I^OvQ|CjpFBfuUYbg*-(W~Cc5*7pzwPD zzJ_x!5(|;Af8k+>Karf`E}*YGjC~Nq=lP)sOaoi1a-gauf2XRwf2S(j9n_h4o_Elb zsDkgHMf*m-gZ_1a?x60(^SgsKO~t6J?>xem_ytb zEqJHFO59-|*By2(0Jt?DkJ6ft`#V`$b9a!Mt$Em)TJyv+wdUCur8Qp%p`v!!Klpiy z=3;i(X73T{hoNu44?p`mzaqt=NIwWnxv8IVqxECiD*pxOl7__CEl32B$ob*=(9q8p zpIA|O<1dCr@MzZ+Q@F|fT%rdhPJl-a62rWh6G@aM3a+ILx&ddw%}7OxFf$jWZbtC} zN(?~aMI@+%qu>ps#x@0LBPE_j;zK0fk_U0c_#?h4ZaZDxG;TYVAj8#UZ8|2HXOf3EEi$E0lmENn&` zt6u+83tjjkn_B2fMwMJ)2kn5C zIm7G#@31&LDJ7o9&s(D4ULbQCSt#6C2F&jV0j~t`yw?6)|H0bde8VKSpUWg85Ul^e znAu|(=*@E(Xl8NKK>wAP`2_-Al9*{QTsNbVNSw79jZ8I7@=xk#ZZHgV#kmX=7c$U) zC1xIhfR`j@b{i&HaW0c=4|To&q?iee(2eTna~Y^&s3ZQb#7qrHdP!ntoMDpQNLc!r z&~_^xv>jgO5l3RYJcJVkCv{2|$RhakQ<>SaDZo?c)eiBV= z&X%>Vb%_+5h66x+J++xM@##{S03VxlVvHA47Bdh&>+!CKZ&*?;RuksR)d0*c2a0h? zdEhx${s_RkYXKOaL=&xZGJgudOpPg&9}g%-{io|nBNJ#kfm}45_cj|%haLsPo6ZSfc|XcGN$pxt)46?& zYC2Q6>GVL3o6a}7>AVR5H=S>i=5y0=&RFB*wsV5p4h34-7fT|peoML;EGS?6Rea~x z_eT~qz`wZR<=k)dJa9c=DY;j_0!aRRFxia6*b_*6h(y?8 zR=@DYtO0P~+s8r<^f>}?Ik#E>)KVXp{VfnQP|eo^(Y=0t9hu`DAQBA#1hTtKzR zA>(w5j1O>&+`7V2mn(o4c>s|7Z0PzOp>l4^3GK)7xdZrcYT1VY8ru~V1(cYA#EX(2_!fzcNZ21r+r|~k`3O+sm)IlDohyF^NT%?1qy|>V0Xc^r>@_lwjzY-6d;`rDV_3A zCF`^R3D#-Lh1KcArO_#ibW-6v=_Vb%Zy~|D{e%STR_5l58@`Rf|AIL%e*n1YwruOS zDw3|pmH%!A4Y$>0NU*YBBf-iRz2)L6TMPUzoU+})O)I-{pJkMj87OJ*d0jMC3L~i- zg~VpEv{3Jse51BlM&-DZb+w>9V4yOpF!dPhZ4 zk@4Cb&5>Ypj6{OWae;cbIbe6ev_Et2mQFf-u6t}lr(=drCD9dJK%Lrx-Nn(VJ`ErA z&sRFYLw!#{OCDNu#x>{R(U!r19_o7v766)Kn?Bb=ecTFg+r!U3E+`$qP@e}$c~C`- z3)W(QYy5m=0*UsjXv`m8ff#IUkZR0t8-84dv6!mnI<#|D&Go-n2LIIq{`_e`y$9gf zLL~N5qQeAyL=Fj?%w;yYeTtdLnQIyF>8FF01j?h@526+D)4_JIVI8kQf-BGCg2nV> zg6CGej>MeusMjb9xNlG(Krxn3z_=N+5aLT?5ZqbzO9dhi~AYolI?$WyULxOdk zjKsy%brJYqI9=C*TQpt!kgne-#~uI;E1Nn=E87(bR(1js7gO0e;D6zieI4AQDce2d z*j*rDU43_JU0Wl;x{g8OV(R)J_+L0(mw;O|U3-wOr<7yg1r00foUD~?hy*K}kHp1P zb~5;1IAs@sTQp@mha9^WB&_QxB>1kBeUH|4AQBf-*9qW%;dGq?Zqan@Lb`sa$8w-y zWsf1j%4SW`%JxL!Vk$cZ{4boc4}x1XW!r}wy96Yx>k%Ya*Yv4c*Y-$UOkMNA|HA1y z8Qh}j+JSW4rX0HnG_34CBv{$xd$qDnk+_)34g~)Tr|bl9i>7SrkYne7gmvAC1nXMl zKCNpVBrc||J;DFN={g47qUqX(bp1j(_Ce6FvYU`#Wltl)U2&EBFRrrf!T-W3n-6Z$ zlx-ez>|~IzuB(t>T~8pvx@J6ZadmA9{ufTyf#4QR*A}GfX64ukpkZZSMS_+677121 zb=t*Mwhs7TIAwc+TQp@Gha5WwB&_RmNU*MlkYHVX(=V>BRlxtk>DnILqUqX%bUmsZ zn-3aRwg3rM_G2ViS?7ZnSJ@2kzi`Sn1-EF*HV8R(AV^r(nMkm%+mK*gPa$zJyW-S` zE~Kt?z%81tmy@nrlw*5>hLyb^308I;60GboBrc}1z8M!%*(%@`P1!mj$F>Iv>v|^= ztm_*{u&zgtxR|;+AHI;fW`J8XUF(vrCzNBGf`*kHj|40GG7_xpJ|r%tvZuiR!nN4c zN1`j69dc|Pkg%>Jkzie)MuK(SiNwX!^%(eHI9+{@M%T3_>3UK*whCxi*&#@ujxWNFW}2Ie6ODzAS%rXssp-bDwO493n(~w|Y-$3GG>iRMGUpQS)fLk&_iC^4 zsssJ_z1khIDpS*sH*R<848LT%Kh`+vkB$mU(wGhuK#gHr9fK7br=vVJ6BY_fjB#dqsR_1)SzW2xG8 zJ(F+Obo*Ajt{)57cU{j8*mqrT2&i4x6Xxk1)3dBQrZ)!YRfPp|4K|I;m9Ih!zAew? z+wuar2VklyhBt6O&aCua>jExm-)mhED5m#X{|QdK*Sh4~^WSUjfPsvkZ&4sAzX1x9 zGx85W_*zKh+=>7(eu-;i-T8SSp{U9K8i_@e_!G2CkrL~47MGq_?p*iKP2yUFAlI4c2_?eh}EtxfQIbq zRY;ugwtAbZUkDT>bHo;~ujec{gRd10J9{6hVrRb&Vs>^>B-q)_kzi++dEDacZe$!d zTk!~adzj(vktlXXZ^xS6o=D!_1={G|mZxfPlaG<$IJp-nvr{-oW~EM{HPE3j`IW%bDWm~>#xMzW3W>!LCQZROdYD`T%%usF ziV)<|bqa5pox(b3$gVzw#J}b0)qzw?r?6__8GLQ&6i%Zm?iBWcn4R4K33hfK671}j zPgYj>i3EH02vF2%vuA6NY0!?@v+XE@#(UnL%|(H+^T02DkY34~_qP9|dBRX^sM#Gv9(TCaT;8&l1YEOI}Y@>GoiM*N-NuYzNxV zM3wD88=9y(_klLmp1DMa28>2UJT=t=3F~Bm%}~4k&l+m_r83k`!%(lD%}~4l&l>93 zr7~2_XLUrSAaTZs`uP8>p}IlrOLAVvBZi@Fup25g;dDNWOXghEf0x);mg#?%#QBJ7 z7B`oz&Zm?~{IP!FssC9LMiq2EYTu+)Q=Q`XrZ@qYPC`+qZ1`~!%0rURL+s1%>En3f z!yo~Dit7iQh&pi<=(9kj=$E!~gT7Zgyn>(Nq8TQAxN3@vPo-NgKgZb<2jqzRutJDg zG&$HTd2^_y&-mF9H4!mts^~h3b*NXUrWqzZ)kMgu&ewqaeF-M$UNVu_;Ztyy!+J5A za}<0Gtnc%{bX2{$neBvZbvnp0gx(}9fq{ku&!dB3*5DqDe2e@di(P`OlK&Z~F5vMn z!hZV4=Yf(DXMQ{`!;bo(XYf4`>|x1sgNFmtaK1ub52$yX#627+lUEd(m=ef*7Pu_G z4rFfvK+bgyL$hSQqAqX#Kw$0%F#l#GW>aD&5>F#x|2kNfvq`Q@+U^oVGI23}a(rX# zb%=VjWJy=TzjsayO(@*~S&g6XNI>Syw*o4<8rVNCRo#gt<y3kY>mEqlB`6TkNq=i=9YOe=N{C|Fh?Gi(Q7q1#Pjm zvp<6Ld=4;{d z=E_V!Y>iWHm5u*i<81dIG|s`DA(rv;{TPr@8eVrjUvI|wSz6awP*ED*BYv+S0aWXv z=rQY{$m-}CH_IUwQ)ImXO4XJuG2GGGLOL2P|Kp&ixI<5d;BWP9(Be z6miKuJ4He`AUV89@oa#Tt7<&mU)N$eWQarrO2=n~6Gbh|Y5!Z|ex z=hQ@V8cm#9g3}g*Q)9qjpVZqi+4wA*K?~UdeGe zlret3?#V@R#Q}m0w!sI&E;c|Ogtq~%3kOU{E|NzSPf$g7L3r=WcMg^eq!sLY*d!1Nm`>bK{9WJAn;{n*hWEz*)4`f@EdjP#ihx7%JM<8ss=JI|Up>!e{np{a)mO&-OVYwsz zv+5|`%q&hPUW?yMqZz$uJ_uIEPpxSSe4?E#%k0MtBl_LMW}aG==y0!}K643@FmZK! z90MAI;-CYI_-o?n*zCO2eqJ##h!Sh#^@jw@1Cl=+WS1e4D;wgPM+dn*K~ziQX(t#) zaP#?Sx4a-UTtSG{@yQC24M-lHKDUFwhh3!<_>3pdftC6y>)@)3O;t&}8acO@4c*BT z--%BcI}=hp4&dW*paqrGv54s3yt}@~k{x&Ez>ZUk8E)XS+xE+{*8%#t4f>G!T;bxF z-8kI)AxUTKCoa|>GMr53i9g2~cy{GT6y6tBm`&YVkwp5*pGtnZ^(vd6NS4|1K* z*fxRf0sv?~oyHODbLF1^Xg|@;i@f%5!&f#x^&vl1I)GJh_R~o66R)~wS^Y%w@hH9+ zGvZ|lVfyJ+KzO3OK7ma?o$=TZVH_JWxYm*|KRuos=BM6}>TLiYm$z9^?57D3lYhUP zOpLg0S==iscG>xg6kFc64PBqc&1}fFcSDs_?2@6P>HvWDex;4uZ-07d=a!Zy9kZv2 zto|LUetf0Zq$s=7R{aa8o*umQ&k*-VqMttw^jCglqhA)CzFZpUchp!f#kSox`qv}W z+i?-pTS(QPth`Q&J)hXBUlmdP$^W?e6A{+RD1qwB%05tk&wg9|>&RS@1$t0{*0LJ} z?)kZ`z?SF*CQ*SA@;21a@`$a#_UHwcQ-KHNc+`;frLDj&DzGO)hy5r(Vfc4qFUn0W zQr9LWA;|{$BSK$(ZIfglB+0Rb{swswytA4F_+HLLFdxC~!}8d8D7x*AQ-NehM-+%V zYAf(171$SHyV9k+V$fPCV(zhZhiyA!boNb8>Z8=J%p;CE%D#UvG?LRWaQX|+DoGF&ux&1~(yP zH%}{%{;IGt&jDF-krW-D!Oe+i)#KZER2#(w3qkNKTtL(o4-<6`RcZXnwDQzF&+4Nz z5@%_zsEj|wp#f6oP@v9}Qq+9~3J|SQU{Z7it^z^Z)r#7p08!^qmBufmz&WdrqQH7^ zx;|(qFbOHUb;`vwIZx~KPb{N_ij3mRfJ%8tisO;fsyWt!*vowHt&u?1LSS&V7DTlFOc|{5;5OnQwb7z({b4YvI_NNe0~i;7ZSQE=w2dpZ(NQOnqJtr5@>Gn zeS!YRy7?Ky3R98z$6DcY!wTzdRv1j*Ixv28ZwyUlACP$%3e|lbV`#c*tC7V1AfD+X z@4hdB;0Fwah}treAnF{t_Zz=54iKS%z-JKy<62pmpSO#VR}qu+Zp@YQ zFLI1H6h*p%MoHEmsVKvk`$6=iNwg$7(NYi{Gl_nSPP7X|jVc+{wM8mQb-#h=UX$q2 z=tN~u!ETf2P;{bJAj+(4RCgItn0~pI+)A1%w~~c0RrfIb^+$w7Kkq3-nXH&&l5AxB z$_P5~Qq(V1!1e;m*~F6UVqqD{>_~4gs|aRfOXC+}#&!j>*NGX~@2t$aVlJpmB`_nK z8@~`Uwm+EdCT3*kvodQm3Ct>k8TrQeg_yCQ!0ZGuBY&Kg*#^u)m8k+|HJMt(ahvtKR;v#MZ5zBYa#X6$z`t3}Mnzh`AuZ!(xw12c*V;}>Ga@ew5+?*sKm z*+vu{M#}z(V2W zpmh|_J7n!U0x#4j?lMsMCE1pAH7eqpcpD@vx36$>*x#I?ar;I2wBKEqO79JZ-p~G@ z(EISE(mQxu`#T1S|GvLlL5fQf=Ti*5ho4<<-hUobS&zmk#>-NMM&q>8x4z1>%%fet z-BiY#|1@~grz-Or;W7+R9)uszy7Ab1BA_((Uhsn+d#546WA80Um}BqRAmg$34}kL6 zyEPK#*n26VY3!Z;qjuvMp#S@BY!7iRi5nj<^d5!8e_!wCFO}X$4ZXM9^giqO`VP$0 zEvK6{-A>g_yAhVLql~ZPYkI{D%+wLJ<-SPNIdoSxexdR8e{zQwp<8t1`1%ou@~&Ns z4Ye@7?w_Q^*b^~;+=wDCgGP<7-$W|P0OMN_Icgh3KBS@$C8BIslc;}mqB~~gXvj=0WNaJg=x$z4z zWBY?yFJeY^J}a|ncYzs=ugN#YFT{-f1ZLxi8TsR^%!(P~Yx1G-3o&DVg4x5wjQn<1 zW^Ik}HTl~3g_yD5!E6~ZBmbV2+0?uB_?lwE_=T8pe9%U*7m|-WCPn%xOw`kE4#ktU z+h8-}PIL_Iun|Z8VPYPPK80VQu2+o5k_%B=ItHT7IcgQ)iWt2HK`e7UFv-xNX3#9QCp-Y>YPQu89&se zr6!gaL+Z%RYFs_9Aj_#Xe<7?DWyvz~$>)1iyB3bD{HCpkUrIf^&5^T>8I%hlS~N#S zn&h7PUO{eACbCUIH=eoca)*C9ohqh(8Ut^l(57>I9WjUH^%B=A}xGFaXD)ZC*1SBlO z<#5~lZ?DSjGOY0WKiLXN@9J3i>7Q(c&W07LBN1v5woPbd&|5@#N~+n^D>k50j?&rm ze-<4P|04VH;V71kKB@>tU6#?v>8O3wHIOR$)`9=oKI%EcBlp`p648JEZ}(A03@dE< zCtD%oJ>5q+kqEWUe^@LGG_26nW`*O7Xxwl3V2#ZO5!Sdw>mq+#D!rR- z(=9Lq2}=tMkAh32_drN-N&NkUq4!;Oz5iJw`Sd*9+Tnd{jE3w1hT7HWJE+aCVNC%lf}^eSc&m+Y`{ilg~v+shK?eR@IGu_!)&R~h7dZ}`4lR=+;Zqx@ zSN}ezRp6BOFDaaF+3p(m(cG=g;tk{VhCucHMdakOv#VE73Ck>Mq=T!1=sLXZbB(>a zjpwRvzpR0STjT^3_l&KkUv{NL_{*;C_B++fuI=;w1vI~Cs+07xt4d;xsAEa2f2=2V zL^k+$92HH8&{5HEq1Spy(krW;7EVH`qoU0WozjfVw}}ELHMH>w;hF5}R{||$zx=Wo zcqeo-)>eoUpr;60-h_TLgjg=mbP7*V&86dURMy|s2Q&{$I&j)EkTZDUm#R4+dtU1j z{tU3W#$@v>Qlp4A_Ufv@jQVP`G?MhLZtT^6T;>pTs`Q{@pcyQ?^r2PX^|E_elIc(; zn60ogBgJAD6Eme(td#x=tkaJ&)^CeXCu>1y(~Q;9Mn|kg{o(;Vwd^F(zFr|bzn`O z29`DL4Tz~}H;}QWw*ktU?gX8w=`cc*rq2P*&xL;iZP9eUtXUU>jBQtVMeQ4ZmimtK zZfA#>E=%U748_d`hba)rw;)j)CkP8@asxnRUjzF6Re-LS^yQ=VvN*u&m#M9B43cs0n+zr;0KHvgBYV&W)$gQF8k?cpQ_WY|BXY&EGHvHitxD- z;dcx-@34zNCm-e5&Ui9KpyQS-To22a4B+=BfH%lPHAHGl- zoC@-C{D7-af=+u-CDg||bO|~e!Yo0VC?kiNDB1&OU#Q~rjgZjD;ehO2A4ddV3AgP4 znWs%H9Oj3(=0vfQF}4#_egMU&r2y7iOLU{gp+8hfIBxj>tmMnK<7vcmq_azWKs?L$ z2Ty`APfDDH=SgC(cv2Dvr>x?GQ>ZRJ4Cd(_I5=e{S4}o*GIJ)v4ONdtE$ifj(sUTi zG+gC8sQ-K^IEGK2336eQl+UlBgysAi)4%s9$BjbK)VSvJV7T2$Ec6+km;k&13gK3~fV z!n;9uRa&hQNN%EJiCRD4yuwN#xT<8WYJi?3XsKFzJ37Q9N@mpBjO0d2maFB!%tJ+@ z&8$@)w7(FvJo6n-$zsg+4J3z1=35f9LmbTaYa&QxzBf{`H1l0Sv`*$*f@odL_bVbO zQ)>i#{ru+;y)!HH$^j%FV}+Jca(SWLQ`I5b#FA@OU=+$v@od(HGX~_Ry`YJ=(o|ms zh|daHxm}7j306qSRPgazA+`PjO`;XDb1NW8R>;)7fbf?%jM`^*0iR?m%}b|2lVXKD zPqh~fL28{GTmf zp6OOd5IXlPZH2swT6>nULITjaXIU#G13LH2utMI1&OOUnA$LIMo|#t2ebBjQc`IZ- zbnaQf3VDKR4_YB@TA);x35oj?Mu2kd2wasian!H@sZ2suB25hgJWcE?TOofQ1Eit} ziTh45J5As!lu^vuU6tzso`>xtcygU+*iseI*n&J?gTdOrJ5e`yhNWf1-bRI z53Yss^3ou>BZ8<>MwCF=W_n(lvb zy2xHC@?fX}vKgokcLw!11{0yt97+(ADb_0E2y%Y}+avZ#}06JehLdWvEu-Kn7~c# zV57+1cu3Hkt=|dv;W)aW$PXk~s|fJ7MBTy;HaOL*3tVfCVvYz_h_a&evqgnC_$T%- z&tW0>LXja#KUxL{gzdpI##12-i%@z8%6v~{UJ7AUnc*mN^cP^>2w_y2uhKEbK${=B zK7`>2WHAcm$YhAvfkmVOhO+C51KiC7L;V~g>}Wy^!W$rIr!LGpq#_4ap-l4u*C)DZ zJ|mx95mrvibWawdt#3$P7EI$#W6;^DUkGQ_<+Ii(_b7{K?>^#+AB4>d<@-3utkWPC zsCXV?f4wY?f9oWDSFTWw!&645JXL%YI-UVN&`)r-kiG`|tE`G4L#L_Kq6%e2>Kg81 zR_s;X4>ct4?IsvqU!lyTVh@;&6p&5STis$(8C}Y!1isM(bK(84)3A7&I*i)|S>yK6 zg%2YC4zD>l(0n(e85PPYu-Pyl)A5C%imp(u0*@Y-(J6~@pO9iSAViT}1g>re8%6F% z`{wMU(1rIT;|Niz-rjL??$RflwbYIAjJc&*m!q&2J9zC0fsjPAorP2o0t;Ahvrn zWu~SaqV(pQoMI%xdqmGr0ltftPX65?ej!%2y22O_U*!BnD3Nfy7ijE!lenG@>bOCrb znpww=4CxPVkW+}TJwrwh<90>qLRpUBU0KlM>It9B}Dk|3Q}RkjzW_z_1p@{e)+U&rq3c*k(#ezabCQBSR802UmSqF1NCWUaEu z%%@CeJUPVl>Ky301(OM|M6b>w(6F;Zr!fcC0hIHIvI{5^dv#$-y0!J{q9|1wj~a3k zZlJx&v(2=F%O3}w8U|`e0z$i2IlgUb$hQQ^?Dd<%Mzq9^891WIs$E!9j69{!Mh;=~#zuxK|@J7`W51 znR1Pdp+V8hgy_|r14LV*3Ov!PCG*jcdoa}Q)taTS_cYuQ#QmgdJB5FDIk=ojB^t$% zbZuBxMa_C}k<#0HJH>st35>gqElC&Xd@mrq+OrYq0?1T?bYO4MMU>8u7os-=A2*{Z zMO+9|D0`7U-HQ^~%AzNMdqhwdNrSGvOkIt>@X5EJu)2}5W%#CFD3eK!D_8-(-?1Or zC53VX;rc2Z_4$00(l|jDZxZs%oen2Kni@Vx&qsCj!@OLp>$P675YJVu+D~#M;Bm81 zu5RKKt$HhI)xh0MB)?h4ihuJ8^r!&dsMJhJ&N!19jr2zJ;T%{PiT8O57eU=Vl9&JEsCgT8J0;8{Oc3%5mv&Y1i3Dvd=`PP zjR3D64De9)I*%4O#TQ*c$wnZ^XNWnHQ0+hyO!*#y4PnM?v1X&tbib2r@Nd0rg%Bu| z@t-(Es~l5E71xvn?hYz`wFO7T*UQQHx6UZO8pU(DF|hp_-H5KP)nN5V)Tk>C?rk;D zcs`m+{_AhDqsspPen1G)$W4F;jS)pUZiKCR@mD0)fI}P zYTpmE1*ESDQM`YZv++roR&$6+p>z!b!`bX|y5Ppy7^A#a*HEEC*^@$RDl;GfI22nD z?0yqwL{l7Ts0NHCX&quUnn~#bhJFec^?0lMz%M95)nh9w%0aze&d(xq*FGV{W|`33 zAvVaE(O$7pP6rXx2t*=V>5JPas@ZU*ZMX(DT#5}>0l6CsLiJd4#505=E}p8bUmdCrWAsFSXHn|#h-FL!?YwRhy7XD7x zqNk~*KJSJ~ZjjT^1QZ{tH-w7?eaEpB00grJ3h~Zk%xLViLRjsz@(bmN!!)KN*m^mK z(@$Ve)du<5u27lH@>Rxkt51F{gZ)h*z20f&h6DpwN|gUs3re?LMd|19B_*6c)rPF& zJ#3V40ruW753XCUrR%OSblr9XT}R-fGVA3Jx6^gyB)U$SO4riU==$^wx-OVW*O_zZ z`a3$d^|BeJz|foVbt_*h)ujj@3J+TCP1dc2+3F3FZq*_AyEK=OnZ60NPSUqz*2~4+ zsQedvO~!}`l5MB!Gat~^w~MZROcKI#pV4(PhN0`_4Vds=FZ*Fszg{-ReD8Xhag?rY z(NBmg?-If#Zo?)lm%O=jjK~n5xY3Iw<1-W(CerV#)>1fXAtB4Uou~10Vke7mb;PBJ zaJRxg&kg8NC77{o4F zA^_V0ncVz#45QF3%Ti--3W9VbIwZ03--w(@uIhD)dKjC^bm&W1PY9dx7?Bj+O%gg1 zg+jEx7BEpPh%%|&P~^5Wr--js+~wQo74e?qjX^u?xm7aR8gEzJ@1D zZi7=dgQw?Or!3_zCB#Q9QM2cFNBXSyo#ILWJhPpmv^y!m0bY+d(_h61Z7nMCJn9tb z#kM$vA5QYjgonzwyJM6Z@9FJKp9cGXKwM$x^rAbQVn1cBaK@FLjLbKb>Ff0NE&JDY zo$Ke6IieKF`4!jytD}s2S8=G}>7=+J(u4=|i|NGRE~>wa(^WPTOZBQ1ruDdy!r~2$5Wz#!rMMk|_E|a1vo)`=&5D^g_LIn^O<$Ee?vW{1D^q(gXd_w{7j z;eDGRbcsHw;Uepv6&S)0X+;yX;+PQg=&o7G00lSQBSdFJf~Si6K{OUq^92r(hP#NT zx_c!aj}%z-4W)L%lbKzpzx>M)JTPAq)^i_WLhfQoLs4os2rDt+pN`<5yB*?f%*}e5 zMsN(K8MtNko7 zah8a=bCE-&lUr}KML_U=bTC}-5oY$a%;+T$iIu)Bk;RGVMVz|bA zZpDQh6D$V@und1#2~<#hvd1M3VZh{Zcq~E8g_UwM+Bg(J(WnI0@S53GlNO60wWxCU zc&B2R8kI@}ClAvE#UltTO1*-}VZqZpq1#9b-8xcKQ+f>X$^?}o2rO(CHS#E`%Oj|i zf!=BF5F?wSNi>ZrjR-F3?okBI!a0awW)qjfH4n$Jq#{@m=1=Vk?yaJ7PfWE*l9g(^Ak4|s##@9DuxK08LI5VjT)`v@&>dNR;R)gZXg-LU)r0f^ID2>+Q zRSBlLHae9>!W&y@hGWi5DuM!yfEnHxoysC%S-6}@?~P8X{C-bkhggR3foHmh%If>f zKBKQx9cIOLSkDY#H<{-#4?Xi(?na8B(&GlfTuor!g%m-Seo zUmpv6;|QFe@sKf$+us9|rC9wQ{PnC2+|U5O;2{x>K~)hv$G(d}jc2Ln0n4DO%4pof zshfYzs+-vQ>}_hC4#~Jn&53K0X0v};nwRM;x-awt(Cwc z$cCnxV3U;~T#%v=gxPF~N+p7y_R|DgtppZ9#$1b;M$9I9wpj@*g5)>R1Rq%m!UgHj zQ&a7ZN+p78U=glokCnh8NX?NBv4RBIXC<%*vI>GQ!RJ zS_v$IoP;17NRY3s1QtO8a19e2w-SU4vb2|``Y|e%2$sH56Z~u?un4kdltX+>f}FGx zSOmEif-u2fR)TOrhGTOwQwgu7J)2Y__#p&g0*95rBFL13F7YR}i+WsMn*Y#kodglV zahO|SoZpJ$PKPgwsss9Qrb;?96}JrCJdWb7&-5j%^dz$g&PB(~xRO>}s76J#7Xr3A7*dZOH%0L22eC*=xbjvU*+vAbPu94KR-CGSWWGnVrgBxS zIK{KWLr#UOVZ|w)d%%;+)wbdk&&iPUj$`Q4F1O+o&n45a98b6=R-EFwZj#2eu;LWY z%Rj=i24PZ2%qMO`(|@W$Da2o_2@@n6UEXGqHw#dJ~S4%m?uT??HH2J-TMrxLHFV z_tKn@X8biC&Nk7L+d`WZ{Te`C0x#we*2KM@$2)lC0bODvE_S&TM+v;tN?h<9zPCcq zSFOaAH$UYNKPN!sH?82zjVFb0k|wLIJf6i&)svW6@~qRuJWG}NOra335qP7Q09rxM zmm0doOOsSe=FH`ohweqR+pM%jztGT~R@%#s2ys2peq^P+*MNR(p{;yNH>tI&ArrB4Grg@+b^; z7*|pkX2u-mm48CHCpSQf3gL`J<&PRVgsTWNtZyx6N)@VJ%P_AIUb@6%vZv|!(KkS! zRD=eTZO(^2h1*``*~{>PF-?>7wiJSaFz#MV^9BPfU@g~AcoJTNMO@E7jpOdMa@qSl z3Vf9XoZ`jgkEonFTjOrA;zl#>J}g!6)8FkHMr!?;LWkDs4{fF5N~2F*t0@~uBcM1Gp21iLbsI~QZ)nX3NDW?rdsZM z`1GOB`JT>d-=JTJ6XhTH-6K5ZT=Ftr98l8JysZ$`-SgLbuu{;?Tmq;OgGixAQpbRl ziJ(cDOoXX4Ra>v6Q#iV3`|#4ouZU@CuHJBmcnES`5o1J3> ziIB3uygW(Vv$OAU@|>AtBIOw^vMAs<#n^jt7=g8NM)~V)=Pj z^^oA05f!}yk4>!QoDiDpCUr#i!%0pt4I>-J;}bE_pF$UrN}}J2Ie$lw?B9W}P3Bn0 z>N7rjA#R&D6aFbKq&N-v4G*aVe3oqzVpnq(-feq^>Uf@u*K)5SSGWeTEBd4Bu6;GS zJW=NWo)TQwNdMbps=CSO;T~(^6t2uR0bo2HC2GSH-W)i8yftF|7r&5j87Wc{2D?mlky8o)2kETOPx$8+)jyb5pFJbp?#7FDA!d*?0UAXSsVcwJ!>Pwhh)N=QMWbxkIwD}k`B;nOGCM$szz}jWfAx-Tq zbgk>1BgAlQ3Gm)|Kl0LF4J<_62?liX3kB}rF%TB?-rESm7_?6t&}mmPRMC#> z=n^HGfp$hCl$9yXnZwaeF0qTCkG2Ux>!oy1kEPz(if2kkB8G9-9PvPfDy#yzO~R!94m?fwdM^`A-3v+}jJ#P*-Ag%95!1u_5$WDG zY-5|G(v(yN$mxcRo&0{{tHkTf8LPlu6hsMJX_Xde0NGs?OeJ5l!0obcGVoWD2mF~V zFf9bJ!0kmdcLQwYlAiAz#g=#Qieha$dSToJNXnSUINF;czO%cI#nK|I9P|7lut^!t zY>b$VnUzW%?3WwRL>7qR?#oxDbEosxFf^OYe2EJ<*NWFQiW6Wbq#u6!6Vk1 zQ9mm}!v-2KwTM(+uL$9Yi-p*tFa0a1cqwxcGq$u0etxZ59*P}er3v2PS1U5Hc{XrM zy&@Ak(grTjt46Um$k?)>ip&+E*i0Fmq*sJuZ?@6|zlu?dIkC6dz@H9Li#f4(+Q9L8 zF(>vONv6;m1&>ryi#f4VZQw+`m=k-S4Lnh=i^NWs)Zh#z^XIGOj@TLUBU6bKws@&k zsEpS|VoS(iMGWO>xg&OF1YxkTo=lIOW5J2w6M8Z|c7Y9i;%+q;6}wQj$S@`0-2}X_ z99vvwjhyEY58^15*ryEVvPfCm=i-PKf&#Tv8mmrG5ACsgt@J!f3f3F1ar>>fP>qVJZC736;WJYyV+32_u17|3mKSbS#@ zq!t9B`MX%JmB1p%atOi%@m7LxLEgm_4^suAQi))(accH0wuF_yBFJ@mdM-A@N?;LW z5GF=x{w_9XB?uSfB!=ruRW&M=2)+eDXnHQTww1slNV=Y$i*0Bnun6)B1Yr)%tOVhL zJg27tW7|Zf62YslSF>-iU91EaLAF2;n&pe_VZp7%PEAkbw|{IoxO^2p1$-PXor@8kI@}*W>7En(B(3D3pfflo#FbGQLtsWpDPuA|!*e|698xA`e2e$)IOmkI zY{qrik;plhl+7}pH*jt#C(4XU*J`F7WE~lAW15L+y~w&U4&XV5voXlVWQ@nCj zPLTw6`|gsi^hVpUJcx+(O_DL`CydP9GCut=JgQ_?0%o#IOmBuVoViD)q_+a570EkA z7Ef=yQ)i~iQt5YrL2JU?E6bMZfJDX5aKePIy=+6KS@|xWj(zQ9wSOTYsy&aZtTrE4 zY>%k1&4~|1qvU+e5M<>@+=pa(F{Iz8B9F=%>BEd7 zGiB}cKOrp_c}&(%j|bU@L^ew{O7CZo&4wY48Dw*0t6(oIE6)8<3SSLL#*zL#C?kU2 z?;Hx8t-+rIoI(^L=sM~UmC-f(YDVHVKyk*^3dgC!S^L4bA{DNU@tlR}CLzVdVmP3s zt|Y%0a5VD8x0Gz4JBJIJQK)JphjN+$)4@A%6+O zweN-Q#Mc_}j198X&v4x$E8xMtT3F53!7xa6Wtf`zm8Y)A*U3Qq&T?M&u6oAub(XoI zIu!1Q^-fVE5zM-(XMq&zZbh(lb392m2CMFpqFEa^>zN}C-el$LVbnlakyQ~6{s`^a z*V6_MKGPfDM8dGl*IPens8|`Nr<8nsY~Z=2rKr9JvRq*UAHH6SE?0p`UmN%dY&9-- z3~|`sCSsp&9SS_aCQ8=+hC;lB(-wX7j7UxtSx*Brn?Qq1(C^>ilkfz}wUt(89VQ*R z2xf)XcFISzC&>cs0Z~RuaIW+D6vUIzoZ3w~=R!{S+ew+!%Z}8}KIZ zq{v#l#V!8A9I5XX1J2IMx*u?wOY}`J;N(w{H41Rr0pPpU4sV2dTaq}p8*mo0LoR&m z8iRS3MCp4)23E8M6Ip=(zU9z+@F0ZKP`Zr9MJU8;27<>!j400~{$(I;A>#JA#N~Ar zv`^wSJLU#NYE6iGx*U)vtGgasnT1o?#TPRzksO^}EubGrO7RDHu zf0^VOQvl3Q*!r3HdU%=l4a|!0GDnh~A_d1%CcY6~CIw{}^JaLNDk!sx>Uk@?On(Ej zGQ7-GU_PKStHR5?ZeZRHD}y#O`5?8KGG?3U#CH>^z?urdQD5wOM}gxwv~S5@;*1Ay(P8cU5u1}fYCupO2C@K0{h zd@xF>9)bAl7Pi~KG+-U55{FOxcn!i*%nH)MhmEjAg)ab(Pi%{yl?cY^j}8>%5mX|KtKDTDafp}x5zK*eNh+r~bX|d(N=Pi%CzYx82Ocy< zwfkWSS?wK&;i&cmp5>g?#$mMOs@4LFac+^i4+W;<(2Asz)!n~*g6HT!skAQvqZ>3g zW|>M4Cu{Ji9Y`15D4oRo)2f|h{a|||7wybPs z8#hF@zL|X;Z(p=*V`kT!M7Eci9r_uvSDD$@C_CEBcB1SZX7(%MJl)KecO$#N%=W?< ztmTVl_LFareapAnU>SSWOokBy3SLn@vL2 zFtfjr7){LVe#&+-vqg!xznQ)K1hO}n+3#K8Jju+q`w-X}W_HRi$QGE{N_&u9VrG|< zaVBHbsf0X@$%K( ze|&}5#|mMYek%ITxI#z-Udsw$dE~7NZrOf@s0Fv<#tLAQB@J-PA&f|^gsWa5?D(Fs zLb#3a^%;K|u6l*Ay8HgaO0E_Fl2J^#LhFHQ<&p@ja&qbcb)|hd2YD;1d{?5zj1rTJ;Gk0KU9B{)w2-Q0w$vV2LB^OW zEnYs{h}bM5=E0HA2{EFKSEMCM@{t4a&VC8jK*K53GL z**}>!EtqSNB+FMq412$SruS$(=lI&|Wq`L#L6SrC-thR?b**pMbJ5Wg>I6e@Au5Ka zZZu-JNMpn(VMOX$Ty+d@HtaKWQ0hN(-5jNwO`*kkxt6ixY)xYYgY zgb~Az{$#cgDip&66Ty#4nlWr4RWUrRyBWiMni3l?n2F%w#bykXJq&QKPz+naZ+>OQ zaFQvDJ%)cYNRnkSCgFN|HxG|tRsHuZ%otYnup(I-9nMe;v%Z8CS^a*p#4y82Pm1AX zGgS-|ojryZpv4+7+Br`*8Ad}Pz)2#l%I%Lq|%_V48}wh!_D;lfhIN28pA|jjp4E| zhdqWFqGI@-4Mq%aLj?E#6w+56!un%iUe zN)$~QOkCSblv#|bTau)`dc#ep}zJQRh8bFKlqH6VXUY{sEK+Iq_lEaW46iCw{V>hApEZVwz#7AM z6GK}+%n%jBP9sK}%s>SA2_sVP#Z|{}D+Awj8R2I$embsZ48KQKMhw$TVPrpC63eC5 zvBVk_P1!(P>Q4W~=!dr=Fa04@D253pg5A^2e%L~)V))^nWW6u1ceglN2jznzYa7cp9W7-PE;?)-gFcz0M)7cahiB%V+>z01+(8w0-E(PxB1C_Z}}eY)>( ztMpz+pBy9oiK9=Mx(@Lp39`@8XYhBr-cL~$b91cs=Z-#p%m8!xFw$6G;q(`dK0~qK z%IPm1eICG*GN-?F^cj!Gq?5$+J4fG&UMW6?6;ii!YK=#vzRMmFVhof|-Kz3^p80>Y zeFvCSMb>sz-+McEPxs`=3=9kd3{epzn*jwe5=4>+sL+EbpdwKP1Vj)M4%&cX#(+8J zxMo(@u(}x5b$^@o#+_cjSIX_>0E>$tt|}jC_^6Y5eQX*6Il4r{pc;pS%WNFQ@+>#y{JKZ8)aC zOZ;l=ci6+5@RDB@1>{&mkGtdxt&U>ZsPP+sf-au1U*cWGgK!dCRB9N@j#Mbi1QisV0_9^r@F{_qC!-t^{Z9-A>}`EEQ$E6*-B2a!^sm*lOar zuQ_Vj&wf?<67O$iSE*&_+|`k&iRKFVq~~EJ!!v0hmae5Q@$f<JpVom)cYqPKaB?GgmwH$*a!h#w)nd{ zZN5UgsO&I>Eqn@B3O(CDfmQck@vUyz?#wh8L8x!u(#dFIt33xqKPV~I;PV=pSlC% zlU_uN=*&E3(#rN&feCTaOITkRbn*nWGrgEQ1!^jO^4Om!owin3>Nr&H*xmYA5LCJX zdz0|c`qR?GT-IX(NUnSd?yI`Vc|*=0CwI(nMD4aV8`WF+{&CdlpCkDhPij?NT1b6n zsEIT0wbh&}{Hmt@W9X*KxUUtQqrhX(Mw<|;gBi8$ z#On3`>PjJ#k#Z2Dww*W?y7+fe%IhM<>%86E9+Q zmnS(n;sVl@Le!NaYaNmD6r;ACxb9s10n$WDxn87jf|w(PQ+QVjQCEu0Hbu(2_@q9h z>^u~I{nDON{v%R2MCVB1B+8XS)RiLRy+~QbsBMpLH;ql__;%Azok=ibxq#zt5^((6 z0#5irz|80@vdn5DAk{-a;}`+6=LtCRd;xQA5^&Np0#5!wz}!fR(dU&2nBQK&Dc>GL z;;G+HCpfKo3c-T@5_bAN0v3)Ju;_RJi%$`-WR-xWn*=O-Rlpfv2{<#R%sx%PiE9MR zxlF)GHwifTVF7dhDq!CG0_J}w;FR!*6n1K*fYZ7OSTKa3e(0eBh8-+*yVBBf} zM_npl{H+9CmOd_EnN*Z6XM88VGeyrXXZ<3+<;j!Cxng$#D-RNI_HhDMZ4$8hJ^^c9 z7I4lN0@lV(X1sH&1+42YVEv&2&O1)Ph9v^dKTp5~*9f@qK>-)NBjDoi1#C>rrLapH z1T+m5uxYA*OP2_^>>>f_TLf%=TELd~1#JCUz~zPWDCLSC0=69_;L2$Nu394C>PrM% zbE|-BcM7=fLjl+SBw%~Nd`h{YyMP-H6mZjY0XLr^U`JZOEiVYT^&J7X@t=T>?{a(M z6oNbY2)J{MfV)l>aQ9{b_dX-wzE=g@|CxXXeWxXQEv)3<1RVC-W8#=R}z zD0Mock1rQ+bWZ^j4iqr)SOJqx7cluk0aLaMIOZtjkX1T)@f)1f2bffK{IeSpBPjHN}f5?3}Iw){Yc#Zli#8>jkXeF5tZ9 z1Z>zP;QUVnT=0W{3!_UY<)StMHg*wk$=(8*CJ5LxTfn6&1YEX3z~*fNuDDsiwnqhA z^@f0}KNWC|T1wH^<`WDkV=oo_4`wkZ3@r2g<4}c`Vc}n*0g3K+3Vz{vjyIM`lB(T8*ZP{lty z;y1@b9dI^j7u{C;E0#L5UhIYyF%}0!*QnHBu%#9phH3FDz#92NW8*4%iTNwBocC$} z#aQq;c8c^8&SpM_G%Mfl!)NjWc8Z)SzQ>s2>s%@9JSh3lS>q3&S$r>AKF=9Z7C-tZ zI7H7xKv1Xn=3V0^4M(A8aEPVC#2Ap`8+nbC+SrCPkzY@Y0V#f&GS!D(!6b%Y5>2pC zlst|sYoJGJDlwr^%SL)<(_3-|uv_2JD%9!3=~z!YeDR}_#UpP`;(eA>no)U)JH=bx zjW^IM7@ZWojkIMW#igEMD0ALOtdSW1v`aOL79WB(M?R~T`kIWq?Vb9S7_Vcewn0oP zjt=sq5;#v{xpFesNe=IW`p-pC1Z;;_2b~#kN;uQK1LYCV_eW43jy*TUD~+jxL7!L1 zJ8^})=w?o~8+jEnMQJG>rl)whBy}o+okeiw^Nv<(CB1@?mLk^37>x`_@v>R!Ix-8^ zj^4ZJCDtg;Q}8+xK;2SYnWWw%O%kWm_%XelT{n`Ykt~g5!N6f2?^CP|M`D7!GTDGT z?tQQ-C$~P=9Jih-tE1sqLVrFHCw8)U>J}$EwO!C3+rq23^g5fxc=|e=Xf2ov+CyA} zttM^3jqp}rZKBt3Lc8$ppG09ec~e)u8Q}%_Oh8cC}>U7Z(eKXicfM_f>hQVSnwJ$8T6&BkE01=(2a1khVqY#WGT zv8!c)(86NZ|1T}(n?45G{@t-=CDAFdrAkMXP-kY!%ByqwG`$^$JWH42*qyg(^a5>6 zIo_Uu3U!(sl}>mE4O*WrxLU3sf_VR3!K~z%TA^PCvG6}x+TNi38?>Suv$Vd-p^;bO zkE(EW_I{)^tv*-715}C)CB-I_;!-`ulhZ~n2OD>T;}A;?B*uW$0l?;&E48WDKxo_> zgvO)cIK)!Zi7_C>v+dM8dIgi%f=M*NPV9#cl1`&IlKj<-A>I)X(0B*E#8Q_IfR_u* z#=nq8EcG%m2BdfjnR<_2!7{W)@%A2wgy=NVNkzwjPrOM)YpkG`Sc<0=jciGc-AN;s z+LIUqQamL}4W(DG46RYT--Bf~oklvT+2j-N%R@k0OfRt%cas}g_Zl~lMl5wHF$Sc# zi=VolUcoZ7M)BSUmf3U~>7@QjKJjkc2efzTCFZc{Iou(1KI#i6yr)vwSact+B9jrb2wtI)=mYgWiN!AprOEIYtEj{%4A03)w+gUV}65cfpD$SeK3NW zxBvOJ{CMsd;uU&s8II?cA#izjezjg%492Y)N&f&go?n6Xmk0SBk?|;3;_Ub)912nX ziqI$@_bMk~FVtTXS_@5}76-?3^k>WPvQ`-ceh)Ebx6x!HE4H1@{Uu~{pCa&8jQ27s z9Fo8z^0^ssyi^E|fz3HYwe9j%9JNMIV_K8m#Gh;Wj^g(&CVh#&*7O}EU%gnPyOuNb z9qcrk??_B~3V%lHThH%Ih)I3x#aOM2=XRvoE{Gg)B+_ZGh&U4Y(wi~I((PEx3*SR7 zy+?P#i^CV?5d0l%=UiQTCrIn`kvM~X6j*lrSf?YPy$IS`z1snv6xg~ZRCcbe9}UvN zRF1fc@-WD&gnvX1-RZ825ikX$g&lL~_USQ@2ax>Z{#o(%yc&?BkbbV#r2uR7OF6+s zZ8ekmG(%de6EKGN_-jMX61@zHcOZ4G?v)$ZA;b(HAf&bW@Z6yKkhNa>VZPeh^id}2 zoZRq^3>WjB3Noae3$XB*9J~0=cU+FuqI~TZfJL>}dn_qlt8YAE0vghOD7nVD#O_0A z<6>eAJr8vAASElk1$5na_-=l6CjvL#R=>aZ@+(fkH|QYFy0Wr9^kns8-OrKLuZ1kHe;6CBvP@Vo8(A+9ohitqHno<{PJ+U)%(d0I5nv=6h z(i$dmGJ5pnA8_AVPm(sJQk)H*!kB!#loOL6VaBsva$6R~oUiXdN>gzdp=aHdCJy|J_WVBVgkN zRhS7%`g7!^CYe*O)@^!#{W-)j2KWrvr0?;_w8daUC(P_Ezgc`1KC>vnMGG;NgqO<4%N4ItQ(yvLjDR zCauVzN+e#Qzt>+vYyD4zX6wcH`Fu_4dwB;+W6dw5mXdK!V;e3Bt0CBD+ZNmtx|!gNr27#$?eTZ!au(5pz$O4Bx`~d3q1b zR2TdVnoNdoBW*#S?`*XauTJUP_hS{@3GdDi;k}#lorP0#=f<~Hm>Kbg%#3&_XT)~~ zmgo}^EjuHgl$jB41l`PtWd?l;`R@gP?E75)bs7HNpd0?2WkRdM>LWHLR7rvWEnKf@$Ph02Wz!fbm%eziDLMziDsA=3(=ks3>)sKI})+TOd zt*upTj}tQe*ly^!TC1p9cU&XD&Xt+laj`lr(Ra9p%9^58ty#fj-hQ`h%UW~3ei@PH z-GgfQHftUl#D|!}>6^iC>hfQKjpwWc7b7`coUjZBiDhjCS1Hc_&e2u`;I2%_}{v(bUkAZ*GYP!G&dQ#ry|K|Nu_ zRf;q0b99&WTCD=6mo_2LZmo*ZFZb$G&vs}z?6=ja^}_Bb&8e6wh+JJqid zuD{;9*}#=;qi3T7(O>h;y#-&w_+9Azjwvh{@dKt6xC^1br}hi3f_F1Rf1qU+=pV79 z$29@{BdxwkKLY=;91==3yXZ~&Z4hRWP@-9xv$b}?Q3x4Qi;$n$&L?yt>eDh#Ww|!# z6=1uf9m0aG!?t;0aTB&yzlLJ<9=)5^YxR{m6x^ zKB*P+kQ|CD`3RT!!JHr?`J5bz%e+-c(|G*F=f5F;qEY{s_MQzo7M7N$Nv~zk9+RG3 zY<{VBgEG^CdX$&$t;e;hGMDLJVR)%Bz2z<4O}gqQx7-IxF{?%%IXB9V6GyJBaG6am zqvRv>97x`v=OZd7Wvq;s>9O#MP$n-MSvlqGsBu!YopEfz~&;ll8fGLq}lcOt;mzdrp4JnQtEi1yrXM4Oz6 z){q;m!HxE#7j3EjCt}xAp$VBNHR)fnDb=JyIJI7<%YMN=7cdx?3JzhEV=_^8&rM}_ zHTYKav0tLLID44x3(>J3`{_i=AZ4>wqsfzg@3kNTT7W9g@3kN+fl?FFbm`naMTvL zEwn`+22YB&yqe_ScWdh!$&%&spY#Tfh3qEz6W-eTb6SKBqh^UF`7hqu&Z0*qt~pO= z((h8E2GOWh82_iYwhQ~)Y?@xY>lm-AooXHC{|uH21h>jx`PO!)LHhBpd~16Y%Dtf` z`77Txd6}WYECMc@6&?ZkDm4!76?&WIpZC@dFdA&r{PW)0fu276 z^WNIMjnySM#%UXdxxhBV24_tqZ5 z3p9nfBKY6EwTHIi=70Cr9-hgnF=&(Sb}aIHgpjXp^a@G_=PmjM5K_0m@&D@`9u78X z{?l*mk-{xzWFWNWKmFE@W~{;%LYm~Cerv}_SO~XK3iIf=2~frsT?9(19F9YAO`8Az zTPtr9o3h=e`TxJQgS}$p|NqwZZBaFv^s5a%)gdgp(Se}9;{srZNG|2e*T56arF6d! zlvpn1-siRI5YMGlpiXqi%cbmwPm*>>D;vLhJ`xGZfT)QSquwxs?CkH3Kr_rK9{lydF|98m$I3u*X2_7-y5+yW+;Wc#DvTZ zCAonfuOsbDr8+TnPlat1-#M4^^Jk#cXDEfd7zJU!lH7$JBkU@@6X*ZC)3T@OYNr>F zAh4=5cA(jX0asPqum|mWY<0D+#J%XNbmSzw;5^i?Iv=O6)_VYH(r@4!Bn|T=1Dy~m zZDa;oMt68pytmP$`{AR#4U1c{H0c)^^%S8?)02kAHZ}v1UT5Hf=8+1|f>5Y&9>A8z zq5jGG8o7*oE<8>81x7jjH{_XkO}Zx)St1P5l)bd}B>jxvN~=ltVAz?><9PDQ&;d0p z7ke|iP+=FgS{l}}^D(_iMkd0-?{i1D6cWfx!DA0MR321%gPNW37L#u8!M-f z6}d@9NLk%VY?9>lLeAx`#CY5=L&jqkas1nI*wWKY*O7?zT5zg5`d7<(IL%Glc~Y%Ak6%Glc~>~=?~hW=RtlL1QO zFW*$dfaYXxm{|IE7DEb$Evg-5;$qMG}wD2hqJSi2riG6Jrj0nC``igesX2?(_bIUVfRMmy`Uu z^LV-Ob}i8nVuKz30D7V1?Pj94HtDy}(sqx^tnxCx00P%$@7}gby_KH+`#6`aN0!!g+-EG9 z%Td^H3R@+Sq;`1xAqq3o!Av4vhj$3$tZA-*7dDJx=QNk+h5bq$mj8x=9>d3EI4jE_ z8o51mAM8u_KTg72BOm!O3SmyRGDw&^tNaz?P=C2#X-w)yiQ~YcznN@{Y?r$)Wt+cC zaT$w9k?WSt;&&u@rX-ZB$pe!?mX~GFoZVl z55MzTM<~rp?Q-2mE+5OLu-Y?>d!MT4eYpBm-1Ba$>Vo`)u2yL*zxX`3KfV-vED&1{ zw-(~XUS&P`oTIcg{dq_Eti^CG>qoe@HSk3TUw-;$6aIL~`V|YLfb|{lpt9XN+9D5* zx4YehO=MrWA16*KeL1!_eC0)cgl_ftg4g0(wxQF|?LRvZ9~dhL=i^RV#NY2{XcqDJ zkJ$tRss#-0Nf4PfP{8z|0%ja8;JAeXj^8fegjWR2{8YfKUj?KR$XF!O*iXRh(E?69 zS-_lg1)OxPfRi5+F!x^q=HU~Xh&TUN0jCs0|48K2S^=lw8(r`%7%t#+{4Xzj3ug#e zG*`glWdfFL5U>=lje=#_djif-0s77?5^z?XfaQGztT;r#%IN~mUMOJo1_5gx5OB`R z0@i*mV10Fv!p`d<;DUh!d0P$>u=Q90m(Le)#WDd`o+IF@w1BH`7I4kI0P!1XT) z*#4$~8$J+l)0YBn{zbr!P>2cL!pqW;yxXb;+}>Hh9lZtIIYhwS2MW07NCEfq4cSQE zeKQ3-Fkirf%LF`pj(|rl20+#JDvMXC?q{W{$*EK|%_~*3WrQQ~28geYOs!t7O4lfp&G|psu3#ksrjFPrw@%B_w~7!`O9m`wi0?C zL$9a-okq9cXzN-~Z#j0Q&sV$O<+&%l5YZGS&FN*;rw zY;#mpiZ4;9vghI0b1{DSbuo{QqHX_`Wi&7B6!QQn+K%ZP0mVE&iqKdVKcIX@~6FwxGUMJ8qm zl~u(&J&HDnJ}rZIcoglz0?DT5#^TvgwCk>BshJ?#oE=p>jq{>tccxLvqoZh#l4Fsa zD!y?V?wjSYR+q3J6-QN7^7>IMUP8Jm=0${9EW@LUdFL#a5JHyPX7!UO$bQ9_J`2!a zOh1LuOQ*xFuHjKrbbwK+h9^zYfv)mAXo~JdyShcdbEfD%*}^O4F;jFuN$M$TDh@mP z5^ z4wqt~qiVgAruce}EhX8I;=`GpLpbo1hZc3s&$q|jaDT#_CM>X!IBr1~}*|?jMXq)8d#@&=eyCg?A z?xrMalk88qo04cRa=Dw5C>FWgO-X8z%iWZuPvmkpB~c=Bxto$`BXYT$lC(rFcT{d9*2jDcKch^JP zJA^g*+(c17boD@( z!0QeAxY8n`C2irBaCA}0IylecXh2UWmBeZP*Dx>BeN+_&FjV??1t}gvaSc%{D|a*C~`dzWw$#noMG=n5AFh~ev(yyjC!aJUX=9>Gd};O zEa^a(bUjI-rk~8m-1R}X!=D=z_z8bnuSdAz!jUEBlT7;HdxR0+*1{86+!eOP0Bz+z zL2|3Xdndv-V{Eq)j23%}k=(~hbd5hJQb1@mT$3{!oVXiuRzi-`lNr`Y{%NGso4Cp! zp<&0@5E%4V7wiPYhgdIK7S=ip~HSLcJOzogFiQ@@FB*n z)BO7fretIkt-{iD?RfmJY9}4+A|g(IL#d-s1pdyVqM^3VSWn0(wm!ik3P}7cM&*-O zHP%sYq7%`Fh=EJ^O%i$!RE@0uK0v5d}VDVc5mV72)sX`m9j4m4@;EeGC&OA}TS<3`0-ymSc zb^$9N5pecv0#<(}U`<7YQqJiqVC_Ky)-Mon-WmZHY$Ql-xlzE@hXh={Q@|B(3Apm# z0xnw0o(T!aKpX=ZaP@N&Eo{@I99+dvjyC?K)~(G1>CV- zz@3`}+oU?S*x&n0k6Ac!wycrom zZHkv*G?J$ymmv1draNmTV;`_N`D1^z)Vx+Q${|swuU4q>`D`-r6EZTnR<>_6GV9%h zG7ISqlv#ZCf0I|-OkP&mPAz3Q)k8osn!Gy-SG20xEq7*9l-{a_=F2M9CWNNnB_9so z%Wh!z*@pc~+qNLJ6O2w9dRy7zU=W>-M{m<=Hh8l3ERNv=0p6fUJIx5*p{*9F1X(L`4xxSVB*4%Fj_cb^DCU>{HaHx3b)ayq7Af7W`VQb+pv4Z_tr{OklLcCA z#O_WoHp1otjq+k6l+6X2!EIIjF^F8C#YXP#Bw{0lF^s-1HqtN}Jg92T0_2vRC)|R!!F!tukEY^+*y9BPxVzo@bC2(aH>nO6% zAax}iwFi^ggEP7|=h0yry}2@r)olmr&vMq9m054D%wqLVw+J*Vv)){p#X5@?nV5cR zsd{r|7HbfFS_W}t7VARuXVY_Iab*_kIuMtcRaHkm}8q zSv-%`+RqV89MzEvvv}N8f!2e>S8y7iO_TIR5){1aM&%JG3P)7iO`;GdVTJ@6Cl->9?fZ0`h_dUIhG8!Z-UA)z-HX0b66G@Zg{(lNp*V2=~wZ!-^0JBsSf zg;{Kn$d}UGlMA!hV7KVFFpKrg)Bz)>`ffzz!Yr|@)-24bp82&cVOH(OSj&Z3Vsouom{qgda$%O(R?Yg(g<0a-YECG)Fv~Bi z=A?oPv;6XEPAs@E%de>BoNyaiH~ zy7)4j&bHU;FJEOxH(wX9S;nqx`to>F4xasLYZGXWOgGlxJXTv*yMCQscQ=+|)(-gn z9WlztHy9kU2bRN;C-@5bCtrxf5F>`jt$bVHSf)GnZ3i9}f|(1cXF| zOU-+MO>vU-v1JVe${L})rMi!y;~2Wg^5!wh%hzid4lVmBaG34Y?O0-3_5<(-4n#iq zpMaL1!T2k2^JEYeqEYMtw}2jIj4=6BeP?3MNzrMQoZY1 z6a~2C@zflMm9(~>1kK8t-@XKX`!=ZA^KS_Di?RL!?=MqP7y)uS%R~&2>s&CB%vU?iw>I_%1rtp-&8zWM)?gs;Hs-*5Pg_?xR$(pneL3X` zrQp;;dtDYL2I3k{Qs8n1y5`@}(Cs zX1=tgrQ}crbohAn;wHwpjA4Z_oEwM$f?hjsD8g<81@l#rNpjy1>Z{5Z3M48 z1w~&q-Ba)z=CE=dXl;D!g9pBjIN!buxm9O@rt9oAzpM<{VmR5ZKvi%<~GRkZEI4<8hk1~{j8_a;O!*i zV)1FrP~rJLM@g|wqs6N}MrR|6pGd`PpT%^07c!)0buE1mocJ?7Rr&!Cp0bs;1M_D@ zMgrl?UKJ%dpu3Mgv7&e-LaInB>*R)%W%4xGqm1$*Rj+!3J2xgP?YF?FzC--9Y7KR* z!5^WbHr@}n?Yjt?8F~sRdrfPzW5&@SOC_tm3S1aZ>FQ_ z>K;Qyhe>_2;Kq``9>GN2cf8Y)(Du!6>UN@=tS8HHFhp#3VE3~(p6GNSw0&cpx>cCy z97q;?eB89gf1;c5^{i(f11GF4NEQCgiw5TdJ694=xq!z#re7TS$_2E^qFiySC&Hx{l4^b48Lj*DA~@pKH3*r z>#NyIlqEspQ?{RrV6FhwgZof+4F%RvN)4md457mS6=dBAvYQH0Osn=ioayZ#YvK23 z2%_E&N-ONG9VOb`Lb-({@QQM`(pz;HyrZezeH2^O2(Q%C`zfkw9;)3e?6&DwDXQ{G zwzEsXB42=bkTE*rCr{Nopr6X7{1E>COI0aEm0JBUqgFM*dlS=ngt3Z7v*x;wekxWv z9KmNA+HZ6!Ub`#9>AXB;*L#Q;q!K@Ui8gb#bgM~8_-rPe%wwWwGts0NMX33bfeobQ zpZEmgZKP#YJx9DyoPE5MgsSIlyKpDkqUH%CX&gpVL41{1bxDlmOU47qp!07 z(5r|J5%f*=czbh<%3nitA3@(I!(fq=xC?U!eFU}DMn}O_Jy%ptUZzT$dR@;EK9tAm zV03KYaw*WSE27Ke_4pf^SUa65pl*`qI!#?wwr|XI4H+b3(%_9K$mlWT-y7=ks|ndb zyWkQ_?bbOvXp>7OQ0v(Xe63}A#W}UU);-hnjRMQ-41LG4jsnifx8BzBvIUxtm2Sh? zRY?jp)XcV6C$oN?W>H!twa_Y1YCCEgIvNuk#6a;DrkvIury(+Yb{9t7e+qn|ZeZo7 zo)9ucRW~ z;P8oj>LMz-=q2RxEBQc8j48+FGRPVQ*L0)SQ9zqdKABl}_F)|H5!g1%cBGH{}$7u!i zGy~O1pJ!{)3m04JNW9J2YNDW*}*Q zxnnvu;|)lkEtM$Jh+z7C>7!Zc47&~X3t6eei)vI;fsG-n=qxaYdLU3LN+InK+817_ zM#X~>ifse)uqL*}5M$NwPu@ajf{TA^V0EM|Rm4nqfEY1@cq_LDY5Z%#LUz$ zwgir{hQoF1&k;bI*B@rHMg2J$q`Xt%xFr&&`o8sWrn5rrVJ8TO_+obQ5^O7=V^KZ~ z%t>DY-{hyK*bXN5Kvk=tr@~Gozkb!H_N1rAE=_LffWL94r-NOSyb9NXN72*Su1{X% zdAi#@l4;MgyWLkw@qNNd_>d*|ZNz`|`8p!5S2=qDZ&5js{jYX`)3GgfBRe_h?1~ym(1eeKKX5DRRbLE3zQ}>_qS8hGiq(ZLN?+({w`%(0Z$p9bJ#gfS40;VU z@t6Rq(O>8!!5(FOi?$=SI~-+U@hSDqnrVFtv{`+NQ9IT*Ym?9IuYAQI#Vg>r_08%E zobxlQr+XX6N9oqSa2^6#k9M!^2qTwOdT1VdMjwUbQ76>{O~_WY|H)c;Bl?VOko@QS z3}-Sr0=rcEr{GUG>{5S_>*%^SULRUTa}2x3v&8ttBuHaUu&~m34u<=tamM45I=G75yIVz8&#o zF!~>4i2ZpWKM|dczOgUy!qVvIari4!;zgCw6~IRlFRqDRhLd~t*MXAu(Q`eSrS;JV zP(8sXb4EzM*<$a_7!SZn-@rohQD`1F~#H)rz&-d^)W1^cpyn047fte`hSb>^T z&{rV`m!n7UJA(GW>Lh5;o~TD5N9G@oqH_u3o+p%g4plW`(0>Ar+SXKvx*5DN$Gxs) z%>(5rP~x^%FUhkn`p7&dA{TR$fhaHLUIQ|YVxzp6%ScIF%oTaO#hY+qj23?o4*oC2 zY*ZvJ0jtxCS=9bPm{mHvvD{S>KY3)pTEYP<9z~VUhhL>-+LQ6S)1G)YH{A3CR=gAZ z1)rj+%ZQc7=!L%Z>M#l`X0LJo?;|;5nUS+Xk9zzul_H{48$Ey<|im+aS zb0IcfeMg5AzC$Cka2KCR`3_SNZmWJue7uS#e1}I4F2PA1{YR=uJ+Gg^1isNh2q^(J zjj}sf?0k81Nl*2e^Dp%s%wem2zRFr^^qrRK(X)l6dO|Yw(+68dKYJXs_mwCJ)XolU zD;wOIhAzNG%aC0c<;Ik+w2G-e@e!zHq6lr}E9dOl&)oQG*m?R-gn@l+DA+%$5@@BM zJ&0Bb+U4)ytrm1CQ>zg4a55NlA*m+XXre~gJfcQI8IIQt6{98+V&UsL8NFEe)-=l$ zKK@__Wz`XmWzN@eO9WOO1ZN_nl=+4M<>7<%m}M%HJ(=nsPCnNzf*ZRSRP16o4{B%L#}GCSgv5~9beG`ae@<;VL}22auga4g&HPk=a204Wy+~i%QXD`c#?|=T_=%jyN)j%NqmaH}yOn0ix&a zKt#{ifry^J01-WVL|r}C01-X60uep$1R{Dq2SoJz4-lhgK{Mm2!WOnucwyN*rWtJb z21SKxwhf>otJx^44t+u(;kyHr3(y_t<*+7 z9-~Uw9SA-Z-9dmcg6v(?Ir!OX>DSq|zX5Ikhn8)htbC-ZJ%@^^3ph)%*!8(6E2Kef zZf?lqNF6?jtp2RCnqh%6;V^5~sG!MOh#aa0MTZXe8&9FO>JYzAJ=!aKJ&#;ow@sXn zG?+r_RcuqhP}E$}&3M1?E&-pitnt8` zjkx}Uv5{dPz`Cyk*L+F*a^L|@(d?oBBFY(>Jxov@eA&Y}BUZM1jBz#a&~`XsnKK0f z5zd*OV??|T!#UF~;+!+R2844azc&YSCtg7=J!H{gCakTe!@>Q);s53}Y%1p)RhgJm zAgam)tAP4t-)lh0+v!_nf;A3CjKS|suspvv!J3Tl_zn~db8p2dlI&L6Ot8qF_auVl z(64}s^T}0k z8b~2d(cQ_F6r8PY$Lhgb=kAYAq_TI5Do4?LyqVIDH_#xQyFf7~k+Q8UetQ7&FPpK> zg9vsGb)@5%0uYiO!8?4u%LAkaS)YOr!olTPI7a`_l|Wf}t<7O`8WCZFZjQoc zOpZPVQtW9sVRLrq=IFTZvN^f|ji~<~e~=^R_j5F_d5+fnUXG?%=)mUw|H@J2_t_l% z9XT3{!@OqQ0&F0US4O`agpNl{mQzOJw{P-t6nPL)oX5Q!MO%~+2PNN!QgZ*NWyFeX ztLJla)DKq?mh^3rBdY=0*?r)c?G^X5)DMC@UQTCXpVt?igZ9L|KGX1h(Sh&>KSb8j z7A8V*1_$Ffq2c1lSH=M%biXSoi@fboIREAo%1}H+h0T#T+hF8*^4PD#F*_XY!Eux) zPgY#|b`?7hDcTqKnPdbbu!?kK)P0E^OlKAxWmm&x&9`UToq?Ke+dYSiGc&CDcINn6 z66OAj-7|g^Lbsx)wLkOO(}0`31;@;EWk<%E53;=s&i3aW6}0m%0;qTL5^T8??j%)W zz=4*cLQZ}V7qjutuEdKHiGC9-#f&<|g^5}C(-y%?N)x3Xy|gm%Zw&e0lE0!R@o(${ z2v22uWqnSfX`9wh!1KtN2p|P)wsb;8z`fVlYB%~xaT>kr= zBn9OUMt~|X%WlQZ5nDa|16;ZCU!{hiVNC7Uq8f3_+1=NZ-GXKVq8w|u8`(~)n)N(~ zlqd&4w`QRvt>`WY4E91*`e}cZa+E_+Xehj9MbFUCOn7AxSis0(_ELPp=$7OOdt1cV zEXMAO-EkMlB3Q%;rrfQ!82kA67jWEOJHiU@w54Rj7~@!Cahk)@^_$X->9)W0L^qH8?hYI;fGznmW>P(Zm&bO7vsGS z6YN|GFPoc=Yy-FdY!M45@FRAgd>aC!1}P}W`L$pwbQ4f_1mM!S`3Ud?DA8x&xZQn> zYBe7c6v`jj9Q0E*o9`i;C!&@&>n~X?e)lB8L7+UI5#m^xT9FPAZFX^Ah7q!Uou*N& z2x}z6ed&*2g>1N$rd3RM;AvRJoIg-pa2LGiVWMTpkwEYp*Jf5eGN3}QxO%AYYHaKJ z+673Bu&B+%ktrH4FyUTKr1F2KUL zne{xiJp1&3eRP;L%v6$v=vT6Sojz{3 z{TnkW9m_@{f1^WbSxki*f6vY=*H5lE=&Y5;l;MO`w^)&u88;ex2?B#dXQ$Zn!Vasig_GowJN6 z<=pBb%D)8@KVKci1sEql40oB#ghwvTg=NCzUY3&M)Q-a5JWgvxKcJ%3<8lb*3X`c)50y zoKQX2ZXLgO!_AJU?)Z!AxA?D^h>y3tl=F@Q~& z&gh`It{$cCQOpy}+9tyL?;Oybq3*pnKTmP2wjxb(+(M+6YG#JqiKgzJHMN*F<9GAc z-7~!}%`1nx`wfueT<0<>#Ew>LPp@=GJ!K zg;7oS>1{Q$dmm3%vry7~sGEb)ULFTu!7-0N1zm#e7~2$Us2|YCesDPWgzOln7JeBy zy9?KU(d0*JGT2L5nF^Tk>olisdhq2)nKc3x@^SM2g0$$j(l4S=^^jw+u|U6_F2-i0 z-fJ=Z&RbyO<7|Xa9{)UQZmdI*0m=z5a)2>Z$buW_<%^@xml}Ip;6P11-U_O$^ ziONC5!@)dGRQRTO1Obu#fN-J`c7kTw6?Cumv8g5}AXMd>X-nvMcnZWQb4d=J1~<$U zLuY0}&IcBtqe5izf5?eQPl=QR=|^GX0eJ zod$P6bPn)FMt}V$IBDsX)h44H`fO@jn<3 zps^hCIaD##Ksr?6cV6}s-6z1L@c3s#dUSWuMp`Z7NvEo!Ujq&O04FZzW%0Z`o|oN$ zd0;%D@_1gxf{!PIc|0$BnDqQa9?#3z0^^0Hc|0%Ut-g3sWggGVUL{^!lgINiw$FG; z`#hePiOkaaJf4@mOP;bGc|0%sns|BNJf4^F8yoS8A$iXzfP@NyDv#Sc>^lpvy(7Hb-pO|olv&6+j(0cZn5$E^>|2<; zRV96lWk0q>*=PK2*^kXuQf}Mmv3wUOr|gB_c@acD&NnWCcJmp^eh<+`nmpr~vJZU$ zG)!~)W#g!8R^=9)tyHe&xHUPe@ugTvN^Ijw z79R4Dw>?CA#|Zw{F|tMbW-}%F(yRO>tm^}^LCrDcKMblz`w2B0loMa3xm7K~vz)|Q zH{ZQzkJ$_}%~$M^@w@hz-NGK3aMvCZ?(k()KF+-!@;49pPbUBTDpaAohG2RYN>=`^ z%=(b#x|$Kne;ji?NP@EACKl(dR)-cr8K%~GeT3usVlw1(RT;lKb}puDXA)+Ud>px3n==yA-@ z+iQAsn7M$5$*Bk(KFFVwzLB$$%c3g^996)}vzM(w?xOF)N=vE2WmGe&5!#y_g7F>) zZ$Dfi(3hP<<^$n9rqqiY^Q}+JWZ-6g3@SbclEea+FQK;@yu6yCw@`3=8@#u@06Sel zJ>!8wM-7^S(5;7)c{h0F(x_oR7+#(wnb6=5IDXRG7%#65j`!#tc47fI_aq_j7>^97 z?{$)TUTg9LPU2!jFd@rwBRmt$e+MC4-sNq}4X6tz9z_5T4OKz2kd7Ud+{#m^0{U4y zQCakxs=Qz)eI~(Xy6?0T{eC;b%eJd~(QR&DU$ojXD*Xl}6XYTIFp2x1)cxt3X!G&W z(MU_|J^pamJGytVTg>C7)Z4==#XMe$*$=N2^LVKuHz2MQ-FOy3^aFUM*vIb&FDik$ zo;7RYoe&&91A$VIlcbm@LDIKRLW2oRHogYl#cX!s&BHy{%%e~CCGJFU6tw*JfOI92 zz?e96_^GB;QAC0C>2m0Zo2Tpb7I9r&j` zJ%2yuDi5KO$@!AW$4ikg%&(323wR~Z!ko$T>5}IakR*9tD0zM#UTFslq#bO4;DuPh z=~Kl7-@+>vIZeES%Uz3z*VOby6jR9RS<0%lA(DR)xL7p{x54R4BC6#HAWF3?A$1g~ zUX`3d&-qs36R=3@D5R+`CUv8gD624LPV5Jy9Rl(jfr!1EfQY>_HBI^Y;5w@Asx7f> zS6bGR0`Gb-qMDAbD>V+v8(%%h5EOIt6zZ8#PA)2iGo zNJ=T7g0vngi~Cfib1`V|=0jSoeJRi?if^+6m~mLD%Dw|`btw}P8OZ&Cm?GNhIHch1 z%O)?gRQmv!#@7?EMY?V6K|%Y&aYlHKa=UBmP*8BT=sw<_3*Xk&k&uid(z!-n z1_%8*Exl{x71!@eiybq5D=iIAw$H+uU6%+uYhT2n6o*lb^8qo^RMhu2+-3ucg|$jc zwGDHOG5C1u_F}K?XAX_Z+i|T%`O3&r2GP|ioAka%pDHPc<+Rl@B3KAZPAZL!EKiA2=;@!rV?*>VFa{F{O~f^tlX{A zW8mi?#|55M))OlV_@X>#up0J(sQ6cu%!F!~ZhR0V@kGMvAfe~O%YzH6ZVd#*pM#fY z7giSuEv|z1BWTr~A3BT=f%h=R?IEG3!22_9*IGTryA@uZhgiEkigfcvV&t?oCq6*E zjX#5+_t42(dkCk$4LHGL4O~yLv*A6z7TiN5^htQRn`xc9mHPXt9d$UmQtJp>CO#Zq zZZlX%tzg{q;N@Lt^1l$BMdoZI5 znbF*kzaxY_g|(H+sX{+pBE3B12oJ&gDJJN25BZmeWSD&@AU=iLpspa9ShstWKZ9fv z%`j&ukGOJFkvS)k>M0Hl7$k--2>~tc0>?dQDl#vO)gde>8MX26B+XCgig-HW-#sHv z74droPD0{jBbM;&&Ub;Ig%{jThX?GzyNI!31mA(9Y&Jc2*PRl*J$9yQUSYHNt{so) zd^n_~?+RZ3fwHo)&^n<qRMh^W;75lt|{kc z1_m}2E@@xR%?y!QT3^o14A#_eS&wpVW(*@<-nX2a8AlPX7*fv7jA_KHhL&?PL-00Z z%DI^#c=e2OZf2ZE9&Bcab-0-kas=h3ntn=9?rZ1=Y-+-7PkpyzwmpSn?f?sF?f~0+ zgO58M`ccR1bjWDPoesUzG5fy4!wrv^Qzjc8d4Y0nc&tFwJmi@h9vs>7u;C%R-0+Ay z6%<{085~PhnL)IO>!3t+rifG<^YWp&j@5?4RdRpvNR2ek3>IEB9X{Sz@pDHs(0od& z`40-m%IAk%l|KU4^v=d#0e^7~oHE&{EC`mf>lgt-K}eOe?_keS5Du1eqjC)CJW*xk zqfPUj3bvTG%!TsvL$F5pDZqksl%MJN*@gJoJNcQGpK+{9fpz2+ql2t=gr&YdR_#%b zX~ibt>yJNqqAG8I%QwUd)_z}#&&JcUAKtU3V!zNc+$vPkEZlqV)|a4;fo8sMeNv3( z)gX(5m3tjt?TKR|TRrB>4uywqz}JYeF7<}OS4TjAbyg*EjCi_j^b<=1v3R?yoi(}4 zr>2tLt{Gj~M}z3SeclM1S5JoHzT zt*+s$A}n`iYRTaZvi7^cBUHtv^3j1PecdldMn93k7vc;#EH8WZCv#X17zT*A;Cvpz zCUPPsvx(<3@z6pTLKjSgX~L_%MuR9OgR*Ix%-jXzGX7v4Wv6$esQB(R?#-Uv$Q=I; zV~MCDp?RNx<~@3kXyQU7>JF8l52tF0m;7xFXw)As?2$LIULFU z5I6fD{Hg3)ne5wc_WxVva|_Uy-VNLI`T*)0-y3R3T|7VvusytdEzX2iEP_|+)6i^v z8pe2{@E9sQESZ=Du0JlXKc(<1=q%(Z=6QiFO+iY=6qy)WY@C}RE6sB~efTRF%Hpqj z89L$vdhdppZ%^qXKcROMynK5~k7h|$6k_2e`5T+f-?&WvW;1`|l8JBrRQ_7m$KNQB z+o6QX9}f@hwp7{VkJ^?{$C9aJ@V^a|?@akdyW>(R3#gQO=H}g(=D@CxrPA?H$c_}| zv6A;*@Jil~<&3FfjhESJ+00JQWOgMpJ3X05f$RUMFfZpY!l#%A0Cp#)m6KU2Wm;Y7 zlR)if;Z({r#h+KjY04^e{{Doj;xuIw@no=y)0C@-=O?N-P1!-bu(XQPlt+mdRaSAD z!f)>Si)*SlO}USFN&6~JQ$%KIeHEuEuajQZql(j%kBOJ}t>QH0TjCW%syI#Y@i3rj zXcea^g0~q{#c7J*)ibI%P3cA+OjG<9AR?zJj^p055(-CF-&2Bew&HuhPle1Otvg#0 z3TG=pTTsqcLbm^(;Nxt?=gn56R&ciB+bMyZri7hJnWjVoRh*{OLYZh#RdJfaIuyk; zMR++)i8yU2v$`LcELCHsDb1_XeymP&q&hw6Ri`;pov!t&(;TTzcCFiXPRdrNlQY$6 zGpp0d$;A8rAF5Mxg>S?$vtBF;4}nTj{})SV)(&1d8d{tzNBuwDQ+P>M;iZh1$HB*Y z^wMNv0yzJV+Q3yoS8y>;lP#Y*v|lsuv#_G-VeMOvO%(Ur}?pp?0w~B@BD1`E@+*-3zCUf{y$_dS81K*nTEbbl7`pJHC2vAZy>->o^k0i!?c zfqcbpg$ld{sy~zxc*)cIqpaQ^XY}UAsQx&axbRQu{ikYtxo6yBUbwNlQ>h%i?cVVF zhrr?8oS5B~cXPZboU++;Pk< zdK<3M+Hqi2_C??_Q`fD)lzkQ42-C1{&V)P!tb~rT$Ux z<%KlsQ-_D)mrHoYU-ye=<*=riJIbOjB5~_Eu=SvwBRZM5;=dSLXO>les%b3DgJ3?z zyxM11i=nAqPCW}QeHICKW{|tw?JP}Nmb;y~?lQ|=84_FM|DVi%vC02=9kD0No1(=g z|0lyQS3`}zZbH4IPC5$VrNUo#CHzlwrClQSsJ|Gx4y6rBby4DeM7{!qWHGqz29nP; z=4=LcjVC@tD3_Osp+E)_sRUvcmz`FEsc!#H*vX~v3S;aem~ds**f&v9r7jb(yXdKn zCtgBYBCQ;;-KA<#W`UYPGHcfi@?HW~;#15!7=ElkJ@5xU-(@O7jsCagCm zycd2kq4C#U+1WK=XJf)o;TIEj%9=2E5HiylCiEjvOgI5Z#)Lf>3={SOQB1fFX-KB0 zW-{GrD46Qjc5zMEHOGYAvL>8ON!?r%Zl(t&EJq}fHU-H4#DpF5jRjRPZ*|xme$Rwi z>v>ylJx0TT{Y0g6PNd<`Ob^eAU* z@SIeKi-69&DDLvN)?f?gi-+c@eW+&7-B}ibhwAz0wp&Nq%t+&MG;nc=G)|x1EE0Ms zE6tmJdaA_e@Bzw1be(Fd*VFJzhTZV%;g{=p#$VSSd&n{_Ofxk=daUUpOM0v)S?JTz zWBI}O$3sJQ3gT@9{l>yOv$2rd(OPNV1=Dj)HWnc@$;MohjY;s!@?oy#G`+*#@Jluf zf8E{iOE%``WaE@yD8w1EWMjD$e1~t4dhkgJ ze*`P+4zGIIF#L6+z%SWYnUjsPv)TBL**F{7=mp0AqikFbMdWFo4PIi?7n*Ebi`3-O z+=Zqz*1#{9nMil`yvZPG@;ua>1&N$RChPR zu*0K>_vc-#u`d*W*3!#=|<6e`EQ{b07l5Y4o_$6Cz_yG7NTPD2j zCHSSd?>E_!8NmbDY^`Iq9zeEk1>^5!E4#V;zt5JH=FLL=oXOVk9#ETe1lQjH|0#Q* zmOp2*8HfK8URX2!x*70a$@#?#CL0qO_r+{Bu4Xn~)P;%9|4TNqrSqq{#>^0zTj{Jc z?@sEsOg0|&)PBpTeFgmesG1wT+{=auuloi5JD81KCL1%z`*t=P4>B8X>*B;NF#d6A z{Livs7h|}JRKThHdj&q1mxxz&#&V1sV~IRfRqo;VXDNFxvhGjT-jDfI0vn9p9$FH! z|EbtRn~uOFzBDd-XeYdbLo$CU7ZRl$6z!#q${}}BLA+`?_7NM=VH6;hzqIpkyXq(G zDVF1usvr@px&cc`gD0x~h8uMTFRgkShxr}IldP$_5t9N(?X7%5{^XT>ETsvCny!&wbAiOu^nwR1_;sX}OAE@k!zu&}6-gtvA zjKn4T zy%4vzcbxqR=#a|QhH9RA@$zTH^BJTM3R@LWOew;KzZf4lJt@OU5mx)FG@ zkICU`Y35o_UH}q(KRH?b#X#13V7dBnlxwu`6QJh;Es{5Rah2A|7I)Ek_)-H#`2SsT z>vVSH)_d0H-rv8uQ)ga|naJD|~)Vv?n3J zcQyV5>-aMK(_AIHn4??+^u+fnx5Fc%NwpK^|#_f9ZzwD#k#$F#IYl z&9GuG*RRvJcV+nT@JD)}XdZqBjYNW@xLozvWRzkJmszp>5hzWtZ7IC*Z@onFz5tK! zbU&#Hd>TT@Etv%4Bo2e40<~~W2?n|WH6<7{Uv03dh+Bg0ON^2s9dHX2SWdhRCqxIg zC>Ad}VzY)R7^Ol}5!1R5*`~>Kh;_IpLde?qB`Va#Bo8ib4aP3EGP+ACI<_;c?I6)pqs}SF4Huej#$EN+VU%jAKuKm2P zUVH;mj2c9cX|IOGy&9HB^}8T|H7t)cjD48YuxJlpq5g1K!>p#T+0Y813cEEd?EVn| zDW-^`j2&Wuu!yYDVRLsz;+Xr833VjSa&2{5Fk1xsp$PgP^52T!1zIlH339C$V7ZIi z(aZY8w*$0%2U7Yp9RWBrpt$BR&`e?KA6M*T~KSq3!3 z|KskxuJGbiN`oXuXWXKLqo{Ew$qwC+7CK^Zjtb9o(%lg*j5W{W ztcjUd#Y$D)`CmJVI*OG=^4^C-LdWBIJl@8O`(rJVd1rg@mic+ddh{(D<~p)YTo zM~Pn{eMQr}MSa8SYsTA_Ck$j4vRB z<`5erhu9hTlW%Fz5+gI6T(QJZbC;IL6$kF@b7_efMHQ|{b!mw@9(QSpuy7S>k#uQ^ z0&kh`(h_yNp-W4YczI)&mdG1RLlsS3TH-*)+m^Ys#Df`c*V^R(C-m*xy0pYDgm=ig zv_wiA%64{Xi8|g*oX_y|t5CiB$@mUuJy z1ePc-teasV76lI1K*Fq;Lzw|8)|6n@Tfixno?=p^`{G~5Wp6l&4X#bQFLMcPY(GTv zensBcY|>Cx%}-)174MMXpXM6z%+(B)`9v4QZot1W+t}@h7t(ASjK`NJLWe1Q$OYEB z&<(8j?(4$p?lE<&m*;1lOx+K{M3i?VPaj^0O#~U&V&N0R@dFU&JQ?!7Rgueeli8s0 z_EYt#tX+AAEp;Pm$vYMG{XkA?2GYsy=nLY$OiiHzhao9FC6Cl;FqB_vF5u#U*oC>2 z+}lq~-asa6ML16iWc$cz9%`A1sC*t&j-)s#7jz-8Fy0q|o=nVLLizl_P)^^8q@j=n zB0_F|Q0H>p)POPb{#-tv$YO0sA!PE`P~~&w9*_HAd_@YwL++tBl8%4ae8qq4KK!wZ zhh{n%>EgM~i&$+=0J){Ah+X^;QkO-F*u`}`Uc@e5Oqv$SB6e|sx6ChM7uWHIMeO1d zFK=ALF5Zsx6-|qzi!?xAU0mQj2N$u6%fhJFup;T=r0HE<#4b*~ z=k}RU#4axK^q*WLU7R$P(~6{vOMFHVyST_xHMfXeT*v1Zv5PM!4Z65F1(e$y=|&X5 zG(ab&X#Gh4uG}J6?sR@h|awp z*bF;tW7jQO4QCclqVsETxb+l0cTaH0!ByjkH+TVm#n-1{NvIh*^>vA$Q!hcMZa2QZ zPF?tqof<{R&zrfLv9~5FAYJ@obh|6Lx0PU}^_w!%TP5wT@p@$*m&oo0BxwasT9O|j zDSbIbUiwiJWC^Y+_)8Q}Ka30mbNMCtA+XRP%%0*B-Ro9quDA2p&*V&QxWcDMF{Y9n zVM4Q5jsSG#bQbCSp7=A3)!bGWxOm>$Uddx@j~{g>j`g>EM%V& zc+31k_9-22Sjavl@$$xn>{Glz8`EYX`_y}kw=FAVpNgP@m^KU9r-Z(J+d}rK=SkBc zTgW~|;W2F%vQO!Fw?b-@6~wez$UfDXe7g26WE%*)TV)~pR1d^rkb5V8!3aR-?jK!&j9NF08a57LY?@W)&5M7j}8Kq&=dVQB2~($Q|+yyx0`z&sj9a>F2x zI@%mbd3iW@S75!D?_zxAD82-LxmV%O*s*KuI6*u9iFQ+pH8kuJ6BX?^K|9v*xZFaP z3zo3s1npShE%Ot!V;ygppdCxRym5kdTul0krU}~d9*nmwOVEyIGTyFrf_5zQ?b{}3 z#}pZMoS+?3V%TwlcC6#wGP35!%?O4ZWBxuJXPu1K6?O4a> zCuqmFkPqxQ$6Q5?=Rfa-%{T|#B!x*ahl)36niZCGip8d+$s|fiLXPvfU`)98j)wa zh&nA581M5i-l1@q)-qmD%Fnai$7s7@`*Gzw;F&hgfbeRhBM0kTFku>dXbFuwhm<)) z=ScE?(!}(meEcHBb1%i8eAkdRjECt2Z8*M`s5?k&p1U4LT*iXJn0}O3xBv`2v1K}_ zOuyA(b>^g?GM|pXq=9_$^D4uos;&xsdXc@+y*N=5gk#(!jgEp9I1$S0x;iweerLrFY37Ni+BOs?~4LAeNo4CUzE7%i}D#2(--$* zUegzOi>%idh2HeV-3T{*k@fNVqK@mn$U1v{aT)1NUlh3Mi&qnF`l7&1U%ZZR(-)~E zuP@46Y5JnbWBQ`dn7*jvx-W`6rZ4Ka?u)mPC;DQ{^u-9$csQa*Ce8<*B!x*ahl-am z%?e98#bQ%T;^k8O>%M60D2`#lrk&1QLMxZ@=CPRgT+&cT%}-)1PNgpZQ1``{?u#+g z7l|&2bFwog9KQ>3{S3yO{CPH60r{Pl%+XMugT&}svMQMwuun0(mMoNLyf#hi6Y?Ut z0J}AF79EcVJEsk!jcDWE&nZtdrh%(sdS@g;ABOyz+=3-+Xc+To#g$w`z;K;tV5odC zlNjlp4t2!rKrtzovs~otK)bQz6#C-(0o1?Q(ru5<3%cznj6n}g4!SMrLXTo!tOp{I zh*_u7V;>oSKY0_~3>G;u;W^D?obXnnm7P-92PQB+H92LG7$-a(kHd6vz#cUXp4~4v=NSGNtPCALmJAe`ALkW;x;V++1J9}4OwPSB208DG6iV!aoor(#M7Mk zuq&&7USInIJK~WzbL5|fzQwK_CxXVhX)X4W0lAFPMoWYQZ&aK4CES!%$f5 zNNdx>8g}y{KFuB;WRw^2X*`t5(9h@0*##7`Q&q%%>I`FXTKA3EPo3d9(U>kB=dj{P zl*^%S@I+P|$zjx;0tWCWV48d|Kj?48x5Fp4Z_wZ3BkP$a+5enKSWkaHvUU;v@#kss z;eL=I_B9~-qtikgBW=!`Mr}?m(K)f*jAOGYOiaaOq)HGIe;a@N#ajR&k*;2(zZao5 zSWw){s1<>CL zH!gaC8yCHfYZtx5jf?&i(i<23TE>lw{$<9Ei(crBi(Xc=#zjxbF&m4EUdOeIp4Gx^ zEH3)L$j7+o1#VpQQRoD-vAF03Zd~*(;l@S(CG#2=eS&b~q8E9Li(Y7qi(bdIi(ce0 zE_xl;F8W5~gMq?x(R0<|?T;LVcz)0($0rwV=sP|wE3fp0vb4Tx@-%!kmPBOe2|cCh4fM2Jof2NNCnyS&+kCoXUpNT zAiM-U0I8WII=o!ETMp(873~AGY{TUe9o+{>xq(I} zS0VY*6WE7~&nNa-B=5#El_S_3>5R!gAX)4SPd*Mj{KYEkMsU}H^f=PzhB^G1ozFxZ ziDbi|$ED1(Xqr>=p(q$VF3qW#LZHW`IW_BeJk6l2OX->@oZ<(Lw)U4wT)0~>1YCnq-6rhUz)O<-D41uQ19l{6Gm^OG2h z!)MnZmF{t_UjLd+=t80!BHHk z6*dU^)uF4uWn$pU`8uraor^oVWykTyw$!pA^FmH&4;9krS6Hs}v2J%bjppBt^s4@py`c%|%bR zMKVRh7I@426b)O)8>VR35-)F@qG2~CeMQq04SNvdZOc+L>=}%=Yn`HD3w`^xDH?WH z!aHPBG;G!&P0_G* ze13|CeFgboD#_J`?fwQm=IRGKHwU;hg~?+Mcnh9|`!3=(BbfCTa2`v~V^YO;$G`Ry zmgaJNN>f(NPhu=p*4*J(sWRz z?J6?QtB9(nChFjA=)YAy z(utqn1oeu40Qaa9e;lTZFN+dC2EDuj-(bk9an?c?PU5FW z5G2Qafe&^PJjrnqJs-tdlUU`h9P6m|=;raU&i&wN$ld1Ma25nTCVse6@i6LTxU~H$ zq+UTuI9pST%N{tG6@x22zK>m~JLYvId!6yl4!0W(^E8EDgY6L~{-?_MtG`hP9Rrcv zcSG?-o1wh;*eB59ah@Ry#ec>+11iXKpu}w$4a*V+)o>Gf-4+xXo*i~_4{D~=D{xLY;on1at@Fl25qv$?Qak3s8&YX))?T^S6mXyihVyA6Pj1MOoFGk`I zCMJYq6B_@89WzNy3_DX*E=}xHDgT#Hqv)%cd6MB_nj0DjeGc5npp=Ob;Yj0F$S;YJ z;nGUsCaG%SRt@1d`~|gy{|*%|#V{}Rd^POwqMN)XN1<1RuL>vjTMwgYR)#<3O&yFR zb}gZwkE^JOUqdBBjtr{-P*(V!@II)g&Ow2&JBxgSfpWqF!X+h(aB%|k8Gb5!4C(GC z=hF~Vxxcnh>U*G^a8)?>TnM(O2!@lmBF5`sN4TnHl6>1FwJ@6G6A$(n1=O%_ZJ15` zyN7r>AkK^EGE#)u#GO6F^8xX$9_&gIQ!%E<-rFHk9fE9?9#&Mz<}}&%^bk_GV6AL> zZ;!1@GTkF#^>s_tC7HE7iB-m05BmwmGb7aFs=>V!v2fBX?hm`?=zOo) zIFZkF&IoJV78}zgL#hnkfr`nOPDifIjR{& z|FagjORl5dB=ujln6$#2_a2LMqLx_hs6LKt_l3hzTAHVpj-7CF4$rCKoLb--Y+~Qk z3gCDx@QK)w;*)8(&;}<%v+&tyQh%5<)*{9%&6MnkBdLOH6t$2zd2~idomhcPKiQd7 z@_}nHvA%#|r&VqG3H@NYq%Svcl|1cU+_XZ{wm#_IZxq&jP|9nDt8$+_O{w9ia=1fO z&z&5|l-u#DkSfM365b^`5ibC0h3K&%w>u286`kSXze4W2a4863kLW2vDE)yo#4!;N zwiCiXL++GCA@vYWRD}C)$I&hJaFyFJap!#)QGc<+RYk2%r90d{=s1F_wsE@ST))KN z#@IN~x;vp?j?PzO<8){2@qR>oN(-54<8*n?W5-8uht|afqm*)Q8fB;o5|+f2N-NNv zaY|UTxu`CIa)-fMq=+^)&a#-3vE$Q>&3b$-3vkcI03#VMvSpJxC0k;kn2u+S@SX`{ zW!n0hv~tu0!Y}ho#9efoQdd6%_E%U)`q z8PWuqdI{`WTr$#-7HvmrRb|mpxC4nLHma9Oxr=8Qg2vksSe04_%MmukIl(lN;?$8^ zF7wP%*sBn<-;Tgyb6wvYP1SolDy^VL@Vs~^R?*>GlXVqDHp;zapBzn4S(k%yTlI@* z+<>|`kyN>Dq5ej2Xom;YUsv4*-(aUhsH%5NWjDkxBMf~_{q$CAe6|3Gcqzc79g`}z zCz?d4Cf848EA$Ohqp3Ejw2S=d8g0b0wlJJsKb0lnf{l#DC6WM?L%;+G|xUa32qR zQw~McoRpjUmQv4RQ4_u`hlia!CLQKt4(CjAmt8l1P{MVym4@H}o4{`rExLQ>I79Vd zy;RCAuQ3D<*#yg>7{lTC!$Rr=3bN5AumpL$zae(^KC=ldLHLPJA=qXU)D`5m zF^1~9da0D#e6k_ zdfPb7^Okersv@qRjnh0IJ=NfdGI)x@V}yZzJ}(;#?dRgn_VA=wik=#+>5`Lf2&t>!FAE^;?SU57kFF)1k1^1zWAq6b#-HKg>`6Ykt%%uDOzZ`D3BFNG*btAw z#?RY0fe^l>7I9H;yb?t4Z8q`p)p%i(&^v76vZt;OsUOl1`Fv}MOuN7TnS{uO>ZCMBizhN|UHmE~L$Qv1=#^0~oD)0SP{-%;z} zl?{KV!K&!2|Bk*F#-v;>CRhI(`jqs&vP*BrRuo zjw`T~#$9x}!5!~vF$AZ1?)zj!y+Se0u=1(0C1>Pl@c9Dv64c)0KHx!>mk0#q5nvrRO{%KxTx4k!d(M*F?T82#9_>QYEDi{-9*uE zqv+*C_ZWyRfqg1c^TO&E_^guCIA5mLH!**z;u2sk-UK)2{&g{D&(rg9auzj{+UWmr z^F>v3!4OEdUUDJRf>ss1aW@oK>&eBn$+bikh1GChp`#?vd4k;JPY5;34@T)U$Fu+ z`!U2{FPSu_{eQ!AG=Zx`Cjq;*%ev#NCd*huVEN_U@ZJ~+$CO{V8`^^0N0+bIfUOHg z$EtSG2iaDsDgI_)`^TF?t`6_QGE#>)i5DTC$~M3#y%a~%Qgdk@8k!QFWZzs7QVX60 z@p0cEqmAm=2vha|=2~dLVq20e&41aLO6?DW`QWh_gc#F_)tQUtaiZL=$!Qx_yIhQ8 z4ymz;XDJ6LZ+#6X*wbH$^*x1&szDNr-XDZl*>=HZ3=2qqtva6x-xd++Zz9MOBKP!9 z!m}Eyf|6Gk=<1{!Iowi8y^CxqZk4HWa^MzI`qy%A$0+@C`Mr>a(x(3^I~d)cl}h(; zbUxvrGymC2Zv&-&D@jeq{^O%DmG0%Fp|{Be*hnKv!k3)4*jF7g(# zCfKKK|4MU6)BeO#{AXjADK!(jfq5raBJCvlgN4c-=Rp@w6X+m;cE$^7`$B_xXMStZ z-rzycEhr-gO?$-9h-!j8-n=Cvkk?6#77kzGQ@^hgdhvt++Ogr@`q4V?QeA#(UlMmI zdLu{WEpVboqOcSzFdLB~R6vAG{dNcp<8S<_F6~#wYEyD2rw*lT?x4Xo;12I(UI$SN zH>kU^mkdp#z+Gt}jq%{1x}A${L+UNBN`-gZ6RnchIS~fW6h%-P(nUikovQf$8KpjY z1#0X^H3~+R$B~2H>%5K?^PV;M{#0n95i3}p!av>Md7V`E=vCO>cJeB^M{koz+t$(b z@1XbO?J4b6OH#*|)agM(@?;#AXhFVOyy23t1skm3vymH>npGN8`MWN& zDBc5w?9}GB%0Bp=QlrSD`(otwI3I;g6oK}xkbEpJB~x7X+hRxU&J2}yhJJZ?hmO!e z+hus;m+%OU&l zt0DD0wkGn&ZkOwf=k>No{=`5#hT(gAU~Gb&=I=`-8^!G=%AF>|$Shq!20H(5= z{TAH|v`*qCLencTa(OM<$#2n_7R5SHcrE&|-=cRRx0BGEukl-yd*d2vT9n@a(Jg9c zIM{E|?J|7nx2Q%@%G7rdN2MQvAYO~k@>?|EtI4wS{1&atA^WM{qTA(K=eKB}9m6oS zr`MuXvQeDZqSQc&aJFbWw2ZVUTR~cMB_dvn5=ceXZPC`zt7r)gmP#M(kJ+qZ1&j1P%f8HzMLy#$fYI6U(kAWA2@nq=y4!rT|}*%0oMXSzAL7>YEh z#%cQQ9z6w3k+oqo(MA~9z8*|(d$%@w*qQ0hw$@~xMiJJri%fIJ{b07<(9Y~{)3`_G z={@AkfwjN`%^q^*&|2W-3B8A%IntTfCMd|?!_KsF+*8dScIFtH#{D#|x1Td7)B?Y? zzutb%oLmc>?4!4zGp9LJg{hIdwWHpC&YV#T%y+1{{hT?g7I@)ldM7t?o;d|2YH_bL z8?>1vPOEZ{x7K(rjZb!RGff<~Eu0VBpv_#e9ih9s+5XF1X5o~3joJRoTvZGF<09=n z&#Z8k_(iH*Hnkju$uxG7hvNL<`6(FE^7QX!ml33MyaEzsK2Jnv~k?O_tv`!nMWKR?a-`2awFGJEpQr%$}~@jF~rVdMXUp;~Zsh@7TDYL`}8VNK@j6 zJEqdga0g+H%O{=8XST{HxFI-hUqkS+GaL*;m93Xbxeq`PZYX5B*#wp#&CG^ErjJcv39=4? z2!~3WpspaR&BjG$&w8npd%%3XUyvDL6Ig;g4MDgsflVQ+?JPl}Xc{4yWE0dCWTM%) z$V{)73ZG|$jc~spGt(xp1UboUC}if@1ePHCLJ;Awz$U0GNCVi2P#s?{m2w}$2Oj9S z&zu_KlSZvUVf^{pIiES*#`Tv0%94n{Xzrj;*7uh(? z^K9d|&n&ZXnrBMRM z?1c&a98q)`Po^1B^mD`_v+69m+RpHjS#=g&yIqC}FX`uqqE#A2*;6whf=ai9cT-lK zMdPxsm{n)dnt-n+%f4+^okeTwa>$N)O+QBz-M(F}<}c{yh@!g!?P!LooQuA3Xp(}y zjiRR`bP9$!eW}`BMG#3Al33BVj$ZLDaqkPNoR4C>=c3>PRo(|=t&y?Oo~@(zkwK%* znurfbtWu*cs(ciP-hqRoam&`xbMXyJr*TG3it(9NyfS@oZrs^@CeGSdLn)1moQmsD z#d`RmkZN4a&yFR=vYpG>X?WhZaifYi%N+Fy9;q6a1b9{c0BBtl+PGEg=#lU5pde)x zq$)Q11^vQ;rq(Sejh!W3P=HtciXm|1sE1>!toYV?*2MjP#G~;{vdZlKQdpe@M_F;H z6Up5Cd{~_TaB-OvPjh^sgVHHJEpw%ZXyGI?*L#VUPJZU-O(sh#r(tG>muL+Y&h-*) zoTil@p}^vHjuXlUKM0pNg{5b^WOLLRP;2ppl)({b>U2SUbrf!rf=|5oGL2dy&@&$i zsg2}yq2cp{F6{3tMf-+K8wHq%9 ztIrNWuBU@ssePemm3 zmGD-)gWPxHXaak$ z>K}$9o@L$SF-uv5!c6ty>t^M2QQ?!rD*ki%4HycpfIgcoZWsOYo*b25(kOZj?E0kL z;jF(7BO?*9@2xN;7%O6!)w!nPLXF z(zi)c3-!*x9ChDsIjZzS3-zkxx^93$eQKdv3F`VPgZj!s^&-k0GSi@@hAf;^+a2>5 zZXID^D;*2>vE=&_Z#4<-6&v@3;M#m{aL3rVZGu}8GCbd~aX$)f!v`VF^F$l>o8X!~ zXK<(5xW5HA;RJ&_!^TA(X8mdkl;(M^jms5WCGI4YI$UVu(t=yt!pOPI#x)RJmjev$ zN*mW$aP#p(z3^ONy^n{HRo>6MLp1g3W(SZSMrPmp>T0x0+E z89AD&&}JhutXpud;jr1}K%B|^AINan9(V<_Km6Y$2uuLwxYg+`L zo{e|=u!bmIZ*$O^88QS-_!8P`vxUPqGR=He`a@VR>SUO4m(9lkA?$ON7Dndv4qDb< zIhH=*PQh{Q8j`e+Sk)x8a-aJ$s&NBt-2K4GI#dPA&eA6bMKIkf$0>a;^Wh6&#fON} zPMA3eE$stWV84yX#v)S0sXZP$Nk4m(b~9ekfgn&#g`Q4lp&w3|yZKlBx>jiqXA}T7 zPN{yAK@zzEp7SyBt@XTB*@Jjo()$dis2^Y@xHxWbW<5k)h>;uj;SB3_MU_&o<9Q}N zFSN%@^PqwkrM2_mI_drM?osMHOcwFVTHsqSgUOqy143(ANJ6NSGrtVU+dJ{9kdwHD zRVG#?FZjy5&^oXd+>MVjuf-0k#r;on5FoxsE$|;$sqcbiL440z;DK1GkAU69_o@ZX zf8D&HJEWF~k9lwC?p;fiW-nm!jt}=>dS-f_uoFY_)Whjcssx)G=BTbi`5JDBdNq}I zcSqk9@F)Wo1&~6yr*tzf`i=>awU_1cSvmUs-?0WPS@ircuz6Jd#S=D^vL$}L%9fjzMf09< zNNuAub)S%Cn_``^A+wli-jCEas^ed#y3H#Mm=r2Idr*$rtthUV53%?c3hH+(PXsl> zLh0qno>CjpXZR<9M1(x#w;&xKTFl5-iA-`@(4kcaV+a2^r-cjJ2%rJl4i>6|3CU zSbzxbJR7&K$k_tqA$y8%AW z!$@(QB>;(4wkxJjK^jX0yH$PX;dWSFr z_rdcquSVmkP}IAmVDPh;I_Ut4H^$M-!H?o0kXhozp-8yw3rv$dh>Oc#6X#Q?l5K_h z&F6St=wbi_s*lZ;9C@Eo6S0(uH)nD~9a~6olsrl!WIBl!WIBl!WIBltf)uAcaee<6=1b zPKVmAKthcxaMe+@U4fG%!yWJD3e?b(d{^LlUl5i43hPnN71#_F)UH5_ zBFoPYX;+{PJpk3VU4fz}tJ=%45ujaxL9Wyc=vif#fT4B;1}K%Cgbdmh7(h*iJ07U* z3Y4;D`6>=vfl|@H6)1G`*-Gx0ScMo@;4uJ%bTbJqImC7aN*=+~0Bq3S;dG{1~1$UI0Z`pnyeh{vU?fL7pqn;+FjYPCxAmw4oDx zSD*#$_+~0_1zIKFYqvV~#a{^bOp^jSAK_95d1Ct~rUj!a z;@*kv-)obnc4tRHSxtXuS!?~WqU3!wPMyoC(FIS0)JbhlZLajm><3akS*YYK_r~<( ztrcCcT9@F3~zkMVezN-B2W1f8Fg)HfaXiD$xZd5 z$2T$}y%M0M+ALdD?1H&Z4uiiTvT&%h4vXJbQGy{$&V|2Cl#zAWZ{}S1yCSP#Bxl=R zJ&-YhdCkg%guCRj)?kNZs5(H10&V{!ijlf z;Kclm?dCf%nM$$m)^=jD(1cL>PE4Wvo0Qp$8hcL6$Oev%0jlHI1%VS&z@!MAm;%Zr zD0`t)+*Fifm`v*=;E1z~^ zt__@+7EU`c`_^@0wq~Qc@1jo_C+6hgo-J7G6F4zHDlsHcTbg#vp7zEO2TshESeqCp zrd4_;(3yvY_nR0-IAjT^u{)n2wFm+z_hcB1uqm{QleK|6x}D*$+2%l;$@~LkFiy<+ zicl`U$!naL^${30rGXREq7o-2wS+I`1Wrs#ZSH57){GO=%IDV*K2#9Ya$-u?vk2O^ z#c31m#I!hQ%@m-mj1x1!;R}OiCib0}X4LdtE2yk$i9poR~s?5@Bvl;KW=6fRhMto)a@4 zBlMW~r=jgfXxoW-BDCT=G55g8El$j7;{zvVr@Bte_eGIC@N`zoiK)Sd)^%bEIGMGb zm|xH`wG*@YE6a%)z};uZ)^TEL?i;)7S<81~YVgB#otPRN!$U?bC#D8J_gWn%rhtm$V0hj?S8prjh)NDtA#`C#K-E z6LTFFuC<()tX+!vj1zNt;KU3Huj|AlLzO)CK+B0KWr$*vFJjA)ODJ(-3Y=9`$+wzV zPE3LSDDXqf>@H4Bi~c3>_nnvlf7P#aG!`!#&^0DB9~<7jYt&u5Z12Q8m6aA@Z6_w# zCWs20m_m34LD}QY%A$GC3z2q&FeND8i7C{}gnF`B%rx&u>X4=uRL3=@x^!Yn4pOLW z8{dg(@xM|~LwzTvh0@EDAF(_UC)sEVrJa~(`c6y>#U-T5w)n|&Vp=He#HF@@XgL{k{{^LTM*v2iUN7Vp=G% zyzFyLJSV1w(oW3DI1X=|m=><-IJ8}`E`byCXguHy+hw<=`w1kNB0#RHt*A|Xy%|^`i z5W~nXxSX|Yf}@!q;So@{lu&7w3p~U)pQX;R+CxktOAX`eB^1#X`xYCfIlC8_`##I= zbPfc$$s~;2;ZOnHcV%5d7Ebh#%-^WriY=RjT~8^9B+5PTEqzy1*#_qcw1JbDCE%-J z`kirfu54|HP2+)wELG|nEXm8>GOwx#b@HhxIhy)iPhx6OC2KtRmmZv|P*tBBFHzb1 zq4wyt*lo)VeTJ2tZlqlQ;APoZr|MDT6Ds@0qfG>~DP~ty_ZU}CStxAyrM9Cv6&_|D zu`6pGzD1WAv1slG$Z|F3`ez5q#yPqEvD32gPSt5}HuLaZSx(6CiCTOJ($*8~&z6mL zhBSp4%BEsaP18|s!olAIVtF~+cNDLGw1wgG1)^BiDa+JgCxY(^#5y{yGamsXiB3-2 z%n)>z`A~0c7j%|W(5L95iFJ0mWx9gwFk-qmJu}C7n66IW%)P)YBxYBqGBXmamod@J z8I<9%w+AL6v70kE-L0v94d01m{Z-(=+|RS}@a`{hICujm4J0Zq|W|(n)q4 zCR6tiR@sdtAM3MZg^*Q~X5TY=t+C(MgUrs6?2)g1F0r3HP9#y;=cnOAP1xy){l)T~ z#7070n5SAn=-SY;02og4rUomGPa1q~2*Qp<@FHln4Y)^qYzSgD!Ipqv+B+e&oJAyT z0`WQOB7Qg;SI*&E$o(A#T0Yft{UsU_|YQOG$FW z;kigV34&AeugBjp{@jN`;|^il*E@Iw?7JKhI<=w zzYop~azY<-}2~%DFl?0cPK#W9a)~A=PIa^5I3G1kQd$S~lH&2<_Y#1KdYwjh3BN zn#+wN5#-$mYV0z}pI14s8X_PC^6-45DSb?7lzfcZgaJi)|!@ z2$gM=)b9|rtd2`QLd~1&N0mj@g}6wlbZbsh`t|@Qbce=3iZp^jeL9a zj}55W3cg}1wum-B!ME2@@V(B^&EO{r*0`ZRAuS5N-J#dqSMa*p3cjNr1>fn!#&~K# zzR1f-wA1|#pG9jc{(-uRf1n=4Hyp4d#a9C3DSn^Vy%N!W4|s~73~2RikR61`D0Mjg zwc<}C`3NfB`;|Tq<(~yoDt`oZ?)^mXcLPJc;};zXef%qZ_k_NuP~Y_!^ao&Q8?>tO z4VpUf`-=JUg40;2gV$kkD-=OIU`Bw_=^GR6Uumgi`3x2ji?}@ZAXm02D3jY7ypbvl` z^(+1YU_8a|#Gu!MtX_kbk>pbbg6nrEUeAf;p!#lyx zR`AP68wGR6@qe%2Z78sQ1vlL@P;f01_9sIblLv!r$0j`3Q}96`69qqnh_B#jo`Np~ zR22LcB1XZSW&V|d3!&hX9;ttD{tf(W1vlQyS1`A2|Mv>+jsojf@P5E}7Q7Uvh`e85 z!7Bi*J`ZF!Au>wcgMV$okCI$0_-IeTH-k(R92smW_ySMCn}HSuw*=ZKm~P{LrQlaT z3ajsSV8NB(XDfIL(#C?h_x-fKTfx^O zZ4}G{1pj*lKY{}5SMb-scnaP?jhSCy!OsF(-DK~mdKHmT>V5oc1%E|yQSfF@!977H z3cdglU%}fv1s?#YD0nR*M#0>`_*V*Ehvh}@9a!*l;AboNbEJ)ec?#oyui*I59VxgQ zFrI?PzUisgw%}=iR!;-jEJQ}B1^CwrK856>;P@yr$(;x?QSfVs_zErqS{BA@02KxQ zfQV5rcY*$uf{(@%-{U*5;KE_G72FwVqhKCo`QIye1PZL*f{z8pQ}E~1nE3@3{3D>% zD?#=*BBNB|ElfEA3w?I0FSoaG7R( zPaqS(&$i$NNE-$7JkbAM!55>z`W3tZ7*D|`QDf#8DEKTutG@)<#fXej*Wh1U@XaI_ z3!dRA*d1XMydNUI1uygz+#OI+@Ipk4g1I00uM}MMZdeW8fr76FKU=};kv0nEp{oDA zg14Z+`W2irGEi{Cw>|aRLqsW{)m=f>4v|r6H~eb_4ry}W7K-#K>TL~@FCHE##6SQ|7_E4wftvAbTj$> zv$7xs{~1$t{AU7cL#i~7PuBIH37Vw_{xbo!CrJCx`i=4YXZz2mcT5BbwvpjKyV%^p z({flhWYc1(?1+TtKN~Fhgs*J&XWN(6_Meeusuzo_N*O3;k~eW3opUIZB|>saGRX~e$vM^Zs-+A zi-P~jZMMCFcj`8?6;HQWEydGqR#)-&L6G_tzZDoy@r4~N#rtlvW`I@~ER3oOL`JDy z@vjx%pX4K`c<(2khFw5P2(e2SYQaib3Civ@z(N zyUn)OxA=i=z0wa{ORx1A^rI-Se!YGJjHlOCRFwGz2E7i@>XMVAYCR&O)KmD^dVPiD zV$j!k2Hgu}V$e$v@eTT3&!7(kR1Er7M2tcEZnJ+<@L?Z>)yY(FJqEoA{A`2%0%>E= zJ9nFHui*c#LFb;bBgO9qjHmdW81!_I)oakA_!p^oy3I}knJE5sM0~}6>M8yvKt=IC zBBB*T*%_D>34 z{eD=j-oa!z5&Z12<0zz!f_LsV`)?`u5)@d!f;R%=DY%vi`))HClfMGlj!n3;r{Kh5 zqu~7!@lANJr{Erdih@r@#3)X8$b(zlj3t zS8(jKK*8g8sn3G<1GIWqkj+M9lsX#!+JYC6Tr7B+r{H}+CKkLJ5nsVadkQ`QP*L!c zh!_R?ZnJ+=G{kIg{0tMEu;Nie{7W^eOW`4mC@iU;+ z$AHY~Oa-U#uN7R3m{#xwo`RQwOceYLBEEue^c4IkprYW^8NPyjx7j}_cqJa$y6wP% zJAj|9;2}sG3*Ncg?7yYpgHd4p3cd&!Pr)ZsW7{eC96+ld2H8?XMyYG@uNAzO?t@GP*Lz`M2rRdZnJ+<@W+_sTJFGt=YgNC;Pa6-3f{Tf?7yYp zTTo#A3Vs6^Pr*f9>QitFK&zu?MO6nxMyVe7*9sm;a#8R$PrQd_Wr!FB`);#;Qt-_mhSf_uu;6>Z&sOlONE-$3+->&XQtY*UpfXFEI9R9U}H3a=bf;cwgUwZ1V3BB(~&k7 zymPnNe@nq9p}_hTd=oI9f?uV^wzJ^(0Ihx6$2rfCH)^c4If$V9=z z&$ASKsi)u;fQo_-LBuH7cbjdm;G7Nk^iVFB8GSd0aHg&U?>3(KX^x8EdqCH2)b6$& zeh-KQdDi!URv~SFUZ+b!Ao}w<<8azZe-Ehobeu&bMwQ=;e_lzA?*U!y;rq`e{sFMn96-7OeYt|K|LE@&k-(PgHKc3HB@ivwfDN8ppR!zHRQa3uH*%fp z;rqwW0RD5qzlVP#SG#EbrT7#`>$9RuKq>A?mVYb+?0f;vDIb0&UYoyKb*TOox_#YA zGtqneH+brc7DNsbp(n}sxG%&|!IJ1LKh)^5bsNoTjS z$fkp2X?&CZQc&xBhwbEnC%mLzXKh_j3%u$}ye0lO$}Dtt^JP(K)}(?b16!Z#e&&%h zaC!@gl(WZ=r|4HXS{Iqi;dJp24RX{qIP=@Oi77`alDxW4R8_r%a>`8IQWQ=l=RBs5 z_P542Q?!a$Po9hHP3_{NU8Iwbc2OqzXxB%lfuQ~IXthXo)79QbyJ%fb;s9`~gTT0^b(73o4eF7j za}WMnXxyw29RK9AIW%sc7o$4Dd< z_{BxI@&T1kJfqVWtyJosCmfY{)};T&$D100{zaYM`aU}9pTNJQ)7i6eu?6atcw47m zJkwEQQJ=&+I=%87NA1t_yE?rt9&7MH@5c}xAVqUc4L?AsIkYhu_v&~ zPli;QoJ~WIXG04@H+0_r*@kZGH}nPPu%U1F8(OEw`31+Ll*6FWcF1n$0 z`U1b9b$Ytr&^kTWZ)i!Qp^wFP`Pi$yL!LWt=vuuxZ$}L+y?S5W&hSup~zoB)yk>AidJ=Je$onGrVv`$z14Xx8n{f5@*PJTm6 z8V$Y4G&FbHIMx5ZXy}~}-}`wD&EcEe?WPvw|MlVfHNRIMbO9TC>c!sht<$Mh-teu{ zc?w@nl;K;a5Bb0wzIA$yKYZ(S^;zEVt<#;)^@eYq?jH7rZ%L!E|APzlBIPCi33>k} zaoJHm7%f)b)p{eNyi4)GZqUrHveTC6OZUoq zEI`_z51Fu}DDSUdsW^`1 zqIQG0Uyj;&4+Z`eLsGlNpknR({c@{zX91TwpKQ{6Grw-_1kL;^`$<;GvbDU&#Yj5| zL9sxU{mrae%lif>m975XtDOyX{n`akQ@fFMYIhmSRW+qcB5Ka}IjW-VhZr-QDDRAA zf1Pw3CdrDn;m4JlG(FdgPCon-d~>HgiBx$Ab~lV!TeObGf55ojw$Z+#xhZ5YmHo19 zV^wqc1z5Y|3xXAG_do{yIZ3O8cu)ePri53~v2_WDGAl}G&JxRm~kEBkFCu@Y-^! zn1w$)_%G0i3R+H0ZiL{}o{p-TgUWN%s#F|;U58hAoalZ_>ydWN4>9GgdsJVX-k~P6 z3`Dp|85vTH>c73Q7D%llOfIgoyN@^W9Pv-|`gW^(^Ys&IhXekJUf+0iwQJ~){wI2U3s$m) zQSJ%)Wzk9&PAP|0jBVgO-aMw4}Yx`6qh0RZG<@ygi~?+?%6H z251B1S2sT06xD-U$$+)rn88g)Rn3oWa?}KucK63mw7V^r)?;^Pd<(nV7uL$_Ejp}> zxR=rHKK>at#%M}Rt`TD_RONoT#51{TBf)Fp9aco#b&rKKlQlbG!Y5Sa&Yx&V*X@Lq z&p7z5VOrn3(P8aQNc9aQSH=zL-8&)G7m_@K=S`{b{W~GmcaV&%Hlz>jgj8Qia&HeK zz#}^$l^aTw{%FZSy!$z=w7Q;;mh|Aenab(GWklR*RyYN3#Vw0CiS~^!oXefdl?8;Y zi#Q>C>1x#FcrYYRH5JmUA|Xw>3t{dv-c5ejM7jZBDuOn&ZQbx^8Mb^fX{u8C|1(xyuJzOuf-S|%$ zGyZP{en;bf1mpj+cX0fl+?q`9gn-+P|IgueOm|KbrN{s0jF+mY4HT%ye`Hd@B~H0d zIqqn0{Qub5!a65}+Km5GG5)W@$u4jF_ZCq8NiZ}1^Vppk|K$W;%_8)}|KzYA&dgHU z{cw(GJ82*J9Q|+)Yy1b1lQ;qyQp*t4e|5)yp5F7v|Fkv!?>w^}|BI~gf9Ldi{O@3m z|2wDG2-XG6*%tVjp-P`)(`Ho5Tc>ZS6AJ2D8s>k!kFqFt3 zeRpKXqN&h z$BMHrw_o~7rT4oCX&?yk;)0kq3%S07i#XcGarS4f{W|^z(l(lOd7H3cI1x@8+9#xX z_5+}k<7lc*78QV?+V2Bgv_JyH4>)iLUZ{_Db1phuhV$9$BkJ($`DpalH5|^pQ&Q&9 zh<(-!=Zu=+T&@d~N29N=(k^iXa%|S3hAc~!zI4n=fbGrLLxmW{PmP@ zDONdZE1rZpw*9gNx$x28RO~`bIv7s@9osTF>98lg=s_LZo`%A(FY+}mYj6toYQL08 zq;pG{-n0EmlWr~PJ=)(b>F&`tg??a7O)9EBVR@Z`@~ZvvItArPR2}>aZg!dSGMXhO zDmD#jwPnna#KGSW4XI&ll*XEHKWVbYR%7V6X^axDF^Z>#)XR7ipi}WTO{suN{8t~0 z2e85T>r`A$HS*b~Q?Y*Fx$1G$`E#rY0On+u=QPZ<5 zqSR?zMI0$y_>~#!dHLn@{Z#~`h6{~+Ygnn`kj zN$UGjH0&4;_7>R1ki2Q zavz2@qwhVc6+z2M_Mbe&>3(*dqbVxLqEqLvd<|>n!Il!{PWD=^Rpbf)YI_hmqvSiZdF+Kx#tDE+H1L+!*{?T z?j$t$Qm^Ii59>ZB;N&%4%RT5Zr(#s{D6i!n_u#Ct8gjhXa=pP@E8DbO3J$Lgu~dCG zyjcxaI0;vx9TtfI*`M}ZUat0za&hN+&G3Ds4*;5ZN^r@=UNijQ#2;HN$VF83deM z<2A#usNrrk!>#ycwp?g8#X|=2CO2;NF0=EHRx^B#JI>{vy10k5n&A|$8FCF$4Y|Q< zhU3nIb5rqZ>3Z1hp%hJM$KA=M0zcgVAd8j2VixU^B=CxHVGH5M=dUVq&6!e zMhzEPw94x28mw-?Y!)HWvg&uYgt_AH#aq6)NqkUVc}BEtSx3hH2KB83Nu`OI>yBj`&f6`2{bN%aI)=SkOy?qxO{G=zS$PW|joU9xuUh7fEpZ z6%w3qrvxWHBEd;7O0e()2~Pe&f>S#Ghb5dkOoBzzC0Klf1g9;Q;PmAZoN>1VXKs?< z?2jZkCkI;^b9OtonFQzcl3>Xs2`)TTf=iBL(0k5>5*&8D1at3}VBS*_9KJ<@BfgYi z{$COtnU5`_IlULOl;Egt5*)p!1jkH};MiFb9Cti}zJt$`V8~?>?7doop?69!>tnd?-VhVey4_BCvcI-*>CY;!JT%c08hVDf-|0z;LOh?IICncGo0O5 zf^)`5aPC|Q&O1kf^RJfRg8L;{@{$A>ek#F5e@k$20gjW+>32z636}PkVA*sDEB*FE!N^rxo60F=R z!K%L{xUu+6a#_8r1Zze~aMMf)Zaz+eTP~Df?OF+LeMW-YK9=D2&|A#DuDJwvjFjNc z=@Q&^gamh=FTp)`OK|V&65RK_1oxM|&Ft%kO7P%#2_Bjw!G@D1*m#iykE~%(wc$XU6{ZuF zYJt>Y*wK$)LfkRC+{WP8vn6%h{z7v6A_-2oQi2ojl;EV7Bv|;F1SdNmFyAT7BsjH~ z1dGN>uy}z4r(Gz)>DNne#s&$_d|iUGzLwx@^&z>O(@27IFJ8sed9j-roZm@+7pxY^ zmQ+jX!g&&0bgBdwUm(FHS4pt+Rtc7El;E;ClJD~8C3VH;5?uL*1Xnfqh$UQID#0~f zB)EQe32vyCVAa7A+<2@6tIv^O&D9Ks7jq;EeTNuE)1>7INXNyB>%uyC_HNHD= zL}^%!>%p9oJ+&3gaWZNAzRqo^+r05poW~`c>THp4rt=*r=8d1_{3+pVhcn*1@rOC_ zj~UK$nn-xW|HIy!fJae0{o~U!n`{C}KnM`7B%E@Ch{z#=D2jw^R)TJ}(o?_`Fg)!RJ+C z7oS&)1AJa9zUK2I;txJQCen^jc^gC>K5rD~^LdlFoX<~-K74*wT*v3<#56u{70dX% zT|C9-=f&%M-YGuk^Dc3c&$|&=miX@xnS6d#oWtkW#U*^+D|+(zEir=6`@}>(?-#TA z{H|EZ=l8`XK7S})=JUtm5T6f09_*Mt_6PW%WaRK1=_R&*k)l@2H&edNn?$>#g`) zLC@oJMSUorE9n#YoT1O=b7g%cpR4Gb_*_+gna|bq5BXeOKg#D!UB{;H8+&Hy75JR3 z*W+^yy)B<>>LEVY(rI(}jXi7YxAM7;zJSkl^(Xjzw!Vwc_4N1nTwniz&kgkCqm-|q zUJYlh4E0BK(BT9Uo^1Qu3yE62w;N*}6B`U0W%F&pXda#HZ-?nnoYyNNn#w+sU! z;jwtWR@&If03}96g0a4`ro}Ohw6TkU33k!lY;+ToYhol_o^|ym<+{R?3vu@uldsVA zP_C|0uKFrh*H~BQprZ};H?QLI2DGt^8K}?=v97r60_%z?uT`!_Syyw2{|)9fXmKlxDM{1Ei)uG}T zQf#!++PFVJ&S`KM2}37|=)O!4(vz%6Iozp@rc|^Vr3ewdH46yh8fiu_=HG@=gothd z|LEm($tljkDbB_z_`VhyNhI}g%Nad88(SDGf(V2t>)* zqQBMvJ*U)OjO%1_^L-cNd0K@!BKi~M zYL8X?C@m{S0=N|)%_;he(q)7=MXM8n6c@ds5&jy{C8Z+#N7x8s=`X?+%LDAz(bTe{ zy@|S86Ql-H>N!e{Lh81g@V6V=5hn>+sEJ|9;9(sR&;07cR7!$f2s{~17E~iu3=&i^!dMf^=h-e|DdtL;t^kgeSf6@C1#;Mhm z;xg$kLYEWxlGbS_&|ifA_7WYXqVFR$nS*<$?m|+FkX0h|zCnbd!$e5=5z=LZoGwCL zV1%B`N9dV*gkC_7&?EH-&55{M!LPQuwyN#pt7nw;|PSM{4Ml1(xGJhXRexNA2fdTZ1vsC`hS%f|& z7u`)+>5ENK`VL=&{-Pfej8k7wis|StLYEWxl45*KpuY(JrELctrJ@-~P39O+sR1Ol zD4`@q`)HzYBQXr;@mPkaGP+nSOY)$K6Ezkzw_M?|;#G(%hpuY(HMRyS;rx^AQ zU0%{3*iR_c9jWMK`um{B1Ci#Qj@t$kuM)c=@r7ri-1NxCn8Ekk5Y;dQF?(h zdWtSN#Vk0***KLx14^d92>-DR&7MaNzC1>V_H;?9(bSwq(<@@5R|@<+Pk;0x(P(65n&lRt=Di{# z@oBM@NNKlwh`s<(%F}pd^8!t~L+~S;{{Mhe<$YDVa*VR4(ah8B;a=nqR6l* z3dPmPEb7^)a~VY)P*i44(BGoWU2KX0NDcf5_h(57I3Qj+KyECImo#O2_M}Z2KAzIJcZMWwTO*<4xh09>}&KbT7-t( z$UE?YxLBakW3};`!;1T@;vO|qBK8zg`K#fm9rA=$`7&XI6V6Z2b^s8558}Lvgcd3_ z&$5Q5RqiZ|D-y9#UMne93vfycq?;f;Q=Eg$t%+LAbGel##gQk)%#-Jzr;C-RtRqiZ zGtYJYd2*~g>5e?sGKDDxs~H(X=-!(wu1DX)vyM4ooCx(mfMY{+5OzpIUqa+Q(4~mq+CEgnH=fIF-w@ zV{o6U$EYko$V29c+aAE8TICx=Q`}D%i7aFo{yWg48C@jKZJnUKaU&>h6pzCw-N}q} z6p5)IT~`^T<3tPO4V9WNG4u~ucHS;%%sLv>E;UzN0x7MdL1rm<%^eO% z05GqOgImhHgzyJI+zi-E5rjlj8JoM_nf(@#>Zh8-J$U%18rbXW4MFs)SARa5z7muf zP+Z(HXagCn8z1VapuPaqZo4c*9oQ~a#X%U?X_u;|;`@PwEwNBB)FQVT-UQv#wPB!T zOsA@JIaK;52z*sqzm28RE0K~a_0wQyOg@IVt6WW1**hnRfci;{9*HfLYA3x)I_t1Y zXwi)r%4Uh`prLt-pt+6ICeK^q1C%ut+6{v5@snN3pGbvhW@H^%eMR%|WYmBsN#NXU zjVxUdspL$hYf-vynuo&WVX>z#jDg2|L1kD+R*9v>?9v?Lsm1Rml=TdLQrz80g%r*Z zx1^eEiSwQ%=00Oqh1fW%;;ltbP;xD(XzQ?QamGS?5ElZ|$KS=*;3&GjX34pcSTIR>h(24| z=SM7;$RzTl64O8JJhD8Jyihy?(M84^Rt4K4HSjHLn!!t!^k&UK>g|!{7c8SP%NCL# z$IikM6pE%)#sC{iHFwOBG5#B|JAkeFyrF%BJ4Z(!*c#(S&adz>4*qlwuVUm}k03K& zV$nV89Ddm+)RW9<9$6QNlyD^wkhg`}J1|L?=of}B28O&7fvm4{;Ii6@w9s@X;6hP8 za_3|b0S!eSJ9e471Sg#g-6*%%# z^&@4OkLYKGPXa}**iBHVb#Kh&+84;UQQd?L8l^1|{V`uJ5@8_9;fZ?IMS|Y3EfRMF zK%+@kN73?a0z3@>jr>^`Gaz>skEl}J$W=@IOkPJ(+WncllBzoj%+26g`GEzRHVHyy zT_VaY6iXq^GF;W{pSDm;!NqpE$WNIow&KD%YPM^cw@kSv8c12axV$`Rrt>JH4)o=(U-J`o@n)`%4 zCuuPl{b%j$cAK-eojm|tG3{(GP$jjqKY*t}!)|BjMt??^Ci?BOy3r9x$z`%a(FS+q zB4VR>`p$Fc{j^A}%@zl_?

n1N2w}>^{ZZM69#(@Ps8kPlcZK*j``{d1qCNMfgHQ z2EfgJ)^REdADbvc15nmLotEi}L_MJSi<$j-1ao~NQx7f>z2MSCVm0Wvk0{V-K*^^T zc>}eB0=<2B0+2KYsg?$+Wv=@(nOex%cC$us7wc*Yq3cOs=8-i@Z!%ZRc0ej0sN~`@ zN-q;W1{s{~DR-qKOV$mpJ~`_~{VX5ZsHs~ANUDU>+9zlKNc$HHreg%!1@ve^jDSztbzv1y7E&g_=h~(WlbfLdoD6QYbUcLfz~T>Sl*fH|zX1wO6P{A7BBb zM4|qm_o@pjjTc{Hx6n&D*EtCucB84*3EYuW-P*WU2P0@+9Ph08nA!2TpDAXx>L%iU?4Yp9V z7eOfcjFnp`8EZreWu{rEI~+pY;SlN$onJopYU&#>&n;1?zvwmeg4UyLp}Lb$^yw$J zP%@y26v|AqPJ@ht0Xk zT|74_5}5!T#GZ|;nfgLxS0^j8^q?})%$i&BZP#cplM~I5GVIUAZP#qzc-U8GEA#Zy zG^^E>iMu*?UWSRmX5{vt7#sn{oEXd&uT+JS`|w0>InAjs_j{=df%v|?Kh6E*eLE)| z-Ubl@u^k^{+mhF+IU}!-tA|--#ksI*P6*dLt0>D$fH}=@J-91$SXR(;d{TO)3|y`; zm7WefPY56KnGmj}3E}Q;G$GsxI-U@&XIl(;qY~zrPwK=|HN$#6+h?Zbyraunuh$PR z0zWy2R3?az%L$^Ps66);RNgvJXtmtCoq$bx8FlvejC=O?tl#V}pWNUeDwp*vW`3t2 zkKfGi4H&pVx8e-k0~pWD5B4%*Hy+fqCapdFRn8vd;Q4t)aTF8uoJVlY_Nl1a=L6F| zQ-Ejtyys(|5B2yb*Na4YzGTliQ`G0&%Z zs<%a`=J`UeqMGMRJ$0#|DSp{}l>e39P;F#i>8armBrkq4|Barky4bfcxc5dwY1QBA z8R3!ODox7Yt*b}H{|s|30-V}w_!trwA;BLF>i{%=h-N3CWYch3cPjw5yD^47#odsP zaf^_HZ?~$+#yA$&+!(9L#@GYbZ0u^Pu{A^9oizfUjeW|;*uroc`)iPLdrUN_Gm*wF zZBTn;WA~!kCK~O+TS4e!>_p>ljU6=D*d?{a(uT{}DMqSlt5oAGT9YVlQLXuv{=IUl zQ6(G(j_tQp(9PWqRHHOQU2My$X#A}&R5UWe6D(e8Pf^K8mLD~oLChN($>G%?WarR& zIGkgd{z{fepBL_P}rgVm0xMpX_6g0ZoJ@dJyGh6^X zJHt7~I&^;O=-0wP&-^r`DiYg4$DYuJJ%PKmy;PkxM*HwQAmzyBTZ-T*WM_dt8@b~D+gk! z!*(yDba)hG@E^AC1IDjc7qQE}z@AOmc8S;p8s|)g2i1Y5={^IJP1lc2S0vJUnKPLI zhIb}2$Z*YMh8ZO;AU6avIg{a*ogDb4mh`T?(Uiqcns<}4q*1^*O0KgyUsv! zcefl+_ULbrkRGje(8G<=_BtybiO}+YmoKfUBClsrmsfcg?KY54rg!mv16Q+{f;_ML zG>eO`GW*PI*=N?lH8+!NZYFlKm|*HQ8FYQDEHbrX0MA-k;G>m$9V5pOnt*04HONG2PrcO0EUBlSg%V6vT??VD1FX&t zKMEYx)5UR>QK=;5C-kv7D#~AFWXqn1v>$#Cy!)|j)F%8C>`)6F{OynjjA@4%;ure# zlqNJhxs*3J<}=G@+X7nAhMG?j-y~=w8ybJ;*O3Qhtav5Unr_IZh_C6s%xk)e`JxEjuE+n}@;furh$4e(Z%4_pZc8_jh1=NIeO(i z+2I_}-B0s&*YfTw8Lk%gHiRqyvA<>K17o+a+GL3X-&l4fOQ6eW)VrN0hiz?eEzoK?i?;UUh&(AE-RT;nsq{cI}h6)<3B{lv;D6750Fx9Yzc zv@J>PS$^S(WU+I=8ptbaq&nj7Mljd;gf#0fqY4jgv#H7{fzsi=$VoK}Z$!c#+E!ab z+YCUdn&E>;n3J_aQI2}$l<%EB!#m(AFQ@HnebSP#0=|4Q9H~zX_qdgpFGo^!Dm|8m z?7dk{gZlZXsX{=`=Tm@WHI)yn1Ct@Fq4dCw$f<0S%SsQVgzJHr_sCs}1n-ek)lo6v znkG~U@HC;gv28Ngm>sr&xYm(XB~XpJS0hF`SR}NHICT>>=s&3u5vrb48+wj`73sMf zE7|)1aP4FTn5G7bsl0)i?u>3&$)Llb7S-HwJ6uxI=3Br;iw2fl(MyPG(VJV9@Zny zX`sy9IA0KR>&Psrm^iDZV!XYH~2|0e?uxyVZ71YGUr=?hvJ-PiCWkP$2A}( zCD!0eyf{HMpmMFls=*mb@M2s7bqAClyYmFLccv$3EwES3(ULAaDzwGoF!Is+t(h~D zwxY_;9Z#7>DPb|VxD8K@fsxxf<_hPIr_8x&dDF3r!a6eNo!Ne;tH9SBmj9#uPB+Sb8%|8@({es z0DXnrON-%7z(`G~W?7t>>)w8*scd5<_W3u)`8wx0nXxM2SwOL3@|>H5GMAMJKL<=n zdifG~r(O!aea7^Fi1-B?3*N`zF-sgAmZ)VFp>bCLOg4>%NbzpPy65qSPx$qvLh%b! zC)(Onmm(!!R-7T8)LXX$vX_lC@1RmI26U7SqdRf%Hj`q%yqdE#Ih&QcVlRC#b6U*`__`Bxq@^ z!VHc-kRN5O3h+LOA=`C=Q+#~6Phu4ZG}D-sYYLJJMw8krZJ2t-#iIOBd6%Bqi(bH7 zhJ8!{DlhXh+S58$D9z~eTrOH5<4YJvGrznToxxo3BqXW~3$UIVB zak9GS^$K@Get+M+6&UHeT3(LA{EJ~ zMIw7PK*~PBq{sDAp`}j3$Mu#}LSl^Ui7Xo!8QSKgc}hM{NQ~_xXzm~u{a54%b;5pw~p)6W6KWw%E^W^kJsgTt#o}#=YjGkJtR_ z^qQ{7Sa=-%_1iV5#BwnL*X%`qW@QD~_! zvp2o_jVZY7gUSnXCv{6@x`?||kr<1N>^>DmPxw!+(g{@*86l+?swBK_QUnhEZn6~^ z(@jE3H&jXdH}pffu~VA%mY;Du zf(skB4=uCU#y#7|xb+m{_D4oGZbLBu#vQ`_MtwmYhid4CZbLWnG4!qA=5Oe=!1x-v ziQo?5A3osZQh#6_nT_0rJ{N}Gj~bR_XnjPnhHl_7^dc-vfA44LCg8$`?n`kSY(sbS zG4#cXp}Qg@8@iLY*3*hRxs7|Nk8wwUgTHYX0OM=iOaBX7@uhC#VvB$HdDO5Z<9-jk zGM$LG;!8Zn9jD_%XB~XziB+yOje9js6l~-6@G)*r#kj4Ik&Szm80RtWRc_<<_Azb` zaPT+o6kvRf+xx%6xJt|I?KW;77b;v!|QGhJk|xYOezlie;d#m7aOfP=q_^ajS)MW+0BxJU-HZ5^3Y z+%7T|E^<3+Sdxou0KOO(nM5w~Ai2n;NnRI`pQ)2BvdQ5hn;b5(DZn2%a=FMNaJ$CO zMLvcs>>~Xso9!Y+J}xp>agjfek$aK(cq-tY#m{%U$O0c1sWPfK7r7J|Ul&>M-{B%{ zp>6BPT;O(*g>aG4s9{MiazF6JxX3(mk-g+11*N<$B0ouw8UlN`%{Frz|X|{z=cgb zkUYaS@v}ZAeois*ab#o@ZxIi9OuWTy;;lX=E_*|9CcXd|UlVWruP|{gnbLPmCx&&6{d7x~=nB47Bp$T4v6 zpKewgU5tx-@!!#l+yQM{N9Gr97x@w{(it@@$wkHjUyO@%l7o$Arjyab>!| zvxTkT(!Ly4m3OVfbzhPr^Cb#V)tC03XYM2_^)c11GVaGz-j_DCJPHY69hti;=21`x z>p+-=Jcb6P`|K=`np`eHoi-_CqY#C5uJuWDqgf?F&4|KKMBu52l6Npx~cYjSA zK@X^&uS?M)2U79{cVmAO`flrI?u;>VTWRLFo3l)zQ+fq-~^GsI+_%9^cgd5k=&Zo7z9}+tl6@c?S7eA$_de zznwXLI!5Ki;%7*}UGR8fLsp@EQJD+aD#~uj%td;Mn+BSLvs7&;9i>|bvf+&x;HVm| z`Rct;(FCAMQqgMQ6%|FhVT77Me-ZlgZbRx>NoZZM8E77`j@>M;09@iWq`N@yIDYha zP>XFxN)6$)Ayjy zak~tkKw#xis1KKtWG*|-lG$fd(Y^F~Z8)D>$cXtTW3i^WdVfrHW>9!rvW zwYveiS9)_g!`X7qD1GWY@)oG$JkYb~u^$22Rw9GXZ$Z%<+4dyb21m9{8*fIo{S@-a z$hIfY_gIHBvTf>O>`^o$+h!m=Q?xxw0JQ-%54gPr?k!|C7s+oEAT6rAiuo}$t>O%YYQfm_gc_iXx z78}|22~eK`wabZ-rL?$0<~1YR#tmPXji%m zNfRAqA%7pQw)9QK^Ii|$w<^4S^!W~mma0UfsWn6o0x?_McR9MXK5y(2TFPseL1BH` z4MmWt*Sb=Y<{~MtnIUE?L(3vF%jz1*FeQhW4S{wu3U-+$r$1`MF9Vim3pqoXx{D zC43x+o4HYELZYdRT`J0hG@}Q)ielo+4$T(Y=c+-xzIhjj0-Zg|^Re%fpsWQ-IbxaZ zB}0&6e5enD`Z6!yoOP%G8>Olk0n0j#V#Svo4-z(mJHD*T21h{Wj4!L`lj6&!-%^Y| zI{+c|IT9(UPrpj6#vp%#yUNvMmAzx#`=GuaW8EuV6m<^A{J=2T9m#l;hm5Tr^zYB zm!&eS!-~x6U)m`U-$kE4BKKTw~07oB}N#w~Trlspx)t2Rv`M`dN_;oAtl%~4} z!$MBkh#d_!upMs|-HvN#G}stSX&oF5wh0KxXS~s1djr#zUxLVe(wU2*!M^4MP&C*d z9DsNO{VIZ2Sg3`f)Vap$=gXL$-9Dv%WPi>xI4(3q$_ZoeSpX!ccx-30}>FP%;|q!{B-Yt~j>p zY+THy3yQ7!s-rxL2K%XUosQrHCrn64gI8IH3<9fUrXa9YRT2b&ZAOs%!T4VB68)b3WSKk8du&?ytA6kjb>fj0cdIemA8ju_)sS7@%=5sxS zl77(LvKNPaJq$+wS%aEsbM`iK8fmSLOZmMJ(ifh&t&an}8<`@wp=3z-|O~RgTg<64_#r16gE@SK^Ds zL@UNCeOReTGzFSpvNU77=8#GHM97`vRQ?iF|4(z2LkY;k5uPXk1Z^T1Ke0)SkA;;)}=sBX4LI77J z#Z)Ba)M^h>b^uqPWQ@Ju`a(+ci%EYMz?Il~1^o)pk4qF(25_xD-V_u8TuHL(jlGf~ zXsa!mnP$n(IDqS|VE$W)LdgKGGjFnm+DAfd@DU0@TWz7tGz)dc0bI*B!SYmBPxEq^ zR0eSU{$^7sud;i9Me`C_$N;XxBX+$4OHr>vDleC~Q7XscZ>GtKon;{dKNfcfnu3MB)$-gT=j z)L;_o7aySzwAB{MOtVmD9Kf|#Goh_0Q79R}_1oKQq2`fLcO#!$QwZ8>3uUHRs51`W z`W={WEm0^Lz%_TWE!0jDs>V59p%Apy7RpSsP-h&#bqbijU!qVlfa|&`wooTXs7*dX zA!w^Dl$mCs&NzT;rRGBWxkRC40M|0pY@ur352139&uu;gZMB6m(=5~(2XK7^%**AL z)G^5bt~X4#h3Za19rO_jL0fI1%rpyiW&vC;JXdI)Akh+W=RGpq2~9-oiN`&V1(tSDA@W09R#nw*$EP-#Q!wGxNcxGU8JJ*Hggph_6mD5Wv-% zS*Ua0WfawOR&g_d9>CDe6OP&9GG0ZcZ+WF`qpzOIyJ=23hF?tB0tH7&s6nw|#d+>dKBMk{@Al=R9`GuD`TodP`T)r`@qsF7o|uD=Qk zTs)gw&ziQvvl2U1$^PM4op(tbo;7i{H33xSYzWV4DKxhkYHJ-?6oXZnyHN~Q#k&46 zSjmzHAUwxlZH_|y=4}*%^%~&(=WT_+nAVDq(7eX*(|JPs(Z?RAki(3@N>6}t4&vI3 z!K^K-fM@-iF<2G-J7cg)6CC0RwH1DqIP&EB7*&(PuU4C5=~hvYfB02J{RqG6 zuYQiPO4IG6-YA4(tSb2^#%gDjTKrU-Vyr6C_{UgP8Xm=19SW|}WchSkn@z=2jMXB* z$z0*Dk)WGQjaV}V}_}s6khddu=BZ7@(-`7 z7zN=~{f$X6R25s;F;x9K#?K&vU&lx>RQ0*0eU=Jpp2JCOilM6T_l=>NPqv;!^b|j} ziOOdY!8v#;S$#cSQSj8>pkk|UK*F~AZlKxfw*$&n-;0EQprO^Ru}JD;^?LJ6E1SVn zOX1oKo=PK&-DRF@TKRjFz*aVcrz%$F;Hd{8l{9f1HZj-tB-MoCrgjH^IiM(-@{gOU zm=$qTZL=ypB1KD8C}p(NvVAN$I>qIv2OtMZo#Zcvf1p%_I|8Np%R%8$6-o||sw_%T zc+^KwvVVtr02sdxSHy<471{(?Z;1%ZSLX>lo((jOQxixwjujrYD*!xC7+`qk2^1bx zF@hZ))xS9ufSGI#-0gNCRZ@7=I{@dF$~{#t0#kU@Cje%jExo|uvo`?EKKlvK?6dWO zmOiWYtuj2ST!AbUCulvq-~wxQ$m>4*@NE}8vMwP!>T=|n>*M&7Q7m_N*|NJEglq2Z zJmFDg_jVcZtXnfYs^a(*9#v7L9Uj$Rl`$|gdzNb;pLK9})GfeKMb*XWEDDeM6;S@J zQ(>X)I)!33>1uvEr>@i)l@WUi*o{6~c?^75D>bB6#^IW^;t7u`wQ>>gtQ9jns-l%* z!=oyyvcseLtLinBV5+JRLR$xiNBssks;6rzW`{@h=XmiVo1>z9J3K0BKU@h^x3X>2 z87_rK9RQra9cBV!HsL~X8$H*m-rll<`FLyrLC>|J@uyvO7}RuH+NP|@h(JV)0tsV%Ylz|#KWMH_}(z6&mgZEGp?R98-+nN zP%c$3Tmy-AgjH`(C=9CN0CpHue{kc+tQw6XpFRnk zztIi>V;ik0DgQ03%gftPQoh=FMC=5xKX^56kCh*q8g6)>sbMqnsiI*!@~OXuQ<2wC z!xZ_nCvdFcaY*=Rm?EDl8nz>!`fGSO*hmfMzJ#h-2M0e@hA#?!x(&qsYWxNmQ;mv? ziddbF==8CKzC`3L_8Go@HuY5rNcKo8_~~5$@bF~@KUFGa2S4?%)OE;fR!ZrVDEO)K zfglGzrCQFQfs2Blu0~F(VOU$@7`T>M1J^#FshZ(NK%0}TLQ$Ri+~kX$Zes>NrM*$7 z7yPsU4seQZsm(ngInj%|U){1}l-U?>Y8b&EO_Lxf$$0!vCJ5+NF308|roJW+Tn# zJQuTro8AU=&Qe_a2RD`0I3IYnh8f&cu?7V<{RATTTcb3x`dPycZpzlU5mY|bpx~zD zu9>9!MD59kgdUt(wLd2|J&@|+vDD7fiU zDA(Gz)dCx_s0cxnvb9kW+Wj8JCs*M$9)t!Z=GI|_2K6oG9lIEx4O=t7WjB8EvH815 zgxurtah8{gO^m5F=(i5~_ zvF*yylHNE_>!9GK&iy+S z+|=pjf46<-LGU$)-T!F&&I>jl?{0%bz%@lzrH(25G3V43=9p5<_MO(iQ(K9DWHx5k z-SYSYU4(Yu$Mdl+jg4$BjVoJnD7fhmF!XQmbAXYWP|e~S+*DDq72MRH@0K`U=RAgj zn|=TkD<;o5ZKL3(!IdTJYg|2c{ovY5AcOzGwlJ)08UcXLQ0E%2p6T`rl)Az;CVLEyf1o-vgFuM&O*UWqul@> zWW$Nt9o&?**G;!6czYcOH^qyy*tHFDmJ{!XY>KT&S;0+d6;g}#2SJo-S|}c)M?P=c zv}w7ZrCVYIF?}B>xraavZu%v``6IAaa8qJ+m+e`+>!bk~b;70`heuJ*xLEXq?&%)e z6Wo+GS|SDsdAfOID#1-BAtS#<{N+A$26M%9h+!QR-1IPnunr1t>U1&+ZhAlR`}^1) zV5IMAdG(+Q>&QG}1{Eahg;E_DXK+)pyB6x<#LD2N*8!w#d*k4y5htM?+?4Ez;HI+} z8Cv3`v4fjFPSD&APMi#Gy4wMw;HFA*KycHaQ9qt~CeU!|oqE=Mz-$h7a8qgkW^hw1 zM&UyI9J0JS?jma)E}{l8jk}0{5Yx_i0$=#>@s1EgVefDUG4=5dC5Y)FWON2G-GpoQ zmOnm*w|Ih>js)5aVygHNf|x3PgdnDFKiY?^{(huASd1T8K}?JFBMM^rzu-r~*x&n6 zFjkBo<$VJaTL;B4ZG`I7hM`;o55+O<0#r#JH6D2GV7(qiaZIyf@TksLcs*)^!=uzV zrg4w*k7IftxJCUuY6V1Lk8;N`C67|~2&!>Rw<9BaP(^VBE|jbI3B@s09EIYTx;^D% zaPaq(QmbrF2`N2}9mlj-SD|>y{|l~?cp9#fSe&cmwu82Q*aCYjC&8buyNgSOufccs;WLsJ}6 zx1sldo4=ud2F4s(R72ZwO#j)2R{8{rW2zXM;+WQasANNjfG@_-c#`OvHT1tyXixYV zIsz_iXm=b_uc6gAri+k~4c$rn;c3Mb$5b&c#W8gocM~}H8~0OSe2r_zG5u#7S82r* z$5b&c#W77=U9xf80AGx8FYy?+9kvC(;b+{T;KIgr$1(L9SB+yj4H?8KE zZ~Tng4P4l`?l`7iAw)Nu#33kn0j4Ajbqvu8QDc9iz*%$p*W_Bi%=X>w~Iu;!QVwz0psf;b{x}x zwu{il6zkwPrizPD9MiW@!;)O&6!67#?vuzx#*vGpUF~&|O%4}P#6ON{e{iei z=OPUrHeJLW$JFa0Y8=zf$jB}-U)1)v2*oi~T!iA7x?N-_IQY9r5iq_kV#hK4XS;|2 zZCeM&F;!fI;+Sql4NG#7uYoVdMex2aUOgojIj5i3MV@uIh#JQ_<&AyJMMp&8)^Uy$~7M z%v(e&kC`c!sbXe|W$HF_UvTg@^9*2o&1}aq{YRTQS1~iiGF5s4ieR?on9AOFsY6>R@g&XxlnCmZ{<*6w7oq zYFLts>;t|S7uicL@-w-}HAB2E^1Q=E)L5o*7x9l}x*pu-`nibqnCT+!Sf*YVQDd2A zA|t!V=c22}MJSf3;vy8w)a@b{fP=q_3$cjErSU8{QnTOv(DL zXHb5zO!EpTmT9T=RxH!rxc0^}B`Wo40%DoEyumk?DPFa*4vJ;UkpfHr#WJO+2G((g zkqz>kkqtP6sq>Ycnh0#LP>hGxnqjvELYU4K&Udd7##9NKfS{$;)^KE_zz3Zv8^tQ6 zP5=FIVa6&|{J<|(sTCmru}bNQs(-A~iO{E}ZVQl)6zjnd97%RuHK4J*$%<9#ZOm${ z(!rJmr|C;Z;K`WMb}3e=%UUIcq_`Bktj0?!v<`|@dir`)2VM$FIvaes$rSU9e>3ph zWbB}%wgx#UX@A<`xe>LKH}dhVDIwPNjnmbfU1fpDCsDmN>b5%z$+@6B?e(T&bV`+ znb)tiG(+K9@zlTDuL)Y^EMSh)H_}{>>&+N*S{0m8Ncnx<+a}98~5*(y~`Xi-9zr&w* zSJPDBUf&Nzzn%nh^niFE~PS@IK&^+ zYGubricr9TG~P3kDL5e^sgil`Ik=X&$;Oeca1_+I&Sd<6T>$R}XajhP-me#Jimmm8 z-0ewHJAzzh4`8{A#PAIXS~o-s$xhYJ-A;ih)&p=s3IJ((A(UApJ^&z%0A)*={`oq+NH zY#4c>oq%ef_|^%is;7rKjds)^OD{(rkQ@sG8qysoMD86nu0MJAzbbk%K6$l}IL(7JJktdK#&`smsWt z%;Kr-fTZ>OW5 zBR`V;TxW9E=r%NHeAl!hP}G7PU0|WeF9RsGI0gDD_1e^GBy<+DS%AK~P@E)GOhpxn zPYL>@8+vJTKwoh~M-%jr8`_tkzqp}~WB^J{CNAEk4X+ZWeC_UWQ^o@k<3zj8-TB-9ykBHk4I4`h#aE z!;)%1t+Y`)k?KReY3ihRP$m!esgpQhXS4%IXNw!FBg4R7Up2I}^Tj8i8A#+vhk+PK z<2uqqkp}aQRIUcoI^?CzV#e|y)ehWNRRKkxkE$hUDSaNM0)MPR$@Q|nbx4sN?ED-c z{q8D;R{8sh&{&^*^v7m0sh0&sv70E{O-i-Gr#SR_ zq4=;V2zJ>7>_LTM2SGoyp)A|DVPITz2g>M6FJ@GpSJ(ozyvuGIJhr8e#g;h?$V#(5{iSn|{vejA=`m$q_2QJE9OMBUt_!j$l39BUlfeMzB;G zkp8+!>HfIKk0nx%@9r2H-;ChP+%YVE+P`DiB!+C~8`hKxTQKuns#E_`BzD4X+)oTJ z`-ytU--zb71I;F#55TF?01Pq#Hvmw9C=C>nEz-It#Ccw2OKs=M6y-k3T zCSW}PAJGhWv@)_b-O~WQZMXx};om)t1jfI6S_F)5_cWx0?rFGQL7jLH13;O0 zU+3Y!H4RV!RhnpaSa=#F9i+zh*?AzR8 zPjQPq8DhV%%xa;UmOWiJW{Qn4&2fT;PQdG}Bl~u}RBrNe>r&HlL{^GwWU!4Ol)hnrh``um2{d%%GOOA0L zv%fO>n9&okoq~W_jH@UZzmXOk{jLt z(Ts9Q??V+sZu}OiD9>>8)kA3>{4gYzQ&pY^(_}XF1~XdyWFmOghak!Xv&Ew7AV{D| z@~x10U}ww)(;ADqo2^-KV{2CY1c_SlR;wslz>z{eD+MnU2Z^GUO2LYFAxMgVxYrX! zZz-O0gRWf5U!asu|n$patvK&Eb#X{-T?73&AFvIDsI#ptK;TIw^wb1 zSM5c9@+z{h5qpPx$KzjrfQI}_(#$|=rkJ#~I8Unw%mHXoQXfXj<8$3XLOv%+#vp~N z`FWpid!G@j0qao)%MTv`6X}PIw*L?O@U3m9?T33%lCK~B41~WQ)&zH7KMVok>xU5_ zO7g>1!2g5&unTNp`Qdz_bY5PM%5~cs=KsOb9I~I(ONAbD0F1*%@?7Csd&hG7>}f)_ z5O2r37O0}i*1UmMhzjbhGn-SP=s^olFN4Ifki&N}I|Dn>-47lzoz|@S@tPG4PmO}0 z|JA1F1*bwWgvR4C(=9G0^a8p|s-r@^@^t~h2N)O}?*}>_2++`%{fX$f9V?<+QEZ2+ zaeYvvgoi`VB)4n{ZzH8HvR+-PRPOhHT8A;T)CHj`D9bvGf>Moh15Uu|#7s@iQ&6g{ zR&dIs@g}qfY&0I?WXkL@OMW-22J}uz( zr}}NyJBR0?esrghPY)R;0m=^;wgXCc3Hh|3yo{jqaN%1(tvdu~ox%8=rF=KOo!D;I zOD`3#+<^dzbhT5jl3#U((2mKAl<*A@rx^hGhd`2a4R}{d=pJ4I=+6KkwuKI4=wAF; zhjAn&A=J+a=#i8VYUczzl9Zr!`A-I2qvBJ+psPE7G$|px8^v19NUnuvL!#^#u@?RX zP`m^lQtJAmUQhLaKthTZdd?wC_HK$c`4^7hUIH%_gl$E9U)9UNxo;%r-jB-4#$dYf z41#`ZLwQz56G)?C0-23p%0)Vcw48Z=mO^mwdysP0MH!C9#W^c+PEahN*Kw3%vmdR8fwpq9`}d$K53#*Q7WSTIG*=GIlk5 zK_Gru6DCJFfykFNQFnUop{)|PeC)`eh362NKeOreI>k-(jhLb_bAg3C|PH^)R|Ii z!$^`{s`C@63&bRdUL*=3H?K+u40-^oPOAb&W7U=cBU7EG0xqN!j(IP(#ARY)U`cLDo!&pmkR13_u|SZpOC6? zPj^J(%7#~?8g@^oVGk?!bo&5x^mH?Yh62;z@#>iHSxWlS9tEqt)pw ztMF6A4Ad~YtWhSs0sQzW;>SqHr-(`yTGptmK2|)-D5K@?T%l>rh(%>1b)lGqtIoJ; zTD#P}q6>ViKV4*&(zFHQW+d?qww` zbUo&~N+wbM%Ved%&>RG{eEQ(>dMY#1DCha&vJ3D&p2qsLpHJZcw^{8+#ORKdw^wXN zIi0i6;{^0)fzG)f*J;VahKGlP)_Wx@CtKO|z*P zJA;$b9=jM7L&_8C9Av%*nIDrK=kL3q8S}`d&M&7WI=^n%2_n0?q*u|^(Jq#({kyh; zu26h%9|*?S1oX+?flRO>&;n^h*mxwcjc6A7&@2lyl{D|`^)Cd?b2iP47chttpQI6b z3o0pc0>f%_*Gi-gfogR72e8eD{vyZdk`NOZOMlU?D1Zhb;)50jKRuR>g{$Y0X^AMe zOOBM|H)3zjeb4|Emi>6(Cu9m0;?Fv=Hv}4on}M1t5Plkz%ZX&TgCy(GfDsOXg!B;J z50Z&Qa+#B4WuQ@bBuGe?;S(U~i$vZDG+XP)dN)CCiVx+b3T2Q};M5qlBnn%)yv`V}mr~-oKPIBTt(hVXj_|tmyQz$ap!w4Pb zSk@+$v$ZojB#{js66^jXGY#~ixGb)l?>q-l=40meDyo~L=|VJ4 zb!J}VROgA})tUWL3F?e%bB5?4no;YSU1aGq-g@@!U~RQ|261_!-rRb*+6aRtN8RQ+i6ecK1+tbNCf&AjUHne{vr{I#BtzD z{Q?;u*NGs%!hC$$8@+uHOAq19mlL!G0B8jl(?5=aQC8wEE3w8(yl5uSS?|9F{+Nwx z*_)Fn11n#SnvW2ZD9sX#5F~=OT5?9pQsET4F!P6vDb z)7A2&(O4iJf;(E<={sN)>0Y`D%$grmjg`%0u zpa5~nnTBiD(IEDe{O_nb{b7~o1F5oG34l|01<1-G5qg*K<`H~HFE43Ge09xZRpJPV zqGg$od-X%2XdOr0{C6NoTj|i>S@SEG>%Mpft{aW6MXRE}2>nGnEkvuLlvi1Ufg1WS zwW^O%Pij^3UPr6?!_w97vQ=%jboIMWs|qLlC#~uWNH7%=ILyT&RM}&i>n~}pR=Adp zDsHX}GFQI@r@4B7>>psRfoGtT$P&0?l>Q1u?S63mpRf=l8}&i}9b1#xL8{&>w0l?K zh5)U^p)_hG%0A@a98rT@N{h*T$j)tp!R6v&iKDGqTCV;G$}tb%g39C6;0keN?%7U? z6{2$JYY1r_!IdH_JQkWK$?5r3xMqSjjkW@Ahp@6Lyz(Kx9{)9_B92;FUD65AK2bG6 zyU<&)#bOz_(^we%`Kj&bLLUchGqU~~gf`+zQc2;hpxT3kdgmJ4CQ={d9V?wF3)U2z z`+0-v6SCk=QCXR115i(yX9G|={2@x>dA2f1556eUR|)5a0V>V8`Vy4O6#Yq%mqcp# zH}K(YoqP{4iNG%dobieiyo|u_3+#`j`?_v?Q`b#qgU_@?M=t6wwiHc{FyyD*ltZWV z;2{TbqZIr|PoDv`!#Mddp{=D2cvstb$T&V0xt$0=-OX!}P$qEJ5&T;4!znFBV$2jR zA^o{XIUdDz1E>RM$qhMk{wPGjk0zkN9^K*{6}x2PUb&S7pq9$}8mcgdjB|3kKk888$3`_x*)tYAfjieQ z81u5lNF-?4B0K{LZW~%b@DZ86pedJ#Nz&8nOvtfEO*b^3A>hjDQ99m_SES%vvWJkq zd4tzCH(I_KcR)O1Fb|7Y5qKSX*0(L74Q`~)?op7qJG;-1Qqzjiv3>TO}%$Dkx%4A(g)xZ|yye{-W|_nEjtZ&2|6~ zehZ0Lkt#W6)s={xaB*kh0PH9mqDb@t(nWDj~c<4#gYM#rjJSmPmDQ2F| z{&~7sdCEHSlr{4V_0N-IR@G+<%w&1(ff@A5hZ zC=<{FfD>In@t2VA;*14gCbsSbPcfjoWyvB@1k4od4GgB~W49Anv01P(Egh@}4cjxn z2r?d{F(rfGuLHh=q|QHp|D*wcS0(tjfCs5@F+E-x(t=e8Ug~v=J`>nh1g}Q$dVuE= zeePhZN#Y_{T{l!frf!7RIw@*U?n{yTJ%Z-HunZ1MT(by17;xSemrr?y6TBwDrzrH3 z2%b&wWeWWwg4ZJWR*PQk?P}|(4mExVqQf*8)HO|z@rHceE?9>FJV>u6o@e7J*>9lc z{z>g?>*`h24zP}1)ioihr>8qgZHYp-)COj$qpecw%Tj5_?p`XjAxiBIq+D25W-$#= zsxs=;*Q=`2mPW`t8<~09;_CF9C~8<|3DnFK=xa-$rg1eKA%V^T&sTx;QA0Dg8k&04 zaIT_;q`jsZtnK%g06@>mf^vgCFSI8OM5!%NYF!|G)Nr0#4K3ViI3Jk@BC}Kj`tEgf zBVB;!%<&s(Eiw)h@#w7pj-G;4GBAn}{Y!rt1++vN02Ib)*on@(&7a zFs6I1i4c7rWJNW&?RR=P2!_c4>cTj!#B-I*-tu6%2d*y^p0u^{7G-FQk=wt`15E=LGqu(TdYICkHwpVgq&k6 z5W|5j5|3F$89e_h60ZR;>`!D2nt1k;R);W}XR5P;!}k$8d<1CV%^5_pe3)9Q!;9Gr{j0aq~FEoP1dZeHdeM~c^ib|sdccXpeCSdpr(O=iV%Kh7sR(m5owj5+nl&t((tbDtFI?tf~ zX~>Ufqpxbo?PSOiN}tc^{Es2q(`4!vhM{_BGwO~!9;&{}LLHMbB%Y5u5#_$GrBP#* zPzFgYpPtO`r7~L?N#XKuCuqDIL3PSDc&geAD7huZx!)ytfq~D}3f}9YmUW>~-O+!A zkehERJ8&NozcZ$8gKs}CF>gP2f|A~U3wGkp#pVIR08bLS82yi7o}UWkA0fGO(3LDg zrfvX)BS>6B)>DP)YE-cq6^TzRVe(iQb=r_;w2VtvB+~Yog6A_WkHOj?6x-7%A8rFA zKkOcggdB_&?e;XfHP3o#GbdHnAqWwGdp#}If%@;z9pGsl!C{8^V2nhRcZ5sKlpb46 zlm*rU1#~0(sT=8s+wyof0%+QKfR3}F*)QRtAMEoTx6|uZH#G2v|YmIW@Zy}UqHp01j@rV%&m%`e|Z3K)j zLww>{k60t>m&N0dhwMilsrx`9ABWU^5$b&WGoe-4xkgkavek^FrzSAN$rdofAE1`T zS#uOnuSeCudd#I>-4CSCRt3)%q%r9DY}T==kd5(r=guYO<`I0xsH{>x>!AF>tRfKy zHydT`%0uGs$en0WEbdNnLVQY&N<8A6a*Q};nn#>da>T(i>;B+E%S>)AAslMB28Tbom%&;=MbQ#`2N`MM}fqYU0 z9HC@7JWU=}v#a(vR#!JzecDi@LPyM%F(S7`7_t*1^+D5f0XvWgKWb9rOl%G` zR^v=;4qU9pnb;gK!$bTN<4n|e*L)k-Kq6=aMt&MtfM`bO`GHvp3XD`jhIW z?MGU?Q?=Ax1OjBZV2jM)xc#CGA+m&Z5PR80`&*?wB>R_HWuj%3et%;XpO%_{Ej=&6 zMvn1?RL*@|cB1|$Q0Bi|b9=o4=I+*_ZKt4==E%vU60pKr9 zPn(AvpDW|-Nm2isnEOClb(7Wl8Y30T1IRkS-*f@uo=@J9fhiM%d9^hq=IxkR!bWBPy8vov;zy2Fd+WLUm4Oc~?q;43Gyxb<$=Gg|Zdf#aev!+)HGFE3& zyB6*V&Sa&0YIyxkQ-r4iYPY$Y6$1r|X>*Sui+_L2Z7%SCvdtYurQ0vVGW(lIoT-7h z(H-AxHacoWjz;IT-W8xkJ6S2H<;|AXOMNdvqm21v(bbmqS_5j^bh`x|0;p}%1E*!v zImq&_v+0|tG~4tEB+k^PKCSL;+3MzVtFyaEEqoO0ef!67)%P8iI%ZnRGcQ%&Ai{L? z|I`e02z0@Awsd3>bg&d;pBykdg+=(d%Dko;n|x z<_RKkrskpP#?inQY>26Yjl5#XR;%ZutZZklz_65ss zn~@5U8LcC3x6?6ctJ5;+@_(aA4_PLC;ml3yGk$f3fnl5ZLNS&W{tMiFEfsF~VS;A2 zy|8Jhe_01P4m#lRt0xj?&_PnWk_~J4b7sS$mf~nw-odQ`DA_{Px~v0p`?)CEx0!{v z0poAGZ-B9FH~imeyYoIWZC442GqoKV?^qyd8Q!wM`xoLCJj#~FqgPR!gB!iX;vL)` z1yz%mtWL56QlVi0SqE5~gBvmC!EF*5iNHL#B^7gfmXE5GFt{cCpS(SrYZ-FfnHdt= zlxA#=xjUPY3=ub@kKKlV;Ep|(-R?yyL}s*(xZO_2q>E0=q>uj_P5Ogn(znmtq&|b& z7c{sX!{DYEOAD9z7~8D<8eh0AFm~HpZyM@fHn>fP4tQ`IhQt|kkkqbZ!%D>c7&k0x zDUOEa9o(Lv!Hq0Lt;;$vxUEFdzRfKB1~C4%`yCkDcDw(bw(InXX}hzLI8)ofc)`@f zOx(E*#cNQa$E%j{=*=+a;70ErdIz^cP`!$ue6I5`QlU%mXB}W|4sOI)3pv*`2^Ss& zkyr9UC(BVDjhE#hPSS};4xfUJ*M#;8ezM??kP49;))6oG%w?Kv%jDC&?8gQTFrP1! z(zI|4nS6^1zXD7#wf`kv5?6mbcF}Y7sXmVCd)rWJP_h`L1M3KC;R**4Jk?Jb;fsLr z7w|e@iV^T$prm=Il?T%jX+!>Z55rMzd)<b zGMF4C4UVFeriFh*Cf}mMS%IYzcu0GYrQGKtYyo9x67K3zP9dMKa zaP(D1cs?-x0`4eY!0+M$YIT=GsIG^F)*|Ckk&xY@{5r7)k=SWpM~n0%ZJl@;!PrM{ z#Z|?!Wwp9*fO_dcyyo5YF;VwJTr8oBTx3mZncFPyWuei#vMqD9W^HqIGabD_0wGiOF<=M=KU;mv35wM-J5T~eo%Xb2mRCh3y6sK4t&bkWVdQ@cv9HbH& zaG5r>^-l0%!ZqU3J-F951J^L+StmOy-@}xz@zqLE61QIL!M>1|O{vyRU#4WU)TKy6 z9ght)wDZf*6W#dEF|Fx|u7IYc5*Rf15Di~24Im2%QkHYsS+&Q-UDy=WvdtQ?6x~qE zwyfhv--4o|8}PqDJRx3ykGH%)3iX88O;_zK@hdce0WTtDT1sySqqn@+X{y`t(q79> zTqJF4OXWY_`^JA&-loE`@IP5_Hk(LmTAF0LG+ql?UCwd#8&?`y;ZF$3HIWTPf2ic0 zfV8}vZA5>7%pgb?whaAgXAeu!v@0QZt2w{JdsE|>HKIFJ=ZZH8>|~Ko;BFr3Vo|_CoedX)n+CFe%f8Y&0YsFht1w>kbm-1Tn;Eb#~{tDR|QJy62$x3l$Tq8yh zt{3CzZS~YEiL=S{^Gsr@kzp=mrfk0_gh7z@mZ_>^H&Dw~w&g8p4>Z!X)}=Tb{ejVk z2s_uhv=j2o;F zrAO&K!n)L02YrrBZQrdCZ$Lxss&c-2Kn4xH4Gp!c=7f9=4YjN8gw%zG+GRQ+Pe8_Y zSx!hfXsBJb6H)_Gx04;6S=O`AP`jE=n%khEcD0<4LTIR6Z6{<2>e{Z36S9m-=PIX~ zoG-;ITkX!aX;Rn7%5^4iBf7AfbOREqKIO8qK1l2vI3a%?1*D!0NxfGx`-{L0=|VEA zolp($lQe4|Xm-y?L!+|WBf8cLcoU4%iGgNIeikwvOlsB~TPzu#l+r9Y-K0q_+iVVY z6*Ih4db0)=P3eqgHLY|?wPyQwnS4^So4ti_N=%qIn)Bj`dJ;0-?w!h(hX68&L$xO=3 zB$J+yObQ_+0Yc~y5(vEvy$PtOsMtjXEFcIL1hJslz>2|MK*fgj>a}05dawPeSM0rC z)bICO`<$6GiT>}s-}61s_rA~jhKIe@UTf{Odp&#BevQl($$!y;remcDNbk3!8bJE$-;1ilXe4hDJiOlF-cvmyrQ8J@<;qAhe$d*Bg z0;T|p1wT(zErXNE_V~Q&4HWRuWFCT?Px7#2vK{2_`1xeZa4CFF4FNg`@)Z*{q6_&G zO1CDHZB6~qSzAUXW+cgw%sSQEVT|$}{FZ3=7D+RY1#psoyiGWyRSHf7KrHUS}yCAQ8q_DS;a)wZpg_V1*W|Vl)d9>FOlg zVO+{s7m9$aP9#&Jr^6`v4)HHa1P;H6CMjMkq5=?Ba7gYjj-%{B2|X>HW!ovs;=IkM zb0O_#GLs!f4TrhYC67{nGSGGygGfF#PUc`eoP^Ex+n{pnoD-Q1u$n?ht4ztokR=A4n~#`V#1BqTQx(SjP)kW98a<~eA$qk1Lt5ad#ldnc3a zAU)8}M|GFFj&D9}-uoCHN9#2!+o-)J`Ud1t{Uk`7YzO%X1MR2*$vmWB7zWc(0~3uq z-iuWAVdGt@0E66^{iOuNk?>Ls)gS-tQhR>^d%UDy9I~NwDMqzX!$fI39jf}tlicbE z3~XbjCIXPHszd*Bsqd+3PJ&~pI+&_jI;*+@s=md@JZ5nsfT-#)PDTu)+Jx+^9EJUL zd&ci&1V3o_7iwXQ1hHcMD~6!a8Sz-v8pDI#R)^6Ba{=Q9$0c>S-)5wNIc~@VEY(*; z;Z*Gh=PLYf9JABNKpX8aZZE`dCN@dw#f^LEor)ADRx(&3G&ju=aNnXbXHwfin^U&Pe;=RG{%t;aRJ|8K0s!#mcZ4M$=_yt?PcnOwf3w zNIQdMe1af)wJW+U>HgGxm{Tx^l%u+YuO@j(7xKE#q4q!_OJR+~Ar)q(aR4i(pwc^x z(@}Q#C1m6NdimNg>1PDr&tA)($-0>nR|fU| zec;bcP#R1UHrj(g547FJX|lkTY&-M55u;k;ObKdrm-VASnH8tlE&7ttAa9|P4#P7a z3NMLwG|X~CFw-<1&OjZ;RJMULMFC@CGixR3oH)s@@O0)xPkgpyUn)9UB< zkoInGxYX29JHf;0M7vu}9V;t$3J2(b{0de)Q^yIV9D3CXy{;KX=`lhcAY`H)Mmfoo zqzna7=! z{VDUJlhT)zH=UG0r2NxKITpWzob_FtVkco11%FDAzxaTa$->%YEFjM`5=<$>UB+%E zDJMaP=mpGReiCUqBkYwR1;%3ep;l1aF5^0k^|MAgm?VR)sCxed9i*E{Iw*E z40q7wTzZ!=f%0PROVoOP+3m`E0|Im5Dc*40kRCQ^1dDS5Aga!Z^Nu!4Fq z3(wjeC!<9bQvD-NN?*JRH|q%}Wk1UN#Yw>%C2H1NPD(#gK5$ZYQ_uHtik*aM6#O|s zwu*Qz$zCHtw+d+twd5w~D5N^(tssdsi&DK4q`*HhzC*O30grW%I*cZgu8ije#XN|V>z$NVQtoh4K4f&eoRrfT z+kCmed|*GnhpBic%#> z0ZW_oQ*As3lb5=@lZBh)`5iF6nfJSRc22cfe_pYNbs{i}rqe?o!| ztxr+watG3$H0QXiYErb3AVy&)o6TCIM($uuqnh2-3M$Qv2%U}b}+Hym7$g& zO)TaDwwzeK2iO{7>0V$PgysWwiO8h^yPDW?Kd_sK&CCF{OK4fZ_7J-w2a944G#aK+Kf;Q>NA1B$na5aG z;#0-ScePtxa1?Ige2XE<`g7q;AC-lZ8yDUR7y_IpRK_;X>?d&x!DWudxrnFRA)p&x zF84jNbP(hZzk&8_jbz|e zr7Q#a^ot#lPv_w6v8-p{50t+PBl2J4rIt9`wRNnU;*$PJM6+@%j| zU*0yHFSyGB@MWe$%b_^fbm!iN63grlZ$F%zxVv2jZx$Ls{LfwJ%U*7mYVbGAyRKVP zC>6S%jt|;GJLudGN4Z((-LOSqk&uft>3*PnfXA^|dGG04(K-ToC`pqr=wI^Q{L} zPz{X7lE!78CD<1F4A($VI;i0*PcC7Z>oZRd_iu+Y(C5%let=v3g`O|qSvA=5eCYw@ zM3Bc~N920Z6DBNk-RH@vnCn(MDgO}U-$l|{y{^YRzMPf#+9#erd$Mv^O;zMP@5xhc zi~#Dd*gCkzxSs~fLsH{9&&H?G8a=MJK*>bIalP*e6N2K&IRiWR?-jI>3&j`1|F@bVj;z`RXM_v!4 z=SokOaAbt* ze+*8Bj3Z`BCdZL~f`B%k$#LWd;uuHLz68Q?#ABxFaU@lbBk2r|H*Z-650@p%V9_-= zr#LoI2Jb9Ek&l9?$C&8ubGaAUz7O{C4ENH}UgdJ10tyOPw>>D+e|A}IDMS}c@jiyH zpRSa_XcH=>vj}z;s4!SN*ji~}#@0q)sn^<)X*L2W_tsfBQFi%}K$X4^$kX@0`yh@#T>d{n*bl4EhkOTL27?C91oK_=Y0F#i9`4%?!FVLxRLn#2 zmx_s|6LM-7N?Zmn#_PX~bJ0QFDVd+6OSpZEFH4+d3~P0`Y*I4Eu`S&x%xmIeHxpx; zC6vm(0cemip?l!4L3ljb4*(560w;$JBKsM7aiFYnt%)VV2Jtlrm{=lg5FVtC6H5p^ z_;)9kJYI}S$;iTC9Sj8*T#DhxRnBM)U4P{)WUmx(ISW`7jt1ce_P72{s$D}vnU(phb z^5W}d^fDqFTHNX@@_N@qE{M7n=QyKJT_o#GmtyvfrpCx$Y#0OXQXrZpC6T28@WTe!@^F3S|r(UFZ>So9&Nq#<@@hfRyTheD7Hw#H^CYxgUq=#g=G^L5e}NE!E7&7qz_y2kj+#bQe;*lvJkw(ups7zT+#r*TJySW1tO5H}MgQ>N~iZoiAVn_4zH_~qh z?zcKxfE|rYbhH3Fn&90$0d_Qv`vUA}{h$pUEx?W@cy(5Q9gXoBJ;DKYG{Nig0_X$(eOZ7VZ6fIn(EvM|#w#<}(Wa8lj+ViWCO&qw06W?o@_N?<*wGdc?^73G zM>~voQ)7S~P3V1_0_(a{3zXkp@Q zivsLuk|=bvtX2rKqj~I(mQA(U%)Zsz(us>4dz%>yrXLN0U%H!jZ-CwH3J|;>ssOti zHG4nu1lZk}T`#&@`qe-}sbr~iy4iQaNxuh9*xC}LJp&JWooA(y{vvR{^tzO^0DIjB zAf%wz<$Mh!mrFmdO8)_PWFMS7_PTuC>vC8UB7ql4xfZl~ouVCikJ?d@=pb8eajTb4 z=+r?VC4YA3{16?>s5lce_mf}4gcA^>(sZA<2-?~)<4(gT9iw6+!!xJOk)6UlnK1B>|+|4p)XzlKTIJq3aF0`Bl!q{}@U ze!Ih&^MQL0gEIit=GtSx()b?37e%$43?guqDwM_eOpMT(XUX>QQO)Np z55`T#mc9#)Px*D0(w<6?0%WJXmLO!P`%o1g^|T{zzanq%bk3Vzce$@r7zQ6VJZm@{ z{%JTADYG4pOP7>)=0XfXCz4{MtVGIOC$0dVl8+2&vS;dSNGzj-@-cjB#bOY)TjJX( zu2S=`xpm!Y(QXx5d_>03=GywQ6fL!+%TT9__Acaweq$@wV}_f((mxLkfGaRV66)dE zgptOO9**If8t4hX?+AF)n=@7dxBrYRcg6(U1L*2-W!?jYM+q(CLI=wTbrQYZm310g zpvrtB9w7UCj3NBXE<@4;>187}MFsCi=G0(H63-qZrwmRmTM33G z5>!MeY$ZHRASIWrBn8UF!&VZqJm`zmov+~csRG?f@`fi!d8Oc3?7|>hv00c%O>n>q zhVtGa1lCMQuo(yv;+P{|RkS})t{_u9zJq}lbCfCJ3evZf-sNygWd)g2TsG(%gYS^e!z$7io$vQnd&Sk6KinD9CG3kh4~FD##v) z+^vhiQ#B5~bf;lvpm(`;&I8B%0Q&>iP70Y5>(N~VRj&O(@OIgeEqdLBPD)|DFVmg) zpYW%u_f0hu)2CsQotg_TRa@SH@GdXJ7^AuK;jO{N1MN*?#2QWSjllMwk%`oP44?md zI97#8^<=QZe8@kmCzBPH!3t}(C>gAp`6E^+^L))C4Y8?jK5JQ@_5_xCYbfM3-3u!rbY4Oz{UYH0 z0E4NtX_%#M2I5LH-IF1haW6a%V>Rh+GfX`+rM17|QZG`*hZrgICOp=JBGX3}ht)4Y zJmvlnx9oyfXN9)P=ZZXI*%j8bjQ&3%zesh+B5SoBM~jWfz%#gG1c1EAAotw}iN5?@fHb zh!D5z$5Q{$(K&w4z!10W{m2`nLfo>q5+Cddamy}rY}rHHvP))%O$%|$E*Wf@72=j1 zc~qX^^FrLRpG~}VVTfDy&BWUlg}7yxL}AM=?UY+~_XIbyZ0dbwI`MQ90fMqMH}{6P zHD_ZqKU5)Z&8fls$P?n$oY^wDH7C(M7{2u3aB@w(X3M}YE@eCJ#&#TuRYBQ~d(%SP zj`M4XHy!_10FnNH?f6RIku%`PcHGPC2@Cu1%Rn{t=~q6YlRtY9yP+7z>sbZM@C72p z%|?QApiUwmp=r1xEW0Avk?le?x+1rrQ57GJS?N}M7ji|I(UKAHvT?fdCqTO7a(JIZ zhj3M}-<95rWY~YM{7_koNBhcVScvMz#k;S7QQ>`7aMRftyKyz?D^5_$Z7p^tE@Be= z6_0w+bNwt))g=>Gpp0FO)KNU^15-&J8kww;_w7XYkwj;Kdm|c~OT5uVI1zXCz7v_P zWcvGa{Oa?2X|L*>sJB0Z=$MidpijzVoT$GVUMZ9DOiRhL@cxXGA(wcQi)dV^+SXa} zG32D6r$|Bj_Uc8nD<-)uy8`LsU%V*0QdBq2S3apnt8kfp58Ev-d8eA{WuyqhchAJ| z9lpV>-Z(umd@~N0wT$Bm+&Uca=)(b03{xKt90J_bhXW*g_2Gc5+T9$%Q;7Pk69OG( zJHsd+_a1I*@8RBgD@d~UaPMRY*?VYIx$goYHGXAc-IA#%?} z*8H4>?LQ;M6_E3UWuW*6*knK)1Zd7kcruL1a5D!((Oi-7pCLdyhR>B@TtYl+BqET% z>;U5TgqYYMV-4y&F9aIGcQEx3MsyPw&Klw5a5mxRAmA!jD4b1hvM4#6O&+p6oK5hd zRbemMS^nxcVDz&d(m} zjM!xRB@<(V$q7gBZXS~pj>df^CmeoJ!Wps22}khiERz$?^Q89(o1Ab2ugfzz;k-h6 z&mxl(j^OoWCMTTNNpFanoNzQ=>E(p;4(Xh5yqs{v#|g*egtM2t-ZdsCoKK1OsWUm@ z{6M^^(d2|9^uA3dCmg|>`1A@o>NhlM~K3(ua;t!5Oj1 z31<*_gOte$r=9p$a>9{BVZ!k}iI_RzxF)3Pg^~Snm)g@<3aNSyauXMEuA|(+boVbHcw|2E>@_(b z)gl7Vhsxx9#0Weec}&hn%(Vyek-Gr`{s39ZO*gFt1oucd8P-={*KBxrRP0)5xaR}+ z$lPS6nVg%B1Hr`HlzAGEtPODRad!yMezE6_|JyJAZ@>88t6wy+U${9S(Ydvuvqy@le*N?#$?=T${+~-aIy4OiP`8)i$ht!W< z1(el#n{mlXsGl>rni@`lfC_CZgaHT!_`(_BGYoq|{iaKR!e2b<*Bk`+E)gJ{A-cW+ z>l?Cu>cYA&gpoQItY00h5JTlef=YeJP%fhj?<4R^8O+<2*S622d1+3bq$Ky6UzEBZ z)njHGl7Za&O+1OlvJP8>k>}$_K$yI!1A|H#^?s#Z1QL;gl9CMH zRfH6)fVub=RCH>2#zkntzhd{F!B~1he`ZfyBfw%zrS?==B(j2y)SB!fEW%P7jbIM< z7aZ^3pt6oIGwKIF^D`W7xzYWPY+ zm8W>s5=`H|3ht7OaJnSV3@dd4sZj|L);p+x+4isG@+sVjeObJG3gKb-kl49=-esGJ zmk)j6y(ERUV;!o?hrx~DS3+HUon1cvg5L-_0^En9V{1%p?aa#G>$b~>Sv2yG#`Z{; zkN8nOkNl-mPd+c*(Uadm3jU}kKP2foD&CVRYXlz?YIeLQN6@%z>c)6ac2fJrd-8LV zGp+Y4zul8rct(&^t0&Km_he^)8{$2=OMt(i1L>Ze2oQcr61pSale@5vkN0E;>u(H| z^FnsKCwJjpo#@G3ct8Iu-jf|XNlEV9L{F9su_ z;)9#nyHi~jvS-IfsC=u`rKV1b*QJyC(arxm)XnN zn5fGxy!{h(*@bs^qAndg88>tD6Ll#W$Zbm0r6xR(s7oQJVsrkxUd)t}WQ482n3h3C z1W2Jhxt83+4kE59-Tt;m?d5znnR3BLS*96mooE){qN4UK!WMS30ma?kq~ckkPZV>w z7R9ixBke=0)apyuy=5t$O}XG}RII0iveS?7s*hcmJ`R&a$5YsK9iZouZZFP7A`X*e zl|`0#u?uBj>NO;vOhqEF-CUCbOVs7N(>>|{G;i}FgPGH_*Dx3dl$FOLM7Y{Wn$IfE z#WoQE7=6V$jf=LZneSSP7U5?u9^#q?HZ{NxRH z)pO6d)qCK1zB8&mxAE^akFSji?+2smz=f9Fk4E*6&?EGJ8AkPeP$iyyhJ-@hocwDF z>ZV`K9L(X}SuWzJTB5xCZ4OWY&->W(H>T8PPI}g@dZlBj+CycNmQrs7FJhHvzeism z+b6tc?F(N@fza7co9ao-5h?wyh2P2Q@#@J+EgFgN1FY~pu3n_n!4F}HJkX|`b+lJ) z!|jKZ!B)@?(fS5<{bh_gmWpIq!dbU~*9~bmQYP1(kJ)rJ15THeh8Zr*xml^&V&E@f z7 zgJEu!aj2Gfzl`bw<{N)lpL^B}`GeXd=fAB>gh5Tl_Bm>j<8ya9s+O)*leJvHcKa_`_Ie0MskmadhqVzbw`X!_|xyT5|I)lkcX zkd;16H4cB#3nkl~N~D=;CC+AQKH4cq(#C%`SGvz6`p|!rGYRDELx$?L;P2?T9yX6W ze_rMd&%0IM4D{=Kl}(zz$Os-+jLd3ZiS~t0A}O@t&$>tWOHYU2$;!TlVWU>q9#<`f zI5v#_YKs#35+|`k&`|v~x}i!OJ@y`~)Os9P`McY4w_DxAUsr=vS=6j`h)%kPzlW;* z9;55?ICb$h1k4BW(Vkro^!^#Uvh@&hJ!c7EI*OU6( z94wtN?URcBbCIN{hoomS)6-w4LGS@O4T29edS8gGqTqv!Or|FXnp{UYl2g}2b*}p0 zW%1-_N~5Mc!8l8skHgPYpvu*oB^%skrQ}vg$%&GZ9Zbn7IwgXis#7BPX*%``82c_q z>?bu*g==~6)_Clp-F9KD(uHxCL{@Bmu^+miE83UPRT;dOAs!T7*+!iHeuoWgqDtNYzaZ+ zsw)Lt-67zb`vhG3gn;W`6tMk00XKXnphJ~2+>Jp2Hx&!GxkkV(eFWS#RKV?H1l%!A zz?};O>^w}suB8I*UMb+7a|G<(Ea1MY1l)gdXp)(H969bDMy%PY4+IhJf+= z1WbrTDLJu5z@z~JVv7k%k6bO_s0#%geVu?~b_qE4PXdnnn}Fj#60r1V0VkwaGWdx_ z0#52FVA)Us%O?p~v5=tK=wk$oIa$EiO#;SUE@1r40wz2tVB+%vCcPtI@>c?4t}1Go z5)v>qDqvb)0n^(B%$O-)=3)V}P8BeFqkuWv1kAl%z`Q>ZRIK`&fYYUPD^^RfR;-b9 zR-BPqO_8+)0@lR@oVi%QSsMhL{h)wz-V(6>I|1ir)iB(K9s)KF7I5B70h^8xaQ8?Gdo~6#*B2FW{0;cPiV`UBIOy1YEX2z~##YTyc?rD{mCA^$7vn-Vkur z4+5?Z)Kbee6#}juD&V@=0TrA+0{sL~D zD&V#w1>Am?fIF@gaOYzJ?s{3k&JP5@$OE<9T_xb2b^-V9FJSjM0`A`_;DJ2?9(+Z> zo(}~){F8u3GJ8Tx)kLYds!83%H@RIvY<~e$P82Zpd;!yL5HS5w0W;nbF!Nghvoh;Uz7%k_w->dX6A`e!r+{e{_NKDU1p+SaAz({?0hdk`aM_^(E?+L-it_|qd6|H1Hwn1*ZUNUlC1Cs8 z0&e(9KnFi8wDi~!BIubf9k%{pDaiUmx|3MHxUYai=L zqdpOEw9&-i$3z4i+greK69gQ;SisWN0#4W<;Ka)WoOHW@We*Bi{=9${{}gcYrvgrK z_oeDnvjm)0EMR55fK|f;oW4xJ>Wc)d*&*PJ`vk0gM!>oc1f01~z*#|jh-s-mr$)f~ zHUa0(7O>%X0h=}oIDeafi*6?9-S1HW{ht&t;4J{GVzhltuf8#Ea{7_o5e-YaH@AKQ zk=9>8G>Ns*@#+die2C)2Ip6B8O8DHmR_Pcz%HF#no7C~xIf zzpa#B9`?6(CnhvHqmcvo!#dBsbq07wMGn$c%lUg9mc2&LF|q_4i^H4GQ6XcSJ~Wjq z04sQqFm@rlr{QzB5v96u`1~~=%V49&*;!Z}t_Sm19D*4&ZzGZcPr$qWdvNRSOodlr z4Y(*1G1h+r#RF!+TZZ4>7|krhffw@V!TK|*(y_u*#?~uI9QdBkW*~4~=J-pvNVopX z!_(Bj{h;3dGkW!#@Qzd9VxwYUnM1&QBWwKqP6238YWy9}_?vqVoP`Y8e@3%^&_E>j zIMRlWD%13#t(Hg}nP^nLMxIySnQP^ay>$l`{U)(Cap-M(kTjn7wmwO07&2H?`)9v( zvK&*bZWi zZgX43;ij?mPw-A=wG)ZANqal;E<}vTJ*bxCwm9%TNZWr#q&M4$+WHNNLv!rvi}AKq zU=x*xt4M6+p;wnU+QBmN|J*f>-<)yeTXAGc#V?D;aW8hAf%6=3Yy`_>FP}0Tj=^?2 zm0jot25BX?^$2ojl6!v=w@cFg0k%>2Mwg_Gy$v7Ar7IS)D-QS>UgbvjZi! z?UJ4Y3!QDd#6Rc_Xlj-$9%*%qc$1DJDs~KZ#DNWx=`|1wpGDbeEaPb#fVT2rrF9r+ zQ;tHzHLeCt%HVDw`dE5$2GXtD{FEmt^Moz)dR%6+w>CM9Llw#$~*v90Hg%5y6 zHSG|%txMpTmBdaUb`i8rxfG6Z2D}peMj)E&-v-pW!|m0VdRisG{S2_n4)8P(*^*~Z zlYPIId5JQw*)m$GG^%B6Hs9C`AGU`xc#4s67>{37D`nakOKdEL@IVLWqws|gS2140 z2<(u&kq{n$u&Q+^+?lmw;okMGp@Q9K9fHpqwJeakaZf88tUU-UUfIeCdi4#j+7m(H zLqWNDv(2*H&>TJ!#2U%PGeL9sO3=j+$mJ_R-Z40z_GHPq7;R>|Pp`cTJQ~Y(uk-4k zz}7NFw3+Q*FS8hJX1h1lz5zKJr*U8A)fdQWKL>?|iQL<~+AvY=He`dwVcgf%rkA5S zi0<%eD?zo~W7Cj!UVd!{P#V(CE2!mOn})RW3TvMLN<-RtMYS&ir6KLSZnfNZ(~x#v zc`f(eG^Cw}Jqgs)kak{F^wN-aUash+A?_UDRLUpcF&U{*SEMOU$ma>zDo*+23QNsV*PwZktdVSXR!Q=OqI#! zGX(c~GWmRl;3>XLKA$1D&!5TXGXzh~%H;DIf~SQu`Fw`p>3NxaK0|PSQRXYSTqt;; zER)Y?2%Ztmj4HLdWwNb7?H7coYu=Vzl*IJhr0(O^tm`f3^2cWQ*{{ zXz{gpoX{VJglgr!Hb#T5#bbo}s!)l>Xz#Un(q~lkwNOVezz;x82}SF##gl~}h>{hA zYf4ZWe=VNC7{bDe(e`WcLr$nD}lB!~SH>V`WA;D*JN^%_pzM4}aqpZ%d z^x70$%`OYnuEW^}U(G2Gx2^|jGMKdC1F;}=e-`7*Ipu|-jK>x##)ostiyQ>Ln^Ruw zAn@6oa+%D+ItX9QDKB+M@X?&|G6#Wg=9G7H5cp(HdAWnY7jw!h90Wd?Qyz5?_+CzV zrGvoda>}b51iqG2UL7ZdH%W&0SWbBzaeZtY<6Al9-I;VN{d_8?yw*YBOF88=aYC3U zPAbNSa>{!U*NXh_SK+}m7UObbp4l6S4_KeA7;(3u%>h?^uEU6Hc|6LWg9Dz4qp@l` z)M#u5jPX62=!ufzUf_iX!P!quYX)fL&VO19v5|1hv2eV5F$S5Q7@xa|p4K^7jIZ59 zPZIJPNbBxmsXU8{s3XQ_Z=x%b1BW}nfsrS;eD=nDyfL4X6JNcF@zI;;$-kpj2a55{ zo9Ig6GcGF+F+O<{UHyB}#Q5S(bWL&yOBo-$iLRBBXCbH<-@A!!VCut?r?^5D<8wFB zvqhE}3+n)U?Ix;M36dO^tBUclo9J;8m}0u0#Q4@tbe$tMK6Mj4r?X1FbQ9eqREI1d zx`{59Aygvzv<4AP`wDI=lN;kRH_=1<-K`=C3*UR(>$nE#iKWg4^H9#kQeK)F<6Ae; z!#Tevs8&+>)J^nA&g5NKeCZ~-giC=gEIxD-J&N;h7Z%^Si4IB>Ec2jZeC8%PIGHN# zNX1s+Q%!VeGE2qy$W3%uGSv#eH*TWCrOerk!*o=PPuxUDbf)r!n`mn?)l$O;ZlWV) z=$95Cg-tJRdgLg1;HGkmBtRTC1yyQ4a8r40f+O*l+7H}R-jd+xF!lpCmG>q%I*k3m zP32<=jx;$*MvU*BM*GnCVHVHE_v+GQ*DgT*hJ?_^Jjuo zjIY>4=Skv7RWUwd6P+)FA9{e$x(}|&^R^h@u!$ZZ%4PNztOy6OYFanAts=x1Y@!Pi zDd;2_;{!I)g~FG`fFxd&#Q1(qbWtMcDkzoK6V{QeWh7iD#Q1tm^q_>28#_tfMoE^~ z+&ZklqGvK|F+N=rJza7pjjux*GGDHV%9ls!Tl=XPAFhe6mokzT72~@#(dC^3^4Xf` z32`a{^68aozibBv_e9c%(_tdjG!mzAHxT0+EY$(MX8=*Q2v!$)0O4!uWsxOC!=h6$ zzQ9t`kW94#@Bx;ZUdb#Knq*$qK8FnO|pD^rKX<* zh*K?He0!y4Kr#!}e0HTe zQ;5rr5yCkw=Wk2-6Mt2 z_pw3{&JWAVf~in3KD<(=4_)F^z1Czzm{Kuk)j1XxtOT@AKD$zPmP94NEHaIk)vXe; zWKt4q@%ZRUon95h3jmt<=1Se!5=1K4lID{ub$Ue*kHA_H@Wqw7^~rHtEIznWcW$yW zi^ca=>el{F(kwooTd6xE!I#A7e$Cfb>JAl_E>}LbQg>{kE``NpVo8WGtL{i4I09sR zf&hAjC3>|iUs|a<%pt~yR_c!G9GLH{)Gg^ueQ1AB<*P+lMhGctakTQn!QdYvg!teg z-A!sAgU9Dc(t)B?3U~{?zNl$e!foZJrI;Ug2kI8Y6Bm{>2)!!C_gm@~C0KuD(AK}h zHFZ$jhpSsC0d%wD^DTAz>*ZKqKHpNepS3pQ>n(M2;;InsK5*wI2z~i@OWj6m3@Jtz zsGCZq;doU1~cdoFde;smXCE}wI$+d{oDzUESQNxb)} zxqQr}?r?^PO=a^sQvzGfluxh$VZvL;Qhwh5n=_-=E<_=UAC!1-)*!-UzUuVF$aUu|X~H%w5OwDYQQkE%Tsf_$~P zVd88vt6`!Da-G;PQ44Au=VyGgxgjbGR-Fhw+1#LaWtzYjn;XidDm8%*HaAqrs#6pA zUUNgW=#X^(1Cgs~AHZ#8A;$Pxb3>IZdK3H@A8T%?k=3q)%D0*uu56vF7rf=7t7VMqj?u+|U@_R>q3qGtG^eG9t&j zlUM2l2weaG&kybmm(_0N17Y65~H|K_vahU4Fh9*qPby^RQ)gblBZf-`1W?d zfqbC3VX)4^fqb92VThF)Fjgvpjw(IGuU}^F zwTWL#!wF7|4>LE!_$gJ79$Eq4Wp0?#S(eW-H%yD?(OMYrRptggqsbanDp8j?pJQ&& zOJON0y}k-Dbu%SXodfVO=7w3qlKCgGYl!g`=7yn(DmsvlFgFad>Vt1EH}vn+A{zPN zS&Z+U^%*Sj$CIw+rh(OG$Vd2A*2)j1@?p^&hqE!Y3jaN-SF`=Yw_>$=vs*oWUZ-D) zLQ4MZ?<#|EuHm#1_^)U1_3aOA1fGZk0oMcrrne^;z7M`P)G1H}91&YTRow)FM{Rc` zV#)0=t+J_8BDAzyrvzt=)|In--XwM(N*(eQN2ldz%WrJuWmwI(f6{L*1=Gu{cS#$z z0y=GC${1$p_iQ`5(b^L6(G(A+v9)5x|gm724Gdk=!sC1U<6 zFsV?gSwL!&BmT*#nd}SxAbw=swe?%H62rY8RJm8;9$MwS_`2#|MDJ#Jb$Y&oH=Z7r zn)gUJDa+yTQ=sc6!si~w4}ou49{d`S3GhDw#~Zh? z_4foRgY5K=9fU6^`YoJH^Jk*J!O8L<|0!8;tfKO<{iL$}z*Fx@_xr0 zhJiZoY7XN#sX?YD{U$VUZ4Lu11XnApzd+h2mJL4n<-Axbw0TB~J7a+D0d!sE%6tTB z<_az2K?lq5xwB+&VXMwK&%uF34b8b6#B5_b+{_Q4iRM z?O_u<*z(|4(NtS76@I@e)W22EXO&x|d>S9J@FJCs0`{mO1MQyGO}*)LsSOt;eizL& zy7&WSH-Dh)(LZ-_=bQYw3(Lt}puGG^i@VrJp#=!#<`#M0Dc}Z%lCVC>7q8AmkS`A}NJ8 zf>IrLmLndv|)bG7`Q8{N8QMlM?3lZexO! z5AXLGnA234JhoNC7)tIX_7U#|U+bP>GiFlXP&> zVk$abs7Juf)dnOAmH{u4!2B{DoGfA+MeIVdL<7G}2PZHhpRmgLWjZ*~LEx9^;CPM$ zzSk)x*gM3&fTL=twg&dWQ~{C;+H{cgi2+;AafE#&zGLUxDZvt*kLn&cW$PsW` znSk4S2)LtJz@5Vd>>Mv(*GvI-A0XhKBLwU|Nx*%p1>BE^g`o3+Edn08R=}QH1w67_ zz@v`?{7;j@3lz&7E;-I@eO-KQ9|#!viGWc7lo}?5JON|+3K%<1z_|Sdj6YMrglhy$ zyi35O#|6ZG1+XRsu9c0OFe&80O-u?{4Tm%-J}H2dm=x%VPYUojCk5{xP6}StX;J{; zI#hT54mbt*GAZl?nwTE)e|LI#7c$i^ZZ>2`oR}W+yG#$&Mb7CV2h}cr<=jnp)=ICb zA~9d4hi0J8=>Z+O)AWF&o=(%lVW8O4!wJBXr-w5^`NQeqIxv%`hr2;Zo*te8C3$*y z9TfdYmOVXu21@eu!0us959}h=^uTUnO%LoU*7U&cVoeY1GS>9KZevXk>^j!;K)u%V zK)u%VK)u%VK)u%VK)u%VK)u%VK)u%VK)u%Vz=F1>2bQokJ+OSN>490arUz23>4E4U zP7mxi_Vhsgj_H9N%$gqR(Gz?W6{pkmAoOzC85@R(E;gnI@+1gR? zk8LS6c9yMB+LqGb&Ws|mBJMXXL$<|A;ipdkAgVV{(FnXqrgx>jXAh-)bZuE;@s z=816e$hrQdb4p$|XTg`CBPCx2ISZ!1DATEVh)nxRv@f)pq_8~;rj(uwzmpZ@ESM6t z!scAH7~*f@N?x@^3ERJPPN_LR9#rMnzjRLNZp+!fbWW*5qOB-Y?iPg6h5<DHLQ= z|I#_j^AMuV^SvS2xD;9Qy{Uqv`Q9-CS2E4P2kHBV?GxU6+84Tp0^y23>z{A?-oIH= z#$cM2Gr-D*?*l7*_+)I0`GalWUY!kzBWKyc`Ul&-4{f;>;|#H9;QRDkq{^b^-T~E; z4d2H)8}DGD;O(8IH>#<%+1#jdIpuLqIRPVjb>sB#8;zzp$Q~ufu0UhXb_{;bUbRrfFc^&1+qnNa?)iX9Q-pQ z8m8%%)Cfyz9wQ3B(yUvFdn7aHWa+p@S)_wSx?hteJ<%a8tejdNbE0dwXIrs_)6vS< zrrdLMo081tOh!wi5dim9mRwF=1AbZ!BWUhLR$RJ@Y@-$KLs^=(Qlng(z;GX}l^)J? z6|P!|bq~J!xQ}sA!?s}z_pw@o$YKyWP6nZ{pU{;Pm_ijGA1ve|KcTBQFjL54+AT|4 z`3jWhH()TPm9P9jsFU_OfHFH#VSw}q_wO-qY+5s$D;!Aq2A~VWs(%O zt$YOrGPn`Q7piULD=@SI{-gl5m9Ic+XI7DIiXR&>vGSExP)sXd zOOdm*GD8*FR=(28rz2lR?gqGGjA z#a^HP;UF{Of654Kl62WtzWnb{)(C7Cs%_=V|NdOu`M0UIl`sEZC)Kv{<^Oma!rFRm zD_{Q4S$LWn;)JNewv{jc7tR2-l`sD{T>{uvzWm=M0)(!UgxXfV{6BSJ*;c;%zdBeu z7^>8^^5u6KU3j*YFTb}d&$jaAPjm7lC1tjiFMqZn87Q-@eEGu`!M5_{k7xpFPpmCE zYwr*gcf9tR&@KO{_V!BlZEK7EcPMKFJ{78MZPEY!w^DnWYFk_M?{!jbYm5GmzeiXj zp!M3;7X6=dXwX!v_H1j5{x6&XY-@}DZ@L7qtu6Y$O9Tl0OA=~ZTlD|bg=Je?^#AH$ z!5AlM&$hOR+Uvrztu3PVy6|jki>N&ZPf}85TU$i!Ne0SnYm2BoO|Y#kqV|NKy7}{6 zyMstjmbOQf{#7}OE3R=by{Cjd}k4St!7!?QN;7{-$ zjVNtP2@cy*QQDRg&pw0ph|;w^B7eV1T9&F}TN6h`i1K?TjCyBjlUKi+B(b*h2Z_?W z|2A0?3JDXFS9Zc!NL6%Hgsz=1&t9zm#{0gIHJJ}Z3qxkId#<1c#Z zl{l*Zbg;E@G!08o)p*`S#FKrwMt3feB+YQTb8RSz&NK45cfiBn{QB~Z(cRt1!YNE_ zfib?8fqli$wt#7@eS_YTxL3GkmN&GBBBkwiHo6%{f}lfcUiDl%9~HKW(yQ%^L=Bx2 ziKzMtJ12FvBw9tmT>fOLGMg!U8!5@^u6hi9%2dbWClOh73?5>_#Zf^@XZ1A#bC|50 zlzZ`GYFq%!>Ss~vgg;W)A!e>VOqd;R@?J3Ete-~`dJCtGV5#q9!Kegh017TqV zR>HpPs?S7c7yLcoSynpVchw*Kxh22XRlk0?CG&}^{zU8|Pp8gLT}3r1+VZF8sR>xN zyNYhVKwJLw{8{^FT#r*EY}PzaYyWh7G0(zJvpg?o|JDD%)oXmb^}MM4pPjALmB^Rp zP3=GLEJIC4emrk!|NiR@bs+t3YyZ(ML;V@G;CV;<*t>p>t%N5#H+d_u4#~|fbZjNE z^9uIjQ($(f5m*mihyp4oB$bKd_Ym`G)T9kuqPF%O(cbletJotU3(e)P8Ke3 z;gE3>R=eK$TyYqUVv1=#H?69dZHg&WD-&8MlQ&%&^4`MRq^}{w0n$iyhyx@7b`e`@|A@*Uh>z(5W zF^3^k!vRS5flT*!2XDOQy@gbiF%>f$ycwD|6TDSSee8VbvGN-kv| z$!y#ogStjlQ_jGHYVcE{oIy(k4CYAKlrwA{eR)^iE8yy<1zhu{fNMV#aQ!y|wwv84 zc|$}%N4bC-n*`i6Ou)@!1>7=Sz-Mxv>x zElY?aa|Dd)Ct!4|fH4aMj9n^V+&Kcq-zZ?h69Oi_Dqzxw0%DOK&{=k5ZvjWO2{?M1 zfMX64aO?>Jj$0?-_)7#V?GSLnZUHAgE#Ra#1T6bZ!17-OtjMfG4CSNC1dQn+VC*0P z<7knlseJrQ0TUJrn7B;9q_YJ~zDz*uCIM3(5HR&Q0n^?VF#SsbGmM^8HZv$-R*it! z0|d+&D`4(i0rQR_h^{(a!0A%D(bZC{(KV9J=ouFXZ|$`L*1ay^%&!HUl~>Q;XO9+e z&SC-UPZMzNr2;nW6tM9L0q6Zgz@{GroFBmbfTrjL6#_175^&L20h<>JxOk<2OKAJ7 zDZ1rO0hc}};IfYdT<*aag{J5gr2?+(D`4wn0ox81aMdaSS6?jPnwte&`=o&D-V<>B zF9NpHK21~fhF$_X#tGPQn1CBs3b<*LfSb1qxaAQ6x4tRhwjTxD&i7cFqIc8_xRVxX znxc0t5U}%T0lUr-aQAHj?s-ALy`Ko!or9Curs(~{1UxWSz=I0~>^WAz!>a{6vW1{} zqEuYZ#=dru7#veX4*NM+%s^M!>AC0%q?NFy{pUbH5NU zFBLaMo2vIK6)=B*fCWrSGb znWnmBKL}Xv!!^jJx)lWiP97-Wl$d~17YjITjewPx30QT9fYYB9u=+y*Yxt5(Q{5RA z0@e-{ux^roGY=DR)=B|qZx(RQb^+@j5OD5G0ycajU}LC1m7Ui|z@~`;&OcJX1*ZwP zaJ_(wwg}j~L%_xN3E1+afJ@&JaM@1+E>9akomZ3zxUz?UZG#0|J4(QHvjuEFO27@P z1azD)V8=BC_4(|u_#U(iPBWc;A4PChc#V4)a53yrW?Rnb@5|HI2+f;}0cIZD?z|LI z2r6(jP?PxmZ>&Y?&PyRPY!AQx9b$P91*bvFa)|o?kS%-=>F(nkgp+_bp8{uaGZ*he z&IAfe+ra2pR&tto=-!NZR1LX-e8K26^BBATqoDCV3*IXlVDh~pN%||4#C?{5n#82z zB?%!((z9(3lU{6joJoh3pLo)NcZY~%!>@)mb8j)EiGc(Yhu`;_uct$7h+sTmZRVnB z$o>>2W0=U%+sxBzlase?>4@`Mgd0_U>M}PsbJy5>8AB2qA`ZPnZY7O}Ld`sD8uB2$ zJke@?l94|v$-|0fp70F`)5~+j<`QB; zqtnb=dP91XCK#Ovm;1C9k!f3t=uZkCZZdlt&0Li<-^pNyGMHd=Og0FUYgO}Ew$xAI z4EZV(!Y{!YvYEny(P;rw{_LAU_k#T;tX~YT$6djFKw8HGF-u_yd1W8IG-ZEkuVR={opWV56ooCwDrvS6VrFRJ8Ao zYj4HkGq^gTz5lCV@&2tj0e!*)w>y`-pMVM+4Nl)C8f_;6#ba#Ez^#0vXUDaM`UWBi zyF2#|fYB#gvbUI+wGWZT=08DGGTTAh=c}r76UV$gZa*B+ck^EG`@v7zF;Pl-|ZCAVc;YZAP|a zP8_2tUDvO+b2`$_rH6chKL5P9Q`^)Trzc%%vjGL3D;PUQowD(Fe# z@3iwSk?dn6!w%|_kKU5}7KveiGlmu``C}x8c>C+3cse?x(LSk*;C7*G=R@gPd8?M#NV{*191BfJ;} zD)P2cFAVq?MJJ%48yq<#mTdGl-M)*NbtO~MZS1+7v{j0>$;acz88zq(#u2s%6?L^swHZ`n{4TVxL0xh*^|m7nHBCk{AAV17 zjOW1EmPpE16dF4dkOwsCm0|FXNKX^sq)X`lYvp%MYx79^=2*v28s{>!dDXnLpN z>G#^*$ap)M{L@@h;gnSwN0(WpbOsP9OLvWYrIg8YavO@O+5@>uoN|d?BIDI=@QjHk zqKqcaKxWuZSn1PTn|xv-YZ7PL83#b>NfeqfDR+1?#2EAN|B;HP8cC(%9v(n3!=N!+Lg(Roxc4(t$>{w*m(&!a{7kkcPB8J- zq$Z#Av8jGw`Q2vI6Xn;7M$P#*6Ci@InCw4eUYDZ!od#qN1c`RjWqjFLj@-=O+9fxRp0S{7 z&sdP76a8;`#t4+izpeh{j&VS8zW(cu(PdP-v;rAC_(_avUnOPo(JrIf!FkD}S{GIS zq^iZ6Fr27>bAY6(sad$u<0!PnT?=jT$p5I&j{Z*yt{w&01Q5CDq~lSP(B-dl0FEB4gPU zmaYpo%Bd_inr64v*Q2jF=tJeV*8yjCtgHd z2cOxyktd^DwKWj;0D`R>XtVF-3^mYZa3tvD&;fEAye&a>LnJs?VZdLPKYZBNr9Os4f`oR!|z==7iMOX_&;Yg4-xN%Fvb?tfB< z@tsw?dBu_VUMq5RjlNhL?mmaVyNIlWpB4vmgOqI~y@|IVT~C7Zvq;E6guxn=Wr7Oc2p{LW$)e`irLibwD5{GCO~ z*jYg37LUHlW10SI=kF{^#!*G+Xh^`^D1-2K7A0eZx>l$}+xa_-l1Z0S(N#hn!2s6- zH6;{p(3VUV{{6zIQFv2=@&;|m1jY~&Ry%)SQ8Lj%;0@Z6@jPA(`EceQ5-dP02uF>l z+VTAMG@fy{^Jf($F}9yjPYUV10Y4|S)AV0yny`f0PSby-=?(%-|CRb31e*RU4LAri z{Z}gYQLWu8P5+fW^ros&<fu{dTrQhg;37YZ`Lv;&8n(MUbzlv}(zr{*hqSZh1vvykjt0)vb{5GK4 zY4xw7$U&ghzY5u6g|q~%{#BGXBxv=oqSQg4)xU}|2Z2`qD!MrcwE9<3?jX?WUqyw3 zK&yWhQ3rum|0-m2W~GBx|0=2+614hPQ5`3Q_!&mE)9PPE9dZ4IvYl4{D!MZ-mLgjH ztEhDlX!Wn6CQbUS8+zj0mc_W-*pEj4`fmk+R{hLFjs0lVubo!? zDo>OY-3MOiaX9nU_&os4JU$=)XJXI8G5-q3yO$l@(@v{?m8W$M)=sN_l_v=~10P#- zPq0*mKxn3pc3SnTT#+0&)CX+Ue;8a^^)rt*7Vw0WR{h#()vxm8-_fcAwbQC!53%A|vqI3SU!^`hi-)jSwCY#6R!WwIpxSBGuW|!ZACf%9)2-TR)vxkw zk!8k0IsmQuRc=fqhmosxTJ@_uPN)>K`X;UVRjzZyMyr06=X6#{tA3T6gzAu`Rlmx` zGCE2wPG~?x<5$3KW^&tU)vxl9&G1W+goJNd^=qe9zsf^7^*NaBwCY!RIEUf{)k-R@ z`c)n&w+rL3Su9%ht6ahZ+Ag7J)vxj>&U0N@wCYzmC{eJ~s@k6=b#O9O+L3CfRlmxi z$t=}QtA3TklBrezTJ@_OE@jSU9HOJzY1OZCL}x0k`c<|jQ!O>L>Q^~ZMs;Zcl6`tr z58J9=)fP#BIBW{4hi%ob>e>WH;_qQw^{cui!O>xCtA17YCOA5bZPl;pu>?n&oFt>2 zR{bi+N(vnrrB%Pm$#JS`r&YhoadCoG9<=ILIZ^Z`vL|h&omTxSmog~|7 z)vt1)@MWHt#EX)4TJ@`3ln9!Rub_JL(~)Gs-^?XIJFWUv9+Xf*BQ#FQfs|y4&7xJm z$}^d@c3SnT)E^Y2@%7Q{L} zoQi;Np*Cy$9C1Vc4{P56A62paKeIJJk`3WzHwh(65*7#s2qlD20|7z{T{;8{2yQ?W zu~0$>6^JN;fPkpj^;w?{+p}S>pgwzf7JQ0|4eS4V&dlu2CgHvJ|9pP=e6n-zX>;bx z+_^Jn=FWMV6r$K6s`ZZ`;D}d9t3&vy8cb*VwM$`A{vnipQ0Q#G_8oZ?#Reh+iou5n z+9?sL8R%@k_C<*(F__NwYu_aisu}2PzxM4}bI#YwoX++uP@@_$w0@P+*?#SNFhdNg zWzpGw?RzGoFn+|t-o7+mKe0w2I+(NlI?Rffp4o|7bTDW8b>IPCGuEHb=!o&$weQC= zV@ik)=4`(X%@eueWaGCJF@a6w&WI@_->S{F)Z`xVY+19LyYSNx-d)7gH7a~Kfo zLby)3_Qha2+pq9cmdXZhUxMZ^q9cBbX_v-eI@_;sW=y$eJQAT>F__NwD?BZZI*nM1 z=i=9^Sn+XpVHGo|W=CiH70yzFvXkg+zryKyghprk74n`u4WP6A3a7?oi<9VVzrtGG zhtS!6h2uzQvshyhgXwI)!tsevT}nFJuW%xZQ;#8??N>M{22gS*(b;~5J4nJ{I@_=C z%GlE@Cehh`g=Z4SU^?5ca04^zW=d!K61@A3 zHIi0}(b;~5YK+W9#$Wpd^;fiA!pOZF0puj{6o(B7vOUwya$AI z>V9g8XwNj)_Ng-s{OT+Z*G!^qRhM?MP#i|B;o1xQq+E@FUiJwb@} zbrCuCr=OtUKjV<>+fxYofK_&^MVXsCj%imT__<{_B_-K267MpP?3A(+L^uow`!7W* z!DLZj$7qO38$mZ+)D1Sp9z^AOYC!Cfsp;^(1KI50GB}V?^)l_YO5D5BT#`fu?!ujD zcC*hddW-xN)N`tSE*uGc*m%7OknhSk~k<4t}DEg*X!-ZEdJqi_Bqo{GRIY#NBVWsA93w0;AJLrDK`u9n;J zMbTpb_^*U-!`l>J8zuWMcekX^1=?UK)xQ3nJyX7YA zIL{)f*w@=K1D|ELp__^BCgHWXDWaQ6ZvUk4pV(s0caz<6rf5NWe!=z(J%EZ?V z{t-&rJ(LS3P%TLS_J9a~rP~wE13%x4a_97CX?!=DrHzB~92nLAm#g(Q^c`HzLvG1C z#&geumHfNif$h-7c>$|-4)Hoy;a0RD`+SB;x%3}* zUj&xbsx*_2eBnr*N_aORA)*oM`|)+L!`NT~R#rs|T+t50I(al6589U0T=ZX2e{ zv6w300gVumk2XuO9F4*Ms3(mcY_3$%;{II3Xa!jMe{w}C@SQyeWq;B$5M6*>PmxuJ zH11U!$JG+~p^s1T9ky|-Uqr%(&ocjM<0`0!iLB3dDct)uj%zP6f1~F6(8kf3Um|iQ zLf9pT@Ll-F9%{$B$weME;D33j+3F%j+F~X8sYx)#7YWqo8SqyL)Sowz;$3_v;6Lgq z@x^4f5E!;~=I5i_9Vt!LG~ausF%3N+qQ!6UdloRwAa~^1*;0Ij*S7yhTTUct)nZm&iw&n#txFSHK;#m1 zFwA(lts9rAZ7w>BS?{6V2RG5JOtrpjoT)j9;5%aNVa*-*W(dx3|1PU4MC7mmUv1T% zhj9)Ck{i;3)f&m$HR#fx?!l<`Nrp>eO- zIMus$M#V7Sn>H@-^&uiRjL}pd+EiA>3}5M1Vm_)%AR_nA)wqvsT)bi;xu^iv;dh%r zHL8EUi z$gD?T73wau9L_Au7k`a7^y+ZbqqGg}l?e*!5m;ib?d?-krS+(kf&MYnC93=3sq5FE zHX?G{7@s2OUsr;N@YBJ$^(@Pv}&>wRPl^ZMJk zR*FYoKz-ei0PbbLxA;g!B}qgYy(`4?7}WUh@O_I{sS(oQEWE?%O>(bYwpgbmBI*4# z!9zAdtWuQfk$Xg;AWB48Mi{MVr7tH^IqgsDDlkV-_Vr)q-FYywM>pP|T8q{x>x zfu%?~s)h-^wF&Afa>sa0^?id>BGPJ_CiuZ7uoQW0zDvAGiu`O7Sc*iU2owBi6Vz2? z?gULG{MPdvqY{zVp$Lm{*#wp%>p%2}Kgytp$4~wb{j8HBB67}~8W*r}v3@}JtGp@Ofi|44QZp52_sal?xN@w=-Y@g_vf#QYz z@$t4p(@hcCU+Y%5d>co$5s^-7HLjhFQ`uL~@rgks^CTOmWDdL3t#F-foRaw#WHMhj z8>eKhg`PD>(WjN#I3@G8O*jyZaD8o@lKI4HjT>O&l+4mMFxP-b%0I-yiMIP%OYs&~ zF8o9Nx<@Ve?sk{BlzOZ&e&q<^Za(k)&Qfg0IK)4m1*o}7K?SVeXfU8t{SJ9*l%?}( z_PfMxe4XW=!^9f;?)g$w%mMLk|GB7P<%!Abe1V4U@sm$T3;q(5vu9}Lwl6`8$vvSj zfp6p{tcl0tf_ZkxE^;B_wXLn>5$&<5u{{WHES zqmn#o%eVoas%zj`@;{-8*-Mpo{bxelOW>#d1keTaeXgO;l4DI5Fz=pE;F~1c7j4>% zPc`&ao3`V>gjhthZ`iaK8R(l9ZNY`3J>oNXQ~mGx**eaJFg5>(0^ijxaSAzEj%XZL zZNbidQrv~*1poI6EDGMg75+vV5*|+=EWO?(o~G6!lay@LG;aQzOZ-GFCKX4>nKn?6 zjc)ubnk;1{sdhvSkz0al4h2&&C18SJqdEklU_J&rjBBo$Sui*Af@9#j<|$~=u|D4$ zy>Ns=Bb4xv#>Eth=N!Kh1-p8?#8FI>{XhI~^gYohHKM`fP5%qM!_Qv9m3O+t8RRCJ zU=>CbWMkZYBl!)cT3~IPW0(m)hIJwTbdBRqxFCG7Pk~Rdz|K#!CSMS`QsXYPaWml- z7X=qz;Zw7}upMx3gjVJ#eJlMlOyUEqrV&D>}@6 zUx){>)a1WkHC@pmI1+A~;V9by4LPa(IIJG{Q<4g+UO*TLq3_4J3y+{*Xd?1A{^k?@ zT#xL?ivvn~^4kj0$$Qn4IF`jVI<^GRISDO=rlhW^&H?i6K2C%oa@F=2h_hA36s0V5 zi(lXna#hjG$oUXU2K*z6t^j81i&*D5wJzq8h3aMJnnx-)Z^wS#C+S5+>kvOG26 zp3$PH^dv72g7(HrLMwD_{FZq5hY6L)k4LFVf@@2I=vOdp;!^I2qd9LX zjwrgUsatHq$i}tjQ!Ly&^dmx~`cnA(U1N)W1HK!XV;>iv@kRUa+Pr}9*D;flbn35| zq!RE3wn)?c_+P{%_fo#J=)Vae?o5HIEx~34tF;4^aN?FpiA$eVs+34x*FK{t_1-l_TpYhP3tlSuh8W4i(DRLn=O&pqOvXRZA$oU-MFCxx^b!_=T@fl3h6OOC2nB_~y73B3QBV#6_$Wg|{Sx7GM$QFJTBLXIf*?+{|{(|E{M9;FW%1B=-3 zOAK^v08}z?0Yf`alwvw8m~;_+OK52K8|bFTEZTF1dqg%S;YnLogI78mSi;vh`1=q+ zw{D6}NgcQd)P8zVgB_jlz{w<6 zsW*~uY=tWoL@C_Q40!Qk!+M#{P6eqUX)}MKL~Ck`Mkz% z1udnOMFmxBzWBagiax~9-)86=a4TqeJ%)e0f&nEl3{@!7(s>!`h>~4Uq#GV(*(kTT z>S8CFTBaG&yb^E%3uZH~|&y zw9#}jvNl{_Hf|N$)*(18C9g%z$i~|wSIs=M_Oe@`K2>q!owCgI9gTO$vPS`@vNYa~ z2u2*Ilt1jax?xOc`uyl#HwmXKIuz;1HZ@v^{EuYm{n% zYxFSCrbY=!hOAqooxHoLB_wa-hR_dho}y7_<9IZ*h~%61q0kPsi}>3ld3%UNef|{s z%H1NPnrtI9Y`TG|<=uR} zR+~CY?#(0NeThB3y&$!fjC>qb3%9AK+BA`K18S`__4EYrK)qI)TAcvitJiZ=&qa{4 zct)|c+SEK5Sv^}V%BEgm(?q^VQp>EV%M!rvo~o8vQ&%Q{ll3xd>N-iL&?Soet57Yo zrfx_8r|D(Z)Qc0qEA)zG>Sjr=LL=m=t5i>vx<$SgD}=Im3u=74VwsvPBkeHBriIAV zE9wzO`rM&bzfyNtI1#y8FLR~tP5}S7MtO--_sRZkVw$v|s^%>pshP5E^)8pFO+iDt z&QvZpg0?U3bctC6zc~@!C0!joo%%Ner-mgWuWCnm>Vxv3SY8hGja)`uP#X5~_%F4M zjQllBdCgP*A!!SPGL%If*@cicB(Rs(&Idhd*8;zb5vAAM(G?sIWd(oMx-3$QS!g1ercPG6xRex zrfY(4Yyz4dX@bAXG{G^OAoeJ0sx!5NKJ|EmR3dUG!h?|GJXN}^y0aAN3PqT}ZxdLG z+yh0JAlW9UtH|?kzA{yMgH$3C#QrVvi>GGW1ePKTwBtOrwM}3tGNZqi5U~mBD)KWX z(wxsp4N{57Lr{bq=c(On0!xvW+Hs!R%Oj^@-_8>eLc1)1c8PQBd5DVdjO2X*Rp8>eKpgP!DsPTg(el+07L zgF1DujZ-quTdf?_srzgk%M`&*pZGDZ{N{a(D+67#Xdq1E%03@GkF!8=6Tr^Y?zF`z zaFz^=rJ@bwyR+4uLo}keMh}w$E7eGPA`up^9VbZH=9uc@fp-4+7M83U}SMkfE&cMmVZ|G5H;O4koMOOTt9(4w8uPdQ= z>|r&J2;5nZtJTZu?H#x`ZXG31glN!rGODC;?;P)Xq_Xh{$upp`r?hPvV?^J{yXynO zeZ;5`O~vQ{;l>|}&=HX3gE4JzC+`C!Ag!|^q6rceDXj>HKf_7+KAaIvb31uAy@NSz z(~K;70BBCj9+Y04VBA4-d*Rz<7^P`Y7G1Ym#dv6%)fdcxwN%d`;-P)5O+!WRAfmzN zm{K)u9>nI@zXFltT>1Rn_U%c`yfhZ#SFOJJ!0sK;Pspi$fV$L znND{&ps3T!Zn0w|wjlo|lU&1Ayoe{aGwyzu$*y5^aP}d(`$OithV6rUg4~(GKjnDW z@YEHE%rwI-g2F|cpk0kRq9mPx7H!MU@`=k|!AJbkATFCfwuiSP@MKW%gfwu*`P zx!)Mo{`64M^1X1A*8Q5_K)GWUF94QVEWT)!n89I=N3olnR&U2$cD7vcn zMcJ7tbVT}dsNC!<(VgNKWw(%ltH*#u-L+D8&VB+FoA^c9Ie){wjp}|a@#bsZ9wvTK zc3TZ8Ht~zH+bPvJj~<`TR>!wzw>NYqeo^*G4?`;rEx8BTalo8x#4l=v8;W0))v2or z{L{Q3h1%$CMTpSSL3F3!KF#6j=|Ih`I|cq}-qqYOu2|hUor$2>1paB>qZIcxs)q^u z)4ZqV?_mP}G%qy}6ZofjZ_UcByx0W(X+CBx)Y8Nyi;)ADqxtC0Ch$-539KnU9nQU7 zp^^wafFe@hpR5I4Rp6gct1NmTDewR1!!L6j~tXOv+lpi){F+IJ}z;rvqd~cMALy>ZjnEyIfP9LKzjCz(1iu zWEdNz@*1K+QKmM5e?pZOHKTf%z(1kMI=5mI_$M?)wJ9!a4-@z&v`^FZFoAzUr|G;@ z6`8<4p}AyDBUI+9z(1k0l+cBw*GLoiC$!Ll7Ms97p|h0)ro}sp1OK#e`cm2=BQTCc z0L($jT4eU6v_)26k_J;8AlaftUrJlF3`}P*#{=rB;sJ$ovlinlU5*Ddz6U(MK^MZ@ zyy_P3q6)%=qJ)4P? zANL6iCLU0DKwVU&i3b!ON)1<5ns`9rVSJBK7smr?nLUc)0nr<_CElKuCLU1B+^bM7 zS#k)!91o~vPO*sx)H3gN7(zPllR1h_JfN2O%;69Y-I$68WZ5Ts8@@n`+2?o2CHoMt zu6^z$2{HT7o%0}PW#R#aONm_uo@A(r2Ndr667FTdVleT5!UO7}Dos3~@K7qEtTgd} z!o&C;1>kr83rh=~W3Qfb814-LAbQcq~s;dtY$zO+28S z4~bR=zGkS22bA+^uhKZw!~@Ft+=iNXKsiT#2Cob#xh5V^&NtLGD5$PI6AviosLf#F z0p%R4$6(?C<@^|DaDHb+O+28SVi4~VaHJfN`@ z4`>xIt$vhaDIO4CQ#_!t^d%kN{Vd0xTBR|+$Z-@8h~bC_G>+l{@r{ZH)Jeqy%IPtl z2JPk4*7!$+=#nNkIX%&`zCWQ#9KGiRN-5m`uUaY|P$v}+$S6ieDyJV2qF=4p1e#-T z2+iCT6&ymdf=T~qD%?b{oS-~MRE4E;k;;J|gzix3dt!jV!EEdD_ z@-sa0&`w$-=J&^Spu z1FIxhWGPQ-NGTBAahQU99RmEUu&wag&7}55r zq4?ks%dkQE@{W{62x1&y1sI|hZkrr5E6tO8W1dGC5n6~}a&};)d4|FFyMXX37{3_5dZoFO_q+Gh zx^jM>I(pgb%7l!sE7y_~v#v}xwtAHThA8!NA2RF8zfktf7}^RBRggA9n{XraZ|`G~h_R28PYQIE&`ZWY{cH_Cj2w zT#EPgb$!t~_lWMJk4usNrVPA7tcQrTcuI5C!16!;C+=-j{wShG04pZP2Q4ks$AS5N zX_2bcqpGpW-;|#$=ky~npOWy%-)~Zj)%j_X6gA*Zuc#)O-!uVy&k>A~-~q!@)Hg9* zLZ8mhF^@sGMZo31nUD@t{KR9uLxq_jr7bCrxx)i+UBs!*`oK z9@GqF;5OnezRf__Qsa|>yBNA=s@dZ~ZNkugZlIf}B^cUEelUAH4uDrWkF$i|0abfE zo{mF%e19yy$Aj{Bo+n}v`T)s(l%h>$re`g8Y6adpomvO4$UPm_3Kn_;e-NwsYL`J> z@eLKh;3gr8Vtwnl#>Zei49w542}D<7*dl#QKi13J6nG^~u}9jOexsj_V=--SG+kAh z5l`$Q^6iB%Ep}NeugTm$PN5iNG<(Q>+%<|~knuHQkd31lWI-sJ`=l#8g<_EL%~P%^ z6oZVfpLUI+7-Y?f2rAmi&dTvI3p8DAfAO`#ZMe0|t8WgcF4EaxrP6pBH{*KfO~Pz*A@ z{-S zxv#2w6N4=GJ#}wlkmbIw?oAA`+z-^fi9we8A>YIQ#4*Ss!9=e{0o08&x4asW%z+ee zERrJwoq%(QKy+tNz6El2bR{^&AdA51L8O`rekEq?MxbI7gDg_e7xy+wO#KD(=^3y2 zgyWYUcwglBoj51BoLY;Rb~!Eq=bNd=@Kw@?zHZ@UD#B@d@rf~RXq9%_$Jm#tucyx# ziVdkwb2*3d7BjPEy2NYP<<>TfH~+SffMqN(Zw=WpI?v^d0)@?P75M|Rfw=Roi}3q7UNYi{ut zwgozAQkRelYZo((OQnjOriy&ZJaB#gE4bQ7c`DguS|PS^;EtG8`P*>$#VNzFO}d1v z(@{!A)zPBrXjw^JYb$lrRvKCX4hN$+;k5ow>-_st*>%&+q<0H{y8Uie9y_9 ze{gbF(n8AU?q;0a+lrIFx98-(Zk*iTkCO+7aq`dvP7YLY^6;6QJi3^Z$5wLkkM)@4 z%`19hBknkc+?gChZeF+9^zh8I!?}hjFWTToSf^NLsAxpIXSP8lk>|txnK+@7oN(=k_$Omx{8x! zyEs{X6DKwIakAoBPFB9d$*RyI61}=BCu=G=Sv!T3bx}^%uj6FHZcZ+`hm%X5=Vaq? zPBx{TOHwwU#L1Q!oLqJmCs!<|q@jZsULDO?N?5wH^m@iUdfCOoXi}=N!2t?W-aFAluewR zdJ`w7Jw!?0`7d&^-~&$1`i_%@?(+$Eb_OTswB=+`PfpGq&dK8GoSe6Slk-<{a>3=C zT)3Z;CHGO%zv5X=hQ7hcuunM|ew33D@&Y0m*^HCQHk^#=!O7^MoQ#>u$=GU6#?^2# zehViPuI1$9dpVi-3@4M`=VbD?oJ?_H%r>w8RELvk9Vi*FvJWS#xN-)pp3iq{SkD1# zla>(4x@=C?_u*v21WqnGo0E&LZZvDdccoob2qz$*$3yTovVH_XbY(?B!(dL!4aw8Yla{ z;p7_ca*}dw3r?;p;bi}KPOhKN$qgGgx$zoKZaTop&F^q>%lDkz>Zu_qw>9VF_8y%4 zZ5$_eEa2qMOE|gf22SpNi<5hfaB}bOocuj=1xdNDA1C)$aq_@YP9D6GlLK#X^6-b8 zJn}Oqk2PLNe2=%_{o+hcE-Bz- zV;Lu#CULU)0#0goa&qYbPPV+o$z{hmxx5KpSn~#N&E({YHk@qh!O8Zaoa{K6lbzL^ z?7E1Pt9Eg+`z}uQJi^Jp2P*Rb_&%?0(li8ac2=s=>l(guJZbGcWX4=etG>LKuEV>h6 zW`zuR<99>Voti=_g5es}n5c?({jN?E${gX~-bQu*{bz_9sl|Z;;JP9s6B>qtfDxx>QcTHqAtFq?1^9J#PIEB*mjpriimK8WzpI zKl?GDoWI2}C8%_i>zoe&5B@0Yo(H9tBp z0ohiTa?zOt25}9R=}e< zbj2|G(P0pywB06JN+`bKAM$|Br=RL^gy1XsiPCNKi(dF4zi^bCmDS|KtX@KNbQN7o zSA>X?PcurM%xb!--a`n6-AGr2h>{;UdLP~L6|?abv+>nn@Xn{7YX0GTza$R6&4qyK zU+9*uqGzL@m`^{|$>RazEBf(Li}aFD#ybS%@Xn^P-8ujqoAFcKlZg3>elWOHe`YE? z9cZT#kMD&P^=AjY(!4z&aLHVBh;lKojJO0B?2quA#ZCzBke93>nw|A&mN3oIUFbU1 zmyPr#;571);PXIol1w8f39k7w!X^I>g6<p3&@oM)F#|q9f4C93Vo+M@*_It$6UEZt3JlJi|XUos%Nw4l0J@QL%Ft4*DRJkN7_`q zhgdhRsr0FD)iFf6aZTk9e(Tl7SI93LACAOpqw4C8;LoNyUY-lA`ID`ZYaajBEBXPp zLcR&(nLmFUkGJLnppF2zQcn5_$tpP)02gSnUs3<9lC1y>F#pPd1`1P$8)dDORr>*2 z{x?f*+w8^wKL^MPd8q~Wb&^3Kt_5g$)Pj4KrT|<+;Gvdy&*Ct^Qvg{hTDbOJ25`+E zkgyvUAiojG@;hVM!Lz#6t4ZGmw5IuYUhyd|KzbC(S~=-gO`KRCt&?ls1?dUu<5!?m zeN?FWSOY-a`sfMRiRxo?!}T%xMD;Pc;rbZeaD9yaFZD6{Ki0<`(EEh-QSrajN9OmY zJ}UlOeH4RK)klS@kBWxtBR{$RW3f_pRMy`MA$6@k9HPrk7Qq}g$ zRDF~+Tp#TlH`Ml9DeF)Fp}zIg0XtFK4>xT6@QJJ+ZrJ+ahOHm|FV+wLN9$h%y-#TU zR{w+bSISoZ#ps|=wr*u?y-wy@uNExa)qDM}m-ko{{&tPrcv&sk>EKO%aJqiEzlIAn z&s(1WTD=3t6(4hGDG@jE8D8l<};fMJF|CTcJi| zi)chP?KoB#=r{)&h!G*K=}-qXDC?mHWl>s0sa_1B-mZh7=nA@G7+r0MjUxD+dILbR z*oja={L9~@;_5$H(rLYX!~*yq@-$j6kJ^v}p2GFg4Y}se zf50i_~}iJki6pn=1aMECN5XVkVWS!k&QH6L7c8TE|<@tX}bRNtTECS0ji~~ zz$L~h8OCYrYTA+_kIu9ol#W_Fu)_YTqRrn=oQc4YWZ~H(0{UDu;x2h zbx{=n%h%Gc{*(Q=KEY1Pu8@21YyR+|%Dk0Q+)JPpauFUA^9RhFO>(3K$vin7ADhW1 zstgH~FPC#lP(S<^-8Bo3#!}oaS&1KcGj7>@_uxV>cFDDbcp?E&Mjzlj{w~}V17*CP zROvw|2d85eTBnjW%Pp|MUvImF976N+L`w__)|?J>1D2@xKeWX12dG&3PY&l{HJ(5! z-14g}RQqv#YTkxAWRB$z8e@U4{g{fHpMiKz!RlCcMBK7-KGIxs{HN;ts>#f?a#++Y z3T`5IheL~}BEf#HyqE8En!-=*@RpS*&)JXuM8qs_7m_iWEm_3b$-Sd#&C1NI#K ze`wD-<)08Qf8Am=It|5|*r%alW&f;;HBlAoHB+of^@}wrSaW^D#hUzoSggcmGVMP$ zlOE8%!Dcc6h=!ZV^thQCXeROYVEVm5r^9wL57qDYHp{)pgquKBeOpxpYt8|hn?Rk4 zI#r4#Ur<-L6QcQf=dN&zlnWOU_)Y_+-nEJ|SjgY3EcueUzgG;JyT7=?+yNXTZBL(o zn!Zf>e^CLMNzCQawIzu~%_d#9O6m#wFTj4s*}ram`WEVnyTc}B?erOWNERG#6~?@8-eah{yB z%k;JJcYvw2{otr%8+dI z8Gf@IgFCi-b=>l2k+kYy%~s&p@~;`oZ2ExyG*Zc|a|AEo#m=40@+8c`%V)KVw zMxiIUNm8SUzp0k|jT+`Kki?KPs7%2oF7ge|_!ztLg30{JrC3&oji2`eDlatjwYcEn zKqRMt{5;CPNQ)ZmFZooR>_l(d&M|h!8>G8p^%}P0-#nC5W@i* z7jQM%Bz=R8M1k)ydy4h)E}N#Q%Wd28Q!4GYx!RUo+WNz}$AFhB^L9zmt5>~JE#C;N z`ID>hn02r<*wqLlijI9C;CGWt`aC^i$ChT!k^Rt1&gl!H*1&PK4m3pAvP(oWRwZMb zZfm|4QSvM=`*n*HyGZiMHd6!5X({k>-K_e$ZVf-a)~pzW$^i*dO^es38hKVPcXk=*NLq-`yfe~_+os)FTp47W!5 z&|dO9d&`YM=lm1TBmXUHw^fRZ=s_5Fru86*Wk(LX#IIDTXBs$Juj;1nv8n2EYUN_t zXP09a9u`*QWow+AqaExalvGKfyvYl)n)zdifw?)PHhQ`Sl2%trv52rMCr-$PHr4~i>e$AW zS2WZV>-RM~NaBtj{i$ruuko_QI~=?W`~F3yrU87c&zZ&jXg}<tQ7$_`gZy-bxnP z#S*zy(rn;r>QAppStXYO)!kHTKf%SNZYi;L*=``fkw|mN2$T)S| ztr9b!geUke*d23pphtWnMd!?2(i`sF>?(N^7M*CVwzHEYu9Ej--Dx;zItSCzgl{N5 zsrRIXrUP&pwvBpM`Q~GwTvjMB?HTSxdga)5N)&ALUg-A z*MQ{^U0&^*3>LpDM0497M7KZmD3D&dyxDg&6X)qBg=k;t8jyF%3en!uXXr9JMEgtI zgRV>S5bZJjnV>B~8*#asE?b9auj$itnH!@0rtOF}FGPDzefCLx>)X)L=a-Ri|Miz%e|jy-7GhoXgw_V3nIwjZ5y|Ij1o-a%_le08qsbORAOm*qzb6HLVURM6FDH1dv?H z#6Z3xNFE6@kUV^w+`TP}n?W*9!;jb_N%S5$4>wWr9M;OElx<`kk;LhA;PP78bTY8* zs7YDaTIr|k3Rr;{llpG8R(?XblUS8{xR(w9*MT+x#l;!ETZpfano?cdUisW4sL_c` zQ2H!gc6O-sLHobWb|cm^dkJVM*5UQo(jP_unyPkV)ymC8lMPjHKiF)Zt`j4O(M zP{@k_={}U}h<*UsK#*ZvGxQ^h<|GR-0ebh?LVKj0IHp#Pr{avE9n^dji8_y@R*oa^ z*m~5BvQX6Vv7)N;kZWbf(@|dj*3|hNrBe0EUg|yaYXG9(u2xdS z?$VB2G**_L4zL^|aHmAD5?w1PW_M{(A`UDRw7axRBG|A{)b7&uT)=o6(;86N?p|r} zYT|yTR#M#V(jJLmBaQ-hm-bA=K?921U0OD`0mo7%%XFp_}#ryW4VI=t&?1$Ph&2=rg;|&Gku!a zkYkvh_er)PogM}x#fBVs8N1w4ZAf$UC4B-mq$~EJ_EEJHbY?{85SI~w$KwLbIP>&K{`ahDQUrOi$?5MvHmt{^g zI3B|odI6k@4PoA|Yvs$ZP+4=9M7!Lf_3N-uSqmF-1Qsf5X+t8gP+2P*ayN7=%dsKp zuuxgphO~y(W$I0;^Lh{#D$BKLYG9$VJR5Q`EL4_nL#{$u%i7qGt10)04H-NDTy0|z zhdwSq;VKAx65W{BL;)$)p7e3FQu|4KfercNC?M@(5QjckfUv&^+<|VCu(F{S;^SK~ z?1eJN+XWX%xN5lvLhP$1V9q1J)Phig#U;8{M zSN$Z_wLdAP3%nH!PfAW{gnht#-6$<(3r3ZE-PlPfFf>gvQ*zC9a*LG1`1*}$Qo<>( zwbFT|=BIQSgae@{-$1*RMMj6Tlh9O_2vJ$#6W+PRy_&6x}mIUWoN>zN#rr|vhXG?U&jrAN(&V} zJc7?2H`7~Gy%u9Kfon|E7c(`z^&HLeHnG&kGaw^^`je5MK8L|XXx@a`BxJpvWfOv2 zQcrAC0&iikP2BDIc_?Fp z1>QvE{H2?E&67N%>pO&-&*PUEi@`mOF=u&{$DH+W*AU+V9&^^i{T=V+@?LQR69JS) zSXNQqI}vPNmMigIF7KO&1IuLu?w1HQEN|o8TVBS-r=f~NKVbQe6f3U>{)(svB!Z2k z9(a<=2XVvZCe8(-TTw*&AV0)M0fTn168yuXtD>zr_^uMKzCqW;F|0z-E8zKtcy5nl z6wh4ne2s2l&;xOd;`sur!%67Q20aR(7JtWGX))RDpmj$AGtd8rLR)0eJ~y z(efD#NnHU*v>ATA^a%`lKeEy(oFUJv_^KOG?UAKOqKYg++02aVRfiUXN6NK|33#N# zg+*qPxT25hrJeGCxB~pKK1mW$N8RrUBQT1lq!q`IW;K<69~? z2pXdg8)Ch1$lRp+SQKZ-MR7(07ev33;Vg^oXOKUm97EJwgOLV4jD%gxOa$V26lKzg zgsC?MYsW}!&oRWaF;M|yuc3t7lqk>O{vsXLHK3p&_%{)(jT6|J_Q1q?$Xv#0BcJ?l zRKnTuaW&)gi{~#i)gkj4VzZ>;tcW4%bdx4_j9_i1t5QR0sNfM2g>eiY1AJYiSuaWUSYLuRSBcj>5K!9Lx*$~REWPl*Ym ztbYf7Y8+DPB|xniWwu1`F=QOcRkLuiEVw!lczhz59{}KL(K8O2$P)D=Y2y$;CdD91 z_Fj1JkKA8Jk|=+3$m=c*vQ=1or_oybUaX6reUdfIyeTK&F*7p#rMz zz)*H4L1!@~{eU+>EkzB(w1%Hj<5c4-Zae%iuuF3WKFS*E?d0`hzgpUGf68(UHt93M z;YlJTifgj_@J2~cxHXQ-95H14TFOBTc8d|ico0Lx>O8|*c^IAlh~W(RJLp7Ib@Ba( zdMJZmWH4RU%3K1EVw=!Q0gw&^8O@NNnD96JdKL9kBzq)@br@GGUm!@O4f&ZMBe&WQ|fF5j5vbWQ`exjAeRbkc*HPzkJ?A*6`qcW7T0&Sz|4VpgDyiYn%nm ztiqE185n|Pjn`Qc5@!H;=)5scR_C+=93(s&7RV|RO$nCOHT^j#?7U1`XMOUV*1Fr< zxVJDFOxr^;NMy_)&Jul>dEe_^F@)?s$o>TBdsvK>OVj>%!7Zi{ctvt{muxJ1;Pec+tSNEHRq1~xl^QjU^ z^RATv0#FkP+?OK6m+%9%m!X-(_#><5v> zI{FDJ3?-`)?)RSHsN>%0F7!qyFC9uP!gps# zk&Ls2ysNz}y~YfpWy_}M|IkdNcb5#O1U1bmt}>=!)|N-pg*b*9klw3gc;;CuvXHmd zmJ`0ufKRho!{?+(@h+S;_}=$&E7u<&ks>5W?;aU`$ko}t1F zd84+R@bw0~z-A4vNmF5tyyqk+GvZ8mnXpLXU6cU+wULTdjJiPn!`zs@A0e=ugrg4rJN5!SH02VC(7!=d)Cp1SZn$YO#=>JhNe@I@1~geU3| zP=#nQJ@CA;m{00asR#G_c|LrOkJ|sDE`bPt(buDJU)II3rlR$f@35SUL5lY)Q?S-M z*1JR{HL~xF4ODA-99;~Wn#y+&9j{vrAw{fkocZJ5(HI?__TA+$pJ6m>b>f5+~7P8BCDzZg;N&hb*wt zGI#z)m-uWVSjsJ&$PIyo!GkQYV#%xNj5izH*WMv+s%E7vz5PUcCS-WjxhmH%w%%sS$w)Ha<^{PxCJ(@igCTWc*V(NxP_Krk^8ldvh7{xRz+z= zV;=euxgT7uqHKFF);LvP7xY(Aw!K>v7{?^urlM?nw~T=sshi<|%3NEL9| z`=v3!wK|-&_bW@Hu9TfRoVE8y8>cFz*+nYGwD)H#OU>7KyT<))88sfVD%zYHmuSo$nzHDPYmY|qBH&dO6``6rKjXmN$;TLWMtuRA%%Tgy5 z?jq%s1TKQI+JRGC;_rw-U<_AcKxoY4{Cpy9S;PEF1Y&=Hgzae@K}J|1i+C0~q=*hQ3#&j=}X^^twem zXqJX0kRk<{NRX@>UQj1I z`}$Im86&c92L}z9e1%zm8hk%0eEP${i0r%ZOXF@|M;tKAp^klRyQ)yfzIGkFKU1h< z-(a?Jf~GR2sq98oW^^2p{tU@g>W$A@;_*J9uP#AJH8jkd5#MI*!Ob6KdgLukz=Aoq|wPG_$Jf1Feqm#fHvSLv{2Nn`6u2&NxaVat*x)Z=>Z zB{e!vnjE)|7T9aB3YMERos6sv*M*H+#kO?_jvn3H3pFDfZNuU0V_-=<0o^G^3{`uh zow7Rt$&ih9$nF#ehRV_iUv3tJ+W1Amo;UE*rYgg0B7)3jo zA)*U2PFH9;%12~Rz(^>HQYDuvWR*fv92L=)$)`yL3OUG)e-x+jPbBwMdCXR1ZxN@0 z%#A}F7MN9bl~(i2xSGt+_DL$zJe8HmnzKZWhmy~xyjYCLdeH#SAz|t7QASxQdNh=L z-p6sua}DtP&*PLw95p#lUivOdqGV>1b!qyZJRqx5Pw{}zhTL34vt@evoqUy2 zqglUVuh@b4Z}M(MMiNA`o_a2tyvK%Kk3l-q?p07Rj%XX{`DyaiHgxUn@PCus{R|b& zzRr_8T}{4T13Y@JlzgM&BZG-%3-nYe`KCD3QA&M+Y0pn^z$8DYP}E?c>Q0}6J`#sI zJPvI(V53GoYN2>8((GW7nr|dO9!H7XCm@SvA<6I?^Ak;3Xkjlv7~`I{P)gWsThx0$ z`Jh7410}L9)zi%6=i@CY^RCru*qr>5J5H;H)R{MJ(YV)b92W&Ix6{#kCE3Fu>bPoy-@J`)raxH2`bg9==knh~Jd zBW;W6f+A#!9uy(di^iWC6j>&4Wop)qB)%~{6WK&c9^ceZmI+*$+B}XI*>8ZBLUE?% zc2J=>8_Gyp8ObaYiZeBbuip1WHWY zogPO#&+@4t_1)=2r5)AePG_b=aTvMNV=(6fLWC>&=;>ds>q`JE0xgK#>C9A)`n25X zF_=;{JimX;oo)%Tn8=;ZOy9&cB6oTWrZqaZm)5AKtr0V|{&kNh?oMY$vZj;Of=o)5 ziMi81?Ps~uW4em)lkdjd>HEPd(~q$k{Q7MScX|}Ulvbi;Wp~S+e!ihO#dRsuFl)w%ce)K;7k8)ILKer}={7hg?oOwgG3Fho2M=(k+u&{M z>$uZZWvo9p=1#Y$Tldv(b9Sf4DqpltvEAte7vZJ5WA60+txR<~BuunS#^N0fIwZN% zzchp!T-1n^zKSq>-I|y?y{?dOQrw+hk1u>z%$*+R6X7iee5sX{2rq9NbEn(X-x%gd2`&I9up;UPdhK}PA9O)bI0B3qy=|MsukweZi>6pEg8>T?TNY5 zV_>CauE%nx$8aL|4V28d(_>)8k{8(KG46D-plTHK_7i!BZ`7!%ZmM>r+a;}mYWXr= zVlj96X{aFMPG|9Ls7>W9yuxGL=_F4{CX~bCbN|sI?oMYm0y9n%ytN|kPGf*_S+qvm^(ctSmeH$0xQtM0o>_SOYBM4?(|bFcRJ&^N#y?8FYZoP72Dr( zr(1+OuaCRaku*mHEluad$d{c~Fo$wFjz(yzFqNGngB5{7EHz(Mt;WHf9>+0X9d|nEndnZx zdm?I*)ooPN zdB`0GAU%!}xp)2I76T4j?sOW(=_jHC)nDGCGyVKboOoKVZo%xss zWtIhK^9y@}X#)&RgVMRdBlkm==sC{3|}hhlVhZd#B=F};*KVP=pA`0gN-+Wl*5xjLtIsR8+Po;kzPr=bS;Hpb7AtQA+GG z{cMJs0M8kHm*PHw!322D7*H40^GS~sZ$g`lp;QXlbL18r){ZrZjA49_Nje93PR}l- z0M9f*Ob_GBwjI6UrU>CC_bE~#^e28fz;k*|&;)o+&+9;nIK`}<*AZedJ}gSlXAXyO zD6Dx&Op)}_Wie2)TffM@6G!0WIL1$YjmbjJ5Tcv#aY!1HI&z|CF|i#fM>^7A7=tQJB@7|Ytq{Ucy^jfE%jF5N8*) zR}c3ka5)GGg4(NxGXb7adlrs0>1_f$qxQG}y-k2;)Sd#E0MDpB24r-XSp0ZL@{^Z= zuM-1BeT8@x7iyVS*=#Y782WV20`4D25Y%o3g8O>AyoOh8evC6XY>wcZKRn_Xp^n!> zb&XZKg<3+z3)eP{ReL?$ta!E8!`=6rM>UDY(!#MOy|exh;sD0SsCF(u?`~f8LPE7G zz{C2DglcC1223+P#)_^pieII9=u88I2;riad3yVjw^H&i7L`BnaI9ZvG|{E6C7W`i z6Mee>jEegGG=wwUCLy>rMK5+Hu{;(`4UGj;coJ$KN~98>wf=oAcrwwYUqymdd+T@Z zET8!1b+peKxe2VQk@my)v;k7_A9O*l1a7tjp=R5E6ZT|)fpqIn=h*0LQMRhuCyuxv zZ62E-R^Iqa#}r&O{Q<8|MUm!lA-j`q5B&gXEo66Mf0V9sWLYTc6Q9!~G>;!AwkDM| zF4Q~}2|~Gm{T^)M5vSlGa;}hM!v9!4^H{3#U162)3dzz2I$5p{hoOn3dO1>iv+p{Q zaX3;tU+GBgZ%;1`{t?-9NlWlfPpHI^+8b1f}1zD7aZ~)DPvP zm6DH*|Lnmm-W2 zeCVVvpp}M(LdcGX(V-3^dmWni%kN^W+-dOocc??&f>{#nCZZV5rc_B?wZlZBO(K^kASTdm9MC8cl-9$yF#dZ_XGJ!LlWRMqM zWRp0(o5=Y66L%Bc30||Ci1}E8VxH9_wwvfYk4FUcZXzldwKBDvh$o6>HxWzVBB)7N z%`CVJpe}Y3xrSiUNILLtqO~y4Bf-fCNs?zB2V`??ZpPVDW9Q=c6y#!JEIfQrE?ogsLVHOXLrS+ znHT29*Ul(^=RP7vooxF;t({R364uV@ZXqH9d+qELl9I4?#t^l3_W6ru?Tm_?P8g9r z2fw@{r!Z^6OJ?ni3ZG60fwMuwlrkmrWP3 z4MW+h)P^ClS!}~l6ryOu5CQ9M82SY;5v-hGHVj<_TABU_K|{Y4E4?H(42{0UY#4gP zqVS`+n+-$zelQz`{BUZ?bR~JJ9?~S0(&~$X>LJZj*=EC#&5*8#G)d+47Z2hs=hdxLidR%z53#gR!KsbtMEZKWsJ()#Ivq*=!h!TSp6gGPYre zjI0f3HVlyk9D>t^p@l0^Z?s{EYJoQlk)MRBoi+>+u)z&O-qqME)c#-i*^ZwM-ls_n zHVhF1Zy2iB>d_m9PKFH}cD}^=Fl-nKqcV2GO~o6A2Hu2sHZ}~I{wP3AFScQ5D+JJn zA+vC*Hw-aYZy4fhy|*a?yVrWvYehx9_WpjKXU^F@3EcO+zdzr6KAC6E zGc(_*XU?2C-}$ad>3o5WDGV`M1SuVbp(v9{fjRHWg!PQ9gOg8<6_W{~3PVVtaxPfx zC=4MlR!8Mn_J(ir0ticA!k9(Bh*#$Mv%USzd70$% z(Uf*2a@Uyec(%fjsoCor9fcuR%t<30g&`MtPqm{kclk0r`@er;4?h+U8JsElnP zb6!UjhS&%hgLiuzg&{_R1eI~~9`jXA6oy>vm@DnLy9~QS%B3=%6&7FML}7?=4eN_3 z44I7P#T14Nk!F7l5``hAGX)%Ke+&|Zp(vYa3bkH7?AQuJ48nj>8INy`Dhx$gN5|*< zsKQVz=-C{kI?4W`A__y%Ao-fLEv7IOrEOuSUl3IoiUk>Aw+GBqUKEBH#IHp;*N&Ev zB`v#}Nu3>C{4Abi6}7KNc$n4>WCtIS?d7{c7gMGs~#*P`c$ zOh}%rXLmJS^z=m+WmR8ov-YBA5Ly3pXVEiRW*(hx;;whtO-sm{xIVTVHAemmq7gFeA>$+rc6+3#EWteFfXV2 z7ct1NqB_)BBv*(27EY`NNN^_x=T&c=E}th>s2ZpOPnUE3p8RvGSIa?x71f7iKU-BF z6ju(?Bls)^FRH$h!MDn6sj45AFCDsii+HVSIV_;!R4z8j0m`Kwi4qiiVi<$un}AqitRb??XAFNs;$Z-EY#{hopP+9@lkSpOoKjf&U3zcf|`f z|D>*~mQg_dDV+~Z|JP)rBTv337GW1l|FPpU52=>{6 zAnv%s5~Q;FY}V>purFN~W2LVzVRgJ)>zw{Uv^a*TG|U4iU{0?E@{2kmDz6(}bJIUT`J^PbvLuZx$u}s;Ii@7^ zFE=Hje}&2Y1LS^>EB8g+AR=!``VZ0Ev+j2qW2I?~Uzu5j_nT=lnDdHT0`p4J|3Zqm ziKZYoz9SmM0(mfSN;~YhIEW%EB}$<^W=jN1D~<}mcRJATST3j@?W&- zzLpdH^uJ`)?T{S=N`Kj^^TQ0fno^t+a z)s1__Yy59nbu%3Q+g4rMUUJX`rF_S#nuLe`eKf6m@3C`O>Oul-Z~UWPWA!ogHsBAM>BRY_QBkeZSmhzV_rlXRfzhD?idK zGgbcc_VwQ~O^QLg{8!BNCm$+REZ=7H51H$Z8)VTV^~!(GT)(nTt9q$V{`=nefng5yWncOg4imP&u6E|KuJ?&C@ zHG-}i+*wlG^{{+iyq%jgCdKVcG3vfqajMlt;^gep>2o0@`_rjP9grMz?sAwf&XC!l zwZysGX8JxS3$|VIK*%|8SRM^xIq=n0mbyU_r9F)4+%DC_Z$sedR~qBg+CQ`^EayvJ z=7vea4*pwG+$TcQ9(AR7lqm*3AU`NSUFLHfBuJ8{UuNAv_qx~&%hGl&5_cDpu=8hrnC zUNv3bvdh|IU8$q*#;(1(4hR`?s*HIPX~;I&o-b?94ZFc(B>hyR@AAK-XC#xp3)5G4 zNBl$71>(MDTRkI(hWg{I;D<8#rgf2bJqV3EqSEla2?256c+}uWXIQdEN>CL!*dx@@ zea#{GA?1o3EFOp8ca$q~cmi|k@_3K>SvCPW%(G&Vqcsg8l>{MKut6p`@gv*dyr*OS zV(Dd@SA&CcQu0*k=JK-dm_K4;Im>P?FT;KtyV-chV%{n*M|UYQ^a>AU4la`PSxDdIe@V|s zcCRpfg}3FKrdN>s=w1PPRIf~xUb*YvvP+YLbD)}M`moz<_X^GcH0hO3hIv$Z#O@Uw zK}6)}VJ@dvkj&{7Wb5<_{dTXwuLi#u66HI&naa!7)F6Mbu3ouCF6~}{*X|W2Wv?V5 zX<%@%++uG%FSpq2W8Gr2d5g`I?D)qi@%HoM)crE)=N_5GIWI3;*6&9!^{0Fx1>xUl z*?LfO#gap(Y(5lbt2tfzC7dP(eY^C>3As6424JYp=~9&gvg_{Agli@d_MA%CyO410 zO2T#92-oi;+;AJ=#)E{LUL@T7Pr@z#Cfs&}aQm->J3OZ&qdQXxcjprBDIwfjNw}{+ z;r&ga49;#hk8>ua&FBi{#O8;yQ8EoSwmL2=6(Vb?i9= zFEn#{4&6y|IG#6idXDHLkKQ>wtA`P4W)W%|2_rWV>TV{CdWJCiEy9??gmL-vBzf;J zbLidBjaPH42q&LRIAt5*)V+k$?k1f66yc125a#_tIJ4E65O!7tVSb3PU>4!*WrPTR zbYV{Kg?k8%w-FXSMOgeAVadmYrN0rDS!W@^Ik|-8WrP*I2qyuzgs^cQVbcYK%~un)JWtsAF5!~Hfc~S|SpCPS1-Kg9 zo-l3*;kb!};};OduOrm&C7kdGVZs}PiQf_?!2x9{d33I#=NI5YJF!+r2gn4}kXVwtTnoO8~Dq+Dg!r7Y$k)4Evw-Op3B`i8b zSo{%T$@he%o`sUb(CSu%ns$WRO2Wwggt|JysA+`JXAs7$AdJ0;Fm5;DxH|~PKTa6` zI-&j(!U;bSCd4-)zljBeNu3Fks|ZuZ5~hX$!&f#ER zHSZAC{)e!x#UdnMUq#q3gRpTSVbd1E=9>r?K18_apM)((2wOdik$hV&;o=IyC4&i< zP9R*ih;aF4!uGv{D;^da!oJrD z*B&8U2kX>xhF@PuxM2Wc{}jTFXAy2%MY#EL!Yy|aZheVx+ZTk}Jw4B^}`VdXi5RhJXayOVJKON0xK5LPFy zfRr`4gta{h>qZjR&mwG?PuRGYuxTe@^TUJ--zQx3H(^Wexe&IsA7R@_!o?E_mz+en zbRprgHH7UK6Ry}#xbjKDRc{h@d_~y#3*qX-l@PtR6=7d{!gT`)*N-9GFq5$VEI@4z z?}w4S*WhYopN)jR*9fTc%Vp!H{4+UEe$tZ8O1&rx^mZ944sR2lk#JP_F@bQUyoHAE zND&9SJz=ahXp!QpkHxrRy8M!u*c5VGUzi$nN9i@~ZCj`10j-($Zm=rf9%o zq2WG6gD-p#J_LkevZ8@WAtd|`0>Fh~wJv-Zm-I0*eM~_gtoJpf94Ap=60M;%e4@{- z8UpY!v;w}CErrA7TsUEbhH>t{fpr>L zYoLS6hJ^9LLHjifrP_wpxP}_i}m!p_BNke9f%ZA)1toWrNNueQMw<$K{2hIf= z@+I{~kAw|4il%)Yq7z#aMd=zUaMF4zrc}b@q zIMq!!IAKI#)_~v(-S*p_#yAq zq1tz$Os6u*Vm@y89nt866Gq%HxOoK=B;d2S=GJTDmDNi^a{tpjV2HBDNI=fa<^ko( z{?)cHJ~)I=gIxF;=-{&9TyRie4X=l;`U=Ds+{R+Js5!n;9lXi86(u~{TZu1yx_ zAR=H8ha0QJStX7aJ9l9?-h!a`=wMqujBf?r>%h^$W_cL?^c7Q-bI7VYLn%mjke)p<&vZtv#pt4OfFaIAipKzzEV7kJea^@tHf6B{F zK;$af#0pGelVb-tb2XxbF}sJQ&yFtejS{YVTy%7SS33pnd31q${jUZ7#3`3#t$X`Z z0+Wv_@C~wW9GDm_uv%zh$maLgaq#Za!D~dy*>6jEN@b5q55c29WwtFzMLsWxQ$^2% zGl>L>S`PM;zV7JMu`hTb|0)m|bDIc~P7 zpuS_$^=RNa7WjLiGr30`#uw(s`g~~zYpUG|$>LFAJRKT$ARwkJ(d(Qj+nAOC+gnP&HBP`y z48X#&v7Jmv`T-~4Nd{m>TzqJ&9B;~#z<)Y{tW{&a1nRHcT(DO5RmDak9wp1K5$i18 zf6%WQ{fL`A&D|=E-MR_a(c!AaGX(1my%10GF`DmJ^4OGEEAB+p;IA*x(%m!(4kD&l zy@N(q5F5hcr=n`(A(<-mDo5%@@t8S%@t|#5Jsu~4yPQC_Xyc1X!rkfSoN8b_>Qn=M zxfu}mU+%c7@ndhx$e@Fo$h23{dnoYX?1I@N%^KBpS6WaU(Y*89%Yk{$n? z;XYjiZwkn7vF?@;5F76>UB1+bd-fGFjQ=ISeyBI&c=Xv%$>ndE&Sm{CGE|*Ey}9%R z`T1m3l)MXrRn@nIYyauZ{hdGzShZ5WEceEvXUZhBdDw*VCNXPW*|+%9&VDP5ou1uK zE}1uS;yE_bKfIz`n#=O!-IQ*L)%i*fIvQ(8#ZIe*@CD{Ynj$Q|XiIIo&A${i=uN?fH2 zT})gbEnj|A{T3IeC96fQYi9L^n_yNqxEW@ZDgEsHd70H0t~hp9DQC?zaiSiTaj8t% zPsmSpv_E7fsm7sgWwdRSh@5$G&j#_a%6pv!iwDae$Nl*omwjr*+ql7^-%VU!h-_`{ z^R(EGjNN!6H15$LzDo$t&pnOzWB%~Xl3%H%4Nk1*T{$DF*ylvl+qO=gpS8 z9f^}qgo@jc&*eLS?M1PYPlR6O`FigqIL@C8j;duZNED1X zk+Djk3^LyKc3)O3DKK7^{UQ-A5znNt!t91;m3VFz&no?hxXzypnLH8lnovO_q|359 zB<5iurt})&L=$b|Svse_3XN_5Rpk0t>2@w6uB&b>VQX}QkTW6deQ(^PiQ1=D3o#|^ z66VeK#4S5tLT&)LO5fuSEA+%QV**Dp?L2YK+WcK_+_Kk|PyKVIKb*QJ!q}sGgvL|enFtxN@l=`KbZXd{2ua4Wwam28v?THXJ{+x*r zJC$njB{C77B*oPGo%krfYMd7m?qP@HqWS2_@!t}D)$`V|Cr7C0=&P{tx>~Q6E?z5l zvfk0sylG$@PP$F*nSJ7!@|!r$pZ7DF4&RlKVrkGR_qszc9ZqC(naG?Dvt5KU9o9oL%gt^a5SKXKWC7JFNVp6%J*bmQC@!TVxRr(om zoj-f3dsnDeOxiBXHcHIzg_!b!t2mtMs?nVGAE&wwE+RVBohjtE5QeF)n@4`qREQ~m zxP)=4n=T<$xT9C;I_JigD=(+ICJd*#CJd*#Chdu-?iTqCo)6In%^P;v+Y+);3Q*sy zg_rrH5Q9z0rd;K!45vExn$1jg$5^we`nz1|^v;9{TV1s&-QM?DbK%%i>{dK_+B-#p z(q-m|P8YFhZ*krwayDD;UcEsgMQ01OxZgglw#m@ddmJ9`4@d7Gy&%DQPoBj7K&IPu zdcD*hdkXj!rq%iq3C)&YuhM(EU|{QAkhWT%BW@+=)p3SK=JFox%g_qNuYCN-4ZpLX!-Sv@HojYvM4Q&!s zZm|$`|JJH9d!zQYtIXJ>ZxB5)Y?@SNCa6vNzT5=)xjwndN=s9|8aZ(4Nu%oVR#7%e zU6p&HguMyx8sBVLZhEa;>_hbVT$qjgl;DGROYTOAw*~R8^qpqO?~v-;ox;2U=4#(0 zNf~eDVjH(NqVLOnKmxt+?)QBo-#OwFa-pblzC`bqlM7{)r{T@bg~Cb)iPtSJ7fLHX zgU!!{;>vmO26Cai@)W#y7*&rHMbJky_) zord3eraw794ZrhDe@eSF{LVA|EsE3dJI_!g>XllShTnN6FTeA=nLoEzG6HHf5&YU- zN$un_WbK2kI%8bMHyT4CA%frBD;Y_CzQj;r=o3WnlY1pKWY>~~H&O_8%uWc}Lv|Pv zTrXZPQ{ngbO2#t$VTM1BAST7n@0E-~4w(#!;Mey`M!N|7_+CjJURyH#^TeSq4ZbXK zp#k}{c>{UY>9a#Vvd%WX?;dBCT^!bqfJcXPf(HbWW%&iF`E;GQIXV!MG zdC+G4oV@n;;jbFBd=}oyOiThQa%)(ArXw}F&NhqfmOs=9+rr-U+>9tG(I_f%8Hh9z zF?NgI@Qn0EzsL^RwC>ZNt($Qc##^?yTlF^m_)8Knz?5~Heg;-eFp{_1kE!*aOhBLc1=oUI0a&*pNPOHSdSTj{Ll4_ZRa)nqKGe~18a$c5Qv-Prg z>vs-&2abxY6QWNII|h!5tOdaXEScyNF}a>BYXvEDzb(*2BWXe+<581wP*clv2{<0? zan0i<${C+N^MFJ?fsxsI z2vd;^ly?HF*-S*_6a-CV5bxRtkcBP%F-U((952K~6nbb7WwRr<={PV|cApi9a%Z1D z(E(tW{(Z05jY=k)w?IS(;MnrPUZ~MCku~k()BrQ4VtvYJk%vUWz|O1LcfnA#hsmK*zyESF)1QjWk8p!WbG4qOc(8u!Yh=bB%U1H{k?}Z)MyD4iY z_*L$?fqk0>$#mRH*nY8Aj`d;ADRq|06|Ly1S*$o6CTHz)4*zDU&qN)+s*XjcgJ2bj z$d7>!tfEYm%G@Y9&n${lr~lJZRmaETv(Pyi@_GL!NSYiAF_OZN6l^YOhe-NC9)DGH zWARP(mx=s=L&>^&L>gf1CDx!8(HvFepJK=)=x4o6jCW<< zESTgXzJE(%B)f<%4+)XtA|8BMt6&QkktcIRFx5qLmv#=C-UO>6hn^Fnr7Ol-Iqnlo zcM+G!q1<4Gi@4=)iNPUnkNf?|wv{W!AmozeA`T!)>lne6TKtDv4N1wZSg6$X;vJS5 z#<3wTS>}8q>y)n}FH4&Y%VRPq2dcn}&lVOFf7%QYrh84Mp_0lH8ie1E2Qo&&*F5+rrTk0Z0@?)LD z+DC~@=wYfzHQ0{u+tYkG3ey4Q$TWr72g&6w;?Hk{D2o!A?I`GPuodtdK|RlF6nhD1 z#wEJM+f6(P;>+J9D{MUG#IN%A$pYKH@Ti`5NrKVUK9zd14)qd@ydyuE9BO2VUy-m( zOpLQ-x_VPC!q5PW^pka5XhriFkwZwhh%_f#j&hSa@;1VjHcgV*VUe^&&z|D$mQ`Zv z+4>TVyXZo>h`fRX%Z?$;q>6M!8O~)mXKp*6zM#)LRz8tR1fAbBg)J;co;0D=Y+KY) zMLswzzx2Er51C9>B`Q!w{D`}raq)1-Gzs29f(v89(Q+#C?@>GU)EotxmxH6&lXL%f4qta48nYS}FB`JV{1uX94JNp^b7sVWScpmUd4asI%8W4LiC72+8;cP+T^?JZT9(jN(Z}V{5*iz2Rb&RD zjf@g@dqkv^q0y8Zs~$&DBuAD5A+v^x%C#HiJ@nIrW~oeRR?7+|G%;3CCN)8SzapJA zDHi0a!+XOe)x|7a)5*fTG)1~#^iScyM=zn;S1`AQIA#?sRA;OK~ zdZAJqc?V4~o5G_Dj?Bvt=|a6jAk0{$$YMsU2+g8Ku0W168P2CYOHV10d|5n(PK+h} zQ-rdmoLu70kzBB7h%7+VlVVcJB&12y&WMUe+pIfUQtq{=UZf1O)hbq(1CVoNq(9i@ zQFgY96d}n*wi8EHWH8q#&7P6NRd1O$WoJnI8 zGpGHLC4^~l5-p#|6Jl#7p9*LZ6}cVE7N&`^oF(jG(#`UB?6HB3wlWNqgizTyZ zh1e@ev%%SDcG%BSff_U4N0(kAsTPvfGYPxTj-3ceX0B(s7-pJq98zp-nz!9ZH3-_& zRG1y~H?m)SjH21$Um^U0Shy?0-tv-Ib25WWyPhB?T5IOVR*?)c4~)NMNYz_F$>%YdXf1;So9hTEinnnS488Q`0fR^9D$G1BvL1 ziy5^he9aLl(j4XmBJ+n8yt#f82;+D_B>8Pi)y#;N&b$NSQbkrE?TN9V%5#Mc_Y~J_ zl8Q~|nwflQG~;feJo9R1nI~<_F*rIo&3^2zML$oDijr*qkkBbHqNNwah4w0|K<0&- z;~~_%OrkYaqyp^trYr}!id-mjTg?QDGj9MJM+jk*)<77!o8{*rh29Pk5zlmyc6s#8 zLGJ2-a*NiS3L%l>F~ZhT9`cp}JOs>!C}R(&B-G2?=XSiF5Mnec5m`l2F(}Le$rSBl z3_-K>;V9v74|(K;J2JF3PSp*FzJ@rZ_DfjZz*|;I>*ELlRVmdR5iS<_$IE_=UM%~y z1uFl(IQ7{hT0JiYCav99`BWD~@q6Q5mv0|&J#Z0`v+SO@RBzD~DT5Gkazel-8*l1$ z(bu$Ud^5z0eOA3M-e}9J_XZ-HJEGYHL@C!&Lm$&>mn>EAS0?9ttx@7J8nByQlOOfj zFBpDiPbs_fOb;2HTX~bH$O>~S{>mrY6 zIcR^XxGK>xVy%mr!jCY?*BG((7A9f0@Gr5Dn0%sadc(+f3XFU|hd7;70!SLM_Lj9k zKHf^5`l%E~rSYn(x$=JrD$y}w?d^x;I`v1gjuC6`pubTICbttfMy$O_)^Q1~ZD2-Tq9&3S$c%Id% z53*d25o^x}h^tc{BkLHk_I$iW#5t^E#M<+jo9+FhF&^hR{Jf-f zO}a6I?C~8P<`}W|_}yVFNxEai+S5|A0_lzsYfq+4I7X~JtqsuvW{^GaX!ae{Nt1fX zUK{MmX0V~yL;iypscCoqB^DQ7)k%FsR{&AnF+LU!V>v~}uTF^FDhchhjz4>V^n7bM zwO@FN+;lqO8gY56B(#+z-~J)z_htCc6BffiX^zJ={GSyT!yjbx;orz&Il~`U{$-#N zi@IpFS>D9G{g7Ozt|t4Bea57*chE(0ty5hI%C9pfjlDyf2gQ%~7^@!M8WdZ{zju+b z>fx>BwN!vsz}>@thkN+1mxBMd;Xj_`a;$)RK0sWZI*F`f1>Ey-x%7y`I#$3vpSfAb z3b^O+9M;Upb*zAUj-c^$Dp-5?J66Cw-?$SvR=_>qAC81H{#-can9ignK@|m&3xaj+JoFXKvQ967D(tkfhbAMy_Ke+;arQHLN`>94q0T zZ`=tSE8(8+k4oTJ3HSUMOJHV;M8`_F=hvfx94q0Tzg$62b67Z5!ev+-6*en2ERG6u ztc1(3aD}m3(j6<|GAvkubjM1#3=2a%v?V$$NTmH}Pjz@^xu!ZapudV!T_z^jThP}9 zx>e@8(iboU?h%tbS>B636uT6jF-eF5L*Pje3gg(x&V#Y_P7$o>s_Y`$!nkKF;-wx! zCY;Yj)P#2-Y9b|26l79VLW&tpMu-uZ{oQ-UrnqMk;-!8LQTEuxc!wcxPrj7*LP;De zFAbNwGeKNta^c*`U$Z=6MB+=zLzmB6{ozhDOE{ ztPL!pO9Dt}1B>Y5XS?RTB*x26u}~CtceH_9wT^hi{I@!CGHmO~vF^=Ks$Gv#fIOyX96j#4 z0LC$}GI;f~E}S#d4*5kF!8kg3F^*mYI#?iN?{7StJ^r`!9tuVgJ`+F_qj=G>+~R482qW zN0q{j7K}y$-34opR-=)?|57OZe{Ltt6f_d(6b56l1db|&YZoTVd*AP3Nw7&IG-8vc z%rce)69<*V$;c@yMQM>fu}XD-B|)$EW*7-{)ku2wm~}#r$NK+&s+A;h_dn|O!Jo~G ze2hk>-9lH9*h9xGl-ko=|$!p&_6w{#%f)`M_+72%Fr z!kzVmyJr&aIhAnlLc)D33HNU#Ja8G|!D|Q)-As7oKEk7q6As=kBcLMV@t1Jb`i!>- z^9~cv{GD)CasXlT3kVB36V9$8M8*;p<9q#TTly1jJ%MoBS%lj+67IN;aOazZyFMe_{R`oqj1G`;??A$R(+CGv z5$?Z<@Zg(-hdv}c{4?Rv#B!v2ESGSw63})uZ^O1@hVW|a>4b4>3CHau9Djf?{$)b_ zVZsUC3M8M9N0``)FsY6(xq&ccHDT)2glYE>roTd%ahNbub%c~zxrEu3ggGM#Cr$+v zpUpv3966m=3t8OaMd$Ep@n*u3U4*5#6P6t!obx$h`QL;Ud7U8a+-`)GHH1|s63$ye zIR6U51@{wHzd=~@DPgUa?X`;Hb*%~OI}tVvB5Z_qOhxggQwW>a6E56Oxac{;mQM&< zy|UX@QM@gSaB&ggl1jp*g9(=%N7z1ta7Bc0pogDDUL5;aG81l#Q6e zDAi#?%`!smR>H{Z33Ueuqh2SB{)8~*C&IX_t|FyFm^pN4=*X+NeF!JdBAl|GaO#zW z({3W1{t)4emk9HY5YF^;gRrx53G;gr7K|mFeJUZcny_#Sp>Zc+(Orbaj}exqGGWaZgtdPY*0qvd)rt-q zDhL}xgiTWkn;QvRwi34PAzX4Bpi}Rs2z{O>^!-pE?nn8GlYIlUyJSnh%MiTY_*ckt zP-U+c@>kht?lRRy&Jpr?Su%EMbdfiVk5dcU#;LBok&?;%i9JPz>eOwTK3%?WcIq}= zuOiOSml03aSrVgDw^MY0c$!A_J9V3OQWsoQG(4so6Sj<`W5_X59J7ZJDUp2V&CrdHs$Y5cH6r*4<(ImGRH z3Gqt3k+@UuBwnp=Bks`$iP!4aiP!5-i2Lo&wsbtUn0J%o5z zPa=M$&mFhdx+obr-?u4_lQ60BgCKd-^8DFT0i9Xiw+Qf)!m4{ z>7m5m^(5jSdLHply_)!!zMS~C-cMB4V?=HJlW19oiE-8+M32>?Kl1Te?TGPKH)4V{ zl$dCZC;F|Eh{@JMVhd{{G1b~ZOtWqwwzM80rdzKNGptXE^5c2(8rrE_E2}jz%j!gI zZ4D)6TlK^otAUtnEhgq!8;JSV4q}0IE3u9B7_qJO8nK=A2{B;(Of0k#5L^S-&|nv z$GWrfBqPOGLhd`E<|g<@-xQyd|1?_UEBF@_DEduQHX> zC0b|ry3)aA*ZJVEhg*rQ;jSxji4Ew=4e*hJ)9o6$jF%HK&*Uo=%ez!n;ReE}S{0W05x@9YHGmMZ-@+1Og~j8m0ggMOqbJy}(H@`NrvR;B1XBXmdTW1otby)0P1(SR#Anl@`bBk{FA%f}uh4ip%;d#fT z=fL` zM^!y2CB|P>Y7660!Fxq{CFxvzhVj2Dq5iKBrSv^<-;wW~$)3uO#M}8ZaXR43XeAaz zl^Du>ewK(@zNwm4_lw8e6n*xhJ93RagHg+Z(Jzp2eXBq5CydO zjrg27=qHrM{)^vKK7`@OQw_@UI{`AzH?z}vacc!)%URHXUZ~6%F{#)pGIg^%-=N zyJg?&HLy-f;{0*w&2vS-&?|FCFm}0*G1N-C$$|^Vr&@Fviqli2xSL@9E-k%ulmx-f zU(56^#?D{q3}JAzDm{Ccw_SS1a2%{cYoyD;s^K_Sh2>j1&Q*0W=c-D#2!V4|)~YUN zaAqytBMgpLS!=qO<5i^?=Qv(vZRCWF<5kv{(&r@}j#pV%b}`4RO5YO($E&QXyO`ru zrQZmH&;HiFF6Og;sct6|Hkkcg%qgojdTm6=zH4IP}a z%FHjtrVdV7Wd=&Iv4c}qnT4g;+`%cU%%W0k@ZgkHW-;aBlvQRH<>Hi8D^0mLW!1`} zT%5AXY)!d1WtG{6a&gM4RUGBwlvOJa<>Hi8W?OauPFYz~*#S6ZWsPFJaLUTMD+rD5 zEVGHl54AyPbY~@TwlD-Vy0em91T?y{Qd|Tyy0coi2xxR?rMd`cbZ4cx2xxR?wR92C z=*~)a5zy$);&Z`#R0=|)J1f%_0~*~~ty}~&y0fxe1T?y{TE_?u4rp{|r*_Z}hgx@T`)CaRXRHv^ zx^p|iZ}u;PQ0va^fFyQ0sCDO-y9lUt=axkYKep*q5Nh4I74REDnf;24TDSZ-S;(k$ zi*E$fx^a);C(A}at=qovn0BWT(CRF6)-T_ag0p@oa=urk;H)40K2HkH`q3Yskb<** z^d}^z;H)40iD@Y~>qoyoGX-b;=ugT{!C620lk-z>){p*_b}2aPM}Ldr6rA2E_SlTqPf3Jk7%-h6;YPxl{ zu00@rXr_-0LN&c$*)hbLR6(ew7o5v*l;6%V2-Wn0^Ny8I5US|~=QmAZ3xjHU!D@~V zw1NskHN9XnitlHoq5|a@3F5A2T-3~O5AN8lI9z1wl`}V4iMwj3DT# z7xa&{FEUg?=&2VBXv%UtsUY;!3kEd}QbFjc7gRN6?F7(MFBr_G$8h$;Q94 zYhDny@{l;4vH2N<+Iqnh-V`XG3PNqYU@FTBRt2H9UND_RVh15ATZr2k8>~U7tryH@ zUY&(xKl{5QQVpihnm*#KWK5{87tDy2s#)|PRM!h;GJFvvu|h`DIS_(Z=^&KY3r>s) zxdt(LX<}Z7n8-K?9rl8gV&YzC7V{8dqCM-N!CtTyH4T=vkut1eML9J0a+pJdyLY%N{myCJYKdoGx*>JF3tZG2kG{|-3 zY2u6u;*@2(6h@_kAQLr+Q&hIbEDOyl4h?Ou8gR-o(3=UOtSt+tECYR;2B{!USqA!{>ajYQ1li6h z%c5Da+A}#DD%&|_SyacO(?PII({fh^swgvB2$k)evMf4279YVX+c{-fG&vSxB;k~0 zAlO`zbIP)4ZY(|}1#!wUFqEvTM{vrrU5jH?B8XF#ff^<-IpUOMVT)*vs&tWj(7|Dc zlA6&t>k!0Qhmv}>gLz2etV4;pO-YQwS%;FXW)*@`s36Wdlx$%du1#1rUa~2JIO|a2 zT7+OA$tcBHhmv)%WHybn4kar|QxFSlhvBS4iCI8I8$cxCtV79qCP75M9UEsIO3dPc zKjOWMk93?b``w9ZEJe6=nzFtV7A_V-(E}$61Gx3u57}3~|<>Ml2csKaMqz@Uh~8_>rir9a~5YEO86bg z%oA*CIz~9oI+Qe!h)yBAd)WIbh_enQb10P!{HT1GQ#DVDTZs>hK^%1`nGr3VpX(G{ zsvwR!l$;m~`W;Ctp+Mi+B$cBMB{P}83_BckD4AteZewuNp=6r9jKfiflF3m~lIM;%HgMhPRg4ksN- zwnIV?Cml*IkKVmt&Bxw{x`WY02t&pVA zE&{eflIl3tn%?$iIT3_qkfd>}JvJ51O18AOe8hxhkn*~*r9;IJ!yx6OhItdpN2S0n z2nJC3D3t=cAjU6mfTu}B*aaycJ3Z#61Da`S(1X4cGt|}~nln>@GGffOjAmu|T!4R+nQa+sd zHCPp9k<}yygwEagsMaNIDEJ_GoujzLm=hHHIEBJAmygGsH0iK1YroI+&rzh z250}8Hiy}da`P&{rZOwY43usHE7d#!%zl(lWDsvaE=`RrnE5Cl6zihnVdbN|%I*(X z`6%zxY(#Xx@v0z>S9Ko1{A1ly=a-<)1HY1Q@Rj&1->Gts`BGkat@%=3xu0LkE78K8 zDnH`qY2G30WT9f^mEvZ)2s>x(f?ee9>AszJ4;Gq^7>8U$PZ009i2fixaS`)HRiOKiQNqr9BBK2oW8>xX zxvE5i)z3hXSI5G@s`~p;mR2!Z)o(+sa@ z*jX`J)!z)}BsX(|JY%|_>}J{^&gpLEE-+`gnBYDzJECP#!J9zra}jrfxZOqEij3}d z5lM*gP?WG6??tfBMp+fS81;V9MJz_syx}4?f_TeCOoxmQql7K_ZV39KDQgGqLi>H) zG)M)#5c6Gg_HNYU&t`1>P6*eUcLla6!giu zw)_22Rt57Q`JjvF`KS<2xrk|q@v4hx2jYDf(Hq34F5-U3_$f-*d5=f5-(sw3&?#Vj zI!2pTsey>B7_I6%qC&ZDW+LKri!ny^slL+zp+hbjvQ_=rXrb9LTGbCg`mme%NY*Od zPjNF_k?IULGZd-jyO>}PFgv3)P{IBnu5}SZK-}RXK1W9PxQG?V=iw+}H`(z>_gs`! z!B;@MRl ztxpin^t{nePy%jXPCa)UMFYTiLtAxF_Qh+TUW{R`;P&1icr zu@ELdk1Z`^%RUI%C%BnYP|(RS#-2;ofu8Q7&0P~jGcSzMs{UC>T;gJseEE_C-rr1= z!#(yn@|pYM)IeEz;vBj2XE`26r$Kj;W2#AGB}QCYE73RhL* zd^L8tUoJyOqLE*c%e&RzS8of;=>*? zv%D%5ANJ_?c~bFVkN)_CRD9T@KOs34ANJ@^OiRUwJ^KBbsrax*e^PcTKJ3w-oS%vh zd-SKYOT~vh`dbvI;=`V7Iw&i(EEOO2$jgVl6jVj+6vw0PnG_oV%deIXfz3yNsZd<= zf$*x7OM5>S+7nf9ff04-_{*dX+3((~^_P4L|( zjpl83y2f)MGK_VNXOIZPwS7-| zsd8*UB0W~vGey-v9m<5x$3#8FuvLp^BOFZ6NWwL)DO`aRA%mZ!JmtN&PL!O2t z3k>;$kjhuwQVh7hAXXjP#{1StX01gcnmm;}ki<>F+I`9&)14 zdzowXma+Bz(B%%<1H1|RqCtLg>DZKqHTAVWZcqwyetQFQeL{Z%@1-W(qEF% zvOtVkWyEjewAvwb)^%`D6zSHb@=Ka;p?(vO zQNJDX$%qww@P+@OqLh#_?`er@ylBV7iL5g#Ix$w!iKuAmZD^lK(@>J6qVZm(Uy*{$ zFa?3j{L#Lw1e(=5M69x~SsBgbX1vU8Ml81(h@Z-4orSJZNvodms^i}Dsl-PO~m&_=Vr(EweY-7_a4cW zAJ_7Z$VunpJKdWoI|kYt%8{3Ih8OdCcuqH7xAeZl_(NOYvCyl&_}i!A2b;XcVz^;c zOptL-&v5bBgO+6&%rYdR41+m*Se&7AO+FPnWxOQUM8|M$STeZdpFWjb9~;h&{49vd z!j-h#`@KD?U|+mS*@khY6VZ_iWjy8KN1XC8p7Pl|DNoDWa>_RLGk(G(WgEg$jF&Nz zF5h6Or+<-x^r@98To<5wCrI~rQf_@kMnIn&xt2Cdz}Rllx()NoK>xSJf#4R|svSy% zKW8y~SR@V$Ns|sm+Q8Q`r+-i&&t6^@zN)>4MDDN?Wg;r9WFEueFM2lKr(Q#rqj>qL zTyByZNson;qE`}pYIbXpG7gu;l121SSEm%0xvmrE`ipmAfZ2bEv;D=7I2VG6ll>*_ zMfxA&FBvYLbcu{d7600wB}@-t+V2ogm3YeVfOq~9OIsELOdBVl*T90D& z=ZG;u$tTz$3xq6ZoaN#xe%V#j_z`g?^*4qre$pi%u|pyPJ-dEIvYT9)rd*O^LJq~q ziZtoIu`+k-k#S9%XIxS9=IN+bNPf*5sZ(V>*yc^uSz4Y=RVSXNO|?iEHq~D7{Qsw^ zI-mHYG}HYYBGGCv*vN*Bo7-GXpUJHnoBguMd^*N!1v2MZ`Y zGOu4ixM4Zr#)}9yT}in4TEZ>26K;EuaQoAQJ6 z!UJsy50(=i>PdJcNO*K4;ou2`$7cark3Nksrjamq4`JNHgya5AIQ}of_{>ZssP95J zp_VXVCSl@I!lW&P$u|+EJWrVV31Qmrgz2s1uw9SVGrACF4kyf-L6{vO%(;kg;%)&8 zrxY`tQ;PXRFgIr1Ap!C`w)QE-{HZR|Ii;B2=pvm{ifwu$C6i|zf(+HO?KC}3mi|54 zPS;`L484?ivVLD;^lW>I{+4)}wz6?C2^0wnRu;!gm}Gvg}7gTNW4k^hj^=w%SL{8=p5o*x}12A?oYf=*Aeg6(})k~ z1;mH-X5yoIFY%zhpZJ7+h4_^Ii1>{Df%u&E$=gQHwlC;x;!C=m_=+Atd{vJozOH8y z-_-Mo|Ip_X-`1BB-__R>-`9^2KhSRyKhj?lKh}xzk-lf!Pjw#gbKQw}SPvt9rSV&= zJ=-49FmBbe?YDXb@jDH3Vm;gbNAD(nukRrKpr0ZBsNW*~qz@B+*1r>f(aG}0)wAud zx`6nb?o9k$4SvV-w zvu(UpKuoYY6BDf}qTd=zOtxkbTUd?6RBJ6U&Du_EY3(PbTMrO3tV6_13+e?u+qSYS zImptpZI+cyY;ED_QO~y7R*;xu9Y@TyP9)}83yJyGT4I591+k5F6S1xJFtMHW3Nc`P zL@cy^AQo9ka_*&P+hVJbSYq`hmRj}1_ErP2%vwzBU|mEkx2_{rSO)}q6rJ%rVcxrh zGruOB^%r4&s_b<3C|b~taCTQh1mAdj6fHcS(0C$YQG~DFR`Kc7{=BZdI-liie?c!^tsX&Gvz)N@62iI%2!Vfz@u z70{~b(f-N{2v=QA*zo{i=OMzbuLxIL#fZ7PfN)KB!k!w!-V+J?@FBlP`)juouDg?P z{fmSfJ|pb+$rtk;?QhH{+|-G1^H9Pq(+RgOCfs&0;r3ezcRWY96ShBkw7<(QiznEg(GBnQ(9zpgaftXTfr5uZkS2 zR$gIM9E>XTrcs3+oq{JITBpJ6-%dkj@oFf$xzq5|cr{`(p?W)^=2k-OlZ27)5bC}n zjEa|qRgX@ivk7B55XRMTwbkco$-D1s;#8`Bc$MyNj%N)pTg?MM6H50p`w@M+kFtd4qvnO%s{msF&{$@+13fcPb;)N4zzV!ZP$0j&h zn0|O$3gX2!h*#QvYou|4c$po1RUF>S;N_--^A?xV?r%A2S<@qNxD`6AC|5-N!O~-hvh3y(zPn`VF`i*j+2u2pNw#YwtWZ73Hf>9XP|7boemJd}%*bgkNQ zAmAij##C;1;UrzgC^ig^nP*(eD&kOG#$AknA(c@bg4%a>@>W@_W^IFWIUK$hjHm`% zy+fR;Ys9GuLGL>|g>mU1$ixjn?>ndS>mc5O^S(H$3In_vWHsIlLQn(G>C!Y(7M9ZT zdkybumD9CpkP1N!Jf~Yz)=mI5@SF}90$D5u9U}{B;JIlGLbiM>Q6Z>-=k#vM+OnVq zp3}E!ko+uyd=AR#2a&NVnFN`R8hGBUSYt3b3y|rkf#=n+=yVXQLQn(GsiMqS(J~!1 z@Vw(=@e!;t9X0U0$*~Y432NXu!RC@2HSoN-vG|k}f*N?vP_nTO3PBA#yG64~u=hhy z1J9{p0+S=uz;jz5(6nfObLh2a!5;HAP;jkz8z|V%w}C3WHuNm`h)Zza7jgkjtc<+= z=4_JhcVVEAmC>%hInF&ER^X6}fU;KLJr@CGt-vQP0?Jx}AEShwHFAS}1D; zhP%SRs#+*(1!l!)RSRXUz)5Zf%36Vw-3*kq0;jtfC~F1Iaxoz&YXx>htD!?7Xf9hz*{Z?%36UB zql7IP%36UhnzD8fl(hn1Hw{uDC~F12YtBMhEAVGCwie1-0j<%UMrJLPwE~H*MyrLg zRv<;=>1D@(vR0s_n}M=cpun99%36Vdn}M=cpv28USu4;%;~{QKhO$m z)kQ#AEAYOHfU;KLQx^ect-w!F!p zl(hmoqcxD9J_2#Ai-59L;0_l7Wv#$HE&|G0frq1n-DFVK3OpBORS3#jftOqal(hnH zx(Fz11>SZMP}T~36eVoQP}T|@Zpzw0P}T|@X&R(LP}U0kr#TB{t-xQ+*jgxS1uQeW zAWYRlSu5aoHCio{wE`{7Tw>xtSu2q4W}vJUXyZ-=WvxJ=n}M=cpw!JkSu0R(<`N?r z%36WWZU)L)fnFw+nMgs5xdh5uf$1*V+%-_v3M`D#sus#xfh8^`1e+Cwe$M<% z6oSo)!Xy^~n-zupAeUugz-C2ZiYo?eR>+|{%-<#kY*rMex(L{;C^XAl69YCY3R}8j zz-C2Zx{H9#ioy&R0h<+tnJxl0D+*h=2-vJBWD)Fgz-C2Z>sSoFhQ-U$t~kZ_vTWqw zR|rcpt6mpxKg8n825eSjd>w+#iqbr$#XgG)!DdBizKej(iqZlX0h<-2ZCnIwR+P4N z5wKZN+RjD5W<_bhMZji7X`zdN&5F_@7Xh0UrNu4+HY-X?Tm)=Zl$N>(*sLgRA0@J| zrKLi!Sy9>%e*3ipHY-Xyptf12%CK2cTJ9oXv!b*tN@QV+OqRJ|E8sVR{2gVt13yKW zu|%igmk86K+2bD~ENnhxoUGGe^C1MA4`q!k)^rKWnk!CsRXsyf{YMsK9ntOnmFrC2~qx!#D&d=jI;Gf zyk@}WLkK1x%9b5Ns!0@r$%nFY8II!H8HQl;q3pb4WfOwQhqCjVrm%&<O8dq*G z`B1i@xk#9NDBD8T6&EHS%I0!C#(L+-cAlzkBW@Ln8-lHevIZ_RW8onfc_=%X4+s|v zBM)V#a{U)&?J~m1L)jTzbT$uyk%zL=uzAEr&q4|8R50>THV^wGM+L#iLs|b=i$baj z!N^0|fTpayTL2>uWrLaqsSu1jl(D9!V@%j69T$rd(I`Fo;4h z@=$idF&hO&9?B*(PsL`3k%zL0v4XNlrl2tLP&O$Ri|L)jGG1}LBWBHsf-Ol4WYst}AkluaiA8`7$(tGNBJ{TqUjhqBqs z0b5RHf*OZN)hCEs#YnL4P&Ol0pk^^cuQJ^8RSUtYL)j|Uj1BZA##IPb9m>_rF9|gOJ*ck7Uphm$i zBIb)OVi%Ezek(^{2R(#Czm>I|l@K)xjtW7MvT`JeM?qAvFLCI%vWD!NWZ@0r&~N1! zZY9y=NC=01E60-flhG{MNbkqEIP_aN3L>)@6vCn3%F!+Yhkh&TV!cHlyOhH#ghRiT zUM1?q-dz>Sum*!gJ`qkMcddNzt5;>-6?9Q#1U2H;i=#qI$aPlTe0 z=}76RGZa+`KC(duXnZB0v9aW1p!J*H9F0#GP+Yx-e-TwP#-Gd9_k>jpD_}ix{5Arh z{t$H%Q}i``oA8!wIs_jC;X<`h-BAn`a(VOJ9cPkLK)Lwcm;&dki-{%f1f8N;;3j@{ zC+HL}WU;0!rp6XQxP%=g6HZY9CrL#Pp2+7UxlEujj92i%*@bS2>e)s0>Z?KIs=EX8 zi_Z?Ld$Z>UDY?8s@3kHuoZAX@?qjU#D2Ix^3@CaU3+23#wNSm#gm7|e=#5RpT)TXSZ)lQRhOkcZ@XU?46~oD+$sPsv#hbIZCyHc; zGwlJqhLfXFPB<6W-`4{pmA_~}sngTcTuRyGd1%Uqjl*SWXfE&u0I9??>@c+m)v9p0 z%P4$`MP5bQL5VXU#%9I6`LP{8Zsx~5{CEr>D%=sD9Y4l=4-a<-$*)I3Gb8%z5r>oc z@>4KpI1z1+k{wYcf8ybc1l0}V&Yeyf|4%qKIBhuTDPTCW9M$H~Do0((!tG8(m7E1C zJPjZGQYLgwM1Lt0z8*E7z&|+~NA#ClQp4{iBIRLP<25q-l~7U9>;8aGTzU#=Bu1o$JG@&G2tS3g^Fa{tgVy;Y6FV zDz|VqereI+NO#9Q;l#rZ*Js2>peKjJJEQI67)@yJi2ef33^g=3d?=WAk@-|ae*sml zEOx9m9y|ZvmrQfac^wgT3Y84HLT^e=XC_DU0v< zY)GBKQMXa?t1%s+%Oi2_rt?^zO2oV4*`MB|+m_cAk6~!W@Y%7Ra6P+P;u(C+rxcIXI^shgZlg z;cP=aMbp9Iw45Ql$BU<6DT-c2-NZPCK7xlr@pRTLN8Nec%Omxpl_iJ3B)nut302B> z2ZW0`__CA8HOm+&FXe3--S0+JmvKa8BE=DuaYQOQ8yw53jh5zAj`Aor=JZrX*5)Yc zVL6nM#W_kQ)ver})C5kdq!2qmt~PwtLAXRZSB*Nj8ri6Gs;t*=C=mUpiYYEbQPiJG z_3X~c$l{B1(eYpxRbq6fN$+=~n1SbWE@H9p>ER%!l2qlKzv_UGhe?vZaMOc0N zmcJn>>xB8qOS&6{yf+jc#o_|!pY|Y+zp*TSisCQG-$UUqDeb!K*rA}~N8uxJGCm%o z|F|!d?1_(pPEUu_1*inA3Z;e*BR}NU6ukbmqxeThWETv@_xc~Y1#A}%p!gYl6sZ#Z zwR+JzepM;iMO-phCPt4K{~jM@KjR}2!_?2`eLOUjjNqf-(;x8d7Aiqw=`_AlHO-wK5|)dN*wJ+Km?55g`?aA~?w z_ij#S=#G~qiXgWkYdR+?LGt(uk8>jqFXe#6y6z)!(6LScu(q%Xx-6$K*waiYoDy1BvUO7^zzspVKq9tmyIE&f0Q?@w^IZa za(N5EZzr6{?Wl_`gq0&Z;_Yh*n=Hrsly z1qSp926TVE0r5Mk9M;pi8(Z&1ht}&d&Y$)$xUgT)i+4}gPQ=n~kA;ea)(>}kIjT+# ze~-ugRroH@=m|g3jK(?ua^-dp_Y%3^MDAgc8v(gfRdf;*{S6^bMBh=dSMh57PubtS#&DO3mC@q7+Bl~`}A)p7hebBHWJ+{V(NYpmw|W!1a|X# zT#(^`1sT2w)p|jM)C;nYzaabi3o^oAkdd+=jYfO{N4%Lo;?0b9N5~?^po%8nY+!L+ zI;QSMxp)+aM@Y;CF`vY*AYP-Wiharv9~&6)u|{V|$b?wvI2opxaANMUUCyy>?vHJA zqsI}lgxQ35IRgrcM^(nuL8vRf1q4$VT!@FTp+5_3=;I&2pP{|)Z)i$68{vcdFs%2X z=ac9tXzS33$Q~dir5qP_^P7h;(MVYovkt|$S2Z1@xiuO89??c5#a$Echz%Mk??Q3| zl5K>n#>;ymmEBpp6!Ax-Vjy~nze_SL9~S(W>O--YF_zHB z!$6D1(2{*Yssd?4i70P}&{!=jckEah?dv?Uj~xtVeDoNQ6G;}9g~k;|&|ChyoW1`2>Q5&`lz+Ih9>1wGUF+G$Gru*;PXB#b#Fs z`78ylmu6kq>>8;(pS9D4JOnS^4rN4O6ubC`kUdy?i;$;Lc816v%Pww~+OtSrCuAuF zZXl_WTw)25O5Vhd34I=l$=ZGHubn2(1t=2woZAFHxXra+=1MN}B{eCM-%v6UFQw$a zZe&kx;rn3WCn>1pEf5HI1U~JAO4$Q1gn`k_e=*Wp-A2LG&Q;F^Ik-egd%#i4N<;)Gj1?gV=|}X&~rOQ&)nZLrpyd;v^DD ztjk#>)&((*#5N$VA+ZmLn@Ai5;w}>Fb%-f^RiaY;Ks-ZYKM=2yxD~|vB%TDZltc>a z`)?9mLHq_nwduzF<6d$s<2{f;16%;f6{u;mXHf9SsBfaXATil6xvCNM%fVPJ_w^v7 zZwjleK4>Di!%mE3_^?PQc@}yJFM~1(%caOSM1(T}Rwf5Sar8N`f7l5=ujsFkj`qdx zjtH_@$Ydu**C$t8yI(iHOSBn;@X}c~N!X9QIJGLtSe3ib>8y~qbWGBfm7@!%P9+Z; z5muc@ua`)^jMTXg=}tw-4Ymqvdi@fWoCqKF9Tjw=f-b&-dX?mDF3P&XzZUWcmi*ALISi{1L0U&WHbNHTk$eC^;TO z3*UqF(W@!NaVScTBY{>#uiWtvR8hTPUgqpBSey&SmRPVj7wihsomB!07UzO7t;K@H zxnOY&6$=*Uf=NExsVL3`6B-K^=YqY(2HmKji?5(w#kpXjj0=`Tlcl| z&ZrO@#N~s0mC&n~aG~P<7+OT#5*SGOwy?bC(+l+3sHwPUFnA?Ml)}Xl7wH^0!Zc7I zU=t$Uj6)+*#>3eQk?sKr=QC`;f;)VdswexF{S7g2x3e>W-*Ehx%sR49VCBSP^UWHinoEAH)4Y1`-`4O!|@$ zwMW+Ir2dYY*aURKFv>~IMKL~CZJtJ<;(ZhnXM@M}a;l{`14Tx8POTL0Mv+j6(?MK} za|fE}n9q3tq?PG7&!dJ`3wL(7ZnRotoD1A1KSGV0!72Kzh?*amX_tS7)rTMXGo8ll zV0(&%QsE7dY^m@Y*B}WDKZ8#vyb+Qm48^PTPx6 zCq8p8>TKr?s|VnMi0X8hZ-6@x)=$9Runf@LVeO4x0@jJ`f-()~jEFzOD8CJk3KdF7 zlrMBbqI@BfvRT`n35lfM!n_ZXy||lGLP}g-Ap#QRZzr{q5ezz)%_Jk(R!E8cw-`w*?k`qi| z1CMi3kaLcxk`_~?Ud4`qEH{xeGWHjcI&pB*>x{xy{%-|!UW4Smp3Fl*0 zhZ4N$osXXdE#q*O$T$S56ads2tL0?(kCh2BiExhH3Nb*ENrW?zWO11@u7pVhjpQ7x zN|;12$Z?KRrDe_$B}^hH=p3m^m_%rrKATB|bMzkIsn|~V^rMbp?niAliO_yYqY!z3O6e zM76yE#NSvm1TxJ3+b#!jKZzSU>HNR#gCJgH&CekCMPb{y>&Mi`B$j|!M&gRj_-l3& z1zqsU7L2w0CVY5TWXCpb$3yfHGVox4xtt{xZ3lqy3F_Jo1+iS1cH^Dfw7sRN#*@9q zmzl;Dp7yrCp^kBZ@~gJNI5$O=HHyfDD*ObNJBl74^eFsR2cvFR4)HG_M#vD;r7l*O zUf(5DCH+XKeS4Gx&Z3eoB(x5kxHyw9YTJE`}LV^8zER0rWNt_OV-`oU5DxAp2qqhn{xNIWt_(hmJ=$6Rx0Kv=+OAqYhUvDvfP{BBP0Lnky3RjBj5jE@x--s{Z zS%f1$&03=Hwvdg4Dk2lwht;N$U%m|CYt~5lXxIsT>XS&zIQ=5a!QDi~#-d3Iv8}Ui zoL1yv5Op!hDJYlF2lk2a4(6c4(k@V2oD&B?!iV<;kuw#R#yx1Bf?B^ainr z#I7KigUbsL@xNT5nsl3qXw0wSRoQrcx>soXf;MB(1VM~S%@9W02|OTpRq+0a9>euX zbF3=HW#xSl+f}_FoAJ;i{muC0wPE!c*8G2dL%?57&=0xj?{~PKc&8SWM^45#4#n5M zp#&X8^ptn88R8NEO-7kl>pbP(j4?gD_IRrmQjsK@O zHO2hiS)sYJt}4E08Gc}rbZw+~F=;(JvcBI=#Y0ffhYFnjyA>aaG2BLa^Wnt~;t(0nmLrSrMHC=14P%O*MP#k% z@x|ATcJs)sClude=!wN&1FxM!J=;!#H^)ARM+%BiPU`0~3fh4#@oiGT_ZgLN!eS%* zW-urgRq0@S^3jEGc~U>gQNSly0{u z?dQnb%Y@)7*b2`>O%bc*LnZsa6j7gCYZ`1n%56ZxZ@^L!KUA{()rk6w-^2G_0}_4% zmWueHl9Luh)NX!*zmIl%AmKM)sfZsc`2mJh=?`i5F>V7Aegl?@_<@&aqQTM`W)A=L z8j$cCuvEkk;J6slXupTs_jh|B;WuEZh#xBX`pXfuiQiz~1Kb8A{01x)@k1p~M}wJo zWtnS-Gg%4M_M6SSsR&Nvz-vU&;32<3hlAY)B>V;}74ZXCF+X_Ww2WjXJdfMzE2PigJ0*+D@s|wS;x75c zDSfqDOz|~+sQ(bROX(Pt`DQ@p2Pv017nkytfX1+wpu>X-GIU6n|2G8E!rAauVUf^nGaj04por39^#mWaX{llA0?Ljso;{AhU4pCCzfP> zMQ!>LtZ^Js6RV0d<)A9Z2Bkj>YvC&?JR8E-gV4gagR*V5uPgikY(<%ZjF|5wG&AN~ zB<8EkGN0~5_LM!t-*3t0tWowVS6jPDHDi%&4I{Jcv|o!YJt}KIj&8<&w8t=}&|b;? zn{jhuuPg%|=v__r34H=wGYA=Um6SM3s%l7a+4z{LCM5VyxEosO5t9hCR03$hF4|5XSNM&25hfkXdUF z&nx8&nOc5-*bZt_IH;vTQw$eVtZZM^n$6mZskURr=3dTbjYH7NtPr%SzGqBL(qXB+ zPW`Y>+kv@SIr2&Rwy^?|HOG;wn)x`Br*V!uh1XBdMnLf$D$?(PP>4h%e3(V{nNE?N zh)i`lrW=s8=tRVF^A|g%>B9}nTDlodGeR*5A?C8z>z$JHbfd}YWEMJk%420EN!y02 z(wAT->9Oq}45vA_ zNMdimsX~lM$^WX(5Z>cE1%JmWJ`Z1O7BI)@4t?oHAMed zfpGa_1tniX%>A)~lKT)nF5L!y>@poc@apH-15oPhW!&-gf`z??_(QRECU5WhBQR7LpwQqkG*PUzh78 z!ACBJh;*XJrV1Xw*Er1Sj}M)Qj#Hgc=KBeq6GDX7Z2ON6CDRk`^Y))* z|1qIvWD+$@(x>D5Y3IODG`$p>n4ouM)HR2-NY2~d?O333G zFCmZUg#0@Q8F#BWT0z0}{Qxft+u}6l&Ge|-{0fZ#v7lM$4d=n5l zA-7Pr<3a+=#4_7ps}O1lXL12<wKN#VnO4@Hlen9CYWR#ZP0-sj7hnEoOHfTKogi;+=x=IML#GA3Ubb%8Cnu zETYAK!-Tzysn5QFvPO&h0WS0|L5t6awo_19`DQ?t2h#muRDw~}8$=Hf?KzTK3?B!Q zH7LL`)<}Rc<{gNw0cf$M0l9x(4R#A0NG)suBqeVPdz3(ntx>}9=G6czeH&bIgBEuK z+LHblOS>rudWzx{J!Q}E_gk_#Ym~jp)z&JjW-PL;0f&>N0cdevJJ}k57F!yC7Pn9X&|*si z(Bixruve-l1#VBG#iwo_Q^Qc1z81s*Bpw2BB#He&oJ9GGy|Hn;i)gX!GXNCRz)Bmq z*0Md2VpZ`?usPsiyEy>iK=Tf4K8CvpXt1h14>^r@*$D7xY&#bLri-h#+>7dHjRI4! z*hGN;;%-~pFssJZi07N6Zyn33E%!RDxgYGE)EvLn@;j)82AIYv5&?b|i%&OF)v<5D zdCbb`JksAoc%}G`KjIWvt?eEhLuEsvrewctgy0bcPzzuI()R(i3spf?mDeDj=WZE zWjob1$C0a=A8;o31@I%;1dTbYABHrZ?0e%~-hd9lF z{qbj$AgVUS#6JXK$2&xTtv-nWvtkOzMg;gQC^&^TfW0dL@gY)ZKh;1{lrszTZ;S2=GfN2N7V)G(>=>J?8B{%l<@w^V^?^_k>Gee^s>Elb3$L-xK_dq6qxBtA|na+7_70E zaL1cWxDy#kxF4e)t(Ofh*o;lhDUc#ANfEssU-0YRG-YdsIx7jPpo7^kV z%_GUa8~!Zdj4Cg?6qsl134;dH{o2QHE;RV|jeIn?aSM$Gdq<#s&IuaKCOqd#z5zm; z8x8&%&ko=2qQM=u^wHp*wlHY$I?z)34&Yh$*fw~VQE`OJL9=KSPgGVG2RS&L7J;z~>Z(S9I0!_0j$}Rq8r9Ak6d)RF zB-o~T2V!dg8f<9*4v<%a-2&l!3tQl5$=kvnCD34NlsMk^_tu3MC5p`yG|>6ahl^T#F05ve*X|>0uzof{=55HrYguEniOL_(6#2M8skdIsVkJtfeDz zoV7t3=O_|F%xAAej?0l6<>-XS@fIE{D@h`9T(qs%Y#t`!U4k5U1M6E(^Fk26fv7qg zkyILyRIN1+BF9z*kz-aY;@F5BzX=5r-q>qHUfs0BG@GTI0^etCBnIVQIea=Z?rJRdnW zIkq6jUP+K+Qy_Be6*O{eN`f4lk|4*XlnXhYiD!o|8R{d)MmP&O=EzGYK4Xw$mM!FX zi{}h-OkQdR%0c9K4$48~*fI@~V`sj%|1A3xInHl?Ch3XGV1FXVCqWYv^sbD$>RF5A z{3cXNcDEr26LbwGceRLu?J#t8^_X~en92EgE*qa6E_pVlBrop{f_ZuRRV**l@~%wF zr%(>h4i5oWGV<{tn31QKL#(NUJf86q@`z5z&qga_vgu;7TnTx6Z9=a75a;aS*2gj&LxT!0%nc)r-kXzUHT&0d+) zq0wUR*t5?zL5tZ$(BiH*5p$!( zr#u^0d%9@xj(hoN@wI~uTHFO%N;g2+MT=R^MvMQ2IK@SasipKOlyjlQ11+?erSdX- z;hPHWV9?^wc0h|C+TEbV?9M}r-`o>u@vLAx&S!^DL*o}&S@C(0MYK3}p&uDB^_hEt zU)E^xbpZ)Mi=#tgYB4G+HxF`fAZ-lBDX6Qu9sOMbqCH1akKyA$vIYfM#u^DQ#=HZu zH2^KPG$5MKtHEx81F3~AfTZMYVUH4Mu{BC0WO+5fN_$`A8^K45FG6j4KdkZ9Am}NI zGdF^&ToE*bhZc9E@W~L~)Cf0F*s__279R}_R9KJ^^Ie5z#(aate3e<|qjX6|_LM!t z-*3t0tWowVS6i#Bnz6{X2B5{32B5`x?PP1f;bdvR;nYG6K#MI6K#TKgz+O2GUmtpx zylJB2Zg?mLmFX=(JVRnX5U-I4gZPm06%S)Cc$c8XJMV~B=i=|DI?&MLX>+2*Q$bX{ zjqOkeRt;IR$Rb+Y5e*hYn5qQzJF zYE|twLA@4Q{0YQdw3zO&+S=BtqqSQxU5ib$c-@`!7PpPKYTS}|$-Z0wW$%ENd#Kjj zJ9eMV@o_D`+iGZl-8e;}#fM?>>2j)`bgdvOFkY{KWjdh6S3+i`_?bWA#8|EEF_jBW zw77I<*B%FhFphs_ZhLGFnYH%tyj{+aspa>F?VyMj|1)Tcxnhcy?Wex`U{CYuA|C7DTPp1<_)wf@m=- z8aOth#a+-&q9!{@BU-$NVOa}6w77W-Fr1wbEk4y~vIax6_*ReABwD*i%=)Pfc>8Eu3XZ@!a@7L(fuE#3i9o{tur9D4xYG~ty5Ej9(B#a=<9 z#ik@^u_-O*bH=8W3oX9(+Ng@`?4!j-I14T2$V(?JFlaH$7FxXZYX&VQFEtb8AX@w| z%0aZ)G7Zt<*el-tv+Pf_IKTawq%VTO1TCHnO-#_cO4xe^YLT4Zf=bEmdVw&9d@Z?a zL~`Dm)2rp7FVJEp=M7voqQ&K};w^lrNcRN6ygdCTmX~RHSEl8|DF?K87jPvbKO6)z z^7MBQYbqhfbDwC-6g#35^7GKjm~4WWELTDvUz?C?zl2Ys#nyeaY7%my#YF2HJ%TGo}xJO8qLr-DD9!e z!zug%gby^rM^f0bnTHl^$Sz^A*Eb~#iBqMvup5gDeWOLRidzGuL zRaVVdWLpE!VoL+i;=FdUHQ;cvG~jS*p$4GEmIk23c{O0K+?fgN6+T-$WFNeM43+8e zAigJYHi*zn5Zyr(gHRP;1osTzG-27-ylFxVTx;>MPd@vI1q3>HD*tM|v(~R*LWVBTj+U+8#Z* z;6#A?4s-1>4TN##gLB*CAjqt>hj-%U41-#Jf7lL+2=IGBQ;Zi=tZZM^n$6mZsV;zv z_bz$YaMsCHnH5%6Rqq{B9pEl-+3Q3ExIdVyl_Q_3Z<{sLk*k_>uM4S}oFft78xSPi zi;DCD5RZe91AGqId|uc(hKT@gf=oo5hs`1aJjSrBr6U5IwLu!^9X0G|0ed9^{8yvN z>YoVk9FLWi_z(d;8#_sltu7cQ@l6vqfVB&wqr`Ch$|8s=h4~%>!j5-{09$<$0cOQg zj*STLZcuPGZvcA%hyb5rSk?j%0dC#`s8i7i5#U)ylQkG3z^{9(CK2GyjQMcYmHgc$ z<{<}_8bhQJa`CdWWI=$LU^YU4cUa#=fXQuy0H1&W(MNzy-aLQ^uvZcU*c6BWdj*XE zo01^FrX&ckDdj?duf8U#ZrZ>{fQ@h#0?d(@p7ORqfLXQ>;4j`a2rzl6!SC4!@IfdC z5n#(SM1VWLqiHs!NZLwjzggc&TD&bCKyo5WV6YgGU zX3W=aI?b0IGc(~%tWCJJkHRO>VC$Y*H3>J-;Aya)B;0p^kc9gM5Rz~o141X<7K&!x zG!elaP0NNexd1hC;%2Xe^Q{|1<9uRX!XOOU=MkT{M{P*FJ`Gp~02M z_-JtB78(uqjzIgI6Ev7j1P$H?r(D*lyYtZC`-TAxj__9x z-Ampy@e3MvWo5;nAd6`5@L4)Opg7Z@@<3Um!OH_Rf(D+WW;=_Q33PqCg!WmG9RT&GP0-a8UB7tHfN2pSGn3+Wz~#Dwlx3^wln|@&TA)I z0}dxk0}iJaY5*E+X#g6WR|EFSYqtgV3en(W55Ng@JFI^(h$<3yf>@u#ULZCGp(;vl z3A7>_Y}wbK!D8TAizjICO~K|wgDnw*221k}sVH8xz}mU{b28;=J>6a-$6Arz)Vh&Xz(Lg ze7cdUiqQe*F(;?;dfRF=x4B143tz(#I@O}q+ z$%Vxt8hox{S!W>8;H(YOIPa*Twn^-jXz;y8lhp~);Kd#*EAb&3d?$92IJS!If?*QT z;1|I<29@cJ_m8Q`Aga1zzE^;-;~k>GR-Z(JSuu@cBN}`n6l}s9z+M}o!8aO~wE#qe zo3{Y7*a^|#SBxfWFhqm@cg@Fc!hI9CCgGk&?i!JBx90S+y>xRzU);D>!fnuC zNw|k#jlG0B-ekg^$VkFH9>QM29nUnCa3?Ze!X42G_t|J>%r{%imn-2;tWCJJkHRO> zVC$Y*H3_%8NdnfBgxi5Tkc7Jyge2Vaz|sk~g`ycWxZVY4!kJuvnnr`Yy%N@YWh8W) zy|SRmy%PU3?-freI3;KnU98tff`_BkhLFq;S(d@#)kh%fgxoGf?m~*Pn5e5xrcODvi)80UX?+(W1d^Wh#xR`oN;+1~~Sww?RxmU*r zyv>*f^$C5L*M#U`qpVfV>*)76|8C*aAmO-WK*Kfd*Tn#POC_0}iJbgG+ASI~=_qv8y^b zrpiEQGQPz7LdbGY<{^3`V0&K}O6s0L_f~R*3m3v&={7 zl8o#rdxpQ?lFeD8>{YI|R#`P;k!=k?gDnj}gY(+S)_}vw(tyLMg&KecTN;1{=hc9{ z^5X-6+mmSUjKgpOJqYVR2x1_Kg&=kyF&V^OAXG&!Y#i^BU!k+?+u8dWIWcgp#S=96 zxnOgm!Ip?YgQa-~^4j6$NE!_uJ15Yyg$AF3ZReuFbaB;|dr=*&E-(d)O*HswciY;A zSv9UkJYP>vTG>`@xz}mU{b2Xm9KY4_JE(>R7|baW4gM61Pd8Gv#rS~p7^7FfG9BIy zQ4X1v;yeC`Q((2W#}qC&(cts2#A1(+g7%o6+aC9=wFkDYcjXL&T7G}n4vJ{-hKB@h zjX7e9mF=rqvsqg))$RuboNU65iD>X&-E~^oi_;u$p+i`G z+gQi*n&Ze-%_}&QmvfFpgMUDf@E=s9>kf~pB%%vBz!Rr~O*Gi@aAE6?vf1<%J8J4vGM1z~R0K2gh zqQO5KP1azD26x7|rT-?;;3FCH;i^025tsM~IjGbaq8CCgUUrr&XfPAZMriP&jofF0 z$!&xNKZXF&M}tk?ENHM-5;WKphz5HFjRu>NpuwgjXs{{eLWBF@?GWGf@zG!-oP`E+ zq5|r!xXW5@`yd! zyDxRp-IY;S0?!9C;XVeHlCk}aeoV$zPwpC#aJT04YI*338`ny>4H_&7_jOofFX4`7 zno7768A-SwhOn1#$1_bO+=+~ra7T2){SKNL^9>gB% zaJJ6(PRR+k`)KeXM;bJEH)tvS5kZOjrU;g^(cnkGcF|yJDV;{~9BA5~&Sekbr zZ!UL{JR3YC*wjLUZ^X89(O|l`YRkQ-j#d|#g2g5p{G_{WZNsb@S0kQpp}uu2tG3+h zwB~-WcT#iwR?F|88X90Zr${uo^yrwP8>u=NgmE5;GwA!Xokx0e$gC9K@kg8jtF=Aq zx!^>D|LNJI@R)!-8gkp?!?pInUiL1c!HvS8mfs(?gCZKdchD4L#1t#rSG8udwqmO9 z1j9Y307Qd-G%RZYhz2)r0amaRqQUE7a5*|58oaB=Y7z~;kue{xx|w*8 zRfy%tL2aS|Ar~(@OBOVk31%ZSINZ}kgUM}#2LFKg(no_$-YjUaR}wVX6o>|U1&s!q zlAyt+BxtZH z#(ay!eAzKG6YfN2r3B5bS>=|;2=-yVrX<`%gXh6|l5j5pAqlqwzaR`?*@wnhoZn^yy@wD~K6B{yjBv8YWC#Trir!8^VgBRc4uw(j^($Q}zshza^WqM%k-eZLP9u#v&|qoafxPkDMS=#u7Hn#v!7pLk zxo9w5T(z}TRY$7}Ou=Fk4gSjAwzgqbjjIvQH$~q%mQ`Esby{;j*gL5?eyinoPz?<* zol_(l-1j7W3yzAaX&{XAn4Qykqz{73O7R_k#3`^^+hYM2oM`ZSo;@}>Ibe^ax$TjF z%vyVR{xD}4)bjhoc2Govrvy!rIO~rHi(0c;TQSwC!LX8OaMsCHnH5%6&Bao@rbA78 zorng1;I7kZ}UdeB^un*XtMez8a&ctWhFjDgS(yL4PYTA z;$4CU4+bm3py)ObWgx0&G}x4u^OxgHDHj?%9%%4+ z6MQt-2xpNOF9r=}*+PTw_>Vz@$x9XeW~0INCy3(Ze~I$;Y=<-jhwjID`CA?UVut- zt50uouf+e%dqtJc!NgKy;9gxcnC{m;hI668yFTZm!HrvJG}t==?Q>4hU^Wpn_+p%n zJiVM_L#o)@axg|DGZnug7kAO%OW*d<;D@FdGz5@4n}kH5&XtKtj;q^-jlBP+2)F$id;XD;QUzuIhR8cRPso9LWL(G^(97 zC_psUNPr>c9f+*~Xt1RLI6z(vb_;~_Eo_0KC2tFRlt6>6QQ~;Zs{x18F(3Fw@ZTGJ z3u@CRV~y_xK~GVfnG32i6_obS;6W6=3c|Y?;e9D=*~~+O{|Z}CVL?XBcR!jL^DP(i zRc4uw(j^($Q}zshza^WqM%k-eZLP9u#vEf!bt*Sa&U0@0pn`m&w z8G75=hFLYPMm%3VC#`I&w%qHq=6wY*`5jb412k}oM1%Lo;?s>(J>XhFR$#bZ z0n2oFQ^W<3St-8bk2nQZYkN%Mf)fpnp6S|SKM=;5Ps?qOjUltv9$wg&GYo3^{b4&O zqQN%@O)*T@hb0o(;Hd!2{|$In{L9Qgu$ z+gQi*n&Ze-&G9&smvW9ogO5hEa6Ky0*MhhMgdE`N9I%N7TfUrVa0r=*I1igeG`NRh zSxZMWIBSD6&O2(@Q9JfZG;XHfJ8 zi0wgCy@=>&GzdH1AsTG;Ni>)hJvla_!5z@&G}x2`4K}4*XmAKE2FLjtVP0I9gXXR`v!2$A-|m5H6r0|&FR(h&=)tZm2ew0SQ75RSYt2Y zjyIWbCo+<7kAtw6aK|%ECESUOmvBdP!hI&18S|CRr1^3s+=;abxAsx^BpPhpQ>!N7 zCK~(^tS1S#f;*6ey9R_L+)sg}6K)GdGidO?a5EE131@NvYUIStUJ2{HG6K5IUg_E7 zUWxyi_lhdt4HHW(!&F@~n6BAAhI668`z`X(;KnU98tff`_BkhLFq;S(oB=|c8x6kf z>9D#R@9N;Q!GHh8M}wD~YtZ1)JXMZC*+qj{&PId#g6*Qg)KXeV@p-uKe{wE^c$;=| z%KYYxvCv?a%EurgNDV&EpuuNg&Z+AzHfS)r^U&aN`vMI$ z@bEAED2ZuMd7!M(;N^iDL4$WXA76NW31sntAP0xjBrsk=UDbE!ZwZL@9LXdGG^(97 zC_psUNPr>c9f+*~Xt1RLI6z(vb_;~_Eo=c)C2tFRlt6>6QQ~;Zs{vNJ8LR7E9vZAN zi&0Alk<5JMQurA;+F?jgT*JXCbBd8Z$4Fm7Y0GLF4_28cVJ)p&40r=9X$&}B3|N_E zKuW8O>?(VXzu%V4S*7fCuC~@0zatmen>qJ&){X=oY-s=S%R=DOhac z!OmaxwzUnjYMhPuz6JW$v8>v1ztfug!QM&D@mwvxgKB7irJN%1;9aozbR$(axmJ)B zP*dssvzDgOQNxbrvRC54+Zjz(|HOlj@mN`@5AooJ3%vns7Yvj5=HO9a9fQjB z6CfsosCp35(G?)_RxIS$hzA#--PODS>;)hm+{du21t1>Wyaia!PKXB| zU^H2SAs&38$7&J}9>SOpSKXj*U7~uq_I7oKICPP&vGZiXgPCGB!h>r^yLd3Ujqu=W z5Fq+^u*sYS5B5re2b%)%V6UL@U{ex2*pvhhHlhrNa9&CiO@L-O-bYzji zgITul;0sF(9!y^9E0lwHaH7=4gDuk#4~`YbbKL;MgY(;;srTT&!T!X9Cqom{?yiiw z#O6_oDGYR#xm2WDyab_M;EaFcBIOC~HKx zeuXa~h;YBl@aJTxtb95k%j0P*7%?!a7Nfsv5bZgVS_~h@lQk$DPu56)BIX^4tpSLz zr2(;hUJZ5&98WE50bC_-3wxA6gso8`JBR$3ffa`$Z!DpU27huU^>sp8B=pej!f zihGFgJ*cERNoF2%sp8CYplqvoi105krIr>0UJOeb12%{OE3*tpX_b*(WzX^V+p;;U zl)cW?);gSsHLWwNL{PVM_xL;k+8KTMB;-+@M5+|1~|P z2B9)tdR0vAPND~h{Ybn9)*+Oy*bY0#yX1WlmVFH(EC#N%c!CIj5Nu9F*b*^_ur%*L z-Wcv8L4;5IInc9(2)}}D=OV&%a@CfDQ5~%=Fa?WEMEDzb+uDX%HO@wS-z0tOSXOPh z-)YVLVDF^nc&?V;K{YhMG)|F-@aC7t6x~SGr67#+n3dCcqz{J7O7R_k#5u59+haZ# zoQUv;o;^0ZB4Ce2x$RL1nYH%t{9(>OsO9&E?VyMVpAj^LI`5ANj9RlGt!$^d<~VXy^9j!6zMLZw;T;hzwD|?m z!U-TcfRF=xH?oNcTgNaF;ddb>&ckLA5so8G(Jbo>BqE%(K^kWsHSB0SdnF>=+i0@- zCn7xBV`Zg2M1*@>=?!2qCgNT4gz%1F-NI?!3F1BwRsTSA^b!a=-XS7v^+`mS6;n7i zBEmmH!C>A1_5u(QUJoiY%US>;!p&QN>Fk7v@UBLaH5ekoCwr_W5#iGr^Wm!d%YR*B z!&o+P3PLVkcAhMVFjLG%i10uU5hk}0BK#TxL?010neza?FTyJcB5VpoguQ}BgiT2h zVN()B*pzZ1!oOV=#haXcMA!&tA;KJa>9n>65oXy!gr7(oM3}r(ZKaI}4?sEigs^2A zBEtPE;<;`BBEtFY&(wR-^{_t?;k%)UX?Ir%d;gAFq}(5%QZlx2AWYCzOYRzxa<}I6 zvb}V3LSNjtR?2MQG`vwq_at{HaQ*H}MGl=jQ7oG`ca)D|Z z5zg8xi=fi%l`&23mH3}|uc-1Vm{@8e9IT57(*fHDaV|vow4#t|d(Zp$qmGk9jaz6$ z*gFL6lTHv}HW5VlaiFxh5#gVn4XfGiugN{Lj*kdGdW}JZCqPT-PAI#GFw5D9a5>m6 zB1|o%pCF3Kg$N&NA;K(`&qhp;s+(aD;eTMxsY!n~h%meJ5aI3i10p;x7@ZRlz8;Og zl!zrhE&vu25uP9ME0_qK9w=)>cudrn5Jb51wK4T~R95~cAj{)vC>UFSQS}n~+Y>~4 zj$}SV8r9Ak6hInlBtQ}K4#d^~MA*^*Bp|N_y9EOJ7Pi3QlDCCDN+814C~?5$)qvxv zDi&CBg9z`AT8-L{bgAOZ!JsN1#8P{g;~~Odp;Al#=u*WQhtihSJVdy+kro3^h9!*w zmx=)^vka&aVcAvo9Dlzpo3l#U>s)QEvuegN+ZuofTN;1}=e3lr0mqZ20moAdH2@K| zGyoCKs{y-Zn`FTJM1(*1TTJ~0mFZtWoJ*qp^)YohiMgox8|5n|V=s7@Ai|b?4I(TC zuC;iA2&dzL=0t=o5rYUz^A6-C&W9TiMEI^?QwtG(6x+^4gz4m}t*xp$T3uiY7MqCh zd+xTi4YO*TjrhJ=PFmSkZMolR&HZ5a*&NT+@;j)82I$Kv5)rPy4u3iVH&QhPgmE6b z=@qa{hj&Ko37M7RJN}4sV70c#1THuc;TJr6bjk$mF*Ub6R;;y0AehM+2(|qFupJZ; z;R!)g%o00_|Sww`t zGc0TAhzMtGkj9xu4Ld6PD|#g&T#JM!M<+ytck)2PAi}03h_ET;LWCpNMb(EGo--`Ozrgj?W+B2H zdFfNt1`%f2LWF;)F^DjEsXf=V5#b3a2N7Y*G(?1t>=4hDdJ_@OZ-1uVlWu_hi3ooR zO-#GHGU}SnTBO|N7@uTpSA%PUt~unc5h-_TPOp}SzPNF%l-nS}UdkQLcqwk z@lx(^#!I>5O{UzTjF)nUGh)CkU`b=Zg<`;5DR(HdQo`oetaHnw1p7E&Q&Mgs!ZTn! zNx2^cAu0Dl5R!6F2BA}K3rRDG@O0eM1XIG9T%Z~`co(pdk-gFuUdQZ}6;1Ay_@8;N zsPc9<0_U8Csk(?T9k6{6=R$-pt@9D##w|1=>>YykNhgRfn+PKO8c^EYi15Fk!#jkR z>1TxB-q=TkZ@s}F!lyt>X+M-*M407lMEJjmT3ke!T1sC)l!XYhR6ZOrL8|md zg9tx>Ij6?nW)NX^=OMyv$|2w#N8SFy6<-XM#J@X|IqLSQJsMCkfJStG(z z%6$nzgi|-+&x27}*&)cm@w6ovqfl4%5c-=4qCH14fgz1*XAKGXiO8ruSB{zuh(WuoJ? znz78b1{_b81|Y(DEoEx}B5Y{@BHTg^K!hy~K!o#Zz-~D(9oQ{IgrC19rmjV0`g0IB zlZfAnH&2te9W{?rzT!IU1@96>*s`xdgvG$M7Eci2K5YZdi3nRF1`(F#9mt!_T_lL` zE5W7~B77^hor?(5$yHlhRduwwz!WSt5#eXuZEG85)i@jRee?CLV_CK3ey26}gT0fQ z<^o@A?RXP*9Ktvv#PPtHK7<@bl}poj?X7c|9gVv3dRt6H;JTQSvT!N8J;aMsCH znH5-8U5ll7MX$NNPDF$sa@T2PFHUp3g$`o%ZL@|ta#b_10zZ+)IT8_GAJM`gs7UV) z;y4g;fX^hGh_H1G6A``_V&cqg77^jahGi`s5#g*2(m3;|VMlY=D-q#hBs@7fAtKz* zV`Zg2M1i;No|@vp-qGp_;>e*9z~5jMhEh%iT9TC%=Dgju!_;f5{-5hgEn9m>JCMm&ge z5D~Wa2@&BrP_DPFWq%^V`R&itdp>XxL4=dkv(aC#Xk zw`L`cwUCwjhO16TrLoZpR{meuNLIY;B52E6@z$(g%U8p;0MK1)J%R4#wScVw=&q#! zM@-o2zLv**>Ju&qND$|2OJWFC6h&M9DG~2ffQt z9jz`f1&d8|w=ddrpW24`zu2p`VVdnv2Itt_YmPs$4M2qVOc>x;7@+Ds*AiW6voTx+ zJmfnYm9n4g)%+v<`~OGwAi_KGF4rFQAb4kpJ*K<%n2E|&YmeFgAK8QG?hCFNB-mM? z&G7qg202KV=2*%<<{+(@fqUG$93s1UPc7SX5YH{Tdo^?2iD``klQqY6tD61l5TbLA z#BX(z8Ka4nmIXzGM^6wGLk5xowe2=;Xj+5zlQfEGw2Fo||`D)KJ@Q?3H-# z;YO3y3Gv+N9xE$xA)Y%NJ4ui22Ta7f1kXJatU884OF?W1qH57UV`@7Pc7#Jb*Xoma zE-S`!Y{YYWqTNt#dwXq&=Z-WiYXOMoHg5r@uoL3BQ;jBTFvN53@mNjbxj!??!&UcO zXP2lO?BcnGxEnzhFFVT>JeLV#BRuy>56>mH5uUpv;yNGCHF>Y#xn4=|TvH&P>lHMf zYf6IWn$mK-H^P_9h36gyJooJ5eLUAR&BAjz^3vfw44%ufh3DSW)8M(}rCvoji03Xt zIf&<4rXikNvtiubf0q4;=jOLR6X$mSfc^P|?-kJGC(f)z;=BNrk~j|mVUn`(oM|G3}Ex7XaIN7axFa z+(HAe-l=6DO#;BOi2$(oZtnxI8$_4B8dIUrOQC{=BOEoN)KT4QcEj=3KZf& zy%q{>c*U0?HIs#fp-^p)qMC#*y&VemNO*;JSQza#dKZN|aHENa_fYuy?T{|KkHWRZ zN-OvPg~$u8?oUzpse`NfGZcP&-sLPs;R}!RISPm3Y!=mDqOkjds4jek!f3DXH45wY zanvmw_BSZ(|CKv}iQ09(0gu=LGZksR)f8ELzi=c4A;IO)r zs-sS5qX)ww^%lMe4!s^ach`^#l}y1B&fPYwLJLA0Z8J@&qf3e_s@ga zn{LIj|0q?4Z*@Z-x)mK3Db?vekod^0m~yUC*I~|~Z#{{rA+;B#8v5R?Sb(<+9LS0l zZpFV;NIl0f{h}*W&uF*zXzE9dr8nju^@MsEOF!=PHU@msQJWa6KjqZ+GDd&e>1Av_ z&*}9B`nZvLo^dwi7UHy>&||%h!jz?czSGO>gcqG&W+S}h^fLS4Wv7?f2Cq52%r1D{ z>18&-8%{5?2i|mgnJuu;>1B4n+fFaD0p4+X8T-HM^fKmu4{bf`f8_Ks#{U?!XZs~i zFJt=8oLv;lFbF)W==BKTCroQ*xDpvkLm-ojre`4ehb$Np0+IW$aRU-P+b1{`jZdLFhEYSvcOaV>Y zew~Ec>=5iY)+TpQo9(xESdoz&66yOE_E~cG!h29GdH^3v*9_G)PqHR?V85`MUy)GB zQS(s_$R^L*#N`~|bEHkboj;4}HqnsJdXeh-MHaiPvHWsoN#16RoI<(KmrcHEjO=ryO}~?TBl|2p-=4maeU_f@ zjDV4)8w#lY_XmvJ4mEnDm~W9g-!3`l%i1R9+ksl@sNCDsQq!F^$u0YO_T3oeLSHs{ zXm8KHK1bU0yXsS8U!SGtyXPWfU!SGt`+5)GzS0c^RR2%<`u6RE8a-0X_h@%N_s%(A z);2NU&8ek<%DwqY%@EckUp4!ASCk8V*`(9Uo3GE2HvQ)K``Ksd`A+ipv(M7=Eegz6 zx}kvTp9;)(Pt@p~DS8B$yCV8%z?-3{$`m)If&Hd|h zq)or`{rUPVJ>Q-D`T8t9-z9i>D*{yhdYdZd`|_3nIk%sF4yHZk85sO1zY z_vR}#XR{{x!)D%oJ|E>mUp851_Os8CHvJCw_p{H^^R4&yv(M7=y)9s0>4pNT|3d-$ zPD70zDdu~RJKx=M&X=`K%=dC?xthwo`AW?VtV!N(=6f^Bg}!X^9kZW(j(WE9ZP!+r)hTNiB1z+?%h|Ji(ge zL1wie7``A9x3L#mpk9lIp@pTCg%GMwR}hA-h8FzH`XM7+|;{&!~0>r zzHG9a@mD@a+VtDlpRdo-^Zo7va~}CDJ>Sa${z|%`fa-sFz+WX$qeqJQ9^uZHulZ|i zU)DA;-(qShr*dz;Qd7;EU8Me0`Rl@8N;@ zN;ecx{SOPww=-(=NHO1+U4Jzp=X_b)#C$iPmY!7Z%~xvrvnDy!#2Z_pT7F~ z=SZ7=^ZfhQXX*J)@%^*U()0Z_u%D$H3aI|2f%s}$)aa37zPGsc_X+mrg}!WZYZFiU9BI?9){iHBmY(lIf4)9T&v&OlJSp8!K=nT` zFy8}EqeqJQKIYDMYR>txwu$*3Of82~xi?>_Ii5AiSB!m6M!C?JP5x}`>vN<{zkmDo z^;vqpxB2t+S$e*m0`rw_D4_cH3(R*4YV=6efLX7GRr}Xss&LE4kpKBW&%k3o3!#!p zyBhE+gsLfYKrW#Jv`~0NRJ{kGqV_CjY0{Ny3;AjUAKoM5livudgGa?xL1~%%Wh)a= z=j1SRQC5U9M?YgK>d(V_RlxjsqNBEaw`)xO_2rN%C}VGxW5(!jU8ujHtUaFJbi$bv zQCYcpfK#+icg@+8oOFOwcwj;L5vbfq*VRpyC)%Nloe4t5ArT={1I~ObqCS2KKM`Jk z=Kg?T3YLIFY;54kKsAc%&%){s+&}4&4P40LZWL0T|BeO+vuVdfH1Qn(m(t3u1ZUZr z3br9UQrb>!TXK9c(I&!~E3q%BAFzFcY)MnCBJTcT>L z);ARuqK|~gktpJa8g$;BQ8jt6=reLmw0*h9Mea(B?_RC1&uCX436UdF#1A!S7{*t> zm*_KcOk{nzqeRZRJ*v*p`j((V#z#WrNEGoy4SM{psG7a2=reLm6n(i4V<>mTtx@&y zbdkFR6{3%X$dM@GhZ@vvQmTPBK0cB1fW#A8Jtf-I&LgqR+@N5b@ukPg=+`O+P=GhaG64DQz@pK51F z>0~}TQQLk$HLCtS9GdrOO0x`HbnfHp)THRtuSrqAk5=F5w21l(2fnx|_1Ode z$nWH1A*GWgLP{r}2q~R>DxGY9()6f0cyDx49crqVv#~t&2lK414zYc`JaO;RQ+Z5R zhp4RW_+LQRiOk@(7cNGjlUtA%iq}h_Essd2OX%kDJj6@BE_Z)9a@~;X%yV-OoS5Yu zwto}j8pgHl-{iPBdp)lHp(M^2J+A(Gj54nNdR+3ze}l*j)`Q$SILK{+gWN7K$U&i9 z50Oa2ALYQ18qn*esH(#WTGF4Z(bTGObaITJJQrs-mru(N+;E4mM{*(ET8_7*e+j11 z@ZoQ$ZJ=(o!#BG{)yt3I4EHrfIo#;*6F7WdlfYplpCnvH|YEACQ)8uo!nn18=F4 z?rh#QvH|{{;9_izuHmXH&~|T>*Y$=_^#p2;L`~PT@v$6YsV?z!yNB?DJSbNU1@ShC zSs<2xsJsjjp?AeMs!e|c##5~8N>1XEkc#(-r`5x5tu4QOUAnu+=|=f_%I|{ja#g#a z;*t%MmG1;PD%mJrc`Kq~@8aLS><}o+-@a6G2HsWDGoBuTu4ESDLC7p_1HoBz40aZ` z`^KcKv0yrlCb7_(M1wnt%2@Zn0D6c0Mg9TuW5KNaOF*J+eKg$@x9FXyoFID0>!E_1c(<+ZVYvP1#TsXH&zuoechE~8 zrgyvCT8DYNKa`Q%>u}lqAN@bt&ICS->iYXPAqz&JDv%gt4Kxx&CF~$7l>`U`%mzrL zK4t@g*~|)-THL91uUqXBTx+dbtJbZ!EA_Qjt+m$HwLmSk?(N@NtM&c;&b@c$-aHc? zA~c^*X3jnL-gC~}Idf;eGxI#p{n##^M;oO$68S0zS(6kMigKJavnU5catmjythzN} zz9hHFPduyc3!vnPCUswBq~z}FAZ5;ho!cPf-Hds1GY$j1M8t-w`*%?2F0UIYx%+RB zvd>3gUqBefWZJ?m{#fCa6Wx!)sBOvq@iIFZ@8BoQY%d>^@fj=k*ht1_A`)8gd*J=B zKK8)-O$mGWQR0JDUX=J?RYD8Hy&fuY2PKopBOH6Y4dwO5$A}X8^CQN`h&&7U7*QWB z;A2Fd1$>Msp#^{PNpA1486ADzjLsgL(beb8Sl?qaHtfM>_(OTxKz|^^Pf_)F%X{GXE8BQQHUu@!9iaudnlX2TD4IJ$Y^3i9y>b`t2o+3dPgN`C z>$^U*Eq8q=ICp(mGpQ=&|G2Qk`OKj)Rl338RB%-Dz5#>rIo|a}br>MCH z!bK!4u_s5tqa`t?X-Pzx<(~?j7+N~~oK*E-0W3$-5}P};6xv)F+SH<^rO>>grPDX0 zsGSGEd?YQgdC$PNhfa2cPIii@X-Pzvmd0IzOaFOr5=~2N@6r;>mX<`8D_)%#Y4lPk{Xh}p( zOCrj}vP(_Z2KHu|f|;Te8Tqi+oz*P*_@`9PWmY zmQL!5rX?NNp@pex(Ua-#mSFb zT9V>u6g4fe7*9((aAX)-VuQR7aWTC9yPB4cLEnNS+{@*4(3}WO-dZd!K{L|QBT(Lf za`rnAeo5gt+>6)-A*&dB-Tsl5Hlku9brV=~GYk+fyjEbOYrIyEu$5*cw;>tnLdQHA z>DspNnwN}pqEpt4#JKGr8R1I@&0bOPpgsUKgZnr^mJv82)BQ*{G zRhl}LJH@X7H7&F?+C_M^V~^kX=`8-T=k;%;st!)q9yT#=c^Fu1lDt3vF^f%7+=imY zCMn*GqQ)i`U2OVpdzeB2Ha!5PW|=3Al-&J1q|BYL^9qE#myl`WF{S}FB?Vmu1YNQq zWlu(z!yydgZkWq1{$K^z#BtQvBs<7Uc4AY)WcN~(*yJ8A#HNH6{2sujKK1}MCG6ox z32gGB1U4nKFx=~*5_izE&&eEnV3XGy*p$$pA2G1WvjA-BqXl4-X93uh(1Jf75t}>{ zz@~&I{LKJ1c@}_8eY5~<@+<(G`e*^z0M&evZMDoHqC%Zi%kz4X=X(_6KrAxyzWwSE_ftG6=CumIQ}=Acxg5oH4ZlY zA7%-IO%x3_v6056iR?P2U^X6>Ppi<_MB9Q*6dY_~(O?rrHD~cfsp@a#m~MN;Cbo01 zNi1k=5>aE5h`nIbDP1Y58$W~{jZN&?lRlmja~hjO)Yud{G1#=^+o|e@3_cQ@*xbRU z(B{g}rWQ3eh2{-5y@ZEM$1?CpY-01Cfo~6;>dut^sr$oWYuScJM;f^?!JHeG>-OkYQ$51P%U4lo4RL_MR+ zpx|H=iw2uS)Yv3q95zv_it0;K)jHf#1~$D_?qL(_#fSB3v56HHn?#PlCJu$gCd%P% z2(jskv!k&|2X_3TRJBWE6BW)Vuqc7q%Pxye5)3yPs3o!l=3^7}7MsE#wMoN#xyP(=YLm>0u_uShjVsiRI#V z@J5?{$Rx##XDl|c7>`XOaAX*4VuQS=a5cQ}3XM(U(f5#i_j(G77VQgD=O2ko75Ma{EVYYDdKcWCFf13pMLufDf52vs%AB0O}!IGlA`| zW_t}#u3-YyQ8a4)2v9HM6l4DgP?tGn4N%+y`$vF!6|Q6}K7}A#am=%NE5^9a08m~L z0OgedP+l1uu?}`*qh%xRFdLEeup592P@B24~ z0%$3r1%L7(EqNwDO9@T*n*mz#EP$5!XaTh3SpY5d(E@16vjAF3Xd#?P0$SoB9ZgG* zz1UBkgR9RTuO0IxP>+_Vu(b3MY3Zf~`<#|G!=$C9U4?qy&7d=(B}Tx>P|az7Fhy;` z-Kl}&|AQ|lPs*5x8i$sy$1GuJiK3w;Hqx{-i(SVQoYax3e!f)G5^W1DQE+I9MMFyz z)tu`tNL4lH)H^M)okL4vLDQ0mnwCWDg_cx1-fZKgROCY@_T(sd51GWArX>+IErm`D zEnRV5sv64RBWa1v9a;))t_*EzQPWar-q6yj(^J$T3_OyS*t}=p+e0TiLMJ;#)U+g` zOG~X+q^ecLa1u>RZ12(%%a)czj-Vy#16tArLrW}JTAFhS&w_(iEOTgyIW-*F1X_9) zajjm0xT0x^mbmqnmJUAI#x*;Mby2j$HUTZ^xC|}nf}tfAEG=!9Ae|^lOE=w+s$Rox zA2gdy9Zs;^l0iMA6TzV+>J2T4sA);WI9j4s6{R1as`_bKda1&rCDw}%>($Z{D=aOE z96?JQ3QJ3r!`%?l(&KnTBI=bq9a!GNRJBRd5*5xUuqc7q%Pvbx5{#iGkt1k{dP_@T zkXw`eAVXSOix-*Hg1>A|QTHE&WQnFF8<9^-5`v*6kqs@0Y-mYjLrWs>mX>aRB2~@9 z+y8^cvaL%?EEj+9qNOD%4*I>NB^KjpX)%rrLrZLs*Nuze(N}3&nuxw1d6&y4K(pUe zG|R+dCYq6!Zin(Dl(Tn1sHbquOZe>|2w6At3flaUme!-wB#BlE&a`LL|RJ27ZTe)($XV1<=8(>OWXqcM_PIlu4F6z3qiKxxIgHv z7~?tvEqO)Il2-;Td1Y)w6YR)F%SLQA8sZ6axD+#l1_Z@3Hm8qiXSt&y<~FLLZ*8$XN1)6$7&rmA0YmiB0g>FUyw zr2BegzosQA-i@NBB`IEsqNXJlU0UK7SlhpVmPX<0Gc_$uFj8{&G)S2*z|LFFQCDOV_K%m@q@{$J?d2nB$vrkm zO9?IbJwQu+>;YOz*u#$!wB$tzT1sePxYt7^?x5uO>yIOVwB+>$EhY5lM+{o>EP$5! zXaTh3SpY31wBS!Zq$SS;Xeprye=|T!o(0fSA1#2EJPV+uK3V`Rc@{uR2`z*ZNkB_H zq@!u+4|pZ-DtuR44_e|!+&o&M!qU>e+CfYID&6O_^hcPqw3N9@PdOQMCbYx|cvYk3 zy!k+idZnARl=ppJk-3p`|NYQq-{h;Ubcj*ps8+(UO?c zv?QXYrO=6?rPuIEUN?h}q$M_YXeqS0GPJ2hO-rG9LrdFFOHq$xz|Jprw_k zIJCr^`Wdnbw3KpLs!|-=Xj)=#ZoQ?YZAeTV*KDyIMN4cG(2^76Jn0d@L! zkWQ4OrF*Z#M-7qagJ#o+!wHsKB>fqk2o5c=y`d!$H7$u4M@!VIq8p1-)fjxX1kaYX zE%RuJ_2R>NwY0q=TDr0u6WD@P=cK6BJW`@*$wuVUl7wJrNn}Gy zA{$x~+0c^6yQQUTAH%a|CdOE{b!my^;;Ub?v?RrQP?Q81$6`D!Ey0mtXo(H-I&m@l z$km#bUPRyj=UpzV*VELS(B!>~#mi_$T3Qa}v>CWAKNG@S3NJ%g3?XYd_PYHeEgkem znmU)d39R`52KY*z*9v$s$!pdBdjTW44arDXIp)boQ*mOke`KWht_jPUkr=oABO@(^ zD~Y`Ug2a9&1jatbbp}TAieMzK9I+9vdmAy@Y(!QgOxwRfE+c)0_Rnz4b~-J{NYmd; zQ<*dMCG^1ViIB2ZV`2XcBMt2SF_hWWXnZGyO%NW0kjFS@(mNRGM^MV}tE?AY6JVs2 zKc}g*Szx56(PlV=kdbmwH69voKar8vqv9Lf1%3?}=>}UPQHGZ`_F#>lyW$z?@=f?` zIp=1Nk(i_|BT15vMxts)lHw{9H6uy!7!)-lvFI{V?hnHJ2pDMzlp1(WFj8`N4W!J| zV5bQ}UOm#R1-To%e|I?)x=Xi_lDlt#l>OAJY3dOO!?+hVvx`4g0V8o3H6zLX@iLo? zlrXcsd?X{e#|9ZGp#{GO7^#mvz(@&u_)&t9yePp)2`vowdZ@%5^i*>*#~zI2^#&s) z^yfzmM)E9xk@{!>jO1AWBPF!pPd;QM&jc7Lp$UI8z(}42Fj5~afRQ{4V5B};03&%8 zz(@%#gcC`?NIayY8R=#)(xVgN7>Qro;V}{wmXSUqBaJ?BpEFW2Oj<@7*Q%%P3_24= zVg$UFQFB&-k-oZxjI;#bIh~YIfEtI9zQ8PD7>S}`BsS8Fl*+DS3YLSB-o)<(l96az z7>R>AE7sDq2E%+r5 z++W%WKo#-SNuv3gsc?ob^Av~T8)aS)JPbVhMjOz?=u^bRe)i!e;y;1p#Ak6vtK$b$Vlg-;$7%?2|cj8 z-%)6CG#2(RV5HNb%)SSWzfIvq2$w_1W1P>^I~eIBC?zI*B;GXvMmphdY3eoTGDkxA z2ZWH3I-&Uj8gD<5k)A-V5EdS{3yXlUX);@gcgQ-JyhZjda9Yru?Hi0y}?Kc{rM4tkvt1vq&`{z zBY76UNC_?YlMflmGXX|QXu{tNFp_5hjMPU9U?k517^#mIz(}42Fj7Jb;Y1QJ5)bKU zM*1$^x_fkX93%0o2t7uk!ZK1)2NGgpnrWt-I!#nvrN*7>Rr`VvcR}b0qfW)>}r(skU*=7RynL#5MsVIYG{o9>H^@6YjG?&No3iQIe77-GHzB zM9vPHO(PB+SX#-j(TU(N67`0WMAVEVVjLq;tBNjMnyTK?&yj9g;V}~HIRbHC?Z67l zNFqlt5{JSv66J6=gp4%n{%A(hf&Fp;@}?X6=iX#0oKav=0<)K0mXRbF!$=}WFcS5a zk-{LiCi_8#jPyE!R0}5It-Gsuq(n24jmT#t3BfRu$cB+bHjE^)VI+}v%SeS!q^dtM zF~+j3%SbF2&wbA_k`zxuQ4(Mri}8$9k0Zk{5*y@=n}g>&-`9+^5q-N*4lkE)hUOw@ z^1hEnf80|iBmEc39Vll{ct1_OM`06$e?!Q+6EnH}BO^V4itW@*V9jV4AR~FLz(_B9 zt!A>7W+b;E8R;L6c{0*QoLKB18ELvx){Mls?H?KGW4MyohkRgSuY|zZ$GFbGNL~?) zdpnbU%d^g1e@fR2~YY2AN<6z-4tAEv1f z*=fizp;<#sY2C}9%+5fQlPQdca0-MxM!uHufSPKdlqgl!nXU;?(_5&z8@kL(AUq8r zber-~ntBNuZ_kmMDpBzV?i9ZU)O4<`(W4(;?bzctemaZCCUqvhCYRH-hfT~|7n>yS zpL*9~lN3{sqZ*r}_!eq4HnHepQ`0?R3I*771(ceBwiqe7`=^jHb71x!2zft8rftDt z6JXP;Q0OjyHBxf-N072x;JQD$4C8LNk6rx13b2XesIf_QkeBSlri97vr6{q_IUk{-?;8!6BQPl(uhs1jr$y%DqzxL)7&4KS&_~Jn-~EvZ`7OyU{mW2 z#HO1c+3^q|T*d$-hEx(cQ9*JvAK^m}W|0x=qXj`y}f`d&g8f>Dd z=6v#oy0Q zm{Ttxn}AJ=fOAjacXfNgCidpmTWoqBiK*k7EtaFOiERRGa)O*EJpydH_(>b&d=sP- zC9&zv>r>T6B>JG)G~xh5fK4{K3u!%!qv59iH8$xVq*%pmWIMb^fL2gafXZb+4DF zLsJJ$UMm(`(2Ur00hAA*oP8gJCn*g2BuzaJA?sx9b^AwbT8N5EsGGo=`(S|BuLO28DYd90ws!BF9^=@~{a?*&!-xCF<-Szv7|&(=_!R=rTt_xE4a_ z_A+R0gT~u)#HL-SIEOpMuK_j<`H!j5F2buFd;H2QCPy^$kkeT_Hr;qesv5^rp@&Uu z?_v|n#mkZRa;P;*@iG)OHc7D^MU71?y4ZB%<6#N~*z^pPnt}dcq~z}HkTUOpop&MR z?Lwx_#6AwNX>ibGWY8rKQucrU51%-LFpRsQgkAi>3b2XesIf_QkeBSlri97vr6{q< zJzR)Q2`%_NfK7eu0c=Xx!;cc!JjykVv5=+BQB*yLFN zHucd0u*tIkY)WXspO1)5o(W)6LKFUG0Gm7uz@|Q005*9RfK7e00BrIs0Gkq82q%&N zn|Me^W79NXQ+<0JHt~n0JZz%EV$=S_rtf#|b8Px1Oj>MOdbgPs=}fSR5pXh8b9VhQ zMcs<;Od2@;jpul2_OXvm`{C!U3^q|T*u+NqY16UnI;P-Hcq1>PRbvxv3pP=3u!%*3 zO%&Cf>w!&Ao{H(VS8QTC2b;u##wHOpHi_5^HvQw&6xDDDTts3MdvX*!Y!Y)Cn?%&u z6gn~3bRn>56N8V$CN_7lDYUsVw5dgnO`&;%P4j_GgBf@vHnDlnz_*7^c7#rLim0(k zL>HST0-OHX3@6b~o7mpPCYCKWi5!7V)Cbt43kI7;zhH@Ed=e{wO_x6IU=wrdFk}<3 zX*1&5(So?5pEj{Kx87pY=}1hAO{|N;CbkK%Nyla0$kPS$M&7m{$oVEnC(5INP2U7I zjYFajn$3O=Fa+2{J)_H@;9wJr2Af3G*d$^cHc_jJzPAM5f%34tk$3J&51UvoKCD+g z6m7|@u-GJW1U7LfEH+UNcSDFxKmJ`bHtE3Lz^9hpx(@s2UUBG*LJ*j}?6TMt2B!Py zeRQw)vrBAau_+94YqB3?h)u;W5}UT2o1z{VhG3$x$wuU3lZ0ciNo0dfA{%TH*v5Dp4RbNRSC)A5dZV$<6=vDiOi(+y5pV-w@Hf5fJPl1%KAAV}<;5E%Oy z*BP+MD*~Ima>Pbl2Rq@WZZaE@_5a)eTx@y-?Z?lDj0Gs+1U|-~-$sh^^5U@~rjQncGgQrcKpp+<8)+E%~KVnmIzjRd%UFNN5 zvmQd|b~LKahQ`}-#HLPEOo90xHNd9pY>jpiUhUZ9S7tG9I*Z4qMZl(`cq;U;iFxZ{ zljQx*|5|L4;%FqU#wIByqo}coMHic1eLhT~0Gs;#)?(8jBPDldL&`h`cE&--8-;Gq z14RRDS_FkAtz||^?mih(_5}#66T&d=hF$F94_1Ip97l~!vV**2CpINab}vPVP43}B zY)WXs?*VM;V-H|c!XAEon-co-BL+5k7JyBC zv;b`KEC8DlTJYy1Vv}bA*p$$OzZt+L&jPTij~0MUo&{i2A1wfzJPW|4gcibyB)}#f z($UzI25hS;48(wSfrBj9AH=F|e4 z((u#c1IK5+#!EB)B)Idm>0Znd2Ae1vY+@sgO)<3Bo7mpPCYCKWi5!7V)Cbt43kI83yb)p(D}YVie{`^kIdvAY3D~p^aee0$ z#1)NA?9HvW*fg=$#x*;Mby3*FHUT#2xC}Pwg2ATGgCOUNDKAQ5(=cFDawD;c{TyJh z0FyyIqZ7fwCh83~iKwwj#5ioCRuzo`HhuPxU{hzMhfS;(AJ(hICRSK%5;+2!I20C} zD2KZt#HQEZjK(G%*r~v#)33w+xi^^#XB1eJ!0ct0#U=@cn{4_-VH4X}Yzl+in(PM| zV$)fFCN>=iY`UCBN;Edvh;#dvJ`E{+U?O>B_&lL9;i+M=;37kxiNIlNvjgJy6cnvKTdc{C$7 z-3;Ygl(S!i&_-bbKJIlogsiQY$?YGpsTLLQP&a`!yI_FW?AbbEJkC9JeJiw+wczP;Ps;u+{p1x8Bl zz6w(IFm$;M!Z7ZJP3+?%_ggN@&6F0c`4H4`5Tm z9)6U-CND~0Q$h>Fy&fuY2R-|2;n)M4yxzd3g#P@9flZzTU{fD00Gm7uz@~&2{P~F3 z3&1AN0WJXu!)CsG&U{5_dn#Ui^HZE zI(XPbg~g_!#HM#Q?{jQ=4kj%&t$WkVigYH}#0YqKgAcUhXKUa24Y6s-+q^WZMU8_^ zb-1oF*hJA_6B}u4x|m(Z6#Ta>Rh_v;V-sx)Hc@b}iA94=6xEzh@e@Wf(W!TAVmk+$ z#Dc~q5j8f6*b6poZo*4?yrzo8Cidhgc-SQ7G&YH-u_<(7u<7?_7sW+Y+?nl>1Xdd*u7r{>)lJCRL9^M<0R{^&8Pqd6 z5gcry-e8l68k(yctD=apN9Dz+73X4sY!`%>K z)6n;#u}KGZe*u10SYs0v&M2@bf!WJ0i%k-Y!6uOgZ{p2j038k=lHJ~l}R2Af1S*d(&SCXo#`iM(5ETK#CMN?A*6Vp|uRSS}ukAJ)~s zza+&uC`tm1V=*3^uE&vKu!#-wHsNZx*mN~2uAy!MYc|0EvB_%%Y`Vv5bv0Y*r%i4{V$)9@ z^TehTaAL84#HNFsvc@LHZU2Z(FT$0?{t*O;eda+r_A#zAV3St_HhJZUji`m4a8vIv z85xKx8Hb;OSOQH}3l{b-z^0!=nY|0$ zw^B$$+h0M*W8_aU9$?dPP)d|4>vh)zu;~d@9k2-4)C3_HLg;ooG?St6_8hTkCVt58 zV(t{b2G~?a&oukCYFo0f5mc>6rVs* za}$d$H!b>mm_q?KoeHIfpp8btcS1nQRLK3yAmm-hRKuVK+;krly36B6!goSI%5H$` zoe+j`KOD?1{%8f<#DUb@Bzwrqc5+j~Z1-}M+~giF$S05|o~0=UVu0B%ZXA)HA9ZsH*w%}s}Zn?9(GEH@1!H~s0-ea=l=VbXHb#*fXkNN2)LjDXiSYR>cbrKsHJ$W7<`i`QoTQR8sa z;5y7-M3sT#DH?8KBh5|sJ}cbx0=VgwD$Px_E!;%G;U*RhH&Ik`ZUi@NMyKAniR~P2 z5(}D}MAY0QVlUkE$40#D#*3;*ZemZ4g2zo_PIHrpnwvr=hMT?#Zkop6Be{vq9c~J3 zt_*EzQFBvh-f+_}aMP_>FdxZHY~C~Q?V*z$p_82=YHkwI<)$t8;ozDWoJ4aI+q>Mv zvgIa`Be;qBfSYu|aMQMbTO=8u#0qfJqp3-1*Svlzc~p|hWlmjzYyvlZhPXDKjJTq? ziM_e?mYX&sF)cT-E{dDjCg3I=m*FN|Fx=GesSR?z3DSv@+;kYY>A-4o6Z<*DUXg= z%3O>q^EnX4P`C`jL-YSV-Lj)*K82|(%3+$y$Jg{R_BhGnCoG z(d4@nW<&T9ggi!mGUEX^bwVjos;pnQCcsUfpz5#CWnKs2a|j_fWe!hQ`z`6Qf5}Y^ zs5qKC#oMQu;HIl>jgB(B+OfxP{B#!2P2<5$+c{l(+{Cf^ruY2ZIBse| z2alVmu-r6?-1Mt!_Bl8G1STyvT{J*XIvI2(+{6fYeWT`lf?u$`=;!372UBm#zwljpBhjgMZelx! zo5X_VCJ{9^iP#G_{S3cgdo}JPMROB-auhsn5_6iHMAY0AIx*bzF1}0e<)dLalAGAv z;ik~$%Fw13H8+Lk4L1$?R*E`?fk$!^oA(TSd+20G=wzpenwvy)xoPT^c&;-CPNKPq z?OkqS*>aP}5!^(5z)iYfxaq%XxGFZkX3Gk2)9(&(xQRJcjcfupU4pn~acrZxiM_e? zmYb%pwsFl)VqFwBu}#2DIxfRax?s5JhIAX`d@a!Lh;iIRttvVLzhFCWtGuQ+|LYz%v0i*wua=uwVYx}<2yWs~SZ<;m z?uL+?&gqXf5x>c#1G@^pVEd5%E zG+{rC(t>NgouYOQLb612la0vdCJDiClgNgfL^j+cvf(C?cgsy#PvS*oCdOE{b-9V< z;&Vq^Zj#~+C~9tEF`k=#g(Jgo6C30mfy?1dH)?Kr41Lc)IlN$g51Ol?$-5DYtI>?l zn+nFHt9Mb(J{`g*6kdeTZz;fN8)kC*2X6Aq)6@O(f*ilBS;;j)R!T=A**~(jzE?V$nyacosTd zA@}dz2`L=z>&B+5|FF}@<3qCsi~4uRpv)eLChI6Hg3v+XYzUhmL>v+eFOIHs;m-!Cbya*xme=@4xgeJ?~3FM=DQ1N$~^J~CI+ii_@5nk2U z<1~KSisz$y@SS;=aa#8Hi23RAku6(3V!3z`GF0=C6epsn`G`fAj~+-3haupjKSQZu z=N%&@cmE4g=33ZEPQ##nj`W&@K@Iq5e9&b|(B&9N*)NVtR}~P3aqt$hi$7WcA8{Zx zAITo_GMs#rFvGpWhJ556Bjlrm7W^LIqdxWkA0_PJM+rXiq68l$v@qQ3p%Qmc6FBy3 zIriWquQ&K8p+7%j@R4T$eAGt^;3Llh_$Z+Te-0%dc_zR|2~GH$0Y369fRFlU0es|H z03Y?y0{FZ23s!2tJ}d;3Hiyd^B>1MUU}GtNQptHV;jv!?9HvWe6$mZspFb0mZSKHZ2~@Wf}AHkf-lW`A_#K6 z3DSv@eDoans2({xXf};FWMD}p!$v29!$;H`J`z#$k%)18M6D|7C`nbhj|d-4Kgr`G z)^h~nzBG>&mXAb^;3E!&x9-9{cCsWGb9dU{M0I*Iky6 zBpAa-B1iBM^_GvqAh#y_L56&^C=;W!AmuwL>MyuG-U}buh(WhT$VN$V)B3=aX*Id^8|0 zU7dh(c)>gqnr3M7He#_0&B#X=LHPvA*-t@uj>5FQ4q4sOR@w}0d#uM9r&%HSif ztog`Qk&k}im?R(V!pX$`k&mu(%9@WDtNkM%oq*^h-m@V{yf5vmc(XopeYu}fN|UXUqT9p`yJH1z)t_?bPD)rdKrd#Et-6d!sQT(DLe~d z1%x~qxgTpj%9xmrH`(Yps|I!Uk9>3is;+=8b2@~dLJ0le0?ob9WVt(me5CN3$={Jec@0yRK$R94#e8i&5 zM}Imf9EO08k_KBo8epX4?kq@|cfw8%guD^xwh4(J@X%Z-%WeG;VXk?7J6 zVHgMRYIgBQE8rszBrT|J*+X82laCT+xOdo)kKAK~e3a0F-vfNq#~$FLggyKy!AD+{ z;G={VhI>6!;tpy8$NoN!J^0A$4L(Zf&yN^<6UdO088y`whlkvL}1IK?pl9xIcqQ>E)5o<7i z>G$p^8a`qp%|}DobxgrM;G?|tnvZB(_=tkTM=TmXqNwH+gO6V8!hGB7x8t#$!$)F4 z^O1;}k3{T+k51}HQRndDDUy%alcV7Ak(kqbB%?Gx(o^qAF*ioNJPy? zBF6C%wW{bpcz*Qg!@@_oF^`W}FFveSJrr%ptgw6}as(f7C@ddQ4tGPyM^ENN^N|iL z6?{~v`G^W<6j+qN>~)vrBMHXvk;oBzM7`ysFvzXRevly_ts9F`T5$aNDe6hQgVYNj z*@%2Tk`N3ZiEQ{tWWz@y8$J?ww|uk-d~_ERV=UXce8h6`Ns}!fNpT~JnvYnF=cAwC z$S{1w26?ZR0c-H1ocwmYYtZ+|a`%FH8#MEw$t%ZV5}J{ZhEGXX-$yxnIfR=i+zR36 z5Dw14UblbbBd-iT^2*>NudMmVRgsTs9Fydu{-Z({>K&p1s28XC9^1N$)=A50-< zTDlrbVHJcUAmnkJ7GjU^Y0+s=mdQ9}%|@O5BMp6qss`vXZ-Q_pgph`Y;a5s7f+ouy za?(%>Di+Y3UjrKYfvpi2;U$bcC}nE$=BRiWIuI~a$n%>ALrg{&h9sG9$+zF#AjKSH zqh=u~rl6==V4*RiE!a$il=&2F&!8|DW{!i9cQkt4fghU* zWxjUh(2!m6MYg|7{DOJ36ikLeNvFu8x)k#pC2(O$g=Z1ivkY@oDl+c1dQ<8!_6QH1kCj89+1$h=gL4C9U3i2#~g8FCy6y#X|1tqi)P9XsW z@n9ATD){JOyi)UZe9_P-=RzQuYTm#DA5Jw#ui1w4(kK>>=9$lkybKsTimh}1e2`L8 z3;L^FO6s*4^MGZeGU8Rpm z7(x07iGXg?N7BU6w`W5fMdwG;e)?!Om^-AhpGrS;zrjk)J?TGaa5%NO@1hkyD3U&I z?r-*ocJ}*>rQmxQfoT|lAvp>C56KBez=#ZGNDf1pTa9rUGFJR^vxkh+o6XS}a_FfO z;VKxUA-SsHPh-;5FIJ?hp<^Al_KGlrW`cnqDpqCShmMm7=yvE=gAo`imSwbuPWS?@ z7RnY5J>nmb=YD%(KQ;77_6x^g=tR8_E`0z$DSynI2?wXCUt!|W0trwWSi!>esYy(Rlsa8LweK6n(1 zCfP-Fl6}Yc9?3rI2yAV9vQv!=d*+rD^$OfZXSnA!eMI2P%W!%$8O{bK!}rg#<9#@_ zx$mQum*Kx<00sZJH&y+8VQ(4k`5%%a{&|cWF)qW!e|(0QAIbc(Bf|_Y7@nru=Jl50 zp4*{g1GhuRi5QpRv>cJ)zlU3s;p`WV0Wy5ff`ii3c^vq1)7^}#+*uLxXwX)Ug0 zA~}%_Oj;kz!PjX`ttz-VBTaQ~S8ZikKy+zuTVxb-G(T8>ETTjAEEHT#8Qz_h*#vvnZ{zMOSY zX-&P8)`4p;t;O|8|G}B?L^d#KUB-ZPT2reE?#66gieZjUYqkkIWsYXi%+?~tr8S+} zv}OyN*5921U*TplttUK~s?I9uEv*lA9S7YpSumYj00c z`K7(3wdXc{MBvLyYkD+k%?2i|+n_aRO>OQ9l)be6)>Mx7Z?~qZBeB`hY3=zRk|X|g zT8kK$*3?F%b<#Ar%C#fIw0>b!n!2mFx3u=$4jmh~9Xc*>>!mdE*18N^9zaWJ|9ITzhFPu21?8)0z!TT5n=NI<2Wy1xF4_Q?DK0TUvXb zGDnLiJzI+ym)3M@)0!=8TCbZ9U*Tplt?#%WpL;!`x3r#u&cP-Q9>t@BT5x9KASUtU_%qe*KvFlpTZtx0QYb62A5rS?&+_bXt4nAR%?D9})QS(wZJkTC;&k>$9LW zX-#eJ8kD`XK72OE`$lZ`8fjOFP<*bWJYwDe}4qSU_Ev|K1 zvw=zLOBj$&Yid&=fGFEnM~{TI2*q< ztGBdX>~7-VQ7oFY7ST!T`m1`Rbpw1wq&3yp-krClsIJ+)rM2faeMI2POKW;GY0U;E ztuKYvq&2m<9VmNgopLnCdlWYNyV&gLwD$ZD$r1lLtwoGWYic9X`dqrowIjo{F2O~} zZMgp(JzINjhmH;04jmV`_0pP_BhtG6F^EQ|HT#8Qz_kA6&@^=@2fmzjQE5%Rlh%Q2 zFRjJ3PHQ$WY5gMxq|=&ORdD;jG_@GR9G%vlr_9mfNvE}lacNDbHm%vhruF;SU}rO# z*4uuGFD=B=is;$8#NEWfqgXU)Euxdw{QX?-w%@#C&93%u`%#VUJsD}e4Q``nYtL=^ zh`^VZ*7Ru7nhi`^cSCE^n%Z3Zi`T)uzE>DPK_fQ%S9snNoz|ZJAvxk-r?rT2X-#cJ zT7P{mT;sGEEJ}1C8jk_S_DYpEZ`z9y%^?>!r2)W-)KT`1ktWfLoK+>=%v! z)B2x7(o`b{zMOSYY3)UkUJv1rm-L?^BJ`(|ER4?E86 zYCo;1#`eB?Yl<4#-dkFGZqr8uzPz-iN0ZiUVAA?F{?3|=_uG>c63^M{)gmN?NUsQ7duc7Mby~B5N$Up~kWOoARl%(T z($sscy`{D1DRZ=V(rGPXTw2qqO>4HWY5l_j_zE|ZXHMaKzr1kRV-qPB0n?54&<)t+}nzUvElh(iF?_lV( zrZ(69VoZ?M-!9~M?}yE!*Q?FR$w@ ztv$Cx=%v!(|S9Q@iT0AdO7Q&(%Oq6y&`b!rM0-$ zY0U;Et)JrH>$Ij;6&!}NPKLMW+1m4zIa)mFv=%Wgt?AUJHCx!UZeIXj;btoN$c03HEB(4uKmKrAgyOC=6GL>%{~{K9X(rn{)gmdCD9u zo^)D^7?;*`YSWr6Y+C2Y_d^7`nrZzi9>=_OY;S4Zg3eA_vuM&p}RI2~}_wHv1ZE zc63^M{)gm`cwYb&^%m#YIPZUvJ(^>Ty_5+@Z z;Bia|hB-Q|Jx`gV#gk5J5#!RDPHkGVg-z>!V}qT|WLnR~>py=uy|=XH$3>j9mJfu{ z@!(OxXT!`z2tO3*rS%egtS=(1smAvH^Jloh_pRR2+H;#eBJky9Wg z)Ezxrdv1ryXH`vF2X4KzmJg!Fr}f|9)}%H2g=4_9zBUU#zRZCyXI)fUdr_oU1g^cb z7S}qh*}$Z=h&rtYVLzyXJHL{qj>RxXr?uxPbF_HUX)R)0TGOdbYqqdy{XAYUcQ%u0 zeG&HWUpMrY)_niZNo#qxSEqIGny*P~zRT{V^*FqZ9g)^lV|!bW)|cW#RMFSgp4;>h zfiEwu>CvP$8<@2IEwpB~rZ(4p`Xor}tqh=G8aDe1Y<6^7d;W*yh<}~dBF3dPwGnB3 z4BsWswIjo{ehIVnjLzQD+H*TpK4M_fI&kZywS0acKCK^tTa(u87mfkb`e3B>EDn4* z>!Q-yiz2-uaP6hFxYlXS1}3dV)M@=X_JbW-6T_489?b!Vrn?m9zOzqmkF z_gp2bd#{t#eYeT#f%|0j%g1H4^;uax_(xeiyi-<>yf3TAK9$wusr86uRMP>nY91r2 zmdUa@b)KwRD`eGHC#&{OS#_KztIn%s)%6out$#pP8-6XT(_WR;H{RuH%)>2B1b>=r@b=JAEI$Po#d(L;HbnXvib>1_w+Pp(n z-%e>@_w%R8>O0G1bwPuyE<8_G7hNZ-i|>-vCC|$0(w(xp>{D5N_kc!PxqOVQu9zXK zE0@UXszzB|eU_}g_dQu%bGNL%|D3FT@V2aenA$`uKRQHK-P2{YrC3(iu94Ms-;~w$ z-<8!3x6A6r|0k=PcF5|-pUdjztY#YfNxrOZDUsDrSIg?wE?M1np{#DdSyn%LTvm6y zE~}saTUK`tX`z+7=E>^r3R(T4PFDA9lGVMp$m+hQWp)4CvU*_1sqDA)7+F17B&&yF zvU=oHSv`8DtRB0XtK6k>80H>-iptpRKJ5tlC$xybxP?@Xi7Sg@uGcF?#GbtMQz$aCHtc`HAQ|YA$3=h>VHeg z`v;?a|I#6tdQ1MgokmMXQ*M&Jr4uPPK<=MZI+JoW-n36mE-j$El5gE7mp%;prQ5im zr&0z}%HOan`2@C8`5jFA{V99mEN-)wKc4z zR3Sw!N~tToX$5M}U@fHzDRNOtUFnr4pthT}lq#giMJaWq=dMKUgRG@gAw@1qsVn90 ziI=~^T1pjCXZSIRE{Dlca(r3xu>QA%AYKmJ;NDr+fKNRf+D>dKj=r5Cf7AAVT&LoAZ+Kr!PS zEcjV=5tc((zUadw^*ppk^Ygwb)7jwYaZg%NTagbitoW#kpSb-!8srV{uSDoStiL+? z-_P_@2Y#D+`7FB@RT)1vP)_&qxrP%FJZ_df%edE~oUs54iJL-H z+|--6DJpq6eZ_I&bTbqZG6lyeizZ}>s*JCM%j@bZ*7+S-5#8}ob}Z+Sz3dA{n;Ap2 z{|BW+OCc&+>P@s1mArGj;xchM9Tp^73XW42O|%qM*&&RUixm&}9jS}%*vyXQoO_l{ z!W^CS1j-rLVDha6D>s?!F0M^obH4|qNU(CWzj@SQI)Zeyj;2>qlTFfbYw+z z#}Oyf8E403NIjL*igHFN77{ImsA#D-(Na|MhTw|H;`A~oBw7lNQx;9M6jd4D%aeBo zS5*2PSrOgw*X&r%`Fq)AjCOPtqWuC&iIzfCwA7nuDJpsKYsH!3bS^ANv=khtEShL3 zs~Ti>EXoDha6D>t0@AIs9L7ct^g+xoi zamu2JmZB&*N8I<9B35bjP#Uv78qd%a$|Rmr>5R7Ym7& zLR7TWn`kL2d8oSLF>(3{6cQ~3$0>^@T8gTSk22*k>x#Gij;x68m|sh0yb4-&9-}=M zjQWxFvLUt_Y1?958G1~1YXYe-?Bw7kl(aP^B=x8Y_xwF0EPH~!yZ+((zDL779 zG|^I2WxSs(_qtd7$?wRD=#EFRV>vH*mksNOXfHuIgWp&x(Nc(tR=(X-M@v!34a*hD ztC-IWNkWEoQXG;66$QzduN#r4SV@ z_2wv}sN_D>iZXF}5)=|G1;;6iCR&QBjCX(J&eV$2{En=M?syeD=DvjG-P@DY!FeaF z8QEXuzJ+q}4*n3&%3NOYT!t&g{%7X$1pN}l^KyAUnMwY+AeV<|8pTUP zr^nw@+>*=LdxxC%Ik~*`G@fn8=JNK_$JCA!yImAB#qRwOMnN7Dqk^#XzUUR(w(L$U%3o!f2wjJwG$~1$iiI`RXQBYGGbZf1csHz&c?!x^fAFveEvQZ;{(M2-c(eTUr>7( zWo>d$CrnP|fS#6g)MTuKyA}Nx9yJ`FPa1R;8Z2Fyrux?>9W@>6%2$T>Q{%cM*1J$Q z;6W@-RIBd8s+4yGS3O4QS6Gyhzba>sMEh^`Y+w0XnprREFVJ=X?=V_hB&EtfvB5X| zegj6~zMvX(7?#&=L(uI>U!My3V#p^|KFE@I>ZWP1XGsxpIZ&zH6wkpa5HAKBsJ&^QNERqj}V zwr!$iGjlKxqlNPvZ~Ig6ot`ESr1nzLI&FuqfOajN<*!Q@fB7zamJ3T+O`!{4ZJ#xtGbT8nt5>(SB1A$ z)VQO<5#>%(mA|2Oj<1#EQI%)BiV;1=uTqtlQG2YfH68vq0M5TAgUzHJz=f*(kRcWH z)c&1qkMp(0%nTeS;|e8#W!Fn~v8eX@@ld7S{5(m0^?MS4ESLjozspA{RrhkT`sxi~ zjria1dGvXYeQpnHbf0?kdG}+~+#lBHKD$QXEQ~qft51YAl4}x1W#eE(xJV*&HuUj> zp)CotsxroAivxujj}AmRZmHM}H&2qNGJ7DZmPZcCYuryOdi2uKoO>uz>x3{+2}xId z@jQ0c%CO4WhSv(w>v9RspD+eY#l3O0Y8IBI$6!&$yTg@7@>n=g4gUc??+d@!jY*KU*CsPPflCdXccGTRX0K`m6o}56APp2(Y*2+ zdOca{|3XW$LE6$AoXCg&AA+b2`)A7{1I<(f{;<-D5}ce zQ+uSZH66Z#gL-_vU!^Lqp?0#bH60E^rjE~hm>$Hh<9sKM>^yzh!-3W(#>#&{JAQ_A z2(-r5zcE3KpXFDn%40DLjGxU-54S;g*l%4izBm|1=Y*!rI4)P8S&nymhc1AapB z8|*C$R;$Vm9FXIW6`Mg2YQLw}_fw5HC@07*Ro$M|YQMq%!DTBg$@jUqmR8f!+@6+x z2uuIOgfd}m=vgdPZiM~u^F-_H5%t?7b?Bg|ji~(WKN$NWC-xU{4CM_9JSw@gJ!xl> zIy_axZ{TX<$khI+sg3>A0h7{aoZiq+@$t^2{%S@8WS(Ru?blz$#=M%W@)z(qP^FsR zPvtL?QyH5M;6hctgqb0Ku_%tkvmD%u=kanZ+ZKs-nP@3i=1_aQgvkj*RUSq~i6}No zvoo+PleSON?h=|DAXSymP_fie{ELcW*+v;9kz@*xIjQmwFDBs|3m)cPeVt|~;TZ=4 zDQ|^X-o?d6F3#ZMTrR%D#U)%^!NoOPbaQb77eC?Rb}sJX;yx_Ot^x~|J(-Qg?~cSG zX+9Q5uEOHzRxB28#$x494vl~Z?i2UPbqcY zL!&c}sI9B+SQBe&Z*6I6KTXAAO?6#uTz53BscVmk*t)h&3k_C4bFFEstBKXLXt}AQ zF~&aC9jmpXxuMpyI!!e+(P%?`bxli4tft{K)mo?5Xx&ziy2_>H?Neg0$@#N_W^GL^ zt@Taqt78p?B{hvD`O{F-TvOFh$8bAp+DjJKM0c!e3pkt){9;;#(ZyraYhB%Gtf8wR!ypZscOUl`}Y4EgkJeT}#Vj z`Lmj_L3LG)9J%`Ty4I@p=2l&kU$eHVHP+r*Ro~uL)K$p8>9x)5Sy(zmtR z)m3eEg42+PeOpy~`v!$w(S}uReQR9};@%KzYHp9! zHMT&9Hnnw4?e!4Xv{p5BG*q=xUR%``t8ZFe-^4;|b4OEcti8Fbs)T_i z>ydEP9c|dey3YEVx>$27y0tZTv_cmB>227^)(xtrsujzo=2%-t&05_LZG(ZqaCB9* z)yG<@+SkHDV{>PnS6ScKf~-R*(yFbgs-&IPK zz z9j$c{6>I96>RRh-de+1`TiRR4^{{Wex`6~P1Euj4l&yn6ar)Ofo9k-}kQuGb8|s_Z zl*_iv3%0IDb&=VqUK`ApP3yIKf!@HNzOlKf4w<|`Ro6Fhg-M31Sge`{ix!d7%`F>L zS4~?DRtS_UjCy+u1*n^hUe;aMPr8Abf*U)K+_74{h3IG0IEFh~+v<^-euI|wwaBg7 z-DxoyAlZ8wtZ8nl?ZgxoR^a%s1#6X!0wpHN{7JD`&HD9K)%BhEJRh{xwHL0hscUJk zZ*H2`P}SB}Sdu>@wydeE9{qwE9H1SIjTnRiS=CaMV~N`qYpmK(U5CStvrc_gL;Y#U zw5HDb*5;;IUDcYp)&>k3W~(I~4ej+UD73ZL*PNntW%X;;wwJH1U){cgL)FsuBMK6t#wT`Xe^^qU-PwwH6_gr_0%|`J*7^E&GzQ1e4JkOnMBSP zMH@N`F}5&=vz|NQm(WZ^U!G)Q*fkx~r#hzx)4Jz*t)|!Wn$&pbwVK_Z*K|00?;z26 zjecTlTARCK)s(ubHmDZN=vdY3ReNJ>LoJF}cbRn~*Ek{bq|;SbcM6Lz5?9iC8CQ2h z(9m1~)c5fU06lqTj=KmbTUQq8MemO&FT2|xef6TRW}>`EjknkJ)yx#QaI)!tyGea; zW-dmjAn9@DFBUn+TcPY--;wPT?WjkeN$t(CE+iYy zYObwWP{(WY!%Jgavpf6AiK6$}1=q=#Qrp+|=r^UdzB5#B5=|dn>s1F_ z#oE`aw)H##w>Lv-Z{;c$Yg`ZFkxRa|j@7H{S!%$Q9VOsToe`_5+jzaF>!r0VRn?;9 z>2gw5ja3ccpxBy*=IW{jeM(lR_c(K_)7$GCaV@EPIJK_2Sa56!F9lQ)&Wp!wXs=r! zR<$msSGamX16-hW;qo2QTKwb8D>|%ERm3H(#2VYy)JvI*c-YaCkV#h$cA`^vH?UK) zj~pc0tMDVcvZJxe>`jqGS0Cs^S{-Yu!etiP;jG%ep`}jF1C7-&oUU>CL3KM$^B`tj z;Bs|idyExvTk}6TGemmPJ0)t)-rY{w&6y$6%m3=k5b3P%o3v+V265)ky@}5ZyXh1? zz&tZJou=2U#YJlK%-Rmz7r+H@(Ry53O%u7Oczu2$|M6G5Je*St%NF;|z$E$GM`mDa zuPxC)>ymx4Mf<>v*`mFTzp-X~kM56qY?N@yv6vIT0KaZbt4U)|c=7~?4<1|kb7 zA>Ujl*(;Igt36za?50oj!O)|Rd-dYja;{!PYp$`Uu5M{=E6UHu>9-oUig0VBy|AUh z*$0UlH`e!TtdIUk!|u*?VvB0qShVMM=S}X>b~;Wzm=i+nvZ`5iO;y#nO;x|TsJI%_ zK}lB^cFqhmY~7=lOUVsNS#o8lZy#g6nSq<^4OKODg^i7S zZ)|#fQyXp+z}7yC%h_DsF2Hfx)mqgex4?@^76TB=XT|p38vz9uw}sl0nHr|a6&h}- zPeUfwxA~R%llApm^#)$i^=xF0l`pkN%zifR_R13OK?5B2g{7(%+#;{t7nXF2B;2jh zdt!2Zo6~de_q#W7dgk_s>Ul|siL}AZ_C4x2105Uco9ayGSkoym5nIbeRTE}4o`>)h zL*c=MJn0$j72M-I#vA`KK{l+mvJ(#O-kE1^NKxDn1;FD@=452MJT+)3^q&uvIbH1u zd-s>GJ+6v915;a?;Rlnjc{o*q5GDn>W@k^j-TaVwYgdPinY5}MPxqQz3cJdx%W6t$ z%5W>FtE+4=CkFpei@Z?qCqKEPShB9Hyf9X_u0*!G=W#z1$31WOHt{iE`IMN~DsBSU zZR>C@5rfXAN0|0U05`gWIQ+e(<1sVDq>iR~JgAD{fk#nS$^6ce&cecJm;k(cXI>9~ z$Re-D{2}A*I6h&OTh8_&q`N6@_Ix?(I05oh-q75%CT23FHwS$?SC%19B6o8BB#dr* zGtR|ztvDQUPT~33q(aaI!;`kU)}|`FD$?U1clTQK4vU`%?H;to_9mgGo6D3r$Ne7NDC0wkLibW7I7@q%C~k}0U(C2I zd)m^MCT@$~Y&k8>Xzv*hVQZ?ZYEIExv^V={R!c|QTHKY|7q+U(_dXtbLMEfc-@K3^ z?aM$3agqY^rv(#;ek-u33+L}bFD3H#_?U^BlKtHsc*8^CJv~JxvKpjW#6_s<-EG(N z0@NA7Svp3%%M~49;Z(e*=ib_NeeC&I^)?B6*1ptDJ8xWGN}{Aswg#Cu1vwYU%7P}kb2>YGi~ z4E<7=)6-PUjJMgz+wWBkc*Cg;cfWC+)T!{Gq<(#@L1g`swTSSCx8zh!LmdDMLadT+ zOUqq%%)_-X!Z#7x*48(oF4n*W-l(mIy;dw58t|%z!YjF*N?si>5pkZ2;cC4RZ#TBr zY2_@ZjCUS7@#aLV6))U!%@ypL-c#AT18>%~;Ca=}=qMjyHo&t82!MIrOJD`!obD@sfH&4DadTjtyV@4imWu={~K! zqotv)XwmWL5u2_Ddvbj(?!92k3Ofs@jEl(w)I!|mf!W#ySy}72o9(X z4(4i9UNwhhJ#Ws6de9#UZa572sySoo<*lq}H+_Hj{-xYV%zfIL9(ObU#~alrZ{7>9 z*uy-aWE$n$@XfRE{x4sxu2~D*E1wiA^Aci@uEF?D!R~rR-cv0MdoA`NBz5z}$X-I^ zlpePc)_ebZqK8d?AmJPEAG|2&%L)+aj$nZ=3>6XvDd~p zzID9$zt>UWrC>x=i|1UpAJDMZ_IO981=nhL)ZX{;(ia&-eazXI!((lj~zzL}yFTXpL z`YDHJlW#?0X5<5EzC~$m^3zL!yIH)`-CB#6+``E}y5+Rpwc=Qq=^pQ_uW7;?eXCpR z+^Z|syM3zDjGM~L|nOjb#F#-6qs57yfYiyNolWIfX~ad!-EMvJYU zQS0+#)WAfK_U>MS+-EKl4NQ$cFgO5s71q|m_e*h7atEzP3Pta2yw|Z9HAi zijyZreRxDSG}$>BCntHWi(>}=NOn9*28&@*TfZkQYr>WlYnx`q?6au+X@Ob$HU;PL zzFoNWjA5S|O%Sd=T%)dU~i1-lVotBnKD&BRo&eSQf^L!9kFY9lG@E{ zQ*J-=8fx)mOp5khDfz@w_!d>7<~?4mifE444IP_P@MczYBgazDMtgjVL0;r?&BynQ z-ow-Opl9@~2fR1$ihUWsz4SKoEkCA;(`-?6%)Rst?=#{;rq|v$V4WAs_-;i{b7mIF zM=sVh*8-_Q=6hvxv|rl_E;pu>N`Gl9pjXZ@G$ z*;Vr;J+^(>j`d%%V@==s#qGa>wlBE@6L*aFRsUsuCG1FSaI%aECa=jRNR{|*1#Mrl zU;UTshcIz<`K7}AQvDF-Zu<3p(Um`?SUyTL4#JgG_}O0bO%QVV*ZWq?l8xY}r>5y|j!4k{f3S^s zJk)a=r(zp>Y`Wb>H%vQs`v2TChkA9@P>w+ zt}!G3f9Bq;J8~OI7tNnC5Bqg?SE{7CoHvgvJ)`X!Tc^t1XRm(YqB5BhU3qgdQz`ku zzx{k)03ZPpAi;~O$IGQ8LBs|3Ktv#bgHRi#hjFI)D(h19=5W^e8=iiD(TJ;I(*p6n zg22&T<+2+EXp>q-L3l{T0otUjQQf;#W_Y#$+N8i-1cbj-Er8k@)ZDLJT~nldN;hy; ztZ8MeE!2Bx#kYBp-99bi0JvBbhYkGyA*8G`(FI)}(p>Gx=d?wxaI7DSHN+aoc@%HeuJwZ!glChuFClCNurui`P7FX z_c(*-HA>2IXg4Q&W7tw8T8d+e6v7Jnw$uB%lrO({J}G~X^(a@^3> z#3A)m?ezuGb{qjcO2vL75tG{B{Gxdiu4xmhtV>p~BJC5b3`pWTU=6W%N(+GzR{vs@ zgx#*+{mW9(YFR8lr+>cugEPeK@1Mi4pll*~((g$m0?H<0)h?qp^>339lug8{-B5NRS8oWUtc7%3P@aHpp1I_qy(nL~U*PqleGJ@mnpzsG4OW3Z zOLUh^0Ih1i6LDg9DjaF{b!37ty+%nxD|fg^YUvJ>FhvSs?vM$>h`qeKt9Q3d5JqqF z?PBee3BpKyTaat4J?mq-L{PK`#Nu=ML(AgR3RasRaK?7tnm;_%wSw7X^sLpI-$Nz_ z%qFAft-fU1z?3-tc|NBd7bn9IY)Q9*`SM16sXkab#?lC3+cvO$vCy>VUM`&69Y%xx z&M6M|u;E}N;tsa^n-oK?>^x>{M9cJ5Ixrfo>EtFdBybadNiJ>xiax0119v*&-^$CMbHxRU1 ztw0|PnE_6CbIS1{W+t$%w&Ab%?%#TCc$?jNTKsM1Y_~ZBImMiP zHbx-rV7GrgN3c5vshZl2Qli~+>E@JeHU~8v{cysGbNYzpN*hkE3YA7$+bB)+wv=T7i83t-yR4?X0?Igo)`TnK+@BLHnuR#WsN6$faOvYMhFsW?EJ zl+_gdNW}r#q^!1ribXkc_HC;cK%10R?dJFPSzlE%kW}zVkQm$4BgS8h71xaomIFat;6i;Nj!S z7|3#}V9+VP#bP;OwR}wNO%$oMW#Vj^A>c`1Vcz8jIQeXfp_N}m~&8H&8s}zRO<-Go}4(2 z+WK8N2RMLXqvhQ8J#t`FC8G8UafbJNo6jpt?Kk!}B~L)Uu77 z#!i9O?_;B)5d&Q-;I{JNus^712)5y0JFE<|be6*+ZZc#wMWU|6T+-Vd^uCZdTl)v|rVmHM|axCof3bDi8tGTm!m+8Y@6I zNOS&=fN9MB-7t;0KM2yClQHuLa|arR^L`MfNdfbBFn5ST8%%TdMt3)3(A!&@5N5s) zGUfr%vwaT`YZ&(6i!*%>BA@g;-vn`I`Sv}fm~8ZH>xT=>@-z{-v-CVp@u<$>JM+7N z>`*)UAbnDMNF-l;pg=0oyzSNHb@mLcq(U49_aWj}=4ao#ap}4L>8Kg9+jB$W7GL)) z>i^tx*Al)#jxpGRhIMYipTXlzj=f9v47J87voXC&+wy|Hr&VTR5%}m0Yv4%4{hFc$ zsTp@2rh*&X(tvw!t>995z$hbuO|VVp@IUcP+xzNFo8D*J6=#}GB4Hr}vTVdv zhHycvV{fq#|MG)xE~9GrTcdjZhVc*7(TT3o&;LgrU9_4xT_O@2!eU$F!)<0KLsTVXp*kH^XtwWSo9h}QkwiZy)pRN`k)$8M+`-kztxrvT>H%< zf41;6ztK#ZlY#HISy3RSiJR+<$+gPd47$%mEej05BJmC3PrA|sdci}LDdDavaCF1@ zyBz{ULIGW#te9Wx3y%;2l3(nR&25fWgNm-2VX<8GsGZx?yu>hS&*~9rIsmGm5+-;p z#Ye{}i!nYw;&$`PHr>6zFjbvziw(k2hc@FD-3}`8B152^6RZz5>N4`lyJr!R>~E+o zUioAvMcTfKmz@h1S^Vn;pzdpCU*zB4G{GA5VgaN2c7vYoI+an8ZKrFWyJzF+T8|>6 zE2%xFxLvB89o_@|ogOe5x;#wb@K7S{U{~728}!KES`tO5i`@y3hK`dipYENpfC*hk z*uyA+@tomLRfhHkl>k!zHzubvy~^29mxG$#K}naI%8f zI?Xxk4v=<~9?ty3q#cdx*5So~m8s@!(TptiFhnqoHe}N zGPKK@N1qylP(e`8*Rfk_pf93{9t{3G4qWNM2U9<%L&=3NB%9VR`Xq){#Z$Z)EEzLEKfmH|Oqg3HbJ5b(V|ocel@I zsT+B|{ro&%;GbM!4_hVw8$`^CJQ_(%-=aQ{o)yG&a(ZnQ6;(lP2&$Uytmketx(>sb zx`dk{kV>u@0;xorA&^R%83L&UnIVu$h8Y5>#FrtEN^%(jsf3mxkV;+&LqffmpY|zD zj_SH%(GlLhJS`xk<7W84#N>xUm`FdAnZfm4Rdi#6Yf;;2Cro0s?dLVGe6F)oLre|f zw1^Q&sK9<>a=evp68!c!s^3-%ZLU^tok+uhYOD}6-LCo}Xt-eY18=%x^@MM@X7z(_ zxM{V6>!lqs2k*DV?b8K}6B2}x0-mdE5glD!bI7Zi78>s!YAHcJO&3(3u3lI@T!B!3@FvK_L8WImW=J7f#V z$H64qAzMf;2a{}vY#|AXm|#jH-%a*}8;urUzRr_;F_@ddNLv`?Y+19`LjF%^iZLf( zY)dY}SM(l(6Om{yM02C;oV5I)3v(P;fU)RXnE#O6{+j%B`x*Tr7d>+S8jeKK!o=MZ zIv0B9km~7zZ6S-U(MJOnRt-tydGZyUiN<%deSShIn0xLb$Kwzb+8VIbkRRe*Q!m1URUUu-g z*g8Sg*m>!_w!p#VGm&KvcXZ<;Uj?cP`N7|MZw>0N};A#k7=V^AB zVQ%f*W{Ve>+w9Kba+{4+TyC=`ipy=bGjX{iwi|JXI2HEVV+7ImyNxx7W^OkoxI@>6 zA6cfag&@13%|jTa+wVg%M@!GOd8$O}FhM)Ny#crrF+L3EGK#|Xk-$Ct>m{q^FzVI0 z!Q&iS?AA>NO8SxR989|ST==b${FqCU! zrV~KhF5AppG`HQf5sko6S=^?XNVWJVx*Radu|whEyRHi}l1 zL^R5js9S2k=bYTX<|iT0taTSH>$_bI5?SLDqIE)HzjZDa42Ve;1P|fGK=@+d^aoVC z=3x|7ydwLC%0S^9RzWcuP`iEL1e%KSUpId*nzD|b%q>XovgCo(BW0faly5fwm2D2{ zQpDylJG#EWbG%;ID0s$BZ-*ZwKh&;U46x>+_SOqVQ%wTsK&|V$x*SjL`U^0CU7J4h zl&|1_0EdUHQH^Fb?rsNI5#X0O7zLXmh(b3ec6vKp6#<>)asR?VlV*|t>Foi#5T5Z3 z7GW542kD_iyWqO(yS=dO@N#E>x3W}mX{xQcqa+BKuw|VG&A6X)xT!KOP%CGzfx4UN zkn&|b&jT@cvuq7~coL0gv=_c!?4dVJ%3e3VZuY#Acu10)g8yj=4lE#sXD`j$1nuT6 z_tboJREP3@QGF27%&_?<3P~p;`CX|u)s;Jfp&rOO7z^&iyN1MI?x&|Xw1@*ctG99swg56y{ z=WifI4eorM2)Y=!dm76@Cx$K-He)&HLeRy)?_(M0LeRxPK9+$l1YHa~j%A<=K^Ftd zu?%z}=wg6VOwCw^1%2Gu9DuWnP0yq^lF8l}yI5>4I3qdii?D-1wu-BZ@tUrX&D}y# z&g7Ygk-g%T$@eaNq$29I3O_0Nj>6xyxucA1)-kv{*=C<<9*rK`6Yn_m2jJ~ux7-np zt(^+i( zwsEfZ{fk&s93pkO0BJ$3XdB{wu4g?sbT@cpIplm6i?s3{i-jl$E6$)O|1lq=8mjc+ zI-L)j47b*#>)X%UH;Z3!$(PxvUgayL)4>g2yar76M?P%ES}`#?`|<|mgFJtO%RZC! z{m;=hy56YCQACxv#zUhVZTA=58uRrrT_&si0a3C-9NA#HoAm|L?a>!ZH%J?p z9^ONb$y4t_<8FeZ_4KI@RYHV^A(~-v7y(~-D2~UXy%U3o$}^txH)U+x5bKs{-MekU z^w9^0SNx8_QSyvyh|-4;x3m`MKyJs3cikdv!i~gb2zBp4W4RAXZ;6{@xE=Hm92ra2Wv;;#B}zt}Kw z=wHQUv>)k^x&SriwF;|ozHPM;tux|9FP0Ps-<;J9RX@b zp-^XLN1-tLi4g@+=VwQ8p-$0`LZQymjzXbM)Q&=-&ee`Wp-$J1LSc4$osBxoyuoXX zIhEoXi{lAFUv2}!*g{|-^_1})$%XVzN zw4)xUPHD&OWjnUEu|H*PZ}z)~*QxRd0^S0|)_Vm0ag`rIKo`KaI2a4Xe9r1!!I`*a zGU*NIA!tk-y$MDEdI%aDNpFHtfF6Rz$kLl&6rhKovC{M=7zOAdXv{pl2}S{W2u9e6 zdh;?Cr-w~$uzJ~`dNVyO1%DBmGJMELHH7_%uzOgqOkutGiUjo#ZCcZM6CZ}+gSqcY zo%!-!@#I}xY4>=8Ym~BNe_RCx#|phHa9;G@rLP0Ms=`;7#b+UKJ` zp!WKR0~{m+aIPSW8Ss zq}d8CYSw?7JlV;<-2zjg)=V#9+urTFg8g0pnH~4_NjVxrB_m9MM~ew9sOC+B?)&Ue zSM&?8$CJ}x=;#YzO!C zWSb8h24gU2kA@LEXn}bI2JO!<0)uvE7=b~1GmOBXof$@8(7p^KFlbkX5g7C?rW1o_ zE`J;Bzl%x7>2To6Myo-X0Uha{ATiT|3VBQQeMb z*br>RX}Zv~V=#*3z+M}TyJz=m#T(zfZoIwAJ1<8rLw<~-R-ty3(cRUL##`3N^}>(Q zU)E75HIuJvY-%sfzk;?qxlcOiTMPRt(~O^Dpk+g|O^0#IPs4P`dJ|4c#BHk(YP6w$ zQ=nXyytC0H;)B0tT58{&k2{T7e*A4UKM8?mt-EMh-)%;$R<_MBU}H{**6UD#FfCA_ zKV?agKQt8GrW!pVG~V_GG!7NL0gXdNZ$PaBe~W-9>7X+91~g^t4QR^P3aCeo>-=k8R)r)1^J3_^1>#040xsG4HYed2ZcoI zc$;`yeZ-pCb;tAih&6NjW(_?Q=gaf)m=rJD`~9ZgX?59&D}(#@h+e7?wGJie&Zy@$gUJON&$Gi2d{}FqmEZ z-hS%hmndry_)RU%^*znFr1u*&uQ%KCDSKWlKJG8O0;hkM4bBW?W1xFWkLX1AX%8gc zA_kC*X@d{EmDI*Bu#N z%BIo&1*BD>%_`n=7C`nEA)>9Q-;ZFRRR_*EZDsNvhx5rq9kZI3hTBdd?t={?)1?=& z?t7*|CdAxQ^F1fwHpacRJ_Y_}jk{P`*KO*yHm2>`o&c+^X?Up@kLfX6C6_Gy23Zq# z&d=ZANY+ZF)CIeLn0cqU$)=$Bl-B_U=6}y)$;+qH?Wf|?nHr+)J%nH!LO;Rfb(=mT zz%&E51*lcf`55TSas=gK3~)XIc-bE|-XQp{wcdvXsOrEOEktzSamAa+Rlgl)xy`@1 z;IE3e0((hEdsH+z97&1NqUrPb^Lsb==Z zy6_>}VbKUzSq0iy6rw@vD?&8jr}}ab4_RLeq9N-GK^I_zzMgYWuun$7S4M;JSoCxd zL{v@A#}y9o2L@87680t%+B*v@TA}BfIHMJy->TpXv6m4B_4Hb#9>{M?(WVKA~1j|@1d^xpL+}Zi!VErZX!DquF1TxOH(#`|8!sk)pom`Ne`bMES6e~7t&Gi5P4nD|HCj~c#571) z?8MsG`*G{+Zst_@>rPBAf06Y^vjzh)s7SE!&ExG~Zu5xZejxf-?ooSXIEm?*kHzlk zW8MNRuH$+1B5*5Mw6|>-J$!lFtq)&b1TJ5q8g1k2l@*jNq>aV|4EM29AbXpJvW1{m zuQWuP*FwV-YM|1s1+$lXcXH}9eYEv?n{yW}YrHWvS^>YjSoKmiXd--n%!=&z)L5Oo zI3ou^2&Yki!BCvyvIAU_bG}bRmqq2$V_GCn>E_&E#em(ID1G`2`AutX>lAu>#zEC4 zU3mu=4l3eQ?BBTcJ+cbp@teLh>Co;^e%K%!MyKD9iKkIYwC|5A>6U>e?UYsH;l15q z(E)$GhGXTetB}3%GHk@~fNuZ>DxzW*jS;88d_k*wfS9n;JwQz0=pG;@^m7jo6TG z=TFaM9*F}|R(d+6%g1DWKAn%jj`6xe`y9r@H6m1DCkl_bXeL69)L|PRLCu{YI;G!% zlzO&#xVYj+#Y;-*HuQb!b}+HNRohBPb@+FxPv1T*Ze+!%&w6pL$@^WSL+bJ5HF?k9 zXqRRWoSv&ITg_$h;dDG_yL8*2(Z~zCPITVO;^R8q6tRd~Gk-k291wYTx87g-_|$cA zgGg29W5E+S;&M5EyHjUZ9^n+aX_QVuDeugvtn&|L)GX|eaF_4>ChGvyHF&dR0dALz zn-hWRoj~X6lxE+a@(5V}df5UyOz~M=e6~NIlKnb4rn`p_do>bX7BS^mx>f3MdXadQ z?bjdWPf75h;R%2 zpe;nrVm*Lp2WSgXv*r&V+5y@^)QAoPh<1Rs5H%9W0HPhBEkq*(nF0I^$J)Xw1({x= z(g4P%qS0QAc$sQg5k}*0Vc!;~Yqy__eQF>0vggS9uW{J<0SKqr0h>FKNi<%QNe_Z5!>wsXK{X)6*fX+zfFR zCvWVDRe9bbh|VUzUmgy|pwF|5j4PYL?==K9pPwG#@1tA*-Vq|0)8pOCApsEFJ_%o# ztihNWIq%?fd&&`6a(`T9JRVM$QBalFCYbJA-bg_>@u^Q!Xea%;g23vTmJ>e@qDH}a ziGo{(CsL;ZA_=y_n2PD)Rq&3XS(|m$ipjfBF4{4b#`CxLX{bRvZRc^Ye)fE@x=|aa z2fXqQEaAKC`Lql)R0D~hjh;ySoZJ)`Q6m}Yhr`du`{E4u&9R*H#p37XU2%Wj9!6G5 z0Ern5jW!Ojf;vIS)_O+?VhQvVKNj6*-Hn=;kEX=Wsdm%C*`!FljCzaeGD;`jevFPp zYEA8jO@2xcV+HF@-}}$P5}>Gvx=K`+0#PS@^iu<=tD+m}q9;vcZ?Us=6!^Q+476}a zZVgwaNW>i_^NN>pjMY6gy%;6>80uhE+?|du z%cuL$LaNc|a7$y+7;gMU>dnmnH1oIF^D;Y}^8Jo})GZ~i2UBRtYDH3L$rXw}-vVNL zJR6V1$n3@;FfzMw<%`U2obV#E8~3@$?8fmeGJAwyS|ldUER+(g?PvQL@_4+>nI`0M zABnSacZvkC{j=`A&J%{<4UPNGZDJIte|&~P=i!Sif}93mB*1W}bn*6p>s5M6>vN-? zs0T^%UW8`Oo*rYgNx;jOx1ioe#lW#F9}?%uS9AV?j=`u{G)p?z=p)f{xQD&iyj7x0 z@cjt71so1VylLZzN=vgF~M9#^64 z6z1fv1E}>8HgSJUAF|uaqF451ID2RVAH@HLm&z%Y?F;9^`E?XJ9`H8X{iw`lvmce& zZ1tlun~i={X0y$Y%4|0IQJEvQ_)&N`b@bZc$6{^DqM_}56vk?EAIknJJCH77!!`*q zSey0NwnGSER6&D&49q6Ht4OAY!}%1Z+srC{c@x9WY^mk*b9$dY&FTM9Jm%Y^j5T$$+wTuoi>F!g&tLQgu8+3+ zQ!A*qGI>Iuit-xhwT`!o5VsHe#@Bk-D;M}`UPZ-Xr(CJnSZ*e`_=G;Gu3pP-b@1v7 zE@4>V-r3?*C1LY=Ri6iIUkxfOrS2D}3EfX@b0;E6^|_{ZuRaJX7#;djF)V%cZ+6I@ z`ZqgBPxWp7_K2&=P;)AJkM&``**{>LFYQ((3lDG~a(GYj?ZM4rN)898>Qj4Htq@dE zimJ5vyB#j3K+~5tiR#-&Pnz%v8Appm$84>x?5Ln5M{^2uGn9Tpf#mn}S3j` znwx{6RyAu?I9&*BZZ2JmCef)sXU&{{yxrxe|9ClN|GC-UrZolxLo}sJuW_TYC!Up0{x08)cNw3A}wy?Mj&8Zg|$$bu9I6t4|kI9e)|1s z0R{5M&k*1KQwf}Awwb?SSLIZcLku;ktoC=R_qd66I6wCbZW!8ZFmZ@{YU7zB*pz%p z?q3*GubJUWqSl2zzem`uZC+#uZRk?OZcEuUN}ojcdleGVO(#Qgzn-Dkyk@TppmB+k z3sBy+RKGIG&DLO~XZFUuN*(Aw)o)Yk$X~xh$<1DM1#U6y7B9O({X-d^(9PfIA$7R9 z+e7M~JB>Rva#4$`AEw=IT!V?UpVy!UNmecnt3v$Czngu|7`<3U@^*7}4X9R&QG{yN z_b3?6+@5O#E&qLh@?JoV_KG5<%e00|EWE(t*wYQf`tE&0RjnCJTTg&$#O+o!rrbX4 ztwspXH49q}N7WjrqF~K-qIq2>xf;)PVxcWahZ~oR^@G{tDQ}e?j@pab#H=tu0@j$~ zFCD96n%@Xh)JvIFovH|L2u$zh5DuH6Qc8F6meSji0+?7zg~?aSI84n_j>hQgAw~{g zr_1c5T>RRV1@>Y)f4@ca<(I>Gx2)PiOg3))`tm8Qb$32>qh)tKb&X{$Uwzy7qa!N> zwvBEkXWLkPDmQ{vlI$1iySCbA-^QrQ(%i#T->yVhPLId*CD~;ceGhZ>UBqUk*sT(6 z3A;+gw7pV})m0k7Eos;N&@XVN3){Twz&|Ftp!}nz1{Jj)8kiW($XvSnZ%=QM9S-aC z(vW;outQ)1^g0AUFTE(3-yU}#%ECnoWd54z1#GIO7f_&XD9*GTsnd%TLEQrO0t!&C=$Fq^Hy3}u59^pNeuL#d{6cF@i13TgK%7IL#?^$;qh zgHH`8tv3=gyj-kQ%R(W|a+$5Z&fn!bIro~R#|OAr?M~GxaN*Ny3B1?jZ!x2PmZ#bYF-hoO2dd@#LmWh1&TabZeZ1_Oeo%*Ft$H!qq0g! z;%jCA8c+4@shSP?vrh{z3&7;xz-fo>B--UoCc%}PI}$BTr-oGQ5mqi z74)*Z6HZ096GjWkm0HbgUr&}jpltW1ENyuBdYVH{v<(F%kYy++)BJ*Wg-rUr$4pQn zV1~*};7=~i1m)-Xm3`$%jU0>vD>iLWz$>HrW{dk(Y9;PhX~GlQQMPW>ikEcdi^g0u zzKB(d#vty#Pucd+$Wba_>qxZ%ww^q{F>I8(`5HI#8^ca8heyrt6sV@eZSa6e*XZTX zr}c+Mp*ZmE3<+}0-!-z8x_6IO-{mL54B!A%n49WBK4A z2Q$oYhm$)WG)H|s2kK8*;OZYLvx`HkIqK_x%~9XTQ6Ke<3=Pwb!-L)`K#U6<#nY8g z7m>A+!R#LW>Wo?i_JIk|GrPw=^m@TmO7GU2E!~n?l^ECxt2%eKEs-034OvsZ^a3`U zkzPQ71~3iYT24c-*5Iu$0eYtKT48JSqG0OuBDDq1;4yZ)F4I_h8+Mq;ycD}s3@%Wk zQ}?OO4!fGaY@;*~F7p$hs<*WnuY;5sUhdfC`s+n>-PwxAF$x2JQ;f%GhSzkMst(!H zwCGg+M=`u4aK0R3m~&9Q=XP!iM5Anl4olkh1*S@gUo3oj28KaaF3L*bl^$5SVc~Ny z>iQaJesoYteNBOAltt8Gsc9<|A)%i|)WK-=FPSj=nM55_W&awBsOn#1F*W~vN6GG9Wwmz<6%&qnfaZ@sIQ{c9|us(+2e)a+lQF+z{DgT@V-$J3s>=?}M` zxAS-Px}a|ClCQEIudUv;dliSylkZJs*S=LJ=-lbVXVCWMgE`pRwozrE%;U}o z;r7bS^+_F;s}XHxQ|HHO*=**umE9%hvD$m{*@(0mz7vr*UxV?uT&xASj@F9TK=ui> z(9C8tuYChLnRoJiJzen#)Fb<-7|d&?_v)0@)9ient+%J-JWJ#sy7cb(gqQVktDkTu z9XxJNvlC(Uz}a8rS`Rq;87e^et{3pxU&dKy_E&W{ zV|IZa5rD^?`rYVX{d3Hitc<5}phM@9WaxS|@V!pfzw!g}OeN8kJkhYitL5o^4~qH$ z+WlGbEB-v4PP6@Hwa$+PKLa)~&)f90d@SEg>Ly#CwpjCLblu%xMx7n^_vhjS$7sQD zf6g~27$Tlhlad$vrS-aEK3F&47!FWaG&tGpvJ`g?l7kh0PFsZFT;ZWWI+(c6Xbxcl ze1DhFu;TC=9iElmx%#TJr}r?S1hZFP*>VUH`bV-9(&E8^V+7zrl^q5Ez7**bDpSA6 zj|9Mj!7E8o?u@xsFFQGcfJNj5YT(O`=Mey_-NkwPA#UzY?vML)C7%x37oT6OxFOiM`R51=dOjSOioT6HdsL6;Sjh$1 z%sUJxI9FZ1s^s&IiP`GkOfFp#*rx9H1xkLekS(86bpTMOEFZJwH&mC}fUs>Zvbdt0 z06oo`-<{8#bX7(e)|emO?EGN~5vX;>XsvjWKl=k8ck&nI$rE(6Z%Mjj_#>8h%c6r7 z^=+3PP?QrcZO(YJ%eS1LbJcqU z#@G4t8K$xs<|F>(#pQrK>S?x3pQWPJTVAN&6U}NfwAe)qY-|P8Q@({wN+n>@t)+1C zuyd%HSMZ$9Xb3c=`T;NdBZj!78DS>HIDEi_g!_Jx^OVaEI+eibH|%XPNx&|L1CihM zhwR8r&%g1d95sAd?hh|qfwCtw|196$pK)GCo&kY&P|pygzzn-3k6_L8YkDtl7!E2( z@@$neRx2e4*XfyrA>0aQ1j%-tWt&w0!!jZnQ@0sL96j0r3_dcI?2j zZIM05g9IGb&u9>g2h5`CQ`y~T83K&JG)_Q{s+;iRep<1_xzLckFH@%D(Mk5%}$2Dm~)uGp;(+ZOf?U`{J1@QQHeh+ z!QU~{Z^^I6m3h>^=M~Q8U46KJd3Sx{p=~N+GRS!VE&e3l$a1JRf>8VhYKOFm* zou6~kM_1ENr~T!aW76Jb*@~;!D&JS1fz{Ff=2&ZVjK5$|it;#7USdwBe>}3byhtSeos9 zk>f}dYD}*-)e%C7FWEDC2fmu6(@K&i&i}-subN3^1dE3QF1&D4u@W}Xq$ezjn)a5` zgOf!TY5i4xZpjB%2brwEEu!jR=z=r-%n~pSv)uD4e~_p0;bKzMZ}EtE@Ee!PHS&o( zagPTcQsZy7U-O6eMe`Q|0)NoeStA#0S*z+IpA<7h{L`OIZAlsI5B4)#j#aLZq9J`) zCDlQv^I>ilWCpG{-_!+a@^kUZCGb~W|N?d4|(nqTE3 z_UnkH3qcDoT#1oymi%3QF7Tw_D@8YjVOAWMSCACVD~i3#loQ1fGc2>7F8kv*&I!a* z{^}lg+F)492TDxxVDbSL@_bJ=j&Tmz{Rb{B$BC@iqtiq7I7nl!v zA+P}ijS;Tw4_#H{gArs)ijC}Tk!7mq$7r!C$B>EZOm^4_bwdyJPi3cSxsN@f8Tjny%G5Zyg z%R}_l$>PiM2yx;**;ERH#oh99H;0QD79n)yEIHj#2c*3Bxt)PjRpGJ%w_KLRPOud< zba!_@U$)ypIKcyP0=0|t0-Vb}I2kcU53lXLV5}nqz8);X=cYtgggK1INNr+?@d$Cz z<*yfa4ldT7i|fL=^ET@I4chm#KSTVndIYlH-7Rx3#76;$&u?s2(245O-ZvQZQ))t9 zmZ!bjbz31nzlD0cbyL3h!m9C>Q&a!^_DvIqy>VZBS$3eXMvNX)66(kaj`5|92MYm4 zF7`#x(mdPkwTOgP7$7UmB86mJ#DE*faEcg zoz*Vc-~Z0HM<|ob^D(_>-HHAvXYqek86n_7l238a9kOWlj5tyt0>PRO<@5-dQJzof z_MpFE%gCv)oCOgs?;8&%rA{h#k@j6Gx>LQ0b?2qBHy?@Z?XJ<6kV%hkc=y3w+yU59ZC_x0^;) zjK%DE$JP>jW&5d2#mhGIiTyM5O{ZTTf%C{e7BPibbp(7_FCVviC=~511gD0`P1Suz zrDKVL>;G)W?sDW4mqY&IRem$Rpi|1<9j91yFQ_b(`n254eal`F<}+)7Z1=2$`c4p^ z%(`w(3}yqwZHK+I&##?*3zv42pmvcqx+=VATAa<0CZ?Xi_q%M4W5*O#a`If>R8 zNf*>Aezc0Y$|EY)>J>`>RF2G8U>^$=qdeYkzNtr8Jh0cVvKy94lI7;NN>Te*VB~U8 zfr_>RmYCU^D*|Ulco*#Wq$@%=J6_hC6uaCq6{}}0WwYOZJ0EI^$9*lK{*IcH-Bm3c zv@b5bV?Ci*)pD%MgaR8b&aY(GnLI^zR;4kIPQqEPZSjEF6CmvPupHoti-3C4bz$lm z%_CKzN2r<10ikS2Wi?eY4=Wfj#WCX#`-ghMc-y8-GSz*Atrf4i{PlH4rBqh~tONr` z=-Awqupf)!7fK<7-r8jtf_ezoMif&qhMTF)!KV?_2b{*>N&b9wW9$u--Jq})BOSF# z8&7udUS~rj46trm@Oa_m#jW>|CH)X;{SjPj3Cs{0Gk z$Wm_bO_>FioOCKNkh)I6(B;uC5rx_D@Fb2e`WagUeim^Wm9vMi%q*x8hI1_uq9-je zlyfTyeR0KCh+S4HmG$&Bs6a1|8Nzv0@0d_?`#oKm_fjIl$%NV<^2r`Gp$OehZ}+aM zZK@fBrRCZY9KslIWU0o13f|oceul}qtTE|)lJH9S9wVOGvRtuCJF>ZIGaNGDi1G^zA=TN^^9e_7r_>uB}X*DX>HVs1oG?b8@= zxjhyORq1{psrrWVV*qH6bv%62)}~lU>$-#tjGvH#`SCQv=C7E+2V#}t7n1UGfo1)C zy5I+mfFHPd?2B*t0go8K#cYLt;u3N?7qi0#f8eU6fQlLR7kI=VrWvxpGgnHCJU-C; zt`d|ih-c$bL5#G2AM=!X_<|J-9-(+tzsi6|4&fzrOqYq+@4yW#ch)QX5NPo$V9Hyc zV5=);1+C=j32T@<05|PW@cm&1ysfIY1d+p;3UTH?^e=4p=J9L(Adi^lhCi2H!S+YqT`c*zqlI5NU8;17p3gD$n-p>Q(_b;|lZ-(~L$ZEfKIU*~ zF$o|iA5)qd1zsG&w$Ui^AK)>Hq! z!{%g_l*x(0U`#TQgis86`}2XFPTd}A-i@4gDj?~c;qn4k6Xt_{XbYtZ)G5sr=!c0E zyPkusicFj(np-i(d{# z8L9>gjto=&9{GnpS@==Y1)q2yV3vL3BP?_L;VMN;bh@I>jL-NB?>8NH5DAhBMo|)b zBgnj&X$`GD-R;X1ex~mQw6f_L7UwE2zlf-o@78;fn8lF_euN0vk8kKpaK=#LwIme> zIG>rZiziHf7`u2-ZNw*xf)m0npg{O16%OA`s04|x)Zn3mqdKw4QD3C7&5M-{zEfug zOs#U#H>(7*a_Uxsql?~Fg4#xHFvT;7jhzS&@`uh!Qb7C_*0=B?O7Wt7ck~-9U(7|H zngmvGRRTC-vP1Iyw8!c8boYX|AKUvqHNv7E++a?{SNQDgQG>Yq7S2rqtu6X$Ke7jzi&ERQI^{9=oD&+P{4+&n1%7?nu(8QG4oSJRgQ{%*8>sOI5- zxlj2s~fRm=fTYpEeba|WaM^ODKzkRRB)p|ioOxEP_j zxCHPc#sRC4*NA>qFUK?DX`(q5Dm_*4MM~~EIdHs*jsTy#N*{(StJL^g^g+v}Xu^pg zfKqeM0p7T2L_bBz*qbH)4Bp5uOD6mQM_=_sZ@Kd^XI3nfD1aPmBEC^@fk$1zdS7CXqf+2KYNc>V6+w@_3i~r$_0TM9?m(G)g`Foj zzcmjDXS3n}`#Z~{ACzQM(9@GvBWMlan-0YhJQbHmI1h7A38X1xI{ge01WQx_r|)n7 z&)@#`banH;-~5f9P5!7^$q}Fq|1Oj0Ihz~mj4+J+T&A_;LrUJ z_>=O_eV&RCC&C*ZPcYI+HB~!pMm>=wuT{9FL=Hf+J+A}#rRxBY5y|~W)*+I62pJeZ zA%Qu-hCX{bq6*mRkLWn`;+J2Qgiw9*W_lHbK-jIQQo>;f%p&_GOu7Kq3mFZ(nD4~U zi&QEU*#xL23Ksk+m5VdlXOL$L@fTkqY~V*6Ayq6XzS4ZjJn~69t3u+MWe5I+lnys? z!0KO0FnEPBOTI22&%1AuP(G0(YHDPu;U}V|Gbd(qD@|*GSWISu-WwzzRDKvX`5^O; z@$5$edmZ(d{D#3Lae}H8?G7wo|0;zZc}@NaUElj-h7rNoQAR{UqI)H<)sLDHa;`pb zk}H90PM?bwWLBWc;YjGgQM;W4QQd8hB3bB$I>C_~RV)WCB=DEKRTmUt>6WVtn5^~$ z=+m6ec*@U0yGv(+7*6Zw-A#~G&LBZdiZANhdJ%pWZ8{DH(Re<3l!xfhS?jAw(M z_eZ*;%EE==tPDFygI*Im5J2IIljK3}Hqep0B>gWaH3&)x&N1{g&sw zs@E^#F871%Dy!80$f-^cH`8=eCI7TPUT~dPl~6uWZ!VIxRH<;nd9!-Md{XS~_a9jI zk`ZP#oT-v|5Y2)IIMnk8PO|*@%Z(q0W>7OiE%~onFga|9v*r1eQhlwDM<{&sP*;fU z7<03~?C^gj5hsxzFna`{G4OW0xe~%j{L2nIS7vb%|8lNADf76ge~B=p>8ev^x(wF+ zD1bFOU_Dqi8O%s1{49m@4STpe;tv)C)Gw?c;*BC+$Y}7HIG4=CwFF1iGP;-`DEbIHTbic21U@Fu@_m0!pk`nVk(p_!vf(Ft%s=V3dnaeMuc z;}8=Qu-7^5)uS34T3G-bBDnFim{B00bk(!^UgZ{R2>dy6cs5llNA;bs+yj-!6aqKt zPKD87=Z^%Y=+=j~*)vSOizFwc8vxXiOm3pv54sbj7KHi0@p|Duo1i`{IJ*cSu3itB0KD@sJ=@ zuO1(9bc8f8HLFhOcxfm_4Zfy3tP4~Qps7yz!+C!$ z#Q}-~^N!aG8k%QOm#~^aDT0HOas~huq0XX|ulfPDnN04_M2=1NkS<>sW3jYEB2_B_ zm1UB8LzA7yEXo%&3{jQudVZh=1#74QQNRB!1b#hYh2*XREx{)VV@ec{82xzX&_ZBP z^J>oyN(=yRoG?T+Df2*?95rj`+|+bn`G9tGc2A;I@c=W9^F#Y~67xBGg?c~=4NFXr zU)0VEl!-WLCI_bghf#<{mw9AMryk40ZSnzC#csx36adOc2>m)qWQo~lxya~8?D+m6 z8Re8}B13?SG#3`U0l`-6seBZnxqL&f+2D*Ws`w9lS^cV{N!%&$^va8_L*iRZfyv*RE9v&A2(UhsoK#b=q#l@g4v)f0CV~3t?jt44v`1XLm`@^BJ#l>v?x6S5h`|nsO=^gqv_JZf4n35{pkSZ2Oe!O| zD8<1(IHY?HhfFuPt1>@5Zu`(QEx@AVME&WUZu)==%P^Hb_6EWlgq?mLFvF^DXwF|s zpzVW17*_kL-eAq4)*FQ^@mU`*Q)-DjVHDea5J-u|=Cg+`yAPxx&AuULR{8)7StZ&F z81^QVPfq)Tvc>U%Mil;Hr!Ie?^LWUvAZl>mWTz-6Q=KLsjyq^B0l3k>`sax0Lz4Bc z{y9>=$=v!^|Cp@@loG#V8wTYk@|20NRjjIH_3a*~TxPh03xC11{H4q}!{z7rTR%2K z8w~Q5*Lli2GBKHX=~O4u6!fjc#~*Hd@xw!Y7$ST`%8tKym0xUBs0o6=hj1p`?c!Ut z{cWb`ENXiQNf+70M#Qr-ffF_G3=pKukiltHHu%BIc|!Dg*pv- zlKg~VU0?8c&p#>uB>V$7(vm-{j+GdXmrRob=GO_HapoC2G9;k+OtbhDjp z`A2M9d_Z^_Y==-~u$S{!OY|8mRp|6M(Fi{RBtBl2_{CV@54I|p$JCS2ahGp8opCNy zTB%V`uk1UbO;E4U(dc}v6qTm@`P8%eD@4&!>YNWbU~c~6-{0}?H~jm8f4}12FZg$h zfB%Jl|A~J;;om3x`{6LtdJYU-fFkGxee?M!e{i6m(FUl?LmTYNfJf8{CVytfJYv-i(n#8z^)Rlggk(UwzYZcZ)&RkSA zh&?ZY^HlF>91H+7jDk_^BGry9Zo&rM)A5NBV?OgOd)^_O!M7dUZtx~sUkR#IJf2UC zYK6out%RH3L|gCzYmFCF3>CS0+HQu48udPV#tF+4e^36sIDg_StV)J48@_kyS+MEnuTWf5 z1$&EgAC(sy;#B%yO~x2;KfLg6dw6aG=VfmK{J|2VumGMdM0j@jk=CGh3=3B_Wt+v$v;#+N7yp$h7n_l*^bzhrC}SARpDU7EAP|l%&!d;k-+q zpa~Z97mai210f(E2;8GE#kfE!SRPQJU7)muRfE$FGom%o{K#SwaQYY3RVHj8fXaED z*=obQ&s0&X1dL;Kx{LR$uw3XKZ;!H{Zega3+pZu#n`Ky~r$1 zDZy+FdllV;eL+PKd_$a@K&M618(BIZ7H~*rn@F#VgD29Tqs%37zFq# zbt_^ggh=MbuJj%Z7m(Lyu!EfFxh{tAS@Kz47y1pI@kGx=ppadGJfpKGOc9G1AMo!> zdif1<%`G1JuRi6$2U)b?$xrxLdKI~sG<*GnaG=Awr1^q4$?4a{r!W$)!;p)F;g;)2 zY8N$lSy^lf>vV?0Lk--^L<{(v$_eE5a`)5I-4i(s5wmk|dgcDTSMI!5?#Euam%VZ$ zvwg7VMh;ahzI>f0`JxvhV42sh)>|NrN7jw+u6^xZY%2hTdxJ9RTqXbc`PcvW;d7Gw zlFUCC8*MDgyC)P31&q!AA-VlE`RVpE>Lb4k!__>qoLDI6(VO`j3@sYxFiPKR6MxkY z|DJwC@CjFh#1KO$(c-CVPxhF% zm;7_Sn=cl)?&#n|hCn18r@~r+8EMcVYk>7hykSMdy-zg%W(x$0a+w)aQ*bFfY~bK) zp)>5gw`(4H^X%fU{)J)5D(p1O;r>m=2VP84Qtf@n?IZS25WCVsjVlacj-Cc$-u0BvHBmqRPG8)6fyMCnQJTg^2o-ghc4 zX~|>n@ic!cac3ncJ6w*fVP%@zpd8fR@#v#xfccehEbd&dz;G<~cz)koHB6t}S75pq ziFnT6RWf@D|vu)@r9SOp;NJw{SQfhDqwVhA6t_!_(meoW&xK=QcDKPQh#(?s#5X zr@$!~?m-})>$drC3Z~=nNAuj62VFj+@zf_QLBl|1+;TGRk!(Hn>_S!g_I$+uS5QyE zoA>lWCz;#rXPn?$ES6TVRmegBh0AohflDhM)UUR7r7!BZ9zXFIFpnL=D$74|eh=1G zxFO($f65Re)n!|1`t%$N2~MB$Ys{atnvophQUpSp++77Iiqgq@*_&S-wOEX$IG~Jk zT}FEBeun~%AvdCQ^yvPMr5i$SMCquy_>QF;LT*6mbci3?G*6GztAB?gj;1-FoO5f6 zafPXdJoV-GDJPq02=_1X2Nsy~&G#(r1Vjgxl#{`CFX=d<14~*{q58vRP1u8_O~(=K zU(z|_bXAkm_iWigq^syn;*?0w0-o)pC(ASLL8LWReqm330Y>IQg6GY@uu5{)`&D1@!t3s(7iip@vt8bTqO-N-$gL>2Ng&TWy;ss=o=aI{UGy zkT&;BQ(5!1awjj(gyY56G(u}c-VW+T;WjmUQMLNjxEjU!0M2O4PZ;DDat6vRQbZ4wJwKXp^8a*DT)6mnPY&P>WcpHs830lwUH?)D8t6vS1 zJHjKEhNg$dEhd$@r-?6cDq1Xl+i}jR{FnZ3nij{mn7nz_^1Z~l;Qh}yM#89U;@YDf zOaT5H5Zp*42>3%DX{CoRYrzYR;BWo}AJE&cKO}J3Fu4}_;+lsd7N2waTI5^aRq;dO zPPcBcBd5vuVlT%Po8Xfc+q*bKHZ~Voxg}Nka#%h5SJb+_+SYc1k+m9w-@o8S7Qi$c zL<95$!?GV`B+q`7V`|xQyt0_|VvOana^>p67+H~}|5X>hNDia%#qy`UjizER5?wTR zaz8OoahX0irg@E9k%i85Y2Q4|`MECh`#tr(zOBub9(3LY?m*`)Y-HW>jtYH`x_0?e z=NdULVOUoJ|F9`&DEdh5Z-n&;_;e8UZtZs}TBbFD>oxJqn5GF~{q;4Fwv^f5B}3f( z>@TwyiD$nQs7ZgBMh1n{{vPLbBru|EpmES= zgOQZ1`1hahc!K`XGTe9^(4TTDl@kVY;xA6F$uG{@Y!MFkgiFzBv42#*I0}YHr4rU( z0!#APEY4J$_#Mc3d}RKO{FOiJt=#OO;}j4tTALH~rE^ zHb~^`^rp8-Sl;x@5MR(cSOpx$6DH%ZH@(7d2I?RJmUP8!-p=a4R~Yk=$f=#q`f}#uSKEqnV*0{(`SA>Qd@yGw!6M7 zedfpW)$TJt9>3KgET8%Dc#UvtI&JUq+OC*l6B(3)W~g}d(KAeo&%CP7aSXR9)$Hns z=eJX*W}_We%e_d%bKa%38_#$j3ekLf)q%^n_O=qxmaz zdcv7_M-b>bJ>k$9rozx>p$RZ4n~;krdJYILj4r}q>p}1!oQpi3+t8}$;v2?n9PW5t zTNlGA816wJp6j-ia0;g5@kjIASP@-5qw&<2E`>(T#5Xd@-s*{LdylOdjA4kw&3Kj2 zO5n;i#8=!N{=QSecXC|eA&H2;h}j)eI{#Kz=t03zz3aJ82Uk+ZwoRG=ft8IADzcKw zqEAd1tc1WBd!5mOYb5$I?r|BI%~NjPc}fu>1~vJFMfpXqPH<*1x-EwKkuc|#)`})Z zOT$4ImBpv@%WuO`P<=B51%m`U<|_m-GW_n3w|CUAH*d5diOFby#5FZmir9xT*c1Zg zBd`;KLoCR}jl@?L!ox_z@yEH3M98^OHgKkgn{p5SE}a?MZT`NkoyB%4wW)I<;uJiO z7!m0fPNO(J@3wgtMbXj?r?`xy=bi|7*tZ&e$X((i?K(!WSj|yV6WE57mzUha-Egt^`Z4+X!I`IAdS1a4m1<3Q z?8I^Okh4k8J4Pnzu^-G}w(8+at-P;EKd6EKklb-dSSyULm-QW@Ho3*!*LRA5*@c8R zq#v=%Kt!;I)1!n>y8HRlnTB9;*8pzpOZxyfw!-feS*LmC2yxPffoL3a=vQ?m;MVK) z2kb*_=AE50w&k@dxO(G46UF>pKO7AXJ{1$N&<{zIhkObidLfx(lDArd)hL0ZdNfB9 z#iwEd9Qk-0C<+9S(M1`J14ZeFBd9&G%YrCk&9PBJeyS^=dVuCNolQJwT^SV*S=SSV z=92nk5H4_k4E1vN#!xSQCjz~x@vnS6aH9$ol&Ix5?0nIry^@*cJw0N#2Wtu8Vla1#;Hve!&El%{L>sQX z$MjV_xIUz!LH!|AX^X|vZ^>_OT4;IaIhU5`!P{vq{j}bxJKH^W08nVI4CrXaJ|OXw z&1Dxf>LAwrEtdj6q1ra1M+GXUIfQM-ed(zcY77{`#o0Ih~q-Ov2?=OsF-7p{Y#p@*|`?nr5;XUNsT zZp3?@hsN%nzBp=Hc-k;poC+uB4g2QpO_;uP)TuyxD?b%!LoXF?>kgzM9DAvR%EIV4 z)kO8mMe0FJuS)t}2yN63g#J4g3svcUAb$myKw9k7w*1TD1{(gnfDaV+2zPdunY;c= zZCOifSGj%Xg$HTrLr~Aj?S>++i{;*jkQVAfk=r$AZ+FS^mbkf$pp*TUV5|8ae=yi$ zh-KfC*y?){^HigE%(&Iam0wrmFAzI!QS)!{m&Vi^`Gt*gMBRR84m=h9N*r7lr~MjL z(`?~bf_85uw$)_VZh&nw9lCH)V~1&6QHNk_De4e(wEH#h46~LOyCl{LH+{j_D#P7s zkI~t2`_g%135l4pEtO6aJ>$UTZnSbMe{Bkl?1onV5?stn|gASTTDBu+Yb6i5&YjaImvuwybmdxK5Tb$Ql>PA= zu71RaCmp!Rku7)?>hlSAuQK$v^~H36o{Y23!|N-)=-Y}sltQ%}L@8aZ6J@_X;YHWz zx;-l;JpM%LV1s0*{Ya{^c6C`r55p)==vqHjA(Ee;s0t)X_mo8K@bHZT4$=lNtI{ui;q zO_Dw|sMzq`z~Pk?FeOe>8(YNmNFTDou)!0M)#U5l<$L+*sC68oltZV6Ovl+%Z`-ox z)jS7eSjGv9Y1+VFV%K2+;YgWrW}-O=z>h~Cu43QwZF z!dQ8aJ3X=&_gu0#|9&rO%kN4}c_n|xvcdQGHK>_o60tV72OJ}xY7T3h2bV+YQ(^a> zZl4Ny-GcL)wIattr((QbE0ZF3Yh_B*m24#{B(G58S1!d337TBgR;*>sZ3tNZa$YPc zOY!29vR=Jjdid@k@)|b6NdfIn{%ox<)&|oTIM^$g!EbLMI)9Cn=nxKWO78sVTD%nf z>;>z~wb^=sT^W|f#wIqy(8TCGox|UnO^&oa*k#BI?3Rzhaub`se1p-sI(IP8M^8zC zA8Lfgv2kVB2=Z?BuCGkZE!wcHerFk`Lfd54h%0N{Tz}#|s&!W%#ppyRYl`y7p-Qbt zxDSs_1XKsL6gQXlhzIsI--1F6&$g%q z0Vvj)Tby__!+I+(epRNhWRMaXx%yq%41&4S2^Wjk4cvzp{5GkM#-0XJ`2yA0}O^@yjgK&Fm4nxHnZxoVv8NoU~ z6%tvv*w?GoTP5BKbx~73=|F8-%pD)GY%}nTSul!6#O?W3XWfrKmiK7fH z7(~aNZM&ooi4oM^RNh_|*%P$czux*@l#z|!2W2Fea~wn9^iVwRkNE4j(c9}oKz4*BcM3Rtn9Jh5l21;)@FI34sO&~qN>M((Ul zzLQT@Nv*ug$~nP54On?S(qfR1e+7x{g$(XyroDW(L~OXiI_EUSzNQBS(=RYtPq&F@ ztp3;{8U_Y-%z>18_RttA-i0N$Pe37}gp~yDG7KQTvz=_M-aT*~7>YlZe+=PchT9~z zQ#0O%SPw(fgQo4mJqQo%x;-iM?6PgxM|D-~XVe8m@GqUZwWDx572(+Yta0+em~|!k zvw!wSR2_){-IAp|gA}4;MdoRZplz{MfwcQActPp`kGlD4HQoDYw3^*5fU1gXCUYxK zS;gTjAH^_E-yMC7PzPv*7c8%=Ii@H0fOzL2Y$b!m=gGurQBG!tv#Ljz9j2@SM<`p% zJ}pXB_Gxii?Jm0+uU*r-&xvXG=}=bfJ{?Z0-4#-w?Q&4r*+$c$tlE7#oMyRh3fx@^ zgHVT`zo~p{bY#D%tR9aTYi!oB)*VbjS%I}Bt698^KZ%9qgSodr)+2lKU#=KUmoqzC zg+Sa7aA(*yecsFt`^&}(({ocEj6&FJOtOKw_1$xUzO-B14FbkC8>nl*Q3sJfU_Z1f z_HglbDMtZc6L<(6>&U)u4^tp=V>#$ zEOAQqyupouNBPAb@N~pggE*2oEB-j1HnZhD|31DP_W0Rl>GA$0-{EnyfnpoKm__)r zUaA*7rptYSg!CSN^WuUJM?R=uoWa=RmB%R3HAJfoE(_eI`EJF>^)Y)s0QE|K8W$q+ zLPD6ca5W;ImZxL7gKa>)o_F~l=ghnzdOQhce@=@yy`-xBETblKwk;c1YAwHC z9uA2_Y>?zMK^D-xH-8(^bI6G}cftVEho$&^S8O-ka`h}7G z+2r{1&tK+@O8oqs-seyAxf4ub{&DrPgMq6!@#=E)sQf9zRQ&T3j`ZKj8FiQxmK#K; zNq8qYI_`SEzyW{YT_@}GDb4wCuO4ulrFwYSpHBROmczkjJfPp<@8LdOep~Y?-(i*j zJRa9u{jg0>%SV-_$|RpTG9Fbs@&^ruAM`6C#~+?hnr-(h{Dq$Z;zA%9e~OF`+kKKQ z|A2}EFJH6W3G*tGci@V@2i>HntT^E!_azg5_%-0%OEZ68kz-Enhfc3o2n?)%b1n9Pbnm8kVP-}Vj(QOCT%X@#o z`tt5zh^*}9@;(HMe|dK>)s}aEJ^Ge+AC~rpoqz6hdJkWgl8Vsb+uUGK-a_yf7wg1!U2tL#)ep-(9~Cbq3snb{9Lu& zo+TADo1WAXBv1MA zbe50H=M-9$V^&MTte0_VF&XnBK_?=_?e3I490gW_gK?$Ab;w$&ecUOM1s6|IbL$i{ zfnv6W(g!$HIc3qx6`7cd zkCGRX1iAqlMze$CxtV$azUn0}s%JOHh_z)V+(5lacMn|m zU1pECltEI!;q&^qm1nS5J{vg}A4DpGm}DO139`?!pjc!e%V$8|gXlN;kQddnxfZ;T zCRxjOomTA1G@<5xguu5`DfqaSQ-`_&ivxTv4PPtsu;G){QKVhmB(|TOa$irlU;y3Q zIW9|SNJ&Bw)6L;ARo^>gw6~><#%7I>&M2U@;T2}h#`-V_adtx7z(4M#^A|W0$ z{^yC~5BVPFNU_i_zWn}Wq9XMmrfpRDE8 z#o~sMKWx{+JG&wro!-YsMwJuy>u{bkw#8N+JqXl-0g()Qw;y@bjF(^h^7Tz}6Us{m zK)r#JRhBRaLe~nT@W0n!yeG{^U|y5N{1uMqHJtXQjs6d$C@aD|oCS z_6C(O#*#)HZUr=sjI@*s(0$xQJhh;QWNLqoZvn} zIkL$fj3BlV!WhOiLKCkVc;%3}x#X*p9d6Jb1omWoBQtfNp{k6_ zg+HSn?`~-@s6N**dNXqP#pT41ip$8s7nd{G>_Pb0Ru3X@tEu zibNTmGg$jUO0l&cL@=)QgJ^k<)WOUUv~TKd6^x`cSyMi8;{6N<#%Yf^Ay(g74%7m3{mU#7x=C2VV8jx zNbB@V2xOFF&g)J3P?+q{Hl?c-^yy`q(j;gotw%DsE#xM{egiEK%t!iNtWW8ZilL-P z*JZk478P}%9#a()7S#=mQTk1OR>kQnv`7EV4Ei}==h)k?B&oPRexoJkz+cpf{Nnwz zmskEA@NbnD2gskv^6|X;HlyKWzeM2utd^oab9W5$wB%7KmXoY<{$%^$uID41XQ9WE z!z;7%4pv-JP1J)n^c>RDBTZQHQFaWi)}C5+u?a~U4d#7tl=;!58m>at2a)7m9`~>Z ztzeR(>V)M~#iJ@ly&DYUDH+uqks&hAE9MKd^}*h95qe@ zVm?7(y9#|Q(;fcMTUyyGzZ+7DyE1vd-oOyxXQxcxWf)uKn|}BPTcp6jNTygYBur_J zFED`lKe3>pkBxL)p@b21#R+{FT4wd~g4eBnQ8r;t5*OInSINC(;Xss!Z<&6m^mEe4 z^07>-x3Kok9jyB~fh2)Z@-(daTLRFqYf4_W$LRY6I399+e?1&+#Rw>Dg zDGu|#ek3LsyMLc0ckbphm z0nG=1YBfl^8Of{Hskx)jPGJI-o$3Sj?MTsHlrP~%U3;Y16FVAKOX`chcRkM^uSkfh|V5#nn6LW(}vW!4kFR&vpaty&ZAPb)v%bZl853iTNuh6 zY;TGrctWnK-0)?O<89{Xm7C%Rta;g))J z_$5e?pVOipXUp)9#TnIr1GyY91;nx)S-s^T1zxMkCamlc6nczyzt{k8(&kL+^cYPd zX50@Y5!Hc|Q00wX*^qBVTWNtG@T*f^=-1E1Z;qaA7AsT;^<8trLQ z@aDcQ)Nho65L;-wFIilCRJ$_x2n5cN%=@755AJRhWnJ8eiqT)HPFB_G)CufovJE)A z4}@j1Zb7jsw=CAX^RB)%u6D*{uEzG+ljno!DV@di%ZTyt{%Z2WpPzH=BA)Q)pTGR< z_?S1H#;>lSLs%lfIrdxdp;o&(aV)1VL&Det@JLE|{6M_X#nJrEgPV6$z-7MXlYaG{ z4jgA7xX&NX`*Q&YNKqei_t=*L*0rbY>yp4sA^X}_ECziJzB785;#C`SRzpk5k%4{787&Pxea?du>{MInRN5@)o>+K;hNiRW11{TnVb^gZPI)`9XYr}u02xP+ zJD=}LaQnRpZoW6c{CgAhbQ2v=AE<7FawYcEz zljn_Bkc}mIXHSv5X>&q!?}WVx5z1|w6XIie^XaOur8#1klgQ>6gs!bQ1|e)|jzRds z%`pg_@nY4E(19(=J9q-@k8mTk=UctUGmu{L3m@baq$Q)EhS(0=u$GFLfpamH)P4J6 ztC20rJdFlKouyrT5?)VecIE_JzEGUIz>jLZ3p5{I?l`j6sj4!7~2fd(gg!NBq{ zhq;_jM69!mmX4R$sK7c4lu=o{5OCoODh*ZlJ1=Ly!Byyxc*@X8i+ioDRe^rETX_#{ zEsu6BE*GzYgo0eerBH-jBplU0;VvqAszcwxgoQ&EoRHM9lQ1@H*ID-I|a-1>kxbF|Lx-u`2YnfeJ6+i!1Liqnba5zKU9 zq2|S92EHFwE9bdt;;T9@)c(u7BB!tlR1IRY$=Rt#hK7&?l zg_~FZ%O)6U7W!Z=;a#)>`}y?)N0~wVpcT{o3}$|8nvqWL2D{`n7=O9p-C)BwYry<1 z?4tBVlT*}3l~ErQy21ccc4?lq$06$_j;BBDk1tnm&BYKp9j?_lYrcoW8rK?g&gi-q zlvZw5b=qov{a6N1amv+^}x6x`PJ=Z4($knIpgXBm@yUh6SloLrz` zs1x_evPb%JV&{b3t&8E$QlkhX9sE`iK>{A9T4a4=`uHldYq@Npo5N*)T=_rc^-mPJ zuzDqD1W?*D@(!aXSVl>;xBsa3>u|%Vjy(D&ZU~(D7f3~v`hS-NQ14iNOYo(V{5lEC zK=Bgx5248jU+%EyQDwLqTZTJq7ot#k1?e$cA*-ru68J<|o2NGId;)hQVN9_5jAOdee{6i^>!&i`=I3VO($HcL*=ymcr z#M(RPa`wCZht(O8jj{0G(hztf&$pkS=L`PBe}BG zi#jUAJGUJ@a#wOet2}d4KOk<8=mrjdALxg}Kd5ft`{^81AHqi)4!1wz_~o|RT-ys) za~g}xi9?lfWgd>^5JdU;Q+?b6|k} zgwt~Wm2D6}>y{cTrzrFf2qEtPrOvkr+S=;-FaBcqC+lYJR^-{QeULYEw<1q}>4UtP zyA`=}w%+cr{x!@#GB3GXkvnI+JCWCOB4`qZ{b? z;ZbK04J$Ijo$82VXbhD#!=W<$#H}7<*JZm0r2loFu9Eb4Oka58s!7EWHaeC<=j!|}$XOw*2*v-JOC#0tiE z<%t2*B2NcXZ4Ij%ya^FF*_)0Nkdn?r%JQ(^tmKzfR6ZaVggV$vBn8EF6V}K5ww44m zo)m?U;d+(tp}eCF$??T)r~^f9O%Md!{=4?wUj9#lU^Cw`b+9&sd(4?Nq- zU&JBgkLu0RBG8CH^8{l9v==xv&aV(u`S%C>L0MA-RA?T11sLx1B*z#QyxtR!h=i%1 z(5=)X5S?)?5)K4oPl6%9Gr-8p;~Wz8xlDoegdfzQ<^A#B_$Gf413)T1JSG=fV&i*Q`G`Q+rr?G2UXGc&Fak$j{QOijrm>3GEqYTVf zm0I$v<7eUqD@K2|OTzQNRWjgFvg#c@*&G!_0OnowQa?xtw#tm6pQ5un2>}DbeD7C$ z=2=<(CU^Rw$R4EnA2HPALy{v7s6@6tz(A#v0KmA}=r}ln_Ao=(Y3P?`@Bn6;fCXRF|UeC^_`yA)xG6{r{Zc2@pK*2W8kkf8r0?%e0-4vHLGFa-Ln16*s z_XE>#NF9Gy8>PmR7eq}xNEi$D~x2f&lEO|mmzW-JBL6eG;L&&YdZo6=3S|)%aD_tL> zB1g$_#Sa*uPYEAPN%@@Z5R?R+krS6JVlCd=aLM6Y`iDQT#^yS zAIu?)|5}CdUt{IbVf@##ClwJE4>~q1p4MfW3PXx-<{>SgOpH=w*B{l50Hli`|LF;i z@i|DUV*_$2z*;T^z+c`0KrZwh0PE@w0DR;f0Bdyz0Dc&BU%n&g{#r$*M@e~G0cwqZ z))4F&CY}O5NHhL9eM0mr6J=3d=SO@nZ-@b3y{Jz_;e6H!u%Y0XJZK_d0iy7)vAV$| zEV1~38nO6Mw>lQT&cv?>?GCQ^=jkHxT3NsPVQn7F2a~RT(FcJT5&VG|(e+uVQa&(i z8G{tt=_>?x&zZ7Af5DvigwVkW5+vZfV)jvSg&))@vmQjWDo%*F&B*g>gx^mdwy4rI z=KlkKhz>ufZFF=#RYyBD@#Mgew=kTm>|J3^+}t}x@dhIGca`IX!S9(wCn?Azs*fNR zEhZ6GHols;^~@#R?35!>V%SSDmdJ6BMnWO+qk=3WNrEgBMM^+*4+PGE3Kj%p#qV$U zS6aX1VhULnlX=Ej5<$gKmz$5@t(Y z=5GLo*iGr?<e46d%Q*=JAkuu?yqdF35Z(D51TDB=g<;Sc!>sMG$S9!59+zX^>D`c zm+zo2zZkme0oQd%0;EDvfJ}uDH}bee2(a=Q8%s&Vgodq>Jc4PR#8tSu`Wm&zJ*|~M z=?0>+&TRrYaSf-`Ah$W|Z(Y+LZbtEe2?JzbQ7Q~6s(JJaDh<~ns1N0RIVK-&Pf(8( zjD!^}UL}v2NkQ6v2N#!B_CpcckYkyCgsN$O8+e(U1I1{6)kdZ9~v9 z1&U=QOyG z{(_jb#;@Nv?-Yyje7*ua9eUMskUYsZN~0hy@>uZ-`3`Cm9!5PFFMF_M_6!Z`{o|$o z&*g%wHwd>p+F_)l@&klc_AXqJLph6E_9l?`t51VQ$O=)(Hv8-wY(^Q~TvJ;536alR z?5Mif_wA|LbocD4+H~o{Pnn2_sP&M=vxEMk&Wz%##48*Jg~1%=_9CVYjh%rnI1FEI zywxM*PzSV6J>0bDRH{U6N}tI*C^PNPYc>4mFu!iq!jxZeF_B?}-w2y|Ec)mA;CvFJOOG9`@4dICz!ZU0LPuLKipdmb4+YlwHfPC^oa0)kc(E&1xgcE@!n7W!JOXh_VY>ZA94>tu~_Ul2#j0c1^2|D7&cD zMwDIEY9q=nYqb$&*R|S+vI|>nMA?U%`fi)252FhIGX3eI}n2q@hbxP4!9M z=P90nqDJfi)Zpl;5xfijdi$LW7$_SBg4sg@h@8RriaSZVtcPxQ@V1Izy8!bBeiB+^ ze*Bd#5PqSbg?1mewurJ%s=Zg_PT(hG?xq(?y+7Z=f`wi<==2jV-lG7-8rje!#^H!_mzQKX7(;idiSVk{XrYCw2?st1!Eg zzmcL8R&F;6IOf_NT^q$@^A z+dHj{8V=ekhY^uN|AMwyy!DZ+2RUWH1?-HVG-ne{q<%aZaWX9MDMq9Ch8n2XioE*n zKwE*TqQP(zgObx6lCb}QckzS@4HmN>NXe_dvI<`xz_9c~M=flZblW2)K6Lrw z-OauKAfGuCFzNhHaKE=DcM-ZG<|0`BMZ2;Kz6dGaV`hORp&0P|6DC zK@YRxbswK5Kt|4J^$G_9{LqS|hKnfHeg6S`jH<_>A ze&NR9zyA?#r)0+@Jy01lS!Am3|B*>MB;sTM?IHd}oCH0k(cr z04vpMFiyW?BY`IvSpw3pay?OBC64)wS91Y^hNndA#ydhHeib{5`~ub!?+C>^lM$D5 zqJ-Ee#IwBTkv|BV1My|c2Ao(QRx_;F;vLLt85`hWcb7a1D?RZQwnpLsBYif*290GJ zohDz>m9hAlF89O}%RAzccOY4uw;%C53dXoal#NMqKs-~@cx-FPPXnVq@rrDmB3Ki^ zUXj7YO2v;NkZdr8`2sdJ8EzC-r7(b2qd+t0Jkd@RR_N;VanzO0!}OmyAd& z82!K>z3J+S2f;_IyYdNcA>xVd!Nn5`UgGg)I1~^3S1r>qh6)4#N_mC>#eZh>B-{XI z{$DT=Bl|M`gpC?(9imaN9+OQ0=N4kIZAd=|gKn69;~COQJbEMhGB$vW@ku5e_=72p zHEIc~W_(GWFp)pVx7h3GM-sr6Gdz$j-qqc2MY zT0&*eO6cL$Uu5`v0%=6PEG^z2TavxRfuMndgj?9VOVmYGMJL` z)h@Y1ho;fR#b}k~2O_!%CRi{xB#TiRE@9cD6NFg~_7s{=@aSJ~z$^5_F2c4_7IKo1 zT9VMSm~V-iH8^HaLJ$UcKK{d2V&R2+Mw|G}AGbKdMwb#5#Bqz9IhxCLGr1 z;S8Q7;`zVi^M;LvPN+4or^70o0C;z!6;XT(uzbRdo-K*U$pXh2GS$UQrSLKg8gG<6Qu-3JFMHE_@`5c1EsJ#pI~j2|jaG;g@xyorLtgyy zA6`~?;zP=mU)TgqK0_`@-a;mq&oF>ikLDtYMx==@!O+j@@p(KOU>lP^q|OzvbjKN4 zy;sP@+?K$qZRJ<2r3#!LhiEnSrb>QBwb*?MOBB0TiSJ!@t0H$Re3usDSPy^DDBQxU z10VRaildVa?~mbZ_Jh8#LjpUWzyKa29OG7ar|{R6JPVHb+ka+Q^&k_$69J$~C^TNu znvX5Tcqe5?@_LeU(D<2l5^T~6>3T}0IFz?jy%C>M-b?b$Ax0r`U8>+DWG(~=Ne&?F zTFE2&0&ArDf&A9gGk)Qs%_77w47xFmBQouj zp9B6RHOqKQu6iJb=}s_smwrh+b6^_BVM7^2ycOV6Y)Ra&(r0Zt3%95jWlh48HJ!mq z+wwbQZ?XPNKd4gl%*A1D4kT*x<1d(Y3NtB8)E8C*@st!cl4KPn7@)0RJ@czC!7E{u zy~U3>&%8i4)in8lmqi8Lqk0HPw;5$Q>3WG&Y? zG0CrVXeLJBSwMimA1}odWN6s;FX?m$fs%iuSJ?gZS3su>OJ#W)jqsbJ3h^6?Njo14 z-0*vX>*X6eZqgje|3WEaledX2y=FRD-6H4`(+A=XS<`3i8L7U_(8wDcmXS&<8~3V= zY0_xaWe)=Rn&jwg2Q*F~b>h=l$;J0{B^Pk{HpURy+bbf|zKDHf=}aOd+SomiO4c#L znNUN%5zh3gSIp`jQBIFXQWO1Uj-pI=B~+@{iDozWEAo}m2Sq}qp`L21O4e?&6SF&{ zaQ$+@7|0=oo5Nm+o8Bk{J1GwFs1-sAAoAWm$7ZO9!if4BjEYt+6)y!Q?eJPDDPw0Q zQ%3i6(Qs*=F4|kk`9-{hOPv;R!3qM8yiyQcZi)Mn4AdF??$cL{T3&G_D{^(4XKnv7 z2f=ozEv_hQ}yjBZ-(b&?oX>L&q>uwc_sr&P4PBsmZ1r&JrtM9<;`1#o zkf6F1FLoVlQ&`+DFjkTJ80aCJ5*0dUPTOq*JH;9pliqW4T94~QZAHs2ye<5!p z@x-DaxmZJ;E?@CUXb8Q7`8xkb_%GnZB~T>~Bd7+%t7rMSe8VY+1UL14M(&`H^27`B zl@SF3`AOfFIO5yj4@re^IWK9a4 zjI&n+bqn6Hk5~E?x(aByl3(c(3eCch@0N@39cx40!Si-8o2}l_;R`3j#XlCSfABB= zfVu|p=@~TtBZHh!&o75R{_neYo9@N`InAJ?%e&Xte*kE5)}@bl-uVYH1Z`oSh6A)9 ziUy&m^=JYy@Q{Rf=)c8KSK#{X`x@c&`I(hF;!#|hsAs^@Q6|QG#Xp?gmiS=R37wVs z8H$$hhj_bu#wXzEg9E0JI*ET`ts+0ETS~4PPpxphV1KrPpYfV)<`JQQ?}ZQm8^f7b z0eX;yMN`pF$$3$Kr9Zz6>5gs0e{n>_1J(roBn`EA!VnP;G+`8wd|*9x0w!OgfWYYE z17GL^gHAa3Br#VpOz1>O%5c>u)E>0hL8Qb0%>XbGcmlCk7!cwPdme@AD@I(zy&*!X z@E38n7>FM**vTge1x0X&7!-tC5>|#cidcfq!fccpdc-yu@vU_FM#g3h#xxM$P#6;h zabnT#m;$gm$lx-o+4pzsp6 zp-^I=@QAdzQCcn`+MuMp(lcZ3Pm`lIOo<=6U*?dj+`#f@?Z()T9?Pv4~r(x*f zsJRn{vC{A>TBD$(1TzGH@d%$#+=bE?{s}4|@lBqn(_f&+@8`xpx@;uUE< zgvCKp%OzSD0wVK6*WGGPuIR3s-)7%TBfLfr4oHAu2w_tZy}}fUe&ly>M~0$Wd=u*< zzvg~KBO}lW^(bz(NB0goqhyTXk#dP#yot%*XU zyF=U}dgNIg)7p+NIG6ILR2fSE-qb-~es$nfLh=XoFdVX};-PqesR_0S*a3kN<{;PE zSpD`^wwV2m!@HG=7*h2$EpAlWI=nYjCAY&n6SJSgix2N5h3s>dPW+ZaI}he1W$c7- zFxSiI2XpPcb}+}=57?(+K{bKBLUpRCV7e4&(&M~|aAz83YxyN@Bq8p%*7!@64r!g> zPug90^QM>BhY1YLfWO=-^ltgWFQ|3+>moeCYJ=S!xRQ|kC_oW>@v#l?S6myi?ZYfQ znS;v7D_i8?dPiK20WpiT^4pLkN3uHv0NqsJK?2BcI8$M#6Yn((-{c+Nh6zL5h~_A%3OSWSILbGYpBw%PVP0}aABz{hn>rcG zPgDkPDGbrul&YpyWY}B=@|DA?oInderUkg%5|jbp`p#Y zk|I{Uhm1)3Q={zXFp>5ez$99u2~0RI!osQvOhQN11ST;cc6N$rN96&)t26Q@bz@C| z+5k5nx*8)!*U4NjQd|+&M44ghd9<4&+{IWQ+fD`FqaY?T-1@07t@mX82{bfd|)}oGi=15P=kF4lnwj^hvanK>0&a-Wg6$) zAz~OX(2(MEYVF~^vXo*w)Gi17QoG>)$pc)rx z``y(fw3BLDt}P+el5kr>v3lj4B-{dumh|)+>MIIfr zR3RH65&~m6eU6Zflgw%$fN=)MB!`supcPdYsJpi&ZLKvBoF|s_3#`b?9wK#gPLp@D zqGCp3xbC?$JBI>87^jgc8i~J<GI~nEuP_P7m}}|@Fr#h>(hCOB8dwKbYb zmi?xUP~`p;snVExKRY;$s%phBs%jR)@{%;CsrE4{uZK(z3qz*sQ>WHJq66nvjvTHW zSJGaA{FaJ6^^RK|ETD8F!Iv9y5*882EPeTN(*yD~@6Ayc$z_x&o@Q`I=Ry1rBi5L; zxMWVkrQ5}1oVu?01WryrSnfRUJ>53po&YE%Iyszc^^ZE}rP$;U?!4ET^EYv{wR4y- zq&0jatR=@^qnea#Pbew$^qE*UjiyZ&jm{}111`X4+h~CSXF_F`O6@n70xwv_FH+4q2(4;DXMU{!k1gw^-5>S^H|!#XT8Spu6}aR_1BCXp2hnzT=& zaUt~3KFwCODWTpQGzsTE{xessEfRhk{n{D>ug7KpNw|;O0!T>SHUktQQ;q>PvS6Jo zIV)--0lV+dzy|j9YHUcK3!h6 zi^_Rn{!-ozn1pd=f?*TnKH4C0V}_&PuXp#q+}!#8SEK?wgN{QukkeIJ6Kv?J{N7zm zDP0YYy2v#yhKH5{i*r_`JGUyKdcyhqK*4TT0j@TRanrtb8Dcq+vx)-I4S7BuS6!?}>?97S288`U@Ro=YiLn9TlG0;J7hn1XdkVQTR!2iB zj$|be(P4PCR*vd)jU)hUxWPo1bTDEB%AhTIK-Kxq9i*1bJgQyIQcxdRN4gVJHM8NS z`lK^NcNQ*!t|wm@LD-D7upT}mTd0XoyAOcOV*d@gZv8iG0s1y={M13x87P%_jnRML zk$}dRmy5{;lZB!6O2QZ(>RC7$!##aXR~0bZ4+in3li9JZd$``G2yef#FZ>r6OTQwm z?I||1JLvf5bAIFTn=|p|18y~c4;J1XS!4jPD~dkS>3Ra_-0x8^Z~b-u z!8w`faC28_D7MZZWnAYXk!wYyrd~*s zPhhOPZP;Wob0{R#Ap5#X(YvrFBgdi+)v4=nSyiY7ZtLZ)q%2TjIh1yjYFC|>($GrV z*9d!QF%otbK1axpv9_=3wR688D3T2gY_;Z~6J}?T#wr@_&tx%LIUh6fW~T!gh_13p z4$3yZERvs-JncpFHgPXaS49_O92M?|5?gBP<0i)ztrErkh;e7DUH0xpq)L97=wo)ADuxd%RE6WtJH6B73#;?U~$L5FV z0bwLgV%B6pt{*rsD0#irpVn|pf!zucm_(0V*#h^%^_YQpGqZ|gI zvTzTZLg|eIpUm};h9nO{@$j~Mw~lA;I4p32+OZIggrrP5td08bCpex+g z5#J85OxtmdXticj*PTr+j%04IY6WEyWJv3PT?f-gm6{U5yMZRQKP3FArGTz(^$t2Rb$3Zb6NMa8BI|3OCz#&{9f$gFwOh+$bzTtwdT5MGL=z-Jl%u zbvNR)f`}SIJY)YWZaTSstH71ChZO^hcE(@mB^8vhoGlPZWU=b}10y_yshfhy_ZSdN zXC#WVhO-z>j?Udsi3H?N6S4+tc~MR-VWXj3`^vbWOT2ez&+sL|p0AX4z;FQLlY;{s z9WctklFf>lYfh>*u6igotmMxik5AP9&3IWV!%W)JX6>}+?E0mw#vLD0;PQI@A#bU>Q ziw6SPQ<5#jJ1oVJd+0K<7+7(FIK4WcUQf$}p_7J)w1d!8n;6mkiz#H}`tLCCD+ZRU zG_9k%fUrsPdRqpk7F*oe?gYblF9l0?L%7M8Lduy#o2CmKz{}xyW>b{vK}jtb2t!ZR zQ}01Uhnc>kKkCQ)h)f0z9!L~-fMlD^a#$&vkWfP6#%fZGRt`io+ABh(?Sw<4mBYzS zzz6oc>3Xa%>g{5g{6gaAzp6yOvD5~*#qnT~V9vv(%l0lHUbjntFfT|hLF-^YEoMxD zq0*&b+JGuSmi7oG94IC#;i#oc;pE(=I6}q91Q4RH6oX_I6vTv)Ij)L}q;pq|^J3Tx zdR7uF5hp1~Ski}(WpRYant!{LPz;snQ;}Y;7+fHQXWIth!yLdI zpf*xFzZ;!Q&$Wx}X5U0Vs zw3c9})DYntUGmN0IZkn2irZW?6|NgZ`p{i~BD?4=D78KEU0^YAuF3S|p3cS6#F)iJ zXyW)XDRmh%E>}6&8?Zo%&LYAhUpC z)ldPboXcRv++8MN6f>!$K53KVo^CcM=0OMKOC&c?x^60lOcsq`Jbwuk+>Qaq`@x61 z`wyS}2k++YsrSXJUh>QR*ZZgYue}c_T5-KxBjo^AlU00Puk0#5t6p%7ObfLNa=+Ce z2)7oTmueIwf}i|)Vw)m4oR^20*L2=@e zh6wBmY=w%5NZ4po)N3?Z(Z`bh%m+w1fdvAOG5_U1Q~qf}zww&DF!+jCPL%T)pZwJrkM0>qN7lS`*pc^D2uu`dB7pIt} zc4F15RDqauJ#iXB6z#wAz$qv+gAxLsbYfIwcUTYM{w;)58GBEfWs<;`oeK(p&Iw_~ zWt@Q-`xDN6iy4{zvpDtM{~#hI-;AI8vvC~0(SCo)8J3slV^|b>{WlIa;%y)UJzn?_ zI%rqCP!SMt1;-&V@sroN7$%u^*^_C1;;+XfF2bxFsphL=)_i$P;*(<%A0LzW_hS-| zk4gOHn8ZiNBpw};`0$v-5%P+H4jpG>3HBrIZvqm(qwy*@!F|nwf->O+CrhM9BU%%F z5NcgANkDpf2F3}LKNs>7*r?!=(8Q}5V+$yeJnKI3AU+4P*;qVL0Tz%6G@#^q@#xLR zGhO}R1My-P0YAmb)A*Hsc}3C~q?W}~^1$DM@iss*n&}J|(i{3Y zOeqKpJ|p>wJZt3ViS% zq+p#hg!~-vr_59#Mn**Oga}4{tX^j8B|N4mp#;CDVTGT6z*w0+WfzBmC?vXBenXN< zG^qN5Y!UKNesGDTx{M5oDq>E<2h5_o{RuK9;@be(Ir)LyepfM$?qn-Rzo26fn?-vu z;@82%pHJxb8UKBuzt8*_@?Y_Y%%whjq6V`ufl}N7`oyG4z9PjcJv%yyi{5s%b&^h#C_PZ)KStq)H~^TeNvp?p9x zPe1r!|^CQL*Jm!h2e92rIz#k(7ETR&_p?Vxge~h4#!OQ35iF0bI*MHzQr97q>S#+N@pZhQ_ zhvOg;Posr29r7mx81?#_+xe4T3_9m*F^obqpI)-Rp|aVcBEm5e22!dl>SPt=A0tIC zO+|shBuwGLcqJTjE>H~~q+*>#sAXxz%)veVz-g?DAViXXn67cQPa4nsKa|9nF9Bd!|9KpYT2RQyYg2yqy@y`+b19nm$&)~KyzL}OJvPXE>*T)oCJ z0z1uNmP<+CEYoguFHWOh@W{wC0ZX@g+d0NEX5VA4K`ar-2`H$b9B|HKWD-O)dz_DMwT zlNh#7V$eQ`w>ryZ#kH(`5~~JC)R-&F2FUK1E0gv~jN2#iy#W$6`X_FH?2i5!wND~y zpTw|z5`zXv$RPhX1LGR%JqO$$kI7u{^DM{$!J?SU-eXd5=xLiJH4+}tjkV`mRsDL-+8{M5&l@Dn!2 zPJLAAI>~Mdjw{iXT1q(Muj}fHnu~R^3aKRLL51m_TPLd!%&(J`N@v%}N`=jJvP#iw z&gn<#Yo$52G|46V0A>GLVA4wqsdE=%TWy`l6}d&WPNj39$f#X`&sJ6^go0C7g@%*; z12wMfADbck{$%#B>31IlqJP@1itHa!d@Feca$O~_y6XKy^M}P!>o6z~SSyg(!{McB z|Fm6|{QPON;k5Z9$k^sjL;XV|yG?+$*jmoTLFj8 zfXGl=p|FL4$~bfeq&tT5zFN=%WOM9}LuWu5EV~!Bw}6!aSlGc@jZWF;^B`XI*!Prj zTp`XB>``F?xrl?oIAW*N3y!OUTF~N+%Ym18IE<#gv_S)!$4lJlc$C!-7+{OK4p;tc z8u>7sg_)psPw+`V!m91wILu3SmQF|DQ1*G+Z86s>OgU~Rq!?iIy{kpy@HV;|)^kx7%bPeX!Ee}4)3J;;j zHe>{tv^oqBSHUxNTE`a(6%ff%xooBLajs9&)%i>EX`Um%v=|zFbi2{)iiMgTUO-EB zavvQdsYx@ZtXDpbjxffyT@JK3$xtzj}0Y=kF_Z1<7 zW9e?F>s@HNr-VjW^OJ$Ms74XZuAUIL2#7I~({em406}6v&}1v-g1$CKFS%A1jb8IN zee@c?PS(tJb8l2G*HG=C7TmDm?>2z)udG+=` zQ{)rz-|g(<07lug=E8^;QQM}gc=hIy2QR%8@&}oMzsC#wfq}>qENahSS^@LbrwjbM zBq!kRDb|f`uox!F5Z>z^ds-vbVwJ+5q^!bp_#mvFp;a+1lA!l$HjooRIGew5uJ24s zqX;A;P4J@qQwc1{$plCHyU7^|e2HDv(-a`c4@ttDACG!}1pL3{;;e%R14#P4LCpQ} zn;@CU5iy{9Y^ig>ZY9e_mjV)Gz#*nl3~Per&Qq}O0lK8yiFF6A4vT0)(Ki@(5B=;} z-m)C0iqoB7B3n{Mb4549WDhZOXv~OmUhJLIisRkI)Byd*8~@?)gWrF=@*jWmA3qvf zH3W#Hjf=*x7wQ8&-_nq2a*c~-1@jb7i1U~TBBGfnYdgiOM?5a^3iIUntJos0!-45GO|QIl_S6-R*o z1x-Hct)yg+xPO9>TwK%51NF}>3DQR0lz>=~@uK>RW5)%2be0iMZw!F#0)A|ySM4Fh z1|49)1~sk}=h72?^^Jlv8;dEJwa@N%R}j&*7@0X*^%TDpuTui8*a%5+v z!lFuv{miD#whGA@efCO)vQmnWkcrQ*#uP223yxQ6I93%6k%}XYw<;XXVaC{}%?n|m zj4q{HyoyWA=j}E(ubN*_F0r8SPRr4=_GdZ_kHxg;{&To2&$Ts*`qvD?W*uYz(~f&| z62s~Re^)%vPsWCc-H$fQbQ>cDhu9*M6&%YS?T`$k?~Al{%MEHHH>d|J=(64IRiM45 zidyCfEO*@Zo}x2;;U;tDe}brgR$-etci3hiu>Zo_jF_gPAuqV+G} z%o)#mcds1}|4!Baz%qXA`sxRK=e8$zN$l!VjzZJ>^!4%7zZ$L?$5d_fU$MuKNCnxJ zN(os7^}I#|J7Y9Ro(wTN&l6A>tOynfv)JE$5{AH5D?I6X23B5Hn=j&+Mr(8`1w4@m zV65S-2q9-68cY#BK`QQ6@$(vP_arr~pkjy?=}@G&e;Blypun~vBu&#X%uR50*i^Jd ztEQBCflY-)s2d-0x5+cbKV%A&;a!~H{&z6%urs#Q@&(%p4)|ExlHgqz97h1UjE)bl z;AXeIE8DgQNnea+!Cx1G8;eNX3hQYy6?M-7FzhBu*~EHiX(8+MZDJKE{^^{yh=?qm zOL<|oo+Xp*Sd48Ty&)~dfhz+Ug(_ncw|?@3Vcf25XMh52n?`4-X$jw#?sM>n6ZlolLZbGix@5o*iPf(A-NK+B2}?M*`|ErI(wOO8nzvM zFE{`L9RwF4OC%93iUQ*3lGeew!8JE=gEW><#&NXeVs`9@Eq85jfi~~l|KzU9gNV0N zm3KkXAF1;6uDw{T5gVxY=^kNol(M=T55Ya^?`^!Z|Mqc4Fz?6d^k-Qa&;6U}P>8)8 zaAtvcO{{GUrmNoIkLb_kzn^^i$KuR|k5T2Ze)`)JG{egeWb*I{>PS9;sbjgRH%__N zV|Zgp{`Kzumzz7^{|b4e^XnS-5cdO0?FM#EVba!vBLA1SRrKq4HVDRF)~o1M{L;DO z2toV?D*|B8#G4Q3_uqqscSrGr@VYCCKH^{yhdpY6D|UvMhLIQ8GM5hYW6Z1INUZldroTXsXz z(~YjbuBE0)`LjtvP4cJK<-F>jgwovXLyyVJ7w=MNfO>tr%MIfopvxEcW`sa+3C$9Z z^F;9k#LR@U3r^zV-uT}2A{s@Dh{uh6kmtHWRTVg^EcwJj@rqA!42$-B<&7JeOFkUx zL*QzN`_}-RrfVMt9-%eIhU3^3r;3$)isLQ*%Pp97PejnNV>R@kVWq>mzUGxWAiCg~%-0zC_w@Ube>- zP*%1-hisn_`IT&ceTNvTeB#g<7W#{pSF$`o)j#>wo7Rysp}55Q0u?8ns%F~K?x=%V z;ADb*K_gg8-b~ISjUSb;cQweKP0p%v1j*P|ZNOU@dyc|j(s~DG&+#yk9O4@8+y_`b z?r1<~4(D^zzruReu}4ok@ao#xB6_NR&TF{aZM>dg9jRy=lv~2`D_v@1sTlxeriAr0 zNlRp{g{InJvK}jr9k~}P^=faP8g0X-{-H6`Rv88z+vI=@X5{gnc_R7KL$4YL5YaK7Smx<0I`aL$^> zQnMJ#eHu#YDM-Bhw3YcrgTNEtqZiG+0)mVR%B4Sf=|p3 ze4vcH4VTs>uyrR@ls?4wp+qf0GqGVxxcl!`HrHsH2a1tTZEiIgv2M!{Oq^Ogv&B2g z+Fhu~*lJ-4Gf#3Z97CX`K+ajuP%`c(>nDifZ2O>hc80XI8mM&UCZPi9P>>Guq}91S z8IvT|cJ}o6=4~G;Nu!SX#_6CM%ZLscY^|_OTefC-C!CGaxt?JG9S^V5*$@4WiX;Tg zTux`Qfj1uvmcKuIMzDDA_9+~PW8Cm9S3~bTB9@KeK*g7$%emz}xd3@kfnD*nx!#Uq z<)BW&U14Gx*Q0fX6h(%}Nl9mIn-~#6>p#==K7_;M&5{IIH5T&+LL#0!H{z;Z-3OC~nR1gM#DFgh zjy#VwpL&Orydf$uj)D=_y3AyP6UrH*0E57Cce2A~V!B#mHegJU!=B-px4|_s4P0z7 zG)Ae8mV0Q}kg)Uy2&?U++031ai-X}jY@$-V0lunS-B2}(Z#zop!QQ&D;m&6Nsq*pc z7=tgvLo3Zm3oUP&!X6^O(31N@+77MoV03Aw(wY6(Q4|o0Y;C`wF=Z~&EClLR%TRJ0 zNiLK~2-GPVo)O?IBTP_43F6mWj;;KVC69qx^$&{qC7?YCl%SoMR ztPU{dCit3L{K(R#b1rOWAh8LTEsENKgh67ln$6hy3ZlKmo{U#mxu|*M;MzT-wA#pn z0Q;x$3}#wM9uHhwE0mcXv}(0dKOSRkAOHWTa?&U0?^8c%My(Hj)9IcjRDS~moi)hL=pT)LTlpu;XQnZY)5NvmJF{2*S5GA)>Q%Ne)|uBRR3D z805~XU!~aOtfIX`oNA!il>XGvqlw`uDtqPk;HiH(gxO*kTb1o+=o2#KgaQiDsr(=e;k=Q?#@TJsNwr4$Rru!^9B8rls_k-RE+;hn z;P!GDLM9y=yIIRSS{Q1r*4X7KNC1tb%tV3KNUxn6RmVkpFRGTgz!zL)0!tHhbDT9= z-F6t_9in;nWT8%5?@6+Wp-h9d%o*t*Ex#uZwVJ*H%_{m>QpZ}9aSf!sV%dMS!;rZ$tZ#LBB>vP zZM{nUV3YiDp$DP29%*q1&?#3FO>(YCn4s)zkSZTxBg|JLGtvavW4_u90VxbGG)#08 z3P=G{@V8KE0C=@IH6^3~mh$AdGsltXetVGjnWCQ>#C%EOJfz+6T%(+e8$B|xd zj2suAad0|57dVXG`yYFE;tY4#CUHLk!A$3@z&HT*E|C58mIhk75!KEeG>x4M9_T`n zRWaHDGdWx3DUqU#FJDzSn7<26(uq{4Ctd0knVwo~OLEe9{tPc~6Z^ykpW6{VqDu*A zskJlxnb{YtyCzMfB!VO-K65|8ZZUe$9ymJl0a71I8Pbkhk~?W}c(#((H;C$6Q`z~I z_AZ=XMLpGa4~>{gO155&uF!-RP`JiZ?}4;VNtQF5;2}hjc`__(kY&@vLgrpN79XfO zm-TSb+|qCnn!7;|Y`Fw-8Kz=4rgCWPOgUo9CG9i14b3CRHY%AL z+$9ZV>$-Aeb>1?dokvU8|8#1l&GimCK9!w@) zH5|77b3~OJp9VkLAc)IGR1S-cqjF^V5f$$qQ5L3(MpQj)mO&7^jVKFic4RIi%7QE% zQQ6#yMh~XLpb`#S|COT3b>Eh+B6$_h?7&;KN|E&7x&tSxZv|xe_7+=kW4O?Db#NtJ zm)(RDWW0HnwNoJq>-JKHDc5mWdlNn~jg3`FZZPg$R~KEr^W<7yi#a>ClKv~LYSQ|- zJgNzE+=DfdSo^RPSH2VD;!aFtjS8Ju6P=~m#qyc7Q+9-vF=xkC)`?}<(oW1Spb2xL z6YC+dccK%nZ2DP~pJW-fbYD`ZEDHOcPz8gvKDBr$-CJ~)q-_O6O(Q@^{xt4(hlb;X zel~9RfNIjB190}XSkTtZ^=oKvG|A4i7k zoCHX6v zyLoeZHi7?H+0Eb0{?zQQ{$7J&`S)UX^7mpl@7(cIkKONouhxzKUhKa7z1SW7z1WTZ zUhEG4UhL*WGyT*HS#Yq{J^y(HNJx@48L|9g(t4j@ywc+vK<%!Lm(`+mS8XDENhHkocs3T>0= z)&$WunQl!MZIkKN#L+gHZcQR>lj+uk(l(iHO)kwat(%hA%!|lUrr7)}=e~;=?Cb%T z`pw$H|5!o-u#ci^g1`)kT~T*FZ(%rriezK#u+yNSWZj7=6n?I|F=b5II6N%*^)=?E zOMzQ*VR<;(Y})o&CJg)9h8=e6@Y5gv3{1p70~2Cg9d~$Od`fFF7~ULwuv#t7Y)jG( zi$@;xFoe}FPxMu;n!%h6TT#RjX`_{ybs1I)3kwUa^1{>{In&{^+b%{yh}6w^frVMi zi+r^}=w;;9ULeNuavRK3BdH8?R{TYg;fPG})=*AJE}+#7&79CyH!~|o+c}@h=o2y~ z9W{xp0=EKk01sozT<33sMNBa!JOa6xP`YWdV(XkH7-og7Uw@R+zEvJLU7roy%gXc> zF~=9dgpB1>JnpjK)>IeWz%?^|R1GRN54RzLrp3cyG!?;!14;>wIShJT#6X}?OJ2Z! z7%#&0I9SL8p&l;=SzA?5?nxu1!TSXp<*F0__>VJ-7 zz77!u7ui#zXTt$I!_3~R$PQ!n++fS)SEU{Y7unE-g#&>@)a*+Y*z=2j(Lzb=l^M>r zRmTcs+nH@Jr5<3fFvgRS%q}yl+8)|y5PfKuvC>L|&_Hly0NY_cCB^OR;{YcRq@vg& zLI@VLnyDx*I2DCH?h47_m;!QP!{plT>C^do`Qncjv*`+%H}s0OO!=A#Q{0tig-Je8YWdUs2Vg&3<=re zzoNqs!$K<3pytT6yz zp_XsURW$L#@eHyRy(-Hblcrely!oBBVY-uBMZxf`5;>Xlq&CIs6+ApeoH_8nN$=22 zT9e`)OJK(4sqHF;4;-n^B5Y_(*866bZRAs7c)DGF7O@ zQpAz3&<|f1v2ivNXv{UocHihriD6}Uj)>= z&c!eujiN<_SOEU&Z5}nu19ZSg=K)g3(RoWUnc{+#j=kvNj3_UmsSDEeZGp(*Wyh$y3D&eiIBajm`^Jl&C?7f<6AZicC1 zNc~1~)9GY3jo$cb=skWwDh7nprXR9WE4}ML@>{6(1a@IglEyUWSLmNGq@ZzWdziFo z795VY)|;VQZ-x&h_t_{u7Be@#krA~5a(f#O_0uUf^5w0jhxR>XjmI^mcCVNgs9*0$lFpKqxB>Jy{ zjEe=PpPUB@VDAjQ z%L9(K=)L9)7whnVP3q`8;Anev9&ofhIuAJ79-W7#&5G-cNgQpD-VRM$HrHtf9Bq%@ z4mjE#od+CkkIn;*wnygy`~A^*82ki0;COxTcIaHdvJYx@ak?0+M?LE?fcQ$!Y9yfX zrVm?RT@X;W5JeZ}z(Qw`yiqT$B36vjQYC*kNvEca+>v3Xf{{x(BDRgrnyYRR8JP0y z)hIfyU-WzZqH+DAFZGLtZbeU#eeKUR?ul0mI)LSEo{USPQr`uAJX(7$$q3m07;~P> z8eJ#?LsQJx9fkFZ>4f_*oZDI0RHImr`{ula(7TJFYcbttV!q>V1WW%aQ$AHdWae8( zqK;cYeWfo_jWTVvaWf5(M4pC+&8SCl?#uiqI6`>&FmiLlD94de$~lfEI!l*(kr?x> zR%=$HvELq3jaEmWzF5gH+Y-&~MYM@vluQ<|u_sr#3m7Oyn#Koa@kaB&Y&_?xr8bfs zo(wzjs9j}WJZg*C7mwO+_Qj(%pMCMDooHV?`YO)b$G!;Dy<}fZ$xzziFycOz_C=Ho zrhO45qiJ76$#B{iQ8J$PMU)><`(o5aR0UKJ%yW(^lodk?W8HWN!*g70c^i+iVSIwD zQPXSXoV`}WC{*@KTKN5NoXQwI+^?Pa|LmTwaL+IvzX@}oXy|X_)e9~Oq231{gL@nY z?&Vs$6XR>+7`KgMTs4ky**L~Y;~2+{WBlGY#<+2eFO6dyHI6ZA9OJNYjFdyY*_9%w zicy+0?sLduzc6Em-sfDE$F|2&DvzwL@~AmXY(g^Iz}Fh)3F*E8$2Ox4&4Y>K;YT_* zxngxZJnqD*A3D!+U2N~@wl!SvRlODRb=mB zhBZc56g$&a%&t6F$LzWm#Zv@p(O0;%nfKvXItc4ck#wIGuOq*fHbzI#YQ0?`ZbuAb zv0k5|i#?5us1meF5g2XFy?(_(pm+C*be^vr%_UL2mahoFqhZ z1o3{8b3Qkt=#-;%WcN};P|$>naI zf9qGk=s0L_;wi7I~*gNLvm zKA>C}K71zmww4&?^}jzndj7+Ag8|JHNY=yJB>8%fA52;g(-9a;;d;87p-tdz&aMOw zu#nR8usK(X&u9vjWf*qm2Hpx?qPbKcoifnuz*O8Q1}1701Jl_gcuiNr9`XJ_t{NGz zOW`}9LFSJ!War_jq6QI{(jZ(=+U5hmhcsfr(c(W-9Xm>}P#+~(^+bQJ$qXN-$h<8+ zVTQkw09nnvT!5;8|JNabFj}skgT>Nc&HN3!e&B#A3kJ^~{7}Ue6QxG%bmFDInT;Vq zj-wtl9Lg}>@*_q05LWZc#d+$|4g}JJ05@4oCSD;l1*=dfLMUM+-*aVgAA9HQc}_vE zaLYy31QcEXAhZN%Q?9f{LLRaIyIKUkZlidr`y?Uaw;UKTB8sli@I?ayT@4o=^pyha zVH~JFsn(zJf>I2H=+ET}J$N@c_nxCbJ$hy*%RUxLiflhyYL#@ZV%A=(w(At*yyH|6 zDgI(x7)Ie{)w^BZu1z=4&gpRGucylwM0jBHn*Qw?qg{>o9D;aX1UU}gOX}$wT#Jt? zXvphRHi^GpjjqUh)My8zjr#0)DwhD+AYF>ZAsUr2(4Wp_bv!vvZkG+QQXNsAm$)fj zDkGxpLTg`YT0Z4h?4~@L+hs#|;%4xmTG(wGsa7L+P_62ClJ#X98Z#$TFBtFH=2BAn zcDY~ic(3B&UZt}&FItW)Ye{kaYaz+DLLDU8ws65AG$K+Z`+19?0eKTyU5rwYbgpoL zBzeNT(4hMaWWA_Y7((&x!iGtzGWaW}XB1Ipq7{lLBfbhnl(}AoBFZqYLJ?(xx1$Jz zM@#}3lkpjqP9zj~RwhO;f7{WeMiZyzcZXnXhta4$zOC*Mm0Nlt3m1tuSTdVyc(Xa@aecID`6^ptePftsphOj z$^xad;=6gH!A*2l-G+&dvSQr{r*3bHn)ce%vrdGRJLPK`>+;&ffTM{)8@qT<#@a;ILkIHddKa;7C3 z$-5ki7~6Wq)m@HrVLcoXsiQ^vNi<6QunH;#uvSsU3QOy}o3P?oyhvQh6sH4^Tgy&$ zgPf#sgb;TrE^*63#bRCZ7GKgSleVujiuC@n5k&G5a!*`Tuk3Y*KJOfwCaqT^h-AI? z#6|VW#%8TuuSO8bdX?d-ci&=I@MT6e$#3&u=m*mwWi!HdlMdm6C75;R*K(o6eN(bO zDTfFsh!G$bn)oaF&kQ(bZl7hu?MrBb#Gz&7Bu>KjL#sBeRqy=|W4hlBZ^qC4**Fg0 zm~wsz;|mAWimw#J8cNZ$$fX?Z0M+f|d;jT77c%#!OKV>(y5rdvR~7@@iRrrOg8KG9 zll#Jiex>+pN^Onr=(cgRT=q8bKoz*yeIa?_&{0C| z%3X%^2XE70;!+^ROqy55950;^m%}G`uN1fGP`98@z~4(2N}-{u8RJTd>(>R_2v|5> zj%JGqLPTd91UIM*t2N1vA{zGhKn{ucC68AFx=zSzOy?NU3Y-(lGT6?0-NM)3#L>23 zRRq?&DRO2=SdiIQIR|92pF*#oTge?o8;%LMy<0QTNfRONV78Akpq*^D?k=KX*Sa-> zR|6{O*5U&BZdI^C79&X%a=yRFT+(fMu`@zN;`sVB#Y%x|v+niz_2v8S^#xW5G%i~c zAR-zTVqBcC`;_p&cq+k{1*eQ5ozwtyGBgj|nNRP+OE5 zoq?8~X>bx+u)48>nn9iJaw4N-9!UQLnOJ-iyCR5ZMrLT?{ldt;ZPW3u(h zTX-p1NYN)aNtl(qhe*vq$T!r ztECsVL6ZF)ZO1apd*0mT=dj^{4ZE`85sx|3m*nV8o)Zt~m2{iUSL$al;XyrYCOjqe z$Xkor^~HP#2KyPk4Lavi(>%iRTCD6XD;n1*nllQu%l=lfQn@{X?O$P#JaI{wscWLu zrC>4n3qieE6lk~`)VOe@8MfzTrp|`@k*mBq%5NRf{7Z&LDivlLuH$qaQO<(GQGO?} z1BdgWu^f-q93|tfxH;sUiOVlY%6U-j(F6|Fru8br8R4J`lL;0qaq+RgB|x*nX3<); zV31MxGMC~7^(ZZ#ZBIK3^2&^EP0eL6Gs5j0rYRy5e6RO`FPUst{hrScw;$3Hd=WK!IWBxXpzzLzI&8Mx*NmnQxp%t0Emc_{A?O6kopLIJ)m=<*EPjDCP?rH{OZ^-ay!(wmM zQY^XgXYXcV_^PiWc{P}wx?WNaiTcf3c=}Nz_;)!_aC0ToDAUoRCtPW|9jP=<(lPtn zDEOfd-Z&v8&$UcmePMvPC zH4_2%v0MRxor5dv?yCSX#k5|p%S=67cD_0tB+Oi_mK@)=0p9B4v-5|fX2ZsqD?=tG zFx?GmCS(2}UPj@{Oan!GhHma{jp*lGV)$viNem@G;xOJ*zt^X2?M?P{e!~I6rocH!##3CS!efSRjc;knOb z-liU~H74JE6}RT@o3G|-=5+g|le20E>r`^b-IPvqzrjh&mED5rlp3p@uK&DmWt60< z9_ZioI_%e4W!Ea?7}6xIv`hm_7f+#eLfG_g^k7P1@?LHzn@28JVKgSnV^%73F@cSVjUvWxnADX zw%g=iRbvy8O` zvu)wBBSvvSotr}c#eD+BWmfW^3=0jt_#$NX+!u(-2^ z!O|jYmJ#I68pUR4uhlHW%AGX~tJSwmm4d)j_E(4@zxvP-^3YQu}^TYVkp-y&RO< z=%Cc1gHjtFlv;RDYJod7_y`s5IE(oC#c9jQ?>KlP?x3;t3^;67Zue<|G6}<(z3xDi zNgy~5<<-$BFONo;b$x6fRNhS9bu=V znOvvW1yJs@MRg|jCb2|8UP#++G&tQSlZl`YlW{*3u}lqY)KRyykAtmH7gHR&bE+L- ztA>f1nlObz{qKND#bopKEa+r`2}}<>e9crGgX9&m||3lt3p)VP~)*b)thHK zL9?*EHmI|Oda4V#gezzTa4Y_Bg2r;kUj}a8s$4@C4c8PH>GRMw)voTEskpx-z1d&h zh}fhaxJAUnulUJ7M?NWgetCtd%6zxib1{1C{;(kaf;IHRbJ2IfJz=> zV|G5#7Lqq=8i7%PVpka;HpzJQ+|>Y|eqi`_Vc0T`2jP5k)IJilL1Wzv0&vdvP+EP5#!oe2CU_io9w)CeWv^wx#@^T zklurfXv8^k&=%n$+rnIj2ZMtW3`qOug5mvq0fQ&_EN(0o$a-ZjN9)yku^X?oymO2+O{ zXFTnZG9Xx?1>*?Q4Sr#rE<6!e0rvC}dY!h-tLb_&Ur)moMKXdki|KEW*im|d;ON0K zqKwxm4d+S~QoB0oBzkxCqM%!p6LTMAx%`-WAj{^I+XGcDwcb9svKi*~z?DrjR~=P4 zc3Fa|J$CDqPR4GX!byno>UF-J%%;(skL(p9)}J*yg;lTtt?K07V|h3jv8z=)i4I0h zwj?sF$(D2vLQ%UV4@FG042XRAI-E@*Mc?e?Zm^=hEZA=PswlUdo zOVTJg1hI5X9)eoulov`V+OW53_0`WnBEVPoz5MfFustN zq3|6L0$xdxGg0INY=?gj7H);EeEdVSObX)3 z*&~lYmx9ysGRDcJI9K&z={BJwFa1rIdqqeYy(k?%)WI$Ma~&@t9C8Ewyvb)+2L1ufeM zY_b7sO8V8hDjk8XSIQ92g&0+F={7J(0l!*x4GdDc-vfgb?F%qmQxJBJ2%m~=h1dEV zHw)L9sbJ<<9D5Ni@g0lz-yk-+!oF63Ww%la{k6La{Z$3L%L=fQ3b5k}u-_}d#uZ>+ zD!`5^z(y5dhZSJi9oVst11ny*u3}2u&zC$6ELJ++`(U^UrWxyt@3>0a;N)VAtpZ4g zXk0V{tV!yfXynrgjN7J3w_G_>pd(PlQqwF|(=daA-Ni z7a=LktT1cIBm|NsjkK}YjACG-sC4ka%eJMdTv~>dj2mkq%~X+HC9oT$$=tby%2YCC zCYznt-ZDGOv4eyQJp?OT&K9eSj6`n{Wr!2qfwhlyegm^aVHYd@8na^$)L3%cLXEAX zE!2pP)E4Sxd#FhOX{j4Y%xwuZ7Rk0yW4&q%^-FuGVLsdz*HL?@VMp2)*AVX8LLIoF zK5t-AwXLXi@Mc%krtoH$)28rd*V3l&W*5??@Mc%hrtoH$(5CQa*UzT#W*5(<@Mc%e zrtoH$&8F~X*UYByW*5w+@Mc%brtoH$N*ms@dh6u(M6_rMDHh4*kz$2x9x0Z`=8LVcSxD4^0v4btO7n>8q)(nt-`gG!q8q)(nt-`!&jR%D4^0v4bo#?n>8q)(nt-`17({vD4^0v4br1)n>8q)(nt-`Lvoun zD4^0v4btOyn>8q)(nt-`gMXVfD58S9r;G#)k9H0lu+q&hDu}=Xp=~fL(=ZvxsfQo~ zVe$}UAn_f748*cSkb&%U2r>|G4nYP|$RWr;R5%0~?B|CdgH87kWUwWD*p-lVG3`B8Ta}J(tCHcU1SeUu*29T_ zBOGlu7}r)rq2*vrq>Mq3Gy1{UC@H4No+Mt|C$Vjx#HxJ~%l1i3+9xq?pTzg}NyP1w zcxj)+sC^Pq`y__#lL*@<5$qswjc7|_B&IMt4*rdOL8i8a6Fg!u!4=EfcxV6ZpMLUS z%R+(4uc-|3R0Yr8J^57M=N521FQa)`Aro8k?vrHv@;AXE4hG}MBM$?WX4v~gQC9mL zYPF9Y_c~9idniKKlnO`@$F^)~pAaAbQCBI6FhVAR{rB$d?}M|PQ!{JvC$LBUQ^ek7 zHTJ3?+U@#c_4lHomiPTYJ7O4O+?k`UIT|FUHA@4YXBUk!-G6Nw;kIdntELeyn?^Wk z8sWHUgx{M+7&ndZrD=qtrV&O>BOEr3Fl-uO&@{p~79^TmbFqBU8L&Zw;yBhILUH(N z5TQ6~HHc6gtQtfpj!_LF6o;k;5sD*Hg9yces6m9{_|qUlaoA}Pp*Y$!h)^748bm0L zEqR0_WYfJ2($z2F9y<@>1-nw4(bOG1HF2<6M01Z;Nja>zl^8Y-I#h;S%odWaNjewZYsxJlkyW za+$&sXFE#IV0c6VF-1pf1@T@SE2F!{IW9xI7stxTu5pgb5bwpYGOBBw<1)m1ajcB! z8t1qS@m?G&qq)X8E6q=eP{{15#j!GKYn#yKuSycfsHNUd>>3lSp; zoPOO-xi`kOq)t8}(Y?M%RNl=>pG^@Gy6*!J5<2k%5E8ob0}v8A^aBtQy7dDP5<2$- z5E8oh0}v8A`U4OWy88nV5<2|@5E8on0}v8-00$r>?gkD(NZc9N2q706A}NuVor*{l z>iYu)r5jLyBK#A|h8+dIS1m9mJJ%`{C}kzxFH|ff6q(fug~FiE;7+vHIpz7(_E9i} zqdo4~&*;CTv1F#YlJug5h4K_At7ZX(9I)i3>%%@F!%YrW;5e3MJH^dH4 zdO|~h@E(z-QrALV#j~Y92$s?LavRLOhk_p`vrSa=BVv)y-$s)a>1E9^CvqV~f2O|} zX&o+~$Fo5&&i>jtj~0vB!iPdMdY&!bMCJya=?=1>h3myK-bDT+O;4eNbUP^sWd|A- z0d_j2KMU)ZJPXjoF6V?Z|5G*%oCN|pRoP954Y>|&NYHx*2z8_d6Zl91RgOfU$vjkQ zA(a0u836g8I#+pLCcCE%KGf{tOLqrEIT%q%XCtw zze<;V1o3}`jn;Vc`}R`!)P3>BD_J5dtdLLp8lntyf1zE<(F@d;_cHPPrt~=o4W_^ z=JsDFzW>L`w=Xw;ob>1qA-VtEd-!;F|3CcYk6Z6|iIARde?Rei)78_7|1`T94(Z0{ z=_Ev=L%jJQKD<{%)1Bfw;KajY{8xnUzf&UIr;{FTD=5Va-aM`_ukrZ{79F4&|Mj>C z@%7uo2Osx6Pd9gW{)hXoPu?F-%)(Rei+6kfO?>hG=siB2d_Vx+kDmW@|JA#B@bH2v z(0{nci~GlK{r>%fcy;qJ{r>IoH}(4KJ;UDj1=Q_7zuiBbeCvG`U%%dac>3_A?*sL> zJMr@44L$wOP4B7q^;iFw-qT6n`+BRMKiq%m-+50S|G*Xbc>mz_e*Nlue|&&7SMUC- z|KaA_ufIK=Jof(Wf!Nna{N=v$o9|LBPae7qpbGcxQT zd*|2SD}SSGvB4N=pZSe!{@eTi`KmZTm)|_ze^ne(fADkfksrVG#Mhf&Z{$qdV6>X~2f zzdZiRfWO?_(&N|rn}=UdzTMq_6|cYEeDR*{@A><;JN~%yZhprcIJteoKAvP|9C3T#(&c_ePvW;x3 zrkLPqI8GIgVN|DhmIeJL)~iIlV#)6EZMljjKC_R#V<#=S&0JB=vQ@Bn(;6Y!*e?h1 z)col(d|Aw1-8`-sp1M4{&oY zOE4XdqXkS{HZ*4N z(;58)F>Zo&V-;yXkf>^TeNOP}Y4kde!c{cX3LuPr{=H1{e%B3|pvw79$5oNid^KMB zNI?$TT4nm*g%M6VtkW4cTd%a?es_jrnfAQ{%Zd^;YD4@x-8CYdFp`qW9V6BWHYI;HZ1t<5-N;>pDq^h^NW?%`8XQs zKbV1UMIIbr>578=;}w&0w)T79MS+2?J4i!7_@itOEEO~O3G?vsP2 z)e75CMhdEcp#M4Shx?Gjz^;Ix|2A+Y)_<)4yR87bssOvJ06VDwJFWoxy#j1p0rsT= z?5F~4Q~`Ea0XD1v8&rU`NIbZqsXqnj90JG1`Uo(msvw{%B`B_3>0!!O0_O~J&d50z znKLx4Ulz5xe(-g#7h7;wO5p0uC!1YcQCkhN;fuT*^~GvEhqV0ZzQn891yA9=!Fr*+ zHjXk3mYt&v+_Fd6gazylmcgWky7C7Hc|?l-A77+vl~e%aCRpt1$Nj<%F5>_iES^bhQYR(lwq*# zCgt$??W7bwzn_$X=Qos6@X9+%DYiYglv3P#?kRTMH8vGHqE08hzWza;XDaZ8p~EN7 zF>3L%)#8nEJCf$y*N-X5N$7IAg6G>c7=f6Q57#vl1-Uts2~C@;>IV z_`lxW|AN~%|0_;g-Q|Q-_&8G|U%ghHc01(287v|{dc}4A^f_V!2<;&L5XUswyHJ|K z5XYY_h9=Rb(U!A&mSY#UrL*bt-VE=9_;+P&Vr>h)IMVnlXwD{Z6t`W+^R7qHDtz%@ zXN%p;6b_k+cuE<%5)AFjPX#o^>|iQfWYYV31szq`HWhG`GIFJ+;vW43UMip|W+&}$ zToLWTPenXV3=JD%$OVrJL(BD`krt|ehYat+*H^W$iwPCz73#qy4LW@+;Tc%k1lTgP z2XO|v7a`N+m-!uw+jth}-C*A;%GWk06vg-S*EhVY!RoB{A}6u;qHYwsx)`I`7|NY6 z-OU{FCzGl@66e$&xO8A6Z&QjYtAKz{WTZ1(X>0OPVvDGaP#P1^lt8H4;GQ*&rUtuP z3bBAOgL@C$cTNPN&qfpBLY41OU~Is5F7b3U>s*Gxlx%jf%}gU0k_^2*o9WRST!9h0cW>S7$gKXuKs2cLk#SSecL!5{LGt{M6Eo!w6w9nkJ zF~%ENPW!Onj#o>VAbOpPVLTc|i-=-m(qiR3-uUjoM(&uuGh+Yq<;1*Fn|WDng60}?0A#f+@zGtND{y4mx> zW$w(OWQAl1S0GMDFHDnMr^Ei#p`fiz-M)6va51d{xQ6ul!fjFDhN#d7u6%G^56%ah zhE|{oW3clEX6TO~Je<*|+!3SW@lyWRWE$^uccEEB~{z$)SZOz;|USSI?P zY4{X2K8!i`sdsV&c#kWU)nGl+#HkBDQ1n8tbIQiE{t`y(+V6Qk0t6c5IBDe83U307 zCjlT}Ej|lO zR3;COIkZZ2dhOHIB;TGT4CpBMR3M#DsgX_nMdxf7tO9?ufW%E_87v1K|Jr|u=FFvr zNVb+3Dcbwasl1_shi1m(eBh7pzBn}Vyu^>g$vj&J%%&_FzE;GBst)C-M=SJJS?9tpk zZ%y9I3tacWwL09O-gJn%f4nMKrLS!ZMcPOXe8Fu%)0*^t8oqY77cbk*w%2*4HTwBI z(`Ias6^^_e<0;MFMBY{Y^VEZO-vkjGh<3%Cl#HJ&TR_^gAi0c3aQkQ=Cgu?sFe6bO zfdLj0IXV+X1w8@-W}L_)Fkps#JOTq|6vrblU$4gYvx6AhLvvsI8f)->#(YozLcuX+>-zAfE>=I1w~eG_M=l(X)GU zpma0G<3K5Aj>m!0&K!>erJgw+2TDJ4JPwqC=6D<^4bAa5P%4_^aiDZG$KyaLX^zK% z($XA{1Er=p9tTQKb36`|qGk^c^zg4et4$l?=FqPDUO33XfS3YSZsKT*dmLO92n(At zVRy|Jw5zus-PWA5bz>@D$y?O(DU6A=OH}omq8@9nujvA5gotzcWgPgxmGv+RH>+M4 zk|a49@bx-89`Qc}=O*z%gzVLEtzj%5e6Q~tz&_|b$e=GrfTt3&|+M+MWhDi-^c*nvfQZI9w{M4VK^A-&43 z;F8YH=LmTEemL_HJAEoDpD}i~Vn-Wg92@ctmm?G&iqO_Or|P6eJFQo&ReI7Z%W(u= z&DR4S%Gv7Y#f|)+wsy8x0p+!rCdiFZIze{xrXjL3CFaO(M0efO^=foQAt&&OK!tE) zdtSZ3$L-lX19Gw+{~WTk2LEJ{_Q+hk zGe*?sYzi+Rp&O7QfxW1WnjmF50$O*bBH5^r%}nY7+K}vQb-KcMKFM-m1Eo6z1UCo< z@dgoybVvS9_g79E^$0uvID~CWHYUFZ$7A7L%6ninOlKmx{|98B_&r!4kcNRv$}qa? z@p2BOiMH7$jo#@5!|&_m3NGH`p%vhiPauWAlk5;>f0g1-m(zQZwJ@yo8M%~G-mXmrQxRb72)NBC ztcvh09pPd(xU8PcB&(~8GQT8kiUXnSEz#OZn`VDVv_~fVHHQzVsTVR)?V(^Y5nYkG zu@RPJ?dmC^Os4kGW|@dY?V4ao>pNbRD`~t;rjowf7g5@G`(o1iPN1ryUbEDWT6|wb zY2WRO$xy%vO`gfK0U$JVB>+P6RstY2Y9>Ik`&^9TSA<|muLH=hNB0VYv(|DEY5?T% z1V6di*4MXZ?PN;ZbSM2yFPoA@I>V{{i`g>;gQ$ii$z?M*_0rGAMb($dLlu&1XLPo^tmRfChLLI#x$(X(#%x2?Y zJbwxFk*mv%*&oxQzW<7VnbE7S6_wKnla~A{ufs8QW+*dl(mMlqgFHO51(|)zP}wwf zcSRj%&wY4(zQjXTx{v8zkI>NNqUSk{UIw-H1pSgOMwhK{=r+I)z{&1`X)>V#n9A+2 zKe+iV zTfLoV+*&DzMlEM~Z(Uk=Nzz)*C=H@oP|tiBV9aqw`wC!%d;<~#LsJ$PWWW}*B8YJn^ zA4HAxjYthkIgC$`HyVj%pTtW_aohX)?a@2=_f!ADJGr}~zsT~+pP%TGECng*DYn{MH=8Q_>KS{h(f*aKlbkMt#>aTh_|o& zin&alkSq7W`#{;PZ+-zhgWW%UxasrP+b93ieeY}X6Q!RPKo2)xf7M1;=FnkXZfHMF zCpp{tiAZ};X7-66BQiS zs{w*AZYO#Np+#C;BK9&{L+Rai%~VrD^L!wJvU+b3l+Nu}4`ROTIiDz!V&DK&v5FJb z05)p}BnNFM?#bJ4Q$%B?+97G`8u5qPr-wa`=*ihW4PegMK2gXrT*?2By|<5%B+2f> zl44V$B$A>C%aUwMYTD#scW-8Ax@Tr@cQiNF-R|6Rj(fXzdwb+rhLxb4>Z;oM z=$Ck(O-J1}GUOB^Z=!KoVg{hGF<00hTC; z^zXg+dJ!3!75P=uySInio~+2o7cXACuXqvhf@r#@CN*8x1@3U2?4gUAOGz&7@1Z%Z zv~gj>m=Y5Ytg^{7Vy-zynwVUzUDY+I7rdY^jA4TLU95232Ud8X|3^sgdyV{EY6;V~ zFty(z7ct$aP21G`ue4n{dd+6t(@9klj*<1d#@ocg=U4DPQm@lz?*}2VTGFLyBc%beg0lxQ7ap}raf3d0tTzpQ^7+n3l zi@|Yv=|t=dxEkz|z_nUQPVtK{wo$)`5yoBh8>EAy9gJ@0al9)}o)}}k!!PQu!QFmQ ze{H4sMLo8rwbc&4sK*8q{GuLPYv334*lLPj)PHleeo>FjCHX}?wr4Dyng!K4DLpot z>KFCcWRhRhV|yunQIE}~_(eT7XSimUU!a{UeXy=R9CtD=C zpDyN4>29M z6K9-X*klh}EZ#<>0ufDI=(Z_v=fX_g8#2P}D<^!s;{lRo;`G6j(Wv;K3=LT%5jxce z)v&5Nr~4J=oAv7W9$9nD3~>aF4rS1ZH}>GFQx}rwc$7c=%4c&xmEK%3g+QinTp|sz z{&q|^yR%3z%0ezq?I$_ z#kY^8w;%&;3dj1AX#PmA?9rSA(xANE_z@WhqzF4gTRgdk>Q3^Xyh|b*`03CEv@R2A zkv!`?wfMR{jI^f)-Psc~Sb65CFM@VyEq>Ieder*hljzpq>L&YOl+-5sbN#^ zbPZR4?h+lH;D&cnICQrtrWh*m_7`w;oi3VFXVjsh-Wt(B+|8XM0|m&Z+o}8w81~ol z_i4FJ!~g;vmbeB(+g>&!?BW(0k?@P0uUA_rI=6Uqgx%+>%^C+zH|Kk6^$jFCZ{DQ# zW24(lqXhPxN@dl9+jkum6>zynMKOlhCqk=a_cl|xMn;S1rH~xdkYv}RXaJ}o!X^Y3 zB5WGB@8eh_j4B3~^Oie}Z%)^ScxzhKgI*yMC$*Uju0C=(O9i)cqctm<@U6rk@ynuKqJJ#-b+z7?Lb#5n<{Wd*~BreR5l^F zogPt4Zx1)J=r9s?SFMFL<3n}MHLHs;J;BR+ zwQ(gC2f~`1X{jgQJ|7;mDMsaE%ke#mU6n$3H-*$y zI4j~0h4#hNxerfq10G$(_SX9sQ?>4!->2i0Pt=dQ`j?(&d#lP=Fy`V1%!ShH3>p}J z2|hrt4S31HbPrULEn01M3*QFC`y~_u2#jJg2!1E85M=GtN$3Wi);U4;8=xDddTt=1 zLTQzBjl03Fa4oDd%SZb5ChW<5M)TDNxMH|K=20;xj-8me-w49-gZY9l(89LB@ZvI_ zFvQMeu%}svo%T@0VLG1pG?)@$zbkU(z^8bkHVB>&GH&BH_6rgcz6X2-HIGu^@NyP5 z;lOr6DDZFwz^h%JG$ItfBtivLx{8I8lBv`Vn|t`oDY^cTl4+C-Ys{wllJtNNm_OxN z5AZ=fV@T-1IQQ3x;6CG$rv zG}YpulUVr7GB7qf#i1oqj$y}EQ&w9Go z$wTTLEc+dKoq#X-Kr9PZA!*_`5>Lt)i`71CUV`pWxUHAPSWudieNY*KCptB2>V_)Q zpqt1Z9c|7L)}j^A(d3QwtiVmirweR#A)Bf@yE}+hhI|^t;pW)QV&q^y#XOif5kyq)SH*fe)46ihh3)YzU`HO4)-{1^1$t>B+)@OfO>!Qn zS$OPNC?`EQg1quo$m&d{I>YM-h0_|J;k#Q?s9~bK4KXAt!ERM#WuOgv0zn}3#tTMh zC&g|6g5$*!7s(@o#u<`J)3Izhq~G6wgryyA{E@0w2TG|TOAf9 zMtUu|)hHDrQ8*QOi!w8!AtT$q?R^jgcp3;nUOYF?64Ibv59HxYV&ISkr-W$(-mhpJt4ZZ!DI(* z8el}>1v9M+rhT~mo6vh;-=|LdD6}Ew#WhXfKD%C;2?me5ZY;DZUBNilx{kPeJNcrb1%$0%*Htq9UjZ&eFa@)x} zb^f`JlaaO-l;{zQ5@i|+f3;n*QK^_+N+;9M2<|Xf>4|Y} zTRPmneMp}6)wVtGw6C`91`~~XrCK-7sKp?)_dC@{ItG&YTX0>En6%_VV6a03(}@wF z&|o-vL!tY4^oB}FftL;5Ak)4;L_#;b4Hi3WMcuS70h^fIRGZh<)4qW)*+HASX&+$O_wHBUc`N_oyKjkE8V>8z^pAGNE*Dq$=e7HFZ|@yP-U7yCdN##TN7`GB z<>n`uZt<&M`oYh<_m=tf*1JFW4*$--`re!Q_kHG_x88p8Uj8}4D&wLz-+kwOBoKX) zfAyUoe2PMZw4c2BeNW$hEBk!0d7l?ppX$D~9+%_nc;%~zg&{v9OzWJqs4dH*wSejlEx2Jn4? zuRo)Hz4Pu@zVxO^MEb>dky7;Ccb>kfbBR9r+LJf4&mt}9Dc0+A1h^?1`|J^tlsJn?)U86x2*=0zs zcrqG4yBe)_5A@?qY~vQl@>cW58Ex6f&$fV6ekZTEdW4?no3I`}d})OHyss}7+w~!( zHsTC^FF$;!Zms$v?O}hM(bl6GcK98xiW4xUfQ}|dv*O`HK1Y7|3iDxI{Zblb`%Rv& z3MSk5GT%H}pD$J$q9o`4P+=oiOogtB{BAp^HP~WuSOFk>&yd1GcdvGlpG+tomn6JuK#jGG3 zBx?{xl$8MdxW-q@(X<*GX)>uAtKf|$lYGWmjvxR?Y*Qd3IdQsE_azi0!-FviD_=}> zA>ZtG?-+(SU#zez>h=5tsd6@t^y`Y2<;R9e%||RQx&l-PmWUTP4yBAWtGn{M(_%9| z&(W4@R()Ymuz_Ln984imcvf7%zBr-LaAnU8Zio7vPlE7m6)nPg6+{WEZB{t=BZQi9 z@Rf;1%UqFUAVgG&t~pt3k?Vqn3Wt2okx-`8eOANJ0S1=odZh}|kbN?TUyt~9ouj)Y zu)f{`ETOd+G7(j9>UeX#go1)dJ=VNG-_B+bxg1}TsPFh5q*~&#r_Cd+VF1O)HE7RV zaF<$tyqJ*{ORmn{NyJ6pl+3-SYf+U$g4=Fy9l{+rK>`n?$KCAek%R)l?FhvxYNZle z;^BJJLswdZQ1oo{xn(EKk!ie?QrR$4N?pD?(PQgdhuB|J>|zD+of^J|AKAe_9nIFw zTZ?}+rKLX1XGl3Y3njB|8R3$~kMP&`_?Xv5LGXme-f>{x9+s$+(6S>(_}$jNW*Hc_lxK=lezL3Yu zV%0iO`-L>j)P5l?D{2#q5zTfnc34N!nV!MW$t)ehiV0F!r%ij7lS5!bHRu>PY%#{Y zVVyQz)P81Z2#0FVvTKNZZw=zm0!^IR@6?X0KEVX3yInCUalP=uFf<=jXGoA7wHQxNF+&UIz2-gd^ra8<6vEGz z`-p$iYt3CMo31OC^D$f3pNQ#Vo*UUJXboP(W-)P~c&xd?twUW8*?afoYkVi|dFi2MV|NI>Etj)vV=8G>Ii5Mblts=K z7-`U>FFcUP8Qrxp#rfMGE><{Mw6ER2GzxvutTd6#%3_b68I{N9NFC9bwQU0|N>>yf&zG(am4>r>`w2&%7N@SZnP0dX z-c-~QFF(1an63NJbfok`LoAmQ;8H1AWinYIQlZW|JNSYI`qq}{yD{XJ?{txG_1re! zZcbmXDyNr6ula9rvIZ>bg+0p==HRtuZ3M0~5$%cw@hB^s*b9bJJYTNztBc|SNBN?k zv)o`7bO{+yt21#}K;6dn6RKkkhnuFBaRG1f!FDvOZlB}iUcbFAmU~iH7nphoR@Xh9 zBK6GNpcT$BI`ndc*H|yl&9#cqIwY^*LTwJG#|fkieo;AtiyE;4e2y zC7E6*!{}aUomBPOcC6+*>Wg{}u||}ia~O*N3TKp9KYU1PiR$4LIM!Cd`ke7sDS|bw znaWqwvvY54pu7}p{T5zAVu7(s34OLRFnHSya?QM@ls-E#C~)>-hr?Y<@o){;At2Tt zt{J^xJ8UDvLbsHnxxyj;8H{E3(1hQeVS6$xbmepp$Gf}Xzdicl>mQ&yY`oRATZejO z>~Z!Klb+9BZwj?RgEw3>+@C@AF>yb~o4E1v2b9g<`9+r9^Ytc<%8-zwoj^=X^{*TpDEty4>8 ziA4P_MJG%(7n(37GHNP<66UpyNSFc{jxc5ZG{lrv1R~UH`fH*Ps>ICP*`0hW;tvL% zAAC@yJf|@gctXYVM+D7g1*T1!IOWKLdSk*4=9gL=*T39Sekt0ZY8Zs2oBbHm2Zj<9 z${>UKI*c%wQrk-tKq$R%u?6+Y#<%p|G&QeO?>@uZQ=ZC=BnF-wNNexROMgU5uPcT& zsKk+zab=%WDB6VnfU<+!gbHf8l?#!D+JrC;U-4GzQ))0&>`i!_)xlT8PzgNx z+CdIwgf=v3lBq|v9gsF|5}SxJ%Q1G&EMDpZluC##2fWkMS5=B6TO&Q|VV`wu6;w=@n5y3H!?5PwDj}wt3a7AjxAo!+eUc#$GCHc-Fztcx>)=B>9g#^Qtp)!iHGs4;0{W#jZ*(K5fPYF0aP7Li;2Sb>=_ zW#VY{nnj;qdzBIp?~QO4&Are|w01Fi?(?9qEoS~qD!W{%QrgQ3(MW{mNGw%hcXf`X zgK+zPP!R%HtgyvnHofq+q!a$yKMB5|g%6x}nB`c$UxYZ5ttr*7RRz?QL@hv7YZZVX z>}dSKcDgEZe~zSjmGemkB;`F0aW%v7(#!4*{HQ?cxfzEc#G-&N;hikRKS zJ4NECgi8_6bPtj&ixZfxSA(-RTLTuDTvEuqg0~b^NOwmLpoxPvj@}e{J{=*?GJG;R z_%-4=QS^ItusB!e&`fPPc5zrb6hK!P|A<_BuJTh)oH2O-exRDlxq* zzgJr&%zJ33Vl}(Q5e;_SN~g!M`RQylzRnSZ!-X993M%bh)p7Y2 zBE~v|xmk+}Gnkb+lVrU(pVCyDuEB=GsBN<4_nNmH7SPL-SsG z%uXn=Ra@AuN@sy?bWe76hAUL`Cs1uU z?BazOAc}I95A_0;qsR^jI~J#!fGW=o+kH(^hN)kAAIhoUJrY5sFR;dfyY2YQA_rr8 z0^ZhL@VmF2+j|SWy_e)w7!6RWqoV)9`>L*~y{_sCUP#|m3oW5KKL@K(GD`Z5P_@=V zlwOr=hz09gfe=DyWSkYL06-O#87bkQEkUW=;HK2PeqE*KZL>x>c2}N8w{=#bRmzi9 zv~5K(msX)XkCj*53K43n!(*DSIjn@vsD?`Y*`fNH?tNgDWQRQpoF^=F>_W|4aGU~) zrv4M~7oUU3pT3)a?&;f44qr+6${E!YJ>nh*A{!1^@6J;Dnq0Fop_RzrPQ-7b?OHWtAKh5ND1S;vja5Z&3cgh1 zN?PGU3gLA8tG zR`Yj++&jRK&HF-BOHE(k?B;;J01Aog3#28bk+;482OAjr0^2v5w*NK=L29ZmYzG1A zque*PeZzB`MfxIY1fsf55ut?BN7&|j>+q%7=;CBDIvgPf<7hoyPo6!zbLaB-!K-)g ztXJbZv)Sdv?d59m^TnF9s8lub& zW`hSD;^Wzf+7`k(fI@#ux}x!s!d<_oeI1qW%>o`*5Z}oKOb5;1qF~B-FM;{N3w`>K zw^v5HR{}JcZ@o$pT!TtJ!of?4b@0kZ-FwOSdnK|H!3*AAAj z%9-L~PAif5^psbpOsQrkYQYsDN`bIk#j=TbS+N;L0xDe^`-rx-Q$7x&CeAn0<>J^! z#;4(rUc+G#6sxoWeC4=T4mGN>0h_#%CEVDC%O|lI>Ot8PK!^RueNhxdYKP z5C$!F@93K1gcBu2cZMS%z^>|+uv`(B%k#VtyV%0qK7y90YFH3^uPg-n;J*(LlC@|R zGVF*Zt6f7yOp(~3vLcULCGv8R0<^?{2X92%>U##S4*E=S5rDU-!Mg+$ZWhD(4~ar)Uj-Hf0i%kB6erpqLhvZI7F6a+biK8RTDJ_jORduygtDR- zxfo(W*VX)jMi*r@AxErV4H5y@U)6DTL3_}_9n!8KvR(^WK-~;IIy_>DkDH;JLICQm zY*qH2o(JhV0jAEHf9pF!Q?gcAYD?)%G3p zBCYH{z!|jb6XXZQ(*5|HS3Dfd$Tei{<*v1U+r<6ho47Z86MYfNZe8e|K4r*#k);f| zFKUFYeD6f5Y@jdNR5s8TiS#6=cglot`yz;h%d-!Y@Rp+-PJaZ-Oe*NoD|BAOD_X;# zb8;?o)I{B%j@{b`mXf*-9jk^B&)Obzz`0K~&8zZcIeTZPGUUD(%7;wjXS^=m5p9!& z6NKJLS1qj1w_yc^2r3d}HD9g)6{~>Qc#o#kZ(PCd%ZA2a_ccx->_J>0IUNgzqH@|+ zt{0-JhF&|BA@dj~6Xhx&1+T*htalYJ4LT7uU(B@vqKrQPL-?)L zE%Zg9>K6K<5|6&!*mhvN1m869=I`rk@ z5^`o`8|2fgXwpPqZqrVV`i;U5ADZ+`$g6|B793yE=?PtHL5Sy-$C=r-l2BEmS_hJM z``1;VU1KUCPkpTkENHiK2SwF?wG zinM(Kc@6Rcd9b>G@+eZfoDlY^4$ZoEM2)&ApXd%axzU!!x@OzHvpb_S#RYl+Me16p zlgh}Z5J+3KWX9`PN@u)!Ttee@11XJHG71Pcc{zTJSJhk1$^?y6mqd-cR+FYcO+wcE z^eG@`s1%h_#|!S9{S`<#z$ax>19-Q9?YbW@h(eZ;iPf&`UW^-5it93)SYK8z2~p2+ z4@iN_tZ=G=W_WUV!kr0{+V#ta1b4Yu=H~@6B)cBhYLML!eN2HkSzAu5H&hebIp0iD zNG;m26C7&pk0v}T?-$&?zQFNTO_rdL@5FX{!HImS8t!ZCj}LdZQ(84jWqR_yQo2=5 zga`oEMAK8;ch^d6VmL8K2zF~(tOCl(Z`%rZ6;Lb|T_ZOukzlg8nz!M^D$v6K4OFJO zx76p0kWbht_p4x^ZBLq5ic=>AECBVacdH?HRJQ_f2Q3>wx!;BdVJVFXR`J=EI@LmP zT0|FlEp%6$yP$SblV#wg?vRfrDAr8{N=RKbpMcd_;R#qh={W(hvwD-TqFRkB=y75l zCcn5E(Y>i_N@csDvo@sBXq096Ko_$|P*KIIMg1O|mWvfmCx_)BXyrVIwcseqwOQtNs! zS}I!&!|4bvPzi5%;?-Rh)NOSQ zTStyF+)d(|=y6?zy26{bHmm6+dLN2H&>KuH?A4aRtMY6DOo41}y#-DLxNeGG0P0!Q zS3~Zo>;>Qs>OO$dQsD{t#c51kgzSBeak?x1T~I@gPhLGBueS`m)E!rgWUZqS z5R@T4=oB&*usRz80Sk|P1c(L1&c;B(ikbtiphuHUg8ae@oVbk}rQnHp6)fh8H*%p- z6m!Hy{5CU4Q6v^M$QjJ&iPFG}xtDK#j?#%Ip_;lU@niL`5GV?Gs^P$kN}?BDucu-!MkW%=>a6KSCl<-yQK7T^L#QrqiX^6 zdvO|=B-%G2(n_Z;R0ROL88@#JK5m_7GIg*!8aNMh2NPF<)6&S5;IuSz0#2}fsZKCG zjtKTNB!8zIyHtj(2kX4P`g)?fjJEyl^~l-C_TN#&Fp$)gRY_6sF@p6aph zf@(GDCjN=hwYMu;j_XDX%jqcWrYY&DNVVIwwQLZ)ek?8Ap!eNfs1(SZ+^Bd15jKG{ zW$X6fPWiC9I#eFC&MuV)4gN?UPL&6jui#k@iiXAm}uEckAE3iJNL(Z}1YMJtq zi^E52O8Z$&bx%R*s_b5w3dXlGzmcHY>^?O`M*c~BHHZ>+HU(O2Ax#Or`_}Cj^WP}M zJWvuH?}bo03b1i^Tr*Kutg3R2R+LDFtr*%^_bU!R95ovmme}^Vug!t&=0EMkv$Geq zyM>OvRHT6p9#sXjmVQ+Qw3gmg37Rt*!7H&CAvk4(ZI%6OXEQ<&G)p#0+TTuAGJqZF zQf2pHH-oQxu%0o9U2SLtW@k$pf!UKijX>^fRbw!tw$-Z`jIY1iW;j07$=-=)H0uylYaT`|!)#X`+kKeuu7 zPr2_P02%xYTj->FJ={wTRdg9z*ZZyqom+<2RpXW*cGkBgh&^fB65P(ZwhS?Y2caz8;t2d$gNb#QuCwUvN7>R1Q2gL3tOwA89Tke2Gy0g1$*=_O`l zdQ!SGq^K*pFLnkKOJ8&iBU*q?hkH|WImZp~RG+#+r)I-9Btc#%uw0>Ty36Er?U*Sp z!g3XFX!0Ap;;{%O&U%<)Gk5*UG-U&YAy`wvgb2g;DZ>+BB`EItoET&*H!r6*?TmOm z%uZ%I1RZh^EVQc9gJ~9ky4qw1s zwPOO}2i<}p^mS%CM=1c=O}PiaeEd2ua@0fbsLBK29W;0ZQcJ}hfz(o8dyt$a62 zMQqvJ*R#Ft9FKtQraL15d)A-3Tj;1mBMo%WqZQCv>e32mE%j*$no~BxtI(+Tq+6S| z(n-heZmhEVCBK&Y->XZjAa>QeK_3TjWEsz%^lt>)&N?^-GpdKZiUEH|{8jF^ugW^O zstm20re$*x!KxnzH3qn&UUdj}P^UhSmRi&Y(o%UEAWmth5^dJi2zTB_QxCI~J`6#J z9WhQO_oSn)GsMDP!LBOKf$GPrU`^^_Tz^RbTX8v6^!p(UqE`nvpDgWFJ;V z#c|Dw`sdRLu1S7lhtU#-p7urggpCl&TT@4v#e>(2b&(MJF)|WjpSDKA?Z@PJ5GyUup{nK$y|Y6ShOeNc zu}D7zDB*R}pAwRfS!dN*1G=Nul#n|p%n(dVT^WLDsU{s5r!Gv{EzMqP6}r1#+zq#r zHjIHUcM9syRO~_Xd7!!~JqfI{zLUUuQgsq!XD#Oeiz+x(!weUzHTltKGRbF`quI8A z?|fRUiut%eo)eX6n}&9}Sm*QN3U}5oZRz=FeXfr(x{Ch(iu~!j`RAU#{e-xl_fnJ! z)NUoWWn;XU6yrI*#IepnPV-aoAeGu%i z11?EP$YTNVUVsMK2zr4jxA64>ka?jONM^^Jm&v}vn8>b%eANjo11o3IZwXV*5nmjL zdM5TRZM0`Y-Kdj@hc~;+ez{ai`eR&vuEgIS;dH=;YK)AYoNI?XF;u&ygQ3HBH4w_O zCX|CC2alfh*o5S&z*=c{_p$^{Hs$z0G$iQbz<7hvy^XLlwPWACInkwoTN;{Qvpy!?{tyFE5;Pm>?Mf`kx2`(<1lTf%>j zXxpavzNuE&2J1BYC3GhmOS$xg2_`w^m zJv=@J%C;kY0?l)EO(YId%pTqS>f5&td%M^1@Dt$q-k`B}fFKR7+ta=c|B$jajN#&D zcKHO#dGXL=^9LsQNWM7_ZXE$fH6t0fIbIIsi}d<3~G8L%r> zq75;myK&nwm|f8-jbRxhUPk`_F~{X*g(F^cb=)dnpHAnaLIoL#0aR!aw8fIUu1go1 z+&a{zFVhdbd!f-4)est=LNoixh!`#J@c_x<>hh(i8YtKTuEg1o33Cm>s_KiI-o}y28dqUp_Rm zUxb@D+k??2fD;sWScq!&QIYn7=HaI~$%YsZnT+X>2Z6US@HCt=f)^ibN3%5s1lMk! zZp4?7Ec=#Pij=U=j{ACTXlVGhBQ%=Bbz@lQ+CB|72!_9gqmLa1Wzz=hiDy*@Yh~b0 zSYol&RMvH{zU-q7zeB@u**-{RoRq-^B&~ta><~+;^^CH?VRp6FM*Z?kjU69TGbr#X zOA!N5@26MM0IO@zaUVe0Rz;}?QItz3mW`bzh%-~Ux?P%PS!%Au+p3hswJm8=ACz)C zfEsf})VmN_zp|+lfx|_5h|y*5r`MpXW1h(Pi)1?rXV+il?JCP3Mk!paJXib3I7Jud z;|bw}>-kLGYJet*&*^Afz`}aMjYXIBB6@Bk`0Cc-J@R1{^6TXc>BCO8r`YKxyp+-> zvQy35St2!{fG#%{S#!t;&5P%rvy{91;eJIo+m)EbYfJ4>-E<9(EL5*Bg1g$aRjV4c z6^wg{tBKde1RnoX4nV|d4@SG;Nt)W>jW*6Z=ccpS_o=-%PMAqf!X0sFT`mRXm($|Ppe8$7@hzRfndGDSBwuVd z%dPEI!l$ZPtXVf`PH&urZq3c^sRm!;W`@59g5vS@yxkfCm&I0ry~e*^LhZGcTDv|Ty{NsK+O8m zJ-||~ZXcBD1(I2tN+)=QCAxq^H9AA2Rzng-OIV^0c;jb}Ud+Od3k`Uq)6i=AH$fpL|C zF<#7ObQ`cBzGeV1s*y@Dzh=zg+%lxlsi~?bTMR+L6plyp{8@2*wOCC=%}y5Ggs+F? z7C&fP>V42PO+WvmAy~q1p@deM4UFHKpIpyJ7dv>yXo955n!(cQ5^Ge~EHRrn?sfE9 z4%eOh*w^X7JN0ESo$-5_CFAx)eEA#yM=wy0%^zh+JqxoWfeX-cC4@u#!mk3b4{P5vZ z+)eP=>rL_b+2Uk0`{H&}JWu)TZQlRP)rlu|Hlymli9pg1P+&gc3x&{EaFBL7Zivz2 zhYy+T*d0A!Q@S%=WAp87hV6kngEb_R!s!i#&lpF2qBmwvN>z5pXiTHh{;L2Dy^)?I z{WjjR`KlC}N%=@MMM0UA+Ocp<%6BohE#*6l9mjE!P*k6os7-@Lbi5}0i^XZqJ8_I$qQcq6@=x0ux1y13O*O>H5+X_yG@pmSqjgOO0`S-wxwyhv&XdI!8&6KAYlO~d zeNPN&Ia8(@eLH)=qcfsBuh7(W=Bq&Z_ zDRS`|;I~}|UmVXQf#dVhJNYCDlo?D3tvTfro1%LIwm?~N`pHlHxe+jrKN0BBc#VTN4lg)l&aENHxk|SE`Z_2VLa4kO`-OJ$ZkAS6^ICND<8Hx(p59vi_B&fwE9q2bBK0jJ*G&TgR2X6 zMfwy3yqdRHig-mD@yE7#8;K+D3|*juy%tBSkvwKQOpCl+ha6PVBeAiKlXjKH5t&qtkrVwILx%2P^>--Ho9P8I zW)6e4fo;}xB3p;eGONehi}$fwk|Cb?zw%*g~K(in96K3-UnBy7I}pC)~uP^ z73=M6g9`>-Ka&sJz_|)8s%r9S)!a)CZ1M>npyHfJQecu*Vn#TuBb6RK`@UmXyFEnX z)|ED5b_Z!}Nq@+)|3lz*dxv48^xL@O^sMN~eqo;gg*#}#ntvTbwoL!+|!Xz(p9=K zJ~n9{U`U4&EXi2T_oHf!9KSx=N%8mkXeY_d>${H7mJFvUN%92?I}; z$uBGTG0BDNqigA&Tj$o0mJrfVpc zFQB~|vFvRqL)toP8BXY9njowr1(KdqjARI-OFMP8vCnpDWRJGX4A7KdM`H;GXeHzZ zYmf$LOY~^Z%^0~Fpi?0Mos|n4i%D=;hkl!R3O(-^n%Lrd`VPT2YnU%PKUq^HytDTm?a=orbQ(Wv`jb1Lvg&2pbi z_YUhiCo8q|gk0hkof*uA0tqjrKi^ecqs( zrO#XT)v^T9uD;Xds_lBe6HX!->f!W3k4nAaHQfUh0uXHoAVDPc-Rw#ET$foOjT8tk&sIJ7XPS+RP*Ry|%q;^t_FR?{-bNV{L%_j@}125-*joYKK zca~q{4`uQSCnpsokIgz;m&PDaliL^W|_qdi|z8KD!Y7i?^D@& zd-0mBN>6d>+1-^-JT8UjaP`b(H4$^9R(%1KS2YJ-<&MAH7D$BGGRUL;XJS zekE*>@qJAh!-OtAKCf=1#(JQR77x~fMeES-j z1_0ROlk3;+Zx-}>jz7qPy|_XJJmRFuWINv6w@>$~f#a2~er%tPsQUAJg!w%@QFEIq zJ5PsjG@h`_|j za>VbRA7_`xge3hrovzj!dYIw%9sK(hoMok-{AamX9|xnTf7?;y-)0o)Lwu1xr3=5F z>U;_K{n_bcx}ro}i}`3K%0IVQ(UCtQq2~2>d~%;@@e{-D^L(!ZEw z@W0zRu9Q)a{Clw+eXuR42A{d6hw*GQKg*GB3d>j1vpHpX9aD`j;cm0VglZ^ur6=en zw2A+&#{B6q26TE!*B>2cC)juor!k+grTwEUk@N@cuPx%4@JZ|YXGY>rw^Wa}1KKm1?eKEOqj`8)tk%#?hevO`di3gp+gGFY^!9r4 z?C_=Y&1SiNc;^m|#hhap9iL84?jN5_j_-f!`0mRVsh8a2cW2qp|JrZ+ov%(n@-y6pI4}OAEXxkE ze;6^akpMJ-;(?8!tzwm#;42S`v%i{;H-o10Ooz5nAu)AlqSZwa-D8n7bAA`5p zuExb}s9wAo&$g2yo8hL9+b4?+Wb*d;Xm)yMyxL@7iix_$^wo1}1!YIK!JL%8?bUJi zThR6op!gvB5}{DSiD7OQO9k*^yPn-yuf}(Z`K4;E{0g(%Vg*Z(rFCbGNLQgc<$B8f zp~8!M$2?%mquW}f?vO5xwM{o>>Q7>?32RNLJFmV<|2Jd<_tDWKt2n|pf*o(m-ZvFz}{#Fy*)p#=#w3!kujK39QM)G!${YaDp(&*N!)Ttwj9-o2+D24Z;G_Q5SfdK)z+iq%HTsbaJ2U1pr8 zQO02|m!!gW+wFu(*&y;mv0BX+S;qfp{qYBRWPe|DWJ@52rM@E5kn99YYKeYIb1$s6 zAeoRNg(7pwm}Y-~DfD}*DOA={&==E1Gb7KmE<@Ujt_E2cW7_n)E)+Gkb1axlz;_^s zdP&KSG($RX1IjP^drY9e6D81)qd5?40;|Suhcv+@xwFMMr{O`h;MYdn;E zoO0lYK|2xUYF^o;Cafs)C~HxkE|eS#M^ukJC#*HYtcTurbujjx_>=$ghgjf$e^lU0 zHX~w&lx|6+MdRTk;td6x=XM$HP$-_&8;$Q^5`AkmiOQ;8iA&`Gt10v_Y*{&H^(SS< zOt|h#E8%mO$24Rmj+r92noy*n@vD}a7eF;Nn!fCy?`4HsayalM95k>OQSEQzzk}>= z;%`~)zJOj;&!~J(5xl^izCvb7^oaV3;Lntd3N%pmKQmAKwE=mevG!mIPor!#ztszI z5ZFc6r@ z%&oO+ijwRNW~qBkSgMlJ9#41WiL~$A@oTm?r3qv>DxgPM-$3q!bVA3_pez3%d!30# zn!2oQDu(bIQ%4(1SUhLFMwLOtWMHvJs+qg(p~-F>+_mX>|pXY>bKy z*wWA>+1=gye(% zIsA8!{TcjCCn2^NC2ELv1j$ZU*kYq*C!!OiDgPFa`2W&m#FgilM&zdW#vG2WOjJG4 zFVZ#0PO(E$ZzhTATqd)Ub1SWO^&6b#`T6jW#K4j$KW09By_yf@%8FT3%tj}R6-9}_ z57}ez$3gZw{w8yBY*L_BQ`dL&_O?VuuO75v7%wgSTFEdme{L8=v+VK|q?~VPZv%#j zpV#BjT$~|M_B;8Lm$<%1?3bRU|m32;r(yZ3@ECOR%iL;2s_x;dVfZC z${h4VQ4R{JLsCvV>&&LQJ4EZ}&uQU2k!2d|nh=HfUb?1Wo2*?C25lB36>VtOTY2-_ zZSDrhSe#Coe43KAwN=;6-na25KY8c!2%J`|POuuCYpt+c62me3VAwILLgj!nEbrhA z^N!CDP+4PCK_LY;=@IL;c(QCJl^eZAC)NAY?VNXxW2-D$T+oyeP1xoDBl}N)*g^Im z;%`}3)erN2NEzbLo!hHfCz}^nG*I{lTUlmHY;ApYjIrZk@rG0nC-zl=r1*lUjvw@B zM+Mup>B=p$=gOAb(UPu^+XZh_!1n;wK}I`V$^%2B_xGZfx67=@=fz|o1+a(BE{uMD zJuPMv?SAn_qLS=ne-})Az)MYKI)%*Br=BW}fpG=+g+I}$cEqG6z)-JGR$%a)?7>!Q&*FSI2`f^3fZMxnn?Tx3J$V=jK58( zwHK9k2d7z{kBcQ8=_$!)g?hu$k%TeW3;In^#zt3#6Yt_P1Dqz6)oMEJ`=;JUsb766 z3w?Y6BTl>A!PVpEqZ|fv1q-tL9x5Tf*J3>-Fdi+glpUCaqQkTQTGLGfVJJ_S^C5 zAp2(g?VUer*r|9b{wt?Ohr8vSYMfQ@%@y5#A)ZY}&tp#eFZNfeOW*g2n3E z2t`f-wMj86Hr9Fx?uQ)f8IQ-xsKEhCW^o7?39EHnVYni)&uJuziOPnqB+*JGz*u7l z_KwX^P=!1xo}mCK)h58`>OervRx~nInj>ji1(?|*Xte{LtCWR}2I_V>h(!3+%u@EZ zn35ugM#igc6P#G6F|#1Uoddl|vAgLcC>8NsNLh6~$$|Dj=0u5WD#&{Xk>*d-22L`L z6~R%6AXsdTzsW2{yF!~SCTDshDezDvRb!a_AoKT^@i)0~ZPqHdKR#RgFgiHsC+|ng z_3=%+k_g@}hdLkvLLi9sFPOAv%}Co=byN<+hannrxt>=j7uGW-E@IS+XI?;JL2#NS zy~hN9dtid6v2wLOP5ZvFDpLo?D(M-GXbAd&nh_077Vs}JRe!1pRlgykO){WVA%rHY zh6xN+ZF`FjPF1)`0Y%zBPQ3!YH_$J(o8mdrCtt%SdxoGBrY5!OeMm+e2sVLLc2Dl_ z@ehEiyO?&>q7l18>8d;}0w%Xs8c_Mz3S{8Tx8Hs9`}6mneCF-BQ_6$Y?Y0LH5(t3{ajLd_yQkiYQi} zyOV0us;)j2jzu35#tv5(LsDkfCMQWuzTxBBv#l9gYgoGQ*|W!r3@XT1fTgkjsPYU&G(zNz2EQ*J63Usd{$4 zNS^|&{TgC9?b(1KtT zq^7Av+96Pkp#4_I1M%gICid$kwl)896I-*3^jb%~7}-_9M8no}l~8`NT8t)RF z)v9R6;6juf%a`WZ*{{OjA7sCRzh!;?;&_Yb{QUXAyNs~ts)qfJ-Y{AU!PM-=!K)_K z+ic!3i-C;=tbW|~LfaB;;(Hkg)40XG0et{};FSM@GN=k~I#g7&E%|JVdnJs(k&JQ9 zBC+uX;$`dcZZuSKQb`l2U|SB}+qHMKsRhOlni0=tOAgPjv{jS~>v|gHTT5B!ueRfj zS=m<&!RoN~SWa8KsZ7h#!&uQ#|$hllWU! z$9-U2EpRw|z7~lYG-J8rn6NC_PcU{r8pSS+V%6=}_YN#l!U$}6B{Ol@Dt6BcYSiLf z-)7eyDeTNZm$3syZJ|%+`#}64dli2ha6#=_b)z{}^&q8@q^ZHuVgW6%pj%3mOGDac zVRWh_l^xx(Gec?M4zkh@|whrjrq6saeS5ib?(J4Mtf1A0UHi)OMyo#oJ>HC zj~Xl9ksOYd7#8Xf?I}6PKG%d_0TEr@xwMj|-(D0qZ;)oEecnec47@69D9=B#KhF&E zXQK>~Mv-<5P{DkZ^}!QGlHT!Xc4BU)AP3|i`!8=YzNff9P>bKc!Q4ta`;v|MUc}F* ze!I*mO~)N)ux5*qka}OTWquLp-%t%$4hAiCY7k7UvOmTI{#pWo!%q4nu$M{osw|q4 zNI63ln8mkqdU;tu2FzhLhW$JmmOLg)QM_>@!~3`SLp_iBWfr(!>L75{Dzl=edLCBs zwt^1UraN~Un zs@D(mfTrQzRP36GK4~tc$RSPAHe#eKLpaIBPd;@sWM&Ktmhffhh%>HlucaZ&`_?yf`FH$nG;Ek-boDE%Mr}fnt$ULST z`KSO@2vQKcqr0f}@l^))g3t24N@j}~tIK6@6aO|Lo)YP!yz7GIU_Ui90)QKzQ@ZjT zg9ZjS>t=34gC`|4nBT?<@V7QmfP3NHG$qu+BE}pIUzb}Gb`u5@c^j^D;)e2Q8oOuo zk>Cg5j$T1x@y@c7r!ZZqv6K+=?3ck52iY&-@6FO>H-R5&bMWp@z)x@wK_yGXNA(|K zWDl~xkH5*I+GZBgb&$yFyA;`myP=z0udJsCX0@f##AiRnef_a$U(*n5>e|%KTOHF# z?*sB>)ToY?{5%UDopDMYA_HO2CA$jU7)@DA&i-rzULBYMD3O7EoVl?n?m_< z?m^1kD|ret$?vygA(epe^F!N+;WLV*((R`iDEI*Hl@>J5GG_-y&QFg+){`=$9%O%_ zD+gE)Bu=MFqJ9{bIxpAW7@M(xl4n^k(im0m7)vp-aY0n$4H99{0JJvLRYAy@Q0^F# zG#RT_Txs98lhLe_;#PK?9*fc)g@W#&aQ2mNBS!xs{+6v(eP4*?``F*6{g--V%)({c zf!SAQbcU4r&g=!59lpk1aKP>~-0Qo-Rq6c;(C)3_lhjb>*H+*5siaYOLgZl<&8=K6+UV>Vol zW;X?)t6h20_a$1`8^41lZ50TDzq}yB3QbLjtgB$%Y&chN3NVF&8b%%EBdDKR6{=Eg zh~YKRW*=M&zedun}8vtjrArN2_&idWB*jpp1}uX6STb$?pWI6v5%J z=|RJF6PtWi&^ZboywfSpRupqek&f!q`Q_r7UK&9-dA@;0z?*N!I>>Z3%Qa9MP+fnW zo57gQbKEe9)T8GaT4S)M)75&DGerUWVro8Tx05Kcz8VoA)VC9^@5r(h^1@vfId0e} zRs{~yqXuYF%!%Il)a(ggZ0DO9Ui~hN9qvS-6ZiN9uCWvX&uwSaO`?w>+sOzwZXDfJ zrA#SqOeMNNDG;Sn^_1uSg$_WOc8-J52zx6V{`PV(C{@Dva2L%sxbIXm9p*l84^@H2 z&{gn+7EvXd-A;X~>JSQg`3l8jwY)Bou?ty*hg#~QM(m;&zA}?9@kn5u#Clkm4eyMF z-tdm+@`iU=LBXR9x_BaL(8QX*!jJsogmWYC(l6d;E8u#N&G2{kw4%bVy2;7!`#lNL zR=cZkWxadY7B-JD7?k&JPUoi!lYp35m44Hl+{%l!B~ot_yMi}Jwq#wY`cd7&@MTU} zA!>{ivSB_*AV3lKvD85~*k|IpxA5Nq-{e*1I`k!;T9MC6kh-$x8M5DGIR6BH%Wy(+ ze+amj&+S}JSDWn!TQ5}}>F}@)?3z8S0}^L{8GjD4pTXaONnjY1=o*g&hZK(s--mW? zHJIy%sOu&2)s!T-RL)+Fl|w0?7=95if=pWJhq&1XbB0^ z*9HJgl|lVlVh4GVQ*FIuWgQx`J#C zSwuS!Mwhw*j#TTk#;C10oH$ecs7xd*Ip0c?EcC?zZwMlgA&BY;Rubai`FT7+Q02A` z>I;d67jEQA0V>;7R3Sma|9>4-I>}O(1H|c^^dT_F^%iX}0*uh>>COO%vCU28Wmqx9 zG}2Bk*}N#>a%sY0Efl}gc}pdn=D>34R5JkBO2pk&t;P`4bV?JRLH(Yhy2|Z z>p>%(wh&f#UcwAP;T4xFBRoVsR=Gd6F(s*G^8>N1DoaYm)XQAfGL2lGH zu~8eHRVq{22UeN%xe8R{C)8&tPz_~j`=fTIXd7j227GmjDLMj*))a9@hnzG$k zNE7dENRuM!DyGb(2#+gJCeDdc;9y27Y7rS9Z4u?O`jq0Bcp{7`j)@9P6EBWQHO=Ka zc+M^{atGNGe|KBJ7ceEGR4)kQk5tg&cSPSmhlA* z(aqZu5Hq+H^V0^-antG8uB1C?DOFZf3@((C@ks!Bgz$pp`?m*}9Xk z%)xsKsl!GaP&l+>?z&}zi^eS(q`_q~tuW60xuT*GNf<4DkTF!IRdq`*e!$48Qe8zG zT(Z4t4NA&a1qF|+ zFrKIzWQF-F{P3(W-e>;>Ti*XX$?~=ruYJuaZs69XB32*vqce0y zUDH*;sGWawOW$WF=NoW^5^o0X7wHDBj099O?x@OSiV? zPmQ3=+(A&7jZ!ESy2w?4-8vtw&jA{9xb1wjy0%+;Rheo`sejVA6fT7hv}!qd_GZ*I zK4$$$dsdazRH|EPbT;e^->?W40L^rYt843l=kjz)Rsax@jhLgEWDSUNE*mjEP}zvN zN%P*`1Hg^I&TYp?i*%t7rk;nltDv4vPs{*Sn3o>atdoK3QH#ww@!lF8`brrcE>*Km z6dI$0Ql{iWx&e4!wnVxnxK~%jlj(vWt}*X`0Tfjo`cxetrcc$A`ZW8SV5x)bZ{Y84 zgVvAA`e^9&l8)(a1NNnt_%fLi{{Gv=?Oxi z&hWsJApz4YU(k^TiWZU;i{#g*_xb5;bO!wcrDOM%spR}949%I+vv{G;ACSSqW7J?l zx!H0%3zdcbq=VF=vR!H|QcpUR=2TV;eMA+uV%(@uw5_ZdfHbgT++@8K!=4X)F(=S= zMr-#K^5uL`+CtRtj4=E&138F3LxQeLK;1$Woku*02X0gJAS`WLn@ckVFl*g&3ERrFu9U zhvk{k49EF!w2jA8jj+(T7*=%^7Dm(C5n!A?INjFigLbvgP^#G<;L-oR(a|R)){|!s z@7%dOe(>sDPHm3q?)7@LSZpwb#mT4H>`r5byT6LI~y)YVjjK*NV=37e3 z&2z4Bs|kt6U%-DziHg4!;<4vWn1JkNHMi$>d}e5H&3wRlN>5b`4QaVy#-+Adoj|6U zhz*3Ny332{Q&O(rC)`(nV#Q3dl2Wvaweig2s3*7(M=^LLkUzx&`D0OmtQZ+>qAT9g z`tNGKGX^t=ILEX93^O`AIK<3wvEr<~0Yx^Gu7|X!3$jDnOw zkx!X9F7leA2iUwxxo%Akx2}2N3><1&DWmPWu){&b{skuX&ov=-ZF)TF#f#+iR-=)o zqo`K=>}Gaxf;|45%GH~?ZVYKYbmP3bp44tgV zPvXA=z8fUjYjIp-Ug@I1m$>!lF*6m z@k3@S$Is}*M)JRn>;M%LM%OVL+G2&r?0;j$_P;h!Y-*4iQLD0YBRA~Du<9^kfF0y( z!wn!l(^Tm*j~jUUiV|cS7J!7AhW*V$hEViS9%e8-*Uf0zMLTCdXnCC(}3oM;$4;bJ4bm&)x!^HJkf z_wSw0XZ8w6vQqykIPf6*kMTEI=d*BElC+Ua(bS1-5{;*Uicf?pagVXXK;vDHLrhvE z6H=V`lo!!>ZDkj?Snt?+r0`+f1P?Au%>=Jje}RRJ??g}x53_UYb6PoGrM?9r;CSI< z(+NG1#FAq6Dl_LxO_=jTF{`KWgPYq%SV4~UKn$1$wpxhncsbK1ykZQQ<1ZCZ^RGps zPGj7m>M;A}umm{>jxBS|24IXR=UA3@K?a&n{b9CG51QB~=HHmWsUXq*bV5JMEvuN< zh`}+l8b8%OXrKL6Cf{GW5#+08y)@Px(zY~(jp^oSEpK5kN)vKoIoT>_jE@*Cj7x2# z!5>9@oBci>#qVk|iZ|X#L-b`;xS%llRx(+FW~6a!gc7t?Mus^2KVaJYdmk;@3?mRQ z?Zrk>SxpCaQCuyWfTiW4Nm+Z7qhJRo`_nui|5=j(`Ow&SEmcDekMWqgT3`&3%!HkdU`_iATuiorZJ2?knkmSZFrR=3nIfb~H(#oy$KjfP6h8QD^07Zr(I z+zdCVSIxoo*^e_T|H#Lz+}u3&$jZ-8R~I#`tOgmbCt1or#Z2-iTQEr)(^IYZ925%z zYr9#-x&Y3ZC4Tzz%uj#z#_?0vzSj#_kQuC^vR18TmSL7}Kr7(}RC!l!Y66AlTQvaC z#tBa}MoKY42bvWe){*cjXidP47je^1FgN|^3*jbxR)xa>mYu9eDGA|l{+P$+JiDu! z{Oya!w8l!}G4kpUvTwuRWV6;}#iLqbr3rmg&9AIHE)c*uBwTQy7YW9=Mu7H2`N@#& z2`2EZ5OR{dGp5RDD5^B=RpJu*3nKP(jlE8GMa>=n^K=AUY~Hv5;tEpJ1nQ=)Ux_XW zj7i1aRE(<^Vh@;|f1`;Z`49*>_>My$YBFh!RE=1FWa%)TZ&ozl!Z@eU;bZk?H~6b? zEHvlEz2n=YK$l0i)uH#bwk2RQAz4k;+een=MziJlD4pd#vUCvp98yH@BTI+nc0Sfy z9#iP>Eo_qLGM0~$-w9nIx9X%2;--2NCs=%arsO;De@=Pmeh7aD8M=?0b1W#yUKOSx ziN5hKGo^p238nWE%TAlSRZmAMVleToxfPX@*Sm)f>1-A!5ED$cP0UfRG-EqLS^jBq z`86KZ_nM4qZD+f#D_4(G+Bi2ASnXFK7&ga3J(la0mND@#DH}H61iCq5stjx@&{%jn46LH14)!aIdAqzp&sHJmb{<3_V$t{7T~J@kc99a2kJ z)e(=cld|}8`0pV5Gx(eA$PBy!tH2}KqDgYVC*zdE03-?Bf7%4y;`w0L57(}zTDh<1 z5Cj7^gko$=K?*uDi6Qm&Tl`-FwnoRZ z-^6vf2iZTt-!g;NV@RDH{NlRa!_uTYX0ywS+soDB>&19;M|Fem`!UPqH=y6hi+zut_BDbgLtc(V zWSqzWeyW|UTQ?lu4dtApEOvOmUN3SuJL=XhJCj#GU5a!#>6dT=7AyLsoFW~sc^WmH z6u1L$Lzj6_7-qrVrw0Y-EN9bAezHA1Eg0IWxL8~kIqnrJkW&n)`}kY>@@zGl;kG48 z{bVj8SN-Dbeu(P$3E*)`Kz0N;X@drouU4aFP9_D=asI>@7l#@OEu~}vS`bUo3Lg@+ zI1!&p^p2ma;<8w+3x=$(ViLz)EL zxI4J`?Uc25`oXr)34%e#(F8v7J!r;!ERx)E0bUl zWP36XP1(^>v^QErTuX`}(3}P2z7tvsq7WFJ!FK`fiL^thF z@9<(fmjXaFouK}1Y`_O8R7EXc=NV8qS!2`{HBQmjlhODYfdfS_>U@<9D(TF^G>SCN zc#pz`?P9=?r&HwTr0aix0*#`3LiR)`0caK+1y-ee2#&#-paM0A+ZojB;)Cso7@9h> z&W);>&U0)wIx~0Tk?vs59#Kj{3`Tfe0q{l*TqcOu0B_fn@r+JFZ>#dvVuSgyYK_RP z8qvgEVyy5=aGGXK?h=vhYP8byofppu6V!!_*=&0gXkcyH2qsBfn70&@(CPeg@l2~n z0tUusor{#da+;0| z9!67BK#i;F73D?2lel4l(e%&WfQH#8AbtngA^z?T0enQ}dd9gX|1`eY`DS>oHzx*g zLp)Ow67AdE5R7il{8_2i8$uSV_jll9B(doV-wv?*nwX@;EZTNb1;B5HDl$_rxYp*n z4S$vbQ(_IZosz-22U8dO(@jyxw^Vt+;r2%7V8#oI-kXe%)aSb{YgDyhS>b=v3;`cn zjOEk_NF%bHYga|D#KE)C1r$605ELl&obwfys$@IIZI-iZy2M#~jhM};?^FetYdx<( z>ol*xKi<3o_4Nb-Z`ieuOdvq(#HkE5uO`8vJFh)XOxS2)kY{euL%Z+`Lgx~gY2O@E zHtD(3)KxnqRL3})0AZi0SDG{^ZgJNnzCw=(1i6&t;juSIgfwm)s+dP=4sBCR0FQRK zeNU1G9F@qEL?!hE*a~guNjfI=2xUA)uCARzJeR#jS%L7;zR96YpY61_rD= z4-;Pr50iaGqKWTe5;$@lRo~5f>tSlZYKrVUOcYZUMFHVIW?uuL4zl;~ceke)&t;zO za8-DkqmyaERk!<6|8|ak6U@;L9ELPPZDI2SUd_>I((-(i&li@aY-XV85DK`M&eb$k zsb(+%n3K&0Nw#`6V$PFcCGr&LnM_Yl`CJH3vUIt%PqNV033wya42dhgrJ0s$R?W1a z?>tq&sut*=T-A1{k#bR=Dutq|sAoXWevM`8|7amwA2U0p)vwSOT)xKc`o(Hj1R1YyS~x2J(TTdf&Yd(`3==+dLu5nJ~7t^mHlExZ93dRfqm>#qzQ{sHCE=WY-1pV7}8KI@I6Ed zf6M&MLm_X88TjfQ8r;O8Xgb1ayWwsqcU6c)g-BxI0Si6mXtfndG49|3@CfbRV_hFv zYGRcReLxc;%RJIAgEnTYXpIOl;MsDtp;Z3NjFEgYR{BYc{~?zC-yfC!VMZWs#d}w& zQdBTM-IB*UR=yQIoZ=Md%o9M6z>W`%8P=m%S!VwVlZY-xDof=@nM8=ofa@x0bUGSi zX?AVN^gT?bKe%@?l@w!Sv~^bo8Z81Fl8J7Do=xY^m^_d~#aa;d>=#(c|6Ekb4}>7! zQ#254?tID^;GVEMSexG{T~#ffYJqtm(-RJpmH1Oa&G0fko1``vG95x<{cIvnlj4%+ z;#xU#;E6ti-sK`wZ;Cx6rNTLJM!A^0v~uZoIw=>P#R?ZXKHwp6GJ9r?M)(3cungM9 z)MVGFP_NpeIQwh(?;!ij_*+(qtYcZ7XY@#m;vftzh69t_8B>(PA#S|}gnQ8J_$>P$xf{Pw*$wW1y5_D) zBNDqt-P%s3mtca;^uF5UpGLW)o;08lVWDW$2zlx?1_=Vt_%jj~3W4Lp?3~BsBswOc z3M-8}>7nP(nFFzprGU!W6c@ySo1^2`v7t?|k6HD}{vjGX$o@Y5mf1LLt0xELV^wT2 zMpUX|tVCjGo^>n|lyQp6`WJbue@}F*iEVC6i}YciTVc*m{7e1Hw`^_Lw4w9X;Q3RK z>|bE={Bz%UdUJiV(^u5lDMFq1h?Aqnwy%v=>gR5_I^is^i9;g|px`@EPY6 z)hRs1POPd9W6XudjeYCsd#Z@7C84`94pyaW zzA&>GhB;r1uV`Z{#@&vrH<3{ziy}2gMpbg~yDGdrOt=SP2z96L`uf7o-X)0zJLZ?fk}aAa{g@Ea`|w-_0~4_p3~!6v0y~Ap?yzi~m5d6(_;!j4p~@4#u0H)Is)X z{7oRzu-@sQwycq!8**F*f(=Kn9N!8rC&f0p{B%NknUfH5C|ap#Pi2D{tWJi07ODpt zTF08O4B*VUjUP#6?-_ih?7br618`yJ1E7#lQl{TEWP)Gv8;y_$+k~#XLKC|33K69; z!6>iX&g{5UqbGtvtv)-aaybtqRZ5d`-}1TL7(mokViR=l zQ>;vnqRMng3ukFN1*W)5HZ88ebD>MqwD-;UQE4K=eOUnw7i}fO}bnuljf_QKg-{51Ey#yw| z%D$6D=XXR!hZ#W5vWN9UhF>QhMqY>VpP2WTi}jRpUlHTGt>e(}JUGDy0E{9Rn>iqU zmuKWc~SAzG#+TY4UE7hIW`nN-(ovt8XncWnD%|set4=_ zvN-Jlq1<$=cVUpd4O~($O>tD5CRr4DTQk>RM7cgiYCq(Wx3nRu9%5u=80mSnjf)CP zSv3^dAAt=$$R6Tv#muqn`SQdwktdt-)E%<+X|!kznrBnPz)nQDdia>b%cPFS!7D54 znKt|8*hYZB+ty%{jh$V+K2bEkBW2x+v7BJ&_M2}rbdARwY*!(D! z^f#zd#^u46NH!KHW{OgN$P#kDM+u1y`HN@iYIR5#F#9B|@*I3GflS&FQ}2^KQm@hC zL3O8wBzShZE{bRES?-vLcB=`|8ZN557`jv_LFM|XnkEP1P^r?c()9E2uT z`&FjeuQZ|Bhu`U}AZdJ>FbvO=4>DUIe+maDLcT9dZcYwD zognvy&?PN9-@ZmEH6`M{@Uh8Bc8peAS=|A4U)|J+3vY&`ULeUpY_G%$&RY@SEJgC~YiI9z_9sqC)G^N633 zEcMi4JWD;lDd*l-lvY{hsR`i*BIbFDts`g}xgII+B_~P51L<2-MIy-QIM*rIVFLe$|MOmW}1eq@L}>uz!o_LO@1eoTBh(*Hi0cn z$|h6-U?>hC%aBbBTO^I)JoLH_>YH4XDAu_qWlJ{sJ~g7#gX6u;mQG)(?2`H`l`8Q< zwQq7vqLz827OC$zGlfU>q$=BIa22W;+4d%}CX*!hL5J<}T;5Um5mKQ?z8}X7vLw7XMpnu&mjO=_|*0{7RYbefs2%rwKKZ?HOp8T(~w`IQ=yk*mZ{u%oKGNc!6iLA7g3!ud1an#w9nG$8HugOp48D zOe+&1JBR_}VTBLj?Fzvtx&g!Ji2-{PgNCDV_?xU0Fi|*#&vLz{2Nj^teu2UKToW)_ zcht|f+A0S%aHiM!>Pq=4tLv*3Jt?dO*+9|koAKu$`)5sfcbERF=j^yP7?L3MYH1*i zYMIXt160$*8wkGa2P&kVu^kUPhBj+^_%f~(!S3#bRf=3%Hj^mMXmjX6cGf2w@Z$VH z)NP`onmW6sk&}bwMgz1Lq7?T_v|bA504UD>U;KBF(QV4fDkxFzh7_exw;&OWRV0)a92U zd`Q!czh!lqrtqj%qfM%NaMdb3lQu3?1lVXbKBxG~#l7PfG+pH=hwqoe$1tYiS%Dip zF`33Ci|pSEWebC9YUv3gtfpfp_(IyBcf~n%7ycCd8CMZAHRlPfr)SuK#}h;Zt+VfC zr-#xNmzgR;O-c=zXoD-h9yT@*xc_wg5Xqg-<~W_GPIs0ys4&)!WFWm52y#|_h6(lG zG$B;OZFECww8oMjpQ1#@G(o;J!x)Y<1P3VvjiJ_TeBWkPbrJxc#wcih$CpMhG{1{^ z!CA4Pl&aIy=@?^9j{V0&H_<_3KL~Ts*fz6N}&R%-DqkntB0XvOu)VjXXfp_#pLpOy&FppEZQzO3|t)_Ip_723_ zvgQu3`{D>%g3{XzZU{yfTU`HsLvTT07ipdIVzpYVZU{<^<{#BQ4sCG>7~LeR=Bqi? z`8RkV!XJU_!P^_i?GOv$&e2d_b_6n?h10||E1CF=Ly)|G1z+N~bIEOR5)Qdqyft@& z!tODL;0x>>aqcN9>U|#^rBOFgis3_jT)Y`u{lS-tsHmd0VW_<`=q2q2zz^!M^~B`% z8|?A0<<>)!h5oh-yfHf+0MYJl00Q+@P=2&J8Zb_9g|@Y}7!h*@eMqh!r!l3j-k3J`MF{c^8JPpy1K% zQ+Of@(C!9QV3K+}FLX^PMO_t7rmnyOyvmm#aU*&^3w?^x5fnKd)sy-(`zvsS53--d z-?Aq~`ZsbPRU_$ZH+wNWoim#wC&wzE&Zj2TnwN?v`|r31|Lx810o+)!G|{!D4^1Z~ zxO{K5pcE;kd0IxxeFxc3-{_I3<|Dda;~@K)n~i-P`G1`|@Q+$_phD315~#4E&OsT! zf3;B=-zaC_1{AN|lGyiRuvP|U@kY@MSC|IY*}QD12-_+n-5g--~#F^G;rS*utpKJnc} zFKFtyk1}Xlc3KfQozne0h?-J_G(X#pR{FjkhcrdbN300*hCJm0hBwuX5yYGG>?h` zwFl9-L;4^Zp6f%P3Lb?(@kBJK41wZ(_9gvK@y_S?v!YJvcy8p&R zTXqcAzVx;^AALj6xp`}-Hz&Epjq%p8`yn-X!@k(~WAB<~Im;t+Pw#D>PpH54+V1fu zKY8c!D0S~jTMc_tG>JMxdNU?}(h)>fhwWy&!UCRhkNw;i@NcctXP3d@u<&{;Zik|E zWcYT%Q-*VFU%D(8sH2?%ilbs@*s55si%Gs5;SN#;Aroc5_ceyVfnbMN`KX>>3T#S= zGPpT%3$+K%2?kW64749fltC@V6J_w5a-t0B3&P_BUOFiW;8Ri({NtrCL48GMdgISI z;I>=+MLh$~*w5fRcgjdXJ7-Xis?k{n{6;ygLA7AgfiwbY(m{A_RVoX>)5!^Pvr_}V zottha9mt2ECq?)g?PKT6^W`cZ=XQY}puj0!b`Ii-cyv zssbCsvp$oW1691V7Ti~0q&`J$JQH1=e0bH({tK?ICm#$_U)ZERGw^f;g2$`!+>G8Z zB0FbiOVlqtTf%$0VFWGc*^>UsZA-x`GiMTy)FM%0q5IC$9mW%--j0v|pS`zX4>mRH4|U}LV`vhT0$^lN~&u_F)5O@cHG#p){0o)+Hv;T z_ndcMJjv<1cdUq5Ki~R^h`slj2V~}WfmzN)ct%DX_irr)sr`B>$duR5eGu*P+y~vB zzB(_XUfX#Yl~d8VZ>FzWx!hPubY71mo=I7d(_Fw#M%)v-yre2`)WoAEe*Z`By!*AK z?mwp$uHXIsclhCC;*=k$``$-y zzyH>}ICy)07=~_>q|79LDUeoCrCO&2Kywwt>!@@@F_(qZjg|&!*+R9oShmpZd2y1L zEp**jw$LIVubXHIb-mK$mD0Qvr_pJ(L&fR!x{YQKkH=FndA;P}s{X?dKA_h|t_x}s zjJW^tyC2ber60;Ky)m;%J+m5;YUssY`kWxY@M@MU%_R!0pok+PrPfvvOt-I#VD2v0 zGh{7ZcFx?=0&OnW>1S-`@5|As^qBE`Z@>TE-=Ou+^5Ips3w68xAR;NIwF)Bw`tf;s zS>~RQT=`TK+1LcPi9ug9dn(rvYv%4@GQSE5Ng&j&yBry|d5ubKRMX+?k62S1X4 z$Ge6K-M(IX%_CoHV_AE#BCgk7)V{2}xYxYGVo~x^i*DvWc>>ndhgp4mvPA83v{6ef zro3J$(VxpoiD;*PnNC74r+<XS@0pe$gG~Pqh1tvLPwBtCy5-4l z;=$TgZwnr5jC1)ac~Bu7Dql71`9E33@#wtX1yp4d-WAVwI{WRG`D@mug5khX${>pP zt!F=oNYyiR-Kb}{@R*-Nnz!mHpwm9=+waf^H7KzEF{J?Nr7M-|Y7ah3T;`dFx&GuR zO(hLPgHuLM>5KlRz?ZW;{kasmvY@0AZ@Iq|zw)Lo3AiHUlx98@%xvV6fRm-Dz|uQ# za{48$@?h6#mD-oI%IZsL^}1Kt(xj%GT*aS6Moi6x!Q5ln?S6|k*1q$D>zaGnf2E#v zVL&$*f;66aB4qAGLaMwyPgj>eM4QT=>yap1Tt8frDw%mK!DX&?W+uc(psz~;8f7U7 zh-CRTF_qzsZxi!lHRjvI)QMIH^kMAxxs)XMO@BiFyPW{hhJR6>8o6O;W-f@^8SR)OI&xlkK6c?U* zana9m{m-*p|HIkH^}P>{Ak_af3-#YOh1v;32)C^;O@8pfAG4@rJ+i|r^z|2w=u%sc zedhn7(0V!jpY-3_XRJtPUTLiK<8x2s=T|M|ot!|y4Aq-hJ}g@ZXTnd;d2hcTFqBKl z-b}LQF}*{_4p_b^o6fo2#v8rzzbRJotAT&?Hvd9pdMt%Xr0b2k>mWMsVJ@X5)iRA8 z)a*881C*-fr7o5AD)oQ+ogcrQb~K6TkKTTto__xDhqP_>W8S)>Qu_T5|N6Thz4eD5 z{^K}R=uUp)OKc3~-uFSDvg5~#y_-~aK4e|)`V8f>bOkR);1RHMIhxh-Ya6*LP_ z))}InP9vo)Hr`;(^>iYctJ`_h>_hb9A-TGp$*;G)={`%QbE#A=ye52cb8wc zpu4GpOe_(aQl)ZDN`vJBpZ`n+{>)m^#9K>&PqO9$pW2rKpL?YOf4-YOazQt9X`jbZ zr8eCZ8_V-9T3vY0tZ|(>50TrKYKxjnS|>98tQUz!x92io{%bCZFQ@;wS-G%dHA>?Z zE_rCsx&Cw@+2;D&<^nt<Z#UU> zhJ63s@4fw}u^Y zt7)B~4leS_-_!MS&O`*$e>pqPf6?PStInr0RC;xE9h7(Vy?X|KksS^#>n)_^;CG>eo1hzxV#TAN}e_AAgNtFw=cZe1Glz zAO6utAHVnY6cN^Uqcpp`TSoCCYk-IT&iikF|9fA1<2RSbpO;L`@%C@eV*L9}F`NLl zV|JiohpH|9StAmnWb)~EXD)xUo6CuQ^d}8A{pa%#|7mlGodV!|9D$T*BGwP-lTv>; z|KR zJAVK)ZC%mR)eNTfu5{h|6_?oYb!vc$(V|92~FTw{u zdjI3^c84uuiaH)>C=>Ih|7}L%-|t4E<4iRCyC2aftygBw1Cz~nKcaYd{n>0{438DSzE{%Iid*g4H_rqOsPy zm&7_HhxHx5``*7s4|je1-FM!jXx7*B2XAp_o_XFy=0Msz00A&9wWmLyA^c}e2+vyE z9@RRO^8SZ!e@xpc?|poof!24Gh9C>BGc~94e`i*}zv(NW$EXxGKYWKbbh<#q(U!Z- z32}O#`d&`orT^AJWt&9~07xz!T zy*j*f*pg%4$M5CsxAh%av;$n!fNpwoR{THKRJ>EK@PhTjw3DQNT7j9T@q5ZNe}iM6 zb<_2p0zI`%-}_FHcNQn%V?HpiH>IfN6BQtDQT@BLYkoQX+w|W$cwoj^r@J4`1vT=G z@IY_+tUVsgZgnUaZc3hfG!iaCZi=CN!W7s$>-VrV(HY>Gu;jg$Qw7YV`?+E|56)@Z zDX`B?!DapP42L4-Oa#pb$JeiJP;&d>haX)(57i9sAJLxdyFYwO9n?~s&;GUQ-1vv@ zefQ(H-udvae?Kj;M8=>a-|M$d=u~(Kit~v!pT5%h)yMBsCpsr2ti1L9hu?cMU0uJC zL7nIabojlEw~83@+?WnjnbWtf>8YMt7*`TeLw+&k$27xyI!kXG(F^2U-%u+LFD`%Z z;Sc21kAC<^;*$5}`2C;!It+KuC)K3zd{Rw+E*h^+s`Im+Y@mD|O-HZG-+Z{vpe63; z_VrP)9I!W4*YnuL-PrmrvUwY@=Km5`6 z2u0udl>YHu8gc&L<@CwL^fPfaO+Vvy{Zj-NzJ96~t8F^*6E72j3 zdUtxc$@0a89A>&NugrwSQSzWv=1t8}+hQ3eOV37N4GKo3=zvz0gp=>kq@tpC%hKKH z_16{y+Qz!v^=Dz7`O~D4kSk~q6q_`73g?k_L?gZaNY46(x_VPxeO+CBLtTASUHzK6 z`gL{n8|vye=?ZB?+ZUqBAh3)pG+}6pt!|RWTJvIh9qB;$o9(#JqCN;YKxn({Y^C!zi3aN62Ldb#pGm=tY znF&7Qa>nD}a>Q2}_btK7swcHd?msK}H5`@_;u+o@eB+A?EnQEa5!W=X+qY^nl!^o5 zU2+Gm%qV~|&_{8!mbN~p`0;IKUF#QAKYjI!s!d=01<E3X4KC5<}&xi^mXy~H^krH6o3Dk`1{wz-@hUL{!Qoa-xBvrsFSuqf$k;J)E8d4 zn!fV-YrlAP=gVJO2HUg2QzDz~^9u)+6X`a6Wej}aD0E{-2s@jCVB+UEr|67J(S!G*v1!kOn-nB-} z&ufAoj^|)pqy5h!+DS)vNNdL3i=!_gehm+b`>GA-i13P9)wrZ1Kx?*qR8BG+eGZIs z^;1|k+{`S~FB_EQD8Q&+-DW6@bJnQt857uG`hw(JUm4Bm8c_GMZD__{a&1Y0Mu|NA z1(%f78U+Ewga%uQk36mt#sJX|$d^+DL_hR!2?4l8hBzvJ60|=rfnjFRDNEZ-x9RYY z+I|6QK#!w%3vu8|HE9&+ITQ*YCUkM@V^$UfjI-B}#6jo;yc%068OfuhHdLGGS1O}A z_^htI%$T1?5}RFqKbcuQ!X!iW9`Y>TCu^zwBt(JhIjLA9N>Q^V)Cd$;mT>im6(Nvb zRKJWzW%23?jAN`^#AO}o=upaodGRgw*Lm^%d2vk|C?J21!}7~N`NGS0emO9wgtu?{ z=cfOV9z)}Q-}-j?|K@r9^pB$1roX6cUbtmtqC~+_xf^=c%_V$DQXS**(}-#_u7F@@jijk473g`zH!gnnYq}`K9*GBRD;0p zh=T))DK|e3-l)+dzz}pB$;K zdd5MtJ(kt95HS_M$C3=mqVV3O>mIv6xeZQw5RIR(>d?KxBODi_9=DRG18ao(2Ytg> zCDEjxt<@OliAB1n8kL^k1>EW!9?C6w$5_%FLE1@e*i~16dxI7@OGPVW>1fkdfiq4I zRE*YF51~~axUF`_)u-ev(G$U;M?ekfS+Hblv1#S(;SN4?YN8yb)hLd5z(~cd0*&Cg z*QzoKy!)X-puJkp5yUyfhSs3EGW~iy%c5wt_OQMTM^NgnSP5gWL1ct7DXX9R;mZl^ zT%Pfz;~_eRqQ5*0Rs%tE4Rakl?Ug4>J&teESz$uA1`8#|1%w5f&;&JW>Ur+27~rFz zo&_UO`6sFRquU-R<;N`2D2Y;5@3t)|6WW(d)R;?vis~Kb+kJb;;wGK=0qBh`)+zKVf zt$6i?Tg6@bD_9=|HKf8H_K`{!fTJ#2 z%>&F!7sJAJ^?)^|wcCf}BUw0zfe`sPYvNYC+d*6jpCZKeNGp1Fc@4y`@fv8?gLNvm zO2UfRa0GQ!y`%{AsdW!zG29A%j@!bTP|+D%wTsrqZlssBJV@#7-)Q`@Bg7KpD>P2e zN)OkD$_ug9yVkgUaSzBUFxTrZJ<%3MhN)-m4@U|z=<^*>5YMCSs*q+hirREt3um03 zmGRtMy@2E*T4aBXB*;T085-AWXgw{)mDU;bzTjCYExEcPNj-jLJYtV2{bY;$J5hP# zC9jhiw?{&)WqSqYG`3tDnTcE76KIMh^YxhI1{~tPnv0+o!YeYZHKhqN3r1!^0?W3c zzA>2qu7HAw*OSS5w4`J;T0(6a+i*tO>y%!huV75WyQD_DkcUb#fY%<{U{?i3HM}ao ztwBUo)**R%q?NYn(JA&R?VC_9A`-LzDHH~Bt67X4p%$3 zWyaN7#<w-G<4wNSNlS(n<4g13LkoH6%5rcdW2rvd0DY5|_HPwP#%MKC zs`?SvMi}Q^vli>G<{OVst#Tx+aZOuzu}?y9^Z=IY;;2K<#zJek<*4P$l3JyXZiXXl ziH?}iBb(7+kJtPBMriPRwj!mpL}WFLK{1k%8%HpWD{ToV3yuR-P7wTsHaw-IlFuT) zyj$!f??QA5iDjSWNXB|=Xw*(M&g+5`8|OGSK&;@rVEBe38CtbNWZLj<9M*cZxwxm8o%(;8mR*V#y7EsdseiCR%*8JE$$jEHE96eqA2X6FMN<( zhd_VJ;cylWYoq~JC8w4XazrTDVdmxoCVwAAY1T=x`LVu>a0nqX4Goutt! zC^W4=rfKa}mZZ@WEU=U^>7vL!w}3$dXDhj+!H`f`tF>f3Vge52LZ~sUp@qjtw4o!c z1YfZ%ZWqs4ARg0}z#r2_<03P{zU0zU5BkdQIRgnyYE0n|R7Z&(wfMBe;7^v2v_-#B zuJc*oTnGK#CNy3vJ~vqs+=-@P_miqQR0BUtFN-% z<=x^}`mVlO-?N{0ofF#p^p9HV5FIDAT>2_YY4OP;lrpl>TG>dBTU+dT8jm8?1Ge#vHI*TcB=?%aCmv>w{`!9;V?Quy(M%pZTH&0h29SreI#{a4w5IP}|UG^UxIkx3U~ zEOce`Z2MWR=L%E~UCwq@(|ln&C!@>WN@M{DNu!lyuk0M0{AKTQCU0BHNU~s%eM`;D zoZG8Ba|67%hzME>xLYIRR#-R$^A?Ep&pWu1xWU@Mt@~MUKl?tt5=pDu(7C=XM-th? zrf|_lA-mn9aaU|Jh!OM>(iu<7Q=%ouLe*wcNI`>~u|!XmCs1G&-OUswsB`~vRSjL5 zG$CCDLt0(l=N?zT`;{fR(2eP`dBb+CC(}C_`bwun)n-`Ml`Y?bii`DanO~d22pI~qV*6-r^7=7s3ZU(%+*+K`w#tHIpWiJjrH(f~b68&K zXnjHWS@BzYvJkS;)X4E)r%`^WE|{P4(KpbP2tBi?j_QK@t^8p|+s`;n`IQ7q2)@s* zNYw>1_OkGv9!P-fI# zc{pKO&A9pypP55ZR&CxKl^8O}=#XQs%oH!X&cbiLuq6QfqSAHbL&_{n(#LjP;) zGDY*KS4an>FOU1a#Q7W?M;1E;5|&fl;_*e`D1=GCJbcsyhAggekA5FW|6EX+jwUFJ z276J4IHcv^X%$0;RZrlAOwg*6i18}@D_vzuHim91DoJf%Ml%OQt&XZ79$JLGup|WL zr(792O0OQLPC^!`hDR=mhpx2e8ae&@7&`nwt6)o9@T@6x|rPIwX$c>SO-H)d|= z!VhRQrRt_GAS;=Y_3D?|Ado3ecoZG?{TyLC8q<}e6cFn9?3E`xbEx$3Ny0w_+XQRv)J{uUYh9E{1lHeTR02c0{DP z6`qCT0ggLcT5o^Mdg3)}DyOpF$Jxw3owTch5;eJBsRmjV%od%Md0G|4-A$Q&3(|c} z)!7+(g;>AcQVGu(aU$-6jn!nAzqYKGxt6_r^w(fbxz^_FJ+KZ&+N;{uWpYMn@hi=N z(1@Wa-XdtKRaxdh(3o*bG!QhRj+S@TnorLaTs8QpdbDVYEhHc4n6}8%ihV_Et=2MI zqZRDDu+6k?d@f|<*2jo%xCpM6vua-(Y_zD3bWxa8EsVg@#L`?z?;)rn67~GtD_7H3UVrTuukL*LON%HcY4Ert`HY=kSr}#6 z)fJ*dZQvwa>iSrJGv8&OxRy|3{zVrDJWe@%=PT>a!ds}#)3FUHVo+-GUpBFENu3&$ zf|$rk+^37O$w(Jv=aMeUDKlM^JukW_CyDk#iENCl+Kh5u!s_sJ6DW17K`MHqIb8@@`pG;ri3&6;F2rT2&|-m=up-QSp?; zub4IxO#sf!2^U@>or@8iyTvq;wwOfT#r&2&tpWtL8tLGhjX`nX8Iko}0$F`k!e44b z<5(-M*O8jVNL`{NbAYa3xn@er5~6uje8_^a+c6SJ2J}Z9g4W7PN21-r6YhH=j-ie# zFF{&Vs1$Lc<;NwUOU%f`&j^T4eZ0(fgXTcyK2}Dlv6Co zxrFrwvDrntXPpYU#Ci-ciARRE4|J!aNrVJx6PV>l+S^I%)jC|oWQn=f;Yg5bn|yb3 ze8ABIw_@~(qkZ-^h=OpQEH95VFp?hQPWA9nFoI)wU^{48VonVb=zhdOtOV>o&=dhPyjYf6^2*K9C@rU$+N0#`p(&{!a4nDyF{O`NU@MWjm zPnsze0@nif@LItj3|rgALZG|VU4St|BYE@4hlJ=YnDi>QPpm&u;L&l} z;(t(pTeY)e_tu7qoKiZ#@o0SorT~OA;X|4=0b5rCEpZ`b*9Q+eoWkU-gEUTchQFv( z1zN%YHuGRd#!v3ha zzdf|x^8JBG&b)l*e7LhXkK%Pi;NgMGb zX`_gLJ83-+ILhV(-W=Mm6{9Wm59ARx!mdUIu0DG5W>ri}9&i@Y%S)Kau@0$K&Wfur zf1Z68U|1J^Y*?`z1JV2Nh0?|JTZ>ltZx4t2YR%V6T?s(D_h97K(t7b#KK4Kr2FcGA zhPgXG3=tk98r|J|9z%$Kj%9oOwO^56q=@eMxG(-uuM%x!_C~2uytW#jw{65{g*Z;| zXNJ6)2$&-sS8)r-tQ*Cpl|y+rxmq_G>%a4MvZv8e3}-vfe_+ zw)nd77K5y|P^Am7otkKYR%r$0wK5X6JuVUDEpKMxI;;q@x|p^j&K$Mo1N>74IK0)? zgi=<&ayuR_Zl}-q7O8xYRjJEqKZTFZ1oR$-t<8m-6#I~#c)flOt?Ur-Yn}J0s;e5j zlF%->xpV!@2;T+Hu0Q&RpZ3RL1NYspHQ-8b|HBhp<5f7A;cX?n(7{Cr9vQX?x#ABb%D_mdU0(4$Ib6*sfjV5Mqy4*b@KJPw+D?O7h_O9EEQ1)IgF(@L)Jn{B4L} zdK`7tWhEF%RxeJx8su53F0w9oTZ(?ii)s*gckb!j0g;Jh%;U1gu@rr@c-FmId+@av zZI8$5hbUk@)0O{Kqy=#y;f8BmV3FV;Fsc~P$UW5&M5l=XxRQb+VJ|Ro2wKeW6je3S z6SwFTN@w`T6&xN(`;S7hksNC2@Po79Eqq^xYnPwvH$mQ5;wauyUQ4%b<8ZAU)iQdy z;rS+S`~^_~XZj#!M9A{^N_F|+t$1D^F+4BsyP*|FoV{{%kB^43%h-jhMW`pNiJsWC zA*!fIM%&*~Hl0^-T(fnt90%qCo#~C#_Q6&;s&2z**3r9T?FbIpxrXc*DL@sh4UAo| zCA1A8?G~PJ-xG0+{Y|3)Yg}U=qN``WQ?HJys3h@?y~aPrS`)qHJobxeAm5npsrjFm zW8XM~aRElRANyjgMGxTvEfXrXv`X7<@ctk>X+blYZ@eX?2H6F z;Y?sFFXRIdt5p>VMgpjR$Ubq!Uje)C|48Ll$H9is&W%fS7@Pt)L>n*bLku{8{sDd`G<4%!MkQLsdhMwXVuc!HV<4gsu=<*aaAEPH@r zjSwGe=ave3`Qey@r3+F=P+(x3!&bl-d&OD{F|9vOufEQWe!KmA>nAOv*rRQr7ydd0 zbE9Y9@O_ZE z4Zi#ooPuHxfUSV9u;{EX-%;2bT>SQSaHAIfiJ|*$8uCY7Q)q9}BUqQ|o~m$BXqqy0w;- zMKu5I>3;3gbJq`}mFbro-pJ$+7yOEM*3#@Bjcd@KesZ<${{+#KEz2|Eb2JN{;q_x@ z3vr$%*rr|^`#cDhsu61<$@#8?kQ;Bn|&*>4~_KW;GW0SdzB88;Y zhd-DHUn16&mL6&%1r1Mdq}7@x3z~5u|2@_=IU`+1Z9@76<91mCW~naB>P+cpw0T|i=2w@XJg=+7bscZ8 z531~9bgD9%$+=jEu-d3*@vPy!yKO#COq`WR7aEt;js|(C)P| z=vY~H`GrE&k^C)Lmd_CKnxwq9FYgvQU{!;`C?Dn-*=`Xnn$`Df_FLQvQEKGDv>JKP zS3}=G(rPcm^`Pb{s?w!BU?d{FU=DGsoCn7GU>+@<@;Vb&p_V9S0Dgm3tS3A�XwV z2b#fLZL=QImBuEVrzczVSkw3{*0JUn`$weH)u_fhUtz19r)Nh^%i5zC9GkTl!g0f# z1+Zo8iamO5-Fla+maNeE0&viUSgq|S%4HTf6P`US_zY{DZ(&3PQ4O8nakYLIoPzA# zes7-t%7accJsaH*l^4@DV0zL;Y)^^k&xtu=BWrluD^C+VE)1iaTGu*#%moB#*Ahbq zM}OQ1BYU?G2rp~@5d51!is3&X?C15JA^Ob`WhrdOv2j3jK$L*O6)S<|EDHhsWD2aO zgIMk-Y<85j$-Rg62~YIDHlpaNDEg#B^deYp?b*(Sz{MlD+(Of{H~LGTXt||!8M~er z^5?`HQR{{%+mo*G-py%ZA+jXL%01f$&^i`HPdd={CFB<-0>RFuh7$WlN#P2j&j#EVgTFs7qPo)HRn}d3-XZvd{?cNnxH2%)(-m$xQ zy_5-{)#FxplP7Yz92P<+TfG2@Ahvh=fN)15#o*b}Iv_l@Zm!FYZHtO6AjEwKL8#NI;ogQs9Asy?7`e5`9-?5NeT5x~YoOEIS{iRa9yv6+Y z$oeGFdhdG4H+$%PA9}Zwf2UL4M%*5xVjJ{~1Tl}j6yy_%OVkSALmj{+1ond$N6>w?euJ7{!m?$P^c=^o}##vlA%osR40 zKntT>&s$)-(f0T!^mOB&w};mAPp)Y*Ho5X;PfV3=zB~L=RSyOs!#~qY5^(L)l|OHf z&(*7LU$)!lpC{bO85M6;@orrw^wu~&(is;$H8Ol(#YE%VL+izZ`zBv=CC%^1mn_ct zn(yLz^x#%dF`v@ob=8dPL0HckMD-xG=c(QvT3;Hr^^^QP?35urEUu_L35~f9H0b$!{J0Is9|aDtd4KkMn16W~t-y+4*P699}iEYb#ib zj(Ry+r15?^)LQ@UtgIPuHP=&5`}?o#ug{qJn6Etqo*R7}4|osOlZO3C>CwakY=NG9 z?T-}v0-WKf=S#Y(5()SAfsP2{5|{q!3|j+7uba|?U%Q6f8$BF45})VOvtbYD1s?jZ zr}sX6C=?T>y-``lqgnGvBXLaOr*$&M=!u^B`mY3@>!0!W>CPYL_?#Wr2Rth?-|`6( z)+k>`8uf9r4`x07la?|bu+F%3?Ke`Gw!>3`FG$0)2@|(_UUhuJXh~Afj*LT!aWMbF z7wtFwx`1EB5DtQoVPCxOj9U#Ze2-%ub)<&*hVr}g7e7ajZ^^TsSi8D@^J`>|8V_8I zCp&o_5V!i?6MRda&;dP*+C8qGWo%u2`sv+QT@rHL4HJysN%g%8#-Vf8+t6D1aIx>i z!^eh?u?9ri7a?EV6$OdB>nENqNoz~r^jVhA7AE23Z^Po%spEeCI`~OL%vSpETrC<9z>>>-#LD+eQ_QZR0f_kH^&x z)VryiaBZYD>C^I>Jxf4(q-WF76+#7GQDEyqRM4&jn%5usm#4>9jAiscZ{$~}$DjB5 zWeq(i#`nfan9n_uhCSLh#dzM_*Z1$x|Ih#P#^RZvRz=Y2_hMh?NnXsA)W&)8=*wsQ zrL6yO3(^S2ciCm(8NfJUY(;&2i4&5}+h&1g^cla2qY!~$1#0bG_K$E2vI68Ku&-}H zq#eua5%3)FiDmSqNRdV2FxtgAOw*|xTGIL@IUP*PR1Qg|Zb*P2xa;)qZ%c*Y+BgfA zu16DnwAhqV|8PUeNP}sytXjhu)Hg%h!!M@ovyIe#H12vkV&~QxjcC`;dNex*izLne z7OidR8%c}wwq;)2cLP@&VlgbjaIqYG8(!Nwl1_RPUQ+dpgf+fjYsBM|hcJi}{0KmR z6T9^GbaS7Uc9&Oo{6mC=AY*B{;SI?(e#bK|fgsT6x)u-0mGUb*6cvlyol0J1K`^7ScmwPB6 zad?3>8is2SZm=`MV1$hbpuRGqBHY5{9+r<_8@v|j(u=~+qWlOU*BitFAo=0rpFpFC! zC?M_&T2Bt2Y?sjSH-TxtQo;xE8r2>w6hBik{q`3ZSkv`%M_eb|qCn;|zUSC%W;ab9{XIz-O%(#$tH)-IkN9E8%31jM_2U9>7Gd{s@Ja574z*Mqe>rh^M$iS3- z3d@gyj42pmcAfuCXbPR z39%dco*W6*#DTOha2n6_pCnASmOMerla3`VT!xhg!;~G6d zblqCowNaFx-L0c2-}Opp&S?;*TUyB;VBRee=_GwQBV9g%8z?wZ2Cdk?U}=oEB!{*L zhBA`%oD28R_Ef&uH*`G+J=8?K+e7O`J^6-0dDB4NWlxR1*5RN1aZKFMdY(~lzX%bG ztdWeX5f}jjy+;0oGLhy{T^aAPZFp3#H9F*qWRbC~$KMYdSIj1CAnpnT$h*aw@@_#u zzUw`KlH02_Mw^R`clpeJ|TGbJa^hqq;Ic1Z*{l@jXb5#L;_aWQ>e{QV8__cz7gzb5|vb@BIah`)bR z{QXiod@l{{AP#-~Xie``hC0e@guQPm90*%7Rp@+d8ge z`*}9v*jtclXSqAQTwr*QF2q*=sjW;&ZFh8AacgS3&}}7jP}^PIR?-u-$*+*od}R?v zZRm^MSSoHUvBJunT7@SYKfygqgs|f(T`J|#MbQ>r6!p+W(Fa`=1<*w)4}E3}JAy_C zFYgu@$h(CZQjAeWGbq!uS!?@S$_!H3zi6hOzo`L7y0#_?g4yhCnxYqL(v-0N)4eel4V0z0d_Jdu~KJQb*pbWs#%TMG143lIPDB4fJp zCZkp(uSV00uBB+o2g@XMQC4#;Y`@};!~A{5ZAEw}is3N|nq?oq1tEodDGxAyq}sYD z*W1DOIpWUP4AP2Z(y~m{H~R|DS^&oyf>nf}EorvJ13W!2BVm6m(g?mqbtvy@{1j;f zjnQ+HMm)&v_f&Jys2K;choWhWN={a)4Z3J^qjng?*@~R0q~v5r-PYnw_b6=CSS)_X zV;9THIkcpuJWQiC=I_a}Lc1-j72P*ljlGqebk-AUaTw~P0Q}jqy8)8nqvtf8W zykFM0<$Q)%p1ua3XesuzeF{b!qnEmlx|s`)sRXJ#ck2rERL)Ut>d8@YI#WfK*(&wg z?oC(!*-uN#q|3h}E?JV&lN$dnH6l@LIgy!viL=8iSHJX?*I)a^tJl8#r3JLqFx_o6 zB(KZ;nGtX7o!ShN?d(Vk+IM<-T_raCaTFzpd$vX^e!=tE zD^DykR?!M~eCTR`b#^CuaiusQ4+dkp!K~_8wR!y4+I(pdKYorDo)bL zzu7}#s&zf|ShZIaJj(I-Zz~m#)UyUC@m$!vJ%Z6tyJyKjay)CpHrKL8si@i#smMnc zg`O@7@adu;mM)6h(M7QyT@)45Md8=Bl+~Bu)@Y{mt}R)(soM$*bz9-JZYx5iwuW}k zj69ag28MUsLk9PX>0J? zUI>etj-}8tp)2KLqRbLdg1|y1w3IIdC$=X|){kSZLb zA&0O;qt$Q@rR*B1=%6vH*!*g=YQGncu*9@*R+2UAG#n|Q)mUGL&c>XgG$yNGOuzBf zCGgH?VB%V*nB0owSWaYSm=Ty0ZB59UW#*$)9ao2Eb_f}ftsF-H@H?x#L zub5fK`v%XlOk@p|rJNYW%wO=FY3wK}lQa@9&(zeESq!Yvl*+lGyxPi{f4-|UUR||p zq*2$l3R>>MFD(fDw0yM8)@m)8rPW$A-)MDh-JlJ4?3o91tTk<8NVZLjL+!J079%-~ z1tht|4wQ5^+TyDX$&EB+Ir22odaoYH7gYJxgM(hUA`JuN;Z|I=h>EIVEnTk$S00BZ zVjHxmSXi}rV_tE!aP?FA$6U*Y1*m1ZXtq$~HRGcNY{@(=y__OSK)>3}^LwHXd<6!e zl&iVm*pxJw7Kap-%rwK| z{JP;9dhxQUCorj=1s4a0({AEkSgliIr;&U0tXL=0P zxbgWpK&r)$M!h%yXG(kokCVCZ2wapH4%VMN^N&=NS&sOV72pulB!cRxRe-0doEEcg z^_4ygE?WStn5%FZoEu*S2m}0zP3txnsP9@H*&mKE4#yWgr+*aBv@rUJt>U)i1$EJz zz{N)_at>W+UrhfD)R>C08lO4>2OngF{9$b1k#TEJOa^{hl#V6mFnk4nyhW zJP?J(TCm*4v+ANZD3Gz9w2wiaFh;Nk2CX=6W39rz!}BRN4$tR|)QSNhjhez$msG zY{etvR?3RW=RB{I65u?p*QA)XM>CMaP&&y!#<%7P*OstK8Pz^PiuFFK{aFVAMxk%x zT>v~XZXKS#V03ss=Ya02YsZ{#Eh3`0$*MR``mvuK{xvv!@N;)sb6gnb>iLJN#YFd_lDia@-{zdic`7~v3yfp_b@3XFH{zmTU9 z39fC=(H3hJThBiQe4aArCmF@-VC^bXas<6e&w_VCf>!PC=*dgCv!|`UTJGCW?e*vd(<*-o<23LJV-4)Z zFy3^Hr1{6PTHLLd273mU=0vq0Wk2cL_6o=@UQ2DnjGotQC}x0pf>v!UtmCLvYXb0u zJz(-PVcMfYBSRj+yyF#^S*r~w>XbBIfoUyvI(6g$_#u~&S8Rj(de;~4KW?w##8a&P-E z9O4dVK@)v&hS3pa!>l9sQe?W0PR0T-lZ?ul7Cc-b$r=!9Y~&U$$_a<<((1GL2$h{)^Tr06(i(9Jh;l0Cqhxa-@C#xt}&2RC*Eqw#;)fLU*tHZq> zEdmh_94-eB!{D5PTXD8BD-pcAbef$gygt=DVOonFWGlFT)U}rF(J5ZnVCi=A=HZdO zE70MQxdsF=FP)6Yd<4;tcXWqGQZUQAOE%649aCl&R~Vw@j!b%M?N|6( zV=o&yGJD1;a^!e8zuvz^uMx}m1RvV%iTPFBle56QQ}qPVOVb9A-$U7q&+2uK_GehB zqH#dv%|hR!*ZP zFtJG4nc9F(kJuB;f`4}muQ~BcTbh52ki%&=MR(=RI!2#^Z4TE8)^@O>P#Eob!KHe> zSw<7Q{}OouK(Mx3@C+cXJP(%~?_);N2|a0P&H;s8UJhRdHF$=!Jv$a>s52}Zd?K_< z-}rafRD8oRLEC0TRSG!u&KT78jYU-y3!_Mb`r7D+X>qHFXjN7KJp&y^(urBmFec!Y zruJ1BKeVp~72MES%ac3wyCoKaSbm?Lj=sFQQ{Eq3ZXo|qzcUzA=NeHE2SL@OMyfnZ zdL5iaRGT($g)yy9Xp|?V}A|M2K5Wj#?Ruz9f%*)4OJ?N1{pgNAGpRGGdRyOchJJ!_!+Z2*7QBCDx%H&JoIep( zG#S0ik8{z3Mbn($ef&kp^{vUjP=5Kd#}7WCsQdVVFBSie`Qfd2KSWiZ=8U2T!3sm* zix2xCSbh7U16#*K@bkz*n>a$2hxyo4+z>;CLs*CDadl5>1N%xEyREbjrpK48iSo13^Bt-h%N@>{59pd#+~w{w*LOiw!2Y^lE6D@63gac} z3r7atyljSL&@VT@Y!r7gIeSx2Re@szltRa6?IorS&SGel2Zc5ea);Iwv>W0Y)QKKf z>*U}Fzv=^P9H^k00q7VsFsubz4`Y*zq4i{H@fd=voU1itQq`Mn`Fn@<{g`4 z;UmO&qt$r5AE#5DETW$7iEHSSELD8}t7N&cO|pAx!HH`wy^RgCie5h91(UV~ZEFjg zf=zC&ApKa#8dVF>U=zt(l=G&?{YOReeEp=*Cp{o;pQkMzubp)aH{Cb3N=vV;&svrR z{1XaLtB>O2EY|V#K`1P+tAsv>@D?oKwk*-M?1M)Jm!LadNIr90nIMbLsgx`sMv;5z z5Zp5>4DBF2@*9WQ!t!qpW&Zrpdy0@7quZS@WfEA2jc}R_TeCK+7!>r3^nh^#T7eyz zN2M8E1dOOTtF=+0ca><7Wd&k@r#=C;(pc(|C7{)D@r5N~ag>6;q!1wZ@NwZ;llG!O zHsycVS3&tGW4HX9HRR(jisOC;sL%*z*-9(?qX%JuE}?AHSI(+&f_uURzy-#QUtY5g zVWozp)q2zT417f4b5l>0qwrFC)W(d)Ad{FD*;JQo3QTaF7 z0Z0=KS#x=A8~PNeRVW=9%k$r91>Ac zgwlAA5G}kaK);TBIzo)j!mYqxmE43L8?+Tz`dl-BMkbC(Ny9t!ZHo zj53XsQP~bZ_1v`wqjZjs$u!miS|}TM;{NXRGK3cf9~hXO@KB~g2ga{5pRC}pZh~AP zT7U~MYS+}Tperzop;ZaIvnQBk(}5DiNSAAMXcQxaa4WPAoS#mWFQ(uA!a~ib%y-0f zjAQJ3nh&40#fRi8=A%P*1C8Vgjjed?YXQP^dcoS)DDeHgg@S>`6t_ZqRj3B>PFosh z$o*oY=7R7hV-`kK2l^=biE(kx2xL{yECnM$lur*H`9HeNF&MQ|ETrl|$kcTOP*GVx z&S9-{+BP7CMpfk%f^TfWV4NNf0ByA}L9}@BalATY?X%b^D+`SV+b=o~_#WQM1D8Ej ziK%~foC(xc?5BPd*sqo2$K5x+h^lJLm-d;U4p0?2pv^W#_})`n0;SmRv2KD4;UkUh zjr|u(kNb{!g?&$==gnRhaJ`R(>y0SjpSVs8_DcMA@VwDfma4u)OwoK1oTnzc1^3V z07upO1<@9JTdS3putvKPtMT_6p1FGci%Knaqc$sPAqKJ^5d#sXGh1Qxvq_W6Vp=-0 zioQ9IgBhIU$XVrL`mz3rB50G@un<5SwhMPtsYbt zdZfJ$zaWPo(r!Hb!qZ~s-q0FA1(&*T-k>~yiRYrn6(El$=%|Ed+OP!___R|4P>{2j zS)km(!UI1simd_X)jWc&gG!!&R)-B=!?}#lp@Nri5OoP_e5pIwvq>oTtz>@e~$(+tuBPHMuR+X%)>AL`^6lCA3XBg8DHb@ z>(Cf2Fov<9(OG%vYFtxKKwB+L5H0q^%a#n3Q!NpC&gxMg3X3%LfHuu|%wCFDvup?~Z~Yu5tE8|))& zh_=|<>KfY9=+A%Wh|g&r*h3xt^~`d$5Ce`^&rJT=MO!pc^)#yltQkBGlFar5w6vl? zt$Gcs@vFA>jfT{lf~HN48ALw3mx|-D(gHnbCw)&}AxdZ?oQt%zD-M9(tDb;1c%#~n zUfYgBf@xuJ!%x28WD)fBze33+*ZoKDK)6TFfXslQidzo_8Ot<1!mq+>r^S41k$;QD zaiM{E#zDY`f4ro|62W;fO0|3I@Mzi~G7PPXm@`mWuQJDS=1k=p3~>AZ%%(4a`lTz zx;k3UFc_=?vmLmtM>IeBBsClkGHdX|N9vL1XtemDoEvel8i=@3`vnlBYBv&yIhu== zoRTmKY~F=ZbX@Ci9n|{s9WX|F53-_pgzm$ShDutTE_!BF)uOR~q)}j1s?bquUrdma zN3x+=_u>g6B8(qeI&o#J;Y;3^d?2?SbC&J6+P|VXPGKdizpVE@UBb1BS*1esQE>=# zB5HJwr#iagaihGR<>qlCX#j_W8`KJUyk&jU(Vf4u5FPDB{n=7u532DRBRHsCwwyBD zmm2`JRGDOQ);W%8+9&tgk-}c4v#R3A#P!|$kzy0lsQpDwsbBwzDAs<@!+1*au4oBu z+=T~i3xDsF^G((Q$~~u|yFXq18Tnc<+;RihS!ceW7W5Irk?;Y2pdr}p)mDHAGahnG zTBIrH(OuF-)p|x*${(1gCxItE2vDM?X(Z{#Eu}- zM6+Vcg4Q5*!yjuQ{bp@5zU&p66?)pir%oZt@wzOqfyyvCa)i-N=xI|=pi_gr2r+`A zu?CPIJkWaFWG$iNPJ|3Qv+l^BgJ|s65n}|XtWEGphJRm+ zykxrn=)a2y{(eLNMo2+hxJr*YwIIfIeWn;3$}H75s~wPfB3is@?=KNpEB=$5%Stw@ zZMgw>!O+wC=t<^PPryU)JSMW(DIc%E8)~>!JFUM(#F&IZCkR-2*<-JOO{&K$jz!z^ z2t`?IGV<*e;;3U=>dHl$So|(4-5!QfzqR}G}_(7qeXPlbW_ou!&{c))N>3f7mJyf8d z(lQQ?odRZTGty_Fd*M1VYRwQP<>O;T!;=q(+KiC)NP&rG)dBA_NNdyQP^*zu)gx7# z@9=)cthx0e%9g=c(qT@eLBnki>L5o(*O2xMxz`$l+#3yIT8%(xHT-C>nN>ZwSG66A zK&=JnrDjfF3pUN^IiN;X&rwGh#Lv1TvwBP%IklzH`ZI{DqLOD%?-{p8o4zy;IdWd{ z5&8XBVNirZlJPtkjtNLJ316Oyxb;x=atVGPd@dukU%BRq`ZFp^!Jn?M9HOSsKCQDx zAhGg83u%ObU_ zf>9D_+y*;wFamV#ZP^E4q~849Vb-eRzPbX|!FZ)s$wN;a3irD4&Zp5n9!Xa!$D{>X zBMw1p@I#t@UykYg+8`Jk&m6RBlt62O(}?8L9*?`14GHev^xQh0Vo0A5W_pG*+<52u{#g--o<$ z?&~DVHd$XW3{_UpRtdbz_FT=aJ`@Nx)zvHkEiALNY;>aO^BbY&#SR1>zHJfP&W~>! z`v%J}d{zvtfa{K6UOaMCi~9EF$0AUx{lPooUHEA*T-xJBa}ZDN@ZmRL`l&2OH^M#$ zc)PjV#(4!Cb&w0jRiSlL&(%1@?yoT$(xO?<)m8`djI|L2i~B*afY~rQo`J_=(?b-b z@DX3QyKuNN;pSBswOxk`BD%kQ$s4l#`B@~9-@AOi7WLQFxH_=V&Of~jDs}Y9o=+zD zNP(HZ292bd94e33U!M zv<7o}QyNRR7wuNu<20vjfcyuK)6)~sQtS~Ng^|b`Y4;W9ZjZ5RY_EUwEn2hjyNN}! zhMJ@~H1=}5IKN^e?eP3f|M`cp!!xzMdEhIIGl9SE-QC}G{?gfkuDm!;H>4zq+h9`E2z*U3-ygAc^<|p+(qeni0q7d5+2fc=VF zVSS08F#uk3G5tQujqn#)WnAV5{Jk8zWsYa2$Ctk^b~*WF1CE#G9?75Xc|7os;qkA_ z`a7aX0xlb;M}O1bk_rjX=zFv!#H@>)d(4lfro(ywUgcv zhen*d#tz;y9{FOLM&3*jcj#g0f#X5m5gT|Ico=w?s^>+AUktw(elh%lF~I-oea*2C z!!^W+lOs;De~fza(@%#UMx0~}@V}8Sh91zDM@HTpd6PY4qG`?tqVt z^BFrnztZ1P@Mq?c_M-JUlr~PXWXW0M(GwVw)|V{Ed}P;k<1j~SX{B6f{yf{Q_E27X=IEi_z|U$gBYsxX=17`-JzuAIUq^iA zKhs9CtfA}SwTCv#k$K41Hz?Op{P0-Vs>T7;2h;k|C$(n1*5mqFt<}@B2hoB^%B>yq zjOSBG&8)NWe9F*+@Z5oi;TKCbAMqjW0u4P3J(wr-N1PmSa>U8`#{>0F&!{IyJvr)0 zsu*a!JoGU1uvAV152<1pdKh|G&elhK81aGJ;fC?RJO9%o|A(h}y|1%3-1`oGi^%`Y z3w?6(#!@e!QxxW{<3tlbZ?L7+#BumV%H7V(*Pg>mO>@lA-`w+gKbNO2=;r|E?@6(* z@V~yNE~1kz#+0uEZiT-9M%qkVHTgQZ?UTJd4ly!(->p&P$B4+Edt%L6S}7Nre=Qx$ ztG&(sI-95ABWlX{?ZFy9t8pUhczQjwUynU{Xm1feUD-^4Bfj0PQJ49NL>dS~^{Qdgs-v zzxYMBh)Ar<9}+68qt9iY0qd+CKTBcVolEUWKS&+cp0GXyPwhl8ki7*~ri5S*d#qhu zv0zK=MeB3OQ9VcQgavVhzgw?YUpoE;h*S9r>kn9tEu&XazML$ZniY>*(Mqjg8?K!N z<o=`O%o#BUor(Ju@~Cq-?ldy|h&f|z zHK(Ky8>7x4J&paGwQ*zy75yi~6|FHwoipm3T-hizjF>ZG&UGMJ6GukO;oS(Jg|VL# z=c5sGM$8#8XPliRF8~p9>?yFDtjWuxz904dsPC_n$|{fXXh+N$F~`FOpN{xD;N$Eh zN1$yZ?H_tm zH&gQX@a?_{K6j4ah{RtR-qNafZGvaSRR#!X_0#Y7(C(Ufs{S~%T=5Cptd=vX6txa~ zL=hhFUI6~Os5spTIKs#=azlgyez7)vWG9b)0Id&eFXA8gJK&gRzPR(|SKZ!G`&Rp5 zzH#e58sP{PjVwH-ix$7H)A4-)gI632v@hNs+W7@F(!}G-Y>)KH8oxP}@6ao2lyCTL zJ9(G=jqd`V39=N75V-HbzRJD^Jwimo5XC*T25mT+YqZ@SS`TgJ-Oh<$jZE)$W(+dg z&@k6?gJ@Q}gub4c90E$JjSd(VDXSU2==;g5||@ zzUx`?Oq>O(j23ww`wT?f8bvHHa7wljb$jt^ zO1YkmnI766Nqb5}SSA_SZVzo;7o-qqzRfXzP$ZR_8NXb5qR)(QOo3@LY|S&Vr}QAC zhZaU3WAz?1-5y#GA$D=XKP^}mSr&}EsTk~u@OM=<@Hg?;1A1tC zc<7<+;KBILJtZmJD5C8Y>G_zphkLlOV)(s1{+r^k)Tl4pT3=7wUNQo#*!J4w>phrQ zOM7>Ex$G#-7hX(|oA1G4fWc7@=57zIha<*KMj~&YUd%Z|-enx|UC$C631KC_Q)?dr z0QVbn%fTZDYZ$0g%yTeuPrcp~&Ch|hN45@H6GQH+eCS7S_KhCe4vz3PF^KH!&%p*Y z=$&#G!h8wfEPaneJ+x5gfd8G>NWk;>GmLkxcu)8Kt8m-r&@y@V2~wob*&`8y+@GsQ^vJN5_V{(;92Xvy2$ZiqeCPJ;4f*<1^f)dvcPBdn z2fG5tso`!U@D*qzRcFI<7=#h~@Ni{<3@iw#$QB%R^~BsCF86-p3Q6_WgpnI>RM?aw zN5vaIhwG%{sh<#4UZ`PwM!E-mb;)Klda7}yZPaFh;qOK)uD8Ao2XM=v`c)Yz*Cnb7 zH!Y(5O@Fj?g4(uXEQ)0apJyixApr4vaJ1NKT#Thnu>;!m;E@9)ZirYm2OvA{mtoIu z)`Ky-!4}Yq0$+fAgG_q3tR3hH_{XsyXEi8$FmF`nAY?|hfXHpcg}4gr(NQA>(qX;f zOpW`(#WsEm1iWz*t|fv9x=-|Ft~!vuVI_hh?6V3%h;lc}VYCI0Yhh1&4pk7wdm>uo zv(KV=$jYEEmVUw`<5px%h-rwm^@zdT*$q1x$)Xq{XpI#iO0ljtA?@MeHpcUUZ601N zz$_J@2V($^9Lx(5A3Q4?Ea>lr$Qaa>z6NryjH+xigm zK$TDS3XP+dM}bYTU2rSbJhmEc#aP0v=ZSEL!@x#ZSI`P4K=>YBgT_Rjpck|xkTV2<3h(!%k7%kdJ>1??kCEn>*H2zg{W1=Wt-hl+u@N2d&z!CKS}go9a*pDciw*bC;ZkM{k!uenCBqY4vwq5 z#yg3YHpOI%+Jlj~+E%P5jADBd;qeq?vcQrM1$a*;*y$e;hhrbx8ONi@TRgibPZROg zU~j{?W+aRe*cza31CIwj_7caZDBB@>j5sp2ek5ndIC82egHeE5an#4L0=J%_H;q;M z3wWu+KMBnZ%J+)`@I}HSQEqB8P_dTLj;Z8mpL4?^ak^tsV$+7gFFT23H%?U9@nY3 z)vr(3+i)wcv~kSBn#A*BP2zd6Hn5)I^NFx=SpjwCnu3;sRz zIJOIJ#dyGW!8XOM7-_imJn;`vx~YP%c;|&=h1U3cxK8+Uc63YU%Bm6`5ruW>f58e)wE!Z za4~(um4<(i?bpPw4LmnXSKXsi^mNbDS}hr@f6Qr?rI*0c}qn}R9p&rM`@|mlljiHU%NgF3Z z0~<%f29A>>UWv>WpbqP5KRusn-u)yRBTLi`ZQO2c4Ex@0`{MYFTW=pW&Ql_vtDE=* zwV<#V%%#QpF&6^6o0ZQ%E+75$PKj-=|LpOXyD7no z>kF?ND^ERgXYl#l!ZB0AU-=-MWh2yEsj3YivhMj%jyj=ViXb;%em4Gc;wvPzKN7!u zA|#>TfzVfI)E5=4zIs8m;YSPg_VEiY>MXA>yOgzN(Wr1!+F;~Gcg_?k|3q8G4aJH2 zzq(trO*Rao@N0`sXUG3Wab_Ov8F9_{#lMhUx2HL&-K;@*&+CUZ9%(Vpl-$yrgY^Ode6YrEj{EhJ`YX~Wi(84F zEWNzvSsP2~`$s}ao@pRzdG{E22iEm5y?4D`eEhS8efvvn<=N!D!|--Y9e5nDTv%#9 z`bi0&9;q=Bc3a)0X|tN?N+j6cHV+Kp3bJ=1!7h1^xFY5~CW3{j-|gj6MXg_c?t@`p zI@Vy}lg;QymAP(uR5lBEL2*IXo(gzu-T`3$(82u`VOhH*GWxy+QK>c zIJRz~`rbe_ZGN&-Xp-g0r6Fy;GtZ+lyQM$c+0+35V2qXJ*)1MvI$>+Zd$- z;dQ*i8XJB+qS=UM9L4Op?}%n8nr8o?E3isTQAW~^byiO;opkNh6G^*X>xkhQcTy9c zwuWCPtYw|i)$r@)x>sswM6(gi=C2FxbPg*cSH_*ZH=-G9AZupC@Fy>ZbDkNG*y$*0 zA6vUMkJwH4%Q^b&$v>xJKldUZTYEHQP$Mbk3|9n}U;<4Ll=HWpYcqVPjut5&; zWnuOY-2r|=`vS`z&zNZ>gj8HV>ZkPZGlLzpI^N>%Iub5&b|q;r?WDdHY8(PT(5t`C zh-o!PP=nRO$x;>@RZ$zV;j<{(5C@>|MUUL@gtPh`1t|^G5sn(cmx<5M;ysV#L)$zN zmXlV7DQAn7dtyKj?Nb$pKooc)kcRk&@#PG&!qXKaPH#CFXHCR_xj)E87>AIHE+2#= zfhTdfg0jDNBqO+O1D4wo&yVJjSP!~R8+K(&Cj@wQ-Tmd?F+s9H;5{0-aAizOdFjEJ zR&Npb>v6e{iS{~ppUA@!Zo~U0Ju>ys-bVS4EfYtGQ|grGN61t!|C-#b_$D9Io*}Mo zVL$cqtdS429Z5@I2K{0!appw~viz3Tm8j9N?M;ahqcwykRVkT%x=o{Sy`GNKPxGQA z(v_gW!FoQ|k9iZkU~Gv9fGc^7!=CtP^yXoe| z1~hi<6&SV0s(aD)>|X6fyNhfO=vN;Y8}I`mCgwuFA}+BlQL9D;o~MUa$9Ft#q2;&S zXe-9gS1w7+BS~TsJ3|+)1;@Xa{|nJ(275@qjvU$ zWmpTSO?{xM>gQ?tV*2`0zu3RMKFo+3pc197k=rop~d#>89*`vso!v{g4Mc9B+(rN^F;AZ^z# zQEVFt$&N?Ht$LlJvkv^iojLi&v>leztE%b>=mD=taBG(|_#EHLD*fBG0cj|fqgH5D zoY}D_ncarN5dqI~Odf&g3HXJYz*fht1`}AGfr+Vl(~5Jjs!sxaYwsAC;K;$%rjPL5 zkArx6Z9=$gAy!eiLv0|~(Z;0g*>eR(#mBq^T+~;~iD_YI2*Ny00vlQ@OCf2s#-X$T ztf?fImh^$mxPt+}EOoYxgk;Af@m}=w$bSNa6DAHtTf*4+^&R@qZ;>T^_`mMG zJ3ycO3AVVR4Yt>L z^IqcuJ+K>H;In9KEu8AX%(3&s!V;st+7^+P)(alIV79b}j{|T@+ zfNgy5&9CA);0V}OJpSDs$H%jWtw6ifcS|ck_vx*|vgwU5d*xw{d-g;_wUGighVD;S z{JF2miTrC!`S z$*O7ejGp!7cN)<1_Q~qrD2y4_w%1-`CaNhi8re@EEzRrA%E-P0kQ}u$*Ld}bTmALr z?#qgp^^-FvEF5b2$)Z)!5#+DRD~?2~pHGMH$~I(cva}m!>gN~$10+(o(b@| zOALRNr;mugwfel6zOiVY|MoP}qxXJVG;2>*$8k{Unz9|5wTBj?bua$?bwq_hT=!yc zuU7K{+res4VGz6#!1?c@qw?FEp7aNfOj5PawO`gmTDJu&YaQW2&8^2K+%utwlDTB5 zZl1QRjWQoeTbDtVwiDl2@4)J{Pj&2E8Qa6dI%6@t-h%cEtgF2dzi+;UHrtu;26uI+ zRnQu_m3EE(@Tl;qc5~Q?N5ZX8gVkyr_;dA84Wji|8LV%(lWDXFv)1|ZR7oSS1m2%a zT9UL-XZrgNcm;SkM+W;HmN|URu3aDX{7FTJ7OcV*=7@${?P4m5Oo|Jq+qNj!>(e`w80&TFez!n=_|m!F}eEo zO|WC8WFckCIem5ZBzSEiW$G@i_pEVxW`Qssnl<>277-FZ=ZwR{S6yn~6YS_7?jvix zkQ0OUUxjCSAyR@x8BXg!XD!X8- z6x^WG&$?WM{2Lx1Z6GU-Ft~Ngyyw}s_?WO8d5^dfs1J&MjDp9R zWsDINI#id+V9_3YhF*c2K4=D%PeBZ{l6r;7p|aOMYNf|i+5|-*!(KTw4ynd2$112b z@0uUm2J~vUD*;|=y8u7meSW(7dw>4_{W<&Fr)oAcUMX;LPfl$b6-w`>t)5vv!kp4% zmQK!4(68@`E8%JKZd(H-#AI4t8nkBCvMIY5*;-@jk5%ijnz|I&%be93Zp+lXE4;90 zyyv+<`x!spPG$E4s~6llm;Dd&Y|ruX;(DBXPxsGv=@F+@^JV(>D068^Ggee&t#Wss zOWkRYR(Pt$b2URtAd-WYSc-?WchihpmJ3f1eDj`H>%5$dJBCf;(8RD+->GHUeq|tNLF|D3U#YB;d#Hcz489r3p z(Ye!5maHqse%Oj_BI`=p@@S8^Yi4QdMP&{xPb02bizlCC#N~ODFFX`?81?j`ji6u* z1vnz!Lz;Qi);KZN*65;CN?EoP)mx+MEb)BHat7^B0s>3bDKxMFfo;9?Au!oM@>71e zHQ&{F!P=|FEFqL~ZaZiC5tw_){KPn?SJ)PuGZ%cF#+JOzcd2TxXKao6oEej^>oMoM z6Z@T&m-v{a(|v%Kh{95#>q8eM9wXb7cJ!c)MrB)JsL(8Q7%p+^7 z8Nb?|X?nJEP4n))J zN0my!GRP|P)i4_cOiEqlq@~2O(^S?i5!aG3M{2ELlwG{J)wATiRx1W4w3LX8jgd_z z^cBG|M&lgX#>fs`+*HIq53@gEtD;uO1c(j_19VZK@3$}*URp3Vck)=9gQg0zTv_n3 zuMWOkS@7YnzMFc>W6;vu+?`&Sd&|4qdNW65Oiw;mMR`1cRPhrOp{STb1KBNG>BY7U zjkCd_4749ER%Sufm7#pmPy+r;PxR{}zPqr?syIhitLN;Yg};uXLL%u0aG=Kl9$867 zF!aW)ebl4mQHyW0HT{rHqe5lks0%VzEgE(Rl#i}{`kI8C1_N;@okszsi@)_{jNxa} z4q>l6GnsV~FukE%oxe;!aXMi$sHKGPHu^8=fuUA*FYFu?qpwmv$o87=ko`)T-FL^+ zEc2mvD`A*4^7POijT6+Z~tGLbD?38+X*$p+d@A@SNBL{FB#1DU5mIgV0ngYIa4WPCmE*|1dTHSo>#UoOx+e5&Svf%d2?@Ke&H!1dY6ElX51RzPnS;G*;3)mr)4&n`Xc)#EXg$;DjAQ7A z=)5V<4X$LwRGx?R+LcpObOrku9D5=1#i?T>rU%I1&DJ~ee4c)BDoyS-FUGp4JEgbi zolAR_BedvYYMEkNK|@vF`m5F)%~4m)Tx!V7!Lz(|Pu~;2`|83J-I}g%HD(tcn8#qB z)^Vj+QP8w|iW*qb)|{@LrP;GRx2XEX+-8;7)OMR|qlL0gkfUo&wMTEt(8j2lv)xnA z*<+m&tAz|g`c{lCGT~M^qT;ZUNmE)>hDRjotc3>81GLy{8chTb$x1m&*LUTWN{mLZ z@)U{eQTWq$^;MQZ+%=0D^&NgQvueX9p{8d6L_>Rqw&-#z?OI5+=F#D{*es@nvId)W zQ1+Aby*s`BnhSl{Xbzu@m9dtz_MsikxY$xEU<4Zhr=~Uf>)av|9$u9WISRC}d}^ud zgdJHFOS4lePG-Acl0P?gadqca*Bg`Swg@ai14Gd+0uukh8n7g}Ezk|lHc2+DL#d?* zoaL;@3dQC%)3=c=66-8&mzCqa1 zX&3X6!xXO8&Z8F&aS7mS|)j5)6uV-AJ7HNd{H}P5< zO1@!l49}{bJvADHJvY!syKK@jKCRqYEU-(9@2*lm+%AeR53ae{qD3 zMv}Ak$cAb0tbS{sr6B6WQyC2{oybe1wjuXjHjYN>nROpp-{ROGqc{o24OaDf)#XPI zj>qcBa1+l|+wl&IgE^D`uZaLqvPu>(F4$LF@3-(-fD{M;3x-{2enZ<6G%+on)ogch(ig>Vs$=rLJwg%=^A>w{ShZt%jpgQu>A(Q)+7HtIn} zlt_@)G{)da8?A%5(CEds>!Iz@Vq`nSzt-ZGk+gKs9tQC~t@LBYmhw-K9*7pV5(l1E zq6aVy^Zr0}z{0d0!mUa@TJ0q&2IIvYMMIfG@GQPD zYJPhn&GGb$;{$HhHt*pd(`pT?mlC^d17`^rcV0AM%VGU%{(Fk&9(`llEv*r1k!CjZ z4dRbR8@50n?G|}@Vu7SRCjWbli}kYCtn0?*XH@S5-(P?Pmxus8?WF86?GDOmXQ z1S~j@(Hf@h(LWwZJ3pkwI(?e(Gi1%@Yz%bP=jWe5b(92o+ z>xf)jc5Yjg`#R+B1M}}`=wG60;1gG72E9FX+DT~766v}+^ljFOg+SJ59=y~7t$1ES z4Crg{w2eo(Y>P%(O}lB6=9scej`7xt##cm(t@Gry!flNJt3BIhnij9|AR2MRJxMFv zr-zO9a7AMgYe{R=UST9k?>I@OF_G*zJQ!`#>O#snw3+KAjE$XIgIJ=Ge;hnK6|cps z(-s{5x{3?m1i^vkF0LJ);Y7s)hP4b7Q3-H-+CZaSt^<>27XqS@q#lk&i=P^KxNOu8EpjYuY=s%G z99T>*g4NqnSTn<;kAbhD#i7Oe1^rR;d8p{q%=*gzc(HDHv}d~>&GgWYO6M3FA6h(L zEuwuFxNo0|Iu?xo#lr36JsibhAh? zsn6GCU0PsTT+ry1GE7RuAx5AK`EVpECnPQA5YHO5%6WQlk7+T-S~_eU%>VI5(w+*f zW02_6O0Q0FQED4X22x4Fw}-UxF79P%+B`nF2T`|5j|2+%R9(`llEv+yL2N``s z-yr^Iv|$VM(IQJn^2qFkBTgSra@=Fe+A}WJOV3EhrycK7lXZkzR~KNEc<>{VUAtmE zkjJzzSocWRLyJQW-XS*g^zeTY+97LxfN9t@YhqxSqG)_xGW?Y@&9)^A)ZvIt*&|OB zo1k^}iV{za)yKQkjTn0(r0Zqa(QqGN8P0?IlJ~7&h{1V`A0KU5xoIn9FX`|Gh(-aV z4XmR#d+-`(Ct6z1iIw2=th_Rxe)RD%?+(jh{D(x~MshU{Jje%o`qe=GMp_?351~J) ztzf)T4h~Q;va$DVYn5j7wZ`?FMx>99ZM0|L6|`|IwK9C-A7@rC+Ui?YUa}VLX&g&WkP8#FduXvHu>L#r)X5>x8eUJ~Jw5yw zmfnHVR|Y?kUI70A56~a*p5BhF(4)bkjD6tHzFZaEd4%gjjX+3?qqo85hLHk%;;6f& z^-w)y8{McCu=fT?+Mqk*-O&05DH?(H3dDiHTXBSet*6o=o)^bGqg5>57E8mCi3?yc z(8{j|_&r~zwVu~%Uo0p!P2J*+aY?iLGjP?Yafx%jrp5UPdJ5i?Iaw=~2)E+R$qlvO z^c=v?CllO*3^ERu2x1`^c}w3DaTP`(-^UJr88Ug`UL$XbXt*zK#jz6i#jQF59f!8s z!7dB*s0kZREM`p^0o}udrZVxTg3pQO)NyCvrO&3RPoWrmSXs!Bn z6s|1092#r!!smfC0i^*WBmNI7<8~y=ZS*LLb|;gqSw6FiJWaD|nv0XbS9xi%lF;6`s?M0h8 z%;VpqI`i_;x9n|#t*E*)F@w3R4a8lCRtH=^1k4}5k;6T+JYErf7YD3Hv<$7cdwSfd zte7ODWdw286u;_u#ICl6RZRaTS8He-ixtJQ_R5-9N~h!zJNtr0SVi15d^M3oG_lm0 z19fHQXiK1R*{8z>j?A1zt_CgXU1&sTxIt^i)z2Jh8GPSjpVhQQC-Iy}w{T8;erq@? zHn$wv$Uq%4Jes6lqeips%B^MRNZO}NC+@o3Ynsf9xGS_G?wav>@B?iSZfpo13@+ig zU9@`d3(8h)_e%bHdMZy55z5;A;dI5f_}@6jx>(i2U6+@*_ZcN(i5SL)nRE zAuX1mhqlt2oCRu;dV0PwZ}J9DTxfZG&DFWsr(L6ED3hqc8dyD^);Cy4RTm;oH24J; zN?P^o$GIKrX_M_&OaC14!S9Q_@w3NwGA{EydZMSg$8<<0jX7V27UuH&tQ#MJ_vsy% ztAB-9&g2iNl)OXN_9p4~`X*qwO76#_#Ut&}I;-YiXsO2BOse6Vn2oIB5UrhR#Ix?v zI;(~NU8Ba_Ose6Vn2qDBW@hpCS}dBIiABD7(=4*r`kuL8>#UmBTBR!MJ{bGq>;YP77ChvNPP<&1?B&I9)v*F7@> zT0*gu8CrVvgVguaesY1ra>L_Me(5_I+?Mr!#eB^%o&KM2TUv}LS7 zxlJRR@2o{O`^9<AGZjgr$0=`uXqt=~dAF(!-3QatlCgyJ!L1sKVS8McA(umQGbS0zvG%EXPK4>l8nz=b@TlW<|f)8A8(A<)? zaMH-njOt*Rmt&w{pSbrn%0ZPDtw%U)&8HF_GYs91!*8i;jf#$BsH-j|ww&u)DK z{)Md@(gm$i<(TJ{)^B3H;Ysb^Imsj8R@!%XKs#d(GBuw?(0-M=r$@+?tUsn~ac)tO z`*2-?+ghX9xFAL&+qZi(?oyn~cdh+cLfSv1JwcWzkAL`GZ=M-*tr>{7*1Yts-3B+k zcRg-cKH8m0JE3Zx!|rS!$XIf;td2P;%0&*cB+v2vezH=Xie-NKQke3L5E*Q-vo2PVE#m3vfs zMbE1QUGD?20qMAboQgh?y$F{WX^qa$wf+{Q`hI01SDxnxh3zm$Ma}K z&#C;-fVkUu$&tc^vNMN|&ynVGFGeO`^9z#YZl-GKU=4S*#an#H8JCb)aofVXZ)aWP z{#?@*HFxdtm}ki&Yvr>-OUyH0Gs3m*_^#DmLai(Tc)V9cPaco2=VQ*rLN1k8n5{zT zOO<9=TIppx@0H<>uWM=fu9cQYV_CiX8Gk&>&zo8Jy4F13T{D`rSV5JPY`N=1@5~#Z zQz%WAm6;$*pGRUTrR7r(PH7&6H-gnbJ1TK+DKXE#9%+p^R;F3olRk5Fap&sJs}^BqgOjO+yyx^Mfi?Y1Uw4w!b_Y>%w#MMuinmb-N7Si6rMvryZx zz$*=1UNP-_SGmq|m%g=L=1UIDckGOHFyImDVv(hlX=90+|R#)du=esHqtQ#@UU?t)R zQ7;(SXLP)~ua+40%8r`ku2YD-!+f)@Qq;5~FbD0zXRR+EX9TTawuGIAy-V$2o7k;? z;Z#R7z1Q@@qAC`-9>Y3l8WxHniFQzxd z-*1Y)eHw3Ewu06d{Azsy|WQTYXuzeCuV>_|!-$&*51Vyx0P!-_O0L}ZoNg0gR*^jELE%3P3<*4?J;@u$6D37Jbj0xFHtGrvcB zNU+abTug6v@X!+iA?-;ENksS03&BwWbql;qQnoj2YO9tGtz*`)0kf&Keg{#c`+w0h@7jP~A9P_}e53d&JX zmbz=~yft>-bTKiGaz{Zq3d$5Rc$qeia#PvcO0GI`z#Rg!qv6x~Mc^nX3o5mTYCE7d zyiYRC%sE8a%1g~Kru zJO^ZrAgGbmwEObt7eBQ;KJ77i^v4=IZx+97qfsc47Dk~&!I|~o`)KXYJ;$>>v^`lC z@;i=llTmNtC5llfO>}&#U$nUCLpF9`|1}BRdW^K`JFY)^|4v99h(@8r`@H#43ae`m zg_f?jKjX>QygzzBr^(`;95o)$t`TbU@ym0JLWwOtc9ce;RQ8P6FUHFORdCS75W2!4 zNACxy&^30Hp4=TJN+n)0JAT^CX`O?&pRU=FHQIdIeR+f{I>Vz+drThvvBr+l*il*z zG7UCIp)?AmQ7BQ;QEA1jqEKn1+eV@EG(O8U3MEm#nFQk(KXozZ)B43t|2~aB)+m%l zp)?AmPp0v?iMc2YKJ_tnl*W$I_@T=A`&~-r;>r|5qfp|AVvD{W-6GoY)?3y!_GoIZakvuWJ>-b}DvsT-3$G3mwS~WB2fJeGIWS4<8rv`{Wfn zFD-kQb*w;bJvJ^s-q|{q)xO_Di*2mOh5U|UCvEj?KW4 zXg>z6pPaNDXs%N|D})2Ec6y)I*MM&^qzyf9Phj$CkIADy)@qB7Vut{*XYp`&QQ~80 zPkv#306V|TlmE;Kx8mJ}!+i}EG^h<052nEGDPVeNv5mD(Aity78O2UqhaWd}j$)^1 zpyzAgz7;r3YNz*U{p3H29WLq`-Y|-tQS2#fc<algDF@#p%)d)_UFepY`;4T!$pT|1oR|QEBv{e5a!gmn0W{ z1fxSA=@q_?YujPD4j;Eqmi73-{62Z*)#s$;3|3HEkBvXq5s!Lkv5h-o1U@)}8#Q;O z{vhQ&K&dMk{{f8JfBXa0b@52Q)wF2*cW=^bZB2+uj}#z+YoXF z>IUw+;edTQ1TE{Nx|n{$wT0AJjo_Xi7kp;b9QO0!IX6i@EDgdS)c6E#2{cZc2wJgc zK(0(Ahddfu6{pO`$$b^Wd~2|k_11`9@xUxfo|!FHkE2#+W)8R>o1T%Q>Xjt50sE7F zP^*;_(ZZ3y%ELo$OFv-#BTB8atHKQS2xBvhacCF(`YSzZBv2GYdyFbEj^Q37uBS%Q zAL&!xV*IlwULK7WRyJDG${!5x8YhZUd%c;}H(#SD8N#EVg;jp0ZM|>kTZK{-NY;vScq{JSy8yaD8d4 zgs}=a#NQ3V-e;;27)x}OX81oGWw2H;zNP99{R;^dCBWETw5B@Hwdhf*5z2fLZxA&` zNnncHVoX6EHh67bURc*j;Ocqy}EszA)JyuS@1I2F8I(B3} zW$nmJ=&x+pKk$x+&dgD*C1$Nqh1!rkF@M_Y^cq5Wi^=$~n%j$Z)Ijqqo7!f0CD1_| zM0%VDFtTCf5B4ejzFVt>Q3Gjo^sJWrnCM%@ehsey-DwPY^wYKX0S&Xelf;>&+$}BePr#%PNkp~&AAi&II*e26mq~$7-I$3Ji01V`-Rj~V%JilEU**ps43|8 zl3+wPS*0gBLfRk~_^U-fd+CgY(BzMvVk+tjGaUZp707T~r5fiy?aFo36sdB=ABi6| zh26t|dG@IFk;sVp^B$w7$m<@HgGNoEt97;e_EbO10`oekIJRbAt{ULnv=$pR1xGs8 zl&8E+GTH?i zdn0v)_6goyz)yOcCp^a9$fs2{(YvIuav9ags7C((_Rcp+j^nuEpcJMg+cK}fk5(W+ z5)c?7{gnqn>;gjw)`DPQcV+W3K9axs6uyF}O}Bqich0=ZuIj4p>DihH@gd*Kf0b3! z(=)TXIyyi7o0@(%VxOxd&p~jNo?e6c-AKP1Ir+JS`zB%X)5NR&^hf_}~B-LQSsptKZl8+h{e{GWuB__g7WYcbe1Jg7p1ua@xs>{qK|X|3l#P z^(o_bRE~avV>E{&Ew$gtJ05q1n*1hu@~1n}voC)~kjz`@6O8GeOwY+>{j90J4>-OH z)V})Fss9ej@XYg{dyXe|Jn4SVU{mumv%8V>Ps){FRVME>-PN=FCqk3^*zXyR{!&Kz zw@msy1K)~HU!VFtL-egjzh@ZU$4vjucIn?*)%O9%uVmVH{0cb!eRj_$?p*utm^=*U z|E~$@_aN>rUca01)8{?K^yEzM>c&2a-Aep~uf4MClM<`x_ip>TXPEqye(>G+Gg5`tMNL2MQhq!dL{FFSKmnVJBi^holGa0d~T=jeA0i1&7IohtNQeN zcNf|3B|jhyN$^@oQ7k_u=!Sk*~Yonw-lcEp?Smp5dcw-l&7=`;;TkM9nI`PyYLVKK<<% zZw}Y@Z(n`9`r+;2)+$*8FTh;{6TbYD_;5G?-75G-p||k&*i;eu1!6U zC3!3daXz2fJZ#_W0S?yR?G`+Jfz+fA#iQdt_8Xr+^s)bV9X>AdKb41kAUUu>#Yeh| z+Y8V7Jm&UKeC@a>Z=~Zt@3me=! zAFU(OZT)J#rV&2}eI9I|XUv<14H{<;Y;a(Yd9RzF>X#f|H=aCm(PGGB|F#D!k13t{9*H?s&*%3xu}gX4Rld3U*iWr&I`aK6C3v{m#`RKh+m;;9S4RU*(B-(|KNl#!(M6&K}s{z@8s(eX$;pUa`Si{5T); z0jYrvDt@kxAE@%d8`39;h7B4|UJzewur(jmS*o}0zgB+M36j^4eFM?36)L~I@P1vY zZ|{d~{>&332e!h&%8VmbM8F-om;ZtxYKks}0XueDJXdg_U`~1d_ zoY)>~=&TzgCpOrckLu*=*6-YTv9?qG)b&VA=Z8u7Ibf?fwboVLbK_gjAO{KA+xh8rCYmEUsOE>RaILu9I?BH_@8_iImHKTJ zH+LQMr~F&<)CW~Pba1X8{@_}1xpkC(=ZEX$R&(IofT|C4aIPQz;97CHb(DW=p1FXk z9y&PJ4}Wm2xZFC*zctTXKvfSNoa=`_xK>?ENxlm8#TdJ$Pd*PR^KZ@VW98{mt`j+adZs*hQi}yAk>-W^pgVo|W zhv44kL*Jn4f2pqWDt@babL&QarR!30il+~7sb3VY^jw~PJ*qt34_o;wo;XnXDZVt$ z=QDeJT_P`tj$Mj#^C&;X&+UhJg+32{o}X*0c*T=f>53;V!nyHt{i1qZuk*fot2uHG zJoscPok^S4(GtM5KSN7n2?BDryuj77y_A-Cp_g1#eD|KB(AEW(S^^2d{i^=6J#^T3u#@U0s3J0&# zesl7r;?WF!eY8_NbwPZw!P>m#^Zj6(Hm(bA2oIXCJ;pZvOZaiVah}J*+nSjpsOFH` zms5Gh`A+G^*#kdtU_0OEFifEKxrp*D)z!W&%^St5x}BeQj-vTSx|(wow^UbkJKy)+ zCJ>#kOFbvix|ix|ZcFn<@v3g;hY3XUTdJ!$FU=dptGb=<`)(6>tmh|M_flOwzn12W z;#J+p#z%8ns;hY}%^St5x{r;I=Co8-^IV!YidS_X8z0SSsor{?QGcp_6t`4Ybvw@l z24v14DmIwQM{%w7+RX3NoaZ%n#SN-PlQJtlFZa=yHQGdDlx<3;b zkokhB*dCSMnx~J}byWV+`cYhKU9BgV->OgQf~s$HF!EFSx$&2_o|^OJ@AiP?#s+iw z(l}M8cD`11EHCE`q!u=4JnI7S#RhZv(zsT2EHCQ@sf7)$!80F^)b>1f*M|u(50879 zkM+rU1L++b%;ihta_cDnsQyy@-0JS7pS|~~`tLjw7?9@|h>8uK8z1$B4yyjqLFHGA zkLoPdRi8`qE{#`x)#8`-7sabSqqwEIs{7dZrE`qpAKN_DdQ0aN#VyrUzlxt*FY;6Q zFPT^GlWfh*3#>JV+WBhr)$=fc0of-I6&vh46X^u|b za~n^B^8un^gPmsr12Pv76&tL@*Und~ubzhq49Gr#sMw(5BVEOv8y~GB(p#@*>-w$N zr}AIQx}$YOx|&Zde(U;ct)q0E#C05YYOOh_bFo(aUT3=BeLtr2IM?&h_vyU%N$pSP znZW7&L-o(Q&NG2NxA7#-{hZJrJ!5-prK`N1X95Gx-4CL=f1ev?!LXl)ejfUH`1|vK zS@h>ce_n7F4EuTL=i#xQ2lex6d*$hy{lo?pAL%Nt^FRM=v)g(OR=?$Sobv&0yDQlr{mH#<)bj7wpLMQ3%vqt@PwyZ3DSas_l~tJCuP@!b5ZA7lohh!V1tT}^xAPMpW^9nE=GAGeQupxKUG)pDu1p& zc~qS7JTK-VxeUp_Hqt|B-Q0NPU&8x2lVdLL{gkcpD*w5>%A3nm@7&{5e@pu(KEl%a zQQoDx>PzveUamiRh%@xp0km`B=|lAu=_*d~QNGr?>Z^ojzd>?fgPl*`A2T0A_8&yU z2G`)(KaiT(b1{ljdM)1fxprRatGei5A*!kssGsv07221$y zZ0z6U$mK1LK0tC|do0yeTx*{GTi5CNnZSU|9YnOHt*0th|~d^Fa4Dyhr>> z(dUb7>fq;X_y|km=H?}Tgi*e^y02q#_V7IRpdRbFeC>R>_4nd`>2qRzxoG=m-z!CN z_(d4yQM%=|htfT7zNx-V=aKUBd2?-Q82az$&^(W=bmM&=_!<%q8izkRHt2b?d5{Mz z;i=Oa>CM;4<%!RYQ~u=hsQeXAywVj<9H{&{KfJ%ooda_PTg8*#qpDZiuXY{!TbftJ zx8|e%Th~|l>FZLFbsO@!1RAH-ZJIs2KCs6;etXqb-<>bJ&iA?Xxp7S}?B}7MhdrJL zdd@w+QCw^N-1^P!r~CKo19iO>c=YgDC=ZpF{cfHp9O7mD8 z@4G>AVS|c~bQO20{E~TaUOh6awR!5P`jK8cPUYJRe`)h7UC&ayMJRrPBbdTPzw(aY6d$`YDYYwIR>HG6}lJRWoN`gm{W=F9c>^~|yy~h=vUs@AKjdZ#Mph@SyjH zSE&5=!n3Yg{gQ7hthJ6>dA6FvR&{I7ZLNHMUbX6~Jk*Qy$WO&9ew^>r^$&e1TK!Y` zRbLTLzA@UreV=2U>%8(y@hZ<;p1#cA9@r5M-r9ezZhovEBo-S~{8;yW6Jv-Uh=%R) z()GFPRdY~0d6lmCC@#`f-Zgl2?mUl8PuL!nUW=z*ZoVik(sS!=Qy>Tq5?661O7 zt#nma@ln4j?%eoj9ZU7x^)9U!#jAcw<5WJypG%#nk4RVRQ+$+fsa{%F#pUu*|GD{; ze^h5{UG=T_s9zO#ZhW+kt@Ye_Mg8XHTg%_-a6jXb9z2h|m9FY4KI&J+ZOL<s%0#!UZsQeTk#VyrUUByTB zR9r59X?0k?A@9o!S!XS5ojPk!^`#}9ArUmrf+ z{^Hj+S3kVHzj}N4#V@~m{`|?meD~_doBP}0KhIx2`R51E*N5BN!<%Q9hN{^RQQ-Lu;_fBO7i|9E%z#wg~yt)4Rn-|}H{ms?)&ku*+fA!7PAHMzS_4jYCU%t40^Wx7!*SAkUdw+j-b$xSq_V(t(_0`So(|@|Y zzxmU%_lNf%KK}Id*SGK9{_yPZpLb6``*`^N@bU1&>%+6VpME^tKK;k{_cwR%{(N7y; literal 0 HcmV?d00001 diff --git a/vendor/github.com/wasilibs/go-re2/internal/wasm/memory.wasm b/vendor/github.com/wasilibs/go-re2/internal/wasm/memory.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b29f3375595e33b2c15fd2122fa2407616d5a68c GIT binary patch literal 28 jcmZQbEY4+QU|?WnV`OG-XkcOIVr0ur&CM^WWMTjSKi&ll literal 0 HcmV?d00001 diff --git a/vendor/github.com/wasilibs/go-re2/re2.go b/vendor/github.com/wasilibs/go-re2/re2.go new file mode 100644 index 00000000..84372caf --- /dev/null +++ b/vendor/github.com/wasilibs/go-re2/re2.go @@ -0,0 +1,99 @@ +package re2 + +import ( + "regexp" + + "github.com/wasilibs/go-re2/internal" +) + +type Regexp = internal.Regexp + +// MatchString reports whether the string s +// contains any match of the regular expression pattern. +// More complicated queries need to use Compile and the full Regexp interface. +func MatchString(pattern string, s string) (matched bool, err error) { + re, err := Compile(pattern) + if err != nil { + return false, err + } + defer internal.Release(re) + return re.MatchString(s), nil +} + +// Match reports whether the byte slice b +// contains any match of the regular expression pattern. +// More complicated queries need to use Compile and the full Regexp interface. +func Match(pattern string, b []byte) (matched bool, err error) { + re, err := Compile(pattern) + if err != nil { + return false, err + } + defer internal.Release(re) + return re.Match(b), nil +} + +// Compile parses a regular expression and returns, if successful, +// a Regexp object that can be used to match against text. +// +// When matching against text, the regexp returns a match that +// begins as early as possible in the input (leftmost), and among those +// it chooses the one that a backtracking search would have found first. +// This so-called leftmost-first matching is the same semantics +// that Perl, Python, and other implementations use, although this +// package implements it without the expense of backtracking. +// For POSIX leftmost-longest matching, see CompilePOSIX. +func Compile(expr string) (*Regexp, error) { + return internal.Compile(expr, internal.CompileOptions{}) +} + +// CompilePOSIX is like Compile but restricts the regular expression +// to POSIX ERE (egrep) syntax and changes the match semantics to +// leftmost-longest. +// +// That is, when matching against text, the regexp returns a match that +// begins as early as possible in the input (leftmost), and among those +// it chooses a match that is as long as possible. +// This so-called leftmost-longest matching is the same semantics +// that early regular expression implementations used and that POSIX +// specifies. +// +// However, there can be multiple leftmost-longest matches, with different +// submatch choices, and here this package diverges from POSIX. +// Among the possible leftmost-longest matches, this package chooses +// the one that a backtracking search would have found first, while POSIX +// specifies that the match be chosen to maximize the length of the first +// subexpression, then the second, and so on from left to right. +// The POSIX rule is computationally prohibitive and not even well-defined. +// See https://swtch.com/~rsc/regexp/regexp2.html#posix for details. +func CompilePOSIX(expr string) (*Regexp, error) { + return internal.Compile(expr, internal.CompileOptions{Longest: true, Posix: true}) +} + +// MustCompile is like Compile but panics if the expression cannot be parsed. +// It simplifies safe initialization of global variables holding compiled regular +// expressions. +func MustCompile(str string) *Regexp { + re, err := Compile(str) + if err != nil { + panic(`regexp: Compile(` + internal.QuoteForError(str) + `): ` + err.Error()) + } + return re +} + +// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed. +// It simplifies safe initialization of global variables holding compiled regular +// expressions. +func MustCompilePOSIX(str string) *Regexp { + regexp, err := CompilePOSIX(str) + if err != nil { + panic(`regexp: CompilePOSIX(` + internal.QuoteForError(str) + `): ` + err.Error()) + } + return regexp +} + +// QuoteMeta returns a string that escapes all regular expression metacharacters +// inside the argument text; the returned string is a regular expression matching +// the literal text. +func QuoteMeta(s string) string { + return regexp.QuoteMeta(s) +} diff --git a/vendor/github.com/wasilibs/wazero-helpers/LICENSE b/vendor/github.com/wasilibs/wazero-helpers/LICENSE new file mode 100644 index 00000000..41189cd1 --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) wasilibs authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving.go b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving.go new file mode 100644 index 00000000..40c261bf --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving.go @@ -0,0 +1,28 @@ +package allocator + +import ( + "errors" + + "github.com/tetratelabs/wazero/experimental" +) + +var errInvalidReallocation = errors.New("allocator: invalid reallocation request: size exceeds reserved address space") + +// NewNonMoving returns a [experimental.MemoryAllocator] that will reserve +// address space up to the maximum requested by a WebAssembly module during +// instantiation, ensuring that the base address of memory never changes even +// when the module requests memory to grow - the memory is never moved. +// +// On unix or windows, this reservation will not commit memory, allowing the +// allocation to succeed even if the requested size is more than available memory. +// On other platforms, it will follow the same behavior as wazero's default for +// shared memory, which uses Go's make([]byte, size) to pre-allocate a slice of +// the requested size, which may or may not work when more than available memory +// depending on the machine's settings related to overcommitting memory. +// +// On unix, this internally uses Mmap while on windows it uses VirtualAlloc, so +// it is appropriate to use the allocator for advanced use cases such as mapping +// an external file into the Wasm module's memory space. +func NewNonMoving() experimental.MemoryAllocator { + return experimental.MemoryAllocatorFunc(alloc) +} diff --git a/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_other.go b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_other.go new file mode 100644 index 00000000..6c2ac9ef --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_other.go @@ -0,0 +1,11 @@ +//go:build !unix && !windows + +package allocator + +import "github.com/tetratelabs/wazero/experimental" + +var pageSize = 0 // used only for test + +func alloc(cap, max uint64) experimental.LinearMemory { + return sliceAlloc(cap, max) +} diff --git a/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_slice.go b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_slice.go new file mode 100644 index 00000000..b67871ce --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_slice.go @@ -0,0 +1,24 @@ +package allocator + +import "github.com/tetratelabs/wazero/experimental" + +// Separate implementation of non-Unix/Windows code to file without +// build tag to allow testing on any platform. + +func sliceAlloc(_, max uint64) experimental.LinearMemory { + buf := make([]byte, max) + return &sliceBuffer{buf: buf[:0]} +} + +type sliceBuffer struct { + buf []byte +} + +func (b *sliceBuffer) Free() {} + +func (b *sliceBuffer) Reallocate(size uint64) []byte { + if int(size) > cap(b.buf) { + panic(errInvalidReallocation) + } + return b.buf[:size] +} diff --git a/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_unix.go b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_unix.go new file mode 100644 index 00000000..e6ef9dbd --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_unix.go @@ -0,0 +1,89 @@ +//go:build unix + +package allocator + +import ( + "fmt" + "math" + "sync" + + "github.com/tetratelabs/wazero/experimental" + "golang.org/x/sys/unix" +) + +var pageSize = unix.Getpagesize() + +func alloc(_, max uint64) experimental.LinearMemory { + // Round up to the page size because recommitting must be page-aligned. + // In practice, the WebAssembly page size should be a multiple of the system + // page size on most if not all platforms and rounding will never happen. + rnd := uint64(pageSize - 1) + reserved := (max + rnd) &^ rnd + + if reserved > math.MaxInt { + // This ensures int(max) overflows to a negative value, + // and unix.Mmap returns EINVAL. + reserved = math.MaxUint64 + } + + // Reserve max bytes of address space, to ensure we won't need to move it. + // A protected, private, anonymous mapping should not commit memory. + b, err := unix.Mmap(-1, 0, int(reserved), unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON) + if err != nil { + panic(fmt.Errorf("allocator_unix: failed to reserve memory: %w", err)) + } + return &mmappedMemory{buf: b[:0], max: max} +} + +// The slice covers the entire mmapped memory: +// - len(buf) is the already committed memory, +// - cap(buf) is the reserved address space, which is max rounded up to a page. +type mmappedMemory struct { + buf []byte + max uint64 + + // Any reasonable Wasm implementation will take a lock before calling Grow, but this + // is invisible to Go's race detector so it can still detect raciness when we updated + // buf. We go ahead and take a lock when mutating since the performance effect should + // be negligible in practice and it will help the race detector confirm the safety. + mu sync.Mutex +} + +func (m *mmappedMemory) Reallocate(size uint64) []byte { + if size > m.max { + panic(errInvalidReallocation) + } + + m.mu.Lock() + defer m.mu.Unlock() + + com := uint64(len(m.buf)) + if com < size { + // Round up to the page size. + rnd := uint64(unix.Getpagesize() - 1) + newCap := (size + rnd) &^ rnd + + // Commit additional memory up to new bytes. + err := unix.Mprotect(m.buf[com:newCap], unix.PROT_READ|unix.PROT_WRITE) + if err != nil { + panic(fmt.Errorf("allocator_unix: failed to commit memory: %w", err)) + } + + // Update committed memory. + m.buf = m.buf[:newCap] + } + // Limit returned capacity because bytes beyond + // len(m.buf) have not yet been committed. + return m.buf[:size:len(m.buf)] +} + +func (m *mmappedMemory) Free() { + m.mu.Lock() + defer m.mu.Unlock() + + err := unix.Munmap(m.buf[:cap(m.buf)]) + if err != nil { + panic(fmt.Errorf("allocator_unix: failed to release memory: %w", err)) + } + m.buf = nil +} diff --git a/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_windows.go b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_windows.go new file mode 100644 index 00000000..0c15d555 --- /dev/null +++ b/vendor/github.com/wasilibs/wazero-helpers/allocator/nonmoving_windows.go @@ -0,0 +1,93 @@ +//go:build windows + +package allocator + +import ( + "fmt" + "math" + "sync" + "unsafe" + + "github.com/tetratelabs/wazero/experimental" + "golang.org/x/sys/windows" +) + +var pageSize = windows.Getpagesize() + +func alloc(_, max uint64) experimental.LinearMemory { + // Round up to the page size because recommitting must be page-aligned. + // In practice, the WebAssembly page size should be a multiple of the system + // page size on most if not all platforms and rounding will never happen. + rnd := uint64(pageSize) - 1 + reserved := (max + rnd) &^ rnd + + if reserved > math.MaxInt { + // This ensures uintptr(max) overflows to a large value, + // and windows.VirtualAlloc returns an error. + reserved = math.MaxUint64 + } + + // Reserve max bytes of address space, to ensure we won't need to move it. + // This does not commit memory. + r, err := windows.VirtualAlloc(0, uintptr(reserved), windows.MEM_RESERVE, windows.PAGE_READWRITE) + if err != nil { + panic(fmt.Errorf("allocator_windows: failed to reserve memory: %w", err)) + } + + buf := unsafe.Slice((*byte)(unsafe.Pointer(r)), int(reserved)) + return &virtualMemory{buf: buf[:0], addr: r, max: max} +} + +// The slice covers the entire mmapped memory: +// - len(buf) is the already committed memory, +// - cap(buf) is the reserved address space, which is max rounded up to a page. +type virtualMemory struct { + buf []byte + addr uintptr + max uint64 + + // Any reasonable Wasm implementation will take a lock before calling Grow, but this + // is invisible to Go's race detector so it can still detect raciness when we updated + // buf. We go ahead and take a lock when mutating since the performance effect should + // be negligible in practice and it will help the race detector confirm the safety. + mu sync.Mutex +} + +func (m *virtualMemory) Reallocate(size uint64) []byte { + if size > m.max { + panic(errInvalidReallocation) + } + + m.mu.Lock() + defer m.mu.Unlock() + + com := uint64(len(m.buf)) + if com < size { + // Round up to the page size. + rnd := uint64(pageSize) - 1 + newCap := (size + rnd) &^ rnd + + // Commit additional memory up to new bytes. + _, err := windows.VirtualAlloc(m.addr, uintptr(newCap), windows.MEM_COMMIT, windows.PAGE_READWRITE) + if err != nil { + panic(fmt.Errorf("allocator_windows: failed to commit memory: %w", err)) + } + + // Update committed memory. + m.buf = m.buf[:newCap] + } + // Limit returned capacity because bytes beyond + // len(m.buf) have not yet been committed. + return m.buf[:size:len(m.buf)] +} + +func (m *virtualMemory) Free() { + m.mu.Lock() + defer m.mu.Unlock() + + err := windows.VirtualFree(m.addr, 0, windows.MEM_RELEASE) + if err != nil { + panic(fmt.Errorf("allocator_windows: failed to release memory: %w", err)) + } + m.addr = 0 +} diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go index dc931187..3e7f8df8 100644 --- a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go +++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go @@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string { type InvalidCostError int func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), MinCost, MaxCost) + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed inclusive range %d..%d", int(ic), MinCost, MaxCost) } const ( diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c..d1c8b264 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 099867de..7838ca5d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,6 +602,95 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } +const minIovec = 8 + +func Readv(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = readv(fd, iovecs) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = preadv(fd, iovecs, offset) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Writev(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = writev(fd, iovecs) + writevRacedetect(iovecs, n) + return n, err +} + +func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = pwritev(fd, iovecs, offset) + writevRacedetect(iovecs, n) + return n, err +} + +func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { + for _, b := range bs { + var v Iovec + v.SetLen(len(b)) + if len(b) > 0 { + v.Base = &b[0] + } else { + v.Base = (*byte)(unsafe.Pointer(&_zero)) + } + vecs = append(vecs, v) + } + return vecs +} + +func writevRacedetect(iovecs []Iovec, n int) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceReadRange(unsafe.Pointer(iovecs[i].Base), m) + } + } +} + +func readvRacedetect(iovecs []Iovec, n int, err error) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) + } + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } +} + //sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) @@ -705,3 +794,7 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys munmap(addr uintptr, length uintptr) (err error) +//sys readv(fd int, iovecs []Iovec) (n int, err error) +//sys preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) +//sys writev(fd int, iovecs []Iovec) (n int, err error) +//sys pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 230a9454..4958a657 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -13,6 +13,7 @@ package unix import ( "encoding/binary" + "slices" "strconv" "syscall" "time" @@ -417,7 +418,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { return nil, 0, EINVAL } sa.raw.Family = AF_UNIX - for i := 0; i < n; i++ { + for i := range n { sa.raw.Path[i] = int8(name[i]) } // length is family (uint16), name, NUL. @@ -507,7 +508,7 @@ func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) { psm := (*[2]byte)(unsafe.Pointer(&sa.raw.Psm)) psm[0] = byte(sa.PSM) psm[1] = byte(sa.PSM >> 8) - for i := 0; i < len(sa.Addr); i++ { + for i := range len(sa.Addr) { sa.raw.Bdaddr[i] = sa.Addr[len(sa.Addr)-1-i] } cid := (*[2]byte)(unsafe.Pointer(&sa.raw.Cid)) @@ -589,11 +590,11 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_CAN sa.raw.Ifindex = int32(sa.Ifindex) rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i] = rx[i] } tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i+4] = tx[i] } return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil @@ -618,11 +619,11 @@ func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_CAN sa.raw.Ifindex = int32(sa.Ifindex) n := (*[8]byte)(unsafe.Pointer(&sa.Name)) - for i := 0; i < 8; i++ { + for i := range 8 { sa.raw.Addr[i] = n[i] } p := (*[4]byte)(unsafe.Pointer(&sa.PGN)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i+8] = p[i] } sa.raw.Addr[12] = sa.Addr @@ -911,7 +912,7 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { // These are EBCDIC encoded by the kernel, but we still need to pad them // with blanks. Initializing with blanks allows the caller to feed in either // a padded or an unpadded string. - for i := 0; i < 8; i++ { + for i := range 8 { sa.raw.Nodeid[i] = ' ' sa.raw.User_id[i] = ' ' sa.raw.Name[i] = ' ' @@ -1148,7 +1149,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { var user [8]byte var name [8]byte - for i := 0; i < 8; i++ { + for i := range 8 { user[i] = byte(pp.User_id[i]) name[i] = byte(pp.Name[i]) } @@ -1173,11 +1174,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { Ifindex: int(pp.Ifindex), } name := (*[8]byte)(unsafe.Pointer(&sa.Name)) - for i := 0; i < 8; i++ { + for i := range 8 { name[i] = pp.Addr[i] } pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN)) - for i := 0; i < 4; i++ { + for i := range 4 { pgn[i] = pp.Addr[i+8] } addr := (*[1]byte)(unsafe.Pointer(&sa.Addr)) @@ -1188,11 +1189,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { Ifindex: int(pp.Ifindex), } rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) - for i := 0; i < 4; i++ { + for i := range 4 { rx[i] = pp.Addr[i] } tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) - for i := 0; i < 4; i++ { + for i := range 4 { tx[i] = pp.Addr[i+4] } return sa, nil @@ -2216,10 +2217,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { return } for i := 0; n > 0 && i < len(iovecs); i++ { - m := int(iovecs[i].Len) - if m > n { - m = n - } + m := min(int(iovecs[i].Len), n) n -= m if m > 0 { raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) @@ -2270,10 +2268,7 @@ func writevRacedetect(iovecs []Iovec, n int) { return } for i := 0; n > 0 && i < len(iovecs); i++ { - m := int(iovecs[i].Len) - if m > n { - m = n - } + m := min(int(iovecs[i].Len), n) n -= m if m > 0 { raceReadRange(unsafe.Pointer(iovecs[i].Base), m) @@ -2320,12 +2315,7 @@ func isGroupMember(gid int) bool { return false } - for _, g := range groups { - if g == gid { - return true - } - } - return false + return slices.Contains(groups, gid) } func isCapDacOverrideSet() bool { diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 4f432bfe..b6db27d9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -319,6 +319,7 @@ const ( AUDIT_INTEGRITY_POLICY_RULE = 0x70f AUDIT_INTEGRITY_RULE = 0x70d AUDIT_INTEGRITY_STATUS = 0x70a + AUDIT_INTEGRITY_USERSPACE = 0x710 AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f AUDIT_IPE_ACCESS = 0x58c @@ -327,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -491,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -527,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -554,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -843,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2023-03-01)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x30 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -936,11 +942,10 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 + ETHTOOL_FAMILY_NAME = "ethtool" + ETHTOOL_FAMILY_VERSION = 0x1 ETHTOOL_FEC_AUTO = 0x2 ETHTOOL_FEC_BASER = 0x10 ETHTOOL_FEC_LLRS = 0x20 @@ -1203,13 +1208,18 @@ const ( FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 FAN_EPIDFD = -0x2 + FAN_ERRNO_BITS = 0x8 + FAN_ERRNO_MASK = 0xff + FAN_ERRNO_SHIFT = 0x18 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 + FAN_EVENT_INFO_TYPE_RANGE = 0x6 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_FS_ERROR = 0x8000 @@ -1224,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1240,6 +1253,7 @@ const ( FAN_OPEN_EXEC = 0x1000 FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 + FAN_PRE_ACCESS = 0x100000 FAN_Q_OVERFLOW = 0x4000 FAN_RENAME = 0x10000000 FAN_REPORT_DFID_NAME = 0xc00 @@ -1247,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1266,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1574,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1625,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1687,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1809,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2485,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2644,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2724,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2787,7 +2813,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1e + RTA_MAX = 0x1f RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -2864,10 +2890,12 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELANYCAST = 0x3d RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELLINKPROP = 0x6d RTM_DELMDB = 0x55 + RTM_DELMULTICAST = 0x39 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 @@ -2917,11 +2945,13 @@ const ( RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 + RTM_NEWANYCAST = 0x3c RTM_NEWCACHEREPORT = 0x60 RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWLINKPROP = 0x6c RTM_NEWMDB = 0x54 + RTM_NEWMULTICAST = 0x38 RTM_NEWNDUSEROPT = 0x44 RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 @@ -2970,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -2987,11 +3018,12 @@ const ( RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 RWF_ATOMIC = 0x40 + RWF_DONTCACHE = 0x80 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x7f + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3271,6 +3303,7 @@ const ( STATX_BTIME = 0x800 STATX_CTIME = 0x80 STATX_DIOALIGN = 0x2000 + STATX_DIO_READ_ALIGN = 0x20000 STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 @@ -3322,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xe + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3392,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3503,6 +3534,7 @@ const ( TP_STATUS_WRONG_FORMAT = 0x4 TRACEFS_MAGIC = 0x74726163 TS_COMM_LEN = 0x20 + UBI_IOCECNFO = 0xc01c6f06 UDF_SUPER_MAGIC = 0x15013346 UDP_CORK = 0x1 UDP_ENCAP = 0x64 @@ -3515,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3559,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3673,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 75207613..1c37f9fb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -372,6 +374,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c68acda5..6f54d34a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -373,6 +375,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index a8c607ab..783ec5c1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -378,6 +380,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 18563dd8..ca83d3ba 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 22912cda..607e611c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -365,6 +367,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 29344eb3..b9cb5bd3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 20d51fb9..65b078a6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 321b6090..5298a303 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 9bacdf1e..7bc557c8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c2242726..152399bb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -426,6 +428,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 6270c8ee..1a1ce240 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 9966c194..4231a1fb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 848e5fcc..21c0e952 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -362,6 +364,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 669b2adb..f00d1cd7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -434,6 +436,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 4834e575..bc8d539e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 @@ -473,6 +475,7 @@ const ( SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 24b346e1..813c05b6 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -2512,6 +2512,90 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_writev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwritev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(libc_fstat64_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index ebd21310..fda32858 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -738,6 +738,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + TEXT libc_fstat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat64(SB) GLOBL ·libc_fstat64_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 824b9c2d..e6f58f3c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -2512,6 +2512,90 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_writev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwritev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 4f178a22..7f8998b9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -738,6 +738,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat(SB) GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff3..aca56ee4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb45069..2ea1ef58 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e50297..d22c8af3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec5..5ee264ae 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a..f9f03ebf 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a33..87c2118e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b99622..391ad102 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9..56561577 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc..0482b52e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfb..71806f08 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b4463650..e35a7105 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c1..2aea4767 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 84053916..6c9bb4e5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790..680bc991 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f..620f2710 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index a46abe64..cd236443 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,10 @@ type Statx_t struct { Atomic_write_unit_min uint32 Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 _ [1]uint32 - _ [9]uint64 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2226,8 +2229,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -2314,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2594,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -3802,7 +3813,16 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2d + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3842,7 +3862,17 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -3949,7 +3979,12 @@ const ( ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb ETHTOOL_A_RINGS_CQE_SIZE = 0xc ETHTOOL_A_RINGS_TX_PUSH = 0xd - ETHTOOL_A_RINGS_MAX = 0x10 + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 ETHTOOL_A_CHANNELS_UNSPEC = 0x0 ETHTOOL_A_CHANNELS_HEADER = 0x1 ETHTOOL_A_CHANNELS_RX_MAX = 0x2 @@ -4015,7 +4050,9 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x6 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4101,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4613,6 +4663,7 @@ const ( NL80211_ATTR_AKM_SUITES = 0x4c NL80211_ATTR_AP_ISOLATE = 0x60 NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a NL80211_ATTR_AUTH_DATA = 0x9c NL80211_ATTR_AUTH_TYPE = 0x35 NL80211_ATTR_BANDS = 0xef @@ -4623,6 +4674,7 @@ const ( NL80211_ATTR_BSS_BASIC_RATES = 0x24 NL80211_ATTR_BSS = 0x2f NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 NL80211_ATTR_BSS_HT_OPMODE = 0x6d NL80211_ATTR_BSSID = 0xf5 NL80211_ATTR_BSS_SELECT = 0xe3 @@ -4682,6 +4734,7 @@ const ( NL80211_ATTR_DTIM_PERIOD = 0xd NL80211_ATTR_DURATION = 0x57 NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 NL80211_ATTR_EML_CAPABILITY = 0x13d NL80211_ATTR_EXT_CAPA = 0xa9 NL80211_ATTR_EXT_CAPA_MASK = 0xaa @@ -4717,6 +4770,7 @@ const ( NL80211_ATTR_HIDDEN_SSID = 0x7e NL80211_ATTR_HT_CAPABILITY = 0x1f NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 NL80211_ATTR_IE_ASSOC_RESP = 0x80 NL80211_ATTR_IE = 0x2a NL80211_ATTR_IE_PROBE_RESP = 0x7f @@ -4747,9 +4801,10 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14d + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 NL80211_ATTR_MAX_MATCH_SETS = 0x85 NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 @@ -4774,9 +4829,12 @@ const ( NL80211_ATTR_MGMT_SUBTYPE = 0x29 NL80211_ATTR_MLD_ADDR = 0x13a NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 NL80211_ATTR_MLO_LINK_ID = 0x139 NL80211_ATTR_MLO_LINKS = 0x138 NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 NL80211_ATTR_MNTR_FLAGS = 0x17 NL80211_ATTR_MPATH_INFO = 0x1b NL80211_ATTR_MPATH_NEXT_HOP = 0x1a @@ -4809,12 +4867,14 @@ const ( NL80211_ATTR_PORT_AUTHORIZED = 0x103 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 NL80211_ATTR_PREV_BSSID = 0x4f NL80211_ATTR_PRIVACY = 0x46 NL80211_ATTR_PROBE_RESP = 0x91 NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 NL80211_ATTR_PROTOCOL_FEATURES = 0xad NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 NL80211_ATTR_QOS_MAP = 0xc7 NL80211_ATTR_RADAR_BACKGROUND = 0x134 NL80211_ATTR_RADAR_EVENT = 0xa8 @@ -4943,7 +5003,9 @@ const ( NL80211_ATTR_WIPHY_FREQ = 0x26 NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 @@ -4978,6 +5040,8 @@ const ( NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 NL80211_BAND_ATTR_MAX = 0xd NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc NL80211_BAND_ATTR_VHT_CAPA = 0x8 NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 @@ -5001,6 +5065,10 @@ const ( NL80211_BSS_BEACON_INTERVAL = 0x4 NL80211_BSS_BEACON_TSF = 0xd NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 NL80211_BSS_CAPABILITY = 0x5 NL80211_BSS_CHAIN_SIGNAL = 0x13 NL80211_BSS_CHAN_WIDTH_10 = 0x1 @@ -5032,6 +5100,9 @@ const ( NL80211_BSS_STATUS = 0x9 NL80211_BSS_STATUS_IBSS_JOINED = 0x2 NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 NL80211_CHAN_HT20 = 0x1 NL80211_CHAN_HT40MINUS = 0x2 NL80211_CHAN_HT40PLUS = 0x3 @@ -5117,7 +5188,8 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9b + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5161,6 +5233,7 @@ const ( NL80211_CMD_SET_COALESCE = 0x65 NL80211_CMD_SET_CQM = 0x3f NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 NL80211_CMD_SET_INTERFACE = 0x6 NL80211_CMD_SET_KEY = 0xa NL80211_CMD_SET_MAC_ACL = 0x5d @@ -5180,6 +5253,7 @@ const ( NL80211_CMD_SET_SAR_SPECS = 0x8c NL80211_CMD_SET_STATION = 0x12 NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 NL80211_CMD_SET_WDS_PEER = 0x42 NL80211_CMD_SET_WIPHY = 0x2 @@ -5247,6 +5321,7 @@ const ( NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 @@ -5262,6 +5337,7 @@ const ( NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 @@ -5281,9 +5357,12 @@ const ( NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c NL80211_EXT_FEATURE_RRM = 0x1 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 @@ -5295,8 +5374,10 @@ const ( NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f NL80211_EXT_FEATURE_SECURE_RTT = 0x38 NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 NL80211_EXT_FEATURE_TXQS = 0x1c NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 @@ -5343,7 +5424,10 @@ const ( NL80211_FREQUENCY_ATTR_2MHZ = 0x16 NL80211_FREQUENCY_ATTR_4MHZ = 0x17 NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 NL80211_FREQUENCY_ATTR_DISABLED = 0x2 @@ -5351,12 +5435,14 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b NL80211_FREQUENCY_ATTR_NO_HE = 0x13 @@ -5364,8 +5450,11 @@ const ( NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_OFFSET = 0x14 NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c NL80211_FREQUENCY_ATTR_RADAR = 0x5 NL80211_FREQUENCY_ATTR_WMM = 0x12 NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 @@ -5430,6 +5519,7 @@ const ( NL80211_IFTYPE_STATION = 0x2 NL80211_IFTYPE_UNSPECIFIED = 0x0 NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 NL80211_KCK_EXT_LEN = 0x18 NL80211_KCK_LEN = 0x10 NL80211_KEK_EXT_LEN = 0x20 @@ -5458,9 +5548,10 @@ const ( NL80211_MAX_SUPP_HT_RATES = 0x4d NL80211_MAX_SUPP_RATES = 0x20 NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 @@ -5703,11 +5794,16 @@ const ( NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c NL80211_RATE_INFO_BITRATE32 = 0x5 NL80211_RATE_INFO_BITRATE = 0x1 NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 @@ -5753,6 +5849,8 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 NL80211_RATE_INFO_SHORT_GI = 0x4 NL80211_RATE_INFO_VHT_MCS = 0x6 NL80211_RATE_INFO_VHT_NSS = 0x7 @@ -5770,14 +5868,19 @@ const ( NL80211_REKEY_DATA_KEK = 0x1 NL80211_REKEY_DATA_REPLAY_CTR = 0x3 NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 NL80211_RRF_AUTO_BW = 0x800 NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 NL80211_RRF_GO_CONCURRENT = 0x1000 NL80211_RRF_IR_CONCURRENT = 0x1000 NL80211_RRF_NO_160MHZ = 0x10000 NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 NL80211_RRF_NO_80MHZ = 0x8000 NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 NL80211_RRF_NO_HE = 0x20000 NL80211_RRF_NO_HT40 = 0x6000 NL80211_RRF_NO_HT40MINUS = 0x2000 @@ -5788,7 +5891,10 @@ const ( NL80211_RRF_NO_IR = 0x80 NL80211_RRF_NO_OFDM = 0x1 NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 NL80211_RRF_PTMP_ONLY = 0x40 NL80211_RRF_PTP_ONLY = 0x20 NL80211_RXMGMT_FLAG_ANSWERED = 0x1 @@ -5849,6 +5955,7 @@ const ( NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 NL80211_STA_FLAG_TDLS_PEER = 0x6 NL80211_STA_FLAG_WME = 0x3 NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 @@ -6007,6 +6114,13 @@ const ( NL80211_VHT_CAPABILITY_LEN = 0xc NL80211_VHT_NSS_MAX = 0x8 NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 NL80211_WMMR_AIFSN = 0x3 NL80211_WMMR_CW_MAX = 0x2 NL80211_WMMR_CW_MIN = 0x1 @@ -6038,6 +6152,7 @@ const ( NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fd402da4..485f2d3a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -338,6 +338,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index eb7a5e18..ecbd1ad8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -351,6 +351,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index d78ac108..02f0463a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -329,6 +329,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index cd06d47f..6f4d400d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -330,6 +330,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2f28fe26..cd532cfa 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -331,6 +331,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 71d6cac2..41336208 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8596d453..eaa37eb7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index cd60ea18..98ae6a1e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b0ae420c..cae19615 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 83597287..6ce3b4e0 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,7 +285,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -341,6 +341,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 69eb6a5c..c7429c6a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5f583cb6..4bf4baf4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index ad05b51a..e9709d70 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -358,6 +358,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cf3ce900..fb44268c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -353,6 +353,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 590b5673..9c38265c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -335,6 +335,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index b6e1ab76..a8b0364c 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -1303,7 +1303,10 @@ func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DE return nil, err } if absoluteSDSize > 0 { - absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0])) + absoluteSD = new(SECURITY_DESCRIPTOR) + if unsafe.Sizeof(*absoluteSD) < uintptr(absoluteSDSize) { + panic("sizeof(SECURITY_DESCRIPTOR) too small") + } } var ( dacl *ACL @@ -1312,19 +1315,55 @@ func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DE group *SID ) if daclSize > 0 { - dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0])) + dacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, daclSize)))) } if saclSize > 0 { - sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0])) + sacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, saclSize)))) } if ownerSize > 0 { - owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0])) + owner = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, ownerSize)))) } if groupSize > 0 { - group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0])) + group = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, groupSize)))) } + // We call into Windows via makeAbsoluteSD, which sets up + // pointers within absoluteSD that point to other chunks of memory + // we pass into makeAbsoluteSD, and that happens outside the view of the GC. + // We therefore take some care here to then verify the pointers are as we expect + // and set them explicitly in view of the GC. See https://go.dev/issue/73199. + // TODO: consider weak pointers once Go 1.24 is appropriate. See suggestion in https://go.dev/cl/663575. err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize, dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize) + if err != nil { + // Don't return absoluteSD, which might be partially initialized. + return nil, err + } + // Before using any fields, verify absoluteSD is in the format we expect according to Windows. + // See https://learn.microsoft.com/en-us/windows/win32/secauthz/absolute-and-self-relative-security-descriptors + absControl, _, err := absoluteSD.Control() + if err != nil { + panic("absoluteSD: " + err.Error()) + } + if absControl&SE_SELF_RELATIVE != 0 { + panic("absoluteSD not in absolute format") + } + if absoluteSD.dacl != dacl { + panic("dacl pointer mismatch") + } + if absoluteSD.sacl != sacl { + panic("sacl pointer mismatch") + } + if absoluteSD.owner != owner { + panic("owner pointer mismatch") + } + if absoluteSD.group != group { + panic("group pointer mismatch") + } + absoluteSD.dacl = dacl + absoluteSD.sacl = sacl + absoluteSD.owner = owner + absoluteSD.group = group + return } diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 4a325438..640f6b15 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -870,6 +870,7 @@ const socket_error = uintptr(^uint32(0)) //sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom //sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo //sys WSASocket(af int32, typ int32, protocol int32, protoInfo *WSAProtocolInfo, group uint32, flags uint32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.WSASocketW +//sys WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err error) [failretval!=0] = ws2_32.WSADuplicateSocketW //sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname //sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname //sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs @@ -1698,8 +1699,9 @@ func NewNTUnicodeString(s string) (*NTUnicodeString, error) { // Slice returns a uint16 slice that aliases the data in the NTUnicodeString. func (s *NTUnicodeString) Slice() []uint16 { - slice := unsafe.Slice(s.Buffer, s.MaximumLength) - return slice[:s.Length] + // Note: this rounds the length down, if it happens + // to (incorrectly) be odd. Probably safer than rounding up. + return unsafe.Slice(s.Buffer, s.MaximumLength/2)[:s.Length/2] } func (s *NTUnicodeString) String() string { diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 9d138de5..958bcf47 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -1074,6 +1074,7 @@ const ( IP_ADD_MEMBERSHIP = 0xc IP_DROP_MEMBERSHIP = 0xd IP_PKTINFO = 0x13 + IP_MTU_DISCOVER = 0x47 IPV6_V6ONLY = 0x1b IPV6_UNICAST_HOPS = 0x4 @@ -1083,6 +1084,7 @@ const ( IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_PKTINFO = 0x13 + IPV6_MTU_DISCOVER = 0x47 MSG_OOB = 0x1 MSG_PEEK = 0x2 @@ -1132,6 +1134,15 @@ const ( WSASYS_STATUS_LEN = 128 ) +// enum PMTUD_STATE from ws2ipdef.h +const ( + IP_PMTUDISC_NOT_SET = 0 + IP_PMTUDISC_DO = 1 + IP_PMTUDISC_DONT = 2 + IP_PMTUDISC_PROBE = 3 + IP_PMTUDISC_MAX = 4 +) + type WSABuf struct { Len uint32 Buf *byte @@ -1146,6 +1157,22 @@ type WSAMsg struct { Flags uint32 } +type WSACMSGHDR struct { + Len uintptr + Level int32 + Type int32 +} + +type IN_PKTINFO struct { + Addr [4]byte + Ifindex uint32 +} + +type IN6_PKTINFO struct { + Addr [16]byte + Ifindex uint32 +} + // Flags for WSASocket const ( WSA_FLAG_OVERLAPPED = 0x01 @@ -2673,6 +2700,8 @@ type CommTimeouts struct { // NTUnicodeString is a UTF-16 string for NT native APIs, corresponding to UNICODE_STRING. type NTUnicodeString struct { + // Note: Length and MaximumLength are in *bytes*, not uint16s. + // They should always be even. Length uint16 MaximumLength uint16 Buffer *uint16 @@ -3601,3 +3630,213 @@ const ( KLF_NOTELLSHELL = 0x00000080 KLF_SETFORPROCESS = 0x00000100 ) + +// Virtual Key codes +// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes +const ( + VK_LBUTTON = 0x01 + VK_RBUTTON = 0x02 + VK_CANCEL = 0x03 + VK_MBUTTON = 0x04 + VK_XBUTTON1 = 0x05 + VK_XBUTTON2 = 0x06 + VK_BACK = 0x08 + VK_TAB = 0x09 + VK_CLEAR = 0x0C + VK_RETURN = 0x0D + VK_SHIFT = 0x10 + VK_CONTROL = 0x11 + VK_MENU = 0x12 + VK_PAUSE = 0x13 + VK_CAPITAL = 0x14 + VK_KANA = 0x15 + VK_HANGEUL = 0x15 + VK_HANGUL = 0x15 + VK_IME_ON = 0x16 + VK_JUNJA = 0x17 + VK_FINAL = 0x18 + VK_HANJA = 0x19 + VK_KANJI = 0x19 + VK_IME_OFF = 0x1A + VK_ESCAPE = 0x1B + VK_CONVERT = 0x1C + VK_NONCONVERT = 0x1D + VK_ACCEPT = 0x1E + VK_MODECHANGE = 0x1F + VK_SPACE = 0x20 + VK_PRIOR = 0x21 + VK_NEXT = 0x22 + VK_END = 0x23 + VK_HOME = 0x24 + VK_LEFT = 0x25 + VK_UP = 0x26 + VK_RIGHT = 0x27 + VK_DOWN = 0x28 + VK_SELECT = 0x29 + VK_PRINT = 0x2A + VK_EXECUTE = 0x2B + VK_SNAPSHOT = 0x2C + VK_INSERT = 0x2D + VK_DELETE = 0x2E + VK_HELP = 0x2F + VK_LWIN = 0x5B + VK_RWIN = 0x5C + VK_APPS = 0x5D + VK_SLEEP = 0x5F + VK_NUMPAD0 = 0x60 + VK_NUMPAD1 = 0x61 + VK_NUMPAD2 = 0x62 + VK_NUMPAD3 = 0x63 + VK_NUMPAD4 = 0x64 + VK_NUMPAD5 = 0x65 + VK_NUMPAD6 = 0x66 + VK_NUMPAD7 = 0x67 + VK_NUMPAD8 = 0x68 + VK_NUMPAD9 = 0x69 + VK_MULTIPLY = 0x6A + VK_ADD = 0x6B + VK_SEPARATOR = 0x6C + VK_SUBTRACT = 0x6D + VK_DECIMAL = 0x6E + VK_DIVIDE = 0x6F + VK_F1 = 0x70 + VK_F2 = 0x71 + VK_F3 = 0x72 + VK_F4 = 0x73 + VK_F5 = 0x74 + VK_F6 = 0x75 + VK_F7 = 0x76 + VK_F8 = 0x77 + VK_F9 = 0x78 + VK_F10 = 0x79 + VK_F11 = 0x7A + VK_F12 = 0x7B + VK_F13 = 0x7C + VK_F14 = 0x7D + VK_F15 = 0x7E + VK_F16 = 0x7F + VK_F17 = 0x80 + VK_F18 = 0x81 + VK_F19 = 0x82 + VK_F20 = 0x83 + VK_F21 = 0x84 + VK_F22 = 0x85 + VK_F23 = 0x86 + VK_F24 = 0x87 + VK_NUMLOCK = 0x90 + VK_SCROLL = 0x91 + VK_OEM_NEC_EQUAL = 0x92 + VK_OEM_FJ_JISHO = 0x92 + VK_OEM_FJ_MASSHOU = 0x93 + VK_OEM_FJ_TOUROKU = 0x94 + VK_OEM_FJ_LOYA = 0x95 + VK_OEM_FJ_ROYA = 0x96 + VK_LSHIFT = 0xA0 + VK_RSHIFT = 0xA1 + VK_LCONTROL = 0xA2 + VK_RCONTROL = 0xA3 + VK_LMENU = 0xA4 + VK_RMENU = 0xA5 + VK_BROWSER_BACK = 0xA6 + VK_BROWSER_FORWARD = 0xA7 + VK_BROWSER_REFRESH = 0xA8 + VK_BROWSER_STOP = 0xA9 + VK_BROWSER_SEARCH = 0xAA + VK_BROWSER_FAVORITES = 0xAB + VK_BROWSER_HOME = 0xAC + VK_VOLUME_MUTE = 0xAD + VK_VOLUME_DOWN = 0xAE + VK_VOLUME_UP = 0xAF + VK_MEDIA_NEXT_TRACK = 0xB0 + VK_MEDIA_PREV_TRACK = 0xB1 + VK_MEDIA_STOP = 0xB2 + VK_MEDIA_PLAY_PAUSE = 0xB3 + VK_LAUNCH_MAIL = 0xB4 + VK_LAUNCH_MEDIA_SELECT = 0xB5 + VK_LAUNCH_APP1 = 0xB6 + VK_LAUNCH_APP2 = 0xB7 + VK_OEM_1 = 0xBA + VK_OEM_PLUS = 0xBB + VK_OEM_COMMA = 0xBC + VK_OEM_MINUS = 0xBD + VK_OEM_PERIOD = 0xBE + VK_OEM_2 = 0xBF + VK_OEM_3 = 0xC0 + VK_OEM_4 = 0xDB + VK_OEM_5 = 0xDC + VK_OEM_6 = 0xDD + VK_OEM_7 = 0xDE + VK_OEM_8 = 0xDF + VK_OEM_AX = 0xE1 + VK_OEM_102 = 0xE2 + VK_ICO_HELP = 0xE3 + VK_ICO_00 = 0xE4 + VK_PROCESSKEY = 0xE5 + VK_ICO_CLEAR = 0xE6 + VK_OEM_RESET = 0xE9 + VK_OEM_JUMP = 0xEA + VK_OEM_PA1 = 0xEB + VK_OEM_PA2 = 0xEC + VK_OEM_PA3 = 0xED + VK_OEM_WSCTRL = 0xEE + VK_OEM_CUSEL = 0xEF + VK_OEM_ATTN = 0xF0 + VK_OEM_FINISH = 0xF1 + VK_OEM_COPY = 0xF2 + VK_OEM_AUTO = 0xF3 + VK_OEM_ENLW = 0xF4 + VK_OEM_BACKTAB = 0xF5 + VK_ATTN = 0xF6 + VK_CRSEL = 0xF7 + VK_EXSEL = 0xF8 + VK_EREOF = 0xF9 + VK_PLAY = 0xFA + VK_ZOOM = 0xFB + VK_NONAME = 0xFC + VK_PA1 = 0xFD + VK_OEM_CLEAR = 0xFE +) + +// Mouse button constants. +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str +const ( + FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001 + RIGHTMOST_BUTTON_PRESSED = 0x0002 + FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004 + FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008 + FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010 +) + +// Control key state constaints. +// https://docs.microsoft.com/en-us/windows/console/key-event-record-str +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str +const ( + CAPSLOCK_ON = 0x0080 + ENHANCED_KEY = 0x0100 + LEFT_ALT_PRESSED = 0x0002 + LEFT_CTRL_PRESSED = 0x0008 + NUMLOCK_ON = 0x0020 + RIGHT_ALT_PRESSED = 0x0001 + RIGHT_CTRL_PRESSED = 0x0004 + SCROLLLOCK_ON = 0x0040 + SHIFT_PRESSED = 0x0010 +) + +// Mouse event record event flags. +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str +const ( + MOUSE_MOVED = 0x0001 + DOUBLE_CLICK = 0x0002 + MOUSE_WHEELED = 0x0004 + MOUSE_HWHEELED = 0x0008 +) + +// Input Record Event Types +// https://learn.microsoft.com/en-us/windows/console/input-record-str +const ( + FOCUS_EVENT = 0x0010 + KEY_EVENT = 0x0001 + MENU_EVENT = 0x0008 + MOUSE_EVENT = 0x0002 + WINDOW_BUFFER_SIZE_EVENT = 0x0004 +) diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 01c0716c..a58bc48b 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -511,6 +511,7 @@ var ( procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSADuplicateSocketW = modws2_32.NewProc("WSADuplicateSocketW") procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") procWSAIoctl = modws2_32.NewProc("WSAIoctl") @@ -4391,6 +4392,14 @@ func WSACleanup() (err error) { return } +func WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err error) { + r1, _, e1 := syscall.Syscall(procWSADuplicateSocketW.Addr(), 3, uintptr(s), uintptr(processID), uintptr(unsafe.Pointer(info))) + if r1 != 0 { + err = errnoErr(e1) + } + return +} + func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) n = int32(r0) diff --git a/vendor/golang.org/x/tools/godoc/util/util.go b/vendor/golang.org/x/tools/godoc/util/util.go index c08ca785..21390556 100644 --- a/vendor/golang.org/x/tools/godoc/util/util.go +++ b/vendor/golang.org/x/tools/godoc/util/util.go @@ -18,18 +18,18 @@ import ( // access to it and records the time the value was last set. type RWValue struct { mutex sync.RWMutex - value interface{} + value any timestamp time.Time // time of last set() } -func (v *RWValue) Set(value interface{}) { +func (v *RWValue) Set(value any) { v.mutex.Lock() v.value = value v.timestamp = time.Now() v.mutex.Unlock() } -func (v *RWValue) Get() (interface{}, time.Time) { +func (v *RWValue) Get() (any, time.Time) { v.mutex.RLock() defer v.mutex.RUnlock() return v.value, v.timestamp diff --git a/vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go b/vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go index 521bf71a..4ab5c7c6 100644 --- a/vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go +++ b/vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go @@ -84,6 +84,6 @@ func (e *emptyVFS) IsDir() bool { return true } -func (e *emptyVFS) Sys() interface{} { +func (e *emptyVFS) Sys() any { return nil } diff --git a/vendor/golang.org/x/tools/godoc/vfs/fs.go b/vendor/golang.org/x/tools/godoc/vfs/fs.go index f12d653f..2bec5886 100644 --- a/vendor/golang.org/x/tools/godoc/vfs/fs.go +++ b/vendor/golang.org/x/tools/godoc/vfs/fs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.16 -// +build go1.16 package vfs diff --git a/vendor/golang.org/x/tools/godoc/vfs/namespace.go b/vendor/golang.org/x/tools/godoc/vfs/namespace.go index 23dd9794..2566051a 100644 --- a/vendor/golang.org/x/tools/godoc/vfs/namespace.go +++ b/vendor/golang.org/x/tools/godoc/vfs/namespace.go @@ -275,7 +275,7 @@ func (d dirInfo) Size() int64 { return 0 } func (d dirInfo) Mode() os.FileMode { return os.ModeDir | 0555 } func (d dirInfo) ModTime() time.Time { return startTime } func (d dirInfo) IsDir() bool { return true } -func (d dirInfo) Sys() interface{} { return nil } +func (d dirInfo) Sys() any { return nil } var startTime = time.Now() diff --git a/vendor/golang.org/x/tools/godoc/vfs/os.go b/vendor/golang.org/x/tools/godoc/vfs/os.go index 35d05094..fe21a586 100644 --- a/vendor/golang.org/x/tools/godoc/vfs/os.go +++ b/vendor/golang.org/x/tools/godoc/vfs/os.go @@ -12,6 +12,7 @@ import ( pathpkg "path" "path/filepath" "runtime" + "slices" ) // We expose a new variable because otherwise we need to copy the findGOROOT logic again @@ -45,10 +46,8 @@ type osFS struct { func isGoPath(path string) bool { for _, bp := range filepath.SplitList(build.Default.GOPATH) { - for _, gp := range filepath.SplitList(path) { - if bp == gp { - return true - } + if slices.Contains(filepath.SplitList(path), bp) { + return true } } return false diff --git a/vendor/modules.txt b/vendor/modules.txt index f0247962..4678b2f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,21 +10,24 @@ github.com/Masterminds/semver/v3 # github.com/Masterminds/sprig/v3 v3.3.0 ## explicit; go 1.21 github.com/Masterminds/sprig/v3 -# github.com/bmatcuk/doublestar/v4 v4.7.1 +# github.com/bmatcuk/doublestar/v4 v4.9.1 ## explicit; go 1.16 github.com/bmatcuk/doublestar/v4 # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew +# github.com/fatih/color v1.16.0 +## explicit; go 1.17 +github.com/fatih/color # github.com/fsnotify/fsnotify v1.8.0 ## explicit; go 1.17 github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify/internal -# github.com/go-git/go-git/v5 v5.13.0 -## explicit; go 1.21 +# github.com/go-git/go-git/v5 v5.16.2 +## explicit; go 1.23.0 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash -# github.com/go-viper/mapstructure/v2 v2.2.1 +# github.com/go-viper/mapstructure/v2 v2.3.0 ## explicit; go 1.18 github.com/go-viper/mapstructure/v2 github.com/go-viper/mapstructure/v2/internal/errors @@ -40,8 +43,8 @@ github.com/google/uuid # github.com/hashicorp/go-cleanhttp v0.5.2 ## explicit; go 1.13 github.com/hashicorp/go-cleanhttp -# github.com/hashicorp/go-retryablehttp v0.7.7 -## explicit; go 1.19 +# github.com/hashicorp/go-retryablehttp v0.7.8 +## explicit; go 1.23 github.com/hashicorp/go-retryablehttp # github.com/huandu/xstrings v1.5.0 ## explicit; go 1.12 @@ -70,11 +73,14 @@ github.com/kyoh86/xdg # github.com/launchdarkly/api-client-go/v15 v15.1.0 ## explicit; go 1.13 github.com/launchdarkly/api-client-go/v15 +# github.com/launchdarkly/api-client-go/v17 v17.2.0 +## explicit; go 1.13 +github.com/launchdarkly/api-client-go/v17 # github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f ## explicit github.com/launchdarkly/json-patch -# github.com/launchdarkly/ld-find-code-refs/v2 v2.13.0 -## explicit; go 1.22 +# github.com/launchdarkly/ld-find-code-refs/v2 v2.14.0 +## explicit; go 1.24 github.com/launchdarkly/ld-find-code-refs/v2/aliases github.com/launchdarkly/ld-find-code-refs/v2/flags github.com/launchdarkly/ld-find-code-refs/v2/internal/helpers @@ -84,10 +90,13 @@ github.com/launchdarkly/ld-find-code-refs/v2/internal/validation github.com/launchdarkly/ld-find-code-refs/v2/internal/version github.com/launchdarkly/ld-find-code-refs/v2/options github.com/launchdarkly/ld-find-code-refs/v2/search +# github.com/mattn/go-colorable v0.1.13 +## explicit; go 1.15 +github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/mattn/go-runewidth v0.0.9 +# github.com/mattn/go-runewidth v0.0.16 ## explicit; go 1.9 github.com/mattn/go-runewidth # github.com/mitchellh/copystructure v1.2.0 @@ -102,9 +111,21 @@ github.com/monochromegane/go-gitignore # github.com/morikuni/aec v1.0.0 ## explicit github.com/morikuni/aec -# github.com/olekukonko/tablewriter v0.0.5 -## explicit; go 1.12 +# github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 +## explicit; go 1.21 +github.com/olekukonko/errors +# github.com/olekukonko/ll v0.0.8 +## explicit; go 1.21 +github.com/olekukonko/ll +github.com/olekukonko/ll/lh +github.com/olekukonko/ll/lx +# github.com/olekukonko/tablewriter v1.0.8 +## explicit; go 1.21 github.com/olekukonko/tablewriter +github.com/olekukonko/tablewriter/pkg/twwarp +github.com/olekukonko/tablewriter/pkg/twwidth +github.com/olekukonko/tablewriter/renderer +github.com/olekukonko/tablewriter/tw # github.com/pelletier/go-toml/v2 v2.2.3 ## explicit; go 1.21.0 github.com/pelletier/go-toml/v2 @@ -115,8 +136,8 @@ github.com/pelletier/go-toml/v2/unstable # github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 ## explicit; go 1.15 github.com/petar-dambovaliev/aho-corasick -# github.com/pjbgf/sha1cd v0.3.0 -## explicit; go 1.19 +# github.com/pjbgf/sha1cd v0.3.2 +## explicit; go 1.21 github.com/pjbgf/sha1cd github.com/pjbgf/sha1cd/internal github.com/pjbgf/sha1cd/ubc @@ -126,6 +147,9 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib +# github.com/rivo/uniseg v0.2.0 +## explicit; go 1.12 +github.com/rivo/uniseg # github.com/sagikazarmark/locafero v0.7.0 ## explicit; go 1.21 github.com/sagikazarmark/locafero @@ -149,7 +173,7 @@ github.com/spf13/afero/mem # github.com/spf13/cast v1.7.1 ## explicit; go 1.19 github.com/spf13/cast -# github.com/spf13/pflag v1.0.6 +# github.com/spf13/pflag v1.0.7 ## explicit; go 1.12 github.com/spf13/pflag # github.com/spf13/viper v1.20.1 @@ -168,16 +192,61 @@ github.com/stretchr/testify/require # github.com/subosito/gotenv v1.6.0 ## explicit; go 1.18 github.com/subosito/gotenv +# github.com/tetratelabs/wazero v1.9.0 +## explicit; go 1.22.0 +github.com/tetratelabs/wazero +github.com/tetratelabs/wazero/api +github.com/tetratelabs/wazero/experimental +github.com/tetratelabs/wazero/experimental/sys +github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1 +github.com/tetratelabs/wazero/internal/descriptor +github.com/tetratelabs/wazero/internal/engine/interpreter +github.com/tetratelabs/wazero/internal/engine/wazevo +github.com/tetratelabs/wazero/internal/engine/wazevo/backend +github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64 +github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64 +github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc +github.com/tetratelabs/wazero/internal/engine/wazevo/frontend +github.com/tetratelabs/wazero/internal/engine/wazevo/ssa +github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi +github.com/tetratelabs/wazero/internal/expctxkeys +github.com/tetratelabs/wazero/internal/filecache +github.com/tetratelabs/wazero/internal/fsapi +github.com/tetratelabs/wazero/internal/ieee754 +github.com/tetratelabs/wazero/internal/internalapi +github.com/tetratelabs/wazero/internal/leb128 +github.com/tetratelabs/wazero/internal/moremath +github.com/tetratelabs/wazero/internal/platform +github.com/tetratelabs/wazero/internal/sock +github.com/tetratelabs/wazero/internal/sys +github.com/tetratelabs/wazero/internal/sysfs +github.com/tetratelabs/wazero/internal/u32 +github.com/tetratelabs/wazero/internal/u64 +github.com/tetratelabs/wazero/internal/version +github.com/tetratelabs/wazero/internal/wasip1 +github.com/tetratelabs/wazero/internal/wasm +github.com/tetratelabs/wazero/internal/wasm/binary +github.com/tetratelabs/wazero/internal/wasmdebug +github.com/tetratelabs/wazero/internal/wasmruntime +github.com/tetratelabs/wazero/sys # github.com/wacul/ptr v1.0.0 ## explicit github.com/wacul/ptr +# github.com/wasilibs/go-re2 v1.10.0 +## explicit; go 1.22.0 +github.com/wasilibs/go-re2 +github.com/wasilibs/go-re2/internal +github.com/wasilibs/go-re2/internal/cre2 +# github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 +## explicit; go 1.20 +github.com/wasilibs/wazero-helpers/allocator # go.uber.org/atomic v1.9.0 ## explicit; go 1.13 go.uber.org/atomic # go.uber.org/multierr v1.9.0 ## explicit; go 1.19 go.uber.org/multierr -# golang.org/x/crypto v0.35.0 +# golang.org/x/crypto v0.41.0 ## explicit; go 1.23.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish @@ -187,12 +256,12 @@ golang.org/x/crypto/scrypt ## explicit; go 1.23.0 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sys v0.30.0 -## explicit; go 1.18 +# golang.org/x/sys v0.35.0 +## explicit; go 1.23.0 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/text v0.22.0 -## explicit; go 1.18 +# golang.org/x/text v0.28.0 +## explicit; go 1.23.0 golang.org/x/text/encoding golang.org/x/text/encoding/internal golang.org/x/text/encoding/internal/identifier @@ -201,8 +270,8 @@ golang.org/x/text/internal/utf8internal golang.org/x/text/runes golang.org/x/text/transform golang.org/x/text/unicode/norm -# golang.org/x/tools v0.28.0 -## explicit; go 1.22.0 +# golang.org/x/tools v0.36.0 +## explicit; go 1.23.0 golang.org/x/tools/godoc/util golang.org/x/tools/godoc/vfs # gopkg.in/yaml.v2 v2.4.0 From 06e2b29590bcf8d472ce9c64bb80b9bff7e50103 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:16:37 +0200 Subject: [PATCH 22/35] chore(deps): bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 (#174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.

Release notes

Sourced from github.com/go-viper/mapstructure/v2's releases.

v2.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0

Commits
  • 8c61ec1 Merge pull request #80 from rostislaved/feature-allow-unset-pointer
  • df765f4 Merge pull request #106 from go-viper/update-linter
  • 5f34b05 update linter
  • 36de1e1 Merge pull request #105 from go-viper/error-refactor
  • 6a283a3 chore: update error type doc
  • 599cb73 Merge pull request #101 from go-viper/dependabot/github_actions/github/codeql...
  • ed3f921 feat: remove value from error messages
  • a3f8b22 revert: error message change
  • 9661f6d feat: add common error interface
  • f12f6c7 Merge pull request #102 from m1k1o/prettify-errors2
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-viper/mapstructure/v2&package-manager=go_modules&previous-version=2.2.1&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/launchdarkly/find-code-references-in-pull-request/network/alerts).
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Isabelle Miller From 85e70d753c836812e79bb689affd9f2880d7671c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 17:06:05 +0200 Subject: [PATCH 23/35] chore(deps): bump github.com/go-viper/mapstructure/v2 from 2.3.0 to 2.4.0 (#179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.3.0 to 2.4.0.
Release notes

Sourced from github.com/go-viper/mapstructure/v2's releases.

v2.4.0

What's Changed

New Contributors

Full Changelog: https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-viper/mapstructure/v2&package-manager=go_modules&previous-version=2.3.0&new-version=2.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/launchdarkly/find-code-references-in-pull-request/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- .../go-viper/mapstructure/v2/.golangci.yaml | 9 + .../go-viper/mapstructure/v2/README.md | 2 +- .../go-viper/mapstructure/v2/decode_hooks.go | 214 +++++++++++------- .../go-viper/mapstructure/v2/errors.go | 170 ++++++++++++++ .../go-viper/mapstructure/v2/mapstructure.go | 98 ++++---- vendor/modules.txt | 2 +- 8 files changed, 370 insertions(+), 131 deletions(-) diff --git a/go.mod b/go.mod index d1521ccd..cf27a3d1 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect github.com/fatih/color v1.16.0 // indirect - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/launchdarkly/api-client-go/v17 v17.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect diff --git a/go.sum b/go.sum index ddc96569..1b4ef56d 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lo github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml index ec1680b3..bda96256 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml +++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -37,3 +37,12 @@ formatters: - standard - default - localmodule + gofmt: + simplify: true + rewrite-rules: + - pattern: interface{} + replacement: any + + exclusions: + paths: + - internal/ diff --git a/vendor/github.com/go-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md index bc4be08e..45db7197 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/README.md +++ b/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -1,7 +1,7 @@ # mapstructure [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure) +[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2) diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go index 57c6de69..a852a0a0 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -13,7 +13,7 @@ import ( "time" ) -// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into the proper DecodeHookFunc type, such as DecodeHookFuncType. func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Create variables here so we can reference them with the reflect pkg @@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Fill in the variables into this interface and the rest is done // automatically using the reflect package. - potential := []interface{}{f1, f2, f3} + potential := []any{f1, f2, f3} v := reflect.ValueOf(h) vt := v.Type() @@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { return nil } -// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into a closure to be used directly // if the type fails to convert we return a closure always erroring to keep the previous behaviour -func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) { +func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Type(), to.Type(), from.Interface()) } case DecodeHookFuncKind: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Kind(), to.Kind(), from.Interface()) } case DecodeHookFuncValue: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from, to) } default: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return nil, errors.New("invalid decode hook signature") } } @@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va func DecodeHookExec( raw DecodeHookFunc, from reflect.Value, to reflect.Value, -) (interface{}, error) { +) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: return f(from.Type(), to.Type(), from.Interface()) @@ -86,11 +86,11 @@ func DecodeHookExec( // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs)) for _, f := range fs { cached = append(cached, cachedDecodeHook(f)) } - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { var err error data := f.Interface() @@ -114,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff)) for _, f := range ff { cached = append(cached, cachedDecodeHook(f)) } - return func(a, b reflect.Value) (interface{}, error) { + return func(a, b reflect.Value) (any, error) { var allErrs string - var out interface{} + var out any var err error for _, c := range cached { @@ -143,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -161,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { } } +// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc]. +// +// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice. +// This function removes that check. +func StringToWeakSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts // strings to time.Duration. func StringToTimeDurationHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -177,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc { } // Convert it by parsing - return time.ParseDuration(data.(string)) + d, err := time.ParseDuration(data.(string)) + + return d, wrapTimeParseDurationError(err) + } +} + +// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts +// strings to *time.Location. +func StringToTimeLocationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Local) { + return data, nil + } + d, err := time.LoadLocation(data.(string)) + + return d, wrapTimeParseLocationError(err) } } @@ -187,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -197,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc { } // Convert it by parsing - return url.Parse(data.(string)) + u, err := url.Parse(data.(string)) + + return u, wrapUrlError(err) } } @@ -207,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -219,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc { // Convert it by parsing ip := net.ParseIP(data.(string)) if ip == nil { - return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + return net.IP{}, fmt.Errorf("failed parsing ip") } return ip, nil @@ -232,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -243,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc { // Convert it by parsing _, net, err := net.ParseCIDR(data.(string)) - return net, err + return net, wrapNetParseError(err) } } @@ -253,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -263,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { } // Convert it by parsing - return time.Parse(layout, data.(string)) + ti, err := time.Parse(layout, data.(string)) + + return ti, wrapTimeParseError(err) } } @@ -275,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { func WeaklyTypedHook( f reflect.Kind, t reflect.Kind, - data interface{}, -) (interface{}, error) { + data any, +) (any, error) { dataVal := reflect.ValueOf(data) switch t { case reflect.String: @@ -305,17 +354,17 @@ func WeaklyTypedHook( } func RecursiveStructToMapHookFunc() DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { if f.Kind() != reflect.Struct { return f.Interface(), nil } - var i interface{} = struct{}{} + var i any = struct{}{} if t.Type() != reflect.TypeOf(&i).Elem() { return f.Interface(), nil } - m := make(map[string]interface{}) + m := make(map[string]any) t.Set(reflect.ValueOf(m)) return f.Interface(), nil @@ -329,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -356,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -366,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddr(data.(string)) + addr, err := netip.ParseAddr(data.(string)) + + return addr, wrapNetIPParseAddrError(err) } } @@ -376,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -386,7 +437,9 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddrPort(data.(string)) + addrPort, err := netip.ParseAddrPort(data.(string)) + + return addrPort, wrapNetIPParseAddrPortError(err) } } @@ -396,8 +449,8 @@ func StringToNetIPPrefixHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -406,7 +459,9 @@ func StringToNetIPPrefixHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParsePrefix(data.(string)) + prefix, err := netip.ParsePrefix(data.(string)) + + return prefix, wrapNetIPParsePrefixError(err) } } @@ -439,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc { // StringToInt8HookFunc returns a DecodeHookFunc that converts // strings to int8. func StringToInt8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int8 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 8) - return int8(i64), err + return int8(i64), wrapStrconvNumError(err) } } // StringToUint8HookFunc returns a DecodeHookFunc that converts // strings to uint8. func StringToUint8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 8) - return uint8(u64), err + return uint8(u64), wrapStrconvNumError(err) } } // StringToInt16HookFunc returns a DecodeHookFunc that converts // strings to int16. func StringToInt16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int16 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 16) - return int16(i64), err + return int16(i64), wrapStrconvNumError(err) } } // StringToUint16HookFunc returns a DecodeHookFunc that converts // strings to uint16. func StringToUint16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 16) - return uint16(u64), err + return uint16(u64), wrapStrconvNumError(err) } } // StringToInt32HookFunc returns a DecodeHookFunc that converts // strings to int32. func StringToInt32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int32 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 32) - return int32(i64), err + return int32(i64), wrapStrconvNumError(err) } } // StringToUint32HookFunc returns a DecodeHookFunc that converts // strings to uint32. func StringToUint32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 32) - return uint32(u64), err + return uint32(u64), wrapStrconvNumError(err) } } // StringToInt64HookFunc returns a DecodeHookFunc that converts // strings to int64. func StringToInt64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int64 { return data, nil } // Convert it by parsing - return strconv.ParseInt(data.(string), 0, 64) + i64, err := strconv.ParseInt(data.(string), 0, 64) + return int64(i64), wrapStrconvNumError(err) } } // StringToUint64HookFunc returns a DecodeHookFunc that converts // strings to uint64. func StringToUint64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 { return data, nil } // Convert it by parsing - return strconv.ParseUint(data.(string), 0, 64) + u64, err := strconv.ParseUint(data.(string), 0, 64) + return uint64(u64), wrapStrconvNumError(err) } } // StringToIntHookFunc returns a DecodeHookFunc that converts // strings to int. func StringToIntHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 0) - return int(i64), err + return int(i64), wrapStrconvNumError(err) } } // StringToUintHookFunc returns a DecodeHookFunc that converts // strings to uint. func StringToUintHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 0) - return uint(u64), err + return uint(u64), wrapStrconvNumError(err) } } // StringToFloat32HookFunc returns a DecodeHookFunc that converts // strings to float32. func StringToFloat32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float32 { return data, nil } // Convert it by parsing f64, err := strconv.ParseFloat(data.(string), 32) - return float32(f64), err + return float32(f64), wrapStrconvNumError(err) } } // StringToFloat64HookFunc returns a DecodeHookFunc that converts // strings to float64. func StringToFloat64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float64 { return data, nil } // Convert it by parsing - return strconv.ParseFloat(data.(string), 64) + f64, err := strconv.ParseFloat(data.(string), 64) + return f64, wrapStrconvNumError(err) } } // StringToBoolHookFunc returns a DecodeHookFunc that converts // strings to bool. func StringToBoolHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Bool { return data, nil } // Convert it by parsing - return strconv.ParseBool(data.(string)) + b, err := strconv.ParseBool(data.(string)) + return b, wrapStrconvNumError(err) } } @@ -629,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc { // StringToComplex64HookFunc returns a DecodeHookFunc that converts // strings to complex64. func StringToComplex64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 { return data, nil } // Convert it by parsing c128, err := strconv.ParseComplex(data.(string), 64) - return complex64(c128), err + return complex64(c128), wrapStrconvNumError(err) } } // StringToComplex128HookFunc returns a DecodeHookFunc that converts // strings to complex128. func StringToComplex128HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 { return data, nil } // Convert it by parsing - return strconv.ParseComplex(data.(string), 128) + c128, err := strconv.ParseComplex(data.(string), 128) + return c128, wrapStrconvNumError(err) } } diff --git a/vendor/github.com/go-viper/mapstructure/v2/errors.go b/vendor/github.com/go-viper/mapstructure/v2/errors.go index 31a3edfb..07d31c22 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/errors.go +++ b/vendor/github.com/go-viper/mapstructure/v2/errors.go @@ -1,8 +1,14 @@ package mapstructure import ( + "errors" "fmt" + "net" + "net/url" "reflect" + "strconv" + "strings" + "time" ) // Error interface is implemented by all errors emitted by mapstructure. @@ -72,3 +78,167 @@ func (e *UnconvertibleTypeError) Error() string { } func (*UnconvertibleTypeError) mapstructure() {} + +func wrapStrconvNumError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*strconv.NumError); ok { + return &strconvNumError{Err: err} + } + + return err +} + +type strconvNumError struct { + Err *strconv.NumError +} + +func (e *strconvNumError) Error() string { + return "strconv." + e.Err.Func + ": " + e.Err.Err.Error() +} + +func (e *strconvNumError) Unwrap() error { return e.Err } + +func wrapUrlError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*url.Error); ok { + return &urlError{Err: err} + } + + return err +} + +type urlError struct { + Err *url.Error +} + +func (e *urlError) Error() string { + return fmt.Sprintf("%s", e.Err.Err) +} + +func (e *urlError) Unwrap() error { return e.Err } + +func wrapNetParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*net.ParseError); ok { + return &netParseError{Err: err} + } + + return err +} + +type netParseError struct { + Err *net.ParseError +} + +func (e *netParseError) Error() string { + return "invalid " + e.Err.Type +} + +func (e *netParseError) Unwrap() error { return e.Err } + +func wrapTimeParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*time.ParseError); ok { + return &timeParseError{Err: err} + } + + return err +} + +type timeParseError struct { + Err *time.ParseError +} + +func (e *timeParseError) Error() string { + if e.Err.Message == "" { + return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem) + } + + return "parsing time " + e.Err.Message +} + +func (e *timeParseError) Unwrap() error { return e.Err } + +func wrapNetIPParseAddrError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapNetIPParseAddrPortError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "invalid port ") { + return errors.New("invalid port") + } else if strings.HasPrefix(errMsg, "invalid ip:port ") { + return errors.New("invalid ip:port") + } + + return err +} + +func wrapNetIPParsePrefixError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapTimeParseDurationError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "time: unknown unit ") { + return errors.New("time: unknown unit") + } else if strings.HasPrefix(errMsg, "time: ") { + idx := strings.LastIndex(errMsg, " ") + + return errors.New(errMsg[:idx]) + } + + return err +} + +func wrapTimeParseLocationError(err error) error { + if err == nil { + return nil + } + errMsg := err.Error() + if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") { + return fmt.Errorf("invalid time zone format: %w", err) + } + + return err +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index 4b738a3a..7c35bce0 100644 --- a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -1,5 +1,5 @@ // Package mapstructure exposes functionality to convert one arbitrary -// Go type into another, typically to convert a map[string]interface{} +// Go type into another, typically to convert a map[string]any // into a native Go structure. // // The Go structure can be arbitrarily complex, containing slices, @@ -54,8 +54,8 @@ // // This would require an input that looks like below: // -// map[string]interface{}{ -// "person": map[string]interface{}{"name": "alice"}, +// map[string]any{ +// "person": map[string]any{"name": "alice"}, // } // // If your "person" value is NOT nested, then you can append ",squash" to @@ -68,7 +68,7 @@ // // Now the following input would be accepted: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -79,7 +79,7 @@ // // Will be decoded into a map: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -95,18 +95,18 @@ // // You can also use the ",remain" suffix on your tag to collect all unused // values in a map. The field with this tag MUST be a map type and should -// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// probably be a "map[string]any" or "map[any]any". // See example below: // // type Friend struct { // Name string -// Other map[string]interface{} `mapstructure:",remain"` +// Other map[string]any `mapstructure:",remain"` // } // // Given the input below, Other would be populated with the other // values that weren't used (everything but "name"): // -// map[string]interface{}{ +// map[string]any{ // "name": "bob", // "address": "123 Maple St.", // } @@ -161,7 +161,7 @@ // // Using this map as input: // -// map[string]interface{}{ +// map[string]any{ // "private": "I will be ignored", // "Public": "I made it through!", // } @@ -204,19 +204,19 @@ import ( // we started with Kinds and then realized Types were the better solution, // but have a promise to not break backwards compat so we now support // both. -type DecodeHookFunc interface{} +type DecodeHookFunc any // DecodeHookFuncType is a DecodeHookFunc which has complete information about // the source and target types. -type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) +type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error) // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the // source and target types. -type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error) // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target // values. -type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error) // DecoderConfig is the configuration that is used to create a new decoder // and allows customization of various aspects of decoding. @@ -287,7 +287,7 @@ type DecoderConfig struct { // Result is a pointer to the struct that will contain the decoded // value. - Result interface{} + Result any // The tag name that mapstructure reads for field names. This // defaults to "mapstructure" @@ -319,7 +319,7 @@ type DecoderConfig struct { // up the most basic Decoder. type Decoder struct { config *DecoderConfig - cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error) + cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error) } // Metadata contains information about decoding a structure that @@ -340,7 +340,7 @@ type Metadata struct { // Decode takes an input structure and uses reflection to translate it to // the output structure. output must be a pointer to a map or struct. -func Decode(input interface{}, output interface{}) error { +func Decode(input any, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -356,7 +356,7 @@ func Decode(input interface{}, output interface{}) error { // WeakDecode is the same as Decode but is shorthand to enable // WeaklyTypedInput. See DecoderConfig for more info. -func WeakDecode(input, output interface{}) error { +func WeakDecode(input, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -373,7 +373,7 @@ func WeakDecode(input, output interface{}) error { // DecodeMetadata is the same as Decode, but is shorthand to // enable metadata collection. See DecoderConfig for more info. -func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func DecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -390,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e // WeakDecodeMetadata is the same as Decode, but is shorthand to // enable both WeaklyTypedInput and metadata collection. See // DecoderConfig for more info. -func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func WeakDecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -457,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { // Decode decodes the given raw interface to the target pointer specified // by the configuration. -func (d *Decoder) Decode(input interface{}) error { +func (d *Decoder) Decode(input any) error { err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) // Retain some of the original behavior when multiple errors ocurr @@ -470,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error { } // isNil returns true if the input is nil or a typed nil pointer. -func isNil(input interface{}) bool { +func isNil(input any) bool { if input == nil { return true } @@ -479,7 +479,7 @@ func isNil(input interface{}) bool { } // Decodes an unknown data type into a specific reflection value. -func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { +func (d *Decoder) decode(name string, input any, outVal reflect.Value) error { var ( inputVal = reflect.ValueOf(input) outputKind = getKind(outVal) @@ -516,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // Hooks need a valid inputVal, so reset it to zero value of outVal type. switch outputKind { case reflect.Struct, reflect.Map: - var mapVal map[string]interface{} + var mapVal map[string]any inputVal = reflect.ValueOf(mapVal) // create nil map pointer case reflect.Slice, reflect.Array: - var sliceVal []interface{} + var sliceVal []any inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer default: inputVal = reflect.Zero(outVal.Type()) @@ -583,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // This decodes a basic type (bool, int, string, etc.) and sets the // value to "data" of that type. -func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error { if val.IsValid() && val.Elem().IsValid() { elem := val.Elem() @@ -640,7 +640,7 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) return nil } -func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeString(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -693,7 +693,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) return nil } -func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -724,7 +724,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er return newDecodeError(name, &ParseError{ Expected: val, Value: data, - Err: err, + Err: wrapStrconvNumError(err), }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": @@ -748,7 +748,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er return nil } -func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -795,7 +795,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e return newDecodeError(name, &ParseError{ Expected: val, Value: data, - Err: err, + Err: wrapStrconvNumError(err), }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": @@ -805,7 +805,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e return newDecodeError(name, &ParseError{ Expected: val, Value: data, - Err: err, + Err: wrapStrconvNumError(err), }) } val.SetUint(i) @@ -819,7 +819,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e return nil } -func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -842,7 +842,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e return newDecodeError(name, &ParseError{ Expected: val, Value: data, - Err: err, + Err: wrapStrconvNumError(err), }) } default: @@ -855,7 +855,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e return nil } -func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -886,7 +886,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) return newDecodeError(name, &ParseError{ Expected: val, Value: data, - Err: err, + Err: wrapStrconvNumError(err), }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": @@ -910,7 +910,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) return nil } -func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -927,7 +927,7 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value return nil } -func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error { valType := val.Type() valKeyType := valType.Key() valElemType := valType.Elem() @@ -1176,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re return nil } -func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { +func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) { // If the input data is nil, then we want to just set the output // pointer to be nil as well. isNil := data == nil @@ -1223,7 +1223,7 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b return false, nil } -func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error { // Create an element of the concrete (non pointer) type and decode // into that. Then set the value of the pointer to this type. dataVal := reflect.Indirect(reflect.ValueOf(data)) @@ -1237,7 +1237,7 @@ func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) e return nil } -func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1259,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return nil } // Create slice of maps of other sizes - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: return d.decodeSlice(name, []byte(dataVal.String()), val) @@ -1268,7 +1268,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string slice. default: // Just re-try this function with data as a slice. - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) } } @@ -1311,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1336,7 +1336,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string array. default: // Just re-try this function with data as a slice. - return d.decodeArray(name, []interface{}{data}, val) + return d.decodeArray(name, []any{data}, val) } } @@ -1372,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) // If the type of the value to write to and the data match directly, @@ -1393,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) // as an intermediary. // Make a new map to hold our result - mapType := reflect.TypeOf((map[string]interface{})(nil)) + mapType := reflect.TypeOf((map[string]any)(nil)) mval := reflect.MakeMap(mapType) // Creating a pointer to a map so that other methods can completely @@ -1424,13 +1424,13 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } dataValKeys := make(map[reflect.Value]struct{}) - dataValKeysUnused := make(map[interface{}]struct{}) + dataValKeysUnused := make(map[any]struct{}) for _, dataValKey := range dataVal.MapKeys() { dataValKeys[dataValKey] = struct{}{} dataValKeysUnused[dataValKey.Interface()] = struct{}{} } - targetValKeysUnused := make(map[interface{}]struct{}) + targetValKeysUnused := make(map[any]struct{}) var errs []error @@ -1583,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // we put the unused keys directly into the remain field. if remainField != nil && len(dataValKeysUnused) > 0 { // Build a map of only the unused values - remain := map[interface{}]interface{}{} + remain := map[any]any{} for key := range dataValKeysUnused { remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() } diff --git a/vendor/modules.txt b/vendor/modules.txt index 4678b2f0..1d6be84d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -27,7 +27,7 @@ github.com/fsnotify/fsnotify/internal ## explicit; go 1.23.0 github.com/go-git/go-git/v5/plumbing github.com/go-git/go-git/v5/plumbing/hash -# github.com/go-viper/mapstructure/v2 v2.3.0 +# github.com/go-viper/mapstructure/v2 v2.4.0 ## explicit; go 1.18 github.com/go-viper/mapstructure/v2 github.com/go-viper/mapstructure/v2/internal/errors From e84aaa912aec198af3e11010f3188b314bd32eb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 14:13:24 +0200 Subject: [PATCH 24/35] chore(deps): bump github.com/stretchr/testify from 1.10.0 to 1.11.0 (#180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.10.0 to 1.11.0.
Release notes

Sourced from github.com/stretchr/testify's releases.

v1.11.0

What's Changed

Functional Changes

v1.11.0 Includes a number of performance improvements.

Fixes

Documentation, Build & CI

... (truncated)

Commits
  • b7801fb Merge pull request #1778 from stretchr/dependabot/github_actions/actions/chec...
  • 69831f3 build(deps): bump actions/checkout from 4 to 5
  • a53be35 Improve captureTestingT helper
  • aafb604 mock: improve formatting of error message
  • 7218e03 improve error msg
  • 929a212 Merge pull request #1758 from stretchr/dolmen/suite-faster-method-filtering
  • bc7459e suite: faster filtering of methods (-testify.m)
  • 7d37b5c suite: refactor methodFilter
  • c58bc90 Merge pull request #1764 from stretchr/dolmen/suite-refactor-stats-for-readab...
  • 87101a6 suite.Run: refactor handling of stats
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/stretchr/testify&package-manager=go_modules&previous-version=1.10.0&new-version=1.11.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- .../testify/assert/assertion_compare.go | 22 +- .../testify/assert/assertion_format.go | 51 ++- .../testify/assert/assertion_forward.go | 102 +++-- .../testify/assert/assertion_order.go | 2 +- .../stretchr/testify/assert/assertions.go | 367 ++++++++++++------ .../github.com/stretchr/testify/assert/doc.go | 4 + .../testify/assert/http_assertions.go | 4 +- .../testify/assert/yaml/yaml_custom.go | 1 - .../testify/assert/yaml/yaml_default.go | 1 - .../stretchr/testify/assert/yaml/yaml_fail.go | 1 - .../stretchr/testify/require/doc.go | 2 + .../stretchr/testify/require/require.go | 108 ++++-- .../testify/require/require_forward.go | 102 +++-- vendor/modules.txt | 2 +- 16 files changed, 538 insertions(+), 237 deletions(-) diff --git a/go.mod b/go.mod index cf27a3d1..cfa76f64 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 golang.org/x/oauth2 v0.30.0 ) diff --git a/go.sum b/go.sum index 1b4ef56d..ed77aed0 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqj github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index 7e19eba0..ffb24e8e 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -390,7 +390,8 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface if h, ok := t.(tHelper); ok { h.Helper() } - return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2) + return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, failMessage, msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second @@ -403,7 +404,8 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in if h, ok := t.(tHelper); ok { h.Helper() } - return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2) + return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, failMessage, msgAndArgs...) } // Less asserts that the first element is less than the second @@ -415,7 +417,8 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) if h, ok := t.(tHelper); ok { h.Helper() } - return compareTwoValues(t, e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2) + return compareTwoValues(t, e1, e2, []compareResult{compareLess}, failMessage, msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second @@ -428,7 +431,8 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter if h, ok := t.(tHelper); ok { h.Helper() } - return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2) + return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, failMessage, msgAndArgs...) } // Positive asserts that the specified element is positive @@ -440,7 +444,8 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { h.Helper() } zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not positive", e) + return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, failMessage, msgAndArgs...) } // Negative asserts that the specified element is negative @@ -452,7 +457,8 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { h.Helper() } zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...) + failMessage := fmt.Sprintf("\"%v\" is not negative", e) + return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, failMessage, msgAndArgs...) } func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool { @@ -468,11 +474,11 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare compareResult, isComparable := compare(e1, e2, e1Kind) if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + return Fail(t, fmt.Sprintf(`Can not compare type "%T"`, e1), msgAndArgs...) } if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...) + return Fail(t, failMessage, msgAndArgs...) } return true diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 19063416..c592f6ad 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -50,10 +50,19 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Emptyf asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // assert.Emptyf(t, obj, "error message %s", "formatted") +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -117,10 +126,8 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// assert.Errorf(t, err, "error message %s", "formatted") func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -438,7 +445,19 @@ func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interf return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) } +// IsNotTypef asserts that the specified objects are not of the same type. +// +// assert.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") +func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsNotType(t, theType, object, append([]interface{}{msg}, args...)...) +} + // IsTypef asserts that the specified objects are of the same type. +// +// assert.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted") func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -585,8 +604,7 @@ func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg str return NotElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmptyf asserts that the specified object is NOT [Empty]. // // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) @@ -693,12 +711,15 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") // assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -782,11 +803,15 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subsetf asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") // assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 21629087..58db9284 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -92,10 +92,19 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st return ElementsMatchf(a.t, listA, listB, msg, args...) } -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Empty asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // a.Empty(obj) +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -103,10 +112,19 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { return Empty(a.t, object, msgAndArgs...) } -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Emptyf asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // a.Emptyf(obj, "error message %s", "formatted") +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -224,10 +242,8 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// a.Error(err) func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -297,10 +313,8 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// a.Errorf(err, "error message %s", "formatted") func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -868,7 +882,29 @@ func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...in return IsNonIncreasingf(a.t, object, msg, args...) } +// IsNotType asserts that the specified objects are not of the same type. +// +// a.IsNotType(&NotMyStruct{}, &MyStruct{}) +func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNotType(a.t, theType, object, msgAndArgs...) +} + +// IsNotTypef asserts that the specified objects are not of the same type. +// +// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") +func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNotTypef(a.t, theType, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. +// +// a.IsType(&MyStruct{}, &MyStruct{}) func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -877,6 +913,8 @@ func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAnd } // IsTypef asserts that the specified objects are of the same type. +// +// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted") func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1162,8 +1200,7 @@ func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg return NotElementsMatchf(a.t, listA, listB, msg, args...) } -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmpty asserts that the specified object is NOT [Empty]. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) @@ -1175,8 +1212,7 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo return NotEmpty(a.t, object, msgAndArgs...) } -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmptyf asserts that the specified object is NOT [Empty]. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) @@ -1378,12 +1414,15 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubset asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.NotSubset([1, 3, 4], [1, 2]) // a.NotSubset({"x": 1, "y": 2}, {"z": 3}) +// a.NotSubset([1, 3, 4], {1: "one", 2: "two"}) +// a.NotSubset({"x": 1, "y": 2}, ["z"]) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1391,12 +1430,15 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") // a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1556,11 +1598,15 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subset asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.Subset([1, 2, 3], [1, 2]) // a.Subset({"x": 1, "y": 2}, {"x": 1}) +// a.Subset([1, 2, 3], {1: "one", 2: "two"}) +// a.Subset({"x": 1, "y": 2}, ["x"]) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1568,11 +1614,15 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subsetf asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") // a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") +// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go index 1d2f7182..2fdf80fd 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_order.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -33,7 +33,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareR compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) + return Fail(t, fmt.Sprintf(`Can not compare type "%T" and "%T"`, value, prevValue), msgAndArgs...) } if !containsValue(allowedComparesResults, compareResult) { diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 4e91332b..de8de0cb 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -210,59 +210,77 @@ the problem actually occurred in calling code.*/ // of each stack frame leading from the current test to the assert call that // failed. func CallerInfo() []string { - var pc uintptr - var ok bool var file string var line int var name string + const stackFrameBufferSize = 10 + pcs := make([]uintptr, stackFrameBufferSize) + callers := []string{} - for i := 0; ; i++ { - pc, file, line, ok = runtime.Caller(i) - if !ok { - // The breaks below failed to terminate the loop, and we ran off the - // end of the call stack. - break - } + offset := 1 - // This is a huge edge case, but it will panic if this is the case, see #180 - if file == "" { - break - } + for { + n := runtime.Callers(offset, pcs) - f := runtime.FuncForPC(pc) - if f == nil { - break - } - name = f.Name() - - // testing.tRunner is the standard library function that calls - // tests. Subtests are called directly by tRunner, without going through - // the Test/Benchmark/Example function that contains the t.Run calls, so - // with subtests we should break when we hit tRunner, without adding it - // to the list of callers. - if name == "testing.tRunner" { + if n == 0 { break } - parts := strings.Split(file, "/") - if len(parts) > 1 { - filename := parts[len(parts)-1] - dir := parts[len(parts)-2] - if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { - callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + frames := runtime.CallersFrames(pcs[:n]) + + for { + frame, more := frames.Next() + pc = frame.PC + file = frame.File + line = frame.Line + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break } - } - // Drop the package - segments := strings.Split(name, ".") - name = segments[len(segments)-1] - if isTest(name, "Test") || - isTest(name, "Benchmark") || - isTest(name, "Example") { - break + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + if len(parts) > 1 { + filename := parts[len(parts)-1] + dir := parts[len(parts)-2] + if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + } + + // Drop the package + dotPos := strings.LastIndexByte(name, '.') + name = name[dotPos+1:] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + + if !more { + break + } } + + // Next batch + offset += cap(pcs) } return callers @@ -437,17 +455,34 @@ func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, return true } +func isType(expectedType, object interface{}) bool { + return ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) +} + // IsType asserts that the specified objects are of the same type. -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { +// +// assert.IsType(t, &MyStruct{}, &MyStruct{}) +func IsType(t TestingT, expectedType, object interface{}, msgAndArgs ...interface{}) bool { + if isType(expectedType, object) { + return true + } if h, ok := t.(tHelper); ok { h.Helper() } + return Fail(t, fmt.Sprintf("Object expected to be of type %T, but was %T", expectedType, object), msgAndArgs...) +} - if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { - return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) +// IsNotType asserts that the specified objects are not of the same type. +// +// assert.IsNotType(t, &NotMyStruct{}, &MyStruct{}) +func IsNotType(t TestingT, theType, object interface{}, msgAndArgs ...interface{}) bool { + if !isType(theType, object) { + return true } - - return true + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Fail(t, fmt.Sprintf("Object type expected to be different than %T", theType), msgAndArgs...) } // Equal asserts that two objects are equal. @@ -475,7 +510,6 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) } return true - } // validateEqualArgs checks whether provided arguments can be safely used in the @@ -510,8 +544,9 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b if !same { // both are pointers but not the same type & pointing to the same address return Fail(t, fmt.Sprintf("Not same: \n"+ - "expected: %p %#v\n"+ - "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) + "expected: %p %#[1]v\n"+ + "actual : %p %#[2]v", + expected, actual), msgAndArgs...) } return true @@ -530,14 +565,14 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} same, ok := samePointers(expected, actual) if !ok { - //fails when the arguments are not pointers + // fails when the arguments are not pointers return !(Fail(t, "Both arguments must be pointers", msgAndArgs...)) } if same { return Fail(t, fmt.Sprintf( - "Expected and actual point to the same object: %p %#v", - expected, expected), msgAndArgs...) + "Expected and actual point to the same object: %p %#[1]v", + expected), msgAndArgs...) } return true } @@ -549,7 +584,7 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} func samePointers(first, second interface{}) (same bool, ok bool) { firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { - return false, false //not both are pointers + return false, false // not both are pointers } firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) @@ -610,7 +645,6 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa } return true - } // EqualExportedValues asserts that the types of two objects are equal and their public @@ -665,7 +699,6 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} } return Equal(t, expected, actual, msgAndArgs...) - } // NotNil asserts that the specified object is not nil. @@ -715,37 +748,45 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { // isEmpty gets whether the specified object is considered empty or not. func isEmpty(object interface{}) bool { - // get nil case out of the way if object == nil { return true } - objValue := reflect.ValueOf(object) + return isEmptyValue(reflect.ValueOf(object)) +} +// isEmptyValue gets whether the specified reflect.Value is considered empty or not. +func isEmptyValue(objValue reflect.Value) bool { + if objValue.IsZero() { + return true + } + // Special cases of non-zero values that we consider empty switch objValue.Kind() { // collection types are empty when they have no element + // Note: array types are empty when they match their zero-initialized state. case reflect.Chan, reflect.Map, reflect.Slice: return objValue.Len() == 0 - // pointers are empty if nil or if the value they point to is empty + // non-nil pointers are empty if the value they point to is empty case reflect.Ptr: - if objValue.IsNil() { - return true - } - deref := objValue.Elem().Interface() - return isEmpty(deref) - // for all other types, compare against the zero value - // array types are empty when they match their zero-initialized state - default: - zero := reflect.Zero(objValue.Type()) - return reflect.DeepEqual(object, zero.Interface()) + return isEmptyValue(objValue.Elem()) } + return false } -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Empty asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // assert.Empty(t, obj) +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := isEmpty(object) if !pass { @@ -756,11 +797,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } return pass - } -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmpty asserts that the specified object is NOT [Empty]. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) @@ -775,7 +814,6 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } return pass - } // getLen tries to get the length of an object. @@ -819,7 +857,6 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { } return true - } // False asserts that the specified value is false. @@ -834,7 +871,6 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { } return true - } // NotEqual asserts that the specified values are NOT equal. @@ -857,7 +893,6 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{ } return true - } // NotEqualValues asserts that two objects are not equal even when converted to the same type @@ -880,7 +915,6 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte // return (true, false) if element was not found. // return (true, true) if element was found. func containsElement(list interface{}, element interface{}) (ok, found bool) { - listValue := reflect.ValueOf(list) listType := reflect.TypeOf(list) if listType == nil { @@ -915,7 +949,6 @@ func containsElement(list interface{}, element interface{}) (ok, found bool) { } } return true, false - } // Contains asserts that the specified string, list(array, slice...) or map contains the @@ -938,7 +971,6 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo } return true - } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -961,14 +993,17 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } return true - } -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subset asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // assert.Subset(t, [1, 2, 3], [1, 2]) // assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) +// assert.Subset(t, [1, 2, 3], {1: "one", 2: "two"}) +// assert.Subset(t, {"x": 1, "y": 2}, ["x"]) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -983,7 +1018,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok } subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { + if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } @@ -1007,6 +1042,13 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok } subsetList := reflect.ValueOf(subset) + if subsetKind == reflect.Map { + keys := make([]interface{}, subsetList.Len()) + for idx, key := range subsetList.MapKeys() { + keys[idx] = key.Interface() + } + subsetList = reflect.ValueOf(keys) + } for i := 0; i < subsetList.Len(); i++ { element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) @@ -1021,12 +1063,15 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true } -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubset asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // assert.NotSubset(t, [1, 3, 4], [1, 2]) // assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) +// assert.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"}) +// assert.NotSubset(t, {"x": 1, "y": 2}, ["z"]) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1041,7 +1086,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) } subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { + if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } @@ -1065,11 +1110,18 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) } subsetList := reflect.ValueOf(subset) + if subsetKind == reflect.Map { + keys := make([]interface{}, subsetList.Len()) + for idx, key := range subsetList.MapKeys() { + keys[idx] = key.Interface() + } + subsetList = reflect.ValueOf(keys) + } for i := 0; i < subsetList.Len(); i++ { element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + return Fail(t, fmt.Sprintf("%q could not be applied builtin len()", list), msgAndArgs...) } if !found { return true @@ -1591,10 +1643,8 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// assert.Error(t, err) func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { if err == nil { if h, ok := t.(tHelper); ok { @@ -1667,7 +1717,6 @@ func matchRegexp(rx interface{}, str interface{}) bool { default: return r.MatchString(fmt.Sprint(v)) } - } // Regexp asserts that a specified regexp matches a string. @@ -1703,7 +1752,6 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf } return !match - } // Zero asserts that i is the zero value for its type. @@ -1814,6 +1862,11 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) } + // Shortcut if same bytes + if actual == expected { + return true + } + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) } @@ -1832,6 +1885,11 @@ func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) } + // Shortcut if same bytes + if actual == expected { + return true + } + if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) } @@ -1933,6 +1991,7 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t } ch := make(chan bool, 1) + checkCond := func() { ch <- condition() } timer := time.NewTimer(waitFor) defer timer.Stop() @@ -1940,18 +1999,23 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t ticker := time.NewTicker(tick) defer ticker.Stop() - for tick := ticker.C; ; { + var tickC <-chan time.Time + + // Check the condition once first on the initial call. + go checkCond() + + for { select { case <-timer.C: return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tick: - tick = nil - go func() { ch <- condition() }() + case <-tickC: + tickC = nil + go checkCond() case v := <-ch: if v { return true } - tick = ticker.C + tickC = ticker.C } } } @@ -1964,6 +2028,9 @@ type CollectT struct { errors []error } +// Helper is like [testing.T.Helper] but does nothing. +func (CollectT) Helper() {} + // Errorf collects the error. func (c *CollectT) Errorf(format string, args ...interface{}) { c.errors = append(c.errors, fmt.Errorf(format, args...)) @@ -2021,35 +2088,42 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time var lastFinishedTickErrs []error ch := make(chan *CollectT, 1) + checkCond := func() { + collect := new(CollectT) + defer func() { + ch <- collect + }() + condition(collect) + } + timer := time.NewTimer(waitFor) defer timer.Stop() ticker := time.NewTicker(tick) defer ticker.Stop() - for tick := ticker.C; ; { + var tickC <-chan time.Time + + // Check the condition once first on the initial call. + go checkCond() + + for { select { case <-timer.C: for _, err := range lastFinishedTickErrs { t.Errorf("%v", err) } return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tick: - tick = nil - go func() { - collect := new(CollectT) - defer func() { - ch <- collect - }() - condition(collect) - }() + case <-tickC: + tickC = nil + go checkCond() case collect := <-ch: if !collect.failed() { return true } // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. lastFinishedTickErrs = collect.errors - tick = ticker.C + tickC = ticker.C } } } @@ -2064,6 +2138,7 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D } ch := make(chan bool, 1) + checkCond := func() { ch <- condition() } timer := time.NewTimer(waitFor) defer timer.Stop() @@ -2071,18 +2146,23 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D ticker := time.NewTicker(tick) defer ticker.Stop() - for tick := ticker.C; ; { + var tickC <-chan time.Time + + // Check the condition once first on the initial call. + go checkCond() + + for { select { case <-timer.C: return true - case <-tick: - tick = nil - go func() { ch <- condition() }() + case <-tickC: + tickC = nil + go checkCond() case v := <-ch: if v { return Fail(t, "Condition satisfied", msgAndArgs...) } - tick = ticker.C + tickC = ticker.C } } } @@ -2100,9 +2180,12 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { var expectedText string if target != nil { expectedText = target.Error() + if err == nil { + return Fail(t, fmt.Sprintf("Expected error with %q in chain but got nil.", expectedText), msgAndArgs...) + } } - chain := buildErrorChainString(err) + chain := buildErrorChainString(err, false) return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ "expected: %q\n"+ @@ -2125,7 +2208,7 @@ func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { expectedText = target.Error() } - chain := buildErrorChainString(err) + chain := buildErrorChainString(err, false) return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ "found: %q\n"+ @@ -2143,11 +2226,17 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{ return true } - chain := buildErrorChainString(err) + expectedType := reflect.TypeOf(target).Elem().String() + if err == nil { + return Fail(t, fmt.Sprintf("An error is expected but got nil.\n"+ + "expected: %s", expectedType), msgAndArgs...) + } + + chain := buildErrorChainString(err, true) return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ - "expected: %q\n"+ - "in chain: %s", target, chain, + "expected: %s\n"+ + "in chain: %s", expectedType, chain, ), msgAndArgs...) } @@ -2161,24 +2250,46 @@ func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interfa return true } - chain := buildErrorChainString(err) + chain := buildErrorChainString(err, true) return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ - "found: %q\n"+ - "in chain: %s", target, chain, + "found: %s\n"+ + "in chain: %s", reflect.TypeOf(target).Elem().String(), chain, ), msgAndArgs...) } -func buildErrorChainString(err error) string { +func unwrapAll(err error) (errs []error) { + errs = append(errs, err) + switch x := err.(type) { + case interface{ Unwrap() error }: + err = x.Unwrap() + if err == nil { + return + } + errs = append(errs, unwrapAll(err)...) + case interface{ Unwrap() []error }: + for _, err := range x.Unwrap() { + errs = append(errs, unwrapAll(err)...) + } + } + return +} + +func buildErrorChainString(err error, withType bool) string { if err == nil { return "" } - e := errors.Unwrap(err) - chain := fmt.Sprintf("%q", err.Error()) - for e != nil { - chain += fmt.Sprintf("\n\t%q", e.Error()) - e = errors.Unwrap(e) + var chain string + errs := unwrapAll(err) + for i := range errs { + if i != 0 { + chain += "\n\t" + } + chain += fmt.Sprintf("%q", errs[i].Error()) + if withType { + chain += fmt.Sprintf(" (%T)", errs[i]) + } } return chain } diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go index 4953981d..a0b953aa 100644 --- a/vendor/github.com/stretchr/testify/assert/doc.go +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -1,5 +1,9 @@ // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // +// # Note +// +// All functions in this package return a bool value indicating whether the assertion has passed. +// // # Example Usage // // The following is a complete example using assert in a standard test function: diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index 861ed4b7..5a6bb75f 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -138,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) + Fail(t, fmt.Sprintf("Expected response body for %q to contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -158,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) + Fail(t, fmt.Sprintf("Expected response body for %q to NOT contain %q but found %q", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go index baa0cc7d..5a74c4f4 100644 --- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go +++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go @@ -1,5 +1,4 @@ //go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default -// +build testify_yaml_custom,!testify_yaml_fail,!testify_yaml_default // Package yaml is an implementation of YAML functions that calls a pluggable implementation. // diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go index b83c6cf6..0bae80e3 100644 --- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go +++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go @@ -1,5 +1,4 @@ //go:build !testify_yaml_fail && !testify_yaml_custom -// +build !testify_yaml_fail,!testify_yaml_custom // Package yaml is just an indirection to handle YAML deserialization. // diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go index e78f7dfe..8041803f 100644 --- a/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go +++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go @@ -1,5 +1,4 @@ //go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default -// +build testify_yaml_fail,!testify_yaml_custom,!testify_yaml_default // Package yaml is an implementation of YAML functions that always fail. // diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go index 96843472..c8e3f94a 100644 --- a/vendor/github.com/stretchr/testify/require/doc.go +++ b/vendor/github.com/stretchr/testify/require/doc.go @@ -23,6 +23,8 @@ // // The `require` package have same global functions as in the `assert` package, // but instead of returning a boolean result they call `t.FailNow()`. +// A consequence of this is that it must be called from the goroutine running +// the test function, not from other goroutines created during the test. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index d8921950..2d02f9bc 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -117,10 +117,19 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string t.FailNow() } -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Empty asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // require.Empty(t, obj) +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -131,10 +140,19 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { t.FailNow() } -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Emptyf asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // require.Emptyf(t, obj, "error message %s", "formatted") +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -279,10 +297,8 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if require.Error(t, err) { -// require.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// require.Error(t, err) func Error(t TestingT, err error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -373,10 +389,8 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if require.Errorf(t, err, "error message %s", "formatted") { -// require.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// require.Errorf(t, err, "error message %s", "formatted") func Errorf(t TestingT, err error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1097,7 +1111,35 @@ func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interf t.FailNow() } +// IsNotType asserts that the specified objects are not of the same type. +// +// require.IsNotType(t, &NotMyStruct{}, &MyStruct{}) +func IsNotType(t TestingT, theType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNotType(t, theType, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsNotTypef asserts that the specified objects are not of the same type. +// +// require.IsNotTypef(t, &NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") +func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNotTypef(t, theType, object, msg, args...) { + return + } + t.FailNow() +} + // IsType asserts that the specified objects are of the same type. +// +// require.IsType(t, &MyStruct{}, &MyStruct{}) func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1109,6 +1151,8 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs } // IsTypef asserts that the specified objects are of the same type. +// +// require.IsTypef(t, &MyStruct{}, &MyStruct{}, "error message %s", "formatted") func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1469,8 +1513,7 @@ func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg str t.FailNow() } -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmpty asserts that the specified object is NOT [Empty]. // // if require.NotEmpty(t, obj) { // require.Equal(t, "two", obj[1]) @@ -1485,8 +1528,7 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { t.FailNow() } -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmptyf asserts that the specified object is NOT [Empty]. // // if require.NotEmptyf(t, obj, "error message %s", "formatted") { // require.Equal(t, "two", obj[1]) @@ -1745,12 +1787,15 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubset asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // require.NotSubset(t, [1, 3, 4], [1, 2]) // require.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) +// require.NotSubset(t, [1, 3, 4], {1: "one", 2: "two"}) +// require.NotSubset(t, {"x": 1, "y": 2}, ["z"]) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1761,12 +1806,15 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i t.FailNow() } -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // require.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") // require.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") +// require.NotSubsetf(t, [1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") +// require.NotSubsetf(t, {"x": 1, "y": 2}, ["z"], "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1971,11 +2019,15 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg t.FailNow() } -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subset asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // require.Subset(t, [1, 2, 3], [1, 2]) // require.Subset(t, {"x": 1, "y": 2}, {"x": 1}) +// require.Subset(t, [1, 2, 3], {1: "one", 2: "two"}) +// require.Subset(t, {"x": 1, "y": 2}, ["x"]) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1986,11 +2038,15 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte t.FailNow() } -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subsetf asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // require.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") // require.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") +// require.Subsetf(t, [1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") +// require.Subsetf(t, {"x": 1, "y": 2}, ["x"], "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 1bd87304..e6f7e944 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -93,10 +93,19 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st ElementsMatchf(a.t, listA, listB, msg, args...) } -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Empty asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // a.Empty(obj) +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -104,10 +113,19 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { Empty(a.t, object, msgAndArgs...) } -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. +// Emptyf asserts that the given value is "empty". +// +// [Zero values] are "empty". +// +// Arrays are "empty" if every element is the zero value of the type (stricter than "empty"). +// +// Slices, maps and channels with zero length are "empty". +// +// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". // // a.Emptyf(obj, "error message %s", "formatted") +// +// [Zero values]: https://go.dev/ref/spec#The_zero_value func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -225,10 +243,8 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// a.Error(err) func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -298,10 +314,8 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// a.Errorf(err, "error message %s", "formatted") func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -869,7 +883,29 @@ func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...in IsNonIncreasingf(a.t, object, msg, args...) } +// IsNotType asserts that the specified objects are not of the same type. +// +// a.IsNotType(&NotMyStruct{}, &MyStruct{}) +func (a *Assertions) IsNotType(theType interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNotType(a.t, theType, object, msgAndArgs...) +} + +// IsNotTypef asserts that the specified objects are not of the same type. +// +// a.IsNotTypef(&NotMyStruct{}, &MyStruct{}, "error message %s", "formatted") +func (a *Assertions) IsNotTypef(theType interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNotTypef(a.t, theType, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. +// +// a.IsType(&MyStruct{}, &MyStruct{}) func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -878,6 +914,8 @@ func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAnd } // IsTypef asserts that the specified objects are of the same type. +// +// a.IsTypef(&MyStruct{}, &MyStruct{}, "error message %s", "formatted") func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1163,8 +1201,7 @@ func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg NotElementsMatchf(a.t, listA, listB, msg, args...) } -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmpty asserts that the specified object is NOT [Empty]. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) @@ -1176,8 +1213,7 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { NotEmpty(a.t, object, msgAndArgs...) } -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. +// NotEmptyf asserts that the specified object is NOT [Empty]. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) @@ -1379,12 +1415,15 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubset asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.NotSubset([1, 3, 4], [1, 2]) // a.NotSubset({"x": 1, "y": 2}, {"z": 3}) +// a.NotSubset([1, 3, 4], {1: "one", 2: "two"}) +// a.NotSubset({"x": 1, "y": 2}, ["z"]) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1392,12 +1431,15 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. +// NotSubsetf asserts that the list (array, slice, or map) does NOT contain all +// elements given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") // a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], {1: "one", 2: "two"}, "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, ["z"], "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1557,11 +1599,15 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subset asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.Subset([1, 2, 3], [1, 2]) // a.Subset({"x": 1, "y": 2}, {"x": 1}) +// a.Subset([1, 2, 3], {1: "one", 2: "two"}) +// a.Subset({"x": 1, "y": 2}, ["x"]) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1569,11 +1615,15 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. +// Subsetf asserts that the list (array, slice, or map) contains all elements +// given in the subset (array, slice, or map). +// Map elements are key-value pairs unless compared with an array or slice where +// only the map key is evaluated. // // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") // a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") +// a.Subsetf([1, 2, 3], {1: "one", 2: "two"}, "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, ["x"], "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/modules.txt b/vendor/modules.txt index 1d6be84d..3eeee20b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -184,7 +184,7 @@ github.com/spf13/viper/internal/encoding/json github.com/spf13/viper/internal/encoding/toml github.com/spf13/viper/internal/encoding/yaml github.com/spf13/viper/internal/features -# github.com/stretchr/testify v1.10.0 +# github.com/stretchr/testify v1.11.0 ## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml From fb8c15d535d8f76ec025e442461a41c589413a9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:27:47 +0200 Subject: [PATCH 25/35] chore(deps): bump golang.org/x/oauth2 from 0.30.0 to 0.31.0 (#182) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.30.0 to 0.31.0.
Commits
  • 014cf77 all: upgrade go directive to at least 1.24.0 [generated]
  • 3c76ce5 endpoints: correct Naver OAuth2 endpoint URLs
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.30.0&new-version=0.31.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 4 ++-- vendor/modules.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index cfa76f64..ac7ca9a2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/launchdarkly/find-code-references-in-pull-request -go 1.24 +go 1.24.0 require ( github.com/Masterminds/sprig/v3 v3.3.0 @@ -9,7 +9,7 @@ require ( github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.11.0 - golang.org/x/oauth2 v0.30.0 + golang.org/x/oauth2 v0.31.0 ) require ( diff --git a/go.sum b/go.sum index ed77aed0..bcb845f7 100644 --- a/go.sum +++ b/go.sum @@ -316,8 +316,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/modules.txt b/vendor/modules.txt index 3eeee20b..2dae8e26 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -252,8 +252,8 @@ golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/oauth2 v0.30.0 -## explicit; go 1.23.0 +# golang.org/x/oauth2 v0.31.0 +## explicit; go 1.24.0 golang.org/x/oauth2 golang.org/x/oauth2/internal # golang.org/x/sys v0.35.0 From b46b75ff8bc8b2f02208c56b3af70d4963869a80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:31:24 +0200 Subject: [PATCH 26/35] chore(deps): bump github.com/stretchr/testify from 1.11.0 to 1.11.1 (#183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [//]: # (dependabot-start) ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- [//]: # (dependabot-end) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.11.0 to 1.11.1.
Release notes

Sourced from github.com/stretchr/testify's releases.

v1.11.1

This release fixes #1785 introduced in v1.11.0 where expected argument values implementing the stringer interface (String() string) with a method which mutates their value, when passed to mock.Mock.On (m.On("Method", <expected>).Return()) or actual argument values passed to mock.Mock.Called may no longer match one another where they previously did match. The behaviour prior to v1.11.0 where the stringer is always called is restored. Future testify releases may not call the stringer method at all in this case.

What's Changed

Full Changelog: https://github.com/stretchr/testify/compare/v1.11.0...v1.11.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/stretchr/testify&package-manager=go_modules&previous-version=1.11.0&new-version=1.11.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Isabelle Miller --- go.mod | 2 +- go.sum | 4 ++-- vendor/modules.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index ac7ca9a2..d0eb6233 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.11.0 + github.com/stretchr/testify v1.11.1 golang.org/x/oauth2 v0.31.0 ) diff --git a/go.sum b/go.sum index bcb845f7..b5266926 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqj github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= -github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= diff --git a/vendor/modules.txt b/vendor/modules.txt index 2dae8e26..0b092b68 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -184,7 +184,7 @@ github.com/spf13/viper/internal/encoding/json github.com/spf13/viper/internal/encoding/toml github.com/spf13/viper/internal/encoding/yaml github.com/spf13/viper/internal/features -# github.com/stretchr/testify v1.11.0 +# github.com/stretchr/testify v1.11.1 ## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml From 460361305cd8df2fd6453f7483600bb06341c635 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:45:02 +0200 Subject: [PATCH 27/35] chore(deps): bump actions/setup-python from 5.6.0 to 6.0.0 (#184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.6.0 to 6.0.0.
Release notes

Sourced from actions/setup-python's releases.

v6.0.0

What's Changed

Breaking Changes

Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. See Release Notes

Enhancements:

Bug fixes:

Dependency updates:

New Contributors

Full Changelog: https://github.com/actions/setup-python/compare/v5...v6.0.0

Commits
  • e797f83 Upgrade to node 24 (#1164)
  • 3d1e2d2 Revert "Enhance cache-dependency-path handling to support files outside the w...
  • 65b0712 Clarify pythonLocation behavior for PyPy and GraalPy in environment variables...
  • 5b668cf Bump actions/checkout from 4 to 5 (#1181)
  • f62a0e2 Change missing cache directory error to warning (#1182)
  • 9322b3c Upgrade setuptools to 78.1.1 to fix path traversal vulnerability in PackageIn...
  • fbeb884 Bump form-data to fix critical vulnerabilities #182 & #183 (#1163)
  • 03bb615 Bump idna from 2.9 to 3.7 in /tests/data (#843)
  • 36da51d Add version parsing from Pipfile (#1067)
  • 3c6f142 update documentation (#1156)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=5.6.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e5131477..b9e26540 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: run: npm install -g @datadog/datadog-ci - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c with: python-version: '3.x' @@ -121,7 +121,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c with: python-version: '3.x' From 74d7168f984fe6932093423b64eb34cbe1c13507 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:45:28 +0200 Subject: [PATCH 28/35] chore(deps): bump actions/setup-node from 4.4.0 to 5.0.0 (#185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.4.0 to 5.0.0.
Release notes

Sourced from actions/setup-node's releases.

v5.0.0

What's Changed

Breaking Changes

This update, introduces automatic caching when a valid packageManager field is present in your package.json. This aims to improve workflow performance and make dependency management more seamless. To disable this automatic caching, set package-manager-cache: false

steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
  with:
    package-manager-cache: false

Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. See Release Notes

Dependency Upgrades

New Contributors

Full Changelog: https://github.com/actions/setup-node/compare/v4...v5.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=4.4.0&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b9e26540..4b656a07 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Set up Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 with: node-version: '18.x' @@ -131,7 +131,7 @@ jobs: pip install pre-commit - name: Set up Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 with: node-version: '18.8.0' From 0827acfc89c9c1eb59c06bc63ce78978496d6c7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:45:52 +0200 Subject: [PATCH 29/35] chore(deps): bump actions/setup-go from 5.5.0 to 6.0.0 (#186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.5.0 to 6.0.0.
Release notes

Sourced from actions/setup-go's releases.

v6.0.0

What's Changed

Breaking Changes

Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. See Release Notes

Dependency Upgrades

New Contributors

Full Changelog: https://github.com/actions/setup-go/compare/v5...v6.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=5.5.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4b656a07..2ed6b62d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: python-version: '3.x' - name: Set up Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 with: go-version-file: go.mod From 8cbd1e5f1a3df95989eb7f0e213bd2046dd14fa5 Mon Sep 17 00:00:00 2001 From: brianvans <1323225+brianvans@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:29:01 -0700 Subject: [PATCH 30/35] docs(readme): add note in README about creating the "ld-flags" label first (#188) This is a minor gotcha, but if you try to run the example Github action, it will break with "ld-flags does not exist" errors unless the Github label is created first. Co-authored-by: kallevmercury <164934876+kallevmercury@users.noreply.github.com> --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 32756fff..cbd2192c 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,9 @@ jobs: access-token: ${{ secrets.LD_ACCESS_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }} - # Add or remove labels on PRs if any flags have changed + # Add or remove labels on PRs if any flags have changed. + # Note: This example requires the "ld-flags" label to have been created in the repository first: + # https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels#creating-a-label - name: Add label if: steps.find-flags.outputs.any-changed == 'true' run: gh pr edit $PR_NUMBER --add-label ld-flags From 7478c42b3c13fcc9192001b95c2fd8fe7388a73c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:26:10 +0200 Subject: [PATCH 31/35] chore(deps): bump golang.org/x/oauth2 from 0.31.0 to 0.32.0 (#189) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.31.0 to 0.32.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.31.0&new-version=0.32.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- vendor/golang.org/x/oauth2/oauth2.go | 3 +-- vendor/modules.txt | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d0eb6233..b8b8ecad 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.11.1 - golang.org/x/oauth2 v0.31.0 + golang.org/x/oauth2 v0.32.0 ) require ( diff --git a/go.sum b/go.sum index b5266926..5ecb7581 100644 --- a/go.sum +++ b/go.sum @@ -316,8 +316,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= -golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index de34feb8..3e3b6306 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -9,7 +9,6 @@ package oauth2 // import "golang.org/x/oauth2" import ( - "bytes" "context" "errors" "net/http" @@ -158,7 +157,7 @@ func SetAuthURLParam(key, value string) AuthCodeOption { // PKCE), https://www.oauth.com/oauth2-servers/pkce/ and // https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches) func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { - var buf bytes.Buffer + var buf strings.Builder buf.WriteString(c.Endpoint.AuthURL) v := url.Values{ "response_type": {"code"}, diff --git a/vendor/modules.txt b/vendor/modules.txt index 0b092b68..89c324d8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -252,7 +252,7 @@ golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/oauth2 v0.31.0 +# golang.org/x/oauth2 v0.32.0 ## explicit; go 1.24.0 golang.org/x/oauth2 golang.org/x/oauth2/internal From 1abb6976ff063c8d04f8100c73c1d09755117c3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:45:56 +0100 Subject: [PATCH 32/35] chore(deps): bump golang.org/x/oauth2 from 0.32.0 to 0.33.0 (#191) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.32.0 to 0.33.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/oauth2&package-manager=go_modules&previous-version=0.32.0&new-version=0.33.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +-- vendor/golang.org/x/oauth2/deviceauth.go | 31 +++++++++++++++++++++++- vendor/golang.org/x/oauth2/oauth2.go | 2 +- vendor/golang.org/x/oauth2/pkce.go | 2 +- vendor/golang.org/x/oauth2/token.go | 2 +- vendor/golang.org/x/oauth2/transport.go | 2 +- vendor/modules.txt | 2 +- 8 files changed, 38 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index b8b8ecad..6ad3b54a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.11.1 - golang.org/x/oauth2 v0.32.0 + golang.org/x/oauth2 v0.33.0 ) require ( diff --git a/go.sum b/go.sum index 5ecb7581..8e2908a7 100644 --- a/go.sum +++ b/go.sum @@ -316,8 +316,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= +golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/golang.org/x/oauth2/deviceauth.go b/vendor/golang.org/x/oauth2/deviceauth.go index e99c92f3..e783a943 100644 --- a/vendor/golang.org/x/oauth2/deviceauth.go +++ b/vendor/golang.org/x/oauth2/deviceauth.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "mime" "net/http" "net/url" "strings" @@ -116,10 +117,38 @@ func retrieveDeviceAuth(ctx context.Context, c *Config, v url.Values) (*DeviceAu return nil, fmt.Errorf("oauth2: cannot auth device: %v", err) } if code := r.StatusCode; code < 200 || code > 299 { - return nil, &RetrieveError{ + retrieveError := &RetrieveError{ Response: r, Body: body, } + + content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) + switch content { + case "application/x-www-form-urlencoded", "text/plain": + // some endpoints return a query string + vals, err := url.ParseQuery(string(body)) + if err != nil { + return nil, retrieveError + } + retrieveError.ErrorCode = vals.Get("error") + retrieveError.ErrorDescription = vals.Get("error_description") + retrieveError.ErrorURI = vals.Get("error_uri") + default: + var tj struct { + // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 + ErrorCode string `json:"error"` + ErrorDescription string `json:"error_description"` + ErrorURI string `json:"error_uri"` + } + if json.Unmarshal(body, &tj) != nil { + return nil, retrieveError + } + retrieveError.ErrorCode = tj.ErrorCode + retrieveError.ErrorDescription = tj.ErrorDescription + retrieveError.ErrorURI = tj.ErrorURI + } + + return nil, retrieveError } da := &DeviceAuthResponse{} diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 3e3b6306..5c527d31 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -98,7 +98,7 @@ const ( // in the POST body as application/x-www-form-urlencoded parameters. AuthStyleInParams AuthStyle = 1 - // AuthStyleInHeader sends the client_id and client_password + // AuthStyleInHeader sends the client_id and client_secret // using HTTP Basic Authorization. This is an optional style // described in the OAuth2 RFC 6749 section 2.3.1. AuthStyleInHeader AuthStyle = 2 diff --git a/vendor/golang.org/x/oauth2/pkce.go b/vendor/golang.org/x/oauth2/pkce.go index cea8374d..f99384f0 100644 --- a/vendor/golang.org/x/oauth2/pkce.go +++ b/vendor/golang.org/x/oauth2/pkce.go @@ -51,7 +51,7 @@ func S256ChallengeFromVerifier(verifier string) string { return base64.RawURLEncoding.EncodeToString(sha[:]) } -// S256ChallengeOption derives a PKCE code challenge derived from verifier with +// S256ChallengeOption derives a PKCE code challenge from the verifier with // method S256. It should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] // only. func S256ChallengeOption(verifier string) AuthCodeOption { diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 239ec329..e995eebb 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -103,7 +103,7 @@ func (t *Token) WithExtra(extra any) *Token { } // Extra returns an extra field. -// Extra fields are key-value pairs returned by the server as a +// Extra fields are key-value pairs returned by the server as // part of the token retrieval response. func (t *Token) Extra(key string) any { if raw, ok := t.raw.(map[string]any); ok { diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go index 8bbebbac..9922ec33 100644 --- a/vendor/golang.org/x/oauth2/transport.go +++ b/vendor/golang.org/x/oauth2/transport.go @@ -58,7 +58,7 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { var cancelOnce sync.Once // CancelRequest does nothing. It used to be a legacy cancellation mechanism -// but now only it only logs on first use to warn that it's deprecated. +// but now only logs on first use to warn that it's deprecated. // // Deprecated: use contexts for cancellation instead. func (t *Transport) CancelRequest(req *http.Request) { diff --git a/vendor/modules.txt b/vendor/modules.txt index 89c324d8..e677129e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -252,7 +252,7 @@ golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/oauth2 v0.32.0 +# golang.org/x/oauth2 v0.33.0 ## explicit; go 1.24.0 golang.org/x/oauth2 golang.org/x/oauth2/internal From 7d5c6b450edc9cee4f00a8c547fa5148910e1988 Mon Sep 17 00:00:00 2001 From: Henry Barrow Date: Tue, 11 Nov 2025 12:36:58 +0000 Subject: [PATCH 33/35] [REL-10104] Update CODEOWNERS (#192) This PR updates code ownership since @launchdarkly/team-enterprise is now empty. --- Related Jira issue: [REL-10104: Update CODEOWNERS](https://launchdarkly.atlassian.net/browse/REL-10104) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 0da4a455..86cf9de5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,3 @@ # These owners will be the default owners for everything in the repo. -* @launchdarkly/team-enterprise +* @launchdarkly/team-fm-next From 4b6166c2705a4520cf7af583079e3f6e6293ce30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 09:54:40 +0100 Subject: [PATCH 34/35] chore(deps): bump golang.org/x/crypto from 0.41.0 to 0.45.0 (#193) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.41.0 to 0.45.0.
Commits
  • 4e0068c go.mod: update golang.org/x dependencies
  • e79546e ssh: curb GSSAPI DoS risk by limiting number of specified OIDs
  • f91f7a7 ssh/agent: prevent panic on malformed constraint
  • 2df4153 acme/autocert: let automatic renewal work with short lifetime certs
  • bcf6a84 acme: pass context to request
  • b4f2b62 ssh: fix error message on unsupported cipher
  • 79ec3a5 ssh: allow to bind to a hostname in remote forwarding
  • 122a78f go.mod: update golang.org/x dependencies
  • c0531f9 all: eliminate vet diagnostics
  • 0997000 all: fix some comments
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/crypto&package-manager=go_modules&previous-version=0.41.0&new-version=0.45.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/launchdarkly/find-code-references-in-pull-request/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 +- go.sum | 16 +- .../golang.org/x/sys/unix/affinity_linux.go | 9 +- vendor/golang.org/x/sys/unix/fdset.go | 4 +- vendor/golang.org/x/sys/unix/ifreq_linux.go | 4 +- vendor/golang.org/x/sys/unix/mkall.sh | 1 + vendor/golang.org/x/sys/unix/mkerrors.sh | 2 + vendor/golang.org/x/sys/unix/syscall_linux.go | 10 +- .../golang.org/x/sys/unix/syscall_netbsd.go | 17 + .../golang.org/x/sys/unix/syscall_solaris.go | 2 +- vendor/golang.org/x/sys/unix/zerrors_linux.go | 359 ++++++ .../golang.org/x/sys/unix/zsyscall_linux.go | 10 + .../x/sys/unix/zsyscall_solaris_amd64.go | 8 +- vendor/golang.org/x/sys/unix/ztypes_linux.go | 72 ++ .../x/sys/windows/syscall_windows.go | 17 + .../golang.org/x/sys/windows/types_windows.go | 98 ++ .../x/sys/windows/zsyscall_windows.go | 1021 +++++++++-------- vendor/golang.org/x/tools/PATENTS | 22 - vendor/golang.org/x/tools/{ => godoc}/LICENSE | 0 vendor/modules.txt | 16 +- 20 files changed, 1156 insertions(+), 540 deletions(-) delete mode 100644 vendor/golang.org/x/tools/PATENTS rename vendor/golang.org/x/tools/{ => godoc}/LICENSE (100%) diff --git a/go.mod b/go.mod index 6ad3b54a..9f9f549b 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect + golang.org/x/tools/godoc v0.1.0-deprecated // indirect ) require ( @@ -69,10 +70,9 @@ require ( github.com/spf13/pflag v1.0.7 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/wacul/ptr v1.0.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8e2908a7..af9f185f 100644 --- a/go.sum +++ b/go.sum @@ -252,8 +252,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -353,15 +353,15 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -405,8 +405,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk= +golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/golang.org/x/sys/unix/affinity_linux.go b/vendor/golang.org/x/sys/unix/affinity_linux.go index 6e5c81ac..3ea47038 100644 --- a/vendor/golang.org/x/sys/unix/affinity_linux.go +++ b/vendor/golang.org/x/sys/unix/affinity_linux.go @@ -38,8 +38,15 @@ func SchedSetaffinity(pid int, set *CPUSet) error { // Zero clears the set s, so that it contains no CPUs. func (s *CPUSet) Zero() { + clear(s[:]) +} + +// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinity] +// will silently ignore any invalid CPU bits in [CPUSet] so this is an +// efficient way of resetting the CPU affinity of a process. +func (s *CPUSet) Fill() { for i := range s { - s[i] = 0 + s[i] = ^cpuMask(0) } } diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go index 9e83d18c..62ed1264 100644 --- a/vendor/golang.org/x/sys/unix/fdset.go +++ b/vendor/golang.org/x/sys/unix/fdset.go @@ -23,7 +23,5 @@ func (fds *FdSet) IsSet(fd int) bool { // Zero clears the set fds. func (fds *FdSet) Zero() { - for i := range fds.Bits { - fds.Bits[i] = 0 - } + clear(fds.Bits[:]) } diff --git a/vendor/golang.org/x/sys/unix/ifreq_linux.go b/vendor/golang.org/x/sys/unix/ifreq_linux.go index 848840ae..309f5a2b 100644 --- a/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -111,9 +111,7 @@ func (ifr *Ifreq) SetUint32(v uint32) { // clear zeroes the ifreq's union field to prevent trailing garbage data from // being sent to the kernel if an ifreq is reused. func (ifr *Ifreq) clear() { - for i := range ifr.raw.Ifru { - ifr.raw.Ifru[i] = 0 - } + clear(ifr.raw.Ifru[:]) } // TODO(mdlayher): export as IfreqData? For now we can provide helpers such as diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index e6f31d37..d0ed6119 100644 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -49,6 +49,7 @@ esac if [[ "$GOOS" = "linux" ]]; then # Use the Docker-based build system # Files generated through docker (use $cmd so you can Ctl-C the build or run) + set -e $cmd docker build --tag generate:$GOOS $GOOS $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS exit diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index d1c8b264..42517077 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -226,6 +226,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -529,6 +530,7 @@ ccflags="$@" $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || + $2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ || $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 4958a657..06c0eea6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -801,9 +801,7 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) { // one. The kernel expects SID to be in network byte order. binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID) copy(sa.raw[8:14], sa.Remote) - for i := 14; i < 14+IFNAMSIZ; i++ { - sa.raw[i] = 0 - } + clear(sa.raw[14 : 14+IFNAMSIZ]) copy(sa.raw[14:], sa.Dev) return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil } @@ -2645,3 +2643,9 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { //sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) //sys Mseal(b []byte, flags uint) (err error) + +//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY + +func SetMemPolicy(mode int, mask *CPUSet) error { + return setMemPolicy(mode, mask, _CPU_SETSIZE) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 88162099..34a46769 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -248,6 +248,23 @@ func Statvfs(path string, buf *Statvfs_t) (err error) { return Statvfs1(path, buf, ST_WAIT) } +func Getvfsstat(buf []Statvfs_t, flags int) (n int, err error) { + var ( + _p0 unsafe.Pointer + bufsize uintptr + ) + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + bufsize = unsafe.Sizeof(Statvfs_t{}) * uintptr(len(buf)) + } + r0, _, e1 := Syscall(SYS_GETVFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + /* * Exposed directly */ diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index abc39554..18a3d9bd 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -629,7 +629,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Kill(pid int, signum syscall.Signal) (err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Link(path string, link string) (err error) -//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten +//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen //sys Lstat(path string, stat *Stat_t) (err error) //sys Madvise(b []byte, advice int) (err error) //sys Mkdir(path string, mode uint32) (err error) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index b6db27d9..d0a75da5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -853,20 +853,86 @@ const ( DM_VERSION_MAJOR = 0x4 DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 + DT_ADDRRNGHI = 0x6ffffeff + DT_ADDRRNGLO = 0x6ffffe00 DT_BLK = 0x6 DT_CHR = 0x2 + DT_DEBUG = 0x15 DT_DIR = 0x4 + DT_ENCODING = 0x20 DT_FIFO = 0x1 + DT_FINI = 0xd + DT_FLAGS_1 = 0x6ffffffb + DT_GNU_HASH = 0x6ffffef5 + DT_HASH = 0x4 + DT_HIOS = 0x6ffff000 + DT_HIPROC = 0x7fffffff + DT_INIT = 0xc + DT_JMPREL = 0x17 DT_LNK = 0xa + DT_LOOS = 0x6000000d + DT_LOPROC = 0x70000000 + DT_NEEDED = 0x1 + DT_NULL = 0x0 + DT_PLTGOT = 0x3 + DT_PLTREL = 0x14 + DT_PLTRELSZ = 0x2 DT_REG = 0x8 + DT_REL = 0x11 + DT_RELA = 0x7 + DT_RELACOUNT = 0x6ffffff9 + DT_RELAENT = 0x9 + DT_RELASZ = 0x8 + DT_RELCOUNT = 0x6ffffffa + DT_RELENT = 0x13 + DT_RELSZ = 0x12 + DT_RPATH = 0xf DT_SOCK = 0xc + DT_SONAME = 0xe + DT_STRSZ = 0xa + DT_STRTAB = 0x5 + DT_SYMBOLIC = 0x10 + DT_SYMENT = 0xb + DT_SYMTAB = 0x6 + DT_TEXTREL = 0x16 DT_UNKNOWN = 0x0 + DT_VALRNGHI = 0x6ffffdff + DT_VALRNGLO = 0x6ffffd00 + DT_VERDEF = 0x6ffffffc + DT_VERDEFNUM = 0x6ffffffd + DT_VERNEED = 0x6ffffffe + DT_VERNEEDNUM = 0x6fffffff + DT_VERSYM = 0x6ffffff0 DT_WHT = 0xe ECHO = 0x8 ECRYPTFS_SUPER_MAGIC = 0xf15f EFD_SEMAPHORE = 0x1 EFIVARFS_MAGIC = 0xde5e81e4 EFS_SUPER_MAGIC = 0x414a53 + EI_CLASS = 0x4 + EI_DATA = 0x5 + EI_MAG0 = 0x0 + EI_MAG1 = 0x1 + EI_MAG2 = 0x2 + EI_MAG3 = 0x3 + EI_NIDENT = 0x10 + EI_OSABI = 0x7 + EI_PAD = 0x8 + EI_VERSION = 0x6 + ELFCLASS32 = 0x1 + ELFCLASS64 = 0x2 + ELFCLASSNONE = 0x0 + ELFCLASSNUM = 0x3 + ELFDATA2LSB = 0x1 + ELFDATA2MSB = 0x2 + ELFDATANONE = 0x0 + ELFMAG = "\177ELF" + ELFMAG0 = 0x7f + ELFMAG1 = 'E' + ELFMAG2 = 'L' + ELFMAG3 = 'F' + ELFOSABI_LINUX = 0x3 + ELFOSABI_NONE = 0x0 EM_386 = 0x3 EM_486 = 0x6 EM_68K = 0x4 @@ -1152,14 +1218,24 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + ET_CORE = 0x4 + ET_DYN = 0x3 + ET_EXEC = 0x2 + ET_HIPROC = 0xffff + ET_LOPROC = 0xff00 + ET_NONE = 0x0 + ET_REL = 0x1 EV_ABS = 0x3 EV_CNT = 0x20 + EV_CURRENT = 0x1 EV_FF = 0x15 EV_FF_STATUS = 0x17 EV_KEY = 0x1 EV_LED = 0x11 EV_MAX = 0x1f EV_MSC = 0x4 + EV_NONE = 0x0 + EV_NUM = 0x2 EV_PWR = 0x16 EV_REL = 0x2 EV_REP = 0x14 @@ -2276,7 +2352,167 @@ const ( NLM_F_REPLACE = 0x100 NLM_F_REQUEST = 0x1 NLM_F_ROOT = 0x100 + NN_386_IOPERM = "LINUX" + NN_386_TLS = "LINUX" + NN_ARC_V2 = "LINUX" + NN_ARM_FPMR = "LINUX" + NN_ARM_GCS = "LINUX" + NN_ARM_HW_BREAK = "LINUX" + NN_ARM_HW_WATCH = "LINUX" + NN_ARM_PACA_KEYS = "LINUX" + NN_ARM_PACG_KEYS = "LINUX" + NN_ARM_PAC_ENABLED_KEYS = "LINUX" + NN_ARM_PAC_MASK = "LINUX" + NN_ARM_POE = "LINUX" + NN_ARM_SSVE = "LINUX" + NN_ARM_SVE = "LINUX" + NN_ARM_SYSTEM_CALL = "LINUX" + NN_ARM_TAGGED_ADDR_CTRL = "LINUX" + NN_ARM_TLS = "LINUX" + NN_ARM_VFP = "LINUX" + NN_ARM_ZA = "LINUX" + NN_ARM_ZT = "LINUX" + NN_AUXV = "CORE" + NN_FILE = "CORE" + NN_GNU_PROPERTY_TYPE_0 = "GNU" + NN_LOONGARCH_CPUCFG = "LINUX" + NN_LOONGARCH_CSR = "LINUX" + NN_LOONGARCH_HW_BREAK = "LINUX" + NN_LOONGARCH_HW_WATCH = "LINUX" + NN_LOONGARCH_LASX = "LINUX" + NN_LOONGARCH_LBT = "LINUX" + NN_LOONGARCH_LSX = "LINUX" + NN_MIPS_DSP = "LINUX" + NN_MIPS_FP_MODE = "LINUX" + NN_MIPS_MSA = "LINUX" + NN_PPC_DEXCR = "LINUX" + NN_PPC_DSCR = "LINUX" + NN_PPC_EBB = "LINUX" + NN_PPC_HASHKEYR = "LINUX" + NN_PPC_PKEY = "LINUX" + NN_PPC_PMU = "LINUX" + NN_PPC_PPR = "LINUX" + NN_PPC_SPE = "LINUX" + NN_PPC_TAR = "LINUX" + NN_PPC_TM_CDSCR = "LINUX" + NN_PPC_TM_CFPR = "LINUX" + NN_PPC_TM_CGPR = "LINUX" + NN_PPC_TM_CPPR = "LINUX" + NN_PPC_TM_CTAR = "LINUX" + NN_PPC_TM_CVMX = "LINUX" + NN_PPC_TM_CVSX = "LINUX" + NN_PPC_TM_SPR = "LINUX" + NN_PPC_VMX = "LINUX" + NN_PPC_VSX = "LINUX" + NN_PRFPREG = "CORE" + NN_PRPSINFO = "CORE" + NN_PRSTATUS = "CORE" + NN_PRXFPREG = "LINUX" + NN_RISCV_CSR = "LINUX" + NN_RISCV_TAGGED_ADDR_CTRL = "LINUX" + NN_RISCV_VECTOR = "LINUX" + NN_S390_CTRS = "LINUX" + NN_S390_GS_BC = "LINUX" + NN_S390_GS_CB = "LINUX" + NN_S390_HIGH_GPRS = "LINUX" + NN_S390_LAST_BREAK = "LINUX" + NN_S390_PREFIX = "LINUX" + NN_S390_PV_CPU_DATA = "LINUX" + NN_S390_RI_CB = "LINUX" + NN_S390_SYSTEM_CALL = "LINUX" + NN_S390_TDB = "LINUX" + NN_S390_TIMER = "LINUX" + NN_S390_TODCMP = "LINUX" + NN_S390_TODPREG = "LINUX" + NN_S390_VXRS_HIGH = "LINUX" + NN_S390_VXRS_LOW = "LINUX" + NN_SIGINFO = "CORE" + NN_TASKSTRUCT = "CORE" + NN_VMCOREDD = "LINUX" + NN_X86_SHSTK = "LINUX" + NN_X86_XSAVE_LAYOUT = "LINUX" + NN_X86_XSTATE = "LINUX" NSFS_MAGIC = 0x6e736673 + NT_386_IOPERM = 0x201 + NT_386_TLS = 0x200 + NT_ARC_V2 = 0x600 + NT_ARM_FPMR = 0x40e + NT_ARM_GCS = 0x410 + NT_ARM_HW_BREAK = 0x402 + NT_ARM_HW_WATCH = 0x403 + NT_ARM_PACA_KEYS = 0x407 + NT_ARM_PACG_KEYS = 0x408 + NT_ARM_PAC_ENABLED_KEYS = 0x40a + NT_ARM_PAC_MASK = 0x406 + NT_ARM_POE = 0x40f + NT_ARM_SSVE = 0x40b + NT_ARM_SVE = 0x405 + NT_ARM_SYSTEM_CALL = 0x404 + NT_ARM_TAGGED_ADDR_CTRL = 0x409 + NT_ARM_TLS = 0x401 + NT_ARM_VFP = 0x400 + NT_ARM_ZA = 0x40c + NT_ARM_ZT = 0x40d + NT_AUXV = 0x6 + NT_FILE = 0x46494c45 + NT_GNU_PROPERTY_TYPE_0 = 0x5 + NT_LOONGARCH_CPUCFG = 0xa00 + NT_LOONGARCH_CSR = 0xa01 + NT_LOONGARCH_HW_BREAK = 0xa05 + NT_LOONGARCH_HW_WATCH = 0xa06 + NT_LOONGARCH_LASX = 0xa03 + NT_LOONGARCH_LBT = 0xa04 + NT_LOONGARCH_LSX = 0xa02 + NT_MIPS_DSP = 0x800 + NT_MIPS_FP_MODE = 0x801 + NT_MIPS_MSA = 0x802 + NT_PPC_DEXCR = 0x111 + NT_PPC_DSCR = 0x105 + NT_PPC_EBB = 0x106 + NT_PPC_HASHKEYR = 0x112 + NT_PPC_PKEY = 0x110 + NT_PPC_PMU = 0x107 + NT_PPC_PPR = 0x104 + NT_PPC_SPE = 0x101 + NT_PPC_TAR = 0x103 + NT_PPC_TM_CDSCR = 0x10f + NT_PPC_TM_CFPR = 0x109 + NT_PPC_TM_CGPR = 0x108 + NT_PPC_TM_CPPR = 0x10e + NT_PPC_TM_CTAR = 0x10d + NT_PPC_TM_CVMX = 0x10a + NT_PPC_TM_CVSX = 0x10b + NT_PPC_TM_SPR = 0x10c + NT_PPC_VMX = 0x100 + NT_PPC_VSX = 0x102 + NT_PRFPREG = 0x2 + NT_PRPSINFO = 0x3 + NT_PRSTATUS = 0x1 + NT_PRXFPREG = 0x46e62b7f + NT_RISCV_CSR = 0x900 + NT_RISCV_TAGGED_ADDR_CTRL = 0x902 + NT_RISCV_VECTOR = 0x901 + NT_S390_CTRS = 0x304 + NT_S390_GS_BC = 0x30c + NT_S390_GS_CB = 0x30b + NT_S390_HIGH_GPRS = 0x300 + NT_S390_LAST_BREAK = 0x306 + NT_S390_PREFIX = 0x305 + NT_S390_PV_CPU_DATA = 0x30e + NT_S390_RI_CB = 0x30d + NT_S390_SYSTEM_CALL = 0x307 + NT_S390_TDB = 0x308 + NT_S390_TIMER = 0x301 + NT_S390_TODCMP = 0x302 + NT_S390_TODPREG = 0x303 + NT_S390_VXRS_HIGH = 0x30a + NT_S390_VXRS_LOW = 0x309 + NT_SIGINFO = 0x53494749 + NT_TASKSTRUCT = 0x4 + NT_VMCOREDD = 0x700 + NT_X86_SHSTK = 0x204 + NT_X86_XSAVE_LAYOUT = 0x205 + NT_X86_XSTATE = 0x202 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -2463,6 +2699,59 @@ const ( PERF_RECORD_MISC_USER = 0x2 PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 PERF_SAMPLE_WEIGHT_TYPE = 0x1004000 + PF_ALG = 0x26 + PF_APPLETALK = 0x5 + PF_ASH = 0x12 + PF_ATMPVC = 0x8 + PF_ATMSVC = 0x14 + PF_AX25 = 0x3 + PF_BLUETOOTH = 0x1f + PF_BRIDGE = 0x7 + PF_CAIF = 0x25 + PF_CAN = 0x1d + PF_DECnet = 0xc + PF_ECONET = 0x13 + PF_FILE = 0x1 + PF_IB = 0x1b + PF_IEEE802154 = 0x24 + PF_INET = 0x2 + PF_INET6 = 0xa + PF_IPX = 0x4 + PF_IRDA = 0x17 + PF_ISDN = 0x22 + PF_IUCV = 0x20 + PF_KCM = 0x29 + PF_KEY = 0xf + PF_LLC = 0x1a + PF_LOCAL = 0x1 + PF_MAX = 0x2e + PF_MCTP = 0x2d + PF_MPLS = 0x1c + PF_NETBEUI = 0xd + PF_NETLINK = 0x10 + PF_NETROM = 0x6 + PF_NFC = 0x27 + PF_PACKET = 0x11 + PF_PHONET = 0x23 + PF_PPPOX = 0x18 + PF_QIPCRTR = 0x2a + PF_R = 0x4 + PF_RDS = 0x15 + PF_ROSE = 0xb + PF_ROUTE = 0x10 + PF_RXRPC = 0x21 + PF_SECURITY = 0xe + PF_SMC = 0x2b + PF_SNA = 0x16 + PF_TIPC = 0x1e + PF_UNIX = 0x1 + PF_UNSPEC = 0x0 + PF_VSOCK = 0x28 + PF_W = 0x2 + PF_WANPIPE = 0x19 + PF_X = 0x1 + PF_X25 = 0x9 + PF_XDP = 0x2c PID_FS_MAGIC = 0x50494446 PIPEFS_MAGIC = 0x50495045 PPPIOCGNPMODE = 0xc008744c @@ -2758,6 +3047,23 @@ const ( PTRACE_SYSCALL_INFO_NONE = 0x0 PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 + PT_AARCH64_MEMTAG_MTE = 0x70000002 + PT_DYNAMIC = 0x2 + PT_GNU_EH_FRAME = 0x6474e550 + PT_GNU_PROPERTY = 0x6474e553 + PT_GNU_RELRO = 0x6474e552 + PT_GNU_STACK = 0x6474e551 + PT_HIOS = 0x6fffffff + PT_HIPROC = 0x7fffffff + PT_INTERP = 0x3 + PT_LOAD = 0x1 + PT_LOOS = 0x60000000 + PT_LOPROC = 0x70000000 + PT_NOTE = 0x4 + PT_NULL = 0x0 + PT_PHDR = 0x6 + PT_SHLIB = 0x5 + PT_TLS = 0x7 P_ALL = 0x0 P_PGID = 0x2 P_PID = 0x1 @@ -3091,6 +3397,47 @@ const ( SEEK_MAX = 0x4 SEEK_SET = 0x0 SELINUX_MAGIC = 0xf97cff8c + SHF_ALLOC = 0x2 + SHF_EXCLUDE = 0x8000000 + SHF_EXECINSTR = 0x4 + SHF_GROUP = 0x200 + SHF_INFO_LINK = 0x40 + SHF_LINK_ORDER = 0x80 + SHF_MASKOS = 0xff00000 + SHF_MASKPROC = 0xf0000000 + SHF_MERGE = 0x10 + SHF_ORDERED = 0x4000000 + SHF_OS_NONCONFORMING = 0x100 + SHF_RELA_LIVEPATCH = 0x100000 + SHF_RO_AFTER_INIT = 0x200000 + SHF_STRINGS = 0x20 + SHF_TLS = 0x400 + SHF_WRITE = 0x1 + SHN_ABS = 0xfff1 + SHN_COMMON = 0xfff2 + SHN_HIPROC = 0xff1f + SHN_HIRESERVE = 0xffff + SHN_LIVEPATCH = 0xff20 + SHN_LOPROC = 0xff00 + SHN_LORESERVE = 0xff00 + SHN_UNDEF = 0x0 + SHT_DYNAMIC = 0x6 + SHT_DYNSYM = 0xb + SHT_HASH = 0x5 + SHT_HIPROC = 0x7fffffff + SHT_HIUSER = 0xffffffff + SHT_LOPROC = 0x70000000 + SHT_LOUSER = 0x80000000 + SHT_NOBITS = 0x8 + SHT_NOTE = 0x7 + SHT_NULL = 0x0 + SHT_NUM = 0xc + SHT_PROGBITS = 0x1 + SHT_REL = 0x9 + SHT_RELA = 0x4 + SHT_SHLIB = 0xa + SHT_STRTAB = 0x3 + SHT_SYMTAB = 0x2 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -3317,6 +3664,16 @@ const ( STATX_UID = 0x8 STATX_WRITE_ATOMIC = 0x10000 STATX__RESERVED = 0x80000000 + STB_GLOBAL = 0x1 + STB_LOCAL = 0x0 + STB_WEAK = 0x2 + STT_COMMON = 0x5 + STT_FILE = 0x4 + STT_FUNC = 0x2 + STT_NOTYPE = 0x0 + STT_OBJECT = 0x1 + STT_SECTION = 0x3 + STT_TLS = 0x6 SYNC_FILE_RANGE_WAIT_AFTER = 0x4 SYNC_FILE_RANGE_WAIT_BEFORE = 0x1 SYNC_FILE_RANGE_WRITE = 0x2 @@ -3553,6 +3910,8 @@ const ( UTIME_OMIT = 0x3ffffffe V9FS_MAGIC = 0x1021997 VERASE = 0x2 + VER_FLG_BASE = 0x1 + VER_FLG_WEAK = 0x2 VINTR = 0x0 VKILL = 0x3 VLNEXT = 0xf diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 5cc1e8eb..8935d10a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -2238,3 +2238,13 @@ func Mseal(b []byte, flags uint) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setMemPolicy(mode int, mask *CPUSet, size int) (err error) { + _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index c6545413..b4609c20 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -72,7 +72,7 @@ import ( //go:cgo_import_dynamic libc_kill kill "libc.so" //go:cgo_import_dynamic libc_lchown lchown "libc.so" //go:cgo_import_dynamic libc_link link "libc.so" -//go:cgo_import_dynamic libc___xnet_llisten __xnet_llisten "libsocket.so" +//go:cgo_import_dynamic libc___xnet_listen __xnet_listen "libsocket.so" //go:cgo_import_dynamic libc_lstat lstat "libc.so" //go:cgo_import_dynamic libc_madvise madvise "libc.so" //go:cgo_import_dynamic libc_mkdir mkdir "libc.so" @@ -221,7 +221,7 @@ import ( //go:linkname procKill libc_kill //go:linkname procLchown libc_lchown //go:linkname procLink libc_link -//go:linkname proc__xnet_llisten libc___xnet_llisten +//go:linkname proc__xnet_listen libc___xnet_listen //go:linkname procLstat libc_lstat //go:linkname procMadvise libc_madvise //go:linkname procMkdir libc_mkdir @@ -371,7 +371,7 @@ var ( procKill, procLchown, procLink, - proc__xnet_llisten, + proc__xnet_listen, procLstat, procMadvise, procMkdir, @@ -1178,7 +1178,7 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_llisten)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0) + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_listen)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index cd236443..c1a46701 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -632,6 +632,8 @@ const ( IFA_FLAGS = 0x8 IFA_RT_PRIORITY = 0x9 IFA_TARGET_NETNSID = 0xa + IFAL_LABEL = 0x2 + IFAL_ADDRESS = 0x1 RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_SITE = 0xc8 RT_SCOPE_LINK = 0xfd @@ -689,6 +691,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfAddrlblmsg = 0xc SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 @@ -740,6 +743,15 @@ type IfAddrmsg struct { Index uint32 } +type IfAddrlblmsg struct { + Family uint8 + _ uint8 + Prefixlen uint8 + Flags uint8 + Index uint32 + Seq uint32 +} + type IfaCacheinfo struct { Prefered uint32 Valid uint32 @@ -3052,6 +3064,23 @@ const ( ) const ( + TCA_UNSPEC = 0x0 + TCA_KIND = 0x1 + TCA_OPTIONS = 0x2 + TCA_STATS = 0x3 + TCA_XSTATS = 0x4 + TCA_RATE = 0x5 + TCA_FCNT = 0x6 + TCA_STATS2 = 0x7 + TCA_STAB = 0x8 + TCA_PAD = 0x9 + TCA_DUMP_INVISIBLE = 0xa + TCA_CHAIN = 0xb + TCA_HW_OFFLOAD = 0xc + TCA_INGRESS_BLOCK = 0xd + TCA_EGRESS_BLOCK = 0xe + TCA_DUMP_FLAGS = 0xf + TCA_EXT_WARN_MSG = 0x10 RTNLGRP_NONE = 0x0 RTNLGRP_LINK = 0x1 RTNLGRP_NOTIFY = 0x2 @@ -3086,6 +3115,18 @@ const ( RTNLGRP_IPV6_MROUTE_R = 0x1f RTNLGRP_NEXTHOP = 0x20 RTNLGRP_BRVLAN = 0x21 + RTNLGRP_MCTP_IFADDR = 0x22 + RTNLGRP_TUNNEL = 0x23 + RTNLGRP_STATS = 0x24 + RTNLGRP_IPV4_MCADDR = 0x25 + RTNLGRP_IPV6_MCADDR = 0x26 + RTNLGRP_IPV6_ACADDR = 0x27 + TCA_ROOT_UNSPEC = 0x0 + TCA_ROOT_TAB = 0x1 + TCA_ROOT_FLAGS = 0x2 + TCA_ROOT_COUNT = 0x3 + TCA_ROOT_TIME_DELTA = 0x4 + TCA_ROOT_EXT_WARN_MSG = 0x5 ) type CapUserHeader struct { @@ -3549,6 +3590,8 @@ type Nhmsg struct { Flags uint32 } +const SizeofNhmsg = 0x8 + type NexthopGrp struct { Id uint32 Weight uint8 @@ -3556,6 +3599,8 @@ type NexthopGrp struct { Resvd2 uint16 } +const SizeofNexthopGrp = 0x8 + const ( NHA_UNSPEC = 0x0 NHA_ID = 0x1 @@ -6291,3 +6336,30 @@ type SockDiagReq struct { } const RTM_NEWNVLAN = 0x70 + +const ( + MPOL_BIND = 0x2 + MPOL_DEFAULT = 0x0 + MPOL_F_ADDR = 0x2 + MPOL_F_MEMS_ALLOWED = 0x4 + MPOL_F_MOF = 0x8 + MPOL_F_MORON = 0x10 + MPOL_F_NODE = 0x1 + MPOL_F_NUMA_BALANCING = 0x2000 + MPOL_F_RELATIVE_NODES = 0x4000 + MPOL_F_SHARED = 0x1 + MPOL_F_STATIC_NODES = 0x8000 + MPOL_INTERLEAVE = 0x3 + MPOL_LOCAL = 0x4 + MPOL_MAX = 0x7 + MPOL_MF_INTERNAL = 0x10 + MPOL_MF_LAZY = 0x8 + MPOL_MF_MOVE_ALL = 0x4 + MPOL_MF_MOVE = 0x2 + MPOL_MF_STRICT = 0x1 + MPOL_MF_VALID = 0x7 + MPOL_MODE_FLAGS = 0xe000 + MPOL_PREFERRED = 0x1 + MPOL_PREFERRED_MANY = 0x5 + MPOL_WEIGHTED_INTERLEAVE = 0x6 +) diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 640f6b15..69439df2 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -321,6 +321,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW +//sys GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents +//sys FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer //sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole //sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot //sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW @@ -890,8 +892,12 @@ const socket_error = uintptr(^uint32(0)) //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar //sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx //sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex +//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2 +//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2 //sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry +//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable //sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange +//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2 //sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange //sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 @@ -914,6 +920,17 @@ type RawSockaddrInet6 struct { Scope_id uint32 } +// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See +// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet. +// +// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using +// unsafe, depending on the address family. +type RawSockaddrInet struct { + Family uint16 + Port uint16 + Data [6]uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 958bcf47..6e4f50eb 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -65,6 +65,22 @@ var signals = [...]string{ 15: "terminated", } +// File flags for [os.OpenFile]. The O_ prefix is used to indicate +// that these flags are specific to the OpenFile function. +const ( + O_FILE_FLAG_OPEN_NO_RECALL = FILE_FLAG_OPEN_NO_RECALL + O_FILE_FLAG_OPEN_REPARSE_POINT = FILE_FLAG_OPEN_REPARSE_POINT + O_FILE_FLAG_SESSION_AWARE = FILE_FLAG_SESSION_AWARE + O_FILE_FLAG_POSIX_SEMANTICS = FILE_FLAG_POSIX_SEMANTICS + O_FILE_FLAG_BACKUP_SEMANTICS = FILE_FLAG_BACKUP_SEMANTICS + O_FILE_FLAG_DELETE_ON_CLOSE = FILE_FLAG_DELETE_ON_CLOSE + O_FILE_FLAG_SEQUENTIAL_SCAN = FILE_FLAG_SEQUENTIAL_SCAN + O_FILE_FLAG_RANDOM_ACCESS = FILE_FLAG_RANDOM_ACCESS + O_FILE_FLAG_NO_BUFFERING = FILE_FLAG_NO_BUFFERING + O_FILE_FLAG_OVERLAPPED = FILE_FLAG_OVERLAPPED + O_FILE_FLAG_WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH +) + const ( FILE_READ_DATA = 0x00000001 FILE_READ_ATTRIBUTES = 0x00000080 @@ -1976,6 +1992,12 @@ const ( SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 ) +// FILE_ZERO_DATA_INFORMATION from winioctl.h +type FileZeroDataInformation struct { + FileOffset int64 + BeyondFinalZero int64 +} + const ( ComputerNameNetBIOS = 0 ComputerNameDnsHostname = 1 @@ -2298,6 +2320,82 @@ type MibIfRow2 struct { OutQLen uint64 } +// IP_ADDRESS_PREFIX stores an IP address prefix. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix. +type IpAddressPrefix struct { + Prefix RawSockaddrInet + PrefixLength uint8 +} + +// NL_ROUTE_ORIGIN enumeration from nldef.h or +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_origin. +const ( + NlroManual = 0 + NlroWellKnown = 1 + NlroDHCP = 2 + NlroRouterAdvertisement = 3 + Nlro6to4 = 4 +) + +// NL_ROUTE_ORIGIN enumeration from nldef.h or +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_protocol. +const ( + MIB_IPPROTO_OTHER = 1 + MIB_IPPROTO_LOCAL = 2 + MIB_IPPROTO_NETMGMT = 3 + MIB_IPPROTO_ICMP = 4 + MIB_IPPROTO_EGP = 5 + MIB_IPPROTO_GGP = 6 + MIB_IPPROTO_HELLO = 7 + MIB_IPPROTO_RIP = 8 + MIB_IPPROTO_IS_IS = 9 + MIB_IPPROTO_ES_IS = 10 + MIB_IPPROTO_CISCO = 11 + MIB_IPPROTO_BBN = 12 + MIB_IPPROTO_OSPF = 13 + MIB_IPPROTO_BGP = 14 + MIB_IPPROTO_IDPR = 15 + MIB_IPPROTO_EIGRP = 16 + MIB_IPPROTO_DVMRP = 17 + MIB_IPPROTO_RPL = 18 + MIB_IPPROTO_DHCP = 19 + MIB_IPPROTO_NT_AUTOSTATIC = 10002 + MIB_IPPROTO_NT_STATIC = 10006 + MIB_IPPROTO_NT_STATIC_NON_DOD = 10007 +) + +// MIB_IPFORWARD_ROW2 stores information about an IP route entry. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2. +type MibIpForwardRow2 struct { + InterfaceLuid uint64 + InterfaceIndex uint32 + DestinationPrefix IpAddressPrefix + NextHop RawSockaddrInet + SitePrefixLength uint8 + ValidLifetime uint32 + PreferredLifetime uint32 + Metric uint32 + Protocol uint32 + Loopback uint8 + AutoconfigureAddress uint8 + Publish uint8 + Immortal uint8 + Age uint32 + Origin uint32 +} + +// MIB_IPFORWARD_TABLE2 contains a table of IP route entries. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_table2. +type MibIpForwardTable2 struct { + NumEntries uint32 + Table [1]MibIpForwardRow2 +} + +// Rows returns the IP route entries in the table. +func (t *MibIpForwardTable2) Rows() []MibIpForwardRow2 { + return unsafe.Slice(&t.Table[0], t.NumEntries) +} + // MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row. type MibUnicastIpAddressRow struct { diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index a58bc48b..f25b7308 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -182,13 +182,17 @@ var ( procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute") procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") + procFreeMibTable = modiphlpapi.NewProc("FreeMibTable") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex") + procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2") + procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2") procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") + procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2") procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") @@ -238,6 +242,7 @@ var ( procFindResourceW = modkernel32.NewProc("FindResourceW") procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") + procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer") procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") procFormatMessageW = modkernel32.NewProc("FormatMessageW") @@ -284,6 +289,7 @@ var ( procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId") + procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents") procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") procGetProcAddress = modkernel32.NewProc("GetProcAddress") @@ -546,25 +552,25 @@ var ( ) func cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) { - r0, _, _ := syscall.Syscall6(procCM_Get_DevNode_Status.Addr(), 4, uintptr(unsafe.Pointer(status)), uintptr(unsafe.Pointer(problemNumber)), uintptr(devInst), uintptr(flags), 0, 0) + r0, _, _ := syscall.SyscallN(procCM_Get_DevNode_Status.Addr(), uintptr(unsafe.Pointer(status)), uintptr(unsafe.Pointer(problemNumber)), uintptr(devInst), uintptr(flags)) ret = CONFIGRET(r0) return } func cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) { - r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_ListW.Addr(), 5, uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(unsafe.Pointer(buffer)), uintptr(bufferLen), uintptr(flags), 0) + r0, _, _ := syscall.SyscallN(procCM_Get_Device_Interface_ListW.Addr(), uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(unsafe.Pointer(buffer)), uintptr(bufferLen), uintptr(flags)) ret = CONFIGRET(r0) return } func cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) { - r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_List_SizeW.Addr(), 4, uintptr(unsafe.Pointer(len)), uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(flags), 0, 0) + r0, _, _ := syscall.SyscallN(procCM_Get_Device_Interface_List_SizeW.Addr(), uintptr(unsafe.Pointer(len)), uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(flags)) ret = CONFIGRET(r0) return } func cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) { - r0, _, _ := syscall.Syscall(procCM_MapCrToWin32Err.Addr(), 2, uintptr(configRet), uintptr(defaultWin32Error), 0) + r0, _, _ := syscall.SyscallN(procCM_MapCrToWin32Err.Addr(), uintptr(configRet), uintptr(defaultWin32Error)) ret = Errno(r0) return } @@ -574,7 +580,7 @@ func AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, if resetToDefault { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procAdjustTokenGroups.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) + r1, _, e1 := syscall.SyscallN(procAdjustTokenGroups.Addr(), uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) if r1 == 0 { err = errnoErr(e1) } @@ -586,7 +592,7 @@ func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tok if disableAllPrivileges { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) + r1, _, e1 := syscall.SyscallN(procAdjustTokenPrivileges.Addr(), uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) if r1 == 0 { err = errnoErr(e1) } @@ -594,7 +600,7 @@ func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tok } func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall12(procAllocateAndInitializeSid.Addr(), 11, uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid)), 0) + r1, _, e1 := syscall.SyscallN(procAllocateAndInitializeSid.Addr(), uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid))) if r1 == 0 { err = errnoErr(e1) } @@ -602,7 +608,7 @@ func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, s } func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) + r0, _, _ := syscall.SyscallN(procBuildSecurityDescriptorW.Addr(), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -610,7 +616,7 @@ func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries } func ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) { - r1, _, e1 := syscall.Syscall(procChangeServiceConfig2W.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(info))) + r1, _, e1 := syscall.SyscallN(procChangeServiceConfig2W.Addr(), uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(info))) if r1 == 0 { err = errnoErr(e1) } @@ -618,7 +624,7 @@ func ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err err } func ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) { - r1, _, e1 := syscall.Syscall12(procChangeServiceConfigW.Addr(), 11, uintptr(service), uintptr(serviceType), uintptr(startType), uintptr(errorControl), uintptr(unsafe.Pointer(binaryPathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), uintptr(unsafe.Pointer(displayName)), 0) + r1, _, e1 := syscall.SyscallN(procChangeServiceConfigW.Addr(), uintptr(service), uintptr(serviceType), uintptr(startType), uintptr(errorControl), uintptr(unsafe.Pointer(binaryPathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), uintptr(unsafe.Pointer(displayName))) if r1 == 0 { err = errnoErr(e1) } @@ -626,7 +632,7 @@ func ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, e } func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) { - r1, _, e1 := syscall.Syscall(procCheckTokenMembership.Addr(), 3, uintptr(tokenHandle), uintptr(unsafe.Pointer(sidToCheck)), uintptr(unsafe.Pointer(isMember))) + r1, _, e1 := syscall.SyscallN(procCheckTokenMembership.Addr(), uintptr(tokenHandle), uintptr(unsafe.Pointer(sidToCheck)), uintptr(unsafe.Pointer(isMember))) if r1 == 0 { err = errnoErr(e1) } @@ -634,7 +640,7 @@ func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) ( } func CloseServiceHandle(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCloseServiceHandle.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procCloseServiceHandle.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -642,7 +648,7 @@ func CloseServiceHandle(handle Handle) (err error) { } func ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procControlService.Addr(), 3, uintptr(service), uintptr(control), uintptr(unsafe.Pointer(status))) + r1, _, e1 := syscall.SyscallN(procControlService.Addr(), uintptr(service), uintptr(control), uintptr(unsafe.Pointer(status))) if r1 == 0 { err = errnoErr(e1) } @@ -650,7 +656,7 @@ func ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err } func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) + r1, _, e1 := syscall.SyscallN(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen))) if r1 == 0 { err = errnoErr(e1) } @@ -658,7 +664,7 @@ func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR } func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) + r1, _, e1 := syscall.SyscallN(procConvertSidToStringSidW.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid))) if r1 == 0 { err = errnoErr(e1) } @@ -675,7 +681,7 @@ func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision ui } func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.SyscallN(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size))) if r1 == 0 { err = errnoErr(e1) } @@ -683,7 +689,7 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision } func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) + r1, _, e1 := syscall.SyscallN(procConvertStringSidToSidW.Addr(), uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid))) if r1 == 0 { err = errnoErr(e1) } @@ -691,7 +697,7 @@ func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { } func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) + r1, _, e1 := syscall.SyscallN(procCopySid.Addr(), uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) if r1 == 0 { err = errnoErr(e1) } @@ -703,7 +709,7 @@ func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, proc if inheritHandles { _p0 = 1 } - r1, _, e1 := syscall.Syscall12(procCreateProcessAsUserW.Addr(), 11, uintptr(token), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0) + r1, _, e1 := syscall.SyscallN(procCreateProcessAsUserW.Addr(), uintptr(token), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo))) if r1 == 0 { err = errnoErr(e1) } @@ -711,7 +717,7 @@ func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, proc } func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall15(procCreateServiceW.Addr(), 13, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateServiceW.Addr(), uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -720,7 +726,7 @@ func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access } func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreateWellKnownSid.Addr(), 4, uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCreateWellKnownSid.Addr(), uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid))) if r1 == 0 { err = errnoErr(e1) } @@ -728,7 +734,7 @@ func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, s } func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCryptAcquireContextW.Addr(), uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -736,7 +742,7 @@ func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16 } func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { - r1, _, e1 := syscall.Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) + r1, _, e1 := syscall.SyscallN(procCryptGenRandom.Addr(), uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) if r1 == 0 { err = errnoErr(e1) } @@ -744,7 +750,7 @@ func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { } func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCryptReleaseContext.Addr(), uintptr(provhandle), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -752,7 +758,7 @@ func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { } func DeleteService(service Handle) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteService.Addr(), 1, uintptr(service), 0, 0) + r1, _, e1 := syscall.SyscallN(procDeleteService.Addr(), uintptr(service)) if r1 == 0 { err = errnoErr(e1) } @@ -760,7 +766,7 @@ func DeleteService(service Handle) (err error) { } func DeregisterEventSource(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procDeregisterEventSource.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procDeregisterEventSource.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -768,7 +774,7 @@ func DeregisterEventSource(handle Handle) (err error) { } func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) { - r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken))) + r1, _, e1 := syscall.SyscallN(procDuplicateTokenEx.Addr(), uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken))) if r1 == 0 { err = errnoErr(e1) } @@ -776,7 +782,7 @@ func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes } func EnumDependentServices(service Handle, activityState uint32, services *ENUM_SERVICE_STATUS, buffSize uint32, bytesNeeded *uint32, servicesReturned *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procEnumDependentServicesW.Addr(), 6, uintptr(service), uintptr(activityState), uintptr(unsafe.Pointer(services)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), uintptr(unsafe.Pointer(servicesReturned))) + r1, _, e1 := syscall.SyscallN(procEnumDependentServicesW.Addr(), uintptr(service), uintptr(activityState), uintptr(unsafe.Pointer(services)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), uintptr(unsafe.Pointer(servicesReturned))) if r1 == 0 { err = errnoErr(e1) } @@ -784,7 +790,7 @@ func EnumDependentServices(service Handle, activityState uint32, services *ENUM_ } func EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) { - r1, _, e1 := syscall.Syscall12(procEnumServicesStatusExW.Addr(), 10, uintptr(mgr), uintptr(infoLevel), uintptr(serviceType), uintptr(serviceState), uintptr(unsafe.Pointer(services)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), uintptr(unsafe.Pointer(servicesReturned)), uintptr(unsafe.Pointer(resumeHandle)), uintptr(unsafe.Pointer(groupName)), 0, 0) + r1, _, e1 := syscall.SyscallN(procEnumServicesStatusExW.Addr(), uintptr(mgr), uintptr(infoLevel), uintptr(serviceType), uintptr(serviceState), uintptr(unsafe.Pointer(services)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), uintptr(unsafe.Pointer(servicesReturned)), uintptr(unsafe.Pointer(resumeHandle)), uintptr(unsafe.Pointer(groupName))) if r1 == 0 { err = errnoErr(e1) } @@ -792,13 +798,13 @@ func EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serv } func EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) { - r0, _, _ := syscall.Syscall(procEqualSid.Addr(), 2, uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2)), 0) + r0, _, _ := syscall.SyscallN(procEqualSid.Addr(), uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2))) isEqual = r0 != 0 return } func FreeSid(sid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + r1, _, e1 := syscall.SyscallN(procFreeSid.Addr(), uintptr(unsafe.Pointer(sid))) if r1 != 0 { err = errnoErr(e1) } @@ -806,7 +812,7 @@ func FreeSid(sid *SID) (err error) { } func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) { - r1, _, e1 := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) + r1, _, e1 := syscall.SyscallN(procGetAce.Addr(), uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) if r1 == 0 { err = errnoErr(e1) } @@ -814,7 +820,7 @@ func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) { } func GetLengthSid(sid *SID) (len uint32) { - r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetLengthSid.Addr(), uintptr(unsafe.Pointer(sid))) len = uint32(r0) return } @@ -829,7 +835,7 @@ func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, security } func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + r0, _, _ := syscall.SyscallN(procGetNamedSecurityInfoW.Addr(), uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -837,7 +843,7 @@ func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securi } func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) + r1, _, e1 := syscall.SyscallN(procGetSecurityDescriptorControl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) if r1 == 0 { err = errnoErr(e1) } @@ -853,7 +859,7 @@ func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl if *daclDefaulted { _p1 = 1 } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetSecurityDescriptorDacl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1))) *daclPresent = _p0 != 0 *daclDefaulted = _p1 != 0 if r1 == 0 { @@ -867,7 +873,7 @@ func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefau if *groupDefaulted { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) + r1, _, e1 := syscall.SyscallN(procGetSecurityDescriptorGroup.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) *groupDefaulted = _p0 != 0 if r1 == 0 { err = errnoErr(e1) @@ -876,7 +882,7 @@ func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefau } func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetSecurityDescriptorLength.Addr(), uintptr(unsafe.Pointer(sd))) len = uint32(r0) return } @@ -886,7 +892,7 @@ func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefau if *ownerDefaulted { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) + r1, _, e1 := syscall.SyscallN(procGetSecurityDescriptorOwner.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) *ownerDefaulted = _p0 != 0 if r1 == 0 { err = errnoErr(e1) @@ -895,7 +901,7 @@ func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefau } func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + r0, _, _ := syscall.SyscallN(procGetSecurityDescriptorRMControl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -911,7 +917,7 @@ func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl if *saclDefaulted { _p1 = 1 } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetSecurityDescriptorSacl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1))) *saclPresent = _p0 != 0 *saclDefaulted = _p1 != 0 if r1 == 0 { @@ -921,7 +927,7 @@ func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl } func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + r0, _, _ := syscall.SyscallN(procGetSecurityInfo.Addr(), uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -929,25 +935,25 @@ func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformati } func getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) { - r0, _, _ := syscall.Syscall(procGetSidIdentifierAuthority.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetSidIdentifierAuthority.Addr(), uintptr(unsafe.Pointer(sid))) authority = (*SidIdentifierAuthority)(unsafe.Pointer(r0)) return } func getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthority.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(index), 0) + r0, _, _ := syscall.SyscallN(procGetSidSubAuthority.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(index)) subAuthority = (*uint32)(unsafe.Pointer(r0)) return } func getSidSubAuthorityCount(sid *SID) (count *uint8) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthorityCount.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetSidSubAuthorityCount.Addr(), uintptr(unsafe.Pointer(sid))) count = (*uint8)(unsafe.Pointer(r0)) return } func GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) + r1, _, e1 := syscall.SyscallN(procGetTokenInformation.Addr(), uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen))) if r1 == 0 { err = errnoErr(e1) } @@ -955,7 +961,7 @@ func GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint } func ImpersonateSelf(impersonationlevel uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) + r1, _, e1 := syscall.SyscallN(procImpersonateSelf.Addr(), uintptr(impersonationlevel)) if r1 == 0 { err = errnoErr(e1) } @@ -963,7 +969,7 @@ func ImpersonateSelf(impersonationlevel uint32) (err error) { } func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { - r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) + r1, _, e1 := syscall.SyscallN(procInitializeSecurityDescriptor.Addr(), uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision)) if r1 == 0 { err = errnoErr(e1) } @@ -979,7 +985,7 @@ func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint if rebootAfterShutdown { _p1 = 1 } - r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) + r1, _, e1 := syscall.SyscallN(procInitiateSystemShutdownExW.Addr(), uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) if r1 == 0 { err = errnoErr(e1) } @@ -987,7 +993,7 @@ func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint } func isTokenRestricted(tokenHandle Token) (ret bool, err error) { - r0, _, e1 := syscall.Syscall(procIsTokenRestricted.Addr(), 1, uintptr(tokenHandle), 0, 0) + r0, _, e1 := syscall.SyscallN(procIsTokenRestricted.Addr(), uintptr(tokenHandle)) ret = r0 != 0 if !ret { err = errnoErr(e1) @@ -996,25 +1002,25 @@ func isTokenRestricted(tokenHandle Token) (ret bool, err error) { } func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + r0, _, _ := syscall.SyscallN(procIsValidSecurityDescriptor.Addr(), uintptr(unsafe.Pointer(sd))) isValid = r0 != 0 return } func isValidSid(sid *SID) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + r0, _, _ := syscall.SyscallN(procIsValidSid.Addr(), uintptr(unsafe.Pointer(sid))) isValid = r0 != 0 return } func isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) { - r0, _, _ := syscall.Syscall(procIsWellKnownSid.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(sidType), 0) + r0, _, _ := syscall.SyscallN(procIsWellKnownSid.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(sidType)) isWellKnown = r0 != 0 return } func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + r1, _, e1 := syscall.SyscallN(procLookupAccountNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use))) if r1 == 0 { err = errnoErr(e1) } @@ -1022,7 +1028,7 @@ func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen } func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + r1, _, e1 := syscall.SyscallN(procLookupAccountSidW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use))) if r1 == 0 { err = errnoErr(e1) } @@ -1030,7 +1036,7 @@ func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint3 } func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { - r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + r1, _, e1 := syscall.SyscallN(procLookupPrivilegeValueW.Addr(), uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) if r1 == 0 { err = errnoErr(e1) } @@ -1038,7 +1044,7 @@ func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err err } func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) + r1, _, e1 := syscall.SyscallN(procMakeAbsoluteSD.Addr(), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize))) if r1 == 0 { err = errnoErr(e1) } @@ -1046,7 +1052,7 @@ func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DE } func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) + r1, _, e1 := syscall.SyscallN(procMakeSelfRelativeSD.Addr(), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) if r1 == 0 { err = errnoErr(e1) } @@ -1054,7 +1060,7 @@ func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURIT } func NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) { - r0, _, _ := syscall.Syscall(procNotifyServiceStatusChangeW.Addr(), 3, uintptr(service), uintptr(notifyMask), uintptr(unsafe.Pointer(notifier))) + r0, _, _ := syscall.SyscallN(procNotifyServiceStatusChangeW.Addr(), uintptr(service), uintptr(notifyMask), uintptr(unsafe.Pointer(notifier))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1062,7 +1068,7 @@ func NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERV } func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token))) + r1, _, e1 := syscall.SyscallN(procOpenProcessToken.Addr(), uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token))) if r1 == 0 { err = errnoErr(e1) } @@ -1070,7 +1076,7 @@ func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { } func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) + r0, _, e1 := syscall.SyscallN(procOpenSCManagerW.Addr(), uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1079,7 +1085,7 @@ func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (ha } func OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) + r0, _, e1 := syscall.SyscallN(procOpenServiceW.Addr(), uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1092,7 +1098,7 @@ func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token if openAsSelf { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + r1, _, e1 := syscall.SyscallN(procOpenThreadToken.Addr(), uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token))) if r1 == 0 { err = errnoErr(e1) } @@ -1100,7 +1106,7 @@ func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token } func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceConfig2W.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceConfig2W.Addr(), uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded))) if r1 == 0 { err = errnoErr(e1) } @@ -1108,7 +1114,7 @@ func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize } func QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceConfigW.Addr(), 4, uintptr(service), uintptr(unsafe.Pointer(serviceConfig)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceConfigW.Addr(), uintptr(service), uintptr(unsafe.Pointer(serviceConfig)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded))) if r1 == 0 { err = errnoErr(e1) } @@ -1120,7 +1126,7 @@ func QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInf if err != nil { return } - r1, _, e1 := syscall.Syscall(procQueryServiceDynamicInformation.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(dynamicInfo)) + r1, _, e1 := syscall.SyscallN(procQueryServiceDynamicInformation.Addr(), uintptr(service), uintptr(infoLevel), uintptr(dynamicInfo)) if r1 == 0 { err = errnoErr(e1) } @@ -1128,7 +1134,7 @@ func QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInf } func QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceLockStatusW.Addr(), 4, uintptr(mgr), uintptr(unsafe.Pointer(lockStatus)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceLockStatusW.Addr(), uintptr(mgr), uintptr(unsafe.Pointer(lockStatus)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded))) if r1 == 0 { err = errnoErr(e1) } @@ -1136,7 +1142,7 @@ func QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, b } func QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(status)), 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceStatus.Addr(), uintptr(service), uintptr(unsafe.Pointer(status))) if r1 == 0 { err = errnoErr(e1) } @@ -1144,7 +1150,7 @@ func QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) { } func QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceStatusEx.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceStatusEx.Addr(), uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded))) if r1 == 0 { err = errnoErr(e1) } @@ -1152,7 +1158,7 @@ func QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize } func RegCloseKey(key Handle) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0) + r0, _, _ := syscall.SyscallN(procRegCloseKey.Addr(), uintptr(key)) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1160,7 +1166,7 @@ func RegCloseKey(key Handle) (regerrno error) { } func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) + r0, _, _ := syscall.SyscallN(procRegEnumKeyExW.Addr(), uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime))) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1176,7 +1182,7 @@ func RegNotifyChangeKeyValue(key Handle, watchSubtree bool, notifyFilter uint32, if asynchronous { _p1 = 1 } - r0, _, _ := syscall.Syscall6(procRegNotifyChangeKeyValue.Addr(), 5, uintptr(key), uintptr(_p0), uintptr(notifyFilter), uintptr(event), uintptr(_p1), 0) + r0, _, _ := syscall.SyscallN(procRegNotifyChangeKeyValue.Addr(), uintptr(key), uintptr(_p0), uintptr(notifyFilter), uintptr(event), uintptr(_p1)) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1184,7 +1190,7 @@ func RegNotifyChangeKeyValue(key Handle, watchSubtree bool, notifyFilter uint32, } func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) + r0, _, _ := syscall.SyscallN(procRegOpenKeyExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result))) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1192,7 +1198,7 @@ func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint } func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := syscall.Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) + r0, _, _ := syscall.SyscallN(procRegQueryInfoKeyW.Addr(), uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1200,7 +1206,7 @@ func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint } func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) + r0, _, _ := syscall.SyscallN(procRegQueryValueExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -1208,7 +1214,7 @@ func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32 } func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procRegisterEventSourceW.Addr(), 2, uintptr(unsafe.Pointer(uncServerName)), uintptr(unsafe.Pointer(sourceName)), 0) + r0, _, e1 := syscall.SyscallN(procRegisterEventSourceW.Addr(), uintptr(unsafe.Pointer(uncServerName)), uintptr(unsafe.Pointer(sourceName))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1217,7 +1223,7 @@ func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Hand } func RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procRegisterServiceCtrlHandlerExW.Addr(), 3, uintptr(unsafe.Pointer(serviceName)), uintptr(handlerProc), uintptr(context)) + r0, _, e1 := syscall.SyscallN(procRegisterServiceCtrlHandlerExW.Addr(), uintptr(unsafe.Pointer(serviceName)), uintptr(handlerProc), uintptr(context)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1226,7 +1232,7 @@ func RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, cont } func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) + r1, _, e1 := syscall.SyscallN(procReportEventW.Addr(), uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) if r1 == 0 { err = errnoErr(e1) } @@ -1234,7 +1240,7 @@ func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrS } func RevertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + r1, _, e1 := syscall.SyscallN(procRevertToSelf.Addr()) if r1 == 0 { err = errnoErr(e1) } @@ -1242,7 +1248,7 @@ func RevertToSelf() (err error) { } func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { - r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) + r0, _, _ := syscall.SyscallN(procSetEntriesInAclW.Addr(), uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1250,7 +1256,7 @@ func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCE } func SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) { - r1, _, e1 := syscall.Syscall(procSetKernelObjectSecurity.Addr(), 3, uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor))) + r1, _, e1 := syscall.SyscallN(procSetKernelObjectSecurity.Addr(), uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor))) if r1 == 0 { err = errnoErr(e1) } @@ -1267,7 +1273,7 @@ func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, security } func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + r0, _, _ := syscall.SyscallN(procSetNamedSecurityInfoW.Addr(), uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1275,7 +1281,7 @@ func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securi } func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) + r1, _, e1 := syscall.SyscallN(procSetSecurityDescriptorControl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) if r1 == 0 { err = errnoErr(e1) } @@ -1291,7 +1297,7 @@ func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl * if daclDefaulted { _p1 = 1 } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetSecurityDescriptorDacl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1)) if r1 == 0 { err = errnoErr(e1) } @@ -1303,7 +1309,7 @@ func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaul if groupDefaulted { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) + r1, _, e1 := syscall.SyscallN(procSetSecurityDescriptorGroup.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) if r1 == 0 { err = errnoErr(e1) } @@ -1315,7 +1321,7 @@ func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaul if ownerDefaulted { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) + r1, _, e1 := syscall.SyscallN(procSetSecurityDescriptorOwner.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) if r1 == 0 { err = errnoErr(e1) } @@ -1323,7 +1329,7 @@ func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaul } func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { - syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + syscall.SyscallN(procSetSecurityDescriptorRMControl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl))) return } @@ -1336,7 +1342,7 @@ func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl * if saclDefaulted { _p1 = 1 } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetSecurityDescriptorSacl.Addr(), uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1)) if r1 == 0 { err = errnoErr(e1) } @@ -1344,7 +1350,7 @@ func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl * } func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - r0, _, _ := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + r0, _, _ := syscall.SyscallN(procSetSecurityInfo.Addr(), uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1352,7 +1358,7 @@ func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformati } func SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procSetServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(serviceStatus)), 0) + r1, _, e1 := syscall.SyscallN(procSetServiceStatus.Addr(), uintptr(service), uintptr(unsafe.Pointer(serviceStatus))) if r1 == 0 { err = errnoErr(e1) } @@ -1360,7 +1366,7 @@ func SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) } func SetThreadToken(thread *Handle, token Token) (err error) { - r1, _, e1 := syscall.Syscall(procSetThreadToken.Addr(), 2, uintptr(unsafe.Pointer(thread)), uintptr(token), 0) + r1, _, e1 := syscall.SyscallN(procSetThreadToken.Addr(), uintptr(unsafe.Pointer(thread)), uintptr(token)) if r1 == 0 { err = errnoErr(e1) } @@ -1368,7 +1374,7 @@ func SetThreadToken(thread *Handle, token Token) (err error) { } func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetTokenInformation.Addr(), uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen)) if r1 == 0 { err = errnoErr(e1) } @@ -1376,7 +1382,7 @@ func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint } func StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) { - r1, _, e1 := syscall.Syscall(procStartServiceCtrlDispatcherW.Addr(), 1, uintptr(unsafe.Pointer(serviceTable)), 0, 0) + r1, _, e1 := syscall.SyscallN(procStartServiceCtrlDispatcherW.Addr(), uintptr(unsafe.Pointer(serviceTable))) if r1 == 0 { err = errnoErr(e1) } @@ -1384,7 +1390,7 @@ func StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) { } func StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procStartServiceW.Addr(), 3, uintptr(service), uintptr(numArgs), uintptr(unsafe.Pointer(argVectors))) + r1, _, e1 := syscall.SyscallN(procStartServiceW.Addr(), uintptr(service), uintptr(numArgs), uintptr(unsafe.Pointer(argVectors))) if r1 == 0 { err = errnoErr(e1) } @@ -1392,7 +1398,7 @@ func StartService(service Handle, numArgs uint32, argVectors **uint16) (err erro } func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { - r1, _, e1 := syscall.Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCertAddCertificateContextToStore.Addr(), uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext))) if r1 == 0 { err = errnoErr(e1) } @@ -1400,7 +1406,7 @@ func CertAddCertificateContextToStore(store Handle, certContext *CertContext, ad } func CertCloseStore(store Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCertCloseStore.Addr(), uintptr(store), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -1408,7 +1414,7 @@ func CertCloseStore(store Handle, flags uint32) (err error) { } func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) + r0, _, e1 := syscall.SyscallN(procCertCreateCertificateContext.Addr(), uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) context = (*CertContext)(unsafe.Pointer(r0)) if context == nil { err = errnoErr(e1) @@ -1417,7 +1423,7 @@ func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, en } func CertDeleteCertificateFromStore(certContext *CertContext) (err error) { - r1, _, e1 := syscall.Syscall(procCertDeleteCertificateFromStore.Addr(), 1, uintptr(unsafe.Pointer(certContext)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCertDeleteCertificateFromStore.Addr(), uintptr(unsafe.Pointer(certContext))) if r1 == 0 { err = errnoErr(e1) } @@ -1425,13 +1431,13 @@ func CertDeleteCertificateFromStore(certContext *CertContext) (err error) { } func CertDuplicateCertificateContext(certContext *CertContext) (dupContext *CertContext) { - r0, _, _ := syscall.Syscall(procCertDuplicateCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(certContext)), 0, 0) + r0, _, _ := syscall.SyscallN(procCertDuplicateCertificateContext.Addr(), uintptr(unsafe.Pointer(certContext))) dupContext = (*CertContext)(unsafe.Pointer(r0)) return } func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) + r0, _, e1 := syscall.SyscallN(procCertEnumCertificatesInStore.Addr(), uintptr(store), uintptr(unsafe.Pointer(prevContext))) context = (*CertContext)(unsafe.Pointer(r0)) if context == nil { err = errnoErr(e1) @@ -1440,7 +1446,7 @@ func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (contex } func CertFindCertificateInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevCertContext *CertContext) (cert *CertContext, err error) { - r0, _, e1 := syscall.Syscall6(procCertFindCertificateInStore.Addr(), 6, uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevCertContext))) + r0, _, e1 := syscall.SyscallN(procCertFindCertificateInStore.Addr(), uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevCertContext))) cert = (*CertContext)(unsafe.Pointer(r0)) if cert == nil { err = errnoErr(e1) @@ -1449,7 +1455,7 @@ func CertFindCertificateInStore(store Handle, certEncodingType uint32, findFlags } func CertFindChainInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevChainContext *CertChainContext) (certchain *CertChainContext, err error) { - r0, _, e1 := syscall.Syscall6(procCertFindChainInStore.Addr(), 6, uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevChainContext))) + r0, _, e1 := syscall.SyscallN(procCertFindChainInStore.Addr(), uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevChainContext))) certchain = (*CertChainContext)(unsafe.Pointer(r0)) if certchain == nil { err = errnoErr(e1) @@ -1458,18 +1464,18 @@ func CertFindChainInStore(store Handle, certEncodingType uint32, findFlags uint3 } func CertFindExtension(objId *byte, countExtensions uint32, extensions *CertExtension) (ret *CertExtension) { - r0, _, _ := syscall.Syscall(procCertFindExtension.Addr(), 3, uintptr(unsafe.Pointer(objId)), uintptr(countExtensions), uintptr(unsafe.Pointer(extensions))) + r0, _, _ := syscall.SyscallN(procCertFindExtension.Addr(), uintptr(unsafe.Pointer(objId)), uintptr(countExtensions), uintptr(unsafe.Pointer(extensions))) ret = (*CertExtension)(unsafe.Pointer(r0)) return } func CertFreeCertificateChain(ctx *CertChainContext) { - syscall.Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + syscall.SyscallN(procCertFreeCertificateChain.Addr(), uintptr(unsafe.Pointer(ctx))) return } func CertFreeCertificateContext(ctx *CertContext) (err error) { - r1, _, e1 := syscall.Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCertFreeCertificateContext.Addr(), uintptr(unsafe.Pointer(ctx))) if r1 == 0 { err = errnoErr(e1) } @@ -1477,7 +1483,7 @@ func CertFreeCertificateContext(ctx *CertContext) (err error) { } func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { - r1, _, e1 := syscall.Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) + r1, _, e1 := syscall.SyscallN(procCertGetCertificateChain.Addr(), uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx))) if r1 == 0 { err = errnoErr(e1) } @@ -1485,13 +1491,13 @@ func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, a } func CertGetNameString(certContext *CertContext, nameType uint32, flags uint32, typePara unsafe.Pointer, name *uint16, size uint32) (chars uint32) { - r0, _, _ := syscall.Syscall6(procCertGetNameStringW.Addr(), 6, uintptr(unsafe.Pointer(certContext)), uintptr(nameType), uintptr(flags), uintptr(typePara), uintptr(unsafe.Pointer(name)), uintptr(size)) + r0, _, _ := syscall.SyscallN(procCertGetNameStringW.Addr(), uintptr(unsafe.Pointer(certContext)), uintptr(nameType), uintptr(flags), uintptr(typePara), uintptr(unsafe.Pointer(name)), uintptr(size)) chars = uint32(r0) return } func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) + r0, _, e1 := syscall.SyscallN(procCertOpenStore.Addr(), uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1500,7 +1506,7 @@ func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptPr } func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { - r0, _, e1 := syscall.Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) + r0, _, e1 := syscall.SyscallN(procCertOpenSystemStoreW.Addr(), uintptr(hprov), uintptr(unsafe.Pointer(name))) store = Handle(r0) if store == 0 { err = errnoErr(e1) @@ -1509,7 +1515,7 @@ func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { } func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { - r1, _, e1 := syscall.Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCertVerifyCertificateChainPolicy.Addr(), uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status))) if r1 == 0 { err = errnoErr(e1) } @@ -1521,7 +1527,7 @@ func CryptAcquireCertificatePrivateKey(cert *CertContext, flags uint32, paramete if *callerFreeProvOrNCryptKey { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procCryptAcquireCertificatePrivateKey.Addr(), 6, uintptr(unsafe.Pointer(cert)), uintptr(flags), uintptr(parameters), uintptr(unsafe.Pointer(cryptProvOrNCryptKey)), uintptr(unsafe.Pointer(keySpec)), uintptr(unsafe.Pointer(&_p0))) + r1, _, e1 := syscall.SyscallN(procCryptAcquireCertificatePrivateKey.Addr(), uintptr(unsafe.Pointer(cert)), uintptr(flags), uintptr(parameters), uintptr(unsafe.Pointer(cryptProvOrNCryptKey)), uintptr(unsafe.Pointer(keySpec)), uintptr(unsafe.Pointer(&_p0))) *callerFreeProvOrNCryptKey = _p0 != 0 if r1 == 0 { err = errnoErr(e1) @@ -1530,7 +1536,7 @@ func CryptAcquireCertificatePrivateKey(cert *CertContext, flags uint32, paramete } func CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procCryptDecodeObject.Addr(), 7, uintptr(encodingType), uintptr(unsafe.Pointer(structType)), uintptr(unsafe.Pointer(encodedBytes)), uintptr(lenEncodedBytes), uintptr(flags), uintptr(decoded), uintptr(unsafe.Pointer(decodedLen)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCryptDecodeObject.Addr(), uintptr(encodingType), uintptr(unsafe.Pointer(structType)), uintptr(unsafe.Pointer(encodedBytes)), uintptr(lenEncodedBytes), uintptr(flags), uintptr(decoded), uintptr(unsafe.Pointer(decodedLen))) if r1 == 0 { err = errnoErr(e1) } @@ -1538,7 +1544,7 @@ func CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte } func CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) { - r1, _, e1 := syscall.Syscall9(procCryptProtectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCryptProtectData.Addr(), uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut))) if r1 == 0 { err = errnoErr(e1) } @@ -1546,7 +1552,7 @@ func CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, } func CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *Handle, msg *Handle, context *unsafe.Pointer) (err error) { - r1, _, e1 := syscall.Syscall12(procCryptQueryObject.Addr(), 11, uintptr(objectType), uintptr(object), uintptr(expectedContentTypeFlags), uintptr(expectedFormatTypeFlags), uintptr(flags), uintptr(unsafe.Pointer(msgAndCertEncodingType)), uintptr(unsafe.Pointer(contentType)), uintptr(unsafe.Pointer(formatType)), uintptr(unsafe.Pointer(certStore)), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(context)), 0) + r1, _, e1 := syscall.SyscallN(procCryptQueryObject.Addr(), uintptr(objectType), uintptr(object), uintptr(expectedContentTypeFlags), uintptr(expectedFormatTypeFlags), uintptr(flags), uintptr(unsafe.Pointer(msgAndCertEncodingType)), uintptr(unsafe.Pointer(contentType)), uintptr(unsafe.Pointer(formatType)), uintptr(unsafe.Pointer(certStore)), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(context))) if r1 == 0 { err = errnoErr(e1) } @@ -1554,7 +1560,7 @@ func CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentT } func CryptUnprotectData(dataIn *DataBlob, name **uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) { - r1, _, e1 := syscall.Syscall9(procCryptUnprotectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCryptUnprotectData.Addr(), uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut))) if r1 == 0 { err = errnoErr(e1) } @@ -1562,7 +1568,7 @@ func CryptUnprotectData(dataIn *DataBlob, name **uint16, optionalEntropy *DataBl } func PFXImportCertStore(pfx *CryptDataBlob, password *uint16, flags uint32) (store Handle, err error) { - r0, _, e1 := syscall.Syscall(procPFXImportCertStore.Addr(), 3, uintptr(unsafe.Pointer(pfx)), uintptr(unsafe.Pointer(password)), uintptr(flags)) + r0, _, e1 := syscall.SyscallN(procPFXImportCertStore.Addr(), uintptr(unsafe.Pointer(pfx)), uintptr(unsafe.Pointer(password)), uintptr(flags)) store = Handle(r0) if store == 0 { err = errnoErr(e1) @@ -1571,7 +1577,7 @@ func PFXImportCertStore(pfx *CryptDataBlob, password *uint16, flags uint32) (sto } func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { - r0, _, _ := syscall.Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) + r0, _, _ := syscall.SyscallN(procDnsNameCompare_W.Addr(), uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2))) same = r0 != 0 return } @@ -1586,7 +1592,7 @@ func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSR } func _DnsQuery(name *uint16, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) { - r0, _, _ := syscall.Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(name)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr))) + r0, _, _ := syscall.SyscallN(procDnsQuery_W.Addr(), uintptr(unsafe.Pointer(name)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr))) if r0 != 0 { status = syscall.Errno(r0) } @@ -1594,12 +1600,12 @@ func _DnsQuery(name *uint16, qtype uint16, options uint32, extra *byte, qrs **DN } func DnsRecordListFree(rl *DNSRecord, freetype uint32) { - syscall.Syscall(procDnsRecordListFree.Addr(), 2, uintptr(unsafe.Pointer(rl)), uintptr(freetype), 0) + syscall.SyscallN(procDnsRecordListFree.Addr(), uintptr(unsafe.Pointer(rl)), uintptr(freetype)) return } func DwmGetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, size uint32) (ret error) { - r0, _, _ := syscall.Syscall6(procDwmGetWindowAttribute.Addr(), 4, uintptr(hwnd), uintptr(attribute), uintptr(value), uintptr(size), 0, 0) + r0, _, _ := syscall.SyscallN(procDwmGetWindowAttribute.Addr(), uintptr(hwnd), uintptr(attribute), uintptr(value), uintptr(size)) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1607,7 +1613,7 @@ func DwmGetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, si } func DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, size uint32) (ret error) { - r0, _, _ := syscall.Syscall6(procDwmSetWindowAttribute.Addr(), 4, uintptr(hwnd), uintptr(attribute), uintptr(value), uintptr(size), 0, 0) + r0, _, _ := syscall.SyscallN(procDwmSetWindowAttribute.Addr(), uintptr(hwnd), uintptr(attribute), uintptr(value), uintptr(size)) if r0 != 0 { ret = syscall.Errno(r0) } @@ -1615,15 +1621,20 @@ func DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, si } func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) { - r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0) + r0, _, _ := syscall.SyscallN(procCancelMibChangeNotify2.Addr(), uintptr(notificationHandle)) if r0 != 0 { errcode = syscall.Errno(r0) } return } +func FreeMibTable(memory unsafe.Pointer) { + syscall.SyscallN(procFreeMibTable.Addr(), uintptr(memory)) + return +} + func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { - r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) + r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1631,7 +1642,7 @@ func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapter } func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { - r0, _, _ := syscall.Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0) + r0, _, _ := syscall.SyscallN(procGetAdaptersInfo.Addr(), uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1639,7 +1650,7 @@ func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { } func getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) { - r0, _, _ := syscall.Syscall(procGetBestInterfaceEx.Addr(), 2, uintptr(sockaddr), uintptr(unsafe.Pointer(pdwBestIfIndex)), 0) + r0, _, _ := syscall.SyscallN(procGetBestInterfaceEx.Addr(), uintptr(sockaddr), uintptr(unsafe.Pointer(pdwBestIfIndex))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1647,7 +1658,7 @@ func getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcod } func GetIfEntry(pIfRow *MibIfRow) (errcode error) { - r0, _, _ := syscall.Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetIfEntry.Addr(), uintptr(unsafe.Pointer(pIfRow))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1655,7 +1666,23 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { } func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) { - r0, _, _ := syscall.Syscall(procGetIfEntry2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(row)), 0) + r0, _, _ := syscall.SyscallN(procGetIfEntry2Ex.Addr(), uintptr(level), uintptr(unsafe.Pointer(row))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetIpForwardTable2.Addr(), uintptr(family), uintptr(unsafe.Pointer(table))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1663,7 +1690,7 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) { } func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) { - r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1675,7 +1702,19 @@ func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsa if initialNotification { _p0 = 1 } - r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + r0, _, _ := syscall.SyscallN(procNotifyIpInterfaceChange.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.SyscallN(procNotifyRouteChange2.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1687,7 +1726,7 @@ func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext if initialNotification { _p0 = 1 } - r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + r0, _, _ := syscall.SyscallN(procNotifyUnicastIpAddressChange.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -1695,7 +1734,7 @@ func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext } func AddDllDirectory(path *uint16) (cookie uintptr, err error) { - r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + r0, _, e1 := syscall.SyscallN(procAddDllDirectory.Addr(), uintptr(unsafe.Pointer(path))) cookie = uintptr(r0) if cookie == 0 { err = errnoErr(e1) @@ -1704,7 +1743,7 @@ func AddDllDirectory(path *uint16) (cookie uintptr, err error) { } func AssignProcessToJobObject(job Handle, process Handle) (err error) { - r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) + r1, _, e1 := syscall.SyscallN(procAssignProcessToJobObject.Addr(), uintptr(job), uintptr(process)) if r1 == 0 { err = errnoErr(e1) } @@ -1712,7 +1751,7 @@ func AssignProcessToJobObject(job Handle, process Handle) (err error) { } func CancelIo(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) + r1, _, e1 := syscall.SyscallN(procCancelIo.Addr(), uintptr(s)) if r1 == 0 { err = errnoErr(e1) } @@ -1720,7 +1759,7 @@ func CancelIo(s Handle) (err error) { } func CancelIoEx(s Handle, o *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) + r1, _, e1 := syscall.SyscallN(procCancelIoEx.Addr(), uintptr(s), uintptr(unsafe.Pointer(o))) if r1 == 0 { err = errnoErr(e1) } @@ -1728,7 +1767,7 @@ func CancelIoEx(s Handle, o *Overlapped) (err error) { } func ClearCommBreak(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procClearCommBreak.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -1736,7 +1775,7 @@ func ClearCommBreak(handle Handle) (err error) { } func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) { - r1, _, e1 := syscall.Syscall(procClearCommError.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat))) + r1, _, e1 := syscall.SyscallN(procClearCommError.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat))) if r1 == 0 { err = errnoErr(e1) } @@ -1744,7 +1783,7 @@ func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error } func CloseHandle(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procCloseHandle.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -1752,12 +1791,12 @@ func CloseHandle(handle Handle) (err error) { } func ClosePseudoConsole(console Handle) { - syscall.Syscall(procClosePseudoConsole.Addr(), 1, uintptr(console), 0, 0) + syscall.SyscallN(procClosePseudoConsole.Addr(), uintptr(console)) return } func ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procConnectNamedPipe.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -1765,7 +1804,7 @@ func ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error) { } func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { - r1, _, e1 := syscall.Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) + r1, _, e1 := syscall.SyscallN(procCreateDirectoryW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa))) if r1 == 0 { err = errnoErr(e1) } @@ -1773,7 +1812,7 @@ func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { } func CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventExW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateEventExW.Addr(), uintptr(unsafe.Pointer(eventAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess)) handle = Handle(r0) if handle == 0 || e1 == ERROR_ALREADY_EXISTS { err = errnoErr(e1) @@ -1782,7 +1821,7 @@ func CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, d } func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateEventW.Addr(), uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 || e1 == ERROR_ALREADY_EXISTS { err = errnoErr(e1) @@ -1791,7 +1830,7 @@ func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialStat } func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) + r0, _, e1 := syscall.SyscallN(procCreateFileMappingW.Addr(), uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 || e1 == ERROR_ALREADY_EXISTS { err = errnoErr(e1) @@ -1800,7 +1839,7 @@ func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxS } func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateFileW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -1809,7 +1848,7 @@ func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes } func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) + r1, _, e1 := syscall.SyscallN(procCreateHardLinkW.Addr(), uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) if r1&0xff == 0 { err = errnoErr(e1) } @@ -1817,7 +1856,7 @@ func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr } func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateIoCompletionPort.Addr(), uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1826,7 +1865,7 @@ func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, thr } func CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateJobObjectW.Addr(), 2, uintptr(unsafe.Pointer(jobAttr)), uintptr(unsafe.Pointer(name)), 0) + r0, _, e1 := syscall.SyscallN(procCreateJobObjectW.Addr(), uintptr(unsafe.Pointer(jobAttr)), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -1835,7 +1874,7 @@ func CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, } func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + r0, _, e1 := syscall.SyscallN(procCreateMutexExW.Addr(), uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess)) handle = Handle(r0) if handle == 0 || e1 == ERROR_ALREADY_EXISTS { err = errnoErr(e1) @@ -1848,7 +1887,7 @@ func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16 if initialOwner { _p0 = 1 } - r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) + r0, _, e1 := syscall.SyscallN(procCreateMutexW.Addr(), uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 || e1 == ERROR_ALREADY_EXISTS { err = errnoErr(e1) @@ -1857,7 +1896,7 @@ func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16 } func CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + r0, _, e1 := syscall.SyscallN(procCreateNamedPipeW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa))) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -1866,7 +1905,7 @@ func CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances u } func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) + r1, _, e1 := syscall.SyscallN(procCreatePipe.Addr(), uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size)) if r1 == 0 { err = errnoErr(e1) } @@ -1878,7 +1917,7 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA if inheritHandles { _p0 = 1 } - r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCreateProcessW.Addr(), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo))) if r1 == 0 { err = errnoErr(e1) } @@ -1886,7 +1925,7 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA } func createPseudoConsole(size uint32, in Handle, out Handle, flags uint32, pconsole *Handle) (hr error) { - r0, _, _ := syscall.Syscall6(procCreatePseudoConsole.Addr(), 5, uintptr(size), uintptr(in), uintptr(out), uintptr(flags), uintptr(unsafe.Pointer(pconsole)), 0) + r0, _, _ := syscall.SyscallN(procCreatePseudoConsole.Addr(), uintptr(size), uintptr(in), uintptr(out), uintptr(flags), uintptr(unsafe.Pointer(pconsole))) if r0 != 0 { hr = syscall.Errno(r0) } @@ -1894,7 +1933,7 @@ func createPseudoConsole(size uint32, in Handle, out Handle, flags uint32, pcons } func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) + r1, _, e1 := syscall.SyscallN(procCreateSymbolicLinkW.Addr(), uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) if r1&0xff == 0 { err = errnoErr(e1) } @@ -1902,7 +1941,7 @@ func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags u } func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) + r0, _, e1 := syscall.SyscallN(procCreateToolhelp32Snapshot.Addr(), uintptr(flags), uintptr(processId)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -1911,7 +1950,7 @@ func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, er } func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) + r1, _, e1 := syscall.SyscallN(procDefineDosDeviceW.Addr(), uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) if r1 == 0 { err = errnoErr(e1) } @@ -1919,7 +1958,7 @@ func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err } func DeleteFile(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + r1, _, e1 := syscall.SyscallN(procDeleteFileW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { err = errnoErr(e1) } @@ -1927,12 +1966,12 @@ func DeleteFile(path *uint16) (err error) { } func deleteProcThreadAttributeList(attrlist *ProcThreadAttributeList) { - syscall.Syscall(procDeleteProcThreadAttributeList.Addr(), 1, uintptr(unsafe.Pointer(attrlist)), 0, 0) + syscall.SyscallN(procDeleteProcThreadAttributeList.Addr(), uintptr(unsafe.Pointer(attrlist))) return } func DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteVolumeMountPointW.Addr(), 1, uintptr(unsafe.Pointer(volumeMountPoint)), 0, 0) + r1, _, e1 := syscall.SyscallN(procDeleteVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(volumeMountPoint))) if r1 == 0 { err = errnoErr(e1) } @@ -1940,7 +1979,7 @@ func DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) { } func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procDeviceIoControl.Addr(), uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -1948,7 +1987,7 @@ func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBuff } func DisconnectNamedPipe(pipe Handle) (err error) { - r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(pipe), 0, 0) + r1, _, e1 := syscall.SyscallN(procDisconnectNamedPipe.Addr(), uintptr(pipe)) if r1 == 0 { err = errnoErr(e1) } @@ -1960,7 +1999,7 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP if bInheritHandle { _p0 = 1 } - r1, _, e1 := syscall.Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) + r1, _, e1 := syscall.SyscallN(procDuplicateHandle.Addr(), uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions)) if r1 == 0 { err = errnoErr(e1) } @@ -1968,7 +2007,7 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP } func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) { - r1, _, e1 := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(dwFunc), 0) + r1, _, e1 := syscall.SyscallN(procEscapeCommFunction.Addr(), uintptr(handle), uintptr(dwFunc)) if r1 == 0 { err = errnoErr(e1) } @@ -1976,12 +2015,12 @@ func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) { } func ExitProcess(exitcode uint32) { - syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) + syscall.SyscallN(procExitProcess.Addr(), uintptr(exitcode)) return } func ExpandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) + r0, _, e1 := syscall.SyscallN(procExpandEnvironmentStringsW.Addr(), uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -1990,7 +2029,7 @@ func ExpandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, } func FindClose(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFindClose.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -1998,7 +2037,7 @@ func FindClose(handle Handle) (err error) { } func FindCloseChangeNotification(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindCloseChangeNotification.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFindCloseChangeNotification.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -2019,7 +2058,7 @@ func _FindFirstChangeNotification(path *uint16, watchSubtree bool, notifyFilter if watchSubtree { _p1 = 1 } - r0, _, e1 := syscall.Syscall(procFindFirstChangeNotificationW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(_p1), uintptr(notifyFilter)) + r0, _, e1 := syscall.SyscallN(procFindFirstChangeNotificationW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(_p1), uintptr(notifyFilter)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -2028,7 +2067,7 @@ func _FindFirstChangeNotification(path *uint16, watchSubtree bool, notifyFilter } func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) + r0, _, e1 := syscall.SyscallN(procFindFirstFileW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data))) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -2037,7 +2076,7 @@ func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err erro } func FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) + r0, _, e1 := syscall.SyscallN(procFindFirstVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -2046,7 +2085,7 @@ func FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, b } func FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeW.Addr(), 2, uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength), 0) + r0, _, e1 := syscall.SyscallN(procFindFirstVolumeW.Addr(), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -2055,7 +2094,7 @@ func FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, er } func FindNextChangeNotification(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextChangeNotification.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFindNextChangeNotification.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -2063,7 +2102,7 @@ func FindNextChangeNotification(handle Handle) (err error) { } func findNextFile1(handle Handle, data *win32finddata1) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + r1, _, e1 := syscall.SyscallN(procFindNextFileW.Addr(), uintptr(handle), uintptr(unsafe.Pointer(data))) if r1 == 0 { err = errnoErr(e1) } @@ -2071,7 +2110,7 @@ func findNextFile1(handle Handle, data *win32finddata1) (err error) { } func FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeMountPointW.Addr(), 3, uintptr(findVolumeMountPoint), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) + r1, _, e1 := syscall.SyscallN(procFindNextVolumeMountPointW.Addr(), uintptr(findVolumeMountPoint), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) if r1 == 0 { err = errnoErr(e1) } @@ -2079,7 +2118,7 @@ func FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uin } func FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeW.Addr(), 3, uintptr(findVolume), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) + r1, _, e1 := syscall.SyscallN(procFindNextVolumeW.Addr(), uintptr(findVolume), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) if r1 == 0 { err = errnoErr(e1) } @@ -2087,7 +2126,7 @@ func FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) } func findResource(module Handle, name uintptr, resType uintptr) (resInfo Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindResourceW.Addr(), 3, uintptr(module), uintptr(name), uintptr(resType)) + r0, _, e1 := syscall.SyscallN(procFindResourceW.Addr(), uintptr(module), uintptr(name), uintptr(resType)) resInfo = Handle(r0) if resInfo == 0 { err = errnoErr(e1) @@ -2096,7 +2135,7 @@ func findResource(module Handle, name uintptr, resType uintptr) (resInfo Handle, } func FindVolumeClose(findVolume Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(findVolume), 0, 0) + r1, _, e1 := syscall.SyscallN(procFindVolumeClose.Addr(), uintptr(findVolume)) if r1 == 0 { err = errnoErr(e1) } @@ -2104,7 +2143,15 @@ func FindVolumeClose(findVolume Handle) (err error) { } func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeMountPointClose.Addr(), 1, uintptr(findVolumeMountPoint), 0, 0) + r1, _, e1 := syscall.SyscallN(procFindVolumeMountPointClose.Addr(), uintptr(findVolumeMountPoint)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FlushConsoleInputBuffer(console Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procFlushConsoleInputBuffer.Addr(), uintptr(console)) if r1 == 0 { err = errnoErr(e1) } @@ -2112,7 +2159,7 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { } func FlushFileBuffers(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFlushFileBuffers.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -2120,7 +2167,7 @@ func FlushFileBuffers(handle Handle) (err error) { } func FlushViewOfFile(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) + r1, _, e1 := syscall.SyscallN(procFlushViewOfFile.Addr(), uintptr(addr), uintptr(length)) if r1 == 0 { err = errnoErr(e1) } @@ -2132,7 +2179,7 @@ func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, bu if len(buf) > 0 { _p0 = &buf[0] } - r0, _, e1 := syscall.Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) + r0, _, e1 := syscall.SyscallN(procFormatMessageW.Addr(), uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args))) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2141,7 +2188,7 @@ func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, bu } func FreeEnvironmentStrings(envs *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) + r1, _, e1 := syscall.SyscallN(procFreeEnvironmentStringsW.Addr(), uintptr(unsafe.Pointer(envs))) if r1 == 0 { err = errnoErr(e1) } @@ -2149,7 +2196,7 @@ func FreeEnvironmentStrings(envs *uint16) (err error) { } func FreeLibrary(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFreeLibrary.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -2157,7 +2204,7 @@ func FreeLibrary(handle Handle) (err error) { } func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGenerateConsoleCtrlEvent.Addr(), 2, uintptr(ctrlEvent), uintptr(processGroupID), 0) + r1, _, e1 := syscall.SyscallN(procGenerateConsoleCtrlEvent.Addr(), uintptr(ctrlEvent), uintptr(processGroupID)) if r1 == 0 { err = errnoErr(e1) } @@ -2165,19 +2212,19 @@ func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err erro } func GetACP() (acp uint32) { - r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetACP.Addr()) acp = uint32(r0) return } func GetActiveProcessorCount(groupNumber uint16) (ret uint32) { - r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) + r0, _, _ := syscall.SyscallN(procGetActiveProcessorCount.Addr(), uintptr(groupNumber)) ret = uint32(r0) return } func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpModemStat)), 0) + r1, _, e1 := syscall.SyscallN(procGetCommModemStatus.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpModemStat))) if r1 == 0 { err = errnoErr(e1) } @@ -2185,7 +2232,7 @@ func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) { } func GetCommState(handle Handle, lpDCB *DCB) (err error) { - r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0) + r1, _, e1 := syscall.SyscallN(procGetCommState.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpDCB))) if r1 == 0 { err = errnoErr(e1) } @@ -2193,7 +2240,7 @@ func GetCommState(handle Handle, lpDCB *DCB) (err error) { } func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { - r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) + r1, _, e1 := syscall.SyscallN(procGetCommTimeouts.Addr(), uintptr(handle), uintptr(unsafe.Pointer(timeouts))) if r1 == 0 { err = errnoErr(e1) } @@ -2201,13 +2248,13 @@ func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { } func GetCommandLine() (cmd *uint16) { - r0, _, _ := syscall.Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetCommandLineW.Addr()) cmd = (*uint16)(unsafe.Pointer(r0)) return } func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + r1, _, e1 := syscall.SyscallN(procGetComputerNameExW.Addr(), uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) if r1 == 0 { err = errnoErr(e1) } @@ -2215,7 +2262,7 @@ func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { } func GetComputerName(buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) + r1, _, e1 := syscall.SyscallN(procGetComputerNameW.Addr(), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) if r1 == 0 { err = errnoErr(e1) } @@ -2223,7 +2270,7 @@ func GetComputerName(buf *uint16, n *uint32) (err error) { } func GetConsoleCP() (cp uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procGetConsoleCP.Addr()) cp = uint32(r0) if cp == 0 { err = errnoErr(e1) @@ -2232,7 +2279,7 @@ func GetConsoleCP() (cp uint32, err error) { } func GetConsoleMode(console Handle, mode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) + r1, _, e1 := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(console), uintptr(unsafe.Pointer(mode))) if r1 == 0 { err = errnoErr(e1) } @@ -2240,7 +2287,7 @@ func GetConsoleMode(console Handle, mode *uint32) (err error) { } func GetConsoleOutputCP() (cp uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetConsoleOutputCP.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procGetConsoleOutputCP.Addr()) cp = uint32(r0) if cp == 0 { err = errnoErr(e1) @@ -2249,7 +2296,7 @@ func GetConsoleOutputCP() (cp uint32, err error) { } func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) + r1, _, e1 := syscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(console), uintptr(unsafe.Pointer(info))) if r1 == 0 { err = errnoErr(e1) } @@ -2257,7 +2304,7 @@ func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) ( } func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + r0, _, e1 := syscall.SyscallN(procGetCurrentDirectoryW.Addr(), uintptr(buflen), uintptr(unsafe.Pointer(buf))) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2266,19 +2313,19 @@ func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { } func GetCurrentProcessId() (pid uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetCurrentProcessId.Addr()) pid = uint32(r0) return } func GetCurrentThreadId() (id uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentThreadId.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetCurrentThreadId.Addr()) id = uint32(r0) return } func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { - r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetDiskFreeSpaceExW.Addr(), uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes))) if r1 == 0 { err = errnoErr(e1) } @@ -2286,13 +2333,13 @@ func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint6 } func GetDriveType(rootPathName *uint16) (driveType uint32) { - r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetDriveTypeW.Addr(), uintptr(unsafe.Pointer(rootPathName))) driveType = uint32(r0) return } func GetEnvironmentStrings() (envs *uint16, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procGetEnvironmentStringsW.Addr()) envs = (*uint16)(unsafe.Pointer(r0)) if envs == nil { err = errnoErr(e1) @@ -2301,7 +2348,7 @@ func GetEnvironmentStrings() (envs *uint16, err error) { } func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) + r0, _, e1 := syscall.SyscallN(procGetEnvironmentVariableW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2310,7 +2357,7 @@ func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32 } func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) + r1, _, e1 := syscall.SyscallN(procGetExitCodeProcess.Addr(), uintptr(handle), uintptr(unsafe.Pointer(exitcode))) if r1 == 0 { err = errnoErr(e1) } @@ -2318,7 +2365,7 @@ func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { } func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) + r1, _, e1 := syscall.SyscallN(procGetFileAttributesExW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) if r1 == 0 { err = errnoErr(e1) } @@ -2326,7 +2373,7 @@ func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { } func GetFileAttributes(name *uint16) (attrs uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetFileAttributesW.Addr(), uintptr(unsafe.Pointer(name))) attrs = uint32(r0) if attrs == INVALID_FILE_ATTRIBUTES { err = errnoErr(e1) @@ -2335,7 +2382,7 @@ func GetFileAttributes(name *uint16) (attrs uint32, err error) { } func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + r1, _, e1 := syscall.SyscallN(procGetFileInformationByHandle.Addr(), uintptr(handle), uintptr(unsafe.Pointer(data))) if r1 == 0 { err = errnoErr(e1) } @@ -2343,7 +2390,7 @@ func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (e } func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetFileInformationByHandleEx.Addr(), uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen)) if r1 == 0 { err = errnoErr(e1) } @@ -2351,7 +2398,7 @@ func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, } func GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetFileTime.Addr(), uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime))) if r1 == 0 { err = errnoErr(e1) } @@ -2359,7 +2406,7 @@ func GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim } func GetFileType(filehandle Handle) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetFileType.Addr(), uintptr(filehandle)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2368,7 +2415,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) { } func GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetFinalPathNameByHandleW.Addr(), uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2377,7 +2424,7 @@ func GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32 } func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetFullPathNameW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname))) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2386,13 +2433,13 @@ func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) ( } func GetLargePageMinimum() (size uintptr) { - r0, _, _ := syscall.Syscall(procGetLargePageMinimum.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetLargePageMinimum.Addr()) size = uintptr(r0) return } func GetLastError() (lasterr error) { - r0, _, _ := syscall.Syscall(procGetLastError.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetLastError.Addr()) if r0 != 0 { lasterr = syscall.Errno(r0) } @@ -2400,7 +2447,7 @@ func GetLastError() (lasterr error) { } func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0) + r0, _, e1 := syscall.SyscallN(procGetLogicalDriveStringsW.Addr(), uintptr(bufferLength), uintptr(unsafe.Pointer(buffer))) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2409,7 +2456,7 @@ func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err } func GetLogicalDrives() (drivesBitMask uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDrives.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procGetLogicalDrives.Addr()) drivesBitMask = uint32(r0) if drivesBitMask == 0 { err = errnoErr(e1) @@ -2418,7 +2465,7 @@ func GetLogicalDrives() (drivesBitMask uint32, err error) { } func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) + r0, _, e1 := syscall.SyscallN(procGetLongPathNameW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2427,13 +2474,13 @@ func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err er } func GetMaximumProcessorCount(groupNumber uint16) (ret uint32) { - r0, _, _ := syscall.Syscall(procGetMaximumProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) + r0, _, _ := syscall.SyscallN(procGetMaximumProcessorCount.Addr(), uintptr(groupNumber)) ret = uint32(r0) return } func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) + r0, _, e1 := syscall.SyscallN(procGetModuleFileNameW.Addr(), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2442,7 +2489,7 @@ func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, } func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { - r1, _, e1 := syscall.Syscall(procGetModuleHandleExW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) + r1, _, e1 := syscall.SyscallN(procGetModuleHandleExW.Addr(), uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) if r1 == 0 { err = errnoErr(e1) } @@ -2450,7 +2497,7 @@ func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err er } func GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetNamedPipeClientProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(clientProcessID)), 0) + r1, _, e1 := syscall.SyscallN(procGetNamedPipeClientProcessId.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(clientProcessID))) if r1 == 0 { err = errnoErr(e1) } @@ -2458,7 +2505,7 @@ func GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err erro } func GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetNamedPipeHandleStateW.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize)) if r1 == 0 { err = errnoErr(e1) } @@ -2466,7 +2513,7 @@ func GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, m } func GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) + r1, _, e1 := syscall.SyscallN(procGetNamedPipeInfo.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances))) if r1 == 0 { err = errnoErr(e1) } @@ -2474,7 +2521,15 @@ func GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint3 } func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetNamedPipeServerProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(serverProcessID)), 0) + r1, _, e1 := syscall.SyscallN(procGetNamedPipeServerProcessId.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(serverProcessID))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents))) if r1 == 0 { err = errnoErr(e1) } @@ -2486,7 +2541,7 @@ func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wa if wait { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetOverlappedResult.Addr(), uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0)) if r1 == 0 { err = errnoErr(e1) } @@ -2494,7 +2549,7 @@ func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wa } func GetPriorityClass(process Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetPriorityClass.Addr(), 1, uintptr(process), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetPriorityClass.Addr(), uintptr(process)) ret = uint32(r0) if ret == 0 { err = errnoErr(e1) @@ -2512,7 +2567,7 @@ func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { } func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { - r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) + r0, _, e1 := syscall.SyscallN(procGetProcAddress.Addr(), uintptr(module), uintptr(unsafe.Pointer(procname))) proc = uintptr(r0) if proc == 0 { err = errnoErr(e1) @@ -2521,7 +2576,7 @@ func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { } func GetProcessId(process Handle) (id uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetProcessId.Addr(), 1, uintptr(process), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetProcessId.Addr(), uintptr(process)) id = uint32(r0) if id == 0 { err = errnoErr(e1) @@ -2530,7 +2585,7 @@ func GetProcessId(process Handle) (id uint32, err error) { } func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetProcessPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { err = errnoErr(e1) } @@ -2538,7 +2593,7 @@ func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uin } func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) + r1, _, e1 := syscall.SyscallN(procGetProcessShutdownParameters.Addr(), uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags))) if r1 == 0 { err = errnoErr(e1) } @@ -2546,7 +2601,7 @@ func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { } func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) + r1, _, e1 := syscall.SyscallN(procGetProcessTimes.Addr(), uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime))) if r1 == 0 { err = errnoErr(e1) } @@ -2554,12 +2609,12 @@ func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, } func GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) { - syscall.Syscall6(procGetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(unsafe.Pointer(lpMinimumWorkingSetSize)), uintptr(unsafe.Pointer(lpMaximumWorkingSetSize)), uintptr(unsafe.Pointer(flags)), 0, 0) + syscall.SyscallN(procGetProcessWorkingSetSizeEx.Addr(), uintptr(hProcess), uintptr(unsafe.Pointer(lpMinimumWorkingSetSize)), uintptr(unsafe.Pointer(lpMaximumWorkingSetSize)), uintptr(unsafe.Pointer(flags))) return } func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) + r1, _, e1 := syscall.SyscallN(procGetQueuedCompletionStatus.Addr(), uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout)) if r1 == 0 { err = errnoErr(e1) } @@ -2567,7 +2622,7 @@ func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overl } func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + r0, _, e1 := syscall.SyscallN(procGetShortPathNameW.Addr(), uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2576,12 +2631,12 @@ func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uin } func getStartupInfo(startupInfo *StartupInfo) { - syscall.Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) + syscall.SyscallN(procGetStartupInfoW.Addr(), uintptr(unsafe.Pointer(startupInfo))) return } func GetStdHandle(stdhandle uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetStdHandle.Addr(), uintptr(stdhandle)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -2590,7 +2645,7 @@ func GetStdHandle(stdhandle uint32) (handle Handle, err error) { } func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + r0, _, e1 := syscall.SyscallN(procGetSystemDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) len = uint32(r0) if len == 0 { err = errnoErr(e1) @@ -2599,7 +2654,7 @@ func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { } func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetSystemPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetSystemPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { err = errnoErr(e1) } @@ -2607,17 +2662,17 @@ func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint } func GetSystemTimeAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + syscall.SyscallN(procGetSystemTimeAsFileTime.Addr(), uintptr(unsafe.Pointer(time))) return } func GetSystemTimePreciseAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimePreciseAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + syscall.SyscallN(procGetSystemTimePreciseAsFileTime.Addr(), uintptr(unsafe.Pointer(time))) return } func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + r0, _, e1 := syscall.SyscallN(procGetSystemWindowsDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) len = uint32(r0) if len == 0 { err = errnoErr(e1) @@ -2626,7 +2681,7 @@ func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err erro } func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + r0, _, e1 := syscall.SyscallN(procGetTempPathW.Addr(), uintptr(buflen), uintptr(unsafe.Pointer(buf))) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2635,7 +2690,7 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { } func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetThreadPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetThreadPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { err = errnoErr(e1) } @@ -2643,13 +2698,13 @@ func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint } func getTickCount64() (ms uint64) { - r0, _, _ := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetTickCount64.Addr()) ms = uint64(r0) return } func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) + r0, _, e1 := syscall.SyscallN(procGetTimeZoneInformation.Addr(), uintptr(unsafe.Pointer(tzi))) rc = uint32(r0) if rc == 0xffffffff { err = errnoErr(e1) @@ -2658,7 +2713,7 @@ func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { } func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetUserPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetUserPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { err = errnoErr(e1) } @@ -2666,7 +2721,7 @@ func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16 } func GetVersion() (ver uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procGetVersion.Addr()) ver = uint32(r0) if ver == 0 { err = errnoErr(e1) @@ -2675,7 +2730,7 @@ func GetVersion() (ver uint32, err error) { } func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) + r1, _, e1 := syscall.SyscallN(procGetVolumeInformationByHandleW.Addr(), uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize)) if r1 == 0 { err = errnoErr(e1) } @@ -2683,7 +2738,7 @@ func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeN } func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationW.Addr(), 8, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) + r1, _, e1 := syscall.SyscallN(procGetVolumeInformationW.Addr(), uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize)) if r1 == 0 { err = errnoErr(e1) } @@ -2691,7 +2746,7 @@ func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volume } func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumeNameForVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) + r1, _, e1 := syscall.SyscallN(procGetVolumeNameForVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) if r1 == 0 { err = errnoErr(e1) } @@ -2699,7 +2754,7 @@ func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint } func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumePathNameW.Addr(), 3, uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) + r1, _, e1 := syscall.SyscallN(procGetVolumePathNameW.Addr(), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) if r1 == 0 { err = errnoErr(e1) } @@ -2707,7 +2762,7 @@ func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength ui } func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetVolumePathNamesForVolumeNameW.Addr(), 4, uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetVolumePathNamesForVolumeNameW.Addr(), uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength))) if r1 == 0 { err = errnoErr(e1) } @@ -2715,7 +2770,7 @@ func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16 } func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + r0, _, e1 := syscall.SyscallN(procGetWindowsDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) len = uint32(r0) if len == 0 { err = errnoErr(e1) @@ -2724,7 +2779,7 @@ func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { } func initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrcount uint32, flags uint32, size *uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procInitializeProcThreadAttributeList.Addr(), 4, uintptr(unsafe.Pointer(attrlist)), uintptr(attrcount), uintptr(flags), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.SyscallN(procInitializeProcThreadAttributeList.Addr(), uintptr(unsafe.Pointer(attrlist)), uintptr(attrcount), uintptr(flags), uintptr(unsafe.Pointer(size))) if r1 == 0 { err = errnoErr(e1) } @@ -2736,7 +2791,7 @@ func IsWow64Process(handle Handle, isWow64 *bool) (err error) { if *isWow64 { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) + r1, _, e1 := syscall.SyscallN(procIsWow64Process.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&_p0))) *isWow64 = _p0 != 0 if r1 == 0 { err = errnoErr(e1) @@ -2749,7 +2804,7 @@ func IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint1 if err != nil { return } - r1, _, e1 := syscall.Syscall(procIsWow64Process2.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(processMachine)), uintptr(unsafe.Pointer(nativeMachine))) + r1, _, e1 := syscall.SyscallN(procIsWow64Process2.Addr(), uintptr(handle), uintptr(unsafe.Pointer(processMachine)), uintptr(unsafe.Pointer(nativeMachine))) if r1 == 0 { err = errnoErr(e1) } @@ -2766,7 +2821,7 @@ func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, e } func _LoadLibraryEx(libname *uint16, zero Handle, flags uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadLibraryExW.Addr(), 3, uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) + r0, _, e1 := syscall.SyscallN(procLoadLibraryExW.Addr(), uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2784,7 +2839,7 @@ func LoadLibrary(libname string) (handle Handle, err error) { } func _LoadLibrary(libname *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) + r0, _, e1 := syscall.SyscallN(procLoadLibraryW.Addr(), uintptr(unsafe.Pointer(libname))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2793,7 +2848,7 @@ func _LoadLibrary(libname *uint16) (handle Handle, err error) { } func LoadResource(module Handle, resInfo Handle) (resData Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0) + r0, _, e1 := syscall.SyscallN(procLoadResource.Addr(), uintptr(module), uintptr(resInfo)) resData = Handle(r0) if resData == 0 { err = errnoErr(e1) @@ -2802,7 +2857,7 @@ func LoadResource(module Handle, resInfo Handle) (resData Handle, err error) { } func LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error) { - r0, _, e1 := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(length), 0) + r0, _, e1 := syscall.SyscallN(procLocalAlloc.Addr(), uintptr(flags), uintptr(length)) ptr = uintptr(r0) if ptr == 0 { err = errnoErr(e1) @@ -2811,7 +2866,7 @@ func LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error) { } func LocalFree(hmem Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) + r0, _, e1 := syscall.SyscallN(procLocalFree.Addr(), uintptr(hmem)) handle = Handle(r0) if handle != 0 { err = errnoErr(e1) @@ -2820,7 +2875,7 @@ func LocalFree(hmem Handle) (handle Handle, err error) { } func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) + r1, _, e1 := syscall.SyscallN(procLockFileEx.Addr(), uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -2828,7 +2883,7 @@ func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, byt } func LockResource(resData Handle) (addr uintptr, err error) { - r0, _, e1 := syscall.Syscall(procLockResource.Addr(), 1, uintptr(resData), 0, 0) + r0, _, e1 := syscall.SyscallN(procLockResource.Addr(), uintptr(resData)) addr = uintptr(r0) if addr == 0 { err = errnoErr(e1) @@ -2837,7 +2892,7 @@ func LockResource(resData Handle) (addr uintptr, err error) { } func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) + r0, _, e1 := syscall.SyscallN(procMapViewOfFile.Addr(), uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length)) addr = uintptr(r0) if addr == 0 { err = errnoErr(e1) @@ -2846,7 +2901,7 @@ func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow ui } func Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procModule32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0) + r1, _, e1 := syscall.SyscallN(procModule32FirstW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -2854,7 +2909,7 @@ func Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { } func Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procModule32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0) + r1, _, e1 := syscall.SyscallN(procModule32NextW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -2862,7 +2917,7 @@ func Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { } func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) + r1, _, e1 := syscall.SyscallN(procMoveFileExW.Addr(), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -2870,7 +2925,7 @@ func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { } func MoveFile(from *uint16, to *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) + r1, _, e1 := syscall.SyscallN(procMoveFileW.Addr(), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to))) if r1 == 0 { err = errnoErr(e1) } @@ -2878,7 +2933,7 @@ func MoveFile(from *uint16, to *uint16) (err error) { } func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { - r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) + r0, _, e1 := syscall.SyscallN(procMultiByteToWideChar.Addr(), uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) nwrite = int32(r0) if nwrite == 0 { err = errnoErr(e1) @@ -2891,7 +2946,7 @@ func OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle H if inheritHandle { _p0 = 1 } - r0, _, e1 := syscall.Syscall(procOpenEventW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + r0, _, e1 := syscall.SyscallN(procOpenEventW.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2904,7 +2959,7 @@ func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle H if inheritHandle { _p0 = 1 } - r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + r0, _, e1 := syscall.SyscallN(procOpenMutexW.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2917,7 +2972,7 @@ func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (ha if inheritHandle { _p0 = 1 } - r0, _, e1 := syscall.Syscall(procOpenProcess.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) + r0, _, e1 := syscall.SyscallN(procOpenProcess.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2930,7 +2985,7 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand if inheritHandle { _p0 = 1 } - r0, _, e1 := syscall.Syscall(procOpenThread.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) + r0, _, e1 := syscall.SyscallN(procOpenThread.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) handle = Handle(r0) if handle == 0 { err = errnoErr(e1) @@ -2939,7 +2994,7 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand } func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) + r1, _, e1 := syscall.SyscallN(procPostQueuedCompletionStatus.Addr(), uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -2947,7 +3002,7 @@ func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overla } func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + r1, _, e1 := syscall.SyscallN(procProcess32FirstW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(procEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -2955,7 +3010,7 @@ func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { } func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + r1, _, e1 := syscall.SyscallN(procProcess32NextW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(procEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -2963,7 +3018,7 @@ func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { } func ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procProcessIdToSessionId.Addr(), 2, uintptr(pid), uintptr(unsafe.Pointer(sessionid)), 0) + r1, _, e1 := syscall.SyscallN(procProcessIdToSessionId.Addr(), uintptr(pid), uintptr(unsafe.Pointer(sessionid))) if r1 == 0 { err = errnoErr(e1) } @@ -2971,7 +3026,7 @@ func ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) { } func PulseEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procPulseEvent.Addr(), 1, uintptr(event), 0, 0) + r1, _, e1 := syscall.SyscallN(procPulseEvent.Addr(), uintptr(event)) if r1 == 0 { err = errnoErr(e1) } @@ -2979,7 +3034,7 @@ func PulseEvent(event Handle) (err error) { } func PurgeComm(handle Handle, dwFlags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(dwFlags), 0) + r1, _, e1 := syscall.SyscallN(procPurgeComm.Addr(), uintptr(handle), uintptr(dwFlags)) if r1 == 0 { err = errnoErr(e1) } @@ -2987,7 +3042,7 @@ func PurgeComm(handle Handle, dwFlags uint32) (err error) { } func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) + r0, _, e1 := syscall.SyscallN(procQueryDosDeviceW.Addr(), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) n = uint32(r0) if n == 0 { err = errnoErr(e1) @@ -2996,7 +3051,7 @@ func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint3 } func QueryFullProcessImageName(proc Handle, flags uint32, exeName *uint16, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryFullProcessImageNameW.Addr(), 4, uintptr(proc), uintptr(flags), uintptr(unsafe.Pointer(exeName)), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.SyscallN(procQueryFullProcessImageNameW.Addr(), uintptr(proc), uintptr(flags), uintptr(unsafe.Pointer(exeName)), uintptr(unsafe.Pointer(size))) if r1 == 0 { err = errnoErr(e1) } @@ -3004,7 +3059,7 @@ func QueryFullProcessImageName(proc Handle, flags uint32, exeName *uint16, size } func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryInformationJobObject.Addr(), 5, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), uintptr(unsafe.Pointer(retlen)), 0) + r1, _, e1 := syscall.SyscallN(procQueryInformationJobObject.Addr(), uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), uintptr(unsafe.Pointer(retlen))) if r1 == 0 { err = errnoErr(e1) } @@ -3012,7 +3067,7 @@ func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobO } func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) + r1, _, e1 := syscall.SyscallN(procReadConsoleW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl))) if r1 == 0 { err = errnoErr(e1) } @@ -3024,7 +3079,7 @@ func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree if watchSubTree { _p0 = 1 } - r1, _, e1 := syscall.Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) + r1, _, e1 := syscall.SyscallN(procReadDirectoryChangesW.Addr(), uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) if r1 == 0 { err = errnoErr(e1) } @@ -3036,7 +3091,7 @@ func readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) ( if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procReadFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -3044,7 +3099,7 @@ func readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) ( } func ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesRead)), 0) + r1, _, e1 := syscall.SyscallN(procReadProcessMemory.Addr(), uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesRead))) if r1 == 0 { err = errnoErr(e1) } @@ -3052,7 +3107,7 @@ func ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size u } func ReleaseMutex(mutex Handle) (err error) { - r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) + r1, _, e1 := syscall.SyscallN(procReleaseMutex.Addr(), uintptr(mutex)) if r1 == 0 { err = errnoErr(e1) } @@ -3060,7 +3115,7 @@ func ReleaseMutex(mutex Handle) (err error) { } func RemoveDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + r1, _, e1 := syscall.SyscallN(procRemoveDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { err = errnoErr(e1) } @@ -3068,7 +3123,7 @@ func RemoveDirectory(path *uint16) (err error) { } func RemoveDllDirectory(cookie uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procRemoveDllDirectory.Addr(), 1, uintptr(cookie), 0, 0) + r1, _, e1 := syscall.SyscallN(procRemoveDllDirectory.Addr(), uintptr(cookie)) if r1 == 0 { err = errnoErr(e1) } @@ -3076,7 +3131,7 @@ func RemoveDllDirectory(cookie uintptr) (err error) { } func ResetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) + r1, _, e1 := syscall.SyscallN(procResetEvent.Addr(), uintptr(event)) if r1 == 0 { err = errnoErr(e1) } @@ -3084,7 +3139,7 @@ func ResetEvent(event Handle) (err error) { } func resizePseudoConsole(pconsole Handle, size uint32) (hr error) { - r0, _, _ := syscall.Syscall(procResizePseudoConsole.Addr(), 2, uintptr(pconsole), uintptr(size), 0) + r0, _, _ := syscall.SyscallN(procResizePseudoConsole.Addr(), uintptr(pconsole), uintptr(size)) if r0 != 0 { hr = syscall.Errno(r0) } @@ -3092,7 +3147,7 @@ func resizePseudoConsole(pconsole Handle, size uint32) (hr error) { } func ResumeThread(thread Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(thread), 0, 0) + r0, _, e1 := syscall.SyscallN(procResumeThread.Addr(), uintptr(thread)) ret = uint32(r0) if ret == 0xffffffff { err = errnoErr(e1) @@ -3101,7 +3156,7 @@ func ResumeThread(thread Handle) (ret uint32, err error) { } func SetCommBreak(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetCommBreak.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -3109,7 +3164,7 @@ func SetCommBreak(handle Handle) (err error) { } func SetCommMask(handle Handle, dwEvtMask uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommMask.Addr(), 2, uintptr(handle), uintptr(dwEvtMask), 0) + r1, _, e1 := syscall.SyscallN(procSetCommMask.Addr(), uintptr(handle), uintptr(dwEvtMask)) if r1 == 0 { err = errnoErr(e1) } @@ -3117,7 +3172,7 @@ func SetCommMask(handle Handle, dwEvtMask uint32) (err error) { } func SetCommState(handle Handle, lpDCB *DCB) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0) + r1, _, e1 := syscall.SyscallN(procSetCommState.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpDCB))) if r1 == 0 { err = errnoErr(e1) } @@ -3125,7 +3180,7 @@ func SetCommState(handle Handle, lpDCB *DCB) (err error) { } func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) + r1, _, e1 := syscall.SyscallN(procSetCommTimeouts.Addr(), uintptr(handle), uintptr(unsafe.Pointer(timeouts))) if r1 == 0 { err = errnoErr(e1) } @@ -3133,7 +3188,7 @@ func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { } func SetConsoleCP(cp uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleCP.Addr(), 1, uintptr(cp), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetConsoleCP.Addr(), uintptr(cp)) if r1 == 0 { err = errnoErr(e1) } @@ -3141,7 +3196,7 @@ func SetConsoleCP(cp uint32) (err error) { } func setConsoleCursorPosition(console Handle, position uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(position), 0) + r1, _, e1 := syscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(console), uintptr(position)) if r1 == 0 { err = errnoErr(e1) } @@ -3149,7 +3204,7 @@ func setConsoleCursorPosition(console Handle, position uint32) (err error) { } func SetConsoleMode(console Handle, mode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(console), uintptr(mode), 0) + r1, _, e1 := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(console), uintptr(mode)) if r1 == 0 { err = errnoErr(e1) } @@ -3157,7 +3212,7 @@ func SetConsoleMode(console Handle, mode uint32) (err error) { } func SetConsoleOutputCP(cp uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleOutputCP.Addr(), 1, uintptr(cp), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetConsoleOutputCP.Addr(), uintptr(cp)) if r1 == 0 { err = errnoErr(e1) } @@ -3165,7 +3220,7 @@ func SetConsoleOutputCP(cp uint32) (err error) { } func SetCurrentDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetCurrentDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { err = errnoErr(e1) } @@ -3173,7 +3228,7 @@ func SetCurrentDirectory(path *uint16) (err error) { } func SetDefaultDllDirectories(directoryFlags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetDefaultDllDirectories.Addr(), 1, uintptr(directoryFlags), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetDefaultDllDirectories.Addr(), uintptr(directoryFlags)) if r1 == 0 { err = errnoErr(e1) } @@ -3190,7 +3245,7 @@ func SetDllDirectory(path string) (err error) { } func _SetDllDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetDllDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetDllDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { err = errnoErr(e1) } @@ -3198,7 +3253,7 @@ func _SetDllDirectory(path *uint16) (err error) { } func SetEndOfFile(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetEndOfFile.Addr(), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -3206,7 +3261,7 @@ func SetEndOfFile(handle Handle) (err error) { } func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) + r1, _, e1 := syscall.SyscallN(procSetEnvironmentVariableW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value))) if r1 == 0 { err = errnoErr(e1) } @@ -3214,13 +3269,13 @@ func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { } func SetErrorMode(mode uint32) (ret uint32) { - r0, _, _ := syscall.Syscall(procSetErrorMode.Addr(), 1, uintptr(mode), 0, 0) + r0, _, _ := syscall.SyscallN(procSetErrorMode.Addr(), uintptr(mode)) ret = uint32(r0) return } func SetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(event), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetEvent.Addr(), uintptr(event)) if r1 == 0 { err = errnoErr(e1) } @@ -3228,7 +3283,7 @@ func SetEvent(event Handle) (err error) { } func SetFileAttributes(name *uint16, attrs uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) + r1, _, e1 := syscall.SyscallN(procSetFileAttributesW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(attrs)) if r1 == 0 { err = errnoErr(e1) } @@ -3236,7 +3291,7 @@ func SetFileAttributes(name *uint16, attrs uint32) (err error) { } func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procSetFileCompletionNotificationModes.Addr(), uintptr(handle), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -3244,7 +3299,7 @@ func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) } func SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetFileInformationByHandle.Addr(), uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen)) if r1 == 0 { err = errnoErr(e1) } @@ -3252,7 +3307,7 @@ func SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inB } func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { - r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) + r0, _, e1 := syscall.SyscallN(procSetFilePointer.Addr(), uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence)) newlowoffset = uint32(r0) if newlowoffset == 0xffffffff { err = errnoErr(e1) @@ -3261,7 +3316,7 @@ func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence } func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetFileTime.Addr(), uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime))) if r1 == 0 { err = errnoErr(e1) } @@ -3269,7 +3324,7 @@ func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim } func SetFileValidData(handle Handle, validDataLength int64) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0) + r1, _, e1 := syscall.SyscallN(procSetFileValidData.Addr(), uintptr(handle), uintptr(validDataLength)) if r1 == 0 { err = errnoErr(e1) } @@ -3277,7 +3332,7 @@ func SetFileValidData(handle Handle, validDataLength int64) (err error) { } func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) + r1, _, e1 := syscall.SyscallN(procSetHandleInformation.Addr(), uintptr(handle), uintptr(mask), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -3285,7 +3340,7 @@ func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) } func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) { - r0, _, e1 := syscall.Syscall6(procSetInformationJobObject.Addr(), 4, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), 0, 0) + r0, _, e1 := syscall.SyscallN(procSetInformationJobObject.Addr(), uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength)) ret = int(r0) if ret == 0 { err = errnoErr(e1) @@ -3294,7 +3349,7 @@ func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobOb } func SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetNamedPipeHandleState.Addr(), 4, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetNamedPipeHandleState.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout))) if r1 == 0 { err = errnoErr(e1) } @@ -3302,7 +3357,7 @@ func SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uin } func SetPriorityClass(process Handle, priorityClass uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetPriorityClass.Addr(), 2, uintptr(process), uintptr(priorityClass), 0) + r1, _, e1 := syscall.SyscallN(procSetPriorityClass.Addr(), uintptr(process), uintptr(priorityClass)) if r1 == 0 { err = errnoErr(e1) } @@ -3314,7 +3369,7 @@ func SetProcessPriorityBoost(process Handle, disable bool) (err error) { if disable { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) + r1, _, e1 := syscall.SyscallN(procSetProcessPriorityBoost.Addr(), uintptr(process), uintptr(_p0)) if r1 == 0 { err = errnoErr(e1) } @@ -3322,7 +3377,7 @@ func SetProcessPriorityBoost(process Handle, disable bool) (err error) { } func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procSetProcessShutdownParameters.Addr(), uintptr(level), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -3330,7 +3385,7 @@ func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { } func SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(dwMinimumWorkingSetSize), uintptr(dwMaximumWorkingSetSize), uintptr(flags), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetProcessWorkingSetSizeEx.Addr(), uintptr(hProcess), uintptr(dwMinimumWorkingSetSize), uintptr(dwMaximumWorkingSetSize), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -3338,7 +3393,7 @@ func SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr } func SetStdHandle(stdhandle uint32, handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0) + r1, _, e1 := syscall.SyscallN(procSetStdHandle.Addr(), uintptr(stdhandle), uintptr(handle)) if r1 == 0 { err = errnoErr(e1) } @@ -3346,7 +3401,7 @@ func SetStdHandle(stdhandle uint32, handle Handle) (err error) { } func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeLabelW.Addr(), 2, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName)), 0) + r1, _, e1 := syscall.SyscallN(procSetVolumeLabelW.Addr(), uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName))) if r1 == 0 { err = errnoErr(e1) } @@ -3354,7 +3409,7 @@ func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { } func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeMountPointW.Addr(), 2, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), 0) + r1, _, e1 := syscall.SyscallN(procSetVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName))) if r1 == 0 { err = errnoErr(e1) } @@ -3362,7 +3417,7 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro } func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetupComm.Addr(), 3, uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue)) + r1, _, e1 := syscall.SyscallN(procSetupComm.Addr(), uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue)) if r1 == 0 { err = errnoErr(e1) } @@ -3370,7 +3425,7 @@ func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) { } func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) { - r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0) + r0, _, e1 := syscall.SyscallN(procSizeofResource.Addr(), uintptr(module), uintptr(resInfo)) size = uint32(r0) if size == 0 { err = errnoErr(e1) @@ -3383,13 +3438,13 @@ func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { if alertable { _p0 = 1 } - r0, _, _ := syscall.Syscall(procSleepEx.Addr(), 2, uintptr(milliseconds), uintptr(_p0), 0) + r0, _, _ := syscall.SyscallN(procSleepEx.Addr(), uintptr(milliseconds), uintptr(_p0)) ret = uint32(r0) return } func TerminateJobObject(job Handle, exitCode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateJobObject.Addr(), 2, uintptr(job), uintptr(exitCode), 0) + r1, _, e1 := syscall.SyscallN(procTerminateJobObject.Addr(), uintptr(job), uintptr(exitCode)) if r1 == 0 { err = errnoErr(e1) } @@ -3397,7 +3452,7 @@ func TerminateJobObject(job Handle, exitCode uint32) (err error) { } func TerminateProcess(handle Handle, exitcode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) + r1, _, e1 := syscall.SyscallN(procTerminateProcess.Addr(), uintptr(handle), uintptr(exitcode)) if r1 == 0 { err = errnoErr(e1) } @@ -3405,7 +3460,7 @@ func TerminateProcess(handle Handle, exitcode uint32) (err error) { } func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32First.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) + r1, _, e1 := syscall.SyscallN(procThread32First.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -3413,7 +3468,7 @@ func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { } func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32Next.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) + r1, _, e1 := syscall.SyscallN(procThread32Next.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry))) if r1 == 0 { err = errnoErr(e1) } @@ -3421,7 +3476,7 @@ func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { } func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procUnlockFileEx.Addr(), uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -3429,7 +3484,7 @@ func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint3 } func UnmapViewOfFile(addr uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) + r1, _, e1 := syscall.SyscallN(procUnmapViewOfFile.Addr(), uintptr(addr)) if r1 == 0 { err = errnoErr(e1) } @@ -3437,7 +3492,7 @@ func UnmapViewOfFile(addr uintptr) (err error) { } func updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procUpdateProcThreadAttribute.Addr(), 7, uintptr(unsafe.Pointer(attrlist)), uintptr(flags), uintptr(attr), uintptr(value), uintptr(size), uintptr(prevvalue), uintptr(unsafe.Pointer(returnedsize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procUpdateProcThreadAttribute.Addr(), uintptr(unsafe.Pointer(attrlist)), uintptr(flags), uintptr(attr), uintptr(value), uintptr(size), uintptr(prevvalue), uintptr(unsafe.Pointer(returnedsize))) if r1 == 0 { err = errnoErr(e1) } @@ -3445,7 +3500,7 @@ func updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, } func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procVirtualAlloc.Addr(), 4, uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect), 0, 0) + r0, _, e1 := syscall.SyscallN(procVirtualAlloc.Addr(), uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect)) value = uintptr(r0) if value == 0 { err = errnoErr(e1) @@ -3454,7 +3509,7 @@ func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint3 } func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualFree.Addr(), 3, uintptr(address), uintptr(size), uintptr(freetype)) + r1, _, e1 := syscall.SyscallN(procVirtualFree.Addr(), uintptr(address), uintptr(size), uintptr(freetype)) if r1 == 0 { err = errnoErr(e1) } @@ -3462,7 +3517,7 @@ func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { } func VirtualLock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) + r1, _, e1 := syscall.SyscallN(procVirtualLock.Addr(), uintptr(addr), uintptr(length)) if r1 == 0 { err = errnoErr(e1) } @@ -3470,7 +3525,7 @@ func VirtualLock(addr uintptr, length uintptr) (err error) { } func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procVirtualProtect.Addr(), 4, uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect)), 0, 0) + r1, _, e1 := syscall.SyscallN(procVirtualProtect.Addr(), uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect))) if r1 == 0 { err = errnoErr(e1) } @@ -3478,7 +3533,7 @@ func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect } func VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procVirtualProtectEx.Addr(), 5, uintptr(process), uintptr(address), uintptr(size), uintptr(newProtect), uintptr(unsafe.Pointer(oldProtect)), 0) + r1, _, e1 := syscall.SyscallN(procVirtualProtectEx.Addr(), uintptr(process), uintptr(address), uintptr(size), uintptr(newProtect), uintptr(unsafe.Pointer(oldProtect))) if r1 == 0 { err = errnoErr(e1) } @@ -3486,7 +3541,7 @@ func VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect } func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualQuery.Addr(), 3, uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) + r1, _, e1 := syscall.SyscallN(procVirtualQuery.Addr(), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) if r1 == 0 { err = errnoErr(e1) } @@ -3494,7 +3549,7 @@ func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintpt } func VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procVirtualQueryEx.Addr(), 4, uintptr(process), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length), 0, 0) + r1, _, e1 := syscall.SyscallN(procVirtualQueryEx.Addr(), uintptr(process), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) if r1 == 0 { err = errnoErr(e1) } @@ -3502,7 +3557,7 @@ func VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformat } func VirtualUnlock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) + r1, _, e1 := syscall.SyscallN(procVirtualUnlock.Addr(), uintptr(addr), uintptr(length)) if r1 == 0 { err = errnoErr(e1) } @@ -3510,13 +3565,13 @@ func VirtualUnlock(addr uintptr, length uintptr) (err error) { } func WTSGetActiveConsoleSessionId() (sessionID uint32) { - r0, _, _ := syscall.Syscall(procWTSGetActiveConsoleSessionId.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procWTSGetActiveConsoleSessionId.Addr()) sessionID = uint32(r0) return } func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procWaitCommEvent.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped))) + r1, _, e1 := syscall.SyscallN(procWaitCommEvent.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -3528,7 +3583,7 @@ func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMil if waitAll { _p0 = 1 } - r0, _, e1 := syscall.Syscall6(procWaitForMultipleObjects.Addr(), 4, uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds), 0, 0) + r0, _, e1 := syscall.SyscallN(procWaitForMultipleObjects.Addr(), uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds)) event = uint32(r0) if event == 0xffffffff { err = errnoErr(e1) @@ -3537,7 +3592,7 @@ func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMil } func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { - r0, _, e1 := syscall.Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) + r0, _, e1 := syscall.SyscallN(procWaitForSingleObject.Addr(), uintptr(handle), uintptr(waitMilliseconds)) event = uint32(r0) if event == 0xffffffff { err = errnoErr(e1) @@ -3546,7 +3601,7 @@ func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, } func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) + r1, _, e1 := syscall.SyscallN(procWriteConsoleW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved))) if r1 == 0 { err = errnoErr(e1) } @@ -3558,7 +3613,7 @@ func writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procWriteFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -3566,7 +3621,7 @@ func writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) } func WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesWritten)), 0) + r1, _, e1 := syscall.SyscallN(procWriteProcessMemory.Addr(), uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesWritten))) if r1 == 0 { err = errnoErr(e1) } @@ -3574,7 +3629,7 @@ func WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size } func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) + r1, _, e1 := syscall.SyscallN(procAcceptEx.Addr(), uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { err = errnoErr(e1) } @@ -3582,12 +3637,12 @@ func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32 } func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { - syscall.Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) + syscall.SyscallN(procGetAcceptExSockaddrs.Addr(), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen))) return } func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) + r1, _, e1 := syscall.SyscallN(procTransmitFile.Addr(), uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -3595,7 +3650,7 @@ func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint } func NetApiBufferFree(buf *byte) (neterr error) { - r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) + r0, _, _ := syscall.SyscallN(procNetApiBufferFree.Addr(), uintptr(unsafe.Pointer(buf))) if r0 != 0 { neterr = syscall.Errno(r0) } @@ -3603,7 +3658,7 @@ func NetApiBufferFree(buf *byte) (neterr error) { } func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) { - r0, _, _ := syscall.Syscall(procNetGetJoinInformation.Addr(), 3, uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType))) + r0, _, _ := syscall.SyscallN(procNetGetJoinInformation.Addr(), uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType))) if r0 != 0 { neterr = syscall.Errno(r0) } @@ -3611,7 +3666,7 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete } func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) { - r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle)), 0) + r0, _, _ := syscall.SyscallN(procNetUserEnum.Addr(), uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle))) if r0 != 0 { neterr = syscall.Errno(r0) } @@ -3619,7 +3674,7 @@ func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, pr } func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { - r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) + r0, _, _ := syscall.SyscallN(procNetUserGetInfo.Addr(), uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf))) if r0 != 0 { neterr = syscall.Errno(r0) } @@ -3627,7 +3682,7 @@ func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **by } func NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(attributes), uintptr(share), uintptr(disposition), uintptr(options), uintptr(eabuffer), uintptr(ealength), 0) + r0, _, _ := syscall.SyscallN(procNtCreateFile.Addr(), uintptr(unsafe.Pointer(handle)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(attributes), uintptr(share), uintptr(disposition), uintptr(options), uintptr(eabuffer), uintptr(ealength)) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3635,7 +3690,7 @@ func NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO } func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) { - r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, _ := syscall.SyscallN(procNtCreateNamedPipeFile.Addr(), uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3643,7 +3698,7 @@ func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, i } func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen)), 0) + r0, _, _ := syscall.SyscallN(procNtQueryInformationProcess.Addr(), uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3651,7 +3706,7 @@ func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe } func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen), uintptr(unsafe.Pointer(retLen)), 0, 0) + r0, _, _ := syscall.SyscallN(procNtQuerySystemInformation.Addr(), uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen), uintptr(unsafe.Pointer(retLen))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3659,7 +3714,7 @@ func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInf } func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class), 0) + r0, _, _ := syscall.SyscallN(procNtSetInformationFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class)) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3667,7 +3722,7 @@ func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, } func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procNtSetInformationProcess.Addr(), 4, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), 0, 0) + r0, _, _ := syscall.SyscallN(procNtSetInformationProcess.Addr(), uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen)) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3675,7 +3730,7 @@ func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.P } func NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) { - r0, _, _ := syscall.Syscall(procNtSetSystemInformation.Addr(), 3, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen)) + r0, _, _ := syscall.SyscallN(procNtSetSystemInformation.Addr(), uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen)) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3683,13 +3738,13 @@ func NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoL } func RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) { - r0, _, _ := syscall.Syscall(procRtlAddFunctionTable.Addr(), 3, uintptr(unsafe.Pointer(functionTable)), uintptr(entryCount), uintptr(baseAddress)) + r0, _, _ := syscall.SyscallN(procRtlAddFunctionTable.Addr(), uintptr(unsafe.Pointer(functionTable)), uintptr(entryCount), uintptr(baseAddress)) ret = r0 != 0 return } func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { - r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(acl)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDefaultNpAcl.Addr(), uintptr(unsafe.Pointer(acl))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3697,13 +3752,13 @@ func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { } func RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) { - r0, _, _ := syscall.Syscall(procRtlDeleteFunctionTable.Addr(), 1, uintptr(unsafe.Pointer(functionTable)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDeleteFunctionTable.Addr(), uintptr(unsafe.Pointer(functionTable))) ret = r0 != 0 return } func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3711,7 +3766,7 @@ func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFile } func RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { - r0, _, _ := syscall.Syscall6(procRtlDosPathNameToRelativeNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDosPathNameToRelativeNtPathName_U_WithStatus.Addr(), uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3719,18 +3774,18 @@ func RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString } func RtlGetCurrentPeb() (peb *PEB) { - r0, _, _ := syscall.Syscall(procRtlGetCurrentPeb.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procRtlGetCurrentPeb.Addr()) peb = (*PEB)(unsafe.Pointer(r0)) return } func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { - syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) + syscall.SyscallN(procRtlGetNtVersionNumbers.Addr(), uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) return } func rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) { - r0, _, _ := syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlGetVersion.Addr(), uintptr(unsafe.Pointer(info))) if r0 != 0 { ntstatus = NTStatus(r0) } @@ -3738,23 +3793,23 @@ func rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) { } func RtlInitString(destinationString *NTString, sourceString *byte) { - syscall.Syscall(procRtlInitString.Addr(), 2, uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString)), 0) + syscall.SyscallN(procRtlInitString.Addr(), uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString))) return } func RtlInitUnicodeString(destinationString *NTUnicodeString, sourceString *uint16) { - syscall.Syscall(procRtlInitUnicodeString.Addr(), 2, uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString)), 0) + syscall.SyscallN(procRtlInitUnicodeString.Addr(), uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString))) return } func rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) { - r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(ntstatus), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlNtStatusToDosErrorNoTeb.Addr(), uintptr(ntstatus)) ret = syscall.Errno(r0) return } func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) + r0, _, _ := syscall.SyscallN(procCLSIDFromString.Addr(), uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -3762,7 +3817,7 @@ func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { } func coCreateGuid(pguid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCoCreateGuid.Addr(), 1, uintptr(unsafe.Pointer(pguid)), 0, 0) + r0, _, _ := syscall.SyscallN(procCoCreateGuid.Addr(), uintptr(unsafe.Pointer(pguid))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -3770,7 +3825,7 @@ func coCreateGuid(pguid *GUID) (ret error) { } func CoGetObject(name *uint16, bindOpts *BIND_OPTS3, guid *GUID, functionTable **uintptr) (ret error) { - r0, _, _ := syscall.Syscall6(procCoGetObject.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bindOpts)), uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(functionTable)), 0, 0) + r0, _, _ := syscall.SyscallN(procCoGetObject.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bindOpts)), uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(functionTable))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -3778,7 +3833,7 @@ func CoGetObject(name *uint16, bindOpts *BIND_OPTS3, guid *GUID, functionTable * } func CoInitializeEx(reserved uintptr, coInit uint32) (ret error) { - r0, _, _ := syscall.Syscall(procCoInitializeEx.Addr(), 2, uintptr(reserved), uintptr(coInit), 0) + r0, _, _ := syscall.SyscallN(procCoInitializeEx.Addr(), uintptr(reserved), uintptr(coInit)) if r0 != 0 { ret = syscall.Errno(r0) } @@ -3786,23 +3841,23 @@ func CoInitializeEx(reserved uintptr, coInit uint32) (ret error) { } func CoTaskMemFree(address unsafe.Pointer) { - syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0) + syscall.SyscallN(procCoTaskMemFree.Addr(), uintptr(address)) return } func CoUninitialize() { - syscall.Syscall(procCoUninitialize.Addr(), 0, 0, 0, 0) + syscall.SyscallN(procCoUninitialize.Addr()) return } func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { - r0, _, _ := syscall.Syscall(procStringFromGUID2.Addr(), 3, uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) + r0, _, _ := syscall.SyscallN(procStringFromGUID2.Addr(), uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) chars = int32(r0) return } func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procEnumProcessModules.Addr(), 4, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), 0, 0) + r1, _, e1 := syscall.SyscallN(procEnumProcessModules.Addr(), uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded))) if r1 == 0 { err = errnoErr(e1) } @@ -3810,7 +3865,7 @@ func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uin } func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procEnumProcessModulesEx.Addr(), 5, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag), 0) + r1, _, e1 := syscall.SyscallN(procEnumProcessModulesEx.Addr(), uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag)) if r1 == 0 { err = errnoErr(e1) } @@ -3818,7 +3873,7 @@ func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *u } func enumProcesses(processIds *uint32, nSize uint32, bytesReturned *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(processIds)), uintptr(nSize), uintptr(unsafe.Pointer(bytesReturned))) + r1, _, e1 := syscall.SyscallN(procEnumProcesses.Addr(), uintptr(unsafe.Pointer(processIds)), uintptr(nSize), uintptr(unsafe.Pointer(bytesReturned))) if r1 == 0 { err = errnoErr(e1) } @@ -3826,7 +3881,7 @@ func enumProcesses(processIds *uint32, nSize uint32, bytesReturned *uint32) (err } func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetModuleBaseNameW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetModuleBaseNameW.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size)) if r1 == 0 { err = errnoErr(e1) } @@ -3834,7 +3889,7 @@ func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uin } func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetModuleFileNameExW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetModuleFileNameExW.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) if r1 == 0 { err = errnoErr(e1) } @@ -3842,7 +3897,7 @@ func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size u } func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetModuleInformation.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetModuleInformation.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb)) if r1 == 0 { err = errnoErr(e1) } @@ -3850,7 +3905,7 @@ func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb } func QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) { - r1, _, e1 := syscall.Syscall(procQueryWorkingSetEx.Addr(), 3, uintptr(process), uintptr(pv), uintptr(cb)) + r1, _, e1 := syscall.SyscallN(procQueryWorkingSetEx.Addr(), uintptr(process), uintptr(pv), uintptr(cb)) if r1 == 0 { err = errnoErr(e1) } @@ -3862,7 +3917,7 @@ func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callb if ret != nil { return } - r0, _, _ := syscall.Syscall6(procSubscribeServiceChangeNotifications.Addr(), 5, uintptr(service), uintptr(eventType), uintptr(callback), uintptr(callbackCtx), uintptr(unsafe.Pointer(subscription)), 0) + r0, _, _ := syscall.SyscallN(procSubscribeServiceChangeNotifications.Addr(), uintptr(service), uintptr(eventType), uintptr(callback), uintptr(callbackCtx), uintptr(unsafe.Pointer(subscription))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -3874,12 +3929,12 @@ func UnsubscribeServiceChangeNotifications(subscription uintptr) (err error) { if err != nil { return } - syscall.Syscall(procUnsubscribeServiceChangeNotifications.Addr(), 1, uintptr(subscription), 0, 0) + syscall.SyscallN(procUnsubscribeServiceChangeNotifications.Addr(), uintptr(subscription)) return } func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) + r1, _, e1 := syscall.SyscallN(procGetUserNameExW.Addr(), uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) if r1&0xff == 0 { err = errnoErr(e1) } @@ -3887,7 +3942,7 @@ func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err er } func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) + r1, _, e1 := syscall.SyscallN(procTranslateNameW.Addr(), uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize))) if r1&0xff == 0 { err = errnoErr(e1) } @@ -3895,7 +3950,7 @@ func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint } func SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiBuildDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) + r1, _, e1 := syscall.SyscallN(procSetupDiBuildDriverInfoList.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) if r1 == 0 { err = errnoErr(e1) } @@ -3903,7 +3958,7 @@ func SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoDa } func SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiCallClassInstaller.Addr(), 3, uintptr(installFunction), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) + r1, _, e1 := syscall.SyscallN(procSetupDiCallClassInstaller.Addr(), uintptr(installFunction), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -3911,7 +3966,7 @@ func SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInf } func SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiCancelDriverInfoSearch.Addr(), 1, uintptr(deviceInfoSet), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetupDiCancelDriverInfoSearch.Addr(), uintptr(deviceInfoSet)) if r1 == 0 { err = errnoErr(e1) } @@ -3919,7 +3974,7 @@ func SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) { } func setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiClassGuidsFromNameExW.Addr(), 6, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(classGuidList)), uintptr(classGuidListSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + r1, _, e1 := syscall.SyscallN(procSetupDiClassGuidsFromNameExW.Addr(), uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(classGuidList)), uintptr(classGuidListSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) if r1 == 0 { err = errnoErr(e1) } @@ -3927,7 +3982,7 @@ func setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGu } func setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiClassNameFromGuidExW.Addr(), 6, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(className)), uintptr(classNameSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + r1, _, e1 := syscall.SyscallN(procSetupDiClassNameFromGuidExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(className)), uintptr(classNameSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) if r1 == 0 { err = errnoErr(e1) } @@ -3935,7 +3990,7 @@ func setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSiz } func setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { - r0, _, e1 := syscall.Syscall6(procSetupDiCreateDeviceInfoListExW.Addr(), 4, uintptr(unsafe.Pointer(classGUID)), uintptr(hwndParent), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0) + r0, _, e1 := syscall.SyscallN(procSetupDiCreateDeviceInfoListExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(hwndParent), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) handle = DevInfo(r0) if handle == DevInfo(InvalidHandle) { err = errnoErr(e1) @@ -3944,7 +3999,7 @@ func setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineN } func setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) { - r1, _, e1 := syscall.Syscall9(procSetupDiCreateDeviceInfoW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(DeviceName)), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(DeviceDescription)), uintptr(hwndParent), uintptr(CreationFlags), uintptr(unsafe.Pointer(deviceInfoData)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetupDiCreateDeviceInfoW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(DeviceName)), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(DeviceDescription)), uintptr(hwndParent), uintptr(CreationFlags), uintptr(unsafe.Pointer(deviceInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -3952,7 +4007,7 @@ func setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUI } func SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiDestroyDeviceInfoList.Addr(), 1, uintptr(deviceInfoSet), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetupDiDestroyDeviceInfoList.Addr(), uintptr(deviceInfoSet)) if r1 == 0 { err = errnoErr(e1) } @@ -3960,7 +4015,7 @@ func SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) { } func SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiDestroyDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) + r1, _, e1 := syscall.SyscallN(procSetupDiDestroyDriverInfoList.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) if r1 == 0 { err = errnoErr(e1) } @@ -3968,7 +4023,7 @@ func SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfo } func setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiEnumDeviceInfo.Addr(), 3, uintptr(deviceInfoSet), uintptr(memberIndex), uintptr(unsafe.Pointer(deviceInfoData))) + r1, _, e1 := syscall.SyscallN(procSetupDiEnumDeviceInfo.Addr(), uintptr(deviceInfoSet), uintptr(memberIndex), uintptr(unsafe.Pointer(deviceInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -3976,7 +4031,7 @@ func setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfo } func setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiEnumDriverInfoW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType), uintptr(memberIndex), uintptr(unsafe.Pointer(driverInfoData)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiEnumDriverInfoW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType), uintptr(memberIndex), uintptr(unsafe.Pointer(driverInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -3984,7 +4039,7 @@ func setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, d } func setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { - r0, _, e1 := syscall.Syscall9(procSetupDiGetClassDevsExW.Addr(), 7, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(Enumerator)), uintptr(hwndParent), uintptr(Flags), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0) + r0, _, e1 := syscall.SyscallN(procSetupDiGetClassDevsExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(Enumerator)), uintptr(hwndParent), uintptr(Flags), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) handle = DevInfo(r0) if handle == DevInfo(InvalidHandle) { err = errnoErr(e1) @@ -3993,7 +4048,7 @@ func setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintp } func SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiGetClassInstallParamsW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), uintptr(unsafe.Pointer(requiredSize)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetClassInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), uintptr(unsafe.Pointer(requiredSize))) if r1 == 0 { err = errnoErr(e1) } @@ -4001,7 +4056,7 @@ func SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfo } func setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInfoListDetailW.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoSetDetailData)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInfoListDetailW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoSetDetailData))) if r1 == 0 { err = errnoErr(e1) } @@ -4009,7 +4064,7 @@ func setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailDa } func setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInstallParamsW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) if r1 == 0 { err = errnoErr(e1) } @@ -4017,7 +4072,7 @@ func setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInf } func setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiGetDeviceInstanceIdW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(instanceId)), uintptr(instanceIdSize), uintptr(unsafe.Pointer(instanceIdRequiredSize)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInstanceIdW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(instanceId)), uintptr(instanceIdSize), uintptr(unsafe.Pointer(instanceIdRequiredSize))) if r1 == 0 { err = errnoErr(e1) } @@ -4025,7 +4080,7 @@ func setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoDa } func setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procSetupDiGetDevicePropertyW.Addr(), 8, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(propertyKey)), uintptr(unsafe.Pointer(propertyType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDevicePropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(propertyKey)), uintptr(unsafe.Pointer(propertyType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } @@ -4033,7 +4088,7 @@ func setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData } func setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procSetupDiGetDeviceRegistryPropertyW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyRegDataType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceRegistryPropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyRegDataType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize))) if r1 == 0 { err = errnoErr(e1) } @@ -4041,7 +4096,7 @@ func setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *Dev } func setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiGetDriverInfoDetailW.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)), uintptr(unsafe.Pointer(driverInfoDetailData)), uintptr(driverInfoDetailDataSize), uintptr(unsafe.Pointer(requiredSize))) + r1, _, e1 := syscall.SyscallN(procSetupDiGetDriverInfoDetailW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)), uintptr(unsafe.Pointer(driverInfoDetailData)), uintptr(driverInfoDetailDataSize), uintptr(unsafe.Pointer(requiredSize))) if r1 == 0 { err = errnoErr(e1) } @@ -4049,7 +4104,7 @@ func setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoDa } func setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDevice.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiGetSelectedDevice.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -4057,7 +4112,7 @@ func setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData } func setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + r1, _, e1 := syscall.SyscallN(procSetupDiGetSelectedDriverW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -4065,7 +4120,7 @@ func setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData } func SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) { - r0, _, e1 := syscall.Syscall6(procSetupDiOpenDevRegKey.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(Scope), uintptr(HwProfile), uintptr(KeyType), uintptr(samDesired)) + r0, _, e1 := syscall.SyscallN(procSetupDiOpenDevRegKey.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(Scope), uintptr(HwProfile), uintptr(KeyType), uintptr(samDesired)) key = Handle(r0) if key == InvalidHandle { err = errnoErr(e1) @@ -4074,7 +4129,7 @@ func SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Sc } func SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiSetClassInstallParamsW.Addr(), 4, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), 0, 0) + r1, _, e1 := syscall.SyscallN(procSetupDiSetClassInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize)) if r1 == 0 { err = errnoErr(e1) } @@ -4082,7 +4137,7 @@ func SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfo } func SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiSetDeviceInstallParamsW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + r1, _, e1 := syscall.SyscallN(procSetupDiSetDeviceInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) if r1 == 0 { err = errnoErr(e1) } @@ -4090,7 +4145,7 @@ func SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInf } func setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetupDiSetDeviceRegistryPropertyW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiSetDeviceRegistryPropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize)) if r1 == 0 { err = errnoErr(e1) } @@ -4098,7 +4153,7 @@ func setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *Dev } func SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDevice.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), 0) + r1, _, e1 := syscall.SyscallN(procSetupDiSetSelectedDevice.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -4106,7 +4161,7 @@ func SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData } func SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { - r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + r1, _, e1 := syscall.SyscallN(procSetupDiSetSelectedDriverW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) if r1 == 0 { err = errnoErr(e1) } @@ -4114,7 +4169,7 @@ func SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData } func setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procSetupUninstallOEMInfW.Addr(), 3, uintptr(unsafe.Pointer(infFileName)), uintptr(flags), uintptr(reserved)) + r1, _, e1 := syscall.SyscallN(procSetupUninstallOEMInfW.Addr(), uintptr(unsafe.Pointer(infFileName)), uintptr(flags), uintptr(reserved)) if r1 == 0 { err = errnoErr(e1) } @@ -4122,7 +4177,7 @@ func setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (er } func commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) { - r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) + r0, _, e1 := syscall.SyscallN(procCommandLineToArgvW.Addr(), uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc))) argv = (**uint16)(unsafe.Pointer(r0)) if argv == nil { err = errnoErr(e1) @@ -4131,7 +4186,7 @@ func commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) { } func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) { - r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path)), 0, 0) + r0, _, _ := syscall.SyscallN(procSHGetKnownFolderPath.Addr(), uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -4139,7 +4194,7 @@ func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **u } func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { - r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) + r1, _, e1 := syscall.SyscallN(procShellExecuteW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) if r1 <= 32 { err = errnoErr(e1) } @@ -4147,12 +4202,12 @@ func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *ui } func EnumChildWindows(hwnd HWND, enumFunc uintptr, param unsafe.Pointer) { - syscall.Syscall(procEnumChildWindows.Addr(), 3, uintptr(hwnd), uintptr(enumFunc), uintptr(param)) + syscall.SyscallN(procEnumChildWindows.Addr(), uintptr(hwnd), uintptr(enumFunc), uintptr(param)) return } func EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) { - r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(param), 0) + r1, _, e1 := syscall.SyscallN(procEnumWindows.Addr(), uintptr(enumFunc), uintptr(param)) if r1 == 0 { err = errnoErr(e1) } @@ -4160,7 +4215,7 @@ func EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) { } func ExitWindowsEx(flags uint32, reason uint32) (err error) { - r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) + r1, _, e1 := syscall.SyscallN(procExitWindowsEx.Addr(), uintptr(flags), uintptr(reason)) if r1 == 0 { err = errnoErr(e1) } @@ -4168,7 +4223,7 @@ func ExitWindowsEx(flags uint32, reason uint32) (err error) { } func GetClassName(hwnd HWND, className *uint16, maxCount int32) (copied int32, err error) { - r0, _, e1 := syscall.Syscall(procGetClassNameW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(className)), uintptr(maxCount)) + r0, _, e1 := syscall.SyscallN(procGetClassNameW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(className)), uintptr(maxCount)) copied = int32(r0) if copied == 0 { err = errnoErr(e1) @@ -4177,19 +4232,19 @@ func GetClassName(hwnd HWND, className *uint16, maxCount int32) (copied int32, e } func GetDesktopWindow() (hwnd HWND) { - r0, _, _ := syscall.Syscall(procGetDesktopWindow.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetDesktopWindow.Addr()) hwnd = HWND(r0) return } func GetForegroundWindow() (hwnd HWND) { - r0, _, _ := syscall.Syscall(procGetForegroundWindow.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetForegroundWindow.Addr()) hwnd = HWND(r0) return } func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetGUIThreadInfo.Addr(), 2, uintptr(thread), uintptr(unsafe.Pointer(info)), 0) + r1, _, e1 := syscall.SyscallN(procGetGUIThreadInfo.Addr(), uintptr(thread), uintptr(unsafe.Pointer(info))) if r1 == 0 { err = errnoErr(e1) } @@ -4197,19 +4252,19 @@ func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { } func GetKeyboardLayout(tid uint32) (hkl Handle) { - r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(tid), 0, 0) + r0, _, _ := syscall.SyscallN(procGetKeyboardLayout.Addr(), uintptr(tid)) hkl = Handle(r0) return } func GetShellWindow() (shellWindow HWND) { - r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0) + r0, _, _ := syscall.SyscallN(procGetShellWindow.Addr()) shellWindow = HWND(r0) return } func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetWindowThreadProcessId.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(pid)), 0) + r0, _, e1 := syscall.SyscallN(procGetWindowThreadProcessId.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(pid))) tid = uint32(r0) if tid == 0 { err = errnoErr(e1) @@ -4218,25 +4273,25 @@ func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) { } func IsWindow(hwnd HWND) (isWindow bool) { - r0, _, _ := syscall.Syscall(procIsWindow.Addr(), 1, uintptr(hwnd), 0, 0) + r0, _, _ := syscall.SyscallN(procIsWindow.Addr(), uintptr(hwnd)) isWindow = r0 != 0 return } func IsWindowUnicode(hwnd HWND) (isUnicode bool) { - r0, _, _ := syscall.Syscall(procIsWindowUnicode.Addr(), 1, uintptr(hwnd), 0, 0) + r0, _, _ := syscall.SyscallN(procIsWindowUnicode.Addr(), uintptr(hwnd)) isUnicode = r0 != 0 return } func IsWindowVisible(hwnd HWND) (isVisible bool) { - r0, _, _ := syscall.Syscall(procIsWindowVisible.Addr(), 1, uintptr(hwnd), 0, 0) + r0, _, _ := syscall.SyscallN(procIsWindowVisible.Addr(), uintptr(hwnd)) isVisible = r0 != 0 return } func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) + r0, _, e1 := syscall.SyscallN(procLoadKeyboardLayoutW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags)) hkl = Handle(r0) if hkl == 0 { err = errnoErr(e1) @@ -4245,7 +4300,7 @@ func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { } func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { - r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) + r0, _, e1 := syscall.SyscallN(procMessageBoxW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype)) ret = int32(r0) if ret == 0 { err = errnoErr(e1) @@ -4254,13 +4309,13 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i } func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { - r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl), 0, 0) + r0, _, _ := syscall.SyscallN(procToUnicodeEx.Addr(), uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl)) ret = int32(r0) return } func UnloadKeyboardLayout(hkl Handle) (err error) { - r1, _, e1 := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) + r1, _, e1 := syscall.SyscallN(procUnloadKeyboardLayout.Addr(), uintptr(hkl)) if r1 == 0 { err = errnoErr(e1) } @@ -4272,7 +4327,7 @@ func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) ( if inheritExisting { _p0 = 1 } - r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) + r1, _, e1 := syscall.SyscallN(procCreateEnvironmentBlock.Addr(), uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) if r1 == 0 { err = errnoErr(e1) } @@ -4280,7 +4335,7 @@ func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) ( } func DestroyEnvironmentBlock(block *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) + r1, _, e1 := syscall.SyscallN(procDestroyEnvironmentBlock.Addr(), uintptr(unsafe.Pointer(block))) if r1 == 0 { err = errnoErr(e1) } @@ -4288,7 +4343,7 @@ func DestroyEnvironmentBlock(block *uint16) (err error) { } func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) + r1, _, e1 := syscall.SyscallN(procGetUserProfileDirectoryW.Addr(), uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) if r1 == 0 { err = errnoErr(e1) } @@ -4305,7 +4360,7 @@ func GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32 } func _GetFileVersionInfoSize(filename *uint16, zeroHandle *Handle) (bufSize uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileVersionInfoSizeW.Addr(), 2, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zeroHandle)), 0) + r0, _, e1 := syscall.SyscallN(procGetFileVersionInfoSizeW.Addr(), uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zeroHandle))) bufSize = uint32(r0) if bufSize == 0 { err = errnoErr(e1) @@ -4323,7 +4378,7 @@ func GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer u } func _GetFileVersionInfo(filename *uint16, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileVersionInfoW.Addr(), 4, uintptr(unsafe.Pointer(filename)), uintptr(handle), uintptr(bufSize), uintptr(buffer), 0, 0) + r1, _, e1 := syscall.SyscallN(procGetFileVersionInfoW.Addr(), uintptr(unsafe.Pointer(filename)), uintptr(handle), uintptr(bufSize), uintptr(buffer)) if r1 == 0 { err = errnoErr(e1) } @@ -4340,7 +4395,7 @@ func VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer } func _VerQueryValue(block unsafe.Pointer, subBlock *uint16, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(block), uintptr(unsafe.Pointer(subBlock)), uintptr(pointerToBufferPointer), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.SyscallN(procVerQueryValueW.Addr(), uintptr(block), uintptr(unsafe.Pointer(subBlock)), uintptr(pointerToBufferPointer), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { err = errnoErr(e1) } @@ -4348,7 +4403,7 @@ func _VerQueryValue(block unsafe.Pointer, subBlock *uint16, pointerToBufferPoint } func TimeBeginPeriod(period uint32) (err error) { - r1, _, e1 := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0) + r1, _, e1 := syscall.SyscallN(proctimeBeginPeriod.Addr(), uintptr(period)) if r1 != 0 { err = errnoErr(e1) } @@ -4356,7 +4411,7 @@ func TimeBeginPeriod(period uint32) (err error) { } func TimeEndPeriod(period uint32) (err error) { - r1, _, e1 := syscall.Syscall(proctimeEndPeriod.Addr(), 1, uintptr(period), 0, 0) + r1, _, e1 := syscall.SyscallN(proctimeEndPeriod.Addr(), uintptr(period)) if r1 != 0 { err = errnoErr(e1) } @@ -4364,7 +4419,7 @@ func TimeEndPeriod(period uint32) (err error) { } func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) { - r0, _, _ := syscall.Syscall(procWinVerifyTrustEx.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data))) + r0, _, _ := syscall.SyscallN(procWinVerifyTrustEx.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data))) if r0 != 0 { ret = syscall.Errno(r0) } @@ -4372,12 +4427,12 @@ func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) } func FreeAddrInfoW(addrinfo *AddrinfoW) { - syscall.Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) + syscall.SyscallN(procFreeAddrInfoW.Addr(), uintptr(unsafe.Pointer(addrinfo))) return } func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { - r0, _, _ := syscall.Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) + r0, _, _ := syscall.SyscallN(procGetAddrInfoW.Addr(), uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result))) if r0 != 0 { sockerr = syscall.Errno(r0) } @@ -4385,7 +4440,7 @@ func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, resul } func WSACleanup() (err error) { - r1, _, e1 := syscall.Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) + r1, _, e1 := syscall.SyscallN(procWSACleanup.Addr()) if r1 == socket_error { err = errnoErr(e1) } @@ -4393,7 +4448,7 @@ func WSACleanup() (err error) { } func WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err error) { - r1, _, e1 := syscall.Syscall(procWSADuplicateSocketW.Addr(), 3, uintptr(s), uintptr(processID), uintptr(unsafe.Pointer(info))) + r1, _, e1 := syscall.SyscallN(procWSADuplicateSocketW.Addr(), uintptr(s), uintptr(processID), uintptr(unsafe.Pointer(info))) if r1 != 0 { err = errnoErr(e1) } @@ -4401,7 +4456,7 @@ func WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err } func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { - r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) + r0, _, e1 := syscall.SyscallN(procWSAEnumProtocolsW.Addr(), uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) n = int32(r0) if n == -1 { err = errnoErr(e1) @@ -4414,7 +4469,7 @@ func WSAGetOverlappedResult(h Handle, o *Overlapped, bytes *uint32, wait bool, f if wait { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + r1, _, e1 := syscall.SyscallN(procWSAGetOverlappedResult.Addr(), uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags))) if r1 == 0 { err = errnoErr(e1) } @@ -4422,7 +4477,7 @@ func WSAGetOverlappedResult(h Handle, o *Overlapped, bytes *uint32, wait bool, f } func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) + r1, _, e1 := syscall.SyscallN(procWSAIoctl.Addr(), uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) if r1 == socket_error { err = errnoErr(e1) } @@ -4430,7 +4485,7 @@ func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbo } func WSALookupServiceBegin(querySet *WSAQUERYSET, flags uint32, handle *Handle) (err error) { - r1, _, e1 := syscall.Syscall(procWSALookupServiceBeginW.Addr(), 3, uintptr(unsafe.Pointer(querySet)), uintptr(flags), uintptr(unsafe.Pointer(handle))) + r1, _, e1 := syscall.SyscallN(procWSALookupServiceBeginW.Addr(), uintptr(unsafe.Pointer(querySet)), uintptr(flags), uintptr(unsafe.Pointer(handle))) if r1 == socket_error { err = errnoErr(e1) } @@ -4438,7 +4493,7 @@ func WSALookupServiceBegin(querySet *WSAQUERYSET, flags uint32, handle *Handle) } func WSALookupServiceEnd(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procWSALookupServiceEnd.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procWSALookupServiceEnd.Addr(), uintptr(handle)) if r1 == socket_error { err = errnoErr(e1) } @@ -4446,7 +4501,7 @@ func WSALookupServiceEnd(handle Handle) (err error) { } func WSALookupServiceNext(handle Handle, flags uint32, size *int32, querySet *WSAQUERYSET) (err error) { - r1, _, e1 := syscall.Syscall6(procWSALookupServiceNextW.Addr(), 4, uintptr(handle), uintptr(flags), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(querySet)), 0, 0) + r1, _, e1 := syscall.SyscallN(procWSALookupServiceNextW.Addr(), uintptr(handle), uintptr(flags), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(querySet))) if r1 == socket_error { err = errnoErr(e1) } @@ -4454,7 +4509,7 @@ func WSALookupServiceNext(handle Handle, flags uint32, size *int32, querySet *WS } func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + r1, _, e1 := syscall.SyscallN(procWSARecv.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { err = errnoErr(e1) } @@ -4462,7 +4517,7 @@ func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32 } func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + r1, _, e1 := syscall.SyscallN(procWSARecvFrom.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { err = errnoErr(e1) } @@ -4470,7 +4525,7 @@ func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *ui } func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + r1, _, e1 := syscall.SyscallN(procWSASend.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { err = errnoErr(e1) } @@ -4478,7 +4533,7 @@ func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, } func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + r1, _, e1 := syscall.SyscallN(procWSASendTo.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { err = errnoErr(e1) } @@ -4486,7 +4541,7 @@ func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32 } func WSASocket(af int32, typ int32, protocol int32, protoInfo *WSAProtocolInfo, group uint32, flags uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protoInfo)), uintptr(group), uintptr(flags)) + r0, _, e1 := syscall.SyscallN(procWSASocketW.Addr(), uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protoInfo)), uintptr(group), uintptr(flags)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -4495,7 +4550,7 @@ func WSASocket(af int32, typ int32, protocol int32, protoInfo *WSAProtocolInfo, } func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { - r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) + r0, _, _ := syscall.SyscallN(procWSAStartup.Addr(), uintptr(verreq), uintptr(unsafe.Pointer(data))) if r0 != 0 { sockerr = syscall.Errno(r0) } @@ -4503,7 +4558,7 @@ func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { } func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + r1, _, e1 := syscall.SyscallN(procbind.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) if r1 == socket_error { err = errnoErr(e1) } @@ -4511,7 +4566,7 @@ func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { } func Closesocket(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) + r1, _, e1 := syscall.SyscallN(procclosesocket.Addr(), uintptr(s)) if r1 == socket_error { err = errnoErr(e1) } @@ -4519,7 +4574,7 @@ func Closesocket(s Handle) (err error) { } func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + r1, _, e1 := syscall.SyscallN(procconnect.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) if r1 == socket_error { err = errnoErr(e1) } @@ -4536,7 +4591,7 @@ func GetHostByName(name string) (h *Hostent, err error) { } func _GetHostByName(name *byte) (h *Hostent, err error) { - r0, _, e1 := syscall.Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + r0, _, e1 := syscall.SyscallN(procgethostbyname.Addr(), uintptr(unsafe.Pointer(name))) h = (*Hostent)(unsafe.Pointer(r0)) if h == nil { err = errnoErr(e1) @@ -4545,7 +4600,7 @@ func _GetHostByName(name *byte) (h *Hostent, err error) { } func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r1, _, e1 := syscall.SyscallN(procgetpeername.Addr(), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if r1 == socket_error { err = errnoErr(e1) } @@ -4562,7 +4617,7 @@ func GetProtoByName(name string) (p *Protoent, err error) { } func _GetProtoByName(name *byte) (p *Protoent, err error) { - r0, _, e1 := syscall.Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + r0, _, e1 := syscall.SyscallN(procgetprotobyname.Addr(), uintptr(unsafe.Pointer(name))) p = (*Protoent)(unsafe.Pointer(r0)) if p == nil { err = errnoErr(e1) @@ -4585,7 +4640,7 @@ func GetServByName(name string, proto string) (s *Servent, err error) { } func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { - r0, _, e1 := syscall.Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) + r0, _, e1 := syscall.SyscallN(procgetservbyname.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto))) s = (*Servent)(unsafe.Pointer(r0)) if s == nil { err = errnoErr(e1) @@ -4594,7 +4649,7 @@ func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { } func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r1, _, e1 := syscall.SyscallN(procgetsockname.Addr(), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if r1 == socket_error { err = errnoErr(e1) } @@ -4602,7 +4657,7 @@ func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { } func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { - r1, _, e1 := syscall.Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) + r1, _, e1 := syscall.SyscallN(procgetsockopt.Addr(), uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen))) if r1 == socket_error { err = errnoErr(e1) } @@ -4610,7 +4665,7 @@ func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int3 } func listen(s Handle, backlog int32) (err error) { - r1, _, e1 := syscall.Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) + r1, _, e1 := syscall.SyscallN(proclisten.Addr(), uintptr(s), uintptr(backlog)) if r1 == socket_error { err = errnoErr(e1) } @@ -4618,7 +4673,7 @@ func listen(s Handle, backlog int32) (err error) { } func Ntohs(netshort uint16) (u uint16) { - r0, _, _ := syscall.Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) + r0, _, _ := syscall.SyscallN(procntohs.Addr(), uintptr(netshort)) u = uint16(r0) return } @@ -4628,7 +4683,7 @@ func recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen * if len(buf) > 0 { _p0 = &buf[0] } - r0, _, e1 := syscall.Syscall6(procrecvfrom.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall.SyscallN(procrecvfrom.Addr(), uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int32(r0) if n == -1 { err = errnoErr(e1) @@ -4641,7 +4696,7 @@ func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) ( if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall6(procsendto.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) + r1, _, e1 := syscall.SyscallN(procsendto.Addr(), uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) if r1 == socket_error { err = errnoErr(e1) } @@ -4649,7 +4704,7 @@ func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) ( } func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { - r1, _, e1 := syscall.Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) + r1, _, e1 := syscall.SyscallN(procsetsockopt.Addr(), uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen)) if r1 == socket_error { err = errnoErr(e1) } @@ -4657,7 +4712,7 @@ func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32 } func shutdown(s Handle, how int32) (err error) { - r1, _, e1 := syscall.Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) + r1, _, e1 := syscall.SyscallN(procshutdown.Addr(), uintptr(s), uintptr(how)) if r1 == socket_error { err = errnoErr(e1) } @@ -4665,7 +4720,7 @@ func shutdown(s Handle, how int32) (err error) { } func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) + r0, _, e1 := syscall.SyscallN(procsocket.Addr(), uintptr(af), uintptr(typ), uintptr(protocol)) handle = Handle(r0) if handle == InvalidHandle { err = errnoErr(e1) @@ -4674,7 +4729,7 @@ func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { } func WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procWTSEnumerateSessionsW.Addr(), 5, uintptr(handle), uintptr(reserved), uintptr(version), uintptr(unsafe.Pointer(sessions)), uintptr(unsafe.Pointer(count)), 0) + r1, _, e1 := syscall.SyscallN(procWTSEnumerateSessionsW.Addr(), uintptr(handle), uintptr(reserved), uintptr(version), uintptr(unsafe.Pointer(sessions)), uintptr(unsafe.Pointer(count))) if r1 == 0 { err = errnoErr(e1) } @@ -4682,12 +4737,12 @@ func WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessio } func WTSFreeMemory(ptr uintptr) { - syscall.Syscall(procWTSFreeMemory.Addr(), 1, uintptr(ptr), 0, 0) + syscall.SyscallN(procWTSFreeMemory.Addr(), uintptr(ptr)) return } func WTSQueryUserToken(session uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) + r1, _, e1 := syscall.SyscallN(procWTSQueryUserToken.Addr(), uintptr(session), uintptr(unsafe.Pointer(token))) if r1 == 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/tools/PATENTS b/vendor/golang.org/x/tools/PATENTS deleted file mode 100644 index 73309904..00000000 --- a/vendor/golang.org/x/tools/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/tools/LICENSE b/vendor/golang.org/x/tools/godoc/LICENSE similarity index 100% rename from vendor/golang.org/x/tools/LICENSE rename to vendor/golang.org/x/tools/godoc/LICENSE diff --git a/vendor/modules.txt b/vendor/modules.txt index e677129e..f2a1c645 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -246,8 +246,8 @@ go.uber.org/atomic # go.uber.org/multierr v1.9.0 ## explicit; go 1.19 go.uber.org/multierr -# golang.org/x/crypto v0.41.0 -## explicit; go 1.23.0 +# golang.org/x/crypto v0.45.0 +## explicit; go 1.24.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 @@ -256,12 +256,12 @@ golang.org/x/crypto/scrypt ## explicit; go 1.24.0 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sys v0.35.0 -## explicit; go 1.23.0 +# golang.org/x/sys v0.38.0 +## explicit; go 1.24.0 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/text v0.28.0 -## explicit; go 1.23.0 +# golang.org/x/text v0.31.0 +## explicit; go 1.24.0 golang.org/x/text/encoding golang.org/x/text/encoding/internal golang.org/x/text/encoding/internal/identifier @@ -270,8 +270,8 @@ golang.org/x/text/internal/utf8internal golang.org/x/text/runes golang.org/x/text/transform golang.org/x/text/unicode/norm -# golang.org/x/tools v0.36.0 -## explicit; go 1.23.0 +# golang.org/x/tools/godoc v0.1.0-deprecated +## explicit; go 1.24.0 golang.org/x/tools/godoc/util golang.org/x/tools/godoc/vfs # gopkg.in/yaml.v2 v2.4.0 From 0b99f043d9461316f4de06957c51fdd40a8a5505 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:14:20 +0100 Subject: [PATCH 35/35] chore(deps): bump actions/setup-python from 6.0.0 to 6.1.0 (#196) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.0.0 to 6.1.0.
Release notes

Sourced from actions/setup-python's releases.

v6.1.0

What's Changed

Enhancements:

Dependency and Documentation updates:

New Contributors

Full Changelog: https://github.com/actions/setup-python/compare/v6...v6.1.0

Commits
  • 83679a8 Bump @​types/node from 24.1.0 to 24.9.1 and update macos-13 to macos-15-intel ...
  • bfc4944 Bump prettier from 3.5.3 to 3.6.2 (#1234)
  • 97aeb3e Bump requests from 2.32.2 to 2.32.4 in /tests/data (#1130)
  • 443da59 Bump actions/publish-action from 0.3.0 to 0.4.0 & Documentation update for pi...
  • cfd55ca graalpy: add graalpy early-access and windows builds (#880)
  • bba65e5 Bump typescript from 5.4.2 to 5.9.3 and update docs/advanced-usage.md (#1094)
  • 18566f8 Improve wording and "fix example" (remove 3.13) on testing against pre-releas...
  • 2e3e4b1 Add support for pip-install input (#1201)
  • 4267e28 Bump urllib3 from 1.26.19 to 2.5.0 in /tests/data and document breaking c...
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=6.0.0&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ed6b62d..c33fc679 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: run: npm install -g @datadog/datadog-ci - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 with: python-version: '3.x' @@ -121,7 +121,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 with: python-version: '3.x'